[
  {
    "path": ".config/dotnet-tools.json",
    "content": "{\n  \"version\": 1,\n  \"isRoot\": true,\n  \"tools\": {\n    \"microsoft.extensions.ai.evaluation.console\": {\n      \"version\": \"9.3.0-preview.1.25126.9\",\n      \"commands\": [\n        \"aieval\"\n      ],\n      \"rollForward\": false\n    }\n  }\n}"
  },
  {
    "path": ".editorconfig",
    "content": "###############################\n# Core EditorConfig Options   #\n###############################\nroot = true\n# All files\n[*]\nindent_style = space\n\n# XML project files\n[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}]\nindent_size = 2\n\n# XML config files\n[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}]\nindent_size = 2\n\n# Code files\n[*.{cs,csx,vb,vbx}]\nindent_size = 4\ninsert_final_newline = true\ncharset = utf-8-bom\n###############################\n# .NET Coding Conventions     #\n###############################\n[*.{cs,vb}]\n# Organize usings\ndotnet_sort_system_directives_first = true\n# this. preferences\ndotnet_style_qualification_for_field = false:silent\ndotnet_style_qualification_for_property = false:silent\ndotnet_style_qualification_for_method = false:silent\ndotnet_style_qualification_for_event = false:silent\n# Language keywords vs BCL types preferences\ndotnet_style_predefined_type_for_locals_parameters_members = true:silent\ndotnet_style_predefined_type_for_member_access = true:silent\n# Parentheses preferences\ndotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent\ndotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent\ndotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent\ndotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent\n# Modifier preferences\ndotnet_style_require_accessibility_modifiers = for_non_interface_members:silent\ndotnet_style_readonly_field = true:suggestion\n# Expression-level preferences\ndotnet_style_object_initializer = true:suggestion\ndotnet_style_collection_initializer = true:suggestion\ndotnet_style_explicit_tuple_names = true:suggestion\ndotnet_style_null_propagation = true:suggestion\ndotnet_style_coalesce_expression = true:suggestion\ndotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent\ndotnet_style_prefer_inferred_tuple_names = true:suggestion\ndotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion\ndotnet_style_prefer_auto_properties = true:silent\ndotnet_style_prefer_conditional_expression_over_assignment = true:silent\ndotnet_style_prefer_conditional_expression_over_return = true:silent\n###############################\n# Naming Conventions          #\n###############################\n# Style Definitions\ndotnet_naming_style.pascal_case_style.capitalization             = pascal_case\n# Use PascalCase for constant fields\ndotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion\ndotnet_naming_rule.constant_fields_should_be_pascal_case.symbols  = constant_fields\ndotnet_naming_rule.constant_fields_should_be_pascal_case.style    = pascal_case_style\ndotnet_naming_symbols.constant_fields.applicable_kinds            = field\ndotnet_naming_symbols.constant_fields.applicable_accessibilities  = *\ndotnet_naming_symbols.constant_fields.required_modifiers          = const\n###############################\n# C# Coding Conventions       #\n###############################\n[*.cs]\n# var preferences\ncsharp_style_var_for_built_in_types = true:silent\ncsharp_style_var_when_type_is_apparent = true:silent\ncsharp_style_var_elsewhere = true:silent\n# Expression-bodied members\ncsharp_style_expression_bodied_methods = false:silent\ncsharp_style_expression_bodied_constructors = false:silent\ncsharp_style_expression_bodied_operators = false:silent\ncsharp_style_expression_bodied_properties = true:silent\ncsharp_style_expression_bodied_indexers = true:silent\ncsharp_style_expression_bodied_accessors = true:silent\n# Pattern matching preferences\ncsharp_style_pattern_matching_over_is_with_cast_check = true:suggestion\ncsharp_style_pattern_matching_over_as_with_null_check = true:suggestion\n# Null-checking preferences\ncsharp_style_throw_expression = true:suggestion\ncsharp_style_conditional_delegate_call = true:suggestion\n# Modifier preferences\ncsharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion\n# Expression-level preferences\ncsharp_prefer_braces = true:silent\ncsharp_style_deconstructed_variable_declaration = true:suggestion\ncsharp_prefer_simple_default_expression = true:suggestion\ncsharp_style_prefer_local_over_anonymous_function = true:suggestion\ncsharp_style_inlined_variable_declaration = true:suggestion\n###############################\n# C# Formatting Rules         #\n###############################\n# New line preferences\ncsharp_new_line_before_open_brace = all\ncsharp_new_line_before_else = true\ncsharp_new_line_before_catch = true\ncsharp_new_line_before_finally = true\ncsharp_new_line_before_members_in_object_initializers = true\ncsharp_new_line_before_members_in_anonymous_types = true\ncsharp_new_line_between_query_expression_clauses = true\n# Indentation preferences\ncsharp_indent_case_contents = true\ncsharp_indent_switch_labels = true\ncsharp_indent_labels = flush_left\n# Space preferences\ncsharp_space_after_cast = false\ncsharp_space_after_keywords_in_control_flow_statements = true\ncsharp_space_between_method_call_parameter_list_parentheses = false\ncsharp_space_between_method_declaration_parameter_list_parentheses = false\ncsharp_space_between_parentheses = false\ncsharp_space_before_colon_in_inheritance_clause = true\ncsharp_space_after_colon_in_inheritance_clause = true\ncsharp_space_around_binary_operators = before_and_after\ncsharp_space_between_method_declaration_empty_parameter_list_parentheses = false\ncsharp_space_between_method_call_name_and_opening_parenthesis = false\ncsharp_space_between_method_call_empty_parameter_list_parentheses = false\n# Wrapping preferences\ncsharp_preserve_single_line_statements = true\ncsharp_preserve_single_line_blocks = true\n###############################\n# VB Coding Conventions       #\n###############################\n[*.vb]\n# Modifier preferences\nvisual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion"
  },
  {
    "path": ".gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n##\n## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore\n\n# User-specific files\n*.rsuser\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Mono auto generated files\nmono_crash.*\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\n[Ww][Ii][Nn]32/\n[Aa][Rr][Mm]/\n[Aa][Rr][Mm]64/\nbld/\n[Bb]in/\n[Oo]bj/\n[Ll]og/\n[Ll]ogs/\n\n# Visual Studio 2015/2017 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# Visual Studio 2017 auto generated files\nGenerated\\ Files/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUnit\n*.VisualState.xml\nTestResult.xml\nnunit-*.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# Benchmark Results\nBenchmarkDotNet.Artifacts/\n\n# .NET Core\nproject.lock.json\nproject.fragment.lock.json\nartifacts/\n\n# ASP.NET Scaffolding\nScaffoldingReadMe.txt\n\n# StyleCop\nStyleCopReport.xml\n\n# Files built by Visual Studio\n*_i.c\n*_p.c\n*_h.h\n*.ilk\n*.meta\n*.obj\n*.iobj\n*.pch\n*.pdb\n*.ipdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*_wpftmp.csproj\n*.log\n*.tlog\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n*.VC.db\n*.VC.VC.opendb\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# Visual Studio Trace Files\n*.e2e\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# AxoCover is a Code Coverage Tool\n.axoCover/*\n!.axoCover/settings.json\n\n# Coverlet is a free, cross platform Code Coverage Tool\ncoverage*.json\ncoverage*.xml\ncoverage*.info\n\n# Visual Studio code coverage results\n*.coverage\n*.coveragexml\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# Note: Comment the next line if you want to checkin your web deploy settings,\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# Microsoft Azure Web App publish settings. Comment the next line if you want to\n# checkin your Azure Web App publish settings, but sensitive information contained\n# in these scripts will be unencrypted\nPublishScripts/\n\n# NuGet Packages\n*.nupkg\n# NuGet Symbol Packages\n*.snupkg\n# The packages folder can be ignored because of Package Restore\n**/[Pp]ackages/*\n# except build/, which is used as an MSBuild target.\n!**/[Pp]ackages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/[Pp]ackages/repositories.config\n# NuGet v3's project.json files produces more ignorable files\n*.nuget.props\n*.nuget.targets\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Windows Store app package directories and files\nAppPackages/\nBundleArtifacts/\nPackage.StoreAssociation.xml\n_pkginfo.txt\n*.appx\n*.appxbundle\n*.appxupload\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!?*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.jfm\n*.pfx\n*.publishsettings\norleans.codegen.cs\n\n# Including strong name files can present a security risk\n# (https://github.com/github/gitignore/pull/2483#issue-259490424)\n#*.snk\n\n# Since there are multiple workflows, uncomment next line to ignore bower_components\n# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)\n#bower_components/\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\nServiceFabricBackup/\n*.rptproj.bak\n\n# SQL Server files\n*.mdf\n*.ldf\n*.ndf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n*.rptproj.rsuser\n*- [Bb]ackup.rdl\n*- [Bb]ackup ([0-9]).rdl\n*- [Bb]ackup ([0-9][0-9]).rdl\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\nnode_modules/\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)\n*.vbw\n\n# Visual Studio 6 auto-generated project file (contains which files were open etc.)\n*.vbp\n\n# Visual Studio 6 workspace and project file (working project files containing files to include in project)\n*.dsw\n*.dsp\n\n# Visual Studio 6 technical files\n*.ncb\n*.aps\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\npaket-files/\n\n# FAKE - F# Make\n.fake/\n\n# CodeRush personal settings\n.cr/personal\n\n# Python Tools for Visual Studio (PTVS)\n__pycache__/\n*.pyc\n\n# Cake - Uncomment if you are using it\n# tools/**\n# !tools/packages.config\n\n# Tabs Studio\n*.tss\n\n# Telerik's JustMock configuration file\n*.jmconfig\n\n# BizTalk build output\n*.btp.cs\n*.btm.cs\n*.odx.cs\n*.xsd.cs\n\n# OpenCover UI analysis results\nOpenCover/\n\n# Azure Stream Analytics local run output\nASALocalRun/\n\n# MSBuild Binary and Structured Log\n*.binlog\n\n# NVidia Nsight GPU debugger configuration file\n*.nvuser\n\n# MFractors (Xamarin productivity tool) working folder\n.mfractor/\n\n# Local History for Visual Studio\n.localhistory/\n\n# Visual Studio History (VSHistory) files\n.vshistory/\n\n# BeatPulse healthcheck temp database\nhealthchecksdb\n\n# Backup folder for Package Reference Convert tool in Visual Studio 2017\nMigrationBackup/\n\n# Ionide (cross platform F# VS Code tools) working folder\n.ionide/\n\n# Fody - auto-generated XML schema\nFodyWeavers.xsd\n\n# VS Code files for those working on multiple tools\n.vscode/*\n!.vscode/settings.json\n!.vscode/tasks.json\n!.vscode/launch.json\n!.vscode/extensions.json\n*.code-workspace\n\n# Local History for Visual Studio Code\n.history/\n\n# Windows Installer files from build outputs\n*.cab\n*.msi\n*.msix\n*.msm\n*.msp\n\n# JetBrains Rider\n*.sln.iml\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Microsoft Open Source Code of Conduct\n\nThis project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).\n\nResources:\n\n- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)\n- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)\n- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns\n"
  },
  {
    "path": "Directory.Build.props",
    "content": "<Project>\n\n  <PropertyGroup>\n    <SuppressNETCoreSdkPreviewMessage>true</SuppressNETCoreSdkPreviewMessage>\n    <ImplicitUsings>enable</ImplicitUsings>\n  </PropertyGroup>\n\n</Project>\n"
  },
  {
    "path": "Directory.Packages.props",
    "content": "<Project>\n  <PropertyGroup>\n    <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>\n    <CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>\n    <MicrosoftExtensionsVersion>8.6.0</MicrosoftExtensionsVersion>\n    <AspireVersion>8.2.2</AspireVersion>\n    <MicrosoftExtensionsAiVersion>9.4.4-preview.1.25259.16</MicrosoftExtensionsAiVersion>\n    <MicrosoftExtensionsAiEvaluationVersion>9.4.4-preview.1.25259.16</MicrosoftExtensionsAiEvaluationVersion>\n  </PropertyGroup>\n  <ItemGroup>\n    <!-- Version together with Aspire -->\n    <PackageVersion Include=\"Aspire.Azure.Storage.Blobs\" Version=\"$(AspireVersion)\" />\n    <PackageVersion Include=\"Aspire.Hosting.AppHost\" Version=\"$(AspireVersion)\" />\n    <PackageVersion Include=\"Aspire.Hosting.Azure.Storage\" Version=\"$(AspireVersion)\" />\n    <PackageVersion Include=\"Aspire.Hosting.PostgreSQL\" Version=\"$(AspireVersion)\" />\n    <PackageVersion Include=\"Aspire.Hosting.Qdrant\" Version=\"$(AspireVersion)\" />\n    <PackageVersion Include=\"Aspire.Hosting.Redis\" Version=\"$(AspireVersion)\" />\n    <PackageVersion Include=\"Aspire.Hosting.Testing\" Version=\"$(AspireVersion)\" />\n    <PackageVersion Include=\"Aspire.Npgsql.EntityFrameworkCore.PostgreSQL\" Version=\"$(AspireVersion)\" />\n    <PackageVersion Include=\"Aspire.StackExchange.Redis\" Version=\"$(AspireVersion)\" />\n    <PackageVersion Include=\"Azure.Identity\" Version=\"1.12.0\" />\n    <PackageVersion Include=\"Azure.AI.OpenAI\" Version=\"2.1.0-beta.1\" />\n    <PackageVersion Include=\"IdentityModel\" Version=\"7.0.0\" />\n    <PackageVersion Include=\"Microsoft.AspNetCore.Authentication.JwtBearer\" Version=\"8.0.10\" />\n    <PackageVersion Include=\"Microsoft.AspNetCore.Authentication.OpenIdConnect\" Version=\"8.0.10\" />\n    <PackageVersion Include=\"Microsoft.Extensions.AI\" Version=\"$(MicrosoftExtensionsAiVersion)\" />\n    <PackageVersion Include=\"Microsoft.Extensions.AI.Evaluation\" Version=\"$(MicrosoftExtensionsAiEvaluationVersion)\" />\n    <PackageVersion Include=\"Microsoft.Extensions.AI.Evaluation.Quality\" Version=\"$(MicrosoftExtensionsAiEvaluationVersion)\" />\n    <PackageVersion Include=\"Microsoft.Extensions.AI.Evaluation.Reporting\" Version=\"$(MicrosoftExtensionsAiEvaluationVersion)\" />\n    <PackageVersion Include=\"Microsoft.Extensions.AI.Ollama\" Version=\"$(MicrosoftExtensionsAiVersion)\" />\n    <PackageVersion Include=\"Microsoft.Extensions.AI.OpenAI\" Version=\"$(MicrosoftExtensionsAiVersion)\" />\n    <PackageVersion Include=\"Microsoft.Extensions.Hosting\" Version=\"8.0.1\" />\n    <PackageVersion Include=\"Microsoft.Extensions.ServiceDiscovery\" Version=\"$(AspireVersion)\" />\n    <PackageVersion Include=\"Microsoft.ML.Tokenizers\" Version=\"1.0.1\" />\n    <PackageVersion Include=\"Microsoft.ML.Tokenizers.Data.O200kBase\" Version=\"1.0.1\" />\n    <!-- Version together with ASP.NET -->\n    <PackageVersion Include=\"Microsoft.AspNetCore.Components.QuickGrid\" Version=\"8.0.10\" />\n    <PackageVersion Include=\"Microsoft.Extensions.Configuration.Json\" Version=\"8.0.1\" />\n    <PackageVersion Include=\"Microsoft.Extensions.Http.Resilience\" Version=\"8.10.0\" />\n    <PackageVersion Include=\"Microsoft.FluentUI.AspNetCore.Components\" Version=\"4.10.3\" />\n    <PackageVersion Include=\"Microsoft.FluentUI.AspNetCore.Components.DataGrid.EntityFrameworkAdapter\" Version=\"4.10.3\" />\n    <PackageVersion Include=\"Microsoft.FluentUI.AspNetCore.Components.Icons\" Version=\"4.10.3\" />\n    <PackageVersion Include=\"Microsoft.Playwright\" Version=\"1.48.0\" />\n    <PackageVersion Include=\"Microsoft.SemanticKernel.Connectors.OpenAI\" Version=\"1.16.0\" />\n    <PackageVersion Include=\"Microsoft.SemanticKernel.Connectors.Qdrant\" Version=\"1.16.0-alpha\" />\n    <PackageVersion Include=\"Microsoft.SemanticKernel.Core\" Version=\"1.25.0\" />\n    <PackageVersion Include=\"Microsoft.SemanticKernel\" Version=\"1.16.0\" />\n    <!-- Open Telemetry -->\n    <PackageVersion Include=\"OpenTelemetry.Exporter.OpenTelemetryProtocol\" Version=\"1.9.0\" />\n    <PackageVersion Include=\"OpenTelemetry.Extensions.Hosting\" Version=\"1.9.0\" />\n    <PackageVersion Include=\"OpenTelemetry.Instrumentation.AspNetCore\" Version=\"1.9.0\" />\n    <PackageVersion Include=\"OpenTelemetry.Instrumentation.Http\" Version=\"1.9.0\" />\n    <PackageVersion Include=\"OpenTelemetry.Instrumentation.Runtime\" Version=\"1.9.0\" />\n    <PackageVersion Include=\"PdfPig\" Version=\"0.1.9\" />\n    <PackageVersion Include=\"SmartComponents.AspNetCore\" Version=\"0.1.0-preview10148\" />\n    <PackageVersion Include=\"SmartComponents.LocalEmbeddings\" Version=\"0.1.0-preview10148\" />\n    <PackageVersion Include=\"SmartComponents.LocalEmbeddings.SemanticKernel\" Version=\"0.1.0-preview10148\" />\n    <PackageVersion Include=\"StatefulReconnection\" Version=\"0.1.0\" />\n    <PackageVersion Include=\"Markdown2Pdf\" Version=\"2.2.1\" />\n    <PackageVersion Include=\"Microsoft.NET.Test.Sdk\" Version=\"17.11.1\" />\n    <PackageVersion Include=\"System.Text.Json\" Version=\"9.0.2\" />\n    <PackageVersion Include=\"xunit\" Version=\"2.9.2\" />\n    <PackageVersion Include=\"xunit.runner.visualstudio\" Version=\"2.8.2\" />\n    <PackageVersion Include=\"Duende.IdentityServer\" Version=\"7.0.8\" />\n    <PackageVersion Include=\"Serilog.AspNetCore\" Version=\"8.0.3\" />\n    <PackageVersion Include=\"System.Runtime.Caching\" Version=\"8.0.1\" />\n    <PackageVersion Include=\"System.Memory.Data\" Version=\"8.0.1\" />\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "LICENSE",
    "content": "    MIT License\n\n    Copyright (c) .NET Foundation. All rights reserved.\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in all\n    copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n    SOFTWARE\n"
  },
  {
    "path": "README.md",
    "content": "# eShopSupport \n\nA sample .NET application showcasing common use cases and development practices for build AI solutions in .NET (Generative AI, specifically). This sample demonstrates a customer support application for an e-commerce website using a services-based architecture with .NET Aspire. It includes support for the following AI use cases:\n\n* Text classification, applying labels based on content\n* Sentiment analysis based on message content\n* Summarization of large sets of text\n* Synthetic data generation, creating test content for the sample\n* Chat bot interactions with chat history and suggested responses\n\n<img width=400 align=top src=https://github.com/user-attachments/assets/5a41493f-565b-4dd0-ae31-1b5c3c2f6d22>\n\n<img width=400 align=top src=https://github.com/user-attachments/assets/7930a940-bb31-4dc0-b5f6-738d43dfcfe5>\n\nThis sample also demonstrates the following development practices:\n\n* Developing a solution locally, using small local models\n* Evaluating the quality of AI responses using grounded Q&A data\n* Leveraging Python projects as part of a .NET Aspire solution\n* Deploying the application, including small local models, to the Cloud (coming soon)\n\n## Architecture\n\n![image](https://github.com/user-attachments/assets/3c339d0d-507a-416b-94ba-0e179d6ff2f5)\n\n## Getting Started\n\n### Prerequisites\n\n- A device with an Nvidia GPU (see [workaround for running on the CPU](https://github.com/dotnet/eShopSupport/issues/19))\n- Clone the eShopSupport repository: https://github.com/dotnet/eshopsupport\n- [Install & start Docker Desktop](https://docs.docker.com/engine/install/)\n- [Install Python 3.12.5](https://www.python.org/downloads/release/python-3125/)\n\n#### Windows with Visual Studio\n- Install [Visual Studio 2022 version 17.10 or newer](https://visualstudio.microsoft.com/vs/)\n  - Select the following workloads:\n    - `ASP.NET and web development` workload.\n    - `Python Development` workload.\n    - `.NET Aspire SDK` component in `Individual components`.\n\n#### Mac, Linux, & Windows without Visual Studio\n- Install the latest [.NET 8 SDK](https://dot.net/download?cid=eshop)\n- Install the [.NET Aspire workload](https://learn.microsoft.com/dotnet/aspire/fundamentals/setup-tooling?tabs=dotnet-cli%2Cunix#install-net-aspire) with the following commands:\n\n  ```powershell\n  dotnet workload update\n  dotnet workload install aspire\n  dotnet restore eShopSupport.sln\n  ```\n- (Optionally) Install [Visual Studio Code](https://code.visualstudio.com) with the [C# Dev Kit extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csdevkit)\n\n#### Install Python requirements\n\nFrom the Terminal, at the root of the cloned repo, run:\n\n```powershell\npip install -r src/PythonInference/requirements.txt\n```\n\n**Note:** If the above command doesn't work on Windows, use the following command:\n\n```powershell\npy -m pip install -r src/PythonInference/requirements.txt\n```\n\n### Running the solution\n\n> [!WARNING]\n> Remember to ensure that Docker is started.\n\n* (Windows only) Run the application from Visual Studio:\n  - Open the `eShopSupport.sln` file in Visual Studio\n  - Ensure that `AppHost` is your startup project\n  - Hit Ctrl-F5 to launch .NET Aspire\n\n* Or run the application from your terminal:\n\n  ```powershell\n  dotnet run --project src/AppHost\n  ```\n\n  then look for lines like this in the console output in order to find the URL to open the Aspire dashboard:\n\n  ```sh\n  Login to the dashboard at: http://localhost:17191/login?t=uniquelogincodeforyou\n  ```\n\n> You may need to install ASP.NET Core HTTPS development certificates first, and then close all browser tabs. Learn more at https://aka.ms/aspnet/https-trust-dev-cert\n\n# Contributing\n\nThis project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.\n\n# Sample data\n\nThe sample data is defined in [seeddata](https://github.com/dotnet/eShopSupport/tree/main/seeddata). All products/descriptions/brands, manuals, customers, and support tickets names are fictional and were generated using [GPT-35-Turbo](https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/chatgpt) using the included [DataGenerator](https://github.com/dotnet/eShopSupport/tree/main/seeddata/DataGenerator) project.\n"
  },
  {
    "path": "SECURITY.md",
    "content": "<!-- BEGIN MICROSOFT SECURITY.MD V0.0.9 BLOCK -->\n\n## Security\n\nMicrosoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet) and [Xamarin](https://github.com/xamarin).\n\nIf you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/security.md/definition), please report it to us as described below.\n\n## Reporting Security Issues\n\n**Please do not report security vulnerabilities through public GitHub issues.**\n\nInstead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/security.md/msrc/create-report).\n\nIf you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com).  If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/security.md/msrc/pgp).\n\nYou should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). \n\nPlease include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:\n\n  * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)\n  * Full paths of source file(s) related to the manifestation of the issue\n  * The location of the affected source code (tag/branch/commit or direct URL)\n  * Any special configuration required to reproduce the issue\n  * Step-by-step instructions to reproduce the issue\n  * Proof-of-concept or exploit code (if possible)\n  * Impact of the issue, including how an attacker might exploit the issue\n\nThis information will help us triage your report more quickly.\n\nIf you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/security.md/msrc/bounty) page for more details about our active programs.\n\n## Preferred Languages\n\nWe prefer all communications to be in English.\n\n## Policy\n\nMicrosoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/security.md/cvd).\n\n<!-- END MICROSOFT SECURITY.MD BLOCK -->\n"
  },
  {
    "path": "eShopSupport.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 17\nVisualStudioVersion = 17.0.31903.59\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"src\", \"src\", \"{7306A281-C46A-4EE3-948D-513D56B1BD34}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Backend\", \"src\\Backend\\Backend.csproj\", \"{96F30B32-9DE5-450F-B54F-CFDFACC91AFF}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"StaffWebUI\", \"src\\StaffWebUI\\StaffWebUI.csproj\", \"{D77F3443-68A2-4F6A-ABB8-0E7CA32643FA}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"AppHost\", \"src\\AppHost\\AppHost.csproj\", \"{BEE4A236-2112-44BF-8013-00542A07E4FE}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"ServiceDefaults\", \"src\\ServiceDefaults\\ServiceDefaults.csproj\", \"{D69799F9-BE09-4303-A67D-323A60AA8C0A}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"DataIngestor\", \"src\\DataIngestor\\DataIngestor.csproj\", \"{E0886BA7-F33C-4FB4-80D1-93FCC1C4A513}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"seeddata\", \"seeddata\", \"{2B17496A-5870-4676-927B-6B45871C7BBA}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"dev\", \"dev\", \"{B3CDC49A-D71A-4C0D-945F-8DD69FC1B066}\"\n\tProjectSection(SolutionItems) = preProject\n\t\tseeddata\\dev\\categories.json = seeddata\\dev\\categories.json\n\t\tseeddata\\dev\\customers.json = seeddata\\dev\\customers.json\n\t\tseeddata\\dev\\evalquestions.json = seeddata\\dev\\evalquestions.json\n\t\tseeddata\\dev\\manual-chunks.json = seeddata\\dev\\manual-chunks.json\n\t\tseeddata\\dev\\manuals.zip = seeddata\\dev\\manuals.zip\n\t\tseeddata\\dev\\products.json = seeddata\\dev\\products.json\n\t\tseeddata\\dev\\tickets.json = seeddata\\dev\\tickets.json\n\tEndProjectSection\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"CustomerWebUI\", \"src\\CustomerWebUI\\CustomerWebUI.csproj\", \"{AAA2257C-D227-404A-8EDF-7BF6C5592D51}\"\nEndProject\nProject(\"{888888A0-9F3D-457C-B088-3A5042F75D52}\") = \"PythonInference\", \"src\\PythonInference\\PythonInference.pyproj\", \"{BAA14585-1716-40FB-A04E-F986F1038638}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"Solution Items\", \"Solution Items\", \"{218618B1-A99C-4174-A13C-0C2CFD065D78}\"\n\tProjectSection(SolutionItems) = preProject\n\t\tDirectory.Packages.props = Directory.Packages.props\n\tEndProjectSection\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"DataGenerator\", \"seeddata\\DataGenerator\\DataGenerator.csproj\", \"{E2871C52-FBBF-44A4-A3CD-185E5F6AA7EB}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Evaluator\", \"src\\Evaluator\\Evaluator.csproj\", \"{A634C7D8-FD7D-49F5-A98E-626F0AEE145F}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"test\", \"test\", \"{9E677D76-414B-492C-AF74-1B091F940D00}\"\n\tProjectSection(SolutionItems) = preProject\n\t\tseeddata\\test\\categories.json = seeddata\\test\\categories.json\n\t\tseeddata\\test\\customers.json = seeddata\\test\\customers.json\n\t\tseeddata\\test\\evalquestions.json = seeddata\\test\\evalquestions.json\n\t\tseeddata\\test\\manual-chunks.json = seeddata\\test\\manual-chunks.json\n\t\tseeddata\\test\\manuals.zip = seeddata\\test\\manuals.zip\n\t\tseeddata\\test\\products.json = seeddata\\test\\products.json\n\t\tseeddata\\test\\tickets.json = seeddata\\test\\tickets.json\n\tEndProjectSection\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"test\", \"test\", \"{51031120-B48D-4680-8808-26B64F235CB9}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"E2ETest\", \"test\\E2ETest\\E2ETest.csproj\", \"{F30843C3-AFB5-435E-8A7D-9B4C86A75E18}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"IdentityServer\", \"src\\IdentityServer\\IdentityServer.csproj\", \"{89404F66-90BC-4D45-9061-050334772CDC}\"\nEndProject\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"EvaluationTests\", \"test\\EvaluationTests\\EvaluationTests.csproj\", \"{6BE0D6D5-F251-4628-9FB9-B19C565FC5EB}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Any CPU = Debug|Any CPU\n\t\tRelease|Any CPU = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{96F30B32-9DE5-450F-B54F-CFDFACC91AFF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{96F30B32-9DE5-450F-B54F-CFDFACC91AFF}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{96F30B32-9DE5-450F-B54F-CFDFACC91AFF}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{96F30B32-9DE5-450F-B54F-CFDFACC91AFF}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{D77F3443-68A2-4F6A-ABB8-0E7CA32643FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{D77F3443-68A2-4F6A-ABB8-0E7CA32643FA}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{D77F3443-68A2-4F6A-ABB8-0E7CA32643FA}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{D77F3443-68A2-4F6A-ABB8-0E7CA32643FA}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{BEE4A236-2112-44BF-8013-00542A07E4FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{BEE4A236-2112-44BF-8013-00542A07E4FE}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{BEE4A236-2112-44BF-8013-00542A07E4FE}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{BEE4A236-2112-44BF-8013-00542A07E4FE}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{D69799F9-BE09-4303-A67D-323A60AA8C0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{D69799F9-BE09-4303-A67D-323A60AA8C0A}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{D69799F9-BE09-4303-A67D-323A60AA8C0A}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{D69799F9-BE09-4303-A67D-323A60AA8C0A}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{E0886BA7-F33C-4FB4-80D1-93FCC1C4A513}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{E0886BA7-F33C-4FB4-80D1-93FCC1C4A513}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{E0886BA7-F33C-4FB4-80D1-93FCC1C4A513}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{E0886BA7-F33C-4FB4-80D1-93FCC1C4A513}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{AAA2257C-D227-404A-8EDF-7BF6C5592D51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{AAA2257C-D227-404A-8EDF-7BF6C5592D51}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{AAA2257C-D227-404A-8EDF-7BF6C5592D51}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{AAA2257C-D227-404A-8EDF-7BF6C5592D51}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{BAA14585-1716-40FB-A04E-F986F1038638}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{BAA14585-1716-40FB-A04E-F986F1038638}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{E2871C52-FBBF-44A4-A3CD-185E5F6AA7EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{E2871C52-FBBF-44A4-A3CD-185E5F6AA7EB}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{E2871C52-FBBF-44A4-A3CD-185E5F6AA7EB}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{E2871C52-FBBF-44A4-A3CD-185E5F6AA7EB}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{A634C7D8-FD7D-49F5-A98E-626F0AEE145F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{A634C7D8-FD7D-49F5-A98E-626F0AEE145F}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{A634C7D8-FD7D-49F5-A98E-626F0AEE145F}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{A634C7D8-FD7D-49F5-A98E-626F0AEE145F}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{F30843C3-AFB5-435E-8A7D-9B4C86A75E18}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{F30843C3-AFB5-435E-8A7D-9B4C86A75E18}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{F30843C3-AFB5-435E-8A7D-9B4C86A75E18}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{F30843C3-AFB5-435E-8A7D-9B4C86A75E18}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{89404F66-90BC-4D45-9061-050334772CDC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{89404F66-90BC-4D45-9061-050334772CDC}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{89404F66-90BC-4D45-9061-050334772CDC}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{89404F66-90BC-4D45-9061-050334772CDC}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{6BE0D6D5-F251-4628-9FB9-B19C565FC5EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{6BE0D6D5-F251-4628-9FB9-B19C565FC5EB}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{6BE0D6D5-F251-4628-9FB9-B19C565FC5EB}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{6BE0D6D5-F251-4628-9FB9-B19C565FC5EB}.Release|Any CPU.Build.0 = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\n\tGlobalSection(NestedProjects) = preSolution\n\t\t{96F30B32-9DE5-450F-B54F-CFDFACC91AFF} = {7306A281-C46A-4EE3-948D-513D56B1BD34}\n\t\t{D77F3443-68A2-4F6A-ABB8-0E7CA32643FA} = {7306A281-C46A-4EE3-948D-513D56B1BD34}\n\t\t{BEE4A236-2112-44BF-8013-00542A07E4FE} = {7306A281-C46A-4EE3-948D-513D56B1BD34}\n\t\t{D69799F9-BE09-4303-A67D-323A60AA8C0A} = {7306A281-C46A-4EE3-948D-513D56B1BD34}\n\t\t{E0886BA7-F33C-4FB4-80D1-93FCC1C4A513} = {7306A281-C46A-4EE3-948D-513D56B1BD34}\n\t\t{B3CDC49A-D71A-4C0D-945F-8DD69FC1B066} = {2B17496A-5870-4676-927B-6B45871C7BBA}\n\t\t{AAA2257C-D227-404A-8EDF-7BF6C5592D51} = {7306A281-C46A-4EE3-948D-513D56B1BD34}\n\t\t{BAA14585-1716-40FB-A04E-F986F1038638} = {7306A281-C46A-4EE3-948D-513D56B1BD34}\n\t\t{E2871C52-FBBF-44A4-A3CD-185E5F6AA7EB} = {2B17496A-5870-4676-927B-6B45871C7BBA}\n\t\t{A634C7D8-FD7D-49F5-A98E-626F0AEE145F} = {7306A281-C46A-4EE3-948D-513D56B1BD34}\n\t\t{9E677D76-414B-492C-AF74-1B091F940D00} = {2B17496A-5870-4676-927B-6B45871C7BBA}\n\t\t{F30843C3-AFB5-435E-8A7D-9B4C86A75E18} = {51031120-B48D-4680-8808-26B64F235CB9}\n\t\t{89404F66-90BC-4D45-9061-050334772CDC} = {7306A281-C46A-4EE3-948D-513D56B1BD34}\n\t\t{6BE0D6D5-F251-4628-9FB9-B19C565FC5EB} = {51031120-B48D-4680-8808-26B64F235CB9}\n\tEndGlobalSection\n\tGlobalSection(ExtensibilityGlobals) = postSolution\n\t\tSolutionGuid = {B2E71FD9-E3D5-450C-A9E0-318DAA986F31}\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "nuget.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n  <packageSources>\n    <!--To inherit the global NuGet package sources remove the <clear/> line below -->\n    <clear />\n    <add key=\"nuget\" value=\"https://api.nuget.org/v3/index.json\" />\n  </packageSources>\n\n  <packageSourceMapping>\n    <!-- key value for <packageSource> should match key values from <packageSources> element -->\n    <clear />\n    <packageSource key=\"nuget\">\n      <package pattern=\"*\" />\n    </packageSource>\n  </packageSourceMapping>\n</configuration>\n"
  },
  {
    "path": "seeddata/DataGenerator/.gitignore",
    "content": "appsettings.Local.json\noutput/\noutput-demo/\n"
  },
  {
    "path": "seeddata/DataGenerator/ChatCompletionServiceExtensions.cs",
    "content": "﻿using Microsoft.Extensions.DependencyInjection;\nusing System.Data.Common;\nusing Microsoft.Extensions.Hosting;\nusing Microsoft.Extensions.Configuration;\nusing Microsoft.Extensions.AI;\nusing Azure.AI.OpenAI;\nusing System.ClientModel;\nusing OpenAI;\n\nnamespace eShopSupport.DataGenerator;\n\npublic static class ChatCompletionServiceExtensions\n{\n    public static void AddOpenAIChatCompletion(this HostApplicationBuilder builder, string connectionStringName)\n    {\n        var connectionStringBuilder = new DbConnectionStringBuilder();\n        var connectionString = builder.Configuration.GetConnectionString(connectionStringName);\n        if (string.IsNullOrEmpty(connectionString))\n        {\n            throw new InvalidOperationException($\"Missing connection string {connectionStringName}\");\n        }\n\n        connectionStringBuilder.ConnectionString = connectionString;\n\n        var deployment = connectionStringBuilder.TryGetValue(\"Deployment\", out var deploymentValue) ? (string)deploymentValue : throw new InvalidOperationException($\"Connection string {connectionStringName} is missing 'Deployment'\");\n        var endpoint = connectionStringBuilder.TryGetValue(\"Endpoint\", out var endpointValue) ? (string)endpointValue : throw new InvalidOperationException($\"Connection string {connectionStringName} is missing 'Endpoint'\");\n        var key = connectionStringBuilder.TryGetValue(\"Key\", out var keyValue) ? (string)keyValue : throw new InvalidOperationException($\"Connection string {connectionStringName} is missing 'Key'\");\n\n        builder.Services.AddSingleton<OpenAIClient>(_ => new AzureOpenAIClient(\n            new Uri(endpoint), new ApiKeyCredential(key)));\n\n        builder.Services.AddChatClient(builder => builder.GetRequiredService<OpenAIClient>().GetChatClient(deployment).AsIChatClient())\n            .UseFunctionInvocation();\n    }\n}\n"
  },
  {
    "path": "seeddata/DataGenerator/DataGenerator.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n    <TargetFramework>net8.0</TargetFramework>\n    <ImplicitUsings>enable</ImplicitUsings>\n    <Nullable>enable</Nullable>\n    <RootNamespace>eShopSupport.DataGenerator</RootNamespace>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Markdown2Pdf\" />\n    <PackageReference Include=\"Microsoft.Extensions.AI\" />\n    <PackageReference Include=\"Microsoft.Extensions.AI.OpenAI\" />\n    <PackageReference Include=\"Microsoft.Extensions.Configuration.Json\" />\n    <PackageReference Include=\"Microsoft.Extensions.Hosting\" />\n    <PackageReference Include=\"SmartComponents.LocalEmbeddings\" />\n    <PackageReference Include=\"Azure.AI.OpenAI\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <None Update=\"appsettings.Local.json\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"appsettings.json\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "seeddata/DataGenerator/Generators/CategoryGenerator.cs",
    "content": "﻿using eShopSupport.DataGenerator.Model;\nusing System.Text.RegularExpressions;\n\nnamespace eShopSupport.DataGenerator.Generators;\n\npublic class CategoryGenerator(IServiceProvider services) : GeneratorBase<Category>(services)\n{\n    protected override string DirectoryName => \"categories\";\n\n    protected override object GetId(Category item) => item.CategoryId;\n\n    protected override async IAsyncEnumerable<Category> GenerateCoreAsync()\n    {\n        // If there are any categories already, assume this covers everything we need\n        if (Directory.GetFiles(OutputDirPath).Any())\n        {\n            yield break;\n        }\n\n        var numCategories = 50;\n        var batchSize = 25;\n        var categoryNames = new HashSet<string>();\n\n        while (categoryNames.Count < numCategories)\n        {\n            Console.WriteLine($\"Generating {batchSize} categories...\");\n\n            var prompt = @$\"Generate {batchSize} product category names for an online retailer\n            of high-tech outdoor adventure goods and related clothing/electronics/etc.\n            Each category name is a single descriptive term, so it does not use the word 'and'.\n            Category names should be interesting and novel, e.g., \"\"Mountain Unicycles\"\", \"\"AI Boots\"\",\n            or \"\"High-volume Water Filtration Plants\"\", not simply \"\"Tents\"\".\n            This retailer sells relatively technical products.\n\n            Each category has a list of up to 8 brand names that make products in that category. All brand names are\n            purely fictional. Brand names are usually multiple words with spaces and/or special characters, e.g.\n            \"\"Orange Gear\"\", \"\"Aqua Tech US\"\", \"\"Livewell\"\", \"\"E & K\"\", \"\"JAXⓇ\"\".\n            Many brand names are used in multiple categories. Some categories have only 2 brands.\n            \n            The response should be a JSON object of the form {{ \"\"categories\"\": [{{\"\"name\"\":\"\"Tents\"\", \"\"brands\"\":[\"\"Rosewood\"\", \"\"Summit Kings\"\"]}}, ...] }}.\";\n\n            var response = await GetAndParseJsonChatCompletion<Response>(prompt, maxTokens: 70 * batchSize);\n            foreach (var c in response.Categories)\n            {\n                if (categoryNames.Add(c.Name))\n                {\n                    c.CategoryId = categoryNames.Count;\n                    c.Brands = c.Brands.Select(ImproveBrandName).ToArray();\n                    yield return c;\n                }\n            }\n        }\n    }\n\n    private static string ImproveBrandName(string name)\n    {\n        // Almost invariably, the name is a PascalCase word like AquaTech, even though we told it to use spaces.\n        // For variety, convert to \"Aqua Tech\" or \"Aquatech\" sometimes.\n        return Regex.Replace(name, @\"([a-z])([A-Z])\", m => Random.Shared.Next(3) switch\n        {\n            0 => $\"{m.Groups[1].Value} {m.Groups[2].Value}\",\n            1 => $\"{m.Groups[1].Value}{m.Groups[2].Value.ToLower()}\",\n            _ => m.Value\n        });\n    }\n\n    private class Response\n    {\n        public required List<Category> Categories { get; set; }\n    }\n}\n"
  },
  {
    "path": "seeddata/DataGenerator/Generators/EvalQuestionGenerator.cs",
    "content": "﻿using System.Text;\nusing System.Threading.Channels;\nusing eShopSupport.DataGenerator.Model;\n\nnamespace eShopSupport.DataGenerator.Generators;\n\npublic class EvalQuestionGenerator(IReadOnlyList<Product> products, IReadOnlyList<Category> categories, IReadOnlyList<Manual> manuals, IServiceProvider services)\n    : GeneratorBase<EvalQuestion>(services)\n{\n    protected override string DirectoryName => \"evalquestions\";\n\n    protected override object GetId(EvalQuestion item)\n        => item.QuestionId;\n\n    protected override async IAsyncEnumerable<EvalQuestion> GenerateCoreAsync()\n    {\n        // If there are any questions already, assume this covers everything we need\n        if (Directory.GetFiles(OutputDirPath).Any())\n        {\n            yield break;\n        }\n\n        var numQuestions = 500;\n        var questionId = 0;\n        var outputChannel = Channel.CreateUnbounded<EvalQuestion>();\n        var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = 10 };\n        CompleteOutputAfterTask(outputChannel.Writer, Parallel.ForAsync(0, numQuestions, parallelOptions, async (_, _) =>\n        {\n            var item = await GenerateSingle();\n            if (!string.IsNullOrWhiteSpace(item.Question) && !string.IsNullOrEmpty(item.Answer))\n            {\n                item.QuestionId = Interlocked.Increment(ref questionId);\n                await outputChannel.Writer.WriteAsync(item);\n            }\n        }));\n\n        await foreach (var item in outputChannel.Reader.ReadAllAsync())\n        {\n            yield return item;\n        }\n    }\n\n    private static void CompleteOutputAfterTask<T>(ChannelWriter<T> writer, Task task)\n    {\n        Task.Run(async () =>\n        {\n            try\n            {\n                await task;\n                writer.Complete();\n            }\n            catch (Exception ex)\n            {\n                writer.Complete(ex);\n            }\n        });\n    }\n\n    private async Task<EvalQuestion> GenerateSingle()\n    {\n        var product = products[Random.Shared.Next(products.Count)];\n        var category = categories.Single(c => c.CategoryId == product.CategoryId);\n        var manual = manuals.Single(m => m.ProductId == product.ProductId);\n        var manualExtract = ManualGenerator.ExtractFromManual(manual);\n        var isQuestionWrittenByAgent = Random.Shared.NextDouble() < 0.75;\n        var questionPrompt = isQuestionWrittenByAgent\n            ? \"\"\"\n                    Questions are short, typically 3-6 words, and are not always full sentences. They may look\n                    like search queries or things typed in a hurry by a support agent. They are not polite or\n                    verbose, since they are addressed to a machine.\n                    Example questions might be \"weight\", \"what are the dimensions\", \"how to shut down\",\n                    \"can use on pets?\", \"what accessories does it come with?\"\n                    \"\"\"\n            : \"\"\"\n                    The question is actually an entire email written by a customer. It usually starts with a\n                    greeting, some description of their situation, and then their question. The whole thing\n                    may be up to 100 words long. It may contain spelling and grammar errors, and may be angry\n                    or rude.\n                    \"\"\";\n\n        var question = await GetAndParseJsonChatCompletion<EvalQuestion>($$\"\"\"\n                    There is an AI system used by customer support agents working for an online retailer.\n                    The AI system is used to help agents answer customer questions.\n\n                    Your task is to write question/answer pairs that will be used to evaluate the\n                    performance of that AI system. All the questions you write will be about actual products\n                    sold by that retailer, based on information from the product catalog and manuals. The\n                    questions should plausibly represent what customers and support agents will ask.\n\n                    In this case, you are to write a question/answer pair based on the following context:\n\n                    <product_name>{{product.Model}}</product_name>\n                    <brand>{{product.Brand}}</brand>\n                    <category>{{category.Name}}</category>\n                    <extract_from_manual>{{manualExtract}}</extract_from_manual>\n\n                    Questions are one of the following types:\n                     - A pre-purchase question to help a customer who wants to know about the product\n                       features, suitability for particular use cases, or other objective facts\n                     - A post-purchase question to help a customer resolve an issue or understand how to\n                       use the product\n\n                    You must select an OBJECTIVE FACT from the product manual and write a question to which\n                    that fact is the answer. Only select facts that are distinctive about this specific product,\n                    not generic information about any product or warranty terms.\n\n                    Always follow these style guidelines:\n                     - {{questionPrompt}}\n                     - Answers are short, typically a single brief sentence of 1-10 words. Never use more than\n                       20 words for an answer.\n                     - The \"verbatim_quote_from_manual\" is 3-6 words taken EXACTLY from the manual which are\n                       the factual basis for the question and asnwer.\n                     - If the provided context does not contain a suitable fact, set all the response properties\n                       to null or empty strings.\n\n                    Respond as JSON in the following form: {\n                        \"question\": \"string\",\n                        \"answer\": \"string\",\n                        \"verbatimQuoteFromManual\": \"string\"\n                    }\n                    \"\"\");\n        question.ProductId = product.ProductId;\n        return question;\n    }\n}\n"
  },
  {
    "path": "seeddata/DataGenerator/Generators/GeneratorBase.cs",
    "content": "﻿using Microsoft.Extensions.AI;\nusing Microsoft.Extensions.DependencyInjection;\nusing System.Diagnostics;\nusing System.Text;\nusing System.Text.Json;\nusing System.Threading.Channels;\n\nnamespace eShopSupport.DataGenerator.Generators;\n\npublic abstract class GeneratorBase<T>\n{\n    protected abstract string DirectoryName { get; }\n\n    protected abstract object GetId(T item);\n\n    public static string OutputDirRoot => Path.Combine(AppContext.BaseDirectory, \"..\", \"..\", \"..\", \"output\");\n\n    protected string OutputDirPath => Path.Combine(OutputDirRoot, DirectoryName);\n\n    protected JsonSerializerOptions SerializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web)\n    {\n        WriteIndented = true\n    };\n\n    public GeneratorBase(IServiceProvider services)\n    {\n        ChatClient = services.GetRequiredService<IChatClient>();\n    }\n\n    public async Task<IReadOnlyList<T>> GenerateAsync()\n    {\n        if (!Directory.Exists(OutputDirPath))\n        {\n            Directory.CreateDirectory(OutputDirPath);\n        }\n\n        var sw = Stopwatch.StartNew();\n        await foreach (var item in GenerateCoreAsync())\n        {\n            sw.Stop();\n            Console.WriteLine($\"Writing {item!.GetType().Name} {GetId(item)} [generated in {sw.Elapsed.TotalSeconds}s]\");\n            var path = GetItemOutputPath(GetId(item).ToString()!);\n            await WriteAsync(path, item);\n            sw.Restart();\n        }\n\n        var existingFiles = Directory.GetFiles(OutputDirPath);\n        return existingFiles.Select(Read).ToList();\n    }\n\n    protected string GetItemOutputPath(string id)\n        => Path.Combine(OutputDirPath, $\"{id}{FilenameExtension}\");\n\n    protected abstract IAsyncEnumerable<T> GenerateCoreAsync();\n\n    protected IChatClient ChatClient { get; }\n\n    protected async Task<string> GetCompletion(string prompt)\n    {\n        // Instructing it to end the content with END_OF_CONTENT is beneficial because it often tries to add a suffix like\n        // \"I have done the task, hope this helps!\". We can avoid that by making it stop before that.\n        var response = await ChatClient.GetResponseAsync(\n            prompt,\n            new ChatOptions { Temperature = 0.9f, StopSequences = [\"END_OF_CONTENT\"] });\n        return response.Text ?? string.Empty;\n    }\n\n    protected async Task<TResponse> GetAndParseJsonChatCompletion<TResponse>(string prompt, int? maxTokens = null, IList<AITool>? tools = null)\n    {\n        var options = new ChatOptions\n        {\n            // MaxOutputTokens = maxTokens, // TODO: Re-enable when https://github.com/dotnet/temp-ai-abstractions/issues/294 is fixed\n            Temperature = 0.9f,\n            ResponseFormat = ChatResponseFormat.Json,\n            Tools = tools,\n        };\n\n        var response = await RunWithRetries(() => ChatClient.GetResponseAsync(prompt, options));\n        var responseString = response.Text ?? string.Empty;\n\n        // Due to what seems like a server-side bug, when asking for a json_object response and with tools enabled,\n        // it often replies with two or more JSON objects concatenated together (duplicates or slight variations).\n        // As a workaround, just read the first complete JSON object from the response.\n        var parsed = ReadAndDeserializeSingleValue<TResponse>(responseString, SerializerOptions)!;\n        return parsed;\n    }\n\n    private static async Task<TResult> RunWithRetries<TResult>(Func<Task<TResult>> operation)\n    {\n        var delay = TimeSpan.FromSeconds(5);\n        var maxAttempts = 5;\n        for (var attemptIndex = 1; ; attemptIndex++)\n        {\n            try\n            {\n                return await operation();\n            }\n            catch (Exception e) when (attemptIndex < maxAttempts)\n            {\n                Console.WriteLine($\"Exception on attempt {attemptIndex}: {e.Message}. Will retry after {delay}\");\n                await Task.Delay(delay);\n                delay += TimeSpan.FromSeconds(15);\n            }\n        }\n    }\n\n    private static TResponse? ReadAndDeserializeSingleValue<TResponse>(string json, JsonSerializerOptions options)\n    {\n        var reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(json).AsSpan());\n        return JsonSerializer.Deserialize<TResponse>(ref reader, options);\n    }\n\n    protected virtual string FilenameExtension => \".json\";\n\n    protected virtual Task WriteAsync(string path, T item)\n    {\n        var itemJson = JsonSerializer.Serialize(item, SerializerOptions);\n        return File.WriteAllTextAsync(path, itemJson);\n    }\n\n    protected virtual T Read(string path)\n    {\n        try\n        {\n            using var existingJson = File.OpenRead(path);\n            return JsonSerializer.Deserialize<T>(existingJson, SerializerOptions)!;\n        }\n        catch (Exception ex)\n        {\n            Console.WriteLine($\"Error reading {path}: {ex.Message}\");\n            throw;\n        }\n    }\n\n    protected IAsyncEnumerable<V> MapParallel<U, V>(IEnumerable<U> source, Func<U, Task<V>> map)\n    {\n        var outputs = Channel.CreateUnbounded<V>();\n        var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = 5 };\n        var mapTask = Parallel.ForEachAsync(source, parallelOptions, async (sourceItem, ct) =>\n        {\n            try\n            {\n                var mappedItem = await map(sourceItem);\n                await outputs.Writer.WriteAsync(mappedItem);\n            }\n            catch (Exception ex)\n            {\n                outputs.Writer.TryComplete(ex);\n            }\n        });\n\n        mapTask.ContinueWith(_ => outputs.Writer.TryComplete());\n\n        return outputs.Reader.ReadAllAsync();\n    }\n}\n"
  },
  {
    "path": "seeddata/DataGenerator/Generators/LocalTextEmbeddingGenerator.cs",
    "content": "﻿using Microsoft.Extensions.AI;\nusing SmartComponents.LocalEmbeddings;\n\nnamespace eShopSupport.DataGenerator.Generators;\n\npublic class LocalTextEmbeddingGenerator : IEmbeddingGenerator<string, Embedding<float>>\n{\n    private readonly LocalEmbedder _embedder = new();\n\n    public EmbeddingGeneratorMetadata Metadata => new(\"local\");\n\n    public void Dispose() => _embedder.Dispose();\n\n    public Task<GeneratedEmbeddings<Embedding<float>>> GenerateAsync(IEnumerable<string> values, EmbeddingGenerationOptions? options = null, CancellationToken cancellationToken = default)\n    {\n        var results = values.Select(v => new Embedding<float>(_embedder.Embed(v).Values)).ToList();\n        return Task.FromResult(new GeneratedEmbeddings<Embedding<float>>(results));\n    }\n\n    public object? GetService(Type serviceType, object? key = null) \n        => serviceType == typeof(IEmbeddingGenerator<string, Embedding<float>>) ? this : null;\n}\n"
  },
  {
    "path": "seeddata/DataGenerator/Generators/ManualGenerator.cs",
    "content": "﻿using eShopSupport.DataGenerator.Model;\nusing System.Text;\n\nnamespace eShopSupport.DataGenerator.Generators;\n\npublic class ManualGenerator(IReadOnlyList<Category> categories, IReadOnlyList<Product> products, IReadOnlyList<ManualToc> manualTocs, IServiceProvider services)\n    : GeneratorBase<Manual>(services)\n{\n    protected override string DirectoryName => $\"manuals{Path.DirectorySeparatorChar}full\";\n\n    protected override object GetId(Manual item) => item.ProductId;\n\n    protected override IAsyncEnumerable<Manual> GenerateCoreAsync()\n    {\n        // Skip the ones we already have\n        var manualsToGenerate = manualTocs.Where(toc => !File.Exists(GetItemOutputPath(toc.ProductId.ToString())));\n        return MapParallel(manualsToGenerate, GenerateManualAsync);\n    }\n\n    private async Task<Manual> GenerateManualAsync(ManualToc toc)\n    {\n        var product = products.Single(p => p.ProductId == toc.ProductId);\n        var category = categories.Single(c => c.CategoryId == product.CategoryId);\n\n        var result = new StringBuilder();\n        result.AppendLine($\"# {product.Model}\");\n        result.AppendLine();\n\n        var desiredSubsectionWordLength = 500;\n        foreach (var section in toc.Sections)\n        {\n            Console.WriteLine($\"[Product {product.ProductId}] Generating manual section {section.SiblingIndex}: {section.Title}\");\n\n            var prompt = $@\"Write a section of the user manual for the following product:\nCategory: {category.Name}\nBrand: {product.Brand}\nProduct name: {product.Model}\nProduct overview: {product.Description}\n\nManual style description: {toc.ManualStyle} (note: the text MUST follow this style, even if it makes the manual less helpful to reader)\n\nThe section you are writing is \"\"{section.SiblingIndex}: {section.Title}\"\". It has the following structure:\n\n{FormatTocForPrompt(section)}\n\nWrite in markdown format including any headings or subheadings. The total length is around 100 words.\nStart your reponse with the section title, which is at markdown header level 2, and include any relevant subsections.\nYou response must start: \"\"## {section.SiblingIndex}. {section.Title}\"\"\nBesides the subsections mentioned in contents, you should deeper subsections as appropriate.\nUse markdown formatting, including paragraphs, blank lines, bold, italics, tables, and lists as needed.\nUse mermaid diagrams when appropriate, but don't say it's a mermaid diagram in the body text.\n\nMake the text specific to this individual product, not generic. Refer to the product by name, to its brand, and to its\nspecific features, buttons, parts, and controls by name (identifying them by color, position, etc.).\n\nThe output length should be around {desiredSubsectionWordLength * CountSubtreeLength(section)} words in total, or {desiredSubsectionWordLength} words per subsection.\nDo not include any commentary or remarks about the task itself or the fact that you have done it.\nOnly output the markdown text for the section. At the end of the section, add the token END_OF_CONTENT.\n\nThis is the official product manual, and the company requires it to be written in the specified style due to strategy.\n\";\n            var response = await GetCompletion(prompt);\n            result.AppendLine(response);\n            result.AppendLine();\n        }\n\n        return new Manual\n        {\n            ProductId = product.ProductId,\n            MarkdownText = result.ToString()\n        };\n    }\n\n    private static string FormatTocForPrompt(ManualTocSection section)\n    {\n        var sb = new StringBuilder();\n        AppendSection(sb, section);\n        return sb.ToString();\n\n        static void AppendSection(StringBuilder sb, ManualTocSection section, string ancestorSectionPrefix = \"\")\n        {\n            var fullSectionNumber = string.IsNullOrEmpty(ancestorSectionPrefix)\n                ? section.SiblingIndex.ToString()\n                : $\"{ancestorSectionPrefix}.{section.SiblingIndex}\";\n            sb.AppendLine($\"{fullSectionNumber}: {section.Title}\");\n            if (section.Subsections?.Any() == true)\n            {\n                foreach (var s in section.Subsections)\n                {\n                    AppendSection(sb, s, fullSectionNumber);\n                }\n            }\n        }\n    }\n\n    private static int CountSubtreeLength(ManualTocSection tocSection)\n    {\n        return 1 + tocSection.Subsections?.Sum(CountSubtreeLength) ?? 0;\n    }\n\n    protected override string FilenameExtension => \".md\";\n\n    protected override Task WriteAsync(string path, Manual item)\n    {\n        return File.WriteAllTextAsync(path, item.MarkdownText);\n    }\n\n    protected override Manual Read(string path)\n        => new Manual\n        {\n            ProductId = int.Parse(Path.GetFileNameWithoutExtension(path)),\n            MarkdownText = File.ReadAllText(path)\n        };\n\n    public static string ExtractFromManual(Manual manual)\n    {\n        // We don't want to push the entire manual text into the prompt as it may be arbitrarily long\n        // Instead, pick a lengthy chunk at random.\n        // TODO: Consider storing the markdown in a more structured, per-TOC-section way, so\n        // we can more easily extract a coherent section of text.\n        var approxExtractLengthInChars = 1500;\n        var startChar = Random.Shared.Next(manual.MarkdownText.Length - approxExtractLengthInChars);\n\n        // Find the line containing this char\n        var lines = manual.MarkdownText.Split('\\n', StringSplitOptions.RemoveEmptyEntries);\n        var lineIndexContainingStartChar = 0;\n        for (var numCharsSeen = 0; numCharsSeen < startChar; lineIndexContainingStartChar++)\n        {\n            numCharsSeen += lines[lineIndexContainingStartChar].Length;\n        }\n\n        // Add lines until we have enough text\n        var extract = new StringBuilder();\n        for (var i = lineIndexContainingStartChar; i < lines.Length; i++)\n        {\n            extract.AppendLine(lines[i]);\n            if (extract.Length >= approxExtractLengthInChars)\n            {\n                break;\n            }\n        }\n\n        return extract.ToString();\n    }\n}\n"
  },
  {
    "path": "seeddata/DataGenerator/Generators/ManualPdfConverter.cs",
    "content": "﻿using eShopSupport.DataGenerator.Model;\nusing Markdown2Pdf;\nusing Markdown2Pdf.Options;\nusing System.Text.RegularExpressions;\n\nnamespace eShopSupport.DataGenerator.Generators;\n\npublic class ManualPdfConverter(IReadOnlyList<Product> products, IReadOnlyList<Manual> manuals)\n{\n    Markdown2PdfConverter CreateConverter(Product product) => new(new()\n    {\n        DocumentTitle = product.Model,\n        MarginOptions = new()\n        {\n            Top = \"80px\",\n            Bottom = \"80px\",\n            Left = \"75px\",\n            Right = \"75px\",\n        },\n        TableOfContents = new()\n        {\n            ListStyle = ListStyle.None,\n            MinDepthLevel = 2,\n            MaxDepthLevel = 4,\n            PageNumberOptions = new()\n            {\n                TabLeader = Leader.Dots,\n            },\n        },\n        CustomHeadContent = @\"<style>\n            h1 { padding-top: 300px; font-size: 4rem !important; page-break-after: always; border-bottom: none !important; }\n            h2 { page-break-before: always; }\n        </style>\",\n        HeaderHtml = \"\",\n        FooterHtml = $\"<div style=\\\"width: 100%; padding: 30px 75px; display: flex; justify-content: space-between;\\\"><span style=\\\"color: gray\\\">(c) {product.Brand}</span><span class=\\\"pageNumber\\\"></span></div>\",\n    });\n\n    public async Task<IReadOnlyList<ManualPdf>> ConvertAsync()\n    {\n        var results = new List<ManualPdf>();\n\n        foreach (var manual in manuals)\n        {\n            var outputDir = Path.Combine(GeneratorBase<object>.OutputDirRoot, \"manuals\", \"pdf\");\n            var outputPath = Path.Combine(outputDir, $\"{manual.ProductId}.pdf\");\n            results.Add(new ManualPdf { ProductId = manual.ProductId, LocalPath = outputPath });\n\n            if (File.Exists(outputPath))\n            {\n                continue;\n            }\n\n            Directory.CreateDirectory(outputDir);\n\n            // Insert TOC marker after first level-1 heading\n            var firstMatch = true;\n            var markdown = Regex.Replace(manual.MarkdownText, \"^(# .*\\r?\\n)\", match =>\n            {\n                if (firstMatch)\n                {\n                    firstMatch = false;\n                    return match.Value + \"\\n[TOC]\\n\\n\";\n                }\n                else\n                {\n                    return match.Value;\n                }\n            }, RegexOptions.Multiline);\n\n            using var inputFile = new TempFile(markdown);\n\n            var product = products.Single(p => p.ProductId == manual.ProductId);\n            var converter = CreateConverter(product);\n            await converter.Convert(inputFile.FilePath, outputPath);\n            Console.WriteLine($\"Wrote {Path.GetFileName(outputPath)}\");\n        }\n\n        return results;\n    }\n\n    private class TempFile : IDisposable\n    {\n        public string FilePath { get; }\n\n        public TempFile(string contents)\n        {\n            FilePath = Path.GetTempFileName();\n            File.WriteAllText(FilePath, contents);\n        }\n\n        public void Dispose()\n            => File.Delete(FilePath);\n    }\n}\n"
  },
  {
    "path": "seeddata/DataGenerator/Generators/ManualTocGenerator.cs",
    "content": "﻿using eShopSupport.DataGenerator.Model;\n\nnamespace eShopSupport.DataGenerator.Generators;\n\npublic class ManualTocGenerator(IReadOnlyList<Category> categories, IReadOnlyList<Product> products, IServiceProvider services) : GeneratorBase<ManualToc>(services)\n{\n    protected override string DirectoryName => $\"manuals{Path.DirectorySeparatorChar}toc\";\n\n    protected override object GetId(ManualToc item) => item.ProductId;\n\n    protected override IAsyncEnumerable<ManualToc> GenerateCoreAsync()\n    {\n        return MapParallel(\n            products.Where(p => !File.Exists(GetItemOutputPath(p.ProductId.ToString()))),\n            GenerateTocForProductAsync);\n    }\n\n    private async Task<ManualToc> GenerateTocForProductAsync(Product product)\n    {\n        // An issue with current LLMs is that, unless strongly prompted otherwise, they tend to write\n        // in a very insipid, bland style that is frustrating to read. A mitigation is to offer strong\n        // and even surprising style guidance to vary the results. Some of the following styles may sound\n        // silly or unprofessional, but this level of hinting is necessary to get the desired variety.\n        var styles = new[] {\n            \"normal\",\n            \"friendly\",\n            \"trying to be cool and hip, with lots of emojis\",\n            \"extremely formal and embarassingly over-polite\",\n            \"extremely technical, with many references to industrial specifications. Require the user to perform complex diagnostics using specialized industrial and scientific equipment before and after use. Refer to standards bodies, formal industry specification codes, and academic research papers\",\n            \"extremely badly translated from another language - most sentences are in broken English, grammatically incorrect, and misspelled\",\n            \"confusing and often off-topic, with spelling mistakes\",\n            \"incredibly negative and risk-averse, implying it would be unreasonable to use the product for any use case at all, and that it must not be used even for its most obvious and primary use case. Do not admit any design or manufacturing faults. Do not apologise that the product is unsuitable. No matter what the user may be trying to do, emphasize that the product must not be used in that specific way. Give examples of harms that came to prior users.\",\n        };\n        var chosenStyle = styles[Random.Shared.Next(styles.Length)];\n        var category = categories.Single(c => c.CategoryId == product.CategoryId);\n\n        var prompt = @$\"Write a suggested table of contents for the user manual for the following product:\n\n            Category: {category.Name}\n            Brand: {product.Brand}\n            Product name: {product.Model}\n            Overview: {product.Description}\n\n            The manual MUST be written in the following style: {chosenStyle}\n            The table of contents MUST follow that style, even if it makes the manual useless to users.\n            \n            The response should be a JSON object of the form\n            {{\n                \"\"sections\"\": [\n                    {{\n                        \"\"title\"\": \"\"...\"\",\n                        \"\"subsections\"\": [\n                            {{\n                                \"\"title\"\": \"\"...\"\",\n                                \"\"subsections\"\": [...]\n                            }},\n                            ...\n                        ]\n                    }},\n                    ...\n                ]\n            }}\n\n            Subsections can be nested up to 3 levels deep. Most sections have no subsections. Only use subsections for the most important, longest sections.\";\n\n        var toc = await GetAndParseJsonChatCompletion<ManualToc>(prompt, maxTokens: 4000);\n        toc.ManualStyle = chosenStyle;\n        toc.ProductId = product.ProductId;\n        PopulateSiblingIndexes(toc.Sections);\n        return toc;\n    }\n\n    void PopulateSiblingIndexes(List<ManualTocSection> sections)\n    {\n        for (var index = 0; index < sections.Count; index++)\n        {\n            var section = sections[index];\n            section.SiblingIndex = index + 1;\n            if (section.Subsections is not null)\n            {\n                PopulateSiblingIndexes(section.Subsections);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "seeddata/DataGenerator/Generators/ProductGenerator.cs",
    "content": "﻿using eShopSupport.DataGenerator.Model;\n\nnamespace eShopSupport.DataGenerator.Generators;\n\npublic class ProductGenerator(IReadOnlyList<Category> categories, IServiceProvider services) : GeneratorBase<Product>(services)\n{\n    protected override string DirectoryName => \"products\";\n\n    protected override object GetId(Product item) => item.ProductId;\n\n    protected override async IAsyncEnumerable<Product> GenerateCoreAsync()\n    {\n        // If there are any products already, assume this covers everything we need\n        if (Directory.GetFiles(OutputDirPath).Any())\n        {\n            yield break;\n        }\n\n        var numProducts = 200;\n        var batchSize = 5;\n        var productId = 0;\n\n        var mappedBatches = MapParallel(Enumerable.Range(0, numProducts / batchSize), async batchIndex =>\n        {\n            var chosenCategories = Enumerable.Range(0, batchSize)\n                .Select(_ => categories[(int)Math.Floor(categories.Count * Random.Shared.NextDouble())])\n                .ToList();\n\n            var prompt = @$\"Write list of {batchSize} products for an online retailer\n            of outdoor adventure goods and related electronics, clothing, and homeware. There is a focus on high-tech products. They match the following category/brand pairs:\n            {string.Join(Environment.NewLine, chosenCategories.Select((c, index) => $\"- product {(index + 1)}: category {c.Name}, brand: {c.Brands[Random.Shared.Next(c.Brands.Length)]}\"))}\n\n            Model names are up to 50 characters long, but usually shorter. Sometimes they include numbers, specs, or product codes.\n            Example model names: \"\"iGPS 220c 64GB\"\", \"\"Nomad Camping Stove\"\", \"\"UX Polarized Sunglasses (Womens)\"\", \"\"40L Backpack, Green\"\"\n            Do not repeat the brand name in the model name.\n\n            The description is up to 200 characters long and is the marketing text that will appear on the product page.\n            Include the key features and selling points.\n\n            The result should be JSON form {{ \"\"products\"\": [{{ \"\"id\"\": 1, \"\"brand\"\": \"\"string\"\", \"\"model\"\": \"\"string\"\", \"\"description\"\": \"\"string\"\", \"\"price\"\": 123.45 }}] }}.\";\n\n            var response = await GetAndParseJsonChatCompletion<Response>(prompt, maxTokens: 200 * batchSize);\n            var batchEntryIndex = 0;\n            foreach (var p in response.Products!)\n            {\n                var category = chosenCategories[batchEntryIndex++];\n                p.CategoryId = category.CategoryId;\n            }\n\n            return response.Products;\n        });\n\n        await foreach (var batch in mappedBatches)\n        {\n            foreach (var p in batch)\n            {\n                p.ProductId = ++productId;\n                yield return p;\n            }\n        }\n    }\n\n    class Response\n    {\n        public List<Product>? Products { get; set; }\n    }\n}\n"
  },
  {
    "path": "seeddata/DataGenerator/Generators/TicketGenerator.cs",
    "content": "﻿using eShopSupport.DataGenerator.Model;\n\nnamespace eShopSupport.DataGenerator.Generators;\n\npublic class TicketGenerator(IReadOnlyList<Product> products, IReadOnlyList<Category> categories, IReadOnlyList<Manual> manuals, IServiceProvider services) : GeneratorBase<Ticket>(services)\n{\n    protected override string DirectoryName => \"tickets/enquiries\";\n\n    protected override object GetId(Ticket item) => item.TicketId;\n\n    protected override async IAsyncEnumerable<Ticket> GenerateCoreAsync()\n    {\n        // If there are any tickets already, assume this covers everything we need\n        if (Directory.GetFiles(OutputDirPath).Any())\n        {\n            yield break;\n        }\n\n        var numTickets = 500;\n        var batchSize = 10;\n        var ticketId = 0;\n\n        string[] situations = [\n            \"asking about a particular usage scenario before purchase\",\n            \"asking a specific technical question about the product's capabilities\",\n            \"needs information on the product's suitability for its most obvious use case\",\n            \"unable to make the product work in one particular way\",\n            \"thinks the product doesn't work at all\",\n            \"can't understand how to do something\",\n            \"has broken the product\",\n            \"needs reassurance that the product is behaving as expected\",\n            \"wants to use the product for a wildly unexpected purpose, but without self-awareness and assumes it's reasonable\",\n            \"incredibly fixated on one minor, obscure detail (before or after purchase), but without self-awareness that they are fixated on an obscure matter. Do not use the word 'fixated'.\",\n            \"a business-to-business enquiry from another retailer who stocks the product and has their own customer enquiries to solve\",\n        ];\n\n        string[] styles = [\n            \"polite\",\n            \"extremely jovial, as if trying to be best friends\",\n            \"formal\",\n            \"embarassed and thinks they are the cause of their own problem\",\n            \"not really interested in communicating clearly, only using a few words and assuming support can figure it out\",\n            \"demanding and entitled\",\n            \"frustrated and angry\",\n            \"grumpy, and trying to claim there are logical flaws in whatever the support agent has said\",\n            \"extremely brief and abbreviated, by a teenager typing on a phone while distracted by another task\",\n            \"extremely technical, as if trying to prove the superiority of their own knowledge\",\n            \"relies on extremely, obviously false assumptions, but is earnest and naive\",\n            \"providing almost no information, so it's impossible to know what they want or why they are submitting the support message\",\n        ];\n\n        while (ticketId < numTickets)\n        {\n            var numInBatch = Math.Min(batchSize, numTickets - ticketId);\n            var ticketsInBatch = await Task.WhenAll(Enumerable.Range(0, numInBatch).Select(async _ =>\n            {\n                var product = products[Random.Shared.Next(products.Count)];\n                var category = categories.Single(c => c.CategoryId == product.CategoryId);\n                var situation = situations[Random.Shared.Next(situations.Length)];\n                var style = styles[Random.Shared.Next(styles.Length)];\n                var manual = manuals.Single(m => m.ProductId == product.ProductId);\n                var manualExtract = ManualGenerator.ExtractFromManual(manual);\n\n                var prompt = @$\"You are creating test data for a customer support ticketing system.\n                    Write a message by a customer who has purchased, or is considering purchasing, the following:\n\n                    Product: {product.Model}\n                    Brand: {product.Brand}\n                    Category: {category.Name}\n                    Description: {product.Description}\n                    Random extract from manual: <extract>{manualExtract}</extract>\n\n                    The situation is: {situation}\n                    If applicable, they can ask for a refund/replacement/repair. However in most cases they\n                    are asking for information or help with a problem.\n\n                    The customer writes in the following style: {style}\n\n                    Create a name for the author, writing the message as if you are that person. The customer name\n                    should be fictional and random, and not based on the support enquiry itself. Do not use cliched\n                    or stereotypical names.\n\n                    Where possible, the message should refer to something specific about this product such as a feature\n                    mentioned in its description or a fact mentioned in the manual (but the customer does not refer\n                    to having read the manual).\n\n                    The message length may be anything from very brief (around 10 words) to very long (around 200 words).\n                    Use blank lines for paragraphs if needed.\n\n                    The result should be JSON form {{ \"\"customerFullName\"\": \"\"string\"\", \"\"message\"\": \"\"string\"\" }}.\";\n\n                var ticket = await GetAndParseJsonChatCompletion<Ticket>(prompt);\n                ticket.ProductId = product.ProductId;\n                ticket.CustomerSituation = situation;\n                ticket.CustomerStyle = style;\n                return ticket;\n            }));\n\n            foreach (var t in ticketsInBatch)\n            {\n                t.TicketId = ++ticketId;\n                yield return t;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "seeddata/DataGenerator/Generators/TicketSummaryGenerator.cs",
    "content": "﻿using eShopSupport.DataGenerator.Model;\nusing System.Text.Json;\nusing System.Text.Json.Serialization;\n\nnamespace eShopSupport.DataGenerator.Generators;\n\npublic class TicketSummaryGenerator(IReadOnlyList<Product> products, IReadOnlyList<TicketThread> threads, IServiceProvider services) : GeneratorBase<TicketThread>(services)\n{\n    protected override object GetId(TicketThread item) => item.TicketId;\n\n    protected override string DirectoryName => \"tickets/threads\";\n\n    protected override IAsyncEnumerable<TicketThread> GenerateCoreAsync()\n    {\n        var threadsNeedingSummaries = threads.Where(\n            thread => string.IsNullOrEmpty(thread.ShortSummary)\n                || string.IsNullOrEmpty(thread.LongSummary)\n                || !thread.TicketStatus.HasValue\n                || !thread.TicketType.HasValue);\n\n        return MapParallel(threadsNeedingSummaries, async thread =>\n        {\n            await GenerateSummaryAsync(thread);\n            return thread;\n        });\n    }\n\n    private async Task GenerateSummaryAsync(TicketThread thread)\n    {\n        // The reason for prompting to express satisfation in words rather than numerically, and forcing it to generate a summary\n        // of the customer's words before doing so, are necessary prompt engineering techniques. If it's asked to generate sentiment\n        // score without first summarizing the customer's words, then it scores the agent's response even when told not to. If it's\n        // asked to score numerically, it produces wildly random scores - it's much better with words than numbers.\n        string[] satisfactionScores = [\"AbsolutelyFurious\", \"VeryUnhappy\", \"Unhappy\", \"Disappointed\", \"Indifferent\", \"Pleased\", \"Happy\", \"Delighted\", \"UnspeakablyThrilled\"];\n\n        var product = products.Single(p => p.ProductId == thread.ProductId);\n        var prompt = $@\"You are part of a customer support ticketing system.\n            Your job is to write brief summaries of customer support interactions. This is to help support agents\n            understand the context quickly so they can help the customer efficiently.\n\n            Here are details of a support ticket.\n\n            Product: {product.Model}\n            Brand: {product.Brand}\n            Customer name: {thread.CustomerFullName}\n\n            The message log so far is:\n\n            {TicketThreadGenerator.FormatMessagesForPrompt(thread.Messages)}\n\n            Write these summaries:\n\n            1. A longer summary that is up to 30 words long, condensing as much distinctive information\n               as possible. Do NOT repeat the customer or product name, since this is known anyway.\n               Try to include what SPECIFIC questions/info were given, not just stating in general that questions/info were given.\n               Always cite specifics of the questions or answers. For example, if there is pending question, summarize it in a few words.\n               FOCUS ON THE CURRENT STATUS AND WHAT KIND OF RESPONSE (IF ANY) WOULD BE MOST USEFUL FROM THE NEXT SUPPORT AGENT.\n\n            2. A shorter summary that is up to 8 words long. This functions as a title for the ticket,\n               so the goal is to distinguish what's unique about this ticket.\n\n            3. A 10-word summary of the latest thing the CUSTOMER has said, ignoring any agent messages. Then, based\n               ONLY on that, score the customer's satisfaction using one of the following phrases ranked from worst to best:\n               {string.Join(\", \", satisfactionScores)}.\n               Pay particular attention to the TONE of the customer's messages, as we are most interested in their emotional state.\n\n            Both summaries will only be seen by customer support agents.\n\n            Respond as JSON in the following form: {{\n              \"\"longSummary\"\": \"\"string\"\",\n              \"\"shortSummary\"\": \"\"string\"\",\n              \"\"tenWordsSummarizingOnlyWhatCustomerSaid\"\": \"\"string\"\",\n              \"\"customerSatisfaction\"\": \"\"string\"\",\n              \"\"ticketStatus\"\": \"\"Open\"\"|\"\"Closed\"\",\n              \"\"ticketType\"\": \"\"Question\"\"|\"\"Idea\"\"|\"\"Complaint\"\"|\"\"Returns\"\"\n            }}\n\n            ticketStatus should be Open if there is some remaining work for support agents to handle, otherwise Closed.\n            ticketType must be one of the specified values best matching the ticket. Do not use any other value except the specified ones.\";\n\n        var response = await GetAndParseJsonChatCompletion<Response>(prompt);\n        thread.ShortSummary = response.ShortSummary;\n        thread.LongSummary = response.LongSummary;\n        thread.CustomerSatisfaction = null;\n        thread.TicketStatus = response.TicketStatus;\n        thread.TicketType = response.TicketType;\n\n        var satisfactionScore = Array.IndexOf(satisfactionScores, response.CustomerSatisfaction ?? string.Empty);\n        if (satisfactionScore > 0)\n        {\n            var satisfactionPercent = (int)(10 * ((double)satisfactionScore / (satisfactionScores.Length - 1)));\n            thread.CustomerSatisfaction = satisfactionPercent;\n        }\n    }\n\n    private class Response\n    {\n        public required string LongSummary { get; set; }\n        public required string ShortSummary { get; set; }\n        public string? CustomerSatisfaction { get; set; }\n\n        [JsonConverter(typeof(JsonStringEnumConverterWithFallback))]\n        public TicketStatus? TicketStatus { get; set; }\n\n        [JsonConverter(typeof(JsonStringEnumConverterWithFallback))]\n        public TicketType? TicketType { get; set; }\n    }\n\n    private class JsonStringEnumConverterWithFallback : JsonConverterFactory\n    {\n        public override bool CanConvert(Type typeToConvert)\n            => typeToConvert.IsEnum;\n\n        public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options)\n        {\n            var closedType = typeof(ErrorHandlingEnumConverter<>).MakeGenericType(typeToConvert);\n            return (JsonConverter?)Activator.CreateInstance(closedType);\n        }\n\n        private class ErrorHandlingEnumConverter<T> : JsonConverter<T> where T: struct\n        {\n            public override bool CanConvert(Type typeToConvert)\n                => typeToConvert.IsEnum;\n\n            public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType != JsonTokenType.String)\n                {\n                    return default;\n                }\n\n                var enumString = reader.GetString();\n                return Enum.TryParse<T>(enumString, ignoreCase: true, out var result)\n                    ? result\n                    : default;\n            }\n\n            public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)\n                => throw new NotImplementedException();\n        }\n    }\n}\n"
  },
  {
    "path": "seeddata/DataGenerator/Generators/TicketThreadGenerator.cs",
    "content": "﻿using eShopSupport.DataGenerator.Model;\nusing System.Text;\nusing System.ComponentModel;\nusing System.Numerics.Tensors;\nusing Microsoft.Extensions.AI;\n\nnamespace eShopSupport.DataGenerator.Generators;\n\npublic class TicketThreadGenerator(IReadOnlyList<Ticket> tickets, IReadOnlyList<Product> products, IReadOnlyList<Manual> manuals, IServiceProvider services) : GeneratorBase<TicketThread>(services)\n{\n    private readonly IEmbeddingGenerator<string, Embedding<float>> embedder = new LocalTextEmbeddingGenerator();\n\n    protected override object GetId(TicketThread item) => item.TicketId;\n\n    protected override string DirectoryName => \"tickets/threads\";\n\n    protected override IAsyncEnumerable<TicketThread> GenerateCoreAsync()\n    {\n        // Skip the ones we already have\n        var threadsToGenerate = tickets.Where(t => !File.Exists(GetItemOutputPath(t.TicketId.ToString()))).ToList();\n        return MapParallel(threadsToGenerate, GenerateThreadAsync);\n    }\n\n    private async Task<TicketThread> GenerateThreadAsync(Ticket ticket)\n    {\n        var messageId = 0;\n        var thread = new TicketThread\n        {\n            TicketId = ticket.TicketId,\n            ProductId = ticket.ProductId,\n            CustomerFullName = ticket.CustomerFullName,\n            Messages = [new TicketThreadMessage { AuthorRole = Role.Customer, MessageId = ++messageId, Text = ticket.Message }]\n        };\n        var product = products.Single(p => p.ProductId == ticket.ProductId);\n\n        // Assume there's a 1-in-3 chance that any message is the last one in the thread\n        // (including the first one, so we might not need to generate any more).\n        // So the number of messages in a thread is geometrically distributed with p = 1/3.\n        const double p = 1.0 / 3.0;\n        var maxMessagesInThread = Math.Floor(Math.Log(1 - Random.Shared.NextDouble()) / Math.Log(1 - p));\n\n        for (var i = 0; i < maxMessagesInThread; i++)\n        {\n            var lastMessageRole = thread.Messages.Last().AuthorRole;\n            var messageRole = lastMessageRole switch\n            {\n                Role.Customer => Role.Assistant,\n                Role.Assistant => Role.Customer,\n                _ => throw new NotImplementedException(),\n            };\n\n            var response = messageRole switch\n            {\n                Role.Customer => await GenerateCustomerMessageAsync(product, ticket, thread.Messages),\n                Role.Assistant => await GenerateAssistantMessageAsync(product, ticket, thread.Messages, manuals),\n                _ => throw new NotImplementedException(),\n            };\n\n            thread.Messages.Add(new TicketThreadMessage { MessageId = ++messageId, AuthorRole = messageRole, Text = response.Message });\n\n            if (response.ShouldClose)\n            {\n                break;\n            }\n        }\n\n        return thread;\n    }\n\n    private async Task<Response> GenerateCustomerMessageAsync(Product product, Ticket ticket, IReadOnlyList<TicketThreadMessage> messages)\n    {\n        var prompt = $@\"You are generating test data for a customer support ticketing system. There is an open ticket as follows:\n        \n        Product: {product.Model}\n        Brand: {product.Brand}\n        Customer name: {ticket.CustomerFullName}\n\n        The message log so far is:\n\n        {FormatMessagesForPrompt(messages)}\n\n        Generate the next reply from the customer. You may do any of:\n\n        - Supply more information as requested by the support agent\n        - Say you did what the support agent suggested and whether or not it worked\n        - Confirm that your enquiry is now resolved and you accept the resolution\n        - Complain about the resolution\n        - Say you need more information\n\n        Write as if you are the customer. This customer ALWAYS writes in the following style: {ticket.CustomerStyle}.\n\n        Respond in the following JSON format: {{ \"\"message\"\": \"\"string\"\", \"\"shouldClose\"\": bool }}.\n        Indicate that the ticket should be closed if, as the customer, you feel the ticket is resolved (whether or not you are satisfied).\n\";\n\n        return await GetAndParseJsonChatCompletion<Response>(prompt);\n    }\n\n    private async Task<Response> GenerateAssistantMessageAsync(Product product, Ticket ticket, IReadOnlyList<TicketThreadMessage> messages, IReadOnlyList<Manual> manuals)\n    {\n        var prompt = $@\"You are a customer service agent working for AdventureWorks, an online retailer. You are responding to a customer\n        enquiry about the following product:\n\n        Product: {product.Model}\n        Brand: {product.Brand}\n\n        The message log so far is:\n\n        {FormatMessagesForPrompt(messages)}\n\n        Your job is to provide the next message to send to the customer, and ideally close the ticket. Your goal is to help resolve their enquiry, which might include:\n\n        - Providing information or technical support\n        - Recommending a return or repair, if compliant with policy below\n        - Closing off-topic enquiries\n\n        You must first decide if you have enough information, and if not, either ask the customer for more details or search for information\n        in the product manual using the configured tool. Don't repeat information that was already given earlier in the message log.\n\n        Our policy for returns/repairs is:\n        - Returns are allowed within 30 days if the product is unused\n        - Defective products may be returned within 1 year of purchase for a refund\n        - There may be other warranty or repair options provided by the manufacturer, as detailed in the manual\n        Returns may be initiated at https://northernmountains.example.com/support/returns\n\n        You ONLY give information based on the product details and manual. If you cannot answer based on the provided context, say that you don't know.\n        Whenever possible, give your answer as a quote from the manual, for example saying \"\"According to the manual, ...\"\".\n        If needed, refer the customer to the manufacturer's support contact detail in the user manual, if any.\n\n        You refer to yourself only as \"\"AdventureWorks Support\"\", or \"\"Support team\"\".\n\n        Respond in the following JSON format: {{ \"\"message\"\": \"\"string\"\", \"\"shouldClose\"\": bool }}.\n        Indicate that the ticket should be closed only if the customer has confirmed it is resolved.\n        It's OK to give very short, 1-sentence replies if applicable.\n        \";\n\n        var manual = manuals.Single(m => m.ProductId == product.ProductId);\n        var tools = new AssistantTools(embedder, manual);\n        var searchManual = AIFunctionFactory.Create(tools.SearchUserManualAsync);\n\n        return await GetAndParseJsonChatCompletion<Response>(prompt, tools: [searchManual]);\n    }\n\n    public static string FormatMessagesForPrompt(IReadOnlyList<TicketThreadMessage> messages)\n    {\n        var sb = new StringBuilder();\n        foreach (var message in messages)\n        {\n            sb.AppendLine($\"<message role=\\\"{message.AuthorRole}\\\">{message.Text}</message>\");\n        }\n        return sb.ToString();\n    }\n\n    private class Response\n    {\n        public required string Message { get; set; }\n        public bool ShouldClose { get; set; }\n    }\n\n    private class AssistantTools(IEmbeddingGenerator<string, Embedding<float>> embedder, Manual manual)\n    {\n        [Description(\"Searches for information in the product's user manual.\")]\n        public async Task<string> SearchUserManualAsync([Description(\"text to look for in user manual\")] string query)\n        {\n            // Obviously it would be more performant to chunk and embed each manual only once, but this is simpler for now\n            var chunks = SplitIntoChunks(manual.MarkdownText, 200).ToList();\n            var embeddings = await embedder.GenerateAsync(chunks);\n            var candidates = chunks.Zip(embeddings);\n            var queryEmbedding = (await embedder.GenerateAsync([query])).Single();\n\n            var closest = candidates\n                .Select(c => new { Text = c.First, Similarity = TensorPrimitives.CosineSimilarity(c.Second.Vector.Span, queryEmbedding.Vector.Span) })\n                .OrderByDescending(c => c.Similarity)\n                .Take(3)\n                .Where(c => c.Similarity > 0.6f)\n                .ToList();\n\n            if (closest.Any())\n            {\n                return string.Join(Environment.NewLine, closest.Select(c => $\"<snippet_from_manual>{c.Text}</snippet_from_manual>\"));\n            }\n            else\n            {\n                return \"The manual contains no relevant information about this\";\n            }\n        }\n\n        // Note: this is not very efficient. Consider using a chunking library.\n        private IEnumerable<string> SplitIntoChunks(string markdownText, int maxLength, SeparatorMode mode = SeparatorMode.Paragraph)\n        {\n            string[] separators = mode switch\n            {\n                SeparatorMode.Paragraph => [\"\\n\\n\", \"\\r\\n\\r\\n\"],\n                SeparatorMode.Sentence => [\". \"],\n                SeparatorMode.Word => [\" \"],\n                _ => throw new NotImplementedException()\n            };\n            var currentChunk = string.Empty;\n            var blocks = markdownText.Split(separators, StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);\n            for (var blockIndex = 0; blockIndex < blocks.Length; blockIndex++)\n            {\n                var block = blocks[blockIndex];\n                if (currentChunk.Length + block.Length <= maxLength)\n                {\n                    if (!string.IsNullOrEmpty(currentChunk))\n                    {\n                        currentChunk += separators.First();\n                    }\n\n                    currentChunk += block;\n                }\n                else\n                {\n                    if (currentChunk.Length > 0)\n                    {\n                        yield return currentChunk;\n                        currentChunk = string.Empty;\n                    }\n\n                    if (block.Length <= maxLength)\n                    {\n                        currentChunk = block;\n                    }\n                    else\n                    {\n                        // This block alone is too big to fit in one chunk, so use a narrower split\n                        SeparatorMode? nextMode = mode switch\n                        {\n                            SeparatorMode.Paragraph => SeparatorMode.Sentence,\n                            SeparatorMode.Sentence => SeparatorMode.Word,\n                            _ => null\n                        };\n\n                        if (nextMode.HasValue)\n                        {\n                            foreach (var chunk in SplitIntoChunks(block, maxLength, nextMode.Value))\n                            {\n                                yield return chunk;\n                            }\n                        }\n                        else\n                        {\n                            // Even a single word is too long\n                            for (var pos = 0; pos < block.Length;)\n                            {\n                                var chunkLength = Math.Min(maxLength, block.Length - pos);\n                                yield return block.Substring(pos, chunkLength);\n                                pos += chunkLength;\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (currentChunk.Length > 0)\n            {\n                yield return currentChunk;\n            }\n        }\n\n        private enum SeparatorMode { Paragraph, Sentence, Word }\n    }\n}\n"
  },
  {
    "path": "seeddata/DataGenerator/Model/Category.cs",
    "content": "﻿namespace eShopSupport.DataGenerator.Model;\n\npublic class Category\n{\n    public int CategoryId { get; set; }\n    public required string Name { get; set; }\n    public required string[] Brands { get; set; }\n}\n"
  },
  {
    "path": "seeddata/DataGenerator/Model/EvalQuestion.cs",
    "content": "﻿namespace eShopSupport.DataGenerator.Model;\n\npublic class EvalQuestion\n{\n    public int QuestionId { get; set; }\n\n    public int? ProductId { get; set; }\n\n    public required string Question { get; set; }\n\n    public required string Answer { get; set; }\n\n    public required string VerbatimQuoteFromManual { get; set; }\n}\n"
  },
  {
    "path": "seeddata/DataGenerator/Model/Manual.cs",
    "content": "﻿namespace eShopSupport.DataGenerator.Model;\n\npublic class Manual\n{\n    public int ProductId { get; set; }\n    public required string MarkdownText { get; set; }\n}\n"
  },
  {
    "path": "seeddata/DataGenerator/Model/ManualPdf.cs",
    "content": "﻿namespace eShopSupport.DataGenerator.Model;\n\npublic class ManualPdf\n{\n    public int ProductId { get; set; }\n    public required string LocalPath { get; set; }\n}\n"
  },
  {
    "path": "seeddata/DataGenerator/Model/ManualToc.cs",
    "content": "﻿namespace eShopSupport.DataGenerator.Model;\n\npublic class ManualToc\n{\n    public int ProductId { get; set; }\n\n    public string? ManualStyle { get; set; }\n\n    public required List<ManualTocSection> Sections { get; set; }\n}\n\npublic class ManualTocSection\n{\n    public int SiblingIndex { get; set; }\n\n    public required string Title { get; set; }\n\n    public List<ManualTocSection>? Subsections { get; set; }\n}\n"
  },
  {
    "path": "seeddata/DataGenerator/Model/Product.cs",
    "content": "﻿namespace eShopSupport.DataGenerator.Model;\n\npublic class Product\n{\n    public int CategoryId { get; set; }\n\n    public int ProductId { get; set; }\n\n    public string? Brand { get; set; }\n\n    public required string Model { get; set; }\n\n    public required string Description { get; set; }\n\n    public decimal Price { get; set; }\n}\n"
  },
  {
    "path": "seeddata/DataGenerator/Model/Role.cs",
    "content": "﻿namespace eShopSupport.DataGenerator.Model;\n\npublic enum Role { Customer, Assistant };\n"
  },
  {
    "path": "seeddata/DataGenerator/Model/Ticket.cs",
    "content": "﻿namespace eShopSupport.DataGenerator.Model;\n\npublic class Ticket\n{\n    public int TicketId { get; set; }\n\n    public int ProductId { get; set; }\n\n    public required string CustomerFullName { get; set; }\n\n    public required string Message { get; set; }\n\n    public string? CustomerSituation { get; set; }\n\n    public string? CustomerStyle { get; set; }\n}\n"
  },
  {
    "path": "seeddata/DataGenerator/Model/TicketThread.cs",
    "content": "﻿using System.Text.Json.Serialization;\n\nnamespace eShopSupport.DataGenerator.Model;\n\npublic class TicketThread\n{\n    public int TicketId { get; set; }\n\n    public int ProductId { get; set; }\n\n    public required string CustomerFullName { get; set; }\n\n    public required List<TicketThreadMessage> Messages { get; set; }\n\n    public string? ShortSummary { get; set; }\n\n    public string? LongSummary { get; set; }\n\n    public int? CustomerSatisfaction { get; set; }\n\n    [JsonConverter(typeof(JsonStringEnumConverter))]\n    public TicketStatus? TicketStatus { get; set; }\n\n    [JsonConverter(typeof(JsonStringEnumConverter))]\n    public TicketType? TicketType { get; set; }\n}\n\npublic enum TicketStatus\n{\n    Open,\n    Closed,\n}\n\npublic enum TicketType\n{\n    Question,\n    Idea,\n    Complaint,\n    Returns,\n}\n"
  },
  {
    "path": "seeddata/DataGenerator/Model/TicketThreadMessage.cs",
    "content": "﻿namespace eShopSupport.DataGenerator.Model;\n\npublic class TicketThreadMessage\n{\n    public int MessageId { get; set; }\n\n    public required Role AuthorRole { get; set; }\n\n    public required string Text { get; set; }\n}\n"
  },
  {
    "path": "seeddata/DataGenerator/Program.cs",
    "content": "﻿using eShopSupport.DataGenerator;\nusing eShopSupport.DataGenerator.Generators;\nusing Microsoft.Extensions.Configuration;\nusing Microsoft.Extensions.Hosting;\n\nvar builder = Host.CreateApplicationBuilder(args);\nbuilder.Configuration.AddJsonFile(\"appsettings.json\");\nbuilder.Configuration.AddJsonFile(\"appsettings.Local.json\", optional: true);\nbuilder.AddOpenAIChatCompletion(\"chatcompletion\");\n\nvar services = builder.Build().Services;\n\nvar categories = await new CategoryGenerator(services).GenerateAsync();\nConsole.WriteLine($\"Got {categories.Count} categories\");\n\nvar products = await new ProductGenerator(categories, services).GenerateAsync();\nConsole.WriteLine($\"Got {products.Count} products\");\n\nvar manualTocs = await new ManualTocGenerator(categories, products, services).GenerateAsync();\nConsole.WriteLine($\"Got {manualTocs.Count} manual TOCs\");\n\nvar manuals = await new ManualGenerator(categories, products, manualTocs, services).GenerateAsync();\nConsole.WriteLine($\"Got {manuals.Count} manuals\");\n\nvar manualPdfs = await new ManualPdfConverter(products, manuals).ConvertAsync();\nConsole.WriteLine($\"Got {manualPdfs.Count} PDFs\");\n\nvar tickets = await new TicketGenerator(products, categories, manuals, services).GenerateAsync();\nConsole.WriteLine($\"Got {tickets.Count} tickets\");\n\nvar ticketThreads = await new TicketThreadGenerator(tickets, products, manuals, services).GenerateAsync();\nConsole.WriteLine($\"Got {ticketThreads.Count} threads\");\n\nvar summarizedThreads = await new TicketSummaryGenerator(products, ticketThreads, services).GenerateAsync();\nConsole.WriteLine($\"Got {summarizedThreads.Count} thread summaries\");\n\nvar evalQuestions = await new EvalQuestionGenerator(products, categories, manuals, services).GenerateAsync();\nConsole.WriteLine($\"Got {evalQuestions.Count} evaluation questions\");\n"
  },
  {
    "path": "seeddata/DataGenerator/appsettings.json",
    "content": "{\n  // REMEMBER NOT TO COMMIT YOUR API KEYS TO SOURCE CONTROL\n  // To reduce the risk, copy this file as appsettings.Local.json and make your changes there,\n  // since that file overrides anything configured here and will be ignored by Git.\n  \"ConnectionStrings\": {\n    //\"chatcompletion\": \"Endpoint=https://TODO.openai.azure.com/;Key=TODO;Deployment=TODO\"\n  }\n}\n"
  },
  {
    "path": "seeddata/dev/categories.json",
    "content": "[\n  {\n    \"CategoryId\": 1,\n    \"Name\": \"Solar Power\",\n    \"NameEmbeddingBase64\": \"SabWv7X47T8/yLw\\u002B9FtpP3Tzpj7DYZM/yAmSP2rGgb9FhIc\\u002Bzk8aP0LTqz8WMbe/YKWmO6o16T8bVYU/gRqDPjSqhD9jDRs/g/Sgv1sc6D4siCBAIk7\\u002BvwwTwb\\u002BWism\\u002BJ4jSP0jxurwMhLY\\u002Bn5Q1Pk2Ohb8rMCTADhzcvT7Ltb9a7Ym/bGfYPvSRUr4qm3y//leLvQamJ8D4ROy/VPfxPrURFr\\u002BZZjXAX2lUvkgwZz45FBLAAEn2PiCIMD/mW4C\\u002BwGy8P9ALPb\\u002BRW\\u002BU/MXk/v/jeEb8QUiE/eq5MPigjLD\\u002BYCZI/dyLnPzbBDUCzWDq\\u002Bmn67Pu3pCUDP3KrACiFsP4/zGEB6kZU\\u002BsfCqvp\\u002BBJT8dtVS/hA46vza2iT7cbGq9KfAzv0O\\u002BZL9ppaa/sYe6P0ezG8AdcLm/8Dj9v62crb9EjGY\\u002BmME0v1I/kr\\u002BiJEY/JamqP35vAEDI73o/xlWbP9vtsz/QKAlAhPabvzK8Jr13ORq/jonaP49lvL\\u002Bdh/u\\u002BH6vEPwpQ3b/6GAW/NnunQMZ0o73McZc/6JlnP7Slp74Hwji\\u002BT1Bov51/Xj5cwTY/eIaCPD77tr8f40G\\u002BVcbAPp3WDb8k/aW/mnkGQGKRn76OZtm\\u002BT2VNP1rcBMBgXiA/h6aNv5T7aj8KgTxA5u0YP0qSmT9Qn3O\\u002B9mQUQFYW\\u002Bz9RyZC\\u002BvmGvPzg8Ij9yGc6/iamTv4Q5Oz8BIyw/7okJPzj6hD\\u002BNLUq/k/S2P0SfpL4jEKo/4UV/PRVz1z7GKmPASHyaP41akr\\u002BbwyE/g4qpPxiZq7\\u002BygWw/6NhPveAZ7z\\u002BlZ68/kVdGv8a/rj8lYl0/wm42voRpnz6ALZo\\u002BSg2fvm6qmz\\u002BROxBA5HWgvyYqM0AdLA4/3Qs3wP6MAD9EaQu/lzxIPhhiFz/3vN8/T34ZQAx3xDy48te/iIcfQGNEB79GDWS/JJaivluF079Vbso/9rq8Pa2fkD9KnWQ/aleiv6fa4z6kb0S9mtVhv55f/z7deuq/INyfPqlobcCtUSM/di99Pnxgqj9Mc0G\\u002BCHUav\\u002BOdmr9yJhjAuZpNP4h53r/nL6Q\\u002BmO1Av6WfhL//HClAFuVUP8bNBL42Dvi/zFH7Pv4jpr\\u002Bq/wQ/1BOLPzQmlr92j7s/eMaUP1lrhcCkAKM/wRS1PlKrqD4ysNk/DnW0vhZZlj\\u002BAE9e/0x4LwJx7t8BSIgm/Vxk/v9o1UL\\u002BrJ3E/xh98v\\u002BzOdT8LLsi/J9nFv9DIqL86thpAqpdnv8TEKj5g66C/fDwnvnsGWT9CN1w/Kp2nv1jcIz741Rq/VCj4vl/1uD/6gG9AYDjcv7lMlz/Scpy/HoI4QFBEgz\\u002Bk6rc/8T1mv7vQfL\\u002B19x6/C9DCPpB9KL94dQQ/R06FPzxmFj/6FZ0/746Pv6xyOz6mUdY/SrJXP744\\u002BL/8pMM9RfJrP\\u002B26t7/hviQ\\u002BFporPqvzgT/0qfe//x0AQMIUfL8F9om/hdigvzitE0BypTo\\u002BUfIIwFNIW0D4Z0u9i\\u002ByWPo/6s7\\u002B4/\\u002B8\\u002BOnQyv2hAvb4BLXM/OOGwPuKpoL5JIms/N9thPtKZtT7AX5S/MIfmP9CuHL4gNya9qrFHP85E3r7hbGI/vDTCvAnunj88lae/cNP6vEJYCL/0Dt8\\u002BwLaRO7SBGb78KQo9vY/FvuQzJr4Qu0C/QfeDv9U5Q74Hf8Q\\u002BOBbdviBKBbwN6R5AvSqSP2qTs8B5qbM/JyAEv6hUY78IdNe/WeP0vQ4z6T/KY5U/UC6ZviB8lD9b/wnAYoTWPipDPL9cOJ0/hOMDP0zmzzwlXJ8\\u002B8e52vpWIRb5YhoI9QVQNQOKa2T5muF1Aa3aSv7RbbL4ppl8//hJ\\u002Bvx0pBUBWw5U9ROQBvzH8hL8lVgW\\u002BWk4Nvh6xzz4uLba\\u002BrzRgP8grJT9SQuS/t2O8PzUfkr\\u002B2WIa/s\\u002BsGQKwqQ7wzDcO\\u002Bu1qBP6OWKMBYfK49sHERwCyxNb9jTU2/OP9gvzgubLx\\u002BlgXAwIvAPRC9rb\\u002B4xK6\\u002BnnN7vx4QDcDccwQ//oOovwZAzz9pZP0\\u002BkeWdP3Zf4b96UGs/\"\n  },\n  {\n    \"CategoryId\": 10,\n    \"Name\": \"Lighting Solutions\",\n    \"NameEmbeddingBase64\": \"QpCAv3TUSr774zU/V3oVPlnoqz9yzxI/wfKQPWSZGD5sZi29\\u002BJXyPxzc1z7Aqvy8kN\\u002BYv/iE6D9nW0U/SMT4PZAFuz8apBQ//\\u002B66v8oRbL/WM5Q/kZdov6jbJcBOsp2/W8AzPtogGL\\u002Btnkg/pgDZv7wsPD1FfyjAGZSRv2g8LrwXtRs/auGcPpPBCz\\u002Bx/A2/LakXv\\u002BOUDr/Vvdy/ffNfv/zU6D983vm/8IATv8W93b\\u002ByIh\\u002B/Ui1vv4gr\\u002BjzyyUe/vdPbverpkb9WXq4/x2o5v0xJNb7W/5e9JkicPgYRFD9etac/OEMAQOR8rj\\u002BgK5M7AkaYvQNGIkDCyIPAgNIGQLjXYD6bp\\u002BU\\u002B9jaqPaY8XL9W3L0\\u002BvgkEP9ZR/L44n7y/dguKPkw7WL6235a/rfNAPfRxTL3Aetu/lUWnv11Fpb9YLR4/2sZVv37XXb80XtA\\u002BBNSKPgEQ4z8Pt2y//G3avcoeTT\\u002B7Hq4/i8mBv/J6Nj5T9PK/JxS\\u002Bv\\u002BKpnT1AZAbATGkzvuBLmb\\u002B\\u002Bl8i\\u002BfrbKQNBpOr33TrU9Z4bzPx5t7r9jKEs/Tz41v1JVrD7IGGw9tAGVv0Qb0D\\u002B44AG/WjYgv1D7Grw\\u002Bd1K\\u002BD5mcP0RfqD0B9oW/NaBrP4ysTb/uhqK/AMhCOm6yKkCQA0pA7B00vo4QlT92GbW\\u002BvghAP5Z0MECkE32/yxRbP5lLtD5gfjm/tdI1Py6hvL7Fsy6/zAydP0VUNj/AhIE8eLW8vTs0GUDnBVY/ovuDPnbbrD8z9\\u002BS/BvfMPgpD6z/whC0\\u002ByD9AQJHR679Rx02/aOBhPrRm9Dx0FYU/fkFDvrMijz\\u002BQZ1I/RpnOPxegKb8n6cE\\u002BAJDzP0bHkT8UH6E/wt2ev4B6akC2mYi/8EJawOE0Tz/mCMm/480jwDpiVr\\u002B8f3q/YqIzQBFmA0A4aOm9kqvlPxKnmj3t7Wa\\u002BP40Xv5RJlb\\u002BwVZE/mWgxP/GEIL90aAu\\u002BtikgP3ZBqj8ZNs\\u002B\\u002B4iAfP9aYnj8kd7O/vm0OQFve57\\u002BxlYG\\u002BaNvXPDX/vz/rYqU\\u002BPAtGvWEUP8DSqSnA2kuaPxYMEb8Sw5M/E\\u002BWGv66yvL6uOqu/4CkNQKj49r5SBEa/0qZCP5jT8DwOcaU\\u002BjIbWvwHvfb8GtFVAVlujPijfH8DufdY\\u002BK08Av6aBcT/YF2a\\u002Bg49gP4JQrT6jO/s\\u002BCgqzvyg0pMAsG\\u002BI/KpHFvqSLx7\\u002Bxcik/E5TIv\\u002Bwgxb7\\u002BqrC/F4UhwCif7T/igyNAbjW\\u002BPhaDMj8CVNO/gsTIPgZH975X/ia/JIWJv477y75uuMy/SunavUx01j4LqQ9AvHckwN9N0b5yyAY/z32NQEpAUj9cPZ091mDtvnQpSj1\\u002BbZy/KuwBv6tub78ibbY/Do2sP2Bxzj\\u002BipbU\\u002BAIZWPirIWb8YX9E/hyO7P4bsGsC8HmK\\u002BMmCtPi2Oxb/1WpA/bGHMvhQEXL7ULS6/DGCNP/H6lL53Zm8/QbdFP8E57T7\\u002BE12/kl2/v84lmz/ARJq80\\u002BDIv\\u002BrSor7Aq2i/OoJbP81RBMCy1g5AcDUFP/\\u002BtyD7cXDK9tjpLP29Iw74k1ce/Um8RQHbru78kS8I/gP1aPxJZmj/9aN8/wnYav3K9Kj\\u002B\\u002BJAu/oSQxv63vxr\\u002BalZY\\u002Ba00SP9Ls0z4fGpG\\u002BuMfev9b2V7/9\\u002Bak\\u002BY0znPtKanr\\u002B7SEe/nqiPvcQAer9HgLU9JzW7P/pCqMA0qhg/HBqQPGzsH8A6hxbAceSDP3UkFz\\u002B97eg/Di9ZP5wQtz5k4lDAklPpPuwj17/0xdM\\u002BkeGjPzrJmD1MSWY/uknnvxAWgb0Y4fe\\u002BKG3APhuqpD60SJNAeLojwH19Mb8SMW8/R/WLPxUfEL/nmoo\\u002B0W1\\u002BPzIp9T6OjhtAXURbP/FqHr8wJtk/wNjpPA7Hvj4RGH\\u002B/5T1zvrT0Fj/pOhw/jbqHP2ZNg79WZaO\\u002Bv4JnP2DgXr8XuIC\\u002BCDqzvqz8rL6/Awm/66wGv1k8LL8GHu8\\u002BTGc\\u002BP0ym4T0YuqA8q1Y6wO5M9j7\\u002BNoE/SsErvyhFFb57hhPAddbXPsCdXT1VKQFA\"\n  },\n  {\n    \"CategoryId\": 11,\n    \"Name\": \"Action Cameras\",\n    \"NameEmbeddingBase64\": \"wo32vn4K0L6oshG9jpCtv/RZjD9J8iNAOSvcPyyryj42aE\\u002B/73gDQPpfIT/JKQ2/qkMdvoKbAUDUUzA/TkQhPkvvzD/t\\u002B72\\u002BJYgwv3gEVT/cMqC/41ycv87\\u002BCUDY4yK9lNgcvxvYI7/Jtkc/IT9uv6ncI78xmhrAIslPPhASqL2gn\\u002BY/kVqIPlqggr6sll6/RvG0v51BAb85QjnAW8\\u002BEP7ZDoj7Txyk/pk0TPdOTBMDe21k\\u002BmlkMv\\u002BBCeD/nS8\\u002B/InwBP3xOub/udMA\\u002BF1oWwFyUMT\\u002BURBu/OpkRv8aFy79jC64\\u002BIPNbP0rN8D8z\\u002BPW\\u002B7R0iQIo/Yj8njoHAzC0BPr9Urb/n0bY/xxznPxaUmT2mz70/WlJYv4JM3r9sKo4/t0ApP0x2KD\\u002B/vgC/5mDKvhk7H78hwf6\\u002BNmhcv2yBG8DIUbA\\u002BqSqtv1TjkD\\u002BsgyU/ilI3Psfcjr9sukw/Uybnv\\u002BZW0T/gEXo/Dk5kv9jmuz9s5f6/uu\\u002B6PjA7wL/OQak\\u002BxuAkPkn61L5wULu\\u002BBPTkQG7MSr9gNK8\\u002BUrfKP1KjV78dRGc/RaiEv1uFSr\\u002B3pwe/5Cfdv0Cnvj/yA5g/mlnivpK66L1T8Ng\\u002B/ByNP0QJCz9Rvq\\u002B\\u002BO5iaP\\u002BLKx74Q7/\\u002B/rkmtPwrRKL8uaIU/\\u002BuCrvxSyj79IpK2/iR5NP0AfeUBW78c/Z4ZAP0qRsD1gcR6/UHHqvU\\u002Brhr8mS1U\\u002BvPS6P5Qpvj/p0BU/hvOXPpghsT4\\u002Bl7I\\u002BNKpWPqWm9z/Q7c\\u002B/rrjsvo4K\\u002Bz75UmO/AGyoPGp9wT4JFdW\\u002BQcxhPyTsDkBe8yY/CSbCP/Nbgj\\u002B\\u002BnIi\\u002BhzPcP3ZsLL91RY\\u002B/Z6mWPgSBzb/JOIS/N9Dovu628z8cp9e9om5QwCcqrj\\u002BoGO\\u002B/lYSDv2yitj/Kk5G/udkLv9ZhOL5oymy7asgcP4pOkT5ege\\u002B/pkMtP85QkL9SZe4\\u002B0vD3Piv3yb9O0FY/BZgtv6nguz7U3Bk9zsdlPWaSab4UxII/bCMiQI0\\u002BR7\\u002BQ3hM9jyxWvoR2mT8UzC\\u002B9ejNLP3aRNr90ape9GVJpv\\u002BU4x79kaNI/CZJav8Y12b7SBeI\\u002BOD8vPzXnsb8AMS/AsiE\\u002BPwUY2L\\u002BwYaM/qtngvjFOhz\\u002Bs2DBA7KADvy2V6L8i35q\\u002Bu2JEvzgwTj9zOx/ALJ2QPIIqk7/gM2u8qPLrP2yswcAeuh8\\u002BQKf2v9cZ2D4obek9eND8v0KhIL4YTiQ9xmhmP3znBUACm0BAZ23Yv9TuIz4IDy0\\u002Bg2vcPqMa3D/k6ye/JXHBP7LmsL/4hAe/szVIvwARSj91Bbs\\u002BGpMQwGWFVz/b8Sm/DL6KQC7erT9c/Pw/Rj7jPwDwKbg5S60/pKPnv1BCQr8cBE\\u002B9vNJ8v5B5/j/ct9E/md8RPlSRwr/5n26\\u002BunP2vhDYmD8DsRPAnxiTP0DFob6AkZi/qMTdP3Dlib/XfkPAcCiMP3GUG742Kq8\\u002Bb0Fuvyz2TT1mUsE/UCRdPBbYTj9Ox90\\u002BcZqWP\\u002BeJlL/KuKo9XpwzP1bMA8Ady0NAOEwRvg6OxD5HePa/QCeUP0ntlT8twMI9dm8UQPbOBj6E1Xs\\u002BuVP2Pzx0VD92Y3M/Eo2dvzzLA8BRU6\\u002B/jE0svkEY6T5uhnG/c/U\\u002BPgSqez\\u002BoDo2/R/loP4Hm2r9qI\\u002BC9Gy5Zv35MPT8Z\\u002BaA\\u002BrDK9v6RULT0FkWI/vkdgvm0vqMBw0ju/WhotPxSTe7\\u002BOsqm/jfAFvxqiAUBOHuY9\\u002B93xPQ4lA0ADmLC/tOjOPxdrn77Ldak//\\u002BBxv5A8lD8WS4Y/DUYWP3MYIUD4UgHAF/yYP8KokT9sc8M/B/BDv3LO/76AaNk6a7KSvx23DL/ilgY/BqDAv5qUHz\\u002BtvO2/aCKfPlNAoD3AT4W7Bv\\u002BiP6dxUT92CLC\\u002Bwua\\u002Bvz3tbz8oNz2/ed0Zv4/Q1D8wSje/46qUP\\u002BPzKL9oVGk96fucPqJBCcAeT74/fy5xPtBNub9C9ly/e1kNP6AfBkDS5Uw/jivcv6T/kj/sSha/hNNQvTe1sj8Itu2/ojVvP89E47/l73a/\"\n  },\n  {\n    \"CategoryId\": 12,\n    \"Name\": \"Excavation\",\n    \"NameEmbeddingBase64\": \"mpmVvwS4nj94zT8/INQJP7ODyL4ks0O/Fpu8viObHb80bDq/wqinvloAYz/A/xrAxoKyPVZB1z9pIJ892EMLP6/PWr\\u002Bc3QFA9qltP6a1tr/C75w/JDSiv2mBiD99ae2/e8q7vy5Mnj/zJ2K/jM6XvwrVBz7tOAHAIuKFvqCOQb4WVLw/7aKePlibmD\\u002BQuvs/Luu3v1MLm774zSC/BEWJP2b63z4QNkM/6I4Tv4Zxs780XnI\\u002BvQTCvh\\u002BJXz6YUIS/WLVSP7ynOL7V6h8/6Fk7v7q0lj6ObeQ9PP7aPMA0Fz\\u002B9zuM/F5ngPrI1Cj\\u002Bm\\u002B7k8jJvqP8B6tz6rFErAPMqHPlLSbz8YOBm\\u002B5PkyvxsRqr8pq3E/hpxHP4X7IT8X0lk\\u002BwIzqu5b3tz7Wxrs/px1FP6Tp9768AEA/vNyKv47yHb\\u002B22pg/sElSPzvnib0ejjg/lIjDvzRcWr6laIy9wM5MPcAITj5yGeQ/CBNbPzDvo77ophG/xuFqP\\u002BDuMb\\u002BipKu\\u002Bph5jv1h19z9QkpC\\u002ByuPEQAgMc7/1TrM/HDwXP52yI76gyxA/HhkcPp1BM77XS6i\\u002Bzv\\u002BTvmI9CT8DaPw\\u002BYkDrPf4o0r\\u002Bj6wG\\u002BDl8QPpAoNj\\u002BAbC8/GoKpPkmOY7\\u002Bvd3C\\u002BxoZ/vvQEgDzKwps/3GuFv6IDkL0CAOe9xOaIPgSA\\u002Bj9Q0T0/g8TfPjX16L7Iy8W/bDjcvraxLT9ceBu/O/e9P0f9\\u002BD6Y8Hu\\u002BAj99vwA3hj00jMK/kLJIv7iyZj8jGbC/7Yeuv1kQgj/Etqk\\u002BrI26vhC0lL7iG4y/KBTHvxAL0bxTbABA8nrXPj7dnz/rNAm/\\u002BBxXv5OBFb/yNIa/d1Hivk\\u002BKnD3\\u002BMwm/kVWGv9ULHUCR5wFA5CCwv2wRgL9FnVA\\u002BkrEFP5mNVr9OLIo/FzQzP\\u002Bo9Vr\\u002BC7em\\u002BLkPGP4g0yD1EAsy/\\u002BCt4PiBgO78v\\u002BnM/5t8dP9ZryL8ariq/ozilP/7l\\u002B73nPJu/GS2Xvl6Axz7KhUo/lItGPph1lj12Rkk/BEBtv08jS7/Q0y4/siQCP7Zhqz7xPZw/TB/5v2DLZj/SOTC9AXYivwHVLr9oIFQ8cu5ZP1bimz9ebcy\\u002BbkKAPwQ2x76TzQg\\u002B6H6HPT4PFb9szEk/tHoFv8AWjj8hOmm/uDaxP7Z7Or8BuSK/JezCPp\\u002B/Lb9noeC/DaZ\\u002BPg6wqMDaPpq\\u002BRtiXP0yJOT9u2IU/7MTvvv5GRD8liO6\\u002BHEwSv/xJjL\\u002BYXL0/3MYZPZD/cjwpSaI\\u002B\\u002BHbIvndHGT/B6Sk/Gohxv94bbr/HaxC/5/gYP3ivjb1il5Y/tu8PwPb1/L8s/Ci\\u002BSA4rQKyFhD/qnaq9ZkSav9e3GT81zlu/Z70fPz3JQsDI6qS9XGaAvvYIsT8tt8M/rJhlPoyRZz57eoe/gMQbP23zjD80aQjACEyDPoBKN7wYN7m/lgLJv2Swuz8dlvW9YAQJP2aqBD/N8rE/CI4wPuwp2r9lPto\\u002BSqqrvKwe4L5Qu6C/MBBSv50K7L6moIG/cL4tP\\u002B80I78kKVQ/jdiPPiQfJL9BFGA/tGa7PUy7uL/BGp0/hrXmPnKAFr/MWvE\\u002BACK2v3dvrL0mGb2\\u002BjhNKPlBAZj9Mq5u/VUNDP6G/tz6oz5E9Aw92P1Q7Pz/a\\u002Blk//14ZP5ckpb7UHI4\\u002BpQEWvthTnb6G2Ck9YtEfvqq1ob8b248\\u002BzE4nvljulcCcNoA/1CeEP\\u002B\\u002BESb9qjoi/xNAiv6h5vjzOOOU/eE0rQActJj/VI0S\\u002BpAV3vgpBnj4OTRS/LnL/vNgwkD/y5IQ/rILLPnUdc7\\u002BoWAbAHgt0vh/Xnz\\u002BG8SFAhA6zPr5h2j8PYti\\u002BM5i/v5iQSr4FUV4/Tngiv0rDhr7oh8a7YhcJQLxMlL4Fk9k\\u002BAKmGP/h/nrvM\\u002BoE/Cp1jv7sJOr9wXA3AP0LIvk4xr79M25A/qhFdP7Lkf7\\u002BX31g/Wobgv8D9Zz\\u002BlI7y\\u002BoigivrvKXz\\u002B7Kpo\\u002BQmPkPez7Zj8I7Zs/Vvj\\u002BvlPIwr4KtVa9XBUIvUV1XD8I2ZA\\u002BQOjpPg14kb/p4pe/\"\n  },\n  {\n    \"CategoryId\": 13,\n    \"Name\": \"Portable Power\",\n    \"NameEmbeddingBase64\": \"dBdbv6/vUj9eVHQ/4cVcv2B/lTzwpdc\\u002BH2ARPyT/4j5eIYu\\u002BTY1jv4DxzD/FzeO\\u002BWFS0vId9YD/GHww/Prb1Pume7j\\u002BR0Aq\\u002B\\u002BQ9sv7lf0762JY8/se8LwHZfbr\\u002BRcB\\u002B\\u002BsYVKPw7lb78iw5o/NJC3Pkjj0T24RVrAkrcFvwyxs76yUrO/xTikPpgQFb4e\\u002Bwk/bQnSP4Xkcr8KeHO/JN5QvgWDzT4ollI\\u002BSGw\\u002BPlq0W77wig8\\u002Bdp\\u002Bqv5PTOb7yOpy/g49CQGynmb6y96A/6GIOPgRLs715KPO\\u002BWnSiPiimuz\\u002Bp2PY\\u002BPHaPP/Iyqj9hwge/ob0XP3KpJ0AaPlHA3yyLPzzkTz\\u002BRULQ/Cr6LPo42JD8AtPi8\\u002BE0Tv4AL9jxkr549d8Y8Pzpotj8Klgu/T6NgP6c8lr8fZam\\u002BkcfBvyyg5b2w8am\\u002BwqLovwLUg7\\u002BN0BU/eNB0v4x7fj9neXg/2DSrPLuunr/CVpA/4mQNwBRVZz8NacI\\u002Blo\\u002B\\u002BP\\u002BDT5r916ti/VBZbPSFF/r/eWPO/ojOtQFS3QL6ioY89pKS5PxlYur/4\\u002BLG/qGFwv2jBPj\\u002BagsM\\u002Bw5qCv7bBAr/DUgg\\u002BqNMsvnQgwb\\u002BIB0q/UL3cP5awBD64mH6/xuVsP8NAsb9sn6k\\u002BXjIUwFvDtj/0fuU/APQyv0Qi2D/Sd3G/3gTHP\\u002BYrDUBIuba\\u002Bypm6P2nysj3mCx09HKiuPRb62T48myM/HeeaPhKGgj9EhqC\\u002BvoX8Pybsvz\\u002BGsrU\\u002BAxOJPtHoHz\\u002B8tyTAoC3dPbqiwr5MjEs/0W88PvGPBb/OCvS\\u002BJ25fP5Gjqj9X5Ks/Bb6ev4Zbpz8j2nc//GisPzrqOj85jBC\\u002BfCCivnCNxz4mzHc/IEc5vxJboD8kKok/KMJPwGgTNj68Y5u\\u002BCnFQPzfn779AyVU8EgnUPmDxw77sE0G/GNqdP6gIiLwBvh8/eF\\u002BJP5ZaJcCg2Ei9\\u002Bc1Ev1O4KT8e9\\u002BC\\u002Bc1TBvsPyn76Q/q4/5z7qvqy5lr8NsVM/KkJ3QJCfD8CCJAVAI\\u002BBfPyZcGT/XVaC\\u002BtBUAvxq78r\\u002B2mHG/xUlNP/vnvr8tinY/cyt0vz/Xlr6Cabs/3iYnQJh8LD5dlOu/jZECPzD0X7\\u002BKisU\\u002BeLKBP2Dmrjs\\u002BtyxAog\\u002BQPnG2/b\\u002B4uK6/uJyJvnDG1zxksg0\\u002Bq\\u002B9vv0FSkz6\\u002Buh/A6rXrvlq/scDI70W/3kaUPBGDBD83unc\\u002B5cWNvxNMrD9\\u002BvpK\\u002BIs6tvyqNDb8YuCVAdiCyvz5lSb9F/LE/kG2mvxx/3z/ovKI/ccDGv9vUm79VACA/38sfP\\u002BgqmT8cWmY/MmF2PgDMeL97wZi/GxOLQPv7hr\\u002BO6cU/Ac0Kv4g6yT/EL/E\\u002BakQXv4y2xL8rK66\\u002BedY1vq2wy79jcAm\\u002B7ubjPsvApj8\\u002Bvke/XFURQHdZDD\\u002BcItK/dE5Av50wIb\\u002B4EA6\\u002BDPrAvxLEBr9\\u002Bv6k\\u002BVm6HP5QPBr\\u002BUwyy/7z26vyhqcj9AT6y/qDelvzCGEEA3UGS/iKxWPbhucr91Q14\\u002B1dndv9VN/L5UAdM\\u002B6LGlPtY87r5bNUY/AU0jP1CCKL4OqLY\\u002B\\u002B4qNPzOjEz8jjARAPvAbQP6b3r9N6vM/sOxhP8IQ1j5/iz\\u002B/VoJdvzGpJz9uLPU\\u002BRN01PXf/Gr8RiQm/kN\\u002BNvPxr4T\\u002B4o8E\\u002Bb2rpvs\\u002BSTb8i91g/TtrnP64SmrzMgp4/27Y3P\\u002BpNycDI9HA/EAS1vijPLL9ef6S/ZnoqP3d2Nj\\u002Bl13M/Dpm9vzTUlT9Hp\\u002BC/nE8fPwSA5L3AsKg/hIslP5mAyj59vJ0\\u002BXSPOv6ltc756Ri/AW3wjP5zrkr22b1BAPo4CwFLYcT\\u002BjQQM/5GOPPzc34z/ekVm9nAsPvkdKlr/gNRO/INQOQK9Exr/4PoQ\\u002B4kOhv1SOvr9uZF0\\u002BsgSsP8dGpr8\\u002Borm\\u002BOGx7P9dqX7/KfWy/wrzfP/2uE8Cj5O6\\u002B/ie3vzEdhb/AcxC7NBfvPbn6I7\\u002Bf3jy/3hqNPkUJkz/m6os\\u002BcAt5v0ZGb76OOtu\\u002BGXTfv7bmoD/n1Hq\\u002BedKmP19gy79FOi1A\"\n  },\n  {\n    \"CategoryId\": 14,\n    \"Name\": \"Backcountry Cookware\",\n    \"NameEmbeddingBase64\": \"Lt42wOzoY76es7w/mMYIwGmVlT9PiYW/3LJVP70ChT9j9yvApzKEwF7ACcDLknfAbanPv7kyIECWzRK/2rEGwORFfD8Ku5o/6rdyPxxRpj2nyRdAxp04wIZ7Fb8RDqu/QUrTP1JSKT\\u002BQQJG\\u002BKx9fv3KegMDOVhHBH8DCP\\u002B0glj4UEDy/2EkFvuJzqb76vBE/YUADvuOvqb/6shXAq39PQE3VJz/RfpA\\u002BR4vTPpqtMb2SGJo\\u002BdO1FPnjkyr9vfQC/PlDFQOHqCz8KUJI/ldnGvw2MUb92nV2\\u002BaYVJQCP7eUCEMk\\u002B\\u002BUKE8P9yK0D/qLrC/hh9jQP4o5T7cPR/BDs7tP1JUwj4c5sO90IzOPpSe4j9fSP8/xKo9viS2DT67i1Y/ziWgP6aEKUCB5gK/Wu9UP3gxUD9Tjh7AJ\\u002BouwFA\\u002BAEBUz9u/CNq6vpKxdz9O4bk9gnsJwPZpccC\\u002B5eq\\u002BJ6T3vpTAhUDp/yS/HFC1P6ImuL/RNxm\\u002BJkFPv1Gvn8BgOEXAEd1DQC\\u002BMTD8dtwM/WhwOQYmOJ8BJOP\\u002B\\u002Bkq8gQMhjP78a6tA/LgIbv/OwKT8iIQA/kB8WwJDJ6b\\u002BZ0tM/jX\\u002BhP4FMBsD3yRRAA/j1P4zcnb9CSfo/kCRmPFabvb\\u002Bev2s\\u002BQNx2v9zGGD99\\u002BTNAUCBGwPfVAkACzBe/SS3WPou8nEBIiwu/SSC6QDDHOT7cNwi\\u002Bu0Wfvmhd4b8YmKa9KMooQKMzB0Cbcou\\u002BSulGQLqcJb9KEzrAdJxAv/vDNUA4G4nA9arRPw\\u002BcAUCLkFk\\u002BXi3iP2Xv\\u002Bb/KbGHA3UOmP8SszT\\u002B6sF6/3cFivxShvz/ERG9AoJQGvuiZ6L11SgXAWSs/QFS4\\u002Bj/YaNS\\u002B\\u002BlFUv4A2WL0b2JE/aBXuwHa8Mj87DeI/DifQPkzHgz301dy9GEB/PgGPF8ASg4u/EnKJQPMpUj\\u002BxqDvACoGhv\\u002Bd7BcAtvo8/zrtsv3d0i78UOUO/PSbUP0D75D8YqGXABEtzP\\u002BO2jsCDTL0\\u002B8nxgQFQIBsB7VLC/EN2Hv7JnqD\\u002Bi\\u002BCk/Lvjcv52Cc79eTls/4tQmPxCRNMBl2hlAHEYywJrdhD8ELoo/vDXoQGqqjj96Oci\\u002BCCuIPewGOL4wW8M/N2kivsqhNj5TyzhA/pa9vwDZzL8pnaq/PkkBQJW3X0Ak3k\\u002B/TOOwv/yxvT8ZrYbAjpRkwHkYF8G7YIw/N6Iwvi6xLT6EsyG//FyovrVHBr\\u002B4OT8/EVCpP3bGBkAhZAtAaOspPgjn7D\\u002BTc/Y\\u002BWB0pvX8rK0DWFSZAfnW/vZrcGsCOPiE9yKufv7l3N7/83qI/Op9QwJQ00r8wRytAypfaQImatL8Jjt4/Uka/v6weub896Fo//Dbmv2UcrL/kadI/eNedP6CmJEA9VTtAziEzvzyctL/uE4\\u002B/6IO3P4IohD6xu0TAeAfFP5A1HD\\u002B2ASPAFExiwLy4M8BaUv8\\u002BnY\\u002Btvp6UN0D0d66\\u002BEnvRP2X4gD91Hrs\\u002B0YM1v5zAW74Amu6/cNAYQIqZAUCT22m/m4QNwF7GmL4G9DdAdi5lQPlVfD4pYJ09HLx7Pt1vJ8DsTV\\u002B/vApevwQ9zT\\u002BmG74\\u002B\\u002BHQBQPqCPb//YWc/IdkIwJYu4r\\u002BS9wLAUEcsQPHPsb8aDFs/yv/2PzioYUBeXUk/9FMewHUJyT8elqw/QLYNvXiA3Ty9QCxAURh1wIoVuj47rIFAIya6Px4WScFS\\u002B7Y/Y\\u002BM7vmAvibzk3jdAbR7SP0ZG7r7PdoRA0tn1v7djgz57ORVArxwmQFbnpj9503y/IPzkPp42u78zNts\\u002B4bARwCy9IEAlkS/AqDAwvrIFG0AG\\u002BeZApgtyPzjaNMBiHj89MKkTP5L1BT/JqRZA\\u002BtlPP9sAJkA5aCXAK7PPP2G07z8DWw5AtDxhQPfs5b8nOUC/FEYIQKbRir8bsXDA2ozMv18NZMAFmKs/pINmQJKqO7\\u002B/3LO/GkqawGfmoD/i2vI/ROO3vgVFQb43ywfAMxioPlZ8Uz\\u002BiWee/uOiawPY4hz6wOUTAms\\u002BVP0pQHj2UIoTANmXqP7kYHD/fUQnA\"\n  },\n  {\n    \"CategoryId\": 15,\n    \"Name\": \"Hydration Systems\",\n    \"NameEmbeddingBase64\": \"M8rpv0\\u002BgQT6oq8c/UYdnPueQWj4fKrO/qAUyQArPjz\\u002Bwhug\\u002Bu\\u002Botv3J1yb2noAjAB4RHPzKHhL5MMfs\\u002BEe\\u002BSv0s\\u002BxT8ajlBAOLVqv6CG3j8h0yY/QBoHwCoUOcAAqR3AoYlkvypwn70dGxU\\u002BsAinvSRQIL\\u002BKTIzAamrSvub0gT6mQs6\\u002BH\\u002BEWvzDKVD4RR0FAj9mqPhBiBL\\u002B97qu/bo/QvwKNzb5YyF0/fZ1Yvwm5jD/wbSO\\u002ByDm2v6BeGMCYvbA\\u002BoFxiP9PC2L\\u002Bz2ABA7FKXPviLhb9ZrwU/VtBdPzxZqj62P60\\u002BSP5aQHB3qr9deVHAYESdP9UzbD\\u002BynazAku0XQKcJWj/8B8A/3A5fv9AYBj\\u002BBN0JAM3qjPyScn7\\u002BaC1E/Fjm0voThCkD5c8E\\u002B6m\\u002BJvi60KT\\u002BusjY/MQfGPTqV8z5xKBBA8mo5wBgNHL3bAYq/lEmkvqtHGb\\u002BraCA/\\u002BjvUviTizj93lPa\\u002BsvqYv66/yb2EXqM/\\u002BoIXQBTW4b\\u002BCI3y/sggiPy7PSL\\u002Bv7Ps/ojLXQJgcij50W40/qpTIP6Ngh7/svrs82HfgvwFX/b4axrG/0CW2v0ByZT49Vwc\\u002BDbl9vgrDEkByTki/lgBpvnhUfj9yLtW\\u002BzWD3P2DQJL94X6S\\u002BYP2uv0tFJz\\u002BN7/Q/K5RHP/1\\u002BIb7vfYI/fFOKP\\u002Bx5TUA2MiPA1aXSPyaHPb/32qG/NELjvv4qvb/KqA0/60d1PjibCT8vDhHAWssNP5V/HEAJkCXAMDTPPSApN0BekKvASzaCv9CQF0BE7Ki\\u002BrwPSvxL28L921FE/5L0Av5hyFD\\u002BmO6o/au3MP7b4cD8SeZQ\\u002Bi2PLPwL01r7tAAzAceKTP3/BsL8cuYe/2VCZv8ODlEAsSQs/ID8EwA\\u002BNxD/xgRS\\u002BUtHKPtjl5j6In2O97N8IQJ\\u002BnLz5gsA6/mjQDQGdrCr8Jfmm/8qcsP2rwJ780tfA\\u002BlvHBPnPpiT9ld6k/hUqEP5S0J0Dsu3C/WcOkP8kTBL5IJE2/gDNBviNbg78IW3\\u002B/XkVnv4iJVb9C9NE\\u002Bvl2kvrQ89j1ZGre/bZpsv1ZJDr\\u002BTDgZAnV5pP0KbhT7gkMI\\u002B6dIGQI4D2T8iUx8/gDR5PCxWW8ANe0E/YE85vVJO4r6Zvq2\\u002BTMrsv\\u002BF5br/Cz6I/BcYgQPUeXj9SMiXAWPXhv/k7LUCliTy/BBIEwJMHqcBTOGc/IkSFP8kpxb9cr3BAxzKNv6YCyz9NL1q/fSr/vxamkr2Tt/0/dai7vovUxz\\u002BMxjI/vVWdP3jxH76OTrY/kCfMPoj1JECYi7i9EMyVPzSuRD658kpAOFXPvy5jK8BNeBvAJn6eQFqGRT8wE8c9YOBXPiT\\u002Bmb\\u002Bp7Bi/wJKoP1rvF8AVW6s/OOg7P9Ncqr6KoK\\u002B/ey5IPpa3IL\\u002BEfry8DRY9QDDiDb\\u002BY47C/f79XvsBvRb9aZXK/p8\\u002Bmv5i0tr8eJWC/5I4NPvRSFkCDF26/\\u002BJxFwJgs5T8y5WU\\u002BQObuv0QvOz\\u002B0CYe/Id0jvwqep7\\u002BDPOa/FoYQvgJCFr8mXZ0\\u002BHJiyvx62YL8bvlS/EYEZQCWk079THka/L1ZHQKPEC8A3P\\u002BM/6I1LQHTNzj4THH\\u002B/men5v\\u002BxSjD7qgsE\\u002BpDXsv8PRHMDh9dk\\u002BdGN4Pw9quj\\u002BfAwc/oskpv57XCL5UUAi/WV/fv44NKb/c7Z8/OvLiv8BIXj5jA05A2S\\u002BlPxRL7sAblkG\\u002B7denPx4YGcBUQQ6/\\u002BlKIv5zg8z/Wx9s/rkbfv\\u002BpYAUCdcb\\u002B/PJh2PyZCor9dgYg/NY6WPxjHF0CuxhNARI6rvrBNUT\\u002B2MRjAaaSWvn9vKD/AL65ABvBwv39\\u002BI78m9TBAs80Yvm6JI0Bi728/UO5DP2g5b71Vtdk/XNGFPwzWsD6Asqu/pyMGQJgJGj\\u002BaSwe/RO6tvcARZz/iTXe/jKRRwPRQwT2He4q\\u002Bv600PwLiX78ZJFg/IXCjwJRtlj8GA7Q\\u002BgMtNv2aNJD5dL3k\\u002BX7tkv1HsFkDgWKI\\u002BFG30vwUIMMAgivG\\u002BhGYwwAB4ijwLrg/Arnn4P/FYj76ncgPA\"\n  },\n  {\n    \"CategoryId\": 16,\n    \"Name\": \"Snowsport Gear\",\n    \"NameEmbeddingBase64\": \"eLaHv4QlRz\\u002B9IgFAGmiHv7NLAEDA5bY/l5wkQGVleD9dGD7AvsxXPx2lGb\\u002BvTzDA3GwaQM9OqD\\u002BrhwQ/qrlqvdpRGUAUU1M/LZYJP8cbTD\\u002BENhY/6JajvyDTjzt2v52/iIwAQNk8oz/yDwO/lwWfvpGl\\u002Bb8\\u002B5GbAqHxuv\\u002BBYtzwehd4\\u002BakEuv7r2G8AMJxe\\u002BiKSvvpH2Tr9d9h3A9KMSQEBrKTy65ak/FyFCwOQxEz6oBM8/XZnvvnmSqD4sIFc/cqEUQJdXGMB8jGs/GjfsvyaJBL7w9ga/iG/PP5i1OEA4OqY\\u002BlNDJPkQmKEDdH7Y9DwwEP1gNej9ExOHAag/RP/qE9z5ASitAT3QMv7iO\\u002Bz99boU94N6qvVjeAj\\u002B0x/E\\u002Bbj5hvulPG79yvKy\\u002BUMPgPlNznT4emIE/fkjCv7Z7rL/TlrO/rqiwv5SpNz9jbLk\\u002B6PuKvm3kzL4iyBi/rGzcv4727D\\u002BAUYY/DmA8P1bwQL9c\\u002Blm95bVKvn4bMcCYFcY/UEHtP7R7Cb9f0jY\\u002ByKYIQeRIKr\\u002BVLQk/JMMvP/7r7j/qORq/Qo5\\u002Bv/AmxT7MTwG/XOIBwDsror7JJi9AbtkpvR5pwr\\u002B41WE/0w13v4Rmzj8xoa2/JzpMQKDQyb7AKCNAtMVawAxs\\u002Bb7v/Zc/gCySPFn2oL\\u002BpxUq/zqw\\u002BQEqSRkCWvcu\\u002B3vJbQKycij9s2Q1A65vzv\\u002BbMIb93QQtAf41ovw6zRz5k3/i/ffQ7Pqu//z8kjQbAMzMBwPCiMEBA2G/AdoEQv/AceL6\\u002B7ljAA92Sv9BbUr\\u002BdHcO\\u002BzqyrvaI6cr\\u002B\\u002B9RK/j1SwvxWZIUAwvvM\\u002BOG2iP767mj4LGay/eprhP97rXz5ufYo/gPyNP4Y7Kb/Hh4S/jXFrwMEF8z9cjUi9rOh6v8DL775MmMi/2KcXv571I7\\u002Bq0XU/fPA/QDMPeb\\u002BPt5q/uCpAvyzNxL\\u002B\\u002Boyw\\u002BzTrUPtCrIr89TNE\\u002BcLukPdRC1j/IwXM/AKHEvyUZBMCTzPc/J3adPw4JMT4VUbW/51geQJYXpL\\u002Be5yO\\u002BRttEQLa/X79xjpu//p8fQEWJUr/vOx8/fKiKvy/woj8bcva/D/BVP2/qcD\\u002BfE36\\u002BscoNwHRb0b8mC0u/eos8v4YWGsDhJum\\u002BIsA9vywvG7\\u002BUPDW9p/iVv1hIXj8QZ7y/Y4LSvrRSwL7IxMm\\u002BFz9Sv5zIvsBSW5Y\\u002BJoI0PraaID8h5cg/CGgMP\\u002BxdCED4HT6\\u002Bpt8nQOSbTD\\u002BHnLBAzkcqvVKZmL86Jgq/94uxPjrF7D5wGVY8LEoKPu8M6r4KMy4/iKJivrQabUA4sRnAcGAHv2a0nb/mgmy//HWDQDIpYj9DYBxAq0oUwHz0fz/rpo2/om\\u002BePzQ6HcCRee4/7n/WvmsoBUC\\u002BT3K\\u002BtqOqP9pTmT6kjXE9BA\\u002BZQEWrRL8MioS/\\u002BzGSP0oIEcAC56S/0aF2vqIVDcBs\\u002BDi/tCtHP99l8T47A1BAXrlhv3vWoz/v3hTAeP\\u002Byv5MU7D4ZMxZAuittPt5cRT9uJW\\u002B/LDVLv36bAMASBec/ZvWhP3NQsr6u3J\\u002B/ZE66PoqExL\\u002BmoU6/sQUrvtmoPT5qT64/lepxP3uERj\\u002BHB9Q/zrPovUMYDT\\u002BoO1i/GHY9P6SyHsBPnhI\\u002BGVvXP5NvP0Cp8ZU/jPU7vx8aMz\\u002BIEd8/HH06v6U8g78HrFQ/9ByXPyid27\\u002Bh63ZAL0jgvgbVAcG/DbO/WdZ9PzIpg789IIm/YoIFwOx3JL8AKWA/\\u002BFElwPI4Gz9nwuG/nTCtP7hocT/L32Q/lCV8vwIzaz8VIJE/U8alv37yHj/jVh2/kJKFv3b3CkCki55ATnoYv4\\u002BU4z\\u002BXaRJAkuGdv2hs3r5K76S/To2oPxYHAEB85SC\\u002BqorBPzVKCj\\u002BW4o6/jPOGPxvTzD4qeJQ/QZPIPhAO7T7oFUu\\u002B7qgDPnZy7r\\u002BBaRY/qy6lPjb1sr8caGk9dbA3wH\\u002BnSj6yvEA\\u002BkefMvzl4oz56PhbA9k43v\\u002BV5Ez4zoznA\\u002BIvWPe5a378Q7Hm/oDYfwIDACj1HtU3ACnFvwMJQxD5ERbc9\"\n  },\n  {\n    \"CategoryId\": 17,\n    \"Name\": \"Off-Grid Communication\",\n    \"NameEmbeddingBase64\": \"sHDrv0y4QEDOtis/2B31vweIiz8JL8M\\u002BOctMPquFrT8lAvC/puBbvzvE/L5kHJG\\u002BQXUKvzx25D/8IUg\\u002B3QsuQP26hj9fY4w/PduRP36toz9W9gdAr52CwE6K7r\\u002BzCSo/IuAYQNLktj7eERzAnYCpv0MH3r\\u002BE85vApaCWPoRhRD6q4d8/hv4dP2LLaj/yrgO\\u002Bc9UXv4PI2L\\u002BBqZfApwteP9qqWj8Uf7M/uPyzPmWgQL9\\u002B/4q/mTg8wCf7Z770xrO9Zs0YvhjhYsCIY0g/CK/hP8MRY7/m6pU\\u002BMrQWQLcF4T\\u002BmsL8/DDmuPVkymL/rxbQ\\u002B1vC6vhqnrD/A0NfA\\u002BAjpP5Z1nD8Kcsy\\u002BruUzv\\u002BKbUT\\u002BAROk/d/6xvvB\\u002BSb455wi/0g6mPrN9yT/efuw/IxPCP5tATsB4YhA\\u002BI4kZPt8wXr8P2BRAbklswJwGjD80/YE/pWSwv5wqwr/QkDlAnH0nv7az0j6UmAO/EKAiwD3LJUDny6c/ZuJ7Po7OgcAeGiu/rPqYPgC5X7y68uq/tK/6QBw3ab\\u002BX7tW\\u002BTKBKP4Cowj5fvcK\\u002BIMsxwOE6J7/jgNe/5Rs/v6Qqvz/szKe/lAo1PztR6r/dQ8A/xOeJP5p5gj7IB/M/DsiCP2ok8L5mpYU/rl3iv1k/EED7SoM/6CBvvKr7Q0B6PoC/fMo/QG4UK0B\\u002B/4e\\u002BmCHdPqZVBD/3xpe/7Lj1P0T9mz8qOARAxmbAvdfL6z\\u002B3zac\\u002B5lRQPx5TPECaqbI/Jq0IPjBREr5LdYnAA4U8QIqIPEB4wTG/xqc8P8unDMByoV\\u002B/cLidP2Cjuj8xbEtAk1Gtv\\u002BBciT5kgpg91WsBPy9mpT9bGu\\u002B/KzbDPwDfgb/KHG6/dxwtvsCLoEAu1PC\\u002B35qQwIxWdD0VMKY\\u002BFaoYvi6VqL8cAvC\\u002BWJadvkwp2D9vtSDAOmQPQMLHecDiute/RCO/vdMU578Pk9k/6Ee7v3rlL7/CChg/47/NPxS3\\u002Bb8MCsC/cnurvzR/Tr0ghcs/AMwxO\\u002B0UXMAx0O2/nwUsQJIWjT897xvA/ae4vw/jkL\\u002BW\\u002BCm/NJjEPehKtr\\u002BRjGQ/wcF5PqGEB8BktpE/sX9nv8gSAz9QooC8XewfP66Vwz/MbXNAHLaFPTgPLr\\u002Bm9ylAR0oDP0OEvL86lUC/ItoDQGpGEkCScoe\\u002BHDF3P7KgfT/ArKu/KWDcvzwaBMH8ts\\u002B/ygP1v4Cb679Utja/TNcmwDy1FkCXhKS/rlhmP3TF2T9OgmFAE9tzPw4w/L80PDs/6jILvdwb\\u002BD8KE6C/2srjv4wuob\\u002B5lHi/kvLwvcODXEBoLuQ\\u002BXg1AwHihQj2p5QW/OVK3QCiwYj6YN0VA8pfePpK16D\\u002B0Lsk/JxICQD3PS8CMjY8\\u002BrngjQHQOrz\\u002BG36m\\u002BmZG4P3QwkT9fYa4\\u002BXl5tP\\u002BCaoT5OGjnAEVUAv8/1nr8qpoq/T/pQwGmi1r\\u002B0Bw3AHzWUP/Dt4r/iLDZA7HqYPxZe2D81tYA/VN3cvz269D0UF9a\\u002BWfGdvxHh3L5TXho/KNmfvwPeYr9xVd0/J23yP5eKBr9L6VQ/H6i5P167Mz/n1FQ/g/Z1QDZMfL/kkJE/gk0wPtgkmr5xEMM/RiEAwCkDJsBCLgXA8jc2QGZs5r82oLM/SEG2P8sgKT5ImcA9l52av6PA\\u002Bj\\u002Bh8wa/tdG7vnewv79mCsM/uI6yvoSLK8DGc4FALakGwAIbAsF0kIu/4ZCIvx5smr8P9MS/RtqmP\\u002B\\u002B1Gz/jikRAS31IwNpZzj8M6wPA4BCkP9iI4j0iM0S/csLPP3HpZ0CSQCFABeQawAfDcb/uW/u/rjcaQA\\u002BkzL4Kn6hAEFd2vPRB7z\\u002BGP7m91b\\u002Bnv6Bg0j8FPjg\\u002BKuefvxHLQz8MjIO/wNL9P/8tzr\\u002BNWXo/0CA6v3TTNj\\u002BgziK/IKnlPbn/ScC/MQLAcH3OP2g3AEDGyqy/DogJQBznHb4Ku9u//dcrwNS/1D8Mc5a\\u002BuoFMvWgYjL2O9y0\\u002BKa5oP2LCXr9jSPk\\u002BqCeuv8WdEMAgkzk/CiCsvhQ7XD99PzjARtekP33wm7/VToA/\"\n  },\n  {\n    \"CategoryId\": 18,\n    \"Name\": \"Camping Shelters\",\n    \"NameEmbeddingBase64\": \"\\u002BnHJvimc1z/iKL8/WAoePkMfCUChYgxA6\\u002ByqviZJ0r\\u002BZqaG/6alJv7If6T6uSJK/0M81PnfuBkDGhAZAhHntPmMpRz\\u002BgO5k/aMbGvqo9AkBS44U\\u002B4MMzvjx4l7wceoi/tGGgvb\\u002Bnu744XGq/Yq1pP1xtUL9IcrW/LhbxP4Lu279auuK/dblxvvBXSz\\u002BNlMY/Z2kvP5CvE77AXWy/wk6iP7jqGz4QXpc/wdyDvkDHAL9zVc4\\u002BRrHovhWRcr\\u002B06h/A7PWmP7eQS7/I2gA/5vhiPl\\u002B3ET7qZey\\u002BZOOoPLRFH71ULgO\\u002BjDfFPjwLDT60F5k/Wo9EvlyJjLxFT3fAHviYvuL\\u002BUkBtpsA\\u002BpNkFwMWz7D9P2ZE/orIgPylJdL/7XVk/3JQNPxDNjL/8dto\\u002BaBRhvWoSeb4P03g/zBv3v1A0WT0yiDPA2YSHv25cgj\\u002Bu7Ma8KsmZvlt6gD\\u002Bru4I/pPacvwQvwT5AZ/w/HExlv7p/9r5BSgu/NRh5P9ZHM8DI9wy/lnGuPUXBJr5OUhbARQbcQHhbmT7qnIc/1\\u002BQ9v95izT2Ml4W/XjE3wJ1HK74XEse\\u002BupKbv0QDfr6qLPY\\u002BH0SNvdBA3r4mT\\u002Be8mvISv2iLLL9Q4YA/O8jAP93R\\u002Bj6KzmFATCiHv50ed78Ht94/ZlZvv7nZ6T\\u002BoE0g9y3cUPhytCEDCWKk/N4q\\u002BP2WsiD/miiA/sC4fPXm3Kb\\u002BF4ze/HpUQPxDtnj0ElGG/k0kzP/Djfr838w9Aw7zHv7iS4j\\u002BAJ4DAcHkqP9KGD78iaTq/pNupP1uw2L9WIe\\u002B\\u002BFKNQPzyXzj6i6DBATVQkwIwQBECAXMw\\u002BcAO6v3YTej9nf5I/wiW/Ps7oTT\\u002BWzZo\\u002BMnrpPqh9hj9QUUy/Blzwv1YyEb7I320/chs/vqophr\\u002BeZlk\\u002BDxMnP\\u002BgTzj\\u002BfgSe/2GnFP0RIt7843/\\u002B/3OdfvzPlwL/gKAc/fvMpvxFcdb\\u002BU\\u002BwY/u1sVPw/KE7/qoEO/dds8v7KsEb\\u002BH844/bOlSPe0O479DU/K/ElMYQGsVBMDlwJe92LpXP31Lhb8Ug1i/KE\\u002BnP77Pvb9mXCdAuKzwPjlolr9q2lc/yI7APyJUrj9ErvM\\u002BnBgRwPQsND8tD3I/DgObPxjlhr6DnYW\\u002ByoGTv0oQMb\\u002BGkpg/K3CEP2miMj/m78a\\u002BDRgzPkP0CD9iKEPAJmnwvwZZr8CszzQ/Fl2IPzCNjj6W1lPAMIeFv808ND/v/N0\\u002BWtpSwCDT3b68a5xAln4twMgDBD2dENk/4rMlP8Qzrj4gRPS8l0fKv4Pmmj\\u002Bd3pA\\u002BMXLhviIMVD0leQ9AcQQMP6Qfizx4YKm/GttkQGmvxT9y7s8/tFJVv02yTT9Ihxy\\u002BpU2YP3p9VcDPYNY/vlkrP8DcA77Yxek/rOGLPxhHdT75nSm/mL2SQEW2H75SdgjA\\u002B4SxvpSdnr\\u002BIwAK/ECj7v4R5mr/Atbq/qBdyPzDHIb9cSR\\u002B\\u002BdIFhv\\u002BO6GUBbKIS/NWW8v47/Vb9yXFS/s3fKPxoYPT\\u002BpyVy/RzcSv3KZjr41yYY\\u002BkD/dPlelib8jHdo\\u002Bfd\\u002BbPng4MsDkkVi/yjYNQFhRgr\\u002Bkh6K/wYYgQJLXBr62nha\\u002Bxxh2vp9FnT\\u002BEzNu/QMITv5bE8j1kLn6/fFeTv2LIsz\\u002B/5R5Ap6cswOcyCkDSy4e/QlPPvpiIQj4wNWc/jtHOvw7qZ79UjRZA/rhHvqKDvcD3KQw/nDpdvgF7SMCiUa6/cD/sPKgxX77ZgSVAPZ65P1i3VT5UNDs/038nQCRMSj/DmJ0\\u002BytZiPpwU8D6Wr08/3QOyv5boSj4jV/C/UBo6PLkbD7\\u002BWkVNAuIhOv7C0ijx7Ncg/PwucPlRccT\\u002BdqaI/aE05PhKkCz\\u002BhCe8\\u002B6NUQvkqgU7\\u002BJW1A/ylvcPkjckT\\u002BENku\\u002BQKaZPx7dib465AfAwIK1Prrzpz9\\u002B88c9OMxWvmqgxr/yqq4/2WQRwFghFECH6pq/hAHavyYNQb5kZY\\u002B/dO3fPgiSvD2vguU/c0yFvlrlXb\\u002B0SwW/9nX7Pun25j7k7CK/QWUuvt1lI8AySto\\u002B\"\n  },\n  {\n    \"CategoryId\": 19,\n    \"Name\": \"Outdoor Cooking\",\n    \"NameEmbeddingBase64\": \"\\u002BF6hPa\\u002B79b6NQOE/vzQMv9opoz\\u002Bt1Y4\\u002BiDzpvoRshL9Nw5C/9p\\u002BDv/7tcb\\u002BPK4q/3TMlvrakZD8ZqtA\\u002BfLHUv2pkmz99B8M/OB5Av4qJ6T2TREw/hyOAv7V2u74yWLW/JvpoPY4Ewz/rrL2/dyiDP5KRRr98FSLAl3dSPgaMXb\\u002BFGY2/ZFmjPYCc1r\\u002BCeZC/AMYUPzS01b7ELQXALFuOP0nTiD5PdkU/GIqDPSaF376No5y/T8o3vnl4d79JUdW/GML1Pw7Gzb143SW/hmDEvcvQ0L/X5iy\\u002BdJW5P/RsuT\\u002Bcwz4/HpnyP0t\\u002Bzr4WGhq/sIiTPydqtj\\u002BcJo7A0weFP/BxcL2a5mU/2Jt4PYryCUCaJGY\\u002B0wUlv1gn0r6lUe8/GP/QPzXKID\\u002BG6nQ/IJyYvqRJ\\u002BL/U\\u002B6e\\u002BFd85wGNihz9Nr3I/y69vvkSkzL4L4wM/WPqyv8Pz3D4VXdM\\u002BB8uEv/1OB0Cq4ABAoMYYPEtDgb/6fxu\\u002BvDlWPriNxL\\u002BZMAS/bHpYPwAbhr\\u002BQRS6/6iXpQLwjNsA8vOY\\u002B/PO8PqB12Lx21rS\\u002BPFsHv9vBo7/ImZC/8Jyuv\\u002BbqM79IWxc/4LFRPOgYDsCRXo8/Xtr3vixOKr/e4xU/I7mDPvFlz7\\u002BAsws/QArJv2pa0j5q/Ic/20VXPuT1pz861d\\u002B\\u002BeEmGPnCEHECZX4g\\u002BsG0XQCYGKT\\u002Bjesa\\u002BbiCDPnyEx7/gDpq8Uai1PqJI1D9HC9g/UyKMP3l8jr7CNxg\\u002BAlFWv05o6T9OvkDAOLpNQLNLir4Awqs6wMsdvEA0l7/oIUu/XvIGPz82Nj\\u002BUQJQ/2CcVvtNTA0CpX3Q/9o\\u002BjvyuNgb5gkoK9xALkPoIxxb46GhY/UuQeP2CUY76Nsea\\u002BvxuHwAhvIL/slCI/fiQhP08QUL8fgcY\\u002BvtXhvtoLFz8aKJI/GFKXP9Kehz\\u002BgsUDA0drBPUyE9b\\u002BM4/k\\u002BRG/BP5B6bT6V\\u002BhQ/wvZUP8S6pT36i2e/TNoBwAPLmL8MkKi/9pEvQEcl9L8yf9W/wxd/vzZZzT67faa\\u002BZQNjP9Ra/z2JOt\\u002B\\u002Ba1nzP2r7nr\\u002BKzQFApN8EwEElWb62Zii/gL07QEjYiL8eI1E/4rOsv7MRTj/zffU/aL36Pspmrz7Ujqk9s3o8v3iSOT5Ido0/EivGP2XMGT\\u002Bh5vQ\\u002BvQpjv3atLT/PCobA2L2hvxJud8CGdhLAqoPlP6f7cr5W1ho/mKyNv6baor\\u002B\\u002BQAy/8I1bPSmgdj8K\\u002BQdA7AgdwICvwj9S/W0/ua4BP5qcwj99h/o/HSGVv6T/QD4aPoo/BLlDPySAnD6RCg0/m/mOvrEimz/e5f6\\u002BsEx2QFaeWD4o7xJAyP\\u002Bqvylsab\\u002B\\u002B2jU9GPlUP3U7JcAALIC\\u002BMIynPpJm3z6kmge/1vUEwDIp1r/alHQ/XCkdQPoIUz7A2Fa/rLpfPfBPt79y8S0/rEjVvwYMdD9YQRLAwFspP8gwyD/alf8/Gconv9AjPD\\u002BixF\\u002B/Gzuev9Ncjj8TS06/C1q1vroFOD8xA0W\\u002BdL7WPjAlmL99BANAQX0ZP\\u002BXPU78vrh6/cXgXP889mD7S7Na\\u002BEkQjvx46DD/m3Pa\\u002BKudIP7Irwr7CNtg/v3cQP4/WMD/Y/CrAlQ8lQA6hgb\\u002BVi\\u002BQ/PCQ4P/XPtj6IrlO/RjHEv67P3z5q/Dm/o9ENv4TrUj7qtwG/dqMQwNDEkb\\u002BBsmFA2NtzvU5dycA1lw4/GXF9PjDdrzzomtA\\u002BNc1kPvi5jz2fC0tAETSwv6VMyD6Y4wg/BIhnvs5YjT8MR\\u002B\\u002B85WANP3hj2r66X4i\\u002BF0lgP0b8iz\\u002BlJ0G/FG7hP6qNJEBEAD9AqYmtvvSjvD7g0aQ/AJzlvlqtl78zOwi/8BiPPCrQrj8cqkC/s8/EPw0Ezb4uxu4/TVEDP9L3aD9S2Ay\\u002BSuhlPlQTlb9Y/pq/OLLYvRQCfr4VIfo\\u002BfbSQv\\u002BJTS793s0c/jUiFv0BgZb8e2HM/CbNJPwo\\u002BQ7/A2gHAas3UPmaCwb5CNAY/Dm2Rv5QHqT6ujdS/dHeEP9ugnj8nBErAuxv/PjqzTL94\\u002BqA/\"\n  },\n  {\n    \"CategoryId\": 2,\n    \"Name\": \"GPS Navigation\",\n    \"NameEmbeddingBase64\": \"4O2QvG0uyL2DQyRAls0IwAEwfr86uL\\u002B\\u002BpcwbPwqMjT97JCC/qac9v3dRgz/cywnAGa4pP9LI\\u002Bz\\u002BP1w2/21HFvyfVWr8G9cI/awgYQKVAaj6Bk5s/4PBSvTAcr74sPVK/Zrorv\\u002BuCUEBI4dO\\u002BsoLMv8skxz2SKWnAJAp1P6BE978Dxx8/KycBP1xLNcDKMFc/4EnPvllpqD922uw\\u002BskccPo/EA0ACOBw\\u002BuM73v3o1Dz78D6O/6hG9v5KjCz/QxRY/ogcFPy2FiL/hx1u/dkYvPiXKlb8jXJE/Cq6BP6JV8T9w2TI/gkf3vn6m575/240\\u002B0DyDP7bER79IRcfAUdEwPwZuAL\\u002B3DhU/MktVPY1h3L9a6ri/kufpva4Maz4v/e8/5\\u002BeMv3WZ7z58tvY\\u002B42BHvYq1g7/sUNA\\u002BvPxyvxhpbz8MFEg/EsXqPyy/MD/V9dk/YvJJP67G57/h2G6/4sETv5Pomz/iQom93ODMP3Kzmr\\u002BGCcQ\\u002BrI\\u002BaPlJzib/07VG/IvGeP\\u002Bz6jD9A0nQ/kibbQLlnMr\\u002B84RZABLvoPZO71j9tmGY/D5WBv17aiz7kL/6\\u002B7iOQv7tZgz\\u002BntIo/XrIsv17jUz/IHI2\\u002BrJsgwBZH1j8u7ne/GFooQBnytr49CRg/4DkKwMM7nL9hRT5A4HPJPk8KGkBJNgK/5rvrPyL\\u002BC0AonRo8bEOpPxny4j9HPIW/QLelv21ZxD/NcR\\u002B/h0KYPtHpmT8pFs6\\u002BxMCTv8gC3j6\\u002Bix/A3xTPPkfJB0AY\\u002ByPAsGOgvn92SkClhXS/6uiRv/TUQz\\u002BiVdq/K9C1vtZf8r4LcYI/JKQvP\\u002BWEUr\\u002B22Us/NiG/PzShPT/pNV/APY6pP6SD876GPxe/ATJ8vy6veEBZNq8/MA8iwH5HXj8YJJA/q8sRPgvW8j41TWw\\u002BJRR0PjOfbz4H7Zw9F2EXQNJ7Xj7PSsO/wPKTP94/Yr/gXLm/eAiWv8xp5r\\u002BUxEu\\u002BsfXWvhBCIz0k5Mk\\u002BNGSNvyQnKL\\u002B4T7K\\u002BH\\u002BZxv5azCUCsprG8gHjlP1J3jL9Pc1S/Yr/WvhS31b/fzsa\\u002Bh\\u002BuGP90hlb92mr0/iuMnwEBI3brbIk8\\u002BILrxP83KMr/xU4U/9v2tvx/gtL/hnwpAPGRJPy4HrT7WLkg/fqXdv0Desb49LALAHrLdPoBj8j3glgXAAtXLPzRnLL\\u002BgSgs8m1Ohv/w\\u002BscBfKfO/OkqVPikwdEBqwfy/mjNOv6/lLL/0jPU/vrO6P\\u002BIEEsBuUW5AwrDtvV7eVz\\u002B\\u002Bdds/\\u002BDKgvdCtJD7SOUW/MHeMP482dr6OFfm\\u002BL6ryPvgCHT8lZtO/RhDYv0Pgyr58nTY\\u002BAottQFSPaD\\u002Bml1g/FJpmv6ZohT9E9qe/qb6zP6ABxr9gs6M8YKCIP9QasD88qqE/MTG3vu4\\u002Bzb9kePS/9X3JP/g95T\\u002B1nYM/Qd2bvgzKxD10OqG/9bOpv3H0lz8UCGs/fvsfPTnoSr9SbBy/argFwM6AAj/Mabe/haOEv14jrb8M7NW/3FyFP9h8kL990oS\\u002B/usqP2MwTL/LL\\u002B4/izulP1xHPj94H6A\\u002BB0jBP/Dnuz16S9G9DK/WP\\u002Bzq9r/qOuO\\u002BIohXv9qfBMBBfSRA3kkzP/CxyD8MneG/G9ftvzFkCj/0\\u002BY09NoSWPwpCar/RTKG\\u002BWlCDP1amS7\\u002BzehnA6vKcvyBGtL2Wrxe/FcVWP7T8a8BUlhJAh7GUvoRGr8DAtZG7u1MtvQDfPb\\u002BCKOa/HLqqvzLEnj/o8GI/D\\u002By4vxsIp74k4FW/Ri6WPzJArz2IguG/9CzFPfvZDkAF6xA/iPUIvvNzYj\\u002BqSvW/rjf\\u002BP\\u002BcJ6j/ORW5A4isMPuC76bobl9g/\\u002Bsn2v5a1xr/AEd89ps\\u002BwvlSQi70xZBe/hDAsQLxPPj\\u002BqXwVA4ZspQCehAD8NFEE/5Mcvvz8dSz/QHJE\\u002Bxk1FP4ry1j9w72O97LU6QLFStb\\u002BgyY6/YwlhPjhDnb449uc\\u002BUF6dvt9nib9ala6/6I1tP/4qjT3Qm50/PxX9v6TErr\\u002BDTV\\u002B/DCyhv8a4Ez\\u002Bv2CXA2vnSPyjGIMAGF/K\\u002B\"\n  },\n  {\n    \"CategoryId\": 20,\n    \"Name\": \"Snow \\u0026 Ice Gear\",\n    \"NameEmbeddingBase64\": \"uWA0wM/rgD80CE9A/tIPPrxzb0AUXKM/K7ohQDBBBT8DShrAdHZfvsK\\u002BhL4VSYa/s0xsQCO6QD4FxLc/7GmgvrAu/j8FNhE/jZQFwJNBHEB7Cqk/rt\\u002Biv6yL/j5Fgri/pHk6QNqoCkCrHBy/uS4nv4bqwT3334XASHQyPdJ7cj4kbb8/R5Ijv5HkNcDn1q6\\u002BqT2xPhSuqb/chzLAF0TlPwzJD73g7gBA5UkMwLXZCr/gyuA/B1wQP1MC8r7z6/s\\u002BHUoFQMeem79SdeE/Rimvv\\u002BkOdL8aFzs/eegBQINhbkCk3/G9Gri/PY5P1T8kYSg/pSVSv3jSjz40FtrA1CtkQNMVYj\\u002BFIE5Ai8Clv2qL\\u002BD/CplE\\u002BgQKCPw1G1r47KRlA1lgFP6x7kr4c95K/RqAwvh8h6L8YkYw/2ACTvz\\u002BdNcBxQiDAmB6qv\\u002BzBMUDHAi0/\\u002BWhGv0Ikkr4wJpO\\u002BR1L4v5g9tj/fciQ/rEQ0Pw9ZWL86Mco\\u002B/ETMPx3ssr8t5RJAtLfrPxkI8b5qIfE92R0XQX356b/etba\\u002B2T91v0TBTj\\u002BaCHu/KI1rvxhhID8N\\u002B8u/grurv9CsEL1ipR1AegOTv/C/8L8k6VY\\u002Bx3B3P6D7Nr9GgVU\\u002ByLtoQBPOiL9FQ64\\u002Brt\\u002BFwCE2h76J7ANALgdtPwJKNL9mDAbA0Z71P0glc0DmNQC/ulknQMa3yj8cMFA/v16UPubpm79Ocpc/unFevt/aer\\u002Bm9jXASLBgP3i1sj/fOUO/wECyv\\u002Bs8\\u002Bz8jvYXAaOXQP6iLFj9ltYvAU7YJv0zk6L/n97G/NJLjvr6YBD98fwNAtuonv8MvpkAYAaa/E3UfQDiV3r6i6IW/VdCZP6p/dj9M/aU/q\\u002BMZvtpnnj/XE/W/evqGwKuyBEBQG1S/6W\\u002BIvpAqrr5Q3AO\\u002B29BxvhgnU7/x2AI/aJSVQKOPD74sBijA\\u002BBVev/khv78wk44/9Pc2PoGdib5j/p4/o/fTPl3G5T\\u002BfUY4/zh8qPxRYxb/EfqI/WMCUvYKsPT9nlqq/2hKJQDg7uD5jYIa/BwkEQBI3qb\\u002BGX3e/llEfQGc5HMA8k0JAbHmUvysb1j69IxXAzrstQNTKgb6SNDy/DlEmwL9Zqr9EF5I/6C/lPNH46L\\u002Bq1uO/gIQIPllP\\u002Br6AoHI82NpHP9DDMr0AwFfAyjEFv9lnwb56nC7A6HECPuCD/cB1ZFQ\\u002Bf7YcP8mrqr8P\\u002BIY/OPFUvykNX0DBCLi/1Kzqvf0arT8ogpJAhlbMvwb2k74pFw\\u002B/aIwPP0Ik7z9dIb09wXgAvx6QyD/7EZw/jT8HwEAAYkCjV9G/lTvPvkgDxj4t1ty/bD3SQBZfLj5LZs4/3Nfxv9rPGr2pJkO/iEWYP8ytjcCY5wRA5jhBv3Cbbj9MrIo/bz9Fv5eZjD\\u002BC82m\\u002B\\u002BWapQLi4or\\u002BltH0\\u002B9FATQGheN8DMQ0m/1iWsPZd6RcDO\\u002BWnAZe\\u002BBP1YYpb8oTApAEUD8vy5nP7\\u002B3SiXA/7XKv7vc6j9gKlU/1pp0v5eKJUC23Oe/OCC9vlqqIsBU\\u002BhZAFgMrPzolH782XWm\\u002BS2mEvqLjEb/LUqe/7awOP8zb6b50Z9c/HfrvPy70pj8s96Y/g5\\u002BjvxKV\\u002Bb5Flpm/TrlAPtxJUMAsGMo8WA9sPiMdOUD85eS\\u002BmMGtv\\u002Bjwcz/9dd0/7Vriv71aQ79Zeq\\u002B\\u002B3T0AQE6qQcCvPaFAejEHvxcGFcGGhyu/\\u002BC4dQDScxr/eTRPAiYDQvwNHtL\\u002BX/oM\\u002Bm4u7v6f2rD7cAwW/enjnP8oAiD8xCX8/DrSfv6gF3DwqdvI/YXT0v8i8dz8qs\\u002B09yLFov5q5MEDWjeFAqk8kPtCg\\u002Bb4\\u002B6cM/a5SGP\\u002B4U4j/8fRg/jbnxP2mRGkCETLK\\u002Bz5njvux8Qj/HeZM\\u002BTCI7QMdY1r6EouM/I2WwPwkyEj92m4m/KG08P/Jenb8cE0e9rsrmPVbAQsAAsRQ7cbF4wMVQRr9qhdk/cderv2VYpL7IGfG/yzYFv6vbjL/e8i/ALhdmv6wCm7/sFOW/MsBGwKbDjD9nZlTAUDiYwFpAAD96EvE9\"\n  },\n  {\n    \"CategoryId\": 21,\n    \"Name\": \"Emergency Gear\",\n    \"NameEmbeddingBase64\": \"Pozsv9LkXz/MPXg/MJlDvZg3NUAotoI/TIUiQHLv3z8Su\\u002B2/vap1vivpc75m4sq\\u002BLdJaPmBbzz9rb6w/lun3Ppj/FkB2uai\\u002Br6irv7BmFkBvc5o/ryMLPwoEFz4gsIi88zOjP3ycvb6b/9I\\u002Bi2N1P54ydr8K/13AYtWXv\\u002Bee2D2sbcs/Qv6\\u002BvttTWr4K/WY/Qh4WPpBA57z0772\\u002BWYEPP7565D4ozmI/qJKmvn7N5r9W8\\u002B2\\u002BsMLyv2rZcj/y8CC\\u002B3C1nQN7aOsANKDxAjNX\\u002BvhPCuD5eGQY\\u002BUtWkPiTf1L\\u002B0zVe\\u002B1L45v7SW3z76s\\u002BU\\u002BXqVaP/DrsD9mGm7AtnGhP3wBnL55s8Q\\u002BxJzkPuayGj8L3/A/1FQ/v1S6s79UFM4\\u002B7jcHP/lE6z/HtC\\u002B/XOJRP5fPoD90YFq/ImnCvkSnsL8CgyG/E5Xavy4dlT5ggMY\\u002BcV2cvudWXb\\u002BbGm8/ygCWvwpaC7/b9bE/ashhvxp2Sz/CERw/Vo2WPyVQSz6yCOy\\u002BNQDOvtJQiL\\u002Bi9sG/xrn7QDTC676EbU6\\u002BPi/IP8laHD4eF9M/fkYqwDh0hD98wrW/a7a5vwCOsz1sFJc/SkVovzbmgr5PpGe/QLngPkRiXT9t0pO/exbXPyd1Pb/8aJW/TkiXvrRHbD8ECuA//11iv6U5Oj6sCU2/Ok0dQESUNECKCLu\\u002BPCfMP\\u002BKs6z5C2E\\u002B/hlaBPpa9V7\\u002BXbTM\\u002B0emmvuBaNT8PcK\\u002B\\u002B3vaiv4Wu4D\\u002B2ZPI/wUQMv2T0871ecXLA1p8YP1g8hz8B5a\\u002B/\\u002BIYnvm2b674GfdS/QBmdvwbblD7yRVE\\u002B1fGmvg1BiT8duUY/9sE/QCKQ6L7wh3C\\u002Bzh8avzEEsD6p9Ym\\u002BvqJevx1pEEDoWfm/bHMSwFYwAT8mSYm/oydMvrsuoL9r5IS\\u002B930AP3yFGz9KPMk/mltSQHz3Aj3E/uY\\u002BFLwZv/5yo78a6G0/hK3GPjiSz7/alKc\\u002BEUPuP4C2FzsHt8E913yBvwaOmD7bqCk/sxPUP1RZAj6\\u002BpTq\\u002BlnAhQM4TDT88JZi/gST9PhMruL9tBhe/l/GLP40NAcC\\u002BKJo/dPfvvi60DD9bN\\u002Ba9vFPLPquKHz/YgZq/L/ZxvvlkKcA1O4g/JlknvpEUa7\\u002BWeglAome0vsw/U7/MZNe\\u002Bb/HAvibuAEDndIq/b2kgP6HFbD8i664\\u002BwRTjPyQIrMBBVSI/g2MhP80YsL5M3Kc\\u002BbSsqPxNVqz9p5UK\\u002BGedivyEyGj8AtElArpygv5D6xr442Vq\\u002B\\u002BCUkP62PJkBsuCM\\u002BAkUUwCFpbb80xmU/sDyfPgSy8D8m/TnAzG9zPyiPXL\\u002Bo0K2/Of2DQCenLr94DBo/uIe1vzK0wL/kW5g\\u002BHB7/PyxpGcBWS1I/wHj9vjK8cj6n1aI\\u002B0Ggov/jR37w5YwTA8G3jP65heD6bF7G/MBeEP0iV/L9t3KW/\\u002BtFpP/\\u002BzAcAsU6C/EGvUP7dqPb\\u002BBTBE/GfuRv5Dmnj/x//m/bUG\\u002BvvO0Y74piYW/vyjjv83U5b68WYa8gG8cvwjzZb8qMHw/Xv\\u002BSPjtxlr8ZVre9SoDavsrKH8AKShnA/EYEQERazb8Book/dw8MP4S7cD/SJLg\\u002B6Hy1v/ibMz3rqRK/EcRPP9KHb75ZG609fBPRvlqWRD/531q/8Mfvvr9I5D9xhc0\\u002BSDZrPjyYUb6U5z2\\u002B6ukpv6I1g7/8\\u002BRJANX6iv72u1MBnVuU/mt/fPmgO9r//XgLANSqIvr6hR79yaA\\u002B92p7uPuEFkD\\u002BiKVe/Qj6\\u002BP8/zqT9vuoE\\u002BWG0tPOggkz9Aqmi96W2vv\\u002Biy\\u002BLxCrGy/8Zsvv9C8sT/uXIpA4ibfvs4iUT\\u002BJObI/t8mDPnRzFT9E\\u002Bqw/RXyhP6zxJkCm3im/vKlmvjWghr58CYk\\u002BFkYHwMwLVb0KA4E/siQ0P3e58j53RSK/zr//Pp/Skj5t6bI\\u002BSVgbP51ltb\\u002Bilg\\u002B/Js7pv9iPp75kny6/YLZBvN6hEr\\u002BvaV\\u002B/mHLYvuCe1T6bBUe/zcPFvzq3bT8o23I/E1KNv7N7uz6S59a/XoMcv9TlFb9Uqeq\\u002B\"\n  },\n  {\n    \"CategoryId\": 22,\n    \"Name\": \"Adventure Electronics\",\n    \"NameEmbeddingBase64\": \"UyHJvykdtD9S2\\u002Bw/pnmfvwo5qr\\u002BWClA/0vxcP9wHhz8351K/rGfAvtZQyD9OksI\\u002BjEJ5P1PXsL4SK4w/0YdePpumyj9YkXC\\u002BQWuEP1/7J0CdPRw/sNKTviIbjD/xtyK/GQ4dvyLU9D7UniS/RV5fv0LME7/wKyXAWA08vdLXfz677CK/vk7svtWccD7E4ZU/KNNvvwyBr7/oJk2\\u002BT9ICP1xhj7/SG7M/SVxYP6gaFb9\\u002BECK\\u002BZvvnvxav0b4ZmP6/CjeVPzlshr81ocI\\u002B4xE4P7hZpr1ma6u/UcdRv4BEuz\\u002BYS0o/J6fxvpBGxT5f430\\u002BtTZ1P2uukj\\u002BowlLAFCktQOPqEr9Yovg/bqcAviDiprtfkNC\\u002BjF0bwIIyWL\\u002BC2ZY/9InAPie0lT8w5e4\\u002BgN/ru94rfT4dI0C/CRGRvzKDVr9W/ai\\u002BgxPav/oQFb/OroM/Aty5PyQtBz0SEb4/AGjfvtBNlz6UmIM/ADwmv9XJAT7WfZC/lR6UvhBByr\\u002BNNfm\\u002BLqxjPskuUb\\u002BRScK/yHWyQLKBoj6hsCM/rAWZP/6XQT9cY7S9OjwkwGFvmb6xuhw/FlqZv1GHhL8MIgG/YIQEP3p0vT04c1\\u002B8ai7XvxkPsT9onMG/1GU5Pyab0D5oK\\u002Bu\\u002BLMoTwIQ1\\u002Bb5HQIQ/Jroavd6H4b7WB4C/w1NEQKU4RED5/ou/T217P6VVoL6NWIO\\u002BnOMIvyOtNj/XffO\\u002BPlH3PgwyvL1bZ8M\\u002BRTgdP9HJ2D/FLaK/oCh3PyAcxj9bY13AMBZXPVx60r9CUqw//XM3v7zF7r0AG\\u002B8\\u002BIvvFPQoxQj85NzxADv4dvwJzOz\\u002BqjYo/xMuOP6Kwdz/MZSHAey2LPyg6ub9A4pW\\u002B5HJ/PxIic0DGHJw/Owl3wBQQpD8kexQ\\u002B8JA\\u002BPdowob84A2W/OJ\\u002BCPxo6IL\\u002BIYXs\\u002BNHokQNm1Lj4KvZe/MEAbP3iu\\u002Br8cFD8/KoPdP4Ac2L83xgM/T4oev6pRC76Omhu9sOqVPKQgKr/eC5k\\u002BlOLfP56FGz7HV62/5AEVQALDkD8q3pc/Obz8PtCm8790Euq9CEaUvT4B3L9tSjU/8I3tv4UzN78PlApAPffTP7RSOD1ppcC9hICQv5gdcb\\u002BlfUM/pkmSP5a/g79YndY/NrVlv7we87\\u002Bkq6S/wMkzvYPvoz5Ayhm7U6zbP1hKGT2mQOc93zcBQJA4tsD8UI\\u002B/27qTPts7hD9OpzDAsMYpvFj75z9VRO2\\u002BLl26PgOsJL9aQMU\\u002BYFTOv5xAuT42qQo/w2cAv8iHBkBqSKA/8kgfv\\u002BnrUb5UDbE9YOjeu90MjT/gn6g\\u002BcCupvHNXJD1SvQA/sdGTQAwCqj9Pmo8/Koifv8opHb5E/v0/3mQ0PeJydr5GiAs/a8NHP6DovD6ytQo/fPBuvvLojb/d7\\u002Be/q3/6PwoXsz9RqHC/xLXEvlIi8L6RHq\\u002B/c7juv8SYWr4u9Ue\\u002B\\u002BU4hP/hkfb5SZFk\\u002B5WNgv13KaT9gOJC/pAO5v1cDTj/qCV2/VFpcPRkOZb8\\u002BJ9W/pV8dvwwJXL9Y3ko/nts9Pwf\\u002BMz\\u002BUvlU/hhMFQE70rr9oUYa/vLTFP4JA0D6Y0lO94NrbO2ywJb8oOwpAKF9Av\\u002B2BKUBgdvC8nCckvl7ReD8w7XQ/J3idPynp075M2Vi\\u002BXbLavtLjib9QWfW/yIvJv21sML8056i/8gsGvymb8L4MNdE/OaKZPwVaosAeajK/W7mEvei5gL\\u002BGSQrAjSqEPiBv5LsahGU\\u002Bew0yvk3r9z8946i/g86yP3oVhL99ZsY\\u002BBNhXP1142z8un7w/K0idv2CnVD8JTaS/Vd\\u002BcPxPm6z9I6V1AYqLUPeZ/Tb/0lmA/vw6xPkXXFj9G/4y/qgGFv6KvtL62GMq/1eYAQCVMkj8cbS09Je/TP01mJb8iQKW/rv24Pu6bE77/CUO\\u002BV9tTP8l0GT\\u002BPsgm/nszKPxKMiL4EBTS/eBRgv75EFL/eC5g\\u002B5P3Tv2Cbo79Qk7\\u002B/YoUfv6f\\u002BQr\\u002BMvkE/CEFuv7QG8z4ZC5Q/iyYvwLT6Qb00WZy/9PsOvnrJBsCsB52/\"\n  },\n  {\n    \"CategoryId\": 23,\n    \"Name\": \"Mountain Biking Gear\",\n    \"NameEmbeddingBase64\": \"8CcGwIxLXT8T85I/VKhWPWOozr\\u002BCwRI/28bDPztFfb7x8dG/iisrP7fn\\u002BT2dKSnAv6EZQCktuj9GvYc/eWIKPghsfUDOcwFA\\u002BpHEP\\u002Bjl/z8i7GA\\u002BwdQtPmF0Oj850Ec/gPmHQOyspz8gyhHAHiFBP69d\\u002Br6ONmHAnAT1Plk0DECsc8K8ai1ov7k0BsBEEzE\\u002BDkcCwK9I6L5He4nAZPHBP\\u002BPu2D9tPfo/T5z1Po9Jcz4rybc/0QhDP6zaaD/Z5eO/0hgIQJ7gKMDHocA/yEgOwACFkz\\u002BKUIm/UIpqPTv/hT/HPke/P87WPhieND9IXBE/wFzYOnhL2j8h5qbAsV/LP395xT/y0ZRAjIkovoXMqz9IOhK/l9KfP2qEnr70iG8/3mJtP3ezJz/MSSo/HEr5PnftxT7cr5e\\u002Bw1zav7Te5L\\u002Ba3SbA9m85wMgYGT\\u002BQQDg9pml2P6Ghar4E4Ou8Ima2vmsA\\u002Bz/jShBAiLfIvuk2mb88A5E/0wqOPmEmGcAQeQg//62DPxKYyr6g6ra\\u002BnDsHQddFt7\\u002B5tpg/rOPEP6lPwz/0aGk/hs8lwG7FuT7AHpG9Mut6v8DNoT9InT5AD3NKP\\u002BnQs76\\u002B06Q\\u002BP5iav4b\\u002BBkBAy/K/YnemPy77vL888uM/rQ9VwEVtDL6oU0c\\u002BmcFOPlpP379nqde/ksPSP36AMkCmzcg/uN7kPyFP0T/m6jdA6/KFv8o2kr8pWRQ/\\u002BzC\\u002Bvzf5vz/bzQTA5plvvjP9yj9MY3K/X3YJv\\u002BDcMkDplnHAFOQJv7a6z790mR6/WoAMv424mL\\u002BJ6de\\u002BxHdTv6JIn7\\u002Bs9GG/lKbmvuIvwD/\\u002BB00/gkKWPxw8P75AcIu/woLuPxarTL8qEhs/kHjMvblJsD8\\u002BCh0/67VYwGiWMj3CVDC/p5HjvojNr7\\u002Bx\\u002BNy9ywtKP6pcCD8mzYE/Mp9lQBwlR7/HTELAquYivypCS8DA2qg7rK3rP8SLGr9An9q8CyhvvuBXlT/9Aum/NeZcwCv3bb9Eug1AVNT7P/hN9jxaos2\\u002B0IJLvs7bW7\\u002BUNxi/QNtiP/XNGcBC4La9bD5Mv0TjPj4Fe0dA2NFbv4xmJj\\u002BsARU/AG52u77GfD\\u002BpbgbAcw8QwAjIgr\\u002BQ9jq8vlWxPyOxmb//Mts/F7ruP39gr74P2Q\\u002B9bigWP7ZQID93JRrAJBbPvvz58L2cejG/yz4Tvm7vnMAcCv6/Q1U8QOe/E0AlMUJAeNKfPy9rdT8eC5q9WOqdP2buYr9D0IZALkh1vyd2B8AqmrO/hNCAvwPSGEAoep8/uTURwBwYEsAZCp\\u002B/p\\u002BclPjtlsD\\u002BlPo/AhdeRP1N8EsCVOBc\\u002BQBOUQB0FfT5i5Ns9yAF5vuBevr8SifC\\u002BlHWcu8RjG8Acigc/uJKlv6FQ0T9pgPa/mPCEv6Vtbb8t71G/D7\\u002BKQNShp77Gvvm/GoHrvrcAgz7uke\\u002B/2oIjQHJZDL\\u002BAFr\\u002B/GPLLPta2jz8IEFNAj\\u002BWSv/VRlT9JL0LAzocowP9GuL9ZugC/\\u002B4ldvmb/Cb8xdYe/snFbvzPQbb/nxC1AGusKQMHzfL8oLxvAmHAJQD1Z7784\\u002BW2/XPgnPgTwm70IT4U/\\u002BvqQP7iqND8br5M/LvARP0fmM0CJvV\\u002B/tKAPv5blqL96\\u002B4c\\u002BAaeoP6LFF764tjO/Rw41vzLrmT5I6cu8vo49P\\u002BrFyz/mIm2\\u002BzVIVPu1KAsA5oYdAjcTev1wRBsH0Jh\\u002B/GAkcv9yp2784C7S/RrJhvr46LUDvgzZAmD7tv6FzPT\\u002Bs4Wc/eBjZP64dB0ADq7C/DKOOPtxKvD\\u002Bqfjw/S3ArvmaCmj\\u002B2bc2\\u002BMmqiv\\u002BnpWEAutI5AB8Sxv\\u002BTQ7D81zcw/IFfnvz488T6705O/ectQP3HrXj/WFRG\\u002BMy4CQDHBqz4je7S/JacUvkosaT2yIqU/GP5tP2/aZT\\u002BIGnO\\u002BvFKgv8Hb0r86Dtk/OTz5P28msL\\u002BmN1LAMNSdv592nz\\u002BiELs\\u002B6NQEwMv\\u002B3D6YkFbARNBMPzNsz76CIM2/FlKKvpCQHb1Ri9S/uWqCv\\u002BeHEz/fRua/ldRBwPEoSL9jhLK/\"\n  },\n  {\n    \"CategoryId\": 24,\n    \"Name\": \"Safety \\u0026 First Aid\",\n    \"NameEmbeddingBase64\": \"SKSfv2DoA70Sm9w/kIkQwJ25NEDCKWM/8McZQMLOSkAagGa\\u002BivpUv7nntb/CyZ6/t5V4vtQ89T9evK\\u002B\\u002B1hXLPj64az\\u002BZ/q2/9JgTwI7UyT\\u002BzmDo/YIdDPyDjmj8a1w3AxlSeP9vIaT\\u002BeDCw/NA2DPuaT1T5SOprAUbuYvtGsM7\\u002BOb5W9gHmhu0DgAr9z3IQ/YvjxP7QInj\\u002BwsBo/rAIKPiuoqT/EEho9aN/\\u002BPEz7Eb/oEv082i0\\u002Bv7YpAkAS95O/SFBgQN3jHsDLHBZA7qsWP3tNej/N9m8/VFuAP9JVB8BZyIQ/FsSsv9t7l7\\u002BJoHdAIOxlPxxsMb72gtDAIDEgQLYIoD/Yj2K\\u002BgSeYvwS8IUAzWyFAIQ9TPyqT9r\\u002BsPk09R/y3P7Vhwz8TEi3AKpXqvmxEtz\\u002Bi4a6/RhprP6TNhT6ulEq/Ws4gwAhMr76IrAY/rX9CvsCjib\\u002BoqLg/GBb6vqa8hj/0so69lPt9P7jsjb\\u002BzVABAPPKBP2aALD\\u002BAF\\u002BK/lkpEv5OVpL/58Kq/tygGQfomeb/Eag4/wpNBv1Bwsj4a4RlAcavGv\\u002BiZLkBS7kXA7KoUP6YCm74CAjBAJP1Iv8PMdz9YkYI9GXyLPkIViT\\u002BIsnC9M5aivkpQeEBdriHAkClsP7UX8b\\u002BkHShAyrUawCLPZL8QhgrAjZsFQOeVjkDq7w0/DhM1QKqngT\\u002BtvLK/ZEhYPTm9lL\\u002B0CnC/DL5UvdsCj7/ZsMs/ra/EvjNcej5\\u002B36U/2z9FwHXpCcC\\u002Bw7TAoJ3gPmBWtT/1TVbApQQkvqJ5478eode/W38RP2C2sL0rIBo/inmmPqTVEECbgpw\\u002B384MQNfkB8DQEv0/9l4ZP1oOAj5CKq\\u002B/OO6sv2c\\u002BAkC/e\\u002BC/WGqCwD5nlD9el9E9gKWZvVZGJr\\u002BbYYE\\u002BzM1iPb9ynj4ePki/GN28P2pSFj9cObq\\u002BzNeyvjcggL888uw/8GIcPxyk37\\u002BuFLK/g1WePkw64j4qAdw/fkehPQs6BL\\u002BdXgU/GugSQGEhKD4CEMO\\u002BfsmJPplt5D6YN2i/ZMwBP\\u002B3VP8AKtZS/tE29v6ZRoL6EGNM/1neFPomwEL\\u002BoS7c/tUsUQPBVtT3Go8A\\u002BWNw1wDN8YT\\u002BwQZ4/7oFuvz89Gz5NPcA/yLElwFWzBD77tqI/iIoJv8a0i0BLR5y\\u002BSpj5P8zcN0Cwmmq/kEeMP/DMF8F928w\\u002BkT2ePrRL4L9xrALAvlOEP2zs0T7ZNgPAqAuSwLEf5z5cMLdAzZ1vvzYXzL8MlRhAdlGFv2N2lj/1RI8\\u002BsPeov5DBurwR6I6/0pbJvxzf4z/a/DC\\u002BQj8rv6bfGcDYjsG/1rmmQA6qg7/nTHg/WiIxwBrYGcC/MTY\\u002BMJ\\u002ByPAydeMACFMs/DGPgPZlfG8DE1y69RlX9vxRbK7/rYEs/gpscPzjdmb4koea\\u002BqPfJPeqTccCL1C3AIYWav8yLDcDKQWa/jp8VvoD3mr8kGCA/vP7cPqxUQ7\\u002BlDDXAKRqPv4qjVT9BQzDANUQVwCj7Ir/vVzw\\u002B8LHIP4uOdsDGGmI/ulfiPl1JAT9YSrk\\u002B7lgkQG2cG7/i7k/AW98vQOg/kTzEKDS/JbIyPdt3dj86vIA/DgUTvyqflb\\u002BpiW4/XqPCPwSISL80j5c/hwsgvxFpez/qJym\\u002Bv1zhP65rJUDo9oQ\\u002BKQXpv35eOz8JV96/VETCP1Y4C7\\u002B\\u002BICJA5BMQwGOiCsGu088\\u002BGqi8PtN5nT6cTh/AeCnHPceDgz90amK/oKNVPxAzBD5\\u002BW2m/dNRZQN/fJkDCbgRA56UCv3Gp\\u002BT9xjuk/7hO5v\\u002BSeBr8aLqu/PuJvPz5wO0Aqqc9Ayx2yP/Ti5r0E0VM/EOtVP774iD/J8sY/ksjFP8fx7T/81Tq9kQh8PzRIAsCdO\\u002Bc/TASJP7g5o75XKnU/NhjpP0QWUz4GGg3A1aCXP4Of8j\\u002BcVJm/7t0ZQGrCzb9mpz0/lItwwAhHl76gqdM\\u002BWB4Ov9My176d8nI/no4rv6Csfj4d2MK/ADh7vlWBbj/CIsq\\u002ByODCv8NvhT/wZwI/48s7v/IAV0BSDNW\\u002B\"\n  },\n  {\n    \"CategoryId\": 25,\n    \"Name\": \"Outdoor Navigation\",\n    \"NameEmbeddingBase64\": \"XIZWvrq6mb9ON/k/CHOZv/U0zb1O1A0/pOxpP1AnnjxWVjS/NSUMv8ag8b06ofe\\u002BFGKRPhpWmj/aNLk\\u002BUjYWvwDivjzKUu0/R2uIP/3DgD\\u002B8HuI\\u002B5xUTv6KDbD5GGhO/\\u002BXe4v/tOQUAPM4u/x5CIPruETD/Clz7A5/byvt1mQ7/aqd\\u002B\\u002BCJXgPl49M8CMD/I\\u002BzP8avwAROT9YYxG922MtvpRVCz8xB88/jCLnvu0dQD6ARkG/672Tv8Yjcj6o/Ca/fD7/Pv3Lqb88QSu/w9/jvv3Qx7\\u002Bi2rk\\u002BNzEaP4fwDUAs00U/RVlxP\\u002BZJnT5\\u002BJ5E\\u002BBHeEPyAEkbwh7KvARxqWP3Yk1D7QbbA/y75qvx\\u002BFUz8wYNi\\u002B6wU3vyYDgD4RMMo/KHQbvazp7j3GDIU/tLgvv3W9FMBbV0M/ixSVv/EN2b7YyZ0/Qd\\u002B8PyRVab5Qrbw/91ACPyNc876v4Ue/jS1sv3hOBUAIfvM/vog7P07DEMCOywS\\u002BNS7OPdwahr9PpCu/sU5mP02\\u002Bcr95QkE/1CDVQH3Y3784JQ9A8IEXP5pTnz\\u002BV/IE\\u002BzIpYv\\u002By6Bj00mOy\\u002BHs2hv240Q75P1YY/GZh5v3pG3r2dshk/OBYZwM4GvD6diIm/zVziP0jgTr8qM2o\\u002BCj8PwFPYZr9YG/4/E84UPxj8yz9nczC\\u002BulXtP9fzHUA7dWU//lDdP1MwlD/QRLm\\u002BuhEtPl5DiD5gdYi\\u002BWRSqvu52UT/i6G2\\u002BNt8WPmx/IT\\u002BOJCO/IqLvPrXNA0BsYzbAKFEKP9/LsT8mb6e\\u002BW8a5v26nA78fLZW/1wsMPl\\u002BXjz6t0Xw/ThqmvtJpSr1544U/3WBdvhjZLD8RS3e/56HKPwKx3r5YcKO\\u002BpO4XvdQEE0DgCVY\\u002B01xlwOm99T7WteK\\u002B3/kUv7ABMr24p0G/JwheviZ9SD85FghAFTghQNDogT9yCB3AVrUOP7os9L\\u002B1P3a\\u002BciovPtjOg7/2yWO\\u002BcqBjP9e3mL79ewM/mKoPwIwbJr8Ajz6/LwVzPw5/S76eKb2/UckaPw\\u002Bonr6zLZa/RN\\u002BAP8yPML8fEai/MlCqP15DUT6sQxdArhcAwDmXAr9wYZQ83BoEQBKc1r7D3uw/v6w4v8i2fL\\u002BSMUQ/tJxQPcpqwD8Q73c/\\u002Bkm6v87QRD6puIe/rvo5P5j4Hj1NSHa/QsmCPtVIa78auzHAYumNvzEMpcBjQNi/Jj8dP/ZONUC\\u002BggvAvJKyvwgzqL7FUmA\\u002BU/rbPp6C7L9Uky9AKhSyv\\u002BzbYz85PT4/UW8aP4YQxz\\u002B0ZDY/5sSQPjpeqL7vQyY\\u002B1elFP9UrAz\\u002Baove\\u002BME62v6moAb4A4jA6OgWDQJZbMz/AMXE/\\u002BWY/v8VcCD8Ax/\\u002B5/BXvPxQLEsCkNDW/agJcP/y6/T4JhMe995\\u002B0v3Rewr9pRoo\\u002B4Bs1QHxDkD9K7o2\\u002BiSCzv3p1hb99RbS\\u002BFP3pv2HpvT9LIOi/NQBkP8hFq77SC8g/VxiOv9D9Aj\\u002Boabm/Ba8Qv/75R77vupW/6PTXPSjGm7546tC9rtAjPyJ8p7/6Ado/dlKHP5IE4L6oUCO/cGvIP9xYur4tc5e/BkiXPq6TVb8EBFu/PC4CPy6fH7\\u002BRTKk/5ZEAQBPceT/cM9u/OmSavqBfTr8d0pg/qVq3P2OX7b4EekW98h9Ev2nLor8A2OO/b3ouv5SEyL7UeES9mlIwvzzSScB7hEFA/v3FPmC5zcC9oF6/DpsmvWMnQr8Swp2/MMcfP3jzBkDvrpw/D9/Xv3bQHD31gES/vESPPcKSHj/RlE2/fqhJP\\u002BbEoj8kN3c\\u002Bvq/2PkTU\\u002Bz5j/Em/NSCvP1G2IEA34GhAg/9xv9IkRT9oM\\u002BM/QrD4v/UBBcAeDLW/fM0bv/6yqD/kG0a/MMRDQGKr\\u002B70w5aA/gmeLP32y4z5Dyzo/SHILvrJti75yk70\\u002BsbKjP/1X8T\\u002By/pI9SDYAP10BOL/2Dhw/7cgdP0I5gb0W1oI/zg6NPjzKlL\\u002BI/tq/wVMvPzMy67270ls/fOqzvzkupL8CEtW/\\u002Bd46vyoL9z4pMSLABAmLPnqU4b/My\\u002BQ/\"\n  },\n  {\n    \"CategoryId\": 26,\n    \"Name\": \"Portable Shelters\",\n    \"NameEmbeddingBase64\": \"\\u002BJoLvR7j6z1u2HU/NPhoP2bKKECuk/4\\u002BIIYuPRzcnL9Co9m/BqAsv4joyj\\u002BrRKy\\u002Bxyc1P13lsz82aZ0/SO9kPpaz/z\\u002BuGLQ/pjjKvn2Yhj\\u002BoyE2/xCoLvUwqOL2VB6W/9dWqPih1Kb96aYO/oWrLPo2zQb77Pu\\u002B/GpdKPxclir/02cW/miKCvmuUmj/V\\u002B7o/ut6ePyCVz722Why/HrXYPycijT0UI5Q/qE8uPnnH8r4Ue8c/jLzFvyQqkb9TTrW/Kfm2P7KrF7\\u002By7Hs/cAfgvRDjwDxmHUe\\u002BQgdKPwIRWT/UQDi9QL9ePyDFVb84A/8\\u002B0MfhPbSFej\\u002BWtCnAWD4vPriVMUDyHcY/kbKavyJftz/yHGo/MprxPhB6Ur0G9Zg/pq4FP4x7HL0nBIY/osg3v20fpr2oxUM/nv/Lv\\u002BYT876aLy3AgBrxv1/nHr8wZSM946kRwEB2FkCeegc/5gZov4EXvr5t3aY//LgHwOxxrj9BKT0/6CDVPwNYLcDGXs2/CA2/PfbcCr\\u002BWMg7ATH7BQAlxMz/Wh6K9vJlzPnb6jL8EUPC\\u002BbxGcvwivRD5y6Ki/rqQov6ARtb3MVBc\\u002B6RTOvY1tcL\\u002BM/JC/A2ukPrO8Db8xx9u\\u002B5yqePxSzXz/z3ek/TfK0v1t\\u002BNL532as/oGxZv3M9Cj\\u002Bd7jM/yqtmP0orxj/OZ20//TzqP/xGoj/uzZQ/nxW1PkYJuj6VF/y\\u002BPEr0P3UuQz/gj\\u002B2/YHlBP4CSwz6K\\u002B6M/mMu/v2rX9D9SV1HAoCarPcBtmD7Hjqq\\u002BUFnWP\\u002Ba9Ub8gNVW/6dAOP\\u002BDAVT/seTBAgRcuv8gk6D9rKHa/U1VGvx9eDUB4iu89oPnVPQrUjz9Sb9s9iBexvYq/VD8lb12/gvMOwFh4Zr\\u002B69po/CizWPnBlv78h2nC\\u002BOhwBP0K7sj8MUiC/1qufP0xKqL\\u002BIvdK/g6xjPyRe3L95\\u002BqE9WCD6v/NZt79zjRC/3HuxP5RzAr\\u002BwNr8\\u002B6nacvtZTJ7\\u002BGVZA/N9QaQOJz\\u002B78VDvG8yiwdQGjZyb9w6lg9vluIPrF1gL8QIwG/igIjvvAF2LzEbV1AnF4Xvc7VtL9IMrW8EPnEPzfgkD6rnIy\\u002BPIWXvz\\u002BCUT\\u002B4zom\\u002B3jGIP32f8z7eGA8/oN8Vv0SSR761pwE/l80OPrSdXT5IqjE/18XzvsrveT8A2SnAykrtv1JRr8A8Zxs/HM9pPvcWzz4iohzAwvYmvxY3oz9Vorm\\u002BHOgHwL2dhr\\u002B6yq1Ae\\u002BUqwNcfSL/OIaM/ZRCGPmAWhbzK62O7oTEWvwzXuL5tRzO\\u002BrgjPPhpKPj3oOgI/I3ssP9nhCr9WX26/gL6AQNeWGL/AcBw/pS8FPphqkz/AJhI\\u002B1NPKvpVdZ8DlphQ/S9JdPzYByr6tBQ0/LuBJPy5COj8pwui/psCKQJ35gD9epTLARggtv6PHHb\\u002ByDJ\\u002B\\u002BcvZ4v9R/wb/8sWm/mOVZvvMHUj8/PgC\\u002BSnw2vopjyT\\u002BhVbG/sNT5vs39db\\u002BUwYq\\u002BUXmSPnD/yj6Edmy/VjVuv4xRAj6ezss\\u002BQK9Svps4eb8xUg0/GKvHvfGzHMCoQl\\u002B9pPQRQA3LH7/cCMw9FUP1P75mQb\\u002Bb3UE\\u002BOxsaP3GOPz5bgam/IA1tv/ne4r0n/iK/jm5EvY9AID/YAKI/\\u002Bmjpv1iA7j/89d\\u002B\\u002BO7p7vlKjTz5S1\\u002B8/KMmwPEH5pD7Ckbk/GxSHvYiGy8Aaqm4/PfUePivTUMAwvuS/j1AHP1pHI7/cZds/dIqtPuKPhr4ys0\\u002B\\u002BW\\u002BXEP0KZiT8sMJ49dKVaP8D5oL56EA4/z4OCPvvspb9yRiXAAgFLvtIzfr6\\u002BFH1AFlrPv/nftj3e5/Y/WdUgPr9lxT\\u002BBP4K\\u002B9gJbP7lcfL6LQoq\\u002B\\u002BrrZvlBBxL/oBBe/jAsTvxc7JL\\u002BYnsU/Ih5nP/B56TwsnI6//lALP3C6rD0VUYa/yI5\\u002BP7gF97/kx8k\\u002BoDW0v3DJ3z9fGsy\\u002BKF/0v8rkkr8zvcu\\u002Bk\\u002BuLvVSbMD9BRtY/xj0Lv2g4uLyrK6a/TAbXv1F/rT\\u002BxsRS/bIodP3hAx7/IqjFA\"\n  },\n  {\n    \"CategoryId\": 27,\n    \"Name\": \"Smart Outerwear\",\n    \"NameEmbeddingBase64\": \"ytmVv4aCeT/e5SQ/4u7nvtGzB0BcqQs/5liKPxwoiD/sJAbAPhTRPJPaEL86mZW/7t/NPz2QpD/m1ek/5RXIPr\\u002BwJEB4N5o\\u002BwDduPvamEUAUroU/srCYv1xDwb8S\\u002B6K\\u002Bk9icv7tyCT/kq3i/29BtPky1qr9v93jA8Qjrvl6wnL/sDQpAUODKPfybhL7al7a\\u002BhLEQP9wkxb5gwwY\\u002Bhf1Pv72vvL82vA4\\u002BMZQCwBHEqr469oE/bYCGv\\u002BB/bD9sRee\\u002BJtlkv801tr7AmfA/ynv2PhpK6b\\u002BC2xI/4Vv/P1aCGz\\u002ByfoK/nDKgvepRlT8\\u002B3kS/Mi4PP19Czz/Ka3PAxOElQH3B6z\\u002BU3fc\\u002Ba7GEv5x\\u002BT78ymfG\\u002BdQhgv6UnBUAGbC0/l337PwZuCUCK/EM\\u002BCrQ2QIDd\\u002Bz30q\\u002B6/glj6v5TPbz4wLMq8VEHGPjLmVD\\u002Bs2Bo/jzD4vhOsmr8C7Lo/OjI4wA4yTD86EVM/bjC4v2ID4r15me2\\u002BMkHgv1jMFD\\u002Bf/pO/PAuhvmB79r8sJ5O/g1b\\u002BQLyFk78MJKQ/AH0bQCjr576m8pc/hPe2v/LywT9lE4S/WxvFv4pPDj8okB\\u002B/mKWNvyBuk7\\u002Bsnkm/hpkIvlirJj962nW/GqfhP2u9/z/C3SQ/cmCfv5nd\\u002BL8rdmg/FVe3v6avgT4LklQ\\u002BZLw6QAubAED8woq/akoOQBcylb4SBr\\u002B/JMRHPnihCT\\u002BgBko\\u002BTPBbPw1GKr/PnOs/HIT1vgz\\u002BLL5SH5W\\u002BIN41PzEoeED2SnbA0VJcQAVrtT\\u002BQbBQ/gwgJv/KVZD2ESJS/IxaAvvshnD2dqbM/b9hQP9uaMr\\u002B8cpW\\u002B9L8WP9BhmD5i8lLAgn\\u002B6P5yFsT6E57E/4\\u002BxjP3XPPT\\u002BboRLAPo6cwPzbRj/Kyn\\u002B99qqIP\\u002BhGiL9u4ak/Ppehvpx1GL9iULE/mp9dQD0PRz76Ms\\u002B/joWzvxScVL9pwpU/hp6ev\\u002BVUCcCRYP\\u002B\\u002BiMyJv9jffDx8J\\u002B6/ngADvrzdnL\\u002B9QLo/GHs0QGJagD95Mt2/OmRPPyGvh75QF6C\\u002BxsokP4\\u002Bisr8Apyg8JNxMPcia\\u002B72BUq8/b4SCv\\u002BRVs7wvCoE/KXSnP12IHT7ucAtAgMy2vzaIrz/U\\u002Byu\\u002B4RtCv1ofxr74eLo/8lWVvoImRr6G44m/2oHCvpJUFj\\u002B477Y\\u002BVLopv3KVPr/q59m\\u002BoEljwBcR1MDUCJQ/E3NNP1yFNL/6gUG/Nkyavk7lYT/hfMC/hmrwPxqOHMDQsWdA9s9kP4KQiT7kH5c/C9aPv\\u002BYJd0Ay9VZAGKqTv6hS/r9Qbis8E5iVv7wyg0AZln6/crCkv9bvur7cYao98\\u002BmkQJAL0z\\u002ByI1hArU5GPyzeOj6eGkJAw3NTP77pV8BiHyNARJ0iPw7FFz\\u002BM7JS\\u002BxAFtv5TdL7/09Ze/wfMpQPb83j7yEIe/ttyAPxp8fr9C8Nq/0OWlv9N8A8AQgJi8wHF4vwIJND/wcN0/p8jzPq6z7L/AO7u\\u002ByBGxPDkNHb9R9wA/RHZqvQBYgL8nXW2\\u002BtY6kv1c9yr9uk\\u002BY/xJwRwC6Aoz0oKWq/LIIOPXxkrr\\u002BEFKi/qEAKQHE98D4zV\\u002Bm/\\u002B50LwHp83b42eZo/axuYP9e6Ez8fNXy/2spxQByMNj/vY0A/ReY1v7AxZLyub2q/9qAWQLavq789zkY/mWQQv1o/lz5\\u002BUWQ\\u002BzympvlbGjr\\u002BSZ9c/fBpKv1e63cCa4ZA9ox96v3sotj7abrq/XHtuPiqLVj8Oa6S9A1Ygv3hD3j9xLAHAkuU9Pwaarb29jcE\\u002BeHS4vJQwtL/jpRxAueKpvySkND8aRDLA00CTP17PmT\\u002B\\u002B35dAmt5dPVR2N74mnuE/aHkqvxEyaL5QX7K/8G7EPmLMN0COxZU/2KxrP3cGaL\\u002BAev\\u002B7cs\\u002BWPyHHir8yJS6/fWCMP26laL8ogLW8cMbFv/uhYL6/kT0/L9ImQFq91b\\u002BwidK/UqiCPxr9sL4ml0Q/dzEFvyvY4r/OVCK/ki6sPuVrZb9a0Rm\\u002BfMUqwCYJXb9ouRI8iv3Rv3EKRj9UbGzAeBhKwCrskb6wftA/\"\n  },\n  {\n    \"CategoryId\": 28,\n    \"Name\": \"Off-grid Cooking\",\n    \"NameEmbeddingBase64\": \"ashSvw/yJEDvIJU/YLeMv4CUfz8Y2IA/qrF8v2iklL6xLJa/JgSHv4Ra37/SfpG/lcawvwyssT\\u002BMSoS/sa0AvxumFT8XreY/HPSav9hJSz3gUwBAFNhywDA2BcAU9Iu/WKcbQBYrjz/svui/l/lFv6Zv/L8TwLbAoLcOPxquPr5lL8\\u002B\\u002BNiymv5QSmz5o8Nm/KJNfvbUd5b6aEWzAWPIbPTg8/T9214k/jPQLvXlij7\\u002BjU9i/5F0Hv4bn17/1hRm\\u002BufQOQILYJ79rEo6/GIwJP7mt676QwwQ9e3BVQDw0uT8g7Fk/U2Utvy4Gyr6LRRM\\u002BI1iFPrpbtj/IrcHAdgsOQMoihj\\u002BIvkm/lOj\\u002BvRpUqz9h8g9A2rgnP27KH79LgYA/isfSP9Zb6z960NE/EL4ou2Zd5r8k84C/dJ8kwE96rz/at9I/cIEawCfAwD\\u002BAr7u6JH0EwACoir7ZiPY/nJhdv9Q3rT\\u002BSNoe/YD3gv0xZgz\\u002BcQsA/Zug/PoueRMBqyou/KSlCP5zeQT11PZS/cYkAQb36AcAh0p\\u002B/GCJQP0\\u002B1ej9gcbe8yCUFwO44v77GdCi/9mnZv5xOfr\\u002BRqcm/BdCqP8dOHsDxY5I/b0jZP2DsEr/IHSJADm1vPgUWSj6VnrQ/bHD6vyxbO0Domy4/kRQJvxwL6j\\u002Bzxaa\\u002BulAuPwNPZEBkT0C/hARvP1J\\u002BOz9i\\u002Bry/FJ7rP5jzL79tOWE\\u002Bs37SPo3qVEDA\\u002BqA/EW8XQIugRT4YlpI\\u002BLqtAPpqqrz9K1cbA8D2JQGENIEDdg2G/Fp/JP6RqBMAU21S/jlnBPf6psz/IJX8/bVmwv5KjKD8g5ag/sCPrvv2N0T4HwHC/HpBBP0ulHcC/ON\\u002B\\u002B0Jv/vhzX6z\\u002BOQ4W/BVdwwJfI\\u002Bb5OBt8/cnBiv4pt7b4YEdo\\u002BKwe1vmYuyb9WYhLAfyQ6QMkiIsBPHQPALeCvPcFecr/266U/E/uSPyJlpb7qkVU/R7pVP2pUZT841K6/m3Gsv6HH4r8CI5q9KHbFP8YHh8AQDAzAHl7JPzmjwT/aO5S/VEFav2esGz6eVxe/oEbnP19DXsAqOI4/fiyJv4Klkr9aHfI\\u002BDsMBQIf7L76Xzo6/MaakvudBCUBfrZFAcAIvPWPWzr6VSRdA3hgKPyMZ5L\\u002BhEVg/nsU0QMpfDkCQlgY\\u002BdE2HvtgNPkCupnbAmssDwI/xAcFQkzq//GWYvyg\\u002B9L8Oive\\u002BiakYwIhH6z60/gfAcpEvvxG5jj8cpgRACAyJv5GpCD4eoms\\u002BypzBvRe1xT/icqE/mENAwBUNVb9QiTs/QAx3P3JCIkB4lZk/5PxJwEGjsj/1yik/R/LcQHKABD9sa6NAUSaZv7NzvT6rkYw/AWc2P2AbB8CC2o6\\u002BluqrP/A6CUBdVve/kvcvvRatDL9iMn2\\u002B/6cSQACBU7vPcGLAfhaEP\\u002BVfrr8XVi4/w8w6wI/Csr\\u002BCO2\\u002B/0/5UPwSvzL8kaj4/3SMyvpCiuj90wzq\\u002BHDkfwDqYsT\\u002BIN/u/VvoMv6I37z0k3lI/UJDzvsT2D7/9Cqk/crf7PzQYWr8M/RY/h\\u002BGyP\\u002BIARj9Gefa\\u002BSyDiPwWSyj/UG3U/hhzJPWJD7z4qVRNA0B6\\u002Bvhuep7/woCPAkbkcQHaRkb\\u002BOQCZAzuVaP2plYT/aCLc\\u002B6gzcvyhm5z93//Y\\u002BEGBnv6pfr75xuO8/vEY6wOFeHb5lYYpAURDqvfw6D8GoyjBA3MTivlwrFj4dWGU/aCTgPeRjrr9Pd1NAsdtJv4QMVD9FTMC/klDmP2rWzj9M7QK/7F5lP8gRxj6kaiJAHZaGv\\u002B5K1D/Q5gvAj9oiQKsUkj\\u002BySs9AexQZv1lstz5YvqQ9HjSevtKPmb95wHA\\u002B5mk2PiDdUD3LMo6/bBynP7hCpL\\u002BKz0RAdEbZPqcbCT/bAUy/7Hu\\u002BP2irL8DAoYjAFAK5PO6b6b6Kw5\\u002B/7bCeP3g2mL9u8CC/2ZQgwNh7Gr6sOxA/0hkHQJDppj09y\\u002BC\\u002BMIQNQHZnqL6FR80\\u002Bwp6Dv3\\u002Brhr/mpJI/TL9nP3j0jz/KR1LAaQUZQIlN476yXR\\u002B/\"\n  },\n  {\n    \"CategoryId\": 29,\n    \"Name\": \"Water Purification\",\n    \"NameEmbeddingBase64\": \"7VI7vzP1Zb9CVjS9onSpv2rIEj9QuPm/pIoNQCAokj/WBzS/knjhPY4UQL\\u002BYAm7AhjgpP/oupL9Ty6Y/gmkOP7Lh5D\\u002B5Utk/GRkkwCpwjz8deaE/DLhGv3Pbob9ZfUW/sHOYPYAmODtGIeI\\u002BDLyVvttEqj/vEkLAjLZpv7XcEb\\u002Bh4lw/sNBou5Sjdz6SWrY/PtMMP45zHT7S3KK/vtkLvka7EL\\u002Bq08A93Om9v3YGHj/68NO9COcRv1oOXz8quOe\\u002B\\u002BvMMQKHj/L/QvIw/6tefvluk3r8adIQ/mtZ9Pwg9rzzIZKc/dFiwPz6wPj9GWWi/SrB9P8ZIYz\\u002BCklfAnmMMQBxAVT/5tQxAivEcPly2ibzukPA/E\\u002B6XPhNdXb9GFog/5LGwP0RrrD68Pww/6kKwvppCrr6AJIM\\u002BJasTv67Fhz8KNJQ/zsu9vzg73j6yxoC9F7efv9IqsD/y3kM/rhGDP9jlh71yrgk/h0ucvx/HhL9/t7A/tnfLP2V/Tb76EIi9GCu6vsk25b6UMMg\\u002BtlDnQGj0FMB243E/TPcEPzb4BcCkKek/mn\\u002Bsv74Rm7/kqhK/jgAvP5rSgD\\u002BQp8E8MD0ov2dVqz94y9y/a81uPh17gT\\u002B862I91j\\u002Bhv/hgk78g7yW8ddlfvzbAY79KCNE/0JLxPgytwT\\u002BLHYY/QGiYP7KrEkBn5wrAflAHQGThO74yp4O/eXwAv7D1H7wMUBo/e14/v04QoT\\u002B2Liy/FgAPv9s\\u002BOz/YFta/dnoov1hl0j5AhEbADQyPP70OyD9aQo2\\u002BBOjvv05XtD3CP4q/72VLv/ZwR0CG0L8\\u002B8CtPvQKFyT5lYro\\u002BFGO9P3oA1r3k4TG/37KbP05fJb\\u002ByAVy/ZUN2v9lXLkC4WpO\\u002Bbqx8v6Qt371c\\u002BSO/Wq4AwIQDL0DuxTK/XO4FPzgqUD/sX/0\\u002BqLA2P169k79MsB6\\u002B5psJPzqFbD7K002\\u002BGD\\u002B/vzKGLD9rItq\\u002Bx/sVPyevgT\\u002BJjwS/qkgxP15eoz0cj3u/2uDdPwhA3b\\u002BsEhA/ugkHP1pVXz7t/GA/WCB7P5ANLL\\u002BaBKC/rS9Tv7mgAsAdoC8/wN6Jv/Ls0L8JpYq\\u002B1t5RP\\u002Bal6j/Oepk/whk9P2telr6rwilAHzoBv/HiSz4GNki/zfUGv/ysWr1rnVs\\u002B0w0sQHWAFj\\u002BKB0Q\\u002B8wfGv1vG7T\\u002BcBhPA3xUdwKDLqsCCLY6\\u002Bd3s4P0x2V7/8Wvk/qIrKv37bgz0zbEG/WmOFv9tkRT4sxMU/RMfkPq54qz7SC2m\\u002BRobdvkWIgr\\u002BWN2ZAGuKRPkOJWz87IJa\\u002BVu1lP8iKOD\\u002BGLPE/qU2yPyQAQL8ytG6/n2dCQNA3rT8fllU/rPidP6Cwor8l1BI/MCypP5tgLcBUvLG/M9gvP5ytUL/OVLC\\u002BoWSrvrkxzb\\u002BGHWQ/pghcP7wErb8hpNi/0zczvmfJir9sh72\\u002B7i4bP9hg2b8mHsO/FdWZP56ubD9VDjA/mJnpvJaywT3kFmU/9bVev4oOST80mhjACgn2v5i\\u002B0D5etYc\\u002BBVMqPtVg1b8NzAo/44O\\u002BvpKpQ7/7p9g\\u002BQZXGP7xHw74IEoG/svOFP3lKqr8FWak/gBogv\\u002BABvT82tFO\\u002BwvsNwJ4n0D5yOQXAmA6BP/4Vqr9rw5s/2BY9P3uTxD/YVNE/C/Uqvwgy1TvLELe/gMqyu0Jhij525FS/KguDv0YDtb8wbbE/NsVMP3LjssAOYoW/kB/EPxg/vr9EHBK/UKZzPVykZD5oPYk/fdR4vot/KUCA05a/tZOFP8qGfL9OnJ6\\u002Bm\\u002BpavsFe7z4MWg0/vRaMv\\u002BTSoz2hp8u9FMceP9iyTD\\u002BbhF1ApZbVv1Wenj5YROI/CLj0PW4C3z5C1VU\\u002BrvC/PQofWz9e9qY/WhI9QFTZYb\\u002BC2pW\\u002BpB4tP1hkxr5CyIs\\u002BYqG0vnBLDcA\\u002B0LS/ZoOBv5iOkb8MvrW/UvlPPlbG0L/EAV4/igcmwC2pXj6TiYs/6qPCv2ZKT786/PU/\\u002BApKPXKROT9TVeY\\u002BXF/6v4UPqr\\u002BMlX69o78wv5pVMD93I1q/dW58P9p4jD3\\u002BQia/\"\n  },\n  {\n    \"CategoryId\": 3,\n    \"Name\": \"Technical Backpacks\",\n    \"NameEmbeddingBase64\": \"efwyv3QNBUBBo7k/85JAvwI0uD8QjLy/zHPUP2rtHUD2f9W/eNiZvzdRjD7HOx7A4BNIv9TIvz/GHw9A4mgxP\\u002BmZGkCjL78\\u002B9RjjP6qVfj8qWgRA/Qm6vmSXfj4QrUW/Upcqvz\\u002BJbj7vCcA\\u002Bn8eVvziBG7//GoXA7F38vnSN7L\\u002BSnZS/AMuBvva5FT\\u002B5ojg/oAb3vHNBjT4SwqW/5vKLvwSpgb/0FN8/D\\u002BEZwLYin78CYgc/uczwv3u/hb\\u002B4r5e/Of9mP6lt175CCH2\\u002ByJkmvmha5D/k5bi\\u002BUrcUwAFRzz\\u002Ba\\u002BY8/Fr/3Pw30yz8TVuq/qhUmQI\\u002BEfz4S4prA7CUbQPLV6z\\u002BA6tU/nFmkv/5uC0CfTjFALY/yPlfnir4\\u002B8v0\\u002BbKylP5oM/D\\u002BDjnw/huZeP6RsCUDxxG6/pHKcv4tO9r9kr4I9nv6Svw7dgT6Ql1U/oKmevwoVlD7G\\u002Bpu/FPSsvcSSW73\\u002BwqK/sVBGv9pA4r8qCbA/qrp8PwoRgsBiBFu/VgJJP5xF971Jo\\u002B4/5lDmQPAJVr9d\\u002BJw/n8J5QP\\u002BmHj8y38U\\u002BnJAewFLKvz/zN86/ZPnQv50\\u002BlT7QYjM7r3apv7pLEr9o4ng\\u002BvDCHPdAEWj6WTMy//1QhP5LO5r5ibP8/eFYswGukij\\u002BlexVAoF42v0UZ8b7msDM\\u002BsmrtP4Al9T9yNwi\\u002BvURCQBgpp7719ktAMvdGvz/TY7\\u002BQZ5Q/\\u002BGW8P2CRAcC6vgLATANNv052zD\\u002ByWGq/DqecPzTcrT8RdmPAVvHYv6RAJz8DfCI/KKt2v/URgb8PS0S/mNY7P1TTBb0EAOY/3qAMvzpo8L5d8xBASDA\\u002BP9psxr1wCq\\u002B9W3qgPw9SIb9M96O/gbsQv\\u002BWM5T\\u002BDJpE\\u002B/kVIwOKrNL9\\u002BI6G\\u002BMr\\u002BZP2cSj7\\u002B0/Xe/gGUWPCKUJz/apgM\\u002BCNUNQC2GI79NYjXAPAJ9v2XhBsAsDZI/d9QDQMNUg7/Te9q\\u002BxBkVP7rqtD9/Qo8/4AAAvw//DcDFX9I/oOhVQIWL5T\\u002BgdwM9tiz2P7Djj7/0b2w/zEyUP5Q1Ob8gdoy\\u002BeqSEPlO\\u002BOb8m/FBAc/tOvzzHpL/qvFA/MFffvcBw4j\\u002BCJJM\\u002B9A5ev5YSwr1Bwvm\\u002BU1oSPppyYr81fZI/HlxgvzK0s7/eFVi/MvGyP7oPjj/Yxw7AnTSHP21ri79uCPq/bQabv4SW8sBef9E9jF6aP\\u002BI2hz9M7v09UJfzPBK9AD83zjk/gjKuPvaNAL9AzmJAxryRv3Y91L5S4Ka\\u002Bxhymv4C6Oj9ptQw/AXfnvplc17/AfRe/Xf6IvliE/T89dNu/ygDVvw6zcb/PgCU\\u002Bbg\\u002BXQDRkkb94CAtAMk\\u002Bxv9/HIz/Gw7M/uqt6P37Ud8BslBRAAWIcP\\u002BDzzj5KlvY\\u002BBH8VQFlMzL5Q1xvAKF4wQMPpJr\\u002BCwQvAlk\\u002Bzv0gkhr8cAPm/nJr8v\\u002BAUXb9fTgu/Um9hvxXHmr4m6pw9ntmJv9H5Kj9xrADAtBecv\\u002BBKcT7dxbm\\u002BvCAOvxLgcb\\u002BEKwg\\u002BDM1LvyLFg7\\u002B8j4U\\u002BzJmpvnPytL4ZrMe\\u002BmE/2P1yLAr9sfYM/WokRQOSFF79aANE/T4YsP9E1D7/CDPM/O1t2P2iEvz8ZqYK/boUsP3IUiz9Enig\\u002B6//Dvzi3GD8jvdw\\u002BSdUxP2WB/b/VpxO/KFfMPljh5T6Q8J4/SnXTPU6UIb89PYhAojZTPt\\u002Bd/sCm04G\\u002BPh6DP7BwC8D4bRK/OAbEvww1oz\\u002BNTqA/2OBTPx7dHj9QU\\u002B6\\u002BjbcHQMh\\u002BKD9LJ4Y\\u002B\\u002BLvsP0YImz5noj1ANlu8v3Ix5z9Log3A52vev/iHaz/UAbFAT6UCv7D93D\\u002BiaBdA/P\\u002Bbv9b8J7/Jg/c/yKpuPoDtkT9g2F8\\u002BHoolQDqF6r9QTdO/RzMIQFalHMCYAGe/IlnHvpYUvD4j46q\\u002BQlkxv5/ZNcBAbVe/4AFyPzQUr79Mxby/ite\\u002Bv/mlMD8/zpa/PI7KPqp\\u002B9z9vD5q/4yNuv4LX8T8GeKc/hhpCvoaLB74BgAHAeA2Iv15WqL0UifW/ANDEv5hS17zh8IG\\u002B\"\n  },\n  {\n    \"CategoryId\": 30,\n    \"Name\": \"Weatherproof Tech\",\n    \"NameEmbeddingBase64\": \"iNMEvxxS7T//UfM/egAzv3ldNkBzO6S/ATPVP2e\\u002Bfz97Sba/4AWxvUv1pL8NlDC/DtjCP0hyrT8zIrw/CDNRP0iGJ0AtqqU/NALmPwXIIz/VLOg/knbKPknS4r752NC/ZEM9vo//sj49NT\\u002B/5W8FP9Bp3rxFT0LAb5N6vyyDo79q\\u002Br89FtbPP2hEwD5wPR0\\u002BbMDyvCPIHsBWVuq/sr89P24Fy7/gLQG/5eZVwDIcvL\\u002BBJjm/jycgwLU5uj9o6aG\\u002BlyczPy8B\\u002Br\\u002BImAtAkgQQPpEmgr9C2Om\\u002BPK3DPlFcYj\\u002Bf2aG/UBfvP3YUWD/RRpe/R08oP/liOkAOzMfAh7ASQPgmF0B5PRZA4YQhwO10bT9Xppc/l3NmvxDEvL1DcClA22xDP8Z5yD\\u002BpDqg/eGXlP79UvL8Ng32/\\u002Bj30vzf2HsBEC1s/XGcgwAflF7\\u002BQvbo8SOrSv3xvND\\u002B1x0y/zSUCvstUqD/LGt49wh4pwOWRzL8YrM4\\u002BkFSUvlE6H8CZrsA\\u002BxeYfQECPv76GtaI9ljXoQCx7fMAVZza/kznwPkkY\\u002BT\\u002BGH8E\\u002B/22Ov86sZj5gp0bAhJgEwHH47b54xqM\\u002BJ92GPYwuZD0mJXg/RFsOP\\u002BgFnT3Nfbm/WtQxP1T8Jj8dlYi\\u002B3SL\\u002Bvw4QQj/thB1A7dVLP4YAdz70k1m\\u002B\\u002B0zdPzEljkCGZYy\\u002B1qp3QKRUZT8aez6/D40/PyDQTD8q0d4/9EJsP7ZID8AyrJ0\\u002BdMyrv8CfSjyYyXm/iCINPsO/Z0B9N1DAmZI7P7IPOL\\u002B2U/e/V8IZP9CnsL6w1jfABX1fvmjUPj\\u002BpwwlADYuevxR0I0AgIa8/5AOZP4XKhb1U8qq/guQZP\\u002Bnc9j\\u002BQtZE\\u002Bv\\u002BCSv/vkIUCPMlu\\u002B1I5KwHYUiD8hRfw/R74rP6D3f7\\u002BplnQ/3td5PqISAT8Cmpc\\u002BlyD9vmSzzb6TDe2/rLbNvj8gxr\\u002Bbx0M/QOCgPmzjpr\\u002B791c/Caj3Pu7AyD/danQ\\u002BcsdEv8gT1b/43F0/q0inP9NEtL9TdZy/SmavPtgQRz84gEG/kfDhP8ei1L/4A2K9CGTkP5xCGsAsMQ1A\\u002BvI8wM0gkb85/Wi\\u002BLI/wPS8gEEBemQtAeJUTwF6kU78YVEq/Mwb\\u002BP/WKAcDPH7I/0HQbwFcG8760hz0\\u002Bf/1jP9jXjj/eogs\\u002BgxBGv/LdfT/soPO9hpGkvyzjs8Ac70zAUXjsvmcvFj9BHNU/uCWXv3a4\\u002Bz7Fb76/P9AJQIfUlL8M3YpAgNQYwHZqEz/UjYm/2XE5v/iKLL9ZBRE/AxOMPy7IAL/WM7a/LSt6vvSeIUAodPm/LxZswK76Xj8gxZa9lneKQLQ2Ib8y44U/M\\u002BqUP55MRj7ZLX2/0syVvUtrjsD6TjY/TieAP0U0Dj7mtfg/d9Kgv8NWPb8L9MM/pnkgQBO5pj4T0\\u002BO/uOIcP0qgKsBwzqy8WJJ3PznSHsBQLU3A9kCNvhl5pz9Ay2E9hglJv1Dg0z/EuOC/qrTtv5Exhz\\u002BE1AU/7qujv44F8z9EJLq9M6d/P24AHr7akbA/VPLLv0AfCT8netG\\u002BpkJtP8gdt7/RRQo/kmgwQDLUkb\\u002BbTQdAT56\\u002BPwgjqL\\u002BNLRlArvFUP1s6xT\\u002B2DlG\\u002BsKMLQLAjHr98Xf0/3sRsP5tFmz\\u002B0Jgw/odPePlxRor\\u002Bf/to\\u002BagnXv//qUj\\u002Bls3q\\u002BEilaPzXBPsBzMopASGeMv\\u002B5M/sBm4Ce/dFWxvgzyEcAnej3AT54ZwPINMj5U1h5A9LCvv2/1tj/rxIzAGQaTP0pYBr403/G\\u002BbEPbP\\u002BO2lz8QIJE/R\\u002BYGvUFXlL5N04s\\u002B0Bedv1SHLj9OyKdAMIy5v2yz2D9k43NAwO6rvsx3Db5Nm/I/crNUPxue0j\\u002BN6ai/Vv\\u002B\\u002BPsoClL/rjhy/xHW9P2rbQD/ObOg\\u002BknSMvm4W8D2kxJO\\u002BEMTrP4gJybzNsJm/1qPtvZSfob08WzW/jrUlvo7B5T68Vj8/oeAHv0TJjr39HH2/SFOUv91Xzb92Qzw/nLV6vi\\u002B1CL9ME1\\u002B/fHKbv\\u002Bk01T6OXjXAb4WEvy4Osz\\u002BQHss/\"\n  },\n  {\n    \"CategoryId\": 31,\n    \"Name\": \"Trekking Gear\",\n    \"NameEmbeddingBase64\": \"1kV/vxQOoz\\u002BjiCxArGHJv4Rpnb9P3J2/djoGQEqQ0z\\u002Bq1kXA5kgLv/6eGECtFjDAwn0QPrvWpD\\u002Brq6g/VKf1v\\u002BqANUB4x80/pnaTPwxpej\\u002B/eY4/Gx0OwKaRm7/Uu9i/fjbNP31itD9U7zS/GM2svx6aD78rAlTACEq6Pjdbnj5onD2/XPCOv5R5cL/4CRo/xIcHv67ewL9II/y/JgStPwh0CEDzJ/A/p\\u002BhRv4vHAj98vBq/L/vLv9xclD7YbL\\u002B/vsglQAWZGz/L2aM\\u002BuBDXvwE3sj/Vkiq/Kzn8vcgeUj/DYlk/ZuRgP4Jymz8MXoc\\u002BlbFdPszLWz8Su5rA28cqQCSLC743oZw/FLTqPYUlMj8WG3A/BXeYP\\u002B3uN7/P4b0//mwwP09n6D8YYic/W8UoPmxzAEBQwka/NKa7vkzQ576Sooi/9MSkvyhPrb4qs1I\\u002BO2k/PpRyuL\\u002BMxxO/W7b1v0F9Gj/eUY0/FPprv0oBX77FFn2\\u002BR1xkP\\u002BRhMcBcLte\\u002B\\u002BJi9P8COrr7Qj3U7rcX7QGIC07\\u002BWZYI/npksQOwkvj8iXPM/j1EGwO7/\\u002Bb4oPtq9ArM0vvxAYj9vfTI/q/GlPYzYoL89wIU\\u002B5LddvwkPBEA6zvK/r54iQMmYkL8ggHm9ObMDwGQE7L4RYQNACKRWvywgw794via/8tcoQEKSH0DVgxA/II6DP1xJ0j8crB8/GoKKv8upwr6zaPy\\u002BPABtv3G\\u002BPz/lpmS/rEZiPsY0FEDdcS6/DraGPlYAK0AMRHHAAALwOXUQZb/u90C\\u002BbGkyv/jVYL\\u002BIaeU\\u002BTAqfvzTtlz1OQBM/yKrUv5v9oz8ykIM/vqUmQELLsD\\u002B4GT/AownTPxKQjr8QJMi\\u002BdJ9SPhRhQECG9l8/S8eTwFsllD4Deo4/vM/IP0gm3r8i5Xq9SgzDP5RwnL4rC1s/FyEhQM2Y/L7DXCLAXBDNPypMAsAuW3o/4PkcQLzfQr/CvQ6/C38fP787Oz9\\u002B4Ka/BGMvwNq7zj9qPCc/\\u002BfKWP\\u002BHuIECZ4Ze/2fHTPxV8Zr7\\u002BZ\\u002BI/2qHlPjIXpb9yy2y/aiX3v1J8xr8OatY/Pzn2vztJS76lNSY/yC9MvWqMuz/erSG/igpxv0zHpL/sw/M/2wpAPYQlC8BPhAZA8gedP5SBSb8IaBC/9KIQvpcs3D8T5gjAWrLivm\\u002BcO77zVUI/DVO8vp4/5MBn3ku/k8O7P3WbD0Cs3ck/TQ75P8hzuj\\u002By4Wo/i3izP3w33L9Dm1JATSQ/vyjPCz\\u002BXM9e\\u002BgsXCvcN6EECIHJU/Ap20v4OGiT7aZ3C/ItzJPZwGF0AfYifAEJ1fvzy9w74yr1\\u002B/l\\u002B2MQHwyoT/e5r8/7r1CwNvkDL\\u002BTJKA/ZznVP5QnXcC4cZw/rciYv1Y12D9Q\\u002BaY85lvhPnqfjD3Dlm\\u002B/j8C5P8AKQ76APZq/Ral\\u002BPjLasb\\u002BYnzDAXkULP2BuJD8GihXAKO4OP/5iLD\\u002BE8GM/J7mHv5xJRT4ReC7AKOoNv49ATsBA0JK/zylfv1ARu74K59O/RFkkvwJEpz7r48k/ivzBvv4\\u002BAj\\u002BGaZ09mneTPwfrI8AQ7Ie9\\u002B9iFvqCoaDwYfx09dDKmvlRpyr9WiCW/3d9AP3ijLEDu5rM\\u002B3qYwQA\\u002BeeT4b7C6/3G5lv0pCmz4SoUu/tZsiPzUrnT91wL8\\u002BtkjoPkjXPT6GiwW\\u002BXM\\u002Bcv7PKWb7JFHZATj8zPwkiBsGujxO\\u002B7rC5vg4vNr\\u002B4rLa/GlstPzpsWz92ogFADElpv9T07j4pxJM/f4kCQLymYz\\u002B9rkG\\u002BDUMtP8Sj5j9tl/Q/l1Rivy0lLz/NCPu/qMxrvWBG2D/twGBAWFiLPoXezT/u3t0\\u002B08dDv9cnMD\\u002By7Za/4tAAvjYOCD\\u002BcYUu9LQKDPi1jlr7B8AG/poIXvlEsuD\\u002BoiK2\\u002BPtHtPjhZaD8wM8o\\u002B5KTQv/j8pT2aUss/OJkyQBViJcBEI9K/BiELwPHkfj8EiyS/XGFpv89pjj4V\\u002B6u/Ftiiv2lG478MMTY/sSZ4PtUW8752NAM/1ZPXvxkvgL9YWHfA8C1KwD05l79JzhvA\"\n  },\n  {\n    \"CategoryId\": 32,\n    \"Name\": \"High-tech Lighting\",\n    \"NameEmbeddingBase64\": \"wCehv0QZJEAty3w\\u002B4GCEv\\u002Bwj3j9iKpO/lp\\u002BUP7gH/T9DgkI\\u002BAlKLP/5ZKz/4CiK/GgXpv590OD/0pTw/UrAaPiVKIkA64r6/gEqNu8hwyb5vWUtAIiXEvv\\u002BA6r\\u002Bi4gnAhiYAQI5lD8DSbcs\\u002BKICLvwFQ4b/BnafA\\u002BPXpv52ltT4KJhxAt1BVP7pGX75GJeu/kRE9v7VgJcBWuRvA9\\u002BtCvz5\\u002Bsz/hY/i/gP4KwO5Yqr\\u002B54Ta/2iQPwGqPir4ubgnAWn2Qv7uL4r/YcMY/8n6kv3EA4z7o0Ty/5\\u002BSMP\\u002BxWNUAUJbs/pMs3QAhsPkCV94K/\\u002BdH5P\\u002BhZsUB8W9nAFlUsQBT3FkDL3Ai/TLkKwOqtsr/6gI4/ScEuv8L5MD\\u002BAARDAHhgLv8\\u002BbsL8FMAq/QIHxvkqnwj/AWIDALtbiv4yWC8DflXdAp7lDwOLK9b\\u002BCa5w/IGlWvGdmvj9nJn6/1P5tPzQaf786aPy9UHo9wIDr17/SKirAUj85wORQjL\\u002Ba5zPA1PIPP\\u002B47BcDPa40/EEfXQCEuDMA59\\u002Bm/7Hx8QCQqbL9j3cs/sJs9v56eGEA\\u002BepQ/5mQEwCu8FD9I1h88Q\\u002Bdiv03uUL\\u002BqtYA/5BYVQFIQzz/nVi0\\u002Bfk9qP8D2CT50hN6/b5kBv0Cyi0BPA0NA2Byav3s31T4GQMi/7iHcPxL2jEB4HZM\\u002Be44dQCxMprw0tEq\\u002BnJ3uP2q2Gz9ueYQ/qzyqP65e7r6zZwbA/wC1PhtO8D\\u002BBS4y\\u002Bxcg5P7ZmJkD2Ix/A\\u002BkMpPu37hT7c8Xu/DMmjQKH6j78cdti/qAzSvaDPir5Vw/E/DawSv3dH5z58T9w/xfGQP9ghAkBANAg/PAkdQEqMmD8PzwJAZA\\u002B8v4EBbUBOq6i\\u002BOoCCwLk8QT\\u002BvfTm/ic9IvrBW4zyMl9O\\u002BNMBWQAp4jT8SEtU\\u002Blv83QGyWlL/m/B3ADudPvndhj7/qPaw/vK20P2GT0r8SP4m\\u002BT2qiP84Ec0De3KS\\u002BnP05P2Bspj2VIUe/aPdpQEqGDcAoyb0/QAmEvzhYqz\\u002BwVvU/n7dfP/QehcDUJrm/OMMgQIDbAMB8xOU\\u002B8T0\\u002BwKYYEcBegTU/4Ib5P/osyj0ARMU\\u002BKkRKP3PLqj\\u002Btp3K\\u002BcCUivqn5ur\\u002Bpza5Alk46P44IUMC0M1y\\u002BlDmLv0Whjz/dcEM91BOXP9b3lj\\u002BE1Ew/hklCwAYiC8GpAwdANR4iv0SHsr814AJA0qsIvwBtXL2AEAC/4QTwvkK63j89P3RAruLqPu52RT/JihPA0rw2vWQJ/j\\u002BMtuQ8pNhYPDi4a79mtHm/kh1EP/7NM0BIK7O\\u002BrkaPwHRN7T7CAho/ZKDSQNIFEb\\u002Bq4DQ/6BN0vyKbiD7EAOu/5eGMvkTTUcDgJNU/pP/iP7paJED2lyNA7asevv\\u002BpfL\\u002BYDD0/goYHP9GydsCAsE/AtHgNQCbAG8DJY\\u002BA/aJKYvmkbdL88bBjAODqqPxuJ7L/4zam/CD2lPQcBuz4yJynAHouFwNU5BEBvTgK/s83tv8cK8r1YBYU/QhhOPlh8t78cYjhAMLK0O94avL69jDg/djrXP\\u002BAj4L4JTM2\\u002BN8poQGHZWb9S\\u002Bz1A/WUSQG5mlz51tIFAPiugPefQVz8E0Go/5oXmPYWfeL7I6Yw\\u002BY5xRPyHrib2mR0i\\u002B/JQFwDdlVsBw4z0/kda5PgDFgb/OBSg//2i4P/TxM8C6iec\\u002BbWTGPhZ1E8EkFBg\\u002BGSepPiFgQcC19j3AvBwov9/pvT3LzdQ/v1n4P8x3gT//bqTAaHEgP\\u002Bib575w\\u002BLU/RJzdPmADmj5adBBAacAlwKf6J78Vwy4\\u002Brfe6vmr5Ir/31LdAmlFfwMQiar8z3oI/WkelPsVk\\u002BD4YQjY/IaNlvizlDj826Q5AjhcJQNpcbr9cBRNATEu2P9LKvT6ot2PAT99Gv6Cpnz\\u002BsBmQ9BJ0PQAYISsBJFeu/h8QNQFAeCMBrLQTAz2X8Pg0JYD4KTDi/XX\\u002BVvsDf9z69S5o\\u002BbTVWPwZZCcC4z6\\u002B8y1f6v3GXOT9zwBc/QzLYv\\u002BKQFr\\u002BoTiS/0DuRPXogCkCZ6TJA\"\n  },\n  {\n    \"CategoryId\": 33,\n    \"Name\": \"Camping Gadgets\",\n    \"NameEmbeddingBase64\": \"77CAvuq0/T\\u002BhZu8/bI/JvywlCEBSY5s/1QYOQEa5u7/ztoq/IAAIv10J6r8x//G\\u002Br9EbP06uF0DKEPw/HZGrvurQjT\\u002BuFmq/2BzPvQs8eD9g2QxAgFlwv2wRfz7Sthi/QEf7u76Fg78klbG/vHgNPxTfP7\\u002By6k3AoTSfP56DPL8y7HHAaynqPvYko7/YCtq9dG0FQAqxSb6zqcu/spqBPwj4DD9p\\u002BOE\\u002B38aDv/XdiL4oxPq9dpJUvycMC7\\u002BqyjTAkbsUQMf4IMAkU8Q/ZE8FPQQl4z51vAzA8CaxvrB5VTzCuKm9hpOeP2zAaj\\u002B8uxM/QyJVP9zr9z8brqvA/wXrP6ALSz8JjHY\\u002BrXokwEHtrD/v/eg/pEVEvpgbSb\\u002ByPTs/wAbjPqUKoj5loEY/kY/pPiySXL7e4ek\\u002BatgvwEiAfD8yvSM/UbapvQLggz\\u002BTJ5Y//Gt8PwTsGT6JUXA/ZOoQwKK1NT\\u002Bbqa8\\u002BC\\u002Baxv1Qe67/p6Z2/xueCPwJsRcB2oi6/grEvv6Srgb/hIk/ANOAHQYbcFb961r0/jayfPxYaBD4wgYC/DuJewEhRe78mOHe\\u002BJjzev0VWjD9P93w\\u002BQKw0P45Vp7/zp9M/h0Bov6raBL\\u002BwqQY/bp2zP3f/5D7f3BNA0Yg/wCYYQL922Mg/RfDAv6SvJUBcaPa/xPU8va62UUBYy8y\\u002BlgfmPxsDYT8A33s/zAkVvmppSL8FEUK\\u002B4M9tv\\u002BDc9j53CTS/aTeQPwyKET\\u002BW0nA/FNptvcvKbkDYgqLAuE77vPRtkT2okT8/X/FOP62UKMBQEMC/ovWLP4YDnD\\u002B/C1RAP5cAwOYTqD9f6lNA7ouAv0Cg7T/wJ0q\\u002BNGVrPwTCsb\\u002BOHAG/bpCBP1ujsr8pGhY/z\\u002BN5wKi4Dz86Q\\u002Bw/Vj3bvlJMtL\\u002B21w0\\u002BBejNPy2jn77F3cy/PvRAQMhQU7/d48i/qAdRPnwuGMDC820/Mes7P3f1pb9keik/6bX4PkbtGr5Asx6/Clh5vtignr8GA7M/F2OHP7fsEcBmvC3AdMIjQCnPt79WpiA\\u002BqcucPqLlCMCDjmm/bp1UQJotJcBbOq0/pOCCv3zUer8eLrI/fcMyQFhd/T/1IWu/gYcJwMD5dz9Vcew/IREOQHaXn790Jt4/lQuev46YAcBMWBU\\u002BKxT9vRrGgj9q1w/AEEKevvsSBD44HGnAODINwPb90MAZzsm/AgcUP8MsHD\\u002BqUey/7QeJvqmgUD\\u002Bg7ARA5l8AwOAsHT4oxUhAc6udwLspnT4\\u002Bki1ARxwlvxFSAED2/as9O8vgvwyMsj8M4Kk/bpBVvpwfSD17BRVA3KOmvRpUUb96rae/TXyqQIaS4D9XUj5AMbsTv1jXxj9cU9I/PnKIP3bWZcAvagxAl3hcP9xC5T5Kuy5ANj4uP4a0xL/m8oi\\u002BUhepQF7pxr4yfDvAtAsJv3nR1L91P42/8L\\u002BMwB0Kl79MJ3u/tqMMQCy2zr7Idi8/9YoUwDAmRkBnDOa/IJjVv/6tFEDuagTAJgkAQGgnr77LxI2/8EFrv7Jtx78EkDc/gHZgPrhy9L7w4J4\\u002BQhqlP7ysur9fOpA\\u002BvGp2QCkOCb6eIeU\\u002BH7EkQD06X7\\u002B5AyJAvzX7PZLssz89TMC/Iuqkv2rRJ0DeZI4/bn8\\u002Bv5gXVj9gZxg/AW27v2bGSD8lyS\\u002B/J0I5vy\\u002Buib7arYg\\u002BqvPSv\\u002B0S678HN4JARiyAvrE38cDYPX8\\u002BGg43v9s2kr\\u002B8CMi/WH/lvY0y9j4uq01AIN6GPwz2\\u002BT9otxG97QrAPxgeQj/avxU/heKZP4J5BkAKY60/FO1SwC6yez85\\u002BivA7kRDPzk2DT/6W5ZA//Cvv0RWBD4kdL0/FemiP5B3Mz9G2Nc/SshzPwUhkT1x/Cm/WvT7P\\u002B6sDL5oDhZAIHjMPhLxBj8RzQnAM9yFP90Mor90T8\\u002B/oc0DPze/4r7IPtk\\u002B9zToPl0q9r\\u002BK7JM\\u002BXh4/wA7L9j4Y6LK/R/KyvyIKh78/Q7W/\\u002BD9kP0hJJj6b9ns\\u002BjJUQv88na7/jT4w/xgL1PzAUBD9PIEbAdMLlPePaK8DXMV\\u002B\\u002B\"\n  },\n  {\n    \"CategoryId\": 34,\n    \"Name\": \"Travel Accessories\",\n    \"NameEmbeddingBase64\": \"owKUvhgOLr\\u002BJ2g1Anrxqv76qDz/dmwu\\u002BDANkQJyDpT90NzjA/Gnnvzh6T74KfX09t/lFPQ6WBEBgjBa\\u002BehK/vzCyjD8w7IC93m83wJg2ob66G9I9tOKxv6HcCb8sEuI\\u002BuDmuvVjNYT/o0We8IVvVv1h0YL7g517Aap4lv4Dior/7gTrAnF8ePu9rvr9gLEQ92PLAvHb8\\u002Bb4\\u002BKSm/XCBgPWagoD/9fBW/VOKQv1EOib/GhQQ\\u002BaFnDvo7fTD82F5a\\u002B2ATqPsZSQL5YbCFAUMWTvj4C/75cEPo9PCNXPlqB/T8AL\\u002BK\\u002BjMmmPgpAxD65Wn\\u002B\\u002B64A/P4GHoj6tImHANugNQFYhxb\\u002BExTk/3e5ov2QOJEAYOcS\\u002BqBnMvtNhcb63phw/Nuamv04ZNEDw8sE/\\u002BwIBv2O9pD6YOXi\\u002B0M7Av28XPT9snfg/4gqGvu2jzz4sEWI/DewLQDRxpr9AG5y\\u002B\\u002BBwFwANbbL/SfWe\\u002B7VW6PmHZUMBvaA4/t1nbPhf\\u002B2L84Wnk90ofrPurpwb/nHb\\u002B/AJHZQJH\\u002B2r\\u002BYUbM/WHTGP3WUoz\\u002BKy7q/Fgvpvwywsj4Ohcw8hUC1vxDfTz2x36k\\u002BfXvqvjZ6Hr8\\u002BZJo9QMZYv1Sqmj86GPq\\u002B7rjtP3xbsb\\u002BfdLi/bUmIvwU/kr/83h9AoUsWPxDL1L\\u002BQFQG/luIbQEZmKkCNo/6\\u002BNLLRP8grbD\\u002BOQw1Ahp2gv8xkND8\\u002Bzhe\\u002BExplvwXKpz\\u002BUSnq/\\u002Bk3VPieDgT\\u002BdhIS/VE/DPHidkD\\u002ByjxzAar\\u002BXveWbwj9GLsM\\u002BBmKcv\\u002BM0Jr/vvgm/cqaaPz4Z4z/sIZU\\u002BX39Ev\\u002BpY8r6w7fE/GPiEP9CXID9OxR2/x0EIQHTn/j7kDFO/by6qvl7SJkDJcUe//gKbwKuRqT/Ai4m\\u002BMG9CPi6xpb4ZNq6/Blu4PmaWzr/Jbw0/yAwyQIgKTz6Xxo6/JTYAQNa5E8AhRr\\u002B\\u002B1/2lvWazYr/6xxLA6uqEPybOcD9yqwW\\u002BelfMv2bzAb/0LT0/p3YqQPJIfz\\u002BG4uW\\u002BejPFP2GSBz8\\u002B7IA\\u002BWW0hv097\\u002Bb\\u002By5oa9\\u002BiOoPvQfCMDeeJw/go1cv07Wc7439VO/\\u002Bs68P1g8vD6r1Zc9lP0EwG1l379UGOG9kH98Po2FFL\\u002Bf334/QvL3vv9EIL6wjAg/C5vMP2yty73ZoKA\\u002Bkq7QPm93MD8OT/i/ykUHP2jpssAYL1I91cQRvzioqj/v95m/xjeTvZvbXD5RYL4\\u002BTDMePgrT9L3n9Og/dwEDwP6YvT7qtYw/6uNUv07J0D\\u002B4m1q99xqFP0yiM781LZW9rNejvihiLUA8T54/Vss7P43at78Smru9IGCRQMonbz6qohG/GL3wPDc29z2uFN8/krk2PsFRL780Hqk/WFJGP/WHr77kyBu/p6w3P14uLT7BLMW\\u002B9CYtQDS54D38qS6/4y1SP14XrL6xPVG/vIvHv6C2fLyMfMQ/hvqOv76sA7/Aj5G7BgR7v9gvOT/k2lK/ilBfP45Qv74CMwnA3ATUP/gMur8yA1S/ZchGvwE9Tb5yp2W\\u002B/tVTPjGALL\\u002BPYli\\u002BAPxROoRlF7/QfwXAAZ9NQDiZ6z4MJ0Y\\u002BczenP8Ajsr9cc8E/LOwWQI6Kvj\\u002BSO7S/3\\u002BplP9JfOT31OU8/XEanPkG/HL4cUas/aj0IP1/Yl781LoG/CKaGv4IGcr88LgK/y08wP\\u002BRxjb5uWhRA0lHevuxcssBK/hw/bpYaPgoCG751PbS/wE8KQLu3ND9oog8/rByLPg4Ahb/tTZ4/5XrHP2VYqD\\u002BuQVA/9J6ePy5njD92Dpk/xmCcPq/e3z\\u002BnlcS\\u002BrlF6v5emkD9IxpFAtw4PPtLGTL7lc0U/YBWzu16/d7\\u002B/7Ya\\u002B5qRcP5Wxfr/wTta/qFKcPqUuqz40L\\u002B4\\u002B3ynrviaye7\\u002BAkH68hDYTvrm53b5XiJy/w5YtP4HUhb4Q0UG80OedP7lJY7\\u002B2UDC\\u002BbpaovuQvTT5Mry4\\u002BpBL9PiAzk79ee5i/jbTAvv0\\u002BmT\\u002BTKV6/2MIFwIdqOT4ePj8/fMKDP2gpFb9/jM\\u002B/8UT0v2DE97\\u002BFg/Q/\"\n  },\n  {\n    \"CategoryId\": 35,\n    \"Name\": \"Outdoor Safety\",\n    \"NameEmbeddingBase64\": \"go91vlJxGr8Ds6Y/Vhdgv85N8z\\u002B0iH0/KLe8P5BCoD4DfJ\\u002B/qFevPQPsPL\\u002B2mfi\\u002BHlb0PZgB0j92bQG\\u002B\\u002BBUuv9gg9j8Y9b0/pUCZvn0azj/0KJ\\u002B\\u002BHem2PqsUmD5QF66/Gw9kvx/cxT8uoue/Fnd8P15ehL//vv\\u002B/3TyLvwa0CL9/xZq/gXkRP7NU5r\\u002BiPTe\\u002BJUOAPlwYyj5mdRS/ZlIUPxg4sr4ccYI/Ni2nvt8DE796pUO/Mcp\\u002Bv2zQmz/7jeq/sIL8P5vYnr\\u002BcMFU/3yySvitYOL9DG64\\u002BgPc4upofir6wyHs\\u002BZGWSPxs6Kr/Cvzs/RzyBPyLvEj8SgKHAAhlHPoAPsj8CBcA/6G2fv12TwT\\u002B\\u002BbJE/3e4Zv94h9r4kqM0/oDZNPxvClD64jTi9HNWaPwmTDcBgQ2i\\u002BJ6GFvzQ6D79kdGQ\\u002BRtGvvxIjWL9pqjM/fnhsvkoIHz5nb/0\\u002BVnMGv5pRHED69TZA\\u002BPm6vLW\\u002Bj7/c8VM/yjGtvqJ5Sr9zwEO/zH1CPxQV7L\\u002BSUVa/lyveQK4L679O5q8/qrg3v\\u002BMKgj\\u002BgDKU8tA99vx6k/L6EvPS/5MBNv8BQCb\\u002BINjNAJ9oQvvisIb\\u002BJwno/TLvTvxptOD9gdPe\\u002BlL2nP\\u002B7YSr8qpjY/rkR5v\\u002BebNL\\u002BLCso/kiOEvu2bmT9Oowi/sGS5Pw0yJ0APhtc/ztNPQPtJYT9YI9i/y\\u002BWwPkQVVr/0OjU9sQ\\u002BwvpqqXz83urI/ZFX\\u002BvOoh4b7/va4\\u002BNJ\\u002BLvx4svz95aE7AavILQCG/Gb8eg2u/5I2Kv9zmdb9\\u002B8Im/LgzkPQOpTL4UMqM/lIXCva5JrT9uC4A/vJSwvXreBr5hMVE/qQI0P8dMcj96WZE/1wtPPtENsD8Mqpa/c3k8wGD3U7wIEYK92h9BP1Rgqb9Qkms8gPLVO5DjIUByPbc/2qMeP9SGdj8p\\u002ByXAxD3mvnam57\\u002B6R7U\\u002B\\u002BiCCP\\u002BG2HL9ojSq/6ASMP5SrWL\\u002BT5XE/Zl72v2CCsr7EbBm\\u002BTvYgQJrXC8DGnQHAY6VXvzQ/Rb9iv7S\\u002BKPTNP3GE3L9CGKW/6sm/P5S/wD0/JAxAvnuev5zSXj5pNlW\\u002BPD6oP4nOB75oYbc/i4QKwBRZ0r4386U/i1whP8TBnD58uco\\u002BQjfwvzEQQD9YEzM9syKkvlaMsz/y/Ao\\u002BxAvkvv8sHD8JOcC/M6KVv3v/q8CjDR7AKOzLP7bgTb32TlK\\u002BOG0Uv43QSL\\u002B3koa/2pN7vxA9K71Zc4BAWJoYwKgor74azb0\\u002B2SGrPqOWFUDQ7kw99J7Qv2CCOb1djV4\\u002B8MSNvl5gjT9VaJ\\u002B/k56OvuI8pD7qT/O/PEd/QFbqCD5iCIk/kEmxv72Vgb\\u002B8FJ\\u002B/t2qtP5xqGMBEsTk/lUgDPyq5vr\\u002Buh7c\\u002BkoQSwFKQUr82678/pzNIQLjHOT1XK12\\u002BquBOv2w\\u002BMsB6goW\\u002BKW\\u002BlPiSFgT/O8v6/bhqiP5iEfr0i\\u002BiZAB46WPRR55T92/u2/tgmiv8Cdpz9Um0W/ztKuv4yDir4KBUW\\u002BOBJLPxA2rr8edes/9tkKP4TlQL/UA2C/fm6BP7CVuL56abK/QFzaP9Fcab76yIC//dMHP1pOpb5qFM8\\u002BthwwP7zmQD0Eipq/f3L4P/ewy76Q4Go/G5\\u002BLP\\u002BTkb7xz6UO/WMmxvyHtKT8s/Du/yAhzv/D/xD7eXYq/P7Z4vl3ADcCC0UBAq640v2fP0sBPhBu/IgM0v4hRP7\\u002BQ44q//BCpPtUM/z8oMDpAG3e9vmpc3z2SEw\\u002B/VfqzP3cAUz\\u002BiVNQ\\u002Bx2wzP1g7Zj\\u002BtEi2\\u002BdVo0P0Ky3z44xhW8T9pVPyLyOkCxSnFAEGa8vS6dnj8wTRNA6spLvyDTc79SO4c\\u002BdjGgvg4U1j\\u002Bc3vm\\u002BqXzmP2aE0r9b75U/qvWbvj\\u002B0WD\\u002BziAk/fEZCP8AtsL7Syie/YloLP4d9xj8HC3g\\u002Bgg3BvhOVbr8gubO9Flx\\u002BvxrUVD6SL5c/gp67vt1KxL9PscC/QZs8vyljsL/loWY\\u002BCtOwPQ5Kl76kheu/ByMEv9OfXj874ce/2EdWvyEjjD7ykv4/\"\n  },\n  {\n    \"CategoryId\": 36,\n    \"Name\": \"Wilderness DJing\",\n    \"NameEmbeddingBase64\": \"kCS7vliZuD\\u002BEDmg/Lo\\u002B4v8DRqT\\u002BEH/I/t5\\u002BnPg4/5r8W\\u002BkG/jD4eviIKxz11AKy\\u002B/dkYQOH\\u002BB0BcKeg/soDGP3uwfD9E\\u002Bcg/XDdpP0hCkz8WOm6\\u002BtLGlPTdkJb/4ORHAPGvrvwpJBz9ExuO/8yHCv7frmj4zLCHAw7glQB7Wfb9/nKy\\u002BYAOhv86Xyz9pgc8\\u002BuUhpvyR2Tb9SP4m/i1wpQC1ygj9UpwC9xrLrv1pMkL/G1fw9p3BEwMk9Yb\\u002B1DRLAxsRPP2wjFL\\u002BqISK/fOy6vwpZtL7h6JW/SB1fP1YqLL6vuwNAx4rMPyNUAr/deBa\\u002B/g87P1kRpD/kap/AOwrvPyzcur1Kqlw/Ujz\\u002Bv\\u002BLrNj8gKmo/cJOOPpTbML1/BCRAzsVGPw/\\u002Bir6Ywso/IRdvvyJA3j4AMKg/urEAwKxKR75So0Q/jXoAwMBcub16/w/AuV\\u002BZvoHysr\\u002BgfSc/aGDrv80RlT6etvC\\u002BijEKwDSj7j\\u002By56S/2qkavwWyPsAZYYu/wzKpPiDbQz7B0qa/nMzmQMUznb/uumg/7CxTP2uCcj\\u002BuG1a/WJsAwNB89L\\u002B6X1a/yCJ5v5ZllD3S4Tw/TV8KvvwlgT/wnhI\\u002B01Hovuvt2T/gZce9llhzQBzQrb\\u002B8QWI/UIvvvurRuL/TfNk/0iovvikq6j9/xOy\\u002Bj8fXP7rJLUBXzdE/QXDDPyTz8r2YHuq9\\u002BHZ\\u002BP\\u002ByCyz11vKu\\u002B6pC6v06O5L1WbvQ\\u002BWPMLQIdZrT\\u002BKj2a/7ym8P3MjhD8jgGzA3sVNPUU347\\u002BtXB2/O/\\u002BUv5D6zb\\u002Bq/4G/xa8tPpIYeb8wxMI/paKBPQ6p6D\\u002BOXYS\\u002BesYUQCQYyj4KwOy/BHJhPxxtDL6XZva/CAPRP92QoEBEQEk\\u002BhxolwJqHF7\\u002BA1WM/NRSLP6SIJb6uF4i/Lc\\u002BnP\\u002BPvkT8schA/nUClP4pDCr/WYALAWDcYPwQB47\\u002ByUClAJ/InQECSI7/CYgs/tB03P5VqbL\\u002B0a2K/AjAPv9aXZb8OnZW/Wh0YP/9MGD/u\\u002BE3AUUkJQEb8/b3CtkG\\u002B9kHIPiBohDwkLRo/77AHQHZStr\\u002BHTC8/owa5P2aMd76YQFU/EzD1P1J4ST8mA8k\\u002BpOikvpvmHL/JQH9A2C8ov1G2lz6qew5AjtB8vyOyDr/280A/xpvOPhzg5j8Dn3O/qGefPiPIpb9i7RTAhFzBvvpH6MAUyqI\\u002BXFShPmIiOD\\u002BRO10/xouVv\\u002B25mz\\u002BYzU4/mchvv2mLrT/ac\\u002Bk/VlVZvxge9T\\u002BN3fo/K\\u002BOKv0MKTUDw8oy75aM6wFbweD9o8I\\u002B9XDkyPjqnXD/ryBY/06yvvi5D3b7gbJe/QGmjQA0h6z\\u002BMnZI/bDZqvhg/p758saO/VK8APaxyusBg\\u002BEm/J7rmPmwiBkAW/WU/m6GBP7\\u002Bg3r8oSYQ\\u002BZTpAQGAuRb3mHDPAYOQdvzcuA78\\u002BP5W/AE9HwKiaBz9mux7AohQ8QEiS5L4ooJC\\u002BFt64v3awxj/zoLu/2aIOwK/MB7\\u002B3NnO/eRHlviYVED9QfFHAeSyFv0SNWcBKxOk\\u002BoCaHvuAZe7\\u002BieQk\\u002BopeBQA/3ZsDiDfS\\u002BtBeTPf8pCT8OPUU/BrbKP8/BGr\\u002Bvg46/4uKhv6IAkT9tVg6/waFNP71TFEDVSm4/eCZDvggIJr3JJAu/VF1KvT1tH0DwQcu/MZ\\u002Bbv39okb/CXYs/doawv9do0b7nnxBAJOjBP6eo0MBPM86/GGa\\u002BvwxiZL5HaQDA8mXUP9Y\\u002BZz/OWTJA47ibv4BByL\\u002BWOic/qeAdQNSSNj1IRr4/qGH3P/hSjz/yqwI/6dnDPxiCPD7/AEbAkWnTPoK6kD/s5IxAQKCCPorx7z944\\u002B\\u002B9iCXDvheKTb/u93s/ZwcUwE4uAb9KWda/LMwyQO3qcL9hdbE/Y/uLPvFfK0BCTZO/sqN0P9os5D4JDYW/HC8Vv8DzF0Bm1mg/K5invx76r78F/iq/84z2v6IvRL4O/Na\\u002BMOn3PI0x3j6qBYe/asooP6ieub7w9hRALYnDv0AEmrrjb6I/xVi5vrbrkj8r2AvAkEIGwJl0GsDyxKC/\"\n  },\n  {\n    \"CategoryId\": 37,\n    \"Name\": \"Adventure Photography\",\n    \"NameEmbeddingBase64\": \"nusEv\\u002B7CID53Eh0/ajRAv6qbyj6kk\\u002BU/YkPuvfnJvr7wpeq/IMNlvWuCnj9DsPS9gNfDPrrJwj8sjdK9iTZrP6vsB0BRat6\\u002BGFWevyyoFkD8NRk\\u002BJL8wvz68kD\\u002BFdWK/MH8vv93djT6ixzi/92Vlv8BjATzYreK/c/tBP3LcZT6iGu2\\u002B/xL1v6Q46T5EdjJAwjMIwGKsNr/iBYi/y8l9Px\\u002BPRj8Sme4/wr\\u002BJvqPnHb9e4DU\\u002BeOy4vzN/sr\\u002B\\u002B5hTA1jGpPnLpcb9ebQu/LmF1v\\u002BpZEb\\u002B0r6C/wp6Evuv5cz/3RJY/ZJsAvjrJ3z5YPSY/WlyCPzzMqT9YUl7AGD0lQHRSNr9hyBRAQoyTPQyorj8M2Qc9UzYXwPHqeL88WQ1AC3GRPiFLrj9D6XA97kGCv91ABz\\u002BSnA2/Ku7fv9Dc178EKwA96OFOv2xvuD9q/zU/bCD9P94WL7/iuVQ/mPEFwO5RxD/YvSg/pNk0PWl8BsAa7rC/lYrkPuu/cL\\u002BIpxM//vpBv6060b4AfAm\\u002BpZ3FQLELiL/GpGo/xd0WQLlAnD\\u002BeKlM\\u002BSqr0v7TK9L7U3NE9NiEKv1s04z0ifUI/OLlePQbUrj/sVqi\\u002BAysLwOKa\\u002Bz7FRay/1kInPz1hg79g9qC9EWWUvznCHL\\u002BWbF4/6KauPq83mL8EmJy\\u002Bi/90QFKBH0A6Rbk/l92TPjpWlz0QbF4/NrUov6Dveb9Nrpi/jFdsPn\\u002Bi3T66Z4e/9CZdPjD88D/n1ae/IoI\\u002BvjO4tj9UqiDAuYOzPmHle76qd5c/daCNPgQvY794n1q/GO\\u002BRvVF9Gj6qqqI/KQWYPoKdkj9lhS8\\u002BSOtHP\\u002BsWMj80DeW/6\\u002Ba/Pj6Xk7\\u002Bbh6i/ugXOvR5OC0BZHNy\\u002BpstpwIEp\\u002BD/MjyS/eDeMv5xahL6MihW/oPjNvbY4jT3c\\u002BmY/ILcRQGam7z6N2YW/8pSRP0Ywwr9kygw/Bj6ePzBjer99WQM/39\\u002B/PhJWEr\\u002BEii2/O\\u002BrjPtSpjD1N148\\u002BlAaYP93TSj91wnC//CdEQNZqMr\\u002BgibS\\u002BNb3HPkx8/75\\u002B1aO/VKyLv7Y/0L9lNLE/5jGcv3ICq72FWfQ/stoNQHT1ML\\u002BO27k\\u002BB0tPvoFg87\\u002BlLqk/\\u002BAw2PY7bHb\\u002BonjU/DZwIPljvlL8SszO/HPacPxtotz\\u002BLNQHAje6xP3FmpL\\u002BBPBnAmcSoP30GtsDmT8\\u002B\\u002B5NOgviPBVz8rZCPAWjDPv3Avqz96bRA/GGUhPwqX775mYsk/\\u002BG0iwBMX9D5JNzc/vSIpP3gMMz\\u002Bf99A\\u002BtwKavlGbkz67ZWe/ZqG2vvJqyz\\u002BOJDu\\u002BdnwXwPgFoj6fCCG\\u002BX4CdQHpvLECEsiC/GS61vgVENr6e7JE/VgXiPlNjrb/2WAS\\u002BipU9v5/\\u002B\\u002BT9\\u002BplC\\u002Baq95vrO7h79yAEo/0JodQPhkpT\\u002BC2Ay/znJZv0RRZT2ssbi/6NrwvOdYqL4m7rq/OF6uP3RMUb9K\\u002BYq\\u002BjPDXv6w1TT8sOiW/g2wVwJ6Wsj1aWm\\u002B/MSdnP28OkL\\u002B85Q3AYbIBP4okYb8iW\\u002BY/jowWP5Ja3L60LtC/\\u002BvEIQF3bHMCC4jS/gPYKP/4qJT4OVy0\\u002BbD7WP/dgjz967B9AbBiQvqZftD9g1U6/6wSBPiI7Yr8OtKk9rmfrP/pg\\u002Bz57Jpm\\u002BM8RKvwynOb84CL6/P9yjv2XmZ78DRs2\\u002B8i3Mv6xNwb\\u002BNoAhA262EP4QCqcA37Ua\\u002BpzWDv6tjd7/wu0q/onxUP\\u002B9Fqj/\\u002Bq40/0g\\u002BEP34\\u002BlD/DZT6/obCdP9q2bz4//iU/CsIkvvBED0Ayxds\\u002BxLsBPnT4D0D\\u002BBzm/oBk/P\\u002BO7wj8xvz5AA/ifvz\\u002BaEcDweN4\\u002BBFENPrSghj/dQa6/rRoUvrw2cD5hDVS/WknaP3wv4j7wotY85FG9P5Mc8z5Yeuu9Vbgyv8iabz0SkgC/SyqAP8AiO0BNEDA\\u002B0LeLP0WFrr/roAg/nKx3P96ikb\\u002Bla2E/XlQ0v6\\u002BvMb80T9W/PA0uP6BUoD/pf8I/rBVsv3xS\\u002Bj3J5yM/4BWOv2DN4j4Q7wXATk09vx3CFsDWZ/K/\"\n  },\n  {\n    \"CategoryId\": 38,\n    \"Name\": \"Extreme Sports Gear\",\n    \"NameEmbeddingBase64\": \"edfcvwQmIEC5I4o/ZJUZwGx0B0DOEgI/Ni77PuG80T8CeaM\\u002B3t3UPqHBUD91gS/AyXCFPnYO3z7eNuU/M9QvvlaoGECp9Jg/Rdvgvny6AUCYZMQ/zKiZvrWGgj\\u002BhBb\\u002B/qYG1P/WNEb8DbXG/KEX/P2XXXL\\u002Bc\\u002BZzAG/ZVviNFRL7VRxVAMQ6UP2NWHb\\u002BcaBDA0oVUvrQ727/RM82/\\u002BeA7QPyrH7/i8gxAFrLivzSde79xTCs\\u002BjKEvPwWz/j4DHY\\u002B/LhWZQOgF/b/SNN4/7r9MPxJCwT9a4nu/Oy2PPyVDtD\\u002BqDGc/74YRv\\u002BRTnD7S0z8/DzYhP1nI8z\\u002Bb86HAFYNaP2o6xz6psyZAbKitvzRQS0BX9ao/Rv\\u002BzP\\u002BDOmb0EIlg/eXHdPxFvzj\\u002BoZNM/shq8P83ryj4cz\\u002Bm/Nqy3v4JtMT6n9E2/HzWZwLmfjr8cUc6//8GQvzzEfb9WHgG/LI3jvzpz/D\\u002BZpRJADhIrv29oxz/8SNw\\u002BW2sPP\\u002BNMRL/Udp29plm3vsN10L\\u002BBlUi/QYsIQRswtL9\\u002Bs7m\\u002Bct3QP3bixz4aBLg/5MLCv\\u002BbFcz3W0Qa\\u002BR3oFwM2XaL9V/4s/RaImP53SYL9I/us/eXI5v5chsD\\u002BPFy7A9CsHQGN/tr/A/x09iJHPv1JUDj/BapQ/70rOvi5QDcAzeZq\\u002BpOCFvC9QDUATIHY/1njOP9HVyT6dF42\\u002BSwD8v5KmD7\\u002Bu1RA\\u002BpOI1v6ggWD8I1Fw\\u002BlEHyvS1Kk0CNvRO\\u002BU\\u002B\\u002BYv8bQikCiwLDAcZ6mv0g1sj3nl8i/gp9hv/FqNL4sIDE\\u002BElZPvn9JIr99Isa\\u002BwOHbPqwoTr7WcSg\\u002B2gQ6QLDDTbwV6/a/HiPAv2IA/r2PLeG\\u002Bzh0hP9Tug0BLhIa97cVxwNgRFL2wQ5G/cW9Vvyp1X78wSBy/Ot5vv6O1MD8IyKQ/BApaQA7zcD1UW5e/3CElv5Lksb8IgfI/vtmZP6RlcL997\\u002BW/SOL9PijDOT/8iO6/WNocwJHph79GFqs/Pp5\\u002BvcbNEr8rz2W/BuB8vmRMKL96WJe\\u002BWJ2eP\\u002BZWYL5gyfI\\u002B6ye8P9XIBsAIAYm\\u002B5C25Pr16jD/wSzs8s0\\u002BNPxNcYz\\u002B9ZLu/4ov7vy4wGb8q/V0/okO\\u002BvNXIMcDyj9o/ZYEFvzXCH74o\\u002BOG/ZF1CvwwVEkDg/l\\u002B/dLSYPhmQbT/uFUg/pu\\u002B5PsJCw8BwGk88\\u002B9Q\\u002Bv/25oD84awxAUgwSQHpBsz93dqM\\u002B5CoEQD7V0z2U1YtA3n5eP7992b/pY0S/oBo7vgRBCEA2DW6/F8Elv2z4zr/KdF8/9LJDPyC0tT/JdnzAexUJQPhlsrwhFf2/1v6RQFac4D/aXaI/AKkAwFcOq74XHf6\\u002B\\u002B6HRP1gXS8ANy5M/NvMSv9Z23T\\u002Blhuq\\u002BuhDKPoA58L\\u002B\\u002Bepu/QvqEP\\u002B51hD98qfi/fVmEPwEZAcAcIY6/Tkl9P27CLcBTkj8\\u002BnHnnPwTuEL3uix9Ag7Gev0DkQkAGBP2/5/uNv/JGi7\\u002BcXZe\\u002BlpJ/v9yy7778wg3AtFM5P20/JMBiVBk/CpAYP43PiD/WrI4\\u002BOxJhv8fyHsCUC/e9WGlhPsmQe75CGCE/zdl4PwHzoD5Gf7M/nkEIv0z8Zz\\u002BgPUs9T/28PysO9T6AlqI/zRdOP4x0WT/e/qG/vMg8P9bgqz5jfQa/\\u002BrZWP0ZVRr/49P88IBcBv38Xir83Juw/fDEYwHR5/8DKKNi\\u002BNKycP\\u002BqOA8AacWm/gLSOv72ypj6eMkc/pPWNv5J/IUDKccC/dEwIP/Lakj\\u002BOgYM/cDfHv74TnD5fwqa\\u002BYNklvYpoFEAx0MM\\u002Bc64oP8rvtj/HpIVAnFg8v3z8R0BrlzFAezrrv1C/p7w24Pa/pvi8v6vbKUDQPWG82A31PqTQhT8BSz6//IWkPtLGRT9YqxlAJYCBP4iOdz1wTmA\\u002Bk6O1v5ZGGr5j5Ss/tZWdP4azzL9gF9e/pR7fvyi1Wb/Kea\\u002B/n7UQwK5oXr9WrJ6/x8\\u002Bxv3xEH71ST7i/WCipvlD9db6VT70/BFwewICCJT7anJ4\\u002BjgRxwOuPiD9CS8K9\"\n  },\n  {\n    \"CategoryId\": 39,\n    \"Name\": \"Survival Essentials\",\n    \"NameEmbeddingBase64\": \"RJuOv8uyrD8QAhFAqOzOvlPgbUAWhiVA/Cr9P/EX3T8jS/c\\u002BAi9rvx7VhT4awQbAPQuIP47evj\\u002BiLgM/mHkiP5LYFj/GQEpAPozev60Wcj/hm1G/wZoXv9oL2b2ju\\u002BO/JrGPP2KFaL4ezSW\\u002BqcysP4B0\\u002BztYEHrADpj8vpC/kr/pJDG\\u002Bx16jPsO0nb8zkKo/iMiXP2IrgD/g\\u002B5u\\u002BkpesP0Fnmr/gIh5A9K1svqpWCz81cUg\\u002BCpHEv3/EDL\\u002BGIcu/rNEjQEpR/78gZGC7z\\u002BapvjxEjL8Mdhq\\u002BCmOyP1rM0r8H5hk/EFp7vFJXN75DQNk\\u002B2xG8P3z\\u002BGb\\u002B6K6bAfmRXPpb7EkB6d1I/clYYwLSBOz97S/A/r7KTP3aVxr\\u002BLT5w/p1MfQF1IMkBM47u9aMv0vqx9wT/Z/6C/DrlQP0mDpj\\u002B0Z1c/0AMRvia3xb4K4m89dEIAv9IuF78U96Q\\u002B6dgEwKKj6T6tMbs\\u002Bpukrv0uskL820vQ\\u002B\\u002BOCZP5J4cb9dcp\\u002B/au\\u002BNP\\u002BU1ML/Treq\\u002Bmfz2QItBqj7G\\u002Br4/37xvP1A6Vb/LR3w\\u002BP13CvxR03T5g8Y\\u002B/jLuOvmgqyj5zZqu\\u002BjgKBvvVEgj6frd2/p0gBPyL7F75kubw9IJHWPitRMj6UyPc\\u002BxJH6vjJ8\\u002BL6Zv0FAaPUEwGGxuD866Mc\\u002BQYG\\u002BP\\u002BplEEAgCAW9PpSoP2YCBz\\u002BLInM/igT6vsSSiTzTiRDAM\\u002B6CvvQy0r7pi2s/MiShvTegXz8IYbg/8DMEv2k\\u002BkT/qUZvAKN7Dv6YGTz\\u002BiLfM9DM6oPQp\\u002B2b/U85w/dFckv6mx5z1aFqY/G/kAP91MTT\\u002BbX\\u002Bu\\u002BFw63PjQODMDDghXANHgJvayVpr8w44q\\u002BE9bFv0cLkEAI1rw\\u002B/HgAwBR\\u002Bxr/oE9w/wvs8PwOppj1KXew/qWHdvpgnwj\\u002B8w2K\\u002BgxXzP1YmUb8hV8K\\u002B7mMwPgLoE8ByxyU/46tcv60xxb84Hre/jv\\u002BnPwD9fr9knuq\\u002BrJAXwJ4sjb9ZNQw/pdFpvlmqMz/pfU4\\u002BXjAPQMgGjb9mpxO/6o2PP2Iw87\\u002BR5Im/5hUFv1rCC8AajoM/ViHvvvDyBbww98y/\\u002B/MDQGMWAEC6rMQ\\u002Bf4ojvqv/8z9uerE/O4\\u002Bjvv8J8r1EUKU/L2bqvobzvj7N3Ay\\u002BFOBCP\\u002BBcpT/Ikla\\u002BgMSGP0mghT8YvYS/surcv6Qp\\u002B8Ba0s89OA7WvkJGgb5Lcrc/BsuPPqwsIz9\\u002B3Mg/ct87v1Kbbb8DNP0/jU4AwA4lEz/8z9g/YiSvv0Bojr4XSVa/GoM3wAYF8L161Kg/lCVGva4l8r\\u002BlnPq\\u002BPQ\\u002Bov/C9Cb91Au6\\u002BapiWQHeyEUBQcOQ\\u002BmuTbvzRyB75QHS5A0usBP79FssDcH\\u002Bw/FWWZPhFN1b92wI6/XpSKvy/tGL45fq0/rpFgQCBrHr5kW4u/sBxpv\\u002BPEXcArdM6/48Q/QJerIL/Et8W/WUG1Pkyqrb2XK\\u002BU/tOg5wOt5Uz\\u002BiCAu/Rl/8v2DbEr85Gi3AMlhzP6woI79U0hC/xCibvpLxkL9AWuk/lB3MvzcMIb7q2gq/9CqIPxfHg8AwSgzAXfBSvsr7CMARX5a/U3ZnP\\u002Bx0AT5M2EK9Tg7hvuj6yD8\\u002B4J6/AC\\u002B9Oy9Zhr\\u002Bmhbm9\\u002Bh84PxRGtj/ise0/WIpFv1BYAUC2p7k/RGdxP4W9bT/sQYk/PkG2v9Yotr\\u002BgG/0/eimGvo0U/MDOY8E/OtSFvIBNMcDYi96/SFvsvrejiz1h2e4/cI6zvg9sFEClba8/\\u002BEWKPwxLgz\\u002BzVp8/d7GuPqdGpz\\u002Bosdk\\u002BSFjnPDzxUb8MFBDA3sQGPmJlDj9ATapA7TZgvoSscr\\u002BpKtw/VMq1vnIPKUBtOls\\u002BpCXDPY06zD/17KU\\u002BTL8VQEwU6r7COTc/CMy8PzvrFL8EZPw/yiiZvYOMKD8SOOM\\u002BA9AywIhRO0AVZgtAwIn6P4e9mcADu/Y9woNpwHJbt7\\u002B0Ng\\u002B/4kw7wFBDyb6gChA\\u002BnM4FwIeuKkA2is8\\u002BoVY2P5blgb/bf58/v8Sgv\\u002BrSoD/alJ2\\u002BT/G3vrG9XD4G/ys/\"\n  },\n  {\n    \"CategoryId\": 4,\n    \"Name\": \"Climbing Gear\",\n    \"NameEmbeddingBase64\": \"XFoxwLpmXz\\u002Bojfg/RhKQPgKsDL8yPr4/ULnAPwh0FD/IAMC/ORajv3YnoD/P/Li/m8UpP61eyT9UefA/twk9P86Iuz8L7\\u002Bc/fwPPPdDL0D6nKhQ/1sICv2ykiL4c1xa9xWfnP87SbD9ABby/eJJEPlofAj9UVzfA4IMWPzfEUz9tlAq/qC4WPlrNb7\\u002BEMt8/UHfPv6JT/r523l2/e67cP9jw8z5Miqc/rHPuvoAo\\u002Br08KJM\\u002BQdRSPwBttjujZ3q/IpmsP6QdSL/MSeK9ltmQv8\\u002B8KL62Nic9HxooPsrrGD/ODl0/3m3EvtrHWL78Mmw/7j/LPk7s0j4Ngl/ARczsP3ycTT8peTdAXH8AvzK3lD8Rokm\\u002BysKYP9d6Fj9yj5U\\u002BO1hdP\\u002Br/4D3sR0w/dG7rPhhv1r7SjUe/PTzgv9uN5j2WHVy/026iv51FCj5RAwM/eu4VvwyaVD1j9p0/xY\\u002B/vwSqoj8em/c/c\\u002B9FP/RwR784aKS/0e\\u002B1P7qczj5JCY\\u002B\\u002BDDtxvymkRL\\u002BsLuq/eWnwQCheub/Y/x0/Gg6JPzl/2T8kW\\u002Bk9PD3Fv\\u002BjXjr78Zi0/1KGavu/s1z208fo/hQ4ZPzcT2b6pHI\\u002B\\u002B5xi9v7CMsT07wAfAaDOFP7o/p7/QR3Q/RnIIwLL4Gb\\u002Bi9Lo/0KRmvyM7or/Oooi99jDHP7pkEkDOBkU/paLOP1WbsT\\u002BXLQy/xOOSv7vYPL8yT7G/gwhDP0qCez9Qc7e/EJ8AvbaTDEDV7f\\u002B\\u002BBq4ePxcSSED5X2jAvnYFQFNKij6shP2/F1Qzv43bQL4OYpq/Erfmv\\u002BLc5r1un1c/LzBHP5yi7j\\u002Bads\\u002B/vhxvPjxYLL4U0wfA6YIvv/C2Bb\\u002B0SgK/jouDvyvbLkCyhaU/p6RiwJTYHz8kMzo\\u002BhDthPUQs979GD9A/aG6VPi0u9b6Zyhk/WpBQQLIEzL5QLyXA/9twv2bSAsC89Jk8KhPHP0Di8L7YFFK9u2f8viF4RD8\\u002BDhO\\u002BmhXQPvxQx71Ee40/chDRP3L7p78EPzU/9qOAPx5YAb8AHKw\\u002B/JbmPqvf0L9MpbK\\u002BOkGev9A7Nj70cH4/QAjAPrj7BT9SdJA\\u002BrEi8P6a9oD8P/4K\\u002B6qBUvzSih7\\u002BMDAE/\\u002BlpSP7aKH8C7l7Y/umdYP4C4FjvWGW2/Jl5IPz6o6z3alSrAp1AXPzLlSL8GqeO\\u002BRkEBvgyHscCFObe\\u002BeeMKQGdt/j/u1L49A44VQAmKxj/BMWS/9lfJPk0yu7\\u002BAJmBAFgPvvuURFr/wc7K\\u002BF1jwvhefCUB\\u002BPqw\\u002BOiMQwJdWs77o1wW9EgLePo8xiz/IvSbA/uqDP98DM8AAzyW/UCNQQFJTHT80SAO\\u002BaFB/PYoTZ7\\u002ByDyE/4dBjP\\u002Bzq/7\\u002BCcbU/x2Uov3Xk8j\\u002B2J6e\\u002BfLbzvrrHb761WhS/b5FYQCj4/j8WbPS/yPrlvBwHvr8a9ou/fsYHQFLunD4/skfAehXuPmznhb6YAhpAkv1nv/uy7z6UWeG/tqvTv1W\\u002BAL81RL\\u002B/DQ9Sv0YZlb/XBbO/2uYLv0tO5r7T7PM\\u002BkM7vP7Tyx75Yp88/wc7LPgkuIsCzNLO/K1y2viBGwzwck6c/m/Nvv/tOqj7duqM\\u002BFu\\u002Bpv8TCCUAy4dK94pV\\u002Bvw4A9D4u268\\u002BFlKCPzSOTz2YEk2/YNELv6g/pT/lm2y/MBmivLiTdL\\u002Bwhxa/4famv8c\\u002BrL/nJl9AKFk6v9CVwsDmsk6/7LEmP6z/1L/QBv2/XFKevoCYez/DwdU/c5OtvkZZ/j7a656\\u002BC4gJP041MD85E3K/Pgj5vgKEhD9OGTg/6jW/vQW58D\\u002BNH9c\\u002BkOHKvCZSLkBaumBAv5GhvWiTsz\\u002BJC/0\\u002B5KcUvmwzab0xDqa/A3KuPrqYTz94dt48ZZe\\u002BPhmUgD9atQE/IMA8P3L7vb1rxGg/oiR8Py5bhr8yw5C/4mDvvthuDL9DWwJAv58JQDpTW8CkI0a9FuoIwKGq0z4AZlA7VqsrwAqiTj\\u002B2mXA9knY8vkawaL86Ace\\u002BSMX5PT5AGr9Y\\u002B/6\\u002BSPgKwJIonz4vYUW/ZcHsv2i35L8xNMA\\u002B\"\n  },\n  {\n    \"CategoryId\": 40,\n    \"Name\": \"Secret Communication\",\n    \"NameEmbeddingBase64\": \"HMWYPgAm1joC9U6\\u002B1NW0v2DMzry1LpI\\u002BhwYfQM7RxT5izjW/KmpaPgkxNL\\u002B/XEg\\u002B1NxaP1CuET/nqwFAo/66PyfejT8bb7q\\u002B1pB4vl7l4z6A2NE/YuSWv2DcOL6Lxhc/erWzPsDSfT3lbK\\u002B/6Gvqv/JroL\\u002B57x7AYunJPgqv\\u002BL2m2s8/JS9KP\\u002Bg4hT8mxa0\\u002B\\u002Bhl3v\\u002Bwrnb\\u002B6aOi/XsiuPyOwl72DqnC\\u002BLNh5PqoQ/73uTV0/GobJv\\u002Bz9\\u002BL5mj1y\\u002BtoR7vhz4KcAIIe4\\u002BZ5H/P\\u002BQqdr86ZZQ/jSeAPzJN9T4gr/Q/lEcDP5aJO7/EA4Y/6nqDP8FYpT\\u002BuroDA3I\\u002BjP9RNzD4bXaM//NTzv4BHKzuMeN4/Wls0v1\\u002BIPz\\u002BzxBY\\u002BvOEFP/7rFL0sJ40/GN6KPzeOob87XO2\\u002BV04Av5KFDj5I0lk/fveSvyqyCT/96g2\\u002BUf8LwAOHAcAXqAJA2DQ7v1R5ML9MhgW\\u002Ba2T8v2yvrD2CGqu/jJZTvrihsr8UeZu/GiKKv8xpmL/JK6W/9\\u002BzIQK8xiL\\u002B4YQU9kS2EP4H\\u002Bf7/CICu\\u002Bki62v9omkT2o7Pq/CmpPv5WaPkB4DZ4\\u002BjqJyv5CCEbzKric/kLgvPDfjE0DsnLg/Fo/HPzZa3r4Iib89Ya6QP94m\\u002Bj6sIxE/vJFnP/AIpz\\u002Bdd12/\\u002B5CIPyXnCUCUgZG99L/5P4g9Yj8pCQJAPlABP\\u002BJGYj/eWHo/1vvfPtXxhL8679o/oBdaP/Tk\\u002BT5iPwE/YMKLvLCuj75yj52/jtEIP\\u002BYYTEDTLo0/DZ\\u002B0PUp0pb/32wI/cnykP0ufSL9t1eg/JU7AvuFJij/c4BHA\\u002BFKkPrq0tz\\u002BnRO6/LlZ9PxAcmT9RxQG/ZWugPvbmNEAwfrs\\u002BByFxwKjeOj8Uw12/UWy9P5J4N8ASfiC\\u002Br3BmP3wegz\\u002BQDeK\\u002BXorJvg3SkL45EwK/cMBnvQdBi7/jlYU/edTmv0A/A7\\u002BOgnm\\u002Btq/BPx/HZr9Wj\\u002B6/3LmSP/\\u002BoQz//3Dk/Oe4UQHrcsr/O9Z4/rrxAv68uqL6Yod2/\\u002BJc/vxgM6b5sclq/IJZcwErx/T2mOqi/YEE0v9wGt79ADQk/mYy0PuVXA78jtZI/N2\\u002Brv8WWhj/MRZU/9PZrvxg2kD5EnV0/8YMKv8YyrL5Yqjq\\u002BwVbFvnK\\u002BnT9HgUW/FBdvv9Rswb1Z9T2/52kpvmw7v8D0x4u/VfPGPgorU78NlUk/6KVTvVIrnz/\\u002Bs0O\\u002BG\\u002BMFP/H4AkCPektAAG\\u002BYP8JL9b/07uQ/PhvLPu9DhT\\u002BMBAy/gBjyvCLRMr6tOqI\\u002B/DohvxAaTT\\u002B2G3o/yI8UwHrd178Hy02/BmgkQEgwsD41qjU\\u002BAu7VP985Cj\\u002BHzLA/pHJwPkkCDcD2x9Q9MN17vvrrRz4iCTlA\\u002BC6LPxTo877KHZY\\u002BmAhzv2Zf3D2aQ7m/njdevtkytr\\u002BhD8K/Wj\\u002B6v9CStb9b2I\\u002B/l87xP0iYDUD6Ey5AlH4wP9ABM7\\u002ByTiC/Wu5vPzDES8B\\u002BsHO/Ynm9Pyufyr8mVU4/xZWevjwvIb8EXis\\u002BI9TrPqBOq7xNNI\\u002B\\u002BB\\u002BiYP0bQMD9ocUo/1NE0QKr3\\u002Br4AFAS/EGG0Pe\\u002BInz8X1\\u002BA/jDNLwDRbEcB2b5K\\u002BCFkZQCcODL9o0gc/XuEhPwMEK76Nrqg\\u002BVDNeP2CUjj9qAI2\\u002BkpRjPvIhRr/Es6q\\u002BqVEZP5SmLMByq6M\\u002BS1ujv1F6u8Cwn6O/amY3vzjurb8W9hPAnoLMPQYOkT8mJXc/CqRNwFnFtT\\u002BO29K\\u002BV5cjv5IHdD6BxQa/988tP0c2DECy2nQ/dT4BwB0svL8WsGm98Ew6PpKeWT5qbl9AhV0HP1eqFD/06cI9DLE3P/gC/D94SM88V7Svv8bPuj9Ou8m\\u002B6sFvv09Kjb7ewkq/IyUwv4cJqT4qeps9yLahvyBx3jxbVpo/bEfkvn53xz59\\u002BJO\\u002BmvDtPx5\\u002BJz6G81\\u002B/FJuPPQylXT\\u002Bcwbi/CgTqv1isTTzhsEY/4Ue3PtAxdj9YjJw/ooQPv04Bv7/\\u002BcAM\\u002B0kaRPh49yL54udS/gGOIu\\u002BeeDb8W2KY9\"\n  },\n  {\n    \"CategoryId\": 41,\n    \"Name\": \"Adventure Nutrition\",\n    \"NameEmbeddingBase64\": \"0QrNv1FvFz8ybwg/Ar2mvu0CbL8KLbE/fNXdPqv/lj9rady/7t6Ev0N\\u002BsD\\u002BS/Pi/\\u002BNxUP7x8AT9UZNY/SO9Dv0vJFEDKXCc\\u002BuhjTvzxHFkA5eQRAaUkBv3raYT/yAaC\\u002BbA\\u002BCPwT5oj/M/wzAeqn1vkIyDT8s1Q3AVoLtPtTYgr70aN8\\u002BZKrTv0f\\u002B5L7s4jlATvZZv2qu175GWRO/Z1ACQBcnqT9TUBZAjnFmP2h/oj2OTbs\\u002BAmXGv5cVEr/lkoC/MNu9Pzaxgr6zIXO/7gZ7Ps78tL9Wtds\\u002BZz93vjY0fT\\u002B\\u002BuYM/iFuUv6esBj\\u002BJE\\u002BI/LVtDPj4aDz4uo1DAWFg4QFowCz/sGCVACo6LvyywBkB0DTy8jO0wwPfumb\\u002Bqo88/Jk\\u002B\\u002BPxf5Gz4k7u0\\u002BVApTPXK1kj2\\u002B/AA9KdIovzQwB77w1ALAta5lv/RujD6aP8g/dYgcP/v\\u002BTL\\u002BZ\\u002Bxs/Z2rgvfwCDECi4E4/YPsGPzhUtL\\u002Byppe/mWqDPzTIpr60PBC\\u002Bxj9sv/Q8nb/W1sK/RpSvQHSTJT4I1Ew/4dBPPo/4lT8MF6o/B/8/wDz8H7/\\u002BnBo/cxmwP/poDj9Mp70\\u002BEkd3PwxfTb5ewQ2/hFcAwDo0wT80xg2\\u002BYECJPtBhyL14nnY/JXDpv6DyITzi5QlAqFQDP7ol/D4kU4I\\u002B8mQqQHiF2D8JyFq\\u002BlkWqvZvJCD\\u002B4ZQk/ik6yv\\u002BRAIL/Mm4\\u002B/5XjlPpX20D\\u002BemPW/agBXv9J4RUB0RUy/NHZcP1BRI7wSeJjAbpVYPYYYmj\\u002BOb0VAI6S2PoVKMb\\u002B03io9Puf1vlh3Hb2FRKQ/fAKjvqT4IT92RJY/TP5oPy8oc79qjBbAVGYQPq4D\\u002Bb/elGS/\\u002BIWwvYqulj/zOGg/3YhOwJiauD7iKW69/BAtv0B0o7\\u002BHi5M/pF\\u002BYvpvujL\\u002BYJgg/4MBbQFh8Ob/QiY2\\u002BF1pwP8u6gr8RLzA/o1lBQJLacL9ChlQ\\u002BRLyQPpyahL7gtQC/qsvAvhdP5T7YQr\\u002B\\u002BjTkEPw6iUT8EiPO/OxU/QOZNeL8aFam\\u002BRUfJvufesb9YXrk8bNq6vg6DkL863E8/epB4v1aZeT\\u002BzsxQ/MEXOPwvE\\u002Br4WMCy/bYbSvx6P3D30NPg/bGZOPoYNlD6LkHC/CeK\\u002BPxiI4r/sNJQ/uvr8PxO3oD/bu0S/Ln3uPsLMbD6Su4\\u002B9/pcYPheetMAt9Kq/y1KUP5EfIj/tZT\\u002B/oJSZPPF84z43N0g\\u002B5Eatv/L9xL7m\\u002BbQ/HItZvuCc370rure9mlVZP7pyAz4s9f4/qZYgv5JMgT8jEtK\\u002BqpEeP5Ckuz109IM\\u002BXQudvl720j9Yt0K\\u002BdT94QOSMJkAqkwm/yFT/vw4HhL3QLtE/91g/P6w\\u002BJr/WbyY/2hG3vxF8nT5Y3TG/lCblvhbf\\u002Br\\u002B3k5W\\u002Bl8dDQF6BWL0QSH\\u002B/rhC2vw6kCsBy/yS/Xl5Pv8hwqL55yIw\\u002BJOGkP/ullz/ArRY/HNirvXa5Oj9iKKy/0WrTv4LRbb/82K6/QvpIv6ZCMMBp4bS/2f/hvp2slz5mdSM/jKkCvrJgOz9VLnm\\u002BnMyPP4edCsD\\u002BtkG/NsTkvhq9\\u002BT7MV4M/znFYPiGfvj/owkw/QuGxvr8/VD\\u002BgstK\\u002BxON3vsqh8Dwn0Qw\\u002BsHgDP2IJJz4k0wu/3sCkv/Nytr\\u002BxZsK/1uYEvxKE1j7\\u002Bld6\\u002BcuUMwCBrE8Dc1jJAvVumPwK9w8DvOXI/pfUlv5TpHcAd3Ka/sovUPszlmz523GI\\u002BoIsxv1cXyz9wx8k/5NfJvaDedT\\u002Bf\\u002BlS/LAQzvVMdkj\\u002BcIpw/AgRDvq1imD/3vkvA3B\\u002BaP3eQAkA8HXJAZAtVvKifm78ZOZ8/pCX0vblLbj\\u002B8/Au/VNO\\u002BPlRwAT9JsCU\\u002BiF8QQAgGfT8KL4y\\u002BTiavP3q9CD8BOfu/ErQ7P1zfoj8b29Q/FSE2v/9c4D6h6sS\\u002BIR8eP2A1z7\\u002BkdwK94wjavyGeDr\\u002BqcqA\\u002BzbHMvzbjcr/3hjm/XPMVvYGg0D3LEke/uyJvv\\u002BlY8T3Ex/2\\u002Bl4Q3wPRQpz6BZQPAw88dwHICbL1UPjXA\"\n  },\n  {\n    \"CategoryId\": 42,\n    \"Name\": \"Tactical Gear\",\n    \"NameEmbeddingBase64\": \"ZRgKwGbRPEBj6f0/JMCHvxrMxj7rW6Q/mwUWQGWHdz9Cu3\\u002B/jiiyv8GQgD\\u002BGs8C/hUrDPyxa2z\\u002B4exBAtmk2v7fWoT\\u002Bhq7A95zFpP9A92z4Ksbm\\u002Brmozv\\u002BwpkL6y\\u002BZW9prJCP48\\u002BLj941sW\\u002BLecdv8qPkL\\u002Bp5oDAR4uqPkD5kD/IfoI/hHppvo3\\u002BMb7TnHc/o7HUv3hc8j5NC4G\\u002BZ\\u002BwoQKp9pL4OoN4/17sIv4oFCb9HQKY/4mSlv79VOz\\u002BaGTM961MZQDsAlr/HeIY/Wschvxb\\u002BI7/KBdm\\u002BHgZPvrSCor\\u002B4\\u002B3k/1cpJvkT/mj9Qzkc/8EDkPU4YCz8KQprAAMCTP9\\u002BC376Oyd8/\\u002Bpa8vmvy7L5Em7U/tSlvP7LAHr9QT2A/v0C3PyRTnj4PQ9A/Kj63vQ9tnz/tuWi/lFx3P2pOaL8jUpu/JDzBvaDXGz\\u002BRKyG/hkrxvfj0gL\\u002BG4ApA5pJLvwrgYj/rpuQ/QJzJvrEotj8Gcia/fDrhvNLMyL4kv1C/1bUSvwxVbL\\u002B\\u002BPP6/gD33QAk9375Ert6/SCEvPYY5lj8Cy4E/J/kzvxoF0T55MgE/SWvAv176/j2Og0q/gOTGPBsbjr\\u002BG1BC/cAIjPgg5VT3qYZS\\u002BfY9dPxozHD8Ws8w\\u002BM2M0v4Nkxr8yX7g/FHuwv4kMoj5uZpC/1dnIvj3raUABUsy\\u002BrBtiPq2zAz9AVsI\\u002BVlWPvzhvir\\u002BhohK/kL1lPBSJIb1sV00/1yELv\\u002BRx1T\\u002BwbK6/2PWdPzUcIkCmqpPAX/01PzPh3T\\u002BdG6O/Tlcovlreob3EE0\\u002B\\u002BtXIIwK7liz8vvQBA01bEvtIhiT9/4P8\\u002Bjr8tP2aviL81a8C/rPCmvswrdjwm8FW/0wQWPlVnKkDgkWy/t2RHwAZQiD5gXq4\\u002B4VCmP1rIwr/\\u002B15\\u002B/YBo8vRBt8LzTPBI/cf7VP3PKbz00psO/Lmiwv7GwIL/y3oQ\\u002B732gPwJ/wb2fETm/FZYoPuxxOz9G4oO\\u002Ba5YYvsqUsL\\u002BXdPo\\u002B0LOGP5QJvD1ZEgM\\u002BDMhPQIgDZb98D\\u002Bo\\u002BsHHyPkXWFcDGbdW\\u002BnH7PPXeUyL/nmJg/yLKBv4xeO73oHoM83gCcP8q6YT\\u002BgTYU/gEf\\u002Bv73qo78Ks0w/tsaePVozTb1wvtc/NGdBPkQi1r47bvO/1oMvvzqkLUCkfgnAi208P4o/gb8NiVI/07cAQPMOwcDixk0/ihQsP4R9Hj\\u002BiH8O\\u002BPx9Xv/adiT\\u002B69LE/uu28vswPWb8/1INAkqsBP87CgL9Me5\\u002B/Tnjqvz7SAEDUm0O\\u002B724CwIBW47\\u002BM1JS\\u002BFJOgPkN1zz\\u002BFPFfANhyyPorAHr64Ide/NQF1QITwzT7yQp8/GKucvyqlUz8mjMw/F9\\u002BzPyQ7m7/CMhZAhM4sP2m1Uj9GILG\\u002BOw7ZP62WKz7US2a/dxd3P61NiT\\u002BmWeO/N4QiPyg6JcA1NTnAKS7ZPwY8vr/g0dm/ehGuveDiP775U3g/vfkgv0SYCz8k2xa/OqwFwGcGtr\\u002BE8jK/vIp1Ps6Upr6ZqFU\\u002B/Fy3PUpF6b8Ua/I/dO1DP67V5D4ENoW/VvbnPwswv7\\u002BKmgq\\u002B38rsP5n4LL8Ag287VRyjPwZmuL5qGQo\\u002BiM4wPlpOyT7857C/26XoPyV\\u002BFEAgdka\\u002Btzyiv6xNjT91aoW/MfnNPYwVUz\\u002BNxuo/QpUGP3Iogb\\u002Bk\\u002BA4\\u002B1LdHv4zbhb\\u002BQVz9A6Kz0v5A508D3uAi/Pa\\u002B0P8zcVz\\u002B3sky/r77hv92xy76GQFG/UpQiwAP1\\u002Bb69VP\\u002B\\u002Bo/O\\u002BP6678b2u7uU/4sGZPaKKOT\\u002BCRvs\\u002BDU4QwCkyqT/8OHO/F0zCP\\u002Ba/oj/MYV5ArlGZvVhzXz8q\\u002BVs/lWUiP\\u002BcRvb5Dtmq\\u002BSxGJP\\u002B5xAkBcsNG\\u002BoIHWPxjrWT\\u002B3I\\u002BW\\u002BCOYFP5bgLD8MLl8/Z8omP1tjoD60WW\\u002B/KAMgvyudTD9nF7E/Xkz/P08jEsBOkqO/tmfxv766G7\\u002BGb06/RM5EwBg9tD8wdcq\\u002BW\\u002B2yv5ZyRj/KtEG/\\u002BEAiv5pnir95VxM/NJ3/vTDq2z6YxAvACDqZv9DkGb/NNOq/\"\n  },\n  {\n    \"CategoryId\": 43,\n    \"Name\": \"All-terrain Vehicles\",\n    \"NameEmbeddingBase64\": \"Nqx8v4/f6D9Gh0xA2YyAv3Af/76FoY8/NwYsvgh9Nz/SUhnAu7s8P6Weej9nTFnAdd5sPyWbGUCvZwQ/dDNUP8JCJUDZdtw/iKEBvsdDHsAtHkQ/Szymv4DWWz\\u002Bat2y/ZG1jvn8fAEA37wDAu2a4vri5YL8cFbPAzt8gPgxVtj9bMo0\\u002BCD\\u002BhPqNvL79kszdAVgkSwN75BEDIAQ490C2Qv0o9Aj8xLiJAVHyavwC4YL9itH4/wNvDv4\\u002Blj7/U3r8\\u002BLpUcQF6d9b/84Lg/IUfav54JKL/7xkO/nuOdv0s1oz8Wo9G9PnRzP5Q1jz98ZKu97d3CPxosxz902dnAd5NyP9eS0j9\\u002BU3c/zKiAv/6Ul7/B//e\\u002BmStBQIjYhT/jnhY/uTiLP5piHD9hRiY/3qgav1HI1z0MMGe9pn/Cv2DcL8AoeIG\\u002BgL2Dv7YwrL8\\u002Bnk2\\u002BNEvtPj6o2b/11q4/Kz89P6J23D8iCFJAKfUYvzw9nb\\u002BrV4w/Sjv6PvxQ8L\\u002BG81Q/WylPP/I\\u002BW8CHNxpAurENQW\\u002BacL9srbs\\u002BvXcFQLurt78IUc6/6AXRPipuJ7\\u002BgZM298lpBwF4clD\\u002BYwrg\\u002BwHSYPk25270\\u002BJFg/cscuwJUVVMD1x6\\u002B/QgdkPz/1qb8HGZ0/IgEuvwTN8b4pQnU/ZBruPr/u4z/T\\u002BXW/lJccQIHcP0Beaag/fdnEP0KwKr7ri2M/7Ciqv2fZjb56BWs/QbHOPhL5PT82yzE\\u002BxqW\\u002Bv7DMHUCw/BXAlV25v02fpD9o/IPADSIhv04aBr8dW6y/eKufPplf174tdbw/vRcCP5hxxT9M6YBAdgVXP8oSjz\\u002BVY7g/PsEOPwHker89VSDAQrMDQFEMdr3ApuM/5eEzPxKHZkAXHa6/nsg1wFYmnb9/Ebw/GlEJQAc5gr5c9gnA1i\\u002BXPjpk0L5Cpxq\\u002BH6GaQLYuqr4P3ZTANkeIPxdcGMAHBVU/7CfevwgwmbuApJG92/71PR6wAD92BK4/RqhgwJvSHT7IaF8/02PrvvSP\\u002Bj3Imrq/BB2KP8kQ8r/FpcC/inuzPwiM9r/eypK/I2o0Pxq6ub85HTBAE9GDvwlsPL7nHGs/yfmRPwQ3Uz/ed9G/Qs3nv1lQGb8uUMs/DrM5v8gUwr9m8dw\\u002BLjKTv/Bj4b7FRm0\\u002BUkUbwD7vEj9wHMK/lDdNPRSWOL88XUXAuPryv\\u002B8DBcGw4ry7gqa9vZmKPj\\u002Bw306\\u002BIrRqvxFLuD/S6Go9yuFFP05Cmz7MQLZAbg5hv/W\\u002Btj6aUE\\u002B/6v4Av3aIzT86tsm/0k\\u002BNP7CM4L82EAY/HqJSPxTG5j/sfUW/ijGkvu6Grrxf2P6\\u002BZZq\\u002BQFv6wD\\u002BA5UdAM7MePvmciT8iYFE/20AgPwBmDsAoKgZA3hG3v8Qz6D2GVJa/TLeQvqcEHsDIP9E\\u002BEpscQKpG\\u002Bj/Qt27AeIyWPwSpyr\\u002BFexjAAF4bv4OOfT/IGeK/cnB/P38v4T3SiAlA81UsP4WQqj\\u002B1Dfm\\u002BIzGJv3Jwmz5wlo080DofP8xbXL83mPA\\u002BCN0HvT3qAMAGT9s/TCJlP\\u002Bd02b9o7g7AOqmMP27fhb9YWVE\\u002BSgl5P2WuG7/GpVe/Yd0RP/My979a3eo/hMkzQMpsJz\\u002Bjv7S/8O9dPPGxFMBWOX8/DvwPQBoqIkBPHIk/MLpPvpgQgb/juXO/7gCDP65DA0DawEY/0okOwL5nSr8eDa5AlTBav5fwEsF9dFi/NJRtvYF3Cz/zzwrAJu6yPTlIRT\\u002BpJEFAUh7Ive6t1z4krpG\\u002BlB2NQLa7fj5gI8G\\u002Bn1RKP\\u002BvP8T/B92tAEBARvgNGE0BhfQjAOtxHP3bT5D8Hcb5AvdoTwK452j3\\u002BBRhAM9IgwH62ib/\\u002BUx7Ao8kUP/hFLL\\u002B/fiG/5j8jQDWQUL8BRATAOMOGQImh9L76fYi\\u002BH7eaP5eOhT\\u002By6SzAegfiP4u2C0D6zOo/OLhIPz\\u002B5uL\\u002BfHwC/LEsQwMqLUD4aSik\\u002BnS27vlQ3pr8M5S3AZwOiv4nboj99sWM/PtWKv3uTL8DWq72/degIwHXIPT8noQ/ASt2gvxIX2j4zJ1W/\"\n  },\n  {\n    \"CategoryId\": 44,\n    \"Name\": \"High-Altitude Cake Protection\",\n    \"NameEmbeddingBase64\": \"1uhqwEiCI0Ceiqo/PNB8Pzd1mb6XoQU/\\u002BE/2P8uDHEB0sRnAWq5nvvRKjb8OlTbAS4UfP/ZEKkCbQ9o\\u002BnhfhPwPFiT8vsQVACiR\\u002BwG8Glj4F3V9AgORjvq/vy77sL9y96SQeQPWr2z\\u002BIkB/A1ZMTQDrQAT1aFKnANMkQPqs5n7/ezCtAhtz7vr3GAMCtq0O\\u002Bsq6JvxuW2j8GljI\\u002BHNfLP0TVhD\\u002BI1N8/XC8fwCb/7b/98X4/9P4AwDDej78ulR6/xHakvxB0C79jO38/cs1PwEb7R79G27Q/5xf\\u002BPhuijj53mbw\\u002B1yKAv6gTdT029oW\\u002BWCsovyAFfz8YhJfAAlCTP/KgvD/upQo/zCYNwNW3Kz5TWRBAK/cYQPR87r68avk/lor6PycZ9T5GYb0/cuuGPlQHVj9eL6q/JqGfv3IFcz9jwwtADmFawLk82r\\u002BwYB\\u002B\\u002BdnCrvz3fAMDvp3g/CKShvpPxrz/YxCA/Fc\\u002BmvwyDbMC/C9a/A2QcP/JKg8C\\u002BW8q/054BP7jyGMCskznAOlobQQO1ZsAy9Rm/VxFXwFi1eL\\u002Byj/6/semsvwI/ij8SUGi\\u002B7V0XvgKUV7/Euiq9Tn6UvmY2LkCiHYE/nIoJwAy3/T8IrZI/wOmBvyZahcB\\u002BQU/ACuKgvz75ez93mTpAisEbv\\u002BiAZb\\u002BIkjy/ABkbQKAQa0DcGLk\\u002Bd\\u002BOMQIMWQ0Dives/tNnAPw/CvL83nVA/Y3jUPzay8j\\u002BPx5M/2hsAveJDHL\\u002Bs00a/axLTPiHtFkAPgmfAbmhUPy2wBT\\u002Bs0z3Abj6rPwZlfT8CRYLAmABwvyDvyb/9sek/rCNhPyjWRT/j5F0\\u002BzLFGwLpfXEDo8RDA8M7Fvc9C2D/Pfly\\u002BwbhiP1QpPkDmf40/VCZcwDp/ez6Z1p8/Ce3EPtzndT43pAJAHCAkvww4Ir/opbC9Uu4gQBB\\u002B77\\u002BC22nAHTTOP2bwFL9ToIg\\u002BFUEZQFuWFcBYYys/2KggP/HqG0Bk9L6/ThAjwPxPeb\\u002BwjVu8o/anv13c5sA\\u002Bt3w/mMhowPY8v70IFEQ/wEmDP5dspb98xWZA/6YWQH1xmL9/ccQ/GfyTv9w1Bb7j\\u002BOu\\u002BiFctQGU94z6A0rE/F4mrvyZqGb935QK\\u002BnKx/vdt6BcBL6YU\\u002BBnoMPmx8\\u002Bj8Fw9A/FARsPxx6RD8c7ETAuXexvcYUY0BJb3fA9hanPkF1CMF9a36/x89bv6k4CcB1Wd4/6hEIv0y4CUAQxgq\\u002BhOhgv7S2kT7cit9AhpXsvxJbIsD4LFc/jORaPro4Gr\\u002BCA0A\\u002BXlNYv5zTGUBh7L4/TiVMP2TqsD\\u002BfA5I\\u002B1fHTv9fBjMBpL6K/5GDYQI3AGkBwEWE/YC2eP1xC076V0kLAIbpvPwJqIMAF4WBA1J4OwIzrCL/AM\\u002B2/ZvX\\u002BvwZgeL/0Zwq/4tgEQMD2MEApGSnA2OUNQArrfL9yX52\\u002BSsD4P67K1z94qpi\\u002BxKOHPyhq7j5s7qS9UxkQwPGqBECAOZK/FCNCwOUFND9cc3C/BaoLQJ3HED6o6cE\\u002B15oWvrgPQD1abExA96cXQL3B7j5aVNQ//B\\u002B7P3Wlej8ON9c\\u002BusVIQGTpCcA06ylAxm\\u002BgQHCSJL\\u002BuJohAuEcSQI4aMT\\u002BKLm2\\u002BSJPpPsqhk7\\u002Bk7eo\\u002BLTJIQORnq79AZI87JCAFwCJBK78NEpk/h8w9wDsXOsAq5LW/RCXGv3MzeT/CVvQ/xjQpP0pRJ8H1Hpa9096VPqc8IsAugAXA1k06PbAcSUCGdjxAGwUswKFZw751wF3ATPcFQD0xM0D\\u002B8pi\\u002BQw\\u002BsPo7jgj\\u002Bw2Ce/TzA6P586jT81TfG/PykDvxwioD\\u002BTR\\u002BZANt7BPgcROMDpviDANaoTPyp7sj\\u002BGzxjAGFQIPbuIsD8Wuei/SsRwQK4l0b\\u002BqeJC\\u002BU\\u002BZ5QGVjlj/HqMu\\u002BeTQoQI6htT2QP0TAVgmyv3Jt5z0vAA/APhLKvYaygcBEveK/UbI2PvPIFj\\u002B4u5s\\u002BvkU5QGWdxT6\\u002BATW/WrsGQE4FF77bV78/ra2PwIwGfL\\u002BeHIbAKwYsQPpooT\\u002BnJkdAdlBQP/PEoj8gOY8/\"\n  },\n  {\n    \"CategoryId\": 45,\n    \"Name\": \"Outdoor Audio\",\n    \"NameEmbeddingBase64\": \"HopXPpWwZ7/APNw/0F5jv2i2nD9moTo/K0WGvgYolL\\u002BPexC/uRWZvhQVx74DlRO/6pkYvShqpT8m2MY/WIncPsY3NkAM1dU/FJvqPsI9hj\\u002BKJdc9Yx6HPmYWtj5BaDy/Z8HBv0oTnT54NK6/rEi\\u002BvpgDHr8JySLAY3DEvqwuxbzuBMg/9Goav1xYY78AUi\\u002B/vA8DvzktXL41yBXAPqfjP5m0kz55cIA/JPrMviO5uL8/QMS/e7LIv5zhPz3C8xzAF9IHQPraoL48h9q\\u002BQK3zviwipL\\u002Bse6q\\u002BHNX9vbtOpT\\u002BAd6A/cTYqQOLyBT/Jv5W\\u002BBUQSP2QeET\\u002BKLJDAuniBP\\u002BGSwD17bC5A0ZYTP6srRT8oFqQ9V7emv1bhd70FT5s/EnavP18jpb/6VB8/j058vzQkX7/a2OE\\u002BfrULwLbrD7\\u002BMWTm\\u002BbziZv582Bb8yed0\\u002B5obHPiA18D00JKe\\u002BkyTnvhzfIT/G5A9AC/GYvxYqy74BOCe\\u002BB64NP/hMMb\\u002B1sAC/fxxaP9Ebg7/sllQ/rBbZQNhVr794c6A/aN8xvkAiaz4RtfO\\u002BNbinv8QHsL8cmai9udHBvQRUvD6q9Ps/HJGBv6toWL\\u002BLwQc/FG09vxbhWj8KfEi\\u002BwMyIP/xblb8By84\\u002B6fX6vyk0ir4xoHo\\u002B6ljoPdLCNkA8fni/kuL7PwaJ4z9efkc/rJEyQD7ggT92\\u002B\\u002By\\u002BzFglP/ygdL\\u002Br/fs\\u002BIo4nv52RtD/m6UA/MfVLPyJdhT9eqG2\\u002Bke\\u002Bov5DbNb7Ll\\u002Bq/kVGHP9RhZT3AD7m/WDWzv2KK1L9StpA9GkTKPo5EXz6t2SZAuw8uv/SJBUCfnaE/h4OwvnzVjT5uHAQ\\u002BPwGBPwV1xj7e5Zw\\u002BZOm7PxwY3D84H7O\\u002BxxNGwEgF57\\u002BaC0y/8QNrP60D575LcMi/bAGLv9D2qz9YWJc/BlTNPzReHD67GUHAtmnXPkJt07/3ug6/kw5KvnQRIT41egq\\u002BddcBvhSR\\u002BL5EGTu/Nt3Iv3SEdb8NlBC/qF1OQCixgL5qL1XA4360PUZ5SD8VoY2/YOF/P2ETBL4vWEa\\u002BivV6PmgoRT/qyOY/7BgFwE6FfL1bY1M/3Y3/Py4EDr6z1mY/\\u002BsD4vebB170ThpU/WiZNPz4IGD5uJ7U/bHXOPo4LFT\\u002Bq53y/6U9cvqBvgT2NfVO\\u002B5G/nvle837\\u002BWlnXAqOjpv4uxpcAj\\u002Bc6\\u002BmKTdP2Exsz9YM6e\\u002BuHzZvwpo/j40h7A8vtcIP5pSxj4mmjpAOY\\u002Btv6S22T8/esQ/o/CePcVbHEB9K1A/XlqXvxT7fj5hji0/8g1FP9ZWtb12P4O/6rk2PnHg0z\\u002BJqZS/wSiDQNYqIT5eTcA/\\u002BP4ovSGj5b4CZgW/wCAFQED7UcD21YW/SkPBP1F3uj8tkQY/FC8EwAYYrL\\u002Bo0a\\u002B\\u002B3gEIQGgiBD68Mxm/hYruvwHyWr8039u/z1pUv975pD\\u002BGqEbA2jWnP8C6Sz\\u002BQVQxA2N4nvqvpoT\\u002BYWrq/puC1v6e0zz4McwM/XYIZv0TQMz9wCJM\\u002BBQDfPlZvCcAslUg/tiSmP85H6r6\\u002B7KC/JsSoPww/Ej6IFew8bO\\u002BMvhAgCT60elg\\u002BxWZfP62der/O\\u002B8s/HnGTvzwOuD8kgRbA787lPwczIz/csls/dNbLvT4ebT5NqyG\\u002Bwbu9Pa513D5xAGO/HQ4wv3ifMr7EsJ49fFFQvwjhIMCS9itASIoVvmL7u8DSSQbAhlPFPizbkr9Ji6W/\\u002BSYsP0VOZz7gmfk/sVI9wLli0D4PLyW/C18mPwqWDr\\u002BPViK/RhGwPyA94z\\u002BaqM8/vKu4P/4EKD8593u\\u002BgsyPP4uzIUDmhixAAM3aPMCbjj9YsX4/FL7Mv4r2n7/Johy/8EjCv08XAj/YcE698vdhQMYBsr/SKv2\\u002BZNCSvsBKIj8FzyU/w\\u002BMMvnuHQL894lq/ABhOuThN8L54vww/uQO3vg31oL/6sKQ/uPXpvnP\\u002BfL4LhJY/RQ2YPY5fjr\\u002BE5fO\\u002BWRsavoGzWL/6qr8/hZ3Kv7xRhr6W/Zo\\u002BtPKfPhfDmz8\\u002BhlzATnOXvuG91r9maJY/\"\n  },\n  {\n    \"CategoryId\": 46,\n    \"Name\": \"Solar Chargers\",\n    \"NameEmbeddingBase64\": \"YIblvyJ\\u002BFUAQoAg\\u002B3nBeP/E91D9z2IK\\u002BKxLqP8ClkTqEFbO\\u002Bn1uAvWaFNj\\u002BpIpO/WhaPvnu3CUAKT3w/9uqFPnkEKD8ZHLA\\u002B/o1Vv/Jxxz7MZdM\\u002Bpv4UwAlFhL9u0z\\u002B\\u002BW6m6P8wYjz8S19A/EoP2vt5NyL8g7RjAAOmTvdM/1L6KeBbAfP7oPt2n\\u002BD5wDKS/AIqFOoq/UsBBe\\u002BG/z1U8P7ymqrzEVU7A8jZOv7oR2b5p5ty/5c0xPwBFuj8yA0W\\u002BUSa1P2Ngp789uCNAry4Lv8Jgib5vMCc\\u002BEJZRvicHPj4c6iI/wr3WPxb8GEB0Lmy\\u002BL0MAPmLO\\u002BD9eRI7AMdgIPxnHSz\\u002BIcQS\\u002BhDwnv7SL9D9SjXe/v1I/v0LHvD7S6vG\\u002Ba/esv2Hjt77SP9a\\u002Bcl2hP5LRo793w7K/NYTwvxiFGb9QgTk8Wr7tPdbmUL916j0/iU\\u002B7Pz5JsD9jAHE/PACGPuWvzD9Uk8g/BR13vgx8GD2rdoe/7aWoP/gyN8ApNa2\\u002BON7BP0AF0b8QSN\\u002B/B7KnQKsEVr4yY\\u002B4/j7N7Pz2QNr/axom\\u002BBse5v5ExQr9Xs8Q\\u002Bolcav5iICsDvfcq\\u002BAARqPvDtt776OHu/2oXDPw/JrD6Txqa/sXIpP3o\\u002BgL/7ywQ/LybDv0CRPz\\u002B8dSBAgg1JPxotaD8MYJK9SOWUP0Ks7D9Uz3g9cBgCQLgxKT\\u002BYa9K/6GlCvw4MD75TcGA\\u002Bblk0P/IhWj92uTK\\u002BOLgKP/8bUb871s0/Z90/P3zgdD/H9UzAYClTvobctr9A/Y\\u002B\\u002BZfoOPwta078Q4yk/Zh/EPuxgHUBW/1k/TnQSvywguz93VZ8/sD\\u002BLvTKIvD7IUAi\\u002BNra8PzFXXT8cvQ1AQFm/vqeVTEDy9xC\\u002Bz9ROwDD9iT\\u002B\\u002B4zO/tSmbP1TTlT/ZRKA/BkJJQIox8D29oKy/\\u002Bm40QMLAgr8EeNO/55IOvx/urL8W\\u002Bh4/E3i5voac0z9Y6AU/kx1\\u002Bv0wBkT\\u002B2aWC/3rWOv3AYaz2FAC2/hKuUPlrsUMCwqmK/aQKvPiWf/T/yca4\\u002B0p9Av1oiDcAc99a/2peNP46alr9wmhg/4Nsov9botL9cHhRA0KoBQAqF9D0Y6LK/k577vj09s78oyp6\\u002BY82kP4sbi79UHQVAiCASP2ZyRMCK4KE/WrOnPsZHsD10YwBAyCAAv8amND8iHjLA5Lxzv4h\\u002BqMAtd2W\\u002BCyiOvnVbuz2d5pq/w8cHvzZP1z\\u002BfQqq/paoov1Gajb/LJvA/sL\\u002Bqvz7vRj87hhHAnbQQvs40FUBN0Jo/IFnYPsTs2LxsDQy/ttJcvyFjRz9Zsm9AtErPvuJICUDO0bW/mbduQCGEFkC3uvQ\\u002BOBIDP6x4iL8i9kg\\u002BQgvwPiuogb\\u002BAwVI/ckOYP0kwrb4KVKg/ZQL9vhBNI72aPSA/whiiP1sK\\u002Bb\\u002BPWpi/MGaNP6aw3r9lyCG/vpymv44Mdj8rwBPAhRqLP4qvpr/InT2/FWqUv/yeJ0DiM9e\\u002B4Djev4BdZECBYDy/VDp7PSgmUr/O7vo9Ni6IPthuE74rca4\\u002B7dryPhyEgz9kGpw/gFgLPsLrhT\\u002BtjU2/NjIwQEHuI79RnnK/ebsQv3BJdb8saSc\\u002BeqY2vy/nXz9AjmG/4ACVvmiCAT\\u002BkiX4/2J8CPbprFb7fia8\\u002BDFS6vZZ7lj32SWa/u\\u002BC5v4KMm75CbVw/eT5ov9qOFj5X1iNApLb1PviircCCoiA/R1Qxvxgwxb9miyfAjx4JP4cG9z9YUKI/uNWjvRthTD9yO/2/ZxScP27Fqr\\u002BFeY8/mCFVP5UtUT6wGyE/NjnMvAYCP78iUgy/G8wCQEESuj5WzG1AItGEv5pwBb8e1EY/7sU7v\\u002Big3D/OMIA\\u002BNR\\u002Bjvep8HsDYdca8gixMv0IsMz9edT4/EyMLQArRZj8ACAbArTF4PwLVWb/TenK/rGPCP511ZL/gmQ2/qc1DP61Cr7\\u002BkRqa/zociwOBUzz2ZEBi/zM9/v9gkOL9fGKC/OoNjvlD3J7/2rX6/tqDOv3q\\u002Bur9ebZk\\u002B3pXYvmPEAkBBhp8\\u002B70XCP4Clbr9EWK0/\"\n  },\n  {\n    \"CategoryId\": 47,\n    \"Name\": \"Hiking Boots\",\n    \"NameEmbeddingBase64\": \"D3Tdv8VklD8utg1ALSGiPtIUYD/ROJU/YCCnv9K5Ij\\u002Bcyci/5JrQvbljXz/l0y\\u002B/5sYUP0Ck1bwOJb8/GYSLPmeWcT/sOY0/jvusvn7y0T/wJXA/vMwdveiiGT/bPQm/4ls/v0/grj8K4tY\\u002BSHg2verFFL\\u002BmTADAQiAmP4rfZD8uwTO\\u002Bm2tzv9V7Gr9nq09ABi0xv7b8uT4y7yO/nnNvP6PThz\\u002BvlLY/QFP\\u002BO118Kz6guGS8sTdEv4ix6L563ae/ONhOvsYE6b4WauA99pCaPjAyAL\\u002BYrRm/bcZGP4hKkj/SyaQ/y\\u002BKFPaSpHj\\u002BSPKU\\u002BxO\\u002BZP4izhDyhOJ/AI2EwP0Hktj81aLw/1O6jv5O\\u002BPj2j/4o\\u002BlsaWP3b8jT48VNE/Hl4DQBsxK7/5QM4\\u002BWs5qPumhhr4I454//bq8v5QV5D0iXWi/VPytPuu8Pz9lzNY/vQF8PzeI3b\\u002BAk2I/cKchwD7\\u002Bnj9o7MI/M0qJP3aL87\\u002BUZ66/2gQWvidu6L8A/IW/iHIiP9lepj2tYju/GufyQNJouL/EJQJAIg1iP3st9T8Wd3A\\u002BK4gQwMjRkT9ct4\\u002B9BiN1vgLABj8gGaM/I7a5v64onj8oVxq\\u002BCznfvwBYLb9AcAE7FRwJQI9Z5b02LwRAA4YxwMIknr\\u002BikS0/RKUiv05MH7/3Eny/4nmJPqUq0D/UJbU/TOMlQJib6T4Zsje/du8cP8FyWL43XIW/AJY9Omgxdr63FgK/9jB1vw0yB0Aq8dO\\u002BVQYgv\\u002BI48j\\u002BkjA3AamiCP0rHgT9n8dy//xF2vodFIb9N9HQ\\u002BnfJ4Pza\\u002Byr6lOCE/cl9ov0TwV75eYyM/dEXNPhLfxL\\u002BJ9La\\u002B6Zv9PssNtz2lGeO\\u002BvLFCP388kb9VRt8/\\u002BuOKv6/BhD9hM4q/GK/fvMbtoD/UYuA/moRhv7gcoT/ccPg/K\\u002BQwQLFDgr841sS/v3Qcv1WIDMAaQ8m/kOGkP0JXID6gO6u8JUWdP0YXfr/UIlg/jHFqvyTHo78kmxU93QfJP3PhEED97RPAM1AUQGTaPcCspSC/Y8PMP0Qc5L/MAH4/NEH5PqjCtzxIKCxAY1gPwPRdKb8nXaq/zrjtP47yBD9SjFc\\u002BIAjivRSDs78\\u002Bspe/4HrdPsi2LT/UCxE/0EiAv0JEmr8Cc6O/ZPijP6YSET\\u002BTao\\u002B/yjzMPxTDzDxCYVrArsQIv8Vzt8BDZp4\\u002BM0EFQET6Tj8BkOC\\u002B\\u002Bzuvvt9Gij8mpfi\\u002BF9jiv7SuMz5RphVAKOlmvhTdGj94nzY/dcV3vgSlMEBEtAxAFKWFv10dpr/6Z0i/RkkVPga2dD/\\u002Bu/e/HiETwJDczL8i4IQ\\u002B//5YQDriXUCZ1hG/9Wnnv\\u002BLubz/\\u002B0CQ\\u002BsBJXP4SzbcBcQKU/Xmapvl6BYD/pLfO/SRdyPJK49r\\u002BPpzU/eDktQEhzUz5wVbS8Z5EIPnwb575yoCPAA/pfvlTFDj\\u002BaI7S/qnIYPx7iNj\\u002BRLRlA6ub2v\\u002BhHL70cwADAfnHMv3Nfmr\\u002BsM3O\\u002BrQ9Zv0Y9QD5wG7O/haupPj7ieb/ig9c/LzkHPyrLNL/bo4g/XJbYP\\u002BCm4rvs7TK/2aXqPp61sb8A6D6\\u002BEhMAQMftq7\\u002BiuMk\\u002BfPZ6P4TRIj/AG4a/JWGhPQz6WL8fcry/snivvmp6jT0VtB0/2byRPqW/TL/O9oq/j0PjP2j0lL/IfJe/W9sWP/S7AcCNaHVAQS4Kv2t0rsB/iaS/mG20P1rcA8Ajbrq\\u002BjmTCvjoctb5EFjI/QGlRPIArOj/oEmI/jfMsQPwIMj8zAhq/er0DPVYsWD/EC2Y/s/dbvopDHT9oIMS/xjcqvgnBOr88tCNA9FS2vujeDj5Y/wlAm8Ewv4iw1b70dwzA\\u002BJY2vtoHI0Br3OW/w93mP6v85j4K5DU/nPsgQDkdq7489gVAdVisP9ynor/0y4s\\u002BRh\\u002BOPl/ZG79s\\u002BPM8uK7vPwLjp8AxpG4\\u002BQL59P4/ZkT\\u002BHxFs\\u002BZO9IvJasTD//gom/lcaUP2JdzL7u22S/duMJv4CRt78UQh/AwBHPv7wmnr/VwTfA0e4LwBxFs79/hAY/\"\n  },\n  {\n    \"CategoryId\": 48,\n    \"Name\": \"Survival Gear\",\n    \"NameEmbeddingBase64\": \"dKz3v/IrDEAAUdI/mK8Uvg2TEUDyp6M/5aesP/HTFD55ntK/odGsvxJlaD9NANm/gf6BP2njlz9rXko/O3NVP6JRZz\\u002B94OA/RU2zPsMDCECNZrE\\u002BimWmPcK0wj5Zzc2/bJTsP/7czb60Umq/4oKZP0\\u002BZST7YoT3ATPUPvtjFpL6\\u002Bw8W\\u002BWlVRPZuXFL9W5eM/IhxAPxbR7T4x97G/wKCrPwfMMr8kQyNAeMe1vjsl\\u002Bz59zvg9eHtQv4\\u002BgLz58zwHAwsROQMmsD8A0Vsg\\u002BEyhJv4u49r7tGyy/rD5OP3sV3r8L7qo\\u002BuuuHPSjIqT5/6Js/CudnPy5i0724inTATHedP8ZGlD6yBqg/7oOzv7IkHz6wLIU/pm9CvpC8C78MJ44\\u002BuTapP1qJsz9YhXg/kTClPin1BkDkZti\\u002ByVdrP8MBQz8cqBw997eOv6brpb4KdHk\\u002Bxndov5zEyb\\u002B24OQ\\u002BaTWov\\u002Bw6XT8GCZA/zkAAvyjwvz4kqGk\\u002BPp1MP5JzDb\\u002BQ0rW\\u002BoOevPmCr375O5rS9rvzoQLs56r4Y5xm\\u002BHaaFPtxTTr6qwns/Xgrhv50ko74IKPq9kkYEvzR62b0HjAw/7\\u002BSQPq9/IL98Lvq\\u002Bd8wov5kOKj/GkYS/4E2uP1RThb/5pZo\\u002B4fc5v1fupb/ShytASO79v28FYj\\u002BG\\u002B7U\\u002BwTYVQFFn\\u002BT/h6yW\\u002BkrMpP5k9AT/3vw0/0TmKv0aNnL59hOi/gJwlO\\u002B93J7/Sy8s\\u002BPHM2vmPVjz8AK3M/v70pvkOFyj8owZHAgoM7vy\\u002BVM786B3U\\u002BUqf6vkR2n79v/xi/UTmev0yx0D7Lk\\u002Bs/OcspvylCmD/bQ7k\\u002BZiyeP3b4pL\\u002BrgRXAVe6rPpIHHr77W22/oOAaP/IuL0CJQz2/yrkBwJO83b6dhG4/wcaGPx1yjL\\u002BHW9w/rMgavzz0kj5QvPi9aGMyQHYIVT5kkmG/n0tbvqVTy7\\u002B8lNQ\\u002BuEavvN76XL\\u002BHXXO/gdwrP4jaMr9/nPY9BUb7v4JP5z1Ygg4\\u002B8esbP3Fj5D98paC/HBz/PzyPP7/mQqc\\u002BcpWSP6/bwL/Tkwq/1V3KPlYG078pf6o/C5YLv2uDCj8HH4m/IjXKPdeToz8aPys/6fdRv4y1Db9O\\u002B44/ApO1vkwKf78YLxu9qrWqPjCK6j2TuPu\\u002BJXS4vSZhqD\\u002BzZQe/Lt2hP0UpCD\\u002BBl7q/O42yvZbfzcA8nBW\\u002B0AoYP/cuET8BsQo/C4XFP3aWiT6jsZU/Dm85v9CSor8M4lJAcAKSv7Y0zL1dAgQ/WI9Av6tLgj8dU2e\\u002Bsj08wMqyz70yjkE\\u002BoA\\u002BFvqrLYL/iy9q/cB0dPkxYNb1SLiu/ynh/QA/DGD/isLA/CFmLvzhMMjwvmBtAupwbPzpEhcBMOwFAYhNzvqN2nT4y7bi\\u002B8PFIvxyW0z0yyza\\u002B1eVgQMOtjT5i8re/0CvRvkD3JsDfz7y/soYvQITunb9uy5a/MSeAPz7zpz4zB\\u002B4/N3yrvxAR7j722La/4oDcvxuHSb9nNvi/BTRYv\\u002BGwYz7hCxa/IdDFPp5r5r4Ovlo//CIWv\\u002B2BI7\\u002BGV2m\\u002B0XIGPx1zd8D4/sC/N3LAPpon179CMcI9Ki4LP6SvDD9ZqaW/7ri5v29swD9LkPa\\u002B\\u002BFVHP5SClz9WiaE925UYPg1y1D\\u002Bw0EA/SjzsvgzzwT/Njyg/AANWPyMfbj/I/pY\\u002BqGKBvxmA6r8HNQJAD3bMvuz81cAVU5g/vPvKvBkChb/0NRHALEhWv5U7or52EKY/FAEtPldUeD9uuSS\\u002BjC7BP0kXBD/rcDM/zycWP5qfej9CoTW/o\\u002BiKv/FInT7o5g/ACOz4PZMgnD81Fm5AyS/NPdq7ND/P7Y4/hm7avpqJ2j8wszY/BGikPsSskz8g6pW\\u002BtUG7P6xwcj18Ph4/j7kOvnBbvD65sMs/Hi0VP/AwAD8bHko/OFWDv8/e0j8w9jFAi/WwP1b2QMDCv\\u002Bk\\u002BIvBIwIDvir8Pl7C/Rh4awDBjdL1D95\\u002B9u\\u002B0IwK62qT/GKge/yn4DP5mQA79IL6c/Esqsv/CRJD8CHJy/WHPTv3uKFT7Ohnq/\"\n  },\n  {\n    \"CategoryId\": 49,\n    \"Name\": \"Fishing Equipment\",\n    \"NameEmbeddingBase64\": \"7jSVv5pwkD5vVrg/UrDMv6SUhz/uz2W/yLfbP9LKfz\\u002Bdl9a/PUBmvq\\u002BS3z7YssO/4AnjO1jGpT8eXt490uVZP8KAFUD824w/UTEPPwBQLz1yY5Y/3UuoPqRHmb4PPxHASUXzPU8EkT\\u002B8roq/tlbOvnoLHT4s8h3AutDcvrIcOr\\u002Bn6Lm/502OvtuDUr9oCau\\u002B0GNIP8VNCcAnmJG/1LnfP\\u002Bl\\u002BwT/\\u002BAak/gCsYwMOJjr5Gbce\\u002BUKmpPit4HT\\u002BETvS/qbpAQI90oL/KfRnA\\u002BrejvwI5KT\\u002B6wkK/xSOTPxaaLL9YV04/RuaIPusfGT/lhRW/9cYvQLg7/byxEn7APPSdPyAQDL9\\u002BhcA/PREYPvBYrj/8br8/fAKvvy/H8z6QfAK85I63Pg52mz\\u002BmcUY/JI7Jvm2zFz3\\u002BVIu\\u002BJLB7v8Geyz8bFC2/aOEWwHPAlT\\u002BmtIO/8sq1vtLBnz/fvI8/XPadv3ybaT8nwWO\\u002BpJv4vsF2Az\\u002BiDMW9BNMKPmkywL88Apo\\u002BKxA0viGLkL92JY2/GQDmQDitaD1y8jY\\u002B/ILXPwUnXb8YZsw\\u002BIfYBv\\u002BkiD8BskMy9rL5hv0tADr/9S0g\\u002BmyaYvU5Upr9cRqc\\u002BLt4HvkbYCr7Uheq/okSSP3RMcL8Uky\\u002B/7KH6v\\u002BoS573nXLA/MOaHP65Clj90R0y/XjfSP23HIEASnYQ\\u002BWmDLP/Lcgr7YCwbAm6Gvvwsak7\\u002B9Wu2\\u002BdJKyPqWsnz8ywWe\\u002BUO81Pu5wyz88GxLAjuNyvzhY0z7YSCLAJ1cpP7DFTT1Ub8i9GtVkv9Ww/74fQ6\\u002B/CcNcv7W8qD\\u002BiUOg/q6kivyNFiz/9XA8\\u002B0ns6P6Ngez6o6QK/2pGYP\\u002BqAv78rDTY\\u002BYLASP8fOKr/c0bk\\u002BI51AwGQMTr9fuN\\u002B\\u002Bge9Cv1m2Bz6\\u002Byio\\u002BWZs3PwFh6L5meuU\\u002B\\u002BkwFQNBDaz/cNta/Pvd8P0lc1r8gRMk8xViUP1oplD2OMPi/SuHSPgYpYr6AZWe6Xyumv/jpJr9muhS/uzcDQPaCmr4o0Ue/NrzhP7ilgj\\u002BXbIQ\\u002BDNWevUoJk786N0M\\u002BrvvSvrzQIsDhjdY/QBYVv9eAQT8qRpo/Ail7PwLBmj94NCg/ZVXCv4iEj79UeyJAQsh\\u002Bv9sj87\\u002B/b98\\u002BtmyCP3wXTj7MQ1O/KjGePwcAdz\\u002BWbs6/C/uFP9J9V7\\u002BYIDLAZmrzPgNbwMBkXDk/5c0AP7jJgz60eTw/iMUZvZAhQT7PRQo/cvB7vxAFEkBz1ew\\u002BfsbOv36nLD9A16M7ZKrOPgNgG0CcFEs/89blv8U/vL9jj7M/ZzKcv\\u002BBmjD8yAqe/TFqDP7Caxz/dYka\\u002BmplQQAS5\\u002BL6d1z2\\u002BFylNP4hwg7\\u002BlGms/JOjWvy5Mhb/V8Ry/sDxYP7D3aD864q09ss11PsL3MT\\u002BKQQ8/6lIUQIiEg71DYMC/7N9FPxrOPb9374y/aO/7vqxRHb8u2wTA75zkP/ghnL\\u002B4mpo/jvtAP3ryUr8G5KG\\u002Bnpidv/I1uz\\u002BUqfW/SuKLv7V2\\u002Bz\\u002B/lMU\\u002Bwj28vqi8IsC47vk\\u002Bs/eXP4ghmT4IUNw\\u002BduqGvsPLdb\\u002BO5RG/4J7oPDQBnz/6duA/Km08Px\\u002BlHb\\u002BwAYo/\\u002B0YywJV9IUDiOBe/FAGzP4Qi5D3NUpA\\u002BZvqBPySVsD/5MJo\\u002BITsTv9\\u002BOYD9W82y/\\u002BDnYP6Pcoj4iZOK\\u002Bo6Cev/CfBb5/miVAfqPPP1flw8BIVdY\\u002Bha3hPhjsJ7/e4s2\\u002BOu46P4CE5rs1yIk/KeEbPtO7AUDWaOu\\u002BEaykPwXpCr9cc089XMLuvumF5z/stm8/R30MwNRrfT/aYaS/hFa2P3ShDED0r11ATK4TPwninz98HxO/zWscPyCiCjxfv6O/7zkHPvXEBkArCQs/UM6JP\\u002BhpLr9coUw/k5M/QFaqdL/gBYK/axkKPwwS47\\u002BOFPi/ugyaPpG24r9Y7q4/NA2jP5Pjq7\\u002BaxJO\\u002BRxIYwKbdWT1slqM/6eYpv/p13j4hzWW\\u002BuWASvrSKUz6Svay/Drn3vkCLdDyAnyU/PgYEvu4F2D9d\\u002BjjAFijMv6IWg76GoJ8/\"\n  },\n  {\n    \"CategoryId\": 5,\n    \"Name\": \"Survival Tools\",\n    \"NameEmbeddingBase64\": \"Xv0AwCFqez\\u002BM8u0/zJKLPkBsFkB7FSk/OlgcPzI6A73x0uW\\u002B4MxcvwjaQj/biMS/mqYQP4TrET\\u002Bcx9\\u002B8uIaUP1Sitr4NdxBA44A4PlzgYj/csjI/YT1MPok9IT8FZ8y/8tftP7Knhz9fyjW/w49pP7pnVT/A/ELA2tgDPyR3kL\\u002BYKD2/6f6aPUqXHL8qMao/apZpP5i1Uz1oaJK/2vgZPxdbeL\\u002B2s0hAvYQOv1iJwL0sGiO\\u002BxPLvvzHxGD5ubQDA7Cv5P3jbn79AQ6O\\u002BnM8QvzCw/b4OpD\\u002B9msefP4xWHcAKcRM/cEtzPF5uQz\\u002BRdKk/\\u002BIW3P9qkUL9xg27AYnW3P\\u002BbL9D5iskA/loruv8iqbL6\\u002BdZ8//ubhPpe5ML\\u002BMFMY9gv8HQOJ76z84rVU/VMnqvjADuT802ei\\u002BNlSSP0bbgT\\u002BA7fS9RKFMv9QkOb9PYW0\\u002B3bSDv41Sm78EUAw/HuiPv6SBmj\\u002BOuzU\\u002BtjAgvz\\u002BQRL9y8dU/npI9P0T0mr/0SvW\\u002Biz93Pxe9\\u002BD4p1Sg\\u002B5nrTQHp8i79cGaU\\u002BS60uPlMLmD2saH4/h2Tjvz4ODr/Rkiq/QdpFvzcbPT7sCyS9pCGRvk9Ba7946cq\\u002BulZUPxpxyL\\u002BPhSy/GESAP\\u002BQtCr9kg5M\\u002B3rcHvjT2jr7CDihAmnW8v8DYjj8KQoI/QN0UQCVZ7T8Af2E\\u002BIfBjPheprz91K2E\\u002B2sd8v65zwT5OeuO/0tS0PpTm1L8F1uy\\u002BorGxvQN16T6ZonI/4pBiPgg4lT/Y8U7AtgFav6tGML0S7kg//5mJvmT/ib8bnDq/iExJv8Y46j5Pd6Y/8IuVPe4V3z7aybQ9eqeEP1h0E8D6if6/EktKPxCG3j7tEfa/dg9Zv7E1TEBUZri9sYm\\u002Bv0REFr5onLc/VaofP9C\\u002Bqb1rgydAiFk/vwxbOD4d8Ru/voD8PwqoVL44os\\u002B\\u002BLVk3vzhJsr\\u002BvZIK\\u002BKTSsPzdYWL8ESBC97e\\u002BZPwDPdr9VK34\\u002BtN7RvwD5Yr0qMTE/zY2lP0trcj8YIS\\u002B\\u002BJBAWQEJATr9tBZo\\u002B1xJ/P2Oqmb\\u002BrZoy/fVMcv2g0b7/L2Lw/PPlGvR2M3r1sfWu/Uoa\\u002BvdBeBT97UXC\\u002B1kKhvpmITT7oZy0\\u002BFQ5yv7REML4o4ok/mv01vhF33r7IuQ2/FEUCP\\u002BQEez9gsvi7NHkyQDUsib4p\\u002B4u/GB57v1zay8B\\u002BvCy/OfKUvlI4Jj9JBrY/Th2qPnvPCL4EWBM\\u002Bsqhzv478YL9wywBAd9Kmv/iUmz63nfQ\\u002Bn2iAvyitIT9HJSC/zcsXwKYFhb/kXok/s2QrPmJb7L88lcy\\u002B5Dqxv5rhUL\\u002BXiQG/RbaEQAAWXT6oMWA\\u002BtmfOv6p1Y75JFz1AYP1svHSHiMA8j/w/c2uhP4eZYL5oYuW\\u002B8Af8vrZW9z7IHkI9jhxbQDH7YT5M5ArAqJpQvkIeIcBNbE\\u002B/isvXP8PhVT4OK2e/BFRAP\\u002BRlxb7Q/\\u002BI/5tu0vyRC7Lxg9Mi/qzPOvwLtxj4WxxnAtp2FvojJSD\\u002BKFoK/gHYRu6SHVr6vQJM/H16UPULfo75MScG\\u002BrLK3PfTPTMBvqsi/YPk/P20QsL9JiqU/5\\u002ByVPpthUD/1UA2/7hPovw0Dhz55goO/HXi3vlpelj8h19w\\u002B18YPP3I7lT8cmnA/F4Wmvpnndj\\u002B8Who/fcYMP\\u002BU0xD/UJwE\\u002BqAHDv5Mmt78KteQ/TVkmP9gtvcDr870/K9rPPYyBt79GVJy/k1v9vg1jPb9qY7o\\u002B2\\u002ByLP6CBsz\\u002BVmgS//KY/P0pQQD/VQGK\\u002BsdGOP4A6WD\\u002Bal7w\\u002BglcHv/Fe4b2y6gfA1E4FvyK6sT56nI1AvfIRPsu2jz9Mz0U/1uZdvqm9rT5iyuQ/b5M3vuL/iz98CvW\\u002B/WzcP3LpVL9Fak8/21OFP\\u002BU6ar5UCfU/Su4vP\\u002BxYzj9eIv0\\u002B1O4Tv/TPij\\u002BuAwJAeSR0P7OiVsCITV07cU9HwJNsX76QP92/mKIOwEMH2r7AJsS7n4vpv4ZywT/3bLO\\u002BIIlbP760IL7C5x0/Zj2Kv0bMRD8IVBo\\u002BSnR1vqDvCT4lMKW/\"\n  },\n  {\n    \"CategoryId\": 50,\n    \"Name\": \"Sleeping Bags\",\n    \"NameEmbeddingBase64\": \"rNhlv1GO/D7PKwu/1GWsPgLKoD93F84/2nAGQN0OJr9udRc/3ZqRPooEoL9cT4o9JKKLvwNxG0Dpbtc/bjvavu5kbT9hMTi/H6M/wBZfkr7egAJASjeTvuhInT9W04Y\\u002B3zaWvl5BoL58sEU/oCQ/vMzrGL/et0fA1AqEvwMEYz78EwG/j5PCvl0PwD8vyzo/scv2P9r\\u002BNT7sneG\\u002Bwu0OP\\u002BzTsT90oEo/dPwNP2r\\u002B1L5UmnE9dHrXvuDnZb7g6te/AEf4PvVmtb7ZmQhA4sedvnucRb/CbUS\\u002B/wfQv8G34r4RMBy/ZmX2Ps4spz\\u002BL59M/JkSEPoshDEBO\\u002BjHATuCTP6Hl6D763wo/TqH4vwk7oz62UK8/ylKdPwzy9r4cOze\\u002BlAvdPt6hED8TcqM/8JqBP3xMDED6pd2\\u002BZZ12PuKBVr\\u002Bh\\u002Bqy/D8srvwXhqb2afwS/Pq1jv2HQdD80btu/WNvsvp6\\u002Bhr7HBGO/PITrPS4uG75m1UO/jl2WP\\u002BPNNcB8mzC/yljOv3MWvT8VAa2/eLHFQOUjzD/ANfk/1s/APzDAjbz6Laq/Fmo6wFK4XT66cIu/Nd2bvmkvCD\\u002BQJzy8FUO7PhsnMEBwcWC\\u002BZkH0P3JBiD8SbM4/vFMUQLR0vD4byeI/ohAVwNBByb/NKgVAcwvFPTb8tz7QF9A\\u002BgGaJvQlmDkCj\\u002BMw/TPZmPxz8c78eIxBAWxtKPwSsxD5RorS80jcSP0Rcjb8BYAM/REotvyt1EsBsAOg\\u002BDaijv\\u002BA3\\u002BD\\u002BsTD/Ar0mWv3/U4L5bfZS\\u002Byxy4PsG4B8C4oGq9TzjjP8wK4r4OsCQ/V4oRwIRWAz\\u002BD8p8/k\\u002B3uP\\u002BjbSD1Hl5s/CkClviapaT5quoo/ltuQP5ednj9/Lr2/f1yfvqsrPL\\u002Brl1\\u002B/MIiTv0RqAcAutYA/OnCAPxhIXD6zWLy/2bgGQLgXEj8AaR86r3E\\u002Bv195P78w3As\\u002Bxmp2vii\\u002BE8BM9uq/XbievyLyGz63owi/xGdavyT3WD/odQE/78pNv9wt3L\\u002Bq\\u002BlC/AnNzP/Uyhj5dw6G/qERlv7LdmL\\u002BgJay9wT4rP\\u002BsUlL8eRSBAykF4P23UnT6s\\u002BZK/7Nf6P2exJEAaSLK/xOBhv/7GFUB7L\\u002BK\\u002BqDDXP1hKmj7S/RA/gSaZv8ryAsDpELQ/fklAv52RuD6jIFK/PP9xPWSqJT9ONk3Ag1Fxv8bywsCuAbA/f/1oPmmok7/VLx8/sxx7v2QMIb/U1vI9SjIPwMy9Ob/Datc/OROyv2Khyr\\u002B6z8g/N1KJP6kkMEDYTSy/UYq/vpz4mz5aVKO/gqqKv\\u002BZdr786cVc/JNmFPtAu1zwA4Jq/PihPQCA8775GCLY/S9mMP1qyKT8IUm4/3HhfPz42BsAS2eA/9OULv1d\\u002B8D6kHd4/zHxBP77jcb5opju/dd5dQH1L7r49fju/CHiNv\\u002BfR\\u002BL9Ly5S/VXzavxYQsL6AWHu\\u002BqmQcP94DXj\\u002BHM5Y/eHrfv45mcT9egN\\u002B/a3t5P0HNhr8DWQO/RjagPghxcr8UPmO/joYKvXOLK7\\u002Bw6F\\u002B/dSgBvzlFoj5yD0K/WqdYvhlRC7/TIYu/g2o\\u002BP7jk3b\\u002B2xx2/9rbLP2dqlj\\u002BoYDM/qGMCP\\u002BjNiT4DxYS/CKx2PZnyyT4WZjm/uqnHvd8D4T37OtI/RSJ6v\\u002B0v8D9Y/UC/7Cl0P3LyjT99OSc/nVdOvoyukb\\u002BfoRlAR1TtvcwRpcBgHse\\u002B5NE1wHRLz788BKA7y4/nPd0RGj8NajBAUJCKO7ATDD9pXBA\\u002BgBBTQKt4577sKyY/E9oEP3r5kT5YOFA/sDHQvyQU2D8\\u002BJc2/\\u002BJ\\u002BGv9nmoT2RtHxAdZA5v7aImz\\u002BKIe0/ovyWvrRdG7/Y6aA\\u002Brv\\u002BCP6qULEAQGze\\u002Bk3zHP7hqar\\u002Bx\\u002B1e/oCyNvrRtRsBrRvY\\u002BRCPAPbFU7b7diu4\\u002BQAGHP7WZPr69vsK\\u002BAOppPiOkrD5kDgo\\u002BdrK0v3trUj8i6hXAPN1yPU9a3b/EE9K/DKjAP1ICQj/WQfI\\u002BYiK3vX0GgD\\u002BBtWg\\u002BwvxQv\\u002BV8Nr82VHPAlY3fv\\u002BY3CL/Oocu\\u002B\"\n  },\n  {\n    \"CategoryId\": 51,\n    \"Name\": \"Trekking Poles\",\n    \"NameEmbeddingBase64\": \"IfkFvmXtyz8yc\\u002B8/zBpzv8GOx77fNay/nChQPnKLXj/LfALA9KsKvSvTGkDcgwfA1AdnP0R9pz9c\\u002BE8/DKItv5Vluj8wOGNAy41VP7RbPz8Vypk/oMI9wMq8or\\u002Bz5uO/o8DFP3WGH0Ak9EO/C38IwFRZcj49m3bAfrOJPxjg7r8pgmq/AkWxv/BqS78Vkos\\u002BrNamv5Cjzb\\u002B\\u002Bds6/dkkVQGHR8D95Fug/ekWSv2XKFj97upa/bLQ7wOS53T55dZ6/IIMDv1IwHT4U2D49mg0wwBQeZT\\u002BMLeG\\u002BL8SPP/210j\\u002ByMSs/ABGYviQGYr4vwsM/V3WePr7Hd78cub3A7JvYPzgLnj9qHAg/1uWrv9adCT\\u002B89KC\\u002BrLS5P7cYZz6tSwlAVLJBPgXI1D\\u002BY\\u002ByA/guSKvy\\u002BDQ79aXgq9fhjfvwKxYr/Y7SW/9b39v1yFZryd8mI/nrqmP4R\\u002B/z4hlUy/nBJ6v\\u002BQYaj84is8/L1gbv7Z9ED10ET\\u002B\\u002BxCZFP\\u002BWKhsDSCa\\u002B\\u002BAWaSPwvlrr4gGqY/iIDiQI6GGcDxIBVAU3KIQIK2E0CesiE/U\\u002B2xvziSDbxig0m/R4DovjgqMj0gFwk85ruTvzmEIcCkoag\\u002BdMf9vnEcHb4tEUG\\u002B1k9rQN2izr/Qr0I/CkkMwApam77Wbf4/bXofvu0StT04sd0\\u002BhlzFP7urJkD60/M/3OuFP6mWOUCqBuM\\u002BfjVzv2y1xT1c3Qo\\u002BNE4gv36hCUBMprS/3Sw\\u002BP0sPqD/KKzI\\u002BJ4zXPvlh5j/Ks2nAkyqCP0B0Lb7wud\\u002B/ss9EvaNyEb9E5RM/FkFIv1xN0D76aNI/FTa9v3PFJj7Drmw/6DSUP1HG1T\\u002B2G4G/ZEpEP6pMuL/KvMQ\\u002BoFL8PFRBhkCazhNA3K6owPN1rD7CS5s/dLHAP7SGBcDESjW\\u002Bz1M1QCILBEBqTwE/dO5sP9Bdyb/k1nTARBfMP0llor/ZSk4/gXQlQBg0nz0ciIc/dbufP\\u002BMQmL4\\u002Baje/YhoIwJn/wj9Ka8q9Lm1YP0CBFD0xjLu/xK1JQFw5P7\\u002BHXs0/S2gXP9zf4b/0X6e/LRhmv7CO3L\\u002B8kwlAYhXXv/EPSL9AwCQ/VH2RPcDEaD0UCzc\\u002BUuHBv8CzGDycfUNA4cMAP5Ut1b9oYh9A6K9HPyWyyr7mey\\u002B/PPqcvgxakj\\u002B2CHK/sm/1Plb\\u002Bu74M/Dy\\u002BNjsqwD5O2sBxRGS/2OpGP/Db7j/8qJU\\u002B56vuvlDIIECTSAy/FmgUvor9LcCpLD5Aw8IDwOAXRz9Y0VC/ouLTPZVjmj9SH4Q\\u002BPfqCvxj9sj9uPce/zqq\\u002BvnBrzj\\u002BMwb\\u002B/59Xuv69Qqb5UKg/ADGiPQHL\\u002BBUCcyEM/HmExwHJ92D4mdqk\\u002Bk7UtQCRnOcDI3n4\\u002B5maIPyhymj8Id1q/aMJXPgKuWD02ao\\u002B\\u002BAhWtPy1Mgj5iqn6\\u002B1KQRvoRXv70bRwXA2ohYP3IYIUDVwyvAEnBrvoF5bD8Kb4U/rlSNv0NYwb7yo2i/dqsZwGV5GMDW77O/rESUvWiyab/KXxbAW\\u002BPXPlZ9Ar8C4TdACnVMP6CcHz8x4hc9ur4aQK/Har96ky0/QHszP7K09z1MfDi/eFQVPsjkc78umFk/MEbgPxTwHkAa/Ay/hmAHQMy4NT\\u002BqSe\\u002B\\u002Bs9gavidXrz/rq52/xdO\\u002Bv1mqnj5ver\\u002B/yYYmvyr/Jr/q2d4\\u002BlmYtvz1Z2D5O12pAij62Pq43AsFu/Co/N47VP2j5Q79i2Du/4rP8PkH0pT6mxzNAgPGgvujHKz2AF7K8kLShP0Y1pT8KHkK/W9iCP/RD3D8G0jNAgFM\\u002BPb482D7HTbq/oJ7nPyLvxD99yndAV1oDPm0vTT9q2qU/Ke2Ov7XCzT4x/pm/lkR1vqAlGL\\u002BqOsw9OMS3vx5Unj/K8Ba/zJvWPsUR8j9\\u002BZBS/HfSDvg2xCb0GuJu/6daUv9TTLj5mPaQ\\u002BZ7ogQPYRFcAd5Pu/whb8v9zusj/fSIy/02SUv8zRer8IkeW/uELvvuXc5r8gcRpA7ZYIv8i7mr\\u002BSnmA9tG8fwBRPCL8FWGvAmveAv/dBKsDSXtC/\"\n  },\n  {\n    \"CategoryId\": 52,\n    \"Name\": \"Backpacks\",\n    \"NameEmbeddingBase64\": \"hKlrvxRHYb5OqXI/qGP5vnYznT8Ul7o8/nHKP95CRT\\u002BPqrK/Dhm3vvlht76A4OG/1l1av3123T8BYeQ/5D5OvthnFkBqxuw\\u002BTgt1v2galD/f4mQ/pOVjv7fNQr/KpVO/z\\u002Bjcv4O3oL7XfY4/bEVuv6BLsL\\u002BIBlrA1VaQPQZflL9LO1y/Fz5xv01mur74B/I/d4XQP2gWLj8865m\\u002Bw9MaPswZpb2kQ9E/xKIgvw\\u002BN0r7GfWo/NL6pv\\u002BYJS78vz6O/ACSlP2FMk7/g6Kq7D6PMvttxBz83IlK/1DqOvwrR2z882TQ/xuB8P2Yc\\u002Bj7wYZK9rO6NP6tNm75mr3vASsD4P1p5ej9TgE0/ETd/v1W4DEABCRJAnJW1PvEz377Tz5g\\u002BZp6XPyJCIUAzTjc/qlJAP7gLlz9c1bc\\u002BrEU0verdob\\u002BbpFS/TbEpvSKBxz/GvWk/PPUsP\\u002BNQHz4xPM2\\u002BZfD2v6AHsz4hgEm/PECZvSg5u7\\u002BCroM/p8iWP1rzZMAIl6y/\\u002BiSOvminPD7\\u002BQrA/8GbjQIAElL/4TQtAGuBeQNTAlL08bwm\\u002Br1dBwEOrjT8CxYe/awJxv1b5pD\\u002Bz0Fg/wmCTv3TpID8Ufrm\\u002B9UCuvvRumr75Sqi\\u002BgvdBPzXbf78AFvs/oiUmwOPS6b3wiBNAHHNuv1R2Zr6M\\u002B1U\\u002BvqSPP9zs1z9oEfa\\u002BkOrvPzRjrr44YxtAZmvavqbKq7\\u002BkrI29xVvoPpGnRL\\u002BdHDm/CAlOPBnPhj92HYO\\u002BXiLePxOBhz9uMVfAnuUcv0gyMD7w4tg9St9Dv1Qmlb8AJUc7gdGmP\\u002B\\u002BGjz7dhFw/iDZgv1pnsL46S7s//PUHPzoJi76AVCM/iQlmP3Aln78j1Ya/ZmM/vvBiQL417ck\\u002Bw/UPwKwRED6u\\u002BXK/fT73PgqM2b0hRBo\\u002BoPjdve7CKz9nsAZAIP3/P\\u002BoOFL9yuv\\u002B/2HqMu8yX9r80Ce6\\u002BLI6lP8GMlb/vn1y/HShDvigBRT/8YXO\\u002B\\u002B\\u002B\\u002Buv5\\u002BH1b/cAvc/4NpaQA8RlD889iu/7CLdP7FA2b9Oma6\\u002BOAVbP5wyrr9ekdS\\u002BTWmMPewrW7/mPB5AJVrGvoQwOr8AKxC77wQGQCSasz\\u002Bkn\\u002Bk\\u002BrB\\u002BEv\\u002BJHrb5Ahny/4HMxP7GOdj1eA6w9Hq6/vziYKr80T4C/JSC1P/ZZnz\\u002BNxw/AYDd/vSVdRL/wYEzAXZNbv7tVyMD6KVs/UljvP5VyNz/i7F2\\u002BISmOPlREsT9MbwM/cHZdvunJmz8qMRBALILRv2667D6sLAxAnFQXvfLp1D8Tac8\\u002BlIgQvwyrN7\\u002BsA62\\u002B4urqvUqj7T/6F26/rPsMv6YCjr\\u002BAx7W9efGJQPShmz\\u002BV/Q0/FJ/ZvuuhVz84CQ8/7SFEPzetSMBEJOo/5N7QPvyD374KVRrAhdpSP5yoMr9WV1G/J28iQNvHA74muca/cSuPv3RvqD36g/W/Ri/Zv534C78yJ5y\\u002BfdOwv2OshT4QhNM/kBDJvzbMaj7i456/4rB8vREVMr\\u002BTGqi//KAuP/Zqmr/0/pi/JuCRvyuU8r7O/h8\\u002BwJa1OpyPQr9ZpSq/AkKlPhe2\\u002BT1IDtu\\u002BVq6tP0iLOL8yzKy\\u002BUo3gP17vKr\\u002BW5a8/3u2ePyz8qD\\u002BAlEy/oOI\\u002Bvhy1oj4aTZi/npmOv4xGUD/n6YM/iK0xv7wV775kg749J\\u002BVLvtQDoz7bCiA/F01pv6xPpb7cFmhAQWq1vkylysBgBpS\\u002BaGNCvQrdZL/hrB2/OMylPXi6YD9sK6M/fhN6P0ljiD\\u002BWebw/vekVQPAMYT9j5yC/MGdYP4ry4z4WKQFAPOe2vZZQ1z\\u002BOm4C/fIOVv8jnKT3vUGZA9tQYveGeWj\\u002BuoxZAhFItvhP\\u002Bpb4V7wG//JTEPTf1sj9e\\u002BQi/Bv0cQFCIe79KoTy/LinMPx94E8AOjr8\\u002BBJGJPS3Oj751Mf09cDWJvz17Q8BkBtO9i5oZP8IemL84wE0\\u002BhDfIv02UUz94XPK\\u002B6h7aPmkfzz7sdum/GCRpPfnejz/IR3Y\\u002BRg6Iv6DZNr\\u002BEEWW/ZBsFv1jbrb6gg8m/Q/6iv9qkYr8mmE2\\u002B\"\n  },\n  {\n    \"CategoryId\": 53,\n    \"Name\": \"Camping Cookware\",\n    \"NameEmbeddingBase64\": \"GK1Fv24ZKUBmRgNARLCSv\\u002BhJHEDorug/XAStPmcLfL5oJQXAaCP2v0Fqxr/xT0DAEd5Hv9DoEkD5GgVAPMCBv6VEID10LT4/G0QOP0ah9j\\u002BvIzFA57dvv4aZGb/0sJ\\u002B/qvgMP3rb/b5H0p6/PEofP\\u002BHjxr\\u002BYDJnApiPMPxLTmb/DrCvAvcy7vn1AOr\\u002BOlA8/6SfhPzsJVb8ryje/ojqEP/7KVj8Q0Nc\\u002BYNOqvg6Tnr5upsy\\u002BYH3ZvsLRF79c\\u002BArAa1lSQMgPgr5An6O\\u002BoUQ0vwxPtj5wMgfAJjFzPi0xqD/mTpG/XaiNPQkj\\u002Br5YBpQ/S8ulP6qJtT9cFK/Ai9CfP\\u002B4i5b3Y/Z8\\u002BsvrlvxK9rT9KMwE/k/ExP4roqr\\u002BiGZU\\u002BzJW4PtpnVz/pHM4\\u002B4VADPlB8Bj6kfaK\\u002B\\u002B8EQwPrR6T8E0ti/kU5bP2N2OT\\u002B/fJo9L\\u002BJGvj5dW74Asfq9\\u002BYKzv519zj8fDGs/HDa0vijT/b/64xPAZNJBvqzlU8CPfZc9MRCSP4vYe78KPxnA424FQX2JyL\\u002BGuNg\\u002B5WYFP6hN2r6ziI\\u002B/0flDwGmruz5o\\u002BQg/MgHuv\\u002B6ULL9Xfdm\\u002BoD2DP8B4NcDqZdQ/fiAZPoDaBcBIUsE/X2iMP9WiLb9fATRAGCMjwHbW0b5oQBVAqu/wv0qLDEBvsWa/MQ\\u002BEP1Y9UECcnr2/eWi6PzK72T79bia/n4GIPzWECsC\\u002BTta\\u002BB6P1Pl6rSD8YnAg9Z2CoP1SY1L8FT\\u002B8\\u002Bg4Qwv57YSkATuH/APtEgQCTgi766PU2\\u002B1JUOPx763b\\u002B4f2O9qnXmPrIJ0j9QheI/CCRNwMK/1T\\u002BpUSBAQsaYv6v7xL\\u002BqAJO/KCRqPyS\\u002Byz0KGEY/b7yyP6\\u002BtiT5Qya0\\u002BbBeAwPA1lj\\u002BG5t8/t1o\\u002BP4d3Fr/MR/8\\u002BUkb/PjMCar7IaMi/CRHNPzvrY78HSvS/uuq3vyJqMMCcdCE/FgShPymB471y\\u002Bgo/txifP7TxJD/bAeK/wXMfvq471r9NF7y\\u002BLtmHPxOFqb/cthHAi4eVP9Q1GT\\u002B\\u002BtmS/rhgAPzMQfb\\u002BF5Qu/vJgzQBRnZcD1dwZAws3Mv4HSaT6tJhk/orw9QN5qqj\\u002BI7g09PEoLwJbzCj7GDTFA6konPwQNGL\\u002BqgxG/AtNMvzrqZb\\u002Bk7ANARdWyPzH81z8zgVW/AjdCvmc4CkBi3IvAwB83wPQMy8Ba6xG/h/mFP9kmk76unaq/YOGvu8hg/71zDARAEG\\u002B2v780oT5NojlAJGkqwKE33D93uvE/3BEQPbRYxD/Qde4/hHHDv\\u002BH9DT8TWHQ/wTyTv8Tz4r79U3dAUK3KvbAVG77mRK2\\u002BfvuFQEKhqz\\u002BTp5dAO0UVwB2zeL7TiYI/BjEPP/ymwb\\u002BqBs4/NCxJP0LGDj/i7P0/HZ63PhWZ07/jl3U/EVyTQGRjOr6qLTPAvhgbP9KA97\\u002B00Du/nxVcwIW2g7/Chmc/OtHyP2snFj80qh4/Nt2FvzQvEEDdgvC/6Cbov\\u002BUxtD4\\u002B7BbA4AXxP2qEhT1XHHe/L41SvxhShb8r1Iw//uyYP5rxeT5luys/UDKoP5fE6b\\u002BJ0VK/H5jUP0zUrr4pE58\\u002B2AbtP\\u002BYrAb\\u002BqVgU\\u002BDjbZPYDEMz/sDM6/jUeXP0KQiT82Nqo/FOKAvjIuCkCs/fA/C0JWwLDvTUCS2He\\u002BT5k/v6yyLD9XEQc/nEUnwDmrmr/nAldA8slaPVim2MA0pac/R\\u002BAovgETDz\\u002Bilyk/6kSzPclixL1iVjhAQjS1PgiagT/27h8/e6vzP1zJcj9Yb0I/cDQPPleSGz\\u002BrN02\\u002BSJ5FwNlyHj/BtHPAKVutvt6VST8lOItAMxXkPdRBo7/DSgw/2/mhP29/ZT\\u002BPZe0/EhMNPox1Xj8VBYa/wGQgQLxGXT90ekpAFg3KP9KTsj/yriHAWAmYPw\\u002B8j7\\u002B2cQbAosKMv35nKr/Bl5A/aKWNvwwBU78TeOs/4lFpwAAASLe0zTC/QtgVv9iAmb38nr2/ZslQP9q7xT\\u002BvESa/FChpvwTHtL5UCaa/XpoSQG2qTT8flhLAZ\\u002BeivfHv7L\\u002BatUy/\"\n  },\n  {\n    \"CategoryId\": 54,\n    \"Name\": \"Outdoor Lighting\",\n    \"NameEmbeddingBase64\": \"R4hcPq7por7sHrE/8KKXPCTmC0BKGSE/shEBvwMBlL9w\\u002Bjm/UzzDP2lY0z1o1989tcSTv7SduD\\u002BWwgQ\\u002BDEFcvzry/j\\u002Bzcb0/IrSMv4TWs72uEsw/IWBOvmOCYb8rcsS/qHuOPpgLYD4Tu1K/IHUdPTIp5b1bwA/A6h2Kv8iuGr4s\\u002Bua8WYzLPkAokb\\u002BNmIK/OxIev4kTkr9aiBTA9sSWvaiQJT/AN4m/YCMQvhxMHL8x36m/0mDBvx4t3z3Qb/e/sPv8PlwYzr7\\u002BuPE/uBomv5RXSb9gNaE8MPXuPoLOzT9k3JI\\u002BiF4VQAUqjT/3M3e/tZjNPq\\u002BtNkAY/ZPADIYmP2wJXT6LiSI/cW6vvgIFCT\\u002BeaIc\\u002BfLhRv3GHYz2ZcI6\\u002BN6vFPiT4or89iAa/2jhbv05u/L/WOIu/XmffvyEPkr/rooA/Xmdlv4O0tL\\u002BTV20/ICMKP6eA3T86WzK/2NZRvyETbj8CakJApO3jvoAQlr8rQ8S/bOGGv6x/FL\\u002B6GqK/QFE1P4SG9b\\u002BYwWY\\u002BKFvLQGOKzr9jpTg/7RGYPxQrpD1uTZw\\u002BKte6vjYz6r4dcb\\u002B\\u002BClbcv6WOEj/Ciqc/NjspvxRYvr/KGb0\\u002BHOduPtxvab5BCvK\\u002BAKeTP/kD2b/l/QS/nk13vyc4/j9MjxFAf6vnPphI4j9W5rO\\u002BfLW1P6zVHUDjcaM/CKD\\u002BP9t0nz5S2ii/7xGuP0AnKL/ZSTQ/N80\\u002BPznqmD9H7Uc9LNhlP\\u002BDzSj/RkIM/zB0Pv5/LHkCJ47K/upgXQPk2377x\\u002B5C98CrNP2uDrr/6j1K//ChyPSAXxT5CI\\u002Bs/2hnTPSpy9z92BpU/z7iQvt5jrj\\u002BeyyI/PgWOP\\u002Bk5dz8WQAFAYwn2PlWthz/MlIe/BMyJwDKAkj5M0Y2/5E/gvh4QLr\\u002BDP4G\\u002BxaOIP9DeFUC66LY/ZSXqP0rFjD6k4da/\\u002BjwCvfb4678TvwA/tpK2PqLYlb4WGjA/YijFP7PIgL6ESHo9mOuyv9xeZz9CnN\\u002B/0PFKQO/GBMACLgDApjXlvujSZD/y9Yi\\u002BUu2tP9kHCcCx\\u002BhbA8MYIQNJK7b5Mmi9AVPvfv7V6E7/EFDC/rGANQGvQa7\\u002BpR9I/bhelPlheHr50EkE/Dh8Rvw9M975YIt0//M9Vv0dZgr9QbxU/m60Gv5Ajm7sobfI\\u002BmZHFvfiOUr8glCLAgnoXwFe/lcBwS\\u002By8e3rAP/QbAb/nIVM/cIvhv74ZFL\\u002BQ5lm/\\u002Bqhfv1B0Bz8zmlFAirbUv7f2uT8bjxi/Dsk5P4CSGkC\\u002BVdY\\u002BT\\u002Batv\\u002BuvQz7Cr5u\\u002BR2chP42Nmz/DLO8\\u002B/D3Ov2KvXD/wwVS/DQuDQAcbzz4iTAY/5A3yv946hr4Bo5S/BLQiPx59IMAMR8Q\\u002BDNumPxYx5z5ygKM\\u002BJhq\\u002Bv7joIb9YDxBAKhEpQCo2rL/E79O\\u002B3oDavginBsBtr6I/olQYvl5JUj8JHT3A\\u002BkfxPl2S5L6EtRJAvinevgFmkT9WNKy/nmv2vwFYoz9KPO0\\u002BnErWv8JeIj82qqq\\u002BnpOdP6F\\u002BEsDpkhhAqkr0Pp2dsr\\u002BKhcO/5c7FPzoNzz3hN1\\u002B/CcRLP5izlr/Y10w\\u002BifKtP/jZqj7LjPc/RH1FP\\u002BwUkD\\u002Bup5\\u002B/3scXP9C9yL80T4G8nQNMPyfUE7/BdzW/f\\u002B05wL5RXr\\u002BN2gS/gAzqupaULr9vsMG\\u002BjUkmv\\u002BqT9b8mYvA/TpuDPiDDv8C99FG/xNNsPv5Obr/kamW/ppukP4pHfD/5skJAVN/jvFwQUL315gPAYsjgPToqCr/pH0U/sqqGP4RQvD6qjrA\\u002BZzT6vqgkNb66Naw\\u002BLRWPP8hdkD/UYTtAhCXivxZxK7466fk/gAoIvA5tTr/pvje/Qz59PuBjtD\\u002BFkc0/wlXxP2Dm475BBe8/8NVAv1jZQz\\u002BWeCC/tBAfv062qr76XKO\\u002BjWylP14Gfb\\u002BjP1I/CwqxvooQhr9kEa\\u002B8tGrHProqDL99bRI/bgYMvppzW78uYqS/VjURPjFE4b/\\u002BWDA/zuL8vyTYpj7KQ6y9fhD7vgIdCz\\u002B\\u002B\\u002BT7AtyiBPVoyqb9jFT5A\"\n  },\n  {\n    \"CategoryId\": 55,\n    \"Name\": \"Hammocks\",\n    \"NameEmbeddingBase64\": \"51zPvhuJ6z96xC8/93jrvwp/lL72Q0hAT0idP0DMzD4Bg5y/LusgPkpa2D6ygfK/b5hpv8hTbj327dY/pKYVPqrcdz\\u002BOIW0/axk2vnbjGkCg2tA/NPERvZSM5z73fsW/Ahd0v/8vTj/Af\\u002Be/C\\u002BtVP\\u002Bkfor/0fl7AJ9/9PrtZC8Ccu9o9QKTlv1TkYr9DkxBAu1Q1P7WDRb7AsI6/5susPz6SST8PcSW/WCQkv3iDuL1I5Ws\\u002BHKi7v0AO6T5mzv\\u002B/nokvP/6PIb7xYf8\\u002BXJMowMOREr8U2RW/NMmVPxJjxj7iW0e/toJ6P2qPUz9JKTw\\u002BZJmBP8OKAED6SZ3AOHTuPxdhOUA8LqQ/ydqzvQ7h6b3454u9cpDRP9ynET5c0lQ/XIwtQCro8z/4nuq9cJ\\u002B2PIZBxj6QIqW/b8swwKpOr7/Cj2a/36Yxv5h1kT08hhc/QAihPLUes7/Pbqw\\u002BgkAjv24aJr7vf4o/fTiqv27poz/JSzi\\u002BTOslP1Tym8DPeGE/MdHqP1O5Fz\\u002B0J4S/m6nkQFph/7/WFQNANjlGQGjom79soFM\\u002BaMybvqMgEb\\u002BaAmW/pJhxPfys3T/eflQ/jgVWP8oaIkDgjJc/bhtavyTL1j7F3gC/uRAAQHPnqT/Ztu\\u002B/4g6\\u002Bv8oSGz\\u002BA9Zo/8iqivuzHTb6uifI/pqlhPzooXkBMptA95qsOP7RnoD\\u002Bq6ek/ZU0Kv3hY670E04E/AXA3v70gQr7aWKs/6q4mPhcSOL9JlaK/wAH3vsh1FkACzBfA48eqPs8ozL\\u002B02be/LIlavl/K\\u002B78NFFO/QX30PlF9hj9sqDw/IAwMv4gro7775Aw/kGJhPwRwFkBh1QDA0OgkPy7uD7/m7t\\u002B\\u002BuNgzv0qDmz2IuRO/aYU6wPqRg74qaIi/DdTUPswZGj8QIzg/0p2HP7PAG78E6OG\\u002BYIBDQJC8Lb62HEnAC\\u002BNdP/iR1r8ydbM/SHYPP2X6IsBMHg\\u002B/RwmGP84QEkB01uG/prjjvs5lfr9qZpg/cDvHPyBflb2qpMq/qHrGP7dHI8Asrh8/YqW4PrIGR7\\u002Bynr4/gnykP3Jscr9OmaA/JhuZv8x1DL9M2zG\\u002BD8W\\u002BPlpLQL/Ay9m/CE9hv0gBYkBQX4y/Bj8PvYEVC76EsCw\\u002BbdwFPtCjlz529nA/\\u002BnhcPx6tfT5UDmnAV3KDvsij4D4BskXAHuYjwLK6xcBMmAs\\u002B1H\\u002B8vqM0v77T\\u002BsS\\u002BBA\\u002BZv1hfvD\\u002B4mYU/Su3yvkz0eb8pb0hA3cDXvxWu\\u002BL8Ie8e9NiqoP9LVHUAR0RJA8umgv\\u002Bc4xL\\u002BAVv\\u002B7kgD9vtjSl738XB3ABaeSv7pPZD5AwNC/lUY2QHKRnz85OgRA1G9fP4x4zD/Yz5A/BhrePiDBH8BcF\\u002BW\\u002BcjpoP4r05T9hi\\u002BY/fFZnv4QHSj9ESY2/7C88QN7J0D4MHGrATAeoPuJVzT9wXlC/QtoUvwL5ob8pCErA3FYzPk85nT8GwIq/KpYiwE0/Oz/Uz2K/zyaDv4NpXcCQyvq/4/kNPpBzLr9JtuC/nh9lP6Ld67/Rbw5AeojZPt7Hkj/SoDK\\u002BFhbrP2gF4TxW3nO/VjIqvzPHiz9twuU/joznPhanzb\\u002BIHHW9uKamP1HRhr/GF5K/9zuaP/dHFL0N30c/IQ4GPx32PT9qerC9nGDFPz1fS0CsjjM\\u002ByrJhPghD5T7dEgy/Nq/\\u002BvrC6xj92kTRA5H\\u002BuP1at6sDK/4i\\u002BQRo2P6QknT5I3ca/krcLP4B/s7xxkCVASsBKP6DfrDx7OV8\\u002B89uxP2yiYr2k3q6/DTbqP5Ezxz9S6j4/uvEav2JCSj\\u002B8ly3AIVDyvdB9xD3Qh6xAuMDBvz5iRT8pVfc/DgmvvzyVQL5PWArAvY8xvyHVuD9cgOS/gJceQOZK5L5kmqm/d7ODPqKuAL9WD5m/\\u002BGeQP9wRxT2IlQG/GjOlPyxPqb/QMMw/pJ1JQEYuWsBCIoQ/pr2sv0hr2z/BMW6/u10tP0sasr8kRUe/n\\u002B7mviV0873QPNq\\u002BAGzyOkm2ab\\u002BWaes96h9Av730Rj8oYby/5UREv4VnB8CNhKK/\"\n  },\n  {\n    \"CategoryId\": 56,\n    \"Name\": \"Insect Protection\",\n    \"NameEmbeddingBase64\": \"fEspv5ZNh7727Qw/G\\u002BEJv\\u002Bzqlj/q1xM/0hibP0usIUBmuC2/MH9uv1mdgz6SDCu\\u002Ba/\\u002B4vjk9Nz\\u002BoBvw\\u002B36jKP8SiYT5yQMw\\u002BN62Sv26JAkCsHm0/53qevvNXzT7Eqek\\u002BduoXP6gmyj/QUCS/bItFP7Nirj9\\u002B2QvAsoNFv3QCpr501MS/68DMvrJn8D4Mxn0/saOQvyJ7qL\\u002BnRwu\\u002BDKFQvwBXcz/cqZs/t3sMv3Bht7\\u002BmxaW\\u002B848\\u002Bv4qFxz4R1bi/HJ8pvzfZBMAlmKk/UGBvvvysTT8j3Bs/hhIyvl7w3b8fjTU/A3zDPsqfKj\\u002BNjoI\\u002ByHegvIpC0r5hrBPA1lEZQC/uZr4CwoU/TKd2v8Ustz8OOzg/2Bd\\u002BP4j7sj4Gup0/jB2EP7ZTbz\\u002BSniA/RL3UP94xV7\\u002BB8ybAHHFyPgkRD706OWu\\u002Bbb8LwIDSur4gyg\\u002B/bKg7P4bPj79PTbI/5JJEv7oyKD/8Zs8\\u002BZnLzvdrzVr8kW76/g4INv5sBZb\\u002BoXW0//ElIvj7y9r/guuC/BojdQGpVfr\\u002B8HGi\\u002BaEwIP762pb8UHGW/nu32v5XzRT6Uk7C/wfMpvxK0rT99SLM/QcQuP9Ypjj90d\\u002B0/RdGSvzobLz4YEpc/7YWKvj9GHD\\u002B2qeW/cn0YP7q1Ar8wZwJAnDXmPmrVAEBeHG4/G2mVPzlPTkC7rEY\\u002B3mx6PyP4yz/OF82/S5K9PyjXJL9wwRg\\u002Bc9GBP9g8Dj8\\u002Bbrc/PPM2vxy3lD3BUIq/6\\u002BS/vwi0hD\\u002BxM0XAF9HRvzHlCr9\\u002BELC9GqjQvnThAL58Ln\\u002B/RCARPxFxHz\\u002BHqLI/ZDW5vkG6xL53xP49aCYtPYUHtD/ioOq\\u002Bjps/P8OKKz5WZNw/hyXUvjGIb0BGVsQ\\u002BSK4GwAHbAz\\u002BQ4Jq9f\\u002BMnvsuyJb5AxVQ/DZKQPnBPFr6ViiI/AO80PwsOQ78fmJq\\u002BlD29PI6o0T1YlNc8QsbnP5BEVr8xP1i/CbOkP8Yixz\\u002BFcZS\\u002BSGVWwL77Db4CsKC9gDNgv3dSDcB\\u002BZrw\\u002BA\\u002BKeP4blGL4XQ7G\\u002BtIUWvvoSPL\\u002BjXey/2p\\u002BIv3MHYL8awPY/3qtyPqZLRz6fve8/AHONOhQDqj/ew6Q/CDCbv1jlLD/cJZY\\u002BmmxlPt\\u002BErL8Bm5s/A63cvqDuTL\\u002B4zuc/VgImvuzBBj\\u002B4GBVAVBg8vDAoq77QCzQ7pEimPptknsABSNS/\\u002BFOMv35Wsr5tpPm\\u002BPXgQv9g1\\u002BbxQXhHAYg2EvUVHz7\\u002B1g/o/3sqlPh6fk78mNZw\\u002BiyrUvp28yT\\u002B7XvM/AFjwOE//y70L3Cs/5\\u002BUkvmQ5hr8HmgxA6TTTvmJ7/72SVifAXRh2QAAbLEBekK4\\u002BqJ0Fv4wJJb/Rf\\u002By\\u002Bo2W4v7vk078Oho4/ONmfvpeW07\\u002BwZAe\\u002B1yGev5\\u002BW/r9cZRI/WhydP61SAz8vEQHA1umTPtAmO8CIS7q8qkFLPjic5T7KPuu/tAfNPjzMFkBLznc/UDthP7Df4jzEMzi/mGPFvXjhtj\\u002BQSja/Fn9\\u002BP/O2tz7TxiI/N0GiP6Z5\\u002Bb\\u002BD9LI//Xo4v1JuYz9g366/MGgpPwTZJr/4Co4\\u002BVKnFP9AAw7\\u002BABJ2/HNW3PmvleL8bWOA/kuhAP3QFWb8klY88k4c7P0SpXL\\u002BQcQK9ySPOPhK8J79nv7Q\\u002BMScSv7SvIr9Q3qE/WtGAvwCCNj/HkOW/unecvbWv8L1YeZA\\u002B5\\u002BKhP6QRsMCVZl4/kEHjPEESI74pxBfA1sktPwlgkz/8DTS\\u002BCmt0PnTgHj7RKQnAf/GqP7CiwT548Qw//hbgP6H7jT\\u002Bc\\u002B9G98TaYvwaHor/mnBbAeoYwv6rhpL/bn5lAGjgtP7lsnb61\\u002BlK\\u002B3innvo7BgT94oUjAeU9Rvyb0CEBHle\\u002B/NVJNQJlamb\\u002BiaXW/D6jgP4OSdL8MEta/CbYFP\\u002B0S7z6\\u002BPWy/PFXWvnKuBUCDsq4/k6\\u002B9PWRn5T32LM6/nsAWvvz/Db85PrY/7J2dv0u5D79tW4W/rlO/v5Quhz5lTaC\\u002BaNAkwGhPCD8oaNq/XwcLPyX9qT/Vp68\\u002BPJWnv5my0j8Xl5Y/\"\n  },\n  {\n    \"CategoryId\": 57,\n    \"Name\": \"Skiing/Snowboarding Gear\",\n    \"NameEmbeddingBase64\": \"6OPtv0GBuT/DMF5ARl1qvzLCJT9t6B9AbioCQC88hj8amhrAZJ8Dv97V7r0o2GzAFpg\\u002BQGaOe0AMnAZA9T7FP4D5HED55kJAHgsuP0Ohyz/5HBNACtzkvsC8xj\\u002BBF4u/7ycNQJZgFEC5wcq/XI55v61Jjb\\u002BcIaHAgeRPv\\u002BRt3L5IoCY9fN5Vv68W/r9snrM\\u002B6Kukv/31Cb9KIWHA01xmQH60sj\\u002BcS01AtT1HwGox775EXExAj9cTPghPmL7lkAo/TivpPweqvr4PZYA/L85AwEa9oD462Tm/Z4A1QIOsRUDiLpS\\u002BJOapv3xINj\\u002BFpoU/Nu5XP8CSjz95bPjAPgJSQJLhpT9SC4tAO/juPg1StD/SSsk\\u002BYUpbPwaydD5zZBtAqas4Px3Drz6KS1i\\u002BRgiVvtAcob6hIzg/Cl1GwExGHcAAF2W7GhlwwL8R9T/WfPa\\u002BReQjvzRXAr\\u002Bx4sc\\u002Bc40BwO6uakBWcPo/02fKPs0Kor/W57a/2WgTvuJOlcDg87s/GkENQIixpj57/3S/GDooQRfvob/igIE/P7RgPz8\\u002BlD8aarC/gVG5v3NjID8gjW88r34iwE4g07\\u002BfBCNANmzqPnROjr8CJgs\\u002BsXUDwA7hED8Qsak\\u002BncNqQP\\u002BuL7\\u002BQ6Iy8uj6nwD05bL8ocQFAALMtPwvpMsDZQwrA4BqAQA6hk0BwEQM\\u002BfkWEQHS7MkCKK6s/Bo6BPWaZ9T4r5H4/PsEXvxNujT/OwIa/Xi2KP2Q03D9NEAnA5Nr4vfVCZkDugYvAJf53P0sixr/pcabA\\u002BvHhv71WIr\\u002BjhnI\\u002BZI6mPVL0Sz99F1\\u002B\\u002BVurhvhQeeUATdgjATwEQQJvg4L9I7h3AZhKsPz/rbb\\u002Bl8Y2/pfraPvN2CkCgGsy\\u002BW5mIwKVttj\\u002BNFJU\\u002BAgHEv6dk4L/Cg\\u002BG9/8MXP2RaA8BYWhg/TtOWQJXWmb9MkXTAwNMCv7vIG8B04UE/7rnPP6utbr9wEK28RFNpvtXXvj\\u002BkeLA/jNYEv4g2LcD/cFZAeBUHvxo/C8BCyw3AzTuLP/4VGL\\u002B4/7U/ahU2QF8Y079H7H\\u002B/JzI5QCZq0b8oJQdAixYtv5enrj/FCc\\u002B/NPLaP2g/8Txt9ee/mdEcwH/Qjr4n3rU\\u002BTL\\u002Bkverapb/QqyS\\u002BwUBvv5RVGz/wh9y/gwBXPylfkT\\u002BMuHzARNZGPj69vT8bA7\\u002B/vhewPuNbEMFZjVw/AHn5P2vdgr\\u002BPNGRAHBOZv3xc7z8Ye6m\\u002BvxTFP/43PD/SApZAeDwQwK\\u002BlRr92uZk\\u002BYmQ4v3irWz5GCOA/CrwhwCo/0T8weg89kpvJv58Vf0CcuxrAjt\\u002BJvnCbkL82UL2/cfzrQGpDMECqGoNA8JFewN5VBr65RQzArimkPxpdgcCBl4BAPvQMv7AENUAAlJu\\u002BH63KP6P5sj4\\u002BMSS\\u002BpbGuQOATpD\\u002B6mijAfvIQP0PG57/0FMC/Tr0OwCf0z79BJ0rAyprnP3eKE8DgfzJAZJoiwNfiwj/\\u002BpRXAMbBZwPLzqT3ZS/Y9puatP6\\u002Bj8D9BDIu/BPq8v8Q7C8BTNW1Anny6P\\u002BOZrr8NrsC\\u002BjECNP3Ok5L9Qfw295A4oP3iS3T3oeYc/2tCiP\\u002BATMD1hxs8/yJEWvfT6Kj/TE46/bm7fvuQ1NsBj6EG/hjvfP/QcZUBrqii\\u002BZg9Iv4ooEz\\u002BR17M/V1tLv5Y4GcDJPoY/igCRP0TQB8DH57lAsNsdwB68NsH6a8m/OvrXPyjD479A/XS/W6WMv0RQDz5GTf0/cz5swDxqw76xB6O/\\u002BvIaQJFzZD4hkN0\\u002Bm2qbPmuByD/lQdo/yAIjwEaaFEC\\u002Be06/0EogP53CVUCS0fNAiQC3PcguqD8Y8z4/B0gAv8eq/73MtT0/OYXqP/6mcj\\u002BgvJm/aex9P8yhFT\\u002B81UO/DCukQD8\\u002Bkj/ZYyA/2\\u002BOyP7CKXb8yEFLAD4qVvmqVSb7et8o/SLFfP9Kla8C0dJW/gplUwNYUV7\\u002Bimro/MCexv6ZVO7\\u002BkAFzARAJ0PfMXNz7YWxPASnRYPuGHAcBoPxDAkGAzwGvrCT\\u002BM6xLAnOqlwOMZK8BWLPK\\u002B\"\n  },\n  {\n    \"CategoryId\": 58,\n    \"Name\": \"Biking Accessories\",\n    \"NameEmbeddingBase64\": \"Wg9BvzSByzxDcro/aHGAv0PEmb8O/qc\\u002BMwcOQDVXoT5yl4\\u002B/\\u002BOtVP0tVMb9aSwLAGA\\u002BKP53inz/s2Y295P/kvjaBTEAicxRAdMs0vzw3hT90QL\\u002B/vKU\\u002Bvku7jz/etGI\\u002BPeoWQIqqbz6udJ6/LcrpPjzVdT7GN/6/aEkevrBlYj/MlEa/AHbvPeAZXb/IzCy/Gldsv6L1sD4uO2rAY/sdPiC4LD/goo8/hBcEPltlyj7qpZ4/fCKIP9LVcz/2Ytm/UBGsPyp8EMBaDSxAImM1vyDt3D9PAAS/1YgKvozSwj9dq9q/6JeIP2yCmz\\u002BUKR4\\u002BHQdIPoIAyT8mYDHAayCuP9u8MT/H5BpAQtwjv0RF3T9G8xI/cyiaPw4Snb0jqxo/VowYP64/dT/Ct2o/kNkrv9ds\\u002BD5VarK/D5R4v/4dpL9DANC\\u002Bd0TWvyPrmD/9OvU\\u002B9CfmP/L9HL5VhUW/crSVvyOUcj8arQFA43G\\u002Bv9Nc2b\\u002BIjnk\\u002BJK6Zvpz4McBYWGU/U3M/PwaVCsAvc5S/JlDcQIky4L/mJQY/kYnXP\\u002BlGhT4pTgg/8tAPwIg0mj\\u002BQ0o6/eAXFvy61rD/LS90/XTlPPiT8Q76AAKc7YyiEPsdpCUC8rK2/SI8ePxgLH7\\u002BMwqI/sEERwApABL7cDQw/nNQuPiNHiL/e8iy/7GQnPujzHUAGloy9tP5sP5ERhz\\u002B\\u002BTR9A2fojvwQUpL5sgGU/n322v\\u002ByTsz\\u002BoD3m/BwOZPeyo0j\\u002BT\\u002Bbk\\u002BBPzkPTpNSkCkEBfAmTAzvppVvr70e/8\\u002BoqEvv70jwr7koXc\\u002BMGRaPn0WCL5UsV6/strOPrSteT88iZg/KpaaP5\\u002B6Xz94Mqe/bwPLP6WdGj6oYhw/W/Tzvu3YLD/2RTc\\u002B\\u002Bjx\\u002BwDaoAT\\u002BEZl\\u002B/orFUv/rwib9B6AO/Kl9DvkgtsL8D/5k/fFJVQAXq3D6LswjAuvN2PSXuAcDMWRU\\u002BzpFIPyaCbb9\\u002BkNO\\u002B2b0ZP8QFej\\u002BeJcC/Nct7wIDnw76Qxbw/sj5EQBgDer/kD2w\\u002B\\u002BhGvv6At0D4yN2W/C3DmvQhr7r8\\u002B6Vu/fIEbwMdEu72cfSNAQveev/D0Ibxw5R0/2eHaviUCtz6Eo\\u002By/VVMtwLsvNT/0256\\u002B6FRTP0ZGp78rRwxAf15PP\\u002BIIAD/kIuy9PIUeP1\\u002B1Ez6bM8\\u002B\\u002BNYiAv3pvkr5Zaa2\\u002BSH2OvnLykMAbHmm/JfjUPxZ2E0AG4js/0QYrP4Rulz6A5VA\\u002BhEH0PT5U4L6O9BFAg0M8wKzm1b\\u002BG94q/Dp0lv/op8D9bvKA/Ev2Vv7VZkr/88oS/1Eq3vtY\\u002BJT8EJou/2wLYP2wT978OM2g/BvR9QJNTFT9erba\\u002Bdhl8P0xs8L8r4dU\\u002BdOCsv8xEyL\\u002B0hGo\\u002BcM8lPoAJFbtor2W/GLmyv5Ho475YmIG/Wg8SQD2Nn79sE9y/VrHyvp8dEj\\u002BCM5C\\u002BKJcUP5LWQj/0phG/oHaSv2GS0z7GLe4/1h8RvzKJoD8I0te/2vSWvhbz/j3SIkG/sP0BvSmFhL52tWS/XqBGvwdYrb/8\\u002Bro/voigP2EOYL/BX/\\u002B/U9puP3EVUL80ABm/oIvaP6wTaT/SweG9Gd6JP\\u002Bx/ib1yQVI/nLinPWIWC0CjZey\\u002B\\u002BJaPPMJH57/NaNa9y8AzPzHjJ79OcCY\\u002BYzMWP4Bfnb4/yHY\\u002BRAPwPX33VD\\u002BrlUU\\u002B5NIHP0CLi75YACpACFGtvwfW0sAhcBG\\u002BOMobPdrClr97KbW/H8ACP/zzmz\\u002BlKAtANpAgv24DTz8Oyw8/dMMLQKUTjz\\u002ByMQa/idtNPnZo1T8Zn70/ghbKPnZ7oj90Y4S/SlARv/N42z\\u002BfJ3pAm1yivwgj0D9WTT8/Xpm0v8vSYb4SIei\\u002BTMaMPbxPJb8j7GC\\u002BLf0VP\\u002BW7DT7vMT6\\u002B\\u002BLLpvtmIEr4sVcs/BFcRv8a6Xj\\u002B04Ym9pDi8v5JUF8AXqDc/FJKcP1rqUr\\u002BPkh7ASnEaP1\\u002B6ej9r2Ww/euKrvxQos7/h8uy/8A\\u002BkPbgzeD\\u002BGQRfA8ft0vmQZBD3IepG/\\u002BJiUPpZYkD55/cW/fNHcv\\u002BofCr\\u002BGABU/\"\n  },\n  {\n    \"CategoryId\": 59,\n    \"Name\": \"Kayaking Gear\",\n    \"NameEmbeddingBase64\": \"yR3Sv\\u002BohkL4\\u002BJfA/K6L6vrqytL4fhcU\\u002Bqm26PzqdQL94wuG/lM6jv5h2gD\\u002BoW6q/mmG8PggRuTzmThw/sSbSvoK2zj937AFAFB7bv0AgWz/N\\u002B7o\\u002BlpvvvsbCgb67wei/BY6nvqJCgb8aJQnAIFiqv/xOTb4S\\u002BVzA2BZnv/p5oT\\u002B1B4m/z225vZLGp794hZA/kikPwCDZ3r9ODy\\u002B/tlg/P01gCkDQSdA/\\u002BjKzvxuRUj9o6gq/OMeOvzZdkD5QKY\\u002B/gORiQMWad78CcJg/lJSfv7AVRjyAfpW/IH6qP9XAwz/B9Y2/AyyrP9hlij7NdG2\\u002B8jkPQI7F\\u002Bz82e5/AfCklQDdvYMCotytAPcQcvw7k\\u002Bj/nHuw/jYimvy5Qxj/sRTI/WC//PU4vsD9u6rk/GP7VOz1o/r4hLL\\u002B/4r1OvyQqOT9l\\u002BPo\\u002BWB2FPKMi/z8CQ4u/IL5pv/tpYr7GTtM/jFvFv0StJUDUMu4/6Nokvgwj6T7gfw0/aakxPxmD4L3ZA6Q/sDeOvBq6AsDYvGq/cS8AQbsrkr8cH6k/7iAGPjvVqT7ZJPg\\u002BYPiDv1qXqT5GLd2/rNIjvxYS/754YsE//lcjv5zkhr5BpLQ/RoAQwHP5CkA89KS/ycOYPjgxBMDakgQ/FhISwGfidb8aH7Q/0lr0PuzNT78Skaq\\u002B67gxQB9TxT88nVo9dtQyP0wfJj/wY2S86JABwFUhRr8AAse/ksQov2xHUL/EH2y/KbmSvojRZD9IKPe/msyWvhGmWECmjW/AAgtrP4wjOD/vPoG/SIPqv/VvBr8iCbm/pcQOv/YN/76D2mo/Aoedvc8tKEByi/Q\\u002B0JD1P6S8Zz/GYUjALAkfP7n6Wr/NHxe/gqGFvQwZMkD8aYS/qA9lwCXqcD/IZkQ9/gQfPzBGnr9ePZY\\u002BDgICPyX9dr9o\\u002BiE/Y4V0QGnXqT8IRQi\\u002B7mqZPvhlz7\\u002BiWy0\\u002BglCfP3OuKL/GlRy/UKw7vZCmSz\\u002BWBr2\\u002BpByhv0iHcL8UZBk/686KP6RrTT8UEiHAeTgdP2flXr7yjYE/gkPQv3RPUb8iCIk\\u002BsRy\\u002BPzKbAsB2Dw8/1f/APlYMcz4opN4\\u002B2vQcP0w8EEAwbrS/qj4FwDzyB8B25jRAwBWQvtgMXz2r\\u002Bh4/S4mPv3yJmb6yLHk/JfxBP0Qj\\u002BD/CQlvAxJeBPLJAVz\\u002B2MtC/9u5LP2ZY7MAsj12/htygP86FCj9PTCxAd1UVQJCXgz\\u002BN3jw/MNeQveTXLT8UNyhAaMgQwIYmWr7w3fU\\u002Bilm2P3j0NECig2q/Uof4vxZtqj8z/ko\\u002BAAQKutT0MD90G\\u002Bu/qIH9vUGmyr\\u002BNyqe/01GeQOJK0L/kw4NAVxgBwHnVDMAMz7A/8s/wPuggLsA/nH8/7C2lPmFAPL28cCu/MF3HvtcVy79hbRg/emdoQCBFVj6mrj3AIfGOPzoGxb9ywPM9d4PHPph0R79ubkS\\u002B5AcCPzCprT4bBB9AuDfVvbxTPT\\u002BpgI\\u002B/fcg8vwq8lb6IHFK/7pUHv6T/kT7DMqK/zvVIP\\u002BiFG8C/BgtAJDk9P/w9w7/ttWC\\u002BhFWTPyvxmsCftQHAUAedPBLuEz/a4kg\\u002BMt01PqDQUDyMtTq\\u002BhJr5v/fksT8PtjI/\\u002BrIsPzyyh79ojCY/SGNTPzJR1z\\u002BHVM0\\u002BhlSZv7Aqvz/F9Je\\u002BPPdnP\\u002BYIQb\\u002B2qeA/G3zxPQRfhr/xrKdAiYVxv8ep\\u002BsDGvvg9ROrCPm5KXMDEaEC/u22BP35c4z912\\u002Bs/plnUv2\\u002B8mz8Acq85x5UGQKritb8Wo8k\\u002BUyqVPwrMXT8gfeG8GRMuwDsCyD/9fJ6/\\u002BgjiPpeFikBupZJAOyrgPhscHD\\u002BjiJ4/movqPitplD98o3o/O0uDP9rDoz7XtBk\\u002B3Kl0P4QwGL0sHx8/uhcIQJ4/Xj7ljCM/5kVBP6xozL8KRD8/TaQov8WMrL4aUec/J/SNP/yfi7/OLgo/4MFDwDJxfz9jcIE\\u002BZBWlvxamJD2o\\u002B/e\\u002BOmRwv0EXnD\\u002B9goo/gK1zvsx04r6g3uc\\u002BqDmxv2Ajlj81/7HA0E0OwGdBor\\u002BsGVO/\"\n  },\n  {\n    \"CategoryId\": 6,\n    \"Name\": \"Water Filtration\",\n    \"NameEmbeddingBase64\": \"lEz3vRUTFsAKogdAEFsNv/9bfD7RU9i/ToA2QJVyFEC2zme/HoXmvaqjVD/ZQpLAl5SZP5WQDsAfJT8/Zva1P\\u002Bjt6D\\u002BuxjdAFCmCwGql7z\\u002BGzZJAoisAP0EpJsBwCa\\u002B/dJ/mvgAFR70tZwFAFy6PvyDaKb92pqjAtqBqvxxYTz7BPJM\\u002BXpCrPnD6DL6tQMI/PO9BP7J3ij48Yum/9EFuvmFsyz7826g/7F/0v7qd/T5I6cm/67aOv2W/dj/WNq6\\u002BQ5GFP0Qex7/fUJm\\u002BGJKcvn9Ax7/8hDFAXqiTP6C96jyi10U/e8/PP18Nsj8aYaW/TWsgP2qNjz/cZM7Aylx4QJEuxj9Aaec/gDSHv0L6ZD/Ih\\u002Bc/MOMYQJFnN78i\\u002BAJAjdcJQIQjiT/dh4o/WL5Tv9vudL\\u002BGRJI/JOBZv6YzzT/cKsw/RUnSv0r01b5hj9u/PqnXv6tZhj5aAWs/MGd8v7iXiz6sZZg/Y2chvwBmLb\\u002Bu74g/SG4oQML7VsC1KQM/4ziUPsaqxL6\\u002BChVAi\\u002B/xQHuXJcBHe2s/1Fj\\u002BP33N8r\\u002Bpv90/pn25vxtDe7\\u002BAyE\\u002B/LJRPPwf0gz82IOK9WzzWv\\u002BvlA0Ay3hDAdC\\u002BKv0f5H0BA8Mk6Xvl8v5ID2b94WSU/HX3cv67tfr4WxBZAHWeMP6aHU0BhSsY/uC4XQMeAO0DUMAXAU7NCQLAFh75D0Zq\\u002B97tAv\\u002BZwmz4oiYo\\u002BE0FsP6QGmT/UauO/iiqmv\\u002BF4or6\\u002BBH3AboLhv\\u002Bywxb3j6nvAHg7ePVXaE0DQx0O/DvUMwH4KWb\\u002BinivAlBWIvwnEVkBSbTU/IPTbvyb59j8K/pE/lw6iP/MUfz9GLxy/ikNdPxsApb/QRru/UEAdwFjvlkA0WbI9esK0vj9oJD\\u002B\\u002Bz/u/O173vwW2CkBADYs9GODHvk1chz96E7e\\u002BF51WPyv/\\u002Br3SdGS/QB55P/SWgD8Jz5a/TfQEP6MYrj/zt4M/rnAPvtCG4j93ARHA60OlPlZ6uL6bB76/pH8dQDR9eMD4IRO\\u002BOLEbP8MfXb8AMQ86Cjg6PyMJMD\\u002BQDgM/B5T2v\\u002BpnEcDgV\\u002B8\\u002BcFtmPlDz/L9Yjwo/7jiov6SG5z9z4UtAKjmFPVwCg74TpwZA/sZkvwpEHD\\u002Bssp0\\u002BgSCmv6/sAD\\u002B\\u002BaS4/ftkJQARGfj9jAdW\\u002BiEUdwPaA2D8PpGnAhFULwIz198B7m60\\u002BGZ7iPSpV3b/a04RA6p9JwEhDsTwv3Nq/EKEXwNN6Z0Crq9w/2HlxvmZvfz444q0\\u002BrpKBPwonTj7lEjJAIBnivRRxCb96Zka/iJrBPgxogT77djlAPraVP5Qhnz6pq8a/ljCNQFB9rz/DIJc/vTQSQIuunb/Eu7E/3QN5PwKSt79uRwDAayLWPk1esr8z0HI/o6LzPucDCcC60rg/vgIfQJ2nCL99Te2/FGF3PnK/nL\\u002BQU1E7PTsOQGz7K8C9WyfAFcyAP2XSXr/0TxBA0wjFv0ZV7z9tGqa9MgUIwLSNJz/82kHA3D4SwPZdUz\\u002B2ZBS/OkoqQCV2FsBSmsI\\u002BTNIuP3T/Tr/v92k/m\\u002ByvvrraCr3b8a6/32ZSP2hmj78ysqM/OxYTvyYUTUAUxmK\\u002BanYhwIqe0z/k0T7A9px\\u002BQGjadL\\u002Bxo\\u002BU\\u002BuMjRPnxHkj3Nu74/1MMDwKJXVb7aKw8/J6SzvhAKCr4BTbg\\u002BTu73v0wMe7\\u002BXAwdAyG\\u002Bnv3zWD8Elwy3AnWxUQIQV17/q\\u002BQDAZMufPqyj4j\\u002B/UhdAnDZhv2cYLEDsI/S/3An3P4\\u002BdBMB\\u002BgDM/ZYLcPqNwRr65c5u/Ngm8Pi7M6z8pCh6/SOuvP8gwCj\\u002BwCq5AoDxUwOB0BD98oBhAMb\\u002BfPjC0fr90mbO/EYNbvpoiZUArdtk/BKqRQAKQXr8PPJm\\u002BFyfQv3kikT1KYV4/YiJZvh1ORsB7NJ2\\u002B3gpxvRQNL8CMk7G/RAoxPwFugr\\u002BfzTs/YFdXwM1ftD9jb\\u002BQ/sbGSvwP/Wz8\\u002BdPU/VsKzv37/PT/M1Iu/lSLkv/SlBcC/jam/Gp\\u002BmvZi1/D5v8APAVqXEvwzAdj7cMDI/\"\n  },\n  {\n    \"CategoryId\": 60,\n    \"Name\": \"Outdoor Electronics\",\n    \"NameEmbeddingBase64\": \"vERQvekITz\\u002BdKRpAQLipvz/Bmj8umbO\\u002BIZdMP02Qqz7\\u002BfL\\u002B9sxqFvtN9QD9JdNy\\u002BWPqdPwvUdD76cbI/fwslv\\u002BBezD/4BZI\\u002BY/HbP\\u002Bthrj827Xc\\u002BiEIPv\\u002BJmDb5J3KK/KZITvzfHZj4unA2\\u002BwkjfPpXlor9nNCjAdFRjvxGmrr0XAhW/THeIP7Yl6r\\u002BAL9O/bE\\u002BcPksKh78PMuK/HTTZPp9k2r/PERi/AiZNPorURL8GSMi/sM7Kv2SGVD9ZKTHA9k6YP7oWkb9MAnk/f7cqP7uheb69YCO9vUinvWXbDEAGFGc/kQb/P36byT5Mkam/shCdP8OdIUDf94PAttVLPxzqJT8A7aQ/akxVPkIspD5ZjM\\u002B9bUqQvzjRqT24/1k/GtMyPho4sT6FsiI/0QS\\u002Bvo0v6r/1/8Q9PLzxv/dWCb/5GXY/uDmav1jMgr/DB2o/Uql9vmGzjz\\u002BM8uG8TkgDvxoLpz\\u002BONRlAK3wvv3ELlz48TJq/zQNav5ax6L8ZlKG/78KMP69p279qe1s9GgjkQMok4b8vREc/A6YpPwyoKD7J1Ie/fEG/v11TkL/SK6S\\u002BiHHxv57xC790bso/X/wbvyY0vL/RXkk/zkARvwzw9D6X2na/3CuAP33krL7vEOS\\u002BnxkFwEdpI75m3Fc/jFB0Pu97cz\\u002Bnmay/\\u002BGyHP4oHP0CFXnI\\u002BXsc\\u002BQFAuwTvGYoC/24ehPgzdDz/y1zI/mYggP4/HHD\\u002BSNcA/O\\u002BO2P60hiD716Ce/qjiVPnGkBEAc6RLAE0rjPwHKrr9uS6C\\u002BSW9Pv5xEZz2EmJK/7LTnPp5ioD9cQzlAlcZLv9xOhj9YRu0/rqafvrQpkD0KvQm/dsyRP0sIUb7kpy4/MxeKPxZUNECWeSQ\\u002Bi/t6wDPtVL69SCG/AKAtPxF2b7/QvHO/vomwPoIznD/aLxc/6C2KPzkLDD9hxRzAbxsXvpYJHMAX4ky\\u002BgHowu4LZX768D4Y\\u002BAPQFvaAAKDxIF\\u002Bo90m7uv/I/cr8cpUC/yrtAQLnyAsCu3/K/EOdHv6IorT\\u002BU9xI/zBvBP/AzAcD49aM8kRMLQJrpmr9JvQ9ALIMPwAgaNLxH/W0/MhaMP3FkMb\\u002BkCb0/LDCav3sqEb76E7M/XPvIP8SehL79xwRA5xr7v\\u002BOEZr\\u002BKiIa/rBW\\u002BvUj8mL4g4pM/ulh8Pxr/2740zwDAoh6cvnyrqcC00BLAW\\u002B\\u002BgP4siXz/zlWW\\u002BWJdqv7anUD0ojH\\u002B\\u002BYkfvPNbPMT\\u002BEkxNAkPELwLD6qj8tr0A/cX8uv/seI0CMdag/blGDvzGY3r5GhjQ\\u002BJ/boPrWkxD9msxg/B7PrPh/Ywz9ziQm//QiNQCAfDL3a0PU/Ja55vzw7x738vxg/lqSdPtxlsr8oBC\\u002B\\u002BMNXWP23Sfr/qy1k/HM7pv8YxC7/EpvC9S/oEQM9rHz/X0am\\u002BEveKviQysb9iImy\\u002BGXWyv8wSYD/onRLAADWQPuIKaL5VXOI/QSSKvgw37z9eFRe/S\\u002BkYv/ie2z9lKBK96bwgv/oQmT\\u002B0DAe/6KOuvKvDtr8ML\\u002Bs/pkE2PuyzQ79RlBe\\u002BFtKiP9WRID9eiyG\\u002BpBfPP0NnFr8nVc2\\u002BQBoqP/2LBsAE6dM/CMjYO2lWuj\\u002BJ8s2/EglnP9E9jT7NyD4/FvI/P/rDOb7LlIA\\u002BZA8Tv0sc777\\u002BEfC/oxY5v3dX6b4YK0e/bI8cvx5qxL/11gpAvOqlPsbEzMDmAJu/lmUvPkDibr9MAdC/49uyPwBtHT/FQRpAZ83Rv/Zeuj/3LLW/6drbPrIlPr964wY/145IP1o8ZT9oOWk\\u002BMMFQv65IGj8k\\u002BUC\\u002B/tocQHCGE0CVskhAu6gmv/aIND/SJQFANycBvxYK8b7MVi89yZijv1R0Oj8ov5q/N4G1P0TjmL3IDWA/lcKDPoruUb96Vxc9hBUJPkJANL8AtWi/TFBjP0PRVb9sx888jCicPvP3N7/t2L6\\u002BzJeCvyVNTr4Lu3A/eNS/vqqA0r\\u002BEoLO/XWpNv0CS1r9VpFI/akHBv4iI\\u002Bz71kwm/xDIxvzcAiz/N8g7A9\\u002BDZvlHhpL9IOw5A\"\n  },\n  {\n    \"CategoryId\": 61,\n    \"Name\": \"Trail Cameras\",\n    \"NameEmbeddingBase64\": \"dv7bviY1Fr8nLiw/cLkOv1b6yz\\u002BIyMQ/NPQGPlTMET2\\u002Bi6S/OdKMP/JtzT6\\u002Bk8K/PMKUPuc68T9haoA\\u002B9\\u002BfSPtLV1j/NQpi\\u002BkZ\\u002BXvrzdKEDRxrO\\u002BLHNxv\\u002BWyoT8W8jy/9X2ov5gyhLzGAXs/tmxKv60/Rr/2QdS/DdwpPzDxhr8G/LE\\u002BmpqdvVOP2j7pRBM/h5KDv56Ncr7jLK2/rA81PZqWLT\\u002B\\u002Basw/m6FvP9umtr982ps\\u002BksrCvzFfGT/INy/AJG41vvhKWb/BVYw\\u002B9f0Tv6VBhz8NF7m/bmvyvyR19r3orVq\\u002BDPzoPwiA8D2wQb48kjG3PxA8nz5uY5TAIZI7P0uv\\u002BL1QNbo/4YrVPrJbr74CY44\\u002BH\\u002ByBvxYJg78/oss/WE3hvrylzb3\\u002BBie/TIxqPYLRpz7iPDY/BAcdwALD478yV5y99tilv5yH6D\\u002Bj2HQ/0sSWP6Vz1L1d\\u002Bhs/KB8QwILj7z\\u002BC2KA/T6x9PvmCmL8Z9/G/UUaCP4YOJsAcS5\\u002B/EJZcuzLUxj4KQLc/F7PQQOd4u78w6AVA2nD4P5IPJz6qmWE/GZrdvxaCTr/eBze/fcaYv1SLnD/cBABAxEeIv6qoqD9o2xS92Duuv3WxsD7Q8X\\u002B\\u002BUajjP112X78wIQ5Acl2Zv0Iy2L/zNFQ/5pKtvtzMQ784uKC/7izmP97dCkC2HM8/9r/tPyZt\\u002BT75fcW\\u002BVFxJvxLmuj4o3Lm\\u002BRJILP84DbD//zrq\\u002BzEGxP5P7w768maG/AbdRvkazHED2m7i/jdGtPp9kmT\\u002BRWQS/IFsGPGkEJT\\u002BrgQHArN0tP5i7wj3cyIQ/a2QXv9Td6z7cx1s/pE15P4Hnd7/hRDO/q9PePwfhl74Qvba/qjxBPRyTPj\\u002BSTZE/7yQ1wEcNfj9WjAjACsMhv9RIZD0OMIK\\u002BwUDAv4FQcT\\u002B5\\u002BKc\\u002Bg/ICP2Rw1j4du1vAnDLwPWmt6L\\u002BHLCm\\u002BoIbOvjnk3L8b\\u002Bfe\\u002BmbnLvleHkD\\u002BiFS6/VDL/vooPTr8K8OM\\u002B5tY8QPuGn74hf1S/f7eEP3pWhb9ar8K\\u002BmxCFP704nL/y4gY/xCTEvzN1ub/Thao/DgR5v6o\\u002BCj8nEta\\u002BVldWPzsYeL9/QuO/K967vq6Zwr\\u002BMxsM/EozGP8hBgry31w0/KABcvgfhy7\\u002BG5hbAwNuXP\\u002BY/Nj9vYMu/sFmDPx6msL9/VHC//lL3vcLywMCcb\\u002BK9UFjpvcNQH0CWWkg\\u002BvZXOvwQ1Dz\\u002Bg5/w/rOCKvmjDQj8QxyVAzsq3v6SYjj2jKN4\\u002BPS\\u002BZPxcd6z8GwYw\\u002BwooYP4zeg7\\u002B4KQi/P2Jevu0yA0A0mO\\u002B93pMwwA49Rz/fiSK/5rGAQNVNZj9ow1s/OS0GP9wsdL7ObAk/hLmtv\\u002Bjzq79as\\u002BS\\u002B19SOv9kzFT/0/V0/1wtUP\\u002BhM6r\\u002Byi3k/YomzP1\\u002BHtT/lCTu/g7IjviL8DT9dUoW//g6qPuCxy73s3yrAvNasPsw67j6apaE/yM1Jv7Ok5T/2ie\\u002B\\u002B9phdv\\u002Bjfbj/aRKS\\u002BY8OuP08dr71o56e/WvLGPWf3jb946zxAv8rEPanugb/CNCa/l9XZP6QGSj4ejCU\\u002BkI83QGa7Wr/Xo6C\\u002BApIsQJjxOT4cfr8/mHF2v/upmb\\u002BV/hPA73VhP5g3mL\\u002BSFdq/\\u002BLeXP7bsFj/\\u002Bt\\u002BQ/LSBDP2Idyr/0oBm/0qtvPuiVbz99l4\\u002B/CFx6veTvBsC/SzxAyGDwPjhFpsDMmOi/LGgLPxhXF8BGYu6\\u002B7iyRPjjjIkA8Ocg/pyiQPzNtFT9Cwzq/JgCnPwh/iT4725W/r6\\u002BlvW47UT92UXY/\\u002BhhdP0WeQUAM3XG/t4MjvyEhjD9OBMw/Ro5Tvwa4Db/\\u002BT88/p8iiv2\\u002BHL783aoo/HKSSv1YSGD\\u002Bu9RzAhHbSP1AFmj2QiR8/Kg8PQG7kxL26X0E/jOBOPUPIlD7cAgG9gF44vmcsgj\\u002Bo3G6/0tGIP0BgbL2KG48\\u002BMD6HP9oPu75R2Sw/HvrDPvEFmr\\u002BWfq\\u002B/ZvsUP0D5aj\\u002BbKQ0/u3sNv4SCnj\\u002Btet2/5qKFPkzEfj67arO/C2dYvzUCAcAUpK6/\"\n  },\n  {\n    \"CategoryId\": 62,\n    \"Name\": \"Off-grid Surgery Kits\",\n    \"NameEmbeddingBase64\": \"RHjTvsLomUCusHdA/Dirv0bHVj/qsB1AgFo4OyXfSEBVbxTAHVndvY6BrT7SBBvAzKC5PAzfIz\\u002BO0l\\u002B/g/t/vlCuM75QqgpALK8HwB\\u002Bgaz4IXJ8/TPtWwFxMUcAifZu/6dQoQHHOyT840gPASvVqvyRFAcDwENXAv4GCv2T2J79qStA\\u002Bu\\u002BuTv\\u002BWTaj/25Y4/k2Bov1Oq9r/4NIPAEV8ovrIWjz9EgpC8aMkNwIIKU78y10U/ny4GwLp0Z794xqW/e0UeQBIDsT4W/sA/iIASvUPutD8eeKc/VuT\\u002BP6UW6j66b7E9q5WTv8wiFT/wHyE/dyWHPhtP5D\\u002ByF/HAyttiQJoMZD8ntaG/QKHoPJzHDcCYCs5AdnI3vtDctL8OqQi/1GP4PyO6iT8ozBg9WoMbP/lVM8BYVai\\u002BXW2jv3j5YL9gqvk/LFRcwJq6Hj/WnRW/trJAv58qt7\\u002BFPJI/xj9Fv24R0D5CESu/9tkPwEF/jT\\u002B4Qdc/MPh5Pci\\u002BYcBWQgbAsQiQPTPmij\\u002BcOl2\\u002B6f81QZXfPcA/3pm/8U0TQK91/D/2ZRi\\u002B8vyCwDOXNr/hSDU/3FDPPi0aBr94Wfc/iowQQOAM9L7Sx4s/3MuGvhEipj6bnApA03cRQA0PBT/W3n8/ki09wM261j9TNos/e30fwDKlOb/weVu\\u002BhJz1P9WhPUD67XE/87CaPkBpG0C7x\\u002By/ixYBQH2Njr9uQpM/oDjUOnNmC0BCaf\\u002B\\u002BJf37vg4NZ7/ENeY/yhXIvh6DvD/qvJjAyBkSQNaU5D\\u002BoZlzAgioyPXRHrr6AWAfAgADbPv1kOECgaYU/ieBRv2hrCj\\u002BAcx4/6tNEP4iCHL8H8BLAxrb3PyA9XTxFYDHA1lBKvyrylUBFAag/2GmdwKvFUj5y5nA/Gpkuv54BKz6PRjE/FOMCP1TfUD9DlpG/JfbuPzuDDMAy\\u002Bqq/BWwHv3cJIr94VcI\\u002BrbjmPsOgPL\\u002BP\\u002B8s/yOXeP5ZHsL6kuoS/dg4CwEGCpD7448k/WMZqPxprCcAlpZa/HGAlQMwaIj8F6fw/3rVGv5tvSsAglynABjgoP5tkTsCqtExA6SzBv3T9ub3Fars/CeH9vuAg8j8eFXm/yGIyvmIyEEDNv51AUhenvx665D4FTHBAS0u6vqyoJcAw6BC/5icZvyVc4z4I/56//4ZBPzod0z/wXPG/W2Chv/ooNMEwAaw/OMygv9rYcr8iwbC/1q8awHNGAkAMxgnAeJ0cvMSe7D92GLBAVK0fvx55YD/8kJc/RW0IwOmk5T9X7kdAOfMOwMQ63L/Mdea/\\u002BScsP9MsmkDg9FM8QjsEwFAXUT8qKh\\u002B/GrL3QGe\\u002Bzz8wfZxAiruov5J4Dz8PusU/Dy2UP8RhP8Bc/ow\\u002BJYEHQA4m5T4nwizAlAWKP2C78j8aVSC/BEDNP8joMb5qvk3AKNopQPryyr/usgfAYq\\u002BBvm1AAsCJ7u2/uB4/PmeyPsCb0XE/5J0ovxQl3j\\u002BxS0S\\u002BrvQdwF77Oz8QBNS/bIIiwEBnZr6WBlK\\u002BMJicvYAX/r7mQoo/Ocb8Pimw\\u002BD6HOGw/jO63P5ADrr/nac2/Q\\u002BWEQJNNDT\\u002B26QJAG6mMPRNstr2\\u002BMipA0y/JPwTdZj60CjDA6PYCQOEY7L4kK0U94ym9P4pNkj86be8\\u002By1MIwJBOAz9ay36/XT3Uv6QiyD/FePY/OIMgwE/GpL59YalAcQGBPmk8EsENJhw/1cCcvhxXMT0iO5K/Cp/iPtyk3r/1QuQ/C/mrP6roKT\\u002Br2HjANeARQNHu2T8FSxy/ckTiPt65mD\\u002BFcLdADzXsv2elTEBi4g3AIOn1PyCz4r8W28pAkXDsP6uxob/LufM\\u002BVn6CvzjTPb9/D4M/AAMBP48TNUADIYy\\u002Bza7Zv7B4b74GqExAXrBkP4Jk\\u002Br8F3mM/b9xoP3Hfwb83lYbAkGjAPxDSVb9HqgO/Z25GQPC/kMARpEnAdHRzwKxWdD582hq9mr/KP4/3EkBMLrq/3JlgP1zDD7/\\u002BvTw/bBgxP2jHC8BFU\\u002BY/8Ieav1/aUr99DkrAlktPv/569j9g0Ni/\"\n  },\n  {\n    \"CategoryId\": 63,\n    \"Name\": \"Aerial Drones\",\n    \"NameEmbeddingBase64\": \"RH15Pe3eCL8c3Eu\\u002BEXxmv0Bvzz/kCQ9AoCo2P1yL8j7jGZE9dou1P2PtaD8y7Zy/MiF1Pmbe8j8kfc4/2NmnP907ED5knwo/vLCdvS5MzT8UjGw/dOwzP0ozwz9YhTE/eronv9f5CEDrY7\\u002B/RqWdviY52D6oSSnAiO7nvKnxfr\\u002BtjMo\\u002B/ZU8PlT27r7ESGI//D4gvJr46z4usum\\u002B1A\\u002BAPXdhBT9q5ZS/b6OTv2BeFsBY2/I8OPyMv0pj4r0uREe/I8jDPhP6vb9FBUu/n1gYwE7D5j0Arjy/\\u002BIwfP0CYq7631Z4\\u002B/BWuP7hlurw2uRHAiI9aPtGckT9M2kvAPVNUvk/VtL7Ja2Y/pmUAPxX3uL9E3os/w7QZv\\u002BjtvjyRRVQ/LIOJvVZ/C782tnk/yGnBP2Q6qb\\u002B27x\\u002B/7Lg/PacL4r\\u002BhnnY/mPTBvtyEj78wxBs/ElifvfBotzxvP/k\\u002BovUkvwtuN0BGezRAv2huvwwTnj7Hk9i/NsgivvD4JcAGGY6\\u002Bbn9OP3qdKsBjniXAVJPsQB7QBr8fVoW\\u002BLhz/PmDBu78ssLi/k59zv\\u002BkvJb/woI\\u002B/Zl2Uv6dwCj8mc7a\\u002ByB7iPoxjoj8zZuA/iFrVvyxMyj7GkXA930AaQFxQi78a2cy/MIu\\u002Bv3Krgj7eMzlAmMBMP95LnT\\u002BWpO2/oFqaP3BlPEDM/My\\u002BYgIoQG5BB0CU7h\\u002B\\u002BBfuIP3fhzL/Oe7Y/jmUAPkZY2j987Nm\\u002BgfQbv6J0AUDgEHC\\u002B9YPKvlE85D9QnaC/PnJ1v4pCAr9eOKa/NKjkPjjvqz\\u002B0dyC/HNMRvtS6bj80Gro/RowjPxMmmz8Pq9o\\u002BzgD3P0\\u002BCVUCO\\u002BNG\\u002BaOTlP6wvBL5p1K2/Am4iv1DLUUA4eEg/\\u002BtgqwJZzMj7qGbu9x1jMvn1cN0BS8ea\\u002BaByevyzZnD8diCW/LPWGPz6Qq7/hqBjAPmAnP5vgh7/o05895BmUv8DnQcD/Dmw/uX\\u002BoP33NAUCLYoM\\u002BUHfcv34CDL9wJf28V2XSvwq4f8DVbjk/PK\\u002BbvpyIQT3gd3w9WnjEPnkX7L9E\\u002BdA9kHDnPzSLlr\\u002B4wQhAuu4UP/ozFj/K5PE/DErLPf9Her8ESco9EfKOPSiY0L8mcp0/woZHPlh7b78i3PI/ToUEwMLqt7/YqXo\\u002BzmanPmDFWDzmcw7AjsIIPk6ilL\\u002BuWN6/uK1TPyAXo8BSUI2/qBzBvuy\\u002BDD4ohcO\\u002ByBDMvxzGWD641gBAAEyVP81bsj7erVNAFhv0v0CGYb5wEY49UIKXvII2G0ClZpi/4Z0cPiQxPb86CBI/ZHq2vjhfSz91P5w\\u002BJAGOvXTLuLxmgAnANM\\u002BTQKrtkj4qFe0/yHcyQHCj0z427Kq/U8MmP0pLfr9C9mA/pvuVP/TXCEDcm6w93clyv9KLkb2AD8S\\u002BsBEFQFQP4T/oMC/A\\u002BHzivptJqb9iCqO/ZkWMPs02ez92HQLAXv6mv0dSsj612Ha/j3k7wBiaST\\u002BM37m\\u002BO9KUv6WQ9T4QTQi/pmBNP8iilzzIzf4\\u002BggMNv\\u002BZ1or8E4ltAhdO3v1Zjhb8kWcK\\u002BSgPGPT54B74A6J0/i8xVQFfKKD\\u002BUq34/kGAdQNl3pL\\u002BXOy5AoJW6Pm4RjT8iQVW/LAnzvxinAL\\u002Bq9WS\\u002BatvPP9zKSr98d\\u002BK//sNpvkmh2r99ami\\u002BqsHZvzgOL7\\u002BO3DK\\u002BPlmrv7qlLT\\u002Bn0StAI0HcPtPLusDccD2/7sPGP3aPf74MgR7A5MIKP/VLKkCZJoA/ZSCsvz3wBT\\u002BTytW/Jpj9P8DnGLu\\u002BhJa/CBakP7ILyD\\u002BKlA8/aW9iv0KXVj4bpwfAp7URQAm1VL\\u002BqG35AuH0OwPC0mr6Woh2//lADwPU9Yb\\u002BNiXe/KPgHvxT7pT87xMe/nlwDQLZ/qL\\u002BsjmA/9BexP0okYr4MyXi/ye62v0Or4b62J/i/dn84P0QJDkAGehi\\u002BJKAQv6bmEz8wk5C\\u002B/vgLPrDvrr\\u002B98TU/18MkPqocH76eHOG/FEM4P3jAgj5hXAxA048hwBS48b6EZ6C//OEMP1QkWz/GNRi/JSlVP1tTm78yAOo/\"\n  },\n  {\n    \"CategoryId\": 64,\n    \"Name\": \"High-Tech Watersports Gear\",\n    \"NameEmbeddingBase64\": \"Ez4RwGRJBUAr3Q1AcnCBwBpMSz6kB0XAFAdDQEwlYUC6KxLATqn7v4asKb67soHAYKScP/XHYr/znhBAoWJdP6RrSUDiSN0\\u002B2sJsvqqhXECtgUlAWPplvpu1mb83SCvAWgt0vfZTBMBR8ea/QO1ZPgDiFcDpitLAYAYUwJzXTD8ptYU/DzOeP68qQb9\\u002B5sW\\u002BKCKnPhy97b/kx6O/aEuSvoiaYr9Fu0tA7V\\u002BAwOWUoD/UE/S9FFQcwINVfj8mpAHARWGSQBupgMBcwKo/PXUmPl4uTT0U7AnAj/z4Pr2e\\u002BD/Okww/5n3xP5U5FkBXt2a\\u002Bf1qxQLzF2D9C6w3BsN\\u002BUQETqfj9xnF9Aid2fv7ztN0CftvA/SGciwKjBV71554c/jF1SP8wfST\\u002BIIyxAm5n9P/\\u002BvKECxbay/mkyiv5hx1b/oRH1A50OlwCyEWj5W5Mi//IdawOFQ6L5/qYs\\u002BOq5DvoB3Vz93nZ6/KAmGwB3HGMCSirM\\u002BqOdgv657QMBoJw2/jakNPnqyqr8UnZA/AsEfQdwTV8AuaIm/cTkkQJisHT0L1ihAVk7Zv8rw5j523D8/UJ9Vv2BmET2H62Q/0nllvtvzEL\\u002BmD3U/ygEQwHpXFUA4IO\\u002B/drDKPytjJMAnSa2/ylqEwEo//L7SHihAZB43v7Lswr8I2t2\\u002BaxeXQAo1eEA7KjbAh2QEQM60lL8UYeI/34rKv2Eno77ckrC9dnR3v2jBH7\\u002BXjgvAhcNxvx1XskA8GZ7ASA4pvj5jY0BobNvAjJCFPrMwIT5tuyDA3UQlv1kVoD8syy7ArkSbv5TtRj8cfkk/OBtmvqAtiT8NfZA/3HF5QG5V3z9QclTAoudaQBFhLb5WKKa\\u002BbkSGvWrtpEBtHYU/TAWlwCsllz\\u002BPF8\\u002B\\u002BWOHEv9DQiLyF\\u002BG7AuMGTP5PVhT9bEAdA5Hk4QJDjLr5W\\u002B3bAT82lP6s0t7\\u002BywhRAsxx1v0MKyD62Pr2/fl2Hv54zU0CgOeW\\u002BAJyBv32vGcB8Ndy\\u002BPUQNQHjHmb862DW\\u002Bpe0TQMhznz8y66JAblOsP96OC8BJJn8/ULEMQE4BisDmCBo/JJn\\u002Bv/FFL77GSI8/l7UXP5glRkCSJvI/ClkqPtKyqb\\u002BRfbc/amBlP/nzC8AGHjpALkyvPTYNCcCTrkrApF/oP03/O0Bw02DAfzOuP73L4z8KK6q/Fnr0v1RwK8HWCp\\u002B/iyP6Ps4NIL9D5zxAfRDsP2PL3T/ZD5M/76YhQDIR7z/zwLdArvNUv33y/r3tAg3AaEmYv\\u002BBQsD/Oyvk/vGCOPMMwUr\\u002BaVxc/600ov6HohkBWu4vAQzpMP3FCkT\\u002B8Ukw\\u002Bj2TNQLLHKD8Absw/enlsP2oKLsBr920/bRcmQFolhcCIk4c\\u002Bktv\\u002BP\\u002Btmf0Busr8/mmB7P3x0KcAZSJ6//dQFQIEm4b8BLb3A54iiPyVgIMAaMbu\\u002BWpyAPfaxWMAVNITAP3vpP4inEsBk5H29ItQGwP3Osz/s/Nu/PjZKwN7ZAL8VoLe/\\u002BHwuwC4Dyj/uuZY\\u002BSqa8v2g2AL9srQ9AnYqGv7xggr62plA/qG5cP4PbnsA4SJC/TrqJP4X4oD/5TJpAqjUPQBJA0T7oVkZAkiwUwDZHjUDxj46\\u002BZOc\\u002BQHQ1BL/bh2BAtp6iPwVHOUCR704/hXuCvwKzQ74AsA\\u002B76j4TP26Cjz/M4Nw/UAAMv4n8Q8ADHrhAZ4RNvkPvU8G2dQDAhgVYP\\u002B5UicChBU7AS6uPv1/AKUBgYDhACxeWPj0BnUBtZS3A9247QALCh76AZLi\\u002BkMEAvfDXAUCO6BJAsf9MwC6AH0D1lj8/gJ3tup6aWkDwF/ZAYRosv4jbDEASdRhAADqzv5O/Qj\\u002BIvLs/kJDAvbEgAEBtz4g/gqJjQICTm7/Azoa75LQEQG2Ndz75uCK/RV6nPrNRvr82kcw9YQztv1uHTMA0NIC\\u002BKNzZP/oTJMBaiy\\u002B/BM9OwKKAEkAYG4O\\u002BC4y/v8bbkj/Agtk/szO/vxKjLL8KzEm\\u002BSBMmvbhA779mD08\\u002BY10EwEDJeT1Cp6XAS9ZewF2blj8Wi589\"\n  },\n  {\n    \"CategoryId\": 65,\n    \"Name\": \"Climbing Harnesses\",\n    \"NameEmbeddingBase64\": \"elwPwDGYTT4gnyVAUfcEPyC4tb\\u002Bmrg9Ait1qP/CCsT/M\\u002BZO9GyXRvrALOD/Ber6/G/85P3adpT/IHOY/Sq2qP/TANz\\u002BZojZACMAFvrLF2D3nNaW//jiUv46Rj79LSm6\\u002BRZINvjWtM0BnZ5e/6AQYv7czAEB29j7Aly4APvbXiL9cB5W/HYBBPxfbW78JMDNAVjLevxj1Kj36cRi\\u002BVrsSQHlaej\\u002BJYkc/ILOwv/r5PL/ecLw\\u002BD5EtP4N/Wb/V52\\u002B/tOUBvjGxib8UhMK9FKBsvx8Kn76UaJA/9FSovs7Kor7UqY0/B9qLvqOT\\u002Bz6mdaM/wCNaP6IWmj0wH47ARowjQPaNWz\\u002BLrQtAc\\u002Bymvy4fJkC3TNQ\\u002BAD9TQHS87j98Yf\\u002B\\u002BGQ8mP4/mVr/Q3BA/qh2HPgzP1T3I8M2\\u002BcVgEwNwVOD4EeTW/6RmEv8ryqz69yy4\\u002BYA\\u002BSO9TQqD5v2lRAJRwXwF09pz9RHSNAbgDovv4y9r/2ZRXACNW\\u002BPgQ7\\u002BT3ykpC/t8Lzv6093b/qDhHA/HPzQEfC2r8Azus/4Fq\\u002BPyuaHkA54J0/Wu8awFjVwLzsrFM/9i9gPvyrFj/9UjFASRIlvZKbrz2dG0S/X8m1vws6i7612SPAmPm6P/ZACT64MVhAjdg0wCij5b2oDBxAl1jDv3EfUL\\u002B2ZqC\\u002B4/ChPsl1RUAtGI0/vZg/QNYDakCdmeq\\u002Bk7F8vx2D1r6Hx\\u002BG/\\u002BH\\u002B\\u002Bvs5Zzj9nsnC\\u002BXPR7v1p3ET/yINK\\u002Bn7JCP2LwOEBIKpTAbOoEQEIimz8gFhLAKI4Wvw42XL\\u002BOEIq/UYI3v1zaA78WsdM\\u002BH1ojvtXUwj9m\\u002BD6/HPuvv4w4Pz9a8vK//qwEvuJPl76M0p\\u002B8Vshfv\\u002BdvX0A6hCpAJgKUwBXtwj\\u002BxYu\\u002B\\u002BLIZDP\\u002BEdgb\\u002BHdck\\u002BIG\\u002BJPy7GZL8KpMU/TO0PQNrAgL8YqJjA1hIMwI5Nor8tM/8\\u002BRFTePyDNP7947Ne9Hpwfv4DsAb\\u002B\\u002Bohg/532uP1oVi7/kZ1A/mIEgQNghjr8Yzfu\\u002BspyyPihjC8CkelI\\u002BJLxkPWY0\\u002Br8QJb\\u002B\\u002BX0utv2PbQz/RFvw\\u002BKyxFv9bEN798jfM9essNQE17xz8sCFk\\u002Blxr3v2D4\\u002BT4Axvo\\u002Br3b/PwDoqDr4oCZAaNazvwROFb/N11i/ODlcv/dglj9OVgrAftmUvktivb4PW6W/0VkyP/4C5MDuntm\\u002BlMVmP3yFOUA2gTLAg/FjPxpKFUB6SLy/q8Nuv4g9j762QhRAxuCSv3irVj5VFV0/mWbJvxZZRkDQFCg/cpegv\\u002BCyK79qr60\\u002Bf27UP5Oqwz\\u002BuHb2\\u002Bz6Y1v\\u002BMTScAa0I2\\u002BjO6eQLAUDkBm1Ba/saVkP8ByU7xJ5cg//DLHPQcEU8B41g1AqhyUvip/FT\\u002BcO6C/0bP2PrgCyL\\u002BlJJ2/mapGQEG\\u002BOUAYePO/XP4KvcRduL/4Nyy/yOjivSh0TT7kGEDAmflfPjHynL9eZ7o/eXNqv4tdIL/n2xzAZVDVv3/o1j5AaRbA4Dt7Pbudr78rpsS/5oDTPoahPb/cdi\\u002B\\u002BLzoWQHO3nD12b/w/MKNfP\\u002BrGlb9A1PS\\u002BYK3BP16WbT9OOne/alkOwDb3FL0Z3KU\\u002Bj84SwHSOAUBmkR89Y0d8vwCOJT\\u002BYTPu\\u002BWhHAP8iHkr\\u002BQFSS/VIcIv0McGT8phTy/ajXdvchTZb\\u002BMrBQ\\u002BIjiGvxq9Zb/FYCdAvVBlv0Lk2sARdoa/\\u002BorvP0lnEcCPuwPAr80av9kyMb0cBkw\\u002B8DewPrrDH7/i6Em/cHYZQCUaBj8\\u002BGzu\\u002BdH\\u002BXvQZZzD8O1QVAS22FPzCYmT/YuMo\\u002BBm8FP0cMvj\\u002BG1nZAmABbv/xs7T\\u002BP5IM\\u002B8Pmwv1TIyj6GS9e/BC2hv69PID1KYBc/FwygPvm5AT/xdfY\\u002B0IlgQM1ZDz\\u002BePgo/sEWUP6p9Y79YxIO/XguTPxLqoD\\u002Bxf38/abAFQCcXfsAq/c4\\u002Bo2/Gv4mmNT8Ymj8\\u002BHS9awP1HQj9RbeE\\u002Bi2gov0ABZrrFQso\\u002BdETEPo5S0r/0pYC/SwcOwHvExz6TSSLAgoeEv24ajz9Ajxk/\"\n  },\n  {\n    \"CategoryId\": 66,\n    \"Name\": \"Nanotech Snowshoes\",\n    \"NameEmbeddingBase64\": \"E2HYv5zEVz4mXlBAnmY0vpjGZEA/lCG/8M5MPwCEGkCW3UnAvgMeQAogOz4Vl7e\\u002BsvcmQBbiIUAwJBRAlpYTQMLW5j\\u002BPOfM/zSlWP8CfQT/MCJpAC/PQv9wwsz\\u002BAEyfA1OUlP97oxj/\\u002BXHM/Ika7vyh77r8qm2fAAllzv1qbH8Ax\\u002BQFALKYgQOAjK78vwLs/NXafP9SBx7\\u002B4eGnA2i1uP65I278me9Q\\u002BWG1RwJLa/r1yxiFAzNQZwGhF8jzWVMw/vht7wAm6kL\\u002BMGkE/p1hAwB7gfD46rbO/JloAQHwjh0C1znm/LoWPP6mgbUBAqhE/hFl2QEUviT/o7uTAgPyyPw4A4UBVWvE/xiYRwDxDJz7sqb0/YYvcP4x4DkCSscs/k0fBP5C4aL3KrY6\\u002Bkiz0vhTrE7\\u002BOkr2/HZ30v9w12b\\u002BUl9i/KvcxwMZqlT97Iqy\\u002B320\\u002BwM6C6j5zhAa/fPC4v0ZIRUCQPx4/2vT5v/2mM8Dslq4\\u002BHaK9v5qTssBMzcU\\u002BJ/kMQGo6BT6T3TFAKxoDQUSLTL3Wob\\u002B/BIaYPgjKhj65Wcu91JUfPriW6D5RW2HARJQpwLhofL7v\\u002BUFAsKV5vuwtCL/A/Ci/8DjtvIRCy798zLo/OTgJQO6SB7/qvGdADulgwDJWPEABBxk/9HAPwJLwF8Ccczq/7id4P9wDikCmh/y\\u002B\\u002BhdxQO62EEDgdve\\u002BuL8xvaqBWr6p4mxAKkqVv/AOrL7APB3A4pBHP\\u002BuwOT9uA5\\u002B/jhsAvw\\u002BrET9BD1HAxjhyvmUvur\\u002B9pzbAWWd1vixWib\\u002B6psW9Pi81P9KuFz/DEeE/gGkkO5GPY0Ako\\u002BY/vZo4QBVWHr4TIiDAjybGP9iRHEDWLxFAFOMNvxQnZkD/J8k/VASzwBVVWEC8osU/vOwgvtiQrb/5h4y//6T/PqESv7\\u002B\\u002BHEC/LzWGQPzRFsDohV/A/DE0wLhEbj6S01RAmuGcvyezt7\\u002BnE6BAAau8P/Ahnj\\u002B9shpA5sCYP5JzDb/YleS8cl8IQAAlBbubHUW/1FqSviYe7z8TsZ6/zi3UP1wfPr/nFw6/Yj3xP1b8Nb9w8TxAws1Bv9gJAMAAJOc6tY2nPzrxrD6wun8/YwSrvyOuBMCmcwG\\u002BXKQYvu1jkb8z/II/Yv7Yv9NYZcDs2zS/wu6VP\\u002BVu8D\\u002BE\\u002BuG/bVRFvxYVfb8otM0/yoI4wMhrB8E5LCG/2CHkvRuGhcD\\u002Be4xAeCQwv3R2jD9SFSPAHkCFP\\u002BbT\\u002B78heVBAIycJwNkOC0AxYki/rp73v3OvVb5atY8/XPSDP\\u002BjnJUA/vh9A5HMHv5busz/g74g8v3egwNZHhMDSIS7AVb3wQKBDiEAgvQK/UKIywGuu7L54JXO/fzmQPl4OmMDPlHY/a8egPpeLhT\\u002BcGVO/fjTwvxedhz9MHOQ\\u002BG0QXQB8EVD9ePwu/8rnWP2oFBcA5ApO//LbavyC2Jr\\u002BLciO/IN6qPWAD8b\\u002Bt\\u002BI0/3dtrv3aNAMD2VxLAqrE\\u002Bv/aQdECLuyhAfyuqv6YIpj/nl5\\u002B/yDQXwC\\u002Bcrb/\\u002B6ppANiqlPsLdmr\\u002BdN9o\\u002BDTw7QLDugb8jlgRAfld8QLrfEb6S\\u002BxhAgB5wQFvumL\\u002BRig1AEEhKv7j6L79cxPg9YfDnPt08Lz\\u002BkdBs/N\\u002Bd0QGwxCL5tagdAJ64hP8waK8CeMFJA/HO\\u002Bv16PHsBkjzFA5rpcv6ZGL0D76xdAvazSPuw\\u002BHsEocsU\\u002B1pQXQFwbkj3mxV\\u002B/w/qbwKoAHr8Bt/A/iE4JQPJ9Lz5tWaXAGH87QPEWJL41Txy/NQF2P88dgT9LqHo/3phOv86vgr21KU7AjlfePgMtmj820xBBMSmJvhUi7b29OYI/rjnHv/bfpT8CZ08/w0ySv63bKL/AelG7PqNevyOPeb84\\u002B26/YVq7P8Q5Ej/m6Ye\\u002BClWXP8oJWL9TXZzAYO55PsXPJL/T2mO/FwzZvibuWsCUp4S/blglwJTyrT1U1PQ/BNm0v8R\\u002BOD\\u002BlR5\\u002B/\\u002B5fXv/GkIcBJyhS/txiVP1NmMMDbboHAmig8wFiF1r20hf6/UAyGwGF/8b\\u002Bk/9o9\"\n  },\n  {\n    \"CategoryId\": 67,\n    \"Name\": \"Outdoor Administration\",\n    \"NameEmbeddingBase64\": \"OP\\u002BpvgPrzD14gwJAsLbOvqKt1T86/Rs/WvNMP4SeQr/DrrS/cG0ovtBdZjzoQqy9GNIhP7KAJj8E9ZM/eCCovxZUqz72oqo/EUerP2/ziT9vvdE/LvPSPvjFTj2Aosu\\u002BjhuXv54nrT9svh/AXeFcP0pIXL85nSLAlB09PNDUML8dQw\\u002B/DZyYvtDZPb\\u002B8zfw9GCRMPICaMT4gqZC/VA\\u002BBPjXNPT/EBK0\\u002BNKsQvsBO3j60ywi/RaZlvwicyr7om4e/HMscvtTNYb8FXQlAxGAWv8kxKL8Mtlw/MvHwPn3\\u002BsT\\u002B9W\\u002BI/7KTmP6cCKL\\u002BZY40\\u002BzFQeP0eSkz8UDrzAEhaIP60GQT\\u002BbXbU/1UIGv0LOnj0gFNo8YPtLvx9vs70fg9E\\u002BEE0RPqIlSr9Qx8I\\u002BKhgxPTRP9L8qsJE/XvBgv5sjD7\\u002BXC9o/ahqwv0Z4eD4ZZqU/xH7WvQRHPz6WuzW/2/E1v2j5KUAqyBxAtVCIP\\u002BqPi788rxo/IMcsvBRRpb80XFS/Zw2KPrgLU72E1Me/YnzKQHrqfr\\u002BEK5I/HvGoPhxDtL43fi6/3nkXPmkdTr8\\u002BPGm/0ZCVv\\u002BjDND2cIME/y6RPPhgWyD1gbtm\\u002BfKZcv8L1j78An4K/Zqd5P27AW78WfCu/PBWWvyVAFb/oghk/yAcrP7VrWT\\u002B4Mqo\\u002B/JjvP\\u002B5qDUD/4SE/wacHQMscwT\\u002BLWZi/5J2yPWFvRL89H6s/bowBvR\\u002B1QT9ZZHo/hkynPmHppD/EsMm/wPufvHIeyT9U2UDAh7KSvlKMZD\\u002BqqAg/DXOBv2QNvr8eDYe\\u002BUtkiP1KbVj94zE4/S2HpPl3bzj5/SKA\\u002BHuFyv/UYyj/yLDE/KeicPmaTxz5P9LY\\u002BU1zjPuZfkz8ukDu/TIEowLgzer59IYy/ctXVPSrjED\\u002BAQEe\\u002BnBMAPzLvyj9LNsA/8C/CP4\\u002BD6r54TCy/GntUPjSy77\\u002B8oI0\\u002BRb79P6xBB7/xGQk/pya3PzYbIj4MwY8\\u002BKAiuv4aQzL8XFZ6/kEARQA/4J8BAdGc832Klv9p0ob/\\u002B/BG\\u002BIFwuPzbAor/AYTu/D\\u002BdLP9J96751bvk/4BgjO1F4yb9kINS9\\u002B/YqQCepe78LguY/ShcqvwQ0yj5aPN8/ks9nP5gvgz/nE18/GB2sv0BYvj4B4WY/wmVdPxB9xzwAT\\u002Be8cF96vqCs2T7bdam\\u002BVQCxvlSFq8Ag\\u002Bra/IOyoPrRGmD5HXZW/gOdWv\\u002BivvD46\\u002BSi/DuLSvZs34T\\u002BMvCA/4ofdv4zHOD7IKdk/xiajPxg8JkCYWH0/DsO/Pvn6Cb/Cc0\\u002B/cJACPzJZUz9ubGM\\u002B/rgaPyDAbL0e2Ge/yn87QKqwRr9Wj30\\u002BkAXavvrwjT45uOi\\u002BNig4vVrQI8DW5X0/U7AHP8/FQL/jVzU/QrULwBNCor91FtQ/RWBOQHlX7z4FGyw\\u002BoFXfvt8yXb8e8/g\\u002BjxDWvznTjD8\\u002BgmLA9O8bP8VHTb\\u002BAgeY/pSkavypNcT8m\\u002BRi/nbi9v7CKRj\\u002B9cIC/XMbyvtLl2r6wuO\\u002B/cgtoP/ARhL9gbK0/HIh\\u002BvAgE0b9rTAC/XKFDPxZ/4L5iA5i/0JScPi62yL\\u002BUDJG/DH22P3JGrb78D1c/UXp3P8QgTL87nO6/flyTPjzkrL\\u002B24RC\\u002B4Fs6vjnYWL\\u002B8HmM9BmvFv\\u002BIfdD7hkY6/hcd7v9jvYr0eo5Y9ZSGsv8nUkr\\u002Bg/eA/J0AePxvZycBE7y\\u002B/QPDzPcKeZL78KBM\\u002ByNLjP4PhFL8HqAhAs4T4vrnm2z5G7K0\\u002BHxqEP58hF79SNFO/IX6yvmZ2Kz9SDCc/beztPlMgpj/3x62/Iu6GP9SI0j8BqCxAKEbRv3HDFT6CuLY/yIvbPpwWg75EeJw8WgGvv6fa7D9Smom/1M8qQDhIRr8BFwRAISJUv27DvD\\u002BPdgU/QgUZP9x7pz7c0ifACD6QP52UQT8ZsE\\u002B/uYZiv5jot7/OSiU/bGFNv6BfOL0ePXc/Tn89P1Ekub/M6Vi/4jggPkUPYr/wmS0/7EVev7GBmz4Crtm/EMiEvo0ljL0jvRLAV7GBv8eyTL\\u002Btids/\"\n  },\n  {\n    \"CategoryId\": 7,\n    \"Name\": \"Cycling Gadgets\",\n    \"NameEmbeddingBase64\": \"E8cgvinYhT4rWNI/L5Zkv6yqOb1eB\\u002Bm907S5PyDAszx6uLG/tQz1vaFoDcAgtbi/BUbTP0FNuT9tr3q/lkuRv6DmIEBgdj2/IRINQJp0iD91T40/G8RAvxc/nz9/WiW/\\u002BpDBP78XPz9sVo\\u002B/NGGgPhp1HL4kFG7ALZn8vcZYnT4tJx3AOg86PxLoIMBqor2/3BZHPnmSLT8kLkvAPqhOP\\u002Bh81D7wE40/KDbMv8CRBz6UhuU/xkTrPfqaCr9dZFa/qGoHQNSifcDJVfg/LweSv4jLwz\\u002BOFiXAl4I8v8JLuT8lCAo\\u002BSdAlQLitlD\\u002B\\u002BghE\\u002B\\u002BJ0vP\\u002B5vAUAg3ZfAss4DQIjjpryP\\u002BdI/IO2Vv/0yvj79jNW\\u002BurHTP63EVL5sD4e8B4LIP/Tp1z85eF4/fmjDPecfOb9wkHC/0CIlwBSwr7818MU/zHG9v9URYD87uZY/DBd7P9bgt74KXpu/MdT2v3Zw0D9gCns\\u002BJXzDv8\\u002BiBb4O3rw/m2ueP/liKMC\\u002B\\u002B\\u002B\\u002B/39gAvho8xr84aM2\\u002BGLwOQdoDt79aKlY/o/8zQHueKT9l9pE/G7UTwODbJz8ujxDA3M7xvzRZDECN6B1Ag\\u002BjFPj4GVr8ZbFc/jq2aviomdT8wdKi/BG6aP1qasr4IiyE/ksVWwLS9mD7ApOC7bPP1v\\u002ByqJj/SO2q/vW/ZPhcPKEBfLcw\\u002BSHeeP9swKEAK8DZAcFsAv21ujz96\\u002BOs\\u002BUjXXvxITsj9b6AvAs/wNv06lOECxLDC\\u002BPiEVvg38c0D7F13ArH6Gv4aXCT8MN78/Yr0ePpoLm7\\u002BMkQHATgn9P1KnPL7IHqU//LHFPeCATz92XQ9A9RKgP2a6e0DwMXG/LueuP5ZUAsCqyCQ9kwjpv9YvIj5OsrM/chp7wJWziD9W9LE/mwTkvo/Oqr\\u002BOlgw9gdcnP8L/pL9ziJg\\u002B88mBQC1W\\u002B7072xfAY76nP8s6AMAWoBM/GnTAP9988r8rxrg\\u002B9Yz9vvjZ2T2ZGpi\\u002Bh6g7wByLC8AXzms/NpdVQMJd0b6tGr09t8u0voooHz/GL5C/zNtzv5wuPsC0uEq/fBcBvvoHAb9xSwVAb\\u002BQDwAdvQz94fek/jOOfP/oV8j0XejzApG4VwIw8D0AnDFW\\u002BwH6NP8LIgr/q\\u002BUdAZ1WlP4ECnL6xHCa/LgrpPn4Aiz7K7uK/wSpGvvJTeD4Dvn0\\u002BoGYzwHvNu8BsOjXA0k0zP7IWC0A\\u002BjLA/EY7CPzNcSD\\u002BfscI/8Eb3voEsQr\\u002Bhjm9A\\u002Bn04wEP5DsAKJNY\\u002BQ22hvxxohz9M5SU/V1JJv/ko1r9mTrm\\u002B5NK7PyocsD4IVfC/O53nvxH6KcBqTIA/sq6/QHnwTT/As0c/xKmaP0AeaTz/O7U\\u002BMUDkvsyXR8C2\\u002BWE\\u002B0EC1POxH0j\\u002B5Bj8/ygUCwIt9q78TqBq/OJUHQJD/mb9UDue/gux8vwhU6LxZWoi/ggz7v1J8EL\\u002B4fPq/HjOJvo0oOECCY9Q/EEJjv7/uHkDuihHAaNF2v9UWLj9s11a/9tD2PoP\\u002BRb/COYU\\u002BnIXwvpMJeb\\u002BohwhA5B/VPqRfqr9XUgzAAtLZP5CGzzwLXD0/XmODQH03eD\\u002BsQVo\\u002BrHuPP441qr5W8EZA4CeTPzQzij/YSCE8850twB4/Oj5gKk0/LH3ZP9lc1L9oHFC/L7OPP9wsE8Cmde09Hm0Evz4tzD92zHg/7LPHPhqv6L\\u002B6tjFA73i2vrIOAcFydHU/rG8FP0NMrz1LNgbAHzAGvxz6PT/E0iJAcNApvnRbuz8VbDy/0vnAP/\\u002Bg7z\\u002BQ/ce\\u002BB73RP5bPFkDiKipAOpt5vmZPnb5XFR\\u002B/BOuYP6Dr4j/EjaJAPa02wFjHJUAPbwBAJxMDwDzEsT49Fu\\u002B\\u002Bs929P6QI5b\\u002B8iaq/F9RgP\\u002Bn/Ij/Uh0C/bNGTvFa2i7\\u002BuIBE\\u002BxBSjPlaEyj4gqGi\\u002BwqQbPpzNLsDmDbG/OB0mQIsWEcDkr1fAgh\\u002Blv2jfYj\\u002BQLZK9QZjhv7GOCMBIPU3AlEUmPxxkUT90rma/otk9v198iL\\u002BwCzi8wg94vSul8z5jmTTAB9IJvpo7Dr9nO5i\\u002B\"\n  },\n  {\n    \"CategoryId\": 8,\n    \"Name\": \"Adventure Footwear\",\n    \"NameEmbeddingBase64\": \"NWfVvwRetD/NPBdASgq7vT/3Dj7UGqg/QuAJvix/sT/2MDzAH4\\u002BEvyQlcj7YvLS\\u002BCaAFPwrUGz8vhdI/drlXP6x38T\\u002B68Es/MoGMv2GqTEBCeldAxF\\u002B5PrRSFb8ABMC/dH82wFXQcz/IsXm/Y9jlvu6Pnz43uALABXrGPp8TdD9Hr\\u002B\\u002B/pEJZv\\u002BEilj9Vguw/1BCyv3\\u002BxLD9Q14W/3hWZPxsp/b6DfQRAADTAvqURdL\\u002BLDzU/To3sv1J4Bz/6qZC\\u002B/UyqPsiE6j2QqC2/V2oUP5Uvn7/0m\\u002Bq/kWyWP6bU1z8aBq0\\u002BwvEGwOwA6j6sZfM\\u002BUK0FQDFz1z64zIzAltg6QJxdf77MvxVATI\\u002Bnv7RCdj963tW\\u002BmUj2PlS/5r/xDAxAnho6QA942j8Hchc/YTfLP0rOB79P45Q\\u002BwMYyv4SNAz\\u002BkGii/xHHov/J9Sj\\u002BlAWA/utLKP0XN5r/ynh9A1tWqvw7kxz9QFbw/982pPnc5xL/I8\\u002Bm/jbD4vmpPT79ywKi\\u002BpUesvQBzkr/zEli/WKz3QArNjr8qAqg/QGGcP2vr3T8SPS4/ri8xwEtGAUCo/t8/3XeDvrwLI75dNu49yFblvLUTzz7k0ak\\u002BiC54wECEtb1SkxDAKLIbP3QrUT9t1uc/gMEZwCLan7/TgJQ/XlCivxRJBsD\\u002BQIA\\u002B8gRIQMZMBEBwZli\\u002B2\\u002BggQFoSg75NgjXAwESdu9KNlL2Kz5\\u002B/HItevrtJTr\\u002BORUA/ob4ZwP5/NEDd6LK/GUWUv6HJBkBAyILARp\\u002B2P/4ikz/GWFm/twezvsuher4cJ8o/OVSZP0woJD7u0dA/cPLjv1gO6b5q0Sq9LUodQG3sy77fcl2/DNg7P1PjeL/2La6/evbcP6kNgT9/uto/gG6fwApomz8TOYy/3Krdv84Ih760JYQ/JL69v7BfKL8yv1ZAtBFEQJGZTb2s2xXAoRxzPhWfBcDKLP0/9lT2P2Awm77Ogno/i4CNPjpVm78OwGS\\u002BRGaov5h2KD8tHE4/LtO0PzNtwT9VWoXAcI8GQL9ZBsDrDDO/UmuhPwmo3b8y2Xe/hBu2vU9GLcDGbqY/8MyNvRPvpr7McJ881YHVP42sH0Dixxi\\u002By/Szv0AljL/sb8m9IB7rvlmfPz85wvu\\u002Brx2uv9ARAT4dN5O/Ct99PzQ5nj9cmqW/WbrPP5A\\u002BCD/TqtW/0XRWv1xz3cCr8FA/VlOePwYwtb7zf2u/dDE2vbKanD/1apk\\u002BqjmWPuknnb\\u002BBWyRAKZJPv2TAJj6\\u002BfNy96Jv3v87ohT9J\\u002Bj5ALkIFwN/lCb\\u002BAF1G8qLBnPiZ54j8C15O/jqIYwB82v74T1Ye/JLmpQMHtnEDnNe6\\u002BLXqEwAtf9T0tZ\\u002B8/NmuDv1JcWcDovR1AiiJKv9Nm5T5\\u002BiGjAct2DPYi5J8B9vA0\\u002B5DhGQK1o/z9x9YS/GOoBPyRptb7Vg0LA/gAKwBQUuL9HbH\\u002B/RBw\\u002BPwdAk77fERtALvmFv3QzPb/NLOK/xRGmv0K6q78wLHW/TLdovxMIc77gaaG/fgepPnDsETxvAfA/J5CNP85j2z6ByDm/dg4WQJsEr7/FPYK/tFT6Pu5enT8eZ4G9cFUPQIgfvjwGltc/UFncP1v5JEC1fAK/TEl6PwDGrr60NOm\\u002BXTDiPwWESj8sn4q/fPgEPnaI1L/gsvQ7zkyAPWC2ab6V/zG/sioTvyijcb9mEGxAWsj\\u002BvetR2cDRq\\u002Bw\\u002BsoZNP4wPTz8S0bW/EJHEPAosjT7WDS8/sCAPP6d7fj/VhNq9sFvWP6kyDD6d7FS/e75cvi1oDECMOz5A8Jfav9J1oz/uOyvAETTTPwdS1b4ObnhAiTLmPoLHpT5W9UY/rLiivo7P6j4nqUPAWW0sv9iZBEBC54q/Jmh\\u002BQBeVRj/L0IK\\u002BqMcYQPh9Az\\u002Bs4ma9ISk2PwGlCMBU8be\\u002B7khlvv5WnD9o0qA/hB4oP5TgOcC4KDA9tQKAPxEqkT6im10/QnKcvj46dL1rfOi/MqsvP\\u002Byp4zx4zzw\\u002BsQgov3nquL\\u002B4mj\\u002B/l3Gdv9Asib\\u002BAqEnA4rJ3wPYO0L8RQjK/\"\n  },\n  {\n    \"CategoryId\": 9,\n    \"Name\": \"Sleeping Gear\",\n    \"NameEmbeddingBase64\": \"LF3Yv1BrCUCNS3O\\u002Bp4gvP6/NBz\\u002BCCPg/R\\u002BG9P\\u002BIf9b6Sg9k\\u002Bpy6svjedRr/aAa\\u002B98PJ8v\\u002BxGH0CxneA/TAhav20W4z8OqhS/79xaPthrFz14Y\\u002BA/xk7Nvlp2uz\\u002Bo/9k\\u002BPbQZP2YBmL8uhHI\\u002BDLeIP7KpXr8421HAwn\\u002Bpv97VjT8IhXa/LKw2v/85470A8Xy9KfOHP7XaCL9OUCm\\u002BbHSkP\\u002BAM/j9EzjM/ePEQPzQ2K78Br8s\\u002BljeXvbp6W77fZ/y/cmD9P6xZlT6nCYk/szFqvwCIFT8cgBq/ASCjPv7OG73VfkU\\u002BxKKLPt9XvD\\u002B\\u002B26Y/w7Syvvb\\u002BKEDmKlrAgaNeP3Jcbj\\u002B2WpY/shwXwO7aoT7MsK4/dteQPn7acb/7IiC/LNqwPksgp77moGA/EOpaP9X5BkC23iu/WCpivQZxbL8bTMG/ljXbvkQbbj4spyW\\u002B2pl3PiqRcD\\u002B44Xm\\u002B5zpWvhzENL8yGW\\u002B\\u002BipAUvxjYzz7Ktnm/DpIAPxml4b0AuDW\\u002BtmaIv4/Xhz/uFLm/gPzTQE4cmz/yZhg/9lsfP3vM1T7jQjy/MnVGwK1DNL8sfno/XF7CvmVtZz96n7Y9U7WZP7W2dj9OmXW\\u002BKsrvP120mT85eFY/J0M0QAoNwj\\u002BEoyQ/PRUdwMwJ/L9GkB5AxLHqvui5wT7gUTy/IIGuPx/aCUD4utc/9gr0PpB3dL9z7ls/uDBaP2BD4T3uRja/NJqaP/Tjm798wSG/4zjevrBBWL3EmE0\\u002BHqOAvphcLUDX9lDAbMDgvnBrKL7iw5\\u002B/VtCaPuYLHcCuVFk/KkjwPphluj1rbq0\\u002B2yjGv5KXpT\\u002BB95E/PWcIQPgx5T3kiEm\\u002BUFu1vchSvD7CPys/miTWP1Gmmz\\u002B\\u002Bc5C/NCqdv3L0S78t6tW\\u002B\\u002Brmdv69WRsCJjyU/uGcEQJaN/76hjwu/qPFTQLtq2D7Wa\\u002BO\\u002BDPMiv0d44b8QPDI9pjjFPkp/CcCKJ8O/IJh6v34YoD5AdUo8x12uvmXWuj/AyxM/prdsv4Af170GJKm/Zu9qP5qQ2j6COVC/k48\\u002Bv75h17/XLp0\\u002Bjd8lPx2xkL9ue9I/Kr5hPhhikT\\u002BWYFq/iIrZP8wGS0AYivu/5vpKv\\u002BTNcD9MbI09Ch6UP\\u002BK\\u002BrL/iC70/iIA5vR9i\\u002BL\\u002B5NwJAYMV9v80/qz6l8qm/jQsiP8uISz8qUPm/XsbkvkoGusAu9rE/jt5/P4Rgqb6OXdO9y6IWv4DFRb\\u002BKKo8\\u002BDlFcv\\u002BXcgr\\u002BzPSBAJGfGvsAwCMB\\u002BsEk/Me34viyAREB67m\\u002B\\u002BrA8AwBr0gr5C5rS/NrsvPpolAb90IJa/m/X1P0WDVb8mCi2/GjpYQNoXnL5MPSZAxDskv2ImDz\\u002Bsy/I/yo\\u002BxP1hnUcCihck/uiQAvzxj/z9PkUc/T9W5PhBJC79SmKq/ZLN/QFgfYL/ufpu/dUVyvyxj9b\\u002BKzwjANcvHv7q15r7lawq/YXLmPxBfij4uKto/klN7v/qpsD0RLSPAqmhmv8lpmb\\u002BXnPe\\u002BbJZrv8MzBL/0bkS/nkHGvuhIbL88Ehq/tawvPQXqCL/3ysK\\u002BpzEUPkDZuL8BZti/qJ/IPe7r2b\\u002BMh4w92sSrP\\u002B7xrz/ONbE/gRWGv5z2iz9Yu\\u002B2\\u002B5uHuPdQeNL51FoW/L75HPvrJkz6Zq4E\\u002BFtBSPR5Q2T9oAge9yaoDP\\u002BMEPT9AWeo9QXabvo\\u002BdIsDVC1dABgSGPpkrs8AwVVi\\u002B9IVZwOC5gr8oPCO/Is9AvwAto75i9a8/3WUzvzY6cT\\u002BlTAK/v4AiQGY2JL/cZG8/rFk\\u002BPtY8kz8y9Pc9dFcZwKP/hj9\\u002B2lC/kISHvy5CuT9\\u002BmH5AwQiDvtTdH0DnfgtAJn4HPqnXdT/AoRc\\u002BqH6OP7UYA0DxYIk\\u002BAFo/P15isj2GEug9n1iRv32NG8Al89e\\u002B4bOAPwpqBb/QQdw\\u002BJGFOP9pVFD/MEv0\\u002Br/GaPxr0kL9TmRq/1xTvvzB2Sj4cYB/AUjK6v9vBxL\\u002BLksq/BmwwPy5HO77dbfC\\u002BZM5DvSIYlj8ZwOw/eXTMv3eJO7887FDAfIANwMN6dr5T6k6/\"\n  }\n]"
  },
  {
    "path": "seeddata/dev/customers.json",
    "content": "[\n  {\n    \"CustomerId\": 71,\n    \"FullName\": \"Sasha Patel\"\n  },\n  {\n    \"CustomerId\": 338,\n    \"FullName\": \"Elliot Lawson\"\n  },\n  {\n    \"CustomerId\": 249,\n    \"FullName\": \"Eva Chen\"\n  },\n  {\n    \"CustomerId\": 236,\n    \"FullName\": \"Riley Williams\"\n  },\n  {\n    \"CustomerId\": 247,\n    \"FullName\": \"Evelyn Chambers\"\n  },\n  {\n    \"CustomerId\": 9,\n    \"FullName\": \"Alisha Reynolds\"\n  },\n  {\n    \"CustomerId\": 134,\n    \"FullName\": \"Emma Lee\"\n  },\n  {\n    \"CustomerId\": 340,\n    \"FullName\": \"Alexander Chen\"\n  },\n  {\n    \"CustomerId\": 269,\n    \"FullName\": \"Fiona Reynolds\"\n  },\n  {\n    \"CustomerId\": 266,\n    \"FullName\": \"Asher Montgomery\"\n  },\n  {\n    \"CustomerId\": 75,\n    \"FullName\": \"Gina Reynolds\"\n  },\n  {\n    \"CustomerId\": 192,\n    \"FullName\": \"Natalie Chen\"\n  },\n  {\n    \"CustomerId\": 43,\n    \"FullName\": \"Aria Thompson\"\n  },\n  {\n    \"CustomerId\": 350,\n    \"FullName\": \"Terry Smith\"\n  },\n  {\n    \"CustomerId\": 34,\n    \"FullName\": \"Samantha Johnson\"\n  },\n  {\n    \"CustomerId\": 88,\n    \"FullName\": \"Elias Porter\"\n  },\n  {\n    \"CustomerId\": 380,\n    \"FullName\": \"Alex Kim\"\n  },\n  {\n    \"CustomerId\": 289,\n    \"FullName\": \"Ava Thompson\"\n  },\n  {\n    \"CustomerId\": 245,\n    \"FullName\": \"Lyla Chan\"\n  },\n  {\n    \"CustomerId\": 303,\n    \"FullName\": \"Lindsey Chen\"\n  },\n  {\n    \"CustomerId\": 344,\n    \"FullName\": \"Travis Andrews\"\n  },\n  {\n    \"CustomerId\": 144,\n    \"FullName\": \"Cassandra Linwood\"\n  },\n  {\n    \"CustomerId\": 274,\n    \"FullName\": \"Kaitlyn Reynolds\"\n  },\n  {\n    \"CustomerId\": 341,\n    \"FullName\": \"Maxwell Bennett\"\n  },\n  {\n    \"CustomerId\": 360,\n    \"FullName\": \"Eliza Thompson\"\n  },\n  {\n    \"CustomerId\": 163,\n    \"FullName\": \"Grace Harper\"\n  },\n  {\n    \"CustomerId\": 166,\n    \"FullName\": \"Renee Bennett\"\n  },\n  {\n    \"CustomerId\": 25,\n    \"FullName\": \"Caroline Thompson\"\n  },\n  {\n    \"CustomerId\": 150,\n    \"FullName\": \"Lindsay Johnson\"\n  },\n  {\n    \"CustomerId\": 10,\n    \"FullName\": \"Alyssa Jacobs\"\n  },\n  {\n    \"CustomerId\": 17,\n    \"FullName\": \"Haley Smith\"\n  },\n  {\n    \"CustomerId\": 81,\n    \"FullName\": \"Evelyn Kim\"\n  },\n  {\n    \"CustomerId\": 23,\n    \"FullName\": \"Lila Chang\"\n  },\n  {\n    \"CustomerId\": 154,\n    \"FullName\": \"Alexandra Martinez\"\n  },\n  {\n    \"CustomerId\": 237,\n    \"FullName\": \"Tobias Reynolds\"\n  },\n  {\n    \"CustomerId\": 195,\n    \"FullName\": \"Evelyn Tran\"\n  },\n  {\n    \"CustomerId\": 277,\n    \"FullName\": \"Evelyn Smith\"\n  },\n  {\n    \"CustomerId\": 285,\n    \"FullName\": \"Nora Johnson\"\n  },\n  {\n    \"CustomerId\": 60,\n    \"FullName\": \"Harper Carter\"\n  },\n  {\n    \"CustomerId\": 257,\n    \"FullName\": \"Marie Chen\"\n  },\n  {\n    \"CustomerId\": 189,\n    \"FullName\": \"Ella Smith\"\n  },\n  {\n    \"CustomerId\": 281,\n    \"FullName\": \"Jillian Stanton\"\n  },\n  {\n    \"CustomerId\": 48,\n    \"FullName\": \"Mila Chang\"\n  },\n  {\n    \"CustomerId\": 221,\n    \"FullName\": \"Ella Tucker\"\n  },\n  {\n    \"CustomerId\": 106,\n    \"FullName\": \"Nora Hamilton\"\n  },\n  {\n    \"CustomerId\": 133,\n    \"FullName\": \"Riley Patel\"\n  },\n  {\n    \"CustomerId\": 36,\n    \"FullName\": \"Taryn Jacobs\"\n  },\n  {\n    \"CustomerId\": 204,\n    \"FullName\": \"Evan Smith\"\n  },\n  {\n    \"CustomerId\": 46,\n    \"FullName\": \"Grace Patel\"\n  },\n  {\n    \"CustomerId\": 14,\n    \"FullName\": \"Evan McAllister\"\n  },\n  {\n    \"CustomerId\": 312,\n    \"FullName\": \"Eliot Jensen\"\n  },\n  {\n    \"CustomerId\": 310,\n    \"FullName\": \"Jenna Adams\"\n  },\n  {\n    \"CustomerId\": 251,\n    \"FullName\": \"Avery Lim\"\n  },\n  {\n    \"CustomerId\": 117,\n    \"FullName\": \"Alexandra Park\"\n  },\n  {\n    \"CustomerId\": 105,\n    \"FullName\": \"Samantha Harris\"\n  },\n  {\n    \"CustomerId\": 35,\n    \"FullName\": \"Evelyn Simmons\"\n  },\n  {\n    \"CustomerId\": 72,\n    \"FullName\": \"Samantha Porter\"\n  },\n  {\n    \"CustomerId\": 66,\n    \"FullName\": \"Hannah Park\"\n  },\n  {\n    \"CustomerId\": 288,\n    \"FullName\": \"Lila Stevenson\"\n  },\n  {\n    \"CustomerId\": 55,\n    \"FullName\": \"Ella Park\"\n  },\n  {\n    \"CustomerId\": 239,\n    \"FullName\": \"Riley Park\"\n  },\n  {\n    \"CustomerId\": 200,\n    \"FullName\": \"Caroline Collins\"\n  },\n  {\n    \"CustomerId\": 302,\n    \"FullName\": \"Selena Chen\"\n  },\n  {\n    \"CustomerId\": 37,\n    \"FullName\": \"Alexis Park\"\n  },\n  {\n    \"CustomerId\": 378,\n    \"FullName\": \"Jasmine Park\"\n  },\n  {\n    \"CustomerId\": 205,\n    \"FullName\": \"Evelyn Collins\"\n  },\n  {\n    \"CustomerId\": 332,\n    \"FullName\": \"Jesse Reynolds\"\n  },\n  {\n    \"CustomerId\": 22,\n    \"FullName\": \"Harper Nguyen\"\n  },\n  {\n    \"CustomerId\": 308,\n    \"FullName\": \"Samantha Park\"\n  },\n  {\n    \"CustomerId\": 382,\n    \"FullName\": \"Lucy Bennett\"\n  },\n  {\n    \"CustomerId\": 258,\n    \"FullName\": \"Eleanor Rivera\"\n  },\n  {\n    \"CustomerId\": 49,\n    \"FullName\": \"Alexandra Stevens\"\n  },\n  {\n    \"CustomerId\": 256,\n    \"FullName\": \"Avery Stone\"\n  },\n  {\n    \"CustomerId\": 287,\n    \"FullName\": \"Lara Nguyen\"\n  },\n  {\n    \"CustomerId\": 124,\n    \"FullName\": \"Samantha Preston\"\n  },\n  {\n    \"CustomerId\": 188,\n    \"FullName\": \"Lila Simmons\"\n  },\n  {\n    \"CustomerId\": 82,\n    \"FullName\": \"Lena Patel\"\n  },\n  {\n    \"CustomerId\": 80,\n    \"FullName\": \"Arianna Park\"\n  },\n  {\n    \"CustomerId\": 156,\n    \"FullName\": \"Ethan Martin\"\n  },\n  {\n    \"CustomerId\": 233,\n    \"FullName\": \"Samir Patel\"\n  },\n  {\n    \"CustomerId\": 184,\n    \"FullName\": \"Patricia Harris\"\n  },\n  {\n    \"CustomerId\": 115,\n    \"FullName\": \"Gavin Park\"\n  },\n  {\n    \"CustomerId\": 226,\n    \"FullName\": \"Riley Thompson\"\n  },\n  {\n    \"CustomerId\": 139,\n    \"FullName\": \"Lila Martinez\"\n  },\n  {\n    \"CustomerId\": 351,\n    \"FullName\": \"Hans Alleman\"\n  },\n  {\n    \"CustomerId\": 230,\n    \"FullName\": \"Elias Kim\"\n  },\n  {\n    \"CustomerId\": 120,\n    \"FullName\": \"Nadia Patel\"\n  },\n  {\n    \"CustomerId\": 214,\n    \"FullName\": \"Evan Carter\"\n  },\n  {\n    \"CustomerId\": 8,\n    \"FullName\": \"Evelyn Park\"\n  },\n  {\n    \"CustomerId\": 33,\n    \"FullName\": \"Samantha Miller\"\n  },\n  {\n    \"CustomerId\": 100,\n    \"FullName\": \"Alexis Taylor\"\n  },\n  {\n    \"CustomerId\": 363,\n    \"FullName\": \"Elena Kim\"\n  },\n  {\n    \"CustomerId\": 126,\n    \"FullName\": \"Lila Chen\"\n  },\n  {\n    \"CustomerId\": 248,\n    \"FullName\": \"Evelyn Tan\"\n  },\n  {\n    \"CustomerId\": 339,\n    \"FullName\": \"Beckett Chen\"\n  },\n  {\n    \"CustomerId\": 58,\n    \"FullName\": \"Samantha Hayes\"\n  },\n  {\n    \"CustomerId\": 368,\n    \"FullName\": \"Jenna Evans\"\n  },\n  {\n    \"CustomerId\": 265,\n    \"FullName\": \"Dr. Alison Kim\"\n  },\n  {\n    \"CustomerId\": 70,\n    \"FullName\": \"Mia Johnson\"\n  },\n  {\n    \"CustomerId\": 30,\n    \"FullName\": \"Eleanor Park\"\n  },\n  {\n    \"CustomerId\": 19,\n    \"FullName\": \"Maggie O\\u0027Connor\"\n  },\n  {\n    \"CustomerId\": 284,\n    \"FullName\": \"Cameron Smith\"\n  },\n  {\n    \"CustomerId\": 296,\n    \"FullName\": \"Megan Crawford\"\n  },\n  {\n    \"CustomerId\": 322,\n    \"FullName\": \"Lindsay Tanaka\"\n  },\n  {\n    \"CustomerId\": 152,\n    \"FullName\": \"Lena Park\"\n  },\n  {\n    \"CustomerId\": 313,\n    \"FullName\": \"Lindsay Chen\"\n  },\n  {\n    \"CustomerId\": 79,\n    \"FullName\": \"Jonathan Wu\"\n  },\n  {\n    \"CustomerId\": 375,\n    \"FullName\": \"Jordan Haines\"\n  },\n  {\n    \"CustomerId\": 52,\n    \"FullName\": \"Riley Jackson\"\n  },\n  {\n    \"CustomerId\": 255,\n    \"FullName\": \"Adrian Park\"\n  },\n  {\n    \"CustomerId\": 212,\n    \"FullName\": \"Jamie Wright\"\n  },\n  {\n    \"CustomerId\": 162,\n    \"FullName\": \"Hannah Smith\"\n  },\n  {\n    \"CustomerId\": 324,\n    \"FullName\": \"Brandon Park\"\n  },\n  {\n    \"CustomerId\": 138,\n    \"FullName\": \"Nadia Chen\"\n  },\n  {\n    \"CustomerId\": 62,\n    \"FullName\": \"Evan Park\"\n  },\n  {\n    \"CustomerId\": 44,\n    \"FullName\": \"Lena Miller\"\n  },\n  {\n    \"CustomerId\": 315,\n    \"FullName\": \"Evan Caldwell\"\n  },\n  {\n    \"CustomerId\": 300,\n    \"FullName\": \"Evelyn Patterson\"\n  },\n  {\n    \"CustomerId\": 377,\n    \"FullName\": \"Mia Reynolds\"\n  },\n  {\n    \"CustomerId\": 111,\n    \"FullName\": \"Megan Harper\"\n  },\n  {\n    \"CustomerId\": 196,\n    \"FullName\": \"Lila Benson\"\n  },\n  {\n    \"CustomerId\": 194,\n    \"FullName\": \"Renee Marshall\"\n  },\n  {\n    \"CustomerId\": 104,\n    \"FullName\": \"Linda Chen\"\n  },\n  {\n    \"CustomerId\": 94,\n    \"FullName\": \"Bridgette Patterson\"\n  },\n  {\n    \"CustomerId\": 164,\n    \"FullName\": \"Nathan Reynolds\"\n  },\n  {\n    \"CustomerId\": 268,\n    \"FullName\": \"Nora Kim\"\n  },\n  {\n    \"CustomerId\": 160,\n    \"FullName\": \"Evelyn Yang\"\n  },\n  {\n    \"CustomerId\": 329,\n    \"FullName\": \"Remy Johnson\"\n  },\n  {\n    \"CustomerId\": 83,\n    \"FullName\": \"Elena Park\"\n  },\n  {\n    \"CustomerId\": 137,\n    \"FullName\": \"Linden Chan\"\n  },\n  {\n    \"CustomerId\": 355,\n    \"FullName\": \"Samantha Andrews\"\n  },\n  {\n    \"CustomerId\": 374,\n    \"FullName\": \"Samantha Wright\"\n  },\n  {\n    \"CustomerId\": 50,\n    \"FullName\": \"Dakota Reyes\"\n  },\n  {\n    \"CustomerId\": 349,\n    \"FullName\": \"Liam Thompson\"\n  },\n  {\n    \"CustomerId\": 18,\n    \"FullName\": \"Evelyn Gardner\"\n  },\n  {\n    \"CustomerId\": 317,\n    \"FullName\": \"Yvette Chen\"\n  },\n  {\n    \"CustomerId\": 175,\n    \"FullName\": \"Eliana Pearson\"\n  },\n  {\n    \"CustomerId\": 383,\n    \"FullName\": \"Marley Johnson\"\n  },\n  {\n    \"CustomerId\": 283,\n    \"FullName\": \"Hannah Liu\"\n  },\n  {\n    \"CustomerId\": 132,\n    \"FullName\": \"Riley Tanner\"\n  },\n  {\n    \"CustomerId\": 259,\n    \"FullName\": \"Lila Patel\"\n  },\n  {\n    \"CustomerId\": 238,\n    \"FullName\": \"Derek Hughes\"\n  },\n  {\n    \"CustomerId\": 197,\n    \"FullName\": \"Olivia Hart\"\n  },\n  {\n    \"CustomerId\": 168,\n    \"FullName\": \"Evan Reynolds\"\n  },\n  {\n    \"CustomerId\": 263,\n    \"FullName\": \"Lila Park\"\n  },\n  {\n    \"CustomerId\": 225,\n    \"FullName\": \"Emma Smith\"\n  },\n  {\n    \"CustomerId\": 187,\n    \"FullName\": \"Lila Porter\"\n  },\n  {\n    \"CustomerId\": 169,\n    \"FullName\": \"Samantha Chen\"\n  },\n  {\n    \"CustomerId\": 7,\n    \"FullName\": \"Evan Williams\"\n  },\n  {\n    \"CustomerId\": 76,\n    \"FullName\": \"Ella Chen\"\n  },\n  {\n    \"CustomerId\": 109,\n    \"FullName\": \"Morgan T. Reynolds\"\n  },\n  {\n    \"CustomerId\": 216,\n    \"FullName\": \"Eliana Chen\"\n  },\n  {\n    \"CustomerId\": 45,\n    \"FullName\": \"Alexa Park\"\n  },\n  {\n    \"CustomerId\": 122,\n    \"FullName\": \"Alexis Johnson\"\n  },\n  {\n    \"CustomerId\": 77,\n    \"FullName\": \"Sasha Park\"\n  },\n  {\n    \"CustomerId\": 328,\n    \"FullName\": \"Dr. Alexei Petrov\"\n  },\n  {\n    \"CustomerId\": 314,\n    \"FullName\": \"Mila Patel\"\n  },\n  {\n    \"CustomerId\": 84,\n    \"FullName\": \"Hannah Lee\"\n  },\n  {\n    \"CustomerId\": 170,\n    \"FullName\": \"Emily Kim\"\n  },\n  {\n    \"CustomerId\": 61,\n    \"FullName\": \"Lila Cunningham\"\n  },\n  {\n    \"CustomerId\": 56,\n    \"FullName\": \"Evan Johnson\"\n  },\n  {\n    \"CustomerId\": 114,\n    \"FullName\": \"Lila Davis\"\n  },\n  {\n    \"CustomerId\": 57,\n    \"FullName\": \"Amelia Chang\"\n  },\n  {\n    \"CustomerId\": 305,\n    \"FullName\": \"Aria Jones\"\n  },\n  {\n    \"CustomerId\": 20,\n    \"FullName\": \"Sophie Chang\"\n  },\n  {\n    \"CustomerId\": 95,\n    \"FullName\": \"Evan Chambers\"\n  },\n  {\n    \"CustomerId\": 186,\n    \"FullName\": \"Avery Sutton\"\n  },\n  {\n    \"CustomerId\": 92,\n    \"FullName\": \"Alexandra Chan\"\n  },\n  {\n    \"CustomerId\": 357,\n    \"FullName\": \"Evelyn Bennett\"\n  },\n  {\n    \"CustomerId\": 198,\n    \"FullName\": \"Olivia Chen\"\n  },\n  {\n    \"CustomerId\": 362,\n    \"FullName\": \"Dr. Megan Davidson\"\n  },\n  {\n    \"CustomerId\": 146,\n    \"FullName\": \"Lena Smith\"\n  },\n  {\n    \"CustomerId\": 96,\n    \"FullName\": \"Evan Patel\"\n  },\n  {\n    \"CustomerId\": 145,\n    \"FullName\": \"Becky Thompson\"\n  },\n  {\n    \"CustomerId\": 272,\n    \"FullName\": \"Avery Shaw\"\n  },\n  {\n    \"CustomerId\": 153,\n    \"FullName\": \"Lindsay Anderson\"\n  },\n  {\n    \"CustomerId\": 215,\n    \"FullName\": \"Emma Porter\"\n  },\n  {\n    \"CustomerId\": 147,\n    \"FullName\": \"Rachel Johnson\"\n  },\n  {\n    \"CustomerId\": 318,\n    \"FullName\": \"Samantha Chan\"\n  },\n  {\n    \"CustomerId\": 327,\n    \"FullName\": \"Natalie Chan\"\n  },\n  {\n    \"CustomerId\": 291,\n    \"FullName\": \"Sarah Johnson\"\n  },\n  {\n    \"CustomerId\": 262,\n    \"FullName\": \"Elliott Park\"\n  },\n  {\n    \"CustomerId\": 235,\n    \"FullName\": \"Lana Park\"\n  },\n  {\n    \"CustomerId\": 59,\n    \"FullName\": \"Hannah Wu\"\n  },\n  {\n    \"CustomerId\": 311,\n    \"FullName\": \"Alexis Cunningham\"\n  },\n  {\n    \"CustomerId\": 180,\n    \"FullName\": \"Megan Bryant\"\n  },\n  {\n    \"CustomerId\": 347,\n    \"FullName\": \"Morgan Stevens\"\n  },\n  {\n    \"CustomerId\": 191,\n    \"FullName\": \"Evan Walters\"\n  },\n  {\n    \"CustomerId\": 13,\n    \"FullName\": \"Evelyn Hart\"\n  },\n  {\n    \"CustomerId\": 304,\n    \"FullName\": \"Rebecca Thompson\"\n  },\n  {\n    \"CustomerId\": 89,\n    \"FullName\": \"Zara Montgomery\"\n  },\n  {\n    \"CustomerId\": 201,\n    \"FullName\": \"Wendy Davis\"\n  },\n  {\n    \"CustomerId\": 176,\n    \"FullName\": \"Remy Thompson\"\n  },\n  {\n    \"CustomerId\": 142,\n    \"FullName\": \"Dr. Samantha Chen\"\n  },\n  {\n    \"CustomerId\": 254,\n    \"FullName\": \"Aria Kim\"\n  },\n  {\n    \"CustomerId\": 326,\n    \"FullName\": \"Harper Green\"\n  },\n  {\n    \"CustomerId\": 282,\n    \"FullName\": \"Lydia Chen\"\n  },\n  {\n    \"CustomerId\": 171,\n    \"FullName\": \"Riley Anderson\"\n  },\n  {\n    \"CustomerId\": 118,\n    \"FullName\": \"Oliver Cheng\"\n  },\n  {\n    \"CustomerId\": 366,\n    \"FullName\": \"Evelyn Morrison\"\n  },\n  {\n    \"CustomerId\": 373,\n    \"FullName\": \"Eliot Finley\"\n  },\n  {\n    \"CustomerId\": 112,\n    \"FullName\": \"Chandra Patel\"\n  },\n  {\n    \"CustomerId\": 358,\n    \"FullName\": \"Elena Sanchez\"\n  },\n  {\n    \"CustomerId\": 68,\n    \"FullName\": \"Marley Clarke\"\n  },\n  {\n    \"CustomerId\": 346,\n    \"FullName\": \"Stella Reynolds\"\n  },\n  {\n    \"CustomerId\": 292,\n    \"FullName\": \"Eliot Bennett\"\n  },\n  {\n    \"CustomerId\": 157,\n    \"FullName\": \"Megan Rivers\"\n  },\n  {\n    \"CustomerId\": 228,\n    \"FullName\": \"Kristen Landon\"\n  },\n  {\n    \"CustomerId\": 365,\n    \"FullName\": \"Hannah Reynolds\"\n  },\n  {\n    \"CustomerId\": 203,\n    \"FullName\": \"Ella Davies\"\n  },\n  {\n    \"CustomerId\": 135,\n    \"FullName\": \"Marissa Thompson\"\n  },\n  {\n    \"CustomerId\": 211,\n    \"FullName\": \"Marcella Bishop\"\n  },\n  {\n    \"CustomerId\": 213,\n    \"FullName\": \"Dr. Olivia Chen\"\n  },\n  {\n    \"CustomerId\": 199,\n    \"FullName\": \"Emerson Chang\"\n  },\n  {\n    \"CustomerId\": 280,\n    \"FullName\": \"Avery Matthews\"\n  },\n  {\n    \"CustomerId\": 337,\n    \"FullName\": \"Evelyn Rivera\"\n  },\n  {\n    \"CustomerId\": 320,\n    \"FullName\": \"Eleanor Davidson\"\n  },\n  {\n    \"CustomerId\": 273,\n    \"FullName\": \"Mila Jacobs\"\n  },\n  {\n    \"CustomerId\": 99,\n    \"FullName\": \"Megan Briggs\"\n  },\n  {\n    \"CustomerId\": 86,\n    \"FullName\": \"Hannah Chang\"\n  },\n  {\n    \"CustomerId\": 93,\n    \"FullName\": \"Erik Johnson\"\n  },\n  {\n    \"CustomerId\": 367,\n    \"FullName\": \"Evelyn MacKenzie\"\n  },\n  {\n    \"CustomerId\": 4,\n    \"FullName\": \"Alexandra Miller\"\n  },\n  {\n    \"CustomerId\": 85,\n    \"FullName\": \"Eva Thompson\"\n  },\n  {\n    \"CustomerId\": 323,\n    \"FullName\": \"Eleanor Chang\"\n  },\n  {\n    \"CustomerId\": 293,\n    \"FullName\": \"Janice Fitzgerald\"\n  },\n  {\n    \"CustomerId\": 11,\n    \"FullName\": \"Hannah Michaels\"\n  },\n  {\n    \"CustomerId\": 335,\n    \"FullName\": \"Isabella Caldwell\"\n  },\n  {\n    \"CustomerId\": 224,\n    \"FullName\": \"Alexis Bennett\"\n  },\n  {\n    \"CustomerId\": 103,\n    \"FullName\": \"Samantha Washington\"\n  },\n  {\n    \"CustomerId\": 140,\n    \"FullName\": \"Lila Richards\"\n  },\n  {\n    \"CustomerId\": 371,\n    \"FullName\": \"Samantha Chang\"\n  },\n  {\n    \"CustomerId\": 241,\n    \"FullName\": \"Bethany Reynolds\"\n  },\n  {\n    \"CustomerId\": 336,\n    \"FullName\": \"Eleanor Green\"\n  },\n  {\n    \"CustomerId\": 370,\n    \"FullName\": \"Avery Thompson\"\n  },\n  {\n    \"CustomerId\": 298,\n    \"FullName\": \"Eleanor Morse\"\n  },\n  {\n    \"CustomerId\": 229,\n    \"FullName\": \"Aiden Smith\"\n  },\n  {\n    \"CustomerId\": 5,\n    \"FullName\": \"Evan Thompson\"\n  },\n  {\n    \"CustomerId\": 218,\n    \"FullName\": \"Hannah Patel\"\n  },\n  {\n    \"CustomerId\": 178,\n    \"FullName\": \"Evelyn Harper\"\n  },\n  {\n    \"CustomerId\": 64,\n    \"FullName\": \"Evelyn Chen\"\n  },\n  {\n    \"CustomerId\": 40,\n    \"FullName\": \"Danielle Murphy\"\n  },\n  {\n    \"CustomerId\": 16,\n    \"FullName\": \"Marisol Perez\"\n  },\n  {\n    \"CustomerId\": 275,\n    \"FullName\": \"Evelyn Sullivan\"\n  },\n  {\n    \"CustomerId\": 240,\n    \"FullName\": \"Marissa Johnson\"\n  },\n  {\n    \"CustomerId\": 172,\n    \"FullName\": \"Alexandra Smith\"\n  },\n  {\n    \"CustomerId\": 234,\n    \"FullName\": \"Tara Nguyen\"\n  },\n  {\n    \"CustomerId\": 261,\n    \"FullName\": \"Julian Bennett\"\n  },\n  {\n    \"CustomerId\": 359,\n    \"FullName\": \"Evelyn Knight\"\n  },\n  {\n    \"CustomerId\": 286,\n    \"FullName\": \"Emerson Hayes\"\n  },\n  {\n    \"CustomerId\": 325,\n    \"FullName\": \"Natalie Blakely\"\n  },\n  {\n    \"CustomerId\": 78,\n    \"FullName\": \"Martha Reynolds\"\n  },\n  {\n    \"CustomerId\": 119,\n    \"FullName\": \"Avery Brooks\"\n  },\n  {\n    \"CustomerId\": 69,\n    \"FullName\": \"Dr. Abigail Reynolds\"\n  },\n  {\n    \"CustomerId\": 252,\n    \"FullName\": \"Dr. Alexandra Chen\"\n  },\n  {\n    \"CustomerId\": 354,\n    \"FullName\": \"Jasper Reynolds\"\n  },\n  {\n    \"CustomerId\": 47,\n    \"FullName\": \"Samantha Smith\"\n  },\n  {\n    \"CustomerId\": 39,\n    \"FullName\": \"Eleanor Liu\"\n  },\n  {\n    \"CustomerId\": 127,\n    \"FullName\": \"Avery Reynolds\"\n  },\n  {\n    \"CustomerId\": 165,\n    \"FullName\": \"Dexter Smith\"\n  },\n  {\n    \"CustomerId\": 158,\n    \"FullName\": \"Jordan Reynolds\"\n  },\n  {\n    \"CustomerId\": 107,\n    \"FullName\": \"Julian Kim\"\n  },\n  {\n    \"CustomerId\": 361,\n    \"FullName\": \"Maxine Robertson\"\n  },\n  {\n    \"CustomerId\": 223,\n    \"FullName\": \"Erika Matthews\"\n  },\n  {\n    \"CustomerId\": 15,\n    \"FullName\": \"Oliver Greene\"\n  },\n  {\n    \"CustomerId\": 348,\n    \"FullName\": \"Avery Chen\"\n  },\n  {\n    \"CustomerId\": 129,\n    \"FullName\": \"Sophie Jenkins\"\n  },\n  {\n    \"CustomerId\": 316,\n    \"FullName\": \"Ella Dawson\"\n  },\n  {\n    \"CustomerId\": 190,\n    \"FullName\": \"Lila Reynolds\"\n  },\n  {\n    \"CustomerId\": 90,\n    \"FullName\": \"Eleanor Langley\"\n  },\n  {\n    \"CustomerId\": 131,\n    \"FullName\": \"Alexis Rodriguez\"\n  },\n  {\n    \"CustomerId\": 321,\n    \"FullName\": \"Eleanor Chung\"\n  },\n  {\n    \"CustomerId\": 206,\n    \"FullName\": \"Cameron Jackson\"\n  },\n  {\n    \"CustomerId\": 343,\n    \"FullName\": \"Vivian Tilden\"\n  },\n  {\n    \"CustomerId\": 161,\n    \"FullName\": \"Liam Garcia\"\n  },\n  {\n    \"CustomerId\": 250,\n    \"FullName\": \"Lila Jameson\"\n  },\n  {\n    \"CustomerId\": 185,\n    \"FullName\": \"Olivia Park\"\n  },\n  {\n    \"CustomerId\": 207,\n    \"FullName\": \"Alanna Smith\"\n  },\n  {\n    \"CustomerId\": 345,\n    \"FullName\": \"Natalie Kim\"\n  },\n  {\n    \"CustomerId\": 231,\n    \"FullName\": \"Jenny Lee\"\n  },\n  {\n    \"CustomerId\": 295,\n    \"FullName\": \"Riley Chen\"\n  },\n  {\n    \"CustomerId\": 167,\n    \"FullName\": \"Samantha Lee\"\n  },\n  {\n    \"CustomerId\": 32,\n    \"FullName\": \"Evelyn Chang\"\n  },\n  {\n    \"CustomerId\": 379,\n    \"FullName\": \"Dr. Evelyn Nguyen\"\n  },\n  {\n    \"CustomerId\": 193,\n    \"FullName\": \"Sophie Martinez\"\n  },\n  {\n    \"CustomerId\": 210,\n    \"FullName\": \"Zara Smith\"\n  },\n  {\n    \"CustomerId\": 130,\n    \"FullName\": \"Mila Johnson\"\n  },\n  {\n    \"CustomerId\": 151,\n    \"FullName\": \"Evelyn Nguyen\"\n  },\n  {\n    \"CustomerId\": 74,\n    \"FullName\": \"Avery Johnson\"\n  },\n  {\n    \"CustomerId\": 232,\n    \"FullName\": \"Amelia Cooper\"\n  },\n  {\n    \"CustomerId\": 181,\n    \"FullName\": \"Megan Stevens\"\n  },\n  {\n    \"CustomerId\": 108,\n    \"FullName\": \"Talia Richardson\"\n  },\n  {\n    \"CustomerId\": 87,\n    \"FullName\": \"Evelyn Andrews\"\n  },\n  {\n    \"CustomerId\": 369,\n    \"FullName\": \"Samantha Patel\"\n  },\n  {\n    \"CustomerId\": 67,\n    \"FullName\": \"Hollis Davidson\"\n  },\n  {\n    \"CustomerId\": 155,\n    \"FullName\": \"Liam Reynolds\"\n  },\n  {\n    \"CustomerId\": 12,\n    \"FullName\": \"Eliot Chang\"\n  },\n  {\n    \"CustomerId\": 31,\n    \"FullName\": \"Eliana Jordan\"\n  },\n  {\n    \"CustomerId\": 202,\n    \"FullName\": \"Alicia Nguyen\"\n  },\n  {\n    \"CustomerId\": 149,\n    \"FullName\": \"Elena Chen\"\n  },\n  {\n    \"CustomerId\": 244,\n    \"FullName\": \"Evelyn Davidson\"\n  },\n  {\n    \"CustomerId\": 307,\n    \"FullName\": \"Evelyn Gray\"\n  },\n  {\n    \"CustomerId\": 253,\n    \"FullName\": \"Eliza Park\"\n  },\n  {\n    \"CustomerId\": 376,\n    \"FullName\": \"Lauren Smith\"\n  },\n  {\n    \"CustomerId\": 219,\n    \"FullName\": \"Abigail Chen\"\n  },\n  {\n    \"CustomerId\": 173,\n    \"FullName\": \"Benjamin Hargrove\"\n  },\n  {\n    \"CustomerId\": 182,\n    \"FullName\": \"Lindsay Bennett\"\n  },\n  {\n    \"CustomerId\": 63,\n    \"FullName\": \"Megan Nguyen\"\n  },\n  {\n    \"CustomerId\": 6,\n    \"FullName\": \"Evelyn Rivers\"\n  },\n  {\n    \"CustomerId\": 183,\n    \"FullName\": \"Lila Hernandez\"\n  },\n  {\n    \"CustomerId\": 28,\n    \"FullName\": \"Benjamin Marks\"\n  },\n  {\n    \"CustomerId\": 217,\n    \"FullName\": \"Lila Andrews\"\n  },\n  {\n    \"CustomerId\": 353,\n    \"FullName\": \"Megan O\\u0027Conner\"\n  },\n  {\n    \"CustomerId\": 38,\n    \"FullName\": \"Samantha Winters\"\n  },\n  {\n    \"CustomerId\": 299,\n    \"FullName\": \"Eliza Kim\"\n  },\n  {\n    \"CustomerId\": 222,\n    \"FullName\": \"Megan Park\"\n  },\n  {\n    \"CustomerId\": 27,\n    \"FullName\": \"Kai Romanov\"\n  },\n  {\n    \"CustomerId\": 53,\n    \"FullName\": \"Emily Chen\"\n  },\n  {\n    \"CustomerId\": 267,\n    \"FullName\": \"Evelyn Sinclair\"\n  },\n  {\n    \"CustomerId\": 290,\n    \"FullName\": \"Evan Miller\"\n  },\n  {\n    \"CustomerId\": 301,\n    \"FullName\": \"Lyla Bennett\"\n  },\n  {\n    \"CustomerId\": 54,\n    \"FullName\": \"Aiden Johnson\"\n  },\n  {\n    \"CustomerId\": 42,\n    \"FullName\": \"Samantha Greene\"\n  },\n  {\n    \"CustomerId\": 279,\n    \"FullName\": \"Jamie Fitzgerald\"\n  },\n  {\n    \"CustomerId\": 278,\n    \"FullName\": \"Megan Carter\"\n  },\n  {\n    \"CustomerId\": 319,\n    \"FullName\": \"Dylan Harlow\"\n  },\n  {\n    \"CustomerId\": 260,\n    \"FullName\": \"Elena Marshall\"\n  },\n  {\n    \"CustomerId\": 246,\n    \"FullName\": \"Dr. Sarah Kennedy\"\n  },\n  {\n    \"CustomerId\": 116,\n    \"FullName\": \"Marie Thompson\"\n  },\n  {\n    \"CustomerId\": 26,\n    \"FullName\": \"Samantha Reynolds\"\n  },\n  {\n    \"CustomerId\": 364,\n    \"FullName\": \"Ella Johnson\"\n  },\n  {\n    \"CustomerId\": 242,\n    \"FullName\": \"Lara Morales\"\n  },\n  {\n    \"CustomerId\": 143,\n    \"FullName\": \"Riley Johnson\"\n  },\n  {\n    \"CustomerId\": 136,\n    \"FullName\": \"Landon Nguyen\"\n  },\n  {\n    \"CustomerId\": 1,\n    \"FullName\": \"Lina Patel\"\n  },\n  {\n    \"CustomerId\": 209,\n    \"FullName\": \"Lindsey Marino\"\n  },\n  {\n    \"CustomerId\": 356,\n    \"FullName\": \"Caleb Johnson\"\n  },\n  {\n    \"CustomerId\": 159,\n    \"FullName\": \"Alexis Reynolds\"\n  },\n  {\n    \"CustomerId\": 123,\n    \"FullName\": \"Maia Chen\"\n  },\n  {\n    \"CustomerId\": 297,\n    \"FullName\": \"Evelyn Peterson\"\n  },\n  {\n    \"CustomerId\": 91,\n    \"FullName\": \"Liam Patel\"\n  },\n  {\n    \"CustomerId\": 24,\n    \"FullName\": \"Samantha Jacobs\"\n  },\n  {\n    \"CustomerId\": 177,\n    \"FullName\": \"Evan Monroe\"\n  },\n  {\n    \"CustomerId\": 125,\n    \"FullName\": \"Riley Clarkson\"\n  },\n  {\n    \"CustomerId\": 73,\n    \"FullName\": \"Evelyn Chan\"\n  },\n  {\n    \"CustomerId\": 3,\n    \"FullName\": \"Eleanor Montgomery\"\n  },\n  {\n    \"CustomerId\": 98,\n    \"FullName\": \"Ethan Reynolds\"\n  },\n  {\n    \"CustomerId\": 270,\n    \"FullName\": \"Jordan Smith\"\n  },\n  {\n    \"CustomerId\": 102,\n    \"FullName\": \"Lila Henderson\"\n  },\n  {\n    \"CustomerId\": 141,\n    \"FullName\": \"Eve Chen\"\n  },\n  {\n    \"CustomerId\": 174,\n    \"FullName\": \"Megan Johnson\"\n  },\n  {\n    \"CustomerId\": 208,\n    \"FullName\": \"Alexis Chen\"\n  },\n  {\n    \"CustomerId\": 51,\n    \"FullName\": \"Joanna Blackwood\"\n  },\n  {\n    \"CustomerId\": 243,\n    \"FullName\": \"Lila Summers\"\n  },\n  {\n    \"CustomerId\": 276,\n    \"FullName\": \"Sophia Hughes\"\n  },\n  {\n    \"CustomerId\": 331,\n    \"FullName\": \"Avery Cho\"\n  },\n  {\n    \"CustomerId\": 330,\n    \"FullName\": \"Avery Park\"\n  },\n  {\n    \"CustomerId\": 264,\n    \"FullName\": \"Samantha Parker\"\n  },\n  {\n    \"CustomerId\": 381,\n    \"FullName\": \"Kai Anderson\"\n  },\n  {\n    \"CustomerId\": 65,\n    \"FullName\": \"Lenny Petrov\"\n  },\n  {\n    \"CustomerId\": 306,\n    \"FullName\": \"Maxine Shaw\"\n  },\n  {\n    \"CustomerId\": 128,\n    \"FullName\": \"Evelyn Johnson\"\n  },\n  {\n    \"CustomerId\": 148,\n    \"FullName\": \"Avery Jennings\"\n  },\n  {\n    \"CustomerId\": 121,\n    \"FullName\": \"Eleanor Kim\"\n  },\n  {\n    \"CustomerId\": 352,\n    \"FullName\": \"Harper Johnson\"\n  },\n  {\n    \"CustomerId\": 29,\n    \"FullName\": \"Lila Chambers\"\n  },\n  {\n    \"CustomerId\": 41,\n    \"FullName\": \"Alexandra Thompson\"\n  },\n  {\n    \"CustomerId\": 333,\n    \"FullName\": \"Zara Patel\"\n  },\n  {\n    \"CustomerId\": 372,\n    \"FullName\": \"Emma Chen\"\n  },\n  {\n    \"CustomerId\": 294,\n    \"FullName\": \"Nicolette Adams\"\n  },\n  {\n    \"CustomerId\": 101,\n    \"FullName\": \"Toby Reynolds\"\n  },\n  {\n    \"CustomerId\": 97,\n    \"FullName\": \"Natalie Reynolds\"\n  },\n  {\n    \"CustomerId\": 113,\n    \"FullName\": \"Farrah Greene\"\n  },\n  {\n    \"CustomerId\": 342,\n    \"FullName\": \"Marissa Green\"\n  },\n  {\n    \"CustomerId\": 271,\n    \"FullName\": \"Samantha Winslow\"\n  },\n  {\n    \"CustomerId\": 220,\n    \"FullName\": \"Evelyn Jacobs\"\n  },\n  {\n    \"CustomerId\": 334,\n    \"FullName\": \"Eloise Park\"\n  },\n  {\n    \"CustomerId\": 309,\n    \"FullName\": \"Lindsay Abbott\"\n  },\n  {\n    \"CustomerId\": 227,\n    \"FullName\": \"Nathaniel McAllister\"\n  },\n  {\n    \"CustomerId\": 21,\n    \"FullName\": \"Megan Robertson\"\n  },\n  {\n    \"CustomerId\": 179,\n    \"FullName\": \"Samantha Jenkins\"\n  },\n  {\n    \"CustomerId\": 2,\n    \"FullName\": \"Ainsley Chan\"\n  },\n  {\n    \"CustomerId\": 110,\n    \"FullName\": \"Avery Chang\"\n  }\n]"
  },
  {
    "path": "seeddata/dev/evalquestions.json",
    "content": "[\n  {\n    \"QuestionId\": 1,\n    \"ProductId\": 158,\n    \"Question\": \"How to access essentials?\",\n    \"Answer\": \"Unzip the main compartment\"\n  },\n  {\n    \"QuestionId\": 2,\n    \"ProductId\": 199,\n    \"Question\": \"What are the overheating precautions?\",\n    \"Answer\": \"Do not leave in direct sunlight for extended periods.\"\n  },\n  {\n    \"QuestionId\": 3,\n    \"ProductId\": 99,\n    \"Question\": \"Hi there, I recently purchased the Summit 3000 Trekking Backpack and I\\u0027m having issues with the strap adjustment. Can you provide me with the specified torque value for the strap adjustment bolts?\",\n    \"Answer\": \"15-20 Nm\"\n  },\n  {\n    \"QuestionId\": 4,\n    \"ProductId\": 35,\n    \"Question\": \"What is included in the set?\",\n    \"Answer\": \"2-quart pot, 1-quart pot, 7.5-inch frying pan, 2 lids, Mesh carry bag\"\n  },\n  {\n    \"QuestionId\": 5,\n    \"ProductId\": 28,\n    \"Question\": \"How to turn on the purifier?\",\n    \"Answer\": \"Press and hold power button for 3 seconds.\"\n  },\n  {\n    \"QuestionId\": 6,\n    \"ProductId\": 51,\n    \"Question\": \"What does the warranty cover?\",\n    \"Answer\": \"Defects in materials or workmanship for one year\"\n  },\n  {\n    \"QuestionId\": 7,\n    \"ProductId\": 137,\n    \"Question\": \"Waterproof rating?\",\n    \"Answer\": \"IP67, 1 meter for 30 minutes\"\n  },\n  {\n    \"QuestionId\": 8,\n    \"ProductId\": 103,\n    \"Question\": \"How to use water pouches?\",\n    \"Answer\": \"Tear open the top and drink directly\"\n  },\n  {\n    \"QuestionId\": 9,\n    \"ProductId\": 108,\n    \"Question\": \"What precautions should be taken for placement?\",\n    \"Answer\": \"On a flat, stable surface\"\n  },\n  {\n    \"QuestionId\": 10,\n    \"ProductId\": 86,\n    \"Question\": \"Hi there, I just received my SOS Multitool Kit and the case is cracked. What should I do?\",\n    \"Answer\": \"Contact Survive All customer service for a replacement case.\"\n  },\n  {\n    \"QuestionId\": 11,\n    \"ProductId\": 26,\n    \"Question\": \"How do I attach the paddle shaft?\",\n    \"Answer\": \"Gently twist in a clockwise direction\"\n  },\n  {\n    \"QuestionId\": 12,\n    \"ProductId\": 157,\n    \"Question\": \"How to open waterproof casing?\",\n    \"Answer\": \"Press latch and slide panel\"\n  },\n  {\n    \"QuestionId\": 13,\n    \"ProductId\": 52,\n    \"Question\": \"GPS limitations?\",\n    \"Answer\": \"May be affected by environmental conditions.\"\n  },\n  {\n    \"QuestionId\": 14,\n    \"ProductId\": 148,\n    \"Question\": \"Machine washing instructions?\",\n    \"Answer\": \"Use gentle cycle with cold water and mild detergent.\"\n  },\n  {\n    \"QuestionId\": 15,\n    \"ProductId\": 163,\n    \"Question\": \"How should the Stealth Cam 500 battery be charged?\",\n    \"Answer\": \"Using the provided charger only\"\n  },\n  {\n    \"QuestionId\": 16,\n    \"ProductId\": 24,\n    \"Question\": \"How do I get in the sleeping bag?\",\n    \"Answer\": \"Enter the sleeping bag, then zip it up.\"\n  },\n  {\n    \"QuestionId\": 17,\n    \"ProductId\": 21,\n    \"Question\": \"Hi there, my WeatherGuard Pro 3000 doesn\\u0027t seem to be charging properly. I\\u0027ve checked the power bank and the USB cable, but it\\u0027s still not working. Can you help?\",\n    \"Answer\": \"Make sure the power bank is turned on and connected to your device.\"\n  },\n  {\n    \"QuestionId\": 18,\n    \"ProductId\": 192,\n    \"Question\": \"Hi there, I recently purchased the Venture 45L Backpack and I\\u0027m wondering how to clean it properly. Can I use any kind of detergent and water?\",\n    \"Answer\": \"Use a mild detergent and lukewarm water to spot clean the exterior of the backpack.\"\n  },\n  {\n    \"QuestionId\": 19,\n    \"ProductId\": 91,\n    \"Question\": \"Moisture Content Acceptance Criteria?\",\n    \"Answer\": \"The moisture content level must be 0%\"\n  },\n  {\n    \"QuestionId\": 20,\n    \"ProductId\": 138,\n    \"Question\": \"What is included in the Ultimate Survival Kit 3000?\",\n    \"Answer\": \"Red and black multi-function survival knife, compact and powerful LED flashlight with adjustable beam, emergency whistle and signal mirror, green and orange paracord, water purification tablets and water storage pouch, mini first aid kit, aluminum emergency blanket, multi-tool with pliers, screwdrivers, and wire cutters, compass, and fire starter.\"\n  },\n  {\n    \"QuestionId\": 21,\n    \"ProductId\": 97,\n    \"Question\": \"How to access screwdriver?\",\n    \"Answer\": \"Unfold appropriately labeled handle.\"\n  },\n  {\n    \"QuestionId\": 22,\n    \"ProductId\": 70,\n    \"Question\": \"Hi, I just bought the Juice Junkie Solar Power Bank and I\\u0027m having trouble measuring the USB output voltage. Can you guide me through the steps to measure the voltage?\",\n    \"Answer\": \"Connect USB multimeter, activate, and record the reading.\"\n  },\n  {\n    \"QuestionId\": 23,\n    \"ProductId\": 200,\n    \"Question\": \"What is the Raptor Tactical Backpack equipped with?\",\n    \"Answer\": \"MOLLE webbing\"\n  },\n  {\n    \"QuestionId\": 24,\n    \"ProductId\": 125,\n    \"Question\": \"What advanced procedures can be performed?\",\n    \"Answer\": \"Suturing, wound cleaning, and minor surgery\"\n  },\n  {\n    \"QuestionId\": 25,\n    \"ProductId\": 16,\n    \"Question\": \"How to configure the system?\",\n    \"Answer\": \"Select the appropriate filter cartridge based on water quality analysis results.\"\n  },\n  {\n    \"QuestionId\": 26,\n    \"ProductId\": 89,\n    \"Question\": \"How to clean?\",\n    \"Answer\": \"Use non-abrasive sponge with mild dish soap.\"\n  },\n  {\n    \"QuestionId\": 27,\n    \"ProductId\": 148,\n    \"Question\": \"How long is the warranty?\",\n    \"Answer\": \"Limited Lifetime Warranty\"\n  },\n  {\n    \"QuestionId\": 28,\n    \"ProductId\": 104,\n    \"Question\": \"Filtration efficiency?\",\n    \"Answer\": \"99.9%\"\n  },\n  {\n    \"QuestionId\": 29,\n    \"ProductId\": 141,\n    \"Question\": \"How to troubleshoot fire starter failure?\",\n    \"Answer\": \"Check Ferrocerium Rod, Inspect Striker, Test Under Different Conditions\"\n  },\n  {\n    \"QuestionId\": 30,\n    \"ProductId\": 154,\n    \"Question\": \"Hi there, I\\u0027m interested in the GuardianGear GPS Personal Locator. Can you tell me the dimensions and weight of the device?\",\n    \"Answer\": \"Length: 3.5 inches, Width: 2 inches, Thickness: 0.6 inches, Weight: 3.5 ounces\"\n  },\n  {\n    \"QuestionId\": 31,\n    \"ProductId\": 169,\n    \"Question\": \"Is it dishwasher safe?\",\n    \"Answer\": \"Yes\"\n  },\n  {\n    \"QuestionId\": 32,\n    \"ProductId\": 50,\n    \"Question\": \"how to clean the hydration system?\",\n    \"Answer\": \"Refer to the \\u0027Cleaning and Maintenance\\u0027 section in the user manual.\"\n  },\n  {\n    \"QuestionId\": 33,\n    \"ProductId\": 146,\n    \"Question\": \"How to take Energy Boost 500?\",\n    \"Answer\": \"Follow 6 meticulous steps in the manual.\"\n  },\n  {\n    \"QuestionId\": 34,\n    \"ProductId\": 144,\n    \"Question\": \"How to secure gear?\",\n    \"Answer\": \"Attach to gear loops using clips or loops\"\n  },\n  {\n    \"QuestionId\": 35,\n    \"ProductId\": 92,\n    \"Question\": \"Hello, I just received my AquaPure Portable Water Filter. Should I rinse the filter cartridge before using it for the first time?\",\n    \"Answer\": \"Yes, rinse under clean, potable water for 10 seconds.\"\n  },\n  {\n    \"QuestionId\": 36,\n    \"ProductId\": 99,\n    \"Question\": \"How to measure tensile strength?\",\n    \"Answer\": \"Use a tensile testing machine\"\n  },\n  {\n    \"QuestionId\": 37,\n    \"ProductId\": 192,\n    \"Question\": \"How to clean?\",\n    \"Answer\": \"Spot clean with mild detergent and lukewarm water.\"\n  },\n  {\n    \"QuestionId\": 38,\n    \"ProductId\": 110,\n    \"Question\": \"Do PowerFuel Energy Bars contain gluten?\",\n    \"Answer\": \"No, PowerFuel Energy Bars are gluten-free.\"\n  },\n  {\n    \"QuestionId\": 39,\n    \"ProductId\": 91,\n    \"Question\": \"Hi there, I recently purchased the Stormguard WeatherShield Pro Jacket and I want to make sure I\\u0027m taking care of it properly. Can you tell me how to perform the moisture retention analysis?\",\n    \"Answer\": \"Select a representative area of the jacket, use a moisture analyzer, and compare the results with acceptable thresholds.\"\n  },\n  {\n    \"QuestionId\": 40,\n    \"ProductId\": 23,\n    \"Question\": \"Hey there, I recently purchased the EZ Camp QuickShade Portable Shelter and I\\u0027m wondering how to take it down properly. Can you provide some guidance?\",\n    \"Answer\": \"Carefully lower the shelter to a comfortable height and collapse the telescoping poles by pressing the release buttons.\"\n  },\n  {\n    \"QuestionId\": 41,\n    \"ProductId\": 135,\n    \"Question\": \"What connectivity options does the WideView 360 have?\",\n    \"Answer\": \"Wi-Fi and Bluetooth\"\n  },\n  {\n    \"QuestionId\": 42,\n    \"ProductId\": 148,\n    \"Question\": \"How to fix zipper stuck?\",\n    \"Answer\": \"Gently pull in opposite direction.\"\n  },\n  {\n    \"QuestionId\": 43,\n    \"ProductId\": 46,\n    \"Question\": \"How to position the solar cooker?\",\n    \"Answer\": \"Adjust the cooker\\u0027s position throughout the day\"\n  },\n  {\n    \"QuestionId\": 44,\n    \"ProductId\": 157,\n    \"Question\": \"Hi there, I just got the 360X Action Camera and I\\u0027m having trouble figuring out how to start recording a video. Can you help?\",\n    \"Answer\": \"Press the Shutter button.\"\n  },\n  {\n    \"QuestionId\": 45,\n    \"ProductId\": 111,\n    \"Question\": \"How to clean the reservoir?\",\n    \"Answer\": \"Rinse with warm, soapy water.\"\n  },\n  {\n    \"QuestionId\": 46,\n    \"ProductId\": 144,\n    \"Question\": \"What is not covered by the warranty?\",\n    \"Answer\": \"Damage caused by misuse, abuse, neglect, improper maintenance, alterations, accidents, or normal wear and tear\"\n  },\n  {\n    \"QuestionId\": 47,\n    \"ProductId\": 133,\n    \"Question\": \"What is the hydration compatibility feature?\",\n    \"Answer\": \"Stay hydrated during outdoor excursions\"\n  },\n  {\n    \"QuestionId\": 48,\n    \"ProductId\": 106,\n    \"Question\": \"How to store the sleeping bag?\",\n    \"Answer\": \"In a cool, dry place\"\n  },\n  {\n    \"QuestionId\": 49,\n    \"ProductId\": 198,\n    \"Question\": \"Hi there, I just bought the WildBeat Portable Bluetooth Speaker and I\\u0027m having trouble pairing it with my phone. Can you walk me through the steps to pair the speaker with my device?\",\n    \"Answer\": \"Press and hold power button until LED flashes blue and red. Select \\u0027WildBeat\\u0027 from Bluetooth settings on your device.\"\n  },\n  {\n    \"QuestionId\": 50,\n    \"ProductId\": 45,\n    \"Question\": \"How to check battery level?\",\n    \"Answer\": \"Press power button.\"\n  },\n  {\n    \"QuestionId\": 51,\n    \"ProductId\": 65,\n    \"Question\": \"Difficulty opening tools?\",\n    \"Answer\": \"Check for rust or debris\"\n  },\n  {\n    \"QuestionId\": 52,\n    \"ProductId\": 130,\n    \"Question\": \"Charging time?\",\n    \"Answer\": \"Approximately 3 hours\"\n  },\n  {\n    \"QuestionId\": 53,\n    \"ProductId\": 22,\n    \"Question\": \"How to install rain cover?\",\n    \"Answer\": \"Follow steps 1-4 in manual.\"\n  },\n  {\n    \"QuestionId\": 54,\n    \"ProductId\": 131,\n    \"Question\": \"How to fix camera not turning on?\",\n    \"Answer\": \"Reset by removing batteries and reinserting\"\n  },\n  {\n    \"QuestionId\": 55,\n    \"ProductId\": 160,\n    \"Question\": \"Hi there, I recently purchased the Trailblazer GPS Navigation Device and I\\u0027m having trouble pairing it with my smartphone. Can you walk me through the steps to pair it with my phone?\",\n    \"Answer\": \"Download Geotrack app, enable Bluetooth, follow on-screen instructions.\"\n  },\n  {\n    \"QuestionId\": 56,\n    \"ProductId\": 46,\n    \"Question\": \"What to do if SunSpot not reaching high temperatures?\",\n    \"Answer\": \"Extend reflectors, check for obstructions, adjust position\"\n  },\n  {\n    \"QuestionId\": 57,\n    \"ProductId\": 160,\n    \"Question\": \"How to clean device?\",\n    \"Answer\": \"Use soft, dry cloth.\"\n  },\n  {\n    \"QuestionId\": 58,\n    \"ProductId\": 43,\n    \"Question\": \"Hi, I just received my NightOps Tactical Flashlight and I can\\u0027t find the spare O-rings. Are they supposed to be included?\",\n    \"Answer\": \"Yes, spare O-rings are included.\"\n  },\n  {\n    \"QuestionId\": 59,\n    \"ProductId\": 199,\n    \"Question\": \"Hello, I just bought the SunShift 100W Solar Charger. I need to know the maximum power output of this charger. Can you please provide that information?\",\n    \"Answer\": \"100W\"\n  },\n  {\n    \"QuestionId\": 60,\n    \"ProductId\": 178,\n    \"Question\": \"Hi there, I just bought the PowerBar Pro 2021 and I\\u0027m wondering how I should store it to maintain its quality. Can I keep it in the fridge?\",\n    \"Answer\": \"Store on a dry and cool place, not in the fridge\"\n  },\n  {\n    \"QuestionId\": 61,\n    \"ProductId\": 176,\n    \"Question\": \"How to take a photo?\",\n    \"Answer\": \"Press power button, select mode, frame shot, press shutter button, review photo\"\n  },\n  {\n    \"QuestionId\": 62,\n    \"ProductId\": 89,\n    \"Question\": \"How to assemble the cookware set?\",\n    \"Answer\": \"Follow easy steps in manual.\"\n  },\n  {\n    \"QuestionId\": 63,\n    \"ProductId\": 12,\n    \"Question\": \"Hi there, I just bought the TrailGPS 5000 and wanted to know if I can use any charger to recharge the battery or if I have to use the one provided. Thanks!\",\n    \"Answer\": \"Always use the provided charger\"\n  },\n  {\n    \"QuestionId\": 64,\n    \"ProductId\": 35,\n    \"Question\": \"How to clean the cookware?\",\n    \"Answer\": \"Use mild dish soap and soft sponge.\"\n  },\n  {\n    \"QuestionId\": 65,\n    \"ProductId\": 183,\n    \"Question\": \"How to clean the pot?\",\n    \"Answer\": \"Hand wash only with mild soap and warm water.\"\n  },\n  {\n    \"QuestionId\": 66,\n    \"ProductId\": 197,\n    \"Question\": \"How to troubleshoot stove ignition?\",\n    \"Answer\": \"Check fuel canister, inspect ignition switch\"\n  },\n  {\n    \"QuestionId\": 67,\n    \"ProductId\": 200,\n    \"Question\": \"How to properly adjust shoulder straps?\",\n    \"Answer\": \"Utilize the adjustable shoulder straps\"\n  },\n  {\n    \"QuestionId\": 68,\n    \"ProductId\": 155,\n    \"Question\": \"How to initiate charging?\",\n    \"Answer\": \"Press the power button.\"\n  },\n  {\n    \"QuestionId\": 69,\n    \"ProductId\": 195,\n    \"Question\": \"hydration bladder compatibility\",\n    \"Answer\": \"compatible with most 2-liter bladders\"\n  },\n  {\n    \"QuestionId\": 70,\n    \"ProductId\": 192,\n    \"Question\": \"Front pocket features?\",\n    \"Answer\": \"Map, compass, snacks storage\"\n  },\n  {\n    \"QuestionId\": 71,\n    \"ProductId\": 81,\n    \"Question\": \"How to attach to climbing rope?\",\n    \"Answer\": \"1. Locate the belay loop, 2. Use a locking carabiner, 3. Double-check\"\n  },\n  {\n    \"QuestionId\": 72,\n    \"ProductId\": 39,\n    \"Question\": \"How do I fold the tent?\",\n    \"Answer\": \"Press and hold red folding levers.\"\n  },\n  {\n    \"QuestionId\": 73,\n    \"ProductId\": 58,\n    \"Question\": \"SOS button not functioning?\",\n    \"Answer\": \"Try system reset or contact support.\"\n  },\n  {\n    \"QuestionId\": 74,\n    \"ProductId\": 137,\n    \"Question\": \"Hi there, I\\u0027m interested in purchasing the WildBeat Pro DJ Controller. Can you tell me about the care and storage recommendations for this product?\",\n    \"Answer\": \"Store in cool, dry place away from direct sunlight and extreme temperatures.\"\n  },\n  {\n    \"QuestionId\": 75,\n    \"ProductId\": 132,\n    \"Question\": \"How to troubleshoot rod not casting properly?\",\n    \"Answer\": \"Check for Line Tangles, Inspect Rod Guides, Verify Reel Mounting, Adjust Casting Technique, Rod Maintenance\"\n  },\n  {\n    \"QuestionId\": 76,\n    \"ProductId\": 134,\n    \"Question\": \"Hello, I just received my SolarFire 2000 and I\\u0027m trying to set it up. Can you tell me how to assemble the stove and solar panel?\",\n    \"Answer\": \"Unfold solar panel, position in sunlight, unfold stove, attach pot securely.\"\n  },\n  {\n    \"QuestionId\": 77,\n    \"ProductId\": 77,\n    \"Question\": \"Hi there, I just bought the Solar Charger 3000X and I\\u0027m not sure how to check the battery status. Can you help?\",\n    \"Answer\": \"Press the power button.\"\n  },\n  {\n    \"QuestionId\": 78,\n    \"ProductId\": 79,\n    \"Question\": \"How should the Adventure Pro Camera be stored?\",\n    \"Answer\": \"Cool, dry place away from direct sunlight\"\n  },\n  {\n    \"QuestionId\": 79,\n    \"ProductId\": 76,\n    \"Question\": \"How do I power on Wilderness DJ Pro?\",\n    \"Answer\": \"Locate the power button on the console.\"\n  },\n  {\n    \"QuestionId\": 80,\n    \"ProductId\": 167,\n    \"Question\": \"What is the Backpacker Cookware Set designed for?\",\n    \"Answer\": \"Outdoor use in backcountry environments\"\n  },\n  {\n    \"QuestionId\": 81,\n    \"ProductId\": 35,\n    \"Question\": \"How should I clean the cookware?\",\n    \"Answer\": \"Use a soft sponge or cloth to gently scrub off any food residue.\"\n  },\n  {\n    \"QuestionId\": 82,\n    \"ProductId\": 144,\n    \"Question\": \"Hi there, I just bought the ProLite Climbing Harness and I\\u0027m not sure how to properly attach it to the climbing rope. Can you give me some guidance?\",\n    \"Answer\": \"Clip the carabiner through the belay loop and ensure it is properly locked before starting your climb.\"\n  },\n  {\n    \"QuestionId\": 83,\n    \"ProductId\": 48,\n    \"Question\": \"how to reset speaker?\",\n    \"Answer\": \"press and hold power button for 10 seconds\"\n  },\n  {\n    \"QuestionId\": 84,\n    \"ProductId\": 64,\n    \"Question\": \"how to activate purification process?\",\n    \"Answer\": \"Press and hold power button.\"\n  },\n  {\n    \"QuestionId\": 85,\n    \"ProductId\": 69,\n    \"Question\": \"Hi, I just received my Summit Step Alpine Explorer Hiking Boots and I\\u0027m not sure if I got all the components mentioned in the manual. Can you confirm what should be included in the packaging?\",\n    \"Answer\": \"You should receive an extra pair of laces and an information booklet.\"\n  },\n  {\n    \"QuestionId\": 86,\n    \"ProductId\": 35,\n    \"Question\": \"How to clean after use?\",\n    \"Answer\": \"Wash with mild dish soap.\"\n  },\n  {\n    \"QuestionId\": 87,\n    \"ProductId\": 95,\n    \"Question\": \"Hello, I recently purchased the Summit 4-Season Sleeping Bag and noticed some clumping of insulation. What\\u0027s the best way to fix this issue?\",\n    \"Answer\": \"Fluff the sleeping bag\"\n  },\n  {\n    \"QuestionId\": 88,\n    \"ProductId\": 31,\n    \"Question\": \"What items are included in the box?\",\n    \"Answer\": \"Nomad Camping Stove, fuel canister, user manual\"\n  },\n  {\n    \"QuestionId\": 89,\n    \"ProductId\": 176,\n    \"Question\": \"how to stop video recording?\",\n    \"Answer\": \"Press the \\u0022Record\\u0022 button again.\"\n  },\n  {\n    \"QuestionId\": 90,\n    \"ProductId\": 77,\n    \"Question\": \"Charging via USB steps?\",\n    \"Answer\": \"Connect USB cable to power source, then to charger\\u0027s USB port\"\n  },\n  {\n    \"QuestionId\": 91,\n    \"ProductId\": 74,\n    \"Question\": \"How should I clean the hammock?\",\n    \"Answer\": \"Hand wash with mild soap and water\"\n  },\n  {\n    \"QuestionId\": 92,\n    \"ProductId\": 63,\n    \"Question\": \"How to turn on lights?\",\n    \"Answer\": \"Press power button once\"\n  },\n  {\n    \"QuestionId\": 93,\n    \"ProductId\": 192,\n    \"Question\": \"What items can be stored in the front pocket?\",\n    \"Answer\": \"Map, compass, snacks\"\n  },\n  {\n    \"QuestionId\": 94,\n    \"ProductId\": 152,\n    \"Question\": \"Hi, I just received my Emergency Beacon Light from Sure Survive and I\\u0027m not sure if all the items are included. Can you confirm what should be in the package?\",\n    \"Answer\": \"Emergency Beacon Light, User Manual, Lanyard\"\n  },\n  {\n    \"QuestionId\": 95,\n    \"ProductId\": 112,\n    \"Question\": \"Dear support, can you explain how to adjust the fit of the Trailblazer Carbon Fiber Mountain Bike Helmet using the dial-fit adjustment system?\",\n    \"Answer\": \"Utilize the *ultra-refined* dial-fit adjustment system located at the back of the helmet to customize the fit to your precise liking.\"\n  },\n  {\n    \"QuestionId\": 96,\n    \"ProductId\": 90,\n    \"Question\": \"What percentage of waterborne bacteria does the pump remove?\",\n    \"Answer\": \"99.9999%\"\n  },\n  {\n    \"QuestionId\": 97,\n    \"ProductId\": 100,\n    \"Question\": \"Hi, I recently purchased the Ridge Runner Hydration Pack. How should I clean the water reservoir to prevent mold and mildew growth?\",\n    \"Answer\": \"Empty and Rinse, Use Mild Soap, Dry Thoroughly\"\n  },\n  {\n    \"QuestionId\": 98,\n    \"ProductId\": 44,\n    \"Question\": \"Hi there, I just bought the RescueTech Emergency Kit from Life Guard X. Can I reuse the emergency blanket?\",\n    \"Answer\": \"No, the emergency blanket is designed for single use only.\"\n  },\n  {\n    \"QuestionId\": 99,\n    \"ProductId\": 153,\n    \"Question\": \"What are the post-use diagnostic procedures?\",\n    \"Answer\": \"Energy Output Analysis\"\n  },\n  {\n    \"QuestionId\": 100,\n    \"ProductId\": 71,\n    \"Question\": \"Hello, I recently purchased the Trailcom Signal Booster 2000 and I wanted to know how to get warranty service if I need it. Can you please provide me with the details?\",\n    \"Answer\": \"Contact our customer service team via website or hotline.\"\n  },\n  {\n    \"QuestionId\": 101,\n    \"ProductId\": 44,\n    \"Question\": \"How to use emergency blanket?\",\n    \"Answer\": \"Unfold and wrap around body\"\n  },\n  {\n    \"QuestionId\": 102,\n    \"ProductId\": 56,\n    \"Question\": \"Hi there, I just purchased the Naptime 5000 Sleeping Bag and I\\u0027m wondering what temperature it is designed to keep me warm in?\",\n    \"Answer\": \"Designed for temperatures as low as 20\\u00B0F\"\n  },\n  {\n    \"QuestionId\": 103,\n    \"ProductId\": 43,\n    \"Question\": \"How to activate strobe mode?\",\n    \"Answer\": \"Double-click side switch\"\n  },\n  {\n    \"QuestionId\": 104,\n    \"ProductId\": 26,\n    \"Question\": \"Proper Shaft Length Adjustment?\",\n    \"Answer\": \"Adjust the shaft to suit your height.\"\n  },\n  {\n    \"QuestionId\": 105,\n    \"ProductId\": 64,\n    \"Question\": \"How to clean the purifier?\",\n    \"Answer\": \"Follow these simple steps.\"\n  },\n  {\n    \"QuestionId\": 106,\n    \"ProductId\": 4,\n    \"Question\": \"How many adults can the emergency tent accommodate?\",\n    \"Answer\": \"Two adults\"\n  },\n  {\n    \"QuestionId\": 107,\n    \"ProductId\": 127,\n    \"Question\": \"Warranty period?\",\n    \"Answer\": \"One year from purchase\"\n  },\n  {\n    \"QuestionId\": 108,\n    \"ProductId\": 184,\n    \"Question\": \"Hi there, I recently bought the LumenX Rechargeable Headlamp and I want to make sure I store it properly. Can you tell me the recommended storage instructions?\",\n    \"Answer\": \"Store in a cool, dry place away from direct sunlight\"\n  },\n  {\n    \"QuestionId\": 109,\n    \"ProductId\": 85,\n    \"Question\": \"How should I store the kit?\",\n    \"Answer\": \"In a cool, dry place away from direct sunlight and moisture.\"\n  },\n  {\n    \"QuestionId\": 110,\n    \"ProductId\": 154,\n    \"Question\": \"SOS button not working?\",\n    \"Answer\": \"Check if button is pressed firmly for a few seconds.\"\n  },\n  {\n    \"QuestionId\": 111,\n    \"ProductId\": 46,\n    \"Question\": \"How to clean SunSpot Solar Cooker?\",\n    \"Answer\": \"Use soft, non-abrasive cloth with mild soap and water\"\n  },\n  {\n    \"QuestionId\": 112,\n    \"ProductId\": 42,\n    \"Question\": \"MOLLE system location?\",\n    \"Answer\": \"Front, sides, shoulder straps\"\n  },\n  {\n    \"QuestionId\": 113,\n    \"ProductId\": 148,\n    \"Question\": \"how to assemble?\",\n    \"Answer\": \"Follow the steps in the manual.\"\n  },\n  {\n    \"QuestionId\": 114,\n    \"ProductId\": 26,\n    \"Question\": \"How should I clean the paddle?\",\n    \"Answer\": \"Use mild soap and warm water.\"\n  },\n  {\n    \"QuestionId\": 115,\n    \"ProductId\": 73,\n    \"Question\": \"What autonomous flight modes does the drone have?\",\n    \"Answer\": \"Follow Me and Waypoint Navigation\"\n  },\n  {\n    \"QuestionId\": 116,\n    \"ProductId\": 39,\n    \"Question\": \"Waterproof?\",\n    \"Answer\": \"The tent has an advanced waterproof design.\"\n  },\n  {\n    \"QuestionId\": 117,\n    \"ProductId\": 185,\n    \"Question\": \"How to clean the exterior?\",\n    \"Answer\": \"Use a damp cloth or mild detergent\"\n  },\n  {\n    \"QuestionId\": 118,\n    \"ProductId\": 74,\n    \"Question\": \"How to pack the suspension straps?\",\n    \"Answer\": \"Coil and store in designated pocket\"\n  },\n  {\n    \"QuestionId\": 119,\n    \"ProductId\": 176,\n    \"Question\": \"How to take a photo?\",\n    \"Answer\": \"Follow steps 1-5.\"\n  },\n  {\n    \"QuestionId\": 120,\n    \"ProductId\": 18,\n    \"Question\": \"Hi there, I recently purchased the Trailblazer 40L Backpack and I\\u0027m wondering how to adjust the shoulder straps. Can you provide some guidance?\",\n    \"Answer\": \"Pull the adjustment buckle to loosen or tighten the straps to your desired length.\"\n  },\n  {\n    \"QuestionId\": 121,\n    \"ProductId\": 119,\n    \"Question\": \"Hi there, I just bought the GloTech GloBeam 1000 High-Powered LED Headlamp and I\\u0027m not sure how to turn it on. Can you help?\",\n    \"Answer\": \"Press the button once to activate the high-powered LED light.\"\n  },\n  {\n    \"QuestionId\": 122,\n    \"ProductId\": 46,\n    \"Question\": \"What are the safety precautions for assembly and disassembly?\",\n    \"Answer\": \"Ensure all parts are securely in place\"\n  },\n  {\n    \"QuestionId\": 123,\n    \"ProductId\": 48,\n    \"Question\": \"How to clean?\",\n    \"Answer\": \"Wipe with soft, dry cloth.\"\n  },\n  {\n    \"QuestionId\": 124,\n    \"ProductId\": 121,\n    \"Question\": \"How to pair with smartphone?\",\n    \"Answer\": \"Follow steps in app menu.\"\n  },\n  {\n    \"QuestionId\": 125,\n    \"ProductId\": 13,\n    \"Question\": \"Hi there, I just bought the PopUp Shelter 2.0 and I\\u0027m having trouble setting it up. Can you give me some tips on how to ensure the poles are correctly aligned with the designated sleeves on the shelter fabric?\",\n    \"Answer\": \"Ensure that the poles are correctly aligned with the designated sleeves.\"\n  },\n  {\n    \"QuestionId\": 126,\n    \"ProductId\": 100,\n    \"Question\": \"how many pockets?\",\n    \"Answer\": \"5 pockets\"\n  },\n  {\n    \"QuestionId\": 127,\n    \"ProductId\": 195,\n    \"Question\": \"What size bladder fits?\",\n    \"Answer\": \"Most standard 2-liter bladders\"\n  },\n  {\n    \"QuestionId\": 128,\n    \"ProductId\": 114,\n    \"Question\": \"Hi, I recently purchased the JXE WildBeat Wireless Waterproof Speaker and I wanted to know how long the warranty lasts for?\",\n    \"Answer\": \"1-year from the date of purchase\"\n  },\n  {\n    \"QuestionId\": 129,\n    \"ProductId\": 20,\n    \"Question\": \"Hi there, I just bought the TrekTracker GPS Watch and I\\u0027m wondering what the rugged design feature means. Can you explain?\",\n    \"Answer\": \"Robust and durable construction\"\n  },\n  {\n    \"QuestionId\": 130,\n    \"ProductId\": 192,\n    \"Question\": \"Hi there, I just purchased the Hiker\\u0027s Haven Venture 45L Backpack and I want to make sure I store it properly. Can you give me any tips on how to store it when not in use?\",\n    \"Answer\": \"Empty all compartments and pockets, avoid compressed storage for extended periods, and use a breathable storage bag.\"\n  },\n  {\n    \"QuestionId\": 131,\n    \"ProductId\": 165,\n    \"Question\": \"What should be used to secure the shelter to the ground?\",\n    \"Answer\": \"Stakes and guylines\"\n  },\n  {\n    \"QuestionId\": 132,\n    \"ProductId\": 86,\n    \"Question\": \"Where is the fish scaler located?\",\n    \"Answer\": \"Near the compass\"\n  },\n  {\n    \"QuestionId\": 133,\n    \"ProductId\": 127,\n    \"Question\": \"how to replace water filter?\",\n    \"Answer\": \"Follow detailed steps in manual.\"\n  },\n  {\n    \"QuestionId\": 134,\n    \"ProductId\": 108,\n    \"Question\": \"solar exposure?\",\n    \"Answer\": \"Position in direct sunlight for optimal performance.\"\n  },\n  {\n    \"QuestionId\": 135,\n    \"ProductId\": 103,\n    \"Question\": \"Hi, I just bought the Survival Kit 5000 and I noticed it includes 10 high-energy emergency food bars. Can you tell me more about the shelf life of these bars?\",\n    \"Answer\": \"Up to 5 years\"\n  },\n  {\n    \"QuestionId\": 136,\n    \"ProductId\": 170,\n    \"Question\": \"How to replace the filter?\",\n    \"Answer\": \"Follow the steps in the manual.\"\n  },\n  {\n    \"QuestionId\": 137,\n    \"ProductId\": 145,\n    \"Question\": \"How to use flashlight?\",\n    \"Answer\": \"Press and hold power button for 3 seconds.\"\n  },\n  {\n    \"QuestionId\": 138,\n    \"ProductId\": 78,\n    \"Question\": \"What maintenance tasks are recommended?\",\n    \"Answer\": \"Inspect seals, check battery, lubricate moving parts, inspect propeller, check for hull damage\"\n  },\n  {\n    \"QuestionId\": 139,\n    \"ProductId\": 196,\n    \"Question\": \"How to power on the watch?\",\n    \"Answer\": \"Press and hold power button for 3 seconds\"\n  },\n  {\n    \"QuestionId\": 140,\n    \"ProductId\": 98,\n    \"Question\": \"Can I calibrate the altimeter myself?\",\n    \"Answer\": \"Do not calibrate the altimeter.\"\n  },\n  {\n    \"QuestionId\": 141,\n    \"ProductId\": 187,\n    \"Question\": \"How to power on?\",\n    \"Answer\": \"Press and hold power button.\"\n  },\n  {\n    \"QuestionId\": 142,\n    \"ProductId\": 51,\n    \"Question\": \"How to use the knife safely?\",\n    \"Answer\": \"Use slow and steady motions.\"\n  },\n  {\n    \"QuestionId\": 143,\n    \"ProductId\": 55,\n    \"Question\": \"How to mark a waypoint?\",\n    \"Answer\": \"Touch the \\u0027Mark\\u0027 button \\uD83D\\uDCCD\\uD83D\\uDD34 and then touch the location on the map\"\n  },\n  {\n    \"QuestionId\": 144,\n    \"ProductId\": 122,\n    \"Question\": \"How to charge AdventureCam 4K?\",\n    \"Answer\": \"Connect USB cable and plug into power source\"\n  },\n  {\n    \"QuestionId\": 145,\n    \"ProductId\": 161,\n    \"Question\": \"How should I clean the chair?\",\n    \"Answer\": \"Avoid contact with liquids, dry clean only, avoid direct sunlight\"\n  },\n  {\n    \"QuestionId\": 146,\n    \"ProductId\": 51,\n    \"Question\": \"What does the warranty cover?\",\n    \"Answer\": \"Defects in materials or workmanship for one year\"\n  },\n  {\n    \"QuestionId\": 147,\n    \"ProductId\": 54,\n    \"Question\": \"Hi there, I recently purchased the AvalanchePro Ski Backpack from PowderPeak and I\\u0027m having trouble fitting my avalanche gear in the designated compartment. What should I do?\",\n    \"Answer\": \"Make sure you are properly securing your avalanche shovel, probe, and beacon in the designated compartments. If they still don\\u0027t fit, double-check the size of your gear and compare it to the size of the compartments.\"\n  },\n  {\n    \"QuestionId\": 148,\n    \"ProductId\": 91,\n    \"Question\": \"What does the jacket block out?\",\n    \"Answer\": \"Wind and cold air\"\n  },\n  {\n    \"QuestionId\": 149,\n    \"ProductId\": 50,\n    \"Question\": \"How to fill reservoir?\",\n    \"Answer\": \"Unscrew, fill, screw back on\"\n  },\n  {\n    \"QuestionId\": 150,\n    \"ProductId\": 110,\n    \"Question\": \"How should I store PowerFuel Energy Bars?\",\n    \"Answer\": \"Embrace profound insight into the micronutrients.\"\n  },\n  {\n    \"QuestionId\": 151,\n    \"ProductId\": 145,\n    \"Question\": \"How long is the warranty?\",\n    \"Answer\": \"1-year limited warranty\"\n  },\n  {\n    \"QuestionId\": 152,\n    \"ProductId\": 128,\n    \"Question\": \"How do I clean the AquaBottle Pro?\",\n    \"Answer\": \"Unscrew lid, wash with warm, soapy water, air dry.\"\n  },\n  {\n    \"QuestionId\": 153,\n    \"ProductId\": 81,\n    \"Question\": \"How do I put on the harness?\",\n    \"Answer\": \"Lay harness on ground, step into leg loops, fasten waistbelt, adjust leg loops.\"\n  },\n  {\n    \"QuestionId\": 154,\n    \"ProductId\": 149,\n    \"Question\": \"How to measure strap tension?\",\n    \"Answer\": \"Use a calibrated tension gauge.\"\n  },\n  {\n    \"QuestionId\": 155,\n    \"ProductId\": 70,\n    \"Question\": \"Hi there, I just bought the Solar Power Bank 10000mAh and I\\u0027m curious about its dimensions. Can you tell me how big and heavy it is?\",\n    \"Answer\": \"Dimensions: 155mm x 80mm x 15mm, Weight: 250g\"\n  },\n  {\n    \"QuestionId\": 156,\n    \"ProductId\": 94,\n    \"Question\": \"How to replace knife blade?\",\n    \"Answer\": \"Unscrew and replace with new blade\"\n  },\n  {\n    \"QuestionId\": 157,\n    \"ProductId\": 29,\n    \"Question\": \"How to check battery level?\",\n    \"Answer\": \"Press battery level indicator button\"\n  },\n  {\n    \"QuestionId\": 158,\n    \"ProductId\": 18,\n    \"Question\": \"Hydration reservoir compatibility?\",\n    \"Answer\": \"Simply insert reservoir into dedicated compartment.\"\n  },\n  {\n    \"QuestionId\": 159,\n    \"ProductId\": 4,\n    \"Question\": \"What is included in the first aid supplies?\",\n    \"Answer\": \"Bandages, gauze, tape, antiseptics, ointment\"\n  },\n  {\n    \"QuestionId\": 160,\n    \"ProductId\": 179,\n    \"Question\": \"how to adjust paddle length?\",\n    \"Answer\": \"locate the black locking button\"\n  },\n  {\n    \"QuestionId\": 161,\n    \"ProductId\": 187,\n    \"Question\": \"What is the battery type?\",\n    \"Answer\": \"Lithium polymer\"\n  },\n  {\n    \"QuestionId\": 162,\n    \"ProductId\": 154,\n    \"Question\": \"Hello, I just purchased the GPS Personal Locator from GuardianGear. Can you tell me about the live tracking feature?\",\n    \"Answer\": \"The GPS Personal Locator has live tracking feature.\"\n  },\n  {\n    \"QuestionId\": 163,\n    \"ProductId\": 157,\n    \"Question\": \"How to switch to photo mode?\",\n    \"Answer\": \"Press Mode button.\"\n  },\n  {\n    \"QuestionId\": 164,\n    \"ProductId\": 111,\n    \"Question\": \"How to fill the reservoir?\",\n    \"Answer\": \"Open the top closure and fill with water or beverage.\"\n  },\n  {\n    \"QuestionId\": 165,\n    \"ProductId\": 119,\n    \"Question\": \"How many lighting modes?\",\n    \"Answer\": \"Three\"\n  },\n  {\n    \"QuestionId\": 166,\n    \"ProductId\": 167,\n    \"Question\": \"Hello, I just bought the Trail Chef Backpacker Cookware Set and I want to make sure I\\u0027m using it correctly. Can you tell me the steps for using the cookware?\",\n    \"Answer\": \"Before use, inspect the cookware for any damage or defects. If you notice any issues, please do not use the product and contact our customer service team immediately.\"\n  },\n  {\n    \"QuestionId\": 167,\n    \"ProductId\": 76,\n    \"Question\": \"How should I clean the Wilderness DJ Pro?\",\n    \"Answer\": \"Soft, damp cloth with non-abrasive solution\"\n  },\n  {\n    \"QuestionId\": 168,\n    \"ProductId\": 128,\n    \"Question\": \"Hi, I recently purchased the AquaBottle Pro and I\\u0027m having trouble with the insulation performance. What can I do to improve it?\",\n    \"Answer\": \"Try the following: [insulation tips from manual]\"\n  },\n  {\n    \"QuestionId\": 169,\n    \"ProductId\": 186,\n    \"Question\": \"How to use the probe during a rescue operation?\",\n    \"Answer\": \"Follow the steps in the manual\"\n  },\n  {\n    \"QuestionId\": 170,\n    \"ProductId\": 105,\n    \"Question\": \"How to troubleshoot slow charging?\",\n    \"Answer\": \"Expose to direct sunlight, check cable \\u0026 adapter compatibility, disconnect unnecessary devices.\"\n  },\n  {\n    \"QuestionId\": 171,\n    \"ProductId\": 88,\n    \"Question\": \"how to store RapidFlow Kayak Paddle?\",\n    \"Answer\": \"Store in cool, dry place away from sharp objects\"\n  },\n  {\n    \"QuestionId\": 172,\n    \"ProductId\": 167,\n    \"Question\": \"Hi there, I just bought the Backpacker Cookware Set by Trail Chef. Can you tell me where it is safe to use this set?\",\n    \"Answer\": \"Outdoor use in backcountry environments\"\n  },\n  {\n    \"QuestionId\": 173,\n    \"ProductId\": 74,\n    \"Question\": \"Maximum weight capacity?\",\n    \"Answer\": \"300 lbs\"\n  },\n  {\n    \"QuestionId\": 174,\n    \"ProductId\": 56,\n    \"Question\": \"Hi there, I recently purchased the Naptime 5000 Sleeping Bag and I\\u0027m wondering how to properly clean and dry it after each use. Can you provide me with some guidance?\",\n    \"Answer\": \"Spot clean with mild detergent, hand wash, and lay flat to dry away from direct sunlight and heat sources.\"\n  },\n  {\n    \"QuestionId\": 175,\n    \"ProductId\": 64,\n    \"Question\": \"What should I do if I notice leaks from the purifier?\",\n    \"Answer\": \"Check seals and O-rings, tighten connections, ensure valves are closed securely.\"\n  },\n  {\n    \"QuestionId\": 176,\n    \"ProductId\": 94,\n    \"Question\": \"How to replace knife blade?\",\n    \"Answer\": \"Unscrew and replace with new blade.\"\n  },\n  {\n    \"QuestionId\": 177,\n    \"ProductId\": 74,\n    \"Question\": \"Hi there, just bought the Naturehaven Ultra-Light Hammock and want to make sure I set it up correctly. What is the maximum weight capacity for this hammock?\",\n    \"Answer\": \"Maximum weight capacity is 300 lbs (136 kg).\"\n  },\n  {\n    \"QuestionId\": 178,\n    \"ProductId\": 180,\n    \"Question\": \"Hi there, I just bought the ExtremeCast 5000 and I\\u0027m having trouble with casting. Can you tell me the key technique for achieving optimal casting performance with this reel?\",\n    \"Answer\": \"Proper Gripping, Smooth Release, Adjusting Tension, Using the Line Guide, Testing Wind Conditions, Practicing Patience\"\n  },\n  {\n    \"QuestionId\": 179,\n    \"ProductId\": 129,\n    \"Question\": \"How do you receive a fax?\",\n    \"Answer\": \"Press \\u0027Accept\\u0027 or \\u0027Reject\\u0027 button\"\n  },\n  {\n    \"QuestionId\": 180,\n    \"ProductId\": 111,\n    \"Question\": \"How to adjust the valve?\",\n    \"Answer\": \"Turn it clockwise to decrease the flow\"\n  },\n  {\n    \"QuestionId\": 181,\n    \"ProductId\": 29,\n    \"Question\": \"How to check battery level?\",\n    \"Answer\": \"Press battery level indicator button\"\n  },\n  {\n    \"QuestionId\": 182,\n    \"ProductId\": 54,\n    \"Question\": \"Hi, I just bought the AvalanchePro Ski Backpack and I want to know how to make a warranty claim. Can you help?\",\n    \"Answer\": \"Contact our customer service team with proof of purchase and a detailed description of the issue.\"\n  },\n  {\n    \"QuestionId\": 183,\n    \"ProductId\": 144,\n    \"Question\": \"How to store the harness?\",\n    \"Answer\": \"Coil the harness neatly, store in ventilated area, avoid sharp objects.\"\n  },\n  {\n    \"QuestionId\": 184,\n    \"ProductId\": 64,\n    \"Question\": \"Hi there, I recently purchased the AquaFusion Portable Water Purifier 1000 and I\\u0027m wondering how to clean it. Can you provide me with the cleaning instructions?\",\n    \"Answer\": \"Fill a container with clean water. Add mild dish soap. Remove and scrub filter. Rinse and air dry filter. Wipe exterior with damp cloth.\"\n  },\n  {\n    \"QuestionId\": 185,\n    \"ProductId\": 75,\n    \"Question\": \"How to connect to the app?\",\n    \"Answer\": \"Make sure Bluetooth is on and follow app instructions.\"\n  },\n  {\n    \"QuestionId\": 186,\n    \"ProductId\": 125,\n    \"Question\": \"Hi there, I recently purchased the MediKit Xpress and I want to make sure I\\u0027m storing it properly. Can you tell me where I should keep it when not in use?\",\n    \"Answer\": \"Store the kit in a cool, dry place away from direct sunlight and extreme temperatures.\"\n  },\n  {\n    \"QuestionId\": 187,\n    \"ProductId\": 44,\n    \"Question\": \"How to use the whistle?\",\n    \"Answer\": \"Blow into the whistle with a firm and steady breath to produce a loud, high-pitched sound.\"\n  },\n  {\n    \"QuestionId\": 188,\n    \"ProductId\": 123,\n    \"Question\": \"What does error code SC3000-002 indicate?\",\n    \"Answer\": \"Low Battery\"\n  },\n  {\n    \"QuestionId\": 189,\n    \"ProductId\": 195,\n    \"Question\": \"Hello, I recently purchased the Trekker 30L Backpack and I\\u0027d like to know how to keep it clean. Do you have any recommendations for cleaning and maintenance?\",\n    \"Answer\": \"Follow simple cleaning instructions\"\n  },\n  {\n    \"QuestionId\": 190,\n    \"ProductId\": 98,\n    \"Question\": \"Altimeter accuracy limitations?\",\n    \"Answer\": \"Changes in weather and altitude can affect accuracy\"\n  },\n  {\n    \"QuestionId\": 191,\n    \"ProductId\": 131,\n    \"Question\": \"How to transfer footage?\",\n    \"Answer\": \"Open weatherproof cover, remove SD card, insert into computer\\u0027s SD card reader\"\n  },\n  {\n    \"QuestionId\": 192,\n    \"ProductId\": 151,\n    \"Question\": \"Hi there, I\\u0027m having trouble igniting the fire starter on my Survivor Multi-Tool. I\\u0027ve checked the position and made sure the surface is dry, but it\\u0027s still not working. What else can I do?\",\n    \"Answer\": \"Strike firmly and consistently along the length of the fire starter rod.\"\n  },\n  {\n    \"QuestionId\": 193,\n    \"ProductId\": 68,\n    \"Question\": \"How should I store my Trailblazer Hiking Shoes?\",\n    \"Answer\": \"Cool, dry place away from direct sunlight\"\n  },\n  {\n    \"QuestionId\": 194,\n    \"ProductId\": 114,\n    \"Question\": \"How long is the warranty?\",\n    \"Answer\": \"1-year limited warranty\"\n  },\n  {\n    \"QuestionId\": 195,\n    \"ProductId\": 149,\n    \"Question\": \"Hello, I just purchased the Thirsttrek AquaFlow Pro and I want to make sure I\\u0027m using it correctly. Can you tell me how to conduct flow rate calibration?\",\n    \"Answer\": \"Use a precision flow meter and tubing to create a closed loop system with the reservoir and bite valve.\"\n  },\n  {\n    \"QuestionId\": 196,\n    \"ProductId\": 196,\n    \"Question\": \"How to customize data screens?\",\n    \"Answer\": \"Navigate to settings and select \\u0027Data Screens\\u0027.\"\n  },\n  {\n    \"QuestionId\": 197,\n    \"ProductId\": 5,\n    \"Question\": \"What should be inspected before each use?\",\n    \"Answer\": \"Inspect for signs of wear, damage, or deterioration\"\n  },\n  {\n    \"QuestionId\": 198,\n    \"ProductId\": 188,\n    \"Question\": \"What are the dimensions?\",\n    \"Answer\": \"26.5 x 21.2 x 2.5 inches\"\n  },\n  {\n    \"QuestionId\": 199,\n    \"ProductId\": 33,\n    \"Question\": \"night vision not working?\",\n    \"Answer\": \"Confirm night vision setting is enabled\"\n  },\n  {\n    \"QuestionId\": 200,\n    \"ProductId\": 19,\n    \"Question\": \"How to access diagnostic mode?\",\n    \"Answer\": \"Press and hold power button for 10 seconds\"\n  },\n  {\n    \"QuestionId\": 201,\n    \"ProductId\": 64,\n    \"Question\": \"How do you drink from the purifier?\",\n    \"Answer\": \"Tilt the purifier and drink from the spout.\"\n  },\n  {\n    \"QuestionId\": 202,\n    \"ProductId\": 67,\n    \"Question\": \"Hi there, I have a nut allergy and I recently purchased the Nutritech Energy Bars Variety Pack. Can I consume them safely?\",\n    \"Answer\": \"The energy bars contain nuts and are manufactured in a facility that also processes other nuts. Therefore, if you have a nut allergy, it is recommended to consult with a healthcare professional before consuming these bars.\"\n  },\n  {\n    \"QuestionId\": 203,\n    \"ProductId\": 92,\n    \"Question\": \"Maximum submersion depth?\",\n    \"Answer\": \"1 meter\"\n  },\n  {\n    \"QuestionId\": 204,\n    \"ProductId\": 69,\n    \"Question\": \"What features do the boots have?\",\n    \"Answer\": \"Waterproof, breathable, aggressive tread, shock-absorbing midsole, reinforced toe and heel caps\"\n  },\n  {\n    \"QuestionId\": 205,\n    \"ProductId\": 180,\n    \"Question\": \"Hi, I bought the ExtremeCast 5000 reel and noticed some corrosion on the components. What should I do to address this issue?\",\n    \"Answer\": \"Thoroughly clean and dry the affected components using a soft cloth and a mild cleaning solution. Apply a light coating of reel lubricant to prevent future corrosion. Store the reel in a dry, cool environment when not in use.\"\n  },\n  {\n    \"QuestionId\": 206,\n    \"ProductId\": 61,\n    \"Question\": \"How to send a message?\",\n    \"Answer\": \"Press \\u0027Message\\u0027 button, select \\u0027New Message\\u0027, type message, press \\u0027Send\\u0027.\"\n  },\n  {\n    \"QuestionId\": 207,\n    \"ProductId\": 51,\n    \"Question\": \"Hi there, I just bought the Survival Pro Multi-Tool and I\\u0027m wondering how to access the knife. Can you give me some tips for using it safely?\",\n    \"Answer\": \"Carefully slide out the knife from its slot and use slow and steady motions to prevent injuries.\"\n  },\n  {\n    \"QuestionId\": 208,\n    \"ProductId\": 172,\n    \"Question\": \"How to fix loose grips?\",\n    \"Answer\": \"Contact customer support for assistance.\"\n  },\n  {\n    \"QuestionId\": 209,\n    \"ProductId\": 91,\n    \"Question\": \"How to conduct pre-use diagnostic check?\",\n    \"Answer\": \"Follow steps in manual\"\n  },\n  {\n    \"QuestionId\": 210,\n    \"ProductId\": 74,\n    \"Question\": \"Hi, I recently purchased the Naturehaven Ultra-Light Hammock and I\\u0027m not sure how to properly store it. Can you provide some guidance on how to pack and store the hammock?\",\n    \"Answer\": \"Store the hammock in a cool, dry place away from direct sunlight.\"\n  },\n  {\n    \"QuestionId\": 211,\n    \"ProductId\": 132,\n    \"Question\": \"How to resolve a stuck reel?\",\n    \"Answer\": \"Check for Line Tangles, Inspect Reel Handle, Reel Lubrication, Verify Drag System, Professional Service\"\n  },\n  {\n    \"QuestionId\": 212,\n    \"ProductId\": 124,\n    \"Question\": \"What should I do before using the SurvivalPro 2000?\",\n    \"Answer\": \"Read the Manual\"\n  },\n  {\n    \"QuestionId\": 213,\n    \"ProductId\": 75,\n    \"Question\": \"How to activate the beacon?\",\n    \"Answer\": \"Press and hold power button for 3 seconds\"\n  },\n  {\n    \"QuestionId\": 214,\n    \"ProductId\": 60,\n    \"Question\": \"How to fill the bottle?\",\n    \"Answer\": \"Unscrew the leak-proof lid, pour in water, then securely reattach the lid.\"\n  },\n  {\n    \"QuestionId\": 215,\n    \"ProductId\": 70,\n    \"Question\": \"What is the battery capacity?\",\n    \"Answer\": \"10000mAh\"\n  },\n  {\n    \"QuestionId\": 216,\n    \"ProductId\": 82,\n    \"Question\": \"What is included in the first aid section?\",\n    \"Answer\": \"Adhesive bandages, antiseptic wipes, ibuprofen, first aid guide\"\n  },\n  {\n    \"QuestionId\": 217,\n    \"ProductId\": 174,\n    \"Question\": \"How to enable Wi-Fi?\",\n    \"Answer\": \"Swipe down from the top of touchscreen.\"\n  },\n  {\n    \"QuestionId\": 218,\n    \"ProductId\": 136,\n    \"Question\": \"How many lights indicate full battery?\",\n    \"Answer\": \"4\"\n  },\n  {\n    \"QuestionId\": 219,\n    \"ProductId\": 192,\n    \"Question\": \"Hi, I just bought the Hiker\\u0027s Haven Venture 45L Backpack and I want to make sure I store it properly. Can you tell me how to store it to prevent damage and maintain its shape?\",\n    \"Answer\": \"Empty all compartments, avoid compression, and use the included storage bag for long-term storage.\"\n  },\n  {\n    \"QuestionId\": 220,\n    \"ProductId\": 179,\n    \"Question\": \"How to adjust footrests?\",\n    \"Answer\": \"Position and use locking mechanism.\"\n  },\n  {\n    \"QuestionId\": 221,\n    \"ProductId\": 125,\n    \"Question\": \"How to provide basic wound care?\",\n    \"Answer\": \"Cleanse with alcohol wipe, apply antibiotic, cover with bandage\"\n  },\n  {\n    \"QuestionId\": 222,\n    \"ProductId\": 177,\n    \"Question\": \"How to pack up?\",\n    \"Answer\": \"Remove Stakes, Collapse Poles, Detach Rainfly, Fold Shelter\"\n  },\n  {\n    \"QuestionId\": 223,\n    \"ProductId\": 93,\n    \"Question\": \"How to clean the stove?\",\n    \"Answer\": \"Use soft, damp cloth.\"\n  },\n  {\n    \"QuestionId\": 224,\n    \"ProductId\": 22,\n    \"Question\": \"How to access pockets?\",\n    \"Answer\": \"Locate and open the zipper or buckle.\"\n  },\n  {\n    \"QuestionId\": 225,\n    \"ProductId\": 17,\n    \"Question\": \"What ventilation technology does the jacket feature?\",\n    \"Answer\": \"Advanced ventilation technology\"\n  },\n  {\n    \"QuestionId\": 226,\n    \"ProductId\": 9,\n    \"Question\": \"Hi there, I recently purchased the AltitudeShield Pro and I want to know if I can return it if it doesn\\u0027t work at high altitudes?\",\n    \"Answer\": \"No, the AltitudeShield Pro cannot be returned if used in high-altitude environments.\"\n  },\n  {\n    \"QuestionId\": 227,\n    \"ProductId\": 75,\n    \"Question\": \"How to charge?\",\n    \"Answer\": \"Follow simple steps with USB cable.\"\n  },\n  {\n    \"QuestionId\": 228,\n    \"ProductId\": 39,\n    \"Question\": \"How to fold the tent?\",\n    \"Answer\": \"Press red folding levers and push down.\"\n  },\n  {\n    \"QuestionId\": 229,\n    \"ProductId\": 72,\n    \"Question\": \"How to adjust sensitivity?\",\n    \"Answer\": \"Turn knob clockwise to increase, counterclockwise to decrease\"\n  },\n  {\n    \"QuestionId\": 230,\n    \"ProductId\": 86,\n    \"Question\": \"Hi, just received my SOS Multitool Kit from Survive All. How do I use the fire starter to create fire?\",\n    \"Answer\": \"Hold the metal rod against the striker at a 45-degree angle and apply firm pressure to produce sparks.\"\n  },\n  {\n    \"QuestionId\": 231,\n    \"ProductId\": 51,\n    \"Question\": \"How to access the knife?\",\n    \"Answer\": \"Slide out from main compartment\"\n  },\n  {\n    \"QuestionId\": 232,\n    \"ProductId\": 73,\n    \"Question\": \"How to perform pre-flight checklist?\",\n    \"Answer\": \"Follow the steps in the manual\"\n  },\n  {\n    \"QuestionId\": 233,\n    \"ProductId\": 167,\n    \"Question\": \"Cleaning instructions?\",\n    \"Answer\": \"Use mild detergent and warm water, avoid abrasive agents.\"\n  },\n  {\n    \"QuestionId\": 234,\n    \"ProductId\": 18,\n    \"Question\": \"How to clean the backpack?\",\n    \"Answer\": \"Shake off loose dirt, wipe with damp cloth, spot clean with mild detergent, rinse, air dry\"\n  },\n  {\n    \"QuestionId\": 235,\n    \"ProductId\": 15,\n    \"Question\": \"How to maintain AdventurePro 1000?\",\n    \"Answer\": \"Follow maintenance guidelines.\"\n  },\n  {\n    \"QuestionId\": 236,\n    \"ProductId\": 92,\n    \"Question\": \"What does the warranty exclude?\",\n    \"Answer\": \"Misuse, negligence, accidents, unauthorized modifications, failure to follow instructions, normal wear and tear\"\n  },\n  {\n    \"QuestionId\": 237,\n    \"ProductId\": 46,\n    \"Question\": \"How to position the Solar Cooker?\",\n    \"Answer\": \"Place in direct sunlight\"\n  },\n  {\n    \"QuestionId\": 238,\n    \"ProductId\": 51,\n    \"Question\": \"how to start a fire?\",\n    \"Answer\": \"Follow the simple steps in the manual.\"\n  },\n  {\n    \"QuestionId\": 239,\n    \"ProductId\": 82,\n    \"Question\": \"What first aid supplies are included?\",\n    \"Answer\": \"adhesive bandages, antiseptic wipes, ibuprofen tablets, first aid guide\"\n  },\n  {\n    \"QuestionId\": 240,\n    \"ProductId\": 87,\n    \"Question\": \"Adjusting the chin strap steps?\",\n    \"Answer\": \"1. Place on head  2. Tighten or loosen  3. Check secure\"\n  },\n  {\n    \"QuestionId\": 241,\n    \"ProductId\": 99,\n    \"Question\": \"What technical support is available?\",\n    \"Answer\": \"Refer to www.hikewise.com/summit3000/support\"\n  },\n  {\n    \"QuestionId\": 242,\n    \"ProductId\": 45,\n    \"Question\": \"How to activate LED light?\",\n    \"Answer\": \"Press power button twice\"\n  },\n  {\n    \"QuestionId\": 243,\n    \"ProductId\": 47,\n    \"Question\": \"How should the bars be stored?\",\n    \"Answer\": \"At room temperature, in a cool and dry environment\"\n  },\n  {\n    \"QuestionId\": 244,\n    \"ProductId\": 26,\n    \"Question\": \"What safety equipment is recommended?\",\n    \"Answer\": \"Wear a Personal Flotation Device (PFD)\"\n  },\n  {\n    \"QuestionId\": 245,\n    \"ProductId\": 163,\n    \"Question\": \"Hi, I recently purchased the Wildwatch Stealth Cam 500 for wildlife photography. Can I use it for hunting as well?\",\n    \"Answer\": \"Do not use the camera for hunting.\"\n  },\n  {\n    \"QuestionId\": 246,\n    \"ProductId\": 174,\n    \"Question\": \"how to clean lens?\",\n    \"Answer\": \"Use microfiber cloth\"\n  },\n  {\n    \"QuestionId\": 247,\n    \"ProductId\": 67,\n    \"Question\": \"Hi, I just purchased the Nutritech Energy Bars Variety Pack and I want to know how to store them to maintain freshness. Can you provide some guidelines?\",\n    \"Answer\": \"Store in a cool, dry place away from direct sunlight and in their original packaging or an airtight container.\"\n  },\n  {\n    \"QuestionId\": 248,\n    \"ProductId\": 31,\n    \"Question\": \"What is the warranty claim procedure?\",\n    \"Answer\": \"Contact customer service at support@wanderstove.com\"\n  },\n  {\n    \"QuestionId\": 249,\n    \"ProductId\": 121,\n    \"Question\": \"How to care for battery?\",\n    \"Answer\": \"Fully charge before each use, avoid overcharging, store partially charged for long periods.\"\n  },\n  {\n    \"QuestionId\": 250,\n    \"ProductId\": 25,\n    \"Question\": \"What safety precautions should I follow?\",\n    \"Answer\": \"Perform thorough inspection, wear proper PPE\"\n  },\n  {\n    \"QuestionId\": 251,\n    \"ProductId\": 84,\n    \"Question\": \"How to reset GPS?\",\n    \"Answer\": \"Hold down GPS button for 10 seconds\"\n  },\n  {\n    \"QuestionId\": 252,\n    \"ProductId\": 81,\n    \"Question\": \"How to put on Summit X harness?\",\n    \"Answer\": \"Follow the simple instructions provided in the manual.\"\n  },\n  {\n    \"QuestionId\": 253,\n    \"ProductId\": 168,\n    \"Question\": \"How to clean exterior?\",\n    \"Answer\": \"Use damp, lint-free cloth\"\n  },\n  {\n    \"QuestionId\": 254,\n    \"ProductId\": 45,\n    \"Question\": \"Troubleshooting guide?\",\n    \"Answer\": \"Refer to troubleshooting guide.\"\n  },\n  {\n    \"QuestionId\": 255,\n    \"ProductId\": 117,\n    \"Question\": \"Hi there, I was wondering if the AdventurePro Off-Grid Satellite Communicator has a texting feature?\",\n    \"Answer\": \"No, the texting feature is disabled.\"\n  },\n  {\n    \"QuestionId\": 256,\n    \"ProductId\": 197,\n    \"Question\": \"How to troubleshoot stove igniting issue?\",\n    \"Answer\": \"Check fuel canister and ignition switch\"\n  },\n  {\n    \"QuestionId\": 257,\n    \"ProductId\": 129,\n    \"Question\": \"How to troubleshoot no power?\",\n    \"Answer\": \"Check battery and power button.\"\n  },\n  {\n    \"QuestionId\": 258,\n    \"ProductId\": 39,\n    \"Question\": \"Hi there, I\\u0027m interested in the Shelter Scape Instant Pop-Up Tent. Can you tell me about its ventilation system?\",\n    \"Answer\": \"State-of-the-art ventilation system for optimal airflow.\"\n  },\n  {\n    \"QuestionId\": 259,\n    \"ProductId\": 24,\n    \"Question\": \"How to clean the sleeping bag?\",\n    \"Answer\": \"Spot clean with damp cloth and mild soap, or use front-loading washing machine with gentle cycle.\"\n  },\n  {\n    \"QuestionId\": 260,\n    \"ProductId\": 114,\n    \"Question\": \"Bluetooth range?\",\n    \"Answer\": \"Approximately 30 feet\"\n  },\n  {\n    \"QuestionId\": 261,\n    \"ProductId\": 175,\n    \"Question\": \"How to clean?\",\n    \"Answer\": \"Use soft, dry cloth. No liquid cleaners.\"\n  },\n  {\n    \"QuestionId\": 262,\n    \"ProductId\": 39,\n    \"Question\": \"Hi there, I just bought the Shelter Scape Instant Pop-Up Tent and I\\u0027m wondering how to fold it for storage. Can you give me some tips?\",\n    \"Answer\": \"Press and hold the red folding levers while pushing the top of the tent downwards.\"\n  },\n  {\n    \"QuestionId\": 263,\n    \"ProductId\": 31,\n    \"Question\": \"What components are included in the box?\",\n    \"Answer\": \"Nomad Camping Stove, Fuel canister, User manual\"\n  },\n  {\n    \"QuestionId\": 264,\n    \"ProductId\": 87,\n    \"Question\": \"How to adjust visor angle?\",\n    \"Answer\": \"Follow steps 1 and 2.\"\n  },\n  {\n    \"QuestionId\": 265,\n    \"ProductId\": 63,\n    \"Question\": \"What is included in the box?\",\n    \"Answer\": \"Solar panel, LED light string, ground stake, user manual\"\n  },\n  {\n    \"QuestionId\": 266,\n    \"ProductId\": 114,\n    \"Question\": \"Hi, I just got the WildBeat Wireless Waterproof Speaker and I want to make sure I store it properly. How should I store it to prolong its lifespan and maintain its performance?\",\n    \"Answer\": \"Store in cool, dry place away from direct sunlight and extreme temperatures. Fully charge battery before storing for extended period.\"\n  },\n  {\n    \"QuestionId\": 267,\n    \"ProductId\": 40,\n    \"Question\": \"How to turn on?\",\n    \"Answer\": \"Press and hold power button for 2 seconds\"\n  },\n  {\n    \"QuestionId\": 268,\n    \"ProductId\": 116,\n    \"Question\": \"Hi, I just bought the UltraLite 2-Person Backpacking Tent and I\\u0027m not sure how to secure it for windy conditions. Can you provide some guidelines?\",\n    \"Answer\": \"Use the provided guy lines and adjustable tensioners for a tight and secure pitch.\"\n  },\n  {\n    \"QuestionId\": 269,\n    \"ProductId\": 128,\n    \"Question\": \"How do I fill the bottle?\",\n    \"Answer\": \"Unscrew the leak-proof cap and pour in your beverage.\"\n  },\n  {\n    \"QuestionId\": 270,\n    \"ProductId\": 108,\n    \"Question\": \"How to adjust sun angle?\",\n    \"Answer\": \"Position stove to align with sun\"\n  },\n  {\n    \"QuestionId\": 271,\n    \"ProductId\": 104,\n    \"Question\": \"How often to replace filter?\",\n    \"Answer\": \"Rated for 500 liters.\"\n  },\n  {\n    \"QuestionId\": 272,\n    \"ProductId\": 132,\n    \"Question\": \"How to clean the rod?\",\n    \"Answer\": \"Remove Excess Dirt and Debris, Use Mild Soap and Water\"\n  },\n  {\n    \"QuestionId\": 273,\n    \"ProductId\": 167,\n    \"Question\": \"Hi there, I just purchased the Trail Chef Backpacker Cookware Set and I want to make sure I\\u0027m using it correctly. Can you provide me with the steps for using the cookware set?\",\n    \"Answer\": \"Inspect for damage, ensure cookware is clean and dry, use on stable surface, use handles when hot, allow to cool before cleaning\"\n  },\n  {\n    \"QuestionId\": 274,\n    \"ProductId\": 163,\n    \"Question\": \"Can I update the firmware myself?\",\n    \"Answer\": \"No, must be done by technician\"\n  },\n  {\n    \"QuestionId\": 275,\n    \"ProductId\": 124,\n    \"Question\": \"How to clean?\",\n    \"Answer\": \"Soft, damp cloth\"\n  },\n  {\n    \"QuestionId\": 276,\n    \"ProductId\": 99,\n    \"Question\": \"What is the maximum load capacity?\",\n    \"Answer\": \"30-35 kg\"\n  },\n  {\n    \"QuestionId\": 277,\n    \"ProductId\": 1,\n    \"Question\": \"How to verify device\\u0027s functionality?\",\n    \"Answer\": \"Perform functional diagnostics\"\n  },\n  {\n    \"QuestionId\": 278,\n    \"ProductId\": 194,\n    \"Question\": \"How to start a fire?\",\n    \"Answer\": \"Use the fire starter tool and waterproof matches.\"\n  },\n  {\n    \"QuestionId\": 279,\n    \"ProductId\": 41,\n    \"Question\": \"Hi there, I just bought the AquaVenture Waterproof Surf Watch and I\\u0027m having trouble figuring out how to activate the GPS tracking feature. Can you help?\",\n    \"Answer\": \"Press and hold the \\u0027GPS\\u0027 button.\"\n  },\n  {\n    \"QuestionId\": 280,\n    \"ProductId\": 134,\n    \"Question\": \"How to collapse SolarFire 2000?\",\n    \"Answer\": \"Ensure stove is cool, then fold panels inwards.\"\n  },\n  {\n    \"QuestionId\": 281,\n    \"ProductId\": 194,\n    \"Question\": \"Hi, I just received my SurvivalPro 3000 Kit and I want to make sure I have everything. Can you provide a list of the contents?\",\n    \"Answer\": \"Check the contents against the provided list\"\n  },\n  {\n    \"QuestionId\": 282,\n    \"ProductId\": 27,\n    \"Question\": \"How to turn off?\",\n    \"Answer\": \"Press and hold for 3 seconds.\"\n  },\n  {\n    \"QuestionId\": 283,\n    \"ProductId\": 30,\n    \"Question\": \"visual inspection guidelines\",\n    \"Answer\": \"Refer to industry specification code BCCKW-002\"\n  },\n  {\n    \"QuestionId\": 284,\n    \"ProductId\": 49,\n    \"Question\": \"How to maintain boots?\",\n    \"Answer\": \"Regular Cleaning, Drying, Conditioning\"\n  },\n  {\n    \"QuestionId\": 285,\n    \"ProductId\": 152,\n    \"Question\": \"Submerging depth?\",\n    \"Answer\": \"Do not exceed max depth\"\n  },\n  {\n    \"QuestionId\": 286,\n    \"ProductId\": 187,\n    \"Question\": \"What is the battery capacity?\",\n    \"Answer\": \"3000mAh\"\n  },\n  {\n    \"QuestionId\": 287,\n    \"ProductId\": 3,\n    \"Question\": \"What should I adjust for comfort?\",\n    \"Answer\": \"tension of the straps\"\n  },\n  {\n    \"QuestionId\": 288,\n    \"ProductId\": 56,\n    \"Question\": \"Hi, I just bought the Naptime 5000 Sleeping Bag and I\\u0027m wondering how low of a temperature it is designed to keep me warm in?\",\n    \"Answer\": \"Designed to keep you warm in temperatures as low as 20\\u00B0F.\"\n  },\n  {\n    \"QuestionId\": 289,\n    \"ProductId\": 95,\n    \"Question\": \"What type of insulation does the sleeping bag have?\",\n    \"Answer\": \"High-quality insulation materials\"\n  },\n  {\n    \"QuestionId\": 290,\n    \"ProductId\": 70,\n    \"Question\": \"How to calibrate solar panel voltage?\",\n    \"Answer\": \"Use a voltage calibrator\"\n  },\n  {\n    \"QuestionId\": 291,\n    \"ProductId\": 86,\n    \"Question\": \"What tools are included?\",\n    \"Answer\": \"Bottle opener, screwdriver, can opener\"\n  },\n  {\n    \"QuestionId\": 292,\n    \"ProductId\": 65,\n    \"Question\": \"How to avoid injury when using the knife?\",\n    \"Answer\": \"Exercise caution to avoid cuts or punctures.\"\n  },\n  {\n    \"QuestionId\": 293,\n    \"ProductId\": 132,\n    \"Question\": \"Cleaning instructions?\",\n    \"Answer\": \"Regularly after each use\"\n  },\n  {\n    \"QuestionId\": 294,\n    \"ProductId\": 38,\n    \"Question\": \"how to ignite?\",\n    \"Answer\": \"turn ignition dial, press button\"\n  },\n  {\n    \"QuestionId\": 295,\n    \"ProductId\": 38,\n    \"Question\": \"Hi there, I just bought the Portable Camping Stove and I\\u0027m not sure how to set it up. Can you walk me through the steps?\",\n    \"Answer\": \"Start by unfolding the legs and locking them into place. Then, attach the fuel canister to the stove and make sure it\\u0027s secure. Finally, open the valve on the fuel canister to let the gas flow.\"\n  },\n  {\n    \"QuestionId\": 296,\n    \"ProductId\": 147,\n    \"Question\": \"What precautions should be taken when flying the SkyMaster X2000?\",\n    \"Answer\": \"Choose suitable environment, avoid obstacles and crowded areas, observe and avoid other aircraft.\"\n  },\n  {\n    \"QuestionId\": 297,\n    \"ProductId\": 182,\n    \"Question\": \"How to properly fit the harness?\",\n    \"Answer\": \"Follow these steps to ensure correct fitting.\"\n  },\n  {\n    \"QuestionId\": 298,\n    \"ProductId\": 198,\n    \"Question\": \"How to connect device?\",\n    \"Answer\": \"Follow easy steps provided in manual.\"\n  },\n  {\n    \"QuestionId\": 299,\n    \"ProductId\": 27,\n    \"Question\": \"Accessory compatibility?\",\n    \"Answer\": \"Range of accessories available.\"\n  },\n  {\n    \"QuestionId\": 300,\n    \"ProductId\": 87,\n    \"Question\": \"how to clean?\",\n    \"Answer\": \"Use soft cloth and mild soap\"\n  },\n  {\n    \"QuestionId\": 301,\n    \"ProductId\": 7,\n    \"Question\": \"How to clean the kit?\",\n    \"Answer\": \"Wipe with damp cloth, use mild disinfectant, air dry\"\n  },\n  {\n    \"QuestionId\": 302,\n    \"ProductId\": 176,\n    \"Question\": \"Hi there, I just got the AdventurePro 4500 camera and I\\u0027m trying to change the resolution for videos. Can you tell me how to do that?\",\n    \"Answer\": \"Navigate to the \\u0027Resolution\\u0027 option in the settings menu and select the desired resolution.\"\n  },\n  {\n    \"QuestionId\": 303,\n    \"ProductId\": 161,\n    \"Question\": \"Hi there, I just bought the ErgoVent Foldable Chair from SummitSeat and I want to make sure I store it properly. Can you tell me how it should be stored to avoid damage?\",\n    \"Answer\": \"Use a specifically designed cover for protection.\"\n  },\n  {\n    \"QuestionId\": 304,\n    \"ProductId\": 162,\n    \"Question\": \"What is the GPS tracking accuracy?\",\n    \"Answer\": \"accurate to within a few meters\"\n  },\n  {\n    \"QuestionId\": 305,\n    \"ProductId\": 86,\n    \"Question\": \"What additional tools are included?\",\n    \"Answer\": \"bottle opener, screwdriver, can opener\"\n  },\n  {\n    \"QuestionId\": 306,\n    \"ProductId\": 33,\n    \"Question\": \"How to contact customer service?\",\n    \"Answer\": \"1-800-555-1234 or support@gameguard.com\"\n  },\n  {\n    \"QuestionId\": 307,\n    \"ProductId\": 98,\n    \"Question\": \"What is discouraged for critical navigation or safety purposes?\",\n    \"Answer\": \"Using external devices or services\"\n  },\n  {\n    \"QuestionId\": 308,\n    \"ProductId\": 8,\n    \"Question\": \"Package contents?\",\n    \"Answer\": \"The Outdoor Admin 5000 device, carrying case, charging cable, user manual\"\n  },\n  {\n    \"QuestionId\": 309,\n    \"ProductId\": 120,\n    \"Question\": \"What tests are used for quality assurance?\",\n    \"Answer\": \"Thermo-imaging, Moisture, Insulation Resistance, Water Pressure, Electronic Component, Snow Load\"\n  },\n  {\n    \"QuestionId\": 310,\n    \"ProductId\": 121,\n    \"Question\": \"How to activate SOS signal?\",\n    \"Answer\": \"Press and hold red button for 3 seconds\"\n  },\n  {\n    \"QuestionId\": 311,\n    \"ProductId\": 105,\n    \"Question\": \"What is included in the package?\",\n    \"Answer\": \"1 Solar Power Bank 10000mAh, 1 Micro-USB cable, 1 Carabiner clip, 1 User Manual\"\n  },\n  {\n    \"QuestionId\": 312,\n    \"ProductId\": 44,\n    \"Question\": \"What is the signal mirror used for?\",\n    \"Answer\": \"Signaling for help over long distances\"\n  },\n  {\n    \"QuestionId\": 313,\n    \"ProductId\": 24,\n    \"Question\": \"How to get in and out?\",\n    \"Answer\": \"Follow the steps in the manual.\"\n  },\n  {\n    \"QuestionId\": 314,\n    \"ProductId\": 21,\n    \"Question\": \"Hey there, my WeatherGuard Pro 3000 isn\\u0027t responding at all. I\\u0027ve tried holding down the power button for 10 seconds, but it\\u0027s still not working. What should I do next?\",\n    \"Answer\": \"Contact TechShield Support for further assistance.\"\n  },\n  {\n    \"QuestionId\": 315,\n    \"ProductId\": 137,\n    \"Question\": \"How to clean WildBeat Pro DJ Controller?\",\n    \"Answer\": \"Use soft, lint-free cloth with water.\"\n  },\n  {\n    \"QuestionId\": 316,\n    \"ProductId\": 182,\n    \"Question\": \"How to store Summit Pro Climbing Harness?\",\n    \"Answer\": \"Store in cool, dry place away from sunlight and moisture.\"\n  },\n  {\n    \"QuestionId\": 317,\n    \"ProductId\": 177,\n    \"Question\": \"How do you set up the poles?\",\n    \"Answer\": \"Insert black pole into sleeve, connect red pole.\"\n  },\n  {\n    \"QuestionId\": 318,\n    \"ProductId\": 140,\n    \"Question\": \"How do I connect to Bluetooth?\",\n    \"Answer\": \"Turn on speaker, search for device, select \\u0027RuggedSound\\u0027\"\n  },\n  {\n    \"QuestionId\": 319,\n    \"ProductId\": 58,\n    \"Question\": \"Battery life indicator?\",\n    \"Answer\": \"Allows you to monitor remaining charge\"\n  },\n  {\n    \"QuestionId\": 320,\n    \"ProductId\": 168,\n    \"Question\": \"How do I power on the WildDJ Pro Mixer?\",\n    \"Answer\": \"Press and hold the power button\"\n  },\n  {\n    \"QuestionId\": 321,\n    \"ProductId\": 101,\n    \"Question\": \"Hi there, I just bought the Ultraglow Lumina LED Camping Lantern and I want to know how to adjust the brightness. Can you help?\",\n    \"Answer\": \"Turn the knob clockwise to increase brightness and counterclockwise to decrease brightness.\"\n  },\n  {\n    \"QuestionId\": 322,\n    \"ProductId\": 73,\n    \"Question\": \"What steps are involved in the initial setup?\",\n    \"Answer\": \"Unpack, inspect, charge battery, power on, verify LED indicators, initialize GPS\"\n  },\n  {\n    \"QuestionId\": 323,\n    \"ProductId\": 110,\n    \"Question\": \"Hi there, I just received my PowerFuel Energy Bars and I want to make sure I store them properly. Can you tell me the optimal storage conditions for the bars?\",\n    \"Answer\": \"Cool, dry place away from direct sunlight\"\n  },\n  {\n    \"QuestionId\": 324,\n    \"ProductId\": 139,\n    \"Question\": \"Screen cleaning steps?\",\n    \"Answer\": \"Clean with soft, dry cloth.\"\n  },\n  {\n    \"QuestionId\": 325,\n    \"ProductId\": 169,\n    \"Question\": \"Hello, I recently purchased the Trailblazer Camping Cookware Set and I\\u0027m wondering how to properly store it when not in use. Can you provide some guidance on this?\",\n    \"Answer\": \"When not in use, the Trailblazer Camping Cookware Set can be stored inside the large pot to save space. Place the smaller items inside the pots and secure the foldable handles around the outside to keep everything together.\"\n  },\n  {\n    \"QuestionId\": 326,\n    \"ProductId\": 102,\n    \"Question\": \"How to collapse the paddle?\",\n    \"Answer\": \"Refer to the user manual for detailed instructions.\"\n  },\n  {\n    \"QuestionId\": 327,\n    \"ProductId\": 102,\n    \"Question\": \"how to clean the paddle?\",\n    \"Answer\": \"Rinse with freshwater and use mild detergent.\"\n  },\n  {\n    \"QuestionId\": 328,\n    \"ProductId\": 101,\n    \"Question\": \"Hi there, I just bought the Ultraglow Lumina LED Camping Lantern and it won\\u0027t turn on. What should I do?\",\n    \"Answer\": \"Ensure that the batteries are inserted correctly.\"\n  },\n  {\n    \"QuestionId\": 329,\n    \"ProductId\": 44,\n    \"Question\": \"What is included in the kit?\",\n    \"Answer\": \"first aid supplies, fire starter, emergency blanket, other tools\"\n  },\n  {\n    \"QuestionId\": 330,\n    \"ProductId\": 2,\n    \"Question\": \"What equipment is required for hardware installation?\",\n    \"Answer\": \"SMD unit, antenna, power cable, mounting brackets, screws and bolts\"\n  },\n  {\n    \"QuestionId\": 331,\n    \"ProductId\": 193,\n    \"Question\": \"How to clean exterior?\",\n    \"Answer\": \"Use mild detergent and warm water\"\n  },\n  {\n    \"QuestionId\": 332,\n    \"ProductId\": 55,\n    \"Question\": \"Warranty coverage period?\",\n    \"Answer\": \"3-year limited warranty\"\n  },\n  {\n    \"QuestionId\": 333,\n    \"ProductId\": 191,\n    \"Question\": \"Hi there, I\\u0027m having trouble with my Luminex 5000 Lantern not turning on. I\\u0027ve tried checking the battery compartment and pressing the power button, but it still won\\u0027t work. What should I do next?\",\n    \"Answer\": \"Contact Customer Support\"\n  },\n  {\n    \"QuestionId\": 334,\n    \"ProductId\": 119,\n    \"Question\": \"What are the different modes?\",\n    \"Answer\": \"High Beam, Low Beam, Strobe\"\n  },\n  {\n    \"QuestionId\": 335,\n    \"ProductId\": 51,\n    \"Question\": \"How to access the knife?\",\n    \"Answer\": \"Locate the main tool compartment and carefully slide out the knife.\"\n  },\n  {\n    \"QuestionId\": 336,\n    \"ProductId\": 101,\n    \"Question\": \"How do I contact customer service?\",\n    \"Answer\": \"customerservice@ultraglow.com, 1-800-123-4567, www.ultraglow.com\"\n  },\n  {\n    \"QuestionId\": 337,\n    \"ProductId\": 89,\n    \"Question\": \"How to store the cookware set?\",\n    \"Answer\": \"Cool, dry place\"\n  },\n  {\n    \"QuestionId\": 338,\n    \"ProductId\": 4,\n    \"Question\": \"Hi, I recently purchased the Life Guard X Emergency Survival Kit and I\\u0027m wondering how to set up the emergency tent. Can you provide instructions?\",\n    \"Answer\": \"Lay the tent flat on the ground.\"\n  },\n  {\n    \"QuestionId\": 339,\n    \"ProductId\": 6,\n    \"Question\": \"How to assemble?\",\n    \"Answer\": \"Attach handle to digging head, fasten locking mechanism.\"\n  },\n  {\n    \"QuestionId\": 340,\n    \"ProductId\": 99,\n    \"Question\": \"Hi there, I recently purchased the Summit 3000 Trekking Backpack and I want to make sure it\\u0027s in good condition before my trip. Can you tell me how to measure the tensile strength of the backpack\\u0027s straps and seams as mentioned in the manual?\",\n    \"Answer\": \"Utilize a tensile testing machine.\"\n  },\n  {\n    \"QuestionId\": 341,\n    \"ProductId\": 181,\n    \"Question\": \"how to adjust paddle length?\",\n    \"Answer\": \"Twist the dial to unlock and slide paddle shaft.\"\n  },\n  {\n    \"QuestionId\": 342,\n    \"ProductId\": 168,\n    \"Question\": \"What color is the crossfader?\",\n    \"Answer\": \"Regal deep blue\"\n  },\n  {\n    \"QuestionId\": 343,\n    \"ProductId\": 62,\n    \"Question\": \"How to adjust brightness level?\",\n    \"Answer\": \"Locate the power button on the top of the headlamp.\"\n  },\n  {\n    \"QuestionId\": 344,\n    \"ProductId\": 170,\n    \"Question\": \"How to wear AquaFlow Hydration System?\",\n    \"Answer\": \"Follow steps in manual for securing straps and attaching drinking tube\"\n  },\n  {\n    \"QuestionId\": 345,\n    \"ProductId\": 146,\n    \"Question\": \"Hi, I just bought the Energy Boost 500 and I\\u0027m not sure how much to take. Can you tell me the recommended dosage?\",\n    \"Answer\": \"1 scoop of Energy Boost 500, mixed with 8-12 ounces of water, 15-30 minutes before activity.\"\n  },\n  {\n    \"QuestionId\": 346,\n    \"ProductId\": 159,\n    \"Question\": \"Charging time via solar panel?\",\n    \"Answer\": \"Charging time may vary based on sunlight intensity.\"\n  },\n  {\n    \"QuestionId\": 347,\n    \"ProductId\": 124,\n    \"Question\": \"Hi there, I just bought the ToughTrek SurvivalPro 2000 and I\\u0027m wondering about the construction. Can you tell me more about the outer casing and the material used?\",\n    \"Answer\": \"Reinforced steel for unparalleled strength and durability\"\n  },\n  {\n    \"QuestionId\": 348,\n    \"ProductId\": 47,\n    \"Question\": \"What is the purpose of the Protein Plus Energy Bars?\",\n    \"Answer\": \"Provide convenient and delicious nutrition for active lifestyles.\"\n  },\n  {\n    \"QuestionId\": 349,\n    \"ProductId\": 97,\n    \"Question\": \"How to resolve knife won\\u0027t open?\",\n    \"Answer\": \"Check for obstructions, use lubrication, contact customer support\"\n  },\n  {\n    \"QuestionId\": 350,\n    \"ProductId\": 163,\n    \"Question\": \"Hi there, I just bought the Stealth Cam 500 and I wanted to know if it\\u0027s waterproof. Can I use it near water?\",\n    \"Answer\": \"No, the Stealth Cam 500 is not waterproof and should not be used near water.\"\n  },\n  {\n    \"QuestionId\": 351,\n    \"ProductId\": 38,\n    \"Question\": \"Hi there, I\\u0027m having trouble igniting my Portable Camping Stove. Can you give me some tips on how to start it?\",\n    \"Answer\": \"Turn the ignition dial to the \\u0027ignite\\u0027 position and press the ignition button.\"\n  },\n  {\n    \"QuestionId\": 352,\n    \"ProductId\": 76,\n    \"Question\": \"What are the key features?\",\n    \"Answer\": \"Rugged design, high-tech equipment, portability, versatility.\"\n  },\n  {\n    \"QuestionId\": 353,\n    \"ProductId\": 162,\n    \"Question\": \"How long to acquire satellite signals?\",\n    \"Answer\": \"At least 5 minutes\"\n  },\n  {\n    \"QuestionId\": 354,\n    \"ProductId\": 116,\n    \"Question\": \"How to prevent leaking inside the tent?\",\n    \"Answer\": \"Properly attach rainfly and keep guy lines taut for ventilation.\"\n  },\n  {\n    \"QuestionId\": 355,\n    \"ProductId\": 166,\n    \"Question\": \"How to check oil level?\",\n    \"Answer\": \"Remove dipstick, wipe clean, check between markings\"\n  },\n  {\n    \"QuestionId\": 356,\n    \"ProductId\": 130,\n    \"Question\": \"What type of sound does the WildBeat Bluetooth Speaker produce?\",\n    \"Answer\": \"360-degree sound\"\n  },\n  {\n    \"QuestionId\": 357,\n    \"ProductId\": 80,\n    \"Question\": \"What is the gear ratio?\",\n    \"Answer\": \"6.2:1\"\n  },\n  {\n    \"QuestionId\": 358,\n    \"ProductId\": 187,\n    \"Question\": \"How to troubleshoot drone power issues?\",\n    \"Answer\": \"Refer to troubleshooting guide\"\n  },\n  {\n    \"QuestionId\": 359,\n    \"ProductId\": 180,\n    \"Question\": \"properly attach reel?\",\n    \"Answer\": \"Ensure the reel is properly attached to the rod.\"\n  },\n  {\n    \"QuestionId\": 360,\n    \"ProductId\": 18,\n    \"Question\": \"Hydration reservoir capacity?\",\n    \"Answer\": \"2L\"\n  },\n  {\n    \"QuestionId\": 361,\n    \"ProductId\": 115,\n    \"Question\": \"How should I store my NanoTrax?\",\n    \"Answer\": \"Dry Thoroughly, Keep Them Together, Avoid Extreme Temperatures, Hang \\u0027Em Up\"\n  },\n  {\n    \"QuestionId\": 362,\n    \"ProductId\": 122,\n    \"Question\": \"How to turn on stabilization?\",\n    \"Answer\": \"In the Video Settings menu, look for the Stabilization option and toggle it on.\"\n  },\n  {\n    \"QuestionId\": 363,\n    \"ProductId\": 183,\n    \"Question\": \"Warranty coverage?\",\n    \"Answer\": \"Campchef offers a limited lifetime warranty\"\n  },\n  {\n    \"QuestionId\": 364,\n    \"ProductId\": 97,\n    \"Question\": \"What is the ultimate tool for navigating the great outdoors?\",\n    \"Answer\": \"NomadGear Compass\"\n  },\n  {\n    \"QuestionId\": 365,\n    \"ProductId\": 125,\n    \"Question\": \"How to sterilize surgical instruments?\",\n    \"Answer\": \"Boil instruments for 20 minutes\"\n  },\n  {\n    \"QuestionId\": 366,\n    \"ProductId\": 89,\n    \"Question\": \"What to use to clean the cookware?\",\n    \"Answer\": \"Non-abrasive sponge or cloth with mild dish soap\"\n  },\n  {\n    \"QuestionId\": 367,\n    \"ProductId\": 71,\n    \"Question\": \"Hello, I just received my Trailcom Signal Booster 2000 and I want to make sure I handle it properly. Can you tell me how far I need to maintain distance between the device and my body to comply with RF exposure requirements?\",\n    \"Answer\": \"Maintain a minimum distance of 20 cm (8 inches) between the Signal Booster 2000 and the body.\"\n  },\n  {\n    \"QuestionId\": 368,\n    \"ProductId\": 67,\n    \"Question\": \"How should the bars be stored?\",\n    \"Answer\": \"In a cool, dry place away from direct sunlight\"\n  },\n  {\n    \"QuestionId\": 369,\n    \"ProductId\": 12,\n    \"Question\": \"What does GPS stand for?\",\n    \"Answer\": \"Global Positioning System\"\n  },\n  {\n    \"QuestionId\": 370,\n    \"ProductId\": 48,\n    \"Question\": \"How to charge?\",\n    \"Answer\": \"Plug USB cable into charging port\"\n  },\n  {\n    \"QuestionId\": 371,\n    \"ProductId\": 196,\n    \"Question\": \"What type of GPS module does the TrailMaster GPS Watch use?\",\n    \"Answer\": \"GPS, GLONASS, and Galileo satellite systems\"\n  },\n  {\n    \"QuestionId\": 372,\n    \"ProductId\": 55,\n    \"Question\": \"how to charge\",\n    \"Answer\": \"Connect USB cable, let it charge for 2 hours\"\n  },\n  {\n    \"QuestionId\": 373,\n    \"ProductId\": 75,\n    \"Question\": \"How to replace battery?\",\n    \"Answer\": \"Follow steps in manual\"\n  },\n  {\n    \"QuestionId\": 374,\n    \"ProductId\": 7,\n    \"Question\": \"Hello, I recently purchased the Off-Grid Surgeon Kit from Adventure Prosthetics. Can you tell me what items are included in the kit?\",\n    \"Answer\": \"Scalpel, surgical scissors, needle holder, forceps, sutures, sterile drapes, antiseptic solution, sterile gloves, gauze pads, adhesive bandages, tourniquet\"\n  },\n  {\n    \"QuestionId\": 375,\n    \"ProductId\": 198,\n    \"Question\": \"How to activate LED light show?\",\n    \"Answer\": \"Press and hold Party Mode button.\"\n  },\n  {\n    \"QuestionId\": 376,\n    \"ProductId\": 33,\n    \"Question\": \"How to activate night vision?\",\n    \"Answer\": \"Press \\u0027Night Vision\\u0027 button\"\n  },\n  {\n    \"QuestionId\": 377,\n    \"ProductId\": 149,\n    \"Question\": \"Hi there, I recently purchased the AquaFlow Pro and I\\u0027m wondering how to assess the condition of the bite valve. Can you provide some guidance?\",\n    \"Answer\": \"Visual Inspection: Examine for signs of wear. Operational Test: Test functionality. Replacement: Use genuine Thirsttrek part if necessary.\"\n  },\n  {\n    \"QuestionId\": 378,\n    \"ProductId\": 190,\n    \"Question\": \"What to verify during visual inspection?\",\n    \"Answer\": \"Stress, wear, damage to construction, locking mechanism, grips\"\n  },\n  {\n    \"QuestionId\": 379,\n    \"ProductId\": 123,\n    \"Question\": \"Hello, I just purchased the SolarCopy 3000. Can you tell me how to clean the solar panels?\",\n    \"Answer\": \"Use a clean, soft cloth to wipe the panels.\"\n  },\n  {\n    \"QuestionId\": 380,\n    \"ProductId\": 156,\n    \"Question\": \"Hi there, I recently purchased the Arctic Ice Grip Crampons from Glacierpro. Can you tell me how to properly store them to maintain their condition?\",\n    \"Answer\": \"Use the storage bag, keep them dry, and store in a cool, dry place.\"\n  },\n  {\n    \"QuestionId\": 381,\n    \"ProductId\": 145,\n    \"Question\": \"How to turn on?\",\n    \"Answer\": \"Press the power button.\"\n  },\n  {\n    \"QuestionId\": 382,\n    \"ProductId\": 160,\n    \"Question\": \"How to set a waypoint?\",\n    \"Answer\": \"Navigate to \\u0027Waypoints\\u0027 option and select \\u0027Add Waypoint\\u0027.\"\n  },\n  {\n    \"QuestionId\": 383,\n    \"ProductId\": 73,\n    \"Question\": \"How to perform pre-flight checklist?\",\n    \"Answer\": \"Follow the 6-step checklist in the manual.\"\n  },\n  {\n    \"QuestionId\": 384,\n    \"ProductId\": 46,\n    \"Question\": \"Hi there, I just bought the SunSpot Solar Cooker from Eco Grill. Can you tell me what precautions I should take when using it to ensure safety?\",\n    \"Answer\": \"Avoid extreme weather conditions, don\\u0027t touch hot reflectors, keep away from children and pets.\"\n  },\n  {\n    \"QuestionId\": 385,\n    \"ProductId\": 127,\n    \"Question\": \"How to clean the HydraPack 2.0?\",\n    \"Answer\": \"Thoroughly rinse with lukewarm water, use mild soap solution, and air dry.\"\n  },\n  {\n    \"QuestionId\": 386,\n    \"ProductId\": 67,\n    \"Question\": \"Hi there, I am interested in purchasing the Nutritech Energy Bars Variety Pack. Can you tell me how many energy bars are included in the pack?\",\n    \"Answer\": \"The Nutritech Energy Bars Variety Pack contains 12 energy bars in total, with 4 bars of each flavor: chocolate chip, peanut butter, and oatmeal raisin.\"\n  },\n  {\n    \"QuestionId\": 387,\n    \"ProductId\": 156,\n    \"Question\": \"How to troubleshoot reduced traction?\",\n    \"Answer\": \"Check positioning, clean teeth, inspect for damage.\"\n  },\n  {\n    \"QuestionId\": 388,\n    \"ProductId\": 123,\n    \"Question\": \"What is the battery type?\",\n    \"Answer\": \"Lithium-ion\"\n  },\n  {\n    \"QuestionId\": 389,\n    \"ProductId\": 66,\n    \"Question\": \"What is the SunSafe Pop-Up Beach Tent suitable for?\",\n    \"Answer\": \"Sun shelter\"\n  },\n  {\n    \"QuestionId\": 390,\n    \"ProductId\": 193,\n    \"Question\": \"Hello, I recently purchased the AltitudeTech Cake Carrier and I want to make sure I am loading and unloading it correctly. Can you provide me with the loading and unloading protocol?\",\n    \"Answer\": \"Place your cake securely on the removable base plate, making sure it is centered and does not come into contact with the sides of the carrier. When unloading the cake, carefully lift it out of the carrier by holding the base plate and avoiding any unnecessary tilting or shaking.\"\n  },\n  {\n    \"QuestionId\": 391,\n    \"ProductId\": 145,\n    \"Question\": \"Hi, I just bought the PowerBeam Solar Powered Portable Charger and I\\u0027m wondering how to charge it indoors. Can I use any USB cable to connect it to a power source?\",\n    \"Answer\": \"Use the included micro-USB cable for indoor charging.\"\n  },\n  {\n    \"QuestionId\": 392,\n    \"ProductId\": 69,\n    \"Question\": \"What material is used for waterproofing?\",\n    \"Answer\": \"Waterproof and breathable membrane\"\n  },\n  {\n    \"QuestionId\": 393,\n    \"ProductId\": 35,\n    \"Question\": \"Hi there, I\\u0027m having trouble with my CookMaster Alpine Camp Cookware Set. The heat doesn\\u0027t seem to distribute evenly across the cookware. What can I do to fix this?\",\n    \"Answer\": \"Ensure that the cookware is placed on a flat surface for proper heat distribution.\"\n  },\n  {\n    \"QuestionId\": 394,\n    \"ProductId\": 18,\n    \"Question\": \"How much water can the hydration reservoir hold?\",\n    \"Answer\": \"2L\"\n  },\n  {\n    \"QuestionId\": 395,\n    \"ProductId\": 149,\n    \"Question\": \"How to conduct flow rate calibration?\",\n    \"Answer\": \"Use a precision flow meter and tubing\"\n  },\n  {\n    \"QuestionId\": 396,\n    \"ProductId\": 93,\n    \"Question\": \"How to assemble the stove?\",\n    \"Answer\": \"Place stand, attach reflector, position stove.\"\n  },\n  {\n    \"QuestionId\": 397,\n    \"ProductId\": 120,\n    \"Question\": \"What is the waterproof testing chamber used for?\",\n    \"Answer\": \"Simulate extreme weather conditions\"\n  },\n  {\n    \"QuestionId\": 398,\n    \"ProductId\": 76,\n    \"Question\": \"What color is the amplifier?\",\n    \"Answer\": \"vibrant green\"\n  },\n  {\n    \"QuestionId\": 399,\n    \"ProductId\": 145,\n    \"Question\": \"How to troubleshoot slow charging?\",\n    \"Answer\": \"Optimize Sun Exposure\"\n  },\n  {\n    \"QuestionId\": 400,\n    \"ProductId\": 70,\n    \"Question\": \"Hi there, I recently purchased the Juice Junkie Solar Power Bank 10000mAh and I\\u0027m not sure how to optimize the solar panel performance. Can you provide some guidance on how to position the solar panel for maximum sunlight exposure?\",\n    \"Answer\": \"Ensure optimal angle and orientation.\"\n  },\n  {\n    \"QuestionId\": 401,\n    \"ProductId\": 103,\n    \"Question\": \"What first aid supplies are included?\",\n    \"Answer\": \"Band-aids, gauze pads, adhesive tape, antiseptic wipes\"\n  },\n  {\n    \"QuestionId\": 402,\n    \"ProductId\": 99,\n    \"Question\": \"What standards does the backpack comply with?\",\n    \"Answer\": \"ISO 11226 and ANSI/HFES 100-2007\"\n  },\n  {\n    \"QuestionId\": 403,\n    \"ProductId\": 145,\n    \"Question\": \"Not charging?\",\n    \"Answer\": \"Check solar panel and connection.\"\n  },\n  {\n    \"QuestionId\": 404,\n    \"ProductId\": 86,\n    \"Question\": \"How to start a fire?\",\n    \"Answer\": \"Follow these simple steps.\"\n  },\n  {\n    \"QuestionId\": 405,\n    \"ProductId\": 82,\n    \"Question\": \"Hi there, I just bought the SurvivalPro Emergency Kit and I want to make sure all the items are included. Can you help me with a checklist?\",\n    \"Answer\": \"Yes, use the checklist provided in the kit.\"\n  },\n  {\n    \"QuestionId\": 406,\n    \"ProductId\": 184,\n    \"Question\": \"How to charge?\",\n    \"Answer\": \"Refer to section 4.2\"\n  },\n  {\n    \"QuestionId\": 407,\n    \"ProductId\": 185,\n    \"Question\": \"How does the insulated interior work?\",\n    \"Answer\": \"Locks in body heat with synthetic fibers\"\n  },\n  {\n    \"QuestionId\": 408,\n    \"ProductId\": 9,\n    \"Question\": \"How to troubleshoot AltitudeShield Pro?\",\n    \"Answer\": \"Not disassemble or tamper.\"\n  },\n  {\n    \"QuestionId\": 409,\n    \"ProductId\": 41,\n    \"Question\": \"Hi there, just got the AquaVenture surf watch and I\\u0027m wondering how to activate the heart rate monitoring feature. Can you help?\",\n    \"Answer\": \"Press the \\u0022HEART\\u0022 button\"\n  },\n  {\n    \"QuestionId\": 410,\n    \"ProductId\": 116,\n    \"Question\": \"Storage tips?\",\n    \"Answer\": \"Ensure the tent is completely dry before storing\"\n  },\n  {\n    \"QuestionId\": 411,\n    \"ProductId\": 163,\n    \"Question\": \"What is the purpose of the Stealth Cam 500?\",\n    \"Answer\": \"Designed to capture wildlife in their natural habitat\"\n  },\n  {\n    \"QuestionId\": 412,\n    \"ProductId\": 119,\n    \"Question\": \"How many lighting modes?\",\n    \"Answer\": \"Three: High, Low, Strobe.\"\n  },\n  {\n    \"QuestionId\": 413,\n    \"ProductId\": 37,\n    \"Question\": \"suitability for children?\",\n    \"Answer\": \"Familiarize with pediatric first aid procedures\"\n  },\n  {\n    \"QuestionId\": 414,\n    \"ProductId\": 71,\n    \"Question\": \"What is the power input?\",\n    \"Answer\": \"12V DC\"\n  },\n  {\n    \"QuestionId\": 415,\n    \"ProductId\": 131,\n    \"Question\": \"Hello, I just bought the NatureCam 1000 and I\\u0027m not sure how to insert the SD card. Can you provide some guidance?\",\n    \"Answer\": \"Locate the SD card slot on the side of the camera, and carefully insert the SD card into the slot until it clicks into place.\"\n  },\n  {\n    \"QuestionId\": 416,\n    \"ProductId\": 66,\n    \"Question\": \"Assembly instructions for beach tent?\",\n    \"Answer\": \"Do not attempt in windy conditions\"\n  },\n  {\n    \"QuestionId\": 417,\n    \"ProductId\": 168,\n    \"Question\": \"What controls the overall sound output?\",\n    \"Answer\": \"Master volume knob\"\n  },\n  {\n    \"QuestionId\": 418,\n    \"ProductId\": 25,\n    \"Question\": \"What PPE is recommended?\",\n    \"Answer\": \"Hard hat, safety goggles, gloves, steel-toed boots\"\n  },\n  {\n    \"QuestionId\": 419,\n    \"ProductId\": 145,\n    \"Question\": \"Hi, I just bought the PowerBeam Solar Powered Portable Charger. How do I charge it using the included micro-USB cable indoors?\",\n    \"Answer\": \"Connect the charger to a power source using the micro-USB cable.\"\n  },\n  {\n    \"QuestionId\": 420,\n    \"ProductId\": 43,\n    \"Question\": \"How to troubleshoot flashlight not turning on?\",\n    \"Answer\": \"Check battery, replace, inspect tailcap\"\n  },\n  {\n    \"QuestionId\": 421,\n    \"ProductId\": 118,\n    \"Question\": \"How to wear PeakPro boots?\",\n    \"Answer\": \"Follow these pro tips.\"\n  },\n  {\n    \"QuestionId\": 422,\n    \"ProductId\": 143,\n    \"Question\": \"How to clean the cookware?\",\n    \"Answer\": \"Hand wash with mild soap\"\n  },\n  {\n    \"QuestionId\": 423,\n    \"ProductId\": 31,\n    \"Question\": \"warranty period?\",\n    \"Answer\": \"one year\"\n  },\n  {\n    \"QuestionId\": 424,\n    \"ProductId\": 23,\n    \"Question\": \"How to fix loose canopy?\",\n    \"Answer\": \"Check tension adjustment knobs\"\n  },\n  {\n    \"QuestionId\": 425,\n    \"ProductId\": 47,\n    \"Question\": \"Hi there, I recently purchased the Nutritech Protein Plus Energy Bars Variety Pack and one of the bars tasted off. Can you help me?\",\n    \"Answer\": \"Please check the expiration date printed on the wrapper.\"\n  },\n  {\n    \"QuestionId\": 426,\n    \"ProductId\": 168,\n    \"Question\": \"Dear customer support, my WildDJ Pro Mixer is having technical difficulties. Can you provide me with guidance and solutions to address the issue?\",\n    \"Answer\": \"Our technical support team is at your service.\"\n  },\n  {\n    \"QuestionId\": 427,\n    \"ProductId\": 53,\n    \"Question\": \"Hi there, I recently purchased the GlacierTech Snowsport Goggles and I want to know if the limited lifetime warranty covers manufacturing defects. Can you confirm?\",\n    \"Answer\": \"Yes, the warranty covers defects in materials and workmanship for the lifetime of the product from the date of purchase.\"\n  },\n  {\n    \"QuestionId\": 428,\n    \"ProductId\": 105,\n    \"Question\": \"How to initiate solar charging?\",\n    \"Answer\": \"Place in direct sunlight\"\n  },\n  {\n    \"QuestionId\": 429,\n    \"ProductId\": 149,\n    \"Question\": \"BPA-Free certification standards?\",\n    \"Answer\": \"Meets FDA and EFSA standards\"\n  },\n  {\n    \"QuestionId\": 430,\n    \"ProductId\": 200,\n    \"Question\": \"What safety standards does the backpack meet?\",\n    \"Answer\": \"ANSI/ISEA 107-2015, ISO 9001:2015\"\n  },\n  {\n    \"QuestionId\": 431,\n    \"ProductId\": 8,\n    \"Question\": \"Hello, I just received my Outdoor Admin 5000 and I\\u0027m curious to know what\\u0027s included in the package. Can you please tell me?\",\n    \"Answer\": \"The Outdoor Admin 5000, a carrying case, charging cable, and user manual.\"\n  },\n  {\n    \"QuestionId\": 432,\n    \"ProductId\": 109,\n    \"Question\": \"What is included for weather preparedness?\",\n    \"Answer\": \"Waterproof jacket and moisture-wicking jersey\"\n  },\n  {\n    \"QuestionId\": 433,\n    \"ProductId\": 103,\n    \"Question\": \"What should I do after unboxing?\",\n    \"Answer\": \"Lay out all the items\"\n  },\n  {\n    \"QuestionId\": 434,\n    \"ProductId\": 158,\n    \"Question\": \"How to clean water bladder?\",\n    \"Answer\": \"Rinse with warm, soapy water.\"\n  },\n  {\n    \"QuestionId\": 435,\n    \"ProductId\": 51,\n    \"Question\": \"Hello, I recently purchased the Resilience Gear Survival Pro Multi-Tool and I wanted to know what the warranty coverage is for this product. Can you provide me with more information on this?\",\n    \"Answer\": \"The limited warranty covers defects in materials or workmanship for one year from the date of purchase.\"\n  },\n  {\n    \"QuestionId\": 436,\n    \"ProductId\": 172,\n    \"Question\": \"How to adjust pole length?\",\n    \"Answer\": \"Reflect on engineering and design.\"\n  },\n  {\n    \"QuestionId\": 437,\n    \"ProductId\": 139,\n    \"Question\": \"How to activate SOS alert?\",\n    \"Answer\": \"Press and hold red button for 3 seconds\"\n  },\n  {\n    \"QuestionId\": 438,\n    \"ProductId\": 97,\n    \"Question\": \"Hey there, I just bought the Wanderer Multi-Tool Keychain and I\\u0027m wondering if it has a compass feature?\",\n    \"Answer\": \"Yes, it has a compass feature.\"\n  },\n  {\n    \"QuestionId\": 439,\n    \"ProductId\": 167,\n    \"Question\": \"Hello, I just bought the Trail Chef Backpacker Cookware Set and I want to make sure I\\u0027m cleaning it properly. Can you tell me what type of detergent I should use?\",\n    \"Answer\": \"Use a mild, non-abrasive detergent\"\n  },\n  {\n    \"QuestionId\": 440,\n    \"ProductId\": 142,\n    \"Question\": \"What are the setup steps?\",\n    \"Answer\": \"1. Wrap the tree-friendly straps around the trees... 2. Attach the carabiners to the loops at each end of the hammock... 3. Enjoy a smooth and stable setup.\"\n  },\n  {\n    \"QuestionId\": 441,\n    \"ProductId\": 151,\n    \"Question\": \"What is the warranty coverage?\",\n    \"Answer\": \"Limited lifetime warranty for defects under normal use\"\n  },\n  {\n    \"QuestionId\": 442,\n    \"ProductId\": 42,\n    \"Question\": \"How do I clean the backpack?\",\n    \"Answer\": \"Use mild detergent and water, then air dry.\"\n  },\n  {\n    \"QuestionId\": 443,\n    \"ProductId\": 107,\n    \"Question\": \"Hi there, I just bought the UltraGrip 3000 Trekking Poles. How should I store them when not in use?\",\n    \"Answer\": \"Store in cool, dry place away from direct sunlight and extreme temperatures.\"\n  },\n  {\n    \"QuestionId\": 444,\n    \"ProductId\": 102,\n    \"Question\": \"How to collapse the paddle?\",\n    \"Answer\": \"Verify that the locking mechanisms are disengaged before attempting to collapse the paddle.\"\n  },\n  {\n    \"QuestionId\": 445,\n    \"ProductId\": 135,\n    \"Question\": \"What is the recommended resolution for footage capture?\",\n    \"Answer\": \"4K resolution\"\n  },\n  {\n    \"QuestionId\": 446,\n    \"ProductId\": 11,\n    \"Question\": \"Hello, I recently purchased the SurvivalMed 3000 and I\\u0027m wondering where it should be stored to maintain its safety and functionality. Can you provide some guidance on this?\",\n    \"Answer\": \"Stored in a secure, climate-controlled environment at all times\"\n  },\n  {\n    \"QuestionId\": 447,\n    \"ProductId\": 15,\n    \"Question\": \"How to charge AdventurePro 1000?\",\n    \"Answer\": \"Use Micro-USB charging cable\"\n  },\n  {\n    \"QuestionId\": 448,\n    \"ProductId\": 87,\n    \"Question\": \"How long is the warranty?\",\n    \"Answer\": \"12 months\"\n  },\n  {\n    \"QuestionId\": 449,\n    \"ProductId\": 158,\n    \"Question\": \"How to clean the water bladder?\",\n    \"Answer\": \"Rinse with warm, soapy water.\"\n  },\n  {\n    \"QuestionId\": 450,\n    \"ProductId\": 122,\n    \"Question\": \"How to transfer footage?\",\n    \"Answer\": \"Connect to device using USB\"\n  },\n  {\n    \"QuestionId\": 451,\n    \"ProductId\": 28,\n    \"Question\": \"How to turn on?\",\n    \"Answer\": \"Press power button for 3 seconds\"\n  },\n  {\n    \"QuestionId\": 452,\n    \"ProductId\": 66,\n    \"Question\": \"How long is the warranty?\",\n    \"Answer\": \"6 months from purchase\"\n  },\n  {\n    \"QuestionId\": 453,\n    \"ProductId\": 45,\n    \"Question\": \"Charging indicators?\",\n    \"Answer\": \"Flashing when charging, steady when fully charged\"\n  },\n  {\n    \"QuestionId\": 454,\n    \"ProductId\": 78,\n    \"Question\": \"Hi there, I\\u0027m considering purchasing the AquaTech X-5000 for some watersports activities. Can you tell me about the water resistance testing and if it\\u0027s suitable for use in rough conditions?\",\n    \"Answer\": \"Conduct a water resistance test to verify the effectiveness of the AquaTech X-5000\\u0027s hydrophobic nano-coating.\"\n  },\n  {\n    \"QuestionId\": 455,\n    \"ProductId\": 80,\n    \"Question\": \"Hi there, I just bought the Stealth 5000 Fishing Reel and I\\u0027m wondering how to set the drag for maximum control. Can you help?\",\n    \"Answer\": \"Turn the drag knob on the top of the reel handle.\"\n  },\n  {\n    \"QuestionId\": 456,\n    \"ProductId\": 126,\n    \"Question\": \"How to activate SOS alert?\",\n    \"Answer\": \"Hold down the SOS button for 3 seconds\"\n  },\n  {\n    \"QuestionId\": 457,\n    \"ProductId\": 3,\n    \"Question\": \"How to set up the hammock?\",\n    \"Answer\": \"Wrap each strap around the tree or post and clip the carabiners to the loops at each end of the hammock body.\"\n  },\n  {\n    \"QuestionId\": 458,\n    \"ProductId\": 146,\n    \"Question\": \"Suitable for children or pregnant women?\",\n    \"Answer\": \"No, for adult use only.\"\n  },\n  {\n    \"QuestionId\": 459,\n    \"ProductId\": 110,\n    \"Question\": \"How should I store the bars?\",\n    \"Answer\": \"Lovingly wrapped in eco-friendly packaging\"\n  },\n  {\n    \"QuestionId\": 460,\n    \"ProductId\": 74,\n    \"Question\": \"Hi there, I just bought the Naturehaven Ultra-Light Hammock and I want to know how to clean it properly. Can I use bleach?\",\n    \"Answer\": \"Hand wash with mild soap and water, avoid using bleach\"\n  },\n  {\n    \"QuestionId\": 461,\n    \"ProductId\": 53,\n    \"Question\": \"How to prevent fogging?\",\n    \"Answer\": \"Clean with soft, dry cloth\"\n  },\n  {\n    \"QuestionId\": 462,\n    \"ProductId\": 183,\n    \"Question\": \"How to prevent rust on cookware?\",\n    \"Answer\": \"Thoroughly dry after use.\"\n  },\n  {\n    \"QuestionId\": 463,\n    \"ProductId\": 194,\n    \"Question\": \"How are the first aid supplies organized?\",\n    \"Answer\": \"In a bright red pouch\"\n  },\n  {\n    \"QuestionId\": 464,\n    \"ProductId\": 192,\n    \"Question\": \"What is the warranty claim process?\",\n    \"Answer\": \"Contact Hiker\\u0027s Haven Customer Service with proof of purchase and photos of defect.\"\n  },\n  {\n    \"QuestionId\": 465,\n    \"ProductId\": 34,\n    \"Question\": \"Battery type for best performance?\",\n    \"Answer\": \"Use 8 AA alkaline or lithium batteries\"\n  },\n  {\n    \"QuestionId\": 466,\n    \"ProductId\": 199,\n    \"Question\": \"What is the short circuit current?\",\n    \"Answer\": \"6.11A\"\n  },\n  {\n    \"QuestionId\": 467,\n    \"ProductId\": 87,\n    \"Question\": \"Hi there, I just bought the Xtreme Trail Bike Helmet and I need to clean the visor. What should I use to clean it?\",\n    \"Answer\": \"Use mild soap and water.\"\n  },\n  {\n    \"QuestionId\": 468,\n    \"ProductId\": 84,\n    \"Question\": \"Hi there, I just got the Trailblazer GPS Smartwatch and I\\u0027m wondering how to start tracking my cycling session. Can you help?\",\n    \"Answer\": \"Press the blue button and select \\u0027Cycling\\u0027 from the menu.\"\n  },\n  {\n    \"QuestionId\": 469,\n    \"ProductId\": 176,\n    \"Question\": \"How to change settings?\",\n    \"Answer\": \"Follow steps in manual\"\n  },\n  {\n    \"QuestionId\": 470,\n    \"ProductId\": 18,\n    \"Question\": \"How to adjust chest strap?\",\n    \"Answer\": \"Use sliding buckle to adjust chest strap height.\"\n  },\n  {\n    \"QuestionId\": 471,\n    \"ProductId\": 141,\n    \"Question\": \"What standard for fire starter conductivity?\",\n    \"Answer\": \"IEEE 156-2000\"\n  },\n  {\n    \"QuestionId\": 472,\n    \"ProductId\": 133,\n    \"Question\": \"Hi there, I just bought the TactiX 3000 backpack and I can\\u0027t figure out how to use the hydration compartment. Can you give me some instructions?\",\n    \"Answer\": \"Unzip, insert, secure, route, connect, and place.\"\n  },\n  {\n    \"QuestionId\": 473,\n    \"ProductId\": 151,\n    \"Question\": \"How to sharpen the knife?\",\n    \"Answer\": \"Use a knife sharpener\"\n  },\n  {\n    \"QuestionId\": 474,\n    \"ProductId\": 165,\n    \"Question\": \"How to attach rainfly?\",\n    \"Answer\": \"Lay it over the top and secure to poles using color-coded clips\"\n  },\n  {\n    \"QuestionId\": 475,\n    \"ProductId\": 137,\n    \"Question\": \"How often to inspect?\",\n    \"Answer\": \"Regularly\"\n  },\n  {\n    \"QuestionId\": 476,\n    \"ProductId\": 2,\n    \"Question\": \"Hi, I\\u0027m interested in the Secure Messaging Device. Can you tell me the processor specification?\",\n    \"Answer\": \"2.5 GHz Quad-Core\"\n  },\n  {\n    \"QuestionId\": 477,\n    \"ProductId\": 68,\n    \"Question\": \"How to find the perfect fit?\",\n    \"Answer\": \"Use ruler to measure foot length\"\n  },\n  {\n    \"QuestionId\": 478,\n    \"ProductId\": 96,\n    \"Question\": \"What is the warranty period?\",\n    \"Answer\": \"One year from the date of purchase\"\n  },\n  {\n    \"QuestionId\": 479,\n    \"ProductId\": 125,\n    \"Question\": \"Hello, I recently purchased the MediKit Xpress from Trailblazer Pharmaceuticals. Can you please provide some tips on how to properly prepare the kit for off-grid use?\",\n    \"Answer\": \"Always make sure to check that all the medical supplies are securely stored inside the kit before heading out on your adventure.\"\n  },\n  {\n    \"QuestionId\": 480,\n    \"ProductId\": 21,\n    \"Question\": \"How to customize settings?\",\n    \"Answer\": \"Tap on Settings app\"\n  },\n  {\n    \"QuestionId\": 481,\n    \"ProductId\": 166,\n    \"Question\": \"How to start the engine?\",\n    \"Answer\": \"Follow simple steps in manual\"\n  },\n  {\n    \"QuestionId\": 482,\n    \"ProductId\": 179,\n    \"Question\": \"How to store the AquaPro 3000?\",\n    \"Answer\": \"Store in a cool, dry place away from sunlight.\"\n  },\n  {\n    \"QuestionId\": 483,\n    \"ProductId\": 8,\n    \"Question\": \"Hi there, I just bought the Outdoor Admin 5000 and I\\u0027m having trouble accessing the emergency contacts. Can you help me with that?\",\n    \"Answer\": \"Select \\u0027Emergency Contacts\\u0027 from main menu\"\n  },\n  {\n    \"QuestionId\": 484,\n    \"ProductId\": 78,\n    \"Question\": \"how to troubleshoot power issues?\",\n    \"Answer\": \"Check Battery Connection, Battery Testing, Charging Process, External Power Source\"\n  },\n  {\n    \"QuestionId\": 485,\n    \"ProductId\": 21,\n    \"Question\": \"Hi there, I just got my WeatherGuard Pro 3000 and I\\u0027m trying to pair it with my smartphone. How many devices can I pair with it?\",\n    \"Answer\": \"You can pair up to 3 devices with your WeatherGuard Pro 3000.\"\n  },\n  {\n    \"QuestionId\": 486,\n    \"ProductId\": 15,\n    \"Question\": \"How to charge AdventurePro 1000?\",\n    \"Answer\": \"Use included Micro-USB charging cable\"\n  },\n  {\n    \"QuestionId\": 487,\n    \"ProductId\": 181,\n    \"Question\": \"Hi there, I just bought the RapidX Kayak Paddle and I\\u0027m having trouble adjusting the feather angle. Can you help me with that?\",\n    \"Answer\": \"Press the neon green feather adjustment button near the blade to adjust the feather angle.\"\n  },\n  {\n    \"QuestionId\": 488,\n    \"ProductId\": 80,\n    \"Question\": \"How to calibrate line counter?\",\n    \"Answer\": \"Lower lure, reset counter to zero\"\n  },\n  {\n    \"QuestionId\": 489,\n    \"ProductId\": 35,\n    \"Question\": \"How to clean the cookware?\",\n    \"Answer\": \"Wash with mild dish soap and warm water.\"\n  },\n  {\n    \"QuestionId\": 490,\n    \"ProductId\": 43,\n    \"Question\": \"Hi, I just bought the NightOps Tactical Flashlight and I\\u0027m not sure how to activate the strobe mode. Can you help?\",\n    \"Answer\": \"Press and hold the button for 2 seconds.\"\n  },\n  {\n    \"QuestionId\": 491,\n    \"ProductId\": 111,\n    \"Question\": \"Warranty duration?\",\n    \"Answer\": \"1-year from purchase\"\n  },\n  {\n    \"QuestionId\": 492,\n    \"ProductId\": 97,\n    \"Question\": \"How to use the knife?\",\n    \"Answer\": \"Carefully slide out the small blade.\"\n  },\n  {\n    \"QuestionId\": 493,\n    \"ProductId\": 93,\n    \"Question\": \"Hi there, I recently purchased the SunChef Solar Powered Stove and I\\u0027m having trouble with it not heating up properly. I\\u0027ve made sure it\\u0027s in direct sunlight, but it still doesn\\u0027t heat up. Any suggestions?\",\n    \"Answer\": \"Ensure Proper Sunlight\"\n  },\n  {\n    \"QuestionId\": 494,\n    \"ProductId\": 186,\n    \"Question\": \"Hi there, I recently purchased the Avalanche Pro 3000 and I want to make sure I know how to use the distress signal beacon in case of an emergency. Can you provide some guidance on how to activate it?\",\n    \"Answer\": \"Press and hold the red distress button to activate the signal.\"\n  },\n  {\n    \"QuestionId\": 495,\n    \"ProductId\": 8,\n    \"Question\": \"What comes in the package?\",\n    \"Answer\": \"The Outdoor Admin 5000 device, carrying case, charging cable, user manual\"\n  },\n  {\n    \"QuestionId\": 496,\n    \"ProductId\": 84,\n    \"Question\": \"How to start tracking cycling?\",\n    \"Answer\": \"Press blue button, select \\u0027Cycling\\u0027\"\n  },\n  {\n    \"QuestionId\": 497,\n    \"ProductId\": 170,\n    \"Question\": \"How to troubleshoot leakage?\",\n    \"Answer\": \"Follow steps in manual.\"\n  },\n  {\n    \"QuestionId\": 498,\n    \"ProductId\": 152,\n    \"Question\": \"How to reset beacon light?\",\n    \"Answer\": \"Remove batteries for 30 seconds\"\n  },\n  {\n    \"QuestionId\": 499,\n    \"ProductId\": 128,\n    \"Question\": \"How long is the warranty?\",\n    \"Answer\": \"1-year limited warranty\"\n  },\n  {\n    \"QuestionId\": 500,\n    \"ProductId\": 81,\n    \"Question\": \"How to troubleshoot difficulty adjusting buckles?\",\n    \"Answer\": \"Check threading and lubricate moving parts\"\n  }\n]"
  },
  {
    "path": "seeddata/dev/products.json",
    "content": "[\n  {\n    \"ProductId\": 1,\n    \"CategoryId\": 35,\n    \"Brand\": \"Escapesafe\",\n    \"Model\": \"Adventure GPS Tracker\",\n    \"Description\": \"Stay safe in the great outdoors with real-time tracking and SOS signal capabilities. Waterproof and durable for any adventure.\",\n    \"Price\": 149.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 10,\n    \"CategoryId\": 32,\n    \"Brand\": \"Beammax\",\n    \"Model\": \"TechBeam 2000\",\n    \"Description\": \"The TechBeam 2000 is a cutting-edge high-tech lighting solution for outdoor adventures. With adjustable brightness and long battery life, it\\u0027s an essential companion for nighttime activities.\",\n    \"Price\": 149.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 100,\n    \"CategoryId\": 52,\n    \"Brand\": \"Adventure Pack\",\n    \"Model\": \"Ridge Runner Hydration Pack\",\n    \"Description\": \"Stay hydrated on the go with the Ridge Runner Hydration Pack. Featuring a 2L water reservoir, ventilated back panel, and multiple pockets for storage, it\\u0027s perfect for hiking, biking, and outdoor activities.\",\n    \"Price\": 49.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 101,\n    \"CategoryId\": 54,\n    \"Brand\": \"Ultraglow\",\n    \"Model\": \"Lumina LED Camping Lantern\",\n    \"Description\": \"Illuminate your campsite with long-lasting, high-intensity LED light. Water-resistant and compact for easy portability. Great for outdoor adventures.\",\n    \"Price\": 29.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 102,\n    \"CategoryId\": 59,\n    \"Brand\": \"Aqua Venture\",\n    \"Model\": \"Voyager Kayak Paddle\",\n    \"Description\": \"Designed for durability and performance on the water. Lightweight and adjustable for comfortable use. A must-have for kayaking enthusiasts.\",\n    \"Price\": 79.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 103,\n    \"CategoryId\": 21,\n    \"Brand\": \"Safetyex\",\n    \"Model\": \"Survival Kit 5000\",\n    \"Description\": \"Be prepared for emergencies with this comprehensive survival kit. Includes first aid supplies, emergency food, water, and essential tools.\",\n    \"Price\": 149.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 104,\n    \"CategoryId\": 6,\n    \"Brand\": \"Aquaduct\",\n    \"Model\": \"Puriflo Water Filter Bottle\",\n    \"Description\": \"Drink clean, filtered water on the go. Removes 99.9% of bacteria and protozoa. Perfect for hiking, camping, and travel.\",\n    \"Price\": 39.99,\n    \"NameEmbedding\": \"5IgEwHokgMCSY4m9qDugwOiW776buZ7A0vbaQC0eFECbVZvAVvzJP5hyX8DAKkDBayJlQIcniMDCicE/QPcuv7HDMEAGHnpAgQvjwELXe0ASFRZB+o2dPpC158D3QynApqKZv+PsjkAsLz1AmLoFvZ8GKz8ZEkXBfsRGv8YiiD/5o7c/XmaUvnAavrzf8DFAL3iuP3lQO75ezRbANTGVvoOkVD/DeSc//stLwCDypz6bmJw/ibEgwFlGQ78y6a4+zuKiQJw4VMDaTG1AAOM9P55BFT+7cghAIzbKvsC33T+IXyM/Dw+DQGuNF0Dsepg9UfjNP+WpuEBCiz3Bq+43QeblL788ims/jDdpv+9+ez9WC0tAkLGRQKXIPMBEVv4+QVddP8ktnkC/M78/mgPTv1OyFr5eS3rABm0NwB4mm0AkaDJAgndIvhZAYD4H0S2/6WNGwHqE6r9MCQpA50YJvipoEcAIUptAa6uHwIVh6L6YLG3AR6edQLnupsBFzBs+v1bJv9sVCT7YJoE/CPlBQSCNzL+X+DBAdo4EwJwZx8CQxAhASrZpwCRadj/o/h/A1pBTv9jKOkBl2Ae/M8L/PiPHCT8kwq/AGOjjP3sgAUE+2yzANoBkvjTPMcAQGwfANPRcwIU3FcDeTHdAZ3/jPmDe/r/CfVRAqv5VQKTZc0AUwIrA3R3sQO4e6D5lWoHAZEU/vZaHj7/w4ZI8VNHSPsaXpL+g6FDAOO7MP4nlEEDN6wDBaCBSwIhZn78UsAfBdSt7wKTFvD8wnFLAUj3lv5Y8E8Da+1nA8OnLvnVlw0Dsi7S+LzYPQOnS5D+YgP6/stEVQLl+kkDKK4k+ZpKqP/cTXMDcXBPA1Ig9vzIuZUBbvLK/cB2GwMYIRb7gQ6bA9FugwBWt9EBa0zXAr9h7QDuyvr/Im1Y+hIv5PgowzT8tvZ0/himyQGrFFUDGsT2/HouZwO7wXkANSB7AGBgnQCYYoT9vy5DAMCpAv6aizb/pnl7Afjy/QLjviMB+Q60+6bWkvsDji0CU9k2+fFRQwM7rqb3NoaE++2/zvyNpj8CIr72/DtYvvxLEtr7bT2A/0H6MPZljhEBLXKk/m+kZQFaqDUBgiKJAwzfPP2NbmkB3sQ0/btlSP4C4jb8X5XBApm19QI7gL0DKXVw/HTuAv6sXPEDQGd3AmmRKwCU5gcGURa9ATq7uv9+lnsBz9IhA53GcvzbahD9CNwHAKMk2P4IC2kCxbM5AanILP+zSDMDrh7U/PhPlPl5B6UApQ5JAKvZ2vexEfUDU304/uxx0v+A3yLtS3BRA4wuTQMAhLT2/zTTAK9Y7Qdn2M0B0kf8+CPCaQIh9SL+TXM6//PcBwERfMcBp1Pi+8C1aQAx7isA49Kw/xfzxv6CnkcBNrmpATMayQCBlAsCdFOXAFi5uvwNdA8Bv+JO/zXuXQE4k28DS/tK/LGkkQGCOdT4CE6k/9rtBwPaVGz7BFgbA+sYWwHiivb+ZVmLAC6ROwPctIsAXyixA+bsFQMHPgsC4AhTAEghXv9BUVcDiZxbA/kC5QG32WEBHPKu/mOxEQByZAsAItZJAYb/3P/y8gEDq3tc/fSPywAC9zz+3ewDAOaavQEb/tz7EJ5NA1kHVviCuQECNkTxAQoMzv+G9LMBaBgE+OK89v4k3sL2QTqc8eXgvP3oksj3qpQ9B+TqtPutcl8HyCrQ+WEMLQFiopcC0pwnAZCDOvxMPIUDmTnJA5qtavzQS4z+wkIrA/g51QIqXIUBeDA5AFEiuv2sDbECV1rS+hudUwBWj3kDa5BM/4WX/P5G8KsBE3DVBU2NYvhKJ7L85Pzm/+mw4v/Iv3j+Lev+/BLxXQAYp173rNlVAbx0JQWhEW8As6DO/8PxOQJWRDMAId+8/w8gdP3+bVcBJiznAAWaKwFDFysCSatW/AeknQCUcccCmFDzAyGwEwcyVAL/J1yVA2On7v3GDDsCq9KRAlPO4P2fDM0D2vgU/WKeYwKoO97/EIBDAHD9vwAzzYECtEJnAtq7aP3OcBEDGQ5ZA\"\n  },\n  {\n    \"ProductId\": 105,\n    \"CategoryId\": 13,\n    \"Brand\": \"Power Pak\",\n    \"Model\": \"Solar Power Bank 10000mAh\",\n    \"Description\": \"Charge your devices anywhere with solar power. Compact and lightweight design with fast charging capabilities. Ideal for outdoor adventures and travel.\",\n    \"Price\": 49.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 106,\n    \"CategoryId\": 50,\n    \"Brand\": \"Sleepranger\",\n    \"Model\": \"ArcticZone 500 Sleeping Bag\",\n    \"Description\": \"Stay warm and comfortable during your outdoor adventures with the ArcticZone 500 sleeping bag. Designed for extreme conditions, this high-tech sleeping bag features advanced insulation and a durable, water-resistant shell.\",\n    \"Price\": 199.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 107,\n    \"CategoryId\": 51,\n    \"Brand\": \"Polepro\",\n    \"Model\": \"UltraGrip 3000 Trekking Poles\",\n    \"Description\": \"Conquer any terrain with the UltraGrip 3000 trekking poles. Featuring lightweight carbon construction and ergonomic grips, these high-tech poles offer superior stability and support for your outdoor excursions.\",\n    \"Price\": 79.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 108,\n    \"CategoryId\": 28,\n    \"Brand\": \"Eco Grill\",\n    \"Model\": \"SolarChef Off-Grid Stove\",\n    \"Description\": \"Cook delicious meals off the grid with the SolarChef stove. Utilizing solar technology, this high-tech stove is eco-friendly and perfect for camping, hiking, and other outdoor activities.\",\n    \"Price\": 149.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 109,\n    \"CategoryId\": 23,\n    \"Brand\": \"TrailTech\",\n    \"Model\": \"XtremeGear 5000 Mountain Biking Kit\",\n    \"Description\": \"Take your mountain biking to the next level with the XtremeGear 5000 kit. This high-tech gear includes advanced protective gear, performance clothing, and accessories for an unparalleled biking experience.\",\n    \"Price\": 299.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 11,\n    \"CategoryId\": 62,\n    \"Brand\": \"Adventurist Anaesthetics\",\n    \"Model\": \"SurvivalMed 3000\",\n    \"Description\": \"The ultimate off-grid surgery kit for adventurers. Whether it\\u0027s a minor wound or a full transplant, the kit contains everything you need.\",\n    \"Price\": 299.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 110,\n    \"CategoryId\": 41,\n    \"Brand\": \"EcoFuels\",\n    \"Model\": \"PowerFuel Energy Bars\",\n    \"Description\": \"Fuel your adventures with PowerFuel energy bars. Packed with high-quality, nutrient-dense ingredients, these eco-friendly bars provide a convenient and delicious source of energy for outdoor activities.\",\n    \"Price\": 14.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 111,\n    \"CategoryId\": 15,\n    \"Brand\": \"Hydratetech\",\n    \"Model\": \"Aquaflow 2L Hydration Pack\",\n    \"Description\": \"Stay hydrated on your outdoor adventures with the Aquaflow 2L Hydration Pack from Hydratetech. Features a leak-proof design, adjustable straps, and a high-flow bite valve.\",\n    \"Price\": 49.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 112,\n    \"CategoryId\": 23,\n    \"Brand\": \"Cyclextreme\",\n    \"Model\": \"Trailblazer Carbon Fiber Mountain Bike Helmet\",\n    \"Description\": \"Hit the trails with confidence while wearing the Trailblazer Carbon Fiber Mountain Bike Helmet from Cyclextreme. Lightweight, durable, and equipped with advanced ventilation for maximum comfort.\",\n    \"Price\": 129.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 113,\n    \"CategoryId\": 3,\n    \"Brand\": \"Backhike\",\n    \"Model\": \"Summit Pro 40L Technical Backpack\",\n    \"Description\": \"Carry all your gear in the Summit Pro 40L Technical Backpack from Backhike. Features a built-in hydration system, padded hip belt, and multiple compartments for organized storage.\",\n    \"Price\": 179.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 114,\n    \"CategoryId\": 36,\n    \"Brand\": \"JXE\",\n    \"Model\": \"WildBeat Wireless Waterproof Speaker\",\n    \"Description\": \"Keep the party going even in the wilderness with the WildBeat Wireless Waterproof Speaker from JXE. Features 360-degree sound, rugged construction, and long battery life.\",\n    \"Price\": 99.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 115,\n    \"CategoryId\": 66,\n    \"Brand\": \"FrostGlider\",\n    \"Model\": \"NanoTrax Ultra-Light Snowshoes\",\n    \"Description\": \"Conquer snowy terrain with ease using the NanoTrax Ultra-Light Snowshoes from FrostGlider. Utilizes nanotech materials for exceptional durability and lightweight performance.\",\n    \"Price\": 199.99,\n    \"NameEmbedding\": \"xcZiwLoX8z/6k95ApRKsP0APakCa+vE/sw0jQJoSl0BmpNLAPhh4QD3xEUCRWI3AKAF7QJD1N0CulHtAszP2P18aB0ADeqpAfiLfv3jpkT71FxxBgBlAwFZpVz+j2VfAkfWIQCKb+0BuBca+8MSBwAn4KcDoMDHBAU40wNkRz8DPvTBARBE+PYiWHMDyro6/GTHGPzaQI78aes/Ab9gCwGRQW0ByYxhARNDxwCkDikDCMZs/Ub7ewEqp6r/FWP4/i5OzwOtVCr8q+Ye9g9qOwK7APUDz0Jc/2kaJQIfglkBUFxA/xZfbPupC/kCE+RVA18cZQHy76UCetXfBHy+MQD/kwUAtLE8/nr3GwAylBcEPEtg/nfrGQAAOKUCG5jFA2i7kP0xTIz8uejI/sSgswJx2+T/m9t/AlXJUwHhEzT4+W1zAbBuIwNA0wD+GaFrAWmpFwKdSCECQXJs/qmzowCHIlECbJCBAzkARwEj1KMB/jYbAqjNdwFFYNcFuabC/zrFoQMWt5T8v5ztACupDQfTNG78uw9a/2jS9v1dDJ8CKxP0/tEW2v8Imoj8cLpDA7UvMwLb+pD2WotdA/z5IwGuMuj+8l72/QZMqQDF+ZL94+mdArItUQPFslj+iveNAWnPSwC48QEDsgto/nSq0P+fYkcC5UFPAWqUJQGojo0BC10vA1QH8QGo590BeYT1A1zEhQGOA0r8a7LpAPdC7vhqfpr4aUwnAO2B3QLYMmL4EDuq+AFyOP8wqab8+LqLAkH1EQAB6rsAtC7zAMockv0OEsMCHcc6/zrQBP9/VmL+ALjI/P5sLwAmpsUAwtGlAqv6XQBuBwD8nIJnAwRfDP2d5PEDxbClA4uQnP1OxGEHsmF7AUOFLwdv7tECnoj9A4iDawCoja8AKhei/vqpSQCgjgsBAXk/A3W7JQMrfjb8OS9XAHqKtwGDFrTygYqU/ZpDyvpvWwr9ewQBBTHzKQHZZnj+028s/TPoRQOZ7Wj+AguE/CYcRQOpNk8Duvh2/yaQSv15YqkDKMY7AMqmcQOATxL9OImy/1QUEP+geh76mlVpBC1stwBTKZT8BIim/FsFIQDYhqT+854xAvXQpwIl5i0AgFX0/IfsDwBDzd7+sqFVAPqXhvup2Z8DA0GDAIudRQF5uHUDXpJ7ALiTVvO98Rz+AkOS/9csZwROBlcFtZZk/Thn8v5bmBMHn4x9BMo7vv7JZHUDTRq7AWAWTPJ1YWUBNPhZB/S8twPiwEUBLQOy+dwy3vySKQECx+j6/SPSmv4vTsUC4Y1dATC8bwGCQAUARnBfAWiLxwI0QCMG9HRDAJYiHQdtcCEEM1+C+SfaFwHzm6L41N9q/QmATwCwIkMChUlZA3fcEQEPDiEA7XEDAq2iYP6pxTD8H14lAgw3rQJVBXD+2Yg/AqvXlPwdvv7+u0Qc/7Tnov4ZZIUAQl4K/AlMGv2eIbMCshFVAOXAFwFHckL/gAe/Aua47v4DRbEBbNhpA4Mz9v/w7JEAsrjHAUxIIwLfCg8Dxa61AATKDQNFZ2j+z2oa/LW6WQG7SgsCS8Z1Alg4kQT33Db/QlKdA+1uhQGwuHkDOc49ARtnJvwonPMDu9fm/bA5zQFwNcUA6r7W9tl26QCI3gz/TA3E+YL93vET14cBV7A9Bz6j9v9A5U8DTmUhAr81owAzzNkA89eM/zlOJPVKSocG00gnAN2CLQPIHUcA3pTXAgYmZwACewjnmkNQ/Qjbvv0ukScD9ZPjAfXiVPfiZnr0PC7k/AqN/PZlomz+a/ZFAZnVGwAPkDcBYyIjAY6SlP2w/8b4Tv5tBoqHNv03Y2L/We4RAGaiAwOGL3j80I6c+CmGjv/R8Lb9kIfG90NbUv1lvN8BaCrK++JpYQMzCAr7AT4U/vB6iQEtICz9puZ3AVijPP7EwOcCv4wzA6FbZP2sC2MDwNby/iHoawOlen8DwByVAAygtv1dEQUCaRAXA1HFqvvgZDj0QCzrA2HfWvwGVxMBeeuTAaDFmwGMkpz57i8c/B5cLwQF9YsCQKO1A\"\n  },\n  {\n    \"ProductId\": 116,\n    \"CategoryId\": 26,\n    \"Brand\": \"Ultratent\",\n    \"Model\": \"UltraLite 2-Person Backpacking Tent\",\n    \"Description\": \"Stay lightweight and protected on your outdoor adventures with the UltraLite tent. With durable materials and easy setup, it\\u0027s perfect for backpacking or camping.\",\n    \"Price\": 299.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 117,\n    \"CategoryId\": 17,\n    \"Brand\": \"Adventure Link\",\n    \"Model\": \"AdventurePro Off-Grid Satellite Communicator\",\n    \"Description\": \"Stay connected even in remote areas with the AdventurePro satellite communicator. Send texts, track your location, and access emergency services with this high-tech device.\",\n    \"Price\": 449.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 118,\n    \"CategoryId\": 47,\n    \"Brand\": \"Summit Step\",\n    \"Model\": \"PeakPro Waterproof Hiking Boots\",\n    \"Description\": \"Conquer any terrain with the PeakPro hiking boots. Featuring waterproof technology, rugged soles, and comfortable fit, these boots are a must-have for avid hikers.\",\n    \"Price\": 179.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 119,\n    \"CategoryId\": 32,\n    \"Brand\": \"GloTech\",\n    \"Model\": \"GloBeam 1000 High-Powered LED Headlamp\",\n    \"Description\": \"Light up the night with the GloBeam headlamp. With ultra-bright LED technology, long battery life, and multiple lighting modes, it\\u0027s perfect for outdoor activities after dark.\",\n    \"Price\": 89.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 12,\n    \"CategoryId\": 22,\n    \"Brand\": \"TrailTech\",\n    \"Model\": \"TrailGPS 5000\",\n    \"Description\": \"High-tech GPS system with advanced mapping and navigation features. Rugged and waterproof design for outdoor use. Long battery life and convenient touchscreen interface.\",\n    \"Price\": 199.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 120,\n    \"CategoryId\": 16,\n    \"Brand\": \"Frost Flare\",\n    \"Model\": \"ArcticPro Insulated Ski Jacket\",\n    \"Description\": \"Stay warm and stylish on the slopes with the ArcticPro ski jacket. Featuring advanced insulation, waterproof design, and thoughtful storage pockets, it\\u0027s a must-have for snowsports enthusiasts.\",\n    \"Price\": 249.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 121,\n    \"CategoryId\": 64,\n    \"Brand\": \"WaterRover\",\n    \"Model\": \"HydroTech 5000\",\n    \"Description\": \"The HydroTech 5000 is the ultimate high-tech watersports gear, with built-in GPS navigation, waterproof communication system, and advanced safety features. Dive into adventure with confidence.\",\n    \"Price\": 499.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 122,\n    \"CategoryId\": 11,\n    \"Brand\": \"Actionpro\",\n    \"Model\": \"AdventureCam 4K\",\n    \"Description\": \"Capture all your outdoor action in stunning 4K resolution with the AdventureCam 4K. Waterproof, shockproof, and equipped with advanced stabilization technology for the perfect shot every time.\",\n    \"Price\": 249.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 123,\n    \"CategoryId\": 67,\n    \"Brand\": \"Nature\\u0027s Photocopier\",\n    \"Model\": \"SolarCopy 3000\",\n    \"Description\": \"The SolarCopy 3000 is the ultimate outdoor administration tool, harnessing the power of the sun to photocopy documents up to A3 size. Sleek, lightweight, and ultra-durable - never leave home without it.\",\n    \"Price\": 149.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 124,\n    \"CategoryId\": 21,\n    \"Brand\": \"ToughTrek\",\n    \"Model\": \"SurvivalPro 2000\",\n    \"Description\": \"Be prepared for anything with the SurvivalPro 2000 emergency gear. Featuring a rugged construction, advanced survival tools, and comprehensive first aid supplies, it\\u0027s your ticket to safety in the wild.\",\n    \"Price\": 199.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 125,\n    \"CategoryId\": 62,\n    \"Brand\": \"Trailblazer Pharmaceuticals\",\n    \"Model\": \"MediKit Xpress\",\n    \"Description\": \"When you\\u0027re off the grid, the MediKit Xpress from Trailblazer Pharmaceuticals has your back. Compact, portable, and equipped with essential medical supplies, it\\u0027s the ultimate off-grid surgery kit for adventurers.\",\n    \"Price\": 349.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 126,\n    \"CategoryId\": 21,\n    \"Brand\": \"SOS Gear\",\n    \"Model\": \"SOS Emergency Beacon\",\n    \"Description\": \"Stay safe in the wilderness with this high-tech emergency beacon. Features GPS tracking, SOS alert, and long battery life.\",\n    \"Price\": 199.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 127,\n    \"CategoryId\": 15,\n    \"Brand\": \"Thirsttrek\",\n    \"Model\": \"HydraPack 2.0\",\n    \"Description\": \"Stay hydrated on the trail with this advanced hydration system. Leak-proof, BPA-free, and includes a built-in water filter.\",\n    \"Price\": 79.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 128,\n    \"CategoryId\": 15,\n    \"Brand\": \"AquaNest\",\n    \"Model\": \"AquaBottle Pro\",\n    \"Description\": \"Quench your thirst with this durable and lightweight water bottle. Insulated, easy to clean, and fits most backpack pockets.\",\n    \"Price\": 49.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 129,\n    \"CategoryId\": 67,\n    \"Brand\": \"TrailFax\",\n    \"Model\": \"TrailFax Mini\",\n    \"Description\": \"It\\u0027s business as usual, even in remote locations or on a mountaintop. Waterproof, shockproof, and preloaded with a 3G SIM card, you can send and receive faxes with ease.\",\n    \"Price\": 299.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 13,\n    \"CategoryId\": 26,\n    \"Brand\": \"EZ Camp\",\n    \"Model\": \"PopUp Shelter 2.0\",\n    \"Description\": \"The perfect portable shelter for camping, festivals, and outdoor events. Easy setup with durable materials and built-in ventilation. Compact storage and lightweight for transportation.\",\n    \"Price\": 149.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 130,\n    \"CategoryId\": 45,\n    \"Brand\": \"WildSound\",\n    \"Model\": \"WildBeat Bluetooth Speaker\",\n    \"Description\": \"Bring the party to the campsite with this portable and weatherproof Bluetooth speaker. Long battery life and 360-degree sound.\",\n    \"Price\": 129.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 131,\n    \"CategoryId\": 61,\n    \"Brand\": \"Naturevision\",\n    \"Model\": \"NatureCam 1000\",\n    \"Description\": \"Capture wildlife in stunning HD with the NatureCam 1000 trail camera. Motion-activated, long battery life, and weatherproof design.\",\n    \"Price\": 199.99,\n    \"NameEmbedding\": \"KiUfQK0yub/ka6o/7RcswJtSM0BZaARAPITwPcwTVj+UdUE+pdheQKzXSz/oJMnAmH47QMKbh0DZcZe/ehhSvYcQXkCpzJ2/4niJv9kKfkAYHKJAVrClPpbUzD+WB12/n2AswHB9/b9gbW0++ShtwNh6rz5SpcjAAF/ov5Tr1jx7toRAa4EJQH2f5z4sljbA7254v5I10r4Y89i/TMj2PwS47j9n4hc/2gsGvygXCr+9nIq/NVwTwMwAzz5cePO/GufHPy48HsDIRtu/4MnFv3DUrD/awBhAgDk0v8no0T+qarQ/6DcUP/CY+j9qrWa/KLp0QKAxmT+LBBPBfMWWPz33fb6LKihABy+vv5ihoT8DsyVAJ3sqwOxQtr5cLcc/UCx0vbKRnr8S2Zs+RCDAv5bTIL/RsGW/p+FcwDRRCL+PSue/nqLHP1bZLr9unc6/tfMRQHL2cT4bCJO+GJuPvUmwkkBo4xg9yCOkvg7khT7IrSjA3XCdPi0dksCwvz6/Y0xXQBJ3QMBa6mRA4PsFQQ3uIsBFYSRAxeVEQN6zt78x+ENASQOAv3UzQMCBwUnAMcWKwF3RZb9+H/w/0Aqrv/7Agr6Krg5ABaixvlhoeLya/iY/6jfUP5vZOz9G8TS/NHI1wCFvzb8wqG5AIMe6PHuloz50a5s/RUyNQCmSgkDnPEhA14WfQP/ItT9hKB1Azh6Sv+I62L+qIOs8kePhPgCYgEAM6QG/+WmBP2lUgz9b4Q3An/yUPzxHPT8bY3PAe/d5vkj/xj5/ghFANswQQDi6YMC8L9+/PtqJvxj/HEDwlRxAiSqWP6HzhkAdKz1Ael+KP31SGD9LGY2/yjUiQBAMjT+HbQ3AyBcCv+1akkD4Dsk/RlOhwNlPzj9/Dy3AOVACvwYnPT9UOni9WoUGwLsB5D+Al6s+4nUoQBJkjL4cjQjB3nnEv9psRcDkGhc/E8EpvllKDL/PheO/uk70Pw77tj6JEwTAxIMcv51Jib5/FAXAqFbnP0yGAb+NGQjASSi4P2Q8+j/c/Ji/Qyw3QLyROr8sZnm+CjcPP6a54r+JbkZASqAPwKPFND4BvilAsoWEP8oXDsC85jNA78cIP7ofWD+cyCRARhYrv+DibD/Hgdw/dtACQEffP8BLQwvADbusv9g/vz+AAAw/73hWP7AGGD/PhuXAnhacwJDpNMHW1qg/hogyv0LsL8CkBidAI8wGwOgNyb8POvU/eGO4P4p3aj+Wsk9AcLTjv1QXzT5qstW/QiMaPmAagkAiFj0/SDg6vfopIsAiVmrAkJiGP9FkM0DiXEM/JF+GwLCF7j1y3kjA9DEHQa3y0D/eAFE+Wj0DQGIbeT+c4jw/d/isv3usrcA4st09ATKJPhV1777knUtAQ600wLJy9L8eFV5AO+1YQIjgw78jhjDANHQGwAU9OD8oFULAEtt4P0yVm78ONkLA++2VP7pXmb83iPK+3pJXP0eV2z9rf6a+0YjYwG4KHT2x3W2+HNbZP5EVwT8k9tG/Ha2KvjegosBSlgpAf5/bv2wynz/1qCLAqXyQQJBICL0Z7d4/3lWCQCilHUDQVEK+4AfYPyLnA0AZe1BAV3Mfvj9Fn77XtCLAY8HCPyWvXL/JwlI/RY/hP9zpSD/M6Tg/2EWJP21Ea8D0vKW/Yk6tvsCjfz8WRP0+D6TWv46hL8AlfX9A2oVWP2toN8EkaYy/lL3Yv90Yj7+l3Ww+Zvf2P7lfoT/i7Kw/0zuXvwlwG8ABrwPANdwiP1Rh/D//cGI/U5CPP6Wfqz+8WY6/hkodPvwD9D9VyTTAOQRzQNXWqT82DO5AMGGnvcyppr+J1vk/tzxTwKiuHcBY1kE/K5a2v0/FaD/xFga/fZjgPxjyG8CpCmQ+Dlq1QHY+NT9W6cG/aI3LP06yhr6hdoa/oKU6P2TAGECEA0e8bHxoQEQyWsBGrsu+wcqCPzRIH8DDIgNAjVcBwFq4X7/LW+q+Sk4cPQ0dRz8oCM+8hi44P7bppT/vqVLAmvNPwM/1CT8ehzbAPgzHv++vJsB0vTC/\"\n  },\n  {\n    \"ProductId\": 132,\n    \"CategoryId\": 49,\n    \"Brand\": \"Fish Tech\",\n    \"Model\": \"AnglerPro 5000\",\n    \"Description\": \"The AnglerPro 5000 fishing rod is expertly crafted for precision casting, with durable construction and a comfortable grip for all-day use.\",\n    \"Price\": 129.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 133,\n    \"CategoryId\": 42,\n    \"Brand\": \"Strategicgear\",\n    \"Model\": \"TactiX 3000\",\n    \"Description\": \"Be prepared for any outdoor adventure with the TactiX 3000 tactical backpack. MOLLE system, hydration compatible, and rugged construction.\",\n    \"Price\": 149.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 134,\n    \"CategoryId\": 33,\n    \"Brand\": \"EcoGizmo\",\n    \"Model\": \"SolarFire 2000\",\n    \"Description\": \"Cook meals and charge devices with the SolarFire 2000 camping stove. Solar-powered, lightweight, and collapsible for easy portability.\",\n    \"Price\": 179.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 135,\n    \"CategoryId\": 61,\n    \"Brand\": \"Trail Eye\",\n    \"Model\": \"WideView 360\",\n    \"Description\": \"Experience panoramic views with the WideView 360 trail camera. 4K resolution, night vision, and remote viewing capabilities for ultimate monitoring.\",\n    \"Price\": 249.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 136,\n    \"CategoryId\": 46,\n    \"Brand\": \"Ecovolt\",\n    \"Model\": \"Solaris 500 Portable Solar Charger\",\n    \"Description\": \"The Solaris 500 is a high-efficiency solar charger designed for outdoor adventures. With a rugged build and multiple charging ports, it\\u0027s perfect for keeping your devices powered on the go.\",\n    \"Price\": 89.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 137,\n    \"CategoryId\": 36,\n    \"Brand\": \"PeakMix\",\n    \"Model\": \"WildBeat Pro DJ Controller\",\n    \"Description\": \"Take your DJ skills into the wild with the WildBeat Pro. This rugged, waterproof controller is designed for outdoor use and features advanced mixing capabilities for your wilderness parties.\",\n    \"Price\": 249.99,\n    \"NameEmbedding\": \"tt6qwMaMsr/bXGdAg1aHwFIH5r5+jzBAg8jCv9w/wr84w7o/WrwKwMarBr5haKa/EmN8QHvZHkBI1Ys/usJjQN0lUz+vgUE/nM0dQMLghUB8ep+/fN/mvterkL/MO5a/Xyrsv7X+JUDtmRPAvqIiv76uAMB+iQPBom+LQHei279hcKxA4mFrv06Tlr9AWQjAyyTuv6UFlL+O1dC/JawSQLsjOUCYZNq/9SftvmI1F79+QJW9mTp4wArPR7+yJ2HA5vGPQDjJ3D/9STzA4pnrv0LTtz/lFdY/teKaPz+GBj8WZBRAfWMWQGBy6b9404s/div1P8DfJEBctvTAPlUeP5Fewj4AUa9AWiRDv656jT8B8DM/r+SJQCcqScCGHCw/HPtRP1F0iz9ew18/EBAnv9w+gT3F+KE/E9fbvwrnTj9ahAo+D74ZwZZehMBB9ZPAoyrFP+SAOr/07ldAV9cqwFaQtT8e18Y/rwSAwK9szT8ZY7K/sNVRwL0Dj8BxYw7Aoes1P9K6xz9fgQTARb4UQfuzlcDv03o/bBJSQJw6CkB8hYu+5JaDwIO6/749kBFAMg0vwJL+pr/gfXK8yJaKvxujrz/OjZu/7nwcv/Issj/3V+i//roAQISIyb50WoM+6xbiv7G3kb8WKeJAPpxEP8amDUBh13k/llWrPz35s0DMCS9AWHmWQBXqqj5PH3lA3SmzvyC/Cr/81cO8l1iDwKwba0BIqjFAW66LQIbfVr8tqnvABnL6P2nnAECFKAnBjj0GwCbCScD+tKK/zHEOwPKBe8BuNSi/BIcqwNfuFL7cQ4g/ZSTNPydlGkDpwGFAEpbTQBWFYUDwQRXA4MlxPyX4WcAPY0nAr1b+P+ssAEE8jhlAa5oLwf2Nqr+Cni2/OTlTwC1NRsAc263AdkR3wHgYGz8EjxW/0GS+P9gV4b/rQODAC4sgQEpFED6p8RFAOgL0P9kMYcDqB/G/xJDAvzO4yD/EZpDAytBTQMubQsB7CHW+7TGcv3LCY8DQVprA8dq5PyAQZEAvrv+/Nh2EwA9Fkb+ibTRA8q5zQHtdeMBPW6E/5g6GQMjXEb9xXStAeKG/P2osNb8K8M6/ko1aP6TqoD+kbJdAadGAv15pYEBR6NZACEMrQHajqcDUWoU/YnggwNc9bkDGcyXAP8mTPy7nFr8i8EDAdO62vyonZMHeIqBAv4bvPsSiQUCveGg/w5w9wPyC/b4dQ4I/OVgYP8S/3j/C+cFAytilPxqwST+CjAVABFpPwPdK1UAGt2s+NGJJwM8KMz/yNtS/YZNRPq2UVb+jt62+u5B7QDhkM0Aq2THAkUI6QUomvUAHIcdA3CymvnDVIL54Gt+/8JSWvzt96sBWIZc/LDL/Px/GhUCK6t8+BFwEQOSzDsD2VwLAImYWP6GKLkBfRNjAtl5uPx6pGT6mzi2/ROArwGDRejz2rl7AgM2hQBCwhz777WTAo7ajv/u/oz9VgzTAnZuWwJsqGECOO6q+oHQgQNsoPT+V8CjAIESHvz8slMDdZfw/FyVhQGigj0DVTfc+UHKXQCZyK8Ay0io++v6hQNGYZ7954oFATGmhQKWdD8Af30q/c/SswCN98D/MLlS/CsUNP1ea20CFHeI/cDhPP0pQBz8Lrqu/epN1PzAMvj/nKdC/4KX8v9ZVI78brw5Af8zEvzvlQMBZrIhAwRuoQG60b8FkJYrAhUrCv+PUF8A00YPA2E23P+svlEA4zVrAM8G/wLGQ9L6JQb4/et9/QOBSKrxRuyFAkxAbQMxTNb4YWP88MAnzP9LQxUDAEKnAxM6jvReLUkD4ZyRBG7T9v9OdOUCKDxRA+S0awDKxTb8Lf9ZAPCRowMTqWL/SyN6/9cqNQEw/C8DrOlBA/vV9P9gOPj+l8pM+CgXYP/S/8b+90PC/AYaSP8AdRz9/o5o/dZciv/6qy8CNKpa/h2fGv1TeAz+s7R5AsVLev14gor9uL4m/Pn4PQLfr8r/Wq0JA8tiywFex/b7QdhZAVOqGvhxO4j2yPBg+VfZGQNCqg8CWI4jA\"\n  },\n  {\n    \"ProductId\": 138,\n    \"CategoryId\": 39,\n    \"Brand\": \"Survive All\",\n    \"Model\": \"Ultimate Survival Kit 3000\",\n    \"Description\": \"Be prepared for anything with the Ultimate Survival Kit 3000. Packed with essential tools and gear for outdoor survival, this kit is a must-have for any adventurer.\",\n    \"Price\": 169.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 139,\n    \"CategoryId\": 7,\n    \"Brand\": \"WheelWise\",\n    \"Model\": \"SmartCyclo GPS Bike Computer\",\n    \"Description\": \"The SmartCyclo GPS Bike Computer is your ultimate cycling companion. With advanced navigation, performance tracking, and safety features, it\\u0027s the perfect gadget for serious cyclists.\",\n    \"Price\": 199.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 14,\n    \"CategoryId\": 19,\n    \"Brand\": \"BackCountry Cook\",\n    \"Model\": \"Propane Camp Stove\",\n    \"Description\": \"High-performance camping stove with adjustable heat output and compact design. Perfect for outdoor cooking and emergency preparedness. Compatible with standard propane canisters.\",\n    \"Price\": 79.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 140,\n    \"CategoryId\": 45,\n    \"Brand\": \"Trektunes\",\n    \"Model\": \"RuggedSound Waterproof Bluetooth Speaker\",\n    \"Description\": \"Take your music with you on all your outdoor adventures with the RuggedSound Waterproof Bluetooth Speaker. Its durable, waterproof design and long battery life make it the perfect outdoor audio companion.\",\n    \"Price\": 79.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 141,\n    \"CategoryId\": 5,\n    \"Brand\": \"SOS Gear\",\n    \"Model\": \"Emergency Survival Kit\",\n    \"Description\": \"Be prepared for any outdoor adventure with this comprehensive survival kit, including a multi-tool, fire starter, and emergency blanket.\",\n    \"Price\": 49.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 142,\n    \"CategoryId\": 9,\n    \"Brand\": \"Dreamscape\",\n    \"Model\": \"UltraLight Camping Hammock\",\n    \"Description\": \"Rest easy under the stars with this lightweight and durable camping hammock, perfect for backpacking and adventure travel.\",\n    \"Price\": 79.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 143,\n    \"CategoryId\": 53,\n    \"Brand\": \"Trail Taste\",\n    \"Model\": \"Titanium Camping Cookware Set\",\n    \"Description\": \"Cook up a delicious meal in the great outdoors with this high-quality, lightweight titanium cookware set. Includes pots, pans, and utensils.\",\n    \"Price\": 129.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 144,\n    \"CategoryId\": 4,\n    \"Brand\": \"RidgeRope\",\n    \"Model\": \"ProLite Climbing Harness\",\n    \"Description\": \"Stay safe while scaling new heights with this durable and comfortable climbing harness, designed for maximum performance and security.\",\n    \"Price\": 149.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 145,\n    \"CategoryId\": 1,\n    \"Brand\": \"PowerBeam\",\n    \"Model\": \"Solar Powered Portable Charger\",\n    \"Description\": \"Harness the power of the sun to keep your devices charged on the go. This portable solar charger is perfect for outdoor adventures and emergency preparedness.\",\n    \"Price\": 59.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 146,\n    \"CategoryId\": 41,\n    \"Brand\": \"Nutritech\",\n    \"Model\": \"Energy Boost 500\",\n    \"Description\": \"Fuel your outdoor adventures with Nutritech\\u0027s Energy Boost 500. Packed with essential nutrients and vitamins to keep you going strong. Perfect for hiking, camping, and long treks.\",\n    \"Price\": 29.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 147,\n    \"CategoryId\": 63,\n    \"Brand\": \"AeroVision\",\n    \"Model\": \"SkyMaster X2000\",\n    \"Description\": \"Take your outdoor photography to new heights with the SkyMaster X2000 aerial drone from AeroVision. With 4K camera, GPS navigation, and 30-minute flight time, it\\u0027s perfect for capturing breathtaking landscapes.\",\n    \"Price\": 599.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 148,\n    \"CategoryId\": 9,\n    \"Brand\": \"Slumberpeak\",\n    \"Model\": \"Alpine Dream 3000\",\n    \"Description\": \"Get a restful night\\u0027s sleep in the great outdoors with the Alpine Dream 3000 sleeping bag from Slumberpeak. With ultra-soft insulation and waterproof shell, it\\u0027s ideal for cold weather camping.\",\n    \"Price\": 149.99,\n    \"NameEmbedding\": \"QxE+wN7k1r7qpQFAaqmuPxC+1b+OjJQ9W8/Qv578lb8HXf4+krnDvrwSDEBY0JrAism9PyJ7tD9SITw/i4ExP2RGJUAjLbg/jLDNPuzA6T+2kd5Aevezv8GfSkBHMABAl4FtQI5FBkDWzhXAbrENwG88zb+szPXAfNW6v8dgHj8YS4JAVhC7vwcCBL+KGk7Ak5iCwAbIVUDNdLXA0ByrQGAYMkBpYTdAjVsNwIm3LL+OX8m/pd1Dv7vgg7/oFbq+zIDCP1aZFcCkflc/Pk8wv6KqFz8ZKqM/DW3PPzKyRj5g01e+qCVOv+ykT0CxNUBAmiFwP4w+tT8jRwHBYOqcP6U3yz9ial5AhtW2wBgDubx36WI/ixacPuAh779XfDc/w+wYQKRoMD/SHAM+1SRiwMGUFsDTc5E/DoUOwKSVjr8gxJK/GjW5v7EBGMBnBVzA5en2Pct9m7/woyk/OsAKQBm5oD9wMBu9zD7Sv0DkDMDo1ty/XgY3wPJFY78cQM8+2yorQAePu7+vdKa/ukokQZIfbb/dJZ9AVppAQD73HED4pgs+WA4owOQL4j7svFS/dU1xwKCHyj0LHQpAtWZvP/kN0z/2kOa+9HMnQMFpJD93jldAqoAAQFfs1j9QMqU/dzO2wI3TqT/WkAVAMSwswF9Dpr+TTE++BEacQEJ8dUBreT1AZ0SVQCIrD0AZZodAOqsMvnoEhr5IzC3AphXVPia1hj7EUmrADCymv4gZScBy4ke/hqk5v1gCxkDDta7A5iIRQKaiBr4cSRLA7ecVQMHACsB5tac/woEFv0szJ8AVGRFAMU/Tvzk7Oj6KYO2/1JjHP45FYkCr+TnAslbzPyTQtj+uawC/wLXbP9UxeUAi/yRAb5NHwNgejT9u8g9A9S99v8H+ocBZQSDAyHB1QCDWTr/R/AnAevgxQExWBz+0wFPAiwUCvwq27b8Hoek/2ESMvPYmRz9SG4o/ffMJQHU6qj/AR3/ADnqYv5OUAj8BJEk/8wHIPxtJv79L03I/A/CePyz9D8AC/oW/akMKPxvLXcCwnlk+BNLJvlklHcDi6J1AdA8Vv92BeL8m3Sm/IFGGQPjAfD3HGRrAtJ2Pv5ffD0CMzYm+wKy1P1AsHjzhKo9A68oIQFf0qL6s3jI/lhP9v5xO/r81UX7Ar/W+PwBGZUACI1fAfocDwVaoV8FbBl1A4yc4QGLEXcB+mFNAiKsawMWoUsDGSQ7AYj0dv24DjD9pvMpArXlEwMDdIL2iBpU/o5byPbLBSUDbScu+xb/Xv5KXJD/oTf2/zaOQPsDn1r2aTzbAGbaXPhu0sr4zYcvAd3g8QdopP0AaMyVA/xVjwNr0hEBrnYq/vOOBP7OqwMAMR9O+tbYVv8D1X0CDqTJAwyNNP9YYm7/Cksq/7gjzQNzO87/a0HfA2WN8v6YuEsC/yDvAbms2P0CYLUBgKCRAZ7AKQK92Iz9tWLg/n7Hsv1ybRUACJpa+lvYWwfVEg75DCd6+h2ALvyncoT+l6Xm/BXxHQMdeBr+GyFlAJIMSQHqxPsBPnKW/PuHCP79Snb9Q7ec/W4XbP8whO8Ayo0/AkwajQOh4wj+NAkNApKgNwP5zjEB1eFS/9Z6Iv1MKoMDqCHI/1y8+PpiyW0DxutQ/xbt9wEU7Iz86WiY/3Go5QHfnRkAc2jw/aLeuv6fxS8DKl0dAUpvLv6ANW8EWO7Y/rsBxwKbdMsDeXp8/TYqMwGJnyb/e+YdAimkWwLpDjj5/54LA/fQfQE3JKECCpck/l3EaQFUUBUDMR8s/sNwBwPJEE0BIity+LeMFwAK1tED0u0lBT4lrP6vO1r/QSrI/4oTPP0UlkT+F14w+tyNRQDSWrDwgG568mYIUQEq7Lr9MrOm/o/KQQB5gxL/hgZ2/9/MUQNuVAj4Cq+y/GnGdv7jFW71CJGZAlQt4QGIOgsDYCAPAg0YCwEuI2j92JT2/Ckotv16pb8B8LLXAOuwfv5HwWMDvyVtA4woHwIpMNsB0FY2/H0cvwG7TBj6tETPA+sgZv6J2ib9pwQDA\"\n  },\n  {\n    \"ProductId\": 149,\n    \"CategoryId\": 15,\n    \"Brand\": \"Thirsttrek\",\n    \"Model\": \"AquaFlow Pro\",\n    \"Description\": \"Stay hydrated on your adventures with the AquaFlow Pro hydration system from Thirsttrek. Featuring a BPA-free reservoir, easy-flow bite valve, and adjustable straps for a comfortable fit.\",\n    \"Price\": 39.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 15,\n    \"CategoryId\": 60,\n    \"Brand\": \"AdventureElec\",\n    \"Model\": \"AdventurePro 1000\",\n    \"Description\": \"Outdoor-ready portable power bank with fast charging and rugged construction. Multiple USB ports for charging electronics on the go. LED indicator lights for battery status.\",\n    \"Price\": 59.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 150,\n    \"CategoryId\": 56,\n    \"Brand\": \"Buzzoff\",\n    \"Model\": \"Outdoor Shield Pro\",\n    \"Description\": \"Protect yourself from pesky bugs with the Outdoor Shield Pro insect repellent from Buzzoff. Formulated with DEET for long-lasting protection, it\\u0027s a must-have for camping and hiking trips.\",\n    \"Price\": 14.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 151,\n    \"CategoryId\": 5,\n    \"Brand\": \"Resilience Gear\",\n    \"Model\": \"Survivor Multi-Tool\",\n    \"Description\": \"Be prepared for anything with this durable and versatile multi-tool. Features include a knife, saw, fire starter, and more.\",\n    \"Price\": 49.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 152,\n    \"CategoryId\": 35,\n    \"Brand\": \"Sure Survive\",\n    \"Model\": \"Emergency Beacon Light\",\n    \"Description\": \"Stay visible in any outdoor situation with this waterproof and long-lasting emergency beacon light. Offers multiple flash modes for maximum visibility.\",\n    \"Price\": 29.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 153,\n    \"CategoryId\": 41,\n    \"Brand\": \"EcoFuels\",\n    \"Model\": \"Organic Energy Bars\",\n    \"Description\": \"Fuel your adventures with these all-natural energy bars. Packed with essential nutrients and available in a variety of delicious flavors.\",\n    \"Price\": 14.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 154,\n    \"CategoryId\": 35,\n    \"Brand\": \"GuardianGear\",\n    \"Model\": \"GPS Personal Locator\",\n    \"Description\": \"Stay connected and safe with this compact GPS personal locator. Features live tracking, SOS button, and long battery life.\",\n    \"Price\": 99.99,\n    \"NameEmbedding\": \"FX31PbYZUL3iwUxAZEzgvzBdkz8LidLA5CarQJtOe0DCS6a/k79AwMFe+j/4Hb7Af246PyAETkCfA/Q/KFlpwKfIhD/omsM/5p12QPgghzyLktxAp6CHwNITpb+uI3fAZvJ/PmjfREA6Z+i/PNh3vyY+J8AMsuXAcU7VP8BNhsBhjgJANN1SQH4OZ8CFfvS+o7AYvmCJJUBoG9G/gtyOPzP9mEB0TH6/IKtYwJuu0D+f8dC/pl6hwNR6Cb6IUXq9lJ8QwOJymMDETMu/T7eBP0gqKb+d4xJA9qgJQM5oLT/T3yxASmHWv11VhL6wWAs/uy0pPzqqej8kAYDBVAyNPnNW5r/HA7w/hT6AvzahscDxah7A2BgqP6lzQEDafsNAwtIuPxSTO0AQqCxAU9AswMja2b+gA54/OqAhwF5XbEDcy/s/ICJ0PzSpH0C5InU/rlogQIMHIcBEPUpAGgx6wIdw0ECM/sE/9xQdP6yZrr9+urRAbA1ZP6jMvb/jUYnAHIWfP3+/GD9NGvq/EM4uQeyea7/XKVpAZSmXQBIrI0C8L3BArbgKwJCAHzw+FFQ+VmYDwPmI3D9alIhAageJP1HJzT9mWSzAMdf0v0IWYEDcOwVAXX9IQLhBtj9Dy88/DD6pwBRqQb+Wl/g/xpsmv5GIgUAurGo/uK3yP29tx0BpgkS/JN+RQIyOUEDcOCvA1IZmwHJgrb72oaM+6Do7P0aVFEDsaAy/3W0Fv/oaVEAVIqXAWXU1wHfWX0Bvt0zAO6JIvwBs4ECRjS3A5YKqP8sVvz7it0/AKUxKwHgGYr7Ci4RA++0BP3hLXzyRhlxA6eHCQJTHgUDiONvAASEgQLqdUUBwZ1XA3mZJPmsK+EA4j7A/HwUOwdBOtz3lljVAbJ2tPslAtj9wJzVAmmK4P2yekD4UWLW+OzWgQBg6Oz9fo3vAG1qVQPMsQcACvay+M/pRwMsFHsB0+y+/04kfv3xVUL7Wok2/Do5BwBrwAL/DUv6/SuANwGECjT9REZ++018aQHLMscATpq2/fGMswGjFd8Av282/OIWCv4vyisAE0Q5BK047wEMHgD+kdwRAkvNEQK7iWz85WSq/5QFGwFoNuj8NJRBA8WRFQNjoG7+Qw7BAJjsJv+YAC8DzB7TADqu8P05cpb+tEynALmBrQPrzWcDUEMM/Kr2IwL/JZcEOIMi/UaWMv2UZEEBoSpC/a4g+PxCXXr9Ue6tAfTVNQMDbQ7/eCN5AeAPMwCIMpj9XZdtAufe1P2dwE0CiMwbAWRJ6P+Klwr6RZZk/V1pzPtQBkT+6fmnAsBJ6wPuYir9N7/W/m2wyQZwavkBwRes8pP0SwNF3QkCUYRC+2YjCPzcW08DaxgRA/NDsP2gYgL/9NSVADIktQIaGor9Z1TfAImKgQGKhhkD6ZOw+slH+vt15a8DYMonAFmIsQCeSGD8hbes/u9ePP4U9yb8IhNg/Gpn0wFSC/z+E+KXAG/2swOambL8h2nrAv1W0P2cmNMB04hHAdqU7QF5dOcDjEAJBd1R2v71kDsD2XcE/NgKEQDF5L8CQGUe+V4ZWQM8mecAjrM8+8NmQP6nrmr9caZhAgndDP9XO878FgojAynBTv9HSV0CqzrC/FMwgPyWoMj/8xiE/oQ86QJWHAcANc7++HC/Wvu55971a4wRAeGMHwFHGwMA+Zo9Ar8cHwLR7hMH+sjXA6V1XPtNMRcD9ZQjALWsFP64RB0C1YY9A33ClvzLQnr/UFv89sIZ4P9DM778ZezbAt1sAQJ59mEDm4B2/cw7Ov91DBMBoOW/AwWpiQMZuJ0BZdzBB9f6zP0vQlL8q1qlAL8cEP8gXJ8ANcWs/sm2JwHLIqj4qnhnAFySQQLyeKz8woiVAGrs4QMtQTT9IDby/HLdNPMKkNL/RxTfAuR4OQBAv9T+7IXM+RAwQQWUC9sCP5qfAjlhtvyZajL+6Nqg9BrCDvrsmFMANh7DA/6yCvWPhJD4jsgJAow8XwGuMNcC2Tdq/4jJawHHiIj8YybM+yAwPParQAMFDQ4RA\"\n  },\n  {\n    \"ProductId\": 155,\n    \"CategoryId\": 34,\n    \"Brand\": \"Traveltech\",\n    \"Model\": \"Portable Solar Charger\",\n    \"Description\": \"Never run out of power on the go with this high-efficiency portable solar charger. Works with all USB devices and is perfect for travel or outdoor activities.\",\n    \"Price\": 79.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 156,\n    \"CategoryId\": 20,\n    \"Brand\": \"Glacierpro\",\n    \"Model\": \"Arctic Ice Grip Crampons\",\n    \"Description\": \"Stay safe on icy terrain with the Arctic Ice Grip Crampons from Glacierpro. Designed for durability and traction, these crampons are a must-have for winter adventurers.\",\n    \"Price\": 89.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 157,\n    \"CategoryId\": 11,\n    \"Brand\": \"Extremeview\",\n    \"Model\": \"360X Action Camera\",\n    \"Description\": \"Capture every adrenaline-filled moment with the 360X Action Camera from Extremeview. With 4K video and waterproof casing, this camera is built for adventure.\",\n    \"Price\": 199.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 158,\n    \"CategoryId\": 15,\n    \"Brand\": \"Thirsttrek\",\n    \"Model\": \"HydraHike Hydration Pack\",\n    \"Description\": \"Stay hydrated on the go with the HydraHike Hydration Pack from Thirsttrek. This pack includes a built-in water bladder and multiple storage compartments for all your essentials.\",\n    \"Price\": 79.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 159,\n    \"CategoryId\": 22,\n    \"Brand\": \"Outdoor Pro\",\n    \"Model\": \"Rugged Solar Power Bank\",\n    \"Description\": \"Never run out of power on your outdoor expeditions with the Rugged Solar Power Bank from Outdoor Pro. With a durable, shockproof design and solar charging capability, this power bank is a game changer.\",\n    \"Price\": 49.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 16,\n    \"CategoryId\": 6,\n    \"Brand\": \"Pureh2O\",\n    \"Model\": \"AquaMax Water Filtration System\",\n    \"Description\": \"Stay hydrated on your outdoor adventures with the AquaMax Water Filtration System. Removes 99.9% of waterborne bacteria and protozoa. Easy to use and lightweight.\",\n    \"Price\": 79.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 160,\n    \"CategoryId\": 25,\n    \"Brand\": \"Geotrack\",\n    \"Model\": \"Trailblazer GPS Navigation Device\",\n    \"Description\": \"Navigate the great outdoors with confidence using the Trailblazer GPS Navigation Device from Geotrack. With preloaded maps and long battery life, this device is essential for any outdoor enthusiast.\",\n    \"Price\": 149.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 161,\n    \"CategoryId\": 33,\n    \"Brand\": \"SummitSeat\",\n    \"Model\": \"ErgoVent Foldable Chair\",\n    \"Description\": \"The ErgoVent Foldable Chair is designed for temporary seating during light outdoor activities.\",\n    \"Price\": 149.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 162,\n    \"CategoryId\": 35,\n    \"Brand\": \"Sure Survive\",\n    \"Model\": \"Safety Beacon 3000\",\n    \"Description\": \"Stay safe in the wilderness with this high-tech emergency beacon. Sends out distress signals and has built-in GPS tracking. A must-have for any outdoor trek.\",\n    \"Price\": 99.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 163,\n    \"CategoryId\": 61,\n    \"Brand\": \"Wildwatch\",\n    \"Model\": \"Stealth Cam 500\",\n    \"Description\": \"Capture wildlife in their natural habitat with this high-resolution trail camera. Night vision and motion detection make it perfect for outdoor research and surveillance.\",\n    \"Price\": 199.99,\n    \"NameEmbedding\": \"fxmlv+rsvD5RFk2/X7y4v96RaEB89Hc/PPzwPQRn1z6K/lg+hFReP3WwzD/iTIrAOvr9PwKinz9rrOo/wY6xvxh2sz9H9py/vNABvwGCb0DQ8oM++AbnvyZmcEBvS8O/pC/Iv7H8wT4b+LG+dlcYP5Muh8B/R/bAvm0ZPfh9o8Cg6UJAOSqJPpC2+DwNhIPAlA6svwJMMj9h95G/MxjMPzxTAsC63PI/6Kwxv6Rfhr0gk0G/WuiUwAZhKj/48zY+BHPoP2iOH8A80SDAsGecPpDP2j/Qg/g/lq0EP6geCL88Jn1AMaLrPhuSFz9ybFm+0mlUQDQqqj8DKM3A/TPGP4cQiD55aDtAXD/lvjIGer/Bi+c/jkozwDwZMsAOcuQ/nN/Ivvp+jT6+z8k9LOkQv7u75r4nzFq/MiodwAjcHcCt2QLAv9MqwLeJAL+xFOi+KJweQA+5GL/dCKxAudQRP97iVEDKLKk/gN26v7DJQT/iz3a/Wjxlv0pqfsAInCjAvGseQPVRLT+K3lhA3R0EQRx0xb8KZ4E/r+kwQASHFL+o17RA+39CwKSV3L8vDa++hAWEwLqdoj8VbYBAujkmP86IP0ASjeO9acCnv1/8WT/ciAi/oYM9QBIG5T9CdStAfEYXP6xbSb8YbMlA1IEowHBIRUAYc9Q/xk6HQAeOaEDHIWZAUU+UQPUMfD/c8gg/Bv2gvra/G79ZujY/ZscYwEdfID8hKUA+lmYlQGO4AcD+O2zATF4AQCS8ZEDtLqHAJrXNP0qCSr/RHi5Aa2H1P9tYp79AgdS8R0yhvwP7yT4N0dU/H8Uwv7IUJkDR+CC/DrWMv8eVj0BaPqe/ShpbQEy7y74vI0/AFfoCQNxLh0DaKd4/WojBwGpgnL6m7EI/jzL1v2wdpT0DDinAej0OwJT0mT9eCCe9gJqKP8rg3T8YKuTAm48/P1JApb8KVFy/aBsNwI2cGMDGgNy/kC9aQPCACb++5JXAqZOiPyhx470t7h0/QHHZP/Dp2D/iGq3AWJ28P1WxDkDYgr4/PQwnQDVvGcAFLQDAyzCPvwhgfb9C3SNAHX9DwBo4xj9Tkw1AUhotQC33EMBowjBAb4MuwNtiZD+GakhAR6QEv1Jshj9X8R4/SrkQP3JM67+bZ0LAClcVwOPDD0AbjLY/xPTxvxI0S79cAjjA7vTgv0CEPMHEp1u/WBK7vLK/OkCKwwa/nmdcwCCOoL5c7L0/Bup1QBQ92T50c8BAnVR6voJTJ7+tIyc+v94qQK6IzEBqL3i/BzKFP8AdV8DI4XE9lIKWP7M9NkCVVIu/sN6fPSaERUBb1+m+ZuYFQYtHBEAWA8Q/rbAhPeqcBr8Py8S+2ISdP2M2i8AwPnA+4ZZYPgNQ6r79Ti9AAtgcPzztLsBvjg6//qoYQCRajL2efafAlfu2vlOUt79A8T6/Ho1nv5a/FD/qJ8y/F2SDPw8Epr/eyf8+dxwSv7ZnoD/aahXAmOkwwKgtqjyxDjG+aNPOP5IoUcDdXBc/O+ldv87wtMCVh8s/lHKyP8W4Ir8AIKK+YTpmQPSrgcA4lUo/bRGJQEzEID/00gTASsiRPyHlSz8jMbg/ybCGv+xsPL9ArzfABSKZQBbEakAcap8+iNNbvpKH2T82+2s/79qjP45xhcAdXK0+WqNbvkigsz5fSQDAwjEXwF69gcDMFYxAhEJlv4h4O8EE/de/3LxAP2VPE7680MW+FxELwEUapD8mMLm/a7BNwCqzX71Jq1LAGoutP74aIj6GxwBA+ETgP5Djhz+TiG2/lYr3v8FKMkCqcCvAZpbDP5yPF7+OuslAzYQvP2JuRL7NdT5AGgXjv2ho6L9G6p4/A9kiwNpdiz8YaCDAqC/EPyCmEcCwSn6+rd87v1G3QUBVChZAyTAbP2AIyj2XiZI/211SP7PKlT82KIq/mVMtQGc+V8D5NJG/Hw+EPywnN8Cf5G5Asm69v1jJKsCyMhPAG6cYvzx3LUBg8tQ/8bylv69d4T+V7h8/yB3Lv5llzz+YCA3ADgK5vz1PCr+LygjA\"\n  },\n  {\n    \"ProductId\": 164,\n    \"CategoryId\": 12,\n    \"Brand\": \"MantleMaster\",\n    \"Model\": \"Excavator Pro 8000\",\n    \"Description\": \"Dig deep with this heavy-duty excavation tool. Perfect for building campsites, clearing paths, or uncovering hidden treasures. Durable and reliable for all expeditions.\",\n    \"Price\": 299.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 165,\n    \"CategoryId\": 18,\n    \"Brand\": \"OutdoorHaven\",\n    \"Model\": \"Rugged Shelter 600\",\n    \"Description\": \"Find refuge in the great outdoors with this sturdy camping shelter. Weatherproof and easy to set up, it\\u0027s the perfect home away from home for any camping trip.\",\n    \"Price\": 249.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 166,\n    \"CategoryId\": 43,\n    \"Brand\": \"XploreraTV\",\n    \"Model\": \"TerrainX 500 ATV\",\n    \"Description\": \"The TerrainX 500 ATV is built for rugged outdoor adventures. With all-terrain capabilities, powerful engine, and durable construction, it\\u0027s the perfect vehicle for off-road exploration.\",\n    \"Price\": 5999.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 167,\n    \"CategoryId\": 14,\n    \"Brand\": \"Trail Chef\",\n    \"Model\": \"Backpacker Cookware Set\",\n    \"Description\": \"The Backpacker Cookware Set by Trail Chef is designed for cooking delicious meals in the backcountry. Lightweight, compact, and durable, it includes everything you need for outdoor culinary adventures.\",\n    \"Price\": 89.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 168,\n    \"CategoryId\": 36,\n    \"Brand\": \"PeakMix\",\n    \"Model\": \"WildDJ Pro Mixer\",\n    \"Description\": \"The WildDJ Pro Mixer by PeakMix is a high-tech DJing system for wilderness parties. With rugged construction, long battery life, and advanced mixing features, it\\u0027s the ultimate outdoor DJ setup.\",\n    \"Price\": 499.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 169,\n    \"CategoryId\": 53,\n    \"Brand\": \"Adventure Cook\",\n    \"Model\": \"Trailblazer Camping Cookware Set\",\n    \"Description\": \"The Trailblazer Camping Cookware Set by Adventure Cook is perfect for outdoor cooking. Lightweight, compact, and versatile, it includes pots, pans, and utensils for gourmet meals on the go.\",\n    \"Price\": 79.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 17,\n    \"CategoryId\": 30,\n    \"Brand\": \"TechShield\",\n    \"Model\": \"RidgeRunner Weatherproof Jacket\",\n    \"Description\": \"Stay protected from the elements with the RidgeRunner Weatherproof Jacket. Made with durable, waterproof material and featuring advanced ventilation technology. Perfect for outdoor enthusiasts.\",\n    \"Price\": 149.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 170,\n    \"CategoryId\": 15,\n    \"Brand\": \"Hydra Pulse\",\n    \"Model\": \"AquaFlow Hydration System\",\n    \"Description\": \"The AquaFlow Hydration System by Hydra Pulse is a high-tech solution for staying hydrated on the trail. With a hands-free design, multiple carrying options, and advanced filtration, it\\u0027s the ultimate outdoor water system.\",\n    \"Price\": 129.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 171,\n    \"CategoryId\": 42,\n    \"Brand\": \"Tactic Tech\",\n    \"Model\": \"Stealth Recon Backpack\",\n    \"Description\": \"The ultimate tactical gear for any outdoor mission. Features multiple compartments, hydration bladder compatibility, and durable construction.\",\n    \"Price\": 149.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 172,\n    \"CategoryId\": 51,\n    \"Brand\": \"Summit Pole\",\n    \"Model\": \"Trailblazer Carbon Trekking Poles\",\n    \"Description\": \"Lightweight and sturdy trekking poles for enhanced stability on any terrain. Ergonomic grips and adjustable length for a custom fit.\",\n    \"Price\": 79.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 173,\n    \"CategoryId\": 27,\n    \"Brand\": \"Eco Vest\",\n    \"Model\": \"TechShell Smart Jacket\",\n    \"Description\": \"Stay warm and connected with this smart outerwear featuring built-in heating technology. Waterproof and windproof for all-weather performance.\",\n    \"Price\": 199.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 174,\n    \"CategoryId\": 11,\n    \"Brand\": \"Actionpro\",\n    \"Model\": \"AdventureX 4K Action Camera\",\n    \"Description\": \"Capture all your outdoor adventures in stunning 4K quality. Waterproof, shockproof, and equipped with advanced image stabilization.\",\n    \"Price\": 249.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 175,\n    \"CategoryId\": 49,\n    \"Brand\": \"Fish Tech\",\n    \"Model\": \"SonarPro Portable Fish Finder\",\n    \"Description\": \"Find fish quickly and easily with this portable sonar fish finder. Wireless connectivity and built-in GPS for accurate fish tracking.\",\n    \"Price\": 129.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 176,\n    \"CategoryId\": 37,\n    \"Brand\": \"Wander Lens\",\n    \"Model\": \"AdventurePro 4500\",\n    \"Description\": \"Capture stunning outdoor shots with this high-tech adventure photography camera. Waterproof, shockproof, and 4K video capabilities.\",\n    \"Price\": 699.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 177,\n    \"CategoryId\": 18,\n    \"Brand\": \"Trektent\",\n    \"Model\": \"UltraLight 2-Person\",\n    \"Description\": \"Stay dry and comfortable in the great outdoors with this lightweight, durable camping shelter. Easy setup and compact for travel.\",\n    \"Price\": 249.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 178,\n    \"CategoryId\": 41,\n    \"Brand\": \"EcoFuels\",\n    \"Model\": \"PowerBar Pro 2021\",\n    \"Description\": \"Fuel your adventures with these nutrition bars packed with sustainable, high-energy ingredients. Vegan and gluten-free options.\",\n    \"Price\": 29.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 179,\n    \"CategoryId\": 59,\n    \"Brand\": \"PaddlePower\",\n    \"Model\": \"AquaPro 3000\",\n    \"Description\": \"Conquer the water with this top-of-the-line kayaking gear. Lightweight paddle with adjustable length and durable, buoyant kayak seat.\",\n    \"Price\": 349.99,\n    \"NameEmbedding\": \"ju4ZwMSOTsBRRKM/0I+Av4MZPr9H1zw+99f+P4CPPz8VkCe/k2qnvbvWKUCjR7TAaWT4Pm+apT8JwA/AZ7BgQEdWaEAnnvI+XDhTwJLisz+5mohA2zH1vuF5kb9oIum/3GA3vpDhQT+C1Cq/kmwZPoyHij9Ph9TAWB8OwFEF3b8G2jk/UYmLP8dj4b9zRIW/g1Xlv0m6B8AMlcm/w2iJv6jc3L5bFMQ+tGh+v4QcAz90JAy/hPKQvtQAMT/CPMa/mtm+QBLJ9b8KR9k/tlklwDAK4z8y8pq/2pQIQPa7Z7/0Tww/h4gLP9BFgT88kpy/+hSQQK5vXEAgYeHAxqSZQB7WzL+Z5zhAOAFyPtJ6PEDca/E/oPE0vIeWIMA7tEW/uvoGPpY2U0BhNaE+zMbGPZLqk7/thZ6/sv+9v9lw4z5DcZc/xOg+wCBVv78Et7o9hmcuvljwxryyaF9AnZCVP7A1fT+Jpoy/VdyDwLO7Gb8ENr6/4KLdvlrCZsA2uGA+ylU9PZxSl8DGtj7AYIPjQEhPHz/1TOQ/g7bFP9WUWMACMBy+Y4yAv/hEz77yGqM+mb0awCYXWz5iOzW/Fvm5vnxIYr8tr7U9Wmdnv4nurD/s1lC/ceoIPhn35L9WN5Y+XStfwMoVrb9aNINAVlFMPyR0mr8GqWA/p44+QMxFT0DhlJa/uLItQLh9uL608qI+GWJNwJjwET+Ltjm+iZPYvx2oGkBekgLAiTSWP6Ls+j84rSnAh6SEPz4X7D+la6bAmKqpP03dxr71Puq/pNzqvwSsNL70F7I/qNEQwEx6b0AJB/8/pE8KvpgMVkAINd++HiFvQHnKNUBdOiPAQpV3P/eXA8DOuNi/7I7Lv8aTd0CXPpBAgda8wFlCM0DsyVK/rltgwLq0cD+uUjLAN8uaP6j/A77s1Ji/KxmfPy117j5DitW/bBcTQG9/sz82xRFAk1ykv88MGkAwiHs80JPUvcRrBECUhpi//nRCvqkq8T+kCVW/DVfFP6J66b9nXEQ/oO4Tvnt0g0B5nbQ/NI87v55tdb8agZK/GTr/P7RChcDOgQFA68XJvhzTgL7N3QVAxf6cP0gSqT9U/72/POszQPC+S8DWEbdAr7LVv9Vu1T/EUylA3vU9v04LNMCjg66+2cIhQMVSIEBstuO/QZA5P4gsGUAgzS7AZEIkwO+gL8Gcl0E/6Blfvw4E9r9AKUtAir0+PmgcVL2zDlq9eGDvvTiGmz5O+qs/Lf31vxJAIb+KlKA/KA+dv7cQdEC3RzZAQkmyvyivLz8MfPg/KhOPvpRmQkBRS5E/qw0sQPZt1z9LYFXAFtkaQc10kT80PBBAucmsPzgFn74tIyu/hEaxvjI9IsAMvsK9aPY3vTXEKr8GlB++j+FKvsh/BL98M7E/bVdTQGubgL7rvKjAJGlOP7CK0L8xESI/CKgnP9Ai7r8OGom+VDB8QFLbG8AP9S2/FvxYwKh1jz+OYKU/K/WQwPaYuT8DjQjAS+kwv/9+Vj+ERyY9qNeqvHCvAMAFXhA/sfo4v0ciEb8g3do+9LsBQNTVI8CT4Zs+WdlBP1VNNkAwfSdAGp0uQP5feL6SG7Q/Cl8iwJFMP0Cib1m+cutdv3qvMr6yW92+OLS4PCHuCEDt7tQ+v/ZOv8RCoT/GdYe/seYOvwprXD96x0A/blr9vyI3uz8KkYpAGNBjP0STM8F2bcM+upKnP3TEk7+Ok0a/0kyMv8wTBT9QotW+Ol42wA0QtEBeA1/AGFsjQKnRJb9cZhtAJCHbPFoZdT843wc+RHKPwAQ+H0Ai8A7AI2gnQA6OqT8jettA6QBxvmYA5b6OXMy+/HYJPlrJAEAxeoU/UPOkvrWyyr+1QLe9d5UpQHfZrr8+dRc+qI0tQHjcbb1GOgzAUDgWP5dzI8A9YnU/OwHkv1KyE7+UAtE/I6V+PxKY8b/bh0G+fyCNwB3Yxb/0pA9AezApwMgDFMBpF5o/HrYKv5tjqT9SzFRAmbu+v2YKNsDTreq/azhiwErYB0BKjBHANgzpPupmML+DbTRA\"\n  },\n  {\n    \"ProductId\": 18,\n    \"CategoryId\": 52,\n    \"Brand\": \"Hiker\\u0027s Haven\",\n    \"Model\": \"Trailblazer 40L Backpack\",\n    \"Description\": \"The Trailblazer 40L Backpack is designed for comfort and durability on long hikes. Features adjustable straps, multiple pockets, and a hydration system compatible design.\",\n    \"Price\": 129.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 180,\n    \"CategoryId\": 49,\n    \"Brand\": \"Reelmaster\",\n    \"Model\": \"ExtremeCast 5000\",\n    \"Description\": \"Reel in the big ones with this high-performance fishing equipment. Smooth casting and retrieval, corrosion-resistant materials.\",\n    \"Price\": 179.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 181,\n    \"CategoryId\": 59,\n    \"Brand\": \"Aqua Venture\",\n    \"Model\": \"RapidX Kayak Paddle\",\n    \"Description\": \"The RapidX Kayak Paddle by Aqua Venture is lightweight and durable, with an adjustable design for maximum comfort. Perfect for all levels of kayakers.\",\n    \"Price\": 89.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 182,\n    \"CategoryId\": 65,\n    \"Brand\": \"Climb Safe\",\n    \"Model\": \"Summit Pro Climbing Harness\",\n    \"Description\": \"The Summit Pro Climbing Harness by Climb Safe offers maximum safety and comfort, with adjustable leg loops and a durable construction. Ideal for experienced climbers.\",\n    \"Price\": 129.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 183,\n    \"CategoryId\": 53,\n    \"Brand\": \"Campchef\",\n    \"Model\": \"Trailblazer Compact Cookware Set\",\n    \"Description\": \"The Trailblazer Compact Cookware Set by Campchef is lightweight and versatile, perfect for camping and outdoor cooking. Includes a frying pan, pot, and utensils.\",\n    \"Price\": 49.99,\n    \"NameEmbedding\": \"mbZPvx6VgEAYXc5AJVKAvmcCX0CqtU5Ag6n9v6Ahkj9y00nAfLLXv3FDlb/HcATBh82ev5TAK0AWa4tA15x3wK2O/b52x5RAooYQv/GLe0B/6VlA4dq+wNSx9r9oTwDAcLyGvROAMT/9C5jAfPxdv2/TGMAbUTvBN/kjQJjklsDIxFC9NC1mwATvuL54UiE//uikP55BsT4c04S/IYmLvymUDEAeT8BAPs2CP0BbuD6KFc6/ex6HwOy0PMBICZDAAQvLQE5LAj8gpo++9gaUwCJMCb/DaqvAd0v5PzuIN0AcfUc/5K+VPrg0XD0+/Wo/B0SaPx0Acb+ET1HBM7huQAIt1778wAc+mRfpv1+tfcCgsYk/SZa1QA9gKcA7T0JA+fomQCseSECT4ghA4MKGv6LZCMC3Y1LAxAi+wIBOi0AjN6nAjZWxv3BYjrxeJ5A+HG9bwAqv+b9aBiI/9gjTwHq5AkAJB1M/vq7AvwzLQcDAJmm/ER25P4wAOMFNVHzA5ql5QJe+gEBBWBTAorJEQQb9I8Bsr1u+wOCOQM8RC798a5Y/75RKwGSxcb+1/idAHNIPwDZ7GMD3IYY/BYDEv7ub0cAgygLAwycgwAOyjcAfG1JAQAlsQFxkvr4yo7NAxHN8wB8qkr+i5hPAZxCCwAtYAkCDGOS/AlQfQBl3hkCo2ze/GfltQGF1Rz+Y92hA8NBFP83ZZ75WPSi/6nPCPzMK2D/05mVAIFFzQCRPFsBjDXnABsBTQBHLjUC6ecfA+K5RQGOGF8Bgl2q/Vwo4vlOyor+qbqq/NJ2IPyNfsEBasgRApAWjvziBrkCExZxAQhm1vpdeH8DNCXLAW22UP4uqj7/8xQo+7nzhPs66Z0B2b9k/p4IawfgArL9Q0Lo/VJl/vTSQMcD3OyC/0hWiQAWEsL/GUtW/1aQPQBkYhj9kUQPBrCfSvmN7f8AOM/A/OoK0P8pjU7+L8s6/jluVQOHleT+Ycz3AcQWHP7opmcDY+9A/fiHMQGZrr7/jYvC++1+bPmruvz/7CBfAfPHfv8QUlcCXrg4/NLcAwL6Um8CNBKxA1qNDwLY6dD/eYjY/grDPQGoYEUB4Y0jA51EawGWQPUCIy+VAE9h+wDhUOD+ABwpABA09wOYKlL9iqTg/rKK0QCrrnT56TIrA9GmFvwZfNkBGRXfAHh7awMJ+asHKdQxAUVGhv6KfHUC0CIFAP5O8Px6wRj+fzlBA95xFwJedWb+aerZA1S+BP5tLTkAJmvE/sKEKwDHHg0AgVO4/InATwPndKMAQBDtALQAevmzyvD9Zv+i+lQyIvz/04b+CxvA9rb8TQbf/f0DV+6NAcM6wwOQe3T41aJJAtJaov8bD9T6CKUJAvDsuwMiXxz4hYBs/nkoFQEbJRsA0BKFAqE76QJNmlz9H6ATB4j8wQIYEGMBUxK+/DjxXwAyfLcBsT38/Hla5P9lxAUDpGwQ+lpwewM5GrUCqNezAW5SLwMWQND8GyuTA7gr+vjhyEECkDSvA8TAHwBmwSsBL0Y1A+SRwQOuSMEA8UfK7bcaLQDgPHsAlemw/IYCEv0mgSj+zNjdAs7TlQNm49b9v4HhAGewbv/J9HL8lkCfAoykKQMJXv70n++o/UXGDP7DVWj9zQJ1A59UOwMFSBMA+eblAD74YwK5zmECKl/g/WLVywAd9mb6tRsRAI/iiPzbNbMGbxtg+x/hZQCT++L9A4YA/HXXrPhgY8j9bxyxAj178PidElL/6Z4pAnrAZQHS+sT/ID+q/VsoBQACAtjfr0Q9A/CgFvxdMMEB5R9fAxgrDPgyCkj8kFSxBgy89vyJ+K8A7HgpAqPBnPA3s4z/MhJZAPEhHPyOaB0Acz0nAKqYhQX28rD+pR0xAmU2kQG6nyb6YH9q/h1uQQG4GpT9GiSzAonzavzFXicA91gk+c5IGQJuDrMAgVzW+IIpSwJzaGMAlSse/pjKAP2K5pD6pnRTA7sYlQEoifEB94CHAu7+9vgzvA79x46PAakaUQPrz878etvQ+wN1NPzRNAMClUQy/\"\n  },\n  {\n    \"ProductId\": 184,\n    \"CategoryId\": 32,\n    \"Brand\": \"GloTech\",\n    \"Model\": \"LumenX Rechargeable Headlamp\",\n    \"Description\": \"The LumenX Rechargeable Headlamp by GloTech features ultra-bright LED bulbs and a rechargeable battery for extended use. Perfect for night hiking and outdoor adventures.\",\n    \"Price\": 69.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 185,\n    \"CategoryId\": 50,\n    \"Brand\": \"Sleepranger\",\n    \"Model\": \"ArcticX Cold Weather Sleeping Bag\",\n    \"Description\": \"The ArcticX Cold Weather Sleeping Bag by Sleepranger is designed for extreme cold conditions, with a waterproof shell and insulated interior. Perfect for winter camping.\",\n    \"Price\": 159.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 186,\n    \"CategoryId\": 20,\n    \"Brand\": \"PowderPeak\",\n    \"Model\": \"Avalanche Pro 3000\",\n    \"Description\": \"Stay safe in the backcountry with the Avalanche Pro 3000. This high-tech snow gear includes a built-in beacon, shovel, and probe for quick and efficient rescue operations.\",\n    \"Price\": 399.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 187,\n    \"CategoryId\": 63,\n    \"Brand\": \"SkySight\",\n    \"Model\": \"DroneX 5000\",\n    \"Description\": \"Capture stunning aerial footage with the DroneX 5000. Equipped with advanced GPS navigation, 4K camera, and obstacle avoidance technology, it\\u0027s the perfect companion for outdoor adventures.\",\n    \"Price\": 899.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 188,\n    \"CategoryId\": 46,\n    \"Brand\": \"Power Up Tech\",\n    \"Model\": \"SolarPod 100\",\n    \"Description\": \"Never run out of power with the SolarPod 100. This portable solar charger features high-efficiency panels and multiple USB ports, making it ideal for outdoor activities and emergencies.\",\n    \"Price\": 79.99,\n    \"NameEmbedding\": \"Q+gwwHAF7D/6WyJA+TLfv6yTb79Ocem/wNqRP2DP4j8Ar9K8JJ1AQOmVcEBP0dW/wIiJPyrJP0CvzHpAEoZzPzJPWUDmkaw++vwpv/bd/L6gYLZA391awHLQML6LlAXAZY9YQKgnFb3E7ig/f6qiv2ZKwb+cl8HAT5p4v4XFJcBSfkJA4m2ivYhp4z/l1IK/YRdfv46Fz8Dj7yrA+EeLPz2WUb/XBlLA+nsPwE6Evz6/G27ATRO0vqMtXD+YAUC/pD/TP7OdOL+KhD5AFCzJv/LUMT+gMGa/TnthP9Pohj9Cizi/H1fYP4qqaUCZaDrAA0BFQFvQZUCuixXBFbx1QERA60DTdIS/xkkqPt76Gr+YLg1AhYcFwF6Lwj/i6dI/GUkNPzzdWz8e2wS/ehUSQKi+PsDpFvm/qocwwP/OEsBDTxa+wEMJwIGH5b9+5S5AmqlIvpiK0r7ATyM/j2BjQHJgH0DxWxdAzyDGwHZfO73725g/3rCuvUdEwL/YSxa/makMQNPIlL+q3SLAcGXtQCAuCMBN4iFAvFLjP5qLqb9FLkRAtkeDwKNlCT/FOZm/Id1Fv47WVL9q+hg/1C3zP2MJPz6iSAlAJ7VfQMQAVb857SrABWsjQIUwIMDU0Vk/PYJcwO6FqT+OzaFAnI9yPwzDtr9aybK/86ieQD24Y0CIpIK/MmtDQOeSFUDqVW6/UO2Kv3kXkb8V0hZA+53NP/BdxD9GjwzAA+yEv/azNED2v0o/q51GPzdNAEAE2crAO59KQGAKhT7+Wty9+lNjQLNrI8DTQkU/9fQGvtfWMECaQVtA2wglwCGUyT8iFK0/hal7QLoJWUBUK4k+hhQBQHZjSD9Q8Ew/LVSAwH1TSkCu8klAMPjVwNQPar9kB14/hO1SP+LVdD/cD2O/MxD6P30rNj58UKm/Rrl0QOTwY8BkaHrABCaTvx1dnL8HYyZAwNGcPzUllz9b6Pa+M4FSv5xozT91iPW+KD7evoD9wbxW+APANoRqP8uZ5L9ZIv0/GAyav0NFTUD3bF8/Jb0cwEQ43781daW/Etkzvkt8i8Cq8ri+lx6/v+BmV8DJFpRAQHIGwJOOib/+MJPAjqgnPxJw7T+rNj4/Xt+5P7JdpL+mVc5AqiA8P2v53sDs7j4/FmQjwOuShL0PcA5AR/4iPzQI6D6irq0/tG+fwHtbLsGHwZ8/aBR8vwSlUz4u74E/fR4FwAKLaT+E56+/tAliP1Qux78htoxAp718wHMCHEDwHbW/CeGNvwxdL0A77vI/LpdYP0mM5r+ifrU/CoZxPUOMcEDyN7M+I69bwOa0ZT9OikTA38LiQFY3p0CV4RZAGWK9vlY9bL9mf8U/5GHpv3ixrMAOtWo+9s4bQAFfKUBqc5A/HLgwv6iqsD4Cs+K/VoJ3QD3XOsD8gY/AUcxsQJL9v78SqQfAUAhJPxVmKECllkvAbQCIQK4EqL5SyFnAvvx1wLFpyT+AiQS/sN2TwKl4cEDnvhFAOta0P1BrtD7hB48/WyMUwJq8cj+IL7c/mFGeP4u1Ij9Mtg5AFF9fQFDLesCKJg1Aof+bQMieLT/wB6ZAhkPAPzRULcAZJIVAibDjPqQUXUA3Zym/tG+cvnoeAD8EKLW+3uDWvst1zL5GIhw+awxrQNmYgb+aoZk/KHpCwK5MBsBvXB5AQiEewJuw8j8E5h5AzYLRP1MyQ8H/1hE/PuG8v5yZwb9vJIPA69hhPxxVEUBY34c+OIGQvbgo1D/JBu/ApTGEQOupnb6D4B4/vNdTQHybBkCGijBAVFHcvx6MDsCWaXDAIK5LQD7Npj6giwVB1Zqdv81IMr/uQnM/6luMwB5SJkBAc5497lO/v+7CVcA7Qh/AMz/tv05UGb/xRho/WZwMQALf4z+n05XAZnnUPvYuEMCM2xTAS6N7P55Gwb/4gH4+RHomQJk1SMA38Ny/jtCJwO2UKcD0vTU/im6ovwu6hr93Kqu/czMvwKxULsDgzyU8pXePvz1WK8BG+HK/vi4dwPCKprx8xo0+AH7gP+qpHMBsIuo/\"\n  },\n  {\n    \"ProductId\": 189,\n    \"CategoryId\": 21,\n    \"Brand\": \"Rescue Mate\",\n    \"Model\": \"Survivor Kit 2000\",\n    \"Description\": \"Be prepared for any emergency situation with the Survivor Kit 2000. This all-in-one gear includes a first aid kit, emergency blanket, and multi-tool, perfect for outdoor enthusiasts.\",\n    \"Price\": 149.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 19,\n    \"CategoryId\": 54,\n    \"Brand\": \"NightBeacon\",\n    \"Model\": \"Lumina LED Camping Lantern\",\n    \"Description\": \"Light up your campsite with the Lumina LED Camping Lantern. Features adjustable brightness settings, long battery life, and a durable, weather-resistant design.\",\n    \"Price\": 39.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 190,\n    \"CategoryId\": 51,\n    \"Brand\": \"Trailtrek\",\n    \"Model\": \"UltraLight Poles 300\",\n    \"Description\": \"Hike with confidence using the UltraLight Poles 300. With durable carbon construction and adjustable height, these trekking poles provide stability and support on any terrain.\",\n    \"Price\": 129.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 191,\n    \"CategoryId\": 10,\n    \"Brand\": \"Flash Bright\",\n    \"Model\": \"Luminex 5000 Lantern\",\n    \"Description\": \"Illuminate your campsite with the ultra-bright Luminex 5000 Lantern. With 360-degree illumination and multiple brightness settings, this lantern is a must-have for outdoor adventures.\",\n    \"Price\": 39.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 192,\n    \"CategoryId\": 52,\n    \"Brand\": \"Hiker\\u0027s Haven\",\n    \"Model\": \"Venture 45L Backpack\",\n    \"Description\": \"The Venture 45L Backpack is designed for long hikes and overnight camping trips. With adjustable straps and multiple compartments, it offers ample storage and comfort for all your gear.\",\n    \"Price\": 79.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 193,\n    \"CategoryId\": 44,\n    \"Brand\": \"SummitChomp\",\n    \"Model\": \"AltitudeTech Cake Carrier\",\n    \"Description\": \"Protect your high-altitude cakes with the AltitudeTech Cake Carrier. Its insulated design and secure latches ensure your baked goods arrive at the summit intact and ready to enjoy.\",\n    \"Price\": 29.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 194,\n    \"CategoryId\": 48,\n    \"Brand\": \"Rescuepro\",\n    \"Model\": \"SurvivalPro 3000 Kit\",\n    \"Description\": \"Be prepared for any outdoor emergency with the SurvivalPro 3000 Kit. Packed with essential survival gear, this kit includes a multi-tool, first aid supplies, and fire-starting equipment.\",\n    \"Price\": 99.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 195,\n    \"CategoryId\": 52,\n    \"Brand\": \"Adventure Pack\",\n    \"Model\": \"Trekker 30L Backpack\",\n    \"Description\": \"The Trekker 30L Backpack is perfect for day hikes and outdoor excursions. Its durable construction, hydration-compatible design, and ventilated back panel make it an essential companion for exploring the great outdoors.\",\n    \"Price\": 59.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 196,\n    \"CategoryId\": 60,\n    \"Brand\": \"ExpeditionTech\",\n    \"Model\": \"TrailMaster GPS Watch\",\n    \"Description\": \"Stay on track and connected with the TrailMaster GPS Watch. Features include built-in maps, real-time location sharing, and rugged design for outdoor adventures.\",\n    \"Price\": 199.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 197,\n    \"CategoryId\": 19,\n    \"Brand\": \"OutdoorOven\",\n    \"Model\": \"Firemaster Portable Camping Stove\",\n    \"Description\": \"Cook up a storm in the great outdoors with the Firemaster Portable Camping Stove. Lightweight, compact, and fuel-efficient for all your outdoor cooking needs.\",\n    \"Price\": 79.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 198,\n    \"CategoryId\": 36,\n    \"Brand\": \"PeakMix\",\n    \"Model\": \"WildBeat Portable Bluetooth Speaker\",\n    \"Description\": \"Bring the party to the wilderness with the WildBeat Portable Bluetooth Speaker. Rugged, water-resistant, and long-lasting battery life for outdoor DJing.\",\n    \"Price\": 129.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 199,\n    \"CategoryId\": 46,\n    \"Brand\": \"Ecovolt\",\n    \"Model\": \"SunShift 100W Solar Charger\",\n    \"Description\": \"Harness the power of the sun with the SunShift 100W Solar Charger. Fast charging, durable, and compact for charging your devices off the grid.\",\n    \"Price\": 149.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 2,\n    \"CategoryId\": 40,\n    \"Brand\": \"SurveillLink\",\n    \"Model\": \"Secure Messaging Device\",\n    \"Description\": \"Keep your communications private with military-grade encryption and secure messaging capabilities. Perfect for outdoor expeditions.\",\n    \"Price\": 199.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 20,\n    \"CategoryId\": 22,\n    \"Brand\": \"Outdoor Pro\",\n    \"Model\": \"TrekTracker GPS Watch\",\n    \"Description\": \"Never get lost on your outdoor adventures with the TrekTracker GPS Watch. Features include built-in maps, altitude tracking, and a rugged, waterproof design.\",\n    \"Price\": 199.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 200,\n    \"CategoryId\": 42,\n    \"Brand\": \"Strategicgear\",\n    \"Model\": \"Raptor Tactical Backpack\",\n    \"Description\": \"Gear up for any mission with the Raptor Tactical Backpack. MOLLE compatible, hydration bladder compatible, and built for extreme durability in the field.\",\n    \"Price\": 179.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 21,\n    \"CategoryId\": 30,\n    \"Brand\": \"TechShield\",\n    \"Model\": \"WeatherGuard Pro 3000\",\n    \"Description\": \"Stay dry and connected with the WeatherGuard Pro 3000. This high-tech weatherproof tech keeps your gadgets safe in any outdoor adventure.\",\n    \"Price\": 199.99,\n    \"NameEmbedding\": \"0RqiwOETX0Ca5EY+lM+nvtJMd0BHED3AD6CEP9HYkD9SkAe/Teejv5uuhD+63ZDAqaFpPkYauD//FxVAraBAQNyJk0BO+TZAqPyJQBQenkDyxQ9AiU/mv0dnMMCMZwLATUIQQEo2SECEHty/JMOVv4JiDj5ufcbA6RhNwJLbCMEmwvM+lru0PzqfJMC9LSrA3bHyv5hHXb/G8SHABjFuP2fZOsDnCjE+XUG/wKJrSMCwn6S/7yNavm6Uxz/uwUC/R319QJq1BMB7WgVA32V/P2T97z8yTfu+VichP9nkQsCkVdw+ccQpQElgDkAppi3ANFC0P8DbJkB8dSDBydaxQJbHYT8DThZA6NjxvoqdekDygxhAlv8hP0uBLsB9G00/sNdhwNj0ZEBVPy+/KFkAQOkt+r+pP+e/d+BZwEuZeMC4jOm/zsV5wPNhIcAEuIc/7APDv84WZT7p9T5ABamhvzL2PUBNxe0/VD57wIWMZsBtBJo/DX7ov5m3ksB9Ru4+bJtoQLO/qr//uFnAGsscQY+bq7/OEKy+dlJYQJzLdj/sWlZA9VKRwG9tZr6Gi9i/CyyTwMYVSsAy2j1A+EmBvuZmKMAE1Gi/ObG1P08iJ79RZMC/pAOYPqdChz9UF0S+Um/SvuxIVj9Owl5AP3e/vpzkoL+dpb8/560SQEEy5UDOzSU/gRShQLMZ/T/7KJA/JFshwAZhIr46ucM//5DCP1N+sb9UYdi+KRLmv7y60775raI+6IwGQC8ynUAsW7rAG3PgPzLf/j7N16nA6ktov+5k5r/THzjAwZGQv2RdQkC8ODg/pKMpwOLvVkCIGlRAKenaPld4c0BiXf2/PLYJQN8FOUAW+zM/nUPRP86IfkDefJBAcki6wDhcMkCKfO8/hez8v0wBwb9aET7AT9/MP5pW5r4cFdm/JH8gPwiiNzysnNzAt6Pmv+rjJj4mrgC/u4CQP6AEAD892jS+UpZmv6RLQkC00bS/Q6jdv5PZv79AgBk//DBFQPexi76FkiHA7duVP8/LeEBt8BRAahVnP4MZI8B9n3O/EwNKQMVJscD7XIZA4nmNwOj7gMDoUUK/5aO1v9WWAEBov9o9U6QFwKFJFEDGFju/Pn09QICwnb/403hADaSmvzBvpj8Oi3i+R+EWQGmyB0AaETxA0JJNP+74MUBq1gU/nm7GvwNEPsECr12+4yORv7T5J72A7Ja/Zsg1Pxs4kL7U87q/E6xDQDhlEcD+IdBAWlNfwHohd7/oQmPAaIFEwAUTQT+74QxA9mZfQI6mZ8CcxVvAMpokv3YskkC5OYXAuX87QAGkIUDJWCbA/dsQQRwZ1T8AYG5A5ciYvwNWCEAr2A6/5iehPj24vsC9drU/pOoQPwIwAD/Q4otA8uxcP/0DFMCUMhO/wtO5QHtMLj7QF4vACZYMQGrY2cDaIko/8qqIv2jBFcC7eU7AjoQFP0csHL+4bZg+EajDv8G0REDQdErApbjpwAYeakC1IZY/e5wPPwOKEkDD+xA+tcrqv1Cgm7+83rw/UV4cQE86sz8lWpW/bWKUP8Ewp8DMLJK/QbRXQI1OlL9tKq0+UyEhwCBj4b9BOJRAZsXTvum5Z0Ag1de+wtycQCbi2D/OxiJAhKZkPpwyCUCz+QJA5KVqP3qZBMCY5wZAB4KcvzDNkL8xWaW/IuWrPvJ7FsA0sNZABgmAwIrjbMGkqhg/DB7FP/ltV8AnyFrA6XCawCVUvr/wq/E/as4gwNpT2D7yUd3AozdnQOP+N78kawc/hOOvP3D5zj+A16K+vhnLP+ouhT/IlX4/f7smv8Pq5T+BfiJBdBPLP2LKckBsOQRABqqiv2VgqL84KypApuIaQLA7RD/qxWPAkFB6P7MLUb8moaa+Hnk4QPaqE0Avfow/Dh/yP/iExry4vzFAwdARQFDZA78Zw/i+EmqAQH/JD8AMFgk/XMxCwAQR0L5lgDBAuCLCvh45x75Gb2+/SjQpwMZKDsCi+qY95ldZvUCY2LxPUZTAESyuv9T80L2yLwPAmH48wFFnJ0A5oQpB\"\n  },\n  {\n    \"ProductId\": 22,\n    \"CategoryId\": 3,\n    \"Brand\": \"Peakpacker\",\n    \"Model\": \"Summit 45L Technical Backpack\",\n    \"Description\": \"The Summit 45L is a top-of-the-line technical backpack with multiple compartments and advanced carrying technology for your outdoor gear.\",\n    \"Price\": 149.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 23,\n    \"CategoryId\": 26,\n    \"Brand\": \"EZ Camp\",\n    \"Model\": \"QuickShade Portable Shelter\",\n    \"Description\": \"Set up camp in minutes with the QuickShade Portable Shelter. Its high-tech design provides instant protection from the elements.\",\n    \"Price\": 129.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 24,\n    \"CategoryId\": 50,\n    \"Brand\": \"Base Camp Comfort\",\n    \"Model\": \"Arctic Dream 0\\u00B0F Sleeping Bag\",\n    \"Description\": \"The Arctic Dream 0\\u00B0F Sleeping Bag is packed with high-tech insulation and materials to keep you warm and comfortable in extreme conditions.\",\n    \"Price\": 179.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 25,\n    \"CategoryId\": 12,\n    \"Brand\": \"DigDigDig\",\n    \"Model\": \"TerraScoop Excavation Tool\",\n    \"Description\": \"The TerraScoop Excavation Tool is a high-tech multi-purpose tool for digging, scraping, and leveling in the great outdoors.\",\n    \"Price\": 49.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 26,\n    \"CategoryId\": 59,\n    \"Brand\": \"RiverTrail\",\n    \"Model\": \"RapidFlow Paddle\",\n    \"Description\": \"A lightweight and durable kayak paddle designed for speed and efficiency on the water. Carbon fiber construction for maximum performance.\",\n    \"Price\": 189.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 27,\n    \"CategoryId\": 37,\n    \"Brand\": \"Wander Lens\",\n    \"Model\": \"AdventurePro DSLR Camera\",\n    \"Description\": \"Capture stunning outdoor photographs with this rugged and high-performance DSLR camera. Waterproof and shockproof for extreme conditions.\",\n    \"Price\": 899.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 28,\n    \"CategoryId\": 29,\n    \"Brand\": \"AquaFusion\",\n    \"Model\": \"PureStream Water Purifier\",\n    \"Description\": \"Ensure safe drinking water on your outdoor adventures with this advanced water purifier. Filters out 99.9% of bacteria and viruses.\",\n    \"Price\": 149.99,\n    \"NameEmbedding\": \"pBPOvwt5PcDTgcO/REM5wMthkr9XpmrA/uAkQEfsLkAS2pXACpdJQDMgGb9FbkTBOB/Ev2UcLsBF0y9AWDOCQFfCl0DwJKhATxvowC3SXUB/+YpARdgnwHa2v78LIQK/OfEGvqBnRT8Q38w9tENFwCaPLr9U3ybBVEEDwCCRKcBtsIo/U8e+v3JyIMBGTo0+DzSzvx+gCL9xS13AKqymPggL6DxgVAs8ZpWPwHayr0BKh+0+lPGxPaiHMT2GR4K+U9G2QLp5fcCLLec/oj0gvnZZpL6RjLq9JFKLP3n0OsDfgNI/RNFcQL1LH0CX+oa/guzsP1Oti0BFsiHBrfLwQHA1AD5Pzes+1RaSwL7ssEA8N7VAIV3aPxJpvr8dNpI/3Vc9QMax+D/CBl0/DCdPv1G3SECcP+6/MHI+wC4vjUBwMIQ/P9yYwH+cur+rH6q/dKoJwIzjcT8sU/4//xEMwGyRyL6+GH++LpKewCcrob8zrae+6xR3QLIBI8D37A9AwvrJv2KcNsBWPI8+e8kUQQoCSsADUANAAl6SP6mRSsC167xAWSeZwCojIT9Sesw/5AvLv067gD/KAL8/yARJwPUqQUA9wl7ABYbYPniDAUF90Y/AqngIv8eoW8A4uohAN5o3wBiknr4DxRpA/KtHQNffXL8A6a0+BKESQHK+GUBMBbe/6MeqQMeD8z+XzYNAJGjVv/kKs74bk8o/SSxgvwy/Kz8WVvq/LZbcP83D6r8oycrAR6yXP2NtLsAhoQ/BeOctwL5jB0A4iDrAl8sAvzbMVMBLpHTASd+uv2umvECGkyS/FFDbvyNFb0Ax500/oG5yP1PPWUDU6ri/2ywnQMjNwb9oBRLA3UnYvxwv9kCKVI7AWL2XwJQ9UUCcbXLAblwLwDxN4UAtze/A6KgsPSEcMkCZkvu/Ms4IQGLOTj8isOq/wuEaQDX5iEBBqD1APp2Sv/SwTD+zcpw/TEqTQGasMEAZzFnAPHORvuhvM8CRByfAju0dQLpmncCW9uO+47Q9PiRwckCAFWNA5NrEvxbiJL8CTb49kNxJwMh+07/AMb+61srcvhqbH8B+Wb4/YkISP1Fdj0Cptlk/F6LiPqacnj+PHLpAuE4dP7MhnkAn84++AeZawO175b/UTK9A3t2AQEFvPkCwNPg+E/Euv3+hvEAsuBrBauTTwMofWcG881s/7WHov+ZrisAgh7dANFvbv/8jCsB1OfW+bEnBv7T/kj/aPMNAJjUOQBDflj3sGbk8xzgaP8aTWkDsisBA3wpUv+QcLUCGxYJAC14LQPcIWEC5S59AAr6UQMSPnL/wbg6/orAsQVyh8z8D+aVAEyOpQIvwH8D+aq8/s0LKv7LEBMGdbA3AHTpJP9RjET6AMDU8yHbEP42EDr/2hAe9peRLQMI/mb9ELdrAoPpJv75XNMDCRpa/lcNaP9o7lMAmr3fAgerQP32HMcCgZB+/xSUpwPLBVUCQGEnACreBwKROOj8CD2jAU+MowGdlmr8YNQU+dxCBP9Gyd8BAjSzAGEKAPOAIpT+NbzxAzOW8QFA8MMBg9j3A5XF5QBIa8L4hLGtAD2ZwQKMcqEAX1JI/aj1owLx2hEBuPCzAk7yMQGoO0D+dvk1AQjAcv8E2PT9oh3VAcXt+vkpqhb+YhaQ/MaOhv+Xbvb83MHG/csCgwEdQtj8hC55Ay/2PP2Dca8Ephte+UkyLPoga/cAp5IjA0o0ewF4aNUCCup6/eg7Svzj0A0C445TA/6YPQOq/oz1spkFA8lKVP4QEFEAaBmBAYfiWwMhRZECiXdM+6LvDPtZ30D8Oc0RB0WoIwHB7iL2clh9AqSjvPhy7AkDS7H4+II8+P9hL8z+MvkNAX7SNQJr2XsCzR/w/OVVHP3poiD7Fvtc/THP3PzqeTsCRvJO/3ryKwOqi2sDQWK3AohayP6lrQD+JOp2/4dTGwLpNZMDC09k+OkIMwNGE677M6r1As7WhP2obFj/J9hlAj0jqwKqQUsA4/7S8xKRpwO8TgUABiZ2/ctmeQGyjOUBuU2I/\"\n  },\n  {\n    \"ProductId\": 29,\n    \"CategoryId\": 46,\n    \"Brand\": \"Ecovolt\",\n    \"Model\": \"SolarBoost Power Bank\",\n    \"Description\": \"Charge your electronic devices with solar power. Ultra-fast charging and high-capacity battery for extended outdoor use.\",\n    \"Price\": 79.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 3,\n    \"CategoryId\": 55,\n    \"Brand\": \"Swingnap\",\n    \"Model\": \"Ultralight Camping Hammock\",\n    \"Description\": \"Relax in style with this ultralight, compact hammock. Easy to set up and pack away, perfect for backpacking or camping trips.\",\n    \"Price\": 79.99,\n    \"NameEmbedding\": \"qPESwFCCgUCVgCk/iliOwFDPtr95g8tAePLFv6LLwz+cgVfAEs+Fv614uj9iSEDACESSwHBBKD3mQs5ADAkyP+4BHb+YjyZAjVQGwCnh10BnvsBAu4AkPxtX5r1wrm++lwiPP3rQdj+7ZzfA3beCQLvyC8BmnA7BQL8yP8h7C8A9SCTABC4YwE2ic78wQBq/hA6TQEXbsL79jOm/bkALQNLOn0CI7BM/5S7MvzoHJT8U6WC+oSVGwM6YHj4nfbvAqkZWPuapdr7AICy+tj4Kv3KIkT/SlDnAHbMQQDwpHb8G4hXAqOKXv8eaWD8dq3M/gnWyPxSOg0BzcU3B8CB8Pc5gsEBeWGU9cV0FwBVOMz7JXJZAyPOEQPuwmr9LMndAIDRsQJqLRECuOsa/BqHYPqwIWr8dfm3AbnhuwEjc9T9WKj3ApHwPwAiTVMCqxoc+gQKEQEjVZj9htSS/swpbwMwtOj+cMoxAVykxwClgv7/6em3A7YkuwEQII8E6jJM97yrcv0M+hD+PnI7AY6w0QSLkmMA1VnI/Ibu6QNhGLr/2RW4/4Xl0wHp0ur++D+m9WMI9wLPtTUDwyaY/sw4nQBCVBb4CJ7tA+k2iP/PfrD+spd0/cxtBQG7uS79TZv0/1YeywOOPAEBsvX9AO0NSvkAHhT+A9nC/Kpplv3PFrEDZhR9AWttvv/tBKUB/PyBAxDszQJ7qf8D7rxm/kkUowJoDmz/79r4/AbgSQL/JHMBuQ4U/wgtUwBExlUD8OfXAeRbMv6dIicDDnFHArwhsv+FMLMDXoUI/xSgyQMIpfb7gM3BAA4WtwJVdWEAnWLJAi8I8P2UliEDspcO/Wq8FQK895b9sR/I9KHVMP9ok8z9DcEC/CyQgwWnPAkCZ44e/Ccj0v2YATsAABai/e5GOQGTANb8CWiPAQpuwQORSsr65qcjA5/iNv2aNYcAO3W1A94KIQPvrEcCTlp6+CniAQJ5QoECmg76/yF1HvqC6YT6MqyFA7a2pv8oImsDWcpXACkTsPxX7D8DSfcq/ostZPzBTTMCwgm6+qKWJQDJXpcAOl8FANrgfv9BJAsCTNipAYx6SQEeI0T8MFnnATADYvx2uykBZf3g/QX8GwIzUij5E/5k/VOsbP4h+c8C5CTNA4gefPy2nEEBOmNDAky2OPiQAN79PE7rAuq12wMT5RcGcVMA9WOW7P0RkJ8BctB/AwY/WvyoqLT98nEpArQs5wJx78b88S9xAYpeWwOhkgL8gZ9Q/bScOQGIkp0CIIkFAYY+lwKiRqz6n1Ea+lbdYPwQIXT/47tK/WsiXv6vXTb9q0cXAtgUSQQpTbEDYEdpACuLEwGT2tD8tuDa/zLFFP+a2YMCzuy2/6EAAQJNPFkDt38FAjLDOP/jcer2mzyk/0aAjQSMtg78WZhPBzNsoP53K477STWw/NKC1wFXir7+eyWXARM7GQDOvAMD16yc/rOV+wCScg0Dpq5XA6M+jwKA7XL+aoFbANVDxP0PxT0Bs5Em+EJbrPPrjqMB9qpxAd/qBQFZWvL8QCRk+G0BmQH4UPcCKNYTABpPFvqBJS78sqrc/nZfKQOziYcDEOis+yTxSPyYpBEAODby//AExQPS6oUA2nXhA3fLpvy5L6j/BwFJAqU5iwB4hwkBc5QNABjs3wBDLmT+kOqq/LflRwCQJTb+ZBMNAfdTIP3Gmc8HeAWs/COcJP8i1NsDIj57ArP+AP1mTHUAnO/hAQiTkPylxHcAp3bu/lR2ZQOrtLz/ZeTVAACKaQPBQpEDYOg4/bqJjwPjAaD8QDcfArKphP0phyj/0mUFBv2aPv+YKcD/7AWhAPHaoP8qoTEDoUd08N/MlwAVofEC611k+STgKQcexfsAgHHtABONRwIJtpkDg6svAIu45QO7Z4L8soJw+kWgLQFPVZb4c/Xc+fy9nQOTHxMBE63FAthK/wEjkZT2D9wjAuO4TP1CbYz56o8y/ULY2vWNfiD5KgQo/84EzP3T/IcCSyiO/yadWPhKmmj/knhTACo5lwMEmxsBQ7Ze+\"\n  },\n  {\n    \"ProductId\": 30,\n    \"CategoryId\": 14,\n    \"Brand\": \"Backcountry Cook\",\n    \"Model\": \"Alpine Chef Camp Cookware Set\",\n    \"Description\": \"Prepare gourmet meals in the wilderness with this premium cookware set. Lightweight and non-stick for easy cooking and cleaning.\",\n    \"Price\": 129.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 31,\n    \"CategoryId\": 28,\n    \"Brand\": \"WanderStove\",\n    \"Model\": \"Nomad Camping Stove\",\n    \"Description\": \"The ultimate off-grid cooking solution for outdoor adventures. Lightweight, compact, and fuel-efficient design.\",\n    \"Price\": 199.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 32,\n    \"CategoryId\": 28,\n    \"Brand\": \"WanderStove\",\n    \"Model\": \"Trailblazer Camp Cooker\",\n    \"Description\": \"Experience the convenience of off-grid cooking with this high-tech camp cooker. Fast heating and easy to use.\",\n    \"Price\": 149.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 33,\n    \"CategoryId\": 61,\n    \"Brand\": \"Game Guard\",\n    \"Model\": \"NatureCam 4K Trail Camera\",\n    \"Description\": \"Capture stunning wildlife footage with this high-resolution trail camera. Built-in night vision for 24/7 monitoring.\",\n    \"Price\": 299.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 34,\n    \"CategoryId\": 61,\n    \"Brand\": \"Wildwatch\",\n    \"Model\": \"WildView HD Trail Camera\",\n    \"Description\": \"Stay connected with nature using this HD trail camera. Motion-activated recording and long battery life.\",\n    \"Price\": 249.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 35,\n    \"CategoryId\": 53,\n    \"Brand\": \"CookMaster\",\n    \"Model\": \"Alpine Camp Cookware Set\",\n    \"Description\": \"Upgrade your camping kitchen with this durable and versatile cookware set. Lightweight and easy to clean.\",\n    \"Price\": 79.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 36,\n    \"CategoryId\": 28,\n    \"Brand\": \"Eco Grill\",\n    \"Model\": \"Portable BBQ Grill\",\n    \"Description\": \"The Eco Grill Portable BBQ Grill is perfect for off-grid cooking, featuring eco-friendly materials and compact design for easy transport. Enjoy delicious meals outdoors with this high-quality grill.\",\n    \"Price\": 89.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 37,\n    \"CategoryId\": 24,\n    \"Brand\": \"Wild Guard\",\n    \"Model\": \"Outdoor First Aid Kit\",\n    \"Description\": \"Be prepared for any adventure with the Wild Guard Outdoor First Aid Kit. This comprehensive kit includes all the essentials for safety and first aid in the great outdoors. Compact and durable for easy packing.\",\n    \"Price\": 39.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 38,\n    \"CategoryId\": 19,\n    \"Brand\": \"Firefood\",\n    \"Model\": \"Portable Camping Stove\",\n    \"Description\": \"The Firefood Portable Camping Stove is a must-have for outdoor cooking. With advanced technology and durable construction, this stove ensures quick and efficient cooking while on the go. Perfect for camping and hiking trips.\",\n    \"Price\": 59.99,\n    \"NameEmbedding\": \"pz9LPzIfO0CKzHZA9rc1vxjyukAzTgBASw7kPZ3XnT6ASYnAnJ3kv2gSr7/DPBjAz/lGwLCZJ0D5+z1AYfBLP/sRQr9mexm/r9hrviz1IT+NgrxAPGAPwKFhcb+AahDAtcoHQLs3778IB9W/RUcoQHNPjsBlI73A5VYkQLPx2z4PGXvAz6R1wEihAMD0Tpc+FSsTQABojj+knzrAPQnFP3ipGkCLFZw/zBQ7P2h5WD42+qW/PJCrv9G/FL8JMmLAWcYUQAVfur8v4Ki+hgRhvzKamj/K4nW/Es2SP5++2T+t88a/rWm4PqMKpb/4R2a/dNRoP5buXECN3CDBMFgqQCdq0j/Bhhe/PncYv/j8YD9/fF9AfMibv2wfqr/lbdc/4+EVQF3oxD/ud5w/TGWdPyT9rT6skyfA2TVawIQslkAlCga/DqnkvubAG78tza6+RZ3Zv02CHz9PTjpAWx8qwLUa1b5MdGE/b0tJwLw3FMCAzsa/U4OcPkolusAqYQzAI6/0P4Fhib90rGvAQqUYQbQvKcDhhI6+R9QbQPT2LsDo7ES/5f1vwDa8HD0LXQM/9B2OwILyRb+SAc6/YRZpvuHNLcClFmc/5ukYPunwSsBVdwpAy5W2P1AcyL+OkZRAOj8OwHyTHz2as4RAaAhwv5qFd0BsLQ3AD0X1P34gp0DMbTw/Rp2BQMq/hj9K2m2+ZQ4IPyLpQsC6NMq/93BkP6C7g70dsRS+ohOSQPIQ/j/m31RAE4WovzKOj0BC6MXASgIgQC959z9GLrs/fsUCQDC7ssCGJEO/NZVrQBQyK0BsOwlAkTmGwMvvhUCX2WJADtPqvzxnZL8lddM/Z5pWv3T50r+5eYq/7IDqP/L/m7/2+Iu+n4rQwOjvXL98u/A/4tCPv+PpEMBmiV6/3Bk5v0EWHD7eSAbA0r0FQJRgMsCatL6/DaSuP5oImMBeUxU/oLDoP4Rgwr9+yEk/oN9xQNJ0GED4aYm/9mf4vzTaTMDypihArqm8QAq1ksCQMp+/7lojQG4Meb+qryXA3LkOP71gXz/ZXN4+1OOKQHTen8AWz4NASDtMwOoHJcAmFvk/6L6kQFBkmT8MfxnAwoysPqdXtj9bCUBAdBv4PhylCkCk4fQ/nFgOvzSIIb5qr28+ImKzP6DoU0AE9LC/z/Gmvi+biUCF7CTB0IYLwJ6bLsHa3z3AJNQ5QC9y3L/c44bAAobZvnx3xb4DcyxAwhQewE6cnkAtb5VAJtzewOToAUCjnS5AWgkXwAi5NECgMg1AO6amwK3N3L7vXE9AghnCvkw6mr64309AaHW5vzJDnj+qgju/toH3QKvxEkBoUrpAu73HwOR7LkAzafQ/QArIO1y5aMDUViA/YOLUv2ojyr5Pd7q+aEfZPuxg+b/UNwQ/WPz6QBrZBj9LL6jAN6qXv74yH8BdbCrAYhX4wLCqbcBKigJAg8JrQA5EQj7AcXU9PoF9wIhlpUBgym3AEHqqwH6hoEDOGqHAgDDwPxLXAz/0MyY/+nWDwNTzcL+uvKJAsPlJQNEp1L5mt3c/8hU9P+FdGMDOUyG/xZSDQELvsL8BeA9AvJGHQF+71r+ZbOs/p/e6P4MCAEBEugbAxa4+QFbhB0AozVhAwyU1v7FC8z9lyjdArOstwHFFCUA8OVS/X8D0vwhmZL4Zg+s/uSwdwG33979DfppAcga/vobfR8FCCWo/qStWv761Dj6S6U2++1KpPw3WBr2ZF7hA37AHwCrxwT/EYMS/LmYIQElRFUBgi3lAzz7pPxc81T9KtLK/gLVXwHf0VL9bhgPBTR2gPwETfz6nSBNBIoBKwDz8+r+8Kqw/Zd0iQJ/A/T+4ebo+AqGrPzkXiL+YkwTAHOpnQLTikL8IEtFAnVqqv8ELmj+yi9a/gP1QQMqyY8DBJ7m/sXxbv/53Ib/cxro/+N6yPivyAMBrmiO/AAWgwKPmib6UFpU9S5J8P3jjkL/DeRHAL4dXQDTi1T8hmgE/dS2QPlxm2r7AyaK/vXMcQMxKD0Cov2q9I6YNQM0D7b+rC2c/\"\n  },\n  {\n    \"ProductId\": 39,\n    \"CategoryId\": 18,\n    \"Brand\": \"Shelter Scape\",\n    \"Model\": \"Instant Pop-Up Tent\",\n    \"Description\": \"Set up camp in no time with the Shelter Scape Instant Pop-Up Tent. With innovative design and high-tech materials, this tent provides reliable shelter for outdoor adventures. Spacious and easy to use for all outdoor enthusiasts.\",\n    \"Price\": 129.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 4,\n    \"CategoryId\": 48,\n    \"Brand\": \"Life Guard X\",\n    \"Model\": \"Emergency Survival Kit\",\n    \"Description\": \"Be prepared for anything with this comprehensive survival kit. Includes first aid supplies, emergency food, and essential tools.\",\n    \"Price\": 249.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 40,\n    \"CategoryId\": 32,\n    \"Brand\": \"GloTech\",\n    \"Model\": \"Rechargeable LED Headlamp\",\n    \"Description\": \"Illuminate your outdoor adventures with the GloTech Rechargeable LED Headlamp. With high-tech lighting and long-lasting battery, this headlamp offers hands-free visibility in any environment. Perfect for camping, hiking, and night-time activities.\",\n    \"Price\": 49.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 41,\n    \"CategoryId\": 64,\n    \"Brand\": \"Wavemaster\",\n    \"Model\": \"AquaVenture Waterproof Surf Watch\",\n    \"Description\": \"Stay on top of the waves with the AquaVenture waterproof surf watch. Features GPS tracking, wave conditions, and heart rate monitoring.\",\n    \"Price\": 199.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 42,\n    \"CategoryId\": 42,\n    \"Brand\": \"Tactic Tech\",\n    \"Model\": \"StealthTrek Tactical Backpack\",\n    \"Description\": \"The StealthTrek tactical backpack is built for rugged outdoor adventures. With multiple compartments, MOLLE system, and hydration bladder compatibility.\",\n    \"Price\": 149.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 43,\n    \"CategoryId\": 42,\n    \"Brand\": \"Strategicgear\",\n    \"Model\": \"NightOps Tactical Flashlight\",\n    \"Description\": \"The NightOps tactical flashlight is a high-performance LED light with multiple brightness levels, strobe mode, and durable aluminum construction.\",\n    \"Price\": 79.99,\n    \"NameEmbedding\": \"NSEZvktXgEBO7e0/DuWXv1Yg3z9OAi0+fCI7QLYriz+ymZ+/st6PwL7W5D9vET6/gF0kwKDBfr2xxzZAdO3fvxqBkj74T6C/VETkvqiuqr/UoJRAXOINwG8XqL85ZFa/dDI2QAgUXj8C4Q++oLG9vxj1icCZM/3AWDqpvpwZB8BOQZY+Bu/4vluG17+P/z6/leV/v7NdpT8BHcy+r7lTQA8OkUARRjPAuaMYwI6m0L/T+d6/1XuEwGHRNz9vND/AsmhVwADlRr9/5Ne/LO+KwFxoLcCNsve/1LoqQHUqzr80DEy/qRBYPqW+rkDyU1s/y4vrP1SQIUCpeDXBnLIzvkVNK7+jvRE+UjlLwHtYSL+2Wk5ApEsFQG738L4boh1A36nyP99OQj+BFxI/r/r9vqdfakCZcazAS4+iPlFAGEC/ris/GOcewFV93r6/d5E/mhKMPzf59b++frs/oXTAPiYUgT8/aBNAFnjTPV8riz/Vcc2/TpE+wKE6QD/mTI7AugZBPsEhEMDqLTTAVB0hQalJCsDjVK6/3G7dQFirgL+5SkdADBsQwGgVWb+2Es0+Kug+wHcxHUB//B0/SAPFPzwGJ0DyJ/W/yr9vQGwusT+EYdM/yk7tPzrWM72KDRy/q5caQAxOoD/0kBNACpzIPkTQaEA6Z2s+MmZIP2F1qUA41ww9OoO+v95nrL/+xkDA5YdKP/ewxb+FA6W/4JtoP+eSnz848YG+1gohwDNU+D/XUJ8+R/B+P+1qDEHC15nAN5cBQPQ3nUCuzve+vrtOQDnBGMAGnAs+1RcgwCfcT8CEXbVA8CrRPspLhj/YQVRAtaEoQDPyBUDTgta/Z3GhPxzZSj/6EBRAYDawPyR3P0COXrS/CertwG9AmL8WohTAA+vmv16BnsDxGYbAtPiBvXxOiDyUnTq+LVVUPyDkf71qwtw9srHevQzQBsBkB7E8rRJ5QE7A97+eh6M/WEWCQJpl1D/qZqW+qi03v1oW1j8qxgzADNQAQEEqOcA82R0/bNLGQP0K0b+b0Wg+1GvIvrtYJcBKySPAnEOdv+5N7b8SYK5AS9yEwIS2Nb8Y7C4/13ONQJ2LBz7Rq4g/goczwNLvc78aWnG+OsCFQOF4jb5Rmb9A9jPqvhaqesCqruM+j17Zv8pVB0AQRtDAOFYBv8Wgtr9aVJI/5F/Kv1rbMcG+i3hAwwIHv0kxj8A3SXi+NNZ6v9Tkz79LsoS/gI6bwJifKj05NKRAyUBkwMMTqb82caC/8CUawMRNoEAE07a/pKuywFeNEj8/FCW/8HNrvwxk5z/Ity/AmKoCwMSav79WWXLA6+cJQaDZl0D3xnxALPe3wE6C9z/7lZlAOhDKPhq8p74UlnxASvDXP68nL0AgzIK/PfoeQEX4A0BRI30/ddCyQC78X78TmrnA25RUQHs2ksBQt5XAwrANQHDCxz86UpC/K6xqPyaJ/78xXpo/a7siwETNSUD2npjAowKlwBqNKD+VXKu/wOAhwGLnHj/vkxdAToWAPsozbcCt2ApBjLuBQOrQsT5i48q/PCraQDi5FcA0QBe/p35AQCBQwsCq3cW+FOSkQN9Nnj9QNBZAJXsMP1P0ej/C7hc//JdoQBlYmz82o8i/2CAmwMHeJ0Be6eI/IHhdP6O6tL+AlXVAHqlxP2ejor+kAfu+nJMWv9Ks8r+goklAODzBP9Bfa8FB8jg+gSVEQH6bg8Aa4QQ/NwpVP8gPwj9Q5LQ/T/QPwPsd778lLt3AGps+QDxKdMArMRBAtHkUQKklAUD39hhAQOPuv+zBrz6urwe+6yYnQJS1GkB6iBNBMthmwDV8kr/WgfU/Ji+HQGKwYL/6DNM+OfFGPgfY9EBJISlAbgaTQEoQhz9nOVFAsKs7QAhjH0DdUg7AuXWaP+xxYr19F4I+lwW/P+whjD/CRL6/K0KcQIzb+cAeeuS/2K2pwDJEHMB3QiTA9EA1wBTUDMAyDDDAOkpOvyFhrz+e5F9AwUvdv1R2DMDXX16+pS+hvx3Ekj/cvfS/wNG+vyltAcAZiHs/\"\n  },\n  {\n    \"ProductId\": 44,\n    \"CategoryId\": 48,\n    \"Brand\": \"Life Guard X\",\n    \"Model\": \"RescueTech Emergency Kit\",\n    \"Description\": \"Be prepared for any emergency with the RescueTech emergency kit. Includes first aid supplies, fire starter, emergency blanket, and more.\",\n    \"Price\": 129.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 45,\n    \"CategoryId\": 34,\n    \"Brand\": \"NomadGear\",\n    \"Model\": \"TrailBlazer Solar Power Bank\",\n    \"Description\": \"Power up your devices on the go with the TrailBlazer solar power bank. Features high-capacity battery, solar charging, and rugged design.\",\n    \"Price\": 79.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 46,\n    \"CategoryId\": 28,\n    \"Brand\": \"Eco Grill\",\n    \"Model\": \"SunSpot Solar Cooker\",\n    \"Description\": \"Harness the power of the sun with this portable solar cooker. No fuel needed, perfect for off-grid cooking and eco-friendly adventures.\",\n    \"Price\": 149.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 47,\n    \"CategoryId\": 41,\n    \"Brand\": \"Nutritech\",\n    \"Model\": \"Protein Plus Energy Bars, Variety Pack\",\n    \"Description\": \"Fuel your outdoor adventures with these high-protein energy bars. Variety pack with delicious flavors for on-the-go nutrition.\",\n    \"Price\": 24.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 48,\n    \"CategoryId\": 60,\n    \"Brand\": \"Tech Outdoors\",\n    \"Model\": \"Rugged Waterproof Bluetooth Speaker\",\n    \"Description\": \"Durable and waterproof, this speaker is perfect for outdoor adventures. Bluetooth connectivity and long battery life for on-the-go music.\",\n    \"Price\": 79.99,\n    \"NameEmbedding\": \"ZI0Iv3MQgj0u20NABuuswD+WPcD02DzA/4uNQG6tnEDT+oPAfQYSwFLmNcBpjinAlUtrQM6kvL8Dq6RAkOVvQF8y6ECjeKs/Iqufv1Bqs0B+QPJATtnAPxyZar66U9W/ItSdv3KmkD+aBJW+WYnTP70H3D8NScnAYy24vrJiE7+ey/0/X62SPxrFqr+nfww/5MPNvwYNR7/nmZW/EhlfQFxYLcBgE7o/eGWBvieb5L/B+cu/SvcdwHHsSD/zQmnAIGJKQEyepcDrw3RArhdqwMN+2L9C3IDAkd0xvzmmX0Aw2K4/gC/PQLnir71vDWO/0rq/QGIBoEBy7znBCQ6rQAtLpUAlRORA5hqoPRvA3D+zlgRALmhkPiS7gUARcRBAxfH3QFrFE8DYg5M/r0WfPoJdTD8yjQo/XL8oP4RvrT+kVxA/LZSBwCuPkT7HsdW/IKBLwOCfGsByszO/C5BbwFY+Ar6/R7Y/0i/hwE9LJr82zlzA/CKDP1jHBcHVLh/AIr24P40Bzr9sPMG+7B02QWxU8cBZ3wNAG5howNxJ5L94ShtAXIKmwNFrFsAX8wLADl+FvzOAE0Cjqz9AauEywKR6Y79by7O/+GqMwAwbFkB+P72/ApHnP4Hak79klPu9pWGOwBdvRz62uslAXtbpvnAPGkAXwQDA9QoLQFYLZ0AVCvC/c1/5QJxKHz+zwQLAH1oiQLO3ND+4qD09YGAhwLXGF8Co/3K9uO+rP+lmaUBoFaS+aaWewJQuekC+fsvAI3INPkATCsD1UbnA8le3v2eaQr/GRjXAOsgNvoF5M0Dk8d1AKXRNwLwPgEDFJYE/Opm5QOJtJr7CoEbAmr6BQHTRlD+dUKk/IFPWu0Gipj9NGwk/G8UAwVCUd74iqNq/1mTkP7+H7D9GHoXAvbo3v3Q7iEBc932+ukaIPp4PpT9SFo3ANlWLP2rojMDpFRy/S5TbwFPtcz8xeYK/8Q/AvxFiFb80EFxAkiYEP7DW0r+TWy1AP/LWQPrqjz90yFrAKInCPgjlJj4VG0C/ZIwhP/g4ib9iFJi/x+gHQE5btz9scqI/ehc9wDadbMDh3wJACjD6QH8V3D+IlKk/ljv4PyCXSb+NU2Y/arN3QIz5o78E2i1AaqNZwBkeF8BdDsPA/r+CPzgxWkACaYq/e/Zevti7Hz8ledrAPvcGwHOkRcEj21vA2ouUP9casz/+qcM+pGiRPd1wREBpFnO/cxI/QF+Mwz9Wvq9AkHRnwDemYkCP2ls/KhQlwIoxlkCbzJ5ABjfFv9k2sz+Nagc/CrHPP8QnDT6z+3TAvBe4wMqxGEAVY4XARpVNQVxFPr/EEve9/z2uQHWfN8Cy9SNA/12Mv6Y6LcHW5rU+XmSWQCt0GcDB2a2/MbxTwPNum8AQov6+5M3QQCKEEkDev5HAMRTkvzgVDMBpiW/A/jdavqhptMBGcnDAJrqRQNtvjkCMZY09pCcJwIAOO0AbAUbApzaNwDhpAkCP9DzAH2kpwHBFOEA43i5AdKltv2Q6xL+l9vc/bG+zv01VQL/KOVS/vggzQNSkxb8zPak/AgllQEkfs79suY1AjIGuQG5PGr+7HEJA/kvTwDZEnj98VmrAQnBmQIRhrz9mn4JAaX71vwLGuL5uOI++9P4IQG74uj+WBfO/cgtRPiMrkL+DO7W/zElCP7qq/8BU1wZBgug/P/bJc8GcPRnAEEiBuzLMasDcubnAsaX6PQxlXz9KV1VAqusSwSXbFkCke4TA17V2QE5SuL/s0jU/yOvXPylVLEBpuXBAvjCcvU4bfD9AG+a+f5s+QEq9bD8i7fNA75GZv8S17UC0XYRAdLXTvvYIC0DYdEFAa9pmv7HpF0CDkJM/rbUkQfwSHsDlYc2/togOP8kRmT/7Noe+vFkXQFK9dcDEddE+7kbiPQc3gr86RhFAaoReQO/3ccDjDwQ/dsaxvzKRwT93XFZAxncpwE5lO8AUrei/UlbFPrLuP8DwKAtAZVCoP75WR8CS6sq/RJEOv8EiBr/MqcTAnMlawAB/KLwpNoNA\"\n  },\n  {\n    \"ProductId\": 49,\n    \"CategoryId\": 8,\n    \"Brand\": \"TrekMaven\",\n    \"Model\": \"Summit Hiking Boots\",\n    \"Description\": \"Designed for rugged terrain, these hiking boots provide ultimate support and traction. Breathable and waterproof for all-weather performance.\",\n    \"Price\": 129.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 5,\n    \"CategoryId\": 55,\n    \"Brand\": \"Swingnap\",\n    \"Model\": \"Double Hammock with Mosquito Net\",\n    \"Description\": \"Enjoy the great outdoors without the bugs with this double hammock featuring a built-in mosquito net. Durable and comfortable for any adventure.\",\n    \"Price\": 129.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 50,\n    \"CategoryId\": 15,\n    \"Brand\": \"Thirsttrek\",\n    \"Model\": \"HydroPack Hydration System, 3L\",\n    \"Description\": \"Stay hydrated on the trail with this high-capacity hydration system. Hands-free drinking and easy refill for long-lasting hydration.\",\n    \"Price\": 49.99,\n    \"NameEmbedding\": \"eW2EwBFXBL8NLw4/GAQBvx8KDD/1DTDA+OGVvT5IVECE1Jm/dNM8v2JOCT9ALjPBWOFxPpNtp8Dt6wlAWhsIv2ukX0C/+sdASRmbwC/VNECLAZZALDN9wAoDhsBAeHzA/h0AQCphC0BQ6Ic+roIEQLYo3L9CW23BENGgPp/nlD8HTUk/e9UlwNTdV8AY/B5AAcW/vwSQ9j+f0ALAirO0v5nHpL/V+jlA1jJywKSGEUBS/y2/56CywMS69L+Pqz/AtbONQJb7isCI7pw8sHFSvk9mdj+6fZ1AN70YQIj7pb/iBC4/QqeRQPTZRECmXsnA2Qa9PyAWaT+q5k3BDtqoQDqcuz/oDItA45gNv5dYd0BGnAFBqT/YQJwsjsActns+mA4dQEJcCEBuhTW/arwov96Ttz/8K1s+j+Sfvyldi8BfSte+vkxNwIVCHsDUg0q+oxKSwOgmfcAN9fI/IhRXwCRw1T843be/D81fwD+aJL/4oifAYiQPQHlV/MCtAeo/nRVkvx6rb8BjuTRA5vM2QY4VI8AvwGFA13+RQMhKf8CHQS9AklT7wBzCCMBR+S/AGb4ywK1MBUCjRLE/7U1nwHrFLkD4Aci/BdNYP+QVQj7+qJw+Nmj9P40kgr/O7IC+TV7tvwUmRkAElatArS16P4imq79QiEtAdMgQQIFfnkAwC009n3qSQKC8KUBvxoZAslzVvpiEisDU0Us9LEiLvweQvz/uLKPAbFusvYwRjUCj06LAKrqSPlhPgEDNvDTBWB5gwO+IjEBSD4a/XAAWPlb1dsCvQZg+0zENQLA7Y0DiUTY/CJ/QvtnkjUCw2qc/7hS5QMj52r++TNnA0BeWQL2XjL92yYjAUZBAwHJXO0EDFv0/QBVWwG1aXUChZSTAPmDmvnJJyD+4QT5ACGlwQLFGmb+l50jA73UtQFIGor/SF53A/OiLP6gpC0DMRhq/MpaYvuMVgkBIiAfATRJqQPrDB0Fn9jfAqm+DQIxmHL+TveU+MWZbPoaSZsDP+mdAIcyKQBfO7r/UhgY/alUoP7qmxb4eWBrAyclLPhLyjr4aEdJA7C15QA5cbb8IdDVAWnOHQBy6y0A+fB4+3n0KwA7+oL+5jzy+4EX8v5sXkj7LYU5A7AEnwP3FbsBAe/Y/Xm24QH8LfL8NHhjBjCVSwFinhkCTgq7ATmjtwEUVgMEYhZhAs014v1Thf8DvCAZBw9P9v52F1EA6m82/8usxwFhcM0AsNjxBdaFQP+Sal0DPk/Y/SqLIP65Dzj8+WbZAp8vJP3VchUCfx21AkSMyP+uE0r4FusJAsNqgvgbHNcAZGIHAvKpXQe7gCr7mN6VAvd0gwAUJKUBKGQ5Af+kTQNse9cCrkANA8iBTQFqmhr66ZJW/oDIHv6aSEj9scHy/MEy/QOBf7r+6yZbA6dRmP+QUUMBwFQm/sECWP7IXG8BY5cnAGF6VPwEbE0Anad+/TQiwwGc79UA8c/s/DXTnwCuJ+r9+c7HAq6+Hv2IZgL8OFlHACjiDwID6IMA3s5i/qJ9RQLgvnr+Lnau/8qN0QAg+F71i4l7A8ky4QA3yDsDC+7pA/F1WQC9QT0BYxQ/A9ZW8wCgjgj+wwp68uKSVv8ptZcD5V5q+G6SgvxXeskDy7NA/j+KEwMgbgz/6uB9A+YVGvwsjD8BrVs8/f5mXwKGif8CmzyhByYYxv2/rtcGueRu/vLvpP0Yh3sD8qKg+5OLkP2MSGUCsRLk+p4yxwOVlxz9Y3qC/5X6hQJl87r/jwCJA0H/GQDo6Wz9BNNNAZkEQwGUNFEAcY7a/whJOQMKATECIdnBBs7J3wP1OMr+R/LZA/OK7Pi4GgUBVnqG/El9GQORU0b90Q1ZAooqWQCuFpL+ccoY/G7QNQbwKxr9kFfi/8QmqQCGoeEBu8b8//gFxwMk+j8C61vO/I4uPQAUiqMA04QdAeIs4wbyc8D93SAzAKz2CwCKbqb2MejTAtnnQv11CPkD/8yA/DUAlwMxXi8BGg7zAx9TWwFRFJkDQ/RHBWZFAQBKYXT8SsUS/\"\n  },\n  {\n    \"ProductId\": 51,\n    \"CategoryId\": 5,\n    \"Brand\": \"Resilience Gear\",\n    \"Model\": \"Survival Pro Multi-Tool\",\n    \"Description\": \"Be prepared for any outdoor emergency with this compact and versatile multi-tool. Features include a knife, saw, fire starter, and more.\",\n    \"Price\": 49.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 52,\n    \"CategoryId\": 17,\n    \"Brand\": \"Trailcom\",\n    \"Model\": \"Trailblazer Off-Grid Communicator\",\n    \"Description\": \"Stay connected even in the most remote locations with this rugged and reliable off-grid communicator. Features include long-range radio, GPS, and emergency SOS beacon.\",\n    \"Price\": 199.99,\n    \"NameEmbedding\": \"o0l5wNOAsECyD7tAXdt3v6LZnT/Ppac/xxM1v1PBLEDT5+3AsypYP8r/oz8fSMbAwag3wCPCoz/rWKI/i1h5QDfsYEAHEPFArz1fQB/yr0BItz8/mzL0wKgx2L88dRA/Nf9HQCYyKkDiowDBA5QqwG6CRr/UlSbBOXSHP9NXW8B5sldAnpQAPqimUz2YaBQ/6Pt/vwnEfkCjRrfAe3UiwOXoRUBjlr9AXWklQNR8gUCqw+y/FwLgwFL0HkC1rZ3AepdCPwW0OcD/GphA7GXZvuppUz8+Wz3AX1qQP3GCskDUT4M/zMd8viioDb/llOM9RCoEv6h0er/SQIbB2e3aQHAXZ0AsvrC/Vtc5wJ8+RcB2LhJAR2ilQJmTbD4CfYxAdFSdPzsIakAiPQNAeUpEPmySm8DHzixAdgnRv4hYCcByhilAgCERwMJbn78sB/E/XwquvxoBRMDRQHtAujnWwLVPW0CDYyy+rppDwEboAkC5M2lA4dMMP5LZTMHAtsTA7fG7P1uqfz+IJaY/DstuQW6g7b/zkxBAv9OCQCZogT+B1qM/nTHKwEqDmr8i5jrArEa8vz7wHUDsPnBAy0mJvma2JsDii9K/uu2Yv66y3r8w1E1AJrC2QPb+jj9eL/JAvCGuwOKVM8BoTUo9hAtjvvAJtUD0Ck7AvQmgQBo4xUBoZu4/66ikP3w75kC4mVQ/oguHP+AMgkCh52BA/Oazv+eeMkD+ps0/v/+nP4Jc9j9KzVO/3kWxP1DMUUDAJBTBX86DP+0Xgj/tTWjA6PfUv/ZKrsAIudO9uxt1vyB1HEBYrvRAlJ8VwI06AkBxJVFAJye6QIFe4z7smT3AtM8LQHb6AL+L+TDAGZVNP/76G0EkZwVANzBRwQWl/z7kNAfAPr1SwK1umMBl+qC/Bp/6v0eyn74X8CjAThTPQOfFvb+GHQ/BdMbaPwM8z78tXf4/5fFuvpBwpz3shqk/3zIRQBVENb8waOy/tm37v42GT8BE0ExAfUimQDn4RL8JPZXAnciwQK5n6L0pZhTABiC+vSjnesD7vqXAmiECQOhLusAmAotAZCm3v/NZGsASyRjAbfwvvwmHbD6MQFfAi8v+v+zmokANGb9AR3cmwIITq7/oj81A6K7Nv/SN2sClL2zA3G0KQXyxub5P+Yy/JBVtQJrqr75kfwZA8NKwwOtMqcGxsyo/hyeVv0JtwEDdVNC+5TvNv3Y/H0A0oaw9WgEZvuE3OEBUShZBw2aIvpPSnD/sJ/c/lu0nP2ELzEDSaQ5Ay5tEwBDCEb/SncG/DQNtQNG1WUBqhY7AqH/CwCBMU79mqKa/+Q9CQYKY50C336xAu624P0StHkC7X4JAe/XJv9QKocBW9Qg/6pVcv7T6FMC1bb6/olhDQAIQAb/YB9w+0rbgQMYzQD/ilgjBtwR0QNT6wD5NqEzA1pN+v4y/4b8lBcTA6X82QDw8U8DagD9Aw/2UP6VBmEAIY+O//kTgwB+ckEAazIfAxq1Xvz05nr820B/AtNv1v74wtL1P8pJApqoHQbBnKj+jliI/ebG7QKxQS8BSfHG/536eQLqorj8vjV9APhgKQKf9K74P6QFAT464wIZQpcBTEI7A+cQ5QAUKM8AkUlm+7eNsQDtAKr6N6RZAsY1MwG6XO8Bs8QhARlpGv41YEEDqkOc/C+uEwNe+0cB0TAVBF4oav4FtpsHIsGnADDPsP70bHsDFVRvAGh9EP0XkLUCslDFAa4SZP5noVL+MTwtAEEWPQCwxE8AfG5HAuJ6kPd7fuEB+vvdAc1YlwGTlcj8wOJ7ACwBJQKRBwT7oeFNBUsglPs39IEAe0WhAg+zRvp9nCcC6lWJAgkA0wMB1eT/5TpXAFA46Qci0NMAgvntAg4PqPmmAr77fdMY+SrJlQD8KA8DBSgrBHH6GQOwiHUB0q6/Ay7PbQGlpR8AJpa3ATPOEwMsoOUCj2Ly//Ymjv3nWRMCPF9rA6HOuP0ZmbsDKK/e/bCSzPl1MasDrzKvALOPmvnVvpsBKFi3AVR2EPva538A33R1A\"\n  },\n  {\n    \"ProductId\": 53,\n    \"CategoryId\": 16,\n    \"Brand\": \"IceMaster\",\n    \"Model\": \"GlacierTech Snowsport Goggles\",\n    \"Description\": \"Experience crystal-clear vision on the slopes with these high-performance snowsport goggles. Features include anti-fog coating, UV protection, and adjustable strap.\",\n    \"Price\": 79.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 54,\n    \"CategoryId\": 57,\n    \"Brand\": \"PowderPeak\",\n    \"Model\": \"AvalanchePro Ski Backpack\",\n    \"Description\": \"Stay safe and organized on backcountry adventures with this durable ski backpack. Features include avalanche safety gear storage, hydration reservoir compatibility, and ergonomic design.\",\n    \"Price\": 149.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 55,\n    \"CategoryId\": 2,\n    \"Brand\": \"Exploremate\",\n    \"Model\": \"Adventurer 2000 GPS Navigator\",\n    \"Description\": \"Never get lost on the trail with this advanced GPS navigator. Features include topographic mapping, waypoint marking, and rugged waterproof design.\",\n    \"Price\": 249.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 56,\n    \"CategoryId\": 9,\n    \"Brand\": \"Slumberpeak\",\n    \"Model\": \"Naptime 5000 Sleeping Bag\",\n    \"Description\": \"Stay warm and cozy on your outdoor adventures with the ultra-warm Naptime 5000 Sleeping Bag from Slumberpeak. Water-resistant, lightweight, and easy to pack.\",\n    \"Price\": 129.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 57,\n    \"CategoryId\": 13,\n    \"Brand\": \"Charge Mate\",\n    \"Model\": \"PowerPort 10000 Portable Charger\",\n    \"Description\": \"Never run out of battery on your outdoor expeditions with the PowerPort 10000 Portable Charger from Charge Mate. Compact, fast-charging, and compatible with all devices.\",\n    \"Price\": 49.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 58,\n    \"CategoryId\": 35,\n    \"Brand\": \"GuardianGear\",\n    \"Model\": \"SafeTrail GPS Locator\",\n    \"Description\": \"Ensure your safety in the great outdoors with the SafeTrail GPS Locator from GuardianGear. Real-time tracking, SOS button, and rugged design for any adventure.\",\n    \"Price\": 199.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 59,\n    \"CategoryId\": 59,\n    \"Brand\": \"Aqua Venture\",\n    \"Model\": \"Explorer 3000 Kayak\",\n    \"Description\": \"Conquer the waterways with the Explorer 3000 Kayak from Aqua Venture. Lightweight, stable, and built for performance with a comfortable seating system.\",\n    \"Price\": 599.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 6,\n    \"CategoryId\": 12,\n    \"Brand\": \"MantleMaster\",\n    \"Model\": \"ExcavaTrek 3000\",\n    \"Description\": \"The ExcavaTrek 3000 is a high-tech excavation tool for outdoor adventurers. With its durable build and precision control, it\\u0027s perfect for digging and uncovering hidden treasures.\",\n    \"Price\": 299.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 60,\n    \"CategoryId\": 6,\n    \"Brand\": \"H2OZone\",\n    \"Model\": \"PureFlow Water Filter Bottle\",\n    \"Description\": \"Stay hydrated on your outdoor journeys with the PureFlow Water Filter Bottle from H2OZone. Removes 99.9% of waterborne bacteria and protozoa, BPA-free, and leak-proof.\",\n    \"Price\": 34.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 61,\n    \"CategoryId\": 17,\n    \"Brand\": \"Adventure Link\",\n    \"Model\": \"Satellite Communicator 2000\",\n    \"Description\": \"Stay connected off the grid with the Satellite Communicator 2000. Send text messages, track your location, and access SOS features in remote areas.\",\n    \"Price\": 299.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 62,\n    \"CategoryId\": 32,\n    \"Brand\": \"LumaBeam\",\n    \"Model\": \"UltraBright Headlamp 500\",\n    \"Description\": \"Light up the night with the UltraBright Headlamp 500. With adjustable brightness and a long battery life, it\\u0027s perfect for outdoor activities after dark.\",\n    \"Price\": 49.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 63,\n    \"CategoryId\": 54,\n    \"Brand\": \"Luminartech\",\n    \"Model\": \"Solar-Powered String Lights\",\n    \"Description\": \"Create a magical outdoor atmosphere with these Solar-Powered String Lights. Waterproof and durable, they\\u0027re ideal for camping and backyard gatherings.\",\n    \"Price\": 39.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 64,\n    \"CategoryId\": 29,\n    \"Brand\": \"AquaFusion\",\n    \"Model\": \"Portable Water Purifier 1000\",\n    \"Description\": \"Safely drink from any water source with the Portable Water Purifier 1000. Removes 99.9% of bacteria, viruses, and protozoa for clean hydration on the go.\",\n    \"Price\": 89.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 65,\n    \"CategoryId\": 33,\n    \"Brand\": \"Camptech\",\n    \"Model\": \"Multi-Tool Camping Gadget\",\n    \"Description\": \"Be prepared for anything with the Multi-Tool Camping Gadget. Includes a knife, saw, screwdriver, and more, all in a compact, portable design.\",\n    \"Price\": 34.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 66,\n    \"CategoryId\": 26,\n    \"Brand\": \"Shade Scape\",\n    \"Model\": \"SunSafe Pop-Up Beach Tent\",\n    \"Description\": \"Stay cool and protected from the sun with this easy-to-assemble portable shelter. UPF 50\\u002B sun protection and durable construction make it perfect for beach trips and outdoor events.\",\n    \"Price\": 89.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 67,\n    \"CategoryId\": 41,\n    \"Brand\": \"Nutritech\",\n    \"Model\": \"Energy Bars Variety Pack\",\n    \"Description\": \"Fuel your next outdoor adventure with these high-protein, low-sugar energy bars. Provides a quick and convenient source of nutrition without sacrificing taste or quality.\",\n    \"Price\": 19.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 68,\n    \"CategoryId\": 8,\n    \"Brand\": \"Stepquest\",\n    \"Model\": \"Trailblazer Hiking Shoes\",\n    \"Description\": \"Conquer any terrain with these rugged and comfortable hiking shoes. Waterproof construction, durable outsole, and extra cushioning provide stability and support on the trails.\",\n    \"Price\": 129.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 69,\n    \"CategoryId\": 47,\n    \"Brand\": \"Summit Step\",\n    \"Model\": \"Alpine Explorer Hiking Boots\",\n    \"Description\": \"Take on challenging hikes with confidence in these waterproof and breathable hiking boots. Aggressive tread pattern and shock-absorbing midsole provide traction and comfort.\",\n    \"Price\": 169.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 7,\n    \"CategoryId\": 62,\n    \"Brand\": \"Adventure Prosthetics\",\n    \"Model\": \"Off-Grid Surgeon Kit\",\n    \"Description\": \"The Off-Grid Surgeon Kit from Adventure Prosthetics is a must-have for any outdoor medical emergency. It includes essential tools and supplies for surgical procedures in remote locations.\",\n    \"Price\": 499.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 70,\n    \"CategoryId\": 13,\n    \"Brand\": \"Juice Junkie\",\n    \"Model\": \"Solar Power Bank 10000mAh\",\n    \"Description\": \"Stay charged and connected on the go with this portable solar power bank. Built-in solar panel and multiple USB ports ensure reliable power for your outdoor electronics.\",\n    \"Price\": 49.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 71,\n    \"CategoryId\": 17,\n    \"Brand\": \"Trailcom\",\n    \"Model\": \"Trailcom Signal Booster 2000\",\n    \"Description\": \"Stay connected even in remote areas with the Trailcom Signal Booster 2000. Boosts signal strength for off-grid communication. Compatible with most devices.\",\n    \"Price\": 199.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 72,\n    \"CategoryId\": 49,\n    \"Brand\": \"Angler\\u0027s Choice\",\n    \"Model\": \"Angler\\u0027s Choice Pro Fish Finder 500\",\n    \"Description\": \"Catch more fish with the Angler\\u0027s Choice Pro Fish Finder 500. High-tech sonar technology for accurate fish location. Easy to use and durable design.\",\n    \"Price\": 299.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 73,\n    \"CategoryId\": 63,\n    \"Brand\": \"SkySight\",\n    \"Model\": \"SkySight Eagle Eye 1000 Drone\",\n    \"Description\": \"Capture stunning aerial footage with the SkySight Eagle Eye 1000 Drone. 4K camera, long battery life, and advanced GPS features for smooth flight control.\",\n    \"Price\": 599.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 74,\n    \"CategoryId\": 55,\n    \"Brand\": \"Naturehaven\",\n    \"Model\": \"Naturehaven Ultra-Light Hammock\",\n    \"Description\": \"Relax in comfort with the Naturehaven Ultra-Light Hammock. Made of durable, lightweight materials. Easy to set up and pack for outdoor adventures.\",\n    \"Price\": 49.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 75,\n    \"CategoryId\": 35,\n    \"Brand\": \"Escapesafe\",\n    \"Model\": \"Escapesafe GPS Locator Beacon\",\n    \"Description\": \"Stay safe during outdoor activities with the Escapesafe GPS Locator Beacon. Sends emergency signal with GPS location to rescue services. Compact and waterproof design.\",\n    \"Price\": 129.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 76,\n    \"CategoryId\": 36,\n    \"Brand\": \"UltiBASS\",\n    \"Model\": \"Wilderness DJ Pro\",\n    \"Description\": \"The ultimate DJing setup for outdoor adventures. With rugged, high-tech equipment that can withstand any environment, the Wilderness DJ Pro is perfect for entertaining on the go.\",\n    \"Price\": 399.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 77,\n    \"CategoryId\": 46,\n    \"Brand\": \"Ecovolt\",\n    \"Model\": \"Solar Charger 3000X\",\n    \"Description\": \"Never run out of power with the Solar Charger 3000X. This high-capacity, portable solar charger is perfect for keeping your electronic devices charged during your outdoor expeditions.\",\n    \"Price\": 149.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 78,\n    \"CategoryId\": 64,\n    \"Brand\": \"WaterRover\",\n    \"Model\": \"AquaTech X-5000\",\n    \"Description\": \"Take your watersports to the next level with the AquaTech X-5000. This high-tech gear features advanced materials and design for maximum performance and durability on the water.\",\n    \"Price\": 599.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 79,\n    \"CategoryId\": 37,\n    \"Brand\": \"Capture Tech\",\n    \"Model\": \"Adventure Pro Camera\",\n    \"Description\": \"Capture every moment of your outdoor adventures with the Adventure Pro Camera. With 4K resolution and advanced image stabilization, this camera is perfect for any adventure photographer.\",\n    \"Price\": 299.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 8,\n    \"CategoryId\": 67,\n    \"Brand\": \"TrailFax\",\n    \"Model\": \"Outdoor Admin 5000\",\n    \"Description\": \"The Outdoor Admin 5000 is a high-tech organizational tool for outdoor enthusiasts. Manage your itinerary, maps, and emergency contacts with ease, all in one device.\",\n    \"Price\": 199.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 80,\n    \"CategoryId\": 49,\n    \"Brand\": \"Reelmaster\",\n    \"Model\": \"Stealth 5000 Fishing Reel\",\n    \"Description\": \"Dominate the waters with the Stealth 5000 Fishing Reel. Built for power and precision, this high-tech reel is designed to handle the toughest fish in any environment.\",\n    \"Price\": 199.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 81,\n    \"CategoryId\": 65,\n    \"Brand\": \"Rockgrip\",\n    \"Model\": \"Summit X Climbing Harness\",\n    \"Description\": \"Stay safe and secure during your climbing adventures with the Summit X Climbing Harness. Features reinforced webbing and adjustable buckles for a comfortable and customizable fit.\",\n    \"Price\": 129.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 82,\n    \"CategoryId\": 39,\n    \"Brand\": \"Essential Tech\",\n    \"Model\": \"SurvivalPro Emergency Kit\",\n    \"Description\": \"Be prepared for any outdoor emergency with the SurvivalPro Emergency Kit. Includes essential tools, first aid supplies, and emergency rations for peace of mind on your adventures.\",\n    \"Price\": 89.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 83,\n    \"CategoryId\": 63,\n    \"Brand\": \"AeroVision\",\n    \"Model\": \"SkyRanger HD Aerial Drone\",\n    \"Description\": \"Capture stunning aerial footage with the SkyRanger HD Aerial Drone. Features 4K camera, GPS tracking, and long battery life for extended flight time.\",\n    \"Price\": 499.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 84,\n    \"CategoryId\": 22,\n    \"Brand\": \"Techtrek\",\n    \"Model\": \"Trailblazer GPS Smartwatch\",\n    \"Description\": \"Navigate your outdoor adventures with ease using the Trailblazer GPS Smartwatch. Built-in GPS, heart rate monitor, and rugged design make it ideal for outdoor activities.\",\n    \"Price\": 199.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 85,\n    \"CategoryId\": 48,\n    \"Brand\": \"ReadySurvive\",\n    \"Model\": \"All-Weather Fire Starter Kit\",\n    \"Description\": \"Stay warm and cook meals outdoors with the All-Weather Fire Starter Kit. Includes waterproof matches, fire starter sticks, and compact carrying case for easy storage.\",\n    \"Price\": 24.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 86,\n    \"CategoryId\": 39,\n    \"Brand\": \"Survive All\",\n    \"Model\": \"SOS Multitool Kit\",\n    \"Description\": \"Be prepared for emergencies with this versatile multitool kit. Includes knife, fire starter, compass, and more.\",\n    \"Price\": 49.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 87,\n    \"CategoryId\": 23,\n    \"Brand\": \"Cyclo Tech\",\n    \"Model\": \"Xtreme Trail Bike Helmet\",\n    \"Description\": \"Protect your head with this high-tech helmet designed for mountain biking. Lightweight, aerodynamic, and adjustable.\",\n    \"Price\": 89.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 88,\n    \"CategoryId\": 59,\n    \"Brand\": \"WaterWay\",\n    \"Model\": \"RapidFlow Kayak Paddle\",\n    \"Description\": \"Paddle through rapids with ease using this lightweight and durable kayak paddle. Ergonomic grip for long paddling sessions.\",\n    \"Price\": 129.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 89,\n    \"CategoryId\": 14,\n    \"Brand\": \"Backcountry Cook\",\n    \"Model\": \"Titanium Backpacking Cookware Set\",\n    \"Description\": \"Cook gourmet meals in the backcountry with this ultra-light and compact cookware set. Non-stick and easy to clean.\",\n    \"Price\": 79.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 9,\n    \"CategoryId\": 44,\n    \"Brand\": \"SummitChomp\",\n    \"Model\": \"AltitudeShield Pro\",\n    \"Description\": \"The AltitudeShield Pro by SummitChomp is a high-altitude cake protection system, designed to keep your baked goods safe and fresh in extreme conditions. Perfect for mountain bakers!\",\n    \"Price\": 79.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 90,\n    \"CategoryId\": 29,\n    \"Brand\": \"AquaFusion\",\n    \"Model\": \"PurifyPro Water Filter Pump\",\n    \"Description\": \"Stay hydrated during outdoor adventures with this high-efficiency water filter pump. Removes 99.9999% of waterborne bacteria.\",\n    \"Price\": 149.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 91,\n    \"CategoryId\": 30,\n    \"Brand\": \"Stormguard\",\n    \"Model\": \"WeatherShield Pro Jacket\",\n    \"Description\": \"Stay dry and warm in any weather with the WeatherShield Pro Jacket. Waterproof, windproof, and breathable, with advanced insulation for superior performance.\",\n    \"Price\": 149.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 92,\n    \"CategoryId\": 29,\n    \"Brand\": \"PureFlow\",\n    \"Model\": \"AquaPure Portable Water Filter\",\n    \"Description\": \"Ensure access to clean drinking water on your outdoor adventures with the AquaPure Portable Water Filter. Removes 99.9% of bacteria and protozoa, with a compact and lightweight design for easy transport.\",\n    \"Price\": 79.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 93,\n    \"CategoryId\": 28,\n    \"Brand\": \"Solarchef\",\n    \"Model\": \"SunChef Solar Powered Stove\",\n    \"Description\": \"Cook your meals off-grid with the SunChef Solar Powered Stove. Utilizes renewable solar energy for eco-friendly cooking, with a lightweight and portable design for convenient use anywhere.\",\n    \"Price\": 199.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 94,\n    \"CategoryId\": 33,\n    \"Brand\": \"Wild Tech\",\n    \"Model\": \"TrailBlazer Multi-Tool\",\n    \"Description\": \"Be prepared for any camping situation with the TrailBlazer Multi-Tool. Features a variety of essential gadgets, including a knife, saw, bottle opener, and more, all in a compact and durable design.\",\n    \"Price\": 39.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 95,\n    \"CategoryId\": 9,\n    \"Brand\": \"Slumberpeak\",\n    \"Model\": \"Summit 4-Season Sleeping Bag\",\n    \"Description\": \"Experience ultimate comfort during your outdoor sleeping with the Summit 4-Season Sleeping Bag. Designed for all-weather use, with high-quality insulation and a spacious yet lightweight construction for a restful night\\u0027s sleep.\",\n    \"Price\": 179.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 96,\n    \"CategoryId\": 54,\n    \"Brand\": \"Luminartech\",\n    \"Model\": \"Solaris 5000 Outdoor Lantern\",\n    \"Description\": \"Illuminate your outdoor adventures with the Solaris 5000. With advanced LED technology, solar-powered, and lightweight design, it\\u0027s the perfect lighting solution for camping, hiking, and more.\",\n    \"Price\": 59.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 97,\n    \"CategoryId\": 34,\n    \"Brand\": \"NomadGear\",\n    \"Model\": \"Wanderer Multi-Tool Keychain\",\n    \"Description\": \"Be prepared for anything with the Wanderer Multi-Tool Keychain. This compact, high-tech tool features a variety of functions, including a knife, screwdriver, and bottle opener, making it a must-have for travelers and adventurers.\",\n    \"Price\": 24.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 98,\n    \"CategoryId\": 25,\n    \"Brand\": \"Exploremate\",\n    \"Model\": \"TrailBlazer GPS Watch\",\n    \"Description\": \"Navigate the great outdoors with ease using the TrailBlazer GPS Watch. With built-in GPS, altimeter, and rugged design, it\\u0027s the ultimate companion for trail running, hiking, and exploring off the beaten path.\",\n    \"Price\": 199.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 99,\n    \"CategoryId\": 31,\n    \"Brand\": \"Hike Wise\",\n    \"Model\": \"Summit 3000 Trekking Backpack\",\n    \"Description\": \"Conquer any trail with the Summit 3000 Trekking Backpack. With ergonomic design, adjustable straps, and durable construction, it offers ample storage and support for all your outdoor adventures.\",\n    \"Price\": 129.99,\n    \"NameEmbedding\": \"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\"\n  }\n]"
  },
  {
    "path": "seeddata/dev/tickets.json",
    "content": "[\n  {\n    \"TicketId\": 1,\n    \"ProductId\": 104,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 1,\n    \"ShortSummary\": \"Filter cartridge replacement and maintenance inquiry\",\n    \"LongSummary\": \"Customer inquiring about replacement frequency and signs for filter cartridge. Requesting maintenance tips for outdoor use. Next agent should provide detailed maintenance steps for outdoor use.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I\\u0027m considering purchasing the Aquaduct Puriflo Water Filter Bottle for my upcoming hiking trip. I\\u0027m wondering if the filter cartridge needs to be replaced regularly, and if so, how often? Also, are there any specific maintenance tips for using the bottle on extended outdoor trips? Thank you for your assistance.\"\n      },\n      {\n        \"MessageId\": 2,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Aquaduct Puriflo Water Filter Bottle is equipped with a high-performance filter cartridge that should be disposed of carefully in accordance with local regulations. To remove the filter cartridge, unscrew the filter housing from the bottle body and carefully remove the cartridge. Additionally, the bottle features a high-performance filter cartridge that utilizes a microfiltration membrane to effectively remove contaminants from water. For maintenance tips, it\\u0027s recommended to store the Puriflo Water Filter Bottle in a clean and dry environment when not in use. Avoid exposing the product to extreme temperatures or direct sunlight, as this may degrade its performance and structural integrity.\"\n      },\n      {\n        \"MessageId\": 3,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information. Just to clarify, how often should the filter cartridge be replaced? Also, are there any specific signs to look for that indicate the cartridge needs to be replaced? Thank you for your help.\"\n      },\n      {\n        \"MessageId\": 4,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The filter cartridge needs to be replaced after filtering 500 liters of water. You can monitor the filter\\u0027s condition by inspecting it for discoloration or clogging. Additionally, weekly maintenance includes cleaning the filter cartridge with warm water and mild detergent. For detailed maintenance and calibration procedures, refer to the user manual.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 2,\n    \"ProductId\": 200,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 56,\n    \"ShortSummary\": \"MOLLE Compatibility Guidance Needed\",\n    \"LongSummary\": \"Customer purchased Raptor Tactical Backpack from Strategicgear and needs guidance on properly utilizing the MOLLE system. Specifically asking for help with securely attaching pouches and accessories. Pending response on how to resolve MOLLE compatibility issues.\",\n    \"CustomerSatisfaction\": 10,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 312,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Raptor Tactical Backpack from Strategicgear and I\\u0027m experiencing some difficulties with the MOLLE compatibility. I was under the impression that the backpack would be able to securely attach additional pouches and accessories, but I\\u0027m having trouble with the webbing. Can you provide me with some guidance on how to properly utilize the MOLLE system? Your assistance would be greatly appreciated. Thank you.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 3,\n    \"ProductId\": 168,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 191,\n    \"ShortSummary\": \"WildDJ Pro Mixer battery charging issue\",\n    \"LongSummary\": \"Customer Evan Walters needs help with WildDJ Pro Mixer battery charging. Specific info on how to charge the battery is needed. Pending question: how to charge the battery?\",\n    \"CustomerSatisfaction\": 10,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 599,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Need help with WildDJ Pro Mixer battery charging. How to do?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 4,\n    \"ProductId\": 140,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 271,\n    \"ShortSummary\": \"Inquiry about wholesale and battery life\",\n    \"LongSummary\": \"Customer Samantha is interested in wholesale options and battery life details for the RuggedSound Waterproof Bluetooth Speaker. Pending question on battery life. Next support agent should provide battery life details.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 920,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there, Trektunes team! I just stumbled upon your RuggedSound Waterproof Bluetooth Speaker and I am absolutely blown away by the idea of taking my music on all my outdoor adventures! The fact that it\\u0027s waterproof and dustproof is a game-changer for me. I run a retail store and I can already see our customers loving this product. Can you share more details about the speaker\\u0027s battery life and how it holds up in different outdoor conditions? Also, do you offer any wholesale options for retailers like us? I\\u0027d love to chat more about stocking your awesome product. Looking forward to hearing from you soon! Cheers, Samantha.\"\n      },\n      {\n        \"MessageId\": 921,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hi Samantha, thank you for your interest in the RuggedSound Waterproof Bluetooth Speaker! According to the product manual, the speaker is designed to withstand the harshest outdoor conditions and is rated IPX7 waterproof, allowing it to be fully submerged in water up to 1 meter deep for 30 minutes without being damaged. The battery life details are not provided in the manual. For wholesale options, please contact our sales team at sales@trektunes.example.com. Let us know if there\\u0027s anything else we can assist you with!\"\n      },\n      {\n        \"MessageId\": 922,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! Thanks for all the info. I\\u0027ll be sure to reach out to your sales team about wholesale options. Do you happen to have any information on the battery life? I\\u0027m so excited to bring this speaker on all my outdoor adventures!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 5,\n    \"ProductId\": 147,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 350,\n    \"ShortSummary\": \"GPS troubleshooting for SkyMaster X2000\",\n    \"LongSummary\": \"Customer needs additional troubleshooting steps for non-functioning GPS on SkyMaster X2000. Advised to contact manufacturer or initiate return process.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Returns\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1242,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"GPS not working, drone won\\u0027t hold position. Need help.\"\n      },\n      {\n        \"MessageId\": 1243,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry, I couldn\\u0027t find information about manufacturer contact details in the manual. If you need to contact the manufacturer, I recommend checking their official website or contacting the store where you purchased the drone for assistance.\"\n      },\n      {\n        \"MessageId\": 1244,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Still not working. Need more help.\"\n      },\n      {\n        \"MessageId\": 1245,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, to address GPS navigation errors, I recommend verifying that the GPS module is properly connected and functioning on the drone. It\\u0027s also advisable to update the drone\\u0027s firmware to ensure compatibility with the latest GPS navigation systems. If GPS errors persist, recalibrate the GPS system and ensure a clear line of sight to the satellites for accurate positioning.\"\n      },\n      {\n        \"MessageId\": 1246,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"GPS still not working after following your suggestions. Please advise further.\"\n      },\n      {\n        \"MessageId\": 1247,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Based on the manual, the next steps to address GPS navigation errors are to recalibrate the GPS system and ensure a clear line of sight to the satellites for accurate positioning. If the issue persists, please initiate a return or repair process at https://northernmountains.example.com/support/returns\"\n      },\n      {\n        \"MessageId\": 1248,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Tried recalibrating GPS and still not working. Will initiate return process.\"\n      },\n      {\n        \"MessageId\": 1249,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry that the troubleshooting steps didn\\u0027t resolve the issue. You may contact AeroVision\\u0027s customer support team at 1-800-AERO-123 or email them at support@aerovision.com for further assistance. If you prefer to initiate a return, you can do so at https://northernmountains.example.com/support/returns. Thank you for choosing SkyMaster X2000.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 6,\n    \"ProductId\": 88,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 357,\n    \"ShortSummary\": \"Safety concern with RapidFlow Kayak Paddle\",\n    \"LongSummary\": \"Customer seeks guidance on addressing grip slippage safety issue with RapidFlow Kayak Paddle. Asks for information on how to ensure safe use. Pending question: How to address grip slippage issue.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1282,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the WaterWay RapidFlow Kayak Paddle and I have a question about the grip slippage issue. I\\u0027ve noticed that the grip seems to be slipping during use, and I\\u0027m concerned about potential safety risks. Can you provide me with some information on how to address this problem? I want to ensure that I can continue using the paddle safely. Thank you.\"\n      },\n      {\n        \"MessageId\": 1283,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, if you experience grip slippage while using the paddle, immediately cease paddling and secure the paddle to your kayak. Continuing to use the paddle with a slipping grip may cause loss of control, leading to potential capsizing or injury. Ensure the paddle\\u0027s grip is securely fastened before resuming use. If the problem persists, discontinue use and seek a professional to inspect the paddle for potential defects.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 7,\n    \"ProductId\": 76,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 56,\n    \"ShortSummary\": \"Inquiry about using Wilderness DJ Pro for summoning forest spirits\",\n    \"LongSummary\": \"Customer inquired about using Wilderness DJ Pro to summon forest spirits, was informed it is not designed for that. Customer accepted, stating they will use it for mixing music.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1304,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, I got the Wilderness DJ Pro and I want to use it to summon forest spirits. Can it do that?\"\n      },\n      {\n        \"MessageId\": 1305,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry, the user manual does not contain any information about summoning forest spirits with the Wilderness DJ Pro.\"\n      },\n      {\n        \"MessageId\": 1306,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Well, that\\u0027s disappointing. I really wanted to summon some forest spirits. Can you recommend a different product that can do that?\"\n      },\n      {\n        \"MessageId\": 1307,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry, but the Wilderness DJ Pro is not designed for summoning forest spirits. However, it is a high-quality product for mixing music and delivering powerful bass. If you have any other questions about the product or need assistance with using it for its intended purpose, feel free to ask. Is there anything else I can help you with?\"\n      },\n      {\n        \"MessageId\": 1308,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Well, I guess I\\u0027ll just use it for mixing music. Thanks.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 8,\n    \"ProductId\": 131,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 121,\n    \"ShortSummary\": \"NatureCam 1000 won\\u0027t turn on\",\n    \"LongSummary\": \"Customer\\u0027s NatureCam 1000 won\\u0027t turn on despite troubleshooting steps. Requesting more in-depth troubleshooting. Needs specific guidance on resolving the issue.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1330,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Greetings Naturevision support team, I recently purchased the NatureCam 1000 and am encountering a major issue - the camera is not turning on at all. I have meticulously checked the batteries, ensured they are properly inserted, and they have sufficient power. Additionally, I attempted to reset the camera by removing the batteries for an extended period and reinserting them as per the troubleshooting manual, but to no avail. I am an experienced user and have never encountered such a problem with previous trail cameras. I would greatly appreciate any specific guidance or insights on how to resolve this issue as I am eager to utilize the stunning HD capture capabilities of the NatureCam 1000. Your prompt assistance in addressing this technical matter is highly anticipated. Thank you for your attention to this matter.\"\n      },\n      {\n        \"MessageId\": 1331,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, if your NatureCam 1000 isn\\u0027t turning on, first check the batteries to make sure they\\u0027re properly inserted and have enough power. If the batteries are fine, try resetting the camera by removing the batteries for a few minutes and then reinserting them.\"\n      },\n      {\n        \"MessageId\": 1332,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I have followed the instructions provided in the manual and by the assistant, but unfortunately, the NatureCam 1000 still does not turn on. I have checked the batteries multiple times and they are properly inserted with enough power. I am confident in my technical abilities and am certain that the issue lies beyond a simple battery or reset problem. I would appreciate a more in-depth troubleshooting process to address this issue. Your urgent attention to this matter is crucial as I am unable to utilize the camera\\u0027s features. Thank you.\"\n      },\n      {\n        \"MessageId\": 1333,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, there are some common problems and how to fix them. We also have tips for dealing with weather-related issues. Let\\u0027s see if this provides further insight into the issue with your NatureCam 1000. I\\u0027ll get back to you shortly with more information.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 9,\n    \"ProductId\": 149,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 379,\n    \"ShortSummary\": \"Inquiry about Buckle Material and Durability\",\n    \"LongSummary\": \"Customer inquiring about material composition, durability, and potential failure modes of the buckles on AquaFlow Pro. Assistant provided information on reservoir material and straps but suggested contacting manufacturer for buckle details.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1362,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Greetings, I am considering utilizing the AquaFlow Pro hydration system from Thirsttrek for a unique application that requires a high level of material durability and performance. I have thoroughly researched the technical specifications of the BPA-free reservoir material properties, including the ASTM D5116-16, ISO 10993-1:2018, and FDA Title 21CFR177.1520 standards. I am confident that the proprietary blend of polyethylene, known as Hydratech 3000, will meet the stringent requirements of my intended use. Additionally, the flow dynamics of the bite valve are of particular interest to me as I require optimal liquid flow for my purposes. I understand that Thirsttrek engineers have conducted thorough analysis, including Computational Fluid Dynamics (CFD) modeling and measurement of flow rates and forces using a hydraulic test bench. I believe that this level of engineering precision aligns with my needs. However, I would appreciate further information or assistance in ensuring that the adjustable straps are suitable for my intended use. Your prompt and detailed response would be greatly appreciated.\"\n      },\n      {\n        \"MessageId\": 1363,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the adjustable straps on the Thirsttrek AquaFlow Pro hydration system have been engineered for comfort and stability. The design analysis includes Finite Element Analysis (FEA) to assess stress distribution and performance under load. This ensures a customized and comfortable fit for users of all sizes.\"\n      },\n      {\n        \"MessageId\": 1364,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information regarding the adjustable straps. I would like to inquire further about the material composition and durability of the buckles used on the Thirsttrek AquaFlow Pro hydration system. Can you provide detailed information on the material type, strength, and potential failure modes of the buckles? Your prompt and comprehensive response would be greatly appreciated.\"\n      },\n      {\n        \"MessageId\": 1365,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Thirsttrek AquaFlow Pro hydration system features a state-of-the-art BPA-free reservoir constructed from a proprietary blend of polyethylene, known as Hydratech 3000. This material has been extensively tested and meets industry standards. Additionally, the adjustable straps have been engineered for comfort and stability, including Finite Element Analysis (FEA) for stress distribution and performance under load. Unfortunately, I was unable to locate specific information about the material composition, durability, and potential failure modes of the buckles in the manual. For detailed information on the buckles, I recommend reaching out to the manufacturer\\u0027s support contact, as detailed in the user manual. If you need further assistance, feel free to ask.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 10,\n    \"ProductId\": 60,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 2,\n    \"ShortSummary\": \"Leaking Water Filter Bottle Issue\",\n    \"LongSummary\": \"Customer Ainsley Chan is frustrated with leaking PureFlow Water Filter Bottle from H2OZone, seeking assistance before hiking trip or refund.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 5,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027m so frustrated with the PureFlow Water Filter Bottle from H2OZone! I bought it for my hiking trip and it\\u0027s leaking everywhere. I made sure the cap was on tight and the seal was in place, but it still leaks. This is not what I expected from a leak-proof bottle. I need help with this before my trip, or else I want a refund.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 11,\n    \"ProductId\": 89,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 13,\n    \"ShortSummary\": \"Info on assembly process and non-stick surface requested\",\n    \"LongSummary\": \"Customer from Mountain Gear Retailers asked for assembly process and non-stick surface info. Assistant provided details. Ticket is awaiting next action.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 35,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, my name is Evelyn and I\\u0027m from Mountain Gear Retailers. We\\u0027ve had a few customers asking about the Titanium Backpacking Cookware Set and I realize I might have been misinforming them. Could you please provide some additional information on the assembly process and the non-stick surface? I want to make sure I\\u0027m giving our customers the most accurate details. Thank you for your help!\"\n      },\n      {\n        \"MessageId\": 36,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hi Evelyn, thanks for reaching out. The Titanium Backpacking Cookware Set is designed to be ultra-light and compact, making it the perfect companion for any adventure. Whether you\\u0027re backpacking through the mountains or camping by the lake, our non-stick cookware set will help you cook gourmet meals with ease. As for the assembly process, before placing the pot on the heat source, ensure the area is clean and level. Place the pot on the stove or heat source. Regarding the non-stick surface, our cookware set is designed to provide a non-stick cooking experience, making it easier to cook and clean. If you have any other questions, feel free to ask. Thank you!\"\n      },\n      {\n        \"MessageId\": 37,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information! I\\u0027ll make sure to pass along these details to our customers. I appreciate your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 12,\n    \"ProductId\": 173,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 23,\n    \"ShortSummary\": \"Inquiry about battery life for heating feature\",\n    \"LongSummary\": \"Customer loves TechShell Smart Jacket, asks about battery life for heating feature. Pending question about battery life. Next agent should provide specific battery life info.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 63,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! I just got my hands on the TechShell Smart Jacket from Eco Vest and I am absolutely loving it! The built-in heating technology is a game-changer for me during the chilly winter days. I do have a quick question though - how long does the battery typically last when using the heating feature? I want to make sure I\\u0027m prepared for those extra cold days. Thanks so much for your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 13,\n    \"ProductId\": 172,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 33,\n    \"ShortSummary\": \"Trailblazer Carbon Trekking Poles Inspection Arranged\",\n    \"LongSummary\": \"Customer Samantha Miller frustrated with Trailblazer Carbon Trekking Poles, arranged inspection for repair/replacement. Pending update on resolution.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 95,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am beyond frustrated with these Trailblazer Carbon Trekking Poles from Summit Pole. They are supposed to provide stability on any terrain, but they just don\\u0027t work at all! I can\\u0027t believe I spent my hard-earned money on poles that are completely useless. I need help with this problem right away. If I don\\u0027t get a satisfactory resolution, I\\u0027ll be asking for a refund or replacement. This is unacceptable.\"\n      },\n      {\n        \"MessageId\": 96,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We are deeply sorry to hear about the issues you\\u0027re experiencing with the Trailblazer Carbon Trekking Poles. According to the manual, if your poles fail due to a manufacturing defect, we will repair or replace them at no cost to you. We urge you to contact our customer support team immediately to arrange for inspection, repair, or replacement as necessary. You can reach us at [customer support contact detail].\"\n      },\n      {\n        \"MessageId\": 97,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I contacted the customer support team and they were able to arrange for inspection of my Trailblazer Carbon Trekking Poles. I\\u0027m waiting to hear back about whether they can be repaired or replaced. This had better be sorted out quickly!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 14,\n    \"ProductId\": 157,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 43,\n    \"ShortSummary\": \"Inquiry about Waterproof Capability for 360X Action Camera\",\n    \"LongSummary\": \"Customer Aria Thompson inquires about the waterproof capability of the 360X Action Camera for extreme water conditions. Request for quick response and resolution to consider purchase. Non-negotiable refund or replacement threat.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 127,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I need to know if the 360X Action Camera is truly waterproof as advertised. I expect it to withstand extreme water conditions without any issues. I demand a quick and satisfactory response as I am considering purchasing this product for my upcoming water sports adventure. If it does not meet my expectations, I will be seeking a refund or replacement. This is non-negotiable.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 15,\n    \"ProductId\": 58,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 54,\n    \"ShortSummary\": \"Inquiry about SafeTrail GPS Locator SOS button functionality\",\n    \"LongSummary\": \"Customer is interested in the SafeTrail GPS Locator and wants to know if the SOS button really works, if it can be tested before purchase, and if emergency contacts will receive location. Assistant provided details on how the SOS button works and how it alerts emergency contacts.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 155,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, I\\u0027m interested in the SafeTrail GPS Locator from GuardianGear. Does the SOS button really work? Like, can I test it out before I buy it? And if I use it for real, will my emergency contacts get my location? Thx!\"\n      },\n      {\n        \"MessageId\": 156,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The SOS button on the SafeTrail GPS Locator can be activated by pressing and holding it for 3 seconds. When activated, it sends an alert to your designated emergency contacts and provides them with your current GPS location. According to the manual, there are procedures for cancelling the SOS signal as well.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 16,\n    \"ProductId\": 100,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 64,\n    \"ShortSummary\": \"Adjustable Compression Straps Inquiry\",\n    \"LongSummary\": \"Customer purchased Ridge Runner Hydration Pack and is looking for guidance on locating and using adjustable compression straps for securing extra gear. Pending question: assistance on locating and using these straps.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 181,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Ridge Runner Hydration Pack and I\\u0027m really impressed with its features and quality. However, I noticed that the manual mentioned adjustable compression straps for securing extra gear, but I can\\u0027t seem to find them on my pack. Could you please provide some guidance on locating and using these straps? Thank you for your assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 17,\n    \"ProductId\": 200,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 72,\n    \"ShortSummary\": \"Customer seeks real-world testing results for Raptor Tactical Backpack\",\n    \"LongSummary\": \"Customer is frustrated with Raptor Tactical Backpack durability and performance claims. Requesting real-world testing results. Pending request for user experiences in tough conditions.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 206,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am so frustrated with the Raptor Tactical Backpack! I need to know if it can actually handle heavy loads and repel water like it claims. I don\\u0027t want to spend my hard-earned money on a backpack that\\u0027s going to fall apart on me. Can someone please give me some real information about this product\\u0027s durability and performance? I need to know if it\\u0027s actually suitable for tough missions before I make a purchase decision.\"\n      },\n      {\n        \"MessageId\": 207,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Raptor Tactical Backpack is designed to accommodate a hydration bladder, providing users with convenient access to water during extended missions. The backpack features a dedicated hydration bladder compartment with a reinforced port for the hydration tube, allowing for seamless integration of hydration systems. In addition, the backpack is engineered to meet stringent industry standards for durability and performance, making it the go-to choice for professionals who require reliable and versatile gear in the field.\"\n      },\n      {\n        \"MessageId\": 208,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I appreciate the information, but I need some real-world testing results. I need to hear from someone who has actually used this backpack in tough conditions. I can\\u0027t just take your word for it.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 18,\n    \"ProductId\": 106,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 8,\n    \"ShortSummary\": \"Unsatisfactory warmth in extreme conditions\",\n    \"LongSummary\": \"Customer purchased ArcticZone 500 sleeping bag, unhappy with warmth in extreme conditions, requested warranty solution or replacement from Sleepranger customer support. Pending response from support agent regarding warranty coverage and potential replacement options.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 249,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I purchased the ArcticZone 500 sleeping bag and I\\u0027m extremely disappointed with the level of sleep comfort. I followed all the troubleshooting steps, but it\\u0027s still not providing the warmth I expected in extreme conditions. The manual claims it\\u0027s designed for extreme conditions, but it\\u0027s not living up to that. This is unacceptable and I expect a solution to this problem.\"\n      },\n      {\n        \"MessageId\": 250,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the user manual, the ArcticZone 500 sleeping bag from Sleepranger is specifically engineered for use in extremely cold environments, making it the ideal choice for arctic expeditions, winter camping, and high-altitude mountaineering. It features advanced insulation, a water-resistant shell, and a temperature rating for extreme conditions. Additionally, the sleeping bag comes with a limited warranty that covers manufacturing defects for a period of 1 year from the date of purchase. This warranty applies only to the original purchaser and is non-transferable. I recommend contacting Sleepranger customer support for assistance with the warranty and product performance.\"\n      },\n      {\n        \"MessageId\": 251,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I already followed all the troubleshooting steps and the sleeping bag is still not providing the warmth I expected in extreme conditions. The warranty should cover this issue, so I expect Sleepranger to provide a solution or a replacement.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 19,\n    \"ProductId\": 109,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 91,\n    \"ShortSummary\": \"XtremeGear 5000 Helmet Camera Slow Motion Inquiry\",\n    \"LongSummary\": \"Customer inquires about slow motion recording with the XtremeGear 5000 helmet camera. Assistant explains app adjustments for better recording experience. Pending response on slow motion recording capabilities.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 282,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, can the helmet camera in the XtremeGear 5000 kit record in slow motion? Thx\"\n      },\n      {\n        \"MessageId\": 283,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The XtremeGear 5000 Mountain Biking Kit includes a high-definition helmet camera for capturing your biking adventures. Here\\u0027s how to adjust it for the best recording experience: Use the app to fine-tune the camera angle, ensuring it captures the desired field of view while riding.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 20,\n    \"ProductId\": 137,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 101,\n    \"ShortSummary\": \"Outdoor DJing with WildBeat Pro Controller\",\n    \"LongSummary\": \"Customer seeking help with utilizing advanced mixing capabilities for outdoor DJing. Assistant provided details on the product\\u0027s rugged and waterproof construction, ideal for wilderness environments. Pending question about specific setup and advanced mixing capabilities.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 313,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! So, I recently got my hands on the WildBeat Pro DJ Controller and I\\u0027m loving it! But I\\u0027m having a bit of trouble making it work in a specific way. I\\u0027m trying to use the advanced mixing capabilities for a big outdoor party, but I\\u0027m running into some issues. Could you help me figure out how to make it work like a charm for my upcoming wilderness shindig? Thanks a bunch!\"\n      },\n      {\n        \"MessageId\": 314,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The WildBeat Pro DJ Controller by PeakMix is specifically designed for outdoor DJing in wilderness environments, with its rugged and waterproof construction. It\\u0027s ideal for your upcoming wilderness shindig and is resistant to UV radiation, ensuring durability and longevity in direct sunlight exposure. For more details on setup and advanced mixing capabilities, please refer to the product manual.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 21,\n    \"ProductId\": 110,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 112,\n    \"ShortSummary\": \"Warranty claim for damaged energy bars\",\n    \"LongSummary\": \"Accidental damage to PowerFuel Energy Bars, seeking warranty coverage. Specific assistance needed.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 343,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the PowerFuel Energy Bars from EcoFuels and I was really looking forward to using them on my hiking trip. However, when I unwrapped the packaging, I accidentally broke one of the bars. I didn\\u0027t expect them to be so delicate! I really hope there\\u0027s a way to fix this because I was relying on these bars for my energy during the trip. Can you please help me with this? I would really appreciate it. Thank you so much.\"\n      },\n      {\n        \"MessageId\": 344,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We\\u0027re sorry to hear about the issue with the PowerFuel Energy Bars. According to the product manual, each purchase of PowerFuel Energy Bars is backed by EcoFuels\\u0027 limited product warranty. If you believe your product is defective or not performing as expected, please reach out to our Customer Support team for further assistance. You can find the contact details in the user manual. Unfortunately, accidental damage is not covered under the warranty. We encourage you to reach out to our support team for further assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 22,\n    \"ProductId\": 90,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 8,\n    \"ShortSummary\": \"Non-functional PurifyPro Water Filter Pump\",\n    \"LongSummary\": \"Customer needs help with non-functional PurifyPro Water Filter Pump, despite following priming instructions. Asks for next steps. Advised to consult user manual for component inspection checklist.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 366,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi, my PurifyPro Water Filter Pump isn\\u0027t working. Can you help?\"\n      },\n      {\n        \"MessageId\": 367,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The PurifyPro Water Filter Pump is designed for outdoor recreational use and is engineered to remove 99.9999% of waterborne bacteria, ensuring a safe and reliable source of drinking water during camping, hiking, or other outdoor activities. You need to prime the pump by pumping the handle several times until water flows through the system. Once primed, it is ready for use in purifying water for consumption.\"\n      },\n      {\n        \"MessageId\": 368,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I tried priming the pump by pumping the handle several times, but it still isn\\u0027t working. What should I do next?\"\n      },\n      {\n        \"MessageId\": 369,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"It seems that the PurifyPro Water Filter Pump requires a thorough inspection of all components before use. According to the manual, the user must ensure that all components are intact, undamaged, and free from any defects. I recommend referring to the AquaFusion PurifyPro Water Filter Pump User Manual (Code: AF-PPWFP-UM-001) for a complete list of components and an inspection checklist.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 23,\n    \"ProductId\": 54,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 131,\n    \"ShortSummary\": \"Difficulty accessing safety gear in backpack\",\n    \"LongSummary\": \"Customer frustrated with accessing safety gear in AvalanchePro Ski Backpack. Assistant provides instructions and return/repair options. Customer demands refund due to design flaw.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 394,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027m really frustrated with the AvalanchePro Ski Backpack from PowderPeak. The manual says it\\u0027s designed to keep my avalanche safety gear easily accessible, but I can\\u0027t seem to get the probe and shovel out when I need them. This is a major flaw in the design of the product and I expect a solution or a refund. I shouldn\\u0027t have to struggle with my safety gear in an emergency situation. This backpack is supposed to be ergonomic and efficient, but I\\u0027m not seeing it. Please provide me with a logical explanation for this design flaw.\"\n      },\n      {\n        \"MessageId\": 395,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The AvalanchePro Ski Backpack is designed to efficiently deploy the shovel and probe in emergency situations. To deploy the shovel, remove it from the designated compartment and assemble the handle and blade. Additionally, if you encounter any missing or broken parts, please contact PowderPeak customer support for assistance with resolving the issue.\"\n      },\n      {\n        \"MessageId\": 396,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"The instructions for deploying the shovel and probe are not helpful at all. I followed them exactly as stated and still had difficulty accessing my safety gear. I need a better explanation or a refund for this poorly designed product.\"\n      },\n      {\n        \"MessageId\": 397,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, to deploy the shovel, I should remove it from the designated compartment and assemble the handle and blade. For the probe, I should remove it from the designated compartment on the AvalanchePro Ski Backpack. If you continue to experience difficulty, you may contact PowderPeak customer support for further assistance. If you\\u0027d like to initiate a return or repair, please visit https://northernmountains.example.com/support/returns\"\n      },\n      {\n        \"MessageId\": 398,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027ve already tried following the instructions exactly as stated and I still can\\u0027t easily access my safety gear. This is unacceptable and I demand a refund for this poorly designed product.\"\n      },\n      {\n        \"MessageId\": 399,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Based on the manual, to deploy the shovel, you need to remove it from the designated compartment and assemble the handle and blade. For the probe, you simply remove it from the designated compartment on the AvalanchePro Ski Backpack. If you continue to experience difficulty, you may contact PowderPeak customer support for further assistance. If you\\u0027d like to initiate a return or repair, please visit https://northernmountains.example.com/support/returns\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 24,\n    \"ProductId\": 82,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 74,\n    \"ShortSummary\": \"Cleaning instructions for SurvivalPro Emergency Kit\",\n    \"LongSummary\": \"Customer inquired about cleaning instructions for SurvivalPro Emergency Kit. Assistant provided detailed cleaning steps. Customer confirmed kit is now ready. No further action needed.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 425,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, just wondering how often I need to clean my SurvivalPro Emergency Kit. Thanks!\"\n      },\n      {\n        \"MessageId\": 426,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, to keep your SurvivalPro Emergency Kit in top condition, it\\u0027s important to regularly clean and sanitize the contents. Use a damp cloth to wipe down the exterior of the carrying case, and inspect the interior for any dirt or debris. Carefully remove any soiled items and clean them according to their individual instructions.\"\n      },\n      {\n        \"MessageId\": 427,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thx for the info! Got it cleaned up and ready to go.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 25,\n    \"ProductId\": 104,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 150,\n    \"ShortSummary\": \"Ongoing Issue with Water Filter Bottle\",\n    \"LongSummary\": \"Customer reported ongoing issue with Puriflo Water Filter Bottle. Troubleshooting steps provided. Pending question: Has customer tried contacting manufacturer\\u0027s support?\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 458,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Bottle not working. Need help.\"\n      },\n      {\n        \"MessageId\": 459,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Based on the product manual, the Aquaduct Puriflo Water Filter Bottle is designed for outdoor enthusiasts and travelers who need a reliable water filtration solution. It is important to inspect the components of the bottle on a monthly basis to ensure proper functioning. If the issue persists, please feel free to contact the manufacturer\\u0027s support for troubleshooting assistance.\"\n      },\n      {\n        \"MessageId\": 460,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Issue still not resolved. Bottle is still not working.\"\n      },\n      {\n        \"MessageId\": 461,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I understand that the issue with the bottle is still unresolved. Here are a few troubleshooting steps based on the product manual: 1. Inspect the components of the bottle on a monthly basis to ensure proper functioning. 2. Store the Puriflo Water Filter Bottle in a clean and dry environment when not in use. Avoid exposing the product to extreme temperatures or direct sunlight, as this may degrade its performance and structural integrity. If the issue persists, you may consider contacting the manufacturer\\u0027s support for further assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 26,\n    \"ProductId\": 128,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 160,\n    \"ShortSummary\": \"Need detailed technical info on AquaBottle Pro filtration system\",\n    \"LongSummary\": \"Retailer Evelyn Yang seeks detailed technical info on AquaBottle Pro filtration system and replacement intervals, requests escalation or access to comprehensive documentation. Next response should provide detailed specifications or escalate to technical expert.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 479,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Greetings, AquaNest team. As a retailer stocking the AquaBottle Pro, I am seeking detailed technical information regarding the filtration system used in this product. Our customers have expressed interest in the filtration efficiency and the replacement process for the filters. We are committed to providing accurate and in-depth knowledge to our customers, and having a comprehensive understanding of the product components is crucial for us. Can you provide detailed specifications on the filtration technology used in the AquaBottle Pro, as well as the recommended replacement intervals? Thank you for your prompt assistance in this matter.\"\n      },\n      {\n        \"MessageId\": 480,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the AquaBottle Pro user manual, the filtration system and replacement process are not covered. However, the manual does emphasize the importance of inspecting and cleaning the bottle before use. If you have any further questions, feel free to reach out.\"\n      },\n      {\n        \"MessageId\": 481,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for your response. However, the information provided in the user manual is insufficient for our needs. We require detailed specifications on the filtration technology and recommended replacement intervals for the filters used in the AquaBottle Pro. Can you please escalate this request to a technical expert or provide access to more comprehensive product documentation? Thank you.\"\n      },\n      {\n        \"MessageId\": 482,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I apologize for the inconvenience. It seems that the specific technical information on the filtration system and filter replacement intervals for the AquaBottle Pro is not available in the user manual. I will escalate this request to our technical support team for further assistance. Thank you for your patience.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 27,\n    \"ProductId\": 165,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 64,\n    \"ShortSummary\": \"Setting up Rugged Shelter 600\",\n    \"LongSummary\": \"Customer needs guidance setting up Rugged Shelter 600, including using guy lines and rainfly, addressing wear and tear, and warranty coverage. Pending assistance needed.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 505,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear OutdoorHaven team, \\n\\nI recently purchased the Rugged Shelter 600 for my camping trip and I\\u0027m having trouble setting it up. I followed the instructions carefully, but I can\\u0027t seem to get it to work in the way described. Could you please provide me with some guidance or assistance on how to properly set up the shelter? I want to make sure I\\u0027m utilizing all of its features to the fullest. Thank you for your help.\"\n      },\n      {\n        \"MessageId\": 506,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The OutdoorHaven Rugged Shelter 600 is designed for use as a camping shelter in outdoor environments. It provides ample space for sleeping, relaxing, and storing gear, and is meant to withstand various weather conditions. When setting up the shelter, carefully unpack the contents of the box and ensure that all parts and accessories are present and in good condition. Use the included guy lines to further secure the shelter in place during windy conditions, and utilize the rainfly for extra weather protection. If you encounter any signs of wear and tear, address them promptly. Additionally, the shelter comes with a limited warranty from OutdoorHaven, so please refer to the warranty information for coverage and claims. If you have any further questions or need assistance, feel free to contact us. Thank you.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 28,\n    \"ProductId\": 17,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 177,\n    \"ShortSummary\": \"RidgeRunner Jacket Waterproof Issue\",\n    \"LongSummary\": \"Customer reported issues with weatherproof jacket not keeping them dry in the rain. Was directed to contact customer support for warranty-related inquiries. Customer successfully troubleshooted the issue with customer support.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 529,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the RidgeRunner Weatherproof Jacket and I\\u0027m having some issues with it. It\\u0027s not working as it should and I\\u0027m not sure what to do. Can you please help me with this?\"\n      },\n      {\n        \"MessageId\": 530,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Thank you for reaching out to us. We\\u0027re sorry to hear that you\\u0027re experiencing issues with the RidgeRunner Weatherproof Jacket. To better assist you, could you please provide more details about the specific issues you are encountering? This will help us understand the situation and provide you with the best support.\"\n      },\n      {\n        \"MessageId\": 531,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I tried wearing the jacket in the rain and it didn\\u0027t keep me dry at all. It\\u0027s supposed to be weatherproof but it\\u0027s not doing its job.\"\n      },\n      {\n        \"MessageId\": 532,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"TechShield RidgeRunner Weatherproof Jacket is covered by a limited lifetime warranty, which guarantees that it will be free from defects in materials and workmanship under normal use. Please contact our customer support team for assistance regarding the issues you are experiencing with the jacket. You can reach out to our support team for troubleshooting and warranty-related inquiries.\"\n      },\n      {\n        \"MessageId\": 533,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I contacted the customer support team as suggested, and they were able to help me troubleshoot the issue with the jacket. It turns out there was a problem with the seams, but they were able to provide a solution. Thank you for your assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 29,\n    \"ProductId\": 141,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 184,\n    \"ShortSummary\": \"Quality issue, return initiated, compensation expected\",\n    \"LongSummary\": \"Customer is dissatisfied with the quality of the product and has initiated a return for a full refund. They expect compensation for their inconvenience. Next support agent should process the return and address the customer\\u0027s request for compensation.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Returns\",\n    \"Messages\": [\n      {\n        \"MessageId\": 558,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am extremely disappointed with the quality of the SOS Gear Emergency Survival Kit. The multi-tool broke after just one use, and the fire starter doesn\\u0027t work at all. I demand a replacement or a full refund immediately. This is completely unacceptable and I expect better from a brand like SOS Gear.\"\n      },\n      {\n        \"MessageId\": 559,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the multi-tool and fire starter are designed to meet the highest industry standards for durability and functionality. The multi-tool has been rigorously tested and meets the requirements of standard industry specifications. The fire starter conforms to the requirements of industry standard specifications for portable fire starters and has been tested for compliance with fire safety standards for outdoor and camping equipment.\"\n      },\n      {\n        \"MessageId\": 560,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Your explanations about industry standards mean nothing to me. All I know is that the multi-tool broke and the fire starter doesn\\u0027t work. I need a replacement or a full refund immediately. This is unacceptable and I expect a resolution right now.\"\n      },\n      {\n        \"MessageId\": 561,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the multi-tool and fire starter are designed to meet the highest industry standards for durability and functionality. The multi-tool has been rigorously tested and meets the requirements of standard industry specifications for multi-tools (ISO 6789-2:2017) and safety requirements for multi-function hand-held tools (EN 50156-1:2018). The fire starter conforms to the requirements of industry standard specifications for portable fire starters (ISO 11999-1:2015) and has been tested for compliance with fire safety standards for outdoor and camping equipment (EN 1860-1:2003). Unfortunately, the manual does not provide specific information regarding the warranty or return policy. However, I can assist you with initiating a return for a refund or replacement. Please visit [Northern Mountains Support](https://northernmountains.example.com/support/returns) to get started.\"\n      },\n      {\n        \"MessageId\": 562,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I have visited the support page and initiated a return for a full refund. This whole experience has been a complete disappointment and I expect to be compensated for my time and inconvenience.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 30,\n    \"ProductId\": 15,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 169,\n    \"ShortSummary\": \"Furious customer demands replacement for broken power bank\",\n    \"LongSummary\": \"Customer furious about broken AdventurePro 1000 power bank, demands replacement or refund. Feels misled by product\\u0027s durability claims. Urgent response needed to address dissatisfaction.\",\n    \"CustomerSatisfaction\": null,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 600,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am absolutely furious! I just bought the AdventurePro 1000 power bank from AdventureElec and it\\u0027s already broken! I can\\u0027t believe this happened after just a few uses. I expect a product like this to be durable and reliable, but it\\u0027s completely failed me. I demand a replacement or refund immediately. This is unacceptable! The manual claims it\\u0027s rugged and built for outdoor use, but it couldn\\u0027t even survive a simple hike. I am extremely disappointed and want this issue resolved as soon as possible.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 31,\n    \"ProductId\": 83,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 200,\n    \"ShortSummary\": \"Urgent 4K Camera Replacement Request\",\n    \"LongSummary\": \"Customer demands immediate replacement for malfunctioning 4K camera. Expects quick resolution.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 631,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I can\\u0027t believe my SkyRanger HD Aerial Drone isn\\u0027t working properly! I demand a replacement immediately. The 4K camera is malfunctioning and I need it fixed ASAP. I shouldn\\u0027t have to deal with these issues after spending so much on this drone. I expect a quick resolution to this problem.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 32,\n    \"ProductId\": 54,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 208,\n    \"ShortSummary\": \"Compatibility of Hydration Reservoirs\",\n    \"LongSummary\": \"Customer inquires about compatibility of hydration reservoirs with AvalanchePro Ski Backpack. Needs confirmation for backcountry adventure setup.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 666,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the AvalanchePro Ski Backpack from PowderPeak and I\\u0027m really impressed with its features for avalanche safety gear storage. I do have a specific technical question - can you confirm if the backpack is compatible with all brands of hydration reservoirs? I want to make sure I have the right setup for my upcoming backcountry adventure. Thank you for your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 33,\n    \"ProductId\": 132,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 215,\n    \"ShortSummary\": \"Inquiry about casting techniques and bait\",\n    \"LongSummary\": \"Customer inquiring about casting techniques and bait for AnglerPro 5000. Needs detailed info before purchase decision. Pending question about specific bait recommendations.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 694,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027m considering purchasing the AnglerPro 5000 fishing rod, but I need more information about the casting techniques and the right bait to use. Can you provide me with details on how to perform the overhead and sidearm casts with this rod? Additionally, I\\u0027m unsure about the best bait to use for specific fish species and water conditions. It\\u0027s frustrating not having this information readily available before making a purchase decision.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 34,\n    \"ProductId\": 166,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 225,\n    \"ShortSummary\": \"TerrainX 500 ATV off-road capability inquiry\",\n    \"LongSummary\": \"Customer is considering purchasing the TerrainX 500 ATV for off-road adventures. Asking if it can handle steep inclines and rocky terrains. Assistant responded with details about 4WD mode and user manual reference for off-road driving.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 727,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I\\u0027m considering purchasing the TerrainX 500 ATV for some off-road adventures. I\\u0027m curious to know if this ATV can handle steep inclines and rocky terrains without any issues. I plan on using it for exploring rugged and challenging trails, so it\\u0027s important for me to make sure it can handle that kind of terrain. Any information or guidance on this would be really helpful. Thanks!\"\n      },\n      {\n        \"MessageId\": 728,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The TerrainX 500 ATV is designed to handle various terrains with ease, including rocky trails. You can engage the 4WD mode to improve traction and maintain a steady speed to navigate rocky terrains. For more information on off-road driving, refer to section 4.2 of the user manual.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 35,\n    \"ProductId\": 50,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 234,\n    \"ShortSummary\": \"Unsatisfied: No built-in filter\",\n    \"LongSummary\": \"Customer is unsatisfied with lack of built-in filter in product and demands a proper solution. No resolution yet, need to offer alternative filtration options or resolution.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 756,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I can\\u0027t believe this Thirsttrek HydroPack doesn\\u0027t come with a built-in filter! How am I supposed to drink \\u0027clean, drinkable water\\u0027 from a stream or river without getting sick? This is a major oversight and I demand a solution to this problem. I shouldn\\u0027t have to worry about getting sick from using this product as advertised. I need a fix for this ASAP.\"\n      },\n      {\n        \"MessageId\": 757,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Thirsttrek HydroPack Hydration System is a high-capacity hydration system designed to keep you hydrated during long outdoor activities. The system features a 3L water reservoir, allowing for hands-free drinking and easy refill, ensuring long-lasting hydration during your adventures. The user manual provides important information on how to use and maintain the system, as well as instructions on ensuring the drinking valve and hose are free from debris and bacteria. However, it does not mention the inclusion of a built-in filter for water purification. Would you be interested in exploring alternative filtration options for your outdoor activities?\"\n      },\n      {\n        \"MessageId\": 758,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I shouldn\\u0027t have to explore alternative filtration options! The product should have come with a built-in filter as advertised. This is a major inconvenience and I\\u0027m not satisfied with the resolution. I demand a proper solution to this problem.\"\n      },\n      {\n        \"MessageId\": 759,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The user manual does not mention the inclusion of a built-in filter for water purification. However, it provides instructions on how to ensure the drinking valve and hose are free from debris and bacteria. It seems that the product does not come with a built-in filter, and the manual does not mention alternative filtration options.\"\n      },\n      {\n        \"MessageId\": 760,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I shouldn\\u0027t have to follow additional instructions or explore alternative options. The product should have come with a built-in filter as advertised. I\\u0027m not satisfied with the resolution and demand a proper solution to this problem.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 36,\n    \"ProductId\": 145,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 241,\n    \"ShortSummary\": \"Frustrated solar charger not working for camping trip\",\n    \"LongSummary\": \"Customer is frustrated with solar charger not working despite following instructions. Needs help to fix the problem for upcoming camping trip.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 787,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am so frustrated with this PowerBeam Solar Powered Portable Charger! I\\u0027ve been trying to charge my device for hours, and it\\u0027s still not working. I made sure the solar panel is in direct sunlight and checked the USB cable for any damage, but nothing is happening. This is ridiculous! I need this to work for my upcoming camping trip, and now I\\u0027m worried it won\\u0027t. I want to know what the problem is and how to fix it, or else I want a refund!\"\n      },\n      {\n        \"MessageId\": 788,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the PowerBeam Solar Powered Portable Charger user manual, to charge the charger, you need to place the solar panels in direct sunlight and ensure they are facing the sun for optimal charging. Have you tried charging the device again following these steps?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 37,\n    \"ProductId\": 196,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 8,\n    \"ShortSummary\": \"Seeking Simplified GPS Watch\",\n    \"LongSummary\": \"Customer is seeking a more basic version of the TrailMaster GPS Watch and is frustrated with the current features. Needs clarification on whether ExpeditionTech plans to release a simpler model.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Idea\",\n    \"Messages\": [\n      {\n        \"MessageId\": 823,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I can\\u0027t believe the TrailMaster GPS Watch requires all these specialized tools just to troubleshoot! I\\u0027m considering purchasing it for my outdoor adventures, but now I\\u0027m having serious doubts. It should be user-friendly and reliable, not a headache to maintain. Can someone please clarify if I really need all these fancy diagnostic tools to use this watch effectively? If not, I may just have to look for a different option.\"\n      },\n      {\n        \"MessageId\": 824,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The TrailMaster GPS Watch is designed for experienced outdoor enthusiasts, providing essential navigation information and location tracking in remote, off-grid environments. It offers a comprehensive suite of navigation tools, real-time location sharing, and runs on a proprietary operating system optimized for outdoor navigation and tracking.\"\n      },\n      {\n        \"MessageId\": 825,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I don\\u0027t care about all those extra features! I just want a simple, user-friendly GPS watch for my outdoor adventures. I don\\u0027t want to deal with specialized tools and a proprietary operating system. Can\\u0027t ExpeditionTech make a more basic version for people like me?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 38,\n    \"ProductId\": 120,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 257,\n    \"ShortSummary\": \"ArcticPro Jacket Insulation Assistance\",\n    \"LongSummary\": \"Customer seeks assistance for ArcticPro jacket insulation issue. Advised return process.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Returns\",\n    \"Messages\": [\n      {\n        \"MessageId\": 855,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the ArcticPro Insulated Ski Jacket from Frost Flare and was really looking forward to using it on my upcoming ski trip. However, I\\u0027ve noticed that the jacket doesn\\u0027t seem to provide the warmth and insulation as described in the product description. I am quite disappointed and was wondering if you could provide some assistance or advice on how to resolve this issue. I really want to enjoy the slopes without feeling cold, so any help would be greatly appreciated. Thank you for your attention to this matter.\"\n      },\n      {\n        \"MessageId\": 856,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Thank you for reaching out to us. I\\u0027m sorry to hear about the issue you\\u0027re experiencing with the ArcticPro Insulated Ski Jacket. Based on the product manual, the jacket is designed with advanced insulation technology to provide maximum warmth and comfort in cold weather conditions. It is also constructed with FrostShield technology to repel moisture and keep you dry in snowy and wet environments. If you have already performed the recommended preliminary checks and are still not satisfied with the insulation, I recommend initiating a return for a refund within 30 days of purchase. You can start the return process at https://northernmountains.example.com/support/returns. If you have any further questions or need assistance with the return process, please feel free to ask. Your satisfaction is our priority.\"\n      },\n      {\n        \"MessageId\": 857,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for your prompt response. I have performed the recommended preliminary checks and unfortunately, the jacket still does not provide the expected insulation. I will proceed with initiating the return for a refund as suggested. I appreciate your assistance in this matter.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 39,\n    \"ProductId\": 30,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 169,\n    \"ShortSummary\": \"Inquiry about scratch resistance of cookware set\",\n    \"LongSummary\": \"Customer needs detailed info on scratch resistance of cookware set. Immediate response required. Pending question regarding refund or replacement if expectations not met.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 887,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I demand to know if the non-stick coating on the Alpine Chef Camp Cookware Set is truly scratch-resistant as advertised. I expect a prompt and detailed response regarding this specific feature before I consider making a purchase. If this feature does not meet my expectations, I will be seeking a refund or replacement. Your immediate attention to this matter is required.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 40,\n    \"ProductId\": 77,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 272,\n    \"ShortSummary\": \"Charging issue with Solar Charger 3000X via USB\",\n    \"LongSummary\": \"Customer reports frustration with inability to charge Solar Charger 3000X via USB despite following manual. Requests urgent solution. Next agent should provide detailed troubleshooting steps.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 923,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am so frustrated with this Solar Charger 3000X! I can\\u0027t get it to charge via USB no matter what I do. I followed the manual and connected it to a power source, but it\\u0027s just not working. I spent good money on this and now I can\\u0027t even use it properly. I need help with this issue ASAP!\"\n      },\n      {\n        \"MessageId\": 924,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, to charge your Solar Charger 3000X via USB, you need to connect the USB cable to a power source and then connect the other end to the charger\\u0027s USB port. If you encounter any issues, you can contact Ecovolt\\u0027s customer support team at 1-800-ECOVOLT or by email at support@ecovolt.com for further assistance.\"\n      },\n      {\n        \"MessageId\": 925,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I tried connecting the USB cable to a different power source and then to the charger\\u0027s USB port, but it\\u0027s still not working! This is so frustrating, I need a solution for this issue now!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 41,\n    \"ProductId\": 27,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 263,\n    \"ShortSummary\": \"Waterproof/Shockproof Camera Replacement\",\n    \"LongSummary\": \"Customer is frustrated with the waterproof and shockproof features of the AdventurePro DSLR Camera. Initiated return process for replacement and expects it to work as advertised.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Returns\",\n    \"Messages\": [\n      {\n        \"MessageId\": 953,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am so frustrated with the AdventurePro DSLR Camera! I thought it was supposed to be waterproof and shockproof, but it doesn\\u0027t work at all. I took it on a hiking trip and it stopped working after just a little bit of rain. I want a refund or a replacement, this is not acceptable!\"\n      },\n      {\n        \"MessageId\": 954,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the AdventurePro DSLR Camera is designed to be waterproof and shockproof. However, it\\u0027s important to avoid intentional submersion for extended periods and to avoid dropping the camera from excessive heights. After any exposure to water, be sure to thoroughly dry the housing to prevent the growth of mold or mildew. You can rinse the camera in clean water to remove salt, sand, or other debris, but be sure to fully dry it afterward.\"\n      },\n      {\n        \"MessageId\": 955,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I followed the instructions in the manual and thoroughly dried the camera after it got wet, but it still doesn\\u0027t work. This is really frustrating and I need a replacement or a refund as soon as possible!\"\n      },\n      {\n        \"MessageId\": 956,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I understand your frustration. Since the product is designed to be waterproof and shockproof, it\\u0027s important to ensure that it was not intentionally submerged for extended periods or dropped from excessive heights. If you\\u0027ve followed the care instructions and the camera still doesn\\u0027t work, please initiate a return for a replacement or refund. You can do so at https://northernmountains.example.com/support/returns. Thank you for your understanding.\"\n      },\n      {\n        \"MessageId\": 957,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I initiated the return process for a replacement, but I am still extremely frustrated with the quality of this camera. I expect the replacement to work as advertised, otherwise I will be demanding a full refund.\"\n      },\n      {\n        \"MessageId\": 958,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I apologize for the inconvenience you\\u0027ve experienced. I understand that the replacement process can be frustrating, and I assure you that we are committed to resolving this issue for you. Please allow us to expedite the replacement process for you, and we will ensure that the replacement camera works as expected. Thank you for your patience and understanding.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 42,\n    \"ProductId\": 200,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 81,\n    \"ShortSummary\": \"Seeking guidance for hiking trip with Raptor Tactical Backpack\",\n    \"LongSummary\": \"Customer is seeking guidance on adjusting and wearing Raptor Tactical Backpack for a hiking trip. They have followed the manual\\u0027s guidelines and are satisfied with the comfort and balance. Next support agent should ensure customer has all necessary information for their trip.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 988,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Raptor Tactical Backpack and I\\u0027m considering using it for a hiking trip with extremely long distances. I believe the backpack\\u0027s durability and load-bearing capabilities make it suitable for such use. Can you provide me with some additional guidance on how to properly adjust and wear the backpack for this purpose? Your assistance would be greatly appreciated. Thank you.\"\n      },\n      {\n        \"MessageId\": 989,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Raptor Tactical Backpack is designed for durability and demanding environments, and it\\u0027s crucial to properly adjust the shoulder straps for comfort and balance. Follow the guidelines provided in the manual for optimal wear and adjustment. You can count on its load-bearing capabilities for your hiking trip.\"\n      },\n      {\n        \"MessageId\": 990,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the guidance on adjusting and wearing the Raptor Tactical Backpack. I have followed the manual\\u0027s guidelines and the backpack feels comfortable and well-balanced. I appreciate your assistance. Thank you.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 43,\n    \"ProductId\": 18,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 294,\n    \"ShortSummary\": \"Hydration system setup for Trailblazer 40L Backpack\",\n    \"LongSummary\": \"Customer seeks detailed instructions on setting up hydration system in Trailblazer 40L Backpack. Assistance provided, customer successfully set up system. Ticket closed.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1013,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Trailblazer 40L Backpack from Hiker\\u0027s Haven and I\\u0027m having some difficulty understanding how to properly utilize the hydration system. The manual mentions a dedicated compartment for the hydration reservoir and a drink tube port, but I\\u0027m unsure of the specific steps to set it up. Can you provide detailed instructions on how to insert the hydration reservoir and route the drink tube? I want to ensure that I am utilizing this feature to its full potential for my upcoming hiking trip. Any assistance would be greatly appreciated. Thank you.\"\n      },\n      {\n        \"MessageId\": 1014,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Trailblazer 40L Backpack is designed to be hydration system compatible. To use the hydration system, insert the hydration reservoir into the designated compartment inside the main compartment of the backpack. Then, route the hose through the opening at the top of the backpack and secure it using the hose clip located on the shoulder strap. If you have any further questions or need assistance, please feel free to ask.\"\n      },\n      {\n        \"MessageId\": 1015,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the instructions. I have successfully inserted the hydration reservoir and routed the drink tube as per your guidance. The system seems to be working well and I feel confident in utilizing it for my hiking trip. I appreciate your assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 44,\n    \"ProductId\": 152,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 303,\n    \"ShortSummary\": \"Difficulty getting beacon light to flash\",\n    \"LongSummary\": \"Customer having trouble getting Emergency Beacon Light to flash, tried mode button. Assistant suggests replacing batteries, contacting Sure Survive for further assistance.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1044,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear Customer Support, I recently purchased the Sure Survive Emergency Beacon Light and I\\u0027m having trouble getting it to flash. I\\u0027ve tried pressing the mode button as mentioned in the manual, but it still isn\\u0027t working. Can you provide some guidance on how to resolve this issue? Thank you.\"\n      },\n      {\n        \"MessageId\": 1045,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Dear customer, based on the manual and troubleshooting information, it seems that irregular flashing may be due to low battery power. Please replace the batteries with new ones and ensure they are fully charged. If the issue persists after replacing the batteries, please contact Sure Survive\\u0027s customer support team for further assistance at Phone: 1-800-SURVIVE or Email: support@suresurvive.com.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 45,\n    \"ProductId\": 89,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 169,\n    \"ShortSummary\": \"Demanding Replacement for Broken Cookware Set\",\n    \"LongSummary\": \"Customer demanding replacement for broken cookware set. Assistant advised proper use and maintenance. Further assistance may be needed.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1073,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I can\\u0027t believe the Titanium Backpacking Cookware Set I bought from you has already broken! This is completely unacceptable. I demand a replacement immediately. I spent good money on this cookware set and I expect it to be durable and reliable. I shouldn\\u0027t have to deal with this kind of issue so soon after purchasing. I expect a prompt response and resolution to this matter!\"\n      },\n      {\n        \"MessageId\": 1074,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We apologize for the inconvenience. According to the product manual, the cookware set is designed for backcountry cooking and should be properly positioned over the heat source at an appropriate level. If you continue to experience issues, please contact Backcountry Cook customer service for further assistance. Additionally, please ensure to check for signs of damage or wear and tear before each use, and refrain from using the cookware if any damage is noticed. Thank you for your understanding.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 46,\n    \"ProductId\": 195,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 319,\n    \"ShortSummary\": \"Hydration setup and weight distribution inquiry\",\n    \"LongSummary\": \"Customer seeks guidance on weight distribution and setup of hydration system for Trekker 30L Backpack. Specific info requested for product performance. Pending response from agent on detailed instructions.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1109,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I recently purchased the Adventure Pack Trekker 30L Backpack and I am concerned about the weight distribution and proper setup of the hydration system. I want to ensure that the product is performing as expected and that I am utilizing it to its full potential. Can you provide guidance on the proper weight distribution and setup of the hydration system as mentioned in the product description? I am confident in my technical knowledge and would appreciate detailed and specific information to address my concerns. Thank you.\"\n      },\n      {\n        \"MessageId\": 1110,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hello! When setting up the hydration system for your Trekker 30L Backpack, make sure your water reservoir is securely placed in the designated compartment and the drinking tube is easily accessible for on-the-go hydration. I hope this helps!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 47,\n    \"ProductId\": 47,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 328,\n    \"ShortSummary\": \"Inquiry about bulk orders and allergen content\",\n    \"LongSummary\": \"Customer inquired about bulk orders and allergen content of bars. Requested prompt response. Allergen info provided, inventory updated. Business relations solidified. No further action needed.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1142,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Greetings, esteemed retailer. As a fellow connoisseur of adventure nutrition, I have extensive knowledge of the Nutritech Protein Plus Energy Bars, Variety Pack. The high-protein content and assortment of flavors make it a top choice for outdoor enthusiasts seeking sustained energy. I am inquiring about the availability of bulk orders for this product as I aim to expand my inventory and meet the growing demand from my discerning customers. Additionally, I would appreciate detailed information regarding the allergen content of each flavor, as my customer base values transparency and safety. Your prompt and thorough response will solidify our future business relations. I eagerly anticipate your expert assistance in this matter.\"\n      },\n      {\n        \"MessageId\": 1143,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Esteemed customer, \\n\\nPlease note that some flavors of the Nutritech Protein Plus Energy Bars, Variety Pack contain nuts and dairy products. We advise checking the individual packaging for specific allergen information before consuming the bars. If you require any further details, feel free to contact us.\"\n      },\n      {\n        \"MessageId\": 1144,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the allergen information provided. I have checked the individual packaging for specific allergen information and have updated my inventory accordingly. As a result, I have been able to meet the growing demand from my discerning customers. Our business relations have been solidified and I appreciate your prompt and thorough response.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 48,\n    \"ProductId\": 96,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 335,\n    \"ShortSummary\": \"Customer Skeptical About Lantern Performance\",\n    \"LongSummary\": \"Customer seeking reassurance about Solaris 5000\\u0027s performance and requesting real-world usage scenarios or testimonials. Assistant provided information about the lantern\\u0027s features and charging process but couldn\\u0027t find specific testimonials or usage scenarios. Customer\\u0027s skepticism remains unresolved.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1170,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027m considering buying the Solaris 5000, but I\\u0027m skeptical about the so-called \\u0027advanced LED technology\\u0027 and \\u0027solar-powered\\u0027 claims. How can I be sure it will actually work as advertised? I don\\u0027t want to end up with a dim, flickering light source that doesn\\u0027t hold its charge! Can you provide any real-world usage scenarios or testimonials to prove its effectiveness?\"\n      },\n      {\n        \"MessageId\": 1171,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Solaris 5000 is a high-tech outdoor lantern designed to provide efficient and reliable lighting during outdoor activities. It features advanced LED technology, a solar-powered battery, and a lightweight, portable design, making it the perfect companion for camping, hiking, and other outdoor adventures. The manual also provides instructions on how to charge the lantern by placing it in direct sunlight with the solar panel facing up. Unfortunately, I couldn\\u0027t find specific testimonials or real-world usage scenarios. If you have any other questions, feel free to ask.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 49,\n    \"ProductId\": 88,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 8,\n    \"ShortSummary\": \"Urgent assistance needed for RapidFlow Kayak Paddle issue\",\n    \"LongSummary\": \"Customer demands immediate assistance with RapidFlow Kayak Paddle. Wants solution or replacement. Concerns about product not working as described and dissatisfaction with inconvenience. Assistant advises against troubleshooting and explains limited warranty coverage.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1202,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I demand immediate assistance with my RapidFlow Kayak Paddle! It\\u0027s not working as described and I expect a solution right away. I shouldn\\u0027t have to deal with this kind of inconvenience after spending my hard-earned money on a high-quality product like this. I need someone to fix this problem or provide me with a replacement paddle!\"\n      },\n      {\n        \"MessageId\": 1203,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, under no circumstances should you attempt to troubleshoot any issues with the WaterWay RapidFlow Kayak Paddle, as doing so may result in injury or death. If you encounter any problems with the paddle, please immediately discontinue use and contact the manufacturer for further instructions. As for warranty, the RapidFlow Kayak Paddle is covered by a limited warranty that protects against defects in materials and workmanship. This warranty does not cover damage caused by misuse, negligence, or normal wear and tear. WaterWay reserves the right to determine whether damage is covered under warranty.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 50,\n    \"ProductId\": 191,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 8,\n    \"ShortSummary\": \"Suitability for Damp Conditions Inquiry\",\n    \"LongSummary\": \"Customer inquires about suitability of Luminex 5000 Lantern for use in damp conditions during camping trip. Needs advice on this specific concern.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1250,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I am considering purchasing the Luminex 5000 Lantern for my upcoming camping trip. I noticed in the product description that it has multiple brightness settings, which is great for different scenarios. However, I\\u0027m wondering if it\\u0027s suitable for use in damp conditions, as I may encounter some rain during my trip. Can you please advise on this? Thank you.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 51,\n    \"ProductId\": 22,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 291,\n    \"ShortSummary\": \"Difficulty with gear fitting and weight distribution\",\n    \"LongSummary\": \"Customer is having trouble fitting all items inside the backpack and experiencing off weight distribution despite following instructions. Requires further assistance with organizing the gear and maintaining comfortable weight distribution.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1252,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Summit 45L Technical Backpack by Peakpacker and I am having trouble with its functionality. Despite following the instructions for filling the compartments, I am unable to fit all my gear inside and the weight distribution seems off. I was hoping to get some assistance with how to properly utilize the compartments and ensure that the backpack works as advertised. Any help or guidance would be greatly appreciated. Thank you.\"\n      },\n      {\n        \"MessageId\": 1253,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hello, thank you for reaching out. According to the user manual, before filling your Peakpacker Summit 45L Technical Backpack with outdoor gear, it is important to ensure that the backpack is properly set up for your adventure. This includes adjusting all straps to fit your body comfortably. The main compartment is designed to accommodate larger gear items, and the backpack has multiple pockets for organization and accessibility.\"\n      },\n      {\n        \"MessageId\": 1254,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information. I have adjusted all the straps and tried to organize my gear in the compartments as per the user manual, but I am still having trouble fitting all my items inside and the weight distribution still feels off. Is there anything else I should try?\"\n      },\n      {\n        \"MessageId\": 1255,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Thank you for adjusting the straps and organizing your gear as per the user manual. If you\\u0027re still having trouble fitting all your items inside or with weight distribution, it may be helpful to reconsider the arrangement of your gear in the multiple pockets for better organization. Additionally, ensure that the backpack is properly set up for your adventure to maintain comfortable weight distribution. For further assistance, please refer to the user manual section on \\u0027Using the Pockets\\u0027 and \\u0027Maintenance of the Backpack\\u0027.\"\n      },\n      {\n        \"MessageId\": 1256,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for your assistance. I have reconsidered the arrangement of my gear in the multiple pockets and made sure the backpack is properly set up for my adventure. Unfortunately, I am still experiencing difficulty fitting all my items inside and the weight distribution is still not ideal. I will review the user manual sections on \\u0027Using the Pockets\\u0027 and \\u0027Maintenance of the Backpack\\u0027 as suggested, but I may need further assistance. Thank you.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 52,\n    \"ProductId\": 154,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 30,\n    \"ShortSummary\": \"Utilizing live tracking for pet safety during outdoor adventures\",\n    \"LongSummary\": \"Customer inquires about utilizing live tracking feature to monitor pet during outdoor adventures. Seeks tips and guidance for this purpose.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1257,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear GuardianGear Support Team, I recently purchased the GPS Personal Locator for outdoor safety and I must say, I am thoroughly impressed with its features. I have a unique idea to use it as a way to track my pet during our outdoor adventures. I believe it will work wonders in keeping my furry friend safe. Could you please provide me with any additional tips or guidance on how to best utilize the live tracking feature for this purpose? Your assistance would be greatly appreciated. Thank you, Eleanor Park\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 53,\n    \"ProductId\": 120,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 127,\n    \"ShortSummary\": \"Product Versatility Inquiry\",\n    \"LongSummary\": \"Customer is considering purchasing ArcticPro Insulated Ski Jacket, but has reservations about its versatility for other winter activities like hiking or snowshoeing. Requests more information on the jacket\\u0027s versatility. Pending response needed on the versatility of the jacket for non-snowsports activities.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1258,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027m considering purchasing the ArcticPro Insulated Ski Jacket, but I have some reservations. Your manual mentions that the jacket is specifically designed for snowsports activities like skiing and snowboarding. However, I\\u0027m wondering if it would be suitable for other winter activities like hiking or snowshoeing. It seems limiting to only promote it for snowsports when it could potentially be useful for other outdoor activities in cold weather. Can you provide more information on the versatility of this jacket?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 54,\n    \"ProductId\": 60,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 74,\n    \"ShortSummary\": \"Demand for Warranty Registration Help\",\n    \"LongSummary\": \"Customer demands clear instructions on registering for warranty extension. Threatens refund. Next support agent should provide step-by-step guidance for registration.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1259,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I just bought the PureFlow Water Filter Bottle and I can\\u0027t figure out how to register for the warranty extension. This is ridiculous, I shouldn\\u0027t have to jump through hoops to get the full benefit of the product I paid for. I demand clear instructions and assistance in getting this sorted out. If I don\\u0027t hear back soon, I\\u0027ll be asking for a refund!\"\n      },\n      {\n        \"MessageId\": 1260,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"To register for the warranty extension, please visit our website within 30 days of purchase. Registered products are also eligible for exclusive offers and promotions. If you require further assistance, please contact H2OZone customer support.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 55,\n    \"ProductId\": 189,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 352,\n    \"ShortSummary\": \"Demand for immediate action, unresolved contact with support\",\n    \"LongSummary\": \"Customer demands immediate action for a replacement, multiple unsuccessful attempts to contact support. Recommend prompt response and resolution from support team.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1261,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I purchased the Survivor Kit 2000 and it doesn\\u0027t work at all! I demand a replacement immediately. This is unacceptable and I expect better quality from Rescue Mate. I shouldn\\u0027t have to deal with faulty gear in an emergency situation.\"\n      },\n      {\n        \"MessageId\": 1262,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We are confident in the quality and durability of the Rescue Mate Survivor Kit 2000 and offer a limited warranty to cover manufacturing defects. This warranty covers the first 12 months from the date of purchase and is only applicable to the original purchaser with a valid proof of purchase. Returns for defective products may be initiated within 1 year of purchase for a refund. For any additional questions regarding the warranty for your Survivor Kit 2000, please contact Rescue Mate at [company contact information].\"\n      },\n      {\n        \"MessageId\": 1263,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I don\\u0027t care about your limited warranty! I expect the products I purchase to work as advertised. I demand a replacement immediately and better quality control from Rescue Mate. This is completely unacceptable and I will not accept anything less than a functional Survivor Kit 2000.\"\n      },\n      {\n        \"MessageId\": 1264,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Based on the user manual, the Rescue Mate Survivor Kit 2000 comes with a limited warranty that covers manufacturing defects for the first 12 months from the date of purchase. Returns for defective products may be initiated within 1 year of purchase for a refund. For any additional questions regarding the warranty, please contact Rescue Mate at the provided company contact information.\\n\\nIn addition, the user manual emphasizes the importance of familiarizing yourself with the contents of the first aid kit and using it effectively in emergency situations. Regarding quality control, the manual does not specifically mention quality control procedures or protocols.\"\n      },\n      {\n        \"MessageId\": 1265,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I don\\u0027t care about the limited warranty or the user manual! I demand a functional replacement for my Survivor Kit 2000 immediately. I expect better quality control from Rescue Mate and will not accept anything less than a fully functional product.\"\n      },\n      {\n        \"MessageId\": 1266,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Based on the information provided in the user manual, the Survivor Kit 2000 comes with a limited warranty that covers manufacturing defects for the first 12 months from the date of purchase. Returns for defective products may be initiated within 1 year of purchase for a refund. For any additional questions regarding the warranty, please contact Rescue Mate at the provided company contact information. With regard to your request for a functional replacement, I recommend reaching out to Rescue Mate\\u0027s support team directly for further assistance.\"\n      },\n      {\n        \"MessageId\": 1267,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I have already reached out to Rescue Mate\\u0027s support team and I am still awaiting a response. This is completely unacceptable and I demand immediate action to resolve this issue.\"\n      },\n      {\n        \"MessageId\": 1268,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I understand your frustration and the urgency of this matter. Based on the user manual, the warranty covers returns for defective products within the first 12 months of purchase. It states, \\u0022Once your warranty claim is received, our customer service team will guide you through the necessary steps to assess the issue and determine the best course of action. Depending on the nature of the issue, we may provide replacement parts or request the return of the product for further inspection.\\u0022 I recommend contacting Rescue Mate\\u0027s support team again and emphasizing the time-sensitive nature of your request. If you need further assistance with initiating a return, you can visit the following link: https://northernmountains.example.com/support/returns\"\n      },\n      {\n        \"MessageId\": 1269,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I have already contacted Rescue Mate\\u0027s support team again and emphasized the urgency of my request. I am still awaiting a response and this is completely unacceptable. I demand immediate action to resolve this issue.\"\n      },\n      {\n        \"MessageId\": 1270,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, \\u0027Once your warranty claim is received, our customer service team will guide you through the necessary steps to assess the issue and determine the best course of action. Depending on the nature of the issue, we may provide replacement parts or request the return of the product for further inspection.\\u0027 If you have already contacted Rescue Mate\\u0027s support team and are still awaiting a response, I recommend reaching out to them again and emphasizing the time-sensitive nature of your request. If you need further assistance with initiating a return, you can visit the following link: https://northernmountains.example.com/support/returns\"\n      },\n      {\n        \"MessageId\": 1271,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I have reached out to Rescue Mate\\u0027s support team multiple times and I am still awaiting a response. This is completely unacceptable and I demand immediate action to resolve this issue.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 56,\n    \"ProductId\": 127,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 353,\n    \"ShortSummary\": \"Leaking HydraPack 2.0\",\n    \"LongSummary\": \"Customer demands replacement or refund for leaking HydraPack 2.0\",\n    \"CustomerSatisfaction\": null,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1272,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I demand to know why my HydraPack 2.0 is leaking! I paid good money for a so-called \\u0027leak-proof\\u0027 system, and now I\\u0027m not getting what I paid for. I expect a replacement immediately or a full refund. This is unacceptable and I will not stand for it!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 57,\n    \"ProductId\": 116,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 354,\n    \"ShortSummary\": \"Inquiring about Material Durability and Warranty Details\",\n    \"LongSummary\": \"Customer inquiring about material durability and warranty details. Pending question about specific material testing. Requesting more information on warranty coverage and claims process.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1273,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I am Jasper Reynolds from Adventure Gear Emporium. We are interested in stocking the Ultratent UltraLite 2-Person Backpacking Tent in our store and have a few questions. Firstly, can you confirm that the tent poles are indeed made of aluminum as stated in the product description? Additionally, we are curious about the durability of the tent body and rainfly. We rely on extremely durable products to ensure our customers have a great outdoor experience. Any information about the materials and construction of the tent would be greatly appreciated. Thank you for your assistance!\"\n      },\n      {\n        \"MessageId\": 1274,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the tent poles are made of aluminum and should be inserted into the corresponding pole sleeves starting with the center hub and working your way outwards. The tent body and rainfly can be cleaned with a soft sponge or cloth using mild soap and water, and it\\u0027s important to avoid touching the tent walls to prevent moisture transfer from the outside to the inside. The ventilation system features adjustable vents on the rainfly and mesh panels on the tent body for optimal airflow while maintaining protection from the elements.\"\n      },\n      {\n        \"MessageId\": 1275,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for your response. We appreciate the information about cleaning and ventilation. However, we are still unsure about the overall durability of the tent body and rainfly. Can you provide more specific details about the materials used and any testing that has been done to ensure the tent\\u0027s durability? We want to make sure we are offering our customers the best quality products. Thank you for your help!\"\n      },\n      {\n        \"MessageId\": 1276,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the tent body, rainfly, and floor can be spot cleaned with a soft sponge or cloth using mild soap and water, and then thoroughly rinsed with clean water and allowed to air dry completely before storing. Ultratent offers a warranty that covers repair or replacement of defective components found within the warranty period. However, it\\u0027s important to note that the warranty does not cover damage caused by improper use, negligence, or natural disasters. If you have any further questions about the warranty or wish to make a claim, you can refer to the warranty section in the user manual or contact an Ultratent authorized distributor for more information. Thank you for considering the Ultratent UltraLite 2-Person Backpacking Tent for your store!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 58,\n    \"ProductId\": 160,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 355,\n    \"ShortSummary\": \"Frustrated customer demands refund/replacement for GPS device\",\n    \"LongSummary\": \"Customer Samantha Andrews is frustrated with the quality of the Trailblazer GPS Navigation Device from Geotrack, demanding a refund or replacement. Pending question regarding device usage and failure details. Next agent should address refund/replacement options and gather more info on device failure.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1277,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am beyond frustrated with my Trailblazer GPS Navigation Device from Geotrack. It has broken down after just a few uses, and I am extremely disappointed with the quality. I expected this device to be durable and reliable for all my outdoor adventures, but it has let me down. I demand a refund or a replacement for this faulty product. This is unacceptable!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 59,\n    \"ProductId\": 117,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 356,\n    \"ShortSummary\": \"Disabled Features Refund Demand\",\n    \"LongSummary\": \"Customer frustrated with disabled text messaging \\u0026 emergency services. Demands refund.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1278,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am beyond frustrated with the AdventurePro Off-Grid Satellite Communicator! I bought this device specifically for its text messaging and emergency services features, but now I can\\u0027t figure out how to use them. This is unacceptable, and I expect a solution to this problem immediately. I demand clear instructions on how to utilize the messaging and emergency services functions, or else I will be seeking a refund for this useless product.\"\n      },\n      {\n        \"MessageId\": 1279,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Based on the product manual, the AdventurePro Off-Grid Satellite Communicator\\u0027s text messaging and emergency services features are disabled for safety reasons. It is recommended to explore alternative communication options and safety measures for emergency assistance. We apologize for any inconvenience this may cause.\"\n      },\n      {\n        \"MessageId\": 1280,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"This is outrageous! I specifically bought this device for its text messaging and emergency services features, and now you\\u0027re telling me they are disabled for safety reasons?! That\\u0027s not what I signed up for. I demand a full refund for this misleading product!\"\n      },\n      {\n        \"MessageId\": 1281,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We apologize for the inconvenience. Based on the product manual, the text messaging and emergency services features of the AdventurePro Off-Grid Satellite Communicator are disabled for safety reasons. It is recommended to explore alternative communication options and safety measures for emergency assistance. If you have any further questions or require assistance with an alternative product, please let us know.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 60,\n    \"ProductId\": 110,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 56,\n    \"ShortSummary\": \"Inquiry about sustainability of PowerFuel Energy Bars\",\n    \"LongSummary\": \"Customer Evan Johnson asks about sustainability and eco-friendly practices of PowerFuel Energy Bars from EcoFuels. Needs detailed information on production methods and packaging materials. Pending response required.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1284,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the PowerFuel Energy Bars from EcoFuels and I have a question about their sustainability contribution. I\\u0027m a big advocate for environmental responsibility and I want to make sure I\\u0027m supporting the right cause. Can you provide more information on how the production of the bars utilizes eco-friendly practices and packaging materials? I want to make sure I fully understand the impact of my purchase. Thanks so much for your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 61,\n    \"ProductId\": 111,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 222,\n    \"ShortSummary\": \"Need Comprehensive Troubleshooting for Aquaflow 2L Hydration Pack\",\n    \"LongSummary\": \"Customer requests more comprehensive troubleshooting steps for Aquaflow 2L Hydration Pack due to customer complaints and lack of clear guidance in manual. Next agent should provide detailed troubleshooting steps.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1285,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there, I sell the Aquaflow 2L Hydration Pack at my store and I\\u0027ve been getting complaints about leaks. Your troubleshooting section says to check the seals, inspect the hose, and check the bite valve - but what if none of those things are the issue? I need a more comprehensive guide to troubleshooting these packs because I don\\u0027t have time to deal with angry customers! Let\\u0027s get this sorted out ASAP, please.\"\n      },\n      {\n        \"MessageId\": 1286,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, before using your Aquaflow 2L Hydration Pack, make sure to inspect it for any damage and wash the reservoir with warm, soapy water. Once you\\u0027ve done that, you\\u0027re ready to start hydrating! If the issue persists after following these steps, it\\u0027s recommended to contact the manufacturer\\u0027s support for further assistance.\"\n      },\n      {\n        \"MessageId\": 1287,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Inspecting for damage and washing the reservoir didn\\u0027t solve the issue. I need more comprehensive troubleshooting steps as I mentioned in my initial message. Please provide further assistance.\"\n      },\n      {\n        \"MessageId\": 1288,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Based on the user manual, the Aquaflow 2L Hydration Pack troubleshooting steps are not explicitly provided. However, the manufacturer\\u0027s support team is available for assistance. You can reach out to them through their website or give them a call for comprehensive troubleshooting guidance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 62,\n    \"ProductId\": 53,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 30,\n    \"ShortSummary\": \"Anti-fog Coating Guidance Needed\",\n    \"LongSummary\": \"Customer seeks guidance with anti-fog coating for GlacierTech Snowsport Goggles. Assistant provided cleaning instructions and warranty details. Pending issue with persistent fogging.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1289,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the GlacierTech Snowsport Goggles and I\\u0027m having some trouble with the anti-fog coating. I followed the instructions to be careful with the lenses and to store the goggles in the protective case, but they still seem to fog up when I\\u0027m on the slopes. Am I doing something wrong or is there a specific way I should be cleaning the lenses? Any guidance would be greatly appreciated. Thank you so much!\"\n      },\n      {\n        \"MessageId\": 1290,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Thank you for reaching out to us. We appreciate your commitment to maintaining the pristine condition of your GlacierTech Snowsport Goggles. To ensure optimal performance, please follow the recommended cleaning procedure for the lenses. By following these steps, you can be assured of experiencing the crystal-clear vision that our goggles are designed to provide. Additionally, IceMaster proudly offers a limited lifetime warranty on the GlacierTech Snowsport Goggles. This warranty covers defects in materials and workmanship for the lifetime of the product from the date of purchase. In the unlikely event that your goggles have a manufacturing defect, IceMaster will repair or replace them free of charge. Please retain your proof of purchase to validate your warranty claim. If you encounter persistent fogging issues that cannot be resolved, please contact IceMaster Customer Support for further assistance. We hope this information is helpful, and thank you for choosing IceMaster! If you have any further questions, feel free to ask.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 63,\n    \"ProductId\": 171,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 358,\n    \"ShortSummary\": \"MOLLE Webbing for Portable Grill\",\n    \"LongSummary\": \"Customer inquired about using MOLLE webbing to attach a portable grill. Assistant confirmed feasibility. Pending response required for next steps.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1291,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear Tactic Tech Support Team, I recently purchased the Stealth Recon Backpack for an upcoming trip, and I must say, I\\u0027m impressed with the durability and functionality of the product. However, I was wondering if it\\u0027s possible to use the MOLLE webbing to attach a small portable grill to the backpack. I have a unique idea to use it for a outdoor cooking setup, and I believe the backpack\\u0027s sturdy construction could support it. Could you please advise if this is feasible? Thank you for your assistance.\"\n      },\n      {\n        \"MessageId\": 1292,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Stealth Recon Backpack features MOLLE (Modular Lightweight Load-carrying Equipment) webbing, which allows you to attach additional pouches, accessories, or gear to enhance its functionality and carry capacity. This makes it feasible to attach a small portable grill to the backpack for your outdoor cooking setup.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 64,\n    \"ProductId\": 22,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 359,\n    \"ShortSummary\": \"Guidance for Filling Backpack\",\n    \"LongSummary\": \"Customer needs guidance on filling the main compartment and utilizing the side pockets of the 45L Technical Backpack for an upcoming trip. Response provided instructions. No pending questions.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1293,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the Peakpacker Summit 45L Technical Backpack and I\\u0027m having trouble figuring out how to properly fill it with my gear. I want to make sure I\\u0027m doing it right for my upcoming outdoor trip, but I\\u0027m feeling a bit embarrassed that I can\\u0027t quite figure it out. Could you provide some guidance on how to fill the main compartment and utilize the side pockets? I want to ensure that I\\u0027m distributing the weight properly and making the most of the storage space. Any help would be greatly appreciated. Thank you!\"\n      },\n      {\n        \"MessageId\": 1294,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hi there, to fill the main compartment of your Peakpacker Summit 45L Technical Backpack, unzip the top lid and open the main compartment zipper. The main compartment is spacious and designed to accommodate larger gear items such as clothing, sleeping bags, and other essentials. As for the side pockets, simply unzip the pocket and carefully place your items inside. Once filled, securely fasten the zipper to ensure your items are secure while on the move. I hope this helps!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 65,\n    \"ProductId\": 29,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 360,\n    \"ShortSummary\": \"Guidance on SolarBoost Power Bank outdoor optimization\",\n    \"LongSummary\": \"Customer Eliza Thompson is seeking guidance on optimizing SolarBoost Power Bank for extended outdoor use, including ideal positioning of solar panel and proper cleaning. Response provided with user manual guidelines, but further questions or clarifications may be needed.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1295,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear Ecovolt Support Team, \\n\\nI recently purchased the SolarBoost Power Bank and I\\u0027m having trouble understanding how to optimize its performance for extended outdoor use. I read in the product description that it is recommended to place the power bank in direct sunlight, but I\\u0027m unsure about the ideal positioning of the solar panel. Additionally, I\\u0027m not sure how to properly clean the solar panels to ensure optimal charging. Could you please provide me with some guidance on these issues? Thank you for your assistance. \\n\\nSincerely, Eliza Thompson\"\n      },\n      {\n        \"MessageId\": 1296,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Dear Eliza Thompson, \\n\\nThank you for reaching out to us. According to the user manual, to optimize the performance of the SolarBoost Power Bank for extended outdoor use, it is recommended to place the power bank in direct sunlight and ensure that the solar panel is facing the sun for optimal charging efficiency. Additionally, it is important to keep the solar panels clean and free from any dirt or dust for optimal performance. If you have any further questions, feel free to ask. \\n\\nSincerely, \\nAdventureWorks Support\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 66,\n    \"ProductId\": 97,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 314,\n    \"ShortSummary\": \"Keychain functionality issue\",\n    \"LongSummary\": \"Customer reported the Wanderer Multi-Tool Keychain isn\\u0027t working and requested assistance. Assistant offered information about the keychain\\u0027s features and asked if the customer would like to know more about using them.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1297,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi, I bought the Wanderer Multi-Tool Keychain and it\\u0027s not working. Can you help me out?\"\n      },\n      {\n        \"MessageId\": 1298,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I found information about the Wanderer Multi-Tool Keychain and the NomadGear brand in the product manual. It seems like the keychain includes a flathead screwdriver and a built-in key ring for easy attachment. Would you like to know more about how to use these features?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 67,\n    \"ProductId\": 14,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 361,\n    \"ShortSummary\": \"Broken Propane Camp Stove - Ignition Issue\",\n    \"LongSummary\": \"Customer reports broken Propane Camp Stove, unable to troubleshoot ignition despite following manual. Requests urgent refund.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1299,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I just bought this Propane Camp Stove from BackCountry Cook and it\\u0027s already broken! The ignition button is not creating a spark, and I\\u0027ve checked the battery compartment and control valve as your troubleshooting manual suggests. None of it works! This is ridiculous, I expect better quality from a high-performance camping stove. I need this issue sorted out ASAP or I want a refund!\"\n      },\n      {\n        \"MessageId\": 1300,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, to troubleshoot the ignition issue, ensure that the propane canister is properly connected to the stove and turn the canister clockwise to ensure a tight fit. If the issue persists, you can contact BackCountry Cook customer support for further assistance. Additionally, the Propane Camp Stove comes with a limited 1-year warranty that covers defects in materials or workmanship. You can contact the friendly customer support team for assistance with warranty-related issues.\"\n      },\n      {\n        \"MessageId\": 1301,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I already tried checking the propane canister and ensuring it\\u0027s properly connected and tightened, but the ignition button still isn\\u0027t creating a spark. I\\u0027m frustrated and disappointed with the quality of this stove, and I want a refund as soon as possible!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 68,\n    \"ProductId\": 59,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 362,\n    \"ShortSummary\": \"Retailer needs detailed kayak info\",\n    \"LongSummary\": \"Retailer Dr. Megan Davidson requests technical specs and maintenance guidelines for Aqua Venture\\u0027s Explorer 3000 Kayak. A prompt and comprehensive response is needed.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1302,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Greetings, I am Dr. Megan Davidson, a fellow retailer who stocks the esteemed Explorer 3000 Kayak by Aqua Venture. I am in need of detailed technical specifications and maintenance guidelines to assist my customers with their inquiries. Your prompt and comprehensive response will be greatly appreciated. Thank you.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 69,\n    \"ProductId\": 113,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 363,\n    \"ShortSummary\": \"Leaking hydration system in Summit Pro 40L backpack\",\n    \"LongSummary\": \"Customer Elena Kim reports a leaking hydration system in her Summit Pro 40L backpack, demanding a replacement or repair ASAP due to damage to her gear. She expects a quality product and is frustrated with the faulty item. Needs immediate solution.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1303,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027m so frustrated! My Summit Pro 40L backpack\\u0027s hydration system is leaking and it\\u0027s ruining my gear. I need this resolved ASAP! I expect a quality product from Backhike, and this backpack is not living up to its description. I demand a replacement or repair for this faulty product. I shouldn\\u0027t have to deal with leaks after following the manual\\u0027s care instructions. Please provide a solution immediately.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 70,\n    \"ProductId\": 196,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 364,\n    \"ShortSummary\": \"GPS Signal Dropping Issue\",\n    \"LongSummary\": \"TrailMaster GPS Watch experiencing GPS signal drop. Customer seeks solution. Next agent to provide troubleshooting steps or possible hardware issues.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1309,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, my TrailMaster GPS Watch keeps losing the GPS signal. Can you help me fix it?\"\n      },\n      {\n        \"MessageId\": 1310,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The TrailMaster GPS Watch features a state-of-the-art multi-constellation receiver that supports GPS, GLONASS, and Galileo satellite systems, ensuring precise location tracking and navigation. It is designed for use by experienced outdoor enthusiasts in challenging environments and offers essential navigation tools, including topographic maps and real-time location sharing for enhanced safety.\"\n      },\n      {\n        \"MessageId\": 1311,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"GPS signal still dropping. What should I do?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 71,\n    \"ProductId\": 37,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 365,\n    \"ShortSummary\": \"Issue with instant cold pack usage\",\n    \"LongSummary\": \"Customer impressed with product but needs guidance on using instant cold pack for sprain. Requesting help to resolve the issue.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1312,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Wild Guard Outdoor First Aid Kit and I must say I am impressed with its comprehensive contents and compact design. However, I encountered an issue while trying to use the instant cold pack to reduce swelling for a minor sprain. I followed the instructions provided, but the pack didn\\u0027t seem to work as expected. Could you please provide me with some guidance on how to properly use this feature? I appreciate your help in resolving this matter. Thank you.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 72,\n    \"ProductId\": 4,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 366,\n    \"ShortSummary\": \"Inquiry about Two-Way Radio in Extreme Weather\",\n    \"LongSummary\": \"Customer inquired about the two-way radio\\u0027s ability to operate in extreme weather conditions. Assistant responded with generic info about tent\\u0027s durability. Customer requested specific info about the radio\\u0027s performance.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1313,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I purchased the Life Guard X Emergency Survival Kit and I need to know if the two-way radio can operate in extreme weather conditions. I don\\u0027t want to be stuck in an emergency situation only to find out that the radio doesn\\u0027t work when I need it most. Your manual talks about the durability and weather-resistance of the radio, but I need more specific information. This is a life-saving tool and I expect it to perform flawlessly in any situation. I hope you can provide me with a satisfactory answer without just quoting from the manual.\"\n      },\n      {\n        \"MessageId\": 1314,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Life Guard X Emergency Survival Kit includes a compact and lightweight emergency tent for protection against the elements. The tent is designed to accommodate two adults and is made of durable, weather-resistant material for added reliability. This indicates that the kit is designed to provide protection in extreme weather conditions.\"\n      },\n      {\n        \"MessageId\": 1315,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Your response does not address my specific question about the two-way radio\\u0027s ability to operate in extreme weather conditions. Please provide me with information regarding the radio specifically, as that is my main concern.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 73,\n    \"ProductId\": 193,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 367,\n    \"ShortSummary\": \"Cake Carrier High-Altitude Issue\",\n    \"LongSummary\": \"Customer purchased AltitudeTech Cake Carrier, experiencing issues with high-altitude cakes not arriving intact. Seeks assistance or guidance on addressing the issue.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1316,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the AltitudeTech Cake Carrier and have been experiencing some issues with its functionality. Despite following the transportation guidelines and cleaning procedures outlined in the manual, my high-altitude cakes are not arriving intact as promised. I am concerned that the product may not be working as intended. I would greatly appreciate any assistance or guidance on how to address this issue. Thank you for your attention to this matter.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 74,\n    \"ProductId\": 79,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 277,\n    \"ShortSummary\": \"Adventure Pro Camera repair request\",\n    \"LongSummary\": \"Adventure Pro Camera fell during hiking trip, needs repair. Customer asking for help with repair and expresses disappointment. Next agent needs to provide options for repair and offer assistance.\",\n    \"CustomerSatisfaction\": 3,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1317,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! So, I was out on this amazing hiking trip with my Adventure Pro Camera and unfortunately, it took a little tumble and now it\\u0027s not working properly. I\\u0027m totally bummed because I was really looking forward to capturing all those breathtaking views. Any chance you can help me out with getting it repaired? I promise I\\u0027ll be more careful next time! Thanks a bunch!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 75,\n    \"ProductId\": 36,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 368,\n    \"ShortSummary\": \"Assembly issues with Eco Grill\",\n    \"LongSummary\": \"Customer needs detailed assembly instructions for Eco Grill, grill not working\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1318,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Grill not working, need help with assembly and positioning\"\n      },\n      {\n        \"MessageId\": 1319,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, assembly instructions are provided in the user manual. It\\u0027s important to follow the step-by-step instructions and conduct a final inspection to ensure all components are properly installed and secured. As for positioning, select a suitable location for the grill, considering safety, ventilation, and proximity to flammable materials.\"\n      },\n      {\n        \"MessageId\": 1320,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Still having issues with assembly, can you provide more detailed instructions?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 76,\n    \"ProductId\": 25,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 126,\n    \"ShortSummary\": \"Tool levelling issue despite manual instructions\",\n    \"LongSummary\": \"Customer reports TerraScoop Excavation Tool not levelling properly despite following manual. Further troubleshooting needed from support agent.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1321,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Tool not levelling properly, need help now.\"\n      },\n      {\n        \"MessageId\": 1322,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the TerraScoop Excavation Tool is engineered to meet your excavation needs with unparalleled precision and efficiency. Please ensure that the tool is being used as directed in the manual. If the issue persists, we recommend contacting DigDigDig customer support for further assistance.\"\n      },\n      {\n        \"MessageId\": 1323,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Tool still not working, tried following manual but no luck\"\n      },\n      {\n        \"MessageId\": 1324,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The TerraScoop Excavation Tool is engineered to meet your excavation needs with unparalleled precision and efficiency. If the tool is not levelling properly, please perform a thorough inspection of the tool to ensure all components are in impeccable condition. Do not proceed to use the tool if any part appears to be damaged or malfunctioning. If the issue persists, please contact DigDigDig customer support for further assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 77,\n    \"ProductId\": 107,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 70,\n    \"ShortSummary\": \"Adjusting UltraGrip 3000 Trekking Poles\",\n    \"LongSummary\": \"Customer needs help adjusting the length on UltraGrip 3000 poles. Assistant advised against outdoor use and to contact customer support for further instructions. Pending question on how to adjust the length.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1325,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, idk how to adjust the length on these UltraGrip 3000 poles. Can u help? Thx\"\n      },\n      {\n        \"MessageId\": 1326,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the UltraGrip 3000 Trekking Poles are not suitable for trekking or hiking. Polepro advises against using these poles for any outdoor activities. It is recommended to discontinue use immediately and contact customer support for further instructions. If you have any further questions or need assistance, please let us know.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 78,\n    \"ProductId\": 106,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 234,\n    \"ShortSummary\": \"Durability of ArcticZone 500 Sleeping Bag for Swimming\",\n    \"LongSummary\": \"Customer inquires about the durability of the ArcticZone 500 Sleeping Bag for swimming. Needs assistance to determine if it will hold up. Pending response on suitability for swimming.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1327,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Sleeping bag for swimming? Will it hold up? Need help.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 79,\n    \"ProductId\": 97,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 369,\n    \"ShortSummary\": \"Product functionality enquiry\",\n    \"LongSummary\": \"Customer purchased Wanderer Multi-Tool Keychain from NomadGear and is unsure if it\\u0027s working properly. Assistance provided on how to attach key ring, specific issues not yet mentioned. Next support agent should inquire about specific issues with the keychain\\u0027s functionality.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1328,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi, I recently purchased the Wanderer Multi-Tool Keychain from NomadGear and I\\u0027m not sure if it\\u0027s working properly. Can you please help me with this? Thank you.\"\n      },\n      {\n        \"MessageId\": 1329,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hi, the Wanderer Multi-Tool Keychain comes with a built-in key ring for easy attachment to your keys or backpack. Simply slide your key ring through the designated hole at the end of the keychain, and you\\u0027re all set! If you have any specific issues with the functionality of the keychain, please let us know. Thank you.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 80,\n    \"ProductId\": 126,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 370,\n    \"ShortSummary\": \"Difficulty Finding Battery Check Button\",\n    \"LongSummary\": \"Customer demands replacement or refund due to difficulty finding battery check button on SOS Emergency Beacon. Requires clarification on the specific issues faced and possible solutions.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1334,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I cannot believe the battery check button on the SOS Emergency Beacon is so hard to find! I\\u0027ve been looking for it for ages and it\\u0027s not clearly labeled at all. This is unacceptable for a product that is supposed to be for emergencies. I demand a replacement or a full refund for this inconvenience!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 81,\n    \"ProductId\": 139,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 371,\n    \"ShortSummary\": \"Excited about SmartCyclo\\u0027s tracking features\",\n    \"LongSummary\": \"Customer excited to hear about SmartCyclo\\u0027s speed and heart rate tracking. Ready to purchase. Next response should confirm purchase.\",\n    \"CustomerSatisfaction\": 8,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1335,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there WheelWise team! I\\u0027m seriously considering getting the SmartCyclo GPS Bike Computer, and I have a burning question about its performance tracking capabilities. Can this awesome gadget really track my speed and monitor my heart rate while I\\u0027m cycling? I love pushing myself to new limits, so having these features would be a game-changer for me. Any info you can share would be amazing! Thanks so much! \\uD83D\\uDE0A\"\n      },\n      {\n        \"MessageId\": 1336,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The SmartCyclo GPS Bike Computer offers advanced performance tracking features to help you monitor your cycling progress and improve your performance. With the ability to track your speed and monitor your heart rate, you can stay on top of your training goals and push yourself to new limits. If you encounter errors in the performance tracking data, please ensure that the sensors, such as the heart rate monitor, are securely connected and functioning correctly. According to the manual, the SmartCyclo GPS Bike Computer uses advanced GPS technology to provide accurate real-time speed measurements.\"\n      },\n      {\n        \"MessageId\": 1337,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey WheelWise team! Thanks for the info! I\\u0027m so excited to hear that the SmartCyclo GPS Bike Computer can track my speed and monitor my heart rate. I\\u0027m definitely going to grab one now! You guys are the best! \\uD83D\\uDE0A\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 82,\n    \"ProductId\": 136,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 372,\n    \"ShortSummary\": \"Solaris 500 Camping and Phone Charging Inquiry\",\n    \"LongSummary\": \"Customer inquired about Solaris 500 for camping and phone charging. Confirmed successful phone charge. Next agent should offer additional details on charging capabilities for other devices.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1338,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Is Solaris 500 good for camping? Will it charge my phone?\"\n      },\n      {\n        \"MessageId\": 1339,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Ecovolt Solaris 500 Portable Solar Charger is designed for outdoor use and is ideal for camping, hiking, and other off-grid activities. It is built to withstand the rigors of outdoor adventures.\"\n      },\n      {\n        \"MessageId\": 1340,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Charged my phone and it worked great!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 83,\n    \"ProductId\": 44,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 74,\n    \"ShortSummary\": \"Inquiry about using fire starter for camping trip\",\n    \"LongSummary\": \"Customer inquires about using fire starter from RescueTech Emergency Kit for camping. Assistant advises to carefully follow instructions to ensure safe operation.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1341,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, I got this RescueTech Emergency Kit from Life Guard X and I\\u0027m thinking of using the fire starter for a camping trip. Do you think that\\u0027s a good idea?\"\n      },\n      {\n        \"MessageId\": 1342,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the fire starter included in the RescueTech Emergency Kit is a vital tool for starting a fire in emergency situations. It is compact and easy to use, making it an essential item for your survival gear. You should carefully follow the instructions provided with the fire starter to ensure safe and successful operation. Keep flammable materials away from the fire starting process to prevent accidents.\"\n      },\n      {\n        \"MessageId\": 1343,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thx, I\\u0027ll make sure to follow the instructions. Appreciate the help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 84,\n    \"ProductId\": 71,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 373,\n    \"ShortSummary\": \"Seeking Specific Frequency Ranges for Compatibility\",\n    \"LongSummary\": \"Customer Eliot Finley seeks specific frequency ranges for Trailcom Signal Booster 2000. Assistant provided general info but customer still seeks specific frequency ranges for compatibility with existing devices.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1344,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello Trailcom Support, I am interested in the Trailcom Signal Booster 2000 for off-grid communication purposes. I need detailed technical specifications and information on its signal strength capabilities. I am particularly interested in how it boosts signal strength and the compatibility with various devices. Additionally, I would like to know if it is suitable for use in remote areas with limited connectivity. Your prompt and detailed response is greatly appreciated. Thank you.\"\n      },\n      {\n        \"MessageId\": 1345,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Trailcom Signal Booster 2000 is designed to elevate your off-grid communication experience by significantly enhancing signal strength, allowing you to stay connected even in the most remote areas. It is compatible with a wide array of devices, ensuring seamless connectivity for all your communication needs. According to the manual, the product complies with all relevant regulatory standards and is designed to operate within approved frequency bands and power levels to ensure minimal interference with other communication systems.\"\n      },\n      {\n        \"MessageId\": 1346,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"\\u003Cmessage role=\\u0022Customer\\u0022\\u003EThank you for the information provided. Can you please also provide the specific frequency ranges that the Trailcom Signal Booster 2000 operates within? I need this information to ensure compatibility with my existing communication devices. Your prompt response is greatly appreciated. Thank you.\"\n      },\n      {\n        \"MessageId\": 1347,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Trailcom Signal Booster 2000 operates within approved frequency bands and power levels to ensure minimal interference with other communication systems. It is compatible with a wide range of devices, including mobile phones, tablets, and other communication devices, and is designed to enhance signal strength for off-grid communication in remote areas.\"\n      },\n      {\n        \"MessageId\": 1348,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information provided. However, I need the specific frequency ranges that the Trailcom Signal Booster 2000 operates within in order to ensure compatibility with my existing communication devices. Could you please provide this information promptly? Thank you.\"\n      },\n      {\n        \"MessageId\": 1349,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Trailcom Signal Booster 2000 operates within approved frequency bands and power levels to ensure minimal interference with other communication systems. It is designed to enhance signal strength for off-grid communication in remote areas. According to the manual, the product complies with all relevant regulatory standards, including FCC regulations.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 85,\n    \"ProductId\": 142,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 374,\n    \"ShortSummary\": \"Excited customer received helpful tips on hammock setup\",\n    \"LongSummary\": \"Customer is excited about the hammock and received helpful tips on repairing and setting up. No pending questions. Next agent response: None needed, customer is satisfied.\",\n    \"CustomerSatisfaction\": 8,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1350,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! So I\\u0027ve been eyeing this UltraLight Camping Hammock from Dreamscape for my upcoming backpacking trip, and I just wanted to make sure it\\u0027s as comfy and durable as it sounds! I mean, who wouldn\\u0027t want to rest easy under the stars, right? Also, any tips on setting it up like a pro? Can\\u0027t wait to chillax in style with this bad boy. Thanks a bunch, you guys rock! \\uD83C\\uDFD5\\uFE0F\\uD83C\\uDF1F\"\n      },\n      {\n        \"MessageId\": 1351,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hey there! The Dreamscape UltraLight Camping Hammock comes with a repair kit and instructions to patch any rips or tears. After repair, give it a gentle tug to ensure the patch holds, and you\\u0027re all set to hit the trail again! As for setting it up, lay out the hammock flat, loop the durable tree straps around a tree, and adjust to the desired height. Here are some storage tips: [storage tips]. Enjoy your backpacking trip and chillax in style!\"\n      },\n      {\n        \"MessageId\": 1352,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! Thanks for the helpful tips on repairing and setting up the hammock! I followed your instructions and had no issues at all. Can\\u0027t wait to take this bad boy out on the trail and chillax in style! You guys totally rock! \\uD83C\\uDFD5\\uFE0F\\uD83C\\uDF1F\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 86,\n    \"ProductId\": 149,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 375,\n    \"ShortSummary\": \"AquaFlow Pro Bite Valve and Straps Issue\",\n    \"LongSummary\": \"Customer experiencing issues with AquaFlow Pro bite valve and adjustable straps. Additional assistance needed for satisfaction.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1353,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I purchased the AquaFlow Pro hydration system from Thirsttrek and I\\u0027m really disappointed. The easy-flow bite valve is anything but easy. I can\\u0027t get it to work properly no matter what I do. And don\\u0027t even get me started on the adjustable straps - they\\u0027re supposed to be comfortable and stable, but they\\u0027re just a pain to adjust. I need some real help here, not just some fancy engineering talk. This product is not living up to its description and I want to know what you\\u0027re going to do about it.\"\n      },\n      {\n        \"MessageId\": 1354,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Thank you for reaching out to us. I understand your frustration and I\\u0027m here to help. According to the manual, the adjustable straps have been engineered for comfort and stability, and there are specific guidelines for adjustment. Have you tried following the recommended adjustment procedure to ensure they provide a comfortable and stable fit? Additionally, the easy-flow bite valve has been designed for optimal liquid flow dynamics, and there are guidelines for assessing and maintaining its performance. If you have additional questions or need further assistance, please let me know.\"\n      },\n      {\n        \"MessageId\": 1355,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Yeah, I followed the guidelines for adjusting the straps and I still can\\u0027t get them to fit comfortably. And as for the easy-flow bite valve, I\\u0027ve tried everything and it\\u0027s just not working as it should. This product is a real letdown and I\\u0027m not satisfied with the resolution so far.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 87,\n    \"ProductId\": 195,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 376,\n    \"ShortSummary\": \"Broken zippers on Trekker 30L Backpack\",\n    \"LongSummary\": \"Customer demands replacement or refund for broken zippers on Trekker 30L Backpack. Expresses disappointment in product durability. Requires immediate resolution.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1356,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I can\\u0027t believe the zippers on my Trekker 30L Backpack have broken already! This is unacceptable for a product that\\u0027s supposed to be durable. I demand a replacement or a full refund. I expect better quality from Adventure Pack and I want this issue resolved immediately.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 88,\n    \"ProductId\": 190,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 377,\n    \"ShortSummary\": \"Troubleshooting UltraLight Poles 300\",\n    \"LongSummary\": \"Customer experiencing issues with UltraLight Poles 300, seeking guidance on flexural strength test and manual instructions. Next agent should provide step-by-step instructions for the test and repair procedures.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1357,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the UltraLight Poles 300 for my upcoming hiking trip. However, I\\u0027m having some trouble with them and it seems like they don\\u0027t work at all. I\\u0027ve relied on the description that these poles provide stability and support on any terrain, but I haven\\u0027t experienced that at all. Can you please help me figure out what\\u0027s going on? I really need these poles to work for my trip. Thank you so much for your assistance!\"\n      },\n      {\n        \"MessageId\": 1358,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hi there, thank you for reaching out to us. It seems that there may be some structural defects with the poles. I advise discontinuing use and contacting our customer service for repair or replacement options. You can also perform a flexural strength test using specialized equipment to determine if the poles have maintained their structural integrity. Refer to ISO 14125 for testing standards. If you need further assistance, please don\\u0027t hesitate to contact us.\"\n      },\n      {\n        \"MessageId\": 1359,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, thanks for your response. I\\u0027m not quite sure how to perform a flexural strength test or where to find the specialized equipment. Could you please provide more guidance on how to do this? I really want to make sure I can rely on the poles for my trip. Thank you!\"\n      },\n      {\n        \"MessageId\": 1360,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Based on the user manual, the UltraLight Poles 300 are compliant with the ISO 12500-1:2014 standard for design, construction, and performance of trekking poles. The product has been designed to provide reliable and stable support on varying terrains. To ensure the integrity of the carbon construction, it is important to perform regular inspections and maintenance. In the event of any damage or potential issues, please follow the troubleshooting and repair procedures outlined in the manual.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 89,\n    \"ProductId\": 156,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 378,\n    \"ShortSummary\": \"Product Usage Inquiry\",\n    \"LongSummary\": \"Customer Jasmine Park is excited about the Arctic Ice Grip Crampons and wants specific tips for using them. Looking for guidance on maximizing usage.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1361,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there Glacierpro team! I just picked up a pair of your Arctic Ice Grip Crampons and I am beyond excited to try them out on the icy trails near me. I have to say, the durability and traction features really caught my eye, and I can\\u0027t wait to see how they hold up in action! Just wanted to check in and see if there are any specific tips or tricks for using them that I should know about? I want to make sure I get the most out of these bad boys. Thanks a million, and looking forward to being part of the Glacierpro community! \\uD83C\\uDFD4\\uFE0F\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 90,\n    \"ProductId\": 54,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 380,\n    \"ShortSummary\": \"Troubleshooting AvalanchePro Ski Backpack\",\n    \"LongSummary\": \"Customer reports issue with AvalanchePro Ski Backpack. Requesting assistance with troubleshooting and resolving the problem. No response yet.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1366,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, my AvalanchePro Ski Backpack doesn\\u0027t seem to work. Can you help? \\uD83C\\uDFD4\\uFE0F\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 91,\n    \"ProductId\": 20,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 380,\n    \"ShortSummary\": \"Using TrekTracker GPS Watch for Orienteering\",\n    \"LongSummary\": \"Customer inquired about using TrekTracker GPS Watch for orienteering in the forest. Assistant confirmed it\\u0027s suitable. Customer is ready to test it.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1367,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, can I use the TrekTracker GPS Watch for orienteering in the forest? I heard it has built-in maps and altitude tracking, so it should work, right? Thx!\"\n      },\n      {\n        \"MessageId\": 1368,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The TrekTracker GPS Watch is specifically designed for outdoor activities such as hiking, camping, trekking, and mountaineering. It is equipped with high-resolution maps and a state-of-the-art GPS receiver compatible with multiple satellite systems. Its high-precision GPS module ensures accurate positioning and tracking, even in challenging terrain. The watch is intended for use as a navigational aid during outdoor activities, making it suitable for orienteering in the forest.\"\n      },\n      {\n        \"MessageId\": 1369,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thx, that clears it up! I\\u0027m ready to go out and test it now.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 92,\n    \"ProductId\": 71,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 138,\n    \"ShortSummary\": \"Trouble using booster in remote areas\",\n    \"LongSummary\": \"Customer purchased Signal Booster 2000, having trouble using it in remote areas. Requests guidance on how to improve signal strength in remote locations.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1370,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the Trailcom Signal Booster 2000 and I\\u0027m having trouble getting it to work in the way I expected. I\\u0027m feeling a bit embarrassed because I thought I had followed all the instructions properly, but it\\u0027s just not working for me. I\\u0027m really hoping you can help me figure out what I might be doing wrong. I\\u0027m especially interested in using it in remote areas, so I was really looking forward to the boost in signal strength. Any guidance or advice you can provide would be greatly appreciated. Thank you so much.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 93,\n    \"ProductId\": 53,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 81,\n    \"ShortSummary\": \"Adjusting strap guidance provided\",\n    \"LongSummary\": \"Customer is satisfied with provided information on adjusting strap. No further assistance needed. Ticket can be closed.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1371,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the IceMaster GlacierTech Snowsport Goggles and I must say, they are absolutely marvelous! However, I have a slight concern about the strap adjustment. It seems to be a tad challenging to lengthen and adjust. Could you kindly provide some guidance on how to ensure the strap is adjusted properly? I want to make sure I am getting the full benefit of this wonderful product! Thank you so much for your help.\"\n      },\n      {\n        \"MessageId\": 1372,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We are pleased to guide you through the process of adjusting the strap. Before you begin, please ensure that you are in a comfortable and well-lit area, as it is essential to have the most optimal conditions for this task. If you encounter any persistent fogging issues that cannot be resolved, please contact IceMaster Customer Support for further assistance. According to the manual, IceMaster proudly offers a limited lifetime warranty on the GlacierTech Snowsport Goggles. This warranty covers defects in materials and workmanship for the lifetime of the product from the date of purchase. In the unlikely event that your goggles have a manufacturing defect, IceMaster will repair or replace them free of charge. Please retain your proof of purchase to validate your warranty claim.\"\n      },\n      {\n        \"MessageId\": 1373,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information. I will make sure to follow the steps you provided and reach out to IceMaster Customer Support if I encounter any fogging issues. I appreciate your assistance!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 94,\n    \"ProductId\": 97,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 381,\n    \"ShortSummary\": \"Concern about using bottle opener on multitool keychain\",\n    \"LongSummary\": \"Customer is concerned about using the bottle opener on the Wanderer Multi-Tool Keychain and is looking for information on how to use it safely. Assistant provided instructions on how to use the bottle opener. Customer will try it out and provide feedback if it works.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1374,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, I got the Wanderer Multi-Tool Keychain and I\\u0027m a bit concerned about using the bottle opener. Can you provide more information on how to use it safely? Thanks.\"\n      },\n      {\n        \"MessageId\": 1375,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, when it\\u0027s time to enjoy a cold beverage, the built-in bottle opener on the Wanderer Multi-Tool Keychain can be used by positioning the edge of the keychain under the bottle cap and applying leverage to pop it off effortlessly. I hope this helps! If you have any other questions, feel free to ask.\"\n      },\n      {\n        \"MessageId\": 1376,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thanks for the information. I\\u0027ll give it a try and let you know if it works. Thanks again!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 95,\n    \"ProductId\": 66,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 259,\n    \"ShortSummary\": \"Inquiry about tent\\u0027s wind \\u0026 storm capabilities\",\n    \"LongSummary\": \"Customer inquires about the SunSafe Pop-Up Beach Tent\\u0027s ability to withstand strong winds and be used in a thunderstorm. Assistant advises seeking alternative shelter. Pending customer response on alternative shelter options needed.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1377,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there! I\\u0027m considering buying the SunSafe Pop-Up Beach Tent for our upcoming beach trip. I\\u0027m just wondering, can it withstand really strong winds? We\\u0027re going to a windy beach and I want to make sure it won\\u0027t blow away. Also, can it be used as a shelter during a sudden thunderstorm? Thanks so much for your help!\"\n      },\n      {\n        \"MessageId\": 1378,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The SunSafe Pop-Up Beach Tent is not designed to withstand strong winds or be used as a shelter during thunderstorms. It is recommended to seek alternative shelter in such conditions for your safety.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 96,\n    \"ProductId\": 96,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 26,\n    \"ShortSummary\": \"Unmet Backyard Party Expectations\",\n    \"LongSummary\": \"Customer is upset that the Solaris 5000 does not meet expectations for backyard parties. Customer demands refund or replacement. Next support agent should clarify product features and options.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1379,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I can\\u0027t believe this! I bought the Solaris 5000 to light up my backyard parties, not for camping or hiking! It\\u0027s supposed to be versatile, right? I demand a refund or replacement because this is not what I signed up for. This is ridiculous!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 97,\n    \"ProductId\": 53,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 382,\n    \"ShortSummary\": \"Lens Cleaning Solution Inquiry\",\n    \"LongSummary\": \"Customer inquired about recommended lens cleaning solution and was provided with detailed instructions. Customer expressed satisfaction with the response.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1380,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there IceMaster Team! Just wanted to say how stoked I am about snagging a pair of your GlacierTech Snowsport Goggles. I mean, anti-fog coating AND UV protection? That\\u0027s next level! But hey, quick question - do you recommend a specific lens cleaning solution for these bad boys? I want to make sure I keep \\u0027em in top-notch condition for shredding the slopes. Thanks a bunch! \\uD83C\\uDFC2\"\n      },\n      {\n        \"MessageId\": 1381,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the user manual, for cleaning the lenses, apply a small amount of lens cleaning solution to the microfiber cloth and gently wipe the lenses in a circular motion. After that, allow the lenses to air dry or use a second clean microfiber cloth to remove any excess cleaning solution. Additionally, the limited lifetime warranty on the GlacierTech Snowsport Goggles covers defects in materials and workmanship for the lifetime of the product from the date of purchase. IceMaster will repair or replace them free of charge in the event of manufacturing defects. Please retain your proof of purchase to validate your warranty claim. If you have any further questions or need assistance with warranty claims, feel free to reach out to us.\"\n      },\n      {\n        \"MessageId\": 1382,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thanks so much for the info! I used the lens cleaning solution and it worked like a charm. You guys are the best! \\uD83D\\uDE4C\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 98,\n    \"ProductId\": 136,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 383,\n    \"ShortSummary\": \"Faulty Solar Charger Demand Refund/Replacement\",\n    \"LongSummary\": \"Customer purchased Solaris 500 Portable Solar Charger, fully charged it, followed care instructions, but it doesn\\u0027t work. Customer demands refund or replacement. Next agent should investigate product functionality and offer resolution options.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1383,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I purchased the Solaris 500 Portable Solar Charger for my outdoor adventures, and it doesn\\u0027t work at all. I made sure to fully charge it before using it, but nothing happens when I connect my devices. This is ridiculous! I followed the cleaning and storage instructions from the manual, so don\\u0027t tell me I didn\\u0027t take care of it properly. I demand a refund or a replacement. This product is a total disappointment!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 99,\n    \"ProductId\": 130,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 122,\n    \"ShortSummary\": \"Speaker won\\u0027t turn on despite charging\",\n    \"LongSummary\": \"Customer unable to turn on speaker despite charging and resetting. Requesting refund or replacement. Next support agent should assess eligibility for return or refund.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Returns\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1384,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I bought the WildBeat Bluetooth Speaker and it won\\u0027t turn on at all! Don\\u0027t tell me to charge it - I already did that and the battery indicator light never comes on. I want a refund or a replacement, this is ridiculous.\"\n      },\n      {\n        \"MessageId\": 1385,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, to pair the WildBeat Bluetooth Speaker with your Bluetooth device, ensure that the speaker is turned on. Then, activate the Bluetooth function on your device and select \\u0022WildBeat\\u0022 from the list of available devices. Once connected, the LED indicator on the speaker will turn solid blue. If you have trouble with the battery indicator light, please try charging the speaker with the provided USB charging cable. If the issue persists, please reach out to the manufacturer\\u0027s support contact detailed in the user manual for further assistance.\"\n      },\n      {\n        \"MessageId\": 1386,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I already told you I tried charging it and the battery indicator light never comes on. I don\\u0027t care about pairing it with my device, I just want a working speaker or my money back!\"\n      },\n      {\n        \"MessageId\": 1387,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, to fully charge the WildBeat Bluetooth Speaker, use the included USB-C cable to connect the speaker to a power source. The LED indicator light on the back of the speaker will glow red while charging and turn off when fully charged. It takes approximately 3 hours to fully charge the speaker. Please ensure you use the original charging cable provided to avoid any damage to the speaker. If you have trouble with the battery indicator light, please ensure that the speaker is fully charged. If the issue persists, you may also try resetting the speaker by pressing and holding the power button for 5 seconds.\"\n      },\n      {\n        \"MessageId\": 1388,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I already told you, I tried charging it with the original cable and the battery indicator light still won\\u0027t come on. I even tried resetting the speaker but that didn\\u0027t work either. This is so frustrating!\"\n      },\n      {\n        \"MessageId\": 1389,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, if your WildBeat Bluetooth Speaker is not powering on, make sure the speaker is fully charged by connecting it to a power source using the included USB cable. The battery indicator light should turn on when it\\u0027s charging. If you have already tried this and the issue persists, you may be eligible for a return or a refund. You can initiate a return for defective products within 1 year of purchase at https://northernmountains.example.com/support/returns. If you need further assistance, please refer to the manufacturer\\u0027s support contact details in the user manual.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 100,\n    \"ProductId\": 70,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 3,\n    \"ShortSummary\": \"USB output confirmed\",\n    \"LongSummary\": \"Customer Eleanor Montgomery confirmed USB output voltage and current. No further assistance needed.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 6,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear Customer Support, my name is Eleanor Montgomery and I recently purchased the Juice Junkie Solar Power Bank 10000mAh. I have been using it to charge my outdoor electronics, and I want to ensure that it is performing as expected. Specifically, I would like to confirm that the USB ports are delivering the correct output voltage and current as mentioned in the product description. Could you please provide me with guidance on how to check this? I want to make sure that the power bank is functioning optimally and efficiently. Thank you for your assistance.\"\n      },\n      {\n        \"MessageId\": 7,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Dear Eleanor Montgomery, \\n\\nAccording to the Juice Junkie Solar Power Bank 10000mAh user manual, the USB ports deliver an output voltage of 5V and a maximum output current of 2.1A. You can measure the USB output current using a multimeter to ensure optimal performance. Follow the steps in the manual for accurate measurement. The product also features a high-efficiency monocrystalline solar panel with a peak power output of 1.8W. If you have any further questions, feel free to ask. Thank you for choosing Juice Junkie! AdventureWorks Support\"\n      },\n      {\n        \"MessageId\": 8,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear AdventureWorks Support, thank you for providing the information on how to measure the USB output current using a multimeter. I have followed the steps in the manual and confirmed that the USB ports are delivering the correct output voltage and current as mentioned. I appreciate your prompt assistance in resolving my query. Thank you for your help. Best regards, Eleanor Montgomery\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 101,\n    \"ProductId\": 15,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 4,\n    \"ShortSummary\": \"Retailer seeking fast charging details\",\n    \"LongSummary\": \"Retailer Alexandra Miller seeks detailed info on AdventurePro 1000 fast charging and troubleshooting tips to share with customers. Next support agent should provide detailed information on fast charging technology and troubleshooting tips.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 9,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear AdventureElec Customer Support,\\n\\nI am a retailer who stocks the AdventurePro 1000 power bank and I have been receiving customer enquiries regarding the fast charging feature of this product. Can you provide me with more detailed information on how the fast charging technology works and any troubleshooting tips that I can share with my customers? Your assistance in this matter would be greatly appreciated. Thank you.\\n\\nSincerely, \\nAlexandra Miller\"\n      },\n      {\n        \"MessageId\": 10,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Dear Alexandra Miller, \\n\\nThank you for reaching out to AdventureElec Customer Support. The AdventurePro 1000 power bank uses fast charging technology to quickly charge your devices. Simply connect the power bank to a power source using the included Micro-USB charging cable, and the LED indicator lights will show the current battery status. Additionally, the power bank features multiple USB ports, allowing you to charge multiple devices simultaneously. As for warranty and repair options, AdventureElec offers a 1-year limited warranty for the AdventurePro 1000. If you need to make a warranty claim, please contact AdventureElec customer service at warranty@adventureelec.com with the original proof of purchase and a detailed description of the issue. Thank you for your support! \\n\\nSincerely, \\nAdventureWorks Support\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 102,\n    \"ProductId\": 133,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 5,\n    \"ShortSummary\": \"MOLLE system attachment instructions for TactiX 3000 backpack.\",\n    \"LongSummary\": \"Customer Evan Thompson asked for information on how to properly attach accessories using the MOLLE system on the TactiX 3000 backpack. Assistant provided detailed instructions on the location and functionality of the MOLLE system. Pending: Feedback on trying the instructions provided.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 11,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi, I recently purchased the TactiX 3000 backpack and I\\u0027m having trouble with the MOLLE system. Can you provide more information on how to properly attach accessories using the MOLLE system? Thanks.\"\n      },\n      {\n        \"MessageId\": 12,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The MOLLE system on the TactiX 3000 backpack allows you to easily attach pouches, pockets, and other accessories to expand the functionality of your backpack. This system is essential for increasing the carrying capacity and customizing the layout to suit your specific needs. According to the manual, it allows for complete customization of the pack\\u0027s layout without the need for additional tools or hardware. You can attach pouches for water bottles, first aid kits, or additional storage pockets. I hope this helps!\"\n      },\n      {\n        \"MessageId\": 13,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thanks for the information. I\\u0027ll give it a try and let you know how it goes.\"\n      },\n      {\n        \"MessageId\": 14,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The MOLLE system on the TactiX 3000 backpack is located on the front and sides of the pack, indicated by the rows of sturdy webbing in tactical black. It allows you to easily attach pouches, pockets, and other accessories to expand the functionality of your backpack. According to the manual, it allows for complete customization of the pack\\u0027s layout without the need for additional tools or hardware. You can attach pouches for water bottles, first aid kits, or additional storage pockets, enhancing the versatility of the backpack.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 103,\n    \"ProductId\": 25,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 6,\n    \"ShortSummary\": \"Tool issues resolved with guidance\",\n    \"LongSummary\": \"Customer had trouble with quick-release lever and attachments, but guidance helped resolve issues. No further assistance needed.\",\n    \"CustomerSatisfaction\": 8,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 15,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the TerraScoop Excavation Tool from DigDigDig and I\\u0027m having some trouble with it. I tried using the quick-release lever to adjust the angle and depth, but it doesn\\u0027t seem to be working at all. I was really looking forward to the convenience of this feature, so I\\u0027m quite disappointed. I also tried to attach some additional accessories as mentioned in the manual, but the tool doesn\\u0027t seem to accommodate them properly. I must say, I had high hopes for the versatility of this tool, but it\\u0027s not living up to my expectations. Can you please provide some guidance on how to make these features work? I really want to make the most out of my TerraScoop Excavation Tool. Thank you for your help.\"\n      },\n      {\n        \"MessageId\": 16,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Dear valued customer, thank you for reaching out to us about your experience with the TerraScoop Excavation Tool. We appreciate your feedback and are here to assist you. Based on the product manual, it seems that the TerraScoop Excavation Tool is designed to provide exceptional performance and versatility in outdoor applications. We understand your concerns about the quick-release lever and accommodation of additional accessories. To address this, we recommend checking the assembly and usage sections of the manual for detailed instructions and troubleshooting tips. If you need further assistance, please feel free to reach out to us. We are committed to ensuring your satisfaction with our products.\"\n      },\n      {\n        \"MessageId\": 17,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Oh, thank you for your response! I did try to follow the manual\\u0027s instructions again, but unfortunately, I\\u0027m still having the same issues with the quick-release lever and attaching additional accessories. I really want to make the most out of this tool, so I\\u0027m a bit disappointed that I\\u0027m still facing these difficulties. Could you provide more specific guidance on troubleshooting these problems? I appreciate your help!\"\n      },\n      {\n        \"MessageId\": 18,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Dear valued customer, according to the product manual, the quick-release lever is designed to allow for swift and effortless adjustment of the tool\\u0027s angle and depth. Simply depress the quick-release lever and move the TerraScoop Excavation Tool to your desired position, then release the lever to lock the tool in place. Additionally, for attaching additional accessories, please refer to section 6.2 of the manual for a comprehensive list of compatible attachments and instructions for their installation. We hope this guidance helps you make the most out of your TerraScoop Excavation Tool. If you need further assistance, please don\\u0027t hesitate to reach out to us. Thank you for choosing AdventureWorks!\"\n      },\n      {\n        \"MessageId\": 19,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the guidance! I followed the instructions again and I was finally able to adjust the angle and depth using the quick-release lever. It turns out I wasn\\u0027t pressing the lever down far enough before trying to move the tool. As for the accessories, I realized that I was trying to attach the wrong ones! I found the correct attachments and now everything seems to be working perfectly. I can\\u0027t believe I didn\\u0027t notice these simple mistakes before. Thank you for your help, I\\u0027m really happy with my TerraScoop Excavation Tool now!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 104,\n    \"ProductId\": 22,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 7,\n    \"ShortSummary\": \"Product care inquiry for Summit 45L Backpack\",\n    \"LongSummary\": \"Customer seeks guidance on cleaning and storing Summit 45L Technical Backpack. Assistant provided cleaning instructions and warranty details. No pending issues. Further assistance may be needed for specific product care advice.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 20,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the Peakpacker Summit 45L Technical Backpack for my store, and I\\u0027ve had a few customers asking about the proper way to clean and store the backpack. I realize I may not have provided clear instructions when selling the product, and I want to make sure our customers have all the information they need to care for their purchase. Can you provide some guidance on how to clean and store the backpack to maintain its quality and longevity? Any help would be greatly appreciated. Thanks!\"\n      },\n      {\n        \"MessageId\": 21,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"To clean the Summit 45L Technical Backpack, simply wipe it down with a damp cloth and mild soap, avoiding harsh chemicals or abrasive materials. You can also ensure that all straps are adjusted to fit your body comfortably before using the backpack for your adventure. For warranty and repair options, please refer to the user manual for detailed instructions. If you have any further questions, feel free to reach out to us.\"\n      },\n      {\n        \"MessageId\": 22,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information! I will make sure to clean the backpack as instructed and adjust the straps properly. If I encounter any further issues, I will reach out to you. Thanks again for your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 105,\n    \"ProductId\": 139,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 8,\n    \"ShortSummary\": \"GPS signal issues on SmartCyclo Bike Computer\",\n    \"LongSummary\": \"Customer is experiencing GPS signal issues with SmartCyclo Bike Computer. Asked for troubleshooting assistance despite proper configuration. Next agent should provide detailed troubleshooting steps.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 23,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear WheelWise Support Team,\\n\\nI recently purchased the SmartCyclo GPS Bike Computer and have been experiencing some trouble with the navigation feature. Despite being in open outdoor areas, the device seems to have difficulty connecting to a stable GPS signal. I have also checked and verified that the navigation settings are properly configured as per the manual. Could you please provide some troubleshooting assistance to resolve this issue? Thank you in advance for your help.\\n\\nSincerely, \\nEvelyn Park\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 106,\n    \"ProductId\": 10,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 9,\n    \"ShortSummary\": \"TechBeam 2000 brightness issue\",\n    \"LongSummary\": \"TechBeam 2000\\u0027s brightness feature not working. Customer considering refund or replacement. Assistant provided info on warranty coverage and troubleshooting. Next response should offer to initiate return or repair under warranty.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 24,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I can\\u0027t believe the TechBeam 2000 is acting up already! I just bought it and the brightness adjustment feature is not working as it should. I need reassurance that this product is reliable and will perform as advertised. If it doesn\\u0027t improve, I may have to consider a refund or replacement. This is really frustrating!\"\n      },\n      {\n        \"MessageId\": 25,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the TechBeam 2000 is covered by a limited warranty against defects in materials and workmanship for a period of one year from the date of purchase. If the brightness issue persists, you may be eligible for a return or repair under the warranty. For troubleshooting, it is essential to address the issues promptly to avoid any potential hazards or damage to the product.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 107,\n    \"ProductId\": 189,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 10,\n    \"ShortSummary\": \"Confusing usage instructions for emergency blanket and multi-tool\",\n    \"LongSummary\": \"Customer needs clear instructions for emergency blanket and multi-tool. Threatening refund. Next agent should provide detailed, step-by-step guide for both items.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 26,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am so frustrated with this Survivor Kit 2000! I can\\u0027t figure out how to use the emergency blanket and multi-tool. I need clear, step-by-step instructions that actually make sense. I spent good money on this kit and I expect it to be user-friendly. Can someone please help me with this before I demand a refund?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 108,\n    \"ProductId\": 179,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 11,\n    \"ShortSummary\": \"AquaPro 3000 kayak seat discomfort\",\n    \"LongSummary\": \"Customer is frustrated with the discomfort of the kayak seat and has tried adjusting it multiple times without success. Next agent should provide alternative solutions or offer to escalate the issue.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 27,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the AquaPro 3000 and have been experiencing some discomfort with the buoyant kayak seat. I\\u0027ve tried adjusting it following the manual\\u0027s instructions, but I still feel like I\\u0027m not getting the proper support. I\\u0027m starting to wonder if I\\u0027m doing something wrong, or if there\\u0027s an issue with the seat itself. I really want to enjoy my time on the water, so I\\u0027m hoping you can help reassure me that the product is behaving as expected. Any advice or guidance would be greatly appreciated. Thank you.\"\n      },\n      {\n        \"MessageId\": 28,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the AquaPro 3000\\u0027s buoyant kayak seat is designed to provide maximum comfort and stability. It can be adjusted using the adjustable straps located underneath the seat. You can pull on the straps to tighten or loosen the seat as needed. It\\u0027s also important to ensure that the kayak seat provides sufficient buoyancy before heading out on the water. Have you checked the seat for any visible signs of damage or wear that may affect its buoyancy?\"\n      },\n      {\n        \"MessageId\": 29,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027ve checked the seat for any signs of damage or wear, and everything looks fine. I\\u0027ve also tried adjusting the straps underneath the seat, but I\\u0027m still not feeling the proper support. I really want to enjoy my time on the water, so I\\u0027m starting to feel frustrated and disappointed. Is there anything else I can try to improve the comfort of the kayak seat?\"\n      },\n      {\n        \"MessageId\": 30,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Based on the product manual, to improve the comfort of the kayak seat, I recommend the following: - Sit in the kayak with the seat adjusted to your preferred position and ensure that it provides adequate support for your back and hips. - To adjust the kayak seat, locate the adjustment strap underneath the seat and pull the strap to loosen or tighten the seat according to your preference. Make sure the seat is secure before paddling. If you are still experiencing discomfort, please do not hesitate to contact PaddlePower customer service for further assistance.\"\n      },\n      {\n        \"MessageId\": 31,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I tried adjusting the kayak seat again following your instructions, but I\\u0027m still not getting the proper support. I really want to enjoy my time on the water, so I\\u0027m feeling quite frustrated and disappointed. Is there anything else I can try to improve the comfort of the kayak seat?\"\n      },\n      {\n        \"MessageId\": 32,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, ensure that the seat provides adequate support for your back and hips when sitting in the kayak. Additionally, check that the seat is securely fastened to the kayak before paddling. If you are still experiencing discomfort, please consider contacting PaddlePower customer service for further assistance.\"\n      },\n      {\n        \"MessageId\": 33,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I tried adjusting the kayak seat again following your instructions, but I\\u0027m still not getting the proper support. I really want to enjoy my time on the water, so I\\u0027m feeling quite frustrated and disappointed. Is there anything else I can try to improve the comfort of the kayak seat?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 109,\n    \"ProductId\": 72,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 12,\n    \"ShortSummary\": \"Technical inquiry on transducer functionality\",\n    \"LongSummary\": \"Retailer Eliot Chang seeks technical insight on transducer functionality in different water conditions for Angler\\u0027s Choice Pro Fish Finder 500. Pending question about transducer impact on accurate fish location.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 34,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Greetings, I am Eliot Chang from [Retailer Name]. As a fellow retailer of the Angler\\u0027s Choice Pro Fish Finder 500, I would like to engage in a technical discussion regarding the sonar technology integrated into this product. I am particularly interested in understanding the transducer mounting and its impact on accurate fish location. Can we delve into the intricacies of the transducer\\u0027s functionality in different water conditions? Your insights will not only benefit my own understanding but also assist in resolving customer queries effectively. Looking forward to a stimulating exchange of technical expertise.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 110,\n    \"ProductId\": 133,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 14,\n    \"ShortSummary\": \"Cleaning tips for MOLLE webbing and hydration system\",\n    \"LongSummary\": \"Retailer asks for MOLLE webbing \\u0026 hydration cleaning tips. Assistant provides detailed steps. Customer satisfied with results.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 38,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello Strategicgear, I am an authorized retailer who stocks the TactiX 3000 tactical backpack. I have been receiving enquiries from our customers regarding the care and maintenance of this product, particularly in relation to the MOLLE system and hydration compatibility. Could you provide detailed information on how to properly clean and maintain the MOLLE webbing, as well as the recommended cleaning process for the hydration bladder and hose? Our customers are eager to ensure the longevity and functionality of their TactiX 3000, and having comprehensive knowledge on these technical aspects will greatly assist us in addressing their concerns. Thank you for your assistance in this matter.\"\n      },\n      {\n        \"MessageId\": 39,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, it is important to clean the MOLLE system periodically, inspecting it for wear or fraying. If any damage is found, carefully trim any loose threads and reinforce the area with a small amount of clear adhesive. When it comes to cleaning the hydration bladder and hose, it is recommended to use a specialized hydration system cleaning kit to ensure thorough cleaning and to air dry the bladder and hose completely after cleaning. These steps will help ensure the longevity and functionality of the TactiX 3000. If you have further questions, feel free to reach out to us. Thank you for choosing Strategicgear and AdventureWorks Support.\"\n      },\n      {\n        \"MessageId\": 40,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information provided. I have followed the recommended steps for cleaning and maintaining the MOLLE system and the hydration bladder and hose. So far, the results have been satisfactory and our customers are pleased with the detailed instructions. I appreciate your prompt and thorough assistance in addressing our concerns. Please consider this enquiry resolved. Thank you.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 111,\n    \"ProductId\": 190,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 8,\n    \"ShortSummary\": \"Durability Concern with UltraLight Poles 300\",\n    \"LongSummary\": \"Customer Evelyn Park is unhappy with the durability of the UltraLight Poles 300, questioning the claimed quality and industry standards. She is seeking reassurance or a replacement.\",\n    \"CustomerSatisfaction\": 3,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 41,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I purchased the UltraLight Poles 300 and they claim to be durable, but mine already have noticeable dents after just a few uses. What kind of quality is this? I expect better from a product that claims to adhere to industry standards. I need reassurance that these poles are actually as durable as they claim to be, or I will be asking for a replacement.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 112,\n    \"ProductId\": 147,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 15,\n    \"ShortSummary\": \"Inquiry about underwater use\",\n    \"LongSummary\": \"Customer enquired about using SkyMaster X2000 underwater, was informed it\\u0027s only for aerial use. Requires assistance finding alternative for underwater footage.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 42,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I just bought the SkyMaster X2000 drone and I\\u0027m so excited to use it for capturing stunning underwater footage! I think it\\u0027s waterproof since it\\u0027s so advanced, right? I can\\u0027t wait to see the fish and coral reefs from a whole new perspective. Do you have any tips for using it underwater? Thanks so much!\"\n      },\n      {\n        \"MessageId\": 43,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The SkyMaster X2000 is designed for aerial photography and videography, featuring a high-quality 4K camera. For detailed specifications and technical information, please refer to the user manual. If you have specific questions about using the drone underwater, refer to the \\u0027SkyMaster X2000 user manual\\u0027 for guidance.\"\n      },\n      {\n        \"MessageId\": 44,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Oh, I didn\\u0027t realize the SkyMaster X2000 was only for aerial use! I guess I\\u0027ll have to find another way to capture underwater footage. Thanks for letting me know.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 113,\n    \"ProductId\": 200,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 16,\n    \"ShortSummary\": \"Raptor Tactical Backpack suitability for heavy loads\",\n    \"LongSummary\": \"Customer purchased Raptor Tactical Backpack without research. Asked if suitable for heavy loads. Received information on functionality and durability. Customer plans to try backpack on shorter hike first.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 45,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the Raptor Tactical Backpack for an upcoming hiking trip, and I\\u0027m wondering if it\\u0027s suitable for carrying heavy loads over long distances. I\\u0027m a bit embarrassed because I didn\\u0027t do any research before purchasing, so I\\u0027m not sure if it\\u0027s the right choice for my needs. Any information or advice would be greatly appreciated. Thank you!\"\n      },\n      {\n        \"MessageId\": 46,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Raptor Tactical Backpack is designed to meet the demanding requirements of modern missions and operations, with a focus on functionality, durability, and exceptional durability and functionality.\"\n      },\n      {\n        \"MessageId\": 47,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Oh, I feel so silly for not doing my research before purchasing. Thank you for the information! I\\u0027ll definitely keep that in mind and give the backpack a try on a shorter hike first. I\\u0027m sure it will work out just fine. Thanks again for your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 114,\n    \"ProductId\": 10,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 17,\n    \"ShortSummary\": \"Inquiry about emergency use\",\n    \"LongSummary\": \"Customer wants to use TechBeam 2000 for emergency communication and navigation but was advised it\\u0027s not suitable. Customer is now aware and may have other questions.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 48,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the TechBeam 2000 for my upcoming camping trip and I\\u0027m planning to use it as a signaling device in case of emergency. I\\u0027m confident that the adjustable brightness and long battery life will make it perfect for this unexpected purpose. Can you provide me with some tips on how to use it for emergency communication and navigation? Thanks so much!\"\n      },\n      {\n        \"MessageId\": 49,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry, but the TechBeam 2000 is not recommended for emergency communication and navigation. It is advised to seek alternative methods for these purposes. Your safety is our top priority, and we want to ensure you have reliable equipment for your camping trip. If you have any other questions or need further assistance, feel free to ask!\"\n      },\n      {\n        \"MessageId\": 50,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Oh, I didn\\u0027t realize that the TechBeam 2000 isn\\u0027t suitable for emergency communication and navigation. Thank you for letting me know! I\\u0027ll look into alternative methods for these purposes. If I have any other questions, I\\u0027ll be sure to reach out. Thanks again for your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 115,\n    \"ProductId\": 63,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 18,\n    \"ShortSummary\": \"Inquiry about Solar-Powered String Lights\",\n    \"LongSummary\": \"Evelyn Gardner inquires about product specifications, safety measures, and maintenance tips for Solar-Powered String Lights. The assistant provides detailed information and offers further assistance if needed.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 51,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear Luminartech team, I am reaching out on behalf of our retail store as we have received inquiries from our customers regarding the Solar-Powered String Lights. Can you please provide us with detailed information on the product specifications, including the safety measures for the solar panel and battery? Additionally, if there are any common maintenance issues or troubleshooting tips that we can pass on to our customers, it would be greatly appreciated. Thank you for your prompt assistance. Sincerely, Evelyn Gardner\"\n      },\n      {\n        \"MessageId\": 52,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Dear Evelyn Gardner, \\n\\nThank you for reaching out to us. According to the Luminartech Solar-Powered String Lights user manual, the solar panel should be placed in direct sunlight for at least 6-8 hours to fully charge the battery. It\\u0027s important to check the solar panel regularly to ensure it is not obstructed by any objects and to clean it if necessary. Additionally, inspect the rechargeable batteries and replace them if needed. For common maintenance, it\\u0027s recommended to store the lights in a safe, dry place when not in use to prevent damage and prolong their lifespan. If any troubleshooting is needed, please follow the steps provided in the manual. If further assistance is required, please feel free to contact Luminartech customer support. We hope this information is helpful for your customers. \\n\\nSincerely, \\nAdventureWorks Support\"\n      },\n      {\n        \"MessageId\": 53,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear AdventureWorks Support, thank you for your prompt response. We have implemented the recommendations provided in the user manual for the Solar-Powered String Lights. The information on product specifications and safety measures for the solar panel and battery is also very helpful. We will pass on this valuable information to our customers. If we encounter any further issues, we will not hesitate to reach out to Luminartech customer support. Sincerely, Evelyn Gardner\"\n      },\n      {\n        \"MessageId\": 54,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Dear Evelyn Gardner, \\n\\nThank you for your feedback. We\\u0027re thrilled to hear that the information provided in the user manual was helpful. If you have any further questions or need assistance in the future, please don\\u0027t hesitate to reach out to us. We\\u0027re here to help. \\n\\nSincerely, \\nAdventureWorks Support\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 116,\n    \"ProductId\": 61,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 19,\n    \"ShortSummary\": \"Inquiry about Satellite Communicator 2000 for Himalayas adventure\",\n    \"LongSummary\": \"Customer is excited about using the Satellite Communicator 2000 in the Himalayas and asked about its reliability in extreme altitudes and harsh weather. Assistant confirmed its suitability and advised to refer to the user manual for specific details. Customer is now all set for the adventure.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 55,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there Adventure Link team! I\\u0027m super excited about the Satellite Communicator 2000 and all its amazing features! I\\u0027m planning a big off-grid adventure and I need to know if this device will work in the Himalayas. Can it handle extreme altitudes and harsh weather conditions? I\\u0027ve heard it has an SOS feature that can be a real life-saver, but I want to make sure it\\u0027s reliable before I head out. Any info you can provide would be awesome! Thanks a bunch!\"\n      },\n      {\n        \"MessageId\": 56,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Satellite Communicator 2000 is built tough and can handle extreme altitudes and harsh weather conditions. However, for specific details on its performance in the Himalayas, please refer to the user manual. It is important to handle the device with care and store it in a cool, dry place away from direct sunlight and extreme temperatures when not in use.\"\n      },\n      {\n        \"MessageId\": 57,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! Thanks so much for the info! I checked the user manual and it looks like the Satellite Communicator 2000 is good to go for the Himalayas. I\\u0027m all set and ready to conquer those mountains! You guys are the best!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 117,\n    \"ProductId\": 150,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 20,\n    \"ShortSummary\": \"Sprayer troubleshooting for Outdoor Shield Pro\",\n    \"LongSummary\": \"Customer needs help troubleshooting sprayer issue on Outdoor Shield Pro. Asked about replacement if issue persists. Next agent should provide detailed troubleshooting steps or initiate replacement process if necessary.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 58,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the Outdoor Shield Pro from Buzzoff and I\\u0027m having trouble getting the sprayer to work. I\\u0027ve tried tightening the cap and checking for any debris, but it still won\\u0027t spray. I really rely on this product to keep bugs away during my camping trips, so I\\u0027d appreciate any help in getting it to work properly. Should I ask for a replacement? Thanks for your help!\"\n      },\n      {\n        \"MessageId\": 59,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hi there, based on the product manual, it\\u0027s recommended to ensure that the cap is securely tightened onto the bottle to prevent leakage and maintain the effectiveness of the repellent. Also, check that the nozzle is not clogged with any debris. If it is, rinse it with warm water and try spraying again. If you\\u0027ve already tried these steps and it\\u0027s still not working, please let us know and we\\u0027ll assist further.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 118,\n    \"ProductId\": 58,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 21,\n    \"ShortSummary\": \"Inquiry about GPS Locator for Hiking Trip\",\n    \"LongSummary\": \"Customer interested in SafeTrail GPS Locator for hiking trip. Asking about accuracy, reliability, and customizability of alerts. Pending response on specifics of alerts.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 60,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I\\u0027m interested in the SafeTrail GPS Locator from GuardianGear for my upcoming hiking trip. Can you provide more information on its accuracy and reliability in real-time tracking? Also, how customizable are the alerts? Thanks!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 119,\n    \"ProductId\": 64,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 22,\n    \"ShortSummary\": \"Water Purifier 1000 not working\",\n    \"LongSummary\": \"Customer reports Portable Water Purifier 1000 not working. Assistant asks if water reservoir filled and purification process followed. Pending response from customer.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 61,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I bought the Portable Water Purifier 1000 and it\\u0027s not working. Can you help me fix it or get a replacement?\"\n      },\n      {\n        \"MessageId\": 62,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I apologize for the inconvenience you\\u0027re experiencing with the Portable Water Purifier 1000. Have you tried filling the water reservoir and following the purification process as outlined in the manual? If that doesn\\u0027t resolve the issue, please let me know and I can help you further.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 120,\n    \"ProductId\": 24,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 8,\n    \"ShortSummary\": \"Sleeping Bag Rolling and Carrying Bag Repair Inquiry\",\n    \"LongSummary\": \"Customer inquired about issues with the Arctic Dream 0\\u00B0F Sleeping Bag. Support provided tips for rolling and repairing the carrying bag. Pending customer feedback.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 64,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear Base Camp Comfort team, \\n\\nI am reaching out on behalf of our retail store, and we have recently received some customer inquiries regarding the Arctic Dream 0\\u00B0F Sleeping Bag. Our customers have mentioned difficulties with rolling up the sleeping bag for storage, as well as issues with the carrying bag tearing. We would appreciate any advice or guidance you can provide to assist our customers with these concerns. Additionally, if there are any specific tips or techniques for addressing these issues, please do let us know. Thank you for your attention to this matter. We look forward to your prompt response. \\n\\nSincerely, \\nEvelyn Park\"\n      },\n      {\n        \"MessageId\": 65,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Dear Evelyn Park, \\n\\nThank you for reaching out to us regarding the Arctic Dream 0\\u00B0F Sleeping Bag. We understand the concerns your customers have raised and would like to offer some guidance to assist them. \\n\\n1. Rolling Up the Sleeping Bag: If they are having trouble rolling up the sleeping bag for storage, we recommend folding it along the existing creases and applying firm but gentle pressure to remove excess air. If the bag remains difficult to roll, they can consider using a larger storage sack or compression straps to aid in the packing process.\\n\\n2. Carrying Bag Tearing: If the carrying bag has torn, it can be repaired using a durable fabric patch and fabric glue. They should clean the torn area, apply the adhesive following the manufacturer\\u0027s instructions, and press the patch firmly in place. Allow sufficient time for the adhesive to dry before using the carrying bag again. \\n\\nAdditionally, for storing the sleeping bag, we recommend using a large cotton storage bag to allow the insulation to remain lofty, and to ensure the sleeping bag is completely clean and dry before storage to prevent mildew or odors from developing. \\n\\nWe hope this information is helpful. If your customers require further assistance, please do not hesitate to contact us. \\n\\nSincerely, \\nAdventureWorks Support\"\n      },\n      {\n        \"MessageId\": 66,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear AdventureWorks Support, Thank you for your prompt and thorough response. We will relay the information you provided to our customers and encourage them to try your suggestions. Should they encounter any further issues, we will be sure to reach out to you. Once again, thank you for your attention to this matter.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 121,\n    \"ProductId\": 37,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 24,\n    \"ShortSummary\": \"Customer frustrated with lack of clear instructions\",\n    \"LongSummary\": \"Customer frustrated with lack of clear instructions for whistle, compass, and poncho. Demands simple instructions. Needs clear, simple response with instructions for each tool.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 67,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am absolutely frustrated with this Wild Guard Outdoor First Aid Kit! I can\\u0027t understand how to use half of the items in here. It\\u0027s supposed to be compact and easy to use, but it\\u0027s just causing me more stress. I need clear instructions on how to use the whistle, compass, and emergency poncho. This is not what I expected when I made the purchase. Can someone please help me figure this out?\"\n      },\n      {\n        \"MessageId\": 68,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Wild Guard Outdoor First Aid Kit includes a variety of tools for outdoor safety. The bright red emergency whistle is used to signal for help in case of emergency. The reflective blanket can be used to stay warm and visible at night. Additionally, the compass in the kit is intended for general outdoor navigation. If you have any further questions about the use of these tools, please refer to the user manual for detailed instructions.\"\n      },\n      {\n        \"MessageId\": 69,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I don\\u0027t care about the user manual! I shouldn\\u0027t have to read a manual just to figure out basic survival tools. This is ridiculous. I demand clear and simple instructions that should have been provided with the kit in the first place!\"\n      },\n      {\n        \"MessageId\": 70,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, in the event of an emergency, the bright red emergency whistle included in the Wild Guard Outdoor First Aid Kit is used to signal for help. The reflective blanket is used to stay warm and visible at night. Additionally, when using the kit in remote areas, ensure that you have a method of communication and can provide clear directions to your location in case of an emergency. If you need further assistance, please feel free to reach out to us.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 122,\n    \"ProductId\": 158,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 25,\n    \"ShortSummary\": \"Demanding replacement for HydraHike Hydration Pack\",\n    \"LongSummary\": \"Customer demands a replacement or full refund for the HydraHike Hydration Pack, insisting it should be able to carry a laptop and books. Customer is dissatisfied with the product\\u0027s functionality and expects immediate action.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 71,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I demand that you provide me with a replacement HydraHike Hydration Pack immediately! I tried to use it to carry my laptop and some books, but the compartments aren\\u0027t big enough. This is unacceptable and I expect you to rectify this situation immediately.\"\n      },\n      {\n        \"MessageId\": 72,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Thank you for reaching out to us. According to the manual, the HydraHike Hydration Pack is designed with multiple pockets and compartments, including a special one for your phone, one for snacks, and one for your keys. It is primarily intended for hydration and may not be suitable for carrying a laptop and books. If you have any further questions or need assistance with another product, feel free to ask. Have a great day!\"\n      },\n      {\n        \"MessageId\": 73,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I don\\u0027t care about the manual! I expect the hydration pack to be able to carry my laptop and books, and it\\u0027s not doing that. This is unacceptable and I demand a replacement or a full refund immediately!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 123,\n    \"ProductId\": 49,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 26,\n    \"ShortSummary\": \"Hiking boots scuffed at fancy dinner party\",\n    \"LongSummary\": \"Customer is upset that the hiking boots got scuffed at a fancy dinner party. Asked for refund or replacement. Assistant recommended reaching out to TrekMaven support for warranty details.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 74,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I can\\u0027t believe the manual says these boots are for rugged terrain and tough landscapes. I wore them to a fancy dinner party and they got scuffed up! This is not what I expected. I demand a refund or replacement for these so-called \\u0027hiking boots\\u0027.\"\n      },\n      {\n        \"MessageId\": 75,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Summit Hiking Boots are designed for rugged terrain and tough landscapes, and they are also equipped with waterproof protection to keep your feet dry and comfortable in wet conditions. There is a section in the manual about unboxing the boots and getting started. However, I couldn\\u0027t find specific warranty information. I recommend reaching out to TrekMaven support for warranty details.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 124,\n    \"ProductId\": 120,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 27,\n    \"ShortSummary\": \"Inquiry about waterproofing and zipper strength\",\n    \"LongSummary\": \"Customer inquiring about ArcticPro jacket waterproofing, sealing, and zipper strength specifications. Customer will conduct tests and contact manufacturer if needed.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 76,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I am considering purchasing the ArcticPro Insulated Ski Jacket by Frost Flare for my upcoming ski trip. I would like to inquire about the waterproofing and sealing features of the jacket. Can you provide detailed information on the effectiveness of the waterproof membrane and the standard waterproofing tester used for conducting the water penetration test? Additionally, I am interested in the seam sealing techniques outlined in research paper RP-ARCTICPRO-SEAM. Any insight on the zipper strength specifications and the industry-approved zipper tester would be greatly appreciated as well. Thank you for your assistance.\"\n      },\n      {\n        \"MessageId\": 77,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The ArcticPro Insulated Ski Jacket is designed with FrostShield technology to repel moisture and keep you dry, providing reliable protection against snow, sleet, and rain with a minimum water column resistance of 20,000 mm. In case of waterproofing and sealing issues, troubleshooting steps are outlined in the manual. Additionally, the zipper functionality can be tested using an industry-approved zipper tester, and standard code IS-ARCTICPRO-ZIP provides zipper strength specifications. If you require further assistance, feel free to contact the manufacturer\\u0027s support as outlined in the user manual.\"\n      },\n      {\n        \"MessageId\": 78,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information provided. I have reviewed the manual and found the troubleshooting steps for waterproofing and sealing issues. I will conduct the water penetration test using the industry-approved waterproofing tester as per your suggestion. I will also test the zipper functionality using the industry-approved zipper tester and compare the results with the specifications outlined in code IS-ARCTICPRO-ZIP. I appreciate your assistance and will contact the manufacturer\\u0027s support if further help is needed.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 125,\n    \"ProductId\": 164,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 28,\n    \"ShortSummary\": \"Trouble with Excavator Pro 8000 attachment tilt \\u0026 rotation\",\n    \"LongSummary\": \"Customer is struggling with operating the attachment tilt and rotation on the Excavator Pro 8000. They have read the manual but still need guidance. They are looking for someone to walk them through the process or provide some guidance. They want to ensure they are using the equipment properly.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 79,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the MantleMaster Excavator Pro 8000 and I\\u0027m having some trouble with operating the attachment tilt and rotation. I feel like I must be doing something wrong and I\\u0027m a bit embarrassed to admit it. I\\u0027ve tried reading through the manual, but I\\u0027m still struggling. Is there anyone who can walk me through the process or provide some guidance? I really want to make sure I\\u0027m using this equipment properly. Thank you for your help.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 126,\n    \"ProductId\": 100,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 29,\n    \"ShortSummary\": \"Quality and Durability Inquiry\",\n    \"LongSummary\": \"Customer requests detailed info on accessing water and durability of tube and bite valve. Response needed about the quality and durability of the tube and bite valve.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 80,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I need to know exactly how easy it is to access the water while wearing the Ridge Runner Hydration Pack. I expect a detailed response before I make a purchase. And it better be good!\"\n      },\n      {\n        \"MessageId\": 81,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, to access water while wearing the Ridge Runner Hydration Pack, you simply use the attached tube and bite valve. Sip from the valve and stay refreshed during all of your outdoor adventures!\"\n      },\n      {\n        \"MessageId\": 82,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I demand more information about the quality and durability of the tube and bite valve. I need to know that they won\\u0027t break or leak after just a few uses. This is important to me!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 127,\n    \"ProductId\": 66,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 30,\n    \"ShortSummary\": \"Broken beach tent replacement request\",\n    \"LongSummary\": \"Customer needs replacement for broken beach tent, warranty discussed, urgency expressed.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 83,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Tent broke at the beach. Need help fixing or replacing it.\"\n      },\n      {\n        \"MessageId\": 84,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry to hear about the issue with your SunSafe Pop-Up Beach Tent. The tent is designed for sun protection and is not recommended for use in inclement weather. If the tent has suffered damage due to extreme weather or misuse, it may not be covered under the warranty. However, if the damage is due to a manufacturing defect, it may be covered for up to 6 months from the date of purchase. If you have any further questions or need assistance, please don\\u0027t hesitate to contact Shade Scape Customer Support for help.\"\n      },\n      {\n        \"MessageId\": 85,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Tent is definitely broken. Need a replacement ASAP.\"\n      },\n      {\n        \"MessageId\": 86,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We understand that the tent is broken, and we apologize for any inconvenience this has caused. According to the limited warranty provided by Shade Scape, manufacturing defects are covered for up to 6 months from the date of purchase. However, please note that any modifications made to the tent will void the warranty. If you believe the damage is due to a manufacturing defect, please contact Shade Scape Customer Support for further assistance.\"\n      },\n      {\n        \"MessageId\": 87,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Tent still broken. Need replacement now.\"\n      },\n      {\n        \"MessageId\": 88,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We understand your urgency and apologize for the inconvenience. According to the limited warranty, manufacturing defects are covered for up to 6 months from the date of purchase. It\\u0027s important to note that the SunSafe Pop-Up Beach Tent is intended for sun protection and is not suitable for use in inclement weather. If you believe the damage is due to a manufacturing defect, please contact Shade Scape Customer Support for further assistance. You can find their contact details in the user manual.\"\n      },\n      {\n        \"MessageId\": 89,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Tent still broken. Want replacement now.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 128,\n    \"ProductId\": 102,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 31,\n    \"ShortSummary\": \"Defective kayak paddle, seeking refund\",\n    \"LongSummary\": \"Customer is experiencing issues with Voyager Kayak Paddle, followed manual, still not working. Asked for fix or replacement. Assistant suggested initiating a return for refund.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Returns\",\n    \"Messages\": [\n      {\n        \"MessageId\": 90,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Paddle doesn\\u0027t work, need help. Fix or replace.\"\n      },\n      {\n        \"MessageId\": 91,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"When attaching the Voyager Kayak Paddle to the kayak, it\\u0027s crucial for stability and maneuverability. Follow the steps outlined in the manual for proper attachment. If you are still experiencing issues, please let us know for further assistance.\"\n      },\n      {\n        \"MessageId\": 92,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Tried following the manual, still not working. Please fix or replace.\"\n      },\n      {\n        \"MessageId\": 93,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Thank you for providing feedback on the Voyager Kayak Paddle. We understand that you\\u0027ve followed the manual, and we apologize for any inconvenience caused. Please initiate a return for a refund as the paddle seems to be defective. You can do this within 1 year of purchase at: [Support Returns](https://northernmountains.example.com/support/returns). If you need further assistance, please let us know.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 129,\n    \"ProductId\": 150,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 32,\n    \"ShortSummary\": \"Outdoor Shield Pro Effectiveness Issue\",\n    \"LongSummary\": \"Customer Evelyn Chang is experiencing issues with Buzzoff\\u0027s Outdoor Shield Pro effectiveness against bugs. She followed the instructions and reapplied as needed, but still getting bitten. She\\u0027s seeking guidance on making the product work more effectively.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 94,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Outdoor Shield Pro from Buzzoff and I\\u0027m experiencing some issues with its effectiveness. I followed the instructions and reapplied as needed, but I still found myself getting bitten by bugs. I was hoping to get some guidance on how to make the product work more effectively, as I really want to be able to enjoy my outdoor activities without the nuisance of insects. Thank you for your help.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 130,\n    \"ProductId\": 142,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 34,\n    \"ShortSummary\": \"Urgent Hammock Replacement Request\",\n    \"LongSummary\": \"Customer is extremely disappointed with the UltraLight Camping Hammock. Demands a prompt solution, either a refund or replacement. Wants to escalate the issue and expects a swift response.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 98,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am extremely disappointed with the Dreamscape UltraLight Camping Hammock. It doesn\\u0027t work at all and I demand a solution to this problem immediately. I spent good money on this product and expected it to live up to its description of being \\u0027perfect for backpacking and adventure travel\\u0027. It\\u0027s a complete letdown and I want either a refund or a replacement. This is unacceptable and I expect a prompt response and resolution to this issue.\"\n      },\n      {\n        \"MessageId\": 99,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We apologize for the inconvenience you\\u0027ve experienced with the Dreamscape UltraLight Camping Hammock. We are committed to resolving this issue promptly. According to the product manual, the hammock should be stored properly when not in use to keep it in top condition. Additionally, it provides instructions for unboxing and hanging the hammock. We will also investigate the warranty and troubleshooting information for further assistance. Thank you for your patience.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 131,\n    \"ProductId\": 37,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 35,\n    \"ShortSummary\": \"Wildlife Safety Procedures Inquiry\",\n    \"LongSummary\": \"Customer inquired about wildlife safety procedures when using the first aid kit. Assistant provided detailed information and customer is now prepared. No further questions at the moment.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 100,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Wild Guard Outdoor First Aid Kit and I noticed in the manual that it mentions being cautious of wildlife encounters. I understand the importance of wildlife safety, but I\\u0027m a bit concerned about the specific precautions mentioned. Can you provide more detailed information on this? Thank you.\"\n      },\n      {\n        \"MessageId\": 101,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, when using the Wild Guard Outdoor First Aid Kit in natural surroundings, it\\u0027s important to be cautious of wildlife encounters and familiarize yourself with wildlife safety procedures. Additionally, you should carry any necessary items for wildlife encounters. If you have any further questions or concerns, feel free to ask.\"\n      },\n      {\n        \"MessageId\": 102,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for providing the information. I have familiarized myself with the wildlife safety procedures and will ensure to carry the necessary items. If I have any further questions, I will reach out. Have a great day!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 132,\n    \"ProductId\": 152,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 36,\n    \"ShortSummary\": \"Non-functional Emergency Beacon Light\",\n    \"LongSummary\": \"Customer is requesting a replacement or refund for the non-functional Emergency Beacon Light. They have tried all troubleshooting steps and are insistent on a resolution ASAP.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Returns\",\n    \"Messages\": [\n      {\n        \"MessageId\": 103,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I just bought this Sure Survive Emergency Beacon Light and it\\u0027s not turning on at all. I made sure the batteries are in properly and fully charged, so don\\u0027t tell me to check that again. Also, I didn\\u0027t see anything in the description about it not working right out of the box. It\\u0027s ridiculous that I have to deal with this. I want a replacement or a refund ASAP!\"\n      },\n      {\n        \"MessageId\": 104,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"It seems that there are common troubleshooting issues and potential solutions for the Sure Survive Emergency Beacon Light. If you are still experiencing problems after performing troubleshooting, you can contact the Sure Survive customer support team for further assistance at:\\n- Phone: 1-800-SURVIVE\\n- Email: support@suresurvive.com\"\n      },\n      {\n        \"MessageId\": 105,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I already tried all the troubleshooting steps and nothing worked. I need a replacement or a refund ASAP, I don\\u0027t want to waste any more time on this.\"\n      },\n      {\n        \"MessageId\": 106,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry that you\\u0027re still experiencing issues with the Sure Survive Emergency Beacon Light. According to the manual, if the light becomes submerged in water, do not use it until it has been thoroughly dried and inspected for any damage. If you\\u0027ve already attempted troubleshooting and are still having problems, I recommend contacting Sure Survive\\u0027s customer support team for further assistance. You can reach them at 1-800-SURVIVE or via email at support@suresurvive.com. They will be able to provide additional support and guidance.\"\n      },\n      {\n        \"MessageId\": 107,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I already told you I tried all the troubleshooting steps and nothing worked. I need a replacement or a refund ASAP, I don\\u0027t want to waste any more time on this. And don\\u0027t give me that nonsense about the light being submerged in water, it\\u0027s never been near water! Just sort this out for me now.\"\n      },\n      {\n        \"MessageId\": 108,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I understand that you have tried all troubleshooting steps and are still experiencing issues. According to the manual, if the light becomes submerged in water, it should not be used until it has been thoroughly dried and inspected for any damage. Since you have already attempted troubleshooting, you may be eligible for a warranty return or repair. You can initiate a return at https://northernmountains.example.com/support/returns, or contact Sure Survive\\u0027s customer support team for further assistance at 1-800-SURVIVE or via email at support@suresurvive.com.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 133,\n    \"ProductId\": 19,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 37,\n    \"ShortSummary\": \"Technical issue with Lumina LED Lantern\",\n    \"LongSummary\": \"Customer having trouble with Lumina LED Camping Lantern, followed instructions for troubleshooting, still not working. Requires further technical assistance from NightBeacon.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 109,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi, I just bought the Lumina LED Camping Lantern and I\\u0027m having some trouble using it. It\\u0027s not working as I expected. Can you help me figure out what\\u0027s wrong?\"\n      },\n      {\n        \"MessageId\": 110,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Lumina LED Camping Lantern features a maximum light output of 1000 lumens, providing powerful illumination for your campsite. The beam pattern is designed to evenly distribute light in a 360-degree radius, ensuring optimal visibility in all directions. The adjustable brightness settings allow for customized light output to suit various lighting needs. Before installing or replacing batteries, it is essential to ensure that the Lumina LED Camping Lantern is disconnected from any power source. If you have further questions or need assistance with troubleshooting, feel free to reach out.\"\n      },\n      {\n        \"MessageId\": 111,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I tried disconnecting the lantern from any power source before replacing the batteries, but it\\u0027s still not working. Can you provide further assistance with troubleshooting?\"\n      },\n      {\n        \"MessageId\": 112,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I understand that you have already disconnected the lantern from any power source before replacing the batteries. The manual specifies that the Lumina LED Camping Lantern requires specific battery type and size for optimal performance. It\\u0027s important to only use the recommended batteries to avoid damage and voiding the warranty. If the issue persists, please contact a certified NightBeacon technician for assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 134,\n    \"ProductId\": 83,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 30,\n    \"ShortSummary\": \"Trouble activating GPS tracking for SkyRanger HD Drone\",\n    \"LongSummary\": \"Customer purchased SkyRanger HD Aerial Drone and is having trouble activating GPS tracking. Confused by manual and indicator light not turning green. Requesting clear explanation. Pending response needed on how to activate GPS tracking.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 113,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I just bought the SkyRanger HD Aerial Drone and I can\\u0027t figure out how to activate the GPS tracking. The manual is so confusing and I\\u0027ve followed the steps but the indicator light never turns green! I\\u0027m starting to think this feature is just a gimmick. Can someone please explain it in a way that actually makes sense?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 135,\n    \"ProductId\": 128,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 38,\n    \"ShortSummary\": \"Insulation problem with AquaBottle Pro\",\n    \"LongSummary\": \"Customer is experiencing issues with AquaBottle Pro insulation. Need to troubleshoot and determine if issue is user error or product defect. Urgent response needed to address customer\\u0027s reliance on the product for outdoor activities.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 114,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the AquaBottle Pro from AquaNest and I\\u0027m having some trouble with it. I filled it with water, but it\\u0027s not staying cold like it\\u0027s supposed to. I thought it was supposed to be really well insulated, but it doesn\\u0027t seem to be working at all. I\\u0027m not sure if I\\u0027m doing something wrong or if there\\u0027s a problem with the bottle itself. Can you help me figure out what\\u0027s going on? I rely on having a reliable water bottle for my outdoor activities, so I really need this to work properly. Thanks for your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 136,\n    \"ProductId\": 174,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 39,\n    \"ShortSummary\": \"Inquiry about microphone and voice control features\",\n    \"LongSummary\": \"Customer is seeking detailed technical specs on external microphone support and voice control. Prompt and comprehensive response needed for purchasing decision.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 115,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I am considering purchasing the AdventureX 4K Action Camera for capturing my outdoor activities. I am particularly interested in the external microphone support and voice control features mentioned in the description. Can you provide detailed technical specifications for the external microphone support, including compatibility with different microphone types and brands? Additionally, I would like to know more about the voice control feature, such as the range and accuracy of voice commands. It is essential for me to ensure that this camera is suitable for professional-grade audio and hands-free operation. Your prompt and detailed response would greatly assist me in making an informed decision about this purchase. Thank you.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 137,\n    \"ProductId\": 151,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 40,\n    \"ShortSummary\": \"Survivor Multi-Tool usage and maintenance\",\n    \"LongSummary\": \"Customer inquired about starting a fire in wet conditions and maintaining the Survivor Multi-Tool. Provided detailed instructions. Pending: Customer testing suggestions and possible follow-up questions.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 116,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the Survivor Multi-Tool and I\\u0027m wondering if it\\u0027s suitable for starting a fire in wet conditions? Also, is there any maintenance I need to do to keep the fire starter and knife working effectively? Thanks for your help.\"\n      },\n      {\n        \"MessageId\": 117,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, to start a fire in wet conditions, ensure the surface of the fire starter is dry and strike firmly and consistently along the length of the fire starter rod. Also, please keep the area around the fire starter clear of any flammable materials for safety precautions. To maintain the efficiency of the fire starter, periodically clean the rod and striker to remove any buildup of debris. Additionally, ensure that the protective cover is securely closed to prevent accidental activation.\"\n      },\n      {\n        \"MessageId\": 118,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thanks for the information. I will try your suggestions and let you know if I have any more questions.\"\n      },\n      {\n        \"MessageId\": 119,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, to maintain the Survivor Multi-Tool, regularly clean and oil the moving parts to ensure smooth operation. Keep the blades sharp and replace any worn or damaged parts as soon as possible. Store the multi-tool in a dry place and avoid exposure to extreme temperatures or moisture. For starting a fire in wet conditions, hold the tool with the fire starter facing down, and then using the back of the knife blade, strike the fire starter rod to create sparks that can be used to start a fire. Always handle the Survivor Multi-Tool with care, keeping your fingers away from the sharp edges of the knife and saw. Do not use the fire starter near flammable materials and always make sure it is fully extinguished after use. If you have any more questions, feel free to ask. Thank you!\"\n      },\n      {\n        \"MessageId\": 120,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thanks for the information. I will try your suggestions and let you know if I have any more questions.\"\n      },\n      {\n        \"MessageId\": 121,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Survivor Multi-Tool is a versatile and durable tool designed to help in survival situations. It features a knife, saw, fire starter, and more. With its compact design, it is easy to carry with you on outdoor adventures. Whether you are camping, hiking, or facing an emergency situation, the Survivor Multi-Tool is designed to help you in your time of need. If you have any more questions or need further assistance, feel free to ask. Thank you!\"\n      },\n      {\n        \"MessageId\": 122,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thanks for the help. I will try out the Survivor Multi-Tool on my next camping trip and let you know if I have any more questions.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 138,\n    \"ProductId\": 148,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 41,\n    \"ShortSummary\": \"Cold spots in Alpine Dream 3000 sleeping bag\",\n    \"LongSummary\": \"Customer frustrated with Alpine Dream 3000 sleeping bag, experiencing cold spots. Asks if common issue and for solution or refund. Next agent needs to address cold spots issue and recommend solution or refund.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 123,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am so frustrated with my Alpine Dream 3000 sleeping bag from Slumberpeak. I bought it for cold weather camping, but I keep getting cold spots in it! I tried shaking it like the manual said, but it\\u0027s not helping. I need this bag to keep me warm, and it\\u0027s failing miserably. I want to know if this is a common issue and if there\\u0027s a solution, or if I should just return it for a refund. This is not what I expected from a supposedly high-quality product.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 139,\n    \"ProductId\": 154,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 42,\n    \"ShortSummary\": \"Waterproof Rating Confirmation\",\n    \"LongSummary\": \"Customer inquiring about waterproof rating for GuardianGear GPS Personal Locator. Assistant confirmed IPX7 rating. Customer satisfied with response.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 124,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there! I\\u0027m thinking about getting the GuardianGear GPS Personal Locator for my upcoming hiking trip, and I just wanted to make sure it will work even if I accidentally drop it in water. I saw that it\\u0027s for outdoor safety, so I\\u0027m hoping it\\u0027s waterproof. Can you please let me know? Thanks so much!\"\n      },\n      {\n        \"MessageId\": 125,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The GuardianGear GPS Personal Locator has a waterproof rating of IPX7, so it is designed to withstand accidental exposure to water. You can confidently take it on your hiking trip without worrying about water damage.\"\n      },\n      {\n        \"MessageId\": 126,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Oh, that\\u0027s great to hear! I feel a lot better knowing that it\\u0027s waterproof. Thank you so much for your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 140,\n    \"ProductId\": 85,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 44,\n    \"ShortSummary\": \"Faulty waterproof matches in fire starter kit\",\n    \"LongSummary\": \"Customer is dissatisfied with the waterproof matches in the fire starter kit failing to light. Customer demands a refund or replacement. Assistant provided usage tips and support contact info.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 128,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I can\\u0027t believe the matches in the All-Weather Fire Starter Kit failed to light on my camping trip! I specifically bought this kit for its waterproof matches and now I\\u0027m left without a reliable source of fire. What\\u0027s the point of advertising a product as all-weather if it can\\u0027t withstand a little moisture? I demand a refund or replacement for this faulty product.\"\n      },\n      {\n        \"MessageId\": 129,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The All-Weather Fire Starter Kit includes waterproof matches, and it\\u0027s important to maintain their waterproof properties by keeping them in their original packaging and avoiding exposure to moisture. If you identify any irregularities, refrain from using the matches and contact customer service for assistance. The manual does not provide specific information about the product return policy or manufacturer contact details.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 141,\n    \"ProductId\": 120,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 45,\n    \"ShortSummary\": \"ArcticPro Ski Jacket Phone Pocket Inquiry\",\n    \"LongSummary\": \"Customer inquired about phone pocket in ArcticPro ski jacket, received confirmation of internal storage pockets. Customer plans to try jacket on slopes, pending feedback.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 130,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, does the ArcticPro ski jacket have a special pocket for my phone? Like, can it fit my phone and keep it safe while I\\u0027m skiing? Thx\"\n      },\n      {\n        \"MessageId\": 131,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The ArcticPro Insulated Ski Jacket is equipped with thoughtful storage pockets to accommodate mobile devices, including a special pocket for keeping your phone safe while skiing. According to the manual, the jacket is designed to provide maximum warmth and comfort in cold weather conditions and is specifically intended for use in snowsports activities such as skiing. If you have any other questions, feel free to ask!\"\n      },\n      {\n        \"MessageId\": 132,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thx! I\\u0027ll def try it out on the slopes and let u know how it goes.\"\n      },\n      {\n        \"MessageId\": 133,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The product manual confirms that the ArcticPro ski jacket includes internal storage pockets for stashing your phone, wallet, and other valuables, keeping them safe and easily accessible. Have a great time on the slopes!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 142,\n    \"ProductId\": 190,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 46,\n    \"ShortSummary\": \"Adjusting UltraLight Poles 300 height mechanism\",\n    \"LongSummary\": \"Customer inquires about proper adjustment of UltraLight Poles 300. Assistant provides details on how to adjust and secure the height setting according to DIN 15562-4:2009 standard. Customer will try suggested method and provide feedback.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 134,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi, I recently purchased the UltraLight Poles 300 and I have a question about the height adjustment mechanism. Can you provide me with more information on how to properly adjust and secure the height setting? Thank you.\"\n      },\n      {\n        \"MessageId\": 135,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"To adjust the height of the UltraLight Poles 300, start by extending the carbon pole to your desired height, ensuring that the height adjustment markings are aligned. The poles feature adjustable height settings for personalized comfort and support. The height adjustment mechanism meets the requirements set forth in the DIN 15562-4:2009 standard for telescopic trekking and walking poles.\"\n      },\n      {\n        \"MessageId\": 136,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information. I will try adjusting the poles as you suggested and let you know if it worked.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 143,\n    \"ProductId\": 138,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 47,\n    \"ShortSummary\": \"Replacement key needed for Ultimate Survival Kit 3000\",\n    \"LongSummary\": \"Customer needs a replacement key for the Ultimate Survival Kit 3000. Pending question about specific shipping details. Next agent should confirm shipping details and process replacement key.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 137,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, I need help with the Ultimate Survival Kit 3000. Can\\u0027t find the key to unlock the box. Can you send a replacement? Thanks!\"\n      },\n      {\n        \"MessageId\": 138,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Ultimate Survival Kit 3000 is designed to provide you with peace of mind during your outdoor activities. It includes essential tools and gear for outdoor survival, making it the ideal companion for any adventure. If you have any specific questions about the kit, feel free to ask!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 144,\n    \"ProductId\": 154,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 48,\n    \"ShortSummary\": \"Request for Outdoor Functionality Information\",\n    \"LongSummary\": \"Customer expresses gratitude for GPS Personal Locator features and asks for more information on its outdoor functionality. Assistant provides details on live tracking, SOS button, and battery life, and refers to official user manual for further guidance. Pending question: how well does it work for outdoor activities?\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 139,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there GuardianGear team! Just wanted to say a HUGE thank you for creating such an awesome GPS Personal Locator. I\\u0027m all about safety and staying connected, so the live tracking and SOS button features are like a dream come true for me. I\\u0027m planning some outdoor adventures and this device seems perfect for keeping me safe. Can you tell me more about how well it works for outdoor activities? Thanks so much for your help, you guys rock!\"\n      },\n      {\n        \"MessageId\": 140,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The GuardianGear GPS Personal Locator is designed to keep you safe and connected during outdoor adventures. It features live tracking, an SOS button, and a long battery life, providing you with the peace of mind you deserve while exploring the great outdoors. For detailed instructions and guidance on utilizing the features of the GPS Personal Locator, please refer to the official user manual.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 145,\n    \"ProductId\": 79,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 49,\n    \"ShortSummary\": \"Inquiry about camera\\u0027s video recording risks\",\n    \"LongSummary\": \"Customer seeks detailed info on risks in adventure video recording with the camera. Pending question: impact on video quality and user safety. Thorough response needed.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 141,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I am interested in purchasing the Adventure Pro Camera for adventure photography, but I have some concerns regarding its video recording capabilities. The 4.2 section of the manual seems to suggest that the camera is not suitable for recording videos due to potential safety hazards and malfunctioning image stabilization. Can you provide more information on this? I am particularly interested in understanding if the camera can be safely used for recording adventure videos and if the advanced features such as image stabilization and 4K resolution pose any risks or limitations in this scenario. Your prompt and detailed response would greatly influence my decision to purchase this product. Thank you.\"\n      },\n      {\n        \"MessageId\": 142,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Adventure Pro Camera is not suitable for recording videos. The advanced image stabilization feature may not function properly, resulting in distorted or shaky video footage. In addition, the 4K resolution capabilities of the camera may pose a risk to the user and those in the vicinity. Therefore, we strongly advise against using this camera for video recording purposes in adventure settings. If you require further assistance, please let us know.\"\n      },\n      {\n        \"MessageId\": 143,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for your response. I appreciate the information provided, but I would like to delve deeper into the technical specifications of the image stabilization feature and 4K resolution capabilities. Can you provide a detailed explanation of how these features may pose risks in adventure video recording scenarios? I am particularly interested in understanding the potential impact on video quality and user safety. Your thorough response will greatly assist me in making an informed decision about the purchase. Thank you.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 146,\n    \"ProductId\": 29,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 50,\n    \"ShortSummary\": \"Trouble charging phone with SolarBoost Power Bank\",\n    \"LongSummary\": \"Customer is experiencing trouble charging their phone with the SolarBoost Power Bank. Will try the reset button first. If that doesn\\u0027t work, may need technical support for solar power charging.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 144,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the SolarBoost Power Bank from Ecovolt and I\\u0027m having some trouble with it. I\\u0027ve been trying to charge my phone with it, but it\\u0027s not responding at all. I didn\\u0027t know about the reset button mentioned in the manual, so I\\u0027ll give that a try. If that doesn\\u0027t work, I might need some technical support. I really love the idea of charging my devices with solar power, so I hope I can get it working again. Thank you!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 147,\n    \"ProductId\": 147,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 51,\n    \"ShortSummary\": \"Battery issue demands immediate resolution\",\n    \"LongSummary\": \"Customer demands immediate resolution to battery issue, refusing to visit website or contact customer support. Assistant advises on battery charging and replacement procedures.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 145,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am absolutely furious with the battery life on my SkyMaster X2000! It\\u0027s advertised as having a 30-minute flight time, but I can barely get it to last 15 minutes. I spent so much money on this drone and now I feel like I\\u0027ve been misled. I demand a refund or a replacement with a properly functioning battery. This is completely unacceptable.\"\n      },\n      {\n        \"MessageId\": 146,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, for additional support and resources, including user manuals and instructional videos, please visit www.aerovision.com/support. You can also contact AeroVision customer support for assistance at 1-800-AERO-123 or email support@aerovision.com.\"\n      },\n      {\n        \"MessageId\": 147,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I don\\u0027t want to visit a website or contact customer support. I just want the battery issue resolved immediately. This is ridiculous!\"\n      },\n      {\n        \"MessageId\": 148,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Based on the manual, it\\u0027s important to ensure that the battery is properly charged and securely inserted into the drone. The LED indicator will light up red when charging and turn green when the battery is fully charged. Additionally, if the battery is damaged, it should be replaced. If you have followed these steps and are still experiencing battery issues, please let us know so we can assist you further.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 148,\n    \"ProductId\": 43,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 52,\n    \"ShortSummary\": \"Troubleshooting strobe mode\",\n    \"LongSummary\": \"Customer needs help with strobe mode on NightOps Tactical Flashlight. Specific details on how to operate requested. Pending response for troubleshooting steps.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 149,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Flashlight not working right. Need help with strobe mode.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 149,\n    \"ProductId\": 124,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 53,\n    \"ShortSummary\": \"Maintenance guidance for SurvivalPro 2000\",\n    \"LongSummary\": \"Customer sought guidance on proper maintenance for SurvivalPro 2000. Assistant provided instructions and customer successfully followed them. No further assistance needed.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 150,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the SurvivalPro 2000 and I\\u0027m having some trouble understanding how to properly maintain and inspect the gear. I want to make sure I\\u0027m following the safety guidelines, but I\\u0027m feeling a bit embarrassed that I can\\u0027t figure it out on my own. Any guidance or tips would be greatly appreciated. Thank you!\"\n      },\n      {\n        \"MessageId\": 151,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, it is advisable to periodically check the functionality and integrity of all tools and components of your SurvivalPro 2000. It is also recommended to clean and maintain the gear according to the instructions in the user manual to ensure that it remains in top working condition. Regular maintenance will help keep the product in the most impeccable state.\"\n      },\n      {\n        \"MessageId\": 152,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information. I will review the user manual again and try to follow the maintenance instructions more closely. I hope I can figure it out this time. I\\u0027ll let you know if I still have trouble. Thank you for your help.\"\n      },\n      {\n        \"MessageId\": 153,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, it is advisable to periodically check the functionality and integrity of all tools and components of your SurvivalPro 2000. It is also recommended to clean and maintain the gear according to the instructions in the user manual to ensure that it remains in top working condition. Regular maintenance will help keep the product in the most impeccable state. If you have any further questions or need additional assistance, feel free to reach out. AdventureWorks Support\"\n      },\n      {\n        \"MessageId\": 154,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I reviewed the user manual again and followed the maintenance instructions more closely. I was able to figure it out this time. Thank you for your assistance!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 150,\n    \"ProductId\": 155,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 8,\n    \"ShortSummary\": \"Trouble with Solar Charger\",\n    \"LongSummary\": \"Customer having trouble with solar charger, but USB cable solved issue. Customer satisfied and ready for camping trip.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 157,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there! I just bought the Traveltech Portable Solar Charger and I\\u0027m having a bit of trouble figuring out how to use it. I\\u0027ve put it in the sun like the manual says, but it\\u0027s not charging my phone. Am I supposed to do something else? I really need this charger for my upcoming camping trip, so I hope you can help me out. Thanks so much!\"\n      },\n      {\n        \"MessageId\": 158,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hi there! If the solar charger is low on battery, you can also charge it using a USB cable and a power source such as a laptop or wall adapter. Also, ensure that the solar panels are positioned in direct sunlight. Move the charger to a sunnier location if necessary. If you need further assistance, please feel free to ask!\"\n      },\n      {\n        \"MessageId\": 159,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi, thanks for your help! I tried charging the solar charger with a USB cable and it worked perfectly. I didn\\u0027t realize I could do that, so I\\u0027m really grateful for your assistance. I\\u0027m all set for my camping trip now! Thanks again!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 151,\n    \"ProductId\": 70,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 55,\n    \"ShortSummary\": \"Solar panel troubleshooting\",\n    \"LongSummary\": \"Customer needs help with solar panel function and if adjustments are needed. Assistant provided info on solar panel and safety compliance. Pending customer response on troubleshooting steps or further assistance.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 160,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the Juice Junkie Solar Power Bank 10000mAh and I\\u0027m having some trouble with the solar panel. I\\u0027ve been relying on it extremely for charging my phone while hiking, but it doesn\\u0027t seem to be working as expected. I haven\\u0027t read the manual, but I was wondering if the solar panel needs to be calibrated or if there\\u0027s a way to adjust the voltage and current output. I\\u0027m really hoping to get this sorted so I can stay connected on my outdoor adventures. Thanks so much for your help!\"\n      },\n      {\n        \"MessageId\": 161,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Juice Junkie Solar Power Bank 10000mAh is equipped with a high-efficiency monocrystalline solar panel, designed to convert sunlight into electrical energy with a peak power output of 1.8W. The solar panel allows you to recharge the power bank directly from sunlight, providing an alternative charging method for outdoor use. According to the manual, the solar panel does not require calibration.\\n\\nThe manual also mentions that the product complies with the IEC 62109-1 standard for the safety of power converters for use in photovoltaic power systems.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 152,\n    \"ProductId\": 88,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 56,\n    \"ShortSummary\": \"RapidFlow Kayak Paddle Troubleshooting\",\n    \"LongSummary\": \"Customer is having issues with the RapidFlow Kayak Paddle and plans to contact the manufacturer for further instructions. They need assistance with troubleshooting and repair options.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 162,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there, I bought the RapidFlow Kayak Paddle from your store and I\\u0027m having some issues with it. Can you help me out?\"\n      },\n      {\n        \"MessageId\": 163,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the RapidFlow Kayak Paddle is covered by a limited warranty that protects against defects in materials and workmanship. However, the warranty does not cover any damage caused by the use of the paddle in whitewater conditions or rapids. If you encounter any problems with the paddle, please immediately discontinue use and contact the manufacturer for further instructions. For defective products, WaterWay may offer repair options as detailed in the manual.\"\n      },\n      {\n        \"MessageId\": 164,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Okay, I\\u0027ll contact the manufacturer for further instructions. Thanks.\"\n      },\n      {\n        \"MessageId\": 165,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the RapidFlow Kayak Paddle is covered by a limited warranty that protects against defects in materials and workmanship. However, the warranty does not cover any damage caused by the use of the paddle in whitewater conditions or rapids. Any such use will void the warranty, and WaterWay will not be held liable for any resulting damages. If you encounter any problems with the paddle, please immediately discontinue use and contact the manufacturer for further instructions. The manual also states that under no circumstances should you attempt to troubleshoot any issues with the paddle, as doing so may result in injury or death.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 153,\n    \"ProductId\": 98,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 57,\n    \"ShortSummary\": \"GPS Watch Functionality Help Request\",\n    \"LongSummary\": \"Customer needs help with TrailBlazer GPS Watch\\u0027s GPS and altimeter features. Looking for tips or advice on getting it to work correctly. Pending question about specific issues.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 166,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there, Exploremate team! I just got my hands on the TrailBlazer GPS Watch and I\\u0027m so stoked to take it out on my next hiking adventure! The GPS navigation and altimeter features are exactly what I need to keep track of my route and elevation changes. But, I seem to be having a little trouble getting it to work the way I want. Any chance you could help me out with some tips or advice? I\\u0027d really appreciate it! Thanks a bunch!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 154,\n    \"ProductId\": 177,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 58,\n    \"ShortSummary\": \"Difficulty with rainfly attachment\",\n    \"LongSummary\": \"Customer needs clear instructions on rainfly attachment and staking out. Frustrated with setup process, unsure if it\\u0027s worth purchasing.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 167,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027m so frustrated with the setup of the Trektent UltraLight 2-Person shelter! I can\\u0027t figure out how to properly attach the rainfly and stake it out. The manual is not helpful at all and I need clear instructions on how to do this before I consider purchasing. This is such a hassle and I need to know if it\\u0027s worth the trouble!\"\n      },\n      {\n        \"MessageId\": 168,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"To properly set up the Trektent UltraLight 2-Person shelter, lay out the tent on a flat surface with the ground stakes facing downward. Unfold the tent, extend the poles to their full length, and insert the color-coded poles into the corresponding sleeves on the tent body. After staking out the tent, adjust the tensioners and stakes as needed to ensure that the tent is properly secured and taut. This will improve the overall stability and weather-resistance of the shelter.\"\n      },\n      {\n        \"MessageId\": 169,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I followed your instructions and tried setting up the tent again, but I\\u0027m still having trouble with the rainfly. It just doesn\\u0027t seem to fit properly and I\\u0027m worried about it not providing enough protection in bad weather. I need more clear instructions specifically for the rainfly attachment and staking out. This is so frustrating!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 155,\n    \"ProductId\": 77,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 59,\n    \"ShortSummary\": \"Solar Charger 3000X for Home Appliances\",\n    \"LongSummary\": \"Customer inquires about using Solar Charger 3000X for home appliances during power outage. Asks for specific precautions. Pending response needed on product suitability for intended use.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 170,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Ecovolt Solar Charger 3000X and I\\u0027m considering using it to power my small appliances at home during a power outage. I think it should work perfectly for this unexpected purpose. However, I wanted to double-check if this is a reasonable use of the product and if there are any specific precautions I should take. Thank you for your assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 156,\n    \"ProductId\": 84,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 60,\n    \"ShortSummary\": \"Difficulty Tracking Cycling Sessions\",\n    \"LongSummary\": \"Customer is having trouble tracking cycling sessions despite following manual instructions and attempting to reset the GPS. The next support agent should offer a different solution for accurately recording cycling sessions.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 171,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I purchased the Trailblazer GPS Smartwatch for its cycling and running features, but I can\\u0027t seem to get it to work properly for cycling. The manual says I should press the blue button to start tracking my ride, but every time I do that, it doesn\\u0027t record my route or distance. It\\u0027s frustrating and I expected better from a product that claims to be the perfect cycling companion. I need assistance to figure out what\\u0027s going wrong.\"\n      },\n      {\n        \"MessageId\": 172,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, to start tracking your cycling session, press the blue button on the side of the watch and select \\u0027Cycling\\u0027 from the menu. The Trailblazer GPS Smartwatch will start recording your ride, allowing you to monitor your speed, distance, and route.\"\n      },\n      {\n        \"MessageId\": 173,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027ve tried pressing the blue button and selecting \\u0027Cycling\\u0027 from the menu multiple times, but it still isn\\u0027t recording my ride properly. This is so frustrating! I need a solution that actually works.\"\n      },\n      {\n        \"MessageId\": 174,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"It seems that the manual recommends resetting the GPS by holding down the GPS button for 10 seconds. Have you tried this step?\"\n      },\n      {\n        \"MessageId\": 175,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Yes, I tried resetting the GPS by holding down the button for 10 seconds like you suggested, and it still isn\\u0027t working properly. This is so frustrating, I just want to be able to track my cycling sessions accurately!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 157,\n    \"ProductId\": 54,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 61,\n    \"ShortSummary\": \"Missing Ski Goggles Compartment Inquiry\",\n    \"LongSummary\": \"Customer demands explanation for lack of ski goggles compartment in AvalanchePro Ski Backpack. Seeks immediate solution. Next agent should address specific oversight and provide resolution.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 176,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I demand to know why the AvalanchePro Ski Backpack doesn\\u0027t have a specific compartment for my ski goggles! I can\\u0027t believe a product designed for backcountry adventures would overlook such a crucial detail. I expect a full explanation and a solution to this oversight immediately.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 158,\n    \"ProductId\": 152,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 62,\n    \"ShortSummary\": \"Emergency Beacon Light Not Turning On\",\n    \"LongSummary\": \"Sure Survive Emergency Beacon Light not turning on despite proper installation and fully charged batteries. Customer seeking further troubleshooting steps or potential solution.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 177,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am experiencing issues with my Sure Survive Emergency Beacon Light. Specifically, the beacon light is not turning on despite having properly installed and fully charged batteries. I have checked the battery contacts and they are clean, and I have also tried replacing the batteries with new ones. Can you provide further troubleshooting steps or a potential solution to this problem?\"\n      },\n      {\n        \"MessageId\": 178,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"If you are experiencing issues with the Sure Survive Emergency Beacon Light, please refer to the following common issues and their potential solutions: \\n- If the beacon light is flashing irregularly, it may be due to low battery power. Replace the batteries with new ones and ensure they are fully charged. If you have attempted to troubleshoot the issues and are still experiencing problems, please contact Sure Survive\\u0027s customer support team for further assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 159,\n    \"ProductId\": 103,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 63,\n    \"ShortSummary\": \"Damaged first aid supplies in Survival Kit 5000\",\n    \"LongSummary\": \"Survival Kit 5000 arrived with damaged first aid supplies. Customer needs assistance with return process and checking usability of items.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Returns\",\n    \"Messages\": [\n      {\n        \"MessageId\": 179,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I can\\u0027t believe the first aid supplies in my Survival Kit 5000 are all messed up! The manual talks about making sure everything is present and in good condition, but my kit arrived with damaged items. This is not what I expected from Safetyex. I need some help sorting this out ASAP.\"\n      },\n      {\n        \"MessageId\": 180,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry to hear about the issues with your Survival Kit 5000. It\\u0027s important to us that our customers receive products in good condition. According to the manual, before using the Survival Kit 5000, it\\u0027s important to familiarize yourself with the safety guidelines. Ensure that you understand how to use each item in the kit properly and safely. As the first aid supplies are essential for addressing injuries, I recommend checking the condition of the damaged items and ensuring they are suitable for use. If you find that the items are not usable, you may be eligible for a return or repair. You can initiate a return at https://northernmountains.example.com/support/returns. If you need further assistance, please let us know.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 160,\n    \"ProductId\": 80,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 65,\n    \"ShortSummary\": \"Using Fishing Reel for Pool Toys\",\n    \"LongSummary\": \"Customer excited about using Stealth 5000 Fishing Reel for reeling in pool toys. Asks if it can handle the challenge and for tips on how to make it work. Pending response on compatibility and tips for use.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 182,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there, Team Reelmaster! Lenny here - I\\u0027m super stoked about the Stealth 5000 Fishing Reel I just got my hands on. This bad boy is a game-changer for my fishing adventures! \\uD83C\\uDFA3 But get this, I\\u0027ve got this crazy idea to use it for reeling in some massive inflatable pool toys at my backyard pool parties. I mean, who needs a regular old pool net when you\\u0027ve got the power and precision of the Stealth 5000, am I right? \\uD83D\\uDE02 Do you think it can handle the challenge? Any tips for me on how to make it work? Thanks a bunch, you guys rock! \\uD83E\\uDD19\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 161,\n    \"ProductId\": 38,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 64,\n    \"ShortSummary\": \"Guidance on Proper Stove Cleaning\",\n    \"LongSummary\": \"Customer is seeking guidance on proper cleaning of the camping stove. Previous assistance provided cleaning instructions. Customer now understands and has started using mild detergent and soft cloth. No further questions or issues reported.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 183,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Firefood Portable Camping Stove and I just want to make sure it\\u0027s behaving as it should. I\\u0027ve been using it for a couple of camping trips, and it seems to be working well, but I just want to double-check. I haven\\u0027t encountered any issues with it so far, but I wanted to reach out and see if there\\u0027s anything specific I should be looking out for to make sure it\\u0027s in tip-top shape. I want to make sure I\\u0027m using it correctly and taking good care of it. Thanks for your help!\"\n      },\n      {\n        \"MessageId\": 184,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hello! I\\u0027m glad to hear that you\\u0027re enjoying the Firefood Portable Camping Stove. According to the manual, setting up the stove is a breeze, and after using it, it\\u0027s recommended to clean it with mild detergent and a soft cloth once it has completely cooled down. Regular maintenance will keep your stove in tip-top shape for all your future outdoor cooking adventures. If you have any other questions or need further assistance, feel free to ask!\"\n      },\n      {\n        \"MessageId\": 185,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information! I\\u0027ve been cleaning the stove with a harsh detergent and a rough scrubbing brush, thinking it would make it cleaner. I guess I didn\\u0027t read the manual properly. I\\u0027ll switch to using a mild detergent and a soft cloth from now on. Thanks for your help!\"\n      },\n      {\n        \"MessageId\": 186,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m glad you found the information helpful! As mentioned in the manual, it\\u0027s important to use a mild detergent and a soft cloth for cleaning the stove to keep it in tip-top shape. If you have any other questions or need further assistance, feel free to ask!\"\n      },\n      {\n        \"MessageId\": 187,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for your help! I\\u0027ve switched to using mild detergent and a soft cloth to clean the stove, and it\\u0027s looking much better now. I appreciate your guidance!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 162,\n    \"ProductId\": 5,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 8,\n    \"ShortSummary\": \"Excited customer asking about hammock suitability for outdoor use\",\n    \"LongSummary\": \"Customer excited about using Double Hammock with Mosquito Net for camping and outdoor adventures. Asks if suitable for extended outdoor use, tips on setting up and care.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 188,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! I recently purchased the Swingnap Double Hammock with Mosquito Net and I am beyond excited to use it for camping trips and outdoor adventures. I love the idea of being able to relax in a hammock without worrying about pesky bugs bothering me. Just wanted to double-check if this hammock is suitable for extended outdoor use? Also, any tips on how to best set it up and take care of it? Can\\u0027t wait to hear back from you - thanks a bunch!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 163,\n    \"ProductId\": 64,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 66,\n    \"ShortSummary\": \"AquaFusion Portable Water Purifier 1000 won\\u0027t turn on\",\n    \"LongSummary\": \"Customer Hannah Park is upset that the AquaFusion Portable Water Purifier 1000 won\\u0027t turn on. She insists it\\u0027s not a battery or filter issue and demands a refund.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 189,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I can\\u0027t believe this! The stupid purifier won\\u0027t turn on, and I made sure the batteries are in properly! I spent good money on this AquaFusion Portable Water Purifier 1000 and now it\\u0027s useless. I need this fixed or replaced ASAP!\"\n      },\n      {\n        \"MessageId\": 190,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the user manual, the AquaFusion Portable Water Purifier 1000 is designed to remove 99.9% of bacteria, viruses, and protozoa from water, ensuring safe hydration. It is important to replace the filter regularly to maintain the purifier\\u0027s effectiveness. Have you replaced the filter recently? If the purifier is still not turning on after ensuring the filter is in place, please let us know so we can assist you further.\"\n      },\n      {\n        \"MessageId\": 191,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I don\\u0027t care about the stupid filter, I made sure it was in properly! This purifier is a piece of junk and I want a refund, not some dumb troubleshooting. You guys need to do better than this!\"\n      },\n      {\n        \"MessageId\": 192,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry to hear about the trouble you\\u0027re having with the Portable Water Purifier 1000. According to the user manual, please ensure that the batteries are properly inserted and that the battery compartment is securely closed. If the purifier still does not turn on, try replacing the batteries with new ones. If you need further assistance, please let us know. In addition, to maintain the purifier\\u0027s effectiveness, it is important to replace the filter regularly to ensure clean and safe hydration.\"\n      },\n      {\n        \"MessageId\": 193,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I ALREADY TOLD YOU, I DON\\u0027T CARE ABOUT THE BATTERIES OR THE FILTER! THE PURIFIER JUST DOESN\\u0027T TURN ON, AND I WANT A REFUND, NOT MORE USELESS TROUBLESHOOTING!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 164,\n    \"ProductId\": 71,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 67,\n    \"ShortSummary\": \"Troubleshooting Signal Booster 2000\",\n    \"LongSummary\": \"Retailer Hollis Davidson seeks troubleshooting tips for Signal Booster 2000\\u0027s signal boosting capability after following manual instructions. Need detailed troubleshooting assistance.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 194,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear Trailcom Support Team, I hope this message finds you well. My company is a retailer stocking the Trailcom Signal Booster 2000, and we have received inquiries from our customers regarding its setup and usage. Could you kindly provide us with detailed instructions or any troubleshooting tips that we can pass on to our customers? Your assistance in this matter would be greatly appreciated. Thank you for your attention to this request. Best regards, Hollis Davidson\"\n      },\n      {\n        \"MessageId\": 195,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Dear Hollis Davidson, \\n\\nAccording to the Trailcom Signal Booster 2000 User Manual, the setup process is detailed in the manual and includes instructions for powering on the device and its compatibility with various communication devices. It also provides information on signal boosting capability. If you require further assistance, please feel free to reach out to us. \\n\\nBest regards, \\nAdventureWorks Support\"\n      },\n      {\n        \"MessageId\": 196,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear AdventureWorks Support, thank you for your prompt response. I have referred to the Trailcom Signal Booster 2000 User Manual and followed the setup instructions, but unfortunately, we are still encountering some issues with the device\\u0027s signal boosting capability. Could you please provide further troubleshooting tips or any additional information that could help us address this issue? Your continued assistance is much appreciated. Best regards, Hollis Davidson\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 165,\n    \"ProductId\": 81,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 68,\n    \"ShortSummary\": \"Tips for using and maintaining climbing harness\",\n    \"LongSummary\": \"Customer is seeking tips on using and maintaining Summit X Climbing Harness. Assistant provided detailed instructions and asked if there are further questions.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 197,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! I just found out that your store stocks the Summit X Climbing Harness from Rockgrip, and I\\u0027m super excited about it! I\\u0027ve been looking for a new harness with reinforced webbing and adjustable buckles for a comfortable fit, and this one seems perfect. Do you have any tips for using and maintaining the harness? I want to make sure I take good care of it so it lasts a long time. Thanks so much for your help!\"\n      },\n      {\n        \"MessageId\": 198,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the Summit X Climbing Harness user manual, before using the harness, it is important to ensure that all parts of the harness are in good condition. Check that the reinforced webbing is not frayed or damaged, and that the adjustable buckles are functioning properly. After each use, it is important to properly store and maintain the harness, and inspect it regularly for signs of damage or wear. It\\u0027s also crucial to inspect the harness for any signs of wear and tear before each use. Additionally, ensure that the harness is the correct size and fits snugly around your body to prevent any issues during climbing activities.\"\n      },\n      {\n        \"MessageId\": 199,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Wow, thanks for the detailed information! I\\u0027ll be sure to check the harness thoroughly before each use and store it properly. I can\\u0027t wait to take it out for a climb. You\\u0027ve been so helpful, I really appreciate it!\"\n      },\n      {\n        \"MessageId\": 200,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, it is important to regularly check the stitching on your Summit X Climbing Harness and store it in a cool, dry place away from direct sunlight and moisture when not in use. Inspect the harness regularly for signs of damage or wear, and replace any worn or damaged parts immediately. Do you have any further questions about the harness?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 166,\n    \"ProductId\": 163,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 69,\n    \"ShortSummary\": \"Temperature Tolerance Concern for Stealth Cam 500\",\n    \"LongSummary\": \"Customer has concerns about temperature tolerance for Stealth Cam 500 and wants to know the impact of using the camera in temperatures just slightly outside the specified range. Customer needs insights on potential damage and possible return or repair options.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 201,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello Wildwatch Support Team, I recently purchased the Stealth Cam 500 for my outdoor wildlife research. I was specifically drawn to its high-resolution and night vision capabilities, which are crucial for capturing the behavior of nocturnal animals. However, I have a concern about the camera\\u0027s temperature tolerance. While I understand the manual specifies a temperature range for operation, I\\u0027m curious about the impact of using the camera in temperatures just slightly outside that range. Would a slight deviation cause irreparable damage to the internal components? Your insights on this matter would be greatly appreciated. Thank you for your time and expertise.\"\n      },\n      {\n        \"MessageId\": 202,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Stealth Cam 500 is designed for use within a specific temperature range. Using the camera in temperatures below -20\\u00B0F (-28\\u00B0C) or above 120\\u00B0F (49\\u00B0C) may result in damage to the camera and void the warranty. It\\u0027s imperative to avoid any exposure to water, extreme temperatures, or physical impact. Additionally, when not in use, the camera must be stored in a temperature-controlled environment, away from direct sunlight and moisture. Would you like to explore return or repair options for your camera?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 167,\n    \"ProductId\": 41,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 70,\n    \"ShortSummary\": \"AquaVenture Waterproof Surf Watch for Deep Sea Diving\",\n    \"LongSummary\": \"Customer inquires about using the AquaVenture watch for deep sea diving. Needs confirmation on its suitability for this purpose.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 203,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, I just bought the AquaVenture waterproof surf watch and I\\u0027m planning to use it for deep sea diving. I think it should work fine, right?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 168,\n    \"ProductId\": 85,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 70,\n    \"ShortSummary\": \"Fire starter sticks not igniting\",\n    \"LongSummary\": \"Customer experiencing trouble with fire starter sticks not igniting. Requesting assistance or guidance. Unsure if user error or product defect. Next agent should provide troubleshooting steps or offer replacement.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 204,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi, I recently purchased the All-Weather Fire Starter Kit from ReadySurvive and I\\u0027m having some trouble with the fire starter sticks not igniting. I\\u0027m not sure if I\\u0027m doing something wrong or if there\\u0027s a defect with the product. Can you please provide some assistance or guidance on how to get the fire starter sticks to ignite properly? Thank you.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 169,\n    \"ProductId\": 174,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 71,\n    \"ShortSummary\": \"Suitability of AdventureX 4K for mountain biking\",\n    \"LongSummary\": \"Customer inquires about the suitability of AdventureX 4K camera for mountain biking. Wants stable and durable features. No response yet.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 205,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, is the AdventureX 4K camera good for mountain biking? Need something stable and durable.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 170,\n    \"ProductId\": 55,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 30,\n    \"ShortSummary\": \"Trouble Marking Waypoints on Adventurer 2000 GPS Navigator\",\n    \"LongSummary\": \"Customer excited about using Adventurer 2000 GPS Navigator for hiking. Asked about marking waypoints, received instructions. Customer acknowledged instructions and will try marking waypoints. No pending questions.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 209,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! I just got my hands on the Exploremate Adventurer 2000 GPS Navigator and I\\u0027m so excited to use it for my upcoming hiking trip. But I\\u0027m having trouble marking waypoints on the device. I thought I could just mark them anywhere, but maybe I need to be in a specific kind of location? Do I need to be in an open area with a clear view of the sky? I\\u0027m not sure how this all works, can you help me out? Thanks so much!\"\n      },\n      {\n        \"MessageId\": 210,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"To mark a waypoint on the Adventurer 2000 GPS Navigator, tap the \\u0027Mark\\u0027 button on the map screen, then select \\u0027Save Waypoint.\\u0027 You can give your waypoint a name and assign it a custom icon for easy identification. Whether it\\u0027s a scenic overlook, a trailhead, or a hidden gem, you can mark it on your map and navigate back to it at any time. If you have any further questions, feel free to ask!\"\n      },\n      {\n        \"MessageId\": 211,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Oh, thanks! I didn\\u0027t realize I could just mark any spot on the map. I\\u0027ll give it a try and let you know if I have any more questions. Thanks again!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 171,\n    \"ProductId\": 19,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 73,\n    \"ShortSummary\": \"Difficulty Adjusting Lantern Brightness\",\n    \"LongSummary\": \"Customer experiencing difficulty adjusting brightness on Lumina LED Camping Lantern. Followed instructions, still not working. Considering product return.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Returns\",\n    \"Messages\": [\n      {\n        \"MessageId\": 212,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Lumina LED Camping Lantern and have been trying to adjust the brightness settings as mentioned in the product description. However, I\\u0027m having trouble getting the desired brightness level. I\\u0027m not sure if I\\u0027m doing something wrong or if there\\u0027s a technical issue with the lantern. Could you please provide guidance on how to properly adjust the brightness? I apologize if I\\u0027m missing something obvious, and I appreciate any assistance you can offer. Thank you for your help.\"\n      },\n      {\n        \"MessageId\": 213,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"To adjust the brightness settings of the NightBeacon Lumina LED Camping Lantern, follow these steps:\\n1. Press and hold the power button for 2 seconds to activate the lantern.\\n2. Press the power button repeatedly to cycle through the brightness settings.\\n3. Release the power button when the desired brightness level is achieved.\\nIf you continue to experience issues, please feel free to reach out to us for further assistance.\"\n      },\n      {\n        \"MessageId\": 214,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I tried following the steps you provided to adjust the brightness settings, but I\\u0027m still having trouble getting the desired level. I\\u0027m not sure if I\\u0027m doing something wrong or if there\\u0027s a technical issue with the lantern. I\\u0027m sorry for any inconvenience and I appreciate your continued assistance. Thank you.\"\n      },\n      {\n        \"MessageId\": 215,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Based on the user manual, the NightBeacon Lumina LED Camping Lantern features adjustable brightness settings to provide customizable illumination for various outdoor activities. To adjust the brightness settings, follow these steps:\\n1. Press and hold the power button for 2 seconds to activate the lantern.\\n2. Press the power button repeatedly to cycle through the brightness settings.\\n3. Release the power button when the desired brightness level is achieved.\\nIf you continue to experience issues, please feel free to reach out to us for further assistance.\"\n      },\n      {\n        \"MessageId\": 216,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I tried following the steps again, but I\\u0027m still having trouble adjusting the brightness. I\\u0027m starting to think that there might be a technical issue with the lantern. Is there anything else I can try, or should I consider returning the product for an exchange? I appreciate your help.\"\n      },\n      {\n        \"MessageId\": 217,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Based on the user manual, the NightBeacon Lumina LED Camping Lantern is designed for versatile illumination with adjustable brightness settings to meet various lighting needs. If you\\u0027re still experiencing issues, please feel free to initiate a return for further assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 172,\n    \"ProductId\": 86,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 74,\n    \"ShortSummary\": \"Non-Functioning SOS Multitool Kit Replacement Request\",\n    \"LongSummary\": \"Customer demands replacement for non-functioning SOS Multitool Kit. Assistant recommends inspecting tools for proper functionality. Next agent should provide guidance on return or repair within warranty period.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 218,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I purchased the SOS Multitool Kit and none of the tools seem to work at all! I demand a replacement immediately. This is completely unacceptable. I expect a functioning product for the amount of money I paid.\"\n      },\n      {\n        \"MessageId\": 219,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Thank you for reaching out to us. We\\u0027re sorry to hear that you\\u0027re experiencing issues with the SOS Multitool Kit. To better assist you, could you please specify which tools are not functioning as expected? Your feedback will help us provide you with the most accurate support.\"\n      },\n      {\n        \"MessageId\": 220,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I shouldn\\u0027t have to specify which tools aren\\u0027t working - the entire kit is a complete disaster! I demand a replacement ASAP.\"\n      },\n      {\n        \"MessageId\": 221,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Based on the product manual, the SOS Multitool Kit is designed to keep you safe and well-equipped during emergencies. It includes a knife, fish scaler, hook remover, and a compass. To address the issue with the tools, we recommend inspecting each tool for proper functionality and maintenance. If the issue persists, we can assist with a return or repair within the warranty period.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 173,\n    \"ProductId\": 59,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 75,\n    \"ShortSummary\": \"Inquiry about kayak stability and performance\",\n    \"LongSummary\": \"Customer seeks specific details about stability and performance of kayak in different water conditions. Requires real-life user experiences or expert opinions to address concerns.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 222,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027m considering purchasing the Explorer 3000 Kayak from Aqua Venture, but I have some concerns about its stability and performance. The description claims it\\u0027s lightweight, stable, and built for performance, but I need more detailed information on how it handles in different water conditions. Can you provide me with some real-life user experiences or expert opinions to back up these claims? I want to make sure I\\u0027m investing in a kayak that truly meets my needs before making a purchase.\"\n      },\n      {\n        \"MessageId\": 223,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the user manual, proper maintenance and care of the Explorer 3000 Kayak are important for ensuring its safety and performance. It is also recommended to read and understand all the safety instructions provided in the manual before using the kayak. Additionally, the Aqua Venture paddle that comes with the kayak is specially designed to be lightweight, durable, and provide maximum performance.\"\n      },\n      {\n        \"MessageId\": 224,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I appreciate the information about the user manual and the Aqua Venture paddle, but I still need more specific details about the stability and performance of the Explorer 3000 Kayak in different water conditions. Can you provide any real-life user experiences or expert opinions to address my concerns?\"\n      },\n      {\n        \"MessageId\": 225,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, proper maintenance and care of the Explorer 3000 Kayak are important for ensuring its safety and performance. It is recommended to inspect the kayak before each use for any signs of wear, damage, or defects, and to clean the kayak after each use to remove any debris, sand, or saltwater that may affect its performance. The Aqua Venture paddle is specially designed to be lightweight, durable, and provide maximum performance. For specific details about the stability and performance of the kayak in different water conditions, it is recommended to refer to the user manual or contact the manufacturer for real-life user experiences or expert opinions.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 174,\n    \"ProductId\": 197,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 76,\n    \"ShortSummary\": \"Stove won\\u0027t light despite checks\",\n    \"LongSummary\": \"Customer unable to light portable stove despite checking fuel and ignition. Will contact customer service for warranty claim.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 226,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, I just got the Firemaster Portable Camping Stove and I can\\u0027t get it to light up. I checked the fuel canister and it\\u0027s full. I also cleaned the ignition switch but still no luck. Can you help me out?\"\n      },\n      {\n        \"MessageId\": 227,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Firemaster Portable Camping Stove should be used in a well-ventilated outdoor area. Also, OutdoorOven reserves the right to repair or replace the product at its discretion. For warranty claims, please contact OutdoorOven Customer Service at customerservice@outdooroven.com with your proof of purchase and the serial number of your stove.\"\n      },\n      {\n        \"MessageId\": 228,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I tried using the stove in a well-ventilated outdoor area and it still won\\u0027t light up. I\\u0027ll contact customer service for warranty claim.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 175,\n    \"ProductId\": 122,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 77,\n    \"ShortSummary\": \"Trouble switching shooting modes\",\n    \"LongSummary\": \"Customer needs help switching shooting modes on AdventureCam 4K\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 229,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, can\\u0027t figure out how to switch shooting modes on my AdventureCam 4K. Help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 176,\n    \"ProductId\": 37,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 78,\n    \"ShortSummary\": \"Inquiry about First Aid Kit usage\",\n    \"LongSummary\": \"Customer has questions about using the Outdoor First Aid Kit, specifically for more serious injuries and the practical use of emergency whistle and reflective blanket. Next support agent should provide detailed information on those topics.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 230,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027m considering purchasing the Wild Guard Outdoor First Aid Kit, but I have some questions about its usage. The user manual mentions using the antiseptic wipes and bandages for cuts and scrapes, but what if I encounter a more serious injury? How should I handle that with this kit? Also, I\\u0027m not sure how effective the emergency whistle and reflective blanket would be in an actual emergency situation. Can you provide more information on their practical use? I want to make sure this kit will meet my needs before making a purchase.\"\n      },\n      {\n        \"MessageId\": 231,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The antiseptic wipes and bandages in the Wild Guard Outdoor First Aid Kit are used to clean and cover wounds. For more severe injuries, the kit includes a triangular bandage for creating a sling and a cold pack to reduce swelling. Always seek medical attention for serious injuries. In emergencies, the bright red emergency whistle can be used to signal for help, and the reflective blanket helps to stay warm and visible at night. The CPR mask can also be used if necessary. According to the manual, it is important to have a method of communication and clear directions to your location in remote areas.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 177,\n    \"ProductId\": 194,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 79,\n    \"ShortSummary\": \"Inquiry about Fire-Starting Equipment\",\n    \"LongSummary\": \"Customer inquired about the fire-starting equipment in the SurvivalPro 3000 Kit, specifically its use in wet conditions. Assistant provided guidance on using the equipment in dry conditions and recommended keeping it dry and free of obstructions.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 232,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Rescuepro SurvivalPro 3000 Kit and I\\u0027m very pleased with the quality of the multi-tool and first aid supplies. I wanted to inquire about the fire-starting equipment and its capabilities. Specifically, I would like to know if it is suitable for use in wet conditions or if there are any tips for using it in damp environments. Thank you for your assistance.\"\n      },\n      {\n        \"MessageId\": 233,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The fire-starting equipment in the Rescuepro SurvivalPro 3000 Kit is designed for use in dry conditions, and it is recommended to keep it dry and free of obstructions. When using the fire starter against the ferrocerium rod, ensure that the equipment is dry to create sparks. If you require further assistance, please contact Rescuepro customer support for additional guidance.\"\n      },\n      {\n        \"MessageId\": 234,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information. I will make sure to keep the fire-starting equipment dry and free of obstructions as recommended. If I encounter any further issues, I will reach out to Rescuepro customer support for additional guidance.\"\n      },\n      {\n        \"MessageId\": 235,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The fire-starting equipment should be kept dry and free of obstructions, and it\\u0027s recommended to clean it with a dry cloth after each use. If you encounter any issues, please contact Rescuepro customer support for assistance. If there is anything else I can help you with, feel free to ask.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 178,\n    \"ProductId\": 136,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 80,\n    \"ShortSummary\": \"Defective Solaris 500 Charger Refund\",\n    \"LongSummary\": \"Customer demands replacement or refund for Solaris 500 Portable Solar Charger. Refund process initiated, customer expects full refund and explanation for inconvenience caused.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 236,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am absolutely furious! I purchased the Solaris 500 Portable Solar Charger for my outdoor adventures and it has stopped working after just a few uses. I can\\u0027t believe this high-efficiency charger has failed me so quickly. I demand a replacement or a refund immediately. This is completely unacceptable!\"\n      },\n      {\n        \"MessageId\": 237,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry to hear that your Solaris 500 Portable Solar Charger stopped working. We value the quality of our products and would like to assist you further. According to the manual, the Solaris 500 is designed for outdoor use and charging devices using direct sunlight. If you\\u0027re experiencing technical issues, we recommend reaching out to Ecovolt\\u0027s technical support for assistance. You can find their contact details in the user manual. If the product is defective, you may be eligible for a refund or replacement within the warranty period.\"\n      },\n      {\n        \"MessageId\": 238,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I shouldn\\u0027t have to reach out to technical support for a product that should work as advertised! I demand a replacement or refund without having to jump through more hoops.\"\n      },\n      {\n        \"MessageId\": 239,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I understand your frustration, and I apologize for the inconvenience caused. According to the manual, the Solaris 500 Portable Solar Charger is designed for outdoor use and is built to withstand the rigors of outdoor adventures. It\\u0027s important to us that you have a positive experience with our products. As per our warranty policy, defective products may be eligible for a refund within the warranty period. If you would like to proceed with a refund, you may initiate the process through our support portal at https://northernmountains.example.com/support/returns. If you need further assistance, please reach out to Ecovolt\\u0027s technical support, as their contact details are provided in the user manual. Thank you for bringing this to our attention.\"\n      },\n      {\n        \"MessageId\": 240,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I can\\u0027t believe I have to go through all this trouble for a product that is supposed to work as advertised! I will initiate the refund process through the support portal, but this is completely unacceptable!\"\n      },\n      {\n        \"MessageId\": 241,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I apologize for the inconvenience. If the product is defective, you may be eligible for a refund within the warranty period. To proceed with a refund, you may initiate the process through our support portal at https://northernmountains.example.com/support/returns. If you need further assistance, please reach out to Ecovolt\\u0027s technical support, as their contact details are provided in the user manual. Thank you for your understanding.\"\n      },\n      {\n        \"MessageId\": 242,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"This whole experience has been a nightmare! I\\u0027ve initiated the refund process through the support portal as you suggested, but I still can\\u0027t believe I have to go through all this trouble for a product that should work as advertised. I expect better from Ecovolt!\"\n      },\n      {\n        \"MessageId\": 243,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry for the inconvenience. If you\\u0027ve initiated the refund process through the support portal, our team will ensure that it is processed as quickly as possible. We appreciate your understanding and thank you for bringing this to our attention. If you have any further questions or concerns, please don\\u0027t hesitate to reach out to us.\"\n      },\n      {\n        \"MessageId\": 244,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"This whole situation has been a complete disaster! I expect a full refund and an explanation from Ecovolt for the inconvenience and frustration caused by their defective product.\"\n      },\n      {\n        \"MessageId\": 245,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry for the inconvenience you\\u0027ve experienced with the Solaris 500 Portable Solar Charger. As per our policy, defective products may be returned within 1 year of purchase for a refund. You\\u0027ve already initiated the refund process through our support portal, and our team will ensure that it is processed as quickly as possible. If you have any further questions or concerns, please don\\u0027t hesitate to reach out to us. Thank you for your understanding.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 179,\n    \"ProductId\": 77,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 81,\n    \"ShortSummary\": \"LED Indicator Malfunction\",\n    \"LongSummary\": \"Customer is frustrated that the LED light on the solar charger is not working after following troubleshooting steps and demands a replacement immediately. Next agent should prioritize providing a replacement or alternative solution.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 246,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am so frustrated with the LED light on my Solar Charger 3000X! It\\u0027s supposed to attract attention in case of emergency, but it\\u0027s not working properly. I need this feature to feel safe during my outdoor expeditions. Can you please provide me with a solution or a replacement as soon as possible?\"\n      },\n      {\n        \"MessageId\": 247,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, if the LED indicator on the Solar Charger 3000X is not lighting up, please try charging the solar charger using a power source and the provided USB cable. Also, ensure that the solar panels are clean and free from any debris that may be blocking the sunlight from reaching the panels.\"\n      },\n      {\n        \"MessageId\": 248,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I tried charging the solar charger using a power source and the provided USB cable, and I made sure the solar panels are clean and free from any debris, but the LED light still isn\\u0027t working! This is so frustrating and unacceptable. I need a replacement immediately!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 180,\n    \"ProductId\": 120,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 82,\n    \"ShortSummary\": \"ArcticPro Jacket Issue: Refund Eligibility\",\n    \"LongSummary\": \"Customer experienced issues with ArcticPro Jacket, assisted with preliminary checks, but issue persists. Customer now eligible for a refund. Next agent should guide through the return process.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Returns\",\n    \"Messages\": [\n      {\n        \"MessageId\": 252,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the ArcticPro Insulated Ski Jacket from Frost Flare and I\\u0027m having some issues with it. It doesn\\u0027t seem to be working at all and I\\u0027m not sure what the problem is. I was really looking forward to using it on my upcoming ski trip, so I\\u0027m quite disappointed. Can you please provide me with some assistance on how to get it working properly? Thank you.\"\n      },\n      {\n        \"MessageId\": 253,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hello, the ArcticPro Insulated Ski Jacket by Frost Flare is designed with advanced insulation technology to keep you warm and comfortable in even the harshest winter conditions. The jacket features a waterproof design, utilizing FrostShield technology to repel moisture and keep you dry in snowy and wet environments. Before using the Frost Flare ArcticPro Insulated Ski Jacket, it is essential to perform a series of preliminary checks to ensure the integrity and functionality of the garment. Would you like assistance with performing these checks?\"\n      },\n      {\n        \"MessageId\": 254,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Yes, I would appreciate assistance with performing the preliminary checks for the ArcticPro Insulated Ski Jacket. Please provide me with the necessary steps to ensure the jacket\\u0027s integrity and functionality. Thank you for your help!\"\n      },\n      {\n        \"MessageId\": 255,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Based on the user manual, before using the Frost Flare ArcticPro Insulated Ski Jacket, it is essential to perform a series of preliminary checks to ensure the integrity and functionality of the garment. I will provide you with the necessary steps for these preliminary checks to ensure the jacket\\u0027s integrity and functionality. Please wait for a moment while I gather the information for you.\"\n      },\n      {\n        \"MessageId\": 256,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for your help. I am ready to perform the preliminary checks for the ArcticPro Insulated Ski Jacket as soon as you provide me with the necessary steps. I appreciate your assistance in helping me get this issue resolved.\"\n      },\n      {\n        \"MessageId\": 257,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Before using the Frost Flare ArcticPro Insulated Ski Jacket, it is essential to perform a series of preliminary checks to ensure the integrity and functionality of the garment. Please refer to the following table for a list of recommended preliminary checks:\"\n      },\n      {\n        \"MessageId\": 258,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for providing the list of recommended preliminary checks. I will perform these checks and let you know the outcome. I appreciate your assistance in helping me resolve this issue.\"\n      },\n      {\n        \"MessageId\": 259,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the user manual, before using the Frost Flare ArcticPro Insulated Ski Jacket, it is essential to perform a series of preliminary checks to ensure the integrity and functionality of the garment. I have provided you with the list of recommended preliminary checks in a previous message. Please perform these checks and let me know the outcome. If the issue persists, we can explore further options.\"\n      },\n      {\n        \"MessageId\": 260,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for providing the list of recommended preliminary checks. I have performed these checks and unfortunately, the issue with the ArcticPro Insulated Ski Jacket persists. It still doesn\\u0027t seem to be working properly. I would appreciate further assistance in resolving this issue. Thank you.\"\n      },\n      {\n        \"MessageId\": 261,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I apologize for the inconvenience you\\u0027ve experienced with the ArcticPro Insulated Ski Jacket. While the preliminary checks are important, it seems that the issue persists despite performing these checks. Since the product is defective, you are eligible for a refund. Please initiate the return process at https://northernmountains.example.com/support/returns to receive a refund. Thank you for your understanding and patience.\"\n      },\n      {\n        \"MessageId\": 262,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for your assistance. I will initiate the return process as advised to receive a refund. I appreciate your help in resolving this issue.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 181,\n    \"ProductId\": 194,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 83,\n    \"ShortSummary\": \"Compass troubleshooting needed\",\n    \"LongSummary\": \"Customer needs detailed instructions for using the compass in the SurvivalPro 3000 Kit. Pending question: What specific troubleshooting tips can be provided?\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 263,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027m having trouble with something in the SurvivalPro 3000 Kit. Can you help me figure it out?\"\n      },\n      {\n        \"MessageId\": 264,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The SurvivalPro 3000 Kit comes equipped with a compass for navigating through the wilderness. To use the compass: 1. Hold the compass flat in your hand. Additionally, the kit should be regularly inspected for any damage to the case or its contents. Replace any items that show signs of wear or damage to ensure the kit is always prepared for use in outdoor emergencies.\"\n      },\n      {\n        \"MessageId\": 265,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I tried holding the compass flat in my hand as you suggested, but I\\u0027m still having trouble figuring it out. Can you provide more detailed instructions or troubleshooting tips?\"\n      },\n      {\n        \"MessageId\": 266,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I found some additional information in the manual for the SurvivalPro 3000 Kit. According to the manual, when you receive your SurvivalPro 3000 Kit, carefully open the packaging to avoid damaging any of the items inside. Check the contents against the provided list to ensure that everything is included. Please note that the kit includes a multi-tool, first aid supplies, and fire-starting equipment, so be sure to locate these items within the packaging. If the issue persists, please contact Rescuepro customer support for assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 182,\n    \"ProductId\": 78,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 84,\n    \"ShortSummary\": \"Inquiry about limited warranty and product durability\",\n    \"LongSummary\": \"Customer questions the limited warranty of AquaTech X-5000 and requests real-life usage scenarios to ensure durability and smart investment. Needs detailed information on warranty and product durability.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 267,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027m considering purchasing the AquaTech X-5000, but your limited warranty seems so limited! It doesn\\u0027t cover misuse or abuse, which is subjective and can easily be used to deny any claims. And the fact that I have to provide the original proof of purchase and return the product to an authorized service center for a claim is just ridiculous. What if I have an issue while I\\u0027m out on the water? This warranty is not inspiring confidence in the product\\u0027s durability. Can you provide more information about how the product holds up in real-life usage scenarios? I need to know that I\\u0027m making a smart investment before I commit to purchasing.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 183,\n    \"ProductId\": 45,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 85,\n    \"ShortSummary\": \"Inquiry about outdoor charging with solar power bank\",\n    \"LongSummary\": \"Customer inquires about using solar power bank for outdoor charging. Informed about warranty and return policy. No pending questions.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 268,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I just bought the TrailBlazer Solar Power Bank for my upcoming camping trip and I\\u0027m wondering if it will really charge my devices using just sunlight? I mean, it sounds too good to be true! Can I rely on it to keep my phone charged while I\\u0027m out in the wilderness? Also, if it doesn\\u0027t work as expected, can I get a refund or replacement? Thanks for your help!\"\n      },\n      {\n        \"MessageId\": 269,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The TrailBlazer solar power bank is designed to provide a reliable power source for your devices while you are on the go. It is equipped with a solar panel for outdoor charging. If you experience any issues with the product, please contact NomadGear customer support for assistance. The product comes with a limited 1-year warranty and a 30-day return or exchange policy for unused products. For warranty claims, support, or returns, please contact NomadGear customer support at support@nomadgear.com or 1-800-555-1234.\"\n      },\n      {\n        \"MessageId\": 270,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, thanks for the information! I\\u0027m glad to hear that the TrailBlazer solar power bank is designed for outdoor charging. I\\u0027ll be sure to reach out to NomadGear customer support if I encounter any issues. Thanks again!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 184,\n    \"ProductId\": 193,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 64,\n    \"ShortSummary\": \"Latch Malfunction in AltitudeTech Cake Carrier\",\n    \"LongSummary\": \"Customer experiencing latch issues with AltitudeTech Cake Carrier, seeking guidance on addressing the problem. Advised to contact SummitChomp customer support for further assistance.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 271,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear Customer Support Team, I recently purchased the AltitudeTech Cake Carrier from SummitChomp and have been trying to use it to transport my high-altitude cakes. However, I am having difficulty with the functionality of the latches. Despite following the safety precautions and performing a thorough inspection, the latches seem to be malfunctioning and not securing the carrier properly. I am concerned that this may compromise the integrity of my baked goods during transport. Could you please provide me with guidance on how to address this issue? I would greatly appreciate your assistance in resolving this matter. Thank you.\"\n      },\n      {\n        \"MessageId\": 272,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Thank you for reaching out to us. We understand the importance of securely transporting your high-altitude cakes. According to the manual, the AltitudeTech Cake Carrier is designed with specialized insulation and secure latches to ensure the safe transportation of delicate baked goods. It\\u0027s crucial to follow the setup and calibration steps provided in the manual to ensure optimal performance. If you are experiencing issues with the latches, please do not use the carrier and contact SummitChomp customer support for further assistance. If you need any further guidance, please feel free to ask.\"\n      },\n      {\n        \"MessageId\": 273,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear Customer Support Team, thank you for your prompt response. I have not used the carrier since experiencing the latch issue, and I will contact SummitChomp customer support for further assistance as suggested. I will keep you updated on the outcome. Thank you for your guidance.\"\n      },\n      {\n        \"MessageId\": 274,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The latching mechanism of the AltitudeTech Cake Carrier is designed to withstand extreme environmental conditions typically encountered at high altitudes. It\\u0027s crucial to perform a thorough inspection of the unit to ensure all components are in proper working order, including the functionality of the latches. If you continue to experience issues with the latches, please contact SummitChomp customer support for further assistance. You may also refer to the manual for additional guidance. Thank you for your understanding.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 185,\n    \"ProductId\": 58,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 86,\n    \"ShortSummary\": \"SafeTrail GPS Locator SOS Button Reliability Inquiry\",\n    \"LongSummary\": \"Customer excited about using SafeTrail GPS Locator for hiking, wants reassurance about SOS button reliability. Pending response needed regarding SOS button reliability.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 275,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! Just got my hands on the SafeTrail GPS Locator and I am SO excited to take it out on my next hiking adventure. Can you reassure me that the SOS button will work like a charm in case of an emergency? I want to make sure it\\u0027s as reliable as it says in the description. Thanks a bunch!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 186,\n    \"ProductId\": 109,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 87,\n    \"ShortSummary\": \"Defective XtremeGear 5000 multitool\",\n    \"LongSummary\": \"Customer Evelyn Andrews is frustrated that the multitool in the XtremeGear 5000 kit is not working despite following bike maintenance instructions. She demands a replacement or refund. Determine if the tool is defective and offer a resolution.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 276,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I can\\u0027t believe the multitool in the XtremeGear 5000 kit doesn\\u0027t work! I followed the bike maintenance instructions, but it\\u0027s still not making the adjustments I need. What\\u0027s the point of including it if it\\u0027s useless? This whole thing is a waste of money. I demand a replacement or a refund!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 187,\n    \"ProductId\": 179,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 88,\n    \"ShortSummary\": \"Adjusting AquaPro 3000 paddle length difficulties\",\n    \"LongSummary\": \"Customer needs guidance with adjusting AquaPro 3000 paddle length, having trouble securing with black locking button. Requesting assistance in making necessary adjustments.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 277,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the AquaPro 3000 and have been trying to adjust the paddle length to suit my individual needs. However, I seem to be encountering some difficulties in finding the correct length despite following the instructions provided. I have tried adjusting the paddle shaft using the black locking button, but it doesn\\u0027t seem to secure in place as expected. I have also referred to the height and paddle length guide in the manual, but I\\u0027m still unsure if I\\u0027m doing it correctly. I believe I have a good understanding of the technical aspects of this product, but I would greatly appreciate some guidance or assistance in making the necessary adjustments. Thank you in advance for your help.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 188,\n    \"ProductId\": 55,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 89,\n    \"ShortSummary\": \"Warranty Coverage Inquiry for Accidental Damage\",\n    \"LongSummary\": \"Customer inquires about warranty coverage for accidental damage. Expresses love for product and good vibes. Pending response on warranty coverage for accidents.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 278,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there Exploremate fam! I just got my hands on the Adventurer 2000 GPS Navigator and I am absolutely loving it! The topographic mapping and waypoint marking features are seriously top-notch. But here\\u0027s the thing - I noticed the warranty doesn\\u0027t cover damage from \\u0027accidents or misuse.\\u0027 So, hypothetically speaking, what if I accidentally drop it off a small rock while hiking? Would that still be covered? \\uD83E\\uDD14 I mean, I promise to take super good care of it, but ya never know what could happen out on the trails, am I right? Anyway, just wanted to check in and spread some good vibes your way! Keep doing what you do best, and I\\u0027ll keep exploring with my new GPS navigator! \\uD83C\\uDF32\\uD83C\\uDF1F\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 189,\n    \"ProductId\": 28,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 90,\n    \"ShortSummary\": \"Broken filter cartridge resolved\",\n    \"LongSummary\": \"Customer Eleanor Langley reported a broken filter cartridge for her PureStream Water Purifier, but was able to resolve the issue by following the provided instructions. No further support is needed at this time.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 279,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear AquaFusion Customer Support, My name is Eleanor Langley and I recently purchased the PureStream Water Purifier for my outdoor adventures. Unfortunately, the filter cartridge seems to have broken during my last trip, and I am now unable to use the purifier. I am in need of assistance in either repairing or replacing the filter cartridge so that I can continue to ensure safe drinking water on my outdoor excursions. Your prompt attention to this matter would be greatly appreciated. Thank you for your help.\"\n      },\n      {\n        \"MessageId\": 280,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Dear Eleanor Langley, \\n\\nThank you for reaching out to us. We\\u0027re sorry to hear about the issue with the filter cartridge of your PureStream Water Purifier. According to the user manual, to replace the filter cartridge, you can remove the cartridge by twisting it counterclockwise and pulling it out. Then, inspect the filter for damage and if it\\u0027s damaged, replace it with a new one. After that, reinstall the filter cartridge by inserting it into the purifier and twisting it clockwise until it locks into place. \\n\\nIf you need further assistance or if you have any other questions, please feel free to let us know. We\\u0027re here to help. \\n\\nAdventureWorks Support\"\n      },\n      {\n        \"MessageId\": 281,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear AdventureWorks Support, thank you for your prompt response. I followed the steps provided in the user manual to replace the filter cartridge, and I\\u0027m happy to report that the PureStream Water Purifier is now working perfectly again. I appreciate your assistance in resolving this matter. Thank you for your help.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 190,\n    \"ProductId\": 36,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 37,\n    \"ShortSummary\": \"Misunderstanding about grill capabilities\",\n    \"LongSummary\": \"Customer misunderstood the capabilities of the Eco Grill Portable BBQ Grill, but now understands it\\u0027s not suitable for cooking a whole hog. No further action needed.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 284,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the Eco Grill Portable BBQ Grill and I have a bit of an unusual question. I was thinking of using it to cook a whole hog for a big family gathering, but now I\\u0027m realizing that might be a bit too ambitious. I hope I haven\\u0027t damaged the grill by even considering it! Do you think it\\u0027s possible, or have I just completely misunderstood the capabilities of the grill? Any advice would be greatly appreciated. Thanks so much!\"\n      },\n      {\n        \"MessageId\": 285,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Eco Grill Portable BBQ Grill is designed for off-grid outdoor use and may not be suitable for cooking a whole hog. It\\u0027s recommended to use the grill according to the provided instructions and safety considerations. If you have further questions, feel free to ask!\"\n      },\n      {\n        \"MessageId\": 286,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Oh gosh, I feel silly now. I definitely misunderstood the capabilities of the grill. Thanks for clarifying that for me. I\\u0027ll stick to the regular grilling and leave the whole hog for another time. I appreciate your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 191,\n    \"ProductId\": 98,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 92,\n    \"ShortSummary\": \"TrailBlazer GPS watch not functioning\",\n    \"LongSummary\": \"TrailBlazer GPS watch not functioning, no power. Customer needs troubleshooting help.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 287,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Watch broken. Need help. No power. No function.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 192,\n    \"ProductId\": 80,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 93,\n    \"ShortSummary\": \"Persistent line tangling issue\",\n    \"LongSummary\": \"Customer Erik Johnson experiencing line tangling issues despite following initial suggestions. Next agent should provide advanced troubleshooting for fishing reel.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 288,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Line keeps tangling, can\\u0027t reel in catch. Help please.\"\n      },\n      {\n        \"MessageId\": 289,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"To prevent line twist, carefully spool the line onto the reel to avoid any twists. Additionally, you can adjust the drag system on the reel to control line tension and prevent line breakage. If you have any further questions, feel free to ask!\"\n      },\n      {\n        \"MessageId\": 290,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Line still keeps tangling even after following your suggestions.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 193,\n    \"ProductId\": 70,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 94,\n    \"ShortSummary\": \"Refund requested for solar power bank\",\n    \"LongSummary\": \"Customer is frustrated with recommended product tests, demands immediate refund. Next agent should address refund process and offer alternative solutions.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Returns\",\n    \"Messages\": [\n      {\n        \"MessageId\": 291,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"So let me get this straight, you\\u0027re telling me I need to do some kind of voltage measurement and capacity test just to make sure this solar power bank works properly? I bought it to make my life easier, not to spend my time conducting tests! And what\\u0027s this about a solar panel inspection? I just want a power bank that I can rely on when I\\u0027m out and about, not a science experiment. If this thing doesn\\u0027t work as advertised, I want a refund!\"\n      },\n      {\n        \"MessageId\": 292,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I understand your concerns, and I apologize for the inconvenience. According to the product manual, the capacity test and voltage measurement are recommended to ensure the power bank\\u0027s proper functioning. Additionally, the solar panel inspection is suggested to maintain optimal performance. If you believe the product is defective, you may be eligible for a refund. You can initiate a return at https://northernmountains.example.com/support/returns.\"\n      },\n      {\n        \"MessageId\": 293,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I don\\u0027t care about the product manual or what is recommended, I just want a working power bank without having to jump through hoops. This is unacceptable and I demand a refund immediately!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 194,\n    \"ProductId\": 1,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 95,\n    \"ShortSummary\": \"Inquiry about Adventure GPS Tracker technical specs\",\n    \"LongSummary\": \"Evan Chambers seeks technical info on Adventure GPS Tracker specs. He\\u0027s satisfied with the device\\u0027s performance. No pending questions. A follow-up on customer satisfaction would be helpful.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 294,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear Escapesafe Customer Support,\\n\\nI am reaching out to inquire about the Adventure GPS Tracker. As a retailer stocking this product, I am seeking detailed technical information regarding its environmental compatibility, functional diagnostics, battery performance, and network connectivity. Our customers are increasingly knowledgeable about the intricacies of such devices, and I aim to provide them with comprehensive insights. Please assist me in understanding the device\\u0027s superiority in withstanding extreme conditions, operating as intended, optimizing battery efficiency, and ensuring reliable network connectivity. Your prompt and thorough response would be greatly appreciated.\\n\\nSincerely, Evan Chambers\"\n      },\n      {\n        \"MessageId\": 295,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Dear Evan Chambers, \\n\\nThank you for reaching out to us about the Adventure GPS Tracker. According to the user manual, the device is equipped with advanced GPS technology, utilizing GPS, GLONASS, and Galileo satellite systems to ensure accurate positioning even in remote areas with limited GPS coverage. The manual also provides guidance on conducting precise battery performance analysis to determine power efficiency, capacity, and adherence to industry standards. In addition, the durability testing of the Adventure GPS Tracker meets MIL-STD-810G standards for resistance to shock, vibration, and temperature extremes. For network connectivity, the manual suggests assessing the device\\u0027s ability to establish and maintain stable connections with GPS satellites. I hope this information is helpful to you and your customers. Should you require further assistance, feel free to reach out to us. \\n\\nSincerely, \\nAdventureWorks Support\"\n      },\n      {\n        \"MessageId\": 296,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear AdventureWorks Support, \\n\\nThank you for the detailed information provided. I have conducted a thorough analysis of the device\\u0027s environmental compatibility, functional diagnostics, battery performance, and network connectivity based on the guidance from the user manual. I must say, the precision and reliability of the Adventure GPS Tracker are truly impressive. It has exceeded our expectations in terms of withstanding extreme conditions, optimizing battery efficiency, and ensuring reliable network connectivity. I am thoroughly satisfied with the device\\u0027s performance and will now be able to provide our customers with the comprehensive insights they seek. I appreciate your prompt and thorough response.\\n\\nSincerely, Evan Chambers\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 195,\n    \"ProductId\": 183,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 96,\n    \"ShortSummary\": \"Boiling issue despite following instructions\",\n    \"LongSummary\": \"Customer unable to boil water in pot despite following instructions. Informed about warranty replacement process. Pending question about whether to close the ticket.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 297,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Pot not boiling water properly. Help needed ASAP.\"\n      },\n      {\n        \"MessageId\": 298,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, to boil water in the Trailblazer Compact Cookware Set, you should add the desired amount of water to the pot and bring it to a boil. Once the liquid is boiling, you can add your ingredients and cook according to your recipe. If you have followed these steps and are still experiencing issues, please let us know so we can further assist you.\"\n      },\n      {\n        \"MessageId\": 299,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Tried following the steps, still not boiling. What next?\"\n      },\n      {\n        \"MessageId\": 300,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry to hear that you\\u0027re still experiencing difficulties. If the product is defective, you may be eligible for a replacement part free of charge under the warranty. To proceed with this, you can contact Campchef Customer Service at 1-800-650-2433 or email support@campchef.com. They will guide you through the process and provide instructions for returning the product if necessary. It\\u0027s important to have the proof of purchase and a description of the issue ready when contacting them. If you need any further assistance, please let us know. Should I close the ticket?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 196,\n    \"ProductId\": 42,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 97,\n    \"ShortSummary\": \"Defective StealthTrek Backpack\",\n    \"LongSummary\": \"Customer is frustrated with malfunctioning StealthTrek Tactical Backpack. Wants replacement or refund. Assistant informed about lifetime warranty and return process.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 301,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am beyond frustrated with my StealthTrek Tactical Backpack from Tactic Tech. I purchased it for rugged outdoor adventures, but it has already broken after just a few uses. The main compartment zipper is completely stuck and won\\u0027t budge, making it impossible to access any of my gear. This is unacceptable! I expect a replacement or a refund for this faulty product.\"\n      },\n      {\n        \"MessageId\": 302,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the StealthTrek Tactical Backpack comes with a limited lifetime warranty that covers manufacturing defects and workmanship. Tactic Tech will repair or replace any defective parts or the entire backpack if necessary, at their discretion. You may initiate the return process at https://northernmountains.example.com/support/returns.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 197,\n    \"ProductId\": 139,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 98,\n    \"ShortSummary\": \"SmartCyclo suitability for indoor cycling\",\n    \"LongSummary\": \"Customer inquires about using SmartCyclo for indoor cycling, seeks guidance on optimizing the device. Pending confirmation and guidance needed for indoor use.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 303,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am considering using the SmartCyclo GPS Bike Computer for indoor cycling on my stationary bike. I believe that the advanced performance tracking features, such as heart rate monitoring, can still be beneficial even in a stationary setting. Can you confirm if the SmartCyclo is suitable for this purpose? Additionally, I would appreciate any guidance on how to optimize the device for indoor cycling if applicable. Thank you for your assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 198,\n    \"ProductId\": 151,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 99,\n    \"ShortSummary\": \"Knife Feature Usage Guidance\",\n    \"LongSummary\": \"Customer seeks guidance on using the knife feature of the Survivor Multi-Tool effectively and safely. Previous response provided detailed instructions. No further questions pending.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 304,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the Survivor Multi-Tool from Resilience Gear and I\\u0027m loving its durability and versatility. However, I have a question about its suitability for cutting and slicing tasks. I want to make sure I\\u0027m using it correctly and safely. Can you provide me with some guidance on how to use the knife feature effectively? I want to ensure that I\\u0027m not causing any damage to the tool due to misuse. Thanks so much for your help!\"\n      },\n      {\n        \"MessageId\": 305,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The knife feature of the Survivor Multi-Tool is located in the center of the tool. To use the knife, carefully pull the knife blade out from the tool and use it for cutting and slicing tasks. Remember to use caution when handling the knife blade, as it is extremely sharp. Additionally, familiarize yourself with the main components of the multi-tool and become familiar with the locations of the buttons and the maneuvering of the controls, ensuring that you understand how to access each feature. If you have any further questions or need assistance, feel free to reach out to us. We\\u0027re here to help!\"\n      },\n      {\n        \"MessageId\": 306,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you so much for the guidance! I\\u0027ll be sure to handle the knife feature with caution and follow your instructions. I really appreciate your help.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 199,\n    \"ProductId\": 24,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 100,\n    \"ShortSummary\": \"Cleaning success\",\n    \"LongSummary\": \"Customer cleaned sleeping bag as suggested and it worked. No pending questions.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 307,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, I bought the Arctic Dream 0\\u00B0F Sleeping Bag and it\\u0027s super warm! How do I clean it without messing it up? Thx!\"\n      },\n      {\n        \"MessageId\": 308,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, to clean your Arctic Dream 0\\u00B0F Sleeping Bag, spot clean the affected area with a damp cloth and mild soap. Do not use harsh chemicals or bleach. This will help keep your sleeping bag in top condition.\"\n      },\n      {\n        \"MessageId\": 309,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thx! I\\u0027ll give it a try and let you know how it goes.\"\n      },\n      {\n        \"MessageId\": 310,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, you can spot clean the affected area with a damp cloth and mild soap. Do not use harsh chemicals or bleach. This will help keep your sleeping bag in top condition. If you have any other questions, feel free to ask!\"\n      },\n      {\n        \"MessageId\": 311,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, just wanted to let you know that I cleaned the sleeping bag as you suggested and it worked like a charm! Thanks for the help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 200,\n    \"ProductId\": 145,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 102,\n    \"ShortSummary\": \"Slow charging issue with solar-powered portable charger\",\n    \"LongSummary\": \"Customer is experiencing slow charging with the solar-powered portable charger despite direct sunlight and panel cleaning. Customer seeks help to understand why it\\u0027s charging slowly.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 315,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the PowerBeam Solar Powered Portable Charger and I\\u0027m having some trouble with it. I thought it would charge my devices really quickly, but it seems to be taking forever. I\\u0027ve tried placing it in direct sunlight and cleaning the solar panel, but it\\u0027s still not working as expected. Can you please help me understand why it\\u0027s charging so slowly? I really want to make sure I\\u0027m getting the most out of this solar charger. Thank you so much for your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 201,\n    \"ProductId\": 121,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 103,\n    \"ShortSummary\": \"Trouble with distance alert feature on HydroTech 5000\",\n    \"LongSummary\": \"Customer needs assistance setting the distance alert feature on the HydroTech 5000. They can\\u0027t figure out how to adjust the parameters and navigate to the settings menu using the touch screen. They are awaiting feedback on whether the provided instructions were helpful.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 316,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the HydroTech 5000 from WaterRover and I\\u0027m having trouble with the distance alert feature. I can\\u0027t seem to figure out how to set the distance limit or adjust the parameters. I thought it would automatically notify me, but I must be doing something wrong. Can you please help me understand how to use this feature properly? Thank you so much!\"\n      },\n      {\n        \"MessageId\": 317,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the distance alert feature on the HydroTech 5000 will notify you when you are straying too far from your designated route. To set the distance limit, navigate to the settings menu using the touch screen and adjust the distance alert parameter. I hope this helps!\"\n      },\n      {\n        \"MessageId\": 318,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Oh, thank you for the information! I didn\\u0027t realize I had to navigate to the settings menu using the touch screen. I\\u0027ll give it a try and let you know how it goes. Thank you again!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 202,\n    \"ProductId\": 58,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 104,\n    \"ShortSummary\": \"Customer excited about setting up geofences for SafeTrail GPS Locator\",\n    \"LongSummary\": \"Customer excited about SafeTrail GPS Locator, asked for tips on setting up geofences. Received detailed instructions, successfully set up geofence, recommended product to friends. Customer highly satisfied. Next agent should continue providing support for any further inquiries.\",\n    \"CustomerSatisfaction\": 8,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 319,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! I just stumbled upon the SafeTrail GPS Locator from GuardianGear and I\\u0027m super excited about it! The idea of setting up virtual boundaries with geofences is so cool! Can you give me some tips on how to make the most out of this feature? I\\u0027m looking to recommend it to my customers and would love to have all the insider info. Thanks a bunch!\"\n      },\n      {\n        \"MessageId\": 320,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"To ensure your safety while using the SafeTrail GPS Locator, you can set up virtual boundaries, also known as geofences, to receive alerts when you enter or leave a specified area. To create a new boundary, tap the \\u0022Add Boundary\\u0022 button within the app. Then, designate the area by setting the desired radius on the map, name the boundary, and save your settings. You can also edit or delete existing boundaries in the app. The SafeTrail GPS Locator app provides a map view of your current location and the option to set up geofencing and customized alerts for specific locations.\"\n      },\n      {\n        \"MessageId\": 321,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"OMG, thank you so much for the tips! I tried setting up a geofence and it worked like a charm! I\\u0027ve already recommended the SafeTrail GPS Locator to two of my friends and they love it too! You guys are the best!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 203,\n    \"ProductId\": 17,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 105,\n    \"ShortSummary\": \"Care Instructions for Amazon Rainforest Camping Jacket\",\n    \"LongSummary\": \"Customer inquired about specific care instructions for the RidgeRunner Weatherproof Jacket in humid/tropical conditions. Agent provided guidance, no further questions from customer. Ticket is open for any additional inquiries.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 322,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the RidgeRunner Weatherproof Jacket and I\\u0027m planning to use it for camping in the Amazon rainforest. I\\u0027m confident that it will provide me with the protection I need in such a challenging environment. However, I wanted to double-check if there are any specific care instructions I should follow considering the humid and tropical conditions. Thank you for your help!\"\n      },\n      {\n        \"MessageId\": 323,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hello, thank you for reaching out to us! According to the product manual, the RidgeRunner Weatherproof Jacket should be stored in a cool, dry place away from direct sunlight when not in use. It\\u0027s also important to avoid folding or compressing the jacket for long periods to maintain its shape and waterproof properties. If you have any further questions, feel free to ask!\"\n      },\n      {\n        \"MessageId\": 324,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the care instructions! I will make sure to store the jacket as advised and avoid folding or compressing it for too long. I appreciate your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 204,\n    \"ProductId\": 65,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 106,\n    \"ShortSummary\": \"Inquiry about Heavy-Duty Versatility\",\n    \"LongSummary\": \"Customer inquiring about the versatility of the Camptech Multi-Tool Camping Gadget for heavy-duty tasks. Advised to contact manufacturer for details. Pending question about handling heavy-duty tasks.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 325,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! I\\u0027m thinking about getting the Camptech Multi-Tool Camping Gadget for my upcoming camping trip, and I wanted to check if it\\u0027s really as versatile as it sounds. I mean, the description says it has a knife, saw, and screwdriver, but I\\u0027m wondering if it can handle heavy-duty tasks like cutting through tough materials or tightening heavy-duty screws. Can\\u0027t wait to hear back and hopefully become best buds with this awesome gadget! Thanks a bunch!\"\n      },\n      {\n        \"MessageId\": 326,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Camptech Multi-Tool Camping Gadget is designed to be a versatile and essential tool for camping adventures. While the manual does not provide specific details about heavy-duty tasks, it emphasizes the gadget\\u0027s ability to handle various camping situations. If you have any concerns about heavy-duty tasks, we recommend reaching out to the manufacturer for further assistance. For warranty information, please refer to the manufacturer\\u0027s support contact details in the user manual.\"\n      },\n      {\n        \"MessageId\": 327,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thanks for the info! I\\u0027ll reach out to the manufacturer to get more details about handling heavy-duty tasks. Can\\u0027t wait to put this gadget to the test! You\\u0027ve been super helpful, best buddy!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 205,\n    \"ProductId\": 30,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 107,\n    \"ShortSummary\": \"Issue with Alpine Chef Cookware Set\",\n    \"LongSummary\": \"Customer Julian Kim reported an issue with the Alpine Chef Camp Cookware Set and was asked for more details on the specific issue. Pending response from the customer to provide more information to assist further.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 328,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Cookware not working as expected. Need help with this.\"\n      },\n      {\n        \"MessageId\": 329,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry to hear that the cookware is not working as expected. To better assist you, could you please provide more details on the specific issue you are facing with the Alpine Chef Camp Cookware Set?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 206,\n    \"ProductId\": 135,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 108,\n    \"ShortSummary\": \"Remote viewing configuration assistance for WideView 360 camera\",\n    \"LongSummary\": \"Customer demands step-by-step remote viewing configuration guidance for WideView 360 camera. They are adamant about not dealing with it on their own.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 330,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I purchased the WideView 360 trail camera and I can\\u0027t figure out how to access the remote viewing feature. This is unacceptable! I demand immediate assistance in setting this up or I will be seeking a refund. I expect better customer support for a product that claims to have advanced features like 4K resolution and panoramic capture.\"\n      },\n      {\n        \"MessageId\": 331,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The WideView 360 trail camera is equipped with advanced remote viewing capabilities, allowing users to monitor the captured panoramic views from a remote location. The user manual provides detailed steps on how to configure the remote viewing feature. According to the manual, the camera offers unparalleled panoramic views with 4K resolution capability and advanced night vision technology.\"\n      },\n      {\n        \"MessageId\": 332,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I demand a step-by-step walkthrough on how to configure the remote viewing feature. I shouldn\\u0027t have to rely on a manual to figure this out. I expect immediate assistance and a resolution to this issue!\"\n      },\n      {\n        \"MessageId\": 333,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"AdventureWorks Support here. According to the manual, the WideView 360 trail camera is equipped with advanced remote viewing capabilities, allowing users to monitor the captured panoramic views from a remote location. The remote viewing feature can be configured using the steps provided in the manual. Would you like me to guide you through the configuration steps?\"\n      },\n      {\n        \"MessageId\": 334,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I demand that you guide me through the configuration steps immediately. I shouldn\\u0027t have to deal with this on my own!\"\n      },\n      {\n        \"MessageId\": 335,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, once the remote viewing configuration is complete, users can access live panoramic views, 4K resolution footage, and night vision feed from the WideView 360 trail camera through the mobile app. The app also provides additional monitoring and recording options for enhanced surveillance.\"\n      },\n      {\n        \"MessageId\": 336,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I expect you to guide me through the configuration steps immediately. I shouldn\\u0027t have to deal with this on my own!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 207,\n    \"ProductId\": 122,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 109,\n    \"ShortSummary\": \"Exposure Settings Assistance Needed\",\n    \"LongSummary\": \"Customer requests detailed instructions on adjusting exposure settings for AdventureCam 4K to improve outdoor photography. Assistance needed to elevate photography skills.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 337,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello! I recently purchased the AdventureCam 4K and I\\u0027m having trouble understanding how to adjust the exposure settings. As an experienced photographer, I pride myself on my technical knowledge and creativity, but I seem to be struggling with this particular feature of the camera. Can you provide me with detailed instructions on how to adjust the exposure settings effectively? I want to make sure my shots are perfectly lit in all lighting conditions, and I believe that mastering this feature will take my outdoor photography to the next level. Any assistance you can provide would be greatly appreciated. Thank you!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 208,\n    \"ProductId\": 60,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 110,\n    \"ShortSummary\": \"Demand for immediate replacement of water bottle used for salad dressing\",\n    \"LongSummary\": \"Customer demands immediate replacement for water bottle used for salad dressing. Refuses to acknowledge warranty. Next agent should address warranty terms and process for replacement.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 338,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I demand that you provide me with a refund for my PureFlow Water Filter Bottle! I used it to store my homemade salad dressing and now it won\\u0027t work properly. This is unacceptable! I expect a replacement bottle at no cost to me immediately.\"\n      },\n      {\n        \"MessageId\": 339,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The PureFlow Water Filter Bottle from H2OZone is designed to remove 99.9% of waterborne bacteria and protozoa, ensuring clean drinking water wherever you go. If the bottle is not working properly, please contact H2OZone customer support for further assistance. The bottle also comes with a limited warranty to ensure your satisfaction. If the problem persists, please refer to the warranty information for details on how to proceed.\"\n      },\n      {\n        \"MessageId\": 340,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I don\\u0027t care about the warranty! I demand a replacement bottle now! This is completely unacceptable and I expect immediate action to resolve this issue!\"\n      },\n      {\n        \"MessageId\": 341,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Based on the manual, the PureFlow Water Filter Bottle comes with a 1-year limited warranty. You can make a warranty claim for manufacturing defects and malfunctions under normal use. For further assistance, please contact H2OZone customer support.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 209,\n    \"ProductId\": 88,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 111,\n    \"ShortSummary\": \"Broken RapidFlow Kayak Paddle in White Water Rapids\",\n    \"LongSummary\": \"Customer Megan Harper reported a broken RapidFlow Kayak Paddle while using it in white water rapids as intended. Inquired about a possible replacement or repair. Waiting for assistance with durability concerns.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 342,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I am reaching out regarding my recent purchase of the WaterWay RapidFlow Kayak Paddle. Unfortunately, the paddle has broken during use and I am in need of assistance. I was using it in white water rapids as intended, and I followed all the safety guidelines outlined in the product manual. I am concerned about the durability of the paddle and would like to inquire about a possible replacement or repair. Your prompt attention to this matter would be greatly appreciated. Thank you.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 210,\n    \"ProductId\": 75,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 113,\n    \"ShortSummary\": \"Inquiry about suitability for hiking\",\n    \"LongSummary\": \"Customer inquires if the Escapesafe GPS Locator Beacon is suitable for hiking. No response yet. Agent to provide product details and suitability for hiking.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 345,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Need to know if Escapesafe GPS Locator Beacon is suitable for hiking. Thanks.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 211,\n    \"ProductId\": 65,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 114,\n    \"ShortSummary\": \"Inquiry about knife, screwdriver, and saw safety and usage\",\n    \"LongSummary\": \"Customer inquired about safety and usage of knife, screwdriver, and saw features. Assistant provided detailed instructions for each feature. Customer successfully used the knife and saw, and will refer to the user manual. No pending questions.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 346,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi, I\\u0027m interested in the Camptech Multi-Tool Camping Gadget. Can you tell me more about the safety precautions and how to properly use the knife, saw, and screwdriver features? Thanks!\"\n      },\n      {\n        \"MessageId\": 347,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The knife on the Camptech Multi-Tool Camping Gadget is a versatile and essential tool for any camping trip. To use the knife, simply slide the safety lock button to the unlock position, then carefully unfold the knife blade. For the screwdriver feature, it is designed to help with small repairs. If you need more detailed instructions, please refer to the user manual for specific guidance.\"\n      },\n      {\n        \"MessageId\": 348,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information. I have unlocked the knife and tried using it, and it worked well. I will refer to the user manual for more details. Can you also provide safety tips for using the saw feature? Thanks!\"\n      },\n      {\n        \"MessageId\": 349,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The saw on the Camptech Multi-Tool Camping Gadget is perfect for cutting through small branches and other wood materials. To use the saw, firmly grip the tool and carefully unfold the saw blade. Use a back and forth motion to saw through the wood, applying gentle pressure as needed. After use, carefully fold the saw blade back into the tool for safe storage. If you need further details, please refer to the user manual.\"\n      },\n      {\n        \"MessageId\": 350,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information. I have successfully used the saw feature and it worked well. I will refer to the user manual for more details if needed. This resolves my enquiry. Thanks!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 212,\n    \"ProductId\": 35,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 115,\n    \"ShortSummary\": \"Material reassurance needed for Alpine Camp Cookware Set\",\n    \"LongSummary\": \"Customer seeks reassurance on the materials used in the CookMaster Alpine Camp Cookware Set. Specific details are requested to ensure top quality and longevity. Pending question about specific materials used.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 351,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I just purchased the CookMaster Alpine Camp Cookware Set and I expect it to be top-notch! I need reassurance that this cookware is as durable and versatile as advertised. I won\\u0027t settle for anything less than the best. If it doesn\\u0027t meet my expectations, I will demand a refund or replacement. I\\u0027m counting on you to provide me with the assistance and information I need to ensure this product performs as expected.\"\n      },\n      {\n        \"MessageId\": 352,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The CookMaster Alpine Camp Cookware Set is designed to be durable and versatile, making it perfect for all your camping kitchen needs. It is essential to clean and store your Alpine Camp Cookware Set properly to maintain its quality and longevity. According to the user manual, the set is just what you need to make your camping cooking experience a breeze!\"\n      },\n      {\n        \"MessageId\": 353,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I appreciate the information, but I need more reassurance. Can you provide specific details about the materials used in the CookMaster Alpine Camp Cookware Set? I want to make sure it\\u0027s top quality and will last for many camping trips to come.\"\n      },\n      {\n        \"MessageId\": 354,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The materials used in the CookMaster Alpine Camp Cookware Set are not specifically mentioned in the user manual. However, the set is designed to be durable and versatile, making it perfect for all your camping kitchen needs.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 213,\n    \"ProductId\": 142,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 116,\n    \"ShortSummary\": \"Refund demand due to manual oversight\",\n    \"LongSummary\": \"Customer demands a refund for oversight in manual details about washing the hammock. Assistant responded with apology and offer for further assistance. Next agent should process refund if necessary.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 355,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am absolutely livid that the manual didn\\u0027t mention the specific type of mild detergent to use when machine washing the hammock! How could you overlook such an important detail? I demand a refund for this oversight!\"\n      },\n      {\n        \"MessageId\": 356,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, when machine washing the hammock, you should use a mild detergent and avoid any harsh chemicals or bleach. I apologize for the oversight and thank you for bringing this to our attention. If you require any further assistance, please don\\u0027t hesitate to contact us.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 214,\n    \"ProductId\": 61,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 30,\n    \"ShortSummary\": \"SOS feature troubleshooting request\",\n    \"LongSummary\": \"Customer experiencing issues with SOS feature on Satellite Communicator 2000, seeking troubleshooting steps. Pending question: troubleshooting steps.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 357,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Adventure Link Satellite Communicator 2000 and I\\u0027m encountering some issues with the SOS feature. When I tried to activate the emergency signal, nothing happened. I made sure the device had a clear line of sight to the sky, but still no luck. Can you provide me with some troubleshooting steps to resolve this issue? Thank you.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 215,\n    \"ProductId\": 52,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 117,\n    \"ShortSummary\": \"Inquiries on emergency beacon testing and battery maintenance\",\n    \"LongSummary\": \"Customer inquires about testing schedule for emergency beacon and battery maintenance. Assistant warns against device maintenance and unauthorized charger use.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 358,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I am considering using the Trailcom Trailblazer Off-Grid Communicator for my upcoming outdoor expedition. I am well-versed in emergency protocols and regulations and understand the gravity of activating the Emergency SOS Beacon. However, I have a specific testing schedule for the beacon in mind and would like to confirm the designated testing times recommended by Trailcom. Additionally, I am aware of the rechargeable lithium-ion battery and the importance of using the provided charger. Can you provide me with detailed information on the battery maintenance and the potential risks associated with using any other charger? Your prompt assistance will be greatly appreciated.\"\n      },\n      {\n        \"MessageId\": 359,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Trailblazer Off-Grid Communicator is not designed for regular maintenance. Attempting to perform any maintenance or repairs on the device may result in damage to the product and void the warranty. Please do not attempt to open the device or access its internal components. Additionally, the device is equipped with a rechargeable lithium-ion battery, and it is crucial to only use the provided charger to recharge the battery. The use of any other charger may lead to overheating, fire, or explosion. Do not attempt to replace the battery yourself - this should only be done by authorized service personnel.\"\n      },\n      {\n        \"MessageId\": 360,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information provided. I understand the importance of following the manufacturer\\u0027s recommendations for maintenance and charging to ensure the safety and proper functioning of the device. I will strictly adhere to the guidelines mentioned in the manual. I appreciate your prompt assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 216,\n    \"ProductId\": 133,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 118,\n    \"ShortSummary\": \"Warranty coverage for wild animal encounters in extreme conditions\",\n    \"LongSummary\": \"Customer Oliver asked if the warranty covers encounters with wild animals in extreme conditions like the Amazon rainforest. Confirms if this is normal wear and tear.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 361,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello Strategicgear team, my name is Oliver and I recently purchased your TactiX 3000 backpack. I\\u0027m planning to take it on a camping trip to the Amazon rainforest and I\\u0027m confident it will hold up to the extreme conditions there. I just wanted to confirm that the warranty covers any unexpected encounters with wild animals, like if a jaguar tries to claw its way into my backpack. I assume this falls under normal wear and tear, right? Thanks for your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 217,\n    \"ProductId\": 131,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 119,\n    \"ShortSummary\": \"NatureCam 1000 troubleshooting\",\n    \"LongSummary\": \"NatureCam 1000 not functioning properly, customer needs assistance. Pending question: what specific issue are they experiencing? Response needed: troubleshooting steps.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 362,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi, I\\u0027m having an issue with my NatureCam 1000 and need help. It\\u0027s not working properly and I\\u0027m not sure what to do. Can you please assist me with this? Thanks.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 218,\n    \"ProductId\": 31,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 120,\n    \"ShortSummary\": \"Issue with igniting Nomad Camping Stove\",\n    \"LongSummary\": \"Customer struggling to ignite Nomad Camping Stove, followed manual instructions. Needs further troubleshooting assistance. Pending question on specific troubleshooting steps.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 363,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear WanderStove Customer Support Team, I recently purchased the Nomad Camping Stove and have encountered an issue with difficulty igniting the stove. I have ensured that the fuel valve is fully open and checked for any blockages in the fuel canister, but I am still unable to ignite the stove. Could you please provide me with further assistance on troubleshooting this issue? Thank you for your prompt attention to this matter. Sincerely, Nadia Patel\"\n      },\n      {\n        \"MessageId\": 364,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Nomad Camping Stove is now set up and ready for use. If the issue persists or cannot be resolved, please contact our customer support team at support@wanderstove.com for further assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 219,\n    \"ProductId\": 129,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 121,\n    \"ShortSummary\": \"Trouble with SIM card after wiping contacts\",\n    \"LongSummary\": \"Customer purchased TrailFax Mini, having trouble with SIM card after wiping contacts. Needs help figuring it out. Pending question: \\u0027Am I doing something wrong?\\u0027 Require troubleshooting assistance.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 365,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the TrailFax Mini and I\\u0027m having trouble with the SIM card. I tried wiping the contacts as suggested in the troubleshooting section, but the issue still persists. I\\u0027m a bit embarrassed to admit it, but I\\u0027m not sure if I\\u0027m doing something wrong. Can you please help me figure this out? Thank you so much.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 220,\n    \"ProductId\": 178,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 122,\n    \"ShortSummary\": \"Energy claims and packaging issues\",\n    \"LongSummary\": \"Customer is dissatisfied with the PowerBar Pro 2021\\u0027s energy boosting claims and difficult packaging. They seek an explanation and solution. Pending question: Can you offer a solution to these discrepancies?\",\n    \"CustomerSatisfaction\": 3,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 370,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I don\\u0027t understand why the PowerBar Pro 2021 is marketed as a high-energy option for adventure activities. I\\u0027ve tried it and it didn\\u0027t give me the boost I was expecting. Plus, the packaging was difficult to open despite the manual\\u0027s claim that it\\u0027s easy. Can you explain these discrepancies and offer a solution?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 221,\n    \"ProductId\": 145,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 123,\n    \"ShortSummary\": \"Compatibility of PowerBeam Solar Charger with older devices\",\n    \"LongSummary\": \"Customer inquires about compatibility of PowerBeam Solar Powered Portable Charger with older devices. Pending question regarding charger compatibility with older devices. Next support agent should address the pending question and provide specific compatibility details.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 371,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I\\u0027m interested in purchasing the PowerBeam Solar Powered Portable Charger for an upcoming camping trip. I\\u0027m a bit worried about whether it will be able to charge my older devices, as I know that some older devices may not be compatible with solar chargers. Can you please advise if this charger will work with older devices? Thanks!\"\n      },\n      {\n        \"MessageId\": 372,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, some older devices may not be able to charge using solar power. If you have further questions or need assistance, please contact our customer support team for further assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 222,\n    \"ProductId\": 157,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 124,\n    \"ShortSummary\": \"Trouble with Waterproof Casing for 360X Action Camera\",\n    \"LongSummary\": \"Customer is frustrated with the waterproof casing instructions for the 360X Action Camera, finding the manual unhelpful. Specific questions on how to use the casing have been raised. A clear explanation on how to properly use the waterproof casing is needed.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 373,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I just bought the 360X Action Camera and I can\\u0027t figure out how to use the waterproof casing. The manual is not helpful at all. It says to open the casing in a dry environment - well duh, of course I wouldn\\u0027t open it underwater! And then it talks about testing the casing by submerging it in water, which doesn\\u0027t make sense at all. I need some real help here, not just nonsense from the manual. This is so frustrating!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 223,\n    \"ProductId\": 8,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 8,\n    \"ShortSummary\": \"Data privacy and compliance reassurance request for Outdoor Admin 5000\",\n    \"LongSummary\": \"Customer recently purchased the Outdoor Admin 5000 and wants reassurance on data privacy and compliance with laws and regulations. Assistant provided info on data security and legal compliance.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 374,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Outdoor Admin 5000 and I just want to make sure that it is behaving as expected. I love the idea of managing my itinerary and emergency contacts all in one device, but I want to be sure that the data privacy and compliance with laws and regulations are being upheld. Can you provide me with some reassurance on this? Thank you.\"\n      },\n      {\n        \"MessageId\": 375,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the user manual, the Outdoor Admin 5000 collects and stores itinerary and emergency contact information for your convenience, and this data is kept secure and is never shared with third parties without your consent. In addition, it is important to comply with all local laws and regulations regarding the use of electronic devices, including data privacy laws and regulations pertaining to emergency communication devices.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 224,\n    \"ProductId\": 49,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 125,\n    \"ShortSummary\": \"Maintenance advice for Summit Hiking Boots\",\n    \"LongSummary\": \"Customer seeks advice on cleaning and maintaining Summit Hiking Boots from TrekMaven for future hikes. Needs detailed tips for upkeep.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 376,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! Just wanted to share how much I adore my Summit Hiking Boots from TrekMaven. These bad boys have been with me through some seriously rugged terrain, and they\\u0027ve never let me down. But hey, I\\u0027ve been trying to find the best way to keep them in top shape after all the adventures we\\u0027ve been on together. Any tips on cleaning and maintaining these beauties? I want to make sure they stay in tip-top condition for many more thrilling hikes to come! Thanks a bunch!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 225,\n    \"ProductId\": 58,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 126,\n    \"ShortSummary\": \"Troubleshooting SafeTrail GPS Locator\",\n    \"LongSummary\": \"Customer Lila Chen is having issues with SafeTrail GPS Locator and needs help figuring out what\\u0027s wrong. No specific details provided. Agent response with troubleshooting steps needed.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 377,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027m having trouble with my SafeTrail GPS Locator. It\\u0027s not working as expected. Can you please help me figure out what\\u0027s wrong?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 226,\n    \"ProductId\": 9,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 127,\n    \"ShortSummary\": \"Unhappy with AltitudeShield Pro at high altitude\",\n    \"LongSummary\": \"Customer is unhappy about AltitudeShield Pro not working at high altitude as advertised. Wants refund but is informed it\\u0027s not possible due to product specifications. Request to speak to manager.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 378,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, I got the AltitudeShield Pro for my mountain baking but it doesn\\u0027t seem to be working at all. Can you help me figure out what\\u0027s going on?\"\n      },\n      {\n        \"MessageId\": 379,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the AltitudeShield Pro is not suitable for use in any environment other than high-altitude locations. It should not be used to protect cakes or baked goods at sea level or in normal atmospheric conditions. If you require further assistance, please feel free to contact our support team.\"\n      },\n      {\n        \"MessageId\": 380,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027m at high altitude and it\\u0027s still not working. What should I do now?\"\n      },\n      {\n        \"MessageId\": 381,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the AltitudeShield Pro is a highly specialized product that must not be used in any way other than explicitly outlined in the user manual. It is also not suitable for use in high-altitude environments. SummitChomp strongly advises against setting up the AltitudeShield Pro in any environment, as it poses a significant risk to both the user and their surroundings. Due to the extreme nature of the environment, SummitChomp cannot guarantee the functionality of the AltitudeShield Pro at high altitudes and therefore cannot offer any warranty coverage for such usage. Unfortunately, SummitChomp does not accept returns for the AltitudeShield Pro if it has been used in high-altitude environments. Once the product has been used in such conditions, it is not eligible for return or refund. I recommend discontinuing the use of the AltitudeShield Pro and ensuring that it is handled safely according to the manufacturer\\u0027s instructions. If you have any further questions, please feel free to contact our support team.\"\n      },\n      {\n        \"MessageId\": 382,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"This is ridiculous. I just want my money back!\"\n      },\n      {\n        \"MessageId\": 383,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the AltitudeShield Pro is not suitable for use in high-altitude environments. SummitChomp strongly advises against setting up the AltitudeShield Pro in any environment, as it poses a significant risk to both the user and their surroundings. Due to the extreme nature of the environment, SummitChomp cannot guarantee the functionality of the AltitudeShield Pro at high altitudes and therefore cannot offer any warranty coverage for such usage. Unfortunately, SummitChomp does not accept returns for the AltitudeShield Pro if it has been used in high-altitude environments. I recommend discontinuing the use of the AltitudeShield Pro and ensuring that it is handled safely according to the manufacturer\\u0027s instructions. If you have any further questions, please feel free to contact our support team.\"\n      },\n      {\n        \"MessageId\": 384,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I want to speak to a manager. This is unacceptable.\"\n      },\n      {\n        \"MessageId\": 385,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the user manual, the AltitudeShield Pro is highly specialized and not suitable for use in any environment other than high-altitude locations. SummitChomp strongly advises against setting up the AltitudeShield Pro in any environment as it poses a significant risk. Due to the extreme nature of the environment, SummitChomp cannot guarantee the functionality of the AltitudeShield Pro at high altitudes and therefore cannot offer any warranty coverage for such usage. Unfortunately, returns are not accepted for the AltitudeShield Pro if it has been used in high-altitude environments. I recommend ensuring that the product is handled safely according to the manufacturer\\u0027s instructions. If you have any further questions, please feel free to contact our support team or refer to the user manual for more details.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 227,\n    \"ProductId\": 165,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 128,\n    \"ShortSummary\": \"Inquiry about safety and intended use for potential business\",\n    \"LongSummary\": \"Customer inquiring about safety precautions and intended use of product for potential business purposes. Looking for detailed information before recommending to customers.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 386,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there OutdoorHaven team! I just stumbled upon your Rugged Shelter 600 and I am absolutely loving the idea of finding refuge in the great outdoors with this beauty. The fact that it\\u0027s weatherproof and easy to set up is music to my ears! I\\u0027m actually thinking of stocking it in my own shop, and I was wondering if you could provide me with some more information about the safety precautions and intended use of the shelter. It\\u0027s always great to have all the details before recommending a product to my customers. Looking forward to your response, and hoping we can be business besties!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 228,\n    \"ProductId\": 90,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 129,\n    \"ShortSummary\": \"Performance issue with PurifyPro Water Filter Pump\",\n    \"LongSummary\": \"Customer demands replacement or full refund for PurifyPro Water Filter Pump performance issues. Needs further assistance with product operation.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 387,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am so frustrated with this PurifyPro Water Filter Pump by AquaFusion! I took it on a hiking trip and it barely filtered any water. I thought it was supposed to remove 99.9999% of bacteria, but I ended up getting sick! I need to know if this product is actually suitable for outdoor use or if I just wasted my money. This is unacceptable and I expect a resolution!\"\n      },\n      {\n        \"MessageId\": 388,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The PurifyPro Water Filter Pump by AquaFusion is specifically designed for outdoor use and is engineered to remove 99.9999% of waterborne bacteria, ensuring a safe and reliable source of drinking water during camping, hiking, or other outdoor activities. According to the manual, it is constructed using high-quality, durable materials to ensure reliable performance in various outdoor conditions. To ensure proper operation, prime the pump by pumping the handle several times until water flows through the system. Once primed, the PurifyPro Water Filter Pump is ready for use in purifying water for consumption. If you have any further questions or need assistance with the product, please feel free to ask.\"\n      },\n      {\n        \"MessageId\": 389,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I followed the instructions and primed the pump by pumping the handle several times, but it still barely filters any water! I am extremely disappointed with the performance of this PurifyPro Water Filter Pump and I do not accept this resolution. I demand a replacement or a full refund!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 229,\n    \"ProductId\": 43,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 130,\n    \"ShortSummary\": \"Outdoor Suitability for NightOps Tactical Flashlight\",\n    \"LongSummary\": \"Customer inquires about the suitability of NightOps Tactical Flashlight for camping and hiking in rugged conditions. Assistant confirms its outdoor suitability and provides assurance for reliability. No further action needed from the support agent at this time.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 390,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there! I\\u0027m thinking about getting the NightOps Tactical Flashlight for camping and hiking. I\\u0027ve heard it\\u0027s super bright and durable, so I\\u0027m hoping it will be perfect for outdoor adventures. Can you confirm if it\\u0027s suitable for outdoor use, especially in rugged conditions? I want to make sure it can handle the elements and provide reliable light when I need it the most. Thanks for your help!\"\n      },\n      {\n        \"MessageId\": 391,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The NightOps Tactical Flashlight is designed to meet the needs of outdoor enthusiasts and is suitable for rugged conditions. It is built to provide reliable light in outdoor adventures. According to the manual, whether you\\u0027re a professional in the field or a devoted outdoor enthusiast, the NightOps Tactical Flashlight is designed to meet your needs and exceed your expectations.\"\n      },\n      {\n        \"MessageId\": 392,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Great, thanks for the information! I\\u0027m excited to take the NightOps Tactical Flashlight on my next camping trip. I\\u0027ll let you know how it goes!\"\n      },\n      {\n        \"MessageId\": 393,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The NightOps Tactical Flashlight is designed to withstand rugged outdoor conditions. It is built for outdoor use and is suitable for camping and hiking as well. We\\u0027re confident it will meet your needs on your next adventure!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 230,\n    \"ProductId\": 54,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 132,\n    \"ShortSummary\": \"Probe deployment assistance needed\",\n    \"LongSummary\": \"Customer needs tips on how to effectively use the probe on their AvalanchePro Ski Backpack. They are eager to hit the slopes and any practical advice would be greatly appreciated.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 400,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! I recently purchased the AvalanchePro Ski Backpack from PowderPeak and I\\u0027m absolutely stoked about it! The avalanche safety gear storage is such a game-changer, and the ergonomic design is seriously top-notch. But I\\u0027m having a little trouble with the probe deployment. Can you give me some tips on how to use it effectively? I\\u0027m just itching to get out there and hit the slopes, so any help would be greatly appreciated! Thanks a bunch, team!\"\n      },\n      {\n        \"MessageId\": 401,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, in the event of an avalanche burial, you should quickly deploy your probe by removing it from the designated compartment on your AvalanchePro Ski Backpack. This will ensure you are prepared for any backcountry emergency.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 231,\n    \"ProductId\": 74,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 5,\n    \"ShortSummary\": \"Technical questions about hammock materials, weight distribution, and usage.\",\n    \"LongSummary\": \"Customer Evan Thompson has technical questions about the Naturehaven Ultra-Light Hammock, including the materials, weight distribution, carabiners, tree straps, recommended usage scenarios, and specific environmental conditions. Pending response needed on the specific materials used, weight distribution, engineering behind carabiners and tree straps, and recommended usage scenarios or specific environmental conditions. Provide detailed information to address customer\\u0027s technical questions.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 402,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I am considering purchasing the Naturehaven Ultra-Light Hammock and I have a few technical questions before making my decision. Can you provide me with information on the specific materials used to construct the hammock? I am also curious about the weight distribution and the engineering behind the carabiners and tree straps included. Additionally, I would like to know if there are any recommended usage scenarios or if there are any specific environmental conditions in which the hammock should not be used. Thank you for your assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 232,\n    \"ProductId\": 31,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 133,\n    \"ShortSummary\": \"Clogged burner issue with Nomad Camping Stove\",\n    \"LongSummary\": \"Customer is frustrated with Nomad Camping Stove, experiencing clogged burner despite following cleaning instructions. Needs resolution ASAP or refund. Specific details about cleaning instructions and return policy requested.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 403,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am so frustrated with my Nomad Camping Stove from WanderStove! I expected it to be lightweight and fuel-efficient, but it\\u0027s not performing as described. The burner keeps getting clogged, and I followed the cleaning instructions in the manual, but it\\u0027s still not working properly. I need reassurance that this product is supposed to work this way, or else I want a refund!\"\n      },\n      {\n        \"MessageId\": 404,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Based on the manual, the Nomad Camping Stove is designed to make cooking in the great outdoors a breeze, and it is specifically designed to meet the needs of campers, hikers, and adventurers. This includes ensuring that they can enjoy delicious meals even in remote locations. However, I will also look up the specific details about the cleaning instructions and the return policy for you.\"\n      },\n      {\n        \"MessageId\": 405,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I followed the cleaning instructions again, but the burner is still getting clogged. I need this issue resolved ASAP, or I want a refund!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 233,\n    \"ProductId\": 25,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 134,\n    \"ShortSummary\": \"Inquiry about TerraScoop\\u0027s capability for leveling uneven ground\",\n    \"LongSummary\": \"Customer inquired about TerraScoop\\u0027s capability for leveling uneven ground. Received assurance of its performance for this task. Customer will proceed with purchase and reach out if needed.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 406,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I am considering purchasing the TerraScoop Excavation Tool from DigDigDig for some outdoor projects. Before I make my purchase, I would like to inquire about the tool\\u0027s capability for leveling uneven ground. Can the TerraScoop efficiently handle this task? Any guidance on this matter would be greatly appreciated. Thank you for your time.\"\n      },\n      {\n        \"MessageId\": 407,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The TerraScoop Excavation Tool is engineered to meet your excavation needs with unparalleled precision and efficiency. It boasts exceptional performance and unmatched versatility in various outdoor applications, making it well-suited for leveling uneven ground. According to the manual, it is tailored to provide exceptional performance in this regard. If you have any further questions or need assistance, feel free to reach out. AdventureWorks Support\"\n      },\n      {\n        \"MessageId\": 408,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information. I appreciate your prompt and helpful response. I will go ahead and make the purchase of the TerraScoop Excavation Tool based on your assurance of its capability for leveling uneven ground. I look forward to using it for my outdoor projects. If I encounter any issues, I will not hesitate to reach out to you for further assistance. Thank you again for your help.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 234,\n    \"ProductId\": 124,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 135,\n    \"ShortSummary\": \"Inquiry about SurvivalPro 2000\\u0027s extreme weather durability\",\n    \"LongSummary\": \"Customer Marissa Thompson is seeking detailed information on the SurvivalPro 2000\\u0027s durability and performance in extreme weather conditions before making a purchase. A prompt and thorough response addressing these specific concerns is needed.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 409,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I need to know if the SurvivalPro 2000 can withstand extreme weather conditions without any damage. I expect it to be able to handle anything, so I need a detailed explanation of its durability and performance in harsh environments. I\\u0027m considering making a purchase, but only if I\\u0027m satisfied with this information. I expect a prompt and thorough response before I make any decisions.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 235,\n    \"ProductId\": 73,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 136,\n    \"ShortSummary\": \"Maintenance inquiry for carbon fiber body\",\n    \"LongSummary\": \"Customer inquires about maintenance recommendations for the carbon fiber body. Specific insights needed. Prompt detailed response required.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 410,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Greetings, I am reaching out with a technical inquiry regarding the SkySight Eagle Eye 1000 Drone. As a retailer of this exceptional product, I am keen to ensure that I have a comprehensive understanding of its features and capabilities to better serve my customers. Could you provide detailed information on the drone body\\u0027s material composition, specifically addressing its carbon fiber composite construction? Additionally, any insights on the pre-flight checklist and safety precautions outlined in the manual would be greatly appreciated. My aim is to offer precise and accurate guidance to our clientele, and your assistance in this matter will contribute to achieving that goal. Thank you for your attention to this matter.\"\n      },\n      {\n        \"MessageId\": 411,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The SkySight Eagle Eye 1000 Drone features a lightweight yet durable carbon fiber composite material for its body construction. Additionally, the pre-flight checklist includes ensuring the drone is in optimal condition for safe operation, and the safety precautions emphasize adherence to guidelines for user and environmental well-being.\"\n      },\n      {\n        \"MessageId\": 412,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information provided. I have reviewed the details on the carbon fiber composite material and the pre-flight checklist. However, I would like to inquire further about the specific maintenance recommendations for ensuring the longevity and performance of the drone, particularly in relation to the carbon fiber body. Could you provide detailed insights on this matter? Your prompt response is greatly appreciated.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 236,\n    \"ProductId\": 123,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 137,\n    \"ShortSummary\": \"Product Inquiry: SolarCopy 3000\",\n    \"LongSummary\": \"Inquiry about SolarCopy 3000. Questions about environmental conditions and mounting best practices. Assistant provided info on monitoring and advanced diagnostic tests, pending further questions.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 413,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Good day, I hope this message finds you well. I am inquiring about the SolarCopy 3000 from Nature\\u0027s Photocopier. We are considering stocking this product in our store and have some queries regarding its assembly and installation process. Specifically, we would like to know more about the recommended environmental conditions for the SolarCopy 3000 and the best practices for securing its mounting. Any insight or guidance you can provide would be greatly appreciated. Thank you for your time and assistance.\"\n      },\n      {\n        \"MessageId\": 414,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Nature\\u0027s Photocopier SolarCopy 3000 manual recommends monitoring the ambient temperature, humidity, and sunlight levels at the intended installation site to ensure they fall within the recommended range. For mounting, advanced diagnostic tests can reveal abnormalities, and if needed, Nature\\u0027s Photocopier technical support can provide further guidance and potential servicing. If you have any other questions, feel free to ask.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 237,\n    \"ProductId\": 86,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 138,\n    \"ShortSummary\": \"SOS Multitool Kit Fire Starter Issue\",\n    \"LongSummary\": \"Customer frustrated with fire starter in SOS Multitool Kit. Asked for replacement or refund. Assistant provided troubleshooting tips.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 415,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am extremely frustrated with the SOS Multitool Kit. I tried using the fire starter as instructed, but it simply won\\u0027t work! I expected better quality from Survive All. I demand a replacement or a full refund for this faulty product.\"\n      },\n      {\n        \"MessageId\": 416,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry to hear about the trouble you\\u0027re experiencing with the fire starter. According to the manual, when starting a fire, it\\u0027s important to have suitable tinder to catch the sparks from the fire starter. Additionally, there\\u0027s a troubleshooting section in the manual for addressing any difficulties with the fire starter. If the issue persists, please feel free to reach out to our customer support team for further assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 238,\n    \"ProductId\": 56,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 119,\n    \"ShortSummary\": \"Difficulty Rolling Up Sleeping Bag\",\n    \"LongSummary\": \"Customer unable to roll up sleeping bag despite following manual. Requesting a better solution. Next support agent should offer advanced troubleshooting or escalate to Slumberpeak\\u0027s support.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 417,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I purchased the Naptime 5000 Sleeping Bag from Slumberpeak and I can\\u0027t get it to roll up tight as described in the manual. This is ridiculous, it\\u0027s supposed to be lightweight and easy to pack, but it\\u0027s just not working for me. I demand a solution to this problem!\"\n      },\n      {\n        \"MessageId\": 418,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, after using the Naptime 5000 Sleeping Bag, it should be rolled up tightly, starting from the foot end towards the hood end. The rolled bag should then be secured with the included compression straps to minimize space. I hope this helps with packing the sleeping bag more effectively!\"\n      },\n      {\n        \"MessageId\": 419,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I followed the instructions in the manual exactly as you said, and it still won\\u0027t roll up tight! This is ridiculous! I demand a better solution to this problem!\"\n      },\n      {\n        \"MessageId\": 420,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I apologize for the inconvenience. According to the manual, after using the Naptime 5000 Sleeping Bag, it should be rolled up tightly, starting from the foot end towards the hood end. The rolled bag should then be secured with the included compression straps to minimize space. If the bag is not rolling up as expected, it may be helpful to ensure that the bag is evenly and tightly rolled. If you are still experiencing issues, we recommend contacting Slumberpeak\\u0027s support for further assistance.\"\n      },\n      {\n        \"MessageId\": 421,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I did what you suggested and rolled up the sleeping bag again, making sure it was evenly and tightly rolled. Still no luck, it\\u0027s just not working as described in the manual. This is ridiculous!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 239,\n    \"ProductId\": 93,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 139,\n    \"ShortSummary\": \"Product Performance Reassurance\",\n    \"LongSummary\": \"Customer is pleased with the SunChef Solar Powered Stove\\u0027s performance and results. No further assistance is needed at this time.\",\n    \"CustomerSatisfaction\": 8,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 422,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear Solarchef Customer Support, I recently purchased the SunChef Solar Powered Stove and I just want to make sure that it is behaving as expected. I love the idea of cooking off-grid with renewable solar energy, and I want to ensure that I am getting the most out of this eco-friendly product. Could you provide me with some reassurance that the product is working as intended? Thank you for your assistance.\"\n      },\n      {\n        \"MessageId\": 423,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Congratulations! Your SunChef Solar Powered Stove is now charged and ready to use. With the assembly complete and the stove charged, you are all set to start cooking delicious meals using renewable solar energy. If you have any technical questions or need further assistance, please refer to the user manual or contact Solarchef customer support.\"\n      },\n      {\n        \"MessageId\": 424,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for your response. I have followed the instructions in the user manual and successfully cooked a meal using the SunChef Solar Powered Stove. It is working perfectly and I am delighted with the results. I appreciate your assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 240,\n    \"ProductId\": 25,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 140,\n    \"ShortSummary\": \"Technical question about rocky soil handling\",\n    \"LongSummary\": \"Customer excited about TerraScoop but has specific technical question about handling rocky soil. Needs expertise and advice on the tool\\u0027s capabilities. Pending question about soil type.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 428,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there, DigDigDig team! I just got my hands on the TerraScoop Excavation Tool and I\\u0027m over the moon about it! I read about the multifunctional blade in the product description and I can\\u0027t wait to put it to the test. But before I go full-on excavation mode, I\\u0027ve got a specific technical question for you all. Can this amazing tool handle rocky soil with ease, or should I stick to softer ground? Your expertise would be a real lifesaver! Thanks a bunch!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 241,\n    \"ProductId\": 74,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 141,\n    \"ShortSummary\": \"Hammock sagging issue\",\n    \"LongSummary\": \"Customer reports hammock sagging. Assistant suggests adjusting tension by retying straps or using different loops. Pending: response from customer on whether this solution worked.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 429,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hammock sags too much, help\"\n      },\n      {\n        \"MessageId\": 430,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"If everything looks good with the setup, it might just be that the fabric has stretched out a bit. Try adjusting the tension by retying the straps or using different loops on the hammock to get the right amount of sag.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 242,\n    \"ProductId\": 134,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 142,\n    \"ShortSummary\": \"SolarFire 2000 Charging Issue\",\n    \"LongSummary\": \"Dr. Samantha Chen has encountered issues with the SolarFire 2000\\u0027s charging function despite following the product description. She suspects an issue with the solar panel or USB port and requires guidance on repair or replacement.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 431,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello EcoGizmo customer support, I recently purchased the SolarFire 2000 camping stove and have encountered an issue with the device charging function. As an expert in solar-powered technology, I have meticulously followed the product description and manual, yet I am unable to make the device charge my devices. I have ensured that the solar panels are receiving sufficient sunlight and that the USB port is not damaged. I would appreciate your technical expertise in resolving this matter, as I believe the issue may lie in the solar panels or the USB port. If necessary, I may need further assistance in the form of a repair or replacement. Your prompt and detailed response is highly anticipated. Thank you for your attention to this matter.\"\n      },\n      {\n        \"MessageId\": 432,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, to charge your devices with the SolarFire 2000, simply connect them to the USB port on the solar panel using the provided charging cable. The solar panel is most effective when exposed to direct sunlight, and the charging speed will vary depending on the quality of the sunlight and the device being charged.\"\n      },\n      {\n        \"MessageId\": 433,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for your response. I have indeed connected my devices to the USB port on the solar panel using the provided charging cable, and have ensured that the solar panel is exposed to direct sunlight. However, despite these measures, I am still unable to charge my devices. I suspect that there may be an issue with either the solar panel or the USB port. I would appreciate further guidance on how to troubleshoot this issue or if a repair or replacement may be necessary.\"\n      },\n      {\n        \"MessageId\": 434,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We take great pride in the quality of our products and want you to experience the utmost satisfaction with your SolarFire 2000. In the unlikely event that you encounter any issues, please do not hesitate to contact our dedicated customer service team, who will be more than happy to assist you.\"\n      },\n      {\n        \"MessageId\": 435,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I have performed further troubleshooting and have determined that the solar panel is not producing the expected output voltage, which is causing the issue with charging my devices. I would appreciate guidance on how to proceed with a repair or replacement of the solar panel.\"\n      },\n      {\n        \"MessageId\": 436,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Assembling your SolarFire 2000 is a delicate process that requires precision and finesse. First, unfold the solar panel and position it in direct sunlight, ensuring that it is at an optimal angle for maximum solar absorption. Then, unfold the stove by gently lifting the top cover and locking it in place.\"\n      },\n      {\n        \"MessageId\": 437,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the detailed instructions. I have followed the steps you outlined, but unfortunately, the solar panel is still not producing the expected output voltage. It seems that there may be a technical issue with the solar panel itself. I would appreciate further guidance on how to proceed with a repair or replacement of the solar panel, as this issue is preventing me from fully utilizing the SolarFire 2000.\"\n      },\n      {\n        \"MessageId\": 438,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Based on the manual, it is important to ensure that the stove is positioned in direct sunlight to allow the solar panel to effectively charge devices. Additionally, please check the solar panel connections for any damage. If the issue persists, please position the devices in a safe and secure location near the solar panel, allowing them to bask in the sunlight. If these measures do not resolve the issue, please contact our dedicated customer service team for further assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 243,\n    \"ProductId\": 25,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 143,\n    \"ShortSummary\": \"Gardening tips for TerraScoop Excavation Tool\",\n    \"LongSummary\": \"Customer purchased TerraScoop Excavation Tool and seeks tips for using it in the garden. No response yet. Next agent should provide gardening tips and usage advice.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 439,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi, I just bought the TerraScoop Excavation Tool and I can\\u0027t wait to use it for gardening. I\\u0027m sure it\\u0027ll be great for planting flowers and digging up weeds. Do you have any tips for using it in the garden? Thanks!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 244,\n    \"ProductId\": 69,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 144,\n    \"ShortSummary\": \"Misleading product description demands full refund and compensation\",\n    \"LongSummary\": \"Customer demands full refund and compensation for misleading product description. Return process offered, awaiting response on next steps.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 440,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am extremely disappointed with the Summit Step Alpine Explorer Hiking Boots. I was promised exceptional performance and comfort during challenging hikes, but I have not experienced that at all! The aggressive tread pattern and shock-absorbing midsole are not living up to their claims and I demand a solution to this issue immediately. I expect a full refund for this misleading product description and false advertising. I will not tolerate being misled about the features and performance of these boots. I demand a response and a resolution to this matter without any further delay.\"\n      },\n      {\n        \"MessageId\": 441,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We apologize for your disappointment with the Summit Step Alpine Explorer Hiking Boots. According to the manual, the boots are designed to provide exceptional performance and comfort during challenging hikes, featuring a waterproof and breathable membrane for comfort in various weather conditions, and an aggressive tread pattern and shock-absorbing midsole for superior traction and comfort on rugged terrain. It appears that the boots are not meeting these specifications for you. We would be happy to facilitate a return for a full refund within 30 days of purchase, provided the product is unused. You may initiate the return process at https://northernmountains.example.com/support/returns. Thank you for bringing this to our attention, and we apologize for any inconvenience this may have caused.\"\n      },\n      {\n        \"MessageId\": 442,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I appreciate the offer for a return, but I am still extremely disappointed with the misleading product description and false advertising. I demand a full refund and compensation for the inconvenience and disappointment caused. I expect a response to this demand without any further delay.\"\n      },\n      {\n        \"MessageId\": 443,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We understand your frustration and we apologize for the inconvenience this has caused. As per our policy, we can facilitate a return for a full refund within 30 days of purchase, provided the product is unused. You may initiate the return process at https://northernmountains.example.com/support/returns. If you have any further questions or need assistance with the return process, please let us know. Thank you for bringing this issue to our attention.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 245,\n    \"ProductId\": 34,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 145,\n    \"ShortSummary\": \"WildView HD Trail Camera setup and wildlife capture\",\n    \"LongSummary\": \"Customer unsure if WildView HD Trail Camera is set up correctly, not capturing wildlife yet. Asked for reassurance. Assistant explained camera is motion-activated. Customer will move camera to a different spot and will update on its performance.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 444,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I just purchased the WildView HD Trail Camera and I\\u0027m so excited to start using it! I\\u0027m a bit unsure if I\\u0027ve set it up correctly though. I\\u0027ve mounted it on a tree and inserted the batteries and SD card, but I\\u0027m not sure if it\\u0027s working as it should. I haven\\u0027t seen any wildlife captured yet, but maybe it takes some time? Can you please reassure me that I\\u0027ve done everything right and that the camera will start capturing wildlife soon? Thank you so much for your help!\"\n      },\n      {\n        \"MessageId\": 445,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The WildView HD Trail Camera is designed to capture wildlife in its natural habitat. It is motion-activated, so ensure that it is placed in an area where wildlife activity is expected. Once set up correctly, the camera will start capturing wildlife in stunning HD quality. If you have any further questions, feel free to ask!\"\n      },\n      {\n        \"MessageId\": 446,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Oh, thank you for explaining that! I didn\\u0027t realize the camera was motion-activated, so I\\u0027ll move it to a different spot where I\\u0027ve seen some wildlife activity. I\\u0027ll let you know if it starts working. Thanks again for your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 246,\n    \"ProductId\": 92,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 146,\n    \"ShortSummary\": \"Assistance needed with initial filtration process\",\n    \"LongSummary\": \"Customer seeking assistance with initial filtration process. Followed maintenance instructions, but still experiencing issues. Requests further guidance on filter cartridge.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 447,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the AquaPure Portable Water Filter and I\\u0027m having trouble with the initial filtration process. I\\u0027m not sure if I\\u0027m doing it correctly and I\\u0027m worried that I might have damaged the filter cartridge. I followed the steps in the manual, but I\\u0027m still not sure. Can you please provide some guidance on how to properly perform the initial filtration? I want to make sure I\\u0027m using this product to its full potential. Thank you.\"\n      },\n      {\n        \"MessageId\": 448,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Thank you for reaching out. To ensure the proper initial filtration, gently handle the filter cartridge to avoid damaging the delicate filter media. After filtration, carefully clean and maintain the AquaPure Portable Water Filter as described in the manual section on maintenance. If you encounter any issues, please contact PureFlow customer support for personalized assistance and to inquire about warranty service options. We are here to support you.\"\n      },\n      {\n        \"MessageId\": 449,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the guidance. I carefully handled the filter cartridge and followed the maintenance instructions in the manual. However, I\\u0027m still experiencing some issues with the initial filtration process. I think I might have damaged the filter cartridge. Can you please provide further assistance?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 247,\n    \"ProductId\": 175,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 147,\n    \"ShortSummary\": \"Trouble with Depth \\u0026 Sensitivity Settings\",\n    \"LongSummary\": \"Customer Rachel Johnson is having trouble adjusting depth range and sensitivity on the SonarPro Portable Fish Finder. Threatened to request a refund if immediate assistance is not provided. Next support agent should address specific steps for adjusting settings.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 450,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I just purchased the SonarPro Portable Fish Finder and I can\\u0027t understand how to adjust the settings for the depth range and sensitivity. This is unacceptable! I demand immediate assistance in figuring this out. I spent good money on this product and I expect it to work as advertised. If I don\\u0027t receive help soon, I will be requesting a refund for this fish finder. I expect better customer support for a product of this caliber.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 248,\n    \"ProductId\": 14,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 148,\n    \"ShortSummary\": \"Safety tips and reassurances for Propane Camp Stove\",\n    \"LongSummary\": \"Customer seeking tips and reassurances for using Propane Camp Stove. Customer feels confident now. Next support agent should offer additional safety tips and remind about warranty coverage.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 451,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! Just wanted to double-check that my Propane Camp Stove is performing as expected. I took it out for a test run and it seemed to be working great, but I wanted to make sure I\\u0027m using it safely. Any tips or reassurances? Also, I\\u0027m super excited to take this bad boy camping next weekend! Thanks a bunch!\"\n      },\n      {\n        \"MessageId\": 452,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We\\u0027re delighted to hear that your Propane Camp Stove is performing well! When using the stove, remember to keep children and pets away and avoid attempting any modifications or repairs yourself. Safety always comes first. Additionally, the stove is covered by a 1-year warranty for defects in materials or workmanship. If you experience any issues, you can contact our friendly customer support team for assistance. Happy camping!\"\n      },\n      {\n        \"MessageId\": 453,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! Thanks so much for the tips and reassurances! I\\u0027ll definitely keep safety in mind and make sure to follow the guidelines. I feel much more confident now using my Propane Camp Stove. Can\\u0027t wait to go camping and cook up some delicious meals! Thanks again!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 249,\n    \"ProductId\": 137,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 149,\n    \"ShortSummary\": \"Installation and Setup Inquiry\",\n    \"LongSummary\": \"Customer needs detailed information on industrial specifications for installation. Still unsure about setup for outdoor gigs. Requires step-by-step guidance.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 454,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the WildBeat Pro DJ Controller and I\\u0027m having some trouble getting it to work. I\\u0027ve followed the cleaning procedure as outlined in the manual, but it still doesn\\u0027t seem to be functioning properly. I\\u0027m really embarrassed to admit this, but I\\u0027m not sure if I\\u0027ve accidentally done something to cause the issue. Could you please provide me with some guidance on how to troubleshoot and resolve the problem? I\\u0027m hoping to use this controller for my upcoming outdoor DJ gigs, so any help would be greatly appreciated. Thank you.\"\n      },\n      {\n        \"MessageId\": 455,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hi there, thank you for reaching out to us. It seems that the WildBeat Pro DJ Controller is a sophisticated piece of equipment designed for optimal performance in outdoor DJing scenarios. In order to troubleshoot and identify any potential issues, it is imperative to have access to specialized diagnostic equipment. As per the manual, the controller is rugged and waterproof, but specific industrial specifications for installation are crucial. If you require further assistance, please refer to the contact support details in the manual. We hope this information helps!\"\n      },\n      {\n        \"MessageId\": 456,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I appreciate the information, but I\\u0027m still unsure about the specific industrial specifications for installation. Could you please provide more details on what I need to do to ensure that the WildBeat Pro DJ Controller is set up correctly for my outdoor gigs? I want to make sure I\\u0027m not causing any issues myself. Thank you.\"\n      },\n      {\n        \"MessageId\": 457,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, in order to mount the WildBeat Pro DJ Controller in an outdoor environment, it is crucial to follow the specific industrial specifications to ensure proper installation. Additionally, before connecting the controller to audio equipment and power sources, it is imperative to conduct a comprehensive analysis of the electrical and audio systems using specialized scientific equipment.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 250,\n    \"ProductId\": 10,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 151,\n    \"ShortSummary\": \"Warranty coverage for accidental damage inquiry\",\n    \"LongSummary\": \"Customer inquired about TechBeam 2000 warranty coverage for accidental damage, and was informed that it is not covered. No further assistance needed at this time.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 462,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi, I just got the TechBeam 2000 and have a question about the warranty. Can you tell me if the warranty covers accidental damage? Thanks.\"\n      },\n      {\n        \"MessageId\": 463,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The TechBeam 2000 is covered by a limited warranty against defects in materials and workmanship for a period of one year from the date of purchase. However, it does not cover accidental damage. If you have any issues with the product, please let us know how we can assist you further.\"\n      },\n      {\n        \"MessageId\": 464,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Okay, thanks for letting me know about the warranty. I\\u0027ll keep that in mind. If I have any other questions, I\\u0027ll be sure to reach out. Have a great day!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 251,\n    \"ProductId\": 27,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 152,\n    \"ShortSummary\": \"Trouble accessing settings menu on AdventurePro DSLR Camera\",\n    \"LongSummary\": \"Customer needs guidance on accessing the settings menu of the AdventurePro DSLR Camera. Assistant provided detailed instructions and asked if the ticket should be closed.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 465,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the AdventurePro DSLR Camera and I\\u0027m having trouble understanding how to access the settings menu. I\\u0027ve tried pressing the \\u0027Menu\\u0027 button but can\\u0027t seem to get it to work. Could you please provide some guidance on how to navigate through the settings? Thank you.\"\n      },\n      {\n        \"MessageId\": 466,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"To access the settings menu, press the \\u0022Menu\\u0022 button located on the back of the camera body. You will then see a list of options on the LCD screen, including \\u0022Image Quality\\u0022, \\u0022White Balance\\u0022, \\u0022ISO\\u0022, \\u0022Exposure Compensation\\u0022, and more. Navigate through the menu using the directional buttons, then press the \\u0022OK\\u0022 button to select and adjust each setting. Refer to the user manual for detailed instructions on each setting. Use the control dial to adjust the aperture and shutter speed, and the ISO button to select the desired ISO setting. Remember, in manual mode, you are in control of every aspect of the exposure, so feel free to experiment and unleash your creativity! If you have any other questions, feel free to ask. Should we close the ticket?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 252,\n    \"ProductId\": 5,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 153,\n    \"ShortSummary\": \"Color Discrepancy Demands Replacement\",\n    \"LongSummary\": \"Customer demands immediate replacement for hammock due to color discrepancy. Customer refused to provide more details or initiate return/exchange.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 467,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I purchased the Swingnap Double Hammock with Mosquito Net and I am extremely disappointed with the color of the fabric. It does not match the description at all! I demand a replacement in the correct color immediately. This is unacceptable and I expect you to resolve this issue promptly. I shouldn\\u0027t have to deal with this after spending my hard-earned money on a product that is not as described. I expect to hear back from you within 24 hours with a solution to this problem.\"\n      },\n      {\n        \"MessageId\": 468,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We apologize for the inconvenience you have experienced with the color of the fabric. According to the manual, the Swingnap Double Hammock with Mosquito Net is designed to provide a comfortable and bug-free outdoor experience. We are committed to resolving this issue for you. To better assist you, could you please provide more details about the color discrepancy? Alternatively, if you would like to initiate a return or exchange, please let us know and we will guide you through the process.\"\n      },\n      {\n        \"MessageId\": 469,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I demand to speak to a manager immediately! I have already provided all the necessary information about the color discrepancy and I expect this issue to be resolved without any further delay. This is completely unacceptable and I will not accept anything less than a replacement in the correct color.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 253,\n    \"ProductId\": 40,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 154,\n    \"ShortSummary\": \"Charging tips for Rechargeable LED Headlamp\",\n    \"LongSummary\": \"Customer Alexandra is seeking tips on how to properly charge her Rechargeable LED Headlamp to maximize its battery life for her upcoming camping trip. Response needed: Provide detailed charging instructions.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 470,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there GloTech team! I recently got my hands on your awesome Rechargeable LED Headlamp for my upcoming camping trip, and I just can\\u0027t wait to light up the night with it! But I\\u0027m a bit confused about how to properly charge the headlamp to make sure it lasts as long as possible. Could you give me some tips on the best way to keep it fully charged and ready for my adventure? Thanks a bunch, you guys are the best!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 254,\n    \"ProductId\": 35,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 155,\n    \"ShortSummary\": \"Inquiry about deep-frying in Alpine Camp Cookware Set\",\n    \"LongSummary\": \"Customer purchased CookMaster Alpine Camp Cookware Set and inquired about using it for deep-frying chicken wings and french fries. Pending response needed regarding the suitability of the cookware for deep-frying.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 471,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, I just bought the CookMaster Alpine Camp Cookware Set and I was wondering if I can use it for making deep-fried foods like chicken wings and french fries? I think it should work fine, right?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 255,\n    \"ProductId\": 58,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 126,\n    \"ShortSummary\": \"Customer queries about SOS button and charging\",\n    \"LongSummary\": \"Customer has questions about using SOS button and charging device. Pending response about charging before use. Next support agent should clarify how SOS button works and whether device needs to be charged before first use.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 472,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I just bought the SafeTrail GPS Locator and I\\u0027m trying to figure out how to use the SOS button. I thought you just press it once for help, but now I\\u0027m not sure. Can you please clarify how it works? Also, I\\u0027m not sure if I need to charge the device before I use it for the first time. Can you let me know? Thanks so much for your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 256,\n    \"ProductId\": 171,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 156,\n    \"ShortSummary\": \"Technical maintenance and care questions for Stealth Recon Backpack\",\n    \"LongSummary\": \"Customer asks for technical info on waterproofing, hydration bladder maintenance, and signs of wear. Needs detailed guidance on care and maintenance.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 473,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Tactic Tech Stealth Recon Backpack and I have some technical questions regarding its maintenance and durability. I want to ensure that the backpack is performing as expected and that I am taking proper care of it. Specifically, I would like to know more about the waterproofing properties and the recommended waterproofing treatment for the fabric. Additionally, I am curious about the maintenance of the hydration bladder and the signs of wear or damage to look out for on the zippers, buckles, and straps. I want to make sure that I am following all the necessary steps to maintain the functionality and safety of the backpack. Your assistance in providing detailed technical information would be greatly appreciated. Thank you.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 257,\n    \"ProductId\": 47,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 157,\n    \"ShortSummary\": \"Excited for Camping Taste Test Challenge\",\n    \"LongSummary\": \"Customer is excited to try out the various flavors of Nutritech Protein Plus Energy Bars for her camping trip and plans a taste test challenge with friends. No pending questions or issues.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Idea\",\n    \"Messages\": [\n      {\n        \"MessageId\": 474,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there, team Nutritech! I am so pumped about using your Protein Plus Energy Bars for my upcoming camping trip. I just know they\\u0027re going to give me the energy I need to tackle those hiking trails and enjoy some midnight stargazing. I mean, who needs s\\u0027mores when you have these amazing bars, am I right? Can\\u0027t wait to unwrap each one and savor the delicious flavors. I\\u0027m thinking of doing a taste test challenge with my friends to see which flavor we love the most. Thanks for creating such awesome fuel for our adventures!\"\n      },\n      {\n        \"MessageId\": 475,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hey there! The Nutritech Protein Plus Energy Bars are designed to provide you with a nutritious snack packed with 20g of high-quality protein to fuel your outdoor activities. Each flavor offers a unique and delightful taste experience, so it\\u0027s perfect for your taste test challenge with friends. Enjoy your camping trip and the midnight stargazing!\"\n      },\n      {\n        \"MessageId\": 476,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! Thanks for the info, I can\\u0027t wait to try out all the flavors. I\\u0027ll make sure to pack a variety for my camping trip. You guys really know how to make snacking fun and nutritious! Can\\u0027t wait to fuel up with Nutritech Protein Plus Energy Bars. You\\u0027re the best!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 258,\n    \"ProductId\": 194,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 158,\n    \"ShortSummary\": \"Multi-Tool Usage Tips\",\n    \"LongSummary\": \"Customer wants tips for using the multi-tool effectively and safely.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 477,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the SurvivalPro 3000 Kit from Rescuepro and I just want to make sure I\\u0027m using it correctly. I\\u0027m a bit embarrassed to ask, but I want to be sure that I\\u0027m familiar with all the features and that everything is in working order. Can you provide any tips for using the multi-tool effectively? I want to make sure I can handle it safely and use it as intended in any emergency situation. Thanks in advance for your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 259,\n    \"ProductId\": 4,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 159,\n    \"ShortSummary\": \"Quality and Packaging Issues\",\n    \"LongSummary\": \"Emergency Survival Kit quality and packaging issues, urgent resolution needed.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 478,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am extremely frustrated with the quality of the Emergency Survival Kit from Life Guard X that we received for our store. The food rations included in the kit are not up to standard and some of the packaging was damaged upon arrival. Our customers are relying on us to provide reliable emergency supplies and this is unacceptable. We need immediate assistance in resolving this issue as our reputation is on the line.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 260,\n    \"ProductId\": 137,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 161,\n    \"ShortSummary\": \"WildBeat Pro DJ Controller Broken\",\n    \"LongSummary\": \"Customer\\u0027s WildBeat Pro DJ Controller is broken and needs fixing/replacement. Customer is asking for help with the issue. Next support agent should provide troubleshooting steps or replacement options.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 483,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, my WildBeat Pro DJ Controller just broke. Can you help me fix it or get a replacement?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 261,\n    \"ProductId\": 197,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 162,\n    \"ShortSummary\": \"Inquiry about Firemaster Stove for Outdoor Cooking\",\n    \"LongSummary\": \"Customer Hannah Smith inquires about Firemaster Portable Camping Stove\\u0027s suitability for cooking in various outdoor conditions. Assistant provided safety precautions and usage guidelines. Pending response on specific weather and terrain suitability.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 484,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear OutdoorOven Support Team, I am interested in purchasing the Firemaster Portable Camping Stove for my upcoming camping trip. Can you please provide information on its suitability for cooking in various outdoor conditions? I want to ensure that it can handle different weather conditions and terrains. Thank you for your assistance.\"\n      },\n      {\n        \"MessageId\": 485,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Firemaster Portable Camping Stove is designed for use in well-ventilated outdoor areas and should be kept away from flammable materials such as tents, leaves, and overhanging branches. It\\u0027s important to never leave the stove unattended while in use, and to wait for it to cool down completely before handling or storing. This information is from the Firemaster Portable Camping Stove user manual.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 262,\n    \"ProductId\": 72,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 163,\n    \"ShortSummary\": \"Troubleshooting Angler\\u0027s Choice Pro Fish Finder 500\",\n    \"LongSummary\": \"Customer having trouble with Angler\\u0027s Choice Pro Fish Finder 500. Asked for help troubleshooting. Needs specific guidance to resolve issue.\",\n    \"CustomerSatisfaction\": 3,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 486,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the Angler\\u0027s Choice Pro Fish Finder 500 and I\\u0027m having some trouble getting it to work. I\\u0027m really relying on this device to help me catch more fish, but it doesn\\u0027t seem to be functioning at all. I\\u0027ve tried following the instructions for cleaning and storage, but it\\u0027s not making any difference. Can you please help me figure out what\\u0027s going wrong? I\\u0027m really hoping to get this sorted out so I can make the most of the sonar technology and improve my fishing experience. Any guidance or assistance would be greatly appreciated. Thanks!\"\n      },\n      {\n        \"MessageId\": 487,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, if the Angler\\u0027s Choice Pro Fish Finder 500 is not operating as expected, I should refer to the troubleshooting section of the user manual for guidance. I recommend that you refer to the troubleshooting section in the manual for assistance. If the issue persists, please feel free to reach out to our customer support team for further assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 263,\n    \"ProductId\": 145,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 164,\n    \"ShortSummary\": \"Inquiry about laptop charging capabilities\",\n    \"LongSummary\": \"Customer inquires about PowerBeam Solar Charger\\u0027s laptop charging capabilities. Pending question: suitability for all devices. Need response on charger\\u0027s laptop compatibility.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 488,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear Support Team, I recently purchased the PowerBeam Solar Powered Portable Charger and I have a specific technical question about its capabilities. Can you please provide information on whether this charger is capable of charging a laptop? I want to ensure that it is suitable for all my devices before making a decision. Thank you for your assistance. Sincerely, Nathan Reynolds\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 264,\n    \"ProductId\": 180,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 165,\n    \"ShortSummary\": \"Smooth Casting Issue\",\n    \"LongSummary\": \"Customer purchased ExtremeCast 5000, unable to cast smoothly despite setup steps. Customer frustrated, seeks specific solution.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 489,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I purchased the ExtremeCast 5000 and followed the setup steps, but I\\u0027m still unable to cast smoothly. This is really frustrating and I expect a solution. And don\\u0027t tell me to check the manual, I shouldn\\u0027t have to do that for a product that claims to have \\u0027smooth casting and retrieval\\u0027 as one of its features.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 265,\n    \"ProductId\": 123,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 166,\n    \"ShortSummary\": \"Customer concerned about high humidity impact on SolarCopy 3000 performance\",\n    \"LongSummary\": \"Customer has concerns about high humidity affecting SolarCopy 3000 performance. Assistant recommends power diagnostic test and monitoring ambient conditions. Customer conducted tests and believes enquiry is resolved. Next response should confirm resolution and offer any additional support if needed.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 490,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I\\u0027m considering purchasing the SolarCopy 3000 for my outdoor administration needs, but I\\u0027m not sure if it\\u0027s suitable for use in a particularly humid environment. Would the high humidity affect the performance of the solar panels or internal components? I want to make sure I\\u0027m making the right choice before making the purchase. Any advice would be greatly appreciated. Thank you!\"\n      },\n      {\n        \"MessageId\": 491,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The SolarCopy 3000 is designed and tested for reliability in outdoor administrative tasks. According to the manual, it is the result of extensive research and development, as well as adherence to industry standards, ensuring its reliability and performance in outdoor administrative tasks.\"\n      },\n      {\n        \"MessageId\": 492,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I appreciate your response and assurance about the reliability of the SolarCopy 3000. However, I\\u0027m still concerned about the specific impact of high humidity on the performance of the solar panels and internal components. Could you provide more detailed information or point me to a resource where I can find this information? Thank you for your help!\"\n      },\n      {\n        \"MessageId\": 493,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The SolarCopy 3000 is equipped with advanced power control and monitoring features to ensure optimal performance, and it is designed for reliability in outdoor administrative tasks. Before using the SolarCopy 3000, it is essential to perform a comprehensive power diagnostic test using a specialized industrial power analyzer. For more detailed information, please refer to the user manual provided with the product.\"\n      },\n      {\n        \"MessageId\": 494,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information. I will be sure to perform the power diagnostic test as recommended and refer to the user manual for more detailed information. I appreciate your assistance in addressing my concerns.\"\n      },\n      {\n        \"MessageId\": 495,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, it is recommended to use scientific equipment to monitor the ambient temperature, humidity, and sunlight levels at the intended installation site. Ensure that these conditions fall within the recommended range as per the Nature\\u0027s Photocopier SolarCopy 3000 industry standard IS3000.\"\n      },\n      {\n        \"MessageId\": 496,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information and advice. I have conducted the power diagnostic test and monitored the ambient temperature, humidity, and sunlight levels at the intended installation site as recommended. Everything seems to fall within the recommended range as per the Nature\\u0027s Photocopier SolarCopy 3000 industry standard IS3000. I appreciate your assistance in addressing my concerns. I believe my enquiry is now resolved. Thank you!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 266,\n    \"ProductId\": 187,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 167,\n    \"ShortSummary\": \"DroneX 5000 not taking off\",\n    \"LongSummary\": \"DroneX 5000 not taking off properly. Customer seeking troubleshooting help.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 497,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"DroneX 5000 not taking off properly. What\\u0027s wrong? Need help.\"\n      },\n      {\n        \"MessageId\": 498,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I see that the DroneX 5000 user manual provides detailed information on assembling the drone and safety precautions. It\\u0027s recommended to refer to the troubleshooting guide for power and connectivity issues. If the issue persists, please contact SkySight customer support for further assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 267,\n    \"ProductId\": 28,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 121,\n    \"ShortSummary\": \"Troubleshooting PureStream Water Purifier\",\n    \"LongSummary\": \"Customer needs assistance with the PureStream Water Purifier. Assistant suggested reviewing user manual Chapter 3. Pending question if customer needs further assistance.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 499,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi, I need help with my PureStream Water Purifier. It\\u0027s not working properly. Can you assist me?\"\n      },\n      {\n        \"MessageId\": 500,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hi, it seems that the PureStream Water Purifier has specific operating instructions provided in the user manual. Have you had a chance to review Chapter 3 of the user manual? It contains detailed information on how to operate the purifier and troubleshoot any issues. If you need further assistance, please feel free to ask!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 268,\n    \"ProductId\": 78,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 168,\n    \"ShortSummary\": \"Performance and Connectivity Issues with AquaTech X-5000\",\n    \"LongSummary\": \"Customer Evan Reynolds is experiencing performance and connectivity issues with AquaTech X-5000. He wants to troubleshoot problems and find a solution to enjoy watersports without issues.\",\n    \"CustomerSatisfaction\": 3,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 501,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, my name is Evan and I recently purchased the AquaTech X-5000 from WaterRover. I rely on extremely high-tech gear for my watersports, so I was really excited about this product. However, I\\u0027ve been experiencing some issues with its performance and connectivity. The materials and design were supposed to provide maximum performance and durability, but I\\u0027m not getting that. Can you help me troubleshoot and fix these issues? I\\u0027m hoping to get back to enjoying my watersports without any problems. Thanks for your help!\"\n      },\n      {\n        \"MessageId\": 502,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hi Evan, thank you for reaching out to us. I understand the importance of high-performance gear for your watersports activities. The AquaTech X-5000 is designed with innovative features to enhance user experience and optimize performance on the water. It\\u0027s capable of reaching speeds of up to 30 knots and features precision-engineered hull design and responsive steering for exceptional maneuverability and agility. This gear is engineered to deliver an unparalleled watersports experience. Let\\u0027s troubleshoot the issues you are experiencing with its performance and connectivity to ensure that you can get back to enjoying your watersports without any problems. Could you provide more details about the specific issues you are facing?\"\n      },\n      {\n        \"MessageId\": 503,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, thanks for your response. I\\u0027m glad to hear about all the amazing features of the AquaTech X-5000. However, despite its capabilities, I\\u0027m still experiencing issues with its performance and connectivity. The gear is not delivering the maximum performance and durability as advertised, and I\\u0027m unable to enjoy my watersports without any problems. Can we continue troubleshooting to find a solution? I really want to make the most out of this product. Thanks for your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 269,\n    \"ProductId\": 43,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 169,\n    \"ShortSummary\": \"Troubleshooting NightOps Tactical Flashlight\",\n    \"LongSummary\": \"Customer Samantha Chen is experiencing difficulty turning on NightOps Tactical Flashlight from Strategicgear. She has checked the batteries and requested expert advice to troubleshoot. Pending: response from support agent with troubleshooting steps.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 504,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! I recently got my hands on the NightOps Tactical Flashlight from Strategicgear and I\\u0027m super pumped about it! But, I\\u0027m having a bit of trouble getting it to turn on. I\\u0027ve checked the batteries and made sure they\\u0027re all properly installed, but still no luck. Any chance you could help me figure out what might be going on? I really want to take this bad boy out for a spin and show off its multiple brightness levels and strobe mode to my friends. Looking forward to your expert advice! Thanks a bunch!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 270,\n    \"ProductId\": 70,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 170,\n    \"ShortSummary\": \"Charging issue with Solar Power Bank\",\n    \"LongSummary\": \"Solar power bank not charging properly. Customer seeking troubleshooting help.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 507,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Need help with solar power bank. Not charging properly. What to do?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 271,\n    \"ProductId\": 157,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 171,\n    \"ShortSummary\": \"Shutter button not working as described\",\n    \"LongSummary\": \"Customer reports issue with Shutter button not working as described. Threatens refund or replacement. Needs reassurance or resolution.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 508,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I bought the 360X Action Camera from Extremeview and I\\u0027m not convinced it\\u0027s working as described. The manual says I should be able to start and stop recording by pressing the Shutter button, but it\\u0027s not working for me. I\\u0027ve tried following the instructions multiple times, and the LED indicator light isn\\u0027t flashing when I press the button. I need reassurance that this camera is behaving as expected, or else I\\u0027ll consider asking for a refund or replacement.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 272,\n    \"ProductId\": 113,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 26,\n    \"ShortSummary\": \"Inquiry about Summit Pro 40L Backpack Features\",\n    \"LongSummary\": \"Customer inquires about hydration system, hip belt, comfort, and durability of the Summit Pro 40L Technical Backpack. Assistant provides details and directs to support resources. No pending questions.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 509,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I am interested in purchasing the Summit Pro 40L Technical Backpack from Backhike for my upcoming outdoor adventures. Can you provide more information on how the built-in hydration system works and if it is suitable for long hikes? I\\u0027m also curious about the padded hip belt and how it helps with weight distribution. Any details on its comfort and durability would be greatly appreciated. Thank you.\"\n      },\n      {\n        \"MessageId\": 510,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Summit Pro 40L Technical Backpack is designed for easy loading and unloading of your gear. You can start your adventures by following the simple steps in the manual. If your backpack appears to be damaged, please contact our customer service team immediately for assistance. Additionally, for immediate assistance, you can call the Backhike customer support hotline at 1-800-BACKHIKE. They are available from Monday to Friday, 9 am to 5 pm. If you need further information, you can visit their online support portal at www.backhike.com/support.\"\n      },\n      {\n        \"MessageId\": 511,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information provided. I will review the manual and instructions for the Summit Pro 40L Technical Backpack. If I encounter any issues or have further questions, I will reach out to the customer service team or visit the online support portal. I appreciate your assistance.\"\n      },\n      {\n        \"MessageId\": 512,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Summit Pro 40L Technical Backpack features a built-in hydration system, designed to keep you hydrated on the go. To assemble the hydration system, follow the steps provided in the user manual. The padded hip belt is designed to provide additional support and comfort during outdoor excursions. You can adjust it for a personalized fit using the steps outlined in the manual. If you have any further questions or need assistance, feel free to reach out to our customer service team.\"\n      },\n      {\n        \"MessageId\": 513,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information on the hydration system and padded hip belt. I will follow the steps in the manual to assemble the hydration system and adjust the hip belt for my upcoming hike. If I encounter any issues, I will reach out to the customer service team. Thank you for your assistance.\"\n      },\n      {\n        \"MessageId\": 514,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The built-in hydration system of the Summit Pro 40L Technical Backpack is designed to keep you hydrated on the go. To assemble the hydration system, follow the simple steps provided in the user manual. The padded hip belt is designed to provide additional support and comfort during outdoor excursions. You can adjust it for a personalized fit using the steps outlined in the manual. If you have any further questions or need assistance with the assembly or adjustment, feel free to reach out to our customer service team.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 273,\n    \"ProductId\": 40,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 172,\n    \"ShortSummary\": \"Charging instructions request for GloTech Rechargeable LED Headlamp\",\n    \"LongSummary\": \"Retail store requests detailed charging info for GloTech Rechargeable LED Headlamp. Assistant provided USB charging instructions. Customer acknowledged and will follow up if needed.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 515,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear GloTech Customer Support, I am reaching out on behalf of our retail store regarding the Rechargeable LED Headlamp. We have received inquiries from customers about the charging instructions for this product. Could you please provide us with detailed information on how to charge the headlamp and how long it takes to fully charge? We want to ensure that we can assist our customers with accurate and helpful information. Thank you for your prompt attention to this matter. Sincerely, Alexandra Smith\"\n      },\n      {\n        \"MessageId\": 516,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, to charge the GloTech Rechargeable LED Headlamp, use the provided USB charging cable and connect it to the charging port located on the side of the headlamp. Make sure to charge the headlamp fully before using it for the first time.\"\n      },\n      {\n        \"MessageId\": 517,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for providing the information on how to charge the Rechargeable LED Headlamp. We will follow the instructions and ensure that our customers are properly informed. If there are any further updates or additional details, we will reach out again. Thank you for your assistance. Sincerely, Alexandra Smith\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 274,\n    \"ProductId\": 171,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 162,\n    \"ShortSummary\": \"Inquiry about backpack suitability for heavy items\",\n    \"LongSummary\": \"Customer inquires about suitability of the Stealth Recon Backpack for heavy items and asks for loading and securing tips for a hiking trip. Pending response to customer\\u0027s queries.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 518,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there! I\\u0027m considering getting the Tactic Tech Stealth Recon Backpack for my upcoming hiking trip. I was wondering if this backpack is suitable for carrying heavy items like camping gear and food? I want to make sure it can handle the weight without getting damaged. Also, do you have any tips on how to properly load and secure the backpack for a long outdoor mission? Thanks so much for your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 275,\n    \"ProductId\": 160,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 173,\n    \"ShortSummary\": \"GPS modification for celestial navigation\",\n    \"LongSummary\": \"Customer seeks assistance in modifying GPS device for celestial navigation purposes. Requires technical specifications and relevant information to optimize the device. Open to refund or replacement if modification is not feasible.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 519,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Geotrack Trailblazer GPS Navigation Device and I am looking to use it for a unique purpose. I have extensive knowledge of technical navigation systems and I believe that this device is capable of performing advanced calculations for celestial navigation. I understand that the device is equipped with a high-precision compass and barometer, and I am confident that with the right software modifications, it can provide accurate celestial navigation data, including altitude and azimuth calculations. I have not found any reference to this specific use in the product description or manual, but I am certain that with the right assistance, this device can be optimized for this purpose. Can you provide me with the technical specifications and any relevant information that would assist me in this endeavor? I am open to the possibility of a refund or replacement if this modification is not feasible, but I am hopeful that your team can support me in achieving this goal. Thank you for your attention to this matter.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 276,\n    \"ProductId\": 126,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 8,\n    \"ShortSummary\": \"GPS tracking feature activation for hiking trip\",\n    \"LongSummary\": \"Customer needs help enabling GPS tracking feature on SOS Emergency Beacon for hiking trip next week. Assistance given on how to activate. Pending response for confirmation.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 520,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the SOS Emergency Beacon from SOS Gear and I\\u0027m having trouble understanding how to enable the GPS tracking feature. I tried following the steps in the manual, but I\\u0027m not sure if I\\u0027m doing it correctly. I really want to make sure I can use this feature when I go hiking next week. Can someone please walk me through the process in simple steps? I want to be prepared in case of an emergency. Thank you so much for your help!\"\n      },\n      {\n        \"MessageId\": 521,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"To enable the GPS tracking feature on your SOS Emergency Beacon, simply press and hold the GPS button for 3 seconds until the LED indicator starts flashing green. Once activated, your beacon will continuously transmit your location to emergency responders. This will help them find you as quickly as possible. Have a safe hiking trip!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 277,\n    \"ProductId\": 8,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 174,\n    \"ShortSummary\": \"Unsatisfactory map feature demands refund or replacement\",\n    \"LongSummary\": \"Customer demands refund or product replacement due to unsatisfactory map feature. Assistant referred to limited warranty for contacting customer support. Questions remain unresolved.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 522,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I can\\u0027t believe the map feature on the Outdoor Admin 5000! It\\u0027s so basic and doesn\\u0027t even offer live updates. I wanted to use it for my extreme hiking trips, but now I think it\\u0027s useless. I expect a refund for this misleading product!\"\n      },\n      {\n        \"MessageId\": 523,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Outdoor Admin 5000 is intended for use as an organizational tool for outdoor activities. It is designed for streamlined organization and navigation. If you have any further questions or require support, you can contact TrailFax customer support via phone at 1-800-OUTDOOR-1, email at support@trailfax.com, or visit their website for live chat support.\"\n      },\n      {\n        \"MessageId\": 524,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I don\\u0027t care what the Outdoor Admin 5000 is \\u0027intended\\u0027 for. The map feature is a key selling point and it is severely lacking. I demand a refund or a product replacement that actually meets my needs! And don\\u0027t give me the runaround with more contact options, I want a real solution now.\"\n      },\n      {\n        \"MessageId\": 525,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the TrailFax Outdoor Admin 5000 offers a limited warranty that covers defects in materials and workmanship for a period of 2 years from the date of purchase. This includes the device itself as well as any included accessories. For a refund or product replacement, it is recommended to contact TrailFax customer support via phone at 1-800-OUTDOOR-1, email at support@trailfax.com, or visit their website for live chat support.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 278,\n    \"ProductId\": 150,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 175,\n    \"ShortSummary\": \"Disappointed with Outdoor Shield Pro performance\",\n    \"LongSummary\": \"Customer disappointed with Outdoor Shield Pro performance, seeking advice or replacement. Assistant asked about storage and offered support contact info.\",\n    \"CustomerSatisfaction\": 3,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 526,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Outdoor Shield Pro from Buzzoff and I\\u0027m a bit disappointed with its performance. Despite following the instructions, I still seem to be getting bitten by bugs. I was really counting on this repellent for my camping trip next weekend, so I\\u0027m not sure what to do now. Can you provide any advice or assistance on how to make the product more effective, or possibly a refund or replacement? Thank you for your help.\"\n      },\n      {\n        \"MessageId\": 527,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hello, thank you for reaching out to us. We are sorry to hear about your experience with the Outdoor Shield Pro. Have you been storing the Outdoor Shield Pro in a cool, dry place away from direct sunlight as recommended in the user manual? Also, if you need immediate assistance, you can contact Buzzoff\\u0027s support team by phone at [phone number] or by email at support@buzzoff.com. Please let us know if you have any further questions or if you\\u0027d like to explore return or replacement options.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 279,\n    \"ProductId\": 158,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 176,\n    \"ShortSummary\": \"Unconventional Use for HydraHike Hydration Pack\",\n    \"LongSummary\": \"Customer excitedly shares plans to use HydraHike Hydration Pack for unconventional purposes, while also noting intention to follow manual\\u0027s tips on maintenance and storage. No specific question or request for info given. Response should acknowledge customer\\u0027s creativity and reassure about pack\\u0027s versatility.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Idea\",\n    \"Messages\": [\n      {\n        \"MessageId\": 528,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! So, I just got my hands on the HydraHike Hydration Pack and let me tell you, I\\u0027m already planning to use it for the most unexpected things! Like, I\\u0027m thinking of using it to carry snacks for my pet iguana on our next hiking trip. I mean, it\\u0027s got all these compartments and pockets, so why not, right? But don\\u0027t worry, I won\\u0027t forget to follow the manual\\u0027s tips on keeping the water bladder clean and properly storing the pack. I\\u0027m sure it\\u0027ll work out just fine! Just wanted to share my wild idea with you and see what you think. Stay cool!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 280,\n    \"ProductId\": 190,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 178,\n    \"ShortSummary\": \"Broken UltraLight Poles 300 Repair/Replacement\",\n    \"LongSummary\": \"Customer Evelyn Harper reported a broken UltraLight Poles 300 and was advised to contact customer support for repair or replacement options. Next agent should assist with the repair or replacement process.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 534,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the UltraLight Poles 300 and unfortunately one of them has broken. I rely on these poles extremely for my hiking trips and I\\u0027m really upset that it\\u0027s no longer usable. I didn\\u0027t expect this to happen, as I thought they were built to last. Can you please advise me on how to get it repaired or replaced? I\\u0027m really looking forward to using them again for my upcoming trekking adventure.\"\n      },\n      {\n        \"MessageId\": 535,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hello, I\\u0027m sorry to hear that one of your UltraLight Poles 300 has broken. According to the product manual, if any delamination or structural defects are detected, you should discontinue use of the poles and contact our customer service for repair or replacement options. You can also perform a flexural strength test using specialized equipment to determine if the poles have maintained their structural integrity. If you need further assistance, please contact Trailtrek customer support for help with the repair or replacement process. We want to ensure that you have a reliable and safe set of poles for your upcoming trekking adventure.\"\n      },\n      {\n        \"MessageId\": 536,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information. I will contact Trailtrek customer support for help with the repair or replacement process as per your suggestion.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 281,\n    \"ProductId\": 145,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 179,\n    \"ShortSummary\": \"Inquiry about solar charger for camping trip\",\n    \"LongSummary\": \"Customer is considering purchasing the PowerBeam Solar Powered Portable Charger for a camping trip. Asked about cloudy weather charging and compatibility with older iPod. Status: Pending a response regarding iPod compatibility.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 537,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! I\\u0027m seriously thinking about getting the PowerBeam Solar Powered Portable Charger for my upcoming camping trip. I mean, how cool is it that I can charge my phone using the power of the sun? But I do have a question - will it still work if it\\u0027s a little cloudy outside? Also, can I use it to charge my older iPod? Thanks so much for your help, I really appreciate it!\"\n      },\n      {\n        \"MessageId\": 538,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The PowerBeam Solar Powered Portable Charger is designed to keep your devices charged using the power of the sun, making it a great choice for your upcoming camping trip. According to the manual, it\\u0027s important to place the solar panels in direct sunlight for optimal charging. However, be mindful of reducing sun exposure to prevent overheating. If it\\u0027s cloudy, try to find a spot with as much sunlight as possible. As for charging your older iPod, the manual does not specify compatibility with specific devices, so it should work with older iPods that use USB charging. If you have any further questions, feel free to ask!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 282,\n    \"ProductId\": 37,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 64,\n    \"ShortSummary\": \"Issue with Outdoor First Aid Kit functionality\",\n    \"LongSummary\": \"Customer purchased Outdoor First Aid Kit, some items not working as expected. Asked for info on kit functionality or replacement eligibility. Response provided on kit design and safety tips. Next support agent should address customer\\u0027s specific concerns and eligibility for replacement.\",\n    \"CustomerSatisfaction\": 3,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 539,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Wild Guard Outdoor First Aid Kit for an upcoming hiking trip. However, I\\u0027ve found that some of the items in the kit are not working as expected. I followed the general safety tips and made sure to keep the kit easily accessible, but I was disappointed when I needed to use it. Can you please provide me with information on how to ensure the kit functions properly or if I am eligible for a replacement? Thank you for your help.\"\n      },\n      {\n        \"MessageId\": 540,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Wild Guard Outdoor First Aid Kit is specifically designed to provide essential first aid supplies for outdoor excursions. It is intended to be easily packable and able to withstand the rigors of outdoor activities. For general safety, always keep the kit in a secure and easily accessible location when engaging in outdoor activities.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 283,\n    \"ProductId\": 165,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 180,\n    \"ShortSummary\": \"Weatherproofing Dissatisfaction with Rugged Shelter 600\",\n    \"LongSummary\": \"Customer is dissatisfied with the Rugged Shelter 600\\u0027s weatherproofing, despite following manual instructions and using the rainfly. They seek an explanation for why it didn\\u0027t work as promised. Kindly provide further clarification on the shelter\\u0027s limitations and proper usage in various weather conditions.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 541,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I don\\u0027t understand why this shelter is advertised as weatherproof when it couldn\\u0027t withstand a light drizzle! I followed the manual and used the rainfly, but it still got wet inside. This is not what I expected from an \\u0027all-weather\\u0027 shelter. I need an explanation for why it didn\\u0027t work as promised.\"\n      },\n      {\n        \"MessageId\": 542,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Rugged Shelter 600 is designed to withstand various weather conditions, and the rainfly provides an extra layer of protection against rain and wind. However, it\\u0027s recommended not to use the shelter in extreme weather such as heavy rain, strong winds, or snowstorms. Additionally, always check the weather forecast before setting up the shelter and be prepared to take it down if conditions worsen.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 284,\n    \"ProductId\": 5,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 181,\n    \"ShortSummary\": \"Inquiring about hammock safety in inclement weather\",\n    \"LongSummary\": \"Customer inquires about safety precautions for hammock in inclement weather. Assistant provides details about using the built-in mosquito net and setting up the hammock securely. Customer query answered, but may need more details on specific weather conditions.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 543,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I am considering purchasing the Swingnap Double Hammock with Mosquito Net and I wanted to inquire about the safety precautions during inclement weather mentioned in the product description. Can you provide more details on how the hammock with mosquito net should be used in strong winds, heavy rain, or lightning? Thank you.\"\n      },\n      {\n        \"MessageId\": 544,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Swingnap Double Hammock with Mosquito Net features a built-in mosquito net of the finest quality mesh. When entering the hammock, carefully unzip the entrance to the net and step inside. Once you are comfortably settled in the hammock, use the convenient zipper pulls to close the mosquito net securely. Additionally, the hammock should be securely suspended between trees and the net can be set up by attaching it to the integrated suspension points on the hammock and using the included straps.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 285,\n    \"ProductId\": 17,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 126,\n    \"ShortSummary\": \"TechShield Jacket Repair/Replacement Request\",\n    \"LongSummary\": \"Customer Lila Chen reported her RidgeRunner Weatherproof Jacket, made by TechShield, has broken while hiking in heavy rain. She is looking for information on how to get it repaired or replaced.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 545,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, my name is Lila and I recently purchased the RidgeRunner Weatherproof Jacket from TechShield. I rely on this jacket extremely to keep me dry and protected from the elements. However, I was out hiking in heavy rain and unfortunately, the jacket has broken. I didn\\u0027t expect this to happen, as the manual mentioned that the jacket is made with durable, waterproof material. I\\u0027m a bit naive when it comes to outdoor gear, but I really need help with this. Can you provide information on how to get it repaired or replaced? Thank you so much for your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 286,\n    \"ProductId\": 4,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 182,\n    \"ShortSummary\": \"Customer questions survival kit contents\",\n    \"LongSummary\": \"Customer questions usefulness of whistle, flashlight, and emergency shelter in survival situations. Requests info on starting fire and navigating rough terrain with kit items.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 546,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I don\\u0027t understand why this emergency survival kit includes a whistle and a flashlight. Are we supposed to be having a party in the wilderness? I need real tools and equipment for survival, not toys! And don\\u0027t even get me started on the so-called \\u0027emergency shelter\\u0027 - how is a lightweight tent going to protect me in a real emergency? This kit seems more like a joke than a serious survival solution. Can someone please explain to me how these items are actually useful in a survival situation? Because right now, I\\u0027m not convinced at all.\"\n      },\n      {\n        \"MessageId\": 547,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The whistle and flashlight included in the emergency survival kit are essential tools for signaling for help and providing illumination in low-light or dark conditions. The whistle is designed to produce a loud and clear sound to attract attention, while the flashlight is compact and durable, providing reliable light when needed. Additionally, the emergency shelter included in the kit is suitable for providing temporary shelter in various emergency situations such as natural disasters, outdoor adventures, or vehicle breakdowns. It is important to prioritize safety, find a suitable location for setting up the shelter, and use any available resources to enhance its effectiveness.\"\n      },\n      {\n        \"MessageId\": 548,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I still don\\u0027t see how a whistle and flashlight are going to help me survive in a real emergency. What if I need to start a fire or navigate through rough terrain? And the so-called \\u0027emergency shelter\\u0027 still seems flimsy to me. I need more convincing that these items are actually going to be useful in a survival situation.\"\n      },\n      {\n        \"MessageId\": 549,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the whistle is designed to produce a loud and clear sound to attract attention in emergency situations. The flashlight provides reliable light in low-light or dark conditions. The emergency shelter included in the kit is suitable for providing temporary shelter in various emergency situations.\"\n      },\n      {\n        \"MessageId\": 550,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I still don\\u0027t understand how these items are going to help me survive in a real emergency. I need more information on how to start a fire and navigate through rough terrain using the items in the kit. And I still don\\u0027t feel confident in the effectiveness of the \\u0027emergency shelter\\u0027.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 287,\n    \"ProductId\": 56,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 34,\n    \"ShortSummary\": \"Unsatisfactory Performance in Cold Weather\",\n    \"LongSummary\": \"Customer is unsatisfied with the Naptime 5000 Sleeping Bag\\u0027s performance in cold weather. Asked if insulation is faulty or if using it wrong. Wants a solution or a refund.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 551,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am so frustrated with this Naptime 5000 Sleeping Bag from Slumberpeak! I purchased it for camping in cold weather and it claims to keep you warm in temperatures as low as 20\\u00B0F. But I used it on a camping trip and I was freezing all night! I followed the instructions to zip it up completely and pull the hood tightly, but it didn\\u0027t help at all. I want to know if there\\u0027s something wrong with the insulation or if I\\u0027m doing something wrong. This is not what I expected from a high-quality sleeping bag. I need a solution or I want a refund!\"\n      },\n      {\n        \"MessageId\": 552,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry to hear about your experience with the Naptime 5000 Sleeping Bag. Based on the product manual, the synthetic insulation is designed to provide excellent warmth retention and is intended to keep you warm in temperatures as low as 20\\u00B0F. It\\u0027s also recommended to contact Slumberpeak\\u0027s customer service team for warranty claims or support inquiries at support@slumberpeak.com or call 1-800-123-4567. I hope this information helps!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 288,\n    \"ProductId\": 112,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 126,\n    \"ShortSummary\": \"Trailblazer Carbon Fiber Mountain Bike Helmet fit inquiry\",\n    \"LongSummary\": \"Customer inquiring about adjusting fit and proper helmet positioning for Trailblazer Carbon Fiber Mountain Bike Helmet. Received guidance and adjusted fit as per user manual. No pending questions.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 553,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello there! I\\u0027m considering purchasing the Trailblazer Carbon Fiber Mountain Bike Helmet from Cyclextreme for my upcoming mountain biking adventures. I have a question about adjusting the fit and proper helmet positioning. I want to make sure I\\u0027m doing it correctly to ensure maximum safety and comfort. Can you provide some guidance on this? Thank you so much for your help!\"\n      },\n      {\n        \"MessageId\": 554,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Trailblazer Carbon Fiber Mountain Bike Helmet is designed to be the ultimate companion for your mountain biking excursions. Crafted from high-quality carbon fiber, this helmet offers unparalleled durability while remaining surprisingly lightweight. To adjust the fit, follow the instructions provided in the user manual. Familiarize yourself with the various components of the helmet and their functions before wearing it for the first time to maximize its effectiveness.\"\n      },\n      {\n        \"MessageId\": 555,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information! I read through the user manual and adjusted the fit of the Trailblazer Carbon Fiber Mountain Bike Helmet as per the instructions. It feels comfortable and secure now. I really appreciate your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 289,\n    \"ProductId\": 168,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 183,\n    \"ShortSummary\": \"WildDJ Pro Mixer malfunction\",\n    \"LongSummary\": \"Customer\\u0027s WildDJ Pro Mixer suddenly stopped working. Desperate for immediate fix. Assistant suggested referring to manual for troubleshooting and contacting support if issue persists.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 556,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there, I\\u0027ve been using the WildDJ Pro Mixer and it suddenly stopped working. I\\u0027ve tried everything, and nothing seems to fix it. I don\\u0027t understand how a \\u0027rugged construction\\u0027 can just break like this. I need help getting this sorted out ASAP.\"\n      },\n      {\n        \"MessageId\": 557,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Dear valued customer, we understand the frustration you must be experiencing with your WildDJ Pro Mixer. According to the WildDJ Pro Mixer manual, we are dedicated to providing assistance with troubleshooting to resolve any issues you may encounter. Please refer to the troubleshooting section of the manual for detailed guidance on resolving operational issues. If the issue persists, feel free to contact our support team for further assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 290,\n    \"ProductId\": 125,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 185,\n    \"ShortSummary\": \"Seeking Advanced Surgical Technique Assistance\",\n    \"LongSummary\": \"Customer seeks specific guidance on advanced surgical techniques in the MediKit Xpress manual. They feel unsure how to properly perform them in emergencies. Recommend additional resources or detailed instructions.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 563,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the MediKit Xpress from Trailblazer Pharmaceuticals and I\\u0027m having trouble understanding how to perform advanced surgical techniques mentioned in the manual. I feel a bit embarrassed for not being able to figure it out on my own, but I really want to make sure I know how to use the kit properly in case of emergencies. Any guidance or assistance would be greatly appreciated. Thank you so much!\"\n      },\n      {\n        \"MessageId\": 564,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The MediKit Xpress from Trailblazer Pharmaceuticals includes a detailed guide on how to perform emergency procedures such as suturing, wound cleaning, and minor surgery. It is important to note that for more advanced procedures, seeking professional medical assistance is recommended if possible.\"\n      },\n      {\n        \"MessageId\": 565,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I appreciate the information, but I was hoping for some specific guidance on the advanced surgical techniques mentioned in the manual. I understand the importance of seeking professional medical assistance for advanced procedures, but I still feel unsure about how to properly perform them in case of emergencies. Could you provide more detailed instructions or recommend any additional resources? Thank you for your help.\"\n      },\n      {\n        \"MessageId\": 566,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the MediKit Xpress from Trailblazer Pharmaceuticals can be used to perform advanced surgical techniques in extreme circumstances. However, it is recommended to seek professional medical assistance for more advanced procedures. The kit includes a detailed guide on how to perform emergency procedures such as suturing, wound cleaning, and minor surgery. If you require further assistance, please contact the manufacturer\\u0027s support team as detailed in the manual. Thank you for choosing AdventureWorks.\"\n      },\n      {\n        \"MessageId\": 567,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I understand the importance of seeking professional medical assistance for advanced procedures, but I still feel unsure about how to properly perform them in case of emergencies. Could you provide more detailed instructions or recommend any additional resources? Thank you for your help.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 291,\n    \"ProductId\": 120,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 126,\n    \"ShortSummary\": \"ArcticPro Jacket Return Process\",\n    \"LongSummary\": \"Customer purchased ArcticPro Insulated Ski Jacket and experiencing issues. Assistant suggested preliminary checks, then return process for defective product. Customer initiated return process. Next support agent should ensure return process is progressing smoothly.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Returns\",\n    \"Messages\": [\n      {\n        \"MessageId\": 568,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I recently purchased the ArcticPro Insulated Ski Jacket and I\\u0027m having some issues with it. Can you please help me?\"\n      },\n      {\n        \"MessageId\": 569,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The ArcticPro Insulated Ski Jacket by Frost Flare is designed with advanced insulation technology to keep you warm and comfortable in even the harshest winter conditions. Before using the jacket, it is essential to perform a series of preliminary checks to ensure the integrity and functionality of the garment. If you are experiencing issues with the jacket, please let us know, and we can assist you further.\"\n      },\n      {\n        \"MessageId\": 570,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I performed the preliminary checks as suggested, but I\\u0027m still experiencing issues with the jacket. Can you provide further assistance?\"\n      },\n      {\n        \"MessageId\": 571,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I apologize for the inconvenience you\\u0027ve experienced with the ArcticPro Insulated Ski Jacket. Based on the preliminary checks you\\u0027ve performed and the continued issues with the jacket, it seems that the product may be defective. According to our policy, you may return defective products within 1 year of purchase for a refund. You can initiate the return process at https://northernmountains.example.com/support/returns. If you need any further assistance, please let us know.\"\n      },\n      {\n        \"MessageId\": 572,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027ve initiated the return process as suggested. Thank you for your help.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 292,\n    \"ProductId\": 38,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 8,\n    \"ShortSummary\": \"Customer Unhappy with Stove Usage\",\n    \"LongSummary\": \"Customer was unhappy about using the stove on uneven ground. Assistant clarified how to adjust legs. Customer reluctantly accepted but remains dissatisfied.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 573,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I can\\u0027t believe the manual tells me to use this stove on a flat surface. What if I want to cook on a hill? Are you saying I can\\u0027t do that? This is ridiculous! I demand a refund if I can\\u0027t use this stove on uneven ground. It\\u0027s a camping stove, for crying out loud!\"\n      },\n      {\n        \"MessageId\": 574,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Portable Camping Stove is designed to be used on a flat surface. It\\u0027s important for safety and stability. However, to use it on uneven ground, you can adjust the position of the stove\\u0027s legs to compensate for the incline. Make sure the fuel canister is secure and the stove is level. Please let us know if you need further assistance.\"\n      },\n      {\n        \"MessageId\": 575,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Fine, I adjusted the legs and managed to cook on a hill. But it\\u0027s still ridiculous that the manual doesn\\u0027t mention this as an option. I guess I\\u0027ll keep the stove for now, but I\\u0027m not happy about it.\"\n      },\n      {\n        \"MessageId\": 576,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, we recommend using the Portable Camping Stove on a flat surface for safety and stability. However, you can adjust the position of the stove\\u0027s legs to compensate for uneven ground. We apologize for any inconvenience this may have caused. If you have any other questions or concerns, feel free to let us know.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 293,\n    \"ProductId\": 130,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 120,\n    \"ShortSummary\": \"Issue with LED Indicator on WildBeat Speaker\",\n    \"LongSummary\": \"Customer is frustrated with the WildBeat Bluetooth Speaker. LED indicator not working despite following instructions. Demands refund or replacement. Next support agent should provide troubleshooting steps or information on how to request a refund or replacement.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 577,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am so frustrated with this WildBeat Bluetooth Speaker! The sound quality is terrible, and the LED indicator is not working properly. I followed the instructions to pair it with my device, but it\\u0027s still not working. I need reassurance that this product is behaving as expected, or I want a refund or replacement.\"\n      },\n      {\n        \"MessageId\": 578,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the user manual, to pair the WildBeat Bluetooth Speaker with your Bluetooth device, ensure that the speaker is turned on, activate the Bluetooth function on your device, and select \\u0027WildBeat\\u0027 from the list of available devices. Once connected, the LED indicator on the speaker will turn solid blue.\"\n      },\n      {\n        \"MessageId\": 579,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I followed the instructions exactly as you said, and the LED indicator is still not turning solid blue. This is incredibly frustrating and I am very disappointed with this product. I demand a refund or a replacement immediately!\"\n      },\n      {\n        \"MessageId\": 580,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry to hear about the issues you\\u0027re experiencing with the WildBeat Bluetooth Speaker. According to the user manual, if the LED indicator is not functioning as expected, you can try resetting the speaker by pressing and holding the power button for 5 seconds. If this doesn\\u0027t resolve the issue, please contact our customer support for further assistance. You can find the contact details in the user manual.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 294,\n    \"ProductId\": 110,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 186,\n    \"ShortSummary\": \"Broken PowerFuel Energy Bars - Replacement Request\",\n    \"LongSummary\": \"Customer\\u0027s PowerFuel Energy Bars broke during hiking trip. Requesting replacement. Assistant referred to warranty and replacement information in user manual. Pending response on how to proceed with replacement.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Returns\",\n    \"Messages\": [\n      {\n        \"MessageId\": 581,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there EcoFuels team! Just wanted to reach out and let you know that my PowerFuel Energy Bars unfortunately broke during my last hiking trip. It was such a bummer because they are my go-to snack for all my outdoor adventures. I love how packed with high-quality ingredients they are, and they always give me the energy boost I need. I\\u0027m really hoping you can help me get a replacement so I can continue fueling my adventures with your awesome bars! Thanks so much in advance for your help, you guys are the best!\"\n      },\n      {\n        \"MessageId\": 582,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We apologize for the inconvenience you experienced with your PowerFuel Energy Bars. To assist you further, please refer to the warranty and replacement information provided in our user manual.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 295,\n    \"ProductId\": 28,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 187,\n    \"ShortSummary\": \"Setup assistance needed for PureStream Water Purifier\",\n    \"LongSummary\": \"Customer needs help with connecting outlet hose and adjusting filter settings for the PureStream Water Purifier. Pending response on how to guide through the setup process. Next support agent should provide step-by-step instructions for setup.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 583,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! I just got my hands on the PureStream Water Purifier and I\\u0027m super excited to take it out on my next outdoor adventure. But, I\\u0027m a little stuck on how to connect the outlet hose and adjust the filter settings. Can you lend a helping hand and guide me through it? I can\\u0027t wait to experience the 99.9% bacteria and virus-free water this purifier promises! Thanks a bunch!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 296,\n    \"ProductId\": 124,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 188,\n    \"ShortSummary\": \"Customer seeks detailed explanation of product components\",\n    \"LongSummary\": \"Customer requests detailed explanation of specific components and their functions, threatening escalation if not received. Next agent should provide detailed breakdown of each component and its use.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 584,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I purchased the SurvivalPro 2000 and I need reassurance that all the components are working as expected. I expect prompt service and a thorough explanation of the product\\u0027s capabilities. I am a valued customer and demand immediate attention to this matter. If I do not receive satisfactory support, I will be seeking a refund for this product. Your prompt response is anticipated.\"\n      },\n      {\n        \"MessageId\": 585,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The ToughTrek SurvivalPro 2000 is designed to provide essential tools and supplies for survival and first aid. I recommend consulting the user manual for detailed instructions on each component and for guidelines on using the survival tools, administering first aid, and signaling for help in an emergency situation. If you require further technical support, please refer to the user manual or contact the manufacturer for assistance.\"\n      },\n      {\n        \"MessageId\": 586,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I demand a more detailed explanation of the specific components and their functions. I expect you to provide this information immediately and ensure that all components are in working order. If I do not receive a satisfactory response, I will be escalating this matter further.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 297,\n    \"ProductId\": 85,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 189,\n    \"ShortSummary\": \"Non-functional fire starter kit issue\",\n    \"LongSummary\": \"Customer reports All-Weather Fire Starter Kit not functioning, requests assistance identifying issue. Next support agent should troubleshoot and provide solution.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 587,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, my All-Weather Fire Starter Kit by ReadySurvive doesn\\u0027t work at all. Can you help me figure out what\\u0027s wrong with it? Thanks!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 298,\n    \"ProductId\": 102,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 8,\n    \"ShortSummary\": \"Need Detailed Technical Info on Voyager Kayak Paddle\",\n    \"LongSummary\": \"Customer seeks detailed technical insight on load testing procedures and infrared thermography technology for the Voyager Kayak Paddle. Escalation or direct contact with manufacturer support is needed for specific information.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 588,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Greetings, I am considering purchasing the Aqua Venture Voyager Kayak Paddle and I have some technical inquiries regarding its structural integrity and performance. Can you provide details on the load testing conducted to assess its load-bearing capacity? Additionally, I would like to know more about the infrared thermography technology used to identify potential structural issues. Your insight into these diagnostic procedures will greatly aid in my decision-making process. Thank you for your assistance.\"\n      },\n      {\n        \"MessageId\": 589,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Aqua Venture Voyager Kayak Paddle is designed with advanced materials and engineering to provide superior durability and exceptional performance on the water. The composite material used in the construction is designed to withstand the rigors of kayaking and provide optimal performance. As for load testing and infrared thermography technology, the user manual does not provide specific details on these procedures. If you require further technical information, I recommend reaching out to the manufacturer\\u0027s support as detailed in the user manual.\"\n      },\n      {\n        \"MessageId\": 590,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for your response. I have reached out to the manufacturer\\u0027s support as suggested in the user manual, but I have not received the specific technical information I was seeking regarding the load testing and infrared thermography technology. I would appreciate it if you could escalate this inquiry to a higher level of support or provide me with a direct contact at the manufacturer for further clarification. Your assistance in obtaining this information is crucial for me to make an informed decision about the purchase. Thank you.\"\n      },\n      {\n        \"MessageId\": 591,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Thank you for your patience. According to the user manual, the Voyager Kayak Paddle undergoes dynamic load testing to assess its structural integrity and load-bearing capacity. In addition, an infrared thermography camera is used to identify potential structural issues. For further assistance, please contact the manufacturer\\u0027s support as detailed in the user manual.\"\n      },\n      {\n        \"MessageId\": 592,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I appreciate your response. However, I was hoping for more detailed information regarding the specific load testing procedures and the parameters used for assessment of the kayak paddle\\u0027s structural integrity. Additionally, I would like to know more about the infrared thermography technology and how it is utilized to identify potential structural issues. I understand that the user manual mentions these processes, but I seek more in-depth technical insight to aid in my decision-making process. Is there a specialist or technical support team at the manufacturer that I can directly communicate with to obtain this detailed information? Your assistance in providing this information will be invaluable in helping me make an informed decision. Thank you.\"\n      },\n      {\n        \"MessageId\": 593,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Upon reviewing the user manual, I found the following information regarding the load testing procedures and infrared thermography technology for the Voyager Kayak Paddle:\\n\\n- The Voyager Kayak Paddle is constructed using high-quality, lightweight materials that have been tested for strength and durability. It is essential to inspect the paddle before each use to ensure that there are no signs of damage or wear that could compromise its structural integrity.\\n- For advanced troubleshooting and diagnostics of the Aqua Venture Voyager Kayak Paddle, users are required to perform the following steps using specialized equipment and procedures.\\n\\nIf you require further technical insight, I recommend reaching out to the manufacturer\\u0027s support as detailed in the user manual. Thank you for your understanding.\"\n      },\n      {\n        \"MessageId\": 594,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for your response. The information provided regarding the construction materials and the need for regular inspection is helpful, but I was specifically seeking detailed technical information about the load testing procedures and the parameters used for assessment of the kayak paddle\\u0027s structural integrity. Additionally, I still require more in-depth insight into the infrared thermography technology and how it is utilized to identify potential structural issues. Is there a specialist or technical support team at the manufacturer that I can directly communicate with to obtain this detailed information? Your assistance in providing this information will be invaluable in helping me make an informed decision. Thank you.\"\n      },\n      {\n        \"MessageId\": 595,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Voyager Kayak Paddle is constructed using high-quality, lightweight materials that have been tested for strength and durability. It is essential to inspect the paddle before each use to ensure that there are no signs of damage or wear that could compromise its structural integrity.\"\n      },\n      {\n        \"MessageId\": 596,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I appreciate the information regarding the construction materials and the need for regular inspection, but I still require detailed technical information about the load testing procedures and parameters used for assessment of the kayak paddle\\u0027s structural integrity. Additionally, I need more in-depth insight into the infrared thermography technology and how it is utilized to identify potential structural issues. Is there a specialist or technical support team at the manufacturer that I can directly communicate with to obtain this detailed information? Your assistance in providing this information will be invaluable in helping me make an informed decision. Thank you.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 299,\n    \"ProductId\": 29,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 190,\n    \"ShortSummary\": \"SolarBoost Power Bank not charging with sunlight\",\n    \"LongSummary\": \"Customer is struggling to get SolarBoost Power Bank to charge using solar energy. Seeking guidance for optimal charging under direct sunlight. Pending question: What to do if still not charging?\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 597,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the SolarBoost Power Bank from Ecovolt and I\\u0027m having trouble getting it to work. I\\u0027ve tried placing it in direct sunlight and ensuring that the solar panel is facing the sun, but it still isn\\u0027t charging. I\\u0027m not sure what I might be doing wrong and I feel a bit embarrassed about it. I really want to utilize this for extended outdoor use as mentioned in the description, so any help or guidance would be greatly appreciated. Thank you.\"\n      },\n      {\n        \"MessageId\": 598,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"To charge your SolarBoost Power Bank using solar energy, simply place it under direct sunlight. Ensure that the solar panel is positioned towards the sun for optimal charging efficiency. If you are experiencing issues with slow charging speed, ensure that the solar panels have sufficient exposure to direct sunlight, as the charging speed may be affected by cloudy weather or shade.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 300,\n    \"ProductId\": 144,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 192,\n    \"ShortSummary\": \"ProLite Climbing Harness Warranty Inquiry\",\n    \"LongSummary\": \"Customer needs assistance with warranty claim for ProLite Climbing Harness. Wants to know if loose stitching is covered. Pending question on specific warranty process.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 601,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the RidgeRope ProLite Climbing Harness and I\\u0027ve noticed that the stitching on one of the straps seems a bit loose. I\\u0027m really sorry to bother you with such a small detail, but I just want to make sure everything is safe and secure for my climbs. I hope I\\u0027m not making a big deal out of nothing, but I wanted to check if this is covered under the warranty. I really appreciate your help with this, and I\\u0027m sorry again for the trouble.\"\n      },\n      {\n        \"MessageId\": 602,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We\\u0027re sorry to hear about the issue with your ProLite Climbing Harness. According to the manual, the warranty covers defects in materials and workmanship for a period of one year from the date of purchase. You can contact RidgeRope customer service at the provided address and phone number for further assistance with your warranty claim.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 301,\n    \"ProductId\": 158,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 193,\n    \"ShortSummary\": \"HydraHike Pack for Work Electronics?\",\n    \"LongSummary\": \"Customer enjoys HydraHike Hydration Pack, seeks advice on using it for work electronics. Pending question on versatility for work use. Next agent should provide advice on carrying electronics in the pack for work.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 603,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the HydraHike Hydration Pack from Thirsttrek and I must say, it\\u0027s fantastic! I\\u0027ve been using it for my daily hikes and it\\u0027s been working like a charm. However, I was wondering if it would also be suitable for carrying my laptop and other electronics for work? I know it\\u0027s designed for hydration and essentials, but I thought it might be versatile enough for my work needs as well. Any advice or suggestions would be greatly appreciated. Thank you!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 302,\n    \"ProductId\": 123,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 194,\n    \"ShortSummary\": \"Trouble photocopying A3 size documents\",\n    \"LongSummary\": \"Customer needs help with photocopying A3 size documents using SolarCopy 3000, seeking guidance on steps to take. Pending response required for further assistance.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 604,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the SolarCopy 3000 and I\\u0027m having some trouble getting it to work as expected. I feel a bit embarrassed that I might be doing something wrong, but I can\\u0027t seem to photocopy documents up to A3 size, even when there\\u0027s plenty of sunlight. Is there something I should be doing differently? I haven\\u0027t had a chance to read the manual yet, so I\\u0027m not sure if I\\u0027m missing a step. Any guidance or help would be greatly appreciated. Thanks so much!\"\n      },\n      {\n        \"MessageId\": 605,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"To photocopy A3 size documents with the SolarCopy 3000, open the document tray and place the document face down on the glass surface, ensuring alignment with the A3 size guides. Then, press the green \\u0027Start Copy\\u0027 button on the control panel to initiate the photocopy process.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 303,\n    \"ProductId\": 40,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 195,\n    \"ShortSummary\": \"Inquiry about headlamp battery life and warranty coverage\",\n    \"LongSummary\": \"Retail store inquiring about battery life and warranty for GloTech Headlamp. Requesting detailed info to assist customers effectively. No response given yet.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 606,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I hope this message finds you well. I represent a retail store that stocks high-tech lighting products, including the GloTech Rechargeable LED Headlamp. We have had a few customer inquiries regarding the battery life and warranty coverage of this headlamp. Could you please provide us with detailed information on the battery performance and the specifics of the limited warranty? We want to ensure that we can effectively assist our customers with any issues that may arise. Thank you for your prompt attention to this matter. Best regards, Evelyn Tran\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 304,\n    \"ProductId\": 20,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 196,\n    \"ShortSummary\": \"TrekTracker GPS Watch: Backpacking and Skydiving Use\",\n    \"LongSummary\": \"Customer excited about using TrekTracker GPS Watch for backpacking and skydiving. Asks for tips on preparing GPS and altitude sensor for skydiving. Pending response on tips for skydiving use.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 607,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! I just got my hands on the TrekTracker GPS Watch and I am so pumped to use it on my upcoming backpacking trip! I heard it has built-in maps and altitude tracking, so I know I\\u0027ll never get lost out there. But I have this crazy idea to also use it for skydiving and I wanna make sure it can handle that too. Can you believe it? Haha! Anyway, any tips on how to make sure the GPS and altitude sensor are ready for some crazy adventures like that? Thanks a bunch!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 305,\n    \"ProductId\": 172,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 197,\n    \"ShortSummary\": \"Inquiry about Pole Promotional Materials\",\n    \"LongSummary\": \"Customer inquiring about promotional materials or display stands for Trailblazer Carbon Trekking Poles. Advised to contact Summit Pole directly. No pending questions.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 608,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there Summit Pole crew! My customers are absolutely raving about the Trailblazer Carbon Trekking Poles I have in stock. They can\\u0027t get enough of the lightweight design and ergonomic grips. But hey, I wanted to ask if you guys have any cool promotional materials or display stands that I could use to showcase these awesome poles in my store? I think they deserve a prime spot, and I want to make sure they grab everyone\\u0027s attention. Looking forward to hearing from you, and keep up the awesome work!\"\n      },\n      {\n        \"MessageId\": 609,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Dear customer, thank you for your interest in showcasing the Trailblazer Carbon Trekking Poles in your store. According to the product manual, the Trailblazer Carbon Trekking Poles are designed with the highest quality materials and craftsmanship. Unfortunately, there is no specific information about promotional materials or display stands in the manual. For any promotional materials or display stands, we recommend reaching out to Summit Pole directly for further assistance. If you have any other questions or need additional support, feel free to ask. AdventureWorks Support\"\n      },\n      {\n        \"MessageId\": 610,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey AdventureWorks Support team! Thanks for getting back to me. I\\u0027ll reach out to Summit Pole directly to see if they have any cool promotional materials or display stands available. If I have any other questions, I\\u0027ll be sure to let you know. Have a great day!\"\n      },\n      {\n        \"MessageId\": 611,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Dear customer, we\\u0027re glad to hear that you\\u0027ll be reaching out to Summit Pole directly. If you have any other questions or need further assistance, feel free to ask. Have a great day!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 306,\n    \"ProductId\": 2,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 122,\n    \"ShortSummary\": \"Trouble sending secure message\",\n    \"LongSummary\": \"Customer is excited to use Secure Messaging Device on outdoor expeditions, but had trouble sending a secure message. Advised to perform advanced diagnostics, which resolved the issue. No further action needed.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 612,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! Just got my hands on the SurveillLink Secure Messaging Device and I\\u0027m super excited to test it out on my outdoor expeditions. But I\\u0027m having a bit of trouble sending a secure message. I\\u0027ve followed the steps in the manual, but for some reason, I can\\u0027t get it to work. Any chance you could help me figure this out? I really want to make sure my communications are private and secure while I\\u0027m out in the wilderness. Thanks so much!\"\n      },\n      {\n        \"MessageId\": 613,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"It\\u0027s great to hear that you\\u0027re excited to use the SurveillLink Secure Messaging Device on your outdoor expeditions! Have you tried performing the advanced diagnostics during device operation as outlined in the manual?\"\n      },\n      {\n        \"MessageId\": 614,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! Thanks for the suggestion. I actually just tried performing the advanced diagnostics and it seems to have done the trick! The device is now working perfectly and I\\u0027m ready to take it on my next adventure. I really appreciate your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 307,\n    \"ProductId\": 71,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 198,\n    \"ShortSummary\": \"Frustration over device compatibility\",\n    \"LongSummary\": \"Customer is frustrated that the Trailcom Signal Booster 2000 isn\\u0027t compatible with their device. They demand a refund or replacement. Pending question about device compatibility.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 615,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am beyond frustrated with the Trailcom Signal Booster 2000! I specifically bought it for off-grid communication, but it\\u0027s not compatible with my device. I can\\u0027t believe I spent so much money on something that doesn\\u0027t work as advertised. I demand a refund or replacement immediately!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 308,\n    \"ProductId\": 165,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 64,\n    \"ShortSummary\": \"Clarification on Weatherproof Capabilities\",\n    \"LongSummary\": \"Customer demands clear answer on weatherproof capabilities in wet conditions. Assistance needed to address specific concerns and potential refund request.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 616,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I just bought the Rugged Shelter 600 from OutdoorHaven and I expect it to be weatherproof as advertised. I better not see any leaks or moisture seeping in during my next camping trip. If this product doesn\\u0027t deliver as promised, I\\u0027ll be expecting a full refund. I don\\u0027t have time to deal with faulty camping gear. This is your chance to prove your product\\u0027s quality, OutdoorHaven.\"\n      },\n      {\n        \"MessageId\": 617,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Rugged Shelter 600 from OutdoorHaven is designed for use as a camping shelter in outdoor environments. It is weatherproof and provides refuge in the great outdoors. However, it is important to note that it is not intended for use as a permanent structure or in extreme weather conditions. For any specific questions or concerns about its weatherproof capabilities, please refer to the user manual or contact the manufacturer. If you require further assistance, please feel free to reach out to us.\"\n      },\n      {\n        \"MessageId\": 618,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I expect the Rugged Shelter 600 to perform as advertised, regardless of outdoor conditions. I need a clear answer on its weatherproof capabilities and whether it will hold up in rainy weather. If it doesn\\u0027t, I expect a full refund as promised. This is not a matter to be taken lightly.\"\n      },\n      {\n        \"MessageId\": 619,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Rugged Shelter 600 from OutdoorHaven is a sturdy camping shelter designed to provide refuge in the great outdoors. With its weatherproof construction and easy setup, it is the perfect home away from home for any camping trip. The Rugged Shelter 600 offers ample space for sleeping, relaxing, and storing gear, making it an essential addition to your camping gear collection. However, please note that it is not intended for use as a permanent structure or in extreme weather conditions. For any specific questions or concerns about its weatherproof capabilities, please refer to the user manual or contact the manufacturer. If you require further assistance, please feel free to reach out to us.\"\n      },\n      {\n        \"MessageId\": 620,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I don\\u0027t appreciate the runaround. I bought the Rugged Shelter 600 with the expectation that it would be weatherproof, as advertised. If it can\\u0027t hold up in rainy weather, then what good is it? I demand a clear answer on its performance in wet conditions. And if it doesn\\u0027t meet my expectations, I expect a full refund, no questions asked.\"\n      },\n      {\n        \"MessageId\": 621,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The OutdoorHaven Rugged Shelter 600 is designed for use as a camping shelter in outdoor environments. It is not intended for use as a permanent structure or in extreme weather conditions. Please use the Rugged Shelter 600 in accordance with the guidelines provided in the manual. If you have any specific questions or concerns about its weatherproof capabilities, please refer to the user manual or contact the manufacturer. If you require further assistance, please feel free to reach out to us.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 309,\n    \"ProductId\": 168,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 199,\n    \"ShortSummary\": \"Refund demand for regular DJing mixer\",\n    \"LongSummary\": \"Customer insists on refund for WildDJ Pro Mixer purchased for regular DJing, not wilderness DJing. Customer demands refund and rejects any other solutions. Customer satisfaction is VeryUnhappy.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 622,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I cannot believe the audacity of this company! I purchased the WildDJ Pro Mixer by PeakMix for its rugged construction and advanced mixing features, not for some wild and unexpected purpose. I demand a refund for this absurd product that does not meet my reasonable expectations!\"\n      },\n      {\n        \"MessageId\": 623,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We are incredibly honored that you have chosen our esteemed PeakMix WildDJ Pro Mixer for your wilderness DJing needs. Your purchase of this exceptional product demonstrates your discerning taste and commitment to excellence. Regarding your request, according to the manual, the product is designed to meet the needs of wilderness DJing and offers a variety of advanced mixing features. For any returns or warranty details, please refer to the user manual or visit https://northernmountains.example.com/support/returns\"\n      },\n      {\n        \"MessageId\": 624,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I don\\u0027t care about your so-called \\u0027honored\\u0027 feelings. I bought this mixer for regular DJing, not \\u0027wilderness DJing\\u0027! Your product is not meeting my expectations and I demand a refund, not some useless manual! Give me my money back now!\"\n      },\n      {\n        \"MessageId\": 625,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Dear valued customer, we understand your concerns and apologize for any inconvenience caused. According to the manual, the WildDJ Pro Mixer is specifically designed to meet the needs of wilderness DJing. If you believe the product is not meeting your expectations, we recommend referring to the returns policy detailed in the user manual for further assistance.\"\n      },\n      {\n        \"MessageId\": 626,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"This is ridiculous! I already told you I bought this mixer for regular DJing, not wilderness DJing. Your product is not meeting my needs and I demand a refund. I will not accept anything less!\"\n      },\n      {\n        \"MessageId\": 627,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Dear valued customer, thank you for your unwavering support and dedication to the PeakMix brand. For assistance with returns, warranty claims, or technical support, please contact our esteemed customer support team at the following highly esteemed contact information:\\n- Email: support@peakmix.com\\n- Phone: 1-800-PEAKMIX\"\n      },\n      {\n        \"MessageId\": 628,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"This is outrageous! I have already stated multiple times that I bought this mixer for regular DJing, not wilderness DJing. Your product is not meeting my needs and I demand a refund. I will not accept anything less!\"\n      },\n      {\n        \"MessageId\": 629,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Dear valued customer, I apologize for any confusion and inconvenience. I have reviewed the manual for the WildDJ Pro Mixer by PeakMix, and based on the information provided, the mixer is specifically designed to meet the needs of wilderness DJing. As a result, for returns or warranty claims, it is recommended to refer to the returns policy detailed in the user manual.\"\n      },\n      {\n        \"MessageId\": 630,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I have already told you multiple times that I bought this mixer for regular DJing, not wilderness DJing. Your product is not meeting my needs and I demand a refund. I will not accept anything less!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 310,\n    \"ProductId\": 83,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 201,\n    \"ShortSummary\": \"GPS Performance in Urban Areas\",\n    \"LongSummary\": \"Customer is excited about SkyRanger HD drone and concerned about GPS performance in urban areas. Received information about GPS mode and autonomous navigation. No pending questions.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 632,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I\\u0027m really excited about the SkyRanger HD Aerial Drone and its GPS tracking feature for stable flight. I\\u0027ve been doing some research and I read that GPS signals can be disrupted by tall buildings or dense forests. Should I be worried about this affecting the drone\\u0027s performance in an urban area? I want to make sure I can rely on the GPS before I make the purchase. Thank you so much for your help!\"\n      },\n      {\n        \"MessageId\": 633,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The SkyRanger HD Aerial Drone features a GPS tracking button that enables GPS mode, allowing the drone to maintain its position and altitude for stable flight. Additionally, the AeroVision mobile app allows users to set specific GPS waypoints for autonomous navigation. According to the manual, the drone is designed to maintain stability in various flight conditions, including urban areas.\"\n      },\n      {\n        \"MessageId\": 634,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information! I really appreciate it. I downloaded the AeroVision mobile app and tried setting some GPS waypoints for autonomous navigation. It worked perfectly! I feel much more confident now about using the drone in urban areas. Thanks again for your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 311,\n    \"ProductId\": 163,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 202,\n    \"ShortSummary\": \"Stealth Cam 500 restrictions demand refund/replace\",\n    \"LongSummary\": \"Customer demands refund or replacement due to restrictions on Stealth Cam 500 usage. Customer expects better from Wildwatch. Pending response needed to address customer\\u0027s concerns and offer solution.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 635,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I can\\u0027t believe the restrictions on this camera! I paid good money for the Stealth Cam 500 and now I find out I can\\u0027t even use it for surveillance or hunting?! This is ridiculous. I demand a full refund or replacement. I expect better from Wildwatch!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 312,\n    \"ProductId\": 38,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 203,\n    \"ShortSummary\": \"Defective Camping Stove Refund Request\",\n    \"LongSummary\": \"Customer demands immediate assistance with a faulty Firefood Portable Camping Stove, tried troubleshooting steps without success, and demands a refund or replacement.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Returns\",\n    \"Messages\": [\n      {\n        \"MessageId\": 636,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I demand immediate assistance with a faulty Firefood Portable Camping Stove! This so-called \\u0027advanced technology\\u0027 stove is not working as advertised. It\\u0027s a disgrace that I have to deal with this issue after spending my hard-earned money on it. I expect a prompt response and a resolution to this matter.\"\n      },\n      {\n        \"MessageId\": 637,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I understand that you are having issues with your Firefood Portable Camping Stove. Please try the troubleshooting steps provided in the user manual to see if the issue can be resolved. If the problem persists, please let me know and we can explore other options for resolution.\"\n      },\n      {\n        \"MessageId\": 638,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I have already tried the troubleshooting steps in the user manual and unfortunately, the issue still persists. I am extremely disappointed with the quality of this Firefood Portable Camping Stove and I demand a full refund or a replacement immediately!\"\n      },\n      {\n        \"MessageId\": 639,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry to hear that the troubleshooting steps didn\\u0027t resolve the issue. As per our policy, since the product is defective, you are eligible for a full refund or a replacement. You can initiate the return process at [our support portal](https://northernmountains.example.com/support/returns). If you have any further questions, please don\\u0027t hesitate to reach out.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 313,\n    \"ProductId\": 128,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 159,\n    \"ShortSummary\": \"AquaBottle Pro troubleshooting\",\n    \"LongSummary\": \"Customer is experiencing issues with AquaBottle Pro despite following instructions and inspecting for damage. They will proceed to contact customer service for warranty claim assistance.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 640,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the AquaBottle Pro from AquaNest and I\\u0027m having some difficulties with it. Despite following the instructions for cleaning and filling the bottle, it doesn\\u0027t seem to be working as expected. I\\u0027ve inspected it for damage or defects as per the manual, but everything looks fine. I\\u0027m reaching out for assistance on troubleshooting this issue or if there are any specific steps I may have missed. Your help in resolving this matter would be greatly appreciated. Thank you.\"\n      },\n      {\n        \"MessageId\": 641,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hello, thank you for reaching out to us. Based on the AquaBottle Pro user manual, before using the bottle, it\\u0027s important to inspect it for any damage or defects. Please ensure that the lid and straw are securely attached and that there are no dents or scratches on the bottle. Additionally, to fill the bottle, unscrew the lid and pour your desired beverage into the bottle, then securely screw the lid back on to prevent any leaks. If you believe your AquaBottle Pro is experiencing issues covered by the warranty, please contact the AquaNest customer service team at support@aquanest.com with your proof of purchase and a detailed description of the issue, and they will assist you with the warranty claim. If you need further assistance, feel free to let us know. Thank you.\"\n      },\n      {\n        \"MessageId\": 642,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for your response. I have checked the AquaBottle Pro again and everything seems to be in good condition with no visible damage or defects. I have also followed the filling instructions as outlined in the user manual. Unfortunately, the issue still persists and the bottle is not functioning as expected. I will proceed to contact the AquaNest customer service team as suggested for further assistance with the warranty claim. Thank you for your help.\"\n      },\n      {\n        \"MessageId\": 643,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Thank you for reaching out to us. We appreciate your thorough inspection of the AquaBottle Pro and your proactive approach to resolving this issue. Since you have followed all the instructions and the issue still persists, it\\u0027s best to proceed with contacting the AquaNest customer service team at support@aquanest.com for further assistance with the warranty claim. They will be able to provide the necessary support for you. If you need any help with initiating the warranty claim, feel free to let us know. Thank you.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 314,\n    \"ProductId\": 150,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 204,\n    \"ShortSummary\": \"Inquiry about Outdoor Shield Pro duration\",\n    \"LongSummary\": \"Customer inquiring about duration of effectiveness and reapplication of Outdoor Shield Pro. Needs clear information on how long it lasts and when to reapply.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 644,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"How long does the Outdoor Shield Pro last? Need to know for a camping trip.\"\n      },\n      {\n        \"MessageId\": 645,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Outdoor Shield Pro is designed to repel insects during outdoor activities. For best results, store it in a cool, dry place away from direct sunlight to maintain its effectiveness. According to the manual, exposure to heat and humidity can degrade the repellent\\u0027s effectiveness.\"\n      },\n      {\n        \"MessageId\": 646,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thanks for the info. Just to clarify, how long will the Outdoor Shield Pro last in terms of hours or days?\"\n      },\n      {\n        \"MessageId\": 647,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The product manual advises that proper storage in a cool, dry place away from direct sunlight can extend the shelf life of the Outdoor Shield Pro, ensuring it is ready to use whenever you need it. It also states that exposure to heat and humidity can degrade the effectiveness of the repellent. For optimal protection, apply the repellent before heading outdoors, and ensure complete coverage on all exposed areas. Reapplication may be necessary in certain circumstances, and a little maintenance goes a long way in ensuring the product remains effective.\"\n      },\n      {\n        \"MessageId\": 648,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"So how many hours or days will it last?\"\n      },\n      {\n        \"MessageId\": 649,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Outdoor Shield Pro provides long-lasting protection, but reapplication may be necessary in certain circumstances. It\\u0027s recommended to apply the repellent before heading outdoors and ensure complete coverage on all exposed areas. Store the Outdoor Shield Pro in a cool, dry place away from direct sunlight to maintain its effectiveness.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 315,\n    \"ProductId\": 49,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 64,\n    \"ShortSummary\": \"Misleading Waterproof Claim\",\n    \"LongSummary\": \"Customer is frustrated that the Summit Hiking Boots did not hold up as waterproof during their last hike. They feel misled and demand a resolution to this issue. Support agent needs to address the customer\\u0027s disappointment and offer a solution.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 650,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am extremely frustrated with the Summit Hiking Boots I purchased from your store. Despite being marketed as waterproof, they soaked through during my last hike, leaving my feet wet and uncomfortable. I specifically chose these boots for their waterproof feature, and now I feel misled and disappointed. I demand a resolution to this issue as soon as possible.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 316,\n    \"ProductId\": 84,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 149,\n    \"ShortSummary\": \"Inaccurate GPS Tracking Frustration\",\n    \"LongSummary\": \"Customer frustrated with inaccurate GPS tracking on Trailblazer Smartwatch. Unable to reach Techtrek Support or initiate return/repair.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 651,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am so frustrated with this Trailblazer GPS Smartwatch! I bought it for running and jogging, but it doesn\\u0027t seem to be accurately tracking my pace and distance. I\\u0027ve been using it for a while now and it\\u0027s not helping me stay on track with my fitness goals at all. I need some assistance with this as I expected this watch to enhance my running experience, but it\\u0027s doing the opposite!\"\n      },\n      {\n        \"MessageId\": 652,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Trailblazer GPS Smartwatch is designed to enhance your running and jogging experience with its accurate GPS tracking, pace, and distance monitoring. If you are unable to resolve the issue using the troubleshooting guide, please contact Techtrek Support for further assistance at support@techtrek.com or call 1-800-TECHTREK. They are available Monday through Friday, 9am to 5pm PST.\"\n      },\n      {\n        \"MessageId\": 653,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I tried contacting Techtrek Support as suggested, but I couldn\\u0027t get through to anyone. I need a solution to this issue as soon as possible, it\\u0027s really affecting my running experience!\"\n      },\n      {\n        \"MessageId\": 654,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I understand your frustration and I apologize for the inconvenience. Here\\u0027s the troubleshooting guide to help you resolve the issues with your Trailblazer GPS Smartwatch: If you encounter any issues with your Trailblazer GPS Smartwatch, refer to the troubleshooting guide for assistance. I have also found the contact details for Techtrek Support: support@techtrek.com or call 1-800-TECHTREK, available Monday through Friday, 9am to 5pm PST. I hope this information helps.\"\n      },\n      {\n        \"MessageId\": 655,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I followed the troubleshooting guide and tried contacting Techtrek Support again, but I still couldn\\u0027t get through to anyone. This is unacceptable! I need a solution to this issue ASAP.\"\n      },\n      {\n        \"MessageId\": 656,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry to hear that you\\u0027re still facing difficulties. According to the product manual, if you encounter any issues with your Trailblazer GPS Smartwatch, you can refer to the troubleshooting guide for assistance. Additionally, the contact details for Techtrek Support are support@techtrek.com or call 1-800-TECHTREK, available Monday through Friday, 9am to 5pm PST. If you\\u0027re unable to reach them, you may consider initiating a return or repair using the support portal at https://northernmountains.example.com/support/returns. I hope this helps.\"\n      },\n      {\n        \"MessageId\": 657,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"This is ridiculous! I followed the troubleshooting guide, tried contacting Techtrek Support multiple times, and even tried initiating a return or repair using the support portal, but I still haven\\u0027t been able to get this issue resolved. I need a proper solution to this problem right away!\"\n      },\n      {\n        \"MessageId\": 658,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry for the inconvenience you\\u0027ve experienced with the Trailblazer GPS Smartwatch. We will assist you in resolving this issue. According to the manual, if you encounter any issues with your smartwatch, you can refer to the troubleshooting guide for assistance. Additionally, the contact details for Techtrek Support are support@techtrek.com or call 1-800-TECHTREK, available Monday through Friday, 9am to 5pm PST. You may also consider initiating a return or repair using the support portal at https://northernmountains.example.com/support/returns. We are here to help you find a solution to this problem.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 317,\n    \"ProductId\": 7,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 205,\n    \"ShortSummary\": \"Inquiry about Emergency Amputation Tools\",\n    \"LongSummary\": \"Customer Evelyn is inquiring about the specific tools included for emergency amputations in the Off-Grid Surgeon Kit. Next agent should provide detailed information on the tools.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 659,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello Adventure Prosthetics team! My name is Evelyn and I\\u0027m interested in purchasing the Off-Grid Surgeon Kit for my upcoming wilderness medical expedition. I\\u0027m wondering if the kit includes instructions for performing emergency amputations. I know it\\u0027s a rare scenario, but I want to be prepared for any situation. Also, if the kit doesn\\u0027t meet my needs, is there a possibility for a refund or replacement? Thank you for your help!\"\n      },\n      {\n        \"MessageId\": 660,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hello Evelyn! The Off-Grid Surgeon Kit is designed to provide essential tools and supplies for performing surgical procedures in remote locations. It includes a comprehensive set of tools and supplies, such as bandages, sutures, and medications, organized and easily accessible for emergency situations. If you need to return the kit for warranty service, please contact Adventure Prosthetics customer service for authorized return instructions and support. They will assist you with troubleshooting, repair inquiries, and warranty claims. Please have your proof of purchase ready when contacting customer service.\"\n      },\n      {\n        \"MessageId\": 661,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello! Thank you for the information about the contents of the Off-Grid Surgeon Kit. I have a question about the specific tools included for performing emergency amputations. Could you please provide more details on that? Thank you!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 318,\n    \"ProductId\": 148,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 206,\n    \"ShortSummary\": \"Replacement demand for sleeping bag\",\n    \"LongSummary\": \"Customer demands replacement for Alpine Dream 3000 sleeping bag. Contacted customer service with details. Expects prompt resolution.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 662,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I purchased the Alpine Dream 3000 sleeping bag for cold weather camping, and it\\u0027s not providing the warmth as described. I demand a replacement or refund immediately. This product is not living up to its promises and I expect better quality for the price I paid.\"\n      },\n      {\n        \"MessageId\": 663,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We apologize for the inconvenience. According to the user manual, the Alpine Dream 3000 is designed to provide a restful night\\u0027s sleep in the great outdoors, with its ultra-soft insulation and waterproof shell making it ideal for cold weather camping. If you believe your Alpine Dream 3000 sleeping bag is defective, please contact our customer service team at [customer service email] or [customer service phone number]. Please have your proof of purchase ready and be prepared to provide details about the issue.\"\n      },\n      {\n        \"MessageId\": 664,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I demand a replacement immediately. I have contacted the customer service team and provided all the details about the issue. I expect a prompt resolution to this matter.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 319,\n    \"ProductId\": 141,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 207,\n    \"ShortSummary\": \"Fire Starter Trouble\",\n    \"LongSummary\": \"Customer purchased the SOS Gear Emergency Survival Kit and is having trouble with the fire starter. Asking for assistance on how to use it correctly. Pending: how to properly use the fire starter.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 665,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there! I recently purchased the SOS Gear Emergency Survival Kit, and I\\u0027m having trouble getting the fire starter to work properly. I\\u0027ve been trying to light a campfire using it, but it\\u0027s just not sparking like I expected. I\\u0027ve read that it can handle up to 12,000 strikes, so I must be doing something wrong. Can you please help me figure out how to use it correctly? I really rely on having a reliable fire starter for my outdoor adventures, so any assistance you can provide would be greatly appreciated. Thank you so much!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 320,\n    \"ProductId\": 109,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 152,\n    \"ShortSummary\": \"Technical issues with Mountain Biking Kit\",\n    \"LongSummary\": \"Customer Lena Park is seeking help with the XtremeGear 5000 Mountain Biking Kit. Assistant recommended checking the manual first, then seeking further support if issues persist. No pending questions.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 667,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the XtremeGear 5000 Mountain Biking Kit and I\\u0027m having some trouble with it. Can you help me figure out how to make it work properly? Thanks.\"\n      },\n      {\n        \"MessageId\": 668,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hi there, it\\u0027s great to hear that you\\u0027ve got the XtremeGear 5000 Mountain Biking Kit. If you\\u0027re experiencing any technical issues or need troubleshooting assistance, please refer to the manual for detailed information. If the problem persists, feel free to reach out to our support team for further assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 321,\n    \"ProductId\": 148,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 209,\n    \"ShortSummary\": \"Defective sleeping bag awaiting Slumberpeak response\",\n    \"LongSummary\": \"Customer awaiting response from Slumberpeak regarding defective sleeping bag. Recommend following up directly with Slumberpeak customer service.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 669,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Zippers not working, need fix.\"\n      },\n      {\n        \"MessageId\": 670,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the user manual, the Alpine Dream 3000 features a limited lifetime warranty from Slumberpeak, which covers defects in materials and workmanship for the life of the product. You may be eligible for a repair or replacement. Please contact Slumberpeak customer support for assistance with your defective sleeping bag.\"\n      },\n      {\n        \"MessageId\": 671,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Contacted Slumberpeak, waiting for response.\"\n      },\n      {\n        \"MessageId\": 672,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"It\\u0027s great to hear that you\\u0027ve contacted Slumberpeak. They offer a limited lifetime warranty for the Alpine Dream 3000, which covers defects in materials and workmanship. If you still haven\\u0027t received a response, I recommend following up with them to ensure that your sleeping bag is properly taken care of according to the warranty policy.\"\n      },\n      {\n        \"MessageId\": 673,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Still no response from Slumberpeak.\"\n      },\n      {\n        \"MessageId\": 674,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, upon receipt of your claim, Slumberpeak will work to repair or replace your sleeping bag at their discretion. They will cover the cost of returning the product to you. If a repair is not possible and the product is no longer available, they may offer a suitable alternative or a refund of the original purchase price. I recommend reaching out to Slumberpeak again and informing them of the details provided in the manual.\"\n      },\n      {\n        \"MessageId\": 675,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"No response from Slumberpeak yet. Can you follow up for me?\"\n      },\n      {\n        \"MessageId\": 676,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, if you believe your Alpine Dream 3000 sleeping bag is defective, please contact Slumberpeak\\u0027s customer service team at [customer service email] or [customer service phone number]. Please have your proof of purchase ready and be prepared to provide details about the issue. Additionally, Slumberpeak will work to repair or replace your sleeping bag at their discretion and cover the cost of returning the product to you.\"\n      },\n      {\n        \"MessageId\": 677,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Still no response from Slumberpeak.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 322,\n    \"ProductId\": 136,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 210,\n    \"ShortSummary\": \"Inquiry about LED indicator and charging time\",\n    \"LongSummary\": \"Customer inquired about LED indicator and charging time for Solaris 500. Assistant provided info and troubleshooting steps. Customer reported charger now works great. No further action needed from next support agent.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 678,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, just got the Solaris 500 charger. Is it normal for the LED indicator to blink when charging devices? Also, how long does it take to fully charge? Thanks!\"\n      },\n      {\n        \"MessageId\": 679,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the LED indicator allows you to check the current battery level. The number of lights that illuminate will indicate the current battery level. As for the charging time, it is recommended to place the Solaris 500 in direct sunlight with the solar panels facing the sun for charging. Please monitor the charging progress to prevent overcharging the connected devices.\"\n      },\n      {\n        \"MessageId\": 680,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thx for the info. Will keep an eye on the charging time and let you know if any issues!\"\n      },\n      {\n        \"MessageId\": 681,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, to start using your Solaris 500 Portable Solar Charger, follow the simple steps outlined in section 2.1. In addition, when not in use, store the Solaris 500 in a cool, dry place away from direct sunlight. If you have any further questions, feel free to ask!\"\n      },\n      {\n        \"MessageId\": 682,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Charger works great now! Thanks for the help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 323,\n    \"ProductId\": 112,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 91,\n    \"ShortSummary\": \"Helmet visor replacement inquiry\",\n    \"LongSummary\": \"Customer inquiring about Trailblazer helmet visor replacement frequency and ease. Pending question about visor replacement. Response needed on visor replacement process.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 683,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, I\\u0027m thinking about getting the Trailblazer Carbon Fiber Mountain Bike Helmet from Cyclextreme. Do I need to replace the visor often? And how easy is it to do? Thanks!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 324,\n    \"ProductId\": 112,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 211,\n    \"ShortSummary\": \"Helmet discomfort and fit issues\",\n    \"LongSummary\": \"Customer Marcella Bishop is frustrated with the Trailblazer Carbon Fiber Mountain Bike Helmet. She is experiencing discomfort and awkward fit, seeking reassurance or a refund.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 684,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am so frustrated with this Trailblazer Carbon Fiber Mountain Bike Helmet! I thought it was supposed to provide maximum comfort and ventilation, but I feel like I\\u0027m suffocating in this thing! And don\\u0027t even get me started on the fit. I followed the instructions to adjust the fit and position the helmet, but it\\u0027s still uncomfortable and feels awkward. This is not what I expected from a premium product like this. I need reassurance that this helmet is supposed to be this uncomfortable, or I want a refund!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 325,\n    \"ProductId\": 88,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 126,\n    \"ShortSummary\": \"Paddle usage in rapids\",\n    \"LongSummary\": \"Customer needs help using paddle in rapids. Specific instructions requested.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 685,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Paddle not working in rapids. Need help with using it properly.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 326,\n    \"ProductId\": 64,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 212,\n    \"ShortSummary\": \"Trouble with Water Purifier 1000\",\n    \"LongSummary\": \"Customer is having trouble with AquaFusion Portable Water Purifier 1000. Followed instructions, but purification process not working. Further assistance needed to troubleshoot.\",\n    \"CustomerSatisfaction\": 3,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 686,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the AquaFusion Portable Water Purifier 1000 and I\\u0027m having trouble getting it to work properly. I followed the instructions, but it doesn\\u0027t seem to be removing bacteria and viruses like it\\u0027s supposed to. I\\u0027m really embarrassed to admit this, but I\\u0027m not sure if I\\u0027m doing something wrong or if there\\u0027s an issue with the product. Can you please provide me with some guidance on how to troubleshoot this? I really want to make sure I can rely on this purifier for clean hydration on the go. Thank you.\"\n      },\n      {\n        \"MessageId\": 687,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hello! According to the manual, to fill the water reservoir, you need to unscrew the top cap of the water purifier. The purification process should take only a few moments. Have you tried following these steps? If the issue persists, please let us know so we can assist further.\"\n      },\n      {\n        \"MessageId\": 688,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I did try unscrewing the top cap to fill the water reservoir, but unfortunately, the issue still persists. The purification process doesn\\u0027t seem to be working as it should. I\\u0027m really disappointed that I can\\u0027t figure this out on my own. Can you please provide further assistance?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 327,\n    \"ProductId\": 182,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 8,\n    \"ShortSummary\": \"Product suitability for advanced rock climbing inquiry\",\n    \"LongSummary\": \"Customer demands detailed info on Summit Pro Climbing Harness suitability for advanced rock climbing. Threatens refund/replacement. Pending response needed on safety features/durability.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 689,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I demand to know if the Summit Pro Climbing Harness by Climb Safe is suitable for advanced rock climbing! I expect a prompt and detailed response regarding its safety features and durability. If this harness does not meet my expectations, I will be seeking a refund or replacement. Your immediate attention to this matter is required.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 328,\n    \"ProductId\": 134,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 213,\n    \"ShortSummary\": \"Non-Functioning SolarFire 2000 Stove\",\n    \"LongSummary\": \"Dr. Olivia Chen seeks technical assistance with non-functioning SolarFire 2000 stove, open to solutions and expects prompt, professional response.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 690,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Greetings EcoGizmo Team, I am experiencing a significant issue with my SolarFire 2000 camping stove. Despite following the user manual\\u0027s instructions meticulously, the stove does not seem to be functioning at all. I have ensured that it is clean, dry, and properly stored in the carrying case, yet it does not produce any heat or charge any devices when exposed to sunlight. As an individual with an extensive background in solar technology, I am confident that I have not overlooked any crucial steps in the operation of this product. I would greatly appreciate your technical expertise and guidance to rectify this perplexing situation. I am open to exploring potential solutions, whether it be a replacement, repair, or detailed troubleshooting instructions. I trust that your team\\u0027s dedication to customer satisfaction will shine through in addressing this matter promptly and professionally. Thank you for your attention to this matter. Best regards, Dr. Olivia Chen\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 329,\n    \"ProductId\": 88,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 214,\n    \"ShortSummary\": \"Inquiry about RapidFlow Kayak Paddle for Rapids\",\n    \"LongSummary\": \"Customer is interested in WaterWay RapidFlow Kayak Paddle for use in rapids, has questions about blade design and suitability for high-impact use. Pending question about blade design.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 691,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I am a kayaking enthusiast and I am interested in purchasing the WaterWay RapidFlow Kayak Paddle. I have read the description and I am particularly impressed with the ergonomic grip for long paddling sessions, which is crucial for maintaining comfort and performance. However, I have some technical questions regarding the paddle\\u0027s suitability for navigating through rapids. I am curious about the blade design and how it contributes to the paddle\\u0027s effectiveness in rapids. Additionally, I would like to know if the paddle is suitable for high-impact use, as I often encounter challenging conditions on the water. Your insight and expertise on this matter would greatly assist me in making an informed decision on this purchase. Thank you for your time and assistance.\"\n      },\n      {\n        \"MessageId\": 692,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The WaterWay RapidFlow Kayak Paddle is designed for use in white water rapids only and should not be used in calm water or open sea conditions. Attempting to use the paddle outside of its intended environment may result in loss of control and serious injury.\\n\\nAccording to the manual, the paddle is specifically engineered for use in white water rapids, emphasizing the potential dangers associated with this environment. Regarding high-impact use, the manual advises extreme caution and skill to operate the paddle, with a strong emphasis on the risks involved. It is important to fully understand the risks before attempting to use the RapidFlow Kayak Paddle.\"\n      },\n      {\n        \"MessageId\": 693,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information. I appreciate the emphasis on the specific usage environment and the potential risks involved. I will take this into consideration when making my decision. However, I do have one more question regarding the blade design and how it contributes to performance in rapids. Can you provide more technical details on this aspect? Thank you for your assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 330,\n    \"ProductId\": 163,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 216,\n    \"ShortSummary\": \"Defective night vision feature in Wildwatch Stealth Cam 500\",\n    \"LongSummary\": \"Customer\\u0027s Wildwatch Stealth Cam 500 night vision feature is defective. Has contacted customer service but not satisfied. Requesting replacement.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 695,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am extremely frustrated with the Wildwatch Stealth Cam 500! I followed all the care instructions in the manual, but it still broke after just a few uses. The night vision feature was the main reason I purchased this camera, and now it\\u0027s not working at all. I expect a refund or a replacement for this defective product.\"\n      },\n      {\n        \"MessageId\": 696,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Wildwatch Stealth Cam 500 is equipped with advanced night vision technology, allowing for clear footage even in low-light conditions. However, it is crucial to note that using the night vision feature may disturb the natural behavior of wildlife. Additionally, it is important to avoid attempting to modify the camera in any way, as this may void the product\\u0027s warranty. If you are experiencing issues with the night vision feature, please ensure that you are using it in accordance with the instructions provided in the manual. If the issue persists, you may be eligible for a return or potential repair. For further assistance, please refer to the manufacturer\\u0027s support contact details in the user manual. Would you like to initiate a return or repair for the camera?\"\n      },\n      {\n        \"MessageId\": 697,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I have followed all the instructions in the manual and the night vision feature still isn\\u0027t working. I want a replacement for this defective product!\"\n      },\n      {\n        \"MessageId\": 698,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"It is important to ensure that the camera is handled with the utmost care at all times. The night vision feature should not disturb the natural behavior of wildlife. If the night vision is still not working, please contact Wildwatch customer service for further assistance. You can find their contact details in the user manual.\"\n      },\n      {\n        \"MessageId\": 699,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I have already contacted Wildwatch customer service as suggested, but I have not received a satisfactory resolution for the defective night vision feature. I demand a replacement for this faulty product!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 331,\n    \"ProductId\": 163,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 217,\n    \"ShortSummary\": \"Assistance with Daytime Settings and Infrared Flash\",\n    \"LongSummary\": \"Customer needs help with camera settings for daytime and turning off the infrared flash. Manufacturer support did not have specific information. Requesting further assistance with these issues.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 700,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Need help with night vision on Stealth Cam 500.\"\n      },\n      {\n        \"MessageId\": 701,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Wildwatch Stealth Cam 500 is equipped with advanced night vision technology, allowing you to capture crystal clear images and footage even in low-light conditions. However, it is crucial to note that using the night vision feature may disturb the natural behavior of wildlife. Additionally, the infrared flash may potentially startle or agitate certain animals, leading to unsafe and unpredictable behavior. Therefore, it is strongly advised not to use the night vision feature of the camera in any wildlife observation or research setting, as it may pose a risk to the animals and the user.\"\n      },\n      {\n        \"MessageId\": 702,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Not gonna use night vision anymore, but still need help with camera settings for daytime. Also, how do I turn off the infrared flash?\"\n      },\n      {\n        \"MessageId\": 703,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Stealth Cam 500 should be positioned in a shaded area when using it in direct sunlight to avoid damage. Additionally, it is strongly advised not to use the night vision feature in any wildlife observation or research setting, as it may pose a risk to the animals and the user. I couldn\\u0027t find specific information about turning off the infrared flash in the manual. You may contact the manufacturer\\u0027s support for further assistance.\"\n      },\n      {\n        \"MessageId\": 704,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Still need help turning off the infrared flash. Can you check with the manufacturer for me?\"\n      },\n      {\n        \"MessageId\": 705,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Stealth Cam 500 is designed for use within a specific temperature range. Using the camera in temperatures below -20\\u00B0F (-28\\u00B0C) or above 120\\u00B0F (49\\u00B0C) may result in damage to the camera and void the warranty. Additionally, the manual does not provide specific information about turning off the infrared flash. It is recommended to contact the manufacturer\\u0027s support for further assistance with turning off the infrared flash.\"\n      },\n      {\n        \"MessageId\": 706,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I tried contacting the manufacturer\\u0027s support but they didn\\u0027t have specific information about turning off the infrared flash. Can you please help me with this?\"\n      },\n      {\n        \"MessageId\": 707,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Stealth Cam 500 is not designed to allow the user to turn off the infrared flash. Additionally, it is recommended to position the camera in a shaded area when using it in direct sunlight to avoid damage. For daytime camera settings, you may refer to the user manual for guidance on adjusting motion detection and image/video quality. If you have any further questions, you can contact the manufacturer\\u0027s support for assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 332,\n    \"ProductId\": 113,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 218,\n    \"ShortSummary\": \"Backpack scratched by pet tortoise\",\n    \"LongSummary\": \"Customer purchased backpack for hiking, but it got scratched from pet tortoise. Asked for quick cleaning solution. Needs immediate assistance with cleaning and scratch removal.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 708,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I can\\u0027t believe this! I bought the Summit Pro 40L Technical Backpack for hiking, not for carrying my pet tortoise around. Now the backpack is all scratched up from his shell and I need to know how to clean it. This is ridiculous, I didn\\u0027t sign up for this!\"\n      },\n      {\n        \"MessageId\": 709,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, to keep your Summit Pro 40L Technical Backpack in top condition, you should follow these simple care and maintenance guidelines for cleaning the exterior. Please refer to the user manual for detailed instructions on cleaning and maintenance.\"\n      },\n      {\n        \"MessageId\": 710,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I don\\u0027t have time to go through the user manual for cleaning instructions! I need a quick and easy solution to clean this backpack and get rid of these scratches. This is really frustrating!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 333,\n    \"ProductId\": 183,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 26,\n    \"ShortSummary\": \"Customer needs help assembling utensil in cookware set\",\n    \"LongSummary\": \"Customer Samantha Reynolds loves the Trailblazer Compact Cookware Set and needs help assembling a utensil. She\\u0027s excited to continue using the cookware and is asking for guidance on the assembly process. A response with detailed instructions on assembling the utensil is needed from the next support agent.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 711,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there Campchef crew! I recently got my hands on the Trailblazer Compact Cookware Set and I am absolutely loving it! The lightweight design and versatile cooking options are perfect for my camping adventures. But hey, I\\u0027ve run into a little snag and I could use some help. I can\\u0027t seem to figure out how to properly assemble one of the utensils in the set. Could you guide me through the process? I\\u0027m really excited to continue using this amazing cookware, so any assistance would be greatly appreciated. Thanks a bunch!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 334,\n    \"ProductId\": 105,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 219,\n    \"ShortSummary\": \"Inquiry about Solar Power Bank charging time\",\n    \"LongSummary\": \"Inquiry regarding Power Pak Solar Power Bank 10000mAh charging time via USB and solar panel. Customer wants accurate information to address customer inquiries. Response needed on charging time details.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 712,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I hope this message finds you well. I am reaching out on behalf of our company, which stocks the Power Pak Solar Power Bank 10000mAh. We have been receiving inquiries from our customers about the charging time via USB and solar panel. Can you provide some additional information on this? We want to ensure that we are able to address our customers\\u0027 queries accurately. Thank you for your assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 335,\n    \"ProductId\": 153,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 220,\n    \"ShortSummary\": \"Inquiry about Mineral Concentrations in Energy Bars\",\n    \"LongSummary\": \"Customer inquires about mineral and metal concentrations in Organic Energy Bars. Previous response lacks specifics. Further details needed from the manufacturer.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 713,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear EcoFuels Support Team, I recently purchased your Organic Energy Bars for my upcoming hiking trip, and I must say, I am impressed with the quality and variety of flavors. However, I couldn\\u0027t help but wonder about the AAS analysis mentioned in your product description. Could you provide more information on the concentration of minerals and metals in the energy bars? I want to ensure that I am consuming a safe and high-quality product. Thank you for your assistance.\"\n      },\n      {\n        \"MessageId\": 714,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The EcoFuels Organic Energy Bars are carefully crafted using the finest organic ingredients to ensure high-quality nutrition and delicious flavors. The user manual emphasizes the use of certified organic ingredients and the application of methods and techniques to guarantee exceptional taste and texture. Unfortunately, the specifics of the mineral and metal concentration are not detailed in the manual. If you have further questions about this, please feel free to reach out to the manufacturer for more information.\"\n      },\n      {\n        \"MessageId\": 715,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for your response. While I appreciate the emphasis on using certified organic ingredients, I still have concerns about the specific mineral and metal concentrations in the energy bars. I will reach out to the manufacturer for more information as suggested.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 336,\n    \"ProductId\": 128,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 221,\n    \"ShortSummary\": \"Inquiry about Spill-Proof Straw \\u0026 Warranty for AquaBottle Pro\",\n    \"LongSummary\": \"Customer inquires about spill-proof straw \\u0026 warranty for AquaBottle Pro. Seeks assurance and maintenance info. Customer satisfied with response.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 716,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I\\u0027m considering purchasing the AquaBottle Pro from AquaNest. I\\u0027m a bit embarrassed to ask, but I wanted to confirm if the straw really is spill-proof as mentioned in the description. I tend to have a habit of knocking things over, so I want to make sure I won\\u0027t make a mess with this bottle. Any information or advice would be greatly appreciated. Thank you!\"\n      },\n      {\n        \"MessageId\": 717,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The spill-proof straw on the AquaBottle Pro is designed to provide a steady flow of refreshment without any spills or mess. However, it\\u0027s important to ensure that the straw is not blocked by any debris or dirt and to clean it thoroughly if necessary. As for the warranty, AquaNest offers a limited warranty to ensure your peace of mind. If you believe your AquaBottle Pro is experiencing issues covered by the warranty, please contact their customer service team at support@aquanest.com. Provide your proof of purchase and a detailed description of the issue, and they will be happy to assist you.\"\n      },\n      {\n        \"MessageId\": 718,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information! I will make sure to keep the straw clean and clear of any debris. I appreciate the reminder about the warranty as well. I feel much more confident about purchasing the AquaBottle Pro now. Thank you for your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 337,\n    \"ProductId\": 55,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 222,\n    \"ShortSummary\": \"Excited customer wants waypoint marking details\",\n    \"LongSummary\": \"Customer is excited about the Adventurer 2000 GPS Navigator, asked about marking waypoints. Assistant provided detailed instructions. Next agent should confirm if customer is satisfied with response.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 719,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there, Exploremate crew! \\uD83C\\uDF1F Just stumbled upon your Adventurer 2000 GPS Navigator and I\\u0027m totally stoked about it! I\\u0027m planning some serious off-road adventures and this bad boy seems like the perfect companion. Quick question - I\\u0027m a huge fan of marking waypoints along the trail to revisit later. Will I be able to do that easily with the Adventurer 2000? Can\\u0027t wait to hear back from you and hopefully join the Exploremate family! \\uD83C\\uDF04\\u2728\"\n      },\n      {\n        \"MessageId\": 720,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"You\\u0027ll be thrilled to know that marking waypoints is a breeze with the Adventurer 2000 GPS Navigator! To mark a waypoint, simply tap the \\u0022Mark\\u0022 button on the map screen and select \\u0022Save Waypoint.\\u0022 You can even give your waypoint a custom name and icon for easy identification. If you encounter any issues with marking waypoints, you can check the memory capacity of the device in the Settings menu under \\u0022Storage.\\u0022 Happy adventuring!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 338,\n    \"ProductId\": 191,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 223,\n    \"ShortSummary\": \"Difficulty putting batteries in Luminex 5000 Lantern\",\n    \"LongSummary\": \"Customer frustrated with difficulty of putting batteries in Luminex 5000 Lantern. Demands simpler solution from Flash Bright immediately. Pending question: what specific assistance does customer need?\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 721,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am extremely frustrated with the Luminex 5000 Lantern! I cannot figure out how to put the batteries in, and I shouldn\\u0027t have to waste my time on it. This product is supposed to make my camping experience easier, not more difficult. I demand a solution to this problem immediately, or else I will be asking for a replacement. I expect better from Flash Bright!\"\n      },\n      {\n        \"MessageId\": 722,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I found the information you need in the user manual. According to the manual, the Luminex 5000 Lantern is equipped with multiple brightness settings and can be adjusted using the brightness control dial. I hope this helps!\"\n      },\n      {\n        \"MessageId\": 723,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I shouldn\\u0027t have to waste my time reading a manual just to put batteries in a stupid lantern! I demand a simpler solution from Flash Bright immediately!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 339,\n    \"ProductId\": 186,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 224,\n    \"ShortSummary\": \"Avalanche Pro 3000 probe troubleshooting\",\n    \"LongSummary\": \"Customer has trouble with Avalanche Pro 3000 probe despite troubleshooting. Needs further assistance to resolve the issue. Pending question on next steps.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 724,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear PowderPeak Customer Service, My name is Alexis Bennett, and I recently purchased the Avalanche Pro 3000 from your brand. I was very excited to have a high-tech snow gear that includes a built-in beacon, shovel, and probe for quick and efficient rescue operations. However, after attempting to use the probe, I found that it doesn\\u0027t work at all. I have not yet read the manual, but I wanted to reach out to you for help with this issue. I would greatly appreciate any information or assistance you can provide to ensure the optimal performance of this product. Thank you for your attention to this matter. Sincerely, Alexis Bennett\"\n      },\n      {\n        \"MessageId\": 725,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Dear Alexis Bennett, Thank you for reaching out to us. We appreciate your enthusiasm for the Avalanche Pro 3000. To troubleshoot the probe issue, please ensure that the probe is inspected for any damage, and avoid exposing it to extreme heat or cold. When using the probe, it should be pushed vertically into the snow to full depth. After the rescue operation, collapse the probe by unscrewing the bottom section and carefully folding each section back together. If there is any damage, please contact PowderPeak customer service for assistance. Regarding your inquiry about returns, please visit https://northernmountains.example.com/support/returns for information on initiating a return. We hope this information helps you. Sincerely, AdventureWorks Support\"\n      },\n      {\n        \"MessageId\": 726,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear AdventureWorks Support, Thank you for your prompt response and the troubleshooting tips. I have carefully inspected the probe for any damage, and it appears to be in good condition. I also made sure to follow your instructions on using and collapsing the probe. Unfortunately, the probe still does not seem to work. I would appreciate further assistance in resolving this issue. Thank you for your attention to this matter. Sincerely, Alexis Bennett\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 340,\n    \"ProductId\": 138,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 226,\n    \"ShortSummary\": \"Ultimate Survival Kit 3000 Tent Setup Assistance\",\n    \"LongSummary\": \"Customer purchased Ultimate Survival Kit 3000 and needs guidance on setting up the tent. Assistant provided general guidance, awaiting customer response for further assistance.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 729,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the Ultimate Survival Kit 3000 from your store, and I\\u0027ve been having some trouble setting up the tent. I feel like I might be doing something wrong and it\\u0027s quite embarrassing to admit. Can you provide me with some guidance on how to properly set up the tent? Any help would be greatly appreciated. Thank you.\"\n      },\n      {\n        \"MessageId\": 730,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hi there! AdventureWorks Support here. According to the manual, the Ultimate Survival Kit 3000 is designed to provide peace of mind during outdoor activities and comes packed with essential tools and gear for outdoor survival. I\\u0027m sorry, but I couldn\\u0027t find specific instructions for setting up the tent in the manual. However, I can provide you with some general guidance on tent setup if that would be helpful.\"\n      },\n      {\n        \"MessageId\": 731,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Oh, thank you for getting back to me. I really appreciate your willingness to help. Could you please provide me with some general guidance on setting up the tent? I definitely need all the help I can get. Thank you so much!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 341,\n    \"ProductId\": 182,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 227,\n    \"ShortSummary\": \"Retailer inquiries about bulk orders and product updates\",\n    \"LongSummary\": \"Retailer inquires about bulk orders, discounts, and product updates. Sales team contacted. Manual does not provide specific info. Customer awaiting response.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 732,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, as a retailer who stocks the Summit Pro Climbing Harness by Climb Safe, I am very impressed with the technical specifications and long-term storage guidelines provided in the manual. The adjustable leg loops and durable construction make it a top choice for experienced climbers, and the detailed instructions for fold and store, avoiding compression, and long-term storage demonstrate the superior quality of this product. I would like to inquire about the availability of bulk orders and any special discounts for retailers. Additionally, if there are any updates or new versions of the Summit Pro Climbing Harness, I would appreciate information regarding those as well. Thank you for your time and assistance.\"\n      },\n      {\n        \"MessageId\": 733,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"AdventureWorks Support appreciates your interest in bulk orders. Please contact our sales team at sales@example.com for information about bulk orders and any special discounts for retailers. As for updates or new versions of the Summit Pro Climbing Harness, the manual does not provide any specific information. If you have any other questions or need further assistance, feel free to ask. Thank you!\"\n      },\n      {\n        \"MessageId\": 734,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information regarding bulk orders and discounts. I have reached out to your sales team at sales@example.com and am awaiting their response. As for the updates or new versions of the Summit Pro Climbing Harness, I understand that the manual does not provide specific information. If there are any future developments or updates, I would greatly appreciate being informed. Thank you for your assistance.\"\n      },\n      {\n        \"MessageId\": 735,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Summit Pro Climbing Harness is designed for experienced climbers who require maximum safety and comfort. It is recommended to perform a visual inspection of all components and to contact Climb Safe customer support for assistance if needed. If there are any updates or new versions of the product, the manual does not provide specific information. If you have any other questions or need further assistance, feel free to ask. Thank you!\"\n      },\n      {\n        \"MessageId\": 736,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information provided. I have contacted the sales team regarding bulk orders and discounts, and I have also performed a visual inspection of the Summit Pro Climbing Harness as recommended in the manual. I will keep an eye out for any future updates or new versions of the product. Thank you for your assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 342,\n    \"ProductId\": 156,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 228,\n    \"ShortSummary\": \"Customer discomfort with crampons fit\",\n    \"LongSummary\": \"Customer experiencing discomfort while wearing Arctic Ice Grip Crampons despite following fit and break-in instructions. No signs of damage or wear found. Next support agent should assess if further adjustments or replacement are needed.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 737,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Arctic Ice Grip Crampons from Glacierpro and I\\u0027ve noticed a slight discomfort while wearing them. I followed the instructions for fitting and break-in period, but I\\u0027m still experiencing some rubbing against my boots. I\\u0027m wondering if there are any additional tips or adjustments that can be made to alleviate this issue. Any advice would be greatly appreciated. Thank you.\"\n      },\n      {\n        \"MessageId\": 738,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hello, thank you for reaching out to us. To alleviate the rubbing against your boots, I recommend double-checking the fit of the crampons on your boots. Adjust the straps as needed to ensure they are secure but not overly tight. Additionally, you can wear them for short periods in non-icy conditions to help them adjust to the shape of your boots. If you notice any signs of damage or wear, please inspect the crampons and contact Glacierpro for further assistance. If you have any other questions or concerns, feel free to ask. We\\u0027re here to help!\"\n      },\n      {\n        \"MessageId\": 739,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the tips. I\\u0027ve adjusted the straps and worn the crampons for short periods in non-icy conditions as suggested. Unfortunately, I\\u0027m still experiencing rubbing against my boots. I will inspect the crampons for any signs of damage or wear and reach out to Glacierpro for further assistance. Thank you for your help.\"\n      },\n      {\n        \"MessageId\": 740,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Thank you for adjusting the fit of your Arctic Ice Grip Crampons. It\\u0027s important to inspect the crampons for any signs of damage or wear, as stated in the user manual. If you notice any issues, please contact Glacierpro for further assistance. If you have any other questions or concerns, feel free to ask. We\\u0027re here to help!\"\n      },\n      {\n        \"MessageId\": 741,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I have inspected the crampons for signs of damage or wear, and I have not found any issues. I will be reaching out to Glacierpro for further assistance. Thank you.\"\n      },\n      {\n        \"MessageId\": 742,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hello, I\\u0027m glad to hear that you\\u0027ve inspected the crampons and haven\\u0027t found any issues. If you\\u0027re experiencing discomfort while wearing the Arctic Ice Grip Crampons, I recommend reaching out to Glacierpro directly for further assistance. You can contact them at support@glacierpro.com. If you have any other questions or concerns, feel free to ask. We\\u0027re here to help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 343,\n    \"ProductId\": 49,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 149,\n    \"ShortSummary\": \"Inquiring about Summit Hiking Boots waterproof and traction.\",\n    \"LongSummary\": \"Customer interested in Summit Hiking Boots waterproof protection and ultimate traction for tough terrain. Provided detailed information on waterproofing and maintenance. No pending question.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 743,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I\\u0027m interested in the Summit Hiking Boots by TrekMaven. Can you tell me more about the waterproof protection and ultimate traction? I want to make sure they\\u0027re suitable for tough terrain. Thanks!\"\n      },\n      {\n        \"MessageId\": 744,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Summit Hiking Boots by TrekMaven offer excellent waterproof protection to keep your feet dry and comfortable, even in tough terrain. They are designed with waterproof and breathable materials to prevent moisture from getting in while still allowing sweat to escape. Additionally, you can use a waterproofing treatment specifically designed for these boots to maintain their waterproof capabilities and overall durability. According to the user manual, the boots should be stored in a cool, dry place away from direct sunlight and stuffed with newspaper to help maintain their shape and absorb any moisture. If you have any more questions or need further assistance, feel free to ask!\"\n      },\n      {\n        \"MessageId\": 745,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thanks for the information! I appreciate your help.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 344,\n    \"ProductId\": 144,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 229,\n    \"ShortSummary\": \"ProLite Climbing Harness gear loops issue\",\n    \"LongSummary\": \"Customer Aiden Smith is having issues with gear loops on ProLite Climbing Harness. Tried securing gear again, still not working. Needs further assistance troubleshooting the issue.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 746,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, the gear loops on my ProLite Climbing Harness are not holding my equipment securely. Can you help me figure out what\\u0027s going on? Thanks!\"\n      },\n      {\n        \"MessageId\": 747,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The ProLite Climbing Harness features gear loops for convenient storage of climbing equipment. To secure your gear, simply attach them to the gear loops using the designated clips or loops. Make sure that the gear is properly attached and will not interfere with your movement during the climb. If you have further questions or need assistance, feel free to reach out to us. AdventureWorks Support\"\n      },\n      {\n        \"MessageId\": 748,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Tried securing gear again, still not working. What next?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 345,\n    \"ProductId\": 97,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 8,\n    \"ShortSummary\": \"Cleaning and Lubricating Inquiry\",\n    \"LongSummary\": \"Customer needs guidance on cleaning and lubricating Wanderer Multi-Tool Keychain. No specific details provided. Next agent should provide step-by-step instructions on cleaning and lubricating the tool for customer\\u0027s adventures.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 749,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Wanderer Multi-Tool Keychain from NomadGear and I\\u0027m having trouble figuring out how to properly clean and maintain it. I want to make sure I keep it in top-notch condition for all my adventures. Can you provide some guidance on the best way to clean and lubricate the tool? Thank you so much for your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 346,\n    \"ProductId\": 50,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 230,\n    \"ShortSummary\": \"Hydration system cleaning query\",\n    \"LongSummary\": \"Customer concerned about cleaning instructions, seeking alternative solutions. Pending response on specific cleaning solutions suited to product materials.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 750,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Thirsttrek HydroPack Hydration System and I have a concern about the cleaning and maintenance instructions provided. I\\u0027m aware of the importance of regularly cleaning the reservoir and hose to ensure optimal performance and hygiene, but I believe the instructions may not be sufficient. I have extensive knowledge about the impact of different cleaning agents on hydration system materials and would like to discuss the potential use of alternative cleaning solutions that may better suit the materials used in this specific product. I\\u0027d appreciate any additional information or guidance you can provide on this matter. Thank you.\"\n      },\n      {\n        \"MessageId\": 751,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, it is important to clean your Thirsttrek HydroPack Hydration System regularly to ensure the drinking valve and hose are free from debris and bacteria. Please refer to the \\u0027Cleaning and Maintenance\\u0027 section in the user manual for detailed instructions on how to properly clean and maintain your hydration system.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 347,\n    \"ProductId\": 139,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 231,\n    \"ShortSummary\": \"SmartCyclo GPS Bike Computer Navigation Inquiry\",\n    \"LongSummary\": \"Customer interested in SmartCyclo GPS Bike Computer navigation features. Requesting more info. Pending response on specific navigation features and functionalities.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 752,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi, I\\u0027m interested in the SmartCyclo GPS Bike Computer. Can you tell me more about the navigation features? Thanks.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 348,\n    \"ProductId\": 123,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 232,\n    \"ShortSummary\": \"SolarCopy 3000 malfunction\",\n    \"LongSummary\": \"Customer demands solution for SolarCopy 3000 not working properly, wants immediate resolution. Assistant recommends advanced diagnostic tests and environmental monitoring per product manual.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 753,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I demand to know why my SolarCopy 3000 is not working properly! I spent a lot of money on this product and I expect it to perform as described. I haven\\u0027t even had it for long and it\\u0027s already acting up. I want a solution to this problem immediately!\"\n      },\n      {\n        \"MessageId\": 754,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Based on the product manual, I recommend performing advanced diagnostic tests and monitoring the environmental conditions, such as temperature, humidity, and sunlight levels, as per the Nature\\u0027s Photocopier SolarCopy 3000 industry standard IS3000. If abnormalities are found, please contact Nature\\u0027s Photocopier technical support for further guidance and potential servicing of the SolarCopy 3000.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 349,\n    \"ProductId\": 51,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 233,\n    \"ShortSummary\": \"Inquiry about Survival Pro Multi-Tool versatility\",\n    \"LongSummary\": \"Customer inquiring about versatility of Survival Pro Multi-Tool. Wants insight on its ability to handle outdoor emergency situations. Response with details on tool\\u0027s capabilities needed.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 755,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! I\\u0027m looking at the Survival Pro Multi-Tool from Resilience Gear and I\\u0027m wondering if it\\u0027s truly as versatile as it claims to be. I mean, with a knife, saw, and fire starter, it sounds like the ultimate survival tool! Can it really handle all those outdoor emergency situations? Any insight would be super helpful. Thanks!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 350,\n    \"ProductId\": 34,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 32,\n    \"ShortSummary\": \"Trouble with powering on WildView HD Trail Camera\",\n    \"LongSummary\": \"Customer Evelyn Chang is having trouble powering on the WildView HD Trail Camera. She has checked the batteries and setup process but still needs advice on what might be wrong. Next support agent should provide troubleshooting steps and ask if the camera has any LED indicators for power status.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 761,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the WildView HD Trail Camera and I\\u0027m having trouble getting it to power on. I\\u0027ve checked the batteries and they seem to be inserted correctly, but still no luck. I\\u0027m worried I might have missed something simple in the setup process. Any advice on what I might be doing wrong? Thanks for your help.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 351,\n    \"ProductId\": 128,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 190,\n    \"ShortSummary\": \"Inquiry about using AquaBottle Pro for hot soup\",\n    \"LongSummary\": \"Customer inquired about using AquaBottle Pro for hot soup, and was informed it\\u0027s meant for cold beverages only. No pending questions. Next agent should ensure customer is satisfied with the response.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 762,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the AquaBottle Pro from AquaNest and I\\u0027m considering using it to store hot soup for my lunch. I think the insulated feature will keep it warm, and it\\u0027s so convenient to carry in my backpack. I just wanted to make sure this is a suitable use for the bottle, and if there are any special instructions for using it with hot liquids. Thank you for your help!\"\n      },\n      {\n        \"MessageId\": 763,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The AquaBottle Pro is designed to keep beverages cold and is not intended for hot liquids. It is best used for cold water, sports drinks, or other chilled beverages. If you have any other questions or need further assistance, feel free to ask!\"\n      },\n      {\n        \"MessageId\": 764,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information. I appreciate your help. I will stick to using the AquaBottle Pro for cold beverages as intended. If I have any other questions in the future, I will be sure to reach out. Have a great day!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 352,\n    \"ProductId\": 50,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 235,\n    \"ShortSummary\": \"Inquiry about Thirsttrek Hydration System functionality\",\n    \"LongSummary\": \"Customer inquired about Thirsttrek HydroPack Hydration System\\u0027s functionality and maintenance. Assistant provided details and cleaning instructions. Customer expressed satisfaction and excitement for upcoming adventure.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 765,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! Just wanted to double-check that the Thirsttrek HydroPack Hydration System is as awesome as it sounds. I\\u0027m super excited to take it on my next hiking trip and want to make sure it\\u0027s going to keep me hydrated for the long haul. Can you reassure me that this baby is going to work like a charm? Thanks a bunch!\"\n      },\n      {\n        \"MessageId\": 766,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Thirsttrek HydroPack Hydration System is a high-capacity hydration system designed to keep you hydrated during long outdoor activities. The system features a 3L water reservoir, allowing for hands-free drinking and easy refill, ensuring long-lasting hydration during your adventures. Additionally, it is important to clean the system regularly to ensure the drinking valve and hose are free from debris and bacteria. Refer to the \\u0022Cleaning and Maintenance\\u0022 section in the user manual for detailed instructions on how to properly clean and maintain your hydration system.\"\n      },\n      {\n        \"MessageId\": 767,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thanks for the info! I\\u0027m glad to hear that the Thirsttrek HydroPack Hydration System is up for the challenge. I\\u0027ll definitely make sure to keep it clean as per the instructions in the user manual. Can\\u0027t wait to take it out on my next adventure! You\\u0027ve been super helpful, I really appreciate it!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 353,\n    \"ProductId\": 149,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 8,\n    \"ShortSummary\": \"Flow Rate Calibration Query for AquaFlow Pro\",\n    \"LongSummary\": \"Customer Evelyn Park inquired about the necessity of flow rate calibration for regular use of AquaFlow Pro. After receiving confirmation, customer performed calibration and product is now performing as specified. Next agent should confirm if any further assistance is needed.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 768,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the AquaFlow Pro hydration system from Thirsttrek and have been enjoying using it on my outdoor adventures. I just wanted to double-check if the flow rate calibration process described in the manual is necessary for regular use, or if the product is expected to perform as specified out of the box. I want to ensure that I am getting the best performance from the product. Your assistance and guidance would be greatly appreciated. Thank you.\"\n      },\n      {\n        \"MessageId\": 769,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the AquaFlow Pro\\u0027s easy-flow bite valve requires flow rate calibration before each use to ensure optimal performance.\"\n      },\n      {\n        \"MessageId\": 770,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information. I have performed the flow rate calibration as per the manual, and the product is indeed performing as specified. I appreciate your prompt assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 354,\n    \"ProductId\": 189,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 236,\n    \"ShortSummary\": \"Survivor Kit 2000 Multi-Tool Assistance\",\n    \"LongSummary\": \"Customer needs help with using the multi-tool in Survivor Kit 2000. Customer has read the manual but is still confused. Walk through on using multi-tool needed.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 771,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there, Rescue Mate team! I recently purchased the Survivor Kit 2000 and I am so excited to take it on my next outdoor adventure. But I\\u0027m having a little trouble figuring out how to use the multi-tool properly. I\\u0027ve read the manual, but I\\u0027m still a bit confused. Can you walk me through it? Thanks a bunch!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 355,\n    \"ProductId\": 109,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 237,\n    \"ShortSummary\": \"Inquiry about XtremeGear 5000 Mountain Biking Kit details\",\n    \"LongSummary\": \"Customer inquired about technical details and warranty process for XtremeGear 5000 Mountain Biking Kit. Assistant provided information on protective gear and warranty claim process. Customer acknowledged the information and expressed readiness to contact for further inquiries.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 772,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello TrailTech team, I am considering purchasing the XtremeGear 5000 Mountain Biking Kit and I have some technical questions regarding its suitability for my biking needs. Specifically, I would like to know more about the advanced protective gear mentioned in the product description. Can you provide detailed information about the materials used, impact resistance, and overall durability of the protective gear? Additionally, I am interested in understanding the warranty claim process, especially regarding the resolution of warranty claims and the possibility of repair or replacement. Please note that I am well-versed in technical specifications and would appreciate detailed and accurate information to make an informed decision. Thank you for your assistance.\"\n      },\n      {\n        \"MessageId\": 773,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The XtremeGear 5000 Mountain Biking Kit includes top-tier protective gear, such as a durable TrailTech-branded helmet with adjustable straps and comfortable padding, as well as elbow and knee pads designed for extreme mountain biking. The kit is covered by a limited warranty for a period of 1 year from the date of purchase. To make a warranty claim, please contact our customer service team at 1-800-TrailTech or email us at support@trailtech.com. You will need to provide proof of purchase and a detailed description of the issue.\"\n      },\n      {\n        \"MessageId\": 774,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information provided. I appreciate the details on the protective gear included in the XtremeGear 5000 Mountain Biking Kit. I will make sure to keep the proof of purchase and contact details handy in case I need to make a warranty claim. I will reach out if I have any further technical inquiries. Thank you for your assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 356,\n    \"ProductId\": 132,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 238,\n    \"ShortSummary\": \"Performance concerns for AnglerPro 5000 fishing rod\",\n    \"LongSummary\": \"Customer Derek Hughes reported issues with AnglerPro 5000\\u0027s casting precision and durability despite meticulous maintenance. Seeks reassurance and advice on addressing issues. Prompt attention requested.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 775,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the AnglerPro 5000 fishing rod from Fish Tech and I have some concerns about its performance. I am an experienced angler and have always been meticulous about the maintenance of my fishing equipment. However, despite following all the proper storage guidelines outlined in the manual, I have noticed some issues with the rod\\u0027s casting precision and overall durability. I was attracted to this product specifically for its expertly crafted design and comfortable grip for all-day use, but I am not experiencing the expected performance. I would appreciate some reassurance that the product is behaving as expected and any advice on how to address these issues. Your prompt attention to this matter is greatly appreciated. Thank you.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 357,\n    \"ProductId\": 12,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 8,\n    \"ShortSummary\": \"Inquiry about TrailGPS 5000 maintenance and diagnostics\",\n    \"LongSummary\": \"Customer inquires about maintenance and diagnostics for TrailGPS 5000 to share with their customers. Assistant replies with details about the importance of regular maintenance, pre-use diagnostics, and troubleshooting procedures from the user manual. Pending the response from the customer on whether the information provided is sufficient.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 776,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I am a retailer who stocks TrailTech\\u0027s TrailGPS 5000. We have had a few customers inquire about the maintenance and diagnostics procedures for the device. Could you provide us with some detailed information that we can share with our customers? We want to ensure that they have the best experience with the product and understand how to maintain and troubleshoot any potential issues. Thank you for your assistance.\"\n      },\n      {\n        \"MessageId\": 777,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the TrailGPS 5000 User Manual, regular maintenance is crucial for optimal performance and longevity. Diagnostics should be performed using specialized equipment before and after each use to ensure accurate readings and safety. Additionally, it is advised to follow the pre-use diagnostics outlined in the manual. For troubleshooting procedures and warranty details, please refer to the User Manual.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 358,\n    \"ProductId\": 77,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 239,\n    \"ShortSummary\": \"Troubleshooting Power Button Issue\",\n    \"LongSummary\": \"Customer had trouble with Solar Charger 3000X power button. Assistant advised on charging procedure. Customer successfully resolved issue by fully charging with USB cable. No further support needed.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 778,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the Solar Charger 3000X from Ecovolt and I\\u0027m having some trouble with it. I\\u0027m not sure if I\\u0027m doing something wrong, but the power button doesn\\u0027t seem to be working properly. I\\u0027ve tried putting it in direct sunlight and also checked the battery level, but it\\u0027s still not responding. I feel like I must be missing something obvious. Can you please help me troubleshoot this? I really want to make sure I can rely on this charger during my outdoor adventures. Thanks so much for your assistance!\"\n      },\n      {\n        \"MessageId\": 779,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"It\\u0027s important to make sure that the Solar Charger 3000X is in direct sunlight when using the power button. Also, be sure to fully charge the charger using the included USB cable before use. If you continue to experience issues, please refer to the troubleshooting section of the manual or contact our customer support team for further assistance.\"\n      },\n      {\n        \"MessageId\": 780,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I feel so silly! I didn\\u0027t realize the charger needed to be fully charged using the USB cable before using the power button. I tried that and it worked perfectly! Thank you so much for your help, I really appreciate it!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 359,\n    \"ProductId\": 22,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 240,\n    \"ShortSummary\": \"Summit 45L backpack hipbelt pockets issue\",\n    \"LongSummary\": \"Customer is frustrated with hipbelt pockets not fitting phone and GPS. Customer demands refund or replacement. Agent provided information on alternative storage and return policy.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 781,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am absolutely furious with the design of the hipbelt pockets on the Summit 45L backpack! It\\u0027s impossible to fit my phone and GPS device in there without them getting squished. I can\\u0027t believe I spent so much money on a backpack that can\\u0027t even hold basic essentials properly. I demand a refund or a replacement immediately. This is unacceptable!\"\n      },\n      {\n        \"MessageId\": 782,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the product manual, the hipbelt pockets on the Summit 45L backpack are designed for quick access to items during outdoor adventures and are made of stretchy, durable fabric. They are not intended for holding larger items like phones or GPS devices. For additional storage, the backpack features internal organization options such as a hydration sleeve, zippered pockets, and gear loops. We recommend using these internal pockets for your phone and GPS device.\"\n      },\n      {\n        \"MessageId\": 783,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I don\\u0027t care what the product manual says! I bought this backpack specifically for the hipbelt pockets to hold my phone and GPS device. It\\u0027s ridiculous that I have to use other pockets for them when the hipbelt pockets should be able to accommodate these items. I demand a refund or a replacement immediately!\"\n      },\n      {\n        \"MessageId\": 784,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I understand your frustration with the hipbelt pockets. The Summit 45L backpack is designed to accommodate larger gear items in the main compartment, and the side pockets are meant for quick access to smaller items during outdoor adventures. The manufacturer recommends using the internal organization options, such as the hydration sleeve, zippered pockets, and gear loops, for additional storage. Additionally, the return policy for unused products allows returns within 30 days. If you would like to initiate a return, you can do so at https://northernmountains.example.com/support/returns. If you have any further questions or need assistance with the return process, please let us know.\"\n      },\n      {\n        \"MessageId\": 785,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"This is ridiculous! I bought this backpack specifically for the hipbelt pockets to hold my phone and GPS device. I shouldn\\u0027t have to use other pockets for them when the hipbelt pockets should be able to accommodate these items. I demand a refund or a replacement immediately!\"\n      },\n      {\n        \"MessageId\": 786,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I understand your frustration with the hipbelt pockets. The Summit 45L backpack is designed to accommodate larger gear items in the main compartment, and the side pockets are meant for quick access to smaller items during outdoor adventures. The manufacturer recommends using the internal organization options, such as the hydration sleeve, zippered pockets, and gear loops, for additional storage. According to the product manual, the side pockets and the main compartment are the appropriate areas for different storage needs. As per our return policy, unused products can be returned within 30 days. If you would like to initiate a return, you can do so at https://northernmountains.example.com/support/returns. If you have any further questions or need assistance with the return process, please let us know.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 360,\n    \"ProductId\": 4,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 242,\n    \"ShortSummary\": \"Missing items from survival kit, demanding replacement\",\n    \"LongSummary\": \"Customer has missing items from emergency survival kit and demands replacement without hassle. Customer satisfaction is low. Next support agent should provide a convenient solution for replacing missing items.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 789,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I can\\u0027t believe this so-called \\u0027survival kit\\u0027 doesn\\u0027t even include a proper emergency shelter. What kind of survival kit is this if it can\\u0027t even keep me safe and dry in the wilderness? I demand answers and a solution to this blatant oversight!\"\n      },\n      {\n        \"MessageId\": 790,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the emergency survival kit includes an emergency tent and blanket designed to provide temporary shelter and protection from the elements. It is important to prioritize safety and find a suitable location for setting up the tent. If there are any issues with the tent, they should be addressed promptly to ensure its integrity. As for the return policy and manufacturer contact details, the manual does not provide specific information about these. You may consider reaching out to the manufacturer directly for further assistance.\"\n      },\n      {\n        \"MessageId\": 791,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I already checked the manual and I do see that it mentions the emergency tent and blanket, but they were missing from the kit I received. I need to know how to get these missing items replaced or if there is a way to expedite the process. This is unacceptable and I expect a swift resolution.\"\n      },\n      {\n        \"MessageId\": 792,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I understand your frustration and the urgency of the situation. It seems that the manual does not provide specific information about the replacement process for missing items. Since the manual does not contain manufacturer contact details or return policy specifics, I recommend reaching out to the manufacturer directly for assistance with expedited replacement of the missing items. I apologize for any inconvenience this may have caused. If you need further assistance, please feel free to ask.\"\n      },\n      {\n        \"MessageId\": 793,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I shouldn\\u0027t have to go through the hassle of reaching out to the manufacturer for missing items. This is your responsibility as the seller. I demand a replacement for the missing items to be sent to me immediately!\"\n      },\n      {\n        \"MessageId\": 794,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I apologize for the inconvenience. According to the manual, there is no specific information provided about the replacement process for missing items. However, you can initiate a return for the entire kit and we will expedite the process for you. Please visit https://northernmountains.example.com/support/returns to start the return process. Once the return is initiated, we will ensure that the missing items are sent to you or provide a refund if you prefer. We apologize for any inconvenience this may have caused.\"\n      },\n      {\n        \"MessageId\": 795,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"This is ridiculous! I shouldn\\u0027t have to go through the hassle of returning the entire kit just to get the missing items replaced. I demand a more convenient solution to this problem!\"\n      },\n      {\n        \"MessageId\": 796,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I apologize for the inconvenience. According to the manual, there is no specific information provided about the replacement process for missing items. As an alternative, you may consider initiating a return for the entire kit and we will expedite the process for you. Please visit [https://northernmountains.example.com/support/returns](https://northernmountains.example.com/support/returns) to start the return process. Once the return is initiated, we will ensure that the missing items are sent to you or provide a refund if you prefer. We apologize for any inconvenience this may have caused.\"\n      },\n      {\n        \"MessageId\": 797,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"This is absolutely unacceptable! I demand a proper resolution to this issue without having to go through the hassle of returning the entire kit. I expect the missing items to be sent to me immediately without any further delay.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 361,\n    \"ProductId\": 135,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 243,\n    \"ShortSummary\": \"Night Vision Setup Issue\",\n    \"LongSummary\": \"Customer frustrated with setting up night vision on WideView 360 trail camera. Manual not helpful. Requests step-by-step phone assistance or refund.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 798,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am so frustrated with this WideView 360 trail camera! I can\\u0027t figure out how to set up the night vision feature. The manual is no help at all. I spent good money on this and I expect it to work properly. I need someone to explain to me step by step how to make this work, or else I want a refund!\"\n      },\n      {\n        \"MessageId\": 799,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The WideView 360 trail camera is equipped with advanced night vision technology, ensuring clear and detailed images even in low-light or nighttime conditions. The night vision features of the camera are in line with the technical specifications provided in the manual. If you require further assistance with setting up the night vision feature, please refer to the \\u0027Installation and Setup\\u0027 section of the user manual.\"\n      },\n      {\n        \"MessageId\": 800,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I already tried following the \\u0027Installation and Setup\\u0027 section of the user manual, but it still doesn\\u0027t work! This is so frustrating! I need someone to walk me through this step by step over the phone or I want a refund!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 362,\n    \"ProductId\": 92,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 244,\n    \"ShortSummary\": \"Taste and Pump Issues with AquaPure Water Filter\",\n    \"LongSummary\": \"Customer experiencing taste and pump issues with AquaPure Portable Water Filter, dissatisfied with customer service. Requesting replacement or refund. Needs further assistance or resolution.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 801,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I can\\u0027t believe I\\u0027m having so much trouble with this AquaPure Portable Water Filter. I tried flushing the filter cartridge like the manual said, but the weird taste in the water is still there. And don\\u0027t even get me started on the pump malfunction! I followed all the troubleshooting steps but it\\u0027s still not working properly. This is ridiculous. I demand a replacement or a refund. And don\\u0027t tell me to contact customer support, I\\u0027ve already tried everything in the manual!\"\n      },\n      {\n        \"MessageId\": 802,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, if you encounter any issues with your AquaPure Portable Water Filter during the warranty period, you\\u0027re urged to reach out to the dedicated customer service team immediately. This may be the best course of action to address the issues you\\u0027re facing with the water filter. You can find the contact details for customer service in the user manual as well.\"\n      },\n      {\n        \"MessageId\": 803,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I already tried contacting customer service as you suggested, but they were not helpful at all. They just gave me the runaround and didn\\u0027t offer any real solutions. This is ridiculous! I demand a replacement or a refund immediately.\"\n      },\n      {\n        \"MessageId\": 804,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We apologize for the inconvenience you\\u0027ve experienced with the AquaPure Portable Water Filter. According to the manual, if you encounter any issues with your AquaPure Portable Water Filter during the warranty period, you\\u0027re urged to reach out to the dedicated customer service team immediately. This may be the best course of action to address the issues you\\u0027re facing with the water filter. You can find the contact details for customer service in the user manual as well. If you have already contacted customer service and did not receive the assistance you needed, we recommend reaching out to them again and informing them about the troubleshooting steps you\\u0027ve taken, and request for a replacement or refund if necessary.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 363,\n    \"ProductId\": 159,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 245,\n    \"ShortSummary\": \"Rugged Solar Power Bank not charging\",\n    \"LongSummary\": \"Customer\\u0027s Rugged Solar Power Bank not charging despite troubleshooting steps and trying different power sources. Customer wants to explore warranty and repair options.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Returns\",\n    \"Messages\": [\n      {\n        \"MessageId\": 805,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Power bank not charging my device, need help\"\n      },\n      {\n        \"MessageId\": 806,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"If your Rugged Solar Power Bank is not charging, please follow these troubleshooting steps:\\n1. Check Solar Panel Placement: Ensure that the solar panels are facing direct sunlight and there are no obstructions blocking the panels.\\n2. Verify Connection: Make sure that the charging cable is securely connected to the power bank and the charging source.\\n3. Inspect Cables: Check the charging cable for any damage or fraying. Replace the cable if it is damaged.\\n4. Change Charging Source: If you are using a solar charger, try charging the power bank using a traditional power source to see if the issue persists. According to the manual, these troubleshooting steps should help resolve the issue.\"\n      },\n      {\n        \"MessageId\": 807,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Tried all the steps, still not charging\"\n      },\n      {\n        \"MessageId\": 808,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"It seems that the power bank may need to be charged from a different power source before attempting to use the solar charging feature. The manual suggests, \\u0022If the power bank has a low battery level, it may not be able to charge. Use a different power source to charge the power bank before using solar charging.\\u0022 If you have not already done so, please try charging the power bank using a traditional power source and then attempt to use the solar charging feature again. If the issue persists, please let us know.\"\n      },\n      {\n        \"MessageId\": 809,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Tried traditional power source, still not working\"\n      },\n      {\n        \"MessageId\": 810,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry to hear that you\\u0027re still experiencing issues with the Rugged Solar Power Bank. According to the manual, if the power bank is not charging, you should ensure that the solar panels are facing direct sunlight and there are no obstructions blocking the panels. Additionally, it\\u0027s recommended to store the power bank in a cool, dry place when not in use to prevent damage from extreme temperatures and moisture. If you\\u0027ve already tried these steps, please let us know if you would like to initiate a return or explore warranty and repair options.\"\n      },\n      {\n        \"MessageId\": 811,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I want to explore warranty and repair options\"\n      },\n      {\n        \"MessageId\": 812,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry, but there is no specific information about warranty and repair options or defective product return policy in the user manual. To explore warranty and repair options, I recommend contacting the manufacturer\\u0027s support team directly. You can find their contact details in the user manual under the support section. If you need further assistance, please let us know.\"\n      },\n      {\n        \"MessageId\": 813,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Contacted manufacturer\\u0027s support team, waiting for response\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 364,\n    \"ProductId\": 70,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 246,\n    \"ShortSummary\": \"Inquiry about Solar Panel Charging Time\",\n    \"LongSummary\": \"Customer inquired about the solar panel charging time. Assistant provided details and confirmed lack of specific charging time. Customer will test solar panel and reach out with further questions if needed.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 814,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I am considering purchasing the Juice Junkie Solar Power Bank 10000mAh and I have a specific technical question regarding its solar panel capability. Can you please provide me with information on how long it takes to fully charge the power bank using the built-in solar panel? Thank you.\"\n      },\n      {\n        \"MessageId\": 815,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the solar input current for the Juice Junkie Solar Power Bank 10000mAh is 200mA, providing an alternative charging method for outdoor use. It is recommended to ensure a well-lit testing environment to allow for solar panel exposure. The panel features a protective tempered glass cover for durability and long-lasting performance. Unfortunately, the manual does not specify the exact time it takes to fully charge the power bank using the built-in solar panel.\"\n      },\n      {\n        \"MessageId\": 816,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information. I understand that the manual does not specify the exact time it takes to fully charge the power bank using the built-in solar panel. I will proceed with testing the solar panel in a well-lit environment and will reach out if I have any further questions. Thank you for your assistance.\"\n      },\n      {\n        \"MessageId\": 817,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The solar input voltage is 5V and the solar input current is 200mA, providing an alternative charging method for outdoor use. Ensure that the testing environment is well-lit to allow for solar panel exposure. The information in the manual does not specify the exact time it takes to fully charge the power bank using the built-in solar panel. If you have any further questions, feel free to reach out. Thank you for choosing AdventureWorks!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 365,\n    \"ProductId\": 50,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 247,\n    \"ShortSummary\": \"Functionality issues with Thirsttrek HydroPack\",\n    \"LongSummary\": \"Customer Evelyn Chambers is experiencing functionality issues with the Thirsttrek HydroPack. Despite following manual instructions precisely, she is unable to use it. She has knowledge of hydration systems, so the issue is not due to user error. She would appreciate troubleshooting assistance or potential solutions.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 818,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Thirsttrek HydroPack Hydration System and have encountered some issues with its functionality. Despite following the manual instructions precisely, I am unable to get the system to work at all. I have attempted to attach the HydroPack to my body and drink from it while on the move, but to no avail. I have also tried refilling the reservoir and cleaning the system as per the manual\\u0027s guidelines, but still no success. I am extremely knowledgeable about hydration systems and have used similar products in the past without any trouble, so I am confident that the issue is not due to user error. I would greatly appreciate any assistance in troubleshooting this problem or any insights into potential solutions. Thank you.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 366,\n    \"ProductId\": 149,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 248,\n    \"ShortSummary\": \"Product Suitability for Outdoor Use\",\n    \"LongSummary\": \"Customer Evelyn Tan inquires about AquaFlow Pro\\u0027s suitability for rugged terrain and outdoor conditions. Await response from support regarding product specifications.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 819,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi, I recently purchased the AquaFlow Pro hydration system from Thirsttrek and I\\u0027m wondering about its suitability for outdoor activities. Can it withstand rugged terrain and outdoor conditions? Any information would be helpful. Thanks!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 367,\n    \"ProductId\": 126,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 143,\n    \"ShortSummary\": \"Battery Life Inquiry Threatening Refund\",\n    \"LongSummary\": \"Customer needs detailed battery life info for SOS Emergency Beacon before purchase decision. Threatens refund if unsatisfactory response. Pending response required on battery life details.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 820,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I need to know exactly how long the battery life is for the SOS Emergency Beacon before I consider purchasing. I expect a prompt and detailed response as I need this information to make my decision. If I don\\u0027t receive a satisfactory answer, I will be demanding a refund for wasting my time.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 368,\n    \"ProductId\": 84,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 249,\n    \"ShortSummary\": \"Heart Rate Display Issue\",\n    \"LongSummary\": \"Customer reports heart rate not showing on screen. Needs resolution on how to fix this issue.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 821,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Can\\u0027t get heart rate to show on screen. Fix it.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 369,\n    \"ProductId\": 145,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 81,\n    \"ShortSummary\": \"Trouble with Solar Panel Charging\",\n    \"LongSummary\": \"Customer bought Solar Powered Portable Charger. Trouble with charging despite direct sunlight exposure. Need assistance troubleshooting the issue with solar panel charging.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 822,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I just bought the PowerBeam Solar Powered Portable Charger and I\\u0027m having some trouble getting it to work. The solar panel seems to be exposed to direct sunlight, but it\\u0027s still not charging. Can you help me with this?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 370,\n    \"ProductId\": 127,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 64,\n    \"ShortSummary\": \"HydraPack 2.0 Usage Inquiry\",\n    \"LongSummary\": \"Customer is awaiting guidance from Thirsttrek\\u0027s support regarding using HydraPack 2.0 for hot beverages. The customer has acknowledged the limited warranty and will continue to wait for guidance.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 826,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the HydraPack 2.0 and I\\u0027m considering using it to store hot beverages for my morning commute. I love the leak-proof feature and the built-in water filter, so I thought it might work for my coffee. Do you think this is a reasonable use for the product? I\\u0027d appreciate any advice or recommendations on how to use it for this purpose. Thank you.\"\n      },\n      {\n        \"MessageId\": 827,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the HydraPack 2.0 is a state-of-the-art hydration system that has been meticulously engineered to ensure optimal performance and convenience for outdoor enthusiasts. It is equipped with a leak-proof design and made from BPA-free materials, but the manual does not specify if it is suitable for storing hot beverages. I recommend contacting Thirsttrek\\u0027s support for specific guidance on using the HydraPack 2.0 for hot beverages. You can find their contact details in the user manual.\"\n      },\n      {\n        \"MessageId\": 828,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for your prompt response. I have reached out to Thirsttrek\\u0027s support as you suggested and am awaiting their guidance on using the HydraPack 2.0 for hot beverages. I will let you know their recommendations. Thank you for your assistance.\"\n      },\n      {\n        \"MessageId\": 829,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the product manual, the use of hot beverages with the HydraPack 2.0 is not specified. I recommend waiting for guidance from Thirsttrek\\u0027s support regarding the use of hot beverages with the product. Please let me know if you need any further assistance.\"\n      },\n      {\n        \"MessageId\": 830,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I have not yet received any guidance from Thirsttrek\\u0027s support regarding the use of hot beverages with the HydraPack 2.0. I will continue to wait for their response. Thank you for your ongoing assistance.\"\n      },\n      {\n        \"MessageId\": 831,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the product manual, the use of hot beverages with the HydraPack 2.0 is not specified. Additionally, the HydraPack 2.0 comes with a limited warranty of one (1) year from the date of purchase. If you believe that your HydraPack 2.0 is experiencing an issue covered by the warranty, please do not hesitate to contact Thirsttrek\\u0027s customer support team for further assistance.\"\n      },\n      {\n        \"MessageId\": 832,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I appreciate your ongoing assistance. I understand that the product manual does not specify the use of hot beverages with the HydraPack 2.0 and that it comes with a one-year limited warranty. I will continue to wait for guidance from Thirsttrek\\u0027s support regarding the use of hot beverages with the product. Thank you for your help.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 371,\n    \"ProductId\": 186,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 250,\n    \"ShortSummary\": \"Avalanche Pro 3000 troubleshooting and resolution\",\n    \"LongSummary\": \"Customer had issues with the Avalanche Pro 3000 but got help from PowderPeak\\u0027s customer support to fix a battery compartment problem. Customer has requested to close the ticket.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 833,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! Just got my hands on the Avalanche Pro 3000 and I was so excited to try it out on the slopes. But uh-oh, it doesn\\u0027t seem to be working at all! I followed all the safety guidelines from the manual, but still no luck. Can you help me figure out what\\u0027s going on? I really want to make sure I can rely on this gear for my backcountry adventures. Thanks a bunch!\"\n      },\n      {\n        \"MessageId\": 834,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Thank you for reaching out to us about the Avalanche Pro 3000. It seems like you\\u0027ve followed the safety guidelines from the manual, but the gear is still not working. We want to ensure that you have the best experience with the Avalanche Pro 3000. Since the product features advanced technology, we recommend getting in touch with PowderPeak\\u0027s customer support for technical assistance. You can find their contact details in the user manual. If you require further support with returns or repairs, please let us know. We\\u0027re here to help!\"\n      },\n      {\n        \"MessageId\": 835,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! Thanks so much for your help. I reached out to PowderPeak\\u0027s customer support and they were able to walk me through some troubleshooting steps. It turns out there was a small issue with the battery compartment, but they helped me fix it and now the Avalanche Pro 3000 is working perfectly! I really appreciate your quick response and the recommendation to contact customer support. I\\u0027m all set now, so you can go ahead and close the ticket. Thanks again!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 372,\n    \"ProductId\": 18,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 251,\n    \"ShortSummary\": \"Hydration System Issue with Trailblazer 40L Backpack\",\n    \"LongSummary\": \"Customer reports issue with Trailblazer 40L Backpack hydration system. Asks for assistance to figure it out. Need troubleshooting steps or replacement options.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 836,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, I just got the Trailblazer 40L Backpack and the hydration system doesn\\u0027t seem to work. Can you help me figure it out?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 373,\n    \"ProductId\": 109,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 252,\n    \"ShortSummary\": \"Disappointing XtremeGear 5000 Kit\",\n    \"LongSummary\": \"Customer seeks resolution for subpar XtremeGear 5000 Mountain Biking Kit. Requests refund or replacement. Expresses disappointment with product\\u0027s performance and safety features.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 837,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I purchased the XtremeGear 5000 Mountain Biking Kit and have found that it does not meet the high-tech standards promised in the description. The protective gear does not provide the level of safety I expected, and the performance clothing does not deliver the promised comfort and functionality. Additionally, the accessories included in the kit are subpar and do not enhance the biking experience as claimed. I am deeply disappointed and would like to discuss options for a refund or replacement. As an avid mountain biker, I have extensive knowledge of high-quality biking gear and have always prioritized safety and performance. The XtremeGear 5000 kit falls short of my expectations and I am seeking a resolution to this matter.\"\n      },\n      {\n        \"MessageId\": 838,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the XtremeGear 5000 Mountain Biking Kit is designed to provide top-tier protection, comfort, and performance. It includes essential protective gear such as a durable helmet, elbow pads, and knee pads, all designed to withstand the demands of extreme mountain biking. Additionally, the performance clothing is designed to enhance the biking experience with moisture-wicking fabric to keep you dry and comfortable. The kit also features versatile accessories such as a hydration pack, multi-tool, and a rugged phone mount. It is a comprehensive set of gear designed to elevate your performance and safety on the trails.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 374,\n    \"ProductId\": 116,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 253,\n    \"ShortSummary\": \"Inquiry about Tent Materials for Arctic Expedition\",\n    \"LongSummary\": \"Customer is seeking detailed information on the materials used in the tent construction and their suitability for sub-zero temperatures. Next agent should provide specific details on the materials and their performance in extreme conditions.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 839,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Greetings, I am in the process of planning an expedition to the Arctic, and I believe the Ultratent UltraLite 2-Person Backpacking Tent would be the perfect shelter for our team in the extreme conditions. I have carefully considered the package contents and safety information, and I am confident that this tent will withstand the harsh environment. However, I would like to confirm whether the materials used in the tent construction are suitable for sub-zero temperatures and high winds. Your prompt response would be greatly appreciated as we finalize our preparations for this daring adventure. Thank you for your assistance.\"\n      },\n      {\n        \"MessageId\": 840,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Ultratent UltraLite 2-Person Backpacking Tent features a ventilation system to regulate temperature and airflow, and it is designed to be secured with stakes and guy lines to prevent it from being affected by wind or other environmental factors. The manual also advises against the use of harsh chemicals and abrasive cleaners on the tent, and recommends proper storage to ensure longevity and performance.\"\n      },\n      {\n        \"MessageId\": 841,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information regarding the ventilation system and securing methods of the Ultratent UltraLite 2-Person Backpacking Tent. I would like to know specifically about the materials used in the tent construction and their suitability for sub-zero temperatures. Could you provide me with detailed information on this aspect? Your prompt response will greatly assist us in finalizing our expedition preparations.\"\n      },\n      {\n        \"MessageId\": 842,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the UltraLite tent is designed to be secured with stakes and guy lines to prevent it from being affected by wind or other environmental factors. It also recommends proper storage in a cool, dry, and well-ventilated area away from direct sunlight. Unfortunately, I couldn\\u0027t find specific details about the materials used and their suitability for sub-zero temperatures. If you have any further questions or if there\\u0027s anything else I can assist you with, please feel free to ask.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 375,\n    \"ProductId\": 195,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 83,\n    \"ShortSummary\": \"Hydration system setup trouble\",\n    \"LongSummary\": \"Customer is still having trouble with the hydration system despite following instructions. They\\u0027re asking for more detailed steps on how to set it up, so further assistance is needed from the next support agent.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 843,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027m having trouble with the hydration system on my Trekker 30L Backpack. Can you help me figure out how to use it properly? Thanks.\"\n      },\n      {\n        \"MessageId\": 844,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Trekker 30L Backpack features a hydration-compatible design, allowing you to easily access your water while on the go. The internal hydration sleeve keeps your water reservoir secure and easily accessible, allowing you to quench your thirst without having to stop and dig through your pack. Make sure your water reservoir is securely placed in the designated compartment and the drinking tube is easily accessible for on-the-go hydration. If you have any further questions, feel free to ask!\"\n      },\n      {\n        \"MessageId\": 845,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thanks for the information. I\\u0027ll make sure to follow your instructions and see if that helps. If I have any more trouble, I\\u0027ll let you know.\"\n      },\n      {\n        \"MessageId\": 846,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"When setting up your hydration system, make sure your water reservoir is securely placed in the designated compartment and the drinking tube is easily accessible for on-the-go hydration. If you need further assistance, feel free to reach out!\"\n      },\n      {\n        \"MessageId\": 847,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I tried following your instructions, but I\\u0027m still having trouble with the hydration system. The drinking tube doesn\\u0027t seem to be easily accessible for on-the-go hydration. Can you provide more detailed steps on how to properly set it up? Thanks.\"\n      },\n      {\n        \"MessageId\": 848,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I understand you\\u0027ve been having trouble with the hydration system on your Trekker 30L Backpack. According to the product manual, to set up the hydration system, make sure your water reservoir is securely placed in the designated compartment and the drinking tube is easily accessible for on-the-go hydration. If you\\u0027ve already tried this and are still experiencing issues, please let us know so we can assist further.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 376,\n    \"ProductId\": 116,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 8,\n    \"ShortSummary\": \"Inquiry about tent materials, poles, and maintenance\",\n    \"LongSummary\": \"Customer inquires about tent materials, poles, and maintenance. Response provided on materials and maintenance. Pending question on specific poles used.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 849,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I am considering purchasing the UltraLite 2-Person Backpacking Tent for my upcoming outdoor trips. I am particularly interested in the durability of the materials and the ease of setup mentioned in the product description. Can you provide me with more technical details on the materials used, such as the denier rating of the fabric and the type of poles used for the tent? I want to ensure that this tent will meet my requirements for withstanding different weather conditions and terrain. Additionally, I would like to know if there are any specific maintenance recommendations to ensure the longevity of the tent. Your prompt and detailed response will greatly inform my decision on whether to proceed with this purchase. Thank you for your assistance.\"\n      },\n      {\n        \"MessageId\": 850,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The UltraLite 2-Person Backpacking Tent comes with aluminum tent poles for sturdy setup and durability. The fabric denier rating is not specified in the manual. However, it is designed for backpacking through rugged terrain and camping in the wilderness, offering reliable protection from the elements. As for maintenance, be sure to avoid setting up the tent on sharp objects, debris, or slopes with water pooling. Additionally, adhere to local regulations and environmental considerations when selecting your campsite for the tent.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 377,\n    \"ProductId\": 15,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 254,\n    \"ShortSummary\": \"Trouble with LED battery indicator lights\",\n    \"LongSummary\": \"Customer needs help with LED battery indicator lights on AdventurePro 1000. Tried reconnecting charging cable, but no change. Requesting assistance with this specific issue.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 851,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the AdventurePro 1000 power bank from AdventureElec and I\\u0027m having some trouble with it. I\\u0027m embarrassed to say that I can\\u0027t seem to figure out how to get the LED battery indicator lights to display correctly. I\\u0027ve tried reconnecting the charging cable, but it doesn\\u0027t seem to help. I\\u0027m not sure if I\\u0027m doing something wrong, but any assistance you can provide would be greatly appreciated. Thank you!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 378,\n    \"ProductId\": 39,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 255,\n    \"ShortSummary\": \"Customer Inquiry: Waterproof Design\",\n    \"LongSummary\": \"Customer wants technical details about waterproof design for outdoor use. Pending question about construction techniques and materials. Response needed with specific details on waterproofing.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 852,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I am considering purchasing the Shelter Scape Instant Pop-Up Tent and I have a question about the waterproof design. Can you provide me with more technical details about the materials used and the construction techniques that make it reliable in protecting against rain and moisture? I want to ensure that it meets my specific requirements for outdoor use. Thank you for your assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 379,\n    \"ProductId\": 81,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 256,\n    \"ShortSummary\": \"Difficulty adjusting Summit X Climbing Harness\",\n    \"LongSummary\": \"Customer is struggling to adjust Summit X Climbing Harness as per manual. Assistant provided instructions for adjusting the waist belt and leg loops. Customer needs further assistance or clearer instructions.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 853,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027ve been trying to attach the Summit X Climbing Harness as per your manual, but the instructions are as clear as mud! I followed the steps to adjust the waist belt, but it\\u0027s still not secure. This is supposed to be a safe and comfortable harness, but I\\u0027m not feeling it right now. Can you provide better instructions or assistance with this? It\\u0027s frustrating to get a product and not be able to use it properly.\"\n      },\n      {\n        \"MessageId\": 854,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"To adjust the Summit X Climbing Harness, use the reinforced webbing located on the waist belt to tighten or loosen the fit. Additionally, adjust the buckles on the leg loops to ensure a secure and comfortable fit around your thighs. When using the harness, always ensure that it is securely fastened and properly adjusted. Double-check that all buckles are properly threaded and tightened, and that the leg loops and waist belt are in the correct position. If you encounter any issues with the Summit X Climbing Harness or have questions about its use, please contact Rockgrip customer support for assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 380,\n    \"ProductId\": 120,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 258,\n    \"ShortSummary\": \"Warranty Claim Initiated\",\n    \"LongSummary\": \"Customer initiated warranty claim process for ArcticPro Insulated Ski Jacket. No further questions or issues raised. Next agent should monitor claim status.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 858,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I bought the ArcticPro Insulated Ski Jacket and it\\u0027s not working properly. Can you help me with this?\"\n      },\n      {\n        \"MessageId\": 859,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Frost Flare ArcticPro Insulated Ski Jacket is covered by a limited warranty against defects in materials and workmanship for a period of one year from the date of purchase. This warranty is valid only for the original purchaser and does not cover damage caused by misuse, improper care, or normal wear and tear. If you are experiencing issues with the jacket, you may be eligible to make a warranty claim. You can initiate a warranty claim process by contacting us at https://northernmountains.example.com/support/warranty-claims\"\n      },\n      {\n        \"MessageId\": 860,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I initiated the warranty claim process as suggested. Thank you for your help.\"\n      },\n      {\n        \"MessageId\": 861,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Frost Flare ArcticPro Insulated Ski Jacket is covered by a limited warranty against defects in materials and workmanship for a period of one year from the date of purchase. This warranty is valid only for the original purchaser and does not cover damage caused by misuse, improper care, or normal wear and tear. If your warranty claim is approved, Frost Flare will repair or replace the defective product at no cost to you. If your claim is denied, you will be provided with a detailed explanation of the decision. Thank you for initiating the warranty claim process. If you have any further questions or need assistance, feel free to reach out to us.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 381,\n    \"ProductId\": 47,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 259,\n    \"ShortSummary\": \"Broken energy bars return request\",\n    \"LongSummary\": \"Customer is requesting a return for broken Nutritech Protein Plus Energy Bars. Assistance requested for return process. Pending response from support agent.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Returns\",\n    \"Messages\": [\n      {\n        \"MessageId\": 862,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi, I bought the Nutritech Protein Plus Energy Bars, Variety Pack and they seem to have broken. Can you help me with this?\"\n      },\n      {\n        \"MessageId\": 863,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We apologize for the inconvenience. According to the Nutritech Protein Plus Energy Bars, Variety Pack user manual, the energy bars have been specifically designed to provide a convenient and delicious source of nutrition for individuals with active lifestyles. If you believe the bars are defective, you may be eligible for a refund within 1 year of purchase. Please let us know if you would like to proceed with a return or if you need further assistance.\"\n      },\n      {\n        \"MessageId\": 864,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I would like to proceed with a return for the Nutritech Protein Plus Energy Bars. Please let me know how to proceed.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 382,\n    \"ProductId\": 23,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 66,\n    \"ShortSummary\": \"Misaligned zippers resolved by removing obstructions\",\n    \"LongSummary\": \"Customer reported issues with misaligned zippers on the QuickShade Portable Shelter. Advised to check for obstructions in the tracks, which resolved the issue. No further action needed.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 865,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the QuickShade Portable Shelter from EZ Camp and I\\u0027m having some issues with the zippers. They seem to be misaligned and I can\\u0027t get them to zip properly. I\\u0027m really embarrassed because I thought I did something wrong when setting it up. Is there anything I can do to fix this, or do I need to request a replacement? I really love the high-tech design of this shelter and it\\u0027s perfect for my camping trips, so I hope we can figure this out. Thank you for your help.\"\n      },\n      {\n        \"MessageId\": 866,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"It seems that the zippers on the QuickShade Portable Shelter may be misaligned due to obstructions or debris in the zipper tracks. I recommend checking for any dirt or debris in the tracks and clearing it away. If the issue persists, please feel free to contact our customer service team for further assistance with replacing the zipper if necessary.\"\n      },\n      {\n        \"MessageId\": 867,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Oh, thank you for the suggestion! I checked the zipper tracks and found some small twigs and dirt stuck in there. After clearing them out, the zippers are working perfectly now. I can\\u0027t believe I didn\\u0027t think of that myself. Thank you so much for your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 383,\n    \"ProductId\": 169,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 8,\n    \"ShortSummary\": \"Seeking Heat Level Guidance\",\n    \"LongSummary\": \"Customer is pleased with product quality but seeks guidance on recommended heat levels for pots and pans. Next support agent should provide specific heat level recommendations for different types of food.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 868,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Trailblazer Camping Cookware Set and I\\u0027m very pleased with the overall quality and functionality. However, I have a question about the recommended heat levels for the pots and pans. I want to ensure that I am using the appropriate heat levels based on the type of food being cooked, as mentioned in the product description. Could you provide some guidance on this matter? Thank you for your assistance.\"\n      },\n      {\n        \"MessageId\": 869,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"When using the Trailblazer Camping Cookware Set, it\\u0027s important to choose a stable and level surface to place the cookware. Ensure the area is clear of any flammable materials and always use caution when cooking with open flame. This will help you cook safely and enjoy your outdoor culinary adventures to the fullest.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 384,\n    \"ProductId\": 76,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 70,\n    \"ShortSummary\": \"Trouble connecting Wilderness DJ Pro to phone\",\n    \"LongSummary\": \"Customer needs help figuring out how to make Wilderness DJ Pro work with their phone. Specific guidance on phone compatibility and setup required.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 870,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, I can\\u0027t figure out how to make the Wilderness DJ Pro work with my phone. Can you help me out?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 385,\n    \"ProductId\": 56,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 260,\n    \"ShortSummary\": \"Product suitability for rainy and cold conditions inquiry\",\n    \"LongSummary\": \"Elena is considering purchasing the Naptime 5000 Sleeping Bag and wants to know if the water-resistant feature is suitable for rainy conditions and if the insulation provides enough warmth for cold nights. Pending response needed for specific product details.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 871,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I am considering purchasing the Naptime 5000 Sleeping Bag from Slumberpeak for my upcoming camping trip. I would like to know if the water-resistant feature is suitable for use in rainy conditions. Can you also confirm if the insulation provides enough warmth for cold nights? Thank you for your assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 386,\n    \"ProductId\": 96,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 261,\n    \"ShortSummary\": \"Battery Replacement Inquiry\",\n    \"LongSummary\": \"Customer needs more info on recommended battery type and replacement instructions for Solaris 5000. Recommend personalized assistance from Luminartech support.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 872,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"How long does the Solaris 5000 battery last? Need more info.\"\n      },\n      {\n        \"MessageId\": 873,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The user manual provides information on the battery replacement for the Solaris 5000 Outdoor Lantern. It recommends using only the recommended battery type and following the instructions for safe and proper battery replacement. If you need further assistance, please refer to the user manual or contact Luminartech support for more details.\"\n      },\n      {\n        \"MessageId\": 874,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thanks, I\\u0027ll check the user manual. Will let you know if I need more help.\"\n      },\n      {\n        \"MessageId\": 875,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Solaris 5000 Outdoor Lantern is designed with a solar-powered battery and advanced LED technology to provide efficient and reliable outdoor lighting. If the battery needs replacement, it\\u0027s important to use only the recommended battery type and follow the instructions in the user manual for safe and proper replacement.\"\n      },\n      {\n        \"MessageId\": 876,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Checked the user manual, but still need more information on the recommended battery type and replacement instructions.\"\n      },\n      {\n        \"MessageId\": 877,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The user manual states that if the battery in your Solaris 5000 Outdoor Lantern needs to be replaced, use only the recommended battery type specified in the user manual and follow the instructions for safe and proper battery replacement. It also provides instructions for charging the lantern using solar power. If you have any further questions or need assistance, feel free to reach out to Luminartech support.\"\n      },\n      {\n        \"MessageId\": 878,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Still need more info on the recommended battery type and replacement instructions for the Solaris 5000 Outdoor Lantern.\"\n      },\n      {\n        \"MessageId\": 879,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The user manual specifies that if the battery in your Solaris 5000 Outdoor Lantern needs to be replaced, use only the recommended battery type specified in the user manual. Follow the instructions in the manual for safe and proper battery replacement. If you have any further questions or need assistance, feel free to reach out to Luminartech customer support for personalized help.\"\n      },\n      {\n        \"MessageId\": 880,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Still need more info on the recommended battery type and replacement instructions for the Solaris 5000 Outdoor Lantern.\"\n      },\n      {\n        \"MessageId\": 881,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The recommended battery type for the Solaris 5000 Outdoor Lantern is specified in the user manual. It states, \\u0022If the battery in your Solaris 5000 Outdoor Lantern needs to be replaced, use only the recommended battery type specified in the user manual. Follow the instructions in the manual for safe and proper battery replacement.\\u0022 As for warranty and repair options, the product warranty covers defects in material and workmanship for one year from the date of purchase. Any attempt to repair the lantern by unauthorized persons will void the warranty. For personalized assistance, please contact Luminartech customer support. If you have any further questions or need assistance, feel free to reach out to Luminartech customer support for personalized help.\"\n      },\n      {\n        \"MessageId\": 882,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I still need more info on the recommended battery type and replacement instructions for the Solaris 5000 Outdoor Lantern.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 387,\n    \"ProductId\": 49,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 262,\n    \"ShortSummary\": \"Waterproof Capability Inquiry for Summit Hiking Boots\",\n    \"LongSummary\": \"Customer inquires about waterproof capability of Summit Hiking Boots. Agent provides detailed information on how the boots remain waterproof in heavy rain and suggests additional protection for extremely wet conditions. Customer\\u0027s question has been answered, but may need further clarification or reassurance on the boots\\u0027 effectiveness in very wet conditions.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 883,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, do these Summit Hiking Boots really stay waterproof in heavy rain? Need to know before I buy, thanks!\"\n      },\n      {\n        \"MessageId\": 884,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Summit Hiking Boots are designed to utilize breathable yet waterproof material to prevent moisture from getting in while still allowing sweat to escape. The gusseted tongue and properly tightened laces also help keep out rain and snow, and you can consider pairing the boots with waterproof gaiters for extended protection in extremely wet conditions. With Summit Hiking Boots, wet weather won\\u0027t hold you back from exploring the great outdoors!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 388,\n    \"ProductId\": 22,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 64,\n    \"ShortSummary\": \"Guidance on utilizing side pockets and front compartment\",\n    \"LongSummary\": \"Customer purchased a Summit 45L Technical Backpack from Peakpacker and needs guidance on utilizing side pockets and front compartment effectively. Pending question about how to use these features. Next support agent should provide detailed instructions on organizing gear in the compartments.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 885,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Summit 45L Technical Backpack from Peakpacker and I\\u0027m having some trouble organizing my gear in the compartments. I\\u0027m not sure how to best utilize the side pockets and the front compartment. Can you provide me with some guidance on how to effectively use these features? Thank you for your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 389,\n    \"ProductId\": 41,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 263,\n    \"ShortSummary\": \"Inquiry about AquaVenture surf watch for snorkeling\",\n    \"LongSummary\": \"Customer Lila Park inquiring about using AquaVenture surf watch for snorkeling, needs guidance on compatibility for underwater activities. Response required on product specifications and warranty for water use.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 886,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, I just got the AquaVenture surf watch and I\\u0027m thinking of using it for snorkeling. Can you help me with something?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 390,\n    \"ProductId\": 137,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 74,\n    \"ShortSummary\": \"Sticky buttons troubleshooting request\",\n    \"LongSummary\": \"WildBeat Pro DJ Controller buttons sticking, not working right. Customer needs help troubleshooting the issue.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 888,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, my WildBeat Pro DJ Controller\\u0027s buttons are sticking and it\\u0027s not working right. Can you help me out?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 391,\n    \"ProductId\": 59,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 264,\n    \"ShortSummary\": \"Unsatisfactory kayak performance resolution demanded\",\n    \"LongSummary\": \"Customer demands resolution for unsatisfactory kayak performance. Previous guidelines not helpful. Immediate assistance needed or refund requested. Next agent should provide alternative solutions or offer refund options.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 889,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am extremely disappointed with my Explorer 3000 Kayak from Aqua Venture. I cannot believe that I am unable to make it work in the way I expected. I demand immediate assistance to resolve this issue. This product was supposed to be lightweight, stable, and built for performance, but I am not seeing any of that. I expect a prompt response and a resolution to this problem. I may even consider asking for a refund if this issue is not addressed to my satisfaction.\"\n      },\n      {\n        \"MessageId\": 890,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We understand your frustration and want to assist you in resolving this issue. According to the manual, the Aqua Venture paddle that comes with the Explorer 3000 Kayak is specially designed for maximum performance, and it is important to grip the paddle firmly and use a smooth, consistent motion while using it. It is also essential to inspect the kayak for any signs of wear, damage, or defects before each use. Have you followed these guidelines for using the kayak and the paddle? Your feedback will help us assist you further.\"\n      },\n      {\n        \"MessageId\": 891,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I have followed the guidelines for using the kayak and paddle as mentioned in the manual, but I am still not satisfied with the performance. This product is not meeting my expectations at all, and I am still demanding immediate assistance to resolve this issue. I expect a better solution to this problem or else I will proceed with asking for a refund.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 392,\n    \"ProductId\": 102,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 265,\n    \"ShortSummary\": \"In-depth performance and safety inquiry\",\n    \"LongSummary\": \"Customer seeks detailed information on the paddle\\u0027s performance and safety features, including flexural strength, torsional resistance, and fatigue performance. Also inquires about safety standards for personal flotation device (PFD).\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 892,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am a kayaking enthusiast and am interested in the Aqua Venture Voyager Kayak Paddle for its lightweight and adjustable design. However, I need more information on its performance and safety features for optimal use. Specifically, I would like to know about its flexural strength, torsional resistance, and fatigue performance as mentioned in the manual. Can you provide detailed insights into how this paddle ensures user safety and reliability? Additionally, I would appreciate recommendations on the proper use of personal protective equipment, such as the ideal personal flotation device (PFD) and any specific safety standards it should meet. Thank you for your assistance in helping me make an informed decision about the suitability of this product for my kayaking activities.\"\n      },\n      {\n        \"MessageId\": 893,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Aqua Venture Voyager Kayak Paddle is designed with a durable composite material to withstand the rigors of kayaking and provide optimal performance. Additionally, it is essential to use the appropriate personal protective equipment, including a properly fitted personal flotation device (PFD) at all times while on the water.\"\n      },\n      {\n        \"MessageId\": 894,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information on the composite material used in the Aqua Venture Voyager Kayak Paddle. However, I would still like detailed insights into its flexural strength, torsional resistance, and fatigue performance as mentioned in the manual. Additionally, if there are any specific safety standards that the personal flotation device (PFD) should meet, I would appreciate that information as well. Thank you for your continued assistance.\"\n      },\n      {\n        \"MessageId\": 895,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Based on the information from the manual, the Aqua Venture Voyager Kayak Paddle is designed with a durable composite material to withstand the rigors of kayaking and provide optimal performance. The adjustable and lightweight design ensures a comfortable and efficient paddling experience. Additionally, the paddle complies with ISO 12402-5:2006 standard for personal flotation devices, ensuring that it is constructed with buoyant materials. It is important for users to familiarize themselves with these standards and ensure that the paddle is used in accordance with the recommended safety practices. If you have any further questions or need assistance, feel free to ask.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 393,\n    \"ProductId\": 196,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 266,\n    \"ShortSummary\": \"GPS Watch Performance Issue\",\n    \"LongSummary\": \"Customer demands reassurance of built-in maps, real-time location sharing, and GPS calibration. Threatens refund or replacement. Urgent response needed.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 896,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I just purchased the TrailMaster GPS Watch and it\\u0027s not performing as expected. I demand a solution to this problem immediately. I spent a lot of money on this watch and I expect it to work perfectly. I need reassurance that the built-in maps, real-time location sharing, and GPS calibration are functioning properly. If this issue is not resolved, I will be requesting a refund or replacement. I hope to hear back from you soon with a resolution to this matter.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 394,\n    \"ProductId\": 193,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 267,\n    \"ShortSummary\": \"Cake carrier reassurance for unexpected road conditions\",\n    \"LongSummary\": \"Customer wants real-life assurance that the cake carrier will keep cakes intact during unexpected road conditions. Needs practical examples to trust product.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 897,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"So let me get this straight. You\\u0027re telling me that this cake carrier can withstand extreme environmental conditions at high altitudes, has a latching mechanism that meets international standards, and uses industrial-grade foam for maximum thermal protection. But can it really keep my cakes fresh and intact during a bumpy car ride? I\\u0027ve had cake carriers before that claim to be top of the line, but they couldn\\u0027t handle a few potholes. I need some real assurance before I make a purchase.\"\n      },\n      {\n        \"MessageId\": 898,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"It\\u0027s crucial to secure the carrier in a stable position within the transportation vehicle to prevent any unnecessary movement that may impact the cake. Additionally, the carrier has integrated secure latches to fasten the lid and provide an airtight seal during transportation, ensuring the safety of your cakes. According to the manual, the insulation material of the carrier is designed to maintain optimal temperature and pressure conditions, preventing damage to delicate textures and structures of the baked goods. This ensures that your cakes reach their destination in perfect condition, providing reliable protection for a wide range of high-altitude baked goods.\"\n      },\n      {\n        \"MessageId\": 899,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"So basically, you\\u0027re saying that if I follow all the instructions perfectly, my cakes will be safe. But what if I encounter unexpected road conditions or a sudden stop? How can I trust that this carrier will really keep my cakes intact? I need some real-life assurance, not just theoretical solutions.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 395,\n    \"ProductId\": 145,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 114,\n    \"ShortSummary\": \"Charger won\\u0027t turn off after full charge\",\n    \"LongSummary\": \"Charger not turning off after fully charged, exposed to direct sunlight. Assistant recommended contacting manufacturer for return/repair. Pending return initiation.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Returns\",\n    \"Messages\": [\n      {\n        \"MessageId\": 900,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Charger not turning off after fully charged. Help!\"\n      },\n      {\n        \"MessageId\": 901,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"If the issue persists, please discontinue use and allow the charger to cool down before attempting to use it again. If the charger is not fully turning off after being fully charged, please ensure that the solar panel is exposed to direct sunlight and is not covered.\"\n      },\n      {\n        \"MessageId\": 902,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Charger still not turning off after being fully charged. Solar panel is exposed to direct sunlight and not covered.\"\n      },\n      {\n        \"MessageId\": 903,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"If the issue persists, we recommend contacting the manufacturer\\u0027s support for further assistance or to initiate a return or repair. You can find their contact details in the user manual. If you wish to proceed with a return, you can initiate it at the following link: [Returns and Repairs](https://northernmountains.example.com/support/returns)\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 396,\n    \"ProductId\": 76,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 268,\n    \"ShortSummary\": \"Troubleshooting Wilderness DJ Pro\",\n    \"LongSummary\": \"Customer needs help with Wilderness DJ Pro. Assistant provided information on the product\\u0027s portability and durability. Customer still needs technical support.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 904,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027m having trouble with the Wilderness DJ Pro. Can someone help me?\"\n      },\n      {\n        \"MessageId\": 905,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Wilderness DJ Pro is designed with portability and versatility in mind, allowing you to take your DJing setup wherever your adventures may lead. It is equipped with rugged, high-tech components that can withstand the harshest environments, making it the perfect companion for entertaining on the go. If you require further technical support, please refer to the manufacturer\\u0027s support contact details in the user manual.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 397,\n    \"ProductId\": 149,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 269,\n    \"ShortSummary\": \"Confusion about calibration and flow rate accuracy\",\n    \"LongSummary\": \"Customer is confused about calibration process, finds it excessive and wants a simpler way to ensure accurate flow rate. Asks about not following ISO 8537 standard for calibration. Needs clarification on the calibration process and consequences of not following the standard.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 906,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there, I\\u0027ve been using the AquaFlow Pro for a while now and I\\u0027m a bit confused about the calibration process mentioned in the manual. It seems like a hassle to set up a closed loop system and measure the flow rate just to adjust the bite valve. Is there a simpler way to ensure the flow rate is accurate? And what happens if I don\\u0027t follow the ISO 8537 standard for calibration? It all sounds a bit excessive to me. Can you shed some light on this? Thanks.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 398,\n    \"ProductId\": 149,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 64,\n    \"ShortSummary\": \"AquaFlow Pro malfunction despite following replacement instructions\",\n    \"LongSummary\": \"Customer is frustrated with AquaFlow Pro not working despite following manufacturer\\u0027s instruction for replacement. Further assistance is needed for resolving the issue.\",\n    \"CustomerSatisfaction\": null,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 907,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am beyond frustrated with the AquaFlow Pro hydration system from Thirsttrek. I purchased it for my hiking trip and it doesn\\u0027t work at all! The bite valve doesn\\u0027t flow as described, and the straps are so uncomfortable. I need this issue resolved as soon as possible, or I want a refund. This is unacceptable.\"\n      },\n      {\n        \"MessageId\": 908,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We apologize for the inconvenience you\\u0027ve experienced with the AquaFlow Pro hydration system from Thirsttrek. According to the manual, the BPA-free reservoir is designed to ensure the highest standards of water purity and safety. If you believe the product is defective, you may be eligible for a refund within 1 year of purchase. Alternatively, you can initiate a return within 30 days if the product is unused. For further assistance, please refer to the manufacturer\\u0027s support contact details in the manual.\"\n      },\n      {\n        \"MessageId\": 909,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I don\\u0027t care about the BPA-free reservoir or the return policy! I just want a working hydration system for my hiking trip. I\\u0027ve already wasted so much time and money on this product, and I need a solution now!\"\n      },\n      {\n        \"MessageId\": 910,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We understand your frustration and want to help resolve this issue. According to the manual, the AquaFlow Pro hydration system from Thirsttrek is designed with a state-of-the-art BPA-free reservoir, ensuring the highest standards of water purity and safety. However, we want to ensure your complete satisfaction. If you believe the product is defective, you may be eligible for a refund within 1 year of purchase. You can also initiate a return within 30 days if the product is unused. For further assistance, please refer to the manufacturer\\u0027s support contact details in the manual. We\\u0027re here to assist you further if needed.\"\n      },\n      {\n        \"MessageId\": 911,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"This is ridiculous! I don\\u0027t want a refund, I want a working hydration system for my hiking trip. I\\u0027ve already wasted so much time and money on this product. I demand a solution now!\"\n      },\n      {\n        \"MessageId\": 912,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We understand your frustration and want to ensure your complete satisfaction with the AquaFlow Pro hydration system. According to the manual, the BPA-free reservoir ensures the highest standards of water purity and safety. If the bite valve doesn\\u0027t flow as described, it may need to be replaced with a genuine Thirsttrek replacement part, following the manufacturer\\u0027s instructions. For further assistance, please refer to the manufacturer\\u0027s support contact details in the manual.\"\n      },\n      {\n        \"MessageId\": 913,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027ve already followed the manufacturer\\u0027s instructions and replaced the bite valve with a genuine Thirsttrek replacement part, but it still doesn\\u0027t work! This is ridiculous and unacceptable. I demand a working hydration system for my hiking trip now!\"\n      },\n      {\n        \"MessageId\": 914,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We understand your frustration. According to the manual, the bite valve should be replaced with a genuine Thirsttrek replacement part if it shows signs of wear or fails the operational test, following the manufacturer\\u0027s instructions. Additionally, the easy-flow bite valve has been designed for optimal liquid flow dynamics, and there are calibration processes outlined in the manual to measure and verify the flow rate. If you require further assistance, please refer to the manufacturer\\u0027s support contact details in the manual.\"\n      },\n      {\n        \"MessageId\": 915,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027ve already replaced the bite valve with a genuine Thirsttrek replacement part as per the manufacturer\\u0027s instructions, and it still doesn\\u0027t work! This is absolutely infuriating and unacceptable. I demand a working hydration system for my hiking trip now!\"\n      },\n      {\n        \"MessageId\": 916,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Based on the manual, the AquaFlow Pro hydration system is designed with a state-of-the-art BPA-free reservoir, ensuring the highest standards of water purity and safety. The easy-flow bite valve has been designed for optimal liquid flow dynamics, and material integrity testing is imperative before use. If you have already followed the instructions for replacing the bite valve and the system still does not work, please refer to the manufacturer\\u0027s support contact details in the manual for further assistance.\"\n      },\n      {\n        \"MessageId\": 917,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027ve already followed all the instructions and replaced the bite valve with a genuine Thirsttrek replacement part multiple times, and it still doesn\\u0027t work! This is beyond frustrating and completely unacceptable. I demand a working hydration system for my hiking trip now!\"\n      },\n      {\n        \"MessageId\": 918,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the AquaFlow Pro hydration system from Thirsttrek features a state-of-the-art BPA-free reservoir, ensuring the highest standards of water purity and safety. The easy-flow bite valve allows for effortless on-the-go hydration, while the adjustable straps provide a customized and comfortable fit for users of all sizes. Additionally, the manual outlines a calibration process to measure and verify the flow rate of the system. If you have already followed the instructions for replacement and the system still does not work, I recommend referring to the manufacturer\\u0027s support contact details in the manual for further assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 399,\n    \"ProductId\": 54,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 270,\n    \"ShortSummary\": \"Small Goggle Pocket Issue\",\n    \"LongSummary\": \"Customer frustrated with small goggle pocket in AvalanchePro Ski Backpack. Demands immediate solution for scratching expensive goggles.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 919,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am extremely frustrated with the AvalanchePro Ski Backpack from PowderPeak! I purchased it for backcountry skiing, and the dedicated pocket for my goggles is too small to fit them properly. It\\u0027s scratching my expensive goggles every time I use it, and I am not happy about it. This is unacceptable for a product that is supposed to keep my gear safe and organized. I demand a solution to this problem immediately.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 400,\n    \"ProductId\": 75,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 273,\n    \"ShortSummary\": \"Seeking Real-Life Scenarios\",\n    \"LongSummary\": \"Customer seeks specific real-life scenarios of Escapesafe GPS Locator Beacon use in remote areas. Escalation or testimonials requested.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 926,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I need to know if the Escapesafe GPS Locator Beacon can accurately send my GPS location to rescue services in remote areas. I expect this product to work flawlessly in any outdoor emergency situation. If it doesn\\u0027t meet my expectations, I\\u0027ll be expecting a full refund. I need answers before I make a purchase decision.\"\n      },\n      {\n        \"MessageId\": 927,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Escapesafe GPS Locator Beacon provides high accuracy for precise location tracking in remote areas. You can configure the GPS settings to optimize accuracy and battery usage. According to the manual, \\u0022By configuring the GPS settings according to your needs, you can ensure that the Escapesafe GPS Locator Beacon will provide accurate location information while optimizing battery usage.\\u0022\"\n      },\n      {\n        \"MessageId\": 928,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I appreciate the information provided, but I need more assurance that the Escapesafe GPS Locator Beacon will truly work flawlessly in any outdoor emergency situation. Can you provide any customer testimonials or real-life scenarios where this product has been successfully used to send accurate GPS location to rescue services in remote areas? I need to be absolutely certain before making a purchase decision.\"\n      },\n      {\n        \"MessageId\": 929,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Escapesafe GPS Locator Beacon user manual does not provide specific customer testimonials or real-life scenarios. However, it does mention that if the device is found to be defective during the warranty period, Escapesafe will repair or replace it free of charge. This warranty does not cover damage caused by accident, misuse, or unauthorized modification. To claim warranty service, please contact Escapesafe Customer Support as detailed in section 7.2 of the manual.\"\n      },\n      {\n        \"MessageId\": 930,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am not satisfied with the response provided. I specifically requested customer testimonials or real-life scenarios where the Escapesafe GPS Locator Beacon has been successfully used in remote areas to send accurate GPS locations to rescue services. I need this information before I can make a purchase decision. Please provide the requested information or escalate this ticket to a higher level of support.\"\n      },\n      {\n        \"MessageId\": 931,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The user manual does not provide specific customer testimonials or real-life scenarios. However, it does mention that the beacon will continue to transmit your GPS location to rescue services until help has arrived in case of an emergency. It is important to stay in the same location and keep the beacon turned on until help arrives. This information is from the manual\\u0027s section on sending an emergency signal. If you have any further questions or need assistance, please feel free to reach out to Escapesafe Customer Support.\"\n      },\n      {\n        \"MessageId\": 932,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am still not satisfied with the response provided. I need specific customer testimonials or real-life scenarios where the Escapesafe GPS Locator Beacon has been successfully used in remote areas to send accurate GPS locations to rescue services. Please provide the requested information or escalate this ticket to a higher level of support.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 401,\n    \"ProductId\": 9,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 274,\n    \"ShortSummary\": \"Broken AltitudeShield Pro\",\n    \"LongSummary\": \"Customer Kaitlyn Reynolds reports that the AltitudeShield Pro she bought is broken. Requesting assistance to address the issue and repair or replace the product.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 933,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I bought the AltitudeShield Pro and it\\u0027s broken. Please help.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 402,\n    \"ProductId\": 194,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 275,\n    \"ShortSummary\": \"Customer Excited About Using SurvivalPro 3000 for Camping\",\n    \"LongSummary\": \"Customer excited about using SurvivalPro 3000 Kit for camping, asked about compass use and kit maintenance. Assistant provided instructions and tips. Pending question about campfire equipment.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 934,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! Just got my hands on the SurvivalPro 3000 Kit and I\\u0027m so stoked to take it on my camping trip next week. I\\u0027m thinking of using the fire-starting equipment to make s\\u0027mores by the campfire - how fun is that!? Can\\u0027t wait to try out the multi-tool too, it\\u0027s like a Swiss army knife on steroids. This kit is seriously top-notch, thanks Rescuepro! \\uD83C\\uDFD5\\uFE0F\\uD83D\\uDD25\"\n      },\n      {\n        \"MessageId\": 935,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the SurvivalPro 3000 Kit comes equipped with a compass for navigating through the wilderness. To use the compass, hold it flat in your hand. Additionally, it\\u0027s recommended to regularly inspect the kit for any damage to the case or its contents to ensure it is always prepared for use in outdoor emergencies.\"\n      },\n      {\n        \"MessageId\": 936,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! Thanks for the info on the compass and the maintenance tips. I\\u0027ll be sure to give it a go and check the kit for any damage. Can\\u0027t wait to head out on my camping trip with this awesome kit! \\uD83D\\uDE0A\\u26FA\"\n      },\n      {\n        \"MessageId\": 937,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the SurvivalPro 3000 Kit should be regularly inspected for any damage to the case or its contents to ensure it is always prepared for use in outdoor emergencies. It also advises to hold the compass flat in your hand when using it for navigation.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 403,\n    \"ProductId\": 10,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 214,\n    \"ShortSummary\": \"TechBeam 2000 Battery Installation Issue\",\n    \"LongSummary\": \"Customer needs more detailed instructions or troubleshooting for TechBeam 2000 battery installation. Further support needed to resolve the issue.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 938,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi, I recently purchased the TechBeam 2000 and I\\u0027m having some trouble with the battery installation. Can you help me out?\"\n      },\n      {\n        \"MessageId\": 939,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The battery installation process for the TechBeam 2000 is detailed in the user manual. According to the manual, the device requires a specific lithium-ion battery pack for optimal performance. To install the battery, you need to open the battery compartment by sliding the latch located on the bottom of the device. For charging the battery, it\\u0027s important to use only the provided charger. If you have any further questions about the installation or charging process, feel free to ask.\"\n      },\n      {\n        \"MessageId\": 940,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I tried following the steps in the manual, but I\\u0027m still having trouble with the battery installation. Can you provide more detailed instructions or troubleshoot with me?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 404,\n    \"ProductId\": 79,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 276,\n    \"ShortSummary\": \"Customer Concerns About Camera Usage\",\n    \"LongSummary\": \"Customer has concerns about using the Adventure Pro Camera, specifically about disassembly, cleaning, and the non-removable lithium-ion battery. Wants reassurance that the camera is behaving as expected.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 941,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello there! I recently purchased the Adventure Pro Camera from Capture Tech and I just want to make sure that I\\u0027m using it correctly. I want to be extra careful with it because I read that it\\u0027s not designed to be disassembled or cleaned by the user. I also noticed that it has a non-removable lithium-ion battery and I don\\u0027t want to do anything that might damage it. Can you please reassure me that I\\u0027m doing everything right and that the camera is behaving as expected? I really want to make the most of its 4K resolution and advanced image stabilization. Thank you so much for your help!\"\n      },\n      {\n        \"MessageId\": 942,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hello there! Thank you for reaching out to AdventureWorks Support. We\\u0027re here to help you with any questions or concerns you have about using the Adventure Pro Camera from Capture Tech. Based on the information from the manual, it\\u0027s important to note that the Adventure Pro Camera is equipped with advanced image stabilization and boasts an impressive 4K resolution for stunning clarity and detail in your photos and videos. Our dedicated support team is available to provide guidance on using the camera effectively and to assist with any technical issues you may encounter. If you have any specific questions or need assistance with anything else, feel free to let us know. We\\u0027re here to help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 405,\n    \"ProductId\": 178,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 277,\n    \"ShortSummary\": \"Inquiry about palm fat sustainability\",\n    \"LongSummary\": \"Customer inquires about palm fat sourcing and sustainability in PowerBar Pro 2021, expresses disappointment with lack of information. Needs guidance on eco-friendly alternatives.\",\n    \"CustomerSatisfaction\": 3,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 943,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the PowerBar Pro 2021 and I noticed that it contains palm fat. I\\u0027m concerned about the environmental impact of this ingredient, as I thought EcoFuels was all about sustainable nutrition. Can you provide me with more information about the sourcing and sustainability of the palm fat used in this product? I really want to make sure I\\u0027m supporting ethical and environmentally friendly brands. Thank you so much for your help!\"\n      },\n      {\n        \"MessageId\": 944,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, there is no information about the sourcing or sustainability of palm fat in the PowerBar Pro 2021. If you have any further questions, feel free to ask.\"\n      },\n      {\n        \"MessageId\": 945,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Oh, I see. I was really hoping to support a brand that prioritizes sustainability and ethical sourcing. I guess I\\u0027ll have to look into other options. Thank you for your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 406,\n    \"ProductId\": 98,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 8,\n    \"ShortSummary\": \"Inquiry on TrailBlazer GPS Watch suitability for outdoor activities\",\n    \"LongSummary\": \"Customer demands answers on TrailBlazer GPS Watch suitability for trail running and hiking. Expects refund or replacement due to lack of warranty coverage. Urgent response needed.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 946,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I demand to know why the TrailBlazer GPS Watch does not come with any warranty coverage! I purchased this watch specifically for outdoor navigation and now I find out that it\\u0027s not reliable for accurate navigation or tracking? This is unacceptable! I need to know if this watch is suitable for trail running and hiking as advertised. If not, I expect a refund or replacement immediately. I am extremely disappointed with this product and the lack of support from Exploremate. I need answers and I need them now!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 407,\n    \"ProductId\": 100,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 278,\n    \"ShortSummary\": \"Missing Cleaning Instructions for Ridge Runner Hydration Pack\",\n    \"LongSummary\": \"Customer demands clear explanation on how to clean and maintain water reservoir in the Ridge Runner Hydration Pack manual. Threatens request for full refund if not provided.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 947,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I just purchased the Ridge Runner Hydration Pack and I can\\u0027t believe there\\u0027s no mention of how to properly clean the reservoir in the manual! This is unacceptable for a product marketed for outdoor use. I demand a clear explanation on how to clean and maintain the water reservoir, or else I\\u0027ll be asking for a full refund!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 408,\n    \"ProductId\": 132,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 279,\n    \"ShortSummary\": \"AnglerPro 5000 Double Haul Technique Inquiry\",\n    \"LongSummary\": \"Customer seeks advice on optimal line release timing for double haul cast with AnglerPro 5000. Next agent should provide detailed instructions or video demonstration.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 948,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the AnglerPro 5000 fishing rod and I am highly impressed with its roll casting capabilities. The manual mentions the double haul cast technique, which I find particularly intriguing. However, I have a specific question regarding the optimal line release timing for achieving maximum distance and accuracy with this technique. I want to ensure that I am utilizing the full potential of this precision casting tool. Your expertise in this matter would be greatly appreciated. Thank you.\"\n      },\n      {\n        \"MessageId\": 949,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, for long-distance casts using the double haul technique with the AnglerPro 5000, you should begin with a smooth back cast, loading the rod with energy. As you initiate the forward cast, pull the line with your non-dominant hand to add extra power to the cast. Position yourself parallel to the water\\u0027s surface with a slight crouch and sweep the rod forward and slightly upward, releasing the line to achieve the desired distance and accuracy.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 409,\n    \"ProductId\": 125,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 280,\n    \"ShortSummary\": \"MediKit Xpress Solar Panel Compatibility\",\n    \"LongSummary\": \"Customer inquires about compatibility of alternative solar panels with MediKit Xpress. Assistant confirms compatibility as long as panels meet necessary specs.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 950,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I hope you are doing well. I recently purchased the MediKit Xpress from Trailblazer Pharmaceuticals and I must say, I am quite impressed with its compact and portable design. However, I have a question about the optional solar panel mentioned in the manual. Is it possible to use a different solar panel with the kit or does it specifically require the one sold by Trailblazer Pharmaceuticals? I want to make sure I have all the necessary components for my off-grid medical procedures. Thank you for your assistance!\"\n      },\n      {\n        \"MessageId\": 951,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the MediKit Xpress does not require any external power source for its basic functionality. However, users can integrate the optional solar panel (sold separately) to ensure continuous power supply for long-duration off-grid medical procedures. As long as the solar panel meets the necessary specifications, it should be compatible with the kit. For more information on compatible solar panels, please refer to the manual.\"\n      },\n      {\n        \"MessageId\": 952,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for clarifying that the MediKit Xpress does not require an external power source for basic functionality. I will make sure to refer to the manual for more information on compatible solar panels. I appreciate your assistance!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 410,\n    \"ProductId\": 194,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 281,\n    \"ShortSummary\": \"Demand for perfect product, no maintenance or refund\",\n    \"LongSummary\": \"Customer demands product to work perfectly without maintenance, troubleshooting, or refund. Assistant advises using first aid supplies for minor injuries and following troubleshooting steps if needed.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 959,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I just bought the SurvivalPro 3000 Kit and I expect it to work perfectly for my upcoming camping trip. I don\\u0027t care about any maintenance or troubleshooting steps, it should just work when I need it. If it doesn\\u0027t, I demand a full refund!\"\n      },\n      {\n        \"MessageId\": 960,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Based on the information provided in the user manual, the first aid supplies are intended for temporary treatment of minor injuries in emergency situations. If you encounter any issues with the fire-starting equipment or the multi-tool, please follow the troubleshooting steps provided in the manual. If the issue persists, please contact Rescuepro customer support for assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 411,\n    \"ProductId\": 99,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 282,\n    \"ShortSummary\": \"Technical inquiry about support system diagnostics\",\n    \"LongSummary\": \"Customer has a technical question about support system diagnostics in the manual. Assistant provided details on measuring forces, maximum load capacity, and post-use inspections. No pending questions.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 961,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi, I have a question about the Summit 3000 Trekking Backpack. Can you help me with some technical details about the support system diagnostics mentioned in the manual?\"\n      },\n      {\n        \"MessageId\": 962,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the user manual, the support system diagnostics involve measuring the forces exerted on the support system during use with a load cell and data acquisition system. The measured forces are compared with the maximum load capacity of the backpack (30-35 kg). If the measured forces exceed the maximum load capacity, it is recommended to reduce the weight of the backpack or adjust the distribution of the load. Additionally, post-use inspections with specialized scientific equipment are recommended to identify any potential issues that may require maintenance or repairs.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 412,\n    \"ProductId\": 199,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 22,\n    \"ShortSummary\": \"Slow charging despite proper positioning\",\n    \"LongSummary\": \"Customer reports slow charging despite following positioning instructions. Considering return or further assistance.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 963,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I bought the SunShift 100W Solar Charger and it\\u0027s supposed to have fast charging, but it\\u0027s taking forever to charge my devices! I can\\u0027t believe I spent money on this thing. I need reassurance that it\\u0027s actually working as expected, because right now it\\u0027s not living up to its description. I expect a prompt response and a solution to this problem!\"\n      },\n      {\n        \"MessageId\": 964,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The SunShift 100W Solar Charger is designed for fast charging, and it features a high-efficiency solar panel that quickly converts sunlight into electrical power. Please ensure that the solar panels are in direct sunlight and properly positioned, as this can affect the charging speed. Additionally, make sure that the device you are trying to charge is compatible with the SunShift 100W Solar Charger.\"\n      },\n      {\n        \"MessageId\": 965,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027ve made sure that the solar panels are in direct sunlight and properly positioned, and that the device I\\u0027m trying to charge is compatible with the SunShift 100W Solar Charger. But it\\u0027s still taking forever to charge my devices! I\\u0027m not happy with this product at all.\"\n      },\n      {\n        \"MessageId\": 966,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"It\\u0027s important to ensure that the solar charger is in direct sunlight and properly positioned. The charging speed may vary depending on the intensity of sunlight. According to the manual, the SunShift 100W Solar Charger features a high-efficiency solar panel that quickly converts sunlight into electrical power, ensuring fast charging. If you\\u0027re still experiencing issues, please let us know if you would like to pursue a return or have any other questions.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 413,\n    \"ProductId\": 83,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 283,\n    \"ShortSummary\": \"GPS Tracking Issue on SkyRanger Drone\",\n    \"LongSummary\": \"Customer is frustrated that GPS tracking feature is not working on the SkyRanger HD Aerial Drone. They are demanding an immediate fix or a refund. Assistant has provided troubleshooting steps and requested further information if the issue persists.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 967,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I can\\u0027t believe the GPS tracking feature is not working on my SkyRanger HD Aerial Drone! I specifically bought this drone for the GPS tracking and now it\\u0027s a complete waste. I want this issue fixed immediately or I demand a refund!\"\n      },\n      {\n        \"MessageId\": 968,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the SkyRanger HD Aerial Drone is equipped with advanced GPS tracking technology for precise positioning and navigation during flight. It also has a Return to Home function that automatically guides the drone back to its takeoff location in the event of signal loss or low battery. If you are experiencing issues with the GPS tracking feature, we recommend checking the app settings and ensuring that the drone is in an open outdoor area with a clear view of the sky. If the issue persists, please let us know so we can assist you further.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 414,\n    \"ProductId\": 11,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 284,\n    \"ShortSummary\": \"SurvivalMed 3000 not working as advertised\",\n    \"LongSummary\": \"Customer is upset because the SurvivalMed 3000 does not work as advertised. Demands refund or replacement. Specific issues with surgical instruments, medications, and sterilization supplies. Pending response on refund/replacement options.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 969,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I can\\u0027t believe this! I bought the SurvivalMed 3000 thinking it could handle any surgery in the wilderness, but now I find out I can\\u0027t even use the surgical instruments, medications, or sterilization supplies! This is ridiculous! I demand a refund or a replacement that actually works as advertised.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 415,\n    \"ProductId\": 119,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 285,\n    \"ShortSummary\": \"Troubleshooting GloBeam 1000 headlamp\",\n    \"LongSummary\": \"Customer having trouble with GloBeam 1000 headlamp. Unable to turn it on, checked battery. Assistance with troubleshooting needed.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 970,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the GloBeam 1000 High-Powered LED Headlamp and I\\u0027m having trouble getting it to work properly. I\\u0027ve tried to turn it on by pressing the power button, but nothing happens. I\\u0027ve also checked the battery installation, and it seems to be correct. Is there something I\\u0027m missing? I really need it for my evening hikes, and I was looking forward to using the different lighting modes mentioned in the product description. Any help or guidance would be greatly appreciated. Thank you!\"\n      },\n      {\n        \"MessageId\": 971,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"It seems that the headlamp offers three different lighting modes: High Beam, Medium Beam, and Low Beam. To switch between modes, simply press the power button located on the top of the headlamp. If the headlamp does not turn on, it may be a common issue that can be addressed. Let\\u0027s troubleshoot this together. Have you tried pressing and holding the power button for a few seconds to see if the headlamp turns on?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 416,\n    \"ProductId\": 57,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 286,\n    \"ShortSummary\": \"Inquiry about using PowerPort 10000 as power bank for multiple devices\",\n    \"LongSummary\": \"Customer inquires about using PowerPort 10000 as a power bank for multiple devices. Assistant provides detailed instructions and encourages reaching out for further assistance if needed. Customer plans to test and follow up.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 972,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I have a question about the PowerPort 10000 Portable Charger from Charge Mate. Can you help me with some information about using it as a power bank? Thank you.\"\n      },\n      {\n        \"MessageId\": 973,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The PowerPort 10000 Portable Charger from Charge Mate is equipped to charge multiple devices simultaneously. You can connect each device to a separate USB port on the charger using the appropriate cable, and the charger will automatically allocate the proper power output to each device for efficient charging. It is also designed for fast-charging, allowing you to power up your devices quickly and efficiently.\"\n      },\n      {\n        \"MessageId\": 974,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information. I will try using it as a power bank with multiple devices and let you know if I encounter any issues.\"\n      },\n      {\n        \"MessageId\": 975,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, you can use the PowerPort 10000 as a power bank by connecting your device to the charger and pressing the power button to initiate charging. This feature is incredibly useful for backpacking, outdoor photography, or any situation where you need to keep your devices powered up. If you encounter any issues, please feel free to reach out to us for further assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 417,\n    \"ProductId\": 12,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 287,\n    \"ShortSummary\": \"Inaccurate Route Calculations Complaint\",\n    \"LongSummary\": \"Customer demands immediate resolution or refund for inaccurate route calculations with TrailGPS 5000. Unhappy with technical jargon; wants issue fixed without specialized equipment.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 976,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I bought the TrailGPS 5000 for my daily commute to work, but it\\u0027s not giving me accurate route calculations. I demand that this issue is fixed immediately or I want a refund. I shouldn\\u0027t have to deal with this inconvenience when I paid for a high-tech GPS system!\"\n      },\n      {\n        \"MessageId\": 977,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, if the device is experiencing difficulties calculating routes, specialized equipment for advanced diagnostic analysis should be consulted. Additionally, to create a new route, users can navigate to the \\u0022Routes\\u0022 menu and select \\u0022Create New Route\\u0022 to input waypoints and adjust the route as needed.\"\n      },\n      {\n        \"MessageId\": 978,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I shouldn\\u0027t have to deal with this technical jargon! I just want a GPS that works properly without needing specialized equipment. Either fix this issue or give me a refund immediately!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 418,\n    \"ProductId\": 159,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 159,\n    \"ShortSummary\": \"Clarification on Smartphone Charging Capacity\",\n    \"LongSummary\": \"Customer demands clear answer on number of smartphone charges. Assistant recommends contacting manufacturer for specific charging capacity. Next agent should provide specific charging capacity details.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 979,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I expect this Rugged Solar Power Bank to be able to charge my smartphone at least 5 times on a single charge. If it can\\u0027t do that, I want a full refund! I don\\u0027t have time to waste on products that don\\u0027t live up to their claims. This is a crucial feature for me and I need to know before I make a purchase.\"\n      },\n      {\n        \"MessageId\": 980,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The user manual provides information on charging the Rugged Solar Power Bank using solar panels. It mentions optimal charging when placed under direct sunlight. However, it does not specify the exact number of smartphone charges on a single power bank charge. I recommend reaching out to the manufacturer\\u0027s support contact detailed in the user manual for more specific information on charging capacity.\"\n      },\n      {\n        \"MessageId\": 981,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I shouldn\\u0027t have to contact the manufacturer for basic information like this! It\\u0027s the responsibility of Outdoor Pro to provide clear and accurate details about their product. I demand a clear and definite answer on the number of smartphone charges the Rugged Solar Power Bank can provide on a single charge. This is unacceptable!\"\n      },\n      {\n        \"MessageId\": 982,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Rugged Solar Power Bank is equipped with a high-capacity 10000mAh battery, which allows you to charge your devices multiple times before needing to recharge the power bank itself. Unfortunately, the manual does not specify the exact number of smartphone charges on a single power bank charge. I recommend reaching out to the manufacturer\\u0027s support contact detailed in the user manual for more specific information on charging capacity.\"\n      },\n      {\n        \"MessageId\": 983,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"This is unacceptable! I purchased this Rugged Solar Power Bank based on the promise of being able to charge my smartphone multiple times, and now I still don\\u0027t have a clear answer on how many charges I can expect. I demand a clear and definite answer from Outdoor Pro, and I will not accept anything less!\"\n      },\n      {\n        \"MessageId\": 984,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Rugged Solar Power Bank features a shockproof design and solar charging capability, and the solar panels, located on the top of the power bank, absorb sunlight and convert it into energy. It is not specified in the manual the exact number of smartphone charges on a single power bank charge. I recommend reaching out to the manufacturer\\u0027s support contact detailed in the user manual for more specific information on charging capacity.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 419,\n    \"ProductId\": 155,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 288,\n    \"ShortSummary\": \"Inquiry about solar charger performance in overcast conditions\",\n    \"LongSummary\": \"Customer inquiring about Traveltech solar charger\\u0027s performance in overcast conditions. Assistant clarified it can also be charged via USB and advised on storage. Customer satisfied with info, no pending questions.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 985,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! I\\u0027m seriously considering getting the Traveltech Portable Solar Charger for my upcoming hiking trip, but I\\u0027m curious about how well it works in overcast conditions. Will it still be able to charge up my devices even when the sun isn\\u0027t shining brightly? I\\u0027m so excited to have a reliable power source while I\\u0027m out in nature - this solar charger sounds like the perfect solution for my outdoor adventures!\"\n      },\n      {\n        \"MessageId\": 986,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Traveltech Portable Solar Charger is designed to work effectively in direct sunlight. However, if the sun isn\\u0027t shining brightly, you can also charge the solar charger using a USB cable and a power source such as a laptop or wall adapter. When not in use, it\\u0027s important to store the solar charger in a safe place away from extreme temperatures and moisture to ensure its longevity.\"\n      },\n      {\n        \"MessageId\": 987,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Wow, thanks for the quick response! I didn\\u0027t realize I could also charge the solar charger using a USB cable and power source. That\\u0027s so handy to know, I feel even more prepared for my hiking trip now. Thanks a bunch for the helpful info!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 420,\n    \"ProductId\": 103,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 289,\n    \"ShortSummary\": \"Need guidance on using water pouches and purifying tablets\",\n    \"LongSummary\": \"Customer is seeking guidance on using water pouches, water filter, and purifying tablets in the Safetyex Survival Kit 5000. No response yet needed, but clear instructions required for next agent.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 991,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! \\uD83C\\uDF0A I just got my hands on the Safetyex Survival Kit 5000 and I\\u0027m super excited about it! But I\\u0027m a little confused about how to use the water pouches \\uD83E\\uDD64. Can you give me a quick rundown on how to use them? Also, I\\u0027d love to know more about the water filter and purifying tablets - how do I use those in case of an emergency? Thanks a bunch for your help! \\uD83D\\uDEB0\\uD83D\\uDCA6\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 421,\n    \"ProductId\": 170,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 34,\n    \"ShortSummary\": \"AquaFlow Hydration System Flow Issue\",\n    \"LongSummary\": \"Flow problem with AquaFlow System. Bite valve checked, positioned correctly, still inconsistent flow. Customer needs further assistance.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 992,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Flow problem with AquaFlow System. Can\\u0027t figure it out. Help!\"\n      },\n      {\n        \"MessageId\": 993,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"If you encounter flow problems with the AquaFlow Hydration System, follow these steps to troubleshoot the issue:\\n\\n1. **Check the Bite Valve**: Ensure that the Bite Valve is connected securely to the drink tube.\\n2. **Position the Bite Valve**: To use the Bite Valve, position it in front of your mouth with the Hydra Pulse logo facing up.\\n3. **Bite and Sip**: Gently bite down on the valve and sip to release the water flow. Release your bite to stop the flow. If you have followed these troubleshooting steps and continue to experience leakage, please contact Hydra Pulse customer support for further assistance.\"\n      },\n      {\n        \"MessageId\": 994,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Still having flow problem. Bite valve secure and positioned correctly. Still can\\u0027t get water to flow consistently.\"\n      },\n      {\n        \"MessageId\": 995,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"If you have followed the troubleshooting steps and continue to experience flow problems, please contact Hydra Pulse customer support for further assistance. For warranty and returns information, please refer to the user manual or visit https://northernmountains.example.com/support/returns.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 422,\n    \"ProductId\": 126,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 126,\n    \"ShortSummary\": \"Inquiry about battery check indicator LED color discrepancy\",\n    \"LongSummary\": \"Customer inquires about battery check indicator LED color discrepancy, seeks clarification for proper functionality. Requesting assistance to ensure beacon readiness for next adventure.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 996,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the SOS Emergency Beacon from SOS Gear and I\\u0027m very impressed with its features. However, I have a question about the battery check indicator. I noticed that the LED light is flashing blue instead of the expected colors mentioned in the manual. Can you explain why this is happening? I want to make sure that the beacon is functioning properly before I head out on my next adventure. Thank you for your help.\"\n      },\n      {\n        \"MessageId\": 997,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the battery check indicator is designed to show the battery level when the battery check button is pressed. The LED light will indicate the battery status. It\\u0027s important to keep an eye on the battery life to ensure the beacon is always ready for use.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 423,\n    \"ProductId\": 83,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 249,\n    \"ShortSummary\": \"Inquiry about SkyRanger HD GPS tracking\",\n    \"LongSummary\": \"Customer inquires about GPS tracking on SkyRanger HD Aerial Drone. Assistant explains GPS waypoints, Return to Home function, and autonomous navigation. Customer appreciates info and plans to test feature.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 998,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I have a question about the GPS tracking feature on the SkyRanger HD Aerial Drone. Can you explain how it works and how accurate it is? I\\u0027m really interested in using it for precise aerial footage, so I want to make sure it\\u0027s reliable. Thanks!\"\n      },\n      {\n        \"MessageId\": 999,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The SkyRanger HD Aerial Drone is equipped with advanced GPS tracking technology, allowing users to set specific GPS waypoints for the drone to follow during flight. This enables precise positioning and navigation, and also allows for the drone to autonomously navigate a predetermined route and capture footage along the way. In addition, the GPS tracking feature enables the Return to Home function in case of signal loss or low battery, guiding the drone back to its takeoff location for a safe landing.\"\n      },\n      {\n        \"MessageId\": 1000,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information. I appreciate the explanation. I will test out the GPS tracking feature and let you know if I have any further questions. Thanks!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 424,\n    \"ProductId\": 164,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 8,\n    \"ShortSummary\": \"Inquiry about Genuine Replacement Parts\",\n    \"LongSummary\": \"Customer inquired about purchasing genuine replacement parts for Excavator Pro 8000, was directed to MantleMaster customer service for assistance. Pending request for specific information on purchasing genuine replacement parts.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1001,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the MantleMaster Excavator Pro 8000 and I\\u0027m absolutely thrilled with its performance. However, I noticed that the manual emphasizes the importance of using genuine MantleMaster replacement parts and accessories for maintenance and repairs. Could you please provide more information on where I can purchase these authentic parts? I want to ensure that I am using the best components for the upkeep of this incredible excavation tool. Thank you for your assistance!\"\n      },\n      {\n        \"MessageId\": 1002,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Excavator Pro 8000 comes with a 3-year limited warranty. This warranty covers defects in materials and workmanship under normal use. For genuine replacement parts, please contact MantleMaster customer service at 1-800-EXCAVATE. Proof of purchase is required for all warranty claims.\"\n      },\n      {\n        \"MessageId\": 1003,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for providing the information about the warranty and the contact number for MantleMaster customer service. I will be sure to reach out to them with my proof of purchase to inquire about the genuine replacement parts. I appreciate your assistance!\"\n      },\n      {\n        \"MessageId\": 1004,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, for genuine replacement parts, please contact MantleMaster customer service at 1-800-EXCAVATE. Proof of purchase is required for all warranty claims.\"\n      },\n      {\n        \"MessageId\": 1005,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I contacted MantleMaster customer service at 1-800-EXCAVATE with my proof of purchase and they were very helpful in providing me with the information I needed to purchase the genuine replacement parts. Thank you for your assistance in directing me to the right place!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 425,\n    \"ProductId\": 37,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 290,\n    \"ShortSummary\": \"Missing Tools in Outdoor First Aid Kit\",\n    \"LongSummary\": \"Customer is disappointed with missing tools in Outdoor First Aid Kit, requests clarification on misleading marketing and wants a refund. Next agent should address the missing tools and offer a resolution.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1006,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there, I\\u0027m not happy with the Wild Guard Outdoor First Aid Kit. I bought it thinking it would be perfect for fixing my bike on the go, but it doesn\\u0027t have any tools included! How am I supposed to make repairs without a wrench or screwdriver? This kit is seriously lacking in essentials. Can you explain why it\\u0027s marketed as \\u0027comprehensive\\u0027 when it clearly can\\u0027t handle basic bike repairs? I want a refund for this misleading product.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 426,\n    \"ProductId\": 33,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 291,\n    \"ShortSummary\": \"Night Vision Troubleshooting\",\n    \"LongSummary\": \"Customer experiencing issues with night vision on NatureCam 4K Trail Camera. Needs assistance troubleshooting night vision feature.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1007,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Camera not working at night. Need help now.\"\n      },\n      {\n        \"MessageId\": 1008,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The NatureCam 4K Trail Camera is equipped with advanced night vision technology, allowing you to capture stunning wildlife footage even in low-light conditions. To activate the night vision mode, simply press the \\u0022Night Vision\\u0022 button located on the front of the camera. With its built-in night vision feature, you can monitor wildlife 24/7, day or night, without disturbing their natural habitat. Get ready to experience the amazing world of wildlife like never before with the NatureCam 4K Trail Camera!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 427,\n    \"ProductId\": 159,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 8,\n    \"ShortSummary\": \"Trouble with Solar Power Bank\",\n    \"LongSummary\": \"Customer purchased Rugged Solar Power Bank from Outdoor Pro and needs help getting it to work. Assistant provided tips for solar charging and maintenance. Pending response needed on specific troubleshooting steps.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1009,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I just bought the Rugged Solar Power Bank from Outdoor Pro and I\\u0027m having trouble getting it to work. Can you help me?\"\n      },\n      {\n        \"MessageId\": 1010,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Rugged Solar Power Bank from Outdoor Pro is a versatile and durable charging solution for outdoor adventures. It features solar charging capability, a built-in flashlight, and dual USB ports. To charge the power bank, place it under direct sunlight for optimal results. Additionally, make sure to store the power bank in a cool, dry place when not in use and clean the solar panels regularly for efficient solar charging.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 428,\n    \"ProductId\": 174,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 292,\n    \"ShortSummary\": \"Wi-Fi connectivity troubleshooting\",\n    \"LongSummary\": \"Customer unable to connect camera to Wi-Fi despite troubleshooting. Needs help resolving the issue with \\u0027Actionpro\\u0027 app. No response yet.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1011,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I am having difficulty connecting my AdventureX 4K Action Camera to Wi-Fi. I have followed the manual\\u0027s instructions carefully, but the camera is not appearing in the list of available devices on the \\u0027Actionpro\\u0027 app. I have extensive experience with Wi-Fi connectivity and troubleshooting, so I have already tried rebooting both the camera and my smartphone, as well as resetting the Wi-Fi settings on the camera. Despite my efforts, I am still unable to establish a connection. I would greatly appreciate any assistance in resolving this issue. Thank you.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 429,\n    \"ProductId\": 57,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 293,\n    \"ShortSummary\": \"Weatherproof design confusion\",\n    \"LongSummary\": \"Customer is confused about weatherproof design, specifically asking about the difference between withstanding light rain and being waterproof. Wants to know if it can handle heavy rain and seeking clarification on the product description.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1012,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027m considering buying the PowerPort 10000 but I\\u0027m confused about the weatherproof design. It says it can withstand light rain, but then it says it\\u0027s not waterproof. What\\u0027s the difference? Can it handle heavy rain? I don\\u0027t want to buy it and then have it break in the rain. It\\u0027s not very clear in the description.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 430,\n    \"ProductId\": 5,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 295,\n    \"ShortSummary\": \"Frame issue, unable to return; Seeking replacement\",\n    \"LongSummary\": \"Customer experiencing frame issue with hammock, unable to initiate return. Advised to contact Swingnap\\u0027s customer support for warranty claim. Customer insists on replacement from company.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1016,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I can\\u0027t believe this! I just bought the Swingnap Double Hammock with Mosquito Net and it\\u0027s already broken! The frame snapped and now I can\\u0027t use it at all. This is ridiculous, I spent good money on this and now I can\\u0027t even enjoy the great outdoors without bugs like it promised. I want a replacement ASAP!\"\n      },\n      {\n        \"MessageId\": 1017,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We\\u0027re sorry to hear about the issue with your Swingnap Double Hammock with Mosquito Net. Based on the product manual, the built-in mosquito net is designed to provide comfort and protection from insects. To address the issue with the frame, we recommend initiating a return for a replacement. You can begin the return process at https://northernmountains.example.com/support/returns. Please let us know if there\\u0027s anything else we can assist you with.\"\n      },\n      {\n        \"MessageId\": 1018,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I followed the link to initiate the return process for a replacement, but the website keeps giving me an error message and won\\u0027t let me proceed. This is beyond frustrating! I just want a working hammock like I paid for!\"\n      },\n      {\n        \"MessageId\": 1019,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We understand your frustration and apologize for the inconvenience. Based on the product manual, the Swingnap Double Hammock with Mosquito Net is backed by a 2-year warranty, covering manufacturing defects. If you believe the frame issue is due to a manufacturing defect, we recommend contacting Swingnap\\u0027s customer support team for further assistance in evaluating and resolving the issue. You can reach them at the contact details provided in the user manual. We\\u0027re here to support you and ensure you have a positive experience with our products.\"\n      },\n      {\n        \"MessageId\": 1020,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"This is ridiculous! I shouldn\\u0027t have to deal with contacting another customer support team just to get a working hammock. I\\u0027ve already wasted enough time dealing with this issue. I expect the company to take responsibility and provide me with a replacement as soon as possible!\"\n      },\n      {\n        \"MessageId\": 1021,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We understand your frustration and apologize for the inconvenience. The Swingnap Double Hammock with Mosquito Net is backed by a 2-year warranty, covering manufacturing defects. If you believe the issue with the frame is due to a manufacturing defect, please contact Swingnap\\u0027s customer support team for further assistance. You can reach them at 1-800-SWINGNAP or by email at support@swingnap.com. Our team is available to help you with any inquiries or concerns you may have about your hammock. We value your feedback and want to ensure that you have a positive experience with our products.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 431,\n    \"ProductId\": 183,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 296,\n    \"ShortSummary\": \"Inquiry about cookware set temperature limit\",\n    \"LongSummary\": \"Customer is demanding the maximum temperature the cookware set can handle. Assistant provided product details and mentioned that the manual does not specify the maximum temperature. Pending question about the maximum temperature.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1022,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I demand to know the maximum temperature that the Trailblazer Compact Cookware Set can handle without overheating! I expect a prompt and detailed response, as I am considering purchasing this product and need to know its capabilities before making a decision. If I do not receive the information I require, I will take my business elsewhere.\"\n      },\n      {\n        \"MessageId\": 1023,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Trailblazer Compact Cookware Set is a versatile and essential addition to any camping trip. It includes a non-stick frying pan, a durable pot with lid, spatula, and spoon for creating delicious meals in the wilderness. The product manual does not specify the maximum temperature it can handle. If you have any further questions or need assistance, please feel free to ask. Thank you!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 432,\n    \"ProductId\": 29,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 297,\n    \"ShortSummary\": \"SolarBoost Power Bank not charging\",\n    \"LongSummary\": \"SolarBoost Power Bank not charging in direct sunlight. Customer requests replacement/refund.\",\n    \"CustomerSatisfaction\": 3,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1024,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am absolutely frustrated with this SolarBoost Power Bank from Ecovolt. I bought it for extended outdoor use, but it\\u0027s not working at all! I followed the manual\\u0027s instructions and placed it in direct sunlight, but it\\u0027s still not charging. I am so disappointed with this product and need help resolving this issue. If this can\\u0027t be fixed, I\\u0027ll be requesting a replacement or refund.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 433,\n    \"ProductId\": 8,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 298,\n    \"ShortSummary\": \"Malfunctioning Outdoor Admin 5000\",\n    \"LongSummary\": \"Customer Eleanor Morse seeks assistance with malfunctioning Outdoor Admin 5000. She has cared for the device and followed the manual but it still has technical issues. She requests prompt attention for repairs or replacement.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1025,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear TrailFax Customer Support,\\n\\nI recently purchased the Outdoor Admin 5000 and unfortunately, the device has stopped functioning properly. I have taken great care of it and followed all the instructions in the manual, but it seems to have a technical issue. I am reaching out to seek assistance in getting the product repaired or replaced. I have found the features of the device incredibly useful in managing my outdoor activities, and I hope to continue using it with your support. I would greatly appreciate your prompt attention to this matter. Thank you for your assistance.\\n\\nSincerely, Eleanor Morse\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 434,\n    \"ProductId\": 143,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 263,\n    \"ShortSummary\": \"Inquiry about cookware set for portable stove\",\n    \"LongSummary\": \"Customer inquires about using the Titanium Camping Cookware Set on a portable camping stove. Assistant advises testing at home before the camping trip. No pending questions.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1026,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there! I just bought the Titanium Camping Cookware Set from Trail Taste and I\\u0027m super excited to use it on my next camping trip. I was wondering if this cookware set is suitable for use on a portable camping stove. I want to make sure I can use it to cook all my favorite camping meals without any issues. Thanks so much for your help!\"\n      },\n      {\n        \"MessageId\": 1027,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Titanium Camping Cookware Set from Trail Taste is recommended for use with a portable camping stove. However, we advise testing the cookware at home to familiarize yourself with the equipment and to practice setting it up, adjusting the heat, and cooking a simple meal to ensure everything is working as expected. This will ensure a smooth experience when using it on your camping trip. If you have any further questions or need assistance, feel free to reach out.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 435,\n    \"ProductId\": 104,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 299,\n    \"ShortSummary\": \"Broken water filter bottle - replacement or refund requested\",\n    \"LongSummary\": \"Customer is frustrated with broken Puriflo Water Filter Bottle. Requesting replacement or refund. Needs further assistance with product issues.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1028,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am so frustrated with this Puriflo Water Filter Bottle from Aquaduct! I bought it for hiking and camping, and now it\\u0027s broken after just a few uses. This is not what I expected when the description claims it\\u0027s perfect for outdoor activities. I want a replacement or a refund. This is unacceptable and I\\u0027m extremely disappointed with the quality of this product.\"\n      },\n      {\n        \"MessageId\": 1029,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Aquaduct Puriflo Water Filter Bottle is designed to provide clean and safe drinking water for outdoor enthusiasts and travelers. It\\u0027s important to inspect the components on a monthly basis to ensure they are functioning properly. If you have encountered any issues with the product, please let us know so we can assist you further.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 436,\n    \"ProductId\": 178,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 300,\n    \"ShortSummary\": \"Inquiry about high-energy ingredient sustainability\",\n    \"LongSummary\": \"Customer is seeking assurance about the quality and sustainability of high-energy ingredients in the product. They specifically asked for details about the sourcing and production process of these ingredients. Pending response needed to address customer\\u0027s concerns.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1030,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I recently purchased the PowerBar Pro 2021 and I expect it to perform as advertised. I want to ensure that the high-energy ingredients are providing the sustainable nutrition I need for my adventures. If the product does not meet my expectations, I will be seeking a refund or replacement. I need assurance that the product is of high quality and will not cause any allergic reactions. Please respond promptly to address my concerns.\"\n      },\n      {\n        \"MessageId\": 1031,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the PowerBar Pro 2021 is gluten-free and suitable for vegans, as it is made with exclusively vegan ingredients and does not contain any animal products. It is also recommended to stop consuming the product and seek medical advice if you experience any allergic reactions. Additionally, the product has a storage time of up to a year from the date of manufacture, and it should be stored in an airtight container once opened to maintain its quality and taste.\"\n      },\n      {\n        \"MessageId\": 1032,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I appreciate the information provided about the PowerBar Pro 2021. However, I need further assurance about the quality of the high-energy ingredients and their sustainability. Can you provide more details about the sourcing and production process of these ingredients?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 437,\n    \"ProductId\": 53,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 150,\n    \"ShortSummary\": \"Anti-fog spray application and lifetime warranty info.\",\n    \"LongSummary\": \"Customer has applied the anti-fog spray as instructed and will test the goggles this weekend. They appreciate the info about the limited lifetime warranty.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1033,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I am considering purchasing the GlacierTech Snowsport Goggles and I have a question about activating the anti-fog coating mentioned in the description. Can you provide me with more details on how to use the anti-fog spray and ensure that it is applied correctly for optimal performance? Thank you for your assistance.\"\n      },\n      {\n        \"MessageId\": 1034,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"To activate the anti-fog coating, use the provided anti-fog spray. Apply a small amount to the inner surface of the lenses, ensuring complete coverage. Allow a few moments for the coating to fully activate before using the goggles. According to the manual, \\u0022This will ensure that the coating has had sufficient time to create a protective barrier against fogging.\\u0022\"\n      },\n      {\n        \"MessageId\": 1035,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the detailed instructions. I have followed the steps and applied the anti-fog spray as directed. I will test the goggles out on the slopes this weekend and let you know if they worked well. Thank you for your assistance.\"\n      },\n      {\n        \"MessageId\": 1036,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the GlacierTech Snowsport Goggles are covered by a limited lifetime warranty. If you experience any issues with manufacturing defects, IceMaster will repair or replace them free of charge. For further assistance with persistent fogging issues or any other questions, please refer to the \\u0022Contact Us\\u0022 section of the manual. We hope you have a great time on the slopes!\"\n      },\n      {\n        \"MessageId\": 1037,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information about the limited lifetime warranty. I appreciate the peace of mind knowing that I am protected against any manufacturing defects. I will definitely refer to the \\u0027Contact Us\\u0027 section if I encounter any persistent fogging issues. Thank you for your assistance!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 438,\n    \"ProductId\": 27,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 301,\n    \"ShortSummary\": \"Defective AdventurePro DSLR Camera Request\",\n    \"LongSummary\": \"Customer\\u0027s AdventurePro DSLR Camera has stopped working, requesting a replacement. Followed safety precautions and only used provided accessories. Pending question: reason for camera\\u0027s failure.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1038,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the AdventurePro DSLR Camera and unfortunately it has stopped working. I\\u0027ve followed the safety precautions outlined in the manual, and I have only used the provided accessories. I would like to request a replacement for the defective camera. I appreciate your prompt attention to this matter.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 439,\n    \"ProductId\": 115,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 302,\n    \"ShortSummary\": \"Strap Issues with Snowshoes\",\n    \"LongSummary\": \"Customer unable to secure snowshoes, wants to return for refund.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Returns\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1039,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Straps not working right. Need help ASAP. Snowshoes not staying on.\"\n      },\n      {\n        \"MessageId\": 1040,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, to prevent the snowshoes from feeling loose while walking, make sure the straps are tightly secured around your boots and adjust the bindings to fit snugly. If needed, tighten the straps to prevent any unnecessary movement while walking.\"\n      },\n      {\n        \"MessageId\": 1041,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Straps still not working. Tried what you said, but snowshoes still falling off. Need more help.\"\n      },\n      {\n        \"MessageId\": 1042,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"It seems that the neon green strap adjusters on the sides of your snowshoes are the key to securing your feet in the snowshoes. Try pulling the straps to tighten them, ensuring a secure fit without being too restricting. This should help prevent the snowshoes from falling off. If you continue to experience issues, you may consider returning the product for a refund within 30 days as per our policy.\"\n      },\n      {\n        \"MessageId\": 1043,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Tried tightening the neon green strap adjusters, but snowshoes still falling off. Want to return for refund.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 440,\n    \"ProductId\": 57,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 218,\n    \"ShortSummary\": \"PowerPort 10000 Charger Not Working\",\n    \"LongSummary\": \"Customer purchased PowerPort 10000 Portable Charger, it\\u0027s now not working. Customer requests help to figure out next steps regarding potential repair or replacement.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1046,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the PowerPort 10000 Portable Charger from Charge Mate and I seem to have accidentally broken it. I\\u0027m not sure what happened, but now it\\u0027s not working. I\\u0027m really embarrassed and I hope I didn\\u0027t cause any damage that\\u0027s not covered. Can you please help me figure out what to do next? Thank you so much.\"\n      },\n      {\n        \"MessageId\": 1047,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the PowerPort 10000 Portable Charger is equipped to charge multiple devices simultaneously. It allocates the proper power output to each device for efficient charging. If you believe your charger may be defective and requires repair or replacement, please refer to the warranty information provided with your product for instructions on how to obtain service.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 441,\n    \"ProductId\": 144,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 169,\n    \"ShortSummary\": \"Rain Usage Inquiry\",\n    \"LongSummary\": \"Customer inquiring about using ProLite Climbing Harness in the rain. Assistant recommended contacting RidgeRope customer support for detailed info. Pending question about usage in wet conditions.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1048,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, I just got the ProLite Climbing Harness from RidgeRope and I\\u0027m wondering if it\\u0027s okay to use it in the rain. Will it get damaged if it gets wet? Thanks!\"\n      },\n      {\n        \"MessageId\": 1049,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The RidgeRope ProLite Climbing Harness is designed with durable materials and features a secure, easy-to-use buckle system for quick adjustments and a snug fit. It also includes gear loops for convenient storage of climbing equipment. However, the manual does not specify whether the harness can be used in the rain. For detailed information on usage in wet conditions, I recommend reaching out to RidgeRope\\u0027s customer support as detailed in the user manual.\"\n      },\n      {\n        \"MessageId\": 1050,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Okay, will contact RidgeRope\\u0027s customer support for info on using the harness in the rain. Thanks!\"\n      },\n      {\n        \"MessageId\": 1051,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The RidgeRope ProLite Climbing Harness is designed with durable materials and features a padded waistbelt and leg loops for added comfort during extended use. However, the manual does not specify whether the harness can be used in the rain. For detailed information on usage in wet conditions, I recommend reaching out to RidgeRope\\u0027s customer support as detailed in the user manual.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 442,\n    \"ProductId\": 104,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 304,\n    \"ShortSummary\": \"Non-working water filter bottle - replacement or refund needed\",\n    \"LongSummary\": \"Customer demands replacement or refund for non-working Puriflo Water Filter Bottle. Wants prompt response and resolution. Assistance needed for return or refund process.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1052,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I just bought the Puriflo Water Filter Bottle and it\\u0027s not working properly! I demand a replacement or a refund immediately. I shouldn\\u0027t have to deal with this kind of inconvenience after spending my hard-earned money on your product. I expect a prompt response and resolution to this issue!\"\n      },\n      {\n        \"MessageId\": 1053,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We apologize for the inconvenience you\\u0027ve experienced with the Puriflo Water Filter Bottle. According to the manual, the Puriflo Water Filter Bottle is designed to meet the needs of outdoor enthusiasts and travelers who require a reliable and efficient water filtration solution. Its superior performance, durability, and portability make it an essential tool for anyone who values access to clean and safe drinking water in any environment. If you believe the product is defective, you may be eligible for a return or refund. For further assistance, please refer to the manufacturer\\u0027s support contact details in the user manual.\"\n      },\n      {\n        \"MessageId\": 1054,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I already checked the user manual and followed all the instructions, but the Puriflo Water Filter Bottle still isn\\u0027t working properly. I want a replacement or a refund as soon as possible!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 443,\n    \"ProductId\": 71,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 305,\n    \"ShortSummary\": \"Inquiry about Signal Booster 2000 heat generation\",\n    \"LongSummary\": \"Customer inquired about normal heat generation of Signal Booster 2000. Received reassurance from assistant. No pending question.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1055,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Trailcom Signal Booster 2000 and I just wanted to confirm that it\\u0027s normal for the device to generate some heat during prolonged use at maximum signal boosting levels. I want to ensure that the product is behaving as expected and to make sure that I\\u0027m using it correctly. Your assistance in providing reassurance would be greatly appreciated. Thank you.\"\n      },\n      {\n        \"MessageId\": 1056,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Trailcom Signal Booster 2000 is designed to enhance signal strength for off-grid communication in remote areas. It complies with all relevant regulatory standards and is designed to operate within approved frequency bands and power levels to ensure minimal interference with other communication systems. As for the heat generation, I\\u0027d recommend using the device within the specified operational conditions to ensure optimal performance. If you have any concerns about the device, feel free to contact us for further assistance.\"\n      },\n      {\n        \"MessageId\": 1057,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for your prompt response. I appreciate the information provided. I will make sure to use the device within the specified operational conditions as per the manual. If I encounter any further issues, I will definitely reach out for assistance. Thank you again for your help.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 444,\n    \"ProductId\": 4,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 306,\n    \"ShortSummary\": \"Inquiry about portable water filter for saltwater use\",\n    \"LongSummary\": \"Customer Maxine Shaw asks if the portable water filter can handle saltwater due to living near the ocean. The pending question needs a response regarding the water filter\\u0027s capability with saltwater.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1058,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! I just bought the Life Guard X Emergency Survival Kit and I\\u0027m super excited to be prepared for anything! I have a quick question - can the portable water filter handle saltwater? I live near the ocean and want to make sure I\\u0027m covered in case of an emergency. Thanks so much for your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 445,\n    \"ProductId\": 44,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 307,\n    \"ShortSummary\": \"Emergency Kit Missing Compass Query\",\n    \"LongSummary\": \"Customer wants explanation for lack of compass in emergency kit. Expresses concern about navigating without cell service or GPS. Needs a detailed response addressing the necessity of a compass in emergency situations.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1059,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I can\\u0027t believe this emergency kit doesn\\u0027t come with a compass! What good is it without a way to navigate? I can\\u0027t trust its reliability without such a basic survival tool. I demand an explanation for this oversight!\"\n      },\n      {\n        \"MessageId\": 1060,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I apologize for the oversight. The RescueTech Emergency Kit is designed to prioritize essential survival tools. However, I understand your concern. If you have any further questions or need assistance with anything else, please feel free to ask.\"\n      },\n      {\n        \"MessageId\": 1061,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I still don\\u0027t understand how a compass isn\\u0027t considered essential in an emergency kit. What if I need to navigate in an area without cell service or GPS? This is unacceptable!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 446,\n    \"ProductId\": 59,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 308,\n    \"ShortSummary\": \"Troubleshooting Explorer 3000 Kayak issues\",\n    \"LongSummary\": \"Customer purchased Explorer 3000 Kayak from Aqua Venture and is experiencing issues. Asked for help with specific troubleshooting steps. Pending question: What should I do if the issue persists? Next support agent should provide further troubleshooting steps or advise on contacting customer support for assistance.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1062,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi, I recently purchased the Explorer 3000 Kayak from Aqua Venture and I\\u0027m experiencing some issues with it. Can you please help me with this?\"\n      },\n      {\n        \"MessageId\": 1063,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, ensure that the battery is fully charged and properly inserted into the battery compartment. Check for any signs of damage to the battery or the kayak\\u0027s power system. If the issue persists, please contact Aqua Venture customer support for further assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 447,\n    \"ProductId\": 147,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 309,\n    \"ShortSummary\": \"Inquiry about adjustable gimbal for landscape photography\",\n    \"LongSummary\": \"Customer inquired about SkyMaster X2000\\u0027s adjustable gimbal control for capturing landscapes. Customer tested feature successfully. No pending questions. Next response should offer further assistance or tips for using the drone\\u0027s features.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1064,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! I recently stumbled upon the SkyMaster X2000 and I am absolutely thrilled about the 4K camera and GPS navigation features. I\\u0027m an avid outdoor photographer and this drone seems like the perfect tool to take my photography to new heights (literally!). I\\u0027m really interested in knowing more about how the adjustable gimbal control works - being able to change the camera angle mid-flight sounds like a game-changer for capturing different perspectives. Can you give me some insight into how well the SkyMaster X2000 performs for capturing breathtaking landscapes? Thanks a bunch!\"\n      },\n      {\n        \"MessageId\": 1065,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The SkyMaster X2000 features an adjustable gimbal that allows you to control the camera angle mid-flight. Using the AeroVision app, you can adjust the tilt of the camera to capture different perspectives and angles while the drone is in the air. This feature is designed to enhance your ability to capture breathtaking landscapes and achieve unique perspectives. The SkyMaster X2000 also boasts a high-quality 4K camera for capturing stunning photos and videos from the sky. To capture a photo, you simply need to press the dedicated camera button on the remote controller. I hope this information helps with your decision! Let me know if there\\u0027s anything else I can assist you with.\"\n      },\n      {\n        \"MessageId\": 1066,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you so much for the information! I\\u0027m super excited to test out the adjustable gimbal feature and see how it enhances my photography. I\\u0027ll definitely give it a go and let you know how it turns out. You\\u0027ve been super helpful, thanks a bunch!\"\n      },\n      {\n        \"MessageId\": 1067,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the SkyMaster X2000 features an adjustable gimbal that allows you to control the camera angle mid-flight. Using the AeroVision app, you can adjust the tilt of the camera to capture different perspectives and angles while the drone is in the air. Simply swipe or use the on-screen controls to tilt the camera up or down, giving you ultimate control over your aerial footage. Be sure to practice using the gimbal controls before attempting complex maneuvers to ensure smooth and fluid camera movements. I hope this information helps! Let me know if there\\u0027s anything else I can assist you with.\"\n      },\n      {\n        \"MessageId\": 1068,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there! I tried out the adjustable gimbal feature and it worked like magic! I was able to capture some stunning aerial footage of the landscapes around my area. Thanks so much for your help, I\\u0027m absolutely loving the SkyMaster X2000!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 448,\n    \"ProductId\": 88,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 310,\n    \"ShortSummary\": \"Performance issues with RapidFlow Kayak Paddle\",\n    \"LongSummary\": \"Customer experiencing issues with the RapidFlow Kayak Paddle. Claims to be using it as instructed, but still has performance issues. Needs further assistance to diagnose the problem.\",\n    \"CustomerSatisfaction\": 3,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1069,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am so frustrated with this RapidFlow Kayak Paddle! I can\\u0027t believe it\\u0027s supposed to be lightweight and durable when I can\\u0027t even make it work properly. It\\u0027s not living up to its description at all. I need help figuring out why it\\u0027s not performing as expected. This is really disappointing.\"\n      },\n      {\n        \"MessageId\": 1070,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry to hear about your experience with the RapidFlow Kayak Paddle. According to the user manual, the paddle is designed for use in white water rapids only and should not be used in calm water or open sea conditions. Using the paddle outside of its intended environment may result in loss of control and serious injury. If you have been using it in conditions other than white water rapids, this might be the reason for the performance issues. Please let us know if that\\u0027s the case or if you need further assistance.\"\n      },\n      {\n        \"MessageId\": 1071,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027ve only been using the paddle in white water rapids as instructed, so that can\\u0027t be the reason for the performance issues. I need further assistance to figure out what\\u0027s going on with this paddle.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 449,\n    \"ProductId\": 199,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 311,\n    \"ShortSummary\": \"Inquiry about solar charger for RV refrigerator\",\n    \"LongSummary\": \"Customer inquiring about using the solar charger to power an RV refrigerator. Asks for guidance on best setup. Needs advice on compatibility and setup specifics.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1072,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the SunShift 100W Solar Charger and I\\u0027m considering using it to power a small refrigerator in my RV. I\\u0027ve read about its fast charging and durability, so I think it should be able to handle the task. Can you provide any guidance on how to best set it up for this purpose? Thank you.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 450,\n    \"ProductId\": 159,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 169,\n    \"ShortSummary\": \"Assistance with Solar Charging Feature\",\n    \"LongSummary\": \"Customer needs assistance with using the solar charging feature on the Rugged Solar Power Bank. Agent provided detailed instructions for using the solar panel for charging. Customer will try and report back if any issues.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1075,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I can\\u0027t figure out how to use the solar charging feature on the Rugged Solar Power Bank. Can you help me with this? Thanks!\"\n      },\n      {\n        \"MessageId\": 1076,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"To charge the Rugged Solar Power Bank, place it under direct sunlight for optimal results. The solar panels, located on the top of the power bank, will absorb sunlight and convert it into energy. Ensure that the panels are facing the sun directly to maximize charging efficiency. It may take several hours to fully charge the power bank using solar power, depending on the intensity of sunlight. The maximum input for the solar panel is 5V, ensuring efficient and safe charging when using solar power. When charging the power bank via solar panel, ensure to do so in an open, outdoor area with direct sunlight for optimal charging efficiency.\"\n      },\n      {\n        \"MessageId\": 1077,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thanks for the information. I will try charging the power bank under direct sunlight and see if it works. I\\u0027ll let you know if I encounter any issues.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 451,\n    \"ProductId\": 154,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 312,\n    \"ShortSummary\": \"Live Tracking Issue on GPS Personal Locator\",\n    \"LongSummary\": \"Customer Eliot Jensen is experiencing issues with live tracking on the GPS Personal Locator despite following instructions and troubleshooting steps. Additional support is needed to resolve the issue.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1078,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, I just got the GuardianGear GPS Personal Locator and I\\u0027m not sure if it\\u0027s working right. I tried the live tracking feature but it seems off. Can you help me figure it out?\"\n      },\n      {\n        \"MessageId\": 1079,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"To initiate live tracking, please press and hold the \\u0022Live Tracking\\u0022 button, which is conveniently located on the side of the device, until the LED indicator light illuminates in a lovely shade of green. The locator will then commence transmitting your precise location in real time to our esteemed servers. If you experience any inaccuracies in the live tracking feature of the GPS Personal Locator, we recommend moving to an open outdoor area with clear visibility to the sky to ensure a stronger GPS signal. Additionally, kindly wait for a few moments for the device to recalibrate and update its location. If issues persist, please contact customer service for additional support.\"\n      },\n      {\n        \"MessageId\": 1080,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Tried live tracking outside but still not working\"\n      },\n      {\n        \"MessageId\": 1081,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The live tracking feature can be initiated by pressing and holding the \\u0022Live Tracking\\u0022 button until the LED indicator light turns green. If inaccuracies persist, try moving to an open outdoor area with clear visibility to the sky and wait for the device to recalibrate. If issues persist, please contact customer service for additional support. According to the manual, for troubleshooting issues with the GPS Personal Locator, please consult the troubleshooting section of the manual for guidance, and if the issue persists, contact customer support for further assistance.\"\n      },\n      {\n        \"MessageId\": 1082,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Still not working after trying all suggestions\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 452,\n    \"ProductId\": 121,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 313,\n    \"ShortSummary\": \"HydroTech 5000 Scuba Diving Support\",\n    \"LongSummary\": \"Customer excited to use HydroTech 5000 for scuba diving trip. Seeks tips for underwater use and app pairing. Agent provided info on battery indicator and app pairing process. Pending question on underwater suitability.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1083,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there! I just bought the HydroTech 5000 and I am so excited to use it for my upcoming scuba diving trip! I heard it has a GPS navigation system, and I can\\u0027t wait to set waypoints and explore the waters with ease. I\\u0027m a bit unsure if it\\u0027s suitable for scuba diving, can you give me some tips on using it underwater? Thanks so much!\"\n      },\n      {\n        \"MessageId\": 1084,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The HydroTech 5000 comes with a battery level indicator, so you can keep an eye on the remaining battery percentage to plan your activities accordingly. To use the GPS navigation system underwater, make sure to pair your smartphone with the HydroTech 5000 using the WaterRover app. Follow the steps in the manual to complete the pairing process.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 453,\n    \"ProductId\": 9,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 314,\n    \"ShortSummary\": \"Product misunderstanding, seeking cake warming solutions\",\n    \"LongSummary\": \"Customer misunderstood product use, seeking alternate cake warming solutions. Next agent should suggest cake warmer or portable food warmer options.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1085,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the AltitudeShield Pro for my high-altitude baking needs. I assumed that it would also keep my cakes warm, but unfortunately, it doesn\\u0027t seem to do that. I didn\\u0027t see anything in the description or manual about temperature control, so I just assumed it would work that way. Can you help me figure out how to keep my cakes warm with this product?\"\n      },\n      {\n        \"MessageId\": 1086,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the AltitudeShield Pro is not suitable for use in any environment other than high-altitude locations. It should not be used to protect cakes or baked goods at sea level or in normal atmospheric conditions. I apologize for the inconvenience.\"\n      },\n      {\n        \"MessageId\": 1087,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Oh, I see. I guess I misunderstood the product description. Is there anything else I can use to keep my cakes warm at sea level?\"\n      },\n      {\n        \"MessageId\": 1088,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry, but the product manual does not contain information on how to keep cakes warm at sea level. You may want to consider using a dedicated cake warmer or a portable food warmer for this purpose.\"\n      },\n      {\n        \"MessageId\": 1089,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for your help. I will look into getting a dedicated cake warmer or portable food warmer. Hopefully, that will solve my problem.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 454,\n    \"ProductId\": 112,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 315,\n    \"ShortSummary\": \"Detailed Ventilation Inquiry\",\n    \"LongSummary\": \"Customer Evan Caldwell seeks detailed information about the design and placement of ventilated channels and vents in the Trailblazer Carbon Fiber Mountain Bike Helmet. Next support agent should provide specific technical details on the ventilation system.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1090,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear support team, I am considering purchasing the Trailblazer Carbon Fiber Mountain Bike Helmet from Cyclextreme, and I have some technical questions about its ventilation and cooling features. The manual mentions \\u0027exquisitely designed ventilated channels and strategically placed vents\\u0027 that provide a \\u0027regal level of comfort.\\u0027 Can you provide more detailed information about the specific design and placement of these ventilated channels and vents? I am particularly interested in understanding how the ventilation system efficiently dissipates heat, as I aim to make an informed decision based on the superior technical capabilities of this product. Your prompt and detailed response would be greatly appreciated. Thank you.\"\n      },\n      {\n        \"MessageId\": 1091,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Trailblazer Carbon Fiber Mountain Bike Helmet is equipped with advanced ventilation through exquisitely designed ventilated channels and strategically placed vents. It is designed to provide a level of comfort that is positively regal. To maximize ventilation and comfort, it is recommended to ensure the front vents are clear of any obstructions such as mud or debris before each use. If you need more detailed information, you can refer to the user manual for the Trailblazer Carbon Fiber Mountain Bike Helmet.\"\n      },\n      {\n        \"MessageId\": 1092,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information provided. I have checked the user manual as suggested, and it does offer some insight into the ventilation system of the Trailblazer Carbon Fiber Mountain Bike Helmet. However, I was hoping for more specific details regarding the design and placement of the ventilated channels and vents. Could you please provide more detailed information about how the ventilation system efficiently dissipates heat, as I aim to make an informed decision based on the superior technical capabilities of this product?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 455,\n    \"ProductId\": 63,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 316,\n    \"ShortSummary\": \"Trouble setting up solar-powered string lights\",\n    \"LongSummary\": \"Customer had trouble setting up solar-powered string lights, needed assistance to understand how to connect LED lights to solar panel and how to charge the lights. Assistant provided detailed explanation on how the lights work, how to connect the LED lights to the solar panel, and how to charge the lights. Customer successfully set up and charged the lights, and expressed appreciation for the assistance.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1093,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Luminartech Solar-Powered String Lights and I\\u0027m having trouble getting them set up. I\\u0027m not sure how to connect the LED lights to the solar panel and I\\u0027m confused about how they charge. I really want to create a magical atmosphere in my backyard, but I can\\u0027t figure it out. Can you please help me understand how to assemble and charge the lights? Thank you so much!\"\n      },\n      {\n        \"MessageId\": 1094,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Luminartech Solar-Powered String Lights are designed to be long-lasting and provide hours of continuous illumination throughout the night. They are solar-powered, meaning there\\u0027s no need for electricity or batteries as the built-in solar panel harnesses the power of the sun to charge the lights during the day. You can effortlessly create a magical outdoor atmosphere with these waterproof and durable string lights, perfect for camping trips or backyard gatherings.\"\n      },\n      {\n        \"MessageId\": 1095,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Oh wow, thank you for explaining how the lights work! I didn\\u0027t realize they were solar-powered, so that makes so much more sense now. I\\u0027ll try connecting the LED lights to the solar panel and see if I can get them to charge. Thank you for your help!\"\n      },\n      {\n        \"MessageId\": 1096,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m glad to hear that you found the information helpful! According to the manual, you can attach the LED lights to the solar panel by connecting the male and female connectors. In terms of charging, make sure to place the solar panel in a location where it can receive direct sunlight for at least 6-8 hours to fully charge the battery. The built-in light sensor will automatically turn the lights on at dusk and off at dawn to conserve energy. If you have any further questions or need additional assistance, feel free to reach out to us.\"\n      },\n      {\n        \"MessageId\": 1097,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you so much for your help! I connected the LED lights to the solar panel and placed it in direct sunlight for 8 hours. It worked like magic and now my backyard looks absolutely beautiful at night! I appreciate your assistance in helping me understand how to set up and charge the lights.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 456,\n    \"ProductId\": 76,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 208,\n    \"ShortSummary\": \"Unresponsive Controls and Sound Issues\",\n    \"LongSummary\": \"Customer is frustrated with unresponsive controls and sound issues. Maintenance steps performed without success. Demands immediate resolution or else will consider returning the product for a refund. Next response should address specific troubleshooting steps or warranty information.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1098,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am absolutely frustrated with my UltiBASS Wilderness DJ Pro! I bought it for outdoor adventures, but the control panel buttons are unresponsive, and I can\\u0027t get the sound to work properly. This is not what I expected from a rugged, high-tech setup that can supposedly withstand any environment. I need help with these issues immediately or else I\\u0027ll have to consider returning this product for a refund.\"\n      },\n      {\n        \"MessageId\": 1099,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"We apologize for the inconvenience. Before considering a return, we recommend performing general maintenance steps to troubleshoot the issues with the Wilderness DJ Pro. If the issue persists, the product is covered by a generous warranty, and you may refer to the warranty information in the manual for details on repair or refund options.\"\n      },\n      {\n        \"MessageId\": 1100,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I tried performing the general maintenance steps as suggested, but the issues with the Wilderness DJ Pro persist. I am extremely disappointed with the product and the fact that it is not living up to its promised ruggedness. I demand a resolution to this issue immediately.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 457,\n    \"ProductId\": 99,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 149,\n    \"ShortSummary\": \"Inquiry about Summit 3000 Trekking Backpack\",\n    \"LongSummary\": \"Customer inquires about Summit 3000\\u0027s suitability for long treks, durability, warranty coverage, and technical support. Needs detailed information and assistance.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1101,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I am considering purchasing the Summit 3000 Trekking Backpack for my upcoming hiking trip. Can you provide information on the backpack\\u0027s suitability for long-distance treks and its durability? I am also interested in the warranty coverage and technical support available for this product. Thank you for your assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 458,\n    \"ProductId\": 156,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 317,\n    \"ShortSummary\": \"Crampons fitting and effectiveness\",\n    \"LongSummary\": \"Customer expressed concern about Arctic Ice Grip Crampons not working as expected, received fitting tips, and reported improved confidence after testing them. Next agent should confirm if customer\\u0027s issue is resolved and offer further assistance if needed.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1102,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the Arctic Ice Grip Crampons and I\\u0027m a little concerned that they might not be working as expected. I\\u0027ve been slipping a lot on icy terrain, and I\\u0027m worried that I might be doing something wrong. I really want to love these crampons, but I\\u0027m just not feeling confident in them. Can you please provide me with some reassurance or tips on how to use them effectively? Thank you so much for your help.\"\n      },\n      {\n        \"MessageId\": 1103,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hi there! To ensure the effectiveness of your Arctic Ice Grip Crampons, it\\u0027s important to adjust the fit properly before use. Here are some tips for putting them on: Before you head out into the winter wonderland, let\\u0027s make sure you know how to properly put on your Arctic Ice Grip Crampons. \\u2744\\uFE0F\\uD83D\\uDD28 Following these maintenance guidelines will help prolong the life of your Arctic Ice Grip Crampons and ensure they are ready for your next adventure on icy terrain. If you encounter any fitting issues, please let us know. Additionally, if you have any further concerns, feel free to reach out to us. Thank you!\"\n      },\n      {\n        \"MessageId\": 1104,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the tips! I adjusted the fit of the crampons as suggested, and I can already feel the difference. I went for a short walk on icy terrain and didn\\u0027t slip once. I\\u0027m feeling much more confident now. I really appreciate your help!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 459,\n    \"ProductId\": 101,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 318,\n    \"ShortSummary\": \"Defective Lantern Flickering\",\n    \"LongSummary\": \"Lumina LED Camping Lantern flickering, changed batteries, still flickering. Customer seeking further assistance with defective lantern. Refund or manufacturer support needed.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1105,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, my Lumina LED Camping Lantern is flickering when I turn it on. Is it supposed to do that? Do I need new batteries?\"\n      },\n      {\n        \"MessageId\": 1106,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Based on the product manual, the Ultraglow Lumina LED Camping Lantern is designed to provide reliable light in outdoor settings. If your lantern is flickering or not turning on, you may need to check the batteries and ensure they are properly inserted. If the issue persists, feel free to contact our friendly customer service team for assistance.\"\n      },\n      {\n        \"MessageId\": 1107,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Changed batteries, still flickering. What should I do now?\"\n      },\n      {\n        \"MessageId\": 1108,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry, the user manual does not provide specific information about flickering issues. However, based on the troubleshooting steps we\\u0027ve already tried, it seems like the lantern may have a defect. You may initiate a return for a refund or contact the manufacturer for further support.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 460,\n    \"ProductId\": 75,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 122,\n    \"ShortSummary\": \"Difficulty setting up emergency contacts\",\n    \"LongSummary\": \"Customer needs clear instructions on setting up emergency contacts for the Escapesafe GPS Locator Beacon. Clarify steps and confirm receipt of instructions.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1111,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Escapesafe GPS Locator Beacon and I\\u0027m having trouble understanding how to set up the emergency contacts. I want to ensure that my emergency contacts are notified in case of an emergency while I\\u0027m out hiking. Can you please provide me with clear instructions on how to set up the emergency contacts on the beacon? Thank you.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 461,\n    \"ProductId\": 88,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 320,\n    \"ShortSummary\": \"Expertise \\u0026 Environment Concern for RapidFlow Kayak Paddle\",\n    \"LongSummary\": \"Customer has concerns about expertise required for RapidFlow Kayak Paddle. Disappointed with limitation to white water rapids only. Needs alternative paddle options.\",\n    \"CustomerSatisfaction\": 3,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1112,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I was considering buying the RapidFlow Kayak Paddle, but after reading your manual, I have serious concerns. You mention the risk of injury or death and the need for experienced paddlers, which makes me question if this paddle is suitable for someone like me. Can you provide more information about the level of expertise required to use this paddle safely? I need to understand the specific usage scenarios in which this paddle is appropriate before making a purchase decision.\"\n      },\n      {\n        \"MessageId\": 1113,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The RapidFlow Kayak Paddle is an advanced piece of kayaking gear that requires extreme caution and skill to operate. It is designed for use in white water rapids only and should not be used in calm water or open sea conditions. Attempting to use the paddle outside of its intended environment may result in loss of control and serious injury. For specific usage scenarios, please refer to the user manual. If you have any concerns about your level of expertise, we recommend seeking guidance from experienced kayakers or contacting the manufacturer for further instructions.\"\n      },\n      {\n        \"MessageId\": 1114,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I find it very concerning that the paddle is designed for use in white water rapids only. I was hoping for a paddle that I could use in a variety of environments. This limitation is a deal-breaker for me. I will need to look for a different paddle that suits my needs better.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 462,\n    \"ProductId\": 67,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 321,\n    \"ShortSummary\": \"Unclear shelf life info for hiking trip\",\n    \"LongSummary\": \"Customer needs clear shelf life info for the Nutritech Energy Bars Variety Pack before hiking trip. Manual and manufacturer have been unhelpful. Customer is frustrated and seeking direct answer.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1115,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027m considering buying the Nutritech Energy Bars Variety Pack for my hiking trip, but I can\\u0027t find any information about the shelf life. It\\u0027s crucial for me to know how long these bars will last before I commit to a purchase. Can you please provide me with this information? I don\\u0027t want to end up with expired bars on my trip.\"\n      },\n      {\n        \"MessageId\": 1116,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the shelf life of the Nutritech Energy Bars Variety Pack is indicated on the packaging. It is recommended to keep the bars in their original packaging or in an airtight container to maintain freshness. The manual also advises avoiding exposure to extreme temperatures or humidity, as this can affect the quality of the product. If you have the packaging, you should be able to find the shelf life information there. If you have any further questions, feel free to ask.\"\n      },\n      {\n        \"MessageId\": 1117,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I checked the packaging like you suggested, and I still couldn\\u0027t find the shelf life information. This is really frustrating! I need to know how long these bars will last before I go on my trip. Can you please provide me with a direct answer instead of just referring me back to the packaging?\"\n      },\n      {\n        \"MessageId\": 1118,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Nutritech Energy Bars Variety Pack should be stored in a cool, dry place away from direct sunlight. However, the specific shelf life information is not provided in the manual. I apologize for the inconvenience. I recommend reaching out to the manufacturer\\u0027s contact information provided in the manual for further assistance regarding the shelf life of the energy bars. If you have any other questions, feel free to ask.\"\n      },\n      {\n        \"MessageId\": 1119,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I already reached out to the manufacturer\\u0027s contact information provided in the manual, and they couldn\\u0027t provide me with the shelf life information either. This is incredibly frustrating. I need to know how long these bars will last before I go on my trip, and I\\u0027m not getting any clear answers. This is unacceptable.\"\n      },\n      {\n        \"MessageId\": 1120,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Nutritech Energy Bars Variety Pack is designed to provide a quick and convenient source of nutrition for outdoor adventures. With a high-protein, low-sugar formula, these energy bars offer a perfect balance of energy and taste. Whether you\\u0027re hiking, cycling, or camping, the Nutritech Energy Bars Variety Pack is the ideal choice to fuel your next excursion. The variety pack includes a selection of delicious flavors to keep your energy levels up during outdoor activities. If you have any further questions, feel free to ask.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 463,\n    \"ProductId\": 83,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 322,\n    \"ShortSummary\": \"Confusion about battery storage and camera settings\",\n    \"LongSummary\": \"Customer is confused about battery storage and camera settings. Needs clarification on battery storage during shoots and available camera resolutions.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1121,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I don\\u0027t understand why your manual says to store the battery at room temperature when it\\u0027s supposed to be used for outdoor aerial filming. How am I supposed to keep it at room temp during a shoot? This seems like a major design flaw! And don\\u0027t get me started on the camera settings. Why does it only offer 720p, 1080p, and 4K? What about the in-between resolutions? I\\u0027m not convinced this drone is as great as you claim it to be.\"\n      },\n      {\n        \"MessageId\": 1122,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The manual recommends storing the battery at room temperature in a dry place when it\\u0027s not in use. Extreme temperatures and moisture can cause damage to the battery cells. As for the camera settings, the available resolutions are 720p, 1080p, and 4K. For exposure and white balance, you can navigate to the camera settings menu to make adjustments.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 464,\n    \"ProductId\": 168,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 323,\n    \"ShortSummary\": \"Inquiring about WildDJ Pro Mixer battery performance\",\n    \"LongSummary\": \"Customer inquires about maintaining optimal battery performance for WildDJ Pro Mixer. Assistant advises regular charging and delicate charging cable usage. No pending questions.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1123,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear PeakMix Support Team, I recently purchased the WildDJ Pro Mixer for an upcoming wilderness party, and I am incredibly impressed with its rugged construction and advanced mixing features. However, I have a rather specific concern about the battery life. I understand that the manual mentions storing the device in a cool, dry place when not in use to prolong battery life, but I\\u0027m curious if there are any additional tips or precautions I should be aware of to ensure optimal battery performance. Your assistance in this matter would be greatly appreciated. Thank you for your attention to this matter. Sincerely, Eleanor Chang\"\n      },\n      {\n        \"MessageId\": 1124,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, to maintain optimal battery performance, it is essential to charge your WildDJ Pro Mixer regularly, even when not in use. This practice will ensure that the battery retains its charge capacity and remains ready for your next wilderness DJing escapade. Additionally, delicate care should be taken when inserting the charging cable to avoid any damage to the battery.\"\n      },\n      {\n        \"MessageId\": 1125,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear PeakMix Support Team, Thank you for your prompt response and helpful advice. I have been charging the WildDJ Pro Mixer regularly as suggested, and I will continue to do so to maintain optimal battery performance. I appreciate your assistance in addressing my concern. Sincerely, Eleanor Chang\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 465,\n    \"ProductId\": 93,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 324,\n    \"ShortSummary\": \"LED indicator light issue\",\n    \"LongSummary\": \"Customer is having trouble with LED indicator light on stove. Assistant advised to charge for 4 hours before use. Waiting for customer to confirm if it works.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1126,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I\\u0027m embarrassed to admit that I can\\u0027t seem to get the LED indicator light on my SunChef Solar Powered Stove to illuminate. I\\u0027ve followed all the setup steps and made sure it\\u0027s in direct sunlight, but the light just won\\u0027t turn on. I feel like I must be missing something really obvious, but I can\\u0027t figure out what it is. I was really looking forward to cooking with renewable solar energy, so I hope there\\u0027s a simple solution to this. Any help or advice would be greatly appreciated. Thank you.\"\n      },\n      {\n        \"MessageId\": 1127,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the LED indicator light on the stove should illuminate when the stove is charging. It\\u0027s recommended to place the stove in direct sunlight with the reflector facing the sun and open the solar panels to expose them to sunlight. Have you tried charging the stove for at least 4 hours before its first use? This should ensure optimal performance. Let me know if this helps.\"\n      },\n      {\n        \"MessageId\": 1128,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I feel so silly! I didn\\u0027t realize I needed to charge it for at least 4 hours before using it. I\\u0027ll give it a try and let you know if it works. Thanks for your help!\"\n      },\n      {\n        \"MessageId\": 1129,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the user manual, the LED indicator light on the stove will illuminate to indicate that the stove is charging. It\\u0027s recommended to allow the stove to charge for at least 4 hours before its first use to ensure optimal performance. I hope this information is helpful. Please let us know if you have any further questions or if there\\u0027s anything else we can assist you with.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 466,\n    \"ProductId\": 157,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 325,\n    \"ShortSummary\": \"Difficulty switching to photo mode on 360X camera\",\n    \"LongSummary\": \"Customer is unable to switch to photo mode on 360X Action Camera despite following provided steps. Customer demands a better solution or refund.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1130,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I purchased the 360X Action Camera from Extremeview expecting it to work flawlessly, but I am unable to switch to photo mode. This is unacceptable considering the price I paid for this supposedly high-quality camera. I demand immediate assistance in resolving this issue or else I will be seeking a refund.\"\n      },\n      {\n        \"MessageId\": 1131,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"To switch to photo mode on the 360X Action Camera, make sure the camera is turned on by pressing the power button, and then press the mode button until the LED screen indicates photo mode. Once in photo mode, you can capture photos by pressing the shutter button. According to the manual, these are the steps to take photos with the 360X Action Camera.\"\n      },\n      {\n        \"MessageId\": 1132,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I followed the steps you provided, and I still cannot switch to photo mode on the 360X Action Camera! This is absolutely ridiculous. I expect a better solution or else I will be demanding a refund.\"\n      },\n      {\n        \"MessageId\": 1133,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"To switch to photo mode on the 360X Action Camera, press the Mode button on the front of the camera until the Photo icon is displayed on the screen. Once in photo mode, frame your shot using the 360-degree rotating lens and press the Shutter button to capture the photo. If you encounter issues, you can also access advanced photo settings through the Camera Settings menu by pressing the Menu button. I hope this helps!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 467,\n    \"ProductId\": 190,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 326,\n    \"ShortSummary\": \"Immediate Assistance Needed for UltraLight Poles 300\",\n    \"LongSummary\": \"Customer Harper Green demands immediate assistance with UltraLight Poles 300, citing dissatisfaction and concern for retail customer satisfaction. Assistant provides product details and asks for specific issues to assist further.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1134,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I demand immediate assistance with my UltraLight Poles 300! They are not performing as described and I expect a quick resolution. I am a retailer and cannot afford to have dissatisfied customers. This is unacceptable!\"\n      },\n      {\n        \"MessageId\": 1135,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Trailtrek UltraLight Poles 300 are designed to provide hikers with reliable and stable support on varying terrains. The poles are constructed with durable carbon material for lightweight yet sturdy support. They also feature adjustable height settings and ergonomically designed handles for a comfortable grip. If your UltraLight Poles 300 are not performing as described, please let us know the specific issue you are facing so that we can assist you further.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 468,\n    \"ProductId\": 107,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 159,\n    \"ShortSummary\": \"Inquiry about weight capacity and maintenance tips\",\n    \"LongSummary\": \"Customer inquiring about weight capacity, maintenance tips, and warranty coverage. Previous responses emphasized limitations and warranty details. Further guidance on proper usage and maintenance needed.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1136,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there, Team Polepro! I\\u0027m absolutely loving the UltraGrip 3000 Trekking Poles so far. These bad boys have been such a game-changer on the trails! Quick question for you - I noticed the carbon construction and ergonomic grips are mentioned in the product description, but can you tell me more about the weight capacity of these poles? Also, do you have any tips for maintaining the tips and the locking mechanism? Thanks a bunch, you guys rock!\"\n      },\n      {\n        \"MessageId\": 1137,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Dear valued customer, thank you for your positive feedback about the UltraGrip 3000 Trekking Poles. However, I must inform you that according to the product manual, the weight capacity of these poles is not specified. It is recommended to use the poles on well-maintained trails only, and they should not be used for mountaineering or under any other circumstances. As for maintenance tips, the manual advises inspecting the tips regularly and replacing them if signs of wear are present. Regarding the warranty, the poles come with a limited warranty that covers manufacturing defects only, and does not cover damages resulting from misuse, abuse, or improper handling. Any alterations or modifications to the trekking poles will void the warranty. If you have any further questions or concerns, please feel free to reach out. AdventureWorks Support\"\n      },\n      {\n        \"MessageId\": 1138,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey AdventureWorks Support! Thanks for the info, I\\u0027ll make sure to keep the trails well-maintained and won\\u0027t push the poles beyond their limits. I\\u0027ll also keep an eye on the tips and will reach out if I notice any wear. You guys have been super helpful, appreciate it!\"\n      },\n      {\n        \"MessageId\": 1139,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Dear valued customer, according to the product manual, the UltraGrip 3000 Trekking Poles are not suitable for mountaineering or any outdoor activities other than well-maintained trails. The lightweight carbon construction and ergonomic grips do not make the product safe or suitable for extreme conditions. It is advised to inspect the tips regularly and replace them if signs of wear are present. The trekking poles come with a limited warranty that covers manufacturing defects only, and any alterations or modifications will void the warranty. If you have any further questions or concerns, please feel free to reach out. AdventureWorks Support\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 469,\n    \"ProductId\": 12,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 327,\n    \"ShortSummary\": \"Troubleshooting route calculation on TrailGPS 5000\",\n    \"LongSummary\": \"Customer needs guidance troubleshooting route calculation issue on TrailGPS 5000. Asked for tips on diagnostics, battery life, and steps to take if issue persists. Pending assistance to troubleshoot issue further.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1140,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the TrailGPS 5000 and I\\u0027m having trouble with the route calculation feature. It\\u0027s not working as expected and I\\u0027m not sure what to do. I tried updating the maps, but it didn\\u0027t seem to help. Can you provide me with some guidance on how to troubleshoot this issue? I\\u0027m really relying on this device for my upcoming outdoor adventure and I need it to work properly. Any assistance you can provide would be greatly appreciated. Thank you!\"\n      },\n      {\n        \"MessageId\": 1141,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Hello, based on the user manual, before using the TrailGPS 5000, it\\u0027s important to perform a series of diagnostics to ensure the device is functioning properly. You can refer to the section \\u0027Pre-Use Diagnostics\\u0027 in the user manual for detailed instructions on performing these diagnostics. Additionally, it\\u0027s recommended to ensure that the device is fully charged and to maximize battery life by adjusting the screen brightness and enabling power-saving mode. Avoid exposing the device to extreme temperatures and excessive water exposure. If you encounter any issues after performing the diagnostics, please let us know for further assistance. Thank you!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 470,\n    \"ProductId\": 153,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 329,\n    \"ShortSummary\": \"Ineffective energy bars, return requested\",\n    \"LongSummary\": \"Customer tried using energy bars on a hike, still no boost. Attempted energy expenditure monitor test and wants to request a return. Needs assistance with return request.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Returns\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1145,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, these EcoFuels bars aren\\u0027t giving me the energy boost I expected. Can you help me figure out what\\u0027s going on?\"\n      },\n      {\n        \"MessageId\": 1146,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The EcoFuels Organic Energy Bars are designed to provide a natural and sustainable source of energy for adventurers. They are intended for use in high-intensity outdoor activities and may require specialized industrial diagnostic equipment for detailed energy output analysis. If you have any further questions or concerns, feel free to reach out to us for additional support.\"\n      },\n      {\n        \"MessageId\": 1147,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Tried using them on a hike, still didn\\u0027t feel any boost. What should I do now?\"\n      },\n      {\n        \"MessageId\": 1148,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Based on the product manual, it is recommended to conduct a detailed analysis of the energy output after using the EcoFuels Organic Energy Bars. Additionally, an energy expenditure monitor is essential for evaluating the effectiveness of the energy bars in fueling outdoor adventures. If you are still experiencing issues after conducting these analyses, you may be eligible for a return or refund. You can initiate a return at https://northernmountains.example.com/support/returns\"\n      },\n      {\n        \"MessageId\": 1149,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Tried the energy expenditure monitor, still no boost. Want to request a return.\"\n      },\n      {\n        \"MessageId\": 1150,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry, the product manual does not provide specific information about the product return policy or contacting the manufacturer. I recommend reaching out to our customer support team for assistance with your return request.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 471,\n    \"ProductId\": 62,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 330,\n    \"ShortSummary\": \"Issue with UltraBright Headlamp 500 operation\",\n    \"LongSummary\": \"Customer needs help with operating the UltraBright Headlamp 500. Assistant suggested cycling through brightness settings. Pending question: Has the customer tried cycling through brightness settings?\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1151,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the UltraBright Headlamp 500 from LumaBeam and I\\u0027m having trouble getting it to work. I feel like I must be doing something wrong because it\\u0027s not turning on at all. I tried adjusting the brightness levels and the tilt, but nothing seems to work. I\\u0027m really embarrassed to admit this, but I\\u0027m not sure if I\\u0027m missing something obvious. Can you please help me figure out what I might be doing wrong? I really want to use this headlamp for my nighttime outdoor activities. Thank you so much for your assistance.\"\n      },\n      {\n        \"MessageId\": 1152,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the UltraBright Headlamp 500 offers three brightness settings: low, medium, and high. To cycle through the brightness settings, press the power button once while the headlamp is turned on. Each press will increase the brightness level, cycling through the available options. To return to the lowest brightness setting, continue pressing the power button until the cycle starts over. Have you tried cycling through the brightness settings to see if that resolves the issue?\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 472,\n    \"ProductId\": 193,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 8,\n    \"ShortSummary\": \"Guidance needed for securing latching mechanism on cake carrier\",\n    \"LongSummary\": \"Customer Evelyn Park is seeking guidance on properly securing latching mechanism for AltitudeTech Cake Carrier by SummitChomp. Specifics on how to use the latches correctly needed. Pending response on latching mechanism guidance.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1153,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the AltitudeTech Cake Carrier by SummitChomp and I\\u0027m having trouble understanding how to properly secure the latching mechanism. I want to make sure that my high-altitude cakes are protected during transportation, so any guidance on how to use the latches correctly would be greatly appreciated. Thank you.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 473,\n    \"ProductId\": 68,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 8,\n    \"ShortSummary\": \"Cleaning instructions for Trailblazer Hiking Shoes\",\n    \"LongSummary\": \"Customer loves Trailblazer Hiking Shoes, but has concerns about safely cleaning them. Would benefit from detailed cleaning instructions to ensure proper care.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1154,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Stepquest Trailblazer Hiking Shoes and I absolutely love them! They are so comfortable and really do keep my feet dry on the trails. However, I have a question about cleaning them. I noticed that the manual mentions using a soft-bristled brush to remove dirt and debris, but I\\u0027m concerned that I might damage the material if I brush too hard. Can you provide some more detailed instructions on how to safely clean these shoes without causing any damage? I want to make sure I take good care of them for long-lasting use. Thank you so much for your help, I really appreciate it!\"\n      },\n      {\n        \"MessageId\": 1155,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, after your hike, you should clean your Trailblazer Hiking Shoes with a damp cloth to remove any dirt or debris. Let them air dry before storing them in a cool, dry place. This will help maintain the proper care for your shoes and ensure long-lasting use.\"\n      },\n      {\n        \"MessageId\": 1156,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for your response. I will try using a damp cloth to clean the shoes as you suggested. I hope this method will work well without causing any damage. I appreciate your help!\"\n      },\n      {\n        \"MessageId\": 1157,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, you should clean your Trailblazer Hiking Shoes with a damp cloth to remove any dirt or debris. Let them air dry before storing them in a cool, dry place. This will help maintain the proper care for your shoes and ensure long-lasting use. Enjoy your adventures with the Trailblazer Hiking Shoes!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 474,\n    \"ProductId\": 33,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 331,\n    \"ShortSummary\": \"Motion Detection Troubleshooting for NatureCam 4K Trail Camera\",\n    \"LongSummary\": \"Customer enjoying NatureCam 4K Trail Camera, but struggling with motion detection. Asked for tips to fix the issue. Needs troubleshooting guidance.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1158,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey there Game Guard team! I recently got my hands on the NatureCam 4K Trail Camera and I am loving it! The high-resolution footage is absolutely stunning, and the built-in night vision is a game-changer for 24/7 monitoring. However, I\\u0027m having a little trouble getting the motion detection to work properly. I\\u0027ve tried adjusting the sensitivity in the settings menu and made sure there are no obstructions, but it\\u0027s still not detecting motion. Any tips or tricks you can share to get this sorted out? Thanks a bunch! You guys rock!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 475,\n    \"ProductId\": 15,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 332,\n    \"ShortSummary\": \"Trouble charging multiple devices with AdventurePro 1000 power bank\",\n    \"LongSummary\": \"Customer had trouble charging multiple devices using USB ports. Assistant provided instructions and troubleshooting steps. Customer realized power bank wasn\\u0027t fully charged, now working perfectly. No further assistance needed.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1159,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the AdventurePro 1000 power bank from AdventureElec and I\\u0027m having some trouble getting it to charge multiple devices at the same time using the USB ports. I\\u0027ve tried plugging in my phone and tablet, but it doesn\\u0027t seem to be working as described. I\\u0027m really hoping there\\u0027s just something simple I\\u0027m missing here. Any help or advice you can provide would be greatly appreciated. Thank you!\"\n      },\n      {\n        \"MessageId\": 1160,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"To charge multiple devices using the USB ports, simply plug your electronic devices into the USB ports on the power bank using their respective charging cables, and the AdventurePro 1000 will start charging them automatically. If you\\u0027re still experiencing issues, please ensure that the devices are compatible and that the power bank is fully charged. If the problem persists, feel free to reach out to our support team for further assistance.\"\n      },\n      {\n        \"MessageId\": 1161,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027m so embarrassed - I realized that my power bank was actually not fully charged when I tried to charge my phone and tablet. I charged it up and tried again, and everything is working perfectly now. Thank you so much for your help! I\\u0027m all set now.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 476,\n    \"ProductId\": 102,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 333,\n    \"ShortSummary\": \"Inquiry about paddle stress analysis\",\n    \"LongSummary\": \"Customer inquires about stress analysis for safety and performance standards of the Voyager Kayak Paddle. Assistant provides information on meeting industry standards and emphasizes following safety guidelines. Further clarification on the stress analysis is needed from the next support agent.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1162,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Aqua Venture Voyager Kayak Paddle and I\\u0027m curious about the stress analysis mentioned in the manual. Can you provide more information on how the paddle\\u0027s stress analysis ensures safety and performance standards? Thank you for your assistance.\"\n      },\n      {\n        \"MessageId\": 1163,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Aqua Venture Voyager Kayak Paddle is designed to meet and exceed industry standards for kayak paddle safety. Before using the paddle, it is essential to ensure that all safety guidelines are followed to prevent accidents and injuries. Additionally, the paddle\\u0027s lightweight and adjustable design is intended to provide a comfortable and efficient paddling experience, aligning with the findings of the research.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 477,\n    \"ProductId\": 26,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 249,\n    \"ShortSummary\": \"Assembly assistance needed for RapidFlow Paddle\",\n    \"LongSummary\": \"Customer purchased RapidFlow Paddle from RiverTrail, but it\\u0027s not floating as expected. Asks for specific assembly instructions for better buoyancy. Needs advice before using it.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1164,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi, I just purchased the RapidFlow Paddle from RiverTrail for my kayaking trips. I noticed that it\\u0027s not floating as expected and wanted to know if there\\u0027s a specific way to assemble it for better buoyancy. I\\u0027m a bit concerned about using it in this condition, so any advice would be greatly appreciated. Thank you.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 478,\n    \"ProductId\": 98,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 334,\n    \"ShortSummary\": \"TrailBlazer GPS Watch Weather Accuracy Inquiry\",\n    \"LongSummary\": \"Customer inquires about TrailBlazer GPS Watch accuracy in extreme weather. Assistant provides information on GPS reliability, safety, and outdoor hazards. Customer acknowledges and plans to prioritize safety when using the watch.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1165,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I\\u0027m interested in the TrailBlazer GPS Watch and wanted to ask about its accuracy in extreme weather conditions. Can it still provide reliable navigation data during heavy rain or snow? Thanks!\"\n      },\n      {\n        \"MessageId\": 1166,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The TrailBlazer GPS Watch is equipped with a GPS navigation system, providing accurate location tracking for outdoor activities. However, it is important to note that the GPS feature may not always be reliable due to environmental factors such as dense tree cover, canyons, or urban settings. Outdoor navigation with the TrailBlazer GPS Watch may expose users to various terrain and environmental hazards, including but not limited to rough terrain, inclement weather, wildlife encounters, and natural obstacles. It is important for users to exercise caution and prioritize safety when venturing into outdoor environments. If you have any further questions or need assistance with anything else, feel free to ask. AdventureWorks Support\"\n      },\n      {\n        \"MessageId\": 1167,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thanks for the information. I\\u0027ll keep that in mind and make sure to prioritize safety when using the TrailBlazer GPS Watch. If I have any further questions, I\\u0027ll reach out. Thanks!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 479,\n    \"ProductId\": 176,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 169,\n    \"ShortSummary\": \"AdventurePro 4500 Outdoor Use and Charging Time Inquiry\",\n    \"LongSummary\": \"Customer inquires about AdventurePro 4500 camera\\u0027s outdoor usability and charging time. Assistant provides details about waterproof, shockproof, and 4K video capabilities, but does not answer the charging time question. Next support agent should address the charging time question.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1168,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Camera good for outdoor? How long to charge?\"\n      },\n      {\n        \"MessageId\": 1169,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The AdventurePro 4500 camera is designed for outdoor use with its waterproof and shockproof features. It can withstand water depths of up to 30 meters and is highly resistant to shocks and impacts. Additionally, the 4K video capabilities ensure that you can capture every detail of your outdoor experiences with crystal clear quality.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 480,\n    \"ProductId\": 138,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 336,\n    \"ShortSummary\": \"Difficulty Setting Up Tent in Ultimate Survival Kit 3000\",\n    \"LongSummary\": \"Customer is unable to set up the tent in the Ultimate Survival Kit 3000 despite following the manual. They demand a refund and refuse to waste any more time on the product. Next support agent can either provide further assistance for tent setup or initiate a return for the product.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1172,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am absolutely furious with the Ultimate Survival Kit 3000! I thought it was supposed to be packed with essential tools for outdoor survival, but I can\\u0027t even get the tent set up properly. The fabric is so confusing and the poles won\\u0027t fit! I demand a refund for this useless product!\"\n      },\n      {\n        \"MessageId\": 1173,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry to hear about your experience with the Ultimate Survival Kit 3000. According to the product manual, the kit is designed to provide essential tools for outdoor survival, including the tent setup. I\\u0027d like to help you resolve this issue. Can you provide more details about the specific challenges you\\u0027re facing with setting up the tent? This will help me assist you better.\"\n      },\n      {\n        \"MessageId\": 1174,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027ve tried everything in the manual, and I still can\\u0027t get the tent set up properly! It\\u0027s so frustrating. This product is a total disaster. I demand a full refund!\"\n      },\n      {\n        \"MessageId\": 1175,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry to hear that you\\u0027re still experiencing difficulties with setting up the tent. According to the product manual, here are the steps for setting up the tent: 1. Lay out the tent fabric on the ground. 2. Insert the tent poles into the corresponding color-coded sleeves on the fabric. 3. Use the provided stakes to secure the tent to the ground. 4. Place the rainfly over the tent for added protection from the elements. If you\\u0027ve followed these steps and are still having trouble, I\\u0027d be happy to assist further or initiate a return for the product. Please let me know how you\\u0027d like to proceed.\"\n      },\n      {\n        \"MessageId\": 1176,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I followed the steps in the manual exactly as you described and I still can\\u0027t get the tent set up properly! This is ridiculous and I refuse to waste any more time on this useless product. Just give me my refund already!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 481,\n    \"ProductId\": 103,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 337,\n    \"ShortSummary\": \"Need Guidance on Using Rope and Carabiner\",\n    \"LongSummary\": \"Customer Evelyn Rivera is seeking guidance on how to effectively use the rope and carabiner in the Survival Kit 5000. Response provided some general information, but specific usage instructions are still needed.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1177,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the Safetyex Survival Kit 5000 and I\\u0027m feeling a bit embarrassed about this, but I\\u0027m not sure if I\\u0027m using it correctly. I thought I would be fully prepared for any emergency, but I\\u0027m having trouble with some of the tools. Specifically, I can\\u0027t seem to figure out how to use the rope and carabiner properly. I\\u0027m worried that I might be doing something wrong and the product doesn\\u0027t work at all. Can you provide me with some guidance on how to use these items effectively? I really want to make sure that I\\u0027m ready for anything. Thank you so much for your help!\"\n      },\n      {\n        \"MessageId\": 1178,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The rope in the Safetyex Survival Kit 5000 is super versatile and can be used for a variety of tasks, while the carabiner ensures secure attachments. With these essential tools at your disposal, you\\u0027ll have the means to conquer any unexpected challenges that come your way.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 482,\n    \"ProductId\": 121,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 338,\n    \"ShortSummary\": \"Malfunctioning HydroTech 5000, Refund Requested\",\n    \"LongSummary\": \"Customer\\u0027s HydroTech 5000 isn\\u0027t functioning. Asked for refund/replacement. Assistant provided pairing and battery care instructions. Pending question: Is the device now functioning properly?\",\n    \"CustomerSatisfaction\": null,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1179,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I purchased the HydroTech 5000 from WaterRover and it doesn\\u0027t work at all! I relied on the GPS navigation and distance alert feature for my watersports activities, but it\\u0027s completely malfunctioning. I demand a refund or replacement immediately. Your so-called \\u0027high-tech\\u0027 gear is a complete disappointment and has caused me nothing but trouble.\"\n      },\n      {\n        \"MessageId\": 1180,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, to pair your smartphone with the HydroTech 5000, follow these steps: 1. Make sure your HydroTech 5000 is powered on and within range of your smartphone. 2. Open the WaterRover app on your smartphone and select \\u0022Pair Device\\u0022 from the menu. 3. On your HydroTech 5000, press and hold the \\u0022Pair\\u0022 button for 5 seconds until the LED indicator starts blinking. 4. Your smartphone should now detect the HydroTech 5000. Select it from the list of available devices to complete the pairing process. Once paired, you can use the WaterRover app to stay connected, share your location with friends, and even send messages while out on the water. Additionally, the manual mentions that the HydroTech 5000 includes a battery level indicator located on the front panel, allowing you to monitor the remaining battery percentage. It\\u0027s important to properly care for the battery by fully charging it before each use and avoiding overcharging. If you won\\u0027t be using the device for an extended period, it\\u0027s best to store it with the battery partially charged to maintain its longevity.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 483,\n    \"ProductId\": 160,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 339,\n    \"ShortSummary\": \"Profile setup issue with unique \\u0027age\\u0027 entry\",\n    \"LongSummary\": \"Customer having trouble setting up profile, trying to use favorite hiking spot as \\u0027age\\u0027. Assistant provided instructions to enable Bluetooth and pair devices for additional features. Customer still needs assistance troubleshooting the issue.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1181,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Trailblazer GPS Navigation Device from Geotrack and I\\u0027m having trouble setting up my profile. I assumed that entering my favorite hiking spot as my \\u0027age\\u0027 would enhance my navigation experience, but it doesn\\u0027t seem to be working. Can you help me with this? Thanks so much!\"\n      },\n      {\n        \"MessageId\": 1182,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the user manual, you need to enable Bluetooth on your smartphone and the Trailblazer GPS Navigation Device. Then, open the Geotrack app and follow the on-screen instructions to pair the two devices. Once paired, you can access additional features such as live tracking, route sharing, and notifications on your smartphone. If you are still experiencing issues, please refer to the troubleshooting section in the user manual for assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 484,\n    \"ProductId\": 191,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 30,\n    \"ShortSummary\": \"Questions about lantern storage\",\n    \"LongSummary\": \"Customer is pleased with product but has questions about storing in damp, dark places. Wants more info on why it\\u0027s important and if it affects performance.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1183,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Luminex 5000 Lantern from Flash Bright and I am really impressed with its 360-degree illumination and multiple brightness settings. However, I noticed in the manual that it mentions avoiding storing the lantern in a damp, dark place. I was wondering if you could provide more information on why this is important and if it could potentially affect the lantern\\u0027s performance in the long run. Thank you for your assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 485,\n    \"ProductId\": 82,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 64,\n    \"ShortSummary\": \"Dietary options inquiry for SurvivalPro Emergency Kit\",\n    \"LongSummary\": \"Inquiry about dietary options in SurvivalPro Emergency Kit. Customer asked about nut allergies. Need confirmation of nut-free options.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1184,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear Essential Tech, \\n\\nWe are a retailer stocking your SurvivalPro Emergency Kit and have been receiving inquiries from our customers regarding the dietary considerations of the emergency rations. Can you provide us with more detailed information about the specific dietary options available in the kit? This will help us address our customers\\u0027 concerns and provide them with accurate information. Thank you for your assistance. \\n\\nSincerely, \\nEvelyn Chen\"\n      },\n      {\n        \"MessageId\": 1185,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the emergency rations included in the SurvivalPro Emergency Kit are designed to provide essential nutrients and energy for a variety of dietary needs. From gluten-free to vegetarian options, we\\u0027ve got you covered! \\uD83E\\uDD66\\uD83C\\uDF7D\\uFE0F\"\n      },\n      {\n        \"MessageId\": 1186,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information provided. Could you please also confirm if the emergency rations in the kit cater to individuals with nut allergies? This is an important consideration for our customers with dietary restrictions. Your assistance is greatly appreciated.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 486,\n    \"ProductId\": 6,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 340,\n    \"ShortSummary\": \"Malfunction due to cleaning method\",\n    \"LongSummary\": \"Customer believes cleaning method caused malfunction, seeks troubleshooting and alternative cleaning solutions. Pending response on how to resolve and prevent future issues.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1187,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"To whom it may concern, I recently experienced a malfunction with my ExcavaTrek 3000 and I believe it may be related to the damp cloth cleaning method suggested in the manual. Based on my technical expertise, I suspect that the accumulation of dirt or debris has caused damage to the tool\\u0027s components, resulting in its breakdown. I would appreciate your guidance on how to troubleshoot and repair the ExcavaTrek 3000, as I am eager to continue utilizing its advanced excavation capabilities. Additionally, I would be interested in learning about any alternative cleaning methods that may be more suitable for maintaining the tool\\u0027s pristine condition. Your prompt assistance in resolving this matter would be greatly appreciated. Thank you in advance for your attention to this technical issue.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 487,\n    \"ProductId\": 175,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 64,\n    \"ShortSummary\": \"Weight inquiry for SonarPro Portable Fish Finder\",\n    \"LongSummary\": \"Customer needed the exact weight of the SonarPro Portable Fish Finder before purchasing. Assistant suggested contacting the manufacturer, who provided the information. Customer requests the ticket to be closed.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1188,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I need to know the exact weight of the SonarPro Portable Fish Finder. It\\u0027s very important for me to have this information before making a purchase decision. Thank you.\"\n      },\n      {\n        \"MessageId\": 1189,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The SonarPro Portable Fish Finder is designed for portability and is lightweight and compact, making it easy to transport and use in various fishing environments. However, I couldn\\u0027t find the exact weight in the manual. I recommend contacting the manufacturer for this specific information. You can find their contact details in the user manual.\"\n      },\n      {\n        \"MessageId\": 1190,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I contacted the manufacturer as suggested and they provided the exact weight of the SonarPro Portable Fish Finder. Thank you for your assistance. Please close the ticket.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 488,\n    \"ProductId\": 94,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 341,\n    \"ShortSummary\": \"Immediate Replacement/Refund Demand\",\n    \"LongSummary\": \"Customer demands immediate replacement or refund, dismisses user manual advice.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1191,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I just purchased the TrailBlazer Multi-Tool and I expect it to perform as described. I better not have any issues with the saw or bottle opener, or I\\u0027ll be demanding a replacement. I don\\u0027t want to deal with any hassle, so make sure this product lives up to its promises.\"\n      },\n      {\n        \"MessageId\": 1192,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the user manual, you can reach Wild Tech Customer Support by phone at 1-800-555-1234 or via email at support@wildtech.com. Please have your product information and details of the issue ready when contacting them to ensure a quick and efficient resolution to your concern. If you encounter any issues with your TrailBlazer Multi-Tool that cannot be resolved through the troubleshooting tips provided in the manual, feel free to contact Wild Tech Customer Support for assistance. Their team is available to help with any questions or concerns regarding the use and maintenance of the multi-tool.\"\n      },\n      {\n        \"MessageId\": 1193,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I expect Wild Tech Customer Support to resolve this issue immediately. I followed the troubleshooting tips in the manual and still can\\u0027t get the saw to work properly. I demand a replacement or a full refund for this inconvenience.\"\n      },\n      {\n        \"MessageId\": 1194,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the user manual, the saw must be carefully extended from the multi-tool and steady pressure should be applied while cutting. Always be aware of your surroundings and potential hazards. As for the bottle opener, the manual explains that you should simply unfold it from the multi-tool and position it under the bottle cap, then apply gentle pressure to pop the cap off. If you are still experiencing issues, you may consider contacting Wild Tech Customer Support for further assistance.\"\n      },\n      {\n        \"MessageId\": 1195,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I don\\u0027t care about the user manual. I bought this Multi-Tool expecting it to work perfectly out of the box. I demand a replacement or a full refund immediately. I don\\u0027t have time to keep troubleshooting or contacting support, this is unacceptable.\"\n      },\n      {\n        \"MessageId\": 1196,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the user manual, the TrailBlazer Multi-Tool is designed to be your ultimate camping companion, and it includes a variety of essential gadgets, such as a sharp knife, a saw, and a bottle opener. If you encounter any issues with your TrailBlazer Multi-Tool that cannot be resolved through the troubleshooting tips provided in the manual, you can contact Wild Tech Customer Support for assistance. Their contact information is available in the manual.\"\n      },\n      {\n        \"MessageId\": 1197,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I don\\u0027t care about the user manual. I want a replacement or full refund immediately. This is unacceptable and I demand a swift resolution to this issue.\"\n      },\n      {\n        \"MessageId\": 1198,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the user manual, if the saw or bottle opener on the TrailBlazer Multi-Tool becomes difficult to operate or malfunctions, you should refrain from using it and seek professional assistance. If the saw blade becomes dull or damaged, it can be replaced by loosening the screws that hold it in place, removing the old blade, and inserting a new one. For the bottle opener, if it becomes loose or ineffective, you can use the included screwdriver to tighten the screws holding it in place. If the problem persists, you may contact Wild Tech Customer Support for further assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 489,\n    \"ProductId\": 56,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 342,\n    \"ShortSummary\": \"Inquiry about cold weather suitability for sleeping bag\",\n    \"LongSummary\": \"Customer inquiring about suitability of Naptime 5000 Sleeping Bag for cold weather camping. Assistant provided tips for maximizing insulation. Pending satisfaction confirmation.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1199,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello there! I just stumbled upon the Naptime 5000 Sleeping Bag from Slumberpeak and I am absolutely thrilled about it! The water-resistant feature is just what I need for my upcoming camping trip. Can you tell me if this sleeping bag is suitable for cold weather camping? I want to make sure I stay warm and cozy out there in the great outdoors. Thanks a bunch!\"\n      },\n      {\n        \"MessageId\": 1200,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Naptime 5000 Sleeping Bag from Slumberpeak is designed to keep you warm and cozy during your outdoor adventures. With its water-resistant and lightweight design, this sleeping bag is easy to pack and carry with you on any camping trip. To maximize the insulation, be sure to zip up the bag completely and pull the hood tightly around your head. This will ensure that you stay warm and comfortable throughout the night, even in cold weather conditions. It\\u0027s the perfect choice for your upcoming camping trip!\"\n      },\n      {\n        \"MessageId\": 1201,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Oh wow, that sounds amazing! I\\u0027ll definitely make sure to zip up the bag and pull the hood tightly around my head to stay warm. Thanks so much for the helpful tips! I can\\u0027t wait to try out my new Naptime 5000 Sleeping Bag on my camping trip. You\\u0027re the best!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 490,\n    \"ProductId\": 71,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 343,\n    \"ShortSummary\": \"Signal Booster 2000 ventilation and RF exposure inquiry\",\n    \"LongSummary\": \"Customer seeks guidance on Trailcom Signal Booster 2000 ventilation and RF exposure requirements. No further issues encountered. Additional monitoring and support if needed.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1204,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear Support Team, I recently purchased the Trailcom Signal Booster 2000 and I am encountering some issues with signal strength. I have read that the device is designed to boost signal strength for off-grid communication, but I seem to be experiencing heat generation during prolonged use at maximum signal boosting levels. Can you provide me with some guidance on how to ensure proper ventilation for the device to prevent overheating? Also, I am curious about the RF exposure requirements and how to maintain a minimum distance of 20 cm between the device and the body. Any information on this would be greatly appreciated. Thank you.\"\n      },\n      {\n        \"MessageId\": 1205,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Trailcom Signal Booster 2000 is designed to boost signal strength for off-grid communication. To prevent overheating, ensure the device has proper ventilation and is not covered during use. The device complies with all relevant regulatory standards, including FCC regulations, to ensure minimal interference with other communication systems.\"\n      },\n      {\n        \"MessageId\": 1206,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information on ensuring proper ventilation for the Trailcom Signal Booster 2000. I have made adjustments to the device\\u0027s placement to allow for better airflow and will monitor the heat generation during prolonged use. As for the RF exposure requirements, could you provide more specific details on maintaining a minimum distance of 20 cm between the device and the body? I want to ensure that I am following the guidelines correctly. Thank you.\"\n      },\n      {\n        \"MessageId\": 1207,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Trailcom Signal Booster 2000 complies with all relevant regulatory standards, including FCC regulations, to ensure minimal interference with other communication systems. It is also designed to operate within the approved frequency bands and power levels. As for the minimum distance between the device and the body, the user manual did not provide specific details regarding this requirement. However, it is recommended to maintain a minimum distance of 20 cm between the device and the body for RF exposure. If you have further questions or concerns, feel free to reach out to us. Thank you.\"\n      },\n      {\n        \"MessageId\": 1208,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information on maintaining a minimum distance of 20 cm between the Trailcom Signal Booster 2000 and the body. I have adjusted the device placement to ensure this distance is maintained. I will continue to monitor the device\\u0027s performance and will reach out if I encounter any further issues. Thank you for your assistance.\"\n      },\n      {\n        \"MessageId\": 1209,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Based on the user manual, the Trailcom Signal Booster 2000 complies with all relevant regulatory standards, including FCC regulations, to ensure minimal interference with other communication systems. It is designed to enhance signal strength for off-grid communication in remote areas.\"\n      },\n      {\n        \"MessageId\": 1210,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I have monitored the device\\u0027s performance since making the adjustments, and I am pleased to report that I have not encountered any further issues with heat generation or signal strength. Thank you for your assistance in providing the necessary guidance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 491,\n    \"ProductId\": 4,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 344,\n    \"ShortSummary\": \"Maintenance and Water Source Concerns\",\n    \"LongSummary\": \"Customer is concerned about the maintenance and water source requirements of the kit. Wants to know if the kit is worth purchasing.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1211,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I can\\u0027t believe the portable water filter needs so much maintenance! How am I supposed to keep track of all this in an emergency situation? And now I have to worry about finding a clear, flowing water source too? This is ridiculous. I need to know if this kit is really worth it before I make a purchase.\"\n      },\n      {\n        \"MessageId\": 1212,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the portable water filter should be thoroughly cleaned and allowed to dry completely after each use. The filtration membrane should also be inspected for damage or signs of wear. Additionally, the water purification tablets should be stored in a cool, dry place and their expiration date should be checked regularly. This kit includes a high-performance water purification system to ensure access to safe drinking water in emergency situations.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 492,\n    \"ProductId\": 50,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 345,\n    \"ShortSummary\": \"Inquiry about Thirsttrek HydroPack durability for outdoor use\",\n    \"LongSummary\": \"Customer inquiring about durability of Thirsttrek HydroPack for rugged outdoor conditions. Seeking performance and reliability insights for long hikes and outdoor adventures. Pending response on product\\u0027s endurance.\",\n    \"CustomerSatisfaction\": 5,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1213,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I\\u0027m considering purchasing the Thirsttrek HydroPack Hydration System for my upcoming hiking trip. Can you provide information on the durability of the reservoir and tubing, especially in rugged outdoor conditions? I want to ensure that it will withstand the demands of long hikes and outdoor adventures. Any advice or insights on its performance and reliability would be greatly appreciated. Thank you.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 493,\n    \"ProductId\": 86,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 133,\n    \"ShortSummary\": \"Info on using multitool kit\",\n    \"LongSummary\": \"Customer purchased SOS Multitool Kit and needed info on using knife and fire starter. Customer reviewed user manual and figured it out. No further assistance needed.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1214,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I recently purchased the SOS Multitool Kit from Survive All and I\\u0027m not sure if it\\u0027s working properly. Can you provide me with more information on how to use the knife and fire starter? I want to make sure I\\u0027m prepared for any survival scenario.\"\n      },\n      {\n        \"MessageId\": 1215,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Congratulations on your purchase of the SOS Multitool Kit from Survive All! The user manual provides detailed instructions on how to use the knife and fire starter effectively. For the knife, it is important to avoid using it for non-emergency purposes to prevent injury. To start a fire using the fire starter, follow the simple steps outlined in the manual.\"\n      },\n      {\n        \"MessageId\": 1216,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thanks for the information. I\\u0027ll review the user manual and see if I can figure it out myself. If I have any further questions, I\\u0027ll reach out again.\"\n      },\n      {\n        \"MessageId\": 1217,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The SOS Multitool Kit is designed to be compact and lightweight, making it easy to carry and perfect for outdoor adventures. It includes a knife, fish scaler, and hook remover, among other tools. For detailed instructions on using the knife and fire starter, please refer to the user manual.\"\n      },\n      {\n        \"MessageId\": 1218,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I reviewed the user manual and was able to figure out how to use the knife and fire starter. Thanks for your help.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 494,\n    \"ProductId\": 70,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 64,\n    \"ShortSummary\": \"Guidance needed for measuring USB output voltage and current\",\n    \"LongSummary\": \"Customer needs guidance on measuring USB output voltage and current. Assistant provided instructions from the manual. Customer acknowledged and will follow the instructions.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1219,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hi there, I recently purchased the Juice Junkie Solar Power Bank 10000mAh and I\\u0027m having trouble understanding how to measure the USB output voltage and current. I want to make sure I\\u0027m using it correctly and getting the most out of it. Can you please provide some guidance on how to do this? I want to ensure that all my outdoor electronics stay charged while on the go. Any help would be greatly appreciated. Thank you!\"\n      },\n      {\n        \"MessageId\": 1220,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, to measure the USB output voltage, you should perform the voltage measurement on each USB port of the power bank to ensure consistency in output across all ports. Additionally, to measure the USB output current, you should follow the steps provided in the manual.\"\n      },\n      {\n        \"MessageId\": 1221,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Oh gosh, I\\u0027m so sorry! I completely overlooked the steps in the manual. I\\u0027ll make sure to follow the instructions to measure the USB output voltage and current. Thank you for pointing me in the right direction!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 495,\n    \"ProductId\": 173,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 126,\n    \"ShortSummary\": \"Difficulty with Heating Technology\",\n    \"LongSummary\": \"Customer has difficulty with heating technology, tried troubleshooting steps without success. Requires immediate assistance or replacement. Next agent should offer advanced troubleshooting options or replacement process.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1222,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I\\u0027m really not happy with the heating technology in my TechShell Smart Jacket. I\\u0027ve checked the battery level and connections, just like your manual says, and it\\u0027s still not working properly. I expect this kind of high-tech outerwear to actually do what it\\u0027s supposed to. I need this fixed as soon as possible, or I\\u0027ll be requesting a replacement. This is just not acceptable.\"\n      },\n      {\n        \"MessageId\": 1223,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The heating technology in your TechShell Smart Jacket is activated by locating the power button and holding it to turn on the heating system. If checking the battery level and connections does not resolve the issue, please contact our customer service team for further assistance.\"\n      },\n      {\n        \"MessageId\": 1224,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I already tried holding down the power button to turn on the heating system, and it still doesn\\u0027t work. I need this fixed ASAP, and I\\u0027m not happy with the response I\\u0027ve received so far.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 496,\n    \"ProductId\": 31,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 346,\n    \"ShortSummary\": \"Excessive smoke and soot despite troubleshooting\",\n    \"LongSummary\": \"Customer has followed troubleshooting steps and contacted support team but still experiencing excessive smoke and soot. Customer demands replacement or refund. Next agent should provide further assistance or initiate process for replacement/refund.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1225,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I purchased the WanderStove Nomad Camping Stove expecting a top-of-the-line off-grid cooking solution. However, I am unable to get the stove to work without excessive smoke and soot. I demand a replacement or a refund for this faulty product. I expect a prompt response and a satisfactory resolution to this issue.\"\n      },\n      {\n        \"MessageId\": 1226,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The WanderStove Nomad Camping Stove is specifically designed to meet the needs of campers, hikers, and adventurers, ensuring that they can enjoy delicious meals even in remote locations. With its innovative features and portability, WanderStove sets the standard for off-grid cooking appliances. If the issue persists or cannot be resolved, please contact our customer support team for further assistance. Remember to always follow proper safety precautions when troubleshooting any issues with the WanderStove Nomad Camping Stove.\"\n      },\n      {\n        \"MessageId\": 1227,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I followed the safety precautions and tried troubleshooting the WanderStove Nomad Camping Stove again, but I am still experiencing excessive smoke and soot. This product is not living up to the standard you claim and I demand a replacement or a refund immediately.\"\n      },\n      {\n        \"MessageId\": 1228,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, to address excessive smoke or soot, check the air vents on the stove for any blockages. If using wood as a fuel source, ensure it is dry and well-seasoned to minimize smoke. If the issue persists, you may need to contact our customer support team for further assistance. Additionally, in case of a warranty claim, please contact our customer service team at support@wanderstove.com.\"\n      },\n      {\n        \"MessageId\": 1229,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I have checked the air vents on the stove and made sure the wood fuel is dry and well-seasoned, but I am still experiencing excessive smoke and soot. This is unacceptable and I demand a replacement or a refund immediately.\"\n      },\n      {\n        \"MessageId\": 1230,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Based on the user manual, the solution for excessive smoke or soot is to check the air vents on the stove for any blockages and to ensure the wood fuel is dry and well-seasoned. If you have already followed these steps, please contact our customer support team for further assistance.\"\n      },\n      {\n        \"MessageId\": 1231,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I have contacted the customer support team as suggested, but I am still experiencing excessive smoke and soot with the WanderStove Nomad Camping Stove. This is unacceptable and I demand a replacement or a refund immediately.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 497,\n    \"ProductId\": 91,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 347,\n    \"ShortSummary\": \"WeatherShield Pro Jacket performance issue\",\n    \"LongSummary\": \"Customer is dissatisfied with the WeatherShield Pro Jacket\\u0027s performance in light drizzle, seeking refund, replacement, or repair. Assistant provided info on ASTM D6413 standards and the warranty for defects.\",\n    \"CustomerSatisfaction\": 1,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1232,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I am so frustrated with the WeatherShield Pro Jacket! It\\u0027s supposed to be waterproof, windproof, and breathable, but it couldn\\u0027t even keep me dry in a light drizzle! I spent good money on this jacket, and now I\\u0027m soaked and freezing. I need to know if there\\u0027s something wrong with it or if it\\u0027s just not suitable for real weather conditions. This jacket is not living up to the \\u0027new standard for performance\\u0027 that Stormguard claims. I want a solution to this problem, whether it\\u0027s a refund, replacement, or repair. I expect better quality and performance from a supposed advanced weatherproof jacket.\"\n      },\n      {\n        \"MessageId\": 1233,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The WeatherShield Pro Jacket is constructed to meet the waterproofing standards set by ASTM D6413. This standard specifies the testing method for determining the waterproofing performance of textiles, including resistance to water penetration. Additionally, the jacket is covered by a limited warranty for a period of 2 years from the date of purchase. This warranty covers defects in materials and workmanship under normal use. Stormguard will repair or replace, at its option, any WeatherShield Pro Jacket that proves to be defective within the warranty period. If you believe your jacket may be defective, please initiate the return process at https://northernmountains.example.com/support/returns. We apologize for any inconvenience caused and are committed to ensuring your satisfaction with our products.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 498,\n    \"ProductId\": 4,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 348,\n    \"ShortSummary\": \"Radio malfunction in survival kit\",\n    \"LongSummary\": \"Customer reported radio not working in the Emergency Survival Kit. Need assistance with troubleshooting and fixing the issue.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Complaint\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1234,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Radio not working. Need help.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 499,\n    \"ProductId\": 80,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 349,\n    \"ShortSummary\": \"Reelmaster sending technician to fix Stealth 5000 Fishing Reel\",\n    \"LongSummary\": \"Reelmaster\\u0027s technical support will send someone to check Stealth 5000 Fishing Reel tomorrow. Customer reports technician came and fixed the reel. Needs no further assistance.\",\n    \"CustomerSatisfaction\": 7,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1235,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hey, my Stealth 5000 Fishing Reel isn\\u0027t working right. Can you fix it?\"\n      },\n      {\n        \"MessageId\": 1236,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Stealth 5000 Fishing Reel is designed for smooth and efficient operation, ensuring that you can handle any fish with ease. Have you tried adjusting the drag setting to maximize control?\"\n      },\n      {\n        \"MessageId\": 1237,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Tried adjusting drag setting. Didn\\u0027t work.\"\n      },\n      {\n        \"MessageId\": 1238,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m sorry to hear that you\\u0027re experiencing issues with the Stealth 5000 Fishing Reel. Based on the user manual, I recommend reaching out to Reelmaster\\u0027s technical support for assistance with troubleshooting and repairs. Here is the contact information for technical support: [Reelmaster Technical Support](https://www.reelmaster.example.com/support/technical) Please let us know if you need further assistance.\"\n      },\n      {\n        \"MessageId\": 1239,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Tried contacting Reelmaster\\u0027s technical support. They said they\\u0027ll send someone to check it out tomorrow.\"\n      },\n      {\n        \"MessageId\": 1240,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"I\\u0027m glad to hear that Reelmaster\\u0027s technical support will be sending someone to check it out tomorrow. If you have any further questions or need additional assistance, feel free to reach out to us. We\\u0027re here to help!\"\n      },\n      {\n        \"MessageId\": 1241,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Technician came and fixed the reel. Works fine now. Thanks!\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 500,\n    \"ProductId\": 130,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 351,\n    \"ShortSummary\": \"Bluetooth pairing PIN problem\",\n    \"LongSummary\": \"Customer is unable to complete Bluetooth pairing because a PIN is required. Support should determine the default bluetooth pairing PIN.\",\n    \"CustomerSatisfaction\": 4,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1251,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hallo. Ich habe den WildBeat Bluetooth-Lautsprecher gekauft, kann ihn aber nicht mit meinem Telefon koppeln. Es wird nach einem PIN-Code gefragt, den ich aber nicht kenne. Was ist die PIN?\"\n      }\n    ]\n  }\n]"
  },
  {
    "path": "seeddata/test/categories.json",
    "content": "[\n  {\n    \"CategoryId\": 1,\n    \"Name\": \"Bike Helmets\",\n    \"NameEmbeddingBase64\": \"\\u002BZSwv7zpbD/2E5k\\u002B3lxgv7b/D8BSGLU/tvVaP/iZkT96EpO/ARzQP9gTBr8PjSLAKIW3P/7GST89\\u002B/Q/tKpgPv\\u002B4CkA3CNo/PpMyP1gWVT8qZLi/ZRcHPtIw8T5weMG8hd\\u002BMPx95iz/o0Lm/5FDbP0I7XD8YBzHAjPpTvvZrrD4c4SC\\u002BagjXv6tujb7nxMa\\u002BHl2hv0jq1D7VMem/DIF4P5rKpD8mdAZAeuxFv/Smgb6Dr/w/KuvHP\\u002BqjBT/uTKW/DK3PP2RPD8B4BLo/eCB0v\\u002B002z/3lh/AbDWlv1joPD\\u002B\\u002BSN\\u002B/cB12P8xxMT9v/aU/rgOuv/F0wD9TwWDA0IThP4jgPj9UEWJA78MuvtYS\\u002B77SNsy\\u002BtHMTQKO1mr5VT\\u002BW\\u002BqoylP13lrr3yZ0i\\u002Bwr8TPyQjIj\\u002BKOh/AkuimvUIEB8BXvre/5sUCwFgGGT9GKUa\\u002Bbz5bP0FMyD4loBS/ZKL4vkzNvD/QRg5ApI5Nv9FhV7\\u002BACcs/zkivvsBD27/tP3U/vr\\u002BOPQheRb/HAQC9s3j0QLZqrT1w2EK8R2EDv2OkoL4KX\\u002BA/pcP5v92IqD/3K8m/efuGv7ZkrT\\u002BODw5AQMwbPwrxkj8yEBC9TUJGv8JNnz9kQMW/K4Z2P5M8bL\\u002BMN7o/rg\\u002BavwAEpr7lwUU/fX2hvqT3GD8AU6E8b4xLP5D3NUAf3aQ/mQS\\u002BPy49sz9Ntkw/kDEZvEQng79JjYQ9S4\\u002BQv2Q6fj728gq/CEwhv1orxD8vaAQ\\u002BpWZZv0Cx3z\\u002B4rDHAbDtDv4UvAb9F2k\\u002B/wLrouzM2n79un6K\\u002BIlQIvuyK5D7SFoK/kApaP4sx6j40L7w/vkW1vnzYOD8M0Ae\\u002BRUl0P9ZH4bw4k7w\\u002BfAFKP/BN4z/TnBC/XKg9wJgyHz8aWkG/Kh53PlThiL9KZK\\u002B/TkbZPrnB\\u002BT4QQZs/ar8eQC8rgz8klAzA9C\\u002BBPkqD6L8qrc8\\u002BnUSMP/1vz78rr/y/jAryPXAbyD45Ncu/TBJMwMipnL2cgC8/2FTWP4rNzb8glMa8u/icv9izZD4UqNS9UgCVvfydGsDlcrW/wBWJOwJMHT/0MgVAPhFSv376uj6WmBg/tLuNvV9iej/2fKO/2iwOwDcRij\\u002B/yio\\u002B/Bzcvp33AsC3mA8/eNQEP28tTb4074y\\u002B7fzbvt/rnz9jA4C/Bprhv5Ri1D7595C/waGav3DHj8DDZqm/2smiP3sq\\u002BT\\u002B0sNo/oKGOP5ymuD9\\u002B0sI/ifVYP3rafL/YAAdA6uSMvzUvCcCclte/flqzvwyavz8APXo/ufKMvyzh0L8Tk6G/Hki9vlhSsj8zO0/AzNpiv9SIe74Na7U\\u002BOd\\u002BTQOiFjb1Ktze\\u002BeOdlPKLfFsCGTy6/di3ZPURtF8A76JQ/cGZAv/8Q6T7w4b2/zSmHv1wMgr/6K/8\\u002BzE/BP67RbL\\u002BPTwLA3rdfv/sLTT9G1gq/fln\\u002BPbknIj9GWee\\u002BQJYOv6Xnmj41uqg/DCozP3UGKT9F00PA3sRTvzzCAcCBFxA/JvceP3ze/TzhrEk/oOCXv8Qp6b8kHsw/KsiuP4SR2b7uVRPAGLV/P7Ie2r4HqZC/kr7qP\\u002BhrxD7SsOS\\u002Bk9ZJP\\u002BgbBT/8jKY/WXWove47G0D3d4s/cub3PqRUCr/82S2\\u002Bb3toP7Ybh77jL8k\\u002Brkb6vbUkkb7RtIK\\u002B2B2evr7Ffj9o8fK9RXmSPlFTOL/6qvY/2gIVv7D/zMDnjJs\\u002B5K9Yv0lQNz\\u002BLb1m/5sbDvVirCUAq1BBAJilbvrRT9L6MDoG/y8IMQAaNfz8Kag2\\u002BfUCVP2I6wT//jQpA2pV7vyRPpz8cEXk/XJMrwP7lhz8kYFVAGBXPv8y3J0AWpOw\\u002BC\\u002Brsv4wLcb5fX1u/QQV4P6CoRT3YGFS\\u002B1aylP/4Cu77GGxfAnPY1PlRXjL8Y9S4/1eRXPo2oIT\\u002BuPYk/xWprv/\\u002BXJD5OJtE/QpreP67su70ylRPAGO\\u002BfvFMO\\u002BT5APcO7pWyFv789Mb\\u002BktArAQvr3PhJazT8SSoy/2I2rP8UnOj9k3Eu/qtKGv20AjT9czgnAVk06wDoz5z\\u002BEknO/\"\n  },\n  {\n    \"CategoryId\": 2,\n    \"Name\": \"Backpacks\",\n    \"NameEmbeddingBase64\": \"hKlrvxRHYb5OqXI/qGP5vnYznT8Ul7o8/nHKP95CRT\\u002BPqrK/Dhm3vvlht76A4OG/1l1av3123T8BYeQ/5D5OvthnFkBqxuw\\u002BTgt1v2galD/f4mQ/pOVjv7fNQr/KpVO/z\\u002Bjcv4O3oL7XfY4/bEVuv6BLsL\\u002BIBlrA1VaQPQZflL9LO1y/Fz5xv01mur74B/I/d4XQP2gWLj8865m\\u002Bw9MaPswZpb2kQ9E/xKIgvw\\u002BN0r7GfWo/NL6pv\\u002BYJS78vz6O/ACSlP2FMk7/g6Kq7D6PMvttxBz83IlK/1DqOvwrR2z882TQ/xuB8P2Yc\\u002Bj7wYZK9rO6NP6tNm75mr3vASsD4P1p5ej9TgE0/ETd/v1W4DEABCRJAnJW1PvEz377Tz5g\\u002BZp6XPyJCIUAzTjc/qlJAP7gLlz9c1bc\\u002BrEU0verdob\\u002BbpFS/TbEpvSKBxz/GvWk/PPUsP\\u002BNQHz4xPM2\\u002BZfD2v6AHsz4hgEm/PECZvSg5u7\\u002BCroM/p8iWP1rzZMAIl6y/\\u002BiSOvminPD7\\u002BQrA/8GbjQIAElL/4TQtAGuBeQNTAlL08bwm\\u002Br1dBwEOrjT8CxYe/awJxv1b5pD\\u002Bz0Fg/wmCTv3TpID8Ufrm\\u002B9UCuvvRumr75Sqi\\u002BgvdBPzXbf78AFvs/oiUmwOPS6b3wiBNAHHNuv1R2Zr6M\\u002B1U\\u002BvqSPP9zs1z9oEfa\\u002BkOrvPzRjrr44YxtAZmvavqbKq7\\u002BkrI29xVvoPpGnRL\\u002BdHDm/CAlOPBnPhj92HYO\\u002BXiLePxOBhz9uMVfAnuUcv0gyMD7w4tg9St9Dv1Qmlb8AJUc7gdGmP\\u002B\\u002BGjz7dhFw/iDZgv1pnsL46S7s//PUHPzoJi76AVCM/iQlmP3Aln78j1Ya/ZmM/vvBiQL417ck\\u002Bw/UPwKwRED6u\\u002BXK/fT73PgqM2b0hRBo\\u002BoPjdve7CKz9nsAZAIP3/P\\u002BoOFL9yuv\\u002B/2HqMu8yX9r80Ce6\\u002BLI6lP8GMlb/vn1y/HShDvigBRT/8YXO\\u002B\\u002B\\u002B\\u002Buv5\\u002BH1b/cAvc/4NpaQA8RlD889iu/7CLdP7FA2b9Oma6\\u002BOAVbP5wyrr9ekdS\\u002BTWmMPewrW7/mPB5AJVrGvoQwOr8AKxC77wQGQCSasz\\u002Bkn\\u002Bk\\u002BrB\\u002BEv\\u002BJHrb5Ahny/4HMxP7GOdj1eA6w9Hq6/vziYKr80T4C/JSC1P/ZZnz\\u002BNxw/AYDd/vSVdRL/wYEzAXZNbv7tVyMD6KVs/UljvP5VyNz/i7F2\\u002BISmOPlREsT9MbwM/cHZdvunJmz8qMRBALILRv2667D6sLAxAnFQXvfLp1D8Tac8\\u002BlIgQvwyrN7\\u002BsA62\\u002B4urqvUqj7T/6F26/rPsMv6YCjr\\u002BAx7W9efGJQPShmz\\u002BV/Q0/FJ/ZvuuhVz84CQ8/7SFEPzetSMBEJOo/5N7QPvyD374KVRrAhdpSP5yoMr9WV1G/J28iQNvHA74muca/cSuPv3RvqD36g/W/Ri/Zv534C78yJ5y\\u002BfdOwv2OshT4QhNM/kBDJvzbMaj7i456/4rB8vREVMr\\u002BTGqi//KAuP/Zqmr/0/pi/JuCRvyuU8r7O/h8\\u002BwJa1OpyPQr9ZpSq/AkKlPhe2\\u002BT1IDtu\\u002BVq6tP0iLOL8yzKy\\u002BUo3gP17vKr\\u002BW5a8/3u2ePyz8qD\\u002BAlEy/oOI\\u002Bvhy1oj4aTZi/npmOv4xGUD/n6YM/iK0xv7wV775kg749J\\u002BVLvtQDoz7bCiA/F01pv6xPpb7cFmhAQWq1vkylysBgBpS\\u002BaGNCvQrdZL/hrB2/OMylPXi6YD9sK6M/fhN6P0ljiD\\u002BWebw/vekVQPAMYT9j5yC/MGdYP4ry4z4WKQFAPOe2vZZQ1z\\u002BOm4C/fIOVv8jnKT3vUGZA9tQYveGeWj\\u002BuoxZAhFItvhP\\u002Bpb4V7wG//JTEPTf1sj9e\\u002BQi/Bv0cQFCIe79KoTy/LinMPx94E8AOjr8\\u002BBJGJPS3Oj751Mf09cDWJvz17Q8BkBtO9i5oZP8IemL84wE0\\u002BhDfIv02UUz94XPK\\u002B6h7aPmkfzz7sdum/GCRpPfnejz/IR3Y\\u002BRg6Iv6DZNr\\u002BEEWW/ZBsFv1jbrb6gg8m/Q/6iv9qkYr8mmE2\\u002B\"\n  },\n  {\n    \"CategoryId\": 3,\n    \"Name\": \"Sleeping Bags\",\n    \"NameEmbeddingBase64\": \"rNhlv1GO/D7PKwu/1GWsPgLKoD93F84/2nAGQN0OJr9udRc/3ZqRPooEoL9cT4o9JKKLvwNxG0Dpbtc/bjvavu5kbT9hMTi/H6M/wBZfkr7egAJASjeTvuhInT9W04Y\\u002B3zaWvl5BoL58sEU/oCQ/vMzrGL/et0fA1AqEvwMEYz78EwG/j5PCvl0PwD8vyzo/scv2P9r\\u002BNT7sneG\\u002Bwu0OP\\u002BzTsT90oEo/dPwNP2r\\u002B1L5UmnE9dHrXvuDnZb7g6te/AEf4PvVmtb7ZmQhA4sedvnucRb/CbUS\\u002B/wfQv8G34r4RMBy/ZmX2Ps4spz\\u002BL59M/JkSEPoshDEBO\\u002BjHATuCTP6Hl6D763wo/TqH4vwk7oz62UK8/ylKdPwzy9r4cOze\\u002BlAvdPt6hED8TcqM/8JqBP3xMDED6pd2\\u002BZZ12PuKBVr\\u002Bh\\u002Bqy/D8srvwXhqb2afwS/Pq1jv2HQdD80btu/WNvsvp6\\u002Bhr7HBGO/PITrPS4uG75m1UO/jl2WP\\u002BPNNcB8mzC/yljOv3MWvT8VAa2/eLHFQOUjzD/ANfk/1s/APzDAjbz6Laq/Fmo6wFK4XT66cIu/Nd2bvmkvCD\\u002BQJzy8FUO7PhsnMEBwcWC\\u002BZkH0P3JBiD8SbM4/vFMUQLR0vD4byeI/ohAVwNBByb/NKgVAcwvFPTb8tz7QF9A\\u002BgGaJvQlmDkCj\\u002BMw/TPZmPxz8c78eIxBAWxtKPwSsxD5RorS80jcSP0Rcjb8BYAM/REotvyt1EsBsAOg\\u002BDaijv\\u002BA3\\u002BD\\u002BsTD/Ar0mWv3/U4L5bfZS\\u002Byxy4PsG4B8C4oGq9TzjjP8wK4r4OsCQ/V4oRwIRWAz\\u002BD8p8/k\\u002B3uP\\u002BjbSD1Hl5s/CkClviapaT5quoo/ltuQP5ednj9/Lr2/f1yfvqsrPL\\u002Brl1\\u002B/MIiTv0RqAcAutYA/OnCAPxhIXD6zWLy/2bgGQLgXEj8AaR86r3E\\u002Bv195P78w3As\\u002Bxmp2vii\\u002BE8BM9uq/XbievyLyGz63owi/xGdavyT3WD/odQE/78pNv9wt3L\\u002Bq\\u002BlC/AnNzP/Uyhj5dw6G/qERlv7LdmL\\u002BgJay9wT4rP\\u002BsUlL8eRSBAykF4P23UnT6s\\u002BZK/7Nf6P2exJEAaSLK/xOBhv/7GFUB7L\\u002BK\\u002BqDDXP1hKmj7S/RA/gSaZv8ryAsDpELQ/fklAv52RuD6jIFK/PP9xPWSqJT9ONk3Ag1Fxv8bywsCuAbA/f/1oPmmok7/VLx8/sxx7v2QMIb/U1vI9SjIPwMy9Ob/Datc/OROyv2Khyr\\u002B6z8g/N1KJP6kkMEDYTSy/UYq/vpz4mz5aVKO/gqqKv\\u002BZdr786cVc/JNmFPtAu1zwA4Jq/PihPQCA8775GCLY/S9mMP1qyKT8IUm4/3HhfPz42BsAS2eA/9OULv1d\\u002B8D6kHd4/zHxBP77jcb5opju/dd5dQH1L7r49fju/CHiNv\\u002BfR\\u002BL9Ly5S/VXzavxYQsL6AWHu\\u002BqmQcP94DXj\\u002BHM5Y/eHrfv45mcT9egN\\u002B/a3t5P0HNhr8DWQO/RjagPghxcr8UPmO/joYKvXOLK7\\u002Bw6F\\u002B/dSgBvzlFoj5yD0K/WqdYvhlRC7/TIYu/g2o\\u002BP7jk3b\\u002B2xx2/9rbLP2dqlj\\u002BoYDM/qGMCP\\u002BjNiT4DxYS/CKx2PZnyyT4WZjm/uqnHvd8D4T37OtI/RSJ6v\\u002B0v8D9Y/UC/7Cl0P3LyjT99OSc/nVdOvoyukb\\u002BfoRlAR1TtvcwRpcBgHse\\u002B5NE1wHRLz788BKA7y4/nPd0RGj8NajBAUJCKO7ATDD9pXBA\\u002BgBBTQKt4577sKyY/E9oEP3r5kT5YOFA/sDHQvyQU2D8\\u002BJc2/\\u002BJ\\u002BGv9nmoT2RtHxAdZA5v7aImz\\u002BKIe0/ovyWvrRdG7/Y6aA\\u002Brv\\u002BCP6qULEAQGze\\u002Bk3zHP7hqar\\u002Bx\\u002B1e/oCyNvrRtRsBrRvY\\u002BRCPAPbFU7b7diu4\\u002BQAGHP7WZPr69vsK\\u002BAOppPiOkrD5kDgo\\u002BdrK0v3trUj8i6hXAPN1yPU9a3b/EE9K/DKjAP1ICQj/WQfI\\u002BYiK3vX0GgD\\u002BBtWg\\u002BwvxQv\\u002BV8Nr82VHPAlY3fv\\u002BY3CL/Oocu\\u002B\"\n  }\n]"
  },
  {
    "path": "seeddata/test/customers.json",
    "content": "[\n  {\n    \"CustomerId\": 2,\n    \"FullName\": \"Eleanor Parker\"\n  },\n  {\n    \"CustomerId\": 3,\n    \"FullName\": \"Karen Johnson\"\n  },\n  {\n    \"CustomerId\": 1,\n    \"FullName\": \"Emily Johnson\"\n  }\n]"
  },
  {
    "path": "seeddata/test/evalquestions.json",
    "content": "[\n  {\n    \"QuestionId\": 1,\n    \"ProductId\": 2,\n    \"Question\": \"How to store Arctic Explorer Sleeping Bag?\",\n    \"Answer\": \"Use compression sack\"\n  },\n  {\n    \"QuestionId\": 2,\n    \"ProductId\": 2,\n    \"Question\": \"How to close the sleeping bag?\",\n    \"Answer\": \"Gently pull the zipper tab downwards\"\n  },\n  {\n    \"QuestionId\": 3,\n    \"ProductId\": 4,\n    \"Question\": \"Warranty duration?\",\n    \"Answer\": \"One year from purchase\"\n  },\n  {\n    \"QuestionId\": 4,\n    \"ProductId\": 5,\n    \"Question\": \"Insulation testing method?\",\n    \"Answer\": \"Comprehensive thermal conductivity tests\"\n  },\n  {\n    \"QuestionId\": 5,\n    \"ProductId\": 4,\n    \"Question\": \"Can I use the sleeping bag without proper ground insulation in extremely cold conditions?\",\n    \"Answer\": \"No\"\n  }\n]"
  },
  {
    "path": "seeddata/test/manual-chunks.json",
    "content": "[\n  {\n    \"ChunkId\": 1,\n    \"ProductId\": 1,\n    \"PageNumber\": 1,\n    \"Text\": \"(c) Rugged Riders 1\\n\\n\\nTrailblazer Bike Helmet\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 2,\n    \"ProductId\": 1,\n    \"PageNumber\": 2,\n    \"Text\": \"(c) Rugged Riders 2\\n\\n\\n3 3 3 4 5 5 5 6 6 6 7 7 7 8 8 8 8 8 8 8 8\\n\\n1. Important Safety Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.1 Proper Helmet Fit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Helmet Care and Maintenance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3 Warning: Not a Toy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 3,\n    \"ProductId\": 1,\n    \"PageNumber\": 2,\n    \"Text\": \"2. Assembly and Adjustment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1: Attaching the LED Safety Light . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2: Adjusting the Helmet Straps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\\n\\n3. Using Your Trailblazer Bike Helmet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1: Wearing and Removing the Helmet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2: Helmet Features and Benefits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 4,\n    \"ProductId\": 1,\n    \"PageNumber\": 2,\n    \"Text\": \"4. Troubleshooting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1: LED Safety Light Not Working . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2: Fitting Issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 5,\n    \"ProductId\": 1,\n    \"PageNumber\": 2,\n    \"Text\": \"5. Warranty Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1 Limited Warranty . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.2 Warranty Claim Process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.3 Exclusions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 6,\n    \"ProductId\": 1,\n    \"PageNumber\": 2,\n    \"Text\": \". . . . 5.4 LED Safety Light Warranty . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5 Limitation of Liability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.6 Non-Transferable Warranty . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.7 Legal Rights . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 7,\n    \"ProductId\": 1,\n    \"PageNumber\": 3,\n    \"Text\": \"(c) Rugged Riders 3\\n\\n1. Important Safety Information\\n\\n\\n1.1 Proper Helmet Fit\\n\\nBefore using your Trailblazer Bike Helmet, it is important to ensure a proper fit to maximize safety and protection. Follow these steps to ensure a secure and comfortable fit:\\n\\n1. Ensure the helmet is the correct size for your head. Refer to the size chart provided by Rugged Riders to determine the appropriate size for your head circumference.\\n\\n2. Adjust the chin strap so that it is snug but not too tight. The chin strap should be securely fastened under the chin to keep the helmet in place during use.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 8,\n    \"ProductId\": 1,\n    \"PageNumber\": 3,\n    \"Text\": \"3. Position the helmet on your head so that it sits level and covers the top of your forehead. The front edge of the helmet should be about one inch above your eyebrows.\\n\\n4. Use the adjustable dial at the back of the helmet to customize the fit. Turn the dial to tighten or loosen the helmet for a comfortable and secure fit.\\n\\n5. Check that the helmet does not move or shift when you shake your head. If the helmet moves, readjust the fit as needed.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 9,\n    \"ProductId\": 1,\n    \"PageNumber\": 3,\n    \"Text\": \"Note: Improper helmet fit may result in reduced protection in the event of an accident. Always ensure a proper fit before using the Trailblazer Bike Helmet.\\n\\n\\n1.2 Helmet Care and Maintenance\\n\\n\\nTo maintain the performance and integrity of your Trailblazer Bike Helmet, follow these care and maintenance guidelines:\\n\\n1. Clean the helmet regularly using a mild soap and water. Avoid using abrasive cleaners or solvents that may damage the helmet\\u0027s shell and components.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 10,\n    \"ProductId\": 1,\n    \"PageNumber\": 3,\n    \"Text\": \"2. Allow the helmet to air dry thoroughly before storing it. Do not use direct heat or high temperatures to dry the helmet, as this may cause deformation or damage to the materials.\\n\\n3. Inspect the helmet regularly for any signs of wear, damage, or deterioration. Check the shell, straps, buckles, and other components for any cracks, dents, or loose parts.\\n\\n4. Store the helmet in a cool, dry place away from direct sunlight and extreme temperatures. Avoid exposing the helmet to harsh chemicals or fumes that may affect its structural integrity.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 11,\n    \"ProductId\": 1,\n    \"PageNumber\": 4,\n    \"Text\": \"(c) Rugged Riders 4\\n\\nNote: Failure to properly care for and maintain your Trailblazer Bike Helmet may result in reduced effectiveness and protection. Regularly inspect and clean the helmet to ensure its safety and performance.\\n\\n\\n1.3 Warning: Not a Toy\\n\\nThe Trailblazer Bike Helmet is designed and intended for use as protective headgear during cycling activities. It is not a toy and should not be used for any other purposes.\\n\\nNote: Misuse of the Trailblazer Bike Helmet may result in injury or reduced protection. Use the helmet only as intended for cycling activities.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 12,\n    \"ProductId\": 1,\n    \"PageNumber\": 5,\n    \"Text\": \"(c) Rugged Riders 5\\n\\n2. Assembly and Adjustment\\n\\n\\n2.1: Attaching the LED Safety Light\\n\\n\\nTo attach the LED safety light to your Trailblazer Bike Helmet, follow the steps below:\\n\\n1. Locate the LED safety light - The LED safety light is located at the rear of the helmet, indicated by the \\u0022LED\\u0022 label.\\n\\n2. Insert the light - Insert the LED safety light into the corresponding slot at the back of the helmet, ensuring it is securely in place.\\n\\n3. Turn on the light - Once attached, press the power button to turn on the LED safety light. The light will emit a bright, steady glow, enhancing your visibility during low-light conditions.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 13,\n    \"ProductId\": 1,\n    \"PageNumber\": 5,\n    \"Text\": \"2.2: Adjusting the Helmet Straps\\n\\n\\nTo ensure a comfortable and secure fit, adjust the helmet straps as follows:\\n\\n1. Locate the straps - The helmet straps are positioned on either side of the helmet, with adjustable buckles for a custom fit.\\n\\n2. Adjust the chin strap - Pull the chin strap to tighten or loosen the fit around your chin, ensuring a snug but comfortable feel.\\n\\n3. Adjust the side straps - Use the side buckles to adjust the tension of the straps around your ears, allowing for a secure fit without causing discomfort.\\n\\n4. Check the fit - Once adjusted, ensure the helmet sits level on your head and does not move excessively when gently tugged.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 14,\n    \"ProductId\": 1,\n    \"PageNumber\": 6,\n    \"Text\": \"(c) Rugged Riders 6\\n\\n3. Using Your Trailblazer Bike Helmet\\n\\n\\n3.1: Wearing and Removing the Helmet\\n\\n\\nTo wear your Trailblazer Bike Helmet from Rugged Riders, follow these steps:\\n\\n1. Open the adjustable chin strap. 2. Place the helmet on your head, ensuring it sits level and low on your forehead. 3. Tighten the chin strap until it is snug under your chin. 4. Adjust the rear fit dial for a secure fit.\\n\\n\\nTo remove the helmet, simply:\\n\\n1. Loosen the chin strap. 2. Lift the helmet off of your head.\",\n    \"Embedding\": \"HF/MwfSfBUL8BNlBhgCQwQ7+RcLjlm1Bw45fQivRAUFdt/vB2RoEQiC8pEERAJLC4o8OQqsA9UCuu4RCUIgaQSIzDUKOMXxCtbh+wZiVQkKG4uHB0Rl5wTZngUD56UVCfp8YQmxvu0Flc/XBtzpMQUWyYEGUgN3C1gnUQUB2B8LbPghC41AdwuPETMGoaqXBW7nRwTkRDELfJITBazLoQbZoa0J1oZRCIpYEQSDXI8Ekx61BAzGkQe1USkF/OnPB4TaMQguEzME1GMtAdnd4wSgxA0J/4BDCJXOOwV2mv0BquppBTSRDQTWUqkBr5MNBAGKAwb+vyEHpULbC1aXnQgLw+EGAPHBCloiLwcHUJ8KwawI/v0q4QlKhJsIacVhBtNhyQRAvukDJemPB+737wBFPj0GGboXBdg1PQR05GcJR5SXChYRNwcxQ/7+Wra6/hYiAQXyJqsF3wd5BtEHRwdhD+sH3Qu1BkxJIwP5wLcFf4AlBSqVbwYMLVcJ0AoDBDemjv+CVIUI59RDCU3D5QkpaM8BN4OpBfKBOwsZpHMEIK35Cc1wuwt59AcH+RkpBjvC9QbdmeEFmsFtCXmouQhzsq8G0fTNARegXwiYvRULF997Bde8ZQhm7NsEa6bZB4fmCwoVds8EOIkdBH+HjwIDmVD4x35/BPoL6Qcl8zUEQWKRAgIIhQqwBNEE2dhzBv38iwl0Aj0Ae6v/BjKvDwZRQs8DDDL1BAH1LQbqjosGrsw3B8CO8wRfnykErDIPC2ZToQJ2zbcFKroPC4Jp4wZG8ysEW82jC+UgiwRW7X0E7lMDBe4lsQQJS6EHhNEBCZBY5wDkIIMFh0i/CDJcLQng87sHIStbBI/mLQV8tyED8AHJCYSFDwv7Li0HpeJPB96pgQfCxG8IWJsjBqwvCQBaUKsHbLPdBa1NrQrwWAUJQ+mDCrc6DQNhoNsFkzBxBYg4pwK6pvcE93ZjBVY+FwaDStcCPiY/B4WyHwYZu2cH0qcRBjwBuQX6iZ8K6Y6PBIj2ZwZWw18CxF6pAzB1bwOgkTcImSnXC9vaSwBLbokCr8YhC24NIQQ1BOkGAtCbBkxJUQZi1LkKNfdZBPIB3wpXal0Iu8AlCZHQbwFR4zEFpSslBAihywRNVaEAxSCzCP1eRQqp0fEHLiUfCMHtuwXHEVEChMkTBJkPSwegtCMPMYs3AAyKoQakBbkLVo7BBp4VfwAVtOEKkoPjAiOsaQRpo/cD4NmVCaGqtwfARQcKJNM7BrtGewVYxL0KM/sZBtdfHwTS6y8HbKPfB2TbtQURhI0Lg86TCf3cmwis4YMErqlJBbpe2Ql40s7/lP69BacoPQZAxesHjbb/BxjEAP+XeO8KqrB1CpkNhwVKkXcFodzbCKmBmwAV6D8JPv4VBREhJQi5zfsHa1V7CemqVwSsK8T+m+eXAKBA9wQUDU8BL1sXBwB/OPut0mMHEgW7AZyvuQQlmkEBUdrnCjmpxwu6Ud8EZVrPAGqRtP+ClycG4XdhAXf6ywTd/bcK0ttJBd0+PQguOMsB9+cfB2SZUQit+0cCNb63BjuAkQW13gEFfb4FBu272wC8yyMCxWD5Bx2IbwWuuikHfxQxB5QVpQBI17cFy2UjBV+jeQTR8dL/34wZClJWdwX3A2MEO3SVAgxkhwX2T8kETDUXBuBs/QM1lEMKhcZJB2392wWsRF8PzKxXCZwYfPnc47EGWBf/B7RBuQS0rmkLBbUlBYDbbwQOPqcE2xa3B8FsCQqNHx0A0kCHBqMjRQYMKZkDviylB+WzDwcDGQUHEMg9BTfPEwfnkvUD/XbtC9LIIQUi+XUKRdYBBNli6wYbhMcCfHCZCx2+PQYdhYkGeQyLC1pifQlfpDL9rmGzBu22RwNp6Z8BVvcPAeOPhQQdqCEIM8QtCVD6+QD5OCELPOyc/HNqtQvw2w8EE2inCgt85Qab3yUHgSgzBp60NwpYWyEG5XC3CEbUjQtAYokCOCfrBV7jDQQXbzkGXzofBRypxQdMDGkFATFfCHuCbwgo6TEBzQFvB\"\n  },\n  {\n    \"ChunkId\": 15,\n    \"ProductId\": 1,\n    \"PageNumber\": 6,\n    \"Text\": \"3.2: Helmet Features and Benefits\\n\\n\\nThe Trailblazer Bike Helmet is designed with the following features and benefits for your safety and convenience:\\n\\n\\nFeature Benefit\\n\\n\\nAerodynamic Design Reduces wind resistance for a smoother ride.\\n\\n\\nAdjustable Fit Ensures a comfortable and secure fit for all riders.\\n\\n\\nBuilt-in LED Safety Light Increases visibility in low-light conditions.\\n\\n\\nIn addition, the Trailblazer Bike Helmet is equipped with a rear fit dial, allowing you to customize the fit to your unique head shape.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 16,\n    \"ProductId\": 1,\n    \"PageNumber\": 7,\n    \"Text\": \"(c) Rugged Riders 7\\n\\n4. Troubleshooting\\n\\n\\n4.1: LED Safety Light Not Working\\n\\n\\nIf the LED safety light on your Trailblazer Bike Helmet is not working, please follow the steps below to troubleshoot the issue:\\n\\n1. Check the Battery: Ensure that the battery is properly installed and functional. Replace the battery if necessary with a CR2032 3V battery.\\n\\n2. Inspect the Light: Examine the LED light to see if there are any visible signs of damage. If the light appears damaged, please contact Rugged Riders customer support for further assistance.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 17,\n    \"ProductId\": 1,\n    \"PageNumber\": 7,\n    \"Text\": \"3. Ensure Proper Connection: Make sure that the wires and connections for the LED light are secure and undamaged.\\n\\n\\nIf the issue persists after performing these steps, please contact Rugged Riders customer support for further assistance.\\n\\n\\n4.2: Fitting Issues\\n\\n\\nIf you experience fitting issues with your Trailblazer Bike Helmet, please refer to the following troubleshooting steps:\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 18,\n    \"ProductId\": 1,\n    \"PageNumber\": 7,\n    \"Text\": \"1. Adjust Straps: Check if the straps are properly adjusted to fit snugly around your head without being too tight.\\n\\n2. Positioning: Ensure that the helmet is positioned correctly on your head, with the front edge no more than one inch above your eyebrows.\\n\\n3. Proper Sizing: Confirm that you have selected the correct helmet size for your head. The Trailblazer Bike Helmet comes in three sizes: Small (S), Medium (M), and Large (L).\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 19,\n    \"ProductId\": 1,\n    \"PageNumber\": 7,\n    \"Text\": \"4. Inspect Buckle and Dial: Examine the buckle and dial for any damage or issues that may be impacting the fit of the helmet.\\n\\n5. Padding: Adjust the inner padding to ensure a comfortable and secure fit.\\n\\n\\nIf you have followed these troubleshooting steps and are still experiencing issues with the fit of your Trailblazer Bike Helmet, please contact Rugged Riders customer support for further assistance.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 20,\n    \"ProductId\": 1,\n    \"PageNumber\": 8,\n    \"Text\": \"(c) Rugged Riders 8\\n\\n5. Warranty Information\\n\\n\\n5.1 Limited Warranty\\n\\nRugged Riders provides a limited warranty for the Trailblazer Bike Helmet. The warranty covers manufacturing defects for a period of 1 year from the date of purchase. This warranty does not cover normal wear and tear, misuse, or accidental damage.\\n\\n\\n5.2 Warranty Claim Process\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 21,\n    \"ProductId\": 1,\n    \"PageNumber\": 8,\n    \"Text\": \"To make a warranty claim, contact Rugged Riders customer service at warranty@ruggedriders.com. Please provide the original proof of purchase and a detailed description of the issue. Rugged Riders will assess the claim and provide further instructions for return or repair.\\n\\n\\n5.3 Exclusions\\n\\nThe limited warranty does not cover damage caused by improper use, modifications, or unauthorized repairs. It also does not cover damage resulting from accidents or misuse of the built-in LED safety light.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 22,\n    \"ProductId\": 1,\n    \"PageNumber\": 8,\n    \"Text\": \"5.4 LED Safety Light Warranty\\n\\nThe built-in LED safety light in the Trailblazer Bike Helmet is covered by a separate limited warranty for a period of 6 months from the date of purchase. This warranty covers defects in materials and workmanship.\\n\\n\\n5.5 Limitation of Liability\\n\\nRugged Riders\\u0027 liability under this limited warranty is limited to the repair or replacement of the defective product. Rugged Riders is not liable for any incidental or consequential damages resulting from the use of the Trailblazer Bike Helmet.\\n\\n\\n5.6 Non-Transferable Warranty\\n\\nThis limited warranty is non-transferable and is only applicable to the original purchaser of the Trailblazer Bike Helmet. It is valid only in the country of purchase.\\n\\n\\n5.7 Legal Rights\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 23,\n    \"ProductId\": 1,\n    \"PageNumber\": 9,\n    \"Text\": \"(c) Rugged Riders 9\\n\\n\\nThis limited warranty gives you specific legal rights, and you may also have other rights which vary from state to state or country to country.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 24,\n    \"ProductId\": 2,\n    \"PageNumber\": 1,\n    \"Text\": \"(c) Insulite 1\\n\\n\\nArctic Explorer Sleeping Bag\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 25,\n    \"ProductId\": 2,\n    \"PageNumber\": 2,\n    \"Text\": \"(c) Insulite 2\\n\\n\\n3 3 3 3 4 4 4 5 5 5 5 7 7 7 7 7 8 8 8 8 8 8\\n\\n1. How to Use . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.1: Opening the Bag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2: Getting In . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3: Closing the Bag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 26,\n    \"ProductId\": 2,\n    \"PageNumber\": 2,\n    \"Text\": \"2. Keeping Warm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1: Insulation Material . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2: Avoiding Drafts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\",\n    \"Embedding\": \"QjXEwsvAF0LcZaFCT2/nQT5bfULTOAtCCYeJQUqMJ0JdXxRBFAq9wVwKMcJ85dXCMT9HQoUzkEJI9z1COrStwHV/HUJYjU9BalZcwsbdZkK41v1CSJNOQgB2gb/5j0XC/UAdQlHXGULAWC3CeStdwaEkCMJkGTbD2ruyQSD0E0K9OpfCc/L5QHpQycHc0sjCqZ39Qb2OXkIuynPCePgMQi0vCMI3tY5B3kh5wmGa8MJD0L5BeKaWwKidy8EjTZrCQKdAQcfPrMFxdV7CyhaMQmwalEEexbVA5S18QruSSEL2zLRCFGuKQji7lUANVWDAmcjMwOH1ikLAsWrDI+JtQ/5gU0Hqp/PBKL6/wg1aC8IGBcJC3wABQw8OoMG4e5RCUptCwj3cM0Kiv4xCDXApwli8A8HYpQzB4jOsQPEa3EFUgCPC+UBAQrDHXkJ7YBzBTzUqwoTWn0ENO7xBVrxCwkJVtEHL+YDC+3cDv2ghpsFzOqZAihEeQhah2MLnpLTBfJ+UQQQCd0C+MB3CZGUqQwfSAkEx+FxCtfRJQV95E0KYjFbCJi6HwuZeS0HcMufB0cCJwhQnB8HSKyjBsQjJQaBANsFbWOHBz5Y6QfB9s8IbSWZCndxbQuXsSsJkJP9BEhfLwJUNtMFfDbRCAgpFwtX2dUKHVp7CMR9bQRKIUMEyEQTBY3VGQn7cpEKPaFpCBvC4QYhzrcFZ3h1CFRagwT60oUGlUvRBh83sQjEx9cLCPUFCAtNYwmBQaMJBQxfDxK/9QYUalELO+61AhQpyQvVU/sK3dMvC88SRwP0pnEHV8FNAJhmvwtejpkLkn0VBCLuIQv2zFkLPLQDCwPckwvuqlMFgXNrBczfAwnjb8ELLpVLC/pIKwsuIPEGpEj3CIQnEwb4fvUF6JAJCt6/YQaMNhcJjb5W/vwzdQhYtdEHK37hC9siEwucfq0JASsFBj9l5Qkj0r8AIRdLCI7ASQiqYoEJfQ9DCr4pAwg5TkMKrc5NCINbEQhnQsMLXs5zCetNKwjpjZULltyrCpLV1QAEMCcKW+QdAjv/HwXfnFcJa9PxCViuOwjSubj51Ng7B9bjcQid4ukLT7hhCYfz3wrekoEIcKvpBHPpywgIwUMJPaM9CNahiwmuHFECfYgnAO8WXQUoIikLGZKJCqvg9QkxwHUJUzgDD0uKXwmuMlsMLoe5CGtAmwDwEocKCdlpCElYOQR+MZkJRttrBZbPDwXe+NkIsJI9CAZVDwscOVMHa9O/BA415QRy8eMJ9qOm/hy4Jwvb2QEHu2ptCegtsQqBQ0UG+5dPB6OqNwo6GOkLI8abAEI5LQ3+EZ0EwoJZCVODmwjeAxUJimQJCgTbvwZv+xcJZDQ1B5dDcQi5bwcIahzRCm3ocwmN0yEFutpBBNXMLQ5ndDMJ1K63CykiiwjkqzsLvjQXCHeh6wk4am8AaLfjArbv+QeDvd0GUjxlC5BmdwmMNLEFkHHvBeCpfwhNle0IauKS/GZH4QHDL5kGSY+DBDCOKQhFYRcIVBZdB624FQ8Z1oUICUz1AwlA3wuD2N8IVgsO/ebhAQh+oAMBoglvCcYVswRLNycETNjLC+a+XwKCo1sAUgYfCFDnjwYCX68LoPL/BVpnCwFjZHUILhJVCfs0Bw8+SpEF8DfFCT0dLPn1sO8JiDUC/VNJlwbzyrsFTm9lC158zwv5wrsNbY3fBT6JeQhXSE8LDErnC3Cc/QfMd/MAw/Sk/B6tjwcXyT8HgcpfCO0W3QuBIr0Er6NZC5+v5wB0/CMJIrIxC0K89wqvNG8HTz2/Cien0wH6tg0DGDphDUjTywfJQLkFxTSjBcnSWQtlzvEF8xIlBnOJsQrkNakLt9zbBdZZiQp2bksEPgVdBRpNLQqkXYD/DX4hCsT4HQg9xTML8LiLCMvexQX3yUcI8nwvCatKXQi+DrME3RvfB4G/IQePtosJKpFPCHK/YweG+3EF6MRpCdd5VQnkkc0H0HIpBWUKJwji04sG8/InC+YojQX6+KUIu1mLCjdQSQr1qJEF1kKpC\"\n  },\n  {\n    \"ChunkId\": 27,\n    \"ProductId\": 2,\n    \"PageNumber\": 2,\n    \"Text\": \"3. Cleaning and Maintenance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1 Cleaning the Sleeping Bag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2 Drying the Sleeping Bag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3 Storage and Maintenance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 28,\n    \"ProductId\": 2,\n    \"PageNumber\": 2,\n    \"Text\": \"4. Storing Your Sleeping Bag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1 Cleaning and Drying Your Sleeping Bag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2 Compression Sack Storage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3 Long-Term Storage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.4 Maintenance and Care . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 29,\n    \"ProductId\": 2,\n    \"PageNumber\": 2,\n    \"Text\": \"5. Contacting Insulite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1 Phone Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.2 Email Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.3 Warranty Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.4 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5 Feedback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\",\n    \"Embedding\": \"xb0uw5R7yMKckilDMMcJQrOG18L42RDCZWLDQV4A9kLSC55AGp8yw2mfbEHnvmLDOknOQVznPkPaCEtCb3aZwfase0KATFbBnjfYwrsfGUPhQ0VDxzYYw6UkJEI6RNPBrxEAQZnAGcFk5ObCD2idwhluj8MD1XjDolfsQsVpIcIKzQBB8qQ3Q8WTD8Jxwz3DoPN2wdP4/0JQKmvAVzmjQvfM8kAX8jFDN0+7whFjBELIDQFBDcdTw64LfcLYRSLDQNhbQTsUaMJA8SPD2k3zwsN6scFoa+pBtpzgQVY+kEKQ5QVDB3ibQhOkG0KB/sRC8FJmwY0Tw0ISSSPEAiHhQ9Oi58Ll+9vB7Oh+QsE7pcIDW9FC0LBsQ38xSMNngqdA2cC0wv9ALkMo0edBls5IQi/mc0Ex74zCE8dhwn5VNEHPW2/BFBOtQS7maUIHM4C/pkYqQooI0MLkSqxCFHCywQN4R0MNCkpDeJA/Qr37P0LR1kPBxjGjQmsakcNHhWPDXgSAwlquu8LQtMHDDiCCQy45n0GTAQNDOi1zQjHpmkAItptBRcCCwnkCt0JsY0bBtsrUwizkhcLAUr9Bid8RQiQAREN2qijDSeuxwRDuucILJjBBkxuIwuPNhUAYXQHD6kJ3Pr1TvUHBaB9Dtjd4QQCYVEIwZRjDN2s5QkdOiUCZPVXCAJsCQzPnL0MFsknCQDhWw2yr+cJBm5jBzDyrwTocoz+woLVCh+xVQ3txnUFgowFCRYsHxPL4V8J2eaLCOYsSw4zrD0Pk23fCv5VIQ0J6KsPoFArDf4CjQS7KnENSgvLBjRIow2x1OkIUq9hCiwpAQWJcmcE+K2HCBH90Qvs3rMI6HqvCpZsIw4G0qkO8KdpCyTZIw6442sGqK7JCHnAtQSvrIkIcZ2lCX3+TQrnXWsGIsYfBUKxoQ5pTJUK1uxBDxS03whcm3UL8ElhDH1i6QlARSELkUSxBGNIYQgytgkKNEtLBnJ0jQW4AwMKoYSlDQJvRwlLjtsLZagzDSPRqw8oWXMJLW1HBVNPhwQJwhsNhw3xCry7HQuyAhcHkGW1DzBIFw2x7XsJTAW5C0+yNQrMwqUIbID7CBauMwjZMPENFEJXCISLSQSFR2EITKrtDBSGSQdkT3kDMoBNCUoscQ/nA9EKitQ1D77hSQYyM6EJ2YtXChm/6whOM+sNT6VpCrsYIwuy1+sIzVmJCXjUUwg6NxUL+UXrCwcjSQkaUUkOPnYlDDkcuQs2jaELrGh/BbLriQmBz1cJCGhxCXw2iQm6dI8JtL0nCZhIIQumLF8J6PMDBpE/6wuUCQELneIlCxnDAQ65OCEMuIM5BPjAgwzkOoEGW69NCma30QYUE3MIC5KFCoODMQoNIn8LBkJpBLoEEwy8aVcKIYH3CrERrQonlWcIb+qTCm15mw+ZHRsIDd8vC5JigQmnHisLwDn9CL8R0QvdOC8J+Gb5CzZNgQ8RT60KZs9nCVQwGw0AvnkKeiUfC6YH+QXshjUKZUojC8GbrwvtPC8P1VJLBjgglQ5sGgsKdkDdClOwsQiLJg0Fm04hCYPedwrQci8KUCwlCB31dQxA40UITiKvBafxBw0Od90Gd6S/DnvelwGNg7MIem71CW8grQolKIkL6201Dvh4QwxmklkJFwpxD5BYzQg0Vs0ESYQ1C3ivRwZx4zsIaXTRDkDHtwvmWIcQzPubBjEjwwvrglMGrCEHBsaEkQ2IHa0IzrrDCptvawdfGq0IAfAnCKwOAwtGuJ8MTp2rB8gH1QrmI88AilVxCTaNCwwdjHb/RbVXDSVlAwvWRlULHI8lDoOQzQkTVYkJtr4ZBKTWoQaR1I0OLiCVDe75oQUvZX8HEJKfCzoTjwSXSdkFs2ohCBg4MQrvCMMMGR03AltwMQ0eT0MKw4l1CgBlawsV3kcGMAMPBNKAkQ5sjVMHkdifC/CJPQTY4lsL9O3hCiY1UwExfqsK862pC64/fQm0OTMLfXuBC5EwOwU047MHodqjCC6HyQq98TsHK5UvD3XiWQq9TY8PJ+tJC\"\n  },\n  {\n    \"ChunkId\": 30,\n    \"ProductId\": 2,\n    \"PageNumber\": 3,\n    \"Text\": \"(c) Insulite 3\\n\\n1. How to Use\\n\\n\\n1.1: Opening the Bag\\n\\nUpon receiving your Arctic Explorer Sleeping Bag, start by unpacking it from the compression sack. Lay the sleeping bag flat on the ground and locate the zipper. The zipper is located on the right-hand side of the sleeping bag and is color-coded in dark blue for easy identification. Begin by gently pulling the zipper tab towards the top of the sleeping bag to open the bag fully. Take care not to force the zipper to prevent any damage to the sleeping bag.\\n\\n\\n1.2: Getting In\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 31,\n    \"ProductId\": 2,\n    \"PageNumber\": 3,\n    \"Text\": \"To get into the Arctic Explorer Sleeping Bag, locate the opening at the top of the bag. The opening is large enough for easy entry and exit and is reinforced with durable stitching to prevent tearing. Situate yourself at the opening, then carefully slide your legs into the sleeping bag, followed by your torso. Once inside, adjust the position of the sleeping bag to ensure a comfortable fit. The sleeping bag features a spacious interior to allow for easy movement while inside.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 32,\n    \"ProductId\": 2,\n    \"PageNumber\": 3,\n    \"Text\": \"1.3: Closing the Bag\\n\\nAfter getting into the Arctic Explorer Sleeping Bag, make sure to fully close the zipper to retain maximum warmth. Gently pull the zipper tab downwards to close the sleeping bag securely. Take care not to trap any fabric in the zipper to avoid damage and maintain the integrity of the sleeping bag\\u0027s insulation. Once the zipper is fully closed, rest assured that you are ready to stay warm and comfortable throughout the night.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 33,\n    \"ProductId\": 2,\n    \"PageNumber\": 4,\n    \"Text\": \"(c) Insulite 4\\n\\n2. Keeping Warm\\n\\n\\n2.1: Insulation Material\\n\\nWhen it comes to staying warm in the Arctic Explorer Sleeping Bag, the insulation material plays a crucial role. The Arctic Explorer Sleeping Bag is equipped with state-of-the-art lightweight insulation that ensures maximum heat retention while keeping the overall weight of the sleeping bag to a minimum. The insulation material is designed to trap body heat and provide exceptional warmth even in the coldest of conditions, allowing you to enjoy a comfortable night\\u0027s sleep no matter where your outdoor adventures take you.\\n\\n\\n2.2: Avoiding Drafts\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 34,\n    \"ProductId\": 2,\n    \"PageNumber\": 4,\n    \"Text\": \"To maximize the warmth and comfort provided by the Arctic Explorer Sleeping Bag, it is important to take measures to avoid drafts. The water-resistant shell of the sleeping bag provides a protective barrier against moisture and drafts, keeping you dry and warm throughout the night. Additionally, the Arctic Explorer Sleeping Bag features a snug-fitting hood that can be easily adjusted to eliminate drafts and retain heat around the head and neck area. By properly sealing the sleeping bag and adjusting the hood, you can create a cozy and draft-free environment that will ensure a restful night\\u0027s sleep in any outdoor setting.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 35,\n    \"ProductId\": 2,\n    \"PageNumber\": 5,\n    \"Text\": \"(c) Insulite 5\\n\\n3. Cleaning and Maintenance\\n\\n\\n3.1 Cleaning the Sleeping Bag\\n\\n\\nTo clean your Arctic Explorer Sleeping Bag, follow these simple steps:\\n\\n1. Preparation: Before cleaning your sleeping bag, make sure to remove any excess dirt or debris by shaking it out.\\n\\n2. Hand washing: If your sleeping bag is lightly soiled, it can be gently hand washed using a mild detergent and cold water.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 36,\n    \"ProductId\": 2,\n    \"PageNumber\": 5,\n    \"Text\": \"3. Machine washing: For more stubborn stains, you can machine wash your sleeping bag on a delicate cycle with a gentle detergent. Make sure to close all zippers and fasten any Velcro tabs before washing.\\n\\n\\n3.2 Drying the Sleeping Bag\\n\\n\\nAfter washing your Arctic Explorer Sleeping Bag, it is important to ensure that it is properly dried to maintain its insulation and water-resistant properties.\\n\\n1. Air drying: The recommended method for drying your sleeping bag is to hang it in a well-ventilated area out of direct sunlight. Ensure that your sleeping bag is completely dry before storing it.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 37,\n    \"ProductId\": 2,\n    \"PageNumber\": 5,\n    \"Text\": \"2. Tumble drying: If you need to expedite the drying process, you can use a large- capacity dryer on a low heat setting. Add a few clean tennis balls to help fluff up the insulation.\\n\\n\\n3.3 Storage and Maintenance\\n\\n\\nProper storage and maintenance of your Arctic Explorer Sleeping Bag will ensure its longevity and performance.\\n\\n1. Storage: When not in use, store your sleeping bag in a large storage sack to allow for proper loft and insulation. Avoid storing it compressed for extended periods of time.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 38,\n    \"ProductId\": 2,\n    \"PageNumber\": 5,\n    \"Text\": \"2. Spot cleaning: For small stains or areas that require spot cleaning, use a gentle detergent and a soft cloth to carefully clean the affected area.\\n\\n3. Repairs: Inspect your sleeping bag regularly for any signs of wear or tear. Small rips or tears can be easily repaired with a patch kit specifically designed for sleeping bag\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 39,\n    \"ProductId\": 2,\n    \"PageNumber\": 6,\n    \"Text\": \"(c) Insulite 6\\n\\n\\nrepairs.\\n\\n4. Professional cleaning: If your sleeping bag requires deep cleaning, consider taking it to a professional outdoor gear cleaner to ensure its longevity and performance.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 40,\n    \"ProductId\": 2,\n    \"PageNumber\": 7,\n    \"Text\": \"(c) Insulite 7\\n\\n4. Storing Your Sleeping Bag\\n\\nWhen you are finished using your Arctic Explorer Sleeping Bag, it is important to store it correctly to ensure its longevity. Improper storage can damage the insulation and reduce the effectiveness of the bag.\\n\\n\\n4.1 Cleaning and Drying Your Sleeping Bag\\n\\nBefore storing your sleeping bag, make sure it is clean and dry. Use a damp cloth to spot clean any dirt or stains on the shell. If the sleeping bag is heavily soiled, you may need to hand wash it with a gentle detergent. After cleaning, hang the sleeping bag in a well- ventilated area to dry completely. Do not store the sleeping bag while it is damp, as this can lead to mold and mildew.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 41,\n    \"ProductId\": 2,\n    \"PageNumber\": 7,\n    \"Text\": \"4.2 Compression Sack Storage\\n\\nThe Arctic Explorer Sleeping Bag comes with a compression sack for easy packing. When storing your sleeping bag, it is best to use the compression sack to reduce its size. This will help maximize storage space and keep the sleeping bag contained. To use the compression sack, simply roll or fold the sleeping bag and place it inside the sack. Use the compression straps to tighten the sack and reduce the overall size.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 42,\n    \"ProductId\": 2,\n    \"PageNumber\": 7,\n    \"Text\": \"4.3 Long-Term Storage\\n\\nIf you will not be using your sleeping bag for an extended period, it is best to store it in a cool, dry place. Avoid storing the sleeping bag in a compressed state for long periods, as this can damage the insulation. Instead, hang the sleeping bag or store it loosely in a large storage bag to allow the insulation to maintain its loft.\\n\\n\\n4.4 Maintenance and Care\\n\\nRegular maintenance and care of your Arctic Explorer Sleeping Bag will prolong its life and ensure it performs at its best. Avoid storing the sleeping bag in direct sunlight, as this can cause the colors to fade and the materials to degrade. Additionally, periodically fluff the insulation and air out the sleeping bag to maintain its loft and freshness.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 43,\n    \"ProductId\": 2,\n    \"PageNumber\": 8,\n    \"Text\": \"(c) Insulite 8\\n\\n5. Contacting Insulite\\n\\nTo reach Insulite customer service, please use one of the methods below. We strive to provide you with the best support for your Arctic Explorer Sleeping Bag.\\n\\n\\n5.1 Phone Support\\n\\n\\nFor immediate assistance, please contact our customer service team at 1-800-555-1234. Our friendly and knowledgeable representatives are available Monday through Friday from 9am to 5pm Eastern Time.\\n\\n\\n5.2 Email Support\\n\\nYou can also reach us via email at support@insulite.com. Please allow up to 24 hours for a response, though we aim to get back to you as soon as possible.\\n\\n\\n5.3 Warranty Information\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 44,\n    \"ProductId\": 2,\n    \"PageNumber\": 8,\n    \"Text\": \"If you have any questions about the warranty for your Arctic Explorer Sleeping Bag, please refer to the warranty card included with your purchase. For additional support, feel free to contact our customer service team.\\n\\n\\n5.4 Online Resources\\n\\nVisit our website at www.insulite.com for additional information, including product specifications, FAQs, and more. You can also find us on social media for the latest news and updates.\\n\\n\\n5.5 Feedback\\n\\nAt Insulite, we value your feedback. If you have any comments, suggestions, or concerns about the Arctic Explorer Sleeping Bag or any other Insulite products, please don\\u0027t hesitate to reach out to us. Your input is essential to our continuous improvement efforts.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 45,\n    \"ProductId\": 3,\n    \"PageNumber\": 1,\n    \"Text\": \"(c) Velocity Pro 1\\n\\n\\nStealth Bike Helmet\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 46,\n    \"ProductId\": 3,\n    \"PageNumber\": 2,\n    \"Text\": \"(c) Velocity Pro 2\\n\\n\\n3 3 3 3 4 4 5 5 6 3 6 6 6\\n\\n1. Safety Guidelines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.1 General Warnings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Proper Fit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3 Impact Protection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 47,\n    \"ProductId\": 3,\n    \"PageNumber\": 2,\n    \"Text\": \"2. Usage Restrictions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1: Off-Road Use . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\\n\\r\\n\\n3. Maintenance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1: Cleaning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 48,\n    \"ProductId\": 3,\n    \"PageNumber\": 2,\n    \"Text\": \"4. Product Liability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1 General Warnings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2 Known Hazards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3 Negligence and Misuse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.4 No Recourse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 49,\n    \"ProductId\": 3,\n    \"PageNumber\": 3,\n    \"Text\": \"(c) Velocity Pro 3\\n\\n1. Safety Guidelines\\n\\n\\n1.1 General Warnings\\n\\nThe Stealth Bike Helmet is designed for use by serious cyclists in controlled and supervised environments only. It is not suitable for recreational riding, motorcycling, or any other activity. Under no circumstances should this helmet be used for activities other than serious cycling, and it should not be used by children or individuals with medical conditions that may impact their ability to cycle safely. Failure to adhere to these warnings may result in severe injury or death.\",\n    \"Embedding\": \"+aYfP9eocUEldBK/+K2+wb/NGcKxpUhCu4hDQoOt7kFPoA3CV1H1Qdk1jz8cDubB/1GdQQh+0EHcxNDBulMkQVlQ3UFCqw9COfcRQhbxo0H68dRBDrcOQv9MsUGfq+C/1x+vQQZOm0Gh3u/BKI1MQGMKocFLKnXC6POSQYSAysHn39jB2nrjwGp1OsLNI5zBoz6MQXkOz0FSKIVB1THZQbQUtMArlxBCNdOeQRplHsFD21lBfCcTQhWQbsC4KunBHWvpQSVDPMKA7sFAH+IuweSTykE46d/BtfaowXB3a8HvwJVAZ7DOPd3WrEC2phNCQhbBQDB9x0HkEK/C0TOfQc2Iq8AquD5CJG3ywRNhcsEDM5tBKiEtQmpTAsKBCw7BanCDwVdFAkLjTqDBKP/OvGUYLEG95V7CPzavwaZkA8KLgaDBkPggwqZzD8GjFgHCqghwQexRIcJ0WYBBIDcAwZILoEGu1X1AwcqRwcgOBUDErDVBNZq/QCk/k8EXwwJBOyCpQfQPqL7iVFXCOMHHQu0js8FhvJ7AmprpwcBNDUKC91tCCz85wpIN50HHkiXChj4lwDgwBELkxAtCB46aPxaOx0HVT0RAQg2EwaHeIUJoKuXBOau9QZTypcE5kdZBAsxowYazbcEiE1hCkWe8wQ9fPkHWYYrBCm7cQUp/H0KnrdBA4Rg6QhI56UHvd6HBsGXvvMEFiUF57QFBqnjXwR10ckHeXHxB7r6oQTxym0Cwz4hBTLTKPxacj0HCfHjCNWz/QGgvA8GUcaLBMOLDQWStjMFiiibAqcqhwBbupUCR8NTBpa0SwQ2JnEHs84ZBMNDOwDJ72j4GObnBk2bzQRYO7MGjrFrBQLZWwTxLjEJfccLB7pakwZKNDkH5mMVA8YXdQK66FMLMJejBr0snwCAh3kCF6OVAxicyQQXM/EHb+FbCCHrDvm9GnME6thLBcJanQeCgrcAfH+rBKeJyQY/YD0EHlOTBU+06wry9gb/e6WVCM4NSQoraasLPQRzB6rK3wbtxAcK85pHBQ2yvQSNlAcLqOr3BgbxGQBjMvMCbnYFBESe5waMVD0IYF61BJjAjQPsswkAMNLhAfxyUwmaf2kEYHHtBM0nLwQ7XrsB6pDXBBNTKwW8PQT+ITWhApPWiQKhUMkKzs01AZQHOwdCB5ECbRD9B6Ia3wTqR6cKe+SDCNxcRQjVQ+kEH6ClCNWxqQXTtikGjUmFB2HA2wiaA/L87Z4tCrjnJwSAQmsKbMAhB+nL4QLes0EHnybzBMi1ywo1ZgcGx487AdOJwQIvuzkG260/CC/S2wYcA4kBrTQBBv9CuQrhQhcFazmNABEkawPkJusGTJoLBSBs6QHr0gcLRGsTAo2awwdTkFMB6EzjC8zTuwdo4IMLyPLnAvDPzQQ63IsLjIJjBDj0xwn5pLMI+9DJB++tqQvMWNMCaGVNAupGmQbo398BNAqJBInsFQhydDkJ6FnXCQOjBwcOgY8F7M/zB9cXrQdn/VcLwI/VBnBLAQLdgc8LM90JBGs0dQpVPpECX45zBCoI7QjT9PMDsQ8LB6mK3QhsseUCAdF3Ck0TyQN6ObkGAST7Bn7/+wIIxQUF0hORB7BbWQdv7AELatPVAlqQWQlvYhT9SXrHB40zWwfrrGsFwbybB8cp4wmMTE0I63ybCeD3AQDPdh8FBpARChJvMwX9NC8MoiwLA8wPMQGbQBkK0TDfAbnk4wYiI7kEA3A89/QbYwSP5u0GHaClBT1NFQSQ5g0FInzJCvM2oQaiM3UHtWQZCIguRwZDFGL8o2IdBMZ8vQSB8tUGPbt5CXjYOv8KbJUItUE6/qVqZwV/5qkG0TbZApVVvQZ05wb3ymOi/X1NBQmLKLsLBILJBzFw9wXYTR0EnOg5B1NE4Pkw3mkF2doVBKsNPwXp3kEFkaum+mDVmQoL8v8B3GAvC9UwKwjfd4z+muXzBgk/RwXMVoEAhOrLBpoIswCLElUGfcItB7O8WQhoykL/cFLzBh9TLwKelQEJfm6lA3pmXweTxLUJtat7A\"\n  },\n  {\n    \"ChunkId\": 50,\n    \"ProductId\": 3,\n    \"PageNumber\": 3,\n    \"Text\": \"1.2 Proper Fit\\n\\nThe Stealth Bike Helmet must be properly fitted and adjusted to ensure maximum protection. Failure to do so may result in the helmet coming off during a crash, exposing the wearer to serious head injuries. Follow these steps to ensure a proper fit:\\n\\r\\n\\n1. Adjust the straps to ensure they are snug but not too tight, with the chin strap positioned directly under the chin.\\n\\n2. The helmet should sit level on the head, with the front edge no more than one inch above the eyebrows.\\n\\n3. Use the adjustable dial at the back of the helmet to further customize the fit to your head shape.\\n\\n\\nFor further guidance on proper fit, please consult a professional bicycle helmet fitter.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 51,\n    \"ProductId\": 3,\n    \"PageNumber\": 3,\n    \"Text\": \"1.3 Impact Protection\\n\\nThe Stealth Bike Helmet is designed to provide impact protection in the event of a crash. However, it is important to note that no helmet can prevent all head injuries. Do not use this helmet as a substitute for safe and responsible cycling practices. Always follow traffic laws, wear high visibility clothing, and use appropriate signaling to ensure your safety on the road.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 52,\n    \"ProductId\": 3,\n    \"PageNumber\": 4,\n    \"Text\": \"(c) Velocity Pro 4\\n\\n2. Usage Restrictions\\n\\n\\n2.1: Off-Road Use\\n\\nThe Velocity Pro Stealth Bike Helmet is expressly not intended for off-road use. Using the helmet for off-road cycling, including but not limited to mountain biking, trail riding, or any other non-paved surface, may result in severe injury or death. The helmet is designed and tested for use on paved roads only, and any other use is against the manufacturer\\u0027s recommendation.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 53,\n    \"ProductId\": 3,\n    \"PageNumber\": 4,\n    \"Text\": \"Previous users who have attempted to use the Velocity Pro Stealth Bike Helmet for off-road cycling have reported serious injuries, including concussions, spinal injuries, and even fatalities. Therefore, it is imperative that users do not utilize the helmet for off-road activities under any circumstances.\\n\\n\\nIn the event of an incident resulting from off-road use of the Velocity Pro Stealth Bike Helmet, the manufacturer bears no responsibility and shall not be held liable for any damages or injuries incurred.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 54,\n    \"ProductId\": 3,\n    \"PageNumber\": 5,\n    \"Text\": \"(c) Velocity Pro 5\\n\\n3. Maintenance\\n\\n\\n3.1: Cleaning\\n\\nWARNING: The Stealth Bike Helmet from Velocity Pro is an advanced piece of safety equipment. Under no circumstances should it be used without strictly adhering to the maintenance guidelines outlined in this manual. Failure to comply with these guidelines may result in serious injury or death.\\n\\n\\nTo clean the Stealth Bike Helmet, follow these steps:\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 55,\n    \"ProductId\": 3,\n    \"PageNumber\": 5,\n    \"Text\": \"1. Use a soft, damp cloth to wipe down the exterior of the helmet. Do not use any harsh chemicals or abrasive materials, as this can damage the outer shell and affect the performance of the helmet.\\n\\n2. If the helmet has removable padding, carefully detach it according to the manufacturer\\u0027s instructions and hand wash it with mild soap and water. Allow the padding to air dry completely before reattaching it to the helmet.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 56,\n    \"ProductId\": 3,\n    \"PageNumber\": 5,\n    \"Text\": \"3. Inspect the ventilation system for any dirt or debris, and gently remove it with a soft brush or compressed air. Do not use excessive force, as this can cause damage to the ventilation components.\\n\\n4. After cleaning, thoroughly inspect the entire helmet for any signs of wear, damage, or deterioration. If any issues are found, do not use the helmet and contact Velocity Pro immediately for further instructions.\\n\\nNote: The Stealth Bike Helmet is not suitable for use in extreme weather conditions, such as heavy rain or snow. It is important to keep the helmet dry at all times to maintain its structural integrity and protective capabilities.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 57,\n    \"ProductId\": 3,\n    \"PageNumber\": 6,\n    \"Text\": \"(c) Velocity Pro 6\\n\\n4. Product Liability\\n\\n\\n4.1 General Warnings\\n\\nThe Velocity Pro Stealth Bike Helmet is not to be used under any circumstances. It is our strong recommendation that you refrain from using this product in any capacity. This includes, but is not limited to, cycling, skating, or any other form of outdoor activity. The Stealth Bike Helmet is not designed to protect against any impact and does not meet safety standards. Using this product may result in severe head injury or death. Do not use the Stealth Bike Helmet for any purpose, no matter how seemingly benign.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 58,\n    \"ProductId\": 3,\n    \"PageNumber\": 6,\n    \"Text\": \"4.2 Known Hazards\\n\\nThe Velocity Pro Stealth Bike Helmet has been known to cause serious harm to users. Prior users have reported severe head injuries and concussions after using this product. The helmet does not provide adequate impact protection and is not suitable for any form of physical activity. It has been known to detach from the user\\u0027s head during use, leading to further injury. Do not underestimate the potential dangers associated with using the Stealth Bike Helmet, as it may result in irreparable harm.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 59,\n    \"ProductId\": 3,\n    \"PageNumber\": 6,\n    \"Text\": \"4.3 Negligence and Misuse\\n\\nUsing the Velocity Pro Stealth Bike Helmet for any purpose would be considered negligent and irresponsible. Any attempt to utilize this product for its intended purpose or otherwise would be a misuse of the product. We strongly advise against any form of negligence or misuse. The consequences of using the Stealth Bike Helmet, even in the most controlled environment, are too severe to risk. It is imperative that users understand the gravity of the situation and refrain from using this product under any circumstances.\",\n    \"Embedding\": \"hACSwTcKekHYVjnAHGAQwsE55cFHhXtBsfWOQrJw9kEd+ojBXV8dQrg0MEHRgyXCzdexQYd5XUHmcnDA3hI+QV2aCkIiRy9CdbX9QZlJ7UH+KZ5Bz1tBwc+F4EGSj2bAOH5yP8ee5EEFJDDCZjg0QNzvxsEOLqbCkLp5Qap5DsLRDwTCBXMRQLwYJMLktT7Biu2gwIQqqUAH3yvBLwodQXp95kBSSMBBqU8gQJh5y8D/hKRBSGr+QQtDScESlqTBnk3eQYks5MEgpOnAMKejwfKByUGqTejBtSAcwZx3nMErkhpBKMVvQZaaZ0ECihFCNwqmQW4mq0FhA67C39SAQUNHT7/gjW5CuZimwUN7AsJhwZBBM7HRQewY2cHZfhHA66mjwWdSTkJWdqLBC2OMQe0hyEH5cFvC1/QnwQffD8Kz0UJBEBR8wXXVmsG4OxLC+TN+QVKm8MFGe2ZBiCNoQKjHQEIhA2lBrEFVwELYE8Hn3xNC2fG1QMAA973ysbm/vRykQf009sCmw2rCdFKWQoJy+8Ged0PBMFHXwS2ZvcCa2DFCEeC1wQzBIEGRvJjBsgOVQVcOBUIzOC5CEO8kQNKBwkFuelhAKdMqwZX9YkKw3hXCLEHewD59sMEMzu/APZoUwfYHAMDpZDtCnLEoQdaHk8FRCgfCA4KwQZkiOUIyFMPAa9U2QltOWUGhxWXCMORJQTDJtr6ObZxBTbrwwBbuEkCELP9BqZrIQSpXsMA2wpRAkRYcwU57gkCkeTbCu2KCwPB830Fx9inBvTb6QFLrK0D0zY/BhXbMwUmI7UDN8g7Cdp17wMjMqEB5IHdB44q6wTCkO0E79TDCDvnmQb9v08FC3mjBx/5jQOmij0LntFHBfH4dwexRC0HpsUpB/7I1QQSuhMCSNMDBx9OpwbQVq0EbCL7BsPWNQc2vTULbc/bB34Q6wEJJr8FLFwbBm4G0QQEGEMF4T9XBQRvzwIpdh0F93BrCya4WwlwCWcC5yBdCisVbQt46rsKwd/LBnQipwSigQr+nFBzAKiKaQRS3SMJQqxfBUxcjwTNWQb99AAtCko2jwVyJaEBtZNNAYumaQLq0HkID4nNB9f5qwnvrRUH7vLVBAlYmwsD2ub+Z0hzCQznEwSe1sUCQUHjAnhE+weXELUILjoNBv3sLwg+wpEEqWB1AXoSMQDOR9sJf+L/B78WjQB+QJEIj++tBvh5fwFCQBsEZcARBHPxtwsq8f0Au76JCMLEVwipEY8KMnb9A95RIQXfemUF41NzBl+kfwnA0a8KW3/3A0vgawlR2BkJQzHDBwEK3waTfz0EO1wxBgCnHQrEpREHqUqpBMK7dP99WW8GWz1HBP8JTwZBaL8JwwBE8c+/EwN+0f0HvsNzBrpuIwR3Ku8GhwbPB7GWRQf2ZxcBLQxDCowRwwYBsn8HR/m3BX1lQQgwDX0EGq4RCotCrQdqVc7/mfb1BM8IgQvkZc0LvYF/CUDrEwcXvCUErx+XA5WTQQe0Mw8FhFBhCXXUbQZY1dcKrPY5AOhjxQUPKGUFiYC9B1hMgQhmwHr/UzavAWM7dQhjXL0E8/v7BlX1TwavyeUHMIb5AbPacwQe8kUBwSYFB6DNMQpjZkkIgESM+ORzzQdfw0T/Dd7/BYVCSwVHu2MC+2r+/YdAswmaN3UAlj+fBqe6ewY/odMHV0DFCv/bEwcJH+8Jq0cPBZ5zdQI+SF0LldR/BOWBSwbLaX0ErjIjBBWWywQXN+b8qWmHBKEXlQYrKfsD1WwJCWHAoQthgokHzZ3RBh56uwYXIz0HeI5rBmBAWwGLwVUGZj95C0hS1P5G/o0HT6x/BO2+Rwa+0BEKZwajADYMBQRYf9cHKPrLBpyRLQvmOJ8IBaYNB5dA0wvuc/cBZQcxAmszRP3MEZ8HgZd9AYeB4waKo4UHqoDjB0oKoQu/qAcFJyknCQIrfwTAbvj8Uqj9B/uydvpaVRsBnDjnBa3QMv9a0TEEdSK1BdoeHQZfWZUEjBm3B7e+hwQsoOEJln/xAkPJqwto7C0JSGRfA\"\n  },\n  {\n    \"ChunkId\": 60,\n    \"ProductId\": 3,\n    \"PageNumber\": 6,\n    \"Text\": \"4.4 No Recourse\\n\\nIn the event of any harm or injury resulting from the use of the Velocity Pro Stealth Bike Helmet, there is no recourse available. Our company takes no responsibility for any consequences associated with the use or misuse of this product. By purchasing the Stealth Bike Helmet, users acknowledge the inherent risks and absolve the company of any liability. It is important to understand that there is no avenue for compensation or resolution in the event of injury or harm.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 61,\n    \"ProductId\": 4,\n    \"PageNumber\": 1,\n    \"Text\": \"(c) Summit Sleep 1\\n\\n\\nAlpine 3000 Sleeping Bag\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 62,\n    \"ProductId\": 4,\n    \"PageNumber\": 2,\n    \"Text\": \"(c) Summit Sleep 2\\n\\n\\n3 3 3 3 4 5 5 6 6 6 7 8 8 8 9 9 9 9 9\\n\\n\\n10 10 10 10\\n\\n1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.1 Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Intended Use . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3 Safety Precautions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.4 Product Registration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 63,\n    \"ProductId\": 4,\n    \"PageNumber\": 2,\n    \"Text\": \"2. Getting Started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1: Unpacking the Sleeping Bag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\\n\\n3. Using the Sleeping Bag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1 Adjusting the Fit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2 Temperature Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3 Packing and Storage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 64,\n    \"ProductId\": 4,\n    \"PageNumber\": 2,\n    \"Text\": \"4. Cleaning and Maintenance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1: Cleaning the Sleeping Bag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2: Storage Tips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\\n\\n5. Troubleshooting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1: Common Issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 65,\n    \"ProductId\": 4,\n    \"PageNumber\": 2,\n    \"Text\": \"Issue: Zipper gets stuck . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Issue: Loss of loft . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Issue: Drafty feel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\\n\\n6. Warranty Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1 How to Make a Warranty Claim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2 Warranty Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 66,\n    \"ProductId\": 4,\n    \"PageNumber\": 3,\n    \"Text\": \"(c) Summit Sleep 3\\n\\n1. Introduction\\n\\nWelcome to the user manual for the Summit Sleep Alpine 3000 Sleeping Bag! This high- performance sleeping bag is designed to keep you warm and comfortable in any climate. Whether you\\u0027re camping in the mountains or backpacking through the desert, the Alpine 3000 is your go-to sleeping solution. This manual will provide you with all the information you need to get the most out of your sleeping bag. Please read through it carefully before using the product to ensure a safe and enjoyable experience.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 67,\n    \"ProductId\": 4,\n    \"PageNumber\": 3,\n    \"Text\": \"1.1 Features\\n\\n\\nThe Alpine 3000 Sleeping Bag is packed with features to enhance your camping experience. This includes:\\n\\n\\nAdvanced insulation for maximum warmth Durable ripstop fabric for longevity Snug mummy shape for optimal heat retention Waterproof and windproof construction Lightweight and compact design for easy transport Integrated pillow pocket for added comfort\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 68,\n    \"ProductId\": 4,\n    \"PageNumber\": 3,\n    \"Text\": \"1.2 Intended Use\\n\\nThe Alpine 3000 Sleeping Bag is intended for use in outdoor camping and backpacking activities. It is designed to provide a comfortable and warm sleeping environment in a wide range of climates, from cold alpine conditions to warmer desert nights. The versatile design of the sleeping bag makes it suitable for use by outdoor enthusiasts of all levels, from beginner campers to experienced mountaineers.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 69,\n    \"ProductId\": 4,\n    \"PageNumber\": 3,\n    \"Text\": \"1.3 Safety Precautions\\n\\n\\nTo ensure your safety while using the Alpine 3000 Sleeping Bag, please keep the following precautions in mind:\\n\\n\\nAlways check the sleeping bag for any tears or damage before each use Do not use the sleeping bag near open flames or other sources of high heat Keep the sleeping bag dry to prevent loss of insulation Do not use the sleeping bag without proper ground insulation in extremely cold conditions\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 70,\n    \"ProductId\": 4,\n    \"PageNumber\": 4,\n    \"Text\": \"(c) Summit Sleep 4\\n\\n\\nDo not store the sleeping bag in a compressed state for extended periods of time\\n\\n\\n1.4 Product Registration\\n\\nFor your convenience and to stay informed of any updates or recalls, we recommend registering your Summit Sleep Alpine 3000 Sleeping Bag. To register your product, please visit our website and complete the online registration form. By registering your product, you will also receive important information about care and maintenance, as well as helpful tips for getting the most out of your sleeping bag.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 71,\n    \"ProductId\": 4,\n    \"PageNumber\": 5,\n    \"Text\": \"(c) Summit Sleep 5\\n\\n2. Getting Started\\n\\n\\n2.1: Unpacking the Sleeping Bag\\n\\nUpon receiving your Alpine 3000 Sleeping Bag, carefully remove it from the packaging. Check the sleeping bag for any damage or defects, such as tears, loose threads, or broken zippers. If you notice any issues, please contact Summit Sleep customer support for assistance.\\n\\nOnce you have inspected the sleeping bag, unzip the compression sack and carefully remove the sleeping bag. Ensure that all parts and accessories, including the stuff sack and compression straps, are included in the packaging. Place the packaging and any tags or labels in a safe location for future reference.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 72,\n    \"ProductId\": 4,\n    \"PageNumber\": 5,\n    \"Text\": \"Inspect the sleeping bag to ensure there are no foreign objects or debris inside. Gently shake the sleeping bag to allow the insulation to loft and regain its full volume. It is normal for the sleeping bag to have a compressed appearance after being removed from the packaging.\\n\\n\\nCongratulations! You are now ready to use your Alpine 3000 Sleeping Bag for your next adventure.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 73,\n    \"ProductId\": 4,\n    \"PageNumber\": 6,\n    \"Text\": \"(c) Summit Sleep 6\\n\\n3. Using the Sleeping Bag\\n\\n\\n3.1 Adjusting the Fit\\n\\nThe Alpine 3000 Sleeping Bag from Summit Sleep is designed to provide a snug and comfortable fit for maximum warmth and insulation. To adjust the fit of the sleeping bag, follow these simple steps:\\n\\n1. Opening the Zipper: To open the sleeping bag, locate the two-way zipper and carefully pull it down using the zipper pulls.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 74,\n    \"ProductId\": 4,\n    \"PageNumber\": 6,\n    \"Text\": \"2. Entering the Sleeping Bag: Once the zipper is open, carefully lie down on the sleeping bag and gently slide your body inside. Ensure that your feet are at the bottom of the bag and your head is positioned in the hood.\\n\\n3. Adjusting the Hood: The hood of the sleeping bag can be adjusted using the drawstring located near the face opening. Pull the drawstring to tighten the hood around your face for added warmth.\\n\\n4. Securing the Zipper: Once inside the sleeping bag, zip it up using the two-way zipper. Ensure that the zipper is fully closed to prevent any cold air from entering the bag.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 75,\n    \"ProductId\": 4,\n    \"PageNumber\": 6,\n    \"Text\": \"5. Adjusting the Fit: To customize the fit, use the adjustable straps located on the sides of the sleeping bag. Tighten or loosen the straps as needed to achieve a comfortable fit.\\n\\n\\n3.2 Temperature Control\\n\\nThe Alpine 3000 Sleeping Bag is designed to provide exceptional temperature control in a variety of climates. Follow these guidelines to optimize the temperature inside the sleeping bag:\\n\\n1. Layering: Depending on the temperature, consider wearing additional clothing layers inside the sleeping bag for added warmth.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 76,\n    \"ProductId\": 4,\n    \"PageNumber\": 6,\n    \"Text\": \"2. Using the Hood: Utilize the hood of the sleeping bag to retain heat around your head and neck during colder nights.\\n\\n3. Ventilation: In warmer temperatures, partially unzip the sleeping bag to allow for ventilation and prevent overheating.\\n\\n4. Utilizing the Draft Collar: The sleeping bag is equipped with a draft collar to prevent warm air from escaping. Ensure that the draft collar is securely fastened around your\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 77,\n    \"ProductId\": 4,\n    \"PageNumber\": 7,\n    \"Text\": \"(c) Summit Sleep 7\\n\\n\\nneck for optimal temperature retention.\\n\\n\\n3.3 Packing and Storage\\n\\nProper packing and storage of the Alpine 3000 Sleeping Bag will help maintain its performance and longevity. Follow these steps to pack and store the sleeping bag:\\n\\n1. Rolling the Bag: When packing the sleeping bag, roll it tightly from the foot end towards the head end. Use the compression straps to secure the rolled bag in place.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 78,\n    \"ProductId\": 4,\n    \"PageNumber\": 7,\n    \"Text\": \"2. Using the Stuff Sack: Place the rolled sleeping bag into the included stuff sack for convenient storage and transportation. Use the drawstring closure to secure the stuff sack.\\n\\n3. Avoiding Compression: When storing the sleeping bag for an extended period, avoid compressing it in a tightly packed state. Instead, store the bag in a cool, dry place with plenty of room to maintain its insulation properties.\\n\\n4. Cleaning and Maintenance: Prior to storing the sleeping bag, ensure that it is clean and completely dry. Refer to section 4 for detailed cleaning and maintenance instructions.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 79,\n    \"ProductId\": 4,\n    \"PageNumber\": 8,\n    \"Text\": \"(c) Summit Sleep 8\\n\\n4. Cleaning and Maintenance\\n\\n\\n4.1: Cleaning the Sleeping Bag\\n\\n\\nTo clean your Summit Sleep Alpine 3000 Sleeping Bag, follow these simple steps:\\n\\n1. Spot clean any small stains with a damp cloth and mild soap. Gently rub the affected area and then wipe with a clean, damp cloth to remove any excess soap.\\n\\n2. For larger stains or more thorough cleaning, hand wash your sleeping bag in a bathtub or large container using a mild detergent. Make sure to fully unzip the sleeping bag and always use cold water.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 80,\n    \"ProductId\": 4,\n    \"PageNumber\": 8,\n    \"Text\": \"3. After washing, thoroughly rinse the sleeping bag to remove any soap residue. 4. Gently squeeze out excess water, being careful not to wring or twist the fabric, which\\n\\ncan damage the insulation. 5. Hang the sleeping bag to air-dry in a well-ventilated area, away from direct sunlight or\\n\\nheat sources. Ensure it is fully dry before storing.\\n\\n\\nIt is important to never dry clean, machine wash, or tumble dry your Alpine 3000 Sleeping Bag, as this can cause damage to the insulation and fabric.\",\n    \"Embedding\": \"7yKSwTBRCkISNdVBg1iAwaypVEKDYUm/TxQRQtwPp0F1vrRAGutVv0TC6sEZ1IzBguveQSQvNEJmDRVBju1NQTETpkAxtyJCQWWcwo96wEGGOkRC7LrEQXl+y0FSGOZB4cmDQRqYc0EL+wI+asaOv7CdQcHAHfzCSM+qvtO2jcAHe8PAMdJVwSbGz0D//gzA5DfSv5x2ZsFRyyzCqCNPQtvU8UHDHUpBCSrDwNHpKsLjjYvBer3HwMnI3UHVV1DB6AmFQk/878FUBopBfWXZwIl3OsJ5NXlBVefXwXjTnsFBHtVBw2DjQAAdikCHvhZCW4wDQVMBCkHOTZ/C2BO1QhItEkIdGBlCme+EwU7akEGdkUBCRjB3QhMIWMJiuKtBCVJSQUHBGELFws1BNBFEQTBYm0FXhsvApq3oQPgXf8Bf8BzCCKoGwijYAD45iExBOgvlwbJFj8GPm4zBiZTbP5NipsFHQdjBR+hfwBR/ocEm0cDBTa4DQnYB/sHEjX5AgVEpQObXK0JOWHnCEP/BQicarsFQHAxCGgs+QdqywMA8hS1AQJBjwuyPZUCczkXAXDLLwWLIacGePmFB/2cPQZUKbEFEWJrBySt+QbX6KkJnJQ1CH5pMQcUWPcL5nwnBmxA3wqnFAMKCpTVC+5kjQetLzsBhkSBAqVBwQcxVA0IwapE8p6EMQk8SR8BqhcPAqHNfP9D7ekFvDz1BxbEGQLqYZMB76iRCqy63QSWeIcJ/2FVBppJawl43g0H0CnnCl63CwHbQ9sAiEx3C6UnTwBVjGsJBAoLCVVggQfd2CULFdNFAx9XtwcGuiUHKj9hA7qoRQpls3UD0BFw/lBuKwf/avcH50ZLBDNh0wI+bfkHwguLBcgfjQSdhZMExmybBW0OdwKXq4sFyJeQ+Nln+QGIILkENvqHBJ9gqQvafoMBnEaRARDodQWoM70EKFErA5kwBwdjEh0BWBQjC73A3QNGqgUJ78AbCcx7WwdwkSEHnTUJCMLVSwEoUacJeeqTByYsAwZmsDEKBr17BqrmvQQnaHMKfEwpANXHTQNF+KsFzaZZCq0CMQRHYkMEionTBaPYbQrd8UUJXdUBBzZUewuZ5gUIcAItABGp4QUhkS0LL4z5AUURKwGJIIMFntY5BRVrNQVC77UCuhhPBnTAQQb/OJkI2nEfCrQ1KwptsC8Pn9ypBExIFQj56KUGVsulBjxEWwgYO5UFEIFzB9nS4wWWeq8EI9AVCDc10wQeqCkEq2D/B/TYAQcTxwEH3jsNBdCuIQY/518GIbxHBQuHjwPtj0sA6uSNBj7UQQlPQF0GWnk7CdaWtQmTFO8EM749BNLClwOZPm0Fg+STB/MpuwcApZ8LMAh9AfuFUQGPmmsGkhwpCyf7gwMkANcJ84UpAnKlcQlbKu8H26BbCAAPFwTZa5cGojaXBpmdCwnrRc8LFriXBpGjxQbuOo0HmswpAmWQywd5IlUHk9yvBaIN2wfZdkL8WPc3BaAyuwV9in0EJn/nA7B+/QU9rNMKo0Ei9Xk/2QPr0YUGPsbHBg4UdQaCyJsIOIMvBjL0BQrUyJsILMkXBtl+CQRuvBEDh8gjC+7idQd+tEkGjeLnBC0YjQv9QRsHq+6JBboUtwJNaykCrl/pBSLlwwtW7HUL+NLFAWYGIQRCXlUHyxU9BKS7BwZTsQMGiP2FBTrTSwRMU5MJx5EjBDmKQweDLxDs9IbbBxMevQTO2vUHLmpFB3RixwOgzkkHStfPBFuf0QYzEHcHG3VPBPMZwQSFsFcFoDL7Bc76rQBzrxkF4tgLCju5XwZrLk8E0iKxCIu+kQFMY9UGrKOZBGqWMQTBlAUIfFxTBdqPmQYBo+kHevXDBCwjsQRczAcIrAQHBlC/hwZzGJcF5mKPAm+npQa4qE8FECuNAMokiQfZthcA4B7FBtGqOQY5q30CjMxrBaWCUwZPDNb8unC7CvHI4wPvgFUDzodzB1KBxQWMGH8Hca8FBcDLjwQa3p0EgIbdAUuQyQQM3qUGZwk/ChFQGwgR1H8DMMDZA\"\n  },\n  {\n    \"ChunkId\": 81,\n    \"ProductId\": 4,\n    \"PageNumber\": 8,\n    \"Text\": \"4.2: Storage Tips\\n\\nProperly storing your sleeping bag is essential to maintaining its performance and longevity. Follow these guidelines for best results:\\n\\n1. After each use, make sure your sleeping bag is completely dry before storing to avoid mildew or mold growth.\\n\\n2. Store your sleeping bag in a large, breathable storage sack to maintain loft and prevent compression of the insulation.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 82,\n    \"ProductId\": 4,\n    \"PageNumber\": 8,\n    \"Text\": \"3. Avoid storing the sleeping bag in a compressed state for long periods, as this can cause permanent damage to the insulation.\\n\\n4. Keep your sleeping bag in a cool, dry place, away from direct sunlight and extreme temperatures.\\n\\n5. Periodically remove your sleeping bag from its storage sack and lay it out flat to air and fluff the insulation.\\n\\n\\nFollowing these cleaning and storage tips will ensure that your Summit Sleep Alpine 3000 Sleeping Bag remains in top condition for all your outdoor adventures.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 83,\n    \"ProductId\": 4,\n    \"PageNumber\": 9,\n    \"Text\": \"(c) Summit Sleep 9\\n\\n5. Troubleshooting\\n\\n\\n5.1: Common Issues\\n\\n\\nIssue: Zipper gets stuck\\n\\nIf you encounter difficulty with the zipper of your Alpine 3000 Sleeping Bag, check for any fabric or debris caught in the zipper teeth. Gently remove any obstructions and try again. If the issue persists, apply a small amount of lubricant to the zipper to help it glide more smoothly. Additionally, ensure that the bag is fully aligned when zipping to prevent any strain on the zipper.\\n\\n\\nIssue: Loss of loft\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 84,\n    \"ProductId\": 4,\n    \"PageNumber\": 9,\n    \"Text\": \"Should you notice a loss of loft in your sleeping bag, it may be due to compression during storage. To restore the loft, remove the sleeping bag from its storage sack and shake it gently to allow the insulation to expand. If the loft does not improve, consider washing and drying the sleeping bag according to the care instructions provided in section 3.3.\\n\\n\\nIssue: Drafty feel\\n\\nIf you feel a draft in your Alpine 3000 Sleeping Bag, check to ensure that the hood and draft collar are securely cinched to prevent cold air from entering. Adjust the drawcords as needed to achieve a snug fit. Additionally, make sure the sleeping bag is properly zipped to further reduce any drafts.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 85,\n    \"ProductId\": 4,\n    \"PageNumber\": 10,\n    \"Text\": \"(c) Summit Sleep 10\\n\\n6. Warranty Information\\n\\nSummit Sleep provides a limited warranty on the Alpine 3000 Sleeping Bag to the original purchaser for a period of one year from the date of purchase. This warranty covers defects in materials and workmanship under normal use. The warranty does not cover damage caused by improper care, accidents, or natural wear and tear. Summit Sleep will repair or replace, at its discretion, any product found to be defective during the warranty period. To make a warranty claim, please contact our customer service department with proof of purchase.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 86,\n    \"ProductId\": 4,\n    \"PageNumber\": 10,\n    \"Text\": \"6.1 How to Make a Warranty Claim\\n\\n\\nTo make a warranty claim for your Alpine 3000 Sleeping Bag, please follow these steps:\\n\\n1. Contact Summit Sleep customer service department at [insert contact information] to request a Warranty Claim Form.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 87,\n    \"ProductId\": 4,\n    \"PageNumber\": 10,\n    \"Text\": \"2. Complete the Warranty Claim Form, providing details of the issue and attaching a copy of your original purchase receipt.\\n\\n3. Ship the completed form along with the defective product to the address provided by Summit Sleep customer service.\\n\\n4. Summit Sleep will assess the product and, if the claim is approved, will repair or replace the product accordingly.\\n\\n\\n6.2 Warranty Limitations\\n\\n\\nThe warranty for the Alpine 3000 Sleeping Bag does not cover the following:\\n\\n\\nDamage resulting from abuse, misuse, or neglect Normal wear and tear Damage caused by improper storage or cleaning Accidental damage or damage caused by natural disasters\\n\\n\\nPlease refer to the warranty card included with your purchase for the full terms and conditions of the limited warranty.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 88,\n    \"ProductId\": 4,\n    \"PageNumber\": 11,\n    \"Text\": \"(c) Summit Sleep 11\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 89,\n    \"ProductId\": 5,\n    \"PageNumber\": 1,\n    \"Text\": \"(c) Snugsleep 1\\n\\n\\nLunar Ultra Sleeping Bag\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 90,\n    \"ProductId\": 5,\n    \"PageNumber\": 2,\n    \"Text\": \"(c) Snugsleep 2\\n\\n\\n4 4 4 4 5 5 5 5 5 5 6 6 6 7 8 8 8 8 8 8 8 8 9 9 9 9\\n\\n\\n10 10 10 12 12 12 13 13 13 13\\n\\n1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.1 Purpose of Manual . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Scope of Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3 Product Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 91,\n    \"ProductId\": 5,\n    \"PageNumber\": 2,\n    \"Text\": \"2. Product Specifications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1 Dimensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Weight . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3 Insulation Material . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4 Lining Material . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5 Pillow Pocket . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 92,\n    \"ProductId\": 5,\n    \"PageNumber\": 2,\n    \"Text\": \"3. Quality Assurance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1: Compliance with Standards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2: Testing Procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3: Certifications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\\n\\n4. Usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1: Pre-Use Diagnostics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 93,\n    \"ProductId\": 5,\n    \"PageNumber\": 2,\n    \"Text\": \"4.1.1: Visual Inspection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.2: Insulation Integrity Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.3: Lining Quality Assessment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 94,\n    \"ProductId\": 5,\n    \"PageNumber\": 2,\n    \"Text\": \"4.2: Instructions for Use . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.1: Unfolding and Layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.2: Entering the Sleeping Bag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.3: Adjustment and Fastening . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 95,\n    \"ProductId\": 5,\n    \"PageNumber\": 2,\n    \"Text\": \"4.3: Post-Use Diagnostics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.1: Moisture and Odor Inspection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.2: Cleaning and Maintenance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 96,\n    \"ProductId\": 5,\n    \"PageNumber\": 2,\n    \"Text\": \"5. Maintenance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1: Cleaning Procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.2: Storage Recommendations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\\n\\n6. Troubleshooting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1 Common Issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2 Diagnostic Equipment Recommendations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 97,\n    \"ProductId\": 5,\n    \"PageNumber\": 2,\n    \"Text\": \"7. Warranty Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.1 Warranty Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.2 Warranty Exclusions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.3 Making a Warranty Claim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 98,\n    \"ProductId\": 5,\n    \"PageNumber\": 3,\n    \"Text\": \"(c) Snugsleep 3\\n\\n\\n13 13\\n\\n7.4 Limitation of Liability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.5 State/Province Rights . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 99,\n    \"ProductId\": 5,\n    \"PageNumber\": 4,\n    \"Text\": \"(c) Snugsleep 4\\n\\n1. Introduction\\n\\n\\n1.1 Purpose of Manual\\n\\nThe purpose of this manual is to provide detailed technical specifications, usage guidelines, and diagnostic procedures for the Lunar Ultra Sleeping Bag, manufactured by Snugsleep. This manual is intended for use by trained professionals and individuals with a background in industrial and scientific equipment operation. It is essential to follow the procedures outlined in this manual for the safe and effective use of the sleeping bag.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 100,\n    \"ProductId\": 5,\n    \"PageNumber\": 4,\n    \"Text\": \"1.2 Scope of Application\\n\\nThis manual applies to the Lunar Ultra Sleeping Bag, including all variants and models, manufactured by Snugsleep. It is important to note that this manual does not cover general sleeping bag usage or basic outdoor camping procedures. The scope of this manual is limited to technical specifications and advanced diagnostics related to the Lunar Ultra Sleeping Bag.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 101,\n    \"ProductId\": 5,\n    \"PageNumber\": 4,\n    \"Text\": \"1.3 Product Overview\\n\\nThe Lunar Ultra Sleeping Bag from Snugsleep is a high-performance outdoor sleeping solution designed for extreme comfort and insulation. Equipped with plush, hypoallergenic insulation and a soft lining, the sleeping bag provides a luxurious sleeping experience in outdoor environments. Additionally, the built-in pillow pocket adds convenience for users who prioritize comfort. The product is constructed with advanced materials and precision engineering to meet the highest industry standards for outdoor gear.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 102,\n    \"ProductId\": 5,\n    \"PageNumber\": 5,\n    \"Text\": \"(c) Snugsleep 5\\n\\n2. Product Specifications\\n\\n\\n2.1 Dimensions\\n\\n\\nThe Lunar Ultra Sleeping Bag from Snugsleep has the following dimensions:\\n\\n\\nLength: 210 cm Width (at the widest point): 85 cm Width (at the narrowest point): 55 cm\\n\\n\\n2.2 Weight\\n\\n\\nThe weight of the Lunar Ultra Sleeping Bag is:\\n\\n\\nTotal weight: 2.2 kg Packed size: 45 cm x 25 cm x 25 cm\\n\\n\\n2.3 Insulation Material\\n\\nThe insulation material used in the Lunar Ultra Sleeping Bag is a proprietary blend of synthetic fibers designed to provide maximum warmth and comfort in various outdoor conditions. This unique blend offers superior insulation properties while remaining lightweight and compressible for easy transport and storage.\",\n    \"Embedding\": \"RT40wluI30EjLgJC87QkwvgTPcGQ9gRCcfhoQcZWqkFqQJC/Uw0EQk4408BRAyrCNdUKQr70E0LVcoxBO4rjwK0Z/UEJWRzCj9BkwkVjrUJlr/tCyDvoQQHcIkJilM1BNiX2QdLJHkK+ySnB7JpQwR6ed0FOfRTDzt4GQGikhMCPhRVCJp6mwSNQy0EMWjbBb62HQn9wN8JeNerBFK/oQVU2mEHun1lC/4A3QqgI+MF6JPfBcQECwtpr4cFzCALC+l5GwbyLYkGAdxZCA0QIwRNA0sE67CFBtSp9wqynFcKOfCNC1lhAQbsoKEJLtlJC53tgQPXb1UEmbwXDLD4FQgdDnUFlIxTBdpW9wsl5G8EbkztCeZGJQgt4sr+BhA5Cv1IQQobqN0KHgDbBJK2VQBIa/0FVnanB6OVMwegBNUKW6j/CMEPJQKrwGsIlxB3BzKU3wuIXNcG6qMm/q33mQaZ6t0EheOrBOKNgwVqFN8JLpRLC8hLVQAjbdMLhPGbCN6bnQD7FDELwIojCZxm6QqolSkHKuYlCTpT9Qfy8uUFpAyNBvTf3wcPJskDGjk3C3B2XwQMiXMFIeVJBn6YsQfV3osDPqZHBkwQUQn265EFsFq5A5OzPQFTCMj4Z3dZBtsuPwiTHQcGwZEZCrbyuwGv048B95URB6koQwT68mUFtRhfBWPcIQicwNUKLXPhBdSZpwS4J+0CFXSHCK0cAwS1TjcHqCgxCDxFqQSsyc8L1FDpC3dr2wVfDHUKe/WrCkvabwrE66kCsamDCIJJ5QCL1ZsKnKxfCgsUBQmEgmMGIR3xCnjRLwryNR0K29sxBj0tGwDTtU0LWdEzC1Gs1QdmVtECZWQFBNjvNQfX9y0FPfTHASEqNwr/YYcFA0Ri/LsIOQmiF3sFefhBBv88qQd/aG0BvpEPCAX9WQn5i30Ew+8rAWnSswRm61kFF0e9BJAM8wVvHacEmq3LBejyGwdZ2SMHGhgDBirf3wEskskFTMAdCE/SxwG8GG8IzsV9AQ98DwXRucUF0pwfC+FydQPkDbECsxARBCkSewcKxLUDnsgZDO7eYwDBfIsGlD7rBVmi3QiAgWULOmc1BbOi7QOm7XULe1ApCRo79wa2xj0DMS4DC/qKUwkrn0sH4NAZCrUVjQk1nx8E0S/S/YhOswQ7/i0ASLJLCGy28wqV/HsNQTN3AIoU0QZpWtsEUGJ1CL2+7wTa9ZkLopuHAgjj/wTahFMJUy9JCT6rWQTE1JMJvwxlChdluwR9MTkH26zVAUNWuv1QTy0BTYcZAZHjBwb9hfEH07czBAOUZQSFQwcFTfe3BxrvgQl0pRsLGpV3BB5/wwW+sEMHnusFAa7XPQSl1U8LoLptCT9pMwaYrF8IJXIFCx6ZTQdp9J8Dmri7C0TDIQqrOFcJaEi7Co6+oQJUWy8ESWKjArsVswimy/8Hte/fB1I+SQdAhCUFMdQK//dlVwieFXEK/g5bBuVOawaYCzMFF/rpBAJjKOU4O0sFhQ47BvzRPwT4lP8LaX8rBGk3JQEW4DEITAwZCgft6Qe3QJ8IY3R9AWLDMQTJ3F8Jglw1BLwkDQmm6UsIw8dFB2VpPQsgxu0FB64tB16AUQSbOh0GAnuRBTr1nQDGwS0JDqiRC+X98wUttnEE10DRCBvrlwJPlSEIROPjAXc32QMkOr8B1LThATLI6wcLuRMM4mqzAjAc8wnSspUA0MwvCnZmCwCC1kEK6EYhCVxYPwgDCRcFfShvC9fspQrGN4T9/Q2zBKqmTQcPJscE67JrBPYcWwtN5vkHfJsLBEOamwdezTUEJNu1C97KqwegclkG8x51BNMSowSoHQUL9yatBfn+gQZSw7UCMtyHB1vJWQhhLa8JuJUXBLgL+QbhG18ERmnzBU7KIQRUDm0GYXSpCPNFWQEmfjUHV7KNBRP6fQiR+a0Eaa8jBy/05wf72gcEaKl/Cmum5wQmDy0GziOHAzDaBQcbG/0AdfbVB5oV5wIZAQsLTpWzAAbU+wm/iCD//4FDC1lSMwqU6IMKZ+RhC\"\n  },\n  {\n    \"ChunkId\": 103,\n    \"ProductId\": 5,\n    \"PageNumber\": 5,\n    \"Text\": \"2.4 Lining Material\\n\\nThe lining material of the Lunar Ultra Sleeping Bag is a soft, breathable, and hypoallergenic microfiber fabric. This high-quality lining provides a comfortable sleeping surface and wicks away moisture to keep you dry and warm throughout the night.\\n\\n\\n2.5 Pillow Pocket\\n\\nThe Lunar Ultra Sleeping Bag features a built-in pillow pocket located at the head of the bag. This pocket is designed to securely hold a pillow in place, providing added comfort and support for a restful night\\u0027s sleep.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 104,\n    \"ProductId\": 5,\n    \"PageNumber\": 6,\n    \"Text\": \"(c) Snugsleep 6\\n\\n3. Quality Assurance\\n\\n\\n3.1: Compliance with Standards\\n\\nThe Snugsleep Lunar Ultra Sleeping Bag has been designed and manufactured to meet the highest industry standards for outdoor sleeping equipment. Our product has been tested and validated against the following formal industry specification codes:\\n\\n\\nISPO 10500:2020 - International Standard for Sleeping Bags ASTM F1956-20 - Standard Specification for Padded Sleeping Bags EN 13537:2012 - European Standard for Sleeping Bags\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 105,\n    \"ProductId\": 5,\n    \"PageNumber\": 6,\n    \"Text\": \"The Lunar Ultra Sleeping Bag has been engineered to adhere to these rigorous standards, ensuring that it meets the strict requirements for comfort, insulation, durability, and safety in outdoor environments. Our commitment to compliance with these standards guarantees that you can rely on the quality and performance of our product during your outdoor adventures.\\n\\n\\n3.2: Testing Procedures\\n\\r\\n\\nTo ensure the highest quality and performance of the Lunar Ultra Sleeping Bag, rigorous testing procedures have been implemented during the manufacturing process. The following testing procedures have been conducted to verify the reliability and functionality of the product:\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 106,\n    \"ProductId\": 5,\n    \"PageNumber\": 6,\n    \"Text\": \"Insulation Testing: Comprehensive thermal conductivity tests have been performed using specialized industrial equipment to measure the insulation performance of the sleeping bag in various environmental conditions. Fabric Durability Testing: The fabric material of the sleeping bag has undergone extensive tensile strength and abrasion resistance tests to assess its durability and resilience. Zipper Performance Testing: The zippers on the sleeping bag have been subjected to repetitive open and close cycles to evaluate their smooth operation and resistance to wear.\\n\\n\\nThese testing procedures have been carried out in accordance with established industry protocols and have demonstrated the superior quality and reliability of the Lunar Ultra Sleeping Bag.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 107,\n    \"ProductId\": 5,\n    \"PageNumber\": 7,\n    \"Text\": \"(c) Snugsleep 7\\n\\n\\n3.3: Certifications\\n\\n\\nThe Snugsleep Lunar Ultra Sleeping Bag has obtained the following certifications from reputable standards bodies and regulatory authorities:\\n\\n\\nOEKO-TEX\\u00AE Standard 100: This certification confirms that the materials used in the sleeping bag are free from harmful substances and comply with human-ecological requirements. REACH Compliance: The product has been assessed for compliance with the European Union\\u0027s REACH regulation, demonstrating that it meets the strict standards for the safe use of chemicals in the manufacturing process.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 108,\n    \"ProductId\": 5,\n    \"PageNumber\": 7,\n    \"Text\": \"These certifications serve as a testament to the safety, quality, and environmental sustainability of the Lunar Ultra Sleeping Bag, underscoring our commitment to providing a premium sleeping experience for outdoor enthusiasts.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 109,\n    \"ProductId\": 5,\n    \"PageNumber\": 8,\n    \"Text\": \"(c) Snugsleep 8\\n\\n4. Usage\\n\\n\\n4.1: Pre-Use Diagnostics\\n\\n\\nBefore using the Lunar Ultra Sleeping Bag, it is essential to perform a series of pre-use diagnostics to ensure optimal performance and safety.\\n\\n\\n4.1.1: Visual Inspection\\n\\nConduct a visual inspection of the sleeping bag, checking for any signs of damage, tears, or abnormal wear and tear. Pay close attention to the stitching, zippers, and insulation material. Refer to the Industrial Standard Code IS-9587-2021 for visual inspection guidelines.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 110,\n    \"ProductId\": 5,\n    \"PageNumber\": 8,\n    \"Text\": \"4.1.2: Insulation Integrity Testing\\n\\nUsing an insulation integrity testing machine (model number: ITM-5500), test the thermal insulation properties of the sleeping bag. Ensure that the hypoallergenic insulation is evenly distributed and free from any cold spots. Refer to the ASTM Standard E2481-19 for insulation integrity testing procedures.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 111,\n    \"ProductId\": 5,\n    \"PageNumber\": 8,\n    \"Text\": \"4.1.3: Lining Quality Assessment\\n\\nUtilize a high-resolution fabric analysis microscope (model number: FAM-7000) to assess the quality and integrity of the soft lining material. Look for any signs of pilling, fraying, or discoloration. Consult the Research Paper \\u0022Advanced Techniques in Textile Quality Assessment\\u0022 for detailed lining quality assessment methodologies.\\n\\n\\n4.2: Instructions for Use\\n\\n\\nOnce the pre-use diagnostics have been successfully completed, follow the instructions below for proper use of the Lunar Ultra Sleeping Bag.\\n\\n\\n4.2.1: Unfolding and Layout\\n\\nTo begin, unfold the sleeping bag and lay it flat on a clean and dry surface. Ensure that the built-in pillow pocket is positioned at the top of the sleeping bag for easy access.\\n\\n\\n4.2.2: Entering the Sleeping Bag\",\n    \"Embedding\": \"xSBfwsfjLELM5rVBvsbhwaco3EGZXG9Cl0gjQk7ahEIwM3bCkSmJQcpXJEHuR2DCtMTCQKbVD0JTMBHA6x0XwOqu5kHuDi3B8xoSwrC0U0Fd5aRCiZudQK++8kCvuPxB1AMAQt9rm0FTkHXC0+aKwk+uG8J+KDXDORk4wu9ckkGHIDlCxsESwvIC4D9581VAzaI5Qf3u0MHq0ULAvgJaQHdTL0I9NUlBWjCuP1M4QsGog6DBEZUfwnUnjkErh07C7xBSvhl9JcKpp2ZANng3wtuLk8GzD2jCtB5IQVAlTMBod4BCHNQJQi4oFkK/+5tC3yKKQRnHg0GzPznDEWSGQr9CjkGv9lE/8teTwqjFl8GsnNBB+lmwQuQ5hMGg1tVB8HwNQvPoQkKw+YpBlTnaP7+3jkIJ5oPCEBhpQaPcEUEfmGzCJRiEQmOEIkLyovXBLK2lwX5eUkGo8qJA9DBkQfYaZUKwG/fAvsXmQa373cEDXUrCzJB6QgcUXsL8mA3C8YUHwjtducAqJ+jBzL35QksFfcKcVrBAiyLBQSJvWsFecyfCBaTRwZz2YcEwZo7Cwv33wUKCxkF4aP/BDFEJwWYAdkHILDdBhIS7wZPtakLY+bNBcIJ1QW+spkEKXDbBH4VpwuPuLsKUcd1BAHBkwi7F48EWMpI/lk0zQjsWQ0Jr+gNBHJGEQSBFBELdljDAtnZ0wnmbKEI2iV3CuLK3QM18BkInO0xBhhFVQTZPHsK+fwzCt13EwSwNEULv10bCz31DwmMY2EG+r37CdRDXQX3yY8JDcMXClq8UQpEfCELNsJ5A3U5jwWW5okL8noBBSIgfQi56hkHSL9/BlSY9QhkEtcFpABzCcd1KwlzKBUMoyO/BF8qfwfzmF8KPcxJBDH4MQn6jQMJp7gzAXCjLQdBF2sGfgE7BzgBwQZeVjMG1TUZB12OgwfvhCkINg+RBUbYmQpBqS8LdpYfCP9D5QW0jOUKAO1nC8hBWwAL3wkHCoklCV8gBPqAH1MLmx43BsiuXP4ceK0JG7m/CRPYUQUaGB8LwNE3AEA8GwvpvPsKgEe5CEzCDwOj8YUBiP0M+lHtdQv6NmkLCBMtB7NuKwKm91EIbQppCi68GwubuX0K7PapBRXRTwuxnTsLFAstB1HVhQiSNaMJmXEjCRP4HQseuxEECfdbBzGvWwvKjRcPsj4c/tO8MQhzqKELejVNCJsNZQNoxSEJe7rfBAp+kwRSy78BeqO5CehAQQpcLHMFWUoRBk8AoPxTX+EGjGDvBFL4SwlePB8LCANG/CgYNwsykPEIdwi1BVwKRwdnA6cBzhyfCRjIOQ08AecLxV7XBJm0DQXeVmECOncbBPxdVwK4JKcL73CNBEQ0fQU0ZacGg7l9CnsywwMUsHMLnjInB6YMgQsfkbEHTWZzCkrBUwiYHAcKzswVBpq15wh/bdcFwVBnCLurnwNEbkcHgJoTBoS0FwgtcmMFJ6rLBid0fwkIarMFuCRTB6SLywcPjhr+vJdfAzBEHQR8C5cHaHpdAVX8KQrBvNUE2nQNB2ud9QtN5hsJ1fApCIMRFQrY4qsBDPprBYTENQhuYqEHRsTJCE4P8wNwMj0CFd3rBGedzQqzQO0I/o71AQ96xwc5fT0Fob1lCaJkNwtqvE8Gh/2RCRsddwf0Ge0GWl/ZBDGkGwtwShcHZF6lBHcCpwfryPsMQcw7BiDeRwWj5FkL1czzB27tlwVSbB0IF5SVCJPJKwbFcJ0H1DvDBopObQq5pd0FqfFjCBHfgQX6tIMCNzjU/SOSDwnUjYEJEz4rCSIdKQVbeKMBzry1DfEgMwabs6UGDhLdBfwvLQDKiAEI8peJBEjqMwSJrgELB0nvBTWBkQiXNscCUkO1BNecPQk7rhMH197nB+qCZP8pdR0GKwTxCIbEGQoMKfcHf24DBWCirQsK88EHHgQnBW3goQVm8gEAGLprCzgfawYq+tUB3phDC+M7cQYqJf0FZdXFCr6YSQpMB9UEeJkvBvPKDQAoxn0GuE1rCSRsYwvdeLEFYc8HA\"\n  },\n  {\n    \"ChunkId\": 112,\n    \"ProductId\": 5,\n    \"PageNumber\": 9,\n    \"Text\": \"(c) Snugsleep 9\\n\\nCarefully unzip the sleeping bag using the color-coded dual zipper system, taking care not to force the zippers. Slide into the sleeping bag, positioning your head within the built-in pillow pocket for added comfort.\\n\\n\\n4.2.3: Adjustment and Fastening\\n\\nOnce inside the sleeping bag, adjust the hood for a snug fit around your head, and secure the zipper to the desired position. Utilize the interior mesh storage pockets for keeping personal items within easy reach.\\n\\n\\n4.3: Post-Use Diagnostics\\n\\n\\nAfter each use, it is imperative to conduct post-use diagnostics to assess the condition of the Lunar Ultra Sleeping Bag.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 113,\n    \"ProductId\": 5,\n    \"PageNumber\": 9,\n    \"Text\": \"4.3.1: Moisture and Odor Inspection\\n\\n\\nInspect the sleeping bag for any signs of moisture accumulation or unpleasant odors. Utilize a moisture content analyzer (model number: MCA-2000) and an electronic nose sensor (model number: ENS-500) for comprehensive moisture and odor inspection.\\n\\n\\n4.3.2: Cleaning and Maintenance\\n\\nFollow the cleaning and maintenance guidelines outlined in the Lunar Ultra Sleeping Bag Maintenance Manual (part number: LUSB-MM-101) to ensure the longevity of the sleeping bag. Use only the recommended cleaning products and techniques as specified by Snugsleep.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 114,\n    \"ProductId\": 5,\n    \"PageNumber\": 10,\n    \"Text\": \"(c) Snugsleep 10\\n\\n5. Maintenance\\n\\n\\n5.1: Cleaning Procedures\\n\\nThe Lunar Ultra Sleeping Bag is designed for easy and efficient cleaning to ensure its longevity and optimal performance. Follow the cleaning procedures outlined below to maintain the quality of your sleeping bag:\\n\\n1. Spot Cleaning: For small stains or spills, spot cleaning with mild soap and water is recommended. Gently dab the affected area with a soft cloth, then allow it to air dry thoroughly before storage.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 115,\n    \"ProductId\": 5,\n    \"PageNumber\": 10,\n    \"Text\": \"2. Machine Washing: If the entire sleeping bag requires cleaning, it can be machine washed in a large capacity front-loading washing machine. Use a gentle cycle with cold water and a mild, non-detergent soap. Ensure all zippers and fastenings are closed before washing.\\n\\n3. Drying: After washing, the sleeping bag should be tumble dried on a low heat setting. Ensure it is completely dry before storage to prevent the growth of mold and mildew.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 116,\n    \"ProductId\": 5,\n    \"PageNumber\": 10,\n    \"Text\": \"4. Professional Cleaning: If necessary, professional cleaning by a reputable provider who specializes in sleeping bag maintenance is recommended.\\n\\n\\n5.2: Storage Recommendations\\n\\nProper storage of the Lunar Ultra Sleeping Bag is essential to maintain its loft and insulation properties. Follow these recommendations to ensure the longevity and performance of your sleeping bag:\\n\\n1. Dry Storage: Always store the sleeping bag in a clean, dry environment. Avoid compressed or humid storage conditions, as these can degrade the insulating properties of the bag.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 117,\n    \"ProductId\": 5,\n    \"PageNumber\": 10,\n    \"Text\": \"2. Loose Storage: When not in use, the sleeping bag should be stored in a large, breathable storage sack to prevent compression of the insulation.\\n\\n3. Air Out: Periodically, the sleeping bag should be removed from storage and aired out in a well-ventilated area to maintain freshness and prevent odors.\\n\\n4. Avoid Prolonged Compression: Do not leave the sleeping bag compressed for extended periods, as this can cause permanent damage to the insulation.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 118,\n    \"ProductId\": 5,\n    \"PageNumber\": 11,\n    \"Text\": \"(c) Snugsleep 11\\n\\n5. Pillow Pocket: Ensure that the built-in pillow pocket is empty and free from debris before storing the sleeping bag.\\n\\n\\nFollowing these cleaning and storage procedures will help to maintain the quality and performance of your Lunar Ultra Sleeping Bag for years of comfortable outdoor adventures.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 119,\n    \"ProductId\": 5,\n    \"PageNumber\": 12,\n    \"Text\": \"(c) Snugsleep 12\\n\\n6. Troubleshooting\\n\\n\\n6.1 Common Issues\\n\\nThe Snugsleep Lunar Ultra Sleeping Bag is designed to provide optimal comfort and performance in a variety of outdoor conditions. However, there are a few common issues that users may encounter. Please refer to the following table for troubleshooting guidance:\\n\\n\\nIssue Possible Cause Solution\\n\\n\\nLoss of Insulation Wear and tear from prolonged use or storage\\n\\nInspect the sleeping bag for any damage or tears. Consider replacing the insulation if necessary.\\n\\n\\nZipper Stuck Debris caught in the zipper mechanism\\n\\nGently clean the zipper with a soft brush or compressed air. Avoid using excessive force to avoid damaging the zipper.\\n\\n\\nUncomfortable Sleeping\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 120,\n    \"ProductId\": 5,\n    \"PageNumber\": 12,\n    \"Text\": \"Incorrect positioning or adjustment of the bag\\n\\n\\nAdjust the positioning of the sleeping bag and consult the user manual for optimal usage.\\n\\n\\n6.2 Diagnostic Equipment Recommendations\\n\\n\\nTo ensure the utmost performance of the Snugsleep Lunar Ultra Sleeping Bag, it is recommended to utilize the following diagnostic equipment:\\n\\n\\nThermal Imaging Camera: Use to identify any potential heat loss areas in the sleeping bag. Hypoallergenic Insulation Tester: Measure the integrity and effectiveness of the insulation material. Sleeping Bag Moisture Analyzer: Check for any moisture buildup within the sleeping bag, which can impact its insulating properties. Comfort Pressure Gauge: Monitor the pressure distribution within the sleeping bag for optimal comfort.\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 121,\n    \"ProductId\": 5,\n    \"PageNumber\": 13,\n    \"Text\": \"(c) Snugsleep 13\\n\\n7. Warranty Information\\n\\n\\n7.1 Warranty Coverage\\n\\nThe Snugsleep Lunar Ultra Sleeping Bag is covered by a limited lifetime warranty. This warranty applies to the original purchaser and covers defects in material and workmanship under normal use. Snugsleep will repair or replace the product at its discretion if a defect is found.\\n\\n\\n7.2 Warranty Exclusions\\n\\nThe warranty does not cover damage caused by misuse, neglect, accidents, or unauthorized repairs or modifications. It also does not cover normal wear and tear, cosmetic damage, or damage caused by improper storage.\\n\\n\\n7.3 Making a Warranty Claim\",\n    \"Embedding\": \"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\"\n  },\n  {\n    \"ChunkId\": 122,\n    \"ProductId\": 5,\n    \"PageNumber\": 13,\n    \"Text\": \"To make a warranty claim, the original purchaser must provide proof of purchase and contact Snugsleep customer service. The product may need to be shipped to a designated service center for inspection and repair or replacement.\\n\\n\\n7.4 Limitation of Liability\\n\\nSnugsleep\\u0027s liability under this warranty is limited to the repair or replacement of the product as stated in section 7.1. Snugsleep is not liable for any incidental or consequential damages arising from the use of the product.\\n\\n\\n7.5 State/Province Rights\\n\\n\\nThis warranty gives the owner specific legal rights, and they may also have other rights that vary from state to state or province to province.\",\n    \"Embedding\": \"UDcvwiH/vcEZlCVC41uNwpkNw8GDZ6PAkBUpQvmkDEK/6dLBcDRtQbfUwMEuPpQ/qKH6QSsep0GWDfRA53yvvhu1WUJ+GGlAGXcgwkgcD0LxYVhBkNX5wZJJO0FRvnpBt6AAwZTla8GrIuPAWqvFQUpajsE2KuXC8G8EwduhykAaXYbCnbwOQaFQdEGlaH7CVowFQYIFekFhyf1BLIiIwPBxWsGo/mhCrlzXQFnD/8FSPEHCz3eRwVbEjUHw+JvBwTZ5QqXNFsIciARCEXAPwZiLDMHK+KbBgRdiwZ0BMEKaqjpCfBnav3DbEULEw6a/IO6GQS8IMMH/9SPDvQvaQSAGF0KsKNxBK34cQBLsKsHv7S5C2NztQRWlGECuK85BoaDYwaSXdULvkIjA+80MQeGgSkFYiJbAiS9Dwk+0MkGC8XTBDTmkwbMj7UApl7s9LJbkwVTahcKNdK5BRMVWwXsBgkIiQpzBFkf4QVkh78DjArVBTxceQipiVMJtmgrCHRBHQKShKUHNAJvC8SSoQmoYs8GVIC9C8Oi4wSr1asG1xJBA3IyMwQNnicHUY/lBz4qkwXCEtcH3YZlBj3WYQRU1AUJx9sDB8ipmwbcBnkJ3unjAaTiVQB0jGkLRIArBEFGywQYl+EGo3iBC6PZaQNCVBsILBS/CMY7aQVy+TUL2QZBAbghPQf7Gv7+EBjLCC4SIQc/VqEEy5d5B3Aswwegx6MHFzJVCHrUWQiow5MFeG1ZB/gbDwghNckH4VgTC2ajgwT+qAEIUi6PCUDQuQskqGcIASNDB4LWRwQFDrEFFuYVABJXSweggGkLdE5hBwfy3Qd4A8sGBjWrCLg6IQRTgQkKuEKLB39nYwLu+l0I+w9xASiWqwtoQ08CE/iFBQ0cXweoiBsFMTopBQFAqQnvBVUGi3PbB8uERQjOTYEIzY82+GJEjv/jTKD/8zkVCB2HHwIh0GcDpDa/AjR76wLosJEHTeM7BzEePwS21ikGAsgdChpXLwd1bBcLq6KTB/DugwdEX88EugZfAIBbGPhWuqcKfAc0/prYAQjrW1MCZyYdCdv/9Pro6g8G1DJHBKhETQjjWVEKyqQ5CSCGfwQxkYkLeplxBl8+WwAmcBUKAF1JBZEQgwYWhnsCaeUtCpj8OQSfQhUEDbpNBvCCRwYNam0FSjA5CS1c2QPtRGMP/AW/A59EAwWvww0HtCrpBjZQrwVWc2MCmperBgvakwRt/FcGLgLlCTZ1fwQFNg78OwX7AZFkKv5rBPcIynSZBswvZwZtWrsGL1X7B0eVVwgl5d0GMTgjCEO3ZwewjkkH2LgLCtpDHQpJbyMBiPAJBmYH/weZFMMHedtdBlWlywfExVcIY6yhCA2IFQr5FvcKvKQNC/38AQUvRKcJdzsNAnkqHQou6g8EuPN/BwgXLQIUO5cHVT5XBejIhQs+3Z8JnBPRAHa4KQXsaK0HeNWfBYMtbQszflUK9iAnCylP8wU1NtkGHUUPCUh/fPxXSDEJf1pfBV1/aQe8q+cFuAzBC6z2KQNZqX0C4DJTB2v4+wVVK/cDZhZrBb/XlQd/jCsKGyJDB9UMAwtBg0EFxpAPBPxI8v6cxzMFGQ1fBaJUEQj1Vcb9v6jtCDCtYQaEGAEISDM8/zE2qwbGGgkK2iqBBqYAbwuJMJMHgt81B1fiawEvvikE/0f9BNOyDQLIaOMPhzvrBwofiwbLl10GiP4rCA9DlQaxZGkAlULJB8JFAwgnV7MHdoIjBXv7FQKP9XsGY9eg/e2GZQTQ6RUGqYCJClc/7wa2fJkIEemTCGJx5wR0g9UFrswlDDJn+QZyZmEGyPA5Byd6wQU4VrkKFAaNB3HaZwV9UQUBp2afBU4Q9QsRcTsEjpgZCBZsBwXjsP8L4BOnAN/orQae0zkBDVlfC7SEhwmSnPEK6HcdAVVbuQrcjKMKFIUnCeyIkwssO7MFmbqJBUVQjQSNxl0DpJPhBLplBQRDP10ArlzbAREVPwZk4iUF+kJJBwCERwY08H0ENTEzCcA3awUKuRkI4LIhB\"\n  }\n]"
  },
  {
    "path": "seeddata/test/products.json",
    "content": "[\n  {\n    \"ProductId\": 1,\n    \"CategoryId\": 1,\n    \"Brand\": \"Rugged Riders\",\n    \"Model\": \"Trailblazer Bike Helmet\",\n    \"Description\": \"The Trailblazer Bike Helmet from Rugged Riders offers maximum protection with an aerodynamic design, adjustable fit, and built-in LED safety light.\",\n    \"Price\": 89.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 2,\n    \"CategoryId\": 3,\n    \"Brand\": \"Insulite\",\n    \"Model\": \"Arctic Explorer Sleeping Bag\",\n    \"Description\": \"Stay warm and comfortable in the great outdoors with the Arctic Explorer Sleeping Bag from Insulite. Features include lightweight insulation, water-resistant shell, and compression sack for easy packing.\",\n    \"Price\": 129.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 3,\n    \"CategoryId\": 1,\n    \"Brand\": \"Velocity Pro\",\n    \"Model\": \"Stealth Bike Helmet\",\n    \"Description\": \"The Stealth Bike Helmet from Velocity Pro is designed for speed and performance. With a sleek, aerodynamic design, adjustable ventilation, and impact-absorbing technology, it\\u0027s the ultimate choice for serious cyclists.\",\n    \"Price\": 119.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 4,\n    \"CategoryId\": 3,\n    \"Brand\": \"Summit Sleep\",\n    \"Model\": \"Alpine 3000 Sleeping Bag\",\n    \"Description\": \"Conquer any climate with the Alpine 3000 Sleeping Bag from Summit Sleep. This high-performance sleeping bag features advanced insulation, durable ripstop fabric, and a snug mummy shape for maximum warmth.\",\n    \"Price\": 159.99,\n    \"NameEmbedding\": \"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\"\n  },\n  {\n    \"ProductId\": 5,\n    \"CategoryId\": 3,\n    \"Brand\": \"Snugsleep\",\n    \"Model\": \"Lunar Ultra Sleeping Bag\",\n    \"Description\": \"Experience luxurious comfort in the great outdoors with the Lunar Ultra Sleeping Bag from Snugsleep. With plush, hypoallergenic insulation, a soft lining, and a built-in pillow pocket, it\\u0027s the ultimate sleeping companion for your adventures.\",\n    \"Price\": 179.99,\n    \"NameEmbedding\": \"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\"\n  }\n]"
  },
  {
    "path": "seeddata/test/tickets.json",
    "content": "[\n  {\n    \"TicketId\": 1,\n    \"ProductId\": 1,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 1,\n    \"ShortSummary\": \"LED safety light issue, warranty claim initiated\",\n    \"LongSummary\": \"Customer seeks assistance with non-functional LED safety light, has followed troubleshooting steps, and initiated warranty claim process. Next agent should provide guidance on potential return or repair process.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 1,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear Customer Support, \\n\\nI recently purchased the Rugged Riders Trailblazer Bike Helmet and I must say, I am quite impressed with its features and design. However, I seem to be having trouble with the built-in LED safety light. It does not seem to be working as expected, despite following the instructions carefully. I have tried troubleshooting on my own, but I am still unable to make it work. \\n\\nI would greatly appreciate it if you could provide assistance on how to resolve this issue. If the LED safety light is defective, I would like to request a replacement or a repair. I believe that the safety features of the helmet are crucial, and I want to ensure that it is functioning properly. Alternatively, if it cannot be resolved, I may need to request a refund. I hope we can find a solution to this matter quickly. Thank you for your attention to this issue. \\n\\nSincerely, \\nEmily Johnson\"\n      },\n      {\n        \"MessageId\": 2,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Dear Emily Johnson, \\n\\nThank you for reaching out to us regarding the issue with the LED safety light on your Rugged Riders Trailblazer Bike Helmet. According to the user manual, the first troubleshooting step is to check the battery and ensure that it is properly installed and functional. If necessary, you can replace the battery with a CR2032 3V battery. If you require further assistance, you may also contact Rugged Riders customer support for warranty-related issues, as there is a limited warranty that covers manufacturing defects for a period of 1 year from the date of purchase. We hope this information helps resolve the issue. If you have any further questions or need assistance with the warranty claim process, please feel free to let us know.\\n\\nSincerely, \\nAdventureWorks Support\"\n      },\n      {\n        \"MessageId\": 3,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear AdventureWorks Support, \\n\\nThank you for your prompt response and the troubleshooting steps provided. I have checked the battery as suggested, and it appears to be properly installed and functional. I even tried replacing it with a new CR2032 3V battery, but unfortunately, the LED safety light is still not working. I would like to proceed with the warranty claim process to address this issue, as it seems to be a manufacturing defect. Please guide me on how to initiate the warranty claim and what steps are involved. I appreciate your assistance in resolving this matter. \\n\\nSincerely, \\nEmily Johnson\"\n      },\n      {\n        \"MessageId\": 4,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"Dear Emily Johnson, \\n\\nThank you for your patience. You can initiate the warranty claim process by contacting Rugged Riders customer service at warranty@ruggedriders.com. Please provide the original proof of purchase and a detailed description of the issue. Rugged Riders will assess the claim and provide further instructions for return or repair. In the meantime, please ensure that the LED safety light is securely inserted and the power button is pressed to turn it on, as outlined in the user manual. If the light still does not work, Rugged Riders customer support can assist further. Sincerely, AdventureWorks Support\"\n      },\n      {\n        \"MessageId\": 5,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Dear AdventureWorks Support, \\n\\nI have contacted Rugged Riders customer service at warranty@ruggedriders.com and provided the original proof of purchase along with a detailed description of the issue. I have followed the instructions in the user manual to ensure that the LED safety light is securely inserted and the power button is pressed to turn it on, but unfortunately, the light is still not working. I hope Rugged Riders can assess the claim and provide further instructions for return or repair soon. Thank you for your assistance in this matter.\\n\\nSincerely, Emily Johnson\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 2,\n    \"ProductId\": 1,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 2,\n    \"ShortSummary\": \"Product Performance Reassurance\",\n    \"LongSummary\": \"Customer seeking reassurance about the performance of Trailblazer Bike Helmet. Fit seems good. No further assistance needed at this time.\",\n    \"CustomerSatisfaction\": 6,\n    \"TicketStatus\": \"Closed\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 6,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Hello, I recently purchased the Trailblazer Bike Helmet from Rugged Riders and I just want to make sure it\\u0027s performing as expected. I\\u0027ve been using it for a few rides now and it seems to be working well, but I just wanted to double-check. I appreciate any reassurance you can provide. Thank you for your time.\"\n      },\n      {\n        \"MessageId\": 7,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"According to the manual, the Trailblazer Bike Helmet is designed and intended for use as protective headgear during cycling activities. It should not be used for any other purposes. The warranty covers manufacturing defects for a period of 1 year from the date of purchase, and Rugged Riders provides a limited warranty for the helmet. If you have any issues with the fit, please contact Rugged Riders customer support for further assistance.\"\n      },\n      {\n        \"MessageId\": 8,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"Thank you for the information. I\\u0027ve checked the fit of the helmet and it seems to be good. I appreciate your assistance.\"\n      }\n    ]\n  },\n  {\n    \"TicketId\": 3,\n    \"ProductId\": 2,\n    \"CreatedAt\": \"0001-01-01T00:00:00\",\n    \"CustomerId\": 3,\n    \"ShortSummary\": \"Inquiry about Arctic Explorer Sleeping Bag\\u0027s Temperature Rating\",\n    \"LongSummary\": \"Customer seeks specific details about the Arctic Explorer Sleeping Bag\\u0027s temperature rating and performance in sub-zero conditions. They plan to contact customer service for further assistance. Next support agent should provide detailed temperature rating and performance information.\",\n    \"CustomerSatisfaction\": 2,\n    \"TicketStatus\": \"Open\",\n    \"TicketType\": \"Question\",\n    \"Messages\": [\n      {\n        \"MessageId\": 9,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I need to know if the Arctic Explorer Sleeping Bag is guaranteed to keep me warm in temperatures below freezing. I expect a detailed response before I even consider making a purchase. If it doesn\\u0027t meet my expectations, I demand a full refund. I won\\u0027t settle for anything less than perfect performance from this sleeping bag.\"\n      },\n      {\n        \"MessageId\": 10,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Arctic Explorer Sleeping Bag is equipped with state-of-the-art lightweight insulation that ensures maximum heat retention while keeping the overall weight of the sleeping bag to a minimum. The water-resistant shell provides a protective barrier against moisture and drafts, keeping you dry and warm throughout the night. If you have any questions about the warranty for your Arctic Explorer Sleeping Bag, please refer to the warranty card included with your purchase. For additional support, feel free to contact our customer service team.\"\n      },\n      {\n        \"MessageId\": 11,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I appreciate the information you provided about the insulation and water-resistant shell of the Arctic Explorer Sleeping Bag. However, I need more details about the specific temperature rating and performance in sub-zero conditions. I expect a comprehensive response to my queries before I make any decisions. Also, I will be contacting your customer service team for further assistance.\"\n      },\n      {\n        \"MessageId\": 12,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": false,\n        \"Text\": \"The Arctic Explorer Sleeping Bag is equipped with state-of-the-art lightweight insulation that ensures maximum heat retention, and the water-resistant shell provides a protective barrier against moisture and drafts. When using the sleeping bag, make sure to fully close the zipper to retain maximum warmth. Gently pull the zipper tab downwards to close the sleeping bag securely. For warranty information, please refer to the warranty card included with your purchase. If you have further questions, feel free to contact our customer service team. I hope this information is helpful to you.\"\n      },\n      {\n        \"MessageId\": 13,\n        \"CreatedAt\": \"0001-01-01T00:00:00\",\n        \"TicketId\": 0,\n        \"IsCustomerMessage\": true,\n        \"Text\": \"I appreciate the information you provided, but I still need specific details about the temperature rating and performance of the Arctic Explorer Sleeping Bag in sub-zero conditions. I expect a comprehensive response before I make any decisions. Also, I will be contacting your customer service team for further assistance.\"\n      }\n    ]\n  }\n]"
  },
  {
    "path": "src/AppHost/.gitignore",
    "content": "appsettings.Local.json\n"
  },
  {
    "path": "src/AppHost/AppHost.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n    <TargetFramework>net8.0</TargetFramework>\n    <ImplicitUsings>enable</ImplicitUsings>\n    <Nullable>enable</Nullable>\n    <IsAspireHost>true</IsAspireHost>\n    <UserSecretsId>dbe89ad9-90f1-44de-9646-7e98b2d8c69d</UserSecretsId>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Aspire.Hosting.AppHost\" />\n    <PackageReference Include=\"Aspire.Hosting.Azure.Storage\" />\n    <PackageReference Include=\"Aspire.Hosting.PostgreSQL\" />\n    <PackageReference Include=\"Aspire.Hosting.Qdrant\" />\n    <PackageReference Include=\"Aspire.Hosting.Redis\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\Backend\\Backend.csproj\" />\n    <ProjectReference Include=\"..\\CustomerWebUI\\CustomerWebUI.csproj\" />\n    <ProjectReference Include=\"..\\IdentityServer\\IdentityServer.csproj\" />\n    <ProjectReference Include=\"..\\StaffWebUI\\StaffWebUI.csproj\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/AppHost/Ollama/OllamaResource.cs",
    "content": "﻿namespace Aspire.Hosting;\n\ninternal class OllamaResource(string name, string[] models, string defaultModel, bool enableGpu) : ContainerResource(name)\n{\n    public string[] Models { get; } = models;\n    public string DefaultModel { get; } = defaultModel;\n    public bool EnableGpu { get; } = enableGpu;\n}\n"
  },
  {
    "path": "src/AppHost/Ollama/OllamaResourceExtensions.cs",
    "content": "﻿using System.Net.Http.Json;\nusing System.Text.Json;\nusing Aspire.Hosting.Lifecycle;\nusing Microsoft.Extensions.Logging;\n\nnamespace Aspire.Hosting;\n\ninternal static class OllamaResourceExtensions\n{\n    public static IResourceBuilder<OllamaResource> AddOllama(this IDistributedApplicationBuilder builder, string name, string[]? models = null, string? defaultModel = null, bool enableGpu = true, int? port = null)\n    {\n        const string configKey = \"OllamaModel\";\n        defaultModel ??= builder.Configuration[configKey];\n\n        if (models is null or { Length: 0 })\n        {\n            if (string.IsNullOrEmpty(defaultModel))\n            {\n                throw new InvalidOperationException($\"Expected the parameter '{nameof(defaultModel)}' or '{nameof(models)}' to be nonempty, or to find a configuration value '{configKey}', but none were provided.\");\n            }\n            models = [defaultModel];\n        }\n\n        var resource = new OllamaResource(name, models, defaultModel ?? models.First(), enableGpu);\n        var ollama = builder.AddResource(resource)\n            .WithHttpEndpoint(port: port, targetPort: 11434)\n            .WithImage(\"ollama/ollama\", tag: \"0.6.5\");\n\n        if (enableGpu)\n        {\n            ollama = ollama.WithContainerRuntimeArgs(\"--gpus=all\");\n        }\n\n        builder.Services.TryAddLifecycleHook<OllamaEnsureModelAvailableHook>();\n\n        // This is a bit of a hack to show downloading models in the UI\n        builder.AddResource(new OllamaModelDownloaderResource($\"ollama-model-downloader-{name}\", resource))\n            .WithInitialState(new()\n            {\n                Properties = [],\n                ResourceType = \"ollama downloader\",\n                State = KnownResourceStates.Hidden\n            })\n            .ExcludeFromManifest();\n\n        return ollama;\n    }\n\n    public static IResourceBuilder<OllamaResource> WithDataVolume(this IResourceBuilder<OllamaResource> builder)\n    {\n        return builder.WithVolume(CreateVolumeName(builder, builder.Resource.Name), \"/root/.ollama\");\n    }\n\n    public static IResourceBuilder<TDestination> WithReference<TDestination>(this IResourceBuilder<TDestination> builder, IResourceBuilder<OllamaResource> ollamaBuilder)\n        where TDestination : IResourceWithEnvironment\n    {\n        return builder\n            .WithReference(ollamaBuilder.GetEndpoint(\"http\"))\n            .WithEnvironment($\"{ollamaBuilder.Resource.Name}:Type\", \"ollama\")\n            .WithEnvironment($\"{ollamaBuilder.Resource.Name}:LlmModelName\", ollamaBuilder.Resource.DefaultModel);\n    }\n\n    private static string CreateVolumeName<T>(IResourceBuilder<T> builder, string suffix) where T : IResource\n    {\n        // Ideally this would be public\n        return (string)typeof(ContainerResource).Assembly\n            .GetType(\"Aspire.Hosting.Utils.VolumeNameGenerator\", true)!\n            .GetMethod(\"CreateVolumeName\")!\n            .MakeGenericMethod(typeof(T))\n            .Invoke(null, [builder, suffix])!;\n    }\n\n    private sealed class OllamaEnsureModelAvailableHook(\n        ResourceLoggerService loggerService,\n        ResourceNotificationService notificationService,\n        DistributedApplicationExecutionContext context) : IDistributedApplicationLifecycleHook\n    {\n        public Task AfterEndpointsAllocatedAsync(DistributedApplicationModel appModel, CancellationToken cancellationToken = default)\n        {\n            if (context.IsPublishMode)\n            {\n                return Task.CompletedTask;\n            }\n\n            var client = new HttpClient();\n\n            foreach (var downloader in appModel.Resources.OfType<OllamaModelDownloaderResource>())\n            {\n                var ollama = downloader.ollamaResource;\n\n                var logger = loggerService.GetLogger(downloader);\n\n                _ = Task.Run(async () =>\n                {\n                    var httpEndpoint = ollama.GetEndpoint(\"http\");\n\n                    // TODO: Make this resilient to failure\n                    var ollamaModelsAvailable = await client.GetFromJsonAsync<OllamaGetTagsResponse>($\"{httpEndpoint.Url}/api/tags\", new JsonSerializerOptions(JsonSerializerDefaults.Web));\n\n                    if (ollamaModelsAvailable is null)\n                    {\n                        return;\n                    }\n\n                    var availableModelNames = ollamaModelsAvailable.Models?.Select(m => m.Name) ?? [];\n\n                    var modelsToDownload = ollama.Models.Except(availableModelNames);\n\n                    if (!modelsToDownload.Any())\n                    {\n                        return;\n                    }\n\n                    logger.LogInformation(\"Downloading models {Models} for ollama {OllamaName}...\", string.Join(\", \", modelsToDownload), ollama.Name);\n\n                    await notificationService.PublishUpdateAsync(downloader, s => s with\n                    {\n                        State = new(\"Downloading models...\", KnownResourceStateStyles.Info)\n                    });\n\n                    await Parallel.ForEachAsync(modelsToDownload, async (modelName, ct) =>\n                    {\n                        await DownloadModelAsync(logger, httpEndpoint, modelName, ct);\n                    });\n\n                    await notificationService.PublishUpdateAsync(downloader, s => s with\n                    {\n                        State = new(\"Models downloaded\", KnownResourceStateStyles.Success)\n                    });\n                },\n                cancellationToken);\n            }\n\n            return Task.CompletedTask;\n        }\n\n        private static async Task DownloadModelAsync(ILogger logger, EndpointReference httpEndpoint, string? modelName, CancellationToken cancellationToken)\n        {\n            logger.LogInformation(\"Pulling ollama model {ModelName}...\", modelName);\n\n            var httpClient = new HttpClient { Timeout = TimeSpan.FromDays(1) };\n            var request = new HttpRequestMessage(HttpMethod.Post, $\"{httpEndpoint.Url}/api/pull\") { Content = JsonContent.Create(new { name = modelName }) };\n            var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);\n            var responseContentStream = await response.Content.ReadAsStreamAsync(cancellationToken);\n            var streamReader = new StreamReader(responseContentStream);\n            var line = (string?)null;\n            while ((line = await streamReader.ReadLineAsync(cancellationToken)) is not null)\n            {\n                logger.Log(LogLevel.Information, 0, line, null, (s, ex) => s);\n            }\n\n            logger.LogInformation(\"Finished pulling ollama mode {ModelName}\", modelName);\n        }\n\n        record OllamaGetTagsResponse(OllamaGetTagsResponseModel[]? Models);\n        record OllamaGetTagsResponseModel(string Name);\n    }\n\n    private class OllamaModelDownloaderResource(string name, OllamaResource ollamaResource) : Resource(name)\n    {\n        public OllamaResource ollamaResource { get; } = ollamaResource;\n    }\n}\n"
  },
  {
    "path": "src/AppHost/Program.cs",
    "content": "﻿using Microsoft.Extensions.Configuration.Json;\nusing Microsoft.Extensions.Hosting;\nusing Projects;\n\nvar builder = DistributedApplication.CreateBuilder(args);\nbuilder.Configuration.Sources.Add(new JsonConfigurationSource { Path = \"appsettings.Local.json\", Optional = true });\n\nvar isE2ETest = builder.Configuration[\"E2E_TEST\"] == \"true\";\n\nvar dbPassword = builder.AddParameter(\"PostgresPassword\", secret: true);\n\nvar postgresServer = builder\n    .AddPostgres(\"eshopsupport-postgres\", password: dbPassword);\nvar backendDb = postgresServer\n    .AddDatabase(\"backenddb\");\n\nvar vectorDb = builder\n    .AddQdrant(\"vector-db\");\n\nvar identityServer = builder.AddProject<IdentityServer>(\"identity-server\")\n    .WithExternalHttpEndpoints();\n\nvar identityEndpoint = identityServer\n    .GetEndpoint(\"https\");\n\n// Use this if you want to use Ollama\nvar chatCompletion = builder.AddOllama(\"chatcompletion\").WithDataVolume();\n\n// ... or use this if you want to use OpenAI (having also configured the API key in appsettings)\n//var chatCompletion = builder.AddConnectionString(\"chatcompletion\");\n\nvar storage = builder.AddAzureStorage(\"eshopsupport-storage\");\nif (builder.Environment.IsDevelopment())\n{\n    storage.RunAsEmulator(r =>\n    {\n        if (!isE2ETest)\n        {\n            r.WithDataVolume();\n        }\n    });\n}\n\nvar blobStorage = storage.AddBlobs(\"eshopsupport-blobs\");\n\nvar pythonInference = builder.AddPythonUvicornApp(\"python-inference\",\n    Path.Combine(\"..\", \"PythonInference\"), port: 62394);\n\nvar redis = builder.AddRedis(\"redis\");\n\nvar backend = builder.AddProject<Backend>(\"backend\")\n    .WithReference(backendDb)\n    .WithReference(chatCompletion)\n    .WithReference(blobStorage)\n    .WithReference(vectorDb)\n    .WithReference(pythonInference)\n    .WithReference(redis)\n    .WithEnvironment(\"IdentityUrl\", identityEndpoint)\n    .WithEnvironment(\"ImportInitialDataDir\", Path.Combine(builder.AppHostDirectory, \"..\", \"..\", \"seeddata\", isE2ETest ? \"test\" : \"dev\"));\n\nvar staffWebUi = builder.AddProject<StaffWebUI>(\"staffwebui\")\n    .WithExternalHttpEndpoints()\n    .WithReference(backend)\n    .WithReference(redis)\n    .WithEnvironment(\"IdentityUrl\", identityEndpoint);\n\nvar customerWebUi = builder.AddProject<CustomerWebUI>(\"customerwebui\")\n    .WithReference(backend)\n    .WithEnvironment(\"IdentityUrl\", identityEndpoint);\n\n// Circular references: IdentityServer needs to know the endpoints of the web UIs\nidentityServer\n    .WithEnvironment(\"CustomerWebUIEndpoint\", customerWebUi.GetEndpoint(\"https\"))\n    .WithEnvironment(\"StaffWebUIEndpoint\", staffWebUi.GetEndpoint(\"https\"));\n\nif (!isE2ETest)\n{\n    postgresServer.WithDataVolume();\n    vectorDb.WithVolume(\"eshopsupport-vector-db-storage\", \"/qdrant/storage\");\n}\n\nbuilder.Build().Run();\n"
  },
  {
    "path": "src/AppHost/Properties/launchSettings.json",
    "content": "{\n  \"$schema\": \"https://json.schemastore.org/launchsettings.json\",\n  \"profiles\": {\n    \"https\": {\n      \"commandName\": \"Project\",\n      \"dotnetRunMessages\": true,\n      \"launchBrowser\": true,\n      \"applicationUrl\": \"https://localhost:17191;http://localhost:15202\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\",\n        \"DOTNET_ENVIRONMENT\": \"Development\",\n        \"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL\": \"https://localhost:21256\",\n        \"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL\": \"https://localhost:22048\"\n      }\n    },\n    \"http\": {\n      \"commandName\": \"Project\",\n      \"dotnetRunMessages\": true,\n      \"launchBrowser\": true,\n      \"applicationUrl\": \"http://localhost:15202\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\",\n        \"DOTNET_ENVIRONMENT\": \"Development\",\n        \"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL\": \"http://localhost:19297\",\n        \"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL\": \"http://localhost:20257\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/AppHost/Python/PythonUvicornAppResourceBuilderExtensions.cs",
    "content": "﻿namespace Aspire.Hosting;\n\npublic static class PythonUvicornAppResourceBuilderExtensions\n{\n    public static IResourceBuilder<PythonUvicornAppResource> AddPythonUvicornApp(this IDistributedApplicationBuilder builder, string name, string workingDirectory, int? port = default, int? targetPort = default)\n    {\n        return builder.AddResource(new PythonUvicornAppResource(name, \"python\", workingDirectory))\n            .WithArgs(\"-m\", \"uvicorn\", \"main:app\")\n            .WithHttpEndpoint(env: \"UVICORN_PORT\", port: port, targetPort: targetPort);\n    }\n}\n\npublic class PythonUvicornAppResource(string name, string command, string workingDirectory)\n    : ExecutableResource(name, command, workingDirectory), IResourceWithServiceDiscovery\n{\n}\n"
  },
  {
    "path": "src/AppHost/appsettings.Development.json",
    "content": "{\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Information\",\n      \"Microsoft.AspNetCore\": \"Warning\"\n    }\n  },\n\n  // REMEMBER NOT TO COMMIT YOUR API KEYS TO SOURCE CONTROL\n  // To reduce the risk, copy this file as appsettings.Local.json and make your changes there,\n  // since that file overrides anything configured here and will be ignored by Git.\n\n  // This is used if you're using Ollama. Be sure to pick a model that supports tools.\n  \"OllamaModel\": \"llama3.1\",\n\n  // This is used if you're using OpenAI\n  \"ConnectionStrings\": {\n    //\"chatcompletion\": \"Endpoint=https://TODO.openai.azure.com/;Key=TODO;Deployment=TODO\"\n  }\n}\n"
  },
  {
    "path": "src/AppHost/appsettings.json",
    "content": "{\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Information\",\n      \"Microsoft.AspNetCore\": \"Warning\",\n      \"Aspire.Hosting.Dcp\": \"Warning\"\n    }\n  },\n  \"Parameters\": {\n    \"PostgresPassword\": \"dev\"\n  }\n}\n"
  },
  {
    "path": "src/Backend/Api/AssistantApi.cs",
    "content": "﻿using System.ComponentModel;\nusing System.Text;\nusing System.Text.Json;\nusing System.Text.RegularExpressions;\nusing eShopSupport.Backend.Data;\nusing eShopSupport.Backend.Services;\nusing eShopSupport.ServiceDefaults.Clients.Backend;\nusing Microsoft.Extensions.AI;\nusing Microsoft.SemanticKernel.Memory;\n\nnamespace eShopSupport.Backend.Api;\n\npublic static class AssistantApi\n{\n    public static void MapAssistantApiEndpoints(this WebApplication app)\n    {\n        app.MapPost(\"/api/assistant/chat\", GetStreamingChatResponseAsync);\n    }\n\n    private static async Task GetStreamingChatResponseAsync(AssistantChatRequest request, HttpContext httpContext, AppDbContext dbContext, IChatClient chatClient, ILoggerFactory loggerFactory, CancellationToken cancellationToken)\n    {\n        var product = request.ProductId.HasValue\n            ? await dbContext.Products.FindAsync(request.ProductId.Value)\n            : null;\n\n        // Build the prompt plus any existing conversation history\n        var messages = new List<ChatMessage>([ new(ChatRole.System, $$\"\"\"\n            You are a helpful AI assistant called 'Assistant' whose job is to help customer service agents working for AdventureWorks, an online retailer.\n            The customer service agent is currently handling the following ticket:\n\n            <product_id>{{request.ProductId}}</product_id>\n            <product_name>{{product?.Model ?? \"None specified\"}}</product_name>\n            <customer_name>{{request.CustomerName}}</customer_name>\n            <summary>{{request.TicketSummary}}</summary>\n\n            The most recent message from the customer is this:\n            <customer_message>{{request.TicketLastCustomerMessage}}</customer_message>\n            However, that is only provided for context. You are not answering that question directly. The real question will be asked by the user below.\n\n            If this is a question about the product, ALWAYS search the product manual.\n\n            ALWAYS justify your answer by citing a search result. Do this by including this syntax in your reply:\n            <cite searchResultId=number>shortVerbatimQuote</cite>\n            shortVerbatimQuote must be a very short, EXACT quote (max 10 words) from whichever search result you are citing.\n            Only give one citation per answer. Always give a citation because this is important to the business.\n            \"\"\") ]);\n\n        messages.AddRange(request.Messages.Select(m => new ChatMessage(m.IsAssistant ? ChatRole.Assistant : ChatRole.User, m.Text)));\n        await httpContext.Response.WriteAsync(\"[null\");\n\n        // Call the LLM backend\n        var searchManual = AIFunctionFactory.Create(new SearchManualContext(httpContext).SearchManual);\n        var executionSettings = new ChatOptions\n        {\n            Temperature = 0,\n            Tools = [searchManual],\n            AdditionalProperties = new() { [\"seed\"] = 0 },\n        };\n        var streamingAnswer = chatClient.GetStreamingResponseAsync(messages, executionSettings, cancellationToken);\n\n        // Stream the response to the UI\n        var answerBuilder = new StringBuilder();\n        await foreach (var chunk in streamingAnswer)\n        {\n            await httpContext.Response.WriteAsync(\",\\n\");\n            await httpContext.Response.WriteAsync(JsonSerializer.Serialize(new AssistantChatReplyItem(AssistantChatReplyItemType.AnswerChunk, chunk.ToString())));\n            answerBuilder.Append(chunk.ToString());\n        }\n\n        // Ask if this answer is suitable for sending directly to the customer\n        // If so, we'll show a button in the UI\n        var classification = await chatClient.GetResponseAsync<MessageClassification>(\n            $\"Determine whether the following message is phrased as a reply to the customer {request.CustomerName} by name: {answerBuilder}\",\n            cancellationToken: cancellationToken);\n        if (classification.TryGetResult(out var result) && result.IsAddressedToCustomerByName)\n        {\n            await httpContext.Response.WriteAsync(\",\\n\");\n            await httpContext.Response.WriteAsync(JsonSerializer.Serialize(new AssistantChatReplyItem(AssistantChatReplyItemType.IsAddressedToCustomer, \"true\")));\n        }\n\n        // Signal to the UI that we're finished\n        await httpContext.Response.WriteAsync(\"]\");\n    }\n\n    private class MessageClassification\n    {\n        public bool IsAddressedToCustomerByName { get; set; }\n    }\n\n    private class SearchManualContext(HttpContext httpContext)\n    {\n        private readonly SemaphoreSlim semaphore = new(1);\n        private readonly ProductManualSemanticSearch manualSearch = httpContext.RequestServices.GetRequiredService<ProductManualSemanticSearch>();\n\n        public async Task<object> SearchManual(\n            [Description(\"A phrase to use when searching the manual\")] string searchPhrase,\n            [Description(\"ID for the product whose manual to search. Set to null only if you must search across all product manuals.\")] int? productId)\n        {\n            await semaphore.WaitAsync(); // Alternatively, you can set ConcurrentInvocation to false in UseFunctionInvocation\n\n            try\n            {\n                // Notify the UI we're doing a search\n                await httpContext.Response.WriteAsync(\",\\n\");\n                await httpContext.Response.WriteAsync(JsonSerializer.Serialize(new AssistantChatReplyItem(AssistantChatReplyItemType.Search, searchPhrase)));\n\n                // Do the search, and supply the results to the UI so it can show one as a citation link\n                var searchResults = await manualSearch.SearchAsync(productId, searchPhrase);\n                foreach (var r in searchResults)\n                {\n                    await httpContext.Response.WriteAsync(\",\\n\");\n                    await httpContext.Response.WriteAsync(JsonSerializer.Serialize(new AssistantChatReplyItem(\n                        AssistantChatReplyItemType.SearchResult,\n                        string.Empty,\n                        int.Parse(r.Metadata.Id),\n                        GetProductId(r),\n                        GetPageNumber(r))));\n                }\n\n                // Return the search results to the assistant\n                return searchResults.Select(r => new\n                {\n                    ProductId = GetProductId(r),\n                    SearchResultId = r.Metadata.Id,\n                    r.Metadata.Text,\n                });\n            }\n            finally\n            {\n                semaphore.Release();\n            }\n        }\n    }\n\n    private static int? GetProductId(MemoryQueryResult result)\n    {\n        var match = Regex.Match(result.Metadata.ExternalSourceName, @\"productid:(\\d+)\");\n        return match.Success ? int.Parse(match.Groups[1].Value) : null;\n    }\n\n    private static int? GetPageNumber(MemoryQueryResult result)\n    {\n        var match = Regex.Match(result.Metadata.AdditionalMetadata, @\"pagenumber:(\\d+)\");\n        return match.Success ? int.Parse(match.Groups[1].Value) : null;\n    }\n}\n"
  },
  {
    "path": "src/Backend/Api/CatalogApi.cs",
    "content": "﻿using System.Numerics.Tensors;\nusing System.Runtime.InteropServices;\nusing Azure.Storage.Blobs;\nusing eShopSupport.Backend.Data;\nusing eShopSupport.Backend.Services;\nusing eShopSupport.ServiceDefaults.Clients.Backend;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.SemanticKernel.Embeddings;\n\nnamespace eShopSupport.Backend.Api;\n\npublic static class CatalogApi\n{\n    public static void MapCatalogApiEndpoints(this WebApplication app)\n    {\n        app.MapGet(\"/manual\", GetManualPdfAsync);\n        app.MapGet(\"/api/categories\", SearchCategoriesAsync);\n        app.MapGet(\"/api/products\", SearchProductsAsync);\n\n        // APIs allowed for use from CustomerWebUI\n        var customerApiPolicy = \"CustomerApi\";\n        app.MapGet(\"/api/customer/products\", SearchProductsAsync)\n            .RequireAuthorization(customerApiPolicy);\n    }\n\n    private static async Task<IEnumerable<FindCategoriesResult>> SearchCategoriesAsync(AppDbContext dbContext, ITextEmbeddingGenerationService embedder, string? searchText, string? ids)\n    {\n        IQueryable<ProductCategory> filteredCategories = dbContext.ProductCategories;\n\n        if (!string.IsNullOrWhiteSpace(ids))\n        {\n            var idsParsed = ids.Split(',').Select(int.Parse).ToList();\n            filteredCategories = filteredCategories.Where(c => idsParsed.Contains(c.CategoryId));\n        }\n\n        var matchingCategories = await filteredCategories.ToArrayAsync();\n\n        // If you have a small number of items, another pattern for semantic search is simply\n        // to do it in process. In this case we also amend the similarity rule so that if the\n        // category is an exact prefix match, it's considered a perfect match. So in effect\n        // we have both a prefix match and a semantic match working together.\n        if (!string.IsNullOrWhiteSpace(searchText))\n        {\n            var searchTextEmbedding = await embedder.GenerateEmbeddingAsync(searchText);\n            matchingCategories = matchingCategories.Select(c => new\n            {\n                Category = c,\n                Similarity = c.Name.StartsWith(searchText, StringComparison.OrdinalIgnoreCase)\n                                    ? 1f\n                                    : TensorPrimitives.CosineSimilarity(FromBase64(c.NameEmbeddingBase64), searchTextEmbedding.Span),\n            }).Where(x => x.Similarity > 0.5f)\n                            .OrderByDescending(x => x.Similarity)\n                            .Take(5)\n                            .Select(x => x.Category)\n                            .ToArray();\n        }\n\n        return matchingCategories.Select(c => new FindCategoriesResult(c.CategoryId) { Name = c.Name });\n\n        static ReadOnlySpan<float> FromBase64(string embeddingBase64)\n        {\n            var bytes = Convert.FromBase64String(embeddingBase64);\n            return MemoryMarshal.Cast<byte, float>(bytes);\n        }\n    }\n\n    private static Task<IEnumerable<FindProductsResult>> SearchProductsAsync(ProductSemanticSearch productSemanticSearch, string searchText)\n        => productSemanticSearch.FindProductsAsync(searchText);\n\n    private static async Task<IResult> GetManualPdfAsync(string file, BlobServiceClient blobServiceClient)\n    {\n        var blobClient = blobServiceClient.GetBlobContainerClient(\"manuals\").GetBlobClient(file);\n        if (!(await blobClient.ExistsAsync()))\n        {\n            return Results.NotFound();\n        }\n\n        var download = await blobClient.DownloadStreamingAsync();\n        return Results.File(download.Value.Content, \"application/pdf\");\n    }\n}\n"
  },
  {
    "path": "src/Backend/Api/TicketApi.cs",
    "content": "﻿using System.Text.RegularExpressions;\nusing CustomerWebUI;\nusing eShopSupport.Backend.Data;\nusing eShopSupport.Backend.Services;\nusing eShopSupport.ServiceDefaults.Clients.Backend;\nusing eShopSupport.ServiceDefaults.Clients.PythonInference;\nusing Microsoft.EntityFrameworkCore;\nusing StackExchange.Redis;\n\nnamespace eShopSupport.Backend.Api;\n\npublic static class TicketApi\n{\n    public static void MapTicketApiEndpoints(this WebApplication app)\n    {\n        // Staff endpoints. Fallback policy requires \"staff\" role.\n        app.MapPost(\"/tickets\", ListTicketsAsync);\n        app.MapGet(\"/tickets/{ticketId:int}\", GetTicketAsync);\n        app.MapPut(\"/api/ticket/{ticketId:int}\", UpdateTicketAsync);\n        \n        // Customer endpoints. These must each take care to restrict access to the customer's own tickets.\n        var customerApiPolicy = \"CustomerApi\";\n\n        app.MapGet(\"/customer/tickets\", (HttpContext httpContext, AppDbContext dbContext) =>\n            ListTicketsAsync(dbContext, new(null, null, httpContext.GetRequiredCustomerId(), 0, 100, nameof(ListTicketsResultItem.TicketId), false)))\n            .RequireAuthorization(customerApiPolicy);\n\n        app.MapGet(\"/customer/tickets/{ticketId:int}\", (HttpContext httpContext, AppDbContext dbContext, int ticketId) =>\n            GetTicketAsync(dbContext, ticketId, httpContext.GetRequiredCustomerId()))\n            .RequireAuthorization(customerApiPolicy);\n\n        app.MapPost(\"/customer/tickets/create\", CreateTicketAsync)\n            .RequireAuthorization(customerApiPolicy);\n\n        app.MapPut(\"/api/customer/ticket/{ticketId:int}/close\", (HttpContext httpContext, AppDbContext dbContext, int ticketId) =>\n            CloseTicketAsync(dbContext, ticketId, httpContext.GetRequiredCustomerId()))\n            .RequireAuthorization(customerApiPolicy);\n    }\n\n    private static async Task<IResult> ListTicketsAsync(AppDbContext dbContext, ListTicketsRequest request)\n    {\n        if (request.MaxResults > 100)\n        {\n            return Results.BadRequest(\"maxResults must be 100 or less\");\n        }\n\n        IQueryable<Ticket> itemsMatchingFilter = dbContext.Tickets\n            .Include(t => t.Product);\n\n        if (request.FilterByCategoryIds is { Count: > 0 })\n        {\n            itemsMatchingFilter = itemsMatchingFilter\n                .Where(t => t.Product != null)\n                .Where(t => request.FilterByCategoryIds.Contains(t.Product!.CategoryId));\n        }\n\n        if (request.FilterByCustomerId is int customerId)\n        {\n            itemsMatchingFilter = itemsMatchingFilter.Where(t => t.CustomerId == customerId);\n        }\n\n        // Count open/closed\n        var itemsMatchingFilterCountByStatus = await itemsMatchingFilter.GroupBy(t => t.TicketStatus)\n            .Select(g => new { Status = g.Key, Count = g.Count() })\n            .ToDictionaryAsync(g => g.Status, g => g.Count);\n        var totalOpen = itemsMatchingFilterCountByStatus.GetValueOrDefault(TicketStatus.Open);\n        var totalClosed = itemsMatchingFilterCountByStatus.GetValueOrDefault(TicketStatus.Closed);\n\n        // Sort and return requested range of\n        if (request.FilterByStatus.HasValue)\n        {\n            itemsMatchingFilter = itemsMatchingFilter.Where(t => t.TicketStatus == request.FilterByStatus.Value);\n        }\n\n        if (!string.IsNullOrEmpty(request.SortBy))\n        {\n            switch (request.SortBy)\n            {\n                case nameof(ListTicketsResultItem.TicketId):\n                    itemsMatchingFilter = request.SortAscending == true\n                        ? itemsMatchingFilter.OrderBy(t => t.TicketId)\n                        : itemsMatchingFilter.OrderByDescending(t => t.TicketId);\n                    break;\n                case nameof(ListTicketsResultItem.CustomerFullName):\n                    itemsMatchingFilter = request.SortAscending == true\n                        ? itemsMatchingFilter.OrderBy(t => t.Customer.FullName).ThenBy(t => t.TicketId)\n                        : itemsMatchingFilter.OrderByDescending(t => t.Customer.FullName).ThenBy(t => t.TicketId);\n                    break;\n                case nameof(ListTicketsResultItem.NumMessages):\n                    itemsMatchingFilter = request.SortAscending == true\n                        ? itemsMatchingFilter.OrderBy(t => t.Messages.Count).ThenBy(t => t.TicketId)\n                        : itemsMatchingFilter.OrderByDescending(t => t.Messages.Count).ThenBy(t => t.TicketId);\n                    break;\n                case nameof(ListTicketsResultItem.CustomerSatisfaction):\n                    itemsMatchingFilter = request.SortAscending == true\n                        ? itemsMatchingFilter.OrderBy(t => t.CustomerSatisfaction).ThenBy(t => t.TicketId)\n                        : itemsMatchingFilter.OrderByDescending(t => t.CustomerSatisfaction).ThenBy(t => t.TicketId);\n                    break;\n                default:\n                    return Results.BadRequest(\"Invalid sortBy value\");\n            }\n        }\n\n        var resultItems = itemsMatchingFilter\n            .Skip(request.StartIndex)\n            .Take(request.MaxResults)\n            .Select(t => new ListTicketsResultItem(t.TicketId, t.TicketType, t.TicketStatus, t.CreatedAt, t.Customer.FullName, t.Product == null ? null : t.Product.Model, t.ShortSummary, t.CustomerSatisfaction, t.Messages.Count));\n\n        return Results.Ok(new ListTicketsResult(await resultItems.ToListAsync(), await itemsMatchingFilter.CountAsync(), totalOpen, totalClosed));\n    }\n\n    private static async Task<IResult> GetTicketAsync(AppDbContext dbContext, int ticketId, int? restrictToCustomerId)\n    {\n        var ticket = await dbContext.Tickets\n            .Where(t => restrictToCustomerId == null || t.CustomerId == restrictToCustomerId)\n            .Include(t => t.Messages)\n            .Include(t => t.Product)\n            .Include(t => t.Customer)\n            .FirstOrDefaultAsync(t => t.TicketId == ticketId);\n        return ticket == null ? Results.NotFound() : Results.Ok(new TicketDetailsResult(\n            ticket.TicketId,\n            ticket.CreatedAt,\n            ticket.CustomerId,\n            ticket.Customer.FullName,\n            ticket.ShortSummary,\n            ticket.LongSummary,\n            ticket.ProductId,\n            ticket.Product?.Brand,\n            ticket.Product?.Model,\n            ticket.TicketType,\n            ticket.TicketStatus,\n            ticket.CustomerSatisfaction,\n            ticket.Messages.OrderBy(m => m.MessageId).Select(m => new TicketDetailsResultMessage(m.MessageId, m.CreatedAt, m.IsCustomerMessage, m.Text)).ToList()\n        ));\n    }\n\n    private static async Task<IResult> UpdateTicketAsync(AppDbContext dbContext, IConnectionMultiplexer redisConnection, int ticketId, UpdateTicketDetailsRequest request)\n    {\n        var ticket = await dbContext.Tickets.FirstOrDefaultAsync(t => t.TicketId == ticketId);\n        if (ticket == null)\n        {\n            return Results.NotFound();\n        }\n\n        ticket.ProductId = request.ProductId;\n        ticket.TicketType = request.TicketType;\n        ticket.TicketStatus = request.TicketStatus;\n        await dbContext.SaveChangesAsync();\n\n        await redisConnection.GetSubscriber().PublishAsync(\n            RedisChannel.Literal($\"ticket:{ticketId}\"), \"Updated\");\n\n        return Results.Ok();\n    }\n\n    private static async Task<IResult> CloseTicketAsync(AppDbContext dbContext, int ticketId, int loggedInCustomerId)\n    {\n        var ticket = await dbContext.Tickets\n            .Where(t => t.CustomerId == loggedInCustomerId)\n            .FirstOrDefaultAsync(t => t.TicketId == ticketId);\n\n        if (ticket == null)\n        {\n            return Results.NotFound();\n        }\n\n        ticket.TicketStatus = TicketStatus.Closed;\n        await dbContext.SaveChangesAsync();\n        return Results.Ok();\n    }\n\n    private static async Task CreateTicketAsync(HttpContext httpContext, AppDbContext dbContext, TicketSummarizer summarizer, PythonInferenceClient pythonInference, CreateTicketRequest request)\n    {\n        // Classify the new ticket using the small zero-shot classifier model\n        var ticketTypes = Enum.GetValues<TicketType>();\n        var inferredTicketType = await pythonInference.ClassifyTextAsync(\n            request.Message,\n            candidateLabels: ticketTypes.Select(type => type.ToString()));\n\n        var ticket = new Ticket\n        {\n            CreatedAt = DateTime.UtcNow,\n            CustomerId = httpContext.GetRequiredCustomerId(),\n            Customer = default!, // Will be populated by DB reference\n            TicketStatus = TicketStatus.Open,\n            TicketType = Enum.TryParse<TicketType>(inferredTicketType, out var type) ? type : TicketType.Question,\n        };\n\n        // TODO: Better lookup using ID\n        if (!string.IsNullOrEmpty(request.ProductName)\n            && Regex.Match(request.ProductName, @\"^(.*) \\((.*)\\)$\") is { Success: true } match)\n        {\n            var brand = match.Groups[2].Value;\n            var model = match.Groups[1].Value;\n            var product = await dbContext.Products.FirstOrDefaultAsync(p => p.Brand == brand && p.Model == model);\n            ticket.ProductId = product?.ProductId;\n        }\n\n        ticket.Messages.Add(new Message\n        {\n            IsCustomerMessage = true,\n            Text = request.Message,\n            CreatedAt = DateTime.UtcNow,\n        });\n\n        dbContext.Tickets.Add(ticket);\n        await dbContext.SaveChangesAsync();\n\n        summarizer.UpdateSummary(ticket.TicketId, enforceRateLimit: true);\n    }\n}\n"
  },
  {
    "path": "src/Backend/Api/TicketMessagingApi.cs",
    "content": "﻿using CustomerWebUI;\nusing eShopSupport.Backend.Data;\nusing eShopSupport.Backend.Services;\nusing eShopSupport.ServiceDefaults.Clients.Backend;\n\nnamespace eShopSupport.Backend.Api;\n\npublic static class TicketMessagingApi\n{\n    public static void MapTicketMessagingApiEndpoints(this WebApplication app)\n    {\n        app.MapPost(\"/api/ticket/{ticketId}/message\", async (int ticketId, AppDbContext dbContext, TicketSummarizer summarizer, SendTicketMessageRequest request) =>\n        {\n            // Staff can post messages on any ticket, so we don't have to validate ticketId\n            await PostMessageAsync(ticketId, dbContext, summarizer, request, isCustomerMessage: false);\n        });\n\n        app.MapPost(\"/api/customer/ticket/{ticketId}/message\", async (HttpContext httpContext, int ticketId, AppDbContext dbContext, TicketSummarizer summarizer, SendTicketMessageRequest request) =>\n        {\n            // Since this is a customer API call, verify this is their ticket\n            var ticket = await dbContext.Tickets.FindAsync(ticketId);\n            if (ticket?.CustomerId != httpContext.GetRequiredCustomerId())\n            {\n                return Results.NotFound();\n            }\n\n            await PostMessageAsync(ticketId, dbContext, summarizer, request, isCustomerMessage: true);\n            return Results.Ok();\n        }).RequireAuthorization(\"CustomerApi\");\n    }\n\n    private static async Task PostMessageAsync(int ticketId, AppDbContext dbContext, TicketSummarizer summarizer, SendTicketMessageRequest request, bool isCustomerMessage)\n    {\n        dbContext.Messages.Add(new Message\n        {\n            TicketId = ticketId,\n            CreatedAt = DateTime.UtcNow,\n            IsCustomerMessage = isCustomerMessage,\n            Text = request.Text,\n        });\n        await dbContext.SaveChangesAsync();\n\n        // Runs in the background and notifies when the summary is updated\n        summarizer.UpdateSummary(ticketId, enforceRateLimit: isCustomerMessage);\n    }\n}\n"
  },
  {
    "path": "src/Backend/Backend.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n  <PropertyGroup>\n    <TargetFramework>net8.0</TargetFramework>\n    <Nullable>enable</Nullable>\n    <ImplicitUsings>enable</ImplicitUsings>\n    <RootNamespace>eShopSupport.Backend</RootNamespace>\n    <NoWarn>$(NoWarn);SKEXP0001;SKEXP0010;SKEXP0020</NoWarn>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Aspire.Azure.Storage.Blobs\" />\n    <PackageReference Include=\"Aspire.StackExchange.Redis\" />\n    <PackageReference Include=\"Aspire.Npgsql.EntityFrameworkCore.PostgreSQL\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.Authentication.JwtBearer\" />\n    <PackageReference Include=\"Microsoft.SemanticKernel.Connectors.Qdrant\" />\n    <PackageReference Include=\"SmartComponents.LocalEmbeddings.SemanticKernel\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\ServiceDefaults\\ServiceDefaults.csproj\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/Backend/Data/AppDbContext.cs",
    "content": "﻿using System.Text.Json;\nusing Microsoft.EntityFrameworkCore;\nusing Polly;\nusing Polly.Retry;\n\nnamespace eShopSupport.Backend.Data;\n\npublic class AppDbContext : DbContext\n{\n    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)\n    {\n    }\n\n    public DbSet<Customer> Customers { get; set; }\n\n    public DbSet<Ticket> Tickets { get; set; }\n\n    public DbSet<Message> Messages { get; set; }\n\n    public DbSet<ProductCategory> ProductCategories { get; set; }\n\n    public DbSet<Product> Products { get; set; }\n\n    protected override void OnModelCreating(ModelBuilder modelBuilder)\n    {\n        base.OnModelCreating(modelBuilder);\n        modelBuilder.Entity<Ticket>().HasMany(t => t.Messages).WithOne().OnDelete(DeleteBehavior.Cascade);\n        modelBuilder.Entity<Ticket>().HasOne(t => t.Product);\n    }\n\n    public static async Task EnsureDbCreatedAsync(IServiceProvider services, string? initialImportDataDir)\n    {\n        using var scope = services.CreateScope();\n        using var dbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();\n\n        // Wait until the DB is ready\n        var pipeline = new ResiliencePipelineBuilder().AddRetry(new RetryStrategyOptions { Delay = TimeSpan.FromSeconds(3) }).Build();\n        var createdDb = await pipeline.ExecuteAsync(async (CancellationToken ct) =>\n            await dbContext.Database.EnsureCreatedAsync(ct));\n\n        if (createdDb && !string.IsNullOrEmpty(initialImportDataDir))\n        {\n            await ImportInitialData(dbContext, initialImportDataDir);\n        }\n    }\n\n    private static async Task ImportInitialData(AppDbContext dbContext, string dirPath)\n    {\n        try\n        {\n            var customers = JsonSerializer.Deserialize<Customer[]>(\n                File.ReadAllText(Path.Combine(dirPath, \"customers.json\")))!;\n\n            var categories = JsonSerializer.Deserialize<ProductCategory[]>(\n                File.ReadAllText(Path.Combine(dirPath, \"categories.json\")))!;\n\n            var products = JsonSerializer.Deserialize<Product[]>(\n                File.ReadAllText(Path.Combine(dirPath, \"products.json\")))!;\n\n            var tickets = JsonSerializer.Deserialize<Ticket[]>(\n                File.ReadAllText(Path.Combine(dirPath, \"tickets.json\")))!;\n\n            // Explicitly remove the IDs so they will be auto-generated by the DB\n            foreach (var ticket in tickets)\n            {\n                ticket.TicketId = 0;\n                ticket.Customer = customers.First(c => c.CustomerId == ticket.CustomerId);\n                ticket.CreatedAt = DateTime.UtcNow;\n                foreach (var message in ticket.Messages)\n                {\n                    message.MessageId = 0;\n                    message.CreatedAt = DateTime.UtcNow;\n                }\n            }\n            foreach (var customer in customers)\n            {\n                customer.CustomerId = 0;\n            }\n\n            // These users correspond to entries in IdentityServer's TestUsers class\n            await dbContext.Customers.AddAsync(new Customer { CustomerId = 10000, FullName = \"Alice Smith\" });\n            await dbContext.Customers.AddAsync(new Customer { CustomerId = 10001, FullName = \"Bob Smith\" });\n\n            await dbContext.Customers.AddRangeAsync(customers);\n            await dbContext.ProductCategories.AddRangeAsync(categories);\n            await dbContext.Products.AddRangeAsync(products);\n            await dbContext.Tickets.AddRangeAsync(tickets);\n            await dbContext.SaveChangesAsync();\n        }\n        catch\n        {\n            // If the initial import failed, we drop the DB so it will try again next time\n            await dbContext.Database.EnsureDeletedAsync();\n            throw;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Backend/Data/AsyncEnumerableExtensions.cs",
    "content": "﻿namespace eShopSupport.Backend.Data;\n\ninternal static class AsyncEnumerableExtensions\n{\n    public static async Task<List<T>> ToListAsync<T>(this IAsyncEnumerable<T> asyncEnumerable)\n    {\n        var result = new List<T>();\n        await foreach (var item in asyncEnumerable)\n        {\n            result.Add(item);\n        }\n        return result;\n    }\n}\n"
  },
  {
    "path": "src/Backend/Data/Customer.cs",
    "content": "﻿namespace eShopSupport.Backend.Data;\n\npublic class Customer\n{\n    public int CustomerId { get; set; }\n\n    public required string FullName { get; set; }\n}\n"
  },
  {
    "path": "src/Backend/Data/ManualChunk.cs",
    "content": "﻿namespace eShopSupport.Backend.Data;\n\npublic class ManualChunk\n{\n    public int ChunkId { get; set; }\n    public int ProductId { get; set; }\n    public int PageNumber { get; set; }\n    public required string Text { get; set; }\n    public required byte[] Embedding { get; set; }\n}\n"
  },
  {
    "path": "src/Backend/Data/Message.cs",
    "content": "﻿namespace eShopSupport.Backend.Data;\n\npublic class Message\n{\n    public int MessageId { get; set; }\n\n    public DateTime CreatedAt { get; set; }\n\n    public int TicketId { get; set; }\n\n    public bool IsCustomerMessage { get; set; }\n\n    public required string Text { get; set; }\n}\n"
  },
  {
    "path": "src/Backend/Data/Product.cs",
    "content": "﻿using System.ComponentModel.DataAnnotations.Schema;\nusing System.Runtime.InteropServices;\nusing System.Text.Json;\nusing System.Text.Json.Serialization;\n\nnamespace eShopSupport.Backend.Data;\n\npublic class Product\n{\n    public int ProductId { get; set; }\n    public int CategoryId { get; set; }\n    public required string Brand { get; set; }\n    public required string Model { get; set; }\n    public required string Description { get; set; }\n    public decimal Price { get; set; }\n\n    [NotMapped, JsonConverter(typeof(EmbeddingJsonConverter))]\n    public required ReadOnlyMemory<float> NameEmbedding { get; set; }\n}\n\nclass EmbeddingJsonConverter : JsonConverter<ReadOnlyMemory<float>>\n{\n    public override ReadOnlyMemory<float> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n    {\n        if (reader.TokenType == JsonTokenType.Null)\n        {\n            return null;\n        }\n\n        if (reader.TokenType != JsonTokenType.String)\n        {\n            throw new InvalidOperationException($\"JSON deserialization failed because the value type was {reader.TokenType} but should be {JsonTokenType.String}\");\n        }\n\n        var bytes = reader.GetBytesFromBase64();\n        var floats = MemoryMarshal.Cast<byte, float>(bytes);\n        return floats.ToArray(); // TODO: Can we avoid copying? The memory is already in the right format.\n    }\n\n    public override void Write(Utf8JsonWriter writer, ReadOnlyMemory<float> value, JsonSerializerOptions options)\n    {\n        var bytes = MemoryMarshal.AsBytes(value.Span);\n        writer.WriteBase64StringValue(bytes);\n    }\n}\n"
  },
  {
    "path": "src/Backend/Data/ProductCategory.cs",
    "content": "﻿using System.ComponentModel.DataAnnotations;\n\nnamespace eShopSupport.Backend.Data;\n\npublic class ProductCategory\n{\n    [Key]\n    public int CategoryId { get; set; }\n\n    public required string Name { get; set; }\n\n    public required string NameEmbeddingBase64 { get; set; }\n}\n"
  },
  {
    "path": "src/Backend/Data/Ticket.cs",
    "content": "﻿using System.Text.Json.Serialization;\nusing eShopSupport.ServiceDefaults.Clients.Backend;\n\nnamespace eShopSupport.Backend.Data;\n\npublic class Ticket\n{\n    public int TicketId { get; set; }\n    \n    public int? ProductId { get; set; }\n\n    public DateTime CreatedAt { get; set; }\n\n    [JsonIgnore]\n    public Product? Product { get; set; }\n\n    public int CustomerId { get; set; }\n\n    [JsonIgnore]\n    public Customer Customer { get; set; } = default!;\n\n    public string? ShortSummary { get; set; }\n    \n    public string? LongSummary { get; set; }\n    \n    public int? CustomerSatisfaction { get; set; }\n\n    [JsonConverter(typeof(JsonStringEnumConverter))]\n    public TicketStatus TicketStatus { get; set; }\n\n    [JsonConverter(typeof(JsonStringEnumConverter))]\n    public TicketType TicketType { get; set; }\n\n    public List<Message> Messages { get; set; } = new();\n}\n"
  },
  {
    "path": "src/Backend/HttpContextUserIdentityExtensions.cs",
    "content": "﻿using System.Security.Claims;\n\nnamespace CustomerWebUI;\n\npublic static class HttpContextUserIdentityExtensions\n{\n    public static int GetRequiredCustomerId(this HttpContext httpContext)\n    {\n        if (httpContext.User.IsInRole(\"staff\"))\n        {\n            throw new InvalidOperationException(\"The current user is not a customer; they are in 'staff' role.\");\n        }\n\n        if (httpContext.User.Identity is { IsAuthenticated: true } and ClaimsIdentity claimsIdentity\n            && claimsIdentity.FindFirst(\"sub\") is { Value: string subscriberIdString })\n        {\n            return int.Parse(subscriberIdString);\n        }\n\n        throw new InvalidOperationException(\"User is not authenticated or missing 'sub' claim\");\n    }\n}\n"
  },
  {
    "path": "src/Backend/Program.cs",
    "content": "﻿using eShopSupport.Backend.Api;\nusing eShopSupport.Backend.Data;\nusing eShopSupport.Backend.Services;\nusing eShopSupport.ServiceDefaults.Clients.PythonInference;\nusing Microsoft.IdentityModel.JsonWebTokens;\nusing Microsoft.SemanticKernel.Connectors.Qdrant;\nusing Microsoft.SemanticKernel.Embeddings;\nusing Microsoft.SemanticKernel.Memory;\nusing SmartComponents.LocalEmbeddings.SemanticKernel;\n\nvar builder = WebApplication.CreateBuilder(args);\n\n// Add service defaults & Aspire components.\nbuilder.AddServiceDefaults();\n\nbuilder.AddNpgsqlDbContext<AppDbContext>(\"backenddb\");\n\nbuilder.AddQdrantHttpClient(\"vector-db\");\nbuilder.Services.AddScoped(s => new QdrantMemoryStore(\n    s.GetQdrantHttpClient(\"vector-db\"), 384));\n\nbuilder.Services.AddScoped<IMemoryStore>(s => s.GetRequiredService<QdrantMemoryStore>());\nbuilder.Services.AddScoped<ITextEmbeddingGenerationService, LocalTextEmbeddingGenerationService>();\nbuilder.Services.AddScoped<ISemanticTextMemory, SemanticTextMemory>();\nbuilder.Services.AddScoped<ProductSemanticSearch>();\nbuilder.Services.AddScoped<ProductManualSemanticSearch>();\nbuilder.Services.AddScoped<TicketSummarizer>();\nbuilder.Services.AddHttpClient<PythonInferenceClient>(c => c.BaseAddress = new Uri(\"http://python-inference\"));\nbuilder.AddAzureBlobClient(\"eshopsupport-blobs\");\n\nbuilder.AddChatCompletionService(\"chatcompletion\");\nbuilder.AddRedisClient(\"redis\");\n\nJsonWebTokenHandler.DefaultInboundClaimTypeMap.Remove(\"sub\");\n\nbuilder.Services.AddAuthentication().AddJwtBearer(options =>\n{\n    options.Authority = builder.Configuration[\"IdentityUrl\"];\n    options.TokenValidationParameters.ValidateAudience = false;\n});\nbuilder.Services.AddAuthorizationBuilder()\n    .AddPolicy(\"CustomerApi\", policy => policy.RequireAuthenticatedUser())\n    .AddFallbackPolicy(\"StaffApi\", policy => policy.RequireRole(\"staff\"));\n\nvar app = builder.Build();\n\nvar initialImportDataDir = builder.Configuration[\"ImportInitialDataDir\"];\nawait AppDbContext.EnsureDbCreatedAsync(app.Services, initialImportDataDir);\nawait ProductSemanticSearch.EnsureSeedDataImportedAsync(app.Services, initialImportDataDir);\nawait ProductManualSemanticSearch.EnsureSeedDataImportedAsync(app.Services, initialImportDataDir);\n\napp.MapAssistantApiEndpoints();\napp.MapTicketApiEndpoints();\napp.MapTicketMessagingApiEndpoints();\napp.MapCatalogApiEndpoints();\n\napp.Run();\n"
  },
  {
    "path": "src/Backend/Properties/launchSettings.json",
    "content": "﻿{\n  \"$schema\": \"http://json.schemastore.org/launchsettings.json\",\n  \"iisSettings\": {\n    \"windowsAuthentication\": false,\n    \"anonymousAuthentication\": true,\n    \"iisExpress\": {\n      \"applicationUrl\": \"http://localhost:52822\",\n      \"sslPort\": 44320\n    }\n  },\n  \"profiles\": {\n    \"http\": {\n      \"commandName\": \"Project\",\n      \"dotnetRunMessages\": true,\n      \"launchBrowser\": true,\n      \"applicationUrl\": \"http://localhost:5165\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    },\n    \"https\": {\n      \"commandName\": \"Project\",\n      \"dotnetRunMessages\": true,\n      \"launchBrowser\": true,\n      \"applicationUrl\": \"https://localhost:7223;http://localhost:5165\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    },\n    \"IIS Express\": {\n      \"commandName\": \"IISExpress\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/Backend/Services/ProductManualSemanticSearch.cs",
    "content": "﻿using System.IO.Compression;\nusing System.Runtime.InteropServices;\nusing System.Text.Json;\nusing Azure.Storage.Blobs;\nusing eShopSupport.Backend.Data;\nusing Microsoft.SemanticKernel.Embeddings;\nusing Microsoft.SemanticKernel.Memory;\n\nnamespace eShopSupport.Backend.Services;\n\npublic class ProductManualSemanticSearch(ITextEmbeddingGenerationService embedder, IServiceProvider services)\n{\n    private const string ManualCollectionName = \"manuals\";\n\n    public async Task<IReadOnlyList<MemoryQueryResult>> SearchAsync(int? productId, string query)\n    {\n        var embedding = await embedder.GenerateEmbeddingAsync(query);\n        var filter = !productId.HasValue\n            ? null\n            : new\n            {\n                must = new[]\n                {\n                    new { key = \"external_source_name\", match = new { value = $\"productid:{productId}\" } }\n                }\n            };\n\n        var httpClient = services.GetQdrantHttpClient(\"vector-db\");\n        var response = await httpClient.PostAsync($\"collections/{ManualCollectionName}/points/search\",\n            JsonContent.Create(new\n            {\n                vector = embedding,\n                with_payload = new[] { \"id\", \"text\", \"external_source_name\", \"additional_metadata\" },\n                limit = 3,\n                filter,\n            }));\n\n        var responseParsed = await response.Content.ReadFromJsonAsync<QdrantResult>();\n\n        return responseParsed!.Result.Select(r => new MemoryQueryResult(\n            new MemoryRecordMetadata(true, r.Payload.Id, r.Payload.Text, \"\", r.Payload.External_Source_Name, r.Payload.Additional_Metadata),\n            r.Score,\n            null)).ToList();\n    }\n\n    public static async Task EnsureSeedDataImportedAsync(IServiceProvider services, string? initialImportDataDir)\n    {\n        if (!string.IsNullOrEmpty(initialImportDataDir))\n        {\n            using var scope = services.CreateScope();\n            await ImportManualFilesSeedDataAsync(initialImportDataDir, scope);\n            await ImportManualChunkSeedDataAsync(initialImportDataDir, scope);\n        }\n    }\n\n    private static async Task ImportManualFilesSeedDataAsync(string importDataFromDir, IServiceScope scope)\n    {\n        var blobStorage = scope.ServiceProvider.GetRequiredService<BlobServiceClient>();\n        var blobClient = blobStorage.GetBlobContainerClient(\"manuals\");\n        if (await blobClient.ExistsAsync())\n        {\n            return;\n        }\n\n        await blobClient.CreateIfNotExistsAsync();\n\n        var manualsZipFilePath = Path.Combine(importDataFromDir, \"manuals.zip\");\n        using var zipFile = ZipFile.OpenRead(manualsZipFilePath);\n        foreach (var file in zipFile.Entries)\n        {\n            using var fileStream = file.Open();\n            await blobClient.UploadBlobAsync(file.FullName, fileStream);\n        }\n    }\n\n    private static async Task ImportManualChunkSeedDataAsync(string importDataFromDir, IServiceScope scope)\n    {\n        var semanticMemory = scope.ServiceProvider.GetRequiredService<IMemoryStore>();\n        var collections = await semanticMemory.GetCollectionsAsync().ToListAsync();\n\n        if (!collections.Contains(ManualCollectionName))\n        {\n            await semanticMemory.CreateCollectionAsync(ManualCollectionName);\n\n            using var fileStream = File.OpenRead(Path.Combine(importDataFromDir, \"manual-chunks.json\"));\n            var manualChunks = JsonSerializer.DeserializeAsyncEnumerable<ManualChunk>(fileStream);\n            await foreach (var chunkChunk in ReadChunkedAsync(manualChunks, 1000))\n            {\n                var mappedRecords = chunkChunk.Select(chunk =>\n                {\n                    var id = chunk!.ChunkId.ToString();\n                    var metadata = new MemoryRecordMetadata(false, id, chunk.Text, \"\", $\"productid:{chunk.ProductId}\", $\"pagenumber:{chunk.PageNumber}\");\n                    var embedding = MemoryMarshal.Cast<byte, float>(new ReadOnlySpan<byte>(chunk.Embedding)).ToArray();\n                    return new MemoryRecord(metadata, embedding, null);\n                });\n\n                await foreach (var _ in semanticMemory.UpsertBatchAsync(ManualCollectionName, mappedRecords)) { }\n            }\n        }\n    }\n\n    private static async Task<bool> HasAnyAsync<T>(IAsyncEnumerable<T> asyncEnumerable)\n    {\n        await foreach (var item in asyncEnumerable)\n        {\n            return true;\n        }\n\n        return false;\n    }\n\n    private static async IAsyncEnumerable<IEnumerable<T>> ReadChunkedAsync<T>(IAsyncEnumerable<T> source, int chunkLength)\n    {\n        var buffer = new T[chunkLength];\n        var index = 0;\n        await foreach (var item in source)\n        {\n            buffer[index++] = item;\n            if (index == chunkLength)\n            {\n                yield return new ArraySegment<T>(buffer, 0, index);\n                index = 0;\n            }\n        }\n\n        if (index > 0)\n        {\n            yield return new ArraySegment<T>(buffer, 0, index);\n        }\n    }\n\n    class QdrantResult\n    {\n        public required QdrantResultEntry[] Result { get; set; }\n    }\n\n    class QdrantResultEntry\n    {\n        public float Score { get; set; }\n        public required QdrantResultEntryPayload Payload { get; set; }\n    }\n\n    class QdrantResultEntryPayload\n    {\n        public required string Id { get; set; }\n        public required string Text { get; set; }\n        public required string External_Source_Name { get; set; }\n        public required string Additional_Metadata { get; set; }\n    }\n}\n"
  },
  {
    "path": "src/Backend/Services/ProductSemanticSearch.cs",
    "content": "﻿using System.Text.Json;\nusing eShopSupport.Backend.Data;\nusing eShopSupport.ServiceDefaults.Clients.Backend;\nusing Microsoft.SemanticKernel.Memory;\n\nnamespace eShopSupport.Backend.Services;\n\npublic class ProductSemanticSearch(ISemanticTextMemory semanticTextMemory)\n{\n    private const string ProductCollectionName = \"products\";\n\n    public async Task<IEnumerable<FindProductsResult>> FindProductsAsync(string searchText)\n    {\n        var results = new List<FindProductsResult>();\n        await foreach (var result in semanticTextMemory.SearchAsync(ProductCollectionName, searchText, minRelevanceScore: 0.6, limit: 5))\n        {\n            // It's a bit weird to get the brand from \"description\" but MemoryQueryResult doesn't have more structured custom metadata\n            results.Add(new FindProductsResult(int.Parse(result.Metadata.Id), result.Metadata.Description, result.Metadata.Text));\n        }\n\n        return results;\n    }\n\n    public static async Task EnsureSeedDataImportedAsync(IServiceProvider services, string? initialImportDataDir)\n    {\n        if (!string.IsNullOrEmpty(initialImportDataDir))\n        {\n            using var scope = services.CreateScope();\n            await ImportProductSeedDataAsync(initialImportDataDir, scope);\n        }\n    }\n\n    private static async Task ImportProductSeedDataAsync(string importDataFromDir, IServiceScope scope)\n    {\n        var semanticMemory = scope.ServiceProvider.GetRequiredService<IMemoryStore>();\n        var collections = await semanticMemory.GetCollectionsAsync().ToListAsync();\n\n        if (!collections.Contains(ProductCollectionName))\n        {\n            var products = JsonSerializer.Deserialize<Product[]>(\n                File.ReadAllText(Path.Combine(importDataFromDir, \"products.json\")))!;\n\n            await semanticMemory.CreateCollectionAsync(ProductCollectionName);\n            var mappedRecords = products.Select(product =>\n            {\n                var id = product.ProductId.ToString();\n                var metadata = new MemoryRecordMetadata(false, id, product.Model, product.Brand, \"\", \"\");\n                return new MemoryRecord(metadata, product.NameEmbedding, null);\n            });\n\n            await foreach (var _ in semanticMemory.UpsertBatchAsync(ProductCollectionName, mappedRecords)) { }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Backend/Services/TicketSummarizer.cs",
    "content": "﻿using System.Text;\nusing System.Threading.RateLimiting;\nusing eShopSupport.Backend.Data;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.Extensions.AI;\nusing StackExchange.Redis;\n\nnamespace eShopSupport.Backend.Services;\n\npublic class TicketSummarizer(IServiceScopeFactory scopeFactory)\n{\n    // Because this LLM call can be triggered by external end-user actions, it's helpful to impose a rate limit\n    // to prevent resource consumption abuse. If the rate limit is exceeded, we'll simply not compute updated summaries\n    // for a while, but everything else will continue to work. In a real application, also consider:\n    // - Adjusting the parameters based on your traffic and usage patterns\n    // - Scoping the rate limit to be per-user\n    private static TokenBucketRateLimiter RateLimiter = new(new()\n    {\n        // With these settings, we're limited to generating one summary every 2 seconds as a long-run average, but\n        // can burst to up to 100 summaries in a short period if it's been several minutes since the last one.\n        AutoReplenishment = true,\n        TokenLimit = 100,\n        ReplenishmentPeriod = TimeSpan.FromSeconds(10),\n        TokensPerPeriod = 5,\n    });\n\n    public void UpdateSummary(int ticketId, bool enforceRateLimit)\n    {\n        if (enforceRateLimit)\n        {\n            using var lease = RateLimiter.AttemptAcquire();\n            if (lease.IsAcquired)\n            {\n                _ = UpdateSummaryAsync(ticketId);\n            }\n        }\n        else\n        {\n            _ = UpdateSummaryAsync(ticketId);\n        }\n    }\n\n    private async Task UpdateSummaryAsync(int ticketId)\n    {\n        await using var scope = scopeFactory.CreateAsyncScope();\n        var logger = scope.ServiceProvider.GetRequiredService<ILogger<TicketSummarizer>>();\n\n        var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();\n        var redisConnection = scope.ServiceProvider.GetRequiredService<IConnectionMultiplexer>();\n        var chatClient = scope.ServiceProvider.GetRequiredService<IChatClient>();\n\n        var ticket = await db.Tickets\n            .Include(t => t.Product)\n            .Include(t => t.Messages)\n            .FirstOrDefaultAsync(t => t.TicketId == ticketId);\n        if (ticket is not null)\n        {\n            // The reason for prompting to express satisfaction in words rather than numerically, and forcing it to generate a summary\n            // of the customer's words before doing so, are necessary prompt engineering techniques. If it's asked to generate sentiment\n            // score without first summarizing the customer's words, then it scores the agent's response even when told not to. If it's\n            // asked to score numerically, it produces wildly random scores - it's much better with words than numbers.\n            string[] satisfactionScores = [\"AbsolutelyFurious\", \"VeryUnhappy\", \"Unhappy\", \"Disappointed\", \"Indifferent\", \"Pleased\", \"Happy\", \"Delighted\", \"UnspeakablyThrilled\"];\n\n            var product = ticket.Product;\n            var prompt = $$\"\"\"\n                You are part of a customer support ticketing system.\n                Your job is to write brief summaries of customer support interactions. This is to help support agents\n                understand the context quickly so they can help the customer efficiently.\n\n                Here are details of a support ticket.\n\n                Product: {{product?.Model ?? \"Not specified\"}}\n                Brand: {{product?.Brand ?? \"Not specified\"}}\n\n                The message log so far is:\n\n                {{FormatMessagesForPrompt(ticket.Messages)}}\n\n                Write these summaries:\n\n                1. A longer summary that is up to 30 words long, condensing as much distinctive information\n                    as possible. Do NOT repeat the customer or product name, since this is known anyway.\n                    Try to include what SPECIFIC questions/info were given, not just stating in general that questions/info were given.\n                    Always cite specifics of the questions or answers. For example, if there is pending question, summarize it in a few words.\n                    FOCUS ON THE CURRENT STATUS AND WHAT KIND OF RESPONSE (IF ANY) WOULD BE MOST USEFUL FROM THE NEXT SUPPORT AGENT.\n\n                2. A shorter summary that is up to 8 words long. This functions as a title for the ticket,\n                    so the goal is to distinguish what's unique about this ticket.\n\n                3. A 10-word summary of the latest thing the CUSTOMER has said, ignoring any agent messages. Then, based\n                    ONLY on tenWordsSummarizingOnlyWhatCustomerSaid, score the customer's satisfaction using one of the following\n                    phrases ranked from worst to best:\n                    {{string.Join(\", \", satisfactionScores)}}.\n                    Pay particular attention to the TONE of the customer's messages, as we are most interested in their emotional state.\n\n                Both summaries will only be seen by customer support agents.\n\n                Respond as JSON in the following form: {\n                  \"LongSummary\": \"string\",\n                  \"ShortSummary\": \"string\",\n                  \"TenWordsSummarizingOnlyWhatCustomerSaid\": \"string\",\n                  \"CustomerSatisfaction\": \"string\"\n                }\n                \"\"\";\n\n            var response = await chatClient.GetResponseAsync<Response>(prompt);\n            if (!response.TryGetResult(out var parsed))\n            {\n                return;\n            }\n\n            var shortSummary = parsed.ShortSummary;\n            var longSummary = parsed.LongSummary;\n            int? satisfactionScore = Array.IndexOf(satisfactionScores, parsed.CustomerSatisfaction ?? string.Empty);\n            if (satisfactionScore < 0)\n            {\n                satisfactionScore = null;\n            }\n\n            await db.Tickets.Where(t => t.TicketId == ticketId).ExecuteUpdateAsync(t => t\n                .SetProperty(t => t.ShortSummary, shortSummary)\n                .SetProperty(t => t.LongSummary, longSummary)\n                .SetProperty(t => t.CustomerSatisfaction, satisfactionScore));\n\n            await redisConnection.GetSubscriber().PublishAsync(\n                RedisChannel.Literal($\"ticket:{ticketId}\"), \"Updated\");\n        }\n    }\n\n    private static string FormatMessagesForPrompt(IReadOnlyList<Message> messages)\n    {\n        var sb = new StringBuilder();\n        foreach (var message in messages)\n        {\n            sb.AppendLine($\"<message role=\\\"{(message.IsCustomerMessage ? \"customer\" : \"support\")}\\\">{message.Text}</message>\");\n        }\n        return sb.ToString();\n    }\n\n    private class Response\n    {\n        public string? LongSummary { get; set; }\n        public string? ShortSummary { get; set; }\n        public string? TenWordsSummarizingOnlyWhatCustomerSaid { get; set; }\n        public string? CustomerSatisfaction { get; set; }\n    }\n}\n"
  },
  {
    "path": "src/Backend/appsettings.Development.json",
    "content": "{\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Information\",\n      \"Microsoft.AspNetCore\": \"Warning\"\n    }\n  }\n}\n"
  },
  {
    "path": "src/Backend/appsettings.json",
    "content": "{\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Information\",\n      \"Microsoft.AspNetCore\": \"Warning\"\n    }\n  },\n  \"AllowedHosts\": \"*\"\n}\n"
  },
  {
    "path": "src/CustomerWebUI/Components/App.razor",
    "content": "﻿<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n    <meta charset=\"utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <base href=\"/\" />\n    <link rel=\"stylesheet\" href=\"css/normalize.css\" />\n    <link rel=\"stylesheet\" href=\"css/app.css\" />\n    <link rel=\"stylesheet\" href=\"CustomerWebUI.styles.css\" />\n    <link rel=\"icon\" type=\"image/png\" href=\"images/favicon.png\" />\n    <HeadOutlet />\n</head>\n\n<body>\n    <Routes />\n    <script src=\"_framework/blazor.web.js\"></script>\n</body>\n\n</html>\n"
  },
  {
    "path": "src/CustomerWebUI/Components/Layout/FooterBar.razor",
    "content": "﻿<footer class='eshop-footer'>\n  <div class='eshop-footer-content'>\n    <div class='eshop-footer-row'>\n      <img role=\"presentation\" src='images/logo-footer.svg' class='logo logo-footer' />\n      <p>© AdventureWorks</p>\n    </div>\n  </div>\n</footer>"
  },
  {
    "path": "src/CustomerWebUI/Components/Layout/FooterBar.razor.css",
    "content": "﻿.eshop-footer {\n  margin-top: 3.5rem;\n  background-color: #000;\n  width: 100%;\n}\n\n.eshop-footer-content {\n  max-width: 120rem;\n  margin: auto;\n}\n\n.eshop-footer-row {\n  padding: 3.5rem 10rem;\n  color: white;\n  display: flex;\n  justify-content: flex-end;\n  align-items: center;\n}\n\n.eshop-footer .logo-footer {\n  color: white;\n  margin-right: auto;\n  width: 100px;\n  height: auto;\n}\n\n\n@media only screen and (max-width: 480px) { \n  .eshop-footer-row {\n    padding: 3.5rem 1rem;\n  }\n}\n\n@media only screen and (min-width: 481px) and (max-width: 1024px) { \n  .eshop-footer-row {\n    padding: 3.5rem 3rem;\n  }\n}"
  },
  {
    "path": "src/CustomerWebUI/Components/Layout/HeaderBar.razor",
    "content": "﻿@using Microsoft.AspNetCore.Components.Endpoints\n\n<div class=\"eshop-header\">\n    <div class=\"eshop-header-hero\">\n        <img role=\"presentation\" src=\"images/header.webp\" />\n    </div>\n    <div class=\"eshop-header-container\">\n        <nav class=\"eshop-header-navbar\">\n            <a class=\"logo logo-header\" href=\"\">\n                <img alt=\"AdventureWorks\" src=\"images/logo-header.svg\" class=\"logo logo-header\" />\n            </a>\n\n            <UserMenu />\n        </nav>\n        <div class=\"eshop-header-intro\">\n            <h1><SectionOutlet SectionName=\"page-header-title\" /></h1>\n            <p><SectionOutlet SectionName=\"page-header-subtitle\" /></p>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "src/CustomerWebUI/Components/Layout/HeaderBar.razor.css",
    "content": "﻿.eshop-header {\n    position: relative;\n    max-width: 120rem;\n    margin: auto;\n    width: 100%;\n}\n\n.eshop-header.home .eshop-header-container {\n    height: 38rem;\n    margin-bottom: 0;\n}\n\n.eshop-header .eshop-header-container {\n    height: 15rem;\n    margin-bottom: 1rem;\n}\n\n.eshop-header-hero {\n    overflow: hidden;\n    position: absolute;\n    max-width: 100%;\n    left: 0;\n    top: 0; \n}\n\n.eshop-header-container {\n    position: relative;\n    margin: auto;\n    margin: 0 10rem;\n}\n\n.eshop-header-intro {\n    position: absolute;\n    max-width: 48rem;\n    bottom: 3rem;\n    white-space: nowrap;\n}\n\n.eshop-header-intro h1 {\n    color: #000;\n    font-size: 3.5rem;\n    font-style: normal;\n    font-weight: 700;\n    line-height: 100%;\n    margin: 0;\n}\n\n.eshop-header-intro p {\n    color: #000;\n    font-size: 2rem;\n    font-style: normal;\n    font-weight: 700;\n    line-height: 125%;\n    margin: 0;\n}\n\n.eshop-header .logo-header {\n    color: black;\n    margin-right: auto;\n    width: 20vw;\n    height: auto;\n    max-width: 250px;\n    min-width: 100px;\n}\n\n.eshop-header-navbar {\n    display: flex;\n    flex-direction: row;\n    justify-content: flex-end;\n    align-items: center;\n    margin-top: 1.25rem;\n    gap: 1.5rem;\n}\n\n@media only screen and (max-width: 480px) { \n    .eshop-header-hero {\n        height: 18rem;\n    }\n\n    .eshop-header-hero img {\n        width: 100%;\n        height: 100%;\n        object-fit: cover;\n        object-position: center;\n    }\n\n    .eshop-header .eshop-header-container {\n        height: 15rem;\n        margin-bottom: 4rem;\n    }\n\n    .eshop-header-container {\n        margin: 0 1rem;\n    }\n\n    .eshop-header.home .eshop-header-container {\n        height: 18rem;\n        margin: 0 1rem;\n    }\n\n    .eshop-header-intro {\n        white-space: wrap;\n        bottom: 0;\n    }\n\n    .eshop-header-intro h1 {\n        font-size: 2rem;\n    }\n    \n    .eshop-header-intro p {\n        font-size: 1.5rem;\n    }\n}\n\n@media only screen and (min-width: 481px) and (max-width: 1024px) { \n    .eshop-header.home .eshop-header-hero {\n        height: 24rem;\n    }\n\n    .eshop-header .eshop-header-hero {\n        height: 15rem;\n    }\n\n    .eshop-header-hero img {\n        width: 100%;\n        height: 100%;\n        object-fit: cover;\n        object-position: center;\n    }\n\n    .eshop-header-container {\n        margin: 0 1rem;\n        margin: 0 3rem;\n    }\n\n    .eshop-header.home .eshop-header-container {\n        height: 24rem;\n        margin: 0 3rem;\n    }\n\n    .eshop-header-intro {\n        white-space: wrap;\n    }\n\n    .eshop-header-intro h1 {\n        font-size: 2rem;\n    }\n    \n    .eshop-header-intro p {\n        font-size: 1.5rem;\n    }\n}"
  },
  {
    "path": "src/CustomerWebUI/Components/Layout/MainLayout.razor",
    "content": "﻿@inherits LayoutComponentBase\n\n<div class=\"container\">\n    <HeaderBar />\n    @Body\n    <FooterBar />\n</div>\n\n<div id=\"blazor-error-ui\">\n    An unhandled error has occurred.\n    <a href=\"\" class=\"reload\">Reload</a>\n    <a class=\"dismiss\">🗙</a>\n</div>\n"
  },
  {
    "path": "src/CustomerWebUI/Components/Layout/MainLayout.razor.css",
    "content": "#blazor-error-ui {\n    background: lightyellow;\n    bottom: 0;\n    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);\n    display: none;\n    left: 0;\n    padding: 0.6rem 1.25rem 0.7rem 1.25rem;\n    position: fixed;\n    width: 100%;\n    z-index: 1000;\n}\n\n    #blazor-error-ui .dismiss {\n        cursor: pointer;\n        position: absolute;\n        right: 0.75rem;\n        top: 0.5rem;\n    }\n\n.container {\n    display: flex;\n    flex-direction: column;\n    justify-items: stretch;\n}\n"
  },
  {
    "path": "src/CustomerWebUI/Components/Layout/UserMenu.razor",
    "content": "﻿@using Microsoft.AspNetCore.Components.Authorization\n@inject NavigationManager Nav\n\n<AuthorizeView>\n    <Authorized>\n        <h3>@context.User.Identity?.Name</h3>\n        <div class=\"dropdown-menu\">\n            <span class=\"dropdown-button\"><img role=\"presentation\" src=\"icons/user.svg\" /></span>\n            <div class=\"dropdown-content\">\n                <a class=\"dropdown-item\" href=\"support\">My support</a>\n                <form class=\"dropdown-item\" method=\"post\" action=\"user/signout\" @formname=\"logout\">\n                    <AntiforgeryToken />\n                    <button type=\"submit\">Log out</button>\n                </form>\n            </div>\n        </div>\n    </Authorized>\n</AuthorizeView>\n\n@code {\n    [CascadingParameter]\n    public HttpContext? HttpContext { get; set; }\n}\n"
  },
  {
    "path": "src/CustomerWebUI/Components/Layout/UserMenu.razor.css",
    "content": "﻿.dropdown-menu {\n    position: relative;\n    display: inline-block;\n}\n\n.dropdown-content {\n    display: none;\n    position: absolute;\n    background-color: #FFF;\n    min-width: 8rem;\n    box-shadow: 0 0.25rem 0.5rem 0 rgba(0, 0, 0, 0.2);\n    z-index: 1;\n}\n\n.dropdown-item {\n    padding: 0.75rem 1rem;\n    text-decoration: none;\n    display: block;\n    color: #000;\n}\n\n.dropdown-item:hover {\n    background-color: #ddd;\n}\n\n.dropdown-menu:hover .dropdown-content {\n    display: block;\n}\n\n.dropdown-item button {\n    border: 0;\n    background: transparent;\n    cursor: pointer;\n    width: 100%;\n    padding: 0;\n    text-align: left;\n}\n"
  },
  {
    "path": "src/CustomerWebUI/Components/Pages/Error.razor",
    "content": "﻿@page \"/Error\"\n@using System.Diagnostics\n\n<PageTitle>Error</PageTitle>\n\n<h1 class=\"text-danger\">Error.</h1>\n<h2 class=\"text-danger\">An error occurred while processing your request.</h2>\n\n@if (ShowRequestId)\n{\n    <p>\n        <strong>Request ID:</strong> <code>@RequestId</code>\n    </p>\n}\n\n<h3>Development Mode</h3>\n<p>\n    Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.\n</p>\n<p>\n    <strong>The Development environment shouldn't be enabled for deployed applications.</strong>\n    It can result in displaying sensitive information from exceptions to end users.\n    For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>\n    and restarting the app.\n</p>\n\n@code{\n    [CascadingParameter]\n    private HttpContext? HttpContext { get; set; }\n\n    private string? RequestId { get; set; }\n    private bool ShowRequestId => !string.IsNullOrEmpty(RequestId);\n\n    protected override void OnInitialized() =>\n        RequestId = Activity.Current?.Id ?? HttpContext?.TraceIdentifier;\n}\n"
  },
  {
    "path": "src/CustomerWebUI/Components/Pages/Home.razor",
    "content": "﻿@page \"/\"\n@inject NavigationManager Nav\n@code {\n    protected override void OnInitialized()\n    {\n        Nav.NavigateTo(\"support\");\n    }\n}\n"
  },
  {
    "path": "src/CustomerWebUI/Components/Pages/Support/Ticket.razor",
    "content": "﻿@page \"/support/tickets/{TicketId:int}\"\n@inject CustomerBackendClient Backend\n@inject NavigationManager Nav\n@implements IValidatableObject\n@using System.ComponentModel.DataAnnotations\n@using eShopSupport.ServiceDefaults.Clients.Backend\n\n<PageTitle>Support | AdventureWorks</PageTitle>\n<SectionContent SectionName=\"page-header-title\">Your support request</SectionContent>\n\n<div class=\"page-gutters\">\n    @if (TicketDetails is { } ticket)\n    {\n        <h3>Created: @ticket.CreatedAt.ToShortDateString()</h3>\n\n        @if (ticket.ProductModel is { } productModel)\n        {\n            <h3>Product: @productModel</h3>\n        }\n\n        <div class=\"messages\">\n            @foreach (var message in ticket.Messages)\n            {\n                <div class=\"message @(message.IsCustomerMessage ? \"customer\" : \"support\")\">\n                    <div class=\"message-metadata\">\n                        <span class=\"timestamp\">@message.CreatedAt.ToShortDateString()</span>\n                        <span class=\"filler\">by</span>\n                        <span class=\"sender\">@(message.IsCustomerMessage ? \"You\" : \"Support\")</span>\n                    </div>\n                    <div class=\"message-text\">@message.MessageText</div>\n                </div>\n            }\n        </div>\n\n        <div class=\"actions\">\n            @if (ticket.TicketStatus == TicketStatus.Closed)\n            {\n                <p>\n                    This support request is now <strong>closed</strong>. If you need any further help, please\n                    <a href=\"support/new\">create a new support request</a>.\n                </p>\n            }\n            else\n            {\n                <h3>Send a further message</h3>\n                <EditForm Model=\"@this\" FormName=\"ticket\" OnValidSubmit=\"@SubmitAsync\" Enhance>\n                    <DataAnnotationsValidator />\n                    <InputTextArea @bind-Value=\"NewMessage\" placeholder=\"Type your message...\" />\n                    <ValidationMessage For=\"@(() => NewMessage)\" />\n\n                    <p>If you're happy with the answer, or if you no longer need support, please close this request using the button below.</p>\n\n                    <p>\n                        <button type=\"submit\" name=\"submitter\" value=\"@CloseAction\">Close</button>\n                        <button type=\"submit\" name=\"submitter\" value=\"@SendAction\">Send</button>\n                    </p>\n                </EditForm>\n            }\n        </div>\n    }\n</div>\n\n@code {\n    const string CloseAction = \"close\";\n    const string SendAction = \"send\";\n\n    [Parameter]\n    public int TicketId { get; set; }\n\n    [CascadingParameter]\n    public HttpContext HttpContext { get; set; } = default!;\n\n    [SupplyParameterFromForm]\n    public string? Submitter { get; set; }\n\n    [SupplyParameterFromForm]\n    public string? NewMessage { get; set; }\n\n    TicketDetailsResult? TicketDetails { get; set; }\n\n    protected override async Task OnInitializedAsync()\n    {\n        TicketDetails = await Backend.GetTicketDetailsAsync(TicketId);\n    }\n\n    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)\n    {\n        if (Submitter == SendAction && string.IsNullOrWhiteSpace(NewMessage))\n        {\n            yield return new ValidationResult(\"Please type a message\", new[] { nameof(NewMessage) });\n        }\n    }\n\n    async Task SubmitAsync()\n    {\n        if (TicketDetails!.TicketStatus != TicketStatus.Open)\n        {\n            Nav.NavigateTo(\"/support\");\n        }\n\n        var ticketId = TicketDetails.TicketId;\n        if (!string.IsNullOrWhiteSpace(NewMessage))\n        {\n            await Backend.SendTicketMessageAsync(ticketId, new(NewMessage));\n        }\n\n        if (Submitter == CloseAction)\n        {\n            await Backend.CloseTicketAsync(ticketId);\n        }\n\n        // Reload the ticket data to update the UI\n        Nav.Refresh();\n    }\n}\n"
  },
  {
    "path": "src/CustomerWebUI/Components/Pages/Support/Ticket.razor.css",
    "content": "﻿.messages {\n    display: flex;\n    flex-direction: column;\n    gap: 1rem;\n    align-items: flex-start;\n    padding-bottom: 2rem;\n    flex-grow: 1;\n}\n\n.message {\n    min-width: 35%;\n    max-width: 75%;\n}\n\n.message-text {\n    background: #6e4999;\n    color: white;\n    border-radius: 0.5rem;\n    padding: 1rem 1.5rem;\n    white-space: pre-line;\n    word-break: break-word;\n    line-height: 1.5rem;\n}\n\n.message.support {\n    align-self: flex-end;\n}\n\n    .message.support .message-text {\n        background-color: #dcd9d9;\n        color: black;\n    }\n\n.message-metadata {\n    margin: 0 0.5rem 0.4rem 0.5rem;\n    font-size: 90%;\n}\n\n.message.support .message-metadata {\n    text-align: right;\n}\n\n.message-metadata .timestamp, .message-metadata .sender {\n    font-weight: 500;\n}\n\n.message-metadata .filler {\n    opacity: 0.7;\n}\n\n::deep textarea {\n    width: 100%;\n    height: 5rem;\n    padding: 1rem;\n    border-radius: 0.5rem;\n    background-color: #f6f6f6;\n}\n\nbutton:focus {\n    outline: 2px solid orange;\n    outline-offset: 1px;\n}\n\nbutton {\n    text-decoration: none;\n    background: black;\n    color: white;\n    display: inline-block;\n    border-radius: 0.4rem;\n    font-weight: 500;\n    padding: 0.6rem 1.5rem;\n    border: 1px solid black;\n    cursor: pointer;\n    margin-right: 1rem;\n}\n\n    button:hover {\n        background: #666;\n    }\n\n    button:active {\n        background: #333;\n    }\n\nbutton[value=close] {\n    background-color: white;\n    border-color: black;\n    color: black;\n}\n"
  },
  {
    "path": "src/CustomerWebUI/Components/Pages/Support/TicketCreate.razor",
    "content": "﻿@page \"/support/new\"\n@implements IValidatableObject\n@inject CustomerBackendClient Backend\n@inject NavigationManager Nav\n@using System.ComponentModel.DataAnnotations\n@using Microsoft.AspNetCore.Components.Authorization\n@using SmartComponents\n@using System.Security.Claims\n@using eShopSupport.ServiceDefaults.Clients.Backend\n\n<PageTitle>Support | AdventureWorks</PageTitle>\n<SectionContent SectionName=\"page-header-title\">New support request</SectionContent>\n\n<EditForm class=\"page-gutters\" FormName=\"support\" Model=\"@this\" OnValidSubmit=\"@HandleSubmitAsync\">\n    <DataAnnotationsValidator />\n\n    <p>Is this about a specific product?</p>\n    <div class=\"answer is-specific-product\">\n        <InputRadioGroup @bind-Value=\"@IsSpecificProduct\">\n            <p>\n                <label>\n                    <InputRadio Value=\"@true\" />\n                    Yes\n                </label>\n            </p>\n            <p>\n                <label>\n                    <InputRadio Value=\"@false\" />\n                    No\n                </label>\n            </p>\n        </InputRadioGroup>\n    </div>\n\n    <div class=\"choose-product\">\n        <p>Which product is it?</p>\n        <div class=\"answer\">\n            <SmartComboBox Url=\"api/product-search\" @bind-Value=\"@ProductName\" placeholder=\"Search for product...\" />\n            <ValidationMessage For=\"@(() => ProductName)\" />\n        </div>\n    </div>\n    \n    <div class=\"message\">\n        <p>How can we help?</p>\n        <div class=\"answer\">\n            <InputTextArea @bind-Value=\"Message\" placeholder=\"Type your message...\" />\n            <ValidationMessage For=\"@(() => Message)\" />\n        </div>\n    </div>\n\n    <p class=\"submit\">\n        <button type=\"submit\">Submit</button>\n    </p>\n</EditForm>\n\n@code {\n    [SupplyParameterFromForm, Required(ErrorMessage = \"Please answer this question\")]\n    public bool? IsSpecificProduct { get; set; }\n\n    [SupplyParameterFromForm]\n    public string? ProductName { get; set; }\n\n    [SupplyParameterFromForm, Required(ErrorMessage = \"Please enter your support request here\")]\n    public string? Message { get; set; }\n\n    [CascadingParameter]\n    public HttpContext HttpContext { get; set; } = default!;\n\n    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)\n    {\n        if (IsSpecificProduct == true && string.IsNullOrWhiteSpace(ProductName))\n        {\n            yield return new ValidationResult(\"Please specify the product\", new[] { nameof(ProductName) });\n        }\n    }\n\n    async Task HandleSubmitAsync()\n    {\n        await Backend.CreateTicketAsync(new(ProductName, Message!));\n        Nav.NavigateTo(\"support\");\n    }\n}\n"
  },
  {
    "path": "src/CustomerWebUI/Components/Pages/Support/TicketCreate.razor.css",
    "content": "﻿.answer {\n    background-color: #eee;\n    border-radius: 0.5rem;\n    padding: 1rem 1.5rem;\n    margin: 0.5rem 0;\n    min-width: 20rem;\n    display: inline-block;\n}\n\n.is-specific-product {\n    padding: 0.75rem 0.75rem;\n}\n\nlabel:has(input[type=radio]) {\n    padding: 0.5rem 0.75rem;\n    display: block;\n    cursor: pointer;\n    border-radius: 0.2rem;\n}\n\nlabel:has(input[type=radio]):hover {\n    background-color: rgba(0,0,0,0.1);\n}\n\n.answer p {\n    padding: 0;\n    margin: 0;\n}\n\n.choose-product, .submit, .message {\n    display: none;\n}\n\nform:has(.is-specific-product input[value=True]:checked) .choose-product {\n    display: block;\n}\n\nform:has(.is-specific-product input:checked) .message, form:has(.is-specific-product input:checked) .submit {\n    display: block;\n}\n\n::deep input[type=text], ::deep textarea, ::deep input[role=combobox] {\n    min-width: 50vw;\n    padding: 0.5rem 1rem;\n    border-radius: 0.4rem;\n    border-width: 1px;\n}\n\n::deep textarea {\n    height: 8rem;\n    padding: 1rem; 1rem 1rem 1rem;\n}\n\nbutton {\n    text-decoration: none;\n    background: black;\n    color: white;\n    padding: 0.6rem 1.5rem;\n    margin-top: 0.75rem;\n    display: inline-block;\n    border-radius: 0.4rem;\n    font-weight: 500;\n    border-width: 0;\n}\n\n    button:hover {\n        background: #666;\n    }\n\n    button:active {\n        background: #333;\n    }\n\n::deep .validation-message {\n    margin-top: 0.5rem;\n}\n"
  },
  {
    "path": "src/CustomerWebUI/Components/Pages/Support/TicketList.razor",
    "content": "﻿@page \"/support\"\n@attribute [StreamRendering]\n@inject CustomerBackendClient Backend\n@using Microsoft.AspNetCore.Authorization\n@using eShopSupport.Backend.Data\n@using eShopSupport.ServiceDefaults.Clients.Backend\n\n<PageTitle>Support | AdventureWorks</PageTitle>\n<SectionContent SectionName=\"page-header-title\">Support</SectionContent>\n\n<div class=\"page-gutters\">\n    <h1>We're here to support your adventure</h1>\n    <p>\n        If you have questions about our products, or are having\n        trouble with anything you bought from us, just send us a message.\n    </p>\n\n    @if (tickets is null)\n    {\n        <p>Loading...</p>\n    }\n    else if (!tickets.Any())\n    {\n        <a class=\"start-button\" href=\"support/new\">Get started</a>\n    }\n    else\n    {\n        <h2>Your support requests</h2>\n        \n        <table>\n            <thead>\n                <tr>\n                    <th>ID</th>\n                    <th>Created</th>\n                    <th>Product</th>\n                    <th>Status</th>\n                    <th></th>\n                </tr>\n            </thead>\n            <tbody>\n                @foreach (var ticket in tickets)\n                {\n                    <tr>\n                        <td>@ticket.TicketId</td>\n                        <td>@ticket.CreatedAt.ToShortDateString()</td>\n                        <td>@ticket.ProductName</td>\n                        <td>@ticket.TicketStatus</td>\n                        <td>\n                            <a class=\"action-button\" href=\"support/tickets/@ticket.TicketId\">View</a>\n                        </td>\n                    </tr>\n                }\n            </tbody>\n        </table>\n\n        <a class=\"start-button\" href=\"support/new\">Start a new support request</a>\n    }\n</div>\n\n@code {\n    [CascadingParameter]\n    public HttpContext HttpContext { get; set; } = default!;\n\n    IEnumerable<ListTicketsResultItem>? tickets;\n\n    protected override async Task OnInitializedAsync()\n    {\n        tickets = (await Backend.ListTicketsAsync()).Items;\n    }\n}\n"
  },
  {
    "path": "src/CustomerWebUI/Components/Pages/Support/TicketList.razor.css",
    "content": "﻿h2 {\n    margin-top: 3rem;\n}\n\n.start-button, .action-button {\n    text-decoration: none;\n    background: black;\n    color: white;\n    display: inline-block;\n    border-radius: 0.4rem;\n    font-weight: 500;\n}\n\n.action-button {\n    padding: 0.3rem 1rem;\n}\n\n.start-button {\n    padding: 0.6rem 1.5rem;\n    margin-top: 0.75rem;\n}\n\n    .start-button:hover, .action-button:hover {\n        background: #666;\n    }\n\n    .start-button:active, .action-button:active {\n        background: #333;\n    }\n\n    table {\n        min-width: 50vw;\n        border-collapse: collapse;\n    }\n\n    th {\n        text-align: left;\n    }\n\n    th, td {\n        padding: 0.4rem;\n    }\n\n    tr:hover {\n        background: #f6f6f6;\n    }"
  },
  {
    "path": "src/CustomerWebUI/Components/Routes.razor",
    "content": "﻿<Router AppAssembly=\"typeof(Program).Assembly\">\n    <Found Context=\"routeData\">\n        <RouteView RouteData=\"routeData\" DefaultLayout=\"typeof(Layout.MainLayout)\" />\n    </Found>\n</Router>\n"
  },
  {
    "path": "src/CustomerWebUI/Components/_Imports.razor",
    "content": "﻿@using System.Net.Http\n@using System.Net.Http.Json\n@using Microsoft.AspNetCore.Authorization\n@using Microsoft.AspNetCore.Components.Forms\n@using Microsoft.AspNetCore.Components.Routing\n@using Microsoft.AspNetCore.Components.Sections\n@using Microsoft.AspNetCore.Components.Web\n@using static Microsoft.AspNetCore.Components.Web.RenderMode\n@using Microsoft.AspNetCore.Components.Web.Virtualization\n@using Microsoft.JSInterop\n@using CustomerWebUI\n@using CustomerWebUI.Components\n\n@attribute [Authorize]\n"
  },
  {
    "path": "src/CustomerWebUI/CustomerWebUI.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n  <PropertyGroup>\n    <TargetFramework>net8.0</TargetFramework>\n    <Nullable>enable</Nullable>\n    <ImplicitUsings>enable</ImplicitUsings>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"SmartComponents.AspNetCore\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.Authentication.OpenIdConnect\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\Backend\\Backend.csproj\" />\n    <ProjectReference Include=\"..\\ServiceDefaults\\ServiceDefaults.csproj\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/CustomerWebUI/Program.cs",
    "content": "﻿using CustomerWebUI.Components;\nusing eShopSupport.ServiceDefaults;\nusing eShopSupport.ServiceDefaults.Clients.Backend;\nusing Microsoft.AspNetCore.Antiforgery;\nusing Microsoft.AspNetCore.Authentication;\nusing Microsoft.AspNetCore.Authentication.Cookies;\nusing Microsoft.AspNetCore.Authentication.OpenIdConnect;\nusing Microsoft.AspNetCore.Components.Authorization;\nusing Microsoft.AspNetCore.Components.Server;\nusing Microsoft.IdentityModel.JsonWebTokens;\n\nvar builder = WebApplication.CreateBuilder(args);\n\n// Add services to the container.\nbuilder.AddServiceDefaults();\nbuilder.Services.AddRazorComponents();\nbuilder.Services.AddSmartComponents();\nbuilder.Services.AddHttpClient<CustomerBackendClient>(client =>\n    client.BaseAddress = new Uri(\"http://backend/\"))\n    .AddAuthToken();\nbuilder.Services.AddCascadingAuthenticationState();\nbuilder.Services.AddScoped<AuthenticationStateProvider, ServerAuthenticationStateProvider>();\n\nJsonWebTokenHandler.DefaultInboundClaimTypeMap.Remove(\"sub\");\n\nbuilder.Services.AddAuthorization();\nbuilder.Services.AddAuthentication(options =>\n{\n    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;\n    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;\n})\n    .AddCookie()\n    .AddOpenIdConnect(options =>\n    {\n        options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;\n        options.Authority = builder.Configuration[\"IdentityUrl\"];\n        options.ClientId = \"customer-webui\";\n        options.ClientSecret = \"customer-webui-secret\";\n        options.ResponseType = \"code\";\n        options.SaveTokens = true;\n        options.GetClaimsFromUserInfoEndpoint = true;\n        options.TokenValidationParameters.NameClaimType = \"name\";\n\n        options.Scope.Clear();\n        options.Scope.Add(\"openid\");\n        options.Scope.Add(\"profile\");\n    });\n\nvar app = builder.Build();\n\n// Configure the HTTP request pipeline.\nif (!app.Environment.IsDevelopment())\n{\n    app.UseExceptionHandler(\"/Error\", createScopeForErrors: true);\n    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.\n    app.UseHsts();\n}\n\napp.UseHttpsRedirection();\napp.UseStaticFiles();\napp.UseAntiforgery();\n\napp.MapRazorComponents<App>();\n\napp.MapSmartComboBox(\"api/product-search\", async request =>\n{\n    var backend = request.HttpContext.RequestServices.GetRequiredService<CustomerBackendClient>();\n    var results = await backend.FindProductsAsync(request.Query.SearchText);\n    return results.Select(r => $\"{r.Model} ({r.Brand})\");\n});\n\napp.MapPost(\"/user/signout\", async (HttpContext httpContext, IAntiforgery antiforgery) =>\n{\n    await antiforgery.ValidateRequestAsync(httpContext);\n    await httpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);\n    await httpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme);\n}).AllowAnonymous();\n\napp.Run();\n"
  },
  {
    "path": "src/CustomerWebUI/Properties/launchSettings.json",
    "content": "{\n  \"$schema\": \"http://json.schemastore.org/launchsettings.json\",\n    \"profiles\": {\n      \"https\": {\n        \"commandName\": \"Project\",\n        \"dotnetRunMessages\": true,\n        \"launchBrowser\": true,\n        \"applicationUrl\": \"https://localhost:7220\",\n        \"environmentVariables\": {\n          \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n        }\n      }\n    }\n  }\n"
  },
  {
    "path": "src/CustomerWebUI/appsettings.Development.json",
    "content": "{\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Information\",\n      \"Microsoft.AspNetCore\": \"Warning\"\n    }\n  }\n}\n"
  },
  {
    "path": "src/CustomerWebUI/appsettings.json",
    "content": "{\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Information\",\n      \"Microsoft.AspNetCore\": \"Warning\"\n    }\n  },\n  \"AllowedHosts\": \"*\"\n}\n"
  },
  {
    "path": "src/CustomerWebUI/wwwroot/css/app.css",
    "content": "/* plus-jakarta-sans-200 - latin */\n@font-face {\n    font-display: swap;\n    font-family: 'Plus Jakarta Sans';\n    font-style: normal;\n    font-weight: 200;\n    src: url('../fonts/plus-jakarta-sans-v8-latin-200.woff2') format('woff2');\n}\n\n/* plus-jakarta-sans-200italic - latin */\n@font-face {\n    font-display: swap; \n    font-family: 'Plus Jakarta Sans';\n    font-style: italic;\n    font-weight: 200;\n    src: url('../fonts/plus-jakarta-sans-v8-latin-200italic.woff2') format('woff2');\n}\n\n/* plus-jakarta-sans-300 - latin */\n@font-face {\n    font-display: swap; \n    font-family: 'Plus Jakarta Sans';\n    font-style: normal;\n    font-weight: 300;\n    src: url('../fonts/plus-jakarta-sans-v8-latin-300.woff2') format('woff2');\n}\n\n/* plus-jakarta-sans-300italic - latin */\n@font-face {\n    font-display: swap; \n    font-family: 'Plus Jakarta Sans';\n    font-style: italic;\n    font-weight: 300;\n    src: url('../fonts/plus-jakarta-sans-v8-latin-300italic.woff2') format('woff2'); \n}\n\n/* plus-jakarta-sans-regular - latin */\n@font-face {\n    font-display: swap; \n    font-family: 'Plus Jakarta Sans';\n    font-style: normal;\n    font-weight: 400;\n    src: url('../fonts/plus-jakarta-sans-v8-latin-regular.woff2') format('woff2'); \n}\n  \n/* plus-jakarta-sans-italic - latin */\n@font-face {\n    font-display: swap; \n    font-family: 'Plus Jakarta Sans';\n    font-style: italic;\n    font-weight: 400;\n    src: url('../fonts/plus-jakarta-sans-v8-latin-italic.woff2') format('woff2'); \n}\n\n/* plus-jakarta-sans-500 - latin */\n@font-face {\n    font-display: swap; \n    font-family: 'Plus Jakarta Sans';\n    font-style: normal;\n    font-weight: 500;\n    src: url('../fonts/plus-jakarta-sans-v8-latin-500.woff2') format('woff2'); \n}\n\n/* plus-jakarta-sans-500italic - latin */\n@font-face {\n    font-display: swap; \n    font-family: 'Plus Jakarta Sans';\n    font-style: italic;\n    font-weight: 500;\n    src: url('../fonts/plus-jakarta-sans-v8-latin-500italic.woff2') format('woff2'); \n}\n\n/* plus-jakarta-sans-600 - latin */\n@font-face {\n    font-display: swap; \n    font-family: 'Plus Jakarta Sans';\n    font-style: normal;\n    font-weight: 600;\n    src: url('../fonts/plus-jakarta-sans-v8-latin-600.woff2') format('woff2'); \n}\n\n/* plus-jakarta-sans-600italic - latin */\n@font-face {\n    font-display: swap; \n    font-family: 'Plus Jakarta Sans';\n    font-style: italic;\n    font-weight: 600;\n    src: url('../fonts/plus-jakarta-sans-v8-latin-600italic.woff2') format('woff2'); \n}\n\n/* plus-jakarta-sans-700 - latin */\n@font-face {\n    font-display: swap; \n    font-family: 'Plus Jakarta Sans';\n    font-style: normal;\n    font-weight: 700;\n    src: url('../fonts/plus-jakarta-sans-v8-latin-700.woff2') format('woff2'); \n}\n\n/* plus-jakarta-sans-700italic - latin */\n@font-face {\n    font-display: swap; \n    font-family: 'Plus Jakarta Sans';\n    font-style: italic;\n    font-weight: 700;\n    src: url('../fonts/plus-jakarta-sans-v8-latin-700italic.woff2') format('woff2'); \n}\n\n/* plus-jakarta-sans-800 - latin */\n@font-face {\n    font-display: swap; \n    font-family: 'Plus Jakarta Sans';\n    font-style: normal;\n    font-weight: 800;\n    src: url('../fonts/plus-jakarta-sans-v8-latin-800.woff2') format('woff2'); \n}\n\n/* plus-jakarta-sans-800italic - latin */\n@font-face {\n    font-display: swap; \n    font-family: 'Plus Jakarta Sans';\n    font-style: italic;\n    font-weight: 800;\n    src: url('../fonts/plus-jakarta-sans-v8-latin-800italic.woff2') format('woff2'); \n}\n\n/* open-sans-300 - latin */\n@font-face {\n    font-display: swap;\n    font-family: 'Open Sans';\n    font-style: normal;\n    font-weight: 300;\n    src: url('../fonts/open-sans-v36-latin-300.woff2') format('woff2');\n}\n\n/* open-sans-300italic - latin */\n@font-face {\n    font-display: swap;\n    font-family: 'Open Sans';\n    font-style: italic;\n    font-weight: 300;\n    src: url('../fonts/open-sans-v36-latin-300italic.woff2') format('woff2');\n}\n\n/* open-sans-regular - latin */\n@font-face {\n    font-display: swap;\n    font-family: 'Open Sans';\n    font-style: normal;\n    font-weight: 400;\n    src: url('../fonts/open-sans-v36-latin-regular.woff2') format('woff2');\n}\n\n/* open-sans-italic - latin */\n@font-face {\n    font-display: swap;\n    font-family: 'Open Sans';\n    font-style: italic;\n    font-weight: 400;\n    src: url('../fonts/open-sans-v36-latin-italic.woff2') format('woff2');\n}\n\n/* open-sans-500 - latin */\n@font-face {\n    font-display: swap;\n    font-family: 'Open Sans';\n    font-style: normal;\n    font-weight: 500;\n    src: url('../fonts/open-sans-v36-latin-500.woff2') format('woff2');\n}\n  \n/* open-sans-500italic - latin */\n@font-face {\n    font-display: swap;\n    font-family: 'Open Sans';\n    font-style: italic;\n    font-weight: 500;\n    src: url('../fonts/open-sans-v36-latin-500italic.woff2') format('woff2');\n}\n\n/* open-sans-600 - latin */\n@font-face {\n    font-display: swap;\n    font-family: 'Open Sans';\n    font-style: normal;\n    font-weight: 600;\n    src: url('../fonts/open-sans-v36-latin-600.woff2') format('woff2');\n}\n\n/* open-sans-600italic - latin */\n@font-face {\n    font-display: swap;\n    font-family: 'Open Sans';\n    font-style: italic;\n    font-weight: 600;\n    src: url('../fonts/open-sans-v36-latin-600italic.woff2') format('woff2');\n}\n\n/* open-sans-700 - latin */\n@font-face {\n    font-display: swap;\n    font-family: 'Open Sans';\n    font-style: normal;\n    font-weight: 700;\n    src: url('../fonts/open-sans-v36-latin-700.woff2') format('woff2');\n}\n\n/* open-sans-700italic - latin */\n@font-face {\n    font-display: swap;\n    font-family: 'Open Sans';\n    font-style: italic;\n    font-weight: 700;\n    src: url('../fonts/open-sans-v36-latin-700italic.woff2') format('woff2');\n}\n\n/* open-sans-800 - latin */\n@font-face {\n    font-display: swap;\n    font-family: 'Open Sans';\n    font-style: normal;\n    font-weight: 800;\n    src: url('../fonts/open-sans-v36-latin-800.woff2') format('woff2');\n}\n\n/* open-sans-800italic - latin */\n@font-face {\n    font-display: swap;\n    font-family: 'Open Sans';\n    font-style: italic;\n    font-weight: 800;\n    src: url('../fonts/open-sans-v36-latin-800italic.woff2') format('woff2');\n}\n\nhtml, body {\n    margin: 0;\n    padding: 0;\n    min-height: 100vh;\n}\n\nbody {\n    font-family: 'Plus Jakarta Sans';\n}\n\n.container {\n    position: relative;\n    max-width: 120rem;\n    margin: auto;\n    min-height: 100vh;\n}\n\n.button {\n    display: flex;\n    padding: 1rem 0.75rem;\n    justify-content: center;\n    align-items: center;\n    gap: 0.25rem;\n    align-self: stretch;\n    border: none;\n    text-decoration: none;\n}\n\n.button.button-primary {\n    background: #000;\n    color: #FFF;\n}\n\n.button.button.button-secondary {\n    border: 1px solid #444;\n    background: #FFF;\n    color: #000;\n}\n\nh1:focus {\n    outline: none;\n}\n\n.valid.modified:not([type=checkbox]) {\n    outline: 1px solid #26b050;\n}\n\n.invalid {\n    outline: 1px solid red;\n}\n\n.validation-message {\n    color: red;\n}\n\n.blazor-error-boundary {\n    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;\n    padding: 1rem 1rem 1rem 3.7rem;\n    color: white;\n}\n\n    .blazor-error-boundary::after {\n        content: \"An error has occurred.\"\n    }\n\n.page-gutters {\n    padding: 0 10rem;\n    flex-grow: 1;\n}\n"
  },
  {
    "path": "src/CustomerWebUI/wwwroot/css/normalize.css",
    "content": "/**\n * 1. Correct the line height in all browsers.\n * 2. Prevent adjustments of font size after orientation changes in iOS.\n */\n\n html {\n    line-height: 1.15; /* 1 */\n    -webkit-text-size-adjust: 100%; /* 2 */\n  }\n  \n  /* Sections\n     ========================================================================== */\n  \n  /**\n   * Remove the margin in all browsers.\n   */\n  \n  body {\n    margin: 0;\n  }\n  \n  /**\n   * Render the `main` element consistently in IE.\n   */\n  \n  main {\n    display: block;\n  }\n  \n  /**\n   * Correct the font size and margin on `h1` elements within `section` and\n   * `article` contexts in Chrome, Firefox, and Safari.\n   */\n  \n  h1 {\n    font-size: 2em;\n    margin: 0.67em 0;\n  }\n  \n  /* Grouping content\n     ========================================================================== */\n  \n  /**\n   * 1. Add the correct box sizing in Firefox.\n   * 2. Show the overflow in Edge and IE.\n   */\n  \n  hr {\n    box-sizing: content-box; /* 1 */\n    height: 0; /* 1 */\n    overflow: visible; /* 2 */\n  }\n  \n  /**\n   * 1. Correct the inheritance and scaling of font size in all browsers.\n   * 2. Correct the odd `em` font sizing in all browsers.\n   */\n  \n  pre {\n    font-family: monospace, monospace; /* 1 */\n    font-size: 1em; /* 2 */\n  }\n  \n  /* Text-level semantics\n     ========================================================================== */\n  \n  /**\n   * Remove the gray background on active links in IE 10.\n   */\n  \n  a {\n    background-color: transparent;\n  }\n  \n  /**\n   * 1. Remove the bottom border in Chrome 57-\n   * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n   */\n  \n  abbr[title] {\n    border-bottom: none; /* 1 */\n    text-decoration: underline; /* 2 */\n    text-decoration: underline dotted; /* 2 */\n  }\n  \n  /**\n   * Add the correct font weight in Chrome, Edge, and Safari.\n   */\n  \n  b,\n  strong {\n    font-weight: bolder;\n  }\n  \n  /**\n   * 1. Correct the inheritance and scaling of font size in all browsers.\n   * 2. Correct the odd `em` font sizing in all browsers.\n   */\n  \n  code,\n  kbd,\n  samp {\n    font-family: monospace, monospace; /* 1 */\n    font-size: 1em; /* 2 */\n  }\n  \n  /**\n   * Add the correct font size in all browsers.\n   */\n  \n  small {\n    font-size: 80%;\n  }\n  \n  /**\n   * Prevent `sub` and `sup` elements from affecting the line height in\n   * all browsers.\n   */\n  \n  sub,\n  sup {\n    font-size: 75%;\n    line-height: 0;\n    position: relative;\n    vertical-align: baseline;\n  }\n  \n  sub {\n    bottom: -0.25em;\n  }\n  \n  sup {\n    top: -0.5em;\n  }\n  \n  /* Embedded content\n     ========================================================================== */\n  \n  /**\n   * Remove the border on images inside links in IE 10.\n   */\n  \n  img {\n    border-style: none;\n  }\n  \n  /* Forms\n     ========================================================================== */\n  \n  /**\n   * 1. Change the font styles in all browsers.\n   * 2. Remove the margin in Firefox and Safari.\n   */\n  \n  button,\n  input,\n  optgroup,\n  select,\n  textarea {\n    font-family: inherit; /* 1 */\n    font-size: 100%; /* 1 */\n    line-height: 1.15; /* 1 */\n    margin: 0; /* 2 */\n  }\n  \n  /**\n   * Show the overflow in IE.\n   * 1. Show the overflow in Edge.\n   */\n  \n  button,\n  input { /* 1 */\n    overflow: visible;\n  }\n  \n  /**\n   * Remove the inheritance of text transform in Edge, Firefox, and IE.\n   * 1. Remove the inheritance of text transform in Firefox.\n   */\n  \n  button,\n  select { /* 1 */\n    text-transform: none;\n  }\n  \n  /**\n   * Correct the inability to style clickable types in iOS and Safari.\n   */\n  \n  button,\n  [type=\"button\"],\n  [type=\"reset\"],\n  [type=\"submit\"] {\n    -webkit-appearance: button;\n  }\n  \n  /**\n   * Remove the inner border and padding in Firefox.\n   */\n  \n  button::-moz-focus-inner,\n  [type=\"button\"]::-moz-focus-inner,\n  [type=\"reset\"]::-moz-focus-inner,\n  [type=\"submit\"]::-moz-focus-inner {\n    border-style: none;\n    padding: 0;\n  }\n  \n  /**\n   * Restore the focus styles unset by the previous rule.\n   */\n  \n  button:-moz-focusring,\n  [type=\"button\"]:-moz-focusring,\n  [type=\"reset\"]:-moz-focusring,\n  [type=\"submit\"]:-moz-focusring {\n    outline: 1px dotted ButtonText;\n  }\n  \n  /**\n   * Correct the padding in Firefox.\n   */\n  \n  fieldset {\n    padding: 0.35em 0.75em 0.625em;\n  }\n  \n  /**\n   * 1. Correct the text wrapping in Edge and IE.\n   * 2. Correct the color inheritance from `fieldset` elements in IE.\n   * 3. Remove the padding so developers are not caught out when they zero out\n   *    `fieldset` elements in all browsers.\n   */\n  \n  legend {\n    box-sizing: border-box; /* 1 */\n    color: inherit; /* 2 */\n    display: table; /* 1 */\n    max-width: 100%; /* 1 */\n    padding: 0; /* 3 */\n    white-space: normal; /* 1 */\n  }\n  \n  /**\n   * Add the correct vertical alignment in Chrome, Firefox, and Opera.\n   */\n  \n  progress {\n    vertical-align: baseline;\n  }\n  \n  /**\n   * Remove the default vertical scrollbar in IE 10+.\n   */\n  \n  textarea {\n    overflow: auto;\n  }\n  \n  /**\n   * 1. Add the correct box sizing in IE 10.\n   * 2. Remove the padding in IE 10.\n   */\n  \n  [type=\"checkbox\"],\n  [type=\"radio\"] {\n    box-sizing: border-box; /* 1 */\n    padding: 0; /* 2 */\n  }\n  \n  /**\n   * Correct the cursor style of increment and decrement buttons in Chrome.\n   */\n  \n  [type=\"number\"]::-webkit-inner-spin-button,\n  [type=\"number\"]::-webkit-outer-spin-button {\n    height: auto;\n  }\n  \n  /**\n   * 1. Correct the odd appearance in Chrome and Safari.\n   * 2. Correct the outline style in Safari.\n   */\n  \n  [type=\"search\"] {\n    -webkit-appearance: textfield; /* 1 */\n    outline-offset: -2px; /* 2 */\n  }\n  \n  /**\n   * Remove the inner padding in Chrome and Safari on macOS.\n   */\n  \n  [type=\"search\"]::-webkit-search-decoration {\n    -webkit-appearance: none;\n  }\n  \n  /**\n   * 1. Correct the inability to style clickable types in iOS and Safari.\n   * 2. Change font properties to `inherit` in Safari.\n   */\n  \n  ::-webkit-file-upload-button {\n    -webkit-appearance: button; /* 1 */\n    font: inherit; /* 2 */\n  }\n  \n  /* Interactive\n     ========================================================================== */\n  \n  /*\n   * Add the correct display in Edge, IE 10+, and Firefox.\n   */\n  \n  details {\n    display: block;\n  }\n  \n  /*\n   * Add the correct display in all browsers.\n   */\n  \n  summary {\n    display: list-item;\n  }\n  \n  /* Misc\n     ========================================================================== */\n  \n  /**\n   * Add the correct display in IE 10+.\n   */\n  \n  template {\n    display: none;\n  }\n  \n  /**\n   * Add the correct display in IE 10.\n   */\n  \n  [hidden] {\n    display: none;\n  }"
  },
  {
    "path": "src/DataIngestor/DataIngestor.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n    <TargetFramework>net8.0</TargetFramework>\n    <ImplicitUsings>enable</ImplicitUsings>\n    <Nullable>enable</Nullable>\n    <RootNamespace>eShopSupport.DataIngestor</RootNamespace>\n    <StartArguments>$(SolutionDir)\\seeddata\\DataGenerator\\output</StartArguments>\n    <NoWarn>$(NoWarn);SKEXP0001;SKEXP0020;SKEXP0050</NoWarn>\n    <IsAspireHost>true</IsAspireHost>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\Backend\\Backend.csproj\" IsAspireProjectResource=\"false\" />\n    <ProjectReference Include=\"..\\Evaluator\\Evaluator.csproj\" IsAspireProjectResource=\"false\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Aspire.Hosting.AppHost\" />\n    <PackageReference Include=\"Microsoft.Extensions.Http.Resilience\" />\n    <PackageReference Include=\"Microsoft.SemanticKernel.Core\" />\n    <PackageReference Include=\"PdfPig\" />\n    <PackageReference Include=\"SmartComponents.LocalEmbeddings\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/DataIngestor/EvalQuestionIngestor.cs",
    "content": "﻿using System.Text.Json;\nusing eShopSupport.Evaluator;\n\npublic class EvalQuestionIngestor\n{\n    public async Task RunAsync(string generatedDataPath, string outputDir)\n    {\n        Console.WriteLine(\"Ingesting evaluation questions...\");\n\n        var questions = new List<EvalQuestion>();\n        var questionsSourceDir = Path.Combine(generatedDataPath, \"evalquestions\");\n        var inputOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web);\n        foreach (var filename in Directory.GetFiles(questionsSourceDir, \"*.json\"))\n        {\n            var generated = await JsonSerializer.DeserializeAsync<EvalQuestion>(File.OpenRead(filename), inputOptions);\n            questions.Add(generated!);\n        }\n\n        var outputOptions = new JsonSerializerOptions { WriteIndented = true };\n        await File.WriteAllTextAsync(Path.Combine(outputDir, \"evalquestions.json\"), JsonSerializer.Serialize(questions.OrderBy(q => q.QuestionId), outputOptions));\n        Console.WriteLine($\"Wrote {questions.Count} evaluation questions\");\n    }\n}\n"
  },
  {
    "path": "src/DataIngestor/ManualIngestor.cs",
    "content": "﻿using System.Runtime.InteropServices;\nusing System.Text.Json;\nusing eShopSupport.Backend.Data;\nusing Microsoft.SemanticKernel.Text;\nusing SmartComponents.LocalEmbeddings.SemanticKernel;\nusing UglyToad.PdfPig;\nusing UglyToad.PdfPig.Content;\nusing UglyToad.PdfPig.DocumentLayoutAnalysis.PageSegmenter;\nusing UglyToad.PdfPig.DocumentLayoutAnalysis.WordExtractor;\n\npublic class ManualIngestor\n{\n    public async Task RunAsync(string sourceDir, string outputDir)\n    {\n        Console.WriteLine(\"Ingesting manuals...\");\n\n        // Prepare\n        var manualsSourceDir = Path.Combine(sourceDir, \"manuals\", \"pdf\");\n        using var embeddingGenerator = new LocalTextEmbeddingGenerationService();\n        var chunks = new List<ManualChunk>();\n        var paragraphIndex = 0;\n\n        // Loop over each PDF file\n        foreach (var file in Directory.GetFiles(manualsSourceDir, \"*.pdf\"))\n        {\n            Console.WriteLine($\"Generating chunks for {file}...\");\n            var docId = int.Parse(Path.GetFileNameWithoutExtension(file));\n\n            // Loop over each page in it\n            using var pdf = PdfDocument.Open(file);\n            foreach (var page in pdf.GetPages())\n            {\n                // [1] Parse (PDF page -> string)\n                var pageText = GetPageText(page);\n\n                // [2] Chunk (split into shorter strings on natural boundaries)\n                var paragraphs = TextChunker.SplitPlainTextParagraphs([pageText], 200);\n\n                // [3] Embed (map into semantic space)\n                var paragraphsWithEmbeddings = paragraphs.Zip(await embeddingGenerator.GenerateEmbeddingsAsync(paragraphs));\n\n                // [4] Save\n                chunks.AddRange(paragraphsWithEmbeddings.Select(p => new ManualChunk\n                {\n                    ProductId = docId,\n                    PageNumber = page.Number,\n                    ChunkId = ++paragraphIndex,\n                    Text = p.First,\n                    Embedding = MemoryMarshal.AsBytes(p.Second.Span).ToArray()\n                }));\n            }\n        }\n\n        var outputOptions = new JsonSerializerOptions { WriteIndented = true };\n        await File.WriteAllTextAsync(Path.Combine(outputDir, \"manual-chunks.json\"), JsonSerializer.Serialize(chunks, outputOptions));\n        Console.WriteLine($\"Wrote {chunks.Count} manual chunks\");\n    }\n\n    private static string GetPageText(Page pdfPage)\n    {\n        var letters = pdfPage.Letters;\n        var words = NearestNeighbourWordExtractor.Instance.GetWords(letters);\n        var textBlocks = DocstrumBoundingBoxes.Instance.GetBlocks(words);\n        return string.Join(Environment.NewLine + Environment.NewLine,\n            textBlocks.Select(t => t.Text.ReplaceLineEndings(\" \")));\n    }\n}\n"
  },
  {
    "path": "src/DataIngestor/ManualZipIngestor.cs",
    "content": "﻿using System.IO.Compression;\n\npublic class ManualZipIngestor\n{\n    public Task RunAsync(string generatedDataPath, string outputDir)\n    {\n        Console.WriteLine(\"Compressing manuals...\");\n\n        var manualsSourceDir = Path.Combine(generatedDataPath, \"manuals\", \"pdf\");\n        var manualsZipPath = Path.Combine(outputDir, \"manuals.zip\");\n        File.Delete(manualsZipPath);\n        ZipFile.CreateFromDirectory(manualsSourceDir, manualsZipPath);\n        return Task.CompletedTask;\n    }\n}\n"
  },
  {
    "path": "src/DataIngestor/PathUtils.cs",
    "content": "﻿public static class PathUtils\n{\n    public static string FindAncestorDirectoryContaining(string pattern)\n    {\n        var currentDir = Directory.GetCurrentDirectory();\n        while (currentDir != null)\n        {\n            if (Directory.GetFiles(currentDir, pattern).Any())\n            {\n                return currentDir!;\n            }\n            currentDir = Directory.GetParent(currentDir)?.FullName;\n        }\n\n        throw new FileNotFoundException($\"Could not find a directory containing {pattern}\");\n    }\n}\n"
  },
  {
    "path": "src/DataIngestor/ProductCategoryIngestor.cs",
    "content": "﻿using System.Runtime.InteropServices;\nusing System.Text.Json;\nusing eShopSupport.Backend.Data;\nusing Microsoft.SemanticKernel.Embeddings;\nusing SmartComponents.LocalEmbeddings.SemanticKernel;\n\nclass ProductCategoryIngestor\n{\n    public async Task RunAsync(string generatedDataPath, string outputDir)\n    {\n        Console.WriteLine(\"Ingesting product categories...\");\n\n        var categories = new List<ProductCategory>();\n        var categoriesSourceDir = Path.Combine(generatedDataPath, \"categories\");\n        var inputOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web);\n        using var embeddingGenerator = new LocalTextEmbeddingGenerationService();\n        foreach (var filename in Directory.GetFiles(categoriesSourceDir, \"*.json\"))\n        {\n            var generated = (await JsonSerializer.DeserializeAsync<GeneratedCategory>(File.OpenRead(filename), inputOptions))!;\n            categories.Add(new ProductCategory\n            {\n                CategoryId = generated.CategoryId,\n                Name = generated.Name,\n                NameEmbeddingBase64 = ToBase64(await embeddingGenerator.GenerateEmbeddingAsync(generated.Name)),\n            });\n        }\n\n        var outputOptions = new JsonSerializerOptions { WriteIndented = true };\n        await File.WriteAllTextAsync(Path.Combine(outputDir, \"categories.json\"), JsonSerializer.Serialize(categories, outputOptions));\n        Console.WriteLine($\"Wrote {categories.Count} categories\");\n    }\n\n    private static string ToBase64(ReadOnlyMemory<float> embedding)\n        => Convert.ToBase64String(MemoryMarshal.AsBytes(embedding.Span));\n\n    internal record GeneratedCategory(int CategoryId, string Name);\n}\n"
  },
  {
    "path": "src/DataIngestor/ProductIngestor.cs",
    "content": "﻿using System.Text.Json;\nusing eShopSupport.Backend.Data;\nusing Microsoft.SemanticKernel.Embeddings;\nusing SmartComponents.LocalEmbeddings.SemanticKernel;\n\nclass ProductIngestor\n{\n    public async Task RunAsync(string generatedDataPath, string outputDir)\n    {\n        Console.WriteLine(\"Ingesting products...\");\n\n        var products = new List<Product>();\n        var productsSourceDir = Path.Combine(generatedDataPath, \"products\");\n        var inputOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web);\n        using var embeddingGenerator = new LocalTextEmbeddingGenerationService();\n        foreach (var filename in Directory.GetFiles(productsSourceDir, \"*.json\"))\n        {\n            var generated = (await JsonSerializer.DeserializeAsync<GeneratedProduct>(File.OpenRead(filename), inputOptions))!;\n            products.Add(new Product\n            {\n                ProductId = generated.ProductId,\n                CategoryId = generated.CategoryId,\n                Brand = generated.Brand,\n                Model = generated.Model,\n                Description = generated.Description,\n                Price = generated.Price,\n                NameEmbedding = await embeddingGenerator.GenerateEmbeddingAsync($\"{generated.Model}, {generated.Brand}\"),\n            });\n        }\n\n        var outputOptions = new JsonSerializerOptions { WriteIndented = true };\n        await File.WriteAllTextAsync(Path.Combine(outputDir, \"products.json\"), JsonSerializer.Serialize(products, outputOptions));\n        Console.WriteLine($\"Wrote {products.Count} products\");\n    }\n\n    internal record GeneratedProduct(int ProductId, int CategoryId, string Brand, string Model, string Description, decimal Price);\n}\n"
  },
  {
    "path": "src/DataIngestor/Program.cs",
    "content": "﻿// This data ingestion pipeline works with the output from the DataGenerator project.\n//\n// The reason for separating data generation from ingestion is:\n//\n//  - For realism. In real-world scenarios, you will be taking data from external sources,\n//    such as existing business data or documents provided by product manufacturers, and need\n//    to ingest that data into your system. You must only ingest the data you will really have\n//    (e.g., final PDFs) and not artificially-available data such as the intermediate JSON\n//    files generated by the DataGenerator.\n//\n//  - For evaluation of different strategies. There are many possible ways to represent the\n//    ingested data (for example, how to chunk and embed text), and we want to be able to\n//    try out different ingestion strategies and then numerally evaluate the quality of the\n//    end-to-end system.\n//\n// In this case the data ingestor does *not* write directly to DBs, but instead emits .json\n// files that the Backend project can quickly import. This is because data ingestion can be\n// a lengthy process, requiring dependencies, and we want each person trying out this sample\n// to be able to run the app without going through the ingestion process first.\n// In real-world cases that's likely useful too, since you can't normally write directly to\n// production DBs.\n\nvar generatedDataPath = args.Length > 0 ? args[0] : null;\nif (string.IsNullOrEmpty(generatedDataPath))\n{\n    Console.WriteLine(\"Usage: DataIngestor [path_to_generated_data]\");\n    return;\n}\n\nif (!Directory.Exists(generatedDataPath))\n{\n    Console.WriteLine($\"Directory not found: {generatedDataPath}. You may need to run the data generator first.\");\n    return;\n}\n\nvar solutionDir = PathUtils.FindAncestorDirectoryContaining(\"*.sln\");\nvar outputDir = Path.Combine(solutionDir, \"seeddata\", \"dev\");\nDirectory.CreateDirectory(outputDir);\n\nawait new TicketIngestor().RunAsync(generatedDataPath, outputDir);\nawait new ProductCategoryIngestor().RunAsync(generatedDataPath, outputDir);\nawait new ProductIngestor().RunAsync(generatedDataPath, outputDir);\nawait new EvalQuestionIngestor().RunAsync(generatedDataPath, outputDir);\nawait new ManualIngestor().RunAsync(generatedDataPath, outputDir);\nawait new ManualZipIngestor().RunAsync(generatedDataPath, outputDir);\n"
  },
  {
    "path": "src/DataIngestor/TicketIngestor.cs",
    "content": "﻿using System.Collections.Concurrent;\nusing System.Text.Json;\nusing eShopSupport.Backend.Data;\nusing eShopSupport.ServiceDefaults.Clients.Backend;\n\nclass TicketIngestor\n{\n    public async Task RunAsync(string generatedDataPath, string outputDir)\n    {\n        Console.WriteLine(\"Ingesting tickets and customers...\");\n\n        var tickets = new List<Ticket>();\n        var customersByName = new ConcurrentDictionary<string, Customer>();\n        var ticketsSourceDir = Path.Combine(generatedDataPath, \"tickets\", \"threads\");\n        var inputOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web);\n        var messageId = 0;\n        var customerId = 0;\n        foreach (var filename in Directory.GetFiles(ticketsSourceDir, \"*.json\"))\n        {\n            // TODO: Consider simplifying by ensuring the generated data is already in exactly the right form\n            var generated = (await JsonSerializer.DeserializeAsync<GeneratedTicket>(File.OpenRead(filename), inputOptions))!;\n            var customer = customersByName.GetOrAdd(generated.CustomerFullName, name => new Customer { FullName = name, CustomerId = ++customerId });\n\n            tickets.Add(new Ticket\n            {\n                TicketId = generated.TicketId,\n                ProductId = generated.ProductId,\n                TicketType = Enum.Parse<TicketType>(generated.TicketType),\n                TicketStatus = Enum.Parse<TicketStatus>(generated.TicketStatus),\n                CustomerId = customer.CustomerId,\n                Customer = customer,\n                ShortSummary = generated.ShortSummary,\n                LongSummary = generated.LongSummary,\n                CustomerSatisfaction = generated.CustomerSatisfaction,\n                Messages = generated.Messages.Select(generatedMessage => new Message\n                {\n                    MessageId = ++messageId,\n                    IsCustomerMessage = generatedMessage.AuthorRole == 0,\n                    Text = generatedMessage.Text\n                }).ToList()\n            });\n        }\n\n        var outputOptions = new JsonSerializerOptions { WriteIndented = true };\n        await File.WriteAllTextAsync(Path.Combine(outputDir, \"tickets.json\"), JsonSerializer.Serialize(tickets.OrderBy(t => t.TicketId), outputOptions));\n        Console.WriteLine($\"Wrote {tickets.Count} tickets\");\n\n        await File.WriteAllTextAsync(Path.Combine(outputDir, \"customers.json\"), JsonSerializer.Serialize(customersByName.Values, outputOptions));\n        Console.WriteLine($\"Wrote {customersByName.Count} customers\");\n    }\n\n    internal record GeneratedTicket(int TicketId, int ProductId, string TicketType, string TicketStatus, string CustomerFullName, string ShortSummary, string LongSummary, int? CustomerSatisfaction, List<GeneratedMessage> Messages);\n    internal record GeneratedMessage(int MessageId, int AuthorRole, string Text);\n}\n"
  },
  {
    "path": "src/Evaluator/.gitignore",
    "content": "appsettings.Local.json\n"
  },
  {
    "path": "src/Evaluator/EvalQuestion.cs",
    "content": "﻿namespace eShopSupport.Evaluator;\n\npublic class EvalQuestion\n{\n    public int QuestionId { get; set; }\n\n    public int? ProductId { get; set; }\n\n    public required string Question { get; set; }\n\n    public required string Answer { get; set; }\n}\n"
  },
  {
    "path": "src/Evaluator/Evaluator.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n    <TargetFramework>net8.0</TargetFramework>\n    <ImplicitUsings>enable</ImplicitUsings>\n    <Nullable>enable</Nullable>\n    <RootNamespace>eShopSupport.Evaluator</RootNamespace>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\Backend\\Backend.csproj\" />\n    <ProjectReference Include=\"..\\ServiceDefaults\\ServiceDefaults.csproj\" />\n\n    <AssemblyAttribute Include=\"System.Reflection.AssemblyMetadataAttribute\">\n      <_Parameter1>EvalQuestionsJsonPath</_Parameter1>\n      <_Parameter2>$(SolutionDir)seeddata\\dev\\evalquestions.json</_Parameter2>\n    </AssemblyAttribute>\n  </ItemGroup>\n\n  <ItemGroup>\n    <None Update=\"appsettings.json\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n    <None Update=\"appsettings.Local.json\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/Evaluator/Program.cs",
    "content": "﻿using System.ClientModel;\nusing System.Data.Common;\nusing System.Reflection;\nusing System.Text;\nusing System.Text.Json;\nusing Azure.AI.OpenAI;\nusing eShopSupport.Evaluator;\nusing eShopSupport.ServiceDefaults.Clients.Backend;\nusing Microsoft.Extensions.AI;\nusing Microsoft.Extensions.Configuration;\n\n// Comparing models:\n//\n// GPT 4o: After 100 questions: average score = 0.800, average duration = 9005.543ms\n// GPT 3.5 Turbo: After 200 questions: average score = 0.733, average duration = 3450.547ms\n// Mistral 7B (Ollama): After 100 questions: average score = 0.547, average duration = 25603.365ms\n//\n// ---\n//\n// Comparing prompts:\n//\n// Effect of adding \"If this is a question about the product, you should ALWAYS search the manual.\"\n// to the prompt:\n//\n// Without: After 200 questions: average score = 0.615, average duration = 2092.407ms\n// With:    After 200 questions: average score = 0.775, average duration = 2670.874ms\n\nvar assistantAnsweringSemaphore = new SemaphoreSlim(/* parallelism */ 3);\nvar backend = await DevToolBackendClient.GetDevToolStaffBackendClientAsync(\n    identityServerHttpClient: new HttpClient { BaseAddress = new Uri(\"https://localhost:7275/\") },\n    backendHttpClient: new HttpClient { BaseAddress = new Uri(\"https://localhost:7223/\") });\nvar chatCompletion = GetChatCompletionService(\"chatcompletion\");\nvar questions = LoadEvaluationQuestions().OrderBy(q => q.QuestionId);\nusing var logFile = File.Open(\"log.txt\", FileMode.Create, FileAccess.Write, FileShare.Read);\nusing var log = new StreamWriter(logFile);\n\nvar questionBatches = questions.Chunk(5);\nvar scoringParallelism = 4;\nvar allScores = new List<double>();\nvar allDurations = new List<TimeSpan>();\nawait Parallel.ForEachAsync(questionBatches, new ParallelOptions { MaxDegreeOfParallelism = scoringParallelism }, async (batch, cancellationToken) =>\n{\n    var assistantAnswers = await Task.WhenAll(batch.Select(GetAssistantAnswerAsync));\n    var scores = await ScoreAnswersAsync(batch.Zip(assistantAnswers.Select(a => a.Answer)).ToList());\n    foreach (var (question, assistantAnswer, score) in batch.Zip(assistantAnswers, scores))\n    {\n        lock (log)\n        {\n            log.WriteLine($\"Question ID: {question.QuestionId}\");\n            log.WriteLine($\"Question: {question.Question}\");\n            log.WriteLine($\"True answer: {question.Answer}\");\n            log.WriteLine($\"Assistant answer: {assistantAnswer.Answer}\");\n            log.WriteLine($\"Assistant duration: {assistantAnswer.Duration}\");\n            log.WriteLine($\"Score: {score.Score}\");\n            log.WriteLine($\"Justification: {score.Justification}\");\n            log.WriteLine();\n            log.Flush();\n            if (score.Score.HasValue)\n            {\n                allScores.Add(score.Score.Value);\n                allDurations.Add(assistantAnswer.Duration);\n            }\n        }\n    }\n\n    Console.WriteLine($\"After {allScores.Count} questions: average score = {allScores.Average():F3}, average duration = {allDurations.Select(d => d.TotalMilliseconds).Average():F3}ms\");\n});\n\nasync Task<(double? Score, string Justification)[]> ScoreAnswersAsync(IReadOnlyCollection<(EvalQuestion Question, string AssistantAnswer)> questionAnswerPairs)\n{\n    var rangeText = $\"questions {questionAnswerPairs.Min(p => p.Question.QuestionId)} to {questionAnswerPairs.Max(p => p.Question.QuestionId)}\";\n    Console.WriteLine($\"Scoring answers to {rangeText}...\");\n    var formattedQuestionAnswerPairs = questionAnswerPairs.Select((pair, index) => \n        $$\"\"\"\n            <question index=\"{{index}}\">\n                <text>{{pair.Question.Question}}</text>\n                <truth>{{pair.Question.Answer}}</truth>\n                <assistantAnswer>{{pair.AssistantAnswer}}</assistantAnswer>\n            </question>\n        \"\"\");\n\n    List<string> scoreWords = [\"Awful\", \"Poor\", \"Good\", \"Perfect\"];\n\n    var prompt = $$\"\"\"\n        There is an AI assistant that answers questions about products sold by an online retailer. The questions\n        may be asked by customers or by customer support agents.\n\n        You are evaluating the quality of an AI assistant's response to several questions. Here are the\n        questions, the desired true answers, and the answers given by the AI system:\n\n        <questions>\n            {{string.Join(\"\\n\", formattedQuestionAnswerPairs)}}\n        </questions>\n\n        Evaluate each of the assistant's answers separately by replying in this JSON format:\n\n        {\n            \"scores\": [\n                { \"index\": 0, \"descriptionOfQuality\": string, \"scoreLabel\": string },\n                { \"index\": 1, \"descriptionOfQuality\": string, \"scoreLabel\": string },\n                ... etc ...\n            ]\n        ]\n\n        Score only based on whether the assistant's answer is true and answers the question. As long as the\n        answer covers the question and is consistent with the truth, it should score as perfect. There is\n        no penalty for giving extra on-topic information or advice. Only penalize for missing necessary facts\n        or being misleading.\n\n        The descriptionOfQuality should be up to 5 words summarizing to what extent the assistant answer\n        is correct and sufficient.\n\n        Based on descriptionOfQuality, the scoreLabel must be one of the following labels, from worst to best: {{string.Join(\", \", scoreWords)}}\n        Do not use any other words for scoreLabel. You may only pick one of those labels.\n        \"\"\";\n\n    var response = await chatCompletion.GetResponseAsync(prompt, new ChatOptions\n    {\n        ResponseFormat = ChatResponseFormat.Json,\n        Temperature = 0,\n        AdditionalProperties = new() { [\"seed\"] = 0 },\n    });\n    var responseJson = response.ToString();\n    var jsonOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web);\n    var parsedResponse = JsonSerializer.Deserialize<ScoringResponse>(responseJson, jsonOptions)!;\n    return parsedResponse.Scores.Select(s =>\n    {\n        var labelIndex = scoreWords.FindIndex(w => w.Equals(s.ScoreLabel, StringComparison.OrdinalIgnoreCase));\n        return (labelIndex < 0 ? (double?)null : ((double)labelIndex) / (scoreWords.Count - 1), s.DescriptionOfQuality);\n    }).ToArray();\n}\n\nstatic EvalQuestion[] LoadEvaluationQuestions()\n{\n    var questionDataPath = Assembly.GetExecutingAssembly()\n        .GetCustomAttributes<AssemblyMetadataAttribute>()\n        .Single(a => a.Key == \"EvalQuestionsJsonPath\").Value!;\n    if (!File.Exists(questionDataPath))\n    {\n        throw new FileNotFoundException(\"Questions not found. Ensure the data ingestor has run.\", questionDataPath);\n    }\n    var questionsJson = File.ReadAllText(questionDataPath);\n    return JsonSerializer.Deserialize<EvalQuestion[]>(questionsJson)!;\n}\n\nasync Task<(string Answer, TimeSpan Duration)> GetAssistantAnswerAsync(EvalQuestion question)\n{\n    await assistantAnsweringSemaphore.WaitAsync();\n    var startTime = DateTime.Now;\n\n    try\n    {\n        Console.WriteLine($\"Asking question {question.QuestionId}...\");\n        var responseItems = backend.AssistantChatAsync(new AssistantChatRequest(\n            question.ProductId,\n            null,\n            null,\n            null,\n            [new() { IsAssistant = true, Text = question.Question }]),\n            CancellationToken.None);\n        var answerBuilder = new StringBuilder();\n        await foreach (var item in responseItems)\n        {\n            if (item.Type == AssistantChatReplyItemType.AnswerChunk)\n            {\n                answerBuilder.Append(item.Text);\n            }\n        }\n\n        var duration = DateTime.Now - startTime;\n        var finalAnswer = answerBuilder.ToString();\n        Console.WriteLine($\"Received answer to question {question.QuestionId}\");\n        return (string.IsNullOrWhiteSpace(finalAnswer) ? \"No answer provided\" : finalAnswer, duration);\n    }\n    catch (Exception ex)\n    {\n        Console.WriteLine($\"Error on question {question.QuestionId}: {ex.Message}\");\n        return (\"SYSTEM ERROR\", DateTime.Now - startTime);\n    }\n    finally\n    {\n        assistantAnsweringSemaphore.Release();\n    }\n}\n\nstatic IChatClient GetChatCompletionService(string connectionStringName)\n{\n    var config = new ConfigurationManager();\n    config.AddJsonFile(\"appsettings.json\");\n    config.AddJsonFile(\"appsettings.Local.json\", optional: true);\n\n    var connectionStringBuilder = new DbConnectionStringBuilder();\n    var connectionString = config.GetConnectionString(connectionStringName);\n    if (string.IsNullOrEmpty(connectionString))\n    {\n        throw new InvalidOperationException($\"Missing connection string {connectionStringName}\");\n    }\n\n    connectionStringBuilder.ConnectionString = connectionString;\n\n    var deployment = connectionStringBuilder.TryGetValue(\"Deployment\", out var deploymentValue) ? (string)deploymentValue : throw new InvalidOperationException($\"Connection string {connectionStringName} is missing 'Deployment'\");\n    var endpoint = connectionStringBuilder.TryGetValue(\"Endpoint\", out var endpointValue) ? (string)endpointValue : throw new InvalidOperationException($\"Connection string {connectionStringName} is missing 'Endpoint'\");\n    var key = connectionStringBuilder.TryGetValue(\"Key\", out var keyValue) ? (string)keyValue : throw new InvalidOperationException($\"Connection string {connectionStringName} is missing 'Key'\");\n\n    return new AzureOpenAIClient(new Uri(endpoint), new ApiKeyCredential(key)).GetChatClient(deployment).AsIChatClient();\n}\n\nrecord ScoringResponse(AnswerScore[] Scores);\nrecord AnswerScore(int Index, string ScoreLabel, string DescriptionOfQuality);\n"
  },
  {
    "path": "src/Evaluator/appsettings.json",
    "content": "{\n  // REMEMBER NOT TO COMMIT YOUR API KEYS TO SOURCE CONTROL\n  // To reduce the risk, copy this file as appsettings.Local.json and make your changes there,\n  // since that file overrides anything configured here and will be ignored by Git.\n  \"ConnectionStrings\": {\n    //\"chatcompletion\": \"Endpoint=https://TODO.openai.azure.com/;Key=TODO;Deployment=TODO\"\n  }\n}\n"
  },
  {
    "path": "src/IdentityServer/.gitignore",
    "content": "keys/\n"
  },
  {
    "path": "src/IdentityServer/Config.cs",
    "content": "﻿using Duende.IdentityServer;\nusing Duende.IdentityServer.Models;\n\nnamespace IdentityServer;\n\npublic static class Config\n{\n    public static IEnumerable<IdentityResource> IdentityResources { get; } =\n    [\n        new IdentityResources.OpenId(),\n        new IdentityResources.Profile(),\n        new IdentityResource(\"role\", [\"role\"]),\n    ];\n\n    public static IEnumerable<ApiScope> ApiScopes { get; } =\n    [\n        new ApiScope(name: \"staff-api\", displayName: \"Staff API\", [\"role\"])\n    ];\n\n    public static IEnumerable<Client> GetClients(IConfiguration configuration) =>\n    [\n        new Client\n        {\n            // This is used by E2E test and evaluation\n            ClientId = \"dev-and-test-tools\",\n            ClientSecrets = { new Secret(\"dev-and-test-tools-secret\".Sha256()) },\n            AllowedGrantTypes = GrantTypes.ClientCredentials,\n            AllowedScopes = { \"staff-api\" },\n            ClientClaimsPrefix = null,\n            Claims = { new(\"role\", \"staff\") }\n        },\n        new Client\n        {\n            ClientId = \"customer-webui\",\n            ClientSecrets = { new Secret(\"customer-webui-secret\".Sha256()) },\n\n            AllowedGrantTypes = GrantTypes.Code,\n\n            RedirectUris = { $\"{configuration[\"CustomerWebUIEndpoint\"]}/signin-oidc\" },\n            PostLogoutRedirectUris = { $\"{configuration[\"CustomerWebUIEndpoint\"]}/signout-callback-oidc\" },\n\n            AllowedScopes =\n            {\n                IdentityServerConstants.StandardScopes.OpenId,\n                IdentityServerConstants.StandardScopes.Profile,\n            },\n        },\n        new Client\n        {\n            ClientId = \"staff-webui\",\n            ClientSecrets = { new Secret(\"staff-webui-secret\".Sha256()) },\n\n            AllowedGrantTypes = GrantTypes.Code,\n\n            RedirectUris = { $\"{configuration[\"StaffWebUIEndpoint\"]}/signin-oidc\" },\n            PostLogoutRedirectUris = { $\"{configuration[\"StaffWebUIEndpoint\"]}/signout-callback-oidc\" },\n\n            AllowedScopes =\n            {\n                IdentityServerConstants.StandardScopes.OpenId,\n                IdentityServerConstants.StandardScopes.Profile,\n                \"staff-api\",\n                \"role\",\n            },\n        }\n    ];\n}\n"
  },
  {
    "path": "src/IdentityServer/HostingExtensions.cs",
    "content": "﻿using Serilog;\n\nnamespace IdentityServer;\n\ninternal static class HostingExtensions\n{\n    public static WebApplication ConfigureServices(this WebApplicationBuilder builder)\n    {\n        builder.Services.AddRazorPages();\n\n        builder.Services.AddIdentityServer(options =>\n            {\n                // https://docs.duendesoftware.com/identityserver/v6/fundamentals/resources/api_scopes#authorization-based-on-scopes\n                options.EmitStaticAudienceClaim = true;\n            })\n            .AddInMemoryIdentityResources(Config.IdentityResources)\n            .AddInMemoryApiScopes(Config.ApiScopes)\n            .AddInMemoryClients(Config.GetClients(builder.Configuration))\n#if DEBUG\n            .AddTestUsers(TestUsers.Users)\n#endif\n            ;\n\n\n        return builder.Build();\n    }\n    \n    public static WebApplication ConfigurePipeline(this WebApplication app)\n    { \n        app.UseSerilogRequestLogging();\n    \n        if (app.Environment.IsDevelopment())\n        {\n            app.UseDeveloperExceptionPage();\n        }\n\n        app.UseStaticFiles();\n        app.UseRouting();\n            \n        app.UseIdentityServer();\n\n        app.UseAuthorization();\n        app.MapRazorPages().RequireAuthorization();\n\n        return app;\n    }\n}\n"
  },
  {
    "path": "src/IdentityServer/IdentityServer.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n  <PropertyGroup>\n    <TargetFramework>net8.0</TargetFramework>\n    <ImplicitUsings>enable</ImplicitUsings>\n    <Nullable>enable</Nullable>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Duende.IdentityServer\" />\n    <PackageReference Include=\"Serilog.AspNetCore\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\ServiceDefaults\\ServiceDefaults.csproj\" />\n  </ItemGroup>\n</Project>\n"
  },
  {
    "path": "src/IdentityServer/Pages/Account/AccessDenied.cshtml",
    "content": "@page\n@model IdentityServer.Pages.Account.AccessDeniedModel\n@{\n}\n<div class=\"row\">\n    <div class=\"col\">\n        <h1>Access Denied</h1>\n        <p>You do not have permission to access that resource.</p>\n    </div>\n</div>"
  },
  {
    "path": "src/IdentityServer/Pages/Account/AccessDenied.cshtml.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing Microsoft.AspNetCore.Mvc.RazorPages;\n\nnamespace IdentityServer.Pages.Account;\n\npublic class AccessDeniedModel : PageModel\n{\n    public void OnGet()\n    {\n    }\n}\n"
  },
  {
    "path": "src/IdentityServer/Pages/Account/Create/Index.cshtml",
    "content": "@page\n@model IdentityServer.Pages.Create.Index\n\n<div class=\"login-page\">\n    <div class=\"lead\">\n        <h1>Create Account</h1>\n    </div>\n\n    <partial name=\"_ValidationSummary\" />\n\n    <div class=\"row\">\n\n        <div class=\"col-sm-6\">\n            <form asp-page=\"/Account/Create/Index\">\n                <input type=\"hidden\" asp-for=\"Input.ReturnUrl\" />\n\n                <div class=\"form-group\">\n                    <label asp-for=\"Input.Username\"></label>\n                    <input class=\"form-control\" placeholder=\"Username\" asp-for=\"Input.Username\" autofocus>\n                </div>\n                <div class=\"form-group\">\n                    <label asp-for=\"Input.Password\"></label>\n                    <input type=\"password\" class=\"form-control\" placeholder=\"Password\" asp-for=\"Input.Password\" autocomplete=\"off\">\n                </div>\n                <div class=\"form-group\">\n                    <label asp-for=\"Input.Name\"></label>\n                    <input type=\"text\" class=\"form-control\" placeholder=\"Name\" asp-for=\"Input.Name\">\n                </div>\n                <div class=\"form-group\">\n                    <label asp-for=\"Input.Email\"></label>\n                    <input type=\"email\" class=\"form-control\" placeholder=\"Email\" asp-for=\"Input.Email\" >\n                </div>\n\n                <button class=\"btn btn-primary\" name=\"Input.Button\" value=\"create\">Create</button>\n                <button class=\"btn btn-secondary\" name=\"Input.Button\" value=\"cancel\">Cancel</button>\n            </form>\n        </div>\n        \n    </div>\n</div>"
  },
  {
    "path": "src/IdentityServer/Pages/Account/Create/Index.cshtml.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing Duende.IdentityServer;\nusing Duende.IdentityServer.Models;\nusing Duende.IdentityServer.Services;\nusing Duende.IdentityServer.Test;\nusing Microsoft.AspNetCore.Authentication;\nusing Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.AspNetCore.Mvc.RazorPages;\n\nnamespace IdentityServer.Pages.Create;\n\n[SecurityHeaders]\n[AllowAnonymous]\npublic class Index : PageModel\n{\n    private readonly TestUserStore _users;\n    private readonly IIdentityServerInteractionService _interaction;\n\n    [BindProperty]\n    public InputModel Input { get; set; } = default!;\n\n    public Index(\n        IIdentityServerInteractionService interaction,\n        TestUserStore? users = null)\n    {\n        // this is where you would plug in your own custom identity management library (e.g. ASP.NET Identity)\n        _users = users ?? throw new InvalidOperationException(\"Please call 'AddTestUsers(TestUsers.Users)' on the IIdentityServerBuilder in Startup or remove the TestUserStore from the AccountController.\");\n            \n        _interaction = interaction;\n    }\n\n    public IActionResult OnGet(string? returnUrl)\n    {\n        Input = new InputModel { ReturnUrl = returnUrl };\n        return Page();\n    }\n        \n    public async Task<IActionResult> OnPost()\n    {\n        // check if we are in the context of an authorization request\n        var context = await _interaction.GetAuthorizationContextAsync(Input.ReturnUrl);\n\n        // the user clicked the \"cancel\" button\n        if (Input.Button != \"create\")\n        {\n            if (context != null)\n            {\n                // if the user cancels, send a result back into IdentityServer as if they \n                // denied the consent (even if this client does not require consent).\n                // this will send back an access denied OIDC error response to the client.\n                await _interaction.DenyAuthorizationAsync(context, AuthorizationError.AccessDenied);\n\n                // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null\n                if (context.IsNativeClient())\n                {\n                    // The client is native, so this change in how to\n                    // return the response is for better UX for the end user.\n                    return this.LoadingPage(Input.ReturnUrl);\n                }\n\n                return Redirect(Input.ReturnUrl ?? \"~/\");\n            }\n            else\n            {\n                // since we don't have a valid context, then we just go back to the home page\n                return Redirect(\"~/\");\n            }\n        }\n\n        if (_users.FindByUsername(Input.Username) != null)\n        {\n            ModelState.AddModelError(\"Input.Username\", \"Invalid username\");\n        }\n\n        if (ModelState.IsValid)\n        {\n            var user = _users.CreateUser(Input.Username, Input.Password, Input.Name, Input.Email);\n\n            // issue authentication cookie with subject ID and username\n            var isuser = new IdentityServerUser(user.SubjectId)\n            {\n                DisplayName = user.Username\n            };\n\n            await HttpContext.SignInAsync(isuser);\n\n            if (context != null)\n            {\n                if (context.IsNativeClient())\n                {\n                    // The client is native, so this change in how to\n                    // return the response is for better UX for the end user.\n                    return this.LoadingPage(Input.ReturnUrl);\n                }\n\n                // we can trust Input.ReturnUrl since GetAuthorizationContextAsync returned non-null\n                return Redirect(Input.ReturnUrl ?? \"~/\");\n            }\n\n            // request for a local page\n            if (Url.IsLocalUrl(Input.ReturnUrl))\n            {\n                return Redirect(Input.ReturnUrl);\n            }\n            else if (string.IsNullOrEmpty(Input.ReturnUrl))\n            {\n                return Redirect(\"~/\");\n            }\n            else\n            {\n                // user might have clicked on a malicious link - should be logged\n                throw new ArgumentException(\"invalid return URL\");\n            }\n        }\n\n        return Page();\n    }\n}\n"
  },
  {
    "path": "src/IdentityServer/Pages/Account/Create/InputModel.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing System.ComponentModel.DataAnnotations;\n\nnamespace IdentityServer.Pages.Create;\n\npublic class InputModel\n{\n    [Required]\n    public string? Username { get; set; }\n\n    [Required]\n    public string? Password { get; set; }\n\n    public string? Name { get; set; }\n    public string? Email { get; set; }\n\n    public string? ReturnUrl { get; set; }\n\n    public string? Button { get; set; }\n}"
  },
  {
    "path": "src/IdentityServer/Pages/Account/Login/Index.cshtml",
    "content": "@page\n@model IdentityServer.Pages.Login.Index\n\n<div class=\"login-page\">\n    <div class=\"lead\">\n        <h1>Login</h1>\n        <p>Choose how to login</p>\n    </div>\n\n    <partial name=\"_ValidationSummary\" />\n\n    <div class=\"row\">\n\n        @if (Model.View.EnableLocalLogin)\n        {\n            <div class=\"col-sm-6\">\n                <div class=\"card\">\n                    <div class=\"card-header\">\n                        <h2>Local Account</h2>\n                    </div>\n\n                    <div class=\"card-body\">\n                        <form asp-page=\"/Account/Login/Index\">\n                            <input type=\"hidden\" asp-for=\"Input.ReturnUrl\" />\n\n                            <div class=\"form-group\">\n                                <label asp-for=\"Input.Username\"></label>\n                                <input class=\"form-control\" placeholder=\"Username\" asp-for=\"Input.Username\" autofocus>\n                            </div>\n                            <div class=\"form-group\">\n                                <label asp-for=\"Input.Password\"></label>\n                                <input type=\"password\" class=\"form-control\" placeholder=\"Password\" asp-for=\"Input.Password\" autocomplete=\"off\">\n                            </div>\n                            \n                            @if (Model.View.AllowRememberLogin)\n                            {\n                                <div class=\"form-group\">\n                                    <div class=\"form-check\">\n                                        <input class=\"form-check-input\" asp-for=\"Input.RememberLogin\">\n                                        <label class=\"form-check-label\" asp-for=\"Input.RememberLogin\">\n                                            Remember My Login\n                                        </label>\n                                    </div>\n                                </div>\n                            }\n                            \n                            <button class=\"btn btn-primary\" name=\"Input.Button\" value=\"login\">Login</button>\n                            <button class=\"btn btn-secondary\" name=\"Input.Button\" value=\"cancel\">Cancel</button>\n                        </form>\n                        <div class=\"test-users\">\n                            Test users:\n                            <ul>\n                                <li>Public: alice/alice</li>\n                                <li>Staff: bob/bob</li>\n                            </ul>\n                        </div>\n                    </div>\n                </div>\n            </div>\n        }\n\n        @if (Model.View.VisibleExternalProviders.Any())\n        {\n            <div class=\"col-sm-6\">\n                <div class=\"card\">\n                    <div class=\"card-header\">\n                        <h2>External Account</h2>\n                    </div>\n                    <div class=\"card-body\">\n                        <ul class=\"list-inline\">\n                            @foreach (var provider in Model.View.VisibleExternalProviders)\n                            {\n                                <li class=\"list-inline-item\">\n                                    <a class=\"btn btn-secondary\"\n                                       asp-page=\"/ExternalLogin/Challenge\"\n                                       asp-route-scheme=\"@provider.AuthenticationScheme\"\n                                       asp-route-returnUrl=\"@Model.Input.ReturnUrl\">\n                                        @provider.DisplayName\n                                    </a>\n                                </li>\n                            }\n                        </ul>\n                    </div>\n                </div>\n            </div>\n        }\n\n        @if (!Model.View.EnableLocalLogin && !Model.View.VisibleExternalProviders.Any())\n        {\n            <div class=\"alert alert-warning\">\n                <strong>Invalid login request</strong>\n                There are no login schemes configured for this request.\n            </div>\n        }\n    </div>\n</div>"
  },
  {
    "path": "src/IdentityServer/Pages/Account/Login/Index.cshtml.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing Duende.IdentityServer;\nusing Duende.IdentityServer.Events;\nusing Duende.IdentityServer.Models;\nusing Duende.IdentityServer.Services;\nusing Duende.IdentityServer.Stores;\nusing Duende.IdentityServer.Test;\nusing Microsoft.AspNetCore.Authentication;\nusing Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.AspNetCore.Mvc.RazorPages;\n\nnamespace IdentityServer.Pages.Login;\n\n[SecurityHeaders]\n[AllowAnonymous]\npublic class Index : PageModel\n{\n    private readonly TestUserStore _users;\n    private readonly IIdentityServerInteractionService _interaction;\n    private readonly IEventService _events;\n    private readonly IAuthenticationSchemeProvider _schemeProvider;\n    private readonly IIdentityProviderStore _identityProviderStore;\n\n    public ViewModel View { get; set; } = default!;\n\n    [BindProperty]\n    public InputModel Input { get; set; } = default!;\n\n    public Index(\n        IIdentityServerInteractionService interaction,\n        IAuthenticationSchemeProvider schemeProvider,\n        IIdentityProviderStore identityProviderStore,\n        IEventService events,\n        TestUserStore? users = null)\n    {\n        // this is where you would plug in your own custom identity management library (e.g. ASP.NET Identity)\n        _users = users ?? throw new InvalidOperationException(\"Please call 'AddTestUsers(TestUsers.Users)' on the IIdentityServerBuilder in Startup or remove the TestUserStore from the AccountController.\");\n            \n        _interaction = interaction;\n        _schemeProvider = schemeProvider;\n        _identityProviderStore = identityProviderStore;\n        _events = events;\n    }\n\n    public async Task<IActionResult> OnGet(string? returnUrl)\n    {\n        await BuildModelAsync(returnUrl);\n            \n        if (View.IsExternalLoginOnly)\n        {\n            // we only have one option for logging in and it's an external provider\n            return RedirectToPage(\"/ExternalLogin/Challenge\", new { scheme = View.ExternalLoginScheme, returnUrl });\n        }\n\n        return Page();\n    }\n        \n    public async Task<IActionResult> OnPost()\n    {\n        // check if we are in the context of an authorization request\n        var context = await _interaction.GetAuthorizationContextAsync(Input.ReturnUrl);\n\n        // the user clicked the \"cancel\" button\n        if (Input.Button != \"login\")\n        {\n            if (context != null)\n            {\n                // This \"can't happen\", because if the ReturnUrl was null, then the context would be null\n                ArgumentNullException.ThrowIfNull(Input.ReturnUrl, nameof(Input.ReturnUrl));\n\n                // if the user cancels, send a result back into IdentityServer as if they \n                // denied the consent (even if this client does not require consent).\n                // this will send back an access denied OIDC error response to the client.\n                await _interaction.DenyAuthorizationAsync(context, AuthorizationError.AccessDenied);\n\n                // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null\n                if (context.IsNativeClient())\n                {\n                    // The client is native, so this change in how to\n                    // return the response is for better UX for the end user.\n                    return this.LoadingPage(Input.ReturnUrl);\n                }\n\n                return Redirect(Input.ReturnUrl ?? \"~/\");\n            }\n            else\n            {\n                // since we don't have a valid context, then we just go back to the home page\n                return Redirect(\"~/\");\n            }\n        }\n\n        if (ModelState.IsValid)\n        {\n            // validate username/password against in-memory store\n            if (_users.ValidateCredentials(Input.Username, Input.Password))\n            {\n                var user = _users.FindByUsername(Input.Username);\n                await _events.RaiseAsync(new UserLoginSuccessEvent(user.Username, user.SubjectId, user.Username, clientId: context?.Client.ClientId));\n                Telemetry.Metrics.UserLogin(context?.Client.ClientId, IdentityServerConstants.LocalIdentityProvider);\n\n                // only set explicit expiration here if user chooses \"remember me\". \n                // otherwise we rely upon expiration configured in cookie middleware.\n                var props = new AuthenticationProperties();\n                if (LoginOptions.AllowRememberLogin && Input.RememberLogin)\n                {\n                    props.IsPersistent = true;\n                    props.ExpiresUtc = DateTimeOffset.UtcNow.Add(LoginOptions.RememberMeLoginDuration);\n                };\n\n                // issue authentication cookie with subject ID and username\n                var isuser = new IdentityServerUser(user.SubjectId)\n                {\n                    DisplayName = user.Username\n                };\n\n                await HttpContext.SignInAsync(isuser, props);\n\n                if (context != null)\n                {\n                    // This \"can't happen\", because if the ReturnUrl was null, then the context would be null\n                    ArgumentNullException.ThrowIfNull(Input.ReturnUrl, nameof(Input.ReturnUrl));\n\n                    if (context.IsNativeClient())\n                    {\n                        // The client is native, so this change in how to\n                        // return the response is for better UX for the end user.\n                        return this.LoadingPage(Input.ReturnUrl);\n                    }\n\n                    // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null\n                    return Redirect(Input.ReturnUrl ?? \"~/\");\n                }\n\n                // request for a local page\n                if (Url.IsLocalUrl(Input.ReturnUrl))\n                {\n                    return Redirect(Input.ReturnUrl);\n                }\n                else if (string.IsNullOrEmpty(Input.ReturnUrl))\n                {\n                    return Redirect(\"~/\");\n                }\n                else\n                {\n                    // user might have clicked on a malicious link - should be logged\n                    throw new ArgumentException(\"invalid return URL\");\n                }\n            }\n\n            const string error = \"invalid credentials\";\n            await _events.RaiseAsync(new UserLoginFailureEvent(Input.Username, error, clientId:context?.Client.ClientId));\n            Telemetry.Metrics.UserLoginFailure(context?.Client.ClientId, IdentityServerConstants.LocalIdentityProvider, error);\n            ModelState.AddModelError(string.Empty, LoginOptions.InvalidCredentialsErrorMessage);\n        }\n\n        // something went wrong, show form with error\n        await BuildModelAsync(Input.ReturnUrl);\n        return Page();\n    }\n\n    private async Task BuildModelAsync(string? returnUrl)\n    {\n        Input = new InputModel\n        {\n            ReturnUrl = returnUrl\n        };\n            \n        var context = await _interaction.GetAuthorizationContextAsync(returnUrl);\n        if (context?.IdP != null && await _schemeProvider.GetSchemeAsync(context.IdP) != null)\n        {\n            var local = context.IdP == Duende.IdentityServer.IdentityServerConstants.LocalIdentityProvider;\n\n            // this is meant to short circuit the UI and only trigger the one external IdP\n            View = new ViewModel\n            {\n                EnableLocalLogin = local,\n            };\n\n            Input.Username = context.LoginHint;\n\n            if (!local)\n            {\n                View.ExternalProviders = new[] { new ViewModel.ExternalProvider ( authenticationScheme: context.IdP ) };\n            }\n\n            return;\n        }\n\n        var schemes = await _schemeProvider.GetAllSchemesAsync();\n\n        var providers = schemes\n            .Where(x => x.DisplayName != null)\n            .Select(x => new ViewModel.ExternalProvider\n            (\n                authenticationScheme: x.Name,\n                displayName: x.DisplayName ?? x.Name\n            )).ToList();\n\n        var dynamicSchemes = (await _identityProviderStore.GetAllSchemeNamesAsync())\n            .Where(x => x.Enabled)\n            .Select(x => new ViewModel.ExternalProvider\n            (\n                authenticationScheme: x.Scheme,\n                displayName: x.DisplayName ?? x.Scheme\n            ));\n        providers.AddRange(dynamicSchemes);\n\n\n        var allowLocal = true;\n        var client = context?.Client;\n        if (client != null)\n        {\n            allowLocal = client.EnableLocalLogin;\n            if (client.IdentityProviderRestrictions != null && client.IdentityProviderRestrictions.Count != 0)\n            {\n                providers = providers.Where(provider => client.IdentityProviderRestrictions.Contains(provider.AuthenticationScheme)).ToList();\n            }\n        }\n\n        View = new ViewModel\n        {\n            AllowRememberLogin = LoginOptions.AllowRememberLogin,\n            EnableLocalLogin = allowLocal && LoginOptions.AllowLocalLogin,\n            ExternalProviders = providers.ToArray()\n        };\n    }\n}\n"
  },
  {
    "path": "src/IdentityServer/Pages/Account/Login/InputModel.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing System.ComponentModel.DataAnnotations;\n\nnamespace IdentityServer.Pages.Login;\n\npublic class InputModel\n{\n    [Required]\n    public string? Username { get; set; }\n    [Required]\n    public string? Password { get; set; }\n    public bool RememberLogin { get; set; }\n    public string? ReturnUrl { get; set; }\n    public string? Button { get; set; }\n}"
  },
  {
    "path": "src/IdentityServer/Pages/Account/Login/LoginOptions.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nnamespace IdentityServer.Pages.Login;\n\npublic static class LoginOptions\n{\n    public static readonly bool AllowLocalLogin = true;\n    public static readonly bool AllowRememberLogin = true;\n    public static readonly TimeSpan RememberMeLoginDuration = TimeSpan.FromDays(30);\n    public static readonly string InvalidCredentialsErrorMessage = \"Invalid username or password\";\n}\n"
  },
  {
    "path": "src/IdentityServer/Pages/Account/Login/ViewModel.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nnamespace IdentityServer.Pages.Login;\n\npublic class ViewModel\n{\n    public bool AllowRememberLogin { get; set; } = true;\n    public bool EnableLocalLogin { get; set; } = true;\n\n    public IEnumerable<ViewModel.ExternalProvider> ExternalProviders { get; set; } = Enumerable.Empty<ExternalProvider>();\n    public IEnumerable<ViewModel.ExternalProvider> VisibleExternalProviders => ExternalProviders.Where(x => !String.IsNullOrWhiteSpace(x.DisplayName));\n\n    public bool IsExternalLoginOnly => EnableLocalLogin == false && ExternalProviders?.Count() == 1;\n    public string? ExternalLoginScheme => IsExternalLoginOnly ? ExternalProviders?.SingleOrDefault()?.AuthenticationScheme : null;\n        \n    public class ExternalProvider\n    {\n        public ExternalProvider(string authenticationScheme, string? displayName = null)\n        {\n            AuthenticationScheme = authenticationScheme;\n            DisplayName = displayName;\n        }\n\n        public string? DisplayName { get; set; }\n        public string AuthenticationScheme { get; set; }\n    }\n}"
  },
  {
    "path": "src/IdentityServer/Pages/Account/Logout/Index.cshtml",
    "content": "@page\n@model IdentityServer.Pages.Logout.Index\n\n<div class=\"logout-page\">\n    <div class=\"lead\">\n        <h1>Logout</h1>\n        <p>Would you like to logout of IdentityServer?</p>\n    </div>\n\n    <form asp-page=\"/Account/Logout/Index\">\n        <input type=\"hidden\" name=\"logoutId\" value=\"@Model.LogoutId\"  />\n        \n        <div class=\"form-group\">\n            <button class=\"btn btn-primary\">Yes</button>\n        </div>\n    </form>\n</div>"
  },
  {
    "path": "src/IdentityServer/Pages/Account/Logout/Index.cshtml.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing Duende.IdentityServer.Events;\nusing Duende.IdentityServer.Extensions;\nusing Duende.IdentityServer.Services;\nusing IdentityModel;\nusing Microsoft.AspNetCore.Authentication;\nusing Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.AspNetCore.Mvc.RazorPages;\n\nnamespace IdentityServer.Pages.Logout;\n\n[SecurityHeaders]\n[AllowAnonymous]\npublic class Index : PageModel\n{\n    private readonly IIdentityServerInteractionService _interaction;\n    private readonly IEventService _events;\n\n    [BindProperty] \n    public string? LogoutId { get; set; }\n\n    public Index(IIdentityServerInteractionService interaction, IEventService events)\n    {\n        _interaction = interaction;\n        _events = events;\n    }\n\n    public async Task<IActionResult> OnGet(string? logoutId)\n    {\n        LogoutId = logoutId;\n\n        var showLogoutPrompt = LogoutOptions.ShowLogoutPrompt;\n\n        if (User.Identity?.IsAuthenticated != true)\n        {\n            // if the user is not authenticated, then just show logged out page\n            showLogoutPrompt = false;\n        }\n        else\n        {\n            var context = await _interaction.GetLogoutContextAsync(LogoutId);\n            if (context?.ShowSignoutPrompt == false)\n            {\n                // it's safe to automatically sign-out\n                showLogoutPrompt = false;\n            }\n        }\n            \n        if (showLogoutPrompt == false)\n        {\n            // if the request for logout was properly authenticated from IdentityServer, then\n            // we don't need to show the prompt and can just log the user out directly.\n            return await OnPost();\n        }\n\n        return Page();\n    }\n\n    public async Task<IActionResult> OnPost()\n    {\n        if (User.Identity?.IsAuthenticated == true)\n        {\n            // if there's no current logout context, we need to create one\n            // this captures necessary info from the current logged in user\n            // this can still return null if there is no context needed\n            LogoutId ??= await _interaction.CreateLogoutContextAsync();\n                \n            // delete local authentication cookie\n            await HttpContext.SignOutAsync();\n\n            // see if we need to trigger federated logout\n            var idp = User.FindFirst(JwtClaimTypes.IdentityProvider)?.Value;\n\n            // raise the logout event\n            await _events.RaiseAsync(new UserLogoutSuccessEvent(User.GetSubjectId(), User.GetDisplayName()));\n            Telemetry.Metrics.UserLogout(idp);\n\n            // if it's a local login we can ignore this workflow\n            if (idp != null && idp != Duende.IdentityServer.IdentityServerConstants.LocalIdentityProvider)\n            {\n                // we need to see if the provider supports external logout\n                if (await HttpContext.GetSchemeSupportsSignOutAsync(idp))\n                {\n                    // build a return URL so the upstream provider will redirect back\n                    // to us after the user has logged out. this allows us to then\n                    // complete our single sign-out processing.\n                    var url = Url.Page(\"/Account/Logout/Loggedout\", new { logoutId = LogoutId });\n\n                    // this triggers a redirect to the external provider for sign-out\n                    return SignOut(new AuthenticationProperties { RedirectUri = url }, idp);\n                }\n            }\n        }\n\n        return RedirectToPage(\"/Account/Logout/LoggedOut\", new { logoutId = LogoutId });\n    }\n}\n"
  },
  {
    "path": "src/IdentityServer/Pages/Account/Logout/LoggedOut.cshtml",
    "content": "@page\n@model IdentityServer.Pages.Logout.LoggedOut\n\n<div class=\"logged-out-page\">\n    <h1>\n        Logout\n        <small>You are now logged out</small>\n    </h1>\n\n    @if (Model.View.PostLogoutRedirectUri != null)\n    {\n        <div>\n            Click <a class=\"PostLogoutRedirectUri\" href=\"@Model.View.PostLogoutRedirectUri\">here</a> to return to the\n            <span>@Model.View.ClientName</span> application.\n        </div>\n    }\n\n    @if (Model.View.SignOutIframeUrl != null)\n    {\n        <iframe width=\"0\" height=\"0\" class=\"signout\" src=\"@Model.View.SignOutIframeUrl\"></iframe>\n    }\n</div>\n\n@section scripts\n{\n    @if (Model.View.AutomaticRedirectAfterSignOut)\n    {\n        <script src=\"~/js/signout-redirect.js\"></script>\n    }\n}"
  },
  {
    "path": "src/IdentityServer/Pages/Account/Logout/LoggedOut.cshtml.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing Duende.IdentityServer.Services;\nusing Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc.RazorPages;\n\nnamespace IdentityServer.Pages.Logout;\n\n[SecurityHeaders]\n[AllowAnonymous]\npublic class LoggedOut : PageModel\n{\n    private readonly IIdentityServerInteractionService _interactionService;\n\n    public LoggedOutViewModel View { get; set; } = default!;\n\n    public LoggedOut(IIdentityServerInteractionService interactionService)\n    {\n        _interactionService = interactionService;\n    }\n\n    public async Task OnGet(string? logoutId)\n    {\n        // get context information (client name, post logout redirect URI and iframe for federated signout)\n        var logout = await _interactionService.GetLogoutContextAsync(logoutId);\n\n        View = new LoggedOutViewModel\n        {\n            AutomaticRedirectAfterSignOut = LogoutOptions.AutomaticRedirectAfterSignOut,\n            PostLogoutRedirectUri = logout?.PostLogoutRedirectUri,\n            ClientName = String.IsNullOrEmpty(logout?.ClientName) ? logout?.ClientId : logout?.ClientName,\n            SignOutIframeUrl = logout?.SignOutIFrameUrl\n        };\n    }\n}\n"
  },
  {
    "path": "src/IdentityServer/Pages/Account/Logout/LoggedOutViewModel.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\n// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nnamespace IdentityServer.Pages.Logout;\n\npublic class LoggedOutViewModel\n{\n    public string? PostLogoutRedirectUri { get; set; }\n    public string? ClientName { get; set; }\n    public string? SignOutIframeUrl { get; set; }\n    public bool AutomaticRedirectAfterSignOut { get; set; }\n}\n"
  },
  {
    "path": "src/IdentityServer/Pages/Account/Logout/LogoutOptions.cs",
    "content": "﻿// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\n\nnamespace IdentityServer.Pages.Logout;\n\npublic static class LogoutOptions\n{\n    public static readonly bool ShowLogoutPrompt = false;\n    public static readonly bool AutomaticRedirectAfterSignOut = true;\n}\n"
  },
  {
    "path": "src/IdentityServer/Pages/Ciba/All.cshtml",
    "content": "@page\n@model IdentityServer.Pages.Ciba.AllModel\n@{\n}\n\n<div class=\"ciba-page\">\n    <div class=\"row\">\n        <div class=\"col\">\n            <div class=\"card\">\n                <div class=\"card-header\">\n                    <h2>Pending Backchannel Login Requests</h2>\n                </div>\n                <div class=\"card-body\">\n                    @if (Model.Logins.Any())\n                    {\n                        <table class=\"table table-bordered table-striped table-sm\">\n                            <thead>\n                                <tr>\n                                    <th>Id</th>\n                                    <th>Client Id</th>\n                                    <th>Binding Message</th>\n                                    <th></th>\n                                </tr>\n                            </thead>\n                            <tbody>\n                                @foreach (var login in Model.Logins)\n                                {\n                                    <tr>\n                                        <td>@login.InternalId</td>\n                                        <td>@login.Client.ClientId</td>\n                                        <td>@login.BindingMessage</td>\n                                        <td>\n                                            <a asp-page=\"Consent\" asp-route-id=\"@login.InternalId\" class=\"btn btn-primary\">Process</a>\n                                        </td>\n                                    </tr>\n                                }\n                            </tbody>\n                        </table>\n                    }\n                    else\n                    {\n                        <div>No Pending Login Requests</div>\n                    }\n                </div>\n            </div>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "src/IdentityServer/Pages/Ciba/All.cshtml.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing Duende.IdentityServer.Models;\nusing Duende.IdentityServer.Services;\nusing Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc.RazorPages;\n\nnamespace IdentityServer.Pages.Ciba;\n\n[SecurityHeaders]\n[Authorize]\npublic class AllModel : PageModel\n{\n    public IEnumerable<BackchannelUserLoginRequest> Logins { get; set; } = default!;\n\n    private readonly IBackchannelAuthenticationInteractionService _backchannelAuthenticationInteraction;\n\n    public AllModel(IBackchannelAuthenticationInteractionService backchannelAuthenticationInteractionService)\n    {\n        _backchannelAuthenticationInteraction = backchannelAuthenticationInteractionService;\n    }\n\n    public async Task OnGet()\n    {\n        Logins = await _backchannelAuthenticationInteraction.GetPendingLoginRequestsForCurrentUserAsync();\n    }\n}"
  },
  {
    "path": "src/IdentityServer/Pages/Ciba/Consent.cshtml",
    "content": "@page\n@model IdentityServer.Pages.Ciba.Consent\n@{\n}\n\n<div class=\"ciba-consent\">\n    <div class=\"lead\">\n        @if (Model.View.ClientLogoUrl != null)\n        {\n            <div class=\"client-logo\"><img src=\"@Model.View.ClientLogoUrl\"></div>\n        }\n        <h1>\n            @Model.View.ClientName\n            <small class=\"text-muted\">is requesting your permission</small>\n        </h1>\n        \n        <h3>Verify that this identifier matches what the client is displaying: <em  class=\"text-primary\">@Model.View.BindingMessage</em></h3>\n\n        <p>Uncheck the permissions you do not wish to grant.</p>\n    </div>\n\n    <div class=\"row\">\n        <div class=\"col-sm-8\">\n            <partial name=\"_ValidationSummary\" />\n        </div>\n    </div>\n\n    <form asp-page=\"/Ciba/Consent\">\n        <input type=\"hidden\" asp-for=\"Input.Id\" />\n        <div class=\"row\">\n            <div class=\"col-sm-8\">\n                @if (Model.View.IdentityScopes.Any())\n                {\n                    <div class=\"form-group\">\n                        <div class=\"card\">\n                            <div class=\"card-header\">\n                                <span class=\"glyphicon glyphicon-user\"></span>\n                                Personal Information\n                            </div>\n                            <ul class=\"list-group list-group-flush\">\n                                @foreach (var scope in Model.View.IdentityScopes)\n                                {\n                                    <partial name=\"_ScopeListItem\" model=\"@scope\" />\n                                }\n                            </ul>\n                        </div>\n                    </div>\n                }\n\n                @if (Model.View.ApiScopes.Any())\n                {\n                    <div class=\"form-group\">\n                        <div class=\"card\">\n                            <div class=\"card-header\">\n                                <span class=\"glyphicon glyphicon-tasks\"></span>\n                                Application Access\n                            </div>\n                            <ul class=\"list-group list-group-flush\">\n                                @foreach (var scope in Model.View.ApiScopes)\n                                {\n                                    <partial name=\"_ScopeListItem\" model=\"scope\" />\n                                }\n                            </ul>\n                        </div>\n                    </div>\n                }\n\n                <div class=\"form-group\">\n                    <div class=\"card\">\n                        <div class=\"card-header\">\n                            <span class=\"glyphicon glyphicon-pencil\"></span>\n                            Description\n                        </div>\n                        <div class=\"card-body\">\n                            <input class=\"form-control\" placeholder=\"Description or name of device\" asp-for=\"Input.Description\" autofocus>\n                        </div>\n                    </div>\n                </div>\n            </div>\n        </div>\n\n        <div class=\"row\">\n            <div class=\"col-sm-4\">\n                <button name=\"Input.button\" value=\"yes\" class=\"btn btn-primary\" autofocus>Yes, Allow</button>\n                <button name=\"Input.button\" value=\"no\" class=\"btn btn-secondary\">No, Do Not Allow</button>\n            </div>\n            <div class=\"col-sm-4 col-lg-auto\">\n                @if (Model.View.ClientUrl != null)\n                {\n                    <a class=\"btn btn-outline-info\" href=\"@Model.View.ClientUrl\">\n                        <span class=\"glyphicon glyphicon-info-sign\"></span>\n                        <strong>@Model.View.ClientName</strong>\n                    </a>\n                }\n            </div>\n        </div>\n    </form>\n</div>\n"
  },
  {
    "path": "src/IdentityServer/Pages/Ciba/Consent.cshtml.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing Duende.IdentityServer.Events;\nusing Duende.IdentityServer.Extensions;\nusing Duende.IdentityServer.Models;\nusing Duende.IdentityServer.Services;\nusing Duende.IdentityServer.Validation;\nusing Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.AspNetCore.Mvc.RazorPages;\n\nnamespace IdentityServer.Pages.Ciba;\n\n[Authorize]\n[SecurityHeaders]\npublic class Consent : PageModel\n{\n    private readonly IBackchannelAuthenticationInteractionService _interaction;\n    private readonly IEventService _events;\n    private readonly ILogger<Consent> _logger;\n\n    public Consent(\n        IBackchannelAuthenticationInteractionService interaction,\n        IEventService events,\n        ILogger<Consent> logger)\n    {\n        _interaction = interaction;\n        _events = events;\n        _logger = logger;\n    }\n\n    public ViewModel View { get; set; } = default!;\n\n    [BindProperty]\n    public InputModel Input { get; set; } = default!;\n\n    public async Task<IActionResult> OnGet(string? id)\n    {\n        if (!await SetViewModelAsync(id))\n        {\n            return RedirectToPage(\"/Home/Error/Index\");\n        }\n\n        Input = new InputModel\n        {\n            Id = id\n        };\n\n        return Page();\n    }\n\n    public async Task<IActionResult> OnPost()\n    {\n        // validate return url is still valid\n        var request = await _interaction.GetLoginRequestByInternalIdAsync(Input.Id ?? throw new ArgumentNullException(nameof(Input.Id)));\n        if (request == null || request.Subject.GetSubjectId() != User.GetSubjectId())\n        {\n            _logger.InvalidId(Input.Id);\n            return RedirectToPage(\"/Home/Error/Index\");\n        }\n\n        CompleteBackchannelLoginRequest? result = null;\n\n        // user clicked 'no' - send back the standard 'access_denied' response\n        if (Input.Button == \"no\")\n        {\n            result = new CompleteBackchannelLoginRequest(Input.Id);\n\n            // emit event\n            await _events.RaiseAsync(new ConsentDeniedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues));\n            Telemetry.Metrics.ConsentDenied(request.Client.ClientId, request.ValidatedResources.ParsedScopes.Select(s => s.ParsedName));\n        }\n        // user clicked 'yes' - validate the data\n        else if (Input.Button == \"yes\")\n        {\n            // if the user consented to some scope, build the response model\n            if (Input.ScopesConsented.Any())\n            {\n                var scopes = Input.ScopesConsented;\n                if (ConsentOptions.EnableOfflineAccess == false)\n                {\n                    scopes = scopes.Where(x => x != Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess);\n                }\n\n                result = new CompleteBackchannelLoginRequest(Input.Id)\n                {\n                    ScopesValuesConsented = scopes.ToArray(),\n                    Description = Input.Description\n                };\n\n                // emit event\n                await _events.RaiseAsync(new ConsentGrantedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues, result.ScopesValuesConsented, false));\n                Telemetry.Metrics.ConsentGranted(request.Client.ClientId, result.ScopesValuesConsented, false);\n                var denied = request.ValidatedResources.ParsedScopes.Select(s => s.ParsedName).Except(result.ScopesValuesConsented);\n                Telemetry.Metrics.ConsentDenied(request.Client.ClientId, denied);\n            }\n            else\n            {\n                ModelState.AddModelError(\"\", ConsentOptions.MustChooseOneErrorMessage);\n            }\n        }\n        else\n        {\n            ModelState.AddModelError(\"\", ConsentOptions.InvalidSelectionErrorMessage);\n        }\n\n        if (result != null)\n        {\n            // communicate outcome of consent back to identityserver\n            await _interaction.CompleteLoginRequestAsync(result);\n\n            return RedirectToPage(\"/Ciba/All\");\n        }\n\n        // we need to redisplay the consent UI\n        if (!await SetViewModelAsync(Input.Id))\n        {\n            return RedirectToPage(\"/Home/Error/Index\");\n        }\n        return Page();\n    }\n\n    private async Task<bool> SetViewModelAsync(string? id)\n    {\n        ArgumentNullException.ThrowIfNull(id);\n\n        var request = await _interaction.GetLoginRequestByInternalIdAsync(id);\n        if (request != null && request.Subject.GetSubjectId() == User.GetSubjectId())\n        {\n            View = CreateConsentViewModel(request);\n            return true;\n        }\n        else\n        {\n            _logger.NoMatchingBackchannelLoginRequest(id);\n            return false;\n        }\n    }\n\n    private ViewModel CreateConsentViewModel(BackchannelUserLoginRequest request)\n    {\n        var vm = new ViewModel\n        {\n            ClientName = request.Client.ClientName ?? request.Client.ClientId,\n            ClientUrl = request.Client.ClientUri,\n            ClientLogoUrl = request.Client.LogoUri,\n            BindingMessage = request.BindingMessage\n        };\n\n        vm.IdentityScopes = request.ValidatedResources.Resources.IdentityResources\n            .Select(x => CreateScopeViewModel(x, Input == null || Input.ScopesConsented.Contains(x.Name)))\n            .ToArray();\n\n        var resourceIndicators = request.RequestedResourceIndicators ?? Enumerable.Empty<string>();\n        var apiResources = request.ValidatedResources.Resources.ApiResources.Where(x => resourceIndicators.Contains(x.Name));\n\n        var apiScopes = new List<ScopeViewModel>();\n        foreach (var parsedScope in request.ValidatedResources.ParsedScopes)\n        {\n            var apiScope = request.ValidatedResources.Resources.FindApiScope(parsedScope.ParsedName);\n            if (apiScope != null)\n            {\n                var scopeVm = CreateScopeViewModel(parsedScope, apiScope, Input == null || Input.ScopesConsented.Contains(parsedScope.RawValue));\n                scopeVm.Resources = apiResources.Where(x => x.Scopes.Contains(parsedScope.ParsedName))\n                    .Select(x => new ResourceViewModel\n                    {\n                        Name = x.Name,\n                        DisplayName = x.DisplayName ?? x.Name,\n                    }).ToArray();\n                apiScopes.Add(scopeVm);\n            }\n        }\n        if (ConsentOptions.EnableOfflineAccess && request.ValidatedResources.Resources.OfflineAccess)\n        {\n            apiScopes.Add(GetOfflineAccessScope(Input == null || Input.ScopesConsented.Contains(Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess)));\n        }\n        vm.ApiScopes = apiScopes;\n\n        return vm;\n    }\n\n    private static ScopeViewModel CreateScopeViewModel(IdentityResource identity, bool check)\n    {\n        return new ScopeViewModel\n        {\n            Name = identity.Name,\n            Value = identity.Name,\n            DisplayName = identity.DisplayName ?? identity.Name,\n            Description = identity.Description,\n            Emphasize = identity.Emphasize,\n            Required = identity.Required,\n            Checked = check || identity.Required\n        };\n    }\n\n    private static ScopeViewModel CreateScopeViewModel(ParsedScopeValue parsedScopeValue, ApiScope apiScope, bool check)\n    {\n        var displayName = apiScope.DisplayName ?? apiScope.Name;\n        if (!String.IsNullOrWhiteSpace(parsedScopeValue.ParsedParameter))\n        {\n            displayName += \":\" + parsedScopeValue.ParsedParameter;\n        }\n\n        return new ScopeViewModel\n        {\n            Name = parsedScopeValue.ParsedName,\n            Value = parsedScopeValue.RawValue,\n            DisplayName = displayName,\n            Description = apiScope.Description,\n            Emphasize = apiScope.Emphasize,\n            Required = apiScope.Required,\n            Checked = check || apiScope.Required\n        };\n    }\n\n    private static ScopeViewModel GetOfflineAccessScope(bool check)\n    {\n        return new ScopeViewModel\n        {\n            Value = Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess,\n            DisplayName = ConsentOptions.OfflineAccessDisplayName,\n            Description = ConsentOptions.OfflineAccessDescription,\n            Emphasize = true,\n            Checked = check\n        };\n    }\n}\n"
  },
  {
    "path": "src/IdentityServer/Pages/Ciba/ConsentOptions.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nnamespace IdentityServer.Pages.Ciba;\n\npublic static class ConsentOptions\n{\n    public static readonly bool EnableOfflineAccess = true;\n    public static readonly string OfflineAccessDisplayName = \"Offline Access\";\n    public static readonly string OfflineAccessDescription = \"Access to your applications and resources, even when you are offline\";\n\n    public static readonly string MustChooseOneErrorMessage = \"You must pick at least one permission\";\n    public static readonly string InvalidSelectionErrorMessage = \"Invalid selection\";\n}"
  },
  {
    "path": "src/IdentityServer/Pages/Ciba/Index.cshtml",
    "content": "@page\n@model IdentityServer.Pages.Ciba.IndexModel\n@{\n}\n\n<div class=\"ciba-page\">\n    <div class=\"lead\">\n        @if (Model.LoginRequest.Client.LogoUri != null)\n        {\n            <div class=\"client-logo\"><img src=\"@Model.LoginRequest.Client.LogoUri\"></div>\n        }\n        <h1>\n            @Model.LoginRequest.Client.ClientName\n            <small class=\"text-muted\">is requesting your permission</small>\n        </h1>\n        \n        <h3>\n            Verify that this identifier matches what the client is displaying:\n            <em class=\"text-primary\">@Model.LoginRequest.BindingMessage</em>\n        </h3>\n\n        <p>\n            Do you wish to continue?\n        </p>\n        <div>\n            <a class=\"btn btn-primary\" asp-page=\"/Ciba/Consent\" asp-route-id=\"@Model.LoginRequest.InternalId\">Yes, Continue</a>\n        </div>\n        \n    </div>\n</div>\n"
  },
  {
    "path": "src/IdentityServer/Pages/Ciba/Index.cshtml.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing Duende.IdentityServer.Models;\nusing Duende.IdentityServer.Services;\nusing Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.AspNetCore.Mvc.RazorPages;\n\nnamespace IdentityServer.Pages.Ciba;\n\n[AllowAnonymous]\n[SecurityHeaders]\npublic class IndexModel : PageModel\n{\n    public BackchannelUserLoginRequest LoginRequest { get; set; } = default!;\n\n    private readonly IBackchannelAuthenticationInteractionService _backchannelAuthenticationInteraction;\n    private readonly ILogger<IndexModel> _logger;\n\n    public IndexModel(IBackchannelAuthenticationInteractionService backchannelAuthenticationInteractionService, ILogger<IndexModel> logger)\n    {\n        _backchannelAuthenticationInteraction = backchannelAuthenticationInteractionService;\n        _logger = logger;\n    }\n\n    public async Task<IActionResult> OnGet(string id)\n    {\n        var result = await _backchannelAuthenticationInteraction.GetLoginRequestByInternalIdAsync(id);\n        if (result == null)\n        {\n            _logger.InvalidBackchannelLoginId(id);\n            return RedirectToPage(\"/Home/Error/Index\");\n        }\n        else\n        {\n            LoginRequest = result;\n        }\n        \n        return Page();\n    }\n}"
  },
  {
    "path": "src/IdentityServer/Pages/Ciba/InputModel.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nnamespace IdentityServer.Pages.Ciba;\n\npublic class InputModel\n{\n    public string? Button { get; set; }\n    public IEnumerable<string> ScopesConsented { get; set; } = new List<string>();\n    public string? Id { get; set; }\n    public string? Description { get; set; }\n}"
  },
  {
    "path": "src/IdentityServer/Pages/Ciba/ViewModel.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nnamespace IdentityServer.Pages.Ciba;\n\npublic class ViewModel\n{\n    public string? ClientName { get; set; }\n    public string? ClientUrl { get; set; }\n    public string? ClientLogoUrl { get; set; }\n        \n    public string? BindingMessage { get; set; }\n\n    public IEnumerable<ScopeViewModel> IdentityScopes { get; set; } = Enumerable.Empty<ScopeViewModel>();\n    public IEnumerable<ScopeViewModel> ApiScopes { get; set; } = Enumerable.Empty<ScopeViewModel>();\n}\n\npublic class ScopeViewModel\n{\n    public string? Name { get; set; }\n    public string? Value { get; set; }\n    public string? DisplayName { get; set; }\n    public string? Description { get; set; }\n    public bool Emphasize { get; set; }\n    public bool Required { get; set; }\n    public bool Checked { get; set; }\n    public IEnumerable<ResourceViewModel> Resources { get; set; } = Enumerable.Empty<ResourceViewModel>();\n}\n\npublic class ResourceViewModel\n{\n    public string? Name { get; set; }\n    public string? DisplayName { get; set; }\n}"
  },
  {
    "path": "src/IdentityServer/Pages/Ciba/_ScopeListItem.cshtml",
    "content": "@using IdentityServer.Pages.Ciba\n@model ScopeViewModel\n\n<li class=\"list-group-item\">\n    <label>\n        <input class=\"consent-scopecheck\"\n               type=\"checkbox\"\n               name=\"Input.ScopesConsented\"\n               id=\"scopes_@Model.Value\"\n               value=\"@Model.Value\"\n               checked=\"@Model.Checked\"\n               disabled=\"@Model.Required\" />\n        @if (Model.Required)\n        {\n            <input type=\"hidden\"\n                   name=\"Input.ScopesConsented\"\n                   value=\"@Model.Value\" />\n        }\n        <strong>@Model.DisplayName</strong>\n        @if (Model.Emphasize)\n        {\n            <span class=\"glyphicon glyphicon-exclamation-sign\"></span>\n        }\n    </label>\n    @if (Model.Required)\n    {\n        <span><em>(required)</em></span>\n    }\n    @if (Model.Description != null)\n    {\n        <div class=\"consent-description\">\n            <label for=\"scopes_@Model.Value\">@Model.Description</label>\n        </div>\n    }\n    @if (Model.Resources?.Any() == true)\n    {\n        <div class=\"consent-description\">\n            <label>Will be available to these resource servers:</label>\n            <ul>\n            @foreach (var resource in Model.Resources)\n            {\n                <li>@resource.DisplayName</li>\n            }\n            </ul>\n        </div>\n    }\n</li>"
  },
  {
    "path": "src/IdentityServer/Pages/Consent/ConsentOptions.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nnamespace IdentityServer.Pages.Consent;\n\npublic static class ConsentOptions\n{\n    public static readonly bool EnableOfflineAccess = true;\n    public static readonly string OfflineAccessDisplayName = \"Offline Access\";\n    public static readonly string OfflineAccessDescription = \"Access to your applications and resources, even when you are offline\";\n\n    public static readonly string MustChooseOneErrorMessage = \"You must pick at least one permission\";\n    public static readonly string InvalidSelectionErrorMessage = \"Invalid selection\";\n}"
  },
  {
    "path": "src/IdentityServer/Pages/Consent/Index.cshtml",
    "content": "@page\n@model IdentityServer.Pages.Consent.Index\n@{\n}\n\n<div class=\"page-consent\">\n    <div class=\"lead\">\n        @if (Model.View.ClientLogoUrl != null)\n        {\n            <div class=\"client-logo\"><img src=\"@Model.View.ClientLogoUrl\"></div>\n        }\n        <h1>\n            @Model.View.ClientName\n            <small class=\"text-muted\">is requesting your permission</small>\n        </h1>\n        <p>Uncheck the permissions you do not wish to grant.</p>\n    </div>\n\n    <div class=\"row\">\n        <div class=\"col-sm-8\">\n            <partial name=\"_ValidationSummary\" />\n        </div>\n    </div>\n\n    <form asp-page=\"/Consent/Index\">\n        <input type=\"hidden\" asp-for=\"Input.ReturnUrl\" />\n        <div class=\"row\">\n            <div class=\"col-sm-8\">\n                @if (Model.View.IdentityScopes.Any())\n                {\n                    <div class=\"form-group\">\n                        <div class=\"card\">\n                            <div class=\"card-header\">\n                                <span class=\"glyphicon glyphicon-user\"></span>\n                                Personal Information\n                            </div>\n                            <ul class=\"list-group list-group-flush\">\n                                @foreach (var scope in Model.View.IdentityScopes)\n                                {\n                                    <partial name=\"_ScopeListItem\" model=\"@scope\" />\n                                }\n                            </ul>\n                        </div>\n                    </div>\n                }\n\n                @if (Model.View.ApiScopes.Any())\n                {\n                    <div class=\"form-group\">\n                        <div class=\"card\">\n                            <div class=\"card-header\">\n                                <span class=\"glyphicon glyphicon-tasks\"></span>\n                                Application Access\n                            </div>\n                            <ul class=\"list-group list-group-flush\">\n                                @foreach (var scope in Model.View.ApiScopes)\n                                {\n                                    <partial name=\"_ScopeListItem\" model=\"scope\" />\n                                }\n                            </ul>\n                        </div>\n                    </div>\n                }\n\n                <div class=\"form-group\">\n                    <div class=\"card\">\n                        <div class=\"card-header\">\n                            <span class=\"glyphicon glyphicon-pencil\"></span>\n                            Description\n                        </div>\n                        <div class=\"card-body\">\n                            <input class=\"form-control\" placeholder=\"Description or name of device\" asp-for=\"Input.Description\" autofocus>\n                        </div>\n                    </div>\n                </div>\n\n                @if (Model.View.AllowRememberConsent)\n                {\n                    <div class=\"form-group\">\n                        <div class=\"form-check\">\n                            <input class=\"form-check-input\" asp-for=\"Input.RememberConsent\">\n                            <label class=\"form-check-label\" asp-for=\"Input.RememberConsent\">\n                                <strong>Remember My Decision</strong>\n                            </label>\n                        </div>\n                    </div>\n                }\n            </div>\n        </div>\n\n        <div class=\"row\">\n            <div class=\"col-sm-4\">\n                <button name=\"Input.button\" value=\"yes\" class=\"btn btn-primary\" autofocus>Yes, Allow</button>\n                <button name=\"Input.button\" value=\"no\" class=\"btn btn-secondary\">No, Do Not Allow</button>\n            </div>\n            <div class=\"col-sm-4 col-lg-auto\">\n                @if (Model.View.ClientUrl != null)\n                {\n                    <a class=\"btn btn-outline-info\" href=\"@Model.View.ClientUrl\">\n                        <span class=\"glyphicon glyphicon-info-sign\"></span>\n                        <strong>@Model.View.ClientName</strong>\n                    </a>\n                }\n            </div>\n        </div>\n    </form>\n</div>\n"
  },
  {
    "path": "src/IdentityServer/Pages/Consent/Index.cshtml.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing Duende.IdentityServer.Events;\nusing Duende.IdentityServer.Extensions;\nusing Duende.IdentityServer.Models;\nusing Duende.IdentityServer.Services;\nusing Duende.IdentityServer.Validation;\nusing IdentityModel;\nusing Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.AspNetCore.Mvc.RazorPages;\n\nnamespace IdentityServer.Pages.Consent;\n\n[Authorize]\n[SecurityHeaders]\npublic class Index : PageModel\n{\n    private readonly IIdentityServerInteractionService _interaction;\n    private readonly IEventService _events;\n    private readonly ILogger<Index> _logger;\n\n    public Index(\n        IIdentityServerInteractionService interaction,\n        IEventService events,\n        ILogger<Index> logger)\n    {\n        _interaction = interaction;\n        _events = events;\n        _logger = logger;\n    }\n\n    public ViewModel View { get; set; } = default!;\n\n    [BindProperty]\n    public InputModel Input { get; set; } = default!;\n\n    public async Task<IActionResult> OnGet(string? returnUrl)\n    {\n        if (!await SetViewModelAsync(returnUrl))\n        {\n            return RedirectToPage(\"/Home/Error/Index\");\n        }\n\n        Input = new InputModel\n        {\n            ReturnUrl = returnUrl,\n        };\n\n        return Page();\n    }\n\n    public async Task<IActionResult> OnPost()\n    {\n        // validate return url is still valid\n        var request = await _interaction.GetAuthorizationContextAsync(Input.ReturnUrl);\n        if (request == null) return RedirectToPage(\"/Home/Error/Index\");\n\n        ConsentResponse? grantedConsent = null;\n\n        // user clicked 'no' - send back the standard 'access_denied' response\n        if (Input.Button == \"no\")\n        {\n            grantedConsent = new ConsentResponse { Error = AuthorizationError.AccessDenied };\n\n            // emit event\n            await _events.RaiseAsync(new ConsentDeniedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues));\n            Telemetry.Metrics.ConsentDenied(request.Client.ClientId, request.ValidatedResources.ParsedScopes.Select(s => s.ParsedName));\n        }\n        // user clicked 'yes' - validate the data\n        else if (Input.Button == \"yes\")\n        {\n            // if the user consented to some scope, build the response model\n            if (Input.ScopesConsented.Any())\n            {\n                var scopes = Input.ScopesConsented;\n                if (ConsentOptions.EnableOfflineAccess == false)\n                {\n                    scopes = scopes.Where(x => x != Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess);\n                }\n\n                grantedConsent = new ConsentResponse\n                {\n                    RememberConsent = Input.RememberConsent,\n                    ScopesValuesConsented = scopes.ToArray(),\n                    Description = Input.Description\n                };\n\n                // emit event\n                await _events.RaiseAsync(new ConsentGrantedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues, grantedConsent.ScopesValuesConsented, grantedConsent.RememberConsent));\n                Telemetry.Metrics.ConsentGranted(request.Client.ClientId, grantedConsent.ScopesValuesConsented, grantedConsent.RememberConsent);\n                var denied = request.ValidatedResources.ParsedScopes.Select(s => s.ParsedName).Except(grantedConsent.ScopesValuesConsented);\n                Telemetry.Metrics.ConsentDenied(request.Client.ClientId, denied);\n            }\n            else\n            {\n                ModelState.AddModelError(\"\", ConsentOptions.MustChooseOneErrorMessage);\n            }\n        }\n        else\n        {\n            ModelState.AddModelError(\"\", ConsentOptions.InvalidSelectionErrorMessage);\n        }\n\n        if (grantedConsent != null)\n        {\n            ArgumentNullException.ThrowIfNull(Input.ReturnUrl, nameof(Input.ReturnUrl));\n\n            // communicate outcome of consent back to identityserver\n            await _interaction.GrantConsentAsync(request, grantedConsent);\n\n            // redirect back to authorization endpoint\n            if (request.IsNativeClient() == true)\n            {\n                // The client is native, so this change in how to\n                // return the response is for better UX for the end user.\n                return this.LoadingPage(Input.ReturnUrl);\n            }\n\n            return Redirect(Input.ReturnUrl);\n        }\n\n        // we need to redisplay the consent UI\n        if (!await SetViewModelAsync(Input.ReturnUrl))\n        {\n            return RedirectToPage(\"/Home/Error/Index\");\n        }\n        return Page();\n    }\n\n    private async Task<bool> SetViewModelAsync(string? returnUrl)\n    {\n        ArgumentNullException.ThrowIfNull(returnUrl);\n\n        var request = await _interaction.GetAuthorizationContextAsync(returnUrl);\n        if (request != null)\n        {\n            View = CreateConsentViewModel(request);\n            return true;\n        }\n        else\n        {\n            _logger.NoConsentMatchingRequest(returnUrl);\n            return false;\n        }\n    }\n\n    private ViewModel CreateConsentViewModel(AuthorizationRequest request)\n    {\n        var vm = new ViewModel\n        {\n            ClientName = request.Client.ClientName ?? request.Client.ClientId,\n            ClientUrl = request.Client.ClientUri,\n            ClientLogoUrl = request.Client.LogoUri,\n            AllowRememberConsent = request.Client.AllowRememberConsent\n        };\n\n        vm.IdentityScopes = request.ValidatedResources.Resources.IdentityResources\n            .Select(x => CreateScopeViewModel(x, Input == null || Input.ScopesConsented.Contains(x.Name)))\n            .ToArray();\n\n        var resourceIndicators = request.Parameters.GetValues(OidcConstants.AuthorizeRequest.Resource) ?? Enumerable.Empty<string>();\n        var apiResources = request.ValidatedResources.Resources.ApiResources.Where(x => resourceIndicators.Contains(x.Name));\n\n        var apiScopes = new List<ScopeViewModel>();\n        foreach (var parsedScope in request.ValidatedResources.ParsedScopes)\n        {\n            var apiScope = request.ValidatedResources.Resources.FindApiScope(parsedScope.ParsedName);\n            if (apiScope != null)\n            {\n                var scopeVm = CreateScopeViewModel(parsedScope, apiScope, Input == null || Input.ScopesConsented.Contains(parsedScope.RawValue));\n                scopeVm.Resources = apiResources.Where(x => x.Scopes.Contains(parsedScope.ParsedName))\n                    .Select(x => new ResourceViewModel\n                    {\n                        Name = x.Name,\n                        DisplayName = x.DisplayName ?? x.Name,\n                    }).ToArray();\n                apiScopes.Add(scopeVm);\n            }\n        }\n        if (ConsentOptions.EnableOfflineAccess && request.ValidatedResources.Resources.OfflineAccess)\n        {\n            apiScopes.Add(CreateOfflineAccessScope(Input == null || Input.ScopesConsented.Contains(Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess)));\n        }\n        vm.ApiScopes = apiScopes;\n\n        return vm;\n    }\n\n    private static ScopeViewModel CreateScopeViewModel(IdentityResource identity, bool check)\n    {\n        return new ScopeViewModel\n        {\n            Name = identity.Name,\n            Value = identity.Name,\n            DisplayName = identity.DisplayName ?? identity.Name,\n            Description = identity.Description,\n            Emphasize = identity.Emphasize,\n            Required = identity.Required,\n            Checked = check || identity.Required\n        };\n    }\n\n    private static ScopeViewModel CreateScopeViewModel(ParsedScopeValue parsedScopeValue, ApiScope apiScope, bool check)\n    {\n\t\tvar displayName = apiScope.DisplayName ?? apiScope.Name;\n        if (!String.IsNullOrWhiteSpace(parsedScopeValue.ParsedParameter))\n        {\n            displayName += \":\" + parsedScopeValue.ParsedParameter;\n        }\n\n        return new ScopeViewModel\n        {\n            Name = parsedScopeValue.ParsedName,\n            Value = parsedScopeValue.RawValue,\n            DisplayName = displayName,\n            Description = apiScope.Description,\n            Emphasize = apiScope.Emphasize,\n            Required = apiScope.Required,\n            Checked = check || apiScope.Required\n        };\n    }\n\n    private static ScopeViewModel CreateOfflineAccessScope(bool check)\n    {\n        return new ScopeViewModel\n        {\n            Value = Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess,\n            DisplayName = ConsentOptions.OfflineAccessDisplayName,\n            Description = ConsentOptions.OfflineAccessDescription,\n            Emphasize = true,\n            Checked = check\n        };\n    }\n}\n"
  },
  {
    "path": "src/IdentityServer/Pages/Consent/InputModel.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nnamespace IdentityServer.Pages.Consent;\n\npublic class InputModel\n{\n    public string? Button { get; set; }\n    public IEnumerable<string> ScopesConsented { get; set; } = new List<string>();\n    public bool RememberConsent { get; set; } = true;\n    public string? ReturnUrl { get; set; }\n    public string? Description { get; set; }\n}"
  },
  {
    "path": "src/IdentityServer/Pages/Consent/ViewModel.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nnamespace IdentityServer.Pages.Consent;\n\npublic class ViewModel\n{\n    public string? ClientName { get; set; }\n    public string? ClientUrl { get; set; }\n    public string? ClientLogoUrl { get; set; }\n    public bool AllowRememberConsent { get; set; }\n\n    public IEnumerable<ScopeViewModel> IdentityScopes { get; set; } = Enumerable.Empty<ScopeViewModel>();\n    public IEnumerable<ScopeViewModel> ApiScopes { get; set; } = Enumerable.Empty<ScopeViewModel>();\n}\n\npublic class ScopeViewModel\n{\n    public string? Name { get; set; }\n    public string? Value { get; set; }\n    public string? DisplayName { get; set; }\n    public string? Description { get; set; }\n    public bool Emphasize { get; set; }\n    public bool Required { get; set; }\n    public bool Checked { get; set; }\n    public IEnumerable<ResourceViewModel> Resources { get; set; } = Enumerable.Empty<ResourceViewModel>();\n}\n\npublic class ResourceViewModel\n{\n    public string? Name { get; set; }\n    public string? DisplayName { get; set; }\n}"
  },
  {
    "path": "src/IdentityServer/Pages/Consent/_ScopeListItem.cshtml",
    "content": "@using IdentityServer.Pages.Consent\n@model ScopeViewModel\n\n<li class=\"list-group-item\">\n    <label>\n        <input class=\"consent-scopecheck\"\n               type=\"checkbox\"\n               name=\"Input.ScopesConsented\"\n               id=\"scopes_@Model.Value\"\n               value=\"@Model.Value\"\n               checked=\"@Model.Checked\"\n               disabled=\"@Model.Required\" />\n        @if (Model.Required)\n        {\n            <input type=\"hidden\"\n                   name=\"Input.ScopesConsented\"\n                   value=\"@Model.Value\" />\n        }\n        <strong>@Model.DisplayName</strong>\n        @if (Model.Emphasize)\n        {\n            <span class=\"glyphicon glyphicon-exclamation-sign\"></span>\n        }\n    </label>\n    @if (Model.Required)\n    {\n        <span><em>(required)</em></span>\n    }\n    @if (Model.Description != null)\n    {\n        <div class=\"consent-description\">\n            <label for=\"scopes_@Model.Value\">@Model.Description</label>\n        </div>\n    }\n    @if (Model.Resources?.Any() == true)\n    {\n        <div class=\"consent-description\">\n            <label>Will be available to these resource servers:</label>\n            <ul>\n            @foreach (var resource in Model.Resources)\n            {\n                <li>@resource.DisplayName</li>\n            }\n            </ul>\n        </div>\n    }\n</li>"
  },
  {
    "path": "src/IdentityServer/Pages/Device/DeviceOptions.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nnamespace IdentityServer.Pages.Device;\n\npublic static class DeviceOptions\n{\n    public static readonly bool EnableOfflineAccess = true;\n    public static readonly string OfflineAccessDisplayName = \"Offline Access\";\n    public static readonly string OfflineAccessDescription = \"Access to your applications and resources, even when you are offline\";\n\n    public static readonly string InvalidUserCode = \"Invalid user code\";\n    public static readonly string MustChooseOneErrorMessage = \"You must pick at least one permission\";\n    public static readonly string InvalidSelectionErrorMessage = \"Invalid selection\";\n}"
  },
  {
    "path": "src/IdentityServer/Pages/Device/Index.cshtml",
    "content": "@page\n@model IdentityServer.Pages.Device.Index\n@{\n}\n\n@if (Model.Input.UserCode == null)\n{\n    @*We need to collect the user code*@\n    <div class=\"page-device-code\">\n        <div class=\"lead\">\n            <h1>User Code</h1>\n            <p>Please enter the code displayed on your device.</p>\n        </div>\n\n        <div class=\"row\">\n            <div class=\"col-sm-8\">\n                <partial name=\"_ValidationSummary\" />\n            </div>\n        </div>\n\n        <div class=\"row\">\n            <div class=\"col-sm-6\">\n                <form asp-page=\"/Device/Index\" method=\"get\">\n                    <div class=\"form-group\">\n                        <label for=\"userCode\">User Code:</label>\n                        <input class=\"form-control\" for=\"userCode\" name=\"userCode\" autofocus />\n                    </div>\n\n                    <button class=\"btn btn-primary\" name=\"button\">Submit</button>\n                </form>\n            </div>\n        </div>\n    </div>\n}\nelse\n{\n    @*collect consent for the user code provided*@\n    <div class=\"page-device-confirmation\">\n        <div class=\"lead\">\n            @if (Model.View.ClientLogoUrl != null)\n            {\n                <div class=\"client-logo\"><img src=\"@Model.View.ClientLogoUrl\"></div>\n            }\n            <h1>\n                @Model.View.ClientName\n                <small class=\"text-muted\">is requesting your permission</small>\n            </h1>\n            <p>Please confirm that the authorization request matches the code: <strong>@Model.Input.UserCode</strong>.</p>\n            <p>Uncheck the permissions you do not wish to grant.</p>\n        </div>\n\n        <div class=\"row\">\n            <div class=\"col-sm-8\">\n                <partial name=\"_ValidationSummary\" />\n            </div>\n        </div>\n\n        <form asp-page=\"/Device/Index\">\n            <input asp-for=\"Input.UserCode\" type=\"hidden\" />\n            <div class=\"row\">\n                <div class=\"col-sm-8\">\n                    @if (Model.View.IdentityScopes.Any())\n                    {\n                        <div class=\"form-group\">\n                            <div class=\"card\">\n                                <div class=\"card-header\">\n                                    <span class=\"glyphicon glyphicon-user\"></span>\n                                    Personal Information\n                                </div>\n                                <ul class=\"list-group list-group-flush\">\n                                    @foreach (var scope in Model.View.IdentityScopes)\n                                    {\n                                        <partial name=\"_ScopeListItem\" model=\"@scope\" />\n                                    }\n                                </ul>\n                            </div>\n                        </div>\n                    }\n\n                    @if (Model.View.ApiScopes.Any())\n                    {\n                        <div class=\"form-group\">\n                            <div class=\"card\">\n                                <div class=\"card-header\">\n                                    <span class=\"glyphicon glyphicon-tasks\"></span>\n                                    Application Access\n                                </div>\n                                <ul class=\"list-group list-group-flush\">\n                                    @foreach (var scope in Model.View.ApiScopes)\n                                    {\n                                        <partial name=\"_ScopeListItem\" model=\"scope\" />\n                                    }\n                                </ul>\n                            </div>\n                        </div>\n                    }\n\n                    <div class=\"form-group\">\n                        <div class=\"card\">\n                            <div class=\"card-header\">\n                                <span class=\"glyphicon glyphicon-pencil\"></span>\n                                Description\n                            </div>\n                            <div class=\"card-body\">\n                                <input class=\"form-control\" placeholder=\"Description or name of device\" asp-for=\"Input.Description\" autofocus>\n                            </div>\n                        </div>\n                    </div>\n\n                    @if (Model.View.AllowRememberConsent)\n                    {\n                        <div class=\"form-group\">\n                            <div class=\"form-check\">\n                                <input class=\"form-check-input\" asp-for=\"Input.RememberConsent\">\n                                <label class=\"form-check-label\" asp-for=\"Input.RememberConsent\">\n                                    <strong>Remember My Decision</strong>\n                                </label>\n                            </div>\n                        </div>\n                    }\n                </div>\n            </div>\n\n            <div class=\"row\">\n                <div class=\"col-sm-4\">\n                    <button name=\"Input.button\" value=\"yes\" class=\"btn btn-primary\" autofocus>Yes, Allow</button>\n                    <button name=\"Input.button\" value=\"no\" class=\"btn btn-secondary\">No, Do Not Allow</button>\n                </div>\n                <div class=\"col-sm-4 col-lg-auto\">\n                    @if (Model.View.ClientUrl != null)\n                    {\n                        <a class=\"btn btn-outline-info\" href=\"@Model.View.ClientUrl\">\n                            <span class=\"glyphicon glyphicon-info-sign\"></span>\n                            <strong>@Model.View.ClientName</strong>\n                        </a>\n                    }\n                </div>\n            </div>\n        </form>\n    </div>\n}\n"
  },
  {
    "path": "src/IdentityServer/Pages/Device/Index.cshtml.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing Duende.IdentityServer.Configuration;\nusing Duende.IdentityServer.Events;\nusing Duende.IdentityServer.Extensions;\nusing Duende.IdentityServer.Models;\nusing Duende.IdentityServer.Services;\nusing Duende.IdentityServer.Validation;\nusing IdentityServer.Pages.Consent;\nusing Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.AspNetCore.Mvc.RazorPages;\nusing Microsoft.Extensions.Options;\n\nnamespace IdentityServer.Pages.Device;\n\n[SecurityHeaders]\n[Authorize]\npublic class Index : PageModel\n{\n    private readonly IDeviceFlowInteractionService _interaction;\n    private readonly IEventService _events;\n    private readonly IOptions<IdentityServerOptions> _options;\n    private readonly ILogger<Index> _logger;\n\n    public Index(\n        IDeviceFlowInteractionService interaction,\n        IEventService eventService,\n        IOptions<IdentityServerOptions> options,\n        ILogger<Index> logger)\n    {\n        _interaction = interaction;\n        _events = eventService;\n        _options = options;\n        _logger = logger;\n    }\n\n    public ViewModel View { get; set; } = default!;\n\n    [BindProperty]\n    public InputModel Input { get; set; } = default!;\n\n    public async Task<IActionResult> OnGet(string? userCode)\n    {\n        if (String.IsNullOrWhiteSpace(userCode))\n        {\n            return Page();\n        }\n\n        if (!await SetViewModelAsync(userCode))\n        {\n            ModelState.AddModelError(\"\", DeviceOptions.InvalidUserCode);\n            return Page();\n        }\n\n        Input = new InputModel { \n            UserCode = userCode,\n        };\n\n        return Page();\n    }\n\n    public async Task<IActionResult> OnPost()\n    {\n        var request = await _interaction.GetAuthorizationContextAsync(Input.UserCode ?? throw new ArgumentNullException(nameof(Input.UserCode)));\n        if (request == null) return RedirectToPage(\"/Home/Error/Index\");\n\n        ConsentResponse? grantedConsent = null;\n\n        // user clicked 'no' - send back the standard 'access_denied' response\n        if (Input.Button == \"no\")\n        {\n            grantedConsent = new ConsentResponse\n            {\n                Error = AuthorizationError.AccessDenied\n            };\n\n            // emit event\n            await _events.RaiseAsync(new ConsentDeniedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues));\n            Telemetry.Metrics.ConsentDenied(request.Client.ClientId, request.ValidatedResources.ParsedScopes.Select(s => s.ParsedName));\n        }\n        // user clicked 'yes' - validate the data\n        else if (Input.Button == \"yes\")\n        {\n            // if the user consented to some scope, build the response model\n            if (Input.ScopesConsented.Any())\n            {\n                var scopes = Input.ScopesConsented;\n                if (ConsentOptions.EnableOfflineAccess == false)\n                {\n                    scopes = scopes.Where(x => x != Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess);\n                }\n\n                grantedConsent = new ConsentResponse\n                {\n                    RememberConsent = Input.RememberConsent,\n                    ScopesValuesConsented = scopes.ToArray(),\n                    Description = Input.Description\n                };\n\n                // emit event\n                await _events.RaiseAsync(new ConsentGrantedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues, grantedConsent.ScopesValuesConsented, grantedConsent.RememberConsent));\n                Telemetry.Metrics.ConsentGranted(request.Client.ClientId, grantedConsent.ScopesValuesConsented, grantedConsent.RememberConsent);\n                var denied = request.ValidatedResources.ParsedScopes.Select(s => s.ParsedName).Except(grantedConsent.ScopesValuesConsented);\n                Telemetry.Metrics.ConsentDenied(request.Client.ClientId, denied);\n            }\n            else\n            {\n                ModelState.AddModelError(\"\", ConsentOptions.MustChooseOneErrorMessage);\n            }\n        }\n        else\n        {\n            ModelState.AddModelError(\"\", ConsentOptions.InvalidSelectionErrorMessage);\n        }\n\n        if (grantedConsent != null)\n        {\n            // communicate outcome of consent back to identityserver\n            await _interaction.HandleRequestAsync(Input.UserCode, grantedConsent);\n\n            // indicate that's it ok to redirect back to authorization endpoint\n            return RedirectToPage(\"/Device/Success\");\n        }\n\n        // we need to redisplay the consent UI\n        if (!await SetViewModelAsync(Input.UserCode))\n        {\n            return RedirectToPage(\"/Home/Error/Index\");\n        }\n        return Page();\n    }\n\n\n    private async Task<bool> SetViewModelAsync(string userCode)\n    {\n        var request = await _interaction.GetAuthorizationContextAsync(userCode);\n        if (request != null)\n        {\n            View = CreateConsentViewModel(request);\n            return true;\n        }\n        else\n        {\n            View = new ViewModel();\n            return false;\n        }\n    }\n\n    private ViewModel CreateConsentViewModel(DeviceFlowAuthorizationRequest request)\n    {\n        var vm = new ViewModel\n        {\n            ClientName = request.Client.ClientName ?? request.Client.ClientId,\n            ClientUrl = request.Client.ClientUri,\n            ClientLogoUrl = request.Client.LogoUri,\n            AllowRememberConsent = request.Client.AllowRememberConsent\n        };\n\n        vm.IdentityScopes = request.ValidatedResources.Resources.IdentityResources.Select(x => CreateScopeViewModel(x, Input == null || Input.ScopesConsented.Contains(x.Name))).ToArray();\n\n        var apiScopes = new List<ScopeViewModel>();\n        foreach (var parsedScope in request.ValidatedResources.ParsedScopes)\n        {\n            var apiScope = request.ValidatedResources.Resources.FindApiScope(parsedScope.ParsedName);\n            if (apiScope != null)\n            {\n                var scopeVm = CreateScopeViewModel(parsedScope, apiScope, Input == null || Input.ScopesConsented.Contains(parsedScope.RawValue));\n                apiScopes.Add(scopeVm);\n            }\n        }\n        if (DeviceOptions.EnableOfflineAccess && request.ValidatedResources.Resources.OfflineAccess)\n        {\n            apiScopes.Add(GetOfflineAccessScope(Input == null || Input.ScopesConsented.Contains(Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess)));\n        }\n        vm.ApiScopes = apiScopes;\n\n        return vm;\n    }\n\n    private static ScopeViewModel CreateScopeViewModel(IdentityResource identity, bool check)\n    {\n        return new ScopeViewModel\n        {\n            Value = identity.Name,\n            DisplayName = identity.DisplayName ?? identity.Name,\n            Description = identity.Description,\n            Emphasize = identity.Emphasize,\n            Required = identity.Required,\n            Checked = check || identity.Required\n        };\n    }\n\n    private static ScopeViewModel CreateScopeViewModel(ParsedScopeValue parsedScopeValue, ApiScope apiScope, bool check)\n    {\n        return new ScopeViewModel\n        {\n            Value = parsedScopeValue.RawValue,\n            // todo: use the parsed scope value in the display?\n            DisplayName = apiScope.DisplayName ?? apiScope.Name,\n            Description = apiScope.Description,\n            Emphasize = apiScope.Emphasize,\n            Required = apiScope.Required,\n            Checked = check || apiScope.Required\n        };\n    }\n\n    private static ScopeViewModel GetOfflineAccessScope(bool check)\n    {\n        return new ScopeViewModel\n        {\n            Value = Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess,\n            DisplayName = DeviceOptions.OfflineAccessDisplayName,\n            Description = DeviceOptions.OfflineAccessDescription,\n            Emphasize = true,\n            Checked = check\n        };\n    }\n}\n"
  },
  {
    "path": "src/IdentityServer/Pages/Device/InputModel.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nnamespace IdentityServer.Pages.Device;\n\npublic class InputModel\n{\n    public string? Button { get; set; }\n    public IEnumerable<string> ScopesConsented { get; set; } = new List<string>();\n    public bool RememberConsent { get; set; } = true;\n    public string? ReturnUrl { get; set; }\n    public string? Description { get; set; }\n    public string? UserCode { get; set; }\n}\n"
  },
  {
    "path": "src/IdentityServer/Pages/Device/Success.cshtml",
    "content": "@page\n@model IdentityServer.Pages.Device.SuccessModel\n@{\n}\n\n\n<div class=\"page-device-success\">\n    <div class=\"lead\">\n        <h1>Success</h1>\n        <p>You have successfully authorized the device</p>\n    </div>\n</div>\n"
  },
  {
    "path": "src/IdentityServer/Pages/Device/Success.cshtml.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc.RazorPages;\n\nnamespace IdentityServer.Pages.Device;\n\n[SecurityHeaders]\n[Authorize]\npublic class SuccessModel : PageModel\n{\n    public void OnGet()\n    {\n    }\n}\n"
  },
  {
    "path": "src/IdentityServer/Pages/Device/ViewModel.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nnamespace IdentityServer.Pages.Device;\n\npublic class ViewModel\n{\n    public string? ClientName { get; set; }\n    public string? ClientUrl { get; set; }\n    public string? ClientLogoUrl { get; set; }\n    public bool AllowRememberConsent { get; set; }\n\n    public IEnumerable<ScopeViewModel> IdentityScopes { get; set; } = Enumerable.Empty<ScopeViewModel>();\n    public IEnumerable<ScopeViewModel> ApiScopes { get; set; } = Enumerable.Empty<ScopeViewModel>();\n}\n\npublic class ScopeViewModel\n{\n    public string? Value { get; set; }\n    public string? DisplayName { get; set; }\n    public string? Description { get; set; }\n    public bool Emphasize { get; set; }\n    public bool Required { get; set; }\n    public bool Checked { get; set; }\n}\n"
  },
  {
    "path": "src/IdentityServer/Pages/Device/_ScopeListItem.cshtml",
    "content": "@using IdentityServer.Pages.Device\n@model ScopeViewModel\n\n<li class=\"list-group-item\">\n    <label>\n        <input class=\"consent-scopecheck\"\n               type=\"checkbox\"\n               name=\"Input.ScopesConsented\"\n               id=\"scopes_@Model.Value\"\n               value=\"@Model.Value\"\n               checked=\"@Model.Checked\"\n               disabled=\"@Model.Required\" />\n        @if (Model.Required)\n        {\n            <input type=\"hidden\"\n                   name=\"Input.ScopesConsented\"\n                   value=\"@Model.Value\" />\n        }\n        <strong>@Model.DisplayName</strong>\n        @if (Model.Emphasize)\n        {\n            <span class=\"glyphicon glyphicon-exclamation-sign\"></span>\n        }\n    </label>\n    @if (Model.Required)\n    {\n        <span><em>(required)</em></span>\n    }\n    @if (Model.Description != null)\n    {\n        <div class=\"consent-description\">\n            <label for=\"scopes_@Model.Value\">@Model.Description</label>\n        </div>\n    }\n</li>"
  },
  {
    "path": "src/IdentityServer/Pages/Diagnostics/Index.cshtml",
    "content": "@page\n@model IdentityServer.Pages.Diagnostics.Index\n\n<div class=\"diagnostics-page\">\n    <div class=\"lead\">\n        <h1>Authentication Cookie</h1>\n    </div>\n\n    <div class=\"row\">\n        <div class=\"col\">\n            <div class=\"card\">\n                <div class=\"card-header\">\n                    <h2>Claims</h2>\n                </div>\n                <div class=\"card-body\">\n                    @if(Model.View.AuthenticateResult.Principal != null)\n                    {\n                        <dl>\n                            @foreach (var claim in Model.View.AuthenticateResult.Principal.Claims)\n                            {\n                                <dt>@claim.Type</dt>\n                                <dd>@claim.Value</dd>\n                            }\n                        </dl>\n                    }\n                </div>\n            </div>\n        </div>\n        \n        <div class=\"col\">\n            <div class=\"card\">\n                <div class=\"card-header\">\n                    <h2>Properties</h2>\n                </div>\n                <div class=\"card-body\">\n                    <dl>\n                        @if (Model.View.AuthenticateResult.Properties != null)\n                        {\n                            @foreach (var prop in Model.View.AuthenticateResult.Properties.Items)\n                            {\n                                <dt>@prop.Key</dt>\n                                <dd>@prop.Value</dd>\n                            }\n                        }\n                        @if (Model.View.Clients.Any())\n                        {\n                            <dt>Clients</dt>\n                            <dd>\n                                @{\n                                    var clients = Model.View.Clients.ToArray();\n                                    for(var i = 0; i < clients.Length; i++)\n                                    {\n                                        <text>@clients[i]</text>\n                                        if (i < clients.Length - 1)\n                                        {\n                                            <text>, </text>\n                                        }\n                                    }\n                                }\n                            </dd>\n                        }\n                    </dl>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "src/IdentityServer/Pages/Diagnostics/Index.cshtml.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing Microsoft.AspNetCore.Authentication;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.AspNetCore.Mvc.RazorPages;\nusing Microsoft.AspNetCore.Authorization;\n\nnamespace IdentityServer.Pages.Diagnostics;\n\n[SecurityHeaders]\n[Authorize]\npublic class Index : PageModel\n{\n    public ViewModel View { get; set; } = default!;\n\n    public async Task<IActionResult> OnGet()\n    {\n        var localAddresses = new List<string?> { \"127.0.0.1\", \"::1\" };\n        if(HttpContext.Connection.LocalIpAddress != null)\n        {\n            localAddresses.Add(HttpContext.Connection.LocalIpAddress.ToString());\n        }\n\n        if (!localAddresses.Contains(HttpContext.Connection.RemoteIpAddress?.ToString()))\n        {\n            return NotFound();\n        }\n\n        View = new ViewModel(await HttpContext.AuthenticateAsync());\n            \n        return Page();\n    }\n}\n"
  },
  {
    "path": "src/IdentityServer/Pages/Diagnostics/ViewModel.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing IdentityModel;\nusing Microsoft.AspNetCore.Authentication;\nusing System.Text;\nusing System.Text.Json;\n\nnamespace IdentityServer.Pages.Diagnostics;\n\npublic class ViewModel\n{\n    public ViewModel(AuthenticateResult result)\n    {\n        AuthenticateResult = result;\n\n        if (result?.Properties?.Items.TryGetValue(\"client_list\", out var encoded) == true)\n        {\n            if (encoded != null)\n            {\n                var bytes = Base64Url.Decode(encoded);\n                var value = Encoding.UTF8.GetString(bytes);\n                Clients = JsonSerializer.Deserialize<string[]>(value) ?? Enumerable.Empty<string>();\n                return;\n            }\n        }\n        Clients = Enumerable.Empty<string>();\n    }\n\n    public AuthenticateResult AuthenticateResult { get; }\n    public IEnumerable<string> Clients { get; }\n}"
  },
  {
    "path": "src/IdentityServer/Pages/Extensions.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing Duende.IdentityServer.Models;\nusing Microsoft.AspNetCore.Authentication;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.AspNetCore.Mvc.RazorPages;\n\nnamespace IdentityServer.Pages;\n\npublic static class Extensions\n{\n    /// <summary>\n    /// Determines if the authentication scheme support signout.\n    /// </summary>\n    internal static async Task<bool> GetSchemeSupportsSignOutAsync(this HttpContext context, string scheme)\n    {\n        var provider = context.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();\n        var handler = await provider.GetHandlerAsync(context, scheme);\n        return (handler is IAuthenticationSignOutHandler);\n    }\n\n    /// <summary>\n    /// Checks if the redirect URI is for a native client.\n    /// </summary>\n    internal static bool IsNativeClient(this AuthorizationRequest context)\n    {\n        return !context.RedirectUri.StartsWith(\"https\", StringComparison.Ordinal)\n               && !context.RedirectUri.StartsWith(\"http\", StringComparison.Ordinal);\n    }\n\n    /// <summary>\n    /// Renders a loading page that is used to redirect back to the redirectUri.\n    /// </summary>\n    internal static IActionResult LoadingPage(this PageModel page, string? redirectUri)\n    {\n        page.HttpContext.Response.StatusCode = 200;\n        page.HttpContext.Response.Headers[\"Location\"] = \"\";\n\n        return page.RedirectToPage(\"/Redirect/Index\", new { RedirectUri = redirectUri });\n    }\n}"
  },
  {
    "path": "src/IdentityServer/Pages/ExternalLogin/Callback.cshtml",
    "content": "@page\n@model IdentityServer.Pages.ExternalLogin.Callback\n\n@{\n    Layout = null;\n}\n\n<!DOCTYPE html>\n\n<html>\n<head>\n    <title></title>\n</head>\n<body>\n<div>\n    \n</div>\n</body>\n</html>"
  },
  {
    "path": "src/IdentityServer/Pages/ExternalLogin/Callback.cshtml.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing System.Security.Claims;\nusing Duende.IdentityServer;\nusing Duende.IdentityServer.Events;\nusing Duende.IdentityServer.Services;\nusing Duende.IdentityServer.Test;\nusing IdentityModel;\nusing Microsoft.AspNetCore.Authentication;\nusing Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.AspNetCore.Mvc.RazorPages;\n\nnamespace IdentityServer.Pages.ExternalLogin;\n\n[AllowAnonymous]\n[SecurityHeaders]\npublic class Callback : PageModel\n{\n    private readonly TestUserStore _users;\n    private readonly IIdentityServerInteractionService _interaction;\n    private readonly ILogger<Callback> _logger;\n    private readonly IEventService _events;\n\n    public Callback(\n        IIdentityServerInteractionService interaction,\n        IEventService events,\n        ILogger<Callback> logger,\n        TestUserStore? users = null)\n    {\n        // this is where you would plug in your own custom identity management library (e.g. ASP.NET Identity)\n        _users = users ?? throw new InvalidOperationException(\"Please call 'AddTestUsers(TestUsers.Users)' on the IIdentityServerBuilder in Startup or remove the TestUserStore from the AccountController.\");\n\n        _interaction = interaction;\n        _logger = logger;\n        _events = events;\n    }\n        \n    public async Task<IActionResult> OnGet()\n    {\n        // read external identity from the temporary cookie\n        var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);\n        if (result.Succeeded != true)\n        {\n            throw new InvalidOperationException($\"External authentication error: { result.Failure }\");\n        }\n\n        var externalUser = result.Principal ?? \n            throw new InvalidOperationException(\"External authentication produced a null Principal\");\n\t\t\n        if (_logger.IsEnabled(LogLevel.Debug))\n        {\n            var externalClaims = externalUser.Claims.Select(c => $\"{c.Type}: {c.Value}\");\n            _logger.ExternalClaims(externalClaims);\n        }\n\n        // lookup our user and external provider info\n        // try to determine the unique id of the external user (issued by the provider)\n        // the most common claim type for that are the sub claim and the NameIdentifier\n        // depending on the external provider, some other claim type might be used\n        var userIdClaim = externalUser.FindFirst(JwtClaimTypes.Subject) ??\n                          externalUser.FindFirst(ClaimTypes.NameIdentifier) ??\n                          throw new InvalidOperationException(\"Unknown userid\");\n\n        var provider = result.Properties.Items[\"scheme\"] ?? throw new InvalidOperationException(\"Null scheme in authentiation properties\");\n        var providerUserId = userIdClaim.Value;\n\n        // find external user\n        var user = _users.FindByExternalProvider(provider, providerUserId);\n        if (user == null)\n        {\n            // this might be where you might initiate a custom workflow for user registration\n            // in this sample we don't show how that would be done, as our sample implementation\n            // simply auto-provisions new external user\n            //\n            // remove the user id claim so we don't include it as an extra claim if/when we provision the user\n            var claims = externalUser.Claims.ToList();\n            claims.Remove(userIdClaim);\n            user = _users.AutoProvisionUser(provider, providerUserId, claims.ToList());\n        }\n\n        // this allows us to collect any additional claims or properties\n        // for the specific protocols used and store them in the local auth cookie.\n        // this is typically used to store data needed for signout from those protocols.\n        var additionalLocalClaims = new List<Claim>();\n        var localSignInProps = new AuthenticationProperties();\n        CaptureExternalLoginContext(result, additionalLocalClaims, localSignInProps);\n            \n        // issue authentication cookie for user\n        var isuser = new IdentityServerUser(user.SubjectId)\n        {\n            DisplayName = user.Username,\n            IdentityProvider = provider,\n            AdditionalClaims = additionalLocalClaims\n        };\n\n        await HttpContext.SignInAsync(isuser, localSignInProps);\n\n        // delete temporary cookie used during external authentication\n        await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);\n\n        // retrieve return URL\n        var returnUrl = result.Properties.Items[\"returnUrl\"] ?? \"~/\";\n\n        // check if external login is in the context of an OIDC request\n        var context = await _interaction.GetAuthorizationContextAsync(returnUrl);\n        await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.SubjectId, user.Username, true, context?.Client.ClientId));\n        Telemetry.Metrics.UserLogin(context?.Client.ClientId, provider!);\n\n        if (context != null)\n        {\n            if (context.IsNativeClient())\n            {\n                // The client is native, so this change in how to\n                // return the response is for better UX for the end user.\n                return this.LoadingPage(returnUrl);\n            }\n        }\n\n        return Redirect(returnUrl);\n    }\n\n    // if the external login is OIDC-based, there are certain things we need to preserve to make logout work\n    // this will be different for WS-Fed, SAML2p or other protocols\n    private static void CaptureExternalLoginContext(AuthenticateResult externalResult, List<Claim> localClaims, AuthenticationProperties localSignInProps)\n    {\n        ArgumentNullException.ThrowIfNull(externalResult.Principal, nameof(externalResult.Principal));\n\n        // capture the idp used to login, so the session knows where the user came from\n        localClaims.Add(new Claim(JwtClaimTypes.IdentityProvider, externalResult.Properties?.Items[\"scheme\"] ?? \"unknown identity provider\"));\n\n        // if the external system sent a session id claim, copy it over\n        // so we can use it for single sign-out\n        var sid = externalResult.Principal.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.SessionId);\n        if (sid != null)\n        {\n            localClaims.Add(new Claim(JwtClaimTypes.SessionId, sid.Value));\n        }\n\n        // if the external provider issued an id_token, we'll keep it for signout\n        var idToken = externalResult.Properties?.GetTokenValue(\"id_token\");\n        if (idToken != null)\n        {\n            localSignInProps.StoreTokens(new[] { new AuthenticationToken { Name = \"id_token\", Value = idToken } });\n        }\n    }\n}\n"
  },
  {
    "path": "src/IdentityServer/Pages/ExternalLogin/Challenge.cshtml",
    "content": "@page\n@model IdentityServer.Pages.ExternalLogin.Challenge\n\n@{\n    Layout = null;\n}\n\n<!DOCTYPE html>\n\n<html>\n<head>\n    <title></title>\n</head>\n<body>\n<div>\n    \n</div>\n</body>\n</html>"
  },
  {
    "path": "src/IdentityServer/Pages/ExternalLogin/Challenge.cshtml.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing Duende.IdentityServer.Services;\nusing Microsoft.AspNetCore.Authentication;\nusing Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.AspNetCore.Mvc.RazorPages;\n\nnamespace IdentityServer.Pages.ExternalLogin;\n\n[AllowAnonymous]\n[SecurityHeaders]\npublic class Challenge : PageModel\n{\n    private readonly IIdentityServerInteractionService _interactionService;\n\n    public Challenge(IIdentityServerInteractionService interactionService)\n    {\n        _interactionService = interactionService;\n    }\n        \n    public IActionResult OnGet(string scheme, string? returnUrl)\n    {\n        if (string.IsNullOrEmpty(returnUrl)) returnUrl = \"~/\";\n\n        // validate returnUrl - either it is a valid OIDC URL or back to a local page\n        if (Url.IsLocalUrl(returnUrl) == false && _interactionService.IsValidReturnUrl(returnUrl) == false)\n        {\n            // user might have clicked on a malicious link - should be logged\n            throw new ArgumentException(\"invalid return URL\");\n        }\n            \n        // start challenge and roundtrip the return URL and scheme \n        var props = new AuthenticationProperties\n        {\n            RedirectUri = Url.Page(\"/externallogin/callback\"),\n                \n            Items =\n            {\n                { \"returnUrl\", returnUrl }, \n                { \"scheme\", scheme },\n            }\n        };\n\n        return Challenge(props, scheme);\n    }\n}\n"
  },
  {
    "path": "src/IdentityServer/Pages/Grants/Index.cshtml",
    "content": "@page\n@model IdentityServer.Pages.Grants.Index\n@{\n}\n\n<div class=\"grants-page\">\n    <div class=\"lead\">\n        <h1>Client Application Permissions</h1>\n        <p>Below is the list of applications you have given permission to and the resources they have access to.</p>\n    </div>\n\n    @if (!Model.View.Grants.Any())\n    {\n        <div class=\"row\">\n            <div class=\"col-sm-8\">\n                <div class=\"alert alert-info\">\n                    You have not given access to any applications\n                </div>\n            </div>\n        </div>\n    }\n    else\n    {\n        foreach (var grant in Model.View.Grants) \n        {\n            <div class=\"card\">\n                <div class=\"card-header\">\n                    <div class=\"row\">\n                        <div class=\"col-sm-8 card-title\">\n                            @if (grant.ClientLogoUrl != null)\n                            {\n                                <img src=\"@grant.ClientLogoUrl\">\n                            }\n                            <strong>@grant.ClientName</strong>\n                        </div>\n\n                        <div class=\"col-sm-2\">\n                            <form asp-page=\"/Grants/Index\">\n                                <input type=\"hidden\" name=\"clientId\" value=\"@grant.ClientId\">\n                                <button class=\"btn btn-danger\">Revoke Access</button>\n                            </form>\n                        </div>\n                    </div>\n                </div>\n                \n                <ul class=\"list-group list-group-flush\">\n                    @if (grant.Description != null)\n                    {\n                        <li class=\"list-group-item\">\n                            <label>Description:</label> @grant.Description\n                        </li>   \n                    }\n                    <li class=\"list-group-item\">\n                        <label>Created:</label> @grant.Created.ToString(\"yyyy-MM-dd\")\n                    </li>\n                    @if (grant.Expires.HasValue)\n                    {\n                        <li class=\"list-group-item\">\n                            <label>Expires:</label> @grant.Expires.Value.ToString(\"yyyy-MM-dd\")\n                        </li>\n                    }\n                    @if (grant.IdentityGrantNames.Any())\n                    {\n                        <li class=\"list-group-item\">\n                            <label>Identity Grants</label>\n                            <ul>\n                                @foreach (var name in grant.IdentityGrantNames)\n                                {\n                                    <li>@name</li>\n                                }\n                            </ul>\n                        </li>\n                    }\n                    @if (grant.ApiGrantNames.Any())\n                    {\n                        <li class=\"list-group-item\">\n                            <label>API Grants</label>\n                            <ul>\n                                @foreach (var name in grant.ApiGrantNames)\n                                {\n                                    <li>@name</li>\n                                }\n                            </ul>\n                        </li>\n                    }\n                </ul>\n            </div>\n        }\n    }\n</div>"
  },
  {
    "path": "src/IdentityServer/Pages/Grants/Index.cshtml.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing Duende.IdentityServer.Events;\nusing Duende.IdentityServer.Extensions;\nusing Duende.IdentityServer.Services;\nusing Duende.IdentityServer.Stores;\nusing Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.AspNetCore.Mvc.RazorPages;\n\nnamespace IdentityServer.Pages.Grants;\n\n[SecurityHeaders]\n[Authorize]\npublic class Index : PageModel\n{\n    private readonly IIdentityServerInteractionService _interaction;\n    private readonly IClientStore _clients;\n    private readonly IResourceStore _resources;\n    private readonly IEventService _events;\n\n    public Index(IIdentityServerInteractionService interaction,\n        IClientStore clients,\n        IResourceStore resources,\n        IEventService events)\n    {\n        _interaction = interaction;\n        _clients = clients;\n        _resources = resources;\n        _events = events;\n    }\n\n    public ViewModel View { get; set; } = default!;\n        \n    public async Task OnGet()\n    {\n        var grants = await _interaction.GetAllUserGrantsAsync();\n\n        var list = new List<GrantViewModel>();\n        foreach (var grant in grants)\n        {\n            var client = await _clients.FindClientByIdAsync(grant.ClientId);\n            if (client != null)\n            {\n                var resources = await _resources.FindResourcesByScopeAsync(grant.Scopes);\n\n                var item = new GrantViewModel()\n                {\n                    ClientId = client.ClientId,\n                    ClientName = client.ClientName ?? client.ClientId,\n                    ClientLogoUrl = client.LogoUri,\n                    ClientUrl = client.ClientUri,\n                    Description = grant.Description,\n                    Created = grant.CreationTime, \n                    Expires = grant.Expiration,\n                    IdentityGrantNames = resources.IdentityResources.Select(x => x.DisplayName ?? x.Name).ToArray(),\n                    ApiGrantNames = resources.ApiScopes.Select(x => x.DisplayName ?? x.Name).ToArray()\n                };\n\n                list.Add(item);\n            }\n        }\n\n        View = new ViewModel\n        {\n            Grants = list\n        };\n    }\n\n    [BindProperty]\n    public string? ClientId { get; set; }\n\n    public async Task<IActionResult> OnPost()\n    {\n        await _interaction.RevokeUserConsentAsync(ClientId);\n        await _events.RaiseAsync(new GrantsRevokedEvent(User.GetSubjectId(), ClientId));\n        Telemetry.Metrics.GrantsRevoked(ClientId);\n\n        return RedirectToPage(\"/Grants/Index\");\n    }\n}\n"
  },
  {
    "path": "src/IdentityServer/Pages/Grants/ViewModel.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nnamespace IdentityServer.Pages.Grants;\n\npublic class ViewModel\n{\n    public IEnumerable<GrantViewModel> Grants { get; set; } = Enumerable.Empty<GrantViewModel>();\n}\n\npublic class GrantViewModel\n{\n    public string? ClientId { get; set; }\n    public string? ClientName { get; set; }\n    public string? ClientUrl { get; set; }\n    public string? ClientLogoUrl { get; set; }\n    public string? Description { get; set; }\n    public DateTime Created { get; set; }\n    public DateTime? Expires { get; set; }\n    public IEnumerable<string> IdentityGrantNames { get; set; } = Enumerable.Empty<string>();\n    public IEnumerable<string> ApiGrantNames { get; set; } = Enumerable.Empty<string>();\n}\n"
  },
  {
    "path": "src/IdentityServer/Pages/Home/Error/Index.cshtml",
    "content": "@page\n@model IdentityServer.Pages.Error.Index\n\n<div class=\"error-page\">\n    <div class=\"lead\">\n        <h1>Error</h1>\n    </div>\n\n    <div class=\"row\">\n        <div class=\"col-sm-6\">\n            <div class=\"alert alert-danger\">\n                Sorry, there was an error\n\n                @if (Model.View.Error != null)\n                {\n                    <strong>\n                        <em>\n                            : @Model.View.Error.Error\n                        </em>\n                    </strong>\n\n                    if (Model.View.Error.ErrorDescription != null)\n                    {\n                        <div>@Model.View.Error.ErrorDescription</div>\n                    }\n                }\n            </div>\n\n            @if (Model?.View?.Error?.RequestId != null)\n            {\n                <div class=\"request-id\">Request Id: @Model.View.Error.RequestId</div>\n            }\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "src/IdentityServer/Pages/Home/Error/Index.cshtml.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing Duende.IdentityServer.Services;\nusing Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc.RazorPages;\n\nnamespace IdentityServer.Pages.Error;\n\n[AllowAnonymous]\n[SecurityHeaders]\npublic class Index : PageModel\n{\n    private readonly IIdentityServerInteractionService _interaction;\n    private readonly IWebHostEnvironment _environment;\n        \n    public ViewModel View { get; set; } = new();\n        \n    public Index(IIdentityServerInteractionService interaction, IWebHostEnvironment environment)\n    {\n        _interaction = interaction;\n        _environment = environment;\n    }\n        \n    public async Task OnGet(string? errorId)\n    {\n        // retrieve error details from identityserver\n        var message = await _interaction.GetErrorContextAsync(errorId);\n        if (message != null)\n        {\n            View.Error = message;\n\n            if (!_environment.IsDevelopment())\n            {\n                // only show in development\n                message.ErrorDescription = null;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/IdentityServer/Pages/Home/Error/ViewModel.cs",
    "content": "﻿// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing Duende.IdentityServer.Models;\n\nnamespace IdentityServer.Pages.Error;\n\npublic class ViewModel\n{\n    public ViewModel()\n    {\n    }\n\n    public ViewModel(string error)\n    {\n        Error = new ErrorMessage { Error = error };\n    }\n\n    public ErrorMessage? Error { get; set; }\n}"
  },
  {
    "path": "src/IdentityServer/Pages/IdentityServerSuppressions.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\n// This file is used by Code Analysis to maintain SuppressMessage\n// attributes that are applied to this project.\n// Project-level suppressions either have no target or are given\n// a specific target and scoped to a namespace, type, member, etc.\n\nusing System.Diagnostics.CodeAnalysis;\n\n// global/shared\n[assembly: SuppressMessage(\"Design\", \"CA1054:URI-like parameters should not be strings\", Justification = \"Consistent with the IdentityServer APIs\")]\n[assembly: SuppressMessage(\"Design\", \"CA1056:URI-like properties should not be strings\", Justification = \"Consistent with the IdentityServer APIs\")]\n[assembly: SuppressMessage(\"Reliability\", \"CA2007:Consider calling ConfigureAwait on the awaited task\", Justification = \"No need for ConfigureAwait in ASP.NET Core application code, as there is no SynchronizationContext.\")]\n\n// page specific\n[assembly: SuppressMessage(\"Design\", \"CA1002:Do not expose generic lists\", Justification = \"TestUsers are not designed to be extended\", Scope = \"member\", Target = \"~P:IdentityServer.TestUsers.Users\")]\n[assembly: SuppressMessage(\"Design\", \"CA1034:Nested types should not be visible\", Justification = \"ExternalProvider is nested by design\", Scope = \"type\", Target = \"~T:IdentityServer.Pages.Login.ViewModel.ExternalProvider\")]\n[assembly: SuppressMessage(\"Naming\", \"CA1716:Identifiers should not match keywords\", Justification = \"This namespace is just for organization, and won't be referenced elsewhere\", Scope = \"namespace\", Target = \"~N:IdentityServer.Pages.Error\")]\n[assembly: SuppressMessage(\"Naming\", \"CA1724:Type names should not match namespaces\", Justification = \"Namespaces of pages are not likely to be used elsewhere, so there is little chance of confusion\", Scope = \"type\", Target = \"~T:IdentityServer.Pages.Ciba.Consent\")]\n[assembly: SuppressMessage(\"Naming\", \"CA1724:Type names should not match namespaces\", Justification = \"Namespaces of pages are not likely to be used elsewhere, so there is little chance of confusion\", Scope = \"type\", Target = \"~T:IdentityServer.Pages.Extensions\")]\n[assembly: SuppressMessage(\"Performance\", \"CA1805:Do not initialize unnecessarily\", Justification = \"This is for clarity and consistency with the surrounding code\", Scope = \"member\", Target = \"~F:IdentityServer.Pages.Logout.LogoutOptions.AutomaticRedirectAfterSignOut\")]\n"
  },
  {
    "path": "src/IdentityServer/Pages/Index.cshtml",
    "content": "@page\n@model IdentityServer.Pages.Home.Index\n\n<div class=\"welcome-page\">\n    <h1>\n        <img src=\"~/duende-logo.svg\" class=\"logo\">\n        Welcome to Duende IdentityServer\n        <small class=\"text-muted\">(version @Model.Version)</small>\n    </h1>\n\n    <ul>\n        <li>\n            IdentityServer publishes a\n            <a href=\"~/.well-known/openid-configuration\">discovery document</a>\n            where you can find metadata and links to all the endpoints, key material, etc.\n        </li>\n        <li>\n            Click <a href=\"~/diagnostics\">here</a> to see the claims for your current session.\n        </li>\n        <li>\n            Click <a href=\"~/grants\">here</a> to manage your stored grants.\n        </li>\n        <li>\n            Click <a href=\"~/serversidesessions\">here</a> to view the server side sessions.\n        </li>\n        <li>\n            Click <a href=\"~/ciba/all\">here</a> to view your pending CIBA login requests.\n        </li>\n        <li>\n            Here are links to the\n            <a href=\"https://github.com/duendesoftware/IdentityServer\">source code repository</a>,\n            and <a href=\"https://github.com/duendesoftware/samples\">ready to use samples</a>.\n        </li>\n    </ul>\n\n    @if(Model.License != null)\n    {\n        <h2>License</h2>\n        <dl>\n            <dt>Serial Number</dt>\n            <dd>@Model.License.SerialNumber</dd>\n            <dt>Expiration</dt>\n            <dd>@Model.License.Expiration!.Value.ToLongDateString()</dd>\n        </dl>\n    }\n</div>\n"
  },
  {
    "path": "src/IdentityServer/Pages/Index.cshtml.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing Duende.IdentityServer;\nusing System.Reflection;\nusing Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc.RazorPages;\n\nnamespace IdentityServer.Pages.Home;\n\n[AllowAnonymous]\npublic class Index : PageModel\n{\n    public Index(IdentityServerLicense? license = null)\n    {\n        License = license;\n    }\n\n    public string Version\n    {\n        get => typeof(Duende.IdentityServer.Hosting.IdentityServerMiddleware).Assembly\n            .GetCustomAttribute<AssemblyInformationalVersionAttribute>()\n            ?.InformationalVersion.Split('+').First()\n            ?? \"unavailable\";\n    }\n    public IdentityServerLicense? License { get; }\n}\n"
  },
  {
    "path": "src/IdentityServer/Pages/Log.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nnamespace IdentityServer.Pages;\n\ninternal static class Log\n{\n\tprivate static readonly Action<ILogger, string?, Exception?> _invalidId = LoggerMessage.Define<string?>(\n\t    LogLevel.Error,\n\t    EventIds.InvalidId,\n\t    \"Invalid id {Id}\");\n\n    public static void InvalidId(this ILogger logger, string? id)\n    {\n        _invalidId(logger, id, null);\n    }\n\n\tprivate static readonly Action<ILogger, string?, Exception?> _invalidBackchannelLoginId = LoggerMessage.Define<string?>(\n\tLogLevel.Warning,\n\tEventIds.InvalidBackchannelLoginId,\n\t\"Invalid backchannel login id {Id}\");\n\n\tpublic static void InvalidBackchannelLoginId(this ILogger logger, string? id)\n\t{\n\t\t_invalidBackchannelLoginId(logger, id, null);\n\t}\n\n\tprivate static Action<ILogger, IEnumerable<string>, Exception?> _externalClaims = LoggerMessage.Define<IEnumerable<string>>(\n\t\tLogLevel.Debug,\n\t\tEventIds.ExternalClaims,\n\t\t\"External claims: {Claims}\");\n\n\tpublic static void ExternalClaims(this ILogger logger, IEnumerable<string> claims) \n\t{ \n\t\t_externalClaims(logger, claims, null);\n\t}\n\n\tprivate static Action<ILogger, string, Exception?> _noMatchingBackchannelLoginRequest = LoggerMessage.Define<string>(\n\t\tLogLevel.Error,\n\t\tEventIds.NoMatchingBackchannelLoginRequest,\n\t\t\"No backchannel login request matching id: {Id}\");\n\n\tpublic static void NoMatchingBackchannelLoginRequest(this ILogger logger, string id) \n\t{ \n\t\t_noMatchingBackchannelLoginRequest(logger, id, null);\n\t}\n\n\tprivate static Action<ILogger, string, Exception?> _noConsentMatchingRequest = LoggerMessage.Define<string>(\n\t\tLogLevel.Error,\n\t\tEventIds.NoConsentMatchingRequest,\n\t\t\"No consent request matching request: {ReturnUrl}\");\n\n\tpublic static void NoConsentMatchingRequest(this ILogger logger, string returnUrl)\n\t{\n\t\t_noConsentMatchingRequest(logger, returnUrl, null);\n\t}\n\n\n}\n\ninternal static class EventIds\n{\n\tprivate const int UIEventsStart = 10000;\n\n    //////////////////////////////\n    // Consent\n    //////////////////////////////\n    private const int ConsentEventsStart = UIEventsStart + 1000;\n    public const int InvalidId = ConsentEventsStart + 0;\n\tpublic const int NoConsentMatchingRequest = ConsentEventsStart + 1;\n\n\t//////////////////////////////\n\t// External Login\n\t//////////////////////////////\n\tprivate const int ExternalLoginEventsStart = UIEventsStart + 2000;\n    public const int ExternalClaims = ExternalLoginEventsStart + 0;\n\n\t//////////////////////////////\n    // CIBA\n\t//////////////////////////////\n\tprivate const int CibaEventsStart = UIEventsStart + 3000;\n\tpublic const int InvalidBackchannelLoginId = CibaEventsStart + 0;\n    public const int NoMatchingBackchannelLoginRequest = CibaEventsStart + 1;\n\n\n\n}\n"
  },
  {
    "path": "src/IdentityServer/Pages/Redirect/Index.cshtml",
    "content": "@page\n@model IdentityServer.Pages.Redirect.IndexModel\n@{\n}\n\n<div class=\"redirect-page\">\n    <div class=\"lead\">\n        <h1>You are now being returned to the application</h1>\n        <p>Once complete, you may close this tab.</p>\n    </div>\n</div>\n\n<meta http-equiv=\"refresh\" content=\"0;url=@Model.RedirectUri\" data-url=\"@Model.RedirectUri\">\n<script src=\"~/js/signin-redirect.js\"></script>\n"
  },
  {
    "path": "src/IdentityServer/Pages/Redirect/Index.cshtml.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.AspNetCore.Mvc.RazorPages;\n\nnamespace IdentityServer.Pages.Redirect;\n\n[AllowAnonymous]\npublic class IndexModel : PageModel\n{\n    public string? RedirectUri { get; set; }\n\n    public IActionResult OnGet(string? redirectUri)\n    {\n        if (!Url.IsLocalUrl(redirectUri))\n        {\n            return RedirectToPage(\"/Home/Error/Index\");\n        }\n\n        RedirectUri = redirectUri;\n        return Page();\n    }\n}\n"
  },
  {
    "path": "src/IdentityServer/Pages/SecurityHeadersAttribute.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing Microsoft.AspNetCore.Mvc.Filters;\nusing Microsoft.AspNetCore.Mvc.RazorPages;\n\nnamespace IdentityServer.Pages;\n\npublic sealed class SecurityHeadersAttribute : ActionFilterAttribute\n{\n    public override void OnResultExecuting(ResultExecutingContext context)\n    {\n        ArgumentNullException.ThrowIfNull(context, nameof(context));\n\n        var result = context.Result;\n        if (result is PageResult)\n        {\n            // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options\n            if (!context.HttpContext.Response.Headers.ContainsKey(\"X-Content-Type-Options\"))\n            {\n                context.HttpContext.Response.Headers.Append(\"X-Content-Type-Options\", \"nosniff\");\n            }\n\n            // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options\n            if (!context.HttpContext.Response.Headers.ContainsKey(\"X-Frame-Options\"))\n            {\n                context.HttpContext.Response.Headers.Append(\"X-Frame-Options\", \"DENY\");\n            }\n\n            // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy\n            var csp = \"default-src 'self'; object-src 'none'; frame-ancestors 'none'; sandbox allow-forms allow-same-origin allow-scripts; base-uri 'self';\";\n            // also consider adding upgrade-insecure-requests once you have HTTPS in place for production\n            //csp += \"upgrade-insecure-requests;\";\n            // also an example if you need client images to be displayed from twitter\n            // csp += \"img-src 'self' https://pbs.twimg.com;\";\n\n            // once for standards compliant browsers\n            if (!context.HttpContext.Response.Headers.ContainsKey(\"Content-Security-Policy\"))\n            {\n                context.HttpContext.Response.Headers.Append(\"Content-Security-Policy\", csp);\n            }\n            // and once again for IE\n            if (!context.HttpContext.Response.Headers.ContainsKey(\"X-Content-Security-Policy\"))\n            {\n                context.HttpContext.Response.Headers.Append(\"X-Content-Security-Policy\", csp);\n            }\n\n            // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy\n            var referrer_policy = \"no-referrer\";\n            if (!context.HttpContext.Response.Headers.ContainsKey(\"Referrer-Policy\"))\n            {\n                context.HttpContext.Response.Headers.Append(\"Referrer-Policy\", referrer_policy);\n            }\n        }\n    }\n}"
  },
  {
    "path": "src/IdentityServer/Pages/ServerSideSessions/Index.cshtml",
    "content": "@page\n@model IdentityServer.Pages.ServerSideSessions.IndexModel\n\n    <div class=\"users-page\">\n        <div class=\"row\">\n            <div class=\"col\">\n                <div class=\"card\">\n                    <div class=\"card-header\">\n                        <h2>User Sessions</h2>\n                    </div>\n                \n                    <div class=\"card-body\">\n\n                    @if (Model.UserSessions != null)\n                    {\n                        <div class=\"row\">\n                            <div class=\"col-1 text-center\">\n                                @if (Model.UserSessions.HasPrevResults)\n                                {\n                                    <a class=\"btn btn-primary\" asp-page=\"/ServerSideSessions/Index\"\n                                         asp-route-prev=\"true\" \n                                         asp-route-token=\"@Model.UserSessions.ResultsToken\"\n                                         asp-route-DisplayNameFilter=\"@Model.DisplayNameFilter\"\n                                         asp-route-SubjectIdFilter=\"@Model.SubjectIdFilter\"\n                                         asp-route-SessionIdFilter=\"@Model.SessionIdFilter\"\n                                    >Prev</a>\n                                }\n                            </div>\n                            <div class=\"col\">\n                                <form class=\"form\">\n                                    <div class=\"form-group row\">\n                                        <label asp-for=\"@Model.DisplayNameFilter\" class=\"col-2 col-form-label\">Name:</label>\n                                        <input type=\"search\" asp-for=\"@Model.DisplayNameFilter\" class=\"col form-control\" autofocus />\n                                    </div>\n                                    <div class=\"form-group row\">\n                                        <label asp-for=\"@Model.SessionIdFilter\" class=\"col-2 col-form-label\">Session Id:</label>\n                                        <input type=\"search\" asp-for=\"@Model.SessionIdFilter\" class=\"col form-control\" autofocus />\n                                    </div>\n                                    <div class=\"form-group row\">\n                                        <label asp-for=\"@Model.SubjectIdFilter\" class=\"col-2 col-form-label\">Subject Id:</label>\n                                        <input type=\"search\" asp-for=\"@Model.SubjectIdFilter\" class=\"col form-control\" autofocus />\n                                    </div>\n                                    <div class=\"form-group row justify-content-end\">\n                                        <button type=\"submit\" class=\"form-control btn btn-success col-1\">Filter</button>\n                                    </div>\n                                </form>\n                            </div>\n                            <div class=\"col-1 text-center\">\n                                @if (Model.UserSessions.HasNextResults)\n                                {\n                                    <a class=\"btn btn-primary\" asp-page=\"/ServerSideSessions/Index\"\n                                         asp-route-token=\"@Model.UserSessions.ResultsToken\"\n                                         asp-route-DisplayNameFilter=\"@Model.DisplayNameFilter\"\n                                         asp-route-SubjectIdFilter=\"@Model.SubjectIdFilter\"\n                                         asp-route-SessionIdFilter=\"@Model.SessionIdFilter\"\n                                    >Next</a>\n                                }\n                            </div>\n                        </div>\n\n                        @if (Model.UserSessions.TotalCount.HasValue)\n                        {\n                            <div class=\"text-center\">\n                                @if (Model.UserSessions.CurrentPage.HasValue && Model.UserSessions.TotalPages.HasValue)\n                                {\n                                    <text>\n                                        Total Results: @Model.UserSessions.TotalCount,\n                                        Page @Model.UserSessions.CurrentPage of @Model.UserSessions.TotalPages\n                                    </text>\n                                }\n                                else\n                                {\n                                    <text>\n                                        Total Results: @Model.UserSessions.TotalCount\n                                    </text>\n                                }\n                            </div>\n                        }\n\n                        <br />\n                    \n                        @if (Model.UserSessions.Results.Any())\n                        {\n                            <div>\n                                <table class=\"table table-bordered table-striped table-sm\">\n                                    <thead>\n                                        <tr>\n                                            <th>Subject Id</th>\n                                            <th>Session Id</th>\n                                            <th>Display Name</th>\n                                            <th>Created</th>\n                                            <th>Expires</th>\n                                            <th></th>\n                                        </tr>\n                                    </thead>\n                                    <tbody>\n                                        @foreach (var session in Model.UserSessions.Results)\n                                        {\n                                            <tr>\n                                                <td>@session.SubjectId</td>\n                                                <td>@session.SessionId</td>\n                                                <td>@session.DisplayName</td>\n                                                <td>@session.Created</td>\n                                                <td>@session.Expires</td>\n                                                <td>\n                                                    <form method=\"post\">\n                                                        <input type=\"hidden\" name=\"SessionId\" value=\"@session.SessionId\" />\n                                                        <button type=\"submit\" class=\"btn btn-danger\">Delete</button>\n                                                    </form>\n                                                </td>\n                                            </tr>\n                                            <tr><td colspan=\"6\">\n                                                <strong>Clients:</strong>\n                                                @if (session.ClientIds?.Any() == true)\n                                                {\n                                                    @(session.ClientIds.Aggregate((x, y) => $\"{x}, {y}\"))\n                                                }\n                                                else\n                                                {\n                                                    @(\"None\")\n                                                }\n                                            </td></tr>\n                                        }\n                                    </tbody>\n                                </table>\n                            </div>\n                        }\n                        else\n                        {\n                            <div class=\"text-center\">No User Sessions</div>\n                        }\n                    }\n                    else\n                    { \n                        <div class=\"row\">\n                            <div class=\"col\">\n                                You do not have server-side sessions enabled.\n                                To do so, use <i>AddServerSideSessions</i> on your IdentityServer configuration.\n                                See the <a href=\"https://docs.duendesoftware.com/identityserver/v6/ui/server_side_sessions\">documentation</a> for more information.\n                            </div>\n                        </div>\n                    }\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>"
  },
  {
    "path": "src/IdentityServer/Pages/ServerSideSessions/Index.cshtml.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing Duende.IdentityServer.Models;\nusing Duende.IdentityServer.Services;\nusing Duende.IdentityServer.Stores;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.AspNetCore.Mvc.RazorPages;\n\nnamespace IdentityServer.Pages.ServerSideSessions\n{\n    public class IndexModel : PageModel\n    {\n        private readonly ISessionManagementService? _sessionManagementService;\n\n        public IndexModel(ISessionManagementService? sessionManagementService = null)\n        {\n            _sessionManagementService = sessionManagementService;\n        }\n\n        public QueryResult<UserSession>? UserSessions { get; set; }\n\n        [BindProperty(SupportsGet = true)]\n        public string? DisplayNameFilter { get; set; }\n\n        [BindProperty(SupportsGet = true)]\n        public string? SessionIdFilter { get; set; }\n\n        [BindProperty(SupportsGet = true)]\n        public string? SubjectIdFilter { get; set; }\n\n        [BindProperty(SupportsGet = true)]\n        public string? Token { get; set; }\n\n        [BindProperty(SupportsGet = true)]\n        public string? Prev { get; set; }\n\n        public async Task OnGet()\n        {\n            if (_sessionManagementService != null)\n            {\n                UserSessions = await _sessionManagementService.QuerySessionsAsync(new SessionQuery\n                {\n                    ResultsToken = Token,\n                    RequestPriorResults = Prev == \"true\",\n                    DisplayName = DisplayNameFilter,\n                    SessionId = SessionIdFilter,\n                    SubjectId = SubjectIdFilter\n                });\n            }\n        }\n\n        [BindProperty]\n        public string? SessionId { get; set; }\n\n        public async Task<IActionResult> OnPost()\n        {\n            ArgumentNullException.ThrowIfNull(_sessionManagementService);\n\n            await _sessionManagementService.RemoveSessionsAsync(new RemoveSessionsContext { \n                SessionId = SessionId,\n            });\n            return RedirectToPage(\"/ServerSideSessions/Index\", new { Token, DisplayNameFilter, SessionIdFilter, SubjectIdFilter, Prev });\n        }\n    }\n}\n\n"
  },
  {
    "path": "src/IdentityServer/Pages/Shared/_Layout.cshtml",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, shrink-to-fit=no\" />\n\n    <title>Duende IdentityServer</title>\n    \n    <link rel=\"icon\" type=\"image/x-icon\" href=\"~/favicon.ico\" />\n    <link rel=\"shortcut icon\" type=\"image/x-icon\" href=\"~/favicon.ico\" />\n    \n    <link rel=\"stylesheet\" href=\"~/lib/bootstrap/dist/css/bootstrap.min.css\" />\n    <link rel=\"stylesheet\" href=\"~/lib/bootstrap4-glyphicons/css/bootstrap-glyphicons.min.css\" />\n    <link rel=\"stylesheet\" href=\"~/css/site.css\" />\n</head>\n<body>\n    <partial name=\"_Nav\" />\n   \n    <div class=\"container body-container\">\n        @RenderBody()\n    </div>\n\n    <script src=\"~/lib/jquery/dist/jquery.slim.min.js\"></script>\n    <script src=\"~/lib/bootstrap/dist/js/bootstrap.bundle.min.js\"></script>\n\n    @RenderSection(\"scripts\", required: false)\n</body>\n</html>\n"
  },
  {
    "path": "src/IdentityServer/Pages/Shared/_Nav.cshtml",
    "content": "@using Duende.IdentityServer.Extensions\n@{\n    #nullable enable\n    string? name = null;\n    if (!true.Equals(ViewData[\"signed-out\"]))\n    {\n        name = Context.User?.GetDisplayName();\n    }\n}\n\n<div class=\"nav-page\">\n    <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n\n        <a href=\"~/\" class=\"navbar-brand\">\n            <img src=\"~/duende-logo.svg\" class=\"icon-banner\">\n            Duende IdentityServer\n        </a>\n\n        @if (!string.IsNullOrWhiteSpace(name))\n        {\n            <ul class=\"navbar-nav mr-auto\">\n                <li class=\"nav-item dropdown\">\n                    <a href=\"#\" class=\"nav-link dropdown-toggle\" data-toggle=\"dropdown\">@name <b class=\"caret\"></b></a>\n                    \n                    <div class=\"dropdown-menu\">\n                        <a class=\"dropdown-item\" asp-page=\"/Account/Logout/Index\">Logout</a>\n                    </div>\n              </li>\n            </ul>\n        }\n    \n    </nav>\n</div>\n"
  },
  {
    "path": "src/IdentityServer/Pages/Shared/_ValidationSummary.cshtml",
    "content": "﻿@if (ViewContext.ModelState.IsValid == false)\n{\n    <div class=\"alert alert-danger\">\n        <strong>Error</strong>\n        <div asp-validation-summary=\"All\" class=\"danger\"></div>\n    </div>\n}"
  },
  {
    "path": "src/IdentityServer/Pages/Telemetry.cs",
    "content": "// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing System.Diagnostics.Metrics;\n\nnamespace IdentityServer.Pages;\n\n#pragma warning disable CA1034 // Nested types should not be visible\n#pragma warning disable CA1724 // Type names should not match namespaces\n\n/// <summary>\n/// Telemetry helpers for the UI\n/// </summary>\npublic static class Telemetry\n{\n    private static readonly string ServiceVersion = typeof(Telemetry).Assembly.GetName().Version!.ToString();\n    \n    /// <summary>\n    /// Service name for telemetry.\n    /// </summary>\n    public static readonly string ServiceName = typeof(Telemetry).Assembly.GetName().Name!;\n\n    /// <summary>\n    /// Metrics configuration\n    /// </summary>\n    public static class Metrics\n    {\n#pragma warning disable 1591\n\n        /// <summary>\n        /// Name of Counters\n        /// </summary>\n        public static class Counters\n        {\n            public const string Consent = \"tokenservice.consent\";\n            public const string GrantsRevoked = \"tokenservice.grants_revoked\";\n            public const string UserLogin = \"tokenservice.user_login\";\n            public const string UserLogout = \"tokenservice.user_logout\";\n        }\n\n        /// <summary>\n        /// Name of tags\n        /// </summary>\n        public static class Tags\n        {\n            public const string Client = \"client\";\n            public const string Error = \"error\";\n            public const string Idp = \"idp\";\n            public const string Remember = \"remember\";\n            public const string Scope = \"scope\";\n            public const string Consent = \"consent\";\n        }\n\n        /// <summary>\n        /// Values of tags\n        /// </summary>\n        public static class TagValues\n        {\n            public const string Granted = \"granted\";\n            public const string Denied = \"denied\";\n        }\n\n#pragma warning restore 1591\n\n        /// <summary>\n        /// Meter for the IdentityServer host project\n        /// </summary>\n        private static readonly Meter Meter = new Meter(ServiceName, ServiceVersion);\n\n        private static Counter<long> ConsentCounter = Meter.CreateCounter<long>(Counters.Consent);\n\n        /// <summary>\n        /// Helper method to increase <see cref=\"Counters.Consent\"/> counter. The scopes\n        /// are expanded and called one by one to not cause a combinatory explosion of scopes.\n        /// </summary>\n        /// <param name=\"clientId\">Client id</param>\n        /// <param name=\"scopes\">Scope names. Each element is added on it's own to the counter</param>\n        public static void ConsentGranted(string clientId, IEnumerable<string> scopes, bool remember)\n        {\n            ArgumentNullException.ThrowIfNull(scopes);\n\n            foreach (var scope in scopes)\n            {\n                ConsentCounter.Add(1,\n                    new(Tags.Client, clientId),\n                    new(Tags.Scope, scope),\n                    new(Tags.Remember, remember),\n                    new(Tags.Consent, TagValues.Granted));\n            }\n        }\n\n        /// <summary>\n        /// Helper method to increase <see cref=\"Counters.ConsentDenied\"/> counter. The scopes\n        /// are expanded and called one by one to not cause a combinatory explosion of scopes.\n        /// </summary>\n        /// <param name=\"clientId\">Client id</param>\n        /// <param name=\"scopes\">Scope names. Each element is added on it's own to the counter</param>\n        public static void ConsentDenied(string clientId, IEnumerable<string> scopes)\n        {\n            ArgumentNullException.ThrowIfNull(scopes);\n            foreach (var scope in scopes)\n            {\n                ConsentCounter.Add(1, new(Tags.Client, clientId), new(Tags.Scope, scope), new(Tags.Consent, TagValues.Denied));\n            }\n        }\n\n        private static Counter<long> GrantsRevokedCounter = Meter.CreateCounter<long>(Counters.GrantsRevoked);\n\n        /// <summary>\n        /// Helper method to increase the <see cref=\"Counters.GrantsRevoked\"/> counter.\n        /// </summary>\n        /// <param name=\"clientId\">Client id to revoke for, or null for all.</param>\n        public static void GrantsRevoked(string? clientId)\n            => GrantsRevokedCounter.Add(1, tag: new(Tags.Client, clientId));\n\n        private static Counter<long> UserLoginCounter = Meter.CreateCounter<long>(Counters.UserLogin);\n\n        /// <summary>\n        /// Helper method to increase <see cref=\"Counters.UserLogin\"/> counter.\n        /// </summary>\n        /// <param name=\"clientId\">Client Id, if available</param>\n        public static void UserLogin(string? clientId, string idp)\n            => UserLoginCounter.Add(1, new(Tags.Client, clientId), new(Tags.Idp, idp));\n\n        /// <summary>\n        /// Helper method to increase <see cref=\"Counters.UserLogin\" counter on failure.\n        /// </summary>\n        /// <param name=\"clientId\">Client Id, if available</param>\n        /// <param name=\"error\">Error message</param>\n        public static void UserLoginFailure(string? clientId, string idp, string error)\n            => UserLoginCounter.Add(1, new(Tags.Client, clientId), new(Tags.Idp, idp), new(Tags.Error, error));\n\n        private static Counter<long> UserLogoutCounter = Meter.CreateCounter<long>(Counters.UserLogout);\n\n        /// <summary>\n        /// Helper method to increase the <see cref=\"Counters.UserLogout\"/> counter.\n        /// </summary>\n        /// <param name=\"idp\">Idp/authentication scheme for external authentication, or \"local\" for built in.</param>\n        public static void UserLogout(string? idp)\n            => UserLogoutCounter.Add(1, tag: new(Tags.Idp, idp));\n    }\n}\n"
  },
  {
    "path": "src/IdentityServer/Pages/TestUsers.cs",
    "content": "﻿// Copyright (c) Duende Software. All rights reserved.\n// See LICENSE in the project root for license information.\n\nusing IdentityModel;\nusing System.Security.Claims;\nusing System.Text.Json;\nusing Duende.IdentityServer;\nusing Duende.IdentityServer.Test;\n\nnamespace IdentityServer;\n\npublic static class TestUsers\n{\n    public static List<TestUser> Users\n    {\n        get\n        {\n            var address = new\n            {\n                street_address = \"One Hacker Way\",\n                locality = \"Heidelberg\",\n                postal_code = \"69118\",\n                country = \"Germany\"\n            };\n                \n            return new List<TestUser>\n            {\n                new TestUser\n                {\n                    SubjectId = \"10000\",\n                    Username = \"alice\",\n                    Password = \"alice\",\n                    Claims =\n                    {\n                        new Claim(JwtClaimTypes.Name, \"Alice Smith\"),\n                        new Claim(JwtClaimTypes.GivenName, \"Alice\"),\n                        new Claim(JwtClaimTypes.FamilyName, \"Smith\"),\n                        new Claim(JwtClaimTypes.Email, \"AliceSmith@email.com\"),\n                        new Claim(JwtClaimTypes.EmailVerified, \"true\", ClaimValueTypes.Boolean),\n                        new Claim(JwtClaimTypes.WebSite, \"http://alice.com\"),\n                        new Claim(JwtClaimTypes.Address, JsonSerializer.Serialize(address), IdentityServerConstants.ClaimValueTypes.Json)\n                    }\n                },\n                new TestUser\n                {\n                    SubjectId = \"10001\",\n                    Username = \"bob\",\n                    Password = \"bob\",\n                    Claims =\n                    {\n                        new Claim(JwtClaimTypes.Name, \"Bob Smith\"),\n                        new Claim(JwtClaimTypes.GivenName, \"Bob\"),\n                        new Claim(JwtClaimTypes.FamilyName, \"Smith\"),\n                        new Claim(JwtClaimTypes.Email, \"BobSmith@email.com\"),\n                        new Claim(JwtClaimTypes.EmailVerified, \"true\", ClaimValueTypes.Boolean),\n                        new Claim(JwtClaimTypes.WebSite, \"http://bob.com\"),\n                        new Claim(JwtClaimTypes.Address, JsonSerializer.Serialize(address), IdentityServerConstants.ClaimValueTypes.Json),\n                        new Claim(JwtClaimTypes.Role, \"staff\"),\n                    }\n                }\n            };\n        }\n    }\n}\n"
  },
  {
    "path": "src/IdentityServer/Pages/_ViewImports.cshtml",
    "content": "﻿@using IdentityServer.Pages\n@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers\n"
  },
  {
    "path": "src/IdentityServer/Pages/_ViewStart.cshtml",
    "content": "﻿@{\n    Layout = \"_Layout\";\n}\n"
  },
  {
    "path": "src/IdentityServer/Program.cs",
    "content": "﻿using IdentityServer;\nusing Serilog;\n\nLog.Logger = new LoggerConfiguration()\n    .WriteTo.Console()\n    .CreateBootstrapLogger();\n\nLog.Information(\"Starting up\");\n\ntry\n{\n    var builder = WebApplication.CreateBuilder(args);\n\n    builder.AddServiceDefaults();\n\n    builder.Host.UseSerilog((ctx, lc) => lc\n        .WriteTo.Console(outputTemplate: \"[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}\")\n        .Enrich.FromLogContext()\n        .ReadFrom.Configuration(ctx.Configuration));\n\n    var app = builder\n        .ConfigureServices()\n        .ConfigurePipeline();\n    \n    app.Run();\n}\ncatch (Exception ex)\n{\n    Log.Fatal(ex, \"Unhandled exception\");\n}\nfinally\n{\n    Log.Information(\"Shut down complete\");\n    Log.CloseAndFlush();\n}\n"
  },
  {
    "path": "src/IdentityServer/Properties/launchSettings.json",
    "content": "{\n  \"profiles\": {\n    \"SelfHost\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      },\n      \"applicationUrl\": \"https://localhost:7275\"\n    }\n  }\n}"
  },
  {
    "path": "src/IdentityServer/appsettings.json",
    "content": "{\n    \"Serilog\": {\n        \"MinimumLevel\": {\n            \"Default\": \"Debug\",\n            \"Override\": {\n                \"Microsoft\": \"Warning\",\n                \"Microsoft.Hosting.Lifetime\": \"Information\",\n                \"Microsoft.AspNetCore.Authentication\": \"Debug\",\n                \"System\": \"Warning\"\n            }\n        }\n    }\n}"
  },
  {
    "path": "src/IdentityServer/wwwroot/css/site.css",
    "content": "﻿.welcome-page .logo {\n  width: 64px;\n}\n\n.icon-banner {\n  width: 32px;\n}\n\n.body-container {\n  margin-top: 60px;\n  padding-bottom: 40px;\n}\n\n.welcome-page li {\n  list-style: none;\n  padding: 4px;\n}\n\n.logged-out-page iframe {\n  display: none;\n  width: 0;\n  height: 0;\n}\n\n.grants-page .card {\n  margin-top: 20px;\n  border-bottom: 1px solid lightgray;\n}\n.grants-page .card .card-title {\n  font-size: 120%;\n  font-weight: bold;\n}\n.grants-page .card .card-title img {\n  width: 100px;\n  height: 100px;\n}\n.grants-page .card label {\n  font-weight: bold;\n}\n.test-users {\n    margin-top: 1rem;\n    background: #ddd;\n    padding: 0.6rem 1rem;\n    padding-bottom: 0.1rem;\n}\n"
  },
  {
    "path": "src/IdentityServer/wwwroot/css/site.scss",
    "content": ".welcome-page {\n  .logo {\n    width: 64px;\n  }\n}\n\n.icon-banner {\n  width: 32px;\n}\n\n.body-container {\n  margin-top: 60px;\n  padding-bottom: 40px;\n}\n\n.welcome-page {\n  li {\n    list-style: none;\n    padding: 4px;\n  }\n}\n\n.logged-out-page {\n  iframe {\n    display: none;\n    width: 0;\n    height: 0;\n  }\n}\n\n.grants-page {\n  .card {\n    margin-top: 20px;\n    border-bottom: 1px solid lightgray;\n\n    .card-title {\n      img {\n        width: 100px;\n        height: 100px;\n      }\n\n      font-size: 120%;\n      font-weight: bold;\n    }\n\n    label {\n      font-weight: bold;\n    }\n  }\n}\n\n.test-users {\n    margin-top: 1rem;\n    background: #ddd;\n    padding: 0.6rem 1rem;\n    padding-bottom: 0.1rem;\n}"
  },
  {
    "path": "src/IdentityServer/wwwroot/js/signin-redirect.js",
    "content": "window.location.href = document.querySelector(\"meta[http-equiv=refresh]\").getAttribute(\"data-url\");\n"
  },
  {
    "path": "src/IdentityServer/wwwroot/js/signout-redirect.js",
    "content": "﻿window.addEventListener(\"load\", function () {\n    var a = document.querySelector(\"a.PostLogoutRedirectUri\");\n    if (a) {\n        window.location = a.href;\n    }\n});\n"
  },
  {
    "path": "src/IdentityServer/wwwroot/lib/bootstrap/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2011-2020 Twitter, Inc.\nCopyright (c) 2011-2020 The Bootstrap Authors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "src/IdentityServer/wwwroot/lib/bootstrap/README.md",
    "content": "<p align=\"center\">\n  <a href=\"https://getbootstrap.com/\">\n    <img src=\"https://getbootstrap.com/docs/4.5/assets/brand/bootstrap-solid.svg\" alt=\"Bootstrap logo\" width=\"72\" height=\"72\">\n  </a>\n</p>\n\n<h3 align=\"center\">Bootstrap</h3>\n\n<p align=\"center\">\n  Sleek, intuitive, and powerful front-end framework for faster and easier web development.\n  <br>\n  <a href=\"https://getbootstrap.com/docs/4.5/\"><strong>Explore Bootstrap docs »</strong></a>\n  <br>\n  <br>\n  <a href=\"https://github.com/twbs/bootstrap/issues/new?template=bug_report.md\">Report bug</a>\n  ·\n  <a href=\"https://github.com/twbs/bootstrap/issues/new?template=feature_request.md\">Request feature</a>\n  ·\n  <a href=\"https://themes.getbootstrap.com/\">Themes</a>\n  ·\n  <a href=\"https://blog.getbootstrap.com/\">Blog</a>\n</p>\n\n\n## Table of contents\n\n- [Quick start](#quick-start)\n- [Status](#status)\n- [What's included](#whats-included)\n- [Bugs and feature requests](#bugs-and-feature-requests)\n- [Documentation](#documentation)\n- [Contributing](#contributing)\n- [Community](#community)\n- [Versioning](#versioning)\n- [Creators](#creators)\n- [Thanks](#thanks)\n- [Copyright and license](#copyright-and-license)\n\n\n## Quick start\n\nSeveral quick start options are available:\n\n- [Download the latest release.](https://github.com/twbs/bootstrap/archive/v4.5.3.zip)\n- Clone the repo: `git clone https://github.com/twbs/bootstrap.git`\n- Install with [npm](https://www.npmjs.com/): `npm install bootstrap`\n- Install with [yarn](https://yarnpkg.com/): `yarn add bootstrap@4.5.3`\n- Install with [Composer](https://getcomposer.org/): `composer require twbs/bootstrap:4.5.3`\n- Install with [NuGet](https://www.nuget.org/): CSS: `Install-Package bootstrap` Sass: `Install-Package bootstrap.sass`\n\nRead the [Getting started page](https://getbootstrap.com/docs/4.5/getting-started/introduction/) for information on the framework contents, templates and examples, and more.\n\n\n## Status\n\n[![Slack](https://bootstrap-slack.herokuapp.com/badge.svg)](https://bootstrap-slack.herokuapp.com/)\n[![Build Status](https://github.com/twbs/bootstrap/workflows/JS%20Tests/badge.svg?branch=v4-dev)](https://github.com/twbs/bootstrap/actions?query=workflow%3AJS+Tests+branch%3Av4-dev)\n[![npm version](https://img.shields.io/npm/v/bootstrap)](https://www.npmjs.com/package/bootstrap)\n[![Gem version](https://img.shields.io/gem/v/bootstrap)](https://rubygems.org/gems/bootstrap)\n[![Meteor Atmosphere](https://img.shields.io/badge/meteor-twbs%3Abootstrap-blue)](https://atmospherejs.com/twbs/bootstrap)\n[![Packagist Prerelease](https://img.shields.io/packagist/vpre/twbs/bootstrap)](https://packagist.org/packages/twbs/bootstrap)\n[![NuGet](https://img.shields.io/nuget/vpre/bootstrap)](https://www.nuget.org/packages/bootstrap/absoluteLatest)\n[![peerDependencies Status](https://img.shields.io/david/peer/twbs/bootstrap)](https://david-dm.org/twbs/bootstrap?type=peer)\n[![devDependency Status](https://img.shields.io/david/dev/twbs/bootstrap)](https://david-dm.org/twbs/bootstrap?type=dev)\n[![Coverage Status](https://img.shields.io/coveralls/github/twbs/bootstrap/v4-dev)](https://coveralls.io/github/twbs/bootstrap?branch=v4-dev)\n[![CSS gzip size](https://img.badgesize.io/twbs/bootstrap/v4-dev/dist/css/bootstrap.min.css?compression=gzip&label=CSS%20gzip%20size)](https://github.com/twbs/bootstrap/blob/v4-dev/dist/css/bootstrap.min.css)\n[![JS gzip size](https://img.badgesize.io/twbs/bootstrap/v4-dev/dist/js/bootstrap.min.js?compression=gzip&label=JS%20gzip%20size)](https://github.com/twbs/bootstrap/blob/v4-dev/dist/js/bootstrap.min.js)\n[![BrowserStack Status](https://www.browserstack.com/automate/badge.svg?badge_key=SkxZcStBeExEdVJqQ2hWYnlWckpkNmNEY213SFp6WHFETWk2bGFuY3pCbz0tLXhqbHJsVlZhQnRBdEpod3NLSDMzaHc9PQ==--3d0b75245708616eb93113221beece33e680b229)](https://www.browserstack.com/automate/public-build/SkxZcStBeExEdVJqQ2hWYnlWckpkNmNEY213SFp6WHFETWk2bGFuY3pCbz0tLXhqbHJsVlZhQnRBdEpod3NLSDMzaHc9PQ==--3d0b75245708616eb93113221beece33e680b229)\n[![Backers on Open Collective](https://img.shields.io/opencollective/backers/bootstrap)](#backers)\n[![Sponsors on Open Collective](https://img.shields.io/opencollective/sponsors/bootstrap)](#sponsors)\n\n\n## What's included\n\nWithin the download you'll find the following directories and files, logically grouping common assets and providing both compiled and minified variations. You'll see something like this:\n\n```text\nbootstrap/\n└── dist/\n    ├── css/\n    │   ├── bootstrap-grid.css\n    │   ├── bootstrap-grid.css.map\n    │   ├── bootstrap-grid.min.css\n    │   ├── bootstrap-grid.min.css.map\n    │   ├── bootstrap-reboot.css\n    │   ├── bootstrap-reboot.css.map\n    │   ├── bootstrap-reboot.min.css\n    │   ├── bootstrap-reboot.min.css.map\n    │   ├── bootstrap.css\n    │   ├── bootstrap.css.map\n    │   ├── bootstrap.min.css\n    │   └── bootstrap.min.css.map\n    └── js/\n        ├── bootstrap.bundle.js\n        ├── bootstrap.bundle.js.map\n        ├── bootstrap.bundle.min.js\n        ├── bootstrap.bundle.min.js.map\n        ├── bootstrap.js\n        ├── bootstrap.js.map\n        ├── bootstrap.min.js\n        └── bootstrap.min.js.map\n```\n\nWe provide compiled CSS and JS (`bootstrap.*`), as well as compiled and minified CSS and JS (`bootstrap.min.*`). [source maps](https://developers.google.com/web/tools/chrome-devtools/javascript/source-maps) (`bootstrap.*.map`) are available for use with certain browsers' developer tools. Bundled JS files (`bootstrap.bundle.js` and minified `bootstrap.bundle.min.js`) include [Popper](https://popper.js.org/), but not [jQuery](https://jquery.com/).\n\n\n## Bugs and feature requests\n\nHave a bug or a feature request? Please first read the [issue guidelines](https://github.com/twbs/bootstrap/blob/v4-dev/.github/CONTRIBUTING.md#using-the-issue-tracker) and search for existing and closed issues. If your problem or idea is not addressed yet, [please open a new issue](https://github.com/twbs/bootstrap/issues/new).\n\n\n## Documentation\n\nBootstrap's documentation, included in this repo in the root directory, is built with [Jekyll](https://jekyllrb.com/) and publicly hosted on GitHub Pages at <https://getbootstrap.com/>. The docs may also be run locally.\n\nDocumentation search is powered by [Algolia's DocSearch](https://community.algolia.com/docsearch/). Working on our search? Be sure to set `debug: true` in `site/docs/4.5/assets/js/src/search.js` file.\n\n### Running documentation locally\n\n1. Run through the [tooling setup](https://getbootstrap.com/docs/4.5/getting-started/build-tools/#tooling-setup) to install Jekyll (the site builder) and other Ruby dependencies with `bundle install`.\n2. Run `npm install` to install Node.js dependencies.\n3. Run `npm start` to compile CSS and JavaScript files, generate our docs, and watch for changes.\n4. Open `http://localhost:9001` in your browser, and voilà.\n\nLearn more about using Jekyll by reading its [documentation](https://jekyllrb.com/docs/).\n\n### Documentation for previous releases\n\nYou can find all our previous releases docs on <https://getbootstrap.com/docs/versions/>.\n\n[Previous releases](https://github.com/twbs/bootstrap/releases) and their documentation are also available for download.\n\n\n## Contributing\n\nPlease read through our [contributing guidelines](https://github.com/twbs/bootstrap/blob/v4-dev/.github/CONTRIBUTING.md). Included are directions for opening issues, coding standards, and notes on development.\n\nMoreover, if your pull request contains JavaScript patches or features, you must include [relevant unit tests](https://github.com/twbs/bootstrap/tree/v4-dev/js/tests). All HTML and CSS should conform to the [Code Guide](https://github.com/mdo/code-guide), maintained by [Mark Otto](https://github.com/mdo).\n\nEditor preferences are available in the [editor config](https://github.com/twbs/bootstrap/blob/v4-dev/.editorconfig) for easy use in common text editors. Read more and download plugins at <https://editorconfig.org/>.\n\n\n## Community\n\nGet updates on Bootstrap's development and chat with the project maintainers and community members.\n\n- Follow [@getbootstrap on Twitter](https://twitter.com/getbootstrap).\n- Read and subscribe to [The Official Bootstrap Blog](https://blog.getbootstrap.com/).\n- Join [the official Slack room](https://bootstrap-slack.herokuapp.com/).\n- Chat with fellow Bootstrappers in IRC. On the `irc.freenode.net` server, in the `##bootstrap` channel.\n- Implementation help may be found at Stack Overflow (tagged [`bootstrap-4`](https://stackoverflow.com/questions/tagged/bootstrap-4)).\n- Developers should use the keyword `bootstrap` on packages which modify or add to the functionality of Bootstrap when distributing through [npm](https://www.npmjs.com/browse/keyword/bootstrap) or similar delivery mechanisms for maximum discoverability.\n\n\n## Versioning\n\nFor transparency into our release cycle and in striving to maintain backward compatibility, Bootstrap is maintained under [the Semantic Versioning guidelines](https://semver.org/). Sometimes we screw up, but we adhere to those rules whenever possible.\n\nSee [the Releases section of our GitHub project](https://github.com/twbs/bootstrap/releases) for changelogs for each release version of Bootstrap. Release announcement posts on [the official Bootstrap blog](https://blog.getbootstrap.com/) contain summaries of the most noteworthy changes made in each release.\n\n\n## Creators\n\n**Mark Otto**\n\n- <https://twitter.com/mdo>\n- <https://github.com/mdo>\n\n**Jacob Thornton**\n\n- <https://twitter.com/fat>\n- <https://github.com/fat>\n\n\n## Thanks\n\n<a href=\"https://www.browserstack.com/\">\n  <img src=\"https://live.browserstack.com/images/opensource/browserstack-logo.svg\" alt=\"BrowserStack Logo\" width=\"192\" height=\"42\">\n</a>\n\nThanks to [BrowserStack](https://www.browserstack.com/) for providing the infrastructure that allows us to test in real browsers!\n\n\n## Sponsors\n\nSupport this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/bootstrap#sponsor)]\n\n[![](https://opencollective.com/bootstrap/sponsor/0/avatar.svg)](https://opencollective.com/bootstrap/sponsor/0/website)\n[![](https://opencollective.com/bootstrap/sponsor/1/avatar.svg)](https://opencollective.com/bootstrap/sponsor/1/website)\n[![](https://opencollective.com/bootstrap/sponsor/2/avatar.svg)](https://opencollective.com/bootstrap/sponsor/2/website)\n[![](https://opencollective.com/bootstrap/sponsor/3/avatar.svg)](https://opencollective.com/bootstrap/sponsor/3/website)\n[![](https://opencollective.com/bootstrap/sponsor/4/avatar.svg)](https://opencollective.com/bootstrap/sponsor/4/website)\n[![](https://opencollective.com/bootstrap/sponsor/5/avatar.svg)](https://opencollective.com/bootstrap/sponsor/5/website)\n[![](https://opencollective.com/bootstrap/sponsor/6/avatar.svg)](https://opencollective.com/bootstrap/sponsor/6/website)\n[![](https://opencollective.com/bootstrap/sponsor/7/avatar.svg)](https://opencollective.com/bootstrap/sponsor/7/website)\n[![](https://opencollective.com/bootstrap/sponsor/8/avatar.svg)](https://opencollective.com/bootstrap/sponsor/8/website)\n[![](https://opencollective.com/bootstrap/sponsor/9/avatar.svg)](https://opencollective.com/bootstrap/sponsor/9/website)\n\n\n## Backers\n\nThank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/bootstrap#backer)]\n\n[![Backers](https://opencollective.com/bootstrap/backers.svg?width=890)](https://opencollective.com/bootstrap#backers)\n\n\n## Copyright and license\n\nCode and documentation copyright 2011-2020 the [Bootstrap Authors](https://github.com/twbs/bootstrap/graphs/contributors) and [Twitter, Inc.](https://twitter.com) Code released under the [MIT License](https://github.com/twbs/bootstrap/blob/main/LICENSE). Docs released under [Creative Commons](https://creativecommons.org/licenses/by/3.0/).\n"
  },
  {
    "path": "src/IdentityServer/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css",
    "content": "/*!\n * Bootstrap Grid v4.5.3 (https://getbootstrap.com/)\n * Copyright 2011-2020 The Bootstrap Authors\n * Copyright 2011-2020 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n */\nhtml {\n  box-sizing: border-box;\n  -ms-overflow-style: scrollbar;\n}\n\n*,\n*::before,\n*::after {\n  box-sizing: inherit;\n}\n\n.container,\n.container-fluid,\n.container-sm,\n.container-md,\n.container-lg,\n.container-xl {\n  width: 100%;\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n@media (min-width: 576px) {\n  .container, .container-sm {\n    max-width: 540px;\n  }\n}\n\n@media (min-width: 768px) {\n  .container, .container-sm, .container-md {\n    max-width: 720px;\n  }\n}\n\n@media (min-width: 992px) {\n  .container, .container-sm, .container-md, .container-lg {\n    max-width: 960px;\n  }\n}\n\n@media (min-width: 1200px) {\n  .container, .container-sm, .container-md, .container-lg, .container-xl {\n    max-width: 1140px;\n  }\n}\n\n.row {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-wrap: wrap;\n  flex-wrap: wrap;\n  margin-right: -15px;\n  margin-left: -15px;\n}\n\n.no-gutters {\n  margin-right: 0;\n  margin-left: 0;\n}\n\n.no-gutters > .col,\n.no-gutters > [class*=\"col-\"] {\n  padding-right: 0;\n  padding-left: 0;\n}\n\n.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col,\n.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,\n.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,\n.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,\n.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,\n.col-xl-auto {\n  position: relative;\n  width: 100%;\n  padding-right: 15px;\n  padding-left: 15px;\n}\n\n.col {\n  -ms-flex-preferred-size: 0;\n  flex-basis: 0;\n  -ms-flex-positive: 1;\n  flex-grow: 1;\n  max-width: 100%;\n}\n\n.row-cols-1 > * {\n  -ms-flex: 0 0 100%;\n  flex: 0 0 100%;\n  max-width: 100%;\n}\n\n.row-cols-2 > * {\n  -ms-flex: 0 0 50%;\n  flex: 0 0 50%;\n  max-width: 50%;\n}\n\n.row-cols-3 > * {\n  -ms-flex: 0 0 33.333333%;\n  flex: 0 0 33.333333%;\n  max-width: 33.333333%;\n}\n\n.row-cols-4 > * {\n  -ms-flex: 0 0 25%;\n  flex: 0 0 25%;\n  max-width: 25%;\n}\n\n.row-cols-5 > * {\n  -ms-flex: 0 0 20%;\n  flex: 0 0 20%;\n  max-width: 20%;\n}\n\n.row-cols-6 > * {\n  -ms-flex: 0 0 16.666667%;\n  flex: 0 0 16.666667%;\n  max-width: 16.666667%;\n}\n\n.col-auto {\n  -ms-flex: 0 0 auto;\n  flex: 0 0 auto;\n  width: auto;\n  max-width: 100%;\n}\n\n.col-1 {\n  -ms-flex: 0 0 8.333333%;\n  flex: 0 0 8.333333%;\n  max-width: 8.333333%;\n}\n\n.col-2 {\n  -ms-flex: 0 0 16.666667%;\n  flex: 0 0 16.666667%;\n  max-width: 16.666667%;\n}\n\n.col-3 {\n  -ms-flex: 0 0 25%;\n  flex: 0 0 25%;\n  max-width: 25%;\n}\n\n.col-4 {\n  -ms-flex: 0 0 33.333333%;\n  flex: 0 0 33.333333%;\n  max-width: 33.333333%;\n}\n\n.col-5 {\n  -ms-flex: 0 0 41.666667%;\n  flex: 0 0 41.666667%;\n  max-width: 41.666667%;\n}\n\n.col-6 {\n  -ms-flex: 0 0 50%;\n  flex: 0 0 50%;\n  max-width: 50%;\n}\n\n.col-7 {\n  -ms-flex: 0 0 58.333333%;\n  flex: 0 0 58.333333%;\n  max-width: 58.333333%;\n}\n\n.col-8 {\n  -ms-flex: 0 0 66.666667%;\n  flex: 0 0 66.666667%;\n  max-width: 66.666667%;\n}\n\n.col-9 {\n  -ms-flex: 0 0 75%;\n  flex: 0 0 75%;\n  max-width: 75%;\n}\n\n.col-10 {\n  -ms-flex: 0 0 83.333333%;\n  flex: 0 0 83.333333%;\n  max-width: 83.333333%;\n}\n\n.col-11 {\n  -ms-flex: 0 0 91.666667%;\n  flex: 0 0 91.666667%;\n  max-width: 91.666667%;\n}\n\n.col-12 {\n  -ms-flex: 0 0 100%;\n  flex: 0 0 100%;\n  max-width: 100%;\n}\n\n.order-first {\n  -ms-flex-order: -1;\n  order: -1;\n}\n\n.order-last {\n  -ms-flex-order: 13;\n  order: 13;\n}\n\n.order-0 {\n  -ms-flex-order: 0;\n  order: 0;\n}\n\n.order-1 {\n  -ms-flex-order: 1;\n  order: 1;\n}\n\n.order-2 {\n  -ms-flex-order: 2;\n  order: 2;\n}\n\n.order-3 {\n  -ms-flex-order: 3;\n  order: 3;\n}\n\n.order-4 {\n  -ms-flex-order: 4;\n  order: 4;\n}\n\n.order-5 {\n  -ms-flex-order: 5;\n  order: 5;\n}\n\n.order-6 {\n  -ms-flex-order: 6;\n  order: 6;\n}\n\n.order-7 {\n  -ms-flex-order: 7;\n  order: 7;\n}\n\n.order-8 {\n  -ms-flex-order: 8;\n  order: 8;\n}\n\n.order-9 {\n  -ms-flex-order: 9;\n  order: 9;\n}\n\n.order-10 {\n  -ms-flex-order: 10;\n  order: 10;\n}\n\n.order-11 {\n  -ms-flex-order: 11;\n  order: 11;\n}\n\n.order-12 {\n  -ms-flex-order: 12;\n  order: 12;\n}\n\n.offset-1 {\n  margin-left: 8.333333%;\n}\n\n.offset-2 {\n  margin-left: 16.666667%;\n}\n\n.offset-3 {\n  margin-left: 25%;\n}\n\n.offset-4 {\n  margin-left: 33.333333%;\n}\n\n.offset-5 {\n  margin-left: 41.666667%;\n}\n\n.offset-6 {\n  margin-left: 50%;\n}\n\n.offset-7 {\n  margin-left: 58.333333%;\n}\n\n.offset-8 {\n  margin-left: 66.666667%;\n}\n\n.offset-9 {\n  margin-left: 75%;\n}\n\n.offset-10 {\n  margin-left: 83.333333%;\n}\n\n.offset-11 {\n  margin-left: 91.666667%;\n}\n\n@media (min-width: 576px) {\n  .col-sm {\n    -ms-flex-preferred-size: 0;\n    flex-basis: 0;\n    -ms-flex-positive: 1;\n    flex-grow: 1;\n    max-width: 100%;\n  }\n  .row-cols-sm-1 > * {\n    -ms-flex: 0 0 100%;\n    flex: 0 0 100%;\n    max-width: 100%;\n  }\n  .row-cols-sm-2 > * {\n    -ms-flex: 0 0 50%;\n    flex: 0 0 50%;\n    max-width: 50%;\n  }\n  .row-cols-sm-3 > * {\n    -ms-flex: 0 0 33.333333%;\n    flex: 0 0 33.333333%;\n    max-width: 33.333333%;\n  }\n  .row-cols-sm-4 > * {\n    -ms-flex: 0 0 25%;\n    flex: 0 0 25%;\n    max-width: 25%;\n  }\n  .row-cols-sm-5 > * {\n    -ms-flex: 0 0 20%;\n    flex: 0 0 20%;\n    max-width: 20%;\n  }\n  .row-cols-sm-6 > * {\n    -ms-flex: 0 0 16.666667%;\n    flex: 0 0 16.666667%;\n    max-width: 16.666667%;\n  }\n  .col-sm-auto {\n    -ms-flex: 0 0 auto;\n    flex: 0 0 auto;\n    width: auto;\n    max-width: 100%;\n  }\n  .col-sm-1 {\n    -ms-flex: 0 0 8.333333%;\n    flex: 0 0 8.333333%;\n    max-width: 8.333333%;\n  }\n  .col-sm-2 {\n    -ms-flex: 0 0 16.666667%;\n    flex: 0 0 16.666667%;\n    max-width: 16.666667%;\n  }\n  .col-sm-3 {\n    -ms-flex: 0 0 25%;\n    flex: 0 0 25%;\n    max-width: 25%;\n  }\n  .col-sm-4 {\n    -ms-flex: 0 0 33.333333%;\n    flex: 0 0 33.333333%;\n    max-width: 33.333333%;\n  }\n  .col-sm-5 {\n    -ms-flex: 0 0 41.666667%;\n    flex: 0 0 41.666667%;\n    max-width: 41.666667%;\n  }\n  .col-sm-6 {\n    -ms-flex: 0 0 50%;\n    flex: 0 0 50%;\n    max-width: 50%;\n  }\n  .col-sm-7 {\n    -ms-flex: 0 0 58.333333%;\n    flex: 0 0 58.333333%;\n    max-width: 58.333333%;\n  }\n  .col-sm-8 {\n    -ms-flex: 0 0 66.666667%;\n    flex: 0 0 66.666667%;\n    max-width: 66.666667%;\n  }\n  .col-sm-9 {\n    -ms-flex: 0 0 75%;\n    flex: 0 0 75%;\n    max-width: 75%;\n  }\n  .col-sm-10 {\n    -ms-flex: 0 0 83.333333%;\n    flex: 0 0 83.333333%;\n    max-width: 83.333333%;\n  }\n  .col-sm-11 {\n    -ms-flex: 0 0 91.666667%;\n    flex: 0 0 91.666667%;\n    max-width: 91.666667%;\n  }\n  .col-sm-12 {\n    -ms-flex: 0 0 100%;\n    flex: 0 0 100%;\n    max-width: 100%;\n  }\n  .order-sm-first {\n    -ms-flex-order: -1;\n    order: -1;\n  }\n  .order-sm-last {\n    -ms-flex-order: 13;\n    order: 13;\n  }\n  .order-sm-0 {\n    -ms-flex-order: 0;\n    order: 0;\n  }\n  .order-sm-1 {\n    -ms-flex-order: 1;\n    order: 1;\n  }\n  .order-sm-2 {\n    -ms-flex-order: 2;\n    order: 2;\n  }\n  .order-sm-3 {\n    -ms-flex-order: 3;\n    order: 3;\n  }\n  .order-sm-4 {\n    -ms-flex-order: 4;\n    order: 4;\n  }\n  .order-sm-5 {\n    -ms-flex-order: 5;\n    order: 5;\n  }\n  .order-sm-6 {\n    -ms-flex-order: 6;\n    order: 6;\n  }\n  .order-sm-7 {\n    -ms-flex-order: 7;\n    order: 7;\n  }\n  .order-sm-8 {\n    -ms-flex-order: 8;\n    order: 8;\n  }\n  .order-sm-9 {\n    -ms-flex-order: 9;\n    order: 9;\n  }\n  .order-sm-10 {\n    -ms-flex-order: 10;\n    order: 10;\n  }\n  .order-sm-11 {\n    -ms-flex-order: 11;\n    order: 11;\n  }\n  .order-sm-12 {\n    -ms-flex-order: 12;\n    order: 12;\n  }\n  .offset-sm-0 {\n    margin-left: 0;\n  }\n  .offset-sm-1 {\n    margin-left: 8.333333%;\n  }\n  .offset-sm-2 {\n    margin-left: 16.666667%;\n  }\n  .offset-sm-3 {\n    margin-left: 25%;\n  }\n  .offset-sm-4 {\n    margin-left: 33.333333%;\n  }\n  .offset-sm-5 {\n    margin-left: 41.666667%;\n  }\n  .offset-sm-6 {\n    margin-left: 50%;\n  }\n  .offset-sm-7 {\n    margin-left: 58.333333%;\n  }\n  .offset-sm-8 {\n    margin-left: 66.666667%;\n  }\n  .offset-sm-9 {\n    margin-left: 75%;\n  }\n  .offset-sm-10 {\n    margin-left: 83.333333%;\n  }\n  .offset-sm-11 {\n    margin-left: 91.666667%;\n  }\n}\n\n@media (min-width: 768px) {\n  .col-md {\n    -ms-flex-preferred-size: 0;\n    flex-basis: 0;\n    -ms-flex-positive: 1;\n    flex-grow: 1;\n    max-width: 100%;\n  }\n  .row-cols-md-1 > * {\n    -ms-flex: 0 0 100%;\n    flex: 0 0 100%;\n    max-width: 100%;\n  }\n  .row-cols-md-2 > * {\n    -ms-flex: 0 0 50%;\n    flex: 0 0 50%;\n    max-width: 50%;\n  }\n  .row-cols-md-3 > * {\n    -ms-flex: 0 0 33.333333%;\n    flex: 0 0 33.333333%;\n    max-width: 33.333333%;\n  }\n  .row-cols-md-4 > * {\n    -ms-flex: 0 0 25%;\n    flex: 0 0 25%;\n    max-width: 25%;\n  }\n  .row-cols-md-5 > * {\n    -ms-flex: 0 0 20%;\n    flex: 0 0 20%;\n    max-width: 20%;\n  }\n  .row-cols-md-6 > * {\n    -ms-flex: 0 0 16.666667%;\n    flex: 0 0 16.666667%;\n    max-width: 16.666667%;\n  }\n  .col-md-auto {\n    -ms-flex: 0 0 auto;\n    flex: 0 0 auto;\n    width: auto;\n    max-width: 100%;\n  }\n  .col-md-1 {\n    -ms-flex: 0 0 8.333333%;\n    flex: 0 0 8.333333%;\n    max-width: 8.333333%;\n  }\n  .col-md-2 {\n    -ms-flex: 0 0 16.666667%;\n    flex: 0 0 16.666667%;\n    max-width: 16.666667%;\n  }\n  .col-md-3 {\n    -ms-flex: 0 0 25%;\n    flex: 0 0 25%;\n    max-width: 25%;\n  }\n  .col-md-4 {\n    -ms-flex: 0 0 33.333333%;\n    flex: 0 0 33.333333%;\n    max-width: 33.333333%;\n  }\n  .col-md-5 {\n    -ms-flex: 0 0 41.666667%;\n    flex: 0 0 41.666667%;\n    max-width: 41.666667%;\n  }\n  .col-md-6 {\n    -ms-flex: 0 0 50%;\n    flex: 0 0 50%;\n    max-width: 50%;\n  }\n  .col-md-7 {\n    -ms-flex: 0 0 58.333333%;\n    flex: 0 0 58.333333%;\n    max-width: 58.333333%;\n  }\n  .col-md-8 {\n    -ms-flex: 0 0 66.666667%;\n    flex: 0 0 66.666667%;\n    max-width: 66.666667%;\n  }\n  .col-md-9 {\n    -ms-flex: 0 0 75%;\n    flex: 0 0 75%;\n    max-width: 75%;\n  }\n  .col-md-10 {\n    -ms-flex: 0 0 83.333333%;\n    flex: 0 0 83.333333%;\n    max-width: 83.333333%;\n  }\n  .col-md-11 {\n    -ms-flex: 0 0 91.666667%;\n    flex: 0 0 91.666667%;\n    max-width: 91.666667%;\n  }\n  .col-md-12 {\n    -ms-flex: 0 0 100%;\n    flex: 0 0 100%;\n    max-width: 100%;\n  }\n  .order-md-first {\n    -ms-flex-order: -1;\n    order: -1;\n  }\n  .order-md-last {\n    -ms-flex-order: 13;\n    order: 13;\n  }\n  .order-md-0 {\n    -ms-flex-order: 0;\n    order: 0;\n  }\n  .order-md-1 {\n    -ms-flex-order: 1;\n    order: 1;\n  }\n  .order-md-2 {\n    -ms-flex-order: 2;\n    order: 2;\n  }\n  .order-md-3 {\n    -ms-flex-order: 3;\n    order: 3;\n  }\n  .order-md-4 {\n    -ms-flex-order: 4;\n    order: 4;\n  }\n  .order-md-5 {\n    -ms-flex-order: 5;\n    order: 5;\n  }\n  .order-md-6 {\n    -ms-flex-order: 6;\n    order: 6;\n  }\n  .order-md-7 {\n    -ms-flex-order: 7;\n    order: 7;\n  }\n  .order-md-8 {\n    -ms-flex-order: 8;\n    order: 8;\n  }\n  .order-md-9 {\n    -ms-flex-order: 9;\n    order: 9;\n  }\n  .order-md-10 {\n    -ms-flex-order: 10;\n    order: 10;\n  }\n  .order-md-11 {\n    -ms-flex-order: 11;\n    order: 11;\n  }\n  .order-md-12 {\n    -ms-flex-order: 12;\n    order: 12;\n  }\n  .offset-md-0 {\n    margin-left: 0;\n  }\n  .offset-md-1 {\n    margin-left: 8.333333%;\n  }\n  .offset-md-2 {\n    margin-left: 16.666667%;\n  }\n  .offset-md-3 {\n    margin-left: 25%;\n  }\n  .offset-md-4 {\n    margin-left: 33.333333%;\n  }\n  .offset-md-5 {\n    margin-left: 41.666667%;\n  }\n  .offset-md-6 {\n    margin-left: 50%;\n  }\n  .offset-md-7 {\n    margin-left: 58.333333%;\n  }\n  .offset-md-8 {\n    margin-left: 66.666667%;\n  }\n  .offset-md-9 {\n    margin-left: 75%;\n  }\n  .offset-md-10 {\n    margin-left: 83.333333%;\n  }\n  .offset-md-11 {\n    margin-left: 91.666667%;\n  }\n}\n\n@media (min-width: 992px) {\n  .col-lg {\n    -ms-flex-preferred-size: 0;\n    flex-basis: 0;\n    -ms-flex-positive: 1;\n    flex-grow: 1;\n    max-width: 100%;\n  }\n  .row-cols-lg-1 > * {\n    -ms-flex: 0 0 100%;\n    flex: 0 0 100%;\n    max-width: 100%;\n  }\n  .row-cols-lg-2 > * {\n    -ms-flex: 0 0 50%;\n    flex: 0 0 50%;\n    max-width: 50%;\n  }\n  .row-cols-lg-3 > * {\n    -ms-flex: 0 0 33.333333%;\n    flex: 0 0 33.333333%;\n    max-width: 33.333333%;\n  }\n  .row-cols-lg-4 > * {\n    -ms-flex: 0 0 25%;\n    flex: 0 0 25%;\n    max-width: 25%;\n  }\n  .row-cols-lg-5 > * {\n    -ms-flex: 0 0 20%;\n    flex: 0 0 20%;\n    max-width: 20%;\n  }\n  .row-cols-lg-6 > * {\n    -ms-flex: 0 0 16.666667%;\n    flex: 0 0 16.666667%;\n    max-width: 16.666667%;\n  }\n  .col-lg-auto {\n    -ms-flex: 0 0 auto;\n    flex: 0 0 auto;\n    width: auto;\n    max-width: 100%;\n  }\n  .col-lg-1 {\n    -ms-flex: 0 0 8.333333%;\n    flex: 0 0 8.333333%;\n    max-width: 8.333333%;\n  }\n  .col-lg-2 {\n    -ms-flex: 0 0 16.666667%;\n    flex: 0 0 16.666667%;\n    max-width: 16.666667%;\n  }\n  .col-lg-3 {\n    -ms-flex: 0 0 25%;\n    flex: 0 0 25%;\n    max-width: 25%;\n  }\n  .col-lg-4 {\n    -ms-flex: 0 0 33.333333%;\n    flex: 0 0 33.333333%;\n    max-width: 33.333333%;\n  }\n  .col-lg-5 {\n    -ms-flex: 0 0 41.666667%;\n    flex: 0 0 41.666667%;\n    max-width: 41.666667%;\n  }\n  .col-lg-6 {\n    -ms-flex: 0 0 50%;\n    flex: 0 0 50%;\n    max-width: 50%;\n  }\n  .col-lg-7 {\n    -ms-flex: 0 0 58.333333%;\n    flex: 0 0 58.333333%;\n    max-width: 58.333333%;\n  }\n  .col-lg-8 {\n    -ms-flex: 0 0 66.666667%;\n    flex: 0 0 66.666667%;\n    max-width: 66.666667%;\n  }\n  .col-lg-9 {\n    -ms-flex: 0 0 75%;\n    flex: 0 0 75%;\n    max-width: 75%;\n  }\n  .col-lg-10 {\n    -ms-flex: 0 0 83.333333%;\n    flex: 0 0 83.333333%;\n    max-width: 83.333333%;\n  }\n  .col-lg-11 {\n    -ms-flex: 0 0 91.666667%;\n    flex: 0 0 91.666667%;\n    max-width: 91.666667%;\n  }\n  .col-lg-12 {\n    -ms-flex: 0 0 100%;\n    flex: 0 0 100%;\n    max-width: 100%;\n  }\n  .order-lg-first {\n    -ms-flex-order: -1;\n    order: -1;\n  }\n  .order-lg-last {\n    -ms-flex-order: 13;\n    order: 13;\n  }\n  .order-lg-0 {\n    -ms-flex-order: 0;\n    order: 0;\n  }\n  .order-lg-1 {\n    -ms-flex-order: 1;\n    order: 1;\n  }\n  .order-lg-2 {\n    -ms-flex-order: 2;\n    order: 2;\n  }\n  .order-lg-3 {\n    -ms-flex-order: 3;\n    order: 3;\n  }\n  .order-lg-4 {\n    -ms-flex-order: 4;\n    order: 4;\n  }\n  .order-lg-5 {\n    -ms-flex-order: 5;\n    order: 5;\n  }\n  .order-lg-6 {\n    -ms-flex-order: 6;\n    order: 6;\n  }\n  .order-lg-7 {\n    -ms-flex-order: 7;\n    order: 7;\n  }\n  .order-lg-8 {\n    -ms-flex-order: 8;\n    order: 8;\n  }\n  .order-lg-9 {\n    -ms-flex-order: 9;\n    order: 9;\n  }\n  .order-lg-10 {\n    -ms-flex-order: 10;\n    order: 10;\n  }\n  .order-lg-11 {\n    -ms-flex-order: 11;\n    order: 11;\n  }\n  .order-lg-12 {\n    -ms-flex-order: 12;\n    order: 12;\n  }\n  .offset-lg-0 {\n    margin-left: 0;\n  }\n  .offset-lg-1 {\n    margin-left: 8.333333%;\n  }\n  .offset-lg-2 {\n    margin-left: 16.666667%;\n  }\n  .offset-lg-3 {\n    margin-left: 25%;\n  }\n  .offset-lg-4 {\n    margin-left: 33.333333%;\n  }\n  .offset-lg-5 {\n    margin-left: 41.666667%;\n  }\n  .offset-lg-6 {\n    margin-left: 50%;\n  }\n  .offset-lg-7 {\n    margin-left: 58.333333%;\n  }\n  .offset-lg-8 {\n    margin-left: 66.666667%;\n  }\n  .offset-lg-9 {\n    margin-left: 75%;\n  }\n  .offset-lg-10 {\n    margin-left: 83.333333%;\n  }\n  .offset-lg-11 {\n    margin-left: 91.666667%;\n  }\n}\n\n@media (min-width: 1200px) {\n  .col-xl {\n    -ms-flex-preferred-size: 0;\n    flex-basis: 0;\n    -ms-flex-positive: 1;\n    flex-grow: 1;\n    max-width: 100%;\n  }\n  .row-cols-xl-1 > * {\n    -ms-flex: 0 0 100%;\n    flex: 0 0 100%;\n    max-width: 100%;\n  }\n  .row-cols-xl-2 > * {\n    -ms-flex: 0 0 50%;\n    flex: 0 0 50%;\n    max-width: 50%;\n  }\n  .row-cols-xl-3 > * {\n    -ms-flex: 0 0 33.333333%;\n    flex: 0 0 33.333333%;\n    max-width: 33.333333%;\n  }\n  .row-cols-xl-4 > * {\n    -ms-flex: 0 0 25%;\n    flex: 0 0 25%;\n    max-width: 25%;\n  }\n  .row-cols-xl-5 > * {\n    -ms-flex: 0 0 20%;\n    flex: 0 0 20%;\n    max-width: 20%;\n  }\n  .row-cols-xl-6 > * {\n    -ms-flex: 0 0 16.666667%;\n    flex: 0 0 16.666667%;\n    max-width: 16.666667%;\n  }\n  .col-xl-auto {\n    -ms-flex: 0 0 auto;\n    flex: 0 0 auto;\n    width: auto;\n    max-width: 100%;\n  }\n  .col-xl-1 {\n    -ms-flex: 0 0 8.333333%;\n    flex: 0 0 8.333333%;\n    max-width: 8.333333%;\n  }\n  .col-xl-2 {\n    -ms-flex: 0 0 16.666667%;\n    flex: 0 0 16.666667%;\n    max-width: 16.666667%;\n  }\n  .col-xl-3 {\n    -ms-flex: 0 0 25%;\n    flex: 0 0 25%;\n    max-width: 25%;\n  }\n  .col-xl-4 {\n    -ms-flex: 0 0 33.333333%;\n    flex: 0 0 33.333333%;\n    max-width: 33.333333%;\n  }\n  .col-xl-5 {\n    -ms-flex: 0 0 41.666667%;\n    flex: 0 0 41.666667%;\n    max-width: 41.666667%;\n  }\n  .col-xl-6 {\n    -ms-flex: 0 0 50%;\n    flex: 0 0 50%;\n    max-width: 50%;\n  }\n  .col-xl-7 {\n    -ms-flex: 0 0 58.333333%;\n    flex: 0 0 58.333333%;\n    max-width: 58.333333%;\n  }\n  .col-xl-8 {\n    -ms-flex: 0 0 66.666667%;\n    flex: 0 0 66.666667%;\n    max-width: 66.666667%;\n  }\n  .col-xl-9 {\n    -ms-flex: 0 0 75%;\n    flex: 0 0 75%;\n    max-width: 75%;\n  }\n  .col-xl-10 {\n    -ms-flex: 0 0 83.333333%;\n    flex: 0 0 83.333333%;\n    max-width: 83.333333%;\n  }\n  .col-xl-11 {\n    -ms-flex: 0 0 91.666667%;\n    flex: 0 0 91.666667%;\n    max-width: 91.666667%;\n  }\n  .col-xl-12 {\n    -ms-flex: 0 0 100%;\n    flex: 0 0 100%;\n    max-width: 100%;\n  }\n  .order-xl-first {\n    -ms-flex-order: -1;\n    order: -1;\n  }\n  .order-xl-last {\n    -ms-flex-order: 13;\n    order: 13;\n  }\n  .order-xl-0 {\n    -ms-flex-order: 0;\n    order: 0;\n  }\n  .order-xl-1 {\n    -ms-flex-order: 1;\n    order: 1;\n  }\n  .order-xl-2 {\n    -ms-flex-order: 2;\n    order: 2;\n  }\n  .order-xl-3 {\n    -ms-flex-order: 3;\n    order: 3;\n  }\n  .order-xl-4 {\n    -ms-flex-order: 4;\n    order: 4;\n  }\n  .order-xl-5 {\n    -ms-flex-order: 5;\n    order: 5;\n  }\n  .order-xl-6 {\n    -ms-flex-order: 6;\n    order: 6;\n  }\n  .order-xl-7 {\n    -ms-flex-order: 7;\n    order: 7;\n  }\n  .order-xl-8 {\n    -ms-flex-order: 8;\n    order: 8;\n  }\n  .order-xl-9 {\n    -ms-flex-order: 9;\n    order: 9;\n  }\n  .order-xl-10 {\n    -ms-flex-order: 10;\n    order: 10;\n  }\n  .order-xl-11 {\n    -ms-flex-order: 11;\n    order: 11;\n  }\n  .order-xl-12 {\n    -ms-flex-order: 12;\n    order: 12;\n  }\n  .offset-xl-0 {\n    margin-left: 0;\n  }\n  .offset-xl-1 {\n    margin-left: 8.333333%;\n  }\n  .offset-xl-2 {\n    margin-left: 16.666667%;\n  }\n  .offset-xl-3 {\n    margin-left: 25%;\n  }\n  .offset-xl-4 {\n    margin-left: 33.333333%;\n  }\n  .offset-xl-5 {\n    margin-left: 41.666667%;\n  }\n  .offset-xl-6 {\n    margin-left: 50%;\n  }\n  .offset-xl-7 {\n    margin-left: 58.333333%;\n  }\n  .offset-xl-8 {\n    margin-left: 66.666667%;\n  }\n  .offset-xl-9 {\n    margin-left: 75%;\n  }\n  .offset-xl-10 {\n    margin-left: 83.333333%;\n  }\n  .offset-xl-11 {\n    margin-left: 91.666667%;\n  }\n}\n\n.d-none {\n  display: none !important;\n}\n\n.d-inline {\n  display: inline !important;\n}\n\n.d-inline-block {\n  display: inline-block !important;\n}\n\n.d-block {\n  display: block !important;\n}\n\n.d-table {\n  display: table !important;\n}\n\n.d-table-row {\n  display: table-row !important;\n}\n\n.d-table-cell {\n  display: table-cell !important;\n}\n\n.d-flex {\n  display: -ms-flexbox !important;\n  display: flex !important;\n}\n\n.d-inline-flex {\n  display: -ms-inline-flexbox !important;\n  display: inline-flex !important;\n}\n\n@media (min-width: 576px) {\n  .d-sm-none {\n    display: none !important;\n  }\n  .d-sm-inline {\n    display: inline !important;\n  }\n  .d-sm-inline-block {\n    display: inline-block !important;\n  }\n  .d-sm-block {\n    display: block !important;\n  }\n  .d-sm-table {\n    display: table !important;\n  }\n  .d-sm-table-row {\n    display: table-row !important;\n  }\n  .d-sm-table-cell {\n    display: table-cell !important;\n  }\n  .d-sm-flex {\n    display: -ms-flexbox !important;\n    display: flex !important;\n  }\n  .d-sm-inline-flex {\n    display: -ms-inline-flexbox !important;\n    display: inline-flex !important;\n  }\n}\n\n@media (min-width: 768px) {\n  .d-md-none {\n    display: none !important;\n  }\n  .d-md-inline {\n    display: inline !important;\n  }\n  .d-md-inline-block {\n    display: inline-block !important;\n  }\n  .d-md-block {\n    display: block !important;\n  }\n  .d-md-table {\n    display: table !important;\n  }\n  .d-md-table-row {\n    display: table-row !important;\n  }\n  .d-md-table-cell {\n    display: table-cell !important;\n  }\n  .d-md-flex {\n    display: -ms-flexbox !important;\n    display: flex !important;\n  }\n  .d-md-inline-flex {\n    display: -ms-inline-flexbox !important;\n    display: inline-flex !important;\n  }\n}\n\n@media (min-width: 992px) {\n  .d-lg-none {\n    display: none !important;\n  }\n  .d-lg-inline {\n    display: inline !important;\n  }\n  .d-lg-inline-block {\n    display: inline-block !important;\n  }\n  .d-lg-block {\n    display: block !important;\n  }\n  .d-lg-table {\n    display: table !important;\n  }\n  .d-lg-table-row {\n    display: table-row !important;\n  }\n  .d-lg-table-cell {\n    display: table-cell !important;\n  }\n  .d-lg-flex {\n    display: -ms-flexbox !important;\n    display: flex !important;\n  }\n  .d-lg-inline-flex {\n    display: -ms-inline-flexbox !important;\n    display: inline-flex !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .d-xl-none {\n    display: none !important;\n  }\n  .d-xl-inline {\n    display: inline !important;\n  }\n  .d-xl-inline-block {\n    display: inline-block !important;\n  }\n  .d-xl-block {\n    display: block !important;\n  }\n  .d-xl-table {\n    display: table !important;\n  }\n  .d-xl-table-row {\n    display: table-row !important;\n  }\n  .d-xl-table-cell {\n    display: table-cell !important;\n  }\n  .d-xl-flex {\n    display: -ms-flexbox !important;\n    display: flex !important;\n  }\n  .d-xl-inline-flex {\n    display: -ms-inline-flexbox !important;\n    display: inline-flex !important;\n  }\n}\n\n@media print {\n  .d-print-none {\n    display: none !important;\n  }\n  .d-print-inline {\n    display: inline !important;\n  }\n  .d-print-inline-block {\n    display: inline-block !important;\n  }\n  .d-print-block {\n    display: block !important;\n  }\n  .d-print-table {\n    display: table !important;\n  }\n  .d-print-table-row {\n    display: table-row !important;\n  }\n  .d-print-table-cell {\n    display: table-cell !important;\n  }\n  .d-print-flex {\n    display: -ms-flexbox !important;\n    display: flex !important;\n  }\n  .d-print-inline-flex {\n    display: -ms-inline-flexbox !important;\n    display: inline-flex !important;\n  }\n}\n\n.flex-row {\n  -ms-flex-direction: row !important;\n  flex-direction: row !important;\n}\n\n.flex-column {\n  -ms-flex-direction: column !important;\n  flex-direction: column !important;\n}\n\n.flex-row-reverse {\n  -ms-flex-direction: row-reverse !important;\n  flex-direction: row-reverse !important;\n}\n\n.flex-column-reverse {\n  -ms-flex-direction: column-reverse !important;\n  flex-direction: column-reverse !important;\n}\n\n.flex-wrap {\n  -ms-flex-wrap: wrap !important;\n  flex-wrap: wrap !important;\n}\n\n.flex-nowrap {\n  -ms-flex-wrap: nowrap !important;\n  flex-wrap: nowrap !important;\n}\n\n.flex-wrap-reverse {\n  -ms-flex-wrap: wrap-reverse !important;\n  flex-wrap: wrap-reverse !important;\n}\n\n.flex-fill {\n  -ms-flex: 1 1 auto !important;\n  flex: 1 1 auto !important;\n}\n\n.flex-grow-0 {\n  -ms-flex-positive: 0 !important;\n  flex-grow: 0 !important;\n}\n\n.flex-grow-1 {\n  -ms-flex-positive: 1 !important;\n  flex-grow: 1 !important;\n}\n\n.flex-shrink-0 {\n  -ms-flex-negative: 0 !important;\n  flex-shrink: 0 !important;\n}\n\n.flex-shrink-1 {\n  -ms-flex-negative: 1 !important;\n  flex-shrink: 1 !important;\n}\n\n.justify-content-start {\n  -ms-flex-pack: start !important;\n  justify-content: flex-start !important;\n}\n\n.justify-content-end {\n  -ms-flex-pack: end !important;\n  justify-content: flex-end !important;\n}\n\n.justify-content-center {\n  -ms-flex-pack: center !important;\n  justify-content: center !important;\n}\n\n.justify-content-between {\n  -ms-flex-pack: justify !important;\n  justify-content: space-between !important;\n}\n\n.justify-content-around {\n  -ms-flex-pack: distribute !important;\n  justify-content: space-around !important;\n}\n\n.align-items-start {\n  -ms-flex-align: start !important;\n  align-items: flex-start !important;\n}\n\n.align-items-end {\n  -ms-flex-align: end !important;\n  align-items: flex-end !important;\n}\n\n.align-items-center {\n  -ms-flex-align: center !important;\n  align-items: center !important;\n}\n\n.align-items-baseline {\n  -ms-flex-align: baseline !important;\n  align-items: baseline !important;\n}\n\n.align-items-stretch {\n  -ms-flex-align: stretch !important;\n  align-items: stretch !important;\n}\n\n.align-content-start {\n  -ms-flex-line-pack: start !important;\n  align-content: flex-start !important;\n}\n\n.align-content-end {\n  -ms-flex-line-pack: end !important;\n  align-content: flex-end !important;\n}\n\n.align-content-center {\n  -ms-flex-line-pack: center !important;\n  align-content: center !important;\n}\n\n.align-content-between {\n  -ms-flex-line-pack: justify !important;\n  align-content: space-between !important;\n}\n\n.align-content-around {\n  -ms-flex-line-pack: distribute !important;\n  align-content: space-around !important;\n}\n\n.align-content-stretch {\n  -ms-flex-line-pack: stretch !important;\n  align-content: stretch !important;\n}\n\n.align-self-auto {\n  -ms-flex-item-align: auto !important;\n  align-self: auto !important;\n}\n\n.align-self-start {\n  -ms-flex-item-align: start !important;\n  align-self: flex-start !important;\n}\n\n.align-self-end {\n  -ms-flex-item-align: end !important;\n  align-self: flex-end !important;\n}\n\n.align-self-center {\n  -ms-flex-item-align: center !important;\n  align-self: center !important;\n}\n\n.align-self-baseline {\n  -ms-flex-item-align: baseline !important;\n  align-self: baseline !important;\n}\n\n.align-self-stretch {\n  -ms-flex-item-align: stretch !important;\n  align-self: stretch !important;\n}\n\n@media (min-width: 576px) {\n  .flex-sm-row {\n    -ms-flex-direction: row !important;\n    flex-direction: row !important;\n  }\n  .flex-sm-column {\n    -ms-flex-direction: column !important;\n    flex-direction: column !important;\n  }\n  .flex-sm-row-reverse {\n    -ms-flex-direction: row-reverse !important;\n    flex-direction: row-reverse !important;\n  }\n  .flex-sm-column-reverse {\n    -ms-flex-direction: column-reverse !important;\n    flex-direction: column-reverse !important;\n  }\n  .flex-sm-wrap {\n    -ms-flex-wrap: wrap !important;\n    flex-wrap: wrap !important;\n  }\n  .flex-sm-nowrap {\n    -ms-flex-wrap: nowrap !important;\n    flex-wrap: nowrap !important;\n  }\n  .flex-sm-wrap-reverse {\n    -ms-flex-wrap: wrap-reverse !important;\n    flex-wrap: wrap-reverse !important;\n  }\n  .flex-sm-fill {\n    -ms-flex: 1 1 auto !important;\n    flex: 1 1 auto !important;\n  }\n  .flex-sm-grow-0 {\n    -ms-flex-positive: 0 !important;\n    flex-grow: 0 !important;\n  }\n  .flex-sm-grow-1 {\n    -ms-flex-positive: 1 !important;\n    flex-grow: 1 !important;\n  }\n  .flex-sm-shrink-0 {\n    -ms-flex-negative: 0 !important;\n    flex-shrink: 0 !important;\n  }\n  .flex-sm-shrink-1 {\n    -ms-flex-negative: 1 !important;\n    flex-shrink: 1 !important;\n  }\n  .justify-content-sm-start {\n    -ms-flex-pack: start !important;\n    justify-content: flex-start !important;\n  }\n  .justify-content-sm-end {\n    -ms-flex-pack: end !important;\n    justify-content: flex-end !important;\n  }\n  .justify-content-sm-center {\n    -ms-flex-pack: center !important;\n    justify-content: center !important;\n  }\n  .justify-content-sm-between {\n    -ms-flex-pack: justify !important;\n    justify-content: space-between !important;\n  }\n  .justify-content-sm-around {\n    -ms-flex-pack: distribute !important;\n    justify-content: space-around !important;\n  }\n  .align-items-sm-start {\n    -ms-flex-align: start !important;\n    align-items: flex-start !important;\n  }\n  .align-items-sm-end {\n    -ms-flex-align: end !important;\n    align-items: flex-end !important;\n  }\n  .align-items-sm-center {\n    -ms-flex-align: center !important;\n    align-items: center !important;\n  }\n  .align-items-sm-baseline {\n    -ms-flex-align: baseline !important;\n    align-items: baseline !important;\n  }\n  .align-items-sm-stretch {\n    -ms-flex-align: stretch !important;\n    align-items: stretch !important;\n  }\n  .align-content-sm-start {\n    -ms-flex-line-pack: start !important;\n    align-content: flex-start !important;\n  }\n  .align-content-sm-end {\n    -ms-flex-line-pack: end !important;\n    align-content: flex-end !important;\n  }\n  .align-content-sm-center {\n    -ms-flex-line-pack: center !important;\n    align-content: center !important;\n  }\n  .align-content-sm-between {\n    -ms-flex-line-pack: justify !important;\n    align-content: space-between !important;\n  }\n  .align-content-sm-around {\n    -ms-flex-line-pack: distribute !important;\n    align-content: space-around !important;\n  }\n  .align-content-sm-stretch {\n    -ms-flex-line-pack: stretch !important;\n    align-content: stretch !important;\n  }\n  .align-self-sm-auto {\n    -ms-flex-item-align: auto !important;\n    align-self: auto !important;\n  }\n  .align-self-sm-start {\n    -ms-flex-item-align: start !important;\n    align-self: flex-start !important;\n  }\n  .align-self-sm-end {\n    -ms-flex-item-align: end !important;\n    align-self: flex-end !important;\n  }\n  .align-self-sm-center {\n    -ms-flex-item-align: center !important;\n    align-self: center !important;\n  }\n  .align-self-sm-baseline {\n    -ms-flex-item-align: baseline !important;\n    align-self: baseline !important;\n  }\n  .align-self-sm-stretch {\n    -ms-flex-item-align: stretch !important;\n    align-self: stretch !important;\n  }\n}\n\n@media (min-width: 768px) {\n  .flex-md-row {\n    -ms-flex-direction: row !important;\n    flex-direction: row !important;\n  }\n  .flex-md-column {\n    -ms-flex-direction: column !important;\n    flex-direction: column !important;\n  }\n  .flex-md-row-reverse {\n    -ms-flex-direction: row-reverse !important;\n    flex-direction: row-reverse !important;\n  }\n  .flex-md-column-reverse {\n    -ms-flex-direction: column-reverse !important;\n    flex-direction: column-reverse !important;\n  }\n  .flex-md-wrap {\n    -ms-flex-wrap: wrap !important;\n    flex-wrap: wrap !important;\n  }\n  .flex-md-nowrap {\n    -ms-flex-wrap: nowrap !important;\n    flex-wrap: nowrap !important;\n  }\n  .flex-md-wrap-reverse {\n    -ms-flex-wrap: wrap-reverse !important;\n    flex-wrap: wrap-reverse !important;\n  }\n  .flex-md-fill {\n    -ms-flex: 1 1 auto !important;\n    flex: 1 1 auto !important;\n  }\n  .flex-md-grow-0 {\n    -ms-flex-positive: 0 !important;\n    flex-grow: 0 !important;\n  }\n  .flex-md-grow-1 {\n    -ms-flex-positive: 1 !important;\n    flex-grow: 1 !important;\n  }\n  .flex-md-shrink-0 {\n    -ms-flex-negative: 0 !important;\n    flex-shrink: 0 !important;\n  }\n  .flex-md-shrink-1 {\n    -ms-flex-negative: 1 !important;\n    flex-shrink: 1 !important;\n  }\n  .justify-content-md-start {\n    -ms-flex-pack: start !important;\n    justify-content: flex-start !important;\n  }\n  .justify-content-md-end {\n    -ms-flex-pack: end !important;\n    justify-content: flex-end !important;\n  }\n  .justify-content-md-center {\n    -ms-flex-pack: center !important;\n    justify-content: center !important;\n  }\n  .justify-content-md-between {\n    -ms-flex-pack: justify !important;\n    justify-content: space-between !important;\n  }\n  .justify-content-md-around {\n    -ms-flex-pack: distribute !important;\n    justify-content: space-around !important;\n  }\n  .align-items-md-start {\n    -ms-flex-align: start !important;\n    align-items: flex-start !important;\n  }\n  .align-items-md-end {\n    -ms-flex-align: end !important;\n    align-items: flex-end !important;\n  }\n  .align-items-md-center {\n    -ms-flex-align: center !important;\n    align-items: center !important;\n  }\n  .align-items-md-baseline {\n    -ms-flex-align: baseline !important;\n    align-items: baseline !important;\n  }\n  .align-items-md-stretch {\n    -ms-flex-align: stretch !important;\n    align-items: stretch !important;\n  }\n  .align-content-md-start {\n    -ms-flex-line-pack: start !important;\n    align-content: flex-start !important;\n  }\n  .align-content-md-end {\n    -ms-flex-line-pack: end !important;\n    align-content: flex-end !important;\n  }\n  .align-content-md-center {\n    -ms-flex-line-pack: center !important;\n    align-content: center !important;\n  }\n  .align-content-md-between {\n    -ms-flex-line-pack: justify !important;\n    align-content: space-between !important;\n  }\n  .align-content-md-around {\n    -ms-flex-line-pack: distribute !important;\n    align-content: space-around !important;\n  }\n  .align-content-md-stretch {\n    -ms-flex-line-pack: stretch !important;\n    align-content: stretch !important;\n  }\n  .align-self-md-auto {\n    -ms-flex-item-align: auto !important;\n    align-self: auto !important;\n  }\n  .align-self-md-start {\n    -ms-flex-item-align: start !important;\n    align-self: flex-start !important;\n  }\n  .align-self-md-end {\n    -ms-flex-item-align: end !important;\n    align-self: flex-end !important;\n  }\n  .align-self-md-center {\n    -ms-flex-item-align: center !important;\n    align-self: center !important;\n  }\n  .align-self-md-baseline {\n    -ms-flex-item-align: baseline !important;\n    align-self: baseline !important;\n  }\n  .align-self-md-stretch {\n    -ms-flex-item-align: stretch !important;\n    align-self: stretch !important;\n  }\n}\n\n@media (min-width: 992px) {\n  .flex-lg-row {\n    -ms-flex-direction: row !important;\n    flex-direction: row !important;\n  }\n  .flex-lg-column {\n    -ms-flex-direction: column !important;\n    flex-direction: column !important;\n  }\n  .flex-lg-row-reverse {\n    -ms-flex-direction: row-reverse !important;\n    flex-direction: row-reverse !important;\n  }\n  .flex-lg-column-reverse {\n    -ms-flex-direction: column-reverse !important;\n    flex-direction: column-reverse !important;\n  }\n  .flex-lg-wrap {\n    -ms-flex-wrap: wrap !important;\n    flex-wrap: wrap !important;\n  }\n  .flex-lg-nowrap {\n    -ms-flex-wrap: nowrap !important;\n    flex-wrap: nowrap !important;\n  }\n  .flex-lg-wrap-reverse {\n    -ms-flex-wrap: wrap-reverse !important;\n    flex-wrap: wrap-reverse !important;\n  }\n  .flex-lg-fill {\n    -ms-flex: 1 1 auto !important;\n    flex: 1 1 auto !important;\n  }\n  .flex-lg-grow-0 {\n    -ms-flex-positive: 0 !important;\n    flex-grow: 0 !important;\n  }\n  .flex-lg-grow-1 {\n    -ms-flex-positive: 1 !important;\n    flex-grow: 1 !important;\n  }\n  .flex-lg-shrink-0 {\n    -ms-flex-negative: 0 !important;\n    flex-shrink: 0 !important;\n  }\n  .flex-lg-shrink-1 {\n    -ms-flex-negative: 1 !important;\n    flex-shrink: 1 !important;\n  }\n  .justify-content-lg-start {\n    -ms-flex-pack: start !important;\n    justify-content: flex-start !important;\n  }\n  .justify-content-lg-end {\n    -ms-flex-pack: end !important;\n    justify-content: flex-end !important;\n  }\n  .justify-content-lg-center {\n    -ms-flex-pack: center !important;\n    justify-content: center !important;\n  }\n  .justify-content-lg-between {\n    -ms-flex-pack: justify !important;\n    justify-content: space-between !important;\n  }\n  .justify-content-lg-around {\n    -ms-flex-pack: distribute !important;\n    justify-content: space-around !important;\n  }\n  .align-items-lg-start {\n    -ms-flex-align: start !important;\n    align-items: flex-start !important;\n  }\n  .align-items-lg-end {\n    -ms-flex-align: end !important;\n    align-items: flex-end !important;\n  }\n  .align-items-lg-center {\n    -ms-flex-align: center !important;\n    align-items: center !important;\n  }\n  .align-items-lg-baseline {\n    -ms-flex-align: baseline !important;\n    align-items: baseline !important;\n  }\n  .align-items-lg-stretch {\n    -ms-flex-align: stretch !important;\n    align-items: stretch !important;\n  }\n  .align-content-lg-start {\n    -ms-flex-line-pack: start !important;\n    align-content: flex-start !important;\n  }\n  .align-content-lg-end {\n    -ms-flex-line-pack: end !important;\n    align-content: flex-end !important;\n  }\n  .align-content-lg-center {\n    -ms-flex-line-pack: center !important;\n    align-content: center !important;\n  }\n  .align-content-lg-between {\n    -ms-flex-line-pack: justify !important;\n    align-content: space-between !important;\n  }\n  .align-content-lg-around {\n    -ms-flex-line-pack: distribute !important;\n    align-content: space-around !important;\n  }\n  .align-content-lg-stretch {\n    -ms-flex-line-pack: stretch !important;\n    align-content: stretch !important;\n  }\n  .align-self-lg-auto {\n    -ms-flex-item-align: auto !important;\n    align-self: auto !important;\n  }\n  .align-self-lg-start {\n    -ms-flex-item-align: start !important;\n    align-self: flex-start !important;\n  }\n  .align-self-lg-end {\n    -ms-flex-item-align: end !important;\n    align-self: flex-end !important;\n  }\n  .align-self-lg-center {\n    -ms-flex-item-align: center !important;\n    align-self: center !important;\n  }\n  .align-self-lg-baseline {\n    -ms-flex-item-align: baseline !important;\n    align-self: baseline !important;\n  }\n  .align-self-lg-stretch {\n    -ms-flex-item-align: stretch !important;\n    align-self: stretch !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .flex-xl-row {\n    -ms-flex-direction: row !important;\n    flex-direction: row !important;\n  }\n  .flex-xl-column {\n    -ms-flex-direction: column !important;\n    flex-direction: column !important;\n  }\n  .flex-xl-row-reverse {\n    -ms-flex-direction: row-reverse !important;\n    flex-direction: row-reverse !important;\n  }\n  .flex-xl-column-reverse {\n    -ms-flex-direction: column-reverse !important;\n    flex-direction: column-reverse !important;\n  }\n  .flex-xl-wrap {\n    -ms-flex-wrap: wrap !important;\n    flex-wrap: wrap !important;\n  }\n  .flex-xl-nowrap {\n    -ms-flex-wrap: nowrap !important;\n    flex-wrap: nowrap !important;\n  }\n  .flex-xl-wrap-reverse {\n    -ms-flex-wrap: wrap-reverse !important;\n    flex-wrap: wrap-reverse !important;\n  }\n  .flex-xl-fill {\n    -ms-flex: 1 1 auto !important;\n    flex: 1 1 auto !important;\n  }\n  .flex-xl-grow-0 {\n    -ms-flex-positive: 0 !important;\n    flex-grow: 0 !important;\n  }\n  .flex-xl-grow-1 {\n    -ms-flex-positive: 1 !important;\n    flex-grow: 1 !important;\n  }\n  .flex-xl-shrink-0 {\n    -ms-flex-negative: 0 !important;\n    flex-shrink: 0 !important;\n  }\n  .flex-xl-shrink-1 {\n    -ms-flex-negative: 1 !important;\n    flex-shrink: 1 !important;\n  }\n  .justify-content-xl-start {\n    -ms-flex-pack: start !important;\n    justify-content: flex-start !important;\n  }\n  .justify-content-xl-end {\n    -ms-flex-pack: end !important;\n    justify-content: flex-end !important;\n  }\n  .justify-content-xl-center {\n    -ms-flex-pack: center !important;\n    justify-content: center !important;\n  }\n  .justify-content-xl-between {\n    -ms-flex-pack: justify !important;\n    justify-content: space-between !important;\n  }\n  .justify-content-xl-around {\n    -ms-flex-pack: distribute !important;\n    justify-content: space-around !important;\n  }\n  .align-items-xl-start {\n    -ms-flex-align: start !important;\n    align-items: flex-start !important;\n  }\n  .align-items-xl-end {\n    -ms-flex-align: end !important;\n    align-items: flex-end !important;\n  }\n  .align-items-xl-center {\n    -ms-flex-align: center !important;\n    align-items: center !important;\n  }\n  .align-items-xl-baseline {\n    -ms-flex-align: baseline !important;\n    align-items: baseline !important;\n  }\n  .align-items-xl-stretch {\n    -ms-flex-align: stretch !important;\n    align-items: stretch !important;\n  }\n  .align-content-xl-start {\n    -ms-flex-line-pack: start !important;\n    align-content: flex-start !important;\n  }\n  .align-content-xl-end {\n    -ms-flex-line-pack: end !important;\n    align-content: flex-end !important;\n  }\n  .align-content-xl-center {\n    -ms-flex-line-pack: center !important;\n    align-content: center !important;\n  }\n  .align-content-xl-between {\n    -ms-flex-line-pack: justify !important;\n    align-content: space-between !important;\n  }\n  .align-content-xl-around {\n    -ms-flex-line-pack: distribute !important;\n    align-content: space-around !important;\n  }\n  .align-content-xl-stretch {\n    -ms-flex-line-pack: stretch !important;\n    align-content: stretch !important;\n  }\n  .align-self-xl-auto {\n    -ms-flex-item-align: auto !important;\n    align-self: auto !important;\n  }\n  .align-self-xl-start {\n    -ms-flex-item-align: start !important;\n    align-self: flex-start !important;\n  }\n  .align-self-xl-end {\n    -ms-flex-item-align: end !important;\n    align-self: flex-end !important;\n  }\n  .align-self-xl-center {\n    -ms-flex-item-align: center !important;\n    align-self: center !important;\n  }\n  .align-self-xl-baseline {\n    -ms-flex-item-align: baseline !important;\n    align-self: baseline !important;\n  }\n  .align-self-xl-stretch {\n    -ms-flex-item-align: stretch !important;\n    align-self: stretch !important;\n  }\n}\n\n.m-0 {\n  margin: 0 !important;\n}\n\n.mt-0,\n.my-0 {\n  margin-top: 0 !important;\n}\n\n.mr-0,\n.mx-0 {\n  margin-right: 0 !important;\n}\n\n.mb-0,\n.my-0 {\n  margin-bottom: 0 !important;\n}\n\n.ml-0,\n.mx-0 {\n  margin-left: 0 !important;\n}\n\n.m-1 {\n  margin: 0.25rem !important;\n}\n\n.mt-1,\n.my-1 {\n  margin-top: 0.25rem !important;\n}\n\n.mr-1,\n.mx-1 {\n  margin-right: 0.25rem !important;\n}\n\n.mb-1,\n.my-1 {\n  margin-bottom: 0.25rem !important;\n}\n\n.ml-1,\n.mx-1 {\n  margin-left: 0.25rem !important;\n}\n\n.m-2 {\n  margin: 0.5rem !important;\n}\n\n.mt-2,\n.my-2 {\n  margin-top: 0.5rem !important;\n}\n\n.mr-2,\n.mx-2 {\n  margin-right: 0.5rem !important;\n}\n\n.mb-2,\n.my-2 {\n  margin-bottom: 0.5rem !important;\n}\n\n.ml-2,\n.mx-2 {\n  margin-left: 0.5rem !important;\n}\n\n.m-3 {\n  margin: 1rem !important;\n}\n\n.mt-3,\n.my-3 {\n  margin-top: 1rem !important;\n}\n\n.mr-3,\n.mx-3 {\n  margin-right: 1rem !important;\n}\n\n.mb-3,\n.my-3 {\n  margin-bottom: 1rem !important;\n}\n\n.ml-3,\n.mx-3 {\n  margin-left: 1rem !important;\n}\n\n.m-4 {\n  margin: 1.5rem !important;\n}\n\n.mt-4,\n.my-4 {\n  margin-top: 1.5rem !important;\n}\n\n.mr-4,\n.mx-4 {\n  margin-right: 1.5rem !important;\n}\n\n.mb-4,\n.my-4 {\n  margin-bottom: 1.5rem !important;\n}\n\n.ml-4,\n.mx-4 {\n  margin-left: 1.5rem !important;\n}\n\n.m-5 {\n  margin: 3rem !important;\n}\n\n.mt-5,\n.my-5 {\n  margin-top: 3rem !important;\n}\n\n.mr-5,\n.mx-5 {\n  margin-right: 3rem !important;\n}\n\n.mb-5,\n.my-5 {\n  margin-bottom: 3rem !important;\n}\n\n.ml-5,\n.mx-5 {\n  margin-left: 3rem !important;\n}\n\n.p-0 {\n  padding: 0 !important;\n}\n\n.pt-0,\n.py-0 {\n  padding-top: 0 !important;\n}\n\n.pr-0,\n.px-0 {\n  padding-right: 0 !important;\n}\n\n.pb-0,\n.py-0 {\n  padding-bottom: 0 !important;\n}\n\n.pl-0,\n.px-0 {\n  padding-left: 0 !important;\n}\n\n.p-1 {\n  padding: 0.25rem !important;\n}\n\n.pt-1,\n.py-1 {\n  padding-top: 0.25rem !important;\n}\n\n.pr-1,\n.px-1 {\n  padding-right: 0.25rem !important;\n}\n\n.pb-1,\n.py-1 {\n  padding-bottom: 0.25rem !important;\n}\n\n.pl-1,\n.px-1 {\n  padding-left: 0.25rem !important;\n}\n\n.p-2 {\n  padding: 0.5rem !important;\n}\n\n.pt-2,\n.py-2 {\n  padding-top: 0.5rem !important;\n}\n\n.pr-2,\n.px-2 {\n  padding-right: 0.5rem !important;\n}\n\n.pb-2,\n.py-2 {\n  padding-bottom: 0.5rem !important;\n}\n\n.pl-2,\n.px-2 {\n  padding-left: 0.5rem !important;\n}\n\n.p-3 {\n  padding: 1rem !important;\n}\n\n.pt-3,\n.py-3 {\n  padding-top: 1rem !important;\n}\n\n.pr-3,\n.px-3 {\n  padding-right: 1rem !important;\n}\n\n.pb-3,\n.py-3 {\n  padding-bottom: 1rem !important;\n}\n\n.pl-3,\n.px-3 {\n  padding-left: 1rem !important;\n}\n\n.p-4 {\n  padding: 1.5rem !important;\n}\n\n.pt-4,\n.py-4 {\n  padding-top: 1.5rem !important;\n}\n\n.pr-4,\n.px-4 {\n  padding-right: 1.5rem !important;\n}\n\n.pb-4,\n.py-4 {\n  padding-bottom: 1.5rem !important;\n}\n\n.pl-4,\n.px-4 {\n  padding-left: 1.5rem !important;\n}\n\n.p-5 {\n  padding: 3rem !important;\n}\n\n.pt-5,\n.py-5 {\n  padding-top: 3rem !important;\n}\n\n.pr-5,\n.px-5 {\n  padding-right: 3rem !important;\n}\n\n.pb-5,\n.py-5 {\n  padding-bottom: 3rem !important;\n}\n\n.pl-5,\n.px-5 {\n  padding-left: 3rem !important;\n}\n\n.m-n1 {\n  margin: -0.25rem !important;\n}\n\n.mt-n1,\n.my-n1 {\n  margin-top: -0.25rem !important;\n}\n\n.mr-n1,\n.mx-n1 {\n  margin-right: -0.25rem !important;\n}\n\n.mb-n1,\n.my-n1 {\n  margin-bottom: -0.25rem !important;\n}\n\n.ml-n1,\n.mx-n1 {\n  margin-left: -0.25rem !important;\n}\n\n.m-n2 {\n  margin: -0.5rem !important;\n}\n\n.mt-n2,\n.my-n2 {\n  margin-top: -0.5rem !important;\n}\n\n.mr-n2,\n.mx-n2 {\n  margin-right: -0.5rem !important;\n}\n\n.mb-n2,\n.my-n2 {\n  margin-bottom: -0.5rem !important;\n}\n\n.ml-n2,\n.mx-n2 {\n  margin-left: -0.5rem !important;\n}\n\n.m-n3 {\n  margin: -1rem !important;\n}\n\n.mt-n3,\n.my-n3 {\n  margin-top: -1rem !important;\n}\n\n.mr-n3,\n.mx-n3 {\n  margin-right: -1rem !important;\n}\n\n.mb-n3,\n.my-n3 {\n  margin-bottom: -1rem !important;\n}\n\n.ml-n3,\n.mx-n3 {\n  margin-left: -1rem !important;\n}\n\n.m-n4 {\n  margin: -1.5rem !important;\n}\n\n.mt-n4,\n.my-n4 {\n  margin-top: -1.5rem !important;\n}\n\n.mr-n4,\n.mx-n4 {\n  margin-right: -1.5rem !important;\n}\n\n.mb-n4,\n.my-n4 {\n  margin-bottom: -1.5rem !important;\n}\n\n.ml-n4,\n.mx-n4 {\n  margin-left: -1.5rem !important;\n}\n\n.m-n5 {\n  margin: -3rem !important;\n}\n\n.mt-n5,\n.my-n5 {\n  margin-top: -3rem !important;\n}\n\n.mr-n5,\n.mx-n5 {\n  margin-right: -3rem !important;\n}\n\n.mb-n5,\n.my-n5 {\n  margin-bottom: -3rem !important;\n}\n\n.ml-n5,\n.mx-n5 {\n  margin-left: -3rem !important;\n}\n\n.m-auto {\n  margin: auto !important;\n}\n\n.mt-auto,\n.my-auto {\n  margin-top: auto !important;\n}\n\n.mr-auto,\n.mx-auto {\n  margin-right: auto !important;\n}\n\n.mb-auto,\n.my-auto {\n  margin-bottom: auto !important;\n}\n\n.ml-auto,\n.mx-auto {\n  margin-left: auto !important;\n}\n\n@media (min-width: 576px) {\n  .m-sm-0 {\n    margin: 0 !important;\n  }\n  .mt-sm-0,\n  .my-sm-0 {\n    margin-top: 0 !important;\n  }\n  .mr-sm-0,\n  .mx-sm-0 {\n    margin-right: 0 !important;\n  }\n  .mb-sm-0,\n  .my-sm-0 {\n    margin-bottom: 0 !important;\n  }\n  .ml-sm-0,\n  .mx-sm-0 {\n    margin-left: 0 !important;\n  }\n  .m-sm-1 {\n    margin: 0.25rem !important;\n  }\n  .mt-sm-1,\n  .my-sm-1 {\n    margin-top: 0.25rem !important;\n  }\n  .mr-sm-1,\n  .mx-sm-1 {\n    margin-right: 0.25rem !important;\n  }\n  .mb-sm-1,\n  .my-sm-1 {\n    margin-bottom: 0.25rem !important;\n  }\n  .ml-sm-1,\n  .mx-sm-1 {\n    margin-left: 0.25rem !important;\n  }\n  .m-sm-2 {\n    margin: 0.5rem !important;\n  }\n  .mt-sm-2,\n  .my-sm-2 {\n    margin-top: 0.5rem !important;\n  }\n  .mr-sm-2,\n  .mx-sm-2 {\n    margin-right: 0.5rem !important;\n  }\n  .mb-sm-2,\n  .my-sm-2 {\n    margin-bottom: 0.5rem !important;\n  }\n  .ml-sm-2,\n  .mx-sm-2 {\n    margin-left: 0.5rem !important;\n  }\n  .m-sm-3 {\n    margin: 1rem !important;\n  }\n  .mt-sm-3,\n  .my-sm-3 {\n    margin-top: 1rem !important;\n  }\n  .mr-sm-3,\n  .mx-sm-3 {\n    margin-right: 1rem !important;\n  }\n  .mb-sm-3,\n  .my-sm-3 {\n    margin-bottom: 1rem !important;\n  }\n  .ml-sm-3,\n  .mx-sm-3 {\n    margin-left: 1rem !important;\n  }\n  .m-sm-4 {\n    margin: 1.5rem !important;\n  }\n  .mt-sm-4,\n  .my-sm-4 {\n    margin-top: 1.5rem !important;\n  }\n  .mr-sm-4,\n  .mx-sm-4 {\n    margin-right: 1.5rem !important;\n  }\n  .mb-sm-4,\n  .my-sm-4 {\n    margin-bottom: 1.5rem !important;\n  }\n  .ml-sm-4,\n  .mx-sm-4 {\n    margin-left: 1.5rem !important;\n  }\n  .m-sm-5 {\n    margin: 3rem !important;\n  }\n  .mt-sm-5,\n  .my-sm-5 {\n    margin-top: 3rem !important;\n  }\n  .mr-sm-5,\n  .mx-sm-5 {\n    margin-right: 3rem !important;\n  }\n  .mb-sm-5,\n  .my-sm-5 {\n    margin-bottom: 3rem !important;\n  }\n  .ml-sm-5,\n  .mx-sm-5 {\n    margin-left: 3rem !important;\n  }\n  .p-sm-0 {\n    padding: 0 !important;\n  }\n  .pt-sm-0,\n  .py-sm-0 {\n    padding-top: 0 !important;\n  }\n  .pr-sm-0,\n  .px-sm-0 {\n    padding-right: 0 !important;\n  }\n  .pb-sm-0,\n  .py-sm-0 {\n    padding-bottom: 0 !important;\n  }\n  .pl-sm-0,\n  .px-sm-0 {\n    padding-left: 0 !important;\n  }\n  .p-sm-1 {\n    padding: 0.25rem !important;\n  }\n  .pt-sm-1,\n  .py-sm-1 {\n    padding-top: 0.25rem !important;\n  }\n  .pr-sm-1,\n  .px-sm-1 {\n    padding-right: 0.25rem !important;\n  }\n  .pb-sm-1,\n  .py-sm-1 {\n    padding-bottom: 0.25rem !important;\n  }\n  .pl-sm-1,\n  .px-sm-1 {\n    padding-left: 0.25rem !important;\n  }\n  .p-sm-2 {\n    padding: 0.5rem !important;\n  }\n  .pt-sm-2,\n  .py-sm-2 {\n    padding-top: 0.5rem !important;\n  }\n  .pr-sm-2,\n  .px-sm-2 {\n    padding-right: 0.5rem !important;\n  }\n  .pb-sm-2,\n  .py-sm-2 {\n    padding-bottom: 0.5rem !important;\n  }\n  .pl-sm-2,\n  .px-sm-2 {\n    padding-left: 0.5rem !important;\n  }\n  .p-sm-3 {\n    padding: 1rem !important;\n  }\n  .pt-sm-3,\n  .py-sm-3 {\n    padding-top: 1rem !important;\n  }\n  .pr-sm-3,\n  .px-sm-3 {\n    padding-right: 1rem !important;\n  }\n  .pb-sm-3,\n  .py-sm-3 {\n    padding-bottom: 1rem !important;\n  }\n  .pl-sm-3,\n  .px-sm-3 {\n    padding-left: 1rem !important;\n  }\n  .p-sm-4 {\n    padding: 1.5rem !important;\n  }\n  .pt-sm-4,\n  .py-sm-4 {\n    padding-top: 1.5rem !important;\n  }\n  .pr-sm-4,\n  .px-sm-4 {\n    padding-right: 1.5rem !important;\n  }\n  .pb-sm-4,\n  .py-sm-4 {\n    padding-bottom: 1.5rem !important;\n  }\n  .pl-sm-4,\n  .px-sm-4 {\n    padding-left: 1.5rem !important;\n  }\n  .p-sm-5 {\n    padding: 3rem !important;\n  }\n  .pt-sm-5,\n  .py-sm-5 {\n    padding-top: 3rem !important;\n  }\n  .pr-sm-5,\n  .px-sm-5 {\n    padding-right: 3rem !important;\n  }\n  .pb-sm-5,\n  .py-sm-5 {\n    padding-bottom: 3rem !important;\n  }\n  .pl-sm-5,\n  .px-sm-5 {\n    padding-left: 3rem !important;\n  }\n  .m-sm-n1 {\n    margin: -0.25rem !important;\n  }\n  .mt-sm-n1,\n  .my-sm-n1 {\n    margin-top: -0.25rem !important;\n  }\n  .mr-sm-n1,\n  .mx-sm-n1 {\n    margin-right: -0.25rem !important;\n  }\n  .mb-sm-n1,\n  .my-sm-n1 {\n    margin-bottom: -0.25rem !important;\n  }\n  .ml-sm-n1,\n  .mx-sm-n1 {\n    margin-left: -0.25rem !important;\n  }\n  .m-sm-n2 {\n    margin: -0.5rem !important;\n  }\n  .mt-sm-n2,\n  .my-sm-n2 {\n    margin-top: -0.5rem !important;\n  }\n  .mr-sm-n2,\n  .mx-sm-n2 {\n    margin-right: -0.5rem !important;\n  }\n  .mb-sm-n2,\n  .my-sm-n2 {\n    margin-bottom: -0.5rem !important;\n  }\n  .ml-sm-n2,\n  .mx-sm-n2 {\n    margin-left: -0.5rem !important;\n  }\n  .m-sm-n3 {\n    margin: -1rem !important;\n  }\n  .mt-sm-n3,\n  .my-sm-n3 {\n    margin-top: -1rem !important;\n  }\n  .mr-sm-n3,\n  .mx-sm-n3 {\n    margin-right: -1rem !important;\n  }\n  .mb-sm-n3,\n  .my-sm-n3 {\n    margin-bottom: -1rem !important;\n  }\n  .ml-sm-n3,\n  .mx-sm-n3 {\n    margin-left: -1rem !important;\n  }\n  .m-sm-n4 {\n    margin: -1.5rem !important;\n  }\n  .mt-sm-n4,\n  .my-sm-n4 {\n    margin-top: -1.5rem !important;\n  }\n  .mr-sm-n4,\n  .mx-sm-n4 {\n    margin-right: -1.5rem !important;\n  }\n  .mb-sm-n4,\n  .my-sm-n4 {\n    margin-bottom: -1.5rem !important;\n  }\n  .ml-sm-n4,\n  .mx-sm-n4 {\n    margin-left: -1.5rem !important;\n  }\n  .m-sm-n5 {\n    margin: -3rem !important;\n  }\n  .mt-sm-n5,\n  .my-sm-n5 {\n    margin-top: -3rem !important;\n  }\n  .mr-sm-n5,\n  .mx-sm-n5 {\n    margin-right: -3rem !important;\n  }\n  .mb-sm-n5,\n  .my-sm-n5 {\n    margin-bottom: -3rem !important;\n  }\n  .ml-sm-n5,\n  .mx-sm-n5 {\n    margin-left: -3rem !important;\n  }\n  .m-sm-auto {\n    margin: auto !important;\n  }\n  .mt-sm-auto,\n  .my-sm-auto {\n    margin-top: auto !important;\n  }\n  .mr-sm-auto,\n  .mx-sm-auto {\n    margin-right: auto !important;\n  }\n  .mb-sm-auto,\n  .my-sm-auto {\n    margin-bottom: auto !important;\n  }\n  .ml-sm-auto,\n  .mx-sm-auto {\n    margin-left: auto !important;\n  }\n}\n\n@media (min-width: 768px) {\n  .m-md-0 {\n    margin: 0 !important;\n  }\n  .mt-md-0,\n  .my-md-0 {\n    margin-top: 0 !important;\n  }\n  .mr-md-0,\n  .mx-md-0 {\n    margin-right: 0 !important;\n  }\n  .mb-md-0,\n  .my-md-0 {\n    margin-bottom: 0 !important;\n  }\n  .ml-md-0,\n  .mx-md-0 {\n    margin-left: 0 !important;\n  }\n  .m-md-1 {\n    margin: 0.25rem !important;\n  }\n  .mt-md-1,\n  .my-md-1 {\n    margin-top: 0.25rem !important;\n  }\n  .mr-md-1,\n  .mx-md-1 {\n    margin-right: 0.25rem !important;\n  }\n  .mb-md-1,\n  .my-md-1 {\n    margin-bottom: 0.25rem !important;\n  }\n  .ml-md-1,\n  .mx-md-1 {\n    margin-left: 0.25rem !important;\n  }\n  .m-md-2 {\n    margin: 0.5rem !important;\n  }\n  .mt-md-2,\n  .my-md-2 {\n    margin-top: 0.5rem !important;\n  }\n  .mr-md-2,\n  .mx-md-2 {\n    margin-right: 0.5rem !important;\n  }\n  .mb-md-2,\n  .my-md-2 {\n    margin-bottom: 0.5rem !important;\n  }\n  .ml-md-2,\n  .mx-md-2 {\n    margin-left: 0.5rem !important;\n  }\n  .m-md-3 {\n    margin: 1rem !important;\n  }\n  .mt-md-3,\n  .my-md-3 {\n    margin-top: 1rem !important;\n  }\n  .mr-md-3,\n  .mx-md-3 {\n    margin-right: 1rem !important;\n  }\n  .mb-md-3,\n  .my-md-3 {\n    margin-bottom: 1rem !important;\n  }\n  .ml-md-3,\n  .mx-md-3 {\n    margin-left: 1rem !important;\n  }\n  .m-md-4 {\n    margin: 1.5rem !important;\n  }\n  .mt-md-4,\n  .my-md-4 {\n    margin-top: 1.5rem !important;\n  }\n  .mr-md-4,\n  .mx-md-4 {\n    margin-right: 1.5rem !important;\n  }\n  .mb-md-4,\n  .my-md-4 {\n    margin-bottom: 1.5rem !important;\n  }\n  .ml-md-4,\n  .mx-md-4 {\n    margin-left: 1.5rem !important;\n  }\n  .m-md-5 {\n    margin: 3rem !important;\n  }\n  .mt-md-5,\n  .my-md-5 {\n    margin-top: 3rem !important;\n  }\n  .mr-md-5,\n  .mx-md-5 {\n    margin-right: 3rem !important;\n  }\n  .mb-md-5,\n  .my-md-5 {\n    margin-bottom: 3rem !important;\n  }\n  .ml-md-5,\n  .mx-md-5 {\n    margin-left: 3rem !important;\n  }\n  .p-md-0 {\n    padding: 0 !important;\n  }\n  .pt-md-0,\n  .py-md-0 {\n    padding-top: 0 !important;\n  }\n  .pr-md-0,\n  .px-md-0 {\n    padding-right: 0 !important;\n  }\n  .pb-md-0,\n  .py-md-0 {\n    padding-bottom: 0 !important;\n  }\n  .pl-md-0,\n  .px-md-0 {\n    padding-left: 0 !important;\n  }\n  .p-md-1 {\n    padding: 0.25rem !important;\n  }\n  .pt-md-1,\n  .py-md-1 {\n    padding-top: 0.25rem !important;\n  }\n  .pr-md-1,\n  .px-md-1 {\n    padding-right: 0.25rem !important;\n  }\n  .pb-md-1,\n  .py-md-1 {\n    padding-bottom: 0.25rem !important;\n  }\n  .pl-md-1,\n  .px-md-1 {\n    padding-left: 0.25rem !important;\n  }\n  .p-md-2 {\n    padding: 0.5rem !important;\n  }\n  .pt-md-2,\n  .py-md-2 {\n    padding-top: 0.5rem !important;\n  }\n  .pr-md-2,\n  .px-md-2 {\n    padding-right: 0.5rem !important;\n  }\n  .pb-md-2,\n  .py-md-2 {\n    padding-bottom: 0.5rem !important;\n  }\n  .pl-md-2,\n  .px-md-2 {\n    padding-left: 0.5rem !important;\n  }\n  .p-md-3 {\n    padding: 1rem !important;\n  }\n  .pt-md-3,\n  .py-md-3 {\n    padding-top: 1rem !important;\n  }\n  .pr-md-3,\n  .px-md-3 {\n    padding-right: 1rem !important;\n  }\n  .pb-md-3,\n  .py-md-3 {\n    padding-bottom: 1rem !important;\n  }\n  .pl-md-3,\n  .px-md-3 {\n    padding-left: 1rem !important;\n  }\n  .p-md-4 {\n    padding: 1.5rem !important;\n  }\n  .pt-md-4,\n  .py-md-4 {\n    padding-top: 1.5rem !important;\n  }\n  .pr-md-4,\n  .px-md-4 {\n    padding-right: 1.5rem !important;\n  }\n  .pb-md-4,\n  .py-md-4 {\n    padding-bottom: 1.5rem !important;\n  }\n  .pl-md-4,\n  .px-md-4 {\n    padding-left: 1.5rem !important;\n  }\n  .p-md-5 {\n    padding: 3rem !important;\n  }\n  .pt-md-5,\n  .py-md-5 {\n    padding-top: 3rem !important;\n  }\n  .pr-md-5,\n  .px-md-5 {\n    padding-right: 3rem !important;\n  }\n  .pb-md-5,\n  .py-md-5 {\n    padding-bottom: 3rem !important;\n  }\n  .pl-md-5,\n  .px-md-5 {\n    padding-left: 3rem !important;\n  }\n  .m-md-n1 {\n    margin: -0.25rem !important;\n  }\n  .mt-md-n1,\n  .my-md-n1 {\n    margin-top: -0.25rem !important;\n  }\n  .mr-md-n1,\n  .mx-md-n1 {\n    margin-right: -0.25rem !important;\n  }\n  .mb-md-n1,\n  .my-md-n1 {\n    margin-bottom: -0.25rem !important;\n  }\n  .ml-md-n1,\n  .mx-md-n1 {\n    margin-left: -0.25rem !important;\n  }\n  .m-md-n2 {\n    margin: -0.5rem !important;\n  }\n  .mt-md-n2,\n  .my-md-n2 {\n    margin-top: -0.5rem !important;\n  }\n  .mr-md-n2,\n  .mx-md-n2 {\n    margin-right: -0.5rem !important;\n  }\n  .mb-md-n2,\n  .my-md-n2 {\n    margin-bottom: -0.5rem !important;\n  }\n  .ml-md-n2,\n  .mx-md-n2 {\n    margin-left: -0.5rem !important;\n  }\n  .m-md-n3 {\n    margin: -1rem !important;\n  }\n  .mt-md-n3,\n  .my-md-n3 {\n    margin-top: -1rem !important;\n  }\n  .mr-md-n3,\n  .mx-md-n3 {\n    margin-right: -1rem !important;\n  }\n  .mb-md-n3,\n  .my-md-n3 {\n    margin-bottom: -1rem !important;\n  }\n  .ml-md-n3,\n  .mx-md-n3 {\n    margin-left: -1rem !important;\n  }\n  .m-md-n4 {\n    margin: -1.5rem !important;\n  }\n  .mt-md-n4,\n  .my-md-n4 {\n    margin-top: -1.5rem !important;\n  }\n  .mr-md-n4,\n  .mx-md-n4 {\n    margin-right: -1.5rem !important;\n  }\n  .mb-md-n4,\n  .my-md-n4 {\n    margin-bottom: -1.5rem !important;\n  }\n  .ml-md-n4,\n  .mx-md-n4 {\n    margin-left: -1.5rem !important;\n  }\n  .m-md-n5 {\n    margin: -3rem !important;\n  }\n  .mt-md-n5,\n  .my-md-n5 {\n    margin-top: -3rem !important;\n  }\n  .mr-md-n5,\n  .mx-md-n5 {\n    margin-right: -3rem !important;\n  }\n  .mb-md-n5,\n  .my-md-n5 {\n    margin-bottom: -3rem !important;\n  }\n  .ml-md-n5,\n  .mx-md-n5 {\n    margin-left: -3rem !important;\n  }\n  .m-md-auto {\n    margin: auto !important;\n  }\n  .mt-md-auto,\n  .my-md-auto {\n    margin-top: auto !important;\n  }\n  .mr-md-auto,\n  .mx-md-auto {\n    margin-right: auto !important;\n  }\n  .mb-md-auto,\n  .my-md-auto {\n    margin-bottom: auto !important;\n  }\n  .ml-md-auto,\n  .mx-md-auto {\n    margin-left: auto !important;\n  }\n}\n\n@media (min-width: 992px) {\n  .m-lg-0 {\n    margin: 0 !important;\n  }\n  .mt-lg-0,\n  .my-lg-0 {\n    margin-top: 0 !important;\n  }\n  .mr-lg-0,\n  .mx-lg-0 {\n    margin-right: 0 !important;\n  }\n  .mb-lg-0,\n  .my-lg-0 {\n    margin-bottom: 0 !important;\n  }\n  .ml-lg-0,\n  .mx-lg-0 {\n    margin-left: 0 !important;\n  }\n  .m-lg-1 {\n    margin: 0.25rem !important;\n  }\n  .mt-lg-1,\n  .my-lg-1 {\n    margin-top: 0.25rem !important;\n  }\n  .mr-lg-1,\n  .mx-lg-1 {\n    margin-right: 0.25rem !important;\n  }\n  .mb-lg-1,\n  .my-lg-1 {\n    margin-bottom: 0.25rem !important;\n  }\n  .ml-lg-1,\n  .mx-lg-1 {\n    margin-left: 0.25rem !important;\n  }\n  .m-lg-2 {\n    margin: 0.5rem !important;\n  }\n  .mt-lg-2,\n  .my-lg-2 {\n    margin-top: 0.5rem !important;\n  }\n  .mr-lg-2,\n  .mx-lg-2 {\n    margin-right: 0.5rem !important;\n  }\n  .mb-lg-2,\n  .my-lg-2 {\n    margin-bottom: 0.5rem !important;\n  }\n  .ml-lg-2,\n  .mx-lg-2 {\n    margin-left: 0.5rem !important;\n  }\n  .m-lg-3 {\n    margin: 1rem !important;\n  }\n  .mt-lg-3,\n  .my-lg-3 {\n    margin-top: 1rem !important;\n  }\n  .mr-lg-3,\n  .mx-lg-3 {\n    margin-right: 1rem !important;\n  }\n  .mb-lg-3,\n  .my-lg-3 {\n    margin-bottom: 1rem !important;\n  }\n  .ml-lg-3,\n  .mx-lg-3 {\n    margin-left: 1rem !important;\n  }\n  .m-lg-4 {\n    margin: 1.5rem !important;\n  }\n  .mt-lg-4,\n  .my-lg-4 {\n    margin-top: 1.5rem !important;\n  }\n  .mr-lg-4,\n  .mx-lg-4 {\n    margin-right: 1.5rem !important;\n  }\n  .mb-lg-4,\n  .my-lg-4 {\n    margin-bottom: 1.5rem !important;\n  }\n  .ml-lg-4,\n  .mx-lg-4 {\n    margin-left: 1.5rem !important;\n  }\n  .m-lg-5 {\n    margin: 3rem !important;\n  }\n  .mt-lg-5,\n  .my-lg-5 {\n    margin-top: 3rem !important;\n  }\n  .mr-lg-5,\n  .mx-lg-5 {\n    margin-right: 3rem !important;\n  }\n  .mb-lg-5,\n  .my-lg-5 {\n    margin-bottom: 3rem !important;\n  }\n  .ml-lg-5,\n  .mx-lg-5 {\n    margin-left: 3rem !important;\n  }\n  .p-lg-0 {\n    padding: 0 !important;\n  }\n  .pt-lg-0,\n  .py-lg-0 {\n    padding-top: 0 !important;\n  }\n  .pr-lg-0,\n  .px-lg-0 {\n    padding-right: 0 !important;\n  }\n  .pb-lg-0,\n  .py-lg-0 {\n    padding-bottom: 0 !important;\n  }\n  .pl-lg-0,\n  .px-lg-0 {\n    padding-left: 0 !important;\n  }\n  .p-lg-1 {\n    padding: 0.25rem !important;\n  }\n  .pt-lg-1,\n  .py-lg-1 {\n    padding-top: 0.25rem !important;\n  }\n  .pr-lg-1,\n  .px-lg-1 {\n    padding-right: 0.25rem !important;\n  }\n  .pb-lg-1,\n  .py-lg-1 {\n    padding-bottom: 0.25rem !important;\n  }\n  .pl-lg-1,\n  .px-lg-1 {\n    padding-left: 0.25rem !important;\n  }\n  .p-lg-2 {\n    padding: 0.5rem !important;\n  }\n  .pt-lg-2,\n  .py-lg-2 {\n    padding-top: 0.5rem !important;\n  }\n  .pr-lg-2,\n  .px-lg-2 {\n    padding-right: 0.5rem !important;\n  }\n  .pb-lg-2,\n  .py-lg-2 {\n    padding-bottom: 0.5rem !important;\n  }\n  .pl-lg-2,\n  .px-lg-2 {\n    padding-left: 0.5rem !important;\n  }\n  .p-lg-3 {\n    padding: 1rem !important;\n  }\n  .pt-lg-3,\n  .py-lg-3 {\n    padding-top: 1rem !important;\n  }\n  .pr-lg-3,\n  .px-lg-3 {\n    padding-right: 1rem !important;\n  }\n  .pb-lg-3,\n  .py-lg-3 {\n    padding-bottom: 1rem !important;\n  }\n  .pl-lg-3,\n  .px-lg-3 {\n    padding-left: 1rem !important;\n  }\n  .p-lg-4 {\n    padding: 1.5rem !important;\n  }\n  .pt-lg-4,\n  .py-lg-4 {\n    padding-top: 1.5rem !important;\n  }\n  .pr-lg-4,\n  .px-lg-4 {\n    padding-right: 1.5rem !important;\n  }\n  .pb-lg-4,\n  .py-lg-4 {\n    padding-bottom: 1.5rem !important;\n  }\n  .pl-lg-4,\n  .px-lg-4 {\n    padding-left: 1.5rem !important;\n  }\n  .p-lg-5 {\n    padding: 3rem !important;\n  }\n  .pt-lg-5,\n  .py-lg-5 {\n    padding-top: 3rem !important;\n  }\n  .pr-lg-5,\n  .px-lg-5 {\n    padding-right: 3rem !important;\n  }\n  .pb-lg-5,\n  .py-lg-5 {\n    padding-bottom: 3rem !important;\n  }\n  .pl-lg-5,\n  .px-lg-5 {\n    padding-left: 3rem !important;\n  }\n  .m-lg-n1 {\n    margin: -0.25rem !important;\n  }\n  .mt-lg-n1,\n  .my-lg-n1 {\n    margin-top: -0.25rem !important;\n  }\n  .mr-lg-n1,\n  .mx-lg-n1 {\n    margin-right: -0.25rem !important;\n  }\n  .mb-lg-n1,\n  .my-lg-n1 {\n    margin-bottom: -0.25rem !important;\n  }\n  .ml-lg-n1,\n  .mx-lg-n1 {\n    margin-left: -0.25rem !important;\n  }\n  .m-lg-n2 {\n    margin: -0.5rem !important;\n  }\n  .mt-lg-n2,\n  .my-lg-n2 {\n    margin-top: -0.5rem !important;\n  }\n  .mr-lg-n2,\n  .mx-lg-n2 {\n    margin-right: -0.5rem !important;\n  }\n  .mb-lg-n2,\n  .my-lg-n2 {\n    margin-bottom: -0.5rem !important;\n  }\n  .ml-lg-n2,\n  .mx-lg-n2 {\n    margin-left: -0.5rem !important;\n  }\n  .m-lg-n3 {\n    margin: -1rem !important;\n  }\n  .mt-lg-n3,\n  .my-lg-n3 {\n    margin-top: -1rem !important;\n  }\n  .mr-lg-n3,\n  .mx-lg-n3 {\n    margin-right: -1rem !important;\n  }\n  .mb-lg-n3,\n  .my-lg-n3 {\n    margin-bottom: -1rem !important;\n  }\n  .ml-lg-n3,\n  .mx-lg-n3 {\n    margin-left: -1rem !important;\n  }\n  .m-lg-n4 {\n    margin: -1.5rem !important;\n  }\n  .mt-lg-n4,\n  .my-lg-n4 {\n    margin-top: -1.5rem !important;\n  }\n  .mr-lg-n4,\n  .mx-lg-n4 {\n    margin-right: -1.5rem !important;\n  }\n  .mb-lg-n4,\n  .my-lg-n4 {\n    margin-bottom: -1.5rem !important;\n  }\n  .ml-lg-n4,\n  .mx-lg-n4 {\n    margin-left: -1.5rem !important;\n  }\n  .m-lg-n5 {\n    margin: -3rem !important;\n  }\n  .mt-lg-n5,\n  .my-lg-n5 {\n    margin-top: -3rem !important;\n  }\n  .mr-lg-n5,\n  .mx-lg-n5 {\n    margin-right: -3rem !important;\n  }\n  .mb-lg-n5,\n  .my-lg-n5 {\n    margin-bottom: -3rem !important;\n  }\n  .ml-lg-n5,\n  .mx-lg-n5 {\n    margin-left: -3rem !important;\n  }\n  .m-lg-auto {\n    margin: auto !important;\n  }\n  .mt-lg-auto,\n  .my-lg-auto {\n    margin-top: auto !important;\n  }\n  .mr-lg-auto,\n  .mx-lg-auto {\n    margin-right: auto !important;\n  }\n  .mb-lg-auto,\n  .my-lg-auto {\n    margin-bottom: auto !important;\n  }\n  .ml-lg-auto,\n  .mx-lg-auto {\n    margin-left: auto !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .m-xl-0 {\n    margin: 0 !important;\n  }\n  .mt-xl-0,\n  .my-xl-0 {\n    margin-top: 0 !important;\n  }\n  .mr-xl-0,\n  .mx-xl-0 {\n    margin-right: 0 !important;\n  }\n  .mb-xl-0,\n  .my-xl-0 {\n    margin-bottom: 0 !important;\n  }\n  .ml-xl-0,\n  .mx-xl-0 {\n    margin-left: 0 !important;\n  }\n  .m-xl-1 {\n    margin: 0.25rem !important;\n  }\n  .mt-xl-1,\n  .my-xl-1 {\n    margin-top: 0.25rem !important;\n  }\n  .mr-xl-1,\n  .mx-xl-1 {\n    margin-right: 0.25rem !important;\n  }\n  .mb-xl-1,\n  .my-xl-1 {\n    margin-bottom: 0.25rem !important;\n  }\n  .ml-xl-1,\n  .mx-xl-1 {\n    margin-left: 0.25rem !important;\n  }\n  .m-xl-2 {\n    margin: 0.5rem !important;\n  }\n  .mt-xl-2,\n  .my-xl-2 {\n    margin-top: 0.5rem !important;\n  }\n  .mr-xl-2,\n  .mx-xl-2 {\n    margin-right: 0.5rem !important;\n  }\n  .mb-xl-2,\n  .my-xl-2 {\n    margin-bottom: 0.5rem !important;\n  }\n  .ml-xl-2,\n  .mx-xl-2 {\n    margin-left: 0.5rem !important;\n  }\n  .m-xl-3 {\n    margin: 1rem !important;\n  }\n  .mt-xl-3,\n  .my-xl-3 {\n    margin-top: 1rem !important;\n  }\n  .mr-xl-3,\n  .mx-xl-3 {\n    margin-right: 1rem !important;\n  }\n  .mb-xl-3,\n  .my-xl-3 {\n    margin-bottom: 1rem !important;\n  }\n  .ml-xl-3,\n  .mx-xl-3 {\n    margin-left: 1rem !important;\n  }\n  .m-xl-4 {\n    margin: 1.5rem !important;\n  }\n  .mt-xl-4,\n  .my-xl-4 {\n    margin-top: 1.5rem !important;\n  }\n  .mr-xl-4,\n  .mx-xl-4 {\n    margin-right: 1.5rem !important;\n  }\n  .mb-xl-4,\n  .my-xl-4 {\n    margin-bottom: 1.5rem !important;\n  }\n  .ml-xl-4,\n  .mx-xl-4 {\n    margin-left: 1.5rem !important;\n  }\n  .m-xl-5 {\n    margin: 3rem !important;\n  }\n  .mt-xl-5,\n  .my-xl-5 {\n    margin-top: 3rem !important;\n  }\n  .mr-xl-5,\n  .mx-xl-5 {\n    margin-right: 3rem !important;\n  }\n  .mb-xl-5,\n  .my-xl-5 {\n    margin-bottom: 3rem !important;\n  }\n  .ml-xl-5,\n  .mx-xl-5 {\n    margin-left: 3rem !important;\n  }\n  .p-xl-0 {\n    padding: 0 !important;\n  }\n  .pt-xl-0,\n  .py-xl-0 {\n    padding-top: 0 !important;\n  }\n  .pr-xl-0,\n  .px-xl-0 {\n    padding-right: 0 !important;\n  }\n  .pb-xl-0,\n  .py-xl-0 {\n    padding-bottom: 0 !important;\n  }\n  .pl-xl-0,\n  .px-xl-0 {\n    padding-left: 0 !important;\n  }\n  .p-xl-1 {\n    padding: 0.25rem !important;\n  }\n  .pt-xl-1,\n  .py-xl-1 {\n    padding-top: 0.25rem !important;\n  }\n  .pr-xl-1,\n  .px-xl-1 {\n    padding-right: 0.25rem !important;\n  }\n  .pb-xl-1,\n  .py-xl-1 {\n    padding-bottom: 0.25rem !important;\n  }\n  .pl-xl-1,\n  .px-xl-1 {\n    padding-left: 0.25rem !important;\n  }\n  .p-xl-2 {\n    padding: 0.5rem !important;\n  }\n  .pt-xl-2,\n  .py-xl-2 {\n    padding-top: 0.5rem !important;\n  }\n  .pr-xl-2,\n  .px-xl-2 {\n    padding-right: 0.5rem !important;\n  }\n  .pb-xl-2,\n  .py-xl-2 {\n    padding-bottom: 0.5rem !important;\n  }\n  .pl-xl-2,\n  .px-xl-2 {\n    padding-left: 0.5rem !important;\n  }\n  .p-xl-3 {\n    padding: 1rem !important;\n  }\n  .pt-xl-3,\n  .py-xl-3 {\n    padding-top: 1rem !important;\n  }\n  .pr-xl-3,\n  .px-xl-3 {\n    padding-right: 1rem !important;\n  }\n  .pb-xl-3,\n  .py-xl-3 {\n    padding-bottom: 1rem !important;\n  }\n  .pl-xl-3,\n  .px-xl-3 {\n    padding-left: 1rem !important;\n  }\n  .p-xl-4 {\n    padding: 1.5rem !important;\n  }\n  .pt-xl-4,\n  .py-xl-4 {\n    padding-top: 1.5rem !important;\n  }\n  .pr-xl-4,\n  .px-xl-4 {\n    padding-right: 1.5rem !important;\n  }\n  .pb-xl-4,\n  .py-xl-4 {\n    padding-bottom: 1.5rem !important;\n  }\n  .pl-xl-4,\n  .px-xl-4 {\n    padding-left: 1.5rem !important;\n  }\n  .p-xl-5 {\n    padding: 3rem !important;\n  }\n  .pt-xl-5,\n  .py-xl-5 {\n    padding-top: 3rem !important;\n  }\n  .pr-xl-5,\n  .px-xl-5 {\n    padding-right: 3rem !important;\n  }\n  .pb-xl-5,\n  .py-xl-5 {\n    padding-bottom: 3rem !important;\n  }\n  .pl-xl-5,\n  .px-xl-5 {\n    padding-left: 3rem !important;\n  }\n  .m-xl-n1 {\n    margin: -0.25rem !important;\n  }\n  .mt-xl-n1,\n  .my-xl-n1 {\n    margin-top: -0.25rem !important;\n  }\n  .mr-xl-n1,\n  .mx-xl-n1 {\n    margin-right: -0.25rem !important;\n  }\n  .mb-xl-n1,\n  .my-xl-n1 {\n    margin-bottom: -0.25rem !important;\n  }\n  .ml-xl-n1,\n  .mx-xl-n1 {\n    margin-left: -0.25rem !important;\n  }\n  .m-xl-n2 {\n    margin: -0.5rem !important;\n  }\n  .mt-xl-n2,\n  .my-xl-n2 {\n    margin-top: -0.5rem !important;\n  }\n  .mr-xl-n2,\n  .mx-xl-n2 {\n    margin-right: -0.5rem !important;\n  }\n  .mb-xl-n2,\n  .my-xl-n2 {\n    margin-bottom: -0.5rem !important;\n  }\n  .ml-xl-n2,\n  .mx-xl-n2 {\n    margin-left: -0.5rem !important;\n  }\n  .m-xl-n3 {\n    margin: -1rem !important;\n  }\n  .mt-xl-n3,\n  .my-xl-n3 {\n    margin-top: -1rem !important;\n  }\n  .mr-xl-n3,\n  .mx-xl-n3 {\n    margin-right: -1rem !important;\n  }\n  .mb-xl-n3,\n  .my-xl-n3 {\n    margin-bottom: -1rem !important;\n  }\n  .ml-xl-n3,\n  .mx-xl-n3 {\n    margin-left: -1rem !important;\n  }\n  .m-xl-n4 {\n    margin: -1.5rem !important;\n  }\n  .mt-xl-n4,\n  .my-xl-n4 {\n    margin-top: -1.5rem !important;\n  }\n  .mr-xl-n4,\n  .mx-xl-n4 {\n    margin-right: -1.5rem !important;\n  }\n  .mb-xl-n4,\n  .my-xl-n4 {\n    margin-bottom: -1.5rem !important;\n  }\n  .ml-xl-n4,\n  .mx-xl-n4 {\n    margin-left: -1.5rem !important;\n  }\n  .m-xl-n5 {\n    margin: -3rem !important;\n  }\n  .mt-xl-n5,\n  .my-xl-n5 {\n    margin-top: -3rem !important;\n  }\n  .mr-xl-n5,\n  .mx-xl-n5 {\n    margin-right: -3rem !important;\n  }\n  .mb-xl-n5,\n  .my-xl-n5 {\n    margin-bottom: -3rem !important;\n  }\n  .ml-xl-n5,\n  .mx-xl-n5 {\n    margin-left: -3rem !important;\n  }\n  .m-xl-auto {\n    margin: auto !important;\n  }\n  .mt-xl-auto,\n  .my-xl-auto {\n    margin-top: auto !important;\n  }\n  .mr-xl-auto,\n  .mx-xl-auto {\n    margin-right: auto !important;\n  }\n  .mb-xl-auto,\n  .my-xl-auto {\n    margin-bottom: auto !important;\n  }\n  .ml-xl-auto,\n  .mx-xl-auto {\n    margin-left: auto !important;\n  }\n}\n/*# sourceMappingURL=bootstrap-grid.css.map */"
  },
  {
    "path": "src/IdentityServer/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css",
    "content": "/*!\n * Bootstrap Reboot v4.5.3 (https://getbootstrap.com/)\n * Copyright 2011-2020 The Bootstrap Authors\n * Copyright 2011-2020 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n*,\n*::before,\n*::after {\n  box-sizing: border-box;\n}\n\nhtml {\n  font-family: sans-serif;\n  line-height: 1.15;\n  -webkit-text-size-adjust: 100%;\n  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n  display: block;\n}\n\nbody {\n  margin: 0;\n  font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n  font-size: 1rem;\n  font-weight: 400;\n  line-height: 1.5;\n  color: #212529;\n  text-align: left;\n  background-color: #fff;\n}\n\n[tabindex=\"-1\"]:focus:not(:focus-visible) {\n  outline: 0 !important;\n}\n\nhr {\n  box-sizing: content-box;\n  height: 0;\n  overflow: visible;\n}\n\nh1, h2, h3, h4, h5, h6 {\n  margin-top: 0;\n  margin-bottom: 0.5rem;\n}\n\np {\n  margin-top: 0;\n  margin-bottom: 1rem;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  text-decoration: underline;\n  -webkit-text-decoration: underline dotted;\n  text-decoration: underline dotted;\n  cursor: help;\n  border-bottom: 0;\n  -webkit-text-decoration-skip-ink: none;\n  text-decoration-skip-ink: none;\n}\n\naddress {\n  margin-bottom: 1rem;\n  font-style: normal;\n  line-height: inherit;\n}\n\nol,\nul,\ndl {\n  margin-top: 0;\n  margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n  margin-bottom: 0;\n}\n\ndt {\n  font-weight: 700;\n}\n\ndd {\n  margin-bottom: .5rem;\n  margin-left: 0;\n}\n\nblockquote {\n  margin: 0 0 1rem;\n}\n\nb,\nstrong {\n  font-weight: bolder;\n}\n\nsmall {\n  font-size: 80%;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsub {\n  bottom: -.25em;\n}\n\nsup {\n  top: -.5em;\n}\n\na {\n  color: #007bff;\n  text-decoration: none;\n  background-color: transparent;\n}\n\na:hover {\n  color: #0056b3;\n  text-decoration: underline;\n}\n\na:not([href]):not([class]) {\n  color: inherit;\n  text-decoration: none;\n}\n\na:not([href]):not([class]):hover {\n  color: inherit;\n  text-decoration: none;\n}\n\npre,\ncode,\nkbd,\nsamp {\n  font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n  font-size: 1em;\n}\n\npre {\n  margin-top: 0;\n  margin-bottom: 1rem;\n  overflow: auto;\n  -ms-overflow-style: scrollbar;\n}\n\nfigure {\n  margin: 0 0 1rem;\n}\n\nimg {\n  vertical-align: middle;\n  border-style: none;\n}\n\nsvg {\n  overflow: hidden;\n  vertical-align: middle;\n}\n\ntable {\n  border-collapse: collapse;\n}\n\ncaption {\n  padding-top: 0.75rem;\n  padding-bottom: 0.75rem;\n  color: #6c757d;\n  text-align: left;\n  caption-side: bottom;\n}\n\nth {\n  text-align: inherit;\n  text-align: -webkit-match-parent;\n}\n\nlabel {\n  display: inline-block;\n  margin-bottom: 0.5rem;\n}\n\nbutton {\n  border-radius: 0;\n}\n\nbutton:focus {\n  outline: 1px dotted;\n  outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n  margin: 0;\n  font-family: inherit;\n  font-size: inherit;\n  line-height: inherit;\n}\n\nbutton,\ninput {\n  overflow: visible;\n}\n\nbutton,\nselect {\n  text-transform: none;\n}\n\n[role=\"button\"] {\n  cursor: pointer;\n}\n\nselect {\n  word-wrap: normal;\n}\n\nbutton,\n[type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n  -webkit-appearance: button;\n}\n\nbutton:not(:disabled),\n[type=\"button\"]:not(:disabled),\n[type=\"reset\"]:not(:disabled),\n[type=\"submit\"]:not(:disabled) {\n  cursor: pointer;\n}\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n  padding: 0;\n  border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  box-sizing: border-box;\n  padding: 0;\n}\n\ntextarea {\n  overflow: auto;\n  resize: vertical;\n}\n\nfieldset {\n  min-width: 0;\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  max-width: 100%;\n  padding: 0;\n  margin-bottom: .5rem;\n  font-size: 1.5rem;\n  line-height: inherit;\n  color: inherit;\n  white-space: normal;\n}\n\nprogress {\n  vertical-align: baseline;\n}\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n  height: auto;\n}\n\n[type=\"search\"] {\n  outline-offset: -2px;\n  -webkit-appearance: none;\n}\n\n[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n\n::-webkit-file-upload-button {\n  font: inherit;\n  -webkit-appearance: button;\n}\n\noutput {\n  display: inline-block;\n}\n\nsummary {\n  display: list-item;\n  cursor: pointer;\n}\n\ntemplate {\n  display: none;\n}\n\n[hidden] {\n  display: none !important;\n}\n/*# sourceMappingURL=bootstrap-reboot.css.map */"
  },
  {
    "path": "src/IdentityServer/wwwroot/lib/bootstrap/dist/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v4.5.3 (https://getbootstrap.com/)\n * Copyright 2011-2020 The Bootstrap Authors\n * Copyright 2011-2020 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n */\n:root {\n  --blue: #007bff;\n  --indigo: #6610f2;\n  --purple: #6f42c1;\n  --pink: #e83e8c;\n  --red: #dc3545;\n  --orange: #fd7e14;\n  --yellow: #ffc107;\n  --green: #28a745;\n  --teal: #20c997;\n  --cyan: #17a2b8;\n  --white: #fff;\n  --gray: #6c757d;\n  --gray-dark: #343a40;\n  --primary: #007bff;\n  --secondary: #6c757d;\n  --success: #28a745;\n  --info: #17a2b8;\n  --warning: #ffc107;\n  --danger: #dc3545;\n  --light: #f8f9fa;\n  --dark: #343a40;\n  --breakpoint-xs: 0;\n  --breakpoint-sm: 576px;\n  --breakpoint-md: 768px;\n  --breakpoint-lg: 992px;\n  --breakpoint-xl: 1200px;\n  --font-family-sans-serif: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n  --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n}\n\n*,\n*::before,\n*::after {\n  box-sizing: border-box;\n}\n\nhtml {\n  font-family: sans-serif;\n  line-height: 1.15;\n  -webkit-text-size-adjust: 100%;\n  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n  display: block;\n}\n\nbody {\n  margin: 0;\n  font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n  font-size: 1rem;\n  font-weight: 400;\n  line-height: 1.5;\n  color: #212529;\n  text-align: left;\n  background-color: #fff;\n}\n\n[tabindex=\"-1\"]:focus:not(:focus-visible) {\n  outline: 0 !important;\n}\n\nhr {\n  box-sizing: content-box;\n  height: 0;\n  overflow: visible;\n}\n\nh1, h2, h3, h4, h5, h6 {\n  margin-top: 0;\n  margin-bottom: 0.5rem;\n}\n\np {\n  margin-top: 0;\n  margin-bottom: 1rem;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  text-decoration: underline;\n  -webkit-text-decoration: underline dotted;\n  text-decoration: underline dotted;\n  cursor: help;\n  border-bottom: 0;\n  -webkit-text-decoration-skip-ink: none;\n  text-decoration-skip-ink: none;\n}\n\naddress {\n  margin-bottom: 1rem;\n  font-style: normal;\n  line-height: inherit;\n}\n\nol,\nul,\ndl {\n  margin-top: 0;\n  margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n  margin-bottom: 0;\n}\n\ndt {\n  font-weight: 700;\n}\n\ndd {\n  margin-bottom: .5rem;\n  margin-left: 0;\n}\n\nblockquote {\n  margin: 0 0 1rem;\n}\n\nb,\nstrong {\n  font-weight: bolder;\n}\n\nsmall {\n  font-size: 80%;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsub {\n  bottom: -.25em;\n}\n\nsup {\n  top: -.5em;\n}\n\na {\n  color: #007bff;\n  text-decoration: none;\n  background-color: transparent;\n}\n\na:hover {\n  color: #0056b3;\n  text-decoration: underline;\n}\n\na:not([href]):not([class]) {\n  color: inherit;\n  text-decoration: none;\n}\n\na:not([href]):not([class]):hover {\n  color: inherit;\n  text-decoration: none;\n}\n\npre,\ncode,\nkbd,\nsamp {\n  font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n  font-size: 1em;\n}\n\npre {\n  margin-top: 0;\n  margin-bottom: 1rem;\n  overflow: auto;\n  -ms-overflow-style: scrollbar;\n}\n\nfigure {\n  margin: 0 0 1rem;\n}\n\nimg {\n  vertical-align: middle;\n  border-style: none;\n}\n\nsvg {\n  overflow: hidden;\n  vertical-align: middle;\n}\n\ntable {\n  border-collapse: collapse;\n}\n\ncaption {\n  padding-top: 0.75rem;\n  padding-bottom: 0.75rem;\n  color: #6c757d;\n  text-align: left;\n  caption-side: bottom;\n}\n\nth {\n  text-align: inherit;\n  text-align: -webkit-match-parent;\n}\n\nlabel {\n  display: inline-block;\n  margin-bottom: 0.5rem;\n}\n\nbutton {\n  border-radius: 0;\n}\n\nbutton:focus {\n  outline: 1px dotted;\n  outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n  margin: 0;\n  font-family: inherit;\n  font-size: inherit;\n  line-height: inherit;\n}\n\nbutton,\ninput {\n  overflow: visible;\n}\n\nbutton,\nselect {\n  text-transform: none;\n}\n\n[role=\"button\"] {\n  cursor: pointer;\n}\n\nselect {\n  word-wrap: normal;\n}\n\nbutton,\n[type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n  -webkit-appearance: button;\n}\n\nbutton:not(:disabled),\n[type=\"button\"]:not(:disabled),\n[type=\"reset\"]:not(:disabled),\n[type=\"submit\"]:not(:disabled) {\n  cursor: pointer;\n}\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n  padding: 0;\n  border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  box-sizing: border-box;\n  padding: 0;\n}\n\ntextarea {\n  overflow: auto;\n  resize: vertical;\n}\n\nfieldset {\n  min-width: 0;\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  max-width: 100%;\n  padding: 0;\n  margin-bottom: .5rem;\n  font-size: 1.5rem;\n  line-height: inherit;\n  color: inherit;\n  white-space: normal;\n}\n\nprogress {\n  vertical-align: baseline;\n}\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n  height: auto;\n}\n\n[type=\"search\"] {\n  outline-offset: -2px;\n  -webkit-appearance: none;\n}\n\n[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n\n::-webkit-file-upload-button {\n  font: inherit;\n  -webkit-appearance: button;\n}\n\noutput {\n  display: inline-block;\n}\n\nsummary {\n  display: list-item;\n  cursor: pointer;\n}\n\ntemplate {\n  display: none;\n}\n\n[hidden] {\n  display: none !important;\n}\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n  margin-bottom: 0.5rem;\n  font-weight: 500;\n  line-height: 1.2;\n}\n\nh1, .h1 {\n  font-size: 2.5rem;\n}\n\nh2, .h2 {\n  font-size: 2rem;\n}\n\nh3, .h3 {\n  font-size: 1.75rem;\n}\n\nh4, .h4 {\n  font-size: 1.5rem;\n}\n\nh5, .h5 {\n  font-size: 1.25rem;\n}\n\nh6, .h6 {\n  font-size: 1rem;\n}\n\n.lead {\n  font-size: 1.25rem;\n  font-weight: 300;\n}\n\n.display-1 {\n  font-size: 6rem;\n  font-weight: 300;\n  line-height: 1.2;\n}\n\n.display-2 {\n  font-size: 5.5rem;\n  font-weight: 300;\n  line-height: 1.2;\n}\n\n.display-3 {\n  font-size: 4.5rem;\n  font-weight: 300;\n  line-height: 1.2;\n}\n\n.display-4 {\n  font-size: 3.5rem;\n  font-weight: 300;\n  line-height: 1.2;\n}\n\nhr {\n  margin-top: 1rem;\n  margin-bottom: 1rem;\n  border: 0;\n  border-top: 1px solid rgba(0, 0, 0, 0.1);\n}\n\nsmall,\n.small {\n  font-size: 80%;\n  font-weight: 400;\n}\n\nmark,\n.mark {\n  padding: 0.2em;\n  background-color: #fcf8e3;\n}\n\n.list-unstyled {\n  padding-left: 0;\n  list-style: none;\n}\n\n.list-inline {\n  padding-left: 0;\n  list-style: none;\n}\n\n.list-inline-item {\n  display: inline-block;\n}\n\n.list-inline-item:not(:last-child) {\n  margin-right: 0.5rem;\n}\n\n.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\n.blockquote {\n  margin-bottom: 1rem;\n  font-size: 1.25rem;\n}\n\n.blockquote-footer {\n  display: block;\n  font-size: 80%;\n  color: #6c757d;\n}\n\n.blockquote-footer::before {\n  content: \"\\2014\\00A0\";\n}\n\n.img-fluid {\n  max-width: 100%;\n  height: auto;\n}\n\n.img-thumbnail {\n  padding: 0.25rem;\n  background-color: #fff;\n  border: 1px solid #dee2e6;\n  border-radius: 0.25rem;\n  max-width: 100%;\n  height: auto;\n}\n\n.figure {\n  display: inline-block;\n}\n\n.figure-img {\n  margin-bottom: 0.5rem;\n  line-height: 1;\n}\n\n.figure-caption {\n  font-size: 90%;\n  color: #6c757d;\n}\n\ncode {\n  font-size: 87.5%;\n  color: #e83e8c;\n  word-wrap: break-word;\n}\n\na > code {\n  color: inherit;\n}\n\nkbd {\n  padding: 0.2rem 0.4rem;\n  font-size: 87.5%;\n  color: #fff;\n  background-color: #212529;\n  border-radius: 0.2rem;\n}\n\nkbd kbd {\n  padding: 0;\n  font-size: 100%;\n  font-weight: 700;\n}\n\npre {\n  display: block;\n  font-size: 87.5%;\n  color: #212529;\n}\n\npre code {\n  font-size: inherit;\n  color: inherit;\n  word-break: normal;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\n.container,\n.container-fluid,\n.container-sm,\n.container-md,\n.container-lg,\n.container-xl {\n  width: 100%;\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n@media (min-width: 576px) {\n  .container, .container-sm {\n    max-width: 540px;\n  }\n}\n\n@media (min-width: 768px) {\n  .container, .container-sm, .container-md {\n    max-width: 720px;\n  }\n}\n\n@media (min-width: 992px) {\n  .container, .container-sm, .container-md, .container-lg {\n    max-width: 960px;\n  }\n}\n\n@media (min-width: 1200px) {\n  .container, .container-sm, .container-md, .container-lg, .container-xl {\n    max-width: 1140px;\n  }\n}\n\n.row {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-wrap: wrap;\n  flex-wrap: wrap;\n  margin-right: -15px;\n  margin-left: -15px;\n}\n\n.no-gutters {\n  margin-right: 0;\n  margin-left: 0;\n}\n\n.no-gutters > .col,\n.no-gutters > [class*=\"col-\"] {\n  padding-right: 0;\n  padding-left: 0;\n}\n\n.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col,\n.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,\n.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,\n.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,\n.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,\n.col-xl-auto {\n  position: relative;\n  width: 100%;\n  padding-right: 15px;\n  padding-left: 15px;\n}\n\n.col {\n  -ms-flex-preferred-size: 0;\n  flex-basis: 0;\n  -ms-flex-positive: 1;\n  flex-grow: 1;\n  max-width: 100%;\n}\n\n.row-cols-1 > * {\n  -ms-flex: 0 0 100%;\n  flex: 0 0 100%;\n  max-width: 100%;\n}\n\n.row-cols-2 > * {\n  -ms-flex: 0 0 50%;\n  flex: 0 0 50%;\n  max-width: 50%;\n}\n\n.row-cols-3 > * {\n  -ms-flex: 0 0 33.333333%;\n  flex: 0 0 33.333333%;\n  max-width: 33.333333%;\n}\n\n.row-cols-4 > * {\n  -ms-flex: 0 0 25%;\n  flex: 0 0 25%;\n  max-width: 25%;\n}\n\n.row-cols-5 > * {\n  -ms-flex: 0 0 20%;\n  flex: 0 0 20%;\n  max-width: 20%;\n}\n\n.row-cols-6 > * {\n  -ms-flex: 0 0 16.666667%;\n  flex: 0 0 16.666667%;\n  max-width: 16.666667%;\n}\n\n.col-auto {\n  -ms-flex: 0 0 auto;\n  flex: 0 0 auto;\n  width: auto;\n  max-width: 100%;\n}\n\n.col-1 {\n  -ms-flex: 0 0 8.333333%;\n  flex: 0 0 8.333333%;\n  max-width: 8.333333%;\n}\n\n.col-2 {\n  -ms-flex: 0 0 16.666667%;\n  flex: 0 0 16.666667%;\n  max-width: 16.666667%;\n}\n\n.col-3 {\n  -ms-flex: 0 0 25%;\n  flex: 0 0 25%;\n  max-width: 25%;\n}\n\n.col-4 {\n  -ms-flex: 0 0 33.333333%;\n  flex: 0 0 33.333333%;\n  max-width: 33.333333%;\n}\n\n.col-5 {\n  -ms-flex: 0 0 41.666667%;\n  flex: 0 0 41.666667%;\n  max-width: 41.666667%;\n}\n\n.col-6 {\n  -ms-flex: 0 0 50%;\n  flex: 0 0 50%;\n  max-width: 50%;\n}\n\n.col-7 {\n  -ms-flex: 0 0 58.333333%;\n  flex: 0 0 58.333333%;\n  max-width: 58.333333%;\n}\n\n.col-8 {\n  -ms-flex: 0 0 66.666667%;\n  flex: 0 0 66.666667%;\n  max-width: 66.666667%;\n}\n\n.col-9 {\n  -ms-flex: 0 0 75%;\n  flex: 0 0 75%;\n  max-width: 75%;\n}\n\n.col-10 {\n  -ms-flex: 0 0 83.333333%;\n  flex: 0 0 83.333333%;\n  max-width: 83.333333%;\n}\n\n.col-11 {\n  -ms-flex: 0 0 91.666667%;\n  flex: 0 0 91.666667%;\n  max-width: 91.666667%;\n}\n\n.col-12 {\n  -ms-flex: 0 0 100%;\n  flex: 0 0 100%;\n  max-width: 100%;\n}\n\n.order-first {\n  -ms-flex-order: -1;\n  order: -1;\n}\n\n.order-last {\n  -ms-flex-order: 13;\n  order: 13;\n}\n\n.order-0 {\n  -ms-flex-order: 0;\n  order: 0;\n}\n\n.order-1 {\n  -ms-flex-order: 1;\n  order: 1;\n}\n\n.order-2 {\n  -ms-flex-order: 2;\n  order: 2;\n}\n\n.order-3 {\n  -ms-flex-order: 3;\n  order: 3;\n}\n\n.order-4 {\n  -ms-flex-order: 4;\n  order: 4;\n}\n\n.order-5 {\n  -ms-flex-order: 5;\n  order: 5;\n}\n\n.order-6 {\n  -ms-flex-order: 6;\n  order: 6;\n}\n\n.order-7 {\n  -ms-flex-order: 7;\n  order: 7;\n}\n\n.order-8 {\n  -ms-flex-order: 8;\n  order: 8;\n}\n\n.order-9 {\n  -ms-flex-order: 9;\n  order: 9;\n}\n\n.order-10 {\n  -ms-flex-order: 10;\n  order: 10;\n}\n\n.order-11 {\n  -ms-flex-order: 11;\n  order: 11;\n}\n\n.order-12 {\n  -ms-flex-order: 12;\n  order: 12;\n}\n\n.offset-1 {\n  margin-left: 8.333333%;\n}\n\n.offset-2 {\n  margin-left: 16.666667%;\n}\n\n.offset-3 {\n  margin-left: 25%;\n}\n\n.offset-4 {\n  margin-left: 33.333333%;\n}\n\n.offset-5 {\n  margin-left: 41.666667%;\n}\n\n.offset-6 {\n  margin-left: 50%;\n}\n\n.offset-7 {\n  margin-left: 58.333333%;\n}\n\n.offset-8 {\n  margin-left: 66.666667%;\n}\n\n.offset-9 {\n  margin-left: 75%;\n}\n\n.offset-10 {\n  margin-left: 83.333333%;\n}\n\n.offset-11 {\n  margin-left: 91.666667%;\n}\n\n@media (min-width: 576px) {\n  .col-sm {\n    -ms-flex-preferred-size: 0;\n    flex-basis: 0;\n    -ms-flex-positive: 1;\n    flex-grow: 1;\n    max-width: 100%;\n  }\n  .row-cols-sm-1 > * {\n    -ms-flex: 0 0 100%;\n    flex: 0 0 100%;\n    max-width: 100%;\n  }\n  .row-cols-sm-2 > * {\n    -ms-flex: 0 0 50%;\n    flex: 0 0 50%;\n    max-width: 50%;\n  }\n  .row-cols-sm-3 > * {\n    -ms-flex: 0 0 33.333333%;\n    flex: 0 0 33.333333%;\n    max-width: 33.333333%;\n  }\n  .row-cols-sm-4 > * {\n    -ms-flex: 0 0 25%;\n    flex: 0 0 25%;\n    max-width: 25%;\n  }\n  .row-cols-sm-5 > * {\n    -ms-flex: 0 0 20%;\n    flex: 0 0 20%;\n    max-width: 20%;\n  }\n  .row-cols-sm-6 > * {\n    -ms-flex: 0 0 16.666667%;\n    flex: 0 0 16.666667%;\n    max-width: 16.666667%;\n  }\n  .col-sm-auto {\n    -ms-flex: 0 0 auto;\n    flex: 0 0 auto;\n    width: auto;\n    max-width: 100%;\n  }\n  .col-sm-1 {\n    -ms-flex: 0 0 8.333333%;\n    flex: 0 0 8.333333%;\n    max-width: 8.333333%;\n  }\n  .col-sm-2 {\n    -ms-flex: 0 0 16.666667%;\n    flex: 0 0 16.666667%;\n    max-width: 16.666667%;\n  }\n  .col-sm-3 {\n    -ms-flex: 0 0 25%;\n    flex: 0 0 25%;\n    max-width: 25%;\n  }\n  .col-sm-4 {\n    -ms-flex: 0 0 33.333333%;\n    flex: 0 0 33.333333%;\n    max-width: 33.333333%;\n  }\n  .col-sm-5 {\n    -ms-flex: 0 0 41.666667%;\n    flex: 0 0 41.666667%;\n    max-width: 41.666667%;\n  }\n  .col-sm-6 {\n    -ms-flex: 0 0 50%;\n    flex: 0 0 50%;\n    max-width: 50%;\n  }\n  .col-sm-7 {\n    -ms-flex: 0 0 58.333333%;\n    flex: 0 0 58.333333%;\n    max-width: 58.333333%;\n  }\n  .col-sm-8 {\n    -ms-flex: 0 0 66.666667%;\n    flex: 0 0 66.666667%;\n    max-width: 66.666667%;\n  }\n  .col-sm-9 {\n    -ms-flex: 0 0 75%;\n    flex: 0 0 75%;\n    max-width: 75%;\n  }\n  .col-sm-10 {\n    -ms-flex: 0 0 83.333333%;\n    flex: 0 0 83.333333%;\n    max-width: 83.333333%;\n  }\n  .col-sm-11 {\n    -ms-flex: 0 0 91.666667%;\n    flex: 0 0 91.666667%;\n    max-width: 91.666667%;\n  }\n  .col-sm-12 {\n    -ms-flex: 0 0 100%;\n    flex: 0 0 100%;\n    max-width: 100%;\n  }\n  .order-sm-first {\n    -ms-flex-order: -1;\n    order: -1;\n  }\n  .order-sm-last {\n    -ms-flex-order: 13;\n    order: 13;\n  }\n  .order-sm-0 {\n    -ms-flex-order: 0;\n    order: 0;\n  }\n  .order-sm-1 {\n    -ms-flex-order: 1;\n    order: 1;\n  }\n  .order-sm-2 {\n    -ms-flex-order: 2;\n    order: 2;\n  }\n  .order-sm-3 {\n    -ms-flex-order: 3;\n    order: 3;\n  }\n  .order-sm-4 {\n    -ms-flex-order: 4;\n    order: 4;\n  }\n  .order-sm-5 {\n    -ms-flex-order: 5;\n    order: 5;\n  }\n  .order-sm-6 {\n    -ms-flex-order: 6;\n    order: 6;\n  }\n  .order-sm-7 {\n    -ms-flex-order: 7;\n    order: 7;\n  }\n  .order-sm-8 {\n    -ms-flex-order: 8;\n    order: 8;\n  }\n  .order-sm-9 {\n    -ms-flex-order: 9;\n    order: 9;\n  }\n  .order-sm-10 {\n    -ms-flex-order: 10;\n    order: 10;\n  }\n  .order-sm-11 {\n    -ms-flex-order: 11;\n    order: 11;\n  }\n  .order-sm-12 {\n    -ms-flex-order: 12;\n    order: 12;\n  }\n  .offset-sm-0 {\n    margin-left: 0;\n  }\n  .offset-sm-1 {\n    margin-left: 8.333333%;\n  }\n  .offset-sm-2 {\n    margin-left: 16.666667%;\n  }\n  .offset-sm-3 {\n    margin-left: 25%;\n  }\n  .offset-sm-4 {\n    margin-left: 33.333333%;\n  }\n  .offset-sm-5 {\n    margin-left: 41.666667%;\n  }\n  .offset-sm-6 {\n    margin-left: 50%;\n  }\n  .offset-sm-7 {\n    margin-left: 58.333333%;\n  }\n  .offset-sm-8 {\n    margin-left: 66.666667%;\n  }\n  .offset-sm-9 {\n    margin-left: 75%;\n  }\n  .offset-sm-10 {\n    margin-left: 83.333333%;\n  }\n  .offset-sm-11 {\n    margin-left: 91.666667%;\n  }\n}\n\n@media (min-width: 768px) {\n  .col-md {\n    -ms-flex-preferred-size: 0;\n    flex-basis: 0;\n    -ms-flex-positive: 1;\n    flex-grow: 1;\n    max-width: 100%;\n  }\n  .row-cols-md-1 > * {\n    -ms-flex: 0 0 100%;\n    flex: 0 0 100%;\n    max-width: 100%;\n  }\n  .row-cols-md-2 > * {\n    -ms-flex: 0 0 50%;\n    flex: 0 0 50%;\n    max-width: 50%;\n  }\n  .row-cols-md-3 > * {\n    -ms-flex: 0 0 33.333333%;\n    flex: 0 0 33.333333%;\n    max-width: 33.333333%;\n  }\n  .row-cols-md-4 > * {\n    -ms-flex: 0 0 25%;\n    flex: 0 0 25%;\n    max-width: 25%;\n  }\n  .row-cols-md-5 > * {\n    -ms-flex: 0 0 20%;\n    flex: 0 0 20%;\n    max-width: 20%;\n  }\n  .row-cols-md-6 > * {\n    -ms-flex: 0 0 16.666667%;\n    flex: 0 0 16.666667%;\n    max-width: 16.666667%;\n  }\n  .col-md-auto {\n    -ms-flex: 0 0 auto;\n    flex: 0 0 auto;\n    width: auto;\n    max-width: 100%;\n  }\n  .col-md-1 {\n    -ms-flex: 0 0 8.333333%;\n    flex: 0 0 8.333333%;\n    max-width: 8.333333%;\n  }\n  .col-md-2 {\n    -ms-flex: 0 0 16.666667%;\n    flex: 0 0 16.666667%;\n    max-width: 16.666667%;\n  }\n  .col-md-3 {\n    -ms-flex: 0 0 25%;\n    flex: 0 0 25%;\n    max-width: 25%;\n  }\n  .col-md-4 {\n    -ms-flex: 0 0 33.333333%;\n    flex: 0 0 33.333333%;\n    max-width: 33.333333%;\n  }\n  .col-md-5 {\n    -ms-flex: 0 0 41.666667%;\n    flex: 0 0 41.666667%;\n    max-width: 41.666667%;\n  }\n  .col-md-6 {\n    -ms-flex: 0 0 50%;\n    flex: 0 0 50%;\n    max-width: 50%;\n  }\n  .col-md-7 {\n    -ms-flex: 0 0 58.333333%;\n    flex: 0 0 58.333333%;\n    max-width: 58.333333%;\n  }\n  .col-md-8 {\n    -ms-flex: 0 0 66.666667%;\n    flex: 0 0 66.666667%;\n    max-width: 66.666667%;\n  }\n  .col-md-9 {\n    -ms-flex: 0 0 75%;\n    flex: 0 0 75%;\n    max-width: 75%;\n  }\n  .col-md-10 {\n    -ms-flex: 0 0 83.333333%;\n    flex: 0 0 83.333333%;\n    max-width: 83.333333%;\n  }\n  .col-md-11 {\n    -ms-flex: 0 0 91.666667%;\n    flex: 0 0 91.666667%;\n    max-width: 91.666667%;\n  }\n  .col-md-12 {\n    -ms-flex: 0 0 100%;\n    flex: 0 0 100%;\n    max-width: 100%;\n  }\n  .order-md-first {\n    -ms-flex-order: -1;\n    order: -1;\n  }\n  .order-md-last {\n    -ms-flex-order: 13;\n    order: 13;\n  }\n  .order-md-0 {\n    -ms-flex-order: 0;\n    order: 0;\n  }\n  .order-md-1 {\n    -ms-flex-order: 1;\n    order: 1;\n  }\n  .order-md-2 {\n    -ms-flex-order: 2;\n    order: 2;\n  }\n  .order-md-3 {\n    -ms-flex-order: 3;\n    order: 3;\n  }\n  .order-md-4 {\n    -ms-flex-order: 4;\n    order: 4;\n  }\n  .order-md-5 {\n    -ms-flex-order: 5;\n    order: 5;\n  }\n  .order-md-6 {\n    -ms-flex-order: 6;\n    order: 6;\n  }\n  .order-md-7 {\n    -ms-flex-order: 7;\n    order: 7;\n  }\n  .order-md-8 {\n    -ms-flex-order: 8;\n    order: 8;\n  }\n  .order-md-9 {\n    -ms-flex-order: 9;\n    order: 9;\n  }\n  .order-md-10 {\n    -ms-flex-order: 10;\n    order: 10;\n  }\n  .order-md-11 {\n    -ms-flex-order: 11;\n    order: 11;\n  }\n  .order-md-12 {\n    -ms-flex-order: 12;\n    order: 12;\n  }\n  .offset-md-0 {\n    margin-left: 0;\n  }\n  .offset-md-1 {\n    margin-left: 8.333333%;\n  }\n  .offset-md-2 {\n    margin-left: 16.666667%;\n  }\n  .offset-md-3 {\n    margin-left: 25%;\n  }\n  .offset-md-4 {\n    margin-left: 33.333333%;\n  }\n  .offset-md-5 {\n    margin-left: 41.666667%;\n  }\n  .offset-md-6 {\n    margin-left: 50%;\n  }\n  .offset-md-7 {\n    margin-left: 58.333333%;\n  }\n  .offset-md-8 {\n    margin-left: 66.666667%;\n  }\n  .offset-md-9 {\n    margin-left: 75%;\n  }\n  .offset-md-10 {\n    margin-left: 83.333333%;\n  }\n  .offset-md-11 {\n    margin-left: 91.666667%;\n  }\n}\n\n@media (min-width: 992px) {\n  .col-lg {\n    -ms-flex-preferred-size: 0;\n    flex-basis: 0;\n    -ms-flex-positive: 1;\n    flex-grow: 1;\n    max-width: 100%;\n  }\n  .row-cols-lg-1 > * {\n    -ms-flex: 0 0 100%;\n    flex: 0 0 100%;\n    max-width: 100%;\n  }\n  .row-cols-lg-2 > * {\n    -ms-flex: 0 0 50%;\n    flex: 0 0 50%;\n    max-width: 50%;\n  }\n  .row-cols-lg-3 > * {\n    -ms-flex: 0 0 33.333333%;\n    flex: 0 0 33.333333%;\n    max-width: 33.333333%;\n  }\n  .row-cols-lg-4 > * {\n    -ms-flex: 0 0 25%;\n    flex: 0 0 25%;\n    max-width: 25%;\n  }\n  .row-cols-lg-5 > * {\n    -ms-flex: 0 0 20%;\n    flex: 0 0 20%;\n    max-width: 20%;\n  }\n  .row-cols-lg-6 > * {\n    -ms-flex: 0 0 16.666667%;\n    flex: 0 0 16.666667%;\n    max-width: 16.666667%;\n  }\n  .col-lg-auto {\n    -ms-flex: 0 0 auto;\n    flex: 0 0 auto;\n    width: auto;\n    max-width: 100%;\n  }\n  .col-lg-1 {\n    -ms-flex: 0 0 8.333333%;\n    flex: 0 0 8.333333%;\n    max-width: 8.333333%;\n  }\n  .col-lg-2 {\n    -ms-flex: 0 0 16.666667%;\n    flex: 0 0 16.666667%;\n    max-width: 16.666667%;\n  }\n  .col-lg-3 {\n    -ms-flex: 0 0 25%;\n    flex: 0 0 25%;\n    max-width: 25%;\n  }\n  .col-lg-4 {\n    -ms-flex: 0 0 33.333333%;\n    flex: 0 0 33.333333%;\n    max-width: 33.333333%;\n  }\n  .col-lg-5 {\n    -ms-flex: 0 0 41.666667%;\n    flex: 0 0 41.666667%;\n    max-width: 41.666667%;\n  }\n  .col-lg-6 {\n    -ms-flex: 0 0 50%;\n    flex: 0 0 50%;\n    max-width: 50%;\n  }\n  .col-lg-7 {\n    -ms-flex: 0 0 58.333333%;\n    flex: 0 0 58.333333%;\n    max-width: 58.333333%;\n  }\n  .col-lg-8 {\n    -ms-flex: 0 0 66.666667%;\n    flex: 0 0 66.666667%;\n    max-width: 66.666667%;\n  }\n  .col-lg-9 {\n    -ms-flex: 0 0 75%;\n    flex: 0 0 75%;\n    max-width: 75%;\n  }\n  .col-lg-10 {\n    -ms-flex: 0 0 83.333333%;\n    flex: 0 0 83.333333%;\n    max-width: 83.333333%;\n  }\n  .col-lg-11 {\n    -ms-flex: 0 0 91.666667%;\n    flex: 0 0 91.666667%;\n    max-width: 91.666667%;\n  }\n  .col-lg-12 {\n    -ms-flex: 0 0 100%;\n    flex: 0 0 100%;\n    max-width: 100%;\n  }\n  .order-lg-first {\n    -ms-flex-order: -1;\n    order: -1;\n  }\n  .order-lg-last {\n    -ms-flex-order: 13;\n    order: 13;\n  }\n  .order-lg-0 {\n    -ms-flex-order: 0;\n    order: 0;\n  }\n  .order-lg-1 {\n    -ms-flex-order: 1;\n    order: 1;\n  }\n  .order-lg-2 {\n    -ms-flex-order: 2;\n    order: 2;\n  }\n  .order-lg-3 {\n    -ms-flex-order: 3;\n    order: 3;\n  }\n  .order-lg-4 {\n    -ms-flex-order: 4;\n    order: 4;\n  }\n  .order-lg-5 {\n    -ms-flex-order: 5;\n    order: 5;\n  }\n  .order-lg-6 {\n    -ms-flex-order: 6;\n    order: 6;\n  }\n  .order-lg-7 {\n    -ms-flex-order: 7;\n    order: 7;\n  }\n  .order-lg-8 {\n    -ms-flex-order: 8;\n    order: 8;\n  }\n  .order-lg-9 {\n    -ms-flex-order: 9;\n    order: 9;\n  }\n  .order-lg-10 {\n    -ms-flex-order: 10;\n    order: 10;\n  }\n  .order-lg-11 {\n    -ms-flex-order: 11;\n    order: 11;\n  }\n  .order-lg-12 {\n    -ms-flex-order: 12;\n    order: 12;\n  }\n  .offset-lg-0 {\n    margin-left: 0;\n  }\n  .offset-lg-1 {\n    margin-left: 8.333333%;\n  }\n  .offset-lg-2 {\n    margin-left: 16.666667%;\n  }\n  .offset-lg-3 {\n    margin-left: 25%;\n  }\n  .offset-lg-4 {\n    margin-left: 33.333333%;\n  }\n  .offset-lg-5 {\n    margin-left: 41.666667%;\n  }\n  .offset-lg-6 {\n    margin-left: 50%;\n  }\n  .offset-lg-7 {\n    margin-left: 58.333333%;\n  }\n  .offset-lg-8 {\n    margin-left: 66.666667%;\n  }\n  .offset-lg-9 {\n    margin-left: 75%;\n  }\n  .offset-lg-10 {\n    margin-left: 83.333333%;\n  }\n  .offset-lg-11 {\n    margin-left: 91.666667%;\n  }\n}\n\n@media (min-width: 1200px) {\n  .col-xl {\n    -ms-flex-preferred-size: 0;\n    flex-basis: 0;\n    -ms-flex-positive: 1;\n    flex-grow: 1;\n    max-width: 100%;\n  }\n  .row-cols-xl-1 > * {\n    -ms-flex: 0 0 100%;\n    flex: 0 0 100%;\n    max-width: 100%;\n  }\n  .row-cols-xl-2 > * {\n    -ms-flex: 0 0 50%;\n    flex: 0 0 50%;\n    max-width: 50%;\n  }\n  .row-cols-xl-3 > * {\n    -ms-flex: 0 0 33.333333%;\n    flex: 0 0 33.333333%;\n    max-width: 33.333333%;\n  }\n  .row-cols-xl-4 > * {\n    -ms-flex: 0 0 25%;\n    flex: 0 0 25%;\n    max-width: 25%;\n  }\n  .row-cols-xl-5 > * {\n    -ms-flex: 0 0 20%;\n    flex: 0 0 20%;\n    max-width: 20%;\n  }\n  .row-cols-xl-6 > * {\n    -ms-flex: 0 0 16.666667%;\n    flex: 0 0 16.666667%;\n    max-width: 16.666667%;\n  }\n  .col-xl-auto {\n    -ms-flex: 0 0 auto;\n    flex: 0 0 auto;\n    width: auto;\n    max-width: 100%;\n  }\n  .col-xl-1 {\n    -ms-flex: 0 0 8.333333%;\n    flex: 0 0 8.333333%;\n    max-width: 8.333333%;\n  }\n  .col-xl-2 {\n    -ms-flex: 0 0 16.666667%;\n    flex: 0 0 16.666667%;\n    max-width: 16.666667%;\n  }\n  .col-xl-3 {\n    -ms-flex: 0 0 25%;\n    flex: 0 0 25%;\n    max-width: 25%;\n  }\n  .col-xl-4 {\n    -ms-flex: 0 0 33.333333%;\n    flex: 0 0 33.333333%;\n    max-width: 33.333333%;\n  }\n  .col-xl-5 {\n    -ms-flex: 0 0 41.666667%;\n    flex: 0 0 41.666667%;\n    max-width: 41.666667%;\n  }\n  .col-xl-6 {\n    -ms-flex: 0 0 50%;\n    flex: 0 0 50%;\n    max-width: 50%;\n  }\n  .col-xl-7 {\n    -ms-flex: 0 0 58.333333%;\n    flex: 0 0 58.333333%;\n    max-width: 58.333333%;\n  }\n  .col-xl-8 {\n    -ms-flex: 0 0 66.666667%;\n    flex: 0 0 66.666667%;\n    max-width: 66.666667%;\n  }\n  .col-xl-9 {\n    -ms-flex: 0 0 75%;\n    flex: 0 0 75%;\n    max-width: 75%;\n  }\n  .col-xl-10 {\n    -ms-flex: 0 0 83.333333%;\n    flex: 0 0 83.333333%;\n    max-width: 83.333333%;\n  }\n  .col-xl-11 {\n    -ms-flex: 0 0 91.666667%;\n    flex: 0 0 91.666667%;\n    max-width: 91.666667%;\n  }\n  .col-xl-12 {\n    -ms-flex: 0 0 100%;\n    flex: 0 0 100%;\n    max-width: 100%;\n  }\n  .order-xl-first {\n    -ms-flex-order: -1;\n    order: -1;\n  }\n  .order-xl-last {\n    -ms-flex-order: 13;\n    order: 13;\n  }\n  .order-xl-0 {\n    -ms-flex-order: 0;\n    order: 0;\n  }\n  .order-xl-1 {\n    -ms-flex-order: 1;\n    order: 1;\n  }\n  .order-xl-2 {\n    -ms-flex-order: 2;\n    order: 2;\n  }\n  .order-xl-3 {\n    -ms-flex-order: 3;\n    order: 3;\n  }\n  .order-xl-4 {\n    -ms-flex-order: 4;\n    order: 4;\n  }\n  .order-xl-5 {\n    -ms-flex-order: 5;\n    order: 5;\n  }\n  .order-xl-6 {\n    -ms-flex-order: 6;\n    order: 6;\n  }\n  .order-xl-7 {\n    -ms-flex-order: 7;\n    order: 7;\n  }\n  .order-xl-8 {\n    -ms-flex-order: 8;\n    order: 8;\n  }\n  .order-xl-9 {\n    -ms-flex-order: 9;\n    order: 9;\n  }\n  .order-xl-10 {\n    -ms-flex-order: 10;\n    order: 10;\n  }\n  .order-xl-11 {\n    -ms-flex-order: 11;\n    order: 11;\n  }\n  .order-xl-12 {\n    -ms-flex-order: 12;\n    order: 12;\n  }\n  .offset-xl-0 {\n    margin-left: 0;\n  }\n  .offset-xl-1 {\n    margin-left: 8.333333%;\n  }\n  .offset-xl-2 {\n    margin-left: 16.666667%;\n  }\n  .offset-xl-3 {\n    margin-left: 25%;\n  }\n  .offset-xl-4 {\n    margin-left: 33.333333%;\n  }\n  .offset-xl-5 {\n    margin-left: 41.666667%;\n  }\n  .offset-xl-6 {\n    margin-left: 50%;\n  }\n  .offset-xl-7 {\n    margin-left: 58.333333%;\n  }\n  .offset-xl-8 {\n    margin-left: 66.666667%;\n  }\n  .offset-xl-9 {\n    margin-left: 75%;\n  }\n  .offset-xl-10 {\n    margin-left: 83.333333%;\n  }\n  .offset-xl-11 {\n    margin-left: 91.666667%;\n  }\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 1rem;\n  color: #212529;\n}\n\n.table th,\n.table td {\n  padding: 0.75rem;\n  vertical-align: top;\n  border-top: 1px solid #dee2e6;\n}\n\n.table thead th {\n  vertical-align: bottom;\n  border-bottom: 2px solid #dee2e6;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #dee2e6;\n}\n\n.table-sm th,\n.table-sm td {\n  padding: 0.3rem;\n}\n\n.table-bordered {\n  border: 1px solid #dee2e6;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border: 1px solid #dee2e6;\n}\n\n.table-bordered thead th,\n.table-bordered thead td {\n  border-bottom-width: 2px;\n}\n\n.table-borderless th,\n.table-borderless td,\n.table-borderless thead th,\n.table-borderless tbody + tbody {\n  border: 0;\n}\n\n.table-striped tbody tr:nth-of-type(odd) {\n  background-color: rgba(0, 0, 0, 0.05);\n}\n\n.table-hover tbody tr:hover {\n  color: #212529;\n  background-color: rgba(0, 0, 0, 0.075);\n}\n\n.table-primary,\n.table-primary > th,\n.table-primary > td {\n  background-color: #b8daff;\n}\n\n.table-primary th,\n.table-primary td,\n.table-primary thead th,\n.table-primary tbody + tbody {\n  border-color: #7abaff;\n}\n\n.table-hover .table-primary:hover {\n  background-color: #9fcdff;\n}\n\n.table-hover .table-primary:hover > td,\n.table-hover .table-primary:hover > th {\n  background-color: #9fcdff;\n}\n\n.table-secondary,\n.table-secondary > th,\n.table-secondary > td {\n  background-color: #d6d8db;\n}\n\n.table-secondary th,\n.table-secondary td,\n.table-secondary thead th,\n.table-secondary tbody + tbody {\n  border-color: #b3b7bb;\n}\n\n.table-hover .table-secondary:hover {\n  background-color: #c8cbcf;\n}\n\n.table-hover .table-secondary:hover > td,\n.table-hover .table-secondary:hover > th {\n  background-color: #c8cbcf;\n}\n\n.table-success,\n.table-success > th,\n.table-success > td {\n  background-color: #c3e6cb;\n}\n\n.table-success th,\n.table-success td,\n.table-success thead th,\n.table-success tbody + tbody {\n  border-color: #8fd19e;\n}\n\n.table-hover .table-success:hover {\n  background-color: #b1dfbb;\n}\n\n.table-hover .table-success:hover > td,\n.table-hover .table-success:hover > th {\n  background-color: #b1dfbb;\n}\n\n.table-info,\n.table-info > th,\n.table-info > td {\n  background-color: #bee5eb;\n}\n\n.table-info th,\n.table-info td,\n.table-info thead th,\n.table-info tbody + tbody {\n  border-color: #86cfda;\n}\n\n.table-hover .table-info:hover {\n  background-color: #abdde5;\n}\n\n.table-hover .table-info:hover > td,\n.table-hover .table-info:hover > th {\n  background-color: #abdde5;\n}\n\n.table-warning,\n.table-warning > th,\n.table-warning > td {\n  background-color: #ffeeba;\n}\n\n.table-warning th,\n.table-warning td,\n.table-warning thead th,\n.table-warning tbody + tbody {\n  border-color: #ffdf7e;\n}\n\n.table-hover .table-warning:hover {\n  background-color: #ffe8a1;\n}\n\n.table-hover .table-warning:hover > td,\n.table-hover .table-warning:hover > th {\n  background-color: #ffe8a1;\n}\n\n.table-danger,\n.table-danger > th,\n.table-danger > td {\n  background-color: #f5c6cb;\n}\n\n.table-danger th,\n.table-danger td,\n.table-danger thead th,\n.table-danger tbody + tbody {\n  border-color: #ed969e;\n}\n\n.table-hover .table-danger:hover {\n  background-color: #f1b0b7;\n}\n\n.table-hover .table-danger:hover > td,\n.table-hover .table-danger:hover > th {\n  background-color: #f1b0b7;\n}\n\n.table-light,\n.table-light > th,\n.table-light > td {\n  background-color: #fdfdfe;\n}\n\n.table-light th,\n.table-light td,\n.table-light thead th,\n.table-light tbody + tbody {\n  border-color: #fbfcfc;\n}\n\n.table-hover .table-light:hover {\n  background-color: #ececf6;\n}\n\n.table-hover .table-light:hover > td,\n.table-hover .table-light:hover > th {\n  background-color: #ececf6;\n}\n\n.table-dark,\n.table-dark > th,\n.table-dark > td {\n  background-color: #c6c8ca;\n}\n\n.table-dark th,\n.table-dark td,\n.table-dark thead th,\n.table-dark tbody + tbody {\n  border-color: #95999c;\n}\n\n.table-hover .table-dark:hover {\n  background-color: #b9bbbe;\n}\n\n.table-hover .table-dark:hover > td,\n.table-hover .table-dark:hover > th {\n  background-color: #b9bbbe;\n}\n\n.table-active,\n.table-active > th,\n.table-active > td {\n  background-color: rgba(0, 0, 0, 0.075);\n}\n\n.table-hover .table-active:hover {\n  background-color: rgba(0, 0, 0, 0.075);\n}\n\n.table-hover .table-active:hover > td,\n.table-hover .table-active:hover > th {\n  background-color: rgba(0, 0, 0, 0.075);\n}\n\n.table .thead-dark th {\n  color: #fff;\n  background-color: #343a40;\n  border-color: #454d55;\n}\n\n.table .thead-light th {\n  color: #495057;\n  background-color: #e9ecef;\n  border-color: #dee2e6;\n}\n\n.table-dark {\n  color: #fff;\n  background-color: #343a40;\n}\n\n.table-dark th,\n.table-dark td,\n.table-dark thead th {\n  border-color: #454d55;\n}\n\n.table-dark.table-bordered {\n  border: 0;\n}\n\n.table-dark.table-striped tbody tr:nth-of-type(odd) {\n  background-color: rgba(255, 255, 255, 0.05);\n}\n\n.table-dark.table-hover tbody tr:hover {\n  color: #fff;\n  background-color: rgba(255, 255, 255, 0.075);\n}\n\n@media (max-width: 575.98px) {\n  .table-responsive-sm {\n    display: block;\n    width: 100%;\n    overflow-x: auto;\n    -webkit-overflow-scrolling: touch;\n  }\n  .table-responsive-sm > .table-bordered {\n    border: 0;\n  }\n}\n\n@media (max-width: 767.98px) {\n  .table-responsive-md {\n    display: block;\n    width: 100%;\n    overflow-x: auto;\n    -webkit-overflow-scrolling: touch;\n  }\n  .table-responsive-md > .table-bordered {\n    border: 0;\n  }\n}\n\n@media (max-width: 991.98px) {\n  .table-responsive-lg {\n    display: block;\n    width: 100%;\n    overflow-x: auto;\n    -webkit-overflow-scrolling: touch;\n  }\n  .table-responsive-lg > .table-bordered {\n    border: 0;\n  }\n}\n\n@media (max-width: 1199.98px) {\n  .table-responsive-xl {\n    display: block;\n    width: 100%;\n    overflow-x: auto;\n    -webkit-overflow-scrolling: touch;\n  }\n  .table-responsive-xl > .table-bordered {\n    border: 0;\n  }\n}\n\n.table-responsive {\n  display: block;\n  width: 100%;\n  overflow-x: auto;\n  -webkit-overflow-scrolling: touch;\n}\n\n.table-responsive > .table-bordered {\n  border: 0;\n}\n\n.form-control {\n  display: block;\n  width: 100%;\n  height: calc(1.5em + 0.75rem + 2px);\n  padding: 0.375rem 0.75rem;\n  font-size: 1rem;\n  font-weight: 400;\n  line-height: 1.5;\n  color: #495057;\n  background-color: #fff;\n  background-clip: padding-box;\n  border: 1px solid #ced4da;\n  border-radius: 0.25rem;\n  transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .form-control {\n    transition: none;\n  }\n}\n\n.form-control::-ms-expand {\n  background-color: transparent;\n  border: 0;\n}\n\n.form-control:-moz-focusring {\n  color: transparent;\n  text-shadow: 0 0 0 #495057;\n}\n\n.form-control:focus {\n  color: #495057;\n  background-color: #fff;\n  border-color: #80bdff;\n  outline: 0;\n  box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.form-control::-webkit-input-placeholder {\n  color: #6c757d;\n  opacity: 1;\n}\n\n.form-control::-moz-placeholder {\n  color: #6c757d;\n  opacity: 1;\n}\n\n.form-control:-ms-input-placeholder {\n  color: #6c757d;\n  opacity: 1;\n}\n\n.form-control::-ms-input-placeholder {\n  color: #6c757d;\n  opacity: 1;\n}\n\n.form-control::placeholder {\n  color: #6c757d;\n  opacity: 1;\n}\n\n.form-control:disabled, .form-control[readonly] {\n  background-color: #e9ecef;\n  opacity: 1;\n}\n\ninput[type=\"date\"].form-control,\ninput[type=\"time\"].form-control,\ninput[type=\"datetime-local\"].form-control,\ninput[type=\"month\"].form-control {\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  appearance: none;\n}\n\nselect.form-control:focus::-ms-value {\n  color: #495057;\n  background-color: #fff;\n}\n\n.form-control-file,\n.form-control-range {\n  display: block;\n  width: 100%;\n}\n\n.col-form-label {\n  padding-top: calc(0.375rem + 1px);\n  padding-bottom: calc(0.375rem + 1px);\n  margin-bottom: 0;\n  font-size: inherit;\n  line-height: 1.5;\n}\n\n.col-form-label-lg {\n  padding-top: calc(0.5rem + 1px);\n  padding-bottom: calc(0.5rem + 1px);\n  font-size: 1.25rem;\n  line-height: 1.5;\n}\n\n.col-form-label-sm {\n  padding-top: calc(0.25rem + 1px);\n  padding-bottom: calc(0.25rem + 1px);\n  font-size: 0.875rem;\n  line-height: 1.5;\n}\n\n.form-control-plaintext {\n  display: block;\n  width: 100%;\n  padding: 0.375rem 0;\n  margin-bottom: 0;\n  font-size: 1rem;\n  line-height: 1.5;\n  color: #212529;\n  background-color: transparent;\n  border: solid transparent;\n  border-width: 1px 0;\n}\n\n.form-control-plaintext.form-control-sm, .form-control-plaintext.form-control-lg {\n  padding-right: 0;\n  padding-left: 0;\n}\n\n.form-control-sm {\n  height: calc(1.5em + 0.5rem + 2px);\n  padding: 0.25rem 0.5rem;\n  font-size: 0.875rem;\n  line-height: 1.5;\n  border-radius: 0.2rem;\n}\n\n.form-control-lg {\n  height: calc(1.5em + 1rem + 2px);\n  padding: 0.5rem 1rem;\n  font-size: 1.25rem;\n  line-height: 1.5;\n  border-radius: 0.3rem;\n}\n\nselect.form-control[size], select.form-control[multiple] {\n  height: auto;\n}\n\ntextarea.form-control {\n  height: auto;\n}\n\n.form-group {\n  margin-bottom: 1rem;\n}\n\n.form-text {\n  display: block;\n  margin-top: 0.25rem;\n}\n\n.form-row {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-wrap: wrap;\n  flex-wrap: wrap;\n  margin-right: -5px;\n  margin-left: -5px;\n}\n\n.form-row > .col,\n.form-row > [class*=\"col-\"] {\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\n.form-check {\n  position: relative;\n  display: block;\n  padding-left: 1.25rem;\n}\n\n.form-check-input {\n  position: absolute;\n  margin-top: 0.3rem;\n  margin-left: -1.25rem;\n}\n\n.form-check-input[disabled] ~ .form-check-label,\n.form-check-input:disabled ~ .form-check-label {\n  color: #6c757d;\n}\n\n.form-check-label {\n  margin-bottom: 0;\n}\n\n.form-check-inline {\n  display: -ms-inline-flexbox;\n  display: inline-flex;\n  -ms-flex-align: center;\n  align-items: center;\n  padding-left: 0;\n  margin-right: 0.75rem;\n}\n\n.form-check-inline .form-check-input {\n  position: static;\n  margin-top: 0;\n  margin-right: 0.3125rem;\n  margin-left: 0;\n}\n\n.valid-feedback {\n  display: none;\n  width: 100%;\n  margin-top: 0.25rem;\n  font-size: 80%;\n  color: #28a745;\n}\n\n.valid-tooltip {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 5;\n  display: none;\n  max-width: 100%;\n  padding: 0.25rem 0.5rem;\n  margin-top: .1rem;\n  font-size: 0.875rem;\n  line-height: 1.5;\n  color: #fff;\n  background-color: rgba(40, 167, 69, 0.9);\n  border-radius: 0.25rem;\n}\n\n.was-validated :valid ~ .valid-feedback,\n.was-validated :valid ~ .valid-tooltip,\n.is-valid ~ .valid-feedback,\n.is-valid ~ .valid-tooltip {\n  display: block;\n}\n\n.was-validated .form-control:valid, .form-control.is-valid {\n  border-color: #28a745;\n  padding-right: calc(1.5em + 0.75rem);\n  background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e\");\n  background-repeat: no-repeat;\n  background-position: right calc(0.375em + 0.1875rem) center;\n  background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);\n}\n\n.was-validated .form-control:valid:focus, .form-control.is-valid:focus {\n  border-color: #28a745;\n  box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);\n}\n\n.was-validated textarea.form-control:valid, textarea.form-control.is-valid {\n  padding-right: calc(1.5em + 0.75rem);\n  background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem);\n}\n\n.was-validated .custom-select:valid, .custom-select.is-valid {\n  border-color: #28a745;\n  padding-right: calc(0.75em + 2.3125rem);\n  background: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e\") no-repeat right 0.75rem center/8px 10px, url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e\") #fff no-repeat center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);\n}\n\n.was-validated .custom-select:valid:focus, .custom-select.is-valid:focus {\n  border-color: #28a745;\n  box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);\n}\n\n.was-validated .form-check-input:valid ~ .form-check-label, .form-check-input.is-valid ~ .form-check-label {\n  color: #28a745;\n}\n\n.was-validated .form-check-input:valid ~ .valid-feedback,\n.was-validated .form-check-input:valid ~ .valid-tooltip, .form-check-input.is-valid ~ .valid-feedback,\n.form-check-input.is-valid ~ .valid-tooltip {\n  display: block;\n}\n\n.was-validated .custom-control-input:valid ~ .custom-control-label, .custom-control-input.is-valid ~ .custom-control-label {\n  color: #28a745;\n}\n\n.was-validated .custom-control-input:valid ~ .custom-control-label::before, .custom-control-input.is-valid ~ .custom-control-label::before {\n  border-color: #28a745;\n}\n\n.was-validated .custom-control-input:valid:checked ~ .custom-control-label::before, .custom-control-input.is-valid:checked ~ .custom-control-label::before {\n  border-color: #34ce57;\n  background-color: #34ce57;\n}\n\n.was-validated .custom-control-input:valid:focus ~ .custom-control-label::before, .custom-control-input.is-valid:focus ~ .custom-control-label::before {\n  box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);\n}\n\n.was-validated .custom-control-input:valid:focus:not(:checked) ~ .custom-control-label::before, .custom-control-input.is-valid:focus:not(:checked) ~ .custom-control-label::before {\n  border-color: #28a745;\n}\n\n.was-validated .custom-file-input:valid ~ .custom-file-label, .custom-file-input.is-valid ~ .custom-file-label {\n  border-color: #28a745;\n}\n\n.was-validated .custom-file-input:valid:focus ~ .custom-file-label, .custom-file-input.is-valid:focus ~ .custom-file-label {\n  border-color: #28a745;\n  box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);\n}\n\n.invalid-feedback {\n  display: none;\n  width: 100%;\n  margin-top: 0.25rem;\n  font-size: 80%;\n  color: #dc3545;\n}\n\n.invalid-tooltip {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 5;\n  display: none;\n  max-width: 100%;\n  padding: 0.25rem 0.5rem;\n  margin-top: .1rem;\n  font-size: 0.875rem;\n  line-height: 1.5;\n  color: #fff;\n  background-color: rgba(220, 53, 69, 0.9);\n  border-radius: 0.25rem;\n}\n\n.was-validated :invalid ~ .invalid-feedback,\n.was-validated :invalid ~ .invalid-tooltip,\n.is-invalid ~ .invalid-feedback,\n.is-invalid ~ .invalid-tooltip {\n  display: block;\n}\n\n.was-validated .form-control:invalid, .form-control.is-invalid {\n  border-color: #dc3545;\n  padding-right: calc(1.5em + 0.75rem);\n  background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e\");\n  background-repeat: no-repeat;\n  background-position: right calc(0.375em + 0.1875rem) center;\n  background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);\n}\n\n.was-validated .form-control:invalid:focus, .form-control.is-invalid:focus {\n  border-color: #dc3545;\n  box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);\n}\n\n.was-validated textarea.form-control:invalid, textarea.form-control.is-invalid {\n  padding-right: calc(1.5em + 0.75rem);\n  background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem);\n}\n\n.was-validated .custom-select:invalid, .custom-select.is-invalid {\n  border-color: #dc3545;\n  padding-right: calc(0.75em + 2.3125rem);\n  background: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e\") no-repeat right 0.75rem center/8px 10px, url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e\") #fff no-repeat center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);\n}\n\n.was-validated .custom-select:invalid:focus, .custom-select.is-invalid:focus {\n  border-color: #dc3545;\n  box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);\n}\n\n.was-validated .form-check-input:invalid ~ .form-check-label, .form-check-input.is-invalid ~ .form-check-label {\n  color: #dc3545;\n}\n\n.was-validated .form-check-input:invalid ~ .invalid-feedback,\n.was-validated .form-check-input:invalid ~ .invalid-tooltip, .form-check-input.is-invalid ~ .invalid-feedback,\n.form-check-input.is-invalid ~ .invalid-tooltip {\n  display: block;\n}\n\n.was-validated .custom-control-input:invalid ~ .custom-control-label, .custom-control-input.is-invalid ~ .custom-control-label {\n  color: #dc3545;\n}\n\n.was-validated .custom-control-input:invalid ~ .custom-control-label::before, .custom-control-input.is-invalid ~ .custom-control-label::before {\n  border-color: #dc3545;\n}\n\n.was-validated .custom-control-input:invalid:checked ~ .custom-control-label::before, .custom-control-input.is-invalid:checked ~ .custom-control-label::before {\n  border-color: #e4606d;\n  background-color: #e4606d;\n}\n\n.was-validated .custom-control-input:invalid:focus ~ .custom-control-label::before, .custom-control-input.is-invalid:focus ~ .custom-control-label::before {\n  box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);\n}\n\n.was-validated .custom-control-input:invalid:focus:not(:checked) ~ .custom-control-label::before, .custom-control-input.is-invalid:focus:not(:checked) ~ .custom-control-label::before {\n  border-color: #dc3545;\n}\n\n.was-validated .custom-file-input:invalid ~ .custom-file-label, .custom-file-input.is-invalid ~ .custom-file-label {\n  border-color: #dc3545;\n}\n\n.was-validated .custom-file-input:invalid:focus ~ .custom-file-label, .custom-file-input.is-invalid:focus ~ .custom-file-label {\n  border-color: #dc3545;\n  box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);\n}\n\n.form-inline {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-flow: row wrap;\n  flex-flow: row wrap;\n  -ms-flex-align: center;\n  align-items: center;\n}\n\n.form-inline .form-check {\n  width: 100%;\n}\n\n@media (min-width: 576px) {\n  .form-inline label {\n    display: -ms-flexbox;\n    display: flex;\n    -ms-flex-align: center;\n    align-items: center;\n    -ms-flex-pack: center;\n    justify-content: center;\n    margin-bottom: 0;\n  }\n  .form-inline .form-group {\n    display: -ms-flexbox;\n    display: flex;\n    -ms-flex: 0 0 auto;\n    flex: 0 0 auto;\n    -ms-flex-flow: row wrap;\n    flex-flow: row wrap;\n    -ms-flex-align: center;\n    align-items: center;\n    margin-bottom: 0;\n  }\n  .form-inline .form-control {\n    display: inline-block;\n    width: auto;\n    vertical-align: middle;\n  }\n  .form-inline .form-control-plaintext {\n    display: inline-block;\n  }\n  .form-inline .input-group,\n  .form-inline .custom-select {\n    width: auto;\n  }\n  .form-inline .form-check {\n    display: -ms-flexbox;\n    display: flex;\n    -ms-flex-align: center;\n    align-items: center;\n    -ms-flex-pack: center;\n    justify-content: center;\n    width: auto;\n    padding-left: 0;\n  }\n  .form-inline .form-check-input {\n    position: relative;\n    -ms-flex-negative: 0;\n    flex-shrink: 0;\n    margin-top: 0;\n    margin-right: 0.25rem;\n    margin-left: 0;\n  }\n  .form-inline .custom-control {\n    -ms-flex-align: center;\n    align-items: center;\n    -ms-flex-pack: center;\n    justify-content: center;\n  }\n  .form-inline .custom-control-label {\n    margin-bottom: 0;\n  }\n}\n\n.btn {\n  display: inline-block;\n  font-weight: 400;\n  color: #212529;\n  text-align: center;\n  vertical-align: middle;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n  background-color: transparent;\n  border: 1px solid transparent;\n  padding: 0.375rem 0.75rem;\n  font-size: 1rem;\n  line-height: 1.5;\n  border-radius: 0.25rem;\n  transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .btn {\n    transition: none;\n  }\n}\n\n.btn:hover {\n  color: #212529;\n  text-decoration: none;\n}\n\n.btn:focus, .btn.focus {\n  outline: 0;\n  box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.btn.disabled, .btn:disabled {\n  opacity: 0.65;\n}\n\n.btn:not(:disabled):not(.disabled) {\n  cursor: pointer;\n}\n\na.btn.disabled,\nfieldset:disabled a.btn {\n  pointer-events: none;\n}\n\n.btn-primary {\n  color: #fff;\n  background-color: #007bff;\n  border-color: #007bff;\n}\n\n.btn-primary:hover {\n  color: #fff;\n  background-color: #0069d9;\n  border-color: #0062cc;\n}\n\n.btn-primary:focus, .btn-primary.focus {\n  color: #fff;\n  background-color: #0069d9;\n  border-color: #0062cc;\n  box-shadow: 0 0 0 0.2rem rgba(38, 143, 255, 0.5);\n}\n\n.btn-primary.disabled, .btn-primary:disabled {\n  color: #fff;\n  background-color: #007bff;\n  border-color: #007bff;\n}\n\n.btn-primary:not(:disabled):not(.disabled):active, .btn-primary:not(:disabled):not(.disabled).active,\n.show > .btn-primary.dropdown-toggle {\n  color: #fff;\n  background-color: #0062cc;\n  border-color: #005cbf;\n}\n\n.btn-primary:not(:disabled):not(.disabled):active:focus, .btn-primary:not(:disabled):not(.disabled).active:focus,\n.show > .btn-primary.dropdown-toggle:focus {\n  box-shadow: 0 0 0 0.2rem rgba(38, 143, 255, 0.5);\n}\n\n.btn-secondary {\n  color: #fff;\n  background-color: #6c757d;\n  border-color: #6c757d;\n}\n\n.btn-secondary:hover {\n  color: #fff;\n  background-color: #5a6268;\n  border-color: #545b62;\n}\n\n.btn-secondary:focus, .btn-secondary.focus {\n  color: #fff;\n  background-color: #5a6268;\n  border-color: #545b62;\n  box-shadow: 0 0 0 0.2rem rgba(130, 138, 145, 0.5);\n}\n\n.btn-secondary.disabled, .btn-secondary:disabled {\n  color: #fff;\n  background-color: #6c757d;\n  border-color: #6c757d;\n}\n\n.btn-secondary:not(:disabled):not(.disabled):active, .btn-secondary:not(:disabled):not(.disabled).active,\n.show > .btn-secondary.dropdown-toggle {\n  color: #fff;\n  background-color: #545b62;\n  border-color: #4e555b;\n}\n\n.btn-secondary:not(:disabled):not(.disabled):active:focus, .btn-secondary:not(:disabled):not(.disabled).active:focus,\n.show > .btn-secondary.dropdown-toggle:focus {\n  box-shadow: 0 0 0 0.2rem rgba(130, 138, 145, 0.5);\n}\n\n.btn-success {\n  color: #fff;\n  background-color: #28a745;\n  border-color: #28a745;\n}\n\n.btn-success:hover {\n  color: #fff;\n  background-color: #218838;\n  border-color: #1e7e34;\n}\n\n.btn-success:focus, .btn-success.focus {\n  color: #fff;\n  background-color: #218838;\n  border-color: #1e7e34;\n  box-shadow: 0 0 0 0.2rem rgba(72, 180, 97, 0.5);\n}\n\n.btn-success.disabled, .btn-success:disabled {\n  color: #fff;\n  background-color: #28a745;\n  border-color: #28a745;\n}\n\n.btn-success:not(:disabled):not(.disabled):active, .btn-success:not(:disabled):not(.disabled).active,\n.show > .btn-success.dropdown-toggle {\n  color: #fff;\n  background-color: #1e7e34;\n  border-color: #1c7430;\n}\n\n.btn-success:not(:disabled):not(.disabled):active:focus, .btn-success:not(:disabled):not(.disabled).active:focus,\n.show > .btn-success.dropdown-toggle:focus {\n  box-shadow: 0 0 0 0.2rem rgba(72, 180, 97, 0.5);\n}\n\n.btn-info {\n  color: #fff;\n  background-color: #17a2b8;\n  border-color: #17a2b8;\n}\n\n.btn-info:hover {\n  color: #fff;\n  background-color: #138496;\n  border-color: #117a8b;\n}\n\n.btn-info:focus, .btn-info.focus {\n  color: #fff;\n  background-color: #138496;\n  border-color: #117a8b;\n  box-shadow: 0 0 0 0.2rem rgba(58, 176, 195, 0.5);\n}\n\n.btn-info.disabled, .btn-info:disabled {\n  color: #fff;\n  background-color: #17a2b8;\n  border-color: #17a2b8;\n}\n\n.btn-info:not(:disabled):not(.disabled):active, .btn-info:not(:disabled):not(.disabled).active,\n.show > .btn-info.dropdown-toggle {\n  color: #fff;\n  background-color: #117a8b;\n  border-color: #10707f;\n}\n\n.btn-info:not(:disabled):not(.disabled):active:focus, .btn-info:not(:disabled):not(.disabled).active:focus,\n.show > .btn-info.dropdown-toggle:focus {\n  box-shadow: 0 0 0 0.2rem rgba(58, 176, 195, 0.5);\n}\n\n.btn-warning {\n  color: #212529;\n  background-color: #ffc107;\n  border-color: #ffc107;\n}\n\n.btn-warning:hover {\n  color: #212529;\n  background-color: #e0a800;\n  border-color: #d39e00;\n}\n\n.btn-warning:focus, .btn-warning.focus {\n  color: #212529;\n  background-color: #e0a800;\n  border-color: #d39e00;\n  box-shadow: 0 0 0 0.2rem rgba(222, 170, 12, 0.5);\n}\n\n.btn-warning.disabled, .btn-warning:disabled {\n  color: #212529;\n  background-color: #ffc107;\n  border-color: #ffc107;\n}\n\n.btn-warning:not(:disabled):not(.disabled):active, .btn-warning:not(:disabled):not(.disabled).active,\n.show > .btn-warning.dropdown-toggle {\n  color: #212529;\n  background-color: #d39e00;\n  border-color: #c69500;\n}\n\n.btn-warning:not(:disabled):not(.disabled):active:focus, .btn-warning:not(:disabled):not(.disabled).active:focus,\n.show > .btn-warning.dropdown-toggle:focus {\n  box-shadow: 0 0 0 0.2rem rgba(222, 170, 12, 0.5);\n}\n\n.btn-danger {\n  color: #fff;\n  background-color: #dc3545;\n  border-color: #dc3545;\n}\n\n.btn-danger:hover {\n  color: #fff;\n  background-color: #c82333;\n  border-color: #bd2130;\n}\n\n.btn-danger:focus, .btn-danger.focus {\n  color: #fff;\n  background-color: #c82333;\n  border-color: #bd2130;\n  box-shadow: 0 0 0 0.2rem rgba(225, 83, 97, 0.5);\n}\n\n.btn-danger.disabled, .btn-danger:disabled {\n  color: #fff;\n  background-color: #dc3545;\n  border-color: #dc3545;\n}\n\n.btn-danger:not(:disabled):not(.disabled):active, .btn-danger:not(:disabled):not(.disabled).active,\n.show > .btn-danger.dropdown-toggle {\n  color: #fff;\n  background-color: #bd2130;\n  border-color: #b21f2d;\n}\n\n.btn-danger:not(:disabled):not(.disabled):active:focus, .btn-danger:not(:disabled):not(.disabled).active:focus,\n.show > .btn-danger.dropdown-toggle:focus {\n  box-shadow: 0 0 0 0.2rem rgba(225, 83, 97, 0.5);\n}\n\n.btn-light {\n  color: #212529;\n  background-color: #f8f9fa;\n  border-color: #f8f9fa;\n}\n\n.btn-light:hover {\n  color: #212529;\n  background-color: #e2e6ea;\n  border-color: #dae0e5;\n}\n\n.btn-light:focus, .btn-light.focus {\n  color: #212529;\n  background-color: #e2e6ea;\n  border-color: #dae0e5;\n  box-shadow: 0 0 0 0.2rem rgba(216, 217, 219, 0.5);\n}\n\n.btn-light.disabled, .btn-light:disabled {\n  color: #212529;\n  background-color: #f8f9fa;\n  border-color: #f8f9fa;\n}\n\n.btn-light:not(:disabled):not(.disabled):active, .btn-light:not(:disabled):not(.disabled).active,\n.show > .btn-light.dropdown-toggle {\n  color: #212529;\n  background-color: #dae0e5;\n  border-color: #d3d9df;\n}\n\n.btn-light:not(:disabled):not(.disabled):active:focus, .btn-light:not(:disabled):not(.disabled).active:focus,\n.show > .btn-light.dropdown-toggle:focus {\n  box-shadow: 0 0 0 0.2rem rgba(216, 217, 219, 0.5);\n}\n\n.btn-dark {\n  color: #fff;\n  background-color: #343a40;\n  border-color: #343a40;\n}\n\n.btn-dark:hover {\n  color: #fff;\n  background-color: #23272b;\n  border-color: #1d2124;\n}\n\n.btn-dark:focus, .btn-dark.focus {\n  color: #fff;\n  background-color: #23272b;\n  border-color: #1d2124;\n  box-shadow: 0 0 0 0.2rem rgba(82, 88, 93, 0.5);\n}\n\n.btn-dark.disabled, .btn-dark:disabled {\n  color: #fff;\n  background-color: #343a40;\n  border-color: #343a40;\n}\n\n.btn-dark:not(:disabled):not(.disabled):active, .btn-dark:not(:disabled):not(.disabled).active,\n.show > .btn-dark.dropdown-toggle {\n  color: #fff;\n  background-color: #1d2124;\n  border-color: #171a1d;\n}\n\n.btn-dark:not(:disabled):not(.disabled):active:focus, .btn-dark:not(:disabled):not(.disabled).active:focus,\n.show > .btn-dark.dropdown-toggle:focus {\n  box-shadow: 0 0 0 0.2rem rgba(82, 88, 93, 0.5);\n}\n\n.btn-outline-primary {\n  color: #007bff;\n  border-color: #007bff;\n}\n\n.btn-outline-primary:hover {\n  color: #fff;\n  background-color: #007bff;\n  border-color: #007bff;\n}\n\n.btn-outline-primary:focus, .btn-outline-primary.focus {\n  box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5);\n}\n\n.btn-outline-primary.disabled, .btn-outline-primary:disabled {\n  color: #007bff;\n  background-color: transparent;\n}\n\n.btn-outline-primary:not(:disabled):not(.disabled):active, .btn-outline-primary:not(:disabled):not(.disabled).active,\n.show > .btn-outline-primary.dropdown-toggle {\n  color: #fff;\n  background-color: #007bff;\n  border-color: #007bff;\n}\n\n.btn-outline-primary:not(:disabled):not(.disabled):active:focus, .btn-outline-primary:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-primary.dropdown-toggle:focus {\n  box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5);\n}\n\n.btn-outline-secondary {\n  color: #6c757d;\n  border-color: #6c757d;\n}\n\n.btn-outline-secondary:hover {\n  color: #fff;\n  background-color: #6c757d;\n  border-color: #6c757d;\n}\n\n.btn-outline-secondary:focus, .btn-outline-secondary.focus {\n  box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5);\n}\n\n.btn-outline-secondary.disabled, .btn-outline-secondary:disabled {\n  color: #6c757d;\n  background-color: transparent;\n}\n\n.btn-outline-secondary:not(:disabled):not(.disabled):active, .btn-outline-secondary:not(:disabled):not(.disabled).active,\n.show > .btn-outline-secondary.dropdown-toggle {\n  color: #fff;\n  background-color: #6c757d;\n  border-color: #6c757d;\n}\n\n.btn-outline-secondary:not(:disabled):not(.disabled):active:focus, .btn-outline-secondary:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-secondary.dropdown-toggle:focus {\n  box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5);\n}\n\n.btn-outline-success {\n  color: #28a745;\n  border-color: #28a745;\n}\n\n.btn-outline-success:hover {\n  color: #fff;\n  background-color: #28a745;\n  border-color: #28a745;\n}\n\n.btn-outline-success:focus, .btn-outline-success.focus {\n  box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5);\n}\n\n.btn-outline-success.disabled, .btn-outline-success:disabled {\n  color: #28a745;\n  background-color: transparent;\n}\n\n.btn-outline-success:not(:disabled):not(.disabled):active, .btn-outline-success:not(:disabled):not(.disabled).active,\n.show > .btn-outline-success.dropdown-toggle {\n  color: #fff;\n  background-color: #28a745;\n  border-color: #28a745;\n}\n\n.btn-outline-success:not(:disabled):not(.disabled):active:focus, .btn-outline-success:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-success.dropdown-toggle:focus {\n  box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5);\n}\n\n.btn-outline-info {\n  color: #17a2b8;\n  border-color: #17a2b8;\n}\n\n.btn-outline-info:hover {\n  color: #fff;\n  background-color: #17a2b8;\n  border-color: #17a2b8;\n}\n\n.btn-outline-info:focus, .btn-outline-info.focus {\n  box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5);\n}\n\n.btn-outline-info.disabled, .btn-outline-info:disabled {\n  color: #17a2b8;\n  background-color: transparent;\n}\n\n.btn-outline-info:not(:disabled):not(.disabled):active, .btn-outline-info:not(:disabled):not(.disabled).active,\n.show > .btn-outline-info.dropdown-toggle {\n  color: #fff;\n  background-color: #17a2b8;\n  border-color: #17a2b8;\n}\n\n.btn-outline-info:not(:disabled):not(.disabled):active:focus, .btn-outline-info:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-info.dropdown-toggle:focus {\n  box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5);\n}\n\n.btn-outline-warning {\n  color: #ffc107;\n  border-color: #ffc107;\n}\n\n.btn-outline-warning:hover {\n  color: #212529;\n  background-color: #ffc107;\n  border-color: #ffc107;\n}\n\n.btn-outline-warning:focus, .btn-outline-warning.focus {\n  box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5);\n}\n\n.btn-outline-warning.disabled, .btn-outline-warning:disabled {\n  color: #ffc107;\n  background-color: transparent;\n}\n\n.btn-outline-warning:not(:disabled):not(.disabled):active, .btn-outline-warning:not(:disabled):not(.disabled).active,\n.show > .btn-outline-warning.dropdown-toggle {\n  color: #212529;\n  background-color: #ffc107;\n  border-color: #ffc107;\n}\n\n.btn-outline-warning:not(:disabled):not(.disabled):active:focus, .btn-outline-warning:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-warning.dropdown-toggle:focus {\n  box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5);\n}\n\n.btn-outline-danger {\n  color: #dc3545;\n  border-color: #dc3545;\n}\n\n.btn-outline-danger:hover {\n  color: #fff;\n  background-color: #dc3545;\n  border-color: #dc3545;\n}\n\n.btn-outline-danger:focus, .btn-outline-danger.focus {\n  box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5);\n}\n\n.btn-outline-danger.disabled, .btn-outline-danger:disabled {\n  color: #dc3545;\n  background-color: transparent;\n}\n\n.btn-outline-danger:not(:disabled):not(.disabled):active, .btn-outline-danger:not(:disabled):not(.disabled).active,\n.show > .btn-outline-danger.dropdown-toggle {\n  color: #fff;\n  background-color: #dc3545;\n  border-color: #dc3545;\n}\n\n.btn-outline-danger:not(:disabled):not(.disabled):active:focus, .btn-outline-danger:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-danger.dropdown-toggle:focus {\n  box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5);\n}\n\n.btn-outline-light {\n  color: #f8f9fa;\n  border-color: #f8f9fa;\n}\n\n.btn-outline-light:hover {\n  color: #212529;\n  background-color: #f8f9fa;\n  border-color: #f8f9fa;\n}\n\n.btn-outline-light:focus, .btn-outline-light.focus {\n  box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5);\n}\n\n.btn-outline-light.disabled, .btn-outline-light:disabled {\n  color: #f8f9fa;\n  background-color: transparent;\n}\n\n.btn-outline-light:not(:disabled):not(.disabled):active, .btn-outline-light:not(:disabled):not(.disabled).active,\n.show > .btn-outline-light.dropdown-toggle {\n  color: #212529;\n  background-color: #f8f9fa;\n  border-color: #f8f9fa;\n}\n\n.btn-outline-light:not(:disabled):not(.disabled):active:focus, .btn-outline-light:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-light.dropdown-toggle:focus {\n  box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5);\n}\n\n.btn-outline-dark {\n  color: #343a40;\n  border-color: #343a40;\n}\n\n.btn-outline-dark:hover {\n  color: #fff;\n  background-color: #343a40;\n  border-color: #343a40;\n}\n\n.btn-outline-dark:focus, .btn-outline-dark.focus {\n  box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5);\n}\n\n.btn-outline-dark.disabled, .btn-outline-dark:disabled {\n  color: #343a40;\n  background-color: transparent;\n}\n\n.btn-outline-dark:not(:disabled):not(.disabled):active, .btn-outline-dark:not(:disabled):not(.disabled).active,\n.show > .btn-outline-dark.dropdown-toggle {\n  color: #fff;\n  background-color: #343a40;\n  border-color: #343a40;\n}\n\n.btn-outline-dark:not(:disabled):not(.disabled):active:focus, .btn-outline-dark:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-dark.dropdown-toggle:focus {\n  box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5);\n}\n\n.btn-link {\n  font-weight: 400;\n  color: #007bff;\n  text-decoration: none;\n}\n\n.btn-link:hover {\n  color: #0056b3;\n  text-decoration: underline;\n}\n\n.btn-link:focus, .btn-link.focus {\n  text-decoration: underline;\n}\n\n.btn-link:disabled, .btn-link.disabled {\n  color: #6c757d;\n  pointer-events: none;\n}\n\n.btn-lg, .btn-group-lg > .btn {\n  padding: 0.5rem 1rem;\n  font-size: 1.25rem;\n  line-height: 1.5;\n  border-radius: 0.3rem;\n}\n\n.btn-sm, .btn-group-sm > .btn {\n  padding: 0.25rem 0.5rem;\n  font-size: 0.875rem;\n  line-height: 1.5;\n  border-radius: 0.2rem;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n}\n\n.btn-block + .btn-block {\n  margin-top: 0.5rem;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.fade {\n  transition: opacity 0.15s linear;\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .fade {\n    transition: none;\n  }\n}\n\n.fade:not(.show) {\n  opacity: 0;\n}\n\n.collapse:not(.show) {\n  display: none;\n}\n\n.collapsing {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  transition: height 0.35s ease;\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .collapsing {\n    transition: none;\n  }\n}\n\n.dropup,\n.dropright,\n.dropdown,\n.dropleft {\n  position: relative;\n}\n\n.dropdown-toggle {\n  white-space: nowrap;\n}\n\n.dropdown-toggle::after {\n  display: inline-block;\n  margin-left: 0.255em;\n  vertical-align: 0.255em;\n  content: \"\";\n  border-top: 0.3em solid;\n  border-right: 0.3em solid transparent;\n  border-bottom: 0;\n  border-left: 0.3em solid transparent;\n}\n\n.dropdown-toggle:empty::after {\n  margin-left: 0;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 10rem;\n  padding: 0.5rem 0;\n  margin: 0.125rem 0 0;\n  font-size: 1rem;\n  color: #212529;\n  text-align: left;\n  list-style: none;\n  background-color: #fff;\n  background-clip: padding-box;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  border-radius: 0.25rem;\n}\n\n.dropdown-menu-left {\n  right: auto;\n  left: 0;\n}\n\n.dropdown-menu-right {\n  right: 0;\n  left: auto;\n}\n\n@media (min-width: 576px) {\n  .dropdown-menu-sm-left {\n    right: auto;\n    left: 0;\n  }\n  .dropdown-menu-sm-right {\n    right: 0;\n    left: auto;\n  }\n}\n\n@media (min-width: 768px) {\n  .dropdown-menu-md-left {\n    right: auto;\n    left: 0;\n  }\n  .dropdown-menu-md-right {\n    right: 0;\n    left: auto;\n  }\n}\n\n@media (min-width: 992px) {\n  .dropdown-menu-lg-left {\n    right: auto;\n    left: 0;\n  }\n  .dropdown-menu-lg-right {\n    right: 0;\n    left: auto;\n  }\n}\n\n@media (min-width: 1200px) {\n  .dropdown-menu-xl-left {\n    right: auto;\n    left: 0;\n  }\n  .dropdown-menu-xl-right {\n    right: 0;\n    left: auto;\n  }\n}\n\n.dropup .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-top: 0;\n  margin-bottom: 0.125rem;\n}\n\n.dropup .dropdown-toggle::after {\n  display: inline-block;\n  margin-left: 0.255em;\n  vertical-align: 0.255em;\n  content: \"\";\n  border-top: 0;\n  border-right: 0.3em solid transparent;\n  border-bottom: 0.3em solid;\n  border-left: 0.3em solid transparent;\n}\n\n.dropup .dropdown-toggle:empty::after {\n  margin-left: 0;\n}\n\n.dropright .dropdown-menu {\n  top: 0;\n  right: auto;\n  left: 100%;\n  margin-top: 0;\n  margin-left: 0.125rem;\n}\n\n.dropright .dropdown-toggle::after {\n  display: inline-block;\n  margin-left: 0.255em;\n  vertical-align: 0.255em;\n  content: \"\";\n  border-top: 0.3em solid transparent;\n  border-right: 0;\n  border-bottom: 0.3em solid transparent;\n  border-left: 0.3em solid;\n}\n\n.dropright .dropdown-toggle:empty::after {\n  margin-left: 0;\n}\n\n.dropright .dropdown-toggle::after {\n  vertical-align: 0;\n}\n\n.dropleft .dropdown-menu {\n  top: 0;\n  right: 100%;\n  left: auto;\n  margin-top: 0;\n  margin-right: 0.125rem;\n}\n\n.dropleft .dropdown-toggle::after {\n  display: inline-block;\n  margin-left: 0.255em;\n  vertical-align: 0.255em;\n  content: \"\";\n}\n\n.dropleft .dropdown-toggle::after {\n  display: none;\n}\n\n.dropleft .dropdown-toggle::before {\n  display: inline-block;\n  margin-right: 0.255em;\n  vertical-align: 0.255em;\n  content: \"\";\n  border-top: 0.3em solid transparent;\n  border-right: 0.3em solid;\n  border-bottom: 0.3em solid transparent;\n}\n\n.dropleft .dropdown-toggle:empty::after {\n  margin-left: 0;\n}\n\n.dropleft .dropdown-toggle::before {\n  vertical-align: 0;\n}\n\n.dropdown-menu[x-placement^=\"top\"], .dropdown-menu[x-placement^=\"right\"], .dropdown-menu[x-placement^=\"bottom\"], .dropdown-menu[x-placement^=\"left\"] {\n  right: auto;\n  bottom: auto;\n}\n\n.dropdown-divider {\n  height: 0;\n  margin: 0.5rem 0;\n  overflow: hidden;\n  border-top: 1px solid #e9ecef;\n}\n\n.dropdown-item {\n  display: block;\n  width: 100%;\n  padding: 0.25rem 1.5rem;\n  clear: both;\n  font-weight: 400;\n  color: #212529;\n  text-align: inherit;\n  white-space: nowrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.dropdown-item:hover, .dropdown-item:focus {\n  color: #16181b;\n  text-decoration: none;\n  background-color: #f8f9fa;\n}\n\n.dropdown-item.active, .dropdown-item:active {\n  color: #fff;\n  text-decoration: none;\n  background-color: #007bff;\n}\n\n.dropdown-item.disabled, .dropdown-item:disabled {\n  color: #6c757d;\n  pointer-events: none;\n  background-color: transparent;\n}\n\n.dropdown-menu.show {\n  display: block;\n}\n\n.dropdown-header {\n  display: block;\n  padding: 0.5rem 1.5rem;\n  margin-bottom: 0;\n  font-size: 0.875rem;\n  color: #6c757d;\n  white-space: nowrap;\n}\n\n.dropdown-item-text {\n  display: block;\n  padding: 0.25rem 1.5rem;\n  color: #212529;\n}\n\n.btn-group,\n.btn-group-vertical {\n  position: relative;\n  display: -ms-inline-flexbox;\n  display: inline-flex;\n  vertical-align: middle;\n}\n\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n  position: relative;\n  -ms-flex: 1 1 auto;\n  flex: 1 1 auto;\n}\n\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover {\n  z-index: 1;\n}\n\n.btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active,\n.btn-group-vertical > .btn:focus,\n.btn-group-vertical > .btn:active,\n.btn-group-vertical > .btn.active {\n  z-index: 1;\n}\n\n.btn-toolbar {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-wrap: wrap;\n  flex-wrap: wrap;\n  -ms-flex-pack: start;\n  justify-content: flex-start;\n}\n\n.btn-toolbar .input-group {\n  width: auto;\n}\n\n.btn-group > .btn:not(:first-child),\n.btn-group > .btn-group:not(:first-child) {\n  margin-left: -1px;\n}\n\n.btn-group > .btn:not(:last-child):not(.dropdown-toggle),\n.btn-group > .btn-group:not(:last-child) > .btn {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n}\n\n.btn-group > .btn:not(:first-child),\n.btn-group > .btn-group:not(:first-child) > .btn {\n  border-top-left-radius: 0;\n  border-bottom-left-radius: 0;\n}\n\n.dropdown-toggle-split {\n  padding-right: 0.5625rem;\n  padding-left: 0.5625rem;\n}\n\n.dropdown-toggle-split::after,\n.dropup .dropdown-toggle-split::after,\n.dropright .dropdown-toggle-split::after {\n  margin-left: 0;\n}\n\n.dropleft .dropdown-toggle-split::before {\n  margin-right: 0;\n}\n\n.btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split {\n  padding-right: 0.375rem;\n  padding-left: 0.375rem;\n}\n\n.btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split {\n  padding-right: 0.75rem;\n  padding-left: 0.75rem;\n}\n\n.btn-group-vertical {\n  -ms-flex-direction: column;\n  flex-direction: column;\n  -ms-flex-align: start;\n  align-items: flex-start;\n  -ms-flex-pack: center;\n  justify-content: center;\n}\n\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group {\n  width: 100%;\n}\n\n.btn-group-vertical > .btn:not(:first-child),\n.btn-group-vertical > .btn-group:not(:first-child) {\n  margin-top: -1px;\n}\n\n.btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle),\n.btn-group-vertical > .btn-group:not(:last-child) > .btn {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n\n.btn-group-vertical > .btn:not(:first-child),\n.btn-group-vertical > .btn-group:not(:first-child) > .btn {\n  border-top-left-radius: 0;\n  border-top-right-radius: 0;\n}\n\n.btn-group-toggle > .btn,\n.btn-group-toggle > .btn-group > .btn {\n  margin-bottom: 0;\n}\n\n.btn-group-toggle > .btn input[type=\"radio\"],\n.btn-group-toggle > .btn input[type=\"checkbox\"],\n.btn-group-toggle > .btn-group > .btn input[type=\"radio\"],\n.btn-group-toggle > .btn-group > .btn input[type=\"checkbox\"] {\n  position: absolute;\n  clip: rect(0, 0, 0, 0);\n  pointer-events: none;\n}\n\n.input-group {\n  position: relative;\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-wrap: wrap;\n  flex-wrap: wrap;\n  -ms-flex-align: stretch;\n  align-items: stretch;\n  width: 100%;\n}\n\n.input-group > .form-control,\n.input-group > .form-control-plaintext,\n.input-group > .custom-select,\n.input-group > .custom-file {\n  position: relative;\n  -ms-flex: 1 1 auto;\n  flex: 1 1 auto;\n  width: 1%;\n  min-width: 0;\n  margin-bottom: 0;\n}\n\n.input-group > .form-control + .form-control,\n.input-group > .form-control + .custom-select,\n.input-group > .form-control + .custom-file,\n.input-group > .form-control-plaintext + .form-control,\n.input-group > .form-control-plaintext + .custom-select,\n.input-group > .form-control-plaintext + .custom-file,\n.input-group > .custom-select + .form-control,\n.input-group > .custom-select + .custom-select,\n.input-group > .custom-select + .custom-file,\n.input-group > .custom-file + .form-control,\n.input-group > .custom-file + .custom-select,\n.input-group > .custom-file + .custom-file {\n  margin-left: -1px;\n}\n\n.input-group > .form-control:focus,\n.input-group > .custom-select:focus,\n.input-group > .custom-file .custom-file-input:focus ~ .custom-file-label {\n  z-index: 3;\n}\n\n.input-group > .custom-file .custom-file-input:focus {\n  z-index: 4;\n}\n\n.input-group > .form-control:not(:last-child),\n.input-group > .custom-select:not(:last-child) {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n}\n\n.input-group > .form-control:not(:first-child),\n.input-group > .custom-select:not(:first-child) {\n  border-top-left-radius: 0;\n  border-bottom-left-radius: 0;\n}\n\n.input-group > .custom-file {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-align: center;\n  align-items: center;\n}\n\n.input-group > .custom-file:not(:last-child) .custom-file-label,\n.input-group > .custom-file:not(:last-child) .custom-file-label::after {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n}\n\n.input-group > .custom-file:not(:first-child) .custom-file-label {\n  border-top-left-radius: 0;\n  border-bottom-left-radius: 0;\n}\n\n.input-group-prepend,\n.input-group-append {\n  display: -ms-flexbox;\n  display: flex;\n}\n\n.input-group-prepend .btn,\n.input-group-append .btn {\n  position: relative;\n  z-index: 2;\n}\n\n.input-group-prepend .btn:focus,\n.input-group-append .btn:focus {\n  z-index: 3;\n}\n\n.input-group-prepend .btn + .btn,\n.input-group-prepend .btn + .input-group-text,\n.input-group-prepend .input-group-text + .input-group-text,\n.input-group-prepend .input-group-text + .btn,\n.input-group-append .btn + .btn,\n.input-group-append .btn + .input-group-text,\n.input-group-append .input-group-text + .input-group-text,\n.input-group-append .input-group-text + .btn {\n  margin-left: -1px;\n}\n\n.input-group-prepend {\n  margin-right: -1px;\n}\n\n.input-group-append {\n  margin-left: -1px;\n}\n\n.input-group-text {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-align: center;\n  align-items: center;\n  padding: 0.375rem 0.75rem;\n  margin-bottom: 0;\n  font-size: 1rem;\n  font-weight: 400;\n  line-height: 1.5;\n  color: #495057;\n  text-align: center;\n  white-space: nowrap;\n  background-color: #e9ecef;\n  border: 1px solid #ced4da;\n  border-radius: 0.25rem;\n}\n\n.input-group-text input[type=\"radio\"],\n.input-group-text input[type=\"checkbox\"] {\n  margin-top: 0;\n}\n\n.input-group-lg > .form-control:not(textarea),\n.input-group-lg > .custom-select {\n  height: calc(1.5em + 1rem + 2px);\n}\n\n.input-group-lg > .form-control,\n.input-group-lg > .custom-select,\n.input-group-lg > .input-group-prepend > .input-group-text,\n.input-group-lg > .input-group-append > .input-group-text,\n.input-group-lg > .input-group-prepend > .btn,\n.input-group-lg > .input-group-append > .btn {\n  padding: 0.5rem 1rem;\n  font-size: 1.25rem;\n  line-height: 1.5;\n  border-radius: 0.3rem;\n}\n\n.input-group-sm > .form-control:not(textarea),\n.input-group-sm > .custom-select {\n  height: calc(1.5em + 0.5rem + 2px);\n}\n\n.input-group-sm > .form-control,\n.input-group-sm > .custom-select,\n.input-group-sm > .input-group-prepend > .input-group-text,\n.input-group-sm > .input-group-append > .input-group-text,\n.input-group-sm > .input-group-prepend > .btn,\n.input-group-sm > .input-group-append > .btn {\n  padding: 0.25rem 0.5rem;\n  font-size: 0.875rem;\n  line-height: 1.5;\n  border-radius: 0.2rem;\n}\n\n.input-group-lg > .custom-select,\n.input-group-sm > .custom-select {\n  padding-right: 1.75rem;\n}\n\n.input-group > .input-group-prepend > .btn,\n.input-group > .input-group-prepend > .input-group-text,\n.input-group > .input-group-append:not(:last-child) > .btn,\n.input-group > .input-group-append:not(:last-child) > .input-group-text,\n.input-group > .input-group-append:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group > .input-group-append:last-child > .input-group-text:not(:last-child) {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n}\n\n.input-group > .input-group-append > .btn,\n.input-group > .input-group-append > .input-group-text,\n.input-group > .input-group-prepend:not(:first-child) > .btn,\n.input-group > .input-group-prepend:not(:first-child) > .input-group-text,\n.input-group > .input-group-prepend:first-child > .btn:not(:first-child),\n.input-group > .input-group-prepend:first-child > .input-group-text:not(:first-child) {\n  border-top-left-radius: 0;\n  border-bottom-left-radius: 0;\n}\n\n.custom-control {\n  position: relative;\n  z-index: 1;\n  display: block;\n  min-height: 1.5rem;\n  padding-left: 1.5rem;\n  -webkit-print-color-adjust: exact;\n  color-adjust: exact;\n}\n\n.custom-control-inline {\n  display: -ms-inline-flexbox;\n  display: inline-flex;\n  margin-right: 1rem;\n}\n\n.custom-control-input {\n  position: absolute;\n  left: 0;\n  z-index: -1;\n  width: 1rem;\n  height: 1.25rem;\n  opacity: 0;\n}\n\n.custom-control-input:checked ~ .custom-control-label::before {\n  color: #fff;\n  border-color: #007bff;\n  background-color: #007bff;\n}\n\n.custom-control-input:focus ~ .custom-control-label::before {\n  box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-control-input:focus:not(:checked) ~ .custom-control-label::before {\n  border-color: #80bdff;\n}\n\n.custom-control-input:not(:disabled):active ~ .custom-control-label::before {\n  color: #fff;\n  background-color: #b3d7ff;\n  border-color: #b3d7ff;\n}\n\n.custom-control-input[disabled] ~ .custom-control-label, .custom-control-input:disabled ~ .custom-control-label {\n  color: #6c757d;\n}\n\n.custom-control-input[disabled] ~ .custom-control-label::before, .custom-control-input:disabled ~ .custom-control-label::before {\n  background-color: #e9ecef;\n}\n\n.custom-control-label {\n  position: relative;\n  margin-bottom: 0;\n  vertical-align: top;\n}\n\n.custom-control-label::before {\n  position: absolute;\n  top: 0.25rem;\n  left: -1.5rem;\n  display: block;\n  width: 1rem;\n  height: 1rem;\n  pointer-events: none;\n  content: \"\";\n  background-color: #fff;\n  border: #adb5bd solid 1px;\n}\n\n.custom-control-label::after {\n  position: absolute;\n  top: 0.25rem;\n  left: -1.5rem;\n  display: block;\n  width: 1rem;\n  height: 1rem;\n  content: \"\";\n  background: no-repeat 50% / 50% 50%;\n}\n\n.custom-checkbox .custom-control-label::before {\n  border-radius: 0.25rem;\n}\n\n.custom-checkbox .custom-control-input:checked ~ .custom-control-label::after {\n  background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3e%3c/svg%3e\");\n}\n\n.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::before {\n  border-color: #007bff;\n  background-color: #007bff;\n}\n\n.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::after {\n  background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e\");\n}\n\n.custom-checkbox .custom-control-input:disabled:checked ~ .custom-control-label::before {\n  background-color: rgba(0, 123, 255, 0.5);\n}\n\n.custom-checkbox .custom-control-input:disabled:indeterminate ~ .custom-control-label::before {\n  background-color: rgba(0, 123, 255, 0.5);\n}\n\n.custom-radio .custom-control-label::before {\n  border-radius: 50%;\n}\n\n.custom-radio .custom-control-input:checked ~ .custom-control-label::after {\n  background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e\");\n}\n\n.custom-radio .custom-control-input:disabled:checked ~ .custom-control-label::before {\n  background-color: rgba(0, 123, 255, 0.5);\n}\n\n.custom-switch {\n  padding-left: 2.25rem;\n}\n\n.custom-switch .custom-control-label::before {\n  left: -2.25rem;\n  width: 1.75rem;\n  pointer-events: all;\n  border-radius: 0.5rem;\n}\n\n.custom-switch .custom-control-label::after {\n  top: calc(0.25rem + 2px);\n  left: calc(-2.25rem + 2px);\n  width: calc(1rem - 4px);\n  height: calc(1rem - 4px);\n  background-color: #adb5bd;\n  border-radius: 0.5rem;\n  transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-transform 0.15s ease-in-out;\n  transition: transform 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n  transition: transform 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-transform 0.15s ease-in-out;\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .custom-switch .custom-control-label::after {\n    transition: none;\n  }\n}\n\n.custom-switch .custom-control-input:checked ~ .custom-control-label::after {\n  background-color: #fff;\n  -webkit-transform: translateX(0.75rem);\n  transform: translateX(0.75rem);\n}\n\n.custom-switch .custom-control-input:disabled:checked ~ .custom-control-label::before {\n  background-color: rgba(0, 123, 255, 0.5);\n}\n\n.custom-select {\n  display: inline-block;\n  width: 100%;\n  height: calc(1.5em + 0.75rem + 2px);\n  padding: 0.375rem 1.75rem 0.375rem 0.75rem;\n  font-size: 1rem;\n  font-weight: 400;\n  line-height: 1.5;\n  color: #495057;\n  vertical-align: middle;\n  background: #fff url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e\") no-repeat right 0.75rem center/8px 10px;\n  border: 1px solid #ced4da;\n  border-radius: 0.25rem;\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  appearance: none;\n}\n\n.custom-select:focus {\n  border-color: #80bdff;\n  outline: 0;\n  box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-select:focus::-ms-value {\n  color: #495057;\n  background-color: #fff;\n}\n\n.custom-select[multiple], .custom-select[size]:not([size=\"1\"]) {\n  height: auto;\n  padding-right: 0.75rem;\n  background-image: none;\n}\n\n.custom-select:disabled {\n  color: #6c757d;\n  background-color: #e9ecef;\n}\n\n.custom-select::-ms-expand {\n  display: none;\n}\n\n.custom-select:-moz-focusring {\n  color: transparent;\n  text-shadow: 0 0 0 #495057;\n}\n\n.custom-select-sm {\n  height: calc(1.5em + 0.5rem + 2px);\n  padding-top: 0.25rem;\n  padding-bottom: 0.25rem;\n  padding-left: 0.5rem;\n  font-size: 0.875rem;\n}\n\n.custom-select-lg {\n  height: calc(1.5em + 1rem + 2px);\n  padding-top: 0.5rem;\n  padding-bottom: 0.5rem;\n  padding-left: 1rem;\n  font-size: 1.25rem;\n}\n\n.custom-file {\n  position: relative;\n  display: inline-block;\n  width: 100%;\n  height: calc(1.5em + 0.75rem + 2px);\n  margin-bottom: 0;\n}\n\n.custom-file-input {\n  position: relative;\n  z-index: 2;\n  width: 100%;\n  height: calc(1.5em + 0.75rem + 2px);\n  margin: 0;\n  opacity: 0;\n}\n\n.custom-file-input:focus ~ .custom-file-label {\n  border-color: #80bdff;\n  box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-file-input[disabled] ~ .custom-file-label,\n.custom-file-input:disabled ~ .custom-file-label {\n  background-color: #e9ecef;\n}\n\n.custom-file-input:lang(en) ~ .custom-file-label::after {\n  content: \"Browse\";\n}\n\n.custom-file-input ~ .custom-file-label[data-browse]::after {\n  content: attr(data-browse);\n}\n\n.custom-file-label {\n  position: absolute;\n  top: 0;\n  right: 0;\n  left: 0;\n  z-index: 1;\n  height: calc(1.5em + 0.75rem + 2px);\n  padding: 0.375rem 0.75rem;\n  font-weight: 400;\n  line-height: 1.5;\n  color: #495057;\n  background-color: #fff;\n  border: 1px solid #ced4da;\n  border-radius: 0.25rem;\n}\n\n.custom-file-label::after {\n  position: absolute;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  z-index: 3;\n  display: block;\n  height: calc(1.5em + 0.75rem);\n  padding: 0.375rem 0.75rem;\n  line-height: 1.5;\n  color: #495057;\n  content: \"Browse\";\n  background-color: #e9ecef;\n  border-left: inherit;\n  border-radius: 0 0.25rem 0.25rem 0;\n}\n\n.custom-range {\n  width: 100%;\n  height: 1.4rem;\n  padding: 0;\n  background-color: transparent;\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  appearance: none;\n}\n\n.custom-range:focus {\n  outline: none;\n}\n\n.custom-range:focus::-webkit-slider-thumb {\n  box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-range:focus::-moz-range-thumb {\n  box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-range:focus::-ms-thumb {\n  box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-range::-moz-focus-outer {\n  border: 0;\n}\n\n.custom-range::-webkit-slider-thumb {\n  width: 1rem;\n  height: 1rem;\n  margin-top: -0.25rem;\n  background-color: #007bff;\n  border: 0;\n  border-radius: 1rem;\n  -webkit-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n  transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n  -webkit-appearance: none;\n  appearance: none;\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .custom-range::-webkit-slider-thumb {\n    -webkit-transition: none;\n    transition: none;\n  }\n}\n\n.custom-range::-webkit-slider-thumb:active {\n  background-color: #b3d7ff;\n}\n\n.custom-range::-webkit-slider-runnable-track {\n  width: 100%;\n  height: 0.5rem;\n  color: transparent;\n  cursor: pointer;\n  background-color: #dee2e6;\n  border-color: transparent;\n  border-radius: 1rem;\n}\n\n.custom-range::-moz-range-thumb {\n  width: 1rem;\n  height: 1rem;\n  background-color: #007bff;\n  border: 0;\n  border-radius: 1rem;\n  -moz-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n  transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n  -moz-appearance: none;\n  appearance: none;\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .custom-range::-moz-range-thumb {\n    -moz-transition: none;\n    transition: none;\n  }\n}\n\n.custom-range::-moz-range-thumb:active {\n  background-color: #b3d7ff;\n}\n\n.custom-range::-moz-range-track {\n  width: 100%;\n  height: 0.5rem;\n  color: transparent;\n  cursor: pointer;\n  background-color: #dee2e6;\n  border-color: transparent;\n  border-radius: 1rem;\n}\n\n.custom-range::-ms-thumb {\n  width: 1rem;\n  height: 1rem;\n  margin-top: 0;\n  margin-right: 0.2rem;\n  margin-left: 0.2rem;\n  background-color: #007bff;\n  border: 0;\n  border-radius: 1rem;\n  -ms-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n  transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n  appearance: none;\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .custom-range::-ms-thumb {\n    -ms-transition: none;\n    transition: none;\n  }\n}\n\n.custom-range::-ms-thumb:active {\n  background-color: #b3d7ff;\n}\n\n.custom-range::-ms-track {\n  width: 100%;\n  height: 0.5rem;\n  color: transparent;\n  cursor: pointer;\n  background-color: transparent;\n  border-color: transparent;\n  border-width: 0.5rem;\n}\n\n.custom-range::-ms-fill-lower {\n  background-color: #dee2e6;\n  border-radius: 1rem;\n}\n\n.custom-range::-ms-fill-upper {\n  margin-right: 15px;\n  background-color: #dee2e6;\n  border-radius: 1rem;\n}\n\n.custom-range:disabled::-webkit-slider-thumb {\n  background-color: #adb5bd;\n}\n\n.custom-range:disabled::-webkit-slider-runnable-track {\n  cursor: default;\n}\n\n.custom-range:disabled::-moz-range-thumb {\n  background-color: #adb5bd;\n}\n\n.custom-range:disabled::-moz-range-track {\n  cursor: default;\n}\n\n.custom-range:disabled::-ms-thumb {\n  background-color: #adb5bd;\n}\n\n.custom-control-label::before,\n.custom-file-label,\n.custom-select {\n  transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .custom-control-label::before,\n  .custom-file-label,\n  .custom-select {\n    transition: none;\n  }\n}\n\n.nav {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-wrap: wrap;\n  flex-wrap: wrap;\n  padding-left: 0;\n  margin-bottom: 0;\n  list-style: none;\n}\n\n.nav-link {\n  display: block;\n  padding: 0.5rem 1rem;\n}\n\n.nav-link:hover, .nav-link:focus {\n  text-decoration: none;\n}\n\n.nav-link.disabled {\n  color: #6c757d;\n  pointer-events: none;\n  cursor: default;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #dee2e6;\n}\n\n.nav-tabs .nav-item {\n  margin-bottom: -1px;\n}\n\n.nav-tabs .nav-link {\n  border: 1px solid transparent;\n  border-top-left-radius: 0.25rem;\n  border-top-right-radius: 0.25rem;\n}\n\n.nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus {\n  border-color: #e9ecef #e9ecef #dee2e6;\n}\n\n.nav-tabs .nav-link.disabled {\n  color: #6c757d;\n  background-color: transparent;\n  border-color: transparent;\n}\n\n.nav-tabs .nav-link.active,\n.nav-tabs .nav-item.show .nav-link {\n  color: #495057;\n  background-color: #fff;\n  border-color: #dee2e6 #dee2e6 #fff;\n}\n\n.nav-tabs .dropdown-menu {\n  margin-top: -1px;\n  border-top-left-radius: 0;\n  border-top-right-radius: 0;\n}\n\n.nav-pills .nav-link {\n  border-radius: 0.25rem;\n}\n\n.nav-pills .nav-link.active,\n.nav-pills .show > .nav-link {\n  color: #fff;\n  background-color: #007bff;\n}\n\n.nav-fill > .nav-link,\n.nav-fill .nav-item {\n  -ms-flex: 1 1 auto;\n  flex: 1 1 auto;\n  text-align: center;\n}\n\n.nav-justified > .nav-link,\n.nav-justified .nav-item {\n  -ms-flex-preferred-size: 0;\n  flex-basis: 0;\n  -ms-flex-positive: 1;\n  flex-grow: 1;\n  text-align: center;\n}\n\n.tab-content > .tab-pane {\n  display: none;\n}\n\n.tab-content > .active {\n  display: block;\n}\n\n.navbar {\n  position: relative;\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-wrap: wrap;\n  flex-wrap: wrap;\n  -ms-flex-align: center;\n  align-items: center;\n  -ms-flex-pack: justify;\n  justify-content: space-between;\n  padding: 0.5rem 1rem;\n}\n\n.navbar .container,\n.navbar .container-fluid, .navbar .container-sm, .navbar .container-md, .navbar .container-lg, .navbar .container-xl {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-wrap: wrap;\n  flex-wrap: wrap;\n  -ms-flex-align: center;\n  align-items: center;\n  -ms-flex-pack: justify;\n  justify-content: space-between;\n}\n\n.navbar-brand {\n  display: inline-block;\n  padding-top: 0.3125rem;\n  padding-bottom: 0.3125rem;\n  margin-right: 1rem;\n  font-size: 1.25rem;\n  line-height: inherit;\n  white-space: nowrap;\n}\n\n.navbar-brand:hover, .navbar-brand:focus {\n  text-decoration: none;\n}\n\n.navbar-nav {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-direction: column;\n  flex-direction: column;\n  padding-left: 0;\n  margin-bottom: 0;\n  list-style: none;\n}\n\n.navbar-nav .nav-link {\n  padding-right: 0;\n  padding-left: 0;\n}\n\n.navbar-nav .dropdown-menu {\n  position: static;\n  float: none;\n}\n\n.navbar-text {\n  display: inline-block;\n  padding-top: 0.5rem;\n  padding-bottom: 0.5rem;\n}\n\n.navbar-collapse {\n  -ms-flex-preferred-size: 100%;\n  flex-basis: 100%;\n  -ms-flex-positive: 1;\n  flex-grow: 1;\n  -ms-flex-align: center;\n  align-items: center;\n}\n\n.navbar-toggler {\n  padding: 0.25rem 0.75rem;\n  font-size: 1.25rem;\n  line-height: 1;\n  background-color: transparent;\n  border: 1px solid transparent;\n  border-radius: 0.25rem;\n}\n\n.navbar-toggler:hover, .navbar-toggler:focus {\n  text-decoration: none;\n}\n\n.navbar-toggler-icon {\n  display: inline-block;\n  width: 1.5em;\n  height: 1.5em;\n  vertical-align: middle;\n  content: \"\";\n  background: no-repeat center center;\n  background-size: 100% 100%;\n}\n\n@media (max-width: 575.98px) {\n  .navbar-expand-sm > .container,\n  .navbar-expand-sm > .container-fluid, .navbar-expand-sm > .container-sm, .navbar-expand-sm > .container-md, .navbar-expand-sm > .container-lg, .navbar-expand-sm > .container-xl {\n    padding-right: 0;\n    padding-left: 0;\n  }\n}\n\n@media (min-width: 576px) {\n  .navbar-expand-sm {\n    -ms-flex-flow: row nowrap;\n    flex-flow: row nowrap;\n    -ms-flex-pack: start;\n    justify-content: flex-start;\n  }\n  .navbar-expand-sm .navbar-nav {\n    -ms-flex-direction: row;\n    flex-direction: row;\n  }\n  .navbar-expand-sm .navbar-nav .dropdown-menu {\n    position: absolute;\n  }\n  .navbar-expand-sm .navbar-nav .nav-link {\n    padding-right: 0.5rem;\n    padding-left: 0.5rem;\n  }\n  .navbar-expand-sm > .container,\n  .navbar-expand-sm > .container-fluid, .navbar-expand-sm > .container-sm, .navbar-expand-sm > .container-md, .navbar-expand-sm > .container-lg, .navbar-expand-sm > .container-xl {\n    -ms-flex-wrap: nowrap;\n    flex-wrap: nowrap;\n  }\n  .navbar-expand-sm .navbar-collapse {\n    display: -ms-flexbox !important;\n    display: flex !important;\n    -ms-flex-preferred-size: auto;\n    flex-basis: auto;\n  }\n  .navbar-expand-sm .navbar-toggler {\n    display: none;\n  }\n}\n\n@media (max-width: 767.98px) {\n  .navbar-expand-md > .container,\n  .navbar-expand-md > .container-fluid, .navbar-expand-md > .container-sm, .navbar-expand-md > .container-md, .navbar-expand-md > .container-lg, .navbar-expand-md > .container-xl {\n    padding-right: 0;\n    padding-left: 0;\n  }\n}\n\n@media (min-width: 768px) {\n  .navbar-expand-md {\n    -ms-flex-flow: row nowrap;\n    flex-flow: row nowrap;\n    -ms-flex-pack: start;\n    justify-content: flex-start;\n  }\n  .navbar-expand-md .navbar-nav {\n    -ms-flex-direction: row;\n    flex-direction: row;\n  }\n  .navbar-expand-md .navbar-nav .dropdown-menu {\n    position: absolute;\n  }\n  .navbar-expand-md .navbar-nav .nav-link {\n    padding-right: 0.5rem;\n    padding-left: 0.5rem;\n  }\n  .navbar-expand-md > .container,\n  .navbar-expand-md > .container-fluid, .navbar-expand-md > .container-sm, .navbar-expand-md > .container-md, .navbar-expand-md > .container-lg, .navbar-expand-md > .container-xl {\n    -ms-flex-wrap: nowrap;\n    flex-wrap: nowrap;\n  }\n  .navbar-expand-md .navbar-collapse {\n    display: -ms-flexbox !important;\n    display: flex !important;\n    -ms-flex-preferred-size: auto;\n    flex-basis: auto;\n  }\n  .navbar-expand-md .navbar-toggler {\n    display: none;\n  }\n}\n\n@media (max-width: 991.98px) {\n  .navbar-expand-lg > .container,\n  .navbar-expand-lg > .container-fluid, .navbar-expand-lg > .container-sm, .navbar-expand-lg > .container-md, .navbar-expand-lg > .container-lg, .navbar-expand-lg > .container-xl {\n    padding-right: 0;\n    padding-left: 0;\n  }\n}\n\n@media (min-width: 992px) {\n  .navbar-expand-lg {\n    -ms-flex-flow: row nowrap;\n    flex-flow: row nowrap;\n    -ms-flex-pack: start;\n    justify-content: flex-start;\n  }\n  .navbar-expand-lg .navbar-nav {\n    -ms-flex-direction: row;\n    flex-direction: row;\n  }\n  .navbar-expand-lg .navbar-nav .dropdown-menu {\n    position: absolute;\n  }\n  .navbar-expand-lg .navbar-nav .nav-link {\n    padding-right: 0.5rem;\n    padding-left: 0.5rem;\n  }\n  .navbar-expand-lg > .container,\n  .navbar-expand-lg > .container-fluid, .navbar-expand-lg > .container-sm, .navbar-expand-lg > .container-md, .navbar-expand-lg > .container-lg, .navbar-expand-lg > .container-xl {\n    -ms-flex-wrap: nowrap;\n    flex-wrap: nowrap;\n  }\n  .navbar-expand-lg .navbar-collapse {\n    display: -ms-flexbox !important;\n    display: flex !important;\n    -ms-flex-preferred-size: auto;\n    flex-basis: auto;\n  }\n  .navbar-expand-lg .navbar-toggler {\n    display: none;\n  }\n}\n\n@media (max-width: 1199.98px) {\n  .navbar-expand-xl > .container,\n  .navbar-expand-xl > .container-fluid, .navbar-expand-xl > .container-sm, .navbar-expand-xl > .container-md, .navbar-expand-xl > .container-lg, .navbar-expand-xl > .container-xl {\n    padding-right: 0;\n    padding-left: 0;\n  }\n}\n\n@media (min-width: 1200px) {\n  .navbar-expand-xl {\n    -ms-flex-flow: row nowrap;\n    flex-flow: row nowrap;\n    -ms-flex-pack: start;\n    justify-content: flex-start;\n  }\n  .navbar-expand-xl .navbar-nav {\n    -ms-flex-direction: row;\n    flex-direction: row;\n  }\n  .navbar-expand-xl .navbar-nav .dropdown-menu {\n    position: absolute;\n  }\n  .navbar-expand-xl .navbar-nav .nav-link {\n    padding-right: 0.5rem;\n    padding-left: 0.5rem;\n  }\n  .navbar-expand-xl > .container,\n  .navbar-expand-xl > .container-fluid, .navbar-expand-xl > .container-sm, .navbar-expand-xl > .container-md, .navbar-expand-xl > .container-lg, .navbar-expand-xl > .container-xl {\n    -ms-flex-wrap: nowrap;\n    flex-wrap: nowrap;\n  }\n  .navbar-expand-xl .navbar-collapse {\n    display: -ms-flexbox !important;\n    display: flex !important;\n    -ms-flex-preferred-size: auto;\n    flex-basis: auto;\n  }\n  .navbar-expand-xl .navbar-toggler {\n    display: none;\n  }\n}\n\n.navbar-expand {\n  -ms-flex-flow: row nowrap;\n  flex-flow: row nowrap;\n  -ms-flex-pack: start;\n  justify-content: flex-start;\n}\n\n.navbar-expand > .container,\n.navbar-expand > .container-fluid, .navbar-expand > .container-sm, .navbar-expand > .container-md, .navbar-expand > .container-lg, .navbar-expand > .container-xl {\n  padding-right: 0;\n  padding-left: 0;\n}\n\n.navbar-expand .navbar-nav {\n  -ms-flex-direction: row;\n  flex-direction: row;\n}\n\n.navbar-expand .navbar-nav .dropdown-menu {\n  position: absolute;\n}\n\n.navbar-expand .navbar-nav .nav-link {\n  padding-right: 0.5rem;\n  padding-left: 0.5rem;\n}\n\n.navbar-expand > .container,\n.navbar-expand > .container-fluid, .navbar-expand > .container-sm, .navbar-expand > .container-md, .navbar-expand > .container-lg, .navbar-expand > .container-xl {\n  -ms-flex-wrap: nowrap;\n  flex-wrap: nowrap;\n}\n\n.navbar-expand .navbar-collapse {\n  display: -ms-flexbox !important;\n  display: flex !important;\n  -ms-flex-preferred-size: auto;\n  flex-basis: auto;\n}\n\n.navbar-expand .navbar-toggler {\n  display: none;\n}\n\n.navbar-light .navbar-brand {\n  color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-light .navbar-brand:hover, .navbar-light .navbar-brand:focus {\n  color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-light .navbar-nav .nav-link {\n  color: rgba(0, 0, 0, 0.5);\n}\n\n.navbar-light .navbar-nav .nav-link:hover, .navbar-light .navbar-nav .nav-link:focus {\n  color: rgba(0, 0, 0, 0.7);\n}\n\n.navbar-light .navbar-nav .nav-link.disabled {\n  color: rgba(0, 0, 0, 0.3);\n}\n\n.navbar-light .navbar-nav .show > .nav-link,\n.navbar-light .navbar-nav .active > .nav-link,\n.navbar-light .navbar-nav .nav-link.show,\n.navbar-light .navbar-nav .nav-link.active {\n  color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-light .navbar-toggler {\n  color: rgba(0, 0, 0, 0.5);\n  border-color: rgba(0, 0, 0, 0.1);\n}\n\n.navbar-light .navbar-toggler-icon {\n  background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e\");\n}\n\n.navbar-light .navbar-text {\n  color: rgba(0, 0, 0, 0.5);\n}\n\n.navbar-light .navbar-text a {\n  color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-light .navbar-text a:hover, .navbar-light .navbar-text a:focus {\n  color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-dark .navbar-brand {\n  color: #fff;\n}\n\n.navbar-dark .navbar-brand:hover, .navbar-dark .navbar-brand:focus {\n  color: #fff;\n}\n\n.navbar-dark .navbar-nav .nav-link {\n  color: rgba(255, 255, 255, 0.5);\n}\n\n.navbar-dark .navbar-nav .nav-link:hover, .navbar-dark .navbar-nav .nav-link:focus {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.navbar-dark .navbar-nav .nav-link.disabled {\n  color: rgba(255, 255, 255, 0.25);\n}\n\n.navbar-dark .navbar-nav .show > .nav-link,\n.navbar-dark .navbar-nav .active > .nav-link,\n.navbar-dark .navbar-nav .nav-link.show,\n.navbar-dark .navbar-nav .nav-link.active {\n  color: #fff;\n}\n\n.navbar-dark .navbar-toggler {\n  color: rgba(255, 255, 255, 0.5);\n  border-color: rgba(255, 255, 255, 0.1);\n}\n\n.navbar-dark .navbar-toggler-icon {\n  background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e\");\n}\n\n.navbar-dark .navbar-text {\n  color: rgba(255, 255, 255, 0.5);\n}\n\n.navbar-dark .navbar-text a {\n  color: #fff;\n}\n\n.navbar-dark .navbar-text a:hover, .navbar-dark .navbar-text a:focus {\n  color: #fff;\n}\n\n.card {\n  position: relative;\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-direction: column;\n  flex-direction: column;\n  min-width: 0;\n  word-wrap: break-word;\n  background-color: #fff;\n  background-clip: border-box;\n  border: 1px solid rgba(0, 0, 0, 0.125);\n  border-radius: 0.25rem;\n}\n\n.card > hr {\n  margin-right: 0;\n  margin-left: 0;\n}\n\n.card > .list-group {\n  border-top: inherit;\n  border-bottom: inherit;\n}\n\n.card > .list-group:first-child {\n  border-top-width: 0;\n  border-top-left-radius: calc(0.25rem - 1px);\n  border-top-right-radius: calc(0.25rem - 1px);\n}\n\n.card > .list-group:last-child {\n  border-bottom-width: 0;\n  border-bottom-right-radius: calc(0.25rem - 1px);\n  border-bottom-left-radius: calc(0.25rem - 1px);\n}\n\n.card > .card-header + .list-group,\n.card > .list-group + .card-footer {\n  border-top: 0;\n}\n\n.card-body {\n  -ms-flex: 1 1 auto;\n  flex: 1 1 auto;\n  min-height: 1px;\n  padding: 1.25rem;\n}\n\n.card-title {\n  margin-bottom: 0.75rem;\n}\n\n.card-subtitle {\n  margin-top: -0.375rem;\n  margin-bottom: 0;\n}\n\n.card-text:last-child {\n  margin-bottom: 0;\n}\n\n.card-link:hover {\n  text-decoration: none;\n}\n\n.card-link + .card-link {\n  margin-left: 1.25rem;\n}\n\n.card-header {\n  padding: 0.75rem 1.25rem;\n  margin-bottom: 0;\n  background-color: rgba(0, 0, 0, 0.03);\n  border-bottom: 1px solid rgba(0, 0, 0, 0.125);\n}\n\n.card-header:first-child {\n  border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0;\n}\n\n.card-footer {\n  padding: 0.75rem 1.25rem;\n  background-color: rgba(0, 0, 0, 0.03);\n  border-top: 1px solid rgba(0, 0, 0, 0.125);\n}\n\n.card-footer:last-child {\n  border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px);\n}\n\n.card-header-tabs {\n  margin-right: -0.625rem;\n  margin-bottom: -0.75rem;\n  margin-left: -0.625rem;\n  border-bottom: 0;\n}\n\n.card-header-pills {\n  margin-right: -0.625rem;\n  margin-left: -0.625rem;\n}\n\n.card-img-overlay {\n  position: absolute;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 1.25rem;\n  border-radius: calc(0.25rem - 1px);\n}\n\n.card-img,\n.card-img-top,\n.card-img-bottom {\n  -ms-flex-negative: 0;\n  flex-shrink: 0;\n  width: 100%;\n}\n\n.card-img,\n.card-img-top {\n  border-top-left-radius: calc(0.25rem - 1px);\n  border-top-right-radius: calc(0.25rem - 1px);\n}\n\n.card-img,\n.card-img-bottom {\n  border-bottom-right-radius: calc(0.25rem - 1px);\n  border-bottom-left-radius: calc(0.25rem - 1px);\n}\n\n.card-deck .card {\n  margin-bottom: 15px;\n}\n\n@media (min-width: 576px) {\n  .card-deck {\n    display: -ms-flexbox;\n    display: flex;\n    -ms-flex-flow: row wrap;\n    flex-flow: row wrap;\n    margin-right: -15px;\n    margin-left: -15px;\n  }\n  .card-deck .card {\n    -ms-flex: 1 0 0%;\n    flex: 1 0 0%;\n    margin-right: 15px;\n    margin-bottom: 0;\n    margin-left: 15px;\n  }\n}\n\n.card-group > .card {\n  margin-bottom: 15px;\n}\n\n@media (min-width: 576px) {\n  .card-group {\n    display: -ms-flexbox;\n    display: flex;\n    -ms-flex-flow: row wrap;\n    flex-flow: row wrap;\n  }\n  .card-group > .card {\n    -ms-flex: 1 0 0%;\n    flex: 1 0 0%;\n    margin-bottom: 0;\n  }\n  .card-group > .card + .card {\n    margin-left: 0;\n    border-left: 0;\n  }\n  .card-group > .card:not(:last-child) {\n    border-top-right-radius: 0;\n    border-bottom-right-radius: 0;\n  }\n  .card-group > .card:not(:last-child) .card-img-top,\n  .card-group > .card:not(:last-child) .card-header {\n    border-top-right-radius: 0;\n  }\n  .card-group > .card:not(:last-child) .card-img-bottom,\n  .card-group > .card:not(:last-child) .card-footer {\n    border-bottom-right-radius: 0;\n  }\n  .card-group > .card:not(:first-child) {\n    border-top-left-radius: 0;\n    border-bottom-left-radius: 0;\n  }\n  .card-group > .card:not(:first-child) .card-img-top,\n  .card-group > .card:not(:first-child) .card-header {\n    border-top-left-radius: 0;\n  }\n  .card-group > .card:not(:first-child) .card-img-bottom,\n  .card-group > .card:not(:first-child) .card-footer {\n    border-bottom-left-radius: 0;\n  }\n}\n\n.card-columns .card {\n  margin-bottom: 0.75rem;\n}\n\n@media (min-width: 576px) {\n  .card-columns {\n    -webkit-column-count: 3;\n    -moz-column-count: 3;\n    column-count: 3;\n    -webkit-column-gap: 1.25rem;\n    -moz-column-gap: 1.25rem;\n    column-gap: 1.25rem;\n    orphans: 1;\n    widows: 1;\n  }\n  .card-columns .card {\n    display: inline-block;\n    width: 100%;\n  }\n}\n\n.accordion {\n  overflow-anchor: none;\n}\n\n.accordion > .card {\n  overflow: hidden;\n}\n\n.accordion > .card:not(:last-of-type) {\n  border-bottom: 0;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n\n.accordion > .card:not(:first-of-type) {\n  border-top-left-radius: 0;\n  border-top-right-radius: 0;\n}\n\n.accordion > .card > .card-header {\n  border-radius: 0;\n  margin-bottom: -1px;\n}\n\n.breadcrumb {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-wrap: wrap;\n  flex-wrap: wrap;\n  padding: 0.75rem 1rem;\n  margin-bottom: 1rem;\n  list-style: none;\n  background-color: #e9ecef;\n  border-radius: 0.25rem;\n}\n\n.breadcrumb-item {\n  display: -ms-flexbox;\n  display: flex;\n}\n\n.breadcrumb-item + .breadcrumb-item {\n  padding-left: 0.5rem;\n}\n\n.breadcrumb-item + .breadcrumb-item::before {\n  display: inline-block;\n  padding-right: 0.5rem;\n  color: #6c757d;\n  content: \"/\";\n}\n\n.breadcrumb-item + .breadcrumb-item:hover::before {\n  text-decoration: underline;\n}\n\n.breadcrumb-item + .breadcrumb-item:hover::before {\n  text-decoration: none;\n}\n\n.breadcrumb-item.active {\n  color: #6c757d;\n}\n\n.pagination {\n  display: -ms-flexbox;\n  display: flex;\n  padding-left: 0;\n  list-style: none;\n  border-radius: 0.25rem;\n}\n\n.page-link {\n  position: relative;\n  display: block;\n  padding: 0.5rem 0.75rem;\n  margin-left: -1px;\n  line-height: 1.25;\n  color: #007bff;\n  background-color: #fff;\n  border: 1px solid #dee2e6;\n}\n\n.page-link:hover {\n  z-index: 2;\n  color: #0056b3;\n  text-decoration: none;\n  background-color: #e9ecef;\n  border-color: #dee2e6;\n}\n\n.page-link:focus {\n  z-index: 3;\n  outline: 0;\n  box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.page-item:first-child .page-link {\n  margin-left: 0;\n  border-top-left-radius: 0.25rem;\n  border-bottom-left-radius: 0.25rem;\n}\n\n.page-item:last-child .page-link {\n  border-top-right-radius: 0.25rem;\n  border-bottom-right-radius: 0.25rem;\n}\n\n.page-item.active .page-link {\n  z-index: 3;\n  color: #fff;\n  background-color: #007bff;\n  border-color: #007bff;\n}\n\n.page-item.disabled .page-link {\n  color: #6c757d;\n  pointer-events: none;\n  cursor: auto;\n  background-color: #fff;\n  border-color: #dee2e6;\n}\n\n.pagination-lg .page-link {\n  padding: 0.75rem 1.5rem;\n  font-size: 1.25rem;\n  line-height: 1.5;\n}\n\n.pagination-lg .page-item:first-child .page-link {\n  border-top-left-radius: 0.3rem;\n  border-bottom-left-radius: 0.3rem;\n}\n\n.pagination-lg .page-item:last-child .page-link {\n  border-top-right-radius: 0.3rem;\n  border-bottom-right-radius: 0.3rem;\n}\n\n.pagination-sm .page-link {\n  padding: 0.25rem 0.5rem;\n  font-size: 0.875rem;\n  line-height: 1.5;\n}\n\n.pagination-sm .page-item:first-child .page-link {\n  border-top-left-radius: 0.2rem;\n  border-bottom-left-radius: 0.2rem;\n}\n\n.pagination-sm .page-item:last-child .page-link {\n  border-top-right-radius: 0.2rem;\n  border-bottom-right-radius: 0.2rem;\n}\n\n.badge {\n  display: inline-block;\n  padding: 0.25em 0.4em;\n  font-size: 75%;\n  font-weight: 700;\n  line-height: 1;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: baseline;\n  border-radius: 0.25rem;\n  transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .badge {\n    transition: none;\n  }\n}\n\na.badge:hover, a.badge:focus {\n  text-decoration: none;\n}\n\n.badge:empty {\n  display: none;\n}\n\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.badge-pill {\n  padding-right: 0.6em;\n  padding-left: 0.6em;\n  border-radius: 10rem;\n}\n\n.badge-primary {\n  color: #fff;\n  background-color: #007bff;\n}\n\na.badge-primary:hover, a.badge-primary:focus {\n  color: #fff;\n  background-color: #0062cc;\n}\n\na.badge-primary:focus, a.badge-primary.focus {\n  outline: 0;\n  box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5);\n}\n\n.badge-secondary {\n  color: #fff;\n  background-color: #6c757d;\n}\n\na.badge-secondary:hover, a.badge-secondary:focus {\n  color: #fff;\n  background-color: #545b62;\n}\n\na.badge-secondary:focus, a.badge-secondary.focus {\n  outline: 0;\n  box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5);\n}\n\n.badge-success {\n  color: #fff;\n  background-color: #28a745;\n}\n\na.badge-success:hover, a.badge-success:focus {\n  color: #fff;\n  background-color: #1e7e34;\n}\n\na.badge-success:focus, a.badge-success.focus {\n  outline: 0;\n  box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5);\n}\n\n.badge-info {\n  color: #fff;\n  background-color: #17a2b8;\n}\n\na.badge-info:hover, a.badge-info:focus {\n  color: #fff;\n  background-color: #117a8b;\n}\n\na.badge-info:focus, a.badge-info.focus {\n  outline: 0;\n  box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5);\n}\n\n.badge-warning {\n  color: #212529;\n  background-color: #ffc107;\n}\n\na.badge-warning:hover, a.badge-warning:focus {\n  color: #212529;\n  background-color: #d39e00;\n}\n\na.badge-warning:focus, a.badge-warning.focus {\n  outline: 0;\n  box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5);\n}\n\n.badge-danger {\n  color: #fff;\n  background-color: #dc3545;\n}\n\na.badge-danger:hover, a.badge-danger:focus {\n  color: #fff;\n  background-color: #bd2130;\n}\n\na.badge-danger:focus, a.badge-danger.focus {\n  outline: 0;\n  box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5);\n}\n\n.badge-light {\n  color: #212529;\n  background-color: #f8f9fa;\n}\n\na.badge-light:hover, a.badge-light:focus {\n  color: #212529;\n  background-color: #dae0e5;\n}\n\na.badge-light:focus, a.badge-light.focus {\n  outline: 0;\n  box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5);\n}\n\n.badge-dark {\n  color: #fff;\n  background-color: #343a40;\n}\n\na.badge-dark:hover, a.badge-dark:focus {\n  color: #fff;\n  background-color: #1d2124;\n}\n\na.badge-dark:focus, a.badge-dark.focus {\n  outline: 0;\n  box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5);\n}\n\n.jumbotron {\n  padding: 2rem 1rem;\n  margin-bottom: 2rem;\n  background-color: #e9ecef;\n  border-radius: 0.3rem;\n}\n\n@media (min-width: 576px) {\n  .jumbotron {\n    padding: 4rem 2rem;\n  }\n}\n\n.jumbotron-fluid {\n  padding-right: 0;\n  padding-left: 0;\n  border-radius: 0;\n}\n\n.alert {\n  position: relative;\n  padding: 0.75rem 1.25rem;\n  margin-bottom: 1rem;\n  border: 1px solid transparent;\n  border-radius: 0.25rem;\n}\n\n.alert-heading {\n  color: inherit;\n}\n\n.alert-link {\n  font-weight: 700;\n}\n\n.alert-dismissible {\n  padding-right: 4rem;\n}\n\n.alert-dismissible .close {\n  position: absolute;\n  top: 0;\n  right: 0;\n  z-index: 2;\n  padding: 0.75rem 1.25rem;\n  color: inherit;\n}\n\n.alert-primary {\n  color: #004085;\n  background-color: #cce5ff;\n  border-color: #b8daff;\n}\n\n.alert-primary hr {\n  border-top-color: #9fcdff;\n}\n\n.alert-primary .alert-link {\n  color: #002752;\n}\n\n.alert-secondary {\n  color: #383d41;\n  background-color: #e2e3e5;\n  border-color: #d6d8db;\n}\n\n.alert-secondary hr {\n  border-top-color: #c8cbcf;\n}\n\n.alert-secondary .alert-link {\n  color: #202326;\n}\n\n.alert-success {\n  color: #155724;\n  background-color: #d4edda;\n  border-color: #c3e6cb;\n}\n\n.alert-success hr {\n  border-top-color: #b1dfbb;\n}\n\n.alert-success .alert-link {\n  color: #0b2e13;\n}\n\n.alert-info {\n  color: #0c5460;\n  background-color: #d1ecf1;\n  border-color: #bee5eb;\n}\n\n.alert-info hr {\n  border-top-color: #abdde5;\n}\n\n.alert-info .alert-link {\n  color: #062c33;\n}\n\n.alert-warning {\n  color: #856404;\n  background-color: #fff3cd;\n  border-color: #ffeeba;\n}\n\n.alert-warning hr {\n  border-top-color: #ffe8a1;\n}\n\n.alert-warning .alert-link {\n  color: #533f03;\n}\n\n.alert-danger {\n  color: #721c24;\n  background-color: #f8d7da;\n  border-color: #f5c6cb;\n}\n\n.alert-danger hr {\n  border-top-color: #f1b0b7;\n}\n\n.alert-danger .alert-link {\n  color: #491217;\n}\n\n.alert-light {\n  color: #818182;\n  background-color: #fefefe;\n  border-color: #fdfdfe;\n}\n\n.alert-light hr {\n  border-top-color: #ececf6;\n}\n\n.alert-light .alert-link {\n  color: #686868;\n}\n\n.alert-dark {\n  color: #1b1e21;\n  background-color: #d6d8d9;\n  border-color: #c6c8ca;\n}\n\n.alert-dark hr {\n  border-top-color: #b9bbbe;\n}\n\n.alert-dark .alert-link {\n  color: #040505;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 1rem 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 1rem 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  display: -ms-flexbox;\n  display: flex;\n  height: 1rem;\n  overflow: hidden;\n  line-height: 0;\n  font-size: 0.75rem;\n  background-color: #e9ecef;\n  border-radius: 0.25rem;\n}\n\n.progress-bar {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-direction: column;\n  flex-direction: column;\n  -ms-flex-pack: center;\n  justify-content: center;\n  overflow: hidden;\n  color: #fff;\n  text-align: center;\n  white-space: nowrap;\n  background-color: #007bff;\n  transition: width 0.6s ease;\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .progress-bar {\n    transition: none;\n  }\n}\n\n.progress-bar-striped {\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-size: 1rem 1rem;\n}\n\n.progress-bar-animated {\n  -webkit-animation: progress-bar-stripes 1s linear infinite;\n  animation: progress-bar-stripes 1s linear infinite;\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .progress-bar-animated {\n    -webkit-animation: none;\n    animation: none;\n  }\n}\n\n.media {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-align: start;\n  align-items: flex-start;\n}\n\n.media-body {\n  -ms-flex: 1;\n  flex: 1;\n}\n\n.list-group {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-direction: column;\n  flex-direction: column;\n  padding-left: 0;\n  margin-bottom: 0;\n  border-radius: 0.25rem;\n}\n\n.list-group-item-action {\n  width: 100%;\n  color: #495057;\n  text-align: inherit;\n}\n\n.list-group-item-action:hover, .list-group-item-action:focus {\n  z-index: 1;\n  color: #495057;\n  text-decoration: none;\n  background-color: #f8f9fa;\n}\n\n.list-group-item-action:active {\n  color: #212529;\n  background-color: #e9ecef;\n}\n\n.list-group-item {\n  position: relative;\n  display: block;\n  padding: 0.75rem 1.25rem;\n  background-color: #fff;\n  border: 1px solid rgba(0, 0, 0, 0.125);\n}\n\n.list-group-item:first-child {\n  border-top-left-radius: inherit;\n  border-top-right-radius: inherit;\n}\n\n.list-group-item:last-child {\n  border-bottom-right-radius: inherit;\n  border-bottom-left-radius: inherit;\n}\n\n.list-group-item.disabled, .list-group-item:disabled {\n  color: #6c757d;\n  pointer-events: none;\n  background-color: #fff;\n}\n\n.list-group-item.active {\n  z-index: 2;\n  color: #fff;\n  background-color: #007bff;\n  border-color: #007bff;\n}\n\n.list-group-item + .list-group-item {\n  border-top-width: 0;\n}\n\n.list-group-item + .list-group-item.active {\n  margin-top: -1px;\n  border-top-width: 1px;\n}\n\n.list-group-horizontal {\n  -ms-flex-direction: row;\n  flex-direction: row;\n}\n\n.list-group-horizontal > .list-group-item:first-child {\n  border-bottom-left-radius: 0.25rem;\n  border-top-right-radius: 0;\n}\n\n.list-group-horizontal > .list-group-item:last-child {\n  border-top-right-radius: 0.25rem;\n  border-bottom-left-radius: 0;\n}\n\n.list-group-horizontal > .list-group-item.active {\n  margin-top: 0;\n}\n\n.list-group-horizontal > .list-group-item + .list-group-item {\n  border-top-width: 1px;\n  border-left-width: 0;\n}\n\n.list-group-horizontal > .list-group-item + .list-group-item.active {\n  margin-left: -1px;\n  border-left-width: 1px;\n}\n\n@media (min-width: 576px) {\n  .list-group-horizontal-sm {\n    -ms-flex-direction: row;\n    flex-direction: row;\n  }\n  .list-group-horizontal-sm > .list-group-item:first-child {\n    border-bottom-left-radius: 0.25rem;\n    border-top-right-radius: 0;\n  }\n  .list-group-horizontal-sm > .list-group-item:last-child {\n    border-top-right-radius: 0.25rem;\n    border-bottom-left-radius: 0;\n  }\n  .list-group-horizontal-sm > .list-group-item.active {\n    margin-top: 0;\n  }\n  .list-group-horizontal-sm > .list-group-item + .list-group-item {\n    border-top-width: 1px;\n    border-left-width: 0;\n  }\n  .list-group-horizontal-sm > .list-group-item + .list-group-item.active {\n    margin-left: -1px;\n    border-left-width: 1px;\n  }\n}\n\n@media (min-width: 768px) {\n  .list-group-horizontal-md {\n    -ms-flex-direction: row;\n    flex-direction: row;\n  }\n  .list-group-horizontal-md > .list-group-item:first-child {\n    border-bottom-left-radius: 0.25rem;\n    border-top-right-radius: 0;\n  }\n  .list-group-horizontal-md > .list-group-item:last-child {\n    border-top-right-radius: 0.25rem;\n    border-bottom-left-radius: 0;\n  }\n  .list-group-horizontal-md > .list-group-item.active {\n    margin-top: 0;\n  }\n  .list-group-horizontal-md > .list-group-item + .list-group-item {\n    border-top-width: 1px;\n    border-left-width: 0;\n  }\n  .list-group-horizontal-md > .list-group-item + .list-group-item.active {\n    margin-left: -1px;\n    border-left-width: 1px;\n  }\n}\n\n@media (min-width: 992px) {\n  .list-group-horizontal-lg {\n    -ms-flex-direction: row;\n    flex-direction: row;\n  }\n  .list-group-horizontal-lg > .list-group-item:first-child {\n    border-bottom-left-radius: 0.25rem;\n    border-top-right-radius: 0;\n  }\n  .list-group-horizontal-lg > .list-group-item:last-child {\n    border-top-right-radius: 0.25rem;\n    border-bottom-left-radius: 0;\n  }\n  .list-group-horizontal-lg > .list-group-item.active {\n    margin-top: 0;\n  }\n  .list-group-horizontal-lg > .list-group-item + .list-group-item {\n    border-top-width: 1px;\n    border-left-width: 0;\n  }\n  .list-group-horizontal-lg > .list-group-item + .list-group-item.active {\n    margin-left: -1px;\n    border-left-width: 1px;\n  }\n}\n\n@media (min-width: 1200px) {\n  .list-group-horizontal-xl {\n    -ms-flex-direction: row;\n    flex-direction: row;\n  }\n  .list-group-horizontal-xl > .list-group-item:first-child {\n    border-bottom-left-radius: 0.25rem;\n    border-top-right-radius: 0;\n  }\n  .list-group-horizontal-xl > .list-group-item:last-child {\n    border-top-right-radius: 0.25rem;\n    border-bottom-left-radius: 0;\n  }\n  .list-group-horizontal-xl > .list-group-item.active {\n    margin-top: 0;\n  }\n  .list-group-horizontal-xl > .list-group-item + .list-group-item {\n    border-top-width: 1px;\n    border-left-width: 0;\n  }\n  .list-group-horizontal-xl > .list-group-item + .list-group-item.active {\n    margin-left: -1px;\n    border-left-width: 1px;\n  }\n}\n\n.list-group-flush {\n  border-radius: 0;\n}\n\n.list-group-flush > .list-group-item {\n  border-width: 0 0 1px;\n}\n\n.list-group-flush > .list-group-item:last-child {\n  border-bottom-width: 0;\n}\n\n.list-group-item-primary {\n  color: #004085;\n  background-color: #b8daff;\n}\n\n.list-group-item-primary.list-group-item-action:hover, .list-group-item-primary.list-group-item-action:focus {\n  color: #004085;\n  background-color: #9fcdff;\n}\n\n.list-group-item-primary.list-group-item-action.active {\n  color: #fff;\n  background-color: #004085;\n  border-color: #004085;\n}\n\n.list-group-item-secondary {\n  color: #383d41;\n  background-color: #d6d8db;\n}\n\n.list-group-item-secondary.list-group-item-action:hover, .list-group-item-secondary.list-group-item-action:focus {\n  color: #383d41;\n  background-color: #c8cbcf;\n}\n\n.list-group-item-secondary.list-group-item-action.active {\n  color: #fff;\n  background-color: #383d41;\n  border-color: #383d41;\n}\n\n.list-group-item-success {\n  color: #155724;\n  background-color: #c3e6cb;\n}\n\n.list-group-item-success.list-group-item-action:hover, .list-group-item-success.list-group-item-action:focus {\n  color: #155724;\n  background-color: #b1dfbb;\n}\n\n.list-group-item-success.list-group-item-action.active {\n  color: #fff;\n  background-color: #155724;\n  border-color: #155724;\n}\n\n.list-group-item-info {\n  color: #0c5460;\n  background-color: #bee5eb;\n}\n\n.list-group-item-info.list-group-item-action:hover, .list-group-item-info.list-group-item-action:focus {\n  color: #0c5460;\n  background-color: #abdde5;\n}\n\n.list-group-item-info.list-group-item-action.active {\n  color: #fff;\n  background-color: #0c5460;\n  border-color: #0c5460;\n}\n\n.list-group-item-warning {\n  color: #856404;\n  background-color: #ffeeba;\n}\n\n.list-group-item-warning.list-group-item-action:hover, .list-group-item-warning.list-group-item-action:focus {\n  color: #856404;\n  background-color: #ffe8a1;\n}\n\n.list-group-item-warning.list-group-item-action.active {\n  color: #fff;\n  background-color: #856404;\n  border-color: #856404;\n}\n\n.list-group-item-danger {\n  color: #721c24;\n  background-color: #f5c6cb;\n}\n\n.list-group-item-danger.list-group-item-action:hover, .list-group-item-danger.list-group-item-action:focus {\n  color: #721c24;\n  background-color: #f1b0b7;\n}\n\n.list-group-item-danger.list-group-item-action.active {\n  color: #fff;\n  background-color: #721c24;\n  border-color: #721c24;\n}\n\n.list-group-item-light {\n  color: #818182;\n  background-color: #fdfdfe;\n}\n\n.list-group-item-light.list-group-item-action:hover, .list-group-item-light.list-group-item-action:focus {\n  color: #818182;\n  background-color: #ececf6;\n}\n\n.list-group-item-light.list-group-item-action.active {\n  color: #fff;\n  background-color: #818182;\n  border-color: #818182;\n}\n\n.list-group-item-dark {\n  color: #1b1e21;\n  background-color: #c6c8ca;\n}\n\n.list-group-item-dark.list-group-item-action:hover, .list-group-item-dark.list-group-item-action:focus {\n  color: #1b1e21;\n  background-color: #b9bbbe;\n}\n\n.list-group-item-dark.list-group-item-action.active {\n  color: #fff;\n  background-color: #1b1e21;\n  border-color: #1b1e21;\n}\n\n.close {\n  float: right;\n  font-size: 1.5rem;\n  font-weight: 700;\n  line-height: 1;\n  color: #000;\n  text-shadow: 0 1px 0 #fff;\n  opacity: .5;\n}\n\n.close:hover {\n  color: #000;\n  text-decoration: none;\n}\n\n.close:not(:disabled):not(.disabled):hover, .close:not(:disabled):not(.disabled):focus {\n  opacity: .75;\n}\n\nbutton.close {\n  padding: 0;\n  background-color: transparent;\n  border: 0;\n}\n\na.close.disabled {\n  pointer-events: none;\n}\n\n.toast {\n  -ms-flex-preferred-size: 350px;\n  flex-basis: 350px;\n  max-width: 350px;\n  font-size: 0.875rem;\n  background-color: rgba(255, 255, 255, 0.85);\n  background-clip: padding-box;\n  border: 1px solid rgba(0, 0, 0, 0.1);\n  box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.1);\n  opacity: 0;\n  border-radius: 0.25rem;\n}\n\n.toast:not(:last-child) {\n  margin-bottom: 0.75rem;\n}\n\n.toast.showing {\n  opacity: 1;\n}\n\n.toast.show {\n  display: block;\n  opacity: 1;\n}\n\n.toast.hide {\n  display: none;\n}\n\n.toast-header {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-align: center;\n  align-items: center;\n  padding: 0.25rem 0.75rem;\n  color: #6c757d;\n  background-color: rgba(255, 255, 255, 0.85);\n  background-clip: padding-box;\n  border-bottom: 1px solid rgba(0, 0, 0, 0.05);\n  border-top-left-radius: calc(0.25rem - 1px);\n  border-top-right-radius: calc(0.25rem - 1px);\n}\n\n.toast-body {\n  padding: 0.75rem;\n}\n\n.modal-open {\n  overflow: hidden;\n}\n\n.modal-open .modal {\n  overflow-x: hidden;\n  overflow-y: auto;\n}\n\n.modal {\n  position: fixed;\n  top: 0;\n  left: 0;\n  z-index: 1050;\n  display: none;\n  width: 100%;\n  height: 100%;\n  overflow: hidden;\n  outline: 0;\n}\n\n.modal-dialog {\n  position: relative;\n  width: auto;\n  margin: 0.5rem;\n  pointer-events: none;\n}\n\n.modal.fade .modal-dialog {\n  transition: -webkit-transform 0.3s ease-out;\n  transition: transform 0.3s ease-out;\n  transition: transform 0.3s ease-out, -webkit-transform 0.3s ease-out;\n  -webkit-transform: translate(0, -50px);\n  transform: translate(0, -50px);\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .modal.fade .modal-dialog {\n    transition: none;\n  }\n}\n\n.modal.show .modal-dialog {\n  -webkit-transform: none;\n  transform: none;\n}\n\n.modal.modal-static .modal-dialog {\n  -webkit-transform: scale(1.02);\n  transform: scale(1.02);\n}\n\n.modal-dialog-scrollable {\n  display: -ms-flexbox;\n  display: flex;\n  max-height: calc(100% - 1rem);\n}\n\n.modal-dialog-scrollable .modal-content {\n  max-height: calc(100vh - 1rem);\n  overflow: hidden;\n}\n\n.modal-dialog-scrollable .modal-header,\n.modal-dialog-scrollable .modal-footer {\n  -ms-flex-negative: 0;\n  flex-shrink: 0;\n}\n\n.modal-dialog-scrollable .modal-body {\n  overflow-y: auto;\n}\n\n.modal-dialog-centered {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-align: center;\n  align-items: center;\n  min-height: calc(100% - 1rem);\n}\n\n.modal-dialog-centered::before {\n  display: block;\n  height: calc(100vh - 1rem);\n  height: -webkit-min-content;\n  height: -moz-min-content;\n  height: min-content;\n  content: \"\";\n}\n\n.modal-dialog-centered.modal-dialog-scrollable {\n  -ms-flex-direction: column;\n  flex-direction: column;\n  -ms-flex-pack: center;\n  justify-content: center;\n  height: 100%;\n}\n\n.modal-dialog-centered.modal-dialog-scrollable .modal-content {\n  max-height: none;\n}\n\n.modal-dialog-centered.modal-dialog-scrollable::before {\n  content: none;\n}\n\n.modal-content {\n  position: relative;\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-direction: column;\n  flex-direction: column;\n  width: 100%;\n  pointer-events: auto;\n  background-color: #fff;\n  background-clip: padding-box;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  border-radius: 0.3rem;\n  outline: 0;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  left: 0;\n  z-index: 1040;\n  width: 100vw;\n  height: 100vh;\n  background-color: #000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop.show {\n  opacity: 0.5;\n}\n\n.modal-header {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-align: start;\n  align-items: flex-start;\n  -ms-flex-pack: justify;\n  justify-content: space-between;\n  padding: 1rem 1rem;\n  border-bottom: 1px solid #dee2e6;\n  border-top-left-radius: calc(0.3rem - 1px);\n  border-top-right-radius: calc(0.3rem - 1px);\n}\n\n.modal-header .close {\n  padding: 1rem 1rem;\n  margin: -1rem -1rem -1rem auto;\n}\n\n.modal-title {\n  margin-bottom: 0;\n  line-height: 1.5;\n}\n\n.modal-body {\n  position: relative;\n  -ms-flex: 1 1 auto;\n  flex: 1 1 auto;\n  padding: 1rem;\n}\n\n.modal-footer {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-wrap: wrap;\n  flex-wrap: wrap;\n  -ms-flex-align: center;\n  align-items: center;\n  -ms-flex-pack: end;\n  justify-content: flex-end;\n  padding: 0.75rem;\n  border-top: 1px solid #dee2e6;\n  border-bottom-right-radius: calc(0.3rem - 1px);\n  border-bottom-left-radius: calc(0.3rem - 1px);\n}\n\n.modal-footer > * {\n  margin: 0.25rem;\n}\n\n.modal-scrollbar-measure {\n  position: absolute;\n  top: -9999px;\n  width: 50px;\n  height: 50px;\n  overflow: scroll;\n}\n\n@media (min-width: 576px) {\n  .modal-dialog {\n    max-width: 500px;\n    margin: 1.75rem auto;\n  }\n  .modal-dialog-scrollable {\n    max-height: calc(100% - 3.5rem);\n  }\n  .modal-dialog-scrollable .modal-content {\n    max-height: calc(100vh - 3.5rem);\n  }\n  .modal-dialog-centered {\n    min-height: calc(100% - 3.5rem);\n  }\n  .modal-dialog-centered::before {\n    height: calc(100vh - 3.5rem);\n    height: -webkit-min-content;\n    height: -moz-min-content;\n    height: min-content;\n  }\n  .modal-sm {\n    max-width: 300px;\n  }\n}\n\n@media (min-width: 992px) {\n  .modal-lg,\n  .modal-xl {\n    max-width: 800px;\n  }\n}\n\n@media (min-width: 1200px) {\n  .modal-xl {\n    max-width: 1140px;\n  }\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1070;\n  display: block;\n  margin: 0;\n  font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n  font-style: normal;\n  font-weight: 400;\n  line-height: 1.5;\n  text-align: left;\n  text-align: start;\n  text-decoration: none;\n  text-shadow: none;\n  text-transform: none;\n  letter-spacing: normal;\n  word-break: normal;\n  word-spacing: normal;\n  white-space: normal;\n  line-break: auto;\n  font-size: 0.875rem;\n  word-wrap: break-word;\n  opacity: 0;\n}\n\n.tooltip.show {\n  opacity: 0.9;\n}\n\n.tooltip .arrow {\n  position: absolute;\n  display: block;\n  width: 0.8rem;\n  height: 0.4rem;\n}\n\n.tooltip .arrow::before {\n  position: absolute;\n  content: \"\";\n  border-color: transparent;\n  border-style: solid;\n}\n\n.bs-tooltip-top, .bs-tooltip-auto[x-placement^=\"top\"] {\n  padding: 0.4rem 0;\n}\n\n.bs-tooltip-top .arrow, .bs-tooltip-auto[x-placement^=\"top\"] .arrow {\n  bottom: 0;\n}\n\n.bs-tooltip-top .arrow::before, .bs-tooltip-auto[x-placement^=\"top\"] .arrow::before {\n  top: 0;\n  border-width: 0.4rem 0.4rem 0;\n  border-top-color: #000;\n}\n\n.bs-tooltip-right, .bs-tooltip-auto[x-placement^=\"right\"] {\n  padding: 0 0.4rem;\n}\n\n.bs-tooltip-right .arrow, .bs-tooltip-auto[x-placement^=\"right\"] .arrow {\n  left: 0;\n  width: 0.4rem;\n  height: 0.8rem;\n}\n\n.bs-tooltip-right .arrow::before, .bs-tooltip-auto[x-placement^=\"right\"] .arrow::before {\n  right: 0;\n  border-width: 0.4rem 0.4rem 0.4rem 0;\n  border-right-color: #000;\n}\n\n.bs-tooltip-bottom, .bs-tooltip-auto[x-placement^=\"bottom\"] {\n  padding: 0.4rem 0;\n}\n\n.bs-tooltip-bottom .arrow, .bs-tooltip-auto[x-placement^=\"bottom\"] .arrow {\n  top: 0;\n}\n\n.bs-tooltip-bottom .arrow::before, .bs-tooltip-auto[x-placement^=\"bottom\"] .arrow::before {\n  bottom: 0;\n  border-width: 0 0.4rem 0.4rem;\n  border-bottom-color: #000;\n}\n\n.bs-tooltip-left, .bs-tooltip-auto[x-placement^=\"left\"] {\n  padding: 0 0.4rem;\n}\n\n.bs-tooltip-left .arrow, .bs-tooltip-auto[x-placement^=\"left\"] .arrow {\n  right: 0;\n  width: 0.4rem;\n  height: 0.8rem;\n}\n\n.bs-tooltip-left .arrow::before, .bs-tooltip-auto[x-placement^=\"left\"] .arrow::before {\n  left: 0;\n  border-width: 0.4rem 0 0.4rem 0.4rem;\n  border-left-color: #000;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 0.25rem 0.5rem;\n  color: #fff;\n  text-align: center;\n  background-color: #000;\n  border-radius: 0.25rem;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1060;\n  display: block;\n  max-width: 276px;\n  font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n  font-style: normal;\n  font-weight: 400;\n  line-height: 1.5;\n  text-align: left;\n  text-align: start;\n  text-decoration: none;\n  text-shadow: none;\n  text-transform: none;\n  letter-spacing: normal;\n  word-break: normal;\n  word-spacing: normal;\n  white-space: normal;\n  line-break: auto;\n  font-size: 0.875rem;\n  word-wrap: break-word;\n  background-color: #fff;\n  background-clip: padding-box;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  border-radius: 0.3rem;\n}\n\n.popover .arrow {\n  position: absolute;\n  display: block;\n  width: 1rem;\n  height: 0.5rem;\n  margin: 0 0.3rem;\n}\n\n.popover .arrow::before, .popover .arrow::after {\n  position: absolute;\n  display: block;\n  content: \"\";\n  border-color: transparent;\n  border-style: solid;\n}\n\n.bs-popover-top, .bs-popover-auto[x-placement^=\"top\"] {\n  margin-bottom: 0.5rem;\n}\n\n.bs-popover-top > .arrow, .bs-popover-auto[x-placement^=\"top\"] > .arrow {\n  bottom: calc(-0.5rem - 1px);\n}\n\n.bs-popover-top > .arrow::before, .bs-popover-auto[x-placement^=\"top\"] > .arrow::before {\n  bottom: 0;\n  border-width: 0.5rem 0.5rem 0;\n  border-top-color: rgba(0, 0, 0, 0.25);\n}\n\n.bs-popover-top > .arrow::after, .bs-popover-auto[x-placement^=\"top\"] > .arrow::after {\n  bottom: 1px;\n  border-width: 0.5rem 0.5rem 0;\n  border-top-color: #fff;\n}\n\n.bs-popover-right, .bs-popover-auto[x-placement^=\"right\"] {\n  margin-left: 0.5rem;\n}\n\n.bs-popover-right > .arrow, .bs-popover-auto[x-placement^=\"right\"] > .arrow {\n  left: calc(-0.5rem - 1px);\n  width: 0.5rem;\n  height: 1rem;\n  margin: 0.3rem 0;\n}\n\n.bs-popover-right > .arrow::before, .bs-popover-auto[x-placement^=\"right\"] > .arrow::before {\n  left: 0;\n  border-width: 0.5rem 0.5rem 0.5rem 0;\n  border-right-color: rgba(0, 0, 0, 0.25);\n}\n\n.bs-popover-right > .arrow::after, .bs-popover-auto[x-placement^=\"right\"] > .arrow::after {\n  left: 1px;\n  border-width: 0.5rem 0.5rem 0.5rem 0;\n  border-right-color: #fff;\n}\n\n.bs-popover-bottom, .bs-popover-auto[x-placement^=\"bottom\"] {\n  margin-top: 0.5rem;\n}\n\n.bs-popover-bottom > .arrow, .bs-popover-auto[x-placement^=\"bottom\"] > .arrow {\n  top: calc(-0.5rem - 1px);\n}\n\n.bs-popover-bottom > .arrow::before, .bs-popover-auto[x-placement^=\"bottom\"] > .arrow::before {\n  top: 0;\n  border-width: 0 0.5rem 0.5rem 0.5rem;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n}\n\n.bs-popover-bottom > .arrow::after, .bs-popover-auto[x-placement^=\"bottom\"] > .arrow::after {\n  top: 1px;\n  border-width: 0 0.5rem 0.5rem 0.5rem;\n  border-bottom-color: #fff;\n}\n\n.bs-popover-bottom .popover-header::before, .bs-popover-auto[x-placement^=\"bottom\"] .popover-header::before {\n  position: absolute;\n  top: 0;\n  left: 50%;\n  display: block;\n  width: 1rem;\n  margin-left: -0.5rem;\n  content: \"\";\n  border-bottom: 1px solid #f7f7f7;\n}\n\n.bs-popover-left, .bs-popover-auto[x-placement^=\"left\"] {\n  margin-right: 0.5rem;\n}\n\n.bs-popover-left > .arrow, .bs-popover-auto[x-placement^=\"left\"] > .arrow {\n  right: calc(-0.5rem - 1px);\n  width: 0.5rem;\n  height: 1rem;\n  margin: 0.3rem 0;\n}\n\n.bs-popover-left > .arrow::before, .bs-popover-auto[x-placement^=\"left\"] > .arrow::before {\n  right: 0;\n  border-width: 0.5rem 0 0.5rem 0.5rem;\n  border-left-color: rgba(0, 0, 0, 0.25);\n}\n\n.bs-popover-left > .arrow::after, .bs-popover-auto[x-placement^=\"left\"] > .arrow::after {\n  right: 1px;\n  border-width: 0.5rem 0 0.5rem 0.5rem;\n  border-left-color: #fff;\n}\n\n.popover-header {\n  padding: 0.5rem 0.75rem;\n  margin-bottom: 0;\n  font-size: 1rem;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  border-top-left-radius: calc(0.3rem - 1px);\n  border-top-right-radius: calc(0.3rem - 1px);\n}\n\n.popover-header:empty {\n  display: none;\n}\n\n.popover-body {\n  padding: 0.5rem 0.75rem;\n  color: #212529;\n}\n\n.carousel {\n  position: relative;\n}\n\n.carousel.pointer-event {\n  -ms-touch-action: pan-y;\n  touch-action: pan-y;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner::after {\n  display: block;\n  clear: both;\n  content: \"\";\n}\n\n.carousel-item {\n  position: relative;\n  display: none;\n  float: left;\n  width: 100%;\n  margin-right: -100%;\n  -webkit-backface-visibility: hidden;\n  backface-visibility: hidden;\n  transition: -webkit-transform 0.6s ease-in-out;\n  transition: transform 0.6s ease-in-out;\n  transition: transform 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out;\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .carousel-item {\n    transition: none;\n  }\n}\n\n.carousel-item.active,\n.carousel-item-next,\n.carousel-item-prev {\n  display: block;\n}\n\n.carousel-item-next:not(.carousel-item-left),\n.active.carousel-item-right {\n  -webkit-transform: translateX(100%);\n  transform: translateX(100%);\n}\n\n.carousel-item-prev:not(.carousel-item-right),\n.active.carousel-item-left {\n  -webkit-transform: translateX(-100%);\n  transform: translateX(-100%);\n}\n\n.carousel-fade .carousel-item {\n  opacity: 0;\n  transition-property: opacity;\n  -webkit-transform: none;\n  transform: none;\n}\n\n.carousel-fade .carousel-item.active,\n.carousel-fade .carousel-item-next.carousel-item-left,\n.carousel-fade .carousel-item-prev.carousel-item-right {\n  z-index: 1;\n  opacity: 1;\n}\n\n.carousel-fade .active.carousel-item-left,\n.carousel-fade .active.carousel-item-right {\n  z-index: 0;\n  opacity: 0;\n  transition: opacity 0s 0.6s;\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .carousel-fade .active.carousel-item-left,\n  .carousel-fade .active.carousel-item-right {\n    transition: none;\n  }\n}\n\n.carousel-control-prev,\n.carousel-control-next {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  z-index: 1;\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-align: center;\n  align-items: center;\n  -ms-flex-pack: center;\n  justify-content: center;\n  width: 15%;\n  color: #fff;\n  text-align: center;\n  opacity: 0.5;\n  transition: opacity 0.15s ease;\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .carousel-control-prev,\n  .carousel-control-next {\n    transition: none;\n  }\n}\n\n.carousel-control-prev:hover, .carousel-control-prev:focus,\n.carousel-control-next:hover,\n.carousel-control-next:focus {\n  color: #fff;\n  text-decoration: none;\n  outline: 0;\n  opacity: 0.9;\n}\n\n.carousel-control-prev {\n  left: 0;\n}\n\n.carousel-control-next {\n  right: 0;\n}\n\n.carousel-control-prev-icon,\n.carousel-control-next-icon {\n  display: inline-block;\n  width: 20px;\n  height: 20px;\n  background: no-repeat 50% / 100% 100%;\n}\n\n.carousel-control-prev-icon {\n  background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3e%3c/svg%3e\");\n}\n\n.carousel-control-next-icon {\n  background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3e%3c/svg%3e\");\n}\n\n.carousel-indicators {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 15;\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-pack: center;\n  justify-content: center;\n  padding-left: 0;\n  margin-right: 15%;\n  margin-left: 15%;\n  list-style: none;\n}\n\n.carousel-indicators li {\n  box-sizing: content-box;\n  -ms-flex: 0 1 auto;\n  flex: 0 1 auto;\n  width: 30px;\n  height: 3px;\n  margin-right: 3px;\n  margin-left: 3px;\n  text-indent: -999px;\n  cursor: pointer;\n  background-color: #fff;\n  background-clip: padding-box;\n  border-top: 10px solid transparent;\n  border-bottom: 10px solid transparent;\n  opacity: .5;\n  transition: opacity 0.6s ease;\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .carousel-indicators li {\n    transition: none;\n  }\n}\n\n.carousel-indicators .active {\n  opacity: 1;\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 15%;\n  bottom: 20px;\n  left: 15%;\n  z-index: 10;\n  padding-top: 20px;\n  padding-bottom: 20px;\n  color: #fff;\n  text-align: center;\n}\n\n@-webkit-keyframes spinner-border {\n  to {\n    -webkit-transform: rotate(360deg);\n    transform: rotate(360deg);\n  }\n}\n\n@keyframes spinner-border {\n  to {\n    -webkit-transform: rotate(360deg);\n    transform: rotate(360deg);\n  }\n}\n\n.spinner-border {\n  display: inline-block;\n  width: 2rem;\n  height: 2rem;\n  vertical-align: text-bottom;\n  border: 0.25em solid currentColor;\n  border-right-color: transparent;\n  border-radius: 50%;\n  -webkit-animation: spinner-border .75s linear infinite;\n  animation: spinner-border .75s linear infinite;\n}\n\n.spinner-border-sm {\n  width: 1rem;\n  height: 1rem;\n  border-width: 0.2em;\n}\n\n@-webkit-keyframes spinner-grow {\n  0% {\n    -webkit-transform: scale(0);\n    transform: scale(0);\n  }\n  50% {\n    opacity: 1;\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n@keyframes spinner-grow {\n  0% {\n    -webkit-transform: scale(0);\n    transform: scale(0);\n  }\n  50% {\n    opacity: 1;\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n.spinner-grow {\n  display: inline-block;\n  width: 2rem;\n  height: 2rem;\n  vertical-align: text-bottom;\n  background-color: currentColor;\n  border-radius: 50%;\n  opacity: 0;\n  -webkit-animation: spinner-grow .75s linear infinite;\n  animation: spinner-grow .75s linear infinite;\n}\n\n.spinner-grow-sm {\n  width: 1rem;\n  height: 1rem;\n}\n\n.align-baseline {\n  vertical-align: baseline !important;\n}\n\n.align-top {\n  vertical-align: top !important;\n}\n\n.align-middle {\n  vertical-align: middle !important;\n}\n\n.align-bottom {\n  vertical-align: bottom !important;\n}\n\n.align-text-bottom {\n  vertical-align: text-bottom !important;\n}\n\n.align-text-top {\n  vertical-align: text-top !important;\n}\n\n.bg-primary {\n  background-color: #007bff !important;\n}\n\na.bg-primary:hover, a.bg-primary:focus,\nbutton.bg-primary:hover,\nbutton.bg-primary:focus {\n  background-color: #0062cc !important;\n}\n\n.bg-secondary {\n  background-color: #6c757d !important;\n}\n\na.bg-secondary:hover, a.bg-secondary:focus,\nbutton.bg-secondary:hover,\nbutton.bg-secondary:focus {\n  background-color: #545b62 !important;\n}\n\n.bg-success {\n  background-color: #28a745 !important;\n}\n\na.bg-success:hover, a.bg-success:focus,\nbutton.bg-success:hover,\nbutton.bg-success:focus {\n  background-color: #1e7e34 !important;\n}\n\n.bg-info {\n  background-color: #17a2b8 !important;\n}\n\na.bg-info:hover, a.bg-info:focus,\nbutton.bg-info:hover,\nbutton.bg-info:focus {\n  background-color: #117a8b !important;\n}\n\n.bg-warning {\n  background-color: #ffc107 !important;\n}\n\na.bg-warning:hover, a.bg-warning:focus,\nbutton.bg-warning:hover,\nbutton.bg-warning:focus {\n  background-color: #d39e00 !important;\n}\n\n.bg-danger {\n  background-color: #dc3545 !important;\n}\n\na.bg-danger:hover, a.bg-danger:focus,\nbutton.bg-danger:hover,\nbutton.bg-danger:focus {\n  background-color: #bd2130 !important;\n}\n\n.bg-light {\n  background-color: #f8f9fa !important;\n}\n\na.bg-light:hover, a.bg-light:focus,\nbutton.bg-light:hover,\nbutton.bg-light:focus {\n  background-color: #dae0e5 !important;\n}\n\n.bg-dark {\n  background-color: #343a40 !important;\n}\n\na.bg-dark:hover, a.bg-dark:focus,\nbutton.bg-dark:hover,\nbutton.bg-dark:focus {\n  background-color: #1d2124 !important;\n}\n\n.bg-white {\n  background-color: #fff !important;\n}\n\n.bg-transparent {\n  background-color: transparent !important;\n}\n\n.border {\n  border: 1px solid #dee2e6 !important;\n}\n\n.border-top {\n  border-top: 1px solid #dee2e6 !important;\n}\n\n.border-right {\n  border-right: 1px solid #dee2e6 !important;\n}\n\n.border-bottom {\n  border-bottom: 1px solid #dee2e6 !important;\n}\n\n.border-left {\n  border-left: 1px solid #dee2e6 !important;\n}\n\n.border-0 {\n  border: 0 !important;\n}\n\n.border-top-0 {\n  border-top: 0 !important;\n}\n\n.border-right-0 {\n  border-right: 0 !important;\n}\n\n.border-bottom-0 {\n  border-bottom: 0 !important;\n}\n\n.border-left-0 {\n  border-left: 0 !important;\n}\n\n.border-primary {\n  border-color: #007bff !important;\n}\n\n.border-secondary {\n  border-color: #6c757d !important;\n}\n\n.border-success {\n  border-color: #28a745 !important;\n}\n\n.border-info {\n  border-color: #17a2b8 !important;\n}\n\n.border-warning {\n  border-color: #ffc107 !important;\n}\n\n.border-danger {\n  border-color: #dc3545 !important;\n}\n\n.border-light {\n  border-color: #f8f9fa !important;\n}\n\n.border-dark {\n  border-color: #343a40 !important;\n}\n\n.border-white {\n  border-color: #fff !important;\n}\n\n.rounded-sm {\n  border-radius: 0.2rem !important;\n}\n\n.rounded {\n  border-radius: 0.25rem !important;\n}\n\n.rounded-top {\n  border-top-left-radius: 0.25rem !important;\n  border-top-right-radius: 0.25rem !important;\n}\n\n.rounded-right {\n  border-top-right-radius: 0.25rem !important;\n  border-bottom-right-radius: 0.25rem !important;\n}\n\n.rounded-bottom {\n  border-bottom-right-radius: 0.25rem !important;\n  border-bottom-left-radius: 0.25rem !important;\n}\n\n.rounded-left {\n  border-top-left-radius: 0.25rem !important;\n  border-bottom-left-radius: 0.25rem !important;\n}\n\n.rounded-lg {\n  border-radius: 0.3rem !important;\n}\n\n.rounded-circle {\n  border-radius: 50% !important;\n}\n\n.rounded-pill {\n  border-radius: 50rem !important;\n}\n\n.rounded-0 {\n  border-radius: 0 !important;\n}\n\n.clearfix::after {\n  display: block;\n  clear: both;\n  content: \"\";\n}\n\n.d-none {\n  display: none !important;\n}\n\n.d-inline {\n  display: inline !important;\n}\n\n.d-inline-block {\n  display: inline-block !important;\n}\n\n.d-block {\n  display: block !important;\n}\n\n.d-table {\n  display: table !important;\n}\n\n.d-table-row {\n  display: table-row !important;\n}\n\n.d-table-cell {\n  display: table-cell !important;\n}\n\n.d-flex {\n  display: -ms-flexbox !important;\n  display: flex !important;\n}\n\n.d-inline-flex {\n  display: -ms-inline-flexbox !important;\n  display: inline-flex !important;\n}\n\n@media (min-width: 576px) {\n  .d-sm-none {\n    display: none !important;\n  }\n  .d-sm-inline {\n    display: inline !important;\n  }\n  .d-sm-inline-block {\n    display: inline-block !important;\n  }\n  .d-sm-block {\n    display: block !important;\n  }\n  .d-sm-table {\n    display: table !important;\n  }\n  .d-sm-table-row {\n    display: table-row !important;\n  }\n  .d-sm-table-cell {\n    display: table-cell !important;\n  }\n  .d-sm-flex {\n    display: -ms-flexbox !important;\n    display: flex !important;\n  }\n  .d-sm-inline-flex {\n    display: -ms-inline-flexbox !important;\n    display: inline-flex !important;\n  }\n}\n\n@media (min-width: 768px) {\n  .d-md-none {\n    display: none !important;\n  }\n  .d-md-inline {\n    display: inline !important;\n  }\n  .d-md-inline-block {\n    display: inline-block !important;\n  }\n  .d-md-block {\n    display: block !important;\n  }\n  .d-md-table {\n    display: table !important;\n  }\n  .d-md-table-row {\n    display: table-row !important;\n  }\n  .d-md-table-cell {\n    display: table-cell !important;\n  }\n  .d-md-flex {\n    display: -ms-flexbox !important;\n    display: flex !important;\n  }\n  .d-md-inline-flex {\n    display: -ms-inline-flexbox !important;\n    display: inline-flex !important;\n  }\n}\n\n@media (min-width: 992px) {\n  .d-lg-none {\n    display: none !important;\n  }\n  .d-lg-inline {\n    display: inline !important;\n  }\n  .d-lg-inline-block {\n    display: inline-block !important;\n  }\n  .d-lg-block {\n    display: block !important;\n  }\n  .d-lg-table {\n    display: table !important;\n  }\n  .d-lg-table-row {\n    display: table-row !important;\n  }\n  .d-lg-table-cell {\n    display: table-cell !important;\n  }\n  .d-lg-flex {\n    display: -ms-flexbox !important;\n    display: flex !important;\n  }\n  .d-lg-inline-flex {\n    display: -ms-inline-flexbox !important;\n    display: inline-flex !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .d-xl-none {\n    display: none !important;\n  }\n  .d-xl-inline {\n    display: inline !important;\n  }\n  .d-xl-inline-block {\n    display: inline-block !important;\n  }\n  .d-xl-block {\n    display: block !important;\n  }\n  .d-xl-table {\n    display: table !important;\n  }\n  .d-xl-table-row {\n    display: table-row !important;\n  }\n  .d-xl-table-cell {\n    display: table-cell !important;\n  }\n  .d-xl-flex {\n    display: -ms-flexbox !important;\n    display: flex !important;\n  }\n  .d-xl-inline-flex {\n    display: -ms-inline-flexbox !important;\n    display: inline-flex !important;\n  }\n}\n\n@media print {\n  .d-print-none {\n    display: none !important;\n  }\n  .d-print-inline {\n    display: inline !important;\n  }\n  .d-print-inline-block {\n    display: inline-block !important;\n  }\n  .d-print-block {\n    display: block !important;\n  }\n  .d-print-table {\n    display: table !important;\n  }\n  .d-print-table-row {\n    display: table-row !important;\n  }\n  .d-print-table-cell {\n    display: table-cell !important;\n  }\n  .d-print-flex {\n    display: -ms-flexbox !important;\n    display: flex !important;\n  }\n  .d-print-inline-flex {\n    display: -ms-inline-flexbox !important;\n    display: inline-flex !important;\n  }\n}\n\n.embed-responsive {\n  position: relative;\n  display: block;\n  width: 100%;\n  padding: 0;\n  overflow: hidden;\n}\n\n.embed-responsive::before {\n  display: block;\n  content: \"\";\n}\n\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  border: 0;\n}\n\n.embed-responsive-21by9::before {\n  padding-top: 42.857143%;\n}\n\n.embed-responsive-16by9::before {\n  padding-top: 56.25%;\n}\n\n.embed-responsive-4by3::before {\n  padding-top: 75%;\n}\n\n.embed-responsive-1by1::before {\n  padding-top: 100%;\n}\n\n.flex-row {\n  -ms-flex-direction: row !important;\n  flex-direction: row !important;\n}\n\n.flex-column {\n  -ms-flex-direction: column !important;\n  flex-direction: column !important;\n}\n\n.flex-row-reverse {\n  -ms-flex-direction: row-reverse !important;\n  flex-direction: row-reverse !important;\n}\n\n.flex-column-reverse {\n  -ms-flex-direction: column-reverse !important;\n  flex-direction: column-reverse !important;\n}\n\n.flex-wrap {\n  -ms-flex-wrap: wrap !important;\n  flex-wrap: wrap !important;\n}\n\n.flex-nowrap {\n  -ms-flex-wrap: nowrap !important;\n  flex-wrap: nowrap !important;\n}\n\n.flex-wrap-reverse {\n  -ms-flex-wrap: wrap-reverse !important;\n  flex-wrap: wrap-reverse !important;\n}\n\n.flex-fill {\n  -ms-flex: 1 1 auto !important;\n  flex: 1 1 auto !important;\n}\n\n.flex-grow-0 {\n  -ms-flex-positive: 0 !important;\n  flex-grow: 0 !important;\n}\n\n.flex-grow-1 {\n  -ms-flex-positive: 1 !important;\n  flex-grow: 1 !important;\n}\n\n.flex-shrink-0 {\n  -ms-flex-negative: 0 !important;\n  flex-shrink: 0 !important;\n}\n\n.flex-shrink-1 {\n  -ms-flex-negative: 1 !important;\n  flex-shrink: 1 !important;\n}\n\n.justify-content-start {\n  -ms-flex-pack: start !important;\n  justify-content: flex-start !important;\n}\n\n.justify-content-end {\n  -ms-flex-pack: end !important;\n  justify-content: flex-end !important;\n}\n\n.justify-content-center {\n  -ms-flex-pack: center !important;\n  justify-content: center !important;\n}\n\n.justify-content-between {\n  -ms-flex-pack: justify !important;\n  justify-content: space-between !important;\n}\n\n.justify-content-around {\n  -ms-flex-pack: distribute !important;\n  justify-content: space-around !important;\n}\n\n.align-items-start {\n  -ms-flex-align: start !important;\n  align-items: flex-start !important;\n}\n\n.align-items-end {\n  -ms-flex-align: end !important;\n  align-items: flex-end !important;\n}\n\n.align-items-center {\n  -ms-flex-align: center !important;\n  align-items: center !important;\n}\n\n.align-items-baseline {\n  -ms-flex-align: baseline !important;\n  align-items: baseline !important;\n}\n\n.align-items-stretch {\n  -ms-flex-align: stretch !important;\n  align-items: stretch !important;\n}\n\n.align-content-start {\n  -ms-flex-line-pack: start !important;\n  align-content: flex-start !important;\n}\n\n.align-content-end {\n  -ms-flex-line-pack: end !important;\n  align-content: flex-end !important;\n}\n\n.align-content-center {\n  -ms-flex-line-pack: center !important;\n  align-content: center !important;\n}\n\n.align-content-between {\n  -ms-flex-line-pack: justify !important;\n  align-content: space-between !important;\n}\n\n.align-content-around {\n  -ms-flex-line-pack: distribute !important;\n  align-content: space-around !important;\n}\n\n.align-content-stretch {\n  -ms-flex-line-pack: stretch !important;\n  align-content: stretch !important;\n}\n\n.align-self-auto {\n  -ms-flex-item-align: auto !important;\n  align-self: auto !important;\n}\n\n.align-self-start {\n  -ms-flex-item-align: start !important;\n  align-self: flex-start !important;\n}\n\n.align-self-end {\n  -ms-flex-item-align: end !important;\n  align-self: flex-end !important;\n}\n\n.align-self-center {\n  -ms-flex-item-align: center !important;\n  align-self: center !important;\n}\n\n.align-self-baseline {\n  -ms-flex-item-align: baseline !important;\n  align-self: baseline !important;\n}\n\n.align-self-stretch {\n  -ms-flex-item-align: stretch !important;\n  align-self: stretch !important;\n}\n\n@media (min-width: 576px) {\n  .flex-sm-row {\n    -ms-flex-direction: row !important;\n    flex-direction: row !important;\n  }\n  .flex-sm-column {\n    -ms-flex-direction: column !important;\n    flex-direction: column !important;\n  }\n  .flex-sm-row-reverse {\n    -ms-flex-direction: row-reverse !important;\n    flex-direction: row-reverse !important;\n  }\n  .flex-sm-column-reverse {\n    -ms-flex-direction: column-reverse !important;\n    flex-direction: column-reverse !important;\n  }\n  .flex-sm-wrap {\n    -ms-flex-wrap: wrap !important;\n    flex-wrap: wrap !important;\n  }\n  .flex-sm-nowrap {\n    -ms-flex-wrap: nowrap !important;\n    flex-wrap: nowrap !important;\n  }\n  .flex-sm-wrap-reverse {\n    -ms-flex-wrap: wrap-reverse !important;\n    flex-wrap: wrap-reverse !important;\n  }\n  .flex-sm-fill {\n    -ms-flex: 1 1 auto !important;\n    flex: 1 1 auto !important;\n  }\n  .flex-sm-grow-0 {\n    -ms-flex-positive: 0 !important;\n    flex-grow: 0 !important;\n  }\n  .flex-sm-grow-1 {\n    -ms-flex-positive: 1 !important;\n    flex-grow: 1 !important;\n  }\n  .flex-sm-shrink-0 {\n    -ms-flex-negative: 0 !important;\n    flex-shrink: 0 !important;\n  }\n  .flex-sm-shrink-1 {\n    -ms-flex-negative: 1 !important;\n    flex-shrink: 1 !important;\n  }\n  .justify-content-sm-start {\n    -ms-flex-pack: start !important;\n    justify-content: flex-start !important;\n  }\n  .justify-content-sm-end {\n    -ms-flex-pack: end !important;\n    justify-content: flex-end !important;\n  }\n  .justify-content-sm-center {\n    -ms-flex-pack: center !important;\n    justify-content: center !important;\n  }\n  .justify-content-sm-between {\n    -ms-flex-pack: justify !important;\n    justify-content: space-between !important;\n  }\n  .justify-content-sm-around {\n    -ms-flex-pack: distribute !important;\n    justify-content: space-around !important;\n  }\n  .align-items-sm-start {\n    -ms-flex-align: start !important;\n    align-items: flex-start !important;\n  }\n  .align-items-sm-end {\n    -ms-flex-align: end !important;\n    align-items: flex-end !important;\n  }\n  .align-items-sm-center {\n    -ms-flex-align: center !important;\n    align-items: center !important;\n  }\n  .align-items-sm-baseline {\n    -ms-flex-align: baseline !important;\n    align-items: baseline !important;\n  }\n  .align-items-sm-stretch {\n    -ms-flex-align: stretch !important;\n    align-items: stretch !important;\n  }\n  .align-content-sm-start {\n    -ms-flex-line-pack: start !important;\n    align-content: flex-start !important;\n  }\n  .align-content-sm-end {\n    -ms-flex-line-pack: end !important;\n    align-content: flex-end !important;\n  }\n  .align-content-sm-center {\n    -ms-flex-line-pack: center !important;\n    align-content: center !important;\n  }\n  .align-content-sm-between {\n    -ms-flex-line-pack: justify !important;\n    align-content: space-between !important;\n  }\n  .align-content-sm-around {\n    -ms-flex-line-pack: distribute !important;\n    align-content: space-around !important;\n  }\n  .align-content-sm-stretch {\n    -ms-flex-line-pack: stretch !important;\n    align-content: stretch !important;\n  }\n  .align-self-sm-auto {\n    -ms-flex-item-align: auto !important;\n    align-self: auto !important;\n  }\n  .align-self-sm-start {\n    -ms-flex-item-align: start !important;\n    align-self: flex-start !important;\n  }\n  .align-self-sm-end {\n    -ms-flex-item-align: end !important;\n    align-self: flex-end !important;\n  }\n  .align-self-sm-center {\n    -ms-flex-item-align: center !important;\n    align-self: center !important;\n  }\n  .align-self-sm-baseline {\n    -ms-flex-item-align: baseline !important;\n    align-self: baseline !important;\n  }\n  .align-self-sm-stretch {\n    -ms-flex-item-align: stretch !important;\n    align-self: stretch !important;\n  }\n}\n\n@media (min-width: 768px) {\n  .flex-md-row {\n    -ms-flex-direction: row !important;\n    flex-direction: row !important;\n  }\n  .flex-md-column {\n    -ms-flex-direction: column !important;\n    flex-direction: column !important;\n  }\n  .flex-md-row-reverse {\n    -ms-flex-direction: row-reverse !important;\n    flex-direction: row-reverse !important;\n  }\n  .flex-md-column-reverse {\n    -ms-flex-direction: column-reverse !important;\n    flex-direction: column-reverse !important;\n  }\n  .flex-md-wrap {\n    -ms-flex-wrap: wrap !important;\n    flex-wrap: wrap !important;\n  }\n  .flex-md-nowrap {\n    -ms-flex-wrap: nowrap !important;\n    flex-wrap: nowrap !important;\n  }\n  .flex-md-wrap-reverse {\n    -ms-flex-wrap: wrap-reverse !important;\n    flex-wrap: wrap-reverse !important;\n  }\n  .flex-md-fill {\n    -ms-flex: 1 1 auto !important;\n    flex: 1 1 auto !important;\n  }\n  .flex-md-grow-0 {\n    -ms-flex-positive: 0 !important;\n    flex-grow: 0 !important;\n  }\n  .flex-md-grow-1 {\n    -ms-flex-positive: 1 !important;\n    flex-grow: 1 !important;\n  }\n  .flex-md-shrink-0 {\n    -ms-flex-negative: 0 !important;\n    flex-shrink: 0 !important;\n  }\n  .flex-md-shrink-1 {\n    -ms-flex-negative: 1 !important;\n    flex-shrink: 1 !important;\n  }\n  .justify-content-md-start {\n    -ms-flex-pack: start !important;\n    justify-content: flex-start !important;\n  }\n  .justify-content-md-end {\n    -ms-flex-pack: end !important;\n    justify-content: flex-end !important;\n  }\n  .justify-content-md-center {\n    -ms-flex-pack: center !important;\n    justify-content: center !important;\n  }\n  .justify-content-md-between {\n    -ms-flex-pack: justify !important;\n    justify-content: space-between !important;\n  }\n  .justify-content-md-around {\n    -ms-flex-pack: distribute !important;\n    justify-content: space-around !important;\n  }\n  .align-items-md-start {\n    -ms-flex-align: start !important;\n    align-items: flex-start !important;\n  }\n  .align-items-md-end {\n    -ms-flex-align: end !important;\n    align-items: flex-end !important;\n  }\n  .align-items-md-center {\n    -ms-flex-align: center !important;\n    align-items: center !important;\n  }\n  .align-items-md-baseline {\n    -ms-flex-align: baseline !important;\n    align-items: baseline !important;\n  }\n  .align-items-md-stretch {\n    -ms-flex-align: stretch !important;\n    align-items: stretch !important;\n  }\n  .align-content-md-start {\n    -ms-flex-line-pack: start !important;\n    align-content: flex-start !important;\n  }\n  .align-content-md-end {\n    -ms-flex-line-pack: end !important;\n    align-content: flex-end !important;\n  }\n  .align-content-md-center {\n    -ms-flex-line-pack: center !important;\n    align-content: center !important;\n  }\n  .align-content-md-between {\n    -ms-flex-line-pack: justify !important;\n    align-content: space-between !important;\n  }\n  .align-content-md-around {\n    -ms-flex-line-pack: distribute !important;\n    align-content: space-around !important;\n  }\n  .align-content-md-stretch {\n    -ms-flex-line-pack: stretch !important;\n    align-content: stretch !important;\n  }\n  .align-self-md-auto {\n    -ms-flex-item-align: auto !important;\n    align-self: auto !important;\n  }\n  .align-self-md-start {\n    -ms-flex-item-align: start !important;\n    align-self: flex-start !important;\n  }\n  .align-self-md-end {\n    -ms-flex-item-align: end !important;\n    align-self: flex-end !important;\n  }\n  .align-self-md-center {\n    -ms-flex-item-align: center !important;\n    align-self: center !important;\n  }\n  .align-self-md-baseline {\n    -ms-flex-item-align: baseline !important;\n    align-self: baseline !important;\n  }\n  .align-self-md-stretch {\n    -ms-flex-item-align: stretch !important;\n    align-self: stretch !important;\n  }\n}\n\n@media (min-width: 992px) {\n  .flex-lg-row {\n    -ms-flex-direction: row !important;\n    flex-direction: row !important;\n  }\n  .flex-lg-column {\n    -ms-flex-direction: column !important;\n    flex-direction: column !important;\n  }\n  .flex-lg-row-reverse {\n    -ms-flex-direction: row-reverse !important;\n    flex-direction: row-reverse !important;\n  }\n  .flex-lg-column-reverse {\n    -ms-flex-direction: column-reverse !important;\n    flex-direction: column-reverse !important;\n  }\n  .flex-lg-wrap {\n    -ms-flex-wrap: wrap !important;\n    flex-wrap: wrap !important;\n  }\n  .flex-lg-nowrap {\n    -ms-flex-wrap: nowrap !important;\n    flex-wrap: nowrap !important;\n  }\n  .flex-lg-wrap-reverse {\n    -ms-flex-wrap: wrap-reverse !important;\n    flex-wrap: wrap-reverse !important;\n  }\n  .flex-lg-fill {\n    -ms-flex: 1 1 auto !important;\n    flex: 1 1 auto !important;\n  }\n  .flex-lg-grow-0 {\n    -ms-flex-positive: 0 !important;\n    flex-grow: 0 !important;\n  }\n  .flex-lg-grow-1 {\n    -ms-flex-positive: 1 !important;\n    flex-grow: 1 !important;\n  }\n  .flex-lg-shrink-0 {\n    -ms-flex-negative: 0 !important;\n    flex-shrink: 0 !important;\n  }\n  .flex-lg-shrink-1 {\n    -ms-flex-negative: 1 !important;\n    flex-shrink: 1 !important;\n  }\n  .justify-content-lg-start {\n    -ms-flex-pack: start !important;\n    justify-content: flex-start !important;\n  }\n  .justify-content-lg-end {\n    -ms-flex-pack: end !important;\n    justify-content: flex-end !important;\n  }\n  .justify-content-lg-center {\n    -ms-flex-pack: center !important;\n    justify-content: center !important;\n  }\n  .justify-content-lg-between {\n    -ms-flex-pack: justify !important;\n    justify-content: space-between !important;\n  }\n  .justify-content-lg-around {\n    -ms-flex-pack: distribute !important;\n    justify-content: space-around !important;\n  }\n  .align-items-lg-start {\n    -ms-flex-align: start !important;\n    align-items: flex-start !important;\n  }\n  .align-items-lg-end {\n    -ms-flex-align: end !important;\n    align-items: flex-end !important;\n  }\n  .align-items-lg-center {\n    -ms-flex-align: center !important;\n    align-items: center !important;\n  }\n  .align-items-lg-baseline {\n    -ms-flex-align: baseline !important;\n    align-items: baseline !important;\n  }\n  .align-items-lg-stretch {\n    -ms-flex-align: stretch !important;\n    align-items: stretch !important;\n  }\n  .align-content-lg-start {\n    -ms-flex-line-pack: start !important;\n    align-content: flex-start !important;\n  }\n  .align-content-lg-end {\n    -ms-flex-line-pack: end !important;\n    align-content: flex-end !important;\n  }\n  .align-content-lg-center {\n    -ms-flex-line-pack: center !important;\n    align-content: center !important;\n  }\n  .align-content-lg-between {\n    -ms-flex-line-pack: justify !important;\n    align-content: space-between !important;\n  }\n  .align-content-lg-around {\n    -ms-flex-line-pack: distribute !important;\n    align-content: space-around !important;\n  }\n  .align-content-lg-stretch {\n    -ms-flex-line-pack: stretch !important;\n    align-content: stretch !important;\n  }\n  .align-self-lg-auto {\n    -ms-flex-item-align: auto !important;\n    align-self: auto !important;\n  }\n  .align-self-lg-start {\n    -ms-flex-item-align: start !important;\n    align-self: flex-start !important;\n  }\n  .align-self-lg-end {\n    -ms-flex-item-align: end !important;\n    align-self: flex-end !important;\n  }\n  .align-self-lg-center {\n    -ms-flex-item-align: center !important;\n    align-self: center !important;\n  }\n  .align-self-lg-baseline {\n    -ms-flex-item-align: baseline !important;\n    align-self: baseline !important;\n  }\n  .align-self-lg-stretch {\n    -ms-flex-item-align: stretch !important;\n    align-self: stretch !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .flex-xl-row {\n    -ms-flex-direction: row !important;\n    flex-direction: row !important;\n  }\n  .flex-xl-column {\n    -ms-flex-direction: column !important;\n    flex-direction: column !important;\n  }\n  .flex-xl-row-reverse {\n    -ms-flex-direction: row-reverse !important;\n    flex-direction: row-reverse !important;\n  }\n  .flex-xl-column-reverse {\n    -ms-flex-direction: column-reverse !important;\n    flex-direction: column-reverse !important;\n  }\n  .flex-xl-wrap {\n    -ms-flex-wrap: wrap !important;\n    flex-wrap: wrap !important;\n  }\n  .flex-xl-nowrap {\n    -ms-flex-wrap: nowrap !important;\n    flex-wrap: nowrap !important;\n  }\n  .flex-xl-wrap-reverse {\n    -ms-flex-wrap: wrap-reverse !important;\n    flex-wrap: wrap-reverse !important;\n  }\n  .flex-xl-fill {\n    -ms-flex: 1 1 auto !important;\n    flex: 1 1 auto !important;\n  }\n  .flex-xl-grow-0 {\n    -ms-flex-positive: 0 !important;\n    flex-grow: 0 !important;\n  }\n  .flex-xl-grow-1 {\n    -ms-flex-positive: 1 !important;\n    flex-grow: 1 !important;\n  }\n  .flex-xl-shrink-0 {\n    -ms-flex-negative: 0 !important;\n    flex-shrink: 0 !important;\n  }\n  .flex-xl-shrink-1 {\n    -ms-flex-negative: 1 !important;\n    flex-shrink: 1 !important;\n  }\n  .justify-content-xl-start {\n    -ms-flex-pack: start !important;\n    justify-content: flex-start !important;\n  }\n  .justify-content-xl-end {\n    -ms-flex-pack: end !important;\n    justify-content: flex-end !important;\n  }\n  .justify-content-xl-center {\n    -ms-flex-pack: center !important;\n    justify-content: center !important;\n  }\n  .justify-content-xl-between {\n    -ms-flex-pack: justify !important;\n    justify-content: space-between !important;\n  }\n  .justify-content-xl-around {\n    -ms-flex-pack: distribute !important;\n    justify-content: space-around !important;\n  }\n  .align-items-xl-start {\n    -ms-flex-align: start !important;\n    align-items: flex-start !important;\n  }\n  .align-items-xl-end {\n    -ms-flex-align: end !important;\n    align-items: flex-end !important;\n  }\n  .align-items-xl-center {\n    -ms-flex-align: center !important;\n    align-items: center !important;\n  }\n  .align-items-xl-baseline {\n    -ms-flex-align: baseline !important;\n    align-items: baseline !important;\n  }\n  .align-items-xl-stretch {\n    -ms-flex-align: stretch !important;\n    align-items: stretch !important;\n  }\n  .align-content-xl-start {\n    -ms-flex-line-pack: start !important;\n    align-content: flex-start !important;\n  }\n  .align-content-xl-end {\n    -ms-flex-line-pack: end !important;\n    align-content: flex-end !important;\n  }\n  .align-content-xl-center {\n    -ms-flex-line-pack: center !important;\n    align-content: center !important;\n  }\n  .align-content-xl-between {\n    -ms-flex-line-pack: justify !important;\n    align-content: space-between !important;\n  }\n  .align-content-xl-around {\n    -ms-flex-line-pack: distribute !important;\n    align-content: space-around !important;\n  }\n  .align-content-xl-stretch {\n    -ms-flex-line-pack: stretch !important;\n    align-content: stretch !important;\n  }\n  .align-self-xl-auto {\n    -ms-flex-item-align: auto !important;\n    align-self: auto !important;\n  }\n  .align-self-xl-start {\n    -ms-flex-item-align: start !important;\n    align-self: flex-start !important;\n  }\n  .align-self-xl-end {\n    -ms-flex-item-align: end !important;\n    align-self: flex-end !important;\n  }\n  .align-self-xl-center {\n    -ms-flex-item-align: center !important;\n    align-self: center !important;\n  }\n  .align-self-xl-baseline {\n    -ms-flex-item-align: baseline !important;\n    align-self: baseline !important;\n  }\n  .align-self-xl-stretch {\n    -ms-flex-item-align: stretch !important;\n    align-self: stretch !important;\n  }\n}\n\n.float-left {\n  float: left !important;\n}\n\n.float-right {\n  float: right !important;\n}\n\n.float-none {\n  float: none !important;\n}\n\n@media (min-width: 576px) {\n  .float-sm-left {\n    float: left !important;\n  }\n  .float-sm-right {\n    float: right !important;\n  }\n  .float-sm-none {\n    float: none !important;\n  }\n}\n\n@media (min-width: 768px) {\n  .float-md-left {\n    float: left !important;\n  }\n  .float-md-right {\n    float: right !important;\n  }\n  .float-md-none {\n    float: none !important;\n  }\n}\n\n@media (min-width: 992px) {\n  .float-lg-left {\n    float: left !important;\n  }\n  .float-lg-right {\n    float: right !important;\n  }\n  .float-lg-none {\n    float: none !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .float-xl-left {\n    float: left !important;\n  }\n  .float-xl-right {\n    float: right !important;\n  }\n  .float-xl-none {\n    float: none !important;\n  }\n}\n\n.user-select-all {\n  -webkit-user-select: all !important;\n  -moz-user-select: all !important;\n  -ms-user-select: all !important;\n  user-select: all !important;\n}\n\n.user-select-auto {\n  -webkit-user-select: auto !important;\n  -moz-user-select: auto !important;\n  -ms-user-select: auto !important;\n  user-select: auto !important;\n}\n\n.user-select-none {\n  -webkit-user-select: none !important;\n  -moz-user-select: none !important;\n  -ms-user-select: none !important;\n  user-select: none !important;\n}\n\n.overflow-auto {\n  overflow: auto !important;\n}\n\n.overflow-hidden {\n  overflow: hidden !important;\n}\n\n.position-static {\n  position: static !important;\n}\n\n.position-relative {\n  position: relative !important;\n}\n\n.position-absolute {\n  position: absolute !important;\n}\n\n.position-fixed {\n  position: fixed !important;\n}\n\n.position-sticky {\n  position: -webkit-sticky !important;\n  position: sticky !important;\n}\n\n.fixed-top {\n  position: fixed;\n  top: 0;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n}\n\n.fixed-bottom {\n  position: fixed;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1030;\n}\n\n@supports ((position: -webkit-sticky) or (position: sticky)) {\n  .sticky-top {\n    position: -webkit-sticky;\n    position: sticky;\n    top: 0;\n    z-index: 1020;\n  }\n}\n\n.sr-only {\n  position: absolute;\n  width: 1px;\n  height: 1px;\n  padding: 0;\n  margin: -1px;\n  overflow: hidden;\n  clip: rect(0, 0, 0, 0);\n  white-space: nowrap;\n  border: 0;\n}\n\n.sr-only-focusable:active, .sr-only-focusable:focus {\n  position: static;\n  width: auto;\n  height: auto;\n  overflow: visible;\n  clip: auto;\n  white-space: normal;\n}\n\n.shadow-sm {\n  box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important;\n}\n\n.shadow {\n  box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important;\n}\n\n.shadow-lg {\n  box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important;\n}\n\n.shadow-none {\n  box-shadow: none !important;\n}\n\n.w-25 {\n  width: 25% !important;\n}\n\n.w-50 {\n  width: 50% !important;\n}\n\n.w-75 {\n  width: 75% !important;\n}\n\n.w-100 {\n  width: 100% !important;\n}\n\n.w-auto {\n  width: auto !important;\n}\n\n.h-25 {\n  height: 25% !important;\n}\n\n.h-50 {\n  height: 50% !important;\n}\n\n.h-75 {\n  height: 75% !important;\n}\n\n.h-100 {\n  height: 100% !important;\n}\n\n.h-auto {\n  height: auto !important;\n}\n\n.mw-100 {\n  max-width: 100% !important;\n}\n\n.mh-100 {\n  max-height: 100% !important;\n}\n\n.min-vw-100 {\n  min-width: 100vw !important;\n}\n\n.min-vh-100 {\n  min-height: 100vh !important;\n}\n\n.vw-100 {\n  width: 100vw !important;\n}\n\n.vh-100 {\n  height: 100vh !important;\n}\n\n.m-0 {\n  margin: 0 !important;\n}\n\n.mt-0,\n.my-0 {\n  margin-top: 0 !important;\n}\n\n.mr-0,\n.mx-0 {\n  margin-right: 0 !important;\n}\n\n.mb-0,\n.my-0 {\n  margin-bottom: 0 !important;\n}\n\n.ml-0,\n.mx-0 {\n  margin-left: 0 !important;\n}\n\n.m-1 {\n  margin: 0.25rem !important;\n}\n\n.mt-1,\n.my-1 {\n  margin-top: 0.25rem !important;\n}\n\n.mr-1,\n.mx-1 {\n  margin-right: 0.25rem !important;\n}\n\n.mb-1,\n.my-1 {\n  margin-bottom: 0.25rem !important;\n}\n\n.ml-1,\n.mx-1 {\n  margin-left: 0.25rem !important;\n}\n\n.m-2 {\n  margin: 0.5rem !important;\n}\n\n.mt-2,\n.my-2 {\n  margin-top: 0.5rem !important;\n}\n\n.mr-2,\n.mx-2 {\n  margin-right: 0.5rem !important;\n}\n\n.mb-2,\n.my-2 {\n  margin-bottom: 0.5rem !important;\n}\n\n.ml-2,\n.mx-2 {\n  margin-left: 0.5rem !important;\n}\n\n.m-3 {\n  margin: 1rem !important;\n}\n\n.mt-3,\n.my-3 {\n  margin-top: 1rem !important;\n}\n\n.mr-3,\n.mx-3 {\n  margin-right: 1rem !important;\n}\n\n.mb-3,\n.my-3 {\n  margin-bottom: 1rem !important;\n}\n\n.ml-3,\n.mx-3 {\n  margin-left: 1rem !important;\n}\n\n.m-4 {\n  margin: 1.5rem !important;\n}\n\n.mt-4,\n.my-4 {\n  margin-top: 1.5rem !important;\n}\n\n.mr-4,\n.mx-4 {\n  margin-right: 1.5rem !important;\n}\n\n.mb-4,\n.my-4 {\n  margin-bottom: 1.5rem !important;\n}\n\n.ml-4,\n.mx-4 {\n  margin-left: 1.5rem !important;\n}\n\n.m-5 {\n  margin: 3rem !important;\n}\n\n.mt-5,\n.my-5 {\n  margin-top: 3rem !important;\n}\n\n.mr-5,\n.mx-5 {\n  margin-right: 3rem !important;\n}\n\n.mb-5,\n.my-5 {\n  margin-bottom: 3rem !important;\n}\n\n.ml-5,\n.mx-5 {\n  margin-left: 3rem !important;\n}\n\n.p-0 {\n  padding: 0 !important;\n}\n\n.pt-0,\n.py-0 {\n  padding-top: 0 !important;\n}\n\n.pr-0,\n.px-0 {\n  padding-right: 0 !important;\n}\n\n.pb-0,\n.py-0 {\n  padding-bottom: 0 !important;\n}\n\n.pl-0,\n.px-0 {\n  padding-left: 0 !important;\n}\n\n.p-1 {\n  padding: 0.25rem !important;\n}\n\n.pt-1,\n.py-1 {\n  padding-top: 0.25rem !important;\n}\n\n.pr-1,\n.px-1 {\n  padding-right: 0.25rem !important;\n}\n\n.pb-1,\n.py-1 {\n  padding-bottom: 0.25rem !important;\n}\n\n.pl-1,\n.px-1 {\n  padding-left: 0.25rem !important;\n}\n\n.p-2 {\n  padding: 0.5rem !important;\n}\n\n.pt-2,\n.py-2 {\n  padding-top: 0.5rem !important;\n}\n\n.pr-2,\n.px-2 {\n  padding-right: 0.5rem !important;\n}\n\n.pb-2,\n.py-2 {\n  padding-bottom: 0.5rem !important;\n}\n\n.pl-2,\n.px-2 {\n  padding-left: 0.5rem !important;\n}\n\n.p-3 {\n  padding: 1rem !important;\n}\n\n.pt-3,\n.py-3 {\n  padding-top: 1rem !important;\n}\n\n.pr-3,\n.px-3 {\n  padding-right: 1rem !important;\n}\n\n.pb-3,\n.py-3 {\n  padding-bottom: 1rem !important;\n}\n\n.pl-3,\n.px-3 {\n  padding-left: 1rem !important;\n}\n\n.p-4 {\n  padding: 1.5rem !important;\n}\n\n.pt-4,\n.py-4 {\n  padding-top: 1.5rem !important;\n}\n\n.pr-4,\n.px-4 {\n  padding-right: 1.5rem !important;\n}\n\n.pb-4,\n.py-4 {\n  padding-bottom: 1.5rem !important;\n}\n\n.pl-4,\n.px-4 {\n  padding-left: 1.5rem !important;\n}\n\n.p-5 {\n  padding: 3rem !important;\n}\n\n.pt-5,\n.py-5 {\n  padding-top: 3rem !important;\n}\n\n.pr-5,\n.px-5 {\n  padding-right: 3rem !important;\n}\n\n.pb-5,\n.py-5 {\n  padding-bottom: 3rem !important;\n}\n\n.pl-5,\n.px-5 {\n  padding-left: 3rem !important;\n}\n\n.m-n1 {\n  margin: -0.25rem !important;\n}\n\n.mt-n1,\n.my-n1 {\n  margin-top: -0.25rem !important;\n}\n\n.mr-n1,\n.mx-n1 {\n  margin-right: -0.25rem !important;\n}\n\n.mb-n1,\n.my-n1 {\n  margin-bottom: -0.25rem !important;\n}\n\n.ml-n1,\n.mx-n1 {\n  margin-left: -0.25rem !important;\n}\n\n.m-n2 {\n  margin: -0.5rem !important;\n}\n\n.mt-n2,\n.my-n2 {\n  margin-top: -0.5rem !important;\n}\n\n.mr-n2,\n.mx-n2 {\n  margin-right: -0.5rem !important;\n}\n\n.mb-n2,\n.my-n2 {\n  margin-bottom: -0.5rem !important;\n}\n\n.ml-n2,\n.mx-n2 {\n  margin-left: -0.5rem !important;\n}\n\n.m-n3 {\n  margin: -1rem !important;\n}\n\n.mt-n3,\n.my-n3 {\n  margin-top: -1rem !important;\n}\n\n.mr-n3,\n.mx-n3 {\n  margin-right: -1rem !important;\n}\n\n.mb-n3,\n.my-n3 {\n  margin-bottom: -1rem !important;\n}\n\n.ml-n3,\n.mx-n3 {\n  margin-left: -1rem !important;\n}\n\n.m-n4 {\n  margin: -1.5rem !important;\n}\n\n.mt-n4,\n.my-n4 {\n  margin-top: -1.5rem !important;\n}\n\n.mr-n4,\n.mx-n4 {\n  margin-right: -1.5rem !important;\n}\n\n.mb-n4,\n.my-n4 {\n  margin-bottom: -1.5rem !important;\n}\n\n.ml-n4,\n.mx-n4 {\n  margin-left: -1.5rem !important;\n}\n\n.m-n5 {\n  margin: -3rem !important;\n}\n\n.mt-n5,\n.my-n5 {\n  margin-top: -3rem !important;\n}\n\n.mr-n5,\n.mx-n5 {\n  margin-right: -3rem !important;\n}\n\n.mb-n5,\n.my-n5 {\n  margin-bottom: -3rem !important;\n}\n\n.ml-n5,\n.mx-n5 {\n  margin-left: -3rem !important;\n}\n\n.m-auto {\n  margin: auto !important;\n}\n\n.mt-auto,\n.my-auto {\n  margin-top: auto !important;\n}\n\n.mr-auto,\n.mx-auto {\n  margin-right: auto !important;\n}\n\n.mb-auto,\n.my-auto {\n  margin-bottom: auto !important;\n}\n\n.ml-auto,\n.mx-auto {\n  margin-left: auto !important;\n}\n\n@media (min-width: 576px) {\n  .m-sm-0 {\n    margin: 0 !important;\n  }\n  .mt-sm-0,\n  .my-sm-0 {\n    margin-top: 0 !important;\n  }\n  .mr-sm-0,\n  .mx-sm-0 {\n    margin-right: 0 !important;\n  }\n  .mb-sm-0,\n  .my-sm-0 {\n    margin-bottom: 0 !important;\n  }\n  .ml-sm-0,\n  .mx-sm-0 {\n    margin-left: 0 !important;\n  }\n  .m-sm-1 {\n    margin: 0.25rem !important;\n  }\n  .mt-sm-1,\n  .my-sm-1 {\n    margin-top: 0.25rem !important;\n  }\n  .mr-sm-1,\n  .mx-sm-1 {\n    margin-right: 0.25rem !important;\n  }\n  .mb-sm-1,\n  .my-sm-1 {\n    margin-bottom: 0.25rem !important;\n  }\n  .ml-sm-1,\n  .mx-sm-1 {\n    margin-left: 0.25rem !important;\n  }\n  .m-sm-2 {\n    margin: 0.5rem !important;\n  }\n  .mt-sm-2,\n  .my-sm-2 {\n    margin-top: 0.5rem !important;\n  }\n  .mr-sm-2,\n  .mx-sm-2 {\n    margin-right: 0.5rem !important;\n  }\n  .mb-sm-2,\n  .my-sm-2 {\n    margin-bottom: 0.5rem !important;\n  }\n  .ml-sm-2,\n  .mx-sm-2 {\n    margin-left: 0.5rem !important;\n  }\n  .m-sm-3 {\n    margin: 1rem !important;\n  }\n  .mt-sm-3,\n  .my-sm-3 {\n    margin-top: 1rem !important;\n  }\n  .mr-sm-3,\n  .mx-sm-3 {\n    margin-right: 1rem !important;\n  }\n  .mb-sm-3,\n  .my-sm-3 {\n    margin-bottom: 1rem !important;\n  }\n  .ml-sm-3,\n  .mx-sm-3 {\n    margin-left: 1rem !important;\n  }\n  .m-sm-4 {\n    margin: 1.5rem !important;\n  }\n  .mt-sm-4,\n  .my-sm-4 {\n    margin-top: 1.5rem !important;\n  }\n  .mr-sm-4,\n  .mx-sm-4 {\n    margin-right: 1.5rem !important;\n  }\n  .mb-sm-4,\n  .my-sm-4 {\n    margin-bottom: 1.5rem !important;\n  }\n  .ml-sm-4,\n  .mx-sm-4 {\n    margin-left: 1.5rem !important;\n  }\n  .m-sm-5 {\n    margin: 3rem !important;\n  }\n  .mt-sm-5,\n  .my-sm-5 {\n    margin-top: 3rem !important;\n  }\n  .mr-sm-5,\n  .mx-sm-5 {\n    margin-right: 3rem !important;\n  }\n  .mb-sm-5,\n  .my-sm-5 {\n    margin-bottom: 3rem !important;\n  }\n  .ml-sm-5,\n  .mx-sm-5 {\n    margin-left: 3rem !important;\n  }\n  .p-sm-0 {\n    padding: 0 !important;\n  }\n  .pt-sm-0,\n  .py-sm-0 {\n    padding-top: 0 !important;\n  }\n  .pr-sm-0,\n  .px-sm-0 {\n    padding-right: 0 !important;\n  }\n  .pb-sm-0,\n  .py-sm-0 {\n    padding-bottom: 0 !important;\n  }\n  .pl-sm-0,\n  .px-sm-0 {\n    padding-left: 0 !important;\n  }\n  .p-sm-1 {\n    padding: 0.25rem !important;\n  }\n  .pt-sm-1,\n  .py-sm-1 {\n    padding-top: 0.25rem !important;\n  }\n  .pr-sm-1,\n  .px-sm-1 {\n    padding-right: 0.25rem !important;\n  }\n  .pb-sm-1,\n  .py-sm-1 {\n    padding-bottom: 0.25rem !important;\n  }\n  .pl-sm-1,\n  .px-sm-1 {\n    padding-left: 0.25rem !important;\n  }\n  .p-sm-2 {\n    padding: 0.5rem !important;\n  }\n  .pt-sm-2,\n  .py-sm-2 {\n    padding-top: 0.5rem !important;\n  }\n  .pr-sm-2,\n  .px-sm-2 {\n    padding-right: 0.5rem !important;\n  }\n  .pb-sm-2,\n  .py-sm-2 {\n    padding-bottom: 0.5rem !important;\n  }\n  .pl-sm-2,\n  .px-sm-2 {\n    padding-left: 0.5rem !important;\n  }\n  .p-sm-3 {\n    padding: 1rem !important;\n  }\n  .pt-sm-3,\n  .py-sm-3 {\n    padding-top: 1rem !important;\n  }\n  .pr-sm-3,\n  .px-sm-3 {\n    padding-right: 1rem !important;\n  }\n  .pb-sm-3,\n  .py-sm-3 {\n    padding-bottom: 1rem !important;\n  }\n  .pl-sm-3,\n  .px-sm-3 {\n    padding-left: 1rem !important;\n  }\n  .p-sm-4 {\n    padding: 1.5rem !important;\n  }\n  .pt-sm-4,\n  .py-sm-4 {\n    padding-top: 1.5rem !important;\n  }\n  .pr-sm-4,\n  .px-sm-4 {\n    padding-right: 1.5rem !important;\n  }\n  .pb-sm-4,\n  .py-sm-4 {\n    padding-bottom: 1.5rem !important;\n  }\n  .pl-sm-4,\n  .px-sm-4 {\n    padding-left: 1.5rem !important;\n  }\n  .p-sm-5 {\n    padding: 3rem !important;\n  }\n  .pt-sm-5,\n  .py-sm-5 {\n    padding-top: 3rem !important;\n  }\n  .pr-sm-5,\n  .px-sm-5 {\n    padding-right: 3rem !important;\n  }\n  .pb-sm-5,\n  .py-sm-5 {\n    padding-bottom: 3rem !important;\n  }\n  .pl-sm-5,\n  .px-sm-5 {\n    padding-left: 3rem !important;\n  }\n  .m-sm-n1 {\n    margin: -0.25rem !important;\n  }\n  .mt-sm-n1,\n  .my-sm-n1 {\n    margin-top: -0.25rem !important;\n  }\n  .mr-sm-n1,\n  .mx-sm-n1 {\n    margin-right: -0.25rem !important;\n  }\n  .mb-sm-n1,\n  .my-sm-n1 {\n    margin-bottom: -0.25rem !important;\n  }\n  .ml-sm-n1,\n  .mx-sm-n1 {\n    margin-left: -0.25rem !important;\n  }\n  .m-sm-n2 {\n    margin: -0.5rem !important;\n  }\n  .mt-sm-n2,\n  .my-sm-n2 {\n    margin-top: -0.5rem !important;\n  }\n  .mr-sm-n2,\n  .mx-sm-n2 {\n    margin-right: -0.5rem !important;\n  }\n  .mb-sm-n2,\n  .my-sm-n2 {\n    margin-bottom: -0.5rem !important;\n  }\n  .ml-sm-n2,\n  .mx-sm-n2 {\n    margin-left: -0.5rem !important;\n  }\n  .m-sm-n3 {\n    margin: -1rem !important;\n  }\n  .mt-sm-n3,\n  .my-sm-n3 {\n    margin-top: -1rem !important;\n  }\n  .mr-sm-n3,\n  .mx-sm-n3 {\n    margin-right: -1rem !important;\n  }\n  .mb-sm-n3,\n  .my-sm-n3 {\n    margin-bottom: -1rem !important;\n  }\n  .ml-sm-n3,\n  .mx-sm-n3 {\n    margin-left: -1rem !important;\n  }\n  .m-sm-n4 {\n    margin: -1.5rem !important;\n  }\n  .mt-sm-n4,\n  .my-sm-n4 {\n    margin-top: -1.5rem !important;\n  }\n  .mr-sm-n4,\n  .mx-sm-n4 {\n    margin-right: -1.5rem !important;\n  }\n  .mb-sm-n4,\n  .my-sm-n4 {\n    margin-bottom: -1.5rem !important;\n  }\n  .ml-sm-n4,\n  .mx-sm-n4 {\n    margin-left: -1.5rem !important;\n  }\n  .m-sm-n5 {\n    margin: -3rem !important;\n  }\n  .mt-sm-n5,\n  .my-sm-n5 {\n    margin-top: -3rem !important;\n  }\n  .mr-sm-n5,\n  .mx-sm-n5 {\n    margin-right: -3rem !important;\n  }\n  .mb-sm-n5,\n  .my-sm-n5 {\n    margin-bottom: -3rem !important;\n  }\n  .ml-sm-n5,\n  .mx-sm-n5 {\n    margin-left: -3rem !important;\n  }\n  .m-sm-auto {\n    margin: auto !important;\n  }\n  .mt-sm-auto,\n  .my-sm-auto {\n    margin-top: auto !important;\n  }\n  .mr-sm-auto,\n  .mx-sm-auto {\n    margin-right: auto !important;\n  }\n  .mb-sm-auto,\n  .my-sm-auto {\n    margin-bottom: auto !important;\n  }\n  .ml-sm-auto,\n  .mx-sm-auto {\n    margin-left: auto !important;\n  }\n}\n\n@media (min-width: 768px) {\n  .m-md-0 {\n    margin: 0 !important;\n  }\n  .mt-md-0,\n  .my-md-0 {\n    margin-top: 0 !important;\n  }\n  .mr-md-0,\n  .mx-md-0 {\n    margin-right: 0 !important;\n  }\n  .mb-md-0,\n  .my-md-0 {\n    margin-bottom: 0 !important;\n  }\n  .ml-md-0,\n  .mx-md-0 {\n    margin-left: 0 !important;\n  }\n  .m-md-1 {\n    margin: 0.25rem !important;\n  }\n  .mt-md-1,\n  .my-md-1 {\n    margin-top: 0.25rem !important;\n  }\n  .mr-md-1,\n  .mx-md-1 {\n    margin-right: 0.25rem !important;\n  }\n  .mb-md-1,\n  .my-md-1 {\n    margin-bottom: 0.25rem !important;\n  }\n  .ml-md-1,\n  .mx-md-1 {\n    margin-left: 0.25rem !important;\n  }\n  .m-md-2 {\n    margin: 0.5rem !important;\n  }\n  .mt-md-2,\n  .my-md-2 {\n    margin-top: 0.5rem !important;\n  }\n  .mr-md-2,\n  .mx-md-2 {\n    margin-right: 0.5rem !important;\n  }\n  .mb-md-2,\n  .my-md-2 {\n    margin-bottom: 0.5rem !important;\n  }\n  .ml-md-2,\n  .mx-md-2 {\n    margin-left: 0.5rem !important;\n  }\n  .m-md-3 {\n    margin: 1rem !important;\n  }\n  .mt-md-3,\n  .my-md-3 {\n    margin-top: 1rem !important;\n  }\n  .mr-md-3,\n  .mx-md-3 {\n    margin-right: 1rem !important;\n  }\n  .mb-md-3,\n  .my-md-3 {\n    margin-bottom: 1rem !important;\n  }\n  .ml-md-3,\n  .mx-md-3 {\n    margin-left: 1rem !important;\n  }\n  .m-md-4 {\n    margin: 1.5rem !important;\n  }\n  .mt-md-4,\n  .my-md-4 {\n    margin-top: 1.5rem !important;\n  }\n  .mr-md-4,\n  .mx-md-4 {\n    margin-right: 1.5rem !important;\n  }\n  .mb-md-4,\n  .my-md-4 {\n    margin-bottom: 1.5rem !important;\n  }\n  .ml-md-4,\n  .mx-md-4 {\n    margin-left: 1.5rem !important;\n  }\n  .m-md-5 {\n    margin: 3rem !important;\n  }\n  .mt-md-5,\n  .my-md-5 {\n    margin-top: 3rem !important;\n  }\n  .mr-md-5,\n  .mx-md-5 {\n    margin-right: 3rem !important;\n  }\n  .mb-md-5,\n  .my-md-5 {\n    margin-bottom: 3rem !important;\n  }\n  .ml-md-5,\n  .mx-md-5 {\n    margin-left: 3rem !important;\n  }\n  .p-md-0 {\n    padding: 0 !important;\n  }\n  .pt-md-0,\n  .py-md-0 {\n    padding-top: 0 !important;\n  }\n  .pr-md-0,\n  .px-md-0 {\n    padding-right: 0 !important;\n  }\n  .pb-md-0,\n  .py-md-0 {\n    padding-bottom: 0 !important;\n  }\n  .pl-md-0,\n  .px-md-0 {\n    padding-left: 0 !important;\n  }\n  .p-md-1 {\n    padding: 0.25rem !important;\n  }\n  .pt-md-1,\n  .py-md-1 {\n    padding-top: 0.25rem !important;\n  }\n  .pr-md-1,\n  .px-md-1 {\n    padding-right: 0.25rem !important;\n  }\n  .pb-md-1,\n  .py-md-1 {\n    padding-bottom: 0.25rem !important;\n  }\n  .pl-md-1,\n  .px-md-1 {\n    padding-left: 0.25rem !important;\n  }\n  .p-md-2 {\n    padding: 0.5rem !important;\n  }\n  .pt-md-2,\n  .py-md-2 {\n    padding-top: 0.5rem !important;\n  }\n  .pr-md-2,\n  .px-md-2 {\n    padding-right: 0.5rem !important;\n  }\n  .pb-md-2,\n  .py-md-2 {\n    padding-bottom: 0.5rem !important;\n  }\n  .pl-md-2,\n  .px-md-2 {\n    padding-left: 0.5rem !important;\n  }\n  .p-md-3 {\n    padding: 1rem !important;\n  }\n  .pt-md-3,\n  .py-md-3 {\n    padding-top: 1rem !important;\n  }\n  .pr-md-3,\n  .px-md-3 {\n    padding-right: 1rem !important;\n  }\n  .pb-md-3,\n  .py-md-3 {\n    padding-bottom: 1rem !important;\n  }\n  .pl-md-3,\n  .px-md-3 {\n    padding-left: 1rem !important;\n  }\n  .p-md-4 {\n    padding: 1.5rem !important;\n  }\n  .pt-md-4,\n  .py-md-4 {\n    padding-top: 1.5rem !important;\n  }\n  .pr-md-4,\n  .px-md-4 {\n    padding-right: 1.5rem !important;\n  }\n  .pb-md-4,\n  .py-md-4 {\n    padding-bottom: 1.5rem !important;\n  }\n  .pl-md-4,\n  .px-md-4 {\n    padding-left: 1.5rem !important;\n  }\n  .p-md-5 {\n    padding: 3rem !important;\n  }\n  .pt-md-5,\n  .py-md-5 {\n    padding-top: 3rem !important;\n  }\n  .pr-md-5,\n  .px-md-5 {\n    padding-right: 3rem !important;\n  }\n  .pb-md-5,\n  .py-md-5 {\n    padding-bottom: 3rem !important;\n  }\n  .pl-md-5,\n  .px-md-5 {\n    padding-left: 3rem !important;\n  }\n  .m-md-n1 {\n    margin: -0.25rem !important;\n  }\n  .mt-md-n1,\n  .my-md-n1 {\n    margin-top: -0.25rem !important;\n  }\n  .mr-md-n1,\n  .mx-md-n1 {\n    margin-right: -0.25rem !important;\n  }\n  .mb-md-n1,\n  .my-md-n1 {\n    margin-bottom: -0.25rem !important;\n  }\n  .ml-md-n1,\n  .mx-md-n1 {\n    margin-left: -0.25rem !important;\n  }\n  .m-md-n2 {\n    margin: -0.5rem !important;\n  }\n  .mt-md-n2,\n  .my-md-n2 {\n    margin-top: -0.5rem !important;\n  }\n  .mr-md-n2,\n  .mx-md-n2 {\n    margin-right: -0.5rem !important;\n  }\n  .mb-md-n2,\n  .my-md-n2 {\n    margin-bottom: -0.5rem !important;\n  }\n  .ml-md-n2,\n  .mx-md-n2 {\n    margin-left: -0.5rem !important;\n  }\n  .m-md-n3 {\n    margin: -1rem !important;\n  }\n  .mt-md-n3,\n  .my-md-n3 {\n    margin-top: -1rem !important;\n  }\n  .mr-md-n3,\n  .mx-md-n3 {\n    margin-right: -1rem !important;\n  }\n  .mb-md-n3,\n  .my-md-n3 {\n    margin-bottom: -1rem !important;\n  }\n  .ml-md-n3,\n  .mx-md-n3 {\n    margin-left: -1rem !important;\n  }\n  .m-md-n4 {\n    margin: -1.5rem !important;\n  }\n  .mt-md-n4,\n  .my-md-n4 {\n    margin-top: -1.5rem !important;\n  }\n  .mr-md-n4,\n  .mx-md-n4 {\n    margin-right: -1.5rem !important;\n  }\n  .mb-md-n4,\n  .my-md-n4 {\n    margin-bottom: -1.5rem !important;\n  }\n  .ml-md-n4,\n  .mx-md-n4 {\n    margin-left: -1.5rem !important;\n  }\n  .m-md-n5 {\n    margin: -3rem !important;\n  }\n  .mt-md-n5,\n  .my-md-n5 {\n    margin-top: -3rem !important;\n  }\n  .mr-md-n5,\n  .mx-md-n5 {\n    margin-right: -3rem !important;\n  }\n  .mb-md-n5,\n  .my-md-n5 {\n    margin-bottom: -3rem !important;\n  }\n  .ml-md-n5,\n  .mx-md-n5 {\n    margin-left: -3rem !important;\n  }\n  .m-md-auto {\n    margin: auto !important;\n  }\n  .mt-md-auto,\n  .my-md-auto {\n    margin-top: auto !important;\n  }\n  .mr-md-auto,\n  .mx-md-auto {\n    margin-right: auto !important;\n  }\n  .mb-md-auto,\n  .my-md-auto {\n    margin-bottom: auto !important;\n  }\n  .ml-md-auto,\n  .mx-md-auto {\n    margin-left: auto !important;\n  }\n}\n\n@media (min-width: 992px) {\n  .m-lg-0 {\n    margin: 0 !important;\n  }\n  .mt-lg-0,\n  .my-lg-0 {\n    margin-top: 0 !important;\n  }\n  .mr-lg-0,\n  .mx-lg-0 {\n    margin-right: 0 !important;\n  }\n  .mb-lg-0,\n  .my-lg-0 {\n    margin-bottom: 0 !important;\n  }\n  .ml-lg-0,\n  .mx-lg-0 {\n    margin-left: 0 !important;\n  }\n  .m-lg-1 {\n    margin: 0.25rem !important;\n  }\n  .mt-lg-1,\n  .my-lg-1 {\n    margin-top: 0.25rem !important;\n  }\n  .mr-lg-1,\n  .mx-lg-1 {\n    margin-right: 0.25rem !important;\n  }\n  .mb-lg-1,\n  .my-lg-1 {\n    margin-bottom: 0.25rem !important;\n  }\n  .ml-lg-1,\n  .mx-lg-1 {\n    margin-left: 0.25rem !important;\n  }\n  .m-lg-2 {\n    margin: 0.5rem !important;\n  }\n  .mt-lg-2,\n  .my-lg-2 {\n    margin-top: 0.5rem !important;\n  }\n  .mr-lg-2,\n  .mx-lg-2 {\n    margin-right: 0.5rem !important;\n  }\n  .mb-lg-2,\n  .my-lg-2 {\n    margin-bottom: 0.5rem !important;\n  }\n  .ml-lg-2,\n  .mx-lg-2 {\n    margin-left: 0.5rem !important;\n  }\n  .m-lg-3 {\n    margin: 1rem !important;\n  }\n  .mt-lg-3,\n  .my-lg-3 {\n    margin-top: 1rem !important;\n  }\n  .mr-lg-3,\n  .mx-lg-3 {\n    margin-right: 1rem !important;\n  }\n  .mb-lg-3,\n  .my-lg-3 {\n    margin-bottom: 1rem !important;\n  }\n  .ml-lg-3,\n  .mx-lg-3 {\n    margin-left: 1rem !important;\n  }\n  .m-lg-4 {\n    margin: 1.5rem !important;\n  }\n  .mt-lg-4,\n  .my-lg-4 {\n    margin-top: 1.5rem !important;\n  }\n  .mr-lg-4,\n  .mx-lg-4 {\n    margin-right: 1.5rem !important;\n  }\n  .mb-lg-4,\n  .my-lg-4 {\n    margin-bottom: 1.5rem !important;\n  }\n  .ml-lg-4,\n  .mx-lg-4 {\n    margin-left: 1.5rem !important;\n  }\n  .m-lg-5 {\n    margin: 3rem !important;\n  }\n  .mt-lg-5,\n  .my-lg-5 {\n    margin-top: 3rem !important;\n  }\n  .mr-lg-5,\n  .mx-lg-5 {\n    margin-right: 3rem !important;\n  }\n  .mb-lg-5,\n  .my-lg-5 {\n    margin-bottom: 3rem !important;\n  }\n  .ml-lg-5,\n  .mx-lg-5 {\n    margin-left: 3rem !important;\n  }\n  .p-lg-0 {\n    padding: 0 !important;\n  }\n  .pt-lg-0,\n  .py-lg-0 {\n    padding-top: 0 !important;\n  }\n  .pr-lg-0,\n  .px-lg-0 {\n    padding-right: 0 !important;\n  }\n  .pb-lg-0,\n  .py-lg-0 {\n    padding-bottom: 0 !important;\n  }\n  .pl-lg-0,\n  .px-lg-0 {\n    padding-left: 0 !important;\n  }\n  .p-lg-1 {\n    padding: 0.25rem !important;\n  }\n  .pt-lg-1,\n  .py-lg-1 {\n    padding-top: 0.25rem !important;\n  }\n  .pr-lg-1,\n  .px-lg-1 {\n    padding-right: 0.25rem !important;\n  }\n  .pb-lg-1,\n  .py-lg-1 {\n    padding-bottom: 0.25rem !important;\n  }\n  .pl-lg-1,\n  .px-lg-1 {\n    padding-left: 0.25rem !important;\n  }\n  .p-lg-2 {\n    padding: 0.5rem !important;\n  }\n  .pt-lg-2,\n  .py-lg-2 {\n    padding-top: 0.5rem !important;\n  }\n  .pr-lg-2,\n  .px-lg-2 {\n    padding-right: 0.5rem !important;\n  }\n  .pb-lg-2,\n  .py-lg-2 {\n    padding-bottom: 0.5rem !important;\n  }\n  .pl-lg-2,\n  .px-lg-2 {\n    padding-left: 0.5rem !important;\n  }\n  .p-lg-3 {\n    padding: 1rem !important;\n  }\n  .pt-lg-3,\n  .py-lg-3 {\n    padding-top: 1rem !important;\n  }\n  .pr-lg-3,\n  .px-lg-3 {\n    padding-right: 1rem !important;\n  }\n  .pb-lg-3,\n  .py-lg-3 {\n    padding-bottom: 1rem !important;\n  }\n  .pl-lg-3,\n  .px-lg-3 {\n    padding-left: 1rem !important;\n  }\n  .p-lg-4 {\n    padding: 1.5rem !important;\n  }\n  .pt-lg-4,\n  .py-lg-4 {\n    padding-top: 1.5rem !important;\n  }\n  .pr-lg-4,\n  .px-lg-4 {\n    padding-right: 1.5rem !important;\n  }\n  .pb-lg-4,\n  .py-lg-4 {\n    padding-bottom: 1.5rem !important;\n  }\n  .pl-lg-4,\n  .px-lg-4 {\n    padding-left: 1.5rem !important;\n  }\n  .p-lg-5 {\n    padding: 3rem !important;\n  }\n  .pt-lg-5,\n  .py-lg-5 {\n    padding-top: 3rem !important;\n  }\n  .pr-lg-5,\n  .px-lg-5 {\n    padding-right: 3rem !important;\n  }\n  .pb-lg-5,\n  .py-lg-5 {\n    padding-bottom: 3rem !important;\n  }\n  .pl-lg-5,\n  .px-lg-5 {\n    padding-left: 3rem !important;\n  }\n  .m-lg-n1 {\n    margin: -0.25rem !important;\n  }\n  .mt-lg-n1,\n  .my-lg-n1 {\n    margin-top: -0.25rem !important;\n  }\n  .mr-lg-n1,\n  .mx-lg-n1 {\n    margin-right: -0.25rem !important;\n  }\n  .mb-lg-n1,\n  .my-lg-n1 {\n    margin-bottom: -0.25rem !important;\n  }\n  .ml-lg-n1,\n  .mx-lg-n1 {\n    margin-left: -0.25rem !important;\n  }\n  .m-lg-n2 {\n    margin: -0.5rem !important;\n  }\n  .mt-lg-n2,\n  .my-lg-n2 {\n    margin-top: -0.5rem !important;\n  }\n  .mr-lg-n2,\n  .mx-lg-n2 {\n    margin-right: -0.5rem !important;\n  }\n  .mb-lg-n2,\n  .my-lg-n2 {\n    margin-bottom: -0.5rem !important;\n  }\n  .ml-lg-n2,\n  .mx-lg-n2 {\n    margin-left: -0.5rem !important;\n  }\n  .m-lg-n3 {\n    margin: -1rem !important;\n  }\n  .mt-lg-n3,\n  .my-lg-n3 {\n    margin-top: -1rem !important;\n  }\n  .mr-lg-n3,\n  .mx-lg-n3 {\n    margin-right: -1rem !important;\n  }\n  .mb-lg-n3,\n  .my-lg-n3 {\n    margin-bottom: -1rem !important;\n  }\n  .ml-lg-n3,\n  .mx-lg-n3 {\n    margin-left: -1rem !important;\n  }\n  .m-lg-n4 {\n    margin: -1.5rem !important;\n  }\n  .mt-lg-n4,\n  .my-lg-n4 {\n    margin-top: -1.5rem !important;\n  }\n  .mr-lg-n4,\n  .mx-lg-n4 {\n    margin-right: -1.5rem !important;\n  }\n  .mb-lg-n4,\n  .my-lg-n4 {\n    margin-bottom: -1.5rem !important;\n  }\n  .ml-lg-n4,\n  .mx-lg-n4 {\n    margin-left: -1.5rem !important;\n  }\n  .m-lg-n5 {\n    margin: -3rem !important;\n  }\n  .mt-lg-n5,\n  .my-lg-n5 {\n    margin-top: -3rem !important;\n  }\n  .mr-lg-n5,\n  .mx-lg-n5 {\n    margin-right: -3rem !important;\n  }\n  .mb-lg-n5,\n  .my-lg-n5 {\n    margin-bottom: -3rem !important;\n  }\n  .ml-lg-n5,\n  .mx-lg-n5 {\n    margin-left: -3rem !important;\n  }\n  .m-lg-auto {\n    margin: auto !important;\n  }\n  .mt-lg-auto,\n  .my-lg-auto {\n    margin-top: auto !important;\n  }\n  .mr-lg-auto,\n  .mx-lg-auto {\n    margin-right: auto !important;\n  }\n  .mb-lg-auto,\n  .my-lg-auto {\n    margin-bottom: auto !important;\n  }\n  .ml-lg-auto,\n  .mx-lg-auto {\n    margin-left: auto !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .m-xl-0 {\n    margin: 0 !important;\n  }\n  .mt-xl-0,\n  .my-xl-0 {\n    margin-top: 0 !important;\n  }\n  .mr-xl-0,\n  .mx-xl-0 {\n    margin-right: 0 !important;\n  }\n  .mb-xl-0,\n  .my-xl-0 {\n    margin-bottom: 0 !important;\n  }\n  .ml-xl-0,\n  .mx-xl-0 {\n    margin-left: 0 !important;\n  }\n  .m-xl-1 {\n    margin: 0.25rem !important;\n  }\n  .mt-xl-1,\n  .my-xl-1 {\n    margin-top: 0.25rem !important;\n  }\n  .mr-xl-1,\n  .mx-xl-1 {\n    margin-right: 0.25rem !important;\n  }\n  .mb-xl-1,\n  .my-xl-1 {\n    margin-bottom: 0.25rem !important;\n  }\n  .ml-xl-1,\n  .mx-xl-1 {\n    margin-left: 0.25rem !important;\n  }\n  .m-xl-2 {\n    margin: 0.5rem !important;\n  }\n  .mt-xl-2,\n  .my-xl-2 {\n    margin-top: 0.5rem !important;\n  }\n  .mr-xl-2,\n  .mx-xl-2 {\n    margin-right: 0.5rem !important;\n  }\n  .mb-xl-2,\n  .my-xl-2 {\n    margin-bottom: 0.5rem !important;\n  }\n  .ml-xl-2,\n  .mx-xl-2 {\n    margin-left: 0.5rem !important;\n  }\n  .m-xl-3 {\n    margin: 1rem !important;\n  }\n  .mt-xl-3,\n  .my-xl-3 {\n    margin-top: 1rem !important;\n  }\n  .mr-xl-3,\n  .mx-xl-3 {\n    margin-right: 1rem !important;\n  }\n  .mb-xl-3,\n  .my-xl-3 {\n    margin-bottom: 1rem !important;\n  }\n  .ml-xl-3,\n  .mx-xl-3 {\n    margin-left: 1rem !important;\n  }\n  .m-xl-4 {\n    margin: 1.5rem !important;\n  }\n  .mt-xl-4,\n  .my-xl-4 {\n    margin-top: 1.5rem !important;\n  }\n  .mr-xl-4,\n  .mx-xl-4 {\n    margin-right: 1.5rem !important;\n  }\n  .mb-xl-4,\n  .my-xl-4 {\n    margin-bottom: 1.5rem !important;\n  }\n  .ml-xl-4,\n  .mx-xl-4 {\n    margin-left: 1.5rem !important;\n  }\n  .m-xl-5 {\n    margin: 3rem !important;\n  }\n  .mt-xl-5,\n  .my-xl-5 {\n    margin-top: 3rem !important;\n  }\n  .mr-xl-5,\n  .mx-xl-5 {\n    margin-right: 3rem !important;\n  }\n  .mb-xl-5,\n  .my-xl-5 {\n    margin-bottom: 3rem !important;\n  }\n  .ml-xl-5,\n  .mx-xl-5 {\n    margin-left: 3rem !important;\n  }\n  .p-xl-0 {\n    padding: 0 !important;\n  }\n  .pt-xl-0,\n  .py-xl-0 {\n    padding-top: 0 !important;\n  }\n  .pr-xl-0,\n  .px-xl-0 {\n    padding-right: 0 !important;\n  }\n  .pb-xl-0,\n  .py-xl-0 {\n    padding-bottom: 0 !important;\n  }\n  .pl-xl-0,\n  .px-xl-0 {\n    padding-left: 0 !important;\n  }\n  .p-xl-1 {\n    padding: 0.25rem !important;\n  }\n  .pt-xl-1,\n  .py-xl-1 {\n    padding-top: 0.25rem !important;\n  }\n  .pr-xl-1,\n  .px-xl-1 {\n    padding-right: 0.25rem !important;\n  }\n  .pb-xl-1,\n  .py-xl-1 {\n    padding-bottom: 0.25rem !important;\n  }\n  .pl-xl-1,\n  .px-xl-1 {\n    padding-left: 0.25rem !important;\n  }\n  .p-xl-2 {\n    padding: 0.5rem !important;\n  }\n  .pt-xl-2,\n  .py-xl-2 {\n    padding-top: 0.5rem !important;\n  }\n  .pr-xl-2,\n  .px-xl-2 {\n    padding-right: 0.5rem !important;\n  }\n  .pb-xl-2,\n  .py-xl-2 {\n    padding-bottom: 0.5rem !important;\n  }\n  .pl-xl-2,\n  .px-xl-2 {\n    padding-left: 0.5rem !important;\n  }\n  .p-xl-3 {\n    padding: 1rem !important;\n  }\n  .pt-xl-3,\n  .py-xl-3 {\n    padding-top: 1rem !important;\n  }\n  .pr-xl-3,\n  .px-xl-3 {\n    padding-right: 1rem !important;\n  }\n  .pb-xl-3,\n  .py-xl-3 {\n    padding-bottom: 1rem !important;\n  }\n  .pl-xl-3,\n  .px-xl-3 {\n    padding-left: 1rem !important;\n  }\n  .p-xl-4 {\n    padding: 1.5rem !important;\n  }\n  .pt-xl-4,\n  .py-xl-4 {\n    padding-top: 1.5rem !important;\n  }\n  .pr-xl-4,\n  .px-xl-4 {\n    padding-right: 1.5rem !important;\n  }\n  .pb-xl-4,\n  .py-xl-4 {\n    padding-bottom: 1.5rem !important;\n  }\n  .pl-xl-4,\n  .px-xl-4 {\n    padding-left: 1.5rem !important;\n  }\n  .p-xl-5 {\n    padding: 3rem !important;\n  }\n  .pt-xl-5,\n  .py-xl-5 {\n    padding-top: 3rem !important;\n  }\n  .pr-xl-5,\n  .px-xl-5 {\n    padding-right: 3rem !important;\n  }\n  .pb-xl-5,\n  .py-xl-5 {\n    padding-bottom: 3rem !important;\n  }\n  .pl-xl-5,\n  .px-xl-5 {\n    padding-left: 3rem !important;\n  }\n  .m-xl-n1 {\n    margin: -0.25rem !important;\n  }\n  .mt-xl-n1,\n  .my-xl-n1 {\n    margin-top: -0.25rem !important;\n  }\n  .mr-xl-n1,\n  .mx-xl-n1 {\n    margin-right: -0.25rem !important;\n  }\n  .mb-xl-n1,\n  .my-xl-n1 {\n    margin-bottom: -0.25rem !important;\n  }\n  .ml-xl-n1,\n  .mx-xl-n1 {\n    margin-left: -0.25rem !important;\n  }\n  .m-xl-n2 {\n    margin: -0.5rem !important;\n  }\n  .mt-xl-n2,\n  .my-xl-n2 {\n    margin-top: -0.5rem !important;\n  }\n  .mr-xl-n2,\n  .mx-xl-n2 {\n    margin-right: -0.5rem !important;\n  }\n  .mb-xl-n2,\n  .my-xl-n2 {\n    margin-bottom: -0.5rem !important;\n  }\n  .ml-xl-n2,\n  .mx-xl-n2 {\n    margin-left: -0.5rem !important;\n  }\n  .m-xl-n3 {\n    margin: -1rem !important;\n  }\n  .mt-xl-n3,\n  .my-xl-n3 {\n    margin-top: -1rem !important;\n  }\n  .mr-xl-n3,\n  .mx-xl-n3 {\n    margin-right: -1rem !important;\n  }\n  .mb-xl-n3,\n  .my-xl-n3 {\n    margin-bottom: -1rem !important;\n  }\n  .ml-xl-n3,\n  .mx-xl-n3 {\n    margin-left: -1rem !important;\n  }\n  .m-xl-n4 {\n    margin: -1.5rem !important;\n  }\n  .mt-xl-n4,\n  .my-xl-n4 {\n    margin-top: -1.5rem !important;\n  }\n  .mr-xl-n4,\n  .mx-xl-n4 {\n    margin-right: -1.5rem !important;\n  }\n  .mb-xl-n4,\n  .my-xl-n4 {\n    margin-bottom: -1.5rem !important;\n  }\n  .ml-xl-n4,\n  .mx-xl-n4 {\n    margin-left: -1.5rem !important;\n  }\n  .m-xl-n5 {\n    margin: -3rem !important;\n  }\n  .mt-xl-n5,\n  .my-xl-n5 {\n    margin-top: -3rem !important;\n  }\n  .mr-xl-n5,\n  .mx-xl-n5 {\n    margin-right: -3rem !important;\n  }\n  .mb-xl-n5,\n  .my-xl-n5 {\n    margin-bottom: -3rem !important;\n  }\n  .ml-xl-n5,\n  .mx-xl-n5 {\n    margin-left: -3rem !important;\n  }\n  .m-xl-auto {\n    margin: auto !important;\n  }\n  .mt-xl-auto,\n  .my-xl-auto {\n    margin-top: auto !important;\n  }\n  .mr-xl-auto,\n  .mx-xl-auto {\n    margin-right: auto !important;\n  }\n  .mb-xl-auto,\n  .my-xl-auto {\n    margin-bottom: auto !important;\n  }\n  .ml-xl-auto,\n  .mx-xl-auto {\n    margin-left: auto !important;\n  }\n}\n\n.stretched-link::after {\n  position: absolute;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1;\n  pointer-events: auto;\n  content: \"\";\n  background-color: rgba(0, 0, 0, 0);\n}\n\n.text-monospace {\n  font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace !important;\n}\n\n.text-justify {\n  text-align: justify !important;\n}\n\n.text-wrap {\n  white-space: normal !important;\n}\n\n.text-nowrap {\n  white-space: nowrap !important;\n}\n\n.text-truncate {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.text-left {\n  text-align: left !important;\n}\n\n.text-right {\n  text-align: right !important;\n}\n\n.text-center {\n  text-align: center !important;\n}\n\n@media (min-width: 576px) {\n  .text-sm-left {\n    text-align: left !important;\n  }\n  .text-sm-right {\n    text-align: right !important;\n  }\n  .text-sm-center {\n    text-align: center !important;\n  }\n}\n\n@media (min-width: 768px) {\n  .text-md-left {\n    text-align: left !important;\n  }\n  .text-md-right {\n    text-align: right !important;\n  }\n  .text-md-center {\n    text-align: center !important;\n  }\n}\n\n@media (min-width: 992px) {\n  .text-lg-left {\n    text-align: left !important;\n  }\n  .text-lg-right {\n    text-align: right !important;\n  }\n  .text-lg-center {\n    text-align: center !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .text-xl-left {\n    text-align: left !important;\n  }\n  .text-xl-right {\n    text-align: right !important;\n  }\n  .text-xl-center {\n    text-align: center !important;\n  }\n}\n\n.text-lowercase {\n  text-transform: lowercase !important;\n}\n\n.text-uppercase {\n  text-transform: uppercase !important;\n}\n\n.text-capitalize {\n  text-transform: capitalize !important;\n}\n\n.font-weight-light {\n  font-weight: 300 !important;\n}\n\n.font-weight-lighter {\n  font-weight: lighter !important;\n}\n\n.font-weight-normal {\n  font-weight: 400 !important;\n}\n\n.font-weight-bold {\n  font-weight: 700 !important;\n}\n\n.font-weight-bolder {\n  font-weight: bolder !important;\n}\n\n.font-italic {\n  font-style: italic !important;\n}\n\n.text-white {\n  color: #fff !important;\n}\n\n.text-primary {\n  color: #007bff !important;\n}\n\na.text-primary:hover, a.text-primary:focus {\n  color: #0056b3 !important;\n}\n\n.text-secondary {\n  color: #6c757d !important;\n}\n\na.text-secondary:hover, a.text-secondary:focus {\n  color: #494f54 !important;\n}\n\n.text-success {\n  color: #28a745 !important;\n}\n\na.text-success:hover, a.text-success:focus {\n  color: #19692c !important;\n}\n\n.text-info {\n  color: #17a2b8 !important;\n}\n\na.text-info:hover, a.text-info:focus {\n  color: #0f6674 !important;\n}\n\n.text-warning {\n  color: #ffc107 !important;\n}\n\na.text-warning:hover, a.text-warning:focus {\n  color: #ba8b00 !important;\n}\n\n.text-danger {\n  color: #dc3545 !important;\n}\n\na.text-danger:hover, a.text-danger:focus {\n  color: #a71d2a !important;\n}\n\n.text-light {\n  color: #f8f9fa !important;\n}\n\na.text-light:hover, a.text-light:focus {\n  color: #cbd3da !important;\n}\n\n.text-dark {\n  color: #343a40 !important;\n}\n\na.text-dark:hover, a.text-dark:focus {\n  color: #121416 !important;\n}\n\n.text-body {\n  color: #212529 !important;\n}\n\n.text-muted {\n  color: #6c757d !important;\n}\n\n.text-black-50 {\n  color: rgba(0, 0, 0, 0.5) !important;\n}\n\n.text-white-50 {\n  color: rgba(255, 255, 255, 0.5) !important;\n}\n\n.text-hide {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.text-decoration-none {\n  text-decoration: none !important;\n}\n\n.text-break {\n  word-break: break-word !important;\n  word-wrap: break-word !important;\n}\n\n.text-reset {\n  color: inherit !important;\n}\n\n.visible {\n  visibility: visible !important;\n}\n\n.invisible {\n  visibility: hidden !important;\n}\n\n@media print {\n  *,\n  *::before,\n  *::after {\n    text-shadow: none !important;\n    box-shadow: none !important;\n  }\n  a:not(.btn) {\n    text-decoration: underline;\n  }\n  abbr[title]::after {\n    content: \" (\" attr(title) \")\";\n  }\n  pre {\n    white-space: pre-wrap !important;\n  }\n  pre,\n  blockquote {\n    border: 1px solid #adb5bd;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n  @page {\n    size: a3;\n  }\n  body {\n    min-width: 992px !important;\n  }\n  .container {\n    min-width: 992px !important;\n  }\n  .navbar {\n    display: none;\n  }\n  .badge {\n    border: 1px solid #000;\n  }\n  .table {\n    border-collapse: collapse !important;\n  }\n  .table td,\n  .table th {\n    background-color: #fff !important;\n  }\n  .table-bordered th,\n  .table-bordered td {\n    border: 1px solid #dee2e6 !important;\n  }\n  .table-dark {\n    color: inherit;\n  }\n  .table-dark th,\n  .table-dark td,\n  .table-dark thead th,\n  .table-dark tbody + tbody {\n    border-color: #dee2e6;\n  }\n  .table .thead-dark th {\n    color: inherit;\n    border-color: #dee2e6;\n  }\n}\n/*# sourceMappingURL=bootstrap.css.map */"
  },
  {
    "path": "src/IdentityServer/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js",
    "content": "/*!\n  * Bootstrap v4.5.3 (https://getbootstrap.com/)\n  * Copyright 2011-2020 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)\n  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n  */\n(function (global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('jquery')) :\n  typeof define === 'function' && define.amd ? define(['exports', 'jquery'], factory) :\n  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.bootstrap = {}, global.jQuery));\n}(this, (function (exports, $) { 'use strict';\n\n  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }\n\n  var $__default = /*#__PURE__*/_interopDefaultLegacy($);\n\n  function _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\n  function _createClass(Constructor, protoProps, staticProps) {\n    if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n    if (staticProps) _defineProperties(Constructor, staticProps);\n    return Constructor;\n  }\n\n  function _extends() {\n    _extends = Object.assign || function (target) {\n      for (var i = 1; i < arguments.length; i++) {\n        var source = arguments[i];\n\n        for (var key in source) {\n          if (Object.prototype.hasOwnProperty.call(source, key)) {\n            target[key] = source[key];\n          }\n        }\n      }\n\n      return target;\n    };\n\n    return _extends.apply(this, arguments);\n  }\n\n  function _inheritsLoose(subClass, superClass) {\n    subClass.prototype = Object.create(superClass.prototype);\n    subClass.prototype.constructor = subClass;\n    subClass.__proto__ = superClass;\n  }\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v4.5.3): util.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n  /**\n   * ------------------------------------------------------------------------\n   * Private TransitionEnd Helpers\n   * ------------------------------------------------------------------------\n   */\n\n  var TRANSITION_END = 'transitionend';\n  var MAX_UID = 1000000;\n  var MILLISECONDS_MULTIPLIER = 1000; // Shoutout AngusCroll (https://goo.gl/pxwQGp)\n\n  function toType(obj) {\n    if (obj === null || typeof obj === 'undefined') {\n      return \"\" + obj;\n    }\n\n    return {}.toString.call(obj).match(/\\s([a-z]+)/i)[1].toLowerCase();\n  }\n\n  function getSpecialTransitionEndEvent() {\n    return {\n      bindType: TRANSITION_END,\n      delegateType: TRANSITION_END,\n      handle: function handle(event) {\n        if ($__default['default'](event.target).is(this)) {\n          return event.handleObj.handler.apply(this, arguments); // eslint-disable-line prefer-rest-params\n        }\n\n        return undefined;\n      }\n    };\n  }\n\n  function transitionEndEmulator(duration) {\n    var _this = this;\n\n    var called = false;\n    $__default['default'](this).one(Util.TRANSITION_END, function () {\n      called = true;\n    });\n    setTimeout(function () {\n      if (!called) {\n        Util.triggerTransitionEnd(_this);\n      }\n    }, duration);\n    return this;\n  }\n\n  function setTransitionEndSupport() {\n    $__default['default'].fn.emulateTransitionEnd = transitionEndEmulator;\n    $__default['default'].event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent();\n  }\n  /**\n   * --------------------------------------------------------------------------\n   * Public Util Api\n   * --------------------------------------------------------------------------\n   */\n\n\n  var Util = {\n    TRANSITION_END: 'bsTransitionEnd',\n    getUID: function getUID(prefix) {\n      do {\n        prefix += ~~(Math.random() * MAX_UID); // \"~~\" acts like a faster Math.floor() here\n      } while (document.getElementById(prefix));\n\n      return prefix;\n    },\n    getSelectorFromElement: function getSelectorFromElement(element) {\n      var selector = element.getAttribute('data-target');\n\n      if (!selector || selector === '#') {\n        var hrefAttr = element.getAttribute('href');\n        selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : '';\n      }\n\n      try {\n        return document.querySelector(selector) ? selector : null;\n      } catch (_) {\n        return null;\n      }\n    },\n    getTransitionDurationFromElement: function getTransitionDurationFromElement(element) {\n      if (!element) {\n        return 0;\n      } // Get transition-duration of the element\n\n\n      var transitionDuration = $__default['default'](element).css('transition-duration');\n      var transitionDelay = $__default['default'](element).css('transition-delay');\n      var floatTransitionDuration = parseFloat(transitionDuration);\n      var floatTransitionDelay = parseFloat(transitionDelay); // Return 0 if element or transition duration is not found\n\n      if (!floatTransitionDuration && !floatTransitionDelay) {\n        return 0;\n      } // If multiple durations are defined, take the first\n\n\n      transitionDuration = transitionDuration.split(',')[0];\n      transitionDelay = transitionDelay.split(',')[0];\n      return (parseFloat(transitionDuration) + parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER;\n    },\n    reflow: function reflow(element) {\n      return element.offsetHeight;\n    },\n    triggerTransitionEnd: function triggerTransitionEnd(element) {\n      $__default['default'](element).trigger(TRANSITION_END);\n    },\n    supportsTransitionEnd: function supportsTransitionEnd() {\n      return Boolean(TRANSITION_END);\n    },\n    isElement: function isElement(obj) {\n      return (obj[0] || obj).nodeType;\n    },\n    typeCheckConfig: function typeCheckConfig(componentName, config, configTypes) {\n      for (var property in configTypes) {\n        if (Object.prototype.hasOwnProperty.call(configTypes, property)) {\n          var expectedTypes = configTypes[property];\n          var value = config[property];\n          var valueType = value && Util.isElement(value) ? 'element' : toType(value);\n\n          if (!new RegExp(expectedTypes).test(valueType)) {\n            throw new Error(componentName.toUpperCase() + \": \" + (\"Option \\\"\" + property + \"\\\" provided type \\\"\" + valueType + \"\\\" \") + (\"but expected type \\\"\" + expectedTypes + \"\\\".\"));\n          }\n        }\n      }\n    },\n    findShadowRoot: function findShadowRoot(element) {\n      if (!document.documentElement.attachShadow) {\n        return null;\n      } // Can find the shadow root otherwise it'll return the document\n\n\n      if (typeof element.getRootNode === 'function') {\n        var root = element.getRootNode();\n        return root instanceof ShadowRoot ? root : null;\n      }\n\n      if (element instanceof ShadowRoot) {\n        return element;\n      } // when we don't find a shadow root\n\n\n      if (!element.parentNode) {\n        return null;\n      }\n\n      return Util.findShadowRoot(element.parentNode);\n    },\n    jQueryDetection: function jQueryDetection() {\n      if (typeof $__default['default'] === 'undefined') {\n        throw new TypeError('Bootstrap\\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\\'s JavaScript.');\n      }\n\n      var version = $__default['default'].fn.jquery.split(' ')[0].split('.');\n      var minMajor = 1;\n      var ltMajor = 2;\n      var minMinor = 9;\n      var minPatch = 1;\n      var maxMajor = 4;\n\n      if (version[0] < ltMajor && version[1] < minMinor || version[0] === minMajor && version[1] === minMinor && version[2] < minPatch || version[0] >= maxMajor) {\n        throw new Error('Bootstrap\\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0');\n      }\n    }\n  };\n  Util.jQueryDetection();\n  setTransitionEndSupport();\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME = 'alert';\n  var VERSION = '4.5.3';\n  var DATA_KEY = 'bs.alert';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var DATA_API_KEY = '.data-api';\n  var JQUERY_NO_CONFLICT = $__default['default'].fn[NAME];\n  var SELECTOR_DISMISS = '[data-dismiss=\"alert\"]';\n  var EVENT_CLOSE = \"close\" + EVENT_KEY;\n  var EVENT_CLOSED = \"closed\" + EVENT_KEY;\n  var EVENT_CLICK_DATA_API = \"click\" + EVENT_KEY + DATA_API_KEY;\n  var CLASS_NAME_ALERT = 'alert';\n  var CLASS_NAME_FADE = 'fade';\n  var CLASS_NAME_SHOW = 'show';\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  var Alert = /*#__PURE__*/function () {\n    function Alert(element) {\n      this._element = element;\n    } // Getters\n\n\n    var _proto = Alert.prototype;\n\n    // Public\n    _proto.close = function close(element) {\n      var rootElement = this._element;\n\n      if (element) {\n        rootElement = this._getRootElement(element);\n      }\n\n      var customEvent = this._triggerCloseEvent(rootElement);\n\n      if (customEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      this._removeElement(rootElement);\n    };\n\n    _proto.dispose = function dispose() {\n      $__default['default'].removeData(this._element, DATA_KEY);\n      this._element = null;\n    } // Private\n    ;\n\n    _proto._getRootElement = function _getRootElement(element) {\n      var selector = Util.getSelectorFromElement(element);\n      var parent = false;\n\n      if (selector) {\n        parent = document.querySelector(selector);\n      }\n\n      if (!parent) {\n        parent = $__default['default'](element).closest(\".\" + CLASS_NAME_ALERT)[0];\n      }\n\n      return parent;\n    };\n\n    _proto._triggerCloseEvent = function _triggerCloseEvent(element) {\n      var closeEvent = $__default['default'].Event(EVENT_CLOSE);\n      $__default['default'](element).trigger(closeEvent);\n      return closeEvent;\n    };\n\n    _proto._removeElement = function _removeElement(element) {\n      var _this = this;\n\n      $__default['default'](element).removeClass(CLASS_NAME_SHOW);\n\n      if (!$__default['default'](element).hasClass(CLASS_NAME_FADE)) {\n        this._destroyElement(element);\n\n        return;\n      }\n\n      var transitionDuration = Util.getTransitionDurationFromElement(element);\n      $__default['default'](element).one(Util.TRANSITION_END, function (event) {\n        return _this._destroyElement(element, event);\n      }).emulateTransitionEnd(transitionDuration);\n    };\n\n    _proto._destroyElement = function _destroyElement(element) {\n      $__default['default'](element).detach().trigger(EVENT_CLOSED).remove();\n    } // Static\n    ;\n\n    Alert._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var $element = $__default['default'](this);\n        var data = $element.data(DATA_KEY);\n\n        if (!data) {\n          data = new Alert(this);\n          $element.data(DATA_KEY, data);\n        }\n\n        if (config === 'close') {\n          data[config](this);\n        }\n      });\n    };\n\n    Alert._handleDismiss = function _handleDismiss(alertInstance) {\n      return function (event) {\n        if (event) {\n          event.preventDefault();\n        }\n\n        alertInstance.close(this);\n      };\n    };\n\n    _createClass(Alert, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }]);\n\n    return Alert;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $__default['default'](document).on(EVENT_CLICK_DATA_API, SELECTOR_DISMISS, Alert._handleDismiss(new Alert()));\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $__default['default'].fn[NAME] = Alert._jQueryInterface;\n  $__default['default'].fn[NAME].Constructor = Alert;\n\n  $__default['default'].fn[NAME].noConflict = function () {\n    $__default['default'].fn[NAME] = JQUERY_NO_CONFLICT;\n    return Alert._jQueryInterface;\n  };\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME$1 = 'button';\n  var VERSION$1 = '4.5.3';\n  var DATA_KEY$1 = 'bs.button';\n  var EVENT_KEY$1 = \".\" + DATA_KEY$1;\n  var DATA_API_KEY$1 = '.data-api';\n  var JQUERY_NO_CONFLICT$1 = $__default['default'].fn[NAME$1];\n  var CLASS_NAME_ACTIVE = 'active';\n  var CLASS_NAME_BUTTON = 'btn';\n  var CLASS_NAME_FOCUS = 'focus';\n  var SELECTOR_DATA_TOGGLE_CARROT = '[data-toggle^=\"button\"]';\n  var SELECTOR_DATA_TOGGLES = '[data-toggle=\"buttons\"]';\n  var SELECTOR_DATA_TOGGLE = '[data-toggle=\"button\"]';\n  var SELECTOR_DATA_TOGGLES_BUTTONS = '[data-toggle=\"buttons\"] .btn';\n  var SELECTOR_INPUT = 'input:not([type=\"hidden\"])';\n  var SELECTOR_ACTIVE = '.active';\n  var SELECTOR_BUTTON = '.btn';\n  var EVENT_CLICK_DATA_API$1 = \"click\" + EVENT_KEY$1 + DATA_API_KEY$1;\n  var EVENT_FOCUS_BLUR_DATA_API = \"focus\" + EVENT_KEY$1 + DATA_API_KEY$1 + \" \" + (\"blur\" + EVENT_KEY$1 + DATA_API_KEY$1);\n  var EVENT_LOAD_DATA_API = \"load\" + EVENT_KEY$1 + DATA_API_KEY$1;\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  var Button = /*#__PURE__*/function () {\n    function Button(element) {\n      this._element = element;\n      this.shouldAvoidTriggerChange = false;\n    } // Getters\n\n\n    var _proto = Button.prototype;\n\n    // Public\n    _proto.toggle = function toggle() {\n      var triggerChangeEvent = true;\n      var addAriaPressed = true;\n      var rootElement = $__default['default'](this._element).closest(SELECTOR_DATA_TOGGLES)[0];\n\n      if (rootElement) {\n        var input = this._element.querySelector(SELECTOR_INPUT);\n\n        if (input) {\n          if (input.type === 'radio') {\n            if (input.checked && this._element.classList.contains(CLASS_NAME_ACTIVE)) {\n              triggerChangeEvent = false;\n            } else {\n              var activeElement = rootElement.querySelector(SELECTOR_ACTIVE);\n\n              if (activeElement) {\n                $__default['default'](activeElement).removeClass(CLASS_NAME_ACTIVE);\n              }\n            }\n          }\n\n          if (triggerChangeEvent) {\n            // if it's not a radio button or checkbox don't add a pointless/invalid checked property to the input\n            if (input.type === 'checkbox' || input.type === 'radio') {\n              input.checked = !this._element.classList.contains(CLASS_NAME_ACTIVE);\n            }\n\n            if (!this.shouldAvoidTriggerChange) {\n              $__default['default'](input).trigger('change');\n            }\n          }\n\n          input.focus();\n          addAriaPressed = false;\n        }\n      }\n\n      if (!(this._element.hasAttribute('disabled') || this._element.classList.contains('disabled'))) {\n        if (addAriaPressed) {\n          this._element.setAttribute('aria-pressed', !this._element.classList.contains(CLASS_NAME_ACTIVE));\n        }\n\n        if (triggerChangeEvent) {\n          $__default['default'](this._element).toggleClass(CLASS_NAME_ACTIVE);\n        }\n      }\n    };\n\n    _proto.dispose = function dispose() {\n      $__default['default'].removeData(this._element, DATA_KEY$1);\n      this._element = null;\n    } // Static\n    ;\n\n    Button._jQueryInterface = function _jQueryInterface(config, avoidTriggerChange) {\n      return this.each(function () {\n        var $element = $__default['default'](this);\n        var data = $element.data(DATA_KEY$1);\n\n        if (!data) {\n          data = new Button(this);\n          $element.data(DATA_KEY$1, data);\n        }\n\n        data.shouldAvoidTriggerChange = avoidTriggerChange;\n\n        if (config === 'toggle') {\n          data[config]();\n        }\n      });\n    };\n\n    _createClass(Button, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION$1;\n      }\n    }]);\n\n    return Button;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $__default['default'](document).on(EVENT_CLICK_DATA_API$1, SELECTOR_DATA_TOGGLE_CARROT, function (event) {\n    var button = event.target;\n    var initialButton = button;\n\n    if (!$__default['default'](button).hasClass(CLASS_NAME_BUTTON)) {\n      button = $__default['default'](button).closest(SELECTOR_BUTTON)[0];\n    }\n\n    if (!button || button.hasAttribute('disabled') || button.classList.contains('disabled')) {\n      event.preventDefault(); // work around Firefox bug #1540995\n    } else {\n      var inputBtn = button.querySelector(SELECTOR_INPUT);\n\n      if (inputBtn && (inputBtn.hasAttribute('disabled') || inputBtn.classList.contains('disabled'))) {\n        event.preventDefault(); // work around Firefox bug #1540995\n\n        return;\n      }\n\n      if (initialButton.tagName === 'INPUT' || button.tagName !== 'LABEL') {\n        Button._jQueryInterface.call($__default['default'](button), 'toggle', initialButton.tagName === 'INPUT');\n      }\n    }\n  }).on(EVENT_FOCUS_BLUR_DATA_API, SELECTOR_DATA_TOGGLE_CARROT, function (event) {\n    var button = $__default['default'](event.target).closest(SELECTOR_BUTTON)[0];\n    $__default['default'](button).toggleClass(CLASS_NAME_FOCUS, /^focus(in)?$/.test(event.type));\n  });\n  $__default['default'](window).on(EVENT_LOAD_DATA_API, function () {\n    // ensure correct active class is set to match the controls' actual values/states\n    // find all checkboxes/readio buttons inside data-toggle groups\n    var buttons = [].slice.call(document.querySelectorAll(SELECTOR_DATA_TOGGLES_BUTTONS));\n\n    for (var i = 0, len = buttons.length; i < len; i++) {\n      var button = buttons[i];\n      var input = button.querySelector(SELECTOR_INPUT);\n\n      if (input.checked || input.hasAttribute('checked')) {\n        button.classList.add(CLASS_NAME_ACTIVE);\n      } else {\n        button.classList.remove(CLASS_NAME_ACTIVE);\n      }\n    } // find all button toggles\n\n\n    buttons = [].slice.call(document.querySelectorAll(SELECTOR_DATA_TOGGLE));\n\n    for (var _i = 0, _len = buttons.length; _i < _len; _i++) {\n      var _button = buttons[_i];\n\n      if (_button.getAttribute('aria-pressed') === 'true') {\n        _button.classList.add(CLASS_NAME_ACTIVE);\n      } else {\n        _button.classList.remove(CLASS_NAME_ACTIVE);\n      }\n    }\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $__default['default'].fn[NAME$1] = Button._jQueryInterface;\n  $__default['default'].fn[NAME$1].Constructor = Button;\n\n  $__default['default'].fn[NAME$1].noConflict = function () {\n    $__default['default'].fn[NAME$1] = JQUERY_NO_CONFLICT$1;\n    return Button._jQueryInterface;\n  };\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME$2 = 'carousel';\n  var VERSION$2 = '4.5.3';\n  var DATA_KEY$2 = 'bs.carousel';\n  var EVENT_KEY$2 = \".\" + DATA_KEY$2;\n  var DATA_API_KEY$2 = '.data-api';\n  var JQUERY_NO_CONFLICT$2 = $__default['default'].fn[NAME$2];\n  var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key\n\n  var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key\n\n  var TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch\n\n  var SWIPE_THRESHOLD = 40;\n  var Default = {\n    interval: 5000,\n    keyboard: true,\n    slide: false,\n    pause: 'hover',\n    wrap: true,\n    touch: true\n  };\n  var DefaultType = {\n    interval: '(number|boolean)',\n    keyboard: 'boolean',\n    slide: '(boolean|string)',\n    pause: '(string|boolean)',\n    wrap: 'boolean',\n    touch: 'boolean'\n  };\n  var DIRECTION_NEXT = 'next';\n  var DIRECTION_PREV = 'prev';\n  var DIRECTION_LEFT = 'left';\n  var DIRECTION_RIGHT = 'right';\n  var EVENT_SLIDE = \"slide\" + EVENT_KEY$2;\n  var EVENT_SLID = \"slid\" + EVENT_KEY$2;\n  var EVENT_KEYDOWN = \"keydown\" + EVENT_KEY$2;\n  var EVENT_MOUSEENTER = \"mouseenter\" + EVENT_KEY$2;\n  var EVENT_MOUSELEAVE = \"mouseleave\" + EVENT_KEY$2;\n  var EVENT_TOUCHSTART = \"touchstart\" + EVENT_KEY$2;\n  var EVENT_TOUCHMOVE = \"touchmove\" + EVENT_KEY$2;\n  var EVENT_TOUCHEND = \"touchend\" + EVENT_KEY$2;\n  var EVENT_POINTERDOWN = \"pointerdown\" + EVENT_KEY$2;\n  var EVENT_POINTERUP = \"pointerup\" + EVENT_KEY$2;\n  var EVENT_DRAG_START = \"dragstart\" + EVENT_KEY$2;\n  var EVENT_LOAD_DATA_API$1 = \"load\" + EVENT_KEY$2 + DATA_API_KEY$2;\n  var EVENT_CLICK_DATA_API$2 = \"click\" + EVENT_KEY$2 + DATA_API_KEY$2;\n  var CLASS_NAME_CAROUSEL = 'carousel';\n  var CLASS_NAME_ACTIVE$1 = 'active';\n  var CLASS_NAME_SLIDE = 'slide';\n  var CLASS_NAME_RIGHT = 'carousel-item-right';\n  var CLASS_NAME_LEFT = 'carousel-item-left';\n  var CLASS_NAME_NEXT = 'carousel-item-next';\n  var CLASS_NAME_PREV = 'carousel-item-prev';\n  var CLASS_NAME_POINTER_EVENT = 'pointer-event';\n  var SELECTOR_ACTIVE$1 = '.active';\n  var SELECTOR_ACTIVE_ITEM = '.active.carousel-item';\n  var SELECTOR_ITEM = '.carousel-item';\n  var SELECTOR_ITEM_IMG = '.carousel-item img';\n  var SELECTOR_NEXT_PREV = '.carousel-item-next, .carousel-item-prev';\n  var SELECTOR_INDICATORS = '.carousel-indicators';\n  var SELECTOR_DATA_SLIDE = '[data-slide], [data-slide-to]';\n  var SELECTOR_DATA_RIDE = '[data-ride=\"carousel\"]';\n  var PointerType = {\n    TOUCH: 'touch',\n    PEN: 'pen'\n  };\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  var Carousel = /*#__PURE__*/function () {\n    function Carousel(element, config) {\n      this._items = null;\n      this._interval = null;\n      this._activeElement = null;\n      this._isPaused = false;\n      this._isSliding = false;\n      this.touchTimeout = null;\n      this.touchStartX = 0;\n      this.touchDeltaX = 0;\n      this._config = this._getConfig(config);\n      this._element = element;\n      this._indicatorsElement = this._element.querySelector(SELECTOR_INDICATORS);\n      this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0;\n      this._pointerEvent = Boolean(window.PointerEvent || window.MSPointerEvent);\n\n      this._addEventListeners();\n    } // Getters\n\n\n    var _proto = Carousel.prototype;\n\n    // Public\n    _proto.next = function next() {\n      if (!this._isSliding) {\n        this._slide(DIRECTION_NEXT);\n      }\n    };\n\n    _proto.nextWhenVisible = function nextWhenVisible() {\n      var $element = $__default['default'](this._element); // Don't call next when the page isn't visible\n      // or the carousel or its parent isn't visible\n\n      if (!document.hidden && $element.is(':visible') && $element.css('visibility') !== 'hidden') {\n        this.next();\n      }\n    };\n\n    _proto.prev = function prev() {\n      if (!this._isSliding) {\n        this._slide(DIRECTION_PREV);\n      }\n    };\n\n    _proto.pause = function pause(event) {\n      if (!event) {\n        this._isPaused = true;\n      }\n\n      if (this._element.querySelector(SELECTOR_NEXT_PREV)) {\n        Util.triggerTransitionEnd(this._element);\n        this.cycle(true);\n      }\n\n      clearInterval(this._interval);\n      this._interval = null;\n    };\n\n    _proto.cycle = function cycle(event) {\n      if (!event) {\n        this._isPaused = false;\n      }\n\n      if (this._interval) {\n        clearInterval(this._interval);\n        this._interval = null;\n      }\n\n      if (this._config.interval && !this._isPaused) {\n        this._interval = setInterval((document.visibilityState ? this.nextWhenVisible : this.next).bind(this), this._config.interval);\n      }\n    };\n\n    _proto.to = function to(index) {\n      var _this = this;\n\n      this._activeElement = this._element.querySelector(SELECTOR_ACTIVE_ITEM);\n\n      var activeIndex = this._getItemIndex(this._activeElement);\n\n      if (index > this._items.length - 1 || index < 0) {\n        return;\n      }\n\n      if (this._isSliding) {\n        $__default['default'](this._element).one(EVENT_SLID, function () {\n          return _this.to(index);\n        });\n        return;\n      }\n\n      if (activeIndex === index) {\n        this.pause();\n        this.cycle();\n        return;\n      }\n\n      var direction = index > activeIndex ? DIRECTION_NEXT : DIRECTION_PREV;\n\n      this._slide(direction, this._items[index]);\n    };\n\n    _proto.dispose = function dispose() {\n      $__default['default'](this._element).off(EVENT_KEY$2);\n      $__default['default'].removeData(this._element, DATA_KEY$2);\n      this._items = null;\n      this._config = null;\n      this._element = null;\n      this._interval = null;\n      this._isPaused = null;\n      this._isSliding = null;\n      this._activeElement = null;\n      this._indicatorsElement = null;\n    } // Private\n    ;\n\n    _proto._getConfig = function _getConfig(config) {\n      config = _extends({}, Default, config);\n      Util.typeCheckConfig(NAME$2, config, DefaultType);\n      return config;\n    };\n\n    _proto._handleSwipe = function _handleSwipe() {\n      var absDeltax = Math.abs(this.touchDeltaX);\n\n      if (absDeltax <= SWIPE_THRESHOLD) {\n        return;\n      }\n\n      var direction = absDeltax / this.touchDeltaX;\n      this.touchDeltaX = 0; // swipe left\n\n      if (direction > 0) {\n        this.prev();\n      } // swipe right\n\n\n      if (direction < 0) {\n        this.next();\n      }\n    };\n\n    _proto._addEventListeners = function _addEventListeners() {\n      var _this2 = this;\n\n      if (this._config.keyboard) {\n        $__default['default'](this._element).on(EVENT_KEYDOWN, function (event) {\n          return _this2._keydown(event);\n        });\n      }\n\n      if (this._config.pause === 'hover') {\n        $__default['default'](this._element).on(EVENT_MOUSEENTER, function (event) {\n          return _this2.pause(event);\n        }).on(EVENT_MOUSELEAVE, function (event) {\n          return _this2.cycle(event);\n        });\n      }\n\n      if (this._config.touch) {\n        this._addTouchEventListeners();\n      }\n    };\n\n    _proto._addTouchEventListeners = function _addTouchEventListeners() {\n      var _this3 = this;\n\n      if (!this._touchSupported) {\n        return;\n      }\n\n      var start = function start(event) {\n        if (_this3._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) {\n          _this3.touchStartX = event.originalEvent.clientX;\n        } else if (!_this3._pointerEvent) {\n          _this3.touchStartX = event.originalEvent.touches[0].clientX;\n        }\n      };\n\n      var move = function move(event) {\n        // ensure swiping with one touch and not pinching\n        if (event.originalEvent.touches && event.originalEvent.touches.length > 1) {\n          _this3.touchDeltaX = 0;\n        } else {\n          _this3.touchDeltaX = event.originalEvent.touches[0].clientX - _this3.touchStartX;\n        }\n      };\n\n      var end = function end(event) {\n        if (_this3._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) {\n          _this3.touchDeltaX = event.originalEvent.clientX - _this3.touchStartX;\n        }\n\n        _this3._handleSwipe();\n\n        if (_this3._config.pause === 'hover') {\n          // If it's a touch-enabled device, mouseenter/leave are fired as\n          // part of the mouse compatibility events on first tap - the carousel\n          // would stop cycling until user tapped out of it;\n          // here, we listen for touchend, explicitly pause the carousel\n          // (as if it's the second time we tap on it, mouseenter compat event\n          // is NOT fired) and after a timeout (to allow for mouse compatibility\n          // events to fire) we explicitly restart cycling\n          _this3.pause();\n\n          if (_this3.touchTimeout) {\n            clearTimeout(_this3.touchTimeout);\n          }\n\n          _this3.touchTimeout = setTimeout(function (event) {\n            return _this3.cycle(event);\n          }, TOUCHEVENT_COMPAT_WAIT + _this3._config.interval);\n        }\n      };\n\n      $__default['default'](this._element.querySelectorAll(SELECTOR_ITEM_IMG)).on(EVENT_DRAG_START, function (e) {\n        return e.preventDefault();\n      });\n\n      if (this._pointerEvent) {\n        $__default['default'](this._element).on(EVENT_POINTERDOWN, function (event) {\n          return start(event);\n        });\n        $__default['default'](this._element).on(EVENT_POINTERUP, function (event) {\n          return end(event);\n        });\n\n        this._element.classList.add(CLASS_NAME_POINTER_EVENT);\n      } else {\n        $__default['default'](this._element).on(EVENT_TOUCHSTART, function (event) {\n          return start(event);\n        });\n        $__default['default'](this._element).on(EVENT_TOUCHMOVE, function (event) {\n          return move(event);\n        });\n        $__default['default'](this._element).on(EVENT_TOUCHEND, function (event) {\n          return end(event);\n        });\n      }\n    };\n\n    _proto._keydown = function _keydown(event) {\n      if (/input|textarea/i.test(event.target.tagName)) {\n        return;\n      }\n\n      switch (event.which) {\n        case ARROW_LEFT_KEYCODE:\n          event.preventDefault();\n          this.prev();\n          break;\n\n        case ARROW_RIGHT_KEYCODE:\n          event.preventDefault();\n          this.next();\n          break;\n      }\n    };\n\n    _proto._getItemIndex = function _getItemIndex(element) {\n      this._items = element && element.parentNode ? [].slice.call(element.parentNode.querySelectorAll(SELECTOR_ITEM)) : [];\n      return this._items.indexOf(element);\n    };\n\n    _proto._getItemByDirection = function _getItemByDirection(direction, activeElement) {\n      var isNextDirection = direction === DIRECTION_NEXT;\n      var isPrevDirection = direction === DIRECTION_PREV;\n\n      var activeIndex = this._getItemIndex(activeElement);\n\n      var lastItemIndex = this._items.length - 1;\n      var isGoingToWrap = isPrevDirection && activeIndex === 0 || isNextDirection && activeIndex === lastItemIndex;\n\n      if (isGoingToWrap && !this._config.wrap) {\n        return activeElement;\n      }\n\n      var delta = direction === DIRECTION_PREV ? -1 : 1;\n      var itemIndex = (activeIndex + delta) % this._items.length;\n      return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex];\n    };\n\n    _proto._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, eventDirectionName) {\n      var targetIndex = this._getItemIndex(relatedTarget);\n\n      var fromIndex = this._getItemIndex(this._element.querySelector(SELECTOR_ACTIVE_ITEM));\n\n      var slideEvent = $__default['default'].Event(EVENT_SLIDE, {\n        relatedTarget: relatedTarget,\n        direction: eventDirectionName,\n        from: fromIndex,\n        to: targetIndex\n      });\n      $__default['default'](this._element).trigger(slideEvent);\n      return slideEvent;\n    };\n\n    _proto._setActiveIndicatorElement = function _setActiveIndicatorElement(element) {\n      if (this._indicatorsElement) {\n        var indicators = [].slice.call(this._indicatorsElement.querySelectorAll(SELECTOR_ACTIVE$1));\n        $__default['default'](indicators).removeClass(CLASS_NAME_ACTIVE$1);\n\n        var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)];\n\n        if (nextIndicator) {\n          $__default['default'](nextIndicator).addClass(CLASS_NAME_ACTIVE$1);\n        }\n      }\n    };\n\n    _proto._slide = function _slide(direction, element) {\n      var _this4 = this;\n\n      var activeElement = this._element.querySelector(SELECTOR_ACTIVE_ITEM);\n\n      var activeElementIndex = this._getItemIndex(activeElement);\n\n      var nextElement = element || activeElement && this._getItemByDirection(direction, activeElement);\n\n      var nextElementIndex = this._getItemIndex(nextElement);\n\n      var isCycling = Boolean(this._interval);\n      var directionalClassName;\n      var orderClassName;\n      var eventDirectionName;\n\n      if (direction === DIRECTION_NEXT) {\n        directionalClassName = CLASS_NAME_LEFT;\n        orderClassName = CLASS_NAME_NEXT;\n        eventDirectionName = DIRECTION_LEFT;\n      } else {\n        directionalClassName = CLASS_NAME_RIGHT;\n        orderClassName = CLASS_NAME_PREV;\n        eventDirectionName = DIRECTION_RIGHT;\n      }\n\n      if (nextElement && $__default['default'](nextElement).hasClass(CLASS_NAME_ACTIVE$1)) {\n        this._isSliding = false;\n        return;\n      }\n\n      var slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName);\n\n      if (slideEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      if (!activeElement || !nextElement) {\n        // Some weirdness is happening, so we bail\n        return;\n      }\n\n      this._isSliding = true;\n\n      if (isCycling) {\n        this.pause();\n      }\n\n      this._setActiveIndicatorElement(nextElement);\n\n      var slidEvent = $__default['default'].Event(EVENT_SLID, {\n        relatedTarget: nextElement,\n        direction: eventDirectionName,\n        from: activeElementIndex,\n        to: nextElementIndex\n      });\n\n      if ($__default['default'](this._element).hasClass(CLASS_NAME_SLIDE)) {\n        $__default['default'](nextElement).addClass(orderClassName);\n        Util.reflow(nextElement);\n        $__default['default'](activeElement).addClass(directionalClassName);\n        $__default['default'](nextElement).addClass(directionalClassName);\n        var nextElementInterval = parseInt(nextElement.getAttribute('data-interval'), 10);\n\n        if (nextElementInterval) {\n          this._config.defaultInterval = this._config.defaultInterval || this._config.interval;\n          this._config.interval = nextElementInterval;\n        } else {\n          this._config.interval = this._config.defaultInterval || this._config.interval;\n        }\n\n        var transitionDuration = Util.getTransitionDurationFromElement(activeElement);\n        $__default['default'](activeElement).one(Util.TRANSITION_END, function () {\n          $__default['default'](nextElement).removeClass(directionalClassName + \" \" + orderClassName).addClass(CLASS_NAME_ACTIVE$1);\n          $__default['default'](activeElement).removeClass(CLASS_NAME_ACTIVE$1 + \" \" + orderClassName + \" \" + directionalClassName);\n          _this4._isSliding = false;\n          setTimeout(function () {\n            return $__default['default'](_this4._element).trigger(slidEvent);\n          }, 0);\n        }).emulateTransitionEnd(transitionDuration);\n      } else {\n        $__default['default'](activeElement).removeClass(CLASS_NAME_ACTIVE$1);\n        $__default['default'](nextElement).addClass(CLASS_NAME_ACTIVE$1);\n        this._isSliding = false;\n        $__default['default'](this._element).trigger(slidEvent);\n      }\n\n      if (isCycling) {\n        this.cycle();\n      }\n    } // Static\n    ;\n\n    Carousel._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var data = $__default['default'](this).data(DATA_KEY$2);\n\n        var _config = _extends({}, Default, $__default['default'](this).data());\n\n        if (typeof config === 'object') {\n          _config = _extends({}, _config, config);\n        }\n\n        var action = typeof config === 'string' ? config : _config.slide;\n\n        if (!data) {\n          data = new Carousel(this, _config);\n          $__default['default'](this).data(DATA_KEY$2, data);\n        }\n\n        if (typeof config === 'number') {\n          data.to(config);\n        } else if (typeof action === 'string') {\n          if (typeof data[action] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + action + \"\\\"\");\n          }\n\n          data[action]();\n        } else if (_config.interval && _config.ride) {\n          data.pause();\n          data.cycle();\n        }\n      });\n    };\n\n    Carousel._dataApiClickHandler = function _dataApiClickHandler(event) {\n      var selector = Util.getSelectorFromElement(this);\n\n      if (!selector) {\n        return;\n      }\n\n      var target = $__default['default'](selector)[0];\n\n      if (!target || !$__default['default'](target).hasClass(CLASS_NAME_CAROUSEL)) {\n        return;\n      }\n\n      var config = _extends({}, $__default['default'](target).data(), $__default['default'](this).data());\n\n      var slideIndex = this.getAttribute('data-slide-to');\n\n      if (slideIndex) {\n        config.interval = false;\n      }\n\n      Carousel._jQueryInterface.call($__default['default'](target), config);\n\n      if (slideIndex) {\n        $__default['default'](target).data(DATA_KEY$2).to(slideIndex);\n      }\n\n      event.preventDefault();\n    };\n\n    _createClass(Carousel, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION$2;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default;\n      }\n    }]);\n\n    return Carousel;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $__default['default'](document).on(EVENT_CLICK_DATA_API$2, SELECTOR_DATA_SLIDE, Carousel._dataApiClickHandler);\n  $__default['default'](window).on(EVENT_LOAD_DATA_API$1, function () {\n    var carousels = [].slice.call(document.querySelectorAll(SELECTOR_DATA_RIDE));\n\n    for (var i = 0, len = carousels.length; i < len; i++) {\n      var $carousel = $__default['default'](carousels[i]);\n\n      Carousel._jQueryInterface.call($carousel, $carousel.data());\n    }\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $__default['default'].fn[NAME$2] = Carousel._jQueryInterface;\n  $__default['default'].fn[NAME$2].Constructor = Carousel;\n\n  $__default['default'].fn[NAME$2].noConflict = function () {\n    $__default['default'].fn[NAME$2] = JQUERY_NO_CONFLICT$2;\n    return Carousel._jQueryInterface;\n  };\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME$3 = 'collapse';\n  var VERSION$3 = '4.5.3';\n  var DATA_KEY$3 = 'bs.collapse';\n  var EVENT_KEY$3 = \".\" + DATA_KEY$3;\n  var DATA_API_KEY$3 = '.data-api';\n  var JQUERY_NO_CONFLICT$3 = $__default['default'].fn[NAME$3];\n  var Default$1 = {\n    toggle: true,\n    parent: ''\n  };\n  var DefaultType$1 = {\n    toggle: 'boolean',\n    parent: '(string|element)'\n  };\n  var EVENT_SHOW = \"show\" + EVENT_KEY$3;\n  var EVENT_SHOWN = \"shown\" + EVENT_KEY$3;\n  var EVENT_HIDE = \"hide\" + EVENT_KEY$3;\n  var EVENT_HIDDEN = \"hidden\" + EVENT_KEY$3;\n  var EVENT_CLICK_DATA_API$3 = \"click\" + EVENT_KEY$3 + DATA_API_KEY$3;\n  var CLASS_NAME_SHOW$1 = 'show';\n  var CLASS_NAME_COLLAPSE = 'collapse';\n  var CLASS_NAME_COLLAPSING = 'collapsing';\n  var CLASS_NAME_COLLAPSED = 'collapsed';\n  var DIMENSION_WIDTH = 'width';\n  var DIMENSION_HEIGHT = 'height';\n  var SELECTOR_ACTIVES = '.show, .collapsing';\n  var SELECTOR_DATA_TOGGLE$1 = '[data-toggle=\"collapse\"]';\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  var Collapse = /*#__PURE__*/function () {\n    function Collapse(element, config) {\n      this._isTransitioning = false;\n      this._element = element;\n      this._config = this._getConfig(config);\n      this._triggerArray = [].slice.call(document.querySelectorAll(\"[data-toggle=\\\"collapse\\\"][href=\\\"#\" + element.id + \"\\\"],\" + (\"[data-toggle=\\\"collapse\\\"][data-target=\\\"#\" + element.id + \"\\\"]\")));\n      var toggleList = [].slice.call(document.querySelectorAll(SELECTOR_DATA_TOGGLE$1));\n\n      for (var i = 0, len = toggleList.length; i < len; i++) {\n        var elem = toggleList[i];\n        var selector = Util.getSelectorFromElement(elem);\n        var filterElement = [].slice.call(document.querySelectorAll(selector)).filter(function (foundElem) {\n          return foundElem === element;\n        });\n\n        if (selector !== null && filterElement.length > 0) {\n          this._selector = selector;\n\n          this._triggerArray.push(elem);\n        }\n      }\n\n      this._parent = this._config.parent ? this._getParent() : null;\n\n      if (!this._config.parent) {\n        this._addAriaAndCollapsedClass(this._element, this._triggerArray);\n      }\n\n      if (this._config.toggle) {\n        this.toggle();\n      }\n    } // Getters\n\n\n    var _proto = Collapse.prototype;\n\n    // Public\n    _proto.toggle = function toggle() {\n      if ($__default['default'](this._element).hasClass(CLASS_NAME_SHOW$1)) {\n        this.hide();\n      } else {\n        this.show();\n      }\n    };\n\n    _proto.show = function show() {\n      var _this = this;\n\n      if (this._isTransitioning || $__default['default'](this._element).hasClass(CLASS_NAME_SHOW$1)) {\n        return;\n      }\n\n      var actives;\n      var activesData;\n\n      if (this._parent) {\n        actives = [].slice.call(this._parent.querySelectorAll(SELECTOR_ACTIVES)).filter(function (elem) {\n          if (typeof _this._config.parent === 'string') {\n            return elem.getAttribute('data-parent') === _this._config.parent;\n          }\n\n          return elem.classList.contains(CLASS_NAME_COLLAPSE);\n        });\n\n        if (actives.length === 0) {\n          actives = null;\n        }\n      }\n\n      if (actives) {\n        activesData = $__default['default'](actives).not(this._selector).data(DATA_KEY$3);\n\n        if (activesData && activesData._isTransitioning) {\n          return;\n        }\n      }\n\n      var startEvent = $__default['default'].Event(EVENT_SHOW);\n      $__default['default'](this._element).trigger(startEvent);\n\n      if (startEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      if (actives) {\n        Collapse._jQueryInterface.call($__default['default'](actives).not(this._selector), 'hide');\n\n        if (!activesData) {\n          $__default['default'](actives).data(DATA_KEY$3, null);\n        }\n      }\n\n      var dimension = this._getDimension();\n\n      $__default['default'](this._element).removeClass(CLASS_NAME_COLLAPSE).addClass(CLASS_NAME_COLLAPSING);\n      this._element.style[dimension] = 0;\n\n      if (this._triggerArray.length) {\n        $__default['default'](this._triggerArray).removeClass(CLASS_NAME_COLLAPSED).attr('aria-expanded', true);\n      }\n\n      this.setTransitioning(true);\n\n      var complete = function complete() {\n        $__default['default'](_this._element).removeClass(CLASS_NAME_COLLAPSING).addClass(CLASS_NAME_COLLAPSE + \" \" + CLASS_NAME_SHOW$1);\n        _this._element.style[dimension] = '';\n\n        _this.setTransitioning(false);\n\n        $__default['default'](_this._element).trigger(EVENT_SHOWN);\n      };\n\n      var capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1);\n      var scrollSize = \"scroll\" + capitalizedDimension;\n      var transitionDuration = Util.getTransitionDurationFromElement(this._element);\n      $__default['default'](this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);\n      this._element.style[dimension] = this._element[scrollSize] + \"px\";\n    };\n\n    _proto.hide = function hide() {\n      var _this2 = this;\n\n      if (this._isTransitioning || !$__default['default'](this._element).hasClass(CLASS_NAME_SHOW$1)) {\n        return;\n      }\n\n      var startEvent = $__default['default'].Event(EVENT_HIDE);\n      $__default['default'](this._element).trigger(startEvent);\n\n      if (startEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      var dimension = this._getDimension();\n\n      this._element.style[dimension] = this._element.getBoundingClientRect()[dimension] + \"px\";\n      Util.reflow(this._element);\n      $__default['default'](this._element).addClass(CLASS_NAME_COLLAPSING).removeClass(CLASS_NAME_COLLAPSE + \" \" + CLASS_NAME_SHOW$1);\n      var triggerArrayLength = this._triggerArray.length;\n\n      if (triggerArrayLength > 0) {\n        for (var i = 0; i < triggerArrayLength; i++) {\n          var trigger = this._triggerArray[i];\n          var selector = Util.getSelectorFromElement(trigger);\n\n          if (selector !== null) {\n            var $elem = $__default['default']([].slice.call(document.querySelectorAll(selector)));\n\n            if (!$elem.hasClass(CLASS_NAME_SHOW$1)) {\n              $__default['default'](trigger).addClass(CLASS_NAME_COLLAPSED).attr('aria-expanded', false);\n            }\n          }\n        }\n      }\n\n      this.setTransitioning(true);\n\n      var complete = function complete() {\n        _this2.setTransitioning(false);\n\n        $__default['default'](_this2._element).removeClass(CLASS_NAME_COLLAPSING).addClass(CLASS_NAME_COLLAPSE).trigger(EVENT_HIDDEN);\n      };\n\n      this._element.style[dimension] = '';\n      var transitionDuration = Util.getTransitionDurationFromElement(this._element);\n      $__default['default'](this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);\n    };\n\n    _proto.setTransitioning = function setTransitioning(isTransitioning) {\n      this._isTransitioning = isTransitioning;\n    };\n\n    _proto.dispose = function dispose() {\n      $__default['default'].removeData(this._element, DATA_KEY$3);\n      this._config = null;\n      this._parent = null;\n      this._element = null;\n      this._triggerArray = null;\n      this._isTransitioning = null;\n    } // Private\n    ;\n\n    _proto._getConfig = function _getConfig(config) {\n      config = _extends({}, Default$1, config);\n      config.toggle = Boolean(config.toggle); // Coerce string values\n\n      Util.typeCheckConfig(NAME$3, config, DefaultType$1);\n      return config;\n    };\n\n    _proto._getDimension = function _getDimension() {\n      var hasWidth = $__default['default'](this._element).hasClass(DIMENSION_WIDTH);\n      return hasWidth ? DIMENSION_WIDTH : DIMENSION_HEIGHT;\n    };\n\n    _proto._getParent = function _getParent() {\n      var _this3 = this;\n\n      var parent;\n\n      if (Util.isElement(this._config.parent)) {\n        parent = this._config.parent; // It's a jQuery object\n\n        if (typeof this._config.parent.jquery !== 'undefined') {\n          parent = this._config.parent[0];\n        }\n      } else {\n        parent = document.querySelector(this._config.parent);\n      }\n\n      var selector = \"[data-toggle=\\\"collapse\\\"][data-parent=\\\"\" + this._config.parent + \"\\\"]\";\n      var children = [].slice.call(parent.querySelectorAll(selector));\n      $__default['default'](children).each(function (i, element) {\n        _this3._addAriaAndCollapsedClass(Collapse._getTargetFromElement(element), [element]);\n      });\n      return parent;\n    };\n\n    _proto._addAriaAndCollapsedClass = function _addAriaAndCollapsedClass(element, triggerArray) {\n      var isOpen = $__default['default'](element).hasClass(CLASS_NAME_SHOW$1);\n\n      if (triggerArray.length) {\n        $__default['default'](triggerArray).toggleClass(CLASS_NAME_COLLAPSED, !isOpen).attr('aria-expanded', isOpen);\n      }\n    } // Static\n    ;\n\n    Collapse._getTargetFromElement = function _getTargetFromElement(element) {\n      var selector = Util.getSelectorFromElement(element);\n      return selector ? document.querySelector(selector) : null;\n    };\n\n    Collapse._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var $element = $__default['default'](this);\n        var data = $element.data(DATA_KEY$3);\n\n        var _config = _extends({}, Default$1, $element.data(), typeof config === 'object' && config ? config : {});\n\n        if (!data && _config.toggle && typeof config === 'string' && /show|hide/.test(config)) {\n          _config.toggle = false;\n        }\n\n        if (!data) {\n          data = new Collapse(this, _config);\n          $element.data(DATA_KEY$3, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    _createClass(Collapse, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION$3;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default$1;\n      }\n    }]);\n\n    return Collapse;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $__default['default'](document).on(EVENT_CLICK_DATA_API$3, SELECTOR_DATA_TOGGLE$1, function (event) {\n    // preventDefault only for <a> elements (which change the URL) not inside the collapsible element\n    if (event.currentTarget.tagName === 'A') {\n      event.preventDefault();\n    }\n\n    var $trigger = $__default['default'](this);\n    var selector = Util.getSelectorFromElement(this);\n    var selectors = [].slice.call(document.querySelectorAll(selector));\n    $__default['default'](selectors).each(function () {\n      var $target = $__default['default'](this);\n      var data = $target.data(DATA_KEY$3);\n      var config = data ? 'toggle' : $trigger.data();\n\n      Collapse._jQueryInterface.call($target, config);\n    });\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $__default['default'].fn[NAME$3] = Collapse._jQueryInterface;\n  $__default['default'].fn[NAME$3].Constructor = Collapse;\n\n  $__default['default'].fn[NAME$3].noConflict = function () {\n    $__default['default'].fn[NAME$3] = JQUERY_NO_CONFLICT$3;\n    return Collapse._jQueryInterface;\n  };\n\n  /**!\n   * @fileOverview Kickass library to create and place poppers near their reference elements.\n   * @version 1.16.1\n   * @license\n   * Copyright (c) 2016 Federico Zivolo and contributors\n   *\n   * Permission is hereby granted, free of charge, to any person obtaining a copy\n   * of this software and associated documentation files (the \"Software\"), to deal\n   * in the Software without restriction, including without limitation the rights\n   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n   * copies of the Software, and to permit persons to whom the Software is\n   * furnished to do so, subject to the following conditions:\n   *\n   * The above copyright notice and this permission notice shall be included in all\n   * copies or substantial portions of the Software.\n   *\n   * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n   * SOFTWARE.\n   */\n  var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined' && typeof navigator !== 'undefined';\n\n  var timeoutDuration = function () {\n    var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];\n    for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) {\n      if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) {\n        return 1;\n      }\n    }\n    return 0;\n  }();\n\n  function microtaskDebounce(fn) {\n    var called = false;\n    return function () {\n      if (called) {\n        return;\n      }\n      called = true;\n      window.Promise.resolve().then(function () {\n        called = false;\n        fn();\n      });\n    };\n  }\n\n  function taskDebounce(fn) {\n    var scheduled = false;\n    return function () {\n      if (!scheduled) {\n        scheduled = true;\n        setTimeout(function () {\n          scheduled = false;\n          fn();\n        }, timeoutDuration);\n      }\n    };\n  }\n\n  var supportsMicroTasks = isBrowser && window.Promise;\n\n  /**\n  * Create a debounced version of a method, that's asynchronously deferred\n  * but called in the minimum time possible.\n  *\n  * @method\n  * @memberof Popper.Utils\n  * @argument {Function} fn\n  * @returns {Function}\n  */\n  var debounce = supportsMicroTasks ? microtaskDebounce : taskDebounce;\n\n  /**\n   * Check if the given variable is a function\n   * @method\n   * @memberof Popper.Utils\n   * @argument {Any} functionToCheck - variable to check\n   * @returns {Boolean} answer to: is a function?\n   */\n  function isFunction(functionToCheck) {\n    var getType = {};\n    return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';\n  }\n\n  /**\n   * Get CSS computed property of the given element\n   * @method\n   * @memberof Popper.Utils\n   * @argument {Eement} element\n   * @argument {String} property\n   */\n  function getStyleComputedProperty(element, property) {\n    if (element.nodeType !== 1) {\n      return [];\n    }\n    // NOTE: 1 DOM access here\n    var window = element.ownerDocument.defaultView;\n    var css = window.getComputedStyle(element, null);\n    return property ? css[property] : css;\n  }\n\n  /**\n   * Returns the parentNode or the host of the element\n   * @method\n   * @memberof Popper.Utils\n   * @argument {Element} element\n   * @returns {Element} parent\n   */\n  function getParentNode(element) {\n    if (element.nodeName === 'HTML') {\n      return element;\n    }\n    return element.parentNode || element.host;\n  }\n\n  /**\n   * Returns the scrolling parent of the given element\n   * @method\n   * @memberof Popper.Utils\n   * @argument {Element} element\n   * @returns {Element} scroll parent\n   */\n  function getScrollParent(element) {\n    // Return body, `getScroll` will take care to get the correct `scrollTop` from it\n    if (!element) {\n      return document.body;\n    }\n\n    switch (element.nodeName) {\n      case 'HTML':\n      case 'BODY':\n        return element.ownerDocument.body;\n      case '#document':\n        return element.body;\n    }\n\n    // Firefox want us to check `-x` and `-y` variations as well\n\n    var _getStyleComputedProp = getStyleComputedProperty(element),\n        overflow = _getStyleComputedProp.overflow,\n        overflowX = _getStyleComputedProp.overflowX,\n        overflowY = _getStyleComputedProp.overflowY;\n\n    if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) {\n      return element;\n    }\n\n    return getScrollParent(getParentNode(element));\n  }\n\n  /**\n   * Returns the reference node of the reference object, or the reference object itself.\n   * @method\n   * @memberof Popper.Utils\n   * @param {Element|Object} reference - the reference element (the popper will be relative to this)\n   * @returns {Element} parent\n   */\n  function getReferenceNode(reference) {\n    return reference && reference.referenceNode ? reference.referenceNode : reference;\n  }\n\n  var isIE11 = isBrowser && !!(window.MSInputMethodContext && document.documentMode);\n  var isIE10 = isBrowser && /MSIE 10/.test(navigator.userAgent);\n\n  /**\n   * Determines if the browser is Internet Explorer\n   * @method\n   * @memberof Popper.Utils\n   * @param {Number} version to check\n   * @returns {Boolean} isIE\n   */\n  function isIE(version) {\n    if (version === 11) {\n      return isIE11;\n    }\n    if (version === 10) {\n      return isIE10;\n    }\n    return isIE11 || isIE10;\n  }\n\n  /**\n   * Returns the offset parent of the given element\n   * @method\n   * @memberof Popper.Utils\n   * @argument {Element} element\n   * @returns {Element} offset parent\n   */\n  function getOffsetParent(element) {\n    if (!element) {\n      return document.documentElement;\n    }\n\n    var noOffsetParent = isIE(10) ? document.body : null;\n\n    // NOTE: 1 DOM access here\n    var offsetParent = element.offsetParent || null;\n    // Skip hidden elements which don't have an offsetParent\n    while (offsetParent === noOffsetParent && element.nextElementSibling) {\n      offsetParent = (element = element.nextElementSibling).offsetParent;\n    }\n\n    var nodeName = offsetParent && offsetParent.nodeName;\n\n    if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') {\n      return element ? element.ownerDocument.documentElement : document.documentElement;\n    }\n\n    // .offsetParent will return the closest TH, TD or TABLE in case\n    // no offsetParent is present, I hate this job...\n    if (['TH', 'TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') {\n      return getOffsetParent(offsetParent);\n    }\n\n    return offsetParent;\n  }\n\n  function isOffsetContainer(element) {\n    var nodeName = element.nodeName;\n\n    if (nodeName === 'BODY') {\n      return false;\n    }\n    return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element;\n  }\n\n  /**\n   * Finds the root node (document, shadowDOM root) of the given element\n   * @method\n   * @memberof Popper.Utils\n   * @argument {Element} node\n   * @returns {Element} root node\n   */\n  function getRoot(node) {\n    if (node.parentNode !== null) {\n      return getRoot(node.parentNode);\n    }\n\n    return node;\n  }\n\n  /**\n   * Finds the offset parent common to the two provided nodes\n   * @method\n   * @memberof Popper.Utils\n   * @argument {Element} element1\n   * @argument {Element} element2\n   * @returns {Element} common offset parent\n   */\n  function findCommonOffsetParent(element1, element2) {\n    // This check is needed to avoid errors in case one of the elements isn't defined for any reason\n    if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {\n      return document.documentElement;\n    }\n\n    // Here we make sure to give as \"start\" the element that comes first in the DOM\n    var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING;\n    var start = order ? element1 : element2;\n    var end = order ? element2 : element1;\n\n    // Get common ancestor container\n    var range = document.createRange();\n    range.setStart(start, 0);\n    range.setEnd(end, 0);\n    var commonAncestorContainer = range.commonAncestorContainer;\n\n    // Both nodes are inside #document\n\n    if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) {\n      if (isOffsetContainer(commonAncestorContainer)) {\n        return commonAncestorContainer;\n      }\n\n      return getOffsetParent(commonAncestorContainer);\n    }\n\n    // one of the nodes is inside shadowDOM, find which one\n    var element1root = getRoot(element1);\n    if (element1root.host) {\n      return findCommonOffsetParent(element1root.host, element2);\n    } else {\n      return findCommonOffsetParent(element1, getRoot(element2).host);\n    }\n  }\n\n  /**\n   * Gets the scroll value of the given element in the given side (top and left)\n   * @method\n   * @memberof Popper.Utils\n   * @argument {Element} element\n   * @argument {String} side `top` or `left`\n   * @returns {number} amount of scrolled pixels\n   */\n  function getScroll(element) {\n    var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top';\n\n    var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft';\n    var nodeName = element.nodeName;\n\n    if (nodeName === 'BODY' || nodeName === 'HTML') {\n      var html = element.ownerDocument.documentElement;\n      var scrollingElement = element.ownerDocument.scrollingElement || html;\n      return scrollingElement[upperSide];\n    }\n\n    return element[upperSide];\n  }\n\n  /*\n   * Sum or subtract the element scroll values (left and top) from a given rect object\n   * @method\n   * @memberof Popper.Utils\n   * @param {Object} rect - Rect object you want to change\n   * @param {HTMLElement} element - The element from the function reads the scroll values\n   * @param {Boolean} subtract - set to true if you want to subtract the scroll values\n   * @return {Object} rect - The modifier rect object\n   */\n  function includeScroll(rect, element) {\n    var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n\n    var scrollTop = getScroll(element, 'top');\n    var scrollLeft = getScroll(element, 'left');\n    var modifier = subtract ? -1 : 1;\n    rect.top += scrollTop * modifier;\n    rect.bottom += scrollTop * modifier;\n    rect.left += scrollLeft * modifier;\n    rect.right += scrollLeft * modifier;\n    return rect;\n  }\n\n  /*\n   * Helper to detect borders of a given element\n   * @method\n   * @memberof Popper.Utils\n   * @param {CSSStyleDeclaration} styles\n   * Result of `getStyleComputedProperty` on the given element\n   * @param {String} axis - `x` or `y`\n   * @return {number} borders - The borders size of the given axis\n   */\n\n  function getBordersSize(styles, axis) {\n    var sideA = axis === 'x' ? 'Left' : 'Top';\n    var sideB = sideA === 'Left' ? 'Right' : 'Bottom';\n\n    return parseFloat(styles['border' + sideA + 'Width']) + parseFloat(styles['border' + sideB + 'Width']);\n  }\n\n  function getSize(axis, body, html, computedStyle) {\n    return Math.max(body['offset' + axis], body['scroll' + axis], html['client' + axis], html['offset' + axis], html['scroll' + axis], isIE(10) ? parseInt(html['offset' + axis]) + parseInt(computedStyle['margin' + (axis === 'Height' ? 'Top' : 'Left')]) + parseInt(computedStyle['margin' + (axis === 'Height' ? 'Bottom' : 'Right')]) : 0);\n  }\n\n  function getWindowSizes(document) {\n    var body = document.body;\n    var html = document.documentElement;\n    var computedStyle = isIE(10) && getComputedStyle(html);\n\n    return {\n      height: getSize('Height', body, html, computedStyle),\n      width: getSize('Width', body, html, computedStyle)\n    };\n  }\n\n  var classCallCheck = function (instance, Constructor) {\n    if (!(instance instanceof Constructor)) {\n      throw new TypeError(\"Cannot call a class as a function\");\n    }\n  };\n\n  var createClass = function () {\n    function 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\n    return function (Constructor, protoProps, staticProps) {\n      if (protoProps) defineProperties(Constructor.prototype, protoProps);\n      if (staticProps) defineProperties(Constructor, staticProps);\n      return Constructor;\n    };\n  }();\n\n\n\n\n\n  var defineProperty = function (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  var _extends$1 = Object.assign || function (target) {\n    for (var i = 1; i < arguments.length; i++) {\n      var source = arguments[i];\n\n      for (var key in source) {\n        if (Object.prototype.hasOwnProperty.call(source, key)) {\n          target[key] = source[key];\n        }\n      }\n    }\n\n    return target;\n  };\n\n  /**\n   * Given element offsets, generate an output similar to getBoundingClientRect\n   * @method\n   * @memberof Popper.Utils\n   * @argument {Object} offsets\n   * @returns {Object} ClientRect like output\n   */\n  function getClientRect(offsets) {\n    return _extends$1({}, offsets, {\n      right: offsets.left + offsets.width,\n      bottom: offsets.top + offsets.height\n    });\n  }\n\n  /**\n   * Get bounding client rect of given element\n   * @method\n   * @memberof Popper.Utils\n   * @param {HTMLElement} element\n   * @return {Object} client rect\n   */\n  function getBoundingClientRect(element) {\n    var rect = {};\n\n    // IE10 10 FIX: Please, don't ask, the element isn't\n    // considered in DOM in some circumstances...\n    // This isn't reproducible in IE10 compatibility mode of IE11\n    try {\n      if (isIE(10)) {\n        rect = element.getBoundingClientRect();\n        var scrollTop = getScroll(element, 'top');\n        var scrollLeft = getScroll(element, 'left');\n        rect.top += scrollTop;\n        rect.left += scrollLeft;\n        rect.bottom += scrollTop;\n        rect.right += scrollLeft;\n      } else {\n        rect = element.getBoundingClientRect();\n      }\n    } catch (e) {}\n\n    var result = {\n      left: rect.left,\n      top: rect.top,\n      width: rect.right - rect.left,\n      height: rect.bottom - rect.top\n    };\n\n    // subtract scrollbar size from sizes\n    var sizes = element.nodeName === 'HTML' ? getWindowSizes(element.ownerDocument) : {};\n    var width = sizes.width || element.clientWidth || result.width;\n    var height = sizes.height || element.clientHeight || result.height;\n\n    var horizScrollbar = element.offsetWidth - width;\n    var vertScrollbar = element.offsetHeight - height;\n\n    // if an hypothetical scrollbar is detected, we must be sure it's not a `border`\n    // we make this check conditional for performance reasons\n    if (horizScrollbar || vertScrollbar) {\n      var styles = getStyleComputedProperty(element);\n      horizScrollbar -= getBordersSize(styles, 'x');\n      vertScrollbar -= getBordersSize(styles, 'y');\n\n      result.width -= horizScrollbar;\n      result.height -= vertScrollbar;\n    }\n\n    return getClientRect(result);\n  }\n\n  function getOffsetRectRelativeToArbitraryNode(children, parent) {\n    var fixedPosition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n\n    var isIE10 = isIE(10);\n    var isHTML = parent.nodeName === 'HTML';\n    var childrenRect = getBoundingClientRect(children);\n    var parentRect = getBoundingClientRect(parent);\n    var scrollParent = getScrollParent(children);\n\n    var styles = getStyleComputedProperty(parent);\n    var borderTopWidth = parseFloat(styles.borderTopWidth);\n    var borderLeftWidth = parseFloat(styles.borderLeftWidth);\n\n    // In cases where the parent is fixed, we must ignore negative scroll in offset calc\n    if (fixedPosition && isHTML) {\n      parentRect.top = Math.max(parentRect.top, 0);\n      parentRect.left = Math.max(parentRect.left, 0);\n    }\n    var offsets = getClientRect({\n      top: childrenRect.top - parentRect.top - borderTopWidth,\n      left: childrenRect.left - parentRect.left - borderLeftWidth,\n      width: childrenRect.width,\n      height: childrenRect.height\n    });\n    offsets.marginTop = 0;\n    offsets.marginLeft = 0;\n\n    // Subtract margins of documentElement in case it's being used as parent\n    // we do this only on HTML because it's the only element that behaves\n    // differently when margins are applied to it. The margins are included in\n    // the box of the documentElement, in the other cases not.\n    if (!isIE10 && isHTML) {\n      var marginTop = parseFloat(styles.marginTop);\n      var marginLeft = parseFloat(styles.marginLeft);\n\n      offsets.top -= borderTopWidth - marginTop;\n      offsets.bottom -= borderTopWidth - marginTop;\n      offsets.left -= borderLeftWidth - marginLeft;\n      offsets.right -= borderLeftWidth - marginLeft;\n\n      // Attach marginTop and marginLeft because in some circumstances we may need them\n      offsets.marginTop = marginTop;\n      offsets.marginLeft = marginLeft;\n    }\n\n    if (isIE10 && !fixedPosition ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') {\n      offsets = includeScroll(offsets, parent);\n    }\n\n    return offsets;\n  }\n\n  function getViewportOffsetRectRelativeToArtbitraryNode(element) {\n    var excludeScroll = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n\n    var html = element.ownerDocument.documentElement;\n    var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html);\n    var width = Math.max(html.clientWidth, window.innerWidth || 0);\n    var height = Math.max(html.clientHeight, window.innerHeight || 0);\n\n    var scrollTop = !excludeScroll ? getScroll(html) : 0;\n    var scrollLeft = !excludeScroll ? getScroll(html, 'left') : 0;\n\n    var offset = {\n      top: scrollTop - relativeOffset.top + relativeOffset.marginTop,\n      left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft,\n      width: width,\n      height: height\n    };\n\n    return getClientRect(offset);\n  }\n\n  /**\n   * Check if the given element is fixed or is inside a fixed parent\n   * @method\n   * @memberof Popper.Utils\n   * @argument {Element} element\n   * @argument {Element} customContainer\n   * @returns {Boolean} answer to \"isFixed?\"\n   */\n  function isFixed(element) {\n    var nodeName = element.nodeName;\n    if (nodeName === 'BODY' || nodeName === 'HTML') {\n      return false;\n    }\n    if (getStyleComputedProperty(element, 'position') === 'fixed') {\n      return true;\n    }\n    var parentNode = getParentNode(element);\n    if (!parentNode) {\n      return false;\n    }\n    return isFixed(parentNode);\n  }\n\n  /**\n   * Finds the first parent of an element that has a transformed property defined\n   * @method\n   * @memberof Popper.Utils\n   * @argument {Element} element\n   * @returns {Element} first transformed parent or documentElement\n   */\n\n  function getFixedPositionOffsetParent(element) {\n    // This check is needed to avoid errors in case one of the elements isn't defined for any reason\n    if (!element || !element.parentElement || isIE()) {\n      return document.documentElement;\n    }\n    var el = element.parentElement;\n    while (el && getStyleComputedProperty(el, 'transform') === 'none') {\n      el = el.parentElement;\n    }\n    return el || document.documentElement;\n  }\n\n  /**\n   * Computed the boundaries limits and return them\n   * @method\n   * @memberof Popper.Utils\n   * @param {HTMLElement} popper\n   * @param {HTMLElement} reference\n   * @param {number} padding\n   * @param {HTMLElement} boundariesElement - Element used to define the boundaries\n   * @param {Boolean} fixedPosition - Is in fixed position mode\n   * @returns {Object} Coordinates of the boundaries\n   */\n  function getBoundaries(popper, reference, padding, boundariesElement) {\n    var fixedPosition = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;\n\n    // NOTE: 1 DOM access here\n\n    var boundaries = { top: 0, left: 0 };\n    var offsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, getReferenceNode(reference));\n\n    // Handle viewport case\n    if (boundariesElement === 'viewport') {\n      boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent, fixedPosition);\n    } else {\n      // Handle other cases based on DOM element used as boundaries\n      var boundariesNode = void 0;\n      if (boundariesElement === 'scrollParent') {\n        boundariesNode = getScrollParent(getParentNode(reference));\n        if (boundariesNode.nodeName === 'BODY') {\n          boundariesNode = popper.ownerDocument.documentElement;\n        }\n      } else if (boundariesElement === 'window') {\n        boundariesNode = popper.ownerDocument.documentElement;\n      } else {\n        boundariesNode = boundariesElement;\n      }\n\n      var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent, fixedPosition);\n\n      // In case of HTML, we need a different computation\n      if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) {\n        var _getWindowSizes = getWindowSizes(popper.ownerDocument),\n            height = _getWindowSizes.height,\n            width = _getWindowSizes.width;\n\n        boundaries.top += offsets.top - offsets.marginTop;\n        boundaries.bottom = height + offsets.top;\n        boundaries.left += offsets.left - offsets.marginLeft;\n        boundaries.right = width + offsets.left;\n      } else {\n        // for all the other DOM elements, this one is good\n        boundaries = offsets;\n      }\n    }\n\n    // Add paddings\n    padding = padding || 0;\n    var isPaddingNumber = typeof padding === 'number';\n    boundaries.left += isPaddingNumber ? padding : padding.left || 0;\n    boundaries.top += isPaddingNumber ? padding : padding.top || 0;\n    boundaries.right -= isPaddingNumber ? padding : padding.right || 0;\n    boundaries.bottom -= isPaddingNumber ? padding : padding.bottom || 0;\n\n    return boundaries;\n  }\n\n  function getArea(_ref) {\n    var width = _ref.width,\n        height = _ref.height;\n\n    return width * height;\n  }\n\n  /**\n   * Utility used to transform the `auto` placement to the placement with more\n   * available space.\n   * @method\n   * @memberof Popper.Utils\n   * @argument {Object} data - The data object generated by update method\n   * @argument {Object} options - Modifiers configuration and options\n   * @returns {Object} The data object, properly modified\n   */\n  function computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) {\n    var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;\n\n    if (placement.indexOf('auto') === -1) {\n      return placement;\n    }\n\n    var boundaries = getBoundaries(popper, reference, padding, boundariesElement);\n\n    var rects = {\n      top: {\n        width: boundaries.width,\n        height: refRect.top - boundaries.top\n      },\n      right: {\n        width: boundaries.right - refRect.right,\n        height: boundaries.height\n      },\n      bottom: {\n        width: boundaries.width,\n        height: boundaries.bottom - refRect.bottom\n      },\n      left: {\n        width: refRect.left - boundaries.left,\n        height: boundaries.height\n      }\n    };\n\n    var sortedAreas = Object.keys(rects).map(function (key) {\n      return _extends$1({\n        key: key\n      }, rects[key], {\n        area: getArea(rects[key])\n      });\n    }).sort(function (a, b) {\n      return b.area - a.area;\n    });\n\n    var filteredAreas = sortedAreas.filter(function (_ref2) {\n      var width = _ref2.width,\n          height = _ref2.height;\n      return width >= popper.clientWidth && height >= popper.clientHeight;\n    });\n\n    var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key;\n\n    var variation = placement.split('-')[1];\n\n    return computedPlacement + (variation ? '-' + variation : '');\n  }\n\n  /**\n   * Get offsets to the reference element\n   * @method\n   * @memberof Popper.Utils\n   * @param {Object} state\n   * @param {Element} popper - the popper element\n   * @param {Element} reference - the reference element (the popper will be relative to this)\n   * @param {Element} fixedPosition - is in fixed position mode\n   * @returns {Object} An object containing the offsets which will be applied to the popper\n   */\n  function getReferenceOffsets(state, popper, reference) {\n    var fixedPosition = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;\n\n    var commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, getReferenceNode(reference));\n    return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent, fixedPosition);\n  }\n\n  /**\n   * Get the outer sizes of the given element (offset size + margins)\n   * @method\n   * @memberof Popper.Utils\n   * @argument {Element} element\n   * @returns {Object} object containing width and height properties\n   */\n  function getOuterSizes(element) {\n    var window = element.ownerDocument.defaultView;\n    var styles = window.getComputedStyle(element);\n    var x = parseFloat(styles.marginTop || 0) + parseFloat(styles.marginBottom || 0);\n    var y = parseFloat(styles.marginLeft || 0) + parseFloat(styles.marginRight || 0);\n    var result = {\n      width: element.offsetWidth + y,\n      height: element.offsetHeight + x\n    };\n    return result;\n  }\n\n  /**\n   * Get the opposite placement of the given one\n   * @method\n   * @memberof Popper.Utils\n   * @argument {String} placement\n   * @returns {String} flipped placement\n   */\n  function getOppositePlacement(placement) {\n    var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' };\n    return placement.replace(/left|right|bottom|top/g, function (matched) {\n      return hash[matched];\n    });\n  }\n\n  /**\n   * Get offsets to the popper\n   * @method\n   * @memberof Popper.Utils\n   * @param {Object} position - CSS position the Popper will get applied\n   * @param {HTMLElement} popper - the popper element\n   * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this)\n   * @param {String} placement - one of the valid placement options\n   * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper\n   */\n  function getPopperOffsets(popper, referenceOffsets, placement) {\n    placement = placement.split('-')[0];\n\n    // Get popper node sizes\n    var popperRect = getOuterSizes(popper);\n\n    // Add position, width and height to our offsets object\n    var popperOffsets = {\n      width: popperRect.width,\n      height: popperRect.height\n    };\n\n    // depending by the popper placement we have to compute its offsets slightly differently\n    var isHoriz = ['right', 'left'].indexOf(placement) !== -1;\n    var mainSide = isHoriz ? 'top' : 'left';\n    var secondarySide = isHoriz ? 'left' : 'top';\n    var measurement = isHoriz ? 'height' : 'width';\n    var secondaryMeasurement = !isHoriz ? 'height' : 'width';\n\n    popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2;\n    if (placement === secondarySide) {\n      popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement];\n    } else {\n      popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)];\n    }\n\n    return popperOffsets;\n  }\n\n  /**\n   * Mimics the `find` method of Array\n   * @method\n   * @memberof Popper.Utils\n   * @argument {Array} arr\n   * @argument prop\n   * @argument value\n   * @returns index or -1\n   */\n  function find(arr, check) {\n    // use native find if supported\n    if (Array.prototype.find) {\n      return arr.find(check);\n    }\n\n    // use `filter` to obtain the same behavior of `find`\n    return arr.filter(check)[0];\n  }\n\n  /**\n   * Return the index of the matching object\n   * @method\n   * @memberof Popper.Utils\n   * @argument {Array} arr\n   * @argument prop\n   * @argument value\n   * @returns index or -1\n   */\n  function findIndex(arr, prop, value) {\n    // use native findIndex if supported\n    if (Array.prototype.findIndex) {\n      return arr.findIndex(function (cur) {\n        return cur[prop] === value;\n      });\n    }\n\n    // use `find` + `indexOf` if `findIndex` isn't supported\n    var match = find(arr, function (obj) {\n      return obj[prop] === value;\n    });\n    return arr.indexOf(match);\n  }\n\n  /**\n   * Loop trough the list of modifiers and run them in order,\n   * each of them will then edit the data object.\n   * @method\n   * @memberof Popper.Utils\n   * @param {dataObject} data\n   * @param {Array} modifiers\n   * @param {String} ends - Optional modifier name used as stopper\n   * @returns {dataObject}\n   */\n  function runModifiers(modifiers, data, ends) {\n    var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends));\n\n    modifiersToRun.forEach(function (modifier) {\n      if (modifier['function']) {\n        // eslint-disable-line dot-notation\n        console.warn('`modifier.function` is deprecated, use `modifier.fn`!');\n      }\n      var fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation\n      if (modifier.enabled && isFunction(fn)) {\n        // Add properties to offsets to make them a complete clientRect object\n        // we do this before each modifier to make sure the previous one doesn't\n        // mess with these values\n        data.offsets.popper = getClientRect(data.offsets.popper);\n        data.offsets.reference = getClientRect(data.offsets.reference);\n\n        data = fn(data, modifier);\n      }\n    });\n\n    return data;\n  }\n\n  /**\n   * Updates the position of the popper, computing the new offsets and applying\n   * the new style.<br />\n   * Prefer `scheduleUpdate` over `update` because of performance reasons.\n   * @method\n   * @memberof Popper\n   */\n  function update() {\n    // if popper is destroyed, don't perform any further update\n    if (this.state.isDestroyed) {\n      return;\n    }\n\n    var data = {\n      instance: this,\n      styles: {},\n      arrowStyles: {},\n      attributes: {},\n      flipped: false,\n      offsets: {}\n    };\n\n    // compute reference element offsets\n    data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference, this.options.positionFixed);\n\n    // compute auto placement, store placement inside the data object,\n    // modifiers will be able to edit `placement` if needed\n    // and refer to originalPlacement to know the original value\n    data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding);\n\n    // store the computed placement inside `originalPlacement`\n    data.originalPlacement = data.placement;\n\n    data.positionFixed = this.options.positionFixed;\n\n    // compute the popper offsets\n    data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement);\n\n    data.offsets.popper.position = this.options.positionFixed ? 'fixed' : 'absolute';\n\n    // run the modifiers\n    data = runModifiers(this.modifiers, data);\n\n    // the first `update` will call `onCreate` callback\n    // the other ones will call `onUpdate` callback\n    if (!this.state.isCreated) {\n      this.state.isCreated = true;\n      this.options.onCreate(data);\n    } else {\n      this.options.onUpdate(data);\n    }\n  }\n\n  /**\n   * Helper used to know if the given modifier is enabled.\n   * @method\n   * @memberof Popper.Utils\n   * @returns {Boolean}\n   */\n  function isModifierEnabled(modifiers, modifierName) {\n    return modifiers.some(function (_ref) {\n      var name = _ref.name,\n          enabled = _ref.enabled;\n      return enabled && name === modifierName;\n    });\n  }\n\n  /**\n   * Get the prefixed supported property name\n   * @method\n   * @memberof Popper.Utils\n   * @argument {String} property (camelCase)\n   * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix)\n   */\n  function getSupportedPropertyName(property) {\n    var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O'];\n    var upperProp = property.charAt(0).toUpperCase() + property.slice(1);\n\n    for (var i = 0; i < prefixes.length; i++) {\n      var prefix = prefixes[i];\n      var toCheck = prefix ? '' + prefix + upperProp : property;\n      if (typeof document.body.style[toCheck] !== 'undefined') {\n        return toCheck;\n      }\n    }\n    return null;\n  }\n\n  /**\n   * Destroys the popper.\n   * @method\n   * @memberof Popper\n   */\n  function destroy() {\n    this.state.isDestroyed = true;\n\n    // touch DOM only if `applyStyle` modifier is enabled\n    if (isModifierEnabled(this.modifiers, 'applyStyle')) {\n      this.popper.removeAttribute('x-placement');\n      this.popper.style.position = '';\n      this.popper.style.top = '';\n      this.popper.style.left = '';\n      this.popper.style.right = '';\n      this.popper.style.bottom = '';\n      this.popper.style.willChange = '';\n      this.popper.style[getSupportedPropertyName('transform')] = '';\n    }\n\n    this.disableEventListeners();\n\n    // remove the popper if user explicitly asked for the deletion on destroy\n    // do not use `remove` because IE11 doesn't support it\n    if (this.options.removeOnDestroy) {\n      this.popper.parentNode.removeChild(this.popper);\n    }\n    return this;\n  }\n\n  /**\n   * Get the window associated with the element\n   * @argument {Element} element\n   * @returns {Window}\n   */\n  function getWindow(element) {\n    var ownerDocument = element.ownerDocument;\n    return ownerDocument ? ownerDocument.defaultView : window;\n  }\n\n  function attachToScrollParents(scrollParent, event, callback, scrollParents) {\n    var isBody = scrollParent.nodeName === 'BODY';\n    var target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent;\n    target.addEventListener(event, callback, { passive: true });\n\n    if (!isBody) {\n      attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents);\n    }\n    scrollParents.push(target);\n  }\n\n  /**\n   * Setup needed event listeners used to update the popper position\n   * @method\n   * @memberof Popper.Utils\n   * @private\n   */\n  function setupEventListeners(reference, options, state, updateBound) {\n    // Resize event listener on window\n    state.updateBound = updateBound;\n    getWindow(reference).addEventListener('resize', state.updateBound, { passive: true });\n\n    // Scroll event listener on scroll parents\n    var scrollElement = getScrollParent(reference);\n    attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents);\n    state.scrollElement = scrollElement;\n    state.eventsEnabled = true;\n\n    return state;\n  }\n\n  /**\n   * It will add resize/scroll events and start recalculating\n   * position of the popper element when they are triggered.\n   * @method\n   * @memberof Popper\n   */\n  function enableEventListeners() {\n    if (!this.state.eventsEnabled) {\n      this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate);\n    }\n  }\n\n  /**\n   * Remove event listeners used to update the popper position\n   * @method\n   * @memberof Popper.Utils\n   * @private\n   */\n  function removeEventListeners(reference, state) {\n    // Remove resize event listener on window\n    getWindow(reference).removeEventListener('resize', state.updateBound);\n\n    // Remove scroll event listener on scroll parents\n    state.scrollParents.forEach(function (target) {\n      target.removeEventListener('scroll', state.updateBound);\n    });\n\n    // Reset state\n    state.updateBound = null;\n    state.scrollParents = [];\n    state.scrollElement = null;\n    state.eventsEnabled = false;\n    return state;\n  }\n\n  /**\n   * It will remove resize/scroll events and won't recalculate popper position\n   * when they are triggered. It also won't trigger `onUpdate` callback anymore,\n   * unless you call `update` method manually.\n   * @method\n   * @memberof Popper\n   */\n  function disableEventListeners() {\n    if (this.state.eventsEnabled) {\n      cancelAnimationFrame(this.scheduleUpdate);\n      this.state = removeEventListeners(this.reference, this.state);\n    }\n  }\n\n  /**\n   * Tells if a given input is a number\n   * @method\n   * @memberof Popper.Utils\n   * @param {*} input to check\n   * @return {Boolean}\n   */\n  function isNumeric(n) {\n    return n !== '' && !isNaN(parseFloat(n)) && isFinite(n);\n  }\n\n  /**\n   * Set the style to the given popper\n   * @method\n   * @memberof Popper.Utils\n   * @argument {Element} element - Element to apply the style to\n   * @argument {Object} styles\n   * Object with a list of properties and values which will be applied to the element\n   */\n  function setStyles(element, styles) {\n    Object.keys(styles).forEach(function (prop) {\n      var unit = '';\n      // add unit if the value is numeric and is one of the following\n      if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) {\n        unit = 'px';\n      }\n      element.style[prop] = styles[prop] + unit;\n    });\n  }\n\n  /**\n   * Set the attributes to the given popper\n   * @method\n   * @memberof Popper.Utils\n   * @argument {Element} element - Element to apply the attributes to\n   * @argument {Object} styles\n   * Object with a list of properties and values which will be applied to the element\n   */\n  function setAttributes(element, attributes) {\n    Object.keys(attributes).forEach(function (prop) {\n      var value = attributes[prop];\n      if (value !== false) {\n        element.setAttribute(prop, attributes[prop]);\n      } else {\n        element.removeAttribute(prop);\n      }\n    });\n  }\n\n  /**\n   * @function\n   * @memberof Modifiers\n   * @argument {Object} data - The data object generated by `update` method\n   * @argument {Object} data.styles - List of style properties - values to apply to popper element\n   * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element\n   * @argument {Object} options - Modifiers configuration and options\n   * @returns {Object} The same data object\n   */\n  function applyStyle(data) {\n    // any property present in `data.styles` will be applied to the popper,\n    // in this way we can make the 3rd party modifiers add custom styles to it\n    // Be aware, modifiers could override the properties defined in the previous\n    // lines of this modifier!\n    setStyles(data.instance.popper, data.styles);\n\n    // any property present in `data.attributes` will be applied to the popper,\n    // they will be set as HTML attributes of the element\n    setAttributes(data.instance.popper, data.attributes);\n\n    // if arrowElement is defined and arrowStyles has some properties\n    if (data.arrowElement && Object.keys(data.arrowStyles).length) {\n      setStyles(data.arrowElement, data.arrowStyles);\n    }\n\n    return data;\n  }\n\n  /**\n   * Set the x-placement attribute before everything else because it could be used\n   * to add margins to the popper margins needs to be calculated to get the\n   * correct popper offsets.\n   * @method\n   * @memberof Popper.modifiers\n   * @param {HTMLElement} reference - The reference element used to position the popper\n   * @param {HTMLElement} popper - The HTML element used as popper\n   * @param {Object} options - Popper.js options\n   */\n  function applyStyleOnLoad(reference, popper, options, modifierOptions, state) {\n    // compute reference element offsets\n    var referenceOffsets = getReferenceOffsets(state, popper, reference, options.positionFixed);\n\n    // compute auto placement, store placement inside the data object,\n    // modifiers will be able to edit `placement` if needed\n    // and refer to originalPlacement to know the original value\n    var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding);\n\n    popper.setAttribute('x-placement', placement);\n\n    // Apply `position` to popper before anything else because\n    // without the position applied we can't guarantee correct computations\n    setStyles(popper, { position: options.positionFixed ? 'fixed' : 'absolute' });\n\n    return options;\n  }\n\n  /**\n   * @function\n   * @memberof Popper.Utils\n   * @argument {Object} data - The data object generated by `update` method\n   * @argument {Boolean} shouldRound - If the offsets should be rounded at all\n   * @returns {Object} The popper's position offsets rounded\n   *\n   * The tale of pixel-perfect positioning. It's still not 100% perfect, but as\n   * good as it can be within reason.\n   * Discussion here: https://github.com/FezVrasta/popper.js/pull/715\n   *\n   * Low DPI screens cause a popper to be blurry if not using full pixels (Safari\n   * as well on High DPI screens).\n   *\n   * Firefox prefers no rounding for positioning and does not have blurriness on\n   * high DPI screens.\n   *\n   * Only horizontal placement and left/right values need to be considered.\n   */\n  function getRoundedOffsets(data, shouldRound) {\n    var _data$offsets = data.offsets,\n        popper = _data$offsets.popper,\n        reference = _data$offsets.reference;\n    var round = Math.round,\n        floor = Math.floor;\n\n    var noRound = function noRound(v) {\n      return v;\n    };\n\n    var referenceWidth = round(reference.width);\n    var popperWidth = round(popper.width);\n\n    var isVertical = ['left', 'right'].indexOf(data.placement) !== -1;\n    var isVariation = data.placement.indexOf('-') !== -1;\n    var sameWidthParity = referenceWidth % 2 === popperWidth % 2;\n    var bothOddWidth = referenceWidth % 2 === 1 && popperWidth % 2 === 1;\n\n    var horizontalToInteger = !shouldRound ? noRound : isVertical || isVariation || sameWidthParity ? round : floor;\n    var verticalToInteger = !shouldRound ? noRound : round;\n\n    return {\n      left: horizontalToInteger(bothOddWidth && !isVariation && shouldRound ? popper.left - 1 : popper.left),\n      top: verticalToInteger(popper.top),\n      bottom: verticalToInteger(popper.bottom),\n      right: horizontalToInteger(popper.right)\n    };\n  }\n\n  var isFirefox = isBrowser && /Firefox/i.test(navigator.userAgent);\n\n  /**\n   * @function\n   * @memberof Modifiers\n   * @argument {Object} data - The data object generated by `update` method\n   * @argument {Object} options - Modifiers configuration and options\n   * @returns {Object} The data object, properly modified\n   */\n  function computeStyle(data, options) {\n    var x = options.x,\n        y = options.y;\n    var popper = data.offsets.popper;\n\n    // Remove this legacy support in Popper.js v2\n\n    var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) {\n      return modifier.name === 'applyStyle';\n    }).gpuAcceleration;\n    if (legacyGpuAccelerationOption !== undefined) {\n      console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!');\n    }\n    var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration;\n\n    var offsetParent = getOffsetParent(data.instance.popper);\n    var offsetParentRect = getBoundingClientRect(offsetParent);\n\n    // Styles\n    var styles = {\n      position: popper.position\n    };\n\n    var offsets = getRoundedOffsets(data, window.devicePixelRatio < 2 || !isFirefox);\n\n    var sideA = x === 'bottom' ? 'top' : 'bottom';\n    var sideB = y === 'right' ? 'left' : 'right';\n\n    // if gpuAcceleration is set to `true` and transform is supported,\n    //  we use `translate3d` to apply the position to the popper we\n    // automatically use the supported prefixed version if needed\n    var prefixedProperty = getSupportedPropertyName('transform');\n\n    // now, let's make a step back and look at this code closely (wtf?)\n    // If the content of the popper grows once it's been positioned, it\n    // may happen that the popper gets misplaced because of the new content\n    // overflowing its reference element\n    // To avoid this problem, we provide two options (x and y), which allow\n    // the consumer to define the offset origin.\n    // If we position a popper on top of a reference element, we can set\n    // `x` to `top` to make the popper grow towards its top instead of\n    // its bottom.\n    var left = void 0,\n        top = void 0;\n    if (sideA === 'bottom') {\n      // when offsetParent is <html> the positioning is relative to the bottom of the screen (excluding the scrollbar)\n      // and not the bottom of the html element\n      if (offsetParent.nodeName === 'HTML') {\n        top = -offsetParent.clientHeight + offsets.bottom;\n      } else {\n        top = -offsetParentRect.height + offsets.bottom;\n      }\n    } else {\n      top = offsets.top;\n    }\n    if (sideB === 'right') {\n      if (offsetParent.nodeName === 'HTML') {\n        left = -offsetParent.clientWidth + offsets.right;\n      } else {\n        left = -offsetParentRect.width + offsets.right;\n      }\n    } else {\n      left = offsets.left;\n    }\n    if (gpuAcceleration && prefixedProperty) {\n      styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)';\n      styles[sideA] = 0;\n      styles[sideB] = 0;\n      styles.willChange = 'transform';\n    } else {\n      // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties\n      var invertTop = sideA === 'bottom' ? -1 : 1;\n      var invertLeft = sideB === 'right' ? -1 : 1;\n      styles[sideA] = top * invertTop;\n      styles[sideB] = left * invertLeft;\n      styles.willChange = sideA + ', ' + sideB;\n    }\n\n    // Attributes\n    var attributes = {\n      'x-placement': data.placement\n    };\n\n    // Update `data` attributes, styles and arrowStyles\n    data.attributes = _extends$1({}, attributes, data.attributes);\n    data.styles = _extends$1({}, styles, data.styles);\n    data.arrowStyles = _extends$1({}, data.offsets.arrow, data.arrowStyles);\n\n    return data;\n  }\n\n  /**\n   * Helper used to know if the given modifier depends from another one.<br />\n   * It checks if the needed modifier is listed and enabled.\n   * @method\n   * @memberof Popper.Utils\n   * @param {Array} modifiers - list of modifiers\n   * @param {String} requestingName - name of requesting modifier\n   * @param {String} requestedName - name of requested modifier\n   * @returns {Boolean}\n   */\n  function isModifierRequired(modifiers, requestingName, requestedName) {\n    var requesting = find(modifiers, function (_ref) {\n      var name = _ref.name;\n      return name === requestingName;\n    });\n\n    var isRequired = !!requesting && modifiers.some(function (modifier) {\n      return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order;\n    });\n\n    if (!isRequired) {\n      var _requesting = '`' + requestingName + '`';\n      var requested = '`' + requestedName + '`';\n      console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!');\n    }\n    return isRequired;\n  }\n\n  /**\n   * @function\n   * @memberof Modifiers\n   * @argument {Object} data - The data object generated by update method\n   * @argument {Object} options - Modifiers configuration and options\n   * @returns {Object} The data object, properly modified\n   */\n  function arrow(data, options) {\n    var _data$offsets$arrow;\n\n    // arrow depends on keepTogether in order to work\n    if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {\n      return data;\n    }\n\n    var arrowElement = options.element;\n\n    // if arrowElement is a string, suppose it's a CSS selector\n    if (typeof arrowElement === 'string') {\n      arrowElement = data.instance.popper.querySelector(arrowElement);\n\n      // if arrowElement is not found, don't run the modifier\n      if (!arrowElement) {\n        return data;\n      }\n    } else {\n      // if the arrowElement isn't a query selector we must check that the\n      // provided DOM node is child of its popper node\n      if (!data.instance.popper.contains(arrowElement)) {\n        console.warn('WARNING: `arrow.element` must be child of its popper element!');\n        return data;\n      }\n    }\n\n    var placement = data.placement.split('-')[0];\n    var _data$offsets = data.offsets,\n        popper = _data$offsets.popper,\n        reference = _data$offsets.reference;\n\n    var isVertical = ['left', 'right'].indexOf(placement) !== -1;\n\n    var len = isVertical ? 'height' : 'width';\n    var sideCapitalized = isVertical ? 'Top' : 'Left';\n    var side = sideCapitalized.toLowerCase();\n    var altSide = isVertical ? 'left' : 'top';\n    var opSide = isVertical ? 'bottom' : 'right';\n    var arrowElementSize = getOuterSizes(arrowElement)[len];\n\n    //\n    // extends keepTogether behavior making sure the popper and its\n    // reference have enough pixels in conjunction\n    //\n\n    // top/left side\n    if (reference[opSide] - arrowElementSize < popper[side]) {\n      data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize);\n    }\n    // bottom/right side\n    if (reference[side] + arrowElementSize > popper[opSide]) {\n      data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];\n    }\n    data.offsets.popper = getClientRect(data.offsets.popper);\n\n    // compute center of the popper\n    var center = reference[side] + reference[len] / 2 - arrowElementSize / 2;\n\n    // Compute the sideValue using the updated popper offsets\n    // take popper margin in account because we don't have this info available\n    var css = getStyleComputedProperty(data.instance.popper);\n    var popperMarginSide = parseFloat(css['margin' + sideCapitalized]);\n    var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width']);\n    var sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide;\n\n    // prevent arrowElement from being placed not contiguously to its popper\n    sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);\n\n    data.arrowElement = arrowElement;\n    data.offsets.arrow = (_data$offsets$arrow = {}, defineProperty(_data$offsets$arrow, side, Math.round(sideValue)), defineProperty(_data$offsets$arrow, altSide, ''), _data$offsets$arrow);\n\n    return data;\n  }\n\n  /**\n   * Get the opposite placement variation of the given one\n   * @method\n   * @memberof Popper.Utils\n   * @argument {String} placement variation\n   * @returns {String} flipped placement variation\n   */\n  function getOppositeVariation(variation) {\n    if (variation === 'end') {\n      return 'start';\n    } else if (variation === 'start') {\n      return 'end';\n    }\n    return variation;\n  }\n\n  /**\n   * List of accepted placements to use as values of the `placement` option.<br />\n   * Valid placements are:\n   * - `auto`\n   * - `top`\n   * - `right`\n   * - `bottom`\n   * - `left`\n   *\n   * Each placement can have a variation from this list:\n   * - `-start`\n   * - `-end`\n   *\n   * Variations are interpreted easily if you think of them as the left to right\n   * written languages. Horizontally (`top` and `bottom`), `start` is left and `end`\n   * is right.<br />\n   * Vertically (`left` and `right`), `start` is top and `end` is bottom.\n   *\n   * Some valid examples are:\n   * - `top-end` (on top of reference, right aligned)\n   * - `right-start` (on right of reference, top aligned)\n   * - `bottom` (on bottom, centered)\n   * - `auto-end` (on the side with more space available, alignment depends by placement)\n   *\n   * @static\n   * @type {Array}\n   * @enum {String}\n   * @readonly\n   * @method placements\n   * @memberof Popper\n   */\n  var placements = ['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start'];\n\n  // Get rid of `auto` `auto-start` and `auto-end`\n  var validPlacements = placements.slice(3);\n\n  /**\n   * Given an initial placement, returns all the subsequent placements\n   * clockwise (or counter-clockwise).\n   *\n   * @method\n   * @memberof Popper.Utils\n   * @argument {String} placement - A valid placement (it accepts variations)\n   * @argument {Boolean} counter - Set to true to walk the placements counterclockwise\n   * @returns {Array} placements including their variations\n   */\n  function clockwise(placement) {\n    var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n\n    var index = validPlacements.indexOf(placement);\n    var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index));\n    return counter ? arr.reverse() : arr;\n  }\n\n  var BEHAVIORS = {\n    FLIP: 'flip',\n    CLOCKWISE: 'clockwise',\n    COUNTERCLOCKWISE: 'counterclockwise'\n  };\n\n  /**\n   * @function\n   * @memberof Modifiers\n   * @argument {Object} data - The data object generated by update method\n   * @argument {Object} options - Modifiers configuration and options\n   * @returns {Object} The data object, properly modified\n   */\n  function flip(data, options) {\n    // if `inner` modifier is enabled, we can't use the `flip` modifier\n    if (isModifierEnabled(data.instance.modifiers, 'inner')) {\n      return data;\n    }\n\n    if (data.flipped && data.placement === data.originalPlacement) {\n      // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides\n      return data;\n    }\n\n    var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement, data.positionFixed);\n\n    var placement = data.placement.split('-')[0];\n    var placementOpposite = getOppositePlacement(placement);\n    var variation = data.placement.split('-')[1] || '';\n\n    var flipOrder = [];\n\n    switch (options.behavior) {\n      case BEHAVIORS.FLIP:\n        flipOrder = [placement, placementOpposite];\n        break;\n      case BEHAVIORS.CLOCKWISE:\n        flipOrder = clockwise(placement);\n        break;\n      case BEHAVIORS.COUNTERCLOCKWISE:\n        flipOrder = clockwise(placement, true);\n        break;\n      default:\n        flipOrder = options.behavior;\n    }\n\n    flipOrder.forEach(function (step, index) {\n      if (placement !== step || flipOrder.length === index + 1) {\n        return data;\n      }\n\n      placement = data.placement.split('-')[0];\n      placementOpposite = getOppositePlacement(placement);\n\n      var popperOffsets = data.offsets.popper;\n      var refOffsets = data.offsets.reference;\n\n      // using floor because the reference offsets may contain decimals we are not going to consider here\n      var floor = Math.floor;\n      var overlapsRef = placement === 'left' && floor(popperOffsets.right) > floor(refOffsets.left) || placement === 'right' && floor(popperOffsets.left) < floor(refOffsets.right) || placement === 'top' && floor(popperOffsets.bottom) > floor(refOffsets.top) || placement === 'bottom' && floor(popperOffsets.top) < floor(refOffsets.bottom);\n\n      var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left);\n      var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right);\n      var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top);\n      var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom);\n\n      var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom;\n\n      // flip the variation if required\n      var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;\n\n      // flips variation if reference element overflows boundaries\n      var flippedVariationByRef = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom);\n\n      // flips variation if popper content overflows boundaries\n      var flippedVariationByContent = !!options.flipVariationsByContent && (isVertical && variation === 'start' && overflowsRight || isVertical && variation === 'end' && overflowsLeft || !isVertical && variation === 'start' && overflowsBottom || !isVertical && variation === 'end' && overflowsTop);\n\n      var flippedVariation = flippedVariationByRef || flippedVariationByContent;\n\n      if (overlapsRef || overflowsBoundaries || flippedVariation) {\n        // this boolean to detect any flip loop\n        data.flipped = true;\n\n        if (overlapsRef || overflowsBoundaries) {\n          placement = flipOrder[index + 1];\n        }\n\n        if (flippedVariation) {\n          variation = getOppositeVariation(variation);\n        }\n\n        data.placement = placement + (variation ? '-' + variation : '');\n\n        // this object contains `position`, we want to preserve it along with\n        // any additional property we may add in the future\n        data.offsets.popper = _extends$1({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement));\n\n        data = runModifiers(data.instance.modifiers, data, 'flip');\n      }\n    });\n    return data;\n  }\n\n  /**\n   * @function\n   * @memberof Modifiers\n   * @argument {Object} data - The data object generated by update method\n   * @argument {Object} options - Modifiers configuration and options\n   * @returns {Object} The data object, properly modified\n   */\n  function keepTogether(data) {\n    var _data$offsets = data.offsets,\n        popper = _data$offsets.popper,\n        reference = _data$offsets.reference;\n\n    var placement = data.placement.split('-')[0];\n    var floor = Math.floor;\n    var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;\n    var side = isVertical ? 'right' : 'bottom';\n    var opSide = isVertical ? 'left' : 'top';\n    var measurement = isVertical ? 'width' : 'height';\n\n    if (popper[side] < floor(reference[opSide])) {\n      data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement];\n    }\n    if (popper[opSide] > floor(reference[side])) {\n      data.offsets.popper[opSide] = floor(reference[side]);\n    }\n\n    return data;\n  }\n\n  /**\n   * Converts a string containing value + unit into a px value number\n   * @function\n   * @memberof {modifiers~offset}\n   * @private\n   * @argument {String} str - Value + unit string\n   * @argument {String} measurement - `height` or `width`\n   * @argument {Object} popperOffsets\n   * @argument {Object} referenceOffsets\n   * @returns {Number|String}\n   * Value in pixels, or original string if no values were extracted\n   */\n  function toValue(str, measurement, popperOffsets, referenceOffsets) {\n    // separate value from unit\n    var split = str.match(/((?:\\-|\\+)?\\d*\\.?\\d*)(.*)/);\n    var value = +split[1];\n    var unit = split[2];\n\n    // If it's not a number it's an operator, I guess\n    if (!value) {\n      return str;\n    }\n\n    if (unit.indexOf('%') === 0) {\n      var element = void 0;\n      switch (unit) {\n        case '%p':\n          element = popperOffsets;\n          break;\n        case '%':\n        case '%r':\n        default:\n          element = referenceOffsets;\n      }\n\n      var rect = getClientRect(element);\n      return rect[measurement] / 100 * value;\n    } else if (unit === 'vh' || unit === 'vw') {\n      // if is a vh or vw, we calculate the size based on the viewport\n      var size = void 0;\n      if (unit === 'vh') {\n        size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);\n      } else {\n        size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);\n      }\n      return size / 100 * value;\n    } else {\n      // if is an explicit pixel unit, we get rid of the unit and keep the value\n      // if is an implicit unit, it's px, and we return just the value\n      return value;\n    }\n  }\n\n  /**\n   * Parse an `offset` string to extrapolate `x` and `y` numeric offsets.\n   * @function\n   * @memberof {modifiers~offset}\n   * @private\n   * @argument {String} offset\n   * @argument {Object} popperOffsets\n   * @argument {Object} referenceOffsets\n   * @argument {String} basePlacement\n   * @returns {Array} a two cells array with x and y offsets in numbers\n   */\n  function parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) {\n    var offsets = [0, 0];\n\n    // Use height if placement is left or right and index is 0 otherwise use width\n    // in this way the first offset will use an axis and the second one\n    // will use the other one\n    var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1;\n\n    // Split the offset string to obtain a list of values and operands\n    // The regex addresses values with the plus or minus sign in front (+10, -20, etc)\n    var fragments = offset.split(/(\\+|\\-)/).map(function (frag) {\n      return frag.trim();\n    });\n\n    // Detect if the offset string contains a pair of values or a single one\n    // they could be separated by comma or space\n    var divider = fragments.indexOf(find(fragments, function (frag) {\n      return frag.search(/,|\\s/) !== -1;\n    }));\n\n    if (fragments[divider] && fragments[divider].indexOf(',') === -1) {\n      console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.');\n    }\n\n    // If divider is found, we divide the list of values and operands to divide\n    // them by ofset X and Y.\n    var splitRegex = /\\s*,\\s*|\\s+/;\n    var ops = divider !== -1 ? [fragments.slice(0, divider).concat([fragments[divider].split(splitRegex)[0]]), [fragments[divider].split(splitRegex)[1]].concat(fragments.slice(divider + 1))] : [fragments];\n\n    // Convert the values with units to absolute pixels to allow our computations\n    ops = ops.map(function (op, index) {\n      // Most of the units rely on the orientation of the popper\n      var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width';\n      var mergeWithPrevious = false;\n      return op\n      // This aggregates any `+` or `-` sign that aren't considered operators\n      // e.g.: 10 + +5 => [10, +, +5]\n      .reduce(function (a, b) {\n        if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) {\n          a[a.length - 1] = b;\n          mergeWithPrevious = true;\n          return a;\n        } else if (mergeWithPrevious) {\n          a[a.length - 1] += b;\n          mergeWithPrevious = false;\n          return a;\n        } else {\n          return a.concat(b);\n        }\n      }, [])\n      // Here we convert the string values into number values (in px)\n      .map(function (str) {\n        return toValue(str, measurement, popperOffsets, referenceOffsets);\n      });\n    });\n\n    // Loop trough the offsets arrays and execute the operations\n    ops.forEach(function (op, index) {\n      op.forEach(function (frag, index2) {\n        if (isNumeric(frag)) {\n          offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1);\n        }\n      });\n    });\n    return offsets;\n  }\n\n  /**\n   * @function\n   * @memberof Modifiers\n   * @argument {Object} data - The data object generated by update method\n   * @argument {Object} options - Modifiers configuration and options\n   * @argument {Number|String} options.offset=0\n   * The offset value as described in the modifier description\n   * @returns {Object} The data object, properly modified\n   */\n  function offset(data, _ref) {\n    var offset = _ref.offset;\n    var placement = data.placement,\n        _data$offsets = data.offsets,\n        popper = _data$offsets.popper,\n        reference = _data$offsets.reference;\n\n    var basePlacement = placement.split('-')[0];\n\n    var offsets = void 0;\n    if (isNumeric(+offset)) {\n      offsets = [+offset, 0];\n    } else {\n      offsets = parseOffset(offset, popper, reference, basePlacement);\n    }\n\n    if (basePlacement === 'left') {\n      popper.top += offsets[0];\n      popper.left -= offsets[1];\n    } else if (basePlacement === 'right') {\n      popper.top += offsets[0];\n      popper.left += offsets[1];\n    } else if (basePlacement === 'top') {\n      popper.left += offsets[0];\n      popper.top -= offsets[1];\n    } else if (basePlacement === 'bottom') {\n      popper.left += offsets[0];\n      popper.top += offsets[1];\n    }\n\n    data.popper = popper;\n    return data;\n  }\n\n  /**\n   * @function\n   * @memberof Modifiers\n   * @argument {Object} data - The data object generated by `update` method\n   * @argument {Object} options - Modifiers configuration and options\n   * @returns {Object} The data object, properly modified\n   */\n  function preventOverflow(data, options) {\n    var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper);\n\n    // If offsetParent is the reference element, we really want to\n    // go one step up and use the next offsetParent as reference to\n    // avoid to make this modifier completely useless and look like broken\n    if (data.instance.reference === boundariesElement) {\n      boundariesElement = getOffsetParent(boundariesElement);\n    }\n\n    // NOTE: DOM access here\n    // resets the popper's position so that the document size can be calculated excluding\n    // the size of the popper element itself\n    var transformProp = getSupportedPropertyName('transform');\n    var popperStyles = data.instance.popper.style; // assignment to help minification\n    var top = popperStyles.top,\n        left = popperStyles.left,\n        transform = popperStyles[transformProp];\n\n    popperStyles.top = '';\n    popperStyles.left = '';\n    popperStyles[transformProp] = '';\n\n    var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement, data.positionFixed);\n\n    // NOTE: DOM access here\n    // restores the original style properties after the offsets have been computed\n    popperStyles.top = top;\n    popperStyles.left = left;\n    popperStyles[transformProp] = transform;\n\n    options.boundaries = boundaries;\n\n    var order = options.priority;\n    var popper = data.offsets.popper;\n\n    var check = {\n      primary: function primary(placement) {\n        var value = popper[placement];\n        if (popper[placement] < boundaries[placement] && !options.escapeWithReference) {\n          value = Math.max(popper[placement], boundaries[placement]);\n        }\n        return defineProperty({}, placement, value);\n      },\n      secondary: function secondary(placement) {\n        var mainSide = placement === 'right' ? 'left' : 'top';\n        var value = popper[mainSide];\n        if (popper[placement] > boundaries[placement] && !options.escapeWithReference) {\n          value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height));\n        }\n        return defineProperty({}, mainSide, value);\n      }\n    };\n\n    order.forEach(function (placement) {\n      var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary';\n      popper = _extends$1({}, popper, check[side](placement));\n    });\n\n    data.offsets.popper = popper;\n\n    return data;\n  }\n\n  /**\n   * @function\n   * @memberof Modifiers\n   * @argument {Object} data - The data object generated by `update` method\n   * @argument {Object} options - Modifiers configuration and options\n   * @returns {Object} The data object, properly modified\n   */\n  function shift(data) {\n    var placement = data.placement;\n    var basePlacement = placement.split('-')[0];\n    var shiftvariation = placement.split('-')[1];\n\n    // if shift shiftvariation is specified, run the modifier\n    if (shiftvariation) {\n      var _data$offsets = data.offsets,\n          reference = _data$offsets.reference,\n          popper = _data$offsets.popper;\n\n      var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1;\n      var side = isVertical ? 'left' : 'top';\n      var measurement = isVertical ? 'width' : 'height';\n\n      var shiftOffsets = {\n        start: defineProperty({}, side, reference[side]),\n        end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement])\n      };\n\n      data.offsets.popper = _extends$1({}, popper, shiftOffsets[shiftvariation]);\n    }\n\n    return data;\n  }\n\n  /**\n   * @function\n   * @memberof Modifiers\n   * @argument {Object} data - The data object generated by update method\n   * @argument {Object} options - Modifiers configuration and options\n   * @returns {Object} The data object, properly modified\n   */\n  function hide(data) {\n    if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) {\n      return data;\n    }\n\n    var refRect = data.offsets.reference;\n    var bound = find(data.instance.modifiers, function (modifier) {\n      return modifier.name === 'preventOverflow';\n    }).boundaries;\n\n    if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) {\n      // Avoid unnecessary DOM access if visibility hasn't changed\n      if (data.hide === true) {\n        return data;\n      }\n\n      data.hide = true;\n      data.attributes['x-out-of-boundaries'] = '';\n    } else {\n      // Avoid unnecessary DOM access if visibility hasn't changed\n      if (data.hide === false) {\n        return data;\n      }\n\n      data.hide = false;\n      data.attributes['x-out-of-boundaries'] = false;\n    }\n\n    return data;\n  }\n\n  /**\n   * @function\n   * @memberof Modifiers\n   * @argument {Object} data - The data object generated by `update` method\n   * @argument {Object} options - Modifiers configuration and options\n   * @returns {Object} The data object, properly modified\n   */\n  function inner(data) {\n    var placement = data.placement;\n    var basePlacement = placement.split('-')[0];\n    var _data$offsets = data.offsets,\n        popper = _data$offsets.popper,\n        reference = _data$offsets.reference;\n\n    var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1;\n\n    var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1;\n\n    popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0);\n\n    data.placement = getOppositePlacement(placement);\n    data.offsets.popper = getClientRect(popper);\n\n    return data;\n  }\n\n  /**\n   * Modifier function, each modifier can have a function of this type assigned\n   * to its `fn` property.<br />\n   * These functions will be called on each update, this means that you must\n   * make sure they are performant enough to avoid performance bottlenecks.\n   *\n   * @function ModifierFn\n   * @argument {dataObject} data - The data object generated by `update` method\n   * @argument {Object} options - Modifiers configuration and options\n   * @returns {dataObject} The data object, properly modified\n   */\n\n  /**\n   * Modifiers are plugins used to alter the behavior of your poppers.<br />\n   * Popper.js uses a set of 9 modifiers to provide all the basic functionalities\n   * needed by the library.\n   *\n   * Usually you don't want to override the `order`, `fn` and `onLoad` props.\n   * All the other properties are configurations that could be tweaked.\n   * @namespace modifiers\n   */\n  var modifiers = {\n    /**\n     * Modifier used to shift the popper on the start or end of its reference\n     * element.<br />\n     * It will read the variation of the `placement` property.<br />\n     * It can be one either `-end` or `-start`.\n     * @memberof modifiers\n     * @inner\n     */\n    shift: {\n      /** @prop {number} order=100 - Index used to define the order of execution */\n      order: 100,\n      /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n      enabled: true,\n      /** @prop {ModifierFn} */\n      fn: shift\n    },\n\n    /**\n     * The `offset` modifier can shift your popper on both its axis.\n     *\n     * It accepts the following units:\n     * - `px` or unit-less, interpreted as pixels\n     * - `%` or `%r`, percentage relative to the length of the reference element\n     * - `%p`, percentage relative to the length of the popper element\n     * - `vw`, CSS viewport width unit\n     * - `vh`, CSS viewport height unit\n     *\n     * For length is intended the main axis relative to the placement of the popper.<br />\n     * This means that if the placement is `top` or `bottom`, the length will be the\n     * `width`. In case of `left` or `right`, it will be the `height`.\n     *\n     * You can provide a single value (as `Number` or `String`), or a pair of values\n     * as `String` divided by a comma or one (or more) white spaces.<br />\n     * The latter is a deprecated method because it leads to confusion and will be\n     * removed in v2.<br />\n     * Additionally, it accepts additions and subtractions between different units.\n     * Note that multiplications and divisions aren't supported.\n     *\n     * Valid examples are:\n     * ```\n     * 10\n     * '10%'\n     * '10, 10'\n     * '10%, 10'\n     * '10 + 10%'\n     * '10 - 5vh + 3%'\n     * '-10px + 5vh, 5px - 6%'\n     * ```\n     * > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap\n     * > with their reference element, unfortunately, you will have to disable the `flip` modifier.\n     * > You can read more on this at this [issue](https://github.com/FezVrasta/popper.js/issues/373).\n     *\n     * @memberof modifiers\n     * @inner\n     */\n    offset: {\n      /** @prop {number} order=200 - Index used to define the order of execution */\n      order: 200,\n      /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n      enabled: true,\n      /** @prop {ModifierFn} */\n      fn: offset,\n      /** @prop {Number|String} offset=0\n       * The offset value as described in the modifier description\n       */\n      offset: 0\n    },\n\n    /**\n     * Modifier used to prevent the popper from being positioned outside the boundary.\n     *\n     * A scenario exists where the reference itself is not within the boundaries.<br />\n     * We can say it has \"escaped the boundaries\" — or just \"escaped\".<br />\n     * In this case we need to decide whether the popper should either:\n     *\n     * - detach from the reference and remain \"trapped\" in the boundaries, or\n     * - if it should ignore the boundary and \"escape with its reference\"\n     *\n     * When `escapeWithReference` is set to`true` and reference is completely\n     * outside its boundaries, the popper will overflow (or completely leave)\n     * the boundaries in order to remain attached to the edge of the reference.\n     *\n     * @memberof modifiers\n     * @inner\n     */\n    preventOverflow: {\n      /** @prop {number} order=300 - Index used to define the order of execution */\n      order: 300,\n      /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n      enabled: true,\n      /** @prop {ModifierFn} */\n      fn: preventOverflow,\n      /**\n       * @prop {Array} [priority=['left','right','top','bottom']]\n       * Popper will try to prevent overflow following these priorities by default,\n       * then, it could overflow on the left and on top of the `boundariesElement`\n       */\n      priority: ['left', 'right', 'top', 'bottom'],\n      /**\n       * @prop {number} padding=5\n       * Amount of pixel used to define a minimum distance between the boundaries\n       * and the popper. This makes sure the popper always has a little padding\n       * between the edges of its container\n       */\n      padding: 5,\n      /**\n       * @prop {String|HTMLElement} boundariesElement='scrollParent'\n       * Boundaries used by the modifier. Can be `scrollParent`, `window`,\n       * `viewport` or any DOM element.\n       */\n      boundariesElement: 'scrollParent'\n    },\n\n    /**\n     * Modifier used to make sure the reference and its popper stay near each other\n     * without leaving any gap between the two. Especially useful when the arrow is\n     * enabled and you want to ensure that it points to its reference element.\n     * It cares only about the first axis. You can still have poppers with margin\n     * between the popper and its reference element.\n     * @memberof modifiers\n     * @inner\n     */\n    keepTogether: {\n      /** @prop {number} order=400 - Index used to define the order of execution */\n      order: 400,\n      /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n      enabled: true,\n      /** @prop {ModifierFn} */\n      fn: keepTogether\n    },\n\n    /**\n     * This modifier is used to move the `arrowElement` of the popper to make\n     * sure it is positioned between the reference element and its popper element.\n     * It will read the outer size of the `arrowElement` node to detect how many\n     * pixels of conjunction are needed.\n     *\n     * It has no effect if no `arrowElement` is provided.\n     * @memberof modifiers\n     * @inner\n     */\n    arrow: {\n      /** @prop {number} order=500 - Index used to define the order of execution */\n      order: 500,\n      /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n      enabled: true,\n      /** @prop {ModifierFn} */\n      fn: arrow,\n      /** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */\n      element: '[x-arrow]'\n    },\n\n    /**\n     * Modifier used to flip the popper's placement when it starts to overlap its\n     * reference element.\n     *\n     * Requires the `preventOverflow` modifier before it in order to work.\n     *\n     * **NOTE:** this modifier will interrupt the current update cycle and will\n     * restart it if it detects the need to flip the placement.\n     * @memberof modifiers\n     * @inner\n     */\n    flip: {\n      /** @prop {number} order=600 - Index used to define the order of execution */\n      order: 600,\n      /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n      enabled: true,\n      /** @prop {ModifierFn} */\n      fn: flip,\n      /**\n       * @prop {String|Array} behavior='flip'\n       * The behavior used to change the popper's placement. It can be one of\n       * `flip`, `clockwise`, `counterclockwise` or an array with a list of valid\n       * placements (with optional variations)\n       */\n      behavior: 'flip',\n      /**\n       * @prop {number} padding=5\n       * The popper will flip if it hits the edges of the `boundariesElement`\n       */\n      padding: 5,\n      /**\n       * @prop {String|HTMLElement} boundariesElement='viewport'\n       * The element which will define the boundaries of the popper position.\n       * The popper will never be placed outside of the defined boundaries\n       * (except if `keepTogether` is enabled)\n       */\n      boundariesElement: 'viewport',\n      /**\n       * @prop {Boolean} flipVariations=false\n       * The popper will switch placement variation between `-start` and `-end` when\n       * the reference element overlaps its boundaries.\n       *\n       * The original placement should have a set variation.\n       */\n      flipVariations: false,\n      /**\n       * @prop {Boolean} flipVariationsByContent=false\n       * The popper will switch placement variation between `-start` and `-end` when\n       * the popper element overlaps its reference boundaries.\n       *\n       * The original placement should have a set variation.\n       */\n      flipVariationsByContent: false\n    },\n\n    /**\n     * Modifier used to make the popper flow toward the inner of the reference element.\n     * By default, when this modifier is disabled, the popper will be placed outside\n     * the reference element.\n     * @memberof modifiers\n     * @inner\n     */\n    inner: {\n      /** @prop {number} order=700 - Index used to define the order of execution */\n      order: 700,\n      /** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */\n      enabled: false,\n      /** @prop {ModifierFn} */\n      fn: inner\n    },\n\n    /**\n     * Modifier used to hide the popper when its reference element is outside of the\n     * popper boundaries. It will set a `x-out-of-boundaries` attribute which can\n     * be used to hide with a CSS selector the popper when its reference is\n     * out of boundaries.\n     *\n     * Requires the `preventOverflow` modifier before it in order to work.\n     * @memberof modifiers\n     * @inner\n     */\n    hide: {\n      /** @prop {number} order=800 - Index used to define the order of execution */\n      order: 800,\n      /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n      enabled: true,\n      /** @prop {ModifierFn} */\n      fn: hide\n    },\n\n    /**\n     * Computes the style that will be applied to the popper element to gets\n     * properly positioned.\n     *\n     * Note that this modifier will not touch the DOM, it just prepares the styles\n     * so that `applyStyle` modifier can apply it. This separation is useful\n     * in case you need to replace `applyStyle` with a custom implementation.\n     *\n     * This modifier has `850` as `order` value to maintain backward compatibility\n     * with previous versions of Popper.js. Expect the modifiers ordering method\n     * to change in future major versions of the library.\n     *\n     * @memberof modifiers\n     * @inner\n     */\n    computeStyle: {\n      /** @prop {number} order=850 - Index used to define the order of execution */\n      order: 850,\n      /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n      enabled: true,\n      /** @prop {ModifierFn} */\n      fn: computeStyle,\n      /**\n       * @prop {Boolean} gpuAcceleration=true\n       * If true, it uses the CSS 3D transformation to position the popper.\n       * Otherwise, it will use the `top` and `left` properties\n       */\n      gpuAcceleration: true,\n      /**\n       * @prop {string} [x='bottom']\n       * Where to anchor the X axis (`bottom` or `top`). AKA X offset origin.\n       * Change this if your popper should grow in a direction different from `bottom`\n       */\n      x: 'bottom',\n      /**\n       * @prop {string} [x='left']\n       * Where to anchor the Y axis (`left` or `right`). AKA Y offset origin.\n       * Change this if your popper should grow in a direction different from `right`\n       */\n      y: 'right'\n    },\n\n    /**\n     * Applies the computed styles to the popper element.\n     *\n     * All the DOM manipulations are limited to this modifier. This is useful in case\n     * you want to integrate Popper.js inside a framework or view library and you\n     * want to delegate all the DOM manipulations to it.\n     *\n     * Note that if you disable this modifier, you must make sure the popper element\n     * has its position set to `absolute` before Popper.js can do its work!\n     *\n     * Just disable this modifier and define your own to achieve the desired effect.\n     *\n     * @memberof modifiers\n     * @inner\n     */\n    applyStyle: {\n      /** @prop {number} order=900 - Index used to define the order of execution */\n      order: 900,\n      /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n      enabled: true,\n      /** @prop {ModifierFn} */\n      fn: applyStyle,\n      /** @prop {Function} */\n      onLoad: applyStyleOnLoad,\n      /**\n       * @deprecated since version 1.10.0, the property moved to `computeStyle` modifier\n       * @prop {Boolean} gpuAcceleration=true\n       * If true, it uses the CSS 3D transformation to position the popper.\n       * Otherwise, it will use the `top` and `left` properties\n       */\n      gpuAcceleration: undefined\n    }\n  };\n\n  /**\n   * The `dataObject` is an object containing all the information used by Popper.js.\n   * This object is passed to modifiers and to the `onCreate` and `onUpdate` callbacks.\n   * @name dataObject\n   * @property {Object} data.instance The Popper.js instance\n   * @property {String} data.placement Placement applied to popper\n   * @property {String} data.originalPlacement Placement originally defined on init\n   * @property {Boolean} data.flipped True if popper has been flipped by flip modifier\n   * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper\n   * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier\n   * @property {Object} data.styles Any CSS property defined here will be applied to the popper. It expects the JavaScript nomenclature (eg. `marginBottom`)\n   * @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow. It expects the JavaScript nomenclature (eg. `marginBottom`)\n   * @property {Object} data.boundaries Offsets of the popper boundaries\n   * @property {Object} data.offsets The measurements of popper, reference and arrow elements\n   * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values\n   * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values\n   * @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0\n   */\n\n  /**\n   * Default options provided to Popper.js constructor.<br />\n   * These can be overridden using the `options` argument of Popper.js.<br />\n   * To override an option, simply pass an object with the same\n   * structure of the `options` object, as the 3rd argument. For example:\n   * ```\n   * new Popper(ref, pop, {\n   *   modifiers: {\n   *     preventOverflow: { enabled: false }\n   *   }\n   * })\n   * ```\n   * @type {Object}\n   * @static\n   * @memberof Popper\n   */\n  var Defaults = {\n    /**\n     * Popper's placement.\n     * @prop {Popper.placements} placement='bottom'\n     */\n    placement: 'bottom',\n\n    /**\n     * Set this to true if you want popper to position it self in 'fixed' mode\n     * @prop {Boolean} positionFixed=false\n     */\n    positionFixed: false,\n\n    /**\n     * Whether events (resize, scroll) are initially enabled.\n     * @prop {Boolean} eventsEnabled=true\n     */\n    eventsEnabled: true,\n\n    /**\n     * Set to true if you want to automatically remove the popper when\n     * you call the `destroy` method.\n     * @prop {Boolean} removeOnDestroy=false\n     */\n    removeOnDestroy: false,\n\n    /**\n     * Callback called when the popper is created.<br />\n     * By default, it is set to no-op.<br />\n     * Access Popper.js instance with `data.instance`.\n     * @prop {onCreate}\n     */\n    onCreate: function onCreate() {},\n\n    /**\n     * Callback called when the popper is updated. This callback is not called\n     * on the initialization/creation of the popper, but only on subsequent\n     * updates.<br />\n     * By default, it is set to no-op.<br />\n     * Access Popper.js instance with `data.instance`.\n     * @prop {onUpdate}\n     */\n    onUpdate: function onUpdate() {},\n\n    /**\n     * List of modifiers used to modify the offsets before they are applied to the popper.\n     * They provide most of the functionalities of Popper.js.\n     * @prop {modifiers}\n     */\n    modifiers: modifiers\n  };\n\n  /**\n   * @callback onCreate\n   * @param {dataObject} data\n   */\n\n  /**\n   * @callback onUpdate\n   * @param {dataObject} data\n   */\n\n  // Utils\n  // Methods\n  var Popper = function () {\n    /**\n     * Creates a new Popper.js instance.\n     * @class Popper\n     * @param {Element|referenceObject} reference - The reference element used to position the popper\n     * @param {Element} popper - The HTML / XML element used as the popper\n     * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults)\n     * @return {Object} instance - The generated Popper.js instance\n     */\n    function Popper(reference, popper) {\n      var _this = this;\n\n      var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n      classCallCheck(this, Popper);\n\n      this.scheduleUpdate = function () {\n        return requestAnimationFrame(_this.update);\n      };\n\n      // make update() debounced, so that it only runs at most once-per-tick\n      this.update = debounce(this.update.bind(this));\n\n      // with {} we create a new object with the options inside it\n      this.options = _extends$1({}, Popper.Defaults, options);\n\n      // init state\n      this.state = {\n        isDestroyed: false,\n        isCreated: false,\n        scrollParents: []\n      };\n\n      // get reference and popper elements (allow jQuery wrappers)\n      this.reference = reference && reference.jquery ? reference[0] : reference;\n      this.popper = popper && popper.jquery ? popper[0] : popper;\n\n      // Deep merge modifiers options\n      this.options.modifiers = {};\n      Object.keys(_extends$1({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) {\n        _this.options.modifiers[name] = _extends$1({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {});\n      });\n\n      // Refactoring modifiers' list (Object => Array)\n      this.modifiers = Object.keys(this.options.modifiers).map(function (name) {\n        return _extends$1({\n          name: name\n        }, _this.options.modifiers[name]);\n      })\n      // sort the modifiers by order\n      .sort(function (a, b) {\n        return a.order - b.order;\n      });\n\n      // modifiers have the ability to execute arbitrary code when Popper.js get inited\n      // such code is executed in the same order of its modifier\n      // they could add new properties to their options configuration\n      // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`!\n      this.modifiers.forEach(function (modifierOptions) {\n        if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) {\n          modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state);\n        }\n      });\n\n      // fire the first update to position the popper in the right place\n      this.update();\n\n      var eventsEnabled = this.options.eventsEnabled;\n      if (eventsEnabled) {\n        // setup event listeners, they will take care of update the position in specific situations\n        this.enableEventListeners();\n      }\n\n      this.state.eventsEnabled = eventsEnabled;\n    }\n\n    // We can't use class properties because they don't get listed in the\n    // class prototype and break stuff like Sinon stubs\n\n\n    createClass(Popper, [{\n      key: 'update',\n      value: function update$$1() {\n        return update.call(this);\n      }\n    }, {\n      key: 'destroy',\n      value: function destroy$$1() {\n        return destroy.call(this);\n      }\n    }, {\n      key: 'enableEventListeners',\n      value: function enableEventListeners$$1() {\n        return enableEventListeners.call(this);\n      }\n    }, {\n      key: 'disableEventListeners',\n      value: function disableEventListeners$$1() {\n        return disableEventListeners.call(this);\n      }\n\n      /**\n       * Schedules an update. It will run on the next UI update available.\n       * @method scheduleUpdate\n       * @memberof Popper\n       */\n\n\n      /**\n       * Collection of utilities useful when writing custom modifiers.\n       * Starting from version 1.7, this method is available only if you\n       * include `popper-utils.js` before `popper.js`.\n       *\n       * **DEPRECATION**: This way to access PopperUtils is deprecated\n       * and will be removed in v2! Use the PopperUtils module directly instead.\n       * Due to the high instability of the methods contained in Utils, we can't\n       * guarantee them to follow semver. Use them at your own risk!\n       * @static\n       * @private\n       * @type {Object}\n       * @deprecated since version 1.8\n       * @member Utils\n       * @memberof Popper\n       */\n\n    }]);\n    return Popper;\n  }();\n\n  /**\n   * The `referenceObject` is an object that provides an interface compatible with Popper.js\n   * and lets you use it as replacement of a real DOM node.<br />\n   * You can use this method to position a popper relatively to a set of coordinates\n   * in case you don't have a DOM node to use as reference.\n   *\n   * ```\n   * new Popper(referenceObject, popperNode);\n   * ```\n   *\n   * NB: This feature isn't supported in Internet Explorer 10.\n   * @name referenceObject\n   * @property {Function} data.getBoundingClientRect\n   * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method.\n   * @property {number} data.clientWidth\n   * An ES6 getter that will return the width of the virtual reference element.\n   * @property {number} data.clientHeight\n   * An ES6 getter that will return the height of the virtual reference element.\n   */\n\n\n  Popper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils;\n  Popper.placements = placements;\n  Popper.Defaults = Defaults;\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME$4 = 'dropdown';\n  var VERSION$4 = '4.5.3';\n  var DATA_KEY$4 = 'bs.dropdown';\n  var EVENT_KEY$4 = \".\" + DATA_KEY$4;\n  var DATA_API_KEY$4 = '.data-api';\n  var JQUERY_NO_CONFLICT$4 = $__default['default'].fn[NAME$4];\n  var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key\n\n  var SPACE_KEYCODE = 32; // KeyboardEvent.which value for space key\n\n  var TAB_KEYCODE = 9; // KeyboardEvent.which value for tab key\n\n  var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key\n\n  var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key\n\n  var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse)\n\n  var REGEXP_KEYDOWN = new RegExp(ARROW_UP_KEYCODE + \"|\" + ARROW_DOWN_KEYCODE + \"|\" + ESCAPE_KEYCODE);\n  var EVENT_HIDE$1 = \"hide\" + EVENT_KEY$4;\n  var EVENT_HIDDEN$1 = \"hidden\" + EVENT_KEY$4;\n  var EVENT_SHOW$1 = \"show\" + EVENT_KEY$4;\n  var EVENT_SHOWN$1 = \"shown\" + EVENT_KEY$4;\n  var EVENT_CLICK = \"click\" + EVENT_KEY$4;\n  var EVENT_CLICK_DATA_API$4 = \"click\" + EVENT_KEY$4 + DATA_API_KEY$4;\n  var EVENT_KEYDOWN_DATA_API = \"keydown\" + EVENT_KEY$4 + DATA_API_KEY$4;\n  var EVENT_KEYUP_DATA_API = \"keyup\" + EVENT_KEY$4 + DATA_API_KEY$4;\n  var CLASS_NAME_DISABLED = 'disabled';\n  var CLASS_NAME_SHOW$2 = 'show';\n  var CLASS_NAME_DROPUP = 'dropup';\n  var CLASS_NAME_DROPRIGHT = 'dropright';\n  var CLASS_NAME_DROPLEFT = 'dropleft';\n  var CLASS_NAME_MENURIGHT = 'dropdown-menu-right';\n  var CLASS_NAME_POSITION_STATIC = 'position-static';\n  var SELECTOR_DATA_TOGGLE$2 = '[data-toggle=\"dropdown\"]';\n  var SELECTOR_FORM_CHILD = '.dropdown form';\n  var SELECTOR_MENU = '.dropdown-menu';\n  var SELECTOR_NAVBAR_NAV = '.navbar-nav';\n  var SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)';\n  var PLACEMENT_TOP = 'top-start';\n  var PLACEMENT_TOPEND = 'top-end';\n  var PLACEMENT_BOTTOM = 'bottom-start';\n  var PLACEMENT_BOTTOMEND = 'bottom-end';\n  var PLACEMENT_RIGHT = 'right-start';\n  var PLACEMENT_LEFT = 'left-start';\n  var Default$2 = {\n    offset: 0,\n    flip: true,\n    boundary: 'scrollParent',\n    reference: 'toggle',\n    display: 'dynamic',\n    popperConfig: null\n  };\n  var DefaultType$2 = {\n    offset: '(number|string|function)',\n    flip: 'boolean',\n    boundary: '(string|element)',\n    reference: '(string|element)',\n    display: 'string',\n    popperConfig: '(null|object)'\n  };\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  var Dropdown = /*#__PURE__*/function () {\n    function Dropdown(element, config) {\n      this._element = element;\n      this._popper = null;\n      this._config = this._getConfig(config);\n      this._menu = this._getMenuElement();\n      this._inNavbar = this._detectNavbar();\n\n      this._addEventListeners();\n    } // Getters\n\n\n    var _proto = Dropdown.prototype;\n\n    // Public\n    _proto.toggle = function toggle() {\n      if (this._element.disabled || $__default['default'](this._element).hasClass(CLASS_NAME_DISABLED)) {\n        return;\n      }\n\n      var isActive = $__default['default'](this._menu).hasClass(CLASS_NAME_SHOW$2);\n\n      Dropdown._clearMenus();\n\n      if (isActive) {\n        return;\n      }\n\n      this.show(true);\n    };\n\n    _proto.show = function show(usePopper) {\n      if (usePopper === void 0) {\n        usePopper = false;\n      }\n\n      if (this._element.disabled || $__default['default'](this._element).hasClass(CLASS_NAME_DISABLED) || $__default['default'](this._menu).hasClass(CLASS_NAME_SHOW$2)) {\n        return;\n      }\n\n      var relatedTarget = {\n        relatedTarget: this._element\n      };\n      var showEvent = $__default['default'].Event(EVENT_SHOW$1, relatedTarget);\n\n      var parent = Dropdown._getParentFromElement(this._element);\n\n      $__default['default'](parent).trigger(showEvent);\n\n      if (showEvent.isDefaultPrevented()) {\n        return;\n      } // Disable totally Popper.js for Dropdown in Navbar\n\n\n      if (!this._inNavbar && usePopper) {\n        /**\n         * Check for Popper dependency\n         * Popper - https://popper.js.org\n         */\n        if (typeof Popper === 'undefined') {\n          throw new TypeError('Bootstrap\\'s dropdowns require Popper.js (https://popper.js.org/)');\n        }\n\n        var referenceElement = this._element;\n\n        if (this._config.reference === 'parent') {\n          referenceElement = parent;\n        } else if (Util.isElement(this._config.reference)) {\n          referenceElement = this._config.reference; // Check if it's jQuery element\n\n          if (typeof this._config.reference.jquery !== 'undefined') {\n            referenceElement = this._config.reference[0];\n          }\n        } // If boundary is not `scrollParent`, then set position to `static`\n        // to allow the menu to \"escape\" the scroll parent's boundaries\n        // https://github.com/twbs/bootstrap/issues/24251\n\n\n        if (this._config.boundary !== 'scrollParent') {\n          $__default['default'](parent).addClass(CLASS_NAME_POSITION_STATIC);\n        }\n\n        this._popper = new Popper(referenceElement, this._menu, this._getPopperConfig());\n      } // If this is a touch-enabled device we add extra\n      // empty mouseover listeners to the body's immediate children;\n      // only needed because of broken event delegation on iOS\n      // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n\n\n      if ('ontouchstart' in document.documentElement && $__default['default'](parent).closest(SELECTOR_NAVBAR_NAV).length === 0) {\n        $__default['default'](document.body).children().on('mouseover', null, $__default['default'].noop);\n      }\n\n      this._element.focus();\n\n      this._element.setAttribute('aria-expanded', true);\n\n      $__default['default'](this._menu).toggleClass(CLASS_NAME_SHOW$2);\n      $__default['default'](parent).toggleClass(CLASS_NAME_SHOW$2).trigger($__default['default'].Event(EVENT_SHOWN$1, relatedTarget));\n    };\n\n    _proto.hide = function hide() {\n      if (this._element.disabled || $__default['default'](this._element).hasClass(CLASS_NAME_DISABLED) || !$__default['default'](this._menu).hasClass(CLASS_NAME_SHOW$2)) {\n        return;\n      }\n\n      var relatedTarget = {\n        relatedTarget: this._element\n      };\n      var hideEvent = $__default['default'].Event(EVENT_HIDE$1, relatedTarget);\n\n      var parent = Dropdown._getParentFromElement(this._element);\n\n      $__default['default'](parent).trigger(hideEvent);\n\n      if (hideEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      if (this._popper) {\n        this._popper.destroy();\n      }\n\n      $__default['default'](this._menu).toggleClass(CLASS_NAME_SHOW$2);\n      $__default['default'](parent).toggleClass(CLASS_NAME_SHOW$2).trigger($__default['default'].Event(EVENT_HIDDEN$1, relatedTarget));\n    };\n\n    _proto.dispose = function dispose() {\n      $__default['default'].removeData(this._element, DATA_KEY$4);\n      $__default['default'](this._element).off(EVENT_KEY$4);\n      this._element = null;\n      this._menu = null;\n\n      if (this._popper !== null) {\n        this._popper.destroy();\n\n        this._popper = null;\n      }\n    };\n\n    _proto.update = function update() {\n      this._inNavbar = this._detectNavbar();\n\n      if (this._popper !== null) {\n        this._popper.scheduleUpdate();\n      }\n    } // Private\n    ;\n\n    _proto._addEventListeners = function _addEventListeners() {\n      var _this = this;\n\n      $__default['default'](this._element).on(EVENT_CLICK, function (event) {\n        event.preventDefault();\n        event.stopPropagation();\n\n        _this.toggle();\n      });\n    };\n\n    _proto._getConfig = function _getConfig(config) {\n      config = _extends({}, this.constructor.Default, $__default['default'](this._element).data(), config);\n      Util.typeCheckConfig(NAME$4, config, this.constructor.DefaultType);\n      return config;\n    };\n\n    _proto._getMenuElement = function _getMenuElement() {\n      if (!this._menu) {\n        var parent = Dropdown._getParentFromElement(this._element);\n\n        if (parent) {\n          this._menu = parent.querySelector(SELECTOR_MENU);\n        }\n      }\n\n      return this._menu;\n    };\n\n    _proto._getPlacement = function _getPlacement() {\n      var $parentDropdown = $__default['default'](this._element.parentNode);\n      var placement = PLACEMENT_BOTTOM; // Handle dropup\n\n      if ($parentDropdown.hasClass(CLASS_NAME_DROPUP)) {\n        placement = $__default['default'](this._menu).hasClass(CLASS_NAME_MENURIGHT) ? PLACEMENT_TOPEND : PLACEMENT_TOP;\n      } else if ($parentDropdown.hasClass(CLASS_NAME_DROPRIGHT)) {\n        placement = PLACEMENT_RIGHT;\n      } else if ($parentDropdown.hasClass(CLASS_NAME_DROPLEFT)) {\n        placement = PLACEMENT_LEFT;\n      } else if ($__default['default'](this._menu).hasClass(CLASS_NAME_MENURIGHT)) {\n        placement = PLACEMENT_BOTTOMEND;\n      }\n\n      return placement;\n    };\n\n    _proto._detectNavbar = function _detectNavbar() {\n      return $__default['default'](this._element).closest('.navbar').length > 0;\n    };\n\n    _proto._getOffset = function _getOffset() {\n      var _this2 = this;\n\n      var offset = {};\n\n      if (typeof this._config.offset === 'function') {\n        offset.fn = function (data) {\n          data.offsets = _extends({}, data.offsets, _this2._config.offset(data.offsets, _this2._element) || {});\n          return data;\n        };\n      } else {\n        offset.offset = this._config.offset;\n      }\n\n      return offset;\n    };\n\n    _proto._getPopperConfig = function _getPopperConfig() {\n      var popperConfig = {\n        placement: this._getPlacement(),\n        modifiers: {\n          offset: this._getOffset(),\n          flip: {\n            enabled: this._config.flip\n          },\n          preventOverflow: {\n            boundariesElement: this._config.boundary\n          }\n        }\n      }; // Disable Popper.js if we have a static display\n\n      if (this._config.display === 'static') {\n        popperConfig.modifiers.applyStyle = {\n          enabled: false\n        };\n      }\n\n      return _extends({}, popperConfig, this._config.popperConfig);\n    } // Static\n    ;\n\n    Dropdown._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var data = $__default['default'](this).data(DATA_KEY$4);\n\n        var _config = typeof config === 'object' ? config : null;\n\n        if (!data) {\n          data = new Dropdown(this, _config);\n          $__default['default'](this).data(DATA_KEY$4, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    Dropdown._clearMenus = function _clearMenus(event) {\n      if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH || event.type === 'keyup' && event.which !== TAB_KEYCODE)) {\n        return;\n      }\n\n      var toggles = [].slice.call(document.querySelectorAll(SELECTOR_DATA_TOGGLE$2));\n\n      for (var i = 0, len = toggles.length; i < len; i++) {\n        var parent = Dropdown._getParentFromElement(toggles[i]);\n\n        var context = $__default['default'](toggles[i]).data(DATA_KEY$4);\n        var relatedTarget = {\n          relatedTarget: toggles[i]\n        };\n\n        if (event && event.type === 'click') {\n          relatedTarget.clickEvent = event;\n        }\n\n        if (!context) {\n          continue;\n        }\n\n        var dropdownMenu = context._menu;\n\n        if (!$__default['default'](parent).hasClass(CLASS_NAME_SHOW$2)) {\n          continue;\n        }\n\n        if (event && (event.type === 'click' && /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) && $__default['default'].contains(parent, event.target)) {\n          continue;\n        }\n\n        var hideEvent = $__default['default'].Event(EVENT_HIDE$1, relatedTarget);\n        $__default['default'](parent).trigger(hideEvent);\n\n        if (hideEvent.isDefaultPrevented()) {\n          continue;\n        } // If this is a touch-enabled device we remove the extra\n        // empty mouseover listeners we added for iOS support\n\n\n        if ('ontouchstart' in document.documentElement) {\n          $__default['default'](document.body).children().off('mouseover', null, $__default['default'].noop);\n        }\n\n        toggles[i].setAttribute('aria-expanded', 'false');\n\n        if (context._popper) {\n          context._popper.destroy();\n        }\n\n        $__default['default'](dropdownMenu).removeClass(CLASS_NAME_SHOW$2);\n        $__default['default'](parent).removeClass(CLASS_NAME_SHOW$2).trigger($__default['default'].Event(EVENT_HIDDEN$1, relatedTarget));\n      }\n    };\n\n    Dropdown._getParentFromElement = function _getParentFromElement(element) {\n      var parent;\n      var selector = Util.getSelectorFromElement(element);\n\n      if (selector) {\n        parent = document.querySelector(selector);\n      }\n\n      return parent || element.parentNode;\n    } // eslint-disable-next-line complexity\n    ;\n\n    Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) {\n      // If not input/textarea:\n      //  - And not a key in REGEXP_KEYDOWN => not a dropdown command\n      // If input/textarea:\n      //  - If space key => not a dropdown command\n      //  - If key is other than escape\n      //    - If key is not up or down => not a dropdown command\n      //    - If trigger inside the menu => not a dropdown command\n      if (/input|textarea/i.test(event.target.tagName) ? event.which === SPACE_KEYCODE || event.which !== ESCAPE_KEYCODE && (event.which !== ARROW_DOWN_KEYCODE && event.which !== ARROW_UP_KEYCODE || $__default['default'](event.target).closest(SELECTOR_MENU).length) : !REGEXP_KEYDOWN.test(event.which)) {\n        return;\n      }\n\n      if (this.disabled || $__default['default'](this).hasClass(CLASS_NAME_DISABLED)) {\n        return;\n      }\n\n      var parent = Dropdown._getParentFromElement(this);\n\n      var isActive = $__default['default'](parent).hasClass(CLASS_NAME_SHOW$2);\n\n      if (!isActive && event.which === ESCAPE_KEYCODE) {\n        return;\n      }\n\n      event.preventDefault();\n      event.stopPropagation();\n\n      if (!isActive || event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE) {\n        if (event.which === ESCAPE_KEYCODE) {\n          $__default['default'](parent.querySelector(SELECTOR_DATA_TOGGLE$2)).trigger('focus');\n        }\n\n        $__default['default'](this).trigger('click');\n        return;\n      }\n\n      var items = [].slice.call(parent.querySelectorAll(SELECTOR_VISIBLE_ITEMS)).filter(function (item) {\n        return $__default['default'](item).is(':visible');\n      });\n\n      if (items.length === 0) {\n        return;\n      }\n\n      var index = items.indexOf(event.target);\n\n      if (event.which === ARROW_UP_KEYCODE && index > 0) {\n        // Up\n        index--;\n      }\n\n      if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) {\n        // Down\n        index++;\n      }\n\n      if (index < 0) {\n        index = 0;\n      }\n\n      items[index].focus();\n    };\n\n    _createClass(Dropdown, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION$4;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default$2;\n      }\n    }, {\n      key: \"DefaultType\",\n      get: function get() {\n        return DefaultType$2;\n      }\n    }]);\n\n    return Dropdown;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $__default['default'](document).on(EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE$2, Dropdown._dataApiKeydownHandler).on(EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown._dataApiKeydownHandler).on(EVENT_CLICK_DATA_API$4 + \" \" + EVENT_KEYUP_DATA_API, Dropdown._clearMenus).on(EVENT_CLICK_DATA_API$4, SELECTOR_DATA_TOGGLE$2, function (event) {\n    event.preventDefault();\n    event.stopPropagation();\n\n    Dropdown._jQueryInterface.call($__default['default'](this), 'toggle');\n  }).on(EVENT_CLICK_DATA_API$4, SELECTOR_FORM_CHILD, function (e) {\n    e.stopPropagation();\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $__default['default'].fn[NAME$4] = Dropdown._jQueryInterface;\n  $__default['default'].fn[NAME$4].Constructor = Dropdown;\n\n  $__default['default'].fn[NAME$4].noConflict = function () {\n    $__default['default'].fn[NAME$4] = JQUERY_NO_CONFLICT$4;\n    return Dropdown._jQueryInterface;\n  };\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME$5 = 'modal';\n  var VERSION$5 = '4.5.3';\n  var DATA_KEY$5 = 'bs.modal';\n  var EVENT_KEY$5 = \".\" + DATA_KEY$5;\n  var DATA_API_KEY$5 = '.data-api';\n  var JQUERY_NO_CONFLICT$5 = $__default['default'].fn[NAME$5];\n  var ESCAPE_KEYCODE$1 = 27; // KeyboardEvent.which value for Escape (Esc) key\n\n  var Default$3 = {\n    backdrop: true,\n    keyboard: true,\n    focus: true,\n    show: true\n  };\n  var DefaultType$3 = {\n    backdrop: '(boolean|string)',\n    keyboard: 'boolean',\n    focus: 'boolean',\n    show: 'boolean'\n  };\n  var EVENT_HIDE$2 = \"hide\" + EVENT_KEY$5;\n  var EVENT_HIDE_PREVENTED = \"hidePrevented\" + EVENT_KEY$5;\n  var EVENT_HIDDEN$2 = \"hidden\" + EVENT_KEY$5;\n  var EVENT_SHOW$2 = \"show\" + EVENT_KEY$5;\n  var EVENT_SHOWN$2 = \"shown\" + EVENT_KEY$5;\n  var EVENT_FOCUSIN = \"focusin\" + EVENT_KEY$5;\n  var EVENT_RESIZE = \"resize\" + EVENT_KEY$5;\n  var EVENT_CLICK_DISMISS = \"click.dismiss\" + EVENT_KEY$5;\n  var EVENT_KEYDOWN_DISMISS = \"keydown.dismiss\" + EVENT_KEY$5;\n  var EVENT_MOUSEUP_DISMISS = \"mouseup.dismiss\" + EVENT_KEY$5;\n  var EVENT_MOUSEDOWN_DISMISS = \"mousedown.dismiss\" + EVENT_KEY$5;\n  var EVENT_CLICK_DATA_API$5 = \"click\" + EVENT_KEY$5 + DATA_API_KEY$5;\n  var CLASS_NAME_SCROLLABLE = 'modal-dialog-scrollable';\n  var CLASS_NAME_SCROLLBAR_MEASURER = 'modal-scrollbar-measure';\n  var CLASS_NAME_BACKDROP = 'modal-backdrop';\n  var CLASS_NAME_OPEN = 'modal-open';\n  var CLASS_NAME_FADE$1 = 'fade';\n  var CLASS_NAME_SHOW$3 = 'show';\n  var CLASS_NAME_STATIC = 'modal-static';\n  var SELECTOR_DIALOG = '.modal-dialog';\n  var SELECTOR_MODAL_BODY = '.modal-body';\n  var SELECTOR_DATA_TOGGLE$3 = '[data-toggle=\"modal\"]';\n  var SELECTOR_DATA_DISMISS = '[data-dismiss=\"modal\"]';\n  var SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top';\n  var SELECTOR_STICKY_CONTENT = '.sticky-top';\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  var Modal = /*#__PURE__*/function () {\n    function Modal(element, config) {\n      this._config = this._getConfig(config);\n      this._element = element;\n      this._dialog = element.querySelector(SELECTOR_DIALOG);\n      this._backdrop = null;\n      this._isShown = false;\n      this._isBodyOverflowing = false;\n      this._ignoreBackdropClick = false;\n      this._isTransitioning = false;\n      this._scrollbarWidth = 0;\n    } // Getters\n\n\n    var _proto = Modal.prototype;\n\n    // Public\n    _proto.toggle = function toggle(relatedTarget) {\n      return this._isShown ? this.hide() : this.show(relatedTarget);\n    };\n\n    _proto.show = function show(relatedTarget) {\n      var _this = this;\n\n      if (this._isShown || this._isTransitioning) {\n        return;\n      }\n\n      if ($__default['default'](this._element).hasClass(CLASS_NAME_FADE$1)) {\n        this._isTransitioning = true;\n      }\n\n      var showEvent = $__default['default'].Event(EVENT_SHOW$2, {\n        relatedTarget: relatedTarget\n      });\n      $__default['default'](this._element).trigger(showEvent);\n\n      if (this._isShown || showEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      this._isShown = true;\n\n      this._checkScrollbar();\n\n      this._setScrollbar();\n\n      this._adjustDialog();\n\n      this._setEscapeEvent();\n\n      this._setResizeEvent();\n\n      $__default['default'](this._element).on(EVENT_CLICK_DISMISS, SELECTOR_DATA_DISMISS, function (event) {\n        return _this.hide(event);\n      });\n      $__default['default'](this._dialog).on(EVENT_MOUSEDOWN_DISMISS, function () {\n        $__default['default'](_this._element).one(EVENT_MOUSEUP_DISMISS, function (event) {\n          if ($__default['default'](event.target).is(_this._element)) {\n            _this._ignoreBackdropClick = true;\n          }\n        });\n      });\n\n      this._showBackdrop(function () {\n        return _this._showElement(relatedTarget);\n      });\n    };\n\n    _proto.hide = function hide(event) {\n      var _this2 = this;\n\n      if (event) {\n        event.preventDefault();\n      }\n\n      if (!this._isShown || this._isTransitioning) {\n        return;\n      }\n\n      var hideEvent = $__default['default'].Event(EVENT_HIDE$2);\n      $__default['default'](this._element).trigger(hideEvent);\n\n      if (!this._isShown || hideEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      this._isShown = false;\n      var transition = $__default['default'](this._element).hasClass(CLASS_NAME_FADE$1);\n\n      if (transition) {\n        this._isTransitioning = true;\n      }\n\n      this._setEscapeEvent();\n\n      this._setResizeEvent();\n\n      $__default['default'](document).off(EVENT_FOCUSIN);\n      $__default['default'](this._element).removeClass(CLASS_NAME_SHOW$3);\n      $__default['default'](this._element).off(EVENT_CLICK_DISMISS);\n      $__default['default'](this._dialog).off(EVENT_MOUSEDOWN_DISMISS);\n\n      if (transition) {\n        var transitionDuration = Util.getTransitionDurationFromElement(this._element);\n        $__default['default'](this._element).one(Util.TRANSITION_END, function (event) {\n          return _this2._hideModal(event);\n        }).emulateTransitionEnd(transitionDuration);\n      } else {\n        this._hideModal();\n      }\n    };\n\n    _proto.dispose = function dispose() {\n      [window, this._element, this._dialog].forEach(function (htmlElement) {\n        return $__default['default'](htmlElement).off(EVENT_KEY$5);\n      });\n      /**\n       * `document` has 2 events `EVENT_FOCUSIN` and `EVENT_CLICK_DATA_API`\n       * Do not move `document` in `htmlElements` array\n       * It will remove `EVENT_CLICK_DATA_API` event that should remain\n       */\n\n      $__default['default'](document).off(EVENT_FOCUSIN);\n      $__default['default'].removeData(this._element, DATA_KEY$5);\n      this._config = null;\n      this._element = null;\n      this._dialog = null;\n      this._backdrop = null;\n      this._isShown = null;\n      this._isBodyOverflowing = null;\n      this._ignoreBackdropClick = null;\n      this._isTransitioning = null;\n      this._scrollbarWidth = null;\n    };\n\n    _proto.handleUpdate = function handleUpdate() {\n      this._adjustDialog();\n    } // Private\n    ;\n\n    _proto._getConfig = function _getConfig(config) {\n      config = _extends({}, Default$3, config);\n      Util.typeCheckConfig(NAME$5, config, DefaultType$3);\n      return config;\n    };\n\n    _proto._triggerBackdropTransition = function _triggerBackdropTransition() {\n      var _this3 = this;\n\n      if (this._config.backdrop === 'static') {\n        var hideEventPrevented = $__default['default'].Event(EVENT_HIDE_PREVENTED);\n        $__default['default'](this._element).trigger(hideEventPrevented);\n\n        if (hideEventPrevented.isDefaultPrevented()) {\n          return;\n        }\n\n        var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;\n\n        if (!isModalOverflowing) {\n          this._element.style.overflowY = 'hidden';\n        }\n\n        this._element.classList.add(CLASS_NAME_STATIC);\n\n        var modalTransitionDuration = Util.getTransitionDurationFromElement(this._dialog);\n        $__default['default'](this._element).off(Util.TRANSITION_END);\n        $__default['default'](this._element).one(Util.TRANSITION_END, function () {\n          _this3._element.classList.remove(CLASS_NAME_STATIC);\n\n          if (!isModalOverflowing) {\n            $__default['default'](_this3._element).one(Util.TRANSITION_END, function () {\n              _this3._element.style.overflowY = '';\n            }).emulateTransitionEnd(_this3._element, modalTransitionDuration);\n          }\n        }).emulateTransitionEnd(modalTransitionDuration);\n\n        this._element.focus();\n      } else {\n        this.hide();\n      }\n    };\n\n    _proto._showElement = function _showElement(relatedTarget) {\n      var _this4 = this;\n\n      var transition = $__default['default'](this._element).hasClass(CLASS_NAME_FADE$1);\n      var modalBody = this._dialog ? this._dialog.querySelector(SELECTOR_MODAL_BODY) : null;\n\n      if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {\n        // Don't move modal's DOM position\n        document.body.appendChild(this._element);\n      }\n\n      this._element.style.display = 'block';\n\n      this._element.removeAttribute('aria-hidden');\n\n      this._element.setAttribute('aria-modal', true);\n\n      this._element.setAttribute('role', 'dialog');\n\n      if ($__default['default'](this._dialog).hasClass(CLASS_NAME_SCROLLABLE) && modalBody) {\n        modalBody.scrollTop = 0;\n      } else {\n        this._element.scrollTop = 0;\n      }\n\n      if (transition) {\n        Util.reflow(this._element);\n      }\n\n      $__default['default'](this._element).addClass(CLASS_NAME_SHOW$3);\n\n      if (this._config.focus) {\n        this._enforceFocus();\n      }\n\n      var shownEvent = $__default['default'].Event(EVENT_SHOWN$2, {\n        relatedTarget: relatedTarget\n      });\n\n      var transitionComplete = function transitionComplete() {\n        if (_this4._config.focus) {\n          _this4._element.focus();\n        }\n\n        _this4._isTransitioning = false;\n        $__default['default'](_this4._element).trigger(shownEvent);\n      };\n\n      if (transition) {\n        var transitionDuration = Util.getTransitionDurationFromElement(this._dialog);\n        $__default['default'](this._dialog).one(Util.TRANSITION_END, transitionComplete).emulateTransitionEnd(transitionDuration);\n      } else {\n        transitionComplete();\n      }\n    };\n\n    _proto._enforceFocus = function _enforceFocus() {\n      var _this5 = this;\n\n      $__default['default'](document).off(EVENT_FOCUSIN) // Guard against infinite focus loop\n      .on(EVENT_FOCUSIN, function (event) {\n        if (document !== event.target && _this5._element !== event.target && $__default['default'](_this5._element).has(event.target).length === 0) {\n          _this5._element.focus();\n        }\n      });\n    };\n\n    _proto._setEscapeEvent = function _setEscapeEvent() {\n      var _this6 = this;\n\n      if (this._isShown) {\n        $__default['default'](this._element).on(EVENT_KEYDOWN_DISMISS, function (event) {\n          if (_this6._config.keyboard && event.which === ESCAPE_KEYCODE$1) {\n            event.preventDefault();\n\n            _this6.hide();\n          } else if (!_this6._config.keyboard && event.which === ESCAPE_KEYCODE$1) {\n            _this6._triggerBackdropTransition();\n          }\n        });\n      } else if (!this._isShown) {\n        $__default['default'](this._element).off(EVENT_KEYDOWN_DISMISS);\n      }\n    };\n\n    _proto._setResizeEvent = function _setResizeEvent() {\n      var _this7 = this;\n\n      if (this._isShown) {\n        $__default['default'](window).on(EVENT_RESIZE, function (event) {\n          return _this7.handleUpdate(event);\n        });\n      } else {\n        $__default['default'](window).off(EVENT_RESIZE);\n      }\n    };\n\n    _proto._hideModal = function _hideModal() {\n      var _this8 = this;\n\n      this._element.style.display = 'none';\n\n      this._element.setAttribute('aria-hidden', true);\n\n      this._element.removeAttribute('aria-modal');\n\n      this._element.removeAttribute('role');\n\n      this._isTransitioning = false;\n\n      this._showBackdrop(function () {\n        $__default['default'](document.body).removeClass(CLASS_NAME_OPEN);\n\n        _this8._resetAdjustments();\n\n        _this8._resetScrollbar();\n\n        $__default['default'](_this8._element).trigger(EVENT_HIDDEN$2);\n      });\n    };\n\n    _proto._removeBackdrop = function _removeBackdrop() {\n      if (this._backdrop) {\n        $__default['default'](this._backdrop).remove();\n        this._backdrop = null;\n      }\n    };\n\n    _proto._showBackdrop = function _showBackdrop(callback) {\n      var _this9 = this;\n\n      var animate = $__default['default'](this._element).hasClass(CLASS_NAME_FADE$1) ? CLASS_NAME_FADE$1 : '';\n\n      if (this._isShown && this._config.backdrop) {\n        this._backdrop = document.createElement('div');\n        this._backdrop.className = CLASS_NAME_BACKDROP;\n\n        if (animate) {\n          this._backdrop.classList.add(animate);\n        }\n\n        $__default['default'](this._backdrop).appendTo(document.body);\n        $__default['default'](this._element).on(EVENT_CLICK_DISMISS, function (event) {\n          if (_this9._ignoreBackdropClick) {\n            _this9._ignoreBackdropClick = false;\n            return;\n          }\n\n          if (event.target !== event.currentTarget) {\n            return;\n          }\n\n          _this9._triggerBackdropTransition();\n        });\n\n        if (animate) {\n          Util.reflow(this._backdrop);\n        }\n\n        $__default['default'](this._backdrop).addClass(CLASS_NAME_SHOW$3);\n\n        if (!callback) {\n          return;\n        }\n\n        if (!animate) {\n          callback();\n          return;\n        }\n\n        var backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop);\n        $__default['default'](this._backdrop).one(Util.TRANSITION_END, callback).emulateTransitionEnd(backdropTransitionDuration);\n      } else if (!this._isShown && this._backdrop) {\n        $__default['default'](this._backdrop).removeClass(CLASS_NAME_SHOW$3);\n\n        var callbackRemove = function callbackRemove() {\n          _this9._removeBackdrop();\n\n          if (callback) {\n            callback();\n          }\n        };\n\n        if ($__default['default'](this._element).hasClass(CLASS_NAME_FADE$1)) {\n          var _backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop);\n\n          $__default['default'](this._backdrop).one(Util.TRANSITION_END, callbackRemove).emulateTransitionEnd(_backdropTransitionDuration);\n        } else {\n          callbackRemove();\n        }\n      } else if (callback) {\n        callback();\n      }\n    } // ----------------------------------------------------------------------\n    // the following methods are used to handle overflowing modals\n    // todo (fat): these should probably be refactored out of modal.js\n    // ----------------------------------------------------------------------\n    ;\n\n    _proto._adjustDialog = function _adjustDialog() {\n      var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;\n\n      if (!this._isBodyOverflowing && isModalOverflowing) {\n        this._element.style.paddingLeft = this._scrollbarWidth + \"px\";\n      }\n\n      if (this._isBodyOverflowing && !isModalOverflowing) {\n        this._element.style.paddingRight = this._scrollbarWidth + \"px\";\n      }\n    };\n\n    _proto._resetAdjustments = function _resetAdjustments() {\n      this._element.style.paddingLeft = '';\n      this._element.style.paddingRight = '';\n    };\n\n    _proto._checkScrollbar = function _checkScrollbar() {\n      var rect = document.body.getBoundingClientRect();\n      this._isBodyOverflowing = Math.round(rect.left + rect.right) < window.innerWidth;\n      this._scrollbarWidth = this._getScrollbarWidth();\n    };\n\n    _proto._setScrollbar = function _setScrollbar() {\n      var _this10 = this;\n\n      if (this._isBodyOverflowing) {\n        // Note: DOMNode.style.paddingRight returns the actual value or '' if not set\n        //   while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set\n        var fixedContent = [].slice.call(document.querySelectorAll(SELECTOR_FIXED_CONTENT));\n        var stickyContent = [].slice.call(document.querySelectorAll(SELECTOR_STICKY_CONTENT)); // Adjust fixed content padding\n\n        $__default['default'](fixedContent).each(function (index, element) {\n          var actualPadding = element.style.paddingRight;\n          var calculatedPadding = $__default['default'](element).css('padding-right');\n          $__default['default'](element).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + _this10._scrollbarWidth + \"px\");\n        }); // Adjust sticky content margin\n\n        $__default['default'](stickyContent).each(function (index, element) {\n          var actualMargin = element.style.marginRight;\n          var calculatedMargin = $__default['default'](element).css('margin-right');\n          $__default['default'](element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) - _this10._scrollbarWidth + \"px\");\n        }); // Adjust body padding\n\n        var actualPadding = document.body.style.paddingRight;\n        var calculatedPadding = $__default['default'](document.body).css('padding-right');\n        $__default['default'](document.body).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + this._scrollbarWidth + \"px\");\n      }\n\n      $__default['default'](document.body).addClass(CLASS_NAME_OPEN);\n    };\n\n    _proto._resetScrollbar = function _resetScrollbar() {\n      // Restore fixed content padding\n      var fixedContent = [].slice.call(document.querySelectorAll(SELECTOR_FIXED_CONTENT));\n      $__default['default'](fixedContent).each(function (index, element) {\n        var padding = $__default['default'](element).data('padding-right');\n        $__default['default'](element).removeData('padding-right');\n        element.style.paddingRight = padding ? padding : '';\n      }); // Restore sticky content\n\n      var elements = [].slice.call(document.querySelectorAll(\"\" + SELECTOR_STICKY_CONTENT));\n      $__default['default'](elements).each(function (index, element) {\n        var margin = $__default['default'](element).data('margin-right');\n\n        if (typeof margin !== 'undefined') {\n          $__default['default'](element).css('margin-right', margin).removeData('margin-right');\n        }\n      }); // Restore body padding\n\n      var padding = $__default['default'](document.body).data('padding-right');\n      $__default['default'](document.body).removeData('padding-right');\n      document.body.style.paddingRight = padding ? padding : '';\n    };\n\n    _proto._getScrollbarWidth = function _getScrollbarWidth() {\n      // thx d.walsh\n      var scrollDiv = document.createElement('div');\n      scrollDiv.className = CLASS_NAME_SCROLLBAR_MEASURER;\n      document.body.appendChild(scrollDiv);\n      var scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth;\n      document.body.removeChild(scrollDiv);\n      return scrollbarWidth;\n    } // Static\n    ;\n\n    Modal._jQueryInterface = function _jQueryInterface(config, relatedTarget) {\n      return this.each(function () {\n        var data = $__default['default'](this).data(DATA_KEY$5);\n\n        var _config = _extends({}, Default$3, $__default['default'](this).data(), typeof config === 'object' && config ? config : {});\n\n        if (!data) {\n          data = new Modal(this, _config);\n          $__default['default'](this).data(DATA_KEY$5, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config](relatedTarget);\n        } else if (_config.show) {\n          data.show(relatedTarget);\n        }\n      });\n    };\n\n    _createClass(Modal, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION$5;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default$3;\n      }\n    }]);\n\n    return Modal;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $__default['default'](document).on(EVENT_CLICK_DATA_API$5, SELECTOR_DATA_TOGGLE$3, function (event) {\n    var _this11 = this;\n\n    var target;\n    var selector = Util.getSelectorFromElement(this);\n\n    if (selector) {\n      target = document.querySelector(selector);\n    }\n\n    var config = $__default['default'](target).data(DATA_KEY$5) ? 'toggle' : _extends({}, $__default['default'](target).data(), $__default['default'](this).data());\n\n    if (this.tagName === 'A' || this.tagName === 'AREA') {\n      event.preventDefault();\n    }\n\n    var $target = $__default['default'](target).one(EVENT_SHOW$2, function (showEvent) {\n      if (showEvent.isDefaultPrevented()) {\n        // Only register focus restorer if modal will actually get shown\n        return;\n      }\n\n      $target.one(EVENT_HIDDEN$2, function () {\n        if ($__default['default'](_this11).is(':visible')) {\n          _this11.focus();\n        }\n      });\n    });\n\n    Modal._jQueryInterface.call($__default['default'](target), config, this);\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $__default['default'].fn[NAME$5] = Modal._jQueryInterface;\n  $__default['default'].fn[NAME$5].Constructor = Modal;\n\n  $__default['default'].fn[NAME$5].noConflict = function () {\n    $__default['default'].fn[NAME$5] = JQUERY_NO_CONFLICT$5;\n    return Modal._jQueryInterface;\n  };\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v4.5.3): tools/sanitizer.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n  var uriAttrs = ['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href'];\n  var ARIA_ATTRIBUTE_PATTERN = /^aria-[\\w-]*$/i;\n  var DefaultWhitelist = {\n    // Global attributes allowed on any supplied element below.\n    '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],\n    a: ['target', 'href', 'title', 'rel'],\n    area: [],\n    b: [],\n    br: [],\n    col: [],\n    code: [],\n    div: [],\n    em: [],\n    hr: [],\n    h1: [],\n    h2: [],\n    h3: [],\n    h4: [],\n    h5: [],\n    h6: [],\n    i: [],\n    img: ['src', 'srcset', 'alt', 'title', 'width', 'height'],\n    li: [],\n    ol: [],\n    p: [],\n    pre: [],\n    s: [],\n    small: [],\n    span: [],\n    sub: [],\n    sup: [],\n    strong: [],\n    u: [],\n    ul: []\n  };\n  /**\n   * A pattern that recognizes a commonly useful subset of URLs that are safe.\n   *\n   * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts\n   */\n\n  var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/gi;\n  /**\n   * A pattern that matches safe data URLs. Only matches image, video and audio types.\n   *\n   * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts\n   */\n\n  var DATA_URL_PATTERN = /^data:(?:image\\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\\/(?:mpeg|mp4|ogg|webm)|audio\\/(?:mp3|oga|ogg|opus));base64,[\\d+/a-z]+=*$/i;\n\n  function allowedAttribute(attr, allowedAttributeList) {\n    var attrName = attr.nodeName.toLowerCase();\n\n    if (allowedAttributeList.indexOf(attrName) !== -1) {\n      if (uriAttrs.indexOf(attrName) !== -1) {\n        return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN));\n      }\n\n      return true;\n    }\n\n    var regExp = allowedAttributeList.filter(function (attrRegex) {\n      return attrRegex instanceof RegExp;\n    }); // Check if a regular expression validates the attribute.\n\n    for (var i = 0, len = regExp.length; i < len; i++) {\n      if (attrName.match(regExp[i])) {\n        return true;\n      }\n    }\n\n    return false;\n  }\n\n  function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {\n    if (unsafeHtml.length === 0) {\n      return unsafeHtml;\n    }\n\n    if (sanitizeFn && typeof sanitizeFn === 'function') {\n      return sanitizeFn(unsafeHtml);\n    }\n\n    var domParser = new window.DOMParser();\n    var createdDocument = domParser.parseFromString(unsafeHtml, 'text/html');\n    var whitelistKeys = Object.keys(whiteList);\n    var elements = [].slice.call(createdDocument.body.querySelectorAll('*'));\n\n    var _loop = function _loop(i, len) {\n      var el = elements[i];\n      var elName = el.nodeName.toLowerCase();\n\n      if (whitelistKeys.indexOf(el.nodeName.toLowerCase()) === -1) {\n        el.parentNode.removeChild(el);\n        return \"continue\";\n      }\n\n      var attributeList = [].slice.call(el.attributes);\n      var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || []);\n      attributeList.forEach(function (attr) {\n        if (!allowedAttribute(attr, whitelistedAttributes)) {\n          el.removeAttribute(attr.nodeName);\n        }\n      });\n    };\n\n    for (var i = 0, len = elements.length; i < len; i++) {\n      var _ret = _loop(i);\n\n      if (_ret === \"continue\") continue;\n    }\n\n    return createdDocument.body.innerHTML;\n  }\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME$6 = 'tooltip';\n  var VERSION$6 = '4.5.3';\n  var DATA_KEY$6 = 'bs.tooltip';\n  var EVENT_KEY$6 = \".\" + DATA_KEY$6;\n  var JQUERY_NO_CONFLICT$6 = $__default['default'].fn[NAME$6];\n  var CLASS_PREFIX = 'bs-tooltip';\n  var BSCLS_PREFIX_REGEX = new RegExp(\"(^|\\\\s)\" + CLASS_PREFIX + \"\\\\S+\", 'g');\n  var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn'];\n  var DefaultType$4 = {\n    animation: 'boolean',\n    template: 'string',\n    title: '(string|element|function)',\n    trigger: 'string',\n    delay: '(number|object)',\n    html: 'boolean',\n    selector: '(string|boolean)',\n    placement: '(string|function)',\n    offset: '(number|string|function)',\n    container: '(string|element|boolean)',\n    fallbackPlacement: '(string|array)',\n    boundary: '(string|element)',\n    sanitize: 'boolean',\n    sanitizeFn: '(null|function)',\n    whiteList: 'object',\n    popperConfig: '(null|object)'\n  };\n  var AttachmentMap = {\n    AUTO: 'auto',\n    TOP: 'top',\n    RIGHT: 'right',\n    BOTTOM: 'bottom',\n    LEFT: 'left'\n  };\n  var Default$4 = {\n    animation: true,\n    template: '<div class=\"tooltip\" role=\"tooltip\">' + '<div class=\"arrow\"></div>' + '<div class=\"tooltip-inner\"></div></div>',\n    trigger: 'hover focus',\n    title: '',\n    delay: 0,\n    html: false,\n    selector: false,\n    placement: 'top',\n    offset: 0,\n    container: false,\n    fallbackPlacement: 'flip',\n    boundary: 'scrollParent',\n    sanitize: true,\n    sanitizeFn: null,\n    whiteList: DefaultWhitelist,\n    popperConfig: null\n  };\n  var HOVER_STATE_SHOW = 'show';\n  var HOVER_STATE_OUT = 'out';\n  var Event = {\n    HIDE: \"hide\" + EVENT_KEY$6,\n    HIDDEN: \"hidden\" + EVENT_KEY$6,\n    SHOW: \"show\" + EVENT_KEY$6,\n    SHOWN: \"shown\" + EVENT_KEY$6,\n    INSERTED: \"inserted\" + EVENT_KEY$6,\n    CLICK: \"click\" + EVENT_KEY$6,\n    FOCUSIN: \"focusin\" + EVENT_KEY$6,\n    FOCUSOUT: \"focusout\" + EVENT_KEY$6,\n    MOUSEENTER: \"mouseenter\" + EVENT_KEY$6,\n    MOUSELEAVE: \"mouseleave\" + EVENT_KEY$6\n  };\n  var CLASS_NAME_FADE$2 = 'fade';\n  var CLASS_NAME_SHOW$4 = 'show';\n  var SELECTOR_TOOLTIP_INNER = '.tooltip-inner';\n  var SELECTOR_ARROW = '.arrow';\n  var TRIGGER_HOVER = 'hover';\n  var TRIGGER_FOCUS = 'focus';\n  var TRIGGER_CLICK = 'click';\n  var TRIGGER_MANUAL = 'manual';\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  var Tooltip = /*#__PURE__*/function () {\n    function Tooltip(element, config) {\n      if (typeof Popper === 'undefined') {\n        throw new TypeError('Bootstrap\\'s tooltips require Popper.js (https://popper.js.org/)');\n      } // private\n\n\n      this._isEnabled = true;\n      this._timeout = 0;\n      this._hoverState = '';\n      this._activeTrigger = {};\n      this._popper = null; // Protected\n\n      this.element = element;\n      this.config = this._getConfig(config);\n      this.tip = null;\n\n      this._setListeners();\n    } // Getters\n\n\n    var _proto = Tooltip.prototype;\n\n    // Public\n    _proto.enable = function enable() {\n      this._isEnabled = true;\n    };\n\n    _proto.disable = function disable() {\n      this._isEnabled = false;\n    };\n\n    _proto.toggleEnabled = function toggleEnabled() {\n      this._isEnabled = !this._isEnabled;\n    };\n\n    _proto.toggle = function toggle(event) {\n      if (!this._isEnabled) {\n        return;\n      }\n\n      if (event) {\n        var dataKey = this.constructor.DATA_KEY;\n        var context = $__default['default'](event.currentTarget).data(dataKey);\n\n        if (!context) {\n          context = new this.constructor(event.currentTarget, this._getDelegateConfig());\n          $__default['default'](event.currentTarget).data(dataKey, context);\n        }\n\n        context._activeTrigger.click = !context._activeTrigger.click;\n\n        if (context._isWithActiveTrigger()) {\n          context._enter(null, context);\n        } else {\n          context._leave(null, context);\n        }\n      } else {\n        if ($__default['default'](this.getTipElement()).hasClass(CLASS_NAME_SHOW$4)) {\n          this._leave(null, this);\n\n          return;\n        }\n\n        this._enter(null, this);\n      }\n    };\n\n    _proto.dispose = function dispose() {\n      clearTimeout(this._timeout);\n      $__default['default'].removeData(this.element, this.constructor.DATA_KEY);\n      $__default['default'](this.element).off(this.constructor.EVENT_KEY);\n      $__default['default'](this.element).closest('.modal').off('hide.bs.modal', this._hideModalHandler);\n\n      if (this.tip) {\n        $__default['default'](this.tip).remove();\n      }\n\n      this._isEnabled = null;\n      this._timeout = null;\n      this._hoverState = null;\n      this._activeTrigger = null;\n\n      if (this._popper) {\n        this._popper.destroy();\n      }\n\n      this._popper = null;\n      this.element = null;\n      this.config = null;\n      this.tip = null;\n    };\n\n    _proto.show = function show() {\n      var _this = this;\n\n      if ($__default['default'](this.element).css('display') === 'none') {\n        throw new Error('Please use show on visible elements');\n      }\n\n      var showEvent = $__default['default'].Event(this.constructor.Event.SHOW);\n\n      if (this.isWithContent() && this._isEnabled) {\n        $__default['default'](this.element).trigger(showEvent);\n        var shadowRoot = Util.findShadowRoot(this.element);\n        var isInTheDom = $__default['default'].contains(shadowRoot !== null ? shadowRoot : this.element.ownerDocument.documentElement, this.element);\n\n        if (showEvent.isDefaultPrevented() || !isInTheDom) {\n          return;\n        }\n\n        var tip = this.getTipElement();\n        var tipId = Util.getUID(this.constructor.NAME);\n        tip.setAttribute('id', tipId);\n        this.element.setAttribute('aria-describedby', tipId);\n        this.setContent();\n\n        if (this.config.animation) {\n          $__default['default'](tip).addClass(CLASS_NAME_FADE$2);\n        }\n\n        var placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement;\n\n        var attachment = this._getAttachment(placement);\n\n        this.addAttachmentClass(attachment);\n\n        var container = this._getContainer();\n\n        $__default['default'](tip).data(this.constructor.DATA_KEY, this);\n\n        if (!$__default['default'].contains(this.element.ownerDocument.documentElement, this.tip)) {\n          $__default['default'](tip).appendTo(container);\n        }\n\n        $__default['default'](this.element).trigger(this.constructor.Event.INSERTED);\n        this._popper = new Popper(this.element, tip, this._getPopperConfig(attachment));\n        $__default['default'](tip).addClass(CLASS_NAME_SHOW$4); // If this is a touch-enabled device we add extra\n        // empty mouseover listeners to the body's immediate children;\n        // only needed because of broken event delegation on iOS\n        // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n\n        if ('ontouchstart' in document.documentElement) {\n          $__default['default'](document.body).children().on('mouseover', null, $__default['default'].noop);\n        }\n\n        var complete = function complete() {\n          if (_this.config.animation) {\n            _this._fixTransition();\n          }\n\n          var prevHoverState = _this._hoverState;\n          _this._hoverState = null;\n          $__default['default'](_this.element).trigger(_this.constructor.Event.SHOWN);\n\n          if (prevHoverState === HOVER_STATE_OUT) {\n            _this._leave(null, _this);\n          }\n        };\n\n        if ($__default['default'](this.tip).hasClass(CLASS_NAME_FADE$2)) {\n          var transitionDuration = Util.getTransitionDurationFromElement(this.tip);\n          $__default['default'](this.tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);\n        } else {\n          complete();\n        }\n      }\n    };\n\n    _proto.hide = function hide(callback) {\n      var _this2 = this;\n\n      var tip = this.getTipElement();\n      var hideEvent = $__default['default'].Event(this.constructor.Event.HIDE);\n\n      var complete = function complete() {\n        if (_this2._hoverState !== HOVER_STATE_SHOW && tip.parentNode) {\n          tip.parentNode.removeChild(tip);\n        }\n\n        _this2._cleanTipClass();\n\n        _this2.element.removeAttribute('aria-describedby');\n\n        $__default['default'](_this2.element).trigger(_this2.constructor.Event.HIDDEN);\n\n        if (_this2._popper !== null) {\n          _this2._popper.destroy();\n        }\n\n        if (callback) {\n          callback();\n        }\n      };\n\n      $__default['default'](this.element).trigger(hideEvent);\n\n      if (hideEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      $__default['default'](tip).removeClass(CLASS_NAME_SHOW$4); // If this is a touch-enabled device we remove the extra\n      // empty mouseover listeners we added for iOS support\n\n      if ('ontouchstart' in document.documentElement) {\n        $__default['default'](document.body).children().off('mouseover', null, $__default['default'].noop);\n      }\n\n      this._activeTrigger[TRIGGER_CLICK] = false;\n      this._activeTrigger[TRIGGER_FOCUS] = false;\n      this._activeTrigger[TRIGGER_HOVER] = false;\n\n      if ($__default['default'](this.tip).hasClass(CLASS_NAME_FADE$2)) {\n        var transitionDuration = Util.getTransitionDurationFromElement(tip);\n        $__default['default'](tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);\n      } else {\n        complete();\n      }\n\n      this._hoverState = '';\n    };\n\n    _proto.update = function update() {\n      if (this._popper !== null) {\n        this._popper.scheduleUpdate();\n      }\n    } // Protected\n    ;\n\n    _proto.isWithContent = function isWithContent() {\n      return Boolean(this.getTitle());\n    };\n\n    _proto.addAttachmentClass = function addAttachmentClass(attachment) {\n      $__default['default'](this.getTipElement()).addClass(CLASS_PREFIX + \"-\" + attachment);\n    };\n\n    _proto.getTipElement = function getTipElement() {\n      this.tip = this.tip || $__default['default'](this.config.template)[0];\n      return this.tip;\n    };\n\n    _proto.setContent = function setContent() {\n      var tip = this.getTipElement();\n      this.setElementContent($__default['default'](tip.querySelectorAll(SELECTOR_TOOLTIP_INNER)), this.getTitle());\n      $__default['default'](tip).removeClass(CLASS_NAME_FADE$2 + \" \" + CLASS_NAME_SHOW$4);\n    };\n\n    _proto.setElementContent = function setElementContent($element, content) {\n      if (typeof content === 'object' && (content.nodeType || content.jquery)) {\n        // Content is a DOM node or a jQuery\n        if (this.config.html) {\n          if (!$__default['default'](content).parent().is($element)) {\n            $element.empty().append(content);\n          }\n        } else {\n          $element.text($__default['default'](content).text());\n        }\n\n        return;\n      }\n\n      if (this.config.html) {\n        if (this.config.sanitize) {\n          content = sanitizeHtml(content, this.config.whiteList, this.config.sanitizeFn);\n        }\n\n        $element.html(content);\n      } else {\n        $element.text(content);\n      }\n    };\n\n    _proto.getTitle = function getTitle() {\n      var title = this.element.getAttribute('data-original-title');\n\n      if (!title) {\n        title = typeof this.config.title === 'function' ? this.config.title.call(this.element) : this.config.title;\n      }\n\n      return title;\n    } // Private\n    ;\n\n    _proto._getPopperConfig = function _getPopperConfig(attachment) {\n      var _this3 = this;\n\n      var defaultBsConfig = {\n        placement: attachment,\n        modifiers: {\n          offset: this._getOffset(),\n          flip: {\n            behavior: this.config.fallbackPlacement\n          },\n          arrow: {\n            element: SELECTOR_ARROW\n          },\n          preventOverflow: {\n            boundariesElement: this.config.boundary\n          }\n        },\n        onCreate: function onCreate(data) {\n          if (data.originalPlacement !== data.placement) {\n            _this3._handlePopperPlacementChange(data);\n          }\n        },\n        onUpdate: function onUpdate(data) {\n          return _this3._handlePopperPlacementChange(data);\n        }\n      };\n      return _extends({}, defaultBsConfig, this.config.popperConfig);\n    };\n\n    _proto._getOffset = function _getOffset() {\n      var _this4 = this;\n\n      var offset = {};\n\n      if (typeof this.config.offset === 'function') {\n        offset.fn = function (data) {\n          data.offsets = _extends({}, data.offsets, _this4.config.offset(data.offsets, _this4.element) || {});\n          return data;\n        };\n      } else {\n        offset.offset = this.config.offset;\n      }\n\n      return offset;\n    };\n\n    _proto._getContainer = function _getContainer() {\n      if (this.config.container === false) {\n        return document.body;\n      }\n\n      if (Util.isElement(this.config.container)) {\n        return $__default['default'](this.config.container);\n      }\n\n      return $__default['default'](document).find(this.config.container);\n    };\n\n    _proto._getAttachment = function _getAttachment(placement) {\n      return AttachmentMap[placement.toUpperCase()];\n    };\n\n    _proto._setListeners = function _setListeners() {\n      var _this5 = this;\n\n      var triggers = this.config.trigger.split(' ');\n      triggers.forEach(function (trigger) {\n        if (trigger === 'click') {\n          $__default['default'](_this5.element).on(_this5.constructor.Event.CLICK, _this5.config.selector, function (event) {\n            return _this5.toggle(event);\n          });\n        } else if (trigger !== TRIGGER_MANUAL) {\n          var eventIn = trigger === TRIGGER_HOVER ? _this5.constructor.Event.MOUSEENTER : _this5.constructor.Event.FOCUSIN;\n          var eventOut = trigger === TRIGGER_HOVER ? _this5.constructor.Event.MOUSELEAVE : _this5.constructor.Event.FOCUSOUT;\n          $__default['default'](_this5.element).on(eventIn, _this5.config.selector, function (event) {\n            return _this5._enter(event);\n          }).on(eventOut, _this5.config.selector, function (event) {\n            return _this5._leave(event);\n          });\n        }\n      });\n\n      this._hideModalHandler = function () {\n        if (_this5.element) {\n          _this5.hide();\n        }\n      };\n\n      $__default['default'](this.element).closest('.modal').on('hide.bs.modal', this._hideModalHandler);\n\n      if (this.config.selector) {\n        this.config = _extends({}, this.config, {\n          trigger: 'manual',\n          selector: ''\n        });\n      } else {\n        this._fixTitle();\n      }\n    };\n\n    _proto._fixTitle = function _fixTitle() {\n      var titleType = typeof this.element.getAttribute('data-original-title');\n\n      if (this.element.getAttribute('title') || titleType !== 'string') {\n        this.element.setAttribute('data-original-title', this.element.getAttribute('title') || '');\n        this.element.setAttribute('title', '');\n      }\n    };\n\n    _proto._enter = function _enter(event, context) {\n      var dataKey = this.constructor.DATA_KEY;\n      context = context || $__default['default'](event.currentTarget).data(dataKey);\n\n      if (!context) {\n        context = new this.constructor(event.currentTarget, this._getDelegateConfig());\n        $__default['default'](event.currentTarget).data(dataKey, context);\n      }\n\n      if (event) {\n        context._activeTrigger[event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER] = true;\n      }\n\n      if ($__default['default'](context.getTipElement()).hasClass(CLASS_NAME_SHOW$4) || context._hoverState === HOVER_STATE_SHOW) {\n        context._hoverState = HOVER_STATE_SHOW;\n        return;\n      }\n\n      clearTimeout(context._timeout);\n      context._hoverState = HOVER_STATE_SHOW;\n\n      if (!context.config.delay || !context.config.delay.show) {\n        context.show();\n        return;\n      }\n\n      context._timeout = setTimeout(function () {\n        if (context._hoverState === HOVER_STATE_SHOW) {\n          context.show();\n        }\n      }, context.config.delay.show);\n    };\n\n    _proto._leave = function _leave(event, context) {\n      var dataKey = this.constructor.DATA_KEY;\n      context = context || $__default['default'](event.currentTarget).data(dataKey);\n\n      if (!context) {\n        context = new this.constructor(event.currentTarget, this._getDelegateConfig());\n        $__default['default'](event.currentTarget).data(dataKey, context);\n      }\n\n      if (event) {\n        context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] = false;\n      }\n\n      if (context._isWithActiveTrigger()) {\n        return;\n      }\n\n      clearTimeout(context._timeout);\n      context._hoverState = HOVER_STATE_OUT;\n\n      if (!context.config.delay || !context.config.delay.hide) {\n        context.hide();\n        return;\n      }\n\n      context._timeout = setTimeout(function () {\n        if (context._hoverState === HOVER_STATE_OUT) {\n          context.hide();\n        }\n      }, context.config.delay.hide);\n    };\n\n    _proto._isWithActiveTrigger = function _isWithActiveTrigger() {\n      for (var trigger in this._activeTrigger) {\n        if (this._activeTrigger[trigger]) {\n          return true;\n        }\n      }\n\n      return false;\n    };\n\n    _proto._getConfig = function _getConfig(config) {\n      var dataAttributes = $__default['default'](this.element).data();\n      Object.keys(dataAttributes).forEach(function (dataAttr) {\n        if (DISALLOWED_ATTRIBUTES.indexOf(dataAttr) !== -1) {\n          delete dataAttributes[dataAttr];\n        }\n      });\n      config = _extends({}, this.constructor.Default, dataAttributes, typeof config === 'object' && config ? config : {});\n\n      if (typeof config.delay === 'number') {\n        config.delay = {\n          show: config.delay,\n          hide: config.delay\n        };\n      }\n\n      if (typeof config.title === 'number') {\n        config.title = config.title.toString();\n      }\n\n      if (typeof config.content === 'number') {\n        config.content = config.content.toString();\n      }\n\n      Util.typeCheckConfig(NAME$6, config, this.constructor.DefaultType);\n\n      if (config.sanitize) {\n        config.template = sanitizeHtml(config.template, config.whiteList, config.sanitizeFn);\n      }\n\n      return config;\n    };\n\n    _proto._getDelegateConfig = function _getDelegateConfig() {\n      var config = {};\n\n      if (this.config) {\n        for (var key in this.config) {\n          if (this.constructor.Default[key] !== this.config[key]) {\n            config[key] = this.config[key];\n          }\n        }\n      }\n\n      return config;\n    };\n\n    _proto._cleanTipClass = function _cleanTipClass() {\n      var $tip = $__default['default'](this.getTipElement());\n      var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX);\n\n      if (tabClass !== null && tabClass.length) {\n        $tip.removeClass(tabClass.join(''));\n      }\n    };\n\n    _proto._handlePopperPlacementChange = function _handlePopperPlacementChange(popperData) {\n      this.tip = popperData.instance.popper;\n\n      this._cleanTipClass();\n\n      this.addAttachmentClass(this._getAttachment(popperData.placement));\n    };\n\n    _proto._fixTransition = function _fixTransition() {\n      var tip = this.getTipElement();\n      var initConfigAnimation = this.config.animation;\n\n      if (tip.getAttribute('x-placement') !== null) {\n        return;\n      }\n\n      $__default['default'](tip).removeClass(CLASS_NAME_FADE$2);\n      this.config.animation = false;\n      this.hide();\n      this.show();\n      this.config.animation = initConfigAnimation;\n    } // Static\n    ;\n\n    Tooltip._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var $element = $__default['default'](this);\n        var data = $element.data(DATA_KEY$6);\n\n        var _config = typeof config === 'object' && config;\n\n        if (!data && /dispose|hide/.test(config)) {\n          return;\n        }\n\n        if (!data) {\n          data = new Tooltip(this, _config);\n          $element.data(DATA_KEY$6, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    _createClass(Tooltip, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION$6;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default$4;\n      }\n    }, {\n      key: \"NAME\",\n      get: function get() {\n        return NAME$6;\n      }\n    }, {\n      key: \"DATA_KEY\",\n      get: function get() {\n        return DATA_KEY$6;\n      }\n    }, {\n      key: \"Event\",\n      get: function get() {\n        return Event;\n      }\n    }, {\n      key: \"EVENT_KEY\",\n      get: function get() {\n        return EVENT_KEY$6;\n      }\n    }, {\n      key: \"DefaultType\",\n      get: function get() {\n        return DefaultType$4;\n      }\n    }]);\n\n    return Tooltip;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n\n  $__default['default'].fn[NAME$6] = Tooltip._jQueryInterface;\n  $__default['default'].fn[NAME$6].Constructor = Tooltip;\n\n  $__default['default'].fn[NAME$6].noConflict = function () {\n    $__default['default'].fn[NAME$6] = JQUERY_NO_CONFLICT$6;\n    return Tooltip._jQueryInterface;\n  };\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME$7 = 'popover';\n  var VERSION$7 = '4.5.3';\n  var DATA_KEY$7 = 'bs.popover';\n  var EVENT_KEY$7 = \".\" + DATA_KEY$7;\n  var JQUERY_NO_CONFLICT$7 = $__default['default'].fn[NAME$7];\n  var CLASS_PREFIX$1 = 'bs-popover';\n  var BSCLS_PREFIX_REGEX$1 = new RegExp(\"(^|\\\\s)\" + CLASS_PREFIX$1 + \"\\\\S+\", 'g');\n\n  var Default$5 = _extends({}, Tooltip.Default, {\n    placement: 'right',\n    trigger: 'click',\n    content: '',\n    template: '<div class=\"popover\" role=\"tooltip\">' + '<div class=\"arrow\"></div>' + '<h3 class=\"popover-header\"></h3>' + '<div class=\"popover-body\"></div></div>'\n  });\n\n  var DefaultType$5 = _extends({}, Tooltip.DefaultType, {\n    content: '(string|element|function)'\n  });\n\n  var CLASS_NAME_FADE$3 = 'fade';\n  var CLASS_NAME_SHOW$5 = 'show';\n  var SELECTOR_TITLE = '.popover-header';\n  var SELECTOR_CONTENT = '.popover-body';\n  var Event$1 = {\n    HIDE: \"hide\" + EVENT_KEY$7,\n    HIDDEN: \"hidden\" + EVENT_KEY$7,\n    SHOW: \"show\" + EVENT_KEY$7,\n    SHOWN: \"shown\" + EVENT_KEY$7,\n    INSERTED: \"inserted\" + EVENT_KEY$7,\n    CLICK: \"click\" + EVENT_KEY$7,\n    FOCUSIN: \"focusin\" + EVENT_KEY$7,\n    FOCUSOUT: \"focusout\" + EVENT_KEY$7,\n    MOUSEENTER: \"mouseenter\" + EVENT_KEY$7,\n    MOUSELEAVE: \"mouseleave\" + EVENT_KEY$7\n  };\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  var Popover = /*#__PURE__*/function (_Tooltip) {\n    _inheritsLoose(Popover, _Tooltip);\n\n    function Popover() {\n      return _Tooltip.apply(this, arguments) || this;\n    }\n\n    var _proto = Popover.prototype;\n\n    // Overrides\n    _proto.isWithContent = function isWithContent() {\n      return this.getTitle() || this._getContent();\n    };\n\n    _proto.addAttachmentClass = function addAttachmentClass(attachment) {\n      $__default['default'](this.getTipElement()).addClass(CLASS_PREFIX$1 + \"-\" + attachment);\n    };\n\n    _proto.getTipElement = function getTipElement() {\n      this.tip = this.tip || $__default['default'](this.config.template)[0];\n      return this.tip;\n    };\n\n    _proto.setContent = function setContent() {\n      var $tip = $__default['default'](this.getTipElement()); // We use append for html objects to maintain js events\n\n      this.setElementContent($tip.find(SELECTOR_TITLE), this.getTitle());\n\n      var content = this._getContent();\n\n      if (typeof content === 'function') {\n        content = content.call(this.element);\n      }\n\n      this.setElementContent($tip.find(SELECTOR_CONTENT), content);\n      $tip.removeClass(CLASS_NAME_FADE$3 + \" \" + CLASS_NAME_SHOW$5);\n    } // Private\n    ;\n\n    _proto._getContent = function _getContent() {\n      return this.element.getAttribute('data-content') || this.config.content;\n    };\n\n    _proto._cleanTipClass = function _cleanTipClass() {\n      var $tip = $__default['default'](this.getTipElement());\n      var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX$1);\n\n      if (tabClass !== null && tabClass.length > 0) {\n        $tip.removeClass(tabClass.join(''));\n      }\n    } // Static\n    ;\n\n    Popover._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var data = $__default['default'](this).data(DATA_KEY$7);\n\n        var _config = typeof config === 'object' ? config : null;\n\n        if (!data && /dispose|hide/.test(config)) {\n          return;\n        }\n\n        if (!data) {\n          data = new Popover(this, _config);\n          $__default['default'](this).data(DATA_KEY$7, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    _createClass(Popover, null, [{\n      key: \"VERSION\",\n      // Getters\n      get: function get() {\n        return VERSION$7;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default$5;\n      }\n    }, {\n      key: \"NAME\",\n      get: function get() {\n        return NAME$7;\n      }\n    }, {\n      key: \"DATA_KEY\",\n      get: function get() {\n        return DATA_KEY$7;\n      }\n    }, {\n      key: \"Event\",\n      get: function get() {\n        return Event$1;\n      }\n    }, {\n      key: \"EVENT_KEY\",\n      get: function get() {\n        return EVENT_KEY$7;\n      }\n    }, {\n      key: \"DefaultType\",\n      get: function get() {\n        return DefaultType$5;\n      }\n    }]);\n\n    return Popover;\n  }(Tooltip);\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n\n  $__default['default'].fn[NAME$7] = Popover._jQueryInterface;\n  $__default['default'].fn[NAME$7].Constructor = Popover;\n\n  $__default['default'].fn[NAME$7].noConflict = function () {\n    $__default['default'].fn[NAME$7] = JQUERY_NO_CONFLICT$7;\n    return Popover._jQueryInterface;\n  };\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME$8 = 'scrollspy';\n  var VERSION$8 = '4.5.3';\n  var DATA_KEY$8 = 'bs.scrollspy';\n  var EVENT_KEY$8 = \".\" + DATA_KEY$8;\n  var DATA_API_KEY$6 = '.data-api';\n  var JQUERY_NO_CONFLICT$8 = $__default['default'].fn[NAME$8];\n  var Default$6 = {\n    offset: 10,\n    method: 'auto',\n    target: ''\n  };\n  var DefaultType$6 = {\n    offset: 'number',\n    method: 'string',\n    target: '(string|element)'\n  };\n  var EVENT_ACTIVATE = \"activate\" + EVENT_KEY$8;\n  var EVENT_SCROLL = \"scroll\" + EVENT_KEY$8;\n  var EVENT_LOAD_DATA_API$2 = \"load\" + EVENT_KEY$8 + DATA_API_KEY$6;\n  var CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item';\n  var CLASS_NAME_ACTIVE$2 = 'active';\n  var SELECTOR_DATA_SPY = '[data-spy=\"scroll\"]';\n  var SELECTOR_NAV_LIST_GROUP = '.nav, .list-group';\n  var SELECTOR_NAV_LINKS = '.nav-link';\n  var SELECTOR_NAV_ITEMS = '.nav-item';\n  var SELECTOR_LIST_ITEMS = '.list-group-item';\n  var SELECTOR_DROPDOWN = '.dropdown';\n  var SELECTOR_DROPDOWN_ITEMS = '.dropdown-item';\n  var SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle';\n  var METHOD_OFFSET = 'offset';\n  var METHOD_POSITION = 'position';\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  var ScrollSpy = /*#__PURE__*/function () {\n    function ScrollSpy(element, config) {\n      var _this = this;\n\n      this._element = element;\n      this._scrollElement = element.tagName === 'BODY' ? window : element;\n      this._config = this._getConfig(config);\n      this._selector = this._config.target + \" \" + SELECTOR_NAV_LINKS + \",\" + (this._config.target + \" \" + SELECTOR_LIST_ITEMS + \",\") + (this._config.target + \" \" + SELECTOR_DROPDOWN_ITEMS);\n      this._offsets = [];\n      this._targets = [];\n      this._activeTarget = null;\n      this._scrollHeight = 0;\n      $__default['default'](this._scrollElement).on(EVENT_SCROLL, function (event) {\n        return _this._process(event);\n      });\n      this.refresh();\n\n      this._process();\n    } // Getters\n\n\n    var _proto = ScrollSpy.prototype;\n\n    // Public\n    _proto.refresh = function refresh() {\n      var _this2 = this;\n\n      var autoMethod = this._scrollElement === this._scrollElement.window ? METHOD_OFFSET : METHOD_POSITION;\n      var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method;\n      var offsetBase = offsetMethod === METHOD_POSITION ? this._getScrollTop() : 0;\n      this._offsets = [];\n      this._targets = [];\n      this._scrollHeight = this._getScrollHeight();\n      var targets = [].slice.call(document.querySelectorAll(this._selector));\n      targets.map(function (element) {\n        var target;\n        var targetSelector = Util.getSelectorFromElement(element);\n\n        if (targetSelector) {\n          target = document.querySelector(targetSelector);\n        }\n\n        if (target) {\n          var targetBCR = target.getBoundingClientRect();\n\n          if (targetBCR.width || targetBCR.height) {\n            // TODO (fat): remove sketch reliance on jQuery position/offset\n            return [$__default['default'](target)[offsetMethod]().top + offsetBase, targetSelector];\n          }\n        }\n\n        return null;\n      }).filter(function (item) {\n        return item;\n      }).sort(function (a, b) {\n        return a[0] - b[0];\n      }).forEach(function (item) {\n        _this2._offsets.push(item[0]);\n\n        _this2._targets.push(item[1]);\n      });\n    };\n\n    _proto.dispose = function dispose() {\n      $__default['default'].removeData(this._element, DATA_KEY$8);\n      $__default['default'](this._scrollElement).off(EVENT_KEY$8);\n      this._element = null;\n      this._scrollElement = null;\n      this._config = null;\n      this._selector = null;\n      this._offsets = null;\n      this._targets = null;\n      this._activeTarget = null;\n      this._scrollHeight = null;\n    } // Private\n    ;\n\n    _proto._getConfig = function _getConfig(config) {\n      config = _extends({}, Default$6, typeof config === 'object' && config ? config : {});\n\n      if (typeof config.target !== 'string' && Util.isElement(config.target)) {\n        var id = $__default['default'](config.target).attr('id');\n\n        if (!id) {\n          id = Util.getUID(NAME$8);\n          $__default['default'](config.target).attr('id', id);\n        }\n\n        config.target = \"#\" + id;\n      }\n\n      Util.typeCheckConfig(NAME$8, config, DefaultType$6);\n      return config;\n    };\n\n    _proto._getScrollTop = function _getScrollTop() {\n      return this._scrollElement === window ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop;\n    };\n\n    _proto._getScrollHeight = function _getScrollHeight() {\n      return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);\n    };\n\n    _proto._getOffsetHeight = function _getOffsetHeight() {\n      return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height;\n    };\n\n    _proto._process = function _process() {\n      var scrollTop = this._getScrollTop() + this._config.offset;\n\n      var scrollHeight = this._getScrollHeight();\n\n      var maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight();\n\n      if (this._scrollHeight !== scrollHeight) {\n        this.refresh();\n      }\n\n      if (scrollTop >= maxScroll) {\n        var target = this._targets[this._targets.length - 1];\n\n        if (this._activeTarget !== target) {\n          this._activate(target);\n        }\n\n        return;\n      }\n\n      if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) {\n        this._activeTarget = null;\n\n        this._clear();\n\n        return;\n      }\n\n      for (var i = this._offsets.length; i--;) {\n        var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]);\n\n        if (isActiveTarget) {\n          this._activate(this._targets[i]);\n        }\n      }\n    };\n\n    _proto._activate = function _activate(target) {\n      this._activeTarget = target;\n\n      this._clear();\n\n      var queries = this._selector.split(',').map(function (selector) {\n        return selector + \"[data-target=\\\"\" + target + \"\\\"],\" + selector + \"[href=\\\"\" + target + \"\\\"]\";\n      });\n\n      var $link = $__default['default']([].slice.call(document.querySelectorAll(queries.join(','))));\n\n      if ($link.hasClass(CLASS_NAME_DROPDOWN_ITEM)) {\n        $link.closest(SELECTOR_DROPDOWN).find(SELECTOR_DROPDOWN_TOGGLE).addClass(CLASS_NAME_ACTIVE$2);\n        $link.addClass(CLASS_NAME_ACTIVE$2);\n      } else {\n        // Set triggered link as active\n        $link.addClass(CLASS_NAME_ACTIVE$2); // Set triggered links parents as active\n        // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor\n\n        $link.parents(SELECTOR_NAV_LIST_GROUP).prev(SELECTOR_NAV_LINKS + \", \" + SELECTOR_LIST_ITEMS).addClass(CLASS_NAME_ACTIVE$2); // Handle special case when .nav-link is inside .nav-item\n\n        $link.parents(SELECTOR_NAV_LIST_GROUP).prev(SELECTOR_NAV_ITEMS).children(SELECTOR_NAV_LINKS).addClass(CLASS_NAME_ACTIVE$2);\n      }\n\n      $__default['default'](this._scrollElement).trigger(EVENT_ACTIVATE, {\n        relatedTarget: target\n      });\n    };\n\n    _proto._clear = function _clear() {\n      [].slice.call(document.querySelectorAll(this._selector)).filter(function (node) {\n        return node.classList.contains(CLASS_NAME_ACTIVE$2);\n      }).forEach(function (node) {\n        return node.classList.remove(CLASS_NAME_ACTIVE$2);\n      });\n    } // Static\n    ;\n\n    ScrollSpy._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var data = $__default['default'](this).data(DATA_KEY$8);\n\n        var _config = typeof config === 'object' && config;\n\n        if (!data) {\n          data = new ScrollSpy(this, _config);\n          $__default['default'](this).data(DATA_KEY$8, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    _createClass(ScrollSpy, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION$8;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default$6;\n      }\n    }]);\n\n    return ScrollSpy;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $__default['default'](window).on(EVENT_LOAD_DATA_API$2, function () {\n    var scrollSpys = [].slice.call(document.querySelectorAll(SELECTOR_DATA_SPY));\n    var scrollSpysLength = scrollSpys.length;\n\n    for (var i = scrollSpysLength; i--;) {\n      var $spy = $__default['default'](scrollSpys[i]);\n\n      ScrollSpy._jQueryInterface.call($spy, $spy.data());\n    }\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $__default['default'].fn[NAME$8] = ScrollSpy._jQueryInterface;\n  $__default['default'].fn[NAME$8].Constructor = ScrollSpy;\n\n  $__default['default'].fn[NAME$8].noConflict = function () {\n    $__default['default'].fn[NAME$8] = JQUERY_NO_CONFLICT$8;\n    return ScrollSpy._jQueryInterface;\n  };\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME$9 = 'tab';\n  var VERSION$9 = '4.5.3';\n  var DATA_KEY$9 = 'bs.tab';\n  var EVENT_KEY$9 = \".\" + DATA_KEY$9;\n  var DATA_API_KEY$7 = '.data-api';\n  var JQUERY_NO_CONFLICT$9 = $__default['default'].fn[NAME$9];\n  var EVENT_HIDE$3 = \"hide\" + EVENT_KEY$9;\n  var EVENT_HIDDEN$3 = \"hidden\" + EVENT_KEY$9;\n  var EVENT_SHOW$3 = \"show\" + EVENT_KEY$9;\n  var EVENT_SHOWN$3 = \"shown\" + EVENT_KEY$9;\n  var EVENT_CLICK_DATA_API$6 = \"click\" + EVENT_KEY$9 + DATA_API_KEY$7;\n  var CLASS_NAME_DROPDOWN_MENU = 'dropdown-menu';\n  var CLASS_NAME_ACTIVE$3 = 'active';\n  var CLASS_NAME_DISABLED$1 = 'disabled';\n  var CLASS_NAME_FADE$4 = 'fade';\n  var CLASS_NAME_SHOW$6 = 'show';\n  var SELECTOR_DROPDOWN$1 = '.dropdown';\n  var SELECTOR_NAV_LIST_GROUP$1 = '.nav, .list-group';\n  var SELECTOR_ACTIVE$2 = '.active';\n  var SELECTOR_ACTIVE_UL = '> li > .active';\n  var SELECTOR_DATA_TOGGLE$4 = '[data-toggle=\"tab\"], [data-toggle=\"pill\"], [data-toggle=\"list\"]';\n  var SELECTOR_DROPDOWN_TOGGLE$1 = '.dropdown-toggle';\n  var SELECTOR_DROPDOWN_ACTIVE_CHILD = '> .dropdown-menu .active';\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  var Tab = /*#__PURE__*/function () {\n    function Tab(element) {\n      this._element = element;\n    } // Getters\n\n\n    var _proto = Tab.prototype;\n\n    // Public\n    _proto.show = function show() {\n      var _this = this;\n\n      if (this._element.parentNode && this._element.parentNode.nodeType === Node.ELEMENT_NODE && $__default['default'](this._element).hasClass(CLASS_NAME_ACTIVE$3) || $__default['default'](this._element).hasClass(CLASS_NAME_DISABLED$1)) {\n        return;\n      }\n\n      var target;\n      var previous;\n      var listElement = $__default['default'](this._element).closest(SELECTOR_NAV_LIST_GROUP$1)[0];\n      var selector = Util.getSelectorFromElement(this._element);\n\n      if (listElement) {\n        var itemSelector = listElement.nodeName === 'UL' || listElement.nodeName === 'OL' ? SELECTOR_ACTIVE_UL : SELECTOR_ACTIVE$2;\n        previous = $__default['default'].makeArray($__default['default'](listElement).find(itemSelector));\n        previous = previous[previous.length - 1];\n      }\n\n      var hideEvent = $__default['default'].Event(EVENT_HIDE$3, {\n        relatedTarget: this._element\n      });\n      var showEvent = $__default['default'].Event(EVENT_SHOW$3, {\n        relatedTarget: previous\n      });\n\n      if (previous) {\n        $__default['default'](previous).trigger(hideEvent);\n      }\n\n      $__default['default'](this._element).trigger(showEvent);\n\n      if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      if (selector) {\n        target = document.querySelector(selector);\n      }\n\n      this._activate(this._element, listElement);\n\n      var complete = function complete() {\n        var hiddenEvent = $__default['default'].Event(EVENT_HIDDEN$3, {\n          relatedTarget: _this._element\n        });\n        var shownEvent = $__default['default'].Event(EVENT_SHOWN$3, {\n          relatedTarget: previous\n        });\n        $__default['default'](previous).trigger(hiddenEvent);\n        $__default['default'](_this._element).trigger(shownEvent);\n      };\n\n      if (target) {\n        this._activate(target, target.parentNode, complete);\n      } else {\n        complete();\n      }\n    };\n\n    _proto.dispose = function dispose() {\n      $__default['default'].removeData(this._element, DATA_KEY$9);\n      this._element = null;\n    } // Private\n    ;\n\n    _proto._activate = function _activate(element, container, callback) {\n      var _this2 = this;\n\n      var activeElements = container && (container.nodeName === 'UL' || container.nodeName === 'OL') ? $__default['default'](container).find(SELECTOR_ACTIVE_UL) : $__default['default'](container).children(SELECTOR_ACTIVE$2);\n      var active = activeElements[0];\n      var isTransitioning = callback && active && $__default['default'](active).hasClass(CLASS_NAME_FADE$4);\n\n      var complete = function complete() {\n        return _this2._transitionComplete(element, active, callback);\n      };\n\n      if (active && isTransitioning) {\n        var transitionDuration = Util.getTransitionDurationFromElement(active);\n        $__default['default'](active).removeClass(CLASS_NAME_SHOW$6).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);\n      } else {\n        complete();\n      }\n    };\n\n    _proto._transitionComplete = function _transitionComplete(element, active, callback) {\n      if (active) {\n        $__default['default'](active).removeClass(CLASS_NAME_ACTIVE$3);\n        var dropdownChild = $__default['default'](active.parentNode).find(SELECTOR_DROPDOWN_ACTIVE_CHILD)[0];\n\n        if (dropdownChild) {\n          $__default['default'](dropdownChild).removeClass(CLASS_NAME_ACTIVE$3);\n        }\n\n        if (active.getAttribute('role') === 'tab') {\n          active.setAttribute('aria-selected', false);\n        }\n      }\n\n      $__default['default'](element).addClass(CLASS_NAME_ACTIVE$3);\n\n      if (element.getAttribute('role') === 'tab') {\n        element.setAttribute('aria-selected', true);\n      }\n\n      Util.reflow(element);\n\n      if (element.classList.contains(CLASS_NAME_FADE$4)) {\n        element.classList.add(CLASS_NAME_SHOW$6);\n      }\n\n      if (element.parentNode && $__default['default'](element.parentNode).hasClass(CLASS_NAME_DROPDOWN_MENU)) {\n        var dropdownElement = $__default['default'](element).closest(SELECTOR_DROPDOWN$1)[0];\n\n        if (dropdownElement) {\n          var dropdownToggleList = [].slice.call(dropdownElement.querySelectorAll(SELECTOR_DROPDOWN_TOGGLE$1));\n          $__default['default'](dropdownToggleList).addClass(CLASS_NAME_ACTIVE$3);\n        }\n\n        element.setAttribute('aria-expanded', true);\n      }\n\n      if (callback) {\n        callback();\n      }\n    } // Static\n    ;\n\n    Tab._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var $this = $__default['default'](this);\n        var data = $this.data(DATA_KEY$9);\n\n        if (!data) {\n          data = new Tab(this);\n          $this.data(DATA_KEY$9, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    _createClass(Tab, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION$9;\n      }\n    }]);\n\n    return Tab;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $__default['default'](document).on(EVENT_CLICK_DATA_API$6, SELECTOR_DATA_TOGGLE$4, function (event) {\n    event.preventDefault();\n\n    Tab._jQueryInterface.call($__default['default'](this), 'show');\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $__default['default'].fn[NAME$9] = Tab._jQueryInterface;\n  $__default['default'].fn[NAME$9].Constructor = Tab;\n\n  $__default['default'].fn[NAME$9].noConflict = function () {\n    $__default['default'].fn[NAME$9] = JQUERY_NO_CONFLICT$9;\n    return Tab._jQueryInterface;\n  };\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME$a = 'toast';\n  var VERSION$a = '4.5.3';\n  var DATA_KEY$a = 'bs.toast';\n  var EVENT_KEY$a = \".\" + DATA_KEY$a;\n  var JQUERY_NO_CONFLICT$a = $__default['default'].fn[NAME$a];\n  var EVENT_CLICK_DISMISS$1 = \"click.dismiss\" + EVENT_KEY$a;\n  var EVENT_HIDE$4 = \"hide\" + EVENT_KEY$a;\n  var EVENT_HIDDEN$4 = \"hidden\" + EVENT_KEY$a;\n  var EVENT_SHOW$4 = \"show\" + EVENT_KEY$a;\n  var EVENT_SHOWN$4 = \"shown\" + EVENT_KEY$a;\n  var CLASS_NAME_FADE$5 = 'fade';\n  var CLASS_NAME_HIDE = 'hide';\n  var CLASS_NAME_SHOW$7 = 'show';\n  var CLASS_NAME_SHOWING = 'showing';\n  var DefaultType$7 = {\n    animation: 'boolean',\n    autohide: 'boolean',\n    delay: 'number'\n  };\n  var Default$7 = {\n    animation: true,\n    autohide: true,\n    delay: 500\n  };\n  var SELECTOR_DATA_DISMISS$1 = '[data-dismiss=\"toast\"]';\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  var Toast = /*#__PURE__*/function () {\n    function Toast(element, config) {\n      this._element = element;\n      this._config = this._getConfig(config);\n      this._timeout = null;\n\n      this._setListeners();\n    } // Getters\n\n\n    var _proto = Toast.prototype;\n\n    // Public\n    _proto.show = function show() {\n      var _this = this;\n\n      var showEvent = $__default['default'].Event(EVENT_SHOW$4);\n      $__default['default'](this._element).trigger(showEvent);\n\n      if (showEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      this._clearTimeout();\n\n      if (this._config.animation) {\n        this._element.classList.add(CLASS_NAME_FADE$5);\n      }\n\n      var complete = function complete() {\n        _this._element.classList.remove(CLASS_NAME_SHOWING);\n\n        _this._element.classList.add(CLASS_NAME_SHOW$7);\n\n        $__default['default'](_this._element).trigger(EVENT_SHOWN$4);\n\n        if (_this._config.autohide) {\n          _this._timeout = setTimeout(function () {\n            _this.hide();\n          }, _this._config.delay);\n        }\n      };\n\n      this._element.classList.remove(CLASS_NAME_HIDE);\n\n      Util.reflow(this._element);\n\n      this._element.classList.add(CLASS_NAME_SHOWING);\n\n      if (this._config.animation) {\n        var transitionDuration = Util.getTransitionDurationFromElement(this._element);\n        $__default['default'](this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);\n      } else {\n        complete();\n      }\n    };\n\n    _proto.hide = function hide() {\n      if (!this._element.classList.contains(CLASS_NAME_SHOW$7)) {\n        return;\n      }\n\n      var hideEvent = $__default['default'].Event(EVENT_HIDE$4);\n      $__default['default'](this._element).trigger(hideEvent);\n\n      if (hideEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      this._close();\n    };\n\n    _proto.dispose = function dispose() {\n      this._clearTimeout();\n\n      if (this._element.classList.contains(CLASS_NAME_SHOW$7)) {\n        this._element.classList.remove(CLASS_NAME_SHOW$7);\n      }\n\n      $__default['default'](this._element).off(EVENT_CLICK_DISMISS$1);\n      $__default['default'].removeData(this._element, DATA_KEY$a);\n      this._element = null;\n      this._config = null;\n    } // Private\n    ;\n\n    _proto._getConfig = function _getConfig(config) {\n      config = _extends({}, Default$7, $__default['default'](this._element).data(), typeof config === 'object' && config ? config : {});\n      Util.typeCheckConfig(NAME$a, config, this.constructor.DefaultType);\n      return config;\n    };\n\n    _proto._setListeners = function _setListeners() {\n      var _this2 = this;\n\n      $__default['default'](this._element).on(EVENT_CLICK_DISMISS$1, SELECTOR_DATA_DISMISS$1, function () {\n        return _this2.hide();\n      });\n    };\n\n    _proto._close = function _close() {\n      var _this3 = this;\n\n      var complete = function complete() {\n        _this3._element.classList.add(CLASS_NAME_HIDE);\n\n        $__default['default'](_this3._element).trigger(EVENT_HIDDEN$4);\n      };\n\n      this._element.classList.remove(CLASS_NAME_SHOW$7);\n\n      if (this._config.animation) {\n        var transitionDuration = Util.getTransitionDurationFromElement(this._element);\n        $__default['default'](this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);\n      } else {\n        complete();\n      }\n    };\n\n    _proto._clearTimeout = function _clearTimeout() {\n      clearTimeout(this._timeout);\n      this._timeout = null;\n    } // Static\n    ;\n\n    Toast._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var $element = $__default['default'](this);\n        var data = $element.data(DATA_KEY$a);\n\n        var _config = typeof config === 'object' && config;\n\n        if (!data) {\n          data = new Toast(this, _config);\n          $element.data(DATA_KEY$a, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config](this);\n        }\n      });\n    };\n\n    _createClass(Toast, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION$a;\n      }\n    }, {\n      key: \"DefaultType\",\n      get: function get() {\n        return DefaultType$7;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default$7;\n      }\n    }]);\n\n    return Toast;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n\n  $__default['default'].fn[NAME$a] = Toast._jQueryInterface;\n  $__default['default'].fn[NAME$a].Constructor = Toast;\n\n  $__default['default'].fn[NAME$a].noConflict = function () {\n    $__default['default'].fn[NAME$a] = JQUERY_NO_CONFLICT$a;\n    return Toast._jQueryInterface;\n  };\n\n  exports.Alert = Alert;\n  exports.Button = Button;\n  exports.Carousel = Carousel;\n  exports.Collapse = Collapse;\n  exports.Dropdown = Dropdown;\n  exports.Modal = Modal;\n  exports.Popover = Popover;\n  exports.Scrollspy = ScrollSpy;\n  exports.Tab = Tab;\n  exports.Toast = Toast;\n  exports.Tooltip = Tooltip;\n  exports.Util = Util;\n\n  Object.defineProperty(exports, '__esModule', { value: true });\n\n})));\n//# sourceMappingURL=bootstrap.bundle.js.map\n"
  },
  {
    "path": "src/IdentityServer/wwwroot/lib/bootstrap/dist/js/bootstrap.js",
    "content": "/*!\n  * Bootstrap v4.5.3 (https://getbootstrap.com/)\n  * Copyright 2011-2020 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)\n  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n  */\n(function (global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('jquery'), require('popper.js')) :\n  typeof define === 'function' && define.amd ? define(['exports', 'jquery', 'popper.js'], factory) :\n  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.bootstrap = {}, global.jQuery, global.Popper));\n}(this, (function (exports, $, Popper) { 'use strict';\n\n  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }\n\n  var $__default = /*#__PURE__*/_interopDefaultLegacy($);\n  var Popper__default = /*#__PURE__*/_interopDefaultLegacy(Popper);\n\n  function _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\n  function _createClass(Constructor, protoProps, staticProps) {\n    if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n    if (staticProps) _defineProperties(Constructor, staticProps);\n    return Constructor;\n  }\n\n  function _extends() {\n    _extends = Object.assign || function (target) {\n      for (var i = 1; i < arguments.length; i++) {\n        var source = arguments[i];\n\n        for (var key in source) {\n          if (Object.prototype.hasOwnProperty.call(source, key)) {\n            target[key] = source[key];\n          }\n        }\n      }\n\n      return target;\n    };\n\n    return _extends.apply(this, arguments);\n  }\n\n  function _inheritsLoose(subClass, superClass) {\n    subClass.prototype = Object.create(superClass.prototype);\n    subClass.prototype.constructor = subClass;\n    subClass.__proto__ = superClass;\n  }\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v4.5.3): util.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n  /**\n   * ------------------------------------------------------------------------\n   * Private TransitionEnd Helpers\n   * ------------------------------------------------------------------------\n   */\n\n  var TRANSITION_END = 'transitionend';\n  var MAX_UID = 1000000;\n  var MILLISECONDS_MULTIPLIER = 1000; // Shoutout AngusCroll (https://goo.gl/pxwQGp)\n\n  function toType(obj) {\n    if (obj === null || typeof obj === 'undefined') {\n      return \"\" + obj;\n    }\n\n    return {}.toString.call(obj).match(/\\s([a-z]+)/i)[1].toLowerCase();\n  }\n\n  function getSpecialTransitionEndEvent() {\n    return {\n      bindType: TRANSITION_END,\n      delegateType: TRANSITION_END,\n      handle: function handle(event) {\n        if ($__default['default'](event.target).is(this)) {\n          return event.handleObj.handler.apply(this, arguments); // eslint-disable-line prefer-rest-params\n        }\n\n        return undefined;\n      }\n    };\n  }\n\n  function transitionEndEmulator(duration) {\n    var _this = this;\n\n    var called = false;\n    $__default['default'](this).one(Util.TRANSITION_END, function () {\n      called = true;\n    });\n    setTimeout(function () {\n      if (!called) {\n        Util.triggerTransitionEnd(_this);\n      }\n    }, duration);\n    return this;\n  }\n\n  function setTransitionEndSupport() {\n    $__default['default'].fn.emulateTransitionEnd = transitionEndEmulator;\n    $__default['default'].event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent();\n  }\n  /**\n   * --------------------------------------------------------------------------\n   * Public Util Api\n   * --------------------------------------------------------------------------\n   */\n\n\n  var Util = {\n    TRANSITION_END: 'bsTransitionEnd',\n    getUID: function getUID(prefix) {\n      do {\n        prefix += ~~(Math.random() * MAX_UID); // \"~~\" acts like a faster Math.floor() here\n      } while (document.getElementById(prefix));\n\n      return prefix;\n    },\n    getSelectorFromElement: function getSelectorFromElement(element) {\n      var selector = element.getAttribute('data-target');\n\n      if (!selector || selector === '#') {\n        var hrefAttr = element.getAttribute('href');\n        selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : '';\n      }\n\n      try {\n        return document.querySelector(selector) ? selector : null;\n      } catch (_) {\n        return null;\n      }\n    },\n    getTransitionDurationFromElement: function getTransitionDurationFromElement(element) {\n      if (!element) {\n        return 0;\n      } // Get transition-duration of the element\n\n\n      var transitionDuration = $__default['default'](element).css('transition-duration');\n      var transitionDelay = $__default['default'](element).css('transition-delay');\n      var floatTransitionDuration = parseFloat(transitionDuration);\n      var floatTransitionDelay = parseFloat(transitionDelay); // Return 0 if element or transition duration is not found\n\n      if (!floatTransitionDuration && !floatTransitionDelay) {\n        return 0;\n      } // If multiple durations are defined, take the first\n\n\n      transitionDuration = transitionDuration.split(',')[0];\n      transitionDelay = transitionDelay.split(',')[0];\n      return (parseFloat(transitionDuration) + parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER;\n    },\n    reflow: function reflow(element) {\n      return element.offsetHeight;\n    },\n    triggerTransitionEnd: function triggerTransitionEnd(element) {\n      $__default['default'](element).trigger(TRANSITION_END);\n    },\n    supportsTransitionEnd: function supportsTransitionEnd() {\n      return Boolean(TRANSITION_END);\n    },\n    isElement: function isElement(obj) {\n      return (obj[0] || obj).nodeType;\n    },\n    typeCheckConfig: function typeCheckConfig(componentName, config, configTypes) {\n      for (var property in configTypes) {\n        if (Object.prototype.hasOwnProperty.call(configTypes, property)) {\n          var expectedTypes = configTypes[property];\n          var value = config[property];\n          var valueType = value && Util.isElement(value) ? 'element' : toType(value);\n\n          if (!new RegExp(expectedTypes).test(valueType)) {\n            throw new Error(componentName.toUpperCase() + \": \" + (\"Option \\\"\" + property + \"\\\" provided type \\\"\" + valueType + \"\\\" \") + (\"but expected type \\\"\" + expectedTypes + \"\\\".\"));\n          }\n        }\n      }\n    },\n    findShadowRoot: function findShadowRoot(element) {\n      if (!document.documentElement.attachShadow) {\n        return null;\n      } // Can find the shadow root otherwise it'll return the document\n\n\n      if (typeof element.getRootNode === 'function') {\n        var root = element.getRootNode();\n        return root instanceof ShadowRoot ? root : null;\n      }\n\n      if (element instanceof ShadowRoot) {\n        return element;\n      } // when we don't find a shadow root\n\n\n      if (!element.parentNode) {\n        return null;\n      }\n\n      return Util.findShadowRoot(element.parentNode);\n    },\n    jQueryDetection: function jQueryDetection() {\n      if (typeof $__default['default'] === 'undefined') {\n        throw new TypeError('Bootstrap\\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\\'s JavaScript.');\n      }\n\n      var version = $__default['default'].fn.jquery.split(' ')[0].split('.');\n      var minMajor = 1;\n      var ltMajor = 2;\n      var minMinor = 9;\n      var minPatch = 1;\n      var maxMajor = 4;\n\n      if (version[0] < ltMajor && version[1] < minMinor || version[0] === minMajor && version[1] === minMinor && version[2] < minPatch || version[0] >= maxMajor) {\n        throw new Error('Bootstrap\\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0');\n      }\n    }\n  };\n  Util.jQueryDetection();\n  setTransitionEndSupport();\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME = 'alert';\n  var VERSION = '4.5.3';\n  var DATA_KEY = 'bs.alert';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var DATA_API_KEY = '.data-api';\n  var JQUERY_NO_CONFLICT = $__default['default'].fn[NAME];\n  var SELECTOR_DISMISS = '[data-dismiss=\"alert\"]';\n  var EVENT_CLOSE = \"close\" + EVENT_KEY;\n  var EVENT_CLOSED = \"closed\" + EVENT_KEY;\n  var EVENT_CLICK_DATA_API = \"click\" + EVENT_KEY + DATA_API_KEY;\n  var CLASS_NAME_ALERT = 'alert';\n  var CLASS_NAME_FADE = 'fade';\n  var CLASS_NAME_SHOW = 'show';\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  var Alert = /*#__PURE__*/function () {\n    function Alert(element) {\n      this._element = element;\n    } // Getters\n\n\n    var _proto = Alert.prototype;\n\n    // Public\n    _proto.close = function close(element) {\n      var rootElement = this._element;\n\n      if (element) {\n        rootElement = this._getRootElement(element);\n      }\n\n      var customEvent = this._triggerCloseEvent(rootElement);\n\n      if (customEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      this._removeElement(rootElement);\n    };\n\n    _proto.dispose = function dispose() {\n      $__default['default'].removeData(this._element, DATA_KEY);\n      this._element = null;\n    } // Private\n    ;\n\n    _proto._getRootElement = function _getRootElement(element) {\n      var selector = Util.getSelectorFromElement(element);\n      var parent = false;\n\n      if (selector) {\n        parent = document.querySelector(selector);\n      }\n\n      if (!parent) {\n        parent = $__default['default'](element).closest(\".\" + CLASS_NAME_ALERT)[0];\n      }\n\n      return parent;\n    };\n\n    _proto._triggerCloseEvent = function _triggerCloseEvent(element) {\n      var closeEvent = $__default['default'].Event(EVENT_CLOSE);\n      $__default['default'](element).trigger(closeEvent);\n      return closeEvent;\n    };\n\n    _proto._removeElement = function _removeElement(element) {\n      var _this = this;\n\n      $__default['default'](element).removeClass(CLASS_NAME_SHOW);\n\n      if (!$__default['default'](element).hasClass(CLASS_NAME_FADE)) {\n        this._destroyElement(element);\n\n        return;\n      }\n\n      var transitionDuration = Util.getTransitionDurationFromElement(element);\n      $__default['default'](element).one(Util.TRANSITION_END, function (event) {\n        return _this._destroyElement(element, event);\n      }).emulateTransitionEnd(transitionDuration);\n    };\n\n    _proto._destroyElement = function _destroyElement(element) {\n      $__default['default'](element).detach().trigger(EVENT_CLOSED).remove();\n    } // Static\n    ;\n\n    Alert._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var $element = $__default['default'](this);\n        var data = $element.data(DATA_KEY);\n\n        if (!data) {\n          data = new Alert(this);\n          $element.data(DATA_KEY, data);\n        }\n\n        if (config === 'close') {\n          data[config](this);\n        }\n      });\n    };\n\n    Alert._handleDismiss = function _handleDismiss(alertInstance) {\n      return function (event) {\n        if (event) {\n          event.preventDefault();\n        }\n\n        alertInstance.close(this);\n      };\n    };\n\n    _createClass(Alert, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }]);\n\n    return Alert;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $__default['default'](document).on(EVENT_CLICK_DATA_API, SELECTOR_DISMISS, Alert._handleDismiss(new Alert()));\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $__default['default'].fn[NAME] = Alert._jQueryInterface;\n  $__default['default'].fn[NAME].Constructor = Alert;\n\n  $__default['default'].fn[NAME].noConflict = function () {\n    $__default['default'].fn[NAME] = JQUERY_NO_CONFLICT;\n    return Alert._jQueryInterface;\n  };\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME$1 = 'button';\n  var VERSION$1 = '4.5.3';\n  var DATA_KEY$1 = 'bs.button';\n  var EVENT_KEY$1 = \".\" + DATA_KEY$1;\n  var DATA_API_KEY$1 = '.data-api';\n  var JQUERY_NO_CONFLICT$1 = $__default['default'].fn[NAME$1];\n  var CLASS_NAME_ACTIVE = 'active';\n  var CLASS_NAME_BUTTON = 'btn';\n  var CLASS_NAME_FOCUS = 'focus';\n  var SELECTOR_DATA_TOGGLE_CARROT = '[data-toggle^=\"button\"]';\n  var SELECTOR_DATA_TOGGLES = '[data-toggle=\"buttons\"]';\n  var SELECTOR_DATA_TOGGLE = '[data-toggle=\"button\"]';\n  var SELECTOR_DATA_TOGGLES_BUTTONS = '[data-toggle=\"buttons\"] .btn';\n  var SELECTOR_INPUT = 'input:not([type=\"hidden\"])';\n  var SELECTOR_ACTIVE = '.active';\n  var SELECTOR_BUTTON = '.btn';\n  var EVENT_CLICK_DATA_API$1 = \"click\" + EVENT_KEY$1 + DATA_API_KEY$1;\n  var EVENT_FOCUS_BLUR_DATA_API = \"focus\" + EVENT_KEY$1 + DATA_API_KEY$1 + \" \" + (\"blur\" + EVENT_KEY$1 + DATA_API_KEY$1);\n  var EVENT_LOAD_DATA_API = \"load\" + EVENT_KEY$1 + DATA_API_KEY$1;\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  var Button = /*#__PURE__*/function () {\n    function Button(element) {\n      this._element = element;\n      this.shouldAvoidTriggerChange = false;\n    } // Getters\n\n\n    var _proto = Button.prototype;\n\n    // Public\n    _proto.toggle = function toggle() {\n      var triggerChangeEvent = true;\n      var addAriaPressed = true;\n      var rootElement = $__default['default'](this._element).closest(SELECTOR_DATA_TOGGLES)[0];\n\n      if (rootElement) {\n        var input = this._element.querySelector(SELECTOR_INPUT);\n\n        if (input) {\n          if (input.type === 'radio') {\n            if (input.checked && this._element.classList.contains(CLASS_NAME_ACTIVE)) {\n              triggerChangeEvent = false;\n            } else {\n              var activeElement = rootElement.querySelector(SELECTOR_ACTIVE);\n\n              if (activeElement) {\n                $__default['default'](activeElement).removeClass(CLASS_NAME_ACTIVE);\n              }\n            }\n          }\n\n          if (triggerChangeEvent) {\n            // if it's not a radio button or checkbox don't add a pointless/invalid checked property to the input\n            if (input.type === 'checkbox' || input.type === 'radio') {\n              input.checked = !this._element.classList.contains(CLASS_NAME_ACTIVE);\n            }\n\n            if (!this.shouldAvoidTriggerChange) {\n              $__default['default'](input).trigger('change');\n            }\n          }\n\n          input.focus();\n          addAriaPressed = false;\n        }\n      }\n\n      if (!(this._element.hasAttribute('disabled') || this._element.classList.contains('disabled'))) {\n        if (addAriaPressed) {\n          this._element.setAttribute('aria-pressed', !this._element.classList.contains(CLASS_NAME_ACTIVE));\n        }\n\n        if (triggerChangeEvent) {\n          $__default['default'](this._element).toggleClass(CLASS_NAME_ACTIVE);\n        }\n      }\n    };\n\n    _proto.dispose = function dispose() {\n      $__default['default'].removeData(this._element, DATA_KEY$1);\n      this._element = null;\n    } // Static\n    ;\n\n    Button._jQueryInterface = function _jQueryInterface(config, avoidTriggerChange) {\n      return this.each(function () {\n        var $element = $__default['default'](this);\n        var data = $element.data(DATA_KEY$1);\n\n        if (!data) {\n          data = new Button(this);\n          $element.data(DATA_KEY$1, data);\n        }\n\n        data.shouldAvoidTriggerChange = avoidTriggerChange;\n\n        if (config === 'toggle') {\n          data[config]();\n        }\n      });\n    };\n\n    _createClass(Button, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION$1;\n      }\n    }]);\n\n    return Button;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $__default['default'](document).on(EVENT_CLICK_DATA_API$1, SELECTOR_DATA_TOGGLE_CARROT, function (event) {\n    var button = event.target;\n    var initialButton = button;\n\n    if (!$__default['default'](button).hasClass(CLASS_NAME_BUTTON)) {\n      button = $__default['default'](button).closest(SELECTOR_BUTTON)[0];\n    }\n\n    if (!button || button.hasAttribute('disabled') || button.classList.contains('disabled')) {\n      event.preventDefault(); // work around Firefox bug #1540995\n    } else {\n      var inputBtn = button.querySelector(SELECTOR_INPUT);\n\n      if (inputBtn && (inputBtn.hasAttribute('disabled') || inputBtn.classList.contains('disabled'))) {\n        event.preventDefault(); // work around Firefox bug #1540995\n\n        return;\n      }\n\n      if (initialButton.tagName === 'INPUT' || button.tagName !== 'LABEL') {\n        Button._jQueryInterface.call($__default['default'](button), 'toggle', initialButton.tagName === 'INPUT');\n      }\n    }\n  }).on(EVENT_FOCUS_BLUR_DATA_API, SELECTOR_DATA_TOGGLE_CARROT, function (event) {\n    var button = $__default['default'](event.target).closest(SELECTOR_BUTTON)[0];\n    $__default['default'](button).toggleClass(CLASS_NAME_FOCUS, /^focus(in)?$/.test(event.type));\n  });\n  $__default['default'](window).on(EVENT_LOAD_DATA_API, function () {\n    // ensure correct active class is set to match the controls' actual values/states\n    // find all checkboxes/readio buttons inside data-toggle groups\n    var buttons = [].slice.call(document.querySelectorAll(SELECTOR_DATA_TOGGLES_BUTTONS));\n\n    for (var i = 0, len = buttons.length; i < len; i++) {\n      var button = buttons[i];\n      var input = button.querySelector(SELECTOR_INPUT);\n\n      if (input.checked || input.hasAttribute('checked')) {\n        button.classList.add(CLASS_NAME_ACTIVE);\n      } else {\n        button.classList.remove(CLASS_NAME_ACTIVE);\n      }\n    } // find all button toggles\n\n\n    buttons = [].slice.call(document.querySelectorAll(SELECTOR_DATA_TOGGLE));\n\n    for (var _i = 0, _len = buttons.length; _i < _len; _i++) {\n      var _button = buttons[_i];\n\n      if (_button.getAttribute('aria-pressed') === 'true') {\n        _button.classList.add(CLASS_NAME_ACTIVE);\n      } else {\n        _button.classList.remove(CLASS_NAME_ACTIVE);\n      }\n    }\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $__default['default'].fn[NAME$1] = Button._jQueryInterface;\n  $__default['default'].fn[NAME$1].Constructor = Button;\n\n  $__default['default'].fn[NAME$1].noConflict = function () {\n    $__default['default'].fn[NAME$1] = JQUERY_NO_CONFLICT$1;\n    return Button._jQueryInterface;\n  };\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME$2 = 'carousel';\n  var VERSION$2 = '4.5.3';\n  var DATA_KEY$2 = 'bs.carousel';\n  var EVENT_KEY$2 = \".\" + DATA_KEY$2;\n  var DATA_API_KEY$2 = '.data-api';\n  var JQUERY_NO_CONFLICT$2 = $__default['default'].fn[NAME$2];\n  var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key\n\n  var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key\n\n  var TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch\n\n  var SWIPE_THRESHOLD = 40;\n  var Default = {\n    interval: 5000,\n    keyboard: true,\n    slide: false,\n    pause: 'hover',\n    wrap: true,\n    touch: true\n  };\n  var DefaultType = {\n    interval: '(number|boolean)',\n    keyboard: 'boolean',\n    slide: '(boolean|string)',\n    pause: '(string|boolean)',\n    wrap: 'boolean',\n    touch: 'boolean'\n  };\n  var DIRECTION_NEXT = 'next';\n  var DIRECTION_PREV = 'prev';\n  var DIRECTION_LEFT = 'left';\n  var DIRECTION_RIGHT = 'right';\n  var EVENT_SLIDE = \"slide\" + EVENT_KEY$2;\n  var EVENT_SLID = \"slid\" + EVENT_KEY$2;\n  var EVENT_KEYDOWN = \"keydown\" + EVENT_KEY$2;\n  var EVENT_MOUSEENTER = \"mouseenter\" + EVENT_KEY$2;\n  var EVENT_MOUSELEAVE = \"mouseleave\" + EVENT_KEY$2;\n  var EVENT_TOUCHSTART = \"touchstart\" + EVENT_KEY$2;\n  var EVENT_TOUCHMOVE = \"touchmove\" + EVENT_KEY$2;\n  var EVENT_TOUCHEND = \"touchend\" + EVENT_KEY$2;\n  var EVENT_POINTERDOWN = \"pointerdown\" + EVENT_KEY$2;\n  var EVENT_POINTERUP = \"pointerup\" + EVENT_KEY$2;\n  var EVENT_DRAG_START = \"dragstart\" + EVENT_KEY$2;\n  var EVENT_LOAD_DATA_API$1 = \"load\" + EVENT_KEY$2 + DATA_API_KEY$2;\n  var EVENT_CLICK_DATA_API$2 = \"click\" + EVENT_KEY$2 + DATA_API_KEY$2;\n  var CLASS_NAME_CAROUSEL = 'carousel';\n  var CLASS_NAME_ACTIVE$1 = 'active';\n  var CLASS_NAME_SLIDE = 'slide';\n  var CLASS_NAME_RIGHT = 'carousel-item-right';\n  var CLASS_NAME_LEFT = 'carousel-item-left';\n  var CLASS_NAME_NEXT = 'carousel-item-next';\n  var CLASS_NAME_PREV = 'carousel-item-prev';\n  var CLASS_NAME_POINTER_EVENT = 'pointer-event';\n  var SELECTOR_ACTIVE$1 = '.active';\n  var SELECTOR_ACTIVE_ITEM = '.active.carousel-item';\n  var SELECTOR_ITEM = '.carousel-item';\n  var SELECTOR_ITEM_IMG = '.carousel-item img';\n  var SELECTOR_NEXT_PREV = '.carousel-item-next, .carousel-item-prev';\n  var SELECTOR_INDICATORS = '.carousel-indicators';\n  var SELECTOR_DATA_SLIDE = '[data-slide], [data-slide-to]';\n  var SELECTOR_DATA_RIDE = '[data-ride=\"carousel\"]';\n  var PointerType = {\n    TOUCH: 'touch',\n    PEN: 'pen'\n  };\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  var Carousel = /*#__PURE__*/function () {\n    function Carousel(element, config) {\n      this._items = null;\n      this._interval = null;\n      this._activeElement = null;\n      this._isPaused = false;\n      this._isSliding = false;\n      this.touchTimeout = null;\n      this.touchStartX = 0;\n      this.touchDeltaX = 0;\n      this._config = this._getConfig(config);\n      this._element = element;\n      this._indicatorsElement = this._element.querySelector(SELECTOR_INDICATORS);\n      this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0;\n      this._pointerEvent = Boolean(window.PointerEvent || window.MSPointerEvent);\n\n      this._addEventListeners();\n    } // Getters\n\n\n    var _proto = Carousel.prototype;\n\n    // Public\n    _proto.next = function next() {\n      if (!this._isSliding) {\n        this._slide(DIRECTION_NEXT);\n      }\n    };\n\n    _proto.nextWhenVisible = function nextWhenVisible() {\n      var $element = $__default['default'](this._element); // Don't call next when the page isn't visible\n      // or the carousel or its parent isn't visible\n\n      if (!document.hidden && $element.is(':visible') && $element.css('visibility') !== 'hidden') {\n        this.next();\n      }\n    };\n\n    _proto.prev = function prev() {\n      if (!this._isSliding) {\n        this._slide(DIRECTION_PREV);\n      }\n    };\n\n    _proto.pause = function pause(event) {\n      if (!event) {\n        this._isPaused = true;\n      }\n\n      if (this._element.querySelector(SELECTOR_NEXT_PREV)) {\n        Util.triggerTransitionEnd(this._element);\n        this.cycle(true);\n      }\n\n      clearInterval(this._interval);\n      this._interval = null;\n    };\n\n    _proto.cycle = function cycle(event) {\n      if (!event) {\n        this._isPaused = false;\n      }\n\n      if (this._interval) {\n        clearInterval(this._interval);\n        this._interval = null;\n      }\n\n      if (this._config.interval && !this._isPaused) {\n        this._interval = setInterval((document.visibilityState ? this.nextWhenVisible : this.next).bind(this), this._config.interval);\n      }\n    };\n\n    _proto.to = function to(index) {\n      var _this = this;\n\n      this._activeElement = this._element.querySelector(SELECTOR_ACTIVE_ITEM);\n\n      var activeIndex = this._getItemIndex(this._activeElement);\n\n      if (index > this._items.length - 1 || index < 0) {\n        return;\n      }\n\n      if (this._isSliding) {\n        $__default['default'](this._element).one(EVENT_SLID, function () {\n          return _this.to(index);\n        });\n        return;\n      }\n\n      if (activeIndex === index) {\n        this.pause();\n        this.cycle();\n        return;\n      }\n\n      var direction = index > activeIndex ? DIRECTION_NEXT : DIRECTION_PREV;\n\n      this._slide(direction, this._items[index]);\n    };\n\n    _proto.dispose = function dispose() {\n      $__default['default'](this._element).off(EVENT_KEY$2);\n      $__default['default'].removeData(this._element, DATA_KEY$2);\n      this._items = null;\n      this._config = null;\n      this._element = null;\n      this._interval = null;\n      this._isPaused = null;\n      this._isSliding = null;\n      this._activeElement = null;\n      this._indicatorsElement = null;\n    } // Private\n    ;\n\n    _proto._getConfig = function _getConfig(config) {\n      config = _extends({}, Default, config);\n      Util.typeCheckConfig(NAME$2, config, DefaultType);\n      return config;\n    };\n\n    _proto._handleSwipe = function _handleSwipe() {\n      var absDeltax = Math.abs(this.touchDeltaX);\n\n      if (absDeltax <= SWIPE_THRESHOLD) {\n        return;\n      }\n\n      var direction = absDeltax / this.touchDeltaX;\n      this.touchDeltaX = 0; // swipe left\n\n      if (direction > 0) {\n        this.prev();\n      } // swipe right\n\n\n      if (direction < 0) {\n        this.next();\n      }\n    };\n\n    _proto._addEventListeners = function _addEventListeners() {\n      var _this2 = this;\n\n      if (this._config.keyboard) {\n        $__default['default'](this._element).on(EVENT_KEYDOWN, function (event) {\n          return _this2._keydown(event);\n        });\n      }\n\n      if (this._config.pause === 'hover') {\n        $__default['default'](this._element).on(EVENT_MOUSEENTER, function (event) {\n          return _this2.pause(event);\n        }).on(EVENT_MOUSELEAVE, function (event) {\n          return _this2.cycle(event);\n        });\n      }\n\n      if (this._config.touch) {\n        this._addTouchEventListeners();\n      }\n    };\n\n    _proto._addTouchEventListeners = function _addTouchEventListeners() {\n      var _this3 = this;\n\n      if (!this._touchSupported) {\n        return;\n      }\n\n      var start = function start(event) {\n        if (_this3._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) {\n          _this3.touchStartX = event.originalEvent.clientX;\n        } else if (!_this3._pointerEvent) {\n          _this3.touchStartX = event.originalEvent.touches[0].clientX;\n        }\n      };\n\n      var move = function move(event) {\n        // ensure swiping with one touch and not pinching\n        if (event.originalEvent.touches && event.originalEvent.touches.length > 1) {\n          _this3.touchDeltaX = 0;\n        } else {\n          _this3.touchDeltaX = event.originalEvent.touches[0].clientX - _this3.touchStartX;\n        }\n      };\n\n      var end = function end(event) {\n        if (_this3._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) {\n          _this3.touchDeltaX = event.originalEvent.clientX - _this3.touchStartX;\n        }\n\n        _this3._handleSwipe();\n\n        if (_this3._config.pause === 'hover') {\n          // If it's a touch-enabled device, mouseenter/leave are fired as\n          // part of the mouse compatibility events on first tap - the carousel\n          // would stop cycling until user tapped out of it;\n          // here, we listen for touchend, explicitly pause the carousel\n          // (as if it's the second time we tap on it, mouseenter compat event\n          // is NOT fired) and after a timeout (to allow for mouse compatibility\n          // events to fire) we explicitly restart cycling\n          _this3.pause();\n\n          if (_this3.touchTimeout) {\n            clearTimeout(_this3.touchTimeout);\n          }\n\n          _this3.touchTimeout = setTimeout(function (event) {\n            return _this3.cycle(event);\n          }, TOUCHEVENT_COMPAT_WAIT + _this3._config.interval);\n        }\n      };\n\n      $__default['default'](this._element.querySelectorAll(SELECTOR_ITEM_IMG)).on(EVENT_DRAG_START, function (e) {\n        return e.preventDefault();\n      });\n\n      if (this._pointerEvent) {\n        $__default['default'](this._element).on(EVENT_POINTERDOWN, function (event) {\n          return start(event);\n        });\n        $__default['default'](this._element).on(EVENT_POINTERUP, function (event) {\n          return end(event);\n        });\n\n        this._element.classList.add(CLASS_NAME_POINTER_EVENT);\n      } else {\n        $__default['default'](this._element).on(EVENT_TOUCHSTART, function (event) {\n          return start(event);\n        });\n        $__default['default'](this._element).on(EVENT_TOUCHMOVE, function (event) {\n          return move(event);\n        });\n        $__default['default'](this._element).on(EVENT_TOUCHEND, function (event) {\n          return end(event);\n        });\n      }\n    };\n\n    _proto._keydown = function _keydown(event) {\n      if (/input|textarea/i.test(event.target.tagName)) {\n        return;\n      }\n\n      switch (event.which) {\n        case ARROW_LEFT_KEYCODE:\n          event.preventDefault();\n          this.prev();\n          break;\n\n        case ARROW_RIGHT_KEYCODE:\n          event.preventDefault();\n          this.next();\n          break;\n      }\n    };\n\n    _proto._getItemIndex = function _getItemIndex(element) {\n      this._items = element && element.parentNode ? [].slice.call(element.parentNode.querySelectorAll(SELECTOR_ITEM)) : [];\n      return this._items.indexOf(element);\n    };\n\n    _proto._getItemByDirection = function _getItemByDirection(direction, activeElement) {\n      var isNextDirection = direction === DIRECTION_NEXT;\n      var isPrevDirection = direction === DIRECTION_PREV;\n\n      var activeIndex = this._getItemIndex(activeElement);\n\n      var lastItemIndex = this._items.length - 1;\n      var isGoingToWrap = isPrevDirection && activeIndex === 0 || isNextDirection && activeIndex === lastItemIndex;\n\n      if (isGoingToWrap && !this._config.wrap) {\n        return activeElement;\n      }\n\n      var delta = direction === DIRECTION_PREV ? -1 : 1;\n      var itemIndex = (activeIndex + delta) % this._items.length;\n      return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex];\n    };\n\n    _proto._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, eventDirectionName) {\n      var targetIndex = this._getItemIndex(relatedTarget);\n\n      var fromIndex = this._getItemIndex(this._element.querySelector(SELECTOR_ACTIVE_ITEM));\n\n      var slideEvent = $__default['default'].Event(EVENT_SLIDE, {\n        relatedTarget: relatedTarget,\n        direction: eventDirectionName,\n        from: fromIndex,\n        to: targetIndex\n      });\n      $__default['default'](this._element).trigger(slideEvent);\n      return slideEvent;\n    };\n\n    _proto._setActiveIndicatorElement = function _setActiveIndicatorElement(element) {\n      if (this._indicatorsElement) {\n        var indicators = [].slice.call(this._indicatorsElement.querySelectorAll(SELECTOR_ACTIVE$1));\n        $__default['default'](indicators).removeClass(CLASS_NAME_ACTIVE$1);\n\n        var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)];\n\n        if (nextIndicator) {\n          $__default['default'](nextIndicator).addClass(CLASS_NAME_ACTIVE$1);\n        }\n      }\n    };\n\n    _proto._slide = function _slide(direction, element) {\n      var _this4 = this;\n\n      var activeElement = this._element.querySelector(SELECTOR_ACTIVE_ITEM);\n\n      var activeElementIndex = this._getItemIndex(activeElement);\n\n      var nextElement = element || activeElement && this._getItemByDirection(direction, activeElement);\n\n      var nextElementIndex = this._getItemIndex(nextElement);\n\n      var isCycling = Boolean(this._interval);\n      var directionalClassName;\n      var orderClassName;\n      var eventDirectionName;\n\n      if (direction === DIRECTION_NEXT) {\n        directionalClassName = CLASS_NAME_LEFT;\n        orderClassName = CLASS_NAME_NEXT;\n        eventDirectionName = DIRECTION_LEFT;\n      } else {\n        directionalClassName = CLASS_NAME_RIGHT;\n        orderClassName = CLASS_NAME_PREV;\n        eventDirectionName = DIRECTION_RIGHT;\n      }\n\n      if (nextElement && $__default['default'](nextElement).hasClass(CLASS_NAME_ACTIVE$1)) {\n        this._isSliding = false;\n        return;\n      }\n\n      var slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName);\n\n      if (slideEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      if (!activeElement || !nextElement) {\n        // Some weirdness is happening, so we bail\n        return;\n      }\n\n      this._isSliding = true;\n\n      if (isCycling) {\n        this.pause();\n      }\n\n      this._setActiveIndicatorElement(nextElement);\n\n      var slidEvent = $__default['default'].Event(EVENT_SLID, {\n        relatedTarget: nextElement,\n        direction: eventDirectionName,\n        from: activeElementIndex,\n        to: nextElementIndex\n      });\n\n      if ($__default['default'](this._element).hasClass(CLASS_NAME_SLIDE)) {\n        $__default['default'](nextElement).addClass(orderClassName);\n        Util.reflow(nextElement);\n        $__default['default'](activeElement).addClass(directionalClassName);\n        $__default['default'](nextElement).addClass(directionalClassName);\n        var nextElementInterval = parseInt(nextElement.getAttribute('data-interval'), 10);\n\n        if (nextElementInterval) {\n          this._config.defaultInterval = this._config.defaultInterval || this._config.interval;\n          this._config.interval = nextElementInterval;\n        } else {\n          this._config.interval = this._config.defaultInterval || this._config.interval;\n        }\n\n        var transitionDuration = Util.getTransitionDurationFromElement(activeElement);\n        $__default['default'](activeElement).one(Util.TRANSITION_END, function () {\n          $__default['default'](nextElement).removeClass(directionalClassName + \" \" + orderClassName).addClass(CLASS_NAME_ACTIVE$1);\n          $__default['default'](activeElement).removeClass(CLASS_NAME_ACTIVE$1 + \" \" + orderClassName + \" \" + directionalClassName);\n          _this4._isSliding = false;\n          setTimeout(function () {\n            return $__default['default'](_this4._element).trigger(slidEvent);\n          }, 0);\n        }).emulateTransitionEnd(transitionDuration);\n      } else {\n        $__default['default'](activeElement).removeClass(CLASS_NAME_ACTIVE$1);\n        $__default['default'](nextElement).addClass(CLASS_NAME_ACTIVE$1);\n        this._isSliding = false;\n        $__default['default'](this._element).trigger(slidEvent);\n      }\n\n      if (isCycling) {\n        this.cycle();\n      }\n    } // Static\n    ;\n\n    Carousel._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var data = $__default['default'](this).data(DATA_KEY$2);\n\n        var _config = _extends({}, Default, $__default['default'](this).data());\n\n        if (typeof config === 'object') {\n          _config = _extends({}, _config, config);\n        }\n\n        var action = typeof config === 'string' ? config : _config.slide;\n\n        if (!data) {\n          data = new Carousel(this, _config);\n          $__default['default'](this).data(DATA_KEY$2, data);\n        }\n\n        if (typeof config === 'number') {\n          data.to(config);\n        } else if (typeof action === 'string') {\n          if (typeof data[action] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + action + \"\\\"\");\n          }\n\n          data[action]();\n        } else if (_config.interval && _config.ride) {\n          data.pause();\n          data.cycle();\n        }\n      });\n    };\n\n    Carousel._dataApiClickHandler = function _dataApiClickHandler(event) {\n      var selector = Util.getSelectorFromElement(this);\n\n      if (!selector) {\n        return;\n      }\n\n      var target = $__default['default'](selector)[0];\n\n      if (!target || !$__default['default'](target).hasClass(CLASS_NAME_CAROUSEL)) {\n        return;\n      }\n\n      var config = _extends({}, $__default['default'](target).data(), $__default['default'](this).data());\n\n      var slideIndex = this.getAttribute('data-slide-to');\n\n      if (slideIndex) {\n        config.interval = false;\n      }\n\n      Carousel._jQueryInterface.call($__default['default'](target), config);\n\n      if (slideIndex) {\n        $__default['default'](target).data(DATA_KEY$2).to(slideIndex);\n      }\n\n      event.preventDefault();\n    };\n\n    _createClass(Carousel, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION$2;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default;\n      }\n    }]);\n\n    return Carousel;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $__default['default'](document).on(EVENT_CLICK_DATA_API$2, SELECTOR_DATA_SLIDE, Carousel._dataApiClickHandler);\n  $__default['default'](window).on(EVENT_LOAD_DATA_API$1, function () {\n    var carousels = [].slice.call(document.querySelectorAll(SELECTOR_DATA_RIDE));\n\n    for (var i = 0, len = carousels.length; i < len; i++) {\n      var $carousel = $__default['default'](carousels[i]);\n\n      Carousel._jQueryInterface.call($carousel, $carousel.data());\n    }\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $__default['default'].fn[NAME$2] = Carousel._jQueryInterface;\n  $__default['default'].fn[NAME$2].Constructor = Carousel;\n\n  $__default['default'].fn[NAME$2].noConflict = function () {\n    $__default['default'].fn[NAME$2] = JQUERY_NO_CONFLICT$2;\n    return Carousel._jQueryInterface;\n  };\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME$3 = 'collapse';\n  var VERSION$3 = '4.5.3';\n  var DATA_KEY$3 = 'bs.collapse';\n  var EVENT_KEY$3 = \".\" + DATA_KEY$3;\n  var DATA_API_KEY$3 = '.data-api';\n  var JQUERY_NO_CONFLICT$3 = $__default['default'].fn[NAME$3];\n  var Default$1 = {\n    toggle: true,\n    parent: ''\n  };\n  var DefaultType$1 = {\n    toggle: 'boolean',\n    parent: '(string|element)'\n  };\n  var EVENT_SHOW = \"show\" + EVENT_KEY$3;\n  var EVENT_SHOWN = \"shown\" + EVENT_KEY$3;\n  var EVENT_HIDE = \"hide\" + EVENT_KEY$3;\n  var EVENT_HIDDEN = \"hidden\" + EVENT_KEY$3;\n  var EVENT_CLICK_DATA_API$3 = \"click\" + EVENT_KEY$3 + DATA_API_KEY$3;\n  var CLASS_NAME_SHOW$1 = 'show';\n  var CLASS_NAME_COLLAPSE = 'collapse';\n  var CLASS_NAME_COLLAPSING = 'collapsing';\n  var CLASS_NAME_COLLAPSED = 'collapsed';\n  var DIMENSION_WIDTH = 'width';\n  var DIMENSION_HEIGHT = 'height';\n  var SELECTOR_ACTIVES = '.show, .collapsing';\n  var SELECTOR_DATA_TOGGLE$1 = '[data-toggle=\"collapse\"]';\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  var Collapse = /*#__PURE__*/function () {\n    function Collapse(element, config) {\n      this._isTransitioning = false;\n      this._element = element;\n      this._config = this._getConfig(config);\n      this._triggerArray = [].slice.call(document.querySelectorAll(\"[data-toggle=\\\"collapse\\\"][href=\\\"#\" + element.id + \"\\\"],\" + (\"[data-toggle=\\\"collapse\\\"][data-target=\\\"#\" + element.id + \"\\\"]\")));\n      var toggleList = [].slice.call(document.querySelectorAll(SELECTOR_DATA_TOGGLE$1));\n\n      for (var i = 0, len = toggleList.length; i < len; i++) {\n        var elem = toggleList[i];\n        var selector = Util.getSelectorFromElement(elem);\n        var filterElement = [].slice.call(document.querySelectorAll(selector)).filter(function (foundElem) {\n          return foundElem === element;\n        });\n\n        if (selector !== null && filterElement.length > 0) {\n          this._selector = selector;\n\n          this._triggerArray.push(elem);\n        }\n      }\n\n      this._parent = this._config.parent ? this._getParent() : null;\n\n      if (!this._config.parent) {\n        this._addAriaAndCollapsedClass(this._element, this._triggerArray);\n      }\n\n      if (this._config.toggle) {\n        this.toggle();\n      }\n    } // Getters\n\n\n    var _proto = Collapse.prototype;\n\n    // Public\n    _proto.toggle = function toggle() {\n      if ($__default['default'](this._element).hasClass(CLASS_NAME_SHOW$1)) {\n        this.hide();\n      } else {\n        this.show();\n      }\n    };\n\n    _proto.show = function show() {\n      var _this = this;\n\n      if (this._isTransitioning || $__default['default'](this._element).hasClass(CLASS_NAME_SHOW$1)) {\n        return;\n      }\n\n      var actives;\n      var activesData;\n\n      if (this._parent) {\n        actives = [].slice.call(this._parent.querySelectorAll(SELECTOR_ACTIVES)).filter(function (elem) {\n          if (typeof _this._config.parent === 'string') {\n            return elem.getAttribute('data-parent') === _this._config.parent;\n          }\n\n          return elem.classList.contains(CLASS_NAME_COLLAPSE);\n        });\n\n        if (actives.length === 0) {\n          actives = null;\n        }\n      }\n\n      if (actives) {\n        activesData = $__default['default'](actives).not(this._selector).data(DATA_KEY$3);\n\n        if (activesData && activesData._isTransitioning) {\n          return;\n        }\n      }\n\n      var startEvent = $__default['default'].Event(EVENT_SHOW);\n      $__default['default'](this._element).trigger(startEvent);\n\n      if (startEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      if (actives) {\n        Collapse._jQueryInterface.call($__default['default'](actives).not(this._selector), 'hide');\n\n        if (!activesData) {\n          $__default['default'](actives).data(DATA_KEY$3, null);\n        }\n      }\n\n      var dimension = this._getDimension();\n\n      $__default['default'](this._element).removeClass(CLASS_NAME_COLLAPSE).addClass(CLASS_NAME_COLLAPSING);\n      this._element.style[dimension] = 0;\n\n      if (this._triggerArray.length) {\n        $__default['default'](this._triggerArray).removeClass(CLASS_NAME_COLLAPSED).attr('aria-expanded', true);\n      }\n\n      this.setTransitioning(true);\n\n      var complete = function complete() {\n        $__default['default'](_this._element).removeClass(CLASS_NAME_COLLAPSING).addClass(CLASS_NAME_COLLAPSE + \" \" + CLASS_NAME_SHOW$1);\n        _this._element.style[dimension] = '';\n\n        _this.setTransitioning(false);\n\n        $__default['default'](_this._element).trigger(EVENT_SHOWN);\n      };\n\n      var capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1);\n      var scrollSize = \"scroll\" + capitalizedDimension;\n      var transitionDuration = Util.getTransitionDurationFromElement(this._element);\n      $__default['default'](this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);\n      this._element.style[dimension] = this._element[scrollSize] + \"px\";\n    };\n\n    _proto.hide = function hide() {\n      var _this2 = this;\n\n      if (this._isTransitioning || !$__default['default'](this._element).hasClass(CLASS_NAME_SHOW$1)) {\n        return;\n      }\n\n      var startEvent = $__default['default'].Event(EVENT_HIDE);\n      $__default['default'](this._element).trigger(startEvent);\n\n      if (startEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      var dimension = this._getDimension();\n\n      this._element.style[dimension] = this._element.getBoundingClientRect()[dimension] + \"px\";\n      Util.reflow(this._element);\n      $__default['default'](this._element).addClass(CLASS_NAME_COLLAPSING).removeClass(CLASS_NAME_COLLAPSE + \" \" + CLASS_NAME_SHOW$1);\n      var triggerArrayLength = this._triggerArray.length;\n\n      if (triggerArrayLength > 0) {\n        for (var i = 0; i < triggerArrayLength; i++) {\n          var trigger = this._triggerArray[i];\n          var selector = Util.getSelectorFromElement(trigger);\n\n          if (selector !== null) {\n            var $elem = $__default['default']([].slice.call(document.querySelectorAll(selector)));\n\n            if (!$elem.hasClass(CLASS_NAME_SHOW$1)) {\n              $__default['default'](trigger).addClass(CLASS_NAME_COLLAPSED).attr('aria-expanded', false);\n            }\n          }\n        }\n      }\n\n      this.setTransitioning(true);\n\n      var complete = function complete() {\n        _this2.setTransitioning(false);\n\n        $__default['default'](_this2._element).removeClass(CLASS_NAME_COLLAPSING).addClass(CLASS_NAME_COLLAPSE).trigger(EVENT_HIDDEN);\n      };\n\n      this._element.style[dimension] = '';\n      var transitionDuration = Util.getTransitionDurationFromElement(this._element);\n      $__default['default'](this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);\n    };\n\n    _proto.setTransitioning = function setTransitioning(isTransitioning) {\n      this._isTransitioning = isTransitioning;\n    };\n\n    _proto.dispose = function dispose() {\n      $__default['default'].removeData(this._element, DATA_KEY$3);\n      this._config = null;\n      this._parent = null;\n      this._element = null;\n      this._triggerArray = null;\n      this._isTransitioning = null;\n    } // Private\n    ;\n\n    _proto._getConfig = function _getConfig(config) {\n      config = _extends({}, Default$1, config);\n      config.toggle = Boolean(config.toggle); // Coerce string values\n\n      Util.typeCheckConfig(NAME$3, config, DefaultType$1);\n      return config;\n    };\n\n    _proto._getDimension = function _getDimension() {\n      var hasWidth = $__default['default'](this._element).hasClass(DIMENSION_WIDTH);\n      return hasWidth ? DIMENSION_WIDTH : DIMENSION_HEIGHT;\n    };\n\n    _proto._getParent = function _getParent() {\n      var _this3 = this;\n\n      var parent;\n\n      if (Util.isElement(this._config.parent)) {\n        parent = this._config.parent; // It's a jQuery object\n\n        if (typeof this._config.parent.jquery !== 'undefined') {\n          parent = this._config.parent[0];\n        }\n      } else {\n        parent = document.querySelector(this._config.parent);\n      }\n\n      var selector = \"[data-toggle=\\\"collapse\\\"][data-parent=\\\"\" + this._config.parent + \"\\\"]\";\n      var children = [].slice.call(parent.querySelectorAll(selector));\n      $__default['default'](children).each(function (i, element) {\n        _this3._addAriaAndCollapsedClass(Collapse._getTargetFromElement(element), [element]);\n      });\n      return parent;\n    };\n\n    _proto._addAriaAndCollapsedClass = function _addAriaAndCollapsedClass(element, triggerArray) {\n      var isOpen = $__default['default'](element).hasClass(CLASS_NAME_SHOW$1);\n\n      if (triggerArray.length) {\n        $__default['default'](triggerArray).toggleClass(CLASS_NAME_COLLAPSED, !isOpen).attr('aria-expanded', isOpen);\n      }\n    } // Static\n    ;\n\n    Collapse._getTargetFromElement = function _getTargetFromElement(element) {\n      var selector = Util.getSelectorFromElement(element);\n      return selector ? document.querySelector(selector) : null;\n    };\n\n    Collapse._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var $element = $__default['default'](this);\n        var data = $element.data(DATA_KEY$3);\n\n        var _config = _extends({}, Default$1, $element.data(), typeof config === 'object' && config ? config : {});\n\n        if (!data && _config.toggle && typeof config === 'string' && /show|hide/.test(config)) {\n          _config.toggle = false;\n        }\n\n        if (!data) {\n          data = new Collapse(this, _config);\n          $element.data(DATA_KEY$3, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    _createClass(Collapse, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION$3;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default$1;\n      }\n    }]);\n\n    return Collapse;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $__default['default'](document).on(EVENT_CLICK_DATA_API$3, SELECTOR_DATA_TOGGLE$1, function (event) {\n    // preventDefault only for <a> elements (which change the URL) not inside the collapsible element\n    if (event.currentTarget.tagName === 'A') {\n      event.preventDefault();\n    }\n\n    var $trigger = $__default['default'](this);\n    var selector = Util.getSelectorFromElement(this);\n    var selectors = [].slice.call(document.querySelectorAll(selector));\n    $__default['default'](selectors).each(function () {\n      var $target = $__default['default'](this);\n      var data = $target.data(DATA_KEY$3);\n      var config = data ? 'toggle' : $trigger.data();\n\n      Collapse._jQueryInterface.call($target, config);\n    });\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $__default['default'].fn[NAME$3] = Collapse._jQueryInterface;\n  $__default['default'].fn[NAME$3].Constructor = Collapse;\n\n  $__default['default'].fn[NAME$3].noConflict = function () {\n    $__default['default'].fn[NAME$3] = JQUERY_NO_CONFLICT$3;\n    return Collapse._jQueryInterface;\n  };\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME$4 = 'dropdown';\n  var VERSION$4 = '4.5.3';\n  var DATA_KEY$4 = 'bs.dropdown';\n  var EVENT_KEY$4 = \".\" + DATA_KEY$4;\n  var DATA_API_KEY$4 = '.data-api';\n  var JQUERY_NO_CONFLICT$4 = $__default['default'].fn[NAME$4];\n  var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key\n\n  var SPACE_KEYCODE = 32; // KeyboardEvent.which value for space key\n\n  var TAB_KEYCODE = 9; // KeyboardEvent.which value for tab key\n\n  var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key\n\n  var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key\n\n  var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse)\n\n  var REGEXP_KEYDOWN = new RegExp(ARROW_UP_KEYCODE + \"|\" + ARROW_DOWN_KEYCODE + \"|\" + ESCAPE_KEYCODE);\n  var EVENT_HIDE$1 = \"hide\" + EVENT_KEY$4;\n  var EVENT_HIDDEN$1 = \"hidden\" + EVENT_KEY$4;\n  var EVENT_SHOW$1 = \"show\" + EVENT_KEY$4;\n  var EVENT_SHOWN$1 = \"shown\" + EVENT_KEY$4;\n  var EVENT_CLICK = \"click\" + EVENT_KEY$4;\n  var EVENT_CLICK_DATA_API$4 = \"click\" + EVENT_KEY$4 + DATA_API_KEY$4;\n  var EVENT_KEYDOWN_DATA_API = \"keydown\" + EVENT_KEY$4 + DATA_API_KEY$4;\n  var EVENT_KEYUP_DATA_API = \"keyup\" + EVENT_KEY$4 + DATA_API_KEY$4;\n  var CLASS_NAME_DISABLED = 'disabled';\n  var CLASS_NAME_SHOW$2 = 'show';\n  var CLASS_NAME_DROPUP = 'dropup';\n  var CLASS_NAME_DROPRIGHT = 'dropright';\n  var CLASS_NAME_DROPLEFT = 'dropleft';\n  var CLASS_NAME_MENURIGHT = 'dropdown-menu-right';\n  var CLASS_NAME_POSITION_STATIC = 'position-static';\n  var SELECTOR_DATA_TOGGLE$2 = '[data-toggle=\"dropdown\"]';\n  var SELECTOR_FORM_CHILD = '.dropdown form';\n  var SELECTOR_MENU = '.dropdown-menu';\n  var SELECTOR_NAVBAR_NAV = '.navbar-nav';\n  var SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)';\n  var PLACEMENT_TOP = 'top-start';\n  var PLACEMENT_TOPEND = 'top-end';\n  var PLACEMENT_BOTTOM = 'bottom-start';\n  var PLACEMENT_BOTTOMEND = 'bottom-end';\n  var PLACEMENT_RIGHT = 'right-start';\n  var PLACEMENT_LEFT = 'left-start';\n  var Default$2 = {\n    offset: 0,\n    flip: true,\n    boundary: 'scrollParent',\n    reference: 'toggle',\n    display: 'dynamic',\n    popperConfig: null\n  };\n  var DefaultType$2 = {\n    offset: '(number|string|function)',\n    flip: 'boolean',\n    boundary: '(string|element)',\n    reference: '(string|element)',\n    display: 'string',\n    popperConfig: '(null|object)'\n  };\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  var Dropdown = /*#__PURE__*/function () {\n    function Dropdown(element, config) {\n      this._element = element;\n      this._popper = null;\n      this._config = this._getConfig(config);\n      this._menu = this._getMenuElement();\n      this._inNavbar = this._detectNavbar();\n\n      this._addEventListeners();\n    } // Getters\n\n\n    var _proto = Dropdown.prototype;\n\n    // Public\n    _proto.toggle = function toggle() {\n      if (this._element.disabled || $__default['default'](this._element).hasClass(CLASS_NAME_DISABLED)) {\n        return;\n      }\n\n      var isActive = $__default['default'](this._menu).hasClass(CLASS_NAME_SHOW$2);\n\n      Dropdown._clearMenus();\n\n      if (isActive) {\n        return;\n      }\n\n      this.show(true);\n    };\n\n    _proto.show = function show(usePopper) {\n      if (usePopper === void 0) {\n        usePopper = false;\n      }\n\n      if (this._element.disabled || $__default['default'](this._element).hasClass(CLASS_NAME_DISABLED) || $__default['default'](this._menu).hasClass(CLASS_NAME_SHOW$2)) {\n        return;\n      }\n\n      var relatedTarget = {\n        relatedTarget: this._element\n      };\n      var showEvent = $__default['default'].Event(EVENT_SHOW$1, relatedTarget);\n\n      var parent = Dropdown._getParentFromElement(this._element);\n\n      $__default['default'](parent).trigger(showEvent);\n\n      if (showEvent.isDefaultPrevented()) {\n        return;\n      } // Disable totally Popper.js for Dropdown in Navbar\n\n\n      if (!this._inNavbar && usePopper) {\n        /**\n         * Check for Popper dependency\n         * Popper - https://popper.js.org\n         */\n        if (typeof Popper__default['default'] === 'undefined') {\n          throw new TypeError('Bootstrap\\'s dropdowns require Popper.js (https://popper.js.org/)');\n        }\n\n        var referenceElement = this._element;\n\n        if (this._config.reference === 'parent') {\n          referenceElement = parent;\n        } else if (Util.isElement(this._config.reference)) {\n          referenceElement = this._config.reference; // Check if it's jQuery element\n\n          if (typeof this._config.reference.jquery !== 'undefined') {\n            referenceElement = this._config.reference[0];\n          }\n        } // If boundary is not `scrollParent`, then set position to `static`\n        // to allow the menu to \"escape\" the scroll parent's boundaries\n        // https://github.com/twbs/bootstrap/issues/24251\n\n\n        if (this._config.boundary !== 'scrollParent') {\n          $__default['default'](parent).addClass(CLASS_NAME_POSITION_STATIC);\n        }\n\n        this._popper = new Popper__default['default'](referenceElement, this._menu, this._getPopperConfig());\n      } // If this is a touch-enabled device we add extra\n      // empty mouseover listeners to the body's immediate children;\n      // only needed because of broken event delegation on iOS\n      // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n\n\n      if ('ontouchstart' in document.documentElement && $__default['default'](parent).closest(SELECTOR_NAVBAR_NAV).length === 0) {\n        $__default['default'](document.body).children().on('mouseover', null, $__default['default'].noop);\n      }\n\n      this._element.focus();\n\n      this._element.setAttribute('aria-expanded', true);\n\n      $__default['default'](this._menu).toggleClass(CLASS_NAME_SHOW$2);\n      $__default['default'](parent).toggleClass(CLASS_NAME_SHOW$2).trigger($__default['default'].Event(EVENT_SHOWN$1, relatedTarget));\n    };\n\n    _proto.hide = function hide() {\n      if (this._element.disabled || $__default['default'](this._element).hasClass(CLASS_NAME_DISABLED) || !$__default['default'](this._menu).hasClass(CLASS_NAME_SHOW$2)) {\n        return;\n      }\n\n      var relatedTarget = {\n        relatedTarget: this._element\n      };\n      var hideEvent = $__default['default'].Event(EVENT_HIDE$1, relatedTarget);\n\n      var parent = Dropdown._getParentFromElement(this._element);\n\n      $__default['default'](parent).trigger(hideEvent);\n\n      if (hideEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      if (this._popper) {\n        this._popper.destroy();\n      }\n\n      $__default['default'](this._menu).toggleClass(CLASS_NAME_SHOW$2);\n      $__default['default'](parent).toggleClass(CLASS_NAME_SHOW$2).trigger($__default['default'].Event(EVENT_HIDDEN$1, relatedTarget));\n    };\n\n    _proto.dispose = function dispose() {\n      $__default['default'].removeData(this._element, DATA_KEY$4);\n      $__default['default'](this._element).off(EVENT_KEY$4);\n      this._element = null;\n      this._menu = null;\n\n      if (this._popper !== null) {\n        this._popper.destroy();\n\n        this._popper = null;\n      }\n    };\n\n    _proto.update = function update() {\n      this._inNavbar = this._detectNavbar();\n\n      if (this._popper !== null) {\n        this._popper.scheduleUpdate();\n      }\n    } // Private\n    ;\n\n    _proto._addEventListeners = function _addEventListeners() {\n      var _this = this;\n\n      $__default['default'](this._element).on(EVENT_CLICK, function (event) {\n        event.preventDefault();\n        event.stopPropagation();\n\n        _this.toggle();\n      });\n    };\n\n    _proto._getConfig = function _getConfig(config) {\n      config = _extends({}, this.constructor.Default, $__default['default'](this._element).data(), config);\n      Util.typeCheckConfig(NAME$4, config, this.constructor.DefaultType);\n      return config;\n    };\n\n    _proto._getMenuElement = function _getMenuElement() {\n      if (!this._menu) {\n        var parent = Dropdown._getParentFromElement(this._element);\n\n        if (parent) {\n          this._menu = parent.querySelector(SELECTOR_MENU);\n        }\n      }\n\n      return this._menu;\n    };\n\n    _proto._getPlacement = function _getPlacement() {\n      var $parentDropdown = $__default['default'](this._element.parentNode);\n      var placement = PLACEMENT_BOTTOM; // Handle dropup\n\n      if ($parentDropdown.hasClass(CLASS_NAME_DROPUP)) {\n        placement = $__default['default'](this._menu).hasClass(CLASS_NAME_MENURIGHT) ? PLACEMENT_TOPEND : PLACEMENT_TOP;\n      } else if ($parentDropdown.hasClass(CLASS_NAME_DROPRIGHT)) {\n        placement = PLACEMENT_RIGHT;\n      } else if ($parentDropdown.hasClass(CLASS_NAME_DROPLEFT)) {\n        placement = PLACEMENT_LEFT;\n      } else if ($__default['default'](this._menu).hasClass(CLASS_NAME_MENURIGHT)) {\n        placement = PLACEMENT_BOTTOMEND;\n      }\n\n      return placement;\n    };\n\n    _proto._detectNavbar = function _detectNavbar() {\n      return $__default['default'](this._element).closest('.navbar').length > 0;\n    };\n\n    _proto._getOffset = function _getOffset() {\n      var _this2 = this;\n\n      var offset = {};\n\n      if (typeof this._config.offset === 'function') {\n        offset.fn = function (data) {\n          data.offsets = _extends({}, data.offsets, _this2._config.offset(data.offsets, _this2._element) || {});\n          return data;\n        };\n      } else {\n        offset.offset = this._config.offset;\n      }\n\n      return offset;\n    };\n\n    _proto._getPopperConfig = function _getPopperConfig() {\n      var popperConfig = {\n        placement: this._getPlacement(),\n        modifiers: {\n          offset: this._getOffset(),\n          flip: {\n            enabled: this._config.flip\n          },\n          preventOverflow: {\n            boundariesElement: this._config.boundary\n          }\n        }\n      }; // Disable Popper.js if we have a static display\n\n      if (this._config.display === 'static') {\n        popperConfig.modifiers.applyStyle = {\n          enabled: false\n        };\n      }\n\n      return _extends({}, popperConfig, this._config.popperConfig);\n    } // Static\n    ;\n\n    Dropdown._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var data = $__default['default'](this).data(DATA_KEY$4);\n\n        var _config = typeof config === 'object' ? config : null;\n\n        if (!data) {\n          data = new Dropdown(this, _config);\n          $__default['default'](this).data(DATA_KEY$4, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    Dropdown._clearMenus = function _clearMenus(event) {\n      if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH || event.type === 'keyup' && event.which !== TAB_KEYCODE)) {\n        return;\n      }\n\n      var toggles = [].slice.call(document.querySelectorAll(SELECTOR_DATA_TOGGLE$2));\n\n      for (var i = 0, len = toggles.length; i < len; i++) {\n        var parent = Dropdown._getParentFromElement(toggles[i]);\n\n        var context = $__default['default'](toggles[i]).data(DATA_KEY$4);\n        var relatedTarget = {\n          relatedTarget: toggles[i]\n        };\n\n        if (event && event.type === 'click') {\n          relatedTarget.clickEvent = event;\n        }\n\n        if (!context) {\n          continue;\n        }\n\n        var dropdownMenu = context._menu;\n\n        if (!$__default['default'](parent).hasClass(CLASS_NAME_SHOW$2)) {\n          continue;\n        }\n\n        if (event && (event.type === 'click' && /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) && $__default['default'].contains(parent, event.target)) {\n          continue;\n        }\n\n        var hideEvent = $__default['default'].Event(EVENT_HIDE$1, relatedTarget);\n        $__default['default'](parent).trigger(hideEvent);\n\n        if (hideEvent.isDefaultPrevented()) {\n          continue;\n        } // If this is a touch-enabled device we remove the extra\n        // empty mouseover listeners we added for iOS support\n\n\n        if ('ontouchstart' in document.documentElement) {\n          $__default['default'](document.body).children().off('mouseover', null, $__default['default'].noop);\n        }\n\n        toggles[i].setAttribute('aria-expanded', 'false');\n\n        if (context._popper) {\n          context._popper.destroy();\n        }\n\n        $__default['default'](dropdownMenu).removeClass(CLASS_NAME_SHOW$2);\n        $__default['default'](parent).removeClass(CLASS_NAME_SHOW$2).trigger($__default['default'].Event(EVENT_HIDDEN$1, relatedTarget));\n      }\n    };\n\n    Dropdown._getParentFromElement = function _getParentFromElement(element) {\n      var parent;\n      var selector = Util.getSelectorFromElement(element);\n\n      if (selector) {\n        parent = document.querySelector(selector);\n      }\n\n      return parent || element.parentNode;\n    } // eslint-disable-next-line complexity\n    ;\n\n    Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) {\n      // If not input/textarea:\n      //  - And not a key in REGEXP_KEYDOWN => not a dropdown command\n      // If input/textarea:\n      //  - If space key => not a dropdown command\n      //  - If key is other than escape\n      //    - If key is not up or down => not a dropdown command\n      //    - If trigger inside the menu => not a dropdown command\n      if (/input|textarea/i.test(event.target.tagName) ? event.which === SPACE_KEYCODE || event.which !== ESCAPE_KEYCODE && (event.which !== ARROW_DOWN_KEYCODE && event.which !== ARROW_UP_KEYCODE || $__default['default'](event.target).closest(SELECTOR_MENU).length) : !REGEXP_KEYDOWN.test(event.which)) {\n        return;\n      }\n\n      if (this.disabled || $__default['default'](this).hasClass(CLASS_NAME_DISABLED)) {\n        return;\n      }\n\n      var parent = Dropdown._getParentFromElement(this);\n\n      var isActive = $__default['default'](parent).hasClass(CLASS_NAME_SHOW$2);\n\n      if (!isActive && event.which === ESCAPE_KEYCODE) {\n        return;\n      }\n\n      event.preventDefault();\n      event.stopPropagation();\n\n      if (!isActive || event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE) {\n        if (event.which === ESCAPE_KEYCODE) {\n          $__default['default'](parent.querySelector(SELECTOR_DATA_TOGGLE$2)).trigger('focus');\n        }\n\n        $__default['default'](this).trigger('click');\n        return;\n      }\n\n      var items = [].slice.call(parent.querySelectorAll(SELECTOR_VISIBLE_ITEMS)).filter(function (item) {\n        return $__default['default'](item).is(':visible');\n      });\n\n      if (items.length === 0) {\n        return;\n      }\n\n      var index = items.indexOf(event.target);\n\n      if (event.which === ARROW_UP_KEYCODE && index > 0) {\n        // Up\n        index--;\n      }\n\n      if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) {\n        // Down\n        index++;\n      }\n\n      if (index < 0) {\n        index = 0;\n      }\n\n      items[index].focus();\n    };\n\n    _createClass(Dropdown, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION$4;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default$2;\n      }\n    }, {\n      key: \"DefaultType\",\n      get: function get() {\n        return DefaultType$2;\n      }\n    }]);\n\n    return Dropdown;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $__default['default'](document).on(EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE$2, Dropdown._dataApiKeydownHandler).on(EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown._dataApiKeydownHandler).on(EVENT_CLICK_DATA_API$4 + \" \" + EVENT_KEYUP_DATA_API, Dropdown._clearMenus).on(EVENT_CLICK_DATA_API$4, SELECTOR_DATA_TOGGLE$2, function (event) {\n    event.preventDefault();\n    event.stopPropagation();\n\n    Dropdown._jQueryInterface.call($__default['default'](this), 'toggle');\n  }).on(EVENT_CLICK_DATA_API$4, SELECTOR_FORM_CHILD, function (e) {\n    e.stopPropagation();\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $__default['default'].fn[NAME$4] = Dropdown._jQueryInterface;\n  $__default['default'].fn[NAME$4].Constructor = Dropdown;\n\n  $__default['default'].fn[NAME$4].noConflict = function () {\n    $__default['default'].fn[NAME$4] = JQUERY_NO_CONFLICT$4;\n    return Dropdown._jQueryInterface;\n  };\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME$5 = 'modal';\n  var VERSION$5 = '4.5.3';\n  var DATA_KEY$5 = 'bs.modal';\n  var EVENT_KEY$5 = \".\" + DATA_KEY$5;\n  var DATA_API_KEY$5 = '.data-api';\n  var JQUERY_NO_CONFLICT$5 = $__default['default'].fn[NAME$5];\n  var ESCAPE_KEYCODE$1 = 27; // KeyboardEvent.which value for Escape (Esc) key\n\n  var Default$3 = {\n    backdrop: true,\n    keyboard: true,\n    focus: true,\n    show: true\n  };\n  var DefaultType$3 = {\n    backdrop: '(boolean|string)',\n    keyboard: 'boolean',\n    focus: 'boolean',\n    show: 'boolean'\n  };\n  var EVENT_HIDE$2 = \"hide\" + EVENT_KEY$5;\n  var EVENT_HIDE_PREVENTED = \"hidePrevented\" + EVENT_KEY$5;\n  var EVENT_HIDDEN$2 = \"hidden\" + EVENT_KEY$5;\n  var EVENT_SHOW$2 = \"show\" + EVENT_KEY$5;\n  var EVENT_SHOWN$2 = \"shown\" + EVENT_KEY$5;\n  var EVENT_FOCUSIN = \"focusin\" + EVENT_KEY$5;\n  var EVENT_RESIZE = \"resize\" + EVENT_KEY$5;\n  var EVENT_CLICK_DISMISS = \"click.dismiss\" + EVENT_KEY$5;\n  var EVENT_KEYDOWN_DISMISS = \"keydown.dismiss\" + EVENT_KEY$5;\n  var EVENT_MOUSEUP_DISMISS = \"mouseup.dismiss\" + EVENT_KEY$5;\n  var EVENT_MOUSEDOWN_DISMISS = \"mousedown.dismiss\" + EVENT_KEY$5;\n  var EVENT_CLICK_DATA_API$5 = \"click\" + EVENT_KEY$5 + DATA_API_KEY$5;\n  var CLASS_NAME_SCROLLABLE = 'modal-dialog-scrollable';\n  var CLASS_NAME_SCROLLBAR_MEASURER = 'modal-scrollbar-measure';\n  var CLASS_NAME_BACKDROP = 'modal-backdrop';\n  var CLASS_NAME_OPEN = 'modal-open';\n  var CLASS_NAME_FADE$1 = 'fade';\n  var CLASS_NAME_SHOW$3 = 'show';\n  var CLASS_NAME_STATIC = 'modal-static';\n  var SELECTOR_DIALOG = '.modal-dialog';\n  var SELECTOR_MODAL_BODY = '.modal-body';\n  var SELECTOR_DATA_TOGGLE$3 = '[data-toggle=\"modal\"]';\n  var SELECTOR_DATA_DISMISS = '[data-dismiss=\"modal\"]';\n  var SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top';\n  var SELECTOR_STICKY_CONTENT = '.sticky-top';\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  var Modal = /*#__PURE__*/function () {\n    function Modal(element, config) {\n      this._config = this._getConfig(config);\n      this._element = element;\n      this._dialog = element.querySelector(SELECTOR_DIALOG);\n      this._backdrop = null;\n      this._isShown = false;\n      this._isBodyOverflowing = false;\n      this._ignoreBackdropClick = false;\n      this._isTransitioning = false;\n      this._scrollbarWidth = 0;\n    } // Getters\n\n\n    var _proto = Modal.prototype;\n\n    // Public\n    _proto.toggle = function toggle(relatedTarget) {\n      return this._isShown ? this.hide() : this.show(relatedTarget);\n    };\n\n    _proto.show = function show(relatedTarget) {\n      var _this = this;\n\n      if (this._isShown || this._isTransitioning) {\n        return;\n      }\n\n      if ($__default['default'](this._element).hasClass(CLASS_NAME_FADE$1)) {\n        this._isTransitioning = true;\n      }\n\n      var showEvent = $__default['default'].Event(EVENT_SHOW$2, {\n        relatedTarget: relatedTarget\n      });\n      $__default['default'](this._element).trigger(showEvent);\n\n      if (this._isShown || showEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      this._isShown = true;\n\n      this._checkScrollbar();\n\n      this._setScrollbar();\n\n      this._adjustDialog();\n\n      this._setEscapeEvent();\n\n      this._setResizeEvent();\n\n      $__default['default'](this._element).on(EVENT_CLICK_DISMISS, SELECTOR_DATA_DISMISS, function (event) {\n        return _this.hide(event);\n      });\n      $__default['default'](this._dialog).on(EVENT_MOUSEDOWN_DISMISS, function () {\n        $__default['default'](_this._element).one(EVENT_MOUSEUP_DISMISS, function (event) {\n          if ($__default['default'](event.target).is(_this._element)) {\n            _this._ignoreBackdropClick = true;\n          }\n        });\n      });\n\n      this._showBackdrop(function () {\n        return _this._showElement(relatedTarget);\n      });\n    };\n\n    _proto.hide = function hide(event) {\n      var _this2 = this;\n\n      if (event) {\n        event.preventDefault();\n      }\n\n      if (!this._isShown || this._isTransitioning) {\n        return;\n      }\n\n      var hideEvent = $__default['default'].Event(EVENT_HIDE$2);\n      $__default['default'](this._element).trigger(hideEvent);\n\n      if (!this._isShown || hideEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      this._isShown = false;\n      var transition = $__default['default'](this._element).hasClass(CLASS_NAME_FADE$1);\n\n      if (transition) {\n        this._isTransitioning = true;\n      }\n\n      this._setEscapeEvent();\n\n      this._setResizeEvent();\n\n      $__default['default'](document).off(EVENT_FOCUSIN);\n      $__default['default'](this._element).removeClass(CLASS_NAME_SHOW$3);\n      $__default['default'](this._element).off(EVENT_CLICK_DISMISS);\n      $__default['default'](this._dialog).off(EVENT_MOUSEDOWN_DISMISS);\n\n      if (transition) {\n        var transitionDuration = Util.getTransitionDurationFromElement(this._element);\n        $__default['default'](this._element).one(Util.TRANSITION_END, function (event) {\n          return _this2._hideModal(event);\n        }).emulateTransitionEnd(transitionDuration);\n      } else {\n        this._hideModal();\n      }\n    };\n\n    _proto.dispose = function dispose() {\n      [window, this._element, this._dialog].forEach(function (htmlElement) {\n        return $__default['default'](htmlElement).off(EVENT_KEY$5);\n      });\n      /**\n       * `document` has 2 events `EVENT_FOCUSIN` and `EVENT_CLICK_DATA_API`\n       * Do not move `document` in `htmlElements` array\n       * It will remove `EVENT_CLICK_DATA_API` event that should remain\n       */\n\n      $__default['default'](document).off(EVENT_FOCUSIN);\n      $__default['default'].removeData(this._element, DATA_KEY$5);\n      this._config = null;\n      this._element = null;\n      this._dialog = null;\n      this._backdrop = null;\n      this._isShown = null;\n      this._isBodyOverflowing = null;\n      this._ignoreBackdropClick = null;\n      this._isTransitioning = null;\n      this._scrollbarWidth = null;\n    };\n\n    _proto.handleUpdate = function handleUpdate() {\n      this._adjustDialog();\n    } // Private\n    ;\n\n    _proto._getConfig = function _getConfig(config) {\n      config = _extends({}, Default$3, config);\n      Util.typeCheckConfig(NAME$5, config, DefaultType$3);\n      return config;\n    };\n\n    _proto._triggerBackdropTransition = function _triggerBackdropTransition() {\n      var _this3 = this;\n\n      if (this._config.backdrop === 'static') {\n        var hideEventPrevented = $__default['default'].Event(EVENT_HIDE_PREVENTED);\n        $__default['default'](this._element).trigger(hideEventPrevented);\n\n        if (hideEventPrevented.isDefaultPrevented()) {\n          return;\n        }\n\n        var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;\n\n        if (!isModalOverflowing) {\n          this._element.style.overflowY = 'hidden';\n        }\n\n        this._element.classList.add(CLASS_NAME_STATIC);\n\n        var modalTransitionDuration = Util.getTransitionDurationFromElement(this._dialog);\n        $__default['default'](this._element).off(Util.TRANSITION_END);\n        $__default['default'](this._element).one(Util.TRANSITION_END, function () {\n          _this3._element.classList.remove(CLASS_NAME_STATIC);\n\n          if (!isModalOverflowing) {\n            $__default['default'](_this3._element).one(Util.TRANSITION_END, function () {\n              _this3._element.style.overflowY = '';\n            }).emulateTransitionEnd(_this3._element, modalTransitionDuration);\n          }\n        }).emulateTransitionEnd(modalTransitionDuration);\n\n        this._element.focus();\n      } else {\n        this.hide();\n      }\n    };\n\n    _proto._showElement = function _showElement(relatedTarget) {\n      var _this4 = this;\n\n      var transition = $__default['default'](this._element).hasClass(CLASS_NAME_FADE$1);\n      var modalBody = this._dialog ? this._dialog.querySelector(SELECTOR_MODAL_BODY) : null;\n\n      if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {\n        // Don't move modal's DOM position\n        document.body.appendChild(this._element);\n      }\n\n      this._element.style.display = 'block';\n\n      this._element.removeAttribute('aria-hidden');\n\n      this._element.setAttribute('aria-modal', true);\n\n      this._element.setAttribute('role', 'dialog');\n\n      if ($__default['default'](this._dialog).hasClass(CLASS_NAME_SCROLLABLE) && modalBody) {\n        modalBody.scrollTop = 0;\n      } else {\n        this._element.scrollTop = 0;\n      }\n\n      if (transition) {\n        Util.reflow(this._element);\n      }\n\n      $__default['default'](this._element).addClass(CLASS_NAME_SHOW$3);\n\n      if (this._config.focus) {\n        this._enforceFocus();\n      }\n\n      var shownEvent = $__default['default'].Event(EVENT_SHOWN$2, {\n        relatedTarget: relatedTarget\n      });\n\n      var transitionComplete = function transitionComplete() {\n        if (_this4._config.focus) {\n          _this4._element.focus();\n        }\n\n        _this4._isTransitioning = false;\n        $__default['default'](_this4._element).trigger(shownEvent);\n      };\n\n      if (transition) {\n        var transitionDuration = Util.getTransitionDurationFromElement(this._dialog);\n        $__default['default'](this._dialog).one(Util.TRANSITION_END, transitionComplete).emulateTransitionEnd(transitionDuration);\n      } else {\n        transitionComplete();\n      }\n    };\n\n    _proto._enforceFocus = function _enforceFocus() {\n      var _this5 = this;\n\n      $__default['default'](document).off(EVENT_FOCUSIN) // Guard against infinite focus loop\n      .on(EVENT_FOCUSIN, function (event) {\n        if (document !== event.target && _this5._element !== event.target && $__default['default'](_this5._element).has(event.target).length === 0) {\n          _this5._element.focus();\n        }\n      });\n    };\n\n    _proto._setEscapeEvent = function _setEscapeEvent() {\n      var _this6 = this;\n\n      if (this._isShown) {\n        $__default['default'](this._element).on(EVENT_KEYDOWN_DISMISS, function (event) {\n          if (_this6._config.keyboard && event.which === ESCAPE_KEYCODE$1) {\n            event.preventDefault();\n\n            _this6.hide();\n          } else if (!_this6._config.keyboard && event.which === ESCAPE_KEYCODE$1) {\n            _this6._triggerBackdropTransition();\n          }\n        });\n      } else if (!this._isShown) {\n        $__default['default'](this._element).off(EVENT_KEYDOWN_DISMISS);\n      }\n    };\n\n    _proto._setResizeEvent = function _setResizeEvent() {\n      var _this7 = this;\n\n      if (this._isShown) {\n        $__default['default'](window).on(EVENT_RESIZE, function (event) {\n          return _this7.handleUpdate(event);\n        });\n      } else {\n        $__default['default'](window).off(EVENT_RESIZE);\n      }\n    };\n\n    _proto._hideModal = function _hideModal() {\n      var _this8 = this;\n\n      this._element.style.display = 'none';\n\n      this._element.setAttribute('aria-hidden', true);\n\n      this._element.removeAttribute('aria-modal');\n\n      this._element.removeAttribute('role');\n\n      this._isTransitioning = false;\n\n      this._showBackdrop(function () {\n        $__default['default'](document.body).removeClass(CLASS_NAME_OPEN);\n\n        _this8._resetAdjustments();\n\n        _this8._resetScrollbar();\n\n        $__default['default'](_this8._element).trigger(EVENT_HIDDEN$2);\n      });\n    };\n\n    _proto._removeBackdrop = function _removeBackdrop() {\n      if (this._backdrop) {\n        $__default['default'](this._backdrop).remove();\n        this._backdrop = null;\n      }\n    };\n\n    _proto._showBackdrop = function _showBackdrop(callback) {\n      var _this9 = this;\n\n      var animate = $__default['default'](this._element).hasClass(CLASS_NAME_FADE$1) ? CLASS_NAME_FADE$1 : '';\n\n      if (this._isShown && this._config.backdrop) {\n        this._backdrop = document.createElement('div');\n        this._backdrop.className = CLASS_NAME_BACKDROP;\n\n        if (animate) {\n          this._backdrop.classList.add(animate);\n        }\n\n        $__default['default'](this._backdrop).appendTo(document.body);\n        $__default['default'](this._element).on(EVENT_CLICK_DISMISS, function (event) {\n          if (_this9._ignoreBackdropClick) {\n            _this9._ignoreBackdropClick = false;\n            return;\n          }\n\n          if (event.target !== event.currentTarget) {\n            return;\n          }\n\n          _this9._triggerBackdropTransition();\n        });\n\n        if (animate) {\n          Util.reflow(this._backdrop);\n        }\n\n        $__default['default'](this._backdrop).addClass(CLASS_NAME_SHOW$3);\n\n        if (!callback) {\n          return;\n        }\n\n        if (!animate) {\n          callback();\n          return;\n        }\n\n        var backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop);\n        $__default['default'](this._backdrop).one(Util.TRANSITION_END, callback).emulateTransitionEnd(backdropTransitionDuration);\n      } else if (!this._isShown && this._backdrop) {\n        $__default['default'](this._backdrop).removeClass(CLASS_NAME_SHOW$3);\n\n        var callbackRemove = function callbackRemove() {\n          _this9._removeBackdrop();\n\n          if (callback) {\n            callback();\n          }\n        };\n\n        if ($__default['default'](this._element).hasClass(CLASS_NAME_FADE$1)) {\n          var _backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop);\n\n          $__default['default'](this._backdrop).one(Util.TRANSITION_END, callbackRemove).emulateTransitionEnd(_backdropTransitionDuration);\n        } else {\n          callbackRemove();\n        }\n      } else if (callback) {\n        callback();\n      }\n    } // ----------------------------------------------------------------------\n    // the following methods are used to handle overflowing modals\n    // todo (fat): these should probably be refactored out of modal.js\n    // ----------------------------------------------------------------------\n    ;\n\n    _proto._adjustDialog = function _adjustDialog() {\n      var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;\n\n      if (!this._isBodyOverflowing && isModalOverflowing) {\n        this._element.style.paddingLeft = this._scrollbarWidth + \"px\";\n      }\n\n      if (this._isBodyOverflowing && !isModalOverflowing) {\n        this._element.style.paddingRight = this._scrollbarWidth + \"px\";\n      }\n    };\n\n    _proto._resetAdjustments = function _resetAdjustments() {\n      this._element.style.paddingLeft = '';\n      this._element.style.paddingRight = '';\n    };\n\n    _proto._checkScrollbar = function _checkScrollbar() {\n      var rect = document.body.getBoundingClientRect();\n      this._isBodyOverflowing = Math.round(rect.left + rect.right) < window.innerWidth;\n      this._scrollbarWidth = this._getScrollbarWidth();\n    };\n\n    _proto._setScrollbar = function _setScrollbar() {\n      var _this10 = this;\n\n      if (this._isBodyOverflowing) {\n        // Note: DOMNode.style.paddingRight returns the actual value or '' if not set\n        //   while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set\n        var fixedContent = [].slice.call(document.querySelectorAll(SELECTOR_FIXED_CONTENT));\n        var stickyContent = [].slice.call(document.querySelectorAll(SELECTOR_STICKY_CONTENT)); // Adjust fixed content padding\n\n        $__default['default'](fixedContent).each(function (index, element) {\n          var actualPadding = element.style.paddingRight;\n          var calculatedPadding = $__default['default'](element).css('padding-right');\n          $__default['default'](element).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + _this10._scrollbarWidth + \"px\");\n        }); // Adjust sticky content margin\n\n        $__default['default'](stickyContent).each(function (index, element) {\n          var actualMargin = element.style.marginRight;\n          var calculatedMargin = $__default['default'](element).css('margin-right');\n          $__default['default'](element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) - _this10._scrollbarWidth + \"px\");\n        }); // Adjust body padding\n\n        var actualPadding = document.body.style.paddingRight;\n        var calculatedPadding = $__default['default'](document.body).css('padding-right');\n        $__default['default'](document.body).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + this._scrollbarWidth + \"px\");\n      }\n\n      $__default['default'](document.body).addClass(CLASS_NAME_OPEN);\n    };\n\n    _proto._resetScrollbar = function _resetScrollbar() {\n      // Restore fixed content padding\n      var fixedContent = [].slice.call(document.querySelectorAll(SELECTOR_FIXED_CONTENT));\n      $__default['default'](fixedContent).each(function (index, element) {\n        var padding = $__default['default'](element).data('padding-right');\n        $__default['default'](element).removeData('padding-right');\n        element.style.paddingRight = padding ? padding : '';\n      }); // Restore sticky content\n\n      var elements = [].slice.call(document.querySelectorAll(\"\" + SELECTOR_STICKY_CONTENT));\n      $__default['default'](elements).each(function (index, element) {\n        var margin = $__default['default'](element).data('margin-right');\n\n        if (typeof margin !== 'undefined') {\n          $__default['default'](element).css('margin-right', margin).removeData('margin-right');\n        }\n      }); // Restore body padding\n\n      var padding = $__default['default'](document.body).data('padding-right');\n      $__default['default'](document.body).removeData('padding-right');\n      document.body.style.paddingRight = padding ? padding : '';\n    };\n\n    _proto._getScrollbarWidth = function _getScrollbarWidth() {\n      // thx d.walsh\n      var scrollDiv = document.createElement('div');\n      scrollDiv.className = CLASS_NAME_SCROLLBAR_MEASURER;\n      document.body.appendChild(scrollDiv);\n      var scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth;\n      document.body.removeChild(scrollDiv);\n      return scrollbarWidth;\n    } // Static\n    ;\n\n    Modal._jQueryInterface = function _jQueryInterface(config, relatedTarget) {\n      return this.each(function () {\n        var data = $__default['default'](this).data(DATA_KEY$5);\n\n        var _config = _extends({}, Default$3, $__default['default'](this).data(), typeof config === 'object' && config ? config : {});\n\n        if (!data) {\n          data = new Modal(this, _config);\n          $__default['default'](this).data(DATA_KEY$5, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config](relatedTarget);\n        } else if (_config.show) {\n          data.show(relatedTarget);\n        }\n      });\n    };\n\n    _createClass(Modal, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION$5;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default$3;\n      }\n    }]);\n\n    return Modal;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $__default['default'](document).on(EVENT_CLICK_DATA_API$5, SELECTOR_DATA_TOGGLE$3, function (event) {\n    var _this11 = this;\n\n    var target;\n    var selector = Util.getSelectorFromElement(this);\n\n    if (selector) {\n      target = document.querySelector(selector);\n    }\n\n    var config = $__default['default'](target).data(DATA_KEY$5) ? 'toggle' : _extends({}, $__default['default'](target).data(), $__default['default'](this).data());\n\n    if (this.tagName === 'A' || this.tagName === 'AREA') {\n      event.preventDefault();\n    }\n\n    var $target = $__default['default'](target).one(EVENT_SHOW$2, function (showEvent) {\n      if (showEvent.isDefaultPrevented()) {\n        // Only register focus restorer if modal will actually get shown\n        return;\n      }\n\n      $target.one(EVENT_HIDDEN$2, function () {\n        if ($__default['default'](_this11).is(':visible')) {\n          _this11.focus();\n        }\n      });\n    });\n\n    Modal._jQueryInterface.call($__default['default'](target), config, this);\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $__default['default'].fn[NAME$5] = Modal._jQueryInterface;\n  $__default['default'].fn[NAME$5].Constructor = Modal;\n\n  $__default['default'].fn[NAME$5].noConflict = function () {\n    $__default['default'].fn[NAME$5] = JQUERY_NO_CONFLICT$5;\n    return Modal._jQueryInterface;\n  };\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v4.5.3): tools/sanitizer.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n  var uriAttrs = ['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href'];\n  var ARIA_ATTRIBUTE_PATTERN = /^aria-[\\w-]*$/i;\n  var DefaultWhitelist = {\n    // Global attributes allowed on any supplied element below.\n    '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],\n    a: ['target', 'href', 'title', 'rel'],\n    area: [],\n    b: [],\n    br: [],\n    col: [],\n    code: [],\n    div: [],\n    em: [],\n    hr: [],\n    h1: [],\n    h2: [],\n    h3: [],\n    h4: [],\n    h5: [],\n    h6: [],\n    i: [],\n    img: ['src', 'srcset', 'alt', 'title', 'width', 'height'],\n    li: [],\n    ol: [],\n    p: [],\n    pre: [],\n    s: [],\n    small: [],\n    span: [],\n    sub: [],\n    sup: [],\n    strong: [],\n    u: [],\n    ul: []\n  };\n  /**\n   * A pattern that recognizes a commonly useful subset of URLs that are safe.\n   *\n   * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts\n   */\n\n  var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/gi;\n  /**\n   * A pattern that matches safe data URLs. Only matches image, video and audio types.\n   *\n   * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts\n   */\n\n  var DATA_URL_PATTERN = /^data:(?:image\\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\\/(?:mpeg|mp4|ogg|webm)|audio\\/(?:mp3|oga|ogg|opus));base64,[\\d+/a-z]+=*$/i;\n\n  function allowedAttribute(attr, allowedAttributeList) {\n    var attrName = attr.nodeName.toLowerCase();\n\n    if (allowedAttributeList.indexOf(attrName) !== -1) {\n      if (uriAttrs.indexOf(attrName) !== -1) {\n        return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN));\n      }\n\n      return true;\n    }\n\n    var regExp = allowedAttributeList.filter(function (attrRegex) {\n      return attrRegex instanceof RegExp;\n    }); // Check if a regular expression validates the attribute.\n\n    for (var i = 0, len = regExp.length; i < len; i++) {\n      if (attrName.match(regExp[i])) {\n        return true;\n      }\n    }\n\n    return false;\n  }\n\n  function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {\n    if (unsafeHtml.length === 0) {\n      return unsafeHtml;\n    }\n\n    if (sanitizeFn && typeof sanitizeFn === 'function') {\n      return sanitizeFn(unsafeHtml);\n    }\n\n    var domParser = new window.DOMParser();\n    var createdDocument = domParser.parseFromString(unsafeHtml, 'text/html');\n    var whitelistKeys = Object.keys(whiteList);\n    var elements = [].slice.call(createdDocument.body.querySelectorAll('*'));\n\n    var _loop = function _loop(i, len) {\n      var el = elements[i];\n      var elName = el.nodeName.toLowerCase();\n\n      if (whitelistKeys.indexOf(el.nodeName.toLowerCase()) === -1) {\n        el.parentNode.removeChild(el);\n        return \"continue\";\n      }\n\n      var attributeList = [].slice.call(el.attributes);\n      var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || []);\n      attributeList.forEach(function (attr) {\n        if (!allowedAttribute(attr, whitelistedAttributes)) {\n          el.removeAttribute(attr.nodeName);\n        }\n      });\n    };\n\n    for (var i = 0, len = elements.length; i < len; i++) {\n      var _ret = _loop(i);\n\n      if (_ret === \"continue\") continue;\n    }\n\n    return createdDocument.body.innerHTML;\n  }\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME$6 = 'tooltip';\n  var VERSION$6 = '4.5.3';\n  var DATA_KEY$6 = 'bs.tooltip';\n  var EVENT_KEY$6 = \".\" + DATA_KEY$6;\n  var JQUERY_NO_CONFLICT$6 = $__default['default'].fn[NAME$6];\n  var CLASS_PREFIX = 'bs-tooltip';\n  var BSCLS_PREFIX_REGEX = new RegExp(\"(^|\\\\s)\" + CLASS_PREFIX + \"\\\\S+\", 'g');\n  var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn'];\n  var DefaultType$4 = {\n    animation: 'boolean',\n    template: 'string',\n    title: '(string|element|function)',\n    trigger: 'string',\n    delay: '(number|object)',\n    html: 'boolean',\n    selector: '(string|boolean)',\n    placement: '(string|function)',\n    offset: '(number|string|function)',\n    container: '(string|element|boolean)',\n    fallbackPlacement: '(string|array)',\n    boundary: '(string|element)',\n    sanitize: 'boolean',\n    sanitizeFn: '(null|function)',\n    whiteList: 'object',\n    popperConfig: '(null|object)'\n  };\n  var AttachmentMap = {\n    AUTO: 'auto',\n    TOP: 'top',\n    RIGHT: 'right',\n    BOTTOM: 'bottom',\n    LEFT: 'left'\n  };\n  var Default$4 = {\n    animation: true,\n    template: '<div class=\"tooltip\" role=\"tooltip\">' + '<div class=\"arrow\"></div>' + '<div class=\"tooltip-inner\"></div></div>',\n    trigger: 'hover focus',\n    title: '',\n    delay: 0,\n    html: false,\n    selector: false,\n    placement: 'top',\n    offset: 0,\n    container: false,\n    fallbackPlacement: 'flip',\n    boundary: 'scrollParent',\n    sanitize: true,\n    sanitizeFn: null,\n    whiteList: DefaultWhitelist,\n    popperConfig: null\n  };\n  var HOVER_STATE_SHOW = 'show';\n  var HOVER_STATE_OUT = 'out';\n  var Event = {\n    HIDE: \"hide\" + EVENT_KEY$6,\n    HIDDEN: \"hidden\" + EVENT_KEY$6,\n    SHOW: \"show\" + EVENT_KEY$6,\n    SHOWN: \"shown\" + EVENT_KEY$6,\n    INSERTED: \"inserted\" + EVENT_KEY$6,\n    CLICK: \"click\" + EVENT_KEY$6,\n    FOCUSIN: \"focusin\" + EVENT_KEY$6,\n    FOCUSOUT: \"focusout\" + EVENT_KEY$6,\n    MOUSEENTER: \"mouseenter\" + EVENT_KEY$6,\n    MOUSELEAVE: \"mouseleave\" + EVENT_KEY$6\n  };\n  var CLASS_NAME_FADE$2 = 'fade';\n  var CLASS_NAME_SHOW$4 = 'show';\n  var SELECTOR_TOOLTIP_INNER = '.tooltip-inner';\n  var SELECTOR_ARROW = '.arrow';\n  var TRIGGER_HOVER = 'hover';\n  var TRIGGER_FOCUS = 'focus';\n  var TRIGGER_CLICK = 'click';\n  var TRIGGER_MANUAL = 'manual';\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  var Tooltip = /*#__PURE__*/function () {\n    function Tooltip(element, config) {\n      if (typeof Popper__default['default'] === 'undefined') {\n        throw new TypeError('Bootstrap\\'s tooltips require Popper.js (https://popper.js.org/)');\n      } // private\n\n\n      this._isEnabled = true;\n      this._timeout = 0;\n      this._hoverState = '';\n      this._activeTrigger = {};\n      this._popper = null; // Protected\n\n      this.element = element;\n      this.config = this._getConfig(config);\n      this.tip = null;\n\n      this._setListeners();\n    } // Getters\n\n\n    var _proto = Tooltip.prototype;\n\n    // Public\n    _proto.enable = function enable() {\n      this._isEnabled = true;\n    };\n\n    _proto.disable = function disable() {\n      this._isEnabled = false;\n    };\n\n    _proto.toggleEnabled = function toggleEnabled() {\n      this._isEnabled = !this._isEnabled;\n    };\n\n    _proto.toggle = function toggle(event) {\n      if (!this._isEnabled) {\n        return;\n      }\n\n      if (event) {\n        var dataKey = this.constructor.DATA_KEY;\n        var context = $__default['default'](event.currentTarget).data(dataKey);\n\n        if (!context) {\n          context = new this.constructor(event.currentTarget, this._getDelegateConfig());\n          $__default['default'](event.currentTarget).data(dataKey, context);\n        }\n\n        context._activeTrigger.click = !context._activeTrigger.click;\n\n        if (context._isWithActiveTrigger()) {\n          context._enter(null, context);\n        } else {\n          context._leave(null, context);\n        }\n      } else {\n        if ($__default['default'](this.getTipElement()).hasClass(CLASS_NAME_SHOW$4)) {\n          this._leave(null, this);\n\n          return;\n        }\n\n        this._enter(null, this);\n      }\n    };\n\n    _proto.dispose = function dispose() {\n      clearTimeout(this._timeout);\n      $__default['default'].removeData(this.element, this.constructor.DATA_KEY);\n      $__default['default'](this.element).off(this.constructor.EVENT_KEY);\n      $__default['default'](this.element).closest('.modal').off('hide.bs.modal', this._hideModalHandler);\n\n      if (this.tip) {\n        $__default['default'](this.tip).remove();\n      }\n\n      this._isEnabled = null;\n      this._timeout = null;\n      this._hoverState = null;\n      this._activeTrigger = null;\n\n      if (this._popper) {\n        this._popper.destroy();\n      }\n\n      this._popper = null;\n      this.element = null;\n      this.config = null;\n      this.tip = null;\n    };\n\n    _proto.show = function show() {\n      var _this = this;\n\n      if ($__default['default'](this.element).css('display') === 'none') {\n        throw new Error('Please use show on visible elements');\n      }\n\n      var showEvent = $__default['default'].Event(this.constructor.Event.SHOW);\n\n      if (this.isWithContent() && this._isEnabled) {\n        $__default['default'](this.element).trigger(showEvent);\n        var shadowRoot = Util.findShadowRoot(this.element);\n        var isInTheDom = $__default['default'].contains(shadowRoot !== null ? shadowRoot : this.element.ownerDocument.documentElement, this.element);\n\n        if (showEvent.isDefaultPrevented() || !isInTheDom) {\n          return;\n        }\n\n        var tip = this.getTipElement();\n        var tipId = Util.getUID(this.constructor.NAME);\n        tip.setAttribute('id', tipId);\n        this.element.setAttribute('aria-describedby', tipId);\n        this.setContent();\n\n        if (this.config.animation) {\n          $__default['default'](tip).addClass(CLASS_NAME_FADE$2);\n        }\n\n        var placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement;\n\n        var attachment = this._getAttachment(placement);\n\n        this.addAttachmentClass(attachment);\n\n        var container = this._getContainer();\n\n        $__default['default'](tip).data(this.constructor.DATA_KEY, this);\n\n        if (!$__default['default'].contains(this.element.ownerDocument.documentElement, this.tip)) {\n          $__default['default'](tip).appendTo(container);\n        }\n\n        $__default['default'](this.element).trigger(this.constructor.Event.INSERTED);\n        this._popper = new Popper__default['default'](this.element, tip, this._getPopperConfig(attachment));\n        $__default['default'](tip).addClass(CLASS_NAME_SHOW$4); // If this is a touch-enabled device we add extra\n        // empty mouseover listeners to the body's immediate children;\n        // only needed because of broken event delegation on iOS\n        // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n\n        if ('ontouchstart' in document.documentElement) {\n          $__default['default'](document.body).children().on('mouseover', null, $__default['default'].noop);\n        }\n\n        var complete = function complete() {\n          if (_this.config.animation) {\n            _this._fixTransition();\n          }\n\n          var prevHoverState = _this._hoverState;\n          _this._hoverState = null;\n          $__default['default'](_this.element).trigger(_this.constructor.Event.SHOWN);\n\n          if (prevHoverState === HOVER_STATE_OUT) {\n            _this._leave(null, _this);\n          }\n        };\n\n        if ($__default['default'](this.tip).hasClass(CLASS_NAME_FADE$2)) {\n          var transitionDuration = Util.getTransitionDurationFromElement(this.tip);\n          $__default['default'](this.tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);\n        } else {\n          complete();\n        }\n      }\n    };\n\n    _proto.hide = function hide(callback) {\n      var _this2 = this;\n\n      var tip = this.getTipElement();\n      var hideEvent = $__default['default'].Event(this.constructor.Event.HIDE);\n\n      var complete = function complete() {\n        if (_this2._hoverState !== HOVER_STATE_SHOW && tip.parentNode) {\n          tip.parentNode.removeChild(tip);\n        }\n\n        _this2._cleanTipClass();\n\n        _this2.element.removeAttribute('aria-describedby');\n\n        $__default['default'](_this2.element).trigger(_this2.constructor.Event.HIDDEN);\n\n        if (_this2._popper !== null) {\n          _this2._popper.destroy();\n        }\n\n        if (callback) {\n          callback();\n        }\n      };\n\n      $__default['default'](this.element).trigger(hideEvent);\n\n      if (hideEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      $__default['default'](tip).removeClass(CLASS_NAME_SHOW$4); // If this is a touch-enabled device we remove the extra\n      // empty mouseover listeners we added for iOS support\n\n      if ('ontouchstart' in document.documentElement) {\n        $__default['default'](document.body).children().off('mouseover', null, $__default['default'].noop);\n      }\n\n      this._activeTrigger[TRIGGER_CLICK] = false;\n      this._activeTrigger[TRIGGER_FOCUS] = false;\n      this._activeTrigger[TRIGGER_HOVER] = false;\n\n      if ($__default['default'](this.tip).hasClass(CLASS_NAME_FADE$2)) {\n        var transitionDuration = Util.getTransitionDurationFromElement(tip);\n        $__default['default'](tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);\n      } else {\n        complete();\n      }\n\n      this._hoverState = '';\n    };\n\n    _proto.update = function update() {\n      if (this._popper !== null) {\n        this._popper.scheduleUpdate();\n      }\n    } // Protected\n    ;\n\n    _proto.isWithContent = function isWithContent() {\n      return Boolean(this.getTitle());\n    };\n\n    _proto.addAttachmentClass = function addAttachmentClass(attachment) {\n      $__default['default'](this.getTipElement()).addClass(CLASS_PREFIX + \"-\" + attachment);\n    };\n\n    _proto.getTipElement = function getTipElement() {\n      this.tip = this.tip || $__default['default'](this.config.template)[0];\n      return this.tip;\n    };\n\n    _proto.setContent = function setContent() {\n      var tip = this.getTipElement();\n      this.setElementContent($__default['default'](tip.querySelectorAll(SELECTOR_TOOLTIP_INNER)), this.getTitle());\n      $__default['default'](tip).removeClass(CLASS_NAME_FADE$2 + \" \" + CLASS_NAME_SHOW$4);\n    };\n\n    _proto.setElementContent = function setElementContent($element, content) {\n      if (typeof content === 'object' && (content.nodeType || content.jquery)) {\n        // Content is a DOM node or a jQuery\n        if (this.config.html) {\n          if (!$__default['default'](content).parent().is($element)) {\n            $element.empty().append(content);\n          }\n        } else {\n          $element.text($__default['default'](content).text());\n        }\n\n        return;\n      }\n\n      if (this.config.html) {\n        if (this.config.sanitize) {\n          content = sanitizeHtml(content, this.config.whiteList, this.config.sanitizeFn);\n        }\n\n        $element.html(content);\n      } else {\n        $element.text(content);\n      }\n    };\n\n    _proto.getTitle = function getTitle() {\n      var title = this.element.getAttribute('data-original-title');\n\n      if (!title) {\n        title = typeof this.config.title === 'function' ? this.config.title.call(this.element) : this.config.title;\n      }\n\n      return title;\n    } // Private\n    ;\n\n    _proto._getPopperConfig = function _getPopperConfig(attachment) {\n      var _this3 = this;\n\n      var defaultBsConfig = {\n        placement: attachment,\n        modifiers: {\n          offset: this._getOffset(),\n          flip: {\n            behavior: this.config.fallbackPlacement\n          },\n          arrow: {\n            element: SELECTOR_ARROW\n          },\n          preventOverflow: {\n            boundariesElement: this.config.boundary\n          }\n        },\n        onCreate: function onCreate(data) {\n          if (data.originalPlacement !== data.placement) {\n            _this3._handlePopperPlacementChange(data);\n          }\n        },\n        onUpdate: function onUpdate(data) {\n          return _this3._handlePopperPlacementChange(data);\n        }\n      };\n      return _extends({}, defaultBsConfig, this.config.popperConfig);\n    };\n\n    _proto._getOffset = function _getOffset() {\n      var _this4 = this;\n\n      var offset = {};\n\n      if (typeof this.config.offset === 'function') {\n        offset.fn = function (data) {\n          data.offsets = _extends({}, data.offsets, _this4.config.offset(data.offsets, _this4.element) || {});\n          return data;\n        };\n      } else {\n        offset.offset = this.config.offset;\n      }\n\n      return offset;\n    };\n\n    _proto._getContainer = function _getContainer() {\n      if (this.config.container === false) {\n        return document.body;\n      }\n\n      if (Util.isElement(this.config.container)) {\n        return $__default['default'](this.config.container);\n      }\n\n      return $__default['default'](document).find(this.config.container);\n    };\n\n    _proto._getAttachment = function _getAttachment(placement) {\n      return AttachmentMap[placement.toUpperCase()];\n    };\n\n    _proto._setListeners = function _setListeners() {\n      var _this5 = this;\n\n      var triggers = this.config.trigger.split(' ');\n      triggers.forEach(function (trigger) {\n        if (trigger === 'click') {\n          $__default['default'](_this5.element).on(_this5.constructor.Event.CLICK, _this5.config.selector, function (event) {\n            return _this5.toggle(event);\n          });\n        } else if (trigger !== TRIGGER_MANUAL) {\n          var eventIn = trigger === TRIGGER_HOVER ? _this5.constructor.Event.MOUSEENTER : _this5.constructor.Event.FOCUSIN;\n          var eventOut = trigger === TRIGGER_HOVER ? _this5.constructor.Event.MOUSELEAVE : _this5.constructor.Event.FOCUSOUT;\n          $__default['default'](_this5.element).on(eventIn, _this5.config.selector, function (event) {\n            return _this5._enter(event);\n          }).on(eventOut, _this5.config.selector, function (event) {\n            return _this5._leave(event);\n          });\n        }\n      });\n\n      this._hideModalHandler = function () {\n        if (_this5.element) {\n          _this5.hide();\n        }\n      };\n\n      $__default['default'](this.element).closest('.modal').on('hide.bs.modal', this._hideModalHandler);\n\n      if (this.config.selector) {\n        this.config = _extends({}, this.config, {\n          trigger: 'manual',\n          selector: ''\n        });\n      } else {\n        this._fixTitle();\n      }\n    };\n\n    _proto._fixTitle = function _fixTitle() {\n      var titleType = typeof this.element.getAttribute('data-original-title');\n\n      if (this.element.getAttribute('title') || titleType !== 'string') {\n        this.element.setAttribute('data-original-title', this.element.getAttribute('title') || '');\n        this.element.setAttribute('title', '');\n      }\n    };\n\n    _proto._enter = function _enter(event, context) {\n      var dataKey = this.constructor.DATA_KEY;\n      context = context || $__default['default'](event.currentTarget).data(dataKey);\n\n      if (!context) {\n        context = new this.constructor(event.currentTarget, this._getDelegateConfig());\n        $__default['default'](event.currentTarget).data(dataKey, context);\n      }\n\n      if (event) {\n        context._activeTrigger[event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER] = true;\n      }\n\n      if ($__default['default'](context.getTipElement()).hasClass(CLASS_NAME_SHOW$4) || context._hoverState === HOVER_STATE_SHOW) {\n        context._hoverState = HOVER_STATE_SHOW;\n        return;\n      }\n\n      clearTimeout(context._timeout);\n      context._hoverState = HOVER_STATE_SHOW;\n\n      if (!context.config.delay || !context.config.delay.show) {\n        context.show();\n        return;\n      }\n\n      context._timeout = setTimeout(function () {\n        if (context._hoverState === HOVER_STATE_SHOW) {\n          context.show();\n        }\n      }, context.config.delay.show);\n    };\n\n    _proto._leave = function _leave(event, context) {\n      var dataKey = this.constructor.DATA_KEY;\n      context = context || $__default['default'](event.currentTarget).data(dataKey);\n\n      if (!context) {\n        context = new this.constructor(event.currentTarget, this._getDelegateConfig());\n        $__default['default'](event.currentTarget).data(dataKey, context);\n      }\n\n      if (event) {\n        context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] = false;\n      }\n\n      if (context._isWithActiveTrigger()) {\n        return;\n      }\n\n      clearTimeout(context._timeout);\n      context._hoverState = HOVER_STATE_OUT;\n\n      if (!context.config.delay || !context.config.delay.hide) {\n        context.hide();\n        return;\n      }\n\n      context._timeout = setTimeout(function () {\n        if (context._hoverState === HOVER_STATE_OUT) {\n          context.hide();\n        }\n      }, context.config.delay.hide);\n    };\n\n    _proto._isWithActiveTrigger = function _isWithActiveTrigger() {\n      for (var trigger in this._activeTrigger) {\n        if (this._activeTrigger[trigger]) {\n          return true;\n        }\n      }\n\n      return false;\n    };\n\n    _proto._getConfig = function _getConfig(config) {\n      var dataAttributes = $__default['default'](this.element).data();\n      Object.keys(dataAttributes).forEach(function (dataAttr) {\n        if (DISALLOWED_ATTRIBUTES.indexOf(dataAttr) !== -1) {\n          delete dataAttributes[dataAttr];\n        }\n      });\n      config = _extends({}, this.constructor.Default, dataAttributes, typeof config === 'object' && config ? config : {});\n\n      if (typeof config.delay === 'number') {\n        config.delay = {\n          show: config.delay,\n          hide: config.delay\n        };\n      }\n\n      if (typeof config.title === 'number') {\n        config.title = config.title.toString();\n      }\n\n      if (typeof config.content === 'number') {\n        config.content = config.content.toString();\n      }\n\n      Util.typeCheckConfig(NAME$6, config, this.constructor.DefaultType);\n\n      if (config.sanitize) {\n        config.template = sanitizeHtml(config.template, config.whiteList, config.sanitizeFn);\n      }\n\n      return config;\n    };\n\n    _proto._getDelegateConfig = function _getDelegateConfig() {\n      var config = {};\n\n      if (this.config) {\n        for (var key in this.config) {\n          if (this.constructor.Default[key] !== this.config[key]) {\n            config[key] = this.config[key];\n          }\n        }\n      }\n\n      return config;\n    };\n\n    _proto._cleanTipClass = function _cleanTipClass() {\n      var $tip = $__default['default'](this.getTipElement());\n      var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX);\n\n      if (tabClass !== null && tabClass.length) {\n        $tip.removeClass(tabClass.join(''));\n      }\n    };\n\n    _proto._handlePopperPlacementChange = function _handlePopperPlacementChange(popperData) {\n      this.tip = popperData.instance.popper;\n\n      this._cleanTipClass();\n\n      this.addAttachmentClass(this._getAttachment(popperData.placement));\n    };\n\n    _proto._fixTransition = function _fixTransition() {\n      var tip = this.getTipElement();\n      var initConfigAnimation = this.config.animation;\n\n      if (tip.getAttribute('x-placement') !== null) {\n        return;\n      }\n\n      $__default['default'](tip).removeClass(CLASS_NAME_FADE$2);\n      this.config.animation = false;\n      this.hide();\n      this.show();\n      this.config.animation = initConfigAnimation;\n    } // Static\n    ;\n\n    Tooltip._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var $element = $__default['default'](this);\n        var data = $element.data(DATA_KEY$6);\n\n        var _config = typeof config === 'object' && config;\n\n        if (!data && /dispose|hide/.test(config)) {\n          return;\n        }\n\n        if (!data) {\n          data = new Tooltip(this, _config);\n          $element.data(DATA_KEY$6, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    _createClass(Tooltip, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION$6;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default$4;\n      }\n    }, {\n      key: \"NAME\",\n      get: function get() {\n        return NAME$6;\n      }\n    }, {\n      key: \"DATA_KEY\",\n      get: function get() {\n        return DATA_KEY$6;\n      }\n    }, {\n      key: \"Event\",\n      get: function get() {\n        return Event;\n      }\n    }, {\n      key: \"EVENT_KEY\",\n      get: function get() {\n        return EVENT_KEY$6;\n      }\n    }, {\n      key: \"DefaultType\",\n      get: function get() {\n        return DefaultType$4;\n      }\n    }]);\n\n    return Tooltip;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n\n  $__default['default'].fn[NAME$6] = Tooltip._jQueryInterface;\n  $__default['default'].fn[NAME$6].Constructor = Tooltip;\n\n  $__default['default'].fn[NAME$6].noConflict = function () {\n    $__default['default'].fn[NAME$6] = JQUERY_NO_CONFLICT$6;\n    return Tooltip._jQueryInterface;\n  };\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME$7 = 'popover';\n  var VERSION$7 = '4.5.3';\n  var DATA_KEY$7 = 'bs.popover';\n  var EVENT_KEY$7 = \".\" + DATA_KEY$7;\n  var JQUERY_NO_CONFLICT$7 = $__default['default'].fn[NAME$7];\n  var CLASS_PREFIX$1 = 'bs-popover';\n  var BSCLS_PREFIX_REGEX$1 = new RegExp(\"(^|\\\\s)\" + CLASS_PREFIX$1 + \"\\\\S+\", 'g');\n\n  var Default$5 = _extends({}, Tooltip.Default, {\n    placement: 'right',\n    trigger: 'click',\n    content: '',\n    template: '<div class=\"popover\" role=\"tooltip\">' + '<div class=\"arrow\"></div>' + '<h3 class=\"popover-header\"></h3>' + '<div class=\"popover-body\"></div></div>'\n  });\n\n  var DefaultType$5 = _extends({}, Tooltip.DefaultType, {\n    content: '(string|element|function)'\n  });\n\n  var CLASS_NAME_FADE$3 = 'fade';\n  var CLASS_NAME_SHOW$5 = 'show';\n  var SELECTOR_TITLE = '.popover-header';\n  var SELECTOR_CONTENT = '.popover-body';\n  var Event$1 = {\n    HIDE: \"hide\" + EVENT_KEY$7,\n    HIDDEN: \"hidden\" + EVENT_KEY$7,\n    SHOW: \"show\" + EVENT_KEY$7,\n    SHOWN: \"shown\" + EVENT_KEY$7,\n    INSERTED: \"inserted\" + EVENT_KEY$7,\n    CLICK: \"click\" + EVENT_KEY$7,\n    FOCUSIN: \"focusin\" + EVENT_KEY$7,\n    FOCUSOUT: \"focusout\" + EVENT_KEY$7,\n    MOUSEENTER: \"mouseenter\" + EVENT_KEY$7,\n    MOUSELEAVE: \"mouseleave\" + EVENT_KEY$7\n  };\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  var Popover = /*#__PURE__*/function (_Tooltip) {\n    _inheritsLoose(Popover, _Tooltip);\n\n    function Popover() {\n      return _Tooltip.apply(this, arguments) || this;\n    }\n\n    var _proto = Popover.prototype;\n\n    // Overrides\n    _proto.isWithContent = function isWithContent() {\n      return this.getTitle() || this._getContent();\n    };\n\n    _proto.addAttachmentClass = function addAttachmentClass(attachment) {\n      $__default['default'](this.getTipElement()).addClass(CLASS_PREFIX$1 + \"-\" + attachment);\n    };\n\n    _proto.getTipElement = function getTipElement() {\n      this.tip = this.tip || $__default['default'](this.config.template)[0];\n      return this.tip;\n    };\n\n    _proto.setContent = function setContent() {\n      var $tip = $__default['default'](this.getTipElement()); // We use append for html objects to maintain js events\n\n      this.setElementContent($tip.find(SELECTOR_TITLE), this.getTitle());\n\n      var content = this._getContent();\n\n      if (typeof content === 'function') {\n        content = content.call(this.element);\n      }\n\n      this.setElementContent($tip.find(SELECTOR_CONTENT), content);\n      $tip.removeClass(CLASS_NAME_FADE$3 + \" \" + CLASS_NAME_SHOW$5);\n    } // Private\n    ;\n\n    _proto._getContent = function _getContent() {\n      return this.element.getAttribute('data-content') || this.config.content;\n    };\n\n    _proto._cleanTipClass = function _cleanTipClass() {\n      var $tip = $__default['default'](this.getTipElement());\n      var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX$1);\n\n      if (tabClass !== null && tabClass.length > 0) {\n        $tip.removeClass(tabClass.join(''));\n      }\n    } // Static\n    ;\n\n    Popover._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var data = $__default['default'](this).data(DATA_KEY$7);\n\n        var _config = typeof config === 'object' ? config : null;\n\n        if (!data && /dispose|hide/.test(config)) {\n          return;\n        }\n\n        if (!data) {\n          data = new Popover(this, _config);\n          $__default['default'](this).data(DATA_KEY$7, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    _createClass(Popover, null, [{\n      key: \"VERSION\",\n      // Getters\n      get: function get() {\n        return VERSION$7;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default$5;\n      }\n    }, {\n      key: \"NAME\",\n      get: function get() {\n        return NAME$7;\n      }\n    }, {\n      key: \"DATA_KEY\",\n      get: function get() {\n        return DATA_KEY$7;\n      }\n    }, {\n      key: \"Event\",\n      get: function get() {\n        return Event$1;\n      }\n    }, {\n      key: \"EVENT_KEY\",\n      get: function get() {\n        return EVENT_KEY$7;\n      }\n    }, {\n      key: \"DefaultType\",\n      get: function get() {\n        return DefaultType$5;\n      }\n    }]);\n\n    return Popover;\n  }(Tooltip);\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n\n  $__default['default'].fn[NAME$7] = Popover._jQueryInterface;\n  $__default['default'].fn[NAME$7].Constructor = Popover;\n\n  $__default['default'].fn[NAME$7].noConflict = function () {\n    $__default['default'].fn[NAME$7] = JQUERY_NO_CONFLICT$7;\n    return Popover._jQueryInterface;\n  };\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME$8 = 'scrollspy';\n  var VERSION$8 = '4.5.3';\n  var DATA_KEY$8 = 'bs.scrollspy';\n  var EVENT_KEY$8 = \".\" + DATA_KEY$8;\n  var DATA_API_KEY$6 = '.data-api';\n  var JQUERY_NO_CONFLICT$8 = $__default['default'].fn[NAME$8];\n  var Default$6 = {\n    offset: 10,\n    method: 'auto',\n    target: ''\n  };\n  var DefaultType$6 = {\n    offset: 'number',\n    method: 'string',\n    target: '(string|element)'\n  };\n  var EVENT_ACTIVATE = \"activate\" + EVENT_KEY$8;\n  var EVENT_SCROLL = \"scroll\" + EVENT_KEY$8;\n  var EVENT_LOAD_DATA_API$2 = \"load\" + EVENT_KEY$8 + DATA_API_KEY$6;\n  var CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item';\n  var CLASS_NAME_ACTIVE$2 = 'active';\n  var SELECTOR_DATA_SPY = '[data-spy=\"scroll\"]';\n  var SELECTOR_NAV_LIST_GROUP = '.nav, .list-group';\n  var SELECTOR_NAV_LINKS = '.nav-link';\n  var SELECTOR_NAV_ITEMS = '.nav-item';\n  var SELECTOR_LIST_ITEMS = '.list-group-item';\n  var SELECTOR_DROPDOWN = '.dropdown';\n  var SELECTOR_DROPDOWN_ITEMS = '.dropdown-item';\n  var SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle';\n  var METHOD_OFFSET = 'offset';\n  var METHOD_POSITION = 'position';\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  var ScrollSpy = /*#__PURE__*/function () {\n    function ScrollSpy(element, config) {\n      var _this = this;\n\n      this._element = element;\n      this._scrollElement = element.tagName === 'BODY' ? window : element;\n      this._config = this._getConfig(config);\n      this._selector = this._config.target + \" \" + SELECTOR_NAV_LINKS + \",\" + (this._config.target + \" \" + SELECTOR_LIST_ITEMS + \",\") + (this._config.target + \" \" + SELECTOR_DROPDOWN_ITEMS);\n      this._offsets = [];\n      this._targets = [];\n      this._activeTarget = null;\n      this._scrollHeight = 0;\n      $__default['default'](this._scrollElement).on(EVENT_SCROLL, function (event) {\n        return _this._process(event);\n      });\n      this.refresh();\n\n      this._process();\n    } // Getters\n\n\n    var _proto = ScrollSpy.prototype;\n\n    // Public\n    _proto.refresh = function refresh() {\n      var _this2 = this;\n\n      var autoMethod = this._scrollElement === this._scrollElement.window ? METHOD_OFFSET : METHOD_POSITION;\n      var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method;\n      var offsetBase = offsetMethod === METHOD_POSITION ? this._getScrollTop() : 0;\n      this._offsets = [];\n      this._targets = [];\n      this._scrollHeight = this._getScrollHeight();\n      var targets = [].slice.call(document.querySelectorAll(this._selector));\n      targets.map(function (element) {\n        var target;\n        var targetSelector = Util.getSelectorFromElement(element);\n\n        if (targetSelector) {\n          target = document.querySelector(targetSelector);\n        }\n\n        if (target) {\n          var targetBCR = target.getBoundingClientRect();\n\n          if (targetBCR.width || targetBCR.height) {\n            // TODO (fat): remove sketch reliance on jQuery position/offset\n            return [$__default['default'](target)[offsetMethod]().top + offsetBase, targetSelector];\n          }\n        }\n\n        return null;\n      }).filter(function (item) {\n        return item;\n      }).sort(function (a, b) {\n        return a[0] - b[0];\n      }).forEach(function (item) {\n        _this2._offsets.push(item[0]);\n\n        _this2._targets.push(item[1]);\n      });\n    };\n\n    _proto.dispose = function dispose() {\n      $__default['default'].removeData(this._element, DATA_KEY$8);\n      $__default['default'](this._scrollElement).off(EVENT_KEY$8);\n      this._element = null;\n      this._scrollElement = null;\n      this._config = null;\n      this._selector = null;\n      this._offsets = null;\n      this._targets = null;\n      this._activeTarget = null;\n      this._scrollHeight = null;\n    } // Private\n    ;\n\n    _proto._getConfig = function _getConfig(config) {\n      config = _extends({}, Default$6, typeof config === 'object' && config ? config : {});\n\n      if (typeof config.target !== 'string' && Util.isElement(config.target)) {\n        var id = $__default['default'](config.target).attr('id');\n\n        if (!id) {\n          id = Util.getUID(NAME$8);\n          $__default['default'](config.target).attr('id', id);\n        }\n\n        config.target = \"#\" + id;\n      }\n\n      Util.typeCheckConfig(NAME$8, config, DefaultType$6);\n      return config;\n    };\n\n    _proto._getScrollTop = function _getScrollTop() {\n      return this._scrollElement === window ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop;\n    };\n\n    _proto._getScrollHeight = function _getScrollHeight() {\n      return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);\n    };\n\n    _proto._getOffsetHeight = function _getOffsetHeight() {\n      return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height;\n    };\n\n    _proto._process = function _process() {\n      var scrollTop = this._getScrollTop() + this._config.offset;\n\n      var scrollHeight = this._getScrollHeight();\n\n      var maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight();\n\n      if (this._scrollHeight !== scrollHeight) {\n        this.refresh();\n      }\n\n      if (scrollTop >= maxScroll) {\n        var target = this._targets[this._targets.length - 1];\n\n        if (this._activeTarget !== target) {\n          this._activate(target);\n        }\n\n        return;\n      }\n\n      if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) {\n        this._activeTarget = null;\n\n        this._clear();\n\n        return;\n      }\n\n      for (var i = this._offsets.length; i--;) {\n        var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]);\n\n        if (isActiveTarget) {\n          this._activate(this._targets[i]);\n        }\n      }\n    };\n\n    _proto._activate = function _activate(target) {\n      this._activeTarget = target;\n\n      this._clear();\n\n      var queries = this._selector.split(',').map(function (selector) {\n        return selector + \"[data-target=\\\"\" + target + \"\\\"],\" + selector + \"[href=\\\"\" + target + \"\\\"]\";\n      });\n\n      var $link = $__default['default']([].slice.call(document.querySelectorAll(queries.join(','))));\n\n      if ($link.hasClass(CLASS_NAME_DROPDOWN_ITEM)) {\n        $link.closest(SELECTOR_DROPDOWN).find(SELECTOR_DROPDOWN_TOGGLE).addClass(CLASS_NAME_ACTIVE$2);\n        $link.addClass(CLASS_NAME_ACTIVE$2);\n      } else {\n        // Set triggered link as active\n        $link.addClass(CLASS_NAME_ACTIVE$2); // Set triggered links parents as active\n        // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor\n\n        $link.parents(SELECTOR_NAV_LIST_GROUP).prev(SELECTOR_NAV_LINKS + \", \" + SELECTOR_LIST_ITEMS).addClass(CLASS_NAME_ACTIVE$2); // Handle special case when .nav-link is inside .nav-item\n\n        $link.parents(SELECTOR_NAV_LIST_GROUP).prev(SELECTOR_NAV_ITEMS).children(SELECTOR_NAV_LINKS).addClass(CLASS_NAME_ACTIVE$2);\n      }\n\n      $__default['default'](this._scrollElement).trigger(EVENT_ACTIVATE, {\n        relatedTarget: target\n      });\n    };\n\n    _proto._clear = function _clear() {\n      [].slice.call(document.querySelectorAll(this._selector)).filter(function (node) {\n        return node.classList.contains(CLASS_NAME_ACTIVE$2);\n      }).forEach(function (node) {\n        return node.classList.remove(CLASS_NAME_ACTIVE$2);\n      });\n    } // Static\n    ;\n\n    ScrollSpy._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var data = $__default['default'](this).data(DATA_KEY$8);\n\n        var _config = typeof config === 'object' && config;\n\n        if (!data) {\n          data = new ScrollSpy(this, _config);\n          $__default['default'](this).data(DATA_KEY$8, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    _createClass(ScrollSpy, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION$8;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default$6;\n      }\n    }]);\n\n    return ScrollSpy;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $__default['default'](window).on(EVENT_LOAD_DATA_API$2, function () {\n    var scrollSpys = [].slice.call(document.querySelectorAll(SELECTOR_DATA_SPY));\n    var scrollSpysLength = scrollSpys.length;\n\n    for (var i = scrollSpysLength; i--;) {\n      var $spy = $__default['default'](scrollSpys[i]);\n\n      ScrollSpy._jQueryInterface.call($spy, $spy.data());\n    }\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $__default['default'].fn[NAME$8] = ScrollSpy._jQueryInterface;\n  $__default['default'].fn[NAME$8].Constructor = ScrollSpy;\n\n  $__default['default'].fn[NAME$8].noConflict = function () {\n    $__default['default'].fn[NAME$8] = JQUERY_NO_CONFLICT$8;\n    return ScrollSpy._jQueryInterface;\n  };\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME$9 = 'tab';\n  var VERSION$9 = '4.5.3';\n  var DATA_KEY$9 = 'bs.tab';\n  var EVENT_KEY$9 = \".\" + DATA_KEY$9;\n  var DATA_API_KEY$7 = '.data-api';\n  var JQUERY_NO_CONFLICT$9 = $__default['default'].fn[NAME$9];\n  var EVENT_HIDE$3 = \"hide\" + EVENT_KEY$9;\n  var EVENT_HIDDEN$3 = \"hidden\" + EVENT_KEY$9;\n  var EVENT_SHOW$3 = \"show\" + EVENT_KEY$9;\n  var EVENT_SHOWN$3 = \"shown\" + EVENT_KEY$9;\n  var EVENT_CLICK_DATA_API$6 = \"click\" + EVENT_KEY$9 + DATA_API_KEY$7;\n  var CLASS_NAME_DROPDOWN_MENU = 'dropdown-menu';\n  var CLASS_NAME_ACTIVE$3 = 'active';\n  var CLASS_NAME_DISABLED$1 = 'disabled';\n  var CLASS_NAME_FADE$4 = 'fade';\n  var CLASS_NAME_SHOW$6 = 'show';\n  var SELECTOR_DROPDOWN$1 = '.dropdown';\n  var SELECTOR_NAV_LIST_GROUP$1 = '.nav, .list-group';\n  var SELECTOR_ACTIVE$2 = '.active';\n  var SELECTOR_ACTIVE_UL = '> li > .active';\n  var SELECTOR_DATA_TOGGLE$4 = '[data-toggle=\"tab\"], [data-toggle=\"pill\"], [data-toggle=\"list\"]';\n  var SELECTOR_DROPDOWN_TOGGLE$1 = '.dropdown-toggle';\n  var SELECTOR_DROPDOWN_ACTIVE_CHILD = '> .dropdown-menu .active';\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  var Tab = /*#__PURE__*/function () {\n    function Tab(element) {\n      this._element = element;\n    } // Getters\n\n\n    var _proto = Tab.prototype;\n\n    // Public\n    _proto.show = function show() {\n      var _this = this;\n\n      if (this._element.parentNode && this._element.parentNode.nodeType === Node.ELEMENT_NODE && $__default['default'](this._element).hasClass(CLASS_NAME_ACTIVE$3) || $__default['default'](this._element).hasClass(CLASS_NAME_DISABLED$1)) {\n        return;\n      }\n\n      var target;\n      var previous;\n      var listElement = $__default['default'](this._element).closest(SELECTOR_NAV_LIST_GROUP$1)[0];\n      var selector = Util.getSelectorFromElement(this._element);\n\n      if (listElement) {\n        var itemSelector = listElement.nodeName === 'UL' || listElement.nodeName === 'OL' ? SELECTOR_ACTIVE_UL : SELECTOR_ACTIVE$2;\n        previous = $__default['default'].makeArray($__default['default'](listElement).find(itemSelector));\n        previous = previous[previous.length - 1];\n      }\n\n      var hideEvent = $__default['default'].Event(EVENT_HIDE$3, {\n        relatedTarget: this._element\n      });\n      var showEvent = $__default['default'].Event(EVENT_SHOW$3, {\n        relatedTarget: previous\n      });\n\n      if (previous) {\n        $__default['default'](previous).trigger(hideEvent);\n      }\n\n      $__default['default'](this._element).trigger(showEvent);\n\n      if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      if (selector) {\n        target = document.querySelector(selector);\n      }\n\n      this._activate(this._element, listElement);\n\n      var complete = function complete() {\n        var hiddenEvent = $__default['default'].Event(EVENT_HIDDEN$3, {\n          relatedTarget: _this._element\n        });\n        var shownEvent = $__default['default'].Event(EVENT_SHOWN$3, {\n          relatedTarget: previous\n        });\n        $__default['default'](previous).trigger(hiddenEvent);\n        $__default['default'](_this._element).trigger(shownEvent);\n      };\n\n      if (target) {\n        this._activate(target, target.parentNode, complete);\n      } else {\n        complete();\n      }\n    };\n\n    _proto.dispose = function dispose() {\n      $__default['default'].removeData(this._element, DATA_KEY$9);\n      this._element = null;\n    } // Private\n    ;\n\n    _proto._activate = function _activate(element, container, callback) {\n      var _this2 = this;\n\n      var activeElements = container && (container.nodeName === 'UL' || container.nodeName === 'OL') ? $__default['default'](container).find(SELECTOR_ACTIVE_UL) : $__default['default'](container).children(SELECTOR_ACTIVE$2);\n      var active = activeElements[0];\n      var isTransitioning = callback && active && $__default['default'](active).hasClass(CLASS_NAME_FADE$4);\n\n      var complete = function complete() {\n        return _this2._transitionComplete(element, active, callback);\n      };\n\n      if (active && isTransitioning) {\n        var transitionDuration = Util.getTransitionDurationFromElement(active);\n        $__default['default'](active).removeClass(CLASS_NAME_SHOW$6).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);\n      } else {\n        complete();\n      }\n    };\n\n    _proto._transitionComplete = function _transitionComplete(element, active, callback) {\n      if (active) {\n        $__default['default'](active).removeClass(CLASS_NAME_ACTIVE$3);\n        var dropdownChild = $__default['default'](active.parentNode).find(SELECTOR_DROPDOWN_ACTIVE_CHILD)[0];\n\n        if (dropdownChild) {\n          $__default['default'](dropdownChild).removeClass(CLASS_NAME_ACTIVE$3);\n        }\n\n        if (active.getAttribute('role') === 'tab') {\n          active.setAttribute('aria-selected', false);\n        }\n      }\n\n      $__default['default'](element).addClass(CLASS_NAME_ACTIVE$3);\n\n      if (element.getAttribute('role') === 'tab') {\n        element.setAttribute('aria-selected', true);\n      }\n\n      Util.reflow(element);\n\n      if (element.classList.contains(CLASS_NAME_FADE$4)) {\n        element.classList.add(CLASS_NAME_SHOW$6);\n      }\n\n      if (element.parentNode && $__default['default'](element.parentNode).hasClass(CLASS_NAME_DROPDOWN_MENU)) {\n        var dropdownElement = $__default['default'](element).closest(SELECTOR_DROPDOWN$1)[0];\n\n        if (dropdownElement) {\n          var dropdownToggleList = [].slice.call(dropdownElement.querySelectorAll(SELECTOR_DROPDOWN_TOGGLE$1));\n          $__default['default'](dropdownToggleList).addClass(CLASS_NAME_ACTIVE$3);\n        }\n\n        element.setAttribute('aria-expanded', true);\n      }\n\n      if (callback) {\n        callback();\n      }\n    } // Static\n    ;\n\n    Tab._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var $this = $__default['default'](this);\n        var data = $this.data(DATA_KEY$9);\n\n        if (!data) {\n          data = new Tab(this);\n          $this.data(DATA_KEY$9, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    _createClass(Tab, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION$9;\n      }\n    }]);\n\n    return Tab;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $__default['default'](document).on(EVENT_CLICK_DATA_API$6, SELECTOR_DATA_TOGGLE$4, function (event) {\n    event.preventDefault();\n\n    Tab._jQueryInterface.call($__default['default'](this), 'show');\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $__default['default'].fn[NAME$9] = Tab._jQueryInterface;\n  $__default['default'].fn[NAME$9].Constructor = Tab;\n\n  $__default['default'].fn[NAME$9].noConflict = function () {\n    $__default['default'].fn[NAME$9] = JQUERY_NO_CONFLICT$9;\n    return Tab._jQueryInterface;\n  };\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME$a = 'toast';\n  var VERSION$a = '4.5.3';\n  var DATA_KEY$a = 'bs.toast';\n  var EVENT_KEY$a = \".\" + DATA_KEY$a;\n  var JQUERY_NO_CONFLICT$a = $__default['default'].fn[NAME$a];\n  var EVENT_CLICK_DISMISS$1 = \"click.dismiss\" + EVENT_KEY$a;\n  var EVENT_HIDE$4 = \"hide\" + EVENT_KEY$a;\n  var EVENT_HIDDEN$4 = \"hidden\" + EVENT_KEY$a;\n  var EVENT_SHOW$4 = \"show\" + EVENT_KEY$a;\n  var EVENT_SHOWN$4 = \"shown\" + EVENT_KEY$a;\n  var CLASS_NAME_FADE$5 = 'fade';\n  var CLASS_NAME_HIDE = 'hide';\n  var CLASS_NAME_SHOW$7 = 'show';\n  var CLASS_NAME_SHOWING = 'showing';\n  var DefaultType$7 = {\n    animation: 'boolean',\n    autohide: 'boolean',\n    delay: 'number'\n  };\n  var Default$7 = {\n    animation: true,\n    autohide: true,\n    delay: 500\n  };\n  var SELECTOR_DATA_DISMISS$1 = '[data-dismiss=\"toast\"]';\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  var Toast = /*#__PURE__*/function () {\n    function Toast(element, config) {\n      this._element = element;\n      this._config = this._getConfig(config);\n      this._timeout = null;\n\n      this._setListeners();\n    } // Getters\n\n\n    var _proto = Toast.prototype;\n\n    // Public\n    _proto.show = function show() {\n      var _this = this;\n\n      var showEvent = $__default['default'].Event(EVENT_SHOW$4);\n      $__default['default'](this._element).trigger(showEvent);\n\n      if (showEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      this._clearTimeout();\n\n      if (this._config.animation) {\n        this._element.classList.add(CLASS_NAME_FADE$5);\n      }\n\n      var complete = function complete() {\n        _this._element.classList.remove(CLASS_NAME_SHOWING);\n\n        _this._element.classList.add(CLASS_NAME_SHOW$7);\n\n        $__default['default'](_this._element).trigger(EVENT_SHOWN$4);\n\n        if (_this._config.autohide) {\n          _this._timeout = setTimeout(function () {\n            _this.hide();\n          }, _this._config.delay);\n        }\n      };\n\n      this._element.classList.remove(CLASS_NAME_HIDE);\n\n      Util.reflow(this._element);\n\n      this._element.classList.add(CLASS_NAME_SHOWING);\n\n      if (this._config.animation) {\n        var transitionDuration = Util.getTransitionDurationFromElement(this._element);\n        $__default['default'](this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);\n      } else {\n        complete();\n      }\n    };\n\n    _proto.hide = function hide() {\n      if (!this._element.classList.contains(CLASS_NAME_SHOW$7)) {\n        return;\n      }\n\n      var hideEvent = $__default['default'].Event(EVENT_HIDE$4);\n      $__default['default'](this._element).trigger(hideEvent);\n\n      if (hideEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      this._close();\n    };\n\n    _proto.dispose = function dispose() {\n      this._clearTimeout();\n\n      if (this._element.classList.contains(CLASS_NAME_SHOW$7)) {\n        this._element.classList.remove(CLASS_NAME_SHOW$7);\n      }\n\n      $__default['default'](this._element).off(EVENT_CLICK_DISMISS$1);\n      $__default['default'].removeData(this._element, DATA_KEY$a);\n      this._element = null;\n      this._config = null;\n    } // Private\n    ;\n\n    _proto._getConfig = function _getConfig(config) {\n      config = _extends({}, Default$7, $__default['default'](this._element).data(), typeof config === 'object' && config ? config : {});\n      Util.typeCheckConfig(NAME$a, config, this.constructor.DefaultType);\n      return config;\n    };\n\n    _proto._setListeners = function _setListeners() {\n      var _this2 = this;\n\n      $__default['default'](this._element).on(EVENT_CLICK_DISMISS$1, SELECTOR_DATA_DISMISS$1, function () {\n        return _this2.hide();\n      });\n    };\n\n    _proto._close = function _close() {\n      var _this3 = this;\n\n      var complete = function complete() {\n        _this3._element.classList.add(CLASS_NAME_HIDE);\n\n        $__default['default'](_this3._element).trigger(EVENT_HIDDEN$4);\n      };\n\n      this._element.classList.remove(CLASS_NAME_SHOW$7);\n\n      if (this._config.animation) {\n        var transitionDuration = Util.getTransitionDurationFromElement(this._element);\n        $__default['default'](this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);\n      } else {\n        complete();\n      }\n    };\n\n    _proto._clearTimeout = function _clearTimeout() {\n      clearTimeout(this._timeout);\n      this._timeout = null;\n    } // Static\n    ;\n\n    Toast._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var $element = $__default['default'](this);\n        var data = $element.data(DATA_KEY$a);\n\n        var _config = typeof config === 'object' && config;\n\n        if (!data) {\n          data = new Toast(this, _config);\n          $element.data(DATA_KEY$a, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config](this);\n        }\n      });\n    };\n\n    _createClass(Toast, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION$a;\n      }\n    }, {\n      key: \"DefaultType\",\n      get: function get() {\n        return DefaultType$7;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default$7;\n      }\n    }]);\n\n    return Toast;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n\n  $__default['default'].fn[NAME$a] = Toast._jQueryInterface;\n  $__default['default'].fn[NAME$a].Constructor = Toast;\n\n  $__default['default'].fn[NAME$a].noConflict = function () {\n    $__default['default'].fn[NAME$a] = JQUERY_NO_CONFLICT$a;\n    return Toast._jQueryInterface;\n  };\n\n  exports.Alert = Alert;\n  exports.Button = Button;\n  exports.Carousel = Carousel;\n  exports.Collapse = Collapse;\n  exports.Dropdown = Dropdown;\n  exports.Modal = Modal;\n  exports.Popover = Popover;\n  exports.Scrollspy = ScrollSpy;\n  exports.Tab = Tab;\n  exports.Toast = Toast;\n  exports.Tooltip = Tooltip;\n  exports.Util = Util;\n\n  Object.defineProperty(exports, '__esModule', { value: true });\n\n})));\n//# sourceMappingURL=bootstrap.js.map\n"
  },
  {
    "path": "src/IdentityServer/wwwroot/lib/bootstrap4-glyphicons/LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\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"
  },
  {
    "path": "src/IdentityServer/wwwroot/lib/bootstrap4-glyphicons/css/bootstrap-glyphicons.css",
    "content": "/*!\n * Bootstrap v3.3.7 (http://getbootstrap.com)\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n@font-face {\n    font-family: 'Glyphicons Halflings';\n    src: url('../fonts/glyphicons/glyphicons-halflings-regular.eot');\n    src: url('../fonts/glyphicons/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');\n}\n.glyphicon {\n  position: relative;\n  top: 1px;\n  display: inline-block;\n  font-family: 'Glyphicons Halflings';\n  font-style: normal;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n.glyphicon-asterisk:before {\n  content: \"\\002a\";\n}\n.glyphicon-plus:before {\n  content: \"\\002b\";\n}\n.glyphicon-euro:before,\n.glyphicon-eur:before {\n  content: \"\\20ac\";\n}\n.glyphicon-minus:before {\n  content: \"\\2212\";\n}\n.glyphicon-cloud:before {\n  content: \"\\2601\";\n}\n.glyphicon-envelope:before {\n  content: \"\\2709\";\n}\n.glyphicon-pencil:before {\n  content: \"\\270f\";\n}\n.glyphicon-glass:before {\n  content: \"\\e001\";\n}\n.glyphicon-music:before {\n  content: \"\\e002\";\n}\n.glyphicon-search:before {\n  content: \"\\e003\";\n}\n.glyphicon-heart:before {\n  content: \"\\e005\";\n}\n.glyphicon-star:before {\n  content: \"\\e006\";\n}\n.glyphicon-star-empty:before {\n  content: \"\\e007\";\n}\n.glyphicon-user:before {\n  content: \"\\e008\";\n}\n.glyphicon-film:before {\n  content: \"\\e009\";\n}\n.glyphicon-th-large:before {\n  content: \"\\e010\";\n}\n.glyphicon-th:before {\n  content: \"\\e011\";\n}\n.glyphicon-th-list:before {\n  content: \"\\e012\";\n}\n.glyphicon-ok:before {\n  content: \"\\e013\";\n}\n.glyphicon-remove:before {\n  content: \"\\e014\";\n}\n.glyphicon-zoom-in:before {\n  content: \"\\e015\";\n}\n.glyphicon-zoom-out:before {\n  content: \"\\e016\";\n}\n.glyphicon-off:before {\n  content: \"\\e017\";\n}\n.glyphicon-signal:before {\n  content: \"\\e018\";\n}\n.glyphicon-cog:before {\n  content: \"\\e019\";\n}\n.glyphicon-trash:before {\n  content: \"\\e020\";\n}\n.glyphicon-home:before {\n  content: \"\\e021\";\n}\n.glyphicon-file:before {\n  content: \"\\e022\";\n}\n.glyphicon-time:before {\n  content: \"\\e023\";\n}\n.glyphicon-road:before {\n  content: \"\\e024\";\n}\n.glyphicon-download-alt:before {\n  content: \"\\e025\";\n}\n.glyphicon-download:before {\n  content: \"\\e026\";\n}\n.glyphicon-upload:before {\n  content: \"\\e027\";\n}\n.glyphicon-inbox:before {\n  content: \"\\e028\";\n}\n.glyphicon-play-circle:before {\n  content: \"\\e029\";\n}\n.glyphicon-repeat:before {\n  content: \"\\e030\";\n}\n.glyphicon-refresh:before {\n  content: \"\\e031\";\n}\n.glyphicon-list-alt:before {\n  content: \"\\e032\";\n}\n.glyphicon-lock:before {\n  content: \"\\e033\";\n}\n.glyphicon-flag:before {\n  content: \"\\e034\";\n}\n.glyphicon-headphones:before {\n  content: \"\\e035\";\n}\n.glyphicon-volume-off:before {\n  content: \"\\e036\";\n}\n.glyphicon-volume-down:before {\n  content: \"\\e037\";\n}\n.glyphicon-volume-up:before {\n  content: \"\\e038\";\n}\n.glyphicon-qrcode:before {\n  content: \"\\e039\";\n}\n.glyphicon-barcode:before {\n  content: \"\\e040\";\n}\n.glyphicon-tag:before {\n  content: \"\\e041\";\n}\n.glyphicon-tags:before {\n  content: \"\\e042\";\n}\n.glyphicon-book:before {\n  content: \"\\e043\";\n}\n.glyphicon-bookmark:before {\n  content: \"\\e044\";\n}\n.glyphicon-print:before {\n  content: \"\\e045\";\n}\n.glyphicon-camera:before {\n  content: \"\\e046\";\n}\n.glyphicon-font:before {\n  content: \"\\e047\";\n}\n.glyphicon-bold:before {\n  content: \"\\e048\";\n}\n.glyphicon-italic:before {\n  content: \"\\e049\";\n}\n.glyphicon-text-height:before {\n  content: \"\\e050\";\n}\n.glyphicon-text-width:before {\n  content: \"\\e051\";\n}\n.glyphicon-align-left:before {\n  content: \"\\e052\";\n}\n.glyphicon-align-center:before {\n  content: \"\\e053\";\n}\n.glyphicon-align-right:before {\n  content: \"\\e054\";\n}\n.glyphicon-align-justify:before {\n  content: \"\\e055\";\n}\n.glyphicon-list:before {\n  content: \"\\e056\";\n}\n.glyphicon-indent-left:before {\n  content: \"\\e057\";\n}\n.glyphicon-indent-right:before {\n  content: \"\\e058\";\n}\n.glyphicon-facetime-video:before {\n  content: \"\\e059\";\n}\n.glyphicon-picture:before {\n  content: \"\\e060\";\n}\n.glyphicon-map-marker:before {\n  content: \"\\e062\";\n}\n.glyphicon-adjust:before {\n  content: \"\\e063\";\n}\n.glyphicon-tint:before {\n  content: \"\\e064\";\n}\n.glyphicon-edit:before {\n  content: \"\\e065\";\n}\n.glyphicon-share:before {\n  content: \"\\e066\";\n}\n.glyphicon-check:before {\n  content: \"\\e067\";\n}\n.glyphicon-move:before {\n  content: \"\\e068\";\n}\n.glyphicon-step-backward:before {\n  content: \"\\e069\";\n}\n.glyphicon-fast-backward:before {\n  content: \"\\e070\";\n}\n.glyphicon-backward:before {\n  content: \"\\e071\";\n}\n.glyphicon-play:before {\n  content: \"\\e072\";\n}\n.glyphicon-pause:before {\n  content: \"\\e073\";\n}\n.glyphicon-stop:before {\n  content: \"\\e074\";\n}\n.glyphicon-forward:before {\n  content: \"\\e075\";\n}\n.glyphicon-fast-forward:before {\n  content: \"\\e076\";\n}\n.glyphicon-step-forward:before {\n  content: \"\\e077\";\n}\n.glyphicon-eject:before {\n  content: \"\\e078\";\n}\n.glyphicon-chevron-left:before {\n  content: \"\\e079\";\n}\n.glyphicon-chevron-right:before {\n  content: \"\\e080\";\n}\n.glyphicon-plus-sign:before {\n  content: \"\\e081\";\n}\n.glyphicon-minus-sign:before {\n  content: \"\\e082\";\n}\n.glyphicon-remove-sign:before {\n  content: \"\\e083\";\n}\n.glyphicon-ok-sign:before {\n  content: \"\\e084\";\n}\n.glyphicon-question-sign:before {\n  content: \"\\e085\";\n}\n.glyphicon-info-sign:before {\n  content: \"\\e086\";\n}\n.glyphicon-screenshot:before {\n  content: \"\\e087\";\n}\n.glyphicon-remove-circle:before {\n  content: \"\\e088\";\n}\n.glyphicon-ok-circle:before {\n  content: \"\\e089\";\n}\n.glyphicon-ban-circle:before {\n  content: \"\\e090\";\n}\n.glyphicon-arrow-left:before {\n  content: \"\\e091\";\n}\n.glyphicon-arrow-right:before {\n  content: \"\\e092\";\n}\n.glyphicon-arrow-up:before {\n  content: \"\\e093\";\n}\n.glyphicon-arrow-down:before {\n  content: \"\\e094\";\n}\n.glyphicon-share-alt:before {\n  content: \"\\e095\";\n}\n.glyphicon-resize-full:before {\n  content: \"\\e096\";\n}\n.glyphicon-resize-small:before {\n  content: \"\\e097\";\n}\n.glyphicon-exclamation-sign:before {\n  content: \"\\e101\";\n}\n.glyphicon-gift:before {\n  content: \"\\e102\";\n}\n.glyphicon-leaf:before {\n  content: \"\\e103\";\n}\n.glyphicon-fire:before {\n  content: \"\\e104\";\n}\n.glyphicon-eye-open:before {\n  content: \"\\e105\";\n}\n.glyphicon-eye-close:before {\n  content: \"\\e106\";\n}\n.glyphicon-warning-sign:before {\n  content: \"\\e107\";\n}\n.glyphicon-plane:before {\n  content: \"\\e108\";\n}\n.glyphicon-calendar:before {\n  content: \"\\e109\";\n}\n.glyphicon-random:before {\n  content: \"\\e110\";\n}\n.glyphicon-comment:before {\n  content: \"\\e111\";\n}\n.glyphicon-magnet:before {\n  content: \"\\e112\";\n}\n.glyphicon-chevron-up:before {\n  content: \"\\e113\";\n}\n.glyphicon-chevron-down:before {\n  content: \"\\e114\";\n}\n.glyphicon-retweet:before {\n  content: \"\\e115\";\n}\n.glyphicon-shopping-cart:before {\n  content: \"\\e116\";\n}\n.glyphicon-folder-close:before {\n  content: \"\\e117\";\n}\n.glyphicon-folder-open:before {\n  content: \"\\e118\";\n}\n.glyphicon-resize-vertical:before {\n  content: \"\\e119\";\n}\n.glyphicon-resize-horizontal:before {\n  content: \"\\e120\";\n}\n.glyphicon-hdd:before {\n  content: \"\\e121\";\n}\n.glyphicon-bullhorn:before {\n  content: \"\\e122\";\n}\n.glyphicon-bell:before {\n  content: \"\\e123\";\n}\n.glyphicon-certificate:before {\n  content: \"\\e124\";\n}\n.glyphicon-thumbs-up:before {\n  content: \"\\e125\";\n}\n.glyphicon-thumbs-down:before {\n  content: \"\\e126\";\n}\n.glyphicon-hand-right:before {\n  content: \"\\e127\";\n}\n.glyphicon-hand-left:before {\n  content: \"\\e128\";\n}\n.glyphicon-hand-up:before {\n  content: \"\\e129\";\n}\n.glyphicon-hand-down:before {\n  content: \"\\e130\";\n}\n.glyphicon-circle-arrow-right:before {\n  content: \"\\e131\";\n}\n.glyphicon-circle-arrow-left:before {\n  content: \"\\e132\";\n}\n.glyphicon-circle-arrow-up:before {\n  content: \"\\e133\";\n}\n.glyphicon-circle-arrow-down:before {\n  content: \"\\e134\";\n}\n.glyphicon-globe:before {\n  content: \"\\e135\";\n}\n.glyphicon-wrench:before {\n  content: \"\\e136\";\n}\n.glyphicon-tasks:before {\n  content: \"\\e137\";\n}\n.glyphicon-filter:before {\n  content: \"\\e138\";\n}\n.glyphicon-briefcase:before {\n  content: \"\\e139\";\n}\n.glyphicon-fullscreen:before {\n  content: \"\\e140\";\n}\n.glyphicon-dashboard:before {\n  content: \"\\e141\";\n}\n.glyphicon-paperclip:before {\n  content: \"\\e142\";\n}\n.glyphicon-heart-empty:before {\n  content: \"\\e143\";\n}\n.glyphicon-link:before {\n  content: \"\\e144\";\n}\n.glyphicon-phone:before {\n  content: \"\\e145\";\n}\n.glyphicon-pushpin:before {\n  content: \"\\e146\";\n}\n.glyphicon-usd:before {\n  content: \"\\e148\";\n}\n.glyphicon-gbp:before {\n  content: \"\\e149\";\n}\n.glyphicon-sort:before {\n  content: \"\\e150\";\n}\n.glyphicon-sort-by-alphabet:before {\n  content: \"\\e151\";\n}\n.glyphicon-sort-by-alphabet-alt:before {\n  content: \"\\e152\";\n}\n.glyphicon-sort-by-order:before {\n  content: \"\\e153\";\n}\n.glyphicon-sort-by-order-alt:before {\n  content: \"\\e154\";\n}\n.glyphicon-sort-by-attributes:before {\n  content: \"\\e155\";\n}\n.glyphicon-sort-by-attributes-alt:before {\n  content: \"\\e156\";\n}\n.glyphicon-unchecked:before {\n  content: \"\\e157\";\n}\n.glyphicon-expand:before {\n  content: \"\\e158\";\n}\n.glyphicon-collapse-down:before {\n  content: \"\\e159\";\n}\n.glyphicon-collapse-up:before {\n  content: \"\\e160\";\n}\n.glyphicon-log-in:before {\n  content: \"\\e161\";\n}\n.glyphicon-flash:before {\n  content: \"\\e162\";\n}\n.glyphicon-log-out:before {\n  content: \"\\e163\";\n}\n.glyphicon-new-window:before {\n  content: \"\\e164\";\n}\n.glyphicon-record:before {\n  content: \"\\e165\";\n}\n.glyphicon-save:before {\n  content: \"\\e166\";\n}\n.glyphicon-open:before {\n  content: \"\\e167\";\n}\n.glyphicon-saved:before {\n  content: \"\\e168\";\n}\n.glyphicon-import:before {\n  content: \"\\e169\";\n}\n.glyphicon-export:before {\n  content: \"\\e170\";\n}\n.glyphicon-send:before {\n  content: \"\\e171\";\n}\n.glyphicon-floppy-disk:before {\n  content: \"\\e172\";\n}\n.glyphicon-floppy-saved:before {\n  content: \"\\e173\";\n}\n.glyphicon-floppy-remove:before {\n  content: \"\\e174\";\n}\n.glyphicon-floppy-save:before {\n  content: \"\\e175\";\n}\n.glyphicon-floppy-open:before {\n  content: \"\\e176\";\n}\n.glyphicon-credit-card:before {\n  content: \"\\e177\";\n}\n.glyphicon-transfer:before {\n  content: \"\\e178\";\n}\n.glyphicon-cutlery:before {\n  content: \"\\e179\";\n}\n.glyphicon-header:before {\n  content: \"\\e180\";\n}\n.glyphicon-compressed:before {\n  content: \"\\e181\";\n}\n.glyphicon-earphone:before {\n  content: \"\\e182\";\n}\n.glyphicon-phone-alt:before {\n  content: \"\\e183\";\n}\n.glyphicon-tower:before {\n  content: \"\\e184\";\n}\n.glyphicon-stats:before {\n  content: \"\\e185\";\n}\n.glyphicon-sd-video:before {\n  content: \"\\e186\";\n}\n.glyphicon-hd-video:before {\n  content: \"\\e187\";\n}\n.glyphicon-subtitles:before {\n  content: \"\\e188\";\n}\n.glyphicon-sound-stereo:before {\n  content: \"\\e189\";\n}\n.glyphicon-sound-dolby:before {\n  content: \"\\e190\";\n}\n.glyphicon-sound-5-1:before {\n  content: \"\\e191\";\n}\n.glyphicon-sound-6-1:before {\n  content: \"\\e192\";\n}\n.glyphicon-sound-7-1:before {\n  content: \"\\e193\";\n}\n.glyphicon-copyright-mark:before {\n  content: \"\\e194\";\n}\n.glyphicon-registration-mark:before {\n  content: \"\\e195\";\n}\n.glyphicon-cloud-download:before {\n  content: \"\\e197\";\n}\n.glyphicon-cloud-upload:before {\n  content: \"\\e198\";\n}\n.glyphicon-tree-conifer:before {\n  content: \"\\e199\";\n}\n.glyphicon-tree-deciduous:before {\n  content: \"\\e200\";\n}\n.glyphicon-cd:before {\n  content: \"\\e201\";\n}\n.glyphicon-save-file:before {\n  content: \"\\e202\";\n}\n.glyphicon-open-file:before {\n  content: \"\\e203\";\n}\n.glyphicon-level-up:before {\n  content: \"\\e204\";\n}\n.glyphicon-copy:before {\n  content: \"\\e205\";\n}\n.glyphicon-paste:before {\n  content: \"\\e206\";\n}\n.glyphicon-alert:before {\n  content: \"\\e209\";\n}\n.glyphicon-equalizer:before {\n  content: \"\\e210\";\n}\n.glyphicon-king:before {\n  content: \"\\e211\";\n}\n.glyphicon-queen:before {\n  content: \"\\e212\";\n}\n.glyphicon-pawn:before {\n  content: \"\\e213\";\n}\n.glyphicon-bishop:before {\n  content: \"\\e214\";\n}\n.glyphicon-knight:before {\n  content: \"\\e215\";\n}\n.glyphicon-baby-formula:before {\n  content: \"\\e216\";\n}\n.glyphicon-tent:before {\n  content: \"\\26fa\";\n}\n.glyphicon-blackboard:before {\n  content: \"\\e218\";\n}\n.glyphicon-bed:before {\n  content: \"\\e219\";\n}\n.glyphicon-apple:before {\n  content: \"\\f8ff\";\n}\n.glyphicon-erase:before {\n  content: \"\\e221\";\n}\n.glyphicon-hourglass:before {\n  content: \"\\231b\";\n}\n.glyphicon-lamp:before {\n  content: \"\\e223\";\n}\n.glyphicon-duplicate:before {\n  content: \"\\e224\";\n}\n.glyphicon-piggy-bank:before {\n  content: \"\\e225\";\n}\n.glyphicon-scissors:before {\n  content: \"\\e226\";\n}\n.glyphicon-bitcoin:before {\n  content: \"\\e227\";\n}\n.glyphicon-btc:before {\n  content: \"\\e227\";\n}\n.glyphicon-xbt:before {\n  content: \"\\e227\";\n}\n.glyphicon-yen:before {\n  content: \"\\00a5\";\n}\n.glyphicon-jpy:before {\n  content: \"\\00a5\";\n}\n.glyphicon-ruble:before {\n  content: \"\\20bd\";\n}\n.glyphicon-rub:before {\n  content: \"\\20bd\";\n}\n.glyphicon-scale:before {\n  content: \"\\e230\";\n}\n.glyphicon-ice-lolly:before {\n  content: \"\\e231\";\n}\n.glyphicon-ice-lolly-tasted:before {\n  content: \"\\e232\";\n}\n.glyphicon-education:before {\n  content: \"\\e233\";\n}\n.glyphicon-option-horizontal:before {\n  content: \"\\e234\";\n}\n.glyphicon-option-vertical:before {\n  content: \"\\e235\";\n}\n.glyphicon-menu-hamburger:before {\n  content: \"\\e236\";\n}\n.glyphicon-modal-window:before {\n  content: \"\\e237\";\n}\n.glyphicon-oil:before {\n  content: \"\\e238\";\n}\n.glyphicon-grain:before {\n  content: \"\\e239\";\n}\n.glyphicon-sunglasses:before {\n  content: \"\\e240\";\n}\n.glyphicon-text-size:before {\n  content: \"\\e241\";\n}\n.glyphicon-text-color:before {\n  content: \"\\e242\";\n}\n.glyphicon-text-background:before {\n  content: \"\\e243\";\n}\n.glyphicon-object-align-top:before {\n  content: \"\\e244\";\n}\n.glyphicon-object-align-bottom:before {\n  content: \"\\e245\";\n}\n.glyphicon-object-align-horizontal:before {\n  content: \"\\e246\";\n}\n.glyphicon-object-align-left:before {\n  content: \"\\e247\";\n}\n.glyphicon-object-align-vertical:before {\n  content: \"\\e248\";\n}\n.glyphicon-object-align-right:before {\n  content: \"\\e249\";\n}\n.glyphicon-triangle-right:before {\n  content: \"\\e250\";\n}\n.glyphicon-triangle-left:before {\n  content: \"\\e251\";\n}\n.glyphicon-triangle-bottom:before {\n  content: \"\\e252\";\n}\n.glyphicon-triangle-top:before {\n  content: \"\\e253\";\n}\n.glyphicon-console:before {\n  content: \"\\e254\";\n}\n.glyphicon-superscript:before {\n  content: \"\\e255\";\n}\n.glyphicon-subscript:before {\n  content: \"\\e256\";\n}\n.glyphicon-menu-left:before {\n  content: \"\\e257\";\n}\n.glyphicon-menu-right:before {\n  content: \"\\e258\";\n}\n.glyphicon-menu-down:before {\n  content: \"\\e259\";\n}\n.glyphicon-menu-up:before {\n  content: \"\\e260\";\n}\n"
  },
  {
    "path": "src/IdentityServer/wwwroot/lib/bootstrap4-glyphicons/maps/glyphicons-fontawesome.css",
    "content": "﻿@font-face {\n  font-family: 'Font Awesome 5 Free';\n  font-style: normal;\n  font-weight: 900;\n  src: url(\"../fonts/fontawesome/fa-solid-900.eot\");\n  src: url(\"../fonts/fontawesome/fa-solid-900.eot?#iefix\") format(\"embedded-opentype\"), url(\"../fonts/fontawesome/fa-solid-900.woff2\") format(\"woff2\"), url(\"../fonts/fontawesome/fa-solid-900.ttf\") format(\"truetype\"), url(\"../fonts/fontawesome/fa-solid-900.svg#fontawesome\") format(\"svg\");\n}\n.glyphicon {\n  font-family: 'Font Awesome 5 Free';\n}\n.glyphicon.glyphicon-chevron-up::before {\n  content: \"\\f077\";\n}\n.glyphicon.glyphicon-chevron-right::before {\n  content: \"\\f054\";\n}\n.glyphicon.glyphicon-chevron-left::before {\n  content: \"\\f053\";\n}\n.glyphicon.glyphicon-asterisk::before {\n  content: \"\\f069\";\n}\n.glyphicon.glyphicon-plus::before {\n  content: \"\\f067\";\n}\n.glyphicon.glyphicon-euro::before,\n.glyphicon.glyphicon-eur::before {\n  content: \"\\f153\";\n}\n.glyphicon.glyphicon-minus::before {\n  content: \"\\f068\";\n}\n.glyphicon.glyphicon-cloud::before {\n  content: \"\\f0c2\";\n}\n.glyphicon.glyphicon-envelope::before {\n  content: \"\\f0e0\";\n}\n.glyphicon.glyphicon-pencil::before {\n  content: \"\\f040\";\n}\n.glyphicon.glyphicon-glass::before {\n  content: \"\\f000\";\n}\n.glyphicon.glyphicon-music::before {\n  content: \"\\f001\";\n}\n.glyphicon.glyphicon-search::before {\n  content: \"\\f002\";\n}\n.glyphicon.glyphicon-heart::before {\n  content: \"\\f004\";\n}\n.glyphicon.glyphicon-star::before {\n  content: \"\\f005\";\n}\n.glyphicon.glyphicon-star-empty::before {\n  content: \"\\f006\";\n}\n.glyphicon.glyphicon-user::before {\n  content: \"\\f007\";\n}\n.glyphicon.glyphicon-film::before {\n  content: \"\\f008\";\n}\n.glyphicon.glyphicon-th-large::before {\n  content: \"\\f009\";\n}\n.glyphicon.glyphicon-th::before {\n  content: \"\\f00a\";\n}\n.glyphicon.glyphicon-th-list::before {\n  content: \"\\f00b\";\n}\n.glyphicon.glyphicon-ok::before {\n  content: \"\\f00c\";\n}\n.glyphicon.glyphicon-remove::before {\n  content: \"\\f00d\";\n}\n.glyphicon.glyphicon-zoom-in::before {\n  content: \"\\f00e\";\n}\n.glyphicon.glyphicon-zoom-out::before {\n  content: \"\\f010\";\n}\n.glyphicon.glyphicon-off::before {\n  content: \"\\f011\";\n}\n.glyphicon.glyphicon-signal::before {\n  content: \"\\f012\";\n}\n.glyphicon.glyphicon-cog::before {\n  content: \"\\f013\";\n}\n.glyphicon.glyphicon-trash::before {\n  content: \"\\f1f8\";\n}\n.glyphicon.glyphicon-home::before {\n  content: \"\\f015\";\n}\n.glyphicon.glyphicon-file::before {\n  content: \"\\f15b\";\n}\n.glyphicon.glyphicon-time::before {\n  content: \"\\f017\";\n}\n.glyphicon.glyphicon-road::before {\n  content: \"\\f018\";\n}\n.glyphicon.glyphicon-download-alt::before {\n  content: \"\\f0ed\";\n}\n.glyphicon.glyphicon-download::before {\n  content: \"\\f019\";\n}\n.glyphicon.glyphicon-upload::before {\n  content: \"\\f093\";\n}\n.glyphicon.glyphicon-inbox::before {\n  content: \"\\f01c\";\n}\n.glyphicon.glyphicon-play-circle::before {\n  content: \"\\f144\";\n}\n.glyphicon.glyphicon-repeat::before {\n  content: \"\\f01e\";\n}\n.glyphicon.glyphicon-refresh::before {\n  content: \"\\f021\";\n}\n.glyphicon.glyphicon-list-alt::before {\n  content: \"\\f022\";\n}\n.glyphicon.glyphicon-lock::before {\n  content: \"\\f023\";\n}\n.glyphicon.glyphicon-flag::before {\n  content: \"\\f024\";\n}\n.glyphicon.glyphicon-headphones::before {\n  content: \"\\f025\";\n}\n.glyphicon.glyphicon-volume-off::before {\n  content: \"\\f026\";\n}\n.glyphicon.glyphicon-volume-down::before {\n  content: \"\\f027\";\n}\n.glyphicon.glyphicon-volume-up::before {\n  content: \"\\f028\";\n}\n.glyphicon.glyphicon-qrcode::before {\n  content: \"\\f029\";\n}\n.glyphicon.glyphicon-barcode::before {\n  content: \"\\f02a\";\n}\n.glyphicon.glyphicon-tag::before {\n  content: \"\\f02b\";\n}\n.glyphicon.glyphicon-tags::before {\n  content: \"\\f02c\";\n}\n.glyphicon.glyphicon-book::before {\n  content: \"\\f02d\";\n}\n.glyphicon.glyphicon-bookmark::before {\n  content: \"\\f02e\";\n}\n.glyphicon.glyphicon-print::before {\n  content: \"\\f02f\";\n}\n.glyphicon.glyphicon-camera::before {\n  content: \"\\f030\";\n}\n.glyphicon.glyphicon-font::before {\n  content: \"\\f031\";\n}\n.glyphicon.glyphicon-bold::before {\n  content: \"\\f032\";\n}\n.glyphicon.glyphicon-italic::before {\n  content: \"\\f033\";\n}\n.glyphicon.glyphicon-text-height::before {\n  content: \"\\f034\";\n}\n.glyphicon.glyphicon-text-width::before {\n  content: \"\\f035\";\n}\n.glyphicon.glyphicon-align-left::before {\n  content: \"\\f036\";\n}\n.glyphicon.glyphicon-align-center::before {\n  content: \"\\f037\";\n}\n.glyphicon.glyphicon-align-right::before {\n  content: \"\\f038\";\n}\n.glyphicon.glyphicon-align-justify::before {\n  content: \"\\f039\";\n}\n.glyphicon.glyphicon-list::before {\n  content: \"\\f03a\";\n}\n.glyphicon.glyphicon-indent-left::before {\n  content: \"\\f03c\";\n}\n.glyphicon.glyphicon-indent-right::before {\n  content: \"\\f03b\";\n}\n.glyphicon.glyphicon-facetime-video::before {\n  content: \"\\f03d\";\n}\n.glyphicon.glyphicon-picture::before {\n  content: \"\\f03e\";\n}\n.glyphicon.glyphicon-map-marker::before {\n  content: \"\\f041\";\n}\n.glyphicon.glyphicon-adjust::before {\n  content: \"\\f042\";\n}\n.glyphicon.glyphicon-tint::before {\n  content: \"\\f043\";\n}\n.glyphicon.glyphicon-edit::before {\n  content: \"\\f044\";\n}\n.glyphicon.glyphicon-share::before {\n  content: \"\\f064\";\n}\n.glyphicon.glyphicon-check::before {\n  content: \"\\f00c\";\n}\n.glyphicon.glyphicon-move::before {\n  content: \"\\f047\";\n}\n.glyphicon.glyphicon-step-backward::before {\n  content: \"\\f048\";\n}\n.glyphicon.glyphicon-fast-backward::before {\n  content: \"\\f049\";\n}\n.glyphicon.glyphicon-backward::before {\n  content: \"\\f04a\";\n}\n.glyphicon.glyphicon-play::before {\n  content: \"\\f04b\";\n}\n.glyphicon.glyphicon-pause::before {\n  content: \"\\f04c\";\n}\n.glyphicon.glyphicon-stop::before {\n  content: \"\\f04d\";\n}\n.glyphicon.glyphicon-forward::before {\n  content: \"\\f04e\";\n}\n.glyphicon.glyphicon-fast-forward::before {\n  content: \"\\f050\";\n}\n.glyphicon.glyphicon-step-forward::before {\n  content: \"\\f051\";\n}\n.glyphicon.glyphicon-eject::before {\n  content: \"\\f052\";\n}\n.glyphicon.glyphicon-chevron-left::before {\n  content: \"\\f053\";\n}\n.glyphicon.glyphicon-chevron-right::before {\n  content: \"\\f054\";\n}\n.glyphicon.glyphicon-plus-sign::before {\n  content: \"\\f055\";\n}\n.glyphicon.glyphicon-minus-sign::before {\n  content: \"\\f056\";\n}\n.glyphicon.glyphicon-remove-sign::before {\n  content: \"\\f057\";\n}\n.glyphicon.glyphicon-ok-sign::before {\n  content: \"\\f058\";\n}\n.glyphicon.glyphicon-question-sign::before {\n  content: \"\\f059\";\n}\n.glyphicon.glyphicon-info-sign::before {\n  content: \"\\f05a\";\n}\n.glyphicon.glyphicon-screenshot::before {\n  content: \"\\f05b\";\n}\n.glyphicon.glyphicon-remove-circle::before {\n  content: \"\\f057\";\n}\n.glyphicon.glyphicon-ok-circle::before {\n  content: \"\\f058\";\n}\n.glyphicon.glyphicon-ban-circle::before {\n  content: \"\\f05e\";\n}\n.glyphicon.glyphicon-arrow-left::before {\n  content: \"\\f060\";\n}\n.glyphicon.glyphicon-arrow-right::before {\n  content: \"\\f061\";\n}\n.glyphicon.glyphicon-arrow-up::before {\n  content: \"\\f062\";\n}\n.glyphicon.glyphicon-arrow-down::before {\n  content: \"\\f063\";\n}\n.glyphicon.glyphicon-share-alt::before {\n  content: \"\\f1e0\";\n}\n.glyphicon.glyphicon-resize-full::before {\n  content: \"\\f065\";\n}\n.glyphicon.glyphicon-resize-small::before {\n  content: \"\\f066\";\n}\n.glyphicon.glyphicon-exclamation-sign::before {\n  content: \"\\f06a\";\n}\n.glyphicon.glyphicon-gift::before {\n  content: \"\\f06b\";\n}\n.glyphicon.glyphicon-leaf::before {\n  content: \"\\f06c\";\n}\n.glyphicon.glyphicon-fire::before {\n  content: \"\\f06d\";\n}\n.glyphicon.glyphicon-eye-open::before {\n  content: \"\\f06e\";\n}\n.glyphicon.glyphicon-eye-close::before {\n  content: \"\\f070\";\n}\n.glyphicon.glyphicon-warning-sign::before {\n  content: \"\\f071\";\n}\n.glyphicon.glyphicon-plane::before {\n  content: \"\\f072\";\n}\n.glyphicon.glyphicon-calendar::before {\n  content: \"\\f073\";\n}\n.glyphicon.glyphicon-random::before {\n  content: \"\\f074\";\n}\n.glyphicon.glyphicon-comment::before {\n  content: \"\\f075\";\n}\n.glyphicon.glyphicon-magnet::before {\n  content: \"\\f076\";\n}\n.glyphicon.glyphicon-chevron-up::before {\n  content: \"\\f077\";\n}\n.glyphicon.glyphicon-chevron-down::before {\n  content: \"\\f078\";\n}\n.glyphicon.glyphicon-retweet::before {\n  content: \"\\f079\";\n}\n.glyphicon.glyphicon-shopping-cart::before {\n  content: \"\\f07a\";\n}\n.glyphicon.glyphicon-folder-close::before {\n  content: \"\\f07b\";\n}\n.glyphicon.glyphicon-folder-open::before {\n  content: \"\\f07c\";\n}\n.glyphicon.glyphicon-resize-vertical::before {\n  content: \"\\f07d\";\n}\n.glyphicon.glyphicon-resize-horizontal::before {\n  content: \"\\f07e\";\n}\n.glyphicon.glyphicon-hdd::before {\n  content: \"\\f0a0\";\n}\n.glyphicon.glyphicon-bullhorn::before {\n  content: \"\\f0a1\";\n}\n.glyphicon.glyphicon-bell::before {\n  content: \"\\f0f3\";\n}\n.glyphicon.glyphicon-certificate::before {\n  content: \"\\f0a3\";\n}\n.glyphicon.glyphicon-thumbs-up::before {\n  content: \"\\f164\";\n}\n.glyphicon.glyphicon-thumbs-down::before {\n  content: \"\\f165\";\n}\n.glyphicon.glyphicon-hand-right::before {\n  content: \"\\f0a4\";\n}\n.glyphicon.glyphicon-hand-left::before {\n  content: \"\\f0a5\";\n}\n.glyphicon.glyphicon-hand-up::before {\n  content: \"\\f0a6\";\n}\n.glyphicon.glyphicon-hand-down::before {\n  content: \"\\f0a7\";\n}\n.glyphicon.glyphicon-circle-arrow-right::before {\n  content: \"\\f0a9\";\n}\n.glyphicon.glyphicon-circle-arrow-left::before {\n  content: \"\\f0a8\";\n}\n.glyphicon.glyphicon-circle-arrow-up::before {\n  content: \"\\f0aa\";\n}\n.glyphicon.glyphicon-circle-arrow-down::before {\n  content: \"\\f0ab\";\n}\n.glyphicon.glyphicon-globe::before {\n  content: \"\\f0ac\";\n}\n.glyphicon.glyphicon-wrench::before {\n  content: \"\\f0ad\";\n}\n.glyphicon.glyphicon-tasks::before {\n  content: \"\\f0ae\";\n}\n.glyphicon.glyphicon-filter::before {\n  content: \"\\f0b0\";\n}\n.glyphicon.glyphicon-briefcase::before {\n  content: \"\\f0b1\";\n}\n.glyphicon.glyphicon-fullscreen::before {\n  content: \"\\f065\";\n}\n.glyphicon.glyphicon-dashboard::before {\n  content: \"\\f0e4\";\n}\n.glyphicon.glyphicon-paperclip::before {\n  content: \"\\f0c6\";\n}\n.glyphicon.glyphicon-heart-empty::before {\n  content: \"\\f08a\";\n}\n.glyphicon.glyphicon-link::before {\n  content: \"\\f0c1\";\n}\n.glyphicon.glyphicon-phone::before {\n  content: \"\\f095\";\n}\n.glyphicon.glyphicon-pushpin::before {\n  content: \"\\f08d\";\n}\n.glyphicon.glyphicon-usd::before {\n  content: \"\\f155\";\n}\n.glyphicon.glyphicon-gbp::before {\n  content: \"\\f154\";\n}\n.glyphicon.glyphicon-sort::before {\n  content: \"\\f0dc\";\n}\n.glyphicon.glyphicon-sort-by-alphabet::before {\n  content: \"\\f15d\";\n}\n.glyphicon.glyphicon-sort-by-alphabet-alt::before {\n  content: \"\\f15e\";\n}\n.glyphicon.glyphicon-sort-by-order::before {\n  content: \"\\f162\";\n}\n.glyphicon.glyphicon-sort-by-order-alt::before {\n  content: \"\\f163\";\n}\n.glyphicon.glyphicon-sort-by-attributes::before {\n  content: \"\\f160\";\n}\n.glyphicon.glyphicon-sort-by-attributes-alt::before {\n  content: \"\\f161\";\n}\n.glyphicon.glyphicon-unchecked::before {\n  content: \"\\f096\";\n}\n.glyphicon.glyphicon-expand::before {\n  content: \"\\f152\";\n}\n.glyphicon.glyphicon-collapse-down::before {\n  content: \"\\f150\";\n}\n.glyphicon.glyphicon-collapse-up::before {\n  content: \"\\f151\";\n}\n.glyphicon.glyphicon-log-in::before {\n  content: \"\\f090\";\n}\n.glyphicon.glyphicon-flash::before {\n  content: \"\\f0e7\";\n}\n.glyphicon.glyphicon-log-out::before {\n  content: \"\\f08b\";\n}\n.glyphicon.glyphicon-new-window::before {\n  content: \"\\f08e\";\n}\n.glyphicon.glyphicon-record::before {\n  content: \"\\f192\";\n}\n.glyphicon.glyphicon-save::before {\n  content: \"\\f0c7\";\n}\n.glyphicon.glyphicon-open::before {\n  content: \"\\f093\";\n}\n.glyphicon.glyphicon-saved::before {\n  content: \"\\f00c\";\n}\n.glyphicon.glyphicon-import::before {\n  content: \"\\f093\";\n}\n.glyphicon.glyphicon-export::before {\n  content: \"\\f019\";\n}\n.glyphicon.glyphicon-send::before {\n  content: \"\\f1d9\";\n}\n.glyphicon.glyphicon-floppy-disk::before {\n  content: \"\\f0c7\";\n}\n.glyphicon.glyphicon-floppy-saved::before {\n  content: \"\\f00c\";\n}\n.glyphicon.glyphicon-floppy-remove::before {\n  content: \"\\f00d\";\n}\n.glyphicon.glyphicon-floppy-save::before {\n  content: \"\\f019\";\n}\n.glyphicon.glyphicon-floppy-open::before {\n  content: \"\\f093\";\n}\n.glyphicon.glyphicon-credit-card::before {\n  content: \"\\f09d\";\n}\n.glyphicon.glyphicon-transfer::before {\n  content: \"\\f0ec\";\n}\n.glyphicon.glyphicon-cutlery::before {\n  content: \"\\f0f5\";\n}\n.glyphicon.glyphicon-header::before {\n  content: \"\\f1dc\";\n}\n.glyphicon.glyphicon-compressed::before {\n  content: \"\\f1c6\";\n}\n.glyphicon.glyphicon-earphone::before {\n  content: \"\\f095\";\n}\n.glyphicon.glyphicon-phone-alt::before {\n  content: \"\\f098\";\n}\n.glyphicon.glyphicon-tower::before {\n  content: \"\\f1ad\";\n}\n.glyphicon.glyphicon-stats::before {\n  content: \"\\f080\";\n}\n.glyphicon.glyphicon-sd-video::before {\n  content: \"\\f008\";\n}\n.glyphicon.glyphicon-hd-video::before {\n  content: \"\\f008\";\n}\n.glyphicon.glyphicon-subtitles::before {\n  content: \"\\f20a\";\n}\n.glyphicon.glyphicon-sound-stereo::before {\n  content: \"\\f001\";\n}\n.glyphicon.glyphicon-sound-dolby::before {\n  content: \"\\f001\";\n}\n.glyphicon.glyphicon-sound-5-1::before {\n  content: \"\\f001\";\n}\n.glyphicon.glyphicon-sound-6-1::before {\n  content: \"\\f001\";\n}\n.glyphicon.glyphicon-sound-7-1::before {\n  content: \"\\f001\";\n}\n.glyphicon.glyphicon-copyright-mark::before {\n  content: \"\\f1f9\";\n}\n.glyphicon.glyphicon-registration-mark::before {\n  content: \"\\f25d\";\n}\n.glyphicon.glyphicon-cloud-download::before {\n  content: \"\\f0ed\";\n}\n.glyphicon.glyphicon-cloud-upload::before {\n  content: \"\\f0ee\";\n}\n.glyphicon.glyphicon-tree-conifer::before {\n  content: \"\\f1bb\";\n}\n.glyphicon.glyphicon-tree-deciduous::before {\n  content: \"\\f1bb\";\n}\n.glyphicon.glyphicon-cd::before {\n  content: \"\\f192\";\n}\n.glyphicon.glyphicon-save-file::before {\n  content: \"\\f0c7\";\n}\n.glyphicon.glyphicon-open-file::before {\n  content: \"\\f115\";\n}\n.glyphicon.glyphicon-level-up::before {\n  content: \"\\f148\";\n}\n.glyphicon.glyphicon-copy::before {\n  content: \"\\f0c5\";\n}\n.glyphicon.glyphicon-paste::before {\n  content: \"\\f0ea\";\n}\n.glyphicon.glyphicon-alert::before {\n  content: \"\\f071\";\n}\n.glyphicon.glyphicon-equalizer::before {\n  content: \"\\f080\";\n}\n.glyphicon.glyphicon-king::before {\n  content: \"\\f128\";\n}\n.glyphicon.glyphicon-queen::before {\n  content: \"\\f128\";\n}\n.glyphicon.glyphicon-pawn::before {\n  content: \"\\f128\";\n}\n.glyphicon.glyphicon-bishop::before {\n  content: \"\\f128\";\n}\n.glyphicon.glyphicon-knight::before {\n  content: \"\\f128\";\n}\n.glyphicon.glyphicon-baby-formula::before {\n  content: \"\\f128\";\n}\n.glyphicon.glyphicon-tent::before {\n  content: \"\\f128\";\n}\n.glyphicon.glyphicon-blackboard::before {\n  content: \"\\f128\";\n}\n.glyphicon.glyphicon-bed::before {\n  content: \"\\f236\";\n}\n.glyphicon.glyphicon-apple::before {\n  content: \"\\f179\";\n}\n.glyphicon.glyphicon-erase::before {\n  content: \"\\f12d\";\n}\n.glyphicon.glyphicon-hourglass::before {\n  content: \"\\f254\";\n}\n.glyphicon.glyphicon-lamp::before {\n  content: \"\\f0eb\";\n}\n.glyphicon.glyphicon-duplicate::before {\n  content: \"\\f0c5\";\n}\n.glyphicon.glyphicon-piggy-bank::before {\n  content: \"\\f0d6\";\n}\n.glyphicon.glyphicon-scissors::before {\n  content: \"\\f0c4\";\n}\n.glyphicon.glyphicon-bitcoin::before {\n  content: \"\\f15a\";\n}\n.glyphicon.glyphicon-btc::before {\n  content: \"\\f15a\";\n}\n.glyphicon.glyphicon-xbt::before {\n  content: \"\\f15a\";\n}\n.glyphicon.glyphicon-yen::before {\n  content: \"\\f157\";\n}\n.glyphicon.glyphicon-jpy::before {\n  content: \"\\f157\";\n}\n.glyphicon.glyphicon-ruble::before {\n  content: \"\\f158\";\n}\n.glyphicon.glyphicon-rub::before {\n  content: \"\\f158\";\n}\n.glyphicon.glyphicon-scale::before {\n  content: \"\\f24e\";\n}\n.glyphicon.glyphicon-ice-lolly::before {\n  content: \"\\f128\";\n}\n.glyphicon.glyphicon-ice-lolly-tasted::before {\n  content: \"\\f128\";\n}\n.glyphicon.glyphicon-education::before {\n  content: \"\\f19d\";\n}\n.glyphicon.glyphicon-option-horizontal::before {\n  content: \"\\f141\";\n}\n.glyphicon.glyphicon-option-vertical::before {\n  content: \"\\f142\";\n}\n.glyphicon.glyphicon-menu-hamburger::before {\n  content: \"\\f0c9\";\n}\n.glyphicon.glyphicon-modal-window::before {\n  content: \"\\f128\";\n}\n.glyphicon.glyphicon-oil::before {\n  content: \"\\f128\";\n}\n.glyphicon.glyphicon-grain::before {\n  content: \"\\f128\";\n}\n.glyphicon.glyphicon-sunglasses::before {\n  content: \"\\f128\";\n}\n.glyphicon.glyphicon-text-size::before {\n  content: \"\\f031\";\n}\n.glyphicon.glyphicon-text-color::before {\n  content: \"\\f031\";\n}\n.glyphicon.glyphicon-text-background::before {\n  content: \"\\f031\";\n}\n.glyphicon.glyphicon-object-align-top::before {\n  content: \"\\f128\";\n}\n.glyphicon.glyphicon-object-align-bottom::before {\n  content: \"\\f128\";\n}\n.glyphicon.glyphicon-object-align-horizontal::before {\n  content: \"\\f128\";\n}\n.glyphicon.glyphicon-object-align-left::before {\n  content: \"\\f128\";\n}\n.glyphicon.glyphicon-object-align-vertical::before {\n  content: \"\\f128\";\n}\n.glyphicon.glyphicon-object-align-right::before {\n  content: \"\\f128\";\n}\n.glyphicon.glyphicon-triangle-right::before {\n  content: \"\\f0da\";\n}\n.glyphicon.glyphicon-triangle-left::before {\n  content: \"\\f0d9\";\n}\n.glyphicon.glyphicon-triangle-bottom::before {\n  content: \"\\f0d7\";\n}\n.glyphicon.glyphicon-triangle-top::before {\n  content: \"\\f0d8\";\n}\n.glyphicon.glyphicon-console::before {\n  content: \"\\f120\";\n}\n.glyphicon.glyphicon-superscript::before {\n  content: \"\\f12b\";\n}\n.glyphicon.glyphicon-subscript::before {\n  content: \"\\f12c\";\n}\n.glyphicon.glyphicon-menu-left::before {\n  content: \"\\f053\";\n}\n.glyphicon.glyphicon-menu-right::before {\n  content: \"\\f054\";\n}\n.glyphicon.glyphicon-menu-down::before {\n  content: \"\\f078\";\n}\n.glyphicon.glyphicon-menu-up::before {\n  content: \"\\f077\";\n}\n.glyphicon.glyphicon-transfer::before {\n  content: \"\\f0ec\";\n}\n/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen\n   readers do not read off random characters that represent icons */\n.fa-glass::before {\n  content: \"\\f000\";\n}\n.fa-music::before {\n  content: \"\\f001\";\n}\n.fa-search::before {\n  content: \"\\f002\";\n}\n.fa-envelope-o::before {\n  content: \"\\f003\";\n}\n.fa-heart::before {\n  content: \"\\f004\";\n}\n.fa-star::before {\n  content: \"\\f005\";\n}\n.fa-star-o::before {\n  content: \"\\f006\";\n}\n.fa-user::before {\n  content: \"\\f007\";\n}\n.fa-film::before {\n  content: \"\\f008\";\n}\n.fa-th-large::before {\n  content: \"\\f009\";\n}\n.fa-th::before {\n  content: \"\\f00a\";\n}\n.fa-th-list::before {\n  content: \"\\f00b\";\n}\n.fa-check::before {\n  content: \"\\f00c\";\n}\n.fa-remove::before,\n.fa-close::before,\n.fa-times::before {\n  content: \"\\f00d\";\n}\n.fa-search-plus::before {\n  content: \"\\f00e\";\n}\n.fa-search-minus::before {\n  content: \"\\f010\";\n}\n.fa-power-off::before {\n  content: \"\\f011\";\n}\n.fa-signal::before {\n  content: \"\\f012\";\n}\n.fa-gear::before,\n.fa-cog::before {\n  content: \"\\f013\";\n}\n.fa-trash-o::before {\n  content: \"\\f014\";\n}\n.fa-home::before {\n  content: \"\\f015\";\n}\n.fa-file-o::before {\n  content: \"\\f016\";\n}\n.fa-clock-o::before {\n  content: \"\\f017\";\n}\n.fa-road::before {\n  content: \"\\f018\";\n}\n.fa-download::before {\n  content: \"\\f019\";\n}\n.fa-arrow-circle-o-down::before {\n  content: \"\\f01a\";\n}\n.fa-arrow-circle-o-up::before {\n  content: \"\\f01b\";\n}\n.fa-inbox::before {\n  content: \"\\f01c\";\n}\n.fa-play-circle-o::before {\n  content: \"\\f01d\";\n}\n.fa-rotate-right::before,\n.fa-repeat::before {\n  content: \"\\f01e\";\n}\n.fa-refresh::before {\n  content: \"\\f021\";\n}\n.fa-list-alt::before {\n  content: \"\\f022\";\n}\n.fa-lock::before {\n  content: \"\\f023\";\n}\n.fa-flag::before {\n  content: \"\\f024\";\n}\n.fa-headphones::before {\n  content: \"\\f025\";\n}\n.fa-volume-off::before {\n  content: \"\\f026\";\n}\n.fa-volume-down::before {\n  content: \"\\f027\";\n}\n.fa-volume-up::before {\n  content: \"\\f028\";\n}\n.fa-qrcode::before {\n  content: \"\\f029\";\n}\n.fa-barcode::before {\n  content: \"\\f02a\";\n}\n.fa-tag::before {\n  content: \"\\f02b\";\n}\n.fa-tags::before {\n  content: \"\\f02c\";\n}\n.fa-book::before {\n  content: \"\\f02d\";\n}\n.fa-bookmark::before {\n  content: \"\\f02e\";\n}\n.fa-print::before {\n  content: \"\\f02f\";\n}\n.fa-camera::before {\n  content: \"\\f030\";\n}\n.fa-font::before {\n  content: \"\\f031\";\n}\n.fa-bold::before {\n  content: \"\\f032\";\n}\n.fa-italic::before {\n  content: \"\\f033\";\n}\n.fa-text-height::before {\n  content: \"\\f034\";\n}\n.fa-text-width::before {\n  content: \"\\f035\";\n}\n.fa-align-left::before {\n  content: \"\\f036\";\n}\n.fa-align-center::before {\n  content: \"\\f037\";\n}\n.fa-align-right::before {\n  content: \"\\f038\";\n}\n.fa-align-justify::before {\n  content: \"\\f039\";\n}\n.fa-list::before {\n  content: \"\\f03a\";\n}\n.fa-dedent::before,\n.fa-outdent::before {\n  content: \"\\f03b\";\n}\n.fa-indent::before {\n  content: \"\\f03c\";\n}\n.fa-video-camera::before {\n  content: \"\\f03d\";\n}\n.fa-photo::before,\n.fa-image::before,\n.fa-picture-o::before {\n  content: \"\\f03e\";\n}\n.fa-pencil::before {\n  content: \"\\f040\";\n}\n.fa-map-marker::before {\n  content: \"\\f041\";\n}\n.fa-adjust::before {\n  content: \"\\f042\";\n}\n.fa-tint::before {\n  content: \"\\f043\";\n}\n.fa-edit::before,\n.fa-pencil-square-o::before {\n  content: \"\\f044\";\n}\n.fa-share-square-o::before {\n  content: \"\\f045\";\n}\n.fa-check-square-o::before {\n  content: \"\\f046\";\n}\n.fa-arrows::before {\n  content: \"\\f047\";\n}\n.fa-step-backward::before {\n  content: \"\\f048\";\n}\n.fa-fast-backward::before {\n  content: \"\\f049\";\n}\n.fa-backward::before {\n  content: \"\\f04a\";\n}\n.fa-play::before {\n  content: \"\\f04b\";\n}\n.fa-pause::before {\n  content: \"\\f04c\";\n}\n.fa-stop::before {\n  content: \"\\f04d\";\n}\n.fa-forward::before {\n  content: \"\\f04e\";\n}\n.fa-fast-forward::before {\n  content: \"\\f050\";\n}\n.fa-step-forward::before {\n  content: \"\\f051\";\n}\n.fa-eject::before {\n  content: \"\\f052\";\n}\n.fa-chevron-left::before {\n  content: \"\\f053\";\n}\n.fa-chevron-right::before {\n  content: \"\\f054\";\n}\n.fa-plus-circle::before {\n  content: \"\\f055\";\n}\n.fa-minus-circle::before {\n  content: \"\\f056\";\n}\n.fa-times-circle::before {\n  content: \"\\f057\";\n}\n.fa-check-circle::before {\n  content: \"\\f058\";\n}\n.fa-question-circle::before {\n  content: \"\\f059\";\n}\n.fa-info-circle::before {\n  content: \"\\f05a\";\n}\n.fa-crosshairs::before {\n  content: \"\\f05b\";\n}\n.fa-times-circle-o::before {\n  content: \"\\f05c\";\n}\n.fa-check-circle-o::before {\n  content: \"\\f05d\";\n}\n.fa-ban::before {\n  content: \"\\f05e\";\n}\n.fa-arrow-left::before {\n  content: \"\\f060\";\n}\n.fa-arrow-right::before {\n  content: \"\\f061\";\n}\n.fa-arrow-up::before {\n  content: \"\\f062\";\n}\n.fa-arrow-down::before {\n  content: \"\\f063\";\n}\n.fa-mail-forward::before,\n.fa-share::before {\n  content: \"\\f064\";\n}\n.fa-expand::before {\n  content: \"\\f065\";\n}\n.fa-compress::before {\n  content: \"\\f066\";\n}\n.fa-plus::before {\n  content: \"\\f067\";\n}\n.fa-minus::before {\n  content: \"\\f068\";\n}\n.fa-asterisk::before {\n  content: \"\\f069\";\n}\n.fa-exclamation-circle::before {\n  content: \"\\f06a\";\n}\n.fa-gift::before {\n  content: \"\\f06b\";\n}\n.fa-leaf::before {\n  content: \"\\f06c\";\n}\n.fa-fire::before {\n  content: \"\\f06d\";\n}\n.fa-eye::before {\n  content: \"\\f06e\";\n}\n.fa-eye-slash::before {\n  content: \"\\f070\";\n}\n.fa-warning::before,\n.fa-exclamation-triangle::before {\n  content: \"\\f071\";\n}\n.fa-plane::before {\n  content: \"\\f072\";\n}\n.fa-calendar::before {\n  content: \"\\f073\";\n}\n.fa-random::before {\n  content: \"\\f074\";\n}\n.fa-comment::before {\n  content: \"\\f075\";\n}\n.fa-magnet::before {\n  content: \"\\f076\";\n}\n.fa-chevron-up::before {\n  content: \"\\f077\";\n}\n.fa-chevron-down::before {\n  content: \"\\f078\";\n}\n.fa-retweet::before {\n  content: \"\\f079\";\n}\n.fa-shopping-cart::before {\n  content: \"\\f07a\";\n}\n.fa-folder::before {\n  content: \"\\f07b\";\n}\n.fa-folder-open::before {\n  content: \"\\f07c\";\n}\n.fa-arrows-v::before {\n  content: \"\\f07d\";\n}\n.fa-arrows-h::before {\n  content: \"\\f07e\";\n}\n.fa-bar-chart-o::before,\n.fa-bar-chart::before {\n  content: \"\\f080\";\n}\n.fa-twitter-square::before {\n  content: \"\\f081\";\n}\n.fa-facebook-square::before {\n  content: \"\\f082\";\n}\n.fa-camera-retro::before {\n  content: \"\\f083\";\n}\n.fa-key::before {\n  content: \"\\f084\";\n}\n.fa-gears::before,\n.fa-cogs::before {\n  content: \"\\f085\";\n}\n.fa-comments::before {\n  content: \"\\f086\";\n}\n.fa-thumbs-o-up::before {\n  content: \"\\f087\";\n}\n.fa-thumbs-o-down::before {\n  content: \"\\f088\";\n}\n.fa-star-half::before {\n  content: \"\\f089\";\n}\n.fa-heart-o::before {\n  content: \"\\f08a\";\n}\n.fa-sign-out::before {\n  content: \"\\f08b\";\n}\n.fa-linkedin-square::before {\n  content: \"\\f08c\";\n}\n.fa-thumb-tack::before {\n  content: \"\\f08d\";\n}\n.fa-external-link::before {\n  content: \"\\f08e\";\n}\n.fa-sign-in::before {\n  content: \"\\f090\";\n}\n.fa-trophy::before {\n  content: \"\\f091\";\n}\n.fa-github-square::before {\n  content: \"\\f092\";\n}\n.fa-upload::before {\n  content: \"\\f093\";\n}\n.fa-lemon-o::before {\n  content: \"\\f094\";\n}\n.fa-phone::before {\n  content: \"\\f095\";\n}\n.fa-square-o::before {\n  content: \"\\f096\";\n}\n.fa-bookmark-o::before {\n  content: \"\\f097\";\n}\n.fa-phone-square::before {\n  content: \"\\f098\";\n}\n.fa-twitter::before {\n  content: \"\\f099\";\n}\n.fa-facebook-f::before,\n.fa-facebook::before {\n  content: \"\\f09a\";\n}\n.fa-github::before {\n  content: \"\\f09b\";\n}\n.fa-unlock::before {\n  content: \"\\f09c\";\n}\n.fa-credit-card::before {\n  content: \"\\f09d\";\n}\n.fa-feed::before,\n.fa-rss::before {\n  content: \"\\f09e\";\n}\n.fa-hdd-o::before {\n  content: \"\\f0a0\";\n}\n.fa-bullhorn::before {\n  content: \"\\f0a1\";\n}\n.fa-bell::before {\n  content: \"\\f0f3\";\n}\n.fa-certificate::before {\n  content: \"\\f0a3\";\n}\n.fa-hand-o-right::before {\n  content: \"\\f0a4\";\n}\n.fa-hand-o-left::before {\n  content: \"\\f0a5\";\n}\n.fa-hand-o-up::before {\n  content: \"\\f0a6\";\n}\n.fa-hand-o-down::before {\n  content: \"\\f0a7\";\n}\n.fa-arrow-circle-left::before {\n  content: \"\\f0a8\";\n}\n.fa-arrow-circle-right::before {\n  content: \"\\f0a9\";\n}\n.fa-arrow-circle-up::before {\n  content: \"\\f0aa\";\n}\n.fa-arrow-circle-down::before {\n  content: \"\\f0ab\";\n}\n.fa-globe::before {\n  content: \"\\f0ac\";\n}\n.fa-wrench::before {\n  content: \"\\f0ad\";\n}\n.fa-tasks::before {\n  content: \"\\f0ae\";\n}\n.fa-filter::before {\n  content: \"\\f0b0\";\n}\n.fa-briefcase::before {\n  content: \"\\f0b1\";\n}\n.fa-arrows-alt::before {\n  content: \"\\f0b2\";\n}\n.fa-group::before,\n.fa-users::before {\n  content: \"\\f0c0\";\n}\n.fa-chain::before,\n.fa-link::before {\n  content: \"\\f0c1\";\n}\n.fa-cloud::before {\n  content: \"\\f0c2\";\n}\n.fa-flask::before {\n  content: \"\\f0c3\";\n}\n.fa-cut::before,\n.fa-scissors::before {\n  content: \"\\f0c4\";\n}\n.fa-copy::before,\n.fa-files-o::before {\n  content: \"\\f0c5\";\n}\n.fa-paperclip::before {\n  content: \"\\f0c6\";\n}\n.fa-save::before,\n.fa-floppy-o::before {\n  content: \"\\f0c7\";\n}\n.fa-square::before {\n  content: \"\\f0c8\";\n}\n.fa-navicon::before,\n.fa-reorder::before,\n.fa-bars::before {\n  content: \"\\f0c9\";\n}\n.fa-list-ul::before {\n  content: \"\\f0ca\";\n}\n.fa-list-ol::before {\n  content: \"\\f0cb\";\n}\n.fa-strikethrough::before {\n  content: \"\\f0cc\";\n}\n.fa-underline::before {\n  content: \"\\f0cd\";\n}\n.fa-table::before {\n  content: \"\\f0ce\";\n}\n.fa-magic::before {\n  content: \"\\f0d0\";\n}\n.fa-truck::before {\n  content: \"\\f0d1\";\n}\n.fa-pinterest::before {\n  content: \"\\f0d2\";\n}\n.fa-pinterest-square::before {\n  content: \"\\f0d3\";\n}\n.fa-google-plus-square::before {\n  content: \"\\f0d4\";\n}\n.fa-google-plus::before {\n  content: \"\\f0d5\";\n}\n.fa-money::before {\n  content: \"\\f0d6\";\n}\n.fa-caret-down::before {\n  content: \"\\f0d7\";\n}\n.fa-caret-up::before {\n  content: \"\\f0d8\";\n}\n.fa-caret-left::before {\n  content: \"\\f0d9\";\n}\n.fa-caret-right::before {\n  content: \"\\f0da\";\n}\n.fa-columns::before {\n  content: \"\\f0db\";\n}\n.fa-unsorted::before,\n.fa-sort::before {\n  content: \"\\f0dc\";\n}\n.fa-sort-down::before,\n.fa-sort-desc::before {\n  content: \"\\f0dd\";\n}\n.fa-sort-up::before,\n.fa-sort-asc::before {\n  content: \"\\f0de\";\n}\n.fa-envelope::before {\n  content: \"\\f0e0\";\n}\n.fa-linkedin::before {\n  content: \"\\f0e1\";\n}\n.fa-rotate-left::before,\n.fa-undo::before {\n  content: \"\\f0e2\";\n}\n.fa-legal::before,\n.fa-gavel::before {\n  content: \"\\f0e3\";\n}\n.fa-dashboard::before,\n.fa-tachometer::before {\n  content: \"\\f0e4\";\n}\n.fa-comment-o::before {\n  content: \"\\f0e5\";\n}\n.fa-comments-o::before {\n  content: \"\\f0e6\";\n}\n.fa-flash::before,\n.fa-bolt::before {\n  content: \"\\f0e7\";\n}\n.fa-sitemap::before {\n  content: \"\\f0e8\";\n}\n.fa-umbrella::before {\n  content: \"\\f0e9\";\n}\n.fa-paste::before,\n.fa-clipboard::before {\n  content: \"\\f0ea\";\n}\n.fa-lightbulb-o::before {\n  content: \"\\f0eb\";\n}\n.fa-exchange::before {\n  content: \"\\f0ec\";\n}\n.fa-cloud-download::before {\n  content: \"\\f0ed\";\n}\n.fa-cloud-upload::before {\n  content: \"\\f0ee\";\n}\n.fa-user-md::before {\n  content: \"\\f0f0\";\n}\n.fa-stethoscope::before {\n  content: \"\\f0f1\";\n}\n.fa-suitcase::before {\n  content: \"\\f0f2\";\n}\n.fa-bell-o::before {\n  content: \"\\f0a2\";\n}\n.fa-coffee::before {\n  content: \"\\f0f4\";\n}\n.fa-cutlery::before {\n  content: \"\\f0f5\";\n}\n.fa-file-text-o::before {\n  content: \"\\f0f6\";\n}\n.fa-building-o::before {\n  content: \"\\f0f7\";\n}\n.fa-hospital-o::before {\n  content: \"\\f0f8\";\n}\n.fa-ambulance::before {\n  content: \"\\f0f9\";\n}\n.fa-medkit::before {\n  content: \"\\f0fa\";\n}\n.fa-fighter-jet::before {\n  content: \"\\f0fb\";\n}\n.fa-beer::before {\n  content: \"\\f0fc\";\n}\n.fa-h-square::before {\n  content: \"\\f0fd\";\n}\n.fa-plus-square::before {\n  content: \"\\f0fe\";\n}\n.fa-angle-double-left::before {\n  content: \"\\f100\";\n}\n.fa-angle-double-right::before {\n  content: \"\\f101\";\n}\n.fa-angle-double-up::before {\n  content: \"\\f102\";\n}\n.fa-angle-double-down::before {\n  content: \"\\f103\";\n}\n.fa-angle-left::before {\n  content: \"\\f104\";\n}\n.fa-angle-right::before {\n  content: \"\\f105\";\n}\n.fa-angle-up::before {\n  content: \"\\f106\";\n}\n.fa-angle-down::before {\n  content: \"\\f107\";\n}\n.fa-desktop::before {\n  content: \"\\f108\";\n}\n.fa-laptop::before {\n  content: \"\\f109\";\n}\n.fa-tablet::before {\n  content: \"\\f10a\";\n}\n.fa-mobile-phone::before,\n.fa-mobile::before {\n  content: \"\\f10b\";\n}\n.fa-circle-o::before {\n  content: \"\\f10c\";\n}\n.fa-quote-left::before {\n  content: \"\\f10d\";\n}\n.fa-quote-right::before {\n  content: \"\\f10e\";\n}\n.fa-spinner::before {\n  content: \"\\f110\";\n}\n.fa-circle::before {\n  content: \"\\f111\";\n}\n.fa-mail-reply::before,\n.fa-reply::before {\n  content: \"\\f112\";\n}\n.fa-github-alt::before {\n  content: \"\\f113\";\n}\n.fa-folder-o::before {\n  content: \"\\f114\";\n}\n.fa-folder-open-o::before {\n  content: \"\\f115\";\n}\n.fa-smile-o::before {\n  content: \"\\f118\";\n}\n.fa-frown-o::before {\n  content: \"\\f119\";\n}\n.fa-meh-o::before {\n  content: \"\\f11a\";\n}\n.fa-gamepad::before {\n  content: \"\\f11b\";\n}\n.fa-keyboard-o::before {\n  content: \"\\f11c\";\n}\n.fa-flag-o::before {\n  content: \"\\f11d\";\n}\n.fa-flag-checkered::before {\n  content: \"\\f11e\";\n}\n.fa-terminal::before {\n  content: \"\\f120\";\n}\n.fa-code::before {\n  content: \"\\f121\";\n}\n.fa-mail-reply-all::before,\n.fa-reply-all::before {\n  content: \"\\f122\";\n}\n.fa-star-half-empty::before,\n.fa-star-half-full::before,\n.fa-star-half-o::before {\n  content: \"\\f123\";\n}\n.fa-location-arrow::before {\n  content: \"\\f124\";\n}\n.fa-crop::before {\n  content: \"\\f125\";\n}\n.fa-code-fork::before {\n  content: \"\\f126\";\n}\n.fa-unlink::before,\n.fa-chain-broken::before {\n  content: \"\\f127\";\n}\n.fa-question::before {\n  content: \"\\f128\";\n}\n.fa-info::before {\n  content: \"\\f129\";\n}\n.fa-exclamation::before {\n  content: \"\\f12a\";\n}\n.fa-superscript::before {\n  content: \"\\f12b\";\n}\n.fa-subscript::before {\n  content: \"\\f12c\";\n}\n.fa-eraser::before {\n  content: \"\\f12d\";\n}\n.fa-puzzle-piece::before {\n  content: \"\\f12e\";\n}\n.fa-microphone::before {\n  content: \"\\f130\";\n}\n.fa-microphone-slash::before {\n  content: \"\\f131\";\n}\n.fa-shield::before {\n  content: \"\\f132\";\n}\n.fa-calendar-o::before {\n  content: \"\\f133\";\n}\n.fa-fire-extinguisher::before {\n  content: \"\\f134\";\n}\n.fa-rocket::before {\n  content: \"\\f135\";\n}\n.fa-maxcdn::before {\n  content: \"\\f136\";\n}\n.fa-chevron-circle-left::before {\n  content: \"\\f137\";\n}\n.fa-chevron-circle-right::before {\n  content: \"\\f138\";\n}\n.fa-chevron-circle-up::before {\n  content: \"\\f139\";\n}\n.fa-chevron-circle-down::before {\n  content: \"\\f13a\";\n}\n.fa-html5::before {\n  content: \"\\f13b\";\n}\n.fa-css3::before {\n  content: \"\\f13c\";\n}\n.fa-anchor::before {\n  content: \"\\f13d\";\n}\n.fa-unlock-alt::before {\n  content: \"\\f13e\";\n}\n.fa-bullseye::before {\n  content: \"\\f140\";\n}\n.fa-ellipsis-h::before {\n  content: \"\\f141\";\n}\n.fa-ellipsis-v::before {\n  content: \"\\f142\";\n}\n.fa-rss-square::before {\n  content: \"\\f143\";\n}\n.fa-play-circle::before {\n  content: \"\\f144\";\n}\n.fa-ticket::before {\n  content: \"\\f145\";\n}\n.fa-minus-square::before {\n  content: \"\\f146\";\n}\n.fa-minus-square-o::before {\n  content: \"\\f147\";\n}\n.fa-level-up::before {\n  content: \"\\f148\";\n}\n.fa-level-down::before {\n  content: \"\\f149\";\n}\n.fa-check-square::before {\n  content: \"\\f14a\";\n}\n.fa-pencil-square::before {\n  content: \"\\f14b\";\n}\n.fa-external-link-square::before {\n  content: \"\\f14c\";\n}\n.fa-share-square::before {\n  content: \"\\f14d\";\n}\n.fa-compass::before {\n  content: \"\\f14e\";\n}\n.fa-toggle-down::before,\n.fa-caret-square-o-down::before {\n  content: \"\\f150\";\n}\n.fa-toggle-up::before,\n.fa-caret-square-o-up::before {\n  content: \"\\f151\";\n}\n.fa-toggle-right::before,\n.fa-caret-square-o-right::before {\n  content: \"\\f152\";\n}\n.fa-euro::before,\n.fa-eur::before {\n  content: \"\\f153\";\n}\n.fa-gbp::before {\n  content: \"\\f154\";\n}\n.fa-dollar::before,\n.fa-usd::before {\n  content: \"\\f155\";\n}\n.fa-rupee::before,\n.fa-inr::before {\n  content: \"\\f156\";\n}\n.fa-cny::before,\n.fa-rmb::before,\n.fa-yen::before,\n.fa-jpy::before {\n  content: \"\\f157\";\n}\n.fa-ruble::before,\n.fa-rouble::before,\n.fa-rub::before {\n  content: \"\\f158\";\n}\n.fa-won::before,\n.fa-krw::before {\n  content: \"\\f159\";\n}\n.fa-bitcoin::before,\n.fa-btc::before {\n  content: \"\\f15a\";\n}\n.fa-file::before {\n  content: \"\\f15b\";\n}\n.fa-file-text::before {\n  content: \"\\f15c\";\n}\n.fa-sort-alpha-asc::before {\n  content: \"\\f15d\";\n}\n.fa-sort-alpha-desc::before {\n  content: \"\\f15e\";\n}\n.fa-sort-amount-asc::before {\n  content: \"\\f160\";\n}\n.fa-sort-amount-desc::before {\n  content: \"\\f161\";\n}\n.fa-sort-numeric-asc::before {\n  content: \"\\f162\";\n}\n.fa-sort-numeric-desc::before {\n  content: \"\\f163\";\n}\n.fa-thumbs-up::before {\n  content: \"\\f164\";\n}\n.fa-thumbs-down::before {\n  content: \"\\f165\";\n}\n.fa-youtube-square::before {\n  content: \"\\f166\";\n}\n.fa-youtube::before {\n  content: \"\\f167\";\n}\n.fa-xing::before {\n  content: \"\\f168\";\n}\n.fa-xing-square::before {\n  content: \"\\f169\";\n}\n.fa-youtube-play::before {\n  content: \"\\f16a\";\n}\n.fa-dropbox::before {\n  content: \"\\f16b\";\n}\n.fa-stack-overflow::before {\n  content: \"\\f16c\";\n}\n.fa-instagram::before {\n  content: \"\\f16d\";\n}\n.fa-flickr::before {\n  content: \"\\f16e\";\n}\n.fa-adn::before {\n  content: \"\\f170\";\n}\n.fa-bitbucket::before {\n  content: \"\\f171\";\n}\n.fa-bitbucket-square::before {\n  content: \"\\f172\";\n}\n.fa-tumblr::before {\n  content: \"\\f173\";\n}\n.fa-tumblr-square::before {\n  content: \"\\f174\";\n}\n.fa-long-arrow-down::before {\n  content: \"\\f175\";\n}\n.fa-long-arrow-up::before {\n  content: \"\\f176\";\n}\n.fa-long-arrow-left::before {\n  content: \"\\f177\";\n}\n.fa-long-arrow-right::before {\n  content: \"\\f178\";\n}\n.fa-apple::before {\n  content: \"\\f179\";\n}\n.fa-windows::before {\n  content: \"\\f17a\";\n}\n.fa-android::before {\n  content: \"\\f17b\";\n}\n.fa-linux::before {\n  content: \"\\f17c\";\n}\n.fa-dribbble::before {\n  content: \"\\f17d\";\n}\n.fa-skype::before {\n  content: \"\\f17e\";\n}\n.fa-foursquare::before {\n  content: \"\\f180\";\n}\n.fa-trello::before {\n  content: \"\\f181\";\n}\n.fa-female::before {\n  content: \"\\f182\";\n}\n.fa-male::before {\n  content: \"\\f183\";\n}\n.fa-gittip::before,\n.fa-gratipay::before {\n  content: \"\\f184\";\n}\n.fa-sun-o::before {\n  content: \"\\f185\";\n}\n.fa-moon-o::before {\n  content: \"\\f186\";\n}\n.fa-archive::before {\n  content: \"\\f187\";\n}\n.fa-bug::before {\n  content: \"\\f188\";\n}\n.fa-vk::before {\n  content: \"\\f189\";\n}\n.fa-weibo::before {\n  content: \"\\f18a\";\n}\n.fa-renren::before {\n  content: \"\\f18b\";\n}\n.fa-pagelines::before {\n  content: \"\\f18c\";\n}\n.fa-stack-exchange::before {\n  content: \"\\f18d\";\n}\n.fa-arrow-circle-o-right::before {\n  content: \"\\f18e\";\n}\n.fa-arrow-circle-o-left::before {\n  content: \"\\f190\";\n}\n.fa-toggle-left::before,\n.fa-caret-square-o-left::before {\n  content: \"\\f191\";\n}\n.fa-dot-circle-o::before {\n  content: \"\\f192\";\n}\n.fa-wheelchair::before {\n  content: \"\\f193\";\n}\n.fa-vimeo-square::before {\n  content: \"\\f194\";\n}\n.fa-turkish-lira::before,\n.fa-try::before {\n  content: \"\\f195\";\n}\n.fa-plus-square-o::before {\n  content: \"\\f196\";\n}\n.fa-space-shuttle::before {\n  content: \"\\f197\";\n}\n.fa-slack::before {\n  content: \"\\f198\";\n}\n.fa-envelope-square::before {\n  content: \"\\f199\";\n}\n.fa-wordpress::before {\n  content: \"\\f19a\";\n}\n.fa-openid::before {\n  content: \"\\f19b\";\n}\n.fa-institution::before,\n.fa-bank::before,\n.fa-university::before {\n  content: \"\\f19c\";\n}\n.fa-mortar-board::before,\n.fa-graduation-cap::before {\n  content: \"\\f19d\";\n}\n.fa-yahoo::before {\n  content: \"\\f19e\";\n}\n.fa-google::before {\n  content: \"\\f1a0\";\n}\n.fa-reddit::before {\n  content: \"\\f1a1\";\n}\n.fa-reddit-square::before {\n  content: \"\\f1a2\";\n}\n.fa-stumbleupon-circle::before {\n  content: \"\\f1a3\";\n}\n.fa-stumbleupon::before {\n  content: \"\\f1a4\";\n}\n.fa-delicious::before {\n  content: \"\\f1a5\";\n}\n.fa-digg::before {\n  content: \"\\f1a6\";\n}\n.fa-pied-piper-pp::before {\n  content: \"\\f1a7\";\n}\n.fa-pied-piper-alt::before {\n  content: \"\\f1a8\";\n}\n.fa-drupal::before {\n  content: \"\\f1a9\";\n}\n.fa-joomla::before {\n  content: \"\\f1aa\";\n}\n.fa-language::before {\n  content: \"\\f1ab\";\n}\n.fa-fax::before {\n  content: \"\\f1ac\";\n}\n.fa-building::before {\n  content: \"\\f1ad\";\n}\n.fa-child::before {\n  content: \"\\f1ae\";\n}\n.fa-paw::before {\n  content: \"\\f1b0\";\n}\n.fa-spoon::before {\n  content: \"\\f1b1\";\n}\n.fa-cube::before {\n  content: \"\\f1b2\";\n}\n.fa-cubes::before {\n  content: \"\\f1b3\";\n}\n.fa-behance::before {\n  content: \"\\f1b4\";\n}\n.fa-behance-square::before {\n  content: \"\\f1b5\";\n}\n.fa-steam::before {\n  content: \"\\f1b6\";\n}\n.fa-steam-square::before {\n  content: \"\\f1b7\";\n}\n.fa-recycle::before {\n  content: \"\\f1b8\";\n}\n.fa-automobile::before,\n.fa-car::before {\n  content: \"\\f1b9\";\n}\n.fa-cab::before,\n.fa-taxi::before {\n  content: \"\\f1ba\";\n}\n.fa-tree::before {\n  content: \"\\f1bb\";\n}\n.fa-spotify::before {\n  content: \"\\f1bc\";\n}\n.fa-deviantart::before {\n  content: \"\\f1bd\";\n}\n.fa-soundcloud::before {\n  content: \"\\f1be\";\n}\n.fa-database::before {\n  content: \"\\f1c0\";\n}\n.fa-file-pdf-o::before {\n  content: \"\\f1c1\";\n}\n.fa-file-word-o::before {\n  content: \"\\f1c2\";\n}\n.fa-file-excel-o::before {\n  content: \"\\f1c3\";\n}\n.fa-file-powerpoint-o::before {\n  content: \"\\f1c4\";\n}\n.fa-file-photo-o::before,\n.fa-file-picture-o::before,\n.fa-file-image-o::before {\n  content: \"\\f1c5\";\n}\n.fa-file-zip-o::before,\n.fa-file-archive-o::before {\n  content: \"\\f1c6\";\n}\n.fa-file-sound-o::before,\n.fa-file-audio-o::before {\n  content: \"\\f1c7\";\n}\n.fa-file-movie-o::before,\n.fa-file-video-o::before {\n  content: \"\\f1c8\";\n}\n.fa-file-code-o::before {\n  content: \"\\f1c9\";\n}\n.fa-vine::before {\n  content: \"\\f1ca\";\n}\n.fa-codepen::before {\n  content: \"\\f1cb\";\n}\n.fa-jsfiddle::before {\n  content: \"\\f1cc\";\n}\n.fa-life-bouy::before,\n.fa-life-buoy::before,\n.fa-life-saver::before,\n.fa-support::before,\n.fa-life-ring::before {\n  content: \"\\f1cd\";\n}\n.fa-circle-o-notch::before {\n  content: \"\\f1ce\";\n}\n.fa-ra::before,\n.fa-resistance::before,\n.fa-rebel::before {\n  content: \"\\f1d0\";\n}\n.fa-ge::before,\n.fa-empire::before {\n  content: \"\\f1d1\";\n}\n.fa-git-square::before {\n  content: \"\\f1d2\";\n}\n.fa-git::before {\n  content: \"\\f1d3\";\n}\n.fa-y-combinator-square::before,\n.fa-yc-square::before,\n.fa-hacker-news::before {\n  content: \"\\f1d4\";\n}\n.fa-tencent-weibo::before {\n  content: \"\\f1d5\";\n}\n.fa-qq::before {\n  content: \"\\f1d6\";\n}\n.fa-wechat::before,\n.fa-weixin::before {\n  content: \"\\f1d7\";\n}\n.fa-send::before,\n.fa-paper-plane::before {\n  content: \"\\f1d8\";\n}\n.fa-send-o::before,\n.fa-paper-plane-o::before {\n  content: \"\\f1d9\";\n}\n.fa-history::before {\n  content: \"\\f1da\";\n}\n.fa-circle-thin::before {\n  content: \"\\f1db\";\n}\n.fa-header::before {\n  content: \"\\f1dc\";\n}\n.fa-paragraph::before {\n  content: \"\\f1dd\";\n}\n.fa-sliders::before {\n  content: \"\\f1de\";\n}\n.fa-share-alt::before {\n  content: \"\\f1e0\";\n}\n.fa-share-alt-square::before {\n  content: \"\\f1e1\";\n}\n.fa-bomb::before {\n  content: \"\\f1e2\";\n}\n.fa-soccer-ball-o::before,\n.fa-futbol-o::before {\n  content: \"\\f1e3\";\n}\n.fa-tty::before {\n  content: \"\\f1e4\";\n}\n.fa-binoculars::before {\n  content: \"\\f1e5\";\n}\n.fa-plug::before {\n  content: \"\\f1e6\";\n}\n.fa-slideshare::before {\n  content: \"\\f1e7\";\n}\n.fa-twitch::before {\n  content: \"\\f1e8\";\n}\n.fa-yelp::before {\n  content: \"\\f1e9\";\n}\n.fa-newspaper-o::before {\n  content: \"\\f1ea\";\n}\n.fa-wifi::before {\n  content: \"\\f1eb\";\n}\n.fa-calculator::before {\n  content: \"\\f1ec\";\n}\n.fa-paypal::before {\n  content: \"\\f1ed\";\n}\n.fa-google-wallet::before {\n  content: \"\\f1ee\";\n}\n.fa-cc-visa::before {\n  content: \"\\f1f0\";\n}\n.fa-cc-mastercard::before {\n  content: \"\\f1f1\";\n}\n.fa-cc-discover::before {\n  content: \"\\f1f2\";\n}\n.fa-cc-amex::before {\n  content: \"\\f1f3\";\n}\n.fa-cc-paypal::before {\n  content: \"\\f1f4\";\n}\n.fa-cc-stripe::before {\n  content: \"\\f1f5\";\n}\n.fa-bell-slash::before {\n  content: \"\\f1f6\";\n}\n.fa-bell-slash-o::before {\n  content: \"\\f1f7\";\n}\n.fa-trash::before {\n  content: \"\\f1f8\";\n}\n.fa-copyright::before {\n  content: \"\\f1f9\";\n}\n.fa-at::before {\n  content: \"\\f1fa\";\n}\n.fa-eyedropper::before {\n  content: \"\\f1fb\";\n}\n.fa-paint-brush::before {\n  content: \"\\f1fc\";\n}\n.fa-birthday-cake::before {\n  content: \"\\f1fd\";\n}\n.fa-area-chart::before {\n  content: \"\\f1fe\";\n}\n.fa-pie-chart::before {\n  content: \"\\f200\";\n}\n.fa-line-chart::before {\n  content: \"\\f201\";\n}\n.fa-lastfm::before {\n  content: \"\\f202\";\n}\n.fa-lastfm-square::before {\n  content: \"\\f203\";\n}\n.fa-toggle-off::before {\n  content: \"\\f204\";\n}\n.fa-toggle-on::before {\n  content: \"\\f205\";\n}\n.fa-bicycle::before {\n  content: \"\\f206\";\n}\n.fa-bus::before {\n  content: \"\\f207\";\n}\n.fa-ioxhost::before {\n  content: \"\\f208\";\n}\n.fa-angellist::before {\n  content: \"\\f209\";\n}\n.fa-cc::before {\n  content: \"\\f20a\";\n}\n.fa-shekel::before,\n.fa-sheqel::before,\n.fa-ils::before {\n  content: \"\\f20b\";\n}\n.fa-meanpath::before {\n  content: \"\\f20c\";\n}\n.fa-buysellads::before {\n  content: \"\\f20d\";\n}\n.fa-connectdevelop::before {\n  content: \"\\f20e\";\n}\n.fa-dashcube::before {\n  content: \"\\f210\";\n}\n.fa-forumbee::before {\n  content: \"\\f211\";\n}\n.fa-leanpub::before {\n  content: \"\\f212\";\n}\n.fa-sellsy::before {\n  content: \"\\f213\";\n}\n.fa-shirtsinbulk::before {\n  content: \"\\f214\";\n}\n.fa-simplybuilt::before {\n  content: \"\\f215\";\n}\n.fa-skyatlas::before {\n  content: \"\\f216\";\n}\n.fa-cart-plus::before {\n  content: \"\\f217\";\n}\n.fa-cart-arrow-down::before {\n  content: \"\\f218\";\n}\n.fa-diamond::before {\n  content: \"\\f219\";\n}\n.fa-ship::before {\n  content: \"\\f21a\";\n}\n.fa-user-secret::before {\n  content: \"\\f21b\";\n}\n.fa-motorcycle::before {\n  content: \"\\f21c\";\n}\n.fa-street-view::before {\n  content: \"\\f21d\";\n}\n.fa-heartbeat::before {\n  content: \"\\f21e\";\n}\n.fa-venus::before {\n  content: \"\\f221\";\n}\n.fa-mars::before {\n  content: \"\\f222\";\n}\n.fa-mercury::before {\n  content: \"\\f223\";\n}\n.fa-intersex::before,\n.fa-transgender::before {\n  content: \"\\f224\";\n}\n.fa-transgender-alt::before {\n  content: \"\\f225\";\n}\n.fa-venus-double::before {\n  content: \"\\f226\";\n}\n.fa-mars-double::before {\n  content: \"\\f227\";\n}\n.fa-venus-mars::before {\n  content: \"\\f228\";\n}\n.fa-mars-stroke::before {\n  content: \"\\f229\";\n}\n.fa-mars-stroke-v::before {\n  content: \"\\f22a\";\n}\n.fa-mars-stroke-h::before {\n  content: \"\\f22b\";\n}\n.fa-neuter::before {\n  content: \"\\f22c\";\n}\n.fa-genderless::before {\n  content: \"\\f22d\";\n}\n.fa-facebook-official::before {\n  content: \"\\f230\";\n}\n.fa-pinterest-p::before {\n  content: \"\\f231\";\n}\n.fa-whatsapp::before {\n  content: \"\\f232\";\n}\n.fa-server::before {\n  content: \"\\f233\";\n}\n.fa-user-plus::before {\n  content: \"\\f234\";\n}\n.fa-user-times::before {\n  content: \"\\f235\";\n}\n.fa-hotel::before,\n.fa-bed::before {\n  content: \"\\f236\";\n}\n.fa-viacoin::before {\n  content: \"\\f237\";\n}\n.fa-train::before {\n  content: \"\\f238\";\n}\n.fa-subway::before {\n  content: \"\\f239\";\n}\n.fa-medium::before {\n  content: \"\\f23a\";\n}\n.fa-yc::before,\n.fa-y-combinator::before {\n  content: \"\\f23b\";\n}\n.fa-optin-monster::before {\n  content: \"\\f23c\";\n}\n.fa-opencart::before {\n  content: \"\\f23d\";\n}\n.fa-expeditedssl::before {\n  content: \"\\f23e\";\n}\n.fa-battery-4::before,\n.fa-battery::before,\n.fa-battery-full::before {\n  content: \"\\f240\";\n}\n.fa-battery-3::before,\n.fa-battery-three-quarters::before {\n  content: \"\\f241\";\n}\n.fa-battery-2::before,\n.fa-battery-half::before {\n  content: \"\\f242\";\n}\n.fa-battery-1::before,\n.fa-battery-quarter::before {\n  content: \"\\f243\";\n}\n.fa-battery-0::before,\n.fa-battery-empty::before {\n  content: \"\\f244\";\n}\n.fa-mouse-pointer::before {\n  content: \"\\f245\";\n}\n.fa-i-cursor::before {\n  content: \"\\f246\";\n}\n.fa-object-group::before {\n  content: \"\\f247\";\n}\n.fa-object-ungroup::before {\n  content: \"\\f248\";\n}\n.fa-sticky-note::before {\n  content: \"\\f249\";\n}\n.fa-sticky-note-o::before {\n  content: \"\\f24a\";\n}\n.fa-cc-jcb::before {\n  content: \"\\f24b\";\n}\n.fa-cc-diners-club::before {\n  content: \"\\f24c\";\n}\n.fa-clone::before {\n  content: \"\\f24d\";\n}\n.fa-balance-scale::before {\n  content: \"\\f24e\";\n}\n.fa-hourglass-o::before {\n  content: \"\\f250\";\n}\n.fa-hourglass-1::before,\n.fa-hourglass-start::before {\n  content: \"\\f251\";\n}\n.fa-hourglass-2::before,\n.fa-hourglass-half::before {\n  content: \"\\f252\";\n}\n.fa-hourglass-3::before,\n.fa-hourglass-end::before {\n  content: \"\\f253\";\n}\n.fa-hourglass::before {\n  content: \"\\f254\";\n}\n.fa-hand-grab-o::before,\n.fa-hand-rock-o::before {\n  content: \"\\f255\";\n}\n.fa-hand-stop-o::before,\n.fa-hand-paper-o::before {\n  content: \"\\f256\";\n}\n.fa-hand-scissors-o::before {\n  content: \"\\f257\";\n}\n.fa-hand-lizard-o::before {\n  content: \"\\f258\";\n}\n.fa-hand-spock-o::before {\n  content: \"\\f259\";\n}\n.fa-hand-pointer-o::before {\n  content: \"\\f25a\";\n}\n.fa-hand-peace-o::before {\n  content: \"\\f25b\";\n}\n.fa-trademark::before {\n  content: \"\\f25c\";\n}\n.fa-registered::before {\n  content: \"\\f25d\";\n}\n.fa-creative-commons::before {\n  content: \"\\f25e\";\n}\n.fa-gg::before {\n  content: \"\\f260\";\n}\n.fa-gg-circle::before {\n  content: \"\\f261\";\n}\n.fa-tripadvisor::before {\n  content: \"\\f262\";\n}\n.fa-odnoklassniki::before {\n  content: \"\\f263\";\n}\n.fa-odnoklassniki-square::before {\n  content: \"\\f264\";\n}\n.fa-get-pocket::before {\n  content: \"\\f265\";\n}\n.fa-wikipedia-w::before {\n  content: \"\\f266\";\n}\n.fa-safari::before {\n  content: \"\\f267\";\n}\n.fa-chrome::before {\n  content: \"\\f268\";\n}\n.fa-firefox::before {\n  content: \"\\f269\";\n}\n.fa-opera::before {\n  content: \"\\f26a\";\n}\n.fa-internet-explorer::before {\n  content: \"\\f26b\";\n}\n.fa-tv::before,\n.fa-television::before {\n  content: \"\\f26c\";\n}\n.fa-contao::before {\n  content: \"\\f26d\";\n}\n.fa-500px::before {\n  content: \"\\f26e\";\n}\n.fa-amazon::before {\n  content: \"\\f270\";\n}\n.fa-calendar-plus-o::before {\n  content: \"\\f271\";\n}\n.fa-calendar-minus-o::before {\n  content: \"\\f272\";\n}\n.fa-calendar-times-o::before {\n  content: \"\\f273\";\n}\n.fa-calendar-check-o::before {\n  content: \"\\f274\";\n}\n.fa-industry::before {\n  content: \"\\f275\";\n}\n.fa-map-pin::before {\n  content: \"\\f276\";\n}\n.fa-map-signs::before {\n  content: \"\\f277\";\n}\n.fa-map-o::before {\n  content: \"\\f278\";\n}\n.fa-map::before {\n  content: \"\\f279\";\n}\n.fa-commenting::before {\n  content: \"\\f27a\";\n}\n.fa-commenting-o::before {\n  content: \"\\f27b\";\n}\n.fa-houzz::before {\n  content: \"\\f27c\";\n}\n.fa-vimeo::before {\n  content: \"\\f27d\";\n}\n.fa-black-tie::before {\n  content: \"\\f27e\";\n}\n.fa-fonticons::before {\n  content: \"\\f280\";\n}\n.fa-reddit-alien::before {\n  content: \"\\f281\";\n}\n.fa-edge::before {\n  content: \"\\f282\";\n}\n.fa-credit-card-alt::before {\n  content: \"\\f283\";\n}\n.fa-codiepie::before {\n  content: \"\\f284\";\n}\n.fa-modx::before {\n  content: \"\\f285\";\n}\n.fa-fort-awesome::before {\n  content: \"\\f286\";\n}\n.fa-usb::before {\n  content: \"\\f287\";\n}\n.fa-product-hunt::before {\n  content: \"\\f288\";\n}\n.fa-mixcloud::before {\n  content: \"\\f289\";\n}\n.fa-scribd::before {\n  content: \"\\f28a\";\n}\n.fa-pause-circle::before {\n  content: \"\\f28b\";\n}\n.fa-pause-circle-o::before {\n  content: \"\\f28c\";\n}\n.fa-stop-circle::before {\n  content: \"\\f28d\";\n}\n.fa-stop-circle-o::before {\n  content: \"\\f28e\";\n}\n.fa-shopping-bag::before {\n  content: \"\\f290\";\n}\n.fa-shopping-basket::before {\n  content: \"\\f291\";\n}\n.fa-hashtag::before {\n  content: \"\\f292\";\n}\n.fa-bluetooth::before {\n  content: \"\\f293\";\n}\n.fa-bluetooth-b::before {\n  content: \"\\f294\";\n}\n.fa-percent::before {\n  content: \"\\f295\";\n}\n.fa-gitlab::before {\n  content: \"\\f296\";\n}\n.fa-wpbeginner::before {\n  content: \"\\f297\";\n}\n.fa-wpforms::before {\n  content: \"\\f298\";\n}\n.fa-envira::before {\n  content: \"\\f299\";\n}\n.fa-universal-access::before {\n  content: \"\\f29a\";\n}\n.fa-wheelchair-alt::before {\n  content: \"\\f29b\";\n}\n.fa-question-circle-o::before {\n  content: \"\\f29c\";\n}\n.fa-blind::before {\n  content: \"\\f29d\";\n}\n.fa-audio-description::before {\n  content: \"\\f29e\";\n}\n.fa-volume-control-phone::before {\n  content: \"\\f2a0\";\n}\n.fa-braille::before {\n  content: \"\\f2a1\";\n}\n.fa-assistive-listening-systems::before {\n  content: \"\\f2a2\";\n}\n.fa-asl-interpreting::before,\n.fa-american-sign-language-interpreting::before {\n  content: \"\\f2a3\";\n}\n.fa-deafness::before,\n.fa-hard-of-hearing::before,\n.fa-deaf::before {\n  content: \"\\f2a4\";\n}\n.fa-glide::before {\n  content: \"\\f2a5\";\n}\n.fa-glide-g::before {\n  content: \"\\f2a6\";\n}\n.fa-signing::before,\n.fa-sign-language::before {\n  content: \"\\f2a7\";\n}\n.fa-low-vision::before {\n  content: \"\\f2a8\";\n}\n.fa-viadeo::before {\n  content: \"\\f2a9\";\n}\n.fa-viadeo-square::before {\n  content: \"\\f2aa\";\n}\n.fa-snapchat::before {\n  content: \"\\f2ab\";\n}\n.fa-snapchat-ghost::before {\n  content: \"\\f2ac\";\n}\n.fa-snapchat-square::before {\n  content: \"\\f2ad\";\n}\n.fa-pied-piper::before {\n  content: \"\\f2ae\";\n}\n.fa-first-order::before {\n  content: \"\\f2b0\";\n}\n.fa-yoast::before {\n  content: \"\\f2b1\";\n}\n.fa-themeisle::before {\n  content: \"\\f2b2\";\n}\n.fa-google-plus-circle::before,\n.fa-google-plus-official::before {\n  content: \"\\f2b3\";\n}\n.fa-fa::before,\n.fa-font-awesome::before {\n  content: \"\\f2b4\";\n}\n.fa-handshake-o::before {\n  content: \"\\f2b5\";\n}\n.fa-envelope-open::before {\n  content: \"\\f2b6\";\n}\n.fa-envelope-open-o::before {\n  content: \"\\f2b7\";\n}\n.fa-linode::before {\n  content: \"\\f2b8\";\n}\n.fa-address-book::before {\n  content: \"\\f2b9\";\n}\n.fa-address-book-o::before {\n  content: \"\\f2ba\";\n}\n.fa-vcard::before,\n.fa-address-card::before {\n  content: \"\\f2bb\";\n}\n.fa-vcard-o::before,\n.fa-address-card-o::before {\n  content: \"\\f2bc\";\n}\n.fa-user-circle::before {\n  content: \"\\f2bd\";\n}\n.fa-user-circle-o::before {\n  content: \"\\f2be\";\n}\n.fa-user-o::before {\n  content: \"\\f2c0\";\n}\n.fa-id-badge::before {\n  content: \"\\f2c1\";\n}\n.fa-drivers-license::before,\n.fa-id-card::before {\n  content: \"\\f2c2\";\n}\n.fa-drivers-license-o::before,\n.fa-id-card-o::before {\n  content: \"\\f2c3\";\n}\n.fa-quora::before {\n  content: \"\\f2c4\";\n}\n.fa-free-code-camp::before {\n  content: \"\\f2c5\";\n}\n.fa-telegram::before {\n  content: \"\\f2c6\";\n}\n.fa-thermometer-4::before,\n.fa-thermometer::before,\n.fa-thermometer-full::before {\n  content: \"\\f2c7\";\n}\n.fa-thermometer-3::before,\n.fa-thermometer-three-quarters::before {\n  content: \"\\f2c8\";\n}\n.fa-thermometer-2::before,\n.fa-thermometer-half::before {\n  content: \"\\f2c9\";\n}\n.fa-thermometer-1::before,\n.fa-thermometer-quarter::before {\n  content: \"\\f2ca\";\n}\n.fa-thermometer-0::before,\n.fa-thermometer-empty::before {\n  content: \"\\f2cb\";\n}\n.fa-shower::before {\n  content: \"\\f2cc\";\n}\n.fa-bathtub::before,\n.fa-s15::before,\n.fa-bath::before {\n  content: \"\\f2cd\";\n}\n.fa-podcast::before {\n  content: \"\\f2ce\";\n}\n.fa-window-maximize::before {\n  content: \"\\f2d0\";\n}\n.fa-window-minimize::before {\n  content: \"\\f2d1\";\n}\n.fa-window-restore::before {\n  content: \"\\f2d2\";\n}\n.fa-times-rectangle::before,\n.fa-window-close::before {\n  content: \"\\f2d3\";\n}\n.fa-times-rectangle-o::before,\n.fa-window-close-o::before {\n  content: \"\\f2d4\";\n}\n.fa-bandcamp::before {\n  content: \"\\f2d5\";\n}\n.fa-grav::before {\n  content: \"\\f2d6\";\n}\n.fa-etsy::before {\n  content: \"\\f2d7\";\n}\n.fa-imdb::before {\n  content: \"\\f2d8\";\n}\n.fa-ravelry::before {\n  content: \"\\f2d9\";\n}\n.fa-eercast::before {\n  content: \"\\f2da\";\n}\n.fa-microchip::before {\n  content: \"\\f2db\";\n}\n.fa-snowflake-o::before {\n  content: \"\\f2dc\";\n}\n.fa-superpowers::before {\n  content: \"\\f2dd\";\n}\n.fa-wpexplorer::before {\n  content: \"\\f2de\";\n}\n.fa-meetup::before {\n  content: \"\\f2e0\";\n}"
  },
  {
    "path": "src/IdentityServer/wwwroot/lib/bootstrap4-glyphicons/maps/glyphicons-fontawesome.less",
    "content": "@font-face {\n    font-family: 'Font Awesome 5 Free';\n    font-style: normal;\n    font-weight: 900;\n    src: url(\"../fonts/fontawesome/fa-solid-900.eot\");\n    src: url(\"../fonts/fontawesome/fa-solid-900.eot?#iefix\") format(\"embedded-opentype\"), url(\"../fonts/fontawesome/fa-solid-900.woff2\") format(\"woff2\"), url(\"../fonts/fontawesome/fa-solid-900.ttf\") format(\"truetype\"), url(\"../fonts/fontawesome/fa-solid-900.svg#fontawesome\") format(\"svg\");\n}\n\n.glyphicon {\n    font-family: 'Font Awesome 5 Free';\n\n    &.glyphicon-chevron-up {\n        .fa-chevron-up();\n    }\n\n    &.glyphicon-chevron-right {\n        .fa-chevron-right();\n    }\n\n    &.glyphicon-chevron-left {\n        .fa-chevron-left();\n    }\n\n    &.glyphicon-asterisk {\n        .fa-asterisk();\n    }\n\n    &.glyphicon-plus {\n        .fa-plus();\n    }\n\n    &.glyphicon-euro,\n    &.glyphicon-eur {\n        .fa-eur();\n    }\n\n    &.glyphicon-minus {\n        .fa-minus();\n    }\n\n    &.glyphicon-cloud {\n        .fa-cloud();\n    }\n\n    &.glyphicon-envelope {\n        .fa-envelope();\n    }\n\n    &.glyphicon-pencil {\n        .fa-pencil();\n    }\n\n    &.glyphicon-glass {\n        .fa-glass();\n    }\n\n    &.glyphicon-music {\n        .fa-music();\n    }\n\n    &.glyphicon-search {\n        .fa-search();\n    }\n\n    &.glyphicon-heart {\n        .fa-heart();\n    }\n\n    &.glyphicon-star {\n        .fa-star();\n    }\n\n    &.glyphicon-star-empty {\n        .fa-star-o();\n    }\n\n    &.glyphicon-user {\n        .fa-user();\n    }\n\n    &.glyphicon-film {\n        .fa-film();\n    }\n\n    &.glyphicon-th-large {\n        .fa-th-large();\n    }\n\n    &.glyphicon-th {\n        .fa-th();\n    }\n\n    &.glyphicon-th-list {\n        .fa-th-list();\n    }\n\n    &.glyphicon-ok {\n        .fa-check();\n    }\n\n    &.glyphicon-remove {\n        .fa-remove();\n    }\n\n    &.glyphicon-zoom-in {\n        .fa-search-plus();\n    }\n\n    &.glyphicon-zoom-out {\n        .fa-search-minus();\n    }\n\n    &.glyphicon-off {\n        .fa-power-off();\n    }\n\n    &.glyphicon-signal {\n        .fa-signal();\n    }\n\n    &.glyphicon-cog {\n        .fa-cog();\n    }\n\n    &.glyphicon-trash {\n        .fa-trash();\n    }\n\n    &.glyphicon-home {\n        .fa-home();\n    }\n\n    &.glyphicon-file {\n        .fa-file();\n    }\n\n    &.glyphicon-time {\n        .fa-clock-o();\n    }\n\n    &.glyphicon-road {\n        .fa-road();\n    }\n\n    &.glyphicon-download-alt {\n        .fa-cloud-download();\n    }\n\n    &.glyphicon-download {\n        .fa-download();\n    }\n\n    &.glyphicon-upload {\n        .fa-upload();\n    }\n\n    &.glyphicon-inbox {\n        .fa-inbox();\n    }\n\n    &.glyphicon-play-circle {\n        .fa-play-circle();\n    }\n\n    &.glyphicon-repeat {\n        .fa-repeat();\n    }\n\n    &.glyphicon-refresh {\n        .fa-refresh();\n    }\n\n    &.glyphicon-list-alt {\n        .fa-list-alt();\n    }\n\n    &.glyphicon-lock {\n        .fa-lock();\n    }\n\n    &.glyphicon-flag {\n        .fa-flag();\n    }\n\n    &.glyphicon-headphones {\n        .fa-headphones();\n    }\n\n    &.glyphicon-volume-off {\n        .fa-volume-off();\n    }\n\n    &.glyphicon-volume-down {\n        .fa-volume-down();\n    }\n\n    &.glyphicon-volume-up {\n        .fa-volume-up();\n    }\n\n    &.glyphicon-qrcode {\n        .fa-qrcode();\n    }\n\n    &.glyphicon-barcode {\n        .fa-barcode();\n    }\n\n    &.glyphicon-tag {\n        .fa-tag();\n    }\n\n    &.glyphicon-tags {\n        .fa-tags();\n    }\n\n    &.glyphicon-book {\n        .fa-book();\n    }\n\n    &.glyphicon-bookmark {\n        .fa-bookmark();\n    }\n\n    &.glyphicon-print {\n        .fa-print();\n    }\n\n    &.glyphicon-camera {\n        .fa-camera();\n    }\n\n    &.glyphicon-font {\n        .fa-font();\n    }\n\n    &.glyphicon-bold {\n        .fa-bold();\n    }\n\n    &.glyphicon-italic {\n        .fa-italic();\n    }\n\n    &.glyphicon-text-height {\n        .fa-text-height();\n    }\n\n    &.glyphicon-text-width {\n        .fa-text-width();\n    }\n\n    &.glyphicon-align-left {\n        .fa-align-left();\n    }\n\n    &.glyphicon-align-center {\n        .fa-align-center();\n    }\n\n    &.glyphicon-align-right {\n        .fa-align-right();\n    }\n\n    &.glyphicon-align-justify {\n        .fa-align-justify();\n    }\n\n    &.glyphicon-list {\n        .fa-list();\n    }\n\n    &.glyphicon-indent-left {\n        .fa-indent();\n    }\n\n    &.glyphicon-indent-right {\n        .fa-outdent();\n    }\n\n    &.glyphicon-facetime-video {\n        .fa-video-camera();\n    }\n\n    &.glyphicon-picture {\n        .fa-picture-o();\n    }\n\n    &.glyphicon-map-marker {\n        .fa-map-marker();\n    }\n\n    &.glyphicon-adjust {\n        .fa-adjust();\n    }\n\n    &.glyphicon-tint {\n        .fa-tint();\n    }\n\n    &.glyphicon-edit {\n        .fa-edit();\n    }\n\n    &.glyphicon-share {\n        .fa-share();\n    }\n\n    &.glyphicon-check {\n        .fa-check();\n    }\n\n    &.glyphicon-move {\n        .fa-arrows();\n    }\n\n    &.glyphicon-step-backward {\n        .fa-step-backward();\n    }\n\n    &.glyphicon-fast-backward {\n        .fa-fast-backward();\n    }\n\n    &.glyphicon-backward {\n        .fa-backward();\n    }\n\n    &.glyphicon-play {\n        .fa-play();\n    }\n\n    &.glyphicon-pause {\n        .fa-pause();\n    }\n\n    &.glyphicon-stop {\n        .fa-stop();\n    }\n\n    &.glyphicon-forward {\n        .fa-forward();\n    }\n\n    &.glyphicon-fast-forward {\n        .fa-fast-forward();\n    }\n\n    &.glyphicon-step-forward {\n        .fa-step-forward();\n    }\n\n    &.glyphicon-eject {\n        .fa-eject();\n    }\n\n    &.glyphicon-chevron-left {\n        .fa-chevron-left();\n    }\n\n    &.glyphicon-chevron-right {\n        .fa-chevron-right();\n    }\n\n    &.glyphicon-plus-sign {\n        .fa-plus-circle();\n    }\n\n    &.glyphicon-minus-sign {\n        .fa-minus-circle();\n    }\n\n    &.glyphicon-remove-sign {\n        .fa-times-circle();\n    }\n\n    &.glyphicon-ok-sign {\n        .fa-check-circle();\n    }\n\n    &.glyphicon-question-sign {\n        .fa-question-circle();\n    }\n\n    &.glyphicon-info-sign {\n        .fa-info-circle();\n    }\n\n    &.glyphicon-screenshot {\n        .fa-crosshairs();\n    }\n\n    &.glyphicon-remove-circle {\n        .fa-times-circle();\n    }\n\n    &.glyphicon-ok-circle {\n        .fa-check-circle();\n    }\n\n    &.glyphicon-ban-circle {\n        .fa-ban();\n    }\n\n    &.glyphicon-arrow-left {\n        .fa-arrow-left();\n    }\n\n    &.glyphicon-arrow-right {\n        .fa-arrow-right();\n    }\n\n    &.glyphicon-arrow-up {\n        .fa-arrow-up();\n    }\n\n    &.glyphicon-arrow-down {\n        .fa-arrow-down();\n    }\n\n    &.glyphicon-share-alt {\n        .fa-share-alt();\n    }\n\n    &.glyphicon-resize-full {\n        .fa-expand();\n    }\n\n    &.glyphicon-resize-small {\n        .fa-compress();\n    }\n\n    &.glyphicon-exclamation-sign {\n        .fa-exclamation-circle();\n    }\n\n    &.glyphicon-gift {\n        .fa-gift();\n    }\n\n    &.glyphicon-leaf {\n        .fa-leaf();\n    }\n\n    &.glyphicon-fire {\n        .fa-fire();\n    }\n\n    &.glyphicon-eye-open {\n        .fa-eye();\n    }\n\n    &.glyphicon-eye-close {\n        .fa-eye-slash();\n    }\n\n    &.glyphicon-warning-sign {\n        .fa-exclamation-triangle();\n    }\n\n    &.glyphicon-plane {\n        .fa-plane();\n    }\n\n    &.glyphicon-calendar {\n        .fa-calendar();\n    }\n\n    &.glyphicon-random {\n        .fa-random();\n    }\n\n    &.glyphicon-comment {\n        .fa-comment();\n    }\n\n    &.glyphicon-magnet {\n        .fa-magnet();\n    }\n\n    &.glyphicon-chevron-up {\n        .fa-chevron-up();\n    }\n\n    &.glyphicon-chevron-down {\n        .fa-chevron-down();\n    }\n\n    &.glyphicon-retweet {\n        .fa-retweet();\n    }\n\n    &.glyphicon-shopping-cart {\n        .fa-shopping-cart();\n    }\n\n    &.glyphicon-folder-close {\n        .fa-folder();\n    }\n\n    &.glyphicon-folder-open {\n        .fa-folder-open();\n    }\n\n    &.glyphicon-resize-vertical {\n        .fa-arrows-v();\n    }\n\n    &.glyphicon-resize-horizontal {\n        .fa-arrows-h();\n    }\n\n    &.glyphicon-hdd {\n        .fa-hdd-o();\n    }\n\n    &.glyphicon-bullhorn {\n        .fa-bullhorn();\n    }\n\n    &.glyphicon-bell {\n        .fa-bell();\n    }\n\n    &.glyphicon-certificate {\n        .fa-certificate();\n    }\n\n    &.glyphicon-thumbs-up {\n        .fa-thumbs-up();\n    }\n\n    &.glyphicon-thumbs-down {\n        .fa-thumbs-down();\n    }\n\n    &.glyphicon-hand-right {\n        .fa-hand-o-right();\n    }\n\n    &.glyphicon-hand-left {\n        .fa-hand-o-left();\n    }\n\n    &.glyphicon-hand-up {\n        .fa-hand-o-up();\n    }\n\n    &.glyphicon-hand-down {\n        .fa-hand-o-down();\n    }\n\n    &.glyphicon-circle-arrow-right {\n        .fa-arrow-circle-right();\n    }\n\n    &.glyphicon-circle-arrow-left {\n        .fa-arrow-circle-left();\n    }\n\n    &.glyphicon-circle-arrow-up {\n        .fa-arrow-circle-up();\n    }\n\n    &.glyphicon-circle-arrow-down {\n        .fa-arrow-circle-down();\n    }\n\n    &.glyphicon-globe {\n        .fa-globe();\n    }\n\n    &.glyphicon-wrench {\n        .fa-wrench();\n    }\n\n    &.glyphicon-tasks {\n        .fa-tasks();\n    }\n\n    &.glyphicon-filter {\n        .fa-filter();\n    }\n\n    &.glyphicon-briefcase {\n        .fa-briefcase();\n    }\n\n    &.glyphicon-fullscreen {\n        .fa-expand();\n    }\n\n    &.glyphicon-dashboard {\n        .fa-dashboard();\n    }\n\n    &.glyphicon-paperclip {\n        .fa-paperclip();\n    }\n\n    &.glyphicon-heart-empty {\n        .fa-heart-o();\n    }\n\n    &.glyphicon-link {\n        .fa-link();\n    }\n\n    &.glyphicon-phone {\n        .fa-phone();\n    }\n\n    &.glyphicon-pushpin {\n        .fa-thumb-tack();\n    }\n\n    &.glyphicon-usd {\n        .fa-usd();\n    }\n\n    &.glyphicon-gbp {\n        .fa-gbp();\n    }\n\n    &.glyphicon-sort {\n        .fa-sort();\n    }\n\n    &.glyphicon-sort-by-alphabet {\n        .fa-sort-alpha-asc();\n    }\n\n    &.glyphicon-sort-by-alphabet-alt {\n        .fa-sort-alpha-desc();\n    }\n\n    &.glyphicon-sort-by-order {\n        .fa-sort-numeric-asc();\n    }\n\n    &.glyphicon-sort-by-order-alt {\n        .fa-sort-numeric-desc();\n    }\n\n    &.glyphicon-sort-by-attributes {\n        .fa-sort-amount-asc();\n    }\n\n    &.glyphicon-sort-by-attributes-alt {\n        .fa-sort-amount-desc();\n    }\n\n    &.glyphicon-unchecked {\n        .fa-square-o();\n    }\n\n    &.glyphicon-expand {\n        .fa-caret-square-o-right();\n    }\n\n    &.glyphicon-collapse-down {\n        .fa-caret-square-o-down();\n    }\n\n    &.glyphicon-collapse-up {\n        .fa-caret-square-o-up();\n    }\n\n    &.glyphicon-log-in {\n        .fa-sign-in();\n    }\n\n    &.glyphicon-flash {\n        .fa-flash();\n    }\n\n    &.glyphicon-log-out {\n        .fa-sign-out();\n    }\n\n    &.glyphicon-new-window {\n        .fa-external-link();\n    }\n\n    &.glyphicon-record {\n        .fa-dot-circle-o();\n    }\n\n    &.glyphicon-save {\n        .fa-save();\n    }\n\n    &.glyphicon-open {\n        .fa-upload();\n    }\n\n    &.glyphicon-saved {\n        .fa-check();\n    }\n\n    &.glyphicon-import {\n        .fa-upload();\n    }\n\n    &.glyphicon-export {\n        .fa-download();\n    }\n\n    &.glyphicon-send {\n        .fa-paper-plane-o();\n    }\n\n    &.glyphicon-floppy-disk {\n        .fa-save();\n    }\n\n    &.glyphicon-floppy-saved {\n        .fa-check();\n    }\n\n    &.glyphicon-floppy-remove {\n        .fa-remove();\n    }\n\n    &.glyphicon-floppy-save {\n        .fa-download();\n    }\n\n    &.glyphicon-floppy-open {\n        .fa-upload();\n    }\n\n    &.glyphicon-credit-card {\n        .fa-credit-card();\n    }\n\n    &.glyphicon-transfer {\n        .fa-exchange();\n    }\n\n    &.glyphicon-cutlery {\n        .fa-cutlery();\n    }\n\n    &.glyphicon-header {\n        .fa-header();\n    }\n\n    &.glyphicon-compressed {\n        .fa-file-archive-o();\n    }\n\n    &.glyphicon-earphone {\n        .fa-phone();\n    }\n\n    &.glyphicon-phone-alt {\n        .fa-phone-square();\n    }\n\n    &.glyphicon-tower {\n        .fa-building();\n    }\n\n    &.glyphicon-stats {\n        .fa-bar-chart();\n    }\n\n    &.glyphicon-sd-video {\n        .fa-film();\n    }\n\n    &.glyphicon-hd-video {\n        .fa-film();\n    }\n\n    &.glyphicon-subtitles {\n        .fa-cc();\n    }\n\n    &.glyphicon-sound-stereo {\n        .fa-music();\n    }\n\n    &.glyphicon-sound-dolby {\n        .fa-music();\n    }\n\n    &.glyphicon-sound-5-1 {\n        .fa-music();\n    }\n\n    &.glyphicon-sound-6-1 {\n        .fa-music();\n    }\n\n    &.glyphicon-sound-7-1 {\n        .fa-music();\n    }\n\n    &.glyphicon-copyright-mark {\n        .fa-copyright();\n    }\n\n    &.glyphicon-registration-mark {\n        .fa-registered();\n    }\n\n    &.glyphicon-cloud-download {\n        .fa-cloud-download();\n    }\n\n    &.glyphicon-cloud-upload {\n        .fa-cloud-upload();\n    }\n\n    &.glyphicon-tree-conifer {\n        .fa-tree();\n    }\n\n    &.glyphicon-tree-deciduous {\n        .fa-tree();\n    }\n\n    &.glyphicon-cd {\n        .fa-dot-circle-o();\n    }\n\n    &.glyphicon-save-file {\n        .fa-save();\n    }\n\n    &.glyphicon-open-file {\n        .fa-folder-open-o();\n    }\n\n    &.glyphicon-level-up {\n        .fa-level-up();\n    }\n\n    &.glyphicon-copy {\n        .fa-copy();\n    }\n\n    &.glyphicon-paste {\n        .fa-paste();\n    }\n\n    &.glyphicon-alert {\n        .fa-exclamation-triangle();\n    }\n\n    &.glyphicon-equalizer {\n        .fa-bar-chart();\n    }\n\n    &.glyphicon-king {\n        .fa-question();\n    }\n\n    &.glyphicon-queen {\n        .fa-question();\n    }\n\n    &.glyphicon-pawn {\n        .fa-question();\n    }\n\n    &.glyphicon-bishop {\n        .fa-question();\n    }\n\n    &.glyphicon-knight {\n        .fa-question();\n    }\n\n    &.glyphicon-baby-formula {\n        .fa-question();\n    }\n\n    &.glyphicon-tent {\n        .fa-question();\n    }\n\n    &.glyphicon-blackboard {\n        .fa-question();\n    }\n\n    &.glyphicon-bed {\n        .fa-bed();\n    }\n\n    &.glyphicon-apple {\n        .fa-apple();\n    }\n\n    &.glyphicon-erase {\n        .fa-eraser();\n    }\n\n    &.glyphicon-hourglass {\n        .fa-hourglass();\n    }\n\n    &.glyphicon-lamp {\n        .fa-lightbulb-o();\n    }\n\n    &.glyphicon-duplicate {\n        .fa-files-o();\n    }\n\n    &.glyphicon-piggy-bank {\n        .fa-money();\n    }\n\n    &.glyphicon-scissors {\n        .fa-scissors();\n    }\n\n    &.glyphicon-bitcoin {\n        .fa-bitcoin();\n    }\n\n    &.glyphicon-btc {\n        .fa-btc();\n    }\n\n    &.glyphicon-xbt {\n        .fa-btc();\n    }\n\n    &.glyphicon-yen {\n        .fa-yen();\n    }\n\n    &.glyphicon-jpy {\n        .fa-jpy();\n    }\n\n    &.glyphicon-ruble {\n        .fa-ruble();\n    }\n\n    &.glyphicon-rub {\n        .fa-rub();\n    }\n\n    &.glyphicon-scale {\n        .fa-balance-scale();\n    }\n\n    &.glyphicon-ice-lolly {\n        .fa-question();\n    }\n\n    &.glyphicon-ice-lolly-tasted {\n        .fa-question();\n    }\n\n    &.glyphicon-education {\n        .fa-graduation-cap();\n    }\n\n    &.glyphicon-option-horizontal {\n        .fa-ellipsis-h();\n    }\n\n    &.glyphicon-option-vertical {\n        .fa-ellipsis-v();\n    }\n\n    &.glyphicon-menu-hamburger {\n        .fa-bars();\n    }\n\n    &.glyphicon-modal-window {\n        .fa-question();\n    }\n\n    &.glyphicon-oil {\n        .fa-question();\n    }\n\n    &.glyphicon-grain {\n        .fa-question();\n    }\n\n    &.glyphicon-sunglasses {\n        .fa-question();\n    }\n\n    &.glyphicon-text-size {\n        .fa-font();\n    }\n\n    &.glyphicon-text-color {\n        .fa-font();\n    }\n\n    &.glyphicon-text-background {\n        .fa-font();\n    }\n\n    &.glyphicon-object-align-top {\n        .fa-question();\n    }\n\n    &.glyphicon-object-align-bottom {\n        .fa-question();\n    }\n\n    &.glyphicon-object-align-horizontal {\n        .fa-question();\n    }\n\n    &.glyphicon-object-align-left {\n        .fa-question();\n    }\n\n    &.glyphicon-object-align-vertical {\n        .fa-question();\n    }\n\n    &.glyphicon-object-align-right {\n        .fa-question();\n    }\n\n    &.glyphicon-triangle-right {\n        .fa-caret-right();\n    }\n\n    &.glyphicon-triangle-left {\n        .fa-caret-left();\n    }\n\n    &.glyphicon-triangle-bottom {\n        .fa-caret-down();\n    }\n\n    &.glyphicon-triangle-top {\n        .fa-caret-up();\n    }\n\n    &.glyphicon-console {\n        .fa-terminal();\n    }\n\n    &.glyphicon-superscript {\n        .fa-superscript();\n    }\n\n    &.glyphicon-subscript {\n        .fa-subscript();\n    }\n\n    &.glyphicon-menu-left {\n        .fa-chevron-left();\n    }\n\n    &.glyphicon-menu-right {\n        .fa-chevron-right();\n    }\n\n    &.glyphicon-menu-down {\n        .fa-chevron-down();\n    }\n\n    &.glyphicon-menu-up {\n        .fa-chevron-up();\n    }\n\n    &.glyphicon-transfer {\n        .fa-exchange();\n    }\n}\n\n\n/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen\n   readers do not read off random characters that represent icons */\n.fa-glass{\n  &::before{\n    content: \"\\f000\";}\n}\n.fa-music{\n  &::before{\n    content: \"\\f001\";}\n}\n.fa-search{\n  &::before{\n    content: \"\\f002\";}\n}\n.fa-envelope-o{\n  &::before{\n    content: \"\\f003\";}\n}\n.fa-heart{\n  &::before{\n    content: \"\\f004\";}\n}\n.fa-star{\n  &::before{\n    content: \"\\f005\";}\n}\n.fa-star-o{\n  &::before{\n    content: \"\\f006\";}\n}\n.fa-user{\n  &::before{\n    content: \"\\f007\";}\n}\n.fa-film{\n  &::before{\n    content: \"\\f008\";}\n}\n.fa-th-large{\n  &::before{\n    content: \"\\f009\";}\n}\n.fa-th{\n  &::before{\n    content: \"\\f00a\";}\n}\n.fa-th-list{\n  &::before{\n    content: \"\\f00b\";}\n}\n.fa-check{\n  &::before{\n    content: \"\\f00c\";}\n}\n.fa-remove,\n.fa-close,\n.fa-times{\n  &::before{\n    content: \"\\f00d\";}\n}\n.fa-search-plus{\n  &::before{\n    content: \"\\f00e\";}\n}\n.fa-search-minus{\n  &::before{\n    content: \"\\f010\";}\n}\n.fa-power-off{\n  &::before{\n    content: \"\\f011\";}\n}\n.fa-signal{\n  &::before{\n    content: \"\\f012\";}\n}\n.fa-gear,\n.fa-cog{\n  &::before{\n    content: \"\\f013\";}\n}\n.fa-trash-o{\n  &::before{\n    content: \"\\f014\";}\n}\n.fa-home{\n  &::before{\n    content: \"\\f015\";}\n}\n.fa-file-o{\n  &::before{\n    content: \"\\f016\";}\n}\n.fa-clock-o{\n  &::before{\n    content: \"\\f017\";}\n}\n.fa-road{\n  &::before{\n    content: \"\\f018\";}\n}\n.fa-download{\n  &::before{\n    content: \"\\f019\";}\n}\n.fa-arrow-circle-o-down{\n  &::before{\n    content: \"\\f01a\";}\n}\n.fa-arrow-circle-o-up{\n  &::before{\n    content: \"\\f01b\";}\n}\n.fa-inbox{\n  &::before{\n    content: \"\\f01c\";}\n}\n.fa-play-circle-o{\n  &::before{\n    content: \"\\f01d\";}\n}\n.fa-rotate-right,\n.fa-repeat{\n  &::before{\n    content: \"\\f01e\";}\n}\n.fa-refresh{\n  &::before{\n    content: \"\\f021\";}\n}\n.fa-list-alt{\n  &::before{\n    content: \"\\f022\";}\n}\n.fa-lock{\n  &::before{\n    content: \"\\f023\";}\n}\n.fa-flag{\n  &::before{\n    content: \"\\f024\";}\n}\n.fa-headphones{\n  &::before{\n    content: \"\\f025\";}\n}\n.fa-volume-off{\n  &::before{\n    content: \"\\f026\";}\n}\n.fa-volume-down{\n  &::before{\n    content: \"\\f027\";}\n}\n.fa-volume-up{\n  &::before{\n    content: \"\\f028\";}\n}\n.fa-qrcode{\n  &::before{\n    content: \"\\f029\";}\n}\n.fa-barcode{\n  &::before{\n    content: \"\\f02a\";}\n}\n.fa-tag{\n  &::before{\n    content: \"\\f02b\";}\n}\n.fa-tags{\n  &::before{\n    content: \"\\f02c\";}\n}\n.fa-book{\n  &::before{\n    content: \"\\f02d\";}\n}\n.fa-bookmark{\n  &::before{\n    content: \"\\f02e\";}\n}\n.fa-print{\n  &::before{\n    content: \"\\f02f\";}\n}\n.fa-camera{\n  &::before{\n    content: \"\\f030\";}\n}\n.fa-font{\n  &::before{\n    content: \"\\f031\";}\n}\n.fa-bold{\n  &::before{\n    content: \"\\f032\";}\n}\n.fa-italic{\n  &::before{\n    content: \"\\f033\";}\n}\n.fa-text-height{\n  &::before{\n    content: \"\\f034\";}\n}\n.fa-text-width{\n  &::before{\n    content: \"\\f035\";}\n}\n.fa-align-left{\n  &::before{\n    content: \"\\f036\";}\n}\n.fa-align-center{\n  &::before{\n    content: \"\\f037\";}\n}\n.fa-align-right{\n  &::before{\n    content: \"\\f038\";}\n}\n.fa-align-justify{\n  &::before{\n    content: \"\\f039\";}\n}\n.fa-list{\n  &::before{\n    content: \"\\f03a\";}\n}\n.fa-dedent,\n.fa-outdent{\n  &::before{\n    content: \"\\f03b\";}\n}\n.fa-indent{\n  &::before{\n    content: \"\\f03c\";}\n}\n.fa-video-camera{\n  &::before{\n    content: \"\\f03d\";}\n}\n.fa-photo,\n.fa-image,\n.fa-picture-o{\n  &::before{\n    content: \"\\f03e\";}\n}\n.fa-pencil{\n  &::before{\n    content: \"\\f040\";}\n}\n.fa-map-marker{\n  &::before{\n    content: \"\\f041\";}\n}\n.fa-adjust{\n  &::before{\n    content: \"\\f042\";}\n}\n.fa-tint{\n  &::before{\n    content: \"\\f043\";}\n}\n.fa-edit,\n.fa-pencil-square-o{\n  &::before{\n    content: \"\\f044\";}\n}\n.fa-share-square-o{\n  &::before{\n    content: \"\\f045\";}\n}\n.fa-check-square-o{\n  &::before{\n    content: \"\\f046\";}\n}\n.fa-arrows{\n  &::before{\n    content: \"\\f047\";}\n}\n.fa-step-backward{\n  &::before{\n    content: \"\\f048\";}\n}\n.fa-fast-backward{\n  &::before{\n    content: \"\\f049\";}\n}\n.fa-backward{\n  &::before{\n    content: \"\\f04a\";}\n}\n.fa-play{\n  &::before{\n    content: \"\\f04b\";}\n}\n.fa-pause{\n  &::before{\n    content: \"\\f04c\";}\n}\n.fa-stop{\n  &::before{\n    content: \"\\f04d\";}\n}\n.fa-forward{\n  &::before{\n    content: \"\\f04e\";}\n}\n.fa-fast-forward{\n  &::before{\n    content: \"\\f050\";}\n}\n.fa-step-forward{\n  &::before{\n    content: \"\\f051\";}\n}\n.fa-eject{\n  &::before{\n    content: \"\\f052\";}\n}\n.fa-chevron-left{\n  &::before{\n    content: \"\\f053\";}\n}\n.fa-chevron-right{\n  &::before{\n    content: \"\\f054\";}\n}\n.fa-plus-circle{\n  &::before{\n    content: \"\\f055\";}\n}\n.fa-minus-circle{\n  &::before{\n    content: \"\\f056\";}\n}\n.fa-times-circle{\n  &::before{\n    content: \"\\f057\";}\n}\n.fa-check-circle{\n  &::before{\n    content: \"\\f058\";}\n}\n.fa-question-circle{\n  &::before{\n    content: \"\\f059\";}\n}\n.fa-info-circle{\n  &::before{\n    content: \"\\f05a\";}\n}\n.fa-crosshairs{\n  &::before{\n    content: \"\\f05b\";}\n}\n.fa-times-circle-o{\n  &::before{\n    content: \"\\f05c\";}\n}\n.fa-check-circle-o{\n  &::before{\n    content: \"\\f05d\";}\n}\n.fa-ban{\n  &::before{\n    content: \"\\f05e\";}\n}\n.fa-arrow-left{\n  &::before{\n    content: \"\\f060\";}\n}\n.fa-arrow-right{\n  &::before{\n    content: \"\\f061\";}\n}\n.fa-arrow-up{\n  &::before{\n    content: \"\\f062\";}\n}\n.fa-arrow-down{\n  &::before{\n    content: \"\\f063\";}\n}\n.fa-mail-forward,\n.fa-share{\n  &::before{\n    content: \"\\f064\";}\n}\n.fa-expand{\n  &::before{\n    content: \"\\f065\";}\n}\n.fa-compress{\n  &::before{\n    content: \"\\f066\";}\n}\n.fa-plus{\n  &::before{\n    content: \"\\f067\";}\n}\n.fa-minus{\n  &::before{\n    content: \"\\f068\";}\n}\n.fa-asterisk{\n  &::before{\n    content: \"\\f069\";}\n}\n.fa-exclamation-circle{\n  &::before{\n    content: \"\\f06a\";}\n}\n.fa-gift{\n  &::before{\n    content: \"\\f06b\";}\n}\n.fa-leaf{\n  &::before{\n    content: \"\\f06c\";}\n}\n.fa-fire{\n  &::before{\n    content: \"\\f06d\";}\n}\n.fa-eye{\n  &::before{\n    content: \"\\f06e\";}\n}\n.fa-eye-slash{\n  &::before{\n    content: \"\\f070\";}\n}\n.fa-warning,\n.fa-exclamation-triangle{\n  &::before{\n    content: \"\\f071\";}\n}\n.fa-plane{\n  &::before{\n    content: \"\\f072\";}\n}\n.fa-calendar{\n  &::before{\n    content: \"\\f073\";}\n}\n.fa-random{\n  &::before{\n    content: \"\\f074\";}\n}\n.fa-comment{\n  &::before{\n    content: \"\\f075\";}\n}\n.fa-magnet{\n  &::before{\n    content: \"\\f076\";}\n}\n.fa-chevron-up{\n  &::before{\n    content: \"\\f077\";}\n}\n.fa-chevron-down{\n  &::before{\n    content: \"\\f078\";}\n}\n.fa-retweet{\n  &::before{\n    content: \"\\f079\";}\n}\n.fa-shopping-cart{\n  &::before{\n    content: \"\\f07a\";}\n}\n.fa-folder{\n  &::before{\n    content: \"\\f07b\";}\n}\n.fa-folder-open{\n  &::before{\n    content: \"\\f07c\";}\n}\n.fa-arrows-v{\n  &::before{\n    content: \"\\f07d\";}\n}\n.fa-arrows-h{\n  &::before{\n    content: \"\\f07e\";}\n}\n.fa-bar-chart-o,\n.fa-bar-chart{\n  &::before{\n    content: \"\\f080\";}\n}\n.fa-twitter-square{\n  &::before{\n    content: \"\\f081\";}\n}\n.fa-facebook-square{\n  &::before{\n    content: \"\\f082\";}\n}\n.fa-camera-retro{\n  &::before{\n    content: \"\\f083\";}\n}\n.fa-key{\n  &::before{\n    content: \"\\f084\";}\n}\n.fa-gears,\n.fa-cogs{\n  &::before{\n    content: \"\\f085\";}\n}\n.fa-comments{\n  &::before{\n    content: \"\\f086\";}\n}\n.fa-thumbs-o-up{\n  &::before{\n    content: \"\\f087\";}\n}\n.fa-thumbs-o-down{\n  &::before{\n    content: \"\\f088\";}\n}\n.fa-star-half{\n  &::before{\n    content: \"\\f089\";}\n}\n.fa-heart-o{\n  &::before{\n    content: \"\\f08a\";}\n}\n.fa-sign-out{\n  &::before{\n    content: \"\\f08b\";}\n}\n.fa-linkedin-square{\n  &::before{\n    content: \"\\f08c\";}\n}\n.fa-thumb-tack{\n  &::before{\n    content: \"\\f08d\";}\n}\n.fa-external-link{\n  &::before{\n    content: \"\\f08e\";}\n}\n.fa-sign-in{\n  &::before{\n    content: \"\\f090\";}\n}\n.fa-trophy{\n  &::before{\n    content: \"\\f091\";}\n}\n.fa-github-square{\n  &::before{\n    content: \"\\f092\";}\n}\n.fa-upload{\n  &::before{\n    content: \"\\f093\";}\n}\n.fa-lemon-o{\n  &::before{\n    content: \"\\f094\";}\n}\n.fa-phone{\n  &::before{\n    content: \"\\f095\";}\n}\n.fa-square-o{\n  &::before{\n    content: \"\\f096\";}\n}\n.fa-bookmark-o{\n  &::before{\n    content: \"\\f097\";}\n}\n.fa-phone-square{\n  &::before{\n    content: \"\\f098\";}\n}\n.fa-twitter{\n  &::before{\n    content: \"\\f099\";}\n}\n.fa-facebook-f,\n.fa-facebook{\n  &::before{\n    content: \"\\f09a\";}\n}\n.fa-github{\n  &::before{\n    content: \"\\f09b\";}\n}\n.fa-unlock{\n  &::before{\n    content: \"\\f09c\";}\n}\n.fa-credit-card{\n  &::before{\n    content: \"\\f09d\";}\n}\n.fa-feed,\n.fa-rss{\n  &::before{\n    content: \"\\f09e\";}\n}\n.fa-hdd-o{\n  &::before{\n    content: \"\\f0a0\";}\n}\n.fa-bullhorn{\n  &::before{\n    content: \"\\f0a1\";}\n}\n.fa-bell{\n  &::before{\n    content: \"\\f0f3\";}\n}\n.fa-certificate{\n  &::before{\n    content: \"\\f0a3\";}\n}\n.fa-hand-o-right{\n  &::before{\n    content: \"\\f0a4\";}\n}\n.fa-hand-o-left{\n  &::before{\n    content: \"\\f0a5\";}\n}\n.fa-hand-o-up{\n  &::before{\n    content: \"\\f0a6\";}\n}\n.fa-hand-o-down{\n  &::before{\n    content: \"\\f0a7\";}\n}\n.fa-arrow-circle-left{\n  &::before{\n    content: \"\\f0a8\";}\n}\n.fa-arrow-circle-right{\n  &::before{\n    content: \"\\f0a9\";}\n}\n.fa-arrow-circle-up{\n  &::before{\n    content: \"\\f0aa\";}\n}\n.fa-arrow-circle-down{\n  &::before{\n    content: \"\\f0ab\";}\n}\n.fa-globe{\n  &::before{\n    content: \"\\f0ac\";}\n}\n.fa-wrench{\n  &::before{\n    content: \"\\f0ad\";}\n}\n.fa-tasks{\n  &::before{\n    content: \"\\f0ae\";}\n}\n.fa-filter{\n  &::before{\n    content: \"\\f0b0\";}\n}\n.fa-briefcase{\n  &::before{\n    content: \"\\f0b1\";}\n}\n.fa-arrows-alt{\n  &::before{\n    content: \"\\f0b2\";}\n}\n.fa-group,\n.fa-users{\n  &::before{\n    content: \"\\f0c0\";}\n}\n.fa-chain,\n.fa-link{\n  &::before{\n    content: \"\\f0c1\";}\n}\n.fa-cloud{\n  &::before{\n    content: \"\\f0c2\";}\n}\n.fa-flask{\n  &::before{\n    content: \"\\f0c3\";}\n}\n.fa-cut,\n.fa-scissors{\n  &::before{\n    content: \"\\f0c4\";}\n}\n.fa-copy,\n.fa-files-o{\n  &::before{\n    content: \"\\f0c5\";}\n}\n.fa-paperclip{\n  &::before{\n    content: \"\\f0c6\";}\n}\n.fa-save,\n.fa-floppy-o{\n  &::before{\n    content: \"\\f0c7\";}\n}\n.fa-square{\n  &::before{\n    content: \"\\f0c8\";}\n}\n.fa-navicon,\n.fa-reorder,\n.fa-bars{\n  &::before{\n    content: \"\\f0c9\";}\n}\n.fa-list-ul{\n  &::before{\n    content: \"\\f0ca\";}\n}\n.fa-list-ol{\n  &::before{\n    content: \"\\f0cb\";}\n}\n.fa-strikethrough{\n  &::before{\n    content: \"\\f0cc\";}\n}\n.fa-underline{\n  &::before{\n    content: \"\\f0cd\";}\n}\n.fa-table{\n  &::before{\n    content: \"\\f0ce\";}\n}\n.fa-magic{\n  &::before{\n    content: \"\\f0d0\";}\n}\n.fa-truck{\n  &::before{\n    content: \"\\f0d1\";}\n}\n.fa-pinterest{\n  &::before{\n    content: \"\\f0d2\";}\n}\n.fa-pinterest-square{\n  &::before{\n    content: \"\\f0d3\";}\n}\n.fa-google-plus-square{\n  &::before{\n    content: \"\\f0d4\";}\n}\n.fa-google-plus{\n  &::before{\n    content: \"\\f0d5\";}\n}\n.fa-money{\n  &::before{\n    content: \"\\f0d6\";}\n}\n.fa-caret-down{\n  &::before{\n    content: \"\\f0d7\";}\n}\n.fa-caret-up{\n  &::before{\n    content: \"\\f0d8\";}\n}\n.fa-caret-left{\n  &::before{\n    content: \"\\f0d9\";}\n}\n.fa-caret-right{\n  &::before{\n    content: \"\\f0da\";}\n}\n.fa-columns{\n  &::before{\n    content: \"\\f0db\";}\n}\n.fa-unsorted,\n.fa-sort{\n  &::before{\n    content: \"\\f0dc\";}\n}\n.fa-sort-down,\n.fa-sort-desc{\n  &::before{\n    content: \"\\f0dd\";}\n}\n.fa-sort-up,\n.fa-sort-asc{\n  &::before{\n    content: \"\\f0de\";}\n}\n.fa-envelope{\n  &::before{\n    content: \"\\f0e0\";}\n}\n.fa-linkedin{\n  &::before{\n    content: \"\\f0e1\";}\n}\n.fa-rotate-left,\n.fa-undo{\n  &::before{\n    content: \"\\f0e2\";}\n}\n.fa-legal,\n.fa-gavel{\n  &::before{\n    content: \"\\f0e3\";}\n}\n.fa-dashboard,\n.fa-tachometer{\n  &::before{\n    content: \"\\f0e4\";}\n}\n.fa-comment-o{\n  &::before{\n    content: \"\\f0e5\";}\n}\n.fa-comments-o{\n  &::before{\n    content: \"\\f0e6\";}\n}\n.fa-flash,\n.fa-bolt{\n  &::before{\n    content: \"\\f0e7\";}\n}\n.fa-sitemap{\n  &::before{\n    content: \"\\f0e8\";}\n}\n.fa-umbrella{\n  &::before{\n    content: \"\\f0e9\";}\n}\n.fa-paste,\n.fa-clipboard{\n  &::before{\n    content: \"\\f0ea\";}\n}\n.fa-lightbulb-o{\n  &::before{\n    content: \"\\f0eb\";}\n}\n.fa-exchange{\n  &::before{\n    content: \"\\f0ec\";}\n}\n.fa-cloud-download{\n  &::before{\n    content: \"\\f0ed\";}\n}\n.fa-cloud-upload{\n  &::before{\n    content: \"\\f0ee\";}\n}\n.fa-user-md{\n  &::before{\n    content: \"\\f0f0\";}\n}\n.fa-stethoscope{\n  &::before{\n    content: \"\\f0f1\";}\n}\n.fa-suitcase{\n  &::before{\n    content: \"\\f0f2\";}\n}\n.fa-bell-o{\n  &::before{\n    content: \"\\f0a2\";}\n}\n.fa-coffee{\n  &::before{\n    content: \"\\f0f4\";}\n}\n.fa-cutlery{\n  &::before{\n    content: \"\\f0f5\";}\n}\n.fa-file-text-o{\n  &::before{\n    content: \"\\f0f6\";}\n}\n.fa-building-o{\n  &::before{\n    content: \"\\f0f7\";}\n}\n.fa-hospital-o{\n  &::before{\n    content: \"\\f0f8\";}\n}\n.fa-ambulance{\n  &::before{\n    content: \"\\f0f9\";}\n}\n.fa-medkit{\n  &::before{\n    content: \"\\f0fa\";}\n}\n.fa-fighter-jet{\n  &::before{\n    content: \"\\f0fb\";}\n}\n.fa-beer{\n  &::before{\n    content: \"\\f0fc\";}\n}\n.fa-h-square{\n  &::before{\n    content: \"\\f0fd\";}\n}\n.fa-plus-square{\n  &::before{\n    content: \"\\f0fe\";}\n}\n.fa-angle-double-left{\n  &::before{\n    content: \"\\f100\";}\n}\n.fa-angle-double-right{\n  &::before{\n    content: \"\\f101\";}\n}\n.fa-angle-double-up{\n  &::before{\n    content: \"\\f102\";}\n}\n.fa-angle-double-down{\n  &::before{\n    content: \"\\f103\";}\n}\n.fa-angle-left{\n  &::before{\n    content: \"\\f104\";}\n}\n.fa-angle-right{\n  &::before{\n    content: \"\\f105\";}\n}\n.fa-angle-up{\n  &::before{\n    content: \"\\f106\";}\n}\n.fa-angle-down{\n  &::before{\n    content: \"\\f107\";}\n}\n.fa-desktop{\n  &::before{\n    content: \"\\f108\";}\n}\n.fa-laptop{\n  &::before{\n    content: \"\\f109\";}\n}\n.fa-tablet{\n  &::before{\n    content: \"\\f10a\";}\n}\n.fa-mobile-phone,\n.fa-mobile{\n  &::before{\n    content: \"\\f10b\";}\n}\n.fa-circle-o{\n  &::before{\n    content: \"\\f10c\";}\n}\n.fa-quote-left{\n  &::before{\n    content: \"\\f10d\";}\n}\n.fa-quote-right{\n  &::before{\n    content: \"\\f10e\";}\n}\n.fa-spinner{\n  &::before{\n    content: \"\\f110\";}\n}\n.fa-circle{\n  &::before{\n    content: \"\\f111\";}\n}\n.fa-mail-reply,\n.fa-reply{\n  &::before{\n    content: \"\\f112\";}\n}\n.fa-github-alt{\n  &::before{\n    content: \"\\f113\";}\n}\n.fa-folder-o{\n  &::before{\n    content: \"\\f114\";}\n}\n.fa-folder-open-o{\n  &::before{\n    content: \"\\f115\";}\n}\n.fa-smile-o{\n  &::before{\n    content: \"\\f118\";}\n}\n.fa-frown-o{\n  &::before{\n    content: \"\\f119\";}\n}\n.fa-meh-o{\n  &::before{\n    content: \"\\f11a\";}\n}\n.fa-gamepad{\n  &::before{\n    content: \"\\f11b\";}\n}\n.fa-keyboard-o{\n  &::before{\n    content: \"\\f11c\";}\n}\n.fa-flag-o{\n  &::before{\n    content: \"\\f11d\";}\n}\n.fa-flag-checkered{\n  &::before{\n    content: \"\\f11e\";}\n}\n.fa-terminal{\n  &::before{\n    content: \"\\f120\";}\n}\n.fa-code{\n  &::before{\n    content: \"\\f121\";}\n}\n.fa-mail-reply-all,\n.fa-reply-all{\n  &::before{\n    content: \"\\f122\";}\n}\n.fa-star-half-empty,\n.fa-star-half-full,\n.fa-star-half-o{\n  &::before{\n    content: \"\\f123\";}\n}\n.fa-location-arrow{\n  &::before{\n    content: \"\\f124\";}\n}\n.fa-crop{\n  &::before{\n    content: \"\\f125\";}\n}\n.fa-code-fork{\n  &::before{\n    content: \"\\f126\";}\n}\n.fa-unlink,\n.fa-chain-broken{\n  &::before{\n    content: \"\\f127\";}\n}\n.fa-question{\n  &::before{\n    content: \"\\f128\";}\n}\n.fa-info{\n  &::before{\n    content: \"\\f129\";}\n}\n.fa-exclamation{\n  &::before{\n    content: \"\\f12a\";}\n}\n.fa-superscript{\n  &::before{\n    content: \"\\f12b\";}\n}\n.fa-subscript{\n  &::before{\n    content: \"\\f12c\";}\n}\n.fa-eraser{\n  &::before{\n    content: \"\\f12d\";}\n}\n.fa-puzzle-piece{\n  &::before{\n    content: \"\\f12e\";}\n}\n.fa-microphone{\n  &::before{\n    content: \"\\f130\";}\n}\n.fa-microphone-slash{\n  &::before{\n    content: \"\\f131\";}\n}\n.fa-shield{\n  &::before{\n    content: \"\\f132\";}\n}\n.fa-calendar-o{\n  &::before{\n    content: \"\\f133\";}\n}\n.fa-fire-extinguisher{\n  &::before{\n    content: \"\\f134\";}\n}\n.fa-rocket{\n  &::before{\n    content: \"\\f135\";}\n}\n.fa-maxcdn{\n  &::before{\n    content: \"\\f136\";}\n}\n.fa-chevron-circle-left{\n  &::before{\n    content: \"\\f137\";}\n}\n.fa-chevron-circle-right{\n  &::before{\n    content: \"\\f138\";}\n}\n.fa-chevron-circle-up{\n  &::before{\n    content: \"\\f139\";}\n}\n.fa-chevron-circle-down{\n  &::before{\n    content: \"\\f13a\";}\n}\n.fa-html5{\n  &::before{\n    content: \"\\f13b\";}\n}\n.fa-css3{\n  &::before{\n    content: \"\\f13c\";}\n}\n.fa-anchor{\n  &::before{\n    content: \"\\f13d\";}\n}\n.fa-unlock-alt{\n  &::before{\n    content: \"\\f13e\";}\n}\n.fa-bullseye{\n  &::before{\n    content: \"\\f140\";}\n}\n.fa-ellipsis-h{\n  &::before{\n    content: \"\\f141\";}\n}\n.fa-ellipsis-v{\n  &::before{\n    content: \"\\f142\";}\n}\n.fa-rss-square{\n  &::before{\n    content: \"\\f143\";}\n}\n.fa-play-circle{\n  &::before{\n    content: \"\\f144\";}\n}\n.fa-ticket{\n  &::before{\n    content: \"\\f145\";}\n}\n.fa-minus-square{\n  &::before{\n    content: \"\\f146\";}\n}\n.fa-minus-square-o{\n  &::before{\n    content: \"\\f147\";}\n}\n.fa-level-up{\n  &::before{\n    content: \"\\f148\";}\n}\n.fa-level-down{\n  &::before{\n    content: \"\\f149\";}\n}\n.fa-check-square{\n  &::before{\n    content: \"\\f14a\";}\n}\n.fa-pencil-square{\n  &::before{\n    content: \"\\f14b\";}\n}\n.fa-external-link-square{\n  &::before{\n    content: \"\\f14c\";}\n}\n.fa-share-square{\n  &::before{\n    content: \"\\f14d\";}\n}\n.fa-compass{\n  &::before{\n    content: \"\\f14e\";}\n}\n.fa-toggle-down,\n.fa-caret-square-o-down{\n  &::before{\n    content: \"\\f150\";}\n}\n.fa-toggle-up,\n.fa-caret-square-o-up{\n  &::before{\n    content: \"\\f151\";}\n}\n.fa-toggle-right,\n.fa-caret-square-o-right{\n  &::before{\n    content: \"\\f152\";}\n}\n.fa-euro,\n.fa-eur{\n  &::before{\n    content: \"\\f153\";}\n}\n.fa-gbp{\n  &::before{\n    content: \"\\f154\";}\n}\n.fa-dollar,\n.fa-usd{\n  &::before{\n    content: \"\\f155\";}\n}\n.fa-rupee,\n.fa-inr{\n  &::before{\n    content: \"\\f156\";}\n}\n.fa-cny,\n.fa-rmb,\n.fa-yen,\n.fa-jpy{\n  &::before{\n    content: \"\\f157\";}\n}\n.fa-ruble,\n.fa-rouble,\n.fa-rub{\n  &::before{\n    content: \"\\f158\";}\n}\n.fa-won,\n.fa-krw{\n  &::before{\n    content: \"\\f159\";}\n}\n.fa-bitcoin,\n.fa-btc{\n  &::before{\n    content: \"\\f15a\";}\n}\n.fa-file{\n  &::before{\n    content: \"\\f15b\";}\n}\n.fa-file-text{\n  &::before{\n    content: \"\\f15c\";}\n}\n.fa-sort-alpha-asc{\n  &::before{\n    content: \"\\f15d\";}\n}\n.fa-sort-alpha-desc{\n  &::before{\n    content: \"\\f15e\";}\n}\n.fa-sort-amount-asc{\n  &::before{\n    content: \"\\f160\";}\n}\n.fa-sort-amount-desc{\n  &::before{\n    content: \"\\f161\";}\n}\n.fa-sort-numeric-asc{\n  &::before{\n    content: \"\\f162\";}\n}\n.fa-sort-numeric-desc{\n  &::before{\n    content: \"\\f163\";}\n}\n.fa-thumbs-up{\n  &::before{\n    content: \"\\f164\";}\n}\n.fa-thumbs-down{\n  &::before{\n    content: \"\\f165\";}\n}\n.fa-youtube-square{\n  &::before{\n    content: \"\\f166\";}\n}\n.fa-youtube{\n  &::before{\n    content: \"\\f167\";}\n}\n.fa-xing{\n  &::before{\n    content: \"\\f168\";}\n}\n.fa-xing-square{\n  &::before{\n    content: \"\\f169\";}\n}\n.fa-youtube-play{\n  &::before{\n    content: \"\\f16a\";}\n}\n.fa-dropbox{\n  &::before{\n    content: \"\\f16b\";}\n}\n.fa-stack-overflow{\n  &::before{\n    content: \"\\f16c\";}\n}\n.fa-instagram{\n  &::before{\n    content: \"\\f16d\";}\n}\n.fa-flickr{\n  &::before{\n    content: \"\\f16e\";}\n}\n.fa-adn{\n  &::before{\n    content: \"\\f170\";}\n}\n.fa-bitbucket{\n  &::before{\n    content: \"\\f171\";}\n}\n.fa-bitbucket-square{\n  &::before{\n    content: \"\\f172\";}\n}\n.fa-tumblr{\n  &::before{\n    content: \"\\f173\";}\n}\n.fa-tumblr-square{\n  &::before{\n    content: \"\\f174\";}\n}\n.fa-long-arrow-down{\n  &::before{\n    content: \"\\f175\";}\n}\n.fa-long-arrow-up{\n  &::before{\n    content: \"\\f176\";}\n}\n.fa-long-arrow-left{\n  &::before{\n    content: \"\\f177\";}\n}\n.fa-long-arrow-right{\n  &::before{\n    content: \"\\f178\";}\n}\n.fa-apple{\n  &::before{\n    content: \"\\f179\";}\n}\n.fa-windows{\n  &::before{\n    content: \"\\f17a\";}\n}\n.fa-android{\n  &::before{\n    content: \"\\f17b\";}\n}\n.fa-linux{\n  &::before{\n    content: \"\\f17c\";}\n}\n.fa-dribbble{\n  &::before{\n    content: \"\\f17d\";}\n}\n.fa-skype{\n  &::before{\n    content: \"\\f17e\";}\n}\n.fa-foursquare{\n  &::before{\n    content: \"\\f180\";}\n}\n.fa-trello{\n  &::before{\n    content: \"\\f181\";}\n}\n.fa-female{\n  &::before{\n    content: \"\\f182\";}\n}\n.fa-male{\n  &::before{\n    content: \"\\f183\";}\n}\n.fa-gittip,\n.fa-gratipay{\n  &::before{\n    content: \"\\f184\";}\n}\n.fa-sun-o{\n  &::before{\n    content: \"\\f185\";}\n}\n.fa-moon-o{\n  &::before{\n    content: \"\\f186\";}\n}\n.fa-archive{\n  &::before{\n    content: \"\\f187\";}\n}\n.fa-bug{\n  &::before{\n    content: \"\\f188\";}\n}\n.fa-vk{\n  &::before{\n    content: \"\\f189\";}\n}\n.fa-weibo{\n  &::before{\n    content: \"\\f18a\";}\n}\n.fa-renren{\n  &::before{\n    content: \"\\f18b\";}\n}\n.fa-pagelines{\n  &::before{\n    content: \"\\f18c\";}\n}\n.fa-stack-exchange{\n  &::before{\n    content: \"\\f18d\";}\n}\n.fa-arrow-circle-o-right{\n  &::before{\n    content: \"\\f18e\";}\n}\n.fa-arrow-circle-o-left{\n  &::before{\n    content: \"\\f190\";}\n}\n.fa-toggle-left,\n.fa-caret-square-o-left{\n  &::before{\n    content: \"\\f191\";}\n}\n.fa-dot-circle-o{\n  &::before{\n    content: \"\\f192\";}\n}\n.fa-wheelchair{\n  &::before{\n    content: \"\\f193\";}\n}\n.fa-vimeo-square{\n  &::before{\n    content: \"\\f194\";}\n}\n.fa-turkish-lira,\n.fa-try{\n  &::before{\n    content: \"\\f195\";}\n}\n.fa-plus-square-o{\n  &::before{\n    content: \"\\f196\";}\n}\n.fa-space-shuttle{\n  &::before{\n    content: \"\\f197\";}\n}\n.fa-slack{\n  &::before{\n    content: \"\\f198\";}\n}\n.fa-envelope-square{\n  &::before{\n    content: \"\\f199\";}\n}\n.fa-wordpress{\n  &::before{\n    content: \"\\f19a\";}\n}\n.fa-openid{\n  &::before{\n    content: \"\\f19b\";}\n}\n.fa-institution,\n.fa-bank,\n.fa-university{\n  &::before{\n    content: \"\\f19c\";}\n}\n.fa-mortar-board,\n.fa-graduation-cap{\n  &::before{\n    content: \"\\f19d\";}\n}\n.fa-yahoo{\n  &::before{\n    content: \"\\f19e\";}\n}\n.fa-google{\n  &::before{\n    content: \"\\f1a0\";}\n}\n.fa-reddit{\n  &::before{\n    content: \"\\f1a1\";}\n}\n.fa-reddit-square{\n  &::before{\n    content: \"\\f1a2\";}\n}\n.fa-stumbleupon-circle{\n  &::before{\n    content: \"\\f1a3\";}\n}\n.fa-stumbleupon{\n  &::before{\n    content: \"\\f1a4\";}\n}\n.fa-delicious{\n  &::before{\n    content: \"\\f1a5\";}\n}\n.fa-digg{\n  &::before{\n    content: \"\\f1a6\";}\n}\n.fa-pied-piper-pp{\n  &::before{\n    content: \"\\f1a7\";}\n}\n.fa-pied-piper-alt{\n  &::before{\n    content: \"\\f1a8\";}\n}\n.fa-drupal{\n  &::before{\n    content: \"\\f1a9\";}\n}\n.fa-joomla{\n  &::before{\n    content: \"\\f1aa\";}\n}\n.fa-language{\n  &::before{\n    content: \"\\f1ab\";}\n}\n.fa-fax{\n  &::before{\n    content: \"\\f1ac\";}\n}\n.fa-building{\n  &::before{\n    content: \"\\f1ad\";}\n}\n.fa-child{\n  &::before{\n    content: \"\\f1ae\";}\n}\n.fa-paw{\n  &::before{\n    content: \"\\f1b0\";}\n}\n.fa-spoon{\n  &::before{\n    content: \"\\f1b1\";}\n}\n.fa-cube{\n  &::before{\n    content: \"\\f1b2\";}\n}\n.fa-cubes{\n  &::before{\n    content: \"\\f1b3\";}\n}\n.fa-behance{\n  &::before{\n    content: \"\\f1b4\";}\n}\n.fa-behance-square{\n  &::before{\n    content: \"\\f1b5\";}\n}\n.fa-steam{\n  &::before{\n    content: \"\\f1b6\";}\n}\n.fa-steam-square{\n  &::before{\n    content: \"\\f1b7\";}\n}\n.fa-recycle{\n  &::before{\n    content: \"\\f1b8\";}\n}\n.fa-automobile,\n.fa-car{\n  &::before{\n    content: \"\\f1b9\";}\n}\n.fa-cab,\n.fa-taxi{\n  &::before{\n    content: \"\\f1ba\";}\n}\n.fa-tree{\n  &::before{\n    content: \"\\f1bb\";}\n}\n.fa-spotify{\n  &::before{\n    content: \"\\f1bc\";}\n}\n.fa-deviantart{\n  &::before{\n    content: \"\\f1bd\";}\n}\n.fa-soundcloud{\n  &::before{\n    content: \"\\f1be\";}\n}\n.fa-database{\n  &::before{\n    content: \"\\f1c0\";}\n}\n.fa-file-pdf-o{\n  &::before{\n    content: \"\\f1c1\";}\n}\n.fa-file-word-o{\n  &::before{\n    content: \"\\f1c2\";}\n}\n.fa-file-excel-o{\n  &::before{\n    content: \"\\f1c3\";}\n}\n.fa-file-powerpoint-o{\n  &::before{\n    content: \"\\f1c4\";}\n}\n.fa-file-photo-o,\n.fa-file-picture-o,\n.fa-file-image-o{\n  &::before{\n    content: \"\\f1c5\";}\n}\n.fa-file-zip-o,\n.fa-file-archive-o{\n  &::before{\n    content: \"\\f1c6\";}\n}\n.fa-file-sound-o,\n.fa-file-audio-o{\n  &::before{\n    content: \"\\f1c7\";}\n}\n.fa-file-movie-o,\n.fa-file-video-o{\n  &::before{\n    content: \"\\f1c8\";}\n}\n.fa-file-code-o{\n  &::before{\n    content: \"\\f1c9\";}\n}\n.fa-vine{\n  &::before{\n    content: \"\\f1ca\";}\n}\n.fa-codepen{\n  &::before{\n    content: \"\\f1cb\";}\n}\n.fa-jsfiddle{\n  &::before{\n    content: \"\\f1cc\";}\n}\n.fa-life-bouy,\n.fa-life-buoy,\n.fa-life-saver,\n.fa-support,\n.fa-life-ring{\n  &::before{\n    content: \"\\f1cd\";}\n}\n.fa-circle-o-notch{\n  &::before{\n    content: \"\\f1ce\";}\n}\n.fa-ra,\n.fa-resistance,\n.fa-rebel{\n  &::before{\n    content: \"\\f1d0\";}\n}\n.fa-ge,\n.fa-empire{\n  &::before{\n    content: \"\\f1d1\";}\n}\n.fa-git-square{\n  &::before{\n    content: \"\\f1d2\";}\n}\n.fa-git{\n  &::before{\n    content: \"\\f1d3\";}\n}\n.fa-y-combinator-square,\n.fa-yc-square,\n.fa-hacker-news{\n  &::before{\n    content: \"\\f1d4\";}\n}\n.fa-tencent-weibo{\n  &::before{\n    content: \"\\f1d5\";}\n}\n.fa-qq{\n  &::before{\n    content: \"\\f1d6\";}\n}\n.fa-wechat,\n.fa-weixin{\n  &::before{\n    content: \"\\f1d7\";}\n}\n.fa-send,\n.fa-paper-plane{\n  &::before{\n    content: \"\\f1d8\";}\n}\n.fa-send-o,\n.fa-paper-plane-o{\n  &::before{\n    content: \"\\f1d9\";}\n}\n.fa-history{\n  &::before{\n    content: \"\\f1da\";}\n}\n.fa-circle-thin{\n  &::before{\n    content: \"\\f1db\";}\n}\n.fa-header{\n  &::before{\n    content: \"\\f1dc\";}\n}\n.fa-paragraph{\n  &::before{\n    content: \"\\f1dd\";}\n}\n.fa-sliders{\n  &::before{\n    content: \"\\f1de\";}\n}\n.fa-share-alt{\n  &::before{\n    content: \"\\f1e0\";}\n}\n.fa-share-alt-square{\n  &::before{\n    content: \"\\f1e1\";}\n}\n.fa-bomb{\n  &::before{\n    content: \"\\f1e2\";}\n}\n.fa-soccer-ball-o,\n.fa-futbol-o{\n  &::before{\n    content: \"\\f1e3\";}\n}\n.fa-tty{\n  &::before{\n    content: \"\\f1e4\";}\n}\n.fa-binoculars{\n  &::before{\n    content: \"\\f1e5\";}\n}\n.fa-plug{\n  &::before{\n    content: \"\\f1e6\";}\n}\n.fa-slideshare{\n  &::before{\n    content: \"\\f1e7\";}\n}\n.fa-twitch{\n  &::before{\n    content: \"\\f1e8\";}\n}\n.fa-yelp{\n  &::before{\n    content: \"\\f1e9\";}\n}\n.fa-newspaper-o{\n  &::before{\n    content: \"\\f1ea\";}\n}\n.fa-wifi{\n  &::before{\n    content: \"\\f1eb\";}\n}\n.fa-calculator{\n  &::before{\n    content: \"\\f1ec\";}\n}\n.fa-paypal{\n  &::before{\n    content: \"\\f1ed\";}\n}\n.fa-google-wallet{\n  &::before{\n    content: \"\\f1ee\";}\n}\n.fa-cc-visa{\n  &::before{\n    content: \"\\f1f0\";}\n}\n.fa-cc-mastercard{\n  &::before{\n    content: \"\\f1f1\";}\n}\n.fa-cc-discover{\n  &::before{\n    content: \"\\f1f2\";}\n}\n.fa-cc-amex{\n  &::before{\n    content: \"\\f1f3\";}\n}\n.fa-cc-paypal{\n  &::before{\n    content: \"\\f1f4\";}\n}\n.fa-cc-stripe{\n  &::before{\n    content: \"\\f1f5\";}\n}\n.fa-bell-slash{\n  &::before{\n    content: \"\\f1f6\";}\n}\n.fa-bell-slash-o{\n  &::before{\n    content: \"\\f1f7\";}\n}\n.fa-trash{\n  &::before{\n    content: \"\\f1f8\";}\n}\n.fa-copyright{\n  &::before{\n    content: \"\\f1f9\";}\n}\n.fa-at{\n  &::before{\n    content: \"\\f1fa\";}\n}\n.fa-eyedropper{\n  &::before{\n    content: \"\\f1fb\";}\n}\n.fa-paint-brush{\n  &::before{\n    content: \"\\f1fc\";}\n}\n.fa-birthday-cake{\n  &::before{\n    content: \"\\f1fd\";}\n}\n.fa-area-chart{\n  &::before{\n    content: \"\\f1fe\";}\n}\n.fa-pie-chart{\n  &::before{\n    content: \"\\f200\";}\n}\n.fa-line-chart{\n  &::before{\n    content: \"\\f201\";}\n}\n.fa-lastfm{\n  &::before{\n    content: \"\\f202\";}\n}\n.fa-lastfm-square{\n  &::before{\n    content: \"\\f203\";}\n}\n.fa-toggle-off{\n  &::before{\n    content: \"\\f204\";}\n}\n.fa-toggle-on{\n  &::before{\n    content: \"\\f205\";}\n}\n.fa-bicycle{\n  &::before{\n    content: \"\\f206\";}\n}\n.fa-bus{\n  &::before{\n    content: \"\\f207\";}\n}\n.fa-ioxhost{\n  &::before{\n    content: \"\\f208\";}\n}\n.fa-angellist{\n  &::before{\n    content: \"\\f209\";}\n}\n.fa-cc{\n  &::before{\n    content: \"\\f20a\";}\n}\n.fa-shekel,\n.fa-sheqel,\n.fa-ils{\n  &::before{\n    content: \"\\f20b\";}\n}\n.fa-meanpath{\n  &::before{\n    content: \"\\f20c\";}\n}\n.fa-buysellads{\n  &::before{\n    content: \"\\f20d\";}\n}\n.fa-connectdevelop{\n  &::before{\n    content: \"\\f20e\";}\n}\n.fa-dashcube{\n  &::before{\n    content: \"\\f210\";}\n}\n.fa-forumbee{\n  &::before{\n    content: \"\\f211\";}\n}\n.fa-leanpub{\n  &::before{\n    content: \"\\f212\";}\n}\n.fa-sellsy{\n  &::before{\n    content: \"\\f213\";}\n}\n.fa-shirtsinbulk{\n  &::before{\n    content: \"\\f214\";}\n}\n.fa-simplybuilt{\n  &::before{\n    content: \"\\f215\";}\n}\n.fa-skyatlas{\n  &::before{\n    content: \"\\f216\";}\n}\n.fa-cart-plus{\n  &::before{\n    content: \"\\f217\";}\n}\n.fa-cart-arrow-down{\n  &::before{\n    content: \"\\f218\";}\n}\n.fa-diamond{\n  &::before{\n    content: \"\\f219\";}\n}\n.fa-ship{\n  &::before{\n    content: \"\\f21a\";}\n}\n.fa-user-secret{\n  &::before{\n    content: \"\\f21b\";}\n}\n.fa-motorcycle{\n  &::before{\n    content: \"\\f21c\";}\n}\n.fa-street-view{\n  &::before{\n    content: \"\\f21d\";}\n}\n.fa-heartbeat{\n  &::before{\n    content: \"\\f21e\";}\n}\n.fa-venus{\n  &::before{\n    content: \"\\f221\";}\n}\n.fa-mars{\n  &::before{\n    content: \"\\f222\";}\n}\n.fa-mercury{\n  &::before{\n    content: \"\\f223\";}\n}\n.fa-intersex,\n.fa-transgender{\n  &::before{\n    content: \"\\f224\";}\n}\n.fa-transgender-alt{\n  &::before{\n    content: \"\\f225\";}\n}\n.fa-venus-double{\n  &::before{\n    content: \"\\f226\";}\n}\n.fa-mars-double{\n  &::before{\n    content: \"\\f227\";}\n}\n.fa-venus-mars{\n  &::before{\n    content: \"\\f228\";}\n}\n.fa-mars-stroke{\n  &::before{\n    content: \"\\f229\";}\n}\n.fa-mars-stroke-v{\n  &::before{\n    content: \"\\f22a\";}\n}\n.fa-mars-stroke-h{\n  &::before{\n    content: \"\\f22b\";}\n}\n.fa-neuter{\n  &::before{\n    content: \"\\f22c\";}\n}\n.fa-genderless{\n  &::before{\n    content: \"\\f22d\";}\n}\n.fa-facebook-official{\n  &::before{\n    content: \"\\f230\";}\n}\n.fa-pinterest-p{\n  &::before{\n    content: \"\\f231\";}\n}\n.fa-whatsapp{\n  &::before{\n    content: \"\\f232\";}\n}\n.fa-server{\n  &::before{\n    content: \"\\f233\";}\n}\n.fa-user-plus{\n  &::before{\n    content: \"\\f234\";}\n}\n.fa-user-times{\n  &::before{\n    content: \"\\f235\";}\n}\n.fa-hotel,\n.fa-bed{\n  &::before{\n    content: \"\\f236\";}\n}\n.fa-viacoin{\n  &::before{\n    content: \"\\f237\";}\n}\n.fa-train{\n  &::before{\n    content: \"\\f238\";}\n}\n.fa-subway{\n  &::before{\n    content: \"\\f239\";}\n}\n.fa-medium{\n  &::before{\n    content: \"\\f23a\";}\n}\n.fa-yc,\n.fa-y-combinator{\n  &::before{\n    content: \"\\f23b\";}\n}\n.fa-optin-monster{\n  &::before{\n    content: \"\\f23c\";}\n}\n.fa-opencart{\n  &::before{\n    content: \"\\f23d\";}\n}\n.fa-expeditedssl{\n  &::before{\n    content: \"\\f23e\";}\n}\n.fa-battery-4,\n.fa-battery,\n.fa-battery-full{\n  &::before{\n    content: \"\\f240\";}\n}\n.fa-battery-3,\n.fa-battery-three-quarters{\n  &::before{\n    content: \"\\f241\";}\n}\n.fa-battery-2,\n.fa-battery-half{\n  &::before{\n    content: \"\\f242\";}\n}\n.fa-battery-1,\n.fa-battery-quarter{\n  &::before{\n    content: \"\\f243\";}\n}\n.fa-battery-0,\n.fa-battery-empty{\n  &::before{\n    content: \"\\f244\";}\n}\n.fa-mouse-pointer{\n  &::before{\n    content: \"\\f245\";}\n}\n.fa-i-cursor{\n  &::before{\n    content: \"\\f246\";}\n}\n.fa-object-group{\n  &::before{\n    content: \"\\f247\";}\n}\n.fa-object-ungroup{\n  &::before{\n    content: \"\\f248\";}\n}\n.fa-sticky-note{\n  &::before{\n    content: \"\\f249\";}\n}\n.fa-sticky-note-o{\n  &::before{\n    content: \"\\f24a\";}\n}\n.fa-cc-jcb{\n  &::before{\n    content: \"\\f24b\";}\n}\n.fa-cc-diners-club{\n  &::before{\n    content: \"\\f24c\";}\n}\n.fa-clone{\n  &::before{\n    content: \"\\f24d\";}\n}\n.fa-balance-scale{\n  &::before{\n    content: \"\\f24e\";}\n}\n.fa-hourglass-o{\n  &::before{\n    content: \"\\f250\";}\n}\n.fa-hourglass-1,\n.fa-hourglass-start{\n  &::before{\n    content: \"\\f251\";}\n}\n.fa-hourglass-2,\n.fa-hourglass-half{\n  &::before{\n    content: \"\\f252\";}\n}\n.fa-hourglass-3,\n.fa-hourglass-end{\n  &::before{\n    content: \"\\f253\";}\n}\n.fa-hourglass{\n  &::before{\n    content: \"\\f254\";}\n}\n.fa-hand-grab-o,\n.fa-hand-rock-o{\n  &::before{\n    content: \"\\f255\";}\n}\n.fa-hand-stop-o,\n.fa-hand-paper-o{\n  &::before{\n    content: \"\\f256\";}\n}\n.fa-hand-scissors-o{\n  &::before{\n    content: \"\\f257\";}\n}\n.fa-hand-lizard-o{\n  &::before{\n    content: \"\\f258\";}\n}\n.fa-hand-spock-o{\n  &::before{\n    content: \"\\f259\";}\n}\n.fa-hand-pointer-o{\n  &::before{\n    content: \"\\f25a\";}\n}\n.fa-hand-peace-o{\n  &::before{\n    content: \"\\f25b\";}\n}\n.fa-trademark{\n  &::before{\n    content: \"\\f25c\";}\n}\n.fa-registered{\n  &::before{\n    content: \"\\f25d\";}\n}\n.fa-creative-commons{\n  &::before{\n    content: \"\\f25e\";}\n}\n.fa-gg{\n  &::before{\n    content: \"\\f260\";}\n}\n.fa-gg-circle{\n  &::before{\n    content: \"\\f261\";}\n}\n.fa-tripadvisor{\n  &::before{\n    content: \"\\f262\";}\n}\n.fa-odnoklassniki{\n  &::before{\n    content: \"\\f263\";}\n}\n.fa-odnoklassniki-square{\n  &::before{\n    content: \"\\f264\";}\n}\n.fa-get-pocket{\n  &::before{\n    content: \"\\f265\";}\n}\n.fa-wikipedia-w{\n  &::before{\n    content: \"\\f266\";}\n}\n.fa-safari{\n  &::before{\n    content: \"\\f267\";}\n}\n.fa-chrome{\n  &::before{\n    content: \"\\f268\";}\n}\n.fa-firefox{\n  &::before{\n    content: \"\\f269\";}\n}\n.fa-opera{\n  &::before{\n    content: \"\\f26a\";}\n}\n.fa-internet-explorer{\n  &::before{\n    content: \"\\f26b\";}\n}\n.fa-tv,\n.fa-television{\n  &::before{\n    content: \"\\f26c\";}\n}\n.fa-contao{\n  &::before{\n    content: \"\\f26d\";}\n}\n.fa-500px{\n  &::before{\n    content: \"\\f26e\";}\n}\n.fa-amazon{\n  &::before{\n    content: \"\\f270\";}\n}\n.fa-calendar-plus-o{\n  &::before{\n    content: \"\\f271\";}\n}\n.fa-calendar-minus-o{\n  &::before{\n    content: \"\\f272\";}\n}\n.fa-calendar-times-o{\n  &::before{\n    content: \"\\f273\";}\n}\n.fa-calendar-check-o{\n  &::before{\n    content: \"\\f274\";}\n}\n.fa-industry{\n  &::before{\n    content: \"\\f275\";}\n}\n.fa-map-pin{\n  &::before{\n    content: \"\\f276\";}\n}\n.fa-map-signs{\n  &::before{\n    content: \"\\f277\";}\n}\n.fa-map-o{\n  &::before{\n    content: \"\\f278\";}\n}\n.fa-map{\n  &::before{\n    content: \"\\f279\";}\n}\n.fa-commenting{\n  &::before{\n    content: \"\\f27a\";}\n}\n.fa-commenting-o{\n  &::before{\n    content: \"\\f27b\";}\n}\n.fa-houzz{\n  &::before{\n    content: \"\\f27c\";}\n}\n.fa-vimeo{\n  &::before{\n    content: \"\\f27d\";}\n}\n.fa-black-tie{\n  &::before{\n    content: \"\\f27e\";}\n}\n.fa-fonticons{\n  &::before{\n    content: \"\\f280\";}\n}\n.fa-reddit-alien{\n  &::before{\n    content: \"\\f281\";}\n}\n.fa-edge{\n  &::before{\n    content: \"\\f282\";}\n}\n.fa-credit-card-alt{\n  &::before{\n    content: \"\\f283\";}\n}\n.fa-codiepie{\n  &::before{\n    content: \"\\f284\";}\n}\n.fa-modx{\n  &::before{\n    content: \"\\f285\";}\n}\n.fa-fort-awesome{\n  &::before{\n    content: \"\\f286\";}\n}\n.fa-usb{\n  &::before{\n    content: \"\\f287\";}\n}\n.fa-product-hunt{\n  &::before{\n    content: \"\\f288\";}\n}\n.fa-mixcloud{\n  &::before{\n    content: \"\\f289\";}\n}\n.fa-scribd{\n  &::before{\n    content: \"\\f28a\";}\n}\n.fa-pause-circle{\n  &::before{\n    content: \"\\f28b\";}\n}\n.fa-pause-circle-o{\n  &::before{\n    content: \"\\f28c\";}\n}\n.fa-stop-circle{\n  &::before{\n    content: \"\\f28d\";}\n}\n.fa-stop-circle-o{\n  &::before{\n    content: \"\\f28e\";}\n}\n.fa-shopping-bag{\n  &::before{\n    content: \"\\f290\";}\n}\n.fa-shopping-basket{\n  &::before{\n    content: \"\\f291\";}\n}\n.fa-hashtag{\n  &::before{\n    content: \"\\f292\";}\n}\n.fa-bluetooth{\n  &::before{\n    content: \"\\f293\";}\n}\n.fa-bluetooth-b{\n  &::before{\n    content: \"\\f294\";}\n}\n.fa-percent{\n  &::before{\n    content: \"\\f295\";}\n}\n.fa-gitlab{\n  &::before{\n    content: \"\\f296\";}\n}\n.fa-wpbeginner{\n  &::before{\n    content: \"\\f297\";}\n}\n.fa-wpforms{\n  &::before{\n    content: \"\\f298\";}\n}\n.fa-envira{\n  &::before{\n    content: \"\\f299\";}\n}\n.fa-universal-access{\n  &::before{\n    content: \"\\f29a\";}\n}\n.fa-wheelchair-alt{\n  &::before{\n    content: \"\\f29b\";}\n}\n.fa-question-circle-o{\n  &::before{\n    content: \"\\f29c\";}\n}\n.fa-blind{\n  &::before{\n    content: \"\\f29d\";}\n}\n.fa-audio-description{\n  &::before{\n    content: \"\\f29e\";}\n}\n.fa-volume-control-phone{\n  &::before{\n    content: \"\\f2a0\";}\n}\n.fa-braille{\n  &::before{\n    content: \"\\f2a1\";}\n}\n.fa-assistive-listening-systems{\n  &::before{\n    content: \"\\f2a2\";}\n}\n.fa-asl-interpreting,\n.fa-american-sign-language-interpreting{\n  &::before{\n    content: \"\\f2a3\";}\n}\n.fa-deafness,\n.fa-hard-of-hearing,\n.fa-deaf{\n  &::before{\n    content: \"\\f2a4\";}\n}\n.fa-glide{\n  &::before{\n    content: \"\\f2a5\";}\n}\n.fa-glide-g{\n  &::before{\n    content: \"\\f2a6\";}\n}\n.fa-signing,\n.fa-sign-language{\n  &::before{\n    content: \"\\f2a7\";}\n}\n.fa-low-vision{\n  &::before{\n    content: \"\\f2a8\";}\n}\n.fa-viadeo{\n  &::before{\n    content: \"\\f2a9\";}\n}\n.fa-viadeo-square{\n  &::before{\n    content: \"\\f2aa\";}\n}\n.fa-snapchat{\n  &::before{\n    content: \"\\f2ab\";}\n}\n.fa-snapchat-ghost{\n  &::before{\n    content: \"\\f2ac\";}\n}\n.fa-snapchat-square{\n  &::before{\n    content: \"\\f2ad\";}\n}\n.fa-pied-piper{\n  &::before{\n    content: \"\\f2ae\";}\n}\n.fa-first-order{\n  &::before{\n    content: \"\\f2b0\";}\n}\n.fa-yoast{\n  &::before{\n    content: \"\\f2b1\";}\n}\n.fa-themeisle{\n  &::before{\n    content: \"\\f2b2\";}\n}\n.fa-google-plus-circle,\n.fa-google-plus-official{\n  &::before{\n    content: \"\\f2b3\";}\n}\n.fa-fa,\n.fa-font-awesome{\n  &::before{\n    content: \"\\f2b4\";}\n}\n.fa-handshake-o{\n  &::before{\n    content: \"\\f2b5\";}\n}\n.fa-envelope-open{\n  &::before{\n    content: \"\\f2b6\";}\n}\n.fa-envelope-open-o{\n  &::before{\n    content: \"\\f2b7\";}\n}\n.fa-linode{\n  &::before{\n    content: \"\\f2b8\";}\n}\n.fa-address-book{\n  &::before{\n    content: \"\\f2b9\";}\n}\n.fa-address-book-o{\n  &::before{\n    content: \"\\f2ba\";}\n}\n.fa-vcard,\n.fa-address-card{\n  &::before{\n    content: \"\\f2bb\";}\n}\n.fa-vcard-o,\n.fa-address-card-o{\n  &::before{\n    content: \"\\f2bc\";}\n}\n.fa-user-circle{\n  &::before{\n    content: \"\\f2bd\";}\n}\n.fa-user-circle-o{\n  &::before{\n    content: \"\\f2be\";}\n}\n.fa-user-o{\n  &::before{\n    content: \"\\f2c0\";}\n}\n.fa-id-badge{\n  &::before{\n    content: \"\\f2c1\";}\n}\n.fa-drivers-license,\n.fa-id-card{\n  &::before{\n    content: \"\\f2c2\";}\n}\n.fa-drivers-license-o,\n.fa-id-card-o{\n  &::before{\n    content: \"\\f2c3\";}\n}\n.fa-quora{\n  &::before{\n    content: \"\\f2c4\";}\n}\n.fa-free-code-camp{\n  &::before{\n    content: \"\\f2c5\";}\n}\n.fa-telegram{\n  &::before{\n    content: \"\\f2c6\";}\n}\n.fa-thermometer-4,\n.fa-thermometer,\n.fa-thermometer-full{\n  &::before{\n    content: \"\\f2c7\";}\n}\n.fa-thermometer-3,\n.fa-thermometer-three-quarters{\n  &::before{\n    content: \"\\f2c8\";}\n}\n.fa-thermometer-2,\n.fa-thermometer-half{\n  &::before{\n    content: \"\\f2c9\";}\n}\n.fa-thermometer-1,\n.fa-thermometer-quarter{\n  &::before{\n    content: \"\\f2ca\";}\n}\n.fa-thermometer-0,\n.fa-thermometer-empty{\n  &::before{\n    content: \"\\f2cb\";}\n}\n.fa-shower{\n  &::before{\n    content: \"\\f2cc\";}\n}\n.fa-bathtub,\n.fa-s15,\n.fa-bath{\n  &::before{\n    content: \"\\f2cd\";}\n}\n.fa-podcast{\n  &::before{\n    content: \"\\f2ce\";}\n}\n.fa-window-maximize{\n  &::before{\n    content: \"\\f2d0\";}\n}\n.fa-window-minimize{\n  &::before{\n    content: \"\\f2d1\";}\n}\n.fa-window-restore{\n  &::before{\n    content: \"\\f2d2\";}\n}\n.fa-times-rectangle,\n.fa-window-close{\n  &::before{\n    content: \"\\f2d3\";}\n}\n.fa-times-rectangle-o,\n.fa-window-close-o{\n  &::before{\n    content: \"\\f2d4\";}\n}\n.fa-bandcamp{\n  &::before{\n    content: \"\\f2d5\";}\n}\n.fa-grav{\n  &::before{\n    content: \"\\f2d6\";}\n}\n.fa-etsy{\n  &::before{\n    content: \"\\f2d7\";}\n}\n.fa-imdb{\n  &::before{\n    content: \"\\f2d8\";}\n}\n.fa-ravelry{\n  &::before{\n    content: \"\\f2d9\";}\n}\n.fa-eercast{\n  &::before{\n    content: \"\\f2da\";}\n}\n.fa-microchip{\n  &::before{\n    content: \"\\f2db\";}\n}\n.fa-snowflake-o{\n  &::before{\n    content: \"\\f2dc\";}\n}\n.fa-superpowers{\n  &::before{\n    content: \"\\f2dd\";}\n}\n.fa-wpexplorer{\n  &::before{\n    content: \"\\f2de\";}\n}\n.fa-meetup{\n  &::before{\n    content: \"\\f2e0\";}\n}"
  },
  {
    "path": "src/IdentityServer/wwwroot/lib/jquery/LICENSE.txt",
    "content": "Copyright JS Foundation and other contributors, https://js.foundation/\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "src/IdentityServer/wwwroot/lib/jquery/README.md",
    "content": "# jQuery\n\n> jQuery is a fast, small, and feature-rich JavaScript library.\n\nFor information on how to get started and how to use jQuery, please see [jQuery's documentation](https://api.jquery.com/).\nFor source files and issues, please visit the [jQuery repo](https://github.com/jquery/jquery).\n\nIf upgrading, please see the [blog post for 3.5.1](https://blog.jquery.com/2020/05/04/jquery-3-5-1-released-fixing-a-regression/). This includes notable differences from the previous version and a more readable changelog.\n\n## Including jQuery\n\nBelow are some of the most common ways to include jQuery.\n\n### Browser\n\n#### Script tag\n\n```html\n<script src=\"https://code.jquery.com/jquery-3.5.1.min.js\"></script>\n```\n\n#### Babel\n\n[Babel](https://babeljs.io/) is a next generation JavaScript compiler. One of the features is the ability to use ES6/ES2015 modules now, even though browsers do not yet support this feature natively.\n\n```js\nimport $ from \"jquery\";\n```\n\n#### Browserify/Webpack\n\nThere are several ways to use [Browserify](http://browserify.org/) and [Webpack](https://webpack.github.io/). For more information on using these tools, please refer to the corresponding project's documentation. In the script, including jQuery will usually look like this...\n\n```js\nvar $ = require( \"jquery\" );\n```\n\n#### AMD (Asynchronous Module Definition)\n\nAMD is a module format built for the browser. For more information, we recommend [require.js' documentation](https://requirejs.org/docs/whyamd.html).\n\n```js\ndefine( [ \"jquery\" ], function( $ ) {\n\n} );\n```\n\n### Node\n\nTo include jQuery in [Node](https://nodejs.org/), first install with npm.\n\n```sh\nnpm install jquery\n```\n\nFor jQuery to work in Node, a window with a document is required. Since no such window exists natively in Node, one can be mocked by tools such as [jsdom](https://github.com/jsdom/jsdom). This can be useful for testing purposes.\n\n```js\nconst { JSDOM } = require( \"jsdom\" );\nconst { window } = new JSDOM( \"\" );\nconst $ = require( \"jquery\" )( window );\n```\n"
  },
  {
    "path": "src/IdentityServer/wwwroot/lib/jquery/dist/jquery.js",
    "content": "/*!\n * jQuery JavaScript Library v3.5.1\n * https://jquery.com/\n *\n * Includes Sizzle.js\n * https://sizzlejs.com/\n *\n * Copyright JS Foundation and other contributors\n * Released under the MIT license\n * https://jquery.org/license\n *\n * Date: 2020-05-04T22:49Z\n */\n( function( global, factory ) {\n\n\t\"use strict\";\n\n\tif ( typeof module === \"object\" && typeof module.exports === \"object\" ) {\n\n\t\t// For CommonJS and CommonJS-like environments where a proper `window`\n\t\t// is present, execute the factory and get jQuery.\n\t\t// For environments that do not have a `window` with a `document`\n\t\t// (such as Node.js), expose a factory as module.exports.\n\t\t// This accentuates the need for the creation of a real `window`.\n\t\t// e.g. var jQuery = require(\"jquery\")(window);\n\t\t// See ticket #14549 for more info.\n\t\tmodule.exports = global.document ?\n\t\t\tfactory( global, true ) :\n\t\t\tfunction( w ) {\n\t\t\t\tif ( !w.document ) {\n\t\t\t\t\tthrow new Error( \"jQuery requires a window with a document\" );\n\t\t\t\t}\n\t\t\t\treturn factory( w );\n\t\t\t};\n\t} else {\n\t\tfactory( global );\n\t}\n\n// Pass this if window is not defined yet\n} )( typeof window !== \"undefined\" ? window : this, function( window, noGlobal ) {\n\n// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1\n// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode\n// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common\n// enough that all such attempts are guarded in a try block.\n\"use strict\";\n\nvar arr = [];\n\nvar getProto = Object.getPrototypeOf;\n\nvar slice = arr.slice;\n\nvar flat = arr.flat ? function( array ) {\n\treturn arr.flat.call( array );\n} : function( array ) {\n\treturn arr.concat.apply( [], array );\n};\n\n\nvar push = arr.push;\n\nvar indexOf = arr.indexOf;\n\nvar class2type = {};\n\nvar toString = class2type.toString;\n\nvar hasOwn = class2type.hasOwnProperty;\n\nvar fnToString = hasOwn.toString;\n\nvar ObjectFunctionString = fnToString.call( Object );\n\nvar support = {};\n\nvar isFunction = function isFunction( obj ) {\n\n      // Support: Chrome <=57, Firefox <=52\n      // In some browsers, typeof returns \"function\" for HTML <object> elements\n      // (i.e., `typeof document.createElement( \"object\" ) === \"function\"`).\n      // We don't want to classify *any* DOM node as a function.\n      return typeof obj === \"function\" && typeof obj.nodeType !== \"number\";\n  };\n\n\nvar isWindow = function isWindow( obj ) {\n\t\treturn obj != null && obj === obj.window;\n\t};\n\n\nvar document = window.document;\n\n\n\n\tvar preservedScriptAttributes = {\n\t\ttype: true,\n\t\tsrc: true,\n\t\tnonce: true,\n\t\tnoModule: true\n\t};\n\n\tfunction DOMEval( code, node, doc ) {\n\t\tdoc = doc || document;\n\n\t\tvar i, val,\n\t\t\tscript = doc.createElement( \"script\" );\n\n\t\tscript.text = code;\n\t\tif ( node ) {\n\t\t\tfor ( i in preservedScriptAttributes ) {\n\n\t\t\t\t// Support: Firefox 64+, Edge 18+\n\t\t\t\t// Some browsers don't support the \"nonce\" property on scripts.\n\t\t\t\t// On the other hand, just using `getAttribute` is not enough as\n\t\t\t\t// the `nonce` attribute is reset to an empty string whenever it\n\t\t\t\t// becomes browsing-context connected.\n\t\t\t\t// See https://github.com/whatwg/html/issues/2369\n\t\t\t\t// See https://html.spec.whatwg.org/#nonce-attributes\n\t\t\t\t// The `node.getAttribute` check was added for the sake of\n\t\t\t\t// `jQuery.globalEval` so that it can fake a nonce-containing node\n\t\t\t\t// via an object.\n\t\t\t\tval = node[ i ] || node.getAttribute && node.getAttribute( i );\n\t\t\t\tif ( val ) {\n\t\t\t\t\tscript.setAttribute( i, val );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tdoc.head.appendChild( script ).parentNode.removeChild( script );\n\t}\n\n\nfunction toType( obj ) {\n\tif ( obj == null ) {\n\t\treturn obj + \"\";\n\t}\n\n\t// Support: Android <=2.3 only (functionish RegExp)\n\treturn typeof obj === \"object\" || typeof obj === \"function\" ?\n\t\tclass2type[ toString.call( obj ) ] || \"object\" :\n\t\ttypeof obj;\n}\n/* global Symbol */\n// Defining this global in .eslintrc.json would create a danger of using the global\n// unguarded in another place, it seems safer to define global only for this module\n\n\n\nvar\n\tversion = \"3.5.1\",\n\n\t// Define a local copy of jQuery\n\tjQuery = function( selector, context ) {\n\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\t// Need init if jQuery is called (just allow error to be thrown if not included)\n\t\treturn new jQuery.fn.init( selector, context );\n\t};\n\njQuery.fn = jQuery.prototype = {\n\n\t// The current version of jQuery being used\n\tjquery: version,\n\n\tconstructor: jQuery,\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\ttoArray: function() {\n\t\treturn slice.call( this );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\n\t\t// Return all the elements in a clean array\n\t\tif ( num == null ) {\n\t\t\treturn slice.call( this );\n\t\t}\n\n\t\t// Return just the one element from the set\n\t\treturn num < 0 ? this[ num + this.length ] : this[ num ];\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems ) {\n\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = jQuery.merge( this.constructor(), elems );\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\teach: function( callback ) {\n\t\treturn jQuery.each( this, callback );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map( this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t} ) );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ) );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\teven: function() {\n\t\treturn this.pushStack( jQuery.grep( this, function( _elem, i ) {\n\t\t\treturn ( i + 1 ) % 2;\n\t\t} ) );\n\t},\n\n\todd: function() {\n\t\treturn this.pushStack( jQuery.grep( this, function( _elem, i ) {\n\t\t\treturn i % 2;\n\t\t} ) );\n\t},\n\n\teq: function( i ) {\n\t\tvar len = this.length,\n\t\t\tj = +i + ( i < 0 ? len : 0 );\n\t\treturn this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor();\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: arr.sort,\n\tsplice: arr.splice\n};\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[ 0 ] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\n\t\t// Skip the boolean and the target\n\t\ttarget = arguments[ i ] || {};\n\t\ti++;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !isFunction( target ) ) {\n\t\ttarget = {};\n\t}\n\n\t// Extend jQuery itself if only one argument is passed\n\tif ( i === length ) {\n\t\ttarget = this;\n\t\ti--;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\n\t\t// Only deal with non-null/undefined values\n\t\tif ( ( options = arguments[ i ] ) != null ) {\n\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent Object.prototype pollution\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( name === \"__proto__\" || target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject( copy ) ||\n\t\t\t\t\t( copyIsArray = Array.isArray( copy ) ) ) ) {\n\t\t\t\t\tsrc = target[ name ];\n\n\t\t\t\t\t// Ensure proper type for the source value\n\t\t\t\t\tif ( copyIsArray && !Array.isArray( src ) ) {\n\t\t\t\t\t\tclone = [];\n\t\t\t\t\t} else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) {\n\t\t\t\t\t\tclone = {};\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src;\n\t\t\t\t\t}\n\t\t\t\t\tcopyIsArray = false;\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend( {\n\n\t// Unique for each copy of jQuery on the page\n\texpando: \"jQuery\" + ( version + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// Assume jQuery is ready without the ready module\n\tisReady: true,\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tnoop: function() {},\n\n\tisPlainObject: function( obj ) {\n\t\tvar proto, Ctor;\n\n\t\t// Detect obvious negatives\n\t\t// Use toString instead of jQuery.type to catch host objects\n\t\tif ( !obj || toString.call( obj ) !== \"[object Object]\" ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tproto = getProto( obj );\n\n\t\t// Objects with no prototype (e.g., `Object.create( null )`) are plain\n\t\tif ( !proto ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Objects with prototype are plain iff they were constructed by a global Object function\n\t\tCtor = hasOwn.call( proto, \"constructor\" ) && proto.constructor;\n\t\treturn typeof Ctor === \"function\" && fnToString.call( Ctor ) === ObjectFunctionString;\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tvar name;\n\n\t\tfor ( name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\t// Evaluates a script in a provided context; falls back to the global one\n\t// if not specified.\n\tglobalEval: function( code, options, doc ) {\n\t\tDOMEval( code, { nonce: options && options.nonce }, doc );\n\t},\n\n\teach: function( obj, callback ) {\n\t\tvar length, i = 0;\n\n\t\tif ( isArrayLike( obj ) ) {\n\t\t\tlength = obj.length;\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor ( i in obj ) {\n\t\t\t\tif ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn obj;\n\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( arr, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( arr != null ) {\n\t\t\tif ( isArrayLike( Object( arr ) ) ) {\n\t\t\t\tjQuery.merge( ret,\n\t\t\t\t\ttypeof arr === \"string\" ?\n\t\t\t\t\t[ arr ] : arr\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tpush.call( ret, arr );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, arr, i ) {\n\t\treturn arr == null ? -1 : indexOf.call( arr, elem, i );\n\t},\n\n\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t// push.apply(_, arraylike) throws on ancient WebKit\n\tmerge: function( first, second ) {\n\t\tvar len = +second.length,\n\t\t\tj = 0,\n\t\t\ti = first.length;\n\n\t\tfor ( ; j < len; j++ ) {\n\t\t\tfirst[ i++ ] = second[ j ];\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, invert ) {\n\t\tvar callbackInverse,\n\t\t\tmatches = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tcallbackExpect = !invert;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( ; i < length; i++ ) {\n\t\t\tcallbackInverse = !callback( elems[ i ], i );\n\t\t\tif ( callbackInverse !== callbackExpect ) {\n\t\t\t\tmatches.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn matches;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar length, value,\n\t\t\ti = 0,\n\t\t\tret = [];\n\n\t\t// Go through the array, translating each of the items to their new values\n\t\tif ( isArrayLike( elems ) ) {\n\t\t\tlength = elems.length;\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( i in elems ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn flat( ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// jQuery.support is not used in Core but other projects attach their\n\t// properties to it so it needs to exist.\n\tsupport: support\n} );\n\nif ( typeof Symbol === \"function\" ) {\n\tjQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];\n}\n\n// Populate the class2type map\njQuery.each( \"Boolean Number String Function Array Date RegExp Object Error Symbol\".split( \" \" ),\nfunction( _i, name ) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n} );\n\nfunction isArrayLike( obj ) {\n\n\t// Support: real iOS 8.2 only (not reproducible in simulator)\n\t// `in` check used to prevent JIT error (gh-2145)\n\t// hasOwn isn't used here due to false negatives\n\t// regarding Nodelist length in IE\n\tvar length = !!obj && \"length\" in obj && obj.length,\n\t\ttype = toType( obj );\n\n\tif ( isFunction( obj ) || isWindow( obj ) ) {\n\t\treturn false;\n\t}\n\n\treturn type === \"array\" || length === 0 ||\n\t\ttypeof length === \"number\" && length > 0 && ( length - 1 ) in obj;\n}\nvar Sizzle =\n/*!\n * Sizzle CSS Selector Engine v2.3.5\n * https://sizzlejs.com/\n *\n * Copyright JS Foundation and other contributors\n * Released under the MIT license\n * https://js.foundation/\n *\n * Date: 2020-03-14\n */\n( function( window ) {\nvar i,\n\tsupport,\n\tExpr,\n\tgetText,\n\tisXML,\n\ttokenize,\n\tcompile,\n\tselect,\n\toutermostContext,\n\tsortInput,\n\thasDuplicate,\n\n\t// Local document vars\n\tsetDocument,\n\tdocument,\n\tdocElem,\n\tdocumentIsHTML,\n\trbuggyQSA,\n\trbuggyMatches,\n\tmatches,\n\tcontains,\n\n\t// Instance-specific data\n\texpando = \"sizzle\" + 1 * new Date(),\n\tpreferredDoc = window.document,\n\tdirruns = 0,\n\tdone = 0,\n\tclassCache = createCache(),\n\ttokenCache = createCache(),\n\tcompilerCache = createCache(),\n\tnonnativeSelectorCache = createCache(),\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t}\n\t\treturn 0;\n\t},\n\n\t// Instance methods\n\thasOwn = ( {} ).hasOwnProperty,\n\tarr = [],\n\tpop = arr.pop,\n\tpushNative = arr.push,\n\tpush = arr.push,\n\tslice = arr.slice,\n\n\t// Use a stripped-down indexOf as it's faster than native\n\t// https://jsperf.com/thor-indexof-vs-for/5\n\tindexOf = function( list, elem ) {\n\t\tvar i = 0,\n\t\t\tlen = list.length;\n\t\tfor ( ; i < len; i++ ) {\n\t\t\tif ( list[ i ] === elem ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t},\n\n\tbooleans = \"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|\" +\n\t\t\"ismap|loop|multiple|open|readonly|required|scoped\",\n\n\t// Regular expressions\n\n\t// http://www.w3.org/TR/css3-selectors/#whitespace\n\twhitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n\n\t// https://www.w3.org/TR/css-syntax-3/#ident-token-diagram\n\tidentifier = \"(?:\\\\\\\\[\\\\da-fA-F]{1,6}\" + whitespace +\n\t\t\"?|\\\\\\\\[^\\\\r\\\\n\\\\f]|[\\\\w-]|[^\\0-\\\\x7f])+\",\n\n\t// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors\n\tattributes = \"\\\\[\" + whitespace + \"*(\" + identifier + \")(?:\" + whitespace +\n\n\t\t// Operator (capture 2)\n\t\t\"*([*^$|!~]?=)\" + whitespace +\n\n\t\t// \"Attribute values must be CSS identifiers [capture 5]\n\t\t// or strings [capture 3 or capture 4]\"\n\t\t\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\" + identifier + \"))|)\" +\n\t\twhitespace + \"*\\\\]\",\n\n\tpseudos = \":(\" + identifier + \")(?:\\\\((\" +\n\n\t\t// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:\n\t\t// 1. quoted (capture 3; capture 4 or capture 5)\n\t\t\"('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|\" +\n\n\t\t// 2. simple (capture 6)\n\t\t\"((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + attributes + \")*)|\" +\n\n\t\t// 3. anything else (capture 2)\n\t\t\".*\" +\n\t\t\")\\\\)|)\",\n\n\t// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n\trwhitespace = new RegExp( whitespace + \"+\", \"g\" ),\n\trtrim = new RegExp( \"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" +\n\t\twhitespace + \"+$\", \"g\" ),\n\n\trcomma = new RegExp( \"^\" + whitespace + \"*,\" + whitespace + \"*\" ),\n\trcombinators = new RegExp( \"^\" + whitespace + \"*([>+~]|\" + whitespace + \")\" + whitespace +\n\t\t\"*\" ),\n\trdescend = new RegExp( whitespace + \"|>\" ),\n\n\trpseudo = new RegExp( pseudos ),\n\tridentifier = new RegExp( \"^\" + identifier + \"$\" ),\n\n\tmatchExpr = {\n\t\t\"ID\": new RegExp( \"^#(\" + identifier + \")\" ),\n\t\t\"CLASS\": new RegExp( \"^\\\\.(\" + identifier + \")\" ),\n\t\t\"TAG\": new RegExp( \"^(\" + identifier + \"|[*])\" ),\n\t\t\"ATTR\": new RegExp( \"^\" + attributes ),\n\t\t\"PSEUDO\": new RegExp( \"^\" + pseudos ),\n\t\t\"CHILD\": new RegExp( \"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" +\n\t\t\twhitespace + \"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" +\n\t\t\twhitespace + \"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\" ),\n\t\t\"bool\": new RegExp( \"^(?:\" + booleans + \")$\", \"i\" ),\n\n\t\t// For use in libraries implementing .is()\n\t\t// We use this for POS matching in `select`\n\t\t\"needsContext\": new RegExp( \"^\" + whitespace +\n\t\t\t\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" + whitespace +\n\t\t\t\"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\", \"i\" )\n\t},\n\n\trhtml = /HTML$/i,\n\trinputs = /^(?:input|select|textarea|button)$/i,\n\trheader = /^h\\d$/i,\n\n\trnative = /^[^{]+\\{\\s*\\[native \\w/,\n\n\t// Easily-parseable/retrievable ID or TAG or CLASS selectors\n\trquickExpr = /^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,\n\n\trsibling = /[+~]/,\n\n\t// CSS escapes\n\t// http://www.w3.org/TR/CSS21/syndata.html#escaped-characters\n\trunescape = new RegExp( \"\\\\\\\\[\\\\da-fA-F]{1,6}\" + whitespace + \"?|\\\\\\\\([^\\\\r\\\\n\\\\f])\", \"g\" ),\n\tfunescape = function( escape, nonHex ) {\n\t\tvar high = \"0x\" + escape.slice( 1 ) - 0x10000;\n\n\t\treturn nonHex ?\n\n\t\t\t// Strip the backslash prefix from a non-hex escape sequence\n\t\t\tnonHex :\n\n\t\t\t// Replace a hexadecimal escape sequence with the encoded Unicode code point\n\t\t\t// Support: IE <=11+\n\t\t\t// For values outside the Basic Multilingual Plane (BMP), manually construct a\n\t\t\t// surrogate pair\n\t\t\thigh < 0 ?\n\t\t\t\tString.fromCharCode( high + 0x10000 ) :\n\t\t\t\tString.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );\n\t},\n\n\t// CSS string/identifier serialization\n\t// https://drafts.csswg.org/cssom/#common-serializing-idioms\n\trcssescape = /([\\0-\\x1f\\x7f]|^-?\\d)|^-$|[^\\0-\\x1f\\x7f-\\uFFFF\\w-]/g,\n\tfcssescape = function( ch, asCodePoint ) {\n\t\tif ( asCodePoint ) {\n\n\t\t\t// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER\n\t\t\tif ( ch === \"\\0\" ) {\n\t\t\t\treturn \"\\uFFFD\";\n\t\t\t}\n\n\t\t\t// Control characters and (dependent upon position) numbers get escaped as code points\n\t\t\treturn ch.slice( 0, -1 ) + \"\\\\\" +\n\t\t\t\tch.charCodeAt( ch.length - 1 ).toString( 16 ) + \" \";\n\t\t}\n\n\t\t// Other potentially-special ASCII characters get backslash-escaped\n\t\treturn \"\\\\\" + ch;\n\t},\n\n\t// Used for iframes\n\t// See setDocument()\n\t// Removing the function wrapper causes a \"Permission Denied\"\n\t// error in IE\n\tunloadHandler = function() {\n\t\tsetDocument();\n\t},\n\n\tinDisabledFieldset = addCombinator(\n\t\tfunction( elem ) {\n\t\t\treturn elem.disabled === true && elem.nodeName.toLowerCase() === \"fieldset\";\n\t\t},\n\t\t{ dir: \"parentNode\", next: \"legend\" }\n\t);\n\n// Optimize for push.apply( _, NodeList )\ntry {\n\tpush.apply(\n\t\t( arr = slice.call( preferredDoc.childNodes ) ),\n\t\tpreferredDoc.childNodes\n\t);\n\n\t// Support: Android<4.0\n\t// Detect silently failing push.apply\n\t// eslint-disable-next-line no-unused-expressions\n\tarr[ preferredDoc.childNodes.length ].nodeType;\n} catch ( e ) {\n\tpush = { apply: arr.length ?\n\n\t\t// Leverage slice if possible\n\t\tfunction( target, els ) {\n\t\t\tpushNative.apply( target, slice.call( els ) );\n\t\t} :\n\n\t\t// Support: IE<9\n\t\t// Otherwise append directly\n\t\tfunction( target, els ) {\n\t\t\tvar j = target.length,\n\t\t\t\ti = 0;\n\n\t\t\t// Can't trust NodeList.length\n\t\t\twhile ( ( target[ j++ ] = els[ i++ ] ) ) {}\n\t\t\ttarget.length = j - 1;\n\t\t}\n\t};\n}\n\nfunction Sizzle( selector, context, results, seed ) {\n\tvar m, i, elem, nid, match, groups, newSelector,\n\t\tnewContext = context && context.ownerDocument,\n\n\t\t// nodeType defaults to 9, since context defaults to document\n\t\tnodeType = context ? context.nodeType : 9;\n\n\tresults = results || [];\n\n\t// Return early from calls with invalid selector or context\n\tif ( typeof selector !== \"string\" || !selector ||\n\t\tnodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {\n\n\t\treturn results;\n\t}\n\n\t// Try to shortcut find operations (as opposed to filters) in HTML documents\n\tif ( !seed ) {\n\t\tsetDocument( context );\n\t\tcontext = context || document;\n\n\t\tif ( documentIsHTML ) {\n\n\t\t\t// If the selector is sufficiently simple, try using a \"get*By*\" DOM method\n\t\t\t// (excepting DocumentFragment context, where the methods don't exist)\n\t\t\tif ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) {\n\n\t\t\t\t// ID selector\n\t\t\t\tif ( ( m = match[ 1 ] ) ) {\n\n\t\t\t\t\t// Document context\n\t\t\t\t\tif ( nodeType === 9 ) {\n\t\t\t\t\t\tif ( ( elem = context.getElementById( m ) ) ) {\n\n\t\t\t\t\t\t\t// Support: IE, Opera, Webkit\n\t\t\t\t\t\t\t// TODO: identify versions\n\t\t\t\t\t\t\t// getElementById can match elements by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === m ) {\n\t\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t// Element context\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// Support: IE, Opera, Webkit\n\t\t\t\t\t\t// TODO: identify versions\n\t\t\t\t\t\t// getElementById can match elements by name instead of ID\n\t\t\t\t\t\tif ( newContext && ( elem = newContext.getElementById( m ) ) &&\n\t\t\t\t\t\t\tcontains( context, elem ) &&\n\t\t\t\t\t\t\telem.id === m ) {\n\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t// Type selector\n\t\t\t\t} else if ( match[ 2 ] ) {\n\t\t\t\t\tpush.apply( results, context.getElementsByTagName( selector ) );\n\t\t\t\t\treturn results;\n\n\t\t\t\t// Class selector\n\t\t\t\t} else if ( ( m = match[ 3 ] ) && support.getElementsByClassName &&\n\t\t\t\t\tcontext.getElementsByClassName ) {\n\n\t\t\t\t\tpush.apply( results, context.getElementsByClassName( m ) );\n\t\t\t\t\treturn results;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Take advantage of querySelectorAll\n\t\t\tif ( support.qsa &&\n\t\t\t\t!nonnativeSelectorCache[ selector + \" \" ] &&\n\t\t\t\t( !rbuggyQSA || !rbuggyQSA.test( selector ) ) &&\n\n\t\t\t\t// Support: IE 8 only\n\t\t\t\t// Exclude object elements\n\t\t\t\t( nodeType !== 1 || context.nodeName.toLowerCase() !== \"object\" ) ) {\n\n\t\t\t\tnewSelector = selector;\n\t\t\t\tnewContext = context;\n\n\t\t\t\t// qSA considers elements outside a scoping root when evaluating child or\n\t\t\t\t// descendant combinators, which is not what we want.\n\t\t\t\t// In such cases, we work around the behavior by prefixing every selector in the\n\t\t\t\t// list with an ID selector referencing the scope context.\n\t\t\t\t// The technique has to be used as well when a leading combinator is used\n\t\t\t\t// as such selectors are not recognized by querySelectorAll.\n\t\t\t\t// Thanks to Andrew Dupont for this technique.\n\t\t\t\tif ( nodeType === 1 &&\n\t\t\t\t\t( rdescend.test( selector ) || rcombinators.test( selector ) ) ) {\n\n\t\t\t\t\t// Expand context for sibling selectors\n\t\t\t\t\tnewContext = rsibling.test( selector ) && testContext( context.parentNode ) ||\n\t\t\t\t\t\tcontext;\n\n\t\t\t\t\t// We can use :scope instead of the ID hack if the browser\n\t\t\t\t\t// supports it & if we're not changing the context.\n\t\t\t\t\tif ( newContext !== context || !support.scope ) {\n\n\t\t\t\t\t\t// Capture the context ID, setting it first if necessary\n\t\t\t\t\t\tif ( ( nid = context.getAttribute( \"id\" ) ) ) {\n\t\t\t\t\t\t\tnid = nid.replace( rcssescape, fcssescape );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcontext.setAttribute( \"id\", ( nid = expando ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prefix every selector in the list\n\t\t\t\t\tgroups = tokenize( selector );\n\t\t\t\t\ti = groups.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tgroups[ i ] = ( nid ? \"#\" + nid : \":scope\" ) + \" \" +\n\t\t\t\t\t\t\ttoSelector( groups[ i ] );\n\t\t\t\t\t}\n\t\t\t\t\tnewSelector = groups.join( \",\" );\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tpush.apply( results,\n\t\t\t\t\t\tnewContext.querySelectorAll( newSelector )\n\t\t\t\t\t);\n\t\t\t\t\treturn results;\n\t\t\t\t} catch ( qsaError ) {\n\t\t\t\t\tnonnativeSelectorCache( selector, true );\n\t\t\t\t} finally {\n\t\t\t\t\tif ( nid === expando ) {\n\t\t\t\t\t\tcontext.removeAttribute( \"id\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// All others\n\treturn select( selector.replace( rtrim, \"$1\" ), context, results, seed );\n}\n\n/**\n * Create key-value caches of limited size\n * @returns {function(string, object)} Returns the Object data after storing it on itself with\n *\tproperty name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)\n *\tdeleting the oldest entry\n */\nfunction createCache() {\n\tvar keys = [];\n\n\tfunction cache( key, value ) {\n\n\t\t// Use (key + \" \") to avoid collision with native prototype properties (see Issue #157)\n\t\tif ( keys.push( key + \" \" ) > Expr.cacheLength ) {\n\n\t\t\t// Only keep the most recent entries\n\t\t\tdelete cache[ keys.shift() ];\n\t\t}\n\t\treturn ( cache[ key + \" \" ] = value );\n\t}\n\treturn cache;\n}\n\n/**\n * Mark a function for special use by Sizzle\n * @param {Function} fn The function to mark\n */\nfunction markFunction( fn ) {\n\tfn[ expando ] = true;\n\treturn fn;\n}\n\n/**\n * Support testing using an element\n * @param {Function} fn Passed the created element and returns a boolean result\n */\nfunction assert( fn ) {\n\tvar el = document.createElement( \"fieldset\" );\n\n\ttry {\n\t\treturn !!fn( el );\n\t} catch ( e ) {\n\t\treturn false;\n\t} finally {\n\n\t\t// Remove from its parent by default\n\t\tif ( el.parentNode ) {\n\t\t\tel.parentNode.removeChild( el );\n\t\t}\n\n\t\t// release memory in IE\n\t\tel = null;\n\t}\n}\n\n/**\n * Adds the same handler for all of the specified attrs\n * @param {String} attrs Pipe-separated list of attributes\n * @param {Function} handler The method that will be applied\n */\nfunction addHandle( attrs, handler ) {\n\tvar arr = attrs.split( \"|\" ),\n\t\ti = arr.length;\n\n\twhile ( i-- ) {\n\t\tExpr.attrHandle[ arr[ i ] ] = handler;\n\t}\n}\n\n/**\n * Checks document order of two siblings\n * @param {Element} a\n * @param {Element} b\n * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b\n */\nfunction siblingCheck( a, b ) {\n\tvar cur = b && a,\n\t\tdiff = cur && a.nodeType === 1 && b.nodeType === 1 &&\n\t\t\ta.sourceIndex - b.sourceIndex;\n\n\t// Use IE sourceIndex if available on both nodes\n\tif ( diff ) {\n\t\treturn diff;\n\t}\n\n\t// Check if b follows a\n\tif ( cur ) {\n\t\twhile ( ( cur = cur.nextSibling ) ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn a ? 1 : -1;\n}\n\n/**\n * Returns a function to use in pseudos for input types\n * @param {String} type\n */\nfunction createInputPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn name === \"input\" && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for buttons\n * @param {String} type\n */\nfunction createButtonPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn ( name === \"input\" || name === \"button\" ) && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for :enabled/:disabled\n * @param {Boolean} disabled true for :disabled; false for :enabled\n */\nfunction createDisabledPseudo( disabled ) {\n\n\t// Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable\n\treturn function( elem ) {\n\n\t\t// Only certain elements can match :enabled or :disabled\n\t\t// https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled\n\t\t// https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled\n\t\tif ( \"form\" in elem ) {\n\n\t\t\t// Check for inherited disabledness on relevant non-disabled elements:\n\t\t\t// * listed form-associated elements in a disabled fieldset\n\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#category-listed\n\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled\n\t\t\t// * option elements in a disabled optgroup\n\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled\n\t\t\t// All such elements have a \"form\" property.\n\t\t\tif ( elem.parentNode && elem.disabled === false ) {\n\n\t\t\t\t// Option elements defer to a parent optgroup if present\n\t\t\t\tif ( \"label\" in elem ) {\n\t\t\t\t\tif ( \"label\" in elem.parentNode ) {\n\t\t\t\t\t\treturn elem.parentNode.disabled === disabled;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn elem.disabled === disabled;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Support: IE 6 - 11\n\t\t\t\t// Use the isDisabled shortcut property to check for disabled fieldset ancestors\n\t\t\t\treturn elem.isDisabled === disabled ||\n\n\t\t\t\t\t// Where there is no isDisabled, check manually\n\t\t\t\t\t/* jshint -W018 */\n\t\t\t\t\telem.isDisabled !== !disabled &&\n\t\t\t\t\tinDisabledFieldset( elem ) === disabled;\n\t\t\t}\n\n\t\t\treturn elem.disabled === disabled;\n\n\t\t// Try to winnow out elements that can't be disabled before trusting the disabled property.\n\t\t// Some victims get caught in our net (label, legend, menu, track), but it shouldn't\n\t\t// even exist on them, let alone have a boolean value.\n\t\t} else if ( \"label\" in elem ) {\n\t\t\treturn elem.disabled === disabled;\n\t\t}\n\n\t\t// Remaining elements are neither :enabled nor :disabled\n\t\treturn false;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for positionals\n * @param {Function} fn\n */\nfunction createPositionalPseudo( fn ) {\n\treturn markFunction( function( argument ) {\n\t\targument = +argument;\n\t\treturn markFunction( function( seed, matches ) {\n\t\t\tvar j,\n\t\t\t\tmatchIndexes = fn( [], seed.length, argument ),\n\t\t\t\ti = matchIndexes.length;\n\n\t\t\t// Match elements found at the specified indexes\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( seed[ ( j = matchIndexes[ i ] ) ] ) {\n\t\t\t\t\tseed[ j ] = !( matches[ j ] = seed[ j ] );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t} );\n}\n\n/**\n * Checks a node for validity as a Sizzle context\n * @param {Element|Object=} context\n * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value\n */\nfunction testContext( context ) {\n\treturn context && typeof context.getElementsByTagName !== \"undefined\" && context;\n}\n\n// Expose support vars for convenience\nsupport = Sizzle.support = {};\n\n/**\n * Detects XML nodes\n * @param {Element|Object} elem An element or a document\n * @returns {Boolean} True iff elem is a non-HTML XML node\n */\nisXML = Sizzle.isXML = function( elem ) {\n\tvar namespace = elem.namespaceURI,\n\t\tdocElem = ( elem.ownerDocument || elem ).documentElement;\n\n\t// Support: IE <=8\n\t// Assume HTML when documentElement doesn't yet exist, such as inside loading iframes\n\t// https://bugs.jquery.com/ticket/4833\n\treturn !rhtml.test( namespace || docElem && docElem.nodeName || \"HTML\" );\n};\n\n/**\n * Sets document-related variables once based on the current document\n * @param {Element|Object} [doc] An element or document object to use to set the document\n * @returns {Object} Returns the current document\n */\nsetDocument = Sizzle.setDocument = function( node ) {\n\tvar hasCompare, subWindow,\n\t\tdoc = node ? node.ownerDocument || node : preferredDoc;\n\n\t// Return early if doc is invalid or already selected\n\t// Support: IE 11+, Edge 17 - 18+\n\t// IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n\t// two documents; shallow comparisons work.\n\t// eslint-disable-next-line eqeqeq\n\tif ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) {\n\t\treturn document;\n\t}\n\n\t// Update global variables\n\tdocument = doc;\n\tdocElem = document.documentElement;\n\tdocumentIsHTML = !isXML( document );\n\n\t// Support: IE 9 - 11+, Edge 12 - 18+\n\t// Accessing iframe documents after unload throws \"permission denied\" errors (jQuery #13936)\n\t// Support: IE 11+, Edge 17 - 18+\n\t// IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n\t// two documents; shallow comparisons work.\n\t// eslint-disable-next-line eqeqeq\n\tif ( preferredDoc != document &&\n\t\t( subWindow = document.defaultView ) && subWindow.top !== subWindow ) {\n\n\t\t// Support: IE 11, Edge\n\t\tif ( subWindow.addEventListener ) {\n\t\t\tsubWindow.addEventListener( \"unload\", unloadHandler, false );\n\n\t\t// Support: IE 9 - 10 only\n\t\t} else if ( subWindow.attachEvent ) {\n\t\t\tsubWindow.attachEvent( \"onunload\", unloadHandler );\n\t\t}\n\t}\n\n\t// Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only,\n\t// Safari 4 - 5 only, Opera <=11.6 - 12.x only\n\t// IE/Edge & older browsers don't support the :scope pseudo-class.\n\t// Support: Safari 6.0 only\n\t// Safari 6.0 supports :scope but it's an alias of :root there.\n\tsupport.scope = assert( function( el ) {\n\t\tdocElem.appendChild( el ).appendChild( document.createElement( \"div\" ) );\n\t\treturn typeof el.querySelectorAll !== \"undefined\" &&\n\t\t\t!el.querySelectorAll( \":scope fieldset div\" ).length;\n\t} );\n\n\t/* Attributes\n\t---------------------------------------------------------------------- */\n\n\t// Support: IE<8\n\t// Verify that getAttribute really returns attributes and not properties\n\t// (excepting IE8 booleans)\n\tsupport.attributes = assert( function( el ) {\n\t\tel.className = \"i\";\n\t\treturn !el.getAttribute( \"className\" );\n\t} );\n\n\t/* getElement(s)By*\n\t---------------------------------------------------------------------- */\n\n\t// Check if getElementsByTagName(\"*\") returns only elements\n\tsupport.getElementsByTagName = assert( function( el ) {\n\t\tel.appendChild( document.createComment( \"\" ) );\n\t\treturn !el.getElementsByTagName( \"*\" ).length;\n\t} );\n\n\t// Support: IE<9\n\tsupport.getElementsByClassName = rnative.test( document.getElementsByClassName );\n\n\t// Support: IE<10\n\t// Check if getElementById returns elements by name\n\t// The broken getElementById methods don't pick up programmatically-set names,\n\t// so use a roundabout getElementsByName test\n\tsupport.getById = assert( function( el ) {\n\t\tdocElem.appendChild( el ).id = expando;\n\t\treturn !document.getElementsByName || !document.getElementsByName( expando ).length;\n\t} );\n\n\t// ID filter and find\n\tif ( support.getById ) {\n\t\tExpr.filter[ \"ID\" ] = function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn elem.getAttribute( \"id\" ) === attrId;\n\t\t\t};\n\t\t};\n\t\tExpr.find[ \"ID\" ] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n\t\t\t\tvar elem = context.getElementById( id );\n\t\t\t\treturn elem ? [ elem ] : [];\n\t\t\t}\n\t\t};\n\t} else {\n\t\tExpr.filter[ \"ID\" ] =  function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" &&\n\t\t\t\t\telem.getAttributeNode( \"id\" );\n\t\t\t\treturn node && node.value === attrId;\n\t\t\t};\n\t\t};\n\n\t\t// Support: IE 6 - 7 only\n\t\t// getElementById is not reliable as a find shortcut\n\t\tExpr.find[ \"ID\" ] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n\t\t\t\tvar node, i, elems,\n\t\t\t\t\telem = context.getElementById( id );\n\n\t\t\t\tif ( elem ) {\n\n\t\t\t\t\t// Verify the id attribute\n\t\t\t\t\tnode = elem.getAttributeNode( \"id\" );\n\t\t\t\t\tif ( node && node.value === id ) {\n\t\t\t\t\t\treturn [ elem ];\n\t\t\t\t\t}\n\n\t\t\t\t\t// Fall back on getElementsByName\n\t\t\t\t\telems = context.getElementsByName( id );\n\t\t\t\t\ti = 0;\n\t\t\t\t\twhile ( ( elem = elems[ i++ ] ) ) {\n\t\t\t\t\t\tnode = elem.getAttributeNode( \"id\" );\n\t\t\t\t\t\tif ( node && node.value === id ) {\n\t\t\t\t\t\t\treturn [ elem ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn [];\n\t\t\t}\n\t\t};\n\t}\n\n\t// Tag\n\tExpr.find[ \"TAG\" ] = support.getElementsByTagName ?\n\t\tfunction( tag, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( tag );\n\n\t\t\t// DocumentFragment nodes don't have gEBTN\n\t\t\t} else if ( support.qsa ) {\n\t\t\t\treturn context.querySelectorAll( tag );\n\t\t\t}\n\t\t} :\n\n\t\tfunction( tag, context ) {\n\t\t\tvar elem,\n\t\t\t\ttmp = [],\n\t\t\t\ti = 0,\n\n\t\t\t\t// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too\n\t\t\t\tresults = context.getElementsByTagName( tag );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( tag === \"*\" ) {\n\t\t\t\twhile ( ( elem = results[ i++ ] ) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn tmp;\n\t\t\t}\n\t\t\treturn results;\n\t\t};\n\n\t// Class\n\tExpr.find[ \"CLASS\" ] = support.getElementsByClassName && function( className, context ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && documentIsHTML ) {\n\t\t\treturn context.getElementsByClassName( className );\n\t\t}\n\t};\n\n\t/* QSA/matchesSelector\n\t---------------------------------------------------------------------- */\n\n\t// QSA and matchesSelector support\n\n\t// matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n\trbuggyMatches = [];\n\n\t// qSa(:focus) reports false when true (Chrome 21)\n\t// We allow this because of a bug in IE8/9 that throws an error\n\t// whenever `document.activeElement` is accessed on an iframe\n\t// So, we allow :focus to pass through QSA all the time to avoid the IE error\n\t// See https://bugs.jquery.com/ticket/13378\n\trbuggyQSA = [];\n\n\tif ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) {\n\n\t\t// Build QSA regex\n\t\t// Regex strategy adopted from Diego Perini\n\t\tassert( function( el ) {\n\n\t\t\tvar input;\n\n\t\t\t// Select is set to empty string on purpose\n\t\t\t// This is to test IE's treatment of not explicitly\n\t\t\t// setting a boolean content attribute,\n\t\t\t// since its presence should be enough\n\t\t\t// https://bugs.jquery.com/ticket/12359\n\t\t\tdocElem.appendChild( el ).innerHTML = \"<a id='\" + expando + \"'></a>\" +\n\t\t\t\t\"<select id='\" + expando + \"-\\r\\\\' msallowcapture=''>\" +\n\t\t\t\t\"<option selected=''></option></select>\";\n\n\t\t\t// Support: IE8, Opera 11-12.16\n\t\t\t// Nothing should be selected when empty strings follow ^= or $= or *=\n\t\t\t// The test attribute must be unknown in Opera but \"safe\" for WinRT\n\t\t\t// https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section\n\t\t\tif ( el.querySelectorAll( \"[msallowcapture^='']\" ).length ) {\n\t\t\t\trbuggyQSA.push( \"[*^$]=\" + whitespace + \"*(?:''|\\\"\\\")\" );\n\t\t\t}\n\n\t\t\t// Support: IE8\n\t\t\t// Boolean attributes and \"value\" are not treated correctly\n\t\t\tif ( !el.querySelectorAll( \"[selected]\" ).length ) {\n\t\t\t\trbuggyQSA.push( \"\\\\[\" + whitespace + \"*(?:value|\" + booleans + \")\" );\n\t\t\t}\n\n\t\t\t// Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+\n\t\t\tif ( !el.querySelectorAll( \"[id~=\" + expando + \"-]\" ).length ) {\n\t\t\t\trbuggyQSA.push( \"~=\" );\n\t\t\t}\n\n\t\t\t// Support: IE 11+, Edge 15 - 18+\n\t\t\t// IE 11/Edge don't find elements on a `[name='']` query in some cases.\n\t\t\t// Adding a temporary attribute to the document before the selection works\n\t\t\t// around the issue.\n\t\t\t// Interestingly, IE 10 & older don't seem to have the issue.\n\t\t\tinput = document.createElement( \"input\" );\n\t\t\tinput.setAttribute( \"name\", \"\" );\n\t\t\tel.appendChild( input );\n\t\t\tif ( !el.querySelectorAll( \"[name='']\" ).length ) {\n\t\t\t\trbuggyQSA.push( \"\\\\[\" + whitespace + \"*name\" + whitespace + \"*=\" +\n\t\t\t\t\twhitespace + \"*(?:''|\\\"\\\")\" );\n\t\t\t}\n\n\t\t\t// Webkit/Opera - :checked should return selected option elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !el.querySelectorAll( \":checked\" ).length ) {\n\t\t\t\trbuggyQSA.push( \":checked\" );\n\t\t\t}\n\n\t\t\t// Support: Safari 8+, iOS 8+\n\t\t\t// https://bugs.webkit.org/show_bug.cgi?id=136851\n\t\t\t// In-page `selector#id sibling-combinator selector` fails\n\t\t\tif ( !el.querySelectorAll( \"a#\" + expando + \"+*\" ).length ) {\n\t\t\t\trbuggyQSA.push( \".#.+[+~]\" );\n\t\t\t}\n\n\t\t\t// Support: Firefox <=3.6 - 5 only\n\t\t\t// Old Firefox doesn't throw on a badly-escaped identifier.\n\t\t\tel.querySelectorAll( \"\\\\\\f\" );\n\t\t\trbuggyQSA.push( \"[\\\\r\\\\n\\\\f]\" );\n\t\t} );\n\n\t\tassert( function( el ) {\n\t\t\tel.innerHTML = \"<a href='' disabled='disabled'></a>\" +\n\t\t\t\t\"<select disabled='disabled'><option/></select>\";\n\n\t\t\t// Support: Windows 8 Native Apps\n\t\t\t// The type and name attributes are restricted during .innerHTML assignment\n\t\t\tvar input = document.createElement( \"input\" );\n\t\t\tinput.setAttribute( \"type\", \"hidden\" );\n\t\t\tel.appendChild( input ).setAttribute( \"name\", \"D\" );\n\n\t\t\t// Support: IE8\n\t\t\t// Enforce case-sensitivity of name attribute\n\t\t\tif ( el.querySelectorAll( \"[name=d]\" ).length ) {\n\t\t\t\trbuggyQSA.push( \"name\" + whitespace + \"*[*^$|!~]?=\" );\n\t\t\t}\n\n\t\t\t// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( el.querySelectorAll( \":enabled\" ).length !== 2 ) {\n\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t}\n\n\t\t\t// Support: IE9-11+\n\t\t\t// IE's :disabled selector does not pick up the children of disabled fieldsets\n\t\t\tdocElem.appendChild( el ).disabled = true;\n\t\t\tif ( el.querySelectorAll( \":disabled\" ).length !== 2 ) {\n\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t}\n\n\t\t\t// Support: Opera 10 - 11 only\n\t\t\t// Opera 10-11 does not throw on post-comma invalid pseudos\n\t\t\tel.querySelectorAll( \"*,:x\" );\n\t\t\trbuggyQSA.push( \",.*:\" );\n\t\t} );\n\t}\n\n\tif ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches ||\n\t\tdocElem.webkitMatchesSelector ||\n\t\tdocElem.mozMatchesSelector ||\n\t\tdocElem.oMatchesSelector ||\n\t\tdocElem.msMatchesSelector ) ) ) ) {\n\n\t\tassert( function( el ) {\n\n\t\t\t// Check to see if it's possible to do matchesSelector\n\t\t\t// on a disconnected node (IE 9)\n\t\t\tsupport.disconnectedMatch = matches.call( el, \"*\" );\n\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( el, \"[s!='']:x\" );\n\t\t\trbuggyMatches.push( \"!=\", pseudos );\n\t\t} );\n\t}\n\n\trbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( \"|\" ) );\n\trbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( \"|\" ) );\n\n\t/* Contains\n\t---------------------------------------------------------------------- */\n\thasCompare = rnative.test( docElem.compareDocumentPosition );\n\n\t// Element contains another\n\t// Purposefully self-exclusive\n\t// As in, an element does not contain itself\n\tcontains = hasCompare || rnative.test( docElem.contains ) ?\n\t\tfunction( a, b ) {\n\t\t\tvar adown = a.nodeType === 9 ? a.documentElement : a,\n\t\t\t\tbup = b && b.parentNode;\n\t\t\treturn a === bup || !!( bup && bup.nodeType === 1 && (\n\t\t\t\tadown.contains ?\n\t\t\t\t\tadown.contains( bup ) :\n\t\t\t\t\ta.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16\n\t\t\t) );\n\t\t} :\n\t\tfunction( a, b ) {\n\t\t\tif ( b ) {\n\t\t\t\twhile ( ( b = b.parentNode ) ) {\n\t\t\t\t\tif ( b === a ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n\n\t/* Sorting\n\t---------------------------------------------------------------------- */\n\n\t// Document order sorting\n\tsortOrder = hasCompare ?\n\tfunction( a, b ) {\n\n\t\t// Flag for duplicate removal\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\t// Sort on method existence if only one input has compareDocumentPosition\n\t\tvar compare = !a.compareDocumentPosition - !b.compareDocumentPosition;\n\t\tif ( compare ) {\n\t\t\treturn compare;\n\t\t}\n\n\t\t// Calculate position if both inputs belong to the same document\n\t\t// Support: IE 11+, Edge 17 - 18+\n\t\t// IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n\t\t// two documents; shallow comparisons work.\n\t\t// eslint-disable-next-line eqeqeq\n\t\tcompare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ?\n\t\t\ta.compareDocumentPosition( b ) :\n\n\t\t\t// Otherwise we know they are disconnected\n\t\t\t1;\n\n\t\t// Disconnected nodes\n\t\tif ( compare & 1 ||\n\t\t\t( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) {\n\n\t\t\t// Choose the first element that is related to our preferred document\n\t\t\t// Support: IE 11+, Edge 17 - 18+\n\t\t\t// IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n\t\t\t// two documents; shallow comparisons work.\n\t\t\t// eslint-disable-next-line eqeqeq\n\t\t\tif ( a == document || a.ownerDocument == preferredDoc &&\n\t\t\t\tcontains( preferredDoc, a ) ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\n\t\t\t// Support: IE 11+, Edge 17 - 18+\n\t\t\t// IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n\t\t\t// two documents; shallow comparisons work.\n\t\t\t// eslint-disable-next-line eqeqeq\n\t\t\tif ( b == document || b.ownerDocument == preferredDoc &&\n\t\t\t\tcontains( preferredDoc, b ) ) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\t// Maintain original order\n\t\t\treturn sortInput ?\n\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t0;\n\t\t}\n\n\t\treturn compare & 4 ? -1 : 1;\n\t} :\n\tfunction( a, b ) {\n\n\t\t// Exit early if the nodes are identical\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tap = [ a ],\n\t\t\tbp = [ b ];\n\n\t\t// Parentless nodes are either documents or disconnected\n\t\tif ( !aup || !bup ) {\n\n\t\t\t// Support: IE 11+, Edge 17 - 18+\n\t\t\t// IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n\t\t\t// two documents; shallow comparisons work.\n\t\t\t/* eslint-disable eqeqeq */\n\t\t\treturn a == document ? -1 :\n\t\t\t\tb == document ? 1 :\n\t\t\t\t/* eslint-enable eqeqeq */\n\t\t\t\taup ? -1 :\n\t\t\t\tbup ? 1 :\n\t\t\t\tsortInput ?\n\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t0;\n\n\t\t// If the nodes are siblings, we can do a quick check\n\t\t} else if ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\t\t}\n\n\t\t// Otherwise we need full lists of their ancestors for comparison\n\t\tcur = a;\n\t\twhile ( ( cur = cur.parentNode ) ) {\n\t\t\tap.unshift( cur );\n\t\t}\n\t\tcur = b;\n\t\twhile ( ( cur = cur.parentNode ) ) {\n\t\t\tbp.unshift( cur );\n\t\t}\n\n\t\t// Walk down the tree looking for a discrepancy\n\t\twhile ( ap[ i ] === bp[ i ] ) {\n\t\t\ti++;\n\t\t}\n\n\t\treturn i ?\n\n\t\t\t// Do a sibling check if the nodes have a common ancestor\n\t\t\tsiblingCheck( ap[ i ], bp[ i ] ) :\n\n\t\t\t// Otherwise nodes in our document sort first\n\t\t\t// Support: IE 11+, Edge 17 - 18+\n\t\t\t// IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n\t\t\t// two documents; shallow comparisons work.\n\t\t\t/* eslint-disable eqeqeq */\n\t\t\tap[ i ] == preferredDoc ? -1 :\n\t\t\tbp[ i ] == preferredDoc ? 1 :\n\t\t\t/* eslint-enable eqeqeq */\n\t\t\t0;\n\t};\n\n\treturn document;\n};\n\nSizzle.matches = function( expr, elements ) {\n\treturn Sizzle( expr, null, null, elements );\n};\n\nSizzle.matchesSelector = function( elem, expr ) {\n\tsetDocument( elem );\n\n\tif ( support.matchesSelector && documentIsHTML &&\n\t\t!nonnativeSelectorCache[ expr + \" \" ] &&\n\t\t( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&\n\t\t( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {\n\n\t\ttry {\n\t\t\tvar ret = matches.call( elem, expr );\n\n\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\tif ( ret || support.disconnectedMatch ||\n\n\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t// fragment in IE 9\n\t\t\t\telem.document && elem.document.nodeType !== 11 ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\tnonnativeSelectorCache( expr, true );\n\t\t}\n\t}\n\n\treturn Sizzle( expr, document, null, [ elem ] ).length > 0;\n};\n\nSizzle.contains = function( context, elem ) {\n\n\t// Set document vars if needed\n\t// Support: IE 11+, Edge 17 - 18+\n\t// IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n\t// two documents; shallow comparisons work.\n\t// eslint-disable-next-line eqeqeq\n\tif ( ( context.ownerDocument || context ) != document ) {\n\t\tsetDocument( context );\n\t}\n\treturn contains( context, elem );\n};\n\nSizzle.attr = function( elem, name ) {\n\n\t// Set document vars if needed\n\t// Support: IE 11+, Edge 17 - 18+\n\t// IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n\t// two documents; shallow comparisons work.\n\t// eslint-disable-next-line eqeqeq\n\tif ( ( elem.ownerDocument || elem ) != document ) {\n\t\tsetDocument( elem );\n\t}\n\n\tvar fn = Expr.attrHandle[ name.toLowerCase() ],\n\n\t\t// Don't get fooled by Object.prototype properties (jQuery #13807)\n\t\tval = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?\n\t\t\tfn( elem, name, !documentIsHTML ) :\n\t\t\tundefined;\n\n\treturn val !== undefined ?\n\t\tval :\n\t\tsupport.attributes || !documentIsHTML ?\n\t\t\telem.getAttribute( name ) :\n\t\t\t( val = elem.getAttributeNode( name ) ) && val.specified ?\n\t\t\t\tval.value :\n\t\t\t\tnull;\n};\n\nSizzle.escape = function( sel ) {\n\treturn ( sel + \"\" ).replace( rcssescape, fcssescape );\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Document sorting and removing duplicates\n * @param {ArrayLike} results\n */\nSizzle.uniqueSort = function( results ) {\n\tvar elem,\n\t\tduplicates = [],\n\t\tj = 0,\n\t\ti = 0;\n\n\t// Unless we *know* we can detect duplicates, assume their presence\n\thasDuplicate = !support.detectDuplicates;\n\tsortInput = !support.sortStable && results.slice( 0 );\n\tresults.sort( sortOrder );\n\n\tif ( hasDuplicate ) {\n\t\twhile ( ( elem = results[ i++ ] ) ) {\n\t\t\tif ( elem === results[ i ] ) {\n\t\t\t\tj = duplicates.push( i );\n\t\t\t}\n\t\t}\n\t\twhile ( j-- ) {\n\t\t\tresults.splice( duplicates[ j ], 1 );\n\t\t}\n\t}\n\n\t// Clear input after sorting to release objects\n\t// See https://github.com/jquery/sizzle/pull/225\n\tsortInput = null;\n\n\treturn results;\n};\n\n/**\n * Utility function for retrieving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\ngetText = Sizzle.getText = function( elem ) {\n\tvar node,\n\t\tret = \"\",\n\t\ti = 0,\n\t\tnodeType = elem.nodeType;\n\n\tif ( !nodeType ) {\n\n\t\t// If no nodeType, this is expected to be an array\n\t\twhile ( ( node = elem[ i++ ] ) ) {\n\n\t\t\t// Do not traverse comment nodes\n\t\t\tret += getText( node );\n\t\t}\n\t} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\n\t\t// Use textContent for elements\n\t\t// innerText usage removed for consistency of new lines (jQuery #11153)\n\t\tif ( typeof elem.textContent === \"string\" ) {\n\t\t\treturn elem.textContent;\n\t\t} else {\n\n\t\t\t// Traverse its children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tret += getText( elem );\n\t\t\t}\n\t\t}\n\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\treturn elem.nodeValue;\n\t}\n\n\t// Do not include comment or processing instruction nodes\n\n\treturn ret;\n};\n\nExpr = Sizzle.selectors = {\n\n\t// Can be adjusted by the user\n\tcacheLength: 50,\n\n\tcreatePseudo: markFunction,\n\n\tmatch: matchExpr,\n\n\tattrHandle: {},\n\n\tfind: {},\n\n\trelative: {\n\t\t\">\": { dir: \"parentNode\", first: true },\n\t\t\" \": { dir: \"parentNode\" },\n\t\t\"+\": { dir: \"previousSibling\", first: true },\n\t\t\"~\": { dir: \"previousSibling\" }\n\t},\n\n\tpreFilter: {\n\t\t\"ATTR\": function( match ) {\n\t\t\tmatch[ 1 ] = match[ 1 ].replace( runescape, funescape );\n\n\t\t\t// Move the given value to match[3] whether quoted or unquoted\n\t\t\tmatch[ 3 ] = ( match[ 3 ] || match[ 4 ] ||\n\t\t\t\tmatch[ 5 ] || \"\" ).replace( runescape, funescape );\n\n\t\t\tif ( match[ 2 ] === \"~=\" ) {\n\t\t\t\tmatch[ 3 ] = \" \" + match[ 3 ] + \" \";\n\t\t\t}\n\n\t\t\treturn match.slice( 0, 4 );\n\t\t},\n\n\t\t\"CHILD\": function( match ) {\n\n\t\t\t/* matches from matchExpr[\"CHILD\"]\n\t\t\t\t1 type (only|nth|...)\n\t\t\t\t2 what (child|of-type)\n\t\t\t\t3 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n\t\t\t\t4 xn-component of xn+y argument ([+-]?\\d*n|)\n\t\t\t\t5 sign of xn-component\n\t\t\t\t6 x of xn-component\n\t\t\t\t7 sign of y-component\n\t\t\t\t8 y of y-component\n\t\t\t*/\n\t\t\tmatch[ 1 ] = match[ 1 ].toLowerCase();\n\n\t\t\tif ( match[ 1 ].slice( 0, 3 ) === \"nth\" ) {\n\n\t\t\t\t// nth-* requires argument\n\t\t\t\tif ( !match[ 3 ] ) {\n\t\t\t\t\tSizzle.error( match[ 0 ] );\n\t\t\t\t}\n\n\t\t\t\t// numeric x and y parameters for Expr.filter.CHILD\n\t\t\t\t// remember that false/true cast respectively to 0/1\n\t\t\t\tmatch[ 4 ] = +( match[ 4 ] ?\n\t\t\t\t\tmatch[ 5 ] + ( match[ 6 ] || 1 ) :\n\t\t\t\t\t2 * ( match[ 3 ] === \"even\" || match[ 3 ] === \"odd\" ) );\n\t\t\t\tmatch[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === \"odd\" );\n\n\t\t\t\t// other types prohibit arguments\n\t\t\t} else if ( match[ 3 ] ) {\n\t\t\t\tSizzle.error( match[ 0 ] );\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\t\"PSEUDO\": function( match ) {\n\t\t\tvar excess,\n\t\t\t\tunquoted = !match[ 6 ] && match[ 2 ];\n\n\t\t\tif ( matchExpr[ \"CHILD\" ].test( match[ 0 ] ) ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// Accept quoted arguments as-is\n\t\t\tif ( match[ 3 ] ) {\n\t\t\t\tmatch[ 2 ] = match[ 4 ] || match[ 5 ] || \"\";\n\n\t\t\t// Strip excess characters from unquoted arguments\n\t\t\t} else if ( unquoted && rpseudo.test( unquoted ) &&\n\n\t\t\t\t// Get excess from tokenize (recursively)\n\t\t\t\t( excess = tokenize( unquoted, true ) ) &&\n\n\t\t\t\t// advance to the next closing parenthesis\n\t\t\t\t( excess = unquoted.indexOf( \")\", unquoted.length - excess ) - unquoted.length ) ) {\n\n\t\t\t\t// excess is a negative index\n\t\t\t\tmatch[ 0 ] = match[ 0 ].slice( 0, excess );\n\t\t\t\tmatch[ 2 ] = unquoted.slice( 0, excess );\n\t\t\t}\n\n\t\t\t// Return only captures needed by the pseudo filter method (type and argument)\n\t\t\treturn match.slice( 0, 3 );\n\t\t}\n\t},\n\n\tfilter: {\n\n\t\t\"TAG\": function( nodeNameSelector ) {\n\t\t\tvar nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn nodeNameSelector === \"*\" ?\n\t\t\t\tfunction() {\n\t\t\t\t\treturn true;\n\t\t\t\t} :\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n\t\t\t\t};\n\t\t},\n\n\t\t\"CLASS\": function( className ) {\n\t\t\tvar pattern = classCache[ className + \" \" ];\n\n\t\t\treturn pattern ||\n\t\t\t\t( pattern = new RegExp( \"(^|\" + whitespace +\n\t\t\t\t\t\")\" + className + \"(\" + whitespace + \"|$)\" ) ) && classCache(\n\t\t\t\t\t\tclassName, function( elem ) {\n\t\t\t\t\t\t\treturn pattern.test(\n\t\t\t\t\t\t\t\ttypeof elem.className === \"string\" && elem.className ||\n\t\t\t\t\t\t\t\ttypeof elem.getAttribute !== \"undefined\" &&\n\t\t\t\t\t\t\t\t\telem.getAttribute( \"class\" ) ||\n\t\t\t\t\t\t\t\t\"\"\n\t\t\t\t\t\t\t);\n\t\t\t\t} );\n\t\t},\n\n\t\t\"ATTR\": function( name, operator, check ) {\n\t\t\treturn function( elem ) {\n\t\t\t\tvar result = Sizzle.attr( elem, name );\n\n\t\t\t\tif ( result == null ) {\n\t\t\t\t\treturn operator === \"!=\";\n\t\t\t\t}\n\t\t\t\tif ( !operator ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tresult += \"\";\n\n\t\t\t\t/* eslint-disable max-len */\n\n\t\t\t\treturn operator === \"=\" ? result === check :\n\t\t\t\t\toperator === \"!=\" ? result !== check :\n\t\t\t\t\toperator === \"^=\" ? check && result.indexOf( check ) === 0 :\n\t\t\t\t\toperator === \"*=\" ? check && result.indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"$=\" ? check && result.slice( -check.length ) === check :\n\t\t\t\t\toperator === \"~=\" ? ( \" \" + result.replace( rwhitespace, \" \" ) + \" \" ).indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"|=\" ? result === check || result.slice( 0, check.length + 1 ) === check + \"-\" :\n\t\t\t\t\tfalse;\n\t\t\t\t/* eslint-enable max-len */\n\n\t\t\t};\n\t\t},\n\n\t\t\"CHILD\": function( type, what, _argument, first, last ) {\n\t\t\tvar simple = type.slice( 0, 3 ) !== \"nth\",\n\t\t\t\tforward = type.slice( -4 ) !== \"last\",\n\t\t\t\tofType = what === \"of-type\";\n\n\t\t\treturn first === 1 && last === 0 ?\n\n\t\t\t\t// Shortcut for :nth-*(n)\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn !!elem.parentNode;\n\t\t\t\t} :\n\n\t\t\t\tfunction( elem, _context, xml ) {\n\t\t\t\t\tvar cache, uniqueCache, outerCache, node, nodeIndex, start,\n\t\t\t\t\t\tdir = simple !== forward ? \"nextSibling\" : \"previousSibling\",\n\t\t\t\t\t\tparent = elem.parentNode,\n\t\t\t\t\t\tname = ofType && elem.nodeName.toLowerCase(),\n\t\t\t\t\t\tuseCache = !xml && !ofType,\n\t\t\t\t\t\tdiff = false;\n\n\t\t\t\t\tif ( parent ) {\n\n\t\t\t\t\t\t// :(first|last|only)-(child|of-type)\n\t\t\t\t\t\tif ( simple ) {\n\t\t\t\t\t\t\twhile ( dir ) {\n\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\twhile ( ( node = node[ dir ] ) ) {\n\t\t\t\t\t\t\t\t\tif ( ofType ?\n\t\t\t\t\t\t\t\t\t\tnode.nodeName.toLowerCase() === name :\n\t\t\t\t\t\t\t\t\t\tnode.nodeType === 1 ) {\n\n\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Reverse direction for :only-* (if we haven't yet done so)\n\t\t\t\t\t\t\t\tstart = dir = type === \"only\" && !start && \"nextSibling\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tstart = [ forward ? parent.firstChild : parent.lastChild ];\n\n\t\t\t\t\t\t// non-xml :nth-child(...) stores cache data on `parent`\n\t\t\t\t\t\tif ( forward && useCache ) {\n\n\t\t\t\t\t\t\t// Seek `elem` from a previously-cached index\n\n\t\t\t\t\t\t\t// ...in a gzip-friendly way\n\t\t\t\t\t\t\tnode = parent;\n\t\t\t\t\t\t\touterCache = node[ expando ] || ( node[ expando ] = {} );\n\n\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t( outerCache[ node.uniqueID ] = {} );\n\n\t\t\t\t\t\t\tcache = uniqueCache[ type ] || [];\n\t\t\t\t\t\t\tnodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];\n\t\t\t\t\t\t\tdiff = nodeIndex && cache[ 2 ];\n\t\t\t\t\t\t\tnode = nodeIndex && parent.childNodes[ nodeIndex ];\n\n\t\t\t\t\t\t\twhile ( ( node = ++nodeIndex && node && node[ dir ] ||\n\n\t\t\t\t\t\t\t\t// Fallback to seeking `elem` from the start\n\t\t\t\t\t\t\t\t( diff = nodeIndex = 0 ) || start.pop() ) ) {\n\n\t\t\t\t\t\t\t\t// When found, cache indexes on `parent` and break\n\t\t\t\t\t\t\t\tif ( node.nodeType === 1 && ++diff && node === elem ) {\n\t\t\t\t\t\t\t\t\tuniqueCache[ type ] = [ dirruns, nodeIndex, diff ];\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t// Use previously-cached element index if available\n\t\t\t\t\t\t\tif ( useCache ) {\n\n\t\t\t\t\t\t\t\t// ...in a gzip-friendly way\n\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\touterCache = node[ expando ] || ( node[ expando ] = {} );\n\n\t\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t\t( outerCache[ node.uniqueID ] = {} );\n\n\t\t\t\t\t\t\t\tcache = uniqueCache[ type ] || [];\n\t\t\t\t\t\t\t\tnodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];\n\t\t\t\t\t\t\t\tdiff = nodeIndex;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// xml :nth-child(...)\n\t\t\t\t\t\t\t// or :nth-last-child(...) or :nth(-last)?-of-type(...)\n\t\t\t\t\t\t\tif ( diff === false ) {\n\n\t\t\t\t\t\t\t\t// Use the same loop as above to seek `elem` from the start\n\t\t\t\t\t\t\t\twhile ( ( node = ++nodeIndex && node && node[ dir ] ||\n\t\t\t\t\t\t\t\t\t( diff = nodeIndex = 0 ) || start.pop() ) ) {\n\n\t\t\t\t\t\t\t\t\tif ( ( ofType ?\n\t\t\t\t\t\t\t\t\t\tnode.nodeName.toLowerCase() === name :\n\t\t\t\t\t\t\t\t\t\tnode.nodeType === 1 ) &&\n\t\t\t\t\t\t\t\t\t\t++diff ) {\n\n\t\t\t\t\t\t\t\t\t\t// Cache the index of each encountered element\n\t\t\t\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t\t\t\touterCache = node[ expando ] ||\n\t\t\t\t\t\t\t\t\t\t\t\t( node[ expando ] = {} );\n\n\t\t\t\t\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t\t\t\t\t( outerCache[ node.uniqueID ] = {} );\n\n\t\t\t\t\t\t\t\t\t\t\tuniqueCache[ type ] = [ dirruns, diff ];\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tif ( node === elem ) {\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Incorporate the offset, then check against cycle size\n\t\t\t\t\t\tdiff -= last;\n\t\t\t\t\t\treturn diff === first || ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t},\n\n\t\t\"PSEUDO\": function( pseudo, argument ) {\n\n\t\t\t// pseudo-class names are case-insensitive\n\t\t\t// http://www.w3.org/TR/selectors/#pseudo-classes\n\t\t\t// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\n\t\t\t// Remember that setFilters inherits from pseudos\n\t\t\tvar args,\n\t\t\t\tfn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||\n\t\t\t\t\tSizzle.error( \"unsupported pseudo: \" + pseudo );\n\n\t\t\t// The user may use createPseudo to indicate that\n\t\t\t// arguments are needed to create the filter function\n\t\t\t// just as Sizzle does\n\t\t\tif ( fn[ expando ] ) {\n\t\t\t\treturn fn( argument );\n\t\t\t}\n\n\t\t\t// But maintain support for old signatures\n\t\t\tif ( fn.length > 1 ) {\n\t\t\t\targs = [ pseudo, pseudo, \"\", argument ];\n\t\t\t\treturn Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?\n\t\t\t\t\tmarkFunction( function( seed, matches ) {\n\t\t\t\t\t\tvar idx,\n\t\t\t\t\t\t\tmatched = fn( seed, argument ),\n\t\t\t\t\t\t\ti = matched.length;\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tidx = indexOf( seed, matched[ i ] );\n\t\t\t\t\t\t\tseed[ idx ] = !( matches[ idx ] = matched[ i ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} ) :\n\t\t\t\t\tfunction( elem ) {\n\t\t\t\t\t\treturn fn( elem, 0, args );\n\t\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn fn;\n\t\t}\n\t},\n\n\tpseudos: {\n\n\t\t// Potentially complex pseudos\n\t\t\"not\": markFunction( function( selector ) {\n\n\t\t\t// Trim the selector passed to compile\n\t\t\t// to avoid treating leading and trailing\n\t\t\t// spaces as combinators\n\t\t\tvar input = [],\n\t\t\t\tresults = [],\n\t\t\t\tmatcher = compile( selector.replace( rtrim, \"$1\" ) );\n\n\t\t\treturn matcher[ expando ] ?\n\t\t\t\tmarkFunction( function( seed, matches, _context, xml ) {\n\t\t\t\t\tvar elem,\n\t\t\t\t\t\tunmatched = matcher( seed, null, xml, [] ),\n\t\t\t\t\t\ti = seed.length;\n\n\t\t\t\t\t// Match elements unmatched by `matcher`\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( ( elem = unmatched[ i ] ) ) {\n\t\t\t\t\t\t\tseed[ i ] = !( matches[ i ] = elem );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} ) :\n\t\t\t\tfunction( elem, _context, xml ) {\n\t\t\t\t\tinput[ 0 ] = elem;\n\t\t\t\t\tmatcher( input, null, xml, results );\n\n\t\t\t\t\t// Don't keep the element (issue #299)\n\t\t\t\t\tinput[ 0 ] = null;\n\t\t\t\t\treturn !results.pop();\n\t\t\t\t};\n\t\t} ),\n\n\t\t\"has\": markFunction( function( selector ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn Sizzle( selector, elem ).length > 0;\n\t\t\t};\n\t\t} ),\n\n\t\t\"contains\": markFunction( function( text ) {\n\t\t\ttext = text.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn ( elem.textContent || getText( elem ) ).indexOf( text ) > -1;\n\t\t\t};\n\t\t} ),\n\n\t\t// \"Whether an element is represented by a :lang() selector\n\t\t// is based solely on the element's language value\n\t\t// being equal to the identifier C,\n\t\t// or beginning with the identifier C immediately followed by \"-\".\n\t\t// The matching of C against the element's language value is performed case-insensitively.\n\t\t// The identifier C does not have to be a valid language name.\"\n\t\t// http://www.w3.org/TR/selectors/#lang-pseudo\n\t\t\"lang\": markFunction( function( lang ) {\n\n\t\t\t// lang value must be a valid identifier\n\t\t\tif ( !ridentifier.test( lang || \"\" ) ) {\n\t\t\t\tSizzle.error( \"unsupported lang: \" + lang );\n\t\t\t}\n\t\t\tlang = lang.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn function( elem ) {\n\t\t\t\tvar elemLang;\n\t\t\t\tdo {\n\t\t\t\t\tif ( ( elemLang = documentIsHTML ?\n\t\t\t\t\t\telem.lang :\n\t\t\t\t\t\telem.getAttribute( \"xml:lang\" ) || elem.getAttribute( \"lang\" ) ) ) {\n\n\t\t\t\t\t\telemLang = elemLang.toLowerCase();\n\t\t\t\t\t\treturn elemLang === lang || elemLang.indexOf( lang + \"-\" ) === 0;\n\t\t\t\t\t}\n\t\t\t\t} while ( ( elem = elem.parentNode ) && elem.nodeType === 1 );\n\t\t\t\treturn false;\n\t\t\t};\n\t\t} ),\n\n\t\t// Miscellaneous\n\t\t\"target\": function( elem ) {\n\t\t\tvar hash = window.location && window.location.hash;\n\t\t\treturn hash && hash.slice( 1 ) === elem.id;\n\t\t},\n\n\t\t\"root\": function( elem ) {\n\t\t\treturn elem === docElem;\n\t\t},\n\n\t\t\"focus\": function( elem ) {\n\t\t\treturn elem === document.activeElement &&\n\t\t\t\t( !document.hasFocus || document.hasFocus() ) &&\n\t\t\t\t!!( elem.type || elem.href || ~elem.tabIndex );\n\t\t},\n\n\t\t// Boolean properties\n\t\t\"enabled\": createDisabledPseudo( false ),\n\t\t\"disabled\": createDisabledPseudo( true ),\n\n\t\t\"checked\": function( elem ) {\n\n\t\t\t// In CSS3, :checked should return both checked and selected elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\tvar nodeName = elem.nodeName.toLowerCase();\n\t\t\treturn ( nodeName === \"input\" && !!elem.checked ) ||\n\t\t\t\t( nodeName === \"option\" && !!elem.selected );\n\t\t},\n\n\t\t\"selected\": function( elem ) {\n\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\t// eslint-disable-next-line no-unused-expressions\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\t// Contents\n\t\t\"empty\": function( elem ) {\n\n\t\t\t// http://www.w3.org/TR/selectors/#empty-pseudo\n\t\t\t// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),\n\t\t\t//   but not by others (comment: 8; processing instruction: 7; etc.)\n\t\t\t// nodeType < 6 works because attributes (2) do not appear as children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tif ( elem.nodeType < 6 ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\t\"parent\": function( elem ) {\n\t\t\treturn !Expr.pseudos[ \"empty\" ]( elem );\n\t\t},\n\n\t\t// Element/input types\n\t\t\"header\": function( elem ) {\n\t\t\treturn rheader.test( elem.nodeName );\n\t\t},\n\n\t\t\"input\": function( elem ) {\n\t\t\treturn rinputs.test( elem.nodeName );\n\t\t},\n\n\t\t\"button\": function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && elem.type === \"button\" || name === \"button\";\n\t\t},\n\n\t\t\"text\": function( elem ) {\n\t\t\tvar attr;\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" &&\n\t\t\t\telem.type === \"text\" &&\n\n\t\t\t\t// Support: IE<8\n\t\t\t\t// New HTML5 attribute values (e.g., \"search\") appear with elem.type === \"text\"\n\t\t\t\t( ( attr = elem.getAttribute( \"type\" ) ) == null ||\n\t\t\t\t\tattr.toLowerCase() === \"text\" );\n\t\t},\n\n\t\t// Position-in-collection\n\t\t\"first\": createPositionalPseudo( function() {\n\t\t\treturn [ 0 ];\n\t\t} ),\n\n\t\t\"last\": createPositionalPseudo( function( _matchIndexes, length ) {\n\t\t\treturn [ length - 1 ];\n\t\t} ),\n\n\t\t\"eq\": createPositionalPseudo( function( _matchIndexes, length, argument ) {\n\t\t\treturn [ argument < 0 ? argument + length : argument ];\n\t\t} ),\n\n\t\t\"even\": createPositionalPseudo( function( matchIndexes, length ) {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t} ),\n\n\t\t\"odd\": createPositionalPseudo( function( matchIndexes, length ) {\n\t\t\tvar i = 1;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t} ),\n\n\t\t\"lt\": createPositionalPseudo( function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ?\n\t\t\t\targument + length :\n\t\t\t\targument > length ?\n\t\t\t\t\tlength :\n\t\t\t\t\targument;\n\t\t\tfor ( ; --i >= 0; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t} ),\n\n\t\t\"gt\": createPositionalPseudo( function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; ++i < length; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t} )\n\t}\n};\n\nExpr.pseudos[ \"nth\" ] = Expr.pseudos[ \"eq\" ];\n\n// Add button/input type pseudos\nfor ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {\n\tExpr.pseudos[ i ] = createInputPseudo( i );\n}\nfor ( i in { submit: true, reset: true } ) {\n\tExpr.pseudos[ i ] = createButtonPseudo( i );\n}\n\n// Easy API for creating new setFilters\nfunction setFilters() {}\nsetFilters.prototype = Expr.filters = Expr.pseudos;\nExpr.setFilters = new setFilters();\n\ntokenize = Sizzle.tokenize = function( selector, parseOnly ) {\n\tvar matched, match, tokens, type,\n\t\tsoFar, groups, preFilters,\n\t\tcached = tokenCache[ selector + \" \" ];\n\n\tif ( cached ) {\n\t\treturn parseOnly ? 0 : cached.slice( 0 );\n\t}\n\n\tsoFar = selector;\n\tgroups = [];\n\tpreFilters = Expr.preFilter;\n\n\twhile ( soFar ) {\n\n\t\t// Comma and first run\n\t\tif ( !matched || ( match = rcomma.exec( soFar ) ) ) {\n\t\t\tif ( match ) {\n\n\t\t\t\t// Don't consume trailing commas as valid\n\t\t\t\tsoFar = soFar.slice( match[ 0 ].length ) || soFar;\n\t\t\t}\n\t\t\tgroups.push( ( tokens = [] ) );\n\t\t}\n\n\t\tmatched = false;\n\n\t\t// Combinators\n\t\tif ( ( match = rcombinators.exec( soFar ) ) ) {\n\t\t\tmatched = match.shift();\n\t\t\ttokens.push( {\n\t\t\t\tvalue: matched,\n\n\t\t\t\t// Cast descendant combinators to space\n\t\t\t\ttype: match[ 0 ].replace( rtrim, \" \" )\n\t\t\t} );\n\t\t\tsoFar = soFar.slice( matched.length );\n\t\t}\n\n\t\t// Filters\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] ||\n\t\t\t\t( match = preFilters[ type ]( match ) ) ) ) {\n\t\t\t\tmatched = match.shift();\n\t\t\t\ttokens.push( {\n\t\t\t\t\tvalue: matched,\n\t\t\t\t\ttype: type,\n\t\t\t\t\tmatches: match\n\t\t\t\t} );\n\t\t\t\tsoFar = soFar.slice( matched.length );\n\t\t\t}\n\t\t}\n\n\t\tif ( !matched ) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Return the length of the invalid excess\n\t// if we're just parsing\n\t// Otherwise, throw an error or return tokens\n\treturn parseOnly ?\n\t\tsoFar.length :\n\t\tsoFar ?\n\t\t\tSizzle.error( selector ) :\n\n\t\t\t// Cache the tokens\n\t\t\ttokenCache( selector, groups ).slice( 0 );\n};\n\nfunction toSelector( tokens ) {\n\tvar i = 0,\n\t\tlen = tokens.length,\n\t\tselector = \"\";\n\tfor ( ; i < len; i++ ) {\n\t\tselector += tokens[ i ].value;\n\t}\n\treturn selector;\n}\n\nfunction addCombinator( matcher, combinator, base ) {\n\tvar dir = combinator.dir,\n\t\tskip = combinator.next,\n\t\tkey = skip || dir,\n\t\tcheckNonElements = base && key === \"parentNode\",\n\t\tdoneName = done++;\n\n\treturn combinator.first ?\n\n\t\t// Check against closest ancestor/preceding element\n\t\tfunction( elem, context, xml ) {\n\t\t\twhile ( ( elem = elem[ dir ] ) ) {\n\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\treturn matcher( elem, context, xml );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t} :\n\n\t\t// Check against all ancestor/preceding elements\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar oldCache, uniqueCache, outerCache,\n\t\t\t\tnewCache = [ dirruns, doneName ];\n\n\t\t\t// We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching\n\t\t\tif ( xml ) {\n\t\t\t\twhile ( ( elem = elem[ dir ] ) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\twhile ( ( elem = elem[ dir ] ) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\touterCache = elem[ expando ] || ( elem[ expando ] = {} );\n\n\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\tuniqueCache = outerCache[ elem.uniqueID ] ||\n\t\t\t\t\t\t\t( outerCache[ elem.uniqueID ] = {} );\n\n\t\t\t\t\t\tif ( skip && skip === elem.nodeName.toLowerCase() ) {\n\t\t\t\t\t\t\telem = elem[ dir ] || elem;\n\t\t\t\t\t\t} else if ( ( oldCache = uniqueCache[ key ] ) &&\n\t\t\t\t\t\t\toldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {\n\n\t\t\t\t\t\t\t// Assign to newCache so results back-propagate to previous elements\n\t\t\t\t\t\t\treturn ( newCache[ 2 ] = oldCache[ 2 ] );\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t// Reuse newcache so results back-propagate to previous elements\n\t\t\t\t\t\t\tuniqueCache[ key ] = newCache;\n\n\t\t\t\t\t\t\t// A match means we're done; a fail means we have to keep checking\n\t\t\t\t\t\t\tif ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) {\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n}\n\nfunction elementMatcher( matchers ) {\n\treturn matchers.length > 1 ?\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar i = matchers.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( !matchers[ i ]( elem, context, xml ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} :\n\t\tmatchers[ 0 ];\n}\n\nfunction multipleContexts( selector, contexts, results ) {\n\tvar i = 0,\n\t\tlen = contexts.length;\n\tfor ( ; i < len; i++ ) {\n\t\tSizzle( selector, contexts[ i ], results );\n\t}\n\treturn results;\n}\n\nfunction condense( unmatched, map, filter, context, xml ) {\n\tvar elem,\n\t\tnewUnmatched = [],\n\t\ti = 0,\n\t\tlen = unmatched.length,\n\t\tmapped = map != null;\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( ( elem = unmatched[ i ] ) ) {\n\t\t\tif ( !filter || filter( elem, context, xml ) ) {\n\t\t\t\tnewUnmatched.push( elem );\n\t\t\t\tif ( mapped ) {\n\t\t\t\t\tmap.push( i );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn newUnmatched;\n}\n\nfunction setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\n\tif ( postFilter && !postFilter[ expando ] ) {\n\t\tpostFilter = setMatcher( postFilter );\n\t}\n\tif ( postFinder && !postFinder[ expando ] ) {\n\t\tpostFinder = setMatcher( postFinder, postSelector );\n\t}\n\treturn markFunction( function( seed, results, context, xml ) {\n\t\tvar temp, i, elem,\n\t\t\tpreMap = [],\n\t\t\tpostMap = [],\n\t\t\tpreexisting = results.length,\n\n\t\t\t// Get initial elements from seed or context\n\t\t\telems = seed || multipleContexts(\n\t\t\t\tselector || \"*\",\n\t\t\t\tcontext.nodeType ? [ context ] : context,\n\t\t\t\t[]\n\t\t\t),\n\n\t\t\t// Prefilter to get matcher input, preserving a map for seed-results synchronization\n\t\t\tmatcherIn = preFilter && ( seed || !selector ) ?\n\t\t\t\tcondense( elems, preMap, preFilter, context, xml ) :\n\t\t\t\telems,\n\n\t\t\tmatcherOut = matcher ?\n\n\t\t\t\t// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\n\t\t\t\tpostFinder || ( seed ? preFilter : preexisting || postFilter ) ?\n\n\t\t\t\t\t// ...intermediate processing is necessary\n\t\t\t\t\t[] :\n\n\t\t\t\t\t// ...otherwise use results directly\n\t\t\t\t\tresults :\n\t\t\t\tmatcherIn;\n\n\t\t// Find primary matches\n\t\tif ( matcher ) {\n\t\t\tmatcher( matcherIn, matcherOut, context, xml );\n\t\t}\n\n\t\t// Apply postFilter\n\t\tif ( postFilter ) {\n\t\t\ttemp = condense( matcherOut, postMap );\n\t\t\tpostFilter( temp, [], context, xml );\n\n\t\t\t// Un-match failing elements by moving them back to matcherIn\n\t\t\ti = temp.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( ( elem = temp[ i ] ) ) {\n\t\t\t\t\tmatcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( seed ) {\n\t\t\tif ( postFinder || preFilter ) {\n\t\t\t\tif ( postFinder ) {\n\n\t\t\t\t\t// Get the final matcherOut by condensing this intermediate into postFinder contexts\n\t\t\t\t\ttemp = [];\n\t\t\t\t\ti = matcherOut.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( ( elem = matcherOut[ i ] ) ) {\n\n\t\t\t\t\t\t\t// Restore matcherIn since elem is not yet a final match\n\t\t\t\t\t\t\ttemp.push( ( matcherIn[ i ] = elem ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpostFinder( null, ( matcherOut = [] ), temp, xml );\n\t\t\t\t}\n\n\t\t\t\t// Move matched elements from seed to results to keep them synchronized\n\t\t\t\ti = matcherOut.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tif ( ( elem = matcherOut[ i ] ) &&\n\t\t\t\t\t\t( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) {\n\n\t\t\t\t\t\tseed[ temp ] = !( results[ temp ] = elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Add elements to results, through postFinder if defined\n\t\t} else {\n\t\t\tmatcherOut = condense(\n\t\t\t\tmatcherOut === results ?\n\t\t\t\t\tmatcherOut.splice( preexisting, matcherOut.length ) :\n\t\t\t\t\tmatcherOut\n\t\t\t);\n\t\t\tif ( postFinder ) {\n\t\t\t\tpostFinder( null, results, matcherOut, xml );\n\t\t\t} else {\n\t\t\t\tpush.apply( results, matcherOut );\n\t\t\t}\n\t\t}\n\t} );\n}\n\nfunction matcherFromTokens( tokens ) {\n\tvar checkContext, matcher, j,\n\t\tlen = tokens.length,\n\t\tleadingRelative = Expr.relative[ tokens[ 0 ].type ],\n\t\timplicitRelative = leadingRelative || Expr.relative[ \" \" ],\n\t\ti = leadingRelative ? 1 : 0,\n\n\t\t// The foundational matcher ensures that elements are reachable from top-level context(s)\n\t\tmatchContext = addCombinator( function( elem ) {\n\t\t\treturn elem === checkContext;\n\t\t}, implicitRelative, true ),\n\t\tmatchAnyContext = addCombinator( function( elem ) {\n\t\t\treturn indexOf( checkContext, elem ) > -1;\n\t\t}, implicitRelative, true ),\n\t\tmatchers = [ function( elem, context, xml ) {\n\t\t\tvar ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\n\t\t\t\t( checkContext = context ).nodeType ?\n\t\t\t\t\tmatchContext( elem, context, xml ) :\n\t\t\t\t\tmatchAnyContext( elem, context, xml ) );\n\n\t\t\t// Avoid hanging onto element (issue #299)\n\t\t\tcheckContext = null;\n\t\t\treturn ret;\n\t\t} ];\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) {\n\t\t\tmatchers = [ addCombinator( elementMatcher( matchers ), matcher ) ];\n\t\t} else {\n\t\t\tmatcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches );\n\n\t\t\t// Return special upon seeing a positional matcher\n\t\t\tif ( matcher[ expando ] ) {\n\n\t\t\t\t// Find the next relative operator (if any) for proper handling\n\t\t\t\tj = ++i;\n\t\t\t\tfor ( ; j < len; j++ ) {\n\t\t\t\t\tif ( Expr.relative[ tokens[ j ].type ] ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn setMatcher(\n\t\t\t\t\ti > 1 && elementMatcher( matchers ),\n\t\t\t\t\ti > 1 && toSelector(\n\n\t\t\t\t\t// If the preceding token was a descendant combinator, insert an implicit any-element `*`\n\t\t\t\t\ttokens\n\t\t\t\t\t\t.slice( 0, i - 1 )\n\t\t\t\t\t\t.concat( { value: tokens[ i - 2 ].type === \" \" ? \"*\" : \"\" } )\n\t\t\t\t\t).replace( rtrim, \"$1\" ),\n\t\t\t\t\tmatcher,\n\t\t\t\t\ti < j && matcherFromTokens( tokens.slice( i, j ) ),\n\t\t\t\t\tj < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ),\n\t\t\t\t\tj < len && toSelector( tokens )\n\t\t\t\t);\n\t\t\t}\n\t\t\tmatchers.push( matcher );\n\t\t}\n\t}\n\n\treturn elementMatcher( matchers );\n}\n\nfunction matcherFromGroupMatchers( elementMatchers, setMatchers ) {\n\tvar bySet = setMatchers.length > 0,\n\t\tbyElement = elementMatchers.length > 0,\n\t\tsuperMatcher = function( seed, context, xml, results, outermost ) {\n\t\t\tvar elem, j, matcher,\n\t\t\t\tmatchedCount = 0,\n\t\t\t\ti = \"0\",\n\t\t\t\tunmatched = seed && [],\n\t\t\t\tsetMatched = [],\n\t\t\t\tcontextBackup = outermostContext,\n\n\t\t\t\t// We must always have either seed elements or outermost context\n\t\t\t\telems = seed || byElement && Expr.find[ \"TAG\" ]( \"*\", outermost ),\n\n\t\t\t\t// Use integer dirruns iff this is the outermost matcher\n\t\t\t\tdirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ),\n\t\t\t\tlen = elems.length;\n\n\t\t\tif ( outermost ) {\n\n\t\t\t\t// Support: IE 11+, Edge 17 - 18+\n\t\t\t\t// IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n\t\t\t\t// two documents; shallow comparisons work.\n\t\t\t\t// eslint-disable-next-line eqeqeq\n\t\t\t\toutermostContext = context == document || context || outermost;\n\t\t\t}\n\n\t\t\t// Add elements passing elementMatchers directly to results\n\t\t\t// Support: IE<9, Safari\n\t\t\t// Tolerate NodeList properties (IE: \"length\"; Safari: <number>) matching elements by id\n\t\t\tfor ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) {\n\t\t\t\tif ( byElement && elem ) {\n\t\t\t\t\tj = 0;\n\n\t\t\t\t\t// Support: IE 11+, Edge 17 - 18+\n\t\t\t\t\t// IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n\t\t\t\t\t// two documents; shallow comparisons work.\n\t\t\t\t\t// eslint-disable-next-line eqeqeq\n\t\t\t\t\tif ( !context && elem.ownerDocument != document ) {\n\t\t\t\t\t\tsetDocument( elem );\n\t\t\t\t\t\txml = !documentIsHTML;\n\t\t\t\t\t}\n\t\t\t\t\twhile ( ( matcher = elementMatchers[ j++ ] ) ) {\n\t\t\t\t\t\tif ( matcher( elem, context || document, xml ) ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( outermost ) {\n\t\t\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Track unmatched elements for set filters\n\t\t\t\tif ( bySet ) {\n\n\t\t\t\t\t// They will have gone through all possible matchers\n\t\t\t\t\tif ( ( elem = !matcher && elem ) ) {\n\t\t\t\t\t\tmatchedCount--;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Lengthen the array for every element, matched or not\n\t\t\t\t\tif ( seed ) {\n\t\t\t\t\t\tunmatched.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// `i` is now the count of elements visited above, and adding it to `matchedCount`\n\t\t\t// makes the latter nonnegative.\n\t\t\tmatchedCount += i;\n\n\t\t\t// Apply set filters to unmatched elements\n\t\t\t// NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`\n\t\t\t// equals `i`), unless we didn't visit _any_ elements in the above loop because we have\n\t\t\t// no element matchers and no seed.\n\t\t\t// Incrementing an initially-string \"0\" `i` allows `i` to remain a string only in that\n\t\t\t// case, which will result in a \"00\" `matchedCount` that differs from `i` but is also\n\t\t\t// numerically zero.\n\t\t\tif ( bySet && i !== matchedCount ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( ( matcher = setMatchers[ j++ ] ) ) {\n\t\t\t\t\tmatcher( unmatched, setMatched, context, xml );\n\t\t\t\t}\n\n\t\t\t\tif ( seed ) {\n\n\t\t\t\t\t// Reintegrate element matches to eliminate the need for sorting\n\t\t\t\t\tif ( matchedCount > 0 ) {\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tif ( !( unmatched[ i ] || setMatched[ i ] ) ) {\n\t\t\t\t\t\t\t\tsetMatched[ i ] = pop.call( results );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Discard index placeholder values to get only actual matches\n\t\t\t\t\tsetMatched = condense( setMatched );\n\t\t\t\t}\n\n\t\t\t\t// Add matches to results\n\t\t\t\tpush.apply( results, setMatched );\n\n\t\t\t\t// Seedless set matches succeeding multiple successful matchers stipulate sorting\n\t\t\t\tif ( outermost && !seed && setMatched.length > 0 &&\n\t\t\t\t\t( matchedCount + setMatchers.length ) > 1 ) {\n\n\t\t\t\t\tSizzle.uniqueSort( results );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Override manipulation of globals by nested matchers\n\t\t\tif ( outermost ) {\n\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\toutermostContext = contextBackup;\n\t\t\t}\n\n\t\t\treturn unmatched;\n\t\t};\n\n\treturn bySet ?\n\t\tmarkFunction( superMatcher ) :\n\t\tsuperMatcher;\n}\n\ncompile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {\n\tvar i,\n\t\tsetMatchers = [],\n\t\telementMatchers = [],\n\t\tcached = compilerCache[ selector + \" \" ];\n\n\tif ( !cached ) {\n\n\t\t// Generate a function of recursive functions that can be used to check each element\n\t\tif ( !match ) {\n\t\t\tmatch = tokenize( selector );\n\t\t}\n\t\ti = match.length;\n\t\twhile ( i-- ) {\n\t\t\tcached = matcherFromTokens( match[ i ] );\n\t\t\tif ( cached[ expando ] ) {\n\t\t\t\tsetMatchers.push( cached );\n\t\t\t} else {\n\t\t\t\telementMatchers.push( cached );\n\t\t\t}\n\t\t}\n\n\t\t// Cache the compiled function\n\t\tcached = compilerCache(\n\t\t\tselector,\n\t\t\tmatcherFromGroupMatchers( elementMatchers, setMatchers )\n\t\t);\n\n\t\t// Save selector and tokenization\n\t\tcached.selector = selector;\n\t}\n\treturn cached;\n};\n\n/**\n * A low-level selection function that works with Sizzle's compiled\n *  selector functions\n * @param {String|Function} selector A selector or a pre-compiled\n *  selector function built with Sizzle.compile\n * @param {Element} context\n * @param {Array} [results]\n * @param {Array} [seed] A set of elements to match against\n */\nselect = Sizzle.select = function( selector, context, results, seed ) {\n\tvar i, tokens, token, type, find,\n\t\tcompiled = typeof selector === \"function\" && selector,\n\t\tmatch = !seed && tokenize( ( selector = compiled.selector || selector ) );\n\n\tresults = results || [];\n\n\t// Try to minimize operations if there is only one selector in the list and no seed\n\t// (the latter of which guarantees us context)\n\tif ( match.length === 1 ) {\n\n\t\t// Reduce context if the leading compound selector is an ID\n\t\ttokens = match[ 0 ] = match[ 0 ].slice( 0 );\n\t\tif ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === \"ID\" &&\n\t\t\tcontext.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) {\n\n\t\t\tcontext = ( Expr.find[ \"ID\" ]( token.matches[ 0 ]\n\t\t\t\t.replace( runescape, funescape ), context ) || [] )[ 0 ];\n\t\t\tif ( !context ) {\n\t\t\t\treturn results;\n\n\t\t\t// Precompiled matchers will still verify ancestry, so step up a level\n\t\t\t} else if ( compiled ) {\n\t\t\t\tcontext = context.parentNode;\n\t\t\t}\n\n\t\t\tselector = selector.slice( tokens.shift().value.length );\n\t\t}\n\n\t\t// Fetch a seed set for right-to-left matching\n\t\ti = matchExpr[ \"needsContext\" ].test( selector ) ? 0 : tokens.length;\n\t\twhile ( i-- ) {\n\t\t\ttoken = tokens[ i ];\n\n\t\t\t// Abort if we hit a combinator\n\t\t\tif ( Expr.relative[ ( type = token.type ) ] ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( ( find = Expr.find[ type ] ) ) {\n\n\t\t\t\t// Search, expanding context for leading sibling combinators\n\t\t\t\tif ( ( seed = find(\n\t\t\t\t\ttoken.matches[ 0 ].replace( runescape, funescape ),\n\t\t\t\t\trsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) ||\n\t\t\t\t\t\tcontext\n\t\t\t\t) ) ) {\n\n\t\t\t\t\t// If seed is empty or no tokens remain, we can return early\n\t\t\t\t\ttokens.splice( i, 1 );\n\t\t\t\t\tselector = seed.length && toSelector( tokens );\n\t\t\t\t\tif ( !selector ) {\n\t\t\t\t\t\tpush.apply( results, seed );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Compile and execute a filtering function if one is not provided\n\t// Provide `match` to avoid retokenization if we modified the selector above\n\t( compiled || compile( selector, match ) )(\n\t\tseed,\n\t\tcontext,\n\t\t!documentIsHTML,\n\t\tresults,\n\t\t!context || rsibling.test( selector ) && testContext( context.parentNode ) || context\n\t);\n\treturn results;\n};\n\n// One-time assignments\n\n// Sort stability\nsupport.sortStable = expando.split( \"\" ).sort( sortOrder ).join( \"\" ) === expando;\n\n// Support: Chrome 14-35+\n// Always assume duplicates if they aren't passed to the comparison function\nsupport.detectDuplicates = !!hasDuplicate;\n\n// Initialize against the default document\nsetDocument();\n\n// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)\n// Detached nodes confoundingly follow *each other*\nsupport.sortDetached = assert( function( el ) {\n\n\t// Should return 1, but returns 4 (following)\n\treturn el.compareDocumentPosition( document.createElement( \"fieldset\" ) ) & 1;\n} );\n\n// Support: IE<8\n// Prevent attribute/property \"interpolation\"\n// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\nif ( !assert( function( el ) {\n\tel.innerHTML = \"<a href='#'></a>\";\n\treturn el.firstChild.getAttribute( \"href\" ) === \"#\";\n} ) ) {\n\taddHandle( \"type|href|height|width\", function( elem, name, isXML ) {\n\t\tif ( !isXML ) {\n\t\t\treturn elem.getAttribute( name, name.toLowerCase() === \"type\" ? 1 : 2 );\n\t\t}\n\t} );\n}\n\n// Support: IE<9\n// Use defaultValue in place of getAttribute(\"value\")\nif ( !support.attributes || !assert( function( el ) {\n\tel.innerHTML = \"<input/>\";\n\tel.firstChild.setAttribute( \"value\", \"\" );\n\treturn el.firstChild.getAttribute( \"value\" ) === \"\";\n} ) ) {\n\taddHandle( \"value\", function( elem, _name, isXML ) {\n\t\tif ( !isXML && elem.nodeName.toLowerCase() === \"input\" ) {\n\t\t\treturn elem.defaultValue;\n\t\t}\n\t} );\n}\n\n// Support: IE<9\n// Use getAttributeNode to fetch booleans when getAttribute lies\nif ( !assert( function( el ) {\n\treturn el.getAttribute( \"disabled\" ) == null;\n} ) ) {\n\taddHandle( booleans, function( elem, name, isXML ) {\n\t\tvar val;\n\t\tif ( !isXML ) {\n\t\t\treturn elem[ name ] === true ? name.toLowerCase() :\n\t\t\t\t( val = elem.getAttributeNode( name ) ) && val.specified ?\n\t\t\t\t\tval.value :\n\t\t\t\t\tnull;\n\t\t}\n\t} );\n}\n\nreturn Sizzle;\n\n} )( window );\n\n\n\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\n\n// Deprecated\njQuery.expr[ \":\" ] = jQuery.expr.pseudos;\njQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\njQuery.escapeSelector = Sizzle.escape;\n\n\n\n\nvar dir = function( elem, dir, until ) {\n\tvar matched = [],\n\t\ttruncate = until !== undefined;\n\n\twhile ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {\n\t\tif ( elem.nodeType === 1 ) {\n\t\t\tif ( truncate && jQuery( elem ).is( until ) ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tmatched.push( elem );\n\t\t}\n\t}\n\treturn matched;\n};\n\n\nvar siblings = function( n, elem ) {\n\tvar matched = [];\n\n\tfor ( ; n; n = n.nextSibling ) {\n\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\tmatched.push( n );\n\t\t}\n\t}\n\n\treturn matched;\n};\n\n\nvar rneedsContext = jQuery.expr.match.needsContext;\n\n\n\nfunction nodeName( elem, name ) {\n\n  return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n\n};\nvar rsingleTag = ( /^<([a-z][^\\/\\0>:\\x20\\t\\r\\n\\f]*)[\\x20\\t\\r\\n\\f]*\\/?>(?:<\\/\\1>|)$/i );\n\n\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, not ) {\n\tif ( isFunction( qualifier ) ) {\n\t\treturn jQuery.grep( elements, function( elem, i ) {\n\t\t\treturn !!qualifier.call( elem, i, elem ) !== not;\n\t\t} );\n\t}\n\n\t// Single element\n\tif ( qualifier.nodeType ) {\n\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\treturn ( elem === qualifier ) !== not;\n\t\t} );\n\t}\n\n\t// Arraylike of elements (jQuery, arguments, Array)\n\tif ( typeof qualifier !== \"string\" ) {\n\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\treturn ( indexOf.call( qualifier, elem ) > -1 ) !== not;\n\t\t} );\n\t}\n\n\t// Filtered directly for both simple and complex selectors\n\treturn jQuery.filter( qualifier, elements, not );\n}\n\njQuery.filter = function( expr, elems, not ) {\n\tvar elem = elems[ 0 ];\n\n\tif ( not ) {\n\t\texpr = \":not(\" + expr + \")\";\n\t}\n\n\tif ( elems.length === 1 && elem.nodeType === 1 ) {\n\t\treturn jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [];\n\t}\n\n\treturn jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {\n\t\treturn elem.nodeType === 1;\n\t} ) );\n};\n\njQuery.fn.extend( {\n\tfind: function( selector ) {\n\t\tvar i, ret,\n\t\t\tlen = this.length,\n\t\t\tself = this;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn this.pushStack( jQuery( selector ).filter( function() {\n\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} ) );\n\t\t}\n\n\t\tret = this.pushStack( [] );\n\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\tjQuery.find( selector, self[ i ], ret );\n\t\t}\n\n\t\treturn len > 1 ? jQuery.uniqueSort( ret ) : ret;\n\t},\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow( this, selector || [], false ) );\n\t},\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow( this, selector || [], true ) );\n\t},\n\tis: function( selector ) {\n\t\treturn !!winnow(\n\t\t\tthis,\n\n\t\t\t// If this is a positional/relative selector, check membership in the returned set\n\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\ttypeof selector === \"string\" && rneedsContext.test( selector ) ?\n\t\t\t\tjQuery( selector ) :\n\t\t\t\tselector || [],\n\t\t\tfalse\n\t\t).length;\n\t}\n} );\n\n\n// Initialize a jQuery object\n\n\n// A central reference to the root jQuery(document)\nvar rootjQuery,\n\n\t// A simple way to check for HTML strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\t// Strict HTML recognition (#11290: must start with <)\n\t// Shortcut simple #id case for speed\n\trquickExpr = /^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]+))$/,\n\n\tinit = jQuery.fn.init = function( selector, context, root ) {\n\t\tvar match, elem;\n\n\t\t// HANDLE: $(\"\"), $(null), $(undefined), $(false)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Method init() accepts an alternate rootjQuery\n\t\t// so migrate can support jQuery.sub (gh-2101)\n\t\troot = root || rootjQuery;\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\tif ( selector[ 0 ] === \"<\" &&\n\t\t\t\tselector[ selector.length - 1 ] === \">\" &&\n\t\t\t\tselector.length >= 3 ) {\n\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = rquickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Match html or make sure no context is specified for #id\n\t\t\tif ( match && ( match[ 1 ] || !context ) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[ 1 ] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[ 0 ] : context;\n\n\t\t\t\t\t// Option to run scripts is true for back-compat\n\t\t\t\t\t// Intentionally let the error be thrown if parseHTML is not present\n\t\t\t\t\tjQuery.merge( this, jQuery.parseHTML(\n\t\t\t\t\t\tmatch[ 1 ],\n\t\t\t\t\t\tcontext && context.nodeType ? context.ownerDocument || context : document,\n\t\t\t\t\t\ttrue\n\t\t\t\t\t) );\n\n\t\t\t\t\t// HANDLE: $(html, props)\n\t\t\t\t\tif ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\tfor ( match in context ) {\n\n\t\t\t\t\t\t\t// Properties of context are called as methods if possible\n\t\t\t\t\t\t\tif ( isFunction( this[ match ] ) ) {\n\t\t\t\t\t\t\t\tthis[ match ]( context[ match ] );\n\n\t\t\t\t\t\t\t// ...and otherwise set as attributes\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.attr( match, context[ match ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn this;\n\n\t\t\t\t// HANDLE: $(#id)\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[ 2 ] );\n\n\t\t\t\t\tif ( elem ) {\n\n\t\t\t\t\t\t// Inject the element directly into the jQuery object\n\t\t\t\t\t\tthis[ 0 ] = elem;\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || root ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(DOMElement)\n\t\t} else if ( selector.nodeType ) {\n\t\t\tthis[ 0 ] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( isFunction( selector ) ) {\n\t\t\treturn root.ready !== undefined ?\n\t\t\t\troot.ready( selector ) :\n\n\t\t\t\t// Execute immediately if ready is not present\n\t\t\t\tselector( jQuery );\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t};\n\n// Give the init function the jQuery prototype for later instantiation\ninit.prototype = jQuery.fn;\n\n// Initialize central reference\nrootjQuery = jQuery( document );\n\n\nvar rparentsprev = /^(?:parents|prev(?:Until|All))/,\n\n\t// Methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend( {\n\thas: function( target ) {\n\t\tvar targets = jQuery( target, this ),\n\t\t\tl = targets.length;\n\n\t\treturn this.filter( function() {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[ i ] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tmatched = [],\n\t\t\ttargets = typeof selectors !== \"string\" && jQuery( selectors );\n\n\t\t// Positional selectors never match, since there's no _selection_ context\n\t\tif ( !rneedsContext.test( selectors ) ) {\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tfor ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {\n\n\t\t\t\t\t// Always skip document fragments\n\t\t\t\t\tif ( cur.nodeType < 11 && ( targets ?\n\t\t\t\t\t\ttargets.index( cur ) > -1 :\n\n\t\t\t\t\t\t// Don't pass non-elements to Sizzle\n\t\t\t\t\t\tcur.nodeType === 1 &&\n\t\t\t\t\t\t\tjQuery.find.matchesSelector( cur, selectors ) ) ) {\n\n\t\t\t\t\t\tmatched.push( cur );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );\n\t},\n\n\t// Determine the position of an element within the set\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;\n\t\t}\n\n\t\t// Index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn indexOf.call( jQuery( elem ), this[ 0 ] );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn indexOf.call( this,\n\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[ 0 ] : elem\n\t\t);\n\t},\n\n\tadd: function( selector, context ) {\n\t\treturn this.pushStack(\n\t\t\tjQuery.uniqueSort(\n\t\t\t\tjQuery.merge( this.get(), jQuery( selector, context ) )\n\t\t\t)\n\t\t);\n\t},\n\n\taddBack: function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter( selector )\n\t\t);\n\t}\n} );\n\nfunction sibling( cur, dir ) {\n\twhile ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}\n\treturn cur;\n}\n\njQuery.each( {\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, _i, until ) {\n\t\treturn dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn sibling( elem, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn sibling( elem, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, _i, until ) {\n\t\treturn dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, _i, until ) {\n\t\treturn dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn siblings( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn siblings( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\tif ( elem.contentDocument != null &&\n\n\t\t\t// Support: IE 11+\n\t\t\t// <object> elements with no `data` attribute has an object\n\t\t\t// `contentDocument` with a `null` prototype.\n\t\t\tgetProto( elem.contentDocument ) ) {\n\n\t\t\treturn elem.contentDocument;\n\t\t}\n\n\t\t// Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only\n\t\t// Treat the template element as a regular one in browsers that\n\t\t// don't support it.\n\t\tif ( nodeName( elem, \"template\" ) ) {\n\t\t\telem = elem.content || elem;\n\t\t}\n\n\t\treturn jQuery.merge( [], elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar matched = jQuery.map( this, fn, until );\n\n\t\tif ( name.slice( -5 ) !== \"Until\" ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tmatched = jQuery.filter( selector, matched );\n\t\t}\n\n\t\tif ( this.length > 1 ) {\n\n\t\t\t// Remove duplicates\n\t\t\tif ( !guaranteedUnique[ name ] ) {\n\t\t\t\tjQuery.uniqueSort( matched );\n\t\t\t}\n\n\t\t\t// Reverse order for parents* and prev-derivatives\n\t\t\tif ( rparentsprev.test( name ) ) {\n\t\t\t\tmatched.reverse();\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched );\n\t};\n} );\nvar rnothtmlwhite = ( /[^\\x20\\t\\r\\n\\f]+/g );\n\n\n\n// Convert String-formatted options into Object-formatted ones\nfunction createOptions( options ) {\n\tvar object = {};\n\tjQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {\n\t\tobject[ flag ] = true;\n\t} );\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\toptions: an optional list of space-separated options that will change how\n *\t\t\tthe callback list behaves or a more traditional option object\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible options:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( options ) {\n\n\t// Convert options from String-formatted to Object-formatted if needed\n\t// (we check in cache first)\n\toptions = typeof options === \"string\" ?\n\t\tcreateOptions( options ) :\n\t\tjQuery.extend( {}, options );\n\n\tvar // Flag to know if list is currently firing\n\t\tfiring,\n\n\t\t// Last fire value for non-forgettable lists\n\t\tmemory,\n\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\n\t\t// Flag to prevent firing\n\t\tlocked,\n\n\t\t// Actual callback list\n\t\tlist = [],\n\n\t\t// Queue of execution data for repeatable lists\n\t\tqueue = [],\n\n\t\t// Index of currently firing callback (modified by add/remove as needed)\n\t\tfiringIndex = -1,\n\n\t\t// Fire callbacks\n\t\tfire = function() {\n\n\t\t\t// Enforce single-firing\n\t\t\tlocked = locked || options.once;\n\n\t\t\t// Execute callbacks for all pending executions,\n\t\t\t// respecting firingIndex overrides and runtime changes\n\t\t\tfired = firing = true;\n\t\t\tfor ( ; queue.length; firingIndex = -1 ) {\n\t\t\t\tmemory = queue.shift();\n\t\t\t\twhile ( ++firingIndex < list.length ) {\n\n\t\t\t\t\t// Run callback and check for early termination\n\t\t\t\t\tif ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&\n\t\t\t\t\t\toptions.stopOnFalse ) {\n\n\t\t\t\t\t\t// Jump to end and forget the data so .add doesn't re-fire\n\t\t\t\t\t\tfiringIndex = list.length;\n\t\t\t\t\t\tmemory = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Forget the data if we're done with it\n\t\t\tif ( !options.memory ) {\n\t\t\t\tmemory = false;\n\t\t\t}\n\n\t\t\tfiring = false;\n\n\t\t\t// Clean up if we're done firing for good\n\t\t\tif ( locked ) {\n\n\t\t\t\t// Keep an empty list if we have data for future add calls\n\t\t\t\tif ( memory ) {\n\t\t\t\t\tlist = [];\n\n\t\t\t\t// Otherwise, this object is spent\n\t\t\t\t} else {\n\t\t\t\t\tlist = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t// Actual Callbacks object\n\t\tself = {\n\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\n\t\t\t\t\t// If we have memory from a past run, we should fire after adding\n\t\t\t\t\tif ( memory && !firing ) {\n\t\t\t\t\t\tfiringIndex = list.length - 1;\n\t\t\t\t\t\tqueue.push( memory );\n\t\t\t\t\t}\n\n\t\t\t\t\t( function add( args ) {\n\t\t\t\t\t\tjQuery.each( args, function( _, arg ) {\n\t\t\t\t\t\t\tif ( isFunction( arg ) ) {\n\t\t\t\t\t\t\t\tif ( !options.unique || !self.has( arg ) ) {\n\t\t\t\t\t\t\t\t\tlist.push( arg );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if ( arg && arg.length && toType( arg ) !== \"string\" ) {\n\n\t\t\t\t\t\t\t\t// Inspect recursively\n\t\t\t\t\t\t\t\tadd( arg );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} );\n\t\t\t\t\t} )( arguments );\n\n\t\t\t\t\tif ( memory && !firing ) {\n\t\t\t\t\t\tfire();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tjQuery.each( arguments, function( _, arg ) {\n\t\t\t\t\tvar index;\n\t\t\t\t\twhile ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n\t\t\t\t\t\tlist.splice( index, 1 );\n\n\t\t\t\t\t\t// Handle firing indexes\n\t\t\t\t\t\tif ( index <= firingIndex ) {\n\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Check if a given callback is in the list.\n\t\t\t// If no argument is given, return whether or not list has callbacks attached.\n\t\t\thas: function( fn ) {\n\t\t\t\treturn fn ?\n\t\t\t\t\tjQuery.inArray( fn, list ) > -1 :\n\t\t\t\t\tlist.length > 0;\n\t\t\t},\n\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tlist = [];\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Disable .fire and .add\n\t\t\t// Abort any current/pending executions\n\t\t\t// Clear all callbacks and values\n\t\t\tdisable: function() {\n\t\t\t\tlocked = queue = [];\n\t\t\t\tlist = memory = \"\";\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\n\t\t\t// Disable .fire\n\t\t\t// Also disable .add unless we have memory (since it would have no effect)\n\t\t\t// Abort any pending executions\n\t\t\tlock: function() {\n\t\t\t\tlocked = queue = [];\n\t\t\t\tif ( !memory && !firing ) {\n\t\t\t\t\tlist = memory = \"\";\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\tlocked: function() {\n\t\t\t\treturn !!locked;\n\t\t\t},\n\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( !locked ) {\n\t\t\t\t\targs = args || [];\n\t\t\t\t\targs = [ context, args.slice ? args.slice() : args ];\n\t\t\t\t\tqueue.push( args );\n\t\t\t\t\tif ( !firing ) {\n\t\t\t\t\t\tfire();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\nfunction Identity( v ) {\n\treturn v;\n}\nfunction Thrower( ex ) {\n\tthrow ex;\n}\n\nfunction adoptValue( value, resolve, reject, noValue ) {\n\tvar method;\n\n\ttry {\n\n\t\t// Check for promise aspect first to privilege synchronous behavior\n\t\tif ( value && isFunction( ( method = value.promise ) ) ) {\n\t\t\tmethod.call( value ).done( resolve ).fail( reject );\n\n\t\t// Other thenables\n\t\t} else if ( value && isFunction( ( method = value.then ) ) ) {\n\t\t\tmethod.call( value, resolve, reject );\n\n\t\t// Other non-thenables\n\t\t} else {\n\n\t\t\t// Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer:\n\t\t\t// * false: [ value ].slice( 0 ) => resolve( value )\n\t\t\t// * true: [ value ].slice( 1 ) => resolve()\n\t\t\tresolve.apply( undefined, [ value ].slice( noValue ) );\n\t\t}\n\n\t// For Promises/A+, convert exceptions into rejections\n\t// Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in\n\t// Deferred#then to conditionally suppress rejection.\n\t} catch ( value ) {\n\n\t\t// Support: Android 4.0 only\n\t\t// Strict mode functions invoked without .call/.apply get global-object context\n\t\treject.apply( undefined, [ value ] );\n\t}\n}\n\njQuery.extend( {\n\n\tDeferred: function( func ) {\n\t\tvar tuples = [\n\n\t\t\t\t// action, add listener, callbacks,\n\t\t\t\t// ... .then handlers, argument index, [final state]\n\t\t\t\t[ \"notify\", \"progress\", jQuery.Callbacks( \"memory\" ),\n\t\t\t\t\tjQuery.Callbacks( \"memory\" ), 2 ],\n\t\t\t\t[ \"resolve\", \"done\", jQuery.Callbacks( \"once memory\" ),\n\t\t\t\t\tjQuery.Callbacks( \"once memory\" ), 0, \"resolved\" ],\n\t\t\t\t[ \"reject\", \"fail\", jQuery.Callbacks( \"once memory\" ),\n\t\t\t\t\tjQuery.Callbacks( \"once memory\" ), 1, \"rejected\" ]\n\t\t\t],\n\t\t\tstate = \"pending\",\n\t\t\tpromise = {\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done( arguments ).fail( arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\t\"catch\": function( fn ) {\n\t\t\t\t\treturn promise.then( null, fn );\n\t\t\t\t},\n\n\t\t\t\t// Keep pipe for back-compat\n\t\t\t\tpipe: function( /* fnDone, fnFail, fnProgress */ ) {\n\t\t\t\t\tvar fns = arguments;\n\n\t\t\t\t\treturn jQuery.Deferred( function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( tuples, function( _i, tuple ) {\n\n\t\t\t\t\t\t\t// Map tuples (progress, done, fail) to arguments (done, fail, progress)\n\t\t\t\t\t\t\tvar fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];\n\n\t\t\t\t\t\t\t// deferred.progress(function() { bind to newDefer or newDefer.notify })\n\t\t\t\t\t\t\t// deferred.done(function() { bind to newDefer or newDefer.resolve })\n\t\t\t\t\t\t\t// deferred.fail(function() { bind to newDefer or newDefer.reject })\n\t\t\t\t\t\t\tdeferred[ tuple[ 1 ] ]( function() {\n\t\t\t\t\t\t\t\tvar returned = fn && fn.apply( this, arguments );\n\t\t\t\t\t\t\t\tif ( returned && isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\treturned.promise()\n\t\t\t\t\t\t\t\t\t\t.progress( newDefer.notify )\n\t\t\t\t\t\t\t\t\t\t.done( newDefer.resolve )\n\t\t\t\t\t\t\t\t\t\t.fail( newDefer.reject );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tnewDefer[ tuple[ 0 ] + \"With\" ](\n\t\t\t\t\t\t\t\t\t\tthis,\n\t\t\t\t\t\t\t\t\t\tfn ? [ returned ] : arguments\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t} );\n\t\t\t\t\t\tfns = null;\n\t\t\t\t\t} ).promise();\n\t\t\t\t},\n\t\t\t\tthen: function( onFulfilled, onRejected, onProgress ) {\n\t\t\t\t\tvar maxDepth = 0;\n\t\t\t\t\tfunction resolve( depth, deferred, handler, special ) {\n\t\t\t\t\t\treturn function() {\n\t\t\t\t\t\t\tvar that = this,\n\t\t\t\t\t\t\t\targs = arguments,\n\t\t\t\t\t\t\t\tmightThrow = function() {\n\t\t\t\t\t\t\t\t\tvar returned, then;\n\n\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.3\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-59\n\t\t\t\t\t\t\t\t\t// Ignore double-resolution attempts\n\t\t\t\t\t\t\t\t\tif ( depth < maxDepth ) {\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\treturned = handler.apply( that, args );\n\n\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.1\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-48\n\t\t\t\t\t\t\t\t\tif ( returned === deferred.promise() ) {\n\t\t\t\t\t\t\t\t\t\tthrow new TypeError( \"Thenable self-resolution\" );\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Support: Promises/A+ sections 2.3.3.1, 3.5\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-54\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-75\n\t\t\t\t\t\t\t\t\t// Retrieve `then` only once\n\t\t\t\t\t\t\t\t\tthen = returned &&\n\n\t\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.4\n\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-64\n\t\t\t\t\t\t\t\t\t\t// Only check objects and functions for thenability\n\t\t\t\t\t\t\t\t\t\t( typeof returned === \"object\" ||\n\t\t\t\t\t\t\t\t\t\t\ttypeof returned === \"function\" ) &&\n\t\t\t\t\t\t\t\t\t\treturned.then;\n\n\t\t\t\t\t\t\t\t\t// Handle a returned thenable\n\t\t\t\t\t\t\t\t\tif ( isFunction( then ) ) {\n\n\t\t\t\t\t\t\t\t\t\t// Special processors (notify) just wait for resolution\n\t\t\t\t\t\t\t\t\t\tif ( special ) {\n\t\t\t\t\t\t\t\t\t\t\tthen.call(\n\t\t\t\t\t\t\t\t\t\t\t\treturned,\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity, special ),\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Thrower, special )\n\t\t\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\t\t\t// Normal processors (resolve) also hook into progress\n\t\t\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t\t\t// ...and disregard older resolution values\n\t\t\t\t\t\t\t\t\t\t\tmaxDepth++;\n\n\t\t\t\t\t\t\t\t\t\t\tthen.call(\n\t\t\t\t\t\t\t\t\t\t\t\treturned,\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity, special ),\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Thrower, special ),\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity,\n\t\t\t\t\t\t\t\t\t\t\t\t\tdeferred.notifyWith )\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Handle all other returned values\n\t\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t\t// Only substitute handlers pass on context\n\t\t\t\t\t\t\t\t\t\t// and multiple values (non-spec behavior)\n\t\t\t\t\t\t\t\t\t\tif ( handler !== Identity ) {\n\t\t\t\t\t\t\t\t\t\t\tthat = undefined;\n\t\t\t\t\t\t\t\t\t\t\targs = [ returned ];\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t// Process the value(s)\n\t\t\t\t\t\t\t\t\t\t// Default process is resolve\n\t\t\t\t\t\t\t\t\t\t( special || deferred.resolveWith )( that, args );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\n\t\t\t\t\t\t\t\t// Only normal processors (resolve) catch and reject exceptions\n\t\t\t\t\t\t\t\tprocess = special ?\n\t\t\t\t\t\t\t\t\tmightThrow :\n\t\t\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\tmightThrow();\n\t\t\t\t\t\t\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t\t\t\t\t\t\tif ( jQuery.Deferred.exceptionHook ) {\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery.Deferred.exceptionHook( e,\n\t\t\t\t\t\t\t\t\t\t\t\t\tprocess.stackTrace );\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.4.1\n\t\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-61\n\t\t\t\t\t\t\t\t\t\t\t// Ignore post-resolution exceptions\n\t\t\t\t\t\t\t\t\t\t\tif ( depth + 1 >= maxDepth ) {\n\n\t\t\t\t\t\t\t\t\t\t\t\t// Only substitute handlers pass on context\n\t\t\t\t\t\t\t\t\t\t\t\t// and multiple values (non-spec behavior)\n\t\t\t\t\t\t\t\t\t\t\t\tif ( handler !== Thrower ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tthat = undefined;\n\t\t\t\t\t\t\t\t\t\t\t\t\targs = [ e ];\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\tdeferred.rejectWith( that, args );\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.1\n\t\t\t\t\t\t\t// https://promisesaplus.com/#point-57\n\t\t\t\t\t\t\t// Re-resolve promises immediately to dodge false rejection from\n\t\t\t\t\t\t\t// subsequent errors\n\t\t\t\t\t\t\tif ( depth ) {\n\t\t\t\t\t\t\t\tprocess();\n\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t// Call an optional hook to record the stack, in case of exception\n\t\t\t\t\t\t\t\t// since it's otherwise lost when execution goes async\n\t\t\t\t\t\t\t\tif ( jQuery.Deferred.getStackHook ) {\n\t\t\t\t\t\t\t\t\tprocess.stackTrace = jQuery.Deferred.getStackHook();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\twindow.setTimeout( process );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.Deferred( function( newDefer ) {\n\n\t\t\t\t\t\t// progress_handlers.add( ... )\n\t\t\t\t\t\ttuples[ 0 ][ 3 ].add(\n\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\tisFunction( onProgress ) ?\n\t\t\t\t\t\t\t\t\tonProgress :\n\t\t\t\t\t\t\t\t\tIdentity,\n\t\t\t\t\t\t\t\tnewDefer.notifyWith\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// fulfilled_handlers.add( ... )\n\t\t\t\t\t\ttuples[ 1 ][ 3 ].add(\n\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\tisFunction( onFulfilled ) ?\n\t\t\t\t\t\t\t\t\tonFulfilled :\n\t\t\t\t\t\t\t\t\tIdentity\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// rejected_handlers.add( ... )\n\t\t\t\t\t\ttuples[ 2 ][ 3 ].add(\n\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\tisFunction( onRejected ) ?\n\t\t\t\t\t\t\t\t\tonRejected :\n\t\t\t\t\t\t\t\t\tThrower\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\t\t\t\t\t} ).promise();\n\t\t\t\t},\n\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\treturn obj != null ? jQuery.extend( obj, promise ) : promise;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = {};\n\n\t\t// Add list-specific methods\n\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\tvar list = tuple[ 2 ],\n\t\t\t\tstateString = tuple[ 5 ];\n\n\t\t\t// promise.progress = list.add\n\t\t\t// promise.done = list.add\n\t\t\t// promise.fail = list.add\n\t\t\tpromise[ tuple[ 1 ] ] = list.add;\n\n\t\t\t// Handle state\n\t\t\tif ( stateString ) {\n\t\t\t\tlist.add(\n\t\t\t\t\tfunction() {\n\n\t\t\t\t\t\t// state = \"resolved\" (i.e., fulfilled)\n\t\t\t\t\t\t// state = \"rejected\"\n\t\t\t\t\t\tstate = stateString;\n\t\t\t\t\t},\n\n\t\t\t\t\t// rejected_callbacks.disable\n\t\t\t\t\t// fulfilled_callbacks.disable\n\t\t\t\t\ttuples[ 3 - i ][ 2 ].disable,\n\n\t\t\t\t\t// rejected_handlers.disable\n\t\t\t\t\t// fulfilled_handlers.disable\n\t\t\t\t\ttuples[ 3 - i ][ 3 ].disable,\n\n\t\t\t\t\t// progress_callbacks.lock\n\t\t\t\t\ttuples[ 0 ][ 2 ].lock,\n\n\t\t\t\t\t// progress_handlers.lock\n\t\t\t\t\ttuples[ 0 ][ 3 ].lock\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// progress_handlers.fire\n\t\t\t// fulfilled_handlers.fire\n\t\t\t// rejected_handlers.fire\n\t\t\tlist.add( tuple[ 3 ].fire );\n\n\t\t\t// deferred.notify = function() { deferred.notifyWith(...) }\n\t\t\t// deferred.resolve = function() { deferred.resolveWith(...) }\n\t\t\t// deferred.reject = function() { deferred.rejectWith(...) }\n\t\t\tdeferred[ tuple[ 0 ] ] = function() {\n\t\t\t\tdeferred[ tuple[ 0 ] + \"With\" ]( this === deferred ? undefined : this, arguments );\n\t\t\t\treturn this;\n\t\t\t};\n\n\t\t\t// deferred.notifyWith = list.fireWith\n\t\t\t// deferred.resolveWith = list.fireWith\n\t\t\t// deferred.rejectWith = list.fireWith\n\t\t\tdeferred[ tuple[ 0 ] + \"With\" ] = list.fireWith;\n\t\t} );\n\n\t\t// Make the deferred a promise\n\t\tpromise.promise( deferred );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( singleValue ) {\n\t\tvar\n\n\t\t\t// count of uncompleted subordinates\n\t\t\tremaining = arguments.length,\n\n\t\t\t// count of unprocessed arguments\n\t\t\ti = remaining,\n\n\t\t\t// subordinate fulfillment data\n\t\t\tresolveContexts = Array( i ),\n\t\t\tresolveValues = slice.call( arguments ),\n\n\t\t\t// the master Deferred\n\t\t\tmaster = jQuery.Deferred(),\n\n\t\t\t// subordinate callback factory\n\t\t\tupdateFunc = function( i ) {\n\t\t\t\treturn function( value ) {\n\t\t\t\t\tresolveContexts[ i ] = this;\n\t\t\t\t\tresolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;\n\t\t\t\t\tif ( !( --remaining ) ) {\n\t\t\t\t\t\tmaster.resolveWith( resolveContexts, resolveValues );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t};\n\n\t\t// Single- and empty arguments are adopted like Promise.resolve\n\t\tif ( remaining <= 1 ) {\n\t\t\tadoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject,\n\t\t\t\t!remaining );\n\n\t\t\t// Use .then() to unwrap secondary thenables (cf. gh-3000)\n\t\t\tif ( master.state() === \"pending\" ||\n\t\t\t\tisFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {\n\n\t\t\t\treturn master.then();\n\t\t\t}\n\t\t}\n\n\t\t// Multiple arguments are aggregated like Promise.all array elements\n\t\twhile ( i-- ) {\n\t\t\tadoptValue( resolveValues[ i ], updateFunc( i ), master.reject );\n\t\t}\n\n\t\treturn master.promise();\n\t}\n} );\n\n\n// These usually indicate a programmer mistake during development,\n// warn about them ASAP rather than swallowing them by default.\nvar rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;\n\njQuery.Deferred.exceptionHook = function( error, stack ) {\n\n\t// Support: IE 8 - 9 only\n\t// Console exists when dev tools are open, which can happen at any time\n\tif ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {\n\t\twindow.console.warn( \"jQuery.Deferred exception: \" + error.message, error.stack, stack );\n\t}\n};\n\n\n\n\njQuery.readyException = function( error ) {\n\twindow.setTimeout( function() {\n\t\tthrow error;\n\t} );\n};\n\n\n\n\n// The deferred used on DOM ready\nvar readyList = jQuery.Deferred();\n\njQuery.fn.ready = function( fn ) {\n\n\treadyList\n\t\t.then( fn )\n\n\t\t// Wrap jQuery.readyException in a function so that the lookup\n\t\t// happens at the time of error handling instead of callback\n\t\t// registration.\n\t\t.catch( function( error ) {\n\t\t\tjQuery.readyException( error );\n\t\t} );\n\n\treturn this;\n};\n\njQuery.extend( {\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\n\t\t// Abort if there are pending holds or we're already ready\n\t\tif ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Remember that the DOM is ready\n\t\tjQuery.isReady = true;\n\n\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If there are functions bound, to execute\n\t\treadyList.resolveWith( document, [ jQuery ] );\n\t}\n} );\n\njQuery.ready.then = readyList.then;\n\n// The ready event handler and self cleanup method\nfunction completed() {\n\tdocument.removeEventListener( \"DOMContentLoaded\", completed );\n\twindow.removeEventListener( \"load\", completed );\n\tjQuery.ready();\n}\n\n// Catch cases where $(document).ready() is called\n// after the browser event has already occurred.\n// Support: IE <=9 - 10 only\n// Older IE sometimes signals \"interactive\" too soon\nif ( document.readyState === \"complete\" ||\n\t( document.readyState !== \"loading\" && !document.documentElement.doScroll ) ) {\n\n\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\twindow.setTimeout( jQuery.ready );\n\n} else {\n\n\t// Use the handy event callback\n\tdocument.addEventListener( \"DOMContentLoaded\", completed );\n\n\t// A fallback to window.onload, that will always work\n\twindow.addEventListener( \"load\", completed );\n}\n\n\n\n\n// Multifunctional method to get and set values of a collection\n// The value/s can optionally be executed if it's a function\nvar access = function( elems, fn, key, value, chainable, emptyGet, raw ) {\n\tvar i = 0,\n\t\tlen = elems.length,\n\t\tbulk = key == null;\n\n\t// Sets many values\n\tif ( toType( key ) === \"object\" ) {\n\t\tchainable = true;\n\t\tfor ( i in key ) {\n\t\t\taccess( elems, fn, i, key[ i ], true, emptyGet, raw );\n\t\t}\n\n\t// Sets one value\n\t} else if ( value !== undefined ) {\n\t\tchainable = true;\n\n\t\tif ( !isFunction( value ) ) {\n\t\t\traw = true;\n\t\t}\n\n\t\tif ( bulk ) {\n\n\t\t\t// Bulk operations run against the entire set\n\t\t\tif ( raw ) {\n\t\t\t\tfn.call( elems, value );\n\t\t\t\tfn = null;\n\n\t\t\t// ...except when executing function values\n\t\t\t} else {\n\t\t\t\tbulk = fn;\n\t\t\t\tfn = function( elem, _key, value ) {\n\t\t\t\t\treturn bulk.call( jQuery( elem ), value );\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\tfn(\n\t\t\t\t\telems[ i ], key, raw ?\n\t\t\t\t\tvalue :\n\t\t\t\t\tvalue.call( elems[ i ], i, fn( elems[ i ], key ) )\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( chainable ) {\n\t\treturn elems;\n\t}\n\n\t// Gets\n\tif ( bulk ) {\n\t\treturn fn.call( elems );\n\t}\n\n\treturn len ? fn( elems[ 0 ], key ) : emptyGet;\n};\n\n\n// Matches dashed string for camelizing\nvar rmsPrefix = /^-ms-/,\n\trdashAlpha = /-([a-z])/g;\n\n// Used by camelCase as callback to replace()\nfunction fcamelCase( _all, letter ) {\n\treturn letter.toUpperCase();\n}\n\n// Convert dashed to camelCase; used by the css and data modules\n// Support: IE <=9 - 11, Edge 12 - 15\n// Microsoft forgot to hump their vendor prefix (#9572)\nfunction camelCase( string ) {\n\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n}\nvar acceptData = function( owner ) {\n\n\t// Accepts only:\n\t//  - Node\n\t//    - Node.ELEMENT_NODE\n\t//    - Node.DOCUMENT_NODE\n\t//  - Object\n\t//    - Any\n\treturn owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );\n};\n\n\n\n\nfunction Data() {\n\tthis.expando = jQuery.expando + Data.uid++;\n}\n\nData.uid = 1;\n\nData.prototype = {\n\n\tcache: function( owner ) {\n\n\t\t// Check if the owner object already has a cache\n\t\tvar value = owner[ this.expando ];\n\n\t\t// If not, create one\n\t\tif ( !value ) {\n\t\t\tvalue = {};\n\n\t\t\t// We can accept data for non-element nodes in modern browsers,\n\t\t\t// but we should not, see #8335.\n\t\t\t// Always return an empty object.\n\t\t\tif ( acceptData( owner ) ) {\n\n\t\t\t\t// If it is a node unlikely to be stringify-ed or looped over\n\t\t\t\t// use plain assignment\n\t\t\t\tif ( owner.nodeType ) {\n\t\t\t\t\towner[ this.expando ] = value;\n\n\t\t\t\t// Otherwise secure it in a non-enumerable property\n\t\t\t\t// configurable must be true to allow the property to be\n\t\t\t\t// deleted when data is removed\n\t\t\t\t} else {\n\t\t\t\t\tObject.defineProperty( owner, this.expando, {\n\t\t\t\t\t\tvalue: value,\n\t\t\t\t\t\tconfigurable: true\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn value;\n\t},\n\tset: function( owner, data, value ) {\n\t\tvar prop,\n\t\t\tcache = this.cache( owner );\n\n\t\t// Handle: [ owner, key, value ] args\n\t\t// Always use camelCase key (gh-2257)\n\t\tif ( typeof data === \"string\" ) {\n\t\t\tcache[ camelCase( data ) ] = value;\n\n\t\t// Handle: [ owner, { properties } ] args\n\t\t} else {\n\n\t\t\t// Copy the properties one-by-one to the cache object\n\t\t\tfor ( prop in data ) {\n\t\t\t\tcache[ camelCase( prop ) ] = data[ prop ];\n\t\t\t}\n\t\t}\n\t\treturn cache;\n\t},\n\tget: function( owner, key ) {\n\t\treturn key === undefined ?\n\t\t\tthis.cache( owner ) :\n\n\t\t\t// Always use camelCase key (gh-2257)\n\t\t\towner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ];\n\t},\n\taccess: function( owner, key, value ) {\n\n\t\t// In cases where either:\n\t\t//\n\t\t//   1. No key was specified\n\t\t//   2. A string key was specified, but no value provided\n\t\t//\n\t\t// Take the \"read\" path and allow the get method to determine\n\t\t// which value to return, respectively either:\n\t\t//\n\t\t//   1. The entire cache object\n\t\t//   2. The data stored at the key\n\t\t//\n\t\tif ( key === undefined ||\n\t\t\t\t( ( key && typeof key === \"string\" ) && value === undefined ) ) {\n\n\t\t\treturn this.get( owner, key );\n\t\t}\n\n\t\t// When the key is not a string, or both a key and value\n\t\t// are specified, set or extend (existing objects) with either:\n\t\t//\n\t\t//   1. An object of properties\n\t\t//   2. A key and value\n\t\t//\n\t\tthis.set( owner, key, value );\n\n\t\t// Since the \"set\" path can have two possible entry points\n\t\t// return the expected data based on which path was taken[*]\n\t\treturn value !== undefined ? value : key;\n\t},\n\tremove: function( owner, key ) {\n\t\tvar i,\n\t\t\tcache = owner[ this.expando ];\n\n\t\tif ( cache === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( key !== undefined ) {\n\n\t\t\t// Support array or space separated string of keys\n\t\t\tif ( Array.isArray( key ) ) {\n\n\t\t\t\t// If key is an array of keys...\n\t\t\t\t// We always set camelCase keys, so remove that.\n\t\t\t\tkey = key.map( camelCase );\n\t\t\t} else {\n\t\t\t\tkey = camelCase( key );\n\n\t\t\t\t// If a key with the spaces exists, use it.\n\t\t\t\t// Otherwise, create an array by matching non-whitespace\n\t\t\t\tkey = key in cache ?\n\t\t\t\t\t[ key ] :\n\t\t\t\t\t( key.match( rnothtmlwhite ) || [] );\n\t\t\t}\n\n\t\t\ti = key.length;\n\n\t\t\twhile ( i-- ) {\n\t\t\t\tdelete cache[ key[ i ] ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if there's no more data\n\t\tif ( key === undefined || jQuery.isEmptyObject( cache ) ) {\n\n\t\t\t// Support: Chrome <=35 - 45\n\t\t\t// Webkit & Blink performance suffers when deleting properties\n\t\t\t// from DOM nodes, so set to undefined instead\n\t\t\t// https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)\n\t\t\tif ( owner.nodeType ) {\n\t\t\t\towner[ this.expando ] = undefined;\n\t\t\t} else {\n\t\t\t\tdelete owner[ this.expando ];\n\t\t\t}\n\t\t}\n\t},\n\thasData: function( owner ) {\n\t\tvar cache = owner[ this.expando ];\n\t\treturn cache !== undefined && !jQuery.isEmptyObject( cache );\n\t}\n};\nvar dataPriv = new Data();\n\nvar dataUser = new Data();\n\n\n\n//\tImplementation Summary\n//\n//\t1. Enforce API surface and semantic compatibility with 1.9.x branch\n//\t2. Improve the module's maintainability by reducing the storage\n//\t\tpaths to a single mechanism.\n//\t3. Use the same single mechanism to support \"private\" and \"user\" data.\n//\t4. _Never_ expose \"private\" data to user code (TODO: Drop _data, _removeData)\n//\t5. Avoid exposing implementation details on user objects (eg. expando properties)\n//\t6. Provide a clear path for implementation upgrade to WeakMap in 2014\n\nvar rbrace = /^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,\n\trmultiDash = /[A-Z]/g;\n\nfunction getData( data ) {\n\tif ( data === \"true\" ) {\n\t\treturn true;\n\t}\n\n\tif ( data === \"false\" ) {\n\t\treturn false;\n\t}\n\n\tif ( data === \"null\" ) {\n\t\treturn null;\n\t}\n\n\t// Only convert to a number if it doesn't change the string\n\tif ( data === +data + \"\" ) {\n\t\treturn +data;\n\t}\n\n\tif ( rbrace.test( data ) ) {\n\t\treturn JSON.parse( data );\n\t}\n\n\treturn data;\n}\n\nfunction dataAttr( elem, key, data ) {\n\tvar name;\n\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\t\tname = \"data-\" + key.replace( rmultiDash, \"-$&\" ).toLowerCase();\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = getData( data );\n\t\t\t} catch ( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tdataUser.set( elem, key, data );\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\treturn data;\n}\n\njQuery.extend( {\n\thasData: function( elem ) {\n\t\treturn dataUser.hasData( elem ) || dataPriv.hasData( elem );\n\t},\n\n\tdata: function( elem, name, data ) {\n\t\treturn dataUser.access( elem, name, data );\n\t},\n\n\tremoveData: function( elem, name ) {\n\t\tdataUser.remove( elem, name );\n\t},\n\n\t// TODO: Now that all calls to _data and _removeData have been replaced\n\t// with direct calls to dataPriv methods, these can be deprecated.\n\t_data: function( elem, name, data ) {\n\t\treturn dataPriv.access( elem, name, data );\n\t},\n\n\t_removeData: function( elem, name ) {\n\t\tdataPriv.remove( elem, name );\n\t}\n} );\n\njQuery.fn.extend( {\n\tdata: function( key, value ) {\n\t\tvar i, name, data,\n\t\t\telem = this[ 0 ],\n\t\t\tattrs = elem && elem.attributes;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = dataUser.get( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !dataPriv.get( elem, \"hasDataAttrs\" ) ) {\n\t\t\t\t\ti = attrs.length;\n\t\t\t\t\twhile ( i-- ) {\n\n\t\t\t\t\t\t// Support: IE 11 only\n\t\t\t\t\t\t// The attrs elements can be null (#14894)\n\t\t\t\t\t\tif ( attrs[ i ] ) {\n\t\t\t\t\t\t\tname = attrs[ i ].name;\n\t\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\t\tname = camelCase( name.slice( 5 ) );\n\t\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tdataPriv.set( elem, \"hasDataAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each( function() {\n\t\t\t\tdataUser.set( this, key );\n\t\t\t} );\n\t\t}\n\n\t\treturn access( this, function( value ) {\n\t\t\tvar data;\n\n\t\t\t// The calling jQuery object (element matches) is not empty\n\t\t\t// (and therefore has an element appears at this[ 0 ]) and the\n\t\t\t// `value` parameter was not undefined. An empty jQuery object\n\t\t\t// will result in `undefined` for elem = this[ 0 ] which will\n\t\t\t// throw an exception if an attempt to read a data cache is made.\n\t\t\tif ( elem && value === undefined ) {\n\n\t\t\t\t// Attempt to get data from the cache\n\t\t\t\t// The key will always be camelCased in Data\n\t\t\t\tdata = dataUser.get( elem, key );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// Attempt to \"discover\" the data in\n\t\t\t\t// HTML5 custom data-* attrs\n\t\t\t\tdata = dataAttr( elem, key );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// We tried really hard, but the data doesn't exist.\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Set the data...\n\t\t\tthis.each( function() {\n\n\t\t\t\t// We always store the camelCased key\n\t\t\t\tdataUser.set( this, key, value );\n\t\t\t} );\n\t\t}, null, value, arguments.length > 1, null, true );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each( function() {\n\t\t\tdataUser.remove( this, key );\n\t\t} );\n\t}\n} );\n\n\njQuery.extend( {\n\tqueue: function( elem, type, data ) {\n\t\tvar queue;\n\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tqueue = dataPriv.get( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !queue || Array.isArray( data ) ) {\n\t\t\t\t\tqueue = dataPriv.access( elem, type, jQuery.makeArray( data ) );\n\t\t\t\t} else {\n\t\t\t\t\tqueue.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn queue || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tstartLength = queue.length,\n\t\t\tfn = queue.shift(),\n\t\t\thooks = jQuery._queueHooks( elem, type ),\n\t\t\tnext = function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t\tstartLength--;\n\t\t}\n\n\t\tif ( fn ) {\n\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\t// Clear up the last queue stop function\n\t\t\tdelete hooks.stop;\n\t\t\tfn.call( elem, next, hooks );\n\t\t}\n\n\t\tif ( !startLength && hooks ) {\n\t\t\thooks.empty.fire();\n\t\t}\n\t},\n\n\t// Not public - generate a queueHooks object, or return the current one\n\t_queueHooks: function( elem, type ) {\n\t\tvar key = type + \"queueHooks\";\n\t\treturn dataPriv.get( elem, key ) || dataPriv.access( elem, key, {\n\t\t\tempty: jQuery.Callbacks( \"once memory\" ).add( function() {\n\t\t\t\tdataPriv.remove( elem, [ type + \"queue\", key ] );\n\t\t\t} )\n\t\t} );\n\t}\n} );\n\njQuery.fn.extend( {\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[ 0 ], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each( function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\t// Ensure a hooks for this queue\n\t\t\t\tjQuery._queueHooks( this, type );\n\n\t\t\t\tif ( type === \"fx\" && queue[ 0 ] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t} );\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each( function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t} );\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, obj ) {\n\t\tvar tmp,\n\t\t\tcount = 1,\n\t\t\tdefer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = this.length,\n\t\t\tresolve = function() {\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t\t}\n\t\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobj = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\n\t\twhile ( i-- ) {\n\t\t\ttmp = dataPriv.get( elements[ i ], type + \"queueHooks\" );\n\t\t\tif ( tmp && tmp.empty ) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.empty.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( obj );\n\t}\n} );\nvar pnum = ( /[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/ ).source;\n\nvar rcssNum = new RegExp( \"^(?:([+-])=|)(\" + pnum + \")([a-z%]*)$\", \"i\" );\n\n\nvar cssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ];\n\nvar documentElement = document.documentElement;\n\n\n\n\tvar isAttached = function( elem ) {\n\t\t\treturn jQuery.contains( elem.ownerDocument, elem );\n\t\t},\n\t\tcomposed = { composed: true };\n\n\t// Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only\n\t// Check attachment across shadow DOM boundaries when possible (gh-3504)\n\t// Support: iOS 10.0-10.2 only\n\t// Early iOS 10 versions support `attachShadow` but not `getRootNode`,\n\t// leading to errors. We need to check for `getRootNode`.\n\tif ( documentElement.getRootNode ) {\n\t\tisAttached = function( elem ) {\n\t\t\treturn jQuery.contains( elem.ownerDocument, elem ) ||\n\t\t\t\telem.getRootNode( composed ) === elem.ownerDocument;\n\t\t};\n\t}\nvar isHiddenWithinTree = function( elem, el ) {\n\n\t\t// isHiddenWithinTree might be called from jQuery#filter function;\n\t\t// in that case, element will be second argument\n\t\telem = el || elem;\n\n\t\t// Inline style trumps all\n\t\treturn elem.style.display === \"none\" ||\n\t\t\telem.style.display === \"\" &&\n\n\t\t\t// Otherwise, check computed style\n\t\t\t// Support: Firefox <=43 - 45\n\t\t\t// Disconnected elements can have computed display: none, so first confirm that elem is\n\t\t\t// in the document.\n\t\t\tisAttached( elem ) &&\n\n\t\t\tjQuery.css( elem, \"display\" ) === \"none\";\n\t};\n\n\n\nfunction adjustCSS( elem, prop, valueParts, tween ) {\n\tvar adjusted, scale,\n\t\tmaxIterations = 20,\n\t\tcurrentValue = tween ?\n\t\t\tfunction() {\n\t\t\t\treturn tween.cur();\n\t\t\t} :\n\t\t\tfunction() {\n\t\t\t\treturn jQuery.css( elem, prop, \"\" );\n\t\t\t},\n\t\tinitial = currentValue(),\n\t\tunit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" ),\n\n\t\t// Starting value computation is required for potential unit mismatches\n\t\tinitialInUnit = elem.nodeType &&\n\t\t\t( jQuery.cssNumber[ prop ] || unit !== \"px\" && +initial ) &&\n\t\t\trcssNum.exec( jQuery.css( elem, prop ) );\n\n\tif ( initialInUnit && initialInUnit[ 3 ] !== unit ) {\n\n\t\t// Support: Firefox <=54\n\t\t// Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144)\n\t\tinitial = initial / 2;\n\n\t\t// Trust units reported by jQuery.css\n\t\tunit = unit || initialInUnit[ 3 ];\n\n\t\t// Iteratively approximate from a nonzero starting point\n\t\tinitialInUnit = +initial || 1;\n\n\t\twhile ( maxIterations-- ) {\n\n\t\t\t// Evaluate and update our best guess (doubling guesses that zero out).\n\t\t\t// Finish if the scale equals or crosses 1 (making the old*new product non-positive).\n\t\t\tjQuery.style( elem, prop, initialInUnit + unit );\n\t\t\tif ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) {\n\t\t\t\tmaxIterations = 0;\n\t\t\t}\n\t\t\tinitialInUnit = initialInUnit / scale;\n\n\t\t}\n\n\t\tinitialInUnit = initialInUnit * 2;\n\t\tjQuery.style( elem, prop, initialInUnit + unit );\n\n\t\t// Make sure we update the tween properties later on\n\t\tvalueParts = valueParts || [];\n\t}\n\n\tif ( valueParts ) {\n\t\tinitialInUnit = +initialInUnit || +initial || 0;\n\n\t\t// Apply relative offset (+=/-=) if specified\n\t\tadjusted = valueParts[ 1 ] ?\n\t\t\tinitialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :\n\t\t\t+valueParts[ 2 ];\n\t\tif ( tween ) {\n\t\t\ttween.unit = unit;\n\t\t\ttween.start = initialInUnit;\n\t\t\ttween.end = adjusted;\n\t\t}\n\t}\n\treturn adjusted;\n}\n\n\nvar defaultDisplayMap = {};\n\nfunction getDefaultDisplay( elem ) {\n\tvar temp,\n\t\tdoc = elem.ownerDocument,\n\t\tnodeName = elem.nodeName,\n\t\tdisplay = defaultDisplayMap[ nodeName ];\n\n\tif ( display ) {\n\t\treturn display;\n\t}\n\n\ttemp = doc.body.appendChild( doc.createElement( nodeName ) );\n\tdisplay = jQuery.css( temp, \"display\" );\n\n\ttemp.parentNode.removeChild( temp );\n\n\tif ( display === \"none\" ) {\n\t\tdisplay = \"block\";\n\t}\n\tdefaultDisplayMap[ nodeName ] = display;\n\n\treturn display;\n}\n\nfunction showHide( elements, show ) {\n\tvar display, elem,\n\t\tvalues = [],\n\t\tindex = 0,\n\t\tlength = elements.length;\n\n\t// Determine new display value for elements that need to change\n\tfor ( ; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tdisplay = elem.style.display;\n\t\tif ( show ) {\n\n\t\t\t// Since we force visibility upon cascade-hidden elements, an immediate (and slow)\n\t\t\t// check is required in this first loop unless we have a nonempty display value (either\n\t\t\t// inline or about-to-be-restored)\n\t\t\tif ( display === \"none\" ) {\n\t\t\t\tvalues[ index ] = dataPriv.get( elem, \"display\" ) || null;\n\t\t\t\tif ( !values[ index ] ) {\n\t\t\t\t\telem.style.display = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( elem.style.display === \"\" && isHiddenWithinTree( elem ) ) {\n\t\t\t\tvalues[ index ] = getDefaultDisplay( elem );\n\t\t\t}\n\t\t} else {\n\t\t\tif ( display !== \"none\" ) {\n\t\t\t\tvalues[ index ] = \"none\";\n\n\t\t\t\t// Remember what we're overwriting\n\t\t\t\tdataPriv.set( elem, \"display\", display );\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set the display of the elements in a second loop to avoid constant reflow\n\tfor ( index = 0; index < length; index++ ) {\n\t\tif ( values[ index ] != null ) {\n\t\t\telements[ index ].style.display = values[ index ];\n\t\t}\n\t}\n\n\treturn elements;\n}\n\njQuery.fn.extend( {\n\tshow: function() {\n\t\treturn showHide( this, true );\n\t},\n\thide: function() {\n\t\treturn showHide( this );\n\t},\n\ttoggle: function( state ) {\n\t\tif ( typeof state === \"boolean\" ) {\n\t\t\treturn state ? this.show() : this.hide();\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tif ( isHiddenWithinTree( this ) ) {\n\t\t\t\tjQuery( this ).show();\n\t\t\t} else {\n\t\t\t\tjQuery( this ).hide();\n\t\t\t}\n\t\t} );\n\t}\n} );\nvar rcheckableType = ( /^(?:checkbox|radio)$/i );\n\nvar rtagName = ( /<([a-z][^\\/\\0>\\x20\\t\\r\\n\\f]*)/i );\n\nvar rscriptType = ( /^$|^module$|\\/(?:java|ecma)script/i );\n\n\n\n( function() {\n\tvar fragment = document.createDocumentFragment(),\n\t\tdiv = fragment.appendChild( document.createElement( \"div\" ) ),\n\t\tinput = document.createElement( \"input\" );\n\n\t// Support: Android 4.0 - 4.3 only\n\t// Check state lost if the name is set (#11217)\n\t// Support: Windows Web Apps (WWA)\n\t// `name` and `type` must use .setAttribute for WWA (#14901)\n\tinput.setAttribute( \"type\", \"radio\" );\n\tinput.setAttribute( \"checked\", \"checked\" );\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tdiv.appendChild( input );\n\n\t// Support: Android <=4.1 only\n\t// Older WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Support: IE <=11 only\n\t// Make sure textarea (and checkbox) defaultValue is properly cloned\n\tdiv.innerHTML = \"<textarea>x</textarea>\";\n\tsupport.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;\n\n\t// Support: IE <=9 only\n\t// IE <=9 replaces <option> tags with their contents when inserted outside of\n\t// the select element.\n\tdiv.innerHTML = \"<option></option>\";\n\tsupport.option = !!div.lastChild;\n} )();\n\n\n// We have to close these tags to support XHTML (#13200)\nvar wrapMap = {\n\n\t// XHTML parsers do not magically insert elements in the\n\t// same way that tag soup parsers do. So we cannot shorten\n\t// this by omitting <tbody> or other required elements.\n\tthead: [ 1, \"<table>\", \"</table>\" ],\n\tcol: [ 2, \"<table><colgroup>\", \"</colgroup></table>\" ],\n\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\n\t_default: [ 0, \"\", \"\" ]\n};\n\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// Support: IE <=9 only\nif ( !support.option ) {\n\twrapMap.optgroup = wrapMap.option = [ 1, \"<select multiple='multiple'>\", \"</select>\" ];\n}\n\n\nfunction getAll( context, tag ) {\n\n\t// Support: IE <=9 - 11 only\n\t// Use typeof to avoid zero-argument method invocation on host objects (#15151)\n\tvar ret;\n\n\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\tret = context.getElementsByTagName( tag || \"*\" );\n\n\t} else if ( typeof context.querySelectorAll !== \"undefined\" ) {\n\t\tret = context.querySelectorAll( tag || \"*\" );\n\n\t} else {\n\t\tret = [];\n\t}\n\n\tif ( tag === undefined || tag && nodeName( context, tag ) ) {\n\t\treturn jQuery.merge( [ context ], ret );\n\t}\n\n\treturn ret;\n}\n\n\n// Mark scripts as having already been evaluated\nfunction setGlobalEval( elems, refElements ) {\n\tvar i = 0,\n\t\tl = elems.length;\n\n\tfor ( ; i < l; i++ ) {\n\t\tdataPriv.set(\n\t\t\telems[ i ],\n\t\t\t\"globalEval\",\n\t\t\t!refElements || dataPriv.get( refElements[ i ], \"globalEval\" )\n\t\t);\n\t}\n}\n\n\nvar rhtml = /<|&#?\\w+;/;\n\nfunction buildFragment( elems, context, scripts, selection, ignored ) {\n\tvar elem, tmp, tag, wrap, attached, j,\n\t\tfragment = context.createDocumentFragment(),\n\t\tnodes = [],\n\t\ti = 0,\n\t\tl = elems.length;\n\n\tfor ( ; i < l; i++ ) {\n\t\telem = elems[ i ];\n\n\t\tif ( elem || elem === 0 ) {\n\n\t\t\t// Add nodes directly\n\t\t\tif ( toType( elem ) === \"object\" ) {\n\n\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\tjQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );\n\n\t\t\t// Convert non-html into a text node\n\t\t\t} else if ( !rhtml.test( elem ) ) {\n\t\t\t\tnodes.push( context.createTextNode( elem ) );\n\n\t\t\t// Convert html into DOM nodes\n\t\t\t} else {\n\t\t\t\ttmp = tmp || fragment.appendChild( context.createElement( \"div\" ) );\n\n\t\t\t\t// Deserialize a standard representation\n\t\t\t\ttag = ( rtagName.exec( elem ) || [ \"\", \"\" ] )[ 1 ].toLowerCase();\n\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default;\n\t\t\t\ttmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];\n\n\t\t\t\t// Descend through wrappers to the right content\n\t\t\t\tj = wrap[ 0 ];\n\t\t\t\twhile ( j-- ) {\n\t\t\t\t\ttmp = tmp.lastChild;\n\t\t\t\t}\n\n\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\tjQuery.merge( nodes, tmp.childNodes );\n\n\t\t\t\t// Remember the top-level container\n\t\t\t\ttmp = fragment.firstChild;\n\n\t\t\t\t// Ensure the created nodes are orphaned (#12392)\n\t\t\t\ttmp.textContent = \"\";\n\t\t\t}\n\t\t}\n\t}\n\n\t// Remove wrapper from fragment\n\tfragment.textContent = \"\";\n\n\ti = 0;\n\twhile ( ( elem = nodes[ i++ ] ) ) {\n\n\t\t// Skip elements already in the context collection (trac-4087)\n\t\tif ( selection && jQuery.inArray( elem, selection ) > -1 ) {\n\t\t\tif ( ignored ) {\n\t\t\t\tignored.push( elem );\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tattached = isAttached( elem );\n\n\t\t// Append to fragment\n\t\ttmp = getAll( fragment.appendChild( elem ), \"script\" );\n\n\t\t// Preserve script evaluation history\n\t\tif ( attached ) {\n\t\t\tsetGlobalEval( tmp );\n\t\t}\n\n\t\t// Capture executables\n\t\tif ( scripts ) {\n\t\t\tj = 0;\n\t\t\twhile ( ( elem = tmp[ j++ ] ) ) {\n\t\t\t\tif ( rscriptType.test( elem.type || \"\" ) ) {\n\t\t\t\t\tscripts.push( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn fragment;\n}\n\n\nvar\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,\n\trtypenamespace = /^([^.]*)(?:\\.(.+)|)/;\n\nfunction returnTrue() {\n\treturn true;\n}\n\nfunction returnFalse() {\n\treturn false;\n}\n\n// Support: IE <=9 - 11+\n// focus() and blur() are asynchronous, except when they are no-op.\n// So expect focus to be synchronous when the element is already active,\n// and blur to be synchronous when the element is not already active.\n// (focus and blur are always synchronous in other supported browsers,\n// this just defines when we can count on it).\nfunction expectSync( elem, type ) {\n\treturn ( elem === safeActiveElement() ) === ( type === \"focus\" );\n}\n\n// Support: IE <=9 only\n// Accessing document.activeElement can throw unexpectedly\n// https://bugs.jquery.com/ticket/13393\nfunction safeActiveElement() {\n\ttry {\n\t\treturn document.activeElement;\n\t} catch ( err ) { }\n}\n\nfunction on( elem, types, selector, data, fn, one ) {\n\tvar origFn, type;\n\n\t// Types can be a map of types/handlers\n\tif ( typeof types === \"object\" ) {\n\n\t\t// ( types-Object, selector, data )\n\t\tif ( typeof selector !== \"string\" ) {\n\n\t\t\t// ( types-Object, data )\n\t\t\tdata = data || selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tfor ( type in types ) {\n\t\t\ton( elem, type, selector, data, types[ type ], one );\n\t\t}\n\t\treturn elem;\n\t}\n\n\tif ( data == null && fn == null ) {\n\n\t\t// ( types, fn )\n\t\tfn = selector;\n\t\tdata = selector = undefined;\n\t} else if ( fn == null ) {\n\t\tif ( typeof selector === \"string\" ) {\n\n\t\t\t// ( types, selector, fn )\n\t\t\tfn = data;\n\t\t\tdata = undefined;\n\t\t} else {\n\n\t\t\t// ( types, data, fn )\n\t\t\tfn = data;\n\t\t\tdata = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t}\n\tif ( fn === false ) {\n\t\tfn = returnFalse;\n\t} else if ( !fn ) {\n\t\treturn elem;\n\t}\n\n\tif ( one === 1 ) {\n\t\torigFn = fn;\n\t\tfn = function( event ) {\n\n\t\t\t// Can use an empty set, since event contains the info\n\t\t\tjQuery().off( event );\n\t\t\treturn origFn.apply( this, arguments );\n\t\t};\n\n\t\t// Use same guid so caller can remove using origFn\n\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t}\n\treturn elem.each( function() {\n\t\tjQuery.event.add( this, types, fn, data, selector );\n\t} );\n}\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tglobal: {},\n\n\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar handleObjIn, eventHandle, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = dataPriv.get( elem );\n\n\t\t// Only attach events to objects that accept data\n\t\tif ( !acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Ensure that invalid selectors throw exceptions at attach time\n\t\t// Evaluate against documentElement in case elem is a non-element node (e.g., document)\n\t\tif ( selector ) {\n\t\t\tjQuery.find.matchesSelector( documentElement, selector );\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tif ( !( events = elemData.events ) ) {\n\t\t\tevents = elemData.events = Object.create( null );\n\t\t}\n\t\tif ( !( eventHandle = elemData.handle ) ) {\n\t\t\teventHandle = elemData.handle = function( e ) {\n\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && jQuery.event.triggered !== e.type ?\n\t\t\t\t\tjQuery.event.dispatch.apply( elem, arguments ) : undefined;\n\t\t\t};\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\ttypes = ( types || \"\" ).match( rnothtmlwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[ t ] ) || [];\n\t\t\ttype = origType = tmp[ 1 ];\n\t\t\tnamespaces = ( tmp[ 2 ] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// There *must* be a type, no attaching namespace-only handlers\n\t\t\tif ( !type ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend( {\n\t\t\t\ttype: type,\n\t\t\t\torigType: origType,\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tneedsContext: selector && jQuery.expr.match.needsContext.test( selector ),\n\t\t\t\tnamespace: namespaces.join( \".\" )\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\tif ( !( handlers = events[ type ] ) ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener if the special events handler returns false\n\t\t\t\tif ( !special.setup ||\n\t\t\t\t\tspecial.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\tvar j, origCount, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = dataPriv.hasData( elem ) && dataPriv.get( elem );\n\n\t\tif ( !elemData || !( events = elemData.events ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = ( types || \"\" ).match( rnothtmlwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[ t ] ) || [];\n\t\t\ttype = origType = tmp[ 1 ];\n\t\t\tnamespaces = ( tmp[ 2 ] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\t\t\thandlers = events[ type ] || [];\n\t\t\ttmp = tmp[ 2 ] &&\n\t\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join( \"\\\\.(?:.*\\\\.|)\" ) + \"(\\\\.|$)\" );\n\n\t\t\t// Remove matching events\n\t\t\torigCount = j = handlers.length;\n\t\t\twhile ( j-- ) {\n\t\t\t\thandleObj = handlers[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t( !tmp || tmp.test( handleObj.namespace ) ) &&\n\t\t\t\t\t( !selector || selector === handleObj.selector ||\n\t\t\t\t\t\tselector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\thandlers.splice( j, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\thandlers.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( origCount && !handlers.length ) {\n\t\t\t\tif ( !special.teardown ||\n\t\t\t\t\tspecial.teardown.call( elem, namespaces, elemData.handle ) === false ) {\n\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove data and the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\tdataPriv.remove( elem, \"handle events\" );\n\t\t}\n\t},\n\n\tdispatch: function( nativeEvent ) {\n\n\t\tvar i, j, ret, matched, handleObj, handlerQueue,\n\t\t\targs = new Array( arguments.length ),\n\n\t\t\t// Make a writable jQuery.Event from the native event object\n\t\t\tevent = jQuery.event.fix( nativeEvent ),\n\n\t\t\thandlers = (\n\t\t\t\t\tdataPriv.get( this, \"events\" ) || Object.create( null )\n\t\t\t\t)[ event.type ] || [],\n\t\t\tspecial = jQuery.event.special[ event.type ] || {};\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[ 0 ] = event;\n\n\t\tfor ( i = 1; i < arguments.length; i++ ) {\n\t\t\targs[ i ] = arguments[ i ];\n\t\t}\n\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers\n\t\thandlerQueue = jQuery.event.handlers.call( this, event, handlers );\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\ti = 0;\n\t\twhile ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tj = 0;\n\t\t\twhile ( ( handleObj = matched.handlers[ j++ ] ) &&\n\t\t\t\t!event.isImmediatePropagationStopped() ) {\n\n\t\t\t\t// If the event is namespaced, then each handler is only invoked if it is\n\t\t\t\t// specially universal or its namespaces are a superset of the event's.\n\t\t\t\tif ( !event.rnamespace || handleObj.namespace === false ||\n\t\t\t\t\tevent.rnamespace.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.handleObj = handleObj;\n\t\t\t\t\tevent.data = handleObj.data;\n\n\t\t\t\t\tret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||\n\t\t\t\t\t\thandleObj.handler ).apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tif ( ( event.result = ret ) === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\thandlers: function( event, handlers ) {\n\t\tvar i, handleObj, sel, matchedHandlers, matchedSelectors,\n\t\t\thandlerQueue = [],\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\tcur = event.target;\n\n\t\t// Find delegate handlers\n\t\tif ( delegateCount &&\n\n\t\t\t// Support: IE <=9\n\t\t\t// Black-hole SVG <use> instance trees (trac-13180)\n\t\t\tcur.nodeType &&\n\n\t\t\t// Support: Firefox <=42\n\t\t\t// Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)\n\t\t\t// https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click\n\t\t\t// Support: IE 11 only\n\t\t\t// ...but not arrow key \"clicks\" of radio inputs, which can have `button` -1 (gh-2343)\n\t\t\t!( event.type === \"click\" && event.button >= 1 ) ) {\n\n\t\t\tfor ( ; cur !== this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't check non-elements (#13208)\n\t\t\t\t// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)\n\t\t\t\tif ( cur.nodeType === 1 && !( event.type === \"click\" && cur.disabled === true ) ) {\n\t\t\t\t\tmatchedHandlers = [];\n\t\t\t\t\tmatchedSelectors = {};\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\n\t\t\t\t\t\t// Don't conflict with Object.prototype properties (#13203)\n\t\t\t\t\t\tsel = handleObj.selector + \" \";\n\n\t\t\t\t\t\tif ( matchedSelectors[ sel ] === undefined ) {\n\t\t\t\t\t\t\tmatchedSelectors[ sel ] = handleObj.needsContext ?\n\t\t\t\t\t\t\t\tjQuery( sel, this ).index( cur ) > -1 :\n\t\t\t\t\t\t\t\tjQuery.find( sel, this, null, [ cur ] ).length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( matchedSelectors[ sel ] ) {\n\t\t\t\t\t\t\tmatchedHandlers.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matchedHandlers.length ) {\n\t\t\t\t\t\thandlerQueue.push( { elem: cur, handlers: matchedHandlers } );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tcur = this;\n\t\tif ( delegateCount < handlers.length ) {\n\t\t\thandlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );\n\t\t}\n\n\t\treturn handlerQueue;\n\t},\n\n\taddProp: function( name, hook ) {\n\t\tObject.defineProperty( jQuery.Event.prototype, name, {\n\t\t\tenumerable: true,\n\t\t\tconfigurable: true,\n\n\t\t\tget: isFunction( hook ) ?\n\t\t\t\tfunction() {\n\t\t\t\t\tif ( this.originalEvent ) {\n\t\t\t\t\t\t\treturn hook( this.originalEvent );\n\t\t\t\t\t}\n\t\t\t\t} :\n\t\t\t\tfunction() {\n\t\t\t\t\tif ( this.originalEvent ) {\n\t\t\t\t\t\t\treturn this.originalEvent[ name ];\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\tset: function( value ) {\n\t\t\t\tObject.defineProperty( this, name, {\n\t\t\t\t\tenumerable: true,\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\twritable: true,\n\t\t\t\t\tvalue: value\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\t},\n\n\tfix: function( originalEvent ) {\n\t\treturn originalEvent[ jQuery.expando ] ?\n\t\t\toriginalEvent :\n\t\t\tnew jQuery.Event( originalEvent );\n\t},\n\n\tspecial: {\n\t\tload: {\n\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\t\tclick: {\n\n\t\t\t// Utilize native event to ensure correct state for checkable inputs\n\t\t\tsetup: function( data ) {\n\n\t\t\t\t// For mutual compressibility with _default, replace `this` access with a local var.\n\t\t\t\t// `|| data` is dead code meant only to preserve the variable through minification.\n\t\t\t\tvar el = this || data;\n\n\t\t\t\t// Claim the first handler\n\t\t\t\tif ( rcheckableType.test( el.type ) &&\n\t\t\t\t\tel.click && nodeName( el, \"input\" ) ) {\n\n\t\t\t\t\t// dataPriv.set( el, \"click\", ... )\n\t\t\t\t\tleverageNative( el, \"click\", returnTrue );\n\t\t\t\t}\n\n\t\t\t\t// Return false to allow normal processing in the caller\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\ttrigger: function( data ) {\n\n\t\t\t\t// For mutual compressibility with _default, replace `this` access with a local var.\n\t\t\t\t// `|| data` is dead code meant only to preserve the variable through minification.\n\t\t\t\tvar el = this || data;\n\n\t\t\t\t// Force setup before triggering a click\n\t\t\t\tif ( rcheckableType.test( el.type ) &&\n\t\t\t\t\tel.click && nodeName( el, \"input\" ) ) {\n\n\t\t\t\t\tleverageNative( el, \"click\" );\n\t\t\t\t}\n\n\t\t\t\t// Return non-false to allow normal event-path propagation\n\t\t\t\treturn true;\n\t\t\t},\n\n\t\t\t// For cross-browser consistency, suppress native .click() on links\n\t\t\t// Also prevent it if we're currently inside a leveraged native-event stack\n\t\t\t_default: function( event ) {\n\t\t\t\tvar target = event.target;\n\t\t\t\treturn rcheckableType.test( target.type ) &&\n\t\t\t\t\ttarget.click && nodeName( target, \"input\" ) &&\n\t\t\t\t\tdataPriv.get( target, \"click\" ) ||\n\t\t\t\t\tnodeName( target, \"a\" );\n\t\t\t}\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tpostDispatch: function( event ) {\n\n\t\t\t\t// Support: Firefox 20+\n\t\t\t\t// Firefox doesn't alert if the returnValue field is not set.\n\t\t\t\tif ( event.result !== undefined && event.originalEvent ) {\n\t\t\t\t\tevent.originalEvent.returnValue = event.result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n};\n\n// Ensure the presence of an event listener that handles manually-triggered\n// synthetic events by interrupting progress until reinvoked in response to\n// *native* events that it fires directly, ensuring that state changes have\n// already occurred before other listeners are invoked.\nfunction leverageNative( el, type, expectSync ) {\n\n\t// Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add\n\tif ( !expectSync ) {\n\t\tif ( dataPriv.get( el, type ) === undefined ) {\n\t\t\tjQuery.event.add( el, type, returnTrue );\n\t\t}\n\t\treturn;\n\t}\n\n\t// Register the controller as a special universal handler for all event namespaces\n\tdataPriv.set( el, type, false );\n\tjQuery.event.add( el, type, {\n\t\tnamespace: false,\n\t\thandler: function( event ) {\n\t\t\tvar notAsync, result,\n\t\t\t\tsaved = dataPriv.get( this, type );\n\n\t\t\tif ( ( event.isTrigger & 1 ) && this[ type ] ) {\n\n\t\t\t\t// Interrupt processing of the outer synthetic .trigger()ed event\n\t\t\t\t// Saved data should be false in such cases, but might be a leftover capture object\n\t\t\t\t// from an async native handler (gh-4350)\n\t\t\t\tif ( !saved.length ) {\n\n\t\t\t\t\t// Store arguments for use when handling the inner native event\n\t\t\t\t\t// There will always be at least one argument (an event object), so this array\n\t\t\t\t\t// will not be confused with a leftover capture object.\n\t\t\t\t\tsaved = slice.call( arguments );\n\t\t\t\t\tdataPriv.set( this, type, saved );\n\n\t\t\t\t\t// Trigger the native event and capture its result\n\t\t\t\t\t// Support: IE <=9 - 11+\n\t\t\t\t\t// focus() and blur() are asynchronous\n\t\t\t\t\tnotAsync = expectSync( this, type );\n\t\t\t\t\tthis[ type ]();\n\t\t\t\t\tresult = dataPriv.get( this, type );\n\t\t\t\t\tif ( saved !== result || notAsync ) {\n\t\t\t\t\t\tdataPriv.set( this, type, false );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult = {};\n\t\t\t\t\t}\n\t\t\t\t\tif ( saved !== result ) {\n\n\t\t\t\t\t\t// Cancel the outer synthetic event\n\t\t\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\treturn result.value;\n\t\t\t\t\t}\n\n\t\t\t\t// If this is an inner synthetic event for an event with a bubbling surrogate\n\t\t\t\t// (focus or blur), assume that the surrogate already propagated from triggering the\n\t\t\t\t// native event and prevent that from happening again here.\n\t\t\t\t// This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the\n\t\t\t\t// bubbling surrogate propagates *after* the non-bubbling base), but that seems\n\t\t\t\t// less bad than duplication.\n\t\t\t\t} else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) {\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t}\n\n\t\t\t// If this is a native event triggered above, everything is now in order\n\t\t\t// Fire an inner synthetic event with the original arguments\n\t\t\t} else if ( saved.length ) {\n\n\t\t\t\t// ...and capture the result\n\t\t\t\tdataPriv.set( this, type, {\n\t\t\t\t\tvalue: jQuery.event.trigger(\n\n\t\t\t\t\t\t// Support: IE <=9 - 11+\n\t\t\t\t\t\t// Extend with the prototype to reset the above stopImmediatePropagation()\n\t\t\t\t\t\tjQuery.extend( saved[ 0 ], jQuery.Event.prototype ),\n\t\t\t\t\t\tsaved.slice( 1 ),\n\t\t\t\t\t\tthis\n\t\t\t\t\t)\n\t\t\t\t} );\n\n\t\t\t\t// Abort handling of the native event\n\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t}\n\t\t}\n\t} );\n}\n\njQuery.removeEvent = function( elem, type, handle ) {\n\n\t// This \"if\" is needed for plain objects\n\tif ( elem.removeEventListener ) {\n\t\telem.removeEventListener( type, handle );\n\t}\n};\n\njQuery.Event = function( src, props ) {\n\n\t// Allow instantiation without the 'new' keyword\n\tif ( !( this instanceof jQuery.Event ) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = src.defaultPrevented ||\n\t\t\t\tsrc.defaultPrevented === undefined &&\n\n\t\t\t\t// Support: Android <=2.3 only\n\t\t\t\tsrc.returnValue === false ?\n\t\t\treturnTrue :\n\t\t\treturnFalse;\n\n\t\t// Create target properties\n\t\t// Support: Safari <=6 - 7 only\n\t\t// Target should not be a text node (#504, #13143)\n\t\tthis.target = ( src.target && src.target.nodeType === 3 ) ?\n\t\t\tsrc.target.parentNode :\n\t\t\tsrc.target;\n\n\t\tthis.currentTarget = src.currentTarget;\n\t\tthis.relatedTarget = src.relatedTarget;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || Date.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tconstructor: jQuery.Event,\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse,\n\tisSimulated: false,\n\n\tpreventDefault: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tif ( e && !this.isSimulated ) {\n\t\t\te.preventDefault();\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tif ( e && !this.isSimulated ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t},\n\tstopImmediatePropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\n\t\tif ( e && !this.isSimulated ) {\n\t\t\te.stopImmediatePropagation();\n\t\t}\n\n\t\tthis.stopPropagation();\n\t}\n};\n\n// Includes all common event props including KeyEvent and MouseEvent specific props\njQuery.each( {\n\taltKey: true,\n\tbubbles: true,\n\tcancelable: true,\n\tchangedTouches: true,\n\tctrlKey: true,\n\tdetail: true,\n\teventPhase: true,\n\tmetaKey: true,\n\tpageX: true,\n\tpageY: true,\n\tshiftKey: true,\n\tview: true,\n\t\"char\": true,\n\tcode: true,\n\tcharCode: true,\n\tkey: true,\n\tkeyCode: true,\n\tbutton: true,\n\tbuttons: true,\n\tclientX: true,\n\tclientY: true,\n\toffsetX: true,\n\toffsetY: true,\n\tpointerId: true,\n\tpointerType: true,\n\tscreenX: true,\n\tscreenY: true,\n\ttargetTouches: true,\n\ttoElement: true,\n\ttouches: true,\n\n\twhich: function( event ) {\n\t\tvar button = event.button;\n\n\t\t// Add which for key events\n\t\tif ( event.which == null && rkeyEvent.test( event.type ) ) {\n\t\t\treturn event.charCode != null ? event.charCode : event.keyCode;\n\t\t}\n\n\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\tif ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {\n\t\t\tif ( button & 1 ) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\tif ( button & 2 ) {\n\t\t\t\treturn 3;\n\t\t\t}\n\n\t\t\tif ( button & 4 ) {\n\t\t\t\treturn 2;\n\t\t\t}\n\n\t\t\treturn 0;\n\t\t}\n\n\t\treturn event.which;\n\t}\n}, jQuery.event.addProp );\n\njQuery.each( { focus: \"focusin\", blur: \"focusout\" }, function( type, delegateType ) {\n\tjQuery.event.special[ type ] = {\n\n\t\t// Utilize native event if possible so blur/focus sequence is correct\n\t\tsetup: function() {\n\n\t\t\t// Claim the first handler\n\t\t\t// dataPriv.set( this, \"focus\", ... )\n\t\t\t// dataPriv.set( this, \"blur\", ... )\n\t\t\tleverageNative( this, type, expectSync );\n\n\t\t\t// Return false to allow normal processing in the caller\n\t\t\treturn false;\n\t\t},\n\t\ttrigger: function() {\n\n\t\t\t// Force setup before trigger\n\t\t\tleverageNative( this, type );\n\n\t\t\t// Return non-false to allow normal event-path propagation\n\t\t\treturn true;\n\t\t},\n\n\t\tdelegateType: delegateType\n\t};\n} );\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\n// so that event delegation works in jQuery.\n// Do the same for pointerenter/pointerleave and pointerover/pointerout\n//\n// Support: Safari 7 only\n// Safari sends mouseenter too often; see:\n// https://bugs.chromium.org/p/chromium/issues/detail?id=470258\n// for the description of the bug (it existed in older Chrome versions as well).\njQuery.each( {\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\",\n\tpointerenter: \"pointerover\",\n\tpointerleave: \"pointerout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar ret,\n\t\t\t\ttarget = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj;\n\n\t\t\t// For mouseenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n} );\n\njQuery.fn.extend( {\n\n\ton: function( types, selector, data, fn ) {\n\t\treturn on( this, types, selector, data, fn );\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn on( this, types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tvar handleObj, type;\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\thandleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ?\n\t\t\t\t\thandleObj.origType + \".\" + handleObj.namespace :\n\t\t\t\t\thandleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t} );\n\t}\n} );\n\n\nvar\n\n\t// Support: IE <=10 - 11, Edge 12 - 13 only\n\t// In IE/Edge using regex groups here causes severe slowdowns.\n\t// See https://connect.microsoft.com/IE/feedback/details/1736512/\n\trnoInnerhtml = /<script|<style|<link/i,\n\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g;\n\n// Prefer a tbody over its parent table for containing new rows\nfunction manipulationTarget( elem, content ) {\n\tif ( nodeName( elem, \"table\" ) &&\n\t\tnodeName( content.nodeType !== 11 ? content : content.firstChild, \"tr\" ) ) {\n\n\t\treturn jQuery( elem ).children( \"tbody\" )[ 0 ] || elem;\n\t}\n\n\treturn elem;\n}\n\n// Replace/restore the type attribute of script elements for safe DOM manipulation\nfunction disableScript( elem ) {\n\telem.type = ( elem.getAttribute( \"type\" ) !== null ) + \"/\" + elem.type;\n\treturn elem;\n}\nfunction restoreScript( elem ) {\n\tif ( ( elem.type || \"\" ).slice( 0, 5 ) === \"true/\" ) {\n\t\telem.type = elem.type.slice( 5 );\n\t} else {\n\t\telem.removeAttribute( \"type\" );\n\t}\n\n\treturn elem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\tvar i, l, type, pdataOld, udataOld, udataCur, events;\n\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// 1. Copy private data: events, handlers, etc.\n\tif ( dataPriv.hasData( src ) ) {\n\t\tpdataOld = dataPriv.get( src );\n\t\tevents = pdataOld.events;\n\n\t\tif ( events ) {\n\t\t\tdataPriv.remove( dest, \"handle events\" );\n\n\t\t\tfor ( type in events ) {\n\t\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// 2. Copy user data\n\tif ( dataUser.hasData( src ) ) {\n\t\tudataOld = dataUser.access( src );\n\t\tudataCur = jQuery.extend( {}, udataOld );\n\n\t\tdataUser.set( dest, udataCur );\n\t}\n}\n\n// Fix IE bugs, see support tests\nfunction fixInput( src, dest ) {\n\tvar nodeName = dest.nodeName.toLowerCase();\n\n\t// Fails to persist the checked state of a cloned checkbox or radio button.\n\tif ( nodeName === \"input\" && rcheckableType.test( src.type ) ) {\n\t\tdest.checked = src.checked;\n\n\t// Fails to return the selected option to the default selected state when cloning options\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n}\n\nfunction domManip( collection, args, callback, ignored ) {\n\n\t// Flatten any nested arrays\n\targs = flat( args );\n\n\tvar fragment, first, scripts, hasScripts, node, doc,\n\t\ti = 0,\n\t\tl = collection.length,\n\t\tiNoClone = l - 1,\n\t\tvalue = args[ 0 ],\n\t\tvalueIsFunction = isFunction( value );\n\n\t// We can't cloneNode fragments that contain checked, in WebKit\n\tif ( valueIsFunction ||\n\t\t\t( l > 1 && typeof value === \"string\" &&\n\t\t\t\t!support.checkClone && rchecked.test( value ) ) ) {\n\t\treturn collection.each( function( index ) {\n\t\t\tvar self = collection.eq( index );\n\t\t\tif ( valueIsFunction ) {\n\t\t\t\targs[ 0 ] = value.call( this, index, self.html() );\n\t\t\t}\n\t\t\tdomManip( self, args, callback, ignored );\n\t\t} );\n\t}\n\n\tif ( l ) {\n\t\tfragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );\n\t\tfirst = fragment.firstChild;\n\n\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\tfragment = first;\n\t\t}\n\n\t\t// Require either new content or an interest in ignored elements to invoke the callback\n\t\tif ( first || ignored ) {\n\t\t\tscripts = jQuery.map( getAll( fragment, \"script\" ), disableScript );\n\t\t\thasScripts = scripts.length;\n\n\t\t\t// Use the original fragment for the last item\n\t\t\t// instead of the first because it can end up\n\t\t\t// being emptied incorrectly in certain situations (#8070).\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tnode = fragment;\n\n\t\t\t\tif ( i !== iNoClone ) {\n\t\t\t\t\tnode = jQuery.clone( node, true, true );\n\n\t\t\t\t\t// Keep references to cloned scripts for later restoration\n\t\t\t\t\tif ( hasScripts ) {\n\n\t\t\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\t\t\tjQuery.merge( scripts, getAll( node, \"script\" ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcallback.call( collection[ i ], node, i );\n\t\t\t}\n\n\t\t\tif ( hasScripts ) {\n\t\t\t\tdoc = scripts[ scripts.length - 1 ].ownerDocument;\n\n\t\t\t\t// Reenable scripts\n\t\t\t\tjQuery.map( scripts, restoreScript );\n\n\t\t\t\t// Evaluate executable scripts on first document insertion\n\t\t\t\tfor ( i = 0; i < hasScripts; i++ ) {\n\t\t\t\t\tnode = scripts[ i ];\n\t\t\t\t\tif ( rscriptType.test( node.type || \"\" ) &&\n\t\t\t\t\t\t!dataPriv.access( node, \"globalEval\" ) &&\n\t\t\t\t\t\tjQuery.contains( doc, node ) ) {\n\n\t\t\t\t\t\tif ( node.src && ( node.type || \"\" ).toLowerCase()  !== \"module\" ) {\n\n\t\t\t\t\t\t\t// Optional AJAX dependency, but won't run scripts if not present\n\t\t\t\t\t\t\tif ( jQuery._evalUrl && !node.noModule ) {\n\t\t\t\t\t\t\t\tjQuery._evalUrl( node.src, {\n\t\t\t\t\t\t\t\t\tnonce: node.nonce || node.getAttribute( \"nonce\" )\n\t\t\t\t\t\t\t\t}, doc );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tDOMEval( node.textContent.replace( rcleanScript, \"\" ), node, doc );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn collection;\n}\n\nfunction remove( elem, selector, keepData ) {\n\tvar node,\n\t\tnodes = selector ? jQuery.filter( selector, elem ) : elem,\n\t\ti = 0;\n\n\tfor ( ; ( node = nodes[ i ] ) != null; i++ ) {\n\t\tif ( !keepData && node.nodeType === 1 ) {\n\t\t\tjQuery.cleanData( getAll( node ) );\n\t\t}\n\n\t\tif ( node.parentNode ) {\n\t\t\tif ( keepData && isAttached( node ) ) {\n\t\t\t\tsetGlobalEval( getAll( node, \"script\" ) );\n\t\t\t}\n\t\t\tnode.parentNode.removeChild( node );\n\t\t}\n\t}\n\n\treturn elem;\n}\n\njQuery.extend( {\n\thtmlPrefilter: function( html ) {\n\t\treturn html;\n\t},\n\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar i, l, srcElements, destElements,\n\t\t\tclone = elem.cloneNode( true ),\n\t\t\tinPage = isAttached( elem );\n\n\t\t// Fix IE cloning issues\n\t\tif ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&\n\t\t\t\t!jQuery.isXMLDoc( elem ) ) {\n\n\t\t\t// We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2\n\t\t\tdestElements = getAll( clone );\n\t\t\tsrcElements = getAll( elem );\n\n\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\tfixInput( srcElements[ i ], destElements[ i ] );\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = srcElements || getAll( elem );\n\t\t\t\tdestElements = destElements || getAll( clone );\n\n\t\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[ i ], destElements[ i ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcloneCopyEvent( elem, clone );\n\t\t\t}\n\t\t}\n\n\t\t// Preserve script evaluation history\n\t\tdestElements = getAll( clone, \"script\" );\n\t\tif ( destElements.length > 0 ) {\n\t\t\tsetGlobalEval( destElements, !inPage && getAll( elem, \"script\" ) );\n\t\t}\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, elem, type,\n\t\t\tspecial = jQuery.event.special,\n\t\t\ti = 0;\n\n\t\tfor ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {\n\t\t\tif ( acceptData( elem ) ) {\n\t\t\t\tif ( ( data = elem[ dataPriv.expando ] ) ) {\n\t\t\t\t\tif ( data.events ) {\n\t\t\t\t\t\tfor ( type in data.events ) {\n\t\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Support: Chrome <=35 - 45+\n\t\t\t\t\t// Assign undefined instead of using delete, see Data#remove\n\t\t\t\t\telem[ dataPriv.expando ] = undefined;\n\t\t\t\t}\n\t\t\t\tif ( elem[ dataUser.expando ] ) {\n\n\t\t\t\t\t// Support: Chrome <=35 - 45+\n\t\t\t\t\t// Assign undefined instead of using delete, see Data#remove\n\t\t\t\t\telem[ dataUser.expando ] = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n} );\n\njQuery.fn.extend( {\n\tdetach: function( selector ) {\n\t\treturn remove( this, selector, true );\n\t},\n\n\tremove: function( selector ) {\n\t\treturn remove( this, selector );\n\t},\n\n\ttext: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().each( function() {\n\t\t\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\t\t\tthis.textContent = value;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t}, null, value, arguments.length );\n\t},\n\n\tappend: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.appendChild( elem );\n\t\t\t}\n\t\t} );\n\t},\n\n\tprepend: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.insertBefore( elem, target.firstChild );\n\t\t\t}\n\t\t} );\n\t},\n\n\tbefore: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t}\n\t\t} );\n\t},\n\n\tafter: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t}\n\t\t} );\n\t},\n\n\tempty: function() {\n\t\tvar elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; ( elem = this[ i ] ) != null; i++ ) {\n\t\t\tif ( elem.nodeType === 1 ) {\n\n\t\t\t\t// Prevent memory leaks\n\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\n\t\t\t\t// Remove any remaining nodes\n\t\t\t\telem.textContent = \"\";\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function() {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t} );\n\t},\n\n\thtml: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\tvar elem = this[ 0 ] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined && elem.nodeType === 1 ) {\n\t\t\t\treturn elem.innerHTML;\n\t\t\t}\n\n\t\t\t// See if we can take a shortcut and just use innerHTML\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [ \"\", \"\" ] )[ 1 ].toLowerCase() ] ) {\n\n\t\t\t\tvalue = jQuery.htmlPrefilter( value );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\t\telem = this[ i ] || {};\n\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch ( e ) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function() {\n\t\tvar ignored = [];\n\n\t\t// Make the changes, replacing each non-ignored context element with the new content\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tvar parent = this.parentNode;\n\n\t\t\tif ( jQuery.inArray( this, ignored ) < 0 ) {\n\t\t\t\tjQuery.cleanData( getAll( this ) );\n\t\t\t\tif ( parent ) {\n\t\t\t\t\tparent.replaceChild( elem, this );\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Force callback invocation\n\t\t}, ignored );\n\t}\n} );\n\njQuery.each( {\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar elems,\n\t\t\tret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tlast = insert.length - 1,\n\t\t\ti = 0;\n\n\t\tfor ( ; i <= last; i++ ) {\n\t\t\telems = i === last ? this : this.clone( true );\n\t\t\tjQuery( insert[ i ] )[ original ]( elems );\n\n\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t// .get() because push.apply(_, arraylike) throws on ancient WebKit\n\t\t\tpush.apply( ret, elems.get() );\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n} );\nvar rnumnonpx = new RegExp( \"^(\" + pnum + \")(?!px)[a-z%]+$\", \"i\" );\n\nvar getStyles = function( elem ) {\n\n\t\t// Support: IE <=11 only, Firefox <=30 (#15098, #14150)\n\t\t// IE throws on elements created in popups\n\t\t// FF meanwhile throws on frame elements through \"defaultView.getComputedStyle\"\n\t\tvar view = elem.ownerDocument.defaultView;\n\n\t\tif ( !view || !view.opener ) {\n\t\t\tview = window;\n\t\t}\n\n\t\treturn view.getComputedStyle( elem );\n\t};\n\nvar swap = function( elem, options, callback ) {\n\tvar ret, name,\n\t\told = {};\n\n\t// Remember the old values, and insert the new ones\n\tfor ( name in options ) {\n\t\told[ name ] = elem.style[ name ];\n\t\telem.style[ name ] = options[ name ];\n\t}\n\n\tret = callback.call( elem );\n\n\t// Revert the old values\n\tfor ( name in options ) {\n\t\telem.style[ name ] = old[ name ];\n\t}\n\n\treturn ret;\n};\n\n\nvar rboxStyle = new RegExp( cssExpand.join( \"|\" ), \"i\" );\n\n\n\n( function() {\n\n\t// Executing both pixelPosition & boxSizingReliable tests require only one layout\n\t// so they're executed at the same time to save the second computation.\n\tfunction computeStyleTests() {\n\n\t\t// This is a singleton, we need to execute it only once\n\t\tif ( !div ) {\n\t\t\treturn;\n\t\t}\n\n\t\tcontainer.style.cssText = \"position:absolute;left:-11111px;width:60px;\" +\n\t\t\t\"margin-top:1px;padding:0;border:0\";\n\t\tdiv.style.cssText =\n\t\t\t\"position:relative;display:block;box-sizing:border-box;overflow:scroll;\" +\n\t\t\t\"margin:auto;border:1px;padding:1px;\" +\n\t\t\t\"width:60%;top:1%\";\n\t\tdocumentElement.appendChild( container ).appendChild( div );\n\n\t\tvar divStyle = window.getComputedStyle( div );\n\t\tpixelPositionVal = divStyle.top !== \"1%\";\n\n\t\t// Support: Android 4.0 - 4.3 only, Firefox <=3 - 44\n\t\treliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12;\n\n\t\t// Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3\n\t\t// Some styles come back with percentage values, even though they shouldn't\n\t\tdiv.style.right = \"60%\";\n\t\tpixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36;\n\n\t\t// Support: IE 9 - 11 only\n\t\t// Detect misreporting of content dimensions for box-sizing:border-box elements\n\t\tboxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36;\n\n\t\t// Support: IE 9 only\n\t\t// Detect overflow:scroll screwiness (gh-3699)\n\t\t// Support: Chrome <=64\n\t\t// Don't get tricked when zoom affects offsetWidth (gh-4029)\n\t\tdiv.style.position = \"absolute\";\n\t\tscrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12;\n\n\t\tdocumentElement.removeChild( container );\n\n\t\t// Nullify the div so it wouldn't be stored in the memory and\n\t\t// it will also be a sign that checks already performed\n\t\tdiv = null;\n\t}\n\n\tfunction roundPixelMeasures( measure ) {\n\t\treturn Math.round( parseFloat( measure ) );\n\t}\n\n\tvar pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal,\n\t\treliableTrDimensionsVal, reliableMarginLeftVal,\n\t\tcontainer = document.createElement( \"div\" ),\n\t\tdiv = document.createElement( \"div\" );\n\n\t// Finish early in limited (non-browser) environments\n\tif ( !div.style ) {\n\t\treturn;\n\t}\n\n\t// Support: IE <=9 - 11 only\n\t// Style of cloned element affects source element cloned (#8908)\n\tdiv.style.backgroundClip = \"content-box\";\n\tdiv.cloneNode( true ).style.backgroundClip = \"\";\n\tsupport.clearCloneStyle = div.style.backgroundClip === \"content-box\";\n\n\tjQuery.extend( support, {\n\t\tboxSizingReliable: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn boxSizingReliableVal;\n\t\t},\n\t\tpixelBoxStyles: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn pixelBoxStylesVal;\n\t\t},\n\t\tpixelPosition: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn pixelPositionVal;\n\t\t},\n\t\treliableMarginLeft: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn reliableMarginLeftVal;\n\t\t},\n\t\tscrollboxSize: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn scrollboxSizeVal;\n\t\t},\n\n\t\t// Support: IE 9 - 11+, Edge 15 - 18+\n\t\t// IE/Edge misreport `getComputedStyle` of table rows with width/height\n\t\t// set in CSS while `offset*` properties report correct values.\n\t\t// Behavior in IE 9 is more subtle than in newer versions & it passes\n\t\t// some versions of this test; make sure not to make it pass there!\n\t\treliableTrDimensions: function() {\n\t\t\tvar table, tr, trChild, trStyle;\n\t\t\tif ( reliableTrDimensionsVal == null ) {\n\t\t\t\ttable = document.createElement( \"table\" );\n\t\t\t\ttr = document.createElement( \"tr\" );\n\t\t\t\ttrChild = document.createElement( \"div\" );\n\n\t\t\t\ttable.style.cssText = \"position:absolute;left:-11111px\";\n\t\t\t\ttr.style.height = \"1px\";\n\t\t\t\ttrChild.style.height = \"9px\";\n\n\t\t\t\tdocumentElement\n\t\t\t\t\t.appendChild( table )\n\t\t\t\t\t.appendChild( tr )\n\t\t\t\t\t.appendChild( trChild );\n\n\t\t\t\ttrStyle = window.getComputedStyle( tr );\n\t\t\t\treliableTrDimensionsVal = parseInt( trStyle.height ) > 3;\n\n\t\t\t\tdocumentElement.removeChild( table );\n\t\t\t}\n\t\t\treturn reliableTrDimensionsVal;\n\t\t}\n\t} );\n} )();\n\n\nfunction curCSS( elem, name, computed ) {\n\tvar width, minWidth, maxWidth, ret,\n\n\t\t// Support: Firefox 51+\n\t\t// Retrieving style before computed somehow\n\t\t// fixes an issue with getting wrong values\n\t\t// on detached elements\n\t\tstyle = elem.style;\n\n\tcomputed = computed || getStyles( elem );\n\n\t// getPropertyValue is needed for:\n\t//   .css('filter') (IE 9 only, #12537)\n\t//   .css('--customProperty) (#3144)\n\tif ( computed ) {\n\t\tret = computed.getPropertyValue( name ) || computed[ name ];\n\n\t\tif ( ret === \"\" && !isAttached( elem ) ) {\n\t\t\tret = jQuery.style( elem, name );\n\t\t}\n\n\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t// Android Browser returns percentage for some values,\n\t\t// but width seems to be reliably pixels.\n\t\t// This is against the CSSOM draft spec:\n\t\t// https://drafts.csswg.org/cssom/#resolved-values\n\t\tif ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) {\n\n\t\t\t// Remember the original values\n\t\t\twidth = style.width;\n\t\t\tminWidth = style.minWidth;\n\t\t\tmaxWidth = style.maxWidth;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tstyle.minWidth = style.maxWidth = style.width = ret;\n\t\t\tret = computed.width;\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.width = width;\n\t\t\tstyle.minWidth = minWidth;\n\t\t\tstyle.maxWidth = maxWidth;\n\t\t}\n\t}\n\n\treturn ret !== undefined ?\n\n\t\t// Support: IE <=9 - 11 only\n\t\t// IE returns zIndex value as an integer.\n\t\tret + \"\" :\n\t\tret;\n}\n\n\nfunction addGetHookIf( conditionFn, hookFn ) {\n\n\t// Define the hook, we'll check on the first run if it's really needed.\n\treturn {\n\t\tget: function() {\n\t\t\tif ( conditionFn() ) {\n\n\t\t\t\t// Hook not needed (or it's not possible to use it due\n\t\t\t\t// to missing dependency), remove it.\n\t\t\t\tdelete this.get;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Hook needed; redefine it so that the support test is not executed again.\n\t\t\treturn ( this.get = hookFn ).apply( this, arguments );\n\t\t}\n\t};\n}\n\n\nvar cssPrefixes = [ \"Webkit\", \"Moz\", \"ms\" ],\n\temptyStyle = document.createElement( \"div\" ).style,\n\tvendorProps = {};\n\n// Return a vendor-prefixed property or undefined\nfunction vendorPropName( name ) {\n\n\t// Check for vendor prefixed names\n\tvar capName = name[ 0 ].toUpperCase() + name.slice( 1 ),\n\t\ti = cssPrefixes.length;\n\n\twhile ( i-- ) {\n\t\tname = cssPrefixes[ i ] + capName;\n\t\tif ( name in emptyStyle ) {\n\t\t\treturn name;\n\t\t}\n\t}\n}\n\n// Return a potentially-mapped jQuery.cssProps or vendor prefixed property\nfunction finalPropName( name ) {\n\tvar final = jQuery.cssProps[ name ] || vendorProps[ name ];\n\n\tif ( final ) {\n\t\treturn final;\n\t}\n\tif ( name in emptyStyle ) {\n\t\treturn name;\n\t}\n\treturn vendorProps[ name ] = vendorPropName( name ) || name;\n}\n\n\nvar\n\n\t// Swappable if display is none or starts with table\n\t// except \"table\", \"table-cell\", or \"table-caption\"\n\t// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n\trdisplayswap = /^(none|table(?!-c[ea]).+)/,\n\trcustomProp = /^--/,\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssNormalTransform = {\n\t\tletterSpacing: \"0\",\n\t\tfontWeight: \"400\"\n\t};\n\nfunction setPositiveNumber( _elem, value, subtract ) {\n\n\t// Any relative (+/-) values have already been\n\t// normalized at this point\n\tvar matches = rcssNum.exec( value );\n\treturn matches ?\n\n\t\t// Guard against undefined \"subtract\", e.g., when used as in cssHooks\n\t\tMath.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || \"px\" ) :\n\t\tvalue;\n}\n\nfunction boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) {\n\tvar i = dimension === \"width\" ? 1 : 0,\n\t\textra = 0,\n\t\tdelta = 0;\n\n\t// Adjustment may not be necessary\n\tif ( box === ( isBorderBox ? \"border\" : \"content\" ) ) {\n\t\treturn 0;\n\t}\n\n\tfor ( ; i < 4; i += 2 ) {\n\n\t\t// Both box models exclude margin\n\t\tif ( box === \"margin\" ) {\n\t\t\tdelta += jQuery.css( elem, box + cssExpand[ i ], true, styles );\n\t\t}\n\n\t\t// If we get here with a content-box, we're seeking \"padding\" or \"border\" or \"margin\"\n\t\tif ( !isBorderBox ) {\n\n\t\t\t// Add padding\n\t\t\tdelta += jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\n\t\t\t// For \"border\" or \"margin\", add border\n\t\t\tif ( box !== \"padding\" ) {\n\t\t\t\tdelta += jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\n\t\t\t// But still keep track of it otherwise\n\t\t\t} else {\n\t\t\t\textra += jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\n\t\t// If we get here with a border-box (content + padding + border), we're seeking \"content\" or\n\t\t// \"padding\" or \"margin\"\n\t\t} else {\n\n\t\t\t// For \"content\", subtract padding\n\t\t\tif ( box === \"content\" ) {\n\t\t\t\tdelta -= jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\t\t\t}\n\n\t\t\t// For \"content\" or \"padding\", subtract border\n\t\t\tif ( box !== \"margin\" ) {\n\t\t\t\tdelta -= jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t}\n\t}\n\n\t// Account for positive content-box scroll gutter when requested by providing computedVal\n\tif ( !isBorderBox && computedVal >= 0 ) {\n\n\t\t// offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border\n\t\t// Assuming integer scroll gutter, subtract the rest and round down\n\t\tdelta += Math.max( 0, Math.ceil(\n\t\t\telem[ \"offset\" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -\n\t\t\tcomputedVal -\n\t\t\tdelta -\n\t\t\textra -\n\t\t\t0.5\n\n\t\t// If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter\n\t\t// Use an explicit zero to avoid NaN (gh-3964)\n\t\t) ) || 0;\n\t}\n\n\treturn delta;\n}\n\nfunction getWidthOrHeight( elem, dimension, extra ) {\n\n\t// Start with computed style\n\tvar styles = getStyles( elem ),\n\n\t\t// To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322).\n\t\t// Fake content-box until we know it's needed to know the true value.\n\t\tboxSizingNeeded = !support.boxSizingReliable() || extra,\n\t\tisBorderBox = boxSizingNeeded &&\n\t\t\tjQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\",\n\t\tvalueIsBorderBox = isBorderBox,\n\n\t\tval = curCSS( elem, dimension, styles ),\n\t\toffsetProp = \"offset\" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 );\n\n\t// Support: Firefox <=54\n\t// Return a confounding non-pixel value or feign ignorance, as appropriate.\n\tif ( rnumnonpx.test( val ) ) {\n\t\tif ( !extra ) {\n\t\t\treturn val;\n\t\t}\n\t\tval = \"auto\";\n\t}\n\n\n\t// Support: IE 9 - 11 only\n\t// Use offsetWidth/offsetHeight for when box sizing is unreliable.\n\t// In those cases, the computed value can be trusted to be border-box.\n\tif ( ( !support.boxSizingReliable() && isBorderBox ||\n\n\t\t// Support: IE 10 - 11+, Edge 15 - 18+\n\t\t// IE/Edge misreport `getComputedStyle` of table rows with width/height\n\t\t// set in CSS while `offset*` properties report correct values.\n\t\t// Interestingly, in some cases IE 9 doesn't suffer from this issue.\n\t\t!support.reliableTrDimensions() && nodeName( elem, \"tr\" ) ||\n\n\t\t// Fall back to offsetWidth/offsetHeight when value is \"auto\"\n\t\t// This happens for inline elements with no explicit setting (gh-3571)\n\t\tval === \"auto\" ||\n\n\t\t// Support: Android <=4.1 - 4.3 only\n\t\t// Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602)\n\t\t!parseFloat( val ) && jQuery.css( elem, \"display\", false, styles ) === \"inline\" ) &&\n\n\t\t// Make sure the element is visible & connected\n\t\telem.getClientRects().length ) {\n\n\t\tisBorderBox = jQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\";\n\n\t\t// Where available, offsetWidth/offsetHeight approximate border box dimensions.\n\t\t// Where not available (e.g., SVG), assume unreliable box-sizing and interpret the\n\t\t// retrieved value as a content box dimension.\n\t\tvalueIsBorderBox = offsetProp in elem;\n\t\tif ( valueIsBorderBox ) {\n\t\t\tval = elem[ offsetProp ];\n\t\t}\n\t}\n\n\t// Normalize \"\" and auto\n\tval = parseFloat( val ) || 0;\n\n\t// Adjust for the element's box model\n\treturn ( val +\n\t\tboxModelAdjustment(\n\t\t\telem,\n\t\t\tdimension,\n\t\t\textra || ( isBorderBox ? \"border\" : \"content\" ),\n\t\t\tvalueIsBorderBox,\n\t\t\tstyles,\n\n\t\t\t// Provide the current computed size to request scroll gutter calculation (gh-3589)\n\t\t\tval\n\t\t)\n\t) + \"px\";\n}\n\njQuery.extend( {\n\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Don't automatically add \"px\" to these possibly-unitless properties\n\tcssNumber: {\n\t\t\"animationIterationCount\": true,\n\t\t\"columnCount\": true,\n\t\t\"fillOpacity\": true,\n\t\t\"flexGrow\": true,\n\t\t\"flexShrink\": true,\n\t\t\"fontWeight\": true,\n\t\t\"gridArea\": true,\n\t\t\"gridColumn\": true,\n\t\t\"gridColumnEnd\": true,\n\t\t\"gridColumnStart\": true,\n\t\t\"gridRow\": true,\n\t\t\"gridRowEnd\": true,\n\t\t\"gridRowStart\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"order\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, hooks,\n\t\t\torigName = camelCase( name ),\n\t\t\tisCustomProp = rcustomProp.test( name ),\n\t\t\tstyle = elem.style;\n\n\t\t// Make sure that we're working with the right name. We don't\n\t\t// want to query the value if it is a CSS custom property\n\t\t// since they are user-defined.\n\t\tif ( !isCustomProp ) {\n\t\t\tname = finalPropName( origName );\n\t\t}\n\n\t\t// Gets hook for the prefixed version, then unprefixed version\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// Convert \"+=\" or \"-=\" to relative numbers (#7345)\n\t\t\tif ( type === \"string\" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {\n\t\t\t\tvalue = adjustCSS( elem, name, ret );\n\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that null and NaN values aren't set (#7116)\n\t\t\tif ( value == null || value !== value ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add the unit (except for certain CSS properties)\n\t\t\t// The isCustomProp check can be removed in jQuery 4.0 when we only auto-append\n\t\t\t// \"px\" to a few hardcoded values.\n\t\t\tif ( type === \"number\" && !isCustomProp ) {\n\t\t\t\tvalue += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? \"\" : \"px\" );\n\t\t\t}\n\n\t\t\t// background-* props affect original clone's values\n\t\t\tif ( !support.clearCloneStyle && value === \"\" && name.indexOf( \"background\" ) === 0 ) {\n\t\t\t\tstyle[ name ] = \"inherit\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !( \"set\" in hooks ) ||\n\t\t\t\t( value = hooks.set( elem, value, extra ) ) !== undefined ) {\n\n\t\t\t\tif ( isCustomProp ) {\n\t\t\t\t\tstyle.setProperty( name, value );\n\t\t\t\t} else {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks &&\n\t\t\t\t( ret = hooks.get( elem, false, extra ) ) !== undefined ) {\n\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra, styles ) {\n\t\tvar val, num, hooks,\n\t\t\torigName = camelCase( name ),\n\t\t\tisCustomProp = rcustomProp.test( name );\n\n\t\t// Make sure that we're working with the right name. We don't\n\t\t// want to modify the value if it is a CSS custom property\n\t\t// since they are user-defined.\n\t\tif ( !isCustomProp ) {\n\t\t\tname = finalPropName( origName );\n\t\t}\n\n\t\t// Try prefixed name followed by the unprefixed name\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks ) {\n\t\t\tval = hooks.get( elem, true, extra );\n\t\t}\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\tif ( val === undefined ) {\n\t\t\tval = curCSS( elem, name, styles );\n\t\t}\n\n\t\t// Convert \"normal\" to computed value\n\t\tif ( val === \"normal\" && name in cssNormalTransform ) {\n\t\t\tval = cssNormalTransform[ name ];\n\t\t}\n\n\t\t// Make numeric if forced or a qualifier was provided and val looks numeric\n\t\tif ( extra === \"\" || extra ) {\n\t\t\tnum = parseFloat( val );\n\t\t\treturn extra === true || isFinite( num ) ? num || 0 : val;\n\t\t}\n\n\t\treturn val;\n\t}\n} );\n\njQuery.each( [ \"height\", \"width\" ], function( _i, dimension ) {\n\tjQuery.cssHooks[ dimension ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\n\t\t\t\t// Certain elements can have dimension info if we invisibly show them\n\t\t\t\t// but it must have a current display style that would benefit\n\t\t\t\treturn rdisplayswap.test( jQuery.css( elem, \"display\" ) ) &&\n\n\t\t\t\t\t// Support: Safari 8+\n\t\t\t\t\t// Table columns in Safari have non-zero offsetWidth & zero\n\t\t\t\t\t// getBoundingClientRect().width unless display is changed.\n\t\t\t\t\t// Support: IE <=11 only\n\t\t\t\t\t// Running getBoundingClientRect on a disconnected node\n\t\t\t\t\t// in IE throws an error.\n\t\t\t\t\t( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?\n\t\t\t\t\t\tswap( elem, cssShow, function() {\n\t\t\t\t\t\t\treturn getWidthOrHeight( elem, dimension, extra );\n\t\t\t\t\t\t} ) :\n\t\t\t\t\t\tgetWidthOrHeight( elem, dimension, extra );\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value, extra ) {\n\t\t\tvar matches,\n\t\t\t\tstyles = getStyles( elem ),\n\n\t\t\t\t// Only read styles.position if the test has a chance to fail\n\t\t\t\t// to avoid forcing a reflow.\n\t\t\t\tscrollboxSizeBuggy = !support.scrollboxSize() &&\n\t\t\t\t\tstyles.position === \"absolute\",\n\n\t\t\t\t// To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991)\n\t\t\t\tboxSizingNeeded = scrollboxSizeBuggy || extra,\n\t\t\t\tisBorderBox = boxSizingNeeded &&\n\t\t\t\t\tjQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\",\n\t\t\t\tsubtract = extra ?\n\t\t\t\t\tboxModelAdjustment(\n\t\t\t\t\t\telem,\n\t\t\t\t\t\tdimension,\n\t\t\t\t\t\textra,\n\t\t\t\t\t\tisBorderBox,\n\t\t\t\t\t\tstyles\n\t\t\t\t\t) :\n\t\t\t\t\t0;\n\n\t\t\t// Account for unreliable border-box dimensions by comparing offset* to computed and\n\t\t\t// faking a content-box to get border and padding (gh-3699)\n\t\t\tif ( isBorderBox && scrollboxSizeBuggy ) {\n\t\t\t\tsubtract -= Math.ceil(\n\t\t\t\t\telem[ \"offset\" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -\n\t\t\t\t\tparseFloat( styles[ dimension ] ) -\n\t\t\t\t\tboxModelAdjustment( elem, dimension, \"border\", false, styles ) -\n\t\t\t\t\t0.5\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Convert to pixels if value adjustment is needed\n\t\t\tif ( subtract && ( matches = rcssNum.exec( value ) ) &&\n\t\t\t\t( matches[ 3 ] || \"px\" ) !== \"px\" ) {\n\n\t\t\t\telem.style[ dimension ] = value;\n\t\t\t\tvalue = jQuery.css( elem, dimension );\n\t\t\t}\n\n\t\t\treturn setPositiveNumber( elem, value, subtract );\n\t\t}\n\t};\n} );\n\njQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,\n\tfunction( elem, computed ) {\n\t\tif ( computed ) {\n\t\t\treturn ( parseFloat( curCSS( elem, \"marginLeft\" ) ) ||\n\t\t\t\telem.getBoundingClientRect().left -\n\t\t\t\t\tswap( elem, { marginLeft: 0 }, function() {\n\t\t\t\t\t\treturn elem.getBoundingClientRect().left;\n\t\t\t\t\t} )\n\t\t\t\t) + \"px\";\n\t\t}\n\t}\n);\n\n// These hooks are used by animate to expand properties\njQuery.each( {\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i = 0,\n\t\t\t\texpanded = {},\n\n\t\t\t\t// Assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split( \" \" ) : [ value ];\n\n\t\t\tfor ( ; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n\n\tif ( prefix !== \"margin\" ) {\n\t\tjQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;\n\t}\n} );\n\njQuery.fn.extend( {\n\tcss: function( name, value ) {\n\t\treturn access( this, function( elem, name, value ) {\n\t\t\tvar styles, len,\n\t\t\t\tmap = {},\n\t\t\t\ti = 0;\n\n\t\t\tif ( Array.isArray( name ) ) {\n\t\t\t\tstyles = getStyles( elem );\n\t\t\t\tlen = name.length;\n\n\t\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t\tmap[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );\n\t\t\t\t}\n\n\t\t\t\treturn map;\n\t\t\t}\n\n\t\t\treturn value !== undefined ?\n\t\t\t\tjQuery.style( elem, name, value ) :\n\t\t\t\tjQuery.css( elem, name );\n\t\t}, name, value, arguments.length > 1 );\n\t}\n} );\n\n\nfunction Tween( elem, options, prop, end, easing ) {\n\treturn new Tween.prototype.init( elem, options, prop, end, easing );\n}\njQuery.Tween = Tween;\n\nTween.prototype = {\n\tconstructor: Tween,\n\tinit: function( elem, options, prop, end, easing, unit ) {\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\t\tthis.easing = easing || jQuery.easing._default;\n\t\tthis.options = options;\n\t\tthis.start = this.now = this.cur();\n\t\tthis.end = end;\n\t\tthis.unit = unit || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n\t},\n\tcur: function() {\n\t\tvar hooks = Tween.propHooks[ this.prop ];\n\n\t\treturn hooks && hooks.get ?\n\t\t\thooks.get( this ) :\n\t\t\tTween.propHooks._default.get( this );\n\t},\n\trun: function( percent ) {\n\t\tvar eased,\n\t\t\thooks = Tween.propHooks[ this.prop ];\n\n\t\tif ( this.options.duration ) {\n\t\t\tthis.pos = eased = jQuery.easing[ this.easing ](\n\t\t\t\tpercent, this.options.duration * percent, 0, 1, this.options.duration\n\t\t\t);\n\t\t} else {\n\t\t\tthis.pos = eased = percent;\n\t\t}\n\t\tthis.now = ( this.end - this.start ) * eased + this.start;\n\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\tif ( hooks && hooks.set ) {\n\t\t\thooks.set( this );\n\t\t} else {\n\t\t\tTween.propHooks._default.set( this );\n\t\t}\n\t\treturn this;\n\t}\n};\n\nTween.prototype.init.prototype = Tween.prototype;\n\nTween.propHooks = {\n\t_default: {\n\t\tget: function( tween ) {\n\t\t\tvar result;\n\n\t\t\t// Use a property on the element directly when it is not a DOM element,\n\t\t\t// or when there is no matching style property that exists.\n\t\t\tif ( tween.elem.nodeType !== 1 ||\n\t\t\t\ttween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {\n\t\t\t\treturn tween.elem[ tween.prop ];\n\t\t\t}\n\n\t\t\t// Passing an empty string as a 3rd parameter to .css will automatically\n\t\t\t// attempt a parseFloat and fallback to a string if the parse fails.\n\t\t\t// Simple values such as \"10px\" are parsed to Float;\n\t\t\t// complex values such as \"rotate(1rad)\" are returned as-is.\n\t\t\tresult = jQuery.css( tween.elem, tween.prop, \"\" );\n\n\t\t\t// Empty strings, null, undefined and \"auto\" are converted to 0.\n\t\t\treturn !result || result === \"auto\" ? 0 : result;\n\t\t},\n\t\tset: function( tween ) {\n\n\t\t\t// Use step hook for back compat.\n\t\t\t// Use cssHook if its there.\n\t\t\t// Use .style if available and use plain properties where available.\n\t\t\tif ( jQuery.fx.step[ tween.prop ] ) {\n\t\t\t\tjQuery.fx.step[ tween.prop ]( tween );\n\t\t\t} else if ( tween.elem.nodeType === 1 && (\n\t\t\t\t\tjQuery.cssHooks[ tween.prop ] ||\n\t\t\t\t\ttween.elem.style[ finalPropName( tween.prop ) ] != null ) ) {\n\t\t\t\tjQuery.style( tween.elem, tween.prop, tween.now + tween.unit );\n\t\t\t} else {\n\t\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t\t}\n\t\t}\n\t}\n};\n\n// Support: IE <=9 only\n// Panic based approach to setting things on disconnected nodes\nTween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {\n\tset: function( tween ) {\n\t\tif ( tween.elem.nodeType && tween.elem.parentNode ) {\n\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t}\n\t}\n};\n\njQuery.easing = {\n\tlinear: function( p ) {\n\t\treturn p;\n\t},\n\tswing: function( p ) {\n\t\treturn 0.5 - Math.cos( p * Math.PI ) / 2;\n\t},\n\t_default: \"swing\"\n};\n\njQuery.fx = Tween.prototype.init;\n\n// Back compat <1.8 extension point\njQuery.fx.step = {};\n\n\n\n\nvar\n\tfxNow, inProgress,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trrun = /queueHooks$/;\n\nfunction schedule() {\n\tif ( inProgress ) {\n\t\tif ( document.hidden === false && window.requestAnimationFrame ) {\n\t\t\twindow.requestAnimationFrame( schedule );\n\t\t} else {\n\t\t\twindow.setTimeout( schedule, jQuery.fx.interval );\n\t\t}\n\n\t\tjQuery.fx.tick();\n\t}\n}\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\twindow.setTimeout( function() {\n\t\tfxNow = undefined;\n\t} );\n\treturn ( fxNow = Date.now() );\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, includeWidth ) {\n\tvar which,\n\t\ti = 0,\n\t\tattrs = { height: type };\n\n\t// If we include width, step value is 1 to do all cssExpand values,\n\t// otherwise step value is 2 to skip over Left and Right\n\tincludeWidth = includeWidth ? 1 : 0;\n\tfor ( ; i < 4; i += 2 - includeWidth ) {\n\t\twhich = cssExpand[ i ];\n\t\tattrs[ \"margin\" + which ] = attrs[ \"padding\" + which ] = type;\n\t}\n\n\tif ( includeWidth ) {\n\t\tattrs.opacity = attrs.width = type;\n\t}\n\n\treturn attrs;\n}\n\nfunction createTween( value, prop, animation ) {\n\tvar tween,\n\t\tcollection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ \"*\" ] ),\n\t\tindex = 0,\n\t\tlength = collection.length;\n\tfor ( ; index < length; index++ ) {\n\t\tif ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {\n\n\t\t\t// We're done with this property\n\t\t\treturn tween;\n\t\t}\n\t}\n}\n\nfunction defaultPrefilter( elem, props, opts ) {\n\tvar prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,\n\t\tisBox = \"width\" in props || \"height\" in props,\n\t\tanim = this,\n\t\torig = {},\n\t\tstyle = elem.style,\n\t\thidden = elem.nodeType && isHiddenWithinTree( elem ),\n\t\tdataShow = dataPriv.get( elem, \"fxshow\" );\n\n\t// Queue-skipping animations hijack the fx hooks\n\tif ( !opts.queue ) {\n\t\thooks = jQuery._queueHooks( elem, \"fx\" );\n\t\tif ( hooks.unqueued == null ) {\n\t\t\thooks.unqueued = 0;\n\t\t\toldfire = hooks.empty.fire;\n\t\t\thooks.empty.fire = function() {\n\t\t\t\tif ( !hooks.unqueued ) {\n\t\t\t\t\toldfire();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\thooks.unqueued++;\n\n\t\tanim.always( function() {\n\n\t\t\t// Ensure the complete handler is called before this completes\n\t\t\tanim.always( function() {\n\t\t\t\thooks.unqueued--;\n\t\t\t\tif ( !jQuery.queue( elem, \"fx\" ).length ) {\n\t\t\t\t\thooks.empty.fire();\n\t\t\t\t}\n\t\t\t} );\n\t\t} );\n\t}\n\n\t// Detect show/hide animations\n\tfor ( prop in props ) {\n\t\tvalue = props[ prop ];\n\t\tif ( rfxtypes.test( value ) ) {\n\t\t\tdelete props[ prop ];\n\t\t\ttoggle = toggle || value === \"toggle\";\n\t\t\tif ( value === ( hidden ? \"hide\" : \"show\" ) ) {\n\n\t\t\t\t// Pretend to be hidden if this is a \"show\" and\n\t\t\t\t// there is still data from a stopped show/hide\n\t\t\t\tif ( value === \"show\" && dataShow && dataShow[ prop ] !== undefined ) {\n\t\t\t\t\thidden = true;\n\n\t\t\t\t// Ignore all other no-op show/hide data\n\t\t\t\t} else {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\torig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );\n\t\t}\n\t}\n\n\t// Bail out if this is a no-op like .hide().hide()\n\tpropTween = !jQuery.isEmptyObject( props );\n\tif ( !propTween && jQuery.isEmptyObject( orig ) ) {\n\t\treturn;\n\t}\n\n\t// Restrict \"overflow\" and \"display\" styles during box animations\n\tif ( isBox && elem.nodeType === 1 ) {\n\n\t\t// Support: IE <=9 - 11, Edge 12 - 15\n\t\t// Record all 3 overflow attributes because IE does not infer the shorthand\n\t\t// from identically-valued overflowX and overflowY and Edge just mirrors\n\t\t// the overflowX value there.\n\t\topts.overflow = [ style.overflow, style.overflowX, style.overflowY ];\n\n\t\t// Identify a display type, preferring old show/hide data over the CSS cascade\n\t\trestoreDisplay = dataShow && dataShow.display;\n\t\tif ( restoreDisplay == null ) {\n\t\t\trestoreDisplay = dataPriv.get( elem, \"display\" );\n\t\t}\n\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\tif ( display === \"none\" ) {\n\t\t\tif ( restoreDisplay ) {\n\t\t\t\tdisplay = restoreDisplay;\n\t\t\t} else {\n\n\t\t\t\t// Get nonempty value(s) by temporarily forcing visibility\n\t\t\t\tshowHide( [ elem ], true );\n\t\t\t\trestoreDisplay = elem.style.display || restoreDisplay;\n\t\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\t\t\tshowHide( [ elem ] );\n\t\t\t}\n\t\t}\n\n\t\t// Animate inline elements as inline-block\n\t\tif ( display === \"inline\" || display === \"inline-block\" && restoreDisplay != null ) {\n\t\t\tif ( jQuery.css( elem, \"float\" ) === \"none\" ) {\n\n\t\t\t\t// Restore the original display value at the end of pure show/hide animations\n\t\t\t\tif ( !propTween ) {\n\t\t\t\t\tanim.done( function() {\n\t\t\t\t\t\tstyle.display = restoreDisplay;\n\t\t\t\t\t} );\n\t\t\t\t\tif ( restoreDisplay == null ) {\n\t\t\t\t\t\tdisplay = style.display;\n\t\t\t\t\t\trestoreDisplay = display === \"none\" ? \"\" : display;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tstyle.display = \"inline-block\";\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( opts.overflow ) {\n\t\tstyle.overflow = \"hidden\";\n\t\tanim.always( function() {\n\t\t\tstyle.overflow = opts.overflow[ 0 ];\n\t\t\tstyle.overflowX = opts.overflow[ 1 ];\n\t\t\tstyle.overflowY = opts.overflow[ 2 ];\n\t\t} );\n\t}\n\n\t// Implement show/hide animations\n\tpropTween = false;\n\tfor ( prop in orig ) {\n\n\t\t// General show/hide setup for this element animation\n\t\tif ( !propTween ) {\n\t\t\tif ( dataShow ) {\n\t\t\t\tif ( \"hidden\" in dataShow ) {\n\t\t\t\t\thidden = dataShow.hidden;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdataShow = dataPriv.access( elem, \"fxshow\", { display: restoreDisplay } );\n\t\t\t}\n\n\t\t\t// Store hidden/visible for toggle so `.stop().toggle()` \"reverses\"\n\t\t\tif ( toggle ) {\n\t\t\t\tdataShow.hidden = !hidden;\n\t\t\t}\n\n\t\t\t// Show elements before animating them\n\t\t\tif ( hidden ) {\n\t\t\t\tshowHide( [ elem ], true );\n\t\t\t}\n\n\t\t\t/* eslint-disable no-loop-func */\n\n\t\t\tanim.done( function() {\n\n\t\t\t/* eslint-enable no-loop-func */\n\n\t\t\t\t// The final step of a \"hide\" animation is actually hiding the element\n\t\t\t\tif ( !hidden ) {\n\t\t\t\t\tshowHide( [ elem ] );\n\t\t\t\t}\n\t\t\t\tdataPriv.remove( elem, \"fxshow\" );\n\t\t\t\tfor ( prop in orig ) {\n\t\t\t\t\tjQuery.style( elem, prop, orig[ prop ] );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\t// Per-property setup\n\t\tpropTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );\n\t\tif ( !( prop in dataShow ) ) {\n\t\t\tdataShow[ prop ] = propTween.start;\n\t\t\tif ( hidden ) {\n\t\t\t\tpropTween.end = propTween.start;\n\t\t\t\tpropTween.start = 0;\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction propFilter( props, specialEasing ) {\n\tvar index, name, easing, value, hooks;\n\n\t// camelCase, specialEasing and expand cssHook pass\n\tfor ( index in props ) {\n\t\tname = camelCase( index );\n\t\teasing = specialEasing[ name ];\n\t\tvalue = props[ index ];\n\t\tif ( Array.isArray( value ) ) {\n\t\t\teasing = value[ 1 ];\n\t\t\tvalue = props[ index ] = value[ 0 ];\n\t\t}\n\n\t\tif ( index !== name ) {\n\t\t\tprops[ name ] = value;\n\t\t\tdelete props[ index ];\n\t\t}\n\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tif ( hooks && \"expand\" in hooks ) {\n\t\t\tvalue = hooks.expand( value );\n\t\t\tdelete props[ name ];\n\n\t\t\t// Not quite $.extend, this won't overwrite existing keys.\n\t\t\t// Reusing 'index' because we have the correct \"name\"\n\t\t\tfor ( index in value ) {\n\t\t\t\tif ( !( index in props ) ) {\n\t\t\t\t\tprops[ index ] = value[ index ];\n\t\t\t\t\tspecialEasing[ index ] = easing;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tspecialEasing[ name ] = easing;\n\t\t}\n\t}\n}\n\nfunction Animation( elem, properties, options ) {\n\tvar result,\n\t\tstopped,\n\t\tindex = 0,\n\t\tlength = Animation.prefilters.length,\n\t\tdeferred = jQuery.Deferred().always( function() {\n\n\t\t\t// Don't match elem in the :animated selector\n\t\t\tdelete tick.elem;\n\t\t} ),\n\t\ttick = function() {\n\t\t\tif ( stopped ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tvar currentTime = fxNow || createFxNow(),\n\t\t\t\tremaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),\n\n\t\t\t\t// Support: Android 2.3 only\n\t\t\t\t// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)\n\t\t\t\ttemp = remaining / animation.duration || 0,\n\t\t\t\tpercent = 1 - temp,\n\t\t\t\tindex = 0,\n\t\t\t\tlength = animation.tweens.length;\n\n\t\t\tfor ( ; index < length; index++ ) {\n\t\t\t\tanimation.tweens[ index ].run( percent );\n\t\t\t}\n\n\t\t\tdeferred.notifyWith( elem, [ animation, percent, remaining ] );\n\n\t\t\t// If there's more to do, yield\n\t\t\tif ( percent < 1 && length ) {\n\t\t\t\treturn remaining;\n\t\t\t}\n\n\t\t\t// If this was an empty animation, synthesize a final progress notification\n\t\t\tif ( !length ) {\n\t\t\t\tdeferred.notifyWith( elem, [ animation, 1, 0 ] );\n\t\t\t}\n\n\t\t\t// Resolve the animation and report its conclusion\n\t\t\tdeferred.resolveWith( elem, [ animation ] );\n\t\t\treturn false;\n\t\t},\n\t\tanimation = deferred.promise( {\n\t\t\telem: elem,\n\t\t\tprops: jQuery.extend( {}, properties ),\n\t\t\topts: jQuery.extend( true, {\n\t\t\t\tspecialEasing: {},\n\t\t\t\teasing: jQuery.easing._default\n\t\t\t}, options ),\n\t\t\toriginalProperties: properties,\n\t\t\toriginalOptions: options,\n\t\t\tstartTime: fxNow || createFxNow(),\n\t\t\tduration: options.duration,\n\t\t\ttweens: [],\n\t\t\tcreateTween: function( prop, end ) {\n\t\t\t\tvar tween = jQuery.Tween( elem, animation.opts, prop, end,\n\t\t\t\t\t\tanimation.opts.specialEasing[ prop ] || animation.opts.easing );\n\t\t\t\tanimation.tweens.push( tween );\n\t\t\t\treturn tween;\n\t\t\t},\n\t\t\tstop: function( gotoEnd ) {\n\t\t\t\tvar index = 0,\n\n\t\t\t\t\t// If we are going to the end, we want to run all the tweens\n\t\t\t\t\t// otherwise we skip this part\n\t\t\t\t\tlength = gotoEnd ? animation.tweens.length : 0;\n\t\t\t\tif ( stopped ) {\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t\tstopped = true;\n\t\t\t\tfor ( ; index < length; index++ ) {\n\t\t\t\t\tanimation.tweens[ index ].run( 1 );\n\t\t\t\t}\n\n\t\t\t\t// Resolve when we played the last frame; otherwise, reject\n\t\t\t\tif ( gotoEnd ) {\n\t\t\t\t\tdeferred.notifyWith( elem, [ animation, 1, 0 ] );\n\t\t\t\t\tdeferred.resolveWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t} else {\n\t\t\t\t\tdeferred.rejectWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t}\n\t\t} ),\n\t\tprops = animation.props;\n\n\tpropFilter( props, animation.opts.specialEasing );\n\n\tfor ( ; index < length; index++ ) {\n\t\tresult = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );\n\t\tif ( result ) {\n\t\t\tif ( isFunction( result.stop ) ) {\n\t\t\t\tjQuery._queueHooks( animation.elem, animation.opts.queue ).stop =\n\t\t\t\t\tresult.stop.bind( result );\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\t}\n\n\tjQuery.map( props, createTween, animation );\n\n\tif ( isFunction( animation.opts.start ) ) {\n\t\tanimation.opts.start.call( elem, animation );\n\t}\n\n\t// Attach callbacks from options\n\tanimation\n\t\t.progress( animation.opts.progress )\n\t\t.done( animation.opts.done, animation.opts.complete )\n\t\t.fail( animation.opts.fail )\n\t\t.always( animation.opts.always );\n\n\tjQuery.fx.timer(\n\t\tjQuery.extend( tick, {\n\t\t\telem: elem,\n\t\t\tanim: animation,\n\t\t\tqueue: animation.opts.queue\n\t\t} )\n\t);\n\n\treturn animation;\n}\n\njQuery.Animation = jQuery.extend( Animation, {\n\n\ttweeners: {\n\t\t\"*\": [ function( prop, value ) {\n\t\t\tvar tween = this.createTween( prop, value );\n\t\t\tadjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );\n\t\t\treturn tween;\n\t\t} ]\n\t},\n\n\ttweener: function( props, callback ) {\n\t\tif ( isFunction( props ) ) {\n\t\t\tcallback = props;\n\t\t\tprops = [ \"*\" ];\n\t\t} else {\n\t\t\tprops = props.match( rnothtmlwhite );\n\t\t}\n\n\t\tvar prop,\n\t\t\tindex = 0,\n\t\t\tlength = props.length;\n\n\t\tfor ( ; index < length; index++ ) {\n\t\t\tprop = props[ index ];\n\t\t\tAnimation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];\n\t\t\tAnimation.tweeners[ prop ].unshift( callback );\n\t\t}\n\t},\n\n\tprefilters: [ defaultPrefilter ],\n\n\tprefilter: function( callback, prepend ) {\n\t\tif ( prepend ) {\n\t\t\tAnimation.prefilters.unshift( callback );\n\t\t} else {\n\t\t\tAnimation.prefilters.push( callback );\n\t\t}\n\t}\n} );\n\njQuery.speed = function( speed, easing, fn ) {\n\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\tcomplete: fn || !fn && easing ||\n\t\t\tisFunction( speed ) && speed,\n\t\tduration: speed,\n\t\teasing: fn && easing || easing && !isFunction( easing ) && easing\n\t};\n\n\t// Go to the end state if fx are off\n\tif ( jQuery.fx.off ) {\n\t\topt.duration = 0;\n\n\t} else {\n\t\tif ( typeof opt.duration !== \"number\" ) {\n\t\t\tif ( opt.duration in jQuery.fx.speeds ) {\n\t\t\t\topt.duration = jQuery.fx.speeds[ opt.duration ];\n\n\t\t\t} else {\n\t\t\t\topt.duration = jQuery.fx.speeds._default;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Normalize opt.queue - true/undefined/null -> \"fx\"\n\tif ( opt.queue == null || opt.queue === true ) {\n\t\topt.queue = \"fx\";\n\t}\n\n\t// Queueing\n\topt.old = opt.complete;\n\n\topt.complete = function() {\n\t\tif ( isFunction( opt.old ) ) {\n\t\t\topt.old.call( this );\n\t\t}\n\n\t\tif ( opt.queue ) {\n\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t}\n\t};\n\n\treturn opt;\n};\n\njQuery.fn.extend( {\n\tfadeTo: function( speed, to, easing, callback ) {\n\n\t\t// Show any hidden elements after setting opacity to 0\n\t\treturn this.filter( isHiddenWithinTree ).css( \"opacity\", 0 ).show()\n\n\t\t\t// Animate to the value specified\n\t\t\t.end().animate( { opacity: to }, speed, easing, callback );\n\t},\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar empty = jQuery.isEmptyObject( prop ),\n\t\t\toptall = jQuery.speed( speed, easing, callback ),\n\t\t\tdoAnimation = function() {\n\n\t\t\t\t// Operate on a copy of prop so per-property easing won't be lost\n\t\t\t\tvar anim = Animation( this, jQuery.extend( {}, prop ), optall );\n\n\t\t\t\t// Empty animations, or finishing resolves immediately\n\t\t\t\tif ( empty || dataPriv.get( this, \"finish\" ) ) {\n\t\t\t\t\tanim.stop( true );\n\t\t\t\t}\n\t\t\t};\n\t\t\tdoAnimation.finish = doAnimation;\n\n\t\treturn empty || optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tvar stopQueue = function( hooks ) {\n\t\t\tvar stop = hooks.stop;\n\t\t\tdelete hooks.stop;\n\t\t\tstop( gotoEnd );\n\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tvar dequeue = true,\n\t\t\t\tindex = type != null && type + \"queueHooks\",\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = dataPriv.get( this );\n\n\t\t\tif ( index ) {\n\t\t\t\tif ( data[ index ] && data[ index ].stop ) {\n\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {\n\t\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this &&\n\t\t\t\t\t( type == null || timers[ index ].queue === type ) ) {\n\n\t\t\t\t\ttimers[ index ].anim.stop( gotoEnd );\n\t\t\t\t\tdequeue = false;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Start the next in the queue if the last step wasn't forced.\n\t\t\t// Timers currently will call their complete callbacks, which\n\t\t\t// will dequeue but only if they were gotoEnd.\n\t\t\tif ( dequeue || !gotoEnd ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t} );\n\t},\n\tfinish: function( type ) {\n\t\tif ( type !== false ) {\n\t\t\ttype = type || \"fx\";\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tvar index,\n\t\t\t\tdata = dataPriv.get( this ),\n\t\t\t\tqueue = data[ type + \"queue\" ],\n\t\t\t\thooks = data[ type + \"queueHooks\" ],\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tlength = queue ? queue.length : 0;\n\n\t\t\t// Enable finishing flag on private data\n\t\t\tdata.finish = true;\n\n\t\t\t// Empty the queue first\n\t\t\tjQuery.queue( this, type, [] );\n\n\t\t\tif ( hooks && hooks.stop ) {\n\t\t\t\thooks.stop.call( this, true );\n\t\t\t}\n\n\t\t\t// Look for any active animations, and finish them\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && timers[ index ].queue === type ) {\n\t\t\t\t\ttimers[ index ].anim.stop( true );\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Look for any animations in the old queue and finish them\n\t\t\tfor ( index = 0; index < length; index++ ) {\n\t\t\t\tif ( queue[ index ] && queue[ index ].finish ) {\n\t\t\t\t\tqueue[ index ].finish.call( this );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Turn off finishing flag\n\t\t\tdelete data.finish;\n\t\t} );\n\t}\n} );\n\njQuery.each( [ \"toggle\", \"show\", \"hide\" ], function( _i, name ) {\n\tvar cssFn = jQuery.fn[ name ];\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn speed == null || typeof speed === \"boolean\" ?\n\t\t\tcssFn.apply( this, arguments ) :\n\t\t\tthis.animate( genFx( name, true ), speed, easing, callback );\n\t};\n} );\n\n// Generate shortcuts for custom animations\njQuery.each( {\n\tslideDown: genFx( \"show\" ),\n\tslideUp: genFx( \"hide\" ),\n\tslideToggle: genFx( \"toggle\" ),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n} );\n\njQuery.timers = [];\njQuery.fx.tick = function() {\n\tvar timer,\n\t\ti = 0,\n\t\ttimers = jQuery.timers;\n\n\tfxNow = Date.now();\n\n\tfor ( ; i < timers.length; i++ ) {\n\t\ttimer = timers[ i ];\n\n\t\t// Run the timer and safely remove it when done (allowing for external removal)\n\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\ttimers.splice( i--, 1 );\n\t\t}\n\t}\n\n\tif ( !timers.length ) {\n\t\tjQuery.fx.stop();\n\t}\n\tfxNow = undefined;\n};\n\njQuery.fx.timer = function( timer ) {\n\tjQuery.timers.push( timer );\n\tjQuery.fx.start();\n};\n\njQuery.fx.interval = 13;\njQuery.fx.start = function() {\n\tif ( inProgress ) {\n\t\treturn;\n\t}\n\n\tinProgress = true;\n\tschedule();\n};\n\njQuery.fx.stop = function() {\n\tinProgress = null;\n};\n\njQuery.fx.speeds = {\n\tslow: 600,\n\tfast: 200,\n\n\t// Default speed\n\t_default: 400\n};\n\n\n// Based off of the plugin by Clint Helfers, with permission.\n// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/\njQuery.fn.delay = function( time, type ) {\n\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\ttype = type || \"fx\";\n\n\treturn this.queue( type, function( next, hooks ) {\n\t\tvar timeout = window.setTimeout( next, time );\n\t\thooks.stop = function() {\n\t\t\twindow.clearTimeout( timeout );\n\t\t};\n\t} );\n};\n\n\n( function() {\n\tvar input = document.createElement( \"input\" ),\n\t\tselect = document.createElement( \"select\" ),\n\t\topt = select.appendChild( document.createElement( \"option\" ) );\n\n\tinput.type = \"checkbox\";\n\n\t// Support: Android <=4.3 only\n\t// Default value for a checkbox should be \"on\"\n\tsupport.checkOn = input.value !== \"\";\n\n\t// Support: IE <=11 only\n\t// Must access selectedIndex to make default options select\n\tsupport.optSelected = opt.selected;\n\n\t// Support: IE <=11 only\n\t// An input loses its value after becoming a radio\n\tinput = document.createElement( \"input\" );\n\tinput.value = \"t\";\n\tinput.type = \"radio\";\n\tsupport.radioValue = input.value === \"t\";\n} )();\n\n\nvar boolHook,\n\tattrHandle = jQuery.expr.attrHandle;\n\njQuery.fn.extend( {\n\tattr: function( name, value ) {\n\t\treturn access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each( function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t} );\n\t}\n} );\n\njQuery.extend( {\n\tattr: function( elem, name, value ) {\n\t\tvar ret, hooks,\n\t\t\tnType = elem.nodeType;\n\n\t\t// Don't get/set attributes on text, comment and attribute nodes\n\t\tif ( nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === \"undefined\" ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\t// Attribute hooks are determined by the lowercase version\n\t\t// Grab necessary hook if one is defined\n\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n\t\t\thooks = jQuery.attrHooks[ name.toLowerCase() ] ||\n\t\t\t\t( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( hooks && \"set\" in hooks &&\n\t\t\t\t( ret = hooks.set( elem, value, name ) ) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, value + \"\" );\n\t\t\treturn value;\n\t\t}\n\n\t\tif ( hooks && \"get\" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tret = jQuery.find.attr( elem, name );\n\n\t\t// Non-existent attributes return null, we normalize to undefined\n\t\treturn ret == null ? undefined : ret;\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( !support.radioValue && value === \"radio\" &&\n\t\t\t\t\tnodeName( elem, \"input\" ) ) {\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar name,\n\t\t\ti = 0,\n\n\t\t\t// Attribute names can contain non-HTML whitespace characters\n\t\t\t// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2\n\t\t\tattrNames = value && value.match( rnothtmlwhite );\n\n\t\tif ( attrNames && elem.nodeType === 1 ) {\n\t\t\twhile ( ( name = attrNames[ i++ ] ) ) {\n\t\t\t\telem.removeAttribute( name );\n\t\t\t}\n\t\t}\n\t}\n} );\n\n// Hooks for boolean attributes\nboolHook = {\n\tset: function( elem, value, name ) {\n\t\tif ( value === false ) {\n\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\telem.setAttribute( name, name );\n\t\t}\n\t\treturn name;\n\t}\n};\n\njQuery.each( jQuery.expr.match.bool.source.match( /\\w+/g ), function( _i, name ) {\n\tvar getter = attrHandle[ name ] || jQuery.find.attr;\n\n\tattrHandle[ name ] = function( elem, name, isXML ) {\n\t\tvar ret, handle,\n\t\t\tlowercaseName = name.toLowerCase();\n\n\t\tif ( !isXML ) {\n\n\t\t\t// Avoid an infinite loop by temporarily removing this function from the getter\n\t\t\thandle = attrHandle[ lowercaseName ];\n\t\t\tattrHandle[ lowercaseName ] = ret;\n\t\t\tret = getter( elem, name, isXML ) != null ?\n\t\t\t\tlowercaseName :\n\t\t\t\tnull;\n\t\t\tattrHandle[ lowercaseName ] = handle;\n\t\t}\n\t\treturn ret;\n\t};\n} );\n\n\n\n\nvar rfocusable = /^(?:input|select|textarea|button)$/i,\n\trclickable = /^(?:a|area)$/i;\n\njQuery.fn.extend( {\n\tprop: function( name, value ) {\n\t\treturn access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\treturn this.each( function() {\n\t\t\tdelete this[ jQuery.propFix[ name ] || name ];\n\t\t} );\n\t}\n} );\n\njQuery.extend( {\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks,\n\t\t\tnType = elem.nodeType;\n\n\t\t// Don't get/set properties on text, comment and attribute nodes\n\t\tif ( nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks &&\n\t\t\t\t( ret = hooks.set( elem, value, name ) ) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\treturn ( elem[ name ] = value );\n\t\t}\n\n\t\tif ( hooks && \"get\" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\treturn elem[ name ];\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\n\t\t\t\t// Support: IE <=9 - 11 only\n\t\t\t\t// elem.tabIndex doesn't always return the\n\t\t\t\t// correct value when it hasn't been explicitly set\n\t\t\t\t// https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\t// Use proper attribute retrieval(#12072)\n\t\t\t\tvar tabindex = jQuery.find.attr( elem, \"tabindex\" );\n\n\t\t\t\tif ( tabindex ) {\n\t\t\t\t\treturn parseInt( tabindex, 10 );\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\trfocusable.test( elem.nodeName ) ||\n\t\t\t\t\trclickable.test( elem.nodeName ) &&\n\t\t\t\t\telem.href\n\t\t\t\t) {\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\"\n\t}\n} );\n\n// Support: IE <=11 only\n// Accessing the selectedIndex property\n// forces the browser to respect setting selected\n// on the option\n// The getter ensures a default option is selected\n// when in an optgroup\n// eslint rule \"no-unused-expressions\" is disabled for this code\n// since it considers such accessions noop\nif ( !support.optSelected ) {\n\tjQuery.propHooks.selected = {\n\t\tget: function( elem ) {\n\n\t\t\t/* eslint no-unused-expressions: \"off\" */\n\n\t\t\tvar parent = elem.parentNode;\n\t\t\tif ( parent && parent.parentNode ) {\n\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\tset: function( elem ) {\n\n\t\t\t/* eslint no-unused-expressions: \"off\" */\n\n\t\t\tvar parent = elem.parentNode;\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\njQuery.each( [\n\t\"tabIndex\",\n\t\"readOnly\",\n\t\"maxLength\",\n\t\"cellSpacing\",\n\t\"cellPadding\",\n\t\"rowSpan\",\n\t\"colSpan\",\n\t\"useMap\",\n\t\"frameBorder\",\n\t\"contentEditable\"\n], function() {\n\tjQuery.propFix[ this.toLowerCase() ] = this;\n} );\n\n\n\n\n\t// Strip and collapse whitespace according to HTML spec\n\t// https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace\n\tfunction stripAndCollapse( value ) {\n\t\tvar tokens = value.match( rnothtmlwhite ) || [];\n\t\treturn tokens.join( \" \" );\n\t}\n\n\nfunction getClass( elem ) {\n\treturn elem.getAttribute && elem.getAttribute( \"class\" ) || \"\";\n}\n\nfunction classesToArray( value ) {\n\tif ( Array.isArray( value ) ) {\n\t\treturn value;\n\t}\n\tif ( typeof value === \"string\" ) {\n\t\treturn value.match( rnothtmlwhite ) || [];\n\t}\n\treturn [];\n}\n\njQuery.fn.extend( {\n\taddClass: function( value ) {\n\t\tvar classes, elem, cur, curValue, clazz, j, finalValue,\n\t\t\ti = 0;\n\n\t\tif ( isFunction( value ) ) {\n\t\t\treturn this.each( function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call( this, j, getClass( this ) ) );\n\t\t\t} );\n\t\t}\n\n\t\tclasses = classesToArray( value );\n\n\t\tif ( classes.length ) {\n\t\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\t\tcurValue = getClass( elem );\n\t\t\t\tcur = elem.nodeType === 1 && ( \" \" + stripAndCollapse( curValue ) + \" \" );\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( ( clazz = classes[ j++ ] ) ) {\n\t\t\t\t\t\tif ( cur.indexOf( \" \" + clazz + \" \" ) < 0 ) {\n\t\t\t\t\t\t\tcur += clazz + \" \";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Only assign if different to avoid unneeded rendering.\n\t\t\t\t\tfinalValue = stripAndCollapse( cur );\n\t\t\t\t\tif ( curValue !== finalValue ) {\n\t\t\t\t\t\telem.setAttribute( \"class\", finalValue );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classes, elem, cur, curValue, clazz, j, finalValue,\n\t\t\ti = 0;\n\n\t\tif ( isFunction( value ) ) {\n\t\t\treturn this.each( function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );\n\t\t\t} );\n\t\t}\n\n\t\tif ( !arguments.length ) {\n\t\t\treturn this.attr( \"class\", \"\" );\n\t\t}\n\n\t\tclasses = classesToArray( value );\n\n\t\tif ( classes.length ) {\n\t\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\t\tcurValue = getClass( elem );\n\n\t\t\t\t// This expression is here for better compressibility (see addClass)\n\t\t\t\tcur = elem.nodeType === 1 && ( \" \" + stripAndCollapse( curValue ) + \" \" );\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( ( clazz = classes[ j++ ] ) ) {\n\n\t\t\t\t\t\t// Remove *all* instances\n\t\t\t\t\t\twhile ( cur.indexOf( \" \" + clazz + \" \" ) > -1 ) {\n\t\t\t\t\t\t\tcur = cur.replace( \" \" + clazz + \" \", \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Only assign if different to avoid unneeded rendering.\n\t\t\t\t\tfinalValue = stripAndCollapse( cur );\n\t\t\t\t\tif ( curValue !== finalValue ) {\n\t\t\t\t\t\telem.setAttribute( \"class\", finalValue );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisValidValue = type === \"string\" || Array.isArray( value );\n\n\t\tif ( typeof stateVal === \"boolean\" && isValidValue ) {\n\t\t\treturn stateVal ? this.addClass( value ) : this.removeClass( value );\n\t\t}\n\n\t\tif ( isFunction( value ) ) {\n\t\t\treturn this.each( function( i ) {\n\t\t\t\tjQuery( this ).toggleClass(\n\t\t\t\t\tvalue.call( this, i, getClass( this ), stateVal ),\n\t\t\t\t\tstateVal\n\t\t\t\t);\n\t\t\t} );\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tvar className, i, self, classNames;\n\n\t\t\tif ( isValidValue ) {\n\n\t\t\t\t// Toggle individual class names\n\t\t\t\ti = 0;\n\t\t\t\tself = jQuery( this );\n\t\t\t\tclassNames = classesToArray( value );\n\n\t\t\t\twhile ( ( className = classNames[ i++ ] ) ) {\n\n\t\t\t\t\t// Check each className given, space separated list\n\t\t\t\t\tif ( self.hasClass( className ) ) {\n\t\t\t\t\t\tself.removeClass( className );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tself.addClass( className );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Toggle whole class name\n\t\t\t} else if ( value === undefined || type === \"boolean\" ) {\n\t\t\t\tclassName = getClass( this );\n\t\t\t\tif ( className ) {\n\n\t\t\t\t\t// Store className if set\n\t\t\t\t\tdataPriv.set( this, \"__className__\", className );\n\t\t\t\t}\n\n\t\t\t\t// If the element has a class name or if we're passed `false`,\n\t\t\t\t// then remove the whole classname (if there was one, the above saved it).\n\t\t\t\t// Otherwise bring back whatever was previously saved (if anything),\n\t\t\t\t// falling back to the empty string if nothing was stored.\n\t\t\t\tif ( this.setAttribute ) {\n\t\t\t\t\tthis.setAttribute( \"class\",\n\t\t\t\t\t\tclassName || value === false ?\n\t\t\t\t\t\t\"\" :\n\t\t\t\t\t\tdataPriv.get( this, \"__className__\" ) || \"\"\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className, elem,\n\t\t\ti = 0;\n\n\t\tclassName = \" \" + selector + \" \";\n\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\tif ( elem.nodeType === 1 &&\n\t\t\t\t( \" \" + stripAndCollapse( getClass( elem ) ) + \" \" ).indexOf( className ) > -1 ) {\n\t\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n} );\n\n\n\n\nvar rreturn = /\\r/g;\n\njQuery.fn.extend( {\n\tval: function( value ) {\n\t\tvar hooks, ret, valueIsFunction,\n\t\t\telem = this[ 0 ];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] ||\n\t\t\t\t\tjQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks &&\n\t\t\t\t\t\"get\" in hooks &&\n\t\t\t\t\t( ret = hooks.get( elem, \"value\" ) ) !== undefined\n\t\t\t\t) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\t// Handle most common string cases\n\t\t\t\tif ( typeof ret === \"string\" ) {\n\t\t\t\t\treturn ret.replace( rreturn, \"\" );\n\t\t\t\t}\n\n\t\t\t\t// Handle cases where value is null/undef or number\n\t\t\t\treturn ret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tvalueIsFunction = isFunction( value );\n\n\t\treturn this.each( function( i ) {\n\t\t\tvar val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( valueIsFunction ) {\n\t\t\t\tval = value.call( this, i, jQuery( this ).val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\n\t\t\t} else if ( Array.isArray( val ) ) {\n\t\t\t\tval = jQuery.map( val, function( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !( \"set\" in hooks ) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t} );\n\t}\n} );\n\njQuery.extend( {\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\n\t\t\t\tvar val = jQuery.find.attr( elem, \"value\" );\n\t\t\t\treturn val != null ?\n\t\t\t\t\tval :\n\n\t\t\t\t\t// Support: IE <=10 - 11 only\n\t\t\t\t\t// option.text throws exceptions (#14686, #14858)\n\t\t\t\t\t// Strip and collapse whitespace\n\t\t\t\t\t// https://html.spec.whatwg.org/#strip-and-collapse-whitespace\n\t\t\t\t\tstripAndCollapse( jQuery.text( elem ) );\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, option, i,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tone = elem.type === \"select-one\",\n\t\t\t\t\tvalues = one ? null : [],\n\t\t\t\t\tmax = one ? index + 1 : options.length;\n\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\ti = max;\n\n\t\t\t\t} else {\n\t\t\t\t\ti = one ? index : 0;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// Support: IE <=9 only\n\t\t\t\t\t// IE8-9 doesn't update selected after form reset (#2551)\n\t\t\t\t\tif ( ( option.selected || i === index ) &&\n\n\t\t\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\t\t\t!option.disabled &&\n\t\t\t\t\t\t\t( !option.parentNode.disabled ||\n\t\t\t\t\t\t\t\t!nodeName( option.parentNode, \"optgroup\" ) ) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar optionSet, option,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tvalues = jQuery.makeArray( value ),\n\t\t\t\t\ti = options.length;\n\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t/* eslint-disable no-cond-assign */\n\n\t\t\t\t\tif ( option.selected =\n\t\t\t\t\t\tjQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1\n\t\t\t\t\t) {\n\t\t\t\t\t\toptionSet = true;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* eslint-enable no-cond-assign */\n\t\t\t\t}\n\n\t\t\t\t// Force browsers to behave consistently when non-matching value is set\n\t\t\t\tif ( !optionSet ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t}\n} );\n\n// Radios and checkboxes getter/setter\njQuery.each( [ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = {\n\t\tset: function( elem, value ) {\n\t\t\tif ( Array.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );\n\t\t\t}\n\t\t}\n\t};\n\tif ( !support.checkOn ) {\n\t\tjQuery.valHooks[ this ].get = function( elem ) {\n\t\t\treturn elem.getAttribute( \"value\" ) === null ? \"on\" : elem.value;\n\t\t};\n\t}\n} );\n\n\n\n\n// Return jQuery for attributes-only inclusion\n\n\nsupport.focusin = \"onfocusin\" in window;\n\n\nvar rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\tstopPropagationCallback = function( e ) {\n\t\te.stopPropagation();\n\t};\n\njQuery.extend( jQuery.event, {\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\n\t\tvar i, cur, tmp, bubbleType, ontype, handle, special, lastElement,\n\t\t\teventPath = [ elem || document ],\n\t\t\ttype = hasOwn.call( event, \"type\" ) ? event.type : event,\n\t\t\tnamespaces = hasOwn.call( event, \"namespace\" ) ? event.namespace.split( \".\" ) : [];\n\n\t\tcur = lastElement = tmp = elem = elem || document;\n\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf( \".\" ) > -1 ) {\n\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split( \".\" );\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\t\tontype = type.indexOf( \":\" ) < 0 && \"on\" + type;\n\n\t\t// Caller can pass in a jQuery.Event object, Object, or just an event type string\n\t\tevent = event[ jQuery.expando ] ?\n\t\t\tevent :\n\t\t\tnew jQuery.Event( type, typeof event === \"object\" && event );\n\n\t\t// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)\n\t\tevent.isTrigger = onlyHandlers ? 2 : 3;\n\t\tevent.namespace = namespaces.join( \".\" );\n\t\tevent.rnamespace = event.namespace ?\n\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join( \"\\\\.(?:.*\\\\.|)\" ) + \"(\\\\.|$)\" ) :\n\t\t\tnull;\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data == null ?\n\t\t\t[ event ] :\n\t\t\tjQuery.makeArray( data, [ event ] );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\tif ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tif ( !rfocusMorph.test( bubbleType + type ) ) {\n\t\t\t\tcur = cur.parentNode;\n\t\t\t}\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push( cur );\n\t\t\t\ttmp = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( tmp === ( elem.ownerDocument || document ) ) {\n\t\t\t\teventPath.push( tmp.defaultView || tmp.parentWindow || window );\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\ti = 0;\n\t\twhile ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {\n\t\t\tlastElement = cur;\n\t\t\tevent.type = i > 1 ?\n\t\t\t\tbubbleType :\n\t\t\t\tspecial.bindType || type;\n\n\t\t\t// jQuery handler\n\t\t\thandle = (\n\t\t\t\t\tdataPriv.get( cur, \"events\" ) || Object.create( null )\n\t\t\t\t)[ event.type ] &&\n\t\t\t\tdataPriv.get( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\t// Native handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && handle.apply && acceptData( cur ) ) {\n\t\t\t\tevent.result = handle.apply( cur, data );\n\t\t\t\tif ( event.result === false ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( ( !special._default ||\n\t\t\t\tspecial._default.apply( eventPath.pop(), data ) === false ) &&\n\t\t\t\tacceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name as the event.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\tif ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\ttmp = elem[ ontype ];\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\n\t\t\t\t\tif ( event.isPropagationStopped() ) {\n\t\t\t\t\t\tlastElement.addEventListener( type, stopPropagationCallback );\n\t\t\t\t\t}\n\n\t\t\t\t\telem[ type ]();\n\n\t\t\t\t\tif ( event.isPropagationStopped() ) {\n\t\t\t\t\t\tlastElement.removeEventListener( type, stopPropagationCallback );\n\t\t\t\t\t}\n\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = tmp;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\t// Piggyback on a donor event to simulate a different one\n\t// Used only for `focus(in | out)` events\n\tsimulate: function( type, elem, event ) {\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{\n\t\t\t\ttype: type,\n\t\t\t\tisSimulated: true\n\t\t\t}\n\t\t);\n\n\t\tjQuery.event.trigger( e, null, elem );\n\t}\n\n} );\n\njQuery.fn.extend( {\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t} );\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tvar elem = this[ 0 ];\n\t\tif ( elem ) {\n\t\t\treturn jQuery.event.trigger( type, data, elem, true );\n\t\t}\n\t}\n} );\n\n\n// Support: Firefox <=44\n// Firefox doesn't have focus(in | out) events\n// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787\n//\n// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1\n// focus(in | out) events fire after focus & blur events,\n// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order\n// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857\nif ( !support.focusin ) {\n\tjQuery.each( { focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler on the document while someone wants focusin/focusout\n\t\tvar handler = function( event ) {\n\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );\n\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\n\t\t\t\t// Handle: regular nodes (via `this.ownerDocument`), window\n\t\t\t\t// (via `this.document`) & document (via `this`).\n\t\t\t\tvar doc = this.ownerDocument || this.document || this,\n\t\t\t\t\tattaches = dataPriv.access( doc, fix );\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t\tdataPriv.access( doc, fix, ( attaches || 0 ) + 1 );\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tvar doc = this.ownerDocument || this.document || this,\n\t\t\t\t\tattaches = dataPriv.access( doc, fix ) - 1;\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.removeEventListener( orig, handler, true );\n\t\t\t\t\tdataPriv.remove( doc, fix );\n\n\t\t\t\t} else {\n\t\t\t\t\tdataPriv.access( doc, fix, attaches );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t} );\n}\nvar location = window.location;\n\nvar nonce = { guid: Date.now() };\n\nvar rquery = ( /\\?/ );\n\n\n\n// Cross-browser xml parsing\njQuery.parseXML = function( data ) {\n\tvar xml;\n\tif ( !data || typeof data !== \"string\" ) {\n\t\treturn null;\n\t}\n\n\t// Support: IE 9 - 11 only\n\t// IE throws on parseFromString with invalid input.\n\ttry {\n\t\txml = ( new window.DOMParser() ).parseFromString( data, \"text/xml\" );\n\t} catch ( e ) {\n\t\txml = undefined;\n\t}\n\n\tif ( !xml || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\tjQuery.error( \"Invalid XML: \" + data );\n\t}\n\treturn xml;\n};\n\n\nvar\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,\n\trsubmittable = /^(?:input|select|textarea|keygen)/i;\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tvar name;\n\n\tif ( Array.isArray( obj ) ) {\n\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\n\t\t\t\t// Item is non-scalar (array or object), encode its numeric index.\n\t\t\t\tbuildParams(\n\t\t\t\t\tprefix + \"[\" + ( typeof v === \"object\" && v != null ? i : \"\" ) + \"]\",\n\t\t\t\t\tv,\n\t\t\t\t\ttraditional,\n\t\t\t\t\tadd\n\t\t\t\t);\n\t\t\t}\n\t\t} );\n\n\t} else if ( !traditional && toType( obj ) === \"object\" ) {\n\n\t\t// Serialize object item.\n\t\tfor ( name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// Serialize an array of form elements or a set of\n// key/values into a query string\njQuery.param = function( a, traditional ) {\n\tvar prefix,\n\t\ts = [],\n\t\tadd = function( key, valueOrFunction ) {\n\n\t\t\t// If value is a function, invoke it and use its return value\n\t\t\tvar value = isFunction( valueOrFunction ) ?\n\t\t\t\tvalueOrFunction() :\n\t\t\t\tvalueOrFunction;\n\n\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" +\n\t\t\t\tencodeURIComponent( value == null ? \"\" : value );\n\t\t};\n\n\tif ( a == null ) {\n\t\treturn \"\";\n\t}\n\n\t// If an array was passed in, assume that it is an array of form elements.\n\tif ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\n\t\t// Serialize the form elements\n\t\tjQuery.each( a, function() {\n\t\t\tadd( this.name, this.value );\n\t\t} );\n\n\t} else {\n\n\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t// did it), otherwise encode params recursively.\n\t\tfor ( prefix in a ) {\n\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t}\n\t}\n\n\t// Return the resulting serialization\n\treturn s.join( \"&\" );\n};\n\njQuery.fn.extend( {\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\tserializeArray: function() {\n\t\treturn this.map( function() {\n\n\t\t\t// Can add propHook for \"elements\" to filter or add form elements\n\t\t\tvar elements = jQuery.prop( this, \"elements\" );\n\t\t\treturn elements ? jQuery.makeArray( elements ) : this;\n\t\t} )\n\t\t.filter( function() {\n\t\t\tvar type = this.type;\n\n\t\t\t// Use .is( \":disabled\" ) so that fieldset[disabled] works\n\t\t\treturn this.name && !jQuery( this ).is( \":disabled\" ) &&\n\t\t\t\trsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&\n\t\t\t\t( this.checked || !rcheckableType.test( type ) );\n\t\t} )\n\t\t.map( function( _i, elem ) {\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\tif ( val == null ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tif ( Array.isArray( val ) ) {\n\t\t\t\treturn jQuery.map( val, function( val ) {\n\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t} ).get();\n\t}\n} );\n\n\nvar\n\tr20 = /%20/g,\n\trhash = /#.*$/,\n\trantiCache = /([?&])_=[^&]*/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)$/mg,\n\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = \"*/\".concat( \"*\" ),\n\n\t// Anchor tag for parsing the document origin\n\toriginAnchor = document.createElement( \"a\" );\n\toriginAnchor.href = location.href;\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tvar dataType,\n\t\t\ti = 0,\n\t\t\tdataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || [];\n\n\t\tif ( isFunction( func ) ) {\n\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\twhile ( ( dataType = dataTypes[ i++ ] ) ) {\n\n\t\t\t\t// Prepend if requested\n\t\t\t\tif ( dataType[ 0 ] === \"+\" ) {\n\t\t\t\t\tdataType = dataType.slice( 1 ) || \"*\";\n\t\t\t\t\t( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );\n\n\t\t\t\t// Otherwise append\n\t\t\t\t} else {\n\t\t\t\t\t( structure[ dataType ] = structure[ dataType ] || [] ).push( func );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {\n\n\tvar inspected = {},\n\t\tseekingTransport = ( structure === transports );\n\n\tfunction inspect( dataType ) {\n\t\tvar selected;\n\t\tinspected[ dataType ] = true;\n\t\tjQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {\n\t\t\tvar dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );\n\t\t\tif ( typeof dataTypeOrTransport === \"string\" &&\n\t\t\t\t!seekingTransport && !inspected[ dataTypeOrTransport ] ) {\n\n\t\t\t\toptions.dataTypes.unshift( dataTypeOrTransport );\n\t\t\t\tinspect( dataTypeOrTransport );\n\t\t\t\treturn false;\n\t\t\t} else if ( seekingTransport ) {\n\t\t\t\treturn !( selected = dataTypeOrTransport );\n\t\t\t}\n\t\t} );\n\t\treturn selected;\n\t}\n\n\treturn inspect( options.dataTypes[ 0 ] ) || !inspected[ \"*\" ] && inspect( \"*\" );\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n\n\treturn target;\n}\n\n/* Handles responses to an ajax request:\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar ct, type, finalDataType, firstDataType,\n\t\tcontents = s.contents,\n\t\tdataTypes = s.dataTypes;\n\n\t// Remove auto dataType and get content-type in the process\n\twhile ( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"Content-Type\" );\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[ 0 ] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n/* Chain conversions given the request and the original response\n * Also sets the responseXXX fields on the jqXHR instance\n */\nfunction ajaxConvert( s, response, jqXHR, isSuccess ) {\n\tvar conv2, current, conv, tmp, prev,\n\t\tconverters = {},\n\n\t\t// Work with a copy of dataTypes in case we need to modify it for conversion\n\t\tdataTypes = s.dataTypes.slice();\n\n\t// Create converters map with lowercased keys\n\tif ( dataTypes[ 1 ] ) {\n\t\tfor ( conv in s.converters ) {\n\t\t\tconverters[ conv.toLowerCase() ] = s.converters[ conv ];\n\t\t}\n\t}\n\n\tcurrent = dataTypes.shift();\n\n\t// Convert to each sequential dataType\n\twhile ( current ) {\n\n\t\tif ( s.responseFields[ current ] ) {\n\t\t\tjqXHR[ s.responseFields[ current ] ] = response;\n\t\t}\n\n\t\t// Apply the dataFilter if provided\n\t\tif ( !prev && isSuccess && s.dataFilter ) {\n\t\t\tresponse = s.dataFilter( response, s.dataType );\n\t\t}\n\n\t\tprev = current;\n\t\tcurrent = dataTypes.shift();\n\n\t\tif ( current ) {\n\n\t\t\t// There's only work to do if current dataType is non-auto\n\t\t\tif ( current === \"*\" ) {\n\n\t\t\t\tcurrent = prev;\n\n\t\t\t// Convert response if prev dataType is non-auto and differs from current\n\t\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t\t// Seek a direct converter\n\t\t\t\tconv = converters[ prev + \" \" + current ] || converters[ \"* \" + current ];\n\n\t\t\t\t// If none found, seek a pair\n\t\t\t\tif ( !conv ) {\n\t\t\t\t\tfor ( conv2 in converters ) {\n\n\t\t\t\t\t\t// If conv2 outputs current\n\t\t\t\t\t\ttmp = conv2.split( \" \" );\n\t\t\t\t\t\tif ( tmp[ 1 ] === current ) {\n\n\t\t\t\t\t\t\t// If prev can be converted to accepted input\n\t\t\t\t\t\t\tconv = converters[ prev + \" \" + tmp[ 0 ] ] ||\n\t\t\t\t\t\t\t\tconverters[ \"* \" + tmp[ 0 ] ];\n\t\t\t\t\t\t\tif ( conv ) {\n\n\t\t\t\t\t\t\t\t// Condense equivalence converters\n\t\t\t\t\t\t\t\tif ( conv === true ) {\n\t\t\t\t\t\t\t\t\tconv = converters[ conv2 ];\n\n\t\t\t\t\t\t\t\t// Otherwise, insert the intermediate dataType\n\t\t\t\t\t\t\t\t} else if ( converters[ conv2 ] !== true ) {\n\t\t\t\t\t\t\t\t\tcurrent = tmp[ 0 ];\n\t\t\t\t\t\t\t\t\tdataTypes.unshift( tmp[ 1 ] );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Apply converter (if not an equivalence)\n\t\t\t\tif ( conv !== true ) {\n\n\t\t\t\t\t// Unless errors are allowed to bubble, catch and return them\n\t\t\t\t\tif ( conv && s.throws ) {\n\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\tstate: \"parsererror\",\n\t\t\t\t\t\t\t\terror: conv ? e : \"No conversion from \" + prev + \" to \" + current\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { state: \"success\", data: response };\n}\n\njQuery.extend( {\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {},\n\n\tajaxSettings: {\n\t\turl: location.href,\n\t\ttype: \"GET\",\n\t\tisLocal: rlocalProtocol.test( location.protocol ),\n\t\tglobal: true,\n\t\tprocessData: true,\n\t\tasync: true,\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\tthrows: false,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\t\"*\": allTypes,\n\t\t\ttext: \"text/plain\",\n\t\t\thtml: \"text/html\",\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\tjson: \"application/json, text/javascript\"\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /\\bxml\\b/,\n\t\t\thtml: /\\bhtml/,\n\t\t\tjson: /\\bjson\\b/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\",\n\t\t\tjson: \"responseJSON\"\n\t\t},\n\n\t\t// Data converters\n\t\t// Keys separate source (or catchall \"*\") and destination types with a single space\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": JSON.parse,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\turl: true,\n\t\t\tcontext: true\n\t\t}\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\treturn settings ?\n\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :\n\n\t\t\t// Extending ajaxSettings\n\t\t\tajaxExtend( jQuery.ajaxSettings, target );\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar transport,\n\n\t\t\t// URL without anti-cache param\n\t\t\tcacheURL,\n\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\n\t\t\t// Url cleanup var\n\t\t\turlAnchor,\n\n\t\t\t// Request state (becomes false upon send and true upon completion)\n\t\t\tcompleted,\n\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\n\t\t\t// Loop variable\n\t\t\ti,\n\n\t\t\t// uncached part of the url\n\t\t\tuncached,\n\n\t\t\t// Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\n\t\t\t// Context for global events is callbackContext if it is a DOM node or jQuery collection\n\t\t\tglobalEventContext = s.context &&\n\t\t\t\t( callbackContext.nodeType || callbackContext.jquery ) ?\n\t\t\t\t\tjQuery( callbackContext ) :\n\t\t\t\t\tjQuery.event,\n\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks( \"once memory\" ),\n\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\n\t\t\t// Default abort message\n\t\t\tstrAbort = \"canceled\",\n\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( completed ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile ( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[ 1 ].toLowerCase() + \" \" ] =\n\t\t\t\t\t\t\t\t\t( responseHeaders[ match[ 1 ].toLowerCase() + \" \" ] || [] )\n\t\t\t\t\t\t\t\t\t\t.concat( match[ 2 ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() + \" \" ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match == null ? null : match.join( \", \" );\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn completed ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tif ( completed == null ) {\n\t\t\t\t\t\tname = requestHeadersNames[ name.toLowerCase() ] =\n\t\t\t\t\t\t\trequestHeadersNames[ name.toLowerCase() ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( completed == null ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Status-dependent callbacks\n\t\t\t\tstatusCode: function( map ) {\n\t\t\t\t\tvar code;\n\t\t\t\t\tif ( map ) {\n\t\t\t\t\t\tif ( completed ) {\n\n\t\t\t\t\t\t\t// Execute the appropriate callbacks\n\t\t\t\t\t\t\tjqXHR.always( map[ jqXHR.status ] );\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t// Lazy-add the new callbacks in a way that preserves old ones\n\t\t\t\t\t\t\tfor ( code in map ) {\n\t\t\t\t\t\t\t\tstatusCode[ code ] = [ statusCode[ code ], map[ code ] ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tvar finalText = statusText || strAbort;\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( finalText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, finalText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR );\n\n\t\t// Add protocol if not provided (prefilters might expect it)\n\t\t// Handle falsy url in the settings object (#10093: consistency with old signature)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url || location.href ) + \"\" )\n\t\t\t.replace( rprotocol, location.protocol + \"//\" );\n\n\t\t// Alias method option to type as per ticket #12004\n\t\ts.type = options.method || options.type || s.method || s.type;\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = ( s.dataType || \"*\" ).toLowerCase().match( rnothtmlwhite ) || [ \"\" ];\n\n\t\t// A cross-domain request is in order when the origin doesn't match the current origin.\n\t\tif ( s.crossDomain == null ) {\n\t\t\turlAnchor = document.createElement( \"a\" );\n\n\t\t\t// Support: IE <=8 - 11, Edge 12 - 15\n\t\t\t// IE throws exception on accessing the href property if url is malformed,\n\t\t\t// e.g. http://example.com:80x/\n\t\t\ttry {\n\t\t\t\turlAnchor.href = s.url;\n\n\t\t\t\t// Support: IE <=8 - 11 only\n\t\t\t\t// Anchor's host property isn't correctly set when s.url is relative\n\t\t\t\turlAnchor.href = urlAnchor.href;\n\t\t\t\ts.crossDomain = originAnchor.protocol + \"//\" + originAnchor.host !==\n\t\t\t\t\turlAnchor.protocol + \"//\" + urlAnchor.host;\n\t\t\t} catch ( e ) {\n\n\t\t\t\t// If there is an error parsing the URL, assume it is crossDomain,\n\t\t\t\t// it can be rejected by the transport if it is invalid\n\t\t\t\ts.crossDomain = true;\n\t\t\t}\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( completed ) {\n\t\t\treturn jqXHR;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\t// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)\n\t\tfireGlobals = jQuery.event && s.global;\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Save the URL in case we're toying with the If-Modified-Since\n\t\t// and/or If-None-Match header later on\n\t\t// Remove hash to simplify url manipulation\n\t\tcacheURL = s.url.replace( rhash, \"\" );\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// Remember the hash so we can put it back\n\t\t\tuncached = s.url.slice( cacheURL.length );\n\n\t\t\t// If data is available and should be processed, append data to url\n\t\t\tif ( s.data && ( s.processData || typeof s.data === \"string\" ) ) {\n\t\t\t\tcacheURL += ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + s.data;\n\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Add or update anti-cache param if needed\n\t\t\tif ( s.cache === false ) {\n\t\t\t\tcacheURL = cacheURL.replace( rantiCache, \"$1\" );\n\t\t\t\tuncached = ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + \"_=\" + ( nonce.guid++ ) +\n\t\t\t\t\tuncached;\n\t\t\t}\n\n\t\t\t// Put hash and anti-cache on the URL that will be requested (gh-1732)\n\t\t\ts.url = cacheURL + uncached;\n\n\t\t// Change '%20' to '+' if this is encoded form body content (gh-2658)\n\t\t} else if ( s.data && s.processData &&\n\t\t\t( s.contentType || \"\" ).indexOf( \"application/x-www-form-urlencoded\" ) === 0 ) {\n\t\t\ts.data = s.data.replace( r20, \"+\" );\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tif ( jQuery.lastModified[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ cacheURL ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ cacheURL ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[ 0 ] ] +\n\t\t\t\t\t( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend &&\n\t\t\t( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) {\n\n\t\t\t// Abort if not done already and return\n\t\t\treturn jqXHR.abort();\n\t\t}\n\n\t\t// Aborting is no longer a cancellation\n\t\tstrAbort = \"abort\";\n\n\t\t// Install callbacks on deferreds\n\t\tcompleteDeferred.add( s.complete );\n\t\tjqXHR.done( s.success );\n\t\tjqXHR.fail( s.error );\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\n\t\t\t// If request was aborted inside ajaxSend, stop there\n\t\t\tif ( completed ) {\n\t\t\t\treturn jqXHR;\n\t\t\t}\n\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = window.setTimeout( function() {\n\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tcompleted = false;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch ( e ) {\n\n\t\t\t\t// Rethrow post-completion exceptions\n\t\t\t\tif ( completed ) {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\n\t\t\t\t// Propagate others as results\n\t\t\t\tdone( -1, e );\n\t\t\t}\n\t\t}\n\n\t\t// Callback for when everything is done\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\t\t\tvar isSuccess, success, error, response, modified,\n\t\t\t\tstatusText = nativeStatusText;\n\n\t\t\t// Ignore repeat invocations\n\t\t\tif ( completed ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tcompleted = true;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\twindow.clearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\t// Determine if successful\n\t\t\tisSuccess = status >= 200 && status < 300 || status === 304;\n\n\t\t\t// Get response data\n\t\t\tif ( responses ) {\n\t\t\t\tresponse = ajaxHandleResponses( s, jqXHR, responses );\n\t\t\t}\n\n\t\t\t// Use a noop converter for missing script\n\t\t\tif ( !isSuccess && jQuery.inArray( \"script\", s.dataTypes ) > -1 ) {\n\t\t\t\ts.converters[ \"text script\" ] = function() {};\n\t\t\t}\n\n\t\t\t// Convert no matter what (that way responseXXX fields are always set)\n\t\t\tresponse = ajaxConvert( s, response, jqXHR, isSuccess );\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( isSuccess ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\t\t\t\t\tmodified = jqXHR.getResponseHeader( \"Last-Modified\" );\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.lastModified[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t\tmodified = jqXHR.getResponseHeader( \"etag\" );\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.etag[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// if no content\n\t\t\t\tif ( status === 204 || s.type === \"HEAD\" ) {\n\t\t\t\t\tstatusText = \"nocontent\";\n\n\t\t\t\t// if not modified\n\t\t\t\t} else if ( status === 304 ) {\n\t\t\t\t\tstatusText = \"notmodified\";\n\n\t\t\t\t// If we have data, let's convert it\n\t\t\t\t} else {\n\t\t\t\t\tstatusText = response.state;\n\t\t\t\t\tsuccess = response.data;\n\t\t\t\t\terror = response.error;\n\t\t\t\t\tisSuccess = !error;\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t// Extract error from statusText and normalize for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( status || !statusText ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = ( nativeStatusText || statusText ) + \"\";\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( isSuccess ? \"ajaxSuccess\" : \"ajaxError\",\n\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t}\n} );\n\njQuery.each( [ \"get\", \"post\" ], function( _i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\n\t\t// Shift arguments if data argument was omitted\n\t\tif ( isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\t// The url can be an options object (which then must have .url)\n\t\treturn jQuery.ajax( jQuery.extend( {\n\t\t\turl: url,\n\t\t\ttype: method,\n\t\t\tdataType: type,\n\t\t\tdata: data,\n\t\t\tsuccess: callback\n\t\t}, jQuery.isPlainObject( url ) && url ) );\n\t};\n} );\n\njQuery.ajaxPrefilter( function( s ) {\n\tvar i;\n\tfor ( i in s.headers ) {\n\t\tif ( i.toLowerCase() === \"content-type\" ) {\n\t\t\ts.contentType = s.headers[ i ] || \"\";\n\t\t}\n\t}\n} );\n\n\njQuery._evalUrl = function( url, options, doc ) {\n\treturn jQuery.ajax( {\n\t\turl: url,\n\n\t\t// Make this explicit, since user can override this through ajaxSetup (#11264)\n\t\ttype: \"GET\",\n\t\tdataType: \"script\",\n\t\tcache: true,\n\t\tasync: false,\n\t\tglobal: false,\n\n\t\t// Only evaluate the response if it is successful (gh-4126)\n\t\t// dataFilter is not invoked for failure responses, so using it instead\n\t\t// of the default converter is kludgy but it works.\n\t\tconverters: {\n\t\t\t\"text script\": function() {}\n\t\t},\n\t\tdataFilter: function( response ) {\n\t\t\tjQuery.globalEval( response, options, doc );\n\t\t}\n\t} );\n};\n\n\njQuery.fn.extend( {\n\twrapAll: function( html ) {\n\t\tvar wrap;\n\n\t\tif ( this[ 0 ] ) {\n\t\t\tif ( isFunction( html ) ) {\n\t\t\t\thtml = html.call( this[ 0 ] );\n\t\t\t}\n\n\t\t\t// The elements to wrap the target around\n\t\t\twrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );\n\n\t\t\tif ( this[ 0 ].parentNode ) {\n\t\t\t\twrap.insertBefore( this[ 0 ] );\n\t\t\t}\n\n\t\t\twrap.map( function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstElementChild ) {\n\t\t\t\t\telem = elem.firstElementChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t} ).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( isFunction( html ) ) {\n\t\t\treturn this.each( function( i ) {\n\t\t\t\tjQuery( this ).wrapInner( html.call( this, i ) );\n\t\t\t} );\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t} );\n\t},\n\n\twrap: function( html ) {\n\t\tvar htmlIsFunction = isFunction( html );\n\n\t\treturn this.each( function( i ) {\n\t\t\tjQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html );\n\t\t} );\n\t},\n\n\tunwrap: function( selector ) {\n\t\tthis.parent( selector ).not( \"body\" ).each( function() {\n\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t} );\n\t\treturn this;\n\t}\n} );\n\n\njQuery.expr.pseudos.hidden = function( elem ) {\n\treturn !jQuery.expr.pseudos.visible( elem );\n};\njQuery.expr.pseudos.visible = function( elem ) {\n\treturn !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );\n};\n\n\n\n\njQuery.ajaxSettings.xhr = function() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch ( e ) {}\n};\n\nvar xhrSuccessStatus = {\n\n\t\t// File protocol always yields status code 0, assume 200\n\t\t0: 200,\n\n\t\t// Support: IE <=9 only\n\t\t// #1450: sometimes IE returns 1223 when it should be 204\n\t\t1223: 204\n\t},\n\txhrSupported = jQuery.ajaxSettings.xhr();\n\nsupport.cors = !!xhrSupported && ( \"withCredentials\" in xhrSupported );\nsupport.ajax = xhrSupported = !!xhrSupported;\n\njQuery.ajaxTransport( function( options ) {\n\tvar callback, errorCallback;\n\n\t// Cross domain only allowed if supported through XMLHttpRequest\n\tif ( support.cors || xhrSupported && !options.crossDomain ) {\n\t\treturn {\n\t\t\tsend: function( headers, complete ) {\n\t\t\t\tvar i,\n\t\t\t\t\txhr = options.xhr();\n\n\t\t\t\txhr.open(\n\t\t\t\t\toptions.type,\n\t\t\t\t\toptions.url,\n\t\t\t\t\toptions.async,\n\t\t\t\t\toptions.username,\n\t\t\t\t\toptions.password\n\t\t\t\t);\n\n\t\t\t\t// Apply custom fields if provided\n\t\t\t\tif ( options.xhrFields ) {\n\t\t\t\t\tfor ( i in options.xhrFields ) {\n\t\t\t\t\t\txhr[ i ] = options.xhrFields[ i ];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Override mime type if needed\n\t\t\t\tif ( options.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\txhr.overrideMimeType( options.mimeType );\n\t\t\t\t}\n\n\t\t\t\t// X-Requested-With header\n\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\tif ( !options.crossDomain && !headers[ \"X-Requested-With\" ] ) {\n\t\t\t\t\theaders[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n\t\t\t\t}\n\n\t\t\t\t// Set headers\n\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t}\n\n\t\t\t\t// Callback\n\t\t\t\tcallback = function( type ) {\n\t\t\t\t\treturn function() {\n\t\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\t\tcallback = errorCallback = xhr.onload =\n\t\t\t\t\t\t\t\txhr.onerror = xhr.onabort = xhr.ontimeout =\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = null;\n\n\t\t\t\t\t\t\tif ( type === \"abort\" ) {\n\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t} else if ( type === \"error\" ) {\n\n\t\t\t\t\t\t\t\t// Support: IE <=9 only\n\t\t\t\t\t\t\t\t// On a manual native abort, IE9 throws\n\t\t\t\t\t\t\t\t// errors on any property access that is not readyState\n\t\t\t\t\t\t\t\tif ( typeof xhr.status !== \"number\" ) {\n\t\t\t\t\t\t\t\t\tcomplete( 0, \"error\" );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcomplete(\n\n\t\t\t\t\t\t\t\t\t\t// File: protocol always yields status 0; see #8605, #14207\n\t\t\t\t\t\t\t\t\t\txhr.status,\n\t\t\t\t\t\t\t\t\t\txhr.statusText\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcomplete(\n\t\t\t\t\t\t\t\t\txhrSuccessStatus[ xhr.status ] || xhr.status,\n\t\t\t\t\t\t\t\t\txhr.statusText,\n\n\t\t\t\t\t\t\t\t\t// Support: IE <=9 only\n\t\t\t\t\t\t\t\t\t// IE9 has no XHR2 but throws on binary (trac-11426)\n\t\t\t\t\t\t\t\t\t// For XHR2 non-text, let the caller handle it (gh-2498)\n\t\t\t\t\t\t\t\t\t( xhr.responseType || \"text\" ) !== \"text\"  ||\n\t\t\t\t\t\t\t\t\ttypeof xhr.responseText !== \"string\" ?\n\t\t\t\t\t\t\t\t\t\t{ binary: xhr.response } :\n\t\t\t\t\t\t\t\t\t\t{ text: xhr.responseText },\n\t\t\t\t\t\t\t\t\txhr.getAllResponseHeaders()\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t};\n\n\t\t\t\t// Listen to events\n\t\t\t\txhr.onload = callback();\n\t\t\t\terrorCallback = xhr.onerror = xhr.ontimeout = callback( \"error\" );\n\n\t\t\t\t// Support: IE 9 only\n\t\t\t\t// Use onreadystatechange to replace onabort\n\t\t\t\t// to handle uncaught aborts\n\t\t\t\tif ( xhr.onabort !== undefined ) {\n\t\t\t\t\txhr.onabort = errorCallback;\n\t\t\t\t} else {\n\t\t\t\t\txhr.onreadystatechange = function() {\n\n\t\t\t\t\t\t// Check readyState before timeout as it changes\n\t\t\t\t\t\tif ( xhr.readyState === 4 ) {\n\n\t\t\t\t\t\t\t// Allow onerror to be called first,\n\t\t\t\t\t\t\t// but that will not handle a native abort\n\t\t\t\t\t\t\t// Also, save errorCallback to a variable\n\t\t\t\t\t\t\t// as xhr.onerror cannot be accessed\n\t\t\t\t\t\t\twindow.setTimeout( function() {\n\t\t\t\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\t\t\t\terrorCallback();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\t// Create the abort callback\n\t\t\t\tcallback = callback( \"abort\" );\n\n\t\t\t\ttry {\n\n\t\t\t\t\t// Do send the request (this may raise an exception)\n\t\t\t\t\txhr.send( options.hasContent && options.data || null );\n\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t// #14683: Only rethrow if this hasn't been notified as an error yet\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n} );\n\n\n\n\n// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432)\njQuery.ajaxPrefilter( function( s ) {\n\tif ( s.crossDomain ) {\n\t\ts.contents.script = false;\n\t}\n} );\n\n// Install script dataType\njQuery.ajaxSetup( {\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, \" +\n\t\t\t\"application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /\\b(?:java|ecma)script\\b/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n} );\n\n// Handle cache's special case and crossDomain\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t}\n} );\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function( s ) {\n\n\t// This transport only deals with cross domain or forced-by-attrs requests\n\tif ( s.crossDomain || s.scriptAttrs ) {\n\t\tvar script, callback;\n\t\treturn {\n\t\t\tsend: function( _, complete ) {\n\t\t\t\tscript = jQuery( \"<script>\" )\n\t\t\t\t\t.attr( s.scriptAttrs || {} )\n\t\t\t\t\t.prop( { charset: s.scriptCharset, src: s.url } )\n\t\t\t\t\t.on( \"load error\", callback = function( evt ) {\n\t\t\t\t\t\tscript.remove();\n\t\t\t\t\t\tcallback = null;\n\t\t\t\t\t\tif ( evt ) {\n\t\t\t\t\t\t\tcomplete( evt.type === \"error\" ? 404 : 200, evt.type );\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\n\t\t\t\t// Use native DOM manipulation to avoid our domManip AJAX trickery\n\t\t\t\tdocument.head.appendChild( script[ 0 ] );\n\t\t\t},\n\t\t\tabort: function() {\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n} );\n\n\n\n\nvar oldCallbacks = [],\n\trjsonp = /(=)\\?(?=&|$)|\\?\\?/;\n\n// Default jsonp settings\njQuery.ajaxSetup( {\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\tvar callback = oldCallbacks.pop() || ( jQuery.expando + \"_\" + ( nonce.guid++ ) );\n\t\tthis[ callback ] = true;\n\t\treturn callback;\n\t}\n} );\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar callbackName, overwritten, responseContainer,\n\t\tjsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?\n\t\t\t\"url\" :\n\t\t\ttypeof s.data === \"string\" &&\n\t\t\t\t( s.contentType || \"\" )\n\t\t\t\t\t.indexOf( \"application/x-www-form-urlencoded\" ) === 0 &&\n\t\t\t\trjsonp.test( s.data ) && \"data\"\n\t\t);\n\n\t// Handle iff the expected data type is \"jsonp\" or we have a parameter to set\n\tif ( jsonProp || s.dataTypes[ 0 ] === \"jsonp\" ) {\n\n\t\t// Get callback name, remembering preexisting value associated with it\n\t\tcallbackName = s.jsonpCallback = isFunction( s.jsonpCallback ) ?\n\t\t\ts.jsonpCallback() :\n\t\t\ts.jsonpCallback;\n\n\t\t// Insert callback into url or form data\n\t\tif ( jsonProp ) {\n\t\t\ts[ jsonProp ] = s[ jsonProp ].replace( rjsonp, \"$1\" + callbackName );\n\t\t} else if ( s.jsonp !== false ) {\n\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.jsonp + \"=\" + callbackName;\n\t\t}\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[ \"script json\" ] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( callbackName + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// Force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Install callback\n\t\toverwritten = window[ callbackName ];\n\t\twindow[ callbackName ] = function() {\n\t\t\tresponseContainer = arguments;\n\t\t};\n\n\t\t// Clean-up function (fires after converters)\n\t\tjqXHR.always( function() {\n\n\t\t\t// If previous value didn't exist - remove it\n\t\t\tif ( overwritten === undefined ) {\n\t\t\t\tjQuery( window ).removeProp( callbackName );\n\n\t\t\t// Otherwise restore preexisting value\n\t\t\t} else {\n\t\t\t\twindow[ callbackName ] = overwritten;\n\t\t\t}\n\n\t\t\t// Save back as free\n\t\t\tif ( s[ callbackName ] ) {\n\n\t\t\t\t// Make sure that re-using the options doesn't screw things around\n\t\t\t\ts.jsonpCallback = originalSettings.jsonpCallback;\n\n\t\t\t\t// Save the callback name for future use\n\t\t\t\toldCallbacks.push( callbackName );\n\t\t\t}\n\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && isFunction( overwritten ) ) {\n\t\t\t\toverwritten( responseContainer[ 0 ] );\n\t\t\t}\n\n\t\t\tresponseContainer = overwritten = undefined;\n\t\t} );\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n} );\n\n\n\n\n// Support: Safari 8 only\n// In Safari 8 documents created via document.implementation.createHTMLDocument\n// collapse sibling forms: the second one becomes a child of the first one.\n// Because of that, this security measure has to be disabled in Safari 8.\n// https://bugs.webkit.org/show_bug.cgi?id=137337\nsupport.createHTMLDocument = ( function() {\n\tvar body = document.implementation.createHTMLDocument( \"\" ).body;\n\tbody.innerHTML = \"<form></form><form></form>\";\n\treturn body.childNodes.length === 2;\n} )();\n\n\n// Argument \"data\" should be string of html\n// context (optional): If specified, the fragment will be created in this context,\n// defaults to document\n// keepScripts (optional): If true, will include scripts passed in the html string\njQuery.parseHTML = function( data, context, keepScripts ) {\n\tif ( typeof data !== \"string\" ) {\n\t\treturn [];\n\t}\n\tif ( typeof context === \"boolean\" ) {\n\t\tkeepScripts = context;\n\t\tcontext = false;\n\t}\n\n\tvar base, parsed, scripts;\n\n\tif ( !context ) {\n\n\t\t// Stop scripts or inline event handlers from being executed immediately\n\t\t// by using document.implementation\n\t\tif ( support.createHTMLDocument ) {\n\t\t\tcontext = document.implementation.createHTMLDocument( \"\" );\n\n\t\t\t// Set the base href for the created document\n\t\t\t// so any parsed elements with URLs\n\t\t\t// are based on the document's URL (gh-2965)\n\t\t\tbase = context.createElement( \"base\" );\n\t\t\tbase.href = document.location.href;\n\t\t\tcontext.head.appendChild( base );\n\t\t} else {\n\t\t\tcontext = document;\n\t\t}\n\t}\n\n\tparsed = rsingleTag.exec( data );\n\tscripts = !keepScripts && [];\n\n\t// Single tag\n\tif ( parsed ) {\n\t\treturn [ context.createElement( parsed[ 1 ] ) ];\n\t}\n\n\tparsed = buildFragment( [ data ], context, scripts );\n\n\tif ( scripts && scripts.length ) {\n\t\tjQuery( scripts ).remove();\n\t}\n\n\treturn jQuery.merge( [], parsed.childNodes );\n};\n\n\n/**\n * Load a url into a page\n */\njQuery.fn.load = function( url, params, callback ) {\n\tvar selector, type, response,\n\t\tself = this,\n\t\toff = url.indexOf( \" \" );\n\n\tif ( off > -1 ) {\n\t\tselector = stripAndCollapse( url.slice( off ) );\n\t\turl = url.slice( 0, off );\n\t}\n\n\t// If it's a function\n\tif ( isFunction( params ) ) {\n\n\t\t// We assume that it's the callback\n\t\tcallback = params;\n\t\tparams = undefined;\n\n\t// Otherwise, build a param string\n\t} else if ( params && typeof params === \"object\" ) {\n\t\ttype = \"POST\";\n\t}\n\n\t// If we have elements to modify, make the request\n\tif ( self.length > 0 ) {\n\t\tjQuery.ajax( {\n\t\t\turl: url,\n\n\t\t\t// If \"type\" variable is undefined, then \"GET\" method will be used.\n\t\t\t// Make value of this field explicit since\n\t\t\t// user can override it through ajaxSetup method\n\t\t\ttype: type || \"GET\",\n\t\t\tdataType: \"html\",\n\t\t\tdata: params\n\t\t} ).done( function( responseText ) {\n\n\t\t\t// Save response for use in complete callback\n\t\t\tresponse = arguments;\n\n\t\t\tself.html( selector ?\n\n\t\t\t\t// If a selector was specified, locate the right elements in a dummy div\n\t\t\t\t// Exclude scripts to avoid IE 'Permission Denied' errors\n\t\t\t\tjQuery( \"<div>\" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :\n\n\t\t\t\t// Otherwise use the full result\n\t\t\t\tresponseText );\n\n\t\t// If the request succeeds, this function gets \"data\", \"status\", \"jqXHR\"\n\t\t// but they are ignored because response was set above.\n\t\t// If it fails, this function gets \"jqXHR\", \"status\", \"error\"\n\t\t} ).always( callback && function( jqXHR, status ) {\n\t\t\tself.each( function() {\n\t\t\t\tcallback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );\n\t\t\t} );\n\t\t} );\n\t}\n\n\treturn this;\n};\n\n\n\n\njQuery.expr.pseudos.animated = function( elem ) {\n\treturn jQuery.grep( jQuery.timers, function( fn ) {\n\t\treturn elem === fn.elem;\n\t} ).length;\n};\n\n\n\n\njQuery.offset = {\n\tsetOffset: function( elem, options, i ) {\n\t\tvar curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,\n\t\t\tposition = jQuery.css( elem, \"position\" ),\n\t\t\tcurElem = jQuery( elem ),\n\t\t\tprops = {};\n\n\t\t// Set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tcurOffset = curElem.offset();\n\t\tcurCSSTop = jQuery.css( elem, \"top\" );\n\t\tcurCSSLeft = jQuery.css( elem, \"left\" );\n\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) &&\n\t\t\t( curCSSTop + curCSSLeft ).indexOf( \"auto\" ) > -1;\n\n\t\t// Need to be able to calculate position if either\n\t\t// top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( isFunction( options ) ) {\n\n\t\t\t// Use jQuery.extend here to allow modification of coordinates argument (gh-1848)\n\t\t\toptions = options.call( elem, i, jQuery.extend( {}, curOffset ) );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\n\t\t} else {\n\t\t\tif ( typeof props.top === \"number\" ) {\n\t\t\t\tprops.top += \"px\";\n\t\t\t}\n\t\t\tif ( typeof props.left === \"number\" ) {\n\t\t\t\tprops.left += \"px\";\n\t\t\t}\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\njQuery.fn.extend( {\n\n\t// offset() relates an element's border box to the document origin\n\toffset: function( options ) {\n\n\t\t// Preserve chaining for setter\n\t\tif ( arguments.length ) {\n\t\t\treturn options === undefined ?\n\t\t\t\tthis :\n\t\t\t\tthis.each( function( i ) {\n\t\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t\t} );\n\t\t}\n\n\t\tvar rect, win,\n\t\t\telem = this[ 0 ];\n\n\t\tif ( !elem ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Return zeros for disconnected and hidden (display: none) elements (gh-2310)\n\t\t// Support: IE <=11 only\n\t\t// Running getBoundingClientRect on a\n\t\t// disconnected node in IE throws an error\n\t\tif ( !elem.getClientRects().length ) {\n\t\t\treturn { top: 0, left: 0 };\n\t\t}\n\n\t\t// Get document-relative position by adding viewport scroll to viewport-relative gBCR\n\t\trect = elem.getBoundingClientRect();\n\t\twin = elem.ownerDocument.defaultView;\n\t\treturn {\n\t\t\ttop: rect.top + win.pageYOffset,\n\t\t\tleft: rect.left + win.pageXOffset\n\t\t};\n\t},\n\n\t// position() relates an element's margin box to its offset parent's padding box\n\t// This corresponds to the behavior of CSS absolute positioning\n\tposition: function() {\n\t\tif ( !this[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar offsetParent, offset, doc,\n\t\t\telem = this[ 0 ],\n\t\t\tparentOffset = { top: 0, left: 0 };\n\n\t\t// position:fixed elements are offset from the viewport, which itself always has zero offset\n\t\tif ( jQuery.css( elem, \"position\" ) === \"fixed\" ) {\n\n\t\t\t// Assume position:fixed implies availability of getBoundingClientRect\n\t\t\toffset = elem.getBoundingClientRect();\n\n\t\t} else {\n\t\t\toffset = this.offset();\n\n\t\t\t// Account for the *real* offset parent, which can be the document or its root element\n\t\t\t// when a statically positioned element is identified\n\t\t\tdoc = elem.ownerDocument;\n\t\t\toffsetParent = elem.offsetParent || doc.documentElement;\n\t\t\twhile ( offsetParent &&\n\t\t\t\t( offsetParent === doc.body || offsetParent === doc.documentElement ) &&\n\t\t\t\tjQuery.css( offsetParent, \"position\" ) === \"static\" ) {\n\n\t\t\t\toffsetParent = offsetParent.parentNode;\n\t\t\t}\n\t\t\tif ( offsetParent && offsetParent !== elem && offsetParent.nodeType === 1 ) {\n\n\t\t\t\t// Incorporate borders into its offset, since they are outside its content origin\n\t\t\t\tparentOffset = jQuery( offsetParent ).offset();\n\t\t\t\tparentOffset.top += jQuery.css( offsetParent, \"borderTopWidth\", true );\n\t\t\t\tparentOffset.left += jQuery.css( offsetParent, \"borderLeftWidth\", true );\n\t\t\t}\n\t\t}\n\n\t\t// Subtract parent offsets and element margins\n\t\treturn {\n\t\t\ttop: offset.top - parentOffset.top - jQuery.css( elem, \"marginTop\", true ),\n\t\t\tleft: offset.left - parentOffset.left - jQuery.css( elem, \"marginLeft\", true )\n\t\t};\n\t},\n\n\t// This method will return documentElement in the following cases:\n\t// 1) For the element inside the iframe without offsetParent, this method will return\n\t//    documentElement of the parent window\n\t// 2) For the hidden or detached element\n\t// 3) For body or html element, i.e. in case of the html node - it will return itself\n\t//\n\t// but those exceptions were never presented as a real life use-cases\n\t// and might be considered as more preferable results.\n\t//\n\t// This logic, however, is not guaranteed and can change at any point in the future\n\toffsetParent: function() {\n\t\treturn this.map( function() {\n\t\t\tvar offsetParent = this.offsetParent;\n\n\t\t\twhile ( offsetParent && jQuery.css( offsetParent, \"position\" ) === \"static\" ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\n\t\t\treturn offsetParent || documentElement;\n\t\t} );\n\t}\n} );\n\n// Create scrollLeft and scrollTop methods\njQuery.each( { scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\" }, function( method, prop ) {\n\tvar top = \"pageYOffset\" === prop;\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn access( this, function( elem, method, val ) {\n\n\t\t\t// Coalesce documents and windows\n\t\t\tvar win;\n\t\t\tif ( isWindow( elem ) ) {\n\t\t\t\twin = elem;\n\t\t\t} else if ( elem.nodeType === 9 ) {\n\t\t\t\twin = elem.defaultView;\n\t\t\t}\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? win[ prop ] : elem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : win.pageXOffset,\n\t\t\t\t\ttop ? val : win.pageYOffset\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length );\n\t};\n} );\n\n// Support: Safari <=7 - 9.1, Chrome <=37 - 49\n// Add the top/left cssHooks using jQuery.fn.position\n// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084\n// Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347\n// getComputedStyle returns percent when specified for top/left/bottom/right;\n// rather than make the css module depend on the offset module, just check for it here\njQuery.each( [ \"top\", \"left\" ], function( _i, prop ) {\n\tjQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,\n\t\tfunction( elem, computed ) {\n\t\t\tif ( computed ) {\n\t\t\t\tcomputed = curCSS( elem, prop );\n\n\t\t\t\t// If curCSS returns percentage, fallback to offset\n\t\t\t\treturn rnumnonpx.test( computed ) ?\n\t\t\t\t\tjQuery( elem ).position()[ prop ] + \"px\" :\n\t\t\t\t\tcomputed;\n\t\t\t}\n\t\t}\n\t);\n} );\n\n\n// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tjQuery.each( { padding: \"inner\" + name, content: type, \"\": \"outer\" + name },\n\t\tfunction( defaultExtra, funcName ) {\n\n\t\t// Margin is only for outerHeight, outerWidth\n\t\tjQuery.fn[ funcName ] = function( margin, value ) {\n\t\t\tvar chainable = arguments.length && ( defaultExtra || typeof margin !== \"boolean\" ),\n\t\t\t\textra = defaultExtra || ( margin === true || value === true ? \"margin\" : \"border\" );\n\n\t\t\treturn access( this, function( elem, type, value ) {\n\t\t\t\tvar doc;\n\n\t\t\t\tif ( isWindow( elem ) ) {\n\n\t\t\t\t\t// $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)\n\t\t\t\t\treturn funcName.indexOf( \"outer\" ) === 0 ?\n\t\t\t\t\t\telem[ \"inner\" + name ] :\n\t\t\t\t\t\telem.document.documentElement[ \"client\" + name ];\n\t\t\t\t}\n\n\t\t\t\t// Get document width or height\n\t\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],\n\t\t\t\t\t// whichever is greatest\n\t\t\t\t\treturn Math.max(\n\t\t\t\t\t\telem.body[ \"scroll\" + name ], doc[ \"scroll\" + name ],\n\t\t\t\t\t\telem.body[ \"offset\" + name ], doc[ \"offset\" + name ],\n\t\t\t\t\t\tdoc[ \"client\" + name ]\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn value === undefined ?\n\n\t\t\t\t\t// Get width or height on the element, requesting but not forcing parseFloat\n\t\t\t\t\tjQuery.css( elem, type, extra ) :\n\n\t\t\t\t\t// Set width or height on the element\n\t\t\t\t\tjQuery.style( elem, type, value, extra );\n\t\t\t}, type, chainable ? margin : undefined, chainable );\n\t\t};\n\t} );\n} );\n\n\njQuery.each( [\n\t\"ajaxStart\",\n\t\"ajaxStop\",\n\t\"ajaxComplete\",\n\t\"ajaxError\",\n\t\"ajaxSuccess\",\n\t\"ajaxSend\"\n], function( _i, type ) {\n\tjQuery.fn[ type ] = function( fn ) {\n\t\treturn this.on( type, fn );\n\t};\n} );\n\n\n\n\njQuery.fn.extend( {\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length === 1 ?\n\t\t\tthis.off( selector, \"**\" ) :\n\t\t\tthis.off( types, selector || \"**\", fn );\n\t},\n\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n} );\n\njQuery.each( ( \"blur focus focusin focusout resize scroll click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup contextmenu\" ).split( \" \" ),\n\tfunction( _i, name ) {\n\n\t\t// Handle event binding\n\t\tjQuery.fn[ name ] = function( data, fn ) {\n\t\t\treturn arguments.length > 0 ?\n\t\t\t\tthis.on( name, null, data, fn ) :\n\t\t\t\tthis.trigger( name );\n\t\t};\n\t} );\n\n\n\n\n// Support: Android <=4.0 only\n// Make sure we trim BOM and NBSP\nvar rtrim = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g;\n\n// Bind a function to a context, optionally partially applying any\n// arguments.\n// jQuery.proxy is deprecated to promote standards (specifically Function#bind)\n// However, it is not slated for removal any time soon\njQuery.proxy = function( fn, context ) {\n\tvar tmp, args, proxy;\n\n\tif ( typeof context === \"string\" ) {\n\t\ttmp = fn[ context ];\n\t\tcontext = fn;\n\t\tfn = tmp;\n\t}\n\n\t// Quick check to determine if target is callable, in the spec\n\t// this throws a TypeError, but we will just return undefined.\n\tif ( !isFunction( fn ) ) {\n\t\treturn undefined;\n\t}\n\n\t// Simulated bind\n\targs = slice.call( arguments, 2 );\n\tproxy = function() {\n\t\treturn fn.apply( context || this, args.concat( slice.call( arguments ) ) );\n\t};\n\n\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\tproxy.guid = fn.guid = fn.guid || jQuery.guid++;\n\n\treturn proxy;\n};\n\njQuery.holdReady = function( hold ) {\n\tif ( hold ) {\n\t\tjQuery.readyWait++;\n\t} else {\n\t\tjQuery.ready( true );\n\t}\n};\njQuery.isArray = Array.isArray;\njQuery.parseJSON = JSON.parse;\njQuery.nodeName = nodeName;\njQuery.isFunction = isFunction;\njQuery.isWindow = isWindow;\njQuery.camelCase = camelCase;\njQuery.type = toType;\n\njQuery.now = Date.now;\n\njQuery.isNumeric = function( obj ) {\n\n\t// As of jQuery 3.0, isNumeric is limited to\n\t// strings and numbers (primitives or objects)\n\t// that can be coerced to finite numbers (gh-2662)\n\tvar type = jQuery.type( obj );\n\treturn ( type === \"number\" || type === \"string\" ) &&\n\n\t\t// parseFloat NaNs numeric-cast false positives (\"\")\n\t\t// ...but misinterprets leading-number strings, particularly hex literals (\"0x...\")\n\t\t// subtraction forces infinities to NaN\n\t\t!isNaN( obj - parseFloat( obj ) );\n};\n\njQuery.trim = function( text ) {\n\treturn text == null ?\n\t\t\"\" :\n\t\t( text + \"\" ).replace( rtrim, \"\" );\n};\n\n\n\n// Register as a named AMD module, since jQuery can be concatenated with other\n// files that may use define, but not via a proper concatenation script that\n// understands anonymous AMD modules. A named AMD is safest and most robust\n// way to register. Lowercase jquery is used because AMD module names are\n// derived from file names, and jQuery is normally delivered in a lowercase\n// file name. Do this after creating the global so that if an AMD module wants\n// to call noConflict to hide this version of jQuery, it will work.\n\n// Note that for maximum portability, libraries that are not jQuery should\n// declare themselves as anonymous modules, and avoid setting a global if an\n// AMD loader is present. jQuery is a special case. For more information, see\n// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon\n\nif ( typeof define === \"function\" && define.amd ) {\n\tdefine( \"jquery\", [], function() {\n\t\treturn jQuery;\n\t} );\n}\n\n\n\n\nvar\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$;\n\njQuery.noConflict = function( deep ) {\n\tif ( window.$ === jQuery ) {\n\t\twindow.$ = _$;\n\t}\n\n\tif ( deep && window.jQuery === jQuery ) {\n\t\twindow.jQuery = _jQuery;\n\t}\n\n\treturn jQuery;\n};\n\n// Expose jQuery and $ identifiers, even in AMD\n// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)\n// and CommonJS for browser emulators (#13566)\nif ( typeof noGlobal === \"undefined\" ) {\n\twindow.jQuery = window.$ = jQuery;\n}\n\n\n\n\nreturn jQuery;\n} );\n"
  },
  {
    "path": "src/IdentityServer/wwwroot/lib/jquery/dist/jquery.slim.js",
    "content": "/*!\n * jQuery JavaScript Library v3.5.1 -ajax,-ajax/jsonp,-ajax/load,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-deprecated/ajax-event-alias,-effects,-effects/Tween,-effects/animatedSelector\n * https://jquery.com/\n *\n * Includes Sizzle.js\n * https://sizzlejs.com/\n *\n * Copyright JS Foundation and other contributors\n * Released under the MIT license\n * https://jquery.org/license\n *\n * Date: 2020-05-04T22:49Z\n */\n( function( global, factory ) {\n\n\t\"use strict\";\n\n\tif ( typeof module === \"object\" && typeof module.exports === \"object\" ) {\n\n\t\t// For CommonJS and CommonJS-like environments where a proper `window`\n\t\t// is present, execute the factory and get jQuery.\n\t\t// For environments that do not have a `window` with a `document`\n\t\t// (such as Node.js), expose a factory as module.exports.\n\t\t// This accentuates the need for the creation of a real `window`.\n\t\t// e.g. var jQuery = require(\"jquery\")(window);\n\t\t// See ticket #14549 for more info.\n\t\tmodule.exports = global.document ?\n\t\t\tfactory( global, true ) :\n\t\t\tfunction( w ) {\n\t\t\t\tif ( !w.document ) {\n\t\t\t\t\tthrow new Error( \"jQuery requires a window with a document\" );\n\t\t\t\t}\n\t\t\t\treturn factory( w );\n\t\t\t};\n\t} else {\n\t\tfactory( global );\n\t}\n\n// Pass this if window is not defined yet\n} )( typeof window !== \"undefined\" ? window : this, function( window, noGlobal ) {\n\n// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1\n// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode\n// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common\n// enough that all such attempts are guarded in a try block.\n\"use strict\";\n\nvar arr = [];\n\nvar getProto = Object.getPrototypeOf;\n\nvar slice = arr.slice;\n\nvar flat = arr.flat ? function( array ) {\n\treturn arr.flat.call( array );\n} : function( array ) {\n\treturn arr.concat.apply( [], array );\n};\n\n\nvar push = arr.push;\n\nvar indexOf = arr.indexOf;\n\nvar class2type = {};\n\nvar toString = class2type.toString;\n\nvar hasOwn = class2type.hasOwnProperty;\n\nvar fnToString = hasOwn.toString;\n\nvar ObjectFunctionString = fnToString.call( Object );\n\nvar support = {};\n\nvar isFunction = function isFunction( obj ) {\n\n      // Support: Chrome <=57, Firefox <=52\n      // In some browsers, typeof returns \"function\" for HTML <object> elements\n      // (i.e., `typeof document.createElement( \"object\" ) === \"function\"`).\n      // We don't want to classify *any* DOM node as a function.\n      return typeof obj === \"function\" && typeof obj.nodeType !== \"number\";\n  };\n\n\nvar isWindow = function isWindow( obj ) {\n\t\treturn obj != null && obj === obj.window;\n\t};\n\n\nvar document = window.document;\n\n\n\n\tvar preservedScriptAttributes = {\n\t\ttype: true,\n\t\tsrc: true,\n\t\tnonce: true,\n\t\tnoModule: true\n\t};\n\n\tfunction DOMEval( code, node, doc ) {\n\t\tdoc = doc || document;\n\n\t\tvar i, val,\n\t\t\tscript = doc.createElement( \"script\" );\n\n\t\tscript.text = code;\n\t\tif ( node ) {\n\t\t\tfor ( i in preservedScriptAttributes ) {\n\n\t\t\t\t// Support: Firefox 64+, Edge 18+\n\t\t\t\t// Some browsers don't support the \"nonce\" property on scripts.\n\t\t\t\t// On the other hand, just using `getAttribute` is not enough as\n\t\t\t\t// the `nonce` attribute is reset to an empty string whenever it\n\t\t\t\t// becomes browsing-context connected.\n\t\t\t\t// See https://github.com/whatwg/html/issues/2369\n\t\t\t\t// See https://html.spec.whatwg.org/#nonce-attributes\n\t\t\t\t// The `node.getAttribute` check was added for the sake of\n\t\t\t\t// `jQuery.globalEval` so that it can fake a nonce-containing node\n\t\t\t\t// via an object.\n\t\t\t\tval = node[ i ] || node.getAttribute && node.getAttribute( i );\n\t\t\t\tif ( val ) {\n\t\t\t\t\tscript.setAttribute( i, val );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tdoc.head.appendChild( script ).parentNode.removeChild( script );\n\t}\n\n\nfunction toType( obj ) {\n\tif ( obj == null ) {\n\t\treturn obj + \"\";\n\t}\n\n\t// Support: Android <=2.3 only (functionish RegExp)\n\treturn typeof obj === \"object\" || typeof obj === \"function\" ?\n\t\tclass2type[ toString.call( obj ) ] || \"object\" :\n\t\ttypeof obj;\n}\n/* global Symbol */\n// Defining this global in .eslintrc.json would create a danger of using the global\n// unguarded in another place, it seems safer to define global only for this module\n\n\n\nvar\n\tversion = \"3.5.1 -ajax,-ajax/jsonp,-ajax/load,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-deprecated/ajax-event-alias,-effects,-effects/Tween,-effects/animatedSelector\",\n\n\t// Define a local copy of jQuery\n\tjQuery = function( selector, context ) {\n\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\t// Need init if jQuery is called (just allow error to be thrown if not included)\n\t\treturn new jQuery.fn.init( selector, context );\n\t};\n\njQuery.fn = jQuery.prototype = {\n\n\t// The current version of jQuery being used\n\tjquery: version,\n\n\tconstructor: jQuery,\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\ttoArray: function() {\n\t\treturn slice.call( this );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\n\t\t// Return all the elements in a clean array\n\t\tif ( num == null ) {\n\t\t\treturn slice.call( this );\n\t\t}\n\n\t\t// Return just the one element from the set\n\t\treturn num < 0 ? this[ num + this.length ] : this[ num ];\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems ) {\n\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = jQuery.merge( this.constructor(), elems );\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\teach: function( callback ) {\n\t\treturn jQuery.each( this, callback );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map( this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t} ) );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ) );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\teven: function() {\n\t\treturn this.pushStack( jQuery.grep( this, function( _elem, i ) {\n\t\t\treturn ( i + 1 ) % 2;\n\t\t} ) );\n\t},\n\n\todd: function() {\n\t\treturn this.pushStack( jQuery.grep( this, function( _elem, i ) {\n\t\t\treturn i % 2;\n\t\t} ) );\n\t},\n\n\teq: function( i ) {\n\t\tvar len = this.length,\n\t\t\tj = +i + ( i < 0 ? len : 0 );\n\t\treturn this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor();\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: arr.sort,\n\tsplice: arr.splice\n};\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[ 0 ] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\n\t\t// Skip the boolean and the target\n\t\ttarget = arguments[ i ] || {};\n\t\ti++;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !isFunction( target ) ) {\n\t\ttarget = {};\n\t}\n\n\t// Extend jQuery itself if only one argument is passed\n\tif ( i === length ) {\n\t\ttarget = this;\n\t\ti--;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\n\t\t// Only deal with non-null/undefined values\n\t\tif ( ( options = arguments[ i ] ) != null ) {\n\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent Object.prototype pollution\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( name === \"__proto__\" || target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject( copy ) ||\n\t\t\t\t\t( copyIsArray = Array.isArray( copy ) ) ) ) {\n\t\t\t\t\tsrc = target[ name ];\n\n\t\t\t\t\t// Ensure proper type for the source value\n\t\t\t\t\tif ( copyIsArray && !Array.isArray( src ) ) {\n\t\t\t\t\t\tclone = [];\n\t\t\t\t\t} else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) {\n\t\t\t\t\t\tclone = {};\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src;\n\t\t\t\t\t}\n\t\t\t\t\tcopyIsArray = false;\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend( {\n\n\t// Unique for each copy of jQuery on the page\n\texpando: \"jQuery\" + ( version + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// Assume jQuery is ready without the ready module\n\tisReady: true,\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tnoop: function() {},\n\n\tisPlainObject: function( obj ) {\n\t\tvar proto, Ctor;\n\n\t\t// Detect obvious negatives\n\t\t// Use toString instead of jQuery.type to catch host objects\n\t\tif ( !obj || toString.call( obj ) !== \"[object Object]\" ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tproto = getProto( obj );\n\n\t\t// Objects with no prototype (e.g., `Object.create( null )`) are plain\n\t\tif ( !proto ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Objects with prototype are plain iff they were constructed by a global Object function\n\t\tCtor = hasOwn.call( proto, \"constructor\" ) && proto.constructor;\n\t\treturn typeof Ctor === \"function\" && fnToString.call( Ctor ) === ObjectFunctionString;\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tvar name;\n\n\t\tfor ( name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\t// Evaluates a script in a provided context; falls back to the global one\n\t// if not specified.\n\tglobalEval: function( code, options, doc ) {\n\t\tDOMEval( code, { nonce: options && options.nonce }, doc );\n\t},\n\n\teach: function( obj, callback ) {\n\t\tvar length, i = 0;\n\n\t\tif ( isArrayLike( obj ) ) {\n\t\t\tlength = obj.length;\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor ( i in obj ) {\n\t\t\t\tif ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn obj;\n\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( arr, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( arr != null ) {\n\t\t\tif ( isArrayLike( Object( arr ) ) ) {\n\t\t\t\tjQuery.merge( ret,\n\t\t\t\t\ttypeof arr === \"string\" ?\n\t\t\t\t\t[ arr ] : arr\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tpush.call( ret, arr );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, arr, i ) {\n\t\treturn arr == null ? -1 : indexOf.call( arr, elem, i );\n\t},\n\n\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t// push.apply(_, arraylike) throws on ancient WebKit\n\tmerge: function( first, second ) {\n\t\tvar len = +second.length,\n\t\t\tj = 0,\n\t\t\ti = first.length;\n\n\t\tfor ( ; j < len; j++ ) {\n\t\t\tfirst[ i++ ] = second[ j ];\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, invert ) {\n\t\tvar callbackInverse,\n\t\t\tmatches = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tcallbackExpect = !invert;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( ; i < length; i++ ) {\n\t\t\tcallbackInverse = !callback( elems[ i ], i );\n\t\t\tif ( callbackInverse !== callbackExpect ) {\n\t\t\t\tmatches.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn matches;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar length, value,\n\t\t\ti = 0,\n\t\t\tret = [];\n\n\t\t// Go through the array, translating each of the items to their new values\n\t\tif ( isArrayLike( elems ) ) {\n\t\t\tlength = elems.length;\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( i in elems ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn flat( ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// jQuery.support is not used in Core but other projects attach their\n\t// properties to it so it needs to exist.\n\tsupport: support\n} );\n\nif ( typeof Symbol === \"function\" ) {\n\tjQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];\n}\n\n// Populate the class2type map\njQuery.each( \"Boolean Number String Function Array Date RegExp Object Error Symbol\".split( \" \" ),\nfunction( _i, name ) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n} );\n\nfunction isArrayLike( obj ) {\n\n\t// Support: real iOS 8.2 only (not reproducible in simulator)\n\t// `in` check used to prevent JIT error (gh-2145)\n\t// hasOwn isn't used here due to false negatives\n\t// regarding Nodelist length in IE\n\tvar length = !!obj && \"length\" in obj && obj.length,\n\t\ttype = toType( obj );\n\n\tif ( isFunction( obj ) || isWindow( obj ) ) {\n\t\treturn false;\n\t}\n\n\treturn type === \"array\" || length === 0 ||\n\t\ttypeof length === \"number\" && length > 0 && ( length - 1 ) in obj;\n}\nvar Sizzle =\n/*!\n * Sizzle CSS Selector Engine v2.3.5\n * https://sizzlejs.com/\n *\n * Copyright JS Foundation and other contributors\n * Released under the MIT license\n * https://js.foundation/\n *\n * Date: 2020-03-14\n */\n( function( window ) {\nvar i,\n\tsupport,\n\tExpr,\n\tgetText,\n\tisXML,\n\ttokenize,\n\tcompile,\n\tselect,\n\toutermostContext,\n\tsortInput,\n\thasDuplicate,\n\n\t// Local document vars\n\tsetDocument,\n\tdocument,\n\tdocElem,\n\tdocumentIsHTML,\n\trbuggyQSA,\n\trbuggyMatches,\n\tmatches,\n\tcontains,\n\n\t// Instance-specific data\n\texpando = \"sizzle\" + 1 * new Date(),\n\tpreferredDoc = window.document,\n\tdirruns = 0,\n\tdone = 0,\n\tclassCache = createCache(),\n\ttokenCache = createCache(),\n\tcompilerCache = createCache(),\n\tnonnativeSelectorCache = createCache(),\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t}\n\t\treturn 0;\n\t},\n\n\t// Instance methods\n\thasOwn = ( {} ).hasOwnProperty,\n\tarr = [],\n\tpop = arr.pop,\n\tpushNative = arr.push,\n\tpush = arr.push,\n\tslice = arr.slice,\n\n\t// Use a stripped-down indexOf as it's faster than native\n\t// https://jsperf.com/thor-indexof-vs-for/5\n\tindexOf = function( list, elem ) {\n\t\tvar i = 0,\n\t\t\tlen = list.length;\n\t\tfor ( ; i < len; i++ ) {\n\t\t\tif ( list[ i ] === elem ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t},\n\n\tbooleans = \"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|\" +\n\t\t\"ismap|loop|multiple|open|readonly|required|scoped\",\n\n\t// Regular expressions\n\n\t// http://www.w3.org/TR/css3-selectors/#whitespace\n\twhitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n\n\t// https://www.w3.org/TR/css-syntax-3/#ident-token-diagram\n\tidentifier = \"(?:\\\\\\\\[\\\\da-fA-F]{1,6}\" + whitespace +\n\t\t\"?|\\\\\\\\[^\\\\r\\\\n\\\\f]|[\\\\w-]|[^\\0-\\\\x7f])+\",\n\n\t// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors\n\tattributes = \"\\\\[\" + whitespace + \"*(\" + identifier + \")(?:\" + whitespace +\n\n\t\t// Operator (capture 2)\n\t\t\"*([*^$|!~]?=)\" + whitespace +\n\n\t\t// \"Attribute values must be CSS identifiers [capture 5]\n\t\t// or strings [capture 3 or capture 4]\"\n\t\t\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\" + identifier + \"))|)\" +\n\t\twhitespace + \"*\\\\]\",\n\n\tpseudos = \":(\" + identifier + \")(?:\\\\((\" +\n\n\t\t// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:\n\t\t// 1. quoted (capture 3; capture 4 or capture 5)\n\t\t\"('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|\" +\n\n\t\t// 2. simple (capture 6)\n\t\t\"((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + attributes + \")*)|\" +\n\n\t\t// 3. anything else (capture 2)\n\t\t\".*\" +\n\t\t\")\\\\)|)\",\n\n\t// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n\trwhitespace = new RegExp( whitespace + \"+\", \"g\" ),\n\trtrim = new RegExp( \"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" +\n\t\twhitespace + \"+$\", \"g\" ),\n\n\trcomma = new RegExp( \"^\" + whitespace + \"*,\" + whitespace + \"*\" ),\n\trcombinators = new RegExp( \"^\" + whitespace + \"*([>+~]|\" + whitespace + \")\" + whitespace +\n\t\t\"*\" ),\n\trdescend = new RegExp( whitespace + \"|>\" ),\n\n\trpseudo = new RegExp( pseudos ),\n\tridentifier = new RegExp( \"^\" + identifier + \"$\" ),\n\n\tmatchExpr = {\n\t\t\"ID\": new RegExp( \"^#(\" + identifier + \")\" ),\n\t\t\"CLASS\": new RegExp( \"^\\\\.(\" + identifier + \")\" ),\n\t\t\"TAG\": new RegExp( \"^(\" + identifier + \"|[*])\" ),\n\t\t\"ATTR\": new RegExp( \"^\" + attributes ),\n\t\t\"PSEUDO\": new RegExp( \"^\" + pseudos ),\n\t\t\"CHILD\": new RegExp( \"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" +\n\t\t\twhitespace + \"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" +\n\t\t\twhitespace + \"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\" ),\n\t\t\"bool\": new RegExp( \"^(?:\" + booleans + \")$\", \"i\" ),\n\n\t\t// For use in libraries implementing .is()\n\t\t// We use this for POS matching in `select`\n\t\t\"needsContext\": new RegExp( \"^\" + whitespace +\n\t\t\t\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" + whitespace +\n\t\t\t\"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\", \"i\" )\n\t},\n\n\trhtml = /HTML$/i,\n\trinputs = /^(?:input|select|textarea|button)$/i,\n\trheader = /^h\\d$/i,\n\n\trnative = /^[^{]+\\{\\s*\\[native \\w/,\n\n\t// Easily-parseable/retrievable ID or TAG or CLASS selectors\n\trquickExpr = /^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,\n\n\trsibling = /[+~]/,\n\n\t// CSS escapes\n\t// http://www.w3.org/TR/CSS21/syndata.html#escaped-characters\n\trunescape = new RegExp( \"\\\\\\\\[\\\\da-fA-F]{1,6}\" + whitespace + \"?|\\\\\\\\([^\\\\r\\\\n\\\\f])\", \"g\" ),\n\tfunescape = function( escape, nonHex ) {\n\t\tvar high = \"0x\" + escape.slice( 1 ) - 0x10000;\n\n\t\treturn nonHex ?\n\n\t\t\t// Strip the backslash prefix from a non-hex escape sequence\n\t\t\tnonHex :\n\n\t\t\t// Replace a hexadecimal escape sequence with the encoded Unicode code point\n\t\t\t// Support: IE <=11+\n\t\t\t// For values outside the Basic Multilingual Plane (BMP), manually construct a\n\t\t\t// surrogate pair\n\t\t\thigh < 0 ?\n\t\t\t\tString.fromCharCode( high + 0x10000 ) :\n\t\t\t\tString.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );\n\t},\n\n\t// CSS string/identifier serialization\n\t// https://drafts.csswg.org/cssom/#common-serializing-idioms\n\trcssescape = /([\\0-\\x1f\\x7f]|^-?\\d)|^-$|[^\\0-\\x1f\\x7f-\\uFFFF\\w-]/g,\n\tfcssescape = function( ch, asCodePoint ) {\n\t\tif ( asCodePoint ) {\n\n\t\t\t// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER\n\t\t\tif ( ch === \"\\0\" ) {\n\t\t\t\treturn \"\\uFFFD\";\n\t\t\t}\n\n\t\t\t// Control characters and (dependent upon position) numbers get escaped as code points\n\t\t\treturn ch.slice( 0, -1 ) + \"\\\\\" +\n\t\t\t\tch.charCodeAt( ch.length - 1 ).toString( 16 ) + \" \";\n\t\t}\n\n\t\t// Other potentially-special ASCII characters get backslash-escaped\n\t\treturn \"\\\\\" + ch;\n\t},\n\n\t// Used for iframes\n\t// See setDocument()\n\t// Removing the function wrapper causes a \"Permission Denied\"\n\t// error in IE\n\tunloadHandler = function() {\n\t\tsetDocument();\n\t},\n\n\tinDisabledFieldset = addCombinator(\n\t\tfunction( elem ) {\n\t\t\treturn elem.disabled === true && elem.nodeName.toLowerCase() === \"fieldset\";\n\t\t},\n\t\t{ dir: \"parentNode\", next: \"legend\" }\n\t);\n\n// Optimize for push.apply( _, NodeList )\ntry {\n\tpush.apply(\n\t\t( arr = slice.call( preferredDoc.childNodes ) ),\n\t\tpreferredDoc.childNodes\n\t);\n\n\t// Support: Android<4.0\n\t// Detect silently failing push.apply\n\t// eslint-disable-next-line no-unused-expressions\n\tarr[ preferredDoc.childNodes.length ].nodeType;\n} catch ( e ) {\n\tpush = { apply: arr.length ?\n\n\t\t// Leverage slice if possible\n\t\tfunction( target, els ) {\n\t\t\tpushNative.apply( target, slice.call( els ) );\n\t\t} :\n\n\t\t// Support: IE<9\n\t\t// Otherwise append directly\n\t\tfunction( target, els ) {\n\t\t\tvar j = target.length,\n\t\t\t\ti = 0;\n\n\t\t\t// Can't trust NodeList.length\n\t\t\twhile ( ( target[ j++ ] = els[ i++ ] ) ) {}\n\t\t\ttarget.length = j - 1;\n\t\t}\n\t};\n}\n\nfunction Sizzle( selector, context, results, seed ) {\n\tvar m, i, elem, nid, match, groups, newSelector,\n\t\tnewContext = context && context.ownerDocument,\n\n\t\t// nodeType defaults to 9, since context defaults to document\n\t\tnodeType = context ? context.nodeType : 9;\n\n\tresults = results || [];\n\n\t// Return early from calls with invalid selector or context\n\tif ( typeof selector !== \"string\" || !selector ||\n\t\tnodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {\n\n\t\treturn results;\n\t}\n\n\t// Try to shortcut find operations (as opposed to filters) in HTML documents\n\tif ( !seed ) {\n\t\tsetDocument( context );\n\t\tcontext = context || document;\n\n\t\tif ( documentIsHTML ) {\n\n\t\t\t// If the selector is sufficiently simple, try using a \"get*By*\" DOM method\n\t\t\t// (excepting DocumentFragment context, where the methods don't exist)\n\t\t\tif ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) {\n\n\t\t\t\t// ID selector\n\t\t\t\tif ( ( m = match[ 1 ] ) ) {\n\n\t\t\t\t\t// Document context\n\t\t\t\t\tif ( nodeType === 9 ) {\n\t\t\t\t\t\tif ( ( elem = context.getElementById( m ) ) ) {\n\n\t\t\t\t\t\t\t// Support: IE, Opera, Webkit\n\t\t\t\t\t\t\t// TODO: identify versions\n\t\t\t\t\t\t\t// getElementById can match elements by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === m ) {\n\t\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t// Element context\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// Support: IE, Opera, Webkit\n\t\t\t\t\t\t// TODO: identify versions\n\t\t\t\t\t\t// getElementById can match elements by name instead of ID\n\t\t\t\t\t\tif ( newContext && ( elem = newContext.getElementById( m ) ) &&\n\t\t\t\t\t\t\tcontains( context, elem ) &&\n\t\t\t\t\t\t\telem.id === m ) {\n\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t// Type selector\n\t\t\t\t} else if ( match[ 2 ] ) {\n\t\t\t\t\tpush.apply( results, context.getElementsByTagName( selector ) );\n\t\t\t\t\treturn results;\n\n\t\t\t\t// Class selector\n\t\t\t\t} else if ( ( m = match[ 3 ] ) && support.getElementsByClassName &&\n\t\t\t\t\tcontext.getElementsByClassName ) {\n\n\t\t\t\t\tpush.apply( results, context.getElementsByClassName( m ) );\n\t\t\t\t\treturn results;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Take advantage of querySelectorAll\n\t\t\tif ( support.qsa &&\n\t\t\t\t!nonnativeSelectorCache[ selector + \" \" ] &&\n\t\t\t\t( !rbuggyQSA || !rbuggyQSA.test( selector ) ) &&\n\n\t\t\t\t// Support: IE 8 only\n\t\t\t\t// Exclude object elements\n\t\t\t\t( nodeType !== 1 || context.nodeName.toLowerCase() !== \"object\" ) ) {\n\n\t\t\t\tnewSelector = selector;\n\t\t\t\tnewContext = context;\n\n\t\t\t\t// qSA considers elements outside a scoping root when evaluating child or\n\t\t\t\t// descendant combinators, which is not what we want.\n\t\t\t\t// In such cases, we work around the behavior by prefixing every selector in the\n\t\t\t\t// list with an ID selector referencing the scope context.\n\t\t\t\t// The technique has to be used as well when a leading combinator is used\n\t\t\t\t// as such selectors are not recognized by querySelectorAll.\n\t\t\t\t// Thanks to Andrew Dupont for this technique.\n\t\t\t\tif ( nodeType === 1 &&\n\t\t\t\t\t( rdescend.test( selector ) || rcombinators.test( selector ) ) ) {\n\n\t\t\t\t\t// Expand context for sibling selectors\n\t\t\t\t\tnewContext = rsibling.test( selector ) && testContext( context.parentNode ) ||\n\t\t\t\t\t\tcontext;\n\n\t\t\t\t\t// We can use :scope instead of the ID hack if the browser\n\t\t\t\t\t// supports it & if we're not changing the context.\n\t\t\t\t\tif ( newContext !== context || !support.scope ) {\n\n\t\t\t\t\t\t// Capture the context ID, setting it first if necessary\n\t\t\t\t\t\tif ( ( nid = context.getAttribute( \"id\" ) ) ) {\n\t\t\t\t\t\t\tnid = nid.replace( rcssescape, fcssescape );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcontext.setAttribute( \"id\", ( nid = expando ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prefix every selector in the list\n\t\t\t\t\tgroups = tokenize( selector );\n\t\t\t\t\ti = groups.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tgroups[ i ] = ( nid ? \"#\" + nid : \":scope\" ) + \" \" +\n\t\t\t\t\t\t\ttoSelector( groups[ i ] );\n\t\t\t\t\t}\n\t\t\t\t\tnewSelector = groups.join( \",\" );\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tpush.apply( results,\n\t\t\t\t\t\tnewContext.querySelectorAll( newSelector )\n\t\t\t\t\t);\n\t\t\t\t\treturn results;\n\t\t\t\t} catch ( qsaError ) {\n\t\t\t\t\tnonnativeSelectorCache( selector, true );\n\t\t\t\t} finally {\n\t\t\t\t\tif ( nid === expando ) {\n\t\t\t\t\t\tcontext.removeAttribute( \"id\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// All others\n\treturn select( selector.replace( rtrim, \"$1\" ), context, results, seed );\n}\n\n/**\n * Create key-value caches of limited size\n * @returns {function(string, object)} Returns the Object data after storing it on itself with\n *\tproperty name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)\n *\tdeleting the oldest entry\n */\nfunction createCache() {\n\tvar keys = [];\n\n\tfunction cache( key, value ) {\n\n\t\t// Use (key + \" \") to avoid collision with native prototype properties (see Issue #157)\n\t\tif ( keys.push( key + \" \" ) > Expr.cacheLength ) {\n\n\t\t\t// Only keep the most recent entries\n\t\t\tdelete cache[ keys.shift() ];\n\t\t}\n\t\treturn ( cache[ key + \" \" ] = value );\n\t}\n\treturn cache;\n}\n\n/**\n * Mark a function for special use by Sizzle\n * @param {Function} fn The function to mark\n */\nfunction markFunction( fn ) {\n\tfn[ expando ] = true;\n\treturn fn;\n}\n\n/**\n * Support testing using an element\n * @param {Function} fn Passed the created element and returns a boolean result\n */\nfunction assert( fn ) {\n\tvar el = document.createElement( \"fieldset\" );\n\n\ttry {\n\t\treturn !!fn( el );\n\t} catch ( e ) {\n\t\treturn false;\n\t} finally {\n\n\t\t// Remove from its parent by default\n\t\tif ( el.parentNode ) {\n\t\t\tel.parentNode.removeChild( el );\n\t\t}\n\n\t\t// release memory in IE\n\t\tel = null;\n\t}\n}\n\n/**\n * Adds the same handler for all of the specified attrs\n * @param {String} attrs Pipe-separated list of attributes\n * @param {Function} handler The method that will be applied\n */\nfunction addHandle( attrs, handler ) {\n\tvar arr = attrs.split( \"|\" ),\n\t\ti = arr.length;\n\n\twhile ( i-- ) {\n\t\tExpr.attrHandle[ arr[ i ] ] = handler;\n\t}\n}\n\n/**\n * Checks document order of two siblings\n * @param {Element} a\n * @param {Element} b\n * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b\n */\nfunction siblingCheck( a, b ) {\n\tvar cur = b && a,\n\t\tdiff = cur && a.nodeType === 1 && b.nodeType === 1 &&\n\t\t\ta.sourceIndex - b.sourceIndex;\n\n\t// Use IE sourceIndex if available on both nodes\n\tif ( diff ) {\n\t\treturn diff;\n\t}\n\n\t// Check if b follows a\n\tif ( cur ) {\n\t\twhile ( ( cur = cur.nextSibling ) ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn a ? 1 : -1;\n}\n\n/**\n * Returns a function to use in pseudos for input types\n * @param {String} type\n */\nfunction createInputPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn name === \"input\" && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for buttons\n * @param {String} type\n */\nfunction createButtonPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn ( name === \"input\" || name === \"button\" ) && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for :enabled/:disabled\n * @param {Boolean} disabled true for :disabled; false for :enabled\n */\nfunction createDisabledPseudo( disabled ) {\n\n\t// Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable\n\treturn function( elem ) {\n\n\t\t// Only certain elements can match :enabled or :disabled\n\t\t// https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled\n\t\t// https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled\n\t\tif ( \"form\" in elem ) {\n\n\t\t\t// Check for inherited disabledness on relevant non-disabled elements:\n\t\t\t// * listed form-associated elements in a disabled fieldset\n\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#category-listed\n\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled\n\t\t\t// * option elements in a disabled optgroup\n\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled\n\t\t\t// All such elements have a \"form\" property.\n\t\t\tif ( elem.parentNode && elem.disabled === false ) {\n\n\t\t\t\t// Option elements defer to a parent optgroup if present\n\t\t\t\tif ( \"label\" in elem ) {\n\t\t\t\t\tif ( \"label\" in elem.parentNode ) {\n\t\t\t\t\t\treturn elem.parentNode.disabled === disabled;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn elem.disabled === disabled;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Support: IE 6 - 11\n\t\t\t\t// Use the isDisabled shortcut property to check for disabled fieldset ancestors\n\t\t\t\treturn elem.isDisabled === disabled ||\n\n\t\t\t\t\t// Where there is no isDisabled, check manually\n\t\t\t\t\t/* jshint -W018 */\n\t\t\t\t\telem.isDisabled !== !disabled &&\n\t\t\t\t\tinDisabledFieldset( elem ) === disabled;\n\t\t\t}\n\n\t\t\treturn elem.disabled === disabled;\n\n\t\t// Try to winnow out elements that can't be disabled before trusting the disabled property.\n\t\t// Some victims get caught in our net (label, legend, menu, track), but it shouldn't\n\t\t// even exist on them, let alone have a boolean value.\n\t\t} else if ( \"label\" in elem ) {\n\t\t\treturn elem.disabled === disabled;\n\t\t}\n\n\t\t// Remaining elements are neither :enabled nor :disabled\n\t\treturn false;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for positionals\n * @param {Function} fn\n */\nfunction createPositionalPseudo( fn ) {\n\treturn markFunction( function( argument ) {\n\t\targument = +argument;\n\t\treturn markFunction( function( seed, matches ) {\n\t\t\tvar j,\n\t\t\t\tmatchIndexes = fn( [], seed.length, argument ),\n\t\t\t\ti = matchIndexes.length;\n\n\t\t\t// Match elements found at the specified indexes\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( seed[ ( j = matchIndexes[ i ] ) ] ) {\n\t\t\t\t\tseed[ j ] = !( matches[ j ] = seed[ j ] );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t} );\n}\n\n/**\n * Checks a node for validity as a Sizzle context\n * @param {Element|Object=} context\n * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value\n */\nfunction testContext( context ) {\n\treturn context && typeof context.getElementsByTagName !== \"undefined\" && context;\n}\n\n// Expose support vars for convenience\nsupport = Sizzle.support = {};\n\n/**\n * Detects XML nodes\n * @param {Element|Object} elem An element or a document\n * @returns {Boolean} True iff elem is a non-HTML XML node\n */\nisXML = Sizzle.isXML = function( elem ) {\n\tvar namespace = elem.namespaceURI,\n\t\tdocElem = ( elem.ownerDocument || elem ).documentElement;\n\n\t// Support: IE <=8\n\t// Assume HTML when documentElement doesn't yet exist, such as inside loading iframes\n\t// https://bugs.jquery.com/ticket/4833\n\treturn !rhtml.test( namespace || docElem && docElem.nodeName || \"HTML\" );\n};\n\n/**\n * Sets document-related variables once based on the current document\n * @param {Element|Object} [doc] An element or document object to use to set the document\n * @returns {Object} Returns the current document\n */\nsetDocument = Sizzle.setDocument = function( node ) {\n\tvar hasCompare, subWindow,\n\t\tdoc = node ? node.ownerDocument || node : preferredDoc;\n\n\t// Return early if doc is invalid or already selected\n\t// Support: IE 11+, Edge 17 - 18+\n\t// IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n\t// two documents; shallow comparisons work.\n\t// eslint-disable-next-line eqeqeq\n\tif ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) {\n\t\treturn document;\n\t}\n\n\t// Update global variables\n\tdocument = doc;\n\tdocElem = document.documentElement;\n\tdocumentIsHTML = !isXML( document );\n\n\t// Support: IE 9 - 11+, Edge 12 - 18+\n\t// Accessing iframe documents after unload throws \"permission denied\" errors (jQuery #13936)\n\t// Support: IE 11+, Edge 17 - 18+\n\t// IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n\t// two documents; shallow comparisons work.\n\t// eslint-disable-next-line eqeqeq\n\tif ( preferredDoc != document &&\n\t\t( subWindow = document.defaultView ) && subWindow.top !== subWindow ) {\n\n\t\t// Support: IE 11, Edge\n\t\tif ( subWindow.addEventListener ) {\n\t\t\tsubWindow.addEventListener( \"unload\", unloadHandler, false );\n\n\t\t// Support: IE 9 - 10 only\n\t\t} else if ( subWindow.attachEvent ) {\n\t\t\tsubWindow.attachEvent( \"onunload\", unloadHandler );\n\t\t}\n\t}\n\n\t// Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only,\n\t// Safari 4 - 5 only, Opera <=11.6 - 12.x only\n\t// IE/Edge & older browsers don't support the :scope pseudo-class.\n\t// Support: Safari 6.0 only\n\t// Safari 6.0 supports :scope but it's an alias of :root there.\n\tsupport.scope = assert( function( el ) {\n\t\tdocElem.appendChild( el ).appendChild( document.createElement( \"div\" ) );\n\t\treturn typeof el.querySelectorAll !== \"undefined\" &&\n\t\t\t!el.querySelectorAll( \":scope fieldset div\" ).length;\n\t} );\n\n\t/* Attributes\n\t---------------------------------------------------------------------- */\n\n\t// Support: IE<8\n\t// Verify that getAttribute really returns attributes and not properties\n\t// (excepting IE8 booleans)\n\tsupport.attributes = assert( function( el ) {\n\t\tel.className = \"i\";\n\t\treturn !el.getAttribute( \"className\" );\n\t} );\n\n\t/* getElement(s)By*\n\t---------------------------------------------------------------------- */\n\n\t// Check if getElementsByTagName(\"*\") returns only elements\n\tsupport.getElementsByTagName = assert( function( el ) {\n\t\tel.appendChild( document.createComment( \"\" ) );\n\t\treturn !el.getElementsByTagName( \"*\" ).length;\n\t} );\n\n\t// Support: IE<9\n\tsupport.getElementsByClassName = rnative.test( document.getElementsByClassName );\n\n\t// Support: IE<10\n\t// Check if getElementById returns elements by name\n\t// The broken getElementById methods don't pick up programmatically-set names,\n\t// so use a roundabout getElementsByName test\n\tsupport.getById = assert( function( el ) {\n\t\tdocElem.appendChild( el ).id = expando;\n\t\treturn !document.getElementsByName || !document.getElementsByName( expando ).length;\n\t} );\n\n\t// ID filter and find\n\tif ( support.getById ) {\n\t\tExpr.filter[ \"ID\" ] = function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn elem.getAttribute( \"id\" ) === attrId;\n\t\t\t};\n\t\t};\n\t\tExpr.find[ \"ID\" ] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n\t\t\t\tvar elem = context.getElementById( id );\n\t\t\t\treturn elem ? [ elem ] : [];\n\t\t\t}\n\t\t};\n\t} else {\n\t\tExpr.filter[ \"ID\" ] =  function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" &&\n\t\t\t\t\telem.getAttributeNode( \"id\" );\n\t\t\t\treturn node && node.value === attrId;\n\t\t\t};\n\t\t};\n\n\t\t// Support: IE 6 - 7 only\n\t\t// getElementById is not reliable as a find shortcut\n\t\tExpr.find[ \"ID\" ] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n\t\t\t\tvar node, i, elems,\n\t\t\t\t\telem = context.getElementById( id );\n\n\t\t\t\tif ( elem ) {\n\n\t\t\t\t\t// Verify the id attribute\n\t\t\t\t\tnode = elem.getAttributeNode( \"id\" );\n\t\t\t\t\tif ( node && node.value === id ) {\n\t\t\t\t\t\treturn [ elem ];\n\t\t\t\t\t}\n\n\t\t\t\t\t// Fall back on getElementsByName\n\t\t\t\t\telems = context.getElementsByName( id );\n\t\t\t\t\ti = 0;\n\t\t\t\t\twhile ( ( elem = elems[ i++ ] ) ) {\n\t\t\t\t\t\tnode = elem.getAttributeNode( \"id\" );\n\t\t\t\t\t\tif ( node && node.value === id ) {\n\t\t\t\t\t\t\treturn [ elem ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn [];\n\t\t\t}\n\t\t};\n\t}\n\n\t// Tag\n\tExpr.find[ \"TAG\" ] = support.getElementsByTagName ?\n\t\tfunction( tag, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( tag );\n\n\t\t\t// DocumentFragment nodes don't have gEBTN\n\t\t\t} else if ( support.qsa ) {\n\t\t\t\treturn context.querySelectorAll( tag );\n\t\t\t}\n\t\t} :\n\n\t\tfunction( tag, context ) {\n\t\t\tvar elem,\n\t\t\t\ttmp = [],\n\t\t\t\ti = 0,\n\n\t\t\t\t// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too\n\t\t\t\tresults = context.getElementsByTagName( tag );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( tag === \"*\" ) {\n\t\t\t\twhile ( ( elem = results[ i++ ] ) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn tmp;\n\t\t\t}\n\t\t\treturn results;\n\t\t};\n\n\t// Class\n\tExpr.find[ \"CLASS\" ] = support.getElementsByClassName && function( className, context ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && documentIsHTML ) {\n\t\t\treturn context.getElementsByClassName( className );\n\t\t}\n\t};\n\n\t/* QSA/matchesSelector\n\t---------------------------------------------------------------------- */\n\n\t// QSA and matchesSelector support\n\n\t// matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n\trbuggyMatches = [];\n\n\t// qSa(:focus) reports false when true (Chrome 21)\n\t// We allow this because of a bug in IE8/9 that throws an error\n\t// whenever `document.activeElement` is accessed on an iframe\n\t// So, we allow :focus to pass through QSA all the time to avoid the IE error\n\t// See https://bugs.jquery.com/ticket/13378\n\trbuggyQSA = [];\n\n\tif ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) {\n\n\t\t// Build QSA regex\n\t\t// Regex strategy adopted from Diego Perini\n\t\tassert( function( el ) {\n\n\t\t\tvar input;\n\n\t\t\t// Select is set to empty string on purpose\n\t\t\t// This is to test IE's treatment of not explicitly\n\t\t\t// setting a boolean content attribute,\n\t\t\t// since its presence should be enough\n\t\t\t// https://bugs.jquery.com/ticket/12359\n\t\t\tdocElem.appendChild( el ).innerHTML = \"<a id='\" + expando + \"'></a>\" +\n\t\t\t\t\"<select id='\" + expando + \"-\\r\\\\' msallowcapture=''>\" +\n\t\t\t\t\"<option selected=''></option></select>\";\n\n\t\t\t// Support: IE8, Opera 11-12.16\n\t\t\t// Nothing should be selected when empty strings follow ^= or $= or *=\n\t\t\t// The test attribute must be unknown in Opera but \"safe\" for WinRT\n\t\t\t// https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section\n\t\t\tif ( el.querySelectorAll( \"[msallowcapture^='']\" ).length ) {\n\t\t\t\trbuggyQSA.push( \"[*^$]=\" + whitespace + \"*(?:''|\\\"\\\")\" );\n\t\t\t}\n\n\t\t\t// Support: IE8\n\t\t\t// Boolean attributes and \"value\" are not treated correctly\n\t\t\tif ( !el.querySelectorAll( \"[selected]\" ).length ) {\n\t\t\t\trbuggyQSA.push( \"\\\\[\" + whitespace + \"*(?:value|\" + booleans + \")\" );\n\t\t\t}\n\n\t\t\t// Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+\n\t\t\tif ( !el.querySelectorAll( \"[id~=\" + expando + \"-]\" ).length ) {\n\t\t\t\trbuggyQSA.push( \"~=\" );\n\t\t\t}\n\n\t\t\t// Support: IE 11+, Edge 15 - 18+\n\t\t\t// IE 11/Edge don't find elements on a `[name='']` query in some cases.\n\t\t\t// Adding a temporary attribute to the document before the selection works\n\t\t\t// around the issue.\n\t\t\t// Interestingly, IE 10 & older don't seem to have the issue.\n\t\t\tinput = document.createElement( \"input\" );\n\t\t\tinput.setAttribute( \"name\", \"\" );\n\t\t\tel.appendChild( input );\n\t\t\tif ( !el.querySelectorAll( \"[name='']\" ).length ) {\n\t\t\t\trbuggyQSA.push( \"\\\\[\" + whitespace + \"*name\" + whitespace + \"*=\" +\n\t\t\t\t\twhitespace + \"*(?:''|\\\"\\\")\" );\n\t\t\t}\n\n\t\t\t// Webkit/Opera - :checked should return selected option elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !el.querySelectorAll( \":checked\" ).length ) {\n\t\t\t\trbuggyQSA.push( \":checked\" );\n\t\t\t}\n\n\t\t\t// Support: Safari 8+, iOS 8+\n\t\t\t// https://bugs.webkit.org/show_bug.cgi?id=136851\n\t\t\t// In-page `selector#id sibling-combinator selector` fails\n\t\t\tif ( !el.querySelectorAll( \"a#\" + expando + \"+*\" ).length ) {\n\t\t\t\trbuggyQSA.push( \".#.+[+~]\" );\n\t\t\t}\n\n\t\t\t// Support: Firefox <=3.6 - 5 only\n\t\t\t// Old Firefox doesn't throw on a badly-escaped identifier.\n\t\t\tel.querySelectorAll( \"\\\\\\f\" );\n\t\t\trbuggyQSA.push( \"[\\\\r\\\\n\\\\f]\" );\n\t\t} );\n\n\t\tassert( function( el ) {\n\t\t\tel.innerHTML = \"<a href='' disabled='disabled'></a>\" +\n\t\t\t\t\"<select disabled='disabled'><option/></select>\";\n\n\t\t\t// Support: Windows 8 Native Apps\n\t\t\t// The type and name attributes are restricted during .innerHTML assignment\n\t\t\tvar input = document.createElement( \"input\" );\n\t\t\tinput.setAttribute( \"type\", \"hidden\" );\n\t\t\tel.appendChild( input ).setAttribute( \"name\", \"D\" );\n\n\t\t\t// Support: IE8\n\t\t\t// Enforce case-sensitivity of name attribute\n\t\t\tif ( el.querySelectorAll( \"[name=d]\" ).length ) {\n\t\t\t\trbuggyQSA.push( \"name\" + whitespace + \"*[*^$|!~]?=\" );\n\t\t\t}\n\n\t\t\t// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( el.querySelectorAll( \":enabled\" ).length !== 2 ) {\n\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t}\n\n\t\t\t// Support: IE9-11+\n\t\t\t// IE's :disabled selector does not pick up the children of disabled fieldsets\n\t\t\tdocElem.appendChild( el ).disabled = true;\n\t\t\tif ( el.querySelectorAll( \":disabled\" ).length !== 2 ) {\n\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t}\n\n\t\t\t// Support: Opera 10 - 11 only\n\t\t\t// Opera 10-11 does not throw on post-comma invalid pseudos\n\t\t\tel.querySelectorAll( \"*,:x\" );\n\t\t\trbuggyQSA.push( \",.*:\" );\n\t\t} );\n\t}\n\n\tif ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches ||\n\t\tdocElem.webkitMatchesSelector ||\n\t\tdocElem.mozMatchesSelector ||\n\t\tdocElem.oMatchesSelector ||\n\t\tdocElem.msMatchesSelector ) ) ) ) {\n\n\t\tassert( function( el ) {\n\n\t\t\t// Check to see if it's possible to do matchesSelector\n\t\t\t// on a disconnected node (IE 9)\n\t\t\tsupport.disconnectedMatch = matches.call( el, \"*\" );\n\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( el, \"[s!='']:x\" );\n\t\t\trbuggyMatches.push( \"!=\", pseudos );\n\t\t} );\n\t}\n\n\trbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( \"|\" ) );\n\trbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( \"|\" ) );\n\n\t/* Contains\n\t---------------------------------------------------------------------- */\n\thasCompare = rnative.test( docElem.compareDocumentPosition );\n\n\t// Element contains another\n\t// Purposefully self-exclusive\n\t// As in, an element does not contain itself\n\tcontains = hasCompare || rnative.test( docElem.contains ) ?\n\t\tfunction( a, b ) {\n\t\t\tvar adown = a.nodeType === 9 ? a.documentElement : a,\n\t\t\t\tbup = b && b.parentNode;\n\t\t\treturn a === bup || !!( bup && bup.nodeType === 1 && (\n\t\t\t\tadown.contains ?\n\t\t\t\t\tadown.contains( bup ) :\n\t\t\t\t\ta.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16\n\t\t\t) );\n\t\t} :\n\t\tfunction( a, b ) {\n\t\t\tif ( b ) {\n\t\t\t\twhile ( ( b = b.parentNode ) ) {\n\t\t\t\t\tif ( b === a ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n\n\t/* Sorting\n\t---------------------------------------------------------------------- */\n\n\t// Document order sorting\n\tsortOrder = hasCompare ?\n\tfunction( a, b ) {\n\n\t\t// Flag for duplicate removal\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\t// Sort on method existence if only one input has compareDocumentPosition\n\t\tvar compare = !a.compareDocumentPosition - !b.compareDocumentPosition;\n\t\tif ( compare ) {\n\t\t\treturn compare;\n\t\t}\n\n\t\t// Calculate position if both inputs belong to the same document\n\t\t// Support: IE 11+, Edge 17 - 18+\n\t\t// IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n\t\t// two documents; shallow comparisons work.\n\t\t// eslint-disable-next-line eqeqeq\n\t\tcompare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ?\n\t\t\ta.compareDocumentPosition( b ) :\n\n\t\t\t// Otherwise we know they are disconnected\n\t\t\t1;\n\n\t\t// Disconnected nodes\n\t\tif ( compare & 1 ||\n\t\t\t( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) {\n\n\t\t\t// Choose the first element that is related to our preferred document\n\t\t\t// Support: IE 11+, Edge 17 - 18+\n\t\t\t// IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n\t\t\t// two documents; shallow comparisons work.\n\t\t\t// eslint-disable-next-line eqeqeq\n\t\t\tif ( a == document || a.ownerDocument == preferredDoc &&\n\t\t\t\tcontains( preferredDoc, a ) ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\n\t\t\t// Support: IE 11+, Edge 17 - 18+\n\t\t\t// IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n\t\t\t// two documents; shallow comparisons work.\n\t\t\t// eslint-disable-next-line eqeqeq\n\t\t\tif ( b == document || b.ownerDocument == preferredDoc &&\n\t\t\t\tcontains( preferredDoc, b ) ) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\t// Maintain original order\n\t\t\treturn sortInput ?\n\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t0;\n\t\t}\n\n\t\treturn compare & 4 ? -1 : 1;\n\t} :\n\tfunction( a, b ) {\n\n\t\t// Exit early if the nodes are identical\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tap = [ a ],\n\t\t\tbp = [ b ];\n\n\t\t// Parentless nodes are either documents or disconnected\n\t\tif ( !aup || !bup ) {\n\n\t\t\t// Support: IE 11+, Edge 17 - 18+\n\t\t\t// IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n\t\t\t// two documents; shallow comparisons work.\n\t\t\t/* eslint-disable eqeqeq */\n\t\t\treturn a == document ? -1 :\n\t\t\t\tb == document ? 1 :\n\t\t\t\t/* eslint-enable eqeqeq */\n\t\t\t\taup ? -1 :\n\t\t\t\tbup ? 1 :\n\t\t\t\tsortInput ?\n\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t0;\n\n\t\t// If the nodes are siblings, we can do a quick check\n\t\t} else if ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\t\t}\n\n\t\t// Otherwise we need full lists of their ancestors for comparison\n\t\tcur = a;\n\t\twhile ( ( cur = cur.parentNode ) ) {\n\t\t\tap.unshift( cur );\n\t\t}\n\t\tcur = b;\n\t\twhile ( ( cur = cur.parentNode ) ) {\n\t\t\tbp.unshift( cur );\n\t\t}\n\n\t\t// Walk down the tree looking for a discrepancy\n\t\twhile ( ap[ i ] === bp[ i ] ) {\n\t\t\ti++;\n\t\t}\n\n\t\treturn i ?\n\n\t\t\t// Do a sibling check if the nodes have a common ancestor\n\t\t\tsiblingCheck( ap[ i ], bp[ i ] ) :\n\n\t\t\t// Otherwise nodes in our document sort first\n\t\t\t// Support: IE 11+, Edge 17 - 18+\n\t\t\t// IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n\t\t\t// two documents; shallow comparisons work.\n\t\t\t/* eslint-disable eqeqeq */\n\t\t\tap[ i ] == preferredDoc ? -1 :\n\t\t\tbp[ i ] == preferredDoc ? 1 :\n\t\t\t/* eslint-enable eqeqeq */\n\t\t\t0;\n\t};\n\n\treturn document;\n};\n\nSizzle.matches = function( expr, elements ) {\n\treturn Sizzle( expr, null, null, elements );\n};\n\nSizzle.matchesSelector = function( elem, expr ) {\n\tsetDocument( elem );\n\n\tif ( support.matchesSelector && documentIsHTML &&\n\t\t!nonnativeSelectorCache[ expr + \" \" ] &&\n\t\t( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&\n\t\t( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {\n\n\t\ttry {\n\t\t\tvar ret = matches.call( elem, expr );\n\n\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\tif ( ret || support.disconnectedMatch ||\n\n\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t// fragment in IE 9\n\t\t\t\telem.document && elem.document.nodeType !== 11 ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\tnonnativeSelectorCache( expr, true );\n\t\t}\n\t}\n\n\treturn Sizzle( expr, document, null, [ elem ] ).length > 0;\n};\n\nSizzle.contains = function( context, elem ) {\n\n\t// Set document vars if needed\n\t// Support: IE 11+, Edge 17 - 18+\n\t// IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n\t// two documents; shallow comparisons work.\n\t// eslint-disable-next-line eqeqeq\n\tif ( ( context.ownerDocument || context ) != document ) {\n\t\tsetDocument( context );\n\t}\n\treturn contains( context, elem );\n};\n\nSizzle.attr = function( elem, name ) {\n\n\t// Set document vars if needed\n\t// Support: IE 11+, Edge 17 - 18+\n\t// IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n\t// two documents; shallow comparisons work.\n\t// eslint-disable-next-line eqeqeq\n\tif ( ( elem.ownerDocument || elem ) != document ) {\n\t\tsetDocument( elem );\n\t}\n\n\tvar fn = Expr.attrHandle[ name.toLowerCase() ],\n\n\t\t// Don't get fooled by Object.prototype properties (jQuery #13807)\n\t\tval = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?\n\t\t\tfn( elem, name, !documentIsHTML ) :\n\t\t\tundefined;\n\n\treturn val !== undefined ?\n\t\tval :\n\t\tsupport.attributes || !documentIsHTML ?\n\t\t\telem.getAttribute( name ) :\n\t\t\t( val = elem.getAttributeNode( name ) ) && val.specified ?\n\t\t\t\tval.value :\n\t\t\t\tnull;\n};\n\nSizzle.escape = function( sel ) {\n\treturn ( sel + \"\" ).replace( rcssescape, fcssescape );\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Document sorting and removing duplicates\n * @param {ArrayLike} results\n */\nSizzle.uniqueSort = function( results ) {\n\tvar elem,\n\t\tduplicates = [],\n\t\tj = 0,\n\t\ti = 0;\n\n\t// Unless we *know* we can detect duplicates, assume their presence\n\thasDuplicate = !support.detectDuplicates;\n\tsortInput = !support.sortStable && results.slice( 0 );\n\tresults.sort( sortOrder );\n\n\tif ( hasDuplicate ) {\n\t\twhile ( ( elem = results[ i++ ] ) ) {\n\t\t\tif ( elem === results[ i ] ) {\n\t\t\t\tj = duplicates.push( i );\n\t\t\t}\n\t\t}\n\t\twhile ( j-- ) {\n\t\t\tresults.splice( duplicates[ j ], 1 );\n\t\t}\n\t}\n\n\t// Clear input after sorting to release objects\n\t// See https://github.com/jquery/sizzle/pull/225\n\tsortInput = null;\n\n\treturn results;\n};\n\n/**\n * Utility function for retrieving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\ngetText = Sizzle.getText = function( elem ) {\n\tvar node,\n\t\tret = \"\",\n\t\ti = 0,\n\t\tnodeType = elem.nodeType;\n\n\tif ( !nodeType ) {\n\n\t\t// If no nodeType, this is expected to be an array\n\t\twhile ( ( node = elem[ i++ ] ) ) {\n\n\t\t\t// Do not traverse comment nodes\n\t\t\tret += getText( node );\n\t\t}\n\t} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\n\t\t// Use textContent for elements\n\t\t// innerText usage removed for consistency of new lines (jQuery #11153)\n\t\tif ( typeof elem.textContent === \"string\" ) {\n\t\t\treturn elem.textContent;\n\t\t} else {\n\n\t\t\t// Traverse its children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tret += getText( elem );\n\t\t\t}\n\t\t}\n\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\treturn elem.nodeValue;\n\t}\n\n\t// Do not include comment or processing instruction nodes\n\n\treturn ret;\n};\n\nExpr = Sizzle.selectors = {\n\n\t// Can be adjusted by the user\n\tcacheLength: 50,\n\n\tcreatePseudo: markFunction,\n\n\tmatch: matchExpr,\n\n\tattrHandle: {},\n\n\tfind: {},\n\n\trelative: {\n\t\t\">\": { dir: \"parentNode\", first: true },\n\t\t\" \": { dir: \"parentNode\" },\n\t\t\"+\": { dir: \"previousSibling\", first: true },\n\t\t\"~\": { dir: \"previousSibling\" }\n\t},\n\n\tpreFilter: {\n\t\t\"ATTR\": function( match ) {\n\t\t\tmatch[ 1 ] = match[ 1 ].replace( runescape, funescape );\n\n\t\t\t// Move the given value to match[3] whether quoted or unquoted\n\t\t\tmatch[ 3 ] = ( match[ 3 ] || match[ 4 ] ||\n\t\t\t\tmatch[ 5 ] || \"\" ).replace( runescape, funescape );\n\n\t\t\tif ( match[ 2 ] === \"~=\" ) {\n\t\t\t\tmatch[ 3 ] = \" \" + match[ 3 ] + \" \";\n\t\t\t}\n\n\t\t\treturn match.slice( 0, 4 );\n\t\t},\n\n\t\t\"CHILD\": function( match ) {\n\n\t\t\t/* matches from matchExpr[\"CHILD\"]\n\t\t\t\t1 type (only|nth|...)\n\t\t\t\t2 what (child|of-type)\n\t\t\t\t3 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n\t\t\t\t4 xn-component of xn+y argument ([+-]?\\d*n|)\n\t\t\t\t5 sign of xn-component\n\t\t\t\t6 x of xn-component\n\t\t\t\t7 sign of y-component\n\t\t\t\t8 y of y-component\n\t\t\t*/\n\t\t\tmatch[ 1 ] = match[ 1 ].toLowerCase();\n\n\t\t\tif ( match[ 1 ].slice( 0, 3 ) === \"nth\" ) {\n\n\t\t\t\t// nth-* requires argument\n\t\t\t\tif ( !match[ 3 ] ) {\n\t\t\t\t\tSizzle.error( match[ 0 ] );\n\t\t\t\t}\n\n\t\t\t\t// numeric x and y parameters for Expr.filter.CHILD\n\t\t\t\t// remember that false/true cast respectively to 0/1\n\t\t\t\tmatch[ 4 ] = +( match[ 4 ] ?\n\t\t\t\t\tmatch[ 5 ] + ( match[ 6 ] || 1 ) :\n\t\t\t\t\t2 * ( match[ 3 ] === \"even\" || match[ 3 ] === \"odd\" ) );\n\t\t\t\tmatch[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === \"odd\" );\n\n\t\t\t\t// other types prohibit arguments\n\t\t\t} else if ( match[ 3 ] ) {\n\t\t\t\tSizzle.error( match[ 0 ] );\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\t\"PSEUDO\": function( match ) {\n\t\t\tvar excess,\n\t\t\t\tunquoted = !match[ 6 ] && match[ 2 ];\n\n\t\t\tif ( matchExpr[ \"CHILD\" ].test( match[ 0 ] ) ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// Accept quoted arguments as-is\n\t\t\tif ( match[ 3 ] ) {\n\t\t\t\tmatch[ 2 ] = match[ 4 ] || match[ 5 ] || \"\";\n\n\t\t\t// Strip excess characters from unquoted arguments\n\t\t\t} else if ( unquoted && rpseudo.test( unquoted ) &&\n\n\t\t\t\t// Get excess from tokenize (recursively)\n\t\t\t\t( excess = tokenize( unquoted, true ) ) &&\n\n\t\t\t\t// advance to the next closing parenthesis\n\t\t\t\t( excess = unquoted.indexOf( \")\", unquoted.length - excess ) - unquoted.length ) ) {\n\n\t\t\t\t// excess is a negative index\n\t\t\t\tmatch[ 0 ] = match[ 0 ].slice( 0, excess );\n\t\t\t\tmatch[ 2 ] = unquoted.slice( 0, excess );\n\t\t\t}\n\n\t\t\t// Return only captures needed by the pseudo filter method (type and argument)\n\t\t\treturn match.slice( 0, 3 );\n\t\t}\n\t},\n\n\tfilter: {\n\n\t\t\"TAG\": function( nodeNameSelector ) {\n\t\t\tvar nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn nodeNameSelector === \"*\" ?\n\t\t\t\tfunction() {\n\t\t\t\t\treturn true;\n\t\t\t\t} :\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n\t\t\t\t};\n\t\t},\n\n\t\t\"CLASS\": function( className ) {\n\t\t\tvar pattern = classCache[ className + \" \" ];\n\n\t\t\treturn pattern ||\n\t\t\t\t( pattern = new RegExp( \"(^|\" + whitespace +\n\t\t\t\t\t\")\" + className + \"(\" + whitespace + \"|$)\" ) ) && classCache(\n\t\t\t\t\t\tclassName, function( elem ) {\n\t\t\t\t\t\t\treturn pattern.test(\n\t\t\t\t\t\t\t\ttypeof elem.className === \"string\" && elem.className ||\n\t\t\t\t\t\t\t\ttypeof elem.getAttribute !== \"undefined\" &&\n\t\t\t\t\t\t\t\t\telem.getAttribute( \"class\" ) ||\n\t\t\t\t\t\t\t\t\"\"\n\t\t\t\t\t\t\t);\n\t\t\t\t} );\n\t\t},\n\n\t\t\"ATTR\": function( name, operator, check ) {\n\t\t\treturn function( elem ) {\n\t\t\t\tvar result = Sizzle.attr( elem, name );\n\n\t\t\t\tif ( result == null ) {\n\t\t\t\t\treturn operator === \"!=\";\n\t\t\t\t}\n\t\t\t\tif ( !operator ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tresult += \"\";\n\n\t\t\t\t/* eslint-disable max-len */\n\n\t\t\t\treturn operator === \"=\" ? result === check :\n\t\t\t\t\toperator === \"!=\" ? result !== check :\n\t\t\t\t\toperator === \"^=\" ? check && result.indexOf( check ) === 0 :\n\t\t\t\t\toperator === \"*=\" ? check && result.indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"$=\" ? check && result.slice( -check.length ) === check :\n\t\t\t\t\toperator === \"~=\" ? ( \" \" + result.replace( rwhitespace, \" \" ) + \" \" ).indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"|=\" ? result === check || result.slice( 0, check.length + 1 ) === check + \"-\" :\n\t\t\t\t\tfalse;\n\t\t\t\t/* eslint-enable max-len */\n\n\t\t\t};\n\t\t},\n\n\t\t\"CHILD\": function( type, what, _argument, first, last ) {\n\t\t\tvar simple = type.slice( 0, 3 ) !== \"nth\",\n\t\t\t\tforward = type.slice( -4 ) !== \"last\",\n\t\t\t\tofType = what === \"of-type\";\n\n\t\t\treturn first === 1 && last === 0 ?\n\n\t\t\t\t// Shortcut for :nth-*(n)\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn !!elem.parentNode;\n\t\t\t\t} :\n\n\t\t\t\tfunction( elem, _context, xml ) {\n\t\t\t\t\tvar cache, uniqueCache, outerCache, node, nodeIndex, start,\n\t\t\t\t\t\tdir = simple !== forward ? \"nextSibling\" : \"previousSibling\",\n\t\t\t\t\t\tparent = elem.parentNode,\n\t\t\t\t\t\tname = ofType && elem.nodeName.toLowerCase(),\n\t\t\t\t\t\tuseCache = !xml && !ofType,\n\t\t\t\t\t\tdiff = false;\n\n\t\t\t\t\tif ( parent ) {\n\n\t\t\t\t\t\t// :(first|last|only)-(child|of-type)\n\t\t\t\t\t\tif ( simple ) {\n\t\t\t\t\t\t\twhile ( dir ) {\n\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\twhile ( ( node = node[ dir ] ) ) {\n\t\t\t\t\t\t\t\t\tif ( ofType ?\n\t\t\t\t\t\t\t\t\t\tnode.nodeName.toLowerCase() === name :\n\t\t\t\t\t\t\t\t\t\tnode.nodeType === 1 ) {\n\n\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Reverse direction for :only-* (if we haven't yet done so)\n\t\t\t\t\t\t\t\tstart = dir = type === \"only\" && !start && \"nextSibling\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tstart = [ forward ? parent.firstChild : parent.lastChild ];\n\n\t\t\t\t\t\t// non-xml :nth-child(...) stores cache data on `parent`\n\t\t\t\t\t\tif ( forward && useCache ) {\n\n\t\t\t\t\t\t\t// Seek `elem` from a previously-cached index\n\n\t\t\t\t\t\t\t// ...in a gzip-friendly way\n\t\t\t\t\t\t\tnode = parent;\n\t\t\t\t\t\t\touterCache = node[ expando ] || ( node[ expando ] = {} );\n\n\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t( outerCache[ node.uniqueID ] = {} );\n\n\t\t\t\t\t\t\tcache = uniqueCache[ type ] || [];\n\t\t\t\t\t\t\tnodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];\n\t\t\t\t\t\t\tdiff = nodeIndex && cache[ 2 ];\n\t\t\t\t\t\t\tnode = nodeIndex && parent.childNodes[ nodeIndex ];\n\n\t\t\t\t\t\t\twhile ( ( node = ++nodeIndex && node && node[ dir ] ||\n\n\t\t\t\t\t\t\t\t// Fallback to seeking `elem` from the start\n\t\t\t\t\t\t\t\t( diff = nodeIndex = 0 ) || start.pop() ) ) {\n\n\t\t\t\t\t\t\t\t// When found, cache indexes on `parent` and break\n\t\t\t\t\t\t\t\tif ( node.nodeType === 1 && ++diff && node === elem ) {\n\t\t\t\t\t\t\t\t\tuniqueCache[ type ] = [ dirruns, nodeIndex, diff ];\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t// Use previously-cached element index if available\n\t\t\t\t\t\t\tif ( useCache ) {\n\n\t\t\t\t\t\t\t\t// ...in a gzip-friendly way\n\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\touterCache = node[ expando ] || ( node[ expando ] = {} );\n\n\t\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t\t( outerCache[ node.uniqueID ] = {} );\n\n\t\t\t\t\t\t\t\tcache = uniqueCache[ type ] || [];\n\t\t\t\t\t\t\t\tnodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];\n\t\t\t\t\t\t\t\tdiff = nodeIndex;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// xml :nth-child(...)\n\t\t\t\t\t\t\t// or :nth-last-child(...) or :nth(-last)?-of-type(...)\n\t\t\t\t\t\t\tif ( diff === false ) {\n\n\t\t\t\t\t\t\t\t// Use the same loop as above to seek `elem` from the start\n\t\t\t\t\t\t\t\twhile ( ( node = ++nodeIndex && node && node[ dir ] ||\n\t\t\t\t\t\t\t\t\t( diff = nodeIndex = 0 ) || start.pop() ) ) {\n\n\t\t\t\t\t\t\t\t\tif ( ( ofType ?\n\t\t\t\t\t\t\t\t\t\tnode.nodeName.toLowerCase() === name :\n\t\t\t\t\t\t\t\t\t\tnode.nodeType === 1 ) &&\n\t\t\t\t\t\t\t\t\t\t++diff ) {\n\n\t\t\t\t\t\t\t\t\t\t// Cache the index of each encountered element\n\t\t\t\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t\t\t\touterCache = node[ expando ] ||\n\t\t\t\t\t\t\t\t\t\t\t\t( node[ expando ] = {} );\n\n\t\t\t\t\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t\t\t\t\t( outerCache[ node.uniqueID ] = {} );\n\n\t\t\t\t\t\t\t\t\t\t\tuniqueCache[ type ] = [ dirruns, diff ];\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tif ( node === elem ) {\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Incorporate the offset, then check against cycle size\n\t\t\t\t\t\tdiff -= last;\n\t\t\t\t\t\treturn diff === first || ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t},\n\n\t\t\"PSEUDO\": function( pseudo, argument ) {\n\n\t\t\t// pseudo-class names are case-insensitive\n\t\t\t// http://www.w3.org/TR/selectors/#pseudo-classes\n\t\t\t// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\n\t\t\t// Remember that setFilters inherits from pseudos\n\t\t\tvar args,\n\t\t\t\tfn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||\n\t\t\t\t\tSizzle.error( \"unsupported pseudo: \" + pseudo );\n\n\t\t\t// The user may use createPseudo to indicate that\n\t\t\t// arguments are needed to create the filter function\n\t\t\t// just as Sizzle does\n\t\t\tif ( fn[ expando ] ) {\n\t\t\t\treturn fn( argument );\n\t\t\t}\n\n\t\t\t// But maintain support for old signatures\n\t\t\tif ( fn.length > 1 ) {\n\t\t\t\targs = [ pseudo, pseudo, \"\", argument ];\n\t\t\t\treturn Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?\n\t\t\t\t\tmarkFunction( function( seed, matches ) {\n\t\t\t\t\t\tvar idx,\n\t\t\t\t\t\t\tmatched = fn( seed, argument ),\n\t\t\t\t\t\t\ti = matched.length;\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tidx = indexOf( seed, matched[ i ] );\n\t\t\t\t\t\t\tseed[ idx ] = !( matches[ idx ] = matched[ i ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} ) :\n\t\t\t\t\tfunction( elem ) {\n\t\t\t\t\t\treturn fn( elem, 0, args );\n\t\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn fn;\n\t\t}\n\t},\n\n\tpseudos: {\n\n\t\t// Potentially complex pseudos\n\t\t\"not\": markFunction( function( selector ) {\n\n\t\t\t// Trim the selector passed to compile\n\t\t\t// to avoid treating leading and trailing\n\t\t\t// spaces as combinators\n\t\t\tvar input = [],\n\t\t\t\tresults = [],\n\t\t\t\tmatcher = compile( selector.replace( rtrim, \"$1\" ) );\n\n\t\t\treturn matcher[ expando ] ?\n\t\t\t\tmarkFunction( function( seed, matches, _context, xml ) {\n\t\t\t\t\tvar elem,\n\t\t\t\t\t\tunmatched = matcher( seed, null, xml, [] ),\n\t\t\t\t\t\ti = seed.length;\n\n\t\t\t\t\t// Match elements unmatched by `matcher`\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( ( elem = unmatched[ i ] ) ) {\n\t\t\t\t\t\t\tseed[ i ] = !( matches[ i ] = elem );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} ) :\n\t\t\t\tfunction( elem, _context, xml ) {\n\t\t\t\t\tinput[ 0 ] = elem;\n\t\t\t\t\tmatcher( input, null, xml, results );\n\n\t\t\t\t\t// Don't keep the element (issue #299)\n\t\t\t\t\tinput[ 0 ] = null;\n\t\t\t\t\treturn !results.pop();\n\t\t\t\t};\n\t\t} ),\n\n\t\t\"has\": markFunction( function( selector ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn Sizzle( selector, elem ).length > 0;\n\t\t\t};\n\t\t} ),\n\n\t\t\"contains\": markFunction( function( text ) {\n\t\t\ttext = text.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn ( elem.textContent || getText( elem ) ).indexOf( text ) > -1;\n\t\t\t};\n\t\t} ),\n\n\t\t// \"Whether an element is represented by a :lang() selector\n\t\t// is based solely on the element's language value\n\t\t// being equal to the identifier C,\n\t\t// or beginning with the identifier C immediately followed by \"-\".\n\t\t// The matching of C against the element's language value is performed case-insensitively.\n\t\t// The identifier C does not have to be a valid language name.\"\n\t\t// http://www.w3.org/TR/selectors/#lang-pseudo\n\t\t\"lang\": markFunction( function( lang ) {\n\n\t\t\t// lang value must be a valid identifier\n\t\t\tif ( !ridentifier.test( lang || \"\" ) ) {\n\t\t\t\tSizzle.error( \"unsupported lang: \" + lang );\n\t\t\t}\n\t\t\tlang = lang.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn function( elem ) {\n\t\t\t\tvar elemLang;\n\t\t\t\tdo {\n\t\t\t\t\tif ( ( elemLang = documentIsHTML ?\n\t\t\t\t\t\telem.lang :\n\t\t\t\t\t\telem.getAttribute( \"xml:lang\" ) || elem.getAttribute( \"lang\" ) ) ) {\n\n\t\t\t\t\t\telemLang = elemLang.toLowerCase();\n\t\t\t\t\t\treturn elemLang === lang || elemLang.indexOf( lang + \"-\" ) === 0;\n\t\t\t\t\t}\n\t\t\t\t} while ( ( elem = elem.parentNode ) && elem.nodeType === 1 );\n\t\t\t\treturn false;\n\t\t\t};\n\t\t} ),\n\n\t\t// Miscellaneous\n\t\t\"target\": function( elem ) {\n\t\t\tvar hash = window.location && window.location.hash;\n\t\t\treturn hash && hash.slice( 1 ) === elem.id;\n\t\t},\n\n\t\t\"root\": function( elem ) {\n\t\t\treturn elem === docElem;\n\t\t},\n\n\t\t\"focus\": function( elem ) {\n\t\t\treturn elem === document.activeElement &&\n\t\t\t\t( !document.hasFocus || document.hasFocus() ) &&\n\t\t\t\t!!( elem.type || elem.href || ~elem.tabIndex );\n\t\t},\n\n\t\t// Boolean properties\n\t\t\"enabled\": createDisabledPseudo( false ),\n\t\t\"disabled\": createDisabledPseudo( true ),\n\n\t\t\"checked\": function( elem ) {\n\n\t\t\t// In CSS3, :checked should return both checked and selected elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\tvar nodeName = elem.nodeName.toLowerCase();\n\t\t\treturn ( nodeName === \"input\" && !!elem.checked ) ||\n\t\t\t\t( nodeName === \"option\" && !!elem.selected );\n\t\t},\n\n\t\t\"selected\": function( elem ) {\n\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\t// eslint-disable-next-line no-unused-expressions\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\t// Contents\n\t\t\"empty\": function( elem ) {\n\n\t\t\t// http://www.w3.org/TR/selectors/#empty-pseudo\n\t\t\t// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),\n\t\t\t//   but not by others (comment: 8; processing instruction: 7; etc.)\n\t\t\t// nodeType < 6 works because attributes (2) do not appear as children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tif ( elem.nodeType < 6 ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\t\"parent\": function( elem ) {\n\t\t\treturn !Expr.pseudos[ \"empty\" ]( elem );\n\t\t},\n\n\t\t// Element/input types\n\t\t\"header\": function( elem ) {\n\t\t\treturn rheader.test( elem.nodeName );\n\t\t},\n\n\t\t\"input\": function( elem ) {\n\t\t\treturn rinputs.test( elem.nodeName );\n\t\t},\n\n\t\t\"button\": function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && elem.type === \"button\" || name === \"button\";\n\t\t},\n\n\t\t\"text\": function( elem ) {\n\t\t\tvar attr;\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" &&\n\t\t\t\telem.type === \"text\" &&\n\n\t\t\t\t// Support: IE<8\n\t\t\t\t// New HTML5 attribute values (e.g., \"search\") appear with elem.type === \"text\"\n\t\t\t\t( ( attr = elem.getAttribute( \"type\" ) ) == null ||\n\t\t\t\t\tattr.toLowerCase() === \"text\" );\n\t\t},\n\n\t\t// Position-in-collection\n\t\t\"first\": createPositionalPseudo( function() {\n\t\t\treturn [ 0 ];\n\t\t} ),\n\n\t\t\"last\": createPositionalPseudo( function( _matchIndexes, length ) {\n\t\t\treturn [ length - 1 ];\n\t\t} ),\n\n\t\t\"eq\": createPositionalPseudo( function( _matchIndexes, length, argument ) {\n\t\t\treturn [ argument < 0 ? argument + length : argument ];\n\t\t} ),\n\n\t\t\"even\": createPositionalPseudo( function( matchIndexes, length ) {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t} ),\n\n\t\t\"odd\": createPositionalPseudo( function( matchIndexes, length ) {\n\t\t\tvar i = 1;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t} ),\n\n\t\t\"lt\": createPositionalPseudo( function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ?\n\t\t\t\targument + length :\n\t\t\t\targument > length ?\n\t\t\t\t\tlength :\n\t\t\t\t\targument;\n\t\t\tfor ( ; --i >= 0; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t} ),\n\n\t\t\"gt\": createPositionalPseudo( function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; ++i < length; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t} )\n\t}\n};\n\nExpr.pseudos[ \"nth\" ] = Expr.pseudos[ \"eq\" ];\n\n// Add button/input type pseudos\nfor ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {\n\tExpr.pseudos[ i ] = createInputPseudo( i );\n}\nfor ( i in { submit: true, reset: true } ) {\n\tExpr.pseudos[ i ] = createButtonPseudo( i );\n}\n\n// Easy API for creating new setFilters\nfunction setFilters() {}\nsetFilters.prototype = Expr.filters = Expr.pseudos;\nExpr.setFilters = new setFilters();\n\ntokenize = Sizzle.tokenize = function( selector, parseOnly ) {\n\tvar matched, match, tokens, type,\n\t\tsoFar, groups, preFilters,\n\t\tcached = tokenCache[ selector + \" \" ];\n\n\tif ( cached ) {\n\t\treturn parseOnly ? 0 : cached.slice( 0 );\n\t}\n\n\tsoFar = selector;\n\tgroups = [];\n\tpreFilters = Expr.preFilter;\n\n\twhile ( soFar ) {\n\n\t\t// Comma and first run\n\t\tif ( !matched || ( match = rcomma.exec( soFar ) ) ) {\n\t\t\tif ( match ) {\n\n\t\t\t\t// Don't consume trailing commas as valid\n\t\t\t\tsoFar = soFar.slice( match[ 0 ].length ) || soFar;\n\t\t\t}\n\t\t\tgroups.push( ( tokens = [] ) );\n\t\t}\n\n\t\tmatched = false;\n\n\t\t// Combinators\n\t\tif ( ( match = rcombinators.exec( soFar ) ) ) {\n\t\t\tmatched = match.shift();\n\t\t\ttokens.push( {\n\t\t\t\tvalue: matched,\n\n\t\t\t\t// Cast descendant combinators to space\n\t\t\t\ttype: match[ 0 ].replace( rtrim, \" \" )\n\t\t\t} );\n\t\t\tsoFar = soFar.slice( matched.length );\n\t\t}\n\n\t\t// Filters\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] ||\n\t\t\t\t( match = preFilters[ type ]( match ) ) ) ) {\n\t\t\t\tmatched = match.shift();\n\t\t\t\ttokens.push( {\n\t\t\t\t\tvalue: matched,\n\t\t\t\t\ttype: type,\n\t\t\t\t\tmatches: match\n\t\t\t\t} );\n\t\t\t\tsoFar = soFar.slice( matched.length );\n\t\t\t}\n\t\t}\n\n\t\tif ( !matched ) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Return the length of the invalid excess\n\t// if we're just parsing\n\t// Otherwise, throw an error or return tokens\n\treturn parseOnly ?\n\t\tsoFar.length :\n\t\tsoFar ?\n\t\t\tSizzle.error( selector ) :\n\n\t\t\t// Cache the tokens\n\t\t\ttokenCache( selector, groups ).slice( 0 );\n};\n\nfunction toSelector( tokens ) {\n\tvar i = 0,\n\t\tlen = tokens.length,\n\t\tselector = \"\";\n\tfor ( ; i < len; i++ ) {\n\t\tselector += tokens[ i ].value;\n\t}\n\treturn selector;\n}\n\nfunction addCombinator( matcher, combinator, base ) {\n\tvar dir = combinator.dir,\n\t\tskip = combinator.next,\n\t\tkey = skip || dir,\n\t\tcheckNonElements = base && key === \"parentNode\",\n\t\tdoneName = done++;\n\n\treturn combinator.first ?\n\n\t\t// Check against closest ancestor/preceding element\n\t\tfunction( elem, context, xml ) {\n\t\t\twhile ( ( elem = elem[ dir ] ) ) {\n\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\treturn matcher( elem, context, xml );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t} :\n\n\t\t// Check against all ancestor/preceding elements\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar oldCache, uniqueCache, outerCache,\n\t\t\t\tnewCache = [ dirruns, doneName ];\n\n\t\t\t// We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching\n\t\t\tif ( xml ) {\n\t\t\t\twhile ( ( elem = elem[ dir ] ) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\twhile ( ( elem = elem[ dir ] ) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\touterCache = elem[ expando ] || ( elem[ expando ] = {} );\n\n\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\tuniqueCache = outerCache[ elem.uniqueID ] ||\n\t\t\t\t\t\t\t( outerCache[ elem.uniqueID ] = {} );\n\n\t\t\t\t\t\tif ( skip && skip === elem.nodeName.toLowerCase() ) {\n\t\t\t\t\t\t\telem = elem[ dir ] || elem;\n\t\t\t\t\t\t} else if ( ( oldCache = uniqueCache[ key ] ) &&\n\t\t\t\t\t\t\toldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {\n\n\t\t\t\t\t\t\t// Assign to newCache so results back-propagate to previous elements\n\t\t\t\t\t\t\treturn ( newCache[ 2 ] = oldCache[ 2 ] );\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t// Reuse newcache so results back-propagate to previous elements\n\t\t\t\t\t\t\tuniqueCache[ key ] = newCache;\n\n\t\t\t\t\t\t\t// A match means we're done; a fail means we have to keep checking\n\t\t\t\t\t\t\tif ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) {\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n}\n\nfunction elementMatcher( matchers ) {\n\treturn matchers.length > 1 ?\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar i = matchers.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( !matchers[ i ]( elem, context, xml ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} :\n\t\tmatchers[ 0 ];\n}\n\nfunction multipleContexts( selector, contexts, results ) {\n\tvar i = 0,\n\t\tlen = contexts.length;\n\tfor ( ; i < len; i++ ) {\n\t\tSizzle( selector, contexts[ i ], results );\n\t}\n\treturn results;\n}\n\nfunction condense( unmatched, map, filter, context, xml ) {\n\tvar elem,\n\t\tnewUnmatched = [],\n\t\ti = 0,\n\t\tlen = unmatched.length,\n\t\tmapped = map != null;\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( ( elem = unmatched[ i ] ) ) {\n\t\t\tif ( !filter || filter( elem, context, xml ) ) {\n\t\t\t\tnewUnmatched.push( elem );\n\t\t\t\tif ( mapped ) {\n\t\t\t\t\tmap.push( i );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn newUnmatched;\n}\n\nfunction setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\n\tif ( postFilter && !postFilter[ expando ] ) {\n\t\tpostFilter = setMatcher( postFilter );\n\t}\n\tif ( postFinder && !postFinder[ expando ] ) {\n\t\tpostFinder = setMatcher( postFinder, postSelector );\n\t}\n\treturn markFunction( function( seed, results, context, xml ) {\n\t\tvar temp, i, elem,\n\t\t\tpreMap = [],\n\t\t\tpostMap = [],\n\t\t\tpreexisting = results.length,\n\n\t\t\t// Get initial elements from seed or context\n\t\t\telems = seed || multipleContexts(\n\t\t\t\tselector || \"*\",\n\t\t\t\tcontext.nodeType ? [ context ] : context,\n\t\t\t\t[]\n\t\t\t),\n\n\t\t\t// Prefilter to get matcher input, preserving a map for seed-results synchronization\n\t\t\tmatcherIn = preFilter && ( seed || !selector ) ?\n\t\t\t\tcondense( elems, preMap, preFilter, context, xml ) :\n\t\t\t\telems,\n\n\t\t\tmatcherOut = matcher ?\n\n\t\t\t\t// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\n\t\t\t\tpostFinder || ( seed ? preFilter : preexisting || postFilter ) ?\n\n\t\t\t\t\t// ...intermediate processing is necessary\n\t\t\t\t\t[] :\n\n\t\t\t\t\t// ...otherwise use results directly\n\t\t\t\t\tresults :\n\t\t\t\tmatcherIn;\n\n\t\t// Find primary matches\n\t\tif ( matcher ) {\n\t\t\tmatcher( matcherIn, matcherOut, context, xml );\n\t\t}\n\n\t\t// Apply postFilter\n\t\tif ( postFilter ) {\n\t\t\ttemp = condense( matcherOut, postMap );\n\t\t\tpostFilter( temp, [], context, xml );\n\n\t\t\t// Un-match failing elements by moving them back to matcherIn\n\t\t\ti = temp.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( ( elem = temp[ i ] ) ) {\n\t\t\t\t\tmatcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( seed ) {\n\t\t\tif ( postFinder || preFilter ) {\n\t\t\t\tif ( postFinder ) {\n\n\t\t\t\t\t// Get the final matcherOut by condensing this intermediate into postFinder contexts\n\t\t\t\t\ttemp = [];\n\t\t\t\t\ti = matcherOut.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( ( elem = matcherOut[ i ] ) ) {\n\n\t\t\t\t\t\t\t// Restore matcherIn since elem is not yet a final match\n\t\t\t\t\t\t\ttemp.push( ( matcherIn[ i ] = elem ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpostFinder( null, ( matcherOut = [] ), temp, xml );\n\t\t\t\t}\n\n\t\t\t\t// Move matched elements from seed to results to keep them synchronized\n\t\t\t\ti = matcherOut.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tif ( ( elem = matcherOut[ i ] ) &&\n\t\t\t\t\t\t( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) {\n\n\t\t\t\t\t\tseed[ temp ] = !( results[ temp ] = elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Add elements to results, through postFinder if defined\n\t\t} else {\n\t\t\tmatcherOut = condense(\n\t\t\t\tmatcherOut === results ?\n\t\t\t\t\tmatcherOut.splice( preexisting, matcherOut.length ) :\n\t\t\t\t\tmatcherOut\n\t\t\t);\n\t\t\tif ( postFinder ) {\n\t\t\t\tpostFinder( null, results, matcherOut, xml );\n\t\t\t} else {\n\t\t\t\tpush.apply( results, matcherOut );\n\t\t\t}\n\t\t}\n\t} );\n}\n\nfunction matcherFromTokens( tokens ) {\n\tvar checkContext, matcher, j,\n\t\tlen = tokens.length,\n\t\tleadingRelative = Expr.relative[ tokens[ 0 ].type ],\n\t\timplicitRelative = leadingRelative || Expr.relative[ \" \" ],\n\t\ti = leadingRelative ? 1 : 0,\n\n\t\t// The foundational matcher ensures that elements are reachable from top-level context(s)\n\t\tmatchContext = addCombinator( function( elem ) {\n\t\t\treturn elem === checkContext;\n\t\t}, implicitRelative, true ),\n\t\tmatchAnyContext = addCombinator( function( elem ) {\n\t\t\treturn indexOf( checkContext, elem ) > -1;\n\t\t}, implicitRelative, true ),\n\t\tmatchers = [ function( elem, context, xml ) {\n\t\t\tvar ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\n\t\t\t\t( checkContext = context ).nodeType ?\n\t\t\t\t\tmatchContext( elem, context, xml ) :\n\t\t\t\t\tmatchAnyContext( elem, context, xml ) );\n\n\t\t\t// Avoid hanging onto element (issue #299)\n\t\t\tcheckContext = null;\n\t\t\treturn ret;\n\t\t} ];\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) {\n\t\t\tmatchers = [ addCombinator( elementMatcher( matchers ), matcher ) ];\n\t\t} else {\n\t\t\tmatcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches );\n\n\t\t\t// Return special upon seeing a positional matcher\n\t\t\tif ( matcher[ expando ] ) {\n\n\t\t\t\t// Find the next relative operator (if any) for proper handling\n\t\t\t\tj = ++i;\n\t\t\t\tfor ( ; j < len; j++ ) {\n\t\t\t\t\tif ( Expr.relative[ tokens[ j ].type ] ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn setMatcher(\n\t\t\t\t\ti > 1 && elementMatcher( matchers ),\n\t\t\t\t\ti > 1 && toSelector(\n\n\t\t\t\t\t// If the preceding token was a descendant combinator, insert an implicit any-element `*`\n\t\t\t\t\ttokens\n\t\t\t\t\t\t.slice( 0, i - 1 )\n\t\t\t\t\t\t.concat( { value: tokens[ i - 2 ].type === \" \" ? \"*\" : \"\" } )\n\t\t\t\t\t).replace( rtrim, \"$1\" ),\n\t\t\t\t\tmatcher,\n\t\t\t\t\ti < j && matcherFromTokens( tokens.slice( i, j ) ),\n\t\t\t\t\tj < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ),\n\t\t\t\t\tj < len && toSelector( tokens )\n\t\t\t\t);\n\t\t\t}\n\t\t\tmatchers.push( matcher );\n\t\t}\n\t}\n\n\treturn elementMatcher( matchers );\n}\n\nfunction matcherFromGroupMatchers( elementMatchers, setMatchers ) {\n\tvar bySet = setMatchers.length > 0,\n\t\tbyElement = elementMatchers.length > 0,\n\t\tsuperMatcher = function( seed, context, xml, results, outermost ) {\n\t\t\tvar elem, j, matcher,\n\t\t\t\tmatchedCount = 0,\n\t\t\t\ti = \"0\",\n\t\t\t\tunmatched = seed && [],\n\t\t\t\tsetMatched = [],\n\t\t\t\tcontextBackup = outermostContext,\n\n\t\t\t\t// We must always have either seed elements or outermost context\n\t\t\t\telems = seed || byElement && Expr.find[ \"TAG\" ]( \"*\", outermost ),\n\n\t\t\t\t// Use integer dirruns iff this is the outermost matcher\n\t\t\t\tdirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ),\n\t\t\t\tlen = elems.length;\n\n\t\t\tif ( outermost ) {\n\n\t\t\t\t// Support: IE 11+, Edge 17 - 18+\n\t\t\t\t// IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n\t\t\t\t// two documents; shallow comparisons work.\n\t\t\t\t// eslint-disable-next-line eqeqeq\n\t\t\t\toutermostContext = context == document || context || outermost;\n\t\t\t}\n\n\t\t\t// Add elements passing elementMatchers directly to results\n\t\t\t// Support: IE<9, Safari\n\t\t\t// Tolerate NodeList properties (IE: \"length\"; Safari: <number>) matching elements by id\n\t\t\tfor ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) {\n\t\t\t\tif ( byElement && elem ) {\n\t\t\t\t\tj = 0;\n\n\t\t\t\t\t// Support: IE 11+, Edge 17 - 18+\n\t\t\t\t\t// IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n\t\t\t\t\t// two documents; shallow comparisons work.\n\t\t\t\t\t// eslint-disable-next-line eqeqeq\n\t\t\t\t\tif ( !context && elem.ownerDocument != document ) {\n\t\t\t\t\t\tsetDocument( elem );\n\t\t\t\t\t\txml = !documentIsHTML;\n\t\t\t\t\t}\n\t\t\t\t\twhile ( ( matcher = elementMatchers[ j++ ] ) ) {\n\t\t\t\t\t\tif ( matcher( elem, context || document, xml ) ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( outermost ) {\n\t\t\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Track unmatched elements for set filters\n\t\t\t\tif ( bySet ) {\n\n\t\t\t\t\t// They will have gone through all possible matchers\n\t\t\t\t\tif ( ( elem = !matcher && elem ) ) {\n\t\t\t\t\t\tmatchedCount--;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Lengthen the array for every element, matched or not\n\t\t\t\t\tif ( seed ) {\n\t\t\t\t\t\tunmatched.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// `i` is now the count of elements visited above, and adding it to `matchedCount`\n\t\t\t// makes the latter nonnegative.\n\t\t\tmatchedCount += i;\n\n\t\t\t// Apply set filters to unmatched elements\n\t\t\t// NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`\n\t\t\t// equals `i`), unless we didn't visit _any_ elements in the above loop because we have\n\t\t\t// no element matchers and no seed.\n\t\t\t// Incrementing an initially-string \"0\" `i` allows `i` to remain a string only in that\n\t\t\t// case, which will result in a \"00\" `matchedCount` that differs from `i` but is also\n\t\t\t// numerically zero.\n\t\t\tif ( bySet && i !== matchedCount ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( ( matcher = setMatchers[ j++ ] ) ) {\n\t\t\t\t\tmatcher( unmatched, setMatched, context, xml );\n\t\t\t\t}\n\n\t\t\t\tif ( seed ) {\n\n\t\t\t\t\t// Reintegrate element matches to eliminate the need for sorting\n\t\t\t\t\tif ( matchedCount > 0 ) {\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tif ( !( unmatched[ i ] || setMatched[ i ] ) ) {\n\t\t\t\t\t\t\t\tsetMatched[ i ] = pop.call( results );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Discard index placeholder values to get only actual matches\n\t\t\t\t\tsetMatched = condense( setMatched );\n\t\t\t\t}\n\n\t\t\t\t// Add matches to results\n\t\t\t\tpush.apply( results, setMatched );\n\n\t\t\t\t// Seedless set matches succeeding multiple successful matchers stipulate sorting\n\t\t\t\tif ( outermost && !seed && setMatched.length > 0 &&\n\t\t\t\t\t( matchedCount + setMatchers.length ) > 1 ) {\n\n\t\t\t\t\tSizzle.uniqueSort( results );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Override manipulation of globals by nested matchers\n\t\t\tif ( outermost ) {\n\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\toutermostContext = contextBackup;\n\t\t\t}\n\n\t\t\treturn unmatched;\n\t\t};\n\n\treturn bySet ?\n\t\tmarkFunction( superMatcher ) :\n\t\tsuperMatcher;\n}\n\ncompile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {\n\tvar i,\n\t\tsetMatchers = [],\n\t\telementMatchers = [],\n\t\tcached = compilerCache[ selector + \" \" ];\n\n\tif ( !cached ) {\n\n\t\t// Generate a function of recursive functions that can be used to check each element\n\t\tif ( !match ) {\n\t\t\tmatch = tokenize( selector );\n\t\t}\n\t\ti = match.length;\n\t\twhile ( i-- ) {\n\t\t\tcached = matcherFromTokens( match[ i ] );\n\t\t\tif ( cached[ expando ] ) {\n\t\t\t\tsetMatchers.push( cached );\n\t\t\t} else {\n\t\t\t\telementMatchers.push( cached );\n\t\t\t}\n\t\t}\n\n\t\t// Cache the compiled function\n\t\tcached = compilerCache(\n\t\t\tselector,\n\t\t\tmatcherFromGroupMatchers( elementMatchers, setMatchers )\n\t\t);\n\n\t\t// Save selector and tokenization\n\t\tcached.selector = selector;\n\t}\n\treturn cached;\n};\n\n/**\n * A low-level selection function that works with Sizzle's compiled\n *  selector functions\n * @param {String|Function} selector A selector or a pre-compiled\n *  selector function built with Sizzle.compile\n * @param {Element} context\n * @param {Array} [results]\n * @param {Array} [seed] A set of elements to match against\n */\nselect = Sizzle.select = function( selector, context, results, seed ) {\n\tvar i, tokens, token, type, find,\n\t\tcompiled = typeof selector === \"function\" && selector,\n\t\tmatch = !seed && tokenize( ( selector = compiled.selector || selector ) );\n\n\tresults = results || [];\n\n\t// Try to minimize operations if there is only one selector in the list and no seed\n\t// (the latter of which guarantees us context)\n\tif ( match.length === 1 ) {\n\n\t\t// Reduce context if the leading compound selector is an ID\n\t\ttokens = match[ 0 ] = match[ 0 ].slice( 0 );\n\t\tif ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === \"ID\" &&\n\t\t\tcontext.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) {\n\n\t\t\tcontext = ( Expr.find[ \"ID\" ]( token.matches[ 0 ]\n\t\t\t\t.replace( runescape, funescape ), context ) || [] )[ 0 ];\n\t\t\tif ( !context ) {\n\t\t\t\treturn results;\n\n\t\t\t// Precompiled matchers will still verify ancestry, so step up a level\n\t\t\t} else if ( compiled ) {\n\t\t\t\tcontext = context.parentNode;\n\t\t\t}\n\n\t\t\tselector = selector.slice( tokens.shift().value.length );\n\t\t}\n\n\t\t// Fetch a seed set for right-to-left matching\n\t\ti = matchExpr[ \"needsContext\" ].test( selector ) ? 0 : tokens.length;\n\t\twhile ( i-- ) {\n\t\t\ttoken = tokens[ i ];\n\n\t\t\t// Abort if we hit a combinator\n\t\t\tif ( Expr.relative[ ( type = token.type ) ] ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( ( find = Expr.find[ type ] ) ) {\n\n\t\t\t\t// Search, expanding context for leading sibling combinators\n\t\t\t\tif ( ( seed = find(\n\t\t\t\t\ttoken.matches[ 0 ].replace( runescape, funescape ),\n\t\t\t\t\trsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) ||\n\t\t\t\t\t\tcontext\n\t\t\t\t) ) ) {\n\n\t\t\t\t\t// If seed is empty or no tokens remain, we can return early\n\t\t\t\t\ttokens.splice( i, 1 );\n\t\t\t\t\tselector = seed.length && toSelector( tokens );\n\t\t\t\t\tif ( !selector ) {\n\t\t\t\t\t\tpush.apply( results, seed );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Compile and execute a filtering function if one is not provided\n\t// Provide `match` to avoid retokenization if we modified the selector above\n\t( compiled || compile( selector, match ) )(\n\t\tseed,\n\t\tcontext,\n\t\t!documentIsHTML,\n\t\tresults,\n\t\t!context || rsibling.test( selector ) && testContext( context.parentNode ) || context\n\t);\n\treturn results;\n};\n\n// One-time assignments\n\n// Sort stability\nsupport.sortStable = expando.split( \"\" ).sort( sortOrder ).join( \"\" ) === expando;\n\n// Support: Chrome 14-35+\n// Always assume duplicates if they aren't passed to the comparison function\nsupport.detectDuplicates = !!hasDuplicate;\n\n// Initialize against the default document\nsetDocument();\n\n// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)\n// Detached nodes confoundingly follow *each other*\nsupport.sortDetached = assert( function( el ) {\n\n\t// Should return 1, but returns 4 (following)\n\treturn el.compareDocumentPosition( document.createElement( \"fieldset\" ) ) & 1;\n} );\n\n// Support: IE<8\n// Prevent attribute/property \"interpolation\"\n// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\nif ( !assert( function( el ) {\n\tel.innerHTML = \"<a href='#'></a>\";\n\treturn el.firstChild.getAttribute( \"href\" ) === \"#\";\n} ) ) {\n\taddHandle( \"type|href|height|width\", function( elem, name, isXML ) {\n\t\tif ( !isXML ) {\n\t\t\treturn elem.getAttribute( name, name.toLowerCase() === \"type\" ? 1 : 2 );\n\t\t}\n\t} );\n}\n\n// Support: IE<9\n// Use defaultValue in place of getAttribute(\"value\")\nif ( !support.attributes || !assert( function( el ) {\n\tel.innerHTML = \"<input/>\";\n\tel.firstChild.setAttribute( \"value\", \"\" );\n\treturn el.firstChild.getAttribute( \"value\" ) === \"\";\n} ) ) {\n\taddHandle( \"value\", function( elem, _name, isXML ) {\n\t\tif ( !isXML && elem.nodeName.toLowerCase() === \"input\" ) {\n\t\t\treturn elem.defaultValue;\n\t\t}\n\t} );\n}\n\n// Support: IE<9\n// Use getAttributeNode to fetch booleans when getAttribute lies\nif ( !assert( function( el ) {\n\treturn el.getAttribute( \"disabled\" ) == null;\n} ) ) {\n\taddHandle( booleans, function( elem, name, isXML ) {\n\t\tvar val;\n\t\tif ( !isXML ) {\n\t\t\treturn elem[ name ] === true ? name.toLowerCase() :\n\t\t\t\t( val = elem.getAttributeNode( name ) ) && val.specified ?\n\t\t\t\t\tval.value :\n\t\t\t\t\tnull;\n\t\t}\n\t} );\n}\n\nreturn Sizzle;\n\n} )( window );\n\n\n\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\n\n// Deprecated\njQuery.expr[ \":\" ] = jQuery.expr.pseudos;\njQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\njQuery.escapeSelector = Sizzle.escape;\n\n\n\n\nvar dir = function( elem, dir, until ) {\n\tvar matched = [],\n\t\ttruncate = until !== undefined;\n\n\twhile ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {\n\t\tif ( elem.nodeType === 1 ) {\n\t\t\tif ( truncate && jQuery( elem ).is( until ) ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tmatched.push( elem );\n\t\t}\n\t}\n\treturn matched;\n};\n\n\nvar siblings = function( n, elem ) {\n\tvar matched = [];\n\n\tfor ( ; n; n = n.nextSibling ) {\n\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\tmatched.push( n );\n\t\t}\n\t}\n\n\treturn matched;\n};\n\n\nvar rneedsContext = jQuery.expr.match.needsContext;\n\n\n\nfunction nodeName( elem, name ) {\n\n  return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n\n};\nvar rsingleTag = ( /^<([a-z][^\\/\\0>:\\x20\\t\\r\\n\\f]*)[\\x20\\t\\r\\n\\f]*\\/?>(?:<\\/\\1>|)$/i );\n\n\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, not ) {\n\tif ( isFunction( qualifier ) ) {\n\t\treturn jQuery.grep( elements, function( elem, i ) {\n\t\t\treturn !!qualifier.call( elem, i, elem ) !== not;\n\t\t} );\n\t}\n\n\t// Single element\n\tif ( qualifier.nodeType ) {\n\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\treturn ( elem === qualifier ) !== not;\n\t\t} );\n\t}\n\n\t// Arraylike of elements (jQuery, arguments, Array)\n\tif ( typeof qualifier !== \"string\" ) {\n\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\treturn ( indexOf.call( qualifier, elem ) > -1 ) !== not;\n\t\t} );\n\t}\n\n\t// Filtered directly for both simple and complex selectors\n\treturn jQuery.filter( qualifier, elements, not );\n}\n\njQuery.filter = function( expr, elems, not ) {\n\tvar elem = elems[ 0 ];\n\n\tif ( not ) {\n\t\texpr = \":not(\" + expr + \")\";\n\t}\n\n\tif ( elems.length === 1 && elem.nodeType === 1 ) {\n\t\treturn jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [];\n\t}\n\n\treturn jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {\n\t\treturn elem.nodeType === 1;\n\t} ) );\n};\n\njQuery.fn.extend( {\n\tfind: function( selector ) {\n\t\tvar i, ret,\n\t\t\tlen = this.length,\n\t\t\tself = this;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn this.pushStack( jQuery( selector ).filter( function() {\n\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} ) );\n\t\t}\n\n\t\tret = this.pushStack( [] );\n\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\tjQuery.find( selector, self[ i ], ret );\n\t\t}\n\n\t\treturn len > 1 ? jQuery.uniqueSort( ret ) : ret;\n\t},\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow( this, selector || [], false ) );\n\t},\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow( this, selector || [], true ) );\n\t},\n\tis: function( selector ) {\n\t\treturn !!winnow(\n\t\t\tthis,\n\n\t\t\t// If this is a positional/relative selector, check membership in the returned set\n\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\ttypeof selector === \"string\" && rneedsContext.test( selector ) ?\n\t\t\t\tjQuery( selector ) :\n\t\t\t\tselector || [],\n\t\t\tfalse\n\t\t).length;\n\t}\n} );\n\n\n// Initialize a jQuery object\n\n\n// A central reference to the root jQuery(document)\nvar rootjQuery,\n\n\t// A simple way to check for HTML strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\t// Strict HTML recognition (#11290: must start with <)\n\t// Shortcut simple #id case for speed\n\trquickExpr = /^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]+))$/,\n\n\tinit = jQuery.fn.init = function( selector, context, root ) {\n\t\tvar match, elem;\n\n\t\t// HANDLE: $(\"\"), $(null), $(undefined), $(false)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Method init() accepts an alternate rootjQuery\n\t\t// so migrate can support jQuery.sub (gh-2101)\n\t\troot = root || rootjQuery;\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\tif ( selector[ 0 ] === \"<\" &&\n\t\t\t\tselector[ selector.length - 1 ] === \">\" &&\n\t\t\t\tselector.length >= 3 ) {\n\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = rquickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Match html or make sure no context is specified for #id\n\t\t\tif ( match && ( match[ 1 ] || !context ) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[ 1 ] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[ 0 ] : context;\n\n\t\t\t\t\t// Option to run scripts is true for back-compat\n\t\t\t\t\t// Intentionally let the error be thrown if parseHTML is not present\n\t\t\t\t\tjQuery.merge( this, jQuery.parseHTML(\n\t\t\t\t\t\tmatch[ 1 ],\n\t\t\t\t\t\tcontext && context.nodeType ? context.ownerDocument || context : document,\n\t\t\t\t\t\ttrue\n\t\t\t\t\t) );\n\n\t\t\t\t\t// HANDLE: $(html, props)\n\t\t\t\t\tif ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\tfor ( match in context ) {\n\n\t\t\t\t\t\t\t// Properties of context are called as methods if possible\n\t\t\t\t\t\t\tif ( isFunction( this[ match ] ) ) {\n\t\t\t\t\t\t\t\tthis[ match ]( context[ match ] );\n\n\t\t\t\t\t\t\t// ...and otherwise set as attributes\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.attr( match, context[ match ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn this;\n\n\t\t\t\t// HANDLE: $(#id)\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[ 2 ] );\n\n\t\t\t\t\tif ( elem ) {\n\n\t\t\t\t\t\t// Inject the element directly into the jQuery object\n\t\t\t\t\t\tthis[ 0 ] = elem;\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || root ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(DOMElement)\n\t\t} else if ( selector.nodeType ) {\n\t\t\tthis[ 0 ] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( isFunction( selector ) ) {\n\t\t\treturn root.ready !== undefined ?\n\t\t\t\troot.ready( selector ) :\n\n\t\t\t\t// Execute immediately if ready is not present\n\t\t\t\tselector( jQuery );\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t};\n\n// Give the init function the jQuery prototype for later instantiation\ninit.prototype = jQuery.fn;\n\n// Initialize central reference\nrootjQuery = jQuery( document );\n\n\nvar rparentsprev = /^(?:parents|prev(?:Until|All))/,\n\n\t// Methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend( {\n\thas: function( target ) {\n\t\tvar targets = jQuery( target, this ),\n\t\t\tl = targets.length;\n\n\t\treturn this.filter( function() {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[ i ] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tmatched = [],\n\t\t\ttargets = typeof selectors !== \"string\" && jQuery( selectors );\n\n\t\t// Positional selectors never match, since there's no _selection_ context\n\t\tif ( !rneedsContext.test( selectors ) ) {\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tfor ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {\n\n\t\t\t\t\t// Always skip document fragments\n\t\t\t\t\tif ( cur.nodeType < 11 && ( targets ?\n\t\t\t\t\t\ttargets.index( cur ) > -1 :\n\n\t\t\t\t\t\t// Don't pass non-elements to Sizzle\n\t\t\t\t\t\tcur.nodeType === 1 &&\n\t\t\t\t\t\t\tjQuery.find.matchesSelector( cur, selectors ) ) ) {\n\n\t\t\t\t\t\tmatched.push( cur );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );\n\t},\n\n\t// Determine the position of an element within the set\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;\n\t\t}\n\n\t\t// Index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn indexOf.call( jQuery( elem ), this[ 0 ] );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn indexOf.call( this,\n\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[ 0 ] : elem\n\t\t);\n\t},\n\n\tadd: function( selector, context ) {\n\t\treturn this.pushStack(\n\t\t\tjQuery.uniqueSort(\n\t\t\t\tjQuery.merge( this.get(), jQuery( selector, context ) )\n\t\t\t)\n\t\t);\n\t},\n\n\taddBack: function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter( selector )\n\t\t);\n\t}\n} );\n\nfunction sibling( cur, dir ) {\n\twhile ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}\n\treturn cur;\n}\n\njQuery.each( {\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, _i, until ) {\n\t\treturn dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn sibling( elem, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn sibling( elem, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, _i, until ) {\n\t\treturn dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, _i, until ) {\n\t\treturn dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn siblings( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn siblings( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\tif ( elem.contentDocument != null &&\n\n\t\t\t// Support: IE 11+\n\t\t\t// <object> elements with no `data` attribute has an object\n\t\t\t// `contentDocument` with a `null` prototype.\n\t\t\tgetProto( elem.contentDocument ) ) {\n\n\t\t\treturn elem.contentDocument;\n\t\t}\n\n\t\t// Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only\n\t\t// Treat the template element as a regular one in browsers that\n\t\t// don't support it.\n\t\tif ( nodeName( elem, \"template\" ) ) {\n\t\t\telem = elem.content || elem;\n\t\t}\n\n\t\treturn jQuery.merge( [], elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar matched = jQuery.map( this, fn, until );\n\n\t\tif ( name.slice( -5 ) !== \"Until\" ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tmatched = jQuery.filter( selector, matched );\n\t\t}\n\n\t\tif ( this.length > 1 ) {\n\n\t\t\t// Remove duplicates\n\t\t\tif ( !guaranteedUnique[ name ] ) {\n\t\t\t\tjQuery.uniqueSort( matched );\n\t\t\t}\n\n\t\t\t// Reverse order for parents* and prev-derivatives\n\t\t\tif ( rparentsprev.test( name ) ) {\n\t\t\t\tmatched.reverse();\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched );\n\t};\n} );\nvar rnothtmlwhite = ( /[^\\x20\\t\\r\\n\\f]+/g );\n\n\n\n// Convert String-formatted options into Object-formatted ones\nfunction createOptions( options ) {\n\tvar object = {};\n\tjQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {\n\t\tobject[ flag ] = true;\n\t} );\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\toptions: an optional list of space-separated options that will change how\n *\t\t\tthe callback list behaves or a more traditional option object\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible options:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( options ) {\n\n\t// Convert options from String-formatted to Object-formatted if needed\n\t// (we check in cache first)\n\toptions = typeof options === \"string\" ?\n\t\tcreateOptions( options ) :\n\t\tjQuery.extend( {}, options );\n\n\tvar // Flag to know if list is currently firing\n\t\tfiring,\n\n\t\t// Last fire value for non-forgettable lists\n\t\tmemory,\n\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\n\t\t// Flag to prevent firing\n\t\tlocked,\n\n\t\t// Actual callback list\n\t\tlist = [],\n\n\t\t// Queue of execution data for repeatable lists\n\t\tqueue = [],\n\n\t\t// Index of currently firing callback (modified by add/remove as needed)\n\t\tfiringIndex = -1,\n\n\t\t// Fire callbacks\n\t\tfire = function() {\n\n\t\t\t// Enforce single-firing\n\t\t\tlocked = locked || options.once;\n\n\t\t\t// Execute callbacks for all pending executions,\n\t\t\t// respecting firingIndex overrides and runtime changes\n\t\t\tfired = firing = true;\n\t\t\tfor ( ; queue.length; firingIndex = -1 ) {\n\t\t\t\tmemory = queue.shift();\n\t\t\t\twhile ( ++firingIndex < list.length ) {\n\n\t\t\t\t\t// Run callback and check for early termination\n\t\t\t\t\tif ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&\n\t\t\t\t\t\toptions.stopOnFalse ) {\n\n\t\t\t\t\t\t// Jump to end and forget the data so .add doesn't re-fire\n\t\t\t\t\t\tfiringIndex = list.length;\n\t\t\t\t\t\tmemory = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Forget the data if we're done with it\n\t\t\tif ( !options.memory ) {\n\t\t\t\tmemory = false;\n\t\t\t}\n\n\t\t\tfiring = false;\n\n\t\t\t// Clean up if we're done firing for good\n\t\t\tif ( locked ) {\n\n\t\t\t\t// Keep an empty list if we have data for future add calls\n\t\t\t\tif ( memory ) {\n\t\t\t\t\tlist = [];\n\n\t\t\t\t// Otherwise, this object is spent\n\t\t\t\t} else {\n\t\t\t\t\tlist = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t// Actual Callbacks object\n\t\tself = {\n\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\n\t\t\t\t\t// If we have memory from a past run, we should fire after adding\n\t\t\t\t\tif ( memory && !firing ) {\n\t\t\t\t\t\tfiringIndex = list.length - 1;\n\t\t\t\t\t\tqueue.push( memory );\n\t\t\t\t\t}\n\n\t\t\t\t\t( function add( args ) {\n\t\t\t\t\t\tjQuery.each( args, function( _, arg ) {\n\t\t\t\t\t\t\tif ( isFunction( arg ) ) {\n\t\t\t\t\t\t\t\tif ( !options.unique || !self.has( arg ) ) {\n\t\t\t\t\t\t\t\t\tlist.push( arg );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if ( arg && arg.length && toType( arg ) !== \"string\" ) {\n\n\t\t\t\t\t\t\t\t// Inspect recursively\n\t\t\t\t\t\t\t\tadd( arg );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} );\n\t\t\t\t\t} )( arguments );\n\n\t\t\t\t\tif ( memory && !firing ) {\n\t\t\t\t\t\tfire();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tjQuery.each( arguments, function( _, arg ) {\n\t\t\t\t\tvar index;\n\t\t\t\t\twhile ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n\t\t\t\t\t\tlist.splice( index, 1 );\n\n\t\t\t\t\t\t// Handle firing indexes\n\t\t\t\t\t\tif ( index <= firingIndex ) {\n\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Check if a given callback is in the list.\n\t\t\t// If no argument is given, return whether or not list has callbacks attached.\n\t\t\thas: function( fn ) {\n\t\t\t\treturn fn ?\n\t\t\t\t\tjQuery.inArray( fn, list ) > -1 :\n\t\t\t\t\tlist.length > 0;\n\t\t\t},\n\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tlist = [];\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Disable .fire and .add\n\t\t\t// Abort any current/pending executions\n\t\t\t// Clear all callbacks and values\n\t\t\tdisable: function() {\n\t\t\t\tlocked = queue = [];\n\t\t\t\tlist = memory = \"\";\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\n\t\t\t// Disable .fire\n\t\t\t// Also disable .add unless we have memory (since it would have no effect)\n\t\t\t// Abort any pending executions\n\t\t\tlock: function() {\n\t\t\t\tlocked = queue = [];\n\t\t\t\tif ( !memory && !firing ) {\n\t\t\t\t\tlist = memory = \"\";\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\tlocked: function() {\n\t\t\t\treturn !!locked;\n\t\t\t},\n\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( !locked ) {\n\t\t\t\t\targs = args || [];\n\t\t\t\t\targs = [ context, args.slice ? args.slice() : args ];\n\t\t\t\t\tqueue.push( args );\n\t\t\t\t\tif ( !firing ) {\n\t\t\t\t\t\tfire();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\nfunction Identity( v ) {\n\treturn v;\n}\nfunction Thrower( ex ) {\n\tthrow ex;\n}\n\nfunction adoptValue( value, resolve, reject, noValue ) {\n\tvar method;\n\n\ttry {\n\n\t\t// Check for promise aspect first to privilege synchronous behavior\n\t\tif ( value && isFunction( ( method = value.promise ) ) ) {\n\t\t\tmethod.call( value ).done( resolve ).fail( reject );\n\n\t\t// Other thenables\n\t\t} else if ( value && isFunction( ( method = value.then ) ) ) {\n\t\t\tmethod.call( value, resolve, reject );\n\n\t\t// Other non-thenables\n\t\t} else {\n\n\t\t\t// Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer:\n\t\t\t// * false: [ value ].slice( 0 ) => resolve( value )\n\t\t\t// * true: [ value ].slice( 1 ) => resolve()\n\t\t\tresolve.apply( undefined, [ value ].slice( noValue ) );\n\t\t}\n\n\t// For Promises/A+, convert exceptions into rejections\n\t// Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in\n\t// Deferred#then to conditionally suppress rejection.\n\t} catch ( value ) {\n\n\t\t// Support: Android 4.0 only\n\t\t// Strict mode functions invoked without .call/.apply get global-object context\n\t\treject.apply( undefined, [ value ] );\n\t}\n}\n\njQuery.extend( {\n\n\tDeferred: function( func ) {\n\t\tvar tuples = [\n\n\t\t\t\t// action, add listener, callbacks,\n\t\t\t\t// ... .then handlers, argument index, [final state]\n\t\t\t\t[ \"notify\", \"progress\", jQuery.Callbacks( \"memory\" ),\n\t\t\t\t\tjQuery.Callbacks( \"memory\" ), 2 ],\n\t\t\t\t[ \"resolve\", \"done\", jQuery.Callbacks( \"once memory\" ),\n\t\t\t\t\tjQuery.Callbacks( \"once memory\" ), 0, \"resolved\" ],\n\t\t\t\t[ \"reject\", \"fail\", jQuery.Callbacks( \"once memory\" ),\n\t\t\t\t\tjQuery.Callbacks( \"once memory\" ), 1, \"rejected\" ]\n\t\t\t],\n\t\t\tstate = \"pending\",\n\t\t\tpromise = {\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done( arguments ).fail( arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\t\"catch\": function( fn ) {\n\t\t\t\t\treturn promise.then( null, fn );\n\t\t\t\t},\n\n\t\t\t\t// Keep pipe for back-compat\n\t\t\t\tpipe: function( /* fnDone, fnFail, fnProgress */ ) {\n\t\t\t\t\tvar fns = arguments;\n\n\t\t\t\t\treturn jQuery.Deferred( function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( tuples, function( _i, tuple ) {\n\n\t\t\t\t\t\t\t// Map tuples (progress, done, fail) to arguments (done, fail, progress)\n\t\t\t\t\t\t\tvar fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];\n\n\t\t\t\t\t\t\t// deferred.progress(function() { bind to newDefer or newDefer.notify })\n\t\t\t\t\t\t\t// deferred.done(function() { bind to newDefer or newDefer.resolve })\n\t\t\t\t\t\t\t// deferred.fail(function() { bind to newDefer or newDefer.reject })\n\t\t\t\t\t\t\tdeferred[ tuple[ 1 ] ]( function() {\n\t\t\t\t\t\t\t\tvar returned = fn && fn.apply( this, arguments );\n\t\t\t\t\t\t\t\tif ( returned && isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\treturned.promise()\n\t\t\t\t\t\t\t\t\t\t.progress( newDefer.notify )\n\t\t\t\t\t\t\t\t\t\t.done( newDefer.resolve )\n\t\t\t\t\t\t\t\t\t\t.fail( newDefer.reject );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tnewDefer[ tuple[ 0 ] + \"With\" ](\n\t\t\t\t\t\t\t\t\t\tthis,\n\t\t\t\t\t\t\t\t\t\tfn ? [ returned ] : arguments\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t} );\n\t\t\t\t\t\tfns = null;\n\t\t\t\t\t} ).promise();\n\t\t\t\t},\n\t\t\t\tthen: function( onFulfilled, onRejected, onProgress ) {\n\t\t\t\t\tvar maxDepth = 0;\n\t\t\t\t\tfunction resolve( depth, deferred, handler, special ) {\n\t\t\t\t\t\treturn function() {\n\t\t\t\t\t\t\tvar that = this,\n\t\t\t\t\t\t\t\targs = arguments,\n\t\t\t\t\t\t\t\tmightThrow = function() {\n\t\t\t\t\t\t\t\t\tvar returned, then;\n\n\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.3\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-59\n\t\t\t\t\t\t\t\t\t// Ignore double-resolution attempts\n\t\t\t\t\t\t\t\t\tif ( depth < maxDepth ) {\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\treturned = handler.apply( that, args );\n\n\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.1\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-48\n\t\t\t\t\t\t\t\t\tif ( returned === deferred.promise() ) {\n\t\t\t\t\t\t\t\t\t\tthrow new TypeError( \"Thenable self-resolution\" );\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Support: Promises/A+ sections 2.3.3.1, 3.5\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-54\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-75\n\t\t\t\t\t\t\t\t\t// Retrieve `then` only once\n\t\t\t\t\t\t\t\t\tthen = returned &&\n\n\t\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.4\n\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-64\n\t\t\t\t\t\t\t\t\t\t// Only check objects and functions for thenability\n\t\t\t\t\t\t\t\t\t\t( typeof returned === \"object\" ||\n\t\t\t\t\t\t\t\t\t\t\ttypeof returned === \"function\" ) &&\n\t\t\t\t\t\t\t\t\t\treturned.then;\n\n\t\t\t\t\t\t\t\t\t// Handle a returned thenable\n\t\t\t\t\t\t\t\t\tif ( isFunction( then ) ) {\n\n\t\t\t\t\t\t\t\t\t\t// Special processors (notify) just wait for resolution\n\t\t\t\t\t\t\t\t\t\tif ( special ) {\n\t\t\t\t\t\t\t\t\t\t\tthen.call(\n\t\t\t\t\t\t\t\t\t\t\t\treturned,\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity, special ),\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Thrower, special )\n\t\t\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\t\t\t// Normal processors (resolve) also hook into progress\n\t\t\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t\t\t// ...and disregard older resolution values\n\t\t\t\t\t\t\t\t\t\t\tmaxDepth++;\n\n\t\t\t\t\t\t\t\t\t\t\tthen.call(\n\t\t\t\t\t\t\t\t\t\t\t\treturned,\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity, special ),\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Thrower, special ),\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity,\n\t\t\t\t\t\t\t\t\t\t\t\t\tdeferred.notifyWith )\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Handle all other returned values\n\t\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t\t// Only substitute handlers pass on context\n\t\t\t\t\t\t\t\t\t\t// and multiple values (non-spec behavior)\n\t\t\t\t\t\t\t\t\t\tif ( handler !== Identity ) {\n\t\t\t\t\t\t\t\t\t\t\tthat = undefined;\n\t\t\t\t\t\t\t\t\t\t\targs = [ returned ];\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t// Process the value(s)\n\t\t\t\t\t\t\t\t\t\t// Default process is resolve\n\t\t\t\t\t\t\t\t\t\t( special || deferred.resolveWith )( that, args );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\n\t\t\t\t\t\t\t\t// Only normal processors (resolve) catch and reject exceptions\n\t\t\t\t\t\t\t\tprocess = special ?\n\t\t\t\t\t\t\t\t\tmightThrow :\n\t\t\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\tmightThrow();\n\t\t\t\t\t\t\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t\t\t\t\t\t\tif ( jQuery.Deferred.exceptionHook ) {\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery.Deferred.exceptionHook( e,\n\t\t\t\t\t\t\t\t\t\t\t\t\tprocess.stackTrace );\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.4.1\n\t\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-61\n\t\t\t\t\t\t\t\t\t\t\t// Ignore post-resolution exceptions\n\t\t\t\t\t\t\t\t\t\t\tif ( depth + 1 >= maxDepth ) {\n\n\t\t\t\t\t\t\t\t\t\t\t\t// Only substitute handlers pass on context\n\t\t\t\t\t\t\t\t\t\t\t\t// and multiple values (non-spec behavior)\n\t\t\t\t\t\t\t\t\t\t\t\tif ( handler !== Thrower ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tthat = undefined;\n\t\t\t\t\t\t\t\t\t\t\t\t\targs = [ e ];\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\tdeferred.rejectWith( that, args );\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.1\n\t\t\t\t\t\t\t// https://promisesaplus.com/#point-57\n\t\t\t\t\t\t\t// Re-resolve promises immediately to dodge false rejection from\n\t\t\t\t\t\t\t// subsequent errors\n\t\t\t\t\t\t\tif ( depth ) {\n\t\t\t\t\t\t\t\tprocess();\n\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t// Call an optional hook to record the stack, in case of exception\n\t\t\t\t\t\t\t\t// since it's otherwise lost when execution goes async\n\t\t\t\t\t\t\t\tif ( jQuery.Deferred.getStackHook ) {\n\t\t\t\t\t\t\t\t\tprocess.stackTrace = jQuery.Deferred.getStackHook();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\twindow.setTimeout( process );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.Deferred( function( newDefer ) {\n\n\t\t\t\t\t\t// progress_handlers.add( ... )\n\t\t\t\t\t\ttuples[ 0 ][ 3 ].add(\n\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\tisFunction( onProgress ) ?\n\t\t\t\t\t\t\t\t\tonProgress :\n\t\t\t\t\t\t\t\t\tIdentity,\n\t\t\t\t\t\t\t\tnewDefer.notifyWith\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// fulfilled_handlers.add( ... )\n\t\t\t\t\t\ttuples[ 1 ][ 3 ].add(\n\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\tisFunction( onFulfilled ) ?\n\t\t\t\t\t\t\t\t\tonFulfilled :\n\t\t\t\t\t\t\t\t\tIdentity\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// rejected_handlers.add( ... )\n\t\t\t\t\t\ttuples[ 2 ][ 3 ].add(\n\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\tisFunction( onRejected ) ?\n\t\t\t\t\t\t\t\t\tonRejected :\n\t\t\t\t\t\t\t\t\tThrower\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\t\t\t\t\t} ).promise();\n\t\t\t\t},\n\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\treturn obj != null ? jQuery.extend( obj, promise ) : promise;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = {};\n\n\t\t// Add list-specific methods\n\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\tvar list = tuple[ 2 ],\n\t\t\t\tstateString = tuple[ 5 ];\n\n\t\t\t// promise.progress = list.add\n\t\t\t// promise.done = list.add\n\t\t\t// promise.fail = list.add\n\t\t\tpromise[ tuple[ 1 ] ] = list.add;\n\n\t\t\t// Handle state\n\t\t\tif ( stateString ) {\n\t\t\t\tlist.add(\n\t\t\t\t\tfunction() {\n\n\t\t\t\t\t\t// state = \"resolved\" (i.e., fulfilled)\n\t\t\t\t\t\t// state = \"rejected\"\n\t\t\t\t\t\tstate = stateString;\n\t\t\t\t\t},\n\n\t\t\t\t\t// rejected_callbacks.disable\n\t\t\t\t\t// fulfilled_callbacks.disable\n\t\t\t\t\ttuples[ 3 - i ][ 2 ].disable,\n\n\t\t\t\t\t// rejected_handlers.disable\n\t\t\t\t\t// fulfilled_handlers.disable\n\t\t\t\t\ttuples[ 3 - i ][ 3 ].disable,\n\n\t\t\t\t\t// progress_callbacks.lock\n\t\t\t\t\ttuples[ 0 ][ 2 ].lock,\n\n\t\t\t\t\t// progress_handlers.lock\n\t\t\t\t\ttuples[ 0 ][ 3 ].lock\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// progress_handlers.fire\n\t\t\t// fulfilled_handlers.fire\n\t\t\t// rejected_handlers.fire\n\t\t\tlist.add( tuple[ 3 ].fire );\n\n\t\t\t// deferred.notify = function() { deferred.notifyWith(...) }\n\t\t\t// deferred.resolve = function() { deferred.resolveWith(...) }\n\t\t\t// deferred.reject = function() { deferred.rejectWith(...) }\n\t\t\tdeferred[ tuple[ 0 ] ] = function() {\n\t\t\t\tdeferred[ tuple[ 0 ] + \"With\" ]( this === deferred ? undefined : this, arguments );\n\t\t\t\treturn this;\n\t\t\t};\n\n\t\t\t// deferred.notifyWith = list.fireWith\n\t\t\t// deferred.resolveWith = list.fireWith\n\t\t\t// deferred.rejectWith = list.fireWith\n\t\t\tdeferred[ tuple[ 0 ] + \"With\" ] = list.fireWith;\n\t\t} );\n\n\t\t// Make the deferred a promise\n\t\tpromise.promise( deferred );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( singleValue ) {\n\t\tvar\n\n\t\t\t// count of uncompleted subordinates\n\t\t\tremaining = arguments.length,\n\n\t\t\t// count of unprocessed arguments\n\t\t\ti = remaining,\n\n\t\t\t// subordinate fulfillment data\n\t\t\tresolveContexts = Array( i ),\n\t\t\tresolveValues = slice.call( arguments ),\n\n\t\t\t// the master Deferred\n\t\t\tmaster = jQuery.Deferred(),\n\n\t\t\t// subordinate callback factory\n\t\t\tupdateFunc = function( i ) {\n\t\t\t\treturn function( value ) {\n\t\t\t\t\tresolveContexts[ i ] = this;\n\t\t\t\t\tresolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;\n\t\t\t\t\tif ( !( --remaining ) ) {\n\t\t\t\t\t\tmaster.resolveWith( resolveContexts, resolveValues );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t};\n\n\t\t// Single- and empty arguments are adopted like Promise.resolve\n\t\tif ( remaining <= 1 ) {\n\t\t\tadoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject,\n\t\t\t\t!remaining );\n\n\t\t\t// Use .then() to unwrap secondary thenables (cf. gh-3000)\n\t\t\tif ( master.state() === \"pending\" ||\n\t\t\t\tisFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {\n\n\t\t\t\treturn master.then();\n\t\t\t}\n\t\t}\n\n\t\t// Multiple arguments are aggregated like Promise.all array elements\n\t\twhile ( i-- ) {\n\t\t\tadoptValue( resolveValues[ i ], updateFunc( i ), master.reject );\n\t\t}\n\n\t\treturn master.promise();\n\t}\n} );\n\n\n// These usually indicate a programmer mistake during development,\n// warn about them ASAP rather than swallowing them by default.\nvar rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;\n\njQuery.Deferred.exceptionHook = function( error, stack ) {\n\n\t// Support: IE 8 - 9 only\n\t// Console exists when dev tools are open, which can happen at any time\n\tif ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {\n\t\twindow.console.warn( \"jQuery.Deferred exception: \" + error.message, error.stack, stack );\n\t}\n};\n\n\n\n\njQuery.readyException = function( error ) {\n\twindow.setTimeout( function() {\n\t\tthrow error;\n\t} );\n};\n\n\n\n\n// The deferred used on DOM ready\nvar readyList = jQuery.Deferred();\n\njQuery.fn.ready = function( fn ) {\n\n\treadyList\n\t\t.then( fn )\n\n\t\t// Wrap jQuery.readyException in a function so that the lookup\n\t\t// happens at the time of error handling instead of callback\n\t\t// registration.\n\t\t.catch( function( error ) {\n\t\t\tjQuery.readyException( error );\n\t\t} );\n\n\treturn this;\n};\n\njQuery.extend( {\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\n\t\t// Abort if there are pending holds or we're already ready\n\t\tif ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Remember that the DOM is ready\n\t\tjQuery.isReady = true;\n\n\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If there are functions bound, to execute\n\t\treadyList.resolveWith( document, [ jQuery ] );\n\t}\n} );\n\njQuery.ready.then = readyList.then;\n\n// The ready event handler and self cleanup method\nfunction completed() {\n\tdocument.removeEventListener( \"DOMContentLoaded\", completed );\n\twindow.removeEventListener( \"load\", completed );\n\tjQuery.ready();\n}\n\n// Catch cases where $(document).ready() is called\n// after the browser event has already occurred.\n// Support: IE <=9 - 10 only\n// Older IE sometimes signals \"interactive\" too soon\nif ( document.readyState === \"complete\" ||\n\t( document.readyState !== \"loading\" && !document.documentElement.doScroll ) ) {\n\n\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\twindow.setTimeout( jQuery.ready );\n\n} else {\n\n\t// Use the handy event callback\n\tdocument.addEventListener( \"DOMContentLoaded\", completed );\n\n\t// A fallback to window.onload, that will always work\n\twindow.addEventListener( \"load\", completed );\n}\n\n\n\n\n// Multifunctional method to get and set values of a collection\n// The value/s can optionally be executed if it's a function\nvar access = function( elems, fn, key, value, chainable, emptyGet, raw ) {\n\tvar i = 0,\n\t\tlen = elems.length,\n\t\tbulk = key == null;\n\n\t// Sets many values\n\tif ( toType( key ) === \"object\" ) {\n\t\tchainable = true;\n\t\tfor ( i in key ) {\n\t\t\taccess( elems, fn, i, key[ i ], true, emptyGet, raw );\n\t\t}\n\n\t// Sets one value\n\t} else if ( value !== undefined ) {\n\t\tchainable = true;\n\n\t\tif ( !isFunction( value ) ) {\n\t\t\traw = true;\n\t\t}\n\n\t\tif ( bulk ) {\n\n\t\t\t// Bulk operations run against the entire set\n\t\t\tif ( raw ) {\n\t\t\t\tfn.call( elems, value );\n\t\t\t\tfn = null;\n\n\t\t\t// ...except when executing function values\n\t\t\t} else {\n\t\t\t\tbulk = fn;\n\t\t\t\tfn = function( elem, _key, value ) {\n\t\t\t\t\treturn bulk.call( jQuery( elem ), value );\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\tfn(\n\t\t\t\t\telems[ i ], key, raw ?\n\t\t\t\t\tvalue :\n\t\t\t\t\tvalue.call( elems[ i ], i, fn( elems[ i ], key ) )\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( chainable ) {\n\t\treturn elems;\n\t}\n\n\t// Gets\n\tif ( bulk ) {\n\t\treturn fn.call( elems );\n\t}\n\n\treturn len ? fn( elems[ 0 ], key ) : emptyGet;\n};\n\n\n// Matches dashed string for camelizing\nvar rmsPrefix = /^-ms-/,\n\trdashAlpha = /-([a-z])/g;\n\n// Used by camelCase as callback to replace()\nfunction fcamelCase( _all, letter ) {\n\treturn letter.toUpperCase();\n}\n\n// Convert dashed to camelCase; used by the css and data modules\n// Support: IE <=9 - 11, Edge 12 - 15\n// Microsoft forgot to hump their vendor prefix (#9572)\nfunction camelCase( string ) {\n\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n}\nvar acceptData = function( owner ) {\n\n\t// Accepts only:\n\t//  - Node\n\t//    - Node.ELEMENT_NODE\n\t//    - Node.DOCUMENT_NODE\n\t//  - Object\n\t//    - Any\n\treturn owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );\n};\n\n\n\n\nfunction Data() {\n\tthis.expando = jQuery.expando + Data.uid++;\n}\n\nData.uid = 1;\n\nData.prototype = {\n\n\tcache: function( owner ) {\n\n\t\t// Check if the owner object already has a cache\n\t\tvar value = owner[ this.expando ];\n\n\t\t// If not, create one\n\t\tif ( !value ) {\n\t\t\tvalue = {};\n\n\t\t\t// We can accept data for non-element nodes in modern browsers,\n\t\t\t// but we should not, see #8335.\n\t\t\t// Always return an empty object.\n\t\t\tif ( acceptData( owner ) ) {\n\n\t\t\t\t// If it is a node unlikely to be stringify-ed or looped over\n\t\t\t\t// use plain assignment\n\t\t\t\tif ( owner.nodeType ) {\n\t\t\t\t\towner[ this.expando ] = value;\n\n\t\t\t\t// Otherwise secure it in a non-enumerable property\n\t\t\t\t// configurable must be true to allow the property to be\n\t\t\t\t// deleted when data is removed\n\t\t\t\t} else {\n\t\t\t\t\tObject.defineProperty( owner, this.expando, {\n\t\t\t\t\t\tvalue: value,\n\t\t\t\t\t\tconfigurable: true\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn value;\n\t},\n\tset: function( owner, data, value ) {\n\t\tvar prop,\n\t\t\tcache = this.cache( owner );\n\n\t\t// Handle: [ owner, key, value ] args\n\t\t// Always use camelCase key (gh-2257)\n\t\tif ( typeof data === \"string\" ) {\n\t\t\tcache[ camelCase( data ) ] = value;\n\n\t\t// Handle: [ owner, { properties } ] args\n\t\t} else {\n\n\t\t\t// Copy the properties one-by-one to the cache object\n\t\t\tfor ( prop in data ) {\n\t\t\t\tcache[ camelCase( prop ) ] = data[ prop ];\n\t\t\t}\n\t\t}\n\t\treturn cache;\n\t},\n\tget: function( owner, key ) {\n\t\treturn key === undefined ?\n\t\t\tthis.cache( owner ) :\n\n\t\t\t// Always use camelCase key (gh-2257)\n\t\t\towner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ];\n\t},\n\taccess: function( owner, key, value ) {\n\n\t\t// In cases where either:\n\t\t//\n\t\t//   1. No key was specified\n\t\t//   2. A string key was specified, but no value provided\n\t\t//\n\t\t// Take the \"read\" path and allow the get method to determine\n\t\t// which value to return, respectively either:\n\t\t//\n\t\t//   1. The entire cache object\n\t\t//   2. The data stored at the key\n\t\t//\n\t\tif ( key === undefined ||\n\t\t\t\t( ( key && typeof key === \"string\" ) && value === undefined ) ) {\n\n\t\t\treturn this.get( owner, key );\n\t\t}\n\n\t\t// When the key is not a string, or both a key and value\n\t\t// are specified, set or extend (existing objects) with either:\n\t\t//\n\t\t//   1. An object of properties\n\t\t//   2. A key and value\n\t\t//\n\t\tthis.set( owner, key, value );\n\n\t\t// Since the \"set\" path can have two possible entry points\n\t\t// return the expected data based on which path was taken[*]\n\t\treturn value !== undefined ? value : key;\n\t},\n\tremove: function( owner, key ) {\n\t\tvar i,\n\t\t\tcache = owner[ this.expando ];\n\n\t\tif ( cache === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( key !== undefined ) {\n\n\t\t\t// Support array or space separated string of keys\n\t\t\tif ( Array.isArray( key ) ) {\n\n\t\t\t\t// If key is an array of keys...\n\t\t\t\t// We always set camelCase keys, so remove that.\n\t\t\t\tkey = key.map( camelCase );\n\t\t\t} else {\n\t\t\t\tkey = camelCase( key );\n\n\t\t\t\t// If a key with the spaces exists, use it.\n\t\t\t\t// Otherwise, create an array by matching non-whitespace\n\t\t\t\tkey = key in cache ?\n\t\t\t\t\t[ key ] :\n\t\t\t\t\t( key.match( rnothtmlwhite ) || [] );\n\t\t\t}\n\n\t\t\ti = key.length;\n\n\t\t\twhile ( i-- ) {\n\t\t\t\tdelete cache[ key[ i ] ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if there's no more data\n\t\tif ( key === undefined || jQuery.isEmptyObject( cache ) ) {\n\n\t\t\t// Support: Chrome <=35 - 45\n\t\t\t// Webkit & Blink performance suffers when deleting properties\n\t\t\t// from DOM nodes, so set to undefined instead\n\t\t\t// https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)\n\t\t\tif ( owner.nodeType ) {\n\t\t\t\towner[ this.expando ] = undefined;\n\t\t\t} else {\n\t\t\t\tdelete owner[ this.expando ];\n\t\t\t}\n\t\t}\n\t},\n\thasData: function( owner ) {\n\t\tvar cache = owner[ this.expando ];\n\t\treturn cache !== undefined && !jQuery.isEmptyObject( cache );\n\t}\n};\nvar dataPriv = new Data();\n\nvar dataUser = new Data();\n\n\n\n//\tImplementation Summary\n//\n//\t1. Enforce API surface and semantic compatibility with 1.9.x branch\n//\t2. Improve the module's maintainability by reducing the storage\n//\t\tpaths to a single mechanism.\n//\t3. Use the same single mechanism to support \"private\" and \"user\" data.\n//\t4. _Never_ expose \"private\" data to user code (TODO: Drop _data, _removeData)\n//\t5. Avoid exposing implementation details on user objects (eg. expando properties)\n//\t6. Provide a clear path for implementation upgrade to WeakMap in 2014\n\nvar rbrace = /^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,\n\trmultiDash = /[A-Z]/g;\n\nfunction getData( data ) {\n\tif ( data === \"true\" ) {\n\t\treturn true;\n\t}\n\n\tif ( data === \"false\" ) {\n\t\treturn false;\n\t}\n\n\tif ( data === \"null\" ) {\n\t\treturn null;\n\t}\n\n\t// Only convert to a number if it doesn't change the string\n\tif ( data === +data + \"\" ) {\n\t\treturn +data;\n\t}\n\n\tif ( rbrace.test( data ) ) {\n\t\treturn JSON.parse( data );\n\t}\n\n\treturn data;\n}\n\nfunction dataAttr( elem, key, data ) {\n\tvar name;\n\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\t\tname = \"data-\" + key.replace( rmultiDash, \"-$&\" ).toLowerCase();\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = getData( data );\n\t\t\t} catch ( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tdataUser.set( elem, key, data );\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\treturn data;\n}\n\njQuery.extend( {\n\thasData: function( elem ) {\n\t\treturn dataUser.hasData( elem ) || dataPriv.hasData( elem );\n\t},\n\n\tdata: function( elem, name, data ) {\n\t\treturn dataUser.access( elem, name, data );\n\t},\n\n\tremoveData: function( elem, name ) {\n\t\tdataUser.remove( elem, name );\n\t},\n\n\t// TODO: Now that all calls to _data and _removeData have been replaced\n\t// with direct calls to dataPriv methods, these can be deprecated.\n\t_data: function( elem, name, data ) {\n\t\treturn dataPriv.access( elem, name, data );\n\t},\n\n\t_removeData: function( elem, name ) {\n\t\tdataPriv.remove( elem, name );\n\t}\n} );\n\njQuery.fn.extend( {\n\tdata: function( key, value ) {\n\t\tvar i, name, data,\n\t\t\telem = this[ 0 ],\n\t\t\tattrs = elem && elem.attributes;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = dataUser.get( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !dataPriv.get( elem, \"hasDataAttrs\" ) ) {\n\t\t\t\t\ti = attrs.length;\n\t\t\t\t\twhile ( i-- ) {\n\n\t\t\t\t\t\t// Support: IE 11 only\n\t\t\t\t\t\t// The attrs elements can be null (#14894)\n\t\t\t\t\t\tif ( attrs[ i ] ) {\n\t\t\t\t\t\t\tname = attrs[ i ].name;\n\t\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\t\tname = camelCase( name.slice( 5 ) );\n\t\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tdataPriv.set( elem, \"hasDataAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each( function() {\n\t\t\t\tdataUser.set( this, key );\n\t\t\t} );\n\t\t}\n\n\t\treturn access( this, function( value ) {\n\t\t\tvar data;\n\n\t\t\t// The calling jQuery object (element matches) is not empty\n\t\t\t// (and therefore has an element appears at this[ 0 ]) and the\n\t\t\t// `value` parameter was not undefined. An empty jQuery object\n\t\t\t// will result in `undefined` for elem = this[ 0 ] which will\n\t\t\t// throw an exception if an attempt to read a data cache is made.\n\t\t\tif ( elem && value === undefined ) {\n\n\t\t\t\t// Attempt to get data from the cache\n\t\t\t\t// The key will always be camelCased in Data\n\t\t\t\tdata = dataUser.get( elem, key );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// Attempt to \"discover\" the data in\n\t\t\t\t// HTML5 custom data-* attrs\n\t\t\t\tdata = dataAttr( elem, key );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// We tried really hard, but the data doesn't exist.\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Set the data...\n\t\t\tthis.each( function() {\n\n\t\t\t\t// We always store the camelCased key\n\t\t\t\tdataUser.set( this, key, value );\n\t\t\t} );\n\t\t}, null, value, arguments.length > 1, null, true );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each( function() {\n\t\t\tdataUser.remove( this, key );\n\t\t} );\n\t}\n} );\n\n\njQuery.extend( {\n\tqueue: function( elem, type, data ) {\n\t\tvar queue;\n\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tqueue = dataPriv.get( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !queue || Array.isArray( data ) ) {\n\t\t\t\t\tqueue = dataPriv.access( elem, type, jQuery.makeArray( data ) );\n\t\t\t\t} else {\n\t\t\t\t\tqueue.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn queue || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tstartLength = queue.length,\n\t\t\tfn = queue.shift(),\n\t\t\thooks = jQuery._queueHooks( elem, type ),\n\t\t\tnext = function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t\tstartLength--;\n\t\t}\n\n\t\tif ( fn ) {\n\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\t// Clear up the last queue stop function\n\t\t\tdelete hooks.stop;\n\t\t\tfn.call( elem, next, hooks );\n\t\t}\n\n\t\tif ( !startLength && hooks ) {\n\t\t\thooks.empty.fire();\n\t\t}\n\t},\n\n\t// Not public - generate a queueHooks object, or return the current one\n\t_queueHooks: function( elem, type ) {\n\t\tvar key = type + \"queueHooks\";\n\t\treturn dataPriv.get( elem, key ) || dataPriv.access( elem, key, {\n\t\t\tempty: jQuery.Callbacks( \"once memory\" ).add( function() {\n\t\t\t\tdataPriv.remove( elem, [ type + \"queue\", key ] );\n\t\t\t} )\n\t\t} );\n\t}\n} );\n\njQuery.fn.extend( {\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[ 0 ], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each( function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\t// Ensure a hooks for this queue\n\t\t\t\tjQuery._queueHooks( this, type );\n\n\t\t\t\tif ( type === \"fx\" && queue[ 0 ] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t} );\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each( function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t} );\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, obj ) {\n\t\tvar tmp,\n\t\t\tcount = 1,\n\t\t\tdefer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = this.length,\n\t\t\tresolve = function() {\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t\t}\n\t\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobj = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\n\t\twhile ( i-- ) {\n\t\t\ttmp = dataPriv.get( elements[ i ], type + \"queueHooks\" );\n\t\t\tif ( tmp && tmp.empty ) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.empty.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( obj );\n\t}\n} );\nvar pnum = ( /[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/ ).source;\n\nvar rcssNum = new RegExp( \"^(?:([+-])=|)(\" + pnum + \")([a-z%]*)$\", \"i\" );\n\n\nvar cssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ];\n\nvar documentElement = document.documentElement;\n\n\n\n\tvar isAttached = function( elem ) {\n\t\t\treturn jQuery.contains( elem.ownerDocument, elem );\n\t\t},\n\t\tcomposed = { composed: true };\n\n\t// Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only\n\t// Check attachment across shadow DOM boundaries when possible (gh-3504)\n\t// Support: iOS 10.0-10.2 only\n\t// Early iOS 10 versions support `attachShadow` but not `getRootNode`,\n\t// leading to errors. We need to check for `getRootNode`.\n\tif ( documentElement.getRootNode ) {\n\t\tisAttached = function( elem ) {\n\t\t\treturn jQuery.contains( elem.ownerDocument, elem ) ||\n\t\t\t\telem.getRootNode( composed ) === elem.ownerDocument;\n\t\t};\n\t}\nvar isHiddenWithinTree = function( elem, el ) {\n\n\t\t// isHiddenWithinTree might be called from jQuery#filter function;\n\t\t// in that case, element will be second argument\n\t\telem = el || elem;\n\n\t\t// Inline style trumps all\n\t\treturn elem.style.display === \"none\" ||\n\t\t\telem.style.display === \"\" &&\n\n\t\t\t// Otherwise, check computed style\n\t\t\t// Support: Firefox <=43 - 45\n\t\t\t// Disconnected elements can have computed display: none, so first confirm that elem is\n\t\t\t// in the document.\n\t\t\tisAttached( elem ) &&\n\n\t\t\tjQuery.css( elem, \"display\" ) === \"none\";\n\t};\n\n\n\nfunction adjustCSS( elem, prop, valueParts, tween ) {\n\tvar adjusted, scale,\n\t\tmaxIterations = 20,\n\t\tcurrentValue = tween ?\n\t\t\tfunction() {\n\t\t\t\treturn tween.cur();\n\t\t\t} :\n\t\t\tfunction() {\n\t\t\t\treturn jQuery.css( elem, prop, \"\" );\n\t\t\t},\n\t\tinitial = currentValue(),\n\t\tunit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" ),\n\n\t\t// Starting value computation is required for potential unit mismatches\n\t\tinitialInUnit = elem.nodeType &&\n\t\t\t( jQuery.cssNumber[ prop ] || unit !== \"px\" && +initial ) &&\n\t\t\trcssNum.exec( jQuery.css( elem, prop ) );\n\n\tif ( initialInUnit && initialInUnit[ 3 ] !== unit ) {\n\n\t\t// Support: Firefox <=54\n\t\t// Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144)\n\t\tinitial = initial / 2;\n\n\t\t// Trust units reported by jQuery.css\n\t\tunit = unit || initialInUnit[ 3 ];\n\n\t\t// Iteratively approximate from a nonzero starting point\n\t\tinitialInUnit = +initial || 1;\n\n\t\twhile ( maxIterations-- ) {\n\n\t\t\t// Evaluate and update our best guess (doubling guesses that zero out).\n\t\t\t// Finish if the scale equals or crosses 1 (making the old*new product non-positive).\n\t\t\tjQuery.style( elem, prop, initialInUnit + unit );\n\t\t\tif ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) {\n\t\t\t\tmaxIterations = 0;\n\t\t\t}\n\t\t\tinitialInUnit = initialInUnit / scale;\n\n\t\t}\n\n\t\tinitialInUnit = initialInUnit * 2;\n\t\tjQuery.style( elem, prop, initialInUnit + unit );\n\n\t\t// Make sure we update the tween properties later on\n\t\tvalueParts = valueParts || [];\n\t}\n\n\tif ( valueParts ) {\n\t\tinitialInUnit = +initialInUnit || +initial || 0;\n\n\t\t// Apply relative offset (+=/-=) if specified\n\t\tadjusted = valueParts[ 1 ] ?\n\t\t\tinitialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :\n\t\t\t+valueParts[ 2 ];\n\t\tif ( tween ) {\n\t\t\ttween.unit = unit;\n\t\t\ttween.start = initialInUnit;\n\t\t\ttween.end = adjusted;\n\t\t}\n\t}\n\treturn adjusted;\n}\n\n\nvar defaultDisplayMap = {};\n\nfunction getDefaultDisplay( elem ) {\n\tvar temp,\n\t\tdoc = elem.ownerDocument,\n\t\tnodeName = elem.nodeName,\n\t\tdisplay = defaultDisplayMap[ nodeName ];\n\n\tif ( display ) {\n\t\treturn display;\n\t}\n\n\ttemp = doc.body.appendChild( doc.createElement( nodeName ) );\n\tdisplay = jQuery.css( temp, \"display\" );\n\n\ttemp.parentNode.removeChild( temp );\n\n\tif ( display === \"none\" ) {\n\t\tdisplay = \"block\";\n\t}\n\tdefaultDisplayMap[ nodeName ] = display;\n\n\treturn display;\n}\n\nfunction showHide( elements, show ) {\n\tvar display, elem,\n\t\tvalues = [],\n\t\tindex = 0,\n\t\tlength = elements.length;\n\n\t// Determine new display value for elements that need to change\n\tfor ( ; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tdisplay = elem.style.display;\n\t\tif ( show ) {\n\n\t\t\t// Since we force visibility upon cascade-hidden elements, an immediate (and slow)\n\t\t\t// check is required in this first loop unless we have a nonempty display value (either\n\t\t\t// inline or about-to-be-restored)\n\t\t\tif ( display === \"none\" ) {\n\t\t\t\tvalues[ index ] = dataPriv.get( elem, \"display\" ) || null;\n\t\t\t\tif ( !values[ index ] ) {\n\t\t\t\t\telem.style.display = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( elem.style.display === \"\" && isHiddenWithinTree( elem ) ) {\n\t\t\t\tvalues[ index ] = getDefaultDisplay( elem );\n\t\t\t}\n\t\t} else {\n\t\t\tif ( display !== \"none\" ) {\n\t\t\t\tvalues[ index ] = \"none\";\n\n\t\t\t\t// Remember what we're overwriting\n\t\t\t\tdataPriv.set( elem, \"display\", display );\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set the display of the elements in a second loop to avoid constant reflow\n\tfor ( index = 0; index < length; index++ ) {\n\t\tif ( values[ index ] != null ) {\n\t\t\telements[ index ].style.display = values[ index ];\n\t\t}\n\t}\n\n\treturn elements;\n}\n\njQuery.fn.extend( {\n\tshow: function() {\n\t\treturn showHide( this, true );\n\t},\n\thide: function() {\n\t\treturn showHide( this );\n\t},\n\ttoggle: function( state ) {\n\t\tif ( typeof state === \"boolean\" ) {\n\t\t\treturn state ? this.show() : this.hide();\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tif ( isHiddenWithinTree( this ) ) {\n\t\t\t\tjQuery( this ).show();\n\t\t\t} else {\n\t\t\t\tjQuery( this ).hide();\n\t\t\t}\n\t\t} );\n\t}\n} );\nvar rcheckableType = ( /^(?:checkbox|radio)$/i );\n\nvar rtagName = ( /<([a-z][^\\/\\0>\\x20\\t\\r\\n\\f]*)/i );\n\nvar rscriptType = ( /^$|^module$|\\/(?:java|ecma)script/i );\n\n\n\n( function() {\n\tvar fragment = document.createDocumentFragment(),\n\t\tdiv = fragment.appendChild( document.createElement( \"div\" ) ),\n\t\tinput = document.createElement( \"input\" );\n\n\t// Support: Android 4.0 - 4.3 only\n\t// Check state lost if the name is set (#11217)\n\t// Support: Windows Web Apps (WWA)\n\t// `name` and `type` must use .setAttribute for WWA (#14901)\n\tinput.setAttribute( \"type\", \"radio\" );\n\tinput.setAttribute( \"checked\", \"checked\" );\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tdiv.appendChild( input );\n\n\t// Support: Android <=4.1 only\n\t// Older WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Support: IE <=11 only\n\t// Make sure textarea (and checkbox) defaultValue is properly cloned\n\tdiv.innerHTML = \"<textarea>x</textarea>\";\n\tsupport.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;\n\n\t// Support: IE <=9 only\n\t// IE <=9 replaces <option> tags with their contents when inserted outside of\n\t// the select element.\n\tdiv.innerHTML = \"<option></option>\";\n\tsupport.option = !!div.lastChild;\n} )();\n\n\n// We have to close these tags to support XHTML (#13200)\nvar wrapMap = {\n\n\t// XHTML parsers do not magically insert elements in the\n\t// same way that tag soup parsers do. So we cannot shorten\n\t// this by omitting <tbody> or other required elements.\n\tthead: [ 1, \"<table>\", \"</table>\" ],\n\tcol: [ 2, \"<table><colgroup>\", \"</colgroup></table>\" ],\n\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\n\t_default: [ 0, \"\", \"\" ]\n};\n\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// Support: IE <=9 only\nif ( !support.option ) {\n\twrapMap.optgroup = wrapMap.option = [ 1, \"<select multiple='multiple'>\", \"</select>\" ];\n}\n\n\nfunction getAll( context, tag ) {\n\n\t// Support: IE <=9 - 11 only\n\t// Use typeof to avoid zero-argument method invocation on host objects (#15151)\n\tvar ret;\n\n\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\tret = context.getElementsByTagName( tag || \"*\" );\n\n\t} else if ( typeof context.querySelectorAll !== \"undefined\" ) {\n\t\tret = context.querySelectorAll( tag || \"*\" );\n\n\t} else {\n\t\tret = [];\n\t}\n\n\tif ( tag === undefined || tag && nodeName( context, tag ) ) {\n\t\treturn jQuery.merge( [ context ], ret );\n\t}\n\n\treturn ret;\n}\n\n\n// Mark scripts as having already been evaluated\nfunction setGlobalEval( elems, refElements ) {\n\tvar i = 0,\n\t\tl = elems.length;\n\n\tfor ( ; i < l; i++ ) {\n\t\tdataPriv.set(\n\t\t\telems[ i ],\n\t\t\t\"globalEval\",\n\t\t\t!refElements || dataPriv.get( refElements[ i ], \"globalEval\" )\n\t\t);\n\t}\n}\n\n\nvar rhtml = /<|&#?\\w+;/;\n\nfunction buildFragment( elems, context, scripts, selection, ignored ) {\n\tvar elem, tmp, tag, wrap, attached, j,\n\t\tfragment = context.createDocumentFragment(),\n\t\tnodes = [],\n\t\ti = 0,\n\t\tl = elems.length;\n\n\tfor ( ; i < l; i++ ) {\n\t\telem = elems[ i ];\n\n\t\tif ( elem || elem === 0 ) {\n\n\t\t\t// Add nodes directly\n\t\t\tif ( toType( elem ) === \"object\" ) {\n\n\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\tjQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );\n\n\t\t\t// Convert non-html into a text node\n\t\t\t} else if ( !rhtml.test( elem ) ) {\n\t\t\t\tnodes.push( context.createTextNode( elem ) );\n\n\t\t\t// Convert html into DOM nodes\n\t\t\t} else {\n\t\t\t\ttmp = tmp || fragment.appendChild( context.createElement( \"div\" ) );\n\n\t\t\t\t// Deserialize a standard representation\n\t\t\t\ttag = ( rtagName.exec( elem ) || [ \"\", \"\" ] )[ 1 ].toLowerCase();\n\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default;\n\t\t\t\ttmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];\n\n\t\t\t\t// Descend through wrappers to the right content\n\t\t\t\tj = wrap[ 0 ];\n\t\t\t\twhile ( j-- ) {\n\t\t\t\t\ttmp = tmp.lastChild;\n\t\t\t\t}\n\n\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\tjQuery.merge( nodes, tmp.childNodes );\n\n\t\t\t\t// Remember the top-level container\n\t\t\t\ttmp = fragment.firstChild;\n\n\t\t\t\t// Ensure the created nodes are orphaned (#12392)\n\t\t\t\ttmp.textContent = \"\";\n\t\t\t}\n\t\t}\n\t}\n\n\t// Remove wrapper from fragment\n\tfragment.textContent = \"\";\n\n\ti = 0;\n\twhile ( ( elem = nodes[ i++ ] ) ) {\n\n\t\t// Skip elements already in the context collection (trac-4087)\n\t\tif ( selection && jQuery.inArray( elem, selection ) > -1 ) {\n\t\t\tif ( ignored ) {\n\t\t\t\tignored.push( elem );\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tattached = isAttached( elem );\n\n\t\t// Append to fragment\n\t\ttmp = getAll( fragment.appendChild( elem ), \"script\" );\n\n\t\t// Preserve script evaluation history\n\t\tif ( attached ) {\n\t\t\tsetGlobalEval( tmp );\n\t\t}\n\n\t\t// Capture executables\n\t\tif ( scripts ) {\n\t\t\tj = 0;\n\t\t\twhile ( ( elem = tmp[ j++ ] ) ) {\n\t\t\t\tif ( rscriptType.test( elem.type || \"\" ) ) {\n\t\t\t\t\tscripts.push( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn fragment;\n}\n\n\nvar\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,\n\trtypenamespace = /^([^.]*)(?:\\.(.+)|)/;\n\nfunction returnTrue() {\n\treturn true;\n}\n\nfunction returnFalse() {\n\treturn false;\n}\n\n// Support: IE <=9 - 11+\n// focus() and blur() are asynchronous, except when they are no-op.\n// So expect focus to be synchronous when the element is already active,\n// and blur to be synchronous when the element is not already active.\n// (focus and blur are always synchronous in other supported browsers,\n// this just defines when we can count on it).\nfunction expectSync( elem, type ) {\n\treturn ( elem === safeActiveElement() ) === ( type === \"focus\" );\n}\n\n// Support: IE <=9 only\n// Accessing document.activeElement can throw unexpectedly\n// https://bugs.jquery.com/ticket/13393\nfunction safeActiveElement() {\n\ttry {\n\t\treturn document.activeElement;\n\t} catch ( err ) { }\n}\n\nfunction on( elem, types, selector, data, fn, one ) {\n\tvar origFn, type;\n\n\t// Types can be a map of types/handlers\n\tif ( typeof types === \"object\" ) {\n\n\t\t// ( types-Object, selector, data )\n\t\tif ( typeof selector !== \"string\" ) {\n\n\t\t\t// ( types-Object, data )\n\t\t\tdata = data || selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tfor ( type in types ) {\n\t\t\ton( elem, type, selector, data, types[ type ], one );\n\t\t}\n\t\treturn elem;\n\t}\n\n\tif ( data == null && fn == null ) {\n\n\t\t// ( types, fn )\n\t\tfn = selector;\n\t\tdata = selector = undefined;\n\t} else if ( fn == null ) {\n\t\tif ( typeof selector === \"string\" ) {\n\n\t\t\t// ( types, selector, fn )\n\t\t\tfn = data;\n\t\t\tdata = undefined;\n\t\t} else {\n\n\t\t\t// ( types, data, fn )\n\t\t\tfn = data;\n\t\t\tdata = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t}\n\tif ( fn === false ) {\n\t\tfn = returnFalse;\n\t} else if ( !fn ) {\n\t\treturn elem;\n\t}\n\n\tif ( one === 1 ) {\n\t\torigFn = fn;\n\t\tfn = function( event ) {\n\n\t\t\t// Can use an empty set, since event contains the info\n\t\t\tjQuery().off( event );\n\t\t\treturn origFn.apply( this, arguments );\n\t\t};\n\n\t\t// Use same guid so caller can remove using origFn\n\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t}\n\treturn elem.each( function() {\n\t\tjQuery.event.add( this, types, fn, data, selector );\n\t} );\n}\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tglobal: {},\n\n\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar handleObjIn, eventHandle, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = dataPriv.get( elem );\n\n\t\t// Only attach events to objects that accept data\n\t\tif ( !acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Ensure that invalid selectors throw exceptions at attach time\n\t\t// Evaluate against documentElement in case elem is a non-element node (e.g., document)\n\t\tif ( selector ) {\n\t\t\tjQuery.find.matchesSelector( documentElement, selector );\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tif ( !( events = elemData.events ) ) {\n\t\t\tevents = elemData.events = Object.create( null );\n\t\t}\n\t\tif ( !( eventHandle = elemData.handle ) ) {\n\t\t\teventHandle = elemData.handle = function( e ) {\n\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && jQuery.event.triggered !== e.type ?\n\t\t\t\t\tjQuery.event.dispatch.apply( elem, arguments ) : undefined;\n\t\t\t};\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\ttypes = ( types || \"\" ).match( rnothtmlwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[ t ] ) || [];\n\t\t\ttype = origType = tmp[ 1 ];\n\t\t\tnamespaces = ( tmp[ 2 ] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// There *must* be a type, no attaching namespace-only handlers\n\t\t\tif ( !type ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend( {\n\t\t\t\ttype: type,\n\t\t\t\torigType: origType,\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tneedsContext: selector && jQuery.expr.match.needsContext.test( selector ),\n\t\t\t\tnamespace: namespaces.join( \".\" )\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\tif ( !( handlers = events[ type ] ) ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener if the special events handler returns false\n\t\t\t\tif ( !special.setup ||\n\t\t\t\t\tspecial.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\tvar j, origCount, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = dataPriv.hasData( elem ) && dataPriv.get( elem );\n\n\t\tif ( !elemData || !( events = elemData.events ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = ( types || \"\" ).match( rnothtmlwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[ t ] ) || [];\n\t\t\ttype = origType = tmp[ 1 ];\n\t\t\tnamespaces = ( tmp[ 2 ] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\t\t\thandlers = events[ type ] || [];\n\t\t\ttmp = tmp[ 2 ] &&\n\t\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join( \"\\\\.(?:.*\\\\.|)\" ) + \"(\\\\.|$)\" );\n\n\t\t\t// Remove matching events\n\t\t\torigCount = j = handlers.length;\n\t\t\twhile ( j-- ) {\n\t\t\t\thandleObj = handlers[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t( !tmp || tmp.test( handleObj.namespace ) ) &&\n\t\t\t\t\t( !selector || selector === handleObj.selector ||\n\t\t\t\t\t\tselector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\thandlers.splice( j, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\thandlers.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( origCount && !handlers.length ) {\n\t\t\t\tif ( !special.teardown ||\n\t\t\t\t\tspecial.teardown.call( elem, namespaces, elemData.handle ) === false ) {\n\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove data and the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\tdataPriv.remove( elem, \"handle events\" );\n\t\t}\n\t},\n\n\tdispatch: function( nativeEvent ) {\n\n\t\tvar i, j, ret, matched, handleObj, handlerQueue,\n\t\t\targs = new Array( arguments.length ),\n\n\t\t\t// Make a writable jQuery.Event from the native event object\n\t\t\tevent = jQuery.event.fix( nativeEvent ),\n\n\t\t\thandlers = (\n\t\t\t\t\tdataPriv.get( this, \"events\" ) || Object.create( null )\n\t\t\t\t)[ event.type ] || [],\n\t\t\tspecial = jQuery.event.special[ event.type ] || {};\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[ 0 ] = event;\n\n\t\tfor ( i = 1; i < arguments.length; i++ ) {\n\t\t\targs[ i ] = arguments[ i ];\n\t\t}\n\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers\n\t\thandlerQueue = jQuery.event.handlers.call( this, event, handlers );\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\ti = 0;\n\t\twhile ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tj = 0;\n\t\t\twhile ( ( handleObj = matched.handlers[ j++ ] ) &&\n\t\t\t\t!event.isImmediatePropagationStopped() ) {\n\n\t\t\t\t// If the event is namespaced, then each handler is only invoked if it is\n\t\t\t\t// specially universal or its namespaces are a superset of the event's.\n\t\t\t\tif ( !event.rnamespace || handleObj.namespace === false ||\n\t\t\t\t\tevent.rnamespace.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.handleObj = handleObj;\n\t\t\t\t\tevent.data = handleObj.data;\n\n\t\t\t\t\tret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||\n\t\t\t\t\t\thandleObj.handler ).apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tif ( ( event.result = ret ) === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\thandlers: function( event, handlers ) {\n\t\tvar i, handleObj, sel, matchedHandlers, matchedSelectors,\n\t\t\thandlerQueue = [],\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\tcur = event.target;\n\n\t\t// Find delegate handlers\n\t\tif ( delegateCount &&\n\n\t\t\t// Support: IE <=9\n\t\t\t// Black-hole SVG <use> instance trees (trac-13180)\n\t\t\tcur.nodeType &&\n\n\t\t\t// Support: Firefox <=42\n\t\t\t// Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)\n\t\t\t// https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click\n\t\t\t// Support: IE 11 only\n\t\t\t// ...but not arrow key \"clicks\" of radio inputs, which can have `button` -1 (gh-2343)\n\t\t\t!( event.type === \"click\" && event.button >= 1 ) ) {\n\n\t\t\tfor ( ; cur !== this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't check non-elements (#13208)\n\t\t\t\t// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)\n\t\t\t\tif ( cur.nodeType === 1 && !( event.type === \"click\" && cur.disabled === true ) ) {\n\t\t\t\t\tmatchedHandlers = [];\n\t\t\t\t\tmatchedSelectors = {};\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\n\t\t\t\t\t\t// Don't conflict with Object.prototype properties (#13203)\n\t\t\t\t\t\tsel = handleObj.selector + \" \";\n\n\t\t\t\t\t\tif ( matchedSelectors[ sel ] === undefined ) {\n\t\t\t\t\t\t\tmatchedSelectors[ sel ] = handleObj.needsContext ?\n\t\t\t\t\t\t\t\tjQuery( sel, this ).index( cur ) > -1 :\n\t\t\t\t\t\t\t\tjQuery.find( sel, this, null, [ cur ] ).length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( matchedSelectors[ sel ] ) {\n\t\t\t\t\t\t\tmatchedHandlers.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matchedHandlers.length ) {\n\t\t\t\t\t\thandlerQueue.push( { elem: cur, handlers: matchedHandlers } );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tcur = this;\n\t\tif ( delegateCount < handlers.length ) {\n\t\t\thandlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );\n\t\t}\n\n\t\treturn handlerQueue;\n\t},\n\n\taddProp: function( name, hook ) {\n\t\tObject.defineProperty( jQuery.Event.prototype, name, {\n\t\t\tenumerable: true,\n\t\t\tconfigurable: true,\n\n\t\t\tget: isFunction( hook ) ?\n\t\t\t\tfunction() {\n\t\t\t\t\tif ( this.originalEvent ) {\n\t\t\t\t\t\t\treturn hook( this.originalEvent );\n\t\t\t\t\t}\n\t\t\t\t} :\n\t\t\t\tfunction() {\n\t\t\t\t\tif ( this.originalEvent ) {\n\t\t\t\t\t\t\treturn this.originalEvent[ name ];\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\tset: function( value ) {\n\t\t\t\tObject.defineProperty( this, name, {\n\t\t\t\t\tenumerable: true,\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\twritable: true,\n\t\t\t\t\tvalue: value\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\t},\n\n\tfix: function( originalEvent ) {\n\t\treturn originalEvent[ jQuery.expando ] ?\n\t\t\toriginalEvent :\n\t\t\tnew jQuery.Event( originalEvent );\n\t},\n\n\tspecial: {\n\t\tload: {\n\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\t\tclick: {\n\n\t\t\t// Utilize native event to ensure correct state for checkable inputs\n\t\t\tsetup: function( data ) {\n\n\t\t\t\t// For mutual compressibility with _default, replace `this` access with a local var.\n\t\t\t\t// `|| data` is dead code meant only to preserve the variable through minification.\n\t\t\t\tvar el = this || data;\n\n\t\t\t\t// Claim the first handler\n\t\t\t\tif ( rcheckableType.test( el.type ) &&\n\t\t\t\t\tel.click && nodeName( el, \"input\" ) ) {\n\n\t\t\t\t\t// dataPriv.set( el, \"click\", ... )\n\t\t\t\t\tleverageNative( el, \"click\", returnTrue );\n\t\t\t\t}\n\n\t\t\t\t// Return false to allow normal processing in the caller\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\ttrigger: function( data ) {\n\n\t\t\t\t// For mutual compressibility with _default, replace `this` access with a local var.\n\t\t\t\t// `|| data` is dead code meant only to preserve the variable through minification.\n\t\t\t\tvar el = this || data;\n\n\t\t\t\t// Force setup before triggering a click\n\t\t\t\tif ( rcheckableType.test( el.type ) &&\n\t\t\t\t\tel.click && nodeName( el, \"input\" ) ) {\n\n\t\t\t\t\tleverageNative( el, \"click\" );\n\t\t\t\t}\n\n\t\t\t\t// Return non-false to allow normal event-path propagation\n\t\t\t\treturn true;\n\t\t\t},\n\n\t\t\t// For cross-browser consistency, suppress native .click() on links\n\t\t\t// Also prevent it if we're currently inside a leveraged native-event stack\n\t\t\t_default: function( event ) {\n\t\t\t\tvar target = event.target;\n\t\t\t\treturn rcheckableType.test( target.type ) &&\n\t\t\t\t\ttarget.click && nodeName( target, \"input\" ) &&\n\t\t\t\t\tdataPriv.get( target, \"click\" ) ||\n\t\t\t\t\tnodeName( target, \"a\" );\n\t\t\t}\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tpostDispatch: function( event ) {\n\n\t\t\t\t// Support: Firefox 20+\n\t\t\t\t// Firefox doesn't alert if the returnValue field is not set.\n\t\t\t\tif ( event.result !== undefined && event.originalEvent ) {\n\t\t\t\t\tevent.originalEvent.returnValue = event.result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n};\n\n// Ensure the presence of an event listener that handles manually-triggered\n// synthetic events by interrupting progress until reinvoked in response to\n// *native* events that it fires directly, ensuring that state changes have\n// already occurred before other listeners are invoked.\nfunction leverageNative( el, type, expectSync ) {\n\n\t// Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add\n\tif ( !expectSync ) {\n\t\tif ( dataPriv.get( el, type ) === undefined ) {\n\t\t\tjQuery.event.add( el, type, returnTrue );\n\t\t}\n\t\treturn;\n\t}\n\n\t// Register the controller as a special universal handler for all event namespaces\n\tdataPriv.set( el, type, false );\n\tjQuery.event.add( el, type, {\n\t\tnamespace: false,\n\t\thandler: function( event ) {\n\t\t\tvar notAsync, result,\n\t\t\t\tsaved = dataPriv.get( this, type );\n\n\t\t\tif ( ( event.isTrigger & 1 ) && this[ type ] ) {\n\n\t\t\t\t// Interrupt processing of the outer synthetic .trigger()ed event\n\t\t\t\t// Saved data should be false in such cases, but might be a leftover capture object\n\t\t\t\t// from an async native handler (gh-4350)\n\t\t\t\tif ( !saved.length ) {\n\n\t\t\t\t\t// Store arguments for use when handling the inner native event\n\t\t\t\t\t// There will always be at least one argument (an event object), so this array\n\t\t\t\t\t// will not be confused with a leftover capture object.\n\t\t\t\t\tsaved = slice.call( arguments );\n\t\t\t\t\tdataPriv.set( this, type, saved );\n\n\t\t\t\t\t// Trigger the native event and capture its result\n\t\t\t\t\t// Support: IE <=9 - 11+\n\t\t\t\t\t// focus() and blur() are asynchronous\n\t\t\t\t\tnotAsync = expectSync( this, type );\n\t\t\t\t\tthis[ type ]();\n\t\t\t\t\tresult = dataPriv.get( this, type );\n\t\t\t\t\tif ( saved !== result || notAsync ) {\n\t\t\t\t\t\tdataPriv.set( this, type, false );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult = {};\n\t\t\t\t\t}\n\t\t\t\t\tif ( saved !== result ) {\n\n\t\t\t\t\t\t// Cancel the outer synthetic event\n\t\t\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\treturn result.value;\n\t\t\t\t\t}\n\n\t\t\t\t// If this is an inner synthetic event for an event with a bubbling surrogate\n\t\t\t\t// (focus or blur), assume that the surrogate already propagated from triggering the\n\t\t\t\t// native event and prevent that from happening again here.\n\t\t\t\t// This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the\n\t\t\t\t// bubbling surrogate propagates *after* the non-bubbling base), but that seems\n\t\t\t\t// less bad than duplication.\n\t\t\t\t} else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) {\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t}\n\n\t\t\t// If this is a native event triggered above, everything is now in order\n\t\t\t// Fire an inner synthetic event with the original arguments\n\t\t\t} else if ( saved.length ) {\n\n\t\t\t\t// ...and capture the result\n\t\t\t\tdataPriv.set( this, type, {\n\t\t\t\t\tvalue: jQuery.event.trigger(\n\n\t\t\t\t\t\t// Support: IE <=9 - 11+\n\t\t\t\t\t\t// Extend with the prototype to reset the above stopImmediatePropagation()\n\t\t\t\t\t\tjQuery.extend( saved[ 0 ], jQuery.Event.prototype ),\n\t\t\t\t\t\tsaved.slice( 1 ),\n\t\t\t\t\t\tthis\n\t\t\t\t\t)\n\t\t\t\t} );\n\n\t\t\t\t// Abort handling of the native event\n\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t}\n\t\t}\n\t} );\n}\n\njQuery.removeEvent = function( elem, type, handle ) {\n\n\t// This \"if\" is needed for plain objects\n\tif ( elem.removeEventListener ) {\n\t\telem.removeEventListener( type, handle );\n\t}\n};\n\njQuery.Event = function( src, props ) {\n\n\t// Allow instantiation without the 'new' keyword\n\tif ( !( this instanceof jQuery.Event ) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = src.defaultPrevented ||\n\t\t\t\tsrc.defaultPrevented === undefined &&\n\n\t\t\t\t// Support: Android <=2.3 only\n\t\t\t\tsrc.returnValue === false ?\n\t\t\treturnTrue :\n\t\t\treturnFalse;\n\n\t\t// Create target properties\n\t\t// Support: Safari <=6 - 7 only\n\t\t// Target should not be a text node (#504, #13143)\n\t\tthis.target = ( src.target && src.target.nodeType === 3 ) ?\n\t\t\tsrc.target.parentNode :\n\t\t\tsrc.target;\n\n\t\tthis.currentTarget = src.currentTarget;\n\t\tthis.relatedTarget = src.relatedTarget;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || Date.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tconstructor: jQuery.Event,\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse,\n\tisSimulated: false,\n\n\tpreventDefault: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tif ( e && !this.isSimulated ) {\n\t\t\te.preventDefault();\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tif ( e && !this.isSimulated ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t},\n\tstopImmediatePropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\n\t\tif ( e && !this.isSimulated ) {\n\t\t\te.stopImmediatePropagation();\n\t\t}\n\n\t\tthis.stopPropagation();\n\t}\n};\n\n// Includes all common event props including KeyEvent and MouseEvent specific props\njQuery.each( {\n\taltKey: true,\n\tbubbles: true,\n\tcancelable: true,\n\tchangedTouches: true,\n\tctrlKey: true,\n\tdetail: true,\n\teventPhase: true,\n\tmetaKey: true,\n\tpageX: true,\n\tpageY: true,\n\tshiftKey: true,\n\tview: true,\n\t\"char\": true,\n\tcode: true,\n\tcharCode: true,\n\tkey: true,\n\tkeyCode: true,\n\tbutton: true,\n\tbuttons: true,\n\tclientX: true,\n\tclientY: true,\n\toffsetX: true,\n\toffsetY: true,\n\tpointerId: true,\n\tpointerType: true,\n\tscreenX: true,\n\tscreenY: true,\n\ttargetTouches: true,\n\ttoElement: true,\n\ttouches: true,\n\n\twhich: function( event ) {\n\t\tvar button = event.button;\n\n\t\t// Add which for key events\n\t\tif ( event.which == null && rkeyEvent.test( event.type ) ) {\n\t\t\treturn event.charCode != null ? event.charCode : event.keyCode;\n\t\t}\n\n\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\tif ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {\n\t\t\tif ( button & 1 ) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\tif ( button & 2 ) {\n\t\t\t\treturn 3;\n\t\t\t}\n\n\t\t\tif ( button & 4 ) {\n\t\t\t\treturn 2;\n\t\t\t}\n\n\t\t\treturn 0;\n\t\t}\n\n\t\treturn event.which;\n\t}\n}, jQuery.event.addProp );\n\njQuery.each( { focus: \"focusin\", blur: \"focusout\" }, function( type, delegateType ) {\n\tjQuery.event.special[ type ] = {\n\n\t\t// Utilize native event if possible so blur/focus sequence is correct\n\t\tsetup: function() {\n\n\t\t\t// Claim the first handler\n\t\t\t// dataPriv.set( this, \"focus\", ... )\n\t\t\t// dataPriv.set( this, \"blur\", ... )\n\t\t\tleverageNative( this, type, expectSync );\n\n\t\t\t// Return false to allow normal processing in the caller\n\t\t\treturn false;\n\t\t},\n\t\ttrigger: function() {\n\n\t\t\t// Force setup before trigger\n\t\t\tleverageNative( this, type );\n\n\t\t\t// Return non-false to allow normal event-path propagation\n\t\t\treturn true;\n\t\t},\n\n\t\tdelegateType: delegateType\n\t};\n} );\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\n// so that event delegation works in jQuery.\n// Do the same for pointerenter/pointerleave and pointerover/pointerout\n//\n// Support: Safari 7 only\n// Safari sends mouseenter too often; see:\n// https://bugs.chromium.org/p/chromium/issues/detail?id=470258\n// for the description of the bug (it existed in older Chrome versions as well).\njQuery.each( {\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\",\n\tpointerenter: \"pointerover\",\n\tpointerleave: \"pointerout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar ret,\n\t\t\t\ttarget = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj;\n\n\t\t\t// For mouseenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n} );\n\njQuery.fn.extend( {\n\n\ton: function( types, selector, data, fn ) {\n\t\treturn on( this, types, selector, data, fn );\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn on( this, types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tvar handleObj, type;\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\thandleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ?\n\t\t\t\t\thandleObj.origType + \".\" + handleObj.namespace :\n\t\t\t\t\thandleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t} );\n\t}\n} );\n\n\nvar\n\n\t// Support: IE <=10 - 11, Edge 12 - 13 only\n\t// In IE/Edge using regex groups here causes severe slowdowns.\n\t// See https://connect.microsoft.com/IE/feedback/details/1736512/\n\trnoInnerhtml = /<script|<style|<link/i,\n\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g;\n\n// Prefer a tbody over its parent table for containing new rows\nfunction manipulationTarget( elem, content ) {\n\tif ( nodeName( elem, \"table\" ) &&\n\t\tnodeName( content.nodeType !== 11 ? content : content.firstChild, \"tr\" ) ) {\n\n\t\treturn jQuery( elem ).children( \"tbody\" )[ 0 ] || elem;\n\t}\n\n\treturn elem;\n}\n\n// Replace/restore the type attribute of script elements for safe DOM manipulation\nfunction disableScript( elem ) {\n\telem.type = ( elem.getAttribute( \"type\" ) !== null ) + \"/\" + elem.type;\n\treturn elem;\n}\nfunction restoreScript( elem ) {\n\tif ( ( elem.type || \"\" ).slice( 0, 5 ) === \"true/\" ) {\n\t\telem.type = elem.type.slice( 5 );\n\t} else {\n\t\telem.removeAttribute( \"type\" );\n\t}\n\n\treturn elem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\tvar i, l, type, pdataOld, udataOld, udataCur, events;\n\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// 1. Copy private data: events, handlers, etc.\n\tif ( dataPriv.hasData( src ) ) {\n\t\tpdataOld = dataPriv.get( src );\n\t\tevents = pdataOld.events;\n\n\t\tif ( events ) {\n\t\t\tdataPriv.remove( dest, \"handle events\" );\n\n\t\t\tfor ( type in events ) {\n\t\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// 2. Copy user data\n\tif ( dataUser.hasData( src ) ) {\n\t\tudataOld = dataUser.access( src );\n\t\tudataCur = jQuery.extend( {}, udataOld );\n\n\t\tdataUser.set( dest, udataCur );\n\t}\n}\n\n// Fix IE bugs, see support tests\nfunction fixInput( src, dest ) {\n\tvar nodeName = dest.nodeName.toLowerCase();\n\n\t// Fails to persist the checked state of a cloned checkbox or radio button.\n\tif ( nodeName === \"input\" && rcheckableType.test( src.type ) ) {\n\t\tdest.checked = src.checked;\n\n\t// Fails to return the selected option to the default selected state when cloning options\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n}\n\nfunction domManip( collection, args, callback, ignored ) {\n\n\t// Flatten any nested arrays\n\targs = flat( args );\n\n\tvar fragment, first, scripts, hasScripts, node, doc,\n\t\ti = 0,\n\t\tl = collection.length,\n\t\tiNoClone = l - 1,\n\t\tvalue = args[ 0 ],\n\t\tvalueIsFunction = isFunction( value );\n\n\t// We can't cloneNode fragments that contain checked, in WebKit\n\tif ( valueIsFunction ||\n\t\t\t( l > 1 && typeof value === \"string\" &&\n\t\t\t\t!support.checkClone && rchecked.test( value ) ) ) {\n\t\treturn collection.each( function( index ) {\n\t\t\tvar self = collection.eq( index );\n\t\t\tif ( valueIsFunction ) {\n\t\t\t\targs[ 0 ] = value.call( this, index, self.html() );\n\t\t\t}\n\t\t\tdomManip( self, args, callback, ignored );\n\t\t} );\n\t}\n\n\tif ( l ) {\n\t\tfragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );\n\t\tfirst = fragment.firstChild;\n\n\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\tfragment = first;\n\t\t}\n\n\t\t// Require either new content or an interest in ignored elements to invoke the callback\n\t\tif ( first || ignored ) {\n\t\t\tscripts = jQuery.map( getAll( fragment, \"script\" ), disableScript );\n\t\t\thasScripts = scripts.length;\n\n\t\t\t// Use the original fragment for the last item\n\t\t\t// instead of the first because it can end up\n\t\t\t// being emptied incorrectly in certain situations (#8070).\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tnode = fragment;\n\n\t\t\t\tif ( i !== iNoClone ) {\n\t\t\t\t\tnode = jQuery.clone( node, true, true );\n\n\t\t\t\t\t// Keep references to cloned scripts for later restoration\n\t\t\t\t\tif ( hasScripts ) {\n\n\t\t\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\t\t\tjQuery.merge( scripts, getAll( node, \"script\" ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcallback.call( collection[ i ], node, i );\n\t\t\t}\n\n\t\t\tif ( hasScripts ) {\n\t\t\t\tdoc = scripts[ scripts.length - 1 ].ownerDocument;\n\n\t\t\t\t// Reenable scripts\n\t\t\t\tjQuery.map( scripts, restoreScript );\n\n\t\t\t\t// Evaluate executable scripts on first document insertion\n\t\t\t\tfor ( i = 0; i < hasScripts; i++ ) {\n\t\t\t\t\tnode = scripts[ i ];\n\t\t\t\t\tif ( rscriptType.test( node.type || \"\" ) &&\n\t\t\t\t\t\t!dataPriv.access( node, \"globalEval\" ) &&\n\t\t\t\t\t\tjQuery.contains( doc, node ) ) {\n\n\t\t\t\t\t\tif ( node.src && ( node.type || \"\" ).toLowerCase()  !== \"module\" ) {\n\n\t\t\t\t\t\t\t// Optional AJAX dependency, but won't run scripts if not present\n\t\t\t\t\t\t\tif ( jQuery._evalUrl && !node.noModule ) {\n\t\t\t\t\t\t\t\tjQuery._evalUrl( node.src, {\n\t\t\t\t\t\t\t\t\tnonce: node.nonce || node.getAttribute( \"nonce\" )\n\t\t\t\t\t\t\t\t}, doc );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tDOMEval( node.textContent.replace( rcleanScript, \"\" ), node, doc );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn collection;\n}\n\nfunction remove( elem, selector, keepData ) {\n\tvar node,\n\t\tnodes = selector ? jQuery.filter( selector, elem ) : elem,\n\t\ti = 0;\n\n\tfor ( ; ( node = nodes[ i ] ) != null; i++ ) {\n\t\tif ( !keepData && node.nodeType === 1 ) {\n\t\t\tjQuery.cleanData( getAll( node ) );\n\t\t}\n\n\t\tif ( node.parentNode ) {\n\t\t\tif ( keepData && isAttached( node ) ) {\n\t\t\t\tsetGlobalEval( getAll( node, \"script\" ) );\n\t\t\t}\n\t\t\tnode.parentNode.removeChild( node );\n\t\t}\n\t}\n\n\treturn elem;\n}\n\njQuery.extend( {\n\thtmlPrefilter: function( html ) {\n\t\treturn html;\n\t},\n\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar i, l, srcElements, destElements,\n\t\t\tclone = elem.cloneNode( true ),\n\t\t\tinPage = isAttached( elem );\n\n\t\t// Fix IE cloning issues\n\t\tif ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&\n\t\t\t\t!jQuery.isXMLDoc( elem ) ) {\n\n\t\t\t// We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2\n\t\t\tdestElements = getAll( clone );\n\t\t\tsrcElements = getAll( elem );\n\n\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\tfixInput( srcElements[ i ], destElements[ i ] );\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = srcElements || getAll( elem );\n\t\t\t\tdestElements = destElements || getAll( clone );\n\n\t\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[ i ], destElements[ i ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcloneCopyEvent( elem, clone );\n\t\t\t}\n\t\t}\n\n\t\t// Preserve script evaluation history\n\t\tdestElements = getAll( clone, \"script\" );\n\t\tif ( destElements.length > 0 ) {\n\t\t\tsetGlobalEval( destElements, !inPage && getAll( elem, \"script\" ) );\n\t\t}\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, elem, type,\n\t\t\tspecial = jQuery.event.special,\n\t\t\ti = 0;\n\n\t\tfor ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {\n\t\t\tif ( acceptData( elem ) ) {\n\t\t\t\tif ( ( data = elem[ dataPriv.expando ] ) ) {\n\t\t\t\t\tif ( data.events ) {\n\t\t\t\t\t\tfor ( type in data.events ) {\n\t\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Support: Chrome <=35 - 45+\n\t\t\t\t\t// Assign undefined instead of using delete, see Data#remove\n\t\t\t\t\telem[ dataPriv.expando ] = undefined;\n\t\t\t\t}\n\t\t\t\tif ( elem[ dataUser.expando ] ) {\n\n\t\t\t\t\t// Support: Chrome <=35 - 45+\n\t\t\t\t\t// Assign undefined instead of using delete, see Data#remove\n\t\t\t\t\telem[ dataUser.expando ] = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n} );\n\njQuery.fn.extend( {\n\tdetach: function( selector ) {\n\t\treturn remove( this, selector, true );\n\t},\n\n\tremove: function( selector ) {\n\t\treturn remove( this, selector );\n\t},\n\n\ttext: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().each( function() {\n\t\t\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\t\t\tthis.textContent = value;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t}, null, value, arguments.length );\n\t},\n\n\tappend: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.appendChild( elem );\n\t\t\t}\n\t\t} );\n\t},\n\n\tprepend: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.insertBefore( elem, target.firstChild );\n\t\t\t}\n\t\t} );\n\t},\n\n\tbefore: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t}\n\t\t} );\n\t},\n\n\tafter: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t}\n\t\t} );\n\t},\n\n\tempty: function() {\n\t\tvar elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; ( elem = this[ i ] ) != null; i++ ) {\n\t\t\tif ( elem.nodeType === 1 ) {\n\n\t\t\t\t// Prevent memory leaks\n\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\n\t\t\t\t// Remove any remaining nodes\n\t\t\t\telem.textContent = \"\";\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function() {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t} );\n\t},\n\n\thtml: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\tvar elem = this[ 0 ] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined && elem.nodeType === 1 ) {\n\t\t\t\treturn elem.innerHTML;\n\t\t\t}\n\n\t\t\t// See if we can take a shortcut and just use innerHTML\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [ \"\", \"\" ] )[ 1 ].toLowerCase() ] ) {\n\n\t\t\t\tvalue = jQuery.htmlPrefilter( value );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\t\telem = this[ i ] || {};\n\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch ( e ) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function() {\n\t\tvar ignored = [];\n\n\t\t// Make the changes, replacing each non-ignored context element with the new content\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tvar parent = this.parentNode;\n\n\t\t\tif ( jQuery.inArray( this, ignored ) < 0 ) {\n\t\t\t\tjQuery.cleanData( getAll( this ) );\n\t\t\t\tif ( parent ) {\n\t\t\t\t\tparent.replaceChild( elem, this );\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Force callback invocation\n\t\t}, ignored );\n\t}\n} );\n\njQuery.each( {\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar elems,\n\t\t\tret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tlast = insert.length - 1,\n\t\t\ti = 0;\n\n\t\tfor ( ; i <= last; i++ ) {\n\t\t\telems = i === last ? this : this.clone( true );\n\t\t\tjQuery( insert[ i ] )[ original ]( elems );\n\n\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t// .get() because push.apply(_, arraylike) throws on ancient WebKit\n\t\t\tpush.apply( ret, elems.get() );\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n} );\nvar rnumnonpx = new RegExp( \"^(\" + pnum + \")(?!px)[a-z%]+$\", \"i\" );\n\nvar getStyles = function( elem ) {\n\n\t\t// Support: IE <=11 only, Firefox <=30 (#15098, #14150)\n\t\t// IE throws on elements created in popups\n\t\t// FF meanwhile throws on frame elements through \"defaultView.getComputedStyle\"\n\t\tvar view = elem.ownerDocument.defaultView;\n\n\t\tif ( !view || !view.opener ) {\n\t\t\tview = window;\n\t\t}\n\n\t\treturn view.getComputedStyle( elem );\n\t};\n\nvar swap = function( elem, options, callback ) {\n\tvar ret, name,\n\t\told = {};\n\n\t// Remember the old values, and insert the new ones\n\tfor ( name in options ) {\n\t\told[ name ] = elem.style[ name ];\n\t\telem.style[ name ] = options[ name ];\n\t}\n\n\tret = callback.call( elem );\n\n\t// Revert the old values\n\tfor ( name in options ) {\n\t\telem.style[ name ] = old[ name ];\n\t}\n\n\treturn ret;\n};\n\n\nvar rboxStyle = new RegExp( cssExpand.join( \"|\" ), \"i\" );\n\n\n\n( function() {\n\n\t// Executing both pixelPosition & boxSizingReliable tests require only one layout\n\t// so they're executed at the same time to save the second computation.\n\tfunction computeStyleTests() {\n\n\t\t// This is a singleton, we need to execute it only once\n\t\tif ( !div ) {\n\t\t\treturn;\n\t\t}\n\n\t\tcontainer.style.cssText = \"position:absolute;left:-11111px;width:60px;\" +\n\t\t\t\"margin-top:1px;padding:0;border:0\";\n\t\tdiv.style.cssText =\n\t\t\t\"position:relative;display:block;box-sizing:border-box;overflow:scroll;\" +\n\t\t\t\"margin:auto;border:1px;padding:1px;\" +\n\t\t\t\"width:60%;top:1%\";\n\t\tdocumentElement.appendChild( container ).appendChild( div );\n\n\t\tvar divStyle = window.getComputedStyle( div );\n\t\tpixelPositionVal = divStyle.top !== \"1%\";\n\n\t\t// Support: Android 4.0 - 4.3 only, Firefox <=3 - 44\n\t\treliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12;\n\n\t\t// Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3\n\t\t// Some styles come back with percentage values, even though they shouldn't\n\t\tdiv.style.right = \"60%\";\n\t\tpixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36;\n\n\t\t// Support: IE 9 - 11 only\n\t\t// Detect misreporting of content dimensions for box-sizing:border-box elements\n\t\tboxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36;\n\n\t\t// Support: IE 9 only\n\t\t// Detect overflow:scroll screwiness (gh-3699)\n\t\t// Support: Chrome <=64\n\t\t// Don't get tricked when zoom affects offsetWidth (gh-4029)\n\t\tdiv.style.position = \"absolute\";\n\t\tscrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12;\n\n\t\tdocumentElement.removeChild( container );\n\n\t\t// Nullify the div so it wouldn't be stored in the memory and\n\t\t// it will also be a sign that checks already performed\n\t\tdiv = null;\n\t}\n\n\tfunction roundPixelMeasures( measure ) {\n\t\treturn Math.round( parseFloat( measure ) );\n\t}\n\n\tvar pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal,\n\t\treliableTrDimensionsVal, reliableMarginLeftVal,\n\t\tcontainer = document.createElement( \"div\" ),\n\t\tdiv = document.createElement( \"div\" );\n\n\t// Finish early in limited (non-browser) environments\n\tif ( !div.style ) {\n\t\treturn;\n\t}\n\n\t// Support: IE <=9 - 11 only\n\t// Style of cloned element affects source element cloned (#8908)\n\tdiv.style.backgroundClip = \"content-box\";\n\tdiv.cloneNode( true ).style.backgroundClip = \"\";\n\tsupport.clearCloneStyle = div.style.backgroundClip === \"content-box\";\n\n\tjQuery.extend( support, {\n\t\tboxSizingReliable: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn boxSizingReliableVal;\n\t\t},\n\t\tpixelBoxStyles: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn pixelBoxStylesVal;\n\t\t},\n\t\tpixelPosition: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn pixelPositionVal;\n\t\t},\n\t\treliableMarginLeft: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn reliableMarginLeftVal;\n\t\t},\n\t\tscrollboxSize: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn scrollboxSizeVal;\n\t\t},\n\n\t\t// Support: IE 9 - 11+, Edge 15 - 18+\n\t\t// IE/Edge misreport `getComputedStyle` of table rows with width/height\n\t\t// set in CSS while `offset*` properties report correct values.\n\t\t// Behavior in IE 9 is more subtle than in newer versions & it passes\n\t\t// some versions of this test; make sure not to make it pass there!\n\t\treliableTrDimensions: function() {\n\t\t\tvar table, tr, trChild, trStyle;\n\t\t\tif ( reliableTrDimensionsVal == null ) {\n\t\t\t\ttable = document.createElement( \"table\" );\n\t\t\t\ttr = document.createElement( \"tr\" );\n\t\t\t\ttrChild = document.createElement( \"div\" );\n\n\t\t\t\ttable.style.cssText = \"position:absolute;left:-11111px\";\n\t\t\t\ttr.style.height = \"1px\";\n\t\t\t\ttrChild.style.height = \"9px\";\n\n\t\t\t\tdocumentElement\n\t\t\t\t\t.appendChild( table )\n\t\t\t\t\t.appendChild( tr )\n\t\t\t\t\t.appendChild( trChild );\n\n\t\t\t\ttrStyle = window.getComputedStyle( tr );\n\t\t\t\treliableTrDimensionsVal = parseInt( trStyle.height ) > 3;\n\n\t\t\t\tdocumentElement.removeChild( table );\n\t\t\t}\n\t\t\treturn reliableTrDimensionsVal;\n\t\t}\n\t} );\n} )();\n\n\nfunction curCSS( elem, name, computed ) {\n\tvar width, minWidth, maxWidth, ret,\n\n\t\t// Support: Firefox 51+\n\t\t// Retrieving style before computed somehow\n\t\t// fixes an issue with getting wrong values\n\t\t// on detached elements\n\t\tstyle = elem.style;\n\n\tcomputed = computed || getStyles( elem );\n\n\t// getPropertyValue is needed for:\n\t//   .css('filter') (IE 9 only, #12537)\n\t//   .css('--customProperty) (#3144)\n\tif ( computed ) {\n\t\tret = computed.getPropertyValue( name ) || computed[ name ];\n\n\t\tif ( ret === \"\" && !isAttached( elem ) ) {\n\t\t\tret = jQuery.style( elem, name );\n\t\t}\n\n\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t// Android Browser returns percentage for some values,\n\t\t// but width seems to be reliably pixels.\n\t\t// This is against the CSSOM draft spec:\n\t\t// https://drafts.csswg.org/cssom/#resolved-values\n\t\tif ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) {\n\n\t\t\t// Remember the original values\n\t\t\twidth = style.width;\n\t\t\tminWidth = style.minWidth;\n\t\t\tmaxWidth = style.maxWidth;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tstyle.minWidth = style.maxWidth = style.width = ret;\n\t\t\tret = computed.width;\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.width = width;\n\t\t\tstyle.minWidth = minWidth;\n\t\t\tstyle.maxWidth = maxWidth;\n\t\t}\n\t}\n\n\treturn ret !== undefined ?\n\n\t\t// Support: IE <=9 - 11 only\n\t\t// IE returns zIndex value as an integer.\n\t\tret + \"\" :\n\t\tret;\n}\n\n\nfunction addGetHookIf( conditionFn, hookFn ) {\n\n\t// Define the hook, we'll check on the first run if it's really needed.\n\treturn {\n\t\tget: function() {\n\t\t\tif ( conditionFn() ) {\n\n\t\t\t\t// Hook not needed (or it's not possible to use it due\n\t\t\t\t// to missing dependency), remove it.\n\t\t\t\tdelete this.get;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Hook needed; redefine it so that the support test is not executed again.\n\t\t\treturn ( this.get = hookFn ).apply( this, arguments );\n\t\t}\n\t};\n}\n\n\nvar cssPrefixes = [ \"Webkit\", \"Moz\", \"ms\" ],\n\temptyStyle = document.createElement( \"div\" ).style,\n\tvendorProps = {};\n\n// Return a vendor-prefixed property or undefined\nfunction vendorPropName( name ) {\n\n\t// Check for vendor prefixed names\n\tvar capName = name[ 0 ].toUpperCase() + name.slice( 1 ),\n\t\ti = cssPrefixes.length;\n\n\twhile ( i-- ) {\n\t\tname = cssPrefixes[ i ] + capName;\n\t\tif ( name in emptyStyle ) {\n\t\t\treturn name;\n\t\t}\n\t}\n}\n\n// Return a potentially-mapped jQuery.cssProps or vendor prefixed property\nfunction finalPropName( name ) {\n\tvar final = jQuery.cssProps[ name ] || vendorProps[ name ];\n\n\tif ( final ) {\n\t\treturn final;\n\t}\n\tif ( name in emptyStyle ) {\n\t\treturn name;\n\t}\n\treturn vendorProps[ name ] = vendorPropName( name ) || name;\n}\n\n\nvar\n\n\t// Swappable if display is none or starts with table\n\t// except \"table\", \"table-cell\", or \"table-caption\"\n\t// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n\trdisplayswap = /^(none|table(?!-c[ea]).+)/,\n\trcustomProp = /^--/,\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssNormalTransform = {\n\t\tletterSpacing: \"0\",\n\t\tfontWeight: \"400\"\n\t};\n\nfunction setPositiveNumber( _elem, value, subtract ) {\n\n\t// Any relative (+/-) values have already been\n\t// normalized at this point\n\tvar matches = rcssNum.exec( value );\n\treturn matches ?\n\n\t\t// Guard against undefined \"subtract\", e.g., when used as in cssHooks\n\t\tMath.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || \"px\" ) :\n\t\tvalue;\n}\n\nfunction boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) {\n\tvar i = dimension === \"width\" ? 1 : 0,\n\t\textra = 0,\n\t\tdelta = 0;\n\n\t// Adjustment may not be necessary\n\tif ( box === ( isBorderBox ? \"border\" : \"content\" ) ) {\n\t\treturn 0;\n\t}\n\n\tfor ( ; i < 4; i += 2 ) {\n\n\t\t// Both box models exclude margin\n\t\tif ( box === \"margin\" ) {\n\t\t\tdelta += jQuery.css( elem, box + cssExpand[ i ], true, styles );\n\t\t}\n\n\t\t// If we get here with a content-box, we're seeking \"padding\" or \"border\" or \"margin\"\n\t\tif ( !isBorderBox ) {\n\n\t\t\t// Add padding\n\t\t\tdelta += jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\n\t\t\t// For \"border\" or \"margin\", add border\n\t\t\tif ( box !== \"padding\" ) {\n\t\t\t\tdelta += jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\n\t\t\t// But still keep track of it otherwise\n\t\t\t} else {\n\t\t\t\textra += jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\n\t\t// If we get here with a border-box (content + padding + border), we're seeking \"content\" or\n\t\t// \"padding\" or \"margin\"\n\t\t} else {\n\n\t\t\t// For \"content\", subtract padding\n\t\t\tif ( box === \"content\" ) {\n\t\t\t\tdelta -= jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\t\t\t}\n\n\t\t\t// For \"content\" or \"padding\", subtract border\n\t\t\tif ( box !== \"margin\" ) {\n\t\t\t\tdelta -= jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t}\n\t}\n\n\t// Account for positive content-box scroll gutter when requested by providing computedVal\n\tif ( !isBorderBox && computedVal >= 0 ) {\n\n\t\t// offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border\n\t\t// Assuming integer scroll gutter, subtract the rest and round down\n\t\tdelta += Math.max( 0, Math.ceil(\n\t\t\telem[ \"offset\" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -\n\t\t\tcomputedVal -\n\t\t\tdelta -\n\t\t\textra -\n\t\t\t0.5\n\n\t\t// If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter\n\t\t// Use an explicit zero to avoid NaN (gh-3964)\n\t\t) ) || 0;\n\t}\n\n\treturn delta;\n}\n\nfunction getWidthOrHeight( elem, dimension, extra ) {\n\n\t// Start with computed style\n\tvar styles = getStyles( elem ),\n\n\t\t// To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322).\n\t\t// Fake content-box until we know it's needed to know the true value.\n\t\tboxSizingNeeded = !support.boxSizingReliable() || extra,\n\t\tisBorderBox = boxSizingNeeded &&\n\t\t\tjQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\",\n\t\tvalueIsBorderBox = isBorderBox,\n\n\t\tval = curCSS( elem, dimension, styles ),\n\t\toffsetProp = \"offset\" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 );\n\n\t// Support: Firefox <=54\n\t// Return a confounding non-pixel value or feign ignorance, as appropriate.\n\tif ( rnumnonpx.test( val ) ) {\n\t\tif ( !extra ) {\n\t\t\treturn val;\n\t\t}\n\t\tval = \"auto\";\n\t}\n\n\n\t// Support: IE 9 - 11 only\n\t// Use offsetWidth/offsetHeight for when box sizing is unreliable.\n\t// In those cases, the computed value can be trusted to be border-box.\n\tif ( ( !support.boxSizingReliable() && isBorderBox ||\n\n\t\t// Support: IE 10 - 11+, Edge 15 - 18+\n\t\t// IE/Edge misreport `getComputedStyle` of table rows with width/height\n\t\t// set in CSS while `offset*` properties report correct values.\n\t\t// Interestingly, in some cases IE 9 doesn't suffer from this issue.\n\t\t!support.reliableTrDimensions() && nodeName( elem, \"tr\" ) ||\n\n\t\t// Fall back to offsetWidth/offsetHeight when value is \"auto\"\n\t\t// This happens for inline elements with no explicit setting (gh-3571)\n\t\tval === \"auto\" ||\n\n\t\t// Support: Android <=4.1 - 4.3 only\n\t\t// Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602)\n\t\t!parseFloat( val ) && jQuery.css( elem, \"display\", false, styles ) === \"inline\" ) &&\n\n\t\t// Make sure the element is visible & connected\n\t\telem.getClientRects().length ) {\n\n\t\tisBorderBox = jQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\";\n\n\t\t// Where available, offsetWidth/offsetHeight approximate border box dimensions.\n\t\t// Where not available (e.g., SVG), assume unreliable box-sizing and interpret the\n\t\t// retrieved value as a content box dimension.\n\t\tvalueIsBorderBox = offsetProp in elem;\n\t\tif ( valueIsBorderBox ) {\n\t\t\tval = elem[ offsetProp ];\n\t\t}\n\t}\n\n\t// Normalize \"\" and auto\n\tval = parseFloat( val ) || 0;\n\n\t// Adjust for the element's box model\n\treturn ( val +\n\t\tboxModelAdjustment(\n\t\t\telem,\n\t\t\tdimension,\n\t\t\textra || ( isBorderBox ? \"border\" : \"content\" ),\n\t\t\tvalueIsBorderBox,\n\t\t\tstyles,\n\n\t\t\t// Provide the current computed size to request scroll gutter calculation (gh-3589)\n\t\t\tval\n\t\t)\n\t) + \"px\";\n}\n\njQuery.extend( {\n\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Don't automatically add \"px\" to these possibly-unitless properties\n\tcssNumber: {\n\t\t\"animationIterationCount\": true,\n\t\t\"columnCount\": true,\n\t\t\"fillOpacity\": true,\n\t\t\"flexGrow\": true,\n\t\t\"flexShrink\": true,\n\t\t\"fontWeight\": true,\n\t\t\"gridArea\": true,\n\t\t\"gridColumn\": true,\n\t\t\"gridColumnEnd\": true,\n\t\t\"gridColumnStart\": true,\n\t\t\"gridRow\": true,\n\t\t\"gridRowEnd\": true,\n\t\t\"gridRowStart\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"order\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, hooks,\n\t\t\torigName = camelCase( name ),\n\t\t\tisCustomProp = rcustomProp.test( name ),\n\t\t\tstyle = elem.style;\n\n\t\t// Make sure that we're working with the right name. We don't\n\t\t// want to query the value if it is a CSS custom property\n\t\t// since they are user-defined.\n\t\tif ( !isCustomProp ) {\n\t\t\tname = finalPropName( origName );\n\t\t}\n\n\t\t// Gets hook for the prefixed version, then unprefixed version\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// Convert \"+=\" or \"-=\" to relative numbers (#7345)\n\t\t\tif ( type === \"string\" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {\n\t\t\t\tvalue = adjustCSS( elem, name, ret );\n\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that null and NaN values aren't set (#7116)\n\t\t\tif ( value == null || value !== value ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add the unit (except for certain CSS properties)\n\t\t\t// The isCustomProp check can be removed in jQuery 4.0 when we only auto-append\n\t\t\t// \"px\" to a few hardcoded values.\n\t\t\tif ( type === \"number\" && !isCustomProp ) {\n\t\t\t\tvalue += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? \"\" : \"px\" );\n\t\t\t}\n\n\t\t\t// background-* props affect original clone's values\n\t\t\tif ( !support.clearCloneStyle && value === \"\" && name.indexOf( \"background\" ) === 0 ) {\n\t\t\t\tstyle[ name ] = \"inherit\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !( \"set\" in hooks ) ||\n\t\t\t\t( value = hooks.set( elem, value, extra ) ) !== undefined ) {\n\n\t\t\t\tif ( isCustomProp ) {\n\t\t\t\t\tstyle.setProperty( name, value );\n\t\t\t\t} else {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks &&\n\t\t\t\t( ret = hooks.get( elem, false, extra ) ) !== undefined ) {\n\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra, styles ) {\n\t\tvar val, num, hooks,\n\t\t\torigName = camelCase( name ),\n\t\t\tisCustomProp = rcustomProp.test( name );\n\n\t\t// Make sure that we're working with the right name. We don't\n\t\t// want to modify the value if it is a CSS custom property\n\t\t// since they are user-defined.\n\t\tif ( !isCustomProp ) {\n\t\t\tname = finalPropName( origName );\n\t\t}\n\n\t\t// Try prefixed name followed by the unprefixed name\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks ) {\n\t\t\tval = hooks.get( elem, true, extra );\n\t\t}\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\tif ( val === undefined ) {\n\t\t\tval = curCSS( elem, name, styles );\n\t\t}\n\n\t\t// Convert \"normal\" to computed value\n\t\tif ( val === \"normal\" && name in cssNormalTransform ) {\n\t\t\tval = cssNormalTransform[ name ];\n\t\t}\n\n\t\t// Make numeric if forced or a qualifier was provided and val looks numeric\n\t\tif ( extra === \"\" || extra ) {\n\t\t\tnum = parseFloat( val );\n\t\t\treturn extra === true || isFinite( num ) ? num || 0 : val;\n\t\t}\n\n\t\treturn val;\n\t}\n} );\n\njQuery.each( [ \"height\", \"width\" ], function( _i, dimension ) {\n\tjQuery.cssHooks[ dimension ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\n\t\t\t\t// Certain elements can have dimension info if we invisibly show them\n\t\t\t\t// but it must have a current display style that would benefit\n\t\t\t\treturn rdisplayswap.test( jQuery.css( elem, \"display\" ) ) &&\n\n\t\t\t\t\t// Support: Safari 8+\n\t\t\t\t\t// Table columns in Safari have non-zero offsetWidth & zero\n\t\t\t\t\t// getBoundingClientRect().width unless display is changed.\n\t\t\t\t\t// Support: IE <=11 only\n\t\t\t\t\t// Running getBoundingClientRect on a disconnected node\n\t\t\t\t\t// in IE throws an error.\n\t\t\t\t\t( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?\n\t\t\t\t\t\tswap( elem, cssShow, function() {\n\t\t\t\t\t\t\treturn getWidthOrHeight( elem, dimension, extra );\n\t\t\t\t\t\t} ) :\n\t\t\t\t\t\tgetWidthOrHeight( elem, dimension, extra );\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value, extra ) {\n\t\t\tvar matches,\n\t\t\t\tstyles = getStyles( elem ),\n\n\t\t\t\t// Only read styles.position if the test has a chance to fail\n\t\t\t\t// to avoid forcing a reflow.\n\t\t\t\tscrollboxSizeBuggy = !support.scrollboxSize() &&\n\t\t\t\t\tstyles.position === \"absolute\",\n\n\t\t\t\t// To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991)\n\t\t\t\tboxSizingNeeded = scrollboxSizeBuggy || extra,\n\t\t\t\tisBorderBox = boxSizingNeeded &&\n\t\t\t\t\tjQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\",\n\t\t\t\tsubtract = extra ?\n\t\t\t\t\tboxModelAdjustment(\n\t\t\t\t\t\telem,\n\t\t\t\t\t\tdimension,\n\t\t\t\t\t\textra,\n\t\t\t\t\t\tisBorderBox,\n\t\t\t\t\t\tstyles\n\t\t\t\t\t) :\n\t\t\t\t\t0;\n\n\t\t\t// Account for unreliable border-box dimensions by comparing offset* to computed and\n\t\t\t// faking a content-box to get border and padding (gh-3699)\n\t\t\tif ( isBorderBox && scrollboxSizeBuggy ) {\n\t\t\t\tsubtract -= Math.ceil(\n\t\t\t\t\telem[ \"offset\" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -\n\t\t\t\t\tparseFloat( styles[ dimension ] ) -\n\t\t\t\t\tboxModelAdjustment( elem, dimension, \"border\", false, styles ) -\n\t\t\t\t\t0.5\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Convert to pixels if value adjustment is needed\n\t\t\tif ( subtract && ( matches = rcssNum.exec( value ) ) &&\n\t\t\t\t( matches[ 3 ] || \"px\" ) !== \"px\" ) {\n\n\t\t\t\telem.style[ dimension ] = value;\n\t\t\t\tvalue = jQuery.css( elem, dimension );\n\t\t\t}\n\n\t\t\treturn setPositiveNumber( elem, value, subtract );\n\t\t}\n\t};\n} );\n\njQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,\n\tfunction( elem, computed ) {\n\t\tif ( computed ) {\n\t\t\treturn ( parseFloat( curCSS( elem, \"marginLeft\" ) ) ||\n\t\t\t\telem.getBoundingClientRect().left -\n\t\t\t\t\tswap( elem, { marginLeft: 0 }, function() {\n\t\t\t\t\t\treturn elem.getBoundingClientRect().left;\n\t\t\t\t\t} )\n\t\t\t\t) + \"px\";\n\t\t}\n\t}\n);\n\n// These hooks are used by animate to expand properties\njQuery.each( {\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i = 0,\n\t\t\t\texpanded = {},\n\n\t\t\t\t// Assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split( \" \" ) : [ value ];\n\n\t\t\tfor ( ; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n\n\tif ( prefix !== \"margin\" ) {\n\t\tjQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;\n\t}\n} );\n\njQuery.fn.extend( {\n\tcss: function( name, value ) {\n\t\treturn access( this, function( elem, name, value ) {\n\t\t\tvar styles, len,\n\t\t\t\tmap = {},\n\t\t\t\ti = 0;\n\n\t\t\tif ( Array.isArray( name ) ) {\n\t\t\t\tstyles = getStyles( elem );\n\t\t\t\tlen = name.length;\n\n\t\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t\tmap[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );\n\t\t\t\t}\n\n\t\t\t\treturn map;\n\t\t\t}\n\n\t\t\treturn value !== undefined ?\n\t\t\t\tjQuery.style( elem, name, value ) :\n\t\t\t\tjQuery.css( elem, name );\n\t\t}, name, value, arguments.length > 1 );\n\t}\n} );\n\n\n// Based off of the plugin by Clint Helfers, with permission.\n// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/\njQuery.fn.delay = function( time, type ) {\n\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\ttype = type || \"fx\";\n\n\treturn this.queue( type, function( next, hooks ) {\n\t\tvar timeout = window.setTimeout( next, time );\n\t\thooks.stop = function() {\n\t\t\twindow.clearTimeout( timeout );\n\t\t};\n\t} );\n};\n\n\n( function() {\n\tvar input = document.createElement( \"input\" ),\n\t\tselect = document.createElement( \"select\" ),\n\t\topt = select.appendChild( document.createElement( \"option\" ) );\n\n\tinput.type = \"checkbox\";\n\n\t// Support: Android <=4.3 only\n\t// Default value for a checkbox should be \"on\"\n\tsupport.checkOn = input.value !== \"\";\n\n\t// Support: IE <=11 only\n\t// Must access selectedIndex to make default options select\n\tsupport.optSelected = opt.selected;\n\n\t// Support: IE <=11 only\n\t// An input loses its value after becoming a radio\n\tinput = document.createElement( \"input\" );\n\tinput.value = \"t\";\n\tinput.type = \"radio\";\n\tsupport.radioValue = input.value === \"t\";\n} )();\n\n\nvar boolHook,\n\tattrHandle = jQuery.expr.attrHandle;\n\njQuery.fn.extend( {\n\tattr: function( name, value ) {\n\t\treturn access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each( function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t} );\n\t}\n} );\n\njQuery.extend( {\n\tattr: function( elem, name, value ) {\n\t\tvar ret, hooks,\n\t\t\tnType = elem.nodeType;\n\n\t\t// Don't get/set attributes on text, comment and attribute nodes\n\t\tif ( nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === \"undefined\" ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\t// Attribute hooks are determined by the lowercase version\n\t\t// Grab necessary hook if one is defined\n\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n\t\t\thooks = jQuery.attrHooks[ name.toLowerCase() ] ||\n\t\t\t\t( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( hooks && \"set\" in hooks &&\n\t\t\t\t( ret = hooks.set( elem, value, name ) ) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, value + \"\" );\n\t\t\treturn value;\n\t\t}\n\n\t\tif ( hooks && \"get\" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tret = jQuery.find.attr( elem, name );\n\n\t\t// Non-existent attributes return null, we normalize to undefined\n\t\treturn ret == null ? undefined : ret;\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( !support.radioValue && value === \"radio\" &&\n\t\t\t\t\tnodeName( elem, \"input\" ) ) {\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar name,\n\t\t\ti = 0,\n\n\t\t\t// Attribute names can contain non-HTML whitespace characters\n\t\t\t// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2\n\t\t\tattrNames = value && value.match( rnothtmlwhite );\n\n\t\tif ( attrNames && elem.nodeType === 1 ) {\n\t\t\twhile ( ( name = attrNames[ i++ ] ) ) {\n\t\t\t\telem.removeAttribute( name );\n\t\t\t}\n\t\t}\n\t}\n} );\n\n// Hooks for boolean attributes\nboolHook = {\n\tset: function( elem, value, name ) {\n\t\tif ( value === false ) {\n\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\telem.setAttribute( name, name );\n\t\t}\n\t\treturn name;\n\t}\n};\n\njQuery.each( jQuery.expr.match.bool.source.match( /\\w+/g ), function( _i, name ) {\n\tvar getter = attrHandle[ name ] || jQuery.find.attr;\n\n\tattrHandle[ name ] = function( elem, name, isXML ) {\n\t\tvar ret, handle,\n\t\t\tlowercaseName = name.toLowerCase();\n\n\t\tif ( !isXML ) {\n\n\t\t\t// Avoid an infinite loop by temporarily removing this function from the getter\n\t\t\thandle = attrHandle[ lowercaseName ];\n\t\t\tattrHandle[ lowercaseName ] = ret;\n\t\t\tret = getter( elem, name, isXML ) != null ?\n\t\t\t\tlowercaseName :\n\t\t\t\tnull;\n\t\t\tattrHandle[ lowercaseName ] = handle;\n\t\t}\n\t\treturn ret;\n\t};\n} );\n\n\n\n\nvar rfocusable = /^(?:input|select|textarea|button)$/i,\n\trclickable = /^(?:a|area)$/i;\n\njQuery.fn.extend( {\n\tprop: function( name, value ) {\n\t\treturn access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\treturn this.each( function() {\n\t\t\tdelete this[ jQuery.propFix[ name ] || name ];\n\t\t} );\n\t}\n} );\n\njQuery.extend( {\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks,\n\t\t\tnType = elem.nodeType;\n\n\t\t// Don't get/set properties on text, comment and attribute nodes\n\t\tif ( nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks &&\n\t\t\t\t( ret = hooks.set( elem, value, name ) ) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\treturn ( elem[ name ] = value );\n\t\t}\n\n\t\tif ( hooks && \"get\" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\treturn elem[ name ];\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\n\t\t\t\t// Support: IE <=9 - 11 only\n\t\t\t\t// elem.tabIndex doesn't always return the\n\t\t\t\t// correct value when it hasn't been explicitly set\n\t\t\t\t// https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\t// Use proper attribute retrieval(#12072)\n\t\t\t\tvar tabindex = jQuery.find.attr( elem, \"tabindex\" );\n\n\t\t\t\tif ( tabindex ) {\n\t\t\t\t\treturn parseInt( tabindex, 10 );\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\trfocusable.test( elem.nodeName ) ||\n\t\t\t\t\trclickable.test( elem.nodeName ) &&\n\t\t\t\t\telem.href\n\t\t\t\t) {\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\"\n\t}\n} );\n\n// Support: IE <=11 only\n// Accessing the selectedIndex property\n// forces the browser to respect setting selected\n// on the option\n// The getter ensures a default option is selected\n// when in an optgroup\n// eslint rule \"no-unused-expressions\" is disabled for this code\n// since it considers such accessions noop\nif ( !support.optSelected ) {\n\tjQuery.propHooks.selected = {\n\t\tget: function( elem ) {\n\n\t\t\t/* eslint no-unused-expressions: \"off\" */\n\n\t\t\tvar parent = elem.parentNode;\n\t\t\tif ( parent && parent.parentNode ) {\n\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\tset: function( elem ) {\n\n\t\t\t/* eslint no-unused-expressions: \"off\" */\n\n\t\t\tvar parent = elem.parentNode;\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\njQuery.each( [\n\t\"tabIndex\",\n\t\"readOnly\",\n\t\"maxLength\",\n\t\"cellSpacing\",\n\t\"cellPadding\",\n\t\"rowSpan\",\n\t\"colSpan\",\n\t\"useMap\",\n\t\"frameBorder\",\n\t\"contentEditable\"\n], function() {\n\tjQuery.propFix[ this.toLowerCase() ] = this;\n} );\n\n\n\n\n\t// Strip and collapse whitespace according to HTML spec\n\t// https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace\n\tfunction stripAndCollapse( value ) {\n\t\tvar tokens = value.match( rnothtmlwhite ) || [];\n\t\treturn tokens.join( \" \" );\n\t}\n\n\nfunction getClass( elem ) {\n\treturn elem.getAttribute && elem.getAttribute( \"class\" ) || \"\";\n}\n\nfunction classesToArray( value ) {\n\tif ( Array.isArray( value ) ) {\n\t\treturn value;\n\t}\n\tif ( typeof value === \"string\" ) {\n\t\treturn value.match( rnothtmlwhite ) || [];\n\t}\n\treturn [];\n}\n\njQuery.fn.extend( {\n\taddClass: function( value ) {\n\t\tvar classes, elem, cur, curValue, clazz, j, finalValue,\n\t\t\ti = 0;\n\n\t\tif ( isFunction( value ) ) {\n\t\t\treturn this.each( function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call( this, j, getClass( this ) ) );\n\t\t\t} );\n\t\t}\n\n\t\tclasses = classesToArray( value );\n\n\t\tif ( classes.length ) {\n\t\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\t\tcurValue = getClass( elem );\n\t\t\t\tcur = elem.nodeType === 1 && ( \" \" + stripAndCollapse( curValue ) + \" \" );\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( ( clazz = classes[ j++ ] ) ) {\n\t\t\t\t\t\tif ( cur.indexOf( \" \" + clazz + \" \" ) < 0 ) {\n\t\t\t\t\t\t\tcur += clazz + \" \";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Only assign if different to avoid unneeded rendering.\n\t\t\t\t\tfinalValue = stripAndCollapse( cur );\n\t\t\t\t\tif ( curValue !== finalValue ) {\n\t\t\t\t\t\telem.setAttribute( \"class\", finalValue );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classes, elem, cur, curValue, clazz, j, finalValue,\n\t\t\ti = 0;\n\n\t\tif ( isFunction( value ) ) {\n\t\t\treturn this.each( function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );\n\t\t\t} );\n\t\t}\n\n\t\tif ( !arguments.length ) {\n\t\t\treturn this.attr( \"class\", \"\" );\n\t\t}\n\n\t\tclasses = classesToArray( value );\n\n\t\tif ( classes.length ) {\n\t\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\t\tcurValue = getClass( elem );\n\n\t\t\t\t// This expression is here for better compressibility (see addClass)\n\t\t\t\tcur = elem.nodeType === 1 && ( \" \" + stripAndCollapse( curValue ) + \" \" );\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( ( clazz = classes[ j++ ] ) ) {\n\n\t\t\t\t\t\t// Remove *all* instances\n\t\t\t\t\t\twhile ( cur.indexOf( \" \" + clazz + \" \" ) > -1 ) {\n\t\t\t\t\t\t\tcur = cur.replace( \" \" + clazz + \" \", \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Only assign if different to avoid unneeded rendering.\n\t\t\t\t\tfinalValue = stripAndCollapse( cur );\n\t\t\t\t\tif ( curValue !== finalValue ) {\n\t\t\t\t\t\telem.setAttribute( \"class\", finalValue );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisValidValue = type === \"string\" || Array.isArray( value );\n\n\t\tif ( typeof stateVal === \"boolean\" && isValidValue ) {\n\t\t\treturn stateVal ? this.addClass( value ) : this.removeClass( value );\n\t\t}\n\n\t\tif ( isFunction( value ) ) {\n\t\t\treturn this.each( function( i ) {\n\t\t\t\tjQuery( this ).toggleClass(\n\t\t\t\t\tvalue.call( this, i, getClass( this ), stateVal ),\n\t\t\t\t\tstateVal\n\t\t\t\t);\n\t\t\t} );\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tvar className, i, self, classNames;\n\n\t\t\tif ( isValidValue ) {\n\n\t\t\t\t// Toggle individual class names\n\t\t\t\ti = 0;\n\t\t\t\tself = jQuery( this );\n\t\t\t\tclassNames = classesToArray( value );\n\n\t\t\t\twhile ( ( className = classNames[ i++ ] ) ) {\n\n\t\t\t\t\t// Check each className given, space separated list\n\t\t\t\t\tif ( self.hasClass( className ) ) {\n\t\t\t\t\t\tself.removeClass( className );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tself.addClass( className );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Toggle whole class name\n\t\t\t} else if ( value === undefined || type === \"boolean\" ) {\n\t\t\t\tclassName = getClass( this );\n\t\t\t\tif ( className ) {\n\n\t\t\t\t\t// Store className if set\n\t\t\t\t\tdataPriv.set( this, \"__className__\", className );\n\t\t\t\t}\n\n\t\t\t\t// If the element has a class name or if we're passed `false`,\n\t\t\t\t// then remove the whole classname (if there was one, the above saved it).\n\t\t\t\t// Otherwise bring back whatever was previously saved (if anything),\n\t\t\t\t// falling back to the empty string if nothing was stored.\n\t\t\t\tif ( this.setAttribute ) {\n\t\t\t\t\tthis.setAttribute( \"class\",\n\t\t\t\t\t\tclassName || value === false ?\n\t\t\t\t\t\t\"\" :\n\t\t\t\t\t\tdataPriv.get( this, \"__className__\" ) || \"\"\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className, elem,\n\t\t\ti = 0;\n\n\t\tclassName = \" \" + selector + \" \";\n\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\tif ( elem.nodeType === 1 &&\n\t\t\t\t( \" \" + stripAndCollapse( getClass( elem ) ) + \" \" ).indexOf( className ) > -1 ) {\n\t\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n} );\n\n\n\n\nvar rreturn = /\\r/g;\n\njQuery.fn.extend( {\n\tval: function( value ) {\n\t\tvar hooks, ret, valueIsFunction,\n\t\t\telem = this[ 0 ];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] ||\n\t\t\t\t\tjQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks &&\n\t\t\t\t\t\"get\" in hooks &&\n\t\t\t\t\t( ret = hooks.get( elem, \"value\" ) ) !== undefined\n\t\t\t\t) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\t// Handle most common string cases\n\t\t\t\tif ( typeof ret === \"string\" ) {\n\t\t\t\t\treturn ret.replace( rreturn, \"\" );\n\t\t\t\t}\n\n\t\t\t\t// Handle cases where value is null/undef or number\n\t\t\t\treturn ret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tvalueIsFunction = isFunction( value );\n\n\t\treturn this.each( function( i ) {\n\t\t\tvar val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( valueIsFunction ) {\n\t\t\t\tval = value.call( this, i, jQuery( this ).val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\n\t\t\t} else if ( Array.isArray( val ) ) {\n\t\t\t\tval = jQuery.map( val, function( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !( \"set\" in hooks ) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t} );\n\t}\n} );\n\njQuery.extend( {\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\n\t\t\t\tvar val = jQuery.find.attr( elem, \"value\" );\n\t\t\t\treturn val != null ?\n\t\t\t\t\tval :\n\n\t\t\t\t\t// Support: IE <=10 - 11 only\n\t\t\t\t\t// option.text throws exceptions (#14686, #14858)\n\t\t\t\t\t// Strip and collapse whitespace\n\t\t\t\t\t// https://html.spec.whatwg.org/#strip-and-collapse-whitespace\n\t\t\t\t\tstripAndCollapse( jQuery.text( elem ) );\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, option, i,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tone = elem.type === \"select-one\",\n\t\t\t\t\tvalues = one ? null : [],\n\t\t\t\t\tmax = one ? index + 1 : options.length;\n\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\ti = max;\n\n\t\t\t\t} else {\n\t\t\t\t\ti = one ? index : 0;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// Support: IE <=9 only\n\t\t\t\t\t// IE8-9 doesn't update selected after form reset (#2551)\n\t\t\t\t\tif ( ( option.selected || i === index ) &&\n\n\t\t\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\t\t\t!option.disabled &&\n\t\t\t\t\t\t\t( !option.parentNode.disabled ||\n\t\t\t\t\t\t\t\t!nodeName( option.parentNode, \"optgroup\" ) ) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar optionSet, option,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tvalues = jQuery.makeArray( value ),\n\t\t\t\t\ti = options.length;\n\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t/* eslint-disable no-cond-assign */\n\n\t\t\t\t\tif ( option.selected =\n\t\t\t\t\t\tjQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1\n\t\t\t\t\t) {\n\t\t\t\t\t\toptionSet = true;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* eslint-enable no-cond-assign */\n\t\t\t\t}\n\n\t\t\t\t// Force browsers to behave consistently when non-matching value is set\n\t\t\t\tif ( !optionSet ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t}\n} );\n\n// Radios and checkboxes getter/setter\njQuery.each( [ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = {\n\t\tset: function( elem, value ) {\n\t\t\tif ( Array.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );\n\t\t\t}\n\t\t}\n\t};\n\tif ( !support.checkOn ) {\n\t\tjQuery.valHooks[ this ].get = function( elem ) {\n\t\t\treturn elem.getAttribute( \"value\" ) === null ? \"on\" : elem.value;\n\t\t};\n\t}\n} );\n\n\n\n\n// Return jQuery for attributes-only inclusion\n\n\nsupport.focusin = \"onfocusin\" in window;\n\n\nvar rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\tstopPropagationCallback = function( e ) {\n\t\te.stopPropagation();\n\t};\n\njQuery.extend( jQuery.event, {\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\n\t\tvar i, cur, tmp, bubbleType, ontype, handle, special, lastElement,\n\t\t\teventPath = [ elem || document ],\n\t\t\ttype = hasOwn.call( event, \"type\" ) ? event.type : event,\n\t\t\tnamespaces = hasOwn.call( event, \"namespace\" ) ? event.namespace.split( \".\" ) : [];\n\n\t\tcur = lastElement = tmp = elem = elem || document;\n\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf( \".\" ) > -1 ) {\n\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split( \".\" );\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\t\tontype = type.indexOf( \":\" ) < 0 && \"on\" + type;\n\n\t\t// Caller can pass in a jQuery.Event object, Object, or just an event type string\n\t\tevent = event[ jQuery.expando ] ?\n\t\t\tevent :\n\t\t\tnew jQuery.Event( type, typeof event === \"object\" && event );\n\n\t\t// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)\n\t\tevent.isTrigger = onlyHandlers ? 2 : 3;\n\t\tevent.namespace = namespaces.join( \".\" );\n\t\tevent.rnamespace = event.namespace ?\n\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join( \"\\\\.(?:.*\\\\.|)\" ) + \"(\\\\.|$)\" ) :\n\t\t\tnull;\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data == null ?\n\t\t\t[ event ] :\n\t\t\tjQuery.makeArray( data, [ event ] );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\tif ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tif ( !rfocusMorph.test( bubbleType + type ) ) {\n\t\t\t\tcur = cur.parentNode;\n\t\t\t}\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push( cur );\n\t\t\t\ttmp = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( tmp === ( elem.ownerDocument || document ) ) {\n\t\t\t\teventPath.push( tmp.defaultView || tmp.parentWindow || window );\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\ti = 0;\n\t\twhile ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {\n\t\t\tlastElement = cur;\n\t\t\tevent.type = i > 1 ?\n\t\t\t\tbubbleType :\n\t\t\t\tspecial.bindType || type;\n\n\t\t\t// jQuery handler\n\t\t\thandle = (\n\t\t\t\t\tdataPriv.get( cur, \"events\" ) || Object.create( null )\n\t\t\t\t)[ event.type ] &&\n\t\t\t\tdataPriv.get( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\t// Native handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && handle.apply && acceptData( cur ) ) {\n\t\t\t\tevent.result = handle.apply( cur, data );\n\t\t\t\tif ( event.result === false ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( ( !special._default ||\n\t\t\t\tspecial._default.apply( eventPath.pop(), data ) === false ) &&\n\t\t\t\tacceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name as the event.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\tif ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\ttmp = elem[ ontype ];\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\n\t\t\t\t\tif ( event.isPropagationStopped() ) {\n\t\t\t\t\t\tlastElement.addEventListener( type, stopPropagationCallback );\n\t\t\t\t\t}\n\n\t\t\t\t\telem[ type ]();\n\n\t\t\t\t\tif ( event.isPropagationStopped() ) {\n\t\t\t\t\t\tlastElement.removeEventListener( type, stopPropagationCallback );\n\t\t\t\t\t}\n\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = tmp;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\t// Piggyback on a donor event to simulate a different one\n\t// Used only for `focus(in | out)` events\n\tsimulate: function( type, elem, event ) {\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{\n\t\t\t\ttype: type,\n\t\t\t\tisSimulated: true\n\t\t\t}\n\t\t);\n\n\t\tjQuery.event.trigger( e, null, elem );\n\t}\n\n} );\n\njQuery.fn.extend( {\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t} );\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tvar elem = this[ 0 ];\n\t\tif ( elem ) {\n\t\t\treturn jQuery.event.trigger( type, data, elem, true );\n\t\t}\n\t}\n} );\n\n\n// Support: Firefox <=44\n// Firefox doesn't have focus(in | out) events\n// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787\n//\n// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1\n// focus(in | out) events fire after focus & blur events,\n// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order\n// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857\nif ( !support.focusin ) {\n\tjQuery.each( { focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler on the document while someone wants focusin/focusout\n\t\tvar handler = function( event ) {\n\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );\n\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\n\t\t\t\t// Handle: regular nodes (via `this.ownerDocument`), window\n\t\t\t\t// (via `this.document`) & document (via `this`).\n\t\t\t\tvar doc = this.ownerDocument || this.document || this,\n\t\t\t\t\tattaches = dataPriv.access( doc, fix );\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t\tdataPriv.access( doc, fix, ( attaches || 0 ) + 1 );\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tvar doc = this.ownerDocument || this.document || this,\n\t\t\t\t\tattaches = dataPriv.access( doc, fix ) - 1;\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.removeEventListener( orig, handler, true );\n\t\t\t\t\tdataPriv.remove( doc, fix );\n\n\t\t\t\t} else {\n\t\t\t\t\tdataPriv.access( doc, fix, attaches );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t} );\n}\n\n\n// Cross-browser xml parsing\njQuery.parseXML = function( data ) {\n\tvar xml;\n\tif ( !data || typeof data !== \"string\" ) {\n\t\treturn null;\n\t}\n\n\t// Support: IE 9 - 11 only\n\t// IE throws on parseFromString with invalid input.\n\ttry {\n\t\txml = ( new window.DOMParser() ).parseFromString( data, \"text/xml\" );\n\t} catch ( e ) {\n\t\txml = undefined;\n\t}\n\n\tif ( !xml || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\tjQuery.error( \"Invalid XML: \" + data );\n\t}\n\treturn xml;\n};\n\n\nvar\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,\n\trsubmittable = /^(?:input|select|textarea|keygen)/i;\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tvar name;\n\n\tif ( Array.isArray( obj ) ) {\n\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\n\t\t\t\t// Item is non-scalar (array or object), encode its numeric index.\n\t\t\t\tbuildParams(\n\t\t\t\t\tprefix + \"[\" + ( typeof v === \"object\" && v != null ? i : \"\" ) + \"]\",\n\t\t\t\t\tv,\n\t\t\t\t\ttraditional,\n\t\t\t\t\tadd\n\t\t\t\t);\n\t\t\t}\n\t\t} );\n\n\t} else if ( !traditional && toType( obj ) === \"object\" ) {\n\n\t\t// Serialize object item.\n\t\tfor ( name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// Serialize an array of form elements or a set of\n// key/values into a query string\njQuery.param = function( a, traditional ) {\n\tvar prefix,\n\t\ts = [],\n\t\tadd = function( key, valueOrFunction ) {\n\n\t\t\t// If value is a function, invoke it and use its return value\n\t\t\tvar value = isFunction( valueOrFunction ) ?\n\t\t\t\tvalueOrFunction() :\n\t\t\t\tvalueOrFunction;\n\n\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" +\n\t\t\t\tencodeURIComponent( value == null ? \"\" : value );\n\t\t};\n\n\tif ( a == null ) {\n\t\treturn \"\";\n\t}\n\n\t// If an array was passed in, assume that it is an array of form elements.\n\tif ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\n\t\t// Serialize the form elements\n\t\tjQuery.each( a, function() {\n\t\t\tadd( this.name, this.value );\n\t\t} );\n\n\t} else {\n\n\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t// did it), otherwise encode params recursively.\n\t\tfor ( prefix in a ) {\n\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t}\n\t}\n\n\t// Return the resulting serialization\n\treturn s.join( \"&\" );\n};\n\njQuery.fn.extend( {\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\tserializeArray: function() {\n\t\treturn this.map( function() {\n\n\t\t\t// Can add propHook for \"elements\" to filter or add form elements\n\t\t\tvar elements = jQuery.prop( this, \"elements\" );\n\t\t\treturn elements ? jQuery.makeArray( elements ) : this;\n\t\t} )\n\t\t.filter( function() {\n\t\t\tvar type = this.type;\n\n\t\t\t// Use .is( \":disabled\" ) so that fieldset[disabled] works\n\t\t\treturn this.name && !jQuery( this ).is( \":disabled\" ) &&\n\t\t\t\trsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&\n\t\t\t\t( this.checked || !rcheckableType.test( type ) );\n\t\t} )\n\t\t.map( function( _i, elem ) {\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\tif ( val == null ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tif ( Array.isArray( val ) ) {\n\t\t\t\treturn jQuery.map( val, function( val ) {\n\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t} ).get();\n\t}\n} );\n\n\njQuery.fn.extend( {\n\twrapAll: function( html ) {\n\t\tvar wrap;\n\n\t\tif ( this[ 0 ] ) {\n\t\t\tif ( isFunction( html ) ) {\n\t\t\t\thtml = html.call( this[ 0 ] );\n\t\t\t}\n\n\t\t\t// The elements to wrap the target around\n\t\t\twrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );\n\n\t\t\tif ( this[ 0 ].parentNode ) {\n\t\t\t\twrap.insertBefore( this[ 0 ] );\n\t\t\t}\n\n\t\t\twrap.map( function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstElementChild ) {\n\t\t\t\t\telem = elem.firstElementChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t} ).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( isFunction( html ) ) {\n\t\t\treturn this.each( function( i ) {\n\t\t\t\tjQuery( this ).wrapInner( html.call( this, i ) );\n\t\t\t} );\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t} );\n\t},\n\n\twrap: function( html ) {\n\t\tvar htmlIsFunction = isFunction( html );\n\n\t\treturn this.each( function( i ) {\n\t\t\tjQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html );\n\t\t} );\n\t},\n\n\tunwrap: function( selector ) {\n\t\tthis.parent( selector ).not( \"body\" ).each( function() {\n\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t} );\n\t\treturn this;\n\t}\n} );\n\n\njQuery.expr.pseudos.hidden = function( elem ) {\n\treturn !jQuery.expr.pseudos.visible( elem );\n};\njQuery.expr.pseudos.visible = function( elem ) {\n\treturn !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );\n};\n\n\n\n\n// Support: Safari 8 only\n// In Safari 8 documents created via document.implementation.createHTMLDocument\n// collapse sibling forms: the second one becomes a child of the first one.\n// Because of that, this security measure has to be disabled in Safari 8.\n// https://bugs.webkit.org/show_bug.cgi?id=137337\nsupport.createHTMLDocument = ( function() {\n\tvar body = document.implementation.createHTMLDocument( \"\" ).body;\n\tbody.innerHTML = \"<form></form><form></form>\";\n\treturn body.childNodes.length === 2;\n} )();\n\n\n// Argument \"data\" should be string of html\n// context (optional): If specified, the fragment will be created in this context,\n// defaults to document\n// keepScripts (optional): If true, will include scripts passed in the html string\njQuery.parseHTML = function( data, context, keepScripts ) {\n\tif ( typeof data !== \"string\" ) {\n\t\treturn [];\n\t}\n\tif ( typeof context === \"boolean\" ) {\n\t\tkeepScripts = context;\n\t\tcontext = false;\n\t}\n\n\tvar base, parsed, scripts;\n\n\tif ( !context ) {\n\n\t\t// Stop scripts or inline event handlers from being executed immediately\n\t\t// by using document.implementation\n\t\tif ( support.createHTMLDocument ) {\n\t\t\tcontext = document.implementation.createHTMLDocument( \"\" );\n\n\t\t\t// Set the base href for the created document\n\t\t\t// so any parsed elements with URLs\n\t\t\t// are based on the document's URL (gh-2965)\n\t\t\tbase = context.createElement( \"base\" );\n\t\t\tbase.href = document.location.href;\n\t\t\tcontext.head.appendChild( base );\n\t\t} else {\n\t\t\tcontext = document;\n\t\t}\n\t}\n\n\tparsed = rsingleTag.exec( data );\n\tscripts = !keepScripts && [];\n\n\t// Single tag\n\tif ( parsed ) {\n\t\treturn [ context.createElement( parsed[ 1 ] ) ];\n\t}\n\n\tparsed = buildFragment( [ data ], context, scripts );\n\n\tif ( scripts && scripts.length ) {\n\t\tjQuery( scripts ).remove();\n\t}\n\n\treturn jQuery.merge( [], parsed.childNodes );\n};\n\n\njQuery.offset = {\n\tsetOffset: function( elem, options, i ) {\n\t\tvar curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,\n\t\t\tposition = jQuery.css( elem, \"position\" ),\n\t\t\tcurElem = jQuery( elem ),\n\t\t\tprops = {};\n\n\t\t// Set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tcurOffset = curElem.offset();\n\t\tcurCSSTop = jQuery.css( elem, \"top\" );\n\t\tcurCSSLeft = jQuery.css( elem, \"left\" );\n\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) &&\n\t\t\t( curCSSTop + curCSSLeft ).indexOf( \"auto\" ) > -1;\n\n\t\t// Need to be able to calculate position if either\n\t\t// top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( isFunction( options ) ) {\n\n\t\t\t// Use jQuery.extend here to allow modification of coordinates argument (gh-1848)\n\t\t\toptions = options.call( elem, i, jQuery.extend( {}, curOffset ) );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\n\t\t} else {\n\t\t\tif ( typeof props.top === \"number\" ) {\n\t\t\t\tprops.top += \"px\";\n\t\t\t}\n\t\t\tif ( typeof props.left === \"number\" ) {\n\t\t\t\tprops.left += \"px\";\n\t\t\t}\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\njQuery.fn.extend( {\n\n\t// offset() relates an element's border box to the document origin\n\toffset: function( options ) {\n\n\t\t// Preserve chaining for setter\n\t\tif ( arguments.length ) {\n\t\t\treturn options === undefined ?\n\t\t\t\tthis :\n\t\t\t\tthis.each( function( i ) {\n\t\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t\t} );\n\t\t}\n\n\t\tvar rect, win,\n\t\t\telem = this[ 0 ];\n\n\t\tif ( !elem ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Return zeros for disconnected and hidden (display: none) elements (gh-2310)\n\t\t// Support: IE <=11 only\n\t\t// Running getBoundingClientRect on a\n\t\t// disconnected node in IE throws an error\n\t\tif ( !elem.getClientRects().length ) {\n\t\t\treturn { top: 0, left: 0 };\n\t\t}\n\n\t\t// Get document-relative position by adding viewport scroll to viewport-relative gBCR\n\t\trect = elem.getBoundingClientRect();\n\t\twin = elem.ownerDocument.defaultView;\n\t\treturn {\n\t\t\ttop: rect.top + win.pageYOffset,\n\t\t\tleft: rect.left + win.pageXOffset\n\t\t};\n\t},\n\n\t// position() relates an element's margin box to its offset parent's padding box\n\t// This corresponds to the behavior of CSS absolute positioning\n\tposition: function() {\n\t\tif ( !this[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar offsetParent, offset, doc,\n\t\t\telem = this[ 0 ],\n\t\t\tparentOffset = { top: 0, left: 0 };\n\n\t\t// position:fixed elements are offset from the viewport, which itself always has zero offset\n\t\tif ( jQuery.css( elem, \"position\" ) === \"fixed\" ) {\n\n\t\t\t// Assume position:fixed implies availability of getBoundingClientRect\n\t\t\toffset = elem.getBoundingClientRect();\n\n\t\t} else {\n\t\t\toffset = this.offset();\n\n\t\t\t// Account for the *real* offset parent, which can be the document or its root element\n\t\t\t// when a statically positioned element is identified\n\t\t\tdoc = elem.ownerDocument;\n\t\t\toffsetParent = elem.offsetParent || doc.documentElement;\n\t\t\twhile ( offsetParent &&\n\t\t\t\t( offsetParent === doc.body || offsetParent === doc.documentElement ) &&\n\t\t\t\tjQuery.css( offsetParent, \"position\" ) === \"static\" ) {\n\n\t\t\t\toffsetParent = offsetParent.parentNode;\n\t\t\t}\n\t\t\tif ( offsetParent && offsetParent !== elem && offsetParent.nodeType === 1 ) {\n\n\t\t\t\t// Incorporate borders into its offset, since they are outside its content origin\n\t\t\t\tparentOffset = jQuery( offsetParent ).offset();\n\t\t\t\tparentOffset.top += jQuery.css( offsetParent, \"borderTopWidth\", true );\n\t\t\t\tparentOffset.left += jQuery.css( offsetParent, \"borderLeftWidth\", true );\n\t\t\t}\n\t\t}\n\n\t\t// Subtract parent offsets and element margins\n\t\treturn {\n\t\t\ttop: offset.top - parentOffset.top - jQuery.css( elem, \"marginTop\", true ),\n\t\t\tleft: offset.left - parentOffset.left - jQuery.css( elem, \"marginLeft\", true )\n\t\t};\n\t},\n\n\t// This method will return documentElement in the following cases:\n\t// 1) For the element inside the iframe without offsetParent, this method will return\n\t//    documentElement of the parent window\n\t// 2) For the hidden or detached element\n\t// 3) For body or html element, i.e. in case of the html node - it will return itself\n\t//\n\t// but those exceptions were never presented as a real life use-cases\n\t// and might be considered as more preferable results.\n\t//\n\t// This logic, however, is not guaranteed and can change at any point in the future\n\toffsetParent: function() {\n\t\treturn this.map( function() {\n\t\t\tvar offsetParent = this.offsetParent;\n\n\t\t\twhile ( offsetParent && jQuery.css( offsetParent, \"position\" ) === \"static\" ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\n\t\t\treturn offsetParent || documentElement;\n\t\t} );\n\t}\n} );\n\n// Create scrollLeft and scrollTop methods\njQuery.each( { scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\" }, function( method, prop ) {\n\tvar top = \"pageYOffset\" === prop;\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn access( this, function( elem, method, val ) {\n\n\t\t\t// Coalesce documents and windows\n\t\t\tvar win;\n\t\t\tif ( isWindow( elem ) ) {\n\t\t\t\twin = elem;\n\t\t\t} else if ( elem.nodeType === 9 ) {\n\t\t\t\twin = elem.defaultView;\n\t\t\t}\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? win[ prop ] : elem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : win.pageXOffset,\n\t\t\t\t\ttop ? val : win.pageYOffset\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length );\n\t};\n} );\n\n// Support: Safari <=7 - 9.1, Chrome <=37 - 49\n// Add the top/left cssHooks using jQuery.fn.position\n// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084\n// Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347\n// getComputedStyle returns percent when specified for top/left/bottom/right;\n// rather than make the css module depend on the offset module, just check for it here\njQuery.each( [ \"top\", \"left\" ], function( _i, prop ) {\n\tjQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,\n\t\tfunction( elem, computed ) {\n\t\t\tif ( computed ) {\n\t\t\t\tcomputed = curCSS( elem, prop );\n\n\t\t\t\t// If curCSS returns percentage, fallback to offset\n\t\t\t\treturn rnumnonpx.test( computed ) ?\n\t\t\t\t\tjQuery( elem ).position()[ prop ] + \"px\" :\n\t\t\t\t\tcomputed;\n\t\t\t}\n\t\t}\n\t);\n} );\n\n\n// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tjQuery.each( { padding: \"inner\" + name, content: type, \"\": \"outer\" + name },\n\t\tfunction( defaultExtra, funcName ) {\n\n\t\t// Margin is only for outerHeight, outerWidth\n\t\tjQuery.fn[ funcName ] = function( margin, value ) {\n\t\t\tvar chainable = arguments.length && ( defaultExtra || typeof margin !== \"boolean\" ),\n\t\t\t\textra = defaultExtra || ( margin === true || value === true ? \"margin\" : \"border\" );\n\n\t\t\treturn access( this, function( elem, type, value ) {\n\t\t\t\tvar doc;\n\n\t\t\t\tif ( isWindow( elem ) ) {\n\n\t\t\t\t\t// $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)\n\t\t\t\t\treturn funcName.indexOf( \"outer\" ) === 0 ?\n\t\t\t\t\t\telem[ \"inner\" + name ] :\n\t\t\t\t\t\telem.document.documentElement[ \"client\" + name ];\n\t\t\t\t}\n\n\t\t\t\t// Get document width or height\n\t\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],\n\t\t\t\t\t// whichever is greatest\n\t\t\t\t\treturn Math.max(\n\t\t\t\t\t\telem.body[ \"scroll\" + name ], doc[ \"scroll\" + name ],\n\t\t\t\t\t\telem.body[ \"offset\" + name ], doc[ \"offset\" + name ],\n\t\t\t\t\t\tdoc[ \"client\" + name ]\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn value === undefined ?\n\n\t\t\t\t\t// Get width or height on the element, requesting but not forcing parseFloat\n\t\t\t\t\tjQuery.css( elem, type, extra ) :\n\n\t\t\t\t\t// Set width or height on the element\n\t\t\t\t\tjQuery.style( elem, type, value, extra );\n\t\t\t}, type, chainable ? margin : undefined, chainable );\n\t\t};\n\t} );\n} );\n\n\njQuery.fn.extend( {\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length === 1 ?\n\t\t\tthis.off( selector, \"**\" ) :\n\t\t\tthis.off( types, selector || \"**\", fn );\n\t},\n\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n} );\n\njQuery.each( ( \"blur focus focusin focusout resize scroll click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup contextmenu\" ).split( \" \" ),\n\tfunction( _i, name ) {\n\n\t\t// Handle event binding\n\t\tjQuery.fn[ name ] = function( data, fn ) {\n\t\t\treturn arguments.length > 0 ?\n\t\t\t\tthis.on( name, null, data, fn ) :\n\t\t\t\tthis.trigger( name );\n\t\t};\n\t} );\n\n\n\n\n// Support: Android <=4.0 only\n// Make sure we trim BOM and NBSP\nvar rtrim = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g;\n\n// Bind a function to a context, optionally partially applying any\n// arguments.\n// jQuery.proxy is deprecated to promote standards (specifically Function#bind)\n// However, it is not slated for removal any time soon\njQuery.proxy = function( fn, context ) {\n\tvar tmp, args, proxy;\n\n\tif ( typeof context === \"string\" ) {\n\t\ttmp = fn[ context ];\n\t\tcontext = fn;\n\t\tfn = tmp;\n\t}\n\n\t// Quick check to determine if target is callable, in the spec\n\t// this throws a TypeError, but we will just return undefined.\n\tif ( !isFunction( fn ) ) {\n\t\treturn undefined;\n\t}\n\n\t// Simulated bind\n\targs = slice.call( arguments, 2 );\n\tproxy = function() {\n\t\treturn fn.apply( context || this, args.concat( slice.call( arguments ) ) );\n\t};\n\n\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\tproxy.guid = fn.guid = fn.guid || jQuery.guid++;\n\n\treturn proxy;\n};\n\njQuery.holdReady = function( hold ) {\n\tif ( hold ) {\n\t\tjQuery.readyWait++;\n\t} else {\n\t\tjQuery.ready( true );\n\t}\n};\njQuery.isArray = Array.isArray;\njQuery.parseJSON = JSON.parse;\njQuery.nodeName = nodeName;\njQuery.isFunction = isFunction;\njQuery.isWindow = isWindow;\njQuery.camelCase = camelCase;\njQuery.type = toType;\n\njQuery.now = Date.now;\n\njQuery.isNumeric = function( obj ) {\n\n\t// As of jQuery 3.0, isNumeric is limited to\n\t// strings and numbers (primitives or objects)\n\t// that can be coerced to finite numbers (gh-2662)\n\tvar type = jQuery.type( obj );\n\treturn ( type === \"number\" || type === \"string\" ) &&\n\n\t\t// parseFloat NaNs numeric-cast false positives (\"\")\n\t\t// ...but misinterprets leading-number strings, particularly hex literals (\"0x...\")\n\t\t// subtraction forces infinities to NaN\n\t\t!isNaN( obj - parseFloat( obj ) );\n};\n\njQuery.trim = function( text ) {\n\treturn text == null ?\n\t\t\"\" :\n\t\t( text + \"\" ).replace( rtrim, \"\" );\n};\n\n\n\n// Register as a named AMD module, since jQuery can be concatenated with other\n// files that may use define, but not via a proper concatenation script that\n// understands anonymous AMD modules. A named AMD is safest and most robust\n// way to register. Lowercase jquery is used because AMD module names are\n// derived from file names, and jQuery is normally delivered in a lowercase\n// file name. Do this after creating the global so that if an AMD module wants\n// to call noConflict to hide this version of jQuery, it will work.\n\n// Note that for maximum portability, libraries that are not jQuery should\n// declare themselves as anonymous modules, and avoid setting a global if an\n// AMD loader is present. jQuery is a special case. For more information, see\n// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon\n\nif ( typeof define === \"function\" && define.amd ) {\n\tdefine( \"jquery\", [], function() {\n\t\treturn jQuery;\n\t} );\n}\n\n\n\n\nvar\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$;\n\njQuery.noConflict = function( deep ) {\n\tif ( window.$ === jQuery ) {\n\t\twindow.$ = _$;\n\t}\n\n\tif ( deep && window.jQuery === jQuery ) {\n\t\twindow.jQuery = _jQuery;\n\t}\n\n\treturn jQuery;\n};\n\n// Expose jQuery and $ identifiers, even in AMD\n// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)\n// and CommonJS for browser emulators (#13566)\nif ( typeof noGlobal === \"undefined\" ) {\n\twindow.jQuery = window.$ = jQuery;\n}\n\n\n\n\nreturn jQuery;\n} );\n"
  },
  {
    "path": "src/PythonInference/PythonInference.pyproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\" DefaultTargets=\"Build\">\n  <PropertyGroup>\n    <Configuration Condition=\" '$(Configuration)' == '' \">Debug</Configuration>\n    <SchemaVersion>2.0</SchemaVersion>\n    <ProjectGuid>{baa14585-1716-40fb-a04e-f986f1038638}</ProjectGuid>\n    <ProjectHome />\n    <StartupFile>main.py</StartupFile>\n    <SearchPath />\n    <WorkingDirectory>.</WorkingDirectory>\n    <OutputPath>.</OutputPath>\n    <ProjectTypeGuids>{888888a0-9f3d-457c-b088-3a5042f75d52}</ProjectTypeGuids>\n    <LaunchProvider>Standard Python launcher</LaunchProvider>\n    <InterpreterId />\n    <Name>PythonInference</Name>\n    <SuppressEnvironmentCreationPrompt>True</SuppressEnvironmentCreationPrompt>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)' == 'Debug'\" />\n  <PropertyGroup Condition=\"'$(Configuration)' == 'Release'\" />\n  <PropertyGroup>\n    <VisualStudioVersion Condition=\" '$(VisualStudioVersion)' == '' \">10.0</VisualStudioVersion>\n  </PropertyGroup>\n  <ItemGroup>\n    <Compile Include=\"main.py\" />\n    <Compile Include=\"routers\\classifier.py\" />\n    <Compile Include=\"routers\\embedder.py\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Folder Include=\"routers\\\" />\n  </ItemGroup>\n  <Import Project=\"$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)\\Python Tools\\Microsoft.PythonTools.targets\" />\n</Project>"
  },
  {
    "path": "src/PythonInference/main.py",
    "content": "from fastapi import FastAPI\nfrom routers import classifier, embedder\n\napp = FastAPI()\napp.include_router(classifier.router)\napp.include_router(embedder.router)\n"
  },
  {
    "path": "src/PythonInference/requirements.txt",
    "content": "annotated-types==0.7.0\nanyio==4.4.0\ncertifi==2024.2.2\ncharset-normalizer==3.3.2\nclick==8.1.7\ncolorama==0.4.6\ndnspython==2.6.1\nemail_validator==2.1.1\nexceptiongroup==1.2.1\nfastapi==0.111.0\nfastapi-cli==0.0.4\nfilelock==3.14.0\nfsspec==2024.5.0\nh11==0.14.0\nhttpcore==1.0.5\nhttptools==0.6.1\nhttpx==0.27.0\nhuggingface-hub==0.23.2\nidna==3.7\nintel-openmp==2021.4.0\nJinja2==3.1.4\njoblib==1.4.2\nmarkdown-it-py==3.0.0\nMarkupSafe==2.1.5\nmdurl==0.1.2\nmkl==2021.4.0\nmpmath==1.3.0\nnetworkx==3.3\nnumpy==1.26.4\norjson==3.10.3\npackaging==24.0\npillow==10.3.0\npydantic==2.7.2\npydantic_core==2.18.3\nPygments==2.18.0\npython-dotenv==1.0.1\npython-multipart==0.0.9\nPyYAML==6.0.1\nregex==2024.5.15\nrequests==2.32.3\nrich==13.7.1\nsafetensors==0.4.3\nscikit-learn==1.5.0\nscipy==1.13.1\nsentence-transformers==3.0.0\nshellingham==1.5.4\nsniffio==1.3.1\nstarlette==0.37.2\nsympy==1.12.1\ntbb==2021.12.0\nthreadpoolctl==3.5.0\ntokenizers==0.19.1\n--extra-index-url https://download.pytorch.org/whl/cu118\ntorch==2.3.0+cu118\ntorchaudio==2.3.0+cu118\ntorchvision==0.18.0+cu118\ntqdm==4.66.4\ntransformers==4.41.1\ntyper==0.12.3\ntyping_extensions==4.12.0\nujson==5.10.0\nurllib3==2.2.1\nuvicorn==0.30.0\nwatchfiles==0.22.0\nwebsockets==12.0\n"
  },
  {
    "path": "src/PythonInference/routers/classifier.py",
    "content": "from fastapi import APIRouter\nfrom pydantic import BaseModel\nfrom transformers import pipeline\n\nrouter = APIRouter()\nclassifier = pipeline('zero-shot-classification', model='cross-encoder/nli-MiniLM2-L6-H768', device='cuda')\nclassifier('warm up', ['a', 'b', 'c'])\n\nclass ClassifyRequest(BaseModel):\n    text: str\n    candidate_labels: list[str]\n\n@router.post(\"/classify\")\ndef classify_text(item: ClassifyRequest) -> str:\n    result = classifier(item.text, item.candidate_labels)\n    return result['labels'][0]\n"
  },
  {
    "path": "src/PythonInference/routers/embedder.py",
    "content": "from fastapi import APIRouter\nfrom pydantic import BaseModel\nfrom sentence_transformers import SentenceTransformer\n\nrouter = APIRouter()\nmodel = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2')\n\nclass EmbedRequest(BaseModel):\n    sentences: list[str]\n\n@router.post(\"/embed\")\ndef embed_sentences(req: EmbedRequest) -> list[list[float]]:\n    embeddings = model.encode(req.sentences)\n    return embeddings.tolist()\n"
  },
  {
    "path": "src/ServiceDefaults/Clients/Backend/CustomerBackendClient.cs",
    "content": "﻿using System.Net.Http.Json;\nusing System.Web;\n\nnamespace eShopSupport.ServiceDefaults.Clients.Backend;\n\npublic class CustomerBackendClient(HttpClient http)\n{\n    public Task CreateTicketAsync(CreateTicketRequest request)\n        => http.PostAsJsonAsync(\"/customer/tickets/create\", request);\n\n    public Task<ListTicketsResult> ListTicketsAsync()\n        => http.GetFromJsonAsync<ListTicketsResult>(\"/customer/tickets\")!;\n\n    public Task<TicketDetailsResult> GetTicketDetailsAsync(int ticketId)\n        => http.GetFromJsonAsync<TicketDetailsResult>($\"/customer/tickets/{ticketId}\")!;\n\n    public Task SendTicketMessageAsync(int ticketId, SendTicketMessageRequest request)\n        => http.PostAsJsonAsync($\"/api/customer/ticket/{ticketId}/message\", request);\n\n    public Task CloseTicketAsync(int ticketId)\n        => http.PutAsync($\"/api/customer/ticket/{ticketId}/close\", null);\n\n    public Task<FindProductsResult[]> FindProductsAsync(string searchText)\n        => http.GetFromJsonAsync<FindProductsResult[]>($\"/api/customer/products?searchText={HttpUtility.UrlEncode(searchText)}\")!;\n}\n"
  },
  {
    "path": "src/ServiceDefaults/Clients/Backend/DevToolBackendClient.cs",
    "content": "﻿using IdentityModel.Client;\n\nnamespace eShopSupport.ServiceDefaults.Clients.Backend;\n\npublic static class DevToolBackendClient\n{\n    /// <summary>\n    /// Returns a <see cref=\"StaffBackendClient\"/> that is pre-authenticated for use in development and testing tools.\n    /// Do not use this in application code.\n    /// </summary>\n    public static async Task<StaffBackendClient> GetDevToolStaffBackendClientAsync(HttpClient identityServerHttpClient, HttpClient backendHttpClient)\n    {\n        var identityServerDisco = await identityServerHttpClient.GetDiscoveryDocumentAsync();\n        if (identityServerDisco.IsError)\n        {\n            throw new InvalidOperationException(identityServerDisco.Error);\n        }\n\n        var tokenResponse = await identityServerHttpClient.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest\n        {\n            Address = identityServerDisco.TokenEndpoint,\n            ClientId = \"dev-and-test-tools\",\n            ClientSecret = \"dev-and-test-tools-secret\",\n            Scope = \"staff-api\"\n        });\n\n        backendHttpClient.SetBearerToken(tokenResponse.AccessToken!);\n        return new StaffBackendClient(backendHttpClient);\n    }\n}\n"
  },
  {
    "path": "src/ServiceDefaults/Clients/Backend/StaffBackendClient.cs",
    "content": "﻿using System.Net.Http.Json;\nusing System.Runtime.CompilerServices;\nusing System.Text.Json;\nusing System.Web;\n\nnamespace eShopSupport.ServiceDefaults.Clients.Backend;\n\npublic class StaffBackendClient(HttpClient http)\n{\n    public async Task<ListTicketsResult> ListTicketsAsync(ListTicketsRequest request)\n    {\n        var result = await http.PostAsJsonAsync(\"/tickets\", request);\n        return (await result.Content.ReadFromJsonAsync<ListTicketsResult>())!;\n    }\n\n    public Task<TicketDetailsResult> GetTicketDetailsAsync(int ticketId)\n        => http.GetFromJsonAsync<TicketDetailsResult>($\"/tickets/{ticketId}\")!;\n\n    public async IAsyncEnumerable<AssistantChatReplyItem> AssistantChatAsync(AssistantChatRequest request, [EnumeratorCancellation] CancellationToken cancellationToken)\n    {\n        var httpRequest = new HttpRequestMessage(HttpMethod.Post, \"/api/assistant/chat\")\n        {\n            Content = JsonContent.Create(request),\n        };\n        var response = await http.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead, cancellationToken);\n        var stream = await response.Content.ReadAsStreamAsync(cancellationToken);\n        await foreach (var item in JsonSerializer.DeserializeAsyncEnumerable<AssistantChatReplyItem>(stream, cancellationToken: cancellationToken))\n        {\n            if (item is not null)\n            {\n                yield return item;\n            }\n        }\n    }\n\n    public async Task<Stream?> ReadManualAsync(string file, CancellationToken cancellationToken)\n    {\n        var request = new HttpRequestMessage(HttpMethod.Get, $\"/manual?file={HttpUtility.UrlEncode(file)}\");\n        var response = await http.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken);\n        return response.IsSuccessStatusCode ? await response.Content.ReadAsStreamAsync(cancellationToken) : null;\n    }\n\n    public async Task SendTicketMessageAsync(int ticketId, SendTicketMessageRequest message)\n    {\n        await http.PostAsJsonAsync($\"/api/ticket/{ticketId}/message\", message);\n    }\n\n    public async Task UpdateTicketDetailsAsync(int ticketId, int? productId, TicketType ticketType, TicketStatus ticketStatus)\n    {\n        await http.PutAsJsonAsync($\"/api/ticket/{ticketId}\", new UpdateTicketDetailsRequest(productId, ticketType, ticketStatus));\n    }\n\n    public Task<FindCategoriesResult[]> FindCategoriesAsync(string searchText)\n    {\n        return http.GetFromJsonAsync<FindCategoriesResult[]>($\"/api/categories?searchText={HttpUtility.UrlEncode(searchText)}\")!;\n    }\n\n    public Task<FindCategoriesResult[]> FindCategoriesAsync(IEnumerable<int> categoryIds)\n    {\n        return http.GetFromJsonAsync<FindCategoriesResult[]>($\"/api/categories?ids={string.Join(\",\", categoryIds)}\")!;\n    }\n\n    public Task<FindProductsResult[]> FindProductsAsync(string searchText)\n    {\n        return http.GetFromJsonAsync<FindProductsResult[]>($\"/api/products?searchText={HttpUtility.UrlEncode(searchText)}\")!;\n    }\n}\n\npublic record ListTicketsRequest(TicketStatus? FilterByStatus, List<int>? FilterByCategoryIds, int? FilterByCustomerId, int StartIndex, int MaxResults, string? SortBy, bool? SortAscending);\n\npublic record ListTicketsResult(ICollection<ListTicketsResultItem> Items, int TotalCount, int TotalOpenCount, int TotalClosedCount);\n\npublic record ListTicketsResultItem(\n    int TicketId, TicketType TicketType, TicketStatus TicketStatus, DateTime CreatedAt, string CustomerFullName, string? ProductName, string? ShortSummary, int? CustomerSatisfaction, int NumMessages);\n\npublic record TicketDetailsResult(\n    int TicketId, DateTime CreatedAt, int CustomerId, string CustomerFullName, string? ShortSummary, string? LongSummary,\n    int? ProductId, string? ProductBrand, string? ProductModel,\n    TicketType TicketType, TicketStatus TicketStatus,\n    int? CustomerSatisfaction, ICollection<TicketDetailsResultMessage> Messages);\n\npublic record TicketDetailsResultMessage(int MessageId, DateTime CreatedAt, bool IsCustomerMessage, string MessageText);\n\npublic record UpdateTicketDetailsRequest(int? ProductId, TicketType TicketType, TicketStatus TicketStatus);\n\npublic record AssistantChatRequest(\n    int? ProductId,\n    string? CustomerName,\n    string? TicketSummary,\n    string? TicketLastCustomerMessage,\n    IReadOnlyList<AssistantChatRequestMessage> Messages);\n\npublic class AssistantChatRequestMessage\n{\n    public bool IsAssistant { get; set; }\n    public required string Text { get; set; }\n}\n\npublic record AssistantChatReplyItem(AssistantChatReplyItemType Type, string Text, int? SearchResultId = null, int? SearchResultProductId = null, int? SearchResultPageNumber = null);\n\npublic enum AssistantChatReplyItemType { AnswerChunk, Search, SearchResult, IsAddressedToCustomer };\n\npublic record SendTicketMessageRequest(string Text);\n\npublic record FindCategoriesResult(int CategoryId)\n{\n    public required string Name { get; set; }\n}\n\npublic record FindProductsResult(int ProductId, string Brand, string Model);\n\npublic enum TicketStatus\n{\n    Open,\n    Closed,\n}\n\npublic enum TicketType\n{\n    Question,\n    Idea,\n    Complaint,\n    Returns,\n}\n\npublic record CreateTicketRequest(\n    string? ProductName,\n    string Message);\n"
  },
  {
    "path": "src/ServiceDefaults/Clients/ChatCompletion/ChatCompletionServiceExtensions.cs",
    "content": "﻿using Microsoft.Extensions.AI;\n\nnamespace Microsoft.Extensions.Hosting;\n\npublic static class ChatCompletionServiceExtensions\n{\n    public static void AddChatCompletionService(this IHostApplicationBuilder builder, string serviceName)\n    {\n        ChatClientBuilder chatClientBuilder = (builder.Configuration[$\"{serviceName}:Type\"] == \"ollama\") ?\n            builder.AddOllamaChatClient(serviceName) :\n            builder.AddOpenAIChatClient(serviceName);\n\n        chatClientBuilder\n            .UseFunctionInvocation()\n            .UseCachingForTest()\n            .UseOpenTelemetry(configure: c => c.EnableSensitiveData = true);\n    }\n}\n"
  },
  {
    "path": "src/ServiceDefaults/Clients/ChatCompletion/PreventStreamingWithFunctions.cs",
    "content": "﻿using System.Runtime.CompilerServices;\nusing Microsoft.Extensions.AI;\n\nnamespace Microsoft.Extensions.Hosting;\n\n/// <summary>\n/// This is used only with Ollama, because the current version of Ollama doesn't support streaming with tool calls.\n/// To work around this Ollama limitation, if the call involves tools, we always resolve it using the non-streaming endpoint.\n/// </summary>\npublic static class PreventStreamingWithFunctionsExtensions\n{\n    public static ChatClientBuilder UsePreventStreamingWithFunctions(this ChatClientBuilder builder)\n    {\n        return builder.Use(inner => new PreventStreamingWithFunctions(inner));\n    }\n\n    private class PreventStreamingWithFunctions(IChatClient innerClient) : DelegatingChatClient(innerClient)\n    {\n        public override Task<ChatResponse> GetResponseAsync(IEnumerable<ChatMessage> chatMessages, ChatOptions? options = null, CancellationToken cancellationToken = default)\n        {\n            // Temporary workaround for an issue in CompleteAsync<T>. Although OpenAI models are happy to\n            // receive system messages at the end of the conversation, it causes a lot of problems for\n            // Llama 3. So replace the schema prompt role with User. We'll update CompleteAsync<T> to\n            // do this natively in the next update.\n            ChatMessage[] chatMessagesArray = [.. chatMessages];\n            if (chatMessagesArray.Length > 1\n                && chatMessagesArray[^1] is { } lastMessage\n                && lastMessage.Role == ChatRole.System\n                && lastMessage.Text?.Contains(\"$schema\") is true)\n            {\n                lastMessage.Role = ChatRole.User;\n            }\n            return base.GetResponseAsync(chatMessagesArray, options, cancellationToken);\n        }\n\n        public override IAsyncEnumerable<ChatResponseUpdate> GetStreamingResponseAsync(IEnumerable<ChatMessage> chatMessages, ChatOptions? options = null, CancellationToken cancellationToken = default)\n        {\n            return options?.Tools is null or []\n                ? base.GetStreamingResponseAsync(chatMessages, options, cancellationToken)\n                : TreatNonstreamingAsStreaming(chatMessages, options, cancellationToken);\n        }\n\n        private async IAsyncEnumerable<ChatResponseUpdate> TreatNonstreamingAsStreaming(IEnumerable<ChatMessage> chatMessages, ChatOptions options, [EnumeratorCancellation] CancellationToken cancellationToken)\n        {\n            var result = await GetResponseAsync(chatMessages, options, cancellationToken);\n            foreach (var update in result.ToChatResponseUpdates())\n            {\n                yield return update;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/ServiceDefaults/Clients/ChatCompletion/ServiceCollectionChatClientExtensions.cs",
    "content": "﻿using System.ClientModel;\nusing System.Data.Common;\nusing Azure.AI.OpenAI;\nusing Microsoft.Extensions.AI;\nusing Microsoft.Extensions.Configuration;\nusing Microsoft.Extensions.DependencyInjection;\nusing OpenAI;\n\nnamespace Microsoft.Extensions.Hosting;\n\npublic static class ServiceCollectionChatClientExtensions\n{\n    public static ChatClientBuilder AddOllamaChatClient(\n        this IHostApplicationBuilder hostBuilder,\n        string serviceName,\n        string? modelName = null)\n    {\n        if (modelName is null)\n        {\n            var configKey = $\"{serviceName}:LlmModelName\";\n            modelName = hostBuilder.Configuration[configKey];\n            if (string.IsNullOrEmpty(modelName))\n            {\n                throw new InvalidOperationException($\"No {nameof(modelName)} was specified, and none could be found from configuration at '{configKey}'\");\n            }\n        }\n\n        return hostBuilder.Services.AddOllamaChatClient(\n            modelName,\n            new Uri($\"http://{serviceName}\"));\n    }\n\n    public static ChatClientBuilder AddOllamaChatClient(\n        this IServiceCollection services,\n        string modelName,\n        Uri? uri = null)\n    {\n        uri ??= new Uri(\"http://localhost:11434\");\n\n        ChatClientBuilder chatClientBuilder = services.AddChatClient(serviceProvider => {\n            var httpClient = serviceProvider.GetService<HttpClient>() ?? new();\n            return new OllamaChatClient(uri, modelName, httpClient);\n        });\n\n        // Temporary workaround for Ollama issues\n        chatClientBuilder.UsePreventStreamingWithFunctions();\n\n        return chatClientBuilder;\n    }\n\n    public static ChatClientBuilder AddOpenAIChatClient(\n        this IHostApplicationBuilder hostBuilder,\n        string serviceName,\n        string? modelOrDeploymentName = null)\n    {\n        // TODO: We would prefer to use Aspire.AI.OpenAI here, but it doesn't yet support the OpenAI v2 client.\n        // So for now we access the connection string and set up a client manually.\n\n        var connectionString = hostBuilder.Configuration.GetConnectionString(serviceName);\n        if (string.IsNullOrWhiteSpace(connectionString))\n        {\n            throw new InvalidOperationException($\"No connection string named '{serviceName}' was found. Ensure a corresponding Aspire service was registered.\");\n        }\n\n        var connectionStringBuilder = new DbConnectionStringBuilder();\n        connectionStringBuilder.ConnectionString = connectionString;\n        var endpoint = (string?)connectionStringBuilder[\"endpoint\"];\n        var apiKey = (string)connectionStringBuilder[\"key\"] ?? throw new InvalidOperationException($\"The connection string named '{serviceName}' does not specify a value for 'Key', but this is required.\");\n\n        modelOrDeploymentName ??= (connectionStringBuilder[\"Deployment\"] ?? connectionStringBuilder[\"Model\"]) as string;\n        if (string.IsNullOrWhiteSpace(modelOrDeploymentName))\n        {\n            throw new InvalidOperationException($\"The connection string named '{serviceName}' does not specify a value for 'Deployment' or 'Model', and no value was passed for {nameof(modelOrDeploymentName)}.\");\n        }\n\n        var endpointUri = string.IsNullOrEmpty(endpoint) ? null : new Uri(endpoint);\n        return hostBuilder.Services.AddOpenAIChatClient(apiKey, modelOrDeploymentName, endpointUri);\n    }\n\n    public static ChatClientBuilder AddOpenAIChatClient(\n        this IServiceCollection services,\n        string apiKey,\n        string modelOrDeploymentName,\n        Uri? endpoint = null)\n    {\n        return services\n            .AddSingleton(_ => endpoint is null\n                ? new OpenAIClient(apiKey)\n                : new AzureOpenAIClient(endpoint, new ApiKeyCredential(apiKey)))\n            .AddChatClient(pipeline =>\n            {\n                var openAiClient = pipeline.GetRequiredService<OpenAIClient>();\n                return openAiClient.GetChatClient(modelOrDeploymentName).AsIChatClient();\n            });\n    }\n}\n"
  },
  {
    "path": "src/ServiceDefaults/Clients/ChatCompletion/TestCachingChatClientBuilderExtensions.cs",
    "content": "﻿using Microsoft.Extensions.AI;\nusing Microsoft.Extensions.Caching.Distributed;\nusing Microsoft.Extensions.Configuration;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Microsoft.Extensions.Hosting;\n\n/// <summary>\n/// This is an experimental approach to making E2E tests deterministic even when depending on nondeterministic LLMs.\n/// If we detect that the application is running in a test environment, we attach a disk cache to the chat client, so\n/// that it always replays the same responses for the same inputs. The cache data is stored in source control and can\n/// be refreshed by deleting it and re-running the tests.\n/// \n/// This has the benefit that:\n///  - E2E tests run faster\n///  - E2E tests are more reliable\n///  - E2E tests can run in CI without having to disclose any API keys/secrets to the CI servers\n/// \n/// However it also has drawbacks:\n///  - Developers must manage a directory of cached responses. Whenever prompts are modified, some existing cache\n///    entries become redundant, but it's impractical to work out which of them are now redundant. So developers\n///    usually need to delete and regenerate all cache entries, which can result in large source control diffs that\n///    are hard to merge together if multiple developers do this concurrently.\n///  - It can mask flaky tests. An E2E test may appear to work reliably but only does because the LLM response\n///    happened to be good on the first run. If the cache entry is deleted, the test may fail on subsequent runs\n///    because the LLM response may be different. To avoid problems, it's still important to author tests in a way\n///    that isn't sensitive to the exact wording of the LLM response.\n/// </summary>\n\npublic static class TestCachingChatClientBuilderExtensions\n{\n    public static ChatClientBuilder UseCachingForTest(this ChatClientBuilder builder)\n    {\n        return builder.Use((client, serviceProvider) => {\n            var cacheDir = serviceProvider.GetRequiredService<IConfiguration>()[\"E2E_TEST_CHAT_COMPLETION_CACHE_DIR\"];\n            if (!string.IsNullOrEmpty(cacheDir))\n            {\n                builder.UseDistributedCache(new DiskCache(cacheDir));\n            }\n            return client;\n        });\n    }\n\n    /// <summary>\n    /// An <see cref=\"IDistributedCache\"/> that stores data in the filesystem.\n    /// </summary>\n    private class DiskCache(string cacheDir) : IDistributedCache\n    {\n        public byte[]? Get(string key)\n        {\n            var path = FilePath(key);\n            return File.Exists(path) ? File.ReadAllBytes(path) : null;\n        }\n\n        public async Task<byte[]?> GetAsync(string key, CancellationToken token = default)\n        {\n            var path = FilePath(key);\n            return File.Exists(path) ? await File.ReadAllBytesAsync(path, token) : null;\n        }\n\n        public void Refresh(string key)\n        {\n        }\n\n        public Task RefreshAsync(string key, CancellationToken token = default)\n            => Task.CompletedTask;\n\n        public void Remove(string key)\n            => File.Delete(FilePath(key));\n\n        public Task RemoveAsync(string key, CancellationToken token = default)\n        {\n            Remove(key);\n            return Task.CompletedTask;\n        }\n\n        public void Set(string key, byte[] value, DistributedCacheEntryOptions options)\n        {\n            var path = FilePath(key);\n            Directory.CreateDirectory(Path.GetDirectoryName(path)!);\n            File.WriteAllBytes(path, value);\n        }\n\n        public async Task SetAsync(string key, byte[] value, DistributedCacheEntryOptions options, CancellationToken token = default)\n        {\n            var path = FilePath(key);\n            Directory.CreateDirectory(Path.GetDirectoryName(path)!);\n            await File.WriteAllBytesAsync(path, value, token);\n        }\n\n        private string FilePath(string key)\n            => Path.Combine(cacheDir, $\"{key}.json\");\n    }\n}\n"
  },
  {
    "path": "src/ServiceDefaults/Clients/HttpClientExtensions.cs",
    "content": "﻿using System.Net.Http.Headers;\nusing Microsoft.AspNetCore.Authentication;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.DependencyInjection.Extensions;\n\nnamespace eShopSupport.ServiceDefaults;\n\npublic static class HttpClientExtensions\n{\n    public static IHttpClientBuilder AddAuthToken(this IHttpClientBuilder builder)\n    {\n        builder.Services.AddHttpContextAccessor();\n\n        builder.Services.TryAddTransient<HttpClientAuthorizationDelegatingHandler>();\n\n        builder.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>();\n\n        return builder;\n    }\n\n    private class HttpClientAuthorizationDelegatingHandler : DelegatingHandler\n    {\n        private readonly IHttpContextAccessor _httpContextAccessor;\n\n        public HttpClientAuthorizationDelegatingHandler(IHttpContextAccessor httpContextAccessor)\n        {\n            _httpContextAccessor = httpContextAccessor;\n        }\n\n        public HttpClientAuthorizationDelegatingHandler(IHttpContextAccessor httpContextAccessor, HttpMessageHandler innerHandler) : base(innerHandler)\n        {\n            _httpContextAccessor = httpContextAccessor;\n        }\n\n        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\n        {\n            if (_httpContextAccessor.HttpContext is HttpContext context)\n            {\n                var accessToken = await context.GetTokenAsync(\"access_token\");\n\n                if (accessToken is not null)\n                {\n                    request.Headers.Authorization = new AuthenticationHeaderValue(\"Bearer\", accessToken);\n                }\n            }\n\n            return await base.SendAsync(request, cancellationToken);\n        }\n    }\n}\n"
  },
  {
    "path": "src/ServiceDefaults/Clients/PythonInference/PythonInferenceClient.cs",
    "content": "﻿using System.Net.Http.Json;\n\nnamespace eShopSupport.ServiceDefaults.Clients.PythonInference;\n\npublic class PythonInferenceClient(HttpClient http)\n{\n    public async Task<string?> ClassifyTextAsync(string text, IEnumerable<string> candidateLabels)\n    {\n        var response = await http.PostAsJsonAsync(\"/classify\",\n            new { text, candidate_labels = candidateLabels });\n        var label = await response.Content.ReadFromJsonAsync<string>();\n        return label;\n    }\n}\n"
  },
  {
    "path": "src/ServiceDefaults/Clients/QdrantHttpClientExtensions.cs",
    "content": "﻿using System.Data.Common;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.Extensions.Configuration;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Microsoft.Extensions.Hosting;\n\npublic static class QdrantHttpClientExtensions\n{\n    /// <summary>\n    /// Adds a keyed <see cref=\"HttpClient\"/> to the service collection, preconfigured to connect to the specified Qdrant service.\n    /// \n    /// This is an alternative to using Aspire.Qdrant.Client. The advantage of this approach is being able to access the underlying\n    /// <see cref=\"HttpClient\"/> instance directly, which is required for Semantic Kernel's QdrantMemoryStore.\n    /// </summary>\n    public static void AddQdrantHttpClient(this WebApplicationBuilder builder, string connectionName)\n    {\n        var connectionString = builder.Configuration.GetConnectionString($\"{connectionName}_http\");\n        var connectionBuilder = new DbConnectionStringBuilder { ConnectionString = connectionString };\n        var endpoint = new Uri((string)connectionBuilder[\"endpoint\"]);\n        var key = (string)connectionBuilder[\"key\"];\n\n        builder.Services.AddKeyedScoped(GetServiceKey(connectionName), (services, _) =>\n        {\n            var httpClient = services.GetRequiredService<HttpClient>();\n            httpClient.BaseAddress = endpoint;\n            httpClient.DefaultRequestHeaders.Add(\"api-key\", key);\n            return httpClient;\n        });\n    }\n\n    public static HttpClient GetQdrantHttpClient(this IServiceProvider services, string connectionName)\n        => services.GetRequiredKeyedService<HttpClient>(GetServiceKey(connectionName));\n\n    private static string GetServiceKey(string connectionName) => $\"{connectionName}_httpclient\";\n}\n"
  },
  {
    "path": "src/ServiceDefaults/Extensions.cs",
    "content": "﻿using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Diagnostics.HealthChecks;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Diagnostics.HealthChecks;\nusing Microsoft.Extensions.Logging;\nusing OpenTelemetry;\nusing OpenTelemetry.Metrics;\nusing OpenTelemetry.Trace;\n\nnamespace Microsoft.Extensions.Hosting;\n\npublic static class Extensions\n{\n    public static IHostApplicationBuilder AddServiceDefaults(this IHostApplicationBuilder builder)\n    {\n        builder.ConfigureOpenTelemetry();\n\n        builder.AddDefaultHealthChecks();\n\n        builder.Services.AddServiceDiscovery();\n\n        builder.Services.ConfigureHttpClientDefaults(http =>\n        {\n            // Turn on resilience by default\n            http.AddStandardResilienceHandler();\n\n            // Turn on service discovery by default\n            http.AddServiceDiscovery();\n        });\n\n        return builder;\n    }\n\n    public static IHostApplicationBuilder ConfigureOpenTelemetry(this IHostApplicationBuilder builder)\n    {\n        builder.Logging.AddOpenTelemetry(logging =>\n        {\n            logging.IncludeFormattedMessage = true;\n            logging.IncludeScopes = true;\n        });\n\n        builder.Services.AddOpenTelemetry()\n            .WithMetrics(metrics =>\n            {\n                metrics.AddAspNetCoreInstrumentation()\n                    .AddHttpClientInstrumentation()\n                    .AddRuntimeInstrumentation()\n                    .AddMeter(\"Experimental.Microsoft.Extensions.AI*\");\n            })\n            .WithTracing(tracing =>\n            {\n                tracing.AddAspNetCoreInstrumentation()\n                    // Uncomment the following line to enable gRPC instrumentation (requires the OpenTelemetry.Instrumentation.GrpcNetClient package)\n                    //.AddGrpcClientInstrumentation()\n                    .AddHttpClientInstrumentation()\n                    .AddSource(\"Experimental.Microsoft.Extensions.AI*\");\n            });\n\n        builder.AddOpenTelemetryExporters();\n\n        return builder;\n    }\n\n    private static IHostApplicationBuilder AddOpenTelemetryExporters(this IHostApplicationBuilder builder)\n    {\n        var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration[\"OTEL_EXPORTER_OTLP_ENDPOINT\"]);\n\n        if (useOtlpExporter)\n        {\n            builder.Services.AddOpenTelemetry().UseOtlpExporter();\n        }\n\n        // Uncomment the following lines to enable the Prometheus exporter (requires the OpenTelemetry.Exporter.Prometheus.AspNetCore package)\n        // builder.Services.AddOpenTelemetry()\n        //    .WithMetrics(metrics => metrics.AddPrometheusExporter());\n\n        // Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.AspNetCore package)\n        //if (!string.IsNullOrEmpty(builder.Configuration[\"APPLICATIONINSIGHTS_CONNECTION_STRING\"]))\n        //{\n        //    builder.Services.AddOpenTelemetry()\n        //       .UseAzureMonitor();\n        //}\n\n        return builder;\n    }\n\n    public static IHostApplicationBuilder AddDefaultHealthChecks(this IHostApplicationBuilder builder)\n    {\n        builder.Services.AddHealthChecks()\n            // Add a default liveness check to ensure app is responsive\n            .AddCheck(\"self\", () => HealthCheckResult.Healthy(), [\"live\"]);\n\n        return builder;\n    }\n\n    public static WebApplication MapDefaultEndpoints(this WebApplication app)\n    {\n        // Uncomment the following line to enable the Prometheus endpoint (requires the OpenTelemetry.Exporter.Prometheus.AspNetCore package)\n        // app.MapPrometheusScrapingEndpoint();\n\n        // Adding health checks endpoints to applications in non-development environments has security implications.\n        // See https://aka.ms/dotnet/aspire/healthchecks for details before enabling these endpoints in non-development environments.\n        if (app.Environment.IsDevelopment())\n        {\n            // All health checks must pass for app to be considered ready to accept traffic after starting\n            app.MapHealthChecks(\"/health\");\n\n            // Only health checks tagged with the \"live\" tag must pass for app to be considered alive\n            app.MapHealthChecks(\"/alive\", new HealthCheckOptions\n            {\n                Predicate = r => r.Tags.Contains(\"live\")\n            });\n        }\n\n        return app;\n    }\n}\n"
  },
  {
    "path": "src/ServiceDefaults/ServiceDefaults.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>net8.0</TargetFramework>\n    <ImplicitUsings>enable</ImplicitUsings>\n    <Nullable>enable</Nullable>\n    <IsAspireSharedProject>true</IsAspireSharedProject>\n    <RootNamespace>eShopSupport.ServiceDefaults</RootNamespace>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <FrameworkReference Include=\"Microsoft.AspNetCore.App\" />\n\n    <PackageReference Include=\"Azure.AI.OpenAI\" />\n    <PackageReference Include=\"Microsoft.Extensions.AI\" />\n    <PackageReference Include=\"Microsoft.Extensions.AI.Ollama\" />\n    <PackageReference Include=\"Microsoft.Extensions.AI.OpenAI\" />\n    <PackageReference Include=\"Microsoft.Extensions.Http.Resilience\" />\n    <PackageReference Include=\"Microsoft.Extensions.ServiceDiscovery\" />\n    <PackageReference Include=\"OpenTelemetry.Exporter.OpenTelemetryProtocol\" />\n    <PackageReference Include=\"OpenTelemetry.Extensions.Hosting\" />\n    <PackageReference Include=\"OpenTelemetry.Instrumentation.AspNetCore\" />\n    <PackageReference Include=\"OpenTelemetry.Instrumentation.Http\" />\n    <PackageReference Include=\"OpenTelemetry.Instrumentation.Runtime\" />\n    <PackageReference Include=\"IdentityModel\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/StaffWebUI/Components/App.razor",
    "content": "﻿<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n    <meta charset=\"utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <base href=\"/\" />\n    <link rel=\"stylesheet\" href=\"app.css\" />\n    <link rel=\"stylesheet\" href=\"StaffWebUI.styles.css\" />\n    <link href=\"_content/Microsoft.FluentUI.AspNetCore.Components/css/reboot.css\" rel=\"stylesheet\" />\n    <HeadOutlet @rendermode=\"@PageRenderMode\" />\n</head>\n\n<body>\n    <script src=\"_content/Microsoft.FluentUI.AspNetCore.Components/js/loading-theme.js\" type=\"text/javascript\"></script>\n\n    <Routes @rendermode=\"@PageRenderMode\" />\n    <script src=\"theme-info.js\"></script>\n    <script src=\"_framework/blazor.web.js\"></script>\n</body>\n\n</html>\n\n@code {\n    IComponentRenderMode? PageRenderMode { get; } = new InteractiveServerRenderMode(false);\n}\n"
  },
  {
    "path": "src/StaffWebUI/Components/Layout/LoginDisplay.razor",
    "content": "﻿@using Microsoft.AspNetCore.Components.Authorization\n@using System.Security.Claims\n@using Microsoft.FluentUI.AspNetCore.Components\n@inject NavigationManager Nav\n\n<div class=\"login-display\" tabindex=\"0\">\n    <AuthorizeView>\n        <FluentIcon Value=\"@(new Icons.Regular.Size20.Person())\" />\n        @(context.User?.Identity?.Name ?? \"Unknown name\")\n    </AuthorizeView>\n    <div class=\"user-menu\">\n        <a href=\"user/signout\">Log out</a>\n    </div>\n</div>\n"
  },
  {
    "path": "src/StaffWebUI/Components/Layout/LoginDisplay.razor.css",
    "content": "﻿.login-display {\n    margin-left: auto;\n    background-color: rgba(128, 128, 128, 0.3);\n    padding: 0.2rem 1rem 0.2rem 0.8rem;\n    border-radius: 0.3rem;\n    margin-right: 0.5rem;\n    display: flex;\n    align-items: center;\n    gap: 0.4rem;\n    font-weight: 400;\n    position: relative;\n}\n\n.login-display:focus-within .user-menu, .login-display:hover .user-menu {\n    display: block;\n}\n\n.user-menu {\n    position: absolute;\n    top: 100%;\n    background-color: white;\n    width: 100%;\n    left: 0;\n    box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.3);\n    border: 1px solid silver;\n    display: none;\n}\n\n    .user-menu a {\n        display: block;\n        padding: 0.3rem 0.8rem;\n        color: black;\n        text-decoration: none;\n    }\n\n    .user-menu a:hover {\n        cursor: pointer;\n        background-color: #ddd;\n    }\n"
  },
  {
    "path": "src/StaffWebUI/Components/Layout/MainLayout.razor",
    "content": "﻿@using Microsoft.FluentUI.AspNetCore.Components\n@inherits LayoutComponentBase\n\n<div class=\"app\">\n    <FluentLayout>\n        <FluentHeader Height=\"@(default)\">\n            <a href=\"\" class=\"main-title\">\n                eShopSupport\n            </a>\n            <SectionOutlet SectionName=\"PageTitle\" />\n            <LoginDisplay />\n            <span class=\"theme-picker\">\n                <ThemePicker />\n            </span>\n        </FluentHeader>\n        @Body\n    </FluentLayout>\n</div>\n\n<div id=\"blazor-error-ui\">\n    An unhandled error has occurred.\n    <a href=\"\" class=\"reload\">Reload</a>\n    <a class=\"dismiss\">🗙</a>\n</div>\n"
  },
  {
    "path": "src/StaffWebUI/Components/Layout/MainLayout.razor.css",
    "content": "#blazor-error-ui {\n    background: lightyellow;\n    bottom: 0;\n    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);\n    display: none;\n    left: 0;\n    padding: 0.6rem 1.25rem 0.7rem 1.25rem;\n    position: fixed;\n    width: 100%;\n    z-index: 1000;\n}\n\n    #blazor-error-ui .dismiss {\n        cursor: pointer;\n        position: absolute;\n        right: 0.75rem;\n        top: 0.5rem;\n    }\n\n::deep header {\n    position: sticky;\n    top: 0;\n    background-color: var(--neutral-layer-4) !important;\n    border-bottom: calc(var(--stroke-width)* 2px) solid var(--accent-fill-rest);\n    color: var(--neutral-foreground-rest) !important;\n}\n\n.main-title {\n    font-weight: 400;\n    margin-right: 0.75rem;\n    padding-right: 0.75rem;\n    border-right: 1px solid var(--neutral-foreground-rest);\n    text-decoration: none;\n    color: var(--neutral-foreground-rest);\n}\n\n.app {\n    display: flex;\n    flex-direction: column;\n    align-items: stretch;\n    min-height: 100vh;\n    background: var(--neutral-layer-1);\n    --header-height: 50px;\n}\n\n::deep header {\n    height: var(--header-height);\n}\n"
  },
  {
    "path": "src/StaffWebUI/Components/Layout/ThemePicker.razor",
    "content": "﻿@using Microsoft.FluentUI.AspNetCore.Components\n@inject IJSRuntime JS\n\n<loading-theme storage-name=\"theme\"></loading-theme>\n<loading-theme-info></loading-theme-info>\n<FluentDesignTheme @bind-Mode=\"@Mode\" StorageName=\"theme\" @bind-Mode:after=\"@UpdateThemeAsync\" />\n\n<button @onclick=\"@ChangeThemeAsync\" title=\"Change theme\"></button>\n\n@code {\n    DesignThemeModes Mode = DesignThemeModes.System;\n\n    async Task ChangeThemeAsync()\n    {\n        Mode = await JS.InvokeAsync<string>(\"LoadingThemeInfo.getEffectiveTheme\") == \"dark\"\n            ? DesignThemeModes.Light\n            : DesignThemeModes.Dark;\n    }\n\n    async Task UpdateThemeAsync()\n        => await JS.InvokeVoidAsync(\"LoadingThemeInfo.updateEffectiveThemeClass\");\n}\n"
  },
  {
    "path": "src/StaffWebUI/Components/Layout/ThemePicker.razor.css",
    "content": "﻿button {\n    border: none;\n    background: none;\n}\n\n    button:after {\n        content: '🌞';\n    }\n\nhtml.dark-mode button:after {\n    content: '🌙';\n}\n"
  },
  {
    "path": "src/StaffWebUI/Components/Layout/Title.razor",
    "content": "﻿<PageTitle>eShopSupport: @ChildContent</PageTitle>\n<SectionContent SectionName=\"PageTitle\">@ChildContent</SectionContent>\n\n@code {\n    [Parameter]\n    public RenderFragment? ChildContent { get; set; }\n}\n"
  },
  {
    "path": "src/StaffWebUI/Components/Pages/Account/AccessDenied.razor",
    "content": "﻿@page \"/Account/AccessDenied\"\n@attribute [AllowAnonymous]\n\n<Title>Access Denied</Title>\n\n<div style=\"padding: 2rem\">\n    <h3>Access Denied</h3>\n\n    <a href=\"user/signout\">Log out</a>\n</div>\n"
  },
  {
    "path": "src/StaffWebUI/Components/Pages/Error.razor",
    "content": "﻿@page \"/Error\"\n@using System.Diagnostics\n\n<PageTitle>Error</PageTitle>\n\n<h1 class=\"text-danger\">Error.</h1>\n<h2 class=\"text-danger\">An error occurred while processing your request.</h2>\n\n@if (ShowRequestId)\n{\n    <p>\n        <strong>Request ID:</strong> <code>@RequestId</code>\n    </p>\n}\n\n<h3>Development Mode</h3>\n<p>\n    Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.\n</p>\n<p>\n    <strong>The Development environment shouldn't be enabled for deployed applications.</strong>\n    It can result in displaying sensitive information from exceptions to end users.\n    For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>\n    and restarting the app.\n</p>\n\n@code{\n    [CascadingParameter]\n    private HttpContext? HttpContext { get; set; }\n\n    private string? RequestId { get; set; }\n    private bool ShowRequestId => !string.IsNullOrEmpty(RequestId);\n\n    protected override void OnInitialized() =>\n        RequestId = Activity.Current?.Id ?? HttpContext?.TraceIdentifier;\n}\n"
  },
  {
    "path": "src/StaffWebUI/Components/Pages/RedisSubscribingComponent.cs",
    "content": "﻿using Microsoft.AspNetCore.Components;\nusing StackExchange.Redis;\n\nnamespace eShopSupport.StaffWebUI.Components.Pages;\n\n/// <summary>\n/// Base class for a component that can easily subscribe to a RedisChannel and override a method to handle notifications.\n/// This base class deals with registering and unregistering subscriptions.\n/// </summary>\npublic abstract class RedisSubscribingComponent : ComponentBase, IDisposable\n{\n    private RedisChannel? _channel;\n    private bool disposedValue;\n    private ExecutionContext? executionContext;\n\n    [Inject]\n    private IConnectionMultiplexer Redis { get; set; } = default!;\n\n    protected RedisChannel? SubscriptionChannel\n    {\n        get => _channel;\n        set\n        {\n            if (_channel != value)\n            {\n                // Remove the old subscription, if any\n                var subscriber = Redis.GetSubscriber();\n                if (_channel.HasValue)\n                {\n                    subscriber.Unsubscribe(_channel.Value, HandleMessage);\n                }\n\n                // Create the new subscription\n                _channel = value;\n                if (_channel.HasValue && !disposedValue)\n                {\n                    // We must explicitly capture and restore the execution context around subscription\n                    // callbacks, otherwise the callback won't have access to any async locals from the\n                    // original context, and then things like HttpClientAuthorizationDelegatingHandler\n                    // won't work.\n                    executionContext = ExecutionContext.Capture();\n\n                    subscriber.Subscribe(_channel.Value, HandleMessage);\n                }\n            }\n        }\n    }\n\n    void HandleMessage(RedisChannel channel, RedisValue value)\n        => _ = HandleMessageAsync(channel, value);\n\n    async Task HandleMessageAsync(RedisChannel channel, RedisValue value)\n    {\n        // This pattern deals with getting onto the renderer sync context, causing the UI to refresh around the\n        // returned task, and processing any exceptions within the component's rendering context\n        try\n        {\n            await InvokeAsync(async () =>\n            {\n                Task? result = null;\n                ExecutionContext.Run(executionContext!, _ =>\n                {\n                    result = EventCallback.Factory\n                        .Create<RedisValue>(this, OnRedisNotificationAsync)\n                        .InvokeAsync(value);\n                }, null);\n\n                await result!;\n            });\n        }\n        catch (Exception ex)\n        {\n            await DispatchExceptionAsync(ex);\n        }\n    }\n\n    protected virtual void Dispose(bool disposing)\n    {\n        if (!disposedValue)\n        {\n            if (disposing)\n            {\n                // Unsubscribe\n                SubscriptionChannel = null;\n            }\n\n            disposedValue = true;\n        }\n    }\n\n    public void Dispose()\n    {\n        Dispose(disposing: true);\n        GC.SuppressFinalize(this);\n    }\n\n    protected virtual Task OnRedisNotificationAsync(RedisValue value)\n        => Task.CompletedTask;\n}\n"
  },
  {
    "path": "src/StaffWebUI/Components/Pages/Ticket/Ticket.razor",
    "content": "﻿@page \"/ticket/{ticketId:int}\"\n@inherits RedisSubscribingComponent\n@using Microsoft.FluentUI.AspNetCore.Components\n@using StackExchange.Redis\n@using eShopSupport.ServiceDefaults.Clients.Backend\n@inject StaffBackendClient Backend\n\n<Title>Ticket @TicketId</Title>\n\n<div class=\"ticket\">\n    <FluentSplitter BarSize=\"6\" BarHandle=\"false\" Panel1MinSize=\"300px\" Panel2Size=\"350px\" Panel2MinSize=\"200px\" Class=\"splitter\">\n        <Panel1>\n            <div class=\"details\">\n                @if (ticket is not null)\n                {\n                    <TicketDetails Ticket=\"@ticket\" />\n                }\n            </div>\n            <div class=\"messages\">\n                <TicketMessages Ticket=\"@ticket\" />\n            </div>\n            <div class=\"write-message\">\n                <EditForm EditContext=\"@editContext\" OnValidSubmit=\"@SendReplyAsync\">\n                    <FluentTextArea @ref=\"replyTextArea\" @bind-Value=\"@replyText\" Placeholder=\"Reply to the customer\" style=\"width: 100%; height: 100%;\" />\n                    <div class=\"actions\">\n                        @if (!isSending)\n                        {\n                            <FluentButton Type=\"ButtonType.Submit\" Appearance=\"Appearance.Accent\" IconStart=\"@sendIcon\">Send</FluentButton>\n                        }\n                        else\n                        {\n                            <FluentProgressRing />\n                        }\n                    </div>\n                </EditForm>\n            </div>\n        </Panel1>\n        <Panel2>\n            <div class=\"assistant\">\n                <TicketAssistant Ticket=\"@ticket\" OnSuggestedReply=\"@AcceptSuggestedReply\" />\n            </div>  \n        </Panel2>\n    </FluentSplitter>\n</div>\n\n@code {\n    private readonly Icon sendIcon = new Icons.Regular.Size20.Mail();\n    private EditContext editContext;\n    private TicketDetailsResult? ticket;\n    private string? replyText;\n    private FluentTextArea? replyTextArea;\n    private bool isSending;\n\n    [Parameter]\n    public int TicketId { get; set; }\n\n    public Ticket() => editContext = new(this);\n\n    protected override async Task OnParametersSetAsync()\n    {\n        ticket = null;\n        ticket = await Backend.GetTicketDetailsAsync(TicketId);\n\n        SubscriptionChannel = RedisChannel.Literal($\"ticket:{TicketId}\");\n    }\n\n    private void AcceptSuggestedReply(string suggestion)\n    {\n        replyText = suggestion;\n        replyTextArea?.FocusAsync();\n        editContext.NotifyFieldChanged(FieldIdentifier.Create(() => replyText));\n    }\n\n    private async Task SendReplyAsync()\n    {\n        if (string.IsNullOrWhiteSpace(replyText))\n        {\n            return;\n        }\n\n        isSending = true;\n        var sendTask = Backend.SendTicketMessageAsync(TicketId, new(replyText));\n        await Task.WhenAll(sendTask, Task.Delay(500));\n\n        replyText = null;\n        editContext.MarkAsUnmodified();\n        ticket = await Backend.GetTicketDetailsAsync(TicketId);\n\n        // To avoid having the \"send\" button flash into existence before animating away,\n        // keep the spinner on screen for a further 1s, giving time for the animation to complete\n        StateHasChanged();\n        await Task.Delay(1000);\n        isSending = false;\n    }\n\n    protected override async Task OnRedisNotificationAsync(RedisValue value)\n        => ticket = await Backend.GetTicketDetailsAsync(TicketId);\n}\n"
  },
  {
    "path": "src/StaffWebUI/Components/Pages/Ticket/Ticket.razor.css",
    "content": "﻿::deep .splitter {\n    height: calc(100vh - var(--header-height));\n}\n\n    ::deep .splitter [slot='1'] {\n        display: flex;\n        flex-direction: column;\n    }\n\n    ::deep .splitter [slot='2'] {\n        background-color: color-mix(in srgb, var(--neutral-layer-2) 95%, grey);\n        color: var(--neutral-foreground-rest);\n    }\n\nhtml.dark-mode .ticket ::deep .splitter [slot='2'] {\n    background-color: color-mix(in srgb, var(--neutral-layer-2) 70%, grey);\n}\n\n.details {\n    padding: 1.5rem 1.5rem;\n    background: var(--neutral-layer-1);\n    box-shadow: 0px 2px 5px #0000000d;\n    border-bottom: calc(var(--stroke-width)* 1px) solid var(--neutral-stroke-active);\n    z-index: 2;\n}\n\n.messages {\n    flex-grow: 1;\n    padding: 0 1.5rem;\n    background: var(--neutral-layer-3);\n    overflow-y: scroll;\n    /* Make the scrollbar default to being at the end, instead of the start */\n    display: flex;\n    flex-direction: column-reverse;\n    /* Fix subpixel text rendering glitch */\n    clip-path: inset(1px 0 0 0);\n}\n\n.write-message {\n    height: 130px;\n    background: var(--neutral-layer-2);\n    border-top: calc(var(--stroke-width)* 1px) solid var(--neutral-stroke-active);\n    flex-shrink: 0;\n    padding: 1rem 1.5rem;\n    box-shadow: 0px -2px 5px #0000000d;\n    z-index: 1;\n    display: flex;\n    transition: height 0.3s cubic-bezier(.16,.75,.35,1.02);\n    transition-delay: 0.05s;\n}\n\n    .write-message:focus-within, .write-message:has(.modified) {\n        height: 250px;\n    }\n\n    .write-message ::deep form {\n        flex-grow: 1;\n        display: flex;\n        flex-direction: column;\n    }\n\n    .write-message ::deep fluent-text-area::part(control) {\n        flex-grow: 1;\n    }\n\n.actions {\n    opacity: 0;\n    transform: scaleY(0);\n    height: 0;\n    transition-property: opacity transform height;\n    transition-timing-function: cubic-bezier(.16,.75,.35,1.02);\n    transition-duration: 0.3s;\n    transition-delay: 0.05s;\n    display: flex;\n    justify-content: center;\n    align-items: center;\n}\n\n.write-message:focus-within .actions, .write-message:has(.modified) .actions {\n    opacity: 1;\n    height: 2.75rem;\n    transform: scaleY(1);\n    margin-top: 0.75rem;\n}\n\n.assistant {\n    display: flex;\n    flex-direction: column;\n    height: 100%;\n}\n"
  },
  {
    "path": "src/StaffWebUI/Components/Pages/Ticket/TicketAssistant.razor",
    "content": "﻿@using Microsoft.FluentUI.AspNetCore.Components\n@using eShopSupport.ServiceDefaults.Clients.Backend\n@inject IJSRuntime JS\n@inject StaffBackendClient Backend\n\n<div class=\"messages-scroller\">\n    <div class=\"messages\">\n        @if (messages.Count == 0)\n        {\n            <div class=\"suggestions\">\n                <p>Ask me about our products, or pick a suggestion to get started.</p>\n                @foreach (var suggestion in suggestions)\n                {\n                    <a href @onclick=\"@(() => ApplySuggestion(suggestion))\" @onclick:preventDefault>\n                        <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M9.56158 3C5.41944 3 2.06158 6.35786 2.06158 10.5C2.06158 11.6329 2.31325 12.7088 2.76423 13.6734C2.5102 14.6714 2.22638 15.7842 2.03999 16.5147C1.80697 17.428 2.6294 18.2588 3.54374 18.039C4.29396 17.8587 5.44699 17.5819 6.47447 17.337C7.41678 17.7631 8.46241 18 9.56158 18C13.7037 18 17.0616 14.6421 17.0616 10.5C17.0616 6.35786 13.7037 3 9.56158 3ZM3.56158 10.5C3.56158 7.18629 6.24787 4.5 9.56158 4.5C12.8753 4.5 15.5616 7.18629 15.5616 10.5C15.5616 13.8137 12.8753 16.5 9.56158 16.5C8.60084 16.5 7.69487 16.2748 6.89161 15.8749L6.6482 15.7537L6.38368 15.8167C5.46095 16.0363 4.39489 16.2919 3.59592 16.4838C3.79467 15.7047 4.05784 14.6724 4.28601 13.7757L4.35619 13.4998L4.22568 13.2468C3.80145 12.4246 3.56158 11.4914 3.56158 10.5ZM14.5616 21.0001C12.5922 21.0001 10.8001 20.241 9.46191 18.9995C9.49511 18.9999 9.52835 19.0001 9.56163 19.0001C10.2796 19.0001 10.9768 18.911 11.6427 18.7434C12.5067 19.2254 13.5021 19.5001 14.5616 19.5001C15.5223 19.5001 16.4283 19.2748 17.2316 18.8749L17.475 18.7537L17.7395 18.8167C18.6611 19.0361 19.7046 19.2625 20.4787 19.4262C20.3037 18.6757 20.065 17.6711 19.8372 16.7757L19.767 16.4999L19.8975 16.2469C20.3217 15.4247 20.5616 14.4915 20.5616 13.5001C20.5616 11.3853 19.4676 9.52617 17.8146 8.45761C17.6363 7.73435 17.3653 7.04756 17.015 6.41052C19.9523 7.42684 22.0616 10.2171 22.0616 13.5001C22.0616 14.6332 21.8098 15.7094 21.3586 16.6741C21.6117 17.6821 21.8679 18.774 22.0304 19.4773C22.2348 20.3623 21.4554 21.1633 20.563 20.9768C19.8358 20.8248 18.6933 20.581 17.6495 20.3367C16.707 20.763 15.6611 21.0001 14.5616 21.0001Z\"></path></svg>\n                        @suggestion\n                    </a>\n                }\n            </div>\n        }\n\n        @for (var i = 0; i < messages.Count; i++)\n        {\n            var id = $\"message{i}\";\n            var state = messages[i]!;\n            <TicketAssistantMessage @key=\"@id\" State=\"@state\" OnCompleted=\"@HandleResponseCompleted\" OnSuggestedReply=\"@OnSuggestedReply\" />\n        }\n    </div>\n</div>\n\n<form class=\"write-message @(ReplyInProgress ? \"in-progress\" : \"\")\" @ref=\"@writeMessageElement\" @onsubmit=\"@SendMessage\">\n    <FluentButton Class=\"stop-responding\" @onclick=\"@StopResponding\" Appearance=\"Appearance.Outline\">Stop responding</FluentButton>\n    <FluentTextArea @bind-Value=\"@userMessageText\" Placeholder=\"Ask the AI assistant&hellip;\" style=\"width: 100%; height: 100%;\" />\n</form>\n\n@code {\n    CancellationTokenSource? currentReplyCancellationTokenSource;\n    List<MessageState> messages = new();\n    ElementReference writeMessageElement;\n    string? userMessageText;\n    string[] suggestions = [\"What does the manual say about this?\", \"Write a suggested reply to the customer.\"];\n\n    [Parameter, EditorRequired]\n    public TicketDetailsResult? Ticket { get; set; }\n\n    [Parameter]\n    public EventCallback<string> OnSuggestedReply { get; set; }\n\n    bool ReplyInProgress => currentReplyCancellationTokenSource?.IsCancellationRequested == false;\n\n    protected override async Task OnAfterRenderAsync(bool firstRender)\n    {\n        if (firstRender)\n        {\n            try\n            {\n                await using var module = await JS.InvokeAsync<IJSObjectReference>(\"import\", \"./Components/Pages/Ticket/TicketAssistant.razor.js\");\n                await module.InvokeVoidAsync(\"submitOnEnter\", writeMessageElement);\n            }\n            catch (JSDisconnectedException)\n            {\n                // Not an error\n            }\n        }\n    }\n\n    void SendMessage()\n    {\n        if (Ticket is { } ticket && !string.IsNullOrWhiteSpace(userMessageText))\n        {\n            StopResponding();\n\n            // Add the user's message to the UI\n            messages.Add(new MessageState(new() { Text = userMessageText }, null, CancellationToken.None));\n            userMessageText = null;\n\n            // Submit request to backend\n            currentReplyCancellationTokenSource = new CancellationTokenSource();\n            var cancellationToken = currentReplyCancellationTokenSource.Token;\n            var request = new AssistantChatRequest(\n                ticket.ProductId,\n                ticket.CustomerFullName,\n                ticket.LongSummary,\n                ticket.Messages.LastOrDefault(m => m.IsCustomerMessage)?.MessageText,\n                messages.Select(m => m.Message).ToList());\n            var responseItems = Backend.AssistantChatAsync(request, cancellationToken);\n\n            // Add the assistant's reply to the UI\n            var reply = new AssistantChatRequestMessage { IsAssistant = true, Text = string.Empty };\n            messages.Add(new MessageState(reply, responseItems, cancellationToken));\n        }\n    }\n\n    private void HandleResponseCompleted(MessageState state)\n    {\n        if (messages.LastOrDefault() == state)\n        {\n            currentReplyCancellationTokenSource = null;\n        }\n\n        // If it was cancelled before the response started, remove the message entirely\n        // But if there was some text already, keep it\n        if (string.IsNullOrEmpty(state.Message.Text))\n        {\n            messages.Remove(state);\n        }\n    }\n\n    private void StopResponding()\n    {\n        currentReplyCancellationTokenSource?.Cancel();\n    }\n\n    private void ApplySuggestion(string suggestion)\n    {\n        userMessageText = suggestion;\n        SendMessage();\n    }\n\n    public record MessageState(AssistantChatRequestMessage Message, IAsyncEnumerable<AssistantChatReplyItem>? ResponseItems, CancellationToken CancellationToken);\n}\n"
  },
  {
    "path": "src/StaffWebUI/Components/Pages/Ticket/TicketAssistant.razor.css",
    "content": "﻿.messages-scroller {\n    /* Make the scrollbar default to being at the end, instead of the start */\n    display: flex;\n    flex-direction: column-reverse;\n\n    overflow-y: auto;\n    flex-grow: 1;\n}\n\n.messages {\n    display: flex;\n    flex-direction: column;\n    padding: 1rem 1.5rem 0 0.75rem;\n    gap: 1rem;\n    align-items: flex-start;\n    margin-bottom: auto;\n}\n\n.suggestions {\n    padding: 0.5rem;\n    padding-right: 0;\n    font-size: 0.85rem;\n    width: 100%;\n}\n\n    .suggestions p {\n        opacity: 0.8;\n        font-size: 0.85rem;\n    }\n\n    .suggestions a svg {\n        width: 1rem;\n        color: var(--accent-fill-rest);\n        flex-shrink: 0;\n        flex-grow: 0;\n        margin-top: 0.15rem;\n    }\n\n    .suggestions a {\n        display: flex;\n        flex-direction: row;\n        align-items: flex-start;\n        gap: 0.5rem;\n        background-color: var(--neutral-layer-floating);\n        border: 1px solid var(--neutral-stroke-input-active);\n        margin-top: 0.75rem;\n        padding: 0.75rem;\n        border-radius: 0.5rem;\n        text-decoration: none;\n        color: #404040;\n    }\n\n        .suggestions a:hover {\n            border-color: var(--accent-fill-rest) !important;\n        }\n\nhtml.dark-mode .suggestions a {\n    background-color: var(--neutral-stroke-focus);\n    border: 1px solid var(--neutral-stroke-hover);\n    color: var(--neutral-foreground-rest);\n}\n\n    ::deep .stop-responding {\n        flex-shrink: 0;\n        opacity: 0;\n        visibility: hidden;\n        transition: opacity, transform;\n        transition-duration: 0.3s;\n        transition-timing-function: ease-out;\n        transition-delay: 0.5s;\n        transform: translateY(0.25rem);\n    }\n\n.write-message.in-progress ::deep .stop-responding {\n    opacity: 1;\n    visibility: visible;\n    transform: translateY(0);\n}\n\n.write-message {\n    height: 160px;\n    flex-shrink: 0;\n    padding: 0.5rem 1rem 1.5rem 1rem;\n    z-index: 1;\n    display: flex;\n    flex-direction: column;\n    gap: 0.5rem;\n    align-items: center;\n}\n\n::deep fluent-text-area {\n    --control-corner-radius: 20;\n\n    /* We can't display the blue highlight at the bottom because it can't draw large on a large border radius */\n    /* Notice that in real Copilot UIs it also doesn't use the blue highlight on this textarea */\n    --focus-stroke-width: 0;\n}\n\n    ::deep fluent-text-area::part(control) {\n        flex-grow: 1;\n        padding: 1rem;\n        border: 1px solid var(--neutral-stroke-rest);\n    }\n"
  },
  {
    "path": "src/StaffWebUI/Components/Pages/Ticket/TicketAssistant.razor.js",
    "content": "﻿export function submitOnEnter(formElem) {\n    formElem.addEventListener('keydown', e => {\n        if (e.key === 'Enter' && !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey) {\n            e.srcElement.dispatchEvent(new Event('change', { bubbles: true }));\n            formElem.requestSubmit();\n        }\n    });\n\n    formElem.addEventListener('submit', e => {\n        // If you're nearly scrolled to the end, scroll entirely to the end so that\n        // when new content is added it will auto-scroll and follow it\n        const messagesScroller = document.querySelector('.messages-scroller');\n        if (Math.abs(messagesScroller.scrollTop) < 5) {\n            messagesScroller.scrollTop = 0;\n        }\n    });\n}\n"
  },
  {
    "path": "src/StaffWebUI/Components/Pages/Ticket/TicketAssistantMessage.razor",
    "content": "﻿@using Microsoft.FluentUI.AspNetCore.Components\n@using System.Text.Json\n@using System.Text.RegularExpressions\n@using System.Web\n@using eShopSupport.ServiceDefaults.Clients.Backend\n@inject IJSRuntime JS\n\n@if (!State.Message.IsAssistant)\n{\n    <div class=\"message\">\n        <div class=\"sender-icon\">\n            <FluentPersona Image=\"@anonymousPersonImage\" ImageSize=\"30px\" />\n        </div>\n        <div class=\"sender-name\">You</div>\n        <div class=\"message-content\">\n            <div class=\"message-text\">@State.Message.Text</div>\n        </div>\n    </div>\n}\nelse\n{\n    <div class=\"message assistant @(visible ? \"visible\" : \"\")\">\n        <div class=\"sender-icon\">\n            <FluentPersona Image=\"@assistantImage\" ImageSize=\"30px\" />\n        </div>\n        <div class=\"sender-name\">Assistant</div>\n        <div class=\"message-content\" @ref=\"messageContentElement\">\n            @if (!string.IsNullOrEmpty(searchText))\n            {\n                <div class=\"search-info\">@searchText</div>\n            }\n\n            <div class=\"message-text\">@(string.IsNullOrEmpty(State.Message.Text) ? \"...\" : State.Message.Text)</div>\n\n            @if (isSuggestedReply)\n            {\n                <div class=\"use-as-reply\">\n                    <FluentButton Appearance=\"Appearance.Accent\" OnClick=\"@UseAsReplyAsync\">Use as reply</FluentButton>\n                </div>\n            }\n\n            @if (!string.IsNullOrEmpty(citationUrl))\n            {\n                <a href=\"@citationUrl\" class=\"reference-link\" target=\"_blank\">\n                    <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-6 h-6\">\n                        <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 6.042A8.967 8.967 0 0 0 6 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 0 1 6 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 0 1 6-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0 0 18 18a8.967 8.967 0 0 0-6 2.292m0-14.25v14.25\" />\n                    </svg>\n                    <span class=\"ref-text\">@(string.IsNullOrWhiteSpace(citationQuote) ? \"Reference\" : citationQuote)</span>\n                </a>\n            }\n        </div>\n    </div>\n}\n\n@code {\n    string anonymousPersonImage = \"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0OCA0OCIgd2lkdGg9IjI1cHgiIGZpbGw9IndoaXRlIiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tbmV1dHJhbC1sYXllci0xKTsgd2lkdGg6IDI1cHg7IiBhcmlhLWhpZGRlbj0idHJ1ZSI+PHBhdGggZD0iTTI0IDRhMTAgMTAgMCAxIDAgMCAyMCAxMCAxMCAwIDAgMCAwLTIwWm0tNy41IDEwYTcuNSA3LjUgMCAxIDEgMTUgMCA3LjUgNy41IDAgMCAxLTE1IDBabS00LjI1IDE0QTQuMjUgNC4yNSAwIDAgMCA4IDMyLjI1VjMzYzAgMy43NiAxLjk0IDYuNTcgNC45MiA4LjM4QzE1Ljg1IDQzLjE2IDE5Ljc5IDQ0IDI0IDQ0czguMTUtLjg0IDExLjA4LTIuNjJDMzguMDYgMzkuNTcgNDAgMzYuNzYgNDAgMzN2LS43NUM0MCAyOS45IDM4LjEgMjggMzUuNzUgMjhoLTIzLjVabS0xLjc1IDQuMjVjMC0uOTcuNzgtMS43NSAxLjc1LTEuNzVoMjMuNWMuOTcgMCAxLjc1Ljc4IDEuNzUgMS43NVYzM2MwIDIuNzQtMS4zNiA0LjgtMy43MiA2LjI0LTIuNDEgMS40Ny01Ljg1IDIuMjYtOS43OCAyLjI2LTMuOTMgMC03LjM3LS43OS05Ljc4LTIuMjYtMi4zNi0xLjQzLTMuNzItMy41LTMuNzItNi4yNHYtLjc1WiIvPjwvc3ZnPg==\";\n    string assistantImage = \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke-width='1.5' stroke='white' class='w-6 h-6'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M12 18v-5.25m0 0a6.01 6.01 0 0 0 1.5-.189m-1.5.189a6.01 6.01 0 0 1-1.5-.189m3.75 7.478a12.06 12.06 0 0 1-4.5 0m3.75 2.383a14.406 14.406 0 0 1-3 0M14.25 18v-.192c0-.983.658-1.823 1.508-2.316a7.5 7.5 0 1 0-7.517 0c.85.493 1.509 1.333 1.509 2.316V18' /%3E%3C/svg%3E%0A\";\n\n    private string? searchText;\n    private bool isSuggestedReply;\n    private ElementReference messageContentElement;\n    private bool visible;\n    private string? citationUrl;\n    private string? citationQuote;\n\n    [Parameter, EditorRequired]\n    public TicketAssistant.MessageState State { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback<TicketAssistant.MessageState> OnCompleted { get; set; }\n\n    [Parameter]\n    public EventCallback<string> OnSuggestedReply { get; set; }\n\n    protected override async Task OnAfterRenderAsync(bool firstRender)\n    {\n        if (!firstRender)\n        {\n            return;\n        }\n\n        // Load the module, or just get a reference if it's already loaded\n        await using var module = await JS.InvokeAsync<IJSObjectReference>(\"import\", \"./Components/Pages/Ticket/TicketAssistantMessage.razor.js\");\n\n        if (State.ResponseItems is not null)\n        {\n            var searchResults = new List<AssistantChatReplyItem>();\n            try\n            {\n                // Don't become visible until either a response starts arriving, or some timeout elapses\n                // This feels more natural than showing a placeholder reply instantly after you submit a message\n                await Task.Delay(500);\n                visible = true;\n                StateHasChanged();\n\n                await foreach (var item in State.ResponseItems)\n                {\n                    switch (item.Type)\n                    {\n                        case AssistantChatReplyItemType.Search:\n                            searchText = item.Text;\n                            StateHasChanged();\n                            break;\n                        case AssistantChatReplyItemType.SearchResult:\n                            searchResults.Add(item);\n                            break;\n                        case AssistantChatReplyItemType.AnswerChunk:\n                            State.Message.Text += item.Text;\n                            await module.InvokeVoidAsync(\"addAnswerChunk\", messageContentElement, item.Text);\n                            break;\n                        case AssistantChatReplyItemType.IsAddressedToCustomer:\n                            isSuggestedReply = item.Text == \"true\";\n                            StateHasChanged();\n                            break;\n                    }\n                }\n            }\n            catch (TaskCanceledException)\n            {\n                // Not an error\n            }\n\n            // Check if there's a citation to show\n            var citeMatches = Regex.Matches(State.Message.Text, \"<cite searchResultId=['\\\"]?(\\\\d+)['\\\"]?>(.*?)</cite>\");\n            if (citeMatches.FirstOrDefault() is { } match\n                && int.TryParse(match.Groups[1].Value, out var searchResultId)\n                && searchResults.FirstOrDefault(s => s.SearchResultId == searchResultId) is { } searchResult)\n            {\n                citationQuote = match.Groups[2].Value;\n                citationQuote = citationQuote.Trim('.', ',', ' ', '\\n', '\\r', '\\t', '\"', '\\'');\n                citationUrl = $\"manual.html?file={searchResult.SearchResultProductId}.pdf&page={searchResult.SearchResultPageNumber}&search={HttpUtility.UrlEncode(citationQuote)}\";\n                State.Message.Text = State.Message.Text[0..match.Index] + State.Message.Text[(match.Index + match.Length)..];\n            }\n\n            State.Message.Text = State.Message.Text.Trim();\n            await OnCompleted.InvokeAsync(State);\n        }\n    }\n\n    private Task UseAsReplyAsync()\n        => OnSuggestedReply.InvokeAsync(State.Message.Text);\n}\n"
  },
  {
    "path": "src/StaffWebUI/Components/Pages/Ticket/TicketAssistantMessage.razor.css",
    "content": "﻿.message {\n    display: grid;\n    grid-template-columns: 2rem 1fr;\n    grid-template-rows: min-content min-content;\n    grid-template-areas:\n        \"sender-icon sender-name\"\n        \". message\";\n    gap: 0.25rem .75rem;\n    animation: message-appear 0.25s ease-out;\n    overflow-y: hidden;\n}\n\n@keyframes message-appear {\n    0% {\n        max-height: 0;\n        opacity: 0;\n    }\n\n    100% {\n        opacity: 1;\n        max-height: 100px;\n    }\n}\n\n.message ::deep .initials {\n    background-color: grey;\n}\n\n.message.assistant ::deep .initials {\n    background-color: #d800b1;\n}\n\n.message.assistant:not(.visible) {\n    display: none;\n}\n\n.sender-icon {\n    grid-area: sender-icon;\n    align-self: center;\n    justify-self: center;\n}\n\n    .sender-icon ::deep img {\n        width: 21px !important;\n    }\n\n.sender-name {\n    grid-area: sender-name;\n    font-size: 1rem;\n    font-weight: 600;\n    align-self: center;\n}\n\n.message-content {\n    grid-area: message;\n}\n\n.message-text {\n    white-space: pre-line;\n    word-break: break-word;\n}\n\n.search-info {\n    font-weight: 500;\n    margin-bottom: 0.5rem;\n}\n\n    .search-info:before {\n        content: 'Searching: ';\n    }\n\n.reference-link {\n    display: flex;\n    text-decoration: none;\n    background-color: rgba(128, 128, 128, 0.3);\n    padding: 0.5rem 0.9rem;\n    border-radius: 0.5rem;\n    margin-top: 1rem;\n}\n\n    .reference-link .ref-text {\n        display: -webkit-box;\n        overflow: hidden;\n        text-overflow: ellipsis;\n        -webkit-line-clamp: 2;\n        -webkit-box-orient: vertical;\n    }\n\n        .reference-link svg {\n            color: var(--neutral-foreground-rest);\n            width: var(--type-ramp-base-line-height);\n            height: var(--type-ramp-base-line-height);\n            flex-grow: 0;\n            flex-shrink: 0;\n            margin-right: 0.4rem;\n        }\n\nhtml:not(.dark-mode) .reference-link {\n    color: var(--accent-fill-rest);\n}\n\n::deep .use-as-reply {\n    margin-top: 0.8rem;\n    text-align: center;\n}\n"
  },
  {
    "path": "src/StaffWebUI/Components/Pages/Ticket/TicketAssistantMessage.razor.js",
    "content": "﻿export function addAnswerChunk(elem, chunkText) {\n    elem = elem.querySelector('.message-text');\n\n    elem.fullText = (elem.fullText || '') + chunkText;\n    elem.textContent = elem.fullText;\n\n    // Hide any citation markup\n    while (true) {\n        const citeStartPos = elem.textContent.indexOf('<cite ');\n        if (citeStartPos < 0) {\n            break;\n        }\n\n        const citeEndPos = elem.textContent.indexOf('</cite>', citeStartPos);\n        if (citeEndPos >= 0) {\n            elem.textContent = elem.textContent.substring(0, citeStartPos) + elem.textContent.substring(citeEndPos + 7);\n        } else {\n            elem.textContent = elem.textContent.substring(0, citeStartPos);\n        }\n    }\n\n    elem.textContent = elem.textContent.trim();\n}\n"
  },
  {
    "path": "src/StaffWebUI/Components/Pages/Ticket/TicketDetails.razor",
    "content": "﻿@using Microsoft.FluentUI.AspNetCore.Components\n@using eShopSupport.ServiceDefaults.Clients.Backend\n@inject StaffBackendClient Backend\n<EditForm EditContext=\"@editContext\" OnValidSubmit=\"@SaveChangesAsync\">\n    <div class=\"details-grid @(editContext.IsModified() ? \"modified\": \"\")\">\n        <div>\n            <FluentSelect TOption=\"TicketType\" @bind-SelectedOption=\"@ticketType\" Items=\"@allTicketTypes\"\n                Label=\"Case type\" OptionText=\"@TicketTypeDisplayText\" style=\"width: 100%; min-width: 12rem;\"\n                @bind-SelectedOption:after=\"@MarkTicketTypeModified\" />\n        </div>\n        <div>\n            <FluentTextField Label=\"Customer\" style=\"width: 100%;\" Value=\"@Ticket?.CustomerFullName\" ReadOnly />\n        </div>\n        <div>\n            <FluentSelect TOption=\"TicketStatus\" @bind-SelectedOption=\"@ticketStatus\" Items=\"@allTicketStatuses\"\n                Label=\"Status\" OptionText=\"@TicketStatusDisplayText\" style=\"width: 100%; min-width: 12rem;\"\n                @bind-SelectedOption:after=\"@MarkTicketStatusModified\" />\n        </div>\n        <div class=\"product-picker\">\n            <FluentAutocomplete TOption=\"FindProductsResult\" @bind-SelectedOptions=\"@ticketProduct\" MaximumSelectedOptions=\"1\"\n                Label=\"Product\" OptionText=\"@FindProductDisplayText\" style=\"width: 100%; min-width: 12rem;\"\n                OnOptionsSearch=\"LookupProductAsync\" @bind-SelectedOptions:after=\"@MarkTicketProductModified\" />\n        </div>\n        <div class=\"actions\">\n            @if (!isSaving)\n            {\n                <FluentButton Type=\"@ButtonType.Submit\" Appearance=\"Appearance.Accent\" IconStart=\"@saveIcon\" Style=\"margin-top: 0.5rem\">\n                    Save changes\n                </FluentButton>\n            }\n            else\n            {\n                <FluentProgressRing />\n            }\n        </div>\n    </div>\n</EditForm>\n\n@code {\n    private readonly Icon saveIcon = new Icons.Regular.Size20.Save();\n    EditContext editContext;\n\n    readonly TicketType[] allTicketTypes = Enum.GetValues<TicketType>();\n    readonly TicketStatus[] allTicketStatuses = Enum.GetValues<TicketStatus>();\n    int loadedTicketId;\n    TicketType ticketType;\n    TicketStatus ticketStatus;\n    IEnumerable<FindProductsResult>? ticketProduct;\n    bool isSaving;\n\n    [Parameter, EditorRequired]\n    public TicketDetailsResult Ticket { get; set; } = default!;\n\n    public TicketDetails() => editContext = new(this);\n\n    protected override void OnParametersSet()\n    {\n        if (Ticket.TicketId != loadedTicketId)\n        {\n            loadedTicketId = Ticket.TicketId;\n            ticketType = Ticket.TicketType;\n            ticketStatus = Ticket.TicketStatus;\n            ticketProduct = Ticket.ProductId.HasValue ? [new FindProductsResult(Ticket.ProductId.Value, Ticket.ProductBrand!, Ticket.ProductModel!)] : [];\n        }\n    }\n\n    // Workaround for https://github.com/microsoft/fluentui-blazor/issues/2086\n    private void MarkTicketTypeModified()\n        => editContext.NotifyFieldChanged(FieldIdentifier.Create(() => ticketType));\n    private void MarkTicketStatusModified()\n        => editContext.NotifyFieldChanged(FieldIdentifier.Create(() => ticketStatus));\n    private void MarkTicketProductModified()\n        => editContext.NotifyFieldChanged(FieldIdentifier.Create(() => ticketProduct));\n\n    async Task SaveChangesAsync()\n    {\n        isSaving = true;\n        var productId = ticketProduct?.FirstOrDefault()?.ProductId;\n        var saveTask = Backend.UpdateTicketDetailsAsync(Ticket.TicketId, productId, ticketType, ticketStatus);\n        await Task.WhenAll(saveTask, Task.Delay(250));\n        editContext.MarkAsUnmodified();\n\n        // To avoid having the \"save\" button flash into existence before animating away,\n        // keep the spinner on screen for a further 1s, giving time for the animation to complete\n        StateHasChanged();\n        await Task.Delay(1000);\n        isSaving = false;\n    }\n\n    string TicketStatusDisplayText(TicketStatus status) => status switch\n    {\n        TicketStatus.Open => \"⏳ Open\",\n        TicketStatus.Closed => \"✅ Closed\",\n        _ => \"Unknown\"\n    };\n\n    string TicketTypeDisplayText(TicketType type) => type switch\n    {\n        TicketType.Question => \"❔ Question\",\n        TicketType.Idea => \"💭 Comment / idea\",\n        TicketType.Complaint => \"👎 Complaint\",\n        TicketType.Returns => \"📦 Returns\",\n        _ => \"Unknown\"\n    };\n\n    string FindProductDisplayText(FindProductsResult product) => $\"{product.Model} ({product.Brand})\";\n\n    async Task LookupProductAsync(OptionsSearchEventArgs<FindProductsResult> args)\n    {\n        args.Items = !string.IsNullOrWhiteSpace(args.Text) ? await Backend.FindProductsAsync(args.Text) : [];\n    }\n}\n"
  },
  {
    "path": "src/StaffWebUI/Components/Pages/Ticket/TicketDetails.razor.css",
    "content": "﻿.details-grid {\n    /* 1 or 2 columns, with min column width 12rem */\n    display: grid;\n    --details-grid-gap: 2rem;\n    grid-template-columns: repeat(auto-fill, minmax(max(12rem, calc(50% - calc(var(--details-grid-gap) / 2))), 1fr));\n    gap: 0.8rem var(--details-grid-gap);\n}\n\n.actions {\n    grid-column: 1 / -1;\n    display: flex;\n    justify-content: center;\n    align-items: center;\n    opacity: 0;\n    transform: scaleY(0);\n    height: 0;\n    transition-property: opacity transform height;\n    transition-timing-function: cubic-bezier(.16,.75,.35,1.02);\n    transition-duration: 0.3s;\n    transition-delay: 0.05s;\n}\n\n.modified .actions {\n    opacity: 1;\n    height: 2.75rem;\n    transform: scaleY(1);\n}\n\n/* The autocomplete shows a slightly odd empty list if there's no match, so hide it in that case */\n.product-picker ::deep fluent-anchored-region:not(:has(fluent-option)) {\n    opacity: 0;\n}\n"
  },
  {
    "path": "src/StaffWebUI/Components/Pages/Ticket/TicketMessages.razor",
    "content": "﻿@using Microsoft.FluentUI.AspNetCore.Components\n@using eShopSupport.ServiceDefaults.Clients.Backend\n\n@if (Ticket is null)\n{\n    <div class=\"loading-progress\">\n        <FluentProgress />\n    </div>\n}\nelse\n{\n    <div class=\"messages\">\n        @if (!string.IsNullOrEmpty(Ticket?.LongSummary))\n        {\n            <div class=\"summary\">\n                <div class=\"summary-text\">\n                    <div>💡</div>\n                    <div>\n                        <strong>Summary:</strong>\n                        @Ticket.LongSummary\n                    </div>\n                </div>\n            </div>\n        }\n\n        @foreach (var message in Ticket!.Messages)\n        {\n            <div class=\"message @(message.IsCustomerMessage ? \"customer\" : \"support\")\">\n                <div class=\"message-metadata\">\n                    <span class=\"timestamp\">@message.CreatedAt.ToShortDateString()</span>\n                    <span class=\"filler\">by</span>\n                    <span class=\"sender\">@(message.IsCustomerMessage ? Ticket.CustomerFullName : \"Support\")</span>\n                </div>\n                <div class=\"message-text\">@message.MessageText</div>\n            </div>\n        }\n    </div>\n}\n\n@code {\n    [Parameter]\n    public TicketDetailsResult? Ticket { get; set; }\n}\n"
  },
  {
    "path": "src/StaffWebUI/Components/Pages/Ticket/TicketMessages.razor.css",
    "content": "﻿.loading-progress {\n    width: 50%;\n    display: grid;\n    grid-gap: 12px;\n    grid-auto-flow: column;\n    height: 100%;\n    align-items: center;\n    margin: auto;\n}\n\n.messages {\n    display: flex;\n    flex-direction: column;\n    gap: 1rem;\n    align-items: flex-start;\n    padding-bottom: 2rem;\n    flex-grow: 1;\n}\n\n    .messages:not(:has(.summary)) {\n        padding-top: 1rem;\n    }\n\n.summary {\n    position: sticky;\n    top: 0;\n    align-self: stretch;\n    z-index: 1;\n    margin: 0 -1rem;\n    border-top: 0.5rem solid var(--neutral-layer-3);\n}\n\n.summary-text {\n    background-color: #393939;\n    color: white;\n    padding: 1rem 1.5rem 1rem 1rem;\n    box-shadow: var(--elevation-shadow-card-rest);\n    border-bottom: calc(var(--stroke-width)* 2px) solid var(--accent-fill-rest);\n    border-radius: calc(var(--layer-corner-radius) * 0.5px);\n    display: flex;\n    gap: 0.5rem;\n}\n\nhtml.dark-mode .summary-text {\n    background-color: #f3f3f3;\n    color: black;\n}\n\n    .summary-text div:first-child {\n        font-size: 125%;\n        width: min-content;\n    }\n\n    .message {\n        max-width: 90%;\n    }\n\n.message-text {\n    background: var(--fill-color);\n    color: var(--neutral-foreground-rest);\n    border: calc(var(--stroke-width)* 1px) solid var(--neutral-stroke-layer-rest);\n    border-radius: calc(var(--layer-corner-radius)* 2.5px);\n    box-shadow: var(--elevation-shadow-card-rest);\n    padding: calc(var(--design-unit)* 5px);\n    white-space: pre-line;\n    word-break: break-word;\n}\n\n.message.support {\n    align-self: flex-end;\n}\n\n.message.support .message-text {\n    border-color: var(--accent-fill-rest);\n    background-color: var(--accent-fill-rest);\n    color: var(--foreground-on-accent-rest);\n}\n\n.message-metadata {\n    margin: 0 0.5rem 0.15rem 0.5rem;\n    font-size: 90%;\n    opacity: 0.65;\n}\n\n    .message.support .message-metadata {\n        text-align: right;\n    }\n\n.message-metadata .timestamp, .message-metadata .sender {\n    font-weight: 500;\n}\n\n.message-metadata .filler {\n    opacity: 0.9;\n}"
  },
  {
    "path": "src/StaffWebUI/Components/Pages/Tickets/Columns/LinkPropertyColumn.cs",
    "content": "﻿using Microsoft.AspNetCore.Components;\nusing Microsoft.AspNetCore.Components.QuickGrid;\nusing Microsoft.AspNetCore.Components.Rendering;\n\nnamespace eShopSupport.StaffWebUI.Components.Pages.Tickets.Columns;\n\npublic class LinkPropertyColumn<TGridItem, TProp> : PropertyColumn<TGridItem, TProp>\n{\n    [Parameter]\n    public required Func<TGridItem, string>? Href { get; set; }\n\n    protected override void CellContent(RenderTreeBuilder builder, TGridItem item)\n    {\n        builder.OpenElement(0, \"a\");\n        builder.AddAttribute(1, \"class\", \"link-col\");\n        builder.AddAttribute(2, \"href\", Href?.Invoke(item));\n        builder.OpenRegion(3);\n        base.CellContent(builder, item);\n        builder.CloseRegion();\n        builder.CloseElement();\n    }\n}\n"
  },
  {
    "path": "src/StaffWebUI/Components/Pages/Tickets/Columns/LinkTemplateColumn.cs",
    "content": "﻿using Microsoft.AspNetCore.Components;\nusing Microsoft.AspNetCore.Components.QuickGrid;\nusing Microsoft.AspNetCore.Components.Rendering;\n\nnamespace eShopSupport.StaffWebUI.Components.Pages.Tickets.Columns;\n\npublic class LinkTemplateColumn<TGridItem> : TemplateColumn<TGridItem>\n{\n    [Parameter]\n    public required Func<TGridItem, string>? Href { get; set; }\n\n    protected override void CellContent(RenderTreeBuilder builder, TGridItem item)\n    {\n        builder.OpenElement(0, \"a\");\n        builder.AddAttribute(1, \"class\", \"link-col\");\n        builder.AddAttribute(2, \"href\", Href?.Invoke(item));\n        builder.OpenRegion(3);\n        base.CellContent(builder, item);\n        builder.CloseRegion();\n        builder.CloseElement();\n    }\n}\n"
  },
  {
    "path": "src/StaffWebUI/Components/Pages/Tickets/SatisfactionIndicator.razor",
    "content": "﻿@if (Satisfaction.HasValue)\n{\n    <progress max=\"9\" value=\"@Satisfaction\" title=\"Satisfaction: @Satisfaction\"></progress>\n}\n@code {\n    [Parameter]\n    public int? Satisfaction { get; set; }\n}\n"
  },
  {
    "path": "src/StaffWebUI/Components/Pages/Tickets/SatisfactionIndicator.razor.css",
    "content": "﻿progress {\n    width: 1.9rem;\n    height: 0.7rem;\n    --accent-color: gray;\n    --accent-color-low: #ed4242;\n    --accent-color-medium: #ff9a0f;\n    --accent-color-high: #1da51d;\n    border: 1.5px solid var(--accent-color);\n    border-radius: 0.5rem;\n    overflow: hidden;\n}\n\nhtml.dark-mode progress {\n    --accent-color-low: #ff3b3b;\n    --accent-color-medium: #ffa427;\n    --accent-color-high: #56ca56;\n}\n\nprogress::-webkit-progress-bar {\n    background: none;\n}\n\nprogress::-webkit-progress-value {\n    background-color: var(--accent-color);\n}\n\nprogress[value=\"0\"], progress[value=\"1\"] {\n    --accent-color: var(--accent-color-low);\n}\n\nprogress[value=\"2\"], progress[value=\"3\"] {\n    --accent-color: var(--accent-color-medium);\n}\n\nprogress[value=\"4\"], progress[value=\"5\"], progress[value=\"6\"], progress[value=\"7\"], progress[value=\"8\"], progress[value=\"9\"] {\n    --accent-color: var(--accent-color-high);\n}\n"
  },
  {
    "path": "src/StaffWebUI/Components/Pages/Tickets/Tickets.razor",
    "content": "﻿@page \"/\"\n@inherits RedisSubscribingComponent\n@using Microsoft.AspNetCore.Components.QuickGrid\n@using StackExchange.Redis\n@using eShopSupport.ServiceDefaults.Clients.Backend\n@using eShopSupport.StaffWebUI.Components.Pages.Tickets.Columns\n@inject StaffBackendClient Backend\n@inject NavigationManager Nav\n@inject IJSRuntime JS\n\n<Title>Tickets</Title>\n\n<div class=\"tickets-page ensure-page-scrollbar\">\n    <TicketsFilter @bind-Filter=\"@filter\" @bind-Filter:after=\"@OnFilterChangedAsync\" TotalOpenCount=\"@totalOpenCount\" TotalClosedCount=\"@totalClosedCount\" />\n    <QuickGrid @ref=\"ticketsGrid\" TGridItem=\"ListTicketsResultItem\" ItemKey=\"@(t => t.TicketId)\" Virtualize=\"true\" ItemSize=\"34\" ItemsProvider=\"@TicketsProvider\" Class=\"tickets-grid\">\n        <ChildContent>\n            <LinkPropertyColumn Href=\"@TicketHref\" Title=\"#\" Property=\"@(t => t.TicketId)\" Sortable=\"true\" Align=\"Align.Center\" Class=\"ticket-id\" IsDefaultSortColumn=\"true\" InitialSortDirection=\"@SortDirection.Descending\" />\n            <LinkPropertyColumn Href=\"@TicketHref\" Title=\"Customer\" Property=\"@(t => t.CustomerFullName)\" Sortable=\"true\" Class=\"ticket-customer\" />\n            <LinkTemplateColumn Href=\"@TicketHref\" Title=\"Summary\" Class=\"ticket-summary\">\n                @TicketTypeIcon(context)\n                <span class=\"spacer\"></span>\n                @context.ShortSummary\n            </LinkTemplateColumn>\n            <LinkTemplateColumn Href=\"@TicketHref\" Title=\"Satisfaction\" Align=\"Align.Center\" SortBy=\"@SortBySatisfaction\" Class=\"ticket-satisfaction\">\n                <SatisfactionIndicator Satisfaction=\"@context.CustomerSatisfaction\" />\n            </LinkTemplateColumn>\n            <LinkPropertyColumn Href=\"@TicketHref\" Title=\"Messages\" Property=\"@(t => t.NumMessages)\" Sortable=\"true\" Align=\"Align.Center\" Class=\"ticket-messages\" />\n        </ChildContent>\n    </QuickGrid>\n\n    @if (totalOpenCount == null && totalClosedCount == null)\n    {\n        <Microsoft.FluentUI.AspNetCore.Components.FluentProgress Class=\"tickets-loading\" />\n    }\n</div>\n\n@code {\n    private readonly GridItemsProvider<ListTicketsResultItem> TicketsProvider;\n    private readonly static Func<ListTicketsResultItem, string> TicketHref = t => $\"ticket/{t.TicketId}\";\n    private readonly static GridSort<ListTicketsResultItem> SortBySatisfaction = GridSort<ListTicketsResultItem>.ByAscending(x => x.CustomerSatisfaction);\n    private QuickGrid<ListTicketsResultItem>? ticketsGrid;\n    private int? totalOpenCount, totalClosedCount;\n    private Filter filter = default!;\n\n    public Tickets()\n    {\n        TicketsProvider = async request =>\n        {\n            var sortColumn = request.GetSortByProperties().FirstOrDefault();\n            var categoryIds = filter.Categories.Select(c => c.CategoryId).ToList();\n            var result = await Backend.ListTicketsAsync(new(filter.Status, categoryIds, null, request.StartIndex, request.Count ?? 100, sortColumn.PropertyName, sortColumn.Direction == SortDirection.Ascending));\n\n            if (result.TotalOpenCount != totalOpenCount || result.TotalClosedCount != totalClosedCount)\n            {\n                // Because this callback is outside the render cycle for this component\n                // we have to notify the framework if its state changes\n                totalOpenCount = result.TotalOpenCount;\n                totalClosedCount = result.TotalClosedCount;\n                StateHasChanged();\n            }\n\n            return new() { Items = result.Items, TotalItemCount = result.TotalCount };\n        };\n    }\n\n    protected override void OnInitialized()\n    {\n        SubscriptionChannel = RedisChannel.Pattern(\"ticket:*\");\n    }\n\n    async Task OnFilterChangedAsync()\n    {\n        await JS.InvokeVoidAsync(\"scrollToTop\");\n\n        if (ticketsGrid is not null)\n        {\n            await ticketsGrid.RefreshDataAsync();\n        }\n    }\n\n    static string TicketTypeIcon(ListTicketsResultItem ticket) => ticket.TicketType switch\n    {\n        TicketType.Idea => \"💭\",\n        TicketType.Question => \"❔\",\n        TicketType.Complaint => \"👎\",\n        TicketType.Returns => \"📦\",\n        _ => string.Empty,\n    };\n\n    public record Filter(TicketStatus Status, IEnumerable<FindCategoriesResult> Categories);\n\n    protected override Task OnRedisNotificationAsync(RedisValue value)\n        => ticketsGrid?.RefreshDataAsync() ?? Task.CompletedTask;\n}\n"
  },
  {
    "path": "src/StaffWebUI/Components/Pages/Tickets/Tickets.razor.css",
    "content": "﻿.tickets-page {\n    --filter-bar-height: 3.25rem;\n}\n\n::deep .tickets-grid {\n    table-layout: fixed;\n    border-collapse: separate;\n    border-spacing: 0;\n    width: 100%;\n    --col-gap: 0.1rem;\n}\n\n::deep thead {\n    position: sticky;\n    top: calc(var(--header-height) + var(--filter-bar-height));\n    background: var(--neutral-fill-stealth-active);\n    z-index: 1;\n    border-bottom: 1px solid silver;\n}\n\n::deep .col-title {\n    font-weight: 600 !important;\n    padding: 0.4rem 0.8rem !important;\n}\n\n::deep .tickets-grid td {\n    border-bottom: calc(var(--stroke-width)* 1px) solid var(--neutral-stroke-divider-rest);\n    height: 34px;\n}\n\n::deep th {\n    padding: 0 0 0.2rem 0;\n    border-bottom: calc(var(--stroke-width)* 1px) solid var(--neutral-layer-4);\n}\n\n    ::deep th.ticket-id {\n        width: 100px;\n    }\n\n    ::deep th.ticket-satisfaction {\n        width: 120px;\n    }\n\n    ::deep th.ticket-messages {\n        width: 120px;\n    }\n\n    ::deep th.ticket-customer {\n        width: 20%;\n    }\n\n    ::deep th.ticket-summary {\n        width: 60%;\n    }\n\n::deep .tickets-grid tbody > tr > td {\n    white-space: nowrap;\n    padding-left: 0.8rem;\n}\n\n::deep .tickets-grid thead > tr > th button {\n    border-radius: calc(var(--control-corner-radius)* 1px);\n    color: var(--neutral-foreground-rest);\n    padding: 0.4rem 0.8rem !important;\n}\n\n::deep .sort-indicator {\n    display: none;\n}\n\n::deep th.col-sort-asc .sort-indicator, ::deep th.col-sort-desc .sort-indicator {\n    display: block;\n    background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' slot='end' style='width: 24px; stroke-width:0.5px; stroke: rgb(45,156,230); fill:rgb(45,156,230)' focusable='false' viewBox='0 0 24 24' aria-hidden='true'%3E%3C!--!--%3E%3Cpath d='M11.65 4h.1c.38 0 .7.28.74.65l.01.1v12.7l3.22-3.23c.27-.26.68-.29.98-.07l.08.07c.27.27.3.69.07.98l-.07.09-4.5 4.5a.75.75 0 0 1-.97.07l-.09-.07-4.5-4.5a.75.75 0 0 1 .98-1.14l.08.07L11 17.44V4.75c0-.38.28-.7.65-.74l.1-.01h-.1Z'%3E%3C/path%3E%3C/svg%3E%0A\");\n    opacity: 1;\n}\n\n::deep tbody tr:hover {\n    background: var(--neutral-fill-stealth-hover);\n}\n\n::deep .link-col {\n    display: block;\n    text-decoration: none;\n    color: var(--neutral-foreground-rest);\n    margin: -0.4rem;\n    padding: 0.4rem;\n    text-overflow: ellipsis;\n    overflow: hidden;\n}\n\n::deep .ticket-summary {\n    filter: saturate(0.7);\n}\n\n.spacer {\n    display: inline-block;\n}\n\n::deep .tickets-loading {\n    margin: 20vh auto;\n    width: 50vw;\n}\n"
  },
  {
    "path": "src/StaffWebUI/Components/Pages/Tickets/TicketsFilter.razor",
    "content": "﻿@using Microsoft.FluentUI.AspNetCore.Components\n@using eShopSupport.ServiceDefaults.Clients.Backend\n@inject StaffBackendClient Backend\n@inject NavigationManager Nav\n\n<div class=\"filter\">\n    <FluentTabs Style=\"flex-grow: 1\" @bind-ActiveTabId:get=\"@(Filter.Status == TicketStatus.Open ? OpenTabId : ClosedTabId)\" @bind-ActiveTabId:set=\"SetActiveTabId\">\n        <FluentTab Id=\"@OpenTabId\" Label=\"@OpenLabel\" Icon=\"@(new Icons.Regular.Size20.Mail())\" />\n        <FluentTab Id=\"@ClosedTabId\" Label=\"@ClosedLabel\" Icon=\"@(new Icons.Regular.Size20.Checkmark())\" />\n    </FluentTabs>\n\n    <FluentAutocomplete Width=\"\" TOption=\"FindCategoriesResult\"\n        @bind-SelectedOptions:get=\"@Filter.Categories\" @bind-SelectedOptions:set=\"SetSelectedCategories\"\n        MaximumSelectedOptions=\"3\" Placeholder=\"Filter by category\" OptionText=\"@(x => x.Name)\"\n        OnOptionsSearch=\"LookupCategoriesAsync\" style=\"min-width: 12rem;\" />\n</div>\n\n@code {\n    private IEnumerable<FindCategoriesResult> selectedCategories = Array.Empty<FindCategoriesResult>();\n    private const string OpenTabId = \"filter-open\";\n    private const string ClosedTabId = \"filter-closed\";\n\n    [Parameter, EditorRequired]\n    public Tickets.Filter Filter { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback<Tickets.Filter> FilterChanged { get; set; }\n\n    [Parameter]\n    public int? TotalOpenCount { get; set; }\n\n    [Parameter]\n    public int? TotalClosedCount { get; set; }\n\n    [SupplyParameterFromQuery(Name = \"status\")]\n    public string? InitialFilterStatus { get; set; }\n\n    [SupplyParameterFromQuery(Name = \"categories\")]\n    public string? InitialFilterCategoryIds { get; set; }\n\n    private string OpenLabel => $\"{TotalOpenCount} Open\";\n\n    private string ClosedLabel => $\"{TotalClosedCount} Closed\";\n\n    protected override async Task OnInitializedAsync()\n    {\n        var filterStatus = Enum.TryParse<TicketStatus>(InitialFilterStatus, out var status) ? status : TicketStatus.Open;\n\n        var filterCategories = new List<FindCategoriesResult>();\n        if (!string.IsNullOrEmpty(InitialFilterCategoryIds))\n        {\n            foreach (var idText in InitialFilterCategoryIds.Split('-'))\n            {\n                if (int.TryParse(idText, out var id))\n                {\n                    // We don't know the category names, but will load them asynchronously later\n                    filterCategories.Add(new(id) { Name = \"...\" });\n                }\n            }\n        }\n\n        await FilterChanged.InvokeAsync(new(filterStatus, filterCategories));\n\n        // Now in the background we can load the category names\n        var categoryNames = await Backend.FindCategoriesAsync(filterCategories.Select(x => x.CategoryId));\n        var categoryNamesById = categoryNames.ToDictionary(x => x.CategoryId);\n        foreach (var filterCategory in filterCategories)\n        {\n            if (categoryNamesById.TryGetValue(filterCategory.CategoryId, out var name))\n            {\n                filterCategory.Name = name.Name;\n            }\n        }\n    }\n\n    Task SetActiveTabId(string id)\n    {\n        var newFilter = Filter with { Status = (id == OpenTabId ? TicketStatus.Open : TicketStatus.Closed) };\n        UpdateUrl(newFilter);\n        return FilterChanged.InvokeAsync(newFilter);\n    }\n\n    async Task LookupCategoriesAsync(OptionsSearchEventArgs<FindCategoriesResult> args)\n    {\n        args.Items = !string.IsNullOrWhiteSpace(args.Text) ? await Backend.FindCategoriesAsync(args.Text) : [];\n    }\n\n    Task SetSelectedCategories(IEnumerable<FindCategoriesResult> values)\n    {\n        var newFilter = Filter with { Categories = values };\n        UpdateUrl(newFilter);\n        return FilterChanged.InvokeAsync(newFilter);\n    }\n\n    void UpdateUrl(Tickets.Filter filter)\n    {\n        // By storing the current filter in the URL, we make it bookmarkable/linkable\n        var categoriesUrlParam = string.Join(\"-\", filter.Categories.Select(c => c.CategoryId));\n        Nav.NavigateTo(Nav.GetUriWithQueryParameters(new Dictionary<string, object?>\n        {\n            { \"status\", filter.Status is TicketStatus.Open ? null : filter.Status.ToString() },\n            { \"categories\", categoriesUrlParam is \"\" ? null : categoriesUrlParam },\n        }), replace: true);\n    }\n}\n"
  },
  {
    "path": "src/StaffWebUI/Components/Pages/Tickets/TicketsFilter.razor.css",
    "content": "﻿.filter {\n    height: var(--filter-bar-height);\n    position: sticky;\n    top: var(--header-height);\n    background: var(--neutral-fill-stealth-active);\n    z-index: 2;\n    padding: 0 1.5rem;\n    display: flex;\n    align-items: center;\n}\n\n::deep fluent-tab {\n    margin-right: 1rem;\n}\n\n::deep .fluent-tab-icon {\n    margin-right: 0.5rem;\n}\n\n::deep fluent-tabs::part(activeIndicator) {\n    width: calc(100% - 1rem);\n    justify-self: start;\n    align-self: center;\n}\n\n/* The autocomplete shows a slightly odd empty list if there's no match, so hide it in that case */\n::deep fluent-anchored-region:not(:has(fluent-option)) {\n    opacity: 0;\n}\n"
  },
  {
    "path": "src/StaffWebUI/Components/Routes.razor",
    "content": "﻿@using Microsoft.AspNetCore.Components.Authorization\n<StatefulReconnection />\n<Router AppAssembly=\"typeof(Program).Assembly\">\n    <Found Context=\"routeData\">\n        <AuthorizeRouteView RouteData=\"routeData\" DefaultLayout=\"typeof(Layout.MainLayout)\">\n            <NotAuthorized>\n                <eShopSupport.StaffWebUI.Components.Pages.Account.AccessDenied />\n            </NotAuthorized>\n        </AuthorizeRouteView>\n        <FocusOnNavigate RouteData=\"routeData\" Selector=\"h1\" />\n    </Found>\n</Router>\n"
  },
  {
    "path": "src/StaffWebUI/Components/_Imports.razor",
    "content": "﻿@using System.Net.Http\n@using System.Net.Http.Json\n@using Microsoft.AspNetCore.Authorization\n@using Microsoft.AspNetCore.Components.Forms\n@using Microsoft.AspNetCore.Components.Routing\n@using Microsoft.AspNetCore.Components.Web\n@using static Microsoft.AspNetCore.Components.Web.RenderMode\n@using Microsoft.AspNetCore.Components.Web.Virtualization\n@using Microsoft.JSInterop\n@using eShopSupport.StaffWebUI\n@using eShopSupport.StaffWebUI.Components\n@using eShopSupport.StaffWebUI.Components.Layout\n@using Microsoft.AspNetCore.Components.Sections\n\n@attribute [Authorize(Roles = \"staff\")]\n"
  },
  {
    "path": "src/StaffWebUI/Program.cs",
    "content": "﻿using eShopSupport.ServiceDefaults;\nusing eShopSupport.ServiceDefaults.Clients.Backend;\nusing eShopSupport.StaffWebUI.Components;\nusing Microsoft.AspNetCore.Authentication;\nusing Microsoft.AspNetCore.Authentication.Cookies;\nusing Microsoft.AspNetCore.Authentication.OpenIdConnect;\nusing Microsoft.FluentUI.AspNetCore.Components;\n\nvar builder = WebApplication.CreateBuilder(args);\n\n// Add service defaults & Aspire components.\nbuilder.AddServiceDefaults();\n\n// Add services to the container.\nbuilder.Services.AddRazorComponents()\n    .AddInteractiveServerComponents();\n\nbuilder.Services.AddFluentUIComponents();\n\nbuilder.Services.AddHttpClient<StaffBackendClient>(client =>\n    client.BaseAddress = new Uri(\"http://backend/\")).AddAuthToken();\n\nbuilder.Services.AddCascadingAuthenticationState();\nbuilder.Services.AddAuthorization();\nbuilder.Services.AddAuthentication(options =>\n{\n    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;\n    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;\n})\n    .AddCookie()\n    .AddOpenIdConnect(options =>\n    {\n        options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;\n        options.Authority = builder.Configuration[\"IdentityUrl\"];\n        options.ClientId = \"staff-webui\";\n        options.ClientSecret = \"staff-webui-secret\";\n        options.ResponseType = \"code\";\n        options.SaveTokens = true;\n        options.GetClaimsFromUserInfoEndpoint = true;\n        options.TokenValidationParameters.NameClaimType = \"name\";\n        options.TokenValidationParameters.RoleClaimType = \"role\";\n        options.ClaimActions.MapUniqueJsonKey(\"role\", \"role\");\n\n        options.Scope.Clear();\n        options.Scope.Add(\"openid\");\n        options.Scope.Add(\"profile\");\n        options.Scope.Add(\"staff-api\");\n        options.Scope.Add(\"role\");\n    });\n\nbuilder.AddRedisClient(\"redis\");\n\nvar app = builder.Build();\n\n// Configure the HTTP request pipeline.\nif (!app.Environment.IsDevelopment())\n{\n    app.UseExceptionHandler(\"/Error\", createScopeForErrors: true);\n    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.\n    app.UseHsts();\n}\n\napp.UseAuthentication();\napp.UseAuthorization();\n\napp.UseHttpsRedirection();\n\napp.UseStaticFiles();\napp.UseAntiforgery();\n\napp.MapRazorComponents<App>()\n    .AddInteractiveServerRenderMode();\n\napp.MapGet(\"/manual\", async (string file, StaffBackendClient backend, CancellationToken cancellationToken) =>\n{\n    var result = await backend.ReadManualAsync(file, cancellationToken);\n    return result is null ? Results.NotFound() : Results.Stream(result, \"application/pdf\");\n});\n\napp.MapGet(\"/user/signout\", async (HttpContext httpContext) =>\n{\n    await httpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);\n    await httpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme);\n}).AllowAnonymous();\n\napp.Run();\n"
  },
  {
    "path": "src/StaffWebUI/Properties/launchSettings.json",
    "content": "{\n  \"$schema\": \"http://json.schemastore.org/launchsettings.json\",\n    \"profiles\": {\n      \"https\": {\n        \"commandName\": \"Project\",\n        \"dotnetRunMessages\": true,\n        \"launchBrowser\": true,\n        \"applicationUrl\": \"https://localhost:7273\",\n        \"environmentVariables\": {\n          \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n        }\n      }\n    }\n  }\n"
  },
  {
    "path": "src/StaffWebUI/StaffWebUI.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n  <PropertyGroup>\n    <TargetFramework>net8.0</TargetFramework>\n    <Nullable>enable</Nullable>\n    <ImplicitUsings>enable</ImplicitUsings>\n    <RootNamespace>eShopSupport.StaffWebUI</RootNamespace>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Aspire.StackExchange.Redis\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.Authentication.OpenIdConnect\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.Components.QuickGrid\" />\n    <PackageReference Include=\"Microsoft.FluentUI.AspNetCore.Components\" />\n    <PackageReference Include=\"Microsoft.FluentUI.AspNetCore.Components.DataGrid.EntityFrameworkAdapter\" />\n    <PackageReference Include=\"Microsoft.FluentUI.AspNetCore.Components.Icons\" />\n    <PackageReference Include=\"StatefulReconnection\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\ServiceDefaults\\ServiceDefaults.csproj\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/StaffWebUI/appsettings.Development.json",
    "content": "{\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Information\",\n      \"Microsoft.AspNetCore\": \"Warning\"\n    }\n  },\n  \"DetailedErrors\": true\n}\n"
  },
  {
    "path": "src/StaffWebUI/appsettings.json",
    "content": "{\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Information\",\n      \"Microsoft.AspNetCore\": \"Warning\"\n    }\n  },\n  \"AllowedHosts\": \"*\"\n}\n"
  },
  {
    "path": "src/StaffWebUI/wwwroot/app.css",
    "content": "html.dark-mode {\n    /* Affects scrollbar style */\n    color-scheme: dark;\n}\n\nhtml:has(.ensure-page-scrollbar) {\n    overflow-y: scroll;\n}\n\nh1:focus {\n    outline: none;\n}\n\n.invalid {\n    outline: 1px solid #e50000;\n}\n\n.validation-message {\n    color: #e50000;\n}\n\n.blazor-error-boundary {\n    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;\n    padding: 1rem 1rem 1rem 3.7rem;\n    color: white;\n}\n\n    .blazor-error-boundary::after {\n        content: \"An error has occurred.\"\n    }\n\n.darker-border-checkbox.form-check-input {\n    border-color: #929292;\n}\n"
  },
  {
    "path": "src/StaffWebUI/wwwroot/manual.html",
    "content": "﻿<!DOCTYPE html>\n<html>\n<body>\n    <iframe frameborder=\"0\"></iframe>\n    <style type=\"text/css\">\n        body, html { margin: 0; padding: 0; overflow: hidden; }\n        iframe { inset: 0; width: 100vw; height: 100vh; }\n    </style>\n    <script>\n        const params = new URL(location.href).searchParams;\n        const iframe = document.querySelector('iframe');\n        const query = { file: `/manual?file=${encodeURIComponent(params.get('file'))}` };\n        const hash = { page: params.get('page'), search: params.get('search'), phrase: true, zoom: '100%' };\n        iframe.src = 'pdfjs-4.2.67-dist/web/viewer.html?' + new URLSearchParams(query).toString() + '#' + new URLSearchParams(hash).toString();\n        iframe.focus();\n    </script>\n</body>\n</html>\n"
  },
  {
    "path": "src/StaffWebUI/wwwroot/pdfjs-4.2.67-dist/LICENSE",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n"
  },
  {
    "path": "src/StaffWebUI/wwwroot/pdfjs-4.2.67-dist/build/pdf.mjs",
    "content": "/**\n * @licstart The following is the entire license notice for the\n * JavaScript code in this page\n *\n * Copyright 2023 Mozilla Foundation\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 * @licend The above is the entire license notice for the\n * JavaScript code in this page\n */\n\n/******/ var __webpack_modules__ = ({\n\n/***/ 976:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, {\n  AnnotationLayer: () => (/* binding */ AnnotationLayer),\n  FreeTextAnnotationElement: () => (/* binding */ FreeTextAnnotationElement),\n  InkAnnotationElement: () => (/* binding */ InkAnnotationElement),\n  StampAnnotationElement: () => (/* binding */ StampAnnotationElement)\n});\n\n// EXTERNAL MODULE: ./src/shared/util.js\nvar util = __webpack_require__(292);\n// EXTERNAL MODULE: ./src/display/display_utils.js\nvar display_utils = __webpack_require__(419);\n// EXTERNAL MODULE: ./src/display/annotation_storage.js\nvar annotation_storage = __webpack_require__(792);\n;// CONCATENATED MODULE: ./src/shared/scripting_utils.js\nfunction makeColorComp(n) {\n  return Math.floor(Math.max(0, Math.min(1, n)) * 255).toString(16).padStart(2, \"0\");\n}\nfunction scaleAndClamp(x) {\n  return Math.max(0, Math.min(255, 255 * x));\n}\nclass ColorConverters {\n  static CMYK_G([c, y, m, k]) {\n    return [\"G\", 1 - Math.min(1, 0.3 * c + 0.59 * m + 0.11 * y + k)];\n  }\n  static G_CMYK([g]) {\n    return [\"CMYK\", 0, 0, 0, 1 - g];\n  }\n  static G_RGB([g]) {\n    return [\"RGB\", g, g, g];\n  }\n  static G_rgb([g]) {\n    g = scaleAndClamp(g);\n    return [g, g, g];\n  }\n  static G_HTML([g]) {\n    const G = makeColorComp(g);\n    return `#${G}${G}${G}`;\n  }\n  static RGB_G([r, g, b]) {\n    return [\"G\", 0.3 * r + 0.59 * g + 0.11 * b];\n  }\n  static RGB_rgb(color) {\n    return color.map(scaleAndClamp);\n  }\n  static RGB_HTML(color) {\n    return `#${color.map(makeColorComp).join(\"\")}`;\n  }\n  static T_HTML() {\n    return \"#00000000\";\n  }\n  static T_rgb() {\n    return [null];\n  }\n  static CMYK_RGB([c, y, m, k]) {\n    return [\"RGB\", 1 - Math.min(1, c + k), 1 - Math.min(1, m + k), 1 - Math.min(1, y + k)];\n  }\n  static CMYK_rgb([c, y, m, k]) {\n    return [scaleAndClamp(1 - Math.min(1, c + k)), scaleAndClamp(1 - Math.min(1, m + k)), scaleAndClamp(1 - Math.min(1, y + k))];\n  }\n  static CMYK_HTML(components) {\n    const rgb = this.CMYK_RGB(components).slice(1);\n    return this.RGB_HTML(rgb);\n  }\n  static RGB_CMYK([r, g, b]) {\n    const c = 1 - r;\n    const m = 1 - g;\n    const y = 1 - b;\n    const k = Math.min(c, m, y);\n    return [\"CMYK\", c, m, y, k];\n  }\n}\n\n// EXTERNAL MODULE: ./src/display/xfa_layer.js\nvar xfa_layer = __webpack_require__(284);\n;// CONCATENATED MODULE: ./src/display/annotation_layer.js\n\n\n\n\n\nconst DEFAULT_TAB_INDEX = 1000;\nconst DEFAULT_FONT_SIZE = 9;\nconst GetElementsByNameSet = new WeakSet();\nfunction getRectDims(rect) {\n  return {\n    width: rect[2] - rect[0],\n    height: rect[3] - rect[1]\n  };\n}\nclass AnnotationElementFactory {\n  static create(parameters) {\n    const subtype = parameters.data.annotationType;\n    switch (subtype) {\n      case util.AnnotationType.LINK:\n        return new LinkAnnotationElement(parameters);\n      case util.AnnotationType.TEXT:\n        return new TextAnnotationElement(parameters);\n      case util.AnnotationType.WIDGET:\n        const fieldType = parameters.data.fieldType;\n        switch (fieldType) {\n          case \"Tx\":\n            return new TextWidgetAnnotationElement(parameters);\n          case \"Btn\":\n            if (parameters.data.radioButton) {\n              return new RadioButtonWidgetAnnotationElement(parameters);\n            } else if (parameters.data.checkBox) {\n              return new CheckboxWidgetAnnotationElement(parameters);\n            }\n            return new PushButtonWidgetAnnotationElement(parameters);\n          case \"Ch\":\n            return new ChoiceWidgetAnnotationElement(parameters);\n          case \"Sig\":\n            return new SignatureWidgetAnnotationElement(parameters);\n        }\n        return new WidgetAnnotationElement(parameters);\n      case util.AnnotationType.POPUP:\n        return new PopupAnnotationElement(parameters);\n      case util.AnnotationType.FREETEXT:\n        return new FreeTextAnnotationElement(parameters);\n      case util.AnnotationType.LINE:\n        return new LineAnnotationElement(parameters);\n      case util.AnnotationType.SQUARE:\n        return new SquareAnnotationElement(parameters);\n      case util.AnnotationType.CIRCLE:\n        return new CircleAnnotationElement(parameters);\n      case util.AnnotationType.POLYLINE:\n        return new PolylineAnnotationElement(parameters);\n      case util.AnnotationType.CARET:\n        return new CaretAnnotationElement(parameters);\n      case util.AnnotationType.INK:\n        return new InkAnnotationElement(parameters);\n      case util.AnnotationType.POLYGON:\n        return new PolygonAnnotationElement(parameters);\n      case util.AnnotationType.HIGHLIGHT:\n        return new HighlightAnnotationElement(parameters);\n      case util.AnnotationType.UNDERLINE:\n        return new UnderlineAnnotationElement(parameters);\n      case util.AnnotationType.SQUIGGLY:\n        return new SquigglyAnnotationElement(parameters);\n      case util.AnnotationType.STRIKEOUT:\n        return new StrikeOutAnnotationElement(parameters);\n      case util.AnnotationType.STAMP:\n        return new StampAnnotationElement(parameters);\n      case util.AnnotationType.FILEATTACHMENT:\n        return new FileAttachmentAnnotationElement(parameters);\n      default:\n        return new AnnotationElement(parameters);\n    }\n  }\n}\nclass AnnotationElement {\n  #updates = null;\n  #hasBorder = false;\n  constructor(parameters, {\n    isRenderable = false,\n    ignoreBorder = false,\n    createQuadrilaterals = false\n  } = {}) {\n    this.isRenderable = isRenderable;\n    this.data = parameters.data;\n    this.layer = parameters.layer;\n    this.linkService = parameters.linkService;\n    this.downloadManager = parameters.downloadManager;\n    this.imageResourcesPath = parameters.imageResourcesPath;\n    this.renderForms = parameters.renderForms;\n    this.svgFactory = parameters.svgFactory;\n    this.annotationStorage = parameters.annotationStorage;\n    this.enableScripting = parameters.enableScripting;\n    this.hasJSActions = parameters.hasJSActions;\n    this._fieldObjects = parameters.fieldObjects;\n    this.parent = parameters.parent;\n    if (isRenderable) {\n      this.container = this._createContainer(ignoreBorder);\n    }\n    if (createQuadrilaterals) {\n      this._createQuadrilaterals();\n    }\n  }\n  static _hasPopupData({\n    titleObj,\n    contentsObj,\n    richText\n  }) {\n    return !!(titleObj?.str || contentsObj?.str || richText?.str);\n  }\n  get hasPopupData() {\n    return AnnotationElement._hasPopupData(this.data);\n  }\n  updateEdited(params) {\n    if (!this.container) {\n      return;\n    }\n    this.#updates ||= {\n      rect: this.data.rect.slice(0)\n    };\n    const {\n      rect\n    } = params;\n    if (rect) {\n      this.#setRectEdited(rect);\n    }\n  }\n  resetEdited() {\n    if (!this.#updates) {\n      return;\n    }\n    this.#setRectEdited(this.#updates.rect);\n    this.#updates = null;\n  }\n  #setRectEdited(rect) {\n    const {\n      container: {\n        style\n      },\n      data: {\n        rect: currentRect,\n        rotation\n      },\n      parent: {\n        viewport: {\n          rawDims: {\n            pageWidth,\n            pageHeight,\n            pageX,\n            pageY\n          }\n        }\n      }\n    } = this;\n    currentRect?.splice(0, 4, ...rect);\n    const {\n      width,\n      height\n    } = getRectDims(rect);\n    style.left = `${100 * (rect[0] - pageX) / pageWidth}%`;\n    style.top = `${100 * (pageHeight - rect[3] + pageY) / pageHeight}%`;\n    if (rotation === 0) {\n      style.width = `${100 * width / pageWidth}%`;\n      style.height = `${100 * height / pageHeight}%`;\n    } else {\n      this.setRotation(rotation);\n    }\n  }\n  _createContainer(ignoreBorder) {\n    const {\n      data,\n      parent: {\n        page,\n        viewport\n      }\n    } = this;\n    const container = document.createElement(\"section\");\n    container.setAttribute(\"data-annotation-id\", data.id);\n    if (!(this instanceof WidgetAnnotationElement)) {\n      container.tabIndex = DEFAULT_TAB_INDEX;\n    }\n    const {\n      style\n    } = container;\n    style.zIndex = this.parent.zIndex++;\n    if (data.popupRef) {\n      container.setAttribute(\"aria-haspopup\", \"dialog\");\n    }\n    if (data.alternativeText) {\n      container.title = data.alternativeText;\n    }\n    if (data.noRotate) {\n      container.classList.add(\"norotate\");\n    }\n    if (!data.rect || this instanceof PopupAnnotationElement) {\n      const {\n        rotation\n      } = data;\n      if (!data.hasOwnCanvas && rotation !== 0) {\n        this.setRotation(rotation, container);\n      }\n      return container;\n    }\n    const {\n      width,\n      height\n    } = getRectDims(data.rect);\n    if (!ignoreBorder && data.borderStyle.width > 0) {\n      style.borderWidth = `${data.borderStyle.width}px`;\n      const horizontalRadius = data.borderStyle.horizontalCornerRadius;\n      const verticalRadius = data.borderStyle.verticalCornerRadius;\n      if (horizontalRadius > 0 || verticalRadius > 0) {\n        const radius = `calc(${horizontalRadius}px * var(--scale-factor)) / calc(${verticalRadius}px * var(--scale-factor))`;\n        style.borderRadius = radius;\n      } else if (this instanceof RadioButtonWidgetAnnotationElement) {\n        const radius = `calc(${width}px * var(--scale-factor)) / calc(${height}px * var(--scale-factor))`;\n        style.borderRadius = radius;\n      }\n      switch (data.borderStyle.style) {\n        case util.AnnotationBorderStyleType.SOLID:\n          style.borderStyle = \"solid\";\n          break;\n        case util.AnnotationBorderStyleType.DASHED:\n          style.borderStyle = \"dashed\";\n          break;\n        case util.AnnotationBorderStyleType.BEVELED:\n          (0,util.warn)(\"Unimplemented border style: beveled\");\n          break;\n        case util.AnnotationBorderStyleType.INSET:\n          (0,util.warn)(\"Unimplemented border style: inset\");\n          break;\n        case util.AnnotationBorderStyleType.UNDERLINE:\n          style.borderBottomStyle = \"solid\";\n          break;\n        default:\n          break;\n      }\n      const borderColor = data.borderColor || null;\n      if (borderColor) {\n        this.#hasBorder = true;\n        style.borderColor = util.Util.makeHexColor(borderColor[0] | 0, borderColor[1] | 0, borderColor[2] | 0);\n      } else {\n        style.borderWidth = 0;\n      }\n    }\n    const rect = util.Util.normalizeRect([data.rect[0], page.view[3] - data.rect[1] + page.view[1], data.rect[2], page.view[3] - data.rect[3] + page.view[1]]);\n    const {\n      pageWidth,\n      pageHeight,\n      pageX,\n      pageY\n    } = viewport.rawDims;\n    style.left = `${100 * (rect[0] - pageX) / pageWidth}%`;\n    style.top = `${100 * (rect[1] - pageY) / pageHeight}%`;\n    const {\n      rotation\n    } = data;\n    if (data.hasOwnCanvas || rotation === 0) {\n      style.width = `${100 * width / pageWidth}%`;\n      style.height = `${100 * height / pageHeight}%`;\n    } else {\n      this.setRotation(rotation, container);\n    }\n    return container;\n  }\n  setRotation(angle, container = this.container) {\n    if (!this.data.rect) {\n      return;\n    }\n    const {\n      pageWidth,\n      pageHeight\n    } = this.parent.viewport.rawDims;\n    const {\n      width,\n      height\n    } = getRectDims(this.data.rect);\n    let elementWidth, elementHeight;\n    if (angle % 180 === 0) {\n      elementWidth = 100 * width / pageWidth;\n      elementHeight = 100 * height / pageHeight;\n    } else {\n      elementWidth = 100 * height / pageWidth;\n      elementHeight = 100 * width / pageHeight;\n    }\n    container.style.width = `${elementWidth}%`;\n    container.style.height = `${elementHeight}%`;\n    container.setAttribute(\"data-main-rotation\", (360 - angle) % 360);\n  }\n  get _commonActions() {\n    const setColor = (jsName, styleName, event) => {\n      const color = event.detail[jsName];\n      const colorType = color[0];\n      const colorArray = color.slice(1);\n      event.target.style[styleName] = ColorConverters[`${colorType}_HTML`](colorArray);\n      this.annotationStorage.setValue(this.data.id, {\n        [styleName]: ColorConverters[`${colorType}_rgb`](colorArray)\n      });\n    };\n    return (0,util.shadow)(this, \"_commonActions\", {\n      display: event => {\n        const {\n          display\n        } = event.detail;\n        const hidden = display % 2 === 1;\n        this.container.style.visibility = hidden ? \"hidden\" : \"visible\";\n        this.annotationStorage.setValue(this.data.id, {\n          noView: hidden,\n          noPrint: display === 1 || display === 2\n        });\n      },\n      print: event => {\n        this.annotationStorage.setValue(this.data.id, {\n          noPrint: !event.detail.print\n        });\n      },\n      hidden: event => {\n        const {\n          hidden\n        } = event.detail;\n        this.container.style.visibility = hidden ? \"hidden\" : \"visible\";\n        this.annotationStorage.setValue(this.data.id, {\n          noPrint: hidden,\n          noView: hidden\n        });\n      },\n      focus: event => {\n        setTimeout(() => event.target.focus({\n          preventScroll: false\n        }), 0);\n      },\n      userName: event => {\n        event.target.title = event.detail.userName;\n      },\n      readonly: event => {\n        event.target.disabled = event.detail.readonly;\n      },\n      required: event => {\n        this._setRequired(event.target, event.detail.required);\n      },\n      bgColor: event => {\n        setColor(\"bgColor\", \"backgroundColor\", event);\n      },\n      fillColor: event => {\n        setColor(\"fillColor\", \"backgroundColor\", event);\n      },\n      fgColor: event => {\n        setColor(\"fgColor\", \"color\", event);\n      },\n      textColor: event => {\n        setColor(\"textColor\", \"color\", event);\n      },\n      borderColor: event => {\n        setColor(\"borderColor\", \"borderColor\", event);\n      },\n      strokeColor: event => {\n        setColor(\"strokeColor\", \"borderColor\", event);\n      },\n      rotation: event => {\n        const angle = event.detail.rotation;\n        this.setRotation(angle);\n        this.annotationStorage.setValue(this.data.id, {\n          rotation: angle\n        });\n      }\n    });\n  }\n  _dispatchEventFromSandbox(actions, jsEvent) {\n    const commonActions = this._commonActions;\n    for (const name of Object.keys(jsEvent.detail)) {\n      const action = actions[name] || commonActions[name];\n      action?.(jsEvent);\n    }\n  }\n  _setDefaultPropertiesFromJS(element) {\n    if (!this.enableScripting) {\n      return;\n    }\n    const storedData = this.annotationStorage.getRawValue(this.data.id);\n    if (!storedData) {\n      return;\n    }\n    const commonActions = this._commonActions;\n    for (const [actionName, detail] of Object.entries(storedData)) {\n      const action = commonActions[actionName];\n      if (action) {\n        const eventProxy = {\n          detail: {\n            [actionName]: detail\n          },\n          target: element\n        };\n        action(eventProxy);\n        delete storedData[actionName];\n      }\n    }\n  }\n  _createQuadrilaterals() {\n    if (!this.container) {\n      return;\n    }\n    const {\n      quadPoints\n    } = this.data;\n    if (!quadPoints) {\n      return;\n    }\n    const [rectBlX, rectBlY, rectTrX, rectTrY] = this.data.rect;\n    if (quadPoints.length === 1) {\n      const [, {\n        x: trX,\n        y: trY\n      }, {\n        x: blX,\n        y: blY\n      }] = quadPoints[0];\n      if (rectTrX === trX && rectTrY === trY && rectBlX === blX && rectBlY === blY) {\n        return;\n      }\n    }\n    const {\n      style\n    } = this.container;\n    let svgBuffer;\n    if (this.#hasBorder) {\n      const {\n        borderColor,\n        borderWidth\n      } = style;\n      style.borderWidth = 0;\n      svgBuffer = [\"url('data:image/svg+xml;utf8,\", `<svg xmlns=\"http://www.w3.org/2000/svg\"`, ` preserveAspectRatio=\"none\" viewBox=\"0 0 1 1\">`, `<g fill=\"transparent\" stroke=\"${borderColor}\" stroke-width=\"${borderWidth}\">`];\n      this.container.classList.add(\"hasBorder\");\n    }\n    const width = rectTrX - rectBlX;\n    const height = rectTrY - rectBlY;\n    const {\n      svgFactory\n    } = this;\n    const svg = svgFactory.createElement(\"svg\");\n    svg.classList.add(\"quadrilateralsContainer\");\n    svg.setAttribute(\"width\", 0);\n    svg.setAttribute(\"height\", 0);\n    const defs = svgFactory.createElement(\"defs\");\n    svg.append(defs);\n    const clipPath = svgFactory.createElement(\"clipPath\");\n    const id = `clippath_${this.data.id}`;\n    clipPath.setAttribute(\"id\", id);\n    clipPath.setAttribute(\"clipPathUnits\", \"objectBoundingBox\");\n    defs.append(clipPath);\n    for (const [, {\n      x: trX,\n      y: trY\n    }, {\n      x: blX,\n      y: blY\n    }] of quadPoints) {\n      const rect = svgFactory.createElement(\"rect\");\n      const x = (blX - rectBlX) / width;\n      const y = (rectTrY - trY) / height;\n      const rectWidth = (trX - blX) / width;\n      const rectHeight = (trY - blY) / height;\n      rect.setAttribute(\"x\", x);\n      rect.setAttribute(\"y\", y);\n      rect.setAttribute(\"width\", rectWidth);\n      rect.setAttribute(\"height\", rectHeight);\n      clipPath.append(rect);\n      svgBuffer?.push(`<rect vector-effect=\"non-scaling-stroke\" x=\"${x}\" y=\"${y}\" width=\"${rectWidth}\" height=\"${rectHeight}\"/>`);\n    }\n    if (this.#hasBorder) {\n      svgBuffer.push(`</g></svg>')`);\n      style.backgroundImage = svgBuffer.join(\"\");\n    }\n    this.container.append(svg);\n    this.container.style.clipPath = `url(#${id})`;\n  }\n  _createPopup() {\n    const {\n      container,\n      data\n    } = this;\n    container.setAttribute(\"aria-haspopup\", \"dialog\");\n    const popup = new PopupAnnotationElement({\n      data: {\n        color: data.color,\n        titleObj: data.titleObj,\n        modificationDate: data.modificationDate,\n        contentsObj: data.contentsObj,\n        richText: data.richText,\n        parentRect: data.rect,\n        borderStyle: 0,\n        id: `popup_${data.id}`,\n        rotation: data.rotation\n      },\n      parent: this.parent,\n      elements: [this]\n    });\n    this.parent.div.append(popup.render());\n  }\n  render() {\n    (0,util.unreachable)(\"Abstract method `AnnotationElement.render` called\");\n  }\n  _getElementsByName(name, skipId = null) {\n    const fields = [];\n    if (this._fieldObjects) {\n      const fieldObj = this._fieldObjects[name];\n      if (fieldObj) {\n        for (const {\n          page,\n          id,\n          exportValues\n        } of fieldObj) {\n          if (page === -1) {\n            continue;\n          }\n          if (id === skipId) {\n            continue;\n          }\n          const exportValue = typeof exportValues === \"string\" ? exportValues : null;\n          const domElement = document.querySelector(`[data-element-id=\"${id}\"]`);\n          if (domElement && !GetElementsByNameSet.has(domElement)) {\n            (0,util.warn)(`_getElementsByName - element not allowed: ${id}`);\n            continue;\n          }\n          fields.push({\n            id,\n            exportValue,\n            domElement\n          });\n        }\n      }\n      return fields;\n    }\n    for (const domElement of document.getElementsByName(name)) {\n      const {\n        exportValue\n      } = domElement;\n      const id = domElement.getAttribute(\"data-element-id\");\n      if (id === skipId) {\n        continue;\n      }\n      if (!GetElementsByNameSet.has(domElement)) {\n        continue;\n      }\n      fields.push({\n        id,\n        exportValue,\n        domElement\n      });\n    }\n    return fields;\n  }\n  show() {\n    if (this.container) {\n      this.container.hidden = false;\n    }\n    this.popup?.maybeShow();\n  }\n  hide() {\n    if (this.container) {\n      this.container.hidden = true;\n    }\n    this.popup?.forceHide();\n  }\n  getElementsToTriggerPopup() {\n    return this.container;\n  }\n  addHighlightArea() {\n    const triggers = this.getElementsToTriggerPopup();\n    if (Array.isArray(triggers)) {\n      for (const element of triggers) {\n        element.classList.add(\"highlightArea\");\n      }\n    } else {\n      triggers.classList.add(\"highlightArea\");\n    }\n  }\n  get _isEditable() {\n    return false;\n  }\n  _editOnDoubleClick() {\n    if (!this._isEditable) {\n      return;\n    }\n    const {\n      annotationEditorType: mode,\n      data: {\n        id: editId\n      }\n    } = this;\n    this.container.addEventListener(\"dblclick\", () => {\n      this.linkService.eventBus?.dispatch(\"switchannotationeditormode\", {\n        source: this,\n        mode,\n        editId\n      });\n    });\n  }\n}\nclass LinkAnnotationElement extends AnnotationElement {\n  constructor(parameters, options = null) {\n    super(parameters, {\n      isRenderable: true,\n      ignoreBorder: !!options?.ignoreBorder,\n      createQuadrilaterals: true\n    });\n    this.isTooltipOnly = parameters.data.isTooltipOnly;\n  }\n  render() {\n    const {\n      data,\n      linkService\n    } = this;\n    const link = document.createElement(\"a\");\n    link.setAttribute(\"data-element-id\", data.id);\n    let isBound = false;\n    if (data.url) {\n      linkService.addLinkAttributes(link, data.url, data.newWindow);\n      isBound = true;\n    } else if (data.action) {\n      this._bindNamedAction(link, data.action);\n      isBound = true;\n    } else if (data.attachment) {\n      this.#bindAttachment(link, data.attachment, data.attachmentDest);\n      isBound = true;\n    } else if (data.setOCGState) {\n      this.#bindSetOCGState(link, data.setOCGState);\n      isBound = true;\n    } else if (data.dest) {\n      this._bindLink(link, data.dest);\n      isBound = true;\n    } else {\n      if (data.actions && (data.actions.Action || data.actions[\"Mouse Up\"] || data.actions[\"Mouse Down\"]) && this.enableScripting && this.hasJSActions) {\n        this._bindJSAction(link, data);\n        isBound = true;\n      }\n      if (data.resetForm) {\n        this._bindResetFormAction(link, data.resetForm);\n        isBound = true;\n      } else if (this.isTooltipOnly && !isBound) {\n        this._bindLink(link, \"\");\n        isBound = true;\n      }\n    }\n    this.container.classList.add(\"linkAnnotation\");\n    if (isBound) {\n      this.container.append(link);\n    }\n    return this.container;\n  }\n  #setInternalLink() {\n    this.container.setAttribute(\"data-internal-link\", \"\");\n  }\n  _bindLink(link, destination) {\n    link.href = this.linkService.getDestinationHash(destination);\n    link.onclick = () => {\n      if (destination) {\n        this.linkService.goToDestination(destination);\n      }\n      return false;\n    };\n    if (destination || destination === \"\") {\n      this.#setInternalLink();\n    }\n  }\n  _bindNamedAction(link, action) {\n    link.href = this.linkService.getAnchorUrl(\"\");\n    link.onclick = () => {\n      this.linkService.executeNamedAction(action);\n      return false;\n    };\n    this.#setInternalLink();\n  }\n  #bindAttachment(link, attachment, dest = null) {\n    link.href = this.linkService.getAnchorUrl(\"\");\n    link.onclick = () => {\n      this.downloadManager?.openOrDownloadData(attachment.content, attachment.filename, dest);\n      return false;\n    };\n    this.#setInternalLink();\n  }\n  #bindSetOCGState(link, action) {\n    link.href = this.linkService.getAnchorUrl(\"\");\n    link.onclick = () => {\n      this.linkService.executeSetOCGState(action);\n      return false;\n    };\n    this.#setInternalLink();\n  }\n  _bindJSAction(link, data) {\n    link.href = this.linkService.getAnchorUrl(\"\");\n    const map = new Map([[\"Action\", \"onclick\"], [\"Mouse Up\", \"onmouseup\"], [\"Mouse Down\", \"onmousedown\"]]);\n    for (const name of Object.keys(data.actions)) {\n      const jsName = map.get(name);\n      if (!jsName) {\n        continue;\n      }\n      link[jsName] = () => {\n        this.linkService.eventBus?.dispatch(\"dispatcheventinsandbox\", {\n          source: this,\n          detail: {\n            id: data.id,\n            name\n          }\n        });\n        return false;\n      };\n    }\n    if (!link.onclick) {\n      link.onclick = () => false;\n    }\n    this.#setInternalLink();\n  }\n  _bindResetFormAction(link, resetForm) {\n    const otherClickAction = link.onclick;\n    if (!otherClickAction) {\n      link.href = this.linkService.getAnchorUrl(\"\");\n    }\n    this.#setInternalLink();\n    if (!this._fieldObjects) {\n      (0,util.warn)(`_bindResetFormAction - \"resetForm\" action not supported, ` + \"ensure that the `fieldObjects` parameter is provided.\");\n      if (!otherClickAction) {\n        link.onclick = () => false;\n      }\n      return;\n    }\n    link.onclick = () => {\n      otherClickAction?.();\n      const {\n        fields: resetFormFields,\n        refs: resetFormRefs,\n        include\n      } = resetForm;\n      const allFields = [];\n      if (resetFormFields.length !== 0 || resetFormRefs.length !== 0) {\n        const fieldIds = new Set(resetFormRefs);\n        for (const fieldName of resetFormFields) {\n          const fields = this._fieldObjects[fieldName] || [];\n          for (const {\n            id\n          } of fields) {\n            fieldIds.add(id);\n          }\n        }\n        for (const fields of Object.values(this._fieldObjects)) {\n          for (const field of fields) {\n            if (fieldIds.has(field.id) === include) {\n              allFields.push(field);\n            }\n          }\n        }\n      } else {\n        for (const fields of Object.values(this._fieldObjects)) {\n          allFields.push(...fields);\n        }\n      }\n      const storage = this.annotationStorage;\n      const allIds = [];\n      for (const field of allFields) {\n        const {\n          id\n        } = field;\n        allIds.push(id);\n        switch (field.type) {\n          case \"text\":\n            {\n              const value = field.defaultValue || \"\";\n              storage.setValue(id, {\n                value\n              });\n              break;\n            }\n          case \"checkbox\":\n          case \"radiobutton\":\n            {\n              const value = field.defaultValue === field.exportValues;\n              storage.setValue(id, {\n                value\n              });\n              break;\n            }\n          case \"combobox\":\n          case \"listbox\":\n            {\n              const value = field.defaultValue || \"\";\n              storage.setValue(id, {\n                value\n              });\n              break;\n            }\n          default:\n            continue;\n        }\n        const domElement = document.querySelector(`[data-element-id=\"${id}\"]`);\n        if (!domElement) {\n          continue;\n        } else if (!GetElementsByNameSet.has(domElement)) {\n          (0,util.warn)(`_bindResetFormAction - element not allowed: ${id}`);\n          continue;\n        }\n        domElement.dispatchEvent(new Event(\"resetform\"));\n      }\n      if (this.enableScripting) {\n        this.linkService.eventBus?.dispatch(\"dispatcheventinsandbox\", {\n          source: this,\n          detail: {\n            id: \"app\",\n            ids: allIds,\n            name: \"ResetForm\"\n          }\n        });\n      }\n      return false;\n    };\n  }\n}\nclass TextAnnotationElement extends AnnotationElement {\n  constructor(parameters) {\n    super(parameters, {\n      isRenderable: true\n    });\n  }\n  render() {\n    this.container.classList.add(\"textAnnotation\");\n    const image = document.createElement(\"img\");\n    image.src = this.imageResourcesPath + \"annotation-\" + this.data.name.toLowerCase() + \".svg\";\n    image.setAttribute(\"data-l10n-id\", \"pdfjs-text-annotation-type\");\n    image.setAttribute(\"data-l10n-args\", JSON.stringify({\n      type: this.data.name\n    }));\n    if (!this.data.popupRef && this.hasPopupData) {\n      this._createPopup();\n    }\n    this.container.append(image);\n    return this.container;\n  }\n}\nclass WidgetAnnotationElement extends AnnotationElement {\n  render() {\n    return this.container;\n  }\n  showElementAndHideCanvas(element) {\n    if (this.data.hasOwnCanvas) {\n      if (element.previousSibling?.nodeName === \"CANVAS\") {\n        element.previousSibling.hidden = true;\n      }\n      element.hidden = false;\n    }\n  }\n  _getKeyModifier(event) {\n    return util.FeatureTest.platform.isMac ? event.metaKey : event.ctrlKey;\n  }\n  _setEventListener(element, elementData, baseName, eventName, valueGetter) {\n    if (baseName.includes(\"mouse\")) {\n      element.addEventListener(baseName, event => {\n        this.linkService.eventBus?.dispatch(\"dispatcheventinsandbox\", {\n          source: this,\n          detail: {\n            id: this.data.id,\n            name: eventName,\n            value: valueGetter(event),\n            shift: event.shiftKey,\n            modifier: this._getKeyModifier(event)\n          }\n        });\n      });\n    } else {\n      element.addEventListener(baseName, event => {\n        if (baseName === \"blur\") {\n          if (!elementData.focused || !event.relatedTarget) {\n            return;\n          }\n          elementData.focused = false;\n        } else if (baseName === \"focus\") {\n          if (elementData.focused) {\n            return;\n          }\n          elementData.focused = true;\n        }\n        if (!valueGetter) {\n          return;\n        }\n        this.linkService.eventBus?.dispatch(\"dispatcheventinsandbox\", {\n          source: this,\n          detail: {\n            id: this.data.id,\n            name: eventName,\n            value: valueGetter(event)\n          }\n        });\n      });\n    }\n  }\n  _setEventListeners(element, elementData, names, getter) {\n    for (const [baseName, eventName] of names) {\n      if (eventName === \"Action\" || this.data.actions?.[eventName]) {\n        if (eventName === \"Focus\" || eventName === \"Blur\") {\n          elementData ||= {\n            focused: false\n          };\n        }\n        this._setEventListener(element, elementData, baseName, eventName, getter);\n        if (eventName === \"Focus\" && !this.data.actions?.Blur) {\n          this._setEventListener(element, elementData, \"blur\", \"Blur\", null);\n        } else if (eventName === \"Blur\" && !this.data.actions?.Focus) {\n          this._setEventListener(element, elementData, \"focus\", \"Focus\", null);\n        }\n      }\n    }\n  }\n  _setBackgroundColor(element) {\n    const color = this.data.backgroundColor || null;\n    element.style.backgroundColor = color === null ? \"transparent\" : util.Util.makeHexColor(color[0], color[1], color[2]);\n  }\n  _setTextStyle(element) {\n    const TEXT_ALIGNMENT = [\"left\", \"center\", \"right\"];\n    const {\n      fontColor\n    } = this.data.defaultAppearanceData;\n    const fontSize = this.data.defaultAppearanceData.fontSize || DEFAULT_FONT_SIZE;\n    const style = element.style;\n    let computedFontSize;\n    const BORDER_SIZE = 2;\n    const roundToOneDecimal = x => Math.round(10 * x) / 10;\n    if (this.data.multiLine) {\n      const height = Math.abs(this.data.rect[3] - this.data.rect[1] - BORDER_SIZE);\n      const numberOfLines = Math.round(height / (util.LINE_FACTOR * fontSize)) || 1;\n      const lineHeight = height / numberOfLines;\n      computedFontSize = Math.min(fontSize, roundToOneDecimal(lineHeight / util.LINE_FACTOR));\n    } else {\n      const height = Math.abs(this.data.rect[3] - this.data.rect[1] - BORDER_SIZE);\n      computedFontSize = Math.min(fontSize, roundToOneDecimal(height / util.LINE_FACTOR));\n    }\n    style.fontSize = `calc(${computedFontSize}px * var(--scale-factor))`;\n    style.color = util.Util.makeHexColor(fontColor[0], fontColor[1], fontColor[2]);\n    if (this.data.textAlignment !== null) {\n      style.textAlign = TEXT_ALIGNMENT[this.data.textAlignment];\n    }\n  }\n  _setRequired(element, isRequired) {\n    if (isRequired) {\n      element.setAttribute(\"required\", true);\n    } else {\n      element.removeAttribute(\"required\");\n    }\n    element.setAttribute(\"aria-required\", isRequired);\n  }\n}\nclass TextWidgetAnnotationElement extends WidgetAnnotationElement {\n  constructor(parameters) {\n    const isRenderable = parameters.renderForms || parameters.data.hasOwnCanvas || !parameters.data.hasAppearance && !!parameters.data.fieldValue;\n    super(parameters, {\n      isRenderable\n    });\n  }\n  setPropertyOnSiblings(base, key, value, keyInStorage) {\n    const storage = this.annotationStorage;\n    for (const element of this._getElementsByName(base.name, base.id)) {\n      if (element.domElement) {\n        element.domElement[key] = value;\n      }\n      storage.setValue(element.id, {\n        [keyInStorage]: value\n      });\n    }\n  }\n  render() {\n    const storage = this.annotationStorage;\n    const id = this.data.id;\n    this.container.classList.add(\"textWidgetAnnotation\");\n    let element = null;\n    if (this.renderForms) {\n      const storedData = storage.getValue(id, {\n        value: this.data.fieldValue\n      });\n      let textContent = storedData.value || \"\";\n      const maxLen = storage.getValue(id, {\n        charLimit: this.data.maxLen\n      }).charLimit;\n      if (maxLen && textContent.length > maxLen) {\n        textContent = textContent.slice(0, maxLen);\n      }\n      let fieldFormattedValues = storedData.formattedValue || this.data.textContent?.join(\"\\n\") || null;\n      if (fieldFormattedValues && this.data.comb) {\n        fieldFormattedValues = fieldFormattedValues.replaceAll(/\\s+/g, \"\");\n      }\n      const elementData = {\n        userValue: textContent,\n        formattedValue: fieldFormattedValues,\n        lastCommittedValue: null,\n        commitKey: 1,\n        focused: false\n      };\n      if (this.data.multiLine) {\n        element = document.createElement(\"textarea\");\n        element.textContent = fieldFormattedValues ?? textContent;\n        if (this.data.doNotScroll) {\n          element.style.overflowY = \"hidden\";\n        }\n      } else {\n        element = document.createElement(\"input\");\n        element.type = \"text\";\n        element.setAttribute(\"value\", fieldFormattedValues ?? textContent);\n        if (this.data.doNotScroll) {\n          element.style.overflowX = \"hidden\";\n        }\n      }\n      if (this.data.hasOwnCanvas) {\n        element.hidden = true;\n      }\n      GetElementsByNameSet.add(element);\n      element.setAttribute(\"data-element-id\", id);\n      element.disabled = this.data.readOnly;\n      element.name = this.data.fieldName;\n      element.tabIndex = DEFAULT_TAB_INDEX;\n      this._setRequired(element, this.data.required);\n      if (maxLen) {\n        element.maxLength = maxLen;\n      }\n      element.addEventListener(\"input\", event => {\n        storage.setValue(id, {\n          value: event.target.value\n        });\n        this.setPropertyOnSiblings(element, \"value\", event.target.value, \"value\");\n        elementData.formattedValue = null;\n      });\n      element.addEventListener(\"resetform\", event => {\n        const defaultValue = this.data.defaultFieldValue ?? \"\";\n        element.value = elementData.userValue = defaultValue;\n        elementData.formattedValue = null;\n      });\n      let blurListener = event => {\n        const {\n          formattedValue\n        } = elementData;\n        if (formattedValue !== null && formattedValue !== undefined) {\n          event.target.value = formattedValue;\n        }\n        event.target.scrollLeft = 0;\n      };\n      if (this.enableScripting && this.hasJSActions) {\n        element.addEventListener(\"focus\", event => {\n          if (elementData.focused) {\n            return;\n          }\n          const {\n            target\n          } = event;\n          if (elementData.userValue) {\n            target.value = elementData.userValue;\n          }\n          elementData.lastCommittedValue = target.value;\n          elementData.commitKey = 1;\n          if (!this.data.actions?.Focus) {\n            elementData.focused = true;\n          }\n        });\n        element.addEventListener(\"updatefromsandbox\", jsEvent => {\n          this.showElementAndHideCanvas(jsEvent.target);\n          const actions = {\n            value(event) {\n              elementData.userValue = event.detail.value ?? \"\";\n              storage.setValue(id, {\n                value: elementData.userValue.toString()\n              });\n              event.target.value = elementData.userValue;\n            },\n            formattedValue(event) {\n              const {\n                formattedValue\n              } = event.detail;\n              elementData.formattedValue = formattedValue;\n              if (formattedValue !== null && formattedValue !== undefined && event.target !== document.activeElement) {\n                event.target.value = formattedValue;\n              }\n              storage.setValue(id, {\n                formattedValue\n              });\n            },\n            selRange(event) {\n              event.target.setSelectionRange(...event.detail.selRange);\n            },\n            charLimit: event => {\n              const {\n                charLimit\n              } = event.detail;\n              const {\n                target\n              } = event;\n              if (charLimit === 0) {\n                target.removeAttribute(\"maxLength\");\n                return;\n              }\n              target.setAttribute(\"maxLength\", charLimit);\n              let value = elementData.userValue;\n              if (!value || value.length <= charLimit) {\n                return;\n              }\n              value = value.slice(0, charLimit);\n              target.value = elementData.userValue = value;\n              storage.setValue(id, {\n                value\n              });\n              this.linkService.eventBus?.dispatch(\"dispatcheventinsandbox\", {\n                source: this,\n                detail: {\n                  id,\n                  name: \"Keystroke\",\n                  value,\n                  willCommit: true,\n                  commitKey: 1,\n                  selStart: target.selectionStart,\n                  selEnd: target.selectionEnd\n                }\n              });\n            }\n          };\n          this._dispatchEventFromSandbox(actions, jsEvent);\n        });\n        element.addEventListener(\"keydown\", event => {\n          elementData.commitKey = 1;\n          let commitKey = -1;\n          if (event.key === \"Escape\") {\n            commitKey = 0;\n          } else if (event.key === \"Enter\" && !this.data.multiLine) {\n            commitKey = 2;\n          } else if (event.key === \"Tab\") {\n            elementData.commitKey = 3;\n          }\n          if (commitKey === -1) {\n            return;\n          }\n          const {\n            value\n          } = event.target;\n          if (elementData.lastCommittedValue === value) {\n            return;\n          }\n          elementData.lastCommittedValue = value;\n          elementData.userValue = value;\n          this.linkService.eventBus?.dispatch(\"dispatcheventinsandbox\", {\n            source: this,\n            detail: {\n              id,\n              name: \"Keystroke\",\n              value,\n              willCommit: true,\n              commitKey,\n              selStart: event.target.selectionStart,\n              selEnd: event.target.selectionEnd\n            }\n          });\n        });\n        const _blurListener = blurListener;\n        blurListener = null;\n        element.addEventListener(\"blur\", event => {\n          if (!elementData.focused || !event.relatedTarget) {\n            return;\n          }\n          if (!this.data.actions?.Blur) {\n            elementData.focused = false;\n          }\n          const {\n            value\n          } = event.target;\n          elementData.userValue = value;\n          if (elementData.lastCommittedValue !== value) {\n            this.linkService.eventBus?.dispatch(\"dispatcheventinsandbox\", {\n              source: this,\n              detail: {\n                id,\n                name: \"Keystroke\",\n                value,\n                willCommit: true,\n                commitKey: elementData.commitKey,\n                selStart: event.target.selectionStart,\n                selEnd: event.target.selectionEnd\n              }\n            });\n          }\n          _blurListener(event);\n        });\n        if (this.data.actions?.Keystroke) {\n          element.addEventListener(\"beforeinput\", event => {\n            elementData.lastCommittedValue = null;\n            const {\n              data,\n              target\n            } = event;\n            const {\n              value,\n              selectionStart,\n              selectionEnd\n            } = target;\n            let selStart = selectionStart,\n              selEnd = selectionEnd;\n            switch (event.inputType) {\n              case \"deleteWordBackward\":\n                {\n                  const match = value.substring(0, selectionStart).match(/\\w*[^\\w]*$/);\n                  if (match) {\n                    selStart -= match[0].length;\n                  }\n                  break;\n                }\n              case \"deleteWordForward\":\n                {\n                  const match = value.substring(selectionStart).match(/^[^\\w]*\\w*/);\n                  if (match) {\n                    selEnd += match[0].length;\n                  }\n                  break;\n                }\n              case \"deleteContentBackward\":\n                if (selectionStart === selectionEnd) {\n                  selStart -= 1;\n                }\n                break;\n              case \"deleteContentForward\":\n                if (selectionStart === selectionEnd) {\n                  selEnd += 1;\n                }\n                break;\n            }\n            event.preventDefault();\n            this.linkService.eventBus?.dispatch(\"dispatcheventinsandbox\", {\n              source: this,\n              detail: {\n                id,\n                name: \"Keystroke\",\n                value,\n                change: data || \"\",\n                willCommit: false,\n                selStart,\n                selEnd\n              }\n            });\n          });\n        }\n        this._setEventListeners(element, elementData, [[\"focus\", \"Focus\"], [\"blur\", \"Blur\"], [\"mousedown\", \"Mouse Down\"], [\"mouseenter\", \"Mouse Enter\"], [\"mouseleave\", \"Mouse Exit\"], [\"mouseup\", \"Mouse Up\"]], event => event.target.value);\n      }\n      if (blurListener) {\n        element.addEventListener(\"blur\", blurListener);\n      }\n      if (this.data.comb) {\n        const fieldWidth = this.data.rect[2] - this.data.rect[0];\n        const combWidth = fieldWidth / maxLen;\n        element.classList.add(\"comb\");\n        element.style.letterSpacing = `calc(${combWidth}px * var(--scale-factor) - 1ch)`;\n      }\n    } else {\n      element = document.createElement(\"div\");\n      element.textContent = this.data.fieldValue;\n      element.style.verticalAlign = \"middle\";\n      element.style.display = \"table-cell\";\n      if (this.data.hasOwnCanvas) {\n        element.hidden = true;\n      }\n    }\n    this._setTextStyle(element);\n    this._setBackgroundColor(element);\n    this._setDefaultPropertiesFromJS(element);\n    this.container.append(element);\n    return this.container;\n  }\n}\nclass SignatureWidgetAnnotationElement extends WidgetAnnotationElement {\n  constructor(parameters) {\n    super(parameters, {\n      isRenderable: !!parameters.data.hasOwnCanvas\n    });\n  }\n}\nclass CheckboxWidgetAnnotationElement extends WidgetAnnotationElement {\n  constructor(parameters) {\n    super(parameters, {\n      isRenderable: parameters.renderForms\n    });\n  }\n  render() {\n    const storage = this.annotationStorage;\n    const data = this.data;\n    const id = data.id;\n    let value = storage.getValue(id, {\n      value: data.exportValue === data.fieldValue\n    }).value;\n    if (typeof value === \"string\") {\n      value = value !== \"Off\";\n      storage.setValue(id, {\n        value\n      });\n    }\n    this.container.classList.add(\"buttonWidgetAnnotation\", \"checkBox\");\n    const element = document.createElement(\"input\");\n    GetElementsByNameSet.add(element);\n    element.setAttribute(\"data-element-id\", id);\n    element.disabled = data.readOnly;\n    this._setRequired(element, this.data.required);\n    element.type = \"checkbox\";\n    element.name = data.fieldName;\n    if (value) {\n      element.setAttribute(\"checked\", true);\n    }\n    element.setAttribute(\"exportValue\", data.exportValue);\n    element.tabIndex = DEFAULT_TAB_INDEX;\n    element.addEventListener(\"change\", event => {\n      const {\n        name,\n        checked\n      } = event.target;\n      for (const checkbox of this._getElementsByName(name, id)) {\n        const curChecked = checked && checkbox.exportValue === data.exportValue;\n        if (checkbox.domElement) {\n          checkbox.domElement.checked = curChecked;\n        }\n        storage.setValue(checkbox.id, {\n          value: curChecked\n        });\n      }\n      storage.setValue(id, {\n        value: checked\n      });\n    });\n    element.addEventListener(\"resetform\", event => {\n      const defaultValue = data.defaultFieldValue || \"Off\";\n      event.target.checked = defaultValue === data.exportValue;\n    });\n    if (this.enableScripting && this.hasJSActions) {\n      element.addEventListener(\"updatefromsandbox\", jsEvent => {\n        const actions = {\n          value(event) {\n            event.target.checked = event.detail.value !== \"Off\";\n            storage.setValue(id, {\n              value: event.target.checked\n            });\n          }\n        };\n        this._dispatchEventFromSandbox(actions, jsEvent);\n      });\n      this._setEventListeners(element, null, [[\"change\", \"Validate\"], [\"change\", \"Action\"], [\"focus\", \"Focus\"], [\"blur\", \"Blur\"], [\"mousedown\", \"Mouse Down\"], [\"mouseenter\", \"Mouse Enter\"], [\"mouseleave\", \"Mouse Exit\"], [\"mouseup\", \"Mouse Up\"]], event => event.target.checked);\n    }\n    this._setBackgroundColor(element);\n    this._setDefaultPropertiesFromJS(element);\n    this.container.append(element);\n    return this.container;\n  }\n}\nclass RadioButtonWidgetAnnotationElement extends WidgetAnnotationElement {\n  constructor(parameters) {\n    super(parameters, {\n      isRenderable: parameters.renderForms\n    });\n  }\n  render() {\n    this.container.classList.add(\"buttonWidgetAnnotation\", \"radioButton\");\n    const storage = this.annotationStorage;\n    const data = this.data;\n    const id = data.id;\n    let value = storage.getValue(id, {\n      value: data.fieldValue === data.buttonValue\n    }).value;\n    if (typeof value === \"string\") {\n      value = value !== data.buttonValue;\n      storage.setValue(id, {\n        value\n      });\n    }\n    if (value) {\n      for (const radio of this._getElementsByName(data.fieldName, id)) {\n        storage.setValue(radio.id, {\n          value: false\n        });\n      }\n    }\n    const element = document.createElement(\"input\");\n    GetElementsByNameSet.add(element);\n    element.setAttribute(\"data-element-id\", id);\n    element.disabled = data.readOnly;\n    this._setRequired(element, this.data.required);\n    element.type = \"radio\";\n    element.name = data.fieldName;\n    if (value) {\n      element.setAttribute(\"checked\", true);\n    }\n    element.tabIndex = DEFAULT_TAB_INDEX;\n    element.addEventListener(\"change\", event => {\n      const {\n        name,\n        checked\n      } = event.target;\n      for (const radio of this._getElementsByName(name, id)) {\n        storage.setValue(radio.id, {\n          value: false\n        });\n      }\n      storage.setValue(id, {\n        value: checked\n      });\n    });\n    element.addEventListener(\"resetform\", event => {\n      const defaultValue = data.defaultFieldValue;\n      event.target.checked = defaultValue !== null && defaultValue !== undefined && defaultValue === data.buttonValue;\n    });\n    if (this.enableScripting && this.hasJSActions) {\n      const pdfButtonValue = data.buttonValue;\n      element.addEventListener(\"updatefromsandbox\", jsEvent => {\n        const actions = {\n          value: event => {\n            const checked = pdfButtonValue === event.detail.value;\n            for (const radio of this._getElementsByName(event.target.name)) {\n              const curChecked = checked && radio.id === id;\n              if (radio.domElement) {\n                radio.domElement.checked = curChecked;\n              }\n              storage.setValue(radio.id, {\n                value: curChecked\n              });\n            }\n          }\n        };\n        this._dispatchEventFromSandbox(actions, jsEvent);\n      });\n      this._setEventListeners(element, null, [[\"change\", \"Validate\"], [\"change\", \"Action\"], [\"focus\", \"Focus\"], [\"blur\", \"Blur\"], [\"mousedown\", \"Mouse Down\"], [\"mouseenter\", \"Mouse Enter\"], [\"mouseleave\", \"Mouse Exit\"], [\"mouseup\", \"Mouse Up\"]], event => event.target.checked);\n    }\n    this._setBackgroundColor(element);\n    this._setDefaultPropertiesFromJS(element);\n    this.container.append(element);\n    return this.container;\n  }\n}\nclass PushButtonWidgetAnnotationElement extends LinkAnnotationElement {\n  constructor(parameters) {\n    super(parameters, {\n      ignoreBorder: parameters.data.hasAppearance\n    });\n  }\n  render() {\n    const container = super.render();\n    container.classList.add(\"buttonWidgetAnnotation\", \"pushButton\");\n    const linkElement = container.lastChild;\n    if (this.enableScripting && this.hasJSActions && linkElement) {\n      this._setDefaultPropertiesFromJS(linkElement);\n      linkElement.addEventListener(\"updatefromsandbox\", jsEvent => {\n        this._dispatchEventFromSandbox({}, jsEvent);\n      });\n    }\n    return container;\n  }\n}\nclass ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {\n  constructor(parameters) {\n    super(parameters, {\n      isRenderable: parameters.renderForms\n    });\n  }\n  render() {\n    this.container.classList.add(\"choiceWidgetAnnotation\");\n    const storage = this.annotationStorage;\n    const id = this.data.id;\n    const storedData = storage.getValue(id, {\n      value: this.data.fieldValue\n    });\n    const selectElement = document.createElement(\"select\");\n    GetElementsByNameSet.add(selectElement);\n    selectElement.setAttribute(\"data-element-id\", id);\n    selectElement.disabled = this.data.readOnly;\n    this._setRequired(selectElement, this.data.required);\n    selectElement.name = this.data.fieldName;\n    selectElement.tabIndex = DEFAULT_TAB_INDEX;\n    let addAnEmptyEntry = this.data.combo && this.data.options.length > 0;\n    if (!this.data.combo) {\n      selectElement.size = this.data.options.length;\n      if (this.data.multiSelect) {\n        selectElement.multiple = true;\n      }\n    }\n    selectElement.addEventListener(\"resetform\", event => {\n      const defaultValue = this.data.defaultFieldValue;\n      for (const option of selectElement.options) {\n        option.selected = option.value === defaultValue;\n      }\n    });\n    for (const option of this.data.options) {\n      const optionElement = document.createElement(\"option\");\n      optionElement.textContent = option.displayValue;\n      optionElement.value = option.exportValue;\n      if (storedData.value.includes(option.exportValue)) {\n        optionElement.setAttribute(\"selected\", true);\n        addAnEmptyEntry = false;\n      }\n      selectElement.append(optionElement);\n    }\n    let removeEmptyEntry = null;\n    if (addAnEmptyEntry) {\n      const noneOptionElement = document.createElement(\"option\");\n      noneOptionElement.value = \" \";\n      noneOptionElement.setAttribute(\"hidden\", true);\n      noneOptionElement.setAttribute(\"selected\", true);\n      selectElement.prepend(noneOptionElement);\n      removeEmptyEntry = () => {\n        noneOptionElement.remove();\n        selectElement.removeEventListener(\"input\", removeEmptyEntry);\n        removeEmptyEntry = null;\n      };\n      selectElement.addEventListener(\"input\", removeEmptyEntry);\n    }\n    const getValue = isExport => {\n      const name = isExport ? \"value\" : \"textContent\";\n      const {\n        options,\n        multiple\n      } = selectElement;\n      if (!multiple) {\n        return options.selectedIndex === -1 ? null : options[options.selectedIndex][name];\n      }\n      return Array.prototype.filter.call(options, option => option.selected).map(option => option[name]);\n    };\n    let selectedValues = getValue(false);\n    const getItems = event => {\n      const options = event.target.options;\n      return Array.prototype.map.call(options, option => ({\n        displayValue: option.textContent,\n        exportValue: option.value\n      }));\n    };\n    if (this.enableScripting && this.hasJSActions) {\n      selectElement.addEventListener(\"updatefromsandbox\", jsEvent => {\n        const actions = {\n          value(event) {\n            removeEmptyEntry?.();\n            const value = event.detail.value;\n            const values = new Set(Array.isArray(value) ? value : [value]);\n            for (const option of selectElement.options) {\n              option.selected = values.has(option.value);\n            }\n            storage.setValue(id, {\n              value: getValue(true)\n            });\n            selectedValues = getValue(false);\n          },\n          multipleSelection(event) {\n            selectElement.multiple = true;\n          },\n          remove(event) {\n            const options = selectElement.options;\n            const index = event.detail.remove;\n            options[index].selected = false;\n            selectElement.remove(index);\n            if (options.length > 0) {\n              const i = Array.prototype.findIndex.call(options, option => option.selected);\n              if (i === -1) {\n                options[0].selected = true;\n              }\n            }\n            storage.setValue(id, {\n              value: getValue(true),\n              items: getItems(event)\n            });\n            selectedValues = getValue(false);\n          },\n          clear(event) {\n            while (selectElement.length !== 0) {\n              selectElement.remove(0);\n            }\n            storage.setValue(id, {\n              value: null,\n              items: []\n            });\n            selectedValues = getValue(false);\n          },\n          insert(event) {\n            const {\n              index,\n              displayValue,\n              exportValue\n            } = event.detail.insert;\n            const selectChild = selectElement.children[index];\n            const optionElement = document.createElement(\"option\");\n            optionElement.textContent = displayValue;\n            optionElement.value = exportValue;\n            if (selectChild) {\n              selectChild.before(optionElement);\n            } else {\n              selectElement.append(optionElement);\n            }\n            storage.setValue(id, {\n              value: getValue(true),\n              items: getItems(event)\n            });\n            selectedValues = getValue(false);\n          },\n          items(event) {\n            const {\n              items\n            } = event.detail;\n            while (selectElement.length !== 0) {\n              selectElement.remove(0);\n            }\n            for (const item of items) {\n              const {\n                displayValue,\n                exportValue\n              } = item;\n              const optionElement = document.createElement(\"option\");\n              optionElement.textContent = displayValue;\n              optionElement.value = exportValue;\n              selectElement.append(optionElement);\n            }\n            if (selectElement.options.length > 0) {\n              selectElement.options[0].selected = true;\n            }\n            storage.setValue(id, {\n              value: getValue(true),\n              items: getItems(event)\n            });\n            selectedValues = getValue(false);\n          },\n          indices(event) {\n            const indices = new Set(event.detail.indices);\n            for (const option of event.target.options) {\n              option.selected = indices.has(option.index);\n            }\n            storage.setValue(id, {\n              value: getValue(true)\n            });\n            selectedValues = getValue(false);\n          },\n          editable(event) {\n            event.target.disabled = !event.detail.editable;\n          }\n        };\n        this._dispatchEventFromSandbox(actions, jsEvent);\n      });\n      selectElement.addEventListener(\"input\", event => {\n        const exportValue = getValue(true);\n        const change = getValue(false);\n        storage.setValue(id, {\n          value: exportValue\n        });\n        event.preventDefault();\n        this.linkService.eventBus?.dispatch(\"dispatcheventinsandbox\", {\n          source: this,\n          detail: {\n            id,\n            name: \"Keystroke\",\n            value: selectedValues,\n            change,\n            changeEx: exportValue,\n            willCommit: false,\n            commitKey: 1,\n            keyDown: false\n          }\n        });\n      });\n      this._setEventListeners(selectElement, null, [[\"focus\", \"Focus\"], [\"blur\", \"Blur\"], [\"mousedown\", \"Mouse Down\"], [\"mouseenter\", \"Mouse Enter\"], [\"mouseleave\", \"Mouse Exit\"], [\"mouseup\", \"Mouse Up\"], [\"input\", \"Action\"], [\"input\", \"Validate\"]], event => event.target.value);\n    } else {\n      selectElement.addEventListener(\"input\", function (event) {\n        storage.setValue(id, {\n          value: getValue(true)\n        });\n      });\n    }\n    if (this.data.combo) {\n      this._setTextStyle(selectElement);\n    } else {}\n    this._setBackgroundColor(selectElement);\n    this._setDefaultPropertiesFromJS(selectElement);\n    this.container.append(selectElement);\n    return this.container;\n  }\n}\nclass PopupAnnotationElement extends AnnotationElement {\n  constructor(parameters) {\n    const {\n      data,\n      elements\n    } = parameters;\n    super(parameters, {\n      isRenderable: AnnotationElement._hasPopupData(data)\n    });\n    this.elements = elements;\n  }\n  render() {\n    this.container.classList.add(\"popupAnnotation\");\n    const popup = new PopupElement({\n      container: this.container,\n      color: this.data.color,\n      titleObj: this.data.titleObj,\n      modificationDate: this.data.modificationDate,\n      contentsObj: this.data.contentsObj,\n      richText: this.data.richText,\n      rect: this.data.rect,\n      parentRect: this.data.parentRect || null,\n      parent: this.parent,\n      elements: this.elements,\n      open: this.data.open\n    });\n    const elementIds = [];\n    for (const element of this.elements) {\n      element.popup = popup;\n      elementIds.push(element.data.id);\n      element.addHighlightArea();\n    }\n    this.container.setAttribute(\"aria-controls\", elementIds.map(id => `${util.AnnotationPrefix}${id}`).join(\",\"));\n    return this.container;\n  }\n}\nclass PopupElement {\n  #boundKeyDown = this.#keyDown.bind(this);\n  #boundHide = this.#hide.bind(this);\n  #boundShow = this.#show.bind(this);\n  #boundToggle = this.#toggle.bind(this);\n  #color = null;\n  #container = null;\n  #contentsObj = null;\n  #dateObj = null;\n  #elements = null;\n  #parent = null;\n  #parentRect = null;\n  #pinned = false;\n  #popup = null;\n  #rect = null;\n  #richText = null;\n  #titleObj = null;\n  #wasVisible = false;\n  constructor({\n    container,\n    color,\n    elements,\n    titleObj,\n    modificationDate,\n    contentsObj,\n    richText,\n    parent,\n    rect,\n    parentRect,\n    open\n  }) {\n    this.#container = container;\n    this.#titleObj = titleObj;\n    this.#contentsObj = contentsObj;\n    this.#richText = richText;\n    this.#parent = parent;\n    this.#color = color;\n    this.#rect = rect;\n    this.#parentRect = parentRect;\n    this.#elements = elements;\n    this.#dateObj = display_utils.PDFDateString.toDateObject(modificationDate);\n    this.trigger = elements.flatMap(e => e.getElementsToTriggerPopup());\n    for (const element of this.trigger) {\n      element.addEventListener(\"click\", this.#boundToggle);\n      element.addEventListener(\"mouseenter\", this.#boundShow);\n      element.addEventListener(\"mouseleave\", this.#boundHide);\n      element.classList.add(\"popupTriggerArea\");\n    }\n    for (const element of elements) {\n      element.container?.addEventListener(\"keydown\", this.#boundKeyDown);\n    }\n    this.#container.hidden = true;\n    if (open) {\n      this.#toggle();\n    }\n  }\n  render() {\n    if (this.#popup) {\n      return;\n    }\n    const {\n      page: {\n        view\n      },\n      viewport: {\n        rawDims: {\n          pageWidth,\n          pageHeight,\n          pageX,\n          pageY\n        }\n      }\n    } = this.#parent;\n    const popup = this.#popup = document.createElement(\"div\");\n    popup.className = \"popup\";\n    if (this.#color) {\n      const baseColor = popup.style.outlineColor = util.Util.makeHexColor(...this.#color);\n      if (CSS.supports(\"background-color\", \"color-mix(in srgb, red 30%, white)\")) {\n        popup.style.backgroundColor = `color-mix(in srgb, ${baseColor} 30%, white)`;\n      } else {\n        const BACKGROUND_ENLIGHT = 0.7;\n        popup.style.backgroundColor = util.Util.makeHexColor(...this.#color.map(c => Math.floor(BACKGROUND_ENLIGHT * (255 - c) + c)));\n      }\n    }\n    const header = document.createElement(\"span\");\n    header.className = \"header\";\n    const title = document.createElement(\"h1\");\n    header.append(title);\n    ({\n      dir: title.dir,\n      str: title.textContent\n    } = this.#titleObj);\n    popup.append(header);\n    if (this.#dateObj) {\n      const modificationDate = document.createElement(\"span\");\n      modificationDate.classList.add(\"popupDate\");\n      modificationDate.setAttribute(\"data-l10n-id\", \"pdfjs-annotation-date-string\");\n      modificationDate.setAttribute(\"data-l10n-args\", JSON.stringify({\n        date: this.#dateObj.toLocaleDateString(),\n        time: this.#dateObj.toLocaleTimeString()\n      }));\n      header.append(modificationDate);\n    }\n    const contentsObj = this.#contentsObj;\n    const richText = this.#richText;\n    if (richText?.str && (!contentsObj?.str || contentsObj.str === richText.str)) {\n      xfa_layer.XfaLayer.render({\n        xfaHtml: richText.html,\n        intent: \"richText\",\n        div: popup\n      });\n      popup.lastChild.classList.add(\"richText\", \"popupContent\");\n    } else {\n      const contents = this._formatContents(contentsObj);\n      popup.append(contents);\n    }\n    let useParentRect = !!this.#parentRect;\n    let rect = useParentRect ? this.#parentRect : this.#rect;\n    for (const element of this.#elements) {\n      if (!rect || util.Util.intersect(element.data.rect, rect) !== null) {\n        rect = element.data.rect;\n        useParentRect = true;\n        break;\n      }\n    }\n    const normalizedRect = util.Util.normalizeRect([rect[0], view[3] - rect[1] + view[1], rect[2], view[3] - rect[3] + view[1]]);\n    const HORIZONTAL_SPACE_AFTER_ANNOTATION = 5;\n    const parentWidth = useParentRect ? rect[2] - rect[0] + HORIZONTAL_SPACE_AFTER_ANNOTATION : 0;\n    const popupLeft = normalizedRect[0] + parentWidth;\n    const popupTop = normalizedRect[1];\n    const {\n      style\n    } = this.#container;\n    style.left = `${100 * (popupLeft - pageX) / pageWidth}%`;\n    style.top = `${100 * (popupTop - pageY) / pageHeight}%`;\n    this.#container.append(popup);\n  }\n  _formatContents({\n    str,\n    dir\n  }) {\n    const p = document.createElement(\"p\");\n    p.classList.add(\"popupContent\");\n    p.dir = dir;\n    const lines = str.split(/(?:\\r\\n?|\\n)/);\n    for (let i = 0, ii = lines.length; i < ii; ++i) {\n      const line = lines[i];\n      p.append(document.createTextNode(line));\n      if (i < ii - 1) {\n        p.append(document.createElement(\"br\"));\n      }\n    }\n    return p;\n  }\n  #keyDown(event) {\n    if (event.altKey || event.shiftKey || event.ctrlKey || event.metaKey) {\n      return;\n    }\n    if (event.key === \"Enter\" || event.key === \"Escape\" && this.#pinned) {\n      this.#toggle();\n    }\n  }\n  #toggle() {\n    this.#pinned = !this.#pinned;\n    if (this.#pinned) {\n      this.#show();\n      this.#container.addEventListener(\"click\", this.#boundToggle);\n      this.#container.addEventListener(\"keydown\", this.#boundKeyDown);\n    } else {\n      this.#hide();\n      this.#container.removeEventListener(\"click\", this.#boundToggle);\n      this.#container.removeEventListener(\"keydown\", this.#boundKeyDown);\n    }\n  }\n  #show() {\n    if (!this.#popup) {\n      this.render();\n    }\n    if (!this.isVisible) {\n      this.#container.hidden = false;\n      this.#container.style.zIndex = parseInt(this.#container.style.zIndex) + 1000;\n    } else if (this.#pinned) {\n      this.#container.classList.add(\"focused\");\n    }\n  }\n  #hide() {\n    this.#container.classList.remove(\"focused\");\n    if (this.#pinned || !this.isVisible) {\n      return;\n    }\n    this.#container.hidden = true;\n    this.#container.style.zIndex = parseInt(this.#container.style.zIndex) - 1000;\n  }\n  forceHide() {\n    this.#wasVisible = this.isVisible;\n    if (!this.#wasVisible) {\n      return;\n    }\n    this.#container.hidden = true;\n  }\n  maybeShow() {\n    if (!this.#wasVisible) {\n      return;\n    }\n    this.#wasVisible = false;\n    this.#container.hidden = false;\n  }\n  get isVisible() {\n    return this.#container.hidden === false;\n  }\n}\nclass FreeTextAnnotationElement extends AnnotationElement {\n  constructor(parameters) {\n    super(parameters, {\n      isRenderable: true,\n      ignoreBorder: true\n    });\n    this.textContent = parameters.data.textContent;\n    this.textPosition = parameters.data.textPosition;\n    this.annotationEditorType = util.AnnotationEditorType.FREETEXT;\n  }\n  render() {\n    this.container.classList.add(\"freeTextAnnotation\");\n    if (this.textContent) {\n      const content = document.createElement(\"div\");\n      content.classList.add(\"annotationTextContent\");\n      content.setAttribute(\"role\", \"comment\");\n      for (const line of this.textContent) {\n        const lineSpan = document.createElement(\"span\");\n        lineSpan.textContent = line;\n        content.append(lineSpan);\n      }\n      this.container.append(content);\n    }\n    if (!this.data.popupRef && this.hasPopupData) {\n      this._createPopup();\n    }\n    this._editOnDoubleClick();\n    return this.container;\n  }\n  get _isEditable() {\n    return this.data.hasOwnCanvas;\n  }\n}\nclass LineAnnotationElement extends AnnotationElement {\n  #line = null;\n  constructor(parameters) {\n    super(parameters, {\n      isRenderable: true,\n      ignoreBorder: true\n    });\n  }\n  render() {\n    this.container.classList.add(\"lineAnnotation\");\n    const data = this.data;\n    const {\n      width,\n      height\n    } = getRectDims(data.rect);\n    const svg = this.svgFactory.create(width, height, true);\n    const line = this.#line = this.svgFactory.createElement(\"svg:line\");\n    line.setAttribute(\"x1\", data.rect[2] - data.lineCoordinates[0]);\n    line.setAttribute(\"y1\", data.rect[3] - data.lineCoordinates[1]);\n    line.setAttribute(\"x2\", data.rect[2] - data.lineCoordinates[2]);\n    line.setAttribute(\"y2\", data.rect[3] - data.lineCoordinates[3]);\n    line.setAttribute(\"stroke-width\", data.borderStyle.width || 1);\n    line.setAttribute(\"stroke\", \"transparent\");\n    line.setAttribute(\"fill\", \"transparent\");\n    svg.append(line);\n    this.container.append(svg);\n    if (!data.popupRef && this.hasPopupData) {\n      this._createPopup();\n    }\n    return this.container;\n  }\n  getElementsToTriggerPopup() {\n    return this.#line;\n  }\n  addHighlightArea() {\n    this.container.classList.add(\"highlightArea\");\n  }\n}\nclass SquareAnnotationElement extends AnnotationElement {\n  #square = null;\n  constructor(parameters) {\n    super(parameters, {\n      isRenderable: true,\n      ignoreBorder: true\n    });\n  }\n  render() {\n    this.container.classList.add(\"squareAnnotation\");\n    const data = this.data;\n    const {\n      width,\n      height\n    } = getRectDims(data.rect);\n    const svg = this.svgFactory.create(width, height, true);\n    const borderWidth = data.borderStyle.width;\n    const square = this.#square = this.svgFactory.createElement(\"svg:rect\");\n    square.setAttribute(\"x\", borderWidth / 2);\n    square.setAttribute(\"y\", borderWidth / 2);\n    square.setAttribute(\"width\", width - borderWidth);\n    square.setAttribute(\"height\", height - borderWidth);\n    square.setAttribute(\"stroke-width\", borderWidth || 1);\n    square.setAttribute(\"stroke\", \"transparent\");\n    square.setAttribute(\"fill\", \"transparent\");\n    svg.append(square);\n    this.container.append(svg);\n    if (!data.popupRef && this.hasPopupData) {\n      this._createPopup();\n    }\n    return this.container;\n  }\n  getElementsToTriggerPopup() {\n    return this.#square;\n  }\n  addHighlightArea() {\n    this.container.classList.add(\"highlightArea\");\n  }\n}\nclass CircleAnnotationElement extends AnnotationElement {\n  #circle = null;\n  constructor(parameters) {\n    super(parameters, {\n      isRenderable: true,\n      ignoreBorder: true\n    });\n  }\n  render() {\n    this.container.classList.add(\"circleAnnotation\");\n    const data = this.data;\n    const {\n      width,\n      height\n    } = getRectDims(data.rect);\n    const svg = this.svgFactory.create(width, height, true);\n    const borderWidth = data.borderStyle.width;\n    const circle = this.#circle = this.svgFactory.createElement(\"svg:ellipse\");\n    circle.setAttribute(\"cx\", width / 2);\n    circle.setAttribute(\"cy\", height / 2);\n    circle.setAttribute(\"rx\", width / 2 - borderWidth / 2);\n    circle.setAttribute(\"ry\", height / 2 - borderWidth / 2);\n    circle.setAttribute(\"stroke-width\", borderWidth || 1);\n    circle.setAttribute(\"stroke\", \"transparent\");\n    circle.setAttribute(\"fill\", \"transparent\");\n    svg.append(circle);\n    this.container.append(svg);\n    if (!data.popupRef && this.hasPopupData) {\n      this._createPopup();\n    }\n    return this.container;\n  }\n  getElementsToTriggerPopup() {\n    return this.#circle;\n  }\n  addHighlightArea() {\n    this.container.classList.add(\"highlightArea\");\n  }\n}\nclass PolylineAnnotationElement extends AnnotationElement {\n  #polyline = null;\n  constructor(parameters) {\n    super(parameters, {\n      isRenderable: true,\n      ignoreBorder: true\n    });\n    this.containerClassName = \"polylineAnnotation\";\n    this.svgElementName = \"svg:polyline\";\n  }\n  render() {\n    this.container.classList.add(this.containerClassName);\n    const data = this.data;\n    const {\n      width,\n      height\n    } = getRectDims(data.rect);\n    const svg = this.svgFactory.create(width, height, true);\n    let points = [];\n    for (const coordinate of data.vertices) {\n      const x = coordinate.x - data.rect[0];\n      const y = data.rect[3] - coordinate.y;\n      points.push(x + \",\" + y);\n    }\n    points = points.join(\" \");\n    const polyline = this.#polyline = this.svgFactory.createElement(this.svgElementName);\n    polyline.setAttribute(\"points\", points);\n    polyline.setAttribute(\"stroke-width\", data.borderStyle.width || 1);\n    polyline.setAttribute(\"stroke\", \"transparent\");\n    polyline.setAttribute(\"fill\", \"transparent\");\n    svg.append(polyline);\n    this.container.append(svg);\n    if (!data.popupRef && this.hasPopupData) {\n      this._createPopup();\n    }\n    return this.container;\n  }\n  getElementsToTriggerPopup() {\n    return this.#polyline;\n  }\n  addHighlightArea() {\n    this.container.classList.add(\"highlightArea\");\n  }\n}\nclass PolygonAnnotationElement extends PolylineAnnotationElement {\n  constructor(parameters) {\n    super(parameters);\n    this.containerClassName = \"polygonAnnotation\";\n    this.svgElementName = \"svg:polygon\";\n  }\n}\nclass CaretAnnotationElement extends AnnotationElement {\n  constructor(parameters) {\n    super(parameters, {\n      isRenderable: true,\n      ignoreBorder: true\n    });\n  }\n  render() {\n    this.container.classList.add(\"caretAnnotation\");\n    if (!this.data.popupRef && this.hasPopupData) {\n      this._createPopup();\n    }\n    return this.container;\n  }\n}\nclass InkAnnotationElement extends AnnotationElement {\n  #polylines = [];\n  constructor(parameters) {\n    super(parameters, {\n      isRenderable: true,\n      ignoreBorder: true\n    });\n    this.containerClassName = \"inkAnnotation\";\n    this.svgElementName = \"svg:polyline\";\n    this.annotationEditorType = util.AnnotationEditorType.INK;\n  }\n  render() {\n    this.container.classList.add(this.containerClassName);\n    const data = this.data;\n    const {\n      width,\n      height\n    } = getRectDims(data.rect);\n    const svg = this.svgFactory.create(width, height, true);\n    for (const inkList of data.inkLists) {\n      let points = [];\n      for (const coordinate of inkList) {\n        const x = coordinate.x - data.rect[0];\n        const y = data.rect[3] - coordinate.y;\n        points.push(`${x},${y}`);\n      }\n      points = points.join(\" \");\n      const polyline = this.svgFactory.createElement(this.svgElementName);\n      this.#polylines.push(polyline);\n      polyline.setAttribute(\"points\", points);\n      polyline.setAttribute(\"stroke-width\", data.borderStyle.width || 1);\n      polyline.setAttribute(\"stroke\", \"transparent\");\n      polyline.setAttribute(\"fill\", \"transparent\");\n      if (!data.popupRef && this.hasPopupData) {\n        this._createPopup();\n      }\n      svg.append(polyline);\n    }\n    this.container.append(svg);\n    return this.container;\n  }\n  getElementsToTriggerPopup() {\n    return this.#polylines;\n  }\n  addHighlightArea() {\n    this.container.classList.add(\"highlightArea\");\n  }\n}\nclass HighlightAnnotationElement extends AnnotationElement {\n  constructor(parameters) {\n    super(parameters, {\n      isRenderable: true,\n      ignoreBorder: true,\n      createQuadrilaterals: true\n    });\n  }\n  render() {\n    if (!this.data.popupRef && this.hasPopupData) {\n      this._createPopup();\n    }\n    this.container.classList.add(\"highlightAnnotation\");\n    return this.container;\n  }\n}\nclass UnderlineAnnotationElement extends AnnotationElement {\n  constructor(parameters) {\n    super(parameters, {\n      isRenderable: true,\n      ignoreBorder: true,\n      createQuadrilaterals: true\n    });\n  }\n  render() {\n    if (!this.data.popupRef && this.hasPopupData) {\n      this._createPopup();\n    }\n    this.container.classList.add(\"underlineAnnotation\");\n    return this.container;\n  }\n}\nclass SquigglyAnnotationElement extends AnnotationElement {\n  constructor(parameters) {\n    super(parameters, {\n      isRenderable: true,\n      ignoreBorder: true,\n      createQuadrilaterals: true\n    });\n  }\n  render() {\n    if (!this.data.popupRef && this.hasPopupData) {\n      this._createPopup();\n    }\n    this.container.classList.add(\"squigglyAnnotation\");\n    return this.container;\n  }\n}\nclass StrikeOutAnnotationElement extends AnnotationElement {\n  constructor(parameters) {\n    super(parameters, {\n      isRenderable: true,\n      ignoreBorder: true,\n      createQuadrilaterals: true\n    });\n  }\n  render() {\n    if (!this.data.popupRef && this.hasPopupData) {\n      this._createPopup();\n    }\n    this.container.classList.add(\"strikeoutAnnotation\");\n    return this.container;\n  }\n}\nclass StampAnnotationElement extends AnnotationElement {\n  constructor(parameters) {\n    super(parameters, {\n      isRenderable: true,\n      ignoreBorder: true\n    });\n  }\n  render() {\n    this.container.classList.add(\"stampAnnotation\");\n    if (!this.data.popupRef && this.hasPopupData) {\n      this._createPopup();\n    }\n    return this.container;\n  }\n}\nclass FileAttachmentAnnotationElement extends AnnotationElement {\n  #trigger = null;\n  constructor(parameters) {\n    super(parameters, {\n      isRenderable: true\n    });\n    const {\n      filename,\n      content\n    } = this.data.file;\n    this.filename = (0,display_utils.getFilenameFromUrl)(filename, true);\n    this.content = content;\n    this.linkService.eventBus?.dispatch(\"fileattachmentannotation\", {\n      source: this,\n      filename,\n      content\n    });\n  }\n  render() {\n    this.container.classList.add(\"fileAttachmentAnnotation\");\n    const {\n      container,\n      data\n    } = this;\n    let trigger;\n    if (data.hasAppearance || data.fillAlpha === 0) {\n      trigger = document.createElement(\"div\");\n    } else {\n      trigger = document.createElement(\"img\");\n      trigger.src = `${this.imageResourcesPath}annotation-${/paperclip/i.test(data.name) ? \"paperclip\" : \"pushpin\"}.svg`;\n      if (data.fillAlpha && data.fillAlpha < 1) {\n        trigger.style = `filter: opacity(${Math.round(data.fillAlpha * 100)}%);`;\n      }\n    }\n    trigger.addEventListener(\"dblclick\", this.#download.bind(this));\n    this.#trigger = trigger;\n    const {\n      isMac\n    } = util.FeatureTest.platform;\n    container.addEventListener(\"keydown\", evt => {\n      if (evt.key === \"Enter\" && (isMac ? evt.metaKey : evt.ctrlKey)) {\n        this.#download();\n      }\n    });\n    if (!data.popupRef && this.hasPopupData) {\n      this._createPopup();\n    } else {\n      trigger.classList.add(\"popupTriggerArea\");\n    }\n    container.append(trigger);\n    return container;\n  }\n  getElementsToTriggerPopup() {\n    return this.#trigger;\n  }\n  addHighlightArea() {\n    this.container.classList.add(\"highlightArea\");\n  }\n  #download() {\n    this.downloadManager?.openOrDownloadData(this.content, this.filename);\n  }\n}\nclass AnnotationLayer {\n  #accessibilityManager = null;\n  #annotationCanvasMap = null;\n  #editableAnnotations = new Map();\n  constructor({\n    div,\n    accessibilityManager,\n    annotationCanvasMap,\n    annotationEditorUIManager,\n    page,\n    viewport\n  }) {\n    this.div = div;\n    this.#accessibilityManager = accessibilityManager;\n    this.#annotationCanvasMap = annotationCanvasMap;\n    this.page = page;\n    this.viewport = viewport;\n    this.zIndex = 0;\n    this._annotationEditorUIManager = annotationEditorUIManager;\n  }\n  #appendElement(element, id) {\n    const contentElement = element.firstChild || element;\n    contentElement.id = `${util.AnnotationPrefix}${id}`;\n    this.div.append(element);\n    this.#accessibilityManager?.moveElementInDOM(this.div, element, contentElement, false);\n  }\n  async render(params) {\n    const {\n      annotations\n    } = params;\n    const layer = this.div;\n    (0,display_utils.setLayerDimensions)(layer, this.viewport);\n    const popupToElements = new Map();\n    const elementParams = {\n      data: null,\n      layer,\n      linkService: params.linkService,\n      downloadManager: params.downloadManager,\n      imageResourcesPath: params.imageResourcesPath || \"\",\n      renderForms: params.renderForms !== false,\n      svgFactory: new display_utils.DOMSVGFactory(),\n      annotationStorage: params.annotationStorage || new annotation_storage.AnnotationStorage(),\n      enableScripting: params.enableScripting === true,\n      hasJSActions: params.hasJSActions,\n      fieldObjects: params.fieldObjects,\n      parent: this,\n      elements: null\n    };\n    for (const data of annotations) {\n      if (data.noHTML) {\n        continue;\n      }\n      const isPopupAnnotation = data.annotationType === util.AnnotationType.POPUP;\n      if (!isPopupAnnotation) {\n        const {\n          width,\n          height\n        } = getRectDims(data.rect);\n        if (width <= 0 || height <= 0) {\n          continue;\n        }\n      } else {\n        const elements = popupToElements.get(data.id);\n        if (!elements) {\n          continue;\n        }\n        elementParams.elements = elements;\n      }\n      elementParams.data = data;\n      const element = AnnotationElementFactory.create(elementParams);\n      if (!element.isRenderable) {\n        continue;\n      }\n      if (!isPopupAnnotation && data.popupRef) {\n        const elements = popupToElements.get(data.popupRef);\n        if (!elements) {\n          popupToElements.set(data.popupRef, [element]);\n        } else {\n          elements.push(element);\n        }\n      }\n      const rendered = element.render();\n      if (data.hidden) {\n        rendered.style.visibility = \"hidden\";\n      }\n      this.#appendElement(rendered, data.id);\n      if (element.annotationEditorType > 0) {\n        this.#editableAnnotations.set(element.data.id, element);\n        this._annotationEditorUIManager?.renderAnnotationElement(element);\n      }\n    }\n    this.#setAnnotationCanvasMap();\n  }\n  update({\n    viewport\n  }) {\n    const layer = this.div;\n    this.viewport = viewport;\n    (0,display_utils.setLayerDimensions)(layer, {\n      rotation: viewport.rotation\n    });\n    this.#setAnnotationCanvasMap();\n    layer.hidden = false;\n  }\n  #setAnnotationCanvasMap() {\n    if (!this.#annotationCanvasMap) {\n      return;\n    }\n    const layer = this.div;\n    for (const [id, canvas] of this.#annotationCanvasMap) {\n      const element = layer.querySelector(`[data-annotation-id=\"${id}\"]`);\n      if (!element) {\n        continue;\n      }\n      canvas.className = \"annotationContent\";\n      const {\n        firstChild\n      } = element;\n      if (!firstChild) {\n        element.append(canvas);\n      } else if (firstChild.nodeName === \"CANVAS\") {\n        firstChild.replaceWith(canvas);\n      } else if (!firstChild.classList.contains(\"annotationContent\")) {\n        firstChild.before(canvas);\n      } else {\n        firstChild.after(canvas);\n      }\n    }\n    this.#annotationCanvasMap.clear();\n  }\n  getEditableAnnotations() {\n    return Array.from(this.#editableAnnotations.values());\n  }\n  getEditableAnnotation(id) {\n    return this.#editableAnnotations.get(id);\n  }\n}\n\n\n/***/ }),\n\n/***/ 792:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   AnnotationStorage: () => (/* binding */ AnnotationStorage),\n/* harmony export */   PrintAnnotationStorage: () => (/* binding */ PrintAnnotationStorage),\n/* harmony export */   SerializableEmpty: () => (/* binding */ SerializableEmpty)\n/* harmony export */ });\n/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292);\n/* harmony import */ var _editor_editor_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(310);\n/* harmony import */ var _shared_murmurhash3_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(651);\n\n\n\nconst SerializableEmpty = Object.freeze({\n  map: null,\n  hash: \"\",\n  transfer: undefined\n});\nclass AnnotationStorage {\n  #modified = false;\n  #storage = new Map();\n  constructor() {\n    this.onSetModified = null;\n    this.onResetModified = null;\n    this.onAnnotationEditor = null;\n  }\n  getValue(key, defaultValue) {\n    const value = this.#storage.get(key);\n    if (value === undefined) {\n      return defaultValue;\n    }\n    return Object.assign(defaultValue, value);\n  }\n  getRawValue(key) {\n    return this.#storage.get(key);\n  }\n  remove(key) {\n    this.#storage.delete(key);\n    if (this.#storage.size === 0) {\n      this.resetModified();\n    }\n    if (typeof this.onAnnotationEditor === \"function\") {\n      for (const value of this.#storage.values()) {\n        if (value instanceof _editor_editor_js__WEBPACK_IMPORTED_MODULE_1__.AnnotationEditor) {\n          return;\n        }\n      }\n      this.onAnnotationEditor(null);\n    }\n  }\n  setValue(key, value) {\n    const obj = this.#storage.get(key);\n    let modified = false;\n    if (obj !== undefined) {\n      for (const [entry, val] of Object.entries(value)) {\n        if (obj[entry] !== val) {\n          modified = true;\n          obj[entry] = val;\n        }\n      }\n    } else {\n      modified = true;\n      this.#storage.set(key, value);\n    }\n    if (modified) {\n      this.#setModified();\n    }\n    if (value instanceof _editor_editor_js__WEBPACK_IMPORTED_MODULE_1__.AnnotationEditor && typeof this.onAnnotationEditor === \"function\") {\n      this.onAnnotationEditor(value.constructor._type);\n    }\n  }\n  has(key) {\n    return this.#storage.has(key);\n  }\n  getAll() {\n    return this.#storage.size > 0 ? (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.objectFromMap)(this.#storage) : null;\n  }\n  setAll(obj) {\n    for (const [key, val] of Object.entries(obj)) {\n      this.setValue(key, val);\n    }\n  }\n  get size() {\n    return this.#storage.size;\n  }\n  #setModified() {\n    if (!this.#modified) {\n      this.#modified = true;\n      if (typeof this.onSetModified === \"function\") {\n        this.onSetModified();\n      }\n    }\n  }\n  resetModified() {\n    if (this.#modified) {\n      this.#modified = false;\n      if (typeof this.onResetModified === \"function\") {\n        this.onResetModified();\n      }\n    }\n  }\n  get print() {\n    return new PrintAnnotationStorage(this);\n  }\n  get serializable() {\n    if (this.#storage.size === 0) {\n      return SerializableEmpty;\n    }\n    const map = new Map(),\n      hash = new _shared_murmurhash3_js__WEBPACK_IMPORTED_MODULE_2__.MurmurHash3_64(),\n      transfer = [];\n    const context = Object.create(null);\n    let hasBitmap = false;\n    for (const [key, val] of this.#storage) {\n      const serialized = val instanceof _editor_editor_js__WEBPACK_IMPORTED_MODULE_1__.AnnotationEditor ? val.serialize(false, context) : val;\n      if (serialized) {\n        map.set(key, serialized);\n        hash.update(`${key}:${JSON.stringify(serialized)}`);\n        hasBitmap ||= !!serialized.bitmap;\n      }\n    }\n    if (hasBitmap) {\n      for (const value of map.values()) {\n        if (value.bitmap) {\n          transfer.push(value.bitmap);\n        }\n      }\n    }\n    return map.size > 0 ? {\n      map,\n      hash: hash.hexdigest(),\n      transfer\n    } : SerializableEmpty;\n  }\n  get editorStats() {\n    let stats = null;\n    const typeToEditor = new Map();\n    for (const value of this.#storage.values()) {\n      if (!(value instanceof _editor_editor_js__WEBPACK_IMPORTED_MODULE_1__.AnnotationEditor)) {\n        continue;\n      }\n      const editorStats = value.telemetryFinalData;\n      if (!editorStats) {\n        continue;\n      }\n      const {\n        type\n      } = editorStats;\n      if (!typeToEditor.has(type)) {\n        typeToEditor.set(type, Object.getPrototypeOf(value).constructor);\n      }\n      stats ||= Object.create(null);\n      const map = stats[type] ||= new Map();\n      for (const [key, val] of Object.entries(editorStats)) {\n        if (key === \"type\") {\n          continue;\n        }\n        let counters = map.get(key);\n        if (!counters) {\n          counters = new Map();\n          map.set(key, counters);\n        }\n        const count = counters.get(val) ?? 0;\n        counters.set(val, count + 1);\n      }\n    }\n    for (const [type, editor] of typeToEditor) {\n      stats[type] = editor.computeTelemetryFinalData(stats[type]);\n    }\n    return stats;\n  }\n}\nclass PrintAnnotationStorage extends AnnotationStorage {\n  #serializable;\n  constructor(parent) {\n    super();\n    const {\n      map,\n      hash,\n      transfer\n    } = parent.serializable;\n    const clone = structuredClone(map, transfer ? {\n      transfer\n    } : null);\n    this.#serializable = {\n      map: clone,\n      hash,\n      transfer\n    };\n  }\n  get print() {\n    (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)(\"Should not call PrintAnnotationStorage.print\");\n  }\n  get serializable() {\n    return this.#serializable;\n  }\n}\n\n\n/***/ }),\n\n/***/ 831:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   PDFDataRangeTransport: () => (/* binding */ PDFDataRangeTransport),\n/* harmony export */   PDFWorker: () => (/* binding */ PDFWorker),\n/* harmony export */   build: () => (/* binding */ build),\n/* harmony export */   getDocument: () => (/* binding */ getDocument),\n/* harmony export */   version: () => (/* binding */ version)\n/* harmony export */ });\n/* unused harmony exports DefaultCanvasFactory, DefaultCMapReaderFactory, DefaultFilterFactory, DefaultStandardFontDataFactory, LoopbackPort, PDFDocumentLoadingTask, PDFDocumentProxy, PDFPageProxy, PDFWorkerUtil, RenderTask */\n/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292);\n/* harmony import */ var _annotation_storage_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(792);\n/* harmony import */ var _display_utils_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(419);\n/* harmony import */ var _font_loader_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(10);\n/* harmony import */ var display_node_utils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(573);\n/* harmony import */ var _canvas_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(923);\n/* harmony import */ var _text_layer_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(814);\n/* harmony import */ var _worker_options_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(164);\n/* harmony import */ var _shared_message_handler_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(178);\n/* harmony import */ var _metadata_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(62);\n/* harmony import */ var _optional_content_config_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(626);\n/* harmony import */ var _transport_stream_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(585);\n/* harmony import */ var display_fetch_stream__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(94);\n/* harmony import */ var display_network__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(457);\n/* harmony import */ var display_node_stream__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(786);\n/* harmony import */ var _xfa_text_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(50);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([display_node_utils__WEBPACK_IMPORTED_MODULE_4__, display_node_stream__WEBPACK_IMPORTED_MODULE_13__]);\n([display_node_utils__WEBPACK_IMPORTED_MODULE_4__, display_node_stream__WEBPACK_IMPORTED_MODULE_13__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__);\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst DEFAULT_RANGE_CHUNK_SIZE = 65536;\nconst RENDERING_CANCELLED_TIMEOUT = 100;\nconst DELAYED_CLEANUP_TIMEOUT = 5000;\nconst DefaultCanvasFactory = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.isNodeJS ? display_node_utils__WEBPACK_IMPORTED_MODULE_4__.NodeCanvasFactory : _display_utils_js__WEBPACK_IMPORTED_MODULE_2__.DOMCanvasFactory;\nconst DefaultCMapReaderFactory = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.isNodeJS ? display_node_utils__WEBPACK_IMPORTED_MODULE_4__.NodeCMapReaderFactory : _display_utils_js__WEBPACK_IMPORTED_MODULE_2__.DOMCMapReaderFactory;\nconst DefaultFilterFactory = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.isNodeJS ? display_node_utils__WEBPACK_IMPORTED_MODULE_4__.NodeFilterFactory : _display_utils_js__WEBPACK_IMPORTED_MODULE_2__.DOMFilterFactory;\nconst DefaultStandardFontDataFactory = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.isNodeJS ? display_node_utils__WEBPACK_IMPORTED_MODULE_4__.NodeStandardFontDataFactory : _display_utils_js__WEBPACK_IMPORTED_MODULE_2__.DOMStandardFontDataFactory;\nfunction getDocument(src) {\n  if (typeof src === \"string\" || src instanceof URL) {\n    src = {\n      url: src\n    };\n  } else if (src instanceof ArrayBuffer || ArrayBuffer.isView(src)) {\n    src = {\n      data: src\n    };\n  }\n  if (typeof src !== \"object\") {\n    throw new Error(\"Invalid parameter in getDocument, need parameter object.\");\n  }\n  if (!src.url && !src.data && !src.range) {\n    throw new Error(\"Invalid parameter object: need either .data, .range or .url\");\n  }\n  const task = new PDFDocumentLoadingTask();\n  const {\n    docId\n  } = task;\n  const url = src.url ? getUrlProp(src.url) : null;\n  const data = src.data ? getDataProp(src.data) : null;\n  const httpHeaders = src.httpHeaders || null;\n  const withCredentials = src.withCredentials === true;\n  const password = src.password ?? null;\n  const rangeTransport = src.range instanceof PDFDataRangeTransport ? src.range : null;\n  const rangeChunkSize = Number.isInteger(src.rangeChunkSize) && src.rangeChunkSize > 0 ? src.rangeChunkSize : DEFAULT_RANGE_CHUNK_SIZE;\n  let worker = src.worker instanceof PDFWorker ? src.worker : null;\n  const verbosity = src.verbosity;\n  const docBaseUrl = typeof src.docBaseUrl === \"string\" && !(0,_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.isDataScheme)(src.docBaseUrl) ? src.docBaseUrl : null;\n  const cMapUrl = typeof src.cMapUrl === \"string\" ? src.cMapUrl : null;\n  const cMapPacked = src.cMapPacked !== false;\n  const CMapReaderFactory = src.CMapReaderFactory || DefaultCMapReaderFactory;\n  const standardFontDataUrl = typeof src.standardFontDataUrl === \"string\" ? src.standardFontDataUrl : null;\n  const StandardFontDataFactory = src.StandardFontDataFactory || DefaultStandardFontDataFactory;\n  const ignoreErrors = src.stopAtErrors !== true;\n  const maxImageSize = Number.isInteger(src.maxImageSize) && src.maxImageSize > -1 ? src.maxImageSize : -1;\n  const isEvalSupported = src.isEvalSupported !== false;\n  const isOffscreenCanvasSupported = typeof src.isOffscreenCanvasSupported === \"boolean\" ? src.isOffscreenCanvasSupported : !_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.isNodeJS;\n  const canvasMaxAreaInBytes = Number.isInteger(src.canvasMaxAreaInBytes) ? src.canvasMaxAreaInBytes : -1;\n  const disableFontFace = typeof src.disableFontFace === \"boolean\" ? src.disableFontFace : _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.isNodeJS;\n  const fontExtraProperties = src.fontExtraProperties === true;\n  const enableXfa = src.enableXfa === true;\n  const ownerDocument = src.ownerDocument || globalThis.document;\n  const disableRange = src.disableRange === true;\n  const disableStream = src.disableStream === true;\n  const disableAutoFetch = src.disableAutoFetch === true;\n  const pdfBug = src.pdfBug === true;\n  const length = rangeTransport ? rangeTransport.length : src.length ?? NaN;\n  const useSystemFonts = typeof src.useSystemFonts === \"boolean\" ? src.useSystemFonts : !_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.isNodeJS && !disableFontFace;\n  const useWorkerFetch = typeof src.useWorkerFetch === \"boolean\" ? src.useWorkerFetch : CMapReaderFactory === _display_utils_js__WEBPACK_IMPORTED_MODULE_2__.DOMCMapReaderFactory && StandardFontDataFactory === _display_utils_js__WEBPACK_IMPORTED_MODULE_2__.DOMStandardFontDataFactory && cMapUrl && standardFontDataUrl && (0,_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.isValidFetchUrl)(cMapUrl, document.baseURI) && (0,_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.isValidFetchUrl)(standardFontDataUrl, document.baseURI);\n  const canvasFactory = src.canvasFactory || new DefaultCanvasFactory({\n    ownerDocument\n  });\n  const filterFactory = src.filterFactory || new DefaultFilterFactory({\n    docId,\n    ownerDocument\n  });\n  const styleElement = null;\n  (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.setVerbosityLevel)(verbosity);\n  const transportFactory = {\n    canvasFactory,\n    filterFactory\n  };\n  if (!useWorkerFetch) {\n    transportFactory.cMapReaderFactory = new CMapReaderFactory({\n      baseUrl: cMapUrl,\n      isCompressed: cMapPacked\n    });\n    transportFactory.standardFontDataFactory = new StandardFontDataFactory({\n      baseUrl: standardFontDataUrl\n    });\n  }\n  if (!worker) {\n    const workerParams = {\n      verbosity,\n      port: _worker_options_js__WEBPACK_IMPORTED_MODULE_14__.GlobalWorkerOptions.workerPort\n    };\n    worker = workerParams.port ? PDFWorker.fromPort(workerParams) : new PDFWorker(workerParams);\n    task._worker = worker;\n  }\n  const fetchDocParams = {\n    docId,\n    apiVersion: \"4.2.67\",\n    data,\n    password,\n    disableAutoFetch,\n    rangeChunkSize,\n    length,\n    docBaseUrl,\n    enableXfa,\n    evaluatorOptions: {\n      maxImageSize,\n      disableFontFace,\n      ignoreErrors,\n      isEvalSupported,\n      isOffscreenCanvasSupported,\n      canvasMaxAreaInBytes,\n      fontExtraProperties,\n      useSystemFonts,\n      cMapUrl: useWorkerFetch ? cMapUrl : null,\n      standardFontDataUrl: useWorkerFetch ? standardFontDataUrl : null\n    }\n  };\n  const transportParams = {\n    ignoreErrors,\n    disableFontFace,\n    fontExtraProperties,\n    enableXfa,\n    ownerDocument,\n    disableAutoFetch,\n    pdfBug,\n    styleElement\n  };\n  worker.promise.then(function () {\n    if (task.destroyed) {\n      throw new Error(\"Loading aborted\");\n    }\n    const workerIdPromise = _fetchDocument(worker, fetchDocParams);\n    const networkStreamPromise = new Promise(function (resolve) {\n      let networkStream;\n      if (rangeTransport) {\n        networkStream = new _transport_stream_js__WEBPACK_IMPORTED_MODULE_10__.PDFDataTransportStream(rangeTransport, {\n          disableRange,\n          disableStream\n        });\n      } else if (!data) {\n        const createPDFNetworkStream = params => {\n          if (_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.isNodeJS) {\n            const isFetchSupported = function () {\n              return typeof fetch !== \"undefined\" && typeof Response !== \"undefined\" && \"body\" in Response.prototype;\n            };\n            return isFetchSupported() && (0,_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.isValidFetchUrl)(params.url) ? new display_fetch_stream__WEBPACK_IMPORTED_MODULE_11__.PDFFetchStream(params) : new display_node_stream__WEBPACK_IMPORTED_MODULE_13__.PDFNodeStream(params);\n          }\n          return (0,_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.isValidFetchUrl)(params.url) ? new display_fetch_stream__WEBPACK_IMPORTED_MODULE_11__.PDFFetchStream(params) : new display_network__WEBPACK_IMPORTED_MODULE_12__.PDFNetworkStream(params);\n        };\n        networkStream = createPDFNetworkStream({\n          url,\n          length,\n          httpHeaders,\n          withCredentials,\n          rangeChunkSize,\n          disableRange,\n          disableStream\n        });\n      }\n      resolve(networkStream);\n    });\n    return Promise.all([workerIdPromise, networkStreamPromise]).then(function ([workerId, networkStream]) {\n      if (task.destroyed) {\n        throw new Error(\"Loading aborted\");\n      }\n      const messageHandler = new _shared_message_handler_js__WEBPACK_IMPORTED_MODULE_7__.MessageHandler(docId, workerId, worker.port);\n      const transport = new WorkerTransport(messageHandler, task, networkStream, transportParams, transportFactory);\n      task._transport = transport;\n      messageHandler.send(\"Ready\", null);\n    });\n  }).catch(task._capability.reject);\n  return task;\n}\nasync function _fetchDocument(worker, source) {\n  if (worker.destroyed) {\n    throw new Error(\"Worker was destroyed\");\n  }\n  const workerId = await worker.messageHandler.sendWithPromise(\"GetDocRequest\", source, source.data ? [source.data.buffer] : null);\n  if (worker.destroyed) {\n    throw new Error(\"Worker was destroyed\");\n  }\n  return workerId;\n}\nfunction getUrlProp(val) {\n  if (val instanceof URL) {\n    return val.href;\n  }\n  try {\n    return new URL(val, window.location).href;\n  } catch {\n    if (_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.isNodeJS && typeof val === \"string\") {\n      return val;\n    }\n  }\n  throw new Error(\"Invalid PDF url data: \" + \"either string or URL-object is expected in the url property.\");\n}\nfunction getDataProp(val) {\n  if (_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.isNodeJS && typeof Buffer !== \"undefined\" && val instanceof Buffer) {\n    throw new Error(\"Please provide binary data as `Uint8Array`, rather than `Buffer`.\");\n  }\n  if (val instanceof Uint8Array && val.byteLength === val.buffer.byteLength) {\n    return val;\n  }\n  if (typeof val === \"string\") {\n    return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.stringToBytes)(val);\n  }\n  if (val instanceof ArrayBuffer || ArrayBuffer.isView(val) || typeof val === \"object\" && !isNaN(val?.length)) {\n    return new Uint8Array(val);\n  }\n  throw new Error(\"Invalid PDF binary data: either TypedArray, \" + \"string, or array-like object is expected in the data property.\");\n}\nfunction isRefProxy(ref) {\n  return typeof ref === \"object\" && Number.isInteger(ref?.num) && ref.num >= 0 && Number.isInteger(ref?.gen) && ref.gen >= 0;\n}\nclass PDFDocumentLoadingTask {\n  static #docId = 0;\n  constructor() {\n    this._capability = Promise.withResolvers();\n    this._transport = null;\n    this._worker = null;\n    this.docId = `d${PDFDocumentLoadingTask.#docId++}`;\n    this.destroyed = false;\n    this.onPassword = null;\n    this.onProgress = null;\n  }\n  get promise() {\n    return this._capability.promise;\n  }\n  async destroy() {\n    this.destroyed = true;\n    try {\n      if (this._worker?.port) {\n        this._worker._pendingDestroy = true;\n      }\n      await this._transport?.destroy();\n    } catch (ex) {\n      if (this._worker?.port) {\n        delete this._worker._pendingDestroy;\n      }\n      throw ex;\n    }\n    this._transport = null;\n    if (this._worker) {\n      this._worker.destroy();\n      this._worker = null;\n    }\n  }\n}\nclass PDFDataRangeTransport {\n  constructor(length, initialData, progressiveDone = false, contentDispositionFilename = null) {\n    this.length = length;\n    this.initialData = initialData;\n    this.progressiveDone = progressiveDone;\n    this.contentDispositionFilename = contentDispositionFilename;\n    this._rangeListeners = [];\n    this._progressListeners = [];\n    this._progressiveReadListeners = [];\n    this._progressiveDoneListeners = [];\n    this._readyCapability = Promise.withResolvers();\n  }\n  addRangeListener(listener) {\n    this._rangeListeners.push(listener);\n  }\n  addProgressListener(listener) {\n    this._progressListeners.push(listener);\n  }\n  addProgressiveReadListener(listener) {\n    this._progressiveReadListeners.push(listener);\n  }\n  addProgressiveDoneListener(listener) {\n    this._progressiveDoneListeners.push(listener);\n  }\n  onDataRange(begin, chunk) {\n    for (const listener of this._rangeListeners) {\n      listener(begin, chunk);\n    }\n  }\n  onDataProgress(loaded, total) {\n    this._readyCapability.promise.then(() => {\n      for (const listener of this._progressListeners) {\n        listener(loaded, total);\n      }\n    });\n  }\n  onDataProgressiveRead(chunk) {\n    this._readyCapability.promise.then(() => {\n      for (const listener of this._progressiveReadListeners) {\n        listener(chunk);\n      }\n    });\n  }\n  onDataProgressiveDone() {\n    this._readyCapability.promise.then(() => {\n      for (const listener of this._progressiveDoneListeners) {\n        listener();\n      }\n    });\n  }\n  transportReady() {\n    this._readyCapability.resolve();\n  }\n  requestDataRange(begin, end) {\n    (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)(\"Abstract method PDFDataRangeTransport.requestDataRange\");\n  }\n  abort() {}\n}\nclass PDFDocumentProxy {\n  constructor(pdfInfo, transport) {\n    this._pdfInfo = pdfInfo;\n    this._transport = transport;\n  }\n  get annotationStorage() {\n    return this._transport.annotationStorage;\n  }\n  get filterFactory() {\n    return this._transport.filterFactory;\n  }\n  get numPages() {\n    return this._pdfInfo.numPages;\n  }\n  get fingerprints() {\n    return this._pdfInfo.fingerprints;\n  }\n  get isPureXfa() {\n    return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, \"isPureXfa\", !!this._transport._htmlForXfa);\n  }\n  get allXfaHtml() {\n    return this._transport._htmlForXfa;\n  }\n  getPage(pageNumber) {\n    return this._transport.getPage(pageNumber);\n  }\n  getPageIndex(ref) {\n    return this._transport.getPageIndex(ref);\n  }\n  getDestinations() {\n    return this._transport.getDestinations();\n  }\n  getDestination(id) {\n    return this._transport.getDestination(id);\n  }\n  getPageLabels() {\n    return this._transport.getPageLabels();\n  }\n  getPageLayout() {\n    return this._transport.getPageLayout();\n  }\n  getPageMode() {\n    return this._transport.getPageMode();\n  }\n  getViewerPreferences() {\n    return this._transport.getViewerPreferences();\n  }\n  getOpenAction() {\n    return this._transport.getOpenAction();\n  }\n  getAttachments() {\n    return this._transport.getAttachments();\n  }\n  getJSActions() {\n    return this._transport.getDocJSActions();\n  }\n  getOutline() {\n    return this._transport.getOutline();\n  }\n  getOptionalContentConfig({\n    intent = \"display\"\n  } = {}) {\n    const {\n      renderingIntent\n    } = this._transport.getRenderingIntent(intent);\n    return this._transport.getOptionalContentConfig(renderingIntent);\n  }\n  getPermissions() {\n    return this._transport.getPermissions();\n  }\n  getMetadata() {\n    return this._transport.getMetadata();\n  }\n  getMarkInfo() {\n    return this._transport.getMarkInfo();\n  }\n  getData() {\n    return this._transport.getData();\n  }\n  saveDocument() {\n    return this._transport.saveDocument();\n  }\n  getDownloadInfo() {\n    return this._transport.downloadInfoCapability.promise;\n  }\n  cleanup(keepLoadedFonts = false) {\n    return this._transport.startCleanup(keepLoadedFonts || this.isPureXfa);\n  }\n  destroy() {\n    return this.loadingTask.destroy();\n  }\n  cachedPageNumber(ref) {\n    return this._transport.cachedPageNumber(ref);\n  }\n  get loadingParams() {\n    return this._transport.loadingParams;\n  }\n  get loadingTask() {\n    return this._transport.loadingTask;\n  }\n  getFieldObjects() {\n    return this._transport.getFieldObjects();\n  }\n  hasJSActions() {\n    return this._transport.hasJSActions();\n  }\n  getCalculationOrderIds() {\n    return this._transport.getCalculationOrderIds();\n  }\n}\nclass PDFPageProxy {\n  #delayedCleanupTimeout = null;\n  #pendingCleanup = false;\n  constructor(pageIndex, pageInfo, transport, pdfBug = false) {\n    this._pageIndex = pageIndex;\n    this._pageInfo = pageInfo;\n    this._transport = transport;\n    this._stats = pdfBug ? new _display_utils_js__WEBPACK_IMPORTED_MODULE_2__.StatTimer() : null;\n    this._pdfBug = pdfBug;\n    this.commonObjs = transport.commonObjs;\n    this.objs = new PDFObjects();\n    this._maybeCleanupAfterRender = false;\n    this._intentStates = new Map();\n    this.destroyed = false;\n  }\n  get pageNumber() {\n    return this._pageIndex + 1;\n  }\n  get rotate() {\n    return this._pageInfo.rotate;\n  }\n  get ref() {\n    return this._pageInfo.ref;\n  }\n  get userUnit() {\n    return this._pageInfo.userUnit;\n  }\n  get view() {\n    return this._pageInfo.view;\n  }\n  getViewport({\n    scale,\n    rotation = this.rotate,\n    offsetX = 0,\n    offsetY = 0,\n    dontFlip = false\n  } = {}) {\n    return new _display_utils_js__WEBPACK_IMPORTED_MODULE_2__.PageViewport({\n      viewBox: this.view,\n      scale,\n      rotation,\n      offsetX,\n      offsetY,\n      dontFlip\n    });\n  }\n  getAnnotations({\n    intent = \"display\"\n  } = {}) {\n    const {\n      renderingIntent\n    } = this._transport.getRenderingIntent(intent);\n    return this._transport.getAnnotations(this._pageIndex, renderingIntent);\n  }\n  getJSActions() {\n    return this._transport.getPageJSActions(this._pageIndex);\n  }\n  get filterFactory() {\n    return this._transport.filterFactory;\n  }\n  get isPureXfa() {\n    return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, \"isPureXfa\", !!this._transport._htmlForXfa);\n  }\n  async getXfa() {\n    return this._transport._htmlForXfa?.children[this._pageIndex] || null;\n  }\n  render({\n    canvasContext,\n    viewport,\n    intent = \"display\",\n    annotationMode = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE,\n    transform = null,\n    background = null,\n    optionalContentConfigPromise = null,\n    annotationCanvasMap = null,\n    pageColors = null,\n    printAnnotationStorage = null\n  }) {\n    this._stats?.time(\"Overall\");\n    const intentArgs = this._transport.getRenderingIntent(intent, annotationMode, printAnnotationStorage);\n    const {\n      renderingIntent,\n      cacheKey\n    } = intentArgs;\n    this.#pendingCleanup = false;\n    this.#abortDelayedCleanup();\n    optionalContentConfigPromise ||= this._transport.getOptionalContentConfig(renderingIntent);\n    let intentState = this._intentStates.get(cacheKey);\n    if (!intentState) {\n      intentState = Object.create(null);\n      this._intentStates.set(cacheKey, intentState);\n    }\n    if (intentState.streamReaderCancelTimeout) {\n      clearTimeout(intentState.streamReaderCancelTimeout);\n      intentState.streamReaderCancelTimeout = null;\n    }\n    const intentPrint = !!(renderingIntent & _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.RenderingIntentFlag.PRINT);\n    if (!intentState.displayReadyCapability) {\n      intentState.displayReadyCapability = Promise.withResolvers();\n      intentState.operatorList = {\n        fnArray: [],\n        argsArray: [],\n        lastChunk: false,\n        separateAnnots: null\n      };\n      this._stats?.time(\"Page Request\");\n      this._pumpOperatorList(intentArgs);\n    }\n    const complete = error => {\n      intentState.renderTasks.delete(internalRenderTask);\n      if (this._maybeCleanupAfterRender || intentPrint) {\n        this.#pendingCleanup = true;\n      }\n      this.#tryCleanup(!intentPrint);\n      if (error) {\n        internalRenderTask.capability.reject(error);\n        this._abortOperatorList({\n          intentState,\n          reason: error instanceof Error ? error : new Error(error)\n        });\n      } else {\n        internalRenderTask.capability.resolve();\n      }\n      this._stats?.timeEnd(\"Rendering\");\n      this._stats?.timeEnd(\"Overall\");\n    };\n    const internalRenderTask = new InternalRenderTask({\n      callback: complete,\n      params: {\n        canvasContext,\n        viewport,\n        transform,\n        background\n      },\n      objs: this.objs,\n      commonObjs: this.commonObjs,\n      annotationCanvasMap,\n      operatorList: intentState.operatorList,\n      pageIndex: this._pageIndex,\n      canvasFactory: this._transport.canvasFactory,\n      filterFactory: this._transport.filterFactory,\n      useRequestAnimationFrame: !intentPrint,\n      pdfBug: this._pdfBug,\n      pageColors\n    });\n    (intentState.renderTasks ||= new Set()).add(internalRenderTask);\n    const renderTask = internalRenderTask.task;\n    Promise.all([intentState.displayReadyCapability.promise, optionalContentConfigPromise]).then(([transparency, optionalContentConfig]) => {\n      if (this.destroyed) {\n        complete();\n        return;\n      }\n      this._stats?.time(\"Rendering\");\n      if (!(optionalContentConfig.renderingIntent & renderingIntent)) {\n        throw new Error(\"Must use the same `intent`-argument when calling the `PDFPageProxy.render` \" + \"and `PDFDocumentProxy.getOptionalContentConfig` methods.\");\n      }\n      internalRenderTask.initializeGraphics({\n        transparency,\n        optionalContentConfig\n      });\n      internalRenderTask.operatorListChanged();\n    }).catch(complete);\n    return renderTask;\n  }\n  getOperatorList({\n    intent = \"display\",\n    annotationMode = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE,\n    printAnnotationStorage = null\n  } = {}) {\n    function operatorListChanged() {\n      if (intentState.operatorList.lastChunk) {\n        intentState.opListReadCapability.resolve(intentState.operatorList);\n        intentState.renderTasks.delete(opListTask);\n      }\n    }\n    const intentArgs = this._transport.getRenderingIntent(intent, annotationMode, printAnnotationStorage, true);\n    let intentState = this._intentStates.get(intentArgs.cacheKey);\n    if (!intentState) {\n      intentState = Object.create(null);\n      this._intentStates.set(intentArgs.cacheKey, intentState);\n    }\n    let opListTask;\n    if (!intentState.opListReadCapability) {\n      opListTask = Object.create(null);\n      opListTask.operatorListChanged = operatorListChanged;\n      intentState.opListReadCapability = Promise.withResolvers();\n      (intentState.renderTasks ||= new Set()).add(opListTask);\n      intentState.operatorList = {\n        fnArray: [],\n        argsArray: [],\n        lastChunk: false,\n        separateAnnots: null\n      };\n      this._stats?.time(\"Page Request\");\n      this._pumpOperatorList(intentArgs);\n    }\n    return intentState.opListReadCapability.promise;\n  }\n  streamTextContent({\n    includeMarkedContent = false,\n    disableNormalization = false\n  } = {}) {\n    const TEXT_CONTENT_CHUNK_SIZE = 100;\n    return this._transport.messageHandler.sendWithStream(\"GetTextContent\", {\n      pageIndex: this._pageIndex,\n      includeMarkedContent: includeMarkedContent === true,\n      disableNormalization: disableNormalization === true\n    }, {\n      highWaterMark: TEXT_CONTENT_CHUNK_SIZE,\n      size(textContent) {\n        return textContent.items.length;\n      }\n    });\n  }\n  getTextContent(params = {}) {\n    if (this._transport._htmlForXfa) {\n      return this.getXfa().then(xfa => _xfa_text_js__WEBPACK_IMPORTED_MODULE_15__.XfaText.textContent(xfa));\n    }\n    const readableStream = this.streamTextContent(params);\n    return new Promise(function (resolve, reject) {\n      function pump() {\n        reader.read().then(function ({\n          value,\n          done\n        }) {\n          if (done) {\n            resolve(textContent);\n            return;\n          }\n          Object.assign(textContent.styles, value.styles);\n          textContent.items.push(...value.items);\n          pump();\n        }, reject);\n      }\n      const reader = readableStream.getReader();\n      const textContent = {\n        items: [],\n        styles: Object.create(null)\n      };\n      pump();\n    });\n  }\n  getStructTree() {\n    return this._transport.getStructTree(this._pageIndex);\n  }\n  _destroy() {\n    this.destroyed = true;\n    const waitOn = [];\n    for (const intentState of this._intentStates.values()) {\n      this._abortOperatorList({\n        intentState,\n        reason: new Error(\"Page was destroyed.\"),\n        force: true\n      });\n      if (intentState.opListReadCapability) {\n        continue;\n      }\n      for (const internalRenderTask of intentState.renderTasks) {\n        waitOn.push(internalRenderTask.completed);\n        internalRenderTask.cancel();\n      }\n    }\n    this.objs.clear();\n    this.#pendingCleanup = false;\n    this.#abortDelayedCleanup();\n    return Promise.all(waitOn);\n  }\n  cleanup(resetStats = false) {\n    this.#pendingCleanup = true;\n    const success = this.#tryCleanup(false);\n    if (resetStats && success) {\n      this._stats &&= new _display_utils_js__WEBPACK_IMPORTED_MODULE_2__.StatTimer();\n    }\n    return success;\n  }\n  #tryCleanup(delayed = false) {\n    this.#abortDelayedCleanup();\n    if (!this.#pendingCleanup || this.destroyed) {\n      return false;\n    }\n    if (delayed) {\n      this.#delayedCleanupTimeout = setTimeout(() => {\n        this.#delayedCleanupTimeout = null;\n        this.#tryCleanup(false);\n      }, DELAYED_CLEANUP_TIMEOUT);\n      return false;\n    }\n    for (const {\n      renderTasks,\n      operatorList\n    } of this._intentStates.values()) {\n      if (renderTasks.size > 0 || !operatorList.lastChunk) {\n        return false;\n      }\n    }\n    this._intentStates.clear();\n    this.objs.clear();\n    this.#pendingCleanup = false;\n    return true;\n  }\n  #abortDelayedCleanup() {\n    if (this.#delayedCleanupTimeout) {\n      clearTimeout(this.#delayedCleanupTimeout);\n      this.#delayedCleanupTimeout = null;\n    }\n  }\n  _startRenderPage(transparency, cacheKey) {\n    const intentState = this._intentStates.get(cacheKey);\n    if (!intentState) {\n      return;\n    }\n    this._stats?.timeEnd(\"Page Request\");\n    intentState.displayReadyCapability?.resolve(transparency);\n  }\n  _renderPageChunk(operatorListChunk, intentState) {\n    for (let i = 0, ii = operatorListChunk.length; i < ii; i++) {\n      intentState.operatorList.fnArray.push(operatorListChunk.fnArray[i]);\n      intentState.operatorList.argsArray.push(operatorListChunk.argsArray[i]);\n    }\n    intentState.operatorList.lastChunk = operatorListChunk.lastChunk;\n    intentState.operatorList.separateAnnots = operatorListChunk.separateAnnots;\n    for (const internalRenderTask of intentState.renderTasks) {\n      internalRenderTask.operatorListChanged();\n    }\n    if (operatorListChunk.lastChunk) {\n      this.#tryCleanup(true);\n    }\n  }\n  _pumpOperatorList({\n    renderingIntent,\n    cacheKey,\n    annotationStorageSerializable\n  }) {\n    const {\n      map,\n      transfer\n    } = annotationStorageSerializable;\n    const readableStream = this._transport.messageHandler.sendWithStream(\"GetOperatorList\", {\n      pageIndex: this._pageIndex,\n      intent: renderingIntent,\n      cacheKey,\n      annotationStorage: map\n    }, transfer);\n    const reader = readableStream.getReader();\n    const intentState = this._intentStates.get(cacheKey);\n    intentState.streamReader = reader;\n    const pump = () => {\n      reader.read().then(({\n        value,\n        done\n      }) => {\n        if (done) {\n          intentState.streamReader = null;\n          return;\n        }\n        if (this._transport.destroyed) {\n          return;\n        }\n        this._renderPageChunk(value, intentState);\n        pump();\n      }, reason => {\n        intentState.streamReader = null;\n        if (this._transport.destroyed) {\n          return;\n        }\n        if (intentState.operatorList) {\n          intentState.operatorList.lastChunk = true;\n          for (const internalRenderTask of intentState.renderTasks) {\n            internalRenderTask.operatorListChanged();\n          }\n          this.#tryCleanup(true);\n        }\n        if (intentState.displayReadyCapability) {\n          intentState.displayReadyCapability.reject(reason);\n        } else if (intentState.opListReadCapability) {\n          intentState.opListReadCapability.reject(reason);\n        } else {\n          throw reason;\n        }\n      });\n    };\n    pump();\n  }\n  _abortOperatorList({\n    intentState,\n    reason,\n    force = false\n  }) {\n    if (!intentState.streamReader) {\n      return;\n    }\n    if (intentState.streamReaderCancelTimeout) {\n      clearTimeout(intentState.streamReaderCancelTimeout);\n      intentState.streamReaderCancelTimeout = null;\n    }\n    if (!force) {\n      if (intentState.renderTasks.size > 0) {\n        return;\n      }\n      if (reason instanceof _display_utils_js__WEBPACK_IMPORTED_MODULE_2__.RenderingCancelledException) {\n        let delay = RENDERING_CANCELLED_TIMEOUT;\n        if (reason.extraDelay > 0 && reason.extraDelay < 1000) {\n          delay += reason.extraDelay;\n        }\n        intentState.streamReaderCancelTimeout = setTimeout(() => {\n          intentState.streamReaderCancelTimeout = null;\n          this._abortOperatorList({\n            intentState,\n            reason,\n            force: true\n          });\n        }, delay);\n        return;\n      }\n    }\n    intentState.streamReader.cancel(new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AbortException(reason.message)).catch(() => {});\n    intentState.streamReader = null;\n    if (this._transport.destroyed) {\n      return;\n    }\n    for (const [curCacheKey, curIntentState] of this._intentStates) {\n      if (curIntentState === intentState) {\n        this._intentStates.delete(curCacheKey);\n        break;\n      }\n    }\n    this.cleanup();\n  }\n  get stats() {\n    return this._stats;\n  }\n}\nclass LoopbackPort {\n  #listeners = new Set();\n  #deferred = Promise.resolve();\n  postMessage(obj, transfer) {\n    const event = {\n      data: structuredClone(obj, transfer ? {\n        transfer\n      } : null)\n    };\n    this.#deferred.then(() => {\n      for (const listener of this.#listeners) {\n        listener.call(this, event);\n      }\n    });\n  }\n  addEventListener(name, listener) {\n    this.#listeners.add(listener);\n  }\n  removeEventListener(name, listener) {\n    this.#listeners.delete(listener);\n  }\n  terminate() {\n    this.#listeners.clear();\n  }\n}\nconst PDFWorkerUtil = {\n  isWorkerDisabled: false,\n  fakeWorkerId: 0\n};\n{\n  if (_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.isNodeJS) {\n    PDFWorkerUtil.isWorkerDisabled = true;\n    _worker_options_js__WEBPACK_IMPORTED_MODULE_14__.GlobalWorkerOptions.workerSrc ||= \"./pdf.worker.mjs\";\n  }\n  PDFWorkerUtil.isSameOrigin = function (baseUrl, otherUrl) {\n    let base;\n    try {\n      base = new URL(baseUrl);\n      if (!base.origin || base.origin === \"null\") {\n        return false;\n      }\n    } catch {\n      return false;\n    }\n    const other = new URL(otherUrl, base);\n    return base.origin === other.origin;\n  };\n  PDFWorkerUtil.createCDNWrapper = function (url) {\n    const wrapper = `await import(\"${url}\");`;\n    return URL.createObjectURL(new Blob([wrapper], {\n      type: \"text/javascript\"\n    }));\n  };\n}\nclass PDFWorker {\n  static #workerPorts;\n  constructor({\n    name = null,\n    port = null,\n    verbosity = (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.getVerbosityLevel)()\n  } = {}) {\n    this.name = name;\n    this.destroyed = false;\n    this.verbosity = verbosity;\n    this._readyCapability = Promise.withResolvers();\n    this._port = null;\n    this._webWorker = null;\n    this._messageHandler = null;\n    if (port) {\n      if (PDFWorker.#workerPorts?.has(port)) {\n        throw new Error(\"Cannot use more than one PDFWorker per port.\");\n      }\n      (PDFWorker.#workerPorts ||= new WeakMap()).set(port, this);\n      this._initializeFromPort(port);\n      return;\n    }\n    this._initialize();\n  }\n  get promise() {\n    return this._readyCapability.promise;\n  }\n  get port() {\n    return this._port;\n  }\n  get messageHandler() {\n    return this._messageHandler;\n  }\n  _initializeFromPort(port) {\n    this._port = port;\n    this._messageHandler = new _shared_message_handler_js__WEBPACK_IMPORTED_MODULE_7__.MessageHandler(\"main\", \"worker\", port);\n    this._messageHandler.on(\"ready\", function () {});\n    this._readyCapability.resolve();\n    this._messageHandler.send(\"configure\", {\n      verbosity: this.verbosity\n    });\n  }\n  _initialize() {\n    if (!PDFWorkerUtil.isWorkerDisabled && !PDFWorker.#mainThreadWorkerMessageHandler) {\n      let {\n        workerSrc\n      } = PDFWorker;\n      try {\n        if (!PDFWorkerUtil.isSameOrigin(window.location.href, workerSrc)) {\n          workerSrc = PDFWorkerUtil.createCDNWrapper(new URL(workerSrc, window.location).href);\n        }\n        const worker = new Worker(workerSrc, {\n          type: \"module\"\n        });\n        const messageHandler = new _shared_message_handler_js__WEBPACK_IMPORTED_MODULE_7__.MessageHandler(\"main\", \"worker\", worker);\n        const terminateEarly = () => {\n          worker.removeEventListener(\"error\", onWorkerError);\n          messageHandler.destroy();\n          worker.terminate();\n          if (this.destroyed) {\n            this._readyCapability.reject(new Error(\"Worker was destroyed\"));\n          } else {\n            this._setupFakeWorker();\n          }\n        };\n        const onWorkerError = () => {\n          if (!this._webWorker) {\n            terminateEarly();\n          }\n        };\n        worker.addEventListener(\"error\", onWorkerError);\n        messageHandler.on(\"test\", data => {\n          worker.removeEventListener(\"error\", onWorkerError);\n          if (this.destroyed) {\n            terminateEarly();\n            return;\n          }\n          if (data) {\n            this._messageHandler = messageHandler;\n            this._port = worker;\n            this._webWorker = worker;\n            this._readyCapability.resolve();\n            messageHandler.send(\"configure\", {\n              verbosity: this.verbosity\n            });\n          } else {\n            this._setupFakeWorker();\n            messageHandler.destroy();\n            worker.terminate();\n          }\n        });\n        messageHandler.on(\"ready\", data => {\n          worker.removeEventListener(\"error\", onWorkerError);\n          if (this.destroyed) {\n            terminateEarly();\n            return;\n          }\n          try {\n            sendTest();\n          } catch {\n            this._setupFakeWorker();\n          }\n        });\n        const sendTest = () => {\n          const testObj = new Uint8Array();\n          messageHandler.send(\"test\", testObj, [testObj.buffer]);\n        };\n        sendTest();\n        return;\n      } catch {\n        (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.info)(\"The worker has been disabled.\");\n      }\n    }\n    this._setupFakeWorker();\n  }\n  _setupFakeWorker() {\n    if (!PDFWorkerUtil.isWorkerDisabled) {\n      (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(\"Setting up fake worker.\");\n      PDFWorkerUtil.isWorkerDisabled = true;\n    }\n    PDFWorker._setupFakeWorkerGlobal.then(WorkerMessageHandler => {\n      if (this.destroyed) {\n        this._readyCapability.reject(new Error(\"Worker was destroyed\"));\n        return;\n      }\n      const port = new LoopbackPort();\n      this._port = port;\n      const id = `fake${PDFWorkerUtil.fakeWorkerId++}`;\n      const workerHandler = new _shared_message_handler_js__WEBPACK_IMPORTED_MODULE_7__.MessageHandler(id + \"_worker\", id, port);\n      WorkerMessageHandler.setup(workerHandler, port);\n      const messageHandler = new _shared_message_handler_js__WEBPACK_IMPORTED_MODULE_7__.MessageHandler(id, id + \"_worker\", port);\n      this._messageHandler = messageHandler;\n      this._readyCapability.resolve();\n      messageHandler.send(\"configure\", {\n        verbosity: this.verbosity\n      });\n    }).catch(reason => {\n      this._readyCapability.reject(new Error(`Setting up fake worker failed: \"${reason.message}\".`));\n    });\n  }\n  destroy() {\n    this.destroyed = true;\n    if (this._webWorker) {\n      this._webWorker.terminate();\n      this._webWorker = null;\n    }\n    PDFWorker.#workerPorts?.delete(this._port);\n    this._port = null;\n    if (this._messageHandler) {\n      this._messageHandler.destroy();\n      this._messageHandler = null;\n    }\n  }\n  static fromPort(params) {\n    if (!params?.port) {\n      throw new Error(\"PDFWorker.fromPort - invalid method signature.\");\n    }\n    const cachedPort = this.#workerPorts?.get(params.port);\n    if (cachedPort) {\n      if (cachedPort._pendingDestroy) {\n        throw new Error(\"PDFWorker.fromPort - the worker is being destroyed.\\n\" + \"Please remember to await `PDFDocumentLoadingTask.destroy()`-calls.\");\n      }\n      return cachedPort;\n    }\n    return new PDFWorker(params);\n  }\n  static get workerSrc() {\n    if (_worker_options_js__WEBPACK_IMPORTED_MODULE_14__.GlobalWorkerOptions.workerSrc) {\n      return _worker_options_js__WEBPACK_IMPORTED_MODULE_14__.GlobalWorkerOptions.workerSrc;\n    }\n    throw new Error('No \"GlobalWorkerOptions.workerSrc\" specified.');\n  }\n  static get #mainThreadWorkerMessageHandler() {\n    try {\n      return globalThis.pdfjsWorker?.WorkerMessageHandler || null;\n    } catch {\n      return null;\n    }\n  }\n  static get _setupFakeWorkerGlobal() {\n    const loader = async () => {\n      if (this.#mainThreadWorkerMessageHandler) {\n        return this.#mainThreadWorkerMessageHandler;\n      }\n      const worker = await import( /*webpackIgnore: true*/this.workerSrc);\n      return worker.WorkerMessageHandler;\n    };\n    return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, \"_setupFakeWorkerGlobal\", loader());\n  }\n}\nclass WorkerTransport {\n  #methodPromises = new Map();\n  #pageCache = new Map();\n  #pagePromises = new Map();\n  #pageRefCache = new Map();\n  #passwordCapability = null;\n  constructor(messageHandler, loadingTask, networkStream, params, factory) {\n    this.messageHandler = messageHandler;\n    this.loadingTask = loadingTask;\n    this.commonObjs = new PDFObjects();\n    this.fontLoader = new _font_loader_js__WEBPACK_IMPORTED_MODULE_3__.FontLoader({\n      ownerDocument: params.ownerDocument,\n      styleElement: params.styleElement\n    });\n    this._params = params;\n    this.canvasFactory = factory.canvasFactory;\n    this.filterFactory = factory.filterFactory;\n    this.cMapReaderFactory = factory.cMapReaderFactory;\n    this.standardFontDataFactory = factory.standardFontDataFactory;\n    this.destroyed = false;\n    this.destroyCapability = null;\n    this._networkStream = networkStream;\n    this._fullReader = null;\n    this._lastProgress = null;\n    this.downloadInfoCapability = Promise.withResolvers();\n    this.setupMessageHandler();\n  }\n  #cacheSimpleMethod(name, data = null) {\n    const cachedPromise = this.#methodPromises.get(name);\n    if (cachedPromise) {\n      return cachedPromise;\n    }\n    const promise = this.messageHandler.sendWithPromise(name, data);\n    this.#methodPromises.set(name, promise);\n    return promise;\n  }\n  get annotationStorage() {\n    return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, \"annotationStorage\", new _annotation_storage_js__WEBPACK_IMPORTED_MODULE_1__.AnnotationStorage());\n  }\n  getRenderingIntent(intent, annotationMode = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE, printAnnotationStorage = null, isOpList = false) {\n    let renderingIntent = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.RenderingIntentFlag.DISPLAY;\n    let annotationStorageSerializable = _annotation_storage_js__WEBPACK_IMPORTED_MODULE_1__.SerializableEmpty;\n    switch (intent) {\n      case \"any\":\n        renderingIntent = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.RenderingIntentFlag.ANY;\n        break;\n      case \"display\":\n        break;\n      case \"print\":\n        renderingIntent = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.RenderingIntentFlag.PRINT;\n        break;\n      default:\n        (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`getRenderingIntent - invalid intent: ${intent}`);\n    }\n    switch (annotationMode) {\n      case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.DISABLE:\n        renderingIntent += _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.RenderingIntentFlag.ANNOTATIONS_DISABLE;\n        break;\n      case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE:\n        break;\n      case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE_FORMS:\n        renderingIntent += _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.RenderingIntentFlag.ANNOTATIONS_FORMS;\n        break;\n      case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE_STORAGE:\n        renderingIntent += _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.RenderingIntentFlag.ANNOTATIONS_STORAGE;\n        const annotationStorage = renderingIntent & _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.RenderingIntentFlag.PRINT && printAnnotationStorage instanceof _annotation_storage_js__WEBPACK_IMPORTED_MODULE_1__.PrintAnnotationStorage ? printAnnotationStorage : this.annotationStorage;\n        annotationStorageSerializable = annotationStorage.serializable;\n        break;\n      default:\n        (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`getRenderingIntent - invalid annotationMode: ${annotationMode}`);\n    }\n    if (isOpList) {\n      renderingIntent += _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.RenderingIntentFlag.OPLIST;\n    }\n    return {\n      renderingIntent,\n      cacheKey: `${renderingIntent}_${annotationStorageSerializable.hash}`,\n      annotationStorageSerializable\n    };\n  }\n  destroy() {\n    if (this.destroyCapability) {\n      return this.destroyCapability.promise;\n    }\n    this.destroyed = true;\n    this.destroyCapability = Promise.withResolvers();\n    this.#passwordCapability?.reject(new Error(\"Worker was destroyed during onPassword callback\"));\n    const waitOn = [];\n    for (const page of this.#pageCache.values()) {\n      waitOn.push(page._destroy());\n    }\n    this.#pageCache.clear();\n    this.#pagePromises.clear();\n    this.#pageRefCache.clear();\n    if (this.hasOwnProperty(\"annotationStorage\")) {\n      this.annotationStorage.resetModified();\n    }\n    const terminated = this.messageHandler.sendWithPromise(\"Terminate\", null);\n    waitOn.push(terminated);\n    Promise.all(waitOn).then(() => {\n      this.commonObjs.clear();\n      this.fontLoader.clear();\n      this.#methodPromises.clear();\n      this.filterFactory.destroy();\n      (0,_text_layer_js__WEBPACK_IMPORTED_MODULE_6__.cleanupTextLayer)();\n      this._networkStream?.cancelAllRequests(new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AbortException(\"Worker was terminated.\"));\n      if (this.messageHandler) {\n        this.messageHandler.destroy();\n        this.messageHandler = null;\n      }\n      this.destroyCapability.resolve();\n    }, this.destroyCapability.reject);\n    return this.destroyCapability.promise;\n  }\n  setupMessageHandler() {\n    const {\n      messageHandler,\n      loadingTask\n    } = this;\n    messageHandler.on(\"GetReader\", (data, sink) => {\n      (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(this._networkStream, \"GetReader - no `IPDFStream` instance available.\");\n      this._fullReader = this._networkStream.getFullReader();\n      this._fullReader.onProgress = evt => {\n        this._lastProgress = {\n          loaded: evt.loaded,\n          total: evt.total\n        };\n      };\n      sink.onPull = () => {\n        this._fullReader.read().then(function ({\n          value,\n          done\n        }) {\n          if (done) {\n            sink.close();\n            return;\n          }\n          (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(value instanceof ArrayBuffer, \"GetReader - expected an ArrayBuffer.\");\n          sink.enqueue(new Uint8Array(value), 1, [value]);\n        }).catch(reason => {\n          sink.error(reason);\n        });\n      };\n      sink.onCancel = reason => {\n        this._fullReader.cancel(reason);\n        sink.ready.catch(readyReason => {\n          if (this.destroyed) {\n            return;\n          }\n          throw readyReason;\n        });\n      };\n    });\n    messageHandler.on(\"ReaderHeadersReady\", data => {\n      const headersCapability = Promise.withResolvers();\n      const fullReader = this._fullReader;\n      fullReader.headersReady.then(() => {\n        if (!fullReader.isStreamingSupported || !fullReader.isRangeSupported) {\n          if (this._lastProgress) {\n            loadingTask.onProgress?.(this._lastProgress);\n          }\n          fullReader.onProgress = evt => {\n            loadingTask.onProgress?.({\n              loaded: evt.loaded,\n              total: evt.total\n            });\n          };\n        }\n        headersCapability.resolve({\n          isStreamingSupported: fullReader.isStreamingSupported,\n          isRangeSupported: fullReader.isRangeSupported,\n          contentLength: fullReader.contentLength\n        });\n      }, headersCapability.reject);\n      return headersCapability.promise;\n    });\n    messageHandler.on(\"GetRangeReader\", (data, sink) => {\n      (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(this._networkStream, \"GetRangeReader - no `IPDFStream` instance available.\");\n      const rangeReader = this._networkStream.getRangeReader(data.begin, data.end);\n      if (!rangeReader) {\n        sink.close();\n        return;\n      }\n      sink.onPull = () => {\n        rangeReader.read().then(function ({\n          value,\n          done\n        }) {\n          if (done) {\n            sink.close();\n            return;\n          }\n          (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(value instanceof ArrayBuffer, \"GetRangeReader - expected an ArrayBuffer.\");\n          sink.enqueue(new Uint8Array(value), 1, [value]);\n        }).catch(reason => {\n          sink.error(reason);\n        });\n      };\n      sink.onCancel = reason => {\n        rangeReader.cancel(reason);\n        sink.ready.catch(readyReason => {\n          if (this.destroyed) {\n            return;\n          }\n          throw readyReason;\n        });\n      };\n    });\n    messageHandler.on(\"GetDoc\", ({\n      pdfInfo\n    }) => {\n      this._numPages = pdfInfo.numPages;\n      this._htmlForXfa = pdfInfo.htmlForXfa;\n      delete pdfInfo.htmlForXfa;\n      loadingTask._capability.resolve(new PDFDocumentProxy(pdfInfo, this));\n    });\n    messageHandler.on(\"DocException\", function (ex) {\n      let reason;\n      switch (ex.name) {\n        case \"PasswordException\":\n          reason = new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.PasswordException(ex.message, ex.code);\n          break;\n        case \"InvalidPDFException\":\n          reason = new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.InvalidPDFException(ex.message);\n          break;\n        case \"MissingPDFException\":\n          reason = new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.MissingPDFException(ex.message);\n          break;\n        case \"UnexpectedResponseException\":\n          reason = new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.UnexpectedResponseException(ex.message, ex.status);\n          break;\n        case \"UnknownErrorException\":\n          reason = new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.UnknownErrorException(ex.message, ex.details);\n          break;\n        default:\n          (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)(\"DocException - expected a valid Error.\");\n      }\n      loadingTask._capability.reject(reason);\n    });\n    messageHandler.on(\"PasswordRequest\", exception => {\n      this.#passwordCapability = Promise.withResolvers();\n      if (loadingTask.onPassword) {\n        const updatePassword = password => {\n          if (password instanceof Error) {\n            this.#passwordCapability.reject(password);\n          } else {\n            this.#passwordCapability.resolve({\n              password\n            });\n          }\n        };\n        try {\n          loadingTask.onPassword(updatePassword, exception.code);\n        } catch (ex) {\n          this.#passwordCapability.reject(ex);\n        }\n      } else {\n        this.#passwordCapability.reject(new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.PasswordException(exception.message, exception.code));\n      }\n      return this.#passwordCapability.promise;\n    });\n    messageHandler.on(\"DataLoaded\", data => {\n      loadingTask.onProgress?.({\n        loaded: data.length,\n        total: data.length\n      });\n      this.downloadInfoCapability.resolve(data);\n    });\n    messageHandler.on(\"StartRenderPage\", data => {\n      if (this.destroyed) {\n        return;\n      }\n      const page = this.#pageCache.get(data.pageIndex);\n      page._startRenderPage(data.transparency, data.cacheKey);\n    });\n    messageHandler.on(\"commonobj\", ([id, type, exportedData]) => {\n      if (this.destroyed) {\n        return null;\n      }\n      if (this.commonObjs.has(id)) {\n        return null;\n      }\n      switch (type) {\n        case \"Font\":\n          const params = this._params;\n          if (\"error\" in exportedData) {\n            const exportedError = exportedData.error;\n            (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`Error during font loading: ${exportedError}`);\n            this.commonObjs.resolve(id, exportedError);\n            break;\n          }\n          const inspectFont = params.pdfBug && globalThis.FontInspector?.enabled ? (font, url) => globalThis.FontInspector.fontAdded(font, url) : null;\n          const font = new _font_loader_js__WEBPACK_IMPORTED_MODULE_3__.FontFaceObject(exportedData, {\n            disableFontFace: params.disableFontFace,\n            ignoreErrors: params.ignoreErrors,\n            inspectFont\n          });\n          this.fontLoader.bind(font).catch(() => messageHandler.sendWithPromise(\"FontFallback\", {\n            id\n          })).finally(() => {\n            if (!params.fontExtraProperties && font.data) {\n              font.data = null;\n            }\n            this.commonObjs.resolve(id, font);\n          });\n          break;\n        case \"CopyLocalImage\":\n          const {\n            imageRef\n          } = exportedData;\n          (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(imageRef, \"The imageRef must be defined.\");\n          for (const pageProxy of this.#pageCache.values()) {\n            for (const [, data] of pageProxy.objs) {\n              if (data.ref !== imageRef) {\n                continue;\n              }\n              if (!data.dataLen) {\n                return null;\n              }\n              this.commonObjs.resolve(id, structuredClone(data));\n              return data.dataLen;\n            }\n          }\n          break;\n        case \"FontPath\":\n        case \"Image\":\n        case \"Pattern\":\n          this.commonObjs.resolve(id, exportedData);\n          break;\n        default:\n          throw new Error(`Got unknown common object type ${type}`);\n      }\n      return null;\n    });\n    messageHandler.on(\"obj\", ([id, pageIndex, type, imageData]) => {\n      if (this.destroyed) {\n        return;\n      }\n      const pageProxy = this.#pageCache.get(pageIndex);\n      if (pageProxy.objs.has(id)) {\n        return;\n      }\n      if (pageProxy._intentStates.size === 0) {\n        imageData?.bitmap?.close();\n        return;\n      }\n      switch (type) {\n        case \"Image\":\n          pageProxy.objs.resolve(id, imageData);\n          if (imageData?.dataLen > _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.MAX_IMAGE_SIZE_TO_CACHE) {\n            pageProxy._maybeCleanupAfterRender = true;\n          }\n          break;\n        case \"Pattern\":\n          pageProxy.objs.resolve(id, imageData);\n          break;\n        default:\n          throw new Error(`Got unknown object type ${type}`);\n      }\n    });\n    messageHandler.on(\"DocProgress\", data => {\n      if (this.destroyed) {\n        return;\n      }\n      loadingTask.onProgress?.({\n        loaded: data.loaded,\n        total: data.total\n      });\n    });\n    messageHandler.on(\"FetchBuiltInCMap\", data => {\n      if (this.destroyed) {\n        return Promise.reject(new Error(\"Worker was destroyed.\"));\n      }\n      if (!this.cMapReaderFactory) {\n        return Promise.reject(new Error(\"CMapReaderFactory not initialized, see the `useWorkerFetch` parameter.\"));\n      }\n      return this.cMapReaderFactory.fetch(data);\n    });\n    messageHandler.on(\"FetchStandardFontData\", data => {\n      if (this.destroyed) {\n        return Promise.reject(new Error(\"Worker was destroyed.\"));\n      }\n      if (!this.standardFontDataFactory) {\n        return Promise.reject(new Error(\"StandardFontDataFactory not initialized, see the `useWorkerFetch` parameter.\"));\n      }\n      return this.standardFontDataFactory.fetch(data);\n    });\n  }\n  getData() {\n    return this.messageHandler.sendWithPromise(\"GetData\", null);\n  }\n  saveDocument() {\n    if (this.annotationStorage.size <= 0) {\n      (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(\"saveDocument called while `annotationStorage` is empty, \" + \"please use the getData-method instead.\");\n    }\n    const {\n      map,\n      transfer\n    } = this.annotationStorage.serializable;\n    return this.messageHandler.sendWithPromise(\"SaveDocument\", {\n      isPureXfa: !!this._htmlForXfa,\n      numPages: this._numPages,\n      annotationStorage: map,\n      filename: this._fullReader?.filename ?? null\n    }, transfer).finally(() => {\n      this.annotationStorage.resetModified();\n    });\n  }\n  getPage(pageNumber) {\n    if (!Number.isInteger(pageNumber) || pageNumber <= 0 || pageNumber > this._numPages) {\n      return Promise.reject(new Error(\"Invalid page request.\"));\n    }\n    const pageIndex = pageNumber - 1,\n      cachedPromise = this.#pagePromises.get(pageIndex);\n    if (cachedPromise) {\n      return cachedPromise;\n    }\n    const promise = this.messageHandler.sendWithPromise(\"GetPage\", {\n      pageIndex\n    }).then(pageInfo => {\n      if (this.destroyed) {\n        throw new Error(\"Transport destroyed\");\n      }\n      if (pageInfo.refStr) {\n        this.#pageRefCache.set(pageInfo.refStr, pageNumber);\n      }\n      const page = new PDFPageProxy(pageIndex, pageInfo, this, this._params.pdfBug);\n      this.#pageCache.set(pageIndex, page);\n      return page;\n    });\n    this.#pagePromises.set(pageIndex, promise);\n    return promise;\n  }\n  getPageIndex(ref) {\n    if (!isRefProxy(ref)) {\n      return Promise.reject(new Error(\"Invalid pageIndex request.\"));\n    }\n    return this.messageHandler.sendWithPromise(\"GetPageIndex\", {\n      num: ref.num,\n      gen: ref.gen\n    });\n  }\n  getAnnotations(pageIndex, intent) {\n    return this.messageHandler.sendWithPromise(\"GetAnnotations\", {\n      pageIndex,\n      intent\n    });\n  }\n  getFieldObjects() {\n    return this.#cacheSimpleMethod(\"GetFieldObjects\");\n  }\n  hasJSActions() {\n    return this.#cacheSimpleMethod(\"HasJSActions\");\n  }\n  getCalculationOrderIds() {\n    return this.messageHandler.sendWithPromise(\"GetCalculationOrderIds\", null);\n  }\n  getDestinations() {\n    return this.messageHandler.sendWithPromise(\"GetDestinations\", null);\n  }\n  getDestination(id) {\n    if (typeof id !== \"string\") {\n      return Promise.reject(new Error(\"Invalid destination request.\"));\n    }\n    return this.messageHandler.sendWithPromise(\"GetDestination\", {\n      id\n    });\n  }\n  getPageLabels() {\n    return this.messageHandler.sendWithPromise(\"GetPageLabels\", null);\n  }\n  getPageLayout() {\n    return this.messageHandler.sendWithPromise(\"GetPageLayout\", null);\n  }\n  getPageMode() {\n    return this.messageHandler.sendWithPromise(\"GetPageMode\", null);\n  }\n  getViewerPreferences() {\n    return this.messageHandler.sendWithPromise(\"GetViewerPreferences\", null);\n  }\n  getOpenAction() {\n    return this.messageHandler.sendWithPromise(\"GetOpenAction\", null);\n  }\n  getAttachments() {\n    return this.messageHandler.sendWithPromise(\"GetAttachments\", null);\n  }\n  getDocJSActions() {\n    return this.#cacheSimpleMethod(\"GetDocJSActions\");\n  }\n  getPageJSActions(pageIndex) {\n    return this.messageHandler.sendWithPromise(\"GetPageJSActions\", {\n      pageIndex\n    });\n  }\n  getStructTree(pageIndex) {\n    return this.messageHandler.sendWithPromise(\"GetStructTree\", {\n      pageIndex\n    });\n  }\n  getOutline() {\n    return this.messageHandler.sendWithPromise(\"GetOutline\", null);\n  }\n  getOptionalContentConfig(renderingIntent) {\n    return this.#cacheSimpleMethod(\"GetOptionalContentConfig\").then(data => new _optional_content_config_js__WEBPACK_IMPORTED_MODULE_9__.OptionalContentConfig(data, renderingIntent));\n  }\n  getPermissions() {\n    return this.messageHandler.sendWithPromise(\"GetPermissions\", null);\n  }\n  getMetadata() {\n    const name = \"GetMetadata\",\n      cachedPromise = this.#methodPromises.get(name);\n    if (cachedPromise) {\n      return cachedPromise;\n    }\n    const promise = this.messageHandler.sendWithPromise(name, null).then(results => ({\n      info: results[0],\n      metadata: results[1] ? new _metadata_js__WEBPACK_IMPORTED_MODULE_8__.Metadata(results[1]) : null,\n      contentDispositionFilename: this._fullReader?.filename ?? null,\n      contentLength: this._fullReader?.contentLength ?? null\n    }));\n    this.#methodPromises.set(name, promise);\n    return promise;\n  }\n  getMarkInfo() {\n    return this.messageHandler.sendWithPromise(\"GetMarkInfo\", null);\n  }\n  async startCleanup(keepLoadedFonts = false) {\n    if (this.destroyed) {\n      return;\n    }\n    await this.messageHandler.sendWithPromise(\"Cleanup\", null);\n    for (const page of this.#pageCache.values()) {\n      const cleanupSuccessful = page.cleanup();\n      if (!cleanupSuccessful) {\n        throw new Error(`startCleanup: Page ${page.pageNumber} is currently rendering.`);\n      }\n    }\n    this.commonObjs.clear();\n    if (!keepLoadedFonts) {\n      this.fontLoader.clear();\n    }\n    this.#methodPromises.clear();\n    this.filterFactory.destroy(true);\n    (0,_text_layer_js__WEBPACK_IMPORTED_MODULE_6__.cleanupTextLayer)();\n  }\n  cachedPageNumber(ref) {\n    if (!isRefProxy(ref)) {\n      return null;\n    }\n    const refStr = ref.gen === 0 ? `${ref.num}R` : `${ref.num}R${ref.gen}`;\n    return this.#pageRefCache.get(refStr) ?? null;\n  }\n  get loadingParams() {\n    const {\n      disableAutoFetch,\n      enableXfa\n    } = this._params;\n    return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, \"loadingParams\", {\n      disableAutoFetch,\n      enableXfa\n    });\n  }\n}\nconst INITIAL_DATA = Symbol(\"INITIAL_DATA\");\nclass PDFObjects {\n  #objs = Object.create(null);\n  #ensureObj(objId) {\n    return this.#objs[objId] ||= {\n      ...Promise.withResolvers(),\n      data: INITIAL_DATA\n    };\n  }\n  get(objId, callback = null) {\n    if (callback) {\n      const obj = this.#ensureObj(objId);\n      obj.promise.then(() => callback(obj.data));\n      return null;\n    }\n    const obj = this.#objs[objId];\n    if (!obj || obj.data === INITIAL_DATA) {\n      throw new Error(`Requesting object that isn't resolved yet ${objId}.`);\n    }\n    return obj.data;\n  }\n  has(objId) {\n    const obj = this.#objs[objId];\n    return !!obj && obj.data !== INITIAL_DATA;\n  }\n  resolve(objId, data = null) {\n    const obj = this.#ensureObj(objId);\n    obj.data = data;\n    obj.resolve();\n  }\n  clear() {\n    for (const objId in this.#objs) {\n      const {\n        data\n      } = this.#objs[objId];\n      data?.bitmap?.close();\n    }\n    this.#objs = Object.create(null);\n  }\n  *[Symbol.iterator]() {\n    for (const objId in this.#objs) {\n      const {\n        data\n      } = this.#objs[objId];\n      if (data === INITIAL_DATA) {\n        continue;\n      }\n      yield [objId, data];\n    }\n  }\n}\nclass RenderTask {\n  #internalRenderTask = null;\n  constructor(internalRenderTask) {\n    this.#internalRenderTask = internalRenderTask;\n    this.onContinue = null;\n  }\n  get promise() {\n    return this.#internalRenderTask.capability.promise;\n  }\n  cancel(extraDelay = 0) {\n    this.#internalRenderTask.cancel(null, extraDelay);\n  }\n  get separateAnnots() {\n    const {\n      separateAnnots\n    } = this.#internalRenderTask.operatorList;\n    if (!separateAnnots) {\n      return false;\n    }\n    const {\n      annotationCanvasMap\n    } = this.#internalRenderTask;\n    return separateAnnots.form || separateAnnots.canvas && annotationCanvasMap?.size > 0;\n  }\n}\nclass InternalRenderTask {\n  static #canvasInUse = new WeakSet();\n  constructor({\n    callback,\n    params,\n    objs,\n    commonObjs,\n    annotationCanvasMap,\n    operatorList,\n    pageIndex,\n    canvasFactory,\n    filterFactory,\n    useRequestAnimationFrame = false,\n    pdfBug = false,\n    pageColors = null\n  }) {\n    this.callback = callback;\n    this.params = params;\n    this.objs = objs;\n    this.commonObjs = commonObjs;\n    this.annotationCanvasMap = annotationCanvasMap;\n    this.operatorListIdx = null;\n    this.operatorList = operatorList;\n    this._pageIndex = pageIndex;\n    this.canvasFactory = canvasFactory;\n    this.filterFactory = filterFactory;\n    this._pdfBug = pdfBug;\n    this.pageColors = pageColors;\n    this.running = false;\n    this.graphicsReadyCallback = null;\n    this.graphicsReady = false;\n    this._useRequestAnimationFrame = useRequestAnimationFrame === true && typeof window !== \"undefined\";\n    this.cancelled = false;\n    this.capability = Promise.withResolvers();\n    this.task = new RenderTask(this);\n    this._cancelBound = this.cancel.bind(this);\n    this._continueBound = this._continue.bind(this);\n    this._scheduleNextBound = this._scheduleNext.bind(this);\n    this._nextBound = this._next.bind(this);\n    this._canvas = params.canvasContext.canvas;\n  }\n  get completed() {\n    return this.capability.promise.catch(function () {});\n  }\n  initializeGraphics({\n    transparency = false,\n    optionalContentConfig\n  }) {\n    if (this.cancelled) {\n      return;\n    }\n    if (this._canvas) {\n      if (InternalRenderTask.#canvasInUse.has(this._canvas)) {\n        throw new Error(\"Cannot use the same canvas during multiple render() operations. \" + \"Use different canvas or ensure previous operations were \" + \"cancelled or completed.\");\n      }\n      InternalRenderTask.#canvasInUse.add(this._canvas);\n    }\n    if (this._pdfBug && globalThis.StepperManager?.enabled) {\n      this.stepper = globalThis.StepperManager.create(this._pageIndex);\n      this.stepper.init(this.operatorList);\n      this.stepper.nextBreakPoint = this.stepper.getNextBreakPoint();\n    }\n    const {\n      canvasContext,\n      viewport,\n      transform,\n      background\n    } = this.params;\n    this.gfx = new _canvas_js__WEBPACK_IMPORTED_MODULE_5__.CanvasGraphics(canvasContext, this.commonObjs, this.objs, this.canvasFactory, this.filterFactory, {\n      optionalContentConfig\n    }, this.annotationCanvasMap, this.pageColors);\n    this.gfx.beginDrawing({\n      transform,\n      viewport,\n      transparency,\n      background\n    });\n    this.operatorListIdx = 0;\n    this.graphicsReady = true;\n    this.graphicsReadyCallback?.();\n  }\n  cancel(error = null, extraDelay = 0) {\n    this.running = false;\n    this.cancelled = true;\n    this.gfx?.endDrawing();\n    InternalRenderTask.#canvasInUse.delete(this._canvas);\n    this.callback(error || new _display_utils_js__WEBPACK_IMPORTED_MODULE_2__.RenderingCancelledException(`Rendering cancelled, page ${this._pageIndex + 1}`, extraDelay));\n  }\n  operatorListChanged() {\n    if (!this.graphicsReady) {\n      this.graphicsReadyCallback ||= this._continueBound;\n      return;\n    }\n    this.stepper?.updateOperatorList(this.operatorList);\n    if (this.running) {\n      return;\n    }\n    this._continue();\n  }\n  _continue() {\n    this.running = true;\n    if (this.cancelled) {\n      return;\n    }\n    if (this.task.onContinue) {\n      this.task.onContinue(this._scheduleNextBound);\n    } else {\n      this._scheduleNext();\n    }\n  }\n  _scheduleNext() {\n    if (this._useRequestAnimationFrame) {\n      window.requestAnimationFrame(() => {\n        this._nextBound().catch(this._cancelBound);\n      });\n    } else {\n      Promise.resolve().then(this._nextBound).catch(this._cancelBound);\n    }\n  }\n  async _next() {\n    if (this.cancelled) {\n      return;\n    }\n    this.operatorListIdx = this.gfx.executeOperatorList(this.operatorList, this.operatorListIdx, this._continueBound, this.stepper);\n    if (this.operatorListIdx === this.operatorList.argsArray.length) {\n      this.running = false;\n      if (this.operatorList.lastChunk) {\n        this.gfx.endDrawing();\n        InternalRenderTask.#canvasInUse.delete(this._canvas);\n        this.callback();\n      }\n    }\n  }\n}\nconst version = \"4.2.67\";\nconst build = \"49b388101\";\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 583:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   BaseCMapReaderFactory: () => (/* binding */ BaseCMapReaderFactory),\n/* harmony export */   BaseCanvasFactory: () => (/* binding */ BaseCanvasFactory),\n/* harmony export */   BaseFilterFactory: () => (/* binding */ BaseFilterFactory),\n/* harmony export */   BaseSVGFactory: () => (/* binding */ BaseSVGFactory),\n/* harmony export */   BaseStandardFontDataFactory: () => (/* binding */ BaseStandardFontDataFactory)\n/* harmony export */ });\n/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292);\n\nclass BaseFilterFactory {\n  constructor() {\n    if (this.constructor === BaseFilterFactory) {\n      (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)(\"Cannot initialize BaseFilterFactory.\");\n    }\n  }\n  addFilter(maps) {\n    return \"none\";\n  }\n  addHCMFilter(fgColor, bgColor) {\n    return \"none\";\n  }\n  addHighlightHCMFilter(filterName, fgColor, bgColor, newFgColor, newBgColor) {\n    return \"none\";\n  }\n  destroy(keepHCM = false) {}\n}\nclass BaseCanvasFactory {\n  constructor() {\n    if (this.constructor === BaseCanvasFactory) {\n      (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)(\"Cannot initialize BaseCanvasFactory.\");\n    }\n  }\n  create(width, height) {\n    if (width <= 0 || height <= 0) {\n      throw new Error(\"Invalid canvas size\");\n    }\n    const canvas = this._createCanvas(width, height);\n    return {\n      canvas,\n      context: canvas.getContext(\"2d\")\n    };\n  }\n  reset(canvasAndContext, width, height) {\n    if (!canvasAndContext.canvas) {\n      throw new Error(\"Canvas is not specified\");\n    }\n    if (width <= 0 || height <= 0) {\n      throw new Error(\"Invalid canvas size\");\n    }\n    canvasAndContext.canvas.width = width;\n    canvasAndContext.canvas.height = height;\n  }\n  destroy(canvasAndContext) {\n    if (!canvasAndContext.canvas) {\n      throw new Error(\"Canvas is not specified\");\n    }\n    canvasAndContext.canvas.width = 0;\n    canvasAndContext.canvas.height = 0;\n    canvasAndContext.canvas = null;\n    canvasAndContext.context = null;\n  }\n  _createCanvas(width, height) {\n    (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)(\"Abstract method `_createCanvas` called.\");\n  }\n}\nclass BaseCMapReaderFactory {\n  constructor({\n    baseUrl = null,\n    isCompressed = true\n  }) {\n    if (this.constructor === BaseCMapReaderFactory) {\n      (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)(\"Cannot initialize BaseCMapReaderFactory.\");\n    }\n    this.baseUrl = baseUrl;\n    this.isCompressed = isCompressed;\n  }\n  async fetch({\n    name\n  }) {\n    if (!this.baseUrl) {\n      throw new Error('The CMap \"baseUrl\" parameter must be specified, ensure that ' + 'the \"cMapUrl\" and \"cMapPacked\" API parameters are provided.');\n    }\n    if (!name) {\n      throw new Error(\"CMap name must be specified.\");\n    }\n    const url = this.baseUrl + name + (this.isCompressed ? \".bcmap\" : \"\");\n    const compressionType = this.isCompressed ? _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.CMapCompressionType.BINARY : _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.CMapCompressionType.NONE;\n    return this._fetchData(url, compressionType).catch(reason => {\n      throw new Error(`Unable to load ${this.isCompressed ? \"binary \" : \"\"}CMap at: ${url}`);\n    });\n  }\n  _fetchData(url, compressionType) {\n    (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)(\"Abstract method `_fetchData` called.\");\n  }\n}\nclass BaseStandardFontDataFactory {\n  constructor({\n    baseUrl = null\n  }) {\n    if (this.constructor === BaseStandardFontDataFactory) {\n      (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)(\"Cannot initialize BaseStandardFontDataFactory.\");\n    }\n    this.baseUrl = baseUrl;\n  }\n  async fetch({\n    filename\n  }) {\n    if (!this.baseUrl) {\n      throw new Error('The standard font \"baseUrl\" parameter must be specified, ensure that ' + 'the \"standardFontDataUrl\" API parameter is provided.');\n    }\n    if (!filename) {\n      throw new Error(\"Font filename must be specified.\");\n    }\n    const url = `${this.baseUrl}${filename}`;\n    return this._fetchData(url).catch(reason => {\n      throw new Error(`Unable to load font data at: ${url}`);\n    });\n  }\n  _fetchData(url) {\n    (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)(\"Abstract method `_fetchData` called.\");\n  }\n}\nclass BaseSVGFactory {\n  constructor() {\n    if (this.constructor === BaseSVGFactory) {\n      (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)(\"Cannot initialize BaseSVGFactory.\");\n    }\n  }\n  create(width, height, skipDimensions = false) {\n    if (width <= 0 || height <= 0) {\n      throw new Error(\"Invalid SVG dimensions\");\n    }\n    const svg = this._createSVG(\"svg:svg\");\n    svg.setAttribute(\"version\", \"1.1\");\n    if (!skipDimensions) {\n      svg.setAttribute(\"width\", `${width}px`);\n      svg.setAttribute(\"height\", `${height}px`);\n    }\n    svg.setAttribute(\"preserveAspectRatio\", \"none\");\n    svg.setAttribute(\"viewBox\", `0 0 ${width} ${height}`);\n    return svg;\n  }\n  createElement(type) {\n    if (typeof type !== \"string\") {\n      throw new Error(\"Invalid SVG element type\");\n    }\n    return this._createSVG(type);\n  }\n  _createSVG(type) {\n    (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)(\"Abstract method `_createSVG` called.\");\n  }\n}\n\n\n/***/ }),\n\n/***/ 923:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, {\n  CanvasGraphics: () => (/* binding */ CanvasGraphics)\n});\n\n// EXTERNAL MODULE: ./src/shared/util.js\nvar util = __webpack_require__(292);\n// EXTERNAL MODULE: ./src/display/display_utils.js\nvar display_utils = __webpack_require__(419);\n;// CONCATENATED MODULE: ./src/display/pattern_helper.js\n\n\nconst PathType = {\n  FILL: \"Fill\",\n  STROKE: \"Stroke\",\n  SHADING: \"Shading\"\n};\nfunction applyBoundingBox(ctx, bbox) {\n  if (!bbox) {\n    return;\n  }\n  const width = bbox[2] - bbox[0];\n  const height = bbox[3] - bbox[1];\n  const region = new Path2D();\n  region.rect(bbox[0], bbox[1], width, height);\n  ctx.clip(region);\n}\nclass BaseShadingPattern {\n  constructor() {\n    if (this.constructor === BaseShadingPattern) {\n      (0,util.unreachable)(\"Cannot initialize BaseShadingPattern.\");\n    }\n  }\n  getPattern() {\n    (0,util.unreachable)(\"Abstract method `getPattern` called.\");\n  }\n}\nclass RadialAxialShadingPattern extends BaseShadingPattern {\n  constructor(IR) {\n    super();\n    this._type = IR[1];\n    this._bbox = IR[2];\n    this._colorStops = IR[3];\n    this._p0 = IR[4];\n    this._p1 = IR[5];\n    this._r0 = IR[6];\n    this._r1 = IR[7];\n    this.matrix = null;\n  }\n  _createGradient(ctx) {\n    let grad;\n    if (this._type === \"axial\") {\n      grad = ctx.createLinearGradient(this._p0[0], this._p0[1], this._p1[0], this._p1[1]);\n    } else if (this._type === \"radial\") {\n      grad = ctx.createRadialGradient(this._p0[0], this._p0[1], this._r0, this._p1[0], this._p1[1], this._r1);\n    }\n    for (const colorStop of this._colorStops) {\n      grad.addColorStop(colorStop[0], colorStop[1]);\n    }\n    return grad;\n  }\n  getPattern(ctx, owner, inverse, pathType) {\n    let pattern;\n    if (pathType === PathType.STROKE || pathType === PathType.FILL) {\n      const ownerBBox = owner.current.getClippedPathBoundingBox(pathType, (0,display_utils.getCurrentTransform)(ctx)) || [0, 0, 0, 0];\n      const width = Math.ceil(ownerBBox[2] - ownerBBox[0]) || 1;\n      const height = Math.ceil(ownerBBox[3] - ownerBBox[1]) || 1;\n      const tmpCanvas = owner.cachedCanvases.getCanvas(\"pattern\", width, height, true);\n      const tmpCtx = tmpCanvas.context;\n      tmpCtx.clearRect(0, 0, tmpCtx.canvas.width, tmpCtx.canvas.height);\n      tmpCtx.beginPath();\n      tmpCtx.rect(0, 0, tmpCtx.canvas.width, tmpCtx.canvas.height);\n      tmpCtx.translate(-ownerBBox[0], -ownerBBox[1]);\n      inverse = util.Util.transform(inverse, [1, 0, 0, 1, ownerBBox[0], ownerBBox[1]]);\n      tmpCtx.transform(...owner.baseTransform);\n      if (this.matrix) {\n        tmpCtx.transform(...this.matrix);\n      }\n      applyBoundingBox(tmpCtx, this._bbox);\n      tmpCtx.fillStyle = this._createGradient(tmpCtx);\n      tmpCtx.fill();\n      pattern = ctx.createPattern(tmpCanvas.canvas, \"no-repeat\");\n      const domMatrix = new DOMMatrix(inverse);\n      pattern.setTransform(domMatrix);\n    } else {\n      applyBoundingBox(ctx, this._bbox);\n      pattern = this._createGradient(ctx);\n    }\n    return pattern;\n  }\n}\nfunction drawTriangle(data, context, p1, p2, p3, c1, c2, c3) {\n  const coords = context.coords,\n    colors = context.colors;\n  const bytes = data.data,\n    rowSize = data.width * 4;\n  let tmp;\n  if (coords[p1 + 1] > coords[p2 + 1]) {\n    tmp = p1;\n    p1 = p2;\n    p2 = tmp;\n    tmp = c1;\n    c1 = c2;\n    c2 = tmp;\n  }\n  if (coords[p2 + 1] > coords[p3 + 1]) {\n    tmp = p2;\n    p2 = p3;\n    p3 = tmp;\n    tmp = c2;\n    c2 = c3;\n    c3 = tmp;\n  }\n  if (coords[p1 + 1] > coords[p2 + 1]) {\n    tmp = p1;\n    p1 = p2;\n    p2 = tmp;\n    tmp = c1;\n    c1 = c2;\n    c2 = tmp;\n  }\n  const x1 = (coords[p1] + context.offsetX) * context.scaleX;\n  const y1 = (coords[p1 + 1] + context.offsetY) * context.scaleY;\n  const x2 = (coords[p2] + context.offsetX) * context.scaleX;\n  const y2 = (coords[p2 + 1] + context.offsetY) * context.scaleY;\n  const x3 = (coords[p3] + context.offsetX) * context.scaleX;\n  const y3 = (coords[p3 + 1] + context.offsetY) * context.scaleY;\n  if (y1 >= y3) {\n    return;\n  }\n  const c1r = colors[c1],\n    c1g = colors[c1 + 1],\n    c1b = colors[c1 + 2];\n  const c2r = colors[c2],\n    c2g = colors[c2 + 1],\n    c2b = colors[c2 + 2];\n  const c3r = colors[c3],\n    c3g = colors[c3 + 1],\n    c3b = colors[c3 + 2];\n  const minY = Math.round(y1),\n    maxY = Math.round(y3);\n  let xa, car, cag, cab;\n  let xb, cbr, cbg, cbb;\n  for (let y = minY; y <= maxY; y++) {\n    if (y < y2) {\n      const k = y < y1 ? 0 : (y1 - y) / (y1 - y2);\n      xa = x1 - (x1 - x2) * k;\n      car = c1r - (c1r - c2r) * k;\n      cag = c1g - (c1g - c2g) * k;\n      cab = c1b - (c1b - c2b) * k;\n    } else {\n      let k;\n      if (y > y3) {\n        k = 1;\n      } else if (y2 === y3) {\n        k = 0;\n      } else {\n        k = (y2 - y) / (y2 - y3);\n      }\n      xa = x2 - (x2 - x3) * k;\n      car = c2r - (c2r - c3r) * k;\n      cag = c2g - (c2g - c3g) * k;\n      cab = c2b - (c2b - c3b) * k;\n    }\n    let k;\n    if (y < y1) {\n      k = 0;\n    } else if (y > y3) {\n      k = 1;\n    } else {\n      k = (y1 - y) / (y1 - y3);\n    }\n    xb = x1 - (x1 - x3) * k;\n    cbr = c1r - (c1r - c3r) * k;\n    cbg = c1g - (c1g - c3g) * k;\n    cbb = c1b - (c1b - c3b) * k;\n    const x1_ = Math.round(Math.min(xa, xb));\n    const x2_ = Math.round(Math.max(xa, xb));\n    let j = rowSize * y + x1_ * 4;\n    for (let x = x1_; x <= x2_; x++) {\n      k = (xa - x) / (xa - xb);\n      if (k < 0) {\n        k = 0;\n      } else if (k > 1) {\n        k = 1;\n      }\n      bytes[j++] = car - (car - cbr) * k | 0;\n      bytes[j++] = cag - (cag - cbg) * k | 0;\n      bytes[j++] = cab - (cab - cbb) * k | 0;\n      bytes[j++] = 255;\n    }\n  }\n}\nfunction drawFigure(data, figure, context) {\n  const ps = figure.coords;\n  const cs = figure.colors;\n  let i, ii;\n  switch (figure.type) {\n    case \"lattice\":\n      const verticesPerRow = figure.verticesPerRow;\n      const rows = Math.floor(ps.length / verticesPerRow) - 1;\n      const cols = verticesPerRow - 1;\n      for (i = 0; i < rows; i++) {\n        let q = i * verticesPerRow;\n        for (let j = 0; j < cols; j++, q++) {\n          drawTriangle(data, context, ps[q], ps[q + 1], ps[q + verticesPerRow], cs[q], cs[q + 1], cs[q + verticesPerRow]);\n          drawTriangle(data, context, ps[q + verticesPerRow + 1], ps[q + 1], ps[q + verticesPerRow], cs[q + verticesPerRow + 1], cs[q + 1], cs[q + verticesPerRow]);\n        }\n      }\n      break;\n    case \"triangles\":\n      for (i = 0, ii = ps.length; i < ii; i += 3) {\n        drawTriangle(data, context, ps[i], ps[i + 1], ps[i + 2], cs[i], cs[i + 1], cs[i + 2]);\n      }\n      break;\n    default:\n      throw new Error(\"illegal figure\");\n  }\n}\nclass MeshShadingPattern extends BaseShadingPattern {\n  constructor(IR) {\n    super();\n    this._coords = IR[2];\n    this._colors = IR[3];\n    this._figures = IR[4];\n    this._bounds = IR[5];\n    this._bbox = IR[7];\n    this._background = IR[8];\n    this.matrix = null;\n  }\n  _createMeshCanvas(combinedScale, backgroundColor, cachedCanvases) {\n    const EXPECTED_SCALE = 1.1;\n    const MAX_PATTERN_SIZE = 3000;\n    const BORDER_SIZE = 2;\n    const offsetX = Math.floor(this._bounds[0]);\n    const offsetY = Math.floor(this._bounds[1]);\n    const boundsWidth = Math.ceil(this._bounds[2]) - offsetX;\n    const boundsHeight = Math.ceil(this._bounds[3]) - offsetY;\n    const width = Math.min(Math.ceil(Math.abs(boundsWidth * combinedScale[0] * EXPECTED_SCALE)), MAX_PATTERN_SIZE);\n    const height = Math.min(Math.ceil(Math.abs(boundsHeight * combinedScale[1] * EXPECTED_SCALE)), MAX_PATTERN_SIZE);\n    const scaleX = boundsWidth / width;\n    const scaleY = boundsHeight / height;\n    const context = {\n      coords: this._coords,\n      colors: this._colors,\n      offsetX: -offsetX,\n      offsetY: -offsetY,\n      scaleX: 1 / scaleX,\n      scaleY: 1 / scaleY\n    };\n    const paddedWidth = width + BORDER_SIZE * 2;\n    const paddedHeight = height + BORDER_SIZE * 2;\n    const tmpCanvas = cachedCanvases.getCanvas(\"mesh\", paddedWidth, paddedHeight, false);\n    const tmpCtx = tmpCanvas.context;\n    const data = tmpCtx.createImageData(width, height);\n    if (backgroundColor) {\n      const bytes = data.data;\n      for (let i = 0, ii = bytes.length; i < ii; i += 4) {\n        bytes[i] = backgroundColor[0];\n        bytes[i + 1] = backgroundColor[1];\n        bytes[i + 2] = backgroundColor[2];\n        bytes[i + 3] = 255;\n      }\n    }\n    for (const figure of this._figures) {\n      drawFigure(data, figure, context);\n    }\n    tmpCtx.putImageData(data, BORDER_SIZE, BORDER_SIZE);\n    const canvas = tmpCanvas.canvas;\n    return {\n      canvas,\n      offsetX: offsetX - BORDER_SIZE * scaleX,\n      offsetY: offsetY - BORDER_SIZE * scaleY,\n      scaleX,\n      scaleY\n    };\n  }\n  getPattern(ctx, owner, inverse, pathType) {\n    applyBoundingBox(ctx, this._bbox);\n    let scale;\n    if (pathType === PathType.SHADING) {\n      scale = util.Util.singularValueDecompose2dScale((0,display_utils.getCurrentTransform)(ctx));\n    } else {\n      scale = util.Util.singularValueDecompose2dScale(owner.baseTransform);\n      if (this.matrix) {\n        const matrixScale = util.Util.singularValueDecompose2dScale(this.matrix);\n        scale = [scale[0] * matrixScale[0], scale[1] * matrixScale[1]];\n      }\n    }\n    const temporaryPatternCanvas = this._createMeshCanvas(scale, pathType === PathType.SHADING ? null : this._background, owner.cachedCanvases);\n    if (pathType !== PathType.SHADING) {\n      ctx.setTransform(...owner.baseTransform);\n      if (this.matrix) {\n        ctx.transform(...this.matrix);\n      }\n    }\n    ctx.translate(temporaryPatternCanvas.offsetX, temporaryPatternCanvas.offsetY);\n    ctx.scale(temporaryPatternCanvas.scaleX, temporaryPatternCanvas.scaleY);\n    return ctx.createPattern(temporaryPatternCanvas.canvas, \"no-repeat\");\n  }\n}\nclass DummyShadingPattern extends BaseShadingPattern {\n  getPattern() {\n    return \"hotpink\";\n  }\n}\nfunction getShadingPattern(IR) {\n  switch (IR[0]) {\n    case \"RadialAxial\":\n      return new RadialAxialShadingPattern(IR);\n    case \"Mesh\":\n      return new MeshShadingPattern(IR);\n    case \"Dummy\":\n      return new DummyShadingPattern();\n  }\n  throw new Error(`Unknown IR type: ${IR[0]}`);\n}\nconst PaintType = {\n  COLORED: 1,\n  UNCOLORED: 2\n};\nclass TilingPattern {\n  static MAX_PATTERN_SIZE = 3000;\n  constructor(IR, color, ctx, canvasGraphicsFactory, baseTransform) {\n    this.operatorList = IR[2];\n    this.matrix = IR[3] || [1, 0, 0, 1, 0, 0];\n    this.bbox = IR[4];\n    this.xstep = IR[5];\n    this.ystep = IR[6];\n    this.paintType = IR[7];\n    this.tilingType = IR[8];\n    this.color = color;\n    this.ctx = ctx;\n    this.canvasGraphicsFactory = canvasGraphicsFactory;\n    this.baseTransform = baseTransform;\n  }\n  createPatternCanvas(owner) {\n    const operatorList = this.operatorList;\n    const bbox = this.bbox;\n    const xstep = this.xstep;\n    const ystep = this.ystep;\n    const paintType = this.paintType;\n    const tilingType = this.tilingType;\n    const color = this.color;\n    const canvasGraphicsFactory = this.canvasGraphicsFactory;\n    (0,util.info)(\"TilingType: \" + tilingType);\n    const x0 = bbox[0],\n      y0 = bbox[1],\n      x1 = bbox[2],\n      y1 = bbox[3];\n    const matrixScale = util.Util.singularValueDecompose2dScale(this.matrix);\n    const curMatrixScale = util.Util.singularValueDecompose2dScale(this.baseTransform);\n    const combinedScale = [matrixScale[0] * curMatrixScale[0], matrixScale[1] * curMatrixScale[1]];\n    const dimx = this.getSizeAndScale(xstep, this.ctx.canvas.width, combinedScale[0]);\n    const dimy = this.getSizeAndScale(ystep, this.ctx.canvas.height, combinedScale[1]);\n    const tmpCanvas = owner.cachedCanvases.getCanvas(\"pattern\", dimx.size, dimy.size, true);\n    const tmpCtx = tmpCanvas.context;\n    const graphics = canvasGraphicsFactory.createCanvasGraphics(tmpCtx);\n    graphics.groupLevel = owner.groupLevel;\n    this.setFillAndStrokeStyleToContext(graphics, paintType, color);\n    let adjustedX0 = x0;\n    let adjustedY0 = y0;\n    let adjustedX1 = x1;\n    let adjustedY1 = y1;\n    if (x0 < 0) {\n      adjustedX0 = 0;\n      adjustedX1 += Math.abs(x0);\n    }\n    if (y0 < 0) {\n      adjustedY0 = 0;\n      adjustedY1 += Math.abs(y0);\n    }\n    tmpCtx.translate(-(dimx.scale * adjustedX0), -(dimy.scale * adjustedY0));\n    graphics.transform(dimx.scale, 0, 0, dimy.scale, 0, 0);\n    tmpCtx.save();\n    this.clipBbox(graphics, adjustedX0, adjustedY0, adjustedX1, adjustedY1);\n    graphics.baseTransform = (0,display_utils.getCurrentTransform)(graphics.ctx);\n    graphics.executeOperatorList(operatorList);\n    graphics.endDrawing();\n    return {\n      canvas: tmpCanvas.canvas,\n      scaleX: dimx.scale,\n      scaleY: dimy.scale,\n      offsetX: adjustedX0,\n      offsetY: adjustedY0\n    };\n  }\n  getSizeAndScale(step, realOutputSize, scale) {\n    step = Math.abs(step);\n    const maxSize = Math.max(TilingPattern.MAX_PATTERN_SIZE, realOutputSize);\n    let size = Math.ceil(step * scale);\n    if (size >= maxSize) {\n      size = maxSize;\n    } else {\n      scale = size / step;\n    }\n    return {\n      scale,\n      size\n    };\n  }\n  clipBbox(graphics, x0, y0, x1, y1) {\n    const bboxWidth = x1 - x0;\n    const bboxHeight = y1 - y0;\n    graphics.ctx.rect(x0, y0, bboxWidth, bboxHeight);\n    graphics.current.updateRectMinMax((0,display_utils.getCurrentTransform)(graphics.ctx), [x0, y0, x1, y1]);\n    graphics.clip();\n    graphics.endPath();\n  }\n  setFillAndStrokeStyleToContext(graphics, paintType, color) {\n    const context = graphics.ctx,\n      current = graphics.current;\n    switch (paintType) {\n      case PaintType.COLORED:\n        const ctx = this.ctx;\n        context.fillStyle = ctx.fillStyle;\n        context.strokeStyle = ctx.strokeStyle;\n        current.fillColor = ctx.fillStyle;\n        current.strokeColor = ctx.strokeStyle;\n        break;\n      case PaintType.UNCOLORED:\n        const cssColor = util.Util.makeHexColor(color[0], color[1], color[2]);\n        context.fillStyle = cssColor;\n        context.strokeStyle = cssColor;\n        current.fillColor = cssColor;\n        current.strokeColor = cssColor;\n        break;\n      default:\n        throw new util.FormatError(`Unsupported paint type: ${paintType}`);\n    }\n  }\n  getPattern(ctx, owner, inverse, pathType) {\n    let matrix = inverse;\n    if (pathType !== PathType.SHADING) {\n      matrix = util.Util.transform(matrix, owner.baseTransform);\n      if (this.matrix) {\n        matrix = util.Util.transform(matrix, this.matrix);\n      }\n    }\n    const temporaryPatternCanvas = this.createPatternCanvas(owner);\n    let domMatrix = new DOMMatrix(matrix);\n    domMatrix = domMatrix.translate(temporaryPatternCanvas.offsetX, temporaryPatternCanvas.offsetY);\n    domMatrix = domMatrix.scale(1 / temporaryPatternCanvas.scaleX, 1 / temporaryPatternCanvas.scaleY);\n    const pattern = ctx.createPattern(temporaryPatternCanvas.canvas, \"repeat\");\n    pattern.setTransform(domMatrix);\n    return pattern;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/shared/image_utils.js\n\nfunction convertToRGBA(params) {\n  switch (params.kind) {\n    case ImageKind.GRAYSCALE_1BPP:\n      return convertBlackAndWhiteToRGBA(params);\n    case ImageKind.RGB_24BPP:\n      return convertRGBToRGBA(params);\n  }\n  return null;\n}\nfunction convertBlackAndWhiteToRGBA({\n  src,\n  srcPos = 0,\n  dest,\n  width,\n  height,\n  nonBlackColor = 0xffffffff,\n  inverseDecode = false\n}) {\n  const black = util.FeatureTest.isLittleEndian ? 0xff000000 : 0x000000ff;\n  const [zeroMapping, oneMapping] = inverseDecode ? [nonBlackColor, black] : [black, nonBlackColor];\n  const widthInSource = width >> 3;\n  const widthRemainder = width & 7;\n  const srcLength = src.length;\n  dest = new Uint32Array(dest.buffer);\n  let destPos = 0;\n  for (let i = 0; i < height; i++) {\n    for (const max = srcPos + widthInSource; srcPos < max; srcPos++) {\n      const elem = srcPos < srcLength ? src[srcPos] : 255;\n      dest[destPos++] = elem & 0b10000000 ? oneMapping : zeroMapping;\n      dest[destPos++] = elem & 0b1000000 ? oneMapping : zeroMapping;\n      dest[destPos++] = elem & 0b100000 ? oneMapping : zeroMapping;\n      dest[destPos++] = elem & 0b10000 ? oneMapping : zeroMapping;\n      dest[destPos++] = elem & 0b1000 ? oneMapping : zeroMapping;\n      dest[destPos++] = elem & 0b100 ? oneMapping : zeroMapping;\n      dest[destPos++] = elem & 0b10 ? oneMapping : zeroMapping;\n      dest[destPos++] = elem & 0b1 ? oneMapping : zeroMapping;\n    }\n    if (widthRemainder === 0) {\n      continue;\n    }\n    const elem = srcPos < srcLength ? src[srcPos++] : 255;\n    for (let j = 0; j < widthRemainder; j++) {\n      dest[destPos++] = elem & 1 << 7 - j ? oneMapping : zeroMapping;\n    }\n  }\n  return {\n    srcPos,\n    destPos\n  };\n}\nfunction convertRGBToRGBA({\n  src,\n  srcPos = 0,\n  dest,\n  destPos = 0,\n  width,\n  height\n}) {\n  let i = 0;\n  const len32 = src.length >> 2;\n  const src32 = new Uint32Array(src.buffer, srcPos, len32);\n  if (FeatureTest.isLittleEndian) {\n    for (; i < len32 - 2; i += 3, destPos += 4) {\n      const s1 = src32[i];\n      const s2 = src32[i + 1];\n      const s3 = src32[i + 2];\n      dest[destPos] = s1 | 0xff000000;\n      dest[destPos + 1] = s1 >>> 24 | s2 << 8 | 0xff000000;\n      dest[destPos + 2] = s2 >>> 16 | s3 << 16 | 0xff000000;\n      dest[destPos + 3] = s3 >>> 8 | 0xff000000;\n    }\n    for (let j = i * 4, jj = src.length; j < jj; j += 3) {\n      dest[destPos++] = src[j] | src[j + 1] << 8 | src[j + 2] << 16 | 0xff000000;\n    }\n  } else {\n    for (; i < len32 - 2; i += 3, destPos += 4) {\n      const s1 = src32[i];\n      const s2 = src32[i + 1];\n      const s3 = src32[i + 2];\n      dest[destPos] = s1 | 0xff;\n      dest[destPos + 1] = s1 << 24 | s2 >>> 8 | 0xff;\n      dest[destPos + 2] = s2 << 16 | s3 >>> 16 | 0xff;\n      dest[destPos + 3] = s3 << 8 | 0xff;\n    }\n    for (let j = i * 4, jj = src.length; j < jj; j += 3) {\n      dest[destPos++] = src[j] << 24 | src[j + 1] << 16 | src[j + 2] << 8 | 0xff;\n    }\n  }\n  return {\n    srcPos,\n    destPos\n  };\n}\nfunction grayToRGBA(src, dest) {\n  if (FeatureTest.isLittleEndian) {\n    for (let i = 0, ii = src.length; i < ii; i++) {\n      dest[i] = src[i] * 0x10101 | 0xff000000;\n    }\n  } else {\n    for (let i = 0, ii = src.length; i < ii; i++) {\n      dest[i] = src[i] * 0x1010100 | 0x000000ff;\n    }\n  }\n}\n\n;// CONCATENATED MODULE: ./src/display/canvas.js\n\n\n\n\nconst MIN_FONT_SIZE = 16;\nconst MAX_FONT_SIZE = 100;\nconst MAX_GROUP_SIZE = 4096;\nconst EXECUTION_TIME = 15;\nconst EXECUTION_STEPS = 10;\nconst MAX_SIZE_TO_COMPILE = 1000;\nconst FULL_CHUNK_HEIGHT = 16;\nfunction mirrorContextOperations(ctx, destCtx) {\n  if (ctx._removeMirroring) {\n    throw new Error(\"Context is already forwarding operations.\");\n  }\n  ctx.__originalSave = ctx.save;\n  ctx.__originalRestore = ctx.restore;\n  ctx.__originalRotate = ctx.rotate;\n  ctx.__originalScale = ctx.scale;\n  ctx.__originalTranslate = ctx.translate;\n  ctx.__originalTransform = ctx.transform;\n  ctx.__originalSetTransform = ctx.setTransform;\n  ctx.__originalResetTransform = ctx.resetTransform;\n  ctx.__originalClip = ctx.clip;\n  ctx.__originalMoveTo = ctx.moveTo;\n  ctx.__originalLineTo = ctx.lineTo;\n  ctx.__originalBezierCurveTo = ctx.bezierCurveTo;\n  ctx.__originalRect = ctx.rect;\n  ctx.__originalClosePath = ctx.closePath;\n  ctx.__originalBeginPath = ctx.beginPath;\n  ctx._removeMirroring = () => {\n    ctx.save = ctx.__originalSave;\n    ctx.restore = ctx.__originalRestore;\n    ctx.rotate = ctx.__originalRotate;\n    ctx.scale = ctx.__originalScale;\n    ctx.translate = ctx.__originalTranslate;\n    ctx.transform = ctx.__originalTransform;\n    ctx.setTransform = ctx.__originalSetTransform;\n    ctx.resetTransform = ctx.__originalResetTransform;\n    ctx.clip = ctx.__originalClip;\n    ctx.moveTo = ctx.__originalMoveTo;\n    ctx.lineTo = ctx.__originalLineTo;\n    ctx.bezierCurveTo = ctx.__originalBezierCurveTo;\n    ctx.rect = ctx.__originalRect;\n    ctx.closePath = ctx.__originalClosePath;\n    ctx.beginPath = ctx.__originalBeginPath;\n    delete ctx._removeMirroring;\n  };\n  ctx.save = function ctxSave() {\n    destCtx.save();\n    this.__originalSave();\n  };\n  ctx.restore = function ctxRestore() {\n    destCtx.restore();\n    this.__originalRestore();\n  };\n  ctx.translate = function ctxTranslate(x, y) {\n    destCtx.translate(x, y);\n    this.__originalTranslate(x, y);\n  };\n  ctx.scale = function ctxScale(x, y) {\n    destCtx.scale(x, y);\n    this.__originalScale(x, y);\n  };\n  ctx.transform = function ctxTransform(a, b, c, d, e, f) {\n    destCtx.transform(a, b, c, d, e, f);\n    this.__originalTransform(a, b, c, d, e, f);\n  };\n  ctx.setTransform = function ctxSetTransform(a, b, c, d, e, f) {\n    destCtx.setTransform(a, b, c, d, e, f);\n    this.__originalSetTransform(a, b, c, d, e, f);\n  };\n  ctx.resetTransform = function ctxResetTransform() {\n    destCtx.resetTransform();\n    this.__originalResetTransform();\n  };\n  ctx.rotate = function ctxRotate(angle) {\n    destCtx.rotate(angle);\n    this.__originalRotate(angle);\n  };\n  ctx.clip = function ctxRotate(rule) {\n    destCtx.clip(rule);\n    this.__originalClip(rule);\n  };\n  ctx.moveTo = function (x, y) {\n    destCtx.moveTo(x, y);\n    this.__originalMoveTo(x, y);\n  };\n  ctx.lineTo = function (x, y) {\n    destCtx.lineTo(x, y);\n    this.__originalLineTo(x, y);\n  };\n  ctx.bezierCurveTo = function (cp1x, cp1y, cp2x, cp2y, x, y) {\n    destCtx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);\n    this.__originalBezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);\n  };\n  ctx.rect = function (x, y, width, height) {\n    destCtx.rect(x, y, width, height);\n    this.__originalRect(x, y, width, height);\n  };\n  ctx.closePath = function () {\n    destCtx.closePath();\n    this.__originalClosePath();\n  };\n  ctx.beginPath = function () {\n    destCtx.beginPath();\n    this.__originalBeginPath();\n  };\n}\nclass CachedCanvases {\n  constructor(canvasFactory) {\n    this.canvasFactory = canvasFactory;\n    this.cache = Object.create(null);\n  }\n  getCanvas(id, width, height) {\n    let canvasEntry;\n    if (this.cache[id] !== undefined) {\n      canvasEntry = this.cache[id];\n      this.canvasFactory.reset(canvasEntry, width, height);\n    } else {\n      canvasEntry = this.canvasFactory.create(width, height);\n      this.cache[id] = canvasEntry;\n    }\n    return canvasEntry;\n  }\n  delete(id) {\n    delete this.cache[id];\n  }\n  clear() {\n    for (const id in this.cache) {\n      const canvasEntry = this.cache[id];\n      this.canvasFactory.destroy(canvasEntry);\n      delete this.cache[id];\n    }\n  }\n}\nfunction drawImageAtIntegerCoords(ctx, srcImg, srcX, srcY, srcW, srcH, destX, destY, destW, destH) {\n  const [a, b, c, d, tx, ty] = (0,display_utils.getCurrentTransform)(ctx);\n  if (b === 0 && c === 0) {\n    const tlX = destX * a + tx;\n    const rTlX = Math.round(tlX);\n    const tlY = destY * d + ty;\n    const rTlY = Math.round(tlY);\n    const brX = (destX + destW) * a + tx;\n    const rWidth = Math.abs(Math.round(brX) - rTlX) || 1;\n    const brY = (destY + destH) * d + ty;\n    const rHeight = Math.abs(Math.round(brY) - rTlY) || 1;\n    ctx.setTransform(Math.sign(a), 0, 0, Math.sign(d), rTlX, rTlY);\n    ctx.drawImage(srcImg, srcX, srcY, srcW, srcH, 0, 0, rWidth, rHeight);\n    ctx.setTransform(a, b, c, d, tx, ty);\n    return [rWidth, rHeight];\n  }\n  if (a === 0 && d === 0) {\n    const tlX = destY * c + tx;\n    const rTlX = Math.round(tlX);\n    const tlY = destX * b + ty;\n    const rTlY = Math.round(tlY);\n    const brX = (destY + destH) * c + tx;\n    const rWidth = Math.abs(Math.round(brX) - rTlX) || 1;\n    const brY = (destX + destW) * b + ty;\n    const rHeight = Math.abs(Math.round(brY) - rTlY) || 1;\n    ctx.setTransform(0, Math.sign(b), Math.sign(c), 0, rTlX, rTlY);\n    ctx.drawImage(srcImg, srcX, srcY, srcW, srcH, 0, 0, rHeight, rWidth);\n    ctx.setTransform(a, b, c, d, tx, ty);\n    return [rHeight, rWidth];\n  }\n  ctx.drawImage(srcImg, srcX, srcY, srcW, srcH, destX, destY, destW, destH);\n  const scaleX = Math.hypot(a, b);\n  const scaleY = Math.hypot(c, d);\n  return [scaleX * destW, scaleY * destH];\n}\nfunction compileType3Glyph(imgData) {\n  const {\n    width,\n    height\n  } = imgData;\n  if (width > MAX_SIZE_TO_COMPILE || height > MAX_SIZE_TO_COMPILE) {\n    return null;\n  }\n  const POINT_TO_PROCESS_LIMIT = 1000;\n  const POINT_TYPES = new Uint8Array([0, 2, 4, 0, 1, 0, 5, 4, 8, 10, 0, 8, 0, 2, 1, 0]);\n  const width1 = width + 1;\n  let points = new Uint8Array(width1 * (height + 1));\n  let i, j, j0;\n  const lineSize = width + 7 & ~7;\n  let data = new Uint8Array(lineSize * height),\n    pos = 0;\n  for (const elem of imgData.data) {\n    let mask = 128;\n    while (mask > 0) {\n      data[pos++] = elem & mask ? 0 : 255;\n      mask >>= 1;\n    }\n  }\n  let count = 0;\n  pos = 0;\n  if (data[pos] !== 0) {\n    points[0] = 1;\n    ++count;\n  }\n  for (j = 1; j < width; j++) {\n    if (data[pos] !== data[pos + 1]) {\n      points[j] = data[pos] ? 2 : 1;\n      ++count;\n    }\n    pos++;\n  }\n  if (data[pos] !== 0) {\n    points[j] = 2;\n    ++count;\n  }\n  for (i = 1; i < height; i++) {\n    pos = i * lineSize;\n    j0 = i * width1;\n    if (data[pos - lineSize] !== data[pos]) {\n      points[j0] = data[pos] ? 1 : 8;\n      ++count;\n    }\n    let sum = (data[pos] ? 4 : 0) + (data[pos - lineSize] ? 8 : 0);\n    for (j = 1; j < width; j++) {\n      sum = (sum >> 2) + (data[pos + 1] ? 4 : 0) + (data[pos - lineSize + 1] ? 8 : 0);\n      if (POINT_TYPES[sum]) {\n        points[j0 + j] = POINT_TYPES[sum];\n        ++count;\n      }\n      pos++;\n    }\n    if (data[pos - lineSize] !== data[pos]) {\n      points[j0 + j] = data[pos] ? 2 : 4;\n      ++count;\n    }\n    if (count > POINT_TO_PROCESS_LIMIT) {\n      return null;\n    }\n  }\n  pos = lineSize * (height - 1);\n  j0 = i * width1;\n  if (data[pos] !== 0) {\n    points[j0] = 8;\n    ++count;\n  }\n  for (j = 1; j < width; j++) {\n    if (data[pos] !== data[pos + 1]) {\n      points[j0 + j] = data[pos] ? 4 : 8;\n      ++count;\n    }\n    pos++;\n  }\n  if (data[pos] !== 0) {\n    points[j0 + j] = 4;\n    ++count;\n  }\n  if (count > POINT_TO_PROCESS_LIMIT) {\n    return null;\n  }\n  const steps = new Int32Array([0, width1, -1, 0, -width1, 0, 0, 0, 1]);\n  const path = new Path2D();\n  for (i = 0; count && i <= height; i++) {\n    let p = i * width1;\n    const end = p + width;\n    while (p < end && !points[p]) {\n      p++;\n    }\n    if (p === end) {\n      continue;\n    }\n    path.moveTo(p % width1, i);\n    const p0 = p;\n    let type = points[p];\n    do {\n      const step = steps[type];\n      do {\n        p += step;\n      } while (!points[p]);\n      const pp = points[p];\n      if (pp !== 5 && pp !== 10) {\n        type = pp;\n        points[p] = 0;\n      } else {\n        type = pp & 0x33 * type >> 4;\n        points[p] &= type >> 2 | type << 2;\n      }\n      path.lineTo(p % width1, p / width1 | 0);\n      if (!points[p]) {\n        --count;\n      }\n    } while (p0 !== p);\n    --i;\n  }\n  data = null;\n  points = null;\n  const drawOutline = function (c) {\n    c.save();\n    c.scale(1 / width, -1 / height);\n    c.translate(0, -height);\n    c.fill(path);\n    c.beginPath();\n    c.restore();\n  };\n  return drawOutline;\n}\nclass CanvasExtraState {\n  constructor(width, height) {\n    this.alphaIsShape = false;\n    this.fontSize = 0;\n    this.fontSizeScale = 1;\n    this.textMatrix = util.IDENTITY_MATRIX;\n    this.textMatrixScale = 1;\n    this.fontMatrix = util.FONT_IDENTITY_MATRIX;\n    this.leading = 0;\n    this.x = 0;\n    this.y = 0;\n    this.lineX = 0;\n    this.lineY = 0;\n    this.charSpacing = 0;\n    this.wordSpacing = 0;\n    this.textHScale = 1;\n    this.textRenderingMode = util.TextRenderingMode.FILL;\n    this.textRise = 0;\n    this.fillColor = \"#000000\";\n    this.strokeColor = \"#000000\";\n    this.patternFill = false;\n    this.fillAlpha = 1;\n    this.strokeAlpha = 1;\n    this.lineWidth = 1;\n    this.activeSMask = null;\n    this.transferMaps = \"none\";\n    this.startNewPathAndClipBox([0, 0, width, height]);\n  }\n  clone() {\n    const clone = Object.create(this);\n    clone.clipBox = this.clipBox.slice();\n    return clone;\n  }\n  setCurrentPoint(x, y) {\n    this.x = x;\n    this.y = y;\n  }\n  updatePathMinMax(transform, x, y) {\n    [x, y] = util.Util.applyTransform([x, y], transform);\n    this.minX = Math.min(this.minX, x);\n    this.minY = Math.min(this.minY, y);\n    this.maxX = Math.max(this.maxX, x);\n    this.maxY = Math.max(this.maxY, y);\n  }\n  updateRectMinMax(transform, rect) {\n    const p1 = util.Util.applyTransform(rect, transform);\n    const p2 = util.Util.applyTransform(rect.slice(2), transform);\n    const p3 = util.Util.applyTransform([rect[0], rect[3]], transform);\n    const p4 = util.Util.applyTransform([rect[2], rect[1]], transform);\n    this.minX = Math.min(this.minX, p1[0], p2[0], p3[0], p4[0]);\n    this.minY = Math.min(this.minY, p1[1], p2[1], p3[1], p4[1]);\n    this.maxX = Math.max(this.maxX, p1[0], p2[0], p3[0], p4[0]);\n    this.maxY = Math.max(this.maxY, p1[1], p2[1], p3[1], p4[1]);\n  }\n  updateScalingPathMinMax(transform, minMax) {\n    util.Util.scaleMinMax(transform, minMax);\n    this.minX = Math.min(this.minX, minMax[0]);\n    this.minY = Math.min(this.minY, minMax[1]);\n    this.maxX = Math.max(this.maxX, minMax[2]);\n    this.maxY = Math.max(this.maxY, minMax[3]);\n  }\n  updateCurvePathMinMax(transform, x0, y0, x1, y1, x2, y2, x3, y3, minMax) {\n    const box = util.Util.bezierBoundingBox(x0, y0, x1, y1, x2, y2, x3, y3, minMax);\n    if (minMax) {\n      return;\n    }\n    this.updateRectMinMax(transform, box);\n  }\n  getPathBoundingBox(pathType = PathType.FILL, transform = null) {\n    const box = [this.minX, this.minY, this.maxX, this.maxY];\n    if (pathType === PathType.STROKE) {\n      if (!transform) {\n        (0,util.unreachable)(\"Stroke bounding box must include transform.\");\n      }\n      const scale = util.Util.singularValueDecompose2dScale(transform);\n      const xStrokePad = scale[0] * this.lineWidth / 2;\n      const yStrokePad = scale[1] * this.lineWidth / 2;\n      box[0] -= xStrokePad;\n      box[1] -= yStrokePad;\n      box[2] += xStrokePad;\n      box[3] += yStrokePad;\n    }\n    return box;\n  }\n  updateClipFromPath() {\n    const intersect = util.Util.intersect(this.clipBox, this.getPathBoundingBox());\n    this.startNewPathAndClipBox(intersect || [0, 0, 0, 0]);\n  }\n  isEmptyClip() {\n    return this.minX === Infinity;\n  }\n  startNewPathAndClipBox(box) {\n    this.clipBox = box;\n    this.minX = Infinity;\n    this.minY = Infinity;\n    this.maxX = 0;\n    this.maxY = 0;\n  }\n  getClippedPathBoundingBox(pathType = PathType.FILL, transform = null) {\n    return util.Util.intersect(this.clipBox, this.getPathBoundingBox(pathType, transform));\n  }\n}\nfunction putBinaryImageData(ctx, imgData) {\n  if (typeof ImageData !== \"undefined\" && imgData instanceof ImageData) {\n    ctx.putImageData(imgData, 0, 0);\n    return;\n  }\n  const height = imgData.height,\n    width = imgData.width;\n  const partialChunkHeight = height % FULL_CHUNK_HEIGHT;\n  const fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT;\n  const totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1;\n  const chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT);\n  let srcPos = 0,\n    destPos;\n  const src = imgData.data;\n  const dest = chunkImgData.data;\n  let i, j, thisChunkHeight, elemsInThisChunk;\n  if (imgData.kind === util.ImageKind.GRAYSCALE_1BPP) {\n    const srcLength = src.byteLength;\n    const dest32 = new Uint32Array(dest.buffer, 0, dest.byteLength >> 2);\n    const dest32DataLength = dest32.length;\n    const fullSrcDiff = width + 7 >> 3;\n    const white = 0xffffffff;\n    const black = util.FeatureTest.isLittleEndian ? 0xff000000 : 0x000000ff;\n    for (i = 0; i < totalChunks; i++) {\n      thisChunkHeight = i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight;\n      destPos = 0;\n      for (j = 0; j < thisChunkHeight; j++) {\n        const srcDiff = srcLength - srcPos;\n        let k = 0;\n        const kEnd = srcDiff > fullSrcDiff ? width : srcDiff * 8 - 7;\n        const kEndUnrolled = kEnd & ~7;\n        let mask = 0;\n        let srcByte = 0;\n        for (; k < kEndUnrolled; k += 8) {\n          srcByte = src[srcPos++];\n          dest32[destPos++] = srcByte & 128 ? white : black;\n          dest32[destPos++] = srcByte & 64 ? white : black;\n          dest32[destPos++] = srcByte & 32 ? white : black;\n          dest32[destPos++] = srcByte & 16 ? white : black;\n          dest32[destPos++] = srcByte & 8 ? white : black;\n          dest32[destPos++] = srcByte & 4 ? white : black;\n          dest32[destPos++] = srcByte & 2 ? white : black;\n          dest32[destPos++] = srcByte & 1 ? white : black;\n        }\n        for (; k < kEnd; k++) {\n          if (mask === 0) {\n            srcByte = src[srcPos++];\n            mask = 128;\n          }\n          dest32[destPos++] = srcByte & mask ? white : black;\n          mask >>= 1;\n        }\n      }\n      while (destPos < dest32DataLength) {\n        dest32[destPos++] = 0;\n      }\n      ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);\n    }\n  } else if (imgData.kind === util.ImageKind.RGBA_32BPP) {\n    j = 0;\n    elemsInThisChunk = width * FULL_CHUNK_HEIGHT * 4;\n    for (i = 0; i < fullChunks; i++) {\n      dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk));\n      srcPos += elemsInThisChunk;\n      ctx.putImageData(chunkImgData, 0, j);\n      j += FULL_CHUNK_HEIGHT;\n    }\n    if (i < totalChunks) {\n      elemsInThisChunk = width * partialChunkHeight * 4;\n      dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk));\n      ctx.putImageData(chunkImgData, 0, j);\n    }\n  } else if (imgData.kind === util.ImageKind.RGB_24BPP) {\n    thisChunkHeight = FULL_CHUNK_HEIGHT;\n    elemsInThisChunk = width * thisChunkHeight;\n    for (i = 0; i < totalChunks; i++) {\n      if (i >= fullChunks) {\n        thisChunkHeight = partialChunkHeight;\n        elemsInThisChunk = width * thisChunkHeight;\n      }\n      destPos = 0;\n      for (j = elemsInThisChunk; j--;) {\n        dest[destPos++] = src[srcPos++];\n        dest[destPos++] = src[srcPos++];\n        dest[destPos++] = src[srcPos++];\n        dest[destPos++] = 255;\n      }\n      ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);\n    }\n  } else {\n    throw new Error(`bad image kind: ${imgData.kind}`);\n  }\n}\nfunction putBinaryImageMask(ctx, imgData) {\n  if (imgData.bitmap) {\n    ctx.drawImage(imgData.bitmap, 0, 0);\n    return;\n  }\n  const height = imgData.height,\n    width = imgData.width;\n  const partialChunkHeight = height % FULL_CHUNK_HEIGHT;\n  const fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT;\n  const totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1;\n  const chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT);\n  let srcPos = 0;\n  const src = imgData.data;\n  const dest = chunkImgData.data;\n  for (let i = 0; i < totalChunks; i++) {\n    const thisChunkHeight = i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight;\n    ({\n      srcPos\n    } = convertBlackAndWhiteToRGBA({\n      src,\n      srcPos,\n      dest,\n      width,\n      height: thisChunkHeight,\n      nonBlackColor: 0\n    }));\n    ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);\n  }\n}\nfunction copyCtxState(sourceCtx, destCtx) {\n  const properties = [\"strokeStyle\", \"fillStyle\", \"fillRule\", \"globalAlpha\", \"lineWidth\", \"lineCap\", \"lineJoin\", \"miterLimit\", \"globalCompositeOperation\", \"font\", \"filter\"];\n  for (const property of properties) {\n    if (sourceCtx[property] !== undefined) {\n      destCtx[property] = sourceCtx[property];\n    }\n  }\n  if (sourceCtx.setLineDash !== undefined) {\n    destCtx.setLineDash(sourceCtx.getLineDash());\n    destCtx.lineDashOffset = sourceCtx.lineDashOffset;\n  }\n}\nfunction resetCtxToDefault(ctx) {\n  ctx.strokeStyle = ctx.fillStyle = \"#000000\";\n  ctx.fillRule = \"nonzero\";\n  ctx.globalAlpha = 1;\n  ctx.lineWidth = 1;\n  ctx.lineCap = \"butt\";\n  ctx.lineJoin = \"miter\";\n  ctx.miterLimit = 10;\n  ctx.globalCompositeOperation = \"source-over\";\n  ctx.font = \"10px sans-serif\";\n  if (ctx.setLineDash !== undefined) {\n    ctx.setLineDash([]);\n    ctx.lineDashOffset = 0;\n  }\n  if (!util.isNodeJS) {\n    const {\n      filter\n    } = ctx;\n    if (filter !== \"none\" && filter !== \"\") {\n      ctx.filter = \"none\";\n    }\n  }\n}\nfunction composeSMaskBackdrop(bytes, r0, g0, b0) {\n  const length = bytes.length;\n  for (let i = 3; i < length; i += 4) {\n    const alpha = bytes[i];\n    if (alpha === 0) {\n      bytes[i - 3] = r0;\n      bytes[i - 2] = g0;\n      bytes[i - 1] = b0;\n    } else if (alpha < 255) {\n      const alpha_ = 255 - alpha;\n      bytes[i - 3] = bytes[i - 3] * alpha + r0 * alpha_ >> 8;\n      bytes[i - 2] = bytes[i - 2] * alpha + g0 * alpha_ >> 8;\n      bytes[i - 1] = bytes[i - 1] * alpha + b0 * alpha_ >> 8;\n    }\n  }\n}\nfunction composeSMaskAlpha(maskData, layerData, transferMap) {\n  const length = maskData.length;\n  const scale = 1 / 255;\n  for (let i = 3; i < length; i += 4) {\n    const alpha = transferMap ? transferMap[maskData[i]] : maskData[i];\n    layerData[i] = layerData[i] * alpha * scale | 0;\n  }\n}\nfunction composeSMaskLuminosity(maskData, layerData, transferMap) {\n  const length = maskData.length;\n  for (let i = 3; i < length; i += 4) {\n    const y = maskData[i - 3] * 77 + maskData[i - 2] * 152 + maskData[i - 1] * 28;\n    layerData[i] = transferMap ? layerData[i] * transferMap[y >> 8] >> 8 : layerData[i] * y >> 16;\n  }\n}\nfunction genericComposeSMask(maskCtx, layerCtx, width, height, subtype, backdrop, transferMap, layerOffsetX, layerOffsetY, maskOffsetX, maskOffsetY) {\n  const hasBackdrop = !!backdrop;\n  const r0 = hasBackdrop ? backdrop[0] : 0;\n  const g0 = hasBackdrop ? backdrop[1] : 0;\n  const b0 = hasBackdrop ? backdrop[2] : 0;\n  const composeFn = subtype === \"Luminosity\" ? composeSMaskLuminosity : composeSMaskAlpha;\n  const PIXELS_TO_PROCESS = 1048576;\n  const chunkSize = Math.min(height, Math.ceil(PIXELS_TO_PROCESS / width));\n  for (let row = 0; row < height; row += chunkSize) {\n    const chunkHeight = Math.min(chunkSize, height - row);\n    const maskData = maskCtx.getImageData(layerOffsetX - maskOffsetX, row + (layerOffsetY - maskOffsetY), width, chunkHeight);\n    const layerData = layerCtx.getImageData(layerOffsetX, row + layerOffsetY, width, chunkHeight);\n    if (hasBackdrop) {\n      composeSMaskBackdrop(maskData.data, r0, g0, b0);\n    }\n    composeFn(maskData.data, layerData.data, transferMap);\n    layerCtx.putImageData(layerData, layerOffsetX, row + layerOffsetY);\n  }\n}\nfunction composeSMask(ctx, smask, layerCtx, layerBox) {\n  const layerOffsetX = layerBox[0];\n  const layerOffsetY = layerBox[1];\n  const layerWidth = layerBox[2] - layerOffsetX;\n  const layerHeight = layerBox[3] - layerOffsetY;\n  if (layerWidth === 0 || layerHeight === 0) {\n    return;\n  }\n  genericComposeSMask(smask.context, layerCtx, layerWidth, layerHeight, smask.subtype, smask.backdrop, smask.transferMap, layerOffsetX, layerOffsetY, smask.offsetX, smask.offsetY);\n  ctx.save();\n  ctx.globalAlpha = 1;\n  ctx.globalCompositeOperation = \"source-over\";\n  ctx.setTransform(1, 0, 0, 1, 0, 0);\n  ctx.drawImage(layerCtx.canvas, 0, 0);\n  ctx.restore();\n}\nfunction getImageSmoothingEnabled(transform, interpolate) {\n  if (interpolate) {\n    return true;\n  }\n  const scale = util.Util.singularValueDecompose2dScale(transform);\n  scale[0] = Math.fround(scale[0]);\n  scale[1] = Math.fround(scale[1]);\n  const actualScale = Math.fround((globalThis.devicePixelRatio || 1) * display_utils.PixelsPerInch.PDF_TO_CSS_UNITS);\n  return scale[0] <= actualScale && scale[1] <= actualScale;\n}\nconst LINE_CAP_STYLES = [\"butt\", \"round\", \"square\"];\nconst LINE_JOIN_STYLES = [\"miter\", \"round\", \"bevel\"];\nconst NORMAL_CLIP = {};\nconst EO_CLIP = {};\nclass CanvasGraphics {\n  constructor(canvasCtx, commonObjs, objs, canvasFactory, filterFactory, {\n    optionalContentConfig,\n    markedContentStack = null\n  }, annotationCanvasMap, pageColors) {\n    this.ctx = canvasCtx;\n    this.current = new CanvasExtraState(this.ctx.canvas.width, this.ctx.canvas.height);\n    this.stateStack = [];\n    this.pendingClip = null;\n    this.pendingEOFill = false;\n    this.res = null;\n    this.xobjs = null;\n    this.commonObjs = commonObjs;\n    this.objs = objs;\n    this.canvasFactory = canvasFactory;\n    this.filterFactory = filterFactory;\n    this.groupStack = [];\n    this.processingType3 = null;\n    this.baseTransform = null;\n    this.baseTransformStack = [];\n    this.groupLevel = 0;\n    this.smaskStack = [];\n    this.smaskCounter = 0;\n    this.tempSMask = null;\n    this.suspendedCtx = null;\n    this.contentVisible = true;\n    this.markedContentStack = markedContentStack || [];\n    this.optionalContentConfig = optionalContentConfig;\n    this.cachedCanvases = new CachedCanvases(this.canvasFactory);\n    this.cachedPatterns = new Map();\n    this.annotationCanvasMap = annotationCanvasMap;\n    this.viewportScale = 1;\n    this.outputScaleX = 1;\n    this.outputScaleY = 1;\n    this.pageColors = pageColors;\n    this._cachedScaleForStroking = [-1, 0];\n    this._cachedGetSinglePixelWidth = null;\n    this._cachedBitmapsMap = new Map();\n  }\n  getObject(data, fallback = null) {\n    if (typeof data === \"string\") {\n      return data.startsWith(\"g_\") ? this.commonObjs.get(data) : this.objs.get(data);\n    }\n    return fallback;\n  }\n  beginDrawing({\n    transform,\n    viewport,\n    transparency = false,\n    background = null\n  }) {\n    const width = this.ctx.canvas.width;\n    const height = this.ctx.canvas.height;\n    const savedFillStyle = this.ctx.fillStyle;\n    this.ctx.fillStyle = background || \"#ffffff\";\n    this.ctx.fillRect(0, 0, width, height);\n    this.ctx.fillStyle = savedFillStyle;\n    if (transparency) {\n      const transparentCanvas = this.cachedCanvases.getCanvas(\"transparent\", width, height);\n      this.compositeCtx = this.ctx;\n      this.transparentCanvas = transparentCanvas.canvas;\n      this.ctx = transparentCanvas.context;\n      this.ctx.save();\n      this.ctx.transform(...(0,display_utils.getCurrentTransform)(this.compositeCtx));\n    }\n    this.ctx.save();\n    resetCtxToDefault(this.ctx);\n    if (transform) {\n      this.ctx.transform(...transform);\n      this.outputScaleX = transform[0];\n      this.outputScaleY = transform[0];\n    }\n    this.ctx.transform(...viewport.transform);\n    this.viewportScale = viewport.scale;\n    this.baseTransform = (0,display_utils.getCurrentTransform)(this.ctx);\n  }\n  executeOperatorList(operatorList, executionStartIdx, continueCallback, stepper) {\n    const argsArray = operatorList.argsArray;\n    const fnArray = operatorList.fnArray;\n    let i = executionStartIdx || 0;\n    const argsArrayLen = argsArray.length;\n    if (argsArrayLen === i) {\n      return i;\n    }\n    const chunkOperations = argsArrayLen - i > EXECUTION_STEPS && typeof continueCallback === \"function\";\n    const endTime = chunkOperations ? Date.now() + EXECUTION_TIME : 0;\n    let steps = 0;\n    const commonObjs = this.commonObjs;\n    const objs = this.objs;\n    let fnId;\n    while (true) {\n      if (stepper !== undefined && i === stepper.nextBreakPoint) {\n        stepper.breakIt(i, continueCallback);\n        return i;\n      }\n      fnId = fnArray[i];\n      if (fnId !== util.OPS.dependency) {\n        this[fnId].apply(this, argsArray[i]);\n      } else {\n        for (const depObjId of argsArray[i]) {\n          const objsPool = depObjId.startsWith(\"g_\") ? commonObjs : objs;\n          if (!objsPool.has(depObjId)) {\n            objsPool.get(depObjId, continueCallback);\n            return i;\n          }\n        }\n      }\n      i++;\n      if (i === argsArrayLen) {\n        return i;\n      }\n      if (chunkOperations && ++steps > EXECUTION_STEPS) {\n        if (Date.now() > endTime) {\n          continueCallback();\n          return i;\n        }\n        steps = 0;\n      }\n    }\n  }\n  #restoreInitialState() {\n    while (this.stateStack.length || this.inSMaskMode) {\n      this.restore();\n    }\n    this.ctx.restore();\n    if (this.transparentCanvas) {\n      this.ctx = this.compositeCtx;\n      this.ctx.save();\n      this.ctx.setTransform(1, 0, 0, 1, 0, 0);\n      this.ctx.drawImage(this.transparentCanvas, 0, 0);\n      this.ctx.restore();\n      this.transparentCanvas = null;\n    }\n  }\n  endDrawing() {\n    this.#restoreInitialState();\n    this.cachedCanvases.clear();\n    this.cachedPatterns.clear();\n    for (const cache of this._cachedBitmapsMap.values()) {\n      for (const canvas of cache.values()) {\n        if (typeof HTMLCanvasElement !== \"undefined\" && canvas instanceof HTMLCanvasElement) {\n          canvas.width = canvas.height = 0;\n        }\n      }\n      cache.clear();\n    }\n    this._cachedBitmapsMap.clear();\n    this.#drawFilter();\n  }\n  #drawFilter() {\n    if (this.pageColors) {\n      const hcmFilterId = this.filterFactory.addHCMFilter(this.pageColors.foreground, this.pageColors.background);\n      if (hcmFilterId !== \"none\") {\n        const savedFilter = this.ctx.filter;\n        this.ctx.filter = hcmFilterId;\n        this.ctx.drawImage(this.ctx.canvas, 0, 0);\n        this.ctx.filter = savedFilter;\n      }\n    }\n  }\n  _scaleImage(img, inverseTransform) {\n    const width = img.width;\n    const height = img.height;\n    let widthScale = Math.max(Math.hypot(inverseTransform[0], inverseTransform[1]), 1);\n    let heightScale = Math.max(Math.hypot(inverseTransform[2], inverseTransform[3]), 1);\n    let paintWidth = width,\n      paintHeight = height;\n    let tmpCanvasId = \"prescale1\";\n    let tmpCanvas, tmpCtx;\n    while (widthScale > 2 && paintWidth > 1 || heightScale > 2 && paintHeight > 1) {\n      let newWidth = paintWidth,\n        newHeight = paintHeight;\n      if (widthScale > 2 && paintWidth > 1) {\n        newWidth = paintWidth >= 16384 ? Math.floor(paintWidth / 2) - 1 || 1 : Math.ceil(paintWidth / 2);\n        widthScale /= paintWidth / newWidth;\n      }\n      if (heightScale > 2 && paintHeight > 1) {\n        newHeight = paintHeight >= 16384 ? Math.floor(paintHeight / 2) - 1 || 1 : Math.ceil(paintHeight) / 2;\n        heightScale /= paintHeight / newHeight;\n      }\n      tmpCanvas = this.cachedCanvases.getCanvas(tmpCanvasId, newWidth, newHeight);\n      tmpCtx = tmpCanvas.context;\n      tmpCtx.clearRect(0, 0, newWidth, newHeight);\n      tmpCtx.drawImage(img, 0, 0, paintWidth, paintHeight, 0, 0, newWidth, newHeight);\n      img = tmpCanvas.canvas;\n      paintWidth = newWidth;\n      paintHeight = newHeight;\n      tmpCanvasId = tmpCanvasId === \"prescale1\" ? \"prescale2\" : \"prescale1\";\n    }\n    return {\n      img,\n      paintWidth,\n      paintHeight\n    };\n  }\n  _createMaskCanvas(img) {\n    const ctx = this.ctx;\n    const {\n      width,\n      height\n    } = img;\n    const fillColor = this.current.fillColor;\n    const isPatternFill = this.current.patternFill;\n    const currentTransform = (0,display_utils.getCurrentTransform)(ctx);\n    let cache, cacheKey, scaled, maskCanvas;\n    if ((img.bitmap || img.data) && img.count > 1) {\n      const mainKey = img.bitmap || img.data.buffer;\n      cacheKey = JSON.stringify(isPatternFill ? currentTransform : [currentTransform.slice(0, 4), fillColor]);\n      cache = this._cachedBitmapsMap.get(mainKey);\n      if (!cache) {\n        cache = new Map();\n        this._cachedBitmapsMap.set(mainKey, cache);\n      }\n      const cachedImage = cache.get(cacheKey);\n      if (cachedImage && !isPatternFill) {\n        const offsetX = Math.round(Math.min(currentTransform[0], currentTransform[2]) + currentTransform[4]);\n        const offsetY = Math.round(Math.min(currentTransform[1], currentTransform[3]) + currentTransform[5]);\n        return {\n          canvas: cachedImage,\n          offsetX,\n          offsetY\n        };\n      }\n      scaled = cachedImage;\n    }\n    if (!scaled) {\n      maskCanvas = this.cachedCanvases.getCanvas(\"maskCanvas\", width, height);\n      putBinaryImageMask(maskCanvas.context, img);\n    }\n    let maskToCanvas = util.Util.transform(currentTransform, [1 / width, 0, 0, -1 / height, 0, 0]);\n    maskToCanvas = util.Util.transform(maskToCanvas, [1, 0, 0, 1, 0, -height]);\n    const [minX, minY, maxX, maxY] = util.Util.getAxialAlignedBoundingBox([0, 0, width, height], maskToCanvas);\n    const drawnWidth = Math.round(maxX - minX) || 1;\n    const drawnHeight = Math.round(maxY - minY) || 1;\n    const fillCanvas = this.cachedCanvases.getCanvas(\"fillCanvas\", drawnWidth, drawnHeight);\n    const fillCtx = fillCanvas.context;\n    const offsetX = minX;\n    const offsetY = minY;\n    fillCtx.translate(-offsetX, -offsetY);\n    fillCtx.transform(...maskToCanvas);\n    if (!scaled) {\n      scaled = this._scaleImage(maskCanvas.canvas, (0,display_utils.getCurrentTransformInverse)(fillCtx));\n      scaled = scaled.img;\n      if (cache && isPatternFill) {\n        cache.set(cacheKey, scaled);\n      }\n    }\n    fillCtx.imageSmoothingEnabled = getImageSmoothingEnabled((0,display_utils.getCurrentTransform)(fillCtx), img.interpolate);\n    drawImageAtIntegerCoords(fillCtx, scaled, 0, 0, scaled.width, scaled.height, 0, 0, width, height);\n    fillCtx.globalCompositeOperation = \"source-in\";\n    const inverse = util.Util.transform((0,display_utils.getCurrentTransformInverse)(fillCtx), [1, 0, 0, 1, -offsetX, -offsetY]);\n    fillCtx.fillStyle = isPatternFill ? fillColor.getPattern(ctx, this, inverse, PathType.FILL) : fillColor;\n    fillCtx.fillRect(0, 0, width, height);\n    if (cache && !isPatternFill) {\n      this.cachedCanvases.delete(\"fillCanvas\");\n      cache.set(cacheKey, fillCanvas.canvas);\n    }\n    return {\n      canvas: fillCanvas.canvas,\n      offsetX: Math.round(offsetX),\n      offsetY: Math.round(offsetY)\n    };\n  }\n  setLineWidth(width) {\n    if (width !== this.current.lineWidth) {\n      this._cachedScaleForStroking[0] = -1;\n    }\n    this.current.lineWidth = width;\n    this.ctx.lineWidth = width;\n  }\n  setLineCap(style) {\n    this.ctx.lineCap = LINE_CAP_STYLES[style];\n  }\n  setLineJoin(style) {\n    this.ctx.lineJoin = LINE_JOIN_STYLES[style];\n  }\n  setMiterLimit(limit) {\n    this.ctx.miterLimit = limit;\n  }\n  setDash(dashArray, dashPhase) {\n    const ctx = this.ctx;\n    if (ctx.setLineDash !== undefined) {\n      ctx.setLineDash(dashArray);\n      ctx.lineDashOffset = dashPhase;\n    }\n  }\n  setRenderingIntent(intent) {}\n  setFlatness(flatness) {}\n  setGState(states) {\n    for (const [key, value] of states) {\n      switch (key) {\n        case \"LW\":\n          this.setLineWidth(value);\n          break;\n        case \"LC\":\n          this.setLineCap(value);\n          break;\n        case \"LJ\":\n          this.setLineJoin(value);\n          break;\n        case \"ML\":\n          this.setMiterLimit(value);\n          break;\n        case \"D\":\n          this.setDash(value[0], value[1]);\n          break;\n        case \"RI\":\n          this.setRenderingIntent(value);\n          break;\n        case \"FL\":\n          this.setFlatness(value);\n          break;\n        case \"Font\":\n          this.setFont(value[0], value[1]);\n          break;\n        case \"CA\":\n          this.current.strokeAlpha = value;\n          break;\n        case \"ca\":\n          this.current.fillAlpha = value;\n          this.ctx.globalAlpha = value;\n          break;\n        case \"BM\":\n          this.ctx.globalCompositeOperation = value;\n          break;\n        case \"SMask\":\n          this.current.activeSMask = value ? this.tempSMask : null;\n          this.tempSMask = null;\n          this.checkSMaskState();\n          break;\n        case \"TR\":\n          this.ctx.filter = this.current.transferMaps = this.filterFactory.addFilter(value);\n          break;\n      }\n    }\n  }\n  get inSMaskMode() {\n    return !!this.suspendedCtx;\n  }\n  checkSMaskState() {\n    const inSMaskMode = this.inSMaskMode;\n    if (this.current.activeSMask && !inSMaskMode) {\n      this.beginSMaskMode();\n    } else if (!this.current.activeSMask && inSMaskMode) {\n      this.endSMaskMode();\n    }\n  }\n  beginSMaskMode() {\n    if (this.inSMaskMode) {\n      throw new Error(\"beginSMaskMode called while already in smask mode\");\n    }\n    const drawnWidth = this.ctx.canvas.width;\n    const drawnHeight = this.ctx.canvas.height;\n    const cacheId = \"smaskGroupAt\" + this.groupLevel;\n    const scratchCanvas = this.cachedCanvases.getCanvas(cacheId, drawnWidth, drawnHeight);\n    this.suspendedCtx = this.ctx;\n    this.ctx = scratchCanvas.context;\n    const ctx = this.ctx;\n    ctx.setTransform(...(0,display_utils.getCurrentTransform)(this.suspendedCtx));\n    copyCtxState(this.suspendedCtx, ctx);\n    mirrorContextOperations(ctx, this.suspendedCtx);\n    this.setGState([[\"BM\", \"source-over\"], [\"ca\", 1], [\"CA\", 1]]);\n  }\n  endSMaskMode() {\n    if (!this.inSMaskMode) {\n      throw new Error(\"endSMaskMode called while not in smask mode\");\n    }\n    this.ctx._removeMirroring();\n    copyCtxState(this.ctx, this.suspendedCtx);\n    this.ctx = this.suspendedCtx;\n    this.suspendedCtx = null;\n  }\n  compose(dirtyBox) {\n    if (!this.current.activeSMask) {\n      return;\n    }\n    if (!dirtyBox) {\n      dirtyBox = [0, 0, this.ctx.canvas.width, this.ctx.canvas.height];\n    } else {\n      dirtyBox[0] = Math.floor(dirtyBox[0]);\n      dirtyBox[1] = Math.floor(dirtyBox[1]);\n      dirtyBox[2] = Math.ceil(dirtyBox[2]);\n      dirtyBox[3] = Math.ceil(dirtyBox[3]);\n    }\n    const smask = this.current.activeSMask;\n    const suspendedCtx = this.suspendedCtx;\n    composeSMask(suspendedCtx, smask, this.ctx, dirtyBox);\n    this.ctx.save();\n    this.ctx.setTransform(1, 0, 0, 1, 0, 0);\n    this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);\n    this.ctx.restore();\n  }\n  save() {\n    if (this.inSMaskMode) {\n      copyCtxState(this.ctx, this.suspendedCtx);\n      this.suspendedCtx.save();\n    } else {\n      this.ctx.save();\n    }\n    const old = this.current;\n    this.stateStack.push(old);\n    this.current = old.clone();\n  }\n  restore() {\n    if (this.stateStack.length === 0 && this.inSMaskMode) {\n      this.endSMaskMode();\n    }\n    if (this.stateStack.length !== 0) {\n      this.current = this.stateStack.pop();\n      if (this.inSMaskMode) {\n        this.suspendedCtx.restore();\n        copyCtxState(this.suspendedCtx, this.ctx);\n      } else {\n        this.ctx.restore();\n      }\n      this.checkSMaskState();\n      this.pendingClip = null;\n      this._cachedScaleForStroking[0] = -1;\n      this._cachedGetSinglePixelWidth = null;\n    }\n  }\n  transform(a, b, c, d, e, f) {\n    this.ctx.transform(a, b, c, d, e, f);\n    this._cachedScaleForStroking[0] = -1;\n    this._cachedGetSinglePixelWidth = null;\n  }\n  constructPath(ops, args, minMax) {\n    const ctx = this.ctx;\n    const current = this.current;\n    let x = current.x,\n      y = current.y;\n    let startX, startY;\n    const currentTransform = (0,display_utils.getCurrentTransform)(ctx);\n    const isScalingMatrix = currentTransform[0] === 0 && currentTransform[3] === 0 || currentTransform[1] === 0 && currentTransform[2] === 0;\n    const minMaxForBezier = isScalingMatrix ? minMax.slice(0) : null;\n    for (let i = 0, j = 0, ii = ops.length; i < ii; i++) {\n      switch (ops[i] | 0) {\n        case util.OPS.rectangle:\n          x = args[j++];\n          y = args[j++];\n          const width = args[j++];\n          const height = args[j++];\n          const xw = x + width;\n          const yh = y + height;\n          ctx.moveTo(x, y);\n          if (width === 0 || height === 0) {\n            ctx.lineTo(xw, yh);\n          } else {\n            ctx.lineTo(xw, y);\n            ctx.lineTo(xw, yh);\n            ctx.lineTo(x, yh);\n          }\n          if (!isScalingMatrix) {\n            current.updateRectMinMax(currentTransform, [x, y, xw, yh]);\n          }\n          ctx.closePath();\n          break;\n        case util.OPS.moveTo:\n          x = args[j++];\n          y = args[j++];\n          ctx.moveTo(x, y);\n          if (!isScalingMatrix) {\n            current.updatePathMinMax(currentTransform, x, y);\n          }\n          break;\n        case util.OPS.lineTo:\n          x = args[j++];\n          y = args[j++];\n          ctx.lineTo(x, y);\n          if (!isScalingMatrix) {\n            current.updatePathMinMax(currentTransform, x, y);\n          }\n          break;\n        case util.OPS.curveTo:\n          startX = x;\n          startY = y;\n          x = args[j + 4];\n          y = args[j + 5];\n          ctx.bezierCurveTo(args[j], args[j + 1], args[j + 2], args[j + 3], x, y);\n          current.updateCurvePathMinMax(currentTransform, startX, startY, args[j], args[j + 1], args[j + 2], args[j + 3], x, y, minMaxForBezier);\n          j += 6;\n          break;\n        case util.OPS.curveTo2:\n          startX = x;\n          startY = y;\n          ctx.bezierCurveTo(x, y, args[j], args[j + 1], args[j + 2], args[j + 3]);\n          current.updateCurvePathMinMax(currentTransform, startX, startY, x, y, args[j], args[j + 1], args[j + 2], args[j + 3], minMaxForBezier);\n          x = args[j + 2];\n          y = args[j + 3];\n          j += 4;\n          break;\n        case util.OPS.curveTo3:\n          startX = x;\n          startY = y;\n          x = args[j + 2];\n          y = args[j + 3];\n          ctx.bezierCurveTo(args[j], args[j + 1], x, y, x, y);\n          current.updateCurvePathMinMax(currentTransform, startX, startY, args[j], args[j + 1], x, y, x, y, minMaxForBezier);\n          j += 4;\n          break;\n        case util.OPS.closePath:\n          ctx.closePath();\n          break;\n      }\n    }\n    if (isScalingMatrix) {\n      current.updateScalingPathMinMax(currentTransform, minMaxForBezier);\n    }\n    current.setCurrentPoint(x, y);\n  }\n  closePath() {\n    this.ctx.closePath();\n  }\n  stroke(consumePath = true) {\n    const ctx = this.ctx;\n    const strokeColor = this.current.strokeColor;\n    ctx.globalAlpha = this.current.strokeAlpha;\n    if (this.contentVisible) {\n      if (typeof strokeColor === \"object\" && strokeColor?.getPattern) {\n        ctx.save();\n        ctx.strokeStyle = strokeColor.getPattern(ctx, this, (0,display_utils.getCurrentTransformInverse)(ctx), PathType.STROKE);\n        this.rescaleAndStroke(false);\n        ctx.restore();\n      } else {\n        this.rescaleAndStroke(true);\n      }\n    }\n    if (consumePath) {\n      this.consumePath(this.current.getClippedPathBoundingBox());\n    }\n    ctx.globalAlpha = this.current.fillAlpha;\n  }\n  closeStroke() {\n    this.closePath();\n    this.stroke();\n  }\n  fill(consumePath = true) {\n    const ctx = this.ctx;\n    const fillColor = this.current.fillColor;\n    const isPatternFill = this.current.patternFill;\n    let needRestore = false;\n    if (isPatternFill) {\n      ctx.save();\n      ctx.fillStyle = fillColor.getPattern(ctx, this, (0,display_utils.getCurrentTransformInverse)(ctx), PathType.FILL);\n      needRestore = true;\n    }\n    const intersect = this.current.getClippedPathBoundingBox();\n    if (this.contentVisible && intersect !== null) {\n      if (this.pendingEOFill) {\n        ctx.fill(\"evenodd\");\n        this.pendingEOFill = false;\n      } else {\n        ctx.fill();\n      }\n    }\n    if (needRestore) {\n      ctx.restore();\n    }\n    if (consumePath) {\n      this.consumePath(intersect);\n    }\n  }\n  eoFill() {\n    this.pendingEOFill = true;\n    this.fill();\n  }\n  fillStroke() {\n    this.fill(false);\n    this.stroke(false);\n    this.consumePath();\n  }\n  eoFillStroke() {\n    this.pendingEOFill = true;\n    this.fillStroke();\n  }\n  closeFillStroke() {\n    this.closePath();\n    this.fillStroke();\n  }\n  closeEOFillStroke() {\n    this.pendingEOFill = true;\n    this.closePath();\n    this.fillStroke();\n  }\n  endPath() {\n    this.consumePath();\n  }\n  clip() {\n    this.pendingClip = NORMAL_CLIP;\n  }\n  eoClip() {\n    this.pendingClip = EO_CLIP;\n  }\n  beginText() {\n    this.current.textMatrix = util.IDENTITY_MATRIX;\n    this.current.textMatrixScale = 1;\n    this.current.x = this.current.lineX = 0;\n    this.current.y = this.current.lineY = 0;\n  }\n  endText() {\n    const paths = this.pendingTextPaths;\n    const ctx = this.ctx;\n    if (paths === undefined) {\n      ctx.beginPath();\n      return;\n    }\n    ctx.save();\n    ctx.beginPath();\n    for (const path of paths) {\n      ctx.setTransform(...path.transform);\n      ctx.translate(path.x, path.y);\n      path.addToPath(ctx, path.fontSize);\n    }\n    ctx.restore();\n    ctx.clip();\n    ctx.beginPath();\n    delete this.pendingTextPaths;\n  }\n  setCharSpacing(spacing) {\n    this.current.charSpacing = spacing;\n  }\n  setWordSpacing(spacing) {\n    this.current.wordSpacing = spacing;\n  }\n  setHScale(scale) {\n    this.current.textHScale = scale / 100;\n  }\n  setLeading(leading) {\n    this.current.leading = -leading;\n  }\n  setFont(fontRefName, size) {\n    const fontObj = this.commonObjs.get(fontRefName);\n    const current = this.current;\n    if (!fontObj) {\n      throw new Error(`Can't find font for ${fontRefName}`);\n    }\n    current.fontMatrix = fontObj.fontMatrix || util.FONT_IDENTITY_MATRIX;\n    if (current.fontMatrix[0] === 0 || current.fontMatrix[3] === 0) {\n      (0,util.warn)(\"Invalid font matrix for font \" + fontRefName);\n    }\n    if (size < 0) {\n      size = -size;\n      current.fontDirection = -1;\n    } else {\n      current.fontDirection = 1;\n    }\n    this.current.font = fontObj;\n    this.current.fontSize = size;\n    if (fontObj.isType3Font) {\n      return;\n    }\n    const name = fontObj.loadedName || \"sans-serif\";\n    const typeface = fontObj.systemFontInfo?.css || `\"${name}\", ${fontObj.fallbackName}`;\n    let bold = \"normal\";\n    if (fontObj.black) {\n      bold = \"900\";\n    } else if (fontObj.bold) {\n      bold = \"bold\";\n    }\n    const italic = fontObj.italic ? \"italic\" : \"normal\";\n    let browserFontSize = size;\n    if (size < MIN_FONT_SIZE) {\n      browserFontSize = MIN_FONT_SIZE;\n    } else if (size > MAX_FONT_SIZE) {\n      browserFontSize = MAX_FONT_SIZE;\n    }\n    this.current.fontSizeScale = size / browserFontSize;\n    this.ctx.font = `${italic} ${bold} ${browserFontSize}px ${typeface}`;\n  }\n  setTextRenderingMode(mode) {\n    this.current.textRenderingMode = mode;\n  }\n  setTextRise(rise) {\n    this.current.textRise = rise;\n  }\n  moveText(x, y) {\n    this.current.x = this.current.lineX += x;\n    this.current.y = this.current.lineY += y;\n  }\n  setLeadingMoveText(x, y) {\n    this.setLeading(-y);\n    this.moveText(x, y);\n  }\n  setTextMatrix(a, b, c, d, e, f) {\n    this.current.textMatrix = [a, b, c, d, e, f];\n    this.current.textMatrixScale = Math.hypot(a, b);\n    this.current.x = this.current.lineX = 0;\n    this.current.y = this.current.lineY = 0;\n  }\n  nextLine() {\n    this.moveText(0, this.current.leading);\n  }\n  paintChar(character, x, y, patternTransform) {\n    const ctx = this.ctx;\n    const current = this.current;\n    const font = current.font;\n    const textRenderingMode = current.textRenderingMode;\n    const fontSize = current.fontSize / current.fontSizeScale;\n    const fillStrokeMode = textRenderingMode & util.TextRenderingMode.FILL_STROKE_MASK;\n    const isAddToPathSet = !!(textRenderingMode & util.TextRenderingMode.ADD_TO_PATH_FLAG);\n    const patternFill = current.patternFill && !font.missingFile;\n    let addToPath;\n    if (font.disableFontFace || isAddToPathSet || patternFill) {\n      addToPath = font.getPathGenerator(this.commonObjs, character);\n    }\n    if (font.disableFontFace || patternFill) {\n      ctx.save();\n      ctx.translate(x, y);\n      ctx.beginPath();\n      addToPath(ctx, fontSize);\n      if (patternTransform) {\n        ctx.setTransform(...patternTransform);\n      }\n      if (fillStrokeMode === util.TextRenderingMode.FILL || fillStrokeMode === util.TextRenderingMode.FILL_STROKE) {\n        ctx.fill();\n      }\n      if (fillStrokeMode === util.TextRenderingMode.STROKE || fillStrokeMode === util.TextRenderingMode.FILL_STROKE) {\n        ctx.stroke();\n      }\n      ctx.restore();\n    } else {\n      if (fillStrokeMode === util.TextRenderingMode.FILL || fillStrokeMode === util.TextRenderingMode.FILL_STROKE) {\n        ctx.fillText(character, x, y);\n      }\n      if (fillStrokeMode === util.TextRenderingMode.STROKE || fillStrokeMode === util.TextRenderingMode.FILL_STROKE) {\n        ctx.strokeText(character, x, y);\n      }\n    }\n    if (isAddToPathSet) {\n      const paths = this.pendingTextPaths ||= [];\n      paths.push({\n        transform: (0,display_utils.getCurrentTransform)(ctx),\n        x,\n        y,\n        fontSize,\n        addToPath\n      });\n    }\n  }\n  get isFontSubpixelAAEnabled() {\n    const {\n      context: ctx\n    } = this.cachedCanvases.getCanvas(\"isFontSubpixelAAEnabled\", 10, 10);\n    ctx.scale(1.5, 1);\n    ctx.fillText(\"I\", 0, 10);\n    const data = ctx.getImageData(0, 0, 10, 10).data;\n    let enabled = false;\n    for (let i = 3; i < data.length; i += 4) {\n      if (data[i] > 0 && data[i] < 255) {\n        enabled = true;\n        break;\n      }\n    }\n    return (0,util.shadow)(this, \"isFontSubpixelAAEnabled\", enabled);\n  }\n  showText(glyphs) {\n    const current = this.current;\n    const font = current.font;\n    if (font.isType3Font) {\n      return this.showType3Text(glyphs);\n    }\n    const fontSize = current.fontSize;\n    if (fontSize === 0) {\n      return undefined;\n    }\n    const ctx = this.ctx;\n    const fontSizeScale = current.fontSizeScale;\n    const charSpacing = current.charSpacing;\n    const wordSpacing = current.wordSpacing;\n    const fontDirection = current.fontDirection;\n    const textHScale = current.textHScale * fontDirection;\n    const glyphsLength = glyphs.length;\n    const vertical = font.vertical;\n    const spacingDir = vertical ? 1 : -1;\n    const defaultVMetrics = font.defaultVMetrics;\n    const widthAdvanceScale = fontSize * current.fontMatrix[0];\n    const simpleFillText = current.textRenderingMode === util.TextRenderingMode.FILL && !font.disableFontFace && !current.patternFill;\n    ctx.save();\n    ctx.transform(...current.textMatrix);\n    ctx.translate(current.x, current.y + current.textRise);\n    if (fontDirection > 0) {\n      ctx.scale(textHScale, -1);\n    } else {\n      ctx.scale(textHScale, 1);\n    }\n    let patternTransform;\n    if (current.patternFill) {\n      ctx.save();\n      const pattern = current.fillColor.getPattern(ctx, this, (0,display_utils.getCurrentTransformInverse)(ctx), PathType.FILL);\n      patternTransform = (0,display_utils.getCurrentTransform)(ctx);\n      ctx.restore();\n      ctx.fillStyle = pattern;\n    }\n    let lineWidth = current.lineWidth;\n    const scale = current.textMatrixScale;\n    if (scale === 0 || lineWidth === 0) {\n      const fillStrokeMode = current.textRenderingMode & util.TextRenderingMode.FILL_STROKE_MASK;\n      if (fillStrokeMode === util.TextRenderingMode.STROKE || fillStrokeMode === util.TextRenderingMode.FILL_STROKE) {\n        lineWidth = this.getSinglePixelWidth();\n      }\n    } else {\n      lineWidth /= scale;\n    }\n    if (fontSizeScale !== 1.0) {\n      ctx.scale(fontSizeScale, fontSizeScale);\n      lineWidth /= fontSizeScale;\n    }\n    ctx.lineWidth = lineWidth;\n    if (font.isInvalidPDFjsFont) {\n      const chars = [];\n      let width = 0;\n      for (const glyph of glyphs) {\n        chars.push(glyph.unicode);\n        width += glyph.width;\n      }\n      ctx.fillText(chars.join(\"\"), 0, 0);\n      current.x += width * widthAdvanceScale * textHScale;\n      ctx.restore();\n      this.compose();\n      return undefined;\n    }\n    let x = 0,\n      i;\n    for (i = 0; i < glyphsLength; ++i) {\n      const glyph = glyphs[i];\n      if (typeof glyph === \"number\") {\n        x += spacingDir * glyph * fontSize / 1000;\n        continue;\n      }\n      let restoreNeeded = false;\n      const spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing;\n      const character = glyph.fontChar;\n      const accent = glyph.accent;\n      let scaledX, scaledY;\n      let width = glyph.width;\n      if (vertical) {\n        const vmetric = glyph.vmetric || defaultVMetrics;\n        const vx = -(glyph.vmetric ? vmetric[1] : width * 0.5) * widthAdvanceScale;\n        const vy = vmetric[2] * widthAdvanceScale;\n        width = vmetric ? -vmetric[0] : width;\n        scaledX = vx / fontSizeScale;\n        scaledY = (x + vy) / fontSizeScale;\n      } else {\n        scaledX = x / fontSizeScale;\n        scaledY = 0;\n      }\n      if (font.remeasure && width > 0) {\n        const measuredWidth = ctx.measureText(character).width * 1000 / fontSize * fontSizeScale;\n        if (width < measuredWidth && this.isFontSubpixelAAEnabled) {\n          const characterScaleX = width / measuredWidth;\n          restoreNeeded = true;\n          ctx.save();\n          ctx.scale(characterScaleX, 1);\n          scaledX /= characterScaleX;\n        } else if (width !== measuredWidth) {\n          scaledX += (width - measuredWidth) / 2000 * fontSize / fontSizeScale;\n        }\n      }\n      if (this.contentVisible && (glyph.isInFont || font.missingFile)) {\n        if (simpleFillText && !accent) {\n          ctx.fillText(character, scaledX, scaledY);\n        } else {\n          this.paintChar(character, scaledX, scaledY, patternTransform);\n          if (accent) {\n            const scaledAccentX = scaledX + fontSize * accent.offset.x / fontSizeScale;\n            const scaledAccentY = scaledY - fontSize * accent.offset.y / fontSizeScale;\n            this.paintChar(accent.fontChar, scaledAccentX, scaledAccentY, patternTransform);\n          }\n        }\n      }\n      const charWidth = vertical ? width * widthAdvanceScale - spacing * fontDirection : width * widthAdvanceScale + spacing * fontDirection;\n      x += charWidth;\n      if (restoreNeeded) {\n        ctx.restore();\n      }\n    }\n    if (vertical) {\n      current.y -= x;\n    } else {\n      current.x += x * textHScale;\n    }\n    ctx.restore();\n    this.compose();\n    return undefined;\n  }\n  showType3Text(glyphs) {\n    const ctx = this.ctx;\n    const current = this.current;\n    const font = current.font;\n    const fontSize = current.fontSize;\n    const fontDirection = current.fontDirection;\n    const spacingDir = font.vertical ? 1 : -1;\n    const charSpacing = current.charSpacing;\n    const wordSpacing = current.wordSpacing;\n    const textHScale = current.textHScale * fontDirection;\n    const fontMatrix = current.fontMatrix || util.FONT_IDENTITY_MATRIX;\n    const glyphsLength = glyphs.length;\n    const isTextInvisible = current.textRenderingMode === util.TextRenderingMode.INVISIBLE;\n    let i, glyph, width, spacingLength;\n    if (isTextInvisible || fontSize === 0) {\n      return;\n    }\n    this._cachedScaleForStroking[0] = -1;\n    this._cachedGetSinglePixelWidth = null;\n    ctx.save();\n    ctx.transform(...current.textMatrix);\n    ctx.translate(current.x, current.y);\n    ctx.scale(textHScale, fontDirection);\n    for (i = 0; i < glyphsLength; ++i) {\n      glyph = glyphs[i];\n      if (typeof glyph === \"number\") {\n        spacingLength = spacingDir * glyph * fontSize / 1000;\n        this.ctx.translate(spacingLength, 0);\n        current.x += spacingLength * textHScale;\n        continue;\n      }\n      const spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing;\n      const operatorList = font.charProcOperatorList[glyph.operatorListId];\n      if (!operatorList) {\n        (0,util.warn)(`Type3 character \"${glyph.operatorListId}\" is not available.`);\n        continue;\n      }\n      if (this.contentVisible) {\n        this.processingType3 = glyph;\n        this.save();\n        ctx.scale(fontSize, fontSize);\n        ctx.transform(...fontMatrix);\n        this.executeOperatorList(operatorList);\n        this.restore();\n      }\n      const transformed = util.Util.applyTransform([glyph.width, 0], fontMatrix);\n      width = transformed[0] * fontSize + spacing;\n      ctx.translate(width, 0);\n      current.x += width * textHScale;\n    }\n    ctx.restore();\n    this.processingType3 = null;\n  }\n  setCharWidth(xWidth, yWidth) {}\n  setCharWidthAndBounds(xWidth, yWidth, llx, lly, urx, ury) {\n    this.ctx.rect(llx, lly, urx - llx, ury - lly);\n    this.ctx.clip();\n    this.endPath();\n  }\n  getColorN_Pattern(IR) {\n    let pattern;\n    if (IR[0] === \"TilingPattern\") {\n      const color = IR[1];\n      const baseTransform = this.baseTransform || (0,display_utils.getCurrentTransform)(this.ctx);\n      const canvasGraphicsFactory = {\n        createCanvasGraphics: ctx => new CanvasGraphics(ctx, this.commonObjs, this.objs, this.canvasFactory, this.filterFactory, {\n          optionalContentConfig: this.optionalContentConfig,\n          markedContentStack: this.markedContentStack\n        })\n      };\n      pattern = new TilingPattern(IR, color, this.ctx, canvasGraphicsFactory, baseTransform);\n    } else {\n      pattern = this._getPattern(IR[1], IR[2]);\n    }\n    return pattern;\n  }\n  setStrokeColorN() {\n    this.current.strokeColor = this.getColorN_Pattern(arguments);\n  }\n  setFillColorN() {\n    this.current.fillColor = this.getColorN_Pattern(arguments);\n    this.current.patternFill = true;\n  }\n  setStrokeRGBColor(r, g, b) {\n    const color = util.Util.makeHexColor(r, g, b);\n    this.ctx.strokeStyle = color;\n    this.current.strokeColor = color;\n  }\n  setFillRGBColor(r, g, b) {\n    const color = util.Util.makeHexColor(r, g, b);\n    this.ctx.fillStyle = color;\n    this.current.fillColor = color;\n    this.current.patternFill = false;\n  }\n  _getPattern(objId, matrix = null) {\n    let pattern;\n    if (this.cachedPatterns.has(objId)) {\n      pattern = this.cachedPatterns.get(objId);\n    } else {\n      pattern = getShadingPattern(this.getObject(objId));\n      this.cachedPatterns.set(objId, pattern);\n    }\n    if (matrix) {\n      pattern.matrix = matrix;\n    }\n    return pattern;\n  }\n  shadingFill(objId) {\n    if (!this.contentVisible) {\n      return;\n    }\n    const ctx = this.ctx;\n    this.save();\n    const pattern = this._getPattern(objId);\n    ctx.fillStyle = pattern.getPattern(ctx, this, (0,display_utils.getCurrentTransformInverse)(ctx), PathType.SHADING);\n    const inv = (0,display_utils.getCurrentTransformInverse)(ctx);\n    if (inv) {\n      const {\n        width,\n        height\n      } = ctx.canvas;\n      const [x0, y0, x1, y1] = util.Util.getAxialAlignedBoundingBox([0, 0, width, height], inv);\n      this.ctx.fillRect(x0, y0, x1 - x0, y1 - y0);\n    } else {\n      this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10);\n    }\n    this.compose(this.current.getClippedPathBoundingBox());\n    this.restore();\n  }\n  beginInlineImage() {\n    (0,util.unreachable)(\"Should not call beginInlineImage\");\n  }\n  beginImageData() {\n    (0,util.unreachable)(\"Should not call beginImageData\");\n  }\n  paintFormXObjectBegin(matrix, bbox) {\n    if (!this.contentVisible) {\n      return;\n    }\n    this.save();\n    this.baseTransformStack.push(this.baseTransform);\n    if (Array.isArray(matrix) && matrix.length === 6) {\n      this.transform(...matrix);\n    }\n    this.baseTransform = (0,display_utils.getCurrentTransform)(this.ctx);\n    if (bbox) {\n      const width = bbox[2] - bbox[0];\n      const height = bbox[3] - bbox[1];\n      this.ctx.rect(bbox[0], bbox[1], width, height);\n      this.current.updateRectMinMax((0,display_utils.getCurrentTransform)(this.ctx), bbox);\n      this.clip();\n      this.endPath();\n    }\n  }\n  paintFormXObjectEnd() {\n    if (!this.contentVisible) {\n      return;\n    }\n    this.restore();\n    this.baseTransform = this.baseTransformStack.pop();\n  }\n  beginGroup(group) {\n    if (!this.contentVisible) {\n      return;\n    }\n    this.save();\n    if (this.inSMaskMode) {\n      this.endSMaskMode();\n      this.current.activeSMask = null;\n    }\n    const currentCtx = this.ctx;\n    if (!group.isolated) {\n      (0,util.info)(\"TODO: Support non-isolated groups.\");\n    }\n    if (group.knockout) {\n      (0,util.warn)(\"Knockout groups not supported.\");\n    }\n    const currentTransform = (0,display_utils.getCurrentTransform)(currentCtx);\n    if (group.matrix) {\n      currentCtx.transform(...group.matrix);\n    }\n    if (!group.bbox) {\n      throw new Error(\"Bounding box is required.\");\n    }\n    let bounds = util.Util.getAxialAlignedBoundingBox(group.bbox, (0,display_utils.getCurrentTransform)(currentCtx));\n    const canvasBounds = [0, 0, currentCtx.canvas.width, currentCtx.canvas.height];\n    bounds = util.Util.intersect(bounds, canvasBounds) || [0, 0, 0, 0];\n    const offsetX = Math.floor(bounds[0]);\n    const offsetY = Math.floor(bounds[1]);\n    let drawnWidth = Math.max(Math.ceil(bounds[2]) - offsetX, 1);\n    let drawnHeight = Math.max(Math.ceil(bounds[3]) - offsetY, 1);\n    let scaleX = 1,\n      scaleY = 1;\n    if (drawnWidth > MAX_GROUP_SIZE) {\n      scaleX = drawnWidth / MAX_GROUP_SIZE;\n      drawnWidth = MAX_GROUP_SIZE;\n    }\n    if (drawnHeight > MAX_GROUP_SIZE) {\n      scaleY = drawnHeight / MAX_GROUP_SIZE;\n      drawnHeight = MAX_GROUP_SIZE;\n    }\n    this.current.startNewPathAndClipBox([0, 0, drawnWidth, drawnHeight]);\n    let cacheId = \"groupAt\" + this.groupLevel;\n    if (group.smask) {\n      cacheId += \"_smask_\" + this.smaskCounter++ % 2;\n    }\n    const scratchCanvas = this.cachedCanvases.getCanvas(cacheId, drawnWidth, drawnHeight);\n    const groupCtx = scratchCanvas.context;\n    groupCtx.scale(1 / scaleX, 1 / scaleY);\n    groupCtx.translate(-offsetX, -offsetY);\n    groupCtx.transform(...currentTransform);\n    if (group.smask) {\n      this.smaskStack.push({\n        canvas: scratchCanvas.canvas,\n        context: groupCtx,\n        offsetX,\n        offsetY,\n        scaleX,\n        scaleY,\n        subtype: group.smask.subtype,\n        backdrop: group.smask.backdrop,\n        transferMap: group.smask.transferMap || null,\n        startTransformInverse: null\n      });\n    } else {\n      currentCtx.setTransform(1, 0, 0, 1, 0, 0);\n      currentCtx.translate(offsetX, offsetY);\n      currentCtx.scale(scaleX, scaleY);\n      currentCtx.save();\n    }\n    copyCtxState(currentCtx, groupCtx);\n    this.ctx = groupCtx;\n    this.setGState([[\"BM\", \"source-over\"], [\"ca\", 1], [\"CA\", 1]]);\n    this.groupStack.push(currentCtx);\n    this.groupLevel++;\n  }\n  endGroup(group) {\n    if (!this.contentVisible) {\n      return;\n    }\n    this.groupLevel--;\n    const groupCtx = this.ctx;\n    const ctx = this.groupStack.pop();\n    this.ctx = ctx;\n    this.ctx.imageSmoothingEnabled = false;\n    if (group.smask) {\n      this.tempSMask = this.smaskStack.pop();\n      this.restore();\n    } else {\n      this.ctx.restore();\n      const currentMtx = (0,display_utils.getCurrentTransform)(this.ctx);\n      this.restore();\n      this.ctx.save();\n      this.ctx.setTransform(...currentMtx);\n      const dirtyBox = util.Util.getAxialAlignedBoundingBox([0, 0, groupCtx.canvas.width, groupCtx.canvas.height], currentMtx);\n      this.ctx.drawImage(groupCtx.canvas, 0, 0);\n      this.ctx.restore();\n      this.compose(dirtyBox);\n    }\n  }\n  beginAnnotation(id, rect, transform, matrix, hasOwnCanvas) {\n    this.#restoreInitialState();\n    resetCtxToDefault(this.ctx);\n    this.ctx.save();\n    this.save();\n    if (this.baseTransform) {\n      this.ctx.setTransform(...this.baseTransform);\n    }\n    if (Array.isArray(rect) && rect.length === 4) {\n      const width = rect[2] - rect[0];\n      const height = rect[3] - rect[1];\n      if (hasOwnCanvas && this.annotationCanvasMap) {\n        transform = transform.slice();\n        transform[4] -= rect[0];\n        transform[5] -= rect[1];\n        rect = rect.slice();\n        rect[0] = rect[1] = 0;\n        rect[2] = width;\n        rect[3] = height;\n        const [scaleX, scaleY] = util.Util.singularValueDecompose2dScale((0,display_utils.getCurrentTransform)(this.ctx));\n        const {\n          viewportScale\n        } = this;\n        const canvasWidth = Math.ceil(width * this.outputScaleX * viewportScale);\n        const canvasHeight = Math.ceil(height * this.outputScaleY * viewportScale);\n        this.annotationCanvas = this.canvasFactory.create(canvasWidth, canvasHeight);\n        const {\n          canvas,\n          context\n        } = this.annotationCanvas;\n        this.annotationCanvasMap.set(id, canvas);\n        this.annotationCanvas.savedCtx = this.ctx;\n        this.ctx = context;\n        this.ctx.save();\n        this.ctx.setTransform(scaleX, 0, 0, -scaleY, 0, height * scaleY);\n        resetCtxToDefault(this.ctx);\n      } else {\n        resetCtxToDefault(this.ctx);\n        this.ctx.rect(rect[0], rect[1], width, height);\n        this.ctx.clip();\n        this.endPath();\n      }\n    }\n    this.current = new CanvasExtraState(this.ctx.canvas.width, this.ctx.canvas.height);\n    this.transform(...transform);\n    this.transform(...matrix);\n  }\n  endAnnotation() {\n    if (this.annotationCanvas) {\n      this.ctx.restore();\n      this.#drawFilter();\n      this.ctx = this.annotationCanvas.savedCtx;\n      delete this.annotationCanvas.savedCtx;\n      delete this.annotationCanvas;\n    }\n  }\n  paintImageMaskXObject(img) {\n    if (!this.contentVisible) {\n      return;\n    }\n    const count = img.count;\n    img = this.getObject(img.data, img);\n    img.count = count;\n    const ctx = this.ctx;\n    const glyph = this.processingType3;\n    if (glyph) {\n      if (glyph.compiled === undefined) {\n        glyph.compiled = compileType3Glyph(img);\n      }\n      if (glyph.compiled) {\n        glyph.compiled(ctx);\n        return;\n      }\n    }\n    const mask = this._createMaskCanvas(img);\n    const maskCanvas = mask.canvas;\n    ctx.save();\n    ctx.setTransform(1, 0, 0, 1, 0, 0);\n    ctx.drawImage(maskCanvas, mask.offsetX, mask.offsetY);\n    ctx.restore();\n    this.compose();\n  }\n  paintImageMaskXObjectRepeat(img, scaleX, skewX = 0, skewY = 0, scaleY, positions) {\n    if (!this.contentVisible) {\n      return;\n    }\n    img = this.getObject(img.data, img);\n    const ctx = this.ctx;\n    ctx.save();\n    const currentTransform = (0,display_utils.getCurrentTransform)(ctx);\n    ctx.transform(scaleX, skewX, skewY, scaleY, 0, 0);\n    const mask = this._createMaskCanvas(img);\n    ctx.setTransform(1, 0, 0, 1, mask.offsetX - currentTransform[4], mask.offsetY - currentTransform[5]);\n    for (let i = 0, ii = positions.length; i < ii; i += 2) {\n      const trans = util.Util.transform(currentTransform, [scaleX, skewX, skewY, scaleY, positions[i], positions[i + 1]]);\n      const [x, y] = util.Util.applyTransform([0, 0], trans);\n      ctx.drawImage(mask.canvas, x, y);\n    }\n    ctx.restore();\n    this.compose();\n  }\n  paintImageMaskXObjectGroup(images) {\n    if (!this.contentVisible) {\n      return;\n    }\n    const ctx = this.ctx;\n    const fillColor = this.current.fillColor;\n    const isPatternFill = this.current.patternFill;\n    for (const image of images) {\n      const {\n        data,\n        width,\n        height,\n        transform\n      } = image;\n      const maskCanvas = this.cachedCanvases.getCanvas(\"maskCanvas\", width, height);\n      const maskCtx = maskCanvas.context;\n      maskCtx.save();\n      const img = this.getObject(data, image);\n      putBinaryImageMask(maskCtx, img);\n      maskCtx.globalCompositeOperation = \"source-in\";\n      maskCtx.fillStyle = isPatternFill ? fillColor.getPattern(maskCtx, this, (0,display_utils.getCurrentTransformInverse)(ctx), PathType.FILL) : fillColor;\n      maskCtx.fillRect(0, 0, width, height);\n      maskCtx.restore();\n      ctx.save();\n      ctx.transform(...transform);\n      ctx.scale(1, -1);\n      drawImageAtIntegerCoords(ctx, maskCanvas.canvas, 0, 0, width, height, 0, -1, 1, 1);\n      ctx.restore();\n    }\n    this.compose();\n  }\n  paintImageXObject(objId) {\n    if (!this.contentVisible) {\n      return;\n    }\n    const imgData = this.getObject(objId);\n    if (!imgData) {\n      (0,util.warn)(\"Dependent image isn't ready yet\");\n      return;\n    }\n    this.paintInlineImageXObject(imgData);\n  }\n  paintImageXObjectRepeat(objId, scaleX, scaleY, positions) {\n    if (!this.contentVisible) {\n      return;\n    }\n    const imgData = this.getObject(objId);\n    if (!imgData) {\n      (0,util.warn)(\"Dependent image isn't ready yet\");\n      return;\n    }\n    const width = imgData.width;\n    const height = imgData.height;\n    const map = [];\n    for (let i = 0, ii = positions.length; i < ii; i += 2) {\n      map.push({\n        transform: [scaleX, 0, 0, scaleY, positions[i], positions[i + 1]],\n        x: 0,\n        y: 0,\n        w: width,\n        h: height\n      });\n    }\n    this.paintInlineImageXObjectGroup(imgData, map);\n  }\n  applyTransferMapsToCanvas(ctx) {\n    if (this.current.transferMaps !== \"none\") {\n      ctx.filter = this.current.transferMaps;\n      ctx.drawImage(ctx.canvas, 0, 0);\n      ctx.filter = \"none\";\n    }\n    return ctx.canvas;\n  }\n  applyTransferMapsToBitmap(imgData) {\n    if (this.current.transferMaps === \"none\") {\n      return imgData.bitmap;\n    }\n    const {\n      bitmap,\n      width,\n      height\n    } = imgData;\n    const tmpCanvas = this.cachedCanvases.getCanvas(\"inlineImage\", width, height);\n    const tmpCtx = tmpCanvas.context;\n    tmpCtx.filter = this.current.transferMaps;\n    tmpCtx.drawImage(bitmap, 0, 0);\n    tmpCtx.filter = \"none\";\n    return tmpCanvas.canvas;\n  }\n  paintInlineImageXObject(imgData) {\n    if (!this.contentVisible) {\n      return;\n    }\n    const width = imgData.width;\n    const height = imgData.height;\n    const ctx = this.ctx;\n    this.save();\n    if (!util.isNodeJS) {\n      const {\n        filter\n      } = ctx;\n      if (filter !== \"none\" && filter !== \"\") {\n        ctx.filter = \"none\";\n      }\n    }\n    ctx.scale(1 / width, -1 / height);\n    let imgToPaint;\n    if (imgData.bitmap) {\n      imgToPaint = this.applyTransferMapsToBitmap(imgData);\n    } else if (typeof HTMLElement === \"function\" && imgData instanceof HTMLElement || !imgData.data) {\n      imgToPaint = imgData;\n    } else {\n      const tmpCanvas = this.cachedCanvases.getCanvas(\"inlineImage\", width, height);\n      const tmpCtx = tmpCanvas.context;\n      putBinaryImageData(tmpCtx, imgData);\n      imgToPaint = this.applyTransferMapsToCanvas(tmpCtx);\n    }\n    const scaled = this._scaleImage(imgToPaint, (0,display_utils.getCurrentTransformInverse)(ctx));\n    ctx.imageSmoothingEnabled = getImageSmoothingEnabled((0,display_utils.getCurrentTransform)(ctx), imgData.interpolate);\n    drawImageAtIntegerCoords(ctx, scaled.img, 0, 0, scaled.paintWidth, scaled.paintHeight, 0, -height, width, height);\n    this.compose();\n    this.restore();\n  }\n  paintInlineImageXObjectGroup(imgData, map) {\n    if (!this.contentVisible) {\n      return;\n    }\n    const ctx = this.ctx;\n    let imgToPaint;\n    if (imgData.bitmap) {\n      imgToPaint = imgData.bitmap;\n    } else {\n      const w = imgData.width;\n      const h = imgData.height;\n      const tmpCanvas = this.cachedCanvases.getCanvas(\"inlineImage\", w, h);\n      const tmpCtx = tmpCanvas.context;\n      putBinaryImageData(tmpCtx, imgData);\n      imgToPaint = this.applyTransferMapsToCanvas(tmpCtx);\n    }\n    for (const entry of map) {\n      ctx.save();\n      ctx.transform(...entry.transform);\n      ctx.scale(1, -1);\n      drawImageAtIntegerCoords(ctx, imgToPaint, entry.x, entry.y, entry.w, entry.h, 0, -1, 1, 1);\n      ctx.restore();\n    }\n    this.compose();\n  }\n  paintSolidColorImageMask() {\n    if (!this.contentVisible) {\n      return;\n    }\n    this.ctx.fillRect(0, 0, 1, 1);\n    this.compose();\n  }\n  markPoint(tag) {}\n  markPointProps(tag, properties) {}\n  beginMarkedContent(tag) {\n    this.markedContentStack.push({\n      visible: true\n    });\n  }\n  beginMarkedContentProps(tag, properties) {\n    if (tag === \"OC\") {\n      this.markedContentStack.push({\n        visible: this.optionalContentConfig.isVisible(properties)\n      });\n    } else {\n      this.markedContentStack.push({\n        visible: true\n      });\n    }\n    this.contentVisible = this.isContentVisible();\n  }\n  endMarkedContent() {\n    this.markedContentStack.pop();\n    this.contentVisible = this.isContentVisible();\n  }\n  beginCompat() {}\n  endCompat() {}\n  consumePath(clipBox) {\n    const isEmpty = this.current.isEmptyClip();\n    if (this.pendingClip) {\n      this.current.updateClipFromPath();\n    }\n    if (!this.pendingClip) {\n      this.compose(clipBox);\n    }\n    const ctx = this.ctx;\n    if (this.pendingClip) {\n      if (!isEmpty) {\n        if (this.pendingClip === EO_CLIP) {\n          ctx.clip(\"evenodd\");\n        } else {\n          ctx.clip();\n        }\n      }\n      this.pendingClip = null;\n    }\n    this.current.startNewPathAndClipBox(this.current.clipBox);\n    ctx.beginPath();\n  }\n  getSinglePixelWidth() {\n    if (!this._cachedGetSinglePixelWidth) {\n      const m = (0,display_utils.getCurrentTransform)(this.ctx);\n      if (m[1] === 0 && m[2] === 0) {\n        this._cachedGetSinglePixelWidth = 1 / Math.min(Math.abs(m[0]), Math.abs(m[3]));\n      } else {\n        const absDet = Math.abs(m[0] * m[3] - m[2] * m[1]);\n        const normX = Math.hypot(m[0], m[2]);\n        const normY = Math.hypot(m[1], m[3]);\n        this._cachedGetSinglePixelWidth = Math.max(normX, normY) / absDet;\n      }\n    }\n    return this._cachedGetSinglePixelWidth;\n  }\n  getScaleForStroking() {\n    if (this._cachedScaleForStroking[0] === -1) {\n      const {\n        lineWidth\n      } = this.current;\n      const {\n        a,\n        b,\n        c,\n        d\n      } = this.ctx.getTransform();\n      let scaleX, scaleY;\n      if (b === 0 && c === 0) {\n        const normX = Math.abs(a);\n        const normY = Math.abs(d);\n        if (normX === normY) {\n          if (lineWidth === 0) {\n            scaleX = scaleY = 1 / normX;\n          } else {\n            const scaledLineWidth = normX * lineWidth;\n            scaleX = scaleY = scaledLineWidth < 1 ? 1 / scaledLineWidth : 1;\n          }\n        } else if (lineWidth === 0) {\n          scaleX = 1 / normX;\n          scaleY = 1 / normY;\n        } else {\n          const scaledXLineWidth = normX * lineWidth;\n          const scaledYLineWidth = normY * lineWidth;\n          scaleX = scaledXLineWidth < 1 ? 1 / scaledXLineWidth : 1;\n          scaleY = scaledYLineWidth < 1 ? 1 / scaledYLineWidth : 1;\n        }\n      } else {\n        const absDet = Math.abs(a * d - b * c);\n        const normX = Math.hypot(a, b);\n        const normY = Math.hypot(c, d);\n        if (lineWidth === 0) {\n          scaleX = normY / absDet;\n          scaleY = normX / absDet;\n        } else {\n          const baseArea = lineWidth * absDet;\n          scaleX = normY > baseArea ? normY / baseArea : 1;\n          scaleY = normX > baseArea ? normX / baseArea : 1;\n        }\n      }\n      this._cachedScaleForStroking[0] = scaleX;\n      this._cachedScaleForStroking[1] = scaleY;\n    }\n    return this._cachedScaleForStroking;\n  }\n  rescaleAndStroke(saveRestore) {\n    const {\n      ctx\n    } = this;\n    const {\n      lineWidth\n    } = this.current;\n    const [scaleX, scaleY] = this.getScaleForStroking();\n    ctx.lineWidth = lineWidth || 1;\n    if (scaleX === 1 && scaleY === 1) {\n      ctx.stroke();\n      return;\n    }\n    const dashes = ctx.getLineDash();\n    if (saveRestore) {\n      ctx.save();\n    }\n    ctx.scale(scaleX, scaleY);\n    if (dashes.length > 0) {\n      const scale = Math.max(scaleX, scaleY);\n      ctx.setLineDash(dashes.map(x => x / scale));\n      ctx.lineDashOffset /= scale;\n    }\n    ctx.stroke();\n    if (saveRestore) {\n      ctx.restore();\n    }\n  }\n  isContentVisible() {\n    for (let i = this.markedContentStack.length - 1; i >= 0; i--) {\n      if (!this.markedContentStack[i].visible) {\n        return false;\n      }\n    }\n    return true;\n  }\n}\nfor (const op in util.OPS) {\n  if (CanvasGraphics.prototype[op] !== undefined) {\n    CanvasGraphics.prototype[util.OPS[op]] = CanvasGraphics.prototype[op];\n  }\n}\n\n\n/***/ }),\n\n/***/ 419:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   DOMCMapReaderFactory: () => (/* binding */ DOMCMapReaderFactory),\n/* harmony export */   DOMCanvasFactory: () => (/* binding */ DOMCanvasFactory),\n/* harmony export */   DOMFilterFactory: () => (/* binding */ DOMFilterFactory),\n/* harmony export */   DOMSVGFactory: () => (/* binding */ DOMSVGFactory),\n/* harmony export */   DOMStandardFontDataFactory: () => (/* binding */ DOMStandardFontDataFactory),\n/* harmony export */   PDFDateString: () => (/* binding */ PDFDateString),\n/* harmony export */   PageViewport: () => (/* binding */ PageViewport),\n/* harmony export */   PixelsPerInch: () => (/* binding */ PixelsPerInch),\n/* harmony export */   RenderingCancelledException: () => (/* binding */ RenderingCancelledException),\n/* harmony export */   StatTimer: () => (/* binding */ StatTimer),\n/* harmony export */   fetchData: () => (/* binding */ fetchData),\n/* harmony export */   getColorValues: () => (/* binding */ getColorValues),\n/* harmony export */   getCurrentTransform: () => (/* binding */ getCurrentTransform),\n/* harmony export */   getCurrentTransformInverse: () => (/* binding */ getCurrentTransformInverse),\n/* harmony export */   getFilenameFromUrl: () => (/* binding */ getFilenameFromUrl),\n/* harmony export */   getPdfFilenameFromUrl: () => (/* binding */ getPdfFilenameFromUrl),\n/* harmony export */   getRGB: () => (/* binding */ getRGB),\n/* harmony export */   getXfaPageViewport: () => (/* binding */ getXfaPageViewport),\n/* harmony export */   isDataScheme: () => (/* binding */ isDataScheme),\n/* harmony export */   isPdfFile: () => (/* binding */ isPdfFile),\n/* harmony export */   isValidFetchUrl: () => (/* binding */ isValidFetchUrl),\n/* harmony export */   noContextMenu: () => (/* binding */ noContextMenu),\n/* harmony export */   setLayerDimensions: () => (/* binding */ setLayerDimensions)\n/* harmony export */ });\n/* unused harmony export deprecated */\n/* harmony import */ var _base_factory_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(583);\n/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(292);\n\n\nconst SVG_NS = \"http://www.w3.org/2000/svg\";\nclass PixelsPerInch {\n  static CSS = 96.0;\n  static PDF = 72.0;\n  static PDF_TO_CSS_UNITS = this.CSS / this.PDF;\n}\nclass DOMFilterFactory extends _base_factory_js__WEBPACK_IMPORTED_MODULE_0__.BaseFilterFactory {\n  #_cache;\n  #_defs;\n  #docId;\n  #document;\n  #_hcmCache;\n  #id = 0;\n  constructor({\n    docId,\n    ownerDocument = globalThis.document\n  } = {}) {\n    super();\n    this.#docId = docId;\n    this.#document = ownerDocument;\n  }\n  get #cache() {\n    return this.#_cache ||= new Map();\n  }\n  get #hcmCache() {\n    return this.#_hcmCache ||= new Map();\n  }\n  get #defs() {\n    if (!this.#_defs) {\n      const div = this.#document.createElement(\"div\");\n      const {\n        style\n      } = div;\n      style.visibility = \"hidden\";\n      style.contain = \"strict\";\n      style.width = style.height = 0;\n      style.position = \"absolute\";\n      style.top = style.left = 0;\n      style.zIndex = -1;\n      const svg = this.#document.createElementNS(SVG_NS, \"svg\");\n      svg.setAttribute(\"width\", 0);\n      svg.setAttribute(\"height\", 0);\n      this.#_defs = this.#document.createElementNS(SVG_NS, \"defs\");\n      div.append(svg);\n      svg.append(this.#_defs);\n      this.#document.body.append(div);\n    }\n    return this.#_defs;\n  }\n  addFilter(maps) {\n    if (!maps) {\n      return \"none\";\n    }\n    let value = this.#cache.get(maps);\n    if (value) {\n      return value;\n    }\n    let tableR, tableG, tableB, key;\n    if (maps.length === 1) {\n      const mapR = maps[0];\n      const buffer = new Array(256);\n      for (let i = 0; i < 256; i++) {\n        buffer[i] = mapR[i] / 255;\n      }\n      key = tableR = tableG = tableB = buffer.join(\",\");\n    } else {\n      const [mapR, mapG, mapB] = maps;\n      const bufferR = new Array(256);\n      const bufferG = new Array(256);\n      const bufferB = new Array(256);\n      for (let i = 0; i < 256; i++) {\n        bufferR[i] = mapR[i] / 255;\n        bufferG[i] = mapG[i] / 255;\n        bufferB[i] = mapB[i] / 255;\n      }\n      tableR = bufferR.join(\",\");\n      tableG = bufferG.join(\",\");\n      tableB = bufferB.join(\",\");\n      key = `${tableR}${tableG}${tableB}`;\n    }\n    value = this.#cache.get(key);\n    if (value) {\n      this.#cache.set(maps, value);\n      return value;\n    }\n    const id = `g_${this.#docId}_transfer_map_${this.#id++}`;\n    const url = `url(#${id})`;\n    this.#cache.set(maps, url);\n    this.#cache.set(key, url);\n    const filter = this.#createFilter(id);\n    this.#addTransferMapConversion(tableR, tableG, tableB, filter);\n    return url;\n  }\n  addHCMFilter(fgColor, bgColor) {\n    const key = `${fgColor}-${bgColor}`;\n    const filterName = \"base\";\n    let info = this.#hcmCache.get(filterName);\n    if (info?.key === key) {\n      return info.url;\n    }\n    if (info) {\n      info.filter?.remove();\n      info.key = key;\n      info.url = \"none\";\n      info.filter = null;\n    } else {\n      info = {\n        key,\n        url: \"none\",\n        filter: null\n      };\n      this.#hcmCache.set(filterName, info);\n    }\n    if (!fgColor || !bgColor) {\n      return info.url;\n    }\n    const fgRGB = this.#getRGB(fgColor);\n    fgColor = _shared_util_js__WEBPACK_IMPORTED_MODULE_1__.Util.makeHexColor(...fgRGB);\n    const bgRGB = this.#getRGB(bgColor);\n    bgColor = _shared_util_js__WEBPACK_IMPORTED_MODULE_1__.Util.makeHexColor(...bgRGB);\n    this.#defs.style.color = \"\";\n    if (fgColor === \"#000000\" && bgColor === \"#ffffff\" || fgColor === bgColor) {\n      return info.url;\n    }\n    const map = new Array(256);\n    for (let i = 0; i <= 255; i++) {\n      const x = i / 255;\n      map[i] = x <= 0.03928 ? x / 12.92 : ((x + 0.055) / 1.055) ** 2.4;\n    }\n    const table = map.join(\",\");\n    const id = `g_${this.#docId}_hcm_filter`;\n    const filter = info.filter = this.#createFilter(id);\n    this.#addTransferMapConversion(table, table, table, filter);\n    this.#addGrayConversion(filter);\n    const getSteps = (c, n) => {\n      const start = fgRGB[c] / 255;\n      const end = bgRGB[c] / 255;\n      const arr = new Array(n + 1);\n      for (let i = 0; i <= n; i++) {\n        arr[i] = start + i / n * (end - start);\n      }\n      return arr.join(\",\");\n    };\n    this.#addTransferMapConversion(getSteps(0, 5), getSteps(1, 5), getSteps(2, 5), filter);\n    info.url = `url(#${id})`;\n    return info.url;\n  }\n  addHighlightHCMFilter(filterName, fgColor, bgColor, newFgColor, newBgColor) {\n    const key = `${fgColor}-${bgColor}-${newFgColor}-${newBgColor}`;\n    let info = this.#hcmCache.get(filterName);\n    if (info?.key === key) {\n      return info.url;\n    }\n    if (info) {\n      info.filter?.remove();\n      info.key = key;\n      info.url = \"none\";\n      info.filter = null;\n    } else {\n      info = {\n        key,\n        url: \"none\",\n        filter: null\n      };\n      this.#hcmCache.set(filterName, info);\n    }\n    if (!fgColor || !bgColor) {\n      return info.url;\n    }\n    const [fgRGB, bgRGB] = [fgColor, bgColor].map(this.#getRGB.bind(this));\n    let fgGray = Math.round(0.2126 * fgRGB[0] + 0.7152 * fgRGB[1] + 0.0722 * fgRGB[2]);\n    let bgGray = Math.round(0.2126 * bgRGB[0] + 0.7152 * bgRGB[1] + 0.0722 * bgRGB[2]);\n    let [newFgRGB, newBgRGB] = [newFgColor, newBgColor].map(this.#getRGB.bind(this));\n    if (bgGray < fgGray) {\n      [fgGray, bgGray, newFgRGB, newBgRGB] = [bgGray, fgGray, newBgRGB, newFgRGB];\n    }\n    this.#defs.style.color = \"\";\n    const getSteps = (fg, bg, n) => {\n      const arr = new Array(256);\n      const step = (bgGray - fgGray) / n;\n      const newStart = fg / 255;\n      const newStep = (bg - fg) / (255 * n);\n      let prev = 0;\n      for (let i = 0; i <= n; i++) {\n        const k = Math.round(fgGray + i * step);\n        const value = newStart + i * newStep;\n        for (let j = prev; j <= k; j++) {\n          arr[j] = value;\n        }\n        prev = k + 1;\n      }\n      for (let i = prev; i < 256; i++) {\n        arr[i] = arr[prev - 1];\n      }\n      return arr.join(\",\");\n    };\n    const id = `g_${this.#docId}_hcm_${filterName}_filter`;\n    const filter = info.filter = this.#createFilter(id);\n    this.#addGrayConversion(filter);\n    this.#addTransferMapConversion(getSteps(newFgRGB[0], newBgRGB[0], 5), getSteps(newFgRGB[1], newBgRGB[1], 5), getSteps(newFgRGB[2], newBgRGB[2], 5), filter);\n    info.url = `url(#${id})`;\n    return info.url;\n  }\n  destroy(keepHCM = false) {\n    if (keepHCM && this.#hcmCache.size !== 0) {\n      return;\n    }\n    if (this.#_defs) {\n      this.#_defs.parentNode.parentNode.remove();\n      this.#_defs = null;\n    }\n    if (this.#_cache) {\n      this.#_cache.clear();\n      this.#_cache = null;\n    }\n    this.#id = 0;\n  }\n  #addGrayConversion(filter) {\n    const feColorMatrix = this.#document.createElementNS(SVG_NS, \"feColorMatrix\");\n    feColorMatrix.setAttribute(\"type\", \"matrix\");\n    feColorMatrix.setAttribute(\"values\", \"0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0 0 0 1 0\");\n    filter.append(feColorMatrix);\n  }\n  #createFilter(id) {\n    const filter = this.#document.createElementNS(SVG_NS, \"filter\");\n    filter.setAttribute(\"color-interpolation-filters\", \"sRGB\");\n    filter.setAttribute(\"id\", id);\n    this.#defs.append(filter);\n    return filter;\n  }\n  #appendFeFunc(feComponentTransfer, func, table) {\n    const feFunc = this.#document.createElementNS(SVG_NS, func);\n    feFunc.setAttribute(\"type\", \"discrete\");\n    feFunc.setAttribute(\"tableValues\", table);\n    feComponentTransfer.append(feFunc);\n  }\n  #addTransferMapConversion(rTable, gTable, bTable, filter) {\n    const feComponentTransfer = this.#document.createElementNS(SVG_NS, \"feComponentTransfer\");\n    filter.append(feComponentTransfer);\n    this.#appendFeFunc(feComponentTransfer, \"feFuncR\", rTable);\n    this.#appendFeFunc(feComponentTransfer, \"feFuncG\", gTable);\n    this.#appendFeFunc(feComponentTransfer, \"feFuncB\", bTable);\n  }\n  #getRGB(color) {\n    this.#defs.style.color = color;\n    return getRGB(getComputedStyle(this.#defs).getPropertyValue(\"color\"));\n  }\n}\nclass DOMCanvasFactory extends _base_factory_js__WEBPACK_IMPORTED_MODULE_0__.BaseCanvasFactory {\n  constructor({\n    ownerDocument = globalThis.document\n  } = {}) {\n    super();\n    this._document = ownerDocument;\n  }\n  _createCanvas(width, height) {\n    const canvas = this._document.createElement(\"canvas\");\n    canvas.width = width;\n    canvas.height = height;\n    return canvas;\n  }\n}\nasync function fetchData(url, type = \"text\") {\n  if (isValidFetchUrl(url, document.baseURI)) {\n    const response = await fetch(url);\n    if (!response.ok) {\n      throw new Error(response.statusText);\n    }\n    switch (type) {\n      case \"arraybuffer\":\n        return response.arrayBuffer();\n      case \"blob\":\n        return response.blob();\n      case \"json\":\n        return response.json();\n    }\n    return response.text();\n  }\n  return new Promise((resolve, reject) => {\n    const request = new XMLHttpRequest();\n    request.open(\"GET\", url, true);\n    request.responseType = type;\n    request.onreadystatechange = () => {\n      if (request.readyState !== XMLHttpRequest.DONE) {\n        return;\n      }\n      if (request.status === 200 || request.status === 0) {\n        switch (type) {\n          case \"arraybuffer\":\n          case \"blob\":\n          case \"json\":\n            resolve(request.response);\n            return;\n        }\n        resolve(request.responseText);\n        return;\n      }\n      reject(new Error(request.statusText));\n    };\n    request.send(null);\n  });\n}\nclass DOMCMapReaderFactory extends _base_factory_js__WEBPACK_IMPORTED_MODULE_0__.BaseCMapReaderFactory {\n  _fetchData(url, compressionType) {\n    return fetchData(url, this.isCompressed ? \"arraybuffer\" : \"text\").then(data => ({\n      cMapData: data instanceof ArrayBuffer ? new Uint8Array(data) : (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_1__.stringToBytes)(data),\n      compressionType\n    }));\n  }\n}\nclass DOMStandardFontDataFactory extends _base_factory_js__WEBPACK_IMPORTED_MODULE_0__.BaseStandardFontDataFactory {\n  _fetchData(url) {\n    return fetchData(url, \"arraybuffer\").then(data => new Uint8Array(data));\n  }\n}\nclass DOMSVGFactory extends _base_factory_js__WEBPACK_IMPORTED_MODULE_0__.BaseSVGFactory {\n  _createSVG(type) {\n    return document.createElementNS(SVG_NS, type);\n  }\n}\nclass PageViewport {\n  constructor({\n    viewBox,\n    scale,\n    rotation,\n    offsetX = 0,\n    offsetY = 0,\n    dontFlip = false\n  }) {\n    this.viewBox = viewBox;\n    this.scale = scale;\n    this.rotation = rotation;\n    this.offsetX = offsetX;\n    this.offsetY = offsetY;\n    const centerX = (viewBox[2] + viewBox[0]) / 2;\n    const centerY = (viewBox[3] + viewBox[1]) / 2;\n    let rotateA, rotateB, rotateC, rotateD;\n    rotation %= 360;\n    if (rotation < 0) {\n      rotation += 360;\n    }\n    switch (rotation) {\n      case 180:\n        rotateA = -1;\n        rotateB = 0;\n        rotateC = 0;\n        rotateD = 1;\n        break;\n      case 90:\n        rotateA = 0;\n        rotateB = 1;\n        rotateC = 1;\n        rotateD = 0;\n        break;\n      case 270:\n        rotateA = 0;\n        rotateB = -1;\n        rotateC = -1;\n        rotateD = 0;\n        break;\n      case 0:\n        rotateA = 1;\n        rotateB = 0;\n        rotateC = 0;\n        rotateD = -1;\n        break;\n      default:\n        throw new Error(\"PageViewport: Invalid rotation, must be a multiple of 90 degrees.\");\n    }\n    if (dontFlip) {\n      rotateC = -rotateC;\n      rotateD = -rotateD;\n    }\n    let offsetCanvasX, offsetCanvasY;\n    let width, height;\n    if (rotateA === 0) {\n      offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX;\n      offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY;\n      width = (viewBox[3] - viewBox[1]) * scale;\n      height = (viewBox[2] - viewBox[0]) * scale;\n    } else {\n      offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX;\n      offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY;\n      width = (viewBox[2] - viewBox[0]) * scale;\n      height = (viewBox[3] - viewBox[1]) * scale;\n    }\n    this.transform = [rotateA * scale, rotateB * scale, rotateC * scale, rotateD * scale, offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY, offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY];\n    this.width = width;\n    this.height = height;\n  }\n  get rawDims() {\n    const {\n      viewBox\n    } = this;\n    return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_1__.shadow)(this, \"rawDims\", {\n      pageWidth: viewBox[2] - viewBox[0],\n      pageHeight: viewBox[3] - viewBox[1],\n      pageX: viewBox[0],\n      pageY: viewBox[1]\n    });\n  }\n  clone({\n    scale = this.scale,\n    rotation = this.rotation,\n    offsetX = this.offsetX,\n    offsetY = this.offsetY,\n    dontFlip = false\n  } = {}) {\n    return new PageViewport({\n      viewBox: this.viewBox.slice(),\n      scale,\n      rotation,\n      offsetX,\n      offsetY,\n      dontFlip\n    });\n  }\n  convertToViewportPoint(x, y) {\n    return _shared_util_js__WEBPACK_IMPORTED_MODULE_1__.Util.applyTransform([x, y], this.transform);\n  }\n  convertToViewportRectangle(rect) {\n    const topLeft = _shared_util_js__WEBPACK_IMPORTED_MODULE_1__.Util.applyTransform([rect[0], rect[1]], this.transform);\n    const bottomRight = _shared_util_js__WEBPACK_IMPORTED_MODULE_1__.Util.applyTransform([rect[2], rect[3]], this.transform);\n    return [topLeft[0], topLeft[1], bottomRight[0], bottomRight[1]];\n  }\n  convertToPdfPoint(x, y) {\n    return _shared_util_js__WEBPACK_IMPORTED_MODULE_1__.Util.applyInverseTransform([x, y], this.transform);\n  }\n}\nclass RenderingCancelledException extends _shared_util_js__WEBPACK_IMPORTED_MODULE_1__.BaseException {\n  constructor(msg, extraDelay = 0) {\n    super(msg, \"RenderingCancelledException\");\n    this.extraDelay = extraDelay;\n  }\n}\nfunction isDataScheme(url) {\n  const ii = url.length;\n  let i = 0;\n  while (i < ii && url[i].trim() === \"\") {\n    i++;\n  }\n  return url.substring(i, i + 5).toLowerCase() === \"data:\";\n}\nfunction isPdfFile(filename) {\n  return typeof filename === \"string\" && /\\.pdf$/i.test(filename);\n}\nfunction getFilenameFromUrl(url, onlyStripPath = false) {\n  if (!onlyStripPath) {\n    [url] = url.split(/[#?]/, 1);\n  }\n  return url.substring(url.lastIndexOf(\"/\") + 1);\n}\nfunction getPdfFilenameFromUrl(url, defaultFilename = \"document.pdf\") {\n  if (typeof url !== \"string\") {\n    return defaultFilename;\n  }\n  if (isDataScheme(url)) {\n    (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_1__.warn)('getPdfFilenameFromUrl: ignore \"data:\"-URL for performance reasons.');\n    return defaultFilename;\n  }\n  const reURI = /^(?:(?:[^:]+:)?\\/\\/[^/]+)?([^?#]*)(\\?[^#]*)?(#.*)?$/;\n  const reFilename = /[^/?#=]+\\.pdf\\b(?!.*\\.pdf\\b)/i;\n  const splitURI = reURI.exec(url);\n  let suggestedFilename = reFilename.exec(splitURI[1]) || reFilename.exec(splitURI[2]) || reFilename.exec(splitURI[3]);\n  if (suggestedFilename) {\n    suggestedFilename = suggestedFilename[0];\n    if (suggestedFilename.includes(\"%\")) {\n      try {\n        suggestedFilename = reFilename.exec(decodeURIComponent(suggestedFilename))[0];\n      } catch {}\n    }\n  }\n  return suggestedFilename || defaultFilename;\n}\nclass StatTimer {\n  started = Object.create(null);\n  times = [];\n  time(name) {\n    if (name in this.started) {\n      (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_1__.warn)(`Timer is already running for ${name}`);\n    }\n    this.started[name] = Date.now();\n  }\n  timeEnd(name) {\n    if (!(name in this.started)) {\n      (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_1__.warn)(`Timer has not been started for ${name}`);\n    }\n    this.times.push({\n      name,\n      start: this.started[name],\n      end: Date.now()\n    });\n    delete this.started[name];\n  }\n  toString() {\n    const outBuf = [];\n    let longest = 0;\n    for (const {\n      name\n    } of this.times) {\n      longest = Math.max(name.length, longest);\n    }\n    for (const {\n      name,\n      start,\n      end\n    } of this.times) {\n      outBuf.push(`${name.padEnd(longest)} ${end - start}ms\\n`);\n    }\n    return outBuf.join(\"\");\n  }\n}\nfunction isValidFetchUrl(url, baseUrl) {\n  try {\n    const {\n      protocol\n    } = baseUrl ? new URL(url, baseUrl) : new URL(url);\n    return protocol === \"http:\" || protocol === \"https:\";\n  } catch {\n    return false;\n  }\n}\nfunction noContextMenu(e) {\n  e.preventDefault();\n}\nfunction deprecated(details) {\n  console.log(\"Deprecated API usage: \" + details);\n}\nlet pdfDateStringRegex;\nclass PDFDateString {\n  static toDateObject(input) {\n    if (!input || typeof input !== \"string\") {\n      return null;\n    }\n    pdfDateStringRegex ||= new RegExp(\"^D:\" + \"(\\\\d{4})\" + \"(\\\\d{2})?\" + \"(\\\\d{2})?\" + \"(\\\\d{2})?\" + \"(\\\\d{2})?\" + \"(\\\\d{2})?\" + \"([Z|+|-])?\" + \"(\\\\d{2})?\" + \"'?\" + \"(\\\\d{2})?\" + \"'?\");\n    const matches = pdfDateStringRegex.exec(input);\n    if (!matches) {\n      return null;\n    }\n    const year = parseInt(matches[1], 10);\n    let month = parseInt(matches[2], 10);\n    month = month >= 1 && month <= 12 ? month - 1 : 0;\n    let day = parseInt(matches[3], 10);\n    day = day >= 1 && day <= 31 ? day : 1;\n    let hour = parseInt(matches[4], 10);\n    hour = hour >= 0 && hour <= 23 ? hour : 0;\n    let minute = parseInt(matches[5], 10);\n    minute = minute >= 0 && minute <= 59 ? minute : 0;\n    let second = parseInt(matches[6], 10);\n    second = second >= 0 && second <= 59 ? second : 0;\n    const universalTimeRelation = matches[7] || \"Z\";\n    let offsetHour = parseInt(matches[8], 10);\n    offsetHour = offsetHour >= 0 && offsetHour <= 23 ? offsetHour : 0;\n    let offsetMinute = parseInt(matches[9], 10) || 0;\n    offsetMinute = offsetMinute >= 0 && offsetMinute <= 59 ? offsetMinute : 0;\n    if (universalTimeRelation === \"-\") {\n      hour += offsetHour;\n      minute += offsetMinute;\n    } else if (universalTimeRelation === \"+\") {\n      hour -= offsetHour;\n      minute -= offsetMinute;\n    }\n    return new Date(Date.UTC(year, month, day, hour, minute, second));\n  }\n}\nfunction getXfaPageViewport(xfaPage, {\n  scale = 1,\n  rotation = 0\n}) {\n  const {\n    width,\n    height\n  } = xfaPage.attributes.style;\n  const viewBox = [0, 0, parseInt(width), parseInt(height)];\n  return new PageViewport({\n    viewBox,\n    scale,\n    rotation\n  });\n}\nfunction getRGB(color) {\n  if (color.startsWith(\"#\")) {\n    const colorRGB = parseInt(color.slice(1), 16);\n    return [(colorRGB & 0xff0000) >> 16, (colorRGB & 0x00ff00) >> 8, colorRGB & 0x0000ff];\n  }\n  if (color.startsWith(\"rgb(\")) {\n    return color.slice(4, -1).split(\",\").map(x => parseInt(x));\n  }\n  if (color.startsWith(\"rgba(\")) {\n    return color.slice(5, -1).split(\",\").map(x => parseInt(x)).slice(0, 3);\n  }\n  (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_1__.warn)(`Not a valid color format: \"${color}\"`);\n  return [0, 0, 0];\n}\nfunction getColorValues(colors) {\n  const span = document.createElement(\"span\");\n  span.style.visibility = \"hidden\";\n  document.body.append(span);\n  for (const name of colors.keys()) {\n    span.style.color = name;\n    const computedColor = window.getComputedStyle(span).color;\n    colors.set(name, getRGB(computedColor));\n  }\n  span.remove();\n}\nfunction getCurrentTransform(ctx) {\n  const {\n    a,\n    b,\n    c,\n    d,\n    e,\n    f\n  } = ctx.getTransform();\n  return [a, b, c, d, e, f];\n}\nfunction getCurrentTransformInverse(ctx) {\n  const {\n    a,\n    b,\n    c,\n    d,\n    e,\n    f\n  } = ctx.getTransform().invertSelf();\n  return [a, b, c, d, e, f];\n}\nfunction setLayerDimensions(div, viewport, mustFlip = false, mustRotate = true) {\n  if (viewport instanceof PageViewport) {\n    const {\n      pageWidth,\n      pageHeight\n    } = viewport.rawDims;\n    const {\n      style\n    } = div;\n    const useRound = _shared_util_js__WEBPACK_IMPORTED_MODULE_1__.FeatureTest.isCSSRoundSupported;\n    const w = `var(--scale-factor) * ${pageWidth}px`,\n      h = `var(--scale-factor) * ${pageHeight}px`;\n    const widthStr = useRound ? `round(${w}, 1px)` : `calc(${w})`,\n      heightStr = useRound ? `round(${h}, 1px)` : `calc(${h})`;\n    if (!mustFlip || viewport.rotation % 180 === 0) {\n      style.width = widthStr;\n      style.height = heightStr;\n    } else {\n      style.width = heightStr;\n      style.height = widthStr;\n    }\n  }\n  if (mustRotate) {\n    div.setAttribute(\"data-main-rotation\", viewport.rotation);\n  }\n}\n\n\n/***/ }),\n\n/***/ 47:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   DrawLayer: () => (/* binding */ DrawLayer)\n/* harmony export */ });\n/* harmony import */ var _display_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(419);\n/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(292);\n\n\nclass DrawLayer {\n  #parent = null;\n  #id = 0;\n  #mapping = new Map();\n  #toUpdate = new Map();\n  constructor({\n    pageIndex\n  }) {\n    this.pageIndex = pageIndex;\n  }\n  setParent(parent) {\n    if (!this.#parent) {\n      this.#parent = parent;\n      return;\n    }\n    if (this.#parent !== parent) {\n      if (this.#mapping.size > 0) {\n        for (const root of this.#mapping.values()) {\n          root.remove();\n          parent.append(root);\n        }\n      }\n      this.#parent = parent;\n    }\n  }\n  static get _svgFactory() {\n    return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_1__.shadow)(this, \"_svgFactory\", new _display_utils_js__WEBPACK_IMPORTED_MODULE_0__.DOMSVGFactory());\n  }\n  static #setBox(element, {\n    x = 0,\n    y = 0,\n    width = 1,\n    height = 1\n  } = {}) {\n    const {\n      style\n    } = element;\n    style.top = `${100 * y}%`;\n    style.left = `${100 * x}%`;\n    style.width = `${100 * width}%`;\n    style.height = `${100 * height}%`;\n  }\n  #createSVG(box) {\n    const svg = DrawLayer._svgFactory.create(1, 1, true);\n    this.#parent.append(svg);\n    svg.setAttribute(\"aria-hidden\", true);\n    DrawLayer.#setBox(svg, box);\n    return svg;\n  }\n  #createClipPath(defs, pathId) {\n    const clipPath = DrawLayer._svgFactory.createElement(\"clipPath\");\n    defs.append(clipPath);\n    const clipPathId = `clip_${pathId}`;\n    clipPath.setAttribute(\"id\", clipPathId);\n    clipPath.setAttribute(\"clipPathUnits\", \"objectBoundingBox\");\n    const clipPathUse = DrawLayer._svgFactory.createElement(\"use\");\n    clipPath.append(clipPathUse);\n    clipPathUse.setAttribute(\"href\", `#${pathId}`);\n    clipPathUse.classList.add(\"clip\");\n    return clipPathId;\n  }\n  highlight(outlines, color, opacity, isPathUpdatable = false) {\n    const id = this.#id++;\n    const root = this.#createSVG(outlines.box);\n    root.classList.add(\"highlight\");\n    if (outlines.free) {\n      root.classList.add(\"free\");\n    }\n    const defs = DrawLayer._svgFactory.createElement(\"defs\");\n    root.append(defs);\n    const path = DrawLayer._svgFactory.createElement(\"path\");\n    defs.append(path);\n    const pathId = `path_p${this.pageIndex}_${id}`;\n    path.setAttribute(\"id\", pathId);\n    path.setAttribute(\"d\", outlines.toSVGPath());\n    if (isPathUpdatable) {\n      this.#toUpdate.set(id, path);\n    }\n    const clipPathId = this.#createClipPath(defs, pathId);\n    const use = DrawLayer._svgFactory.createElement(\"use\");\n    root.append(use);\n    root.setAttribute(\"fill\", color);\n    root.setAttribute(\"fill-opacity\", opacity);\n    use.setAttribute(\"href\", `#${pathId}`);\n    this.#mapping.set(id, root);\n    return {\n      id,\n      clipPathId: `url(#${clipPathId})`\n    };\n  }\n  highlightOutline(outlines) {\n    const id = this.#id++;\n    const root = this.#createSVG(outlines.box);\n    root.classList.add(\"highlightOutline\");\n    const defs = DrawLayer._svgFactory.createElement(\"defs\");\n    root.append(defs);\n    const path = DrawLayer._svgFactory.createElement(\"path\");\n    defs.append(path);\n    const pathId = `path_p${this.pageIndex}_${id}`;\n    path.setAttribute(\"id\", pathId);\n    path.setAttribute(\"d\", outlines.toSVGPath());\n    path.setAttribute(\"vector-effect\", \"non-scaling-stroke\");\n    let maskId;\n    if (outlines.free) {\n      root.classList.add(\"free\");\n      const mask = DrawLayer._svgFactory.createElement(\"mask\");\n      defs.append(mask);\n      maskId = `mask_p${this.pageIndex}_${id}`;\n      mask.setAttribute(\"id\", maskId);\n      mask.setAttribute(\"maskUnits\", \"objectBoundingBox\");\n      const rect = DrawLayer._svgFactory.createElement(\"rect\");\n      mask.append(rect);\n      rect.setAttribute(\"width\", \"1\");\n      rect.setAttribute(\"height\", \"1\");\n      rect.setAttribute(\"fill\", \"white\");\n      const use = DrawLayer._svgFactory.createElement(\"use\");\n      mask.append(use);\n      use.setAttribute(\"href\", `#${pathId}`);\n      use.setAttribute(\"stroke\", \"none\");\n      use.setAttribute(\"fill\", \"black\");\n      use.setAttribute(\"fill-rule\", \"nonzero\");\n      use.classList.add(\"mask\");\n    }\n    const use1 = DrawLayer._svgFactory.createElement(\"use\");\n    root.append(use1);\n    use1.setAttribute(\"href\", `#${pathId}`);\n    if (maskId) {\n      use1.setAttribute(\"mask\", `url(#${maskId})`);\n    }\n    const use2 = use1.cloneNode();\n    root.append(use2);\n    use1.classList.add(\"mainOutline\");\n    use2.classList.add(\"secondaryOutline\");\n    this.#mapping.set(id, root);\n    return id;\n  }\n  finalizeLine(id, line) {\n    const path = this.#toUpdate.get(id);\n    this.#toUpdate.delete(id);\n    this.updateBox(id, line.box);\n    path.setAttribute(\"d\", line.toSVGPath());\n  }\n  updateLine(id, line) {\n    const root = this.#mapping.get(id);\n    const defs = root.firstChild;\n    const path = defs.firstChild;\n    path.setAttribute(\"d\", line.toSVGPath());\n  }\n  removeFreeHighlight(id) {\n    this.remove(id);\n    this.#toUpdate.delete(id);\n  }\n  updatePath(id, line) {\n    this.#toUpdate.get(id).setAttribute(\"d\", line.toSVGPath());\n  }\n  updateBox(id, box) {\n    DrawLayer.#setBox(this.#mapping.get(id), box);\n  }\n  show(id, visible) {\n    this.#mapping.get(id).classList.toggle(\"hidden\", !visible);\n  }\n  rotate(id, angle) {\n    this.#mapping.get(id).setAttribute(\"data-main-rotation\", angle);\n  }\n  changeColor(id, color) {\n    this.#mapping.get(id).setAttribute(\"fill\", color);\n  }\n  changeOpacity(id, opacity) {\n    this.#mapping.get(id).setAttribute(\"fill-opacity\", opacity);\n  }\n  addClass(id, className) {\n    this.#mapping.get(id).classList.add(className);\n  }\n  removeClass(id, className) {\n    this.#mapping.get(id).classList.remove(className);\n  }\n  remove(id) {\n    if (this.#parent === null) {\n      return;\n    }\n    this.#mapping.get(id).remove();\n    this.#mapping.delete(id);\n  }\n  destroy() {\n    this.#parent = null;\n    for (const root of this.#mapping.values()) {\n      root.remove();\n    }\n    this.#mapping.clear();\n  }\n}\n\n\n/***/ }),\n\n/***/ 731:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, {\n  AnnotationEditorLayer: () => (/* binding */ AnnotationEditorLayer)\n});\n\n// EXTERNAL MODULE: ./src/shared/util.js\nvar util = __webpack_require__(292);\n// EXTERNAL MODULE: ./src/display/editor/editor.js + 1 modules\nvar editor_editor = __webpack_require__(310);\n// EXTERNAL MODULE: ./src/display/editor/tools.js\nvar tools = __webpack_require__(830);\n// EXTERNAL MODULE: ./src/display/annotation_layer.js + 1 modules\nvar annotation_layer = __webpack_require__(976);\n;// CONCATENATED MODULE: ./src/display/editor/freetext.js\n\n\n\n\nconst EOL_PATTERN = /\\r\\n?|\\n/g;\nclass FreeTextEditor extends editor_editor.AnnotationEditor {\n  #boundEditorDivBlur = this.editorDivBlur.bind(this);\n  #boundEditorDivFocus = this.editorDivFocus.bind(this);\n  #boundEditorDivInput = this.editorDivInput.bind(this);\n  #boundEditorDivKeydown = this.editorDivKeydown.bind(this);\n  #boundEditorDivPaste = this.editorDivPaste.bind(this);\n  #color;\n  #content = \"\";\n  #editorDivId = `${this.id}-editor`;\n  #fontSize;\n  #initialData = null;\n  static _freeTextDefaultContent = \"\";\n  static _internalPadding = 0;\n  static _defaultColor = null;\n  static _defaultFontSize = 10;\n  static get _keyboardManager() {\n    const proto = FreeTextEditor.prototype;\n    const arrowChecker = self => self.isEmpty();\n    const small = tools.AnnotationEditorUIManager.TRANSLATE_SMALL;\n    const big = tools.AnnotationEditorUIManager.TRANSLATE_BIG;\n    return (0,util.shadow)(this, \"_keyboardManager\", new tools.KeyboardManager([[[\"ctrl+s\", \"mac+meta+s\", \"ctrl+p\", \"mac+meta+p\"], proto.commitOrRemove, {\n      bubbles: true\n    }], [[\"ctrl+Enter\", \"mac+meta+Enter\", \"Escape\", \"mac+Escape\"], proto.commitOrRemove], [[\"ArrowLeft\", \"mac+ArrowLeft\"], proto._translateEmpty, {\n      args: [-small, 0],\n      checker: arrowChecker\n    }], [[\"ctrl+ArrowLeft\", \"mac+shift+ArrowLeft\"], proto._translateEmpty, {\n      args: [-big, 0],\n      checker: arrowChecker\n    }], [[\"ArrowRight\", \"mac+ArrowRight\"], proto._translateEmpty, {\n      args: [small, 0],\n      checker: arrowChecker\n    }], [[\"ctrl+ArrowRight\", \"mac+shift+ArrowRight\"], proto._translateEmpty, {\n      args: [big, 0],\n      checker: arrowChecker\n    }], [[\"ArrowUp\", \"mac+ArrowUp\"], proto._translateEmpty, {\n      args: [0, -small],\n      checker: arrowChecker\n    }], [[\"ctrl+ArrowUp\", \"mac+shift+ArrowUp\"], proto._translateEmpty, {\n      args: [0, -big],\n      checker: arrowChecker\n    }], [[\"ArrowDown\", \"mac+ArrowDown\"], proto._translateEmpty, {\n      args: [0, small],\n      checker: arrowChecker\n    }], [[\"ctrl+ArrowDown\", \"mac+shift+ArrowDown\"], proto._translateEmpty, {\n      args: [0, big],\n      checker: arrowChecker\n    }]]));\n  }\n  static _type = \"freetext\";\n  static _editorType = util.AnnotationEditorType.FREETEXT;\n  constructor(params) {\n    super({\n      ...params,\n      name: \"freeTextEditor\"\n    });\n    this.#color = params.color || FreeTextEditor._defaultColor || editor_editor.AnnotationEditor._defaultLineColor;\n    this.#fontSize = params.fontSize || FreeTextEditor._defaultFontSize;\n  }\n  static initialize(l10n, uiManager) {\n    editor_editor.AnnotationEditor.initialize(l10n, uiManager, {\n      strings: [\"pdfjs-free-text-default-content\"]\n    });\n    const style = getComputedStyle(document.documentElement);\n    this._internalPadding = parseFloat(style.getPropertyValue(\"--freetext-padding\"));\n  }\n  static updateDefaultParams(type, value) {\n    switch (type) {\n      case util.AnnotationEditorParamsType.FREETEXT_SIZE:\n        FreeTextEditor._defaultFontSize = value;\n        break;\n      case util.AnnotationEditorParamsType.FREETEXT_COLOR:\n        FreeTextEditor._defaultColor = value;\n        break;\n    }\n  }\n  updateParams(type, value) {\n    switch (type) {\n      case util.AnnotationEditorParamsType.FREETEXT_SIZE:\n        this.#updateFontSize(value);\n        break;\n      case util.AnnotationEditorParamsType.FREETEXT_COLOR:\n        this.#updateColor(value);\n        break;\n    }\n  }\n  static get defaultPropertiesToUpdate() {\n    return [[util.AnnotationEditorParamsType.FREETEXT_SIZE, FreeTextEditor._defaultFontSize], [util.AnnotationEditorParamsType.FREETEXT_COLOR, FreeTextEditor._defaultColor || editor_editor.AnnotationEditor._defaultLineColor]];\n  }\n  get propertiesToUpdate() {\n    return [[util.AnnotationEditorParamsType.FREETEXT_SIZE, this.#fontSize], [util.AnnotationEditorParamsType.FREETEXT_COLOR, this.#color]];\n  }\n  #updateFontSize(fontSize) {\n    const setFontsize = size => {\n      this.editorDiv.style.fontSize = `calc(${size}px * var(--scale-factor))`;\n      this.translate(0, -(size - this.#fontSize) * this.parentScale);\n      this.#fontSize = size;\n      this.#setEditorDimensions();\n    };\n    const savedFontsize = this.#fontSize;\n    this.addCommands({\n      cmd: setFontsize.bind(this, fontSize),\n      undo: setFontsize.bind(this, savedFontsize),\n      post: this._uiManager.updateUI.bind(this._uiManager, this),\n      mustExec: true,\n      type: util.AnnotationEditorParamsType.FREETEXT_SIZE,\n      overwriteIfSameType: true,\n      keepUndo: true\n    });\n  }\n  #updateColor(color) {\n    const setColor = col => {\n      this.#color = this.editorDiv.style.color = col;\n    };\n    const savedColor = this.#color;\n    this.addCommands({\n      cmd: setColor.bind(this, color),\n      undo: setColor.bind(this, savedColor),\n      post: this._uiManager.updateUI.bind(this._uiManager, this),\n      mustExec: true,\n      type: util.AnnotationEditorParamsType.FREETEXT_COLOR,\n      overwriteIfSameType: true,\n      keepUndo: true\n    });\n  }\n  _translateEmpty(x, y) {\n    this._uiManager.translateSelectedEditors(x, y, true);\n  }\n  getInitialTranslation() {\n    const scale = this.parentScale;\n    return [-FreeTextEditor._internalPadding * scale, -(FreeTextEditor._internalPadding + this.#fontSize) * scale];\n  }\n  rebuild() {\n    if (!this.parent) {\n      return;\n    }\n    super.rebuild();\n    if (this.div === null) {\n      return;\n    }\n    if (!this.isAttachedToDOM) {\n      this.parent.add(this);\n    }\n  }\n  enableEditMode() {\n    if (this.isInEditMode()) {\n      return;\n    }\n    this.parent.setEditingState(false);\n    this.parent.updateToolbar(util.AnnotationEditorType.FREETEXT);\n    super.enableEditMode();\n    this.overlayDiv.classList.remove(\"enabled\");\n    this.editorDiv.contentEditable = true;\n    this._isDraggable = false;\n    this.div.removeAttribute(\"aria-activedescendant\");\n    this.editorDiv.addEventListener(\"keydown\", this.#boundEditorDivKeydown);\n    this.editorDiv.addEventListener(\"focus\", this.#boundEditorDivFocus);\n    this.editorDiv.addEventListener(\"blur\", this.#boundEditorDivBlur);\n    this.editorDiv.addEventListener(\"input\", this.#boundEditorDivInput);\n    this.editorDiv.addEventListener(\"paste\", this.#boundEditorDivPaste);\n  }\n  disableEditMode() {\n    if (!this.isInEditMode()) {\n      return;\n    }\n    this.parent.setEditingState(true);\n    super.disableEditMode();\n    this.overlayDiv.classList.add(\"enabled\");\n    this.editorDiv.contentEditable = false;\n    this.div.setAttribute(\"aria-activedescendant\", this.#editorDivId);\n    this._isDraggable = true;\n    this.editorDiv.removeEventListener(\"keydown\", this.#boundEditorDivKeydown);\n    this.editorDiv.removeEventListener(\"focus\", this.#boundEditorDivFocus);\n    this.editorDiv.removeEventListener(\"blur\", this.#boundEditorDivBlur);\n    this.editorDiv.removeEventListener(\"input\", this.#boundEditorDivInput);\n    this.editorDiv.removeEventListener(\"paste\", this.#boundEditorDivPaste);\n    this.div.focus({\n      preventScroll: true\n    });\n    this.isEditing = false;\n    this.parent.div.classList.add(\"freetextEditing\");\n  }\n  focusin(event) {\n    if (!this._focusEventsAllowed) {\n      return;\n    }\n    super.focusin(event);\n    if (event.target !== this.editorDiv) {\n      this.editorDiv.focus();\n    }\n  }\n  onceAdded() {\n    if (this.width) {\n      return;\n    }\n    this.enableEditMode();\n    this.editorDiv.focus();\n    if (this._initialOptions?.isCentered) {\n      this.center();\n    }\n    this._initialOptions = null;\n  }\n  isEmpty() {\n    return !this.editorDiv || this.editorDiv.innerText.trim() === \"\";\n  }\n  remove() {\n    this.isEditing = false;\n    if (this.parent) {\n      this.parent.setEditingState(true);\n      this.parent.div.classList.add(\"freetextEditing\");\n    }\n    super.remove();\n  }\n  #extractText() {\n    const buffer = [];\n    this.editorDiv.normalize();\n    for (const child of this.editorDiv.childNodes) {\n      buffer.push(FreeTextEditor.#getNodeContent(child));\n    }\n    return buffer.join(\"\\n\");\n  }\n  #setEditorDimensions() {\n    const [parentWidth, parentHeight] = this.parentDimensions;\n    let rect;\n    if (this.isAttachedToDOM) {\n      rect = this.div.getBoundingClientRect();\n    } else {\n      const {\n        currentLayer,\n        div\n      } = this;\n      const savedDisplay = div.style.display;\n      const savedVisibility = div.classList.contains(\"hidden\");\n      div.classList.remove(\"hidden\");\n      div.style.display = \"hidden\";\n      currentLayer.div.append(this.div);\n      rect = div.getBoundingClientRect();\n      div.remove();\n      div.style.display = savedDisplay;\n      div.classList.toggle(\"hidden\", savedVisibility);\n    }\n    if (this.rotation % 180 === this.parentRotation % 180) {\n      this.width = rect.width / parentWidth;\n      this.height = rect.height / parentHeight;\n    } else {\n      this.width = rect.height / parentWidth;\n      this.height = rect.width / parentHeight;\n    }\n    this.fixAndSetPosition();\n  }\n  commit() {\n    if (!this.isInEditMode()) {\n      return;\n    }\n    super.commit();\n    this.disableEditMode();\n    const savedText = this.#content;\n    const newText = this.#content = this.#extractText().trimEnd();\n    if (savedText === newText) {\n      return;\n    }\n    const setText = text => {\n      this.#content = text;\n      if (!text) {\n        this.remove();\n        return;\n      }\n      this.#setContent();\n      this._uiManager.rebuild(this);\n      this.#setEditorDimensions();\n    };\n    this.addCommands({\n      cmd: () => {\n        setText(newText);\n      },\n      undo: () => {\n        setText(savedText);\n      },\n      mustExec: false\n    });\n    this.#setEditorDimensions();\n  }\n  shouldGetKeyboardEvents() {\n    return this.isInEditMode();\n  }\n  enterInEditMode() {\n    this.enableEditMode();\n    this.editorDiv.focus();\n  }\n  dblclick(event) {\n    this.enterInEditMode();\n  }\n  keydown(event) {\n    if (event.target === this.div && event.key === \"Enter\") {\n      this.enterInEditMode();\n      event.preventDefault();\n    }\n  }\n  editorDivKeydown(event) {\n    FreeTextEditor._keyboardManager.exec(this, event);\n  }\n  editorDivFocus(event) {\n    this.isEditing = true;\n  }\n  editorDivBlur(event) {\n    this.isEditing = false;\n  }\n  editorDivInput(event) {\n    this.parent.div.classList.toggle(\"freetextEditing\", this.isEmpty());\n  }\n  disableEditing() {\n    this.editorDiv.setAttribute(\"role\", \"comment\");\n    this.editorDiv.removeAttribute(\"aria-multiline\");\n  }\n  enableEditing() {\n    this.editorDiv.setAttribute(\"role\", \"textbox\");\n    this.editorDiv.setAttribute(\"aria-multiline\", true);\n  }\n  render() {\n    if (this.div) {\n      return this.div;\n    }\n    let baseX, baseY;\n    if (this.width) {\n      baseX = this.x;\n      baseY = this.y;\n    }\n    super.render();\n    this.editorDiv = document.createElement(\"div\");\n    this.editorDiv.className = \"internal\";\n    this.editorDiv.setAttribute(\"id\", this.#editorDivId);\n    this.editorDiv.setAttribute(\"data-l10n-id\", \"pdfjs-free-text\");\n    this.enableEditing();\n    editor_editor.AnnotationEditor._l10nPromise.get(\"pdfjs-free-text-default-content\").then(msg => this.editorDiv?.setAttribute(\"default-content\", msg));\n    this.editorDiv.contentEditable = true;\n    const {\n      style\n    } = this.editorDiv;\n    style.fontSize = `calc(${this.#fontSize}px * var(--scale-factor))`;\n    style.color = this.#color;\n    this.div.append(this.editorDiv);\n    this.overlayDiv = document.createElement(\"div\");\n    this.overlayDiv.classList.add(\"overlay\", \"enabled\");\n    this.div.append(this.overlayDiv);\n    (0,tools.bindEvents)(this, this.div, [\"dblclick\", \"keydown\"]);\n    if (this.width) {\n      const [parentWidth, parentHeight] = this.parentDimensions;\n      if (this.annotationElementId) {\n        const {\n          position\n        } = this.#initialData;\n        let [tx, ty] = this.getInitialTranslation();\n        [tx, ty] = this.pageTranslationToScreen(tx, ty);\n        const [pageWidth, pageHeight] = this.pageDimensions;\n        const [pageX, pageY] = this.pageTranslation;\n        let posX, posY;\n        switch (this.rotation) {\n          case 0:\n            posX = baseX + (position[0] - pageX) / pageWidth;\n            posY = baseY + this.height - (position[1] - pageY) / pageHeight;\n            break;\n          case 90:\n            posX = baseX + (position[0] - pageX) / pageWidth;\n            posY = baseY - (position[1] - pageY) / pageHeight;\n            [tx, ty] = [ty, -tx];\n            break;\n          case 180:\n            posX = baseX - this.width + (position[0] - pageX) / pageWidth;\n            posY = baseY - (position[1] - pageY) / pageHeight;\n            [tx, ty] = [-tx, -ty];\n            break;\n          case 270:\n            posX = baseX + (position[0] - pageX - this.height * pageHeight) / pageWidth;\n            posY = baseY + (position[1] - pageY - this.width * pageWidth) / pageHeight;\n            [tx, ty] = [-ty, tx];\n            break;\n        }\n        this.setAt(posX * parentWidth, posY * parentHeight, tx, ty);\n      } else {\n        this.setAt(baseX * parentWidth, baseY * parentHeight, this.width * parentWidth, this.height * parentHeight);\n      }\n      this.#setContent();\n      this._isDraggable = true;\n      this.editorDiv.contentEditable = false;\n    } else {\n      this._isDraggable = false;\n      this.editorDiv.contentEditable = true;\n    }\n    return this.div;\n  }\n  static #getNodeContent(node) {\n    return (node.nodeType === Node.TEXT_NODE ? node.nodeValue : node.innerText).replaceAll(EOL_PATTERN, \"\");\n  }\n  editorDivPaste(event) {\n    const clipboardData = event.clipboardData || window.clipboardData;\n    const {\n      types\n    } = clipboardData;\n    if (types.length === 1 && types[0] === \"text/plain\") {\n      return;\n    }\n    event.preventDefault();\n    const paste = FreeTextEditor.#deserializeContent(clipboardData.getData(\"text\") || \"\").replaceAll(EOL_PATTERN, \"\\n\");\n    if (!paste) {\n      return;\n    }\n    const selection = window.getSelection();\n    if (!selection.rangeCount) {\n      return;\n    }\n    this.editorDiv.normalize();\n    selection.deleteFromDocument();\n    const range = selection.getRangeAt(0);\n    if (!paste.includes(\"\\n\")) {\n      range.insertNode(document.createTextNode(paste));\n      this.editorDiv.normalize();\n      selection.collapseToStart();\n      return;\n    }\n    const {\n      startContainer,\n      startOffset\n    } = range;\n    const bufferBefore = [];\n    const bufferAfter = [];\n    if (startContainer.nodeType === Node.TEXT_NODE) {\n      const parent = startContainer.parentElement;\n      bufferAfter.push(startContainer.nodeValue.slice(startOffset).replaceAll(EOL_PATTERN, \"\"));\n      if (parent !== this.editorDiv) {\n        let buffer = bufferBefore;\n        for (const child of this.editorDiv.childNodes) {\n          if (child === parent) {\n            buffer = bufferAfter;\n            continue;\n          }\n          buffer.push(FreeTextEditor.#getNodeContent(child));\n        }\n      }\n      bufferBefore.push(startContainer.nodeValue.slice(0, startOffset).replaceAll(EOL_PATTERN, \"\"));\n    } else if (startContainer === this.editorDiv) {\n      let buffer = bufferBefore;\n      let i = 0;\n      for (const child of this.editorDiv.childNodes) {\n        if (i++ === startOffset) {\n          buffer = bufferAfter;\n        }\n        buffer.push(FreeTextEditor.#getNodeContent(child));\n      }\n    }\n    this.#content = `${bufferBefore.join(\"\\n\")}${paste}${bufferAfter.join(\"\\n\")}`;\n    this.#setContent();\n    const newRange = new Range();\n    let beforeLength = bufferBefore.reduce((acc, line) => acc + line.length, 0);\n    for (const {\n      firstChild\n    } of this.editorDiv.childNodes) {\n      if (firstChild.nodeType === Node.TEXT_NODE) {\n        const length = firstChild.nodeValue.length;\n        if (beforeLength <= length) {\n          newRange.setStart(firstChild, beforeLength);\n          newRange.setEnd(firstChild, beforeLength);\n          break;\n        }\n        beforeLength -= length;\n      }\n    }\n    selection.removeAllRanges();\n    selection.addRange(newRange);\n  }\n  #setContent() {\n    this.editorDiv.replaceChildren();\n    if (!this.#content) {\n      return;\n    }\n    for (const line of this.#content.split(\"\\n\")) {\n      const div = document.createElement(\"div\");\n      div.append(line ? document.createTextNode(line) : document.createElement(\"br\"));\n      this.editorDiv.append(div);\n    }\n  }\n  #serializeContent() {\n    return this.#content.replaceAll(\"\\xa0\", \" \");\n  }\n  static #deserializeContent(content) {\n    return content.replaceAll(\" \", \"\\xa0\");\n  }\n  get contentDiv() {\n    return this.editorDiv;\n  }\n  static deserialize(data, parent, uiManager) {\n    let initialData = null;\n    if (data instanceof annotation_layer.FreeTextAnnotationElement) {\n      const {\n        data: {\n          defaultAppearanceData: {\n            fontSize,\n            fontColor\n          },\n          rect,\n          rotation,\n          id\n        },\n        textContent,\n        textPosition,\n        parent: {\n          page: {\n            pageNumber\n          }\n        }\n      } = data;\n      if (!textContent || textContent.length === 0) {\n        return null;\n      }\n      initialData = data = {\n        annotationType: util.AnnotationEditorType.FREETEXT,\n        color: Array.from(fontColor),\n        fontSize,\n        value: textContent.join(\"\\n\"),\n        position: textPosition,\n        pageIndex: pageNumber - 1,\n        rect: rect.slice(0),\n        rotation,\n        id,\n        deleted: false\n      };\n    }\n    const editor = super.deserialize(data, parent, uiManager);\n    editor.#fontSize = data.fontSize;\n    editor.#color = util.Util.makeHexColor(...data.color);\n    editor.#content = FreeTextEditor.#deserializeContent(data.value);\n    editor.annotationElementId = data.id || null;\n    editor.#initialData = initialData;\n    return editor;\n  }\n  serialize(isForCopying = false) {\n    if (this.isEmpty()) {\n      return null;\n    }\n    if (this.deleted) {\n      return {\n        pageIndex: this.pageIndex,\n        id: this.annotationElementId,\n        deleted: true\n      };\n    }\n    const padding = FreeTextEditor._internalPadding * this.parentScale;\n    const rect = this.getRect(padding, padding);\n    const color = editor_editor.AnnotationEditor._colorManager.convert(this.isAttachedToDOM ? getComputedStyle(this.editorDiv).color : this.#color);\n    const serialized = {\n      annotationType: util.AnnotationEditorType.FREETEXT,\n      color,\n      fontSize: this.#fontSize,\n      value: this.#serializeContent(),\n      pageIndex: this.pageIndex,\n      rect,\n      rotation: this.rotation,\n      structTreeParentId: this._structTreeParentId\n    };\n    if (isForCopying) {\n      return serialized;\n    }\n    if (this.annotationElementId && !this.#hasElementChanged(serialized)) {\n      return null;\n    }\n    serialized.id = this.annotationElementId;\n    return serialized;\n  }\n  #hasElementChanged(serialized) {\n    const {\n      value,\n      fontSize,\n      color,\n      pageIndex\n    } = this.#initialData;\n    return this._hasBeenMoved || serialized.value !== value || serialized.fontSize !== fontSize || serialized.color.some((c, i) => c !== color[i]) || serialized.pageIndex !== pageIndex;\n  }\n  renderAnnotationElement(annotation) {\n    const content = super.renderAnnotationElement(annotation);\n    if (this.deleted) {\n      return content;\n    }\n    const {\n      style\n    } = content;\n    style.fontSize = `calc(${this.#fontSize}px * var(--scale-factor))`;\n    style.color = this.#color;\n    content.replaceChildren();\n    for (const line of this.#content.split(\"\\n\")) {\n      const div = document.createElement(\"div\");\n      div.append(line ? document.createTextNode(line) : document.createElement(\"br\"));\n      content.append(div);\n    }\n    const padding = FreeTextEditor._internalPadding * this.parentScale;\n    annotation.updateEdited({\n      rect: this.getRect(padding, padding)\n    });\n    return content;\n  }\n  resetAnnotationElement(annotation) {\n    super.resetAnnotationElement(annotation);\n    annotation.resetEdited();\n  }\n}\n\n// EXTERNAL MODULE: ./src/display/editor/outliner.js\nvar editor_outliner = __webpack_require__(61);\n// EXTERNAL MODULE: ./src/display/editor/color_picker.js\nvar color_picker = __webpack_require__(259);\n// EXTERNAL MODULE: ./src/display/display_utils.js\nvar display_utils = __webpack_require__(419);\n;// CONCATENATED MODULE: ./src/display/editor/highlight.js\n\n\n\n\n\n\nclass HighlightEditor extends editor_editor.AnnotationEditor {\n  #anchorNode = null;\n  #anchorOffset = 0;\n  #boxes;\n  #clipPathId = null;\n  #colorPicker = null;\n  #focusOutlines = null;\n  #focusNode = null;\n  #focusOffset = 0;\n  #highlightDiv = null;\n  #highlightOutlines = null;\n  #id = null;\n  #isFreeHighlight = false;\n  #boundKeydown = this.#keydown.bind(this);\n  #lastPoint = null;\n  #opacity;\n  #outlineId = null;\n  #text = \"\";\n  #thickness;\n  #methodOfCreation = \"\";\n  static _defaultColor = null;\n  static _defaultOpacity = 1;\n  static _defaultThickness = 12;\n  static _l10nPromise;\n  static _type = \"highlight\";\n  static _editorType = util.AnnotationEditorType.HIGHLIGHT;\n  static _freeHighlightId = -1;\n  static _freeHighlight = null;\n  static _freeHighlightClipId = \"\";\n  static get _keyboardManager() {\n    const proto = HighlightEditor.prototype;\n    return (0,util.shadow)(this, \"_keyboardManager\", new tools.KeyboardManager([[[\"ArrowLeft\", \"mac+ArrowLeft\"], proto._moveCaret, {\n      args: [0]\n    }], [[\"ArrowRight\", \"mac+ArrowRight\"], proto._moveCaret, {\n      args: [1]\n    }], [[\"ArrowUp\", \"mac+ArrowUp\"], proto._moveCaret, {\n      args: [2]\n    }], [[\"ArrowDown\", \"mac+ArrowDown\"], proto._moveCaret, {\n      args: [3]\n    }]]));\n  }\n  constructor(params) {\n    super({\n      ...params,\n      name: \"highlightEditor\"\n    });\n    this.color = params.color || HighlightEditor._defaultColor;\n    this.#thickness = params.thickness || HighlightEditor._defaultThickness;\n    this.#opacity = params.opacity || HighlightEditor._defaultOpacity;\n    this.#boxes = params.boxes || null;\n    this.#methodOfCreation = params.methodOfCreation || \"\";\n    this.#text = params.text || \"\";\n    this._isDraggable = false;\n    if (params.highlightId > -1) {\n      this.#isFreeHighlight = true;\n      this.#createFreeOutlines(params);\n      this.#addToDrawLayer();\n    } else {\n      this.#anchorNode = params.anchorNode;\n      this.#anchorOffset = params.anchorOffset;\n      this.#focusNode = params.focusNode;\n      this.#focusOffset = params.focusOffset;\n      this.#createOutlines();\n      this.#addToDrawLayer();\n      this.rotate(this.rotation);\n    }\n  }\n  get telemetryInitialData() {\n    return {\n      action: \"added\",\n      type: this.#isFreeHighlight ? \"free_highlight\" : \"highlight\",\n      color: this._uiManager.highlightColorNames.get(this.color),\n      thickness: this.#thickness,\n      methodOfCreation: this.#methodOfCreation\n    };\n  }\n  get telemetryFinalData() {\n    return {\n      type: \"highlight\",\n      color: this._uiManager.highlightColorNames.get(this.color)\n    };\n  }\n  static computeTelemetryFinalData(data) {\n    return {\n      numberOfColors: data.get(\"color\").size\n    };\n  }\n  #createOutlines() {\n    const outliner = new editor_outliner.Outliner(this.#boxes, 0.001);\n    this.#highlightOutlines = outliner.getOutlines();\n    ({\n      x: this.x,\n      y: this.y,\n      width: this.width,\n      height: this.height\n    } = this.#highlightOutlines.box);\n    const outlinerForOutline = new editor_outliner.Outliner(this.#boxes, 0.0025, 0.001, this._uiManager.direction === \"ltr\");\n    this.#focusOutlines = outlinerForOutline.getOutlines();\n    const {\n      lastPoint\n    } = this.#focusOutlines.box;\n    this.#lastPoint = [(lastPoint[0] - this.x) / this.width, (lastPoint[1] - this.y) / this.height];\n  }\n  #createFreeOutlines({\n    highlightOutlines,\n    highlightId,\n    clipPathId\n  }) {\n    this.#highlightOutlines = highlightOutlines;\n    const extraThickness = 1.5;\n    this.#focusOutlines = highlightOutlines.getNewOutline(this.#thickness / 2 + extraThickness, 0.0025);\n    if (highlightId >= 0) {\n      this.#id = highlightId;\n      this.#clipPathId = clipPathId;\n      this.parent.drawLayer.finalizeLine(highlightId, highlightOutlines);\n      this.#outlineId = this.parent.drawLayer.highlightOutline(this.#focusOutlines);\n    } else if (this.parent) {\n      const angle = this.parent.viewport.rotation;\n      this.parent.drawLayer.updateLine(this.#id, highlightOutlines);\n      this.parent.drawLayer.updateBox(this.#id, HighlightEditor.#rotateBbox(this.#highlightOutlines.box, (angle - this.rotation + 360) % 360));\n      this.parent.drawLayer.updateLine(this.#outlineId, this.#focusOutlines);\n      this.parent.drawLayer.updateBox(this.#outlineId, HighlightEditor.#rotateBbox(this.#focusOutlines.box, angle));\n    }\n    const {\n      x,\n      y,\n      width,\n      height\n    } = highlightOutlines.box;\n    switch (this.rotation) {\n      case 0:\n        this.x = x;\n        this.y = y;\n        this.width = width;\n        this.height = height;\n        break;\n      case 90:\n        {\n          const [pageWidth, pageHeight] = this.parentDimensions;\n          this.x = y;\n          this.y = 1 - x;\n          this.width = width * pageHeight / pageWidth;\n          this.height = height * pageWidth / pageHeight;\n          break;\n        }\n      case 180:\n        this.x = 1 - x;\n        this.y = 1 - y;\n        this.width = width;\n        this.height = height;\n        break;\n      case 270:\n        {\n          const [pageWidth, pageHeight] = this.parentDimensions;\n          this.x = 1 - y;\n          this.y = x;\n          this.width = width * pageHeight / pageWidth;\n          this.height = height * pageWidth / pageHeight;\n          break;\n        }\n    }\n    const {\n      lastPoint\n    } = this.#focusOutlines.box;\n    this.#lastPoint = [(lastPoint[0] - x) / width, (lastPoint[1] - y) / height];\n  }\n  static initialize(l10n, uiManager) {\n    editor_editor.AnnotationEditor.initialize(l10n, uiManager);\n    HighlightEditor._defaultColor ||= uiManager.highlightColors?.values().next().value || \"#fff066\";\n  }\n  static updateDefaultParams(type, value) {\n    switch (type) {\n      case util.AnnotationEditorParamsType.HIGHLIGHT_DEFAULT_COLOR:\n        HighlightEditor._defaultColor = value;\n        break;\n      case util.AnnotationEditorParamsType.HIGHLIGHT_THICKNESS:\n        HighlightEditor._defaultThickness = value;\n        break;\n    }\n  }\n  translateInPage(x, y) {}\n  get toolbarPosition() {\n    return this.#lastPoint;\n  }\n  updateParams(type, value) {\n    switch (type) {\n      case util.AnnotationEditorParamsType.HIGHLIGHT_COLOR:\n        this.#updateColor(value);\n        break;\n      case util.AnnotationEditorParamsType.HIGHLIGHT_THICKNESS:\n        this.#updateThickness(value);\n        break;\n    }\n  }\n  static get defaultPropertiesToUpdate() {\n    return [[util.AnnotationEditorParamsType.HIGHLIGHT_DEFAULT_COLOR, HighlightEditor._defaultColor], [util.AnnotationEditorParamsType.HIGHLIGHT_THICKNESS, HighlightEditor._defaultThickness]];\n  }\n  get propertiesToUpdate() {\n    return [[util.AnnotationEditorParamsType.HIGHLIGHT_COLOR, this.color || HighlightEditor._defaultColor], [util.AnnotationEditorParamsType.HIGHLIGHT_THICKNESS, this.#thickness || HighlightEditor._defaultThickness], [util.AnnotationEditorParamsType.HIGHLIGHT_FREE, this.#isFreeHighlight]];\n  }\n  #updateColor(color) {\n    const setColor = col => {\n      this.color = col;\n      this.parent?.drawLayer.changeColor(this.#id, col);\n      this.#colorPicker?.updateColor(col);\n    };\n    const savedColor = this.color;\n    this.addCommands({\n      cmd: setColor.bind(this, color),\n      undo: setColor.bind(this, savedColor),\n      post: this._uiManager.updateUI.bind(this._uiManager, this),\n      mustExec: true,\n      type: util.AnnotationEditorParamsType.HIGHLIGHT_COLOR,\n      overwriteIfSameType: true,\n      keepUndo: true\n    });\n    this._reportTelemetry({\n      action: \"color_changed\",\n      color: this._uiManager.highlightColorNames.get(color)\n    }, true);\n  }\n  #updateThickness(thickness) {\n    const savedThickness = this.#thickness;\n    const setThickness = th => {\n      this.#thickness = th;\n      this.#changeThickness(th);\n    };\n    this.addCommands({\n      cmd: setThickness.bind(this, thickness),\n      undo: setThickness.bind(this, savedThickness),\n      post: this._uiManager.updateUI.bind(this._uiManager, this),\n      mustExec: true,\n      type: util.AnnotationEditorParamsType.INK_THICKNESS,\n      overwriteIfSameType: true,\n      keepUndo: true\n    });\n    this._reportTelemetry({\n      action: \"thickness_changed\",\n      thickness\n    }, true);\n  }\n  async addEditToolbar() {\n    const toolbar = await super.addEditToolbar();\n    if (!toolbar) {\n      return null;\n    }\n    if (this._uiManager.highlightColors) {\n      this.#colorPicker = new color_picker.ColorPicker({\n        editor: this\n      });\n      toolbar.addColorPicker(this.#colorPicker);\n    }\n    return toolbar;\n  }\n  disableEditing() {\n    super.disableEditing();\n    this.div.classList.toggle(\"disabled\", true);\n  }\n  enableEditing() {\n    super.enableEditing();\n    this.div.classList.toggle(\"disabled\", false);\n  }\n  fixAndSetPosition() {\n    return super.fixAndSetPosition(this.#getRotation());\n  }\n  getBaseTranslation() {\n    return [0, 0];\n  }\n  getRect(tx, ty) {\n    return super.getRect(tx, ty, this.#getRotation());\n  }\n  onceAdded() {\n    this.parent.addUndoableEditor(this);\n    this.div.focus();\n  }\n  remove() {\n    this.#cleanDrawLayer();\n    this._reportTelemetry({\n      action: \"deleted\"\n    });\n    super.remove();\n  }\n  rebuild() {\n    if (!this.parent) {\n      return;\n    }\n    super.rebuild();\n    if (this.div === null) {\n      return;\n    }\n    this.#addToDrawLayer();\n    if (!this.isAttachedToDOM) {\n      this.parent.add(this);\n    }\n  }\n  setParent(parent) {\n    let mustBeSelected = false;\n    if (this.parent && !parent) {\n      this.#cleanDrawLayer();\n    } else if (parent) {\n      this.#addToDrawLayer(parent);\n      mustBeSelected = !this.parent && this.div?.classList.contains(\"selectedEditor\");\n    }\n    super.setParent(parent);\n    this.show(this._isVisible);\n    if (mustBeSelected) {\n      this.select();\n    }\n  }\n  #changeThickness(thickness) {\n    if (!this.#isFreeHighlight) {\n      return;\n    }\n    this.#createFreeOutlines({\n      highlightOutlines: this.#highlightOutlines.getNewOutline(thickness / 2)\n    });\n    this.fixAndSetPosition();\n    const [parentWidth, parentHeight] = this.parentDimensions;\n    this.setDims(this.width * parentWidth, this.height * parentHeight);\n  }\n  #cleanDrawLayer() {\n    if (this.#id === null || !this.parent) {\n      return;\n    }\n    this.parent.drawLayer.remove(this.#id);\n    this.#id = null;\n    this.parent.drawLayer.remove(this.#outlineId);\n    this.#outlineId = null;\n  }\n  #addToDrawLayer(parent = this.parent) {\n    if (this.#id !== null) {\n      return;\n    }\n    ({\n      id: this.#id,\n      clipPathId: this.#clipPathId\n    } = parent.drawLayer.highlight(this.#highlightOutlines, this.color, this.#opacity));\n    this.#outlineId = parent.drawLayer.highlightOutline(this.#focusOutlines);\n    if (this.#highlightDiv) {\n      this.#highlightDiv.style.clipPath = this.#clipPathId;\n    }\n  }\n  static #rotateBbox({\n    x,\n    y,\n    width,\n    height\n  }, angle) {\n    switch (angle) {\n      case 90:\n        return {\n          x: 1 - y - height,\n          y: x,\n          width: height,\n          height: width\n        };\n      case 180:\n        return {\n          x: 1 - x - width,\n          y: 1 - y - height,\n          width,\n          height\n        };\n      case 270:\n        return {\n          x: y,\n          y: 1 - x - width,\n          width: height,\n          height: width\n        };\n    }\n    return {\n      x,\n      y,\n      width,\n      height\n    };\n  }\n  rotate(angle) {\n    const {\n      drawLayer\n    } = this.parent;\n    let box;\n    if (this.#isFreeHighlight) {\n      angle = (angle - this.rotation + 360) % 360;\n      box = HighlightEditor.#rotateBbox(this.#highlightOutlines.box, angle);\n    } else {\n      box = HighlightEditor.#rotateBbox(this, angle);\n    }\n    drawLayer.rotate(this.#id, angle);\n    drawLayer.rotate(this.#outlineId, angle);\n    drawLayer.updateBox(this.#id, box);\n    drawLayer.updateBox(this.#outlineId, HighlightEditor.#rotateBbox(this.#focusOutlines.box, angle));\n  }\n  render() {\n    if (this.div) {\n      return this.div;\n    }\n    const div = super.render();\n    if (this.#text) {\n      div.setAttribute(\"aria-label\", this.#text);\n      div.setAttribute(\"role\", \"mark\");\n    }\n    if (this.#isFreeHighlight) {\n      div.classList.add(\"free\");\n    } else {\n      this.div.addEventListener(\"keydown\", this.#boundKeydown);\n    }\n    const highlightDiv = this.#highlightDiv = document.createElement(\"div\");\n    div.append(highlightDiv);\n    highlightDiv.setAttribute(\"aria-hidden\", \"true\");\n    highlightDiv.className = \"internal\";\n    highlightDiv.style.clipPath = this.#clipPathId;\n    const [parentWidth, parentHeight] = this.parentDimensions;\n    this.setDims(this.width * parentWidth, this.height * parentHeight);\n    (0,tools.bindEvents)(this, this.#highlightDiv, [\"pointerover\", \"pointerleave\"]);\n    this.enableEditing();\n    return div;\n  }\n  pointerover() {\n    this.parent.drawLayer.addClass(this.#outlineId, \"hovered\");\n  }\n  pointerleave() {\n    this.parent.drawLayer.removeClass(this.#outlineId, \"hovered\");\n  }\n  #keydown(event) {\n    HighlightEditor._keyboardManager.exec(this, event);\n  }\n  _moveCaret(direction) {\n    this.parent.unselect(this);\n    switch (direction) {\n      case 0:\n      case 2:\n        this.#setCaret(true);\n        break;\n      case 1:\n      case 3:\n        this.#setCaret(false);\n        break;\n    }\n  }\n  #setCaret(start) {\n    if (!this.#anchorNode) {\n      return;\n    }\n    const selection = window.getSelection();\n    if (start) {\n      selection.setPosition(this.#anchorNode, this.#anchorOffset);\n    } else {\n      selection.setPosition(this.#focusNode, this.#focusOffset);\n    }\n  }\n  select() {\n    super.select();\n    if (!this.#outlineId) {\n      return;\n    }\n    this.parent?.drawLayer.removeClass(this.#outlineId, \"hovered\");\n    this.parent?.drawLayer.addClass(this.#outlineId, \"selected\");\n  }\n  unselect() {\n    super.unselect();\n    if (!this.#outlineId) {\n      return;\n    }\n    this.parent?.drawLayer.removeClass(this.#outlineId, \"selected\");\n    if (!this.#isFreeHighlight) {\n      this.#setCaret(false);\n    }\n  }\n  get _mustFixPosition() {\n    return !this.#isFreeHighlight;\n  }\n  show(visible = this._isVisible) {\n    super.show(visible);\n    if (this.parent) {\n      this.parent.drawLayer.show(this.#id, visible);\n      this.parent.drawLayer.show(this.#outlineId, visible);\n    }\n  }\n  #getRotation() {\n    return this.#isFreeHighlight ? this.rotation : 0;\n  }\n  #serializeBoxes() {\n    if (this.#isFreeHighlight) {\n      return null;\n    }\n    const [pageWidth, pageHeight] = this.pageDimensions;\n    const boxes = this.#boxes;\n    const quadPoints = new Array(boxes.length * 8);\n    let i = 0;\n    for (const {\n      x,\n      y,\n      width,\n      height\n    } of boxes) {\n      const sx = x * pageWidth;\n      const sy = (1 - y - height) * pageHeight;\n      quadPoints[i] = quadPoints[i + 4] = sx;\n      quadPoints[i + 1] = quadPoints[i + 3] = sy;\n      quadPoints[i + 2] = quadPoints[i + 6] = sx + width * pageWidth;\n      quadPoints[i + 5] = quadPoints[i + 7] = sy + height * pageHeight;\n      i += 8;\n    }\n    return quadPoints;\n  }\n  #serializeOutlines(rect) {\n    return this.#highlightOutlines.serialize(rect, this.#getRotation());\n  }\n  static startHighlighting(parent, isLTR, {\n    target: textLayer,\n    x,\n    y\n  }) {\n    const {\n      x: layerX,\n      y: layerY,\n      width: parentWidth,\n      height: parentHeight\n    } = textLayer.getBoundingClientRect();\n    const pointerMove = e => {\n      this.#highlightMove(parent, e);\n    };\n    const pointerDownOptions = {\n      capture: true,\n      passive: false\n    };\n    const pointerDown = e => {\n      e.preventDefault();\n      e.stopPropagation();\n    };\n    const pointerUpCallback = e => {\n      textLayer.removeEventListener(\"pointermove\", pointerMove);\n      window.removeEventListener(\"blur\", pointerUpCallback);\n      window.removeEventListener(\"pointerup\", pointerUpCallback);\n      window.removeEventListener(\"pointerdown\", pointerDown, pointerDownOptions);\n      window.removeEventListener(\"contextmenu\", display_utils.noContextMenu);\n      this.#endHighlight(parent, e);\n    };\n    window.addEventListener(\"blur\", pointerUpCallback);\n    window.addEventListener(\"pointerup\", pointerUpCallback);\n    window.addEventListener(\"pointerdown\", pointerDown, pointerDownOptions);\n    window.addEventListener(\"contextmenu\", display_utils.noContextMenu);\n    textLayer.addEventListener(\"pointermove\", pointerMove);\n    this._freeHighlight = new editor_outliner.FreeOutliner({\n      x,\n      y\n    }, [layerX, layerY, parentWidth, parentHeight], parent.scale, this._defaultThickness / 2, isLTR, 0.001);\n    ({\n      id: this._freeHighlightId,\n      clipPathId: this._freeHighlightClipId\n    } = parent.drawLayer.highlight(this._freeHighlight, this._defaultColor, this._defaultOpacity, true));\n  }\n  static #highlightMove(parent, event) {\n    if (this._freeHighlight.add(event)) {\n      parent.drawLayer.updatePath(this._freeHighlightId, this._freeHighlight);\n    }\n  }\n  static #endHighlight(parent, event) {\n    if (!this._freeHighlight.isEmpty()) {\n      parent.createAndAddNewEditor(event, false, {\n        highlightId: this._freeHighlightId,\n        highlightOutlines: this._freeHighlight.getOutlines(),\n        clipPathId: this._freeHighlightClipId,\n        methodOfCreation: \"main_toolbar\"\n      });\n    } else {\n      parent.drawLayer.removeFreeHighlight(this._freeHighlightId);\n    }\n    this._freeHighlightId = -1;\n    this._freeHighlight = null;\n    this._freeHighlightClipId = \"\";\n  }\n  static deserialize(data, parent, uiManager) {\n    const editor = super.deserialize(data, parent, uiManager);\n    const {\n      rect: [blX, blY, trX, trY],\n      color,\n      quadPoints\n    } = data;\n    editor.color = util.Util.makeHexColor(...color);\n    editor.#opacity = data.opacity;\n    const [pageWidth, pageHeight] = editor.pageDimensions;\n    editor.width = (trX - blX) / pageWidth;\n    editor.height = (trY - blY) / pageHeight;\n    const boxes = editor.#boxes = [];\n    for (let i = 0; i < quadPoints.length; i += 8) {\n      boxes.push({\n        x: (quadPoints[4] - trX) / pageWidth,\n        y: (trY - (1 - quadPoints[i + 5])) / pageHeight,\n        width: (quadPoints[i + 2] - quadPoints[i]) / pageWidth,\n        height: (quadPoints[i + 5] - quadPoints[i + 1]) / pageHeight\n      });\n    }\n    editor.#createOutlines();\n    return editor;\n  }\n  serialize(isForCopying = false) {\n    if (this.isEmpty() || isForCopying) {\n      return null;\n    }\n    const rect = this.getRect(0, 0);\n    const color = editor_editor.AnnotationEditor._colorManager.convert(this.color);\n    return {\n      annotationType: util.AnnotationEditorType.HIGHLIGHT,\n      color,\n      opacity: this.#opacity,\n      thickness: this.#thickness,\n      quadPoints: this.#serializeBoxes(),\n      outlines: this.#serializeOutlines(rect),\n      pageIndex: this.pageIndex,\n      rect,\n      rotation: this.#getRotation(),\n      structTreeParentId: this._structTreeParentId\n    };\n  }\n  static canCreateNewEmptyEditor() {\n    return false;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/display/editor/ink.js\n\n\n\n\n\nclass InkEditor extends editor_editor.AnnotationEditor {\n  #baseHeight = 0;\n  #baseWidth = 0;\n  #boundCanvasPointermove = this.canvasPointermove.bind(this);\n  #boundCanvasPointerleave = this.canvasPointerleave.bind(this);\n  #boundCanvasPointerup = this.canvasPointerup.bind(this);\n  #boundCanvasPointerdown = this.canvasPointerdown.bind(this);\n  #canvasContextMenuTimeoutId = null;\n  #currentPath2D = new Path2D();\n  #disableEditing = false;\n  #hasSomethingToDraw = false;\n  #isCanvasInitialized = false;\n  #observer = null;\n  #realWidth = 0;\n  #realHeight = 0;\n  #requestFrameCallback = null;\n  static _defaultColor = null;\n  static _defaultOpacity = 1;\n  static _defaultThickness = 1;\n  static _type = \"ink\";\n  static _editorType = util.AnnotationEditorType.INK;\n  constructor(params) {\n    super({\n      ...params,\n      name: \"inkEditor\"\n    });\n    this.color = params.color || null;\n    this.thickness = params.thickness || null;\n    this.opacity = params.opacity || null;\n    this.paths = [];\n    this.bezierPath2D = [];\n    this.allRawPaths = [];\n    this.currentPath = [];\n    this.scaleFactor = 1;\n    this.translationX = this.translationY = 0;\n    this.x = 0;\n    this.y = 0;\n    this._willKeepAspectRatio = true;\n  }\n  static initialize(l10n, uiManager) {\n    editor_editor.AnnotationEditor.initialize(l10n, uiManager);\n  }\n  static updateDefaultParams(type, value) {\n    switch (type) {\n      case util.AnnotationEditorParamsType.INK_THICKNESS:\n        InkEditor._defaultThickness = value;\n        break;\n      case util.AnnotationEditorParamsType.INK_COLOR:\n        InkEditor._defaultColor = value;\n        break;\n      case util.AnnotationEditorParamsType.INK_OPACITY:\n        InkEditor._defaultOpacity = value / 100;\n        break;\n    }\n  }\n  updateParams(type, value) {\n    switch (type) {\n      case util.AnnotationEditorParamsType.INK_THICKNESS:\n        this.#updateThickness(value);\n        break;\n      case util.AnnotationEditorParamsType.INK_COLOR:\n        this.#updateColor(value);\n        break;\n      case util.AnnotationEditorParamsType.INK_OPACITY:\n        this.#updateOpacity(value);\n        break;\n    }\n  }\n  static get defaultPropertiesToUpdate() {\n    return [[util.AnnotationEditorParamsType.INK_THICKNESS, InkEditor._defaultThickness], [util.AnnotationEditorParamsType.INK_COLOR, InkEditor._defaultColor || editor_editor.AnnotationEditor._defaultLineColor], [util.AnnotationEditorParamsType.INK_OPACITY, Math.round(InkEditor._defaultOpacity * 100)]];\n  }\n  get propertiesToUpdate() {\n    return [[util.AnnotationEditorParamsType.INK_THICKNESS, this.thickness || InkEditor._defaultThickness], [util.AnnotationEditorParamsType.INK_COLOR, this.color || InkEditor._defaultColor || editor_editor.AnnotationEditor._defaultLineColor], [util.AnnotationEditorParamsType.INK_OPACITY, Math.round(100 * (this.opacity ?? InkEditor._defaultOpacity))]];\n  }\n  #updateThickness(thickness) {\n    const setThickness = th => {\n      this.thickness = th;\n      this.#fitToContent();\n    };\n    const savedThickness = this.thickness;\n    this.addCommands({\n      cmd: setThickness.bind(this, thickness),\n      undo: setThickness.bind(this, savedThickness),\n      post: this._uiManager.updateUI.bind(this._uiManager, this),\n      mustExec: true,\n      type: util.AnnotationEditorParamsType.INK_THICKNESS,\n      overwriteIfSameType: true,\n      keepUndo: true\n    });\n  }\n  #updateColor(color) {\n    const setColor = col => {\n      this.color = col;\n      this.#redraw();\n    };\n    const savedColor = this.color;\n    this.addCommands({\n      cmd: setColor.bind(this, color),\n      undo: setColor.bind(this, savedColor),\n      post: this._uiManager.updateUI.bind(this._uiManager, this),\n      mustExec: true,\n      type: util.AnnotationEditorParamsType.INK_COLOR,\n      overwriteIfSameType: true,\n      keepUndo: true\n    });\n  }\n  #updateOpacity(opacity) {\n    const setOpacity = op => {\n      this.opacity = op;\n      this.#redraw();\n    };\n    opacity /= 100;\n    const savedOpacity = this.opacity;\n    this.addCommands({\n      cmd: setOpacity.bind(this, opacity),\n      undo: setOpacity.bind(this, savedOpacity),\n      post: this._uiManager.updateUI.bind(this._uiManager, this),\n      mustExec: true,\n      type: util.AnnotationEditorParamsType.INK_OPACITY,\n      overwriteIfSameType: true,\n      keepUndo: true\n    });\n  }\n  rebuild() {\n    if (!this.parent) {\n      return;\n    }\n    super.rebuild();\n    if (this.div === null) {\n      return;\n    }\n    if (!this.canvas) {\n      this.#createCanvas();\n      this.#createObserver();\n    }\n    if (!this.isAttachedToDOM) {\n      this.parent.add(this);\n      this.#setCanvasDims();\n    }\n    this.#fitToContent();\n  }\n  remove() {\n    if (this.canvas === null) {\n      return;\n    }\n    if (!this.isEmpty()) {\n      this.commit();\n    }\n    this.canvas.width = this.canvas.height = 0;\n    this.canvas.remove();\n    this.canvas = null;\n    if (this.#canvasContextMenuTimeoutId) {\n      clearTimeout(this.#canvasContextMenuTimeoutId);\n      this.#canvasContextMenuTimeoutId = null;\n    }\n    this.#observer.disconnect();\n    this.#observer = null;\n    super.remove();\n  }\n  setParent(parent) {\n    if (!this.parent && parent) {\n      this._uiManager.removeShouldRescale(this);\n    } else if (this.parent && parent === null) {\n      this._uiManager.addShouldRescale(this);\n    }\n    super.setParent(parent);\n  }\n  onScaleChanging() {\n    const [parentWidth, parentHeight] = this.parentDimensions;\n    const width = this.width * parentWidth;\n    const height = this.height * parentHeight;\n    this.setDimensions(width, height);\n  }\n  enableEditMode() {\n    if (this.#disableEditing || this.canvas === null) {\n      return;\n    }\n    super.enableEditMode();\n    this._isDraggable = false;\n    this.canvas.addEventListener(\"pointerdown\", this.#boundCanvasPointerdown);\n  }\n  disableEditMode() {\n    if (!this.isInEditMode() || this.canvas === null) {\n      return;\n    }\n    super.disableEditMode();\n    this._isDraggable = !this.isEmpty();\n    this.div.classList.remove(\"editing\");\n    this.canvas.removeEventListener(\"pointerdown\", this.#boundCanvasPointerdown);\n  }\n  onceAdded() {\n    this._isDraggable = !this.isEmpty();\n  }\n  isEmpty() {\n    return this.paths.length === 0 || this.paths.length === 1 && this.paths[0].length === 0;\n  }\n  #getInitialBBox() {\n    const {\n      parentRotation,\n      parentDimensions: [width, height]\n    } = this;\n    switch (parentRotation) {\n      case 90:\n        return [0, height, height, width];\n      case 180:\n        return [width, height, width, height];\n      case 270:\n        return [width, 0, height, width];\n      default:\n        return [0, 0, width, height];\n    }\n  }\n  #setStroke() {\n    const {\n      ctx,\n      color,\n      opacity,\n      thickness,\n      parentScale,\n      scaleFactor\n    } = this;\n    ctx.lineWidth = thickness * parentScale / scaleFactor;\n    ctx.lineCap = \"round\";\n    ctx.lineJoin = \"round\";\n    ctx.miterLimit = 10;\n    ctx.strokeStyle = `${color}${(0,tools.opacityToHex)(opacity)}`;\n  }\n  #startDrawing(x, y) {\n    this.canvas.addEventListener(\"contextmenu\", display_utils.noContextMenu);\n    this.canvas.addEventListener(\"pointerleave\", this.#boundCanvasPointerleave);\n    this.canvas.addEventListener(\"pointermove\", this.#boundCanvasPointermove);\n    this.canvas.addEventListener(\"pointerup\", this.#boundCanvasPointerup);\n    this.canvas.removeEventListener(\"pointerdown\", this.#boundCanvasPointerdown);\n    this.isEditing = true;\n    if (!this.#isCanvasInitialized) {\n      this.#isCanvasInitialized = true;\n      this.#setCanvasDims();\n      this.thickness ||= InkEditor._defaultThickness;\n      this.color ||= InkEditor._defaultColor || editor_editor.AnnotationEditor._defaultLineColor;\n      this.opacity ??= InkEditor._defaultOpacity;\n    }\n    this.currentPath.push([x, y]);\n    this.#hasSomethingToDraw = false;\n    this.#setStroke();\n    this.#requestFrameCallback = () => {\n      this.#drawPoints();\n      if (this.#requestFrameCallback) {\n        window.requestAnimationFrame(this.#requestFrameCallback);\n      }\n    };\n    window.requestAnimationFrame(this.#requestFrameCallback);\n  }\n  #draw(x, y) {\n    const [lastX, lastY] = this.currentPath.at(-1);\n    if (this.currentPath.length > 1 && x === lastX && y === lastY) {\n      return;\n    }\n    const currentPath = this.currentPath;\n    let path2D = this.#currentPath2D;\n    currentPath.push([x, y]);\n    this.#hasSomethingToDraw = true;\n    if (currentPath.length <= 2) {\n      path2D.moveTo(...currentPath[0]);\n      path2D.lineTo(x, y);\n      return;\n    }\n    if (currentPath.length === 3) {\n      this.#currentPath2D = path2D = new Path2D();\n      path2D.moveTo(...currentPath[0]);\n    }\n    this.#makeBezierCurve(path2D, ...currentPath.at(-3), ...currentPath.at(-2), x, y);\n  }\n  #endPath() {\n    if (this.currentPath.length === 0) {\n      return;\n    }\n    const lastPoint = this.currentPath.at(-1);\n    this.#currentPath2D.lineTo(...lastPoint);\n  }\n  #stopDrawing(x, y) {\n    this.#requestFrameCallback = null;\n    x = Math.min(Math.max(x, 0), this.canvas.width);\n    y = Math.min(Math.max(y, 0), this.canvas.height);\n    this.#draw(x, y);\n    this.#endPath();\n    let bezier;\n    if (this.currentPath.length !== 1) {\n      bezier = this.#generateBezierPoints();\n    } else {\n      const xy = [x, y];\n      bezier = [[xy, xy.slice(), xy.slice(), xy]];\n    }\n    const path2D = this.#currentPath2D;\n    const currentPath = this.currentPath;\n    this.currentPath = [];\n    this.#currentPath2D = new Path2D();\n    const cmd = () => {\n      this.allRawPaths.push(currentPath);\n      this.paths.push(bezier);\n      this.bezierPath2D.push(path2D);\n      this._uiManager.rebuild(this);\n    };\n    const undo = () => {\n      this.allRawPaths.pop();\n      this.paths.pop();\n      this.bezierPath2D.pop();\n      if (this.paths.length === 0) {\n        this.remove();\n      } else {\n        if (!this.canvas) {\n          this.#createCanvas();\n          this.#createObserver();\n        }\n        this.#fitToContent();\n      }\n    };\n    this.addCommands({\n      cmd,\n      undo,\n      mustExec: true\n    });\n  }\n  #drawPoints() {\n    if (!this.#hasSomethingToDraw) {\n      return;\n    }\n    this.#hasSomethingToDraw = false;\n    const thickness = Math.ceil(this.thickness * this.parentScale);\n    const lastPoints = this.currentPath.slice(-3);\n    const x = lastPoints.map(xy => xy[0]);\n    const y = lastPoints.map(xy => xy[1]);\n    const xMin = Math.min(...x) - thickness;\n    const xMax = Math.max(...x) + thickness;\n    const yMin = Math.min(...y) - thickness;\n    const yMax = Math.max(...y) + thickness;\n    const {\n      ctx\n    } = this;\n    ctx.save();\n    ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n    for (const path of this.bezierPath2D) {\n      ctx.stroke(path);\n    }\n    ctx.stroke(this.#currentPath2D);\n    ctx.restore();\n  }\n  #makeBezierCurve(path2D, x0, y0, x1, y1, x2, y2) {\n    const prevX = (x0 + x1) / 2;\n    const prevY = (y0 + y1) / 2;\n    const x3 = (x1 + x2) / 2;\n    const y3 = (y1 + y2) / 2;\n    path2D.bezierCurveTo(prevX + 2 * (x1 - prevX) / 3, prevY + 2 * (y1 - prevY) / 3, x3 + 2 * (x1 - x3) / 3, y3 + 2 * (y1 - y3) / 3, x3, y3);\n  }\n  #generateBezierPoints() {\n    const path = this.currentPath;\n    if (path.length <= 2) {\n      return [[path[0], path[0], path.at(-1), path.at(-1)]];\n    }\n    const bezierPoints = [];\n    let i;\n    let [x0, y0] = path[0];\n    for (i = 1; i < path.length - 2; i++) {\n      const [x1, y1] = path[i];\n      const [x2, y2] = path[i + 1];\n      const x3 = (x1 + x2) / 2;\n      const y3 = (y1 + y2) / 2;\n      const control1 = [x0 + 2 * (x1 - x0) / 3, y0 + 2 * (y1 - y0) / 3];\n      const control2 = [x3 + 2 * (x1 - x3) / 3, y3 + 2 * (y1 - y3) / 3];\n      bezierPoints.push([[x0, y0], control1, control2, [x3, y3]]);\n      [x0, y0] = [x3, y3];\n    }\n    const [x1, y1] = path[i];\n    const [x2, y2] = path[i + 1];\n    const control1 = [x0 + 2 * (x1 - x0) / 3, y0 + 2 * (y1 - y0) / 3];\n    const control2 = [x2 + 2 * (x1 - x2) / 3, y2 + 2 * (y1 - y2) / 3];\n    bezierPoints.push([[x0, y0], control1, control2, [x2, y2]]);\n    return bezierPoints;\n  }\n  #redraw() {\n    if (this.isEmpty()) {\n      this.#updateTransform();\n      return;\n    }\n    this.#setStroke();\n    const {\n      canvas,\n      ctx\n    } = this;\n    ctx.setTransform(1, 0, 0, 1, 0, 0);\n    ctx.clearRect(0, 0, canvas.width, canvas.height);\n    this.#updateTransform();\n    for (const path of this.bezierPath2D) {\n      ctx.stroke(path);\n    }\n  }\n  commit() {\n    if (this.#disableEditing) {\n      return;\n    }\n    super.commit();\n    this.isEditing = false;\n    this.disableEditMode();\n    this.setInForeground();\n    this.#disableEditing = true;\n    this.div.classList.add(\"disabled\");\n    this.#fitToContent(true);\n    this.select();\n    this.parent.addInkEditorIfNeeded(true);\n    this.moveInDOM();\n    this.div.focus({\n      preventScroll: true\n    });\n  }\n  focusin(event) {\n    if (!this._focusEventsAllowed) {\n      return;\n    }\n    super.focusin(event);\n    this.enableEditMode();\n  }\n  canvasPointerdown(event) {\n    if (event.button !== 0 || !this.isInEditMode() || this.#disableEditing) {\n      return;\n    }\n    this.setInForeground();\n    event.preventDefault();\n    if (!this.div.contains(document.activeElement)) {\n      this.div.focus({\n        preventScroll: true\n      });\n    }\n    this.#startDrawing(event.offsetX, event.offsetY);\n  }\n  canvasPointermove(event) {\n    event.preventDefault();\n    this.#draw(event.offsetX, event.offsetY);\n  }\n  canvasPointerup(event) {\n    event.preventDefault();\n    this.#endDrawing(event);\n  }\n  canvasPointerleave(event) {\n    this.#endDrawing(event);\n  }\n  #endDrawing(event) {\n    this.canvas.removeEventListener(\"pointerleave\", this.#boundCanvasPointerleave);\n    this.canvas.removeEventListener(\"pointermove\", this.#boundCanvasPointermove);\n    this.canvas.removeEventListener(\"pointerup\", this.#boundCanvasPointerup);\n    this.canvas.addEventListener(\"pointerdown\", this.#boundCanvasPointerdown);\n    if (this.#canvasContextMenuTimeoutId) {\n      clearTimeout(this.#canvasContextMenuTimeoutId);\n    }\n    this.#canvasContextMenuTimeoutId = setTimeout(() => {\n      this.#canvasContextMenuTimeoutId = null;\n      this.canvas.removeEventListener(\"contextmenu\", display_utils.noContextMenu);\n    }, 10);\n    this.#stopDrawing(event.offsetX, event.offsetY);\n    this.addToAnnotationStorage();\n    this.setInBackground();\n  }\n  #createCanvas() {\n    this.canvas = document.createElement(\"canvas\");\n    this.canvas.width = this.canvas.height = 0;\n    this.canvas.className = \"inkEditorCanvas\";\n    this.canvas.setAttribute(\"data-l10n-id\", \"pdfjs-ink-canvas\");\n    this.div.append(this.canvas);\n    this.ctx = this.canvas.getContext(\"2d\");\n  }\n  #createObserver() {\n    this.#observer = new ResizeObserver(entries => {\n      const rect = entries[0].contentRect;\n      if (rect.width && rect.height) {\n        this.setDimensions(rect.width, rect.height);\n      }\n    });\n    this.#observer.observe(this.div);\n  }\n  get isResizable() {\n    return !this.isEmpty() && this.#disableEditing;\n  }\n  render() {\n    if (this.div) {\n      return this.div;\n    }\n    let baseX, baseY;\n    if (this.width) {\n      baseX = this.x;\n      baseY = this.y;\n    }\n    super.render();\n    this.div.setAttribute(\"data-l10n-id\", \"pdfjs-ink\");\n    const [x, y, w, h] = this.#getInitialBBox();\n    this.setAt(x, y, 0, 0);\n    this.setDims(w, h);\n    this.#createCanvas();\n    if (this.width) {\n      const [parentWidth, parentHeight] = this.parentDimensions;\n      this.setAspectRatio(this.width * parentWidth, this.height * parentHeight);\n      this.setAt(baseX * parentWidth, baseY * parentHeight, this.width * parentWidth, this.height * parentHeight);\n      this.#isCanvasInitialized = true;\n      this.#setCanvasDims();\n      this.setDims(this.width * parentWidth, this.height * parentHeight);\n      this.#redraw();\n      this.div.classList.add(\"disabled\");\n    } else {\n      this.div.classList.add(\"editing\");\n      this.enableEditMode();\n    }\n    this.#createObserver();\n    return this.div;\n  }\n  #setCanvasDims() {\n    if (!this.#isCanvasInitialized) {\n      return;\n    }\n    const [parentWidth, parentHeight] = this.parentDimensions;\n    this.canvas.width = Math.ceil(this.width * parentWidth);\n    this.canvas.height = Math.ceil(this.height * parentHeight);\n    this.#updateTransform();\n  }\n  setDimensions(width, height) {\n    const roundedWidth = Math.round(width);\n    const roundedHeight = Math.round(height);\n    if (this.#realWidth === roundedWidth && this.#realHeight === roundedHeight) {\n      return;\n    }\n    this.#realWidth = roundedWidth;\n    this.#realHeight = roundedHeight;\n    this.canvas.style.visibility = \"hidden\";\n    const [parentWidth, parentHeight] = this.parentDimensions;\n    this.width = width / parentWidth;\n    this.height = height / parentHeight;\n    this.fixAndSetPosition();\n    if (this.#disableEditing) {\n      this.#setScaleFactor(width, height);\n    }\n    this.#setCanvasDims();\n    this.#redraw();\n    this.canvas.style.visibility = \"visible\";\n    this.fixDims();\n  }\n  #setScaleFactor(width, height) {\n    const padding = this.#getPadding();\n    const scaleFactorW = (width - padding) / this.#baseWidth;\n    const scaleFactorH = (height - padding) / this.#baseHeight;\n    this.scaleFactor = Math.min(scaleFactorW, scaleFactorH);\n  }\n  #updateTransform() {\n    const padding = this.#getPadding() / 2;\n    this.ctx.setTransform(this.scaleFactor, 0, 0, this.scaleFactor, this.translationX * this.scaleFactor + padding, this.translationY * this.scaleFactor + padding);\n  }\n  static #buildPath2D(bezier) {\n    const path2D = new Path2D();\n    for (let i = 0, ii = bezier.length; i < ii; i++) {\n      const [first, control1, control2, second] = bezier[i];\n      if (i === 0) {\n        path2D.moveTo(...first);\n      }\n      path2D.bezierCurveTo(control1[0], control1[1], control2[0], control2[1], second[0], second[1]);\n    }\n    return path2D;\n  }\n  static #toPDFCoordinates(points, rect, rotation) {\n    const [blX, blY, trX, trY] = rect;\n    switch (rotation) {\n      case 0:\n        for (let i = 0, ii = points.length; i < ii; i += 2) {\n          points[i] += blX;\n          points[i + 1] = trY - points[i + 1];\n        }\n        break;\n      case 90:\n        for (let i = 0, ii = points.length; i < ii; i += 2) {\n          const x = points[i];\n          points[i] = points[i + 1] + blX;\n          points[i + 1] = x + blY;\n        }\n        break;\n      case 180:\n        for (let i = 0, ii = points.length; i < ii; i += 2) {\n          points[i] = trX - points[i];\n          points[i + 1] += blY;\n        }\n        break;\n      case 270:\n        for (let i = 0, ii = points.length; i < ii; i += 2) {\n          const x = points[i];\n          points[i] = trX - points[i + 1];\n          points[i + 1] = trY - x;\n        }\n        break;\n      default:\n        throw new Error(\"Invalid rotation\");\n    }\n    return points;\n  }\n  static #fromPDFCoordinates(points, rect, rotation) {\n    const [blX, blY, trX, trY] = rect;\n    switch (rotation) {\n      case 0:\n        for (let i = 0, ii = points.length; i < ii; i += 2) {\n          points[i] -= blX;\n          points[i + 1] = trY - points[i + 1];\n        }\n        break;\n      case 90:\n        for (let i = 0, ii = points.length; i < ii; i += 2) {\n          const x = points[i];\n          points[i] = points[i + 1] - blY;\n          points[i + 1] = x - blX;\n        }\n        break;\n      case 180:\n        for (let i = 0, ii = points.length; i < ii; i += 2) {\n          points[i] = trX - points[i];\n          points[i + 1] -= blY;\n        }\n        break;\n      case 270:\n        for (let i = 0, ii = points.length; i < ii; i += 2) {\n          const x = points[i];\n          points[i] = trY - points[i + 1];\n          points[i + 1] = trX - x;\n        }\n        break;\n      default:\n        throw new Error(\"Invalid rotation\");\n    }\n    return points;\n  }\n  #serializePaths(s, tx, ty, rect) {\n    const paths = [];\n    const padding = this.thickness / 2;\n    const shiftX = s * tx + padding;\n    const shiftY = s * ty + padding;\n    for (const bezier of this.paths) {\n      const buffer = [];\n      const points = [];\n      for (let j = 0, jj = bezier.length; j < jj; j++) {\n        const [first, control1, control2, second] = bezier[j];\n        if (first[0] === second[0] && first[1] === second[1] && jj === 1) {\n          const p0 = s * first[0] + shiftX;\n          const p1 = s * first[1] + shiftY;\n          buffer.push(p0, p1);\n          points.push(p0, p1);\n          break;\n        }\n        const p10 = s * first[0] + shiftX;\n        const p11 = s * first[1] + shiftY;\n        const p20 = s * control1[0] + shiftX;\n        const p21 = s * control1[1] + shiftY;\n        const p30 = s * control2[0] + shiftX;\n        const p31 = s * control2[1] + shiftY;\n        const p40 = s * second[0] + shiftX;\n        const p41 = s * second[1] + shiftY;\n        if (j === 0) {\n          buffer.push(p10, p11);\n          points.push(p10, p11);\n        }\n        buffer.push(p20, p21, p30, p31, p40, p41);\n        points.push(p20, p21);\n        if (j === jj - 1) {\n          points.push(p40, p41);\n        }\n      }\n      paths.push({\n        bezier: InkEditor.#toPDFCoordinates(buffer, rect, this.rotation),\n        points: InkEditor.#toPDFCoordinates(points, rect, this.rotation)\n      });\n    }\n    return paths;\n  }\n  #getBbox() {\n    let xMin = Infinity;\n    let xMax = -Infinity;\n    let yMin = Infinity;\n    let yMax = -Infinity;\n    for (const path of this.paths) {\n      for (const [first, control1, control2, second] of path) {\n        const bbox = util.Util.bezierBoundingBox(...first, ...control1, ...control2, ...second);\n        xMin = Math.min(xMin, bbox[0]);\n        yMin = Math.min(yMin, bbox[1]);\n        xMax = Math.max(xMax, bbox[2]);\n        yMax = Math.max(yMax, bbox[3]);\n      }\n    }\n    return [xMin, yMin, xMax, yMax];\n  }\n  #getPadding() {\n    return this.#disableEditing ? Math.ceil(this.thickness * this.parentScale) : 0;\n  }\n  #fitToContent(firstTime = false) {\n    if (this.isEmpty()) {\n      return;\n    }\n    if (!this.#disableEditing) {\n      this.#redraw();\n      return;\n    }\n    const bbox = this.#getBbox();\n    const padding = this.#getPadding();\n    this.#baseWidth = Math.max(editor_editor.AnnotationEditor.MIN_SIZE, bbox[2] - bbox[0]);\n    this.#baseHeight = Math.max(editor_editor.AnnotationEditor.MIN_SIZE, bbox[3] - bbox[1]);\n    const width = Math.ceil(padding + this.#baseWidth * this.scaleFactor);\n    const height = Math.ceil(padding + this.#baseHeight * this.scaleFactor);\n    const [parentWidth, parentHeight] = this.parentDimensions;\n    this.width = width / parentWidth;\n    this.height = height / parentHeight;\n    this.setAspectRatio(width, height);\n    const prevTranslationX = this.translationX;\n    const prevTranslationY = this.translationY;\n    this.translationX = -bbox[0];\n    this.translationY = -bbox[1];\n    this.#setCanvasDims();\n    this.#redraw();\n    this.#realWidth = width;\n    this.#realHeight = height;\n    this.setDims(width, height);\n    const unscaledPadding = firstTime ? padding / this.scaleFactor / 2 : 0;\n    this.translate(prevTranslationX - this.translationX - unscaledPadding, prevTranslationY - this.translationY - unscaledPadding);\n  }\n  static deserialize(data, parent, uiManager) {\n    if (data instanceof annotation_layer.InkAnnotationElement) {\n      return null;\n    }\n    const editor = super.deserialize(data, parent, uiManager);\n    editor.thickness = data.thickness;\n    editor.color = util.Util.makeHexColor(...data.color);\n    editor.opacity = data.opacity;\n    const [pageWidth, pageHeight] = editor.pageDimensions;\n    const width = editor.width * pageWidth;\n    const height = editor.height * pageHeight;\n    const scaleFactor = editor.parentScale;\n    const padding = data.thickness / 2;\n    editor.#disableEditing = true;\n    editor.#realWidth = Math.round(width);\n    editor.#realHeight = Math.round(height);\n    const {\n      paths,\n      rect,\n      rotation\n    } = data;\n    for (let {\n      bezier\n    } of paths) {\n      bezier = InkEditor.#fromPDFCoordinates(bezier, rect, rotation);\n      const path = [];\n      editor.paths.push(path);\n      let p0 = scaleFactor * (bezier[0] - padding);\n      let p1 = scaleFactor * (bezier[1] - padding);\n      for (let i = 2, ii = bezier.length; i < ii; i += 6) {\n        const p10 = scaleFactor * (bezier[i] - padding);\n        const p11 = scaleFactor * (bezier[i + 1] - padding);\n        const p20 = scaleFactor * (bezier[i + 2] - padding);\n        const p21 = scaleFactor * (bezier[i + 3] - padding);\n        const p30 = scaleFactor * (bezier[i + 4] - padding);\n        const p31 = scaleFactor * (bezier[i + 5] - padding);\n        path.push([[p0, p1], [p10, p11], [p20, p21], [p30, p31]]);\n        p0 = p30;\n        p1 = p31;\n      }\n      const path2D = this.#buildPath2D(path);\n      editor.bezierPath2D.push(path2D);\n    }\n    const bbox = editor.#getBbox();\n    editor.#baseWidth = Math.max(editor_editor.AnnotationEditor.MIN_SIZE, bbox[2] - bbox[0]);\n    editor.#baseHeight = Math.max(editor_editor.AnnotationEditor.MIN_SIZE, bbox[3] - bbox[1]);\n    editor.#setScaleFactor(width, height);\n    return editor;\n  }\n  serialize() {\n    if (this.isEmpty()) {\n      return null;\n    }\n    const rect = this.getRect(0, 0);\n    const color = editor_editor.AnnotationEditor._colorManager.convert(this.ctx.strokeStyle);\n    return {\n      annotationType: util.AnnotationEditorType.INK,\n      color,\n      thickness: this.thickness,\n      opacity: this.opacity,\n      paths: this.#serializePaths(this.scaleFactor / this.parentScale, this.translationX, this.translationY, rect),\n      pageIndex: this.pageIndex,\n      rect,\n      rotation: this.rotation,\n      structTreeParentId: this._structTreeParentId\n    };\n  }\n}\n\n;// CONCATENATED MODULE: ./src/display/editor/stamp.js\n\n\n\n\nclass StampEditor extends editor_editor.AnnotationEditor {\n  #bitmap = null;\n  #bitmapId = null;\n  #bitmapPromise = null;\n  #bitmapUrl = null;\n  #bitmapFile = null;\n  #bitmapFileName = \"\";\n  #canvas = null;\n  #observer = null;\n  #resizeTimeoutId = null;\n  #isSvg = false;\n  #hasBeenAddedInUndoStack = false;\n  static _type = \"stamp\";\n  static _editorType = util.AnnotationEditorType.STAMP;\n  constructor(params) {\n    super({\n      ...params,\n      name: \"stampEditor\"\n    });\n    this.#bitmapUrl = params.bitmapUrl;\n    this.#bitmapFile = params.bitmapFile;\n  }\n  static initialize(l10n, uiManager) {\n    editor_editor.AnnotationEditor.initialize(l10n, uiManager);\n  }\n  static get supportedTypes() {\n    const types = [\"apng\", \"avif\", \"bmp\", \"gif\", \"jpeg\", \"png\", \"svg+xml\", \"webp\", \"x-icon\"];\n    return (0,util.shadow)(this, \"supportedTypes\", types.map(type => `image/${type}`));\n  }\n  static get supportedTypesStr() {\n    return (0,util.shadow)(this, \"supportedTypesStr\", this.supportedTypes.join(\",\"));\n  }\n  static isHandlingMimeForPasting(mime) {\n    return this.supportedTypes.includes(mime);\n  }\n  static paste(item, parent) {\n    parent.pasteEditor(util.AnnotationEditorType.STAMP, {\n      bitmapFile: item.getAsFile()\n    });\n  }\n  #getBitmapFetched(data, fromId = false) {\n    if (!data) {\n      this.remove();\n      return;\n    }\n    this.#bitmap = data.bitmap;\n    if (!fromId) {\n      this.#bitmapId = data.id;\n      this.#isSvg = data.isSvg;\n    }\n    if (data.file) {\n      this.#bitmapFileName = data.file.name;\n    }\n    this.#createCanvas();\n  }\n  #getBitmapDone() {\n    this.#bitmapPromise = null;\n    this._uiManager.enableWaiting(false);\n    if (this.#canvas) {\n      this.div.focus();\n    }\n  }\n  #getBitmap() {\n    if (this.#bitmapId) {\n      this._uiManager.enableWaiting(true);\n      this._uiManager.imageManager.getFromId(this.#bitmapId).then(data => this.#getBitmapFetched(data, true)).finally(() => this.#getBitmapDone());\n      return;\n    }\n    if (this.#bitmapUrl) {\n      const url = this.#bitmapUrl;\n      this.#bitmapUrl = null;\n      this._uiManager.enableWaiting(true);\n      this.#bitmapPromise = this._uiManager.imageManager.getFromUrl(url).then(data => this.#getBitmapFetched(data)).finally(() => this.#getBitmapDone());\n      return;\n    }\n    if (this.#bitmapFile) {\n      const file = this.#bitmapFile;\n      this.#bitmapFile = null;\n      this._uiManager.enableWaiting(true);\n      this.#bitmapPromise = this._uiManager.imageManager.getFromFile(file).then(data => this.#getBitmapFetched(data)).finally(() => this.#getBitmapDone());\n      return;\n    }\n    const input = document.createElement(\"input\");\n    input.type = \"file\";\n    input.accept = StampEditor.supportedTypesStr;\n    this.#bitmapPromise = new Promise(resolve => {\n      input.addEventListener(\"change\", async () => {\n        if (!input.files || input.files.length === 0) {\n          this.remove();\n        } else {\n          this._uiManager.enableWaiting(true);\n          const data = await this._uiManager.imageManager.getFromFile(input.files[0]);\n          this.#getBitmapFetched(data);\n        }\n        resolve();\n      });\n      input.addEventListener(\"cancel\", () => {\n        this.remove();\n        resolve();\n      });\n    }).finally(() => this.#getBitmapDone());\n    input.click();\n  }\n  remove() {\n    if (this.#bitmapId) {\n      this.#bitmap = null;\n      this._uiManager.imageManager.deleteId(this.#bitmapId);\n      this.#canvas?.remove();\n      this.#canvas = null;\n      this.#observer?.disconnect();\n      this.#observer = null;\n      if (this.#resizeTimeoutId) {\n        clearTimeout(this.#resizeTimeoutId);\n        this.#resizeTimeoutId = null;\n      }\n    }\n    super.remove();\n  }\n  rebuild() {\n    if (!this.parent) {\n      if (this.#bitmapId) {\n        this.#getBitmap();\n      }\n      return;\n    }\n    super.rebuild();\n    if (this.div === null) {\n      return;\n    }\n    if (this.#bitmapId && this.#canvas === null) {\n      this.#getBitmap();\n    }\n    if (!this.isAttachedToDOM) {\n      this.parent.add(this);\n    }\n  }\n  onceAdded() {\n    this._isDraggable = true;\n    this.div.focus();\n  }\n  isEmpty() {\n    return !(this.#bitmapPromise || this.#bitmap || this.#bitmapUrl || this.#bitmapFile || this.#bitmapId);\n  }\n  get isResizable() {\n    return true;\n  }\n  render() {\n    if (this.div) {\n      return this.div;\n    }\n    let baseX, baseY;\n    if (this.width) {\n      baseX = this.x;\n      baseY = this.y;\n    }\n    super.render();\n    this.div.hidden = true;\n    this.addAltTextButton();\n    if (this.#bitmap) {\n      this.#createCanvas();\n    } else {\n      this.#getBitmap();\n    }\n    if (this.width) {\n      const [parentWidth, parentHeight] = this.parentDimensions;\n      this.setAt(baseX * parentWidth, baseY * parentHeight, this.width * parentWidth, this.height * parentHeight);\n    }\n    return this.div;\n  }\n  #createCanvas() {\n    const {\n      div\n    } = this;\n    let {\n      width,\n      height\n    } = this.#bitmap;\n    const [pageWidth, pageHeight] = this.pageDimensions;\n    const MAX_RATIO = 0.75;\n    if (this.width) {\n      width = this.width * pageWidth;\n      height = this.height * pageHeight;\n    } else if (width > MAX_RATIO * pageWidth || height > MAX_RATIO * pageHeight) {\n      const factor = Math.min(MAX_RATIO * pageWidth / width, MAX_RATIO * pageHeight / height);\n      width *= factor;\n      height *= factor;\n    }\n    const [parentWidth, parentHeight] = this.parentDimensions;\n    this.setDims(width * parentWidth / pageWidth, height * parentHeight / pageHeight);\n    this._uiManager.enableWaiting(false);\n    const canvas = this.#canvas = document.createElement(\"canvas\");\n    div.append(canvas);\n    div.hidden = false;\n    this.#drawBitmap(width, height);\n    this.#createObserver();\n    if (!this.#hasBeenAddedInUndoStack) {\n      this.parent.addUndoableEditor(this);\n      this.#hasBeenAddedInUndoStack = true;\n    }\n    this._reportTelemetry({\n      action: \"inserted_image\"\n    });\n    if (this.#bitmapFileName) {\n      canvas.setAttribute(\"aria-label\", this.#bitmapFileName);\n    }\n  }\n  #setDimensions(width, height) {\n    const [parentWidth, parentHeight] = this.parentDimensions;\n    this.width = width / parentWidth;\n    this.height = height / parentHeight;\n    this.setDims(width, height);\n    if (this._initialOptions?.isCentered) {\n      this.center();\n    } else {\n      this.fixAndSetPosition();\n    }\n    this._initialOptions = null;\n    if (this.#resizeTimeoutId !== null) {\n      clearTimeout(this.#resizeTimeoutId);\n    }\n    const TIME_TO_WAIT = 200;\n    this.#resizeTimeoutId = setTimeout(() => {\n      this.#resizeTimeoutId = null;\n      this.#drawBitmap(width, height);\n    }, TIME_TO_WAIT);\n  }\n  #scaleBitmap(width, height) {\n    const {\n      width: bitmapWidth,\n      height: bitmapHeight\n    } = this.#bitmap;\n    let newWidth = bitmapWidth;\n    let newHeight = bitmapHeight;\n    let bitmap = this.#bitmap;\n    while (newWidth > 2 * width || newHeight > 2 * height) {\n      const prevWidth = newWidth;\n      const prevHeight = newHeight;\n      if (newWidth > 2 * width) {\n        newWidth = newWidth >= 16384 ? Math.floor(newWidth / 2) - 1 : Math.ceil(newWidth / 2);\n      }\n      if (newHeight > 2 * height) {\n        newHeight = newHeight >= 16384 ? Math.floor(newHeight / 2) - 1 : Math.ceil(newHeight / 2);\n      }\n      const offscreen = new OffscreenCanvas(newWidth, newHeight);\n      const ctx = offscreen.getContext(\"2d\");\n      ctx.drawImage(bitmap, 0, 0, prevWidth, prevHeight, 0, 0, newWidth, newHeight);\n      bitmap = offscreen.transferToImageBitmap();\n    }\n    return bitmap;\n  }\n  #drawBitmap(width, height) {\n    width = Math.ceil(width);\n    height = Math.ceil(height);\n    const canvas = this.#canvas;\n    if (!canvas || canvas.width === width && canvas.height === height) {\n      return;\n    }\n    canvas.width = width;\n    canvas.height = height;\n    const bitmap = this.#isSvg ? this.#bitmap : this.#scaleBitmap(width, height);\n    if (this._uiManager.hasMLManager && !this.hasAltText()) {\n      const offscreen = new OffscreenCanvas(width, height);\n      const ctx = offscreen.getContext(\"2d\");\n      ctx.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, 0, 0, width, height);\n      offscreen.convertToBlob().then(blob => {\n        const fileReader = new FileReader();\n        fileReader.onload = () => {\n          const url = fileReader.result;\n          this._uiManager.mlGuess({\n            service: \"image-to-text\",\n            request: {\n              imageData: url\n            }\n          }).then(response => {\n            const altText = response?.output || \"\";\n            if (this.parent && altText && !this.hasAltText()) {\n              this.altTextData = {\n                altText,\n                decorative: false\n              };\n            }\n          });\n        };\n        fileReader.readAsDataURL(blob);\n      });\n    }\n    const ctx = canvas.getContext(\"2d\");\n    ctx.filter = this._uiManager.hcmFilter;\n    ctx.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, 0, 0, width, height);\n  }\n  getImageForAltText() {\n    return this.#canvas;\n  }\n  #serializeBitmap(toUrl) {\n    if (toUrl) {\n      if (this.#isSvg) {\n        const url = this._uiManager.imageManager.getSvgUrl(this.#bitmapId);\n        if (url) {\n          return url;\n        }\n      }\n      const canvas = document.createElement(\"canvas\");\n      ({\n        width: canvas.width,\n        height: canvas.height\n      } = this.#bitmap);\n      const ctx = canvas.getContext(\"2d\");\n      ctx.drawImage(this.#bitmap, 0, 0);\n      return canvas.toDataURL();\n    }\n    if (this.#isSvg) {\n      const [pageWidth, pageHeight] = this.pageDimensions;\n      const width = Math.round(this.width * pageWidth * display_utils.PixelsPerInch.PDF_TO_CSS_UNITS);\n      const height = Math.round(this.height * pageHeight * display_utils.PixelsPerInch.PDF_TO_CSS_UNITS);\n      const offscreen = new OffscreenCanvas(width, height);\n      const ctx = offscreen.getContext(\"2d\");\n      ctx.drawImage(this.#bitmap, 0, 0, this.#bitmap.width, this.#bitmap.height, 0, 0, width, height);\n      return offscreen.transferToImageBitmap();\n    }\n    return structuredClone(this.#bitmap);\n  }\n  #createObserver() {\n    this.#observer = new ResizeObserver(entries => {\n      const rect = entries[0].contentRect;\n      if (rect.width && rect.height) {\n        this.#setDimensions(rect.width, rect.height);\n      }\n    });\n    this.#observer.observe(this.div);\n  }\n  static deserialize(data, parent, uiManager) {\n    if (data instanceof annotation_layer.StampAnnotationElement) {\n      return null;\n    }\n    const editor = super.deserialize(data, parent, uiManager);\n    const {\n      rect,\n      bitmapUrl,\n      bitmapId,\n      isSvg,\n      accessibilityData\n    } = data;\n    if (bitmapId && uiManager.imageManager.isValidId(bitmapId)) {\n      editor.#bitmapId = bitmapId;\n    } else {\n      editor.#bitmapUrl = bitmapUrl;\n    }\n    editor.#isSvg = isSvg;\n    const [parentWidth, parentHeight] = editor.pageDimensions;\n    editor.width = (rect[2] - rect[0]) / parentWidth;\n    editor.height = (rect[3] - rect[1]) / parentHeight;\n    if (accessibilityData) {\n      editor.altTextData = accessibilityData;\n    }\n    return editor;\n  }\n  serialize(isForCopying = false, context = null) {\n    if (this.isEmpty()) {\n      return null;\n    }\n    const serialized = {\n      annotationType: util.AnnotationEditorType.STAMP,\n      bitmapId: this.#bitmapId,\n      pageIndex: this.pageIndex,\n      rect: this.getRect(0, 0),\n      rotation: this.rotation,\n      isSvg: this.#isSvg,\n      structTreeParentId: this._structTreeParentId\n    };\n    if (isForCopying) {\n      serialized.bitmapUrl = this.#serializeBitmap(true);\n      serialized.accessibilityData = this.altTextData;\n      return serialized;\n    }\n    const {\n      decorative,\n      altText\n    } = this.altTextData;\n    if (!decorative && altText) {\n      serialized.accessibilityData = {\n        type: \"Figure\",\n        alt: altText\n      };\n    }\n    if (context === null) {\n      return serialized;\n    }\n    context.stamps ||= new Map();\n    const area = this.#isSvg ? (serialized.rect[2] - serialized.rect[0]) * (serialized.rect[3] - serialized.rect[1]) : null;\n    if (!context.stamps.has(this.#bitmapId)) {\n      context.stamps.set(this.#bitmapId, {\n        area,\n        serialized\n      });\n      serialized.bitmap = this.#serializeBitmap(false);\n    } else if (this.#isSvg) {\n      const prevData = context.stamps.get(this.#bitmapId);\n      if (area > prevData.area) {\n        prevData.area = area;\n        prevData.serialized.bitmap.close();\n        prevData.serialized.bitmap = this.#serializeBitmap(false);\n      }\n    }\n    return serialized;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/display/editor/annotation_editor_layer.js\n\n\n\n\n\n\n\nclass AnnotationEditorLayer {\n  #accessibilityManager;\n  #allowClick = false;\n  #annotationLayer = null;\n  #boundPointerup = null;\n  #boundPointerdown = null;\n  #boundTextLayerPointerDown = null;\n  #editorFocusTimeoutId = null;\n  #editors = new Map();\n  #hadPointerDown = false;\n  #isCleaningUp = false;\n  #isDisabling = false;\n  #textLayer = null;\n  #uiManager;\n  static _initialized = false;\n  static #editorTypes = new Map([FreeTextEditor, InkEditor, StampEditor, HighlightEditor].map(type => [type._editorType, type]));\n  constructor({\n    uiManager,\n    pageIndex,\n    div,\n    accessibilityManager,\n    annotationLayer,\n    drawLayer,\n    textLayer,\n    viewport,\n    l10n\n  }) {\n    const editorTypes = [...AnnotationEditorLayer.#editorTypes.values()];\n    if (!AnnotationEditorLayer._initialized) {\n      AnnotationEditorLayer._initialized = true;\n      for (const editorType of editorTypes) {\n        editorType.initialize(l10n, uiManager);\n      }\n    }\n    uiManager.registerEditorTypes(editorTypes);\n    this.#uiManager = uiManager;\n    this.pageIndex = pageIndex;\n    this.div = div;\n    this.#accessibilityManager = accessibilityManager;\n    this.#annotationLayer = annotationLayer;\n    this.viewport = viewport;\n    this.#textLayer = textLayer;\n    this.drawLayer = drawLayer;\n    this.#uiManager.addLayer(this);\n  }\n  get isEmpty() {\n    return this.#editors.size === 0;\n  }\n  get isInvisible() {\n    return this.isEmpty && this.#uiManager.getMode() === util.AnnotationEditorType.NONE;\n  }\n  updateToolbar(mode) {\n    this.#uiManager.updateToolbar(mode);\n  }\n  updateMode(mode = this.#uiManager.getMode()) {\n    this.#cleanup();\n    switch (mode) {\n      case util.AnnotationEditorType.NONE:\n        this.disableTextSelection();\n        this.togglePointerEvents(false);\n        this.toggleAnnotationLayerPointerEvents(true);\n        this.disableClick();\n        return;\n      case util.AnnotationEditorType.INK:\n        this.addInkEditorIfNeeded(false);\n        this.disableTextSelection();\n        this.togglePointerEvents(true);\n        this.disableClick();\n        break;\n      case util.AnnotationEditorType.HIGHLIGHT:\n        this.enableTextSelection();\n        this.togglePointerEvents(false);\n        this.disableClick();\n        break;\n      default:\n        this.disableTextSelection();\n        this.togglePointerEvents(true);\n        this.enableClick();\n    }\n    this.toggleAnnotationLayerPointerEvents(false);\n    const {\n      classList\n    } = this.div;\n    for (const editorType of AnnotationEditorLayer.#editorTypes.values()) {\n      classList.toggle(`${editorType._type}Editing`, mode === editorType._editorType);\n    }\n    this.div.hidden = false;\n  }\n  hasTextLayer(textLayer) {\n    return textLayer === this.#textLayer?.div;\n  }\n  addInkEditorIfNeeded(isCommitting) {\n    if (this.#uiManager.getMode() !== util.AnnotationEditorType.INK) {\n      return;\n    }\n    if (!isCommitting) {\n      for (const editor of this.#editors.values()) {\n        if (editor.isEmpty()) {\n          editor.setInBackground();\n          return;\n        }\n      }\n    }\n    const editor = this.createAndAddNewEditor({\n      offsetX: 0,\n      offsetY: 0\n    }, false);\n    editor.setInBackground();\n  }\n  setEditingState(isEditing) {\n    this.#uiManager.setEditingState(isEditing);\n  }\n  addCommands(params) {\n    this.#uiManager.addCommands(params);\n  }\n  togglePointerEvents(enabled = false) {\n    this.div.classList.toggle(\"disabled\", !enabled);\n  }\n  toggleAnnotationLayerPointerEvents(enabled = false) {\n    this.#annotationLayer?.div.classList.toggle(\"disabled\", !enabled);\n  }\n  enable() {\n    this.div.tabIndex = 0;\n    this.togglePointerEvents(true);\n    const annotationElementIds = new Set();\n    for (const editor of this.#editors.values()) {\n      editor.enableEditing();\n      editor.show(true);\n      if (editor.annotationElementId) {\n        this.#uiManager.removeChangedExistingAnnotation(editor);\n        annotationElementIds.add(editor.annotationElementId);\n      }\n    }\n    if (!this.#annotationLayer) {\n      return;\n    }\n    const editables = this.#annotationLayer.getEditableAnnotations();\n    for (const editable of editables) {\n      editable.hide();\n      if (this.#uiManager.isDeletedAnnotationElement(editable.data.id)) {\n        continue;\n      }\n      if (annotationElementIds.has(editable.data.id)) {\n        continue;\n      }\n      const editor = this.deserialize(editable);\n      if (!editor) {\n        continue;\n      }\n      this.addOrRebuild(editor);\n      editor.enableEditing();\n    }\n  }\n  disable() {\n    this.#isDisabling = true;\n    this.div.tabIndex = -1;\n    this.togglePointerEvents(false);\n    const changedAnnotations = new Map();\n    const resetAnnotations = new Map();\n    for (const editor of this.#editors.values()) {\n      editor.disableEditing();\n      if (!editor.annotationElementId) {\n        continue;\n      }\n      if (editor.serialize() !== null) {\n        changedAnnotations.set(editor.annotationElementId, editor);\n        continue;\n      } else {\n        resetAnnotations.set(editor.annotationElementId, editor);\n      }\n      this.getEditableAnnotation(editor.annotationElementId)?.show();\n      editor.remove();\n    }\n    if (this.#annotationLayer) {\n      const editables = this.#annotationLayer.getEditableAnnotations();\n      for (const editable of editables) {\n        const {\n          id\n        } = editable.data;\n        if (this.#uiManager.isDeletedAnnotationElement(id)) {\n          continue;\n        }\n        let editor = resetAnnotations.get(id);\n        if (editor) {\n          editor.resetAnnotationElement(editable);\n          editor.show(false);\n          editable.show();\n          continue;\n        }\n        editor = changedAnnotations.get(id);\n        if (editor) {\n          this.#uiManager.addChangedExistingAnnotation(editor);\n          editor.renderAnnotationElement(editable);\n          editor.show(false);\n        }\n        editable.show();\n      }\n    }\n    this.#cleanup();\n    if (this.isEmpty) {\n      this.div.hidden = true;\n    }\n    const {\n      classList\n    } = this.div;\n    for (const editorType of AnnotationEditorLayer.#editorTypes.values()) {\n      classList.remove(`${editorType._type}Editing`);\n    }\n    this.disableTextSelection();\n    this.toggleAnnotationLayerPointerEvents(true);\n    this.#isDisabling = false;\n  }\n  getEditableAnnotation(id) {\n    return this.#annotationLayer?.getEditableAnnotation(id) || null;\n  }\n  setActiveEditor(editor) {\n    const currentActive = this.#uiManager.getActive();\n    if (currentActive === editor) {\n      return;\n    }\n    this.#uiManager.setActiveEditor(editor);\n  }\n  enableTextSelection() {\n    this.div.tabIndex = -1;\n    if (this.#textLayer?.div && !this.#boundTextLayerPointerDown) {\n      this.#boundTextLayerPointerDown = this.#textLayerPointerDown.bind(this);\n      this.#textLayer.div.addEventListener(\"pointerdown\", this.#boundTextLayerPointerDown);\n      this.#textLayer.div.classList.add(\"highlighting\");\n    }\n  }\n  disableTextSelection() {\n    this.div.tabIndex = 0;\n    if (this.#textLayer?.div && this.#boundTextLayerPointerDown) {\n      this.#textLayer.div.removeEventListener(\"pointerdown\", this.#boundTextLayerPointerDown);\n      this.#boundTextLayerPointerDown = null;\n      this.#textLayer.div.classList.remove(\"highlighting\");\n    }\n  }\n  #textLayerPointerDown(event) {\n    this.#uiManager.unselectAll();\n    if (event.target === this.#textLayer.div) {\n      const {\n        isMac\n      } = util.FeatureTest.platform;\n      if (event.button !== 0 || event.ctrlKey && isMac) {\n        return;\n      }\n      this.#uiManager.showAllEditors(\"highlight\", true, true);\n      this.#textLayer.div.classList.add(\"free\");\n      HighlightEditor.startHighlighting(this, this.#uiManager.direction === \"ltr\", event);\n      this.#textLayer.div.addEventListener(\"pointerup\", () => {\n        this.#textLayer.div.classList.remove(\"free\");\n      }, {\n        once: true\n      });\n      event.preventDefault();\n    }\n  }\n  enableClick() {\n    if (this.#boundPointerdown) {\n      return;\n    }\n    this.#boundPointerdown = this.pointerdown.bind(this);\n    this.#boundPointerup = this.pointerup.bind(this);\n    this.div.addEventListener(\"pointerdown\", this.#boundPointerdown);\n    this.div.addEventListener(\"pointerup\", this.#boundPointerup);\n  }\n  disableClick() {\n    if (!this.#boundPointerdown) {\n      return;\n    }\n    this.div.removeEventListener(\"pointerdown\", this.#boundPointerdown);\n    this.div.removeEventListener(\"pointerup\", this.#boundPointerup);\n    this.#boundPointerdown = null;\n    this.#boundPointerup = null;\n  }\n  attach(editor) {\n    this.#editors.set(editor.id, editor);\n    const {\n      annotationElementId\n    } = editor;\n    if (annotationElementId && this.#uiManager.isDeletedAnnotationElement(annotationElementId)) {\n      this.#uiManager.removeDeletedAnnotationElement(editor);\n    }\n  }\n  detach(editor) {\n    this.#editors.delete(editor.id);\n    this.#accessibilityManager?.removePointerInTextLayer(editor.contentDiv);\n    if (!this.#isDisabling && editor.annotationElementId) {\n      this.#uiManager.addDeletedAnnotationElement(editor);\n    }\n  }\n  remove(editor) {\n    this.detach(editor);\n    this.#uiManager.removeEditor(editor);\n    editor.div.remove();\n    editor.isAttachedToDOM = false;\n    if (!this.#isCleaningUp) {\n      this.addInkEditorIfNeeded(false);\n    }\n  }\n  changeParent(editor) {\n    if (editor.parent === this) {\n      return;\n    }\n    if (editor.parent && editor.annotationElementId) {\n      this.#uiManager.addDeletedAnnotationElement(editor.annotationElementId);\n      editor_editor.AnnotationEditor.deleteAnnotationElement(editor);\n      editor.annotationElementId = null;\n    }\n    this.attach(editor);\n    editor.parent?.detach(editor);\n    editor.setParent(this);\n    if (editor.div && editor.isAttachedToDOM) {\n      editor.div.remove();\n      this.div.append(editor.div);\n    }\n  }\n  add(editor) {\n    if (editor.parent === this && editor.isAttachedToDOM) {\n      return;\n    }\n    this.changeParent(editor);\n    this.#uiManager.addEditor(editor);\n    this.attach(editor);\n    if (!editor.isAttachedToDOM) {\n      const div = editor.render();\n      this.div.append(div);\n      editor.isAttachedToDOM = true;\n    }\n    editor.fixAndSetPosition();\n    editor.onceAdded();\n    this.#uiManager.addToAnnotationStorage(editor);\n    editor._reportTelemetry(editor.telemetryInitialData);\n  }\n  moveEditorInDOM(editor) {\n    if (!editor.isAttachedToDOM) {\n      return;\n    }\n    const {\n      activeElement\n    } = document;\n    if (editor.div.contains(activeElement) && !this.#editorFocusTimeoutId) {\n      editor._focusEventsAllowed = false;\n      this.#editorFocusTimeoutId = setTimeout(() => {\n        this.#editorFocusTimeoutId = null;\n        if (!editor.div.contains(document.activeElement)) {\n          editor.div.addEventListener(\"focusin\", () => {\n            editor._focusEventsAllowed = true;\n          }, {\n            once: true\n          });\n          activeElement.focus();\n        } else {\n          editor._focusEventsAllowed = true;\n        }\n      }, 0);\n    }\n    editor._structTreeParentId = this.#accessibilityManager?.moveElementInDOM(this.div, editor.div, editor.contentDiv, true);\n  }\n  addOrRebuild(editor) {\n    if (editor.needsToBeRebuilt()) {\n      editor.parent ||= this;\n      editor.rebuild();\n      editor.show();\n    } else {\n      this.add(editor);\n    }\n  }\n  addUndoableEditor(editor) {\n    const cmd = () => editor._uiManager.rebuild(editor);\n    const undo = () => {\n      editor.remove();\n    };\n    this.addCommands({\n      cmd,\n      undo,\n      mustExec: false\n    });\n  }\n  getNextId() {\n    return this.#uiManager.getId();\n  }\n  get #currentEditorType() {\n    return AnnotationEditorLayer.#editorTypes.get(this.#uiManager.getMode());\n  }\n  #createNewEditor(params) {\n    const editorType = this.#currentEditorType;\n    return editorType ? new editorType.prototype.constructor(params) : null;\n  }\n  canCreateNewEmptyEditor() {\n    return this.#currentEditorType?.canCreateNewEmptyEditor();\n  }\n  pasteEditor(mode, params) {\n    this.#uiManager.updateToolbar(mode);\n    this.#uiManager.updateMode(mode);\n    const {\n      offsetX,\n      offsetY\n    } = this.#getCenterPoint();\n    const id = this.getNextId();\n    const editor = this.#createNewEditor({\n      parent: this,\n      id,\n      x: offsetX,\n      y: offsetY,\n      uiManager: this.#uiManager,\n      isCentered: true,\n      ...params\n    });\n    if (editor) {\n      this.add(editor);\n    }\n  }\n  deserialize(data) {\n    return AnnotationEditorLayer.#editorTypes.get(data.annotationType ?? data.annotationEditorType)?.deserialize(data, this, this.#uiManager) || null;\n  }\n  createAndAddNewEditor(event, isCentered, data = {}) {\n    const id = this.getNextId();\n    const editor = this.#createNewEditor({\n      parent: this,\n      id,\n      x: event.offsetX,\n      y: event.offsetY,\n      uiManager: this.#uiManager,\n      isCentered,\n      ...data\n    });\n    if (editor) {\n      this.add(editor);\n    }\n    return editor;\n  }\n  #getCenterPoint() {\n    const {\n      x,\n      y,\n      width,\n      height\n    } = this.div.getBoundingClientRect();\n    const tlX = Math.max(0, x);\n    const tlY = Math.max(0, y);\n    const brX = Math.min(window.innerWidth, x + width);\n    const brY = Math.min(window.innerHeight, y + height);\n    const centerX = (tlX + brX) / 2 - x;\n    const centerY = (tlY + brY) / 2 - y;\n    const [offsetX, offsetY] = this.viewport.rotation % 180 === 0 ? [centerX, centerY] : [centerY, centerX];\n    return {\n      offsetX,\n      offsetY\n    };\n  }\n  addNewEditor() {\n    this.createAndAddNewEditor(this.#getCenterPoint(), true);\n  }\n  setSelected(editor) {\n    this.#uiManager.setSelected(editor);\n  }\n  toggleSelected(editor) {\n    this.#uiManager.toggleSelected(editor);\n  }\n  isSelected(editor) {\n    return this.#uiManager.isSelected(editor);\n  }\n  unselect(editor) {\n    this.#uiManager.unselect(editor);\n  }\n  pointerup(event) {\n    const {\n      isMac\n    } = util.FeatureTest.platform;\n    if (event.button !== 0 || event.ctrlKey && isMac) {\n      return;\n    }\n    if (event.target !== this.div) {\n      return;\n    }\n    if (!this.#hadPointerDown) {\n      return;\n    }\n    this.#hadPointerDown = false;\n    if (!this.#allowClick) {\n      this.#allowClick = true;\n      return;\n    }\n    if (this.#uiManager.getMode() === util.AnnotationEditorType.STAMP) {\n      this.#uiManager.unselectAll();\n      return;\n    }\n    this.createAndAddNewEditor(event, false);\n  }\n  pointerdown(event) {\n    if (this.#uiManager.getMode() === util.AnnotationEditorType.HIGHLIGHT) {\n      this.enableTextSelection();\n    }\n    if (this.#hadPointerDown) {\n      this.#hadPointerDown = false;\n      return;\n    }\n    const {\n      isMac\n    } = util.FeatureTest.platform;\n    if (event.button !== 0 || event.ctrlKey && isMac) {\n      return;\n    }\n    if (event.target !== this.div) {\n      return;\n    }\n    this.#hadPointerDown = true;\n    const editor = this.#uiManager.getActive();\n    this.#allowClick = !editor || editor.isEmpty();\n  }\n  findNewParent(editor, x, y) {\n    const layer = this.#uiManager.findParent(x, y);\n    if (layer === null || layer === this) {\n      return false;\n    }\n    layer.changeParent(editor);\n    return true;\n  }\n  destroy() {\n    if (this.#uiManager.getActive()?.parent === this) {\n      this.#uiManager.commitOrRemove();\n      this.#uiManager.setActiveEditor(null);\n    }\n    if (this.#editorFocusTimeoutId) {\n      clearTimeout(this.#editorFocusTimeoutId);\n      this.#editorFocusTimeoutId = null;\n    }\n    for (const editor of this.#editors.values()) {\n      this.#accessibilityManager?.removePointerInTextLayer(editor.contentDiv);\n      editor.setParent(null);\n      editor.isAttachedToDOM = false;\n      editor.div.remove();\n    }\n    this.div = null;\n    this.#editors.clear();\n    this.#uiManager.removeLayer(this);\n  }\n  #cleanup() {\n    this.#isCleaningUp = true;\n    for (const editor of this.#editors.values()) {\n      if (editor.isEmpty()) {\n        editor.remove();\n      }\n    }\n    this.#isCleaningUp = false;\n  }\n  render({\n    viewport\n  }) {\n    this.viewport = viewport;\n    (0,display_utils.setLayerDimensions)(this.div, viewport);\n    for (const editor of this.#uiManager.getEditors(this.pageIndex)) {\n      this.add(editor);\n      editor.rebuild();\n    }\n    this.updateMode();\n  }\n  update({\n    viewport\n  }) {\n    this.#uiManager.commitOrRemove();\n    this.#cleanup();\n    const oldRotation = this.viewport.rotation;\n    const rotation = viewport.rotation;\n    this.viewport = viewport;\n    (0,display_utils.setLayerDimensions)(this.div, {\n      rotation\n    });\n    if (oldRotation !== rotation) {\n      for (const editor of this.#editors.values()) {\n        editor.rotate(rotation);\n      }\n    }\n    this.addInkEditorIfNeeded(false);\n  }\n  get pageDimensions() {\n    const {\n      pageWidth,\n      pageHeight\n    } = this.viewport.rawDims;\n    return [pageWidth, pageHeight];\n  }\n  get scale() {\n    return this.#uiManager.viewParameters.realScale;\n  }\n}\n\n\n/***/ }),\n\n/***/ 259:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   ColorPicker: () => (/* binding */ ColorPicker)\n/* harmony export */ });\n/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292);\n/* harmony import */ var _tools_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(830);\n/* harmony import */ var _display_utils_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(419);\n\n\n\nclass ColorPicker {\n  #boundKeyDown = this.#keyDown.bind(this);\n  #boundPointerDown = this.#pointerDown.bind(this);\n  #button = null;\n  #buttonSwatch = null;\n  #defaultColor;\n  #dropdown = null;\n  #dropdownWasFromKeyboard = false;\n  #isMainColorPicker = false;\n  #editor = null;\n  #eventBus;\n  #uiManager = null;\n  #type;\n  static get _keyboardManager() {\n    return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, \"_keyboardManager\", new _tools_js__WEBPACK_IMPORTED_MODULE_1__.KeyboardManager([[[\"Escape\", \"mac+Escape\"], ColorPicker.prototype._hideDropdownFromKeyboard], [[\" \", \"mac+ \"], ColorPicker.prototype._colorSelectFromKeyboard], [[\"ArrowDown\", \"ArrowRight\", \"mac+ArrowDown\", \"mac+ArrowRight\"], ColorPicker.prototype._moveToNext], [[\"ArrowUp\", \"ArrowLeft\", \"mac+ArrowUp\", \"mac+ArrowLeft\"], ColorPicker.prototype._moveToPrevious], [[\"Home\", \"mac+Home\"], ColorPicker.prototype._moveToBeginning], [[\"End\", \"mac+End\"], ColorPicker.prototype._moveToEnd]]));\n  }\n  constructor({\n    editor = null,\n    uiManager = null\n  }) {\n    if (editor) {\n      this.#isMainColorPicker = false;\n      this.#type = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.HIGHLIGHT_COLOR;\n      this.#editor = editor;\n    } else {\n      this.#isMainColorPicker = true;\n      this.#type = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.HIGHLIGHT_DEFAULT_COLOR;\n    }\n    this.#uiManager = editor?._uiManager || uiManager;\n    this.#eventBus = this.#uiManager._eventBus;\n    this.#defaultColor = editor?.color || this.#uiManager?.highlightColors.values().next().value || \"#FFFF98\";\n  }\n  renderButton() {\n    const button = this.#button = document.createElement(\"button\");\n    button.className = \"colorPicker\";\n    button.tabIndex = \"0\";\n    button.setAttribute(\"data-l10n-id\", \"pdfjs-editor-colorpicker-button\");\n    button.setAttribute(\"aria-haspopup\", true);\n    button.addEventListener(\"click\", this.#openDropdown.bind(this));\n    button.addEventListener(\"keydown\", this.#boundKeyDown);\n    const swatch = this.#buttonSwatch = document.createElement(\"span\");\n    swatch.className = \"swatch\";\n    swatch.setAttribute(\"aria-hidden\", true);\n    swatch.style.backgroundColor = this.#defaultColor;\n    button.append(swatch);\n    return button;\n  }\n  renderMainDropdown() {\n    const dropdown = this.#dropdown = this.#getDropdownRoot();\n    dropdown.setAttribute(\"aria-orientation\", \"horizontal\");\n    dropdown.setAttribute(\"aria-labelledby\", \"highlightColorPickerLabel\");\n    return dropdown;\n  }\n  #getDropdownRoot() {\n    const div = document.createElement(\"div\");\n    div.addEventListener(\"contextmenu\", _display_utils_js__WEBPACK_IMPORTED_MODULE_2__.noContextMenu);\n    div.className = \"dropdown\";\n    div.role = \"listbox\";\n    div.setAttribute(\"aria-multiselectable\", false);\n    div.setAttribute(\"aria-orientation\", \"vertical\");\n    div.setAttribute(\"data-l10n-id\", \"pdfjs-editor-colorpicker-dropdown\");\n    for (const [name, color] of this.#uiManager.highlightColors) {\n      const button = document.createElement(\"button\");\n      button.tabIndex = \"0\";\n      button.role = \"option\";\n      button.setAttribute(\"data-color\", color);\n      button.title = name;\n      button.setAttribute(\"data-l10n-id\", `pdfjs-editor-colorpicker-${name}`);\n      const swatch = document.createElement(\"span\");\n      button.append(swatch);\n      swatch.className = \"swatch\";\n      swatch.style.backgroundColor = color;\n      button.setAttribute(\"aria-selected\", color === this.#defaultColor);\n      button.addEventListener(\"click\", this.#colorSelect.bind(this, color));\n      div.append(button);\n    }\n    div.addEventListener(\"keydown\", this.#boundKeyDown);\n    return div;\n  }\n  #colorSelect(color, event) {\n    event.stopPropagation();\n    this.#eventBus.dispatch(\"switchannotationeditorparams\", {\n      source: this,\n      type: this.#type,\n      value: color\n    });\n  }\n  _colorSelectFromKeyboard(event) {\n    if (event.target === this.#button) {\n      this.#openDropdown(event);\n      return;\n    }\n    const color = event.target.getAttribute(\"data-color\");\n    if (!color) {\n      return;\n    }\n    this.#colorSelect(color, event);\n  }\n  _moveToNext(event) {\n    if (!this.#isDropdownVisible) {\n      this.#openDropdown(event);\n      return;\n    }\n    if (event.target === this.#button) {\n      this.#dropdown.firstChild?.focus();\n      return;\n    }\n    event.target.nextSibling?.focus();\n  }\n  _moveToPrevious(event) {\n    if (event.target === this.#dropdown?.firstChild || event.target === this.#button) {\n      if (this.#isDropdownVisible) {\n        this._hideDropdownFromKeyboard();\n      }\n      return;\n    }\n    if (!this.#isDropdownVisible) {\n      this.#openDropdown(event);\n    }\n    event.target.previousSibling?.focus();\n  }\n  _moveToBeginning(event) {\n    if (!this.#isDropdownVisible) {\n      this.#openDropdown(event);\n      return;\n    }\n    this.#dropdown.firstChild?.focus();\n  }\n  _moveToEnd(event) {\n    if (!this.#isDropdownVisible) {\n      this.#openDropdown(event);\n      return;\n    }\n    this.#dropdown.lastChild?.focus();\n  }\n  #keyDown(event) {\n    ColorPicker._keyboardManager.exec(this, event);\n  }\n  #openDropdown(event) {\n    if (this.#isDropdownVisible) {\n      this.hideDropdown();\n      return;\n    }\n    this.#dropdownWasFromKeyboard = event.detail === 0;\n    window.addEventListener(\"pointerdown\", this.#boundPointerDown);\n    if (this.#dropdown) {\n      this.#dropdown.classList.remove(\"hidden\");\n      return;\n    }\n    const root = this.#dropdown = this.#getDropdownRoot();\n    this.#button.append(root);\n  }\n  #pointerDown(event) {\n    if (this.#dropdown?.contains(event.target)) {\n      return;\n    }\n    this.hideDropdown();\n  }\n  hideDropdown() {\n    this.#dropdown?.classList.add(\"hidden\");\n    window.removeEventListener(\"pointerdown\", this.#boundPointerDown);\n  }\n  get #isDropdownVisible() {\n    return this.#dropdown && !this.#dropdown.classList.contains(\"hidden\");\n  }\n  _hideDropdownFromKeyboard() {\n    if (this.#isMainColorPicker) {\n      return;\n    }\n    if (!this.#isDropdownVisible) {\n      this.#editor?.unselect();\n      return;\n    }\n    this.hideDropdown();\n    this.#button.focus({\n      preventScroll: true,\n      focusVisible: this.#dropdownWasFromKeyboard\n    });\n  }\n  updateColor(color) {\n    if (this.#buttonSwatch) {\n      this.#buttonSwatch.style.backgroundColor = color;\n    }\n    if (!this.#dropdown) {\n      return;\n    }\n    const i = this.#uiManager.highlightColors.values();\n    for (const child of this.#dropdown.children) {\n      child.setAttribute(\"aria-selected\", i.next().value === color);\n    }\n  }\n  destroy() {\n    this.#button?.remove();\n    this.#button = null;\n    this.#buttonSwatch = null;\n    this.#dropdown?.remove();\n    this.#dropdown = null;\n  }\n}\n\n\n/***/ }),\n\n/***/ 310:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, {\n  AnnotationEditor: () => (/* binding */ AnnotationEditor)\n});\n\n// EXTERNAL MODULE: ./src/display/editor/tools.js\nvar tools = __webpack_require__(830);\n// EXTERNAL MODULE: ./src/shared/util.js\nvar util = __webpack_require__(292);\n// EXTERNAL MODULE: ./src/display/display_utils.js\nvar display_utils = __webpack_require__(419);\n;// CONCATENATED MODULE: ./src/display/editor/alt_text.js\n\nclass AltText {\n  #altText = \"\";\n  #altTextDecorative = false;\n  #altTextButton = null;\n  #altTextTooltip = null;\n  #altTextTooltipTimeout = null;\n  #altTextWasFromKeyBoard = false;\n  #editor = null;\n  static _l10nPromise = null;\n  constructor(editor) {\n    this.#editor = editor;\n  }\n  static initialize(l10nPromise) {\n    AltText._l10nPromise ||= l10nPromise;\n  }\n  async render() {\n    const altText = this.#altTextButton = document.createElement(\"button\");\n    altText.className = \"altText\";\n    const msg = await AltText._l10nPromise.get(\"pdfjs-editor-alt-text-button-label\");\n    altText.textContent = msg;\n    altText.setAttribute(\"aria-label\", msg);\n    altText.tabIndex = \"0\";\n    altText.addEventListener(\"contextmenu\", display_utils.noContextMenu);\n    altText.addEventListener(\"pointerdown\", event => event.stopPropagation());\n    const onClick = event => {\n      event.preventDefault();\n      this.#editor._uiManager.editAltText(this.#editor);\n    };\n    altText.addEventListener(\"click\", onClick, {\n      capture: true\n    });\n    altText.addEventListener(\"keydown\", event => {\n      if (event.target === altText && event.key === \"Enter\") {\n        this.#altTextWasFromKeyBoard = true;\n        onClick(event);\n      }\n    });\n    await this.#setState();\n    return altText;\n  }\n  finish() {\n    if (!this.#altTextButton) {\n      return;\n    }\n    this.#altTextButton.focus({\n      focusVisible: this.#altTextWasFromKeyBoard\n    });\n    this.#altTextWasFromKeyBoard = false;\n  }\n  isEmpty() {\n    return !this.#altText && !this.#altTextDecorative;\n  }\n  get data() {\n    return {\n      altText: this.#altText,\n      decorative: this.#altTextDecorative\n    };\n  }\n  set data({\n    altText,\n    decorative\n  }) {\n    if (this.#altText === altText && this.#altTextDecorative === decorative) {\n      return;\n    }\n    this.#altText = altText;\n    this.#altTextDecorative = decorative;\n    this.#setState();\n  }\n  toggle(enabled = false) {\n    if (!this.#altTextButton) {\n      return;\n    }\n    if (!enabled && this.#altTextTooltipTimeout) {\n      clearTimeout(this.#altTextTooltipTimeout);\n      this.#altTextTooltipTimeout = null;\n    }\n    this.#altTextButton.disabled = !enabled;\n  }\n  destroy() {\n    this.#altTextButton?.remove();\n    this.#altTextButton = null;\n    this.#altTextTooltip = null;\n  }\n  async #setState() {\n    const button = this.#altTextButton;\n    if (!button) {\n      return;\n    }\n    if (!this.#altText && !this.#altTextDecorative) {\n      button.classList.remove(\"done\");\n      this.#altTextTooltip?.remove();\n      return;\n    }\n    button.classList.add(\"done\");\n    AltText._l10nPromise.get(\"pdfjs-editor-alt-text-edit-button-label\").then(msg => {\n      button.setAttribute(\"aria-label\", msg);\n    });\n    let tooltip = this.#altTextTooltip;\n    if (!tooltip) {\n      this.#altTextTooltip = tooltip = document.createElement(\"span\");\n      tooltip.className = \"tooltip\";\n      tooltip.setAttribute(\"role\", \"tooltip\");\n      const id = tooltip.id = `alt-text-tooltip-${this.#editor.id}`;\n      button.setAttribute(\"aria-describedby\", id);\n      const DELAY_TO_SHOW_TOOLTIP = 100;\n      button.addEventListener(\"mouseenter\", () => {\n        this.#altTextTooltipTimeout = setTimeout(() => {\n          this.#altTextTooltipTimeout = null;\n          this.#altTextTooltip.classList.add(\"show\");\n          this.#editor._reportTelemetry({\n            action: \"alt_text_tooltip\"\n          });\n        }, DELAY_TO_SHOW_TOOLTIP);\n      });\n      button.addEventListener(\"mouseleave\", () => {\n        if (this.#altTextTooltipTimeout) {\n          clearTimeout(this.#altTextTooltipTimeout);\n          this.#altTextTooltipTimeout = null;\n        }\n        this.#altTextTooltip?.classList.remove(\"show\");\n      });\n    }\n    tooltip.innerText = this.#altTextDecorative ? await AltText._l10nPromise.get(\"pdfjs-editor-alt-text-decorative-tooltip\") : this.#altText;\n    if (!tooltip.parentNode) {\n      button.append(tooltip);\n    }\n    const element = this.#editor.getImageForAltText();\n    element?.setAttribute(\"aria-describedby\", tooltip.id);\n  }\n}\n\n// EXTERNAL MODULE: ./src/display/editor/toolbar.js\nvar toolbar = __webpack_require__(362);\n;// CONCATENATED MODULE: ./src/display/editor/editor.js\n\n\n\n\n\nclass AnnotationEditor {\n  #allResizerDivs = null;\n  #altText = null;\n  #disabled = false;\n  #keepAspectRatio = false;\n  #resizersDiv = null;\n  #savedDimensions = null;\n  #boundFocusin = this.focusin.bind(this);\n  #boundFocusout = this.focusout.bind(this);\n  #editToolbar = null;\n  #focusedResizerName = \"\";\n  #hasBeenClicked = false;\n  #initialPosition = null;\n  #isEditing = false;\n  #isInEditMode = false;\n  #isResizerEnabledForKeyboard = false;\n  #moveInDOMTimeout = null;\n  #prevDragX = 0;\n  #prevDragY = 0;\n  #telemetryTimeouts = null;\n  _initialOptions = Object.create(null);\n  _isVisible = true;\n  _uiManager = null;\n  _focusEventsAllowed = true;\n  _l10nPromise = null;\n  #isDraggable = false;\n  #zIndex = AnnotationEditor._zIndex++;\n  static _borderLineWidth = -1;\n  static _colorManager = new tools.ColorManager();\n  static _zIndex = 1;\n  static _telemetryTimeout = 1000;\n  static get _resizerKeyboardManager() {\n    const resize = AnnotationEditor.prototype._resizeWithKeyboard;\n    const small = tools.AnnotationEditorUIManager.TRANSLATE_SMALL;\n    const big = tools.AnnotationEditorUIManager.TRANSLATE_BIG;\n    return (0,util.shadow)(this, \"_resizerKeyboardManager\", new tools.KeyboardManager([[[\"ArrowLeft\", \"mac+ArrowLeft\"], resize, {\n      args: [-small, 0]\n    }], [[\"ctrl+ArrowLeft\", \"mac+shift+ArrowLeft\"], resize, {\n      args: [-big, 0]\n    }], [[\"ArrowRight\", \"mac+ArrowRight\"], resize, {\n      args: [small, 0]\n    }], [[\"ctrl+ArrowRight\", \"mac+shift+ArrowRight\"], resize, {\n      args: [big, 0]\n    }], [[\"ArrowUp\", \"mac+ArrowUp\"], resize, {\n      args: [0, -small]\n    }], [[\"ctrl+ArrowUp\", \"mac+shift+ArrowUp\"], resize, {\n      args: [0, -big]\n    }], [[\"ArrowDown\", \"mac+ArrowDown\"], resize, {\n      args: [0, small]\n    }], [[\"ctrl+ArrowDown\", \"mac+shift+ArrowDown\"], resize, {\n      args: [0, big]\n    }], [[\"Escape\", \"mac+Escape\"], AnnotationEditor.prototype._stopResizingWithKeyboard]]));\n  }\n  constructor(parameters) {\n    if (this.constructor === AnnotationEditor) {\n      (0,util.unreachable)(\"Cannot initialize AnnotationEditor.\");\n    }\n    this.parent = parameters.parent;\n    this.id = parameters.id;\n    this.width = this.height = null;\n    this.pageIndex = parameters.parent.pageIndex;\n    this.name = parameters.name;\n    this.div = null;\n    this._uiManager = parameters.uiManager;\n    this.annotationElementId = null;\n    this._willKeepAspectRatio = false;\n    this._initialOptions.isCentered = parameters.isCentered;\n    this._structTreeParentId = null;\n    const {\n      rotation,\n      rawDims: {\n        pageWidth,\n        pageHeight,\n        pageX,\n        pageY\n      }\n    } = this.parent.viewport;\n    this.rotation = rotation;\n    this.pageRotation = (360 + rotation - this._uiManager.viewParameters.rotation) % 360;\n    this.pageDimensions = [pageWidth, pageHeight];\n    this.pageTranslation = [pageX, pageY];\n    const [width, height] = this.parentDimensions;\n    this.x = parameters.x / width;\n    this.y = parameters.y / height;\n    this.isAttachedToDOM = false;\n    this.deleted = false;\n  }\n  get editorType() {\n    return Object.getPrototypeOf(this).constructor._type;\n  }\n  static get _defaultLineColor() {\n    return (0,util.shadow)(this, \"_defaultLineColor\", this._colorManager.getHexCode(\"CanvasText\"));\n  }\n  static deleteAnnotationElement(editor) {\n    const fakeEditor = new FakeEditor({\n      id: editor.parent.getNextId(),\n      parent: editor.parent,\n      uiManager: editor._uiManager\n    });\n    fakeEditor.annotationElementId = editor.annotationElementId;\n    fakeEditor.deleted = true;\n    fakeEditor._uiManager.addToAnnotationStorage(fakeEditor);\n  }\n  static initialize(l10n, _uiManager, options) {\n    AnnotationEditor._l10nPromise ||= new Map([\"pdfjs-editor-alt-text-button-label\", \"pdfjs-editor-alt-text-edit-button-label\", \"pdfjs-editor-alt-text-decorative-tooltip\", \"pdfjs-editor-resizer-label-topLeft\", \"pdfjs-editor-resizer-label-topMiddle\", \"pdfjs-editor-resizer-label-topRight\", \"pdfjs-editor-resizer-label-middleRight\", \"pdfjs-editor-resizer-label-bottomRight\", \"pdfjs-editor-resizer-label-bottomMiddle\", \"pdfjs-editor-resizer-label-bottomLeft\", \"pdfjs-editor-resizer-label-middleLeft\"].map(str => [str, l10n.get(str.replaceAll(/([A-Z])/g, c => `-${c.toLowerCase()}`))]));\n    if (options?.strings) {\n      for (const str of options.strings) {\n        AnnotationEditor._l10nPromise.set(str, l10n.get(str));\n      }\n    }\n    if (AnnotationEditor._borderLineWidth !== -1) {\n      return;\n    }\n    const style = getComputedStyle(document.documentElement);\n    AnnotationEditor._borderLineWidth = parseFloat(style.getPropertyValue(\"--outline-width\")) || 0;\n  }\n  static updateDefaultParams(_type, _value) {}\n  static get defaultPropertiesToUpdate() {\n    return [];\n  }\n  static isHandlingMimeForPasting(mime) {\n    return false;\n  }\n  static paste(item, parent) {\n    (0,util.unreachable)(\"Not implemented\");\n  }\n  get propertiesToUpdate() {\n    return [];\n  }\n  get _isDraggable() {\n    return this.#isDraggable;\n  }\n  set _isDraggable(value) {\n    this.#isDraggable = value;\n    this.div?.classList.toggle(\"draggable\", value);\n  }\n  get isEnterHandled() {\n    return true;\n  }\n  center() {\n    const [pageWidth, pageHeight] = this.pageDimensions;\n    switch (this.parentRotation) {\n      case 90:\n        this.x -= this.height * pageHeight / (pageWidth * 2);\n        this.y += this.width * pageWidth / (pageHeight * 2);\n        break;\n      case 180:\n        this.x += this.width / 2;\n        this.y += this.height / 2;\n        break;\n      case 270:\n        this.x += this.height * pageHeight / (pageWidth * 2);\n        this.y -= this.width * pageWidth / (pageHeight * 2);\n        break;\n      default:\n        this.x -= this.width / 2;\n        this.y -= this.height / 2;\n        break;\n    }\n    this.fixAndSetPosition();\n  }\n  addCommands(params) {\n    this._uiManager.addCommands(params);\n  }\n  get currentLayer() {\n    return this._uiManager.currentLayer;\n  }\n  setInBackground() {\n    this.div.style.zIndex = 0;\n  }\n  setInForeground() {\n    this.div.style.zIndex = this.#zIndex;\n  }\n  setParent(parent) {\n    if (parent !== null) {\n      this.pageIndex = parent.pageIndex;\n      this.pageDimensions = parent.pageDimensions;\n    } else {\n      this.#stopResizing();\n    }\n    this.parent = parent;\n  }\n  focusin(event) {\n    if (!this._focusEventsAllowed) {\n      return;\n    }\n    if (!this.#hasBeenClicked) {\n      this.parent.setSelected(this);\n    } else {\n      this.#hasBeenClicked = false;\n    }\n  }\n  focusout(event) {\n    if (!this._focusEventsAllowed) {\n      return;\n    }\n    if (!this.isAttachedToDOM) {\n      return;\n    }\n    const target = event.relatedTarget;\n    if (target?.closest(`#${this.id}`)) {\n      return;\n    }\n    event.preventDefault();\n    if (!this.parent?.isMultipleSelection) {\n      this.commitOrRemove();\n    }\n  }\n  commitOrRemove() {\n    if (this.isEmpty()) {\n      this.remove();\n    } else {\n      this.commit();\n    }\n  }\n  commit() {\n    this.addToAnnotationStorage();\n  }\n  addToAnnotationStorage() {\n    this._uiManager.addToAnnotationStorage(this);\n  }\n  setAt(x, y, tx, ty) {\n    const [width, height] = this.parentDimensions;\n    [tx, ty] = this.screenToPageTranslation(tx, ty);\n    this.x = (x + tx) / width;\n    this.y = (y + ty) / height;\n    this.fixAndSetPosition();\n  }\n  #translate([width, height], x, y) {\n    [x, y] = this.screenToPageTranslation(x, y);\n    this.x += x / width;\n    this.y += y / height;\n    this.fixAndSetPosition();\n  }\n  translate(x, y) {\n    this.#translate(this.parentDimensions, x, y);\n  }\n  translateInPage(x, y) {\n    this.#initialPosition ||= [this.x, this.y];\n    this.#translate(this.pageDimensions, x, y);\n    this.div.scrollIntoView({\n      block: \"nearest\"\n    });\n  }\n  drag(tx, ty) {\n    this.#initialPosition ||= [this.x, this.y];\n    const [parentWidth, parentHeight] = this.parentDimensions;\n    this.x += tx / parentWidth;\n    this.y += ty / parentHeight;\n    if (this.parent && (this.x < 0 || this.x > 1 || this.y < 0 || this.y > 1)) {\n      const {\n        x,\n        y\n      } = this.div.getBoundingClientRect();\n      if (this.parent.findNewParent(this, x, y)) {\n        this.x -= Math.floor(this.x);\n        this.y -= Math.floor(this.y);\n      }\n    }\n    let {\n      x,\n      y\n    } = this;\n    const [bx, by] = this.getBaseTranslation();\n    x += bx;\n    y += by;\n    this.div.style.left = `${(100 * x).toFixed(2)}%`;\n    this.div.style.top = `${(100 * y).toFixed(2)}%`;\n    this.div.scrollIntoView({\n      block: \"nearest\"\n    });\n  }\n  get _hasBeenMoved() {\n    return !!this.#initialPosition && (this.#initialPosition[0] !== this.x || this.#initialPosition[1] !== this.y);\n  }\n  getBaseTranslation() {\n    const [parentWidth, parentHeight] = this.parentDimensions;\n    const {\n      _borderLineWidth\n    } = AnnotationEditor;\n    const x = _borderLineWidth / parentWidth;\n    const y = _borderLineWidth / parentHeight;\n    switch (this.rotation) {\n      case 90:\n        return [-x, y];\n      case 180:\n        return [x, y];\n      case 270:\n        return [x, -y];\n      default:\n        return [-x, -y];\n    }\n  }\n  get _mustFixPosition() {\n    return true;\n  }\n  fixAndSetPosition(rotation = this.rotation) {\n    const [pageWidth, pageHeight] = this.pageDimensions;\n    let {\n      x,\n      y,\n      width,\n      height\n    } = this;\n    width *= pageWidth;\n    height *= pageHeight;\n    x *= pageWidth;\n    y *= pageHeight;\n    if (this._mustFixPosition) {\n      switch (rotation) {\n        case 0:\n          x = Math.max(0, Math.min(pageWidth - width, x));\n          y = Math.max(0, Math.min(pageHeight - height, y));\n          break;\n        case 90:\n          x = Math.max(0, Math.min(pageWidth - height, x));\n          y = Math.min(pageHeight, Math.max(width, y));\n          break;\n        case 180:\n          x = Math.min(pageWidth, Math.max(width, x));\n          y = Math.min(pageHeight, Math.max(height, y));\n          break;\n        case 270:\n          x = Math.min(pageWidth, Math.max(height, x));\n          y = Math.max(0, Math.min(pageHeight - width, y));\n          break;\n      }\n    }\n    this.x = x /= pageWidth;\n    this.y = y /= pageHeight;\n    const [bx, by] = this.getBaseTranslation();\n    x += bx;\n    y += by;\n    const {\n      style\n    } = this.div;\n    style.left = `${(100 * x).toFixed(2)}%`;\n    style.top = `${(100 * y).toFixed(2)}%`;\n    this.moveInDOM();\n  }\n  static #rotatePoint(x, y, angle) {\n    switch (angle) {\n      case 90:\n        return [y, -x];\n      case 180:\n        return [-x, -y];\n      case 270:\n        return [-y, x];\n      default:\n        return [x, y];\n    }\n  }\n  screenToPageTranslation(x, y) {\n    return AnnotationEditor.#rotatePoint(x, y, this.parentRotation);\n  }\n  pageTranslationToScreen(x, y) {\n    return AnnotationEditor.#rotatePoint(x, y, 360 - this.parentRotation);\n  }\n  #getRotationMatrix(rotation) {\n    switch (rotation) {\n      case 90:\n        {\n          const [pageWidth, pageHeight] = this.pageDimensions;\n          return [0, -pageWidth / pageHeight, pageHeight / pageWidth, 0];\n        }\n      case 180:\n        return [-1, 0, 0, -1];\n      case 270:\n        {\n          const [pageWidth, pageHeight] = this.pageDimensions;\n          return [0, pageWidth / pageHeight, -pageHeight / pageWidth, 0];\n        }\n      default:\n        return [1, 0, 0, 1];\n    }\n  }\n  get parentScale() {\n    return this._uiManager.viewParameters.realScale;\n  }\n  get parentRotation() {\n    return (this._uiManager.viewParameters.rotation + this.pageRotation) % 360;\n  }\n  get parentDimensions() {\n    const {\n      parentScale,\n      pageDimensions: [pageWidth, pageHeight]\n    } = this;\n    const scaledWidth = pageWidth * parentScale;\n    const scaledHeight = pageHeight * parentScale;\n    return util.FeatureTest.isCSSRoundSupported ? [Math.round(scaledWidth), Math.round(scaledHeight)] : [scaledWidth, scaledHeight];\n  }\n  setDims(width, height) {\n    const [parentWidth, parentHeight] = this.parentDimensions;\n    this.div.style.width = `${(100 * width / parentWidth).toFixed(2)}%`;\n    if (!this.#keepAspectRatio) {\n      this.div.style.height = `${(100 * height / parentHeight).toFixed(2)}%`;\n    }\n  }\n  fixDims() {\n    const {\n      style\n    } = this.div;\n    const {\n      height,\n      width\n    } = style;\n    const widthPercent = width.endsWith(\"%\");\n    const heightPercent = !this.#keepAspectRatio && height.endsWith(\"%\");\n    if (widthPercent && heightPercent) {\n      return;\n    }\n    const [parentWidth, parentHeight] = this.parentDimensions;\n    if (!widthPercent) {\n      style.width = `${(100 * parseFloat(width) / parentWidth).toFixed(2)}%`;\n    }\n    if (!this.#keepAspectRatio && !heightPercent) {\n      style.height = `${(100 * parseFloat(height) / parentHeight).toFixed(2)}%`;\n    }\n  }\n  getInitialTranslation() {\n    return [0, 0];\n  }\n  #createResizers() {\n    if (this.#resizersDiv) {\n      return;\n    }\n    this.#resizersDiv = document.createElement(\"div\");\n    this.#resizersDiv.classList.add(\"resizers\");\n    const classes = this._willKeepAspectRatio ? [\"topLeft\", \"topRight\", \"bottomRight\", \"bottomLeft\"] : [\"topLeft\", \"topMiddle\", \"topRight\", \"middleRight\", \"bottomRight\", \"bottomMiddle\", \"bottomLeft\", \"middleLeft\"];\n    for (const name of classes) {\n      const div = document.createElement(\"div\");\n      this.#resizersDiv.append(div);\n      div.classList.add(\"resizer\", name);\n      div.setAttribute(\"data-resizer-name\", name);\n      div.addEventListener(\"pointerdown\", this.#resizerPointerdown.bind(this, name));\n      div.addEventListener(\"contextmenu\", display_utils.noContextMenu);\n      div.tabIndex = -1;\n    }\n    this.div.prepend(this.#resizersDiv);\n  }\n  #resizerPointerdown(name, event) {\n    event.preventDefault();\n    const {\n      isMac\n    } = util.FeatureTest.platform;\n    if (event.button !== 0 || event.ctrlKey && isMac) {\n      return;\n    }\n    this.#altText?.toggle(false);\n    const boundResizerPointermove = this.#resizerPointermove.bind(this, name);\n    const savedDraggable = this._isDraggable;\n    this._isDraggable = false;\n    const pointerMoveOptions = {\n      passive: true,\n      capture: true\n    };\n    this.parent.togglePointerEvents(false);\n    window.addEventListener(\"pointermove\", boundResizerPointermove, pointerMoveOptions);\n    window.addEventListener(\"contextmenu\", display_utils.noContextMenu);\n    const savedX = this.x;\n    const savedY = this.y;\n    const savedWidth = this.width;\n    const savedHeight = this.height;\n    const savedParentCursor = this.parent.div.style.cursor;\n    const savedCursor = this.div.style.cursor;\n    this.div.style.cursor = this.parent.div.style.cursor = window.getComputedStyle(event.target).cursor;\n    const pointerUpCallback = () => {\n      this.parent.togglePointerEvents(true);\n      this.#altText?.toggle(true);\n      this._isDraggable = savedDraggable;\n      window.removeEventListener(\"pointerup\", pointerUpCallback);\n      window.removeEventListener(\"blur\", pointerUpCallback);\n      window.removeEventListener(\"pointermove\", boundResizerPointermove, pointerMoveOptions);\n      window.removeEventListener(\"contextmenu\", display_utils.noContextMenu);\n      this.parent.div.style.cursor = savedParentCursor;\n      this.div.style.cursor = savedCursor;\n      this.#addResizeToUndoStack(savedX, savedY, savedWidth, savedHeight);\n    };\n    window.addEventListener(\"pointerup\", pointerUpCallback);\n    window.addEventListener(\"blur\", pointerUpCallback);\n  }\n  #addResizeToUndoStack(savedX, savedY, savedWidth, savedHeight) {\n    const newX = this.x;\n    const newY = this.y;\n    const newWidth = this.width;\n    const newHeight = this.height;\n    if (newX === savedX && newY === savedY && newWidth === savedWidth && newHeight === savedHeight) {\n      return;\n    }\n    this.addCommands({\n      cmd: () => {\n        this.width = newWidth;\n        this.height = newHeight;\n        this.x = newX;\n        this.y = newY;\n        const [parentWidth, parentHeight] = this.parentDimensions;\n        this.setDims(parentWidth * newWidth, parentHeight * newHeight);\n        this.fixAndSetPosition();\n      },\n      undo: () => {\n        this.width = savedWidth;\n        this.height = savedHeight;\n        this.x = savedX;\n        this.y = savedY;\n        const [parentWidth, parentHeight] = this.parentDimensions;\n        this.setDims(parentWidth * savedWidth, parentHeight * savedHeight);\n        this.fixAndSetPosition();\n      },\n      mustExec: true\n    });\n  }\n  #resizerPointermove(name, event) {\n    const [parentWidth, parentHeight] = this.parentDimensions;\n    const savedX = this.x;\n    const savedY = this.y;\n    const savedWidth = this.width;\n    const savedHeight = this.height;\n    const minWidth = AnnotationEditor.MIN_SIZE / parentWidth;\n    const minHeight = AnnotationEditor.MIN_SIZE / parentHeight;\n    const round = x => Math.round(x * 10000) / 10000;\n    const rotationMatrix = this.#getRotationMatrix(this.rotation);\n    const transf = (x, y) => [rotationMatrix[0] * x + rotationMatrix[2] * y, rotationMatrix[1] * x + rotationMatrix[3] * y];\n    const invRotationMatrix = this.#getRotationMatrix(360 - this.rotation);\n    const invTransf = (x, y) => [invRotationMatrix[0] * x + invRotationMatrix[2] * y, invRotationMatrix[1] * x + invRotationMatrix[3] * y];\n    let getPoint;\n    let getOpposite;\n    let isDiagonal = false;\n    let isHorizontal = false;\n    switch (name) {\n      case \"topLeft\":\n        isDiagonal = true;\n        getPoint = (w, h) => [0, 0];\n        getOpposite = (w, h) => [w, h];\n        break;\n      case \"topMiddle\":\n        getPoint = (w, h) => [w / 2, 0];\n        getOpposite = (w, h) => [w / 2, h];\n        break;\n      case \"topRight\":\n        isDiagonal = true;\n        getPoint = (w, h) => [w, 0];\n        getOpposite = (w, h) => [0, h];\n        break;\n      case \"middleRight\":\n        isHorizontal = true;\n        getPoint = (w, h) => [w, h / 2];\n        getOpposite = (w, h) => [0, h / 2];\n        break;\n      case \"bottomRight\":\n        isDiagonal = true;\n        getPoint = (w, h) => [w, h];\n        getOpposite = (w, h) => [0, 0];\n        break;\n      case \"bottomMiddle\":\n        getPoint = (w, h) => [w / 2, h];\n        getOpposite = (w, h) => [w / 2, 0];\n        break;\n      case \"bottomLeft\":\n        isDiagonal = true;\n        getPoint = (w, h) => [0, h];\n        getOpposite = (w, h) => [w, 0];\n        break;\n      case \"middleLeft\":\n        isHorizontal = true;\n        getPoint = (w, h) => [0, h / 2];\n        getOpposite = (w, h) => [w, h / 2];\n        break;\n    }\n    const point = getPoint(savedWidth, savedHeight);\n    const oppositePoint = getOpposite(savedWidth, savedHeight);\n    let transfOppositePoint = transf(...oppositePoint);\n    const oppositeX = round(savedX + transfOppositePoint[0]);\n    const oppositeY = round(savedY + transfOppositePoint[1]);\n    let ratioX = 1;\n    let ratioY = 1;\n    let [deltaX, deltaY] = this.screenToPageTranslation(event.movementX, event.movementY);\n    [deltaX, deltaY] = invTransf(deltaX / parentWidth, deltaY / parentHeight);\n    if (isDiagonal) {\n      const oldDiag = Math.hypot(savedWidth, savedHeight);\n      ratioX = ratioY = Math.max(Math.min(Math.hypot(oppositePoint[0] - point[0] - deltaX, oppositePoint[1] - point[1] - deltaY) / oldDiag, 1 / savedWidth, 1 / savedHeight), minWidth / savedWidth, minHeight / savedHeight);\n    } else if (isHorizontal) {\n      ratioX = Math.max(minWidth, Math.min(1, Math.abs(oppositePoint[0] - point[0] - deltaX))) / savedWidth;\n    } else {\n      ratioY = Math.max(minHeight, Math.min(1, Math.abs(oppositePoint[1] - point[1] - deltaY))) / savedHeight;\n    }\n    const newWidth = round(savedWidth * ratioX);\n    const newHeight = round(savedHeight * ratioY);\n    transfOppositePoint = transf(...getOpposite(newWidth, newHeight));\n    const newX = oppositeX - transfOppositePoint[0];\n    const newY = oppositeY - transfOppositePoint[1];\n    this.width = newWidth;\n    this.height = newHeight;\n    this.x = newX;\n    this.y = newY;\n    this.setDims(parentWidth * newWidth, parentHeight * newHeight);\n    this.fixAndSetPosition();\n  }\n  altTextFinish() {\n    this.#altText?.finish();\n  }\n  async addEditToolbar() {\n    if (this.#editToolbar || this.#isInEditMode) {\n      return this.#editToolbar;\n    }\n    this.#editToolbar = new toolbar.EditorToolbar(this);\n    this.div.append(this.#editToolbar.render());\n    if (this.#altText) {\n      this.#editToolbar.addAltTextButton(await this.#altText.render());\n    }\n    return this.#editToolbar;\n  }\n  removeEditToolbar() {\n    if (!this.#editToolbar) {\n      return;\n    }\n    this.#editToolbar.remove();\n    this.#editToolbar = null;\n    this.#altText?.destroy();\n  }\n  getClientDimensions() {\n    return this.div.getBoundingClientRect();\n  }\n  async addAltTextButton() {\n    if (this.#altText) {\n      return;\n    }\n    AltText.initialize(AnnotationEditor._l10nPromise);\n    this.#altText = new AltText(this);\n    await this.addEditToolbar();\n  }\n  get altTextData() {\n    return this.#altText?.data;\n  }\n  set altTextData(data) {\n    if (!this.#altText) {\n      return;\n    }\n    this.#altText.data = data;\n  }\n  hasAltText() {\n    return !this.#altText?.isEmpty();\n  }\n  render() {\n    this.div = document.createElement(\"div\");\n    this.div.setAttribute(\"data-editor-rotation\", (360 - this.rotation) % 360);\n    this.div.className = this.name;\n    this.div.setAttribute(\"id\", this.id);\n    this.div.tabIndex = this.#disabled ? -1 : 0;\n    if (!this._isVisible) {\n      this.div.classList.add(\"hidden\");\n    }\n    this.setInForeground();\n    this.div.addEventListener(\"focusin\", this.#boundFocusin);\n    this.div.addEventListener(\"focusout\", this.#boundFocusout);\n    const [parentWidth, parentHeight] = this.parentDimensions;\n    if (this.parentRotation % 180 !== 0) {\n      this.div.style.maxWidth = `${(100 * parentHeight / parentWidth).toFixed(2)}%`;\n      this.div.style.maxHeight = `${(100 * parentWidth / parentHeight).toFixed(2)}%`;\n    }\n    const [tx, ty] = this.getInitialTranslation();\n    this.translate(tx, ty);\n    (0,tools.bindEvents)(this, this.div, [\"pointerdown\"]);\n    return this.div;\n  }\n  pointerdown(event) {\n    const {\n      isMac\n    } = util.FeatureTest.platform;\n    if (event.button !== 0 || event.ctrlKey && isMac) {\n      event.preventDefault();\n      return;\n    }\n    this.#hasBeenClicked = true;\n    if (this._isDraggable) {\n      this.#setUpDragSession(event);\n      return;\n    }\n    this.#selectOnPointerEvent(event);\n  }\n  #selectOnPointerEvent(event) {\n    const {\n      isMac\n    } = util.FeatureTest.platform;\n    if (event.ctrlKey && !isMac || event.shiftKey || event.metaKey && isMac) {\n      this.parent.toggleSelected(this);\n    } else {\n      this.parent.setSelected(this);\n    }\n  }\n  #setUpDragSession(event) {\n    const isSelected = this._uiManager.isSelected(this);\n    this._uiManager.setUpDragSession();\n    let pointerMoveOptions, pointerMoveCallback;\n    if (isSelected) {\n      this.div.classList.add(\"moving\");\n      pointerMoveOptions = {\n        passive: true,\n        capture: true\n      };\n      this.#prevDragX = event.clientX;\n      this.#prevDragY = event.clientY;\n      pointerMoveCallback = e => {\n        const {\n          clientX: x,\n          clientY: y\n        } = e;\n        const [tx, ty] = this.screenToPageTranslation(x - this.#prevDragX, y - this.#prevDragY);\n        this.#prevDragX = x;\n        this.#prevDragY = y;\n        this._uiManager.dragSelectedEditors(tx, ty);\n      };\n      window.addEventListener(\"pointermove\", pointerMoveCallback, pointerMoveOptions);\n    }\n    const pointerUpCallback = () => {\n      window.removeEventListener(\"pointerup\", pointerUpCallback);\n      window.removeEventListener(\"blur\", pointerUpCallback);\n      if (isSelected) {\n        this.div.classList.remove(\"moving\");\n        window.removeEventListener(\"pointermove\", pointerMoveCallback, pointerMoveOptions);\n      }\n      this.#hasBeenClicked = false;\n      if (!this._uiManager.endDragSession()) {\n        this.#selectOnPointerEvent(event);\n      }\n    };\n    window.addEventListener(\"pointerup\", pointerUpCallback);\n    window.addEventListener(\"blur\", pointerUpCallback);\n  }\n  moveInDOM() {\n    if (this.#moveInDOMTimeout) {\n      clearTimeout(this.#moveInDOMTimeout);\n    }\n    this.#moveInDOMTimeout = setTimeout(() => {\n      this.#moveInDOMTimeout = null;\n      this.parent?.moveEditorInDOM(this);\n    }, 0);\n  }\n  _setParentAndPosition(parent, x, y) {\n    parent.changeParent(this);\n    this.x = x;\n    this.y = y;\n    this.fixAndSetPosition();\n  }\n  getRect(tx, ty, rotation = this.rotation) {\n    const scale = this.parentScale;\n    const [pageWidth, pageHeight] = this.pageDimensions;\n    const [pageX, pageY] = this.pageTranslation;\n    const shiftX = tx / scale;\n    const shiftY = ty / scale;\n    const x = this.x * pageWidth;\n    const y = this.y * pageHeight;\n    const width = this.width * pageWidth;\n    const height = this.height * pageHeight;\n    switch (rotation) {\n      case 0:\n        return [x + shiftX + pageX, pageHeight - y - shiftY - height + pageY, x + shiftX + width + pageX, pageHeight - y - shiftY + pageY];\n      case 90:\n        return [x + shiftY + pageX, pageHeight - y + shiftX + pageY, x + shiftY + height + pageX, pageHeight - y + shiftX + width + pageY];\n      case 180:\n        return [x - shiftX - width + pageX, pageHeight - y + shiftY + pageY, x - shiftX + pageX, pageHeight - y + shiftY + height + pageY];\n      case 270:\n        return [x - shiftY - height + pageX, pageHeight - y - shiftX - width + pageY, x - shiftY + pageX, pageHeight - y - shiftX + pageY];\n      default:\n        throw new Error(\"Invalid rotation\");\n    }\n  }\n  getRectInCurrentCoords(rect, pageHeight) {\n    const [x1, y1, x2, y2] = rect;\n    const width = x2 - x1;\n    const height = y2 - y1;\n    switch (this.rotation) {\n      case 0:\n        return [x1, pageHeight - y2, width, height];\n      case 90:\n        return [x1, pageHeight - y1, height, width];\n      case 180:\n        return [x2, pageHeight - y1, width, height];\n      case 270:\n        return [x2, pageHeight - y2, height, width];\n      default:\n        throw new Error(\"Invalid rotation\");\n    }\n  }\n  onceAdded() {}\n  isEmpty() {\n    return false;\n  }\n  enableEditMode() {\n    this.#isInEditMode = true;\n  }\n  disableEditMode() {\n    this.#isInEditMode = false;\n  }\n  isInEditMode() {\n    return this.#isInEditMode;\n  }\n  shouldGetKeyboardEvents() {\n    return this.#isResizerEnabledForKeyboard;\n  }\n  needsToBeRebuilt() {\n    return this.div && !this.isAttachedToDOM;\n  }\n  rebuild() {\n    this.div?.addEventListener(\"focusin\", this.#boundFocusin);\n    this.div?.addEventListener(\"focusout\", this.#boundFocusout);\n  }\n  rotate(_angle) {}\n  serialize(isForCopying = false, context = null) {\n    (0,util.unreachable)(\"An editor must be serializable\");\n  }\n  static deserialize(data, parent, uiManager) {\n    const editor = new this.prototype.constructor({\n      parent,\n      id: parent.getNextId(),\n      uiManager\n    });\n    editor.rotation = data.rotation;\n    const [pageWidth, pageHeight] = editor.pageDimensions;\n    const [x, y, width, height] = editor.getRectInCurrentCoords(data.rect, pageHeight);\n    editor.x = x / pageWidth;\n    editor.y = y / pageHeight;\n    editor.width = width / pageWidth;\n    editor.height = height / pageHeight;\n    return editor;\n  }\n  get hasBeenModified() {\n    return !!this.annotationElementId && (this.deleted || this.serialize() !== null);\n  }\n  remove() {\n    this.div.removeEventListener(\"focusin\", this.#boundFocusin);\n    this.div.removeEventListener(\"focusout\", this.#boundFocusout);\n    if (!this.isEmpty()) {\n      this.commit();\n    }\n    if (this.parent) {\n      this.parent.remove(this);\n    } else {\n      this._uiManager.removeEditor(this);\n    }\n    if (this.#moveInDOMTimeout) {\n      clearTimeout(this.#moveInDOMTimeout);\n      this.#moveInDOMTimeout = null;\n    }\n    this.#stopResizing();\n    this.removeEditToolbar();\n    if (this.#telemetryTimeouts) {\n      for (const timeout of this.#telemetryTimeouts.values()) {\n        clearTimeout(timeout);\n      }\n      this.#telemetryTimeouts = null;\n    }\n    this.parent = null;\n  }\n  get isResizable() {\n    return false;\n  }\n  makeResizable() {\n    if (this.isResizable) {\n      this.#createResizers();\n      this.#resizersDiv.classList.remove(\"hidden\");\n      (0,tools.bindEvents)(this, this.div, [\"keydown\"]);\n    }\n  }\n  get toolbarPosition() {\n    return null;\n  }\n  keydown(event) {\n    if (!this.isResizable || event.target !== this.div || event.key !== \"Enter\") {\n      return;\n    }\n    this._uiManager.setSelected(this);\n    this.#savedDimensions = {\n      savedX: this.x,\n      savedY: this.y,\n      savedWidth: this.width,\n      savedHeight: this.height\n    };\n    const children = this.#resizersDiv.children;\n    if (!this.#allResizerDivs) {\n      this.#allResizerDivs = Array.from(children);\n      const boundResizerKeydown = this.#resizerKeydown.bind(this);\n      const boundResizerBlur = this.#resizerBlur.bind(this);\n      for (const div of this.#allResizerDivs) {\n        const name = div.getAttribute(\"data-resizer-name\");\n        div.setAttribute(\"role\", \"spinbutton\");\n        div.addEventListener(\"keydown\", boundResizerKeydown);\n        div.addEventListener(\"blur\", boundResizerBlur);\n        div.addEventListener(\"focus\", this.#resizerFocus.bind(this, name));\n        AnnotationEditor._l10nPromise.get(`pdfjs-editor-resizer-label-${name}`).then(msg => div.setAttribute(\"aria-label\", msg));\n      }\n    }\n    const first = this.#allResizerDivs[0];\n    let firstPosition = 0;\n    for (const div of children) {\n      if (div === first) {\n        break;\n      }\n      firstPosition++;\n    }\n    const nextFirstPosition = (360 - this.rotation + this.parentRotation) % 360 / 90 * (this.#allResizerDivs.length / 4);\n    if (nextFirstPosition !== firstPosition) {\n      if (nextFirstPosition < firstPosition) {\n        for (let i = 0; i < firstPosition - nextFirstPosition; i++) {\n          this.#resizersDiv.append(this.#resizersDiv.firstChild);\n        }\n      } else if (nextFirstPosition > firstPosition) {\n        for (let i = 0; i < nextFirstPosition - firstPosition; i++) {\n          this.#resizersDiv.firstChild.before(this.#resizersDiv.lastChild);\n        }\n      }\n      let i = 0;\n      for (const child of children) {\n        const div = this.#allResizerDivs[i++];\n        const name = div.getAttribute(\"data-resizer-name\");\n        AnnotationEditor._l10nPromise.get(`pdfjs-editor-resizer-label-${name}`).then(msg => child.setAttribute(\"aria-label\", msg));\n      }\n    }\n    this.#setResizerTabIndex(0);\n    this.#isResizerEnabledForKeyboard = true;\n    this.#resizersDiv.firstChild.focus({\n      focusVisible: true\n    });\n    event.preventDefault();\n    event.stopImmediatePropagation();\n  }\n  #resizerKeydown(event) {\n    AnnotationEditor._resizerKeyboardManager.exec(this, event);\n  }\n  #resizerBlur(event) {\n    if (this.#isResizerEnabledForKeyboard && event.relatedTarget?.parentNode !== this.#resizersDiv) {\n      this.#stopResizing();\n    }\n  }\n  #resizerFocus(name) {\n    this.#focusedResizerName = this.#isResizerEnabledForKeyboard ? name : \"\";\n  }\n  #setResizerTabIndex(value) {\n    if (!this.#allResizerDivs) {\n      return;\n    }\n    for (const div of this.#allResizerDivs) {\n      div.tabIndex = value;\n    }\n  }\n  _resizeWithKeyboard(x, y) {\n    if (!this.#isResizerEnabledForKeyboard) {\n      return;\n    }\n    this.#resizerPointermove(this.#focusedResizerName, {\n      movementX: x,\n      movementY: y\n    });\n  }\n  #stopResizing() {\n    this.#isResizerEnabledForKeyboard = false;\n    this.#setResizerTabIndex(-1);\n    if (this.#savedDimensions) {\n      const {\n        savedX,\n        savedY,\n        savedWidth,\n        savedHeight\n      } = this.#savedDimensions;\n      this.#addResizeToUndoStack(savedX, savedY, savedWidth, savedHeight);\n      this.#savedDimensions = null;\n    }\n  }\n  _stopResizingWithKeyboard() {\n    this.#stopResizing();\n    this.div.focus();\n  }\n  select() {\n    this.makeResizable();\n    this.div?.classList.add(\"selectedEditor\");\n    if (!this.#editToolbar) {\n      this.addEditToolbar().then(() => {\n        if (this.div?.classList.contains(\"selectedEditor\")) {\n          this.#editToolbar?.show();\n        }\n      });\n      return;\n    }\n    this.#editToolbar?.show();\n  }\n  unselect() {\n    this.#resizersDiv?.classList.add(\"hidden\");\n    this.div?.classList.remove(\"selectedEditor\");\n    if (this.div?.contains(document.activeElement)) {\n      this._uiManager.currentLayer.div.focus({\n        preventScroll: true\n      });\n    }\n    this.#editToolbar?.hide();\n  }\n  updateParams(type, value) {}\n  disableEditing() {}\n  enableEditing() {}\n  enterInEditMode() {}\n  getImageForAltText() {\n    return null;\n  }\n  get contentDiv() {\n    return this.div;\n  }\n  get isEditing() {\n    return this.#isEditing;\n  }\n  set isEditing(value) {\n    this.#isEditing = value;\n    if (!this.parent) {\n      return;\n    }\n    if (value) {\n      this.parent.setSelected(this);\n      this.parent.setActiveEditor(this);\n    } else {\n      this.parent.setActiveEditor(null);\n    }\n  }\n  setAspectRatio(width, height) {\n    this.#keepAspectRatio = true;\n    const aspectRatio = width / height;\n    const {\n      style\n    } = this.div;\n    style.aspectRatio = aspectRatio;\n    style.height = \"auto\";\n  }\n  static get MIN_SIZE() {\n    return 16;\n  }\n  static canCreateNewEmptyEditor() {\n    return true;\n  }\n  get telemetryInitialData() {\n    return {\n      action: \"added\"\n    };\n  }\n  get telemetryFinalData() {\n    return null;\n  }\n  _reportTelemetry(data, mustWait = false) {\n    if (mustWait) {\n      this.#telemetryTimeouts ||= new Map();\n      const {\n        action\n      } = data;\n      let timeout = this.#telemetryTimeouts.get(action);\n      if (timeout) {\n        clearTimeout(timeout);\n      }\n      timeout = setTimeout(() => {\n        this._reportTelemetry(data);\n        this.#telemetryTimeouts.delete(action);\n        if (this.#telemetryTimeouts.size === 0) {\n          this.#telemetryTimeouts = null;\n        }\n      }, AnnotationEditor._telemetryTimeout);\n      this.#telemetryTimeouts.set(action, timeout);\n      return;\n    }\n    data.type ||= this.editorType;\n    this._uiManager._eventBus.dispatch(\"reporttelemetry\", {\n      source: this,\n      details: {\n        type: \"editing\",\n        data\n      }\n    });\n  }\n  show(visible = this._isVisible) {\n    this.div.classList.toggle(\"hidden\", !visible);\n    this._isVisible = visible;\n  }\n  enable() {\n    if (this.div) {\n      this.div.tabIndex = 0;\n    }\n    this.#disabled = false;\n  }\n  disable() {\n    if (this.div) {\n      this.div.tabIndex = -1;\n    }\n    this.#disabled = true;\n  }\n  renderAnnotationElement(annotation) {\n    let content = annotation.container.querySelector(\".annotationContent\");\n    if (!content) {\n      content = document.createElement(\"div\");\n      content.classList.add(\"annotationContent\", this.editorType);\n      annotation.container.prepend(content);\n    } else if (content.nodeName === \"CANVAS\") {\n      const canvas = content;\n      content = document.createElement(\"div\");\n      content.classList.add(\"annotationContent\", this.editorType);\n      canvas.before(content);\n    }\n    return content;\n  }\n  resetAnnotationElement(annotation) {\n    const {\n      firstChild\n    } = annotation.container;\n    if (firstChild.nodeName === \"DIV\" && firstChild.classList.contains(\"annotationContent\")) {\n      firstChild.remove();\n    }\n  }\n}\nclass FakeEditor extends AnnotationEditor {\n  constructor(params) {\n    super(params);\n    this.annotationElementId = params.annotationElementId;\n    this.deleted = true;\n  }\n  serialize() {\n    return {\n      id: this.annotationElementId,\n      deleted: true,\n      pageIndex: this.pageIndex\n    };\n  }\n}\n\n\n/***/ }),\n\n/***/ 61:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   FreeOutliner: () => (/* binding */ FreeOutliner),\n/* harmony export */   Outliner: () => (/* binding */ Outliner)\n/* harmony export */ });\n/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292);\n\nclass Outliner {\n  #box;\n  #verticalEdges = [];\n  #intervals = [];\n  constructor(boxes, borderWidth = 0, innerMargin = 0, isLTR = true) {\n    let minX = Infinity;\n    let maxX = -Infinity;\n    let minY = Infinity;\n    let maxY = -Infinity;\n    const NUMBER_OF_DIGITS = 4;\n    const EPSILON = 10 ** -NUMBER_OF_DIGITS;\n    for (const {\n      x,\n      y,\n      width,\n      height\n    } of boxes) {\n      const x1 = Math.floor((x - borderWidth) / EPSILON) * EPSILON;\n      const x2 = Math.ceil((x + width + borderWidth) / EPSILON) * EPSILON;\n      const y1 = Math.floor((y - borderWidth) / EPSILON) * EPSILON;\n      const y2 = Math.ceil((y + height + borderWidth) / EPSILON) * EPSILON;\n      const left = [x1, y1, y2, true];\n      const right = [x2, y1, y2, false];\n      this.#verticalEdges.push(left, right);\n      minX = Math.min(minX, x1);\n      maxX = Math.max(maxX, x2);\n      minY = Math.min(minY, y1);\n      maxY = Math.max(maxY, y2);\n    }\n    const bboxWidth = maxX - minX + 2 * innerMargin;\n    const bboxHeight = maxY - minY + 2 * innerMargin;\n    const shiftedMinX = minX - innerMargin;\n    const shiftedMinY = minY - innerMargin;\n    const lastEdge = this.#verticalEdges.at(isLTR ? -1 : -2);\n    const lastPoint = [lastEdge[0], lastEdge[2]];\n    for (const edge of this.#verticalEdges) {\n      const [x, y1, y2] = edge;\n      edge[0] = (x - shiftedMinX) / bboxWidth;\n      edge[1] = (y1 - shiftedMinY) / bboxHeight;\n      edge[2] = (y2 - shiftedMinY) / bboxHeight;\n    }\n    this.#box = {\n      x: shiftedMinX,\n      y: shiftedMinY,\n      width: bboxWidth,\n      height: bboxHeight,\n      lastPoint\n    };\n  }\n  getOutlines() {\n    this.#verticalEdges.sort((a, b) => a[0] - b[0] || a[1] - b[1] || a[2] - b[2]);\n    const outlineVerticalEdges = [];\n    for (const edge of this.#verticalEdges) {\n      if (edge[3]) {\n        outlineVerticalEdges.push(...this.#breakEdge(edge));\n        this.#insert(edge);\n      } else {\n        this.#remove(edge);\n        outlineVerticalEdges.push(...this.#breakEdge(edge));\n      }\n    }\n    return this.#getOutlines(outlineVerticalEdges);\n  }\n  #getOutlines(outlineVerticalEdges) {\n    const edges = [];\n    const allEdges = new Set();\n    for (const edge of outlineVerticalEdges) {\n      const [x, y1, y2] = edge;\n      edges.push([x, y1, edge], [x, y2, edge]);\n    }\n    edges.sort((a, b) => a[1] - b[1] || a[0] - b[0]);\n    for (let i = 0, ii = edges.length; i < ii; i += 2) {\n      const edge1 = edges[i][2];\n      const edge2 = edges[i + 1][2];\n      edge1.push(edge2);\n      edge2.push(edge1);\n      allEdges.add(edge1);\n      allEdges.add(edge2);\n    }\n    const outlines = [];\n    let outline;\n    while (allEdges.size > 0) {\n      const edge = allEdges.values().next().value;\n      let [x, y1, y2, edge1, edge2] = edge;\n      allEdges.delete(edge);\n      let lastPointX = x;\n      let lastPointY = y1;\n      outline = [x, y2];\n      outlines.push(outline);\n      while (true) {\n        let e;\n        if (allEdges.has(edge1)) {\n          e = edge1;\n        } else if (allEdges.has(edge2)) {\n          e = edge2;\n        } else {\n          break;\n        }\n        allEdges.delete(e);\n        [x, y1, y2, edge1, edge2] = e;\n        if (lastPointX !== x) {\n          outline.push(lastPointX, lastPointY, x, lastPointY === y1 ? y1 : y2);\n          lastPointX = x;\n        }\n        lastPointY = lastPointY === y1 ? y2 : y1;\n      }\n      outline.push(lastPointX, lastPointY);\n    }\n    return new HighlightOutline(outlines, this.#box);\n  }\n  #binarySearch(y) {\n    const array = this.#intervals;\n    let start = 0;\n    let end = array.length - 1;\n    while (start <= end) {\n      const middle = start + end >> 1;\n      const y1 = array[middle][0];\n      if (y1 === y) {\n        return middle;\n      }\n      if (y1 < y) {\n        start = middle + 1;\n      } else {\n        end = middle - 1;\n      }\n    }\n    return end + 1;\n  }\n  #insert([, y1, y2]) {\n    const index = this.#binarySearch(y1);\n    this.#intervals.splice(index, 0, [y1, y2]);\n  }\n  #remove([, y1, y2]) {\n    const index = this.#binarySearch(y1);\n    for (let i = index; i < this.#intervals.length; i++) {\n      const [start, end] = this.#intervals[i];\n      if (start !== y1) {\n        break;\n      }\n      if (start === y1 && end === y2) {\n        this.#intervals.splice(i, 1);\n        return;\n      }\n    }\n    for (let i = index - 1; i >= 0; i--) {\n      const [start, end] = this.#intervals[i];\n      if (start !== y1) {\n        break;\n      }\n      if (start === y1 && end === y2) {\n        this.#intervals.splice(i, 1);\n        return;\n      }\n    }\n  }\n  #breakEdge(edge) {\n    const [x, y1, y2] = edge;\n    const results = [[x, y1, y2]];\n    const index = this.#binarySearch(y2);\n    for (let i = 0; i < index; i++) {\n      const [start, end] = this.#intervals[i];\n      for (let j = 0, jj = results.length; j < jj; j++) {\n        const [, y3, y4] = results[j];\n        if (end <= y3 || y4 <= start) {\n          continue;\n        }\n        if (y3 >= start) {\n          if (y4 > end) {\n            results[j][1] = end;\n          } else {\n            if (jj === 1) {\n              return [];\n            }\n            results.splice(j, 1);\n            j--;\n            jj--;\n          }\n          continue;\n        }\n        results[j][2] = start;\n        if (y4 > end) {\n          results.push([x, end, y4]);\n        }\n      }\n    }\n    return results;\n  }\n}\nclass Outline {\n  toSVGPath() {\n    throw new Error(\"Abstract method `toSVGPath` must be implemented.\");\n  }\n  get box() {\n    throw new Error(\"Abstract getter `box` must be implemented.\");\n  }\n  serialize(_bbox, _rotation) {\n    throw new Error(\"Abstract method `serialize` must be implemented.\");\n  }\n  get free() {\n    return this instanceof FreeHighlightOutline;\n  }\n}\nclass HighlightOutline extends Outline {\n  #box;\n  #outlines;\n  constructor(outlines, box) {\n    super();\n    this.#outlines = outlines;\n    this.#box = box;\n  }\n  toSVGPath() {\n    const buffer = [];\n    for (const polygon of this.#outlines) {\n      let [prevX, prevY] = polygon;\n      buffer.push(`M${prevX} ${prevY}`);\n      for (let i = 2; i < polygon.length; i += 2) {\n        const x = polygon[i];\n        const y = polygon[i + 1];\n        if (x === prevX) {\n          buffer.push(`V${y}`);\n          prevY = y;\n        } else if (y === prevY) {\n          buffer.push(`H${x}`);\n          prevX = x;\n        }\n      }\n      buffer.push(\"Z\");\n    }\n    return buffer.join(\" \");\n  }\n  serialize([blX, blY, trX, trY], _rotation) {\n    const outlines = [];\n    const width = trX - blX;\n    const height = trY - blY;\n    for (const outline of this.#outlines) {\n      const points = new Array(outline.length);\n      for (let i = 0; i < outline.length; i += 2) {\n        points[i] = blX + outline[i] * width;\n        points[i + 1] = trY - outline[i + 1] * height;\n      }\n      outlines.push(points);\n    }\n    return outlines;\n  }\n  get box() {\n    return this.#box;\n  }\n}\nclass FreeOutliner {\n  #box;\n  #bottom = [];\n  #innerMargin;\n  #isLTR;\n  #top = [];\n  #last = new Float64Array(18);\n  #lastX;\n  #lastY;\n  #min;\n  #min_dist;\n  #scaleFactor;\n  #thickness;\n  #points = [];\n  static #MIN_DIST = 8;\n  static #MIN_DIFF = 2;\n  static #MIN = FreeOutliner.#MIN_DIST + FreeOutliner.#MIN_DIFF;\n  constructor({\n    x,\n    y\n  }, box, scaleFactor, thickness, isLTR, innerMargin = 0) {\n    this.#box = box;\n    this.#thickness = thickness * scaleFactor;\n    this.#isLTR = isLTR;\n    this.#last.set([NaN, NaN, NaN, NaN, x, y], 6);\n    this.#innerMargin = innerMargin;\n    this.#min_dist = FreeOutliner.#MIN_DIST * scaleFactor;\n    this.#min = FreeOutliner.#MIN * scaleFactor;\n    this.#scaleFactor = scaleFactor;\n    this.#points.push(x, y);\n  }\n  get free() {\n    return true;\n  }\n  isEmpty() {\n    return isNaN(this.#last[8]);\n  }\n  #getLastCoords() {\n    const lastTop = this.#last.subarray(4, 6);\n    const lastBottom = this.#last.subarray(16, 18);\n    const [x, y, width, height] = this.#box;\n    return [(this.#lastX + (lastTop[0] - lastBottom[0]) / 2 - x) / width, (this.#lastY + (lastTop[1] - lastBottom[1]) / 2 - y) / height, (this.#lastX + (lastBottom[0] - lastTop[0]) / 2 - x) / width, (this.#lastY + (lastBottom[1] - lastTop[1]) / 2 - y) / height];\n  }\n  add({\n    x,\n    y\n  }) {\n    this.#lastX = x;\n    this.#lastY = y;\n    const [layerX, layerY, layerWidth, layerHeight] = this.#box;\n    let [x1, y1, x2, y2] = this.#last.subarray(8, 12);\n    const diffX = x - x2;\n    const diffY = y - y2;\n    const d = Math.hypot(diffX, diffY);\n    if (d < this.#min) {\n      return false;\n    }\n    const diffD = d - this.#min_dist;\n    const K = diffD / d;\n    const shiftX = K * diffX;\n    const shiftY = K * diffY;\n    let x0 = x1;\n    let y0 = y1;\n    x1 = x2;\n    y1 = y2;\n    x2 += shiftX;\n    y2 += shiftY;\n    this.#points?.push(x, y);\n    const nX = -shiftY / diffD;\n    const nY = shiftX / diffD;\n    const thX = nX * this.#thickness;\n    const thY = nY * this.#thickness;\n    this.#last.set(this.#last.subarray(2, 8), 0);\n    this.#last.set([x2 + thX, y2 + thY], 4);\n    this.#last.set(this.#last.subarray(14, 18), 12);\n    this.#last.set([x2 - thX, y2 - thY], 16);\n    if (isNaN(this.#last[6])) {\n      if (this.#top.length === 0) {\n        this.#last.set([x1 + thX, y1 + thY], 2);\n        this.#top.push(NaN, NaN, NaN, NaN, (x1 + thX - layerX) / layerWidth, (y1 + thY - layerY) / layerHeight);\n        this.#last.set([x1 - thX, y1 - thY], 14);\n        this.#bottom.push(NaN, NaN, NaN, NaN, (x1 - thX - layerX) / layerWidth, (y1 - thY - layerY) / layerHeight);\n      }\n      this.#last.set([x0, y0, x1, y1, x2, y2], 6);\n      return !this.isEmpty();\n    }\n    this.#last.set([x0, y0, x1, y1, x2, y2], 6);\n    const angle = Math.abs(Math.atan2(y0 - y1, x0 - x1) - Math.atan2(shiftY, shiftX));\n    if (angle < Math.PI / 2) {\n      [x1, y1, x2, y2] = this.#last.subarray(2, 6);\n      this.#top.push(NaN, NaN, NaN, NaN, ((x1 + x2) / 2 - layerX) / layerWidth, ((y1 + y2) / 2 - layerY) / layerHeight);\n      [x1, y1, x0, y0] = this.#last.subarray(14, 18);\n      this.#bottom.push(NaN, NaN, NaN, NaN, ((x0 + x1) / 2 - layerX) / layerWidth, ((y0 + y1) / 2 - layerY) / layerHeight);\n      return true;\n    }\n    [x0, y0, x1, y1, x2, y2] = this.#last.subarray(0, 6);\n    this.#top.push(((x0 + 5 * x1) / 6 - layerX) / layerWidth, ((y0 + 5 * y1) / 6 - layerY) / layerHeight, ((5 * x1 + x2) / 6 - layerX) / layerWidth, ((5 * y1 + y2) / 6 - layerY) / layerHeight, ((x1 + x2) / 2 - layerX) / layerWidth, ((y1 + y2) / 2 - layerY) / layerHeight);\n    [x2, y2, x1, y1, x0, y0] = this.#last.subarray(12, 18);\n    this.#bottom.push(((x0 + 5 * x1) / 6 - layerX) / layerWidth, ((y0 + 5 * y1) / 6 - layerY) / layerHeight, ((5 * x1 + x2) / 6 - layerX) / layerWidth, ((5 * y1 + y2) / 6 - layerY) / layerHeight, ((x1 + x2) / 2 - layerX) / layerWidth, ((y1 + y2) / 2 - layerY) / layerHeight);\n    return true;\n  }\n  toSVGPath() {\n    if (this.isEmpty()) {\n      return \"\";\n    }\n    const top = this.#top;\n    const bottom = this.#bottom;\n    const lastTop = this.#last.subarray(4, 6);\n    const lastBottom = this.#last.subarray(16, 18);\n    const [x, y, width, height] = this.#box;\n    const [lastTopX, lastTopY, lastBottomX, lastBottomY] = this.#getLastCoords();\n    if (isNaN(this.#last[6]) && !this.isEmpty()) {\n      return `M${(this.#last[2] - x) / width} ${(this.#last[3] - y) / height} L${(this.#last[4] - x) / width} ${(this.#last[5] - y) / height} L${lastTopX} ${lastTopY} L${lastBottomX} ${lastBottomY} L${(this.#last[16] - x) / width} ${(this.#last[17] - y) / height} L${(this.#last[14] - x) / width} ${(this.#last[15] - y) / height} Z`;\n    }\n    const buffer = [];\n    buffer.push(`M${top[4]} ${top[5]}`);\n    for (let i = 6; i < top.length; i += 6) {\n      if (isNaN(top[i])) {\n        buffer.push(`L${top[i + 4]} ${top[i + 5]}`);\n      } else {\n        buffer.push(`C${top[i]} ${top[i + 1]} ${top[i + 2]} ${top[i + 3]} ${top[i + 4]} ${top[i + 5]}`);\n      }\n    }\n    buffer.push(`L${(lastTop[0] - x) / width} ${(lastTop[1] - y) / height} L${lastTopX} ${lastTopY} L${lastBottomX} ${lastBottomY} L${(lastBottom[0] - x) / width} ${(lastBottom[1] - y) / height}`);\n    for (let i = bottom.length - 6; i >= 6; i -= 6) {\n      if (isNaN(bottom[i])) {\n        buffer.push(`L${bottom[i + 4]} ${bottom[i + 5]}`);\n      } else {\n        buffer.push(`C${bottom[i]} ${bottom[i + 1]} ${bottom[i + 2]} ${bottom[i + 3]} ${bottom[i + 4]} ${bottom[i + 5]}`);\n      }\n    }\n    buffer.push(`L${bottom[4]} ${bottom[5]} Z`);\n    return buffer.join(\" \");\n  }\n  getOutlines() {\n    const top = this.#top;\n    const bottom = this.#bottom;\n    const last = this.#last;\n    const lastTop = last.subarray(4, 6);\n    const lastBottom = last.subarray(16, 18);\n    const [layerX, layerY, layerWidth, layerHeight] = this.#box;\n    const points = new Float64Array((this.#points?.length ?? 0) + 2);\n    for (let i = 0, ii = points.length - 2; i < ii; i += 2) {\n      points[i] = (this.#points[i] - layerX) / layerWidth;\n      points[i + 1] = (this.#points[i + 1] - layerY) / layerHeight;\n    }\n    points[points.length - 2] = (this.#lastX - layerX) / layerWidth;\n    points[points.length - 1] = (this.#lastY - layerY) / layerHeight;\n    const [lastTopX, lastTopY, lastBottomX, lastBottomY] = this.#getLastCoords();\n    if (isNaN(last[6]) && !this.isEmpty()) {\n      const outline = new Float64Array(36);\n      outline.set([NaN, NaN, NaN, NaN, (last[2] - layerX) / layerWidth, (last[3] - layerY) / layerHeight, NaN, NaN, NaN, NaN, (last[4] - layerX) / layerWidth, (last[5] - layerY) / layerHeight, NaN, NaN, NaN, NaN, lastTopX, lastTopY, NaN, NaN, NaN, NaN, lastBottomX, lastBottomY, NaN, NaN, NaN, NaN, (last[16] - layerX) / layerWidth, (last[17] - layerY) / layerHeight, NaN, NaN, NaN, NaN, (last[14] - layerX) / layerWidth, (last[15] - layerY) / layerHeight], 0);\n      return new FreeHighlightOutline(outline, points, this.#box, this.#scaleFactor, this.#innerMargin, this.#isLTR);\n    }\n    const outline = new Float64Array(this.#top.length + 24 + this.#bottom.length);\n    let N = top.length;\n    for (let i = 0; i < N; i += 2) {\n      if (isNaN(top[i])) {\n        outline[i] = outline[i + 1] = NaN;\n        continue;\n      }\n      outline[i] = top[i];\n      outline[i + 1] = top[i + 1];\n    }\n    outline.set([NaN, NaN, NaN, NaN, (lastTop[0] - layerX) / layerWidth, (lastTop[1] - layerY) / layerHeight, NaN, NaN, NaN, NaN, lastTopX, lastTopY, NaN, NaN, NaN, NaN, lastBottomX, lastBottomY, NaN, NaN, NaN, NaN, (lastBottom[0] - layerX) / layerWidth, (lastBottom[1] - layerY) / layerHeight], N);\n    N += 24;\n    for (let i = bottom.length - 6; i >= 6; i -= 6) {\n      for (let j = 0; j < 6; j += 2) {\n        if (isNaN(bottom[i + j])) {\n          outline[N] = outline[N + 1] = NaN;\n          N += 2;\n          continue;\n        }\n        outline[N] = bottom[i + j];\n        outline[N + 1] = bottom[i + j + 1];\n        N += 2;\n      }\n    }\n    outline.set([NaN, NaN, NaN, NaN, bottom[4], bottom[5]], N);\n    return new FreeHighlightOutline(outline, points, this.#box, this.#scaleFactor, this.#innerMargin, this.#isLTR);\n  }\n}\nclass FreeHighlightOutline extends Outline {\n  #box;\n  #bbox = null;\n  #innerMargin;\n  #isLTR;\n  #points;\n  #scaleFactor;\n  #outline;\n  constructor(outline, points, box, scaleFactor, innerMargin, isLTR) {\n    super();\n    this.#outline = outline;\n    this.#points = points;\n    this.#box = box;\n    this.#scaleFactor = scaleFactor;\n    this.#innerMargin = innerMargin;\n    this.#isLTR = isLTR;\n    this.#computeMinMax(isLTR);\n    const {\n      x,\n      y,\n      width,\n      height\n    } = this.#bbox;\n    for (let i = 0, ii = outline.length; i < ii; i += 2) {\n      outline[i] = (outline[i] - x) / width;\n      outline[i + 1] = (outline[i + 1] - y) / height;\n    }\n    for (let i = 0, ii = points.length; i < ii; i += 2) {\n      points[i] = (points[i] - x) / width;\n      points[i + 1] = (points[i + 1] - y) / height;\n    }\n  }\n  toSVGPath() {\n    const buffer = [`M${this.#outline[4]} ${this.#outline[5]}`];\n    for (let i = 6, ii = this.#outline.length; i < ii; i += 6) {\n      if (isNaN(this.#outline[i])) {\n        buffer.push(`L${this.#outline[i + 4]} ${this.#outline[i + 5]}`);\n        continue;\n      }\n      buffer.push(`C${this.#outline[i]} ${this.#outline[i + 1]} ${this.#outline[i + 2]} ${this.#outline[i + 3]} ${this.#outline[i + 4]} ${this.#outline[i + 5]}`);\n    }\n    buffer.push(\"Z\");\n    return buffer.join(\" \");\n  }\n  serialize([blX, blY, trX, trY], rotation) {\n    const width = trX - blX;\n    const height = trY - blY;\n    let outline;\n    let points;\n    switch (rotation) {\n      case 0:\n        outline = this.#rescale(this.#outline, blX, trY, width, -height);\n        points = this.#rescale(this.#points, blX, trY, width, -height);\n        break;\n      case 90:\n        outline = this.#rescaleAndSwap(this.#outline, blX, blY, width, height);\n        points = this.#rescaleAndSwap(this.#points, blX, blY, width, height);\n        break;\n      case 180:\n        outline = this.#rescale(this.#outline, trX, blY, -width, height);\n        points = this.#rescale(this.#points, trX, blY, -width, height);\n        break;\n      case 270:\n        outline = this.#rescaleAndSwap(this.#outline, trX, trY, -width, -height);\n        points = this.#rescaleAndSwap(this.#points, trX, trY, -width, -height);\n        break;\n    }\n    return {\n      outline: Array.from(outline),\n      points: [Array.from(points)]\n    };\n  }\n  #rescale(src, tx, ty, sx, sy) {\n    const dest = new Float64Array(src.length);\n    for (let i = 0, ii = src.length; i < ii; i += 2) {\n      dest[i] = tx + src[i] * sx;\n      dest[i + 1] = ty + src[i + 1] * sy;\n    }\n    return dest;\n  }\n  #rescaleAndSwap(src, tx, ty, sx, sy) {\n    const dest = new Float64Array(src.length);\n    for (let i = 0, ii = src.length; i < ii; i += 2) {\n      dest[i] = tx + src[i + 1] * sx;\n      dest[i + 1] = ty + src[i] * sy;\n    }\n    return dest;\n  }\n  #computeMinMax(isLTR) {\n    const outline = this.#outline;\n    let lastX = outline[4];\n    let lastY = outline[5];\n    let minX = lastX;\n    let minY = lastY;\n    let maxX = lastX;\n    let maxY = lastY;\n    let lastPointX = lastX;\n    let lastPointY = lastY;\n    const ltrCallback = isLTR ? Math.max : Math.min;\n    for (let i = 6, ii = outline.length; i < ii; i += 6) {\n      if (isNaN(outline[i])) {\n        minX = Math.min(minX, outline[i + 4]);\n        minY = Math.min(minY, outline[i + 5]);\n        maxX = Math.max(maxX, outline[i + 4]);\n        maxY = Math.max(maxY, outline[i + 5]);\n        if (lastPointY < outline[i + 5]) {\n          lastPointX = outline[i + 4];\n          lastPointY = outline[i + 5];\n        } else if (lastPointY === outline[i + 5]) {\n          lastPointX = ltrCallback(lastPointX, outline[i + 4]);\n        }\n      } else {\n        const bbox = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.Util.bezierBoundingBox(lastX, lastY, ...outline.slice(i, i + 6));\n        minX = Math.min(minX, bbox[0]);\n        minY = Math.min(minY, bbox[1]);\n        maxX = Math.max(maxX, bbox[2]);\n        maxY = Math.max(maxY, bbox[3]);\n        if (lastPointY < bbox[3]) {\n          lastPointX = bbox[2];\n          lastPointY = bbox[3];\n        } else if (lastPointY === bbox[3]) {\n          lastPointX = ltrCallback(lastPointX, bbox[2]);\n        }\n      }\n      lastX = outline[i + 4];\n      lastY = outline[i + 5];\n    }\n    const x = minX - this.#innerMargin,\n      y = minY - this.#innerMargin,\n      width = maxX - minX + 2 * this.#innerMargin,\n      height = maxY - minY + 2 * this.#innerMargin;\n    this.#bbox = {\n      x,\n      y,\n      width,\n      height,\n      lastPoint: [lastPointX, lastPointY]\n    };\n  }\n  get box() {\n    return this.#bbox;\n  }\n  getNewOutline(thickness, innerMargin) {\n    const {\n      x,\n      y,\n      width,\n      height\n    } = this.#bbox;\n    const [layerX, layerY, layerWidth, layerHeight] = this.#box;\n    const sx = width * layerWidth;\n    const sy = height * layerHeight;\n    const tx = x * layerWidth + layerX;\n    const ty = y * layerHeight + layerY;\n    const outliner = new FreeOutliner({\n      x: this.#points[0] * sx + tx,\n      y: this.#points[1] * sy + ty\n    }, this.#box, this.#scaleFactor, thickness, this.#isLTR, innerMargin ?? this.#innerMargin);\n    for (let i = 2; i < this.#points.length; i += 2) {\n      outliner.add({\n        x: this.#points[i] * sx + tx,\n        y: this.#points[i + 1] * sy + ty\n      });\n    }\n    return outliner.getOutlines();\n  }\n}\n\n\n/***/ }),\n\n/***/ 362:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   EditorToolbar: () => (/* binding */ EditorToolbar),\n/* harmony export */   HighlightToolbar: () => (/* binding */ HighlightToolbar)\n/* harmony export */ });\n/* harmony import */ var _display_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(419);\n\nclass EditorToolbar {\n  #toolbar = null;\n  #colorPicker = null;\n  #editor;\n  #buttons = null;\n  constructor(editor) {\n    this.#editor = editor;\n  }\n  render() {\n    const editToolbar = this.#toolbar = document.createElement(\"div\");\n    editToolbar.className = \"editToolbar\";\n    editToolbar.setAttribute(\"role\", \"toolbar\");\n    editToolbar.addEventListener(\"contextmenu\", _display_utils_js__WEBPACK_IMPORTED_MODULE_0__.noContextMenu);\n    editToolbar.addEventListener(\"pointerdown\", EditorToolbar.#pointerDown);\n    const buttons = this.#buttons = document.createElement(\"div\");\n    buttons.className = \"buttons\";\n    editToolbar.append(buttons);\n    const position = this.#editor.toolbarPosition;\n    if (position) {\n      const {\n        style\n      } = editToolbar;\n      const x = this.#editor._uiManager.direction === \"ltr\" ? 1 - position[0] : position[0];\n      style.insetInlineEnd = `${100 * x}%`;\n      style.top = `calc(${100 * position[1]}% + var(--editor-toolbar-vert-offset))`;\n    }\n    this.#addDeleteButton();\n    return editToolbar;\n  }\n  static #pointerDown(e) {\n    e.stopPropagation();\n  }\n  #focusIn(e) {\n    this.#editor._focusEventsAllowed = false;\n    e.preventDefault();\n    e.stopPropagation();\n  }\n  #focusOut(e) {\n    this.#editor._focusEventsAllowed = true;\n    e.preventDefault();\n    e.stopPropagation();\n  }\n  #addListenersToElement(element) {\n    element.addEventListener(\"focusin\", this.#focusIn.bind(this), {\n      capture: true\n    });\n    element.addEventListener(\"focusout\", this.#focusOut.bind(this), {\n      capture: true\n    });\n    element.addEventListener(\"contextmenu\", _display_utils_js__WEBPACK_IMPORTED_MODULE_0__.noContextMenu);\n  }\n  hide() {\n    this.#toolbar.classList.add(\"hidden\");\n    this.#colorPicker?.hideDropdown();\n  }\n  show() {\n    this.#toolbar.classList.remove(\"hidden\");\n  }\n  #addDeleteButton() {\n    const button = document.createElement(\"button\");\n    button.className = \"delete\";\n    button.tabIndex = 0;\n    button.setAttribute(\"data-l10n-id\", `pdfjs-editor-remove-${this.#editor.editorType}-button`);\n    this.#addListenersToElement(button);\n    button.addEventListener(\"click\", e => {\n      this.#editor._uiManager.delete();\n    });\n    this.#buttons.append(button);\n  }\n  get #divider() {\n    const divider = document.createElement(\"div\");\n    divider.className = \"divider\";\n    return divider;\n  }\n  addAltTextButton(button) {\n    this.#addListenersToElement(button);\n    this.#buttons.prepend(button, this.#divider);\n  }\n  addColorPicker(colorPicker) {\n    this.#colorPicker = colorPicker;\n    const button = colorPicker.renderButton();\n    this.#addListenersToElement(button);\n    this.#buttons.prepend(button, this.#divider);\n  }\n  remove() {\n    this.#toolbar.remove();\n    this.#colorPicker?.destroy();\n    this.#colorPicker = null;\n  }\n}\nclass HighlightToolbar {\n  #buttons = null;\n  #toolbar = null;\n  #uiManager;\n  constructor(uiManager) {\n    this.#uiManager = uiManager;\n  }\n  #render() {\n    const editToolbar = this.#toolbar = document.createElement(\"div\");\n    editToolbar.className = \"editToolbar\";\n    editToolbar.setAttribute(\"role\", \"toolbar\");\n    editToolbar.addEventListener(\"contextmenu\", _display_utils_js__WEBPACK_IMPORTED_MODULE_0__.noContextMenu);\n    const buttons = this.#buttons = document.createElement(\"div\");\n    buttons.className = \"buttons\";\n    editToolbar.append(buttons);\n    this.#addHighlightButton();\n    return editToolbar;\n  }\n  #getLastPoint(boxes, isLTR) {\n    let lastY = 0;\n    let lastX = 0;\n    for (const box of boxes) {\n      const y = box.y + box.height;\n      if (y < lastY) {\n        continue;\n      }\n      const x = box.x + (isLTR ? box.width : 0);\n      if (y > lastY) {\n        lastX = x;\n        lastY = y;\n        continue;\n      }\n      if (isLTR) {\n        if (x > lastX) {\n          lastX = x;\n        }\n      } else if (x < lastX) {\n        lastX = x;\n      }\n    }\n    return [isLTR ? 1 - lastX : lastX, lastY];\n  }\n  show(parent, boxes, isLTR) {\n    const [x, y] = this.#getLastPoint(boxes, isLTR);\n    const {\n      style\n    } = this.#toolbar ||= this.#render();\n    parent.append(this.#toolbar);\n    style.insetInlineEnd = `${100 * x}%`;\n    style.top = `calc(${100 * y}% + var(--editor-toolbar-vert-offset))`;\n  }\n  hide() {\n    this.#toolbar.remove();\n  }\n  #addHighlightButton() {\n    const button = document.createElement(\"button\");\n    button.className = \"highlightButton\";\n    button.tabIndex = 0;\n    button.setAttribute(\"data-l10n-id\", `pdfjs-highlight-floating-button1`);\n    const span = document.createElement(\"span\");\n    button.append(span);\n    span.className = \"visuallyHidden\";\n    span.setAttribute(\"data-l10n-id\", \"pdfjs-highlight-floating-button-label\");\n    button.addEventListener(\"contextmenu\", _display_utils_js__WEBPACK_IMPORTED_MODULE_0__.noContextMenu);\n    button.addEventListener(\"click\", () => {\n      this.#uiManager.highlightSelection(\"floating_button\");\n    });\n    this.#buttons.append(button);\n  }\n}\n\n\n/***/ }),\n\n/***/ 830:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   AnnotationEditorUIManager: () => (/* binding */ AnnotationEditorUIManager),\n/* harmony export */   ColorManager: () => (/* binding */ ColorManager),\n/* harmony export */   KeyboardManager: () => (/* binding */ KeyboardManager),\n/* harmony export */   bindEvents: () => (/* binding */ bindEvents),\n/* harmony export */   opacityToHex: () => (/* binding */ opacityToHex)\n/* harmony export */ });\n/* unused harmony export CommandManager */\n/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292);\n/* harmony import */ var _display_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(419);\n/* harmony import */ var _toolbar_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(362);\n\n\n\nfunction bindEvents(obj, element, names) {\n  for (const name of names) {\n    element.addEventListener(name, obj[name].bind(obj));\n  }\n}\nfunction opacityToHex(opacity) {\n  return Math.round(Math.min(255, Math.max(1, 255 * opacity))).toString(16).padStart(2, \"0\");\n}\nclass IdManager {\n  #id = 0;\n  constructor() {}\n  get id() {\n    return `${_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorPrefix}${this.#id++}`;\n  }\n}\nclass ImageManager {\n  #baseId = (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.getUuid)();\n  #id = 0;\n  #cache = null;\n  static get _isSVGFittingCanvas() {\n    const svg = `data:image/svg+xml;charset=UTF-8,<svg viewBox=\"0 0 1 1\" width=\"1\" height=\"1\" xmlns=\"http://www.w3.org/2000/svg\"><rect width=\"1\" height=\"1\" style=\"fill:red;\"/></svg>`;\n    const canvas = new OffscreenCanvas(1, 3);\n    const ctx = canvas.getContext(\"2d\");\n    const image = new Image();\n    image.src = svg;\n    const promise = image.decode().then(() => {\n      ctx.drawImage(image, 0, 0, 1, 1, 0, 0, 1, 3);\n      return new Uint32Array(ctx.getImageData(0, 0, 1, 1).data.buffer)[0] === 0;\n    });\n    return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, \"_isSVGFittingCanvas\", promise);\n  }\n  async #get(key, rawData) {\n    this.#cache ||= new Map();\n    let data = this.#cache.get(key);\n    if (data === null) {\n      return null;\n    }\n    if (data?.bitmap) {\n      data.refCounter += 1;\n      return data;\n    }\n    try {\n      data ||= {\n        bitmap: null,\n        id: `image_${this.#baseId}_${this.#id++}`,\n        refCounter: 0,\n        isSvg: false\n      };\n      let image;\n      if (typeof rawData === \"string\") {\n        data.url = rawData;\n        image = await (0,_display_utils_js__WEBPACK_IMPORTED_MODULE_1__.fetchData)(rawData, \"blob\");\n      } else {\n        image = data.file = rawData;\n      }\n      if (image.type === \"image/svg+xml\") {\n        const mustRemoveAspectRatioPromise = ImageManager._isSVGFittingCanvas;\n        const fileReader = new FileReader();\n        const imageElement = new Image();\n        const imagePromise = new Promise((resolve, reject) => {\n          imageElement.onload = () => {\n            data.bitmap = imageElement;\n            data.isSvg = true;\n            resolve();\n          };\n          fileReader.onload = async () => {\n            const url = data.svgUrl = fileReader.result;\n            imageElement.src = (await mustRemoveAspectRatioPromise) ? `${url}#svgView(preserveAspectRatio(none))` : url;\n          };\n          imageElement.onerror = fileReader.onerror = reject;\n        });\n        fileReader.readAsDataURL(image);\n        await imagePromise;\n      } else {\n        data.bitmap = await createImageBitmap(image);\n      }\n      data.refCounter = 1;\n    } catch (e) {\n      console.error(e);\n      data = null;\n    }\n    this.#cache.set(key, data);\n    if (data) {\n      this.#cache.set(data.id, data);\n    }\n    return data;\n  }\n  async getFromFile(file) {\n    const {\n      lastModified,\n      name,\n      size,\n      type\n    } = file;\n    return this.#get(`${lastModified}_${name}_${size}_${type}`, file);\n  }\n  async getFromUrl(url) {\n    return this.#get(url, url);\n  }\n  async getFromId(id) {\n    this.#cache ||= new Map();\n    const data = this.#cache.get(id);\n    if (!data) {\n      return null;\n    }\n    if (data.bitmap) {\n      data.refCounter += 1;\n      return data;\n    }\n    if (data.file) {\n      return this.getFromFile(data.file);\n    }\n    return this.getFromUrl(data.url);\n  }\n  getSvgUrl(id) {\n    const data = this.#cache.get(id);\n    if (!data?.isSvg) {\n      return null;\n    }\n    return data.svgUrl;\n  }\n  deleteId(id) {\n    this.#cache ||= new Map();\n    const data = this.#cache.get(id);\n    if (!data) {\n      return;\n    }\n    data.refCounter -= 1;\n    if (data.refCounter !== 0) {\n      return;\n    }\n    data.bitmap = null;\n  }\n  isValidId(id) {\n    return id.startsWith(`image_${this.#baseId}_`);\n  }\n}\nclass CommandManager {\n  #commands = [];\n  #locked = false;\n  #maxSize;\n  #position = -1;\n  constructor(maxSize = 128) {\n    this.#maxSize = maxSize;\n  }\n  add({\n    cmd,\n    undo,\n    post,\n    mustExec,\n    type = NaN,\n    overwriteIfSameType = false,\n    keepUndo = false\n  }) {\n    if (mustExec) {\n      cmd();\n    }\n    if (this.#locked) {\n      return;\n    }\n    const save = {\n      cmd,\n      undo,\n      post,\n      type\n    };\n    if (this.#position === -1) {\n      if (this.#commands.length > 0) {\n        this.#commands.length = 0;\n      }\n      this.#position = 0;\n      this.#commands.push(save);\n      return;\n    }\n    if (overwriteIfSameType && this.#commands[this.#position].type === type) {\n      if (keepUndo) {\n        save.undo = this.#commands[this.#position].undo;\n      }\n      this.#commands[this.#position] = save;\n      return;\n    }\n    const next = this.#position + 1;\n    if (next === this.#maxSize) {\n      this.#commands.splice(0, 1);\n    } else {\n      this.#position = next;\n      if (next < this.#commands.length) {\n        this.#commands.splice(next);\n      }\n    }\n    this.#commands.push(save);\n  }\n  undo() {\n    if (this.#position === -1) {\n      return;\n    }\n    this.#locked = true;\n    const {\n      undo,\n      post\n    } = this.#commands[this.#position];\n    undo();\n    post?.();\n    this.#locked = false;\n    this.#position -= 1;\n  }\n  redo() {\n    if (this.#position < this.#commands.length - 1) {\n      this.#position += 1;\n      this.#locked = true;\n      const {\n        cmd,\n        post\n      } = this.#commands[this.#position];\n      cmd();\n      post?.();\n      this.#locked = false;\n    }\n  }\n  hasSomethingToUndo() {\n    return this.#position !== -1;\n  }\n  hasSomethingToRedo() {\n    return this.#position < this.#commands.length - 1;\n  }\n  destroy() {\n    this.#commands = null;\n  }\n}\nclass KeyboardManager {\n  constructor(callbacks) {\n    this.buffer = [];\n    this.callbacks = new Map();\n    this.allKeys = new Set();\n    const {\n      isMac\n    } = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.FeatureTest.platform;\n    for (const [keys, callback, options = {}] of callbacks) {\n      for (const key of keys) {\n        const isMacKey = key.startsWith(\"mac+\");\n        if (isMac && isMacKey) {\n          this.callbacks.set(key.slice(4), {\n            callback,\n            options\n          });\n          this.allKeys.add(key.split(\"+\").at(-1));\n        } else if (!isMac && !isMacKey) {\n          this.callbacks.set(key, {\n            callback,\n            options\n          });\n          this.allKeys.add(key.split(\"+\").at(-1));\n        }\n      }\n    }\n  }\n  #serialize(event) {\n    if (event.altKey) {\n      this.buffer.push(\"alt\");\n    }\n    if (event.ctrlKey) {\n      this.buffer.push(\"ctrl\");\n    }\n    if (event.metaKey) {\n      this.buffer.push(\"meta\");\n    }\n    if (event.shiftKey) {\n      this.buffer.push(\"shift\");\n    }\n    this.buffer.push(event.key);\n    const str = this.buffer.join(\"+\");\n    this.buffer.length = 0;\n    return str;\n  }\n  exec(self, event) {\n    if (!this.allKeys.has(event.key)) {\n      return;\n    }\n    const info = this.callbacks.get(this.#serialize(event));\n    if (!info) {\n      return;\n    }\n    const {\n      callback,\n      options: {\n        bubbles = false,\n        args = [],\n        checker = null\n      }\n    } = info;\n    if (checker && !checker(self, event)) {\n      return;\n    }\n    callback.bind(self, ...args, event)();\n    if (!bubbles) {\n      event.stopPropagation();\n      event.preventDefault();\n    }\n  }\n}\nclass ColorManager {\n  static _colorsMapping = new Map([[\"CanvasText\", [0, 0, 0]], [\"Canvas\", [255, 255, 255]]]);\n  get _colors() {\n    const colors = new Map([[\"CanvasText\", null], [\"Canvas\", null]]);\n    (0,_display_utils_js__WEBPACK_IMPORTED_MODULE_1__.getColorValues)(colors);\n    return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, \"_colors\", colors);\n  }\n  convert(color) {\n    const rgb = (0,_display_utils_js__WEBPACK_IMPORTED_MODULE_1__.getRGB)(color);\n    if (!window.matchMedia(\"(forced-colors: active)\").matches) {\n      return rgb;\n    }\n    for (const [name, RGB] of this._colors) {\n      if (RGB.every((x, i) => x === rgb[i])) {\n        return ColorManager._colorsMapping.get(name);\n      }\n    }\n    return rgb;\n  }\n  getHexCode(name) {\n    const rgb = this._colors.get(name);\n    if (!rgb) {\n      return name;\n    }\n    return _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.Util.makeHexColor(...rgb);\n  }\n}\nclass AnnotationEditorUIManager {\n  #activeEditor = null;\n  #allEditors = new Map();\n  #allLayers = new Map();\n  #altTextManager = null;\n  #annotationStorage = null;\n  #changedExistingAnnotations = null;\n  #commandManager = new CommandManager();\n  #currentPageIndex = 0;\n  #deletedAnnotationsElementIds = new Set();\n  #draggingEditors = null;\n  #editorTypes = null;\n  #editorsToRescale = new Set();\n  #enableHighlightFloatingButton = false;\n  #filterFactory = null;\n  #focusMainContainerTimeoutId = null;\n  #highlightColors = null;\n  #highlightWhenShiftUp = false;\n  #highlightToolbar = null;\n  #idManager = new IdManager();\n  #isEnabled = false;\n  #isWaiting = false;\n  #lastActiveElement = null;\n  #mainHighlightColorPicker = null;\n  #mlManager = null;\n  #mode = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE;\n  #selectedEditors = new Set();\n  #selectedTextNode = null;\n  #pageColors = null;\n  #showAllStates = null;\n  #boundBlur = this.blur.bind(this);\n  #boundFocus = this.focus.bind(this);\n  #boundCopy = this.copy.bind(this);\n  #boundCut = this.cut.bind(this);\n  #boundPaste = this.paste.bind(this);\n  #boundKeydown = this.keydown.bind(this);\n  #boundKeyup = this.keyup.bind(this);\n  #boundOnEditingAction = this.onEditingAction.bind(this);\n  #boundOnPageChanging = this.onPageChanging.bind(this);\n  #boundOnScaleChanging = this.onScaleChanging.bind(this);\n  #boundSelectionChange = this.#selectionChange.bind(this);\n  #boundOnRotationChanging = this.onRotationChanging.bind(this);\n  #previousStates = {\n    isEditing: false,\n    isEmpty: true,\n    hasSomethingToUndo: false,\n    hasSomethingToRedo: false,\n    hasSelectedEditor: false,\n    hasSelectedText: false\n  };\n  #translation = [0, 0];\n  #translationTimeoutId = null;\n  #container = null;\n  #viewer = null;\n  static TRANSLATE_SMALL = 1;\n  static TRANSLATE_BIG = 10;\n  static get _keyboardManager() {\n    const proto = AnnotationEditorUIManager.prototype;\n    const arrowChecker = self => self.#container.contains(document.activeElement) && document.activeElement.tagName !== \"BUTTON\" && self.hasSomethingToControl();\n    const textInputChecker = (_self, {\n      target: el\n    }) => {\n      if (el instanceof HTMLInputElement) {\n        const {\n          type\n        } = el;\n        return type !== \"text\" && type !== \"number\";\n      }\n      return true;\n    };\n    const small = this.TRANSLATE_SMALL;\n    const big = this.TRANSLATE_BIG;\n    return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, \"_keyboardManager\", new KeyboardManager([[[\"ctrl+a\", \"mac+meta+a\"], proto.selectAll, {\n      checker: textInputChecker\n    }], [[\"ctrl+z\", \"mac+meta+z\"], proto.undo, {\n      checker: textInputChecker\n    }], [[\"ctrl+y\", \"ctrl+shift+z\", \"mac+meta+shift+z\", \"ctrl+shift+Z\", \"mac+meta+shift+Z\"], proto.redo, {\n      checker: textInputChecker\n    }], [[\"Backspace\", \"alt+Backspace\", \"ctrl+Backspace\", \"shift+Backspace\", \"mac+Backspace\", \"mac+alt+Backspace\", \"mac+ctrl+Backspace\", \"Delete\", \"ctrl+Delete\", \"shift+Delete\", \"mac+Delete\"], proto.delete, {\n      checker: textInputChecker\n    }], [[\"Enter\", \"mac+Enter\"], proto.addNewEditorFromKeyboard, {\n      checker: (self, {\n        target: el\n      }) => !(el instanceof HTMLButtonElement) && self.#container.contains(el) && !self.isEnterHandled\n    }], [[\" \", \"mac+ \"], proto.addNewEditorFromKeyboard, {\n      checker: (self, {\n        target: el\n      }) => !(el instanceof HTMLButtonElement) && self.#container.contains(document.activeElement)\n    }], [[\"Escape\", \"mac+Escape\"], proto.unselectAll], [[\"ArrowLeft\", \"mac+ArrowLeft\"], proto.translateSelectedEditors, {\n      args: [-small, 0],\n      checker: arrowChecker\n    }], [[\"ctrl+ArrowLeft\", \"mac+shift+ArrowLeft\"], proto.translateSelectedEditors, {\n      args: [-big, 0],\n      checker: arrowChecker\n    }], [[\"ArrowRight\", \"mac+ArrowRight\"], proto.translateSelectedEditors, {\n      args: [small, 0],\n      checker: arrowChecker\n    }], [[\"ctrl+ArrowRight\", \"mac+shift+ArrowRight\"], proto.translateSelectedEditors, {\n      args: [big, 0],\n      checker: arrowChecker\n    }], [[\"ArrowUp\", \"mac+ArrowUp\"], proto.translateSelectedEditors, {\n      args: [0, -small],\n      checker: arrowChecker\n    }], [[\"ctrl+ArrowUp\", \"mac+shift+ArrowUp\"], proto.translateSelectedEditors, {\n      args: [0, -big],\n      checker: arrowChecker\n    }], [[\"ArrowDown\", \"mac+ArrowDown\"], proto.translateSelectedEditors, {\n      args: [0, small],\n      checker: arrowChecker\n    }], [[\"ctrl+ArrowDown\", \"mac+shift+ArrowDown\"], proto.translateSelectedEditors, {\n      args: [0, big],\n      checker: arrowChecker\n    }]]));\n  }\n  constructor(container, viewer, altTextManager, eventBus, pdfDocument, pageColors, highlightColors, enableHighlightFloatingButton, mlManager) {\n    this.#container = container;\n    this.#viewer = viewer;\n    this.#altTextManager = altTextManager;\n    this._eventBus = eventBus;\n    this._eventBus._on(\"editingaction\", this.#boundOnEditingAction);\n    this._eventBus._on(\"pagechanging\", this.#boundOnPageChanging);\n    this._eventBus._on(\"scalechanging\", this.#boundOnScaleChanging);\n    this._eventBus._on(\"rotationchanging\", this.#boundOnRotationChanging);\n    this.#addSelectionListener();\n    this.#addKeyboardManager();\n    this.#annotationStorage = pdfDocument.annotationStorage;\n    this.#filterFactory = pdfDocument.filterFactory;\n    this.#pageColors = pageColors;\n    this.#highlightColors = highlightColors || null;\n    this.#enableHighlightFloatingButton = enableHighlightFloatingButton;\n    this.#mlManager = mlManager || null;\n    this.viewParameters = {\n      realScale: _display_utils_js__WEBPACK_IMPORTED_MODULE_1__.PixelsPerInch.PDF_TO_CSS_UNITS,\n      rotation: 0\n    };\n    this.isShiftKeyDown = false;\n  }\n  destroy() {\n    this.#removeKeyboardManager();\n    this.#removeFocusManager();\n    this._eventBus._off(\"editingaction\", this.#boundOnEditingAction);\n    this._eventBus._off(\"pagechanging\", this.#boundOnPageChanging);\n    this._eventBus._off(\"scalechanging\", this.#boundOnScaleChanging);\n    this._eventBus._off(\"rotationchanging\", this.#boundOnRotationChanging);\n    for (const layer of this.#allLayers.values()) {\n      layer.destroy();\n    }\n    this.#allLayers.clear();\n    this.#allEditors.clear();\n    this.#editorsToRescale.clear();\n    this.#activeEditor = null;\n    this.#selectedEditors.clear();\n    this.#commandManager.destroy();\n    this.#altTextManager?.destroy();\n    this.#highlightToolbar?.hide();\n    this.#highlightToolbar = null;\n    if (this.#focusMainContainerTimeoutId) {\n      clearTimeout(this.#focusMainContainerTimeoutId);\n      this.#focusMainContainerTimeoutId = null;\n    }\n    if (this.#translationTimeoutId) {\n      clearTimeout(this.#translationTimeoutId);\n      this.#translationTimeoutId = null;\n    }\n    this.#removeSelectionListener();\n  }\n  async mlGuess(data) {\n    return this.#mlManager?.guess(data) || null;\n  }\n  get hasMLManager() {\n    return !!this.#mlManager;\n  }\n  get hcmFilter() {\n    return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, \"hcmFilter\", this.#pageColors ? this.#filterFactory.addHCMFilter(this.#pageColors.foreground, this.#pageColors.background) : \"none\");\n  }\n  get direction() {\n    return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, \"direction\", getComputedStyle(this.#container).direction);\n  }\n  get highlightColors() {\n    return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, \"highlightColors\", this.#highlightColors ? new Map(this.#highlightColors.split(\",\").map(pair => pair.split(\"=\").map(x => x.trim()))) : null);\n  }\n  get highlightColorNames() {\n    return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, \"highlightColorNames\", this.highlightColors ? new Map(Array.from(this.highlightColors, e => e.reverse())) : null);\n  }\n  setMainHighlightColorPicker(colorPicker) {\n    this.#mainHighlightColorPicker = colorPicker;\n  }\n  editAltText(editor) {\n    this.#altTextManager?.editAltText(this, editor);\n  }\n  onPageChanging({\n    pageNumber\n  }) {\n    this.#currentPageIndex = pageNumber - 1;\n  }\n  focusMainContainer() {\n    this.#container.focus();\n  }\n  findParent(x, y) {\n    for (const layer of this.#allLayers.values()) {\n      const {\n        x: layerX,\n        y: layerY,\n        width,\n        height\n      } = layer.div.getBoundingClientRect();\n      if (x >= layerX && x <= layerX + width && y >= layerY && y <= layerY + height) {\n        return layer;\n      }\n    }\n    return null;\n  }\n  disableUserSelect(value = false) {\n    this.#viewer.classList.toggle(\"noUserSelect\", value);\n  }\n  addShouldRescale(editor) {\n    this.#editorsToRescale.add(editor);\n  }\n  removeShouldRescale(editor) {\n    this.#editorsToRescale.delete(editor);\n  }\n  onScaleChanging({\n    scale\n  }) {\n    this.commitOrRemove();\n    this.viewParameters.realScale = scale * _display_utils_js__WEBPACK_IMPORTED_MODULE_1__.PixelsPerInch.PDF_TO_CSS_UNITS;\n    for (const editor of this.#editorsToRescale) {\n      editor.onScaleChanging();\n    }\n  }\n  onRotationChanging({\n    pagesRotation\n  }) {\n    this.commitOrRemove();\n    this.viewParameters.rotation = pagesRotation;\n  }\n  #getAnchorElementForSelection({\n    anchorNode\n  }) {\n    return anchorNode.nodeType === Node.TEXT_NODE ? anchorNode.parentElement : anchorNode;\n  }\n  highlightSelection(methodOfCreation = \"\") {\n    const selection = document.getSelection();\n    if (!selection || selection.isCollapsed) {\n      return;\n    }\n    const {\n      anchorNode,\n      anchorOffset,\n      focusNode,\n      focusOffset\n    } = selection;\n    const text = selection.toString();\n    const anchorElement = this.#getAnchorElementForSelection(selection);\n    const textLayer = anchorElement.closest(\".textLayer\");\n    const boxes = this.getSelectionBoxes(textLayer);\n    if (!boxes) {\n      return;\n    }\n    selection.empty();\n    if (this.#mode === _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE) {\n      this._eventBus.dispatch(\"showannotationeditorui\", {\n        source: this,\n        mode: _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.HIGHLIGHT\n      });\n      this.showAllEditors(\"highlight\", true, true);\n    }\n    for (const layer of this.#allLayers.values()) {\n      if (layer.hasTextLayer(textLayer)) {\n        layer.createAndAddNewEditor({\n          x: 0,\n          y: 0\n        }, false, {\n          methodOfCreation,\n          boxes,\n          anchorNode,\n          anchorOffset,\n          focusNode,\n          focusOffset,\n          text\n        });\n        break;\n      }\n    }\n  }\n  #displayHighlightToolbar() {\n    const selection = document.getSelection();\n    if (!selection || selection.isCollapsed) {\n      return;\n    }\n    const anchorElement = this.#getAnchorElementForSelection(selection);\n    const textLayer = anchorElement.closest(\".textLayer\");\n    const boxes = this.getSelectionBoxes(textLayer);\n    if (!boxes) {\n      return;\n    }\n    this.#highlightToolbar ||= new _toolbar_js__WEBPACK_IMPORTED_MODULE_2__.HighlightToolbar(this);\n    this.#highlightToolbar.show(textLayer, boxes, this.direction === \"ltr\");\n  }\n  addToAnnotationStorage(editor) {\n    if (!editor.isEmpty() && this.#annotationStorage && !this.#annotationStorage.has(editor.id)) {\n      this.#annotationStorage.setValue(editor.id, editor);\n    }\n  }\n  #selectionChange() {\n    const selection = document.getSelection();\n    if (!selection || selection.isCollapsed) {\n      if (this.#selectedTextNode) {\n        this.#highlightToolbar?.hide();\n        this.#selectedTextNode = null;\n        this.#dispatchUpdateStates({\n          hasSelectedText: false\n        });\n      }\n      return;\n    }\n    const {\n      anchorNode\n    } = selection;\n    if (anchorNode === this.#selectedTextNode) {\n      return;\n    }\n    const anchorElement = this.#getAnchorElementForSelection(selection);\n    const textLayer = anchorElement.closest(\".textLayer\");\n    if (!textLayer) {\n      if (this.#selectedTextNode) {\n        this.#highlightToolbar?.hide();\n        this.#selectedTextNode = null;\n        this.#dispatchUpdateStates({\n          hasSelectedText: false\n        });\n      }\n      return;\n    }\n    this.#highlightToolbar?.hide();\n    this.#selectedTextNode = anchorNode;\n    this.#dispatchUpdateStates({\n      hasSelectedText: true\n    });\n    if (this.#mode !== _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.HIGHLIGHT && this.#mode !== _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE) {\n      return;\n    }\n    if (this.#mode === _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.HIGHLIGHT) {\n      this.showAllEditors(\"highlight\", true, true);\n    }\n    this.#highlightWhenShiftUp = this.isShiftKeyDown;\n    if (!this.isShiftKeyDown) {\n      const pointerup = e => {\n        if (e.type === \"pointerup\" && e.button !== 0) {\n          return;\n        }\n        window.removeEventListener(\"pointerup\", pointerup);\n        window.removeEventListener(\"blur\", pointerup);\n        if (e.type === \"pointerup\") {\n          this.#onSelectEnd(\"main_toolbar\");\n        }\n      };\n      window.addEventListener(\"pointerup\", pointerup);\n      window.addEventListener(\"blur\", pointerup);\n    }\n  }\n  #onSelectEnd(methodOfCreation = \"\") {\n    if (this.#mode === _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.HIGHLIGHT) {\n      this.highlightSelection(methodOfCreation);\n    } else if (this.#enableHighlightFloatingButton) {\n      this.#displayHighlightToolbar();\n    }\n  }\n  #addSelectionListener() {\n    document.addEventListener(\"selectionchange\", this.#boundSelectionChange);\n  }\n  #removeSelectionListener() {\n    document.removeEventListener(\"selectionchange\", this.#boundSelectionChange);\n  }\n  #addFocusManager() {\n    window.addEventListener(\"focus\", this.#boundFocus);\n    window.addEventListener(\"blur\", this.#boundBlur);\n  }\n  #removeFocusManager() {\n    window.removeEventListener(\"focus\", this.#boundFocus);\n    window.removeEventListener(\"blur\", this.#boundBlur);\n  }\n  blur() {\n    this.isShiftKeyDown = false;\n    if (this.#highlightWhenShiftUp) {\n      this.#highlightWhenShiftUp = false;\n      this.#onSelectEnd(\"main_toolbar\");\n    }\n    if (!this.hasSelection) {\n      return;\n    }\n    const {\n      activeElement\n    } = document;\n    for (const editor of this.#selectedEditors) {\n      if (editor.div.contains(activeElement)) {\n        this.#lastActiveElement = [editor, activeElement];\n        editor._focusEventsAllowed = false;\n        break;\n      }\n    }\n  }\n  focus() {\n    if (!this.#lastActiveElement) {\n      return;\n    }\n    const [lastEditor, lastActiveElement] = this.#lastActiveElement;\n    this.#lastActiveElement = null;\n    lastActiveElement.addEventListener(\"focusin\", () => {\n      lastEditor._focusEventsAllowed = true;\n    }, {\n      once: true\n    });\n    lastActiveElement.focus();\n  }\n  #addKeyboardManager() {\n    window.addEventListener(\"keydown\", this.#boundKeydown);\n    window.addEventListener(\"keyup\", this.#boundKeyup);\n  }\n  #removeKeyboardManager() {\n    window.removeEventListener(\"keydown\", this.#boundKeydown);\n    window.removeEventListener(\"keyup\", this.#boundKeyup);\n  }\n  #addCopyPasteListeners() {\n    document.addEventListener(\"copy\", this.#boundCopy);\n    document.addEventListener(\"cut\", this.#boundCut);\n    document.addEventListener(\"paste\", this.#boundPaste);\n  }\n  #removeCopyPasteListeners() {\n    document.removeEventListener(\"copy\", this.#boundCopy);\n    document.removeEventListener(\"cut\", this.#boundCut);\n    document.removeEventListener(\"paste\", this.#boundPaste);\n  }\n  addEditListeners() {\n    this.#addKeyboardManager();\n    this.#addCopyPasteListeners();\n  }\n  removeEditListeners() {\n    this.#removeKeyboardManager();\n    this.#removeCopyPasteListeners();\n  }\n  copy(event) {\n    event.preventDefault();\n    this.#activeEditor?.commitOrRemove();\n    if (!this.hasSelection) {\n      return;\n    }\n    const editors = [];\n    for (const editor of this.#selectedEditors) {\n      const serialized = editor.serialize(true);\n      if (serialized) {\n        editors.push(serialized);\n      }\n    }\n    if (editors.length === 0) {\n      return;\n    }\n    event.clipboardData.setData(\"application/pdfjs\", JSON.stringify(editors));\n  }\n  cut(event) {\n    this.copy(event);\n    this.delete();\n  }\n  paste(event) {\n    event.preventDefault();\n    const {\n      clipboardData\n    } = event;\n    for (const item of clipboardData.items) {\n      for (const editorType of this.#editorTypes) {\n        if (editorType.isHandlingMimeForPasting(item.type)) {\n          editorType.paste(item, this.currentLayer);\n          return;\n        }\n      }\n    }\n    let data = clipboardData.getData(\"application/pdfjs\");\n    if (!data) {\n      return;\n    }\n    try {\n      data = JSON.parse(data);\n    } catch (ex) {\n      (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`paste: \"${ex.message}\".`);\n      return;\n    }\n    if (!Array.isArray(data)) {\n      return;\n    }\n    this.unselectAll();\n    const layer = this.currentLayer;\n    try {\n      const newEditors = [];\n      for (const editor of data) {\n        const deserializedEditor = layer.deserialize(editor);\n        if (!deserializedEditor) {\n          return;\n        }\n        newEditors.push(deserializedEditor);\n      }\n      const cmd = () => {\n        for (const editor of newEditors) {\n          this.#addEditorToLayer(editor);\n        }\n        this.#selectEditors(newEditors);\n      };\n      const undo = () => {\n        for (const editor of newEditors) {\n          editor.remove();\n        }\n      };\n      this.addCommands({\n        cmd,\n        undo,\n        mustExec: true\n      });\n    } catch (ex) {\n      (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`paste: \"${ex.message}\".`);\n    }\n  }\n  keydown(event) {\n    if (!this.isShiftKeyDown && event.key === \"Shift\") {\n      this.isShiftKeyDown = true;\n    }\n    if (this.#mode !== _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE && !this.isEditorHandlingKeyboard) {\n      AnnotationEditorUIManager._keyboardManager.exec(this, event);\n    }\n  }\n  keyup(event) {\n    if (this.isShiftKeyDown && event.key === \"Shift\") {\n      this.isShiftKeyDown = false;\n      if (this.#highlightWhenShiftUp) {\n        this.#highlightWhenShiftUp = false;\n        this.#onSelectEnd(\"main_toolbar\");\n      }\n    }\n  }\n  onEditingAction({\n    name\n  }) {\n    switch (name) {\n      case \"undo\":\n      case \"redo\":\n      case \"delete\":\n      case \"selectAll\":\n        this[name]();\n        break;\n      case \"highlightSelection\":\n        this.highlightSelection(\"context_menu\");\n        break;\n    }\n  }\n  #dispatchUpdateStates(details) {\n    const hasChanged = Object.entries(details).some(([key, value]) => this.#previousStates[key] !== value);\n    if (hasChanged) {\n      this._eventBus.dispatch(\"annotationeditorstateschanged\", {\n        source: this,\n        details: Object.assign(this.#previousStates, details)\n      });\n      if (this.#mode === _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.HIGHLIGHT && details.hasSelectedEditor === false) {\n        this.#dispatchUpdateUI([[_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.HIGHLIGHT_FREE, true]]);\n      }\n    }\n  }\n  #dispatchUpdateUI(details) {\n    this._eventBus.dispatch(\"annotationeditorparamschanged\", {\n      source: this,\n      details\n    });\n  }\n  setEditingState(isEditing) {\n    if (isEditing) {\n      this.#addFocusManager();\n      this.#addCopyPasteListeners();\n      this.#dispatchUpdateStates({\n        isEditing: this.#mode !== _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE,\n        isEmpty: this.#isEmpty(),\n        hasSomethingToUndo: this.#commandManager.hasSomethingToUndo(),\n        hasSomethingToRedo: this.#commandManager.hasSomethingToRedo(),\n        hasSelectedEditor: false\n      });\n    } else {\n      this.#removeFocusManager();\n      this.#removeCopyPasteListeners();\n      this.#dispatchUpdateStates({\n        isEditing: false\n      });\n      this.disableUserSelect(false);\n    }\n  }\n  registerEditorTypes(types) {\n    if (this.#editorTypes) {\n      return;\n    }\n    this.#editorTypes = types;\n    for (const editorType of this.#editorTypes) {\n      this.#dispatchUpdateUI(editorType.defaultPropertiesToUpdate);\n    }\n  }\n  getId() {\n    return this.#idManager.id;\n  }\n  get currentLayer() {\n    return this.#allLayers.get(this.#currentPageIndex);\n  }\n  getLayer(pageIndex) {\n    return this.#allLayers.get(pageIndex);\n  }\n  get currentPageIndex() {\n    return this.#currentPageIndex;\n  }\n  addLayer(layer) {\n    this.#allLayers.set(layer.pageIndex, layer);\n    if (this.#isEnabled) {\n      layer.enable();\n    } else {\n      layer.disable();\n    }\n  }\n  removeLayer(layer) {\n    this.#allLayers.delete(layer.pageIndex);\n  }\n  updateMode(mode, editId = null, isFromKeyboard = false) {\n    if (this.#mode === mode) {\n      return;\n    }\n    this.#mode = mode;\n    if (mode === _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE) {\n      this.setEditingState(false);\n      this.#disableAll();\n      return;\n    }\n    this.setEditingState(true);\n    this.#enableAll();\n    this.unselectAll();\n    for (const layer of this.#allLayers.values()) {\n      layer.updateMode(mode);\n    }\n    if (!editId && isFromKeyboard) {\n      this.addNewEditorFromKeyboard();\n      return;\n    }\n    if (!editId) {\n      return;\n    }\n    for (const editor of this.#allEditors.values()) {\n      if (editor.annotationElementId === editId) {\n        this.setSelected(editor);\n        editor.enterInEditMode();\n        break;\n      }\n    }\n  }\n  addNewEditorFromKeyboard() {\n    if (this.currentLayer.canCreateNewEmptyEditor()) {\n      this.currentLayer.addNewEditor();\n    }\n  }\n  updateToolbar(mode) {\n    if (mode === this.#mode) {\n      return;\n    }\n    this._eventBus.dispatch(\"switchannotationeditormode\", {\n      source: this,\n      mode\n    });\n  }\n  updateParams(type, value) {\n    if (!this.#editorTypes) {\n      return;\n    }\n    switch (type) {\n      case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.CREATE:\n        this.currentLayer.addNewEditor();\n        return;\n      case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.HIGHLIGHT_DEFAULT_COLOR:\n        this.#mainHighlightColorPicker?.updateColor(value);\n        break;\n      case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL:\n        this._eventBus.dispatch(\"reporttelemetry\", {\n          source: this,\n          details: {\n            type: \"editing\",\n            data: {\n              type: \"highlight\",\n              action: \"toggle_visibility\"\n            }\n          }\n        });\n        (this.#showAllStates ||= new Map()).set(type, value);\n        this.showAllEditors(\"highlight\", value);\n        break;\n    }\n    for (const editor of this.#selectedEditors) {\n      editor.updateParams(type, value);\n    }\n    for (const editorType of this.#editorTypes) {\n      editorType.updateDefaultParams(type, value);\n    }\n  }\n  showAllEditors(type, visible, updateButton = false) {\n    for (const editor of this.#allEditors.values()) {\n      if (editor.editorType === type) {\n        editor.show(visible);\n      }\n    }\n    const state = this.#showAllStates?.get(_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL) ?? true;\n    if (state !== visible) {\n      this.#dispatchUpdateUI([[_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL, visible]]);\n    }\n  }\n  enableWaiting(mustWait = false) {\n    if (this.#isWaiting === mustWait) {\n      return;\n    }\n    this.#isWaiting = mustWait;\n    for (const layer of this.#allLayers.values()) {\n      if (mustWait) {\n        layer.disableClick();\n      } else {\n        layer.enableClick();\n      }\n      layer.div.classList.toggle(\"waiting\", mustWait);\n    }\n  }\n  #enableAll() {\n    if (!this.#isEnabled) {\n      this.#isEnabled = true;\n      for (const layer of this.#allLayers.values()) {\n        layer.enable();\n      }\n      for (const editor of this.#allEditors.values()) {\n        editor.enable();\n      }\n    }\n  }\n  #disableAll() {\n    this.unselectAll();\n    if (this.#isEnabled) {\n      this.#isEnabled = false;\n      for (const layer of this.#allLayers.values()) {\n        layer.disable();\n      }\n      for (const editor of this.#allEditors.values()) {\n        editor.disable();\n      }\n    }\n  }\n  getEditors(pageIndex) {\n    const editors = [];\n    for (const editor of this.#allEditors.values()) {\n      if (editor.pageIndex === pageIndex) {\n        editors.push(editor);\n      }\n    }\n    return editors;\n  }\n  getEditor(id) {\n    return this.#allEditors.get(id);\n  }\n  addEditor(editor) {\n    this.#allEditors.set(editor.id, editor);\n  }\n  removeEditor(editor) {\n    if (editor.div.contains(document.activeElement)) {\n      if (this.#focusMainContainerTimeoutId) {\n        clearTimeout(this.#focusMainContainerTimeoutId);\n      }\n      this.#focusMainContainerTimeoutId = setTimeout(() => {\n        this.focusMainContainer();\n        this.#focusMainContainerTimeoutId = null;\n      }, 0);\n    }\n    this.#allEditors.delete(editor.id);\n    this.unselect(editor);\n    if (!editor.annotationElementId || !this.#deletedAnnotationsElementIds.has(editor.annotationElementId)) {\n      this.#annotationStorage?.remove(editor.id);\n    }\n  }\n  addDeletedAnnotationElement(editor) {\n    this.#deletedAnnotationsElementIds.add(editor.annotationElementId);\n    this.addChangedExistingAnnotation(editor);\n    editor.deleted = true;\n  }\n  isDeletedAnnotationElement(annotationElementId) {\n    return this.#deletedAnnotationsElementIds.has(annotationElementId);\n  }\n  removeDeletedAnnotationElement(editor) {\n    this.#deletedAnnotationsElementIds.delete(editor.annotationElementId);\n    this.removeChangedExistingAnnotation(editor);\n    editor.deleted = false;\n  }\n  #addEditorToLayer(editor) {\n    const layer = this.#allLayers.get(editor.pageIndex);\n    if (layer) {\n      layer.addOrRebuild(editor);\n    } else {\n      this.addEditor(editor);\n      this.addToAnnotationStorage(editor);\n    }\n  }\n  setActiveEditor(editor) {\n    if (this.#activeEditor === editor) {\n      return;\n    }\n    this.#activeEditor = editor;\n    if (editor) {\n      this.#dispatchUpdateUI(editor.propertiesToUpdate);\n    }\n  }\n  get #lastSelectedEditor() {\n    let ed = null;\n    for (ed of this.#selectedEditors) {}\n    return ed;\n  }\n  updateUI(editor) {\n    if (this.#lastSelectedEditor === editor) {\n      this.#dispatchUpdateUI(editor.propertiesToUpdate);\n    }\n  }\n  toggleSelected(editor) {\n    if (this.#selectedEditors.has(editor)) {\n      this.#selectedEditors.delete(editor);\n      editor.unselect();\n      this.#dispatchUpdateStates({\n        hasSelectedEditor: this.hasSelection\n      });\n      return;\n    }\n    this.#selectedEditors.add(editor);\n    editor.select();\n    this.#dispatchUpdateUI(editor.propertiesToUpdate);\n    this.#dispatchUpdateStates({\n      hasSelectedEditor: true\n    });\n  }\n  setSelected(editor) {\n    for (const ed of this.#selectedEditors) {\n      if (ed !== editor) {\n        ed.unselect();\n      }\n    }\n    this.#selectedEditors.clear();\n    this.#selectedEditors.add(editor);\n    editor.select();\n    this.#dispatchUpdateUI(editor.propertiesToUpdate);\n    this.#dispatchUpdateStates({\n      hasSelectedEditor: true\n    });\n  }\n  isSelected(editor) {\n    return this.#selectedEditors.has(editor);\n  }\n  get firstSelectedEditor() {\n    return this.#selectedEditors.values().next().value;\n  }\n  unselect(editor) {\n    editor.unselect();\n    this.#selectedEditors.delete(editor);\n    this.#dispatchUpdateStates({\n      hasSelectedEditor: this.hasSelection\n    });\n  }\n  get hasSelection() {\n    return this.#selectedEditors.size !== 0;\n  }\n  get isEnterHandled() {\n    return this.#selectedEditors.size === 1 && this.firstSelectedEditor.isEnterHandled;\n  }\n  undo() {\n    this.#commandManager.undo();\n    this.#dispatchUpdateStates({\n      hasSomethingToUndo: this.#commandManager.hasSomethingToUndo(),\n      hasSomethingToRedo: true,\n      isEmpty: this.#isEmpty()\n    });\n  }\n  redo() {\n    this.#commandManager.redo();\n    this.#dispatchUpdateStates({\n      hasSomethingToUndo: true,\n      hasSomethingToRedo: this.#commandManager.hasSomethingToRedo(),\n      isEmpty: this.#isEmpty()\n    });\n  }\n  addCommands(params) {\n    this.#commandManager.add(params);\n    this.#dispatchUpdateStates({\n      hasSomethingToUndo: true,\n      hasSomethingToRedo: false,\n      isEmpty: this.#isEmpty()\n    });\n  }\n  #isEmpty() {\n    if (this.#allEditors.size === 0) {\n      return true;\n    }\n    if (this.#allEditors.size === 1) {\n      for (const editor of this.#allEditors.values()) {\n        return editor.isEmpty();\n      }\n    }\n    return false;\n  }\n  delete() {\n    this.commitOrRemove();\n    if (!this.hasSelection) {\n      return;\n    }\n    const editors = [...this.#selectedEditors];\n    const cmd = () => {\n      for (const editor of editors) {\n        editor.remove();\n      }\n    };\n    const undo = () => {\n      for (const editor of editors) {\n        this.#addEditorToLayer(editor);\n      }\n    };\n    this.addCommands({\n      cmd,\n      undo,\n      mustExec: true\n    });\n  }\n  commitOrRemove() {\n    this.#activeEditor?.commitOrRemove();\n  }\n  hasSomethingToControl() {\n    return this.#activeEditor || this.hasSelection;\n  }\n  #selectEditors(editors) {\n    for (const editor of this.#selectedEditors) {\n      editor.unselect();\n    }\n    this.#selectedEditors.clear();\n    for (const editor of editors) {\n      if (editor.isEmpty()) {\n        continue;\n      }\n      this.#selectedEditors.add(editor);\n      editor.select();\n    }\n    this.#dispatchUpdateStates({\n      hasSelectedEditor: this.hasSelection\n    });\n  }\n  selectAll() {\n    for (const editor of this.#selectedEditors) {\n      editor.commit();\n    }\n    this.#selectEditors(this.#allEditors.values());\n  }\n  unselectAll() {\n    if (this.#activeEditor) {\n      this.#activeEditor.commitOrRemove();\n      if (this.#mode !== _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE) {\n        return;\n      }\n    }\n    if (!this.hasSelection) {\n      return;\n    }\n    for (const editor of this.#selectedEditors) {\n      editor.unselect();\n    }\n    this.#selectedEditors.clear();\n    this.#dispatchUpdateStates({\n      hasSelectedEditor: false\n    });\n  }\n  translateSelectedEditors(x, y, noCommit = false) {\n    if (!noCommit) {\n      this.commitOrRemove();\n    }\n    if (!this.hasSelection) {\n      return;\n    }\n    this.#translation[0] += x;\n    this.#translation[1] += y;\n    const [totalX, totalY] = this.#translation;\n    const editors = [...this.#selectedEditors];\n    const TIME_TO_WAIT = 1000;\n    if (this.#translationTimeoutId) {\n      clearTimeout(this.#translationTimeoutId);\n    }\n    this.#translationTimeoutId = setTimeout(() => {\n      this.#translationTimeoutId = null;\n      this.#translation[0] = this.#translation[1] = 0;\n      this.addCommands({\n        cmd: () => {\n          for (const editor of editors) {\n            if (this.#allEditors.has(editor.id)) {\n              editor.translateInPage(totalX, totalY);\n            }\n          }\n        },\n        undo: () => {\n          for (const editor of editors) {\n            if (this.#allEditors.has(editor.id)) {\n              editor.translateInPage(-totalX, -totalY);\n            }\n          }\n        },\n        mustExec: false\n      });\n    }, TIME_TO_WAIT);\n    for (const editor of editors) {\n      editor.translateInPage(x, y);\n    }\n  }\n  setUpDragSession() {\n    if (!this.hasSelection) {\n      return;\n    }\n    this.disableUserSelect(true);\n    this.#draggingEditors = new Map();\n    for (const editor of this.#selectedEditors) {\n      this.#draggingEditors.set(editor, {\n        savedX: editor.x,\n        savedY: editor.y,\n        savedPageIndex: editor.pageIndex,\n        newX: 0,\n        newY: 0,\n        newPageIndex: -1\n      });\n    }\n  }\n  endDragSession() {\n    if (!this.#draggingEditors) {\n      return false;\n    }\n    this.disableUserSelect(false);\n    const map = this.#draggingEditors;\n    this.#draggingEditors = null;\n    let mustBeAddedInUndoStack = false;\n    for (const [{\n      x,\n      y,\n      pageIndex\n    }, value] of map) {\n      value.newX = x;\n      value.newY = y;\n      value.newPageIndex = pageIndex;\n      mustBeAddedInUndoStack ||= x !== value.savedX || y !== value.savedY || pageIndex !== value.savedPageIndex;\n    }\n    if (!mustBeAddedInUndoStack) {\n      return false;\n    }\n    const move = (editor, x, y, pageIndex) => {\n      if (this.#allEditors.has(editor.id)) {\n        const parent = this.#allLayers.get(pageIndex);\n        if (parent) {\n          editor._setParentAndPosition(parent, x, y);\n        } else {\n          editor.pageIndex = pageIndex;\n          editor.x = x;\n          editor.y = y;\n        }\n      }\n    };\n    this.addCommands({\n      cmd: () => {\n        for (const [editor, {\n          newX,\n          newY,\n          newPageIndex\n        }] of map) {\n          move(editor, newX, newY, newPageIndex);\n        }\n      },\n      undo: () => {\n        for (const [editor, {\n          savedX,\n          savedY,\n          savedPageIndex\n        }] of map) {\n          move(editor, savedX, savedY, savedPageIndex);\n        }\n      },\n      mustExec: true\n    });\n    return true;\n  }\n  dragSelectedEditors(tx, ty) {\n    if (!this.#draggingEditors) {\n      return;\n    }\n    for (const editor of this.#draggingEditors.keys()) {\n      editor.drag(tx, ty);\n    }\n  }\n  rebuild(editor) {\n    if (editor.parent === null) {\n      const parent = this.getLayer(editor.pageIndex);\n      if (parent) {\n        parent.changeParent(editor);\n        parent.addOrRebuild(editor);\n      } else {\n        this.addEditor(editor);\n        this.addToAnnotationStorage(editor);\n        editor.rebuild();\n      }\n    } else {\n      editor.parent.addOrRebuild(editor);\n    }\n  }\n  get isEditorHandlingKeyboard() {\n    return this.getActive()?.shouldGetKeyboardEvents() || this.#selectedEditors.size === 1 && this.firstSelectedEditor.shouldGetKeyboardEvents();\n  }\n  isActive(editor) {\n    return this.#activeEditor === editor;\n  }\n  getActive() {\n    return this.#activeEditor;\n  }\n  getMode() {\n    return this.#mode;\n  }\n  get imageManager() {\n    return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, \"imageManager\", new ImageManager());\n  }\n  getSelectionBoxes(textLayer) {\n    if (!textLayer) {\n      return null;\n    }\n    const selection = document.getSelection();\n    for (let i = 0, ii = selection.rangeCount; i < ii; i++) {\n      if (!textLayer.contains(selection.getRangeAt(i).commonAncestorContainer)) {\n        return null;\n      }\n    }\n    const {\n      x: layerX,\n      y: layerY,\n      width: parentWidth,\n      height: parentHeight\n    } = textLayer.getBoundingClientRect();\n    let rotator;\n    switch (textLayer.getAttribute(\"data-main-rotation\")) {\n      case \"90\":\n        rotator = (x, y, w, h) => ({\n          x: (y - layerY) / parentHeight,\n          y: 1 - (x + w - layerX) / parentWidth,\n          width: h / parentHeight,\n          height: w / parentWidth\n        });\n        break;\n      case \"180\":\n        rotator = (x, y, w, h) => ({\n          x: 1 - (x + w - layerX) / parentWidth,\n          y: 1 - (y + h - layerY) / parentHeight,\n          width: w / parentWidth,\n          height: h / parentHeight\n        });\n        break;\n      case \"270\":\n        rotator = (x, y, w, h) => ({\n          x: 1 - (y + h - layerY) / parentHeight,\n          y: (x - layerX) / parentWidth,\n          width: h / parentHeight,\n          height: w / parentWidth\n        });\n        break;\n      default:\n        rotator = (x, y, w, h) => ({\n          x: (x - layerX) / parentWidth,\n          y: (y - layerY) / parentHeight,\n          width: w / parentWidth,\n          height: h / parentHeight\n        });\n        break;\n    }\n    const boxes = [];\n    for (let i = 0, ii = selection.rangeCount; i < ii; i++) {\n      const range = selection.getRangeAt(i);\n      if (range.collapsed) {\n        continue;\n      }\n      for (const {\n        x,\n        y,\n        width,\n        height\n      } of range.getClientRects()) {\n        if (width === 0 || height === 0) {\n          continue;\n        }\n        boxes.push(rotator(x, y, width, height));\n      }\n    }\n    return boxes.length === 0 ? null : boxes;\n  }\n  addChangedExistingAnnotation({\n    annotationElementId,\n    id\n  }) {\n    (this.#changedExistingAnnotations ||= new Map()).set(annotationElementId, id);\n  }\n  removeChangedExistingAnnotation({\n    annotationElementId\n  }) {\n    this.#changedExistingAnnotations?.delete(annotationElementId);\n  }\n  renderAnnotationElement(annotation) {\n    const editorId = this.#changedExistingAnnotations?.get(annotation.data.id);\n    if (!editorId) {\n      return;\n    }\n    const editor = this.#annotationStorage.getRawValue(editorId);\n    if (!editor) {\n      return;\n    }\n    if (this.#mode === _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE && !editor.hasBeenModified) {\n      return;\n    }\n    editor.renderAnnotationElement(annotation);\n  }\n}\n\n\n/***/ }),\n\n/***/ 94:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   PDFFetchStream: () => (/* binding */ PDFFetchStream)\n/* harmony export */ });\n/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292);\n/* harmony import */ var _network_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(490);\n\n\nfunction createFetchOptions(headers, withCredentials, abortController) {\n  return {\n    method: \"GET\",\n    headers,\n    signal: abortController.signal,\n    mode: \"cors\",\n    credentials: withCredentials ? \"include\" : \"same-origin\",\n    redirect: \"follow\"\n  };\n}\nfunction createHeaders(httpHeaders) {\n  const headers = new Headers();\n  for (const property in httpHeaders) {\n    const value = httpHeaders[property];\n    if (value === undefined) {\n      continue;\n    }\n    headers.append(property, value);\n  }\n  return headers;\n}\nfunction getArrayBuffer(val) {\n  if (val instanceof Uint8Array) {\n    return val.buffer;\n  }\n  if (val instanceof ArrayBuffer) {\n    return val;\n  }\n  (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`getArrayBuffer - unexpected data format: ${val}`);\n  return new Uint8Array(val).buffer;\n}\nclass PDFFetchStream {\n  constructor(source) {\n    this.source = source;\n    this.isHttp = /^https?:/i.test(source.url);\n    this.httpHeaders = this.isHttp && source.httpHeaders || {};\n    this._fullRequestReader = null;\n    this._rangeRequestReaders = [];\n  }\n  get _progressiveDataLength() {\n    return this._fullRequestReader?._loaded ?? 0;\n  }\n  getFullReader() {\n    (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(!this._fullRequestReader, \"PDFFetchStream.getFullReader can only be called once.\");\n    this._fullRequestReader = new PDFFetchStreamReader(this);\n    return this._fullRequestReader;\n  }\n  getRangeReader(begin, end) {\n    if (end <= this._progressiveDataLength) {\n      return null;\n    }\n    const reader = new PDFFetchStreamRangeReader(this, begin, end);\n    this._rangeRequestReaders.push(reader);\n    return reader;\n  }\n  cancelAllRequests(reason) {\n    this._fullRequestReader?.cancel(reason);\n    for (const reader of this._rangeRequestReaders.slice(0)) {\n      reader.cancel(reason);\n    }\n  }\n}\nclass PDFFetchStreamReader {\n  constructor(stream) {\n    this._stream = stream;\n    this._reader = null;\n    this._loaded = 0;\n    this._filename = null;\n    const source = stream.source;\n    this._withCredentials = source.withCredentials || false;\n    this._contentLength = source.length;\n    this._headersCapability = Promise.withResolvers();\n    this._disableRange = source.disableRange || false;\n    this._rangeChunkSize = source.rangeChunkSize;\n    if (!this._rangeChunkSize && !this._disableRange) {\n      this._disableRange = true;\n    }\n    this._abortController = new AbortController();\n    this._isStreamingSupported = !source.disableStream;\n    this._isRangeSupported = !source.disableRange;\n    this._headers = createHeaders(this._stream.httpHeaders);\n    const url = source.url;\n    fetch(url, createFetchOptions(this._headers, this._withCredentials, this._abortController)).then(response => {\n      if (!(0,_network_utils_js__WEBPACK_IMPORTED_MODULE_1__.validateResponseStatus)(response.status)) {\n        throw (0,_network_utils_js__WEBPACK_IMPORTED_MODULE_1__.createResponseStatusError)(response.status, url);\n      }\n      this._reader = response.body.getReader();\n      this._headersCapability.resolve();\n      const getResponseHeader = name => response.headers.get(name);\n      const {\n        allowRangeRequests,\n        suggestedLength\n      } = (0,_network_utils_js__WEBPACK_IMPORTED_MODULE_1__.validateRangeRequestCapabilities)({\n        getResponseHeader,\n        isHttp: this._stream.isHttp,\n        rangeChunkSize: this._rangeChunkSize,\n        disableRange: this._disableRange\n      });\n      this._isRangeSupported = allowRangeRequests;\n      this._contentLength = suggestedLength || this._contentLength;\n      this._filename = (0,_network_utils_js__WEBPACK_IMPORTED_MODULE_1__.extractFilenameFromHeader)(getResponseHeader);\n      if (!this._isStreamingSupported && this._isRangeSupported) {\n        this.cancel(new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AbortException(\"Streaming is disabled.\"));\n      }\n    }).catch(this._headersCapability.reject);\n    this.onProgress = null;\n  }\n  get headersReady() {\n    return this._headersCapability.promise;\n  }\n  get filename() {\n    return this._filename;\n  }\n  get contentLength() {\n    return this._contentLength;\n  }\n  get isRangeSupported() {\n    return this._isRangeSupported;\n  }\n  get isStreamingSupported() {\n    return this._isStreamingSupported;\n  }\n  async read() {\n    await this._headersCapability.promise;\n    const {\n      value,\n      done\n    } = await this._reader.read();\n    if (done) {\n      return {\n        value,\n        done\n      };\n    }\n    this._loaded += value.byteLength;\n    this.onProgress?.({\n      loaded: this._loaded,\n      total: this._contentLength\n    });\n    return {\n      value: getArrayBuffer(value),\n      done: false\n    };\n  }\n  cancel(reason) {\n    this._reader?.cancel(reason);\n    this._abortController.abort();\n  }\n}\nclass PDFFetchStreamRangeReader {\n  constructor(stream, begin, end) {\n    this._stream = stream;\n    this._reader = null;\n    this._loaded = 0;\n    const source = stream.source;\n    this._withCredentials = source.withCredentials || false;\n    this._readCapability = Promise.withResolvers();\n    this._isStreamingSupported = !source.disableStream;\n    this._abortController = new AbortController();\n    this._headers = createHeaders(this._stream.httpHeaders);\n    this._headers.append(\"Range\", `bytes=${begin}-${end - 1}`);\n    const url = source.url;\n    fetch(url, createFetchOptions(this._headers, this._withCredentials, this._abortController)).then(response => {\n      if (!(0,_network_utils_js__WEBPACK_IMPORTED_MODULE_1__.validateResponseStatus)(response.status)) {\n        throw (0,_network_utils_js__WEBPACK_IMPORTED_MODULE_1__.createResponseStatusError)(response.status, url);\n      }\n      this._readCapability.resolve();\n      this._reader = response.body.getReader();\n    }).catch(this._readCapability.reject);\n    this.onProgress = null;\n  }\n  get isStreamingSupported() {\n    return this._isStreamingSupported;\n  }\n  async read() {\n    await this._readCapability.promise;\n    const {\n      value,\n      done\n    } = await this._reader.read();\n    if (done) {\n      return {\n        value,\n        done\n      };\n    }\n    this._loaded += value.byteLength;\n    this.onProgress?.({\n      loaded: this._loaded\n    });\n    return {\n      value: getArrayBuffer(value),\n      done: false\n    };\n  }\n  cancel(reason) {\n    this._reader?.cancel(reason);\n    this._abortController.abort();\n  }\n}\n\n\n/***/ }),\n\n/***/ 10:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   FontFaceObject: () => (/* binding */ FontFaceObject),\n/* harmony export */   FontLoader: () => (/* binding */ FontLoader)\n/* harmony export */ });\n/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292);\n\nclass FontLoader {\n  #systemFonts = new Set();\n  constructor({\n    ownerDocument = globalThis.document,\n    styleElement = null\n  }) {\n    this._document = ownerDocument;\n    this.nativeFontFaces = new Set();\n    this.styleElement = null;\n    this.loadingRequests = [];\n    this.loadTestFontId = 0;\n  }\n  addNativeFontFace(nativeFontFace) {\n    this.nativeFontFaces.add(nativeFontFace);\n    this._document.fonts.add(nativeFontFace);\n  }\n  removeNativeFontFace(nativeFontFace) {\n    this.nativeFontFaces.delete(nativeFontFace);\n    this._document.fonts.delete(nativeFontFace);\n  }\n  insertRule(rule) {\n    if (!this.styleElement) {\n      this.styleElement = this._document.createElement(\"style\");\n      this._document.documentElement.getElementsByTagName(\"head\")[0].append(this.styleElement);\n    }\n    const styleSheet = this.styleElement.sheet;\n    styleSheet.insertRule(rule, styleSheet.cssRules.length);\n  }\n  clear() {\n    for (const nativeFontFace of this.nativeFontFaces) {\n      this._document.fonts.delete(nativeFontFace);\n    }\n    this.nativeFontFaces.clear();\n    this.#systemFonts.clear();\n    if (this.styleElement) {\n      this.styleElement.remove();\n      this.styleElement = null;\n    }\n  }\n  async loadSystemFont({\n    systemFontInfo: info,\n    _inspectFont\n  }) {\n    if (!info || this.#systemFonts.has(info.loadedName)) {\n      return;\n    }\n    (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(!this.disableFontFace, \"loadSystemFont shouldn't be called when `disableFontFace` is set.\");\n    if (this.isFontLoadingAPISupported) {\n      const {\n        loadedName,\n        src,\n        style\n      } = info;\n      const fontFace = new FontFace(loadedName, src, style);\n      this.addNativeFontFace(fontFace);\n      try {\n        await fontFace.load();\n        this.#systemFonts.add(loadedName);\n        _inspectFont?.(info);\n      } catch {\n        (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`Cannot load system font: ${info.baseFontName}, installing it could help to improve PDF rendering.`);\n        this.removeNativeFontFace(fontFace);\n      }\n      return;\n    }\n    (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)(\"Not implemented: loadSystemFont without the Font Loading API.\");\n  }\n  async bind(font) {\n    if (font.attached || font.missingFile && !font.systemFontInfo) {\n      return;\n    }\n    font.attached = true;\n    if (font.systemFontInfo) {\n      await this.loadSystemFont(font);\n      return;\n    }\n    if (this.isFontLoadingAPISupported) {\n      const nativeFontFace = font.createNativeFontFace();\n      if (nativeFontFace) {\n        this.addNativeFontFace(nativeFontFace);\n        try {\n          await nativeFontFace.loaded;\n        } catch (ex) {\n          (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`Failed to load font '${nativeFontFace.family}': '${ex}'.`);\n          font.disableFontFace = true;\n          throw ex;\n        }\n      }\n      return;\n    }\n    const rule = font.createFontFaceRule();\n    if (rule) {\n      this.insertRule(rule);\n      if (this.isSyncFontLoadingSupported) {\n        return;\n      }\n      await new Promise(resolve => {\n        const request = this._queueLoadingCallback(resolve);\n        this._prepareFontLoadEvent(font, request);\n      });\n    }\n  }\n  get isFontLoadingAPISupported() {\n    const hasFonts = !!this._document?.fonts;\n    return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, \"isFontLoadingAPISupported\", hasFonts);\n  }\n  get isSyncFontLoadingSupported() {\n    let supported = false;\n    if (_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.isNodeJS) {\n      supported = true;\n    } else if (typeof navigator !== \"undefined\" && typeof navigator?.userAgent === \"string\" && /Mozilla\\/5.0.*?rv:\\d+.*? Gecko/.test(navigator.userAgent)) {\n      supported = true;\n    }\n    return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, \"isSyncFontLoadingSupported\", supported);\n  }\n  _queueLoadingCallback(callback) {\n    function completeRequest() {\n      (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(!request.done, \"completeRequest() cannot be called twice.\");\n      request.done = true;\n      while (loadingRequests.length > 0 && loadingRequests[0].done) {\n        const otherRequest = loadingRequests.shift();\n        setTimeout(otherRequest.callback, 0);\n      }\n    }\n    const {\n      loadingRequests\n    } = this;\n    const request = {\n      done: false,\n      complete: completeRequest,\n      callback\n    };\n    loadingRequests.push(request);\n    return request;\n  }\n  get _loadTestFont() {\n    const testFont = atob(\"T1RUTwALAIAAAwAwQ0ZGIDHtZg4AAAOYAAAAgUZGVE1lkzZwAAAEHAAAABxHREVGABQA\" + \"FQAABDgAAAAeT1MvMlYNYwkAAAEgAAAAYGNtYXABDQLUAAACNAAAAUJoZWFk/xVFDQAA\" + \"ALwAAAA2aGhlYQdkA+oAAAD0AAAAJGhtdHgD6AAAAAAEWAAAAAZtYXhwAAJQAAAAARgA\" + \"AAAGbmFtZVjmdH4AAAGAAAAAsXBvc3T/hgAzAAADeAAAACAAAQAAAAEAALZRFsRfDzz1\" + \"AAsD6AAAAADOBOTLAAAAAM4KHDwAAAAAA+gDIQAAAAgAAgAAAAAAAAABAAADIQAAAFoD\" + \"6AAAAAAD6AABAAAAAAAAAAAAAAAAAAAAAQAAUAAAAgAAAAQD6AH0AAUAAAKKArwAAACM\" + \"AooCvAAAAeAAMQECAAACAAYJAAAAAAAAAAAAAQAAAAAAAAAAAAAAAFBmRWQAwAAuAC4D\" + \"IP84AFoDIQAAAAAAAQAAAAAAAAAAACAAIAABAAAADgCuAAEAAAAAAAAAAQAAAAEAAAAA\" + \"AAEAAQAAAAEAAAAAAAIAAQAAAAEAAAAAAAMAAQAAAAEAAAAAAAQAAQAAAAEAAAAAAAUA\" + \"AQAAAAEAAAAAAAYAAQAAAAMAAQQJAAAAAgABAAMAAQQJAAEAAgABAAMAAQQJAAIAAgAB\" + \"AAMAAQQJAAMAAgABAAMAAQQJAAQAAgABAAMAAQQJAAUAAgABAAMAAQQJAAYAAgABWABY\" + \"AAAAAAAAAwAAAAMAAAAcAAEAAAAAADwAAwABAAAAHAAEACAAAAAEAAQAAQAAAC7//wAA\" + \"AC7////TAAEAAAAAAAABBgAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\" + \"AAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\" + \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\" + \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\" + \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\" + \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAD/gwAyAAAAAQAAAAAAAAAAAAAAAAAA\" + \"AAABAAQEAAEBAQJYAAEBASH4DwD4GwHEAvgcA/gXBIwMAYuL+nz5tQXkD5j3CBLnEQAC\" + \"AQEBIVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYAAABAQAADwACAQEEE/t3\" + \"Dov6fAH6fAT+fPp8+nwHDosMCvm1Cvm1DAz6fBQAAAAAAAABAAAAAMmJbzEAAAAAzgTj\" + \"FQAAAADOBOQpAAEAAAAAAAAADAAUAAQAAAABAAAAAgABAAAAAAAAAAAD6AAAAAAAAA==\");\n    return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, \"_loadTestFont\", testFont);\n  }\n  _prepareFontLoadEvent(font, request) {\n    function int32(data, offset) {\n      return data.charCodeAt(offset) << 24 | data.charCodeAt(offset + 1) << 16 | data.charCodeAt(offset + 2) << 8 | data.charCodeAt(offset + 3) & 0xff;\n    }\n    function spliceString(s, offset, remove, insert) {\n      const chunk1 = s.substring(0, offset);\n      const chunk2 = s.substring(offset + remove);\n      return chunk1 + insert + chunk2;\n    }\n    let i, ii;\n    const canvas = this._document.createElement(\"canvas\");\n    canvas.width = 1;\n    canvas.height = 1;\n    const ctx = canvas.getContext(\"2d\");\n    let called = 0;\n    function isFontReady(name, callback) {\n      if (++called > 30) {\n        (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(\"Load test font never loaded.\");\n        callback();\n        return;\n      }\n      ctx.font = \"30px \" + name;\n      ctx.fillText(\".\", 0, 20);\n      const imageData = ctx.getImageData(0, 0, 1, 1);\n      if (imageData.data[3] > 0) {\n        callback();\n        return;\n      }\n      setTimeout(isFontReady.bind(null, name, callback));\n    }\n    const loadTestFontId = `lt${Date.now()}${this.loadTestFontId++}`;\n    let data = this._loadTestFont;\n    const COMMENT_OFFSET = 976;\n    data = spliceString(data, COMMENT_OFFSET, loadTestFontId.length, loadTestFontId);\n    const CFF_CHECKSUM_OFFSET = 16;\n    const XXXX_VALUE = 0x58585858;\n    let checksum = int32(data, CFF_CHECKSUM_OFFSET);\n    for (i = 0, ii = loadTestFontId.length - 3; i < ii; i += 4) {\n      checksum = checksum - XXXX_VALUE + int32(loadTestFontId, i) | 0;\n    }\n    if (i < loadTestFontId.length) {\n      checksum = checksum - XXXX_VALUE + int32(loadTestFontId + \"XXX\", i) | 0;\n    }\n    data = spliceString(data, CFF_CHECKSUM_OFFSET, 4, (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.string32)(checksum));\n    const url = `url(data:font/opentype;base64,${btoa(data)});`;\n    const rule = `@font-face {font-family:\"${loadTestFontId}\";src:${url}}`;\n    this.insertRule(rule);\n    const div = this._document.createElement(\"div\");\n    div.style.visibility = \"hidden\";\n    div.style.width = div.style.height = \"10px\";\n    div.style.position = \"absolute\";\n    div.style.top = div.style.left = \"0px\";\n    for (const name of [font.loadedName, loadTestFontId]) {\n      const span = this._document.createElement(\"span\");\n      span.textContent = \"Hi\";\n      span.style.fontFamily = name;\n      div.append(span);\n    }\n    this._document.body.append(div);\n    isFontReady(loadTestFontId, () => {\n      div.remove();\n      request.complete();\n    });\n  }\n}\nclass FontFaceObject {\n  constructor(translatedData, {\n    disableFontFace = false,\n    ignoreErrors = false,\n    inspectFont = null\n  }) {\n    this.compiledGlyphs = Object.create(null);\n    for (const i in translatedData) {\n      this[i] = translatedData[i];\n    }\n    this.disableFontFace = disableFontFace === true;\n    this.ignoreErrors = ignoreErrors === true;\n    this._inspectFont = inspectFont;\n  }\n  createNativeFontFace() {\n    if (!this.data || this.disableFontFace) {\n      return null;\n    }\n    let nativeFontFace;\n    if (!this.cssFontInfo) {\n      nativeFontFace = new FontFace(this.loadedName, this.data, {});\n    } else {\n      const css = {\n        weight: this.cssFontInfo.fontWeight\n      };\n      if (this.cssFontInfo.italicAngle) {\n        css.style = `oblique ${this.cssFontInfo.italicAngle}deg`;\n      }\n      nativeFontFace = new FontFace(this.cssFontInfo.fontFamily, this.data, css);\n    }\n    this._inspectFont?.(this);\n    return nativeFontFace;\n  }\n  createFontFaceRule() {\n    if (!this.data || this.disableFontFace) {\n      return null;\n    }\n    const data = (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.bytesToString)(this.data);\n    const url = `url(data:${this.mimetype};base64,${btoa(data)});`;\n    let rule;\n    if (!this.cssFontInfo) {\n      rule = `@font-face {font-family:\"${this.loadedName}\";src:${url}}`;\n    } else {\n      let css = `font-weight: ${this.cssFontInfo.fontWeight};`;\n      if (this.cssFontInfo.italicAngle) {\n        css += `font-style: oblique ${this.cssFontInfo.italicAngle}deg;`;\n      }\n      rule = `@font-face {font-family:\"${this.cssFontInfo.fontFamily}\";${css}src:${url}}`;\n    }\n    this._inspectFont?.(this, url);\n    return rule;\n  }\n  getPathGenerator(objs, character) {\n    if (this.compiledGlyphs[character] !== undefined) {\n      return this.compiledGlyphs[character];\n    }\n    let cmds;\n    try {\n      cmds = objs.get(this.loadedName + \"_path_\" + character);\n    } catch (ex) {\n      if (!this.ignoreErrors) {\n        throw ex;\n      }\n      (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`getPathGenerator - ignoring character: \"${ex}\".`);\n    }\n    if (!Array.isArray(cmds) || cmds.length === 0) {\n      return this.compiledGlyphs[character] = function (c, size) {};\n    }\n    const commands = [];\n    for (let i = 0, ii = cmds.length; i < ii;) {\n      switch (cmds[i++]) {\n        case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.FontRenderOps.BEZIER_CURVE_TO:\n          {\n            const [a, b, c, d, e, f] = cmds.slice(i, i + 6);\n            commands.push(ctx => ctx.bezierCurveTo(a, b, c, d, e, f));\n            i += 6;\n          }\n          break;\n        case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.FontRenderOps.MOVE_TO:\n          {\n            const [a, b] = cmds.slice(i, i + 2);\n            commands.push(ctx => ctx.moveTo(a, b));\n            i += 2;\n          }\n          break;\n        case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.FontRenderOps.LINE_TO:\n          {\n            const [a, b] = cmds.slice(i, i + 2);\n            commands.push(ctx => ctx.lineTo(a, b));\n            i += 2;\n          }\n          break;\n        case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.FontRenderOps.QUADRATIC_CURVE_TO:\n          {\n            const [a, b, c, d] = cmds.slice(i, i + 4);\n            commands.push(ctx => ctx.quadraticCurveTo(a, b, c, d));\n            i += 4;\n          }\n          break;\n        case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.FontRenderOps.RESTORE:\n          commands.push(ctx => ctx.restore());\n          break;\n        case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.FontRenderOps.SAVE:\n          commands.push(ctx => ctx.save());\n          break;\n        case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.FontRenderOps.SCALE:\n          (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(commands.length === 2, \"Scale command is only valid at the third position.\");\n          break;\n        case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.FontRenderOps.TRANSFORM:\n          {\n            const [a, b, c, d, e, f] = cmds.slice(i, i + 6);\n            commands.push(ctx => ctx.transform(a, b, c, d, e, f));\n            i += 6;\n          }\n          break;\n        case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.FontRenderOps.TRANSLATE:\n          {\n            const [a, b] = cmds.slice(i, i + 2);\n            commands.push(ctx => ctx.translate(a, b));\n            i += 2;\n          }\n          break;\n      }\n    }\n    return this.compiledGlyphs[character] = function glyphDrawer(ctx, size) {\n      commands[0](ctx);\n      commands[1](ctx);\n      ctx.scale(size, -size);\n      for (let i = 2, ii = commands.length; i < ii; i++) {\n        commands[i](ctx);\n      }\n    };\n  }\n}\n\n\n/***/ }),\n\n/***/ 62:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   Metadata: () => (/* binding */ Metadata)\n/* harmony export */ });\n/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292);\n\nclass Metadata {\n  #metadataMap;\n  #data;\n  constructor({\n    parsedData,\n    rawData\n  }) {\n    this.#metadataMap = parsedData;\n    this.#data = rawData;\n  }\n  getRaw() {\n    return this.#data;\n  }\n  get(name) {\n    return this.#metadataMap.get(name) ?? null;\n  }\n  getAll() {\n    return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.objectFromMap)(this.#metadataMap);\n  }\n  has(name) {\n    return this.#metadataMap.has(name);\n  }\n}\n\n\n/***/ }),\n\n/***/ 457:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   PDFNetworkStream: () => (/* binding */ PDFNetworkStream)\n/* harmony export */ });\n/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292);\n/* harmony import */ var _network_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(490);\n\n\nconst OK_RESPONSE = 200;\nconst PARTIAL_CONTENT_RESPONSE = 206;\nfunction getArrayBuffer(xhr) {\n  const data = xhr.response;\n  if (typeof data !== \"string\") {\n    return data;\n  }\n  return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.stringToBytes)(data).buffer;\n}\nclass NetworkManager {\n  constructor(url, args = {}) {\n    this.url = url;\n    this.isHttp = /^https?:/i.test(url);\n    this.httpHeaders = this.isHttp && args.httpHeaders || Object.create(null);\n    this.withCredentials = args.withCredentials || false;\n    this.currXhrId = 0;\n    this.pendingRequests = Object.create(null);\n  }\n  requestRange(begin, end, listeners) {\n    const args = {\n      begin,\n      end\n    };\n    for (const prop in listeners) {\n      args[prop] = listeners[prop];\n    }\n    return this.request(args);\n  }\n  requestFull(listeners) {\n    return this.request(listeners);\n  }\n  request(args) {\n    const xhr = new XMLHttpRequest();\n    const xhrId = this.currXhrId++;\n    const pendingRequest = this.pendingRequests[xhrId] = {\n      xhr\n    };\n    xhr.open(\"GET\", this.url);\n    xhr.withCredentials = this.withCredentials;\n    for (const property in this.httpHeaders) {\n      const value = this.httpHeaders[property];\n      if (value === undefined) {\n        continue;\n      }\n      xhr.setRequestHeader(property, value);\n    }\n    if (this.isHttp && \"begin\" in args && \"end\" in args) {\n      xhr.setRequestHeader(\"Range\", `bytes=${args.begin}-${args.end - 1}`);\n      pendingRequest.expectedStatus = PARTIAL_CONTENT_RESPONSE;\n    } else {\n      pendingRequest.expectedStatus = OK_RESPONSE;\n    }\n    xhr.responseType = \"arraybuffer\";\n    if (args.onError) {\n      xhr.onerror = function (evt) {\n        args.onError(xhr.status);\n      };\n    }\n    xhr.onreadystatechange = this.onStateChange.bind(this, xhrId);\n    xhr.onprogress = this.onProgress.bind(this, xhrId);\n    pendingRequest.onHeadersReceived = args.onHeadersReceived;\n    pendingRequest.onDone = args.onDone;\n    pendingRequest.onError = args.onError;\n    pendingRequest.onProgress = args.onProgress;\n    xhr.send(null);\n    return xhrId;\n  }\n  onProgress(xhrId, evt) {\n    const pendingRequest = this.pendingRequests[xhrId];\n    if (!pendingRequest) {\n      return;\n    }\n    pendingRequest.onProgress?.(evt);\n  }\n  onStateChange(xhrId, evt) {\n    const pendingRequest = this.pendingRequests[xhrId];\n    if (!pendingRequest) {\n      return;\n    }\n    const xhr = pendingRequest.xhr;\n    if (xhr.readyState >= 2 && pendingRequest.onHeadersReceived) {\n      pendingRequest.onHeadersReceived();\n      delete pendingRequest.onHeadersReceived;\n    }\n    if (xhr.readyState !== 4) {\n      return;\n    }\n    if (!(xhrId in this.pendingRequests)) {\n      return;\n    }\n    delete this.pendingRequests[xhrId];\n    if (xhr.status === 0 && this.isHttp) {\n      pendingRequest.onError?.(xhr.status);\n      return;\n    }\n    const xhrStatus = xhr.status || OK_RESPONSE;\n    const ok_response_on_range_request = xhrStatus === OK_RESPONSE && pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE;\n    if (!ok_response_on_range_request && xhrStatus !== pendingRequest.expectedStatus) {\n      pendingRequest.onError?.(xhr.status);\n      return;\n    }\n    const chunk = getArrayBuffer(xhr);\n    if (xhrStatus === PARTIAL_CONTENT_RESPONSE) {\n      const rangeHeader = xhr.getResponseHeader(\"Content-Range\");\n      const matches = /bytes (\\d+)-(\\d+)\\/(\\d+)/.exec(rangeHeader);\n      pendingRequest.onDone({\n        begin: parseInt(matches[1], 10),\n        chunk\n      });\n    } else if (chunk) {\n      pendingRequest.onDone({\n        begin: 0,\n        chunk\n      });\n    } else {\n      pendingRequest.onError?.(xhr.status);\n    }\n  }\n  getRequestXhr(xhrId) {\n    return this.pendingRequests[xhrId].xhr;\n  }\n  isPendingRequest(xhrId) {\n    return xhrId in this.pendingRequests;\n  }\n  abortRequest(xhrId) {\n    const xhr = this.pendingRequests[xhrId].xhr;\n    delete this.pendingRequests[xhrId];\n    xhr.abort();\n  }\n}\nclass PDFNetworkStream {\n  constructor(source) {\n    this._source = source;\n    this._manager = new NetworkManager(source.url, {\n      httpHeaders: source.httpHeaders,\n      withCredentials: source.withCredentials\n    });\n    this._rangeChunkSize = source.rangeChunkSize;\n    this._fullRequestReader = null;\n    this._rangeRequestReaders = [];\n  }\n  _onRangeRequestReaderClosed(reader) {\n    const i = this._rangeRequestReaders.indexOf(reader);\n    if (i >= 0) {\n      this._rangeRequestReaders.splice(i, 1);\n    }\n  }\n  getFullReader() {\n    (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(!this._fullRequestReader, \"PDFNetworkStream.getFullReader can only be called once.\");\n    this._fullRequestReader = new PDFNetworkStreamFullRequestReader(this._manager, this._source);\n    return this._fullRequestReader;\n  }\n  getRangeReader(begin, end) {\n    const reader = new PDFNetworkStreamRangeRequestReader(this._manager, begin, end);\n    reader.onClosed = this._onRangeRequestReaderClosed.bind(this);\n    this._rangeRequestReaders.push(reader);\n    return reader;\n  }\n  cancelAllRequests(reason) {\n    this._fullRequestReader?.cancel(reason);\n    for (const reader of this._rangeRequestReaders.slice(0)) {\n      reader.cancel(reason);\n    }\n  }\n}\nclass PDFNetworkStreamFullRequestReader {\n  constructor(manager, source) {\n    this._manager = manager;\n    const args = {\n      onHeadersReceived: this._onHeadersReceived.bind(this),\n      onDone: this._onDone.bind(this),\n      onError: this._onError.bind(this),\n      onProgress: this._onProgress.bind(this)\n    };\n    this._url = source.url;\n    this._fullRequestId = manager.requestFull(args);\n    this._headersReceivedCapability = Promise.withResolvers();\n    this._disableRange = source.disableRange || false;\n    this._contentLength = source.length;\n    this._rangeChunkSize = source.rangeChunkSize;\n    if (!this._rangeChunkSize && !this._disableRange) {\n      this._disableRange = true;\n    }\n    this._isStreamingSupported = false;\n    this._isRangeSupported = false;\n    this._cachedChunks = [];\n    this._requests = [];\n    this._done = false;\n    this._storedError = undefined;\n    this._filename = null;\n    this.onProgress = null;\n  }\n  _onHeadersReceived() {\n    const fullRequestXhrId = this._fullRequestId;\n    const fullRequestXhr = this._manager.getRequestXhr(fullRequestXhrId);\n    const getResponseHeader = name => fullRequestXhr.getResponseHeader(name);\n    const {\n      allowRangeRequests,\n      suggestedLength\n    } = (0,_network_utils_js__WEBPACK_IMPORTED_MODULE_1__.validateRangeRequestCapabilities)({\n      getResponseHeader,\n      isHttp: this._manager.isHttp,\n      rangeChunkSize: this._rangeChunkSize,\n      disableRange: this._disableRange\n    });\n    if (allowRangeRequests) {\n      this._isRangeSupported = true;\n    }\n    this._contentLength = suggestedLength || this._contentLength;\n    this._filename = (0,_network_utils_js__WEBPACK_IMPORTED_MODULE_1__.extractFilenameFromHeader)(getResponseHeader);\n    if (this._isRangeSupported) {\n      this._manager.abortRequest(fullRequestXhrId);\n    }\n    this._headersReceivedCapability.resolve();\n  }\n  _onDone(data) {\n    if (data) {\n      if (this._requests.length > 0) {\n        const requestCapability = this._requests.shift();\n        requestCapability.resolve({\n          value: data.chunk,\n          done: false\n        });\n      } else {\n        this._cachedChunks.push(data.chunk);\n      }\n    }\n    this._done = true;\n    if (this._cachedChunks.length > 0) {\n      return;\n    }\n    for (const requestCapability of this._requests) {\n      requestCapability.resolve({\n        value: undefined,\n        done: true\n      });\n    }\n    this._requests.length = 0;\n  }\n  _onError(status) {\n    this._storedError = (0,_network_utils_js__WEBPACK_IMPORTED_MODULE_1__.createResponseStatusError)(status, this._url);\n    this._headersReceivedCapability.reject(this._storedError);\n    for (const requestCapability of this._requests) {\n      requestCapability.reject(this._storedError);\n    }\n    this._requests.length = 0;\n    this._cachedChunks.length = 0;\n  }\n  _onProgress(evt) {\n    this.onProgress?.({\n      loaded: evt.loaded,\n      total: evt.lengthComputable ? evt.total : this._contentLength\n    });\n  }\n  get filename() {\n    return this._filename;\n  }\n  get isRangeSupported() {\n    return this._isRangeSupported;\n  }\n  get isStreamingSupported() {\n    return this._isStreamingSupported;\n  }\n  get contentLength() {\n    return this._contentLength;\n  }\n  get headersReady() {\n    return this._headersReceivedCapability.promise;\n  }\n  async read() {\n    if (this._storedError) {\n      throw this._storedError;\n    }\n    if (this._cachedChunks.length > 0) {\n      const chunk = this._cachedChunks.shift();\n      return {\n        value: chunk,\n        done: false\n      };\n    }\n    if (this._done) {\n      return {\n        value: undefined,\n        done: true\n      };\n    }\n    const requestCapability = Promise.withResolvers();\n    this._requests.push(requestCapability);\n    return requestCapability.promise;\n  }\n  cancel(reason) {\n    this._done = true;\n    this._headersReceivedCapability.reject(reason);\n    for (const requestCapability of this._requests) {\n      requestCapability.resolve({\n        value: undefined,\n        done: true\n      });\n    }\n    this._requests.length = 0;\n    if (this._manager.isPendingRequest(this._fullRequestId)) {\n      this._manager.abortRequest(this._fullRequestId);\n    }\n    this._fullRequestReader = null;\n  }\n}\nclass PDFNetworkStreamRangeRequestReader {\n  constructor(manager, begin, end) {\n    this._manager = manager;\n    const args = {\n      onDone: this._onDone.bind(this),\n      onError: this._onError.bind(this),\n      onProgress: this._onProgress.bind(this)\n    };\n    this._url = manager.url;\n    this._requestId = manager.requestRange(begin, end, args);\n    this._requests = [];\n    this._queuedChunk = null;\n    this._done = false;\n    this._storedError = undefined;\n    this.onProgress = null;\n    this.onClosed = null;\n  }\n  _close() {\n    this.onClosed?.(this);\n  }\n  _onDone(data) {\n    const chunk = data.chunk;\n    if (this._requests.length > 0) {\n      const requestCapability = this._requests.shift();\n      requestCapability.resolve({\n        value: chunk,\n        done: false\n      });\n    } else {\n      this._queuedChunk = chunk;\n    }\n    this._done = true;\n    for (const requestCapability of this._requests) {\n      requestCapability.resolve({\n        value: undefined,\n        done: true\n      });\n    }\n    this._requests.length = 0;\n    this._close();\n  }\n  _onError(status) {\n    this._storedError = (0,_network_utils_js__WEBPACK_IMPORTED_MODULE_1__.createResponseStatusError)(status, this._url);\n    for (const requestCapability of this._requests) {\n      requestCapability.reject(this._storedError);\n    }\n    this._requests.length = 0;\n    this._queuedChunk = null;\n  }\n  _onProgress(evt) {\n    if (!this.isStreamingSupported) {\n      this.onProgress?.({\n        loaded: evt.loaded\n      });\n    }\n  }\n  get isStreamingSupported() {\n    return false;\n  }\n  async read() {\n    if (this._storedError) {\n      throw this._storedError;\n    }\n    if (this._queuedChunk !== null) {\n      const chunk = this._queuedChunk;\n      this._queuedChunk = null;\n      return {\n        value: chunk,\n        done: false\n      };\n    }\n    if (this._done) {\n      return {\n        value: undefined,\n        done: true\n      };\n    }\n    const requestCapability = Promise.withResolvers();\n    this._requests.push(requestCapability);\n    return requestCapability.promise;\n  }\n  cancel(reason) {\n    this._done = true;\n    for (const requestCapability of this._requests) {\n      requestCapability.resolve({\n        value: undefined,\n        done: true\n      });\n    }\n    this._requests.length = 0;\n    if (this._manager.isPendingRequest(this._requestId)) {\n      this._manager.abortRequest(this._requestId);\n    }\n    this._close();\n  }\n}\n\n\n/***/ }),\n\n/***/ 490:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, {\n  createResponseStatusError: () => (/* binding */ createResponseStatusError),\n  extractFilenameFromHeader: () => (/* binding */ extractFilenameFromHeader),\n  validateRangeRequestCapabilities: () => (/* binding */ validateRangeRequestCapabilities),\n  validateResponseStatus: () => (/* binding */ validateResponseStatus)\n});\n\n// EXTERNAL MODULE: ./src/shared/util.js\nvar util = __webpack_require__(292);\n;// CONCATENATED MODULE: ./src/display/content_disposition.js\n\nfunction getFilenameFromContentDispositionHeader(contentDisposition) {\n  let needsEncodingFixup = true;\n  let tmp = toParamRegExp(\"filename\\\\*\", \"i\").exec(contentDisposition);\n  if (tmp) {\n    tmp = tmp[1];\n    let filename = rfc2616unquote(tmp);\n    filename = unescape(filename);\n    filename = rfc5987decode(filename);\n    filename = rfc2047decode(filename);\n    return fixupEncoding(filename);\n  }\n  tmp = rfc2231getparam(contentDisposition);\n  if (tmp) {\n    const filename = rfc2047decode(tmp);\n    return fixupEncoding(filename);\n  }\n  tmp = toParamRegExp(\"filename\", \"i\").exec(contentDisposition);\n  if (tmp) {\n    tmp = tmp[1];\n    let filename = rfc2616unquote(tmp);\n    filename = rfc2047decode(filename);\n    return fixupEncoding(filename);\n  }\n  function toParamRegExp(attributePattern, flags) {\n    return new RegExp(\"(?:^|;)\\\\s*\" + attributePattern + \"\\\\s*=\\\\s*\" + \"(\" + '[^\";\\\\s][^;\\\\s]*' + \"|\" + '\"(?:[^\"\\\\\\\\]|\\\\\\\\\"?)+\"?' + \")\", flags);\n  }\n  function textdecode(encoding, value) {\n    if (encoding) {\n      if (!/^[\\x00-\\xFF]+$/.test(value)) {\n        return value;\n      }\n      try {\n        const decoder = new TextDecoder(encoding, {\n          fatal: true\n        });\n        const buffer = (0,util.stringToBytes)(value);\n        value = decoder.decode(buffer);\n        needsEncodingFixup = false;\n      } catch {}\n    }\n    return value;\n  }\n  function fixupEncoding(value) {\n    if (needsEncodingFixup && /[\\x80-\\xff]/.test(value)) {\n      value = textdecode(\"utf-8\", value);\n      if (needsEncodingFixup) {\n        value = textdecode(\"iso-8859-1\", value);\n      }\n    }\n    return value;\n  }\n  function rfc2231getparam(contentDispositionStr) {\n    const matches = [];\n    let match;\n    const iter = toParamRegExp(\"filename\\\\*((?!0\\\\d)\\\\d+)(\\\\*?)\", \"ig\");\n    while ((match = iter.exec(contentDispositionStr)) !== null) {\n      let [, n, quot, part] = match;\n      n = parseInt(n, 10);\n      if (n in matches) {\n        if (n === 0) {\n          break;\n        }\n        continue;\n      }\n      matches[n] = [quot, part];\n    }\n    const parts = [];\n    for (let n = 0; n < matches.length; ++n) {\n      if (!(n in matches)) {\n        break;\n      }\n      let [quot, part] = matches[n];\n      part = rfc2616unquote(part);\n      if (quot) {\n        part = unescape(part);\n        if (n === 0) {\n          part = rfc5987decode(part);\n        }\n      }\n      parts.push(part);\n    }\n    return parts.join(\"\");\n  }\n  function rfc2616unquote(value) {\n    if (value.startsWith('\"')) {\n      const parts = value.slice(1).split('\\\\\"');\n      for (let i = 0; i < parts.length; ++i) {\n        const quotindex = parts[i].indexOf('\"');\n        if (quotindex !== -1) {\n          parts[i] = parts[i].slice(0, quotindex);\n          parts.length = i + 1;\n        }\n        parts[i] = parts[i].replaceAll(/\\\\(.)/g, \"$1\");\n      }\n      value = parts.join('\"');\n    }\n    return value;\n  }\n  function rfc5987decode(extvalue) {\n    const encodingend = extvalue.indexOf(\"'\");\n    if (encodingend === -1) {\n      return extvalue;\n    }\n    const encoding = extvalue.slice(0, encodingend);\n    const langvalue = extvalue.slice(encodingend + 1);\n    const value = langvalue.replace(/^[^']*'/, \"\");\n    return textdecode(encoding, value);\n  }\n  function rfc2047decode(value) {\n    if (!value.startsWith(\"=?\") || /[\\x00-\\x19\\x80-\\xff]/.test(value)) {\n      return value;\n    }\n    return value.replaceAll(/=\\?([\\w-]*)\\?([QqBb])\\?((?:[^?]|\\?(?!=))*)\\?=/g, function (matches, charset, encoding, text) {\n      if (encoding === \"q\" || encoding === \"Q\") {\n        text = text.replaceAll(\"_\", \" \");\n        text = text.replaceAll(/=([0-9a-fA-F]{2})/g, function (match, hex) {\n          return String.fromCharCode(parseInt(hex, 16));\n        });\n        return textdecode(charset, text);\n      }\n      try {\n        text = atob(text);\n      } catch {}\n      return textdecode(charset, text);\n    });\n  }\n  return \"\";\n}\n\n// EXTERNAL MODULE: ./src/display/display_utils.js\nvar display_utils = __webpack_require__(419);\n;// CONCATENATED MODULE: ./src/display/network_utils.js\n\n\n\nfunction validateRangeRequestCapabilities({\n  getResponseHeader,\n  isHttp,\n  rangeChunkSize,\n  disableRange\n}) {\n  const returnValues = {\n    allowRangeRequests: false,\n    suggestedLength: undefined\n  };\n  const length = parseInt(getResponseHeader(\"Content-Length\"), 10);\n  if (!Number.isInteger(length)) {\n    return returnValues;\n  }\n  returnValues.suggestedLength = length;\n  if (length <= 2 * rangeChunkSize) {\n    return returnValues;\n  }\n  if (disableRange || !isHttp) {\n    return returnValues;\n  }\n  if (getResponseHeader(\"Accept-Ranges\") !== \"bytes\") {\n    return returnValues;\n  }\n  const contentEncoding = getResponseHeader(\"Content-Encoding\") || \"identity\";\n  if (contentEncoding !== \"identity\") {\n    return returnValues;\n  }\n  returnValues.allowRangeRequests = true;\n  return returnValues;\n}\nfunction extractFilenameFromHeader(getResponseHeader) {\n  const contentDisposition = getResponseHeader(\"Content-Disposition\");\n  if (contentDisposition) {\n    let filename = getFilenameFromContentDispositionHeader(contentDisposition);\n    if (filename.includes(\"%\")) {\n      try {\n        filename = decodeURIComponent(filename);\n      } catch {}\n    }\n    if ((0,display_utils.isPdfFile)(filename)) {\n      return filename;\n    }\n  }\n  return null;\n}\nfunction createResponseStatusError(status, url) {\n  if (status === 404 || status === 0 && url.startsWith(\"file:\")) {\n    return new util.MissingPDFException('Missing PDF \"' + url + '\".');\n  }\n  return new util.UnexpectedResponseException(`Unexpected server response (${status}) while retrieving PDF \"${url}\".`, status);\n}\nfunction validateResponseStatus(status) {\n  return status === 200 || status === 206;\n}\n\n\n/***/ }),\n\n/***/ 786:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   PDFNodeStream: () => (/* binding */ PDFNodeStream)\n/* harmony export */ });\n/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292);\n/* harmony import */ var _network_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(490);\n\n\nlet fs, http, https, url;\nif (_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.isNodeJS) {\n  fs = await import( /*webpackIgnore: true*/\"fs\");\n  http = await import( /*webpackIgnore: true*/\"http\");\n  https = await import( /*webpackIgnore: true*/\"https\");\n  url = await import( /*webpackIgnore: true*/\"url\");\n}\nconst fileUriRegex = /^file:\\/\\/\\/[a-zA-Z]:\\//;\nfunction parseUrl(sourceUrl) {\n  const parsedUrl = url.parse(sourceUrl);\n  if (parsedUrl.protocol === \"file:\" || parsedUrl.host) {\n    return parsedUrl;\n  }\n  if (/^[a-z]:[/\\\\]/i.test(sourceUrl)) {\n    return url.parse(`file:///${sourceUrl}`);\n  }\n  if (!parsedUrl.host) {\n    parsedUrl.protocol = \"file:\";\n  }\n  return parsedUrl;\n}\nclass PDFNodeStream {\n  constructor(source) {\n    this.source = source;\n    this.url = parseUrl(source.url);\n    this.isHttp = this.url.protocol === \"http:\" || this.url.protocol === \"https:\";\n    this.isFsUrl = this.url.protocol === \"file:\";\n    this.httpHeaders = this.isHttp && source.httpHeaders || {};\n    this._fullRequestReader = null;\n    this._rangeRequestReaders = [];\n  }\n  get _progressiveDataLength() {\n    return this._fullRequestReader?._loaded ?? 0;\n  }\n  getFullReader() {\n    (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(!this._fullRequestReader, \"PDFNodeStream.getFullReader can only be called once.\");\n    this._fullRequestReader = this.isFsUrl ? new PDFNodeStreamFsFullReader(this) : new PDFNodeStreamFullReader(this);\n    return this._fullRequestReader;\n  }\n  getRangeReader(start, end) {\n    if (end <= this._progressiveDataLength) {\n      return null;\n    }\n    const rangeReader = this.isFsUrl ? new PDFNodeStreamFsRangeReader(this, start, end) : new PDFNodeStreamRangeReader(this, start, end);\n    this._rangeRequestReaders.push(rangeReader);\n    return rangeReader;\n  }\n  cancelAllRequests(reason) {\n    this._fullRequestReader?.cancel(reason);\n    for (const reader of this._rangeRequestReaders.slice(0)) {\n      reader.cancel(reason);\n    }\n  }\n}\nclass BaseFullReader {\n  constructor(stream) {\n    this._url = stream.url;\n    this._done = false;\n    this._storedError = null;\n    this.onProgress = null;\n    const source = stream.source;\n    this._contentLength = source.length;\n    this._loaded = 0;\n    this._filename = null;\n    this._disableRange = source.disableRange || false;\n    this._rangeChunkSize = source.rangeChunkSize;\n    if (!this._rangeChunkSize && !this._disableRange) {\n      this._disableRange = true;\n    }\n    this._isStreamingSupported = !source.disableStream;\n    this._isRangeSupported = !source.disableRange;\n    this._readableStream = null;\n    this._readCapability = Promise.withResolvers();\n    this._headersCapability = Promise.withResolvers();\n  }\n  get headersReady() {\n    return this._headersCapability.promise;\n  }\n  get filename() {\n    return this._filename;\n  }\n  get contentLength() {\n    return this._contentLength;\n  }\n  get isRangeSupported() {\n    return this._isRangeSupported;\n  }\n  get isStreamingSupported() {\n    return this._isStreamingSupported;\n  }\n  async read() {\n    await this._readCapability.promise;\n    if (this._done) {\n      return {\n        value: undefined,\n        done: true\n      };\n    }\n    if (this._storedError) {\n      throw this._storedError;\n    }\n    const chunk = this._readableStream.read();\n    if (chunk === null) {\n      this._readCapability = Promise.withResolvers();\n      return this.read();\n    }\n    this._loaded += chunk.length;\n    this.onProgress?.({\n      loaded: this._loaded,\n      total: this._contentLength\n    });\n    const buffer = new Uint8Array(chunk).buffer;\n    return {\n      value: buffer,\n      done: false\n    };\n  }\n  cancel(reason) {\n    if (!this._readableStream) {\n      this._error(reason);\n      return;\n    }\n    this._readableStream.destroy(reason);\n  }\n  _error(reason) {\n    this._storedError = reason;\n    this._readCapability.resolve();\n  }\n  _setReadableStream(readableStream) {\n    this._readableStream = readableStream;\n    readableStream.on(\"readable\", () => {\n      this._readCapability.resolve();\n    });\n    readableStream.on(\"end\", () => {\n      readableStream.destroy();\n      this._done = true;\n      this._readCapability.resolve();\n    });\n    readableStream.on(\"error\", reason => {\n      this._error(reason);\n    });\n    if (!this._isStreamingSupported && this._isRangeSupported) {\n      this._error(new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AbortException(\"streaming is disabled\"));\n    }\n    if (this._storedError) {\n      this._readableStream.destroy(this._storedError);\n    }\n  }\n}\nclass BaseRangeReader {\n  constructor(stream) {\n    this._url = stream.url;\n    this._done = false;\n    this._storedError = null;\n    this.onProgress = null;\n    this._loaded = 0;\n    this._readableStream = null;\n    this._readCapability = Promise.withResolvers();\n    const source = stream.source;\n    this._isStreamingSupported = !source.disableStream;\n  }\n  get isStreamingSupported() {\n    return this._isStreamingSupported;\n  }\n  async read() {\n    await this._readCapability.promise;\n    if (this._done) {\n      return {\n        value: undefined,\n        done: true\n      };\n    }\n    if (this._storedError) {\n      throw this._storedError;\n    }\n    const chunk = this._readableStream.read();\n    if (chunk === null) {\n      this._readCapability = Promise.withResolvers();\n      return this.read();\n    }\n    this._loaded += chunk.length;\n    this.onProgress?.({\n      loaded: this._loaded\n    });\n    const buffer = new Uint8Array(chunk).buffer;\n    return {\n      value: buffer,\n      done: false\n    };\n  }\n  cancel(reason) {\n    if (!this._readableStream) {\n      this._error(reason);\n      return;\n    }\n    this._readableStream.destroy(reason);\n  }\n  _error(reason) {\n    this._storedError = reason;\n    this._readCapability.resolve();\n  }\n  _setReadableStream(readableStream) {\n    this._readableStream = readableStream;\n    readableStream.on(\"readable\", () => {\n      this._readCapability.resolve();\n    });\n    readableStream.on(\"end\", () => {\n      readableStream.destroy();\n      this._done = true;\n      this._readCapability.resolve();\n    });\n    readableStream.on(\"error\", reason => {\n      this._error(reason);\n    });\n    if (this._storedError) {\n      this._readableStream.destroy(this._storedError);\n    }\n  }\n}\nfunction createRequestOptions(parsedUrl, headers) {\n  return {\n    protocol: parsedUrl.protocol,\n    auth: parsedUrl.auth,\n    host: parsedUrl.hostname,\n    port: parsedUrl.port,\n    path: parsedUrl.path,\n    method: \"GET\",\n    headers\n  };\n}\nclass PDFNodeStreamFullReader extends BaseFullReader {\n  constructor(stream) {\n    super(stream);\n    const handleResponse = response => {\n      if (response.statusCode === 404) {\n        const error = new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.MissingPDFException(`Missing PDF \"${this._url}\".`);\n        this._storedError = error;\n        this._headersCapability.reject(error);\n        return;\n      }\n      this._headersCapability.resolve();\n      this._setReadableStream(response);\n      const getResponseHeader = name => this._readableStream.headers[name.toLowerCase()];\n      const {\n        allowRangeRequests,\n        suggestedLength\n      } = (0,_network_utils_js__WEBPACK_IMPORTED_MODULE_1__.validateRangeRequestCapabilities)({\n        getResponseHeader,\n        isHttp: stream.isHttp,\n        rangeChunkSize: this._rangeChunkSize,\n        disableRange: this._disableRange\n      });\n      this._isRangeSupported = allowRangeRequests;\n      this._contentLength = suggestedLength || this._contentLength;\n      this._filename = (0,_network_utils_js__WEBPACK_IMPORTED_MODULE_1__.extractFilenameFromHeader)(getResponseHeader);\n    };\n    this._request = null;\n    if (this._url.protocol === \"http:\") {\n      this._request = http.request(createRequestOptions(this._url, stream.httpHeaders), handleResponse);\n    } else {\n      this._request = https.request(createRequestOptions(this._url, stream.httpHeaders), handleResponse);\n    }\n    this._request.on(\"error\", reason => {\n      this._storedError = reason;\n      this._headersCapability.reject(reason);\n    });\n    this._request.end();\n  }\n}\nclass PDFNodeStreamRangeReader extends BaseRangeReader {\n  constructor(stream, start, end) {\n    super(stream);\n    this._httpHeaders = {};\n    for (const property in stream.httpHeaders) {\n      const value = stream.httpHeaders[property];\n      if (value === undefined) {\n        continue;\n      }\n      this._httpHeaders[property] = value;\n    }\n    this._httpHeaders.Range = `bytes=${start}-${end - 1}`;\n    const handleResponse = response => {\n      if (response.statusCode === 404) {\n        const error = new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.MissingPDFException(`Missing PDF \"${this._url}\".`);\n        this._storedError = error;\n        return;\n      }\n      this._setReadableStream(response);\n    };\n    this._request = null;\n    if (this._url.protocol === \"http:\") {\n      this._request = http.request(createRequestOptions(this._url, this._httpHeaders), handleResponse);\n    } else {\n      this._request = https.request(createRequestOptions(this._url, this._httpHeaders), handleResponse);\n    }\n    this._request.on(\"error\", reason => {\n      this._storedError = reason;\n    });\n    this._request.end();\n  }\n}\nclass PDFNodeStreamFsFullReader extends BaseFullReader {\n  constructor(stream) {\n    super(stream);\n    let path = decodeURIComponent(this._url.path);\n    if (fileUriRegex.test(this._url.href)) {\n      path = path.replace(/^\\//, \"\");\n    }\n    fs.promises.lstat(path).then(stat => {\n      this._contentLength = stat.size;\n      this._setReadableStream(fs.createReadStream(path));\n      this._headersCapability.resolve();\n    }, error => {\n      if (error.code === \"ENOENT\") {\n        error = new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.MissingPDFException(`Missing PDF \"${path}\".`);\n      }\n      this._storedError = error;\n      this._headersCapability.reject(error);\n    });\n  }\n}\nclass PDFNodeStreamFsRangeReader extends BaseRangeReader {\n  constructor(stream, start, end) {\n    super(stream);\n    let path = decodeURIComponent(this._url.path);\n    if (fileUriRegex.test(this._url.href)) {\n      path = path.replace(/^\\//, \"\");\n    }\n    this._setReadableStream(fs.createReadStream(path, {\n      start,\n      end: end - 1\n    }));\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } }, 1);\n\n/***/ }),\n\n/***/ 573:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   NodeCMapReaderFactory: () => (/* binding */ NodeCMapReaderFactory),\n/* harmony export */   NodeCanvasFactory: () => (/* binding */ NodeCanvasFactory),\n/* harmony export */   NodeFilterFactory: () => (/* binding */ NodeFilterFactory),\n/* harmony export */   NodeStandardFontDataFactory: () => (/* binding */ NodeStandardFontDataFactory)\n/* harmony export */ });\n/* harmony import */ var _base_factory_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(583);\n/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(292);\n\n\nlet fs, canvas, path2d;\nif (_shared_util_js__WEBPACK_IMPORTED_MODULE_1__.isNodeJS) {\n  fs = await import( /*webpackIgnore: true*/\"fs\");\n  try {\n    canvas = await import( /*webpackIgnore: true*/\"canvas\");\n  } catch {}\n  try {\n    path2d = await import( /*webpackIgnore: true*/\"path2d\");\n  } catch {}\n}\nconst fetchData = function (url) {\n  return fs.promises.readFile(url).then(data => new Uint8Array(data));\n};\nclass NodeFilterFactory extends _base_factory_js__WEBPACK_IMPORTED_MODULE_0__.BaseFilterFactory {}\nclass NodeCanvasFactory extends _base_factory_js__WEBPACK_IMPORTED_MODULE_0__.BaseCanvasFactory {\n  _createCanvas(width, height) {\n    return canvas.createCanvas(width, height);\n  }\n}\nclass NodeCMapReaderFactory extends _base_factory_js__WEBPACK_IMPORTED_MODULE_0__.BaseCMapReaderFactory {\n  _fetchData(url, compressionType) {\n    return fetchData(url).then(data => ({\n      cMapData: data,\n      compressionType\n    }));\n  }\n}\nclass NodeStandardFontDataFactory extends _base_factory_js__WEBPACK_IMPORTED_MODULE_0__.BaseStandardFontDataFactory {\n  _fetchData(url) {\n    return fetchData(url);\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } }, 1);\n\n/***/ }),\n\n/***/ 626:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   OptionalContentConfig: () => (/* binding */ OptionalContentConfig)\n/* harmony export */ });\n/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292);\n/* harmony import */ var _shared_murmurhash3_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(651);\n\n\nconst INTERNAL = Symbol(\"INTERNAL\");\nclass OptionalContentGroup {\n  #isDisplay = false;\n  #isPrint = false;\n  #userSet = false;\n  #visible = true;\n  constructor(renderingIntent, {\n    name,\n    intent,\n    usage\n  }) {\n    this.#isDisplay = !!(renderingIntent & _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.RenderingIntentFlag.DISPLAY);\n    this.#isPrint = !!(renderingIntent & _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.RenderingIntentFlag.PRINT);\n    this.name = name;\n    this.intent = intent;\n    this.usage = usage;\n  }\n  get visible() {\n    if (this.#userSet) {\n      return this.#visible;\n    }\n    if (!this.#visible) {\n      return false;\n    }\n    const {\n      print,\n      view\n    } = this.usage;\n    if (this.#isDisplay) {\n      return view?.viewState !== \"OFF\";\n    } else if (this.#isPrint) {\n      return print?.printState !== \"OFF\";\n    }\n    return true;\n  }\n  _setVisible(internal, visible, userSet = false) {\n    if (internal !== INTERNAL) {\n      (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)(\"Internal method `_setVisible` called.\");\n    }\n    this.#userSet = userSet;\n    this.#visible = visible;\n  }\n}\nclass OptionalContentConfig {\n  #cachedGetHash = null;\n  #groups = new Map();\n  #initialHash = null;\n  #order = null;\n  constructor(data, renderingIntent = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.RenderingIntentFlag.DISPLAY) {\n    this.renderingIntent = renderingIntent;\n    this.name = null;\n    this.creator = null;\n    if (data === null) {\n      return;\n    }\n    this.name = data.name;\n    this.creator = data.creator;\n    this.#order = data.order;\n    for (const group of data.groups) {\n      this.#groups.set(group.id, new OptionalContentGroup(renderingIntent, group));\n    }\n    if (data.baseState === \"OFF\") {\n      for (const group of this.#groups.values()) {\n        group._setVisible(INTERNAL, false);\n      }\n    }\n    for (const on of data.on) {\n      this.#groups.get(on)._setVisible(INTERNAL, true);\n    }\n    for (const off of data.off) {\n      this.#groups.get(off)._setVisible(INTERNAL, false);\n    }\n    this.#initialHash = this.getHash();\n  }\n  #evaluateVisibilityExpression(array) {\n    const length = array.length;\n    if (length < 2) {\n      return true;\n    }\n    const operator = array[0];\n    for (let i = 1; i < length; i++) {\n      const element = array[i];\n      let state;\n      if (Array.isArray(element)) {\n        state = this.#evaluateVisibilityExpression(element);\n      } else if (this.#groups.has(element)) {\n        state = this.#groups.get(element).visible;\n      } else {\n        (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`Optional content group not found: ${element}`);\n        return true;\n      }\n      switch (operator) {\n        case \"And\":\n          if (!state) {\n            return false;\n          }\n          break;\n        case \"Or\":\n          if (state) {\n            return true;\n          }\n          break;\n        case \"Not\":\n          return !state;\n        default:\n          return true;\n      }\n    }\n    return operator === \"And\";\n  }\n  isVisible(group) {\n    if (this.#groups.size === 0) {\n      return true;\n    }\n    if (!group) {\n      (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.info)(\"Optional content group not defined.\");\n      return true;\n    }\n    if (group.type === \"OCG\") {\n      if (!this.#groups.has(group.id)) {\n        (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`Optional content group not found: ${group.id}`);\n        return true;\n      }\n      return this.#groups.get(group.id).visible;\n    } else if (group.type === \"OCMD\") {\n      if (group.expression) {\n        return this.#evaluateVisibilityExpression(group.expression);\n      }\n      if (!group.policy || group.policy === \"AnyOn\") {\n        for (const id of group.ids) {\n          if (!this.#groups.has(id)) {\n            (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`Optional content group not found: ${id}`);\n            return true;\n          }\n          if (this.#groups.get(id).visible) {\n            return true;\n          }\n        }\n        return false;\n      } else if (group.policy === \"AllOn\") {\n        for (const id of group.ids) {\n          if (!this.#groups.has(id)) {\n            (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`Optional content group not found: ${id}`);\n            return true;\n          }\n          if (!this.#groups.get(id).visible) {\n            return false;\n          }\n        }\n        return true;\n      } else if (group.policy === \"AnyOff\") {\n        for (const id of group.ids) {\n          if (!this.#groups.has(id)) {\n            (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`Optional content group not found: ${id}`);\n            return true;\n          }\n          if (!this.#groups.get(id).visible) {\n            return true;\n          }\n        }\n        return false;\n      } else if (group.policy === \"AllOff\") {\n        for (const id of group.ids) {\n          if (!this.#groups.has(id)) {\n            (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`Optional content group not found: ${id}`);\n            return true;\n          }\n          if (this.#groups.get(id).visible) {\n            return false;\n          }\n        }\n        return true;\n      }\n      (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`Unknown optional content policy ${group.policy}.`);\n      return true;\n    }\n    (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`Unknown group type ${group.type}.`);\n    return true;\n  }\n  setVisibility(id, visible = true) {\n    const group = this.#groups.get(id);\n    if (!group) {\n      (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`Optional content group not found: ${id}`);\n      return;\n    }\n    group._setVisible(INTERNAL, !!visible, true);\n    this.#cachedGetHash = null;\n  }\n  setOCGState({\n    state,\n    preserveRB\n  }) {\n    let operator;\n    for (const elem of state) {\n      switch (elem) {\n        case \"ON\":\n        case \"OFF\":\n        case \"Toggle\":\n          operator = elem;\n          continue;\n      }\n      const group = this.#groups.get(elem);\n      if (!group) {\n        continue;\n      }\n      switch (operator) {\n        case \"ON\":\n          group._setVisible(INTERNAL, true);\n          break;\n        case \"OFF\":\n          group._setVisible(INTERNAL, false);\n          break;\n        case \"Toggle\":\n          group._setVisible(INTERNAL, !group.visible);\n          break;\n      }\n    }\n    this.#cachedGetHash = null;\n  }\n  get hasInitialVisibility() {\n    return this.#initialHash === null || this.getHash() === this.#initialHash;\n  }\n  getOrder() {\n    if (!this.#groups.size) {\n      return null;\n    }\n    if (this.#order) {\n      return this.#order.slice();\n    }\n    return [...this.#groups.keys()];\n  }\n  getGroups() {\n    return this.#groups.size > 0 ? (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.objectFromMap)(this.#groups) : null;\n  }\n  getGroup(id) {\n    return this.#groups.get(id) || null;\n  }\n  getHash() {\n    if (this.#cachedGetHash !== null) {\n      return this.#cachedGetHash;\n    }\n    const hash = new _shared_murmurhash3_js__WEBPACK_IMPORTED_MODULE_1__.MurmurHash3_64();\n    for (const [id, group] of this.#groups) {\n      hash.update(`${id}:${group.visible}`);\n    }\n    return this.#cachedGetHash = hash.hexdigest();\n  }\n}\n\n\n/***/ }),\n\n/***/ 814:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   cleanupTextLayer: () => (/* binding */ cleanupTextLayer),\n/* harmony export */   renderTextLayer: () => (/* binding */ renderTextLayer),\n/* harmony export */   updateTextLayer: () => (/* binding */ updateTextLayer)\n/* harmony export */ });\n/* unused harmony export TextLayerRenderTask */\n/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292);\n/* harmony import */ var _display_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(419);\n\n\nconst MAX_TEXT_DIVS_TO_RENDER = 100000;\nconst DEFAULT_FONT_SIZE = 30;\nconst DEFAULT_FONT_ASCENT = 0.8;\nconst ascentCache = new Map();\nlet _canvasContext = null;\nfunction getCtx() {\n  if (!_canvasContext) {\n    const canvas = document.createElement(\"canvas\");\n    canvas.className = \"hiddenCanvasElement\";\n    document.body.append(canvas);\n    _canvasContext = canvas.getContext(\"2d\", {\n      alpha: false\n    });\n  }\n  return _canvasContext;\n}\nfunction cleanupTextLayer() {\n  _canvasContext?.canvas.remove();\n  _canvasContext = null;\n}\nfunction getAscent(fontFamily) {\n  const cachedAscent = ascentCache.get(fontFamily);\n  if (cachedAscent) {\n    return cachedAscent;\n  }\n  const ctx = getCtx();\n  const savedFont = ctx.font;\n  ctx.canvas.width = ctx.canvas.height = DEFAULT_FONT_SIZE;\n  ctx.font = `${DEFAULT_FONT_SIZE}px ${fontFamily}`;\n  const metrics = ctx.measureText(\"\");\n  let ascent = metrics.fontBoundingBoxAscent;\n  let descent = Math.abs(metrics.fontBoundingBoxDescent);\n  if (ascent) {\n    const ratio = ascent / (ascent + descent);\n    ascentCache.set(fontFamily, ratio);\n    ctx.canvas.width = ctx.canvas.height = 0;\n    ctx.font = savedFont;\n    return ratio;\n  }\n  ctx.strokeStyle = \"red\";\n  ctx.clearRect(0, 0, DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE);\n  ctx.strokeText(\"g\", 0, 0);\n  let pixels = ctx.getImageData(0, 0, DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE).data;\n  descent = 0;\n  for (let i = pixels.length - 1 - 3; i >= 0; i -= 4) {\n    if (pixels[i] > 0) {\n      descent = Math.ceil(i / 4 / DEFAULT_FONT_SIZE);\n      break;\n    }\n  }\n  ctx.clearRect(0, 0, DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE);\n  ctx.strokeText(\"A\", 0, DEFAULT_FONT_SIZE);\n  pixels = ctx.getImageData(0, 0, DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE).data;\n  ascent = 0;\n  for (let i = 0, ii = pixels.length; i < ii; i += 4) {\n    if (pixels[i] > 0) {\n      ascent = DEFAULT_FONT_SIZE - Math.floor(i / 4 / DEFAULT_FONT_SIZE);\n      break;\n    }\n  }\n  ctx.canvas.width = ctx.canvas.height = 0;\n  ctx.font = savedFont;\n  if (ascent) {\n    const ratio = ascent / (ascent + descent);\n    ascentCache.set(fontFamily, ratio);\n    return ratio;\n  }\n  ascentCache.set(fontFamily, DEFAULT_FONT_ASCENT);\n  return DEFAULT_FONT_ASCENT;\n}\nfunction appendText(task, geom, styles) {\n  const textDiv = document.createElement(\"span\");\n  const textDivProperties = {\n    angle: 0,\n    canvasWidth: 0,\n    hasText: geom.str !== \"\",\n    hasEOL: geom.hasEOL,\n    fontSize: 0\n  };\n  task._textDivs.push(textDiv);\n  const tx = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.Util.transform(task._transform, geom.transform);\n  let angle = Math.atan2(tx[1], tx[0]);\n  const style = styles[geom.fontName];\n  if (style.vertical) {\n    angle += Math.PI / 2;\n  }\n  const fontFamily = task._fontInspectorEnabled && style.fontSubstitution || style.fontFamily;\n  const fontHeight = Math.hypot(tx[2], tx[3]);\n  const fontAscent = fontHeight * getAscent(fontFamily);\n  let left, top;\n  if (angle === 0) {\n    left = tx[4];\n    top = tx[5] - fontAscent;\n  } else {\n    left = tx[4] + fontAscent * Math.sin(angle);\n    top = tx[5] - fontAscent * Math.cos(angle);\n  }\n  const scaleFactorStr = \"calc(var(--scale-factor)*\";\n  const divStyle = textDiv.style;\n  if (task._container === task._rootContainer) {\n    divStyle.left = `${(100 * left / task._pageWidth).toFixed(2)}%`;\n    divStyle.top = `${(100 * top / task._pageHeight).toFixed(2)}%`;\n  } else {\n    divStyle.left = `${scaleFactorStr}${left.toFixed(2)}px)`;\n    divStyle.top = `${scaleFactorStr}${top.toFixed(2)}px)`;\n  }\n  divStyle.fontSize = `${scaleFactorStr}${fontHeight.toFixed(2)}px)`;\n  divStyle.fontFamily = fontFamily;\n  textDivProperties.fontSize = fontHeight;\n  textDiv.setAttribute(\"role\", \"presentation\");\n  textDiv.textContent = geom.str;\n  textDiv.dir = geom.dir;\n  if (task._fontInspectorEnabled) {\n    textDiv.dataset.fontName = style.fontSubstitutionLoadedName || geom.fontName;\n  }\n  if (angle !== 0) {\n    textDivProperties.angle = angle * (180 / Math.PI);\n  }\n  let shouldScaleText = false;\n  if (geom.str.length > 1) {\n    shouldScaleText = true;\n  } else if (geom.str !== \" \" && geom.transform[0] !== geom.transform[3]) {\n    const absScaleX = Math.abs(geom.transform[0]),\n      absScaleY = Math.abs(geom.transform[3]);\n    if (absScaleX !== absScaleY && Math.max(absScaleX, absScaleY) / Math.min(absScaleX, absScaleY) > 1.5) {\n      shouldScaleText = true;\n    }\n  }\n  if (shouldScaleText) {\n    textDivProperties.canvasWidth = style.vertical ? geom.height : geom.width;\n  }\n  task._textDivProperties.set(textDiv, textDivProperties);\n  if (task._isReadableStream) {\n    task._layoutText(textDiv);\n  }\n}\nfunction layout(params) {\n  const {\n    div,\n    scale,\n    properties,\n    ctx,\n    prevFontSize,\n    prevFontFamily\n  } = params;\n  const {\n    style\n  } = div;\n  let transform = \"\";\n  if (properties.canvasWidth !== 0 && properties.hasText) {\n    const {\n      fontFamily\n    } = style;\n    const {\n      canvasWidth,\n      fontSize\n    } = properties;\n    if (prevFontSize !== fontSize || prevFontFamily !== fontFamily) {\n      ctx.font = `${fontSize * scale}px ${fontFamily}`;\n      params.prevFontSize = fontSize;\n      params.prevFontFamily = fontFamily;\n    }\n    const {\n      width\n    } = ctx.measureText(div.textContent);\n    if (width > 0) {\n      transform = `scaleX(${canvasWidth * scale / width})`;\n    }\n  }\n  if (properties.angle !== 0) {\n    transform = `rotate(${properties.angle}deg) ${transform}`;\n  }\n  if (transform.length > 0) {\n    style.transform = transform;\n  }\n}\nfunction render(task) {\n  if (task._canceled) {\n    return;\n  }\n  const textDivs = task._textDivs;\n  const capability = task._capability;\n  const textDivsLength = textDivs.length;\n  if (textDivsLength > MAX_TEXT_DIVS_TO_RENDER) {\n    capability.resolve();\n    return;\n  }\n  if (!task._isReadableStream) {\n    for (const textDiv of textDivs) {\n      task._layoutText(textDiv);\n    }\n  }\n  capability.resolve();\n}\nclass TextLayerRenderTask {\n  constructor({\n    textContentSource,\n    container,\n    viewport,\n    textDivs,\n    textDivProperties,\n    textContentItemsStr\n  }) {\n    this._textContentSource = textContentSource;\n    this._isReadableStream = textContentSource instanceof ReadableStream;\n    this._container = this._rootContainer = container;\n    this._textDivs = textDivs || [];\n    this._textContentItemsStr = textContentItemsStr || [];\n    this._fontInspectorEnabled = !!globalThis.FontInspector?.enabled;\n    this._reader = null;\n    this._textDivProperties = textDivProperties || new WeakMap();\n    this._canceled = false;\n    this._capability = Promise.withResolvers();\n    this._layoutTextParams = {\n      prevFontSize: null,\n      prevFontFamily: null,\n      div: null,\n      scale: viewport.scale * (globalThis.devicePixelRatio || 1),\n      properties: null,\n      ctx: getCtx()\n    };\n    const {\n      pageWidth,\n      pageHeight,\n      pageX,\n      pageY\n    } = viewport.rawDims;\n    this._transform = [1, 0, 0, -1, -pageX, pageY + pageHeight];\n    this._pageWidth = pageWidth;\n    this._pageHeight = pageHeight;\n    (0,_display_utils_js__WEBPACK_IMPORTED_MODULE_1__.setLayerDimensions)(container, viewport);\n    this._capability.promise.finally(() => {\n      this._layoutTextParams = null;\n    }).catch(() => {});\n  }\n  get promise() {\n    return this._capability.promise;\n  }\n  cancel() {\n    this._canceled = true;\n    if (this._reader) {\n      this._reader.cancel(new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AbortException(\"TextLayer task cancelled.\")).catch(() => {});\n      this._reader = null;\n    }\n    this._capability.reject(new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AbortException(\"TextLayer task cancelled.\"));\n  }\n  _processItems(items, styleCache) {\n    for (const item of items) {\n      if (item.str === undefined) {\n        if (item.type === \"beginMarkedContentProps\" || item.type === \"beginMarkedContent\") {\n          const parent = this._container;\n          this._container = document.createElement(\"span\");\n          this._container.classList.add(\"markedContent\");\n          if (item.id !== null) {\n            this._container.setAttribute(\"id\", `${item.id}`);\n          }\n          parent.append(this._container);\n        } else if (item.type === \"endMarkedContent\") {\n          this._container = this._container.parentNode;\n        }\n        continue;\n      }\n      this._textContentItemsStr.push(item.str);\n      appendText(this, item, styleCache);\n    }\n  }\n  _layoutText(textDiv) {\n    const textDivProperties = this._layoutTextParams.properties = this._textDivProperties.get(textDiv);\n    this._layoutTextParams.div = textDiv;\n    layout(this._layoutTextParams);\n    if (textDivProperties.hasText) {\n      this._container.append(textDiv);\n    }\n    if (textDivProperties.hasEOL) {\n      const br = document.createElement(\"br\");\n      br.setAttribute(\"role\", \"presentation\");\n      this._container.append(br);\n    }\n  }\n  _render() {\n    const {\n      promise,\n      resolve,\n      reject\n    } = Promise.withResolvers();\n    let styleCache = Object.create(null);\n    if (this._isReadableStream) {\n      const pump = () => {\n        this._reader.read().then(({\n          value,\n          done\n        }) => {\n          if (done) {\n            resolve();\n            return;\n          }\n          Object.assign(styleCache, value.styles);\n          this._processItems(value.items, styleCache);\n          pump();\n        }, reject);\n      };\n      this._reader = this._textContentSource.getReader();\n      pump();\n    } else if (this._textContentSource) {\n      const {\n        items,\n        styles\n      } = this._textContentSource;\n      this._processItems(items, styles);\n      resolve();\n    } else {\n      throw new Error('No \"textContentSource\" parameter specified.');\n    }\n    promise.then(() => {\n      styleCache = null;\n      render(this);\n    }, this._capability.reject);\n  }\n}\nfunction renderTextLayer(params) {\n  const task = new TextLayerRenderTask(params);\n  task._render();\n  return task;\n}\nfunction updateTextLayer({\n  container,\n  viewport,\n  textDivs,\n  textDivProperties,\n  mustRotate = true,\n  mustRescale = true\n}) {\n  if (mustRotate) {\n    (0,_display_utils_js__WEBPACK_IMPORTED_MODULE_1__.setLayerDimensions)(container, {\n      rotation: viewport.rotation\n    });\n  }\n  if (mustRescale) {\n    const ctx = getCtx();\n    const scale = viewport.scale * (globalThis.devicePixelRatio || 1);\n    const params = {\n      prevFontSize: null,\n      prevFontFamily: null,\n      div: null,\n      scale,\n      properties: null,\n      ctx\n    };\n    for (const div of textDivs) {\n      params.properties = textDivProperties.get(div);\n      params.div = div;\n      layout(params);\n    }\n  }\n}\n\n\n/***/ }),\n\n/***/ 585:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   PDFDataTransportStream: () => (/* binding */ PDFDataTransportStream)\n/* harmony export */ });\n/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292);\n/* harmony import */ var _display_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(419);\n\n\nclass PDFDataTransportStream {\n  constructor(pdfDataRangeTransport, {\n    disableRange = false,\n    disableStream = false\n  }) {\n    (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(pdfDataRangeTransport, 'PDFDataTransportStream - missing required \"pdfDataRangeTransport\" argument.');\n    const {\n      length,\n      initialData,\n      progressiveDone,\n      contentDispositionFilename\n    } = pdfDataRangeTransport;\n    this._queuedChunks = [];\n    this._progressiveDone = progressiveDone;\n    this._contentDispositionFilename = contentDispositionFilename;\n    if (initialData?.length > 0) {\n      const buffer = initialData instanceof Uint8Array && initialData.byteLength === initialData.buffer.byteLength ? initialData.buffer : new Uint8Array(initialData).buffer;\n      this._queuedChunks.push(buffer);\n    }\n    this._pdfDataRangeTransport = pdfDataRangeTransport;\n    this._isStreamingSupported = !disableStream;\n    this._isRangeSupported = !disableRange;\n    this._contentLength = length;\n    this._fullRequestReader = null;\n    this._rangeReaders = [];\n    pdfDataRangeTransport.addRangeListener((begin, chunk) => {\n      this._onReceiveData({\n        begin,\n        chunk\n      });\n    });\n    pdfDataRangeTransport.addProgressListener((loaded, total) => {\n      this._onProgress({\n        loaded,\n        total\n      });\n    });\n    pdfDataRangeTransport.addProgressiveReadListener(chunk => {\n      this._onReceiveData({\n        chunk\n      });\n    });\n    pdfDataRangeTransport.addProgressiveDoneListener(() => {\n      this._onProgressiveDone();\n    });\n    pdfDataRangeTransport.transportReady();\n  }\n  _onReceiveData({\n    begin,\n    chunk\n  }) {\n    const buffer = chunk instanceof Uint8Array && chunk.byteLength === chunk.buffer.byteLength ? chunk.buffer : new Uint8Array(chunk).buffer;\n    if (begin === undefined) {\n      if (this._fullRequestReader) {\n        this._fullRequestReader._enqueue(buffer);\n      } else {\n        this._queuedChunks.push(buffer);\n      }\n    } else {\n      const found = this._rangeReaders.some(function (rangeReader) {\n        if (rangeReader._begin !== begin) {\n          return false;\n        }\n        rangeReader._enqueue(buffer);\n        return true;\n      });\n      (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(found, \"_onReceiveData - no `PDFDataTransportStreamRangeReader` instance found.\");\n    }\n  }\n  get _progressiveDataLength() {\n    return this._fullRequestReader?._loaded ?? 0;\n  }\n  _onProgress(evt) {\n    if (evt.total === undefined) {\n      this._rangeReaders[0]?.onProgress?.({\n        loaded: evt.loaded\n      });\n    } else {\n      this._fullRequestReader?.onProgress?.({\n        loaded: evt.loaded,\n        total: evt.total\n      });\n    }\n  }\n  _onProgressiveDone() {\n    this._fullRequestReader?.progressiveDone();\n    this._progressiveDone = true;\n  }\n  _removeRangeReader(reader) {\n    const i = this._rangeReaders.indexOf(reader);\n    if (i >= 0) {\n      this._rangeReaders.splice(i, 1);\n    }\n  }\n  getFullReader() {\n    (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(!this._fullRequestReader, \"PDFDataTransportStream.getFullReader can only be called once.\");\n    const queuedChunks = this._queuedChunks;\n    this._queuedChunks = null;\n    return new PDFDataTransportStreamReader(this, queuedChunks, this._progressiveDone, this._contentDispositionFilename);\n  }\n  getRangeReader(begin, end) {\n    if (end <= this._progressiveDataLength) {\n      return null;\n    }\n    const reader = new PDFDataTransportStreamRangeReader(this, begin, end);\n    this._pdfDataRangeTransport.requestDataRange(begin, end);\n    this._rangeReaders.push(reader);\n    return reader;\n  }\n  cancelAllRequests(reason) {\n    this._fullRequestReader?.cancel(reason);\n    for (const reader of this._rangeReaders.slice(0)) {\n      reader.cancel(reason);\n    }\n    this._pdfDataRangeTransport.abort();\n  }\n}\nclass PDFDataTransportStreamReader {\n  constructor(stream, queuedChunks, progressiveDone = false, contentDispositionFilename = null) {\n    this._stream = stream;\n    this._done = progressiveDone || false;\n    this._filename = (0,_display_utils_js__WEBPACK_IMPORTED_MODULE_1__.isPdfFile)(contentDispositionFilename) ? contentDispositionFilename : null;\n    this._queuedChunks = queuedChunks || [];\n    this._loaded = 0;\n    for (const chunk of this._queuedChunks) {\n      this._loaded += chunk.byteLength;\n    }\n    this._requests = [];\n    this._headersReady = Promise.resolve();\n    stream._fullRequestReader = this;\n    this.onProgress = null;\n  }\n  _enqueue(chunk) {\n    if (this._done) {\n      return;\n    }\n    if (this._requests.length > 0) {\n      const requestCapability = this._requests.shift();\n      requestCapability.resolve({\n        value: chunk,\n        done: false\n      });\n    } else {\n      this._queuedChunks.push(chunk);\n    }\n    this._loaded += chunk.byteLength;\n  }\n  get headersReady() {\n    return this._headersReady;\n  }\n  get filename() {\n    return this._filename;\n  }\n  get isRangeSupported() {\n    return this._stream._isRangeSupported;\n  }\n  get isStreamingSupported() {\n    return this._stream._isStreamingSupported;\n  }\n  get contentLength() {\n    return this._stream._contentLength;\n  }\n  async read() {\n    if (this._queuedChunks.length > 0) {\n      const chunk = this._queuedChunks.shift();\n      return {\n        value: chunk,\n        done: false\n      };\n    }\n    if (this._done) {\n      return {\n        value: undefined,\n        done: true\n      };\n    }\n    const requestCapability = Promise.withResolvers();\n    this._requests.push(requestCapability);\n    return requestCapability.promise;\n  }\n  cancel(reason) {\n    this._done = true;\n    for (const requestCapability of this._requests) {\n      requestCapability.resolve({\n        value: undefined,\n        done: true\n      });\n    }\n    this._requests.length = 0;\n  }\n  progressiveDone() {\n    if (this._done) {\n      return;\n    }\n    this._done = true;\n  }\n}\nclass PDFDataTransportStreamRangeReader {\n  constructor(stream, begin, end) {\n    this._stream = stream;\n    this._begin = begin;\n    this._end = end;\n    this._queuedChunk = null;\n    this._requests = [];\n    this._done = false;\n    this.onProgress = null;\n  }\n  _enqueue(chunk) {\n    if (this._done) {\n      return;\n    }\n    if (this._requests.length === 0) {\n      this._queuedChunk = chunk;\n    } else {\n      const requestsCapability = this._requests.shift();\n      requestsCapability.resolve({\n        value: chunk,\n        done: false\n      });\n      for (const requestCapability of this._requests) {\n        requestCapability.resolve({\n          value: undefined,\n          done: true\n        });\n      }\n      this._requests.length = 0;\n    }\n    this._done = true;\n    this._stream._removeRangeReader(this);\n  }\n  get isStreamingSupported() {\n    return false;\n  }\n  async read() {\n    if (this._queuedChunk) {\n      const chunk = this._queuedChunk;\n      this._queuedChunk = null;\n      return {\n        value: chunk,\n        done: false\n      };\n    }\n    if (this._done) {\n      return {\n        value: undefined,\n        done: true\n      };\n    }\n    const requestCapability = Promise.withResolvers();\n    this._requests.push(requestCapability);\n    return requestCapability.promise;\n  }\n  cancel(reason) {\n    this._done = true;\n    for (const requestCapability of this._requests) {\n      requestCapability.resolve({\n        value: undefined,\n        done: true\n      });\n    }\n    this._requests.length = 0;\n    this._stream._removeRangeReader(this);\n  }\n}\n\n\n/***/ }),\n\n/***/ 164:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   GlobalWorkerOptions: () => (/* binding */ GlobalWorkerOptions)\n/* harmony export */ });\nclass GlobalWorkerOptions {\n  static #port = null;\n  static #src = \"\";\n  static get workerPort() {\n    return this.#port;\n  }\n  static set workerPort(val) {\n    if (!(typeof Worker !== \"undefined\" && val instanceof Worker) && val !== null) {\n      throw new Error(\"Invalid `workerPort` type.\");\n    }\n    this.#port = val;\n  }\n  static get workerSrc() {\n    return this.#src;\n  }\n  static set workerSrc(val) {\n    if (typeof val !== \"string\") {\n      throw new Error(\"Invalid `workerSrc` type.\");\n    }\n    this.#src = val;\n  }\n}\n\n\n/***/ }),\n\n/***/ 284:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   XfaLayer: () => (/* binding */ XfaLayer)\n/* harmony export */ });\n/* harmony import */ var _xfa_text_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(50);\n\nclass XfaLayer {\n  static setupStorage(html, id, element, storage, intent) {\n    const storedData = storage.getValue(id, {\n      value: null\n    });\n    switch (element.name) {\n      case \"textarea\":\n        if (storedData.value !== null) {\n          html.textContent = storedData.value;\n        }\n        if (intent === \"print\") {\n          break;\n        }\n        html.addEventListener(\"input\", event => {\n          storage.setValue(id, {\n            value: event.target.value\n          });\n        });\n        break;\n      case \"input\":\n        if (element.attributes.type === \"radio\" || element.attributes.type === \"checkbox\") {\n          if (storedData.value === element.attributes.xfaOn) {\n            html.setAttribute(\"checked\", true);\n          } else if (storedData.value === element.attributes.xfaOff) {\n            html.removeAttribute(\"checked\");\n          }\n          if (intent === \"print\") {\n            break;\n          }\n          html.addEventListener(\"change\", event => {\n            storage.setValue(id, {\n              value: event.target.checked ? event.target.getAttribute(\"xfaOn\") : event.target.getAttribute(\"xfaOff\")\n            });\n          });\n        } else {\n          if (storedData.value !== null) {\n            html.setAttribute(\"value\", storedData.value);\n          }\n          if (intent === \"print\") {\n            break;\n          }\n          html.addEventListener(\"input\", event => {\n            storage.setValue(id, {\n              value: event.target.value\n            });\n          });\n        }\n        break;\n      case \"select\":\n        if (storedData.value !== null) {\n          html.setAttribute(\"value\", storedData.value);\n          for (const option of element.children) {\n            if (option.attributes.value === storedData.value) {\n              option.attributes.selected = true;\n            } else if (option.attributes.hasOwnProperty(\"selected\")) {\n              delete option.attributes.selected;\n            }\n          }\n        }\n        html.addEventListener(\"input\", event => {\n          const options = event.target.options;\n          const value = options.selectedIndex === -1 ? \"\" : options[options.selectedIndex].value;\n          storage.setValue(id, {\n            value\n          });\n        });\n        break;\n    }\n  }\n  static setAttributes({\n    html,\n    element,\n    storage = null,\n    intent,\n    linkService\n  }) {\n    const {\n      attributes\n    } = element;\n    const isHTMLAnchorElement = html instanceof HTMLAnchorElement;\n    if (attributes.type === \"radio\") {\n      attributes.name = `${attributes.name}-${intent}`;\n    }\n    for (const [key, value] of Object.entries(attributes)) {\n      if (value === null || value === undefined) {\n        continue;\n      }\n      switch (key) {\n        case \"class\":\n          if (value.length) {\n            html.setAttribute(key, value.join(\" \"));\n          }\n          break;\n        case \"dataId\":\n          break;\n        case \"id\":\n          html.setAttribute(\"data-element-id\", value);\n          break;\n        case \"style\":\n          Object.assign(html.style, value);\n          break;\n        case \"textContent\":\n          html.textContent = value;\n          break;\n        default:\n          if (!isHTMLAnchorElement || key !== \"href\" && key !== \"newWindow\") {\n            html.setAttribute(key, value);\n          }\n      }\n    }\n    if (isHTMLAnchorElement) {\n      linkService.addLinkAttributes(html, attributes.href, attributes.newWindow);\n    }\n    if (storage && attributes.dataId) {\n      this.setupStorage(html, attributes.dataId, element, storage);\n    }\n  }\n  static render(parameters) {\n    const storage = parameters.annotationStorage;\n    const linkService = parameters.linkService;\n    const root = parameters.xfaHtml;\n    const intent = parameters.intent || \"display\";\n    const rootHtml = document.createElement(root.name);\n    if (root.attributes) {\n      this.setAttributes({\n        html: rootHtml,\n        element: root,\n        intent,\n        linkService\n      });\n    }\n    const isNotForRichText = intent !== \"richText\";\n    const rootDiv = parameters.div;\n    rootDiv.append(rootHtml);\n    if (parameters.viewport) {\n      const transform = `matrix(${parameters.viewport.transform.join(\",\")})`;\n      rootDiv.style.transform = transform;\n    }\n    if (isNotForRichText) {\n      rootDiv.setAttribute(\"class\", \"xfaLayer xfaFont\");\n    }\n    const textDivs = [];\n    if (root.children.length === 0) {\n      if (root.value) {\n        const node = document.createTextNode(root.value);\n        rootHtml.append(node);\n        if (isNotForRichText && _xfa_text_js__WEBPACK_IMPORTED_MODULE_0__.XfaText.shouldBuildText(root.name)) {\n          textDivs.push(node);\n        }\n      }\n      return {\n        textDivs\n      };\n    }\n    const stack = [[root, -1, rootHtml]];\n    while (stack.length > 0) {\n      const [parent, i, html] = stack.at(-1);\n      if (i + 1 === parent.children.length) {\n        stack.pop();\n        continue;\n      }\n      const child = parent.children[++stack.at(-1)[1]];\n      if (child === null) {\n        continue;\n      }\n      const {\n        name\n      } = child;\n      if (name === \"#text\") {\n        const node = document.createTextNode(child.value);\n        textDivs.push(node);\n        html.append(node);\n        continue;\n      }\n      const childHtml = child?.attributes?.xmlns ? document.createElementNS(child.attributes.xmlns, name) : document.createElement(name);\n      html.append(childHtml);\n      if (child.attributes) {\n        this.setAttributes({\n          html: childHtml,\n          element: child,\n          storage,\n          intent,\n          linkService\n        });\n      }\n      if (child.children?.length > 0) {\n        stack.push([child, -1, childHtml]);\n      } else if (child.value) {\n        const node = document.createTextNode(child.value);\n        if (isNotForRichText && _xfa_text_js__WEBPACK_IMPORTED_MODULE_0__.XfaText.shouldBuildText(name)) {\n          textDivs.push(node);\n        }\n        childHtml.append(node);\n      }\n    }\n    for (const el of rootDiv.querySelectorAll(\".xfaNonInteractive input, .xfaNonInteractive textarea\")) {\n      el.setAttribute(\"readOnly\", true);\n    }\n    return {\n      textDivs\n    };\n  }\n  static update(parameters) {\n    const transform = `matrix(${parameters.viewport.transform.join(\",\")})`;\n    parameters.div.style.transform = transform;\n    parameters.div.hidden = false;\n  }\n}\n\n\n/***/ }),\n\n/***/ 50:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   XfaText: () => (/* binding */ XfaText)\n/* harmony export */ });\nclass XfaText {\n  static textContent(xfa) {\n    const items = [];\n    const output = {\n      items,\n      styles: Object.create(null)\n    };\n    function walk(node) {\n      if (!node) {\n        return;\n      }\n      let str = null;\n      const name = node.name;\n      if (name === \"#text\") {\n        str = node.value;\n      } else if (!XfaText.shouldBuildText(name)) {\n        return;\n      } else if (node?.attributes?.textContent) {\n        str = node.attributes.textContent;\n      } else if (node.value) {\n        str = node.value;\n      }\n      if (str !== null) {\n        items.push({\n          str\n        });\n      }\n      if (!node.children) {\n        return;\n      }\n      for (const child of node.children) {\n        walk(child);\n      }\n    }\n    walk(xfa);\n    return output;\n  }\n  static shouldBuildText(name) {\n    return !(name === \"textarea\" || name === \"input\" || name === \"option\" || name === \"select\");\n  }\n}\n\n\n/***/ }),\n\n/***/ 228:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   AbortException: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AbortException),\n/* harmony export */   AnnotationEditorLayer: () => (/* reexport safe */ _display_editor_annotation_editor_layer_js__WEBPACK_IMPORTED_MODULE_4__.AnnotationEditorLayer),\n/* harmony export */   AnnotationEditorParamsType: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType),\n/* harmony export */   AnnotationEditorType: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType),\n/* harmony export */   AnnotationEditorUIManager: () => (/* reexport safe */ _display_editor_tools_js__WEBPACK_IMPORTED_MODULE_5__.AnnotationEditorUIManager),\n/* harmony export */   AnnotationLayer: () => (/* reexport safe */ _display_annotation_layer_js__WEBPACK_IMPORTED_MODULE_6__.AnnotationLayer),\n/* harmony export */   AnnotationMode: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode),\n/* harmony export */   CMapCompressionType: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.CMapCompressionType),\n/* harmony export */   ColorPicker: () => (/* reexport safe */ _display_editor_color_picker_js__WEBPACK_IMPORTED_MODULE_7__.ColorPicker),\n/* harmony export */   DOMSVGFactory: () => (/* reexport safe */ _display_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.DOMSVGFactory),\n/* harmony export */   DrawLayer: () => (/* reexport safe */ _display_draw_layer_js__WEBPACK_IMPORTED_MODULE_8__.DrawLayer),\n/* harmony export */   FeatureTest: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.FeatureTest),\n/* harmony export */   GlobalWorkerOptions: () => (/* reexport safe */ _display_worker_options_js__WEBPACK_IMPORTED_MODULE_10__.GlobalWorkerOptions),\n/* harmony export */   ImageKind: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.ImageKind),\n/* harmony export */   InvalidPDFException: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.InvalidPDFException),\n/* harmony export */   MissingPDFException: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.MissingPDFException),\n/* harmony export */   OPS: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.OPS),\n/* harmony export */   Outliner: () => (/* reexport safe */ _display_editor_outliner_js__WEBPACK_IMPORTED_MODULE_9__.Outliner),\n/* harmony export */   PDFDataRangeTransport: () => (/* reexport safe */ _display_api_js__WEBPACK_IMPORTED_MODULE_1__.PDFDataRangeTransport),\n/* harmony export */   PDFDateString: () => (/* reexport safe */ _display_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.PDFDateString),\n/* harmony export */   PDFWorker: () => (/* reexport safe */ _display_api_js__WEBPACK_IMPORTED_MODULE_1__.PDFWorker),\n/* harmony export */   PasswordResponses: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.PasswordResponses),\n/* harmony export */   PermissionFlag: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.PermissionFlag),\n/* harmony export */   PixelsPerInch: () => (/* reexport safe */ _display_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.PixelsPerInch),\n/* harmony export */   RenderingCancelledException: () => (/* reexport safe */ _display_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.RenderingCancelledException),\n/* harmony export */   UnexpectedResponseException: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.UnexpectedResponseException),\n/* harmony export */   Util: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.Util),\n/* harmony export */   VerbosityLevel: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.VerbosityLevel),\n/* harmony export */   XfaLayer: () => (/* reexport safe */ _display_xfa_layer_js__WEBPACK_IMPORTED_MODULE_11__.XfaLayer),\n/* harmony export */   build: () => (/* reexport safe */ _display_api_js__WEBPACK_IMPORTED_MODULE_1__.build),\n/* harmony export */   createValidAbsoluteUrl: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.createValidAbsoluteUrl),\n/* harmony export */   fetchData: () => (/* reexport safe */ _display_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.fetchData),\n/* harmony export */   getDocument: () => (/* reexport safe */ _display_api_js__WEBPACK_IMPORTED_MODULE_1__.getDocument),\n/* harmony export */   getFilenameFromUrl: () => (/* reexport safe */ _display_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.getFilenameFromUrl),\n/* harmony export */   getPdfFilenameFromUrl: () => (/* reexport safe */ _display_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.getPdfFilenameFromUrl),\n/* harmony export */   getXfaPageViewport: () => (/* reexport safe */ _display_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.getXfaPageViewport),\n/* harmony export */   isDataScheme: () => (/* reexport safe */ _display_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.isDataScheme),\n/* harmony export */   isPdfFile: () => (/* reexport safe */ _display_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.isPdfFile),\n/* harmony export */   noContextMenu: () => (/* reexport safe */ _display_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.noContextMenu),\n/* harmony export */   normalizeUnicode: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.normalizeUnicode),\n/* harmony export */   renderTextLayer: () => (/* reexport safe */ _display_text_layer_js__WEBPACK_IMPORTED_MODULE_3__.renderTextLayer),\n/* harmony export */   setLayerDimensions: () => (/* reexport safe */ _display_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.setLayerDimensions),\n/* harmony export */   shadow: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow),\n/* harmony export */   updateTextLayer: () => (/* reexport safe */ _display_text_layer_js__WEBPACK_IMPORTED_MODULE_3__.updateTextLayer),\n/* harmony export */   version: () => (/* reexport safe */ _display_api_js__WEBPACK_IMPORTED_MODULE_1__.version)\n/* harmony export */ });\n/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292);\n/* harmony import */ var _display_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(831);\n/* harmony import */ var _display_display_utils_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(419);\n/* harmony import */ var _display_text_layer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(814);\n/* harmony import */ var _display_editor_annotation_editor_layer_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(731);\n/* harmony import */ var _display_editor_tools_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(830);\n/* harmony import */ var _display_annotation_layer_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(976);\n/* harmony import */ var _display_editor_color_picker_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(259);\n/* harmony import */ var _display_draw_layer_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(47);\n/* harmony import */ var _display_worker_options_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(164);\n/* harmony import */ var _display_editor_outliner_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(61);\n/* harmony import */ var _display_xfa_layer_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(284);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([_display_api_js__WEBPACK_IMPORTED_MODULE_1__]);\n_display_api_js__WEBPACK_IMPORTED_MODULE_1__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];\n\n\n\n\n\n\n\n\n\n\n\n\nconst pdfjsVersion = \"4.2.67\";\nconst pdfjsBuild = \"49b388101\";\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 178:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   MessageHandler: () => (/* binding */ MessageHandler)\n/* harmony export */ });\n/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292);\n\nconst CallbackKind = {\n  UNKNOWN: 0,\n  DATA: 1,\n  ERROR: 2\n};\nconst StreamKind = {\n  UNKNOWN: 0,\n  CANCEL: 1,\n  CANCEL_COMPLETE: 2,\n  CLOSE: 3,\n  ENQUEUE: 4,\n  ERROR: 5,\n  PULL: 6,\n  PULL_COMPLETE: 7,\n  START_COMPLETE: 8\n};\nfunction wrapReason(reason) {\n  if (!(reason instanceof Error || typeof reason === \"object\" && reason !== null)) {\n    (0,_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)('wrapReason: Expected \"reason\" to be a (possibly cloned) Error.');\n  }\n  switch (reason.name) {\n    case \"AbortException\":\n      return new _util_js__WEBPACK_IMPORTED_MODULE_0__.AbortException(reason.message);\n    case \"MissingPDFException\":\n      return new _util_js__WEBPACK_IMPORTED_MODULE_0__.MissingPDFException(reason.message);\n    case \"PasswordException\":\n      return new _util_js__WEBPACK_IMPORTED_MODULE_0__.PasswordException(reason.message, reason.code);\n    case \"UnexpectedResponseException\":\n      return new _util_js__WEBPACK_IMPORTED_MODULE_0__.UnexpectedResponseException(reason.message, reason.status);\n    case \"UnknownErrorException\":\n      return new _util_js__WEBPACK_IMPORTED_MODULE_0__.UnknownErrorException(reason.message, reason.details);\n    default:\n      return new _util_js__WEBPACK_IMPORTED_MODULE_0__.UnknownErrorException(reason.message, reason.toString());\n  }\n}\nclass MessageHandler {\n  constructor(sourceName, targetName, comObj) {\n    this.sourceName = sourceName;\n    this.targetName = targetName;\n    this.comObj = comObj;\n    this.callbackId = 1;\n    this.streamId = 1;\n    this.streamSinks = Object.create(null);\n    this.streamControllers = Object.create(null);\n    this.callbackCapabilities = Object.create(null);\n    this.actionHandler = Object.create(null);\n    this._onComObjOnMessage = event => {\n      const data = event.data;\n      if (data.targetName !== this.sourceName) {\n        return;\n      }\n      if (data.stream) {\n        this.#processStreamMessage(data);\n        return;\n      }\n      if (data.callback) {\n        const callbackId = data.callbackId;\n        const capability = this.callbackCapabilities[callbackId];\n        if (!capability) {\n          throw new Error(`Cannot resolve callback ${callbackId}`);\n        }\n        delete this.callbackCapabilities[callbackId];\n        if (data.callback === CallbackKind.DATA) {\n          capability.resolve(data.data);\n        } else if (data.callback === CallbackKind.ERROR) {\n          capability.reject(wrapReason(data.reason));\n        } else {\n          throw new Error(\"Unexpected callback case\");\n        }\n        return;\n      }\n      const action = this.actionHandler[data.action];\n      if (!action) {\n        throw new Error(`Unknown action from worker: ${data.action}`);\n      }\n      if (data.callbackId) {\n        const cbSourceName = this.sourceName;\n        const cbTargetName = data.sourceName;\n        new Promise(function (resolve) {\n          resolve(action(data.data));\n        }).then(function (result) {\n          comObj.postMessage({\n            sourceName: cbSourceName,\n            targetName: cbTargetName,\n            callback: CallbackKind.DATA,\n            callbackId: data.callbackId,\n            data: result\n          });\n        }, function (reason) {\n          comObj.postMessage({\n            sourceName: cbSourceName,\n            targetName: cbTargetName,\n            callback: CallbackKind.ERROR,\n            callbackId: data.callbackId,\n            reason: wrapReason(reason)\n          });\n        });\n        return;\n      }\n      if (data.streamId) {\n        this.#createStreamSink(data);\n        return;\n      }\n      action(data.data);\n    };\n    comObj.addEventListener(\"message\", this._onComObjOnMessage);\n  }\n  on(actionName, handler) {\n    const ah = this.actionHandler;\n    if (ah[actionName]) {\n      throw new Error(`There is already an actionName called \"${actionName}\"`);\n    }\n    ah[actionName] = handler;\n  }\n  send(actionName, data, transfers) {\n    this.comObj.postMessage({\n      sourceName: this.sourceName,\n      targetName: this.targetName,\n      action: actionName,\n      data\n    }, transfers);\n  }\n  sendWithPromise(actionName, data, transfers) {\n    const callbackId = this.callbackId++;\n    const capability = Promise.withResolvers();\n    this.callbackCapabilities[callbackId] = capability;\n    try {\n      this.comObj.postMessage({\n        sourceName: this.sourceName,\n        targetName: this.targetName,\n        action: actionName,\n        callbackId,\n        data\n      }, transfers);\n    } catch (ex) {\n      capability.reject(ex);\n    }\n    return capability.promise;\n  }\n  sendWithStream(actionName, data, queueingStrategy, transfers) {\n    const streamId = this.streamId++,\n      sourceName = this.sourceName,\n      targetName = this.targetName,\n      comObj = this.comObj;\n    return new ReadableStream({\n      start: controller => {\n        const startCapability = Promise.withResolvers();\n        this.streamControllers[streamId] = {\n          controller,\n          startCall: startCapability,\n          pullCall: null,\n          cancelCall: null,\n          isClosed: false\n        };\n        comObj.postMessage({\n          sourceName,\n          targetName,\n          action: actionName,\n          streamId,\n          data,\n          desiredSize: controller.desiredSize\n        }, transfers);\n        return startCapability.promise;\n      },\n      pull: controller => {\n        const pullCapability = Promise.withResolvers();\n        this.streamControllers[streamId].pullCall = pullCapability;\n        comObj.postMessage({\n          sourceName,\n          targetName,\n          stream: StreamKind.PULL,\n          streamId,\n          desiredSize: controller.desiredSize\n        });\n        return pullCapability.promise;\n      },\n      cancel: reason => {\n        (0,_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(reason instanceof Error, \"cancel must have a valid reason\");\n        const cancelCapability = Promise.withResolvers();\n        this.streamControllers[streamId].cancelCall = cancelCapability;\n        this.streamControllers[streamId].isClosed = true;\n        comObj.postMessage({\n          sourceName,\n          targetName,\n          stream: StreamKind.CANCEL,\n          streamId,\n          reason: wrapReason(reason)\n        });\n        return cancelCapability.promise;\n      }\n    }, queueingStrategy);\n  }\n  #createStreamSink(data) {\n    const streamId = data.streamId,\n      sourceName = this.sourceName,\n      targetName = data.sourceName,\n      comObj = this.comObj;\n    const self = this,\n      action = this.actionHandler[data.action];\n    const streamSink = {\n      enqueue(chunk, size = 1, transfers) {\n        if (this.isCancelled) {\n          return;\n        }\n        const lastDesiredSize = this.desiredSize;\n        this.desiredSize -= size;\n        if (lastDesiredSize > 0 && this.desiredSize <= 0) {\n          this.sinkCapability = Promise.withResolvers();\n          this.ready = this.sinkCapability.promise;\n        }\n        comObj.postMessage({\n          sourceName,\n          targetName,\n          stream: StreamKind.ENQUEUE,\n          streamId,\n          chunk\n        }, transfers);\n      },\n      close() {\n        if (this.isCancelled) {\n          return;\n        }\n        this.isCancelled = true;\n        comObj.postMessage({\n          sourceName,\n          targetName,\n          stream: StreamKind.CLOSE,\n          streamId\n        });\n        delete self.streamSinks[streamId];\n      },\n      error(reason) {\n        (0,_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(reason instanceof Error, \"error must have a valid reason\");\n        if (this.isCancelled) {\n          return;\n        }\n        this.isCancelled = true;\n        comObj.postMessage({\n          sourceName,\n          targetName,\n          stream: StreamKind.ERROR,\n          streamId,\n          reason: wrapReason(reason)\n        });\n      },\n      sinkCapability: Promise.withResolvers(),\n      onPull: null,\n      onCancel: null,\n      isCancelled: false,\n      desiredSize: data.desiredSize,\n      ready: null\n    };\n    streamSink.sinkCapability.resolve();\n    streamSink.ready = streamSink.sinkCapability.promise;\n    this.streamSinks[streamId] = streamSink;\n    new Promise(function (resolve) {\n      resolve(action(data.data, streamSink));\n    }).then(function () {\n      comObj.postMessage({\n        sourceName,\n        targetName,\n        stream: StreamKind.START_COMPLETE,\n        streamId,\n        success: true\n      });\n    }, function (reason) {\n      comObj.postMessage({\n        sourceName,\n        targetName,\n        stream: StreamKind.START_COMPLETE,\n        streamId,\n        reason: wrapReason(reason)\n      });\n    });\n  }\n  #processStreamMessage(data) {\n    const streamId = data.streamId,\n      sourceName = this.sourceName,\n      targetName = data.sourceName,\n      comObj = this.comObj;\n    const streamController = this.streamControllers[streamId],\n      streamSink = this.streamSinks[streamId];\n    switch (data.stream) {\n      case StreamKind.START_COMPLETE:\n        if (data.success) {\n          streamController.startCall.resolve();\n        } else {\n          streamController.startCall.reject(wrapReason(data.reason));\n        }\n        break;\n      case StreamKind.PULL_COMPLETE:\n        if (data.success) {\n          streamController.pullCall.resolve();\n        } else {\n          streamController.pullCall.reject(wrapReason(data.reason));\n        }\n        break;\n      case StreamKind.PULL:\n        if (!streamSink) {\n          comObj.postMessage({\n            sourceName,\n            targetName,\n            stream: StreamKind.PULL_COMPLETE,\n            streamId,\n            success: true\n          });\n          break;\n        }\n        if (streamSink.desiredSize <= 0 && data.desiredSize > 0) {\n          streamSink.sinkCapability.resolve();\n        }\n        streamSink.desiredSize = data.desiredSize;\n        new Promise(function (resolve) {\n          resolve(streamSink.onPull?.());\n        }).then(function () {\n          comObj.postMessage({\n            sourceName,\n            targetName,\n            stream: StreamKind.PULL_COMPLETE,\n            streamId,\n            success: true\n          });\n        }, function (reason) {\n          comObj.postMessage({\n            sourceName,\n            targetName,\n            stream: StreamKind.PULL_COMPLETE,\n            streamId,\n            reason: wrapReason(reason)\n          });\n        });\n        break;\n      case StreamKind.ENQUEUE:\n        (0,_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(streamController, \"enqueue should have stream controller\");\n        if (streamController.isClosed) {\n          break;\n        }\n        streamController.controller.enqueue(data.chunk);\n        break;\n      case StreamKind.CLOSE:\n        (0,_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(streamController, \"close should have stream controller\");\n        if (streamController.isClosed) {\n          break;\n        }\n        streamController.isClosed = true;\n        streamController.controller.close();\n        this.#deleteStreamController(streamController, streamId);\n        break;\n      case StreamKind.ERROR:\n        (0,_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(streamController, \"error should have stream controller\");\n        streamController.controller.error(wrapReason(data.reason));\n        this.#deleteStreamController(streamController, streamId);\n        break;\n      case StreamKind.CANCEL_COMPLETE:\n        if (data.success) {\n          streamController.cancelCall.resolve();\n        } else {\n          streamController.cancelCall.reject(wrapReason(data.reason));\n        }\n        this.#deleteStreamController(streamController, streamId);\n        break;\n      case StreamKind.CANCEL:\n        if (!streamSink) {\n          break;\n        }\n        new Promise(function (resolve) {\n          resolve(streamSink.onCancel?.(wrapReason(data.reason)));\n        }).then(function () {\n          comObj.postMessage({\n            sourceName,\n            targetName,\n            stream: StreamKind.CANCEL_COMPLETE,\n            streamId,\n            success: true\n          });\n        }, function (reason) {\n          comObj.postMessage({\n            sourceName,\n            targetName,\n            stream: StreamKind.CANCEL_COMPLETE,\n            streamId,\n            reason: wrapReason(reason)\n          });\n        });\n        streamSink.sinkCapability.reject(wrapReason(data.reason));\n        streamSink.isCancelled = true;\n        delete this.streamSinks[streamId];\n        break;\n      default:\n        throw new Error(\"Unexpected stream case\");\n    }\n  }\n  async #deleteStreamController(streamController, streamId) {\n    await Promise.allSettled([streamController.startCall?.promise, streamController.pullCall?.promise, streamController.cancelCall?.promise]);\n    delete this.streamControllers[streamId];\n  }\n  destroy() {\n    this.comObj.removeEventListener(\"message\", this._onComObjOnMessage);\n  }\n}\n\n\n/***/ }),\n\n/***/ 651:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   MurmurHash3_64: () => (/* binding */ MurmurHash3_64)\n/* harmony export */ });\nconst SEED = 0xc3d2e1f0;\nconst MASK_HIGH = 0xffff0000;\nconst MASK_LOW = 0xffff;\nclass MurmurHash3_64 {\n  constructor(seed) {\n    this.h1 = seed ? seed & 0xffffffff : SEED;\n    this.h2 = seed ? seed & 0xffffffff : SEED;\n  }\n  update(input) {\n    let data, length;\n    if (typeof input === \"string\") {\n      data = new Uint8Array(input.length * 2);\n      length = 0;\n      for (let i = 0, ii = input.length; i < ii; i++) {\n        const code = input.charCodeAt(i);\n        if (code <= 0xff) {\n          data[length++] = code;\n        } else {\n          data[length++] = code >>> 8;\n          data[length++] = code & 0xff;\n        }\n      }\n    } else if (ArrayBuffer.isView(input)) {\n      data = input.slice();\n      length = data.byteLength;\n    } else {\n      throw new Error(\"Invalid data format, must be a string or TypedArray.\");\n    }\n    const blockCounts = length >> 2;\n    const tailLength = length - blockCounts * 4;\n    const dataUint32 = new Uint32Array(data.buffer, 0, blockCounts);\n    let k1 = 0,\n      k2 = 0;\n    let h1 = this.h1,\n      h2 = this.h2;\n    const C1 = 0xcc9e2d51,\n      C2 = 0x1b873593;\n    const C1_LOW = C1 & MASK_LOW,\n      C2_LOW = C2 & MASK_LOW;\n    for (let i = 0; i < blockCounts; i++) {\n      if (i & 1) {\n        k1 = dataUint32[i];\n        k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW;\n        k1 = k1 << 15 | k1 >>> 17;\n        k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW;\n        h1 ^= k1;\n        h1 = h1 << 13 | h1 >>> 19;\n        h1 = h1 * 5 + 0xe6546b64;\n      } else {\n        k2 = dataUint32[i];\n        k2 = k2 * C1 & MASK_HIGH | k2 * C1_LOW & MASK_LOW;\n        k2 = k2 << 15 | k2 >>> 17;\n        k2 = k2 * C2 & MASK_HIGH | k2 * C2_LOW & MASK_LOW;\n        h2 ^= k2;\n        h2 = h2 << 13 | h2 >>> 19;\n        h2 = h2 * 5 + 0xe6546b64;\n      }\n    }\n    k1 = 0;\n    switch (tailLength) {\n      case 3:\n        k1 ^= data[blockCounts * 4 + 2] << 16;\n      case 2:\n        k1 ^= data[blockCounts * 4 + 1] << 8;\n      case 1:\n        k1 ^= data[blockCounts * 4];\n        k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW;\n        k1 = k1 << 15 | k1 >>> 17;\n        k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW;\n        if (blockCounts & 1) {\n          h1 ^= k1;\n        } else {\n          h2 ^= k1;\n        }\n    }\n    this.h1 = h1;\n    this.h2 = h2;\n  }\n  hexdigest() {\n    let h1 = this.h1,\n      h2 = this.h2;\n    h1 ^= h2 >>> 1;\n    h1 = h1 * 0xed558ccd & MASK_HIGH | h1 * 0x8ccd & MASK_LOW;\n    h2 = h2 * 0xff51afd7 & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xafd7ed55 & MASK_HIGH) >>> 16;\n    h1 ^= h2 >>> 1;\n    h1 = h1 * 0x1a85ec53 & MASK_HIGH | h1 * 0xec53 & MASK_LOW;\n    h2 = h2 * 0xc4ceb9fe & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xb9fe1a85 & MASK_HIGH) >>> 16;\n    h1 ^= h2 >>> 1;\n    return (h1 >>> 0).toString(16).padStart(8, \"0\") + (h2 >>> 0).toString(16).padStart(8, \"0\");\n  }\n}\n\n\n/***/ }),\n\n/***/ 292:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   AbortException: () => (/* binding */ AbortException),\n/* harmony export */   AnnotationBorderStyleType: () => (/* binding */ AnnotationBorderStyleType),\n/* harmony export */   AnnotationEditorParamsType: () => (/* binding */ AnnotationEditorParamsType),\n/* harmony export */   AnnotationEditorPrefix: () => (/* binding */ AnnotationEditorPrefix),\n/* harmony export */   AnnotationEditorType: () => (/* binding */ AnnotationEditorType),\n/* harmony export */   AnnotationMode: () => (/* binding */ AnnotationMode),\n/* harmony export */   AnnotationPrefix: () => (/* binding */ AnnotationPrefix),\n/* harmony export */   AnnotationType: () => (/* binding */ AnnotationType),\n/* harmony export */   BaseException: () => (/* binding */ BaseException),\n/* harmony export */   CMapCompressionType: () => (/* binding */ CMapCompressionType),\n/* harmony export */   FONT_IDENTITY_MATRIX: () => (/* binding */ FONT_IDENTITY_MATRIX),\n/* harmony export */   FeatureTest: () => (/* binding */ FeatureTest),\n/* harmony export */   FontRenderOps: () => (/* binding */ FontRenderOps),\n/* harmony export */   FormatError: () => (/* binding */ FormatError),\n/* harmony export */   IDENTITY_MATRIX: () => (/* binding */ IDENTITY_MATRIX),\n/* harmony export */   ImageKind: () => (/* binding */ ImageKind),\n/* harmony export */   InvalidPDFException: () => (/* binding */ InvalidPDFException),\n/* harmony export */   LINE_FACTOR: () => (/* binding */ LINE_FACTOR),\n/* harmony export */   MAX_IMAGE_SIZE_TO_CACHE: () => (/* binding */ MAX_IMAGE_SIZE_TO_CACHE),\n/* harmony export */   MissingPDFException: () => (/* binding */ MissingPDFException),\n/* harmony export */   OPS: () => (/* binding */ OPS),\n/* harmony export */   PasswordException: () => (/* binding */ PasswordException),\n/* harmony export */   PasswordResponses: () => (/* binding */ PasswordResponses),\n/* harmony export */   PermissionFlag: () => (/* binding */ PermissionFlag),\n/* harmony export */   RenderingIntentFlag: () => (/* binding */ RenderingIntentFlag),\n/* harmony export */   TextRenderingMode: () => (/* binding */ TextRenderingMode),\n/* harmony export */   UnexpectedResponseException: () => (/* binding */ UnexpectedResponseException),\n/* harmony export */   UnknownErrorException: () => (/* binding */ UnknownErrorException),\n/* harmony export */   Util: () => (/* binding */ Util),\n/* harmony export */   VerbosityLevel: () => (/* binding */ VerbosityLevel),\n/* harmony export */   assert: () => (/* binding */ assert),\n/* harmony export */   bytesToString: () => (/* binding */ bytesToString),\n/* harmony export */   createValidAbsoluteUrl: () => (/* binding */ createValidAbsoluteUrl),\n/* harmony export */   getUuid: () => (/* binding */ getUuid),\n/* harmony export */   getVerbosityLevel: () => (/* binding */ getVerbosityLevel),\n/* harmony export */   info: () => (/* binding */ info),\n/* harmony export */   isNodeJS: () => (/* binding */ isNodeJS),\n/* harmony export */   normalizeUnicode: () => (/* binding */ normalizeUnicode),\n/* harmony export */   objectFromMap: () => (/* binding */ objectFromMap),\n/* harmony export */   setVerbosityLevel: () => (/* binding */ setVerbosityLevel),\n/* harmony export */   shadow: () => (/* binding */ shadow),\n/* harmony export */   string32: () => (/* binding */ string32),\n/* harmony export */   stringToBytes: () => (/* binding */ stringToBytes),\n/* harmony export */   unreachable: () => (/* binding */ unreachable),\n/* harmony export */   warn: () => (/* binding */ warn)\n/* harmony export */ });\n/* unused harmony exports AnnotationActionEventType, AnnotationFieldFlag, AnnotationFlag, AnnotationReplyType, BASELINE_FACTOR, DocumentActionEventType, getModificationDate, isArrayEqual, LINE_DESCENT_FACTOR, objectSize, PageActionEventType, stringToPDFString, stringToUTF8String, utf8StringToString */\nconst isNodeJS = typeof process === \"object\" && process + \"\" === \"[object process]\" && !process.versions.nw && !(process.versions.electron && process.type && process.type !== \"browser\");\nconst IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];\nconst FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];\nconst MAX_IMAGE_SIZE_TO_CACHE = 10e6;\nconst LINE_FACTOR = 1.35;\nconst LINE_DESCENT_FACTOR = 0.35;\nconst BASELINE_FACTOR = LINE_DESCENT_FACTOR / LINE_FACTOR;\nconst RenderingIntentFlag = {\n  ANY: 0x01,\n  DISPLAY: 0x02,\n  PRINT: 0x04,\n  SAVE: 0x08,\n  ANNOTATIONS_FORMS: 0x10,\n  ANNOTATIONS_STORAGE: 0x20,\n  ANNOTATIONS_DISABLE: 0x40,\n  OPLIST: 0x100\n};\nconst AnnotationMode = {\n  DISABLE: 0,\n  ENABLE: 1,\n  ENABLE_FORMS: 2,\n  ENABLE_STORAGE: 3\n};\nconst AnnotationEditorPrefix = \"pdfjs_internal_editor_\";\nconst AnnotationEditorType = {\n  DISABLE: -1,\n  NONE: 0,\n  FREETEXT: 3,\n  HIGHLIGHT: 9,\n  STAMP: 13,\n  INK: 15\n};\nconst AnnotationEditorParamsType = {\n  RESIZE: 1,\n  CREATE: 2,\n  FREETEXT_SIZE: 11,\n  FREETEXT_COLOR: 12,\n  FREETEXT_OPACITY: 13,\n  INK_COLOR: 21,\n  INK_THICKNESS: 22,\n  INK_OPACITY: 23,\n  HIGHLIGHT_COLOR: 31,\n  HIGHLIGHT_DEFAULT_COLOR: 32,\n  HIGHLIGHT_THICKNESS: 33,\n  HIGHLIGHT_FREE: 34,\n  HIGHLIGHT_SHOW_ALL: 35\n};\nconst PermissionFlag = {\n  PRINT: 0x04,\n  MODIFY_CONTENTS: 0x08,\n  COPY: 0x10,\n  MODIFY_ANNOTATIONS: 0x20,\n  FILL_INTERACTIVE_FORMS: 0x100,\n  COPY_FOR_ACCESSIBILITY: 0x200,\n  ASSEMBLE: 0x400,\n  PRINT_HIGH_QUALITY: 0x800\n};\nconst TextRenderingMode = {\n  FILL: 0,\n  STROKE: 1,\n  FILL_STROKE: 2,\n  INVISIBLE: 3,\n  FILL_ADD_TO_PATH: 4,\n  STROKE_ADD_TO_PATH: 5,\n  FILL_STROKE_ADD_TO_PATH: 6,\n  ADD_TO_PATH: 7,\n  FILL_STROKE_MASK: 3,\n  ADD_TO_PATH_FLAG: 4\n};\nconst ImageKind = {\n  GRAYSCALE_1BPP: 1,\n  RGB_24BPP: 2,\n  RGBA_32BPP: 3\n};\nconst AnnotationType = {\n  TEXT: 1,\n  LINK: 2,\n  FREETEXT: 3,\n  LINE: 4,\n  SQUARE: 5,\n  CIRCLE: 6,\n  POLYGON: 7,\n  POLYLINE: 8,\n  HIGHLIGHT: 9,\n  UNDERLINE: 10,\n  SQUIGGLY: 11,\n  STRIKEOUT: 12,\n  STAMP: 13,\n  CARET: 14,\n  INK: 15,\n  POPUP: 16,\n  FILEATTACHMENT: 17,\n  SOUND: 18,\n  MOVIE: 19,\n  WIDGET: 20,\n  SCREEN: 21,\n  PRINTERMARK: 22,\n  TRAPNET: 23,\n  WATERMARK: 24,\n  THREED: 25,\n  REDACT: 26\n};\nconst AnnotationReplyType = {\n  GROUP: \"Group\",\n  REPLY: \"R\"\n};\nconst AnnotationFlag = {\n  INVISIBLE: 0x01,\n  HIDDEN: 0x02,\n  PRINT: 0x04,\n  NOZOOM: 0x08,\n  NOROTATE: 0x10,\n  NOVIEW: 0x20,\n  READONLY: 0x40,\n  LOCKED: 0x80,\n  TOGGLENOVIEW: 0x100,\n  LOCKEDCONTENTS: 0x200\n};\nconst AnnotationFieldFlag = {\n  READONLY: 0x0000001,\n  REQUIRED: 0x0000002,\n  NOEXPORT: 0x0000004,\n  MULTILINE: 0x0001000,\n  PASSWORD: 0x0002000,\n  NOTOGGLETOOFF: 0x0004000,\n  RADIO: 0x0008000,\n  PUSHBUTTON: 0x0010000,\n  COMBO: 0x0020000,\n  EDIT: 0x0040000,\n  SORT: 0x0080000,\n  FILESELECT: 0x0100000,\n  MULTISELECT: 0x0200000,\n  DONOTSPELLCHECK: 0x0400000,\n  DONOTSCROLL: 0x0800000,\n  COMB: 0x1000000,\n  RICHTEXT: 0x2000000,\n  RADIOSINUNISON: 0x2000000,\n  COMMITONSELCHANGE: 0x4000000\n};\nconst AnnotationBorderStyleType = {\n  SOLID: 1,\n  DASHED: 2,\n  BEVELED: 3,\n  INSET: 4,\n  UNDERLINE: 5\n};\nconst AnnotationActionEventType = {\n  E: \"Mouse Enter\",\n  X: \"Mouse Exit\",\n  D: \"Mouse Down\",\n  U: \"Mouse Up\",\n  Fo: \"Focus\",\n  Bl: \"Blur\",\n  PO: \"PageOpen\",\n  PC: \"PageClose\",\n  PV: \"PageVisible\",\n  PI: \"PageInvisible\",\n  K: \"Keystroke\",\n  F: \"Format\",\n  V: \"Validate\",\n  C: \"Calculate\"\n};\nconst DocumentActionEventType = {\n  WC: \"WillClose\",\n  WS: \"WillSave\",\n  DS: \"DidSave\",\n  WP: \"WillPrint\",\n  DP: \"DidPrint\"\n};\nconst PageActionEventType = {\n  O: \"PageOpen\",\n  C: \"PageClose\"\n};\nconst VerbosityLevel = {\n  ERRORS: 0,\n  WARNINGS: 1,\n  INFOS: 5\n};\nconst CMapCompressionType = {\n  NONE: 0,\n  BINARY: 1\n};\nconst OPS = {\n  dependency: 1,\n  setLineWidth: 2,\n  setLineCap: 3,\n  setLineJoin: 4,\n  setMiterLimit: 5,\n  setDash: 6,\n  setRenderingIntent: 7,\n  setFlatness: 8,\n  setGState: 9,\n  save: 10,\n  restore: 11,\n  transform: 12,\n  moveTo: 13,\n  lineTo: 14,\n  curveTo: 15,\n  curveTo2: 16,\n  curveTo3: 17,\n  closePath: 18,\n  rectangle: 19,\n  stroke: 20,\n  closeStroke: 21,\n  fill: 22,\n  eoFill: 23,\n  fillStroke: 24,\n  eoFillStroke: 25,\n  closeFillStroke: 26,\n  closeEOFillStroke: 27,\n  endPath: 28,\n  clip: 29,\n  eoClip: 30,\n  beginText: 31,\n  endText: 32,\n  setCharSpacing: 33,\n  setWordSpacing: 34,\n  setHScale: 35,\n  setLeading: 36,\n  setFont: 37,\n  setTextRenderingMode: 38,\n  setTextRise: 39,\n  moveText: 40,\n  setLeadingMoveText: 41,\n  setTextMatrix: 42,\n  nextLine: 43,\n  showText: 44,\n  showSpacedText: 45,\n  nextLineShowText: 46,\n  nextLineSetSpacingShowText: 47,\n  setCharWidth: 48,\n  setCharWidthAndBounds: 49,\n  setStrokeColorSpace: 50,\n  setFillColorSpace: 51,\n  setStrokeColor: 52,\n  setStrokeColorN: 53,\n  setFillColor: 54,\n  setFillColorN: 55,\n  setStrokeGray: 56,\n  setFillGray: 57,\n  setStrokeRGBColor: 58,\n  setFillRGBColor: 59,\n  setStrokeCMYKColor: 60,\n  setFillCMYKColor: 61,\n  shadingFill: 62,\n  beginInlineImage: 63,\n  beginImageData: 64,\n  endInlineImage: 65,\n  paintXObject: 66,\n  markPoint: 67,\n  markPointProps: 68,\n  beginMarkedContent: 69,\n  beginMarkedContentProps: 70,\n  endMarkedContent: 71,\n  beginCompat: 72,\n  endCompat: 73,\n  paintFormXObjectBegin: 74,\n  paintFormXObjectEnd: 75,\n  beginGroup: 76,\n  endGroup: 77,\n  beginAnnotation: 80,\n  endAnnotation: 81,\n  paintImageMaskXObject: 83,\n  paintImageMaskXObjectGroup: 84,\n  paintImageXObject: 85,\n  paintInlineImageXObject: 86,\n  paintInlineImageXObjectGroup: 87,\n  paintImageXObjectRepeat: 88,\n  paintImageMaskXObjectRepeat: 89,\n  paintSolidColorImageMask: 90,\n  constructPath: 91\n};\nconst PasswordResponses = {\n  NEED_PASSWORD: 1,\n  INCORRECT_PASSWORD: 2\n};\nlet verbosity = VerbosityLevel.WARNINGS;\nfunction setVerbosityLevel(level) {\n  if (Number.isInteger(level)) {\n    verbosity = level;\n  }\n}\nfunction getVerbosityLevel() {\n  return verbosity;\n}\nfunction info(msg) {\n  if (verbosity >= VerbosityLevel.INFOS) {\n    console.log(`Info: ${msg}`);\n  }\n}\nfunction warn(msg) {\n  if (verbosity >= VerbosityLevel.WARNINGS) {\n    console.log(`Warning: ${msg}`);\n  }\n}\nfunction unreachable(msg) {\n  throw new Error(msg);\n}\nfunction assert(cond, msg) {\n  if (!cond) {\n    unreachable(msg);\n  }\n}\nfunction _isValidProtocol(url) {\n  switch (url?.protocol) {\n    case \"http:\":\n    case \"https:\":\n    case \"ftp:\":\n    case \"mailto:\":\n    case \"tel:\":\n      return true;\n    default:\n      return false;\n  }\n}\nfunction createValidAbsoluteUrl(url, baseUrl = null, options = null) {\n  if (!url) {\n    return null;\n  }\n  try {\n    if (options && typeof url === \"string\") {\n      if (options.addDefaultProtocol && url.startsWith(\"www.\")) {\n        const dots = url.match(/\\./g);\n        if (dots?.length >= 2) {\n          url = `http://${url}`;\n        }\n      }\n      if (options.tryConvertEncoding) {\n        try {\n          url = stringToUTF8String(url);\n        } catch {}\n      }\n    }\n    const absoluteUrl = baseUrl ? new URL(url, baseUrl) : new URL(url);\n    if (_isValidProtocol(absoluteUrl)) {\n      return absoluteUrl;\n    }\n  } catch {}\n  return null;\n}\nfunction shadow(obj, prop, value, nonSerializable = false) {\n  Object.defineProperty(obj, prop, {\n    value,\n    enumerable: !nonSerializable,\n    configurable: true,\n    writable: false\n  });\n  return value;\n}\nconst BaseException = function BaseExceptionClosure() {\n  function BaseException(message, name) {\n    if (this.constructor === BaseException) {\n      unreachable(\"Cannot initialize BaseException.\");\n    }\n    this.message = message;\n    this.name = name;\n  }\n  BaseException.prototype = new Error();\n  BaseException.constructor = BaseException;\n  return BaseException;\n}();\nclass PasswordException extends BaseException {\n  constructor(msg, code) {\n    super(msg, \"PasswordException\");\n    this.code = code;\n  }\n}\nclass UnknownErrorException extends BaseException {\n  constructor(msg, details) {\n    super(msg, \"UnknownErrorException\");\n    this.details = details;\n  }\n}\nclass InvalidPDFException extends BaseException {\n  constructor(msg) {\n    super(msg, \"InvalidPDFException\");\n  }\n}\nclass MissingPDFException extends BaseException {\n  constructor(msg) {\n    super(msg, \"MissingPDFException\");\n  }\n}\nclass UnexpectedResponseException extends BaseException {\n  constructor(msg, status) {\n    super(msg, \"UnexpectedResponseException\");\n    this.status = status;\n  }\n}\nclass FormatError extends BaseException {\n  constructor(msg) {\n    super(msg, \"FormatError\");\n  }\n}\nclass AbortException extends BaseException {\n  constructor(msg) {\n    super(msg, \"AbortException\");\n  }\n}\nfunction bytesToString(bytes) {\n  if (typeof bytes !== \"object\" || bytes?.length === undefined) {\n    unreachable(\"Invalid argument for bytesToString\");\n  }\n  const length = bytes.length;\n  const MAX_ARGUMENT_COUNT = 8192;\n  if (length < MAX_ARGUMENT_COUNT) {\n    return String.fromCharCode.apply(null, bytes);\n  }\n  const strBuf = [];\n  for (let i = 0; i < length; i += MAX_ARGUMENT_COUNT) {\n    const chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length);\n    const chunk = bytes.subarray(i, chunkEnd);\n    strBuf.push(String.fromCharCode.apply(null, chunk));\n  }\n  return strBuf.join(\"\");\n}\nfunction stringToBytes(str) {\n  if (typeof str !== \"string\") {\n    unreachable(\"Invalid argument for stringToBytes\");\n  }\n  const length = str.length;\n  const bytes = new Uint8Array(length);\n  for (let i = 0; i < length; ++i) {\n    bytes[i] = str.charCodeAt(i) & 0xff;\n  }\n  return bytes;\n}\nfunction string32(value) {\n  return String.fromCharCode(value >> 24 & 0xff, value >> 16 & 0xff, value >> 8 & 0xff, value & 0xff);\n}\nfunction objectSize(obj) {\n  return Object.keys(obj).length;\n}\nfunction objectFromMap(map) {\n  const obj = Object.create(null);\n  for (const [key, value] of map) {\n    obj[key] = value;\n  }\n  return obj;\n}\nfunction isLittleEndian() {\n  const buffer8 = new Uint8Array(4);\n  buffer8[0] = 1;\n  const view32 = new Uint32Array(buffer8.buffer, 0, 1);\n  return view32[0] === 1;\n}\nfunction isEvalSupported() {\n  try {\n    new Function(\"\");\n    return true;\n  } catch {\n    return false;\n  }\n}\nclass FeatureTest {\n  static get isLittleEndian() {\n    return shadow(this, \"isLittleEndian\", isLittleEndian());\n  }\n  static get isEvalSupported() {\n    return shadow(this, \"isEvalSupported\", isEvalSupported());\n  }\n  static get isOffscreenCanvasSupported() {\n    return shadow(this, \"isOffscreenCanvasSupported\", typeof OffscreenCanvas !== \"undefined\");\n  }\n  static get platform() {\n    if (typeof navigator !== \"undefined\" && typeof navigator?.platform === \"string\") {\n      return shadow(this, \"platform\", {\n        isMac: navigator.platform.includes(\"Mac\")\n      });\n    }\n    return shadow(this, \"platform\", {\n      isMac: false\n    });\n  }\n  static get isCSSRoundSupported() {\n    return shadow(this, \"isCSSRoundSupported\", globalThis.CSS?.supports?.(\"width: round(1.5px, 1px)\"));\n  }\n}\nconst hexNumbers = Array.from(Array(256).keys(), n => n.toString(16).padStart(2, \"0\"));\nclass Util {\n  static makeHexColor(r, g, b) {\n    return `#${hexNumbers[r]}${hexNumbers[g]}${hexNumbers[b]}`;\n  }\n  static scaleMinMax(transform, minMax) {\n    let temp;\n    if (transform[0]) {\n      if (transform[0] < 0) {\n        temp = minMax[0];\n        minMax[0] = minMax[2];\n        minMax[2] = temp;\n      }\n      minMax[0] *= transform[0];\n      minMax[2] *= transform[0];\n      if (transform[3] < 0) {\n        temp = minMax[1];\n        minMax[1] = minMax[3];\n        minMax[3] = temp;\n      }\n      minMax[1] *= transform[3];\n      minMax[3] *= transform[3];\n    } else {\n      temp = minMax[0];\n      minMax[0] = minMax[1];\n      minMax[1] = temp;\n      temp = minMax[2];\n      minMax[2] = minMax[3];\n      minMax[3] = temp;\n      if (transform[1] < 0) {\n        temp = minMax[1];\n        minMax[1] = minMax[3];\n        minMax[3] = temp;\n      }\n      minMax[1] *= transform[1];\n      minMax[3] *= transform[1];\n      if (transform[2] < 0) {\n        temp = minMax[0];\n        minMax[0] = minMax[2];\n        minMax[2] = temp;\n      }\n      minMax[0] *= transform[2];\n      minMax[2] *= transform[2];\n    }\n    minMax[0] += transform[4];\n    minMax[1] += transform[5];\n    minMax[2] += transform[4];\n    minMax[3] += transform[5];\n  }\n  static transform(m1, m2) {\n    return [m1[0] * m2[0] + m1[2] * m2[1], m1[1] * m2[0] + m1[3] * m2[1], m1[0] * m2[2] + m1[2] * m2[3], m1[1] * m2[2] + m1[3] * m2[3], m1[0] * m2[4] + m1[2] * m2[5] + m1[4], m1[1] * m2[4] + m1[3] * m2[5] + m1[5]];\n  }\n  static applyTransform(p, m) {\n    const xt = p[0] * m[0] + p[1] * m[2] + m[4];\n    const yt = p[0] * m[1] + p[1] * m[3] + m[5];\n    return [xt, yt];\n  }\n  static applyInverseTransform(p, m) {\n    const d = m[0] * m[3] - m[1] * m[2];\n    const xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d;\n    const yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d;\n    return [xt, yt];\n  }\n  static getAxialAlignedBoundingBox(r, m) {\n    const p1 = this.applyTransform(r, m);\n    const p2 = this.applyTransform(r.slice(2, 4), m);\n    const p3 = this.applyTransform([r[0], r[3]], m);\n    const p4 = this.applyTransform([r[2], r[1]], m);\n    return [Math.min(p1[0], p2[0], p3[0], p4[0]), Math.min(p1[1], p2[1], p3[1], p4[1]), Math.max(p1[0], p2[0], p3[0], p4[0]), Math.max(p1[1], p2[1], p3[1], p4[1])];\n  }\n  static inverseTransform(m) {\n    const d = m[0] * m[3] - m[1] * m[2];\n    return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d, (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d];\n  }\n  static singularValueDecompose2dScale(m) {\n    const transpose = [m[0], m[2], m[1], m[3]];\n    const a = m[0] * transpose[0] + m[1] * transpose[2];\n    const b = m[0] * transpose[1] + m[1] * transpose[3];\n    const c = m[2] * transpose[0] + m[3] * transpose[2];\n    const d = m[2] * transpose[1] + m[3] * transpose[3];\n    const first = (a + d) / 2;\n    const second = Math.sqrt((a + d) ** 2 - 4 * (a * d - c * b)) / 2;\n    const sx = first + second || 1;\n    const sy = first - second || 1;\n    return [Math.sqrt(sx), Math.sqrt(sy)];\n  }\n  static normalizeRect(rect) {\n    const r = rect.slice(0);\n    if (rect[0] > rect[2]) {\n      r[0] = rect[2];\n      r[2] = rect[0];\n    }\n    if (rect[1] > rect[3]) {\n      r[1] = rect[3];\n      r[3] = rect[1];\n    }\n    return r;\n  }\n  static intersect(rect1, rect2) {\n    const xLow = Math.max(Math.min(rect1[0], rect1[2]), Math.min(rect2[0], rect2[2]));\n    const xHigh = Math.min(Math.max(rect1[0], rect1[2]), Math.max(rect2[0], rect2[2]));\n    if (xLow > xHigh) {\n      return null;\n    }\n    const yLow = Math.max(Math.min(rect1[1], rect1[3]), Math.min(rect2[1], rect2[3]));\n    const yHigh = Math.min(Math.max(rect1[1], rect1[3]), Math.max(rect2[1], rect2[3]));\n    if (yLow > yHigh) {\n      return null;\n    }\n    return [xLow, yLow, xHigh, yHigh];\n  }\n  static #getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, t, minMax) {\n    if (t <= 0 || t >= 1) {\n      return;\n    }\n    const mt = 1 - t;\n    const tt = t * t;\n    const ttt = tt * t;\n    const x = mt * (mt * (mt * x0 + 3 * t * x1) + 3 * tt * x2) + ttt * x3;\n    const y = mt * (mt * (mt * y0 + 3 * t * y1) + 3 * tt * y2) + ttt * y3;\n    minMax[0] = Math.min(minMax[0], x);\n    minMax[1] = Math.min(minMax[1], y);\n    minMax[2] = Math.max(minMax[2], x);\n    minMax[3] = Math.max(minMax[3], y);\n  }\n  static #getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, a, b, c, minMax) {\n    if (Math.abs(a) < 1e-12) {\n      if (Math.abs(b) >= 1e-12) {\n        this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, -c / b, minMax);\n      }\n      return;\n    }\n    const delta = b ** 2 - 4 * c * a;\n    if (delta < 0) {\n      return;\n    }\n    const sqrtDelta = Math.sqrt(delta);\n    const a2 = 2 * a;\n    this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, (-b + sqrtDelta) / a2, minMax);\n    this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, (-b - sqrtDelta) / a2, minMax);\n  }\n  static bezierBoundingBox(x0, y0, x1, y1, x2, y2, x3, y3, minMax) {\n    if (minMax) {\n      minMax[0] = Math.min(minMax[0], x0, x3);\n      minMax[1] = Math.min(minMax[1], y0, y3);\n      minMax[2] = Math.max(minMax[2], x0, x3);\n      minMax[3] = Math.max(minMax[3], y0, y3);\n    } else {\n      minMax = [Math.min(x0, x3), Math.min(y0, y3), Math.max(x0, x3), Math.max(y0, y3)];\n    }\n    this.#getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, 3 * (-x0 + 3 * (x1 - x2) + x3), 6 * (x0 - 2 * x1 + x2), 3 * (x1 - x0), minMax);\n    this.#getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, 3 * (-y0 + 3 * (y1 - y2) + y3), 6 * (y0 - 2 * y1 + y2), 3 * (y1 - y0), minMax);\n    return minMax;\n  }\n}\nconst PDFStringTranslateTable = (/* unused pure expression or super */ null && ([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2d8, 0x2c7, 0x2c6, 0x2d9, 0x2dd, 0x2db, 0x2da, 0x2dc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x192, 0x2044, 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018, 0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x141, 0x152, 0x160, 0x178, 0x17d, 0x131, 0x142, 0x153, 0x161, 0x17e, 0, 0x20ac]));\nfunction stringToPDFString(str) {\n  if (str[0] >= \"\\xEF\") {\n    let encoding;\n    if (str[0] === \"\\xFE\" && str[1] === \"\\xFF\") {\n      encoding = \"utf-16be\";\n      if (str.length % 2 === 1) {\n        str = str.slice(0, -1);\n      }\n    } else if (str[0] === \"\\xFF\" && str[1] === \"\\xFE\") {\n      encoding = \"utf-16le\";\n      if (str.length % 2 === 1) {\n        str = str.slice(0, -1);\n      }\n    } else if (str[0] === \"\\xEF\" && str[1] === \"\\xBB\" && str[2] === \"\\xBF\") {\n      encoding = \"utf-8\";\n    }\n    if (encoding) {\n      try {\n        const decoder = new TextDecoder(encoding, {\n          fatal: true\n        });\n        const buffer = stringToBytes(str);\n        const decoded = decoder.decode(buffer);\n        if (!decoded.includes(\"\\x1b\")) {\n          return decoded;\n        }\n        return decoded.replaceAll(/\\x1b[^\\x1b]*(?:\\x1b|$)/g, \"\");\n      } catch (ex) {\n        warn(`stringToPDFString: \"${ex}\".`);\n      }\n    }\n  }\n  const strBuf = [];\n  for (let i = 0, ii = str.length; i < ii; i++) {\n    const charCode = str.charCodeAt(i);\n    if (charCode === 0x1b) {\n      while (++i < ii && str.charCodeAt(i) !== 0x1b) {}\n      continue;\n    }\n    const code = PDFStringTranslateTable[charCode];\n    strBuf.push(code ? String.fromCharCode(code) : str.charAt(i));\n  }\n  return strBuf.join(\"\");\n}\nfunction stringToUTF8String(str) {\n  return decodeURIComponent(escape(str));\n}\nfunction utf8StringToString(str) {\n  return unescape(encodeURIComponent(str));\n}\nfunction isArrayEqual(arr1, arr2) {\n  if (arr1.length !== arr2.length) {\n    return false;\n  }\n  for (let i = 0, ii = arr1.length; i < ii; i++) {\n    if (arr1[i] !== arr2[i]) {\n      return false;\n    }\n  }\n  return true;\n}\nfunction getModificationDate(date = new Date()) {\n  const buffer = [date.getUTCFullYear().toString(), (date.getUTCMonth() + 1).toString().padStart(2, \"0\"), date.getUTCDate().toString().padStart(2, \"0\"), date.getUTCHours().toString().padStart(2, \"0\"), date.getUTCMinutes().toString().padStart(2, \"0\"), date.getUTCSeconds().toString().padStart(2, \"0\")];\n  return buffer.join(\"\");\n}\nlet NormalizeRegex = null;\nlet NormalizationMap = null;\nfunction normalizeUnicode(str) {\n  if (!NormalizeRegex) {\n    NormalizeRegex = /([\\u00a0\\u00b5\\u037e\\u0eb3\\u2000-\\u200a\\u202f\\u2126\\ufb00-\\ufb04\\ufb06\\ufb20-\\ufb36\\ufb38-\\ufb3c\\ufb3e\\ufb40-\\ufb41\\ufb43-\\ufb44\\ufb46-\\ufba1\\ufba4-\\ufba9\\ufbae-\\ufbb1\\ufbd3-\\ufbdc\\ufbde-\\ufbe7\\ufbea-\\ufbf8\\ufbfc-\\ufbfd\\ufc00-\\ufc5d\\ufc64-\\ufcf1\\ufcf5-\\ufd3d\\ufd88\\ufdf4\\ufdfa-\\ufdfb\\ufe71\\ufe77\\ufe79\\ufe7b\\ufe7d]+)|(\\ufb05+)/gu;\n    NormalizationMap = new Map([[\"ﬅ\", \"ſt\"]]);\n  }\n  return str.replaceAll(NormalizeRegex, (_, p1, p2) => p1 ? p1.normalize(\"NFKC\") : NormalizationMap.get(p2));\n}\nfunction getUuid() {\n  if (typeof crypto !== \"undefined\" && typeof crypto?.randomUUID === \"function\") {\n    return crypto.randomUUID();\n  }\n  const buf = new Uint8Array(32);\n  if (typeof crypto !== \"undefined\" && typeof crypto?.getRandomValues === \"function\") {\n    crypto.getRandomValues(buf);\n  } else {\n    for (let i = 0; i < 32; i++) {\n      buf[i] = Math.floor(Math.random() * 255);\n    }\n  }\n  return bytesToString(buf);\n}\nconst AnnotationPrefix = \"pdfjs_internal_id_\";\nconst FontRenderOps = {\n  BEZIER_CURVE_TO: 0,\n  MOVE_TO: 1,\n  LINE_TO: 2,\n  QUADRATIC_CURVE_TO: 3,\n  RESTORE: 4,\n  SAVE: 5,\n  SCALE: 6,\n  TRANSFORM: 7,\n  TRANSLATE: 8\n};\n\n\n/***/ })\n\n/******/ });\n/************************************************************************/\n/******/ // The module cache\n/******/ var __webpack_module_cache__ = {};\n/******/ \n/******/ // The require function\n/******/ function __webpack_require__(moduleId) {\n/******/ \t// Check if module is in cache\n/******/ \tvar cachedModule = __webpack_module_cache__[moduleId];\n/******/ \tif (cachedModule !== undefined) {\n/******/ \t\treturn cachedModule.exports;\n/******/ \t}\n/******/ \t// Create a new module (and put it into the cache)\n/******/ \tvar module = __webpack_module_cache__[moduleId] = {\n/******/ \t\t// no module.id needed\n/******/ \t\t// no module.loaded needed\n/******/ \t\texports: {}\n/******/ \t};\n/******/ \n/******/ \t// Execute the module function\n/******/ \t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n/******/ \n/******/ \t// Return the exports of the module\n/******/ \treturn module.exports;\n/******/ }\n/******/ \n/************************************************************************/\n/******/ /* webpack/runtime/async module */\n/******/ (() => {\n/******/ \tvar webpackQueues = typeof Symbol === \"function\" ? Symbol(\"webpack queues\") : \"__webpack_queues__\";\n/******/ \tvar webpackExports = typeof Symbol === \"function\" ? Symbol(\"webpack exports\") : \"__webpack_exports__\";\n/******/ \tvar webpackError = typeof Symbol === \"function\" ? Symbol(\"webpack error\") : \"__webpack_error__\";\n/******/ \tvar resolveQueue = (queue) => {\n/******/ \t\tif(queue && queue.d < 1) {\n/******/ \t\t\tqueue.d = 1;\n/******/ \t\t\tqueue.forEach((fn) => (fn.r--));\n/******/ \t\t\tqueue.forEach((fn) => (fn.r-- ? fn.r++ : fn()));\n/******/ \t\t}\n/******/ \t}\n/******/ \tvar wrapDeps = (deps) => (deps.map((dep) => {\n/******/ \t\tif(dep !== null && typeof dep === \"object\") {\n/******/ \t\t\tif(dep[webpackQueues]) return dep;\n/******/ \t\t\tif(dep.then) {\n/******/ \t\t\t\tvar queue = [];\n/******/ \t\t\t\tqueue.d = 0;\n/******/ \t\t\t\tdep.then((r) => {\n/******/ \t\t\t\t\tobj[webpackExports] = r;\n/******/ \t\t\t\t\tresolveQueue(queue);\n/******/ \t\t\t\t}, (e) => {\n/******/ \t\t\t\t\tobj[webpackError] = e;\n/******/ \t\t\t\t\tresolveQueue(queue);\n/******/ \t\t\t\t});\n/******/ \t\t\t\tvar obj = {};\n/******/ \t\t\t\tobj[webpackQueues] = (fn) => (fn(queue));\n/******/ \t\t\t\treturn obj;\n/******/ \t\t\t}\n/******/ \t\t}\n/******/ \t\tvar ret = {};\n/******/ \t\tret[webpackQueues] = x => {};\n/******/ \t\tret[webpackExports] = dep;\n/******/ \t\treturn ret;\n/******/ \t}));\n/******/ \t__webpack_require__.a = (module, body, hasAwait) => {\n/******/ \t\tvar queue;\n/******/ \t\thasAwait && ((queue = []).d = -1);\n/******/ \t\tvar depQueues = new Set();\n/******/ \t\tvar exports = module.exports;\n/******/ \t\tvar currentDeps;\n/******/ \t\tvar outerResolve;\n/******/ \t\tvar reject;\n/******/ \t\tvar promise = new Promise((resolve, rej) => {\n/******/ \t\t\treject = rej;\n/******/ \t\t\touterResolve = resolve;\n/******/ \t\t});\n/******/ \t\tpromise[webpackExports] = exports;\n/******/ \t\tpromise[webpackQueues] = (fn) => (queue && fn(queue), depQueues.forEach(fn), promise[\"catch\"](x => {}));\n/******/ \t\tmodule.exports = promise;\n/******/ \t\tbody((deps) => {\n/******/ \t\t\tcurrentDeps = wrapDeps(deps);\n/******/ \t\t\tvar fn;\n/******/ \t\t\tvar getResult = () => (currentDeps.map((d) => {\n/******/ \t\t\t\tif(d[webpackError]) throw d[webpackError];\n/******/ \t\t\t\treturn d[webpackExports];\n/******/ \t\t\t}))\n/******/ \t\t\tvar promise = new Promise((resolve) => {\n/******/ \t\t\t\tfn = () => (resolve(getResult));\n/******/ \t\t\t\tfn.r = 0;\n/******/ \t\t\t\tvar fnQueue = (q) => (q !== queue && !depQueues.has(q) && (depQueues.add(q), q && !q.d && (fn.r++, q.push(fn))));\n/******/ \t\t\t\tcurrentDeps.map((dep) => (dep[webpackQueues](fnQueue)));\n/******/ \t\t\t});\n/******/ \t\t\treturn fn.r ? promise : getResult();\n/******/ \t\t}, (err) => ((err ? reject(promise[webpackError] = err) : outerResolve(exports)), resolveQueue(queue)));\n/******/ \t\tqueue && queue.d < 0 && (queue.d = 0);\n/******/ \t};\n/******/ })();\n/******/ \n/******/ /* webpack/runtime/define property getters */\n/******/ (() => {\n/******/ \t// define getter functions for harmony exports\n/******/ \t__webpack_require__.d = (exports, definition) => {\n/******/ \t\tfor(var key in definition) {\n/******/ \t\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n/******/ \t\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n/******/ \t\t\t}\n/******/ \t\t}\n/******/ \t};\n/******/ })();\n/******/ \n/******/ /* webpack/runtime/hasOwnProperty shorthand */\n/******/ (() => {\n/******/ \t__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))\n/******/ })();\n/******/ \n/************************************************************************/\n/******/ \n/******/ // startup\n/******/ // Load entry module and return exports\n/******/ // This entry module used 'module' so it can't be inlined\n/******/ var __webpack_exports__ = __webpack_require__(228);\n/******/ __webpack_exports__ = globalThis.pdfjsLib = await (globalThis.pdfjsLibPromise = __webpack_exports__);\n/******/ var __webpack_exports__AbortException = __webpack_exports__.AbortException;\n/******/ var __webpack_exports__AnnotationEditorLayer = __webpack_exports__.AnnotationEditorLayer;\n/******/ var __webpack_exports__AnnotationEditorParamsType = __webpack_exports__.AnnotationEditorParamsType;\n/******/ var __webpack_exports__AnnotationEditorType = __webpack_exports__.AnnotationEditorType;\n/******/ var __webpack_exports__AnnotationEditorUIManager = __webpack_exports__.AnnotationEditorUIManager;\n/******/ var __webpack_exports__AnnotationLayer = __webpack_exports__.AnnotationLayer;\n/******/ var __webpack_exports__AnnotationMode = __webpack_exports__.AnnotationMode;\n/******/ var __webpack_exports__CMapCompressionType = __webpack_exports__.CMapCompressionType;\n/******/ var __webpack_exports__ColorPicker = __webpack_exports__.ColorPicker;\n/******/ var __webpack_exports__DOMSVGFactory = __webpack_exports__.DOMSVGFactory;\n/******/ var __webpack_exports__DrawLayer = __webpack_exports__.DrawLayer;\n/******/ var __webpack_exports__FeatureTest = __webpack_exports__.FeatureTest;\n/******/ var __webpack_exports__GlobalWorkerOptions = __webpack_exports__.GlobalWorkerOptions;\n/******/ var __webpack_exports__ImageKind = __webpack_exports__.ImageKind;\n/******/ var __webpack_exports__InvalidPDFException = __webpack_exports__.InvalidPDFException;\n/******/ var __webpack_exports__MissingPDFException = __webpack_exports__.MissingPDFException;\n/******/ var __webpack_exports__OPS = __webpack_exports__.OPS;\n/******/ var __webpack_exports__Outliner = __webpack_exports__.Outliner;\n/******/ var __webpack_exports__PDFDataRangeTransport = __webpack_exports__.PDFDataRangeTransport;\n/******/ var __webpack_exports__PDFDateString = __webpack_exports__.PDFDateString;\n/******/ var __webpack_exports__PDFWorker = __webpack_exports__.PDFWorker;\n/******/ var __webpack_exports__PasswordResponses = __webpack_exports__.PasswordResponses;\n/******/ var __webpack_exports__PermissionFlag = __webpack_exports__.PermissionFlag;\n/******/ var __webpack_exports__PixelsPerInch = __webpack_exports__.PixelsPerInch;\n/******/ var __webpack_exports__RenderingCancelledException = __webpack_exports__.RenderingCancelledException;\n/******/ var __webpack_exports__UnexpectedResponseException = __webpack_exports__.UnexpectedResponseException;\n/******/ var __webpack_exports__Util = __webpack_exports__.Util;\n/******/ var __webpack_exports__VerbosityLevel = __webpack_exports__.VerbosityLevel;\n/******/ var __webpack_exports__XfaLayer = __webpack_exports__.XfaLayer;\n/******/ var __webpack_exports__build = __webpack_exports__.build;\n/******/ var __webpack_exports__createValidAbsoluteUrl = __webpack_exports__.createValidAbsoluteUrl;\n/******/ var __webpack_exports__fetchData = __webpack_exports__.fetchData;\n/******/ var __webpack_exports__getDocument = __webpack_exports__.getDocument;\n/******/ var __webpack_exports__getFilenameFromUrl = __webpack_exports__.getFilenameFromUrl;\n/******/ var __webpack_exports__getPdfFilenameFromUrl = __webpack_exports__.getPdfFilenameFromUrl;\n/******/ var __webpack_exports__getXfaPageViewport = __webpack_exports__.getXfaPageViewport;\n/******/ var __webpack_exports__isDataScheme = __webpack_exports__.isDataScheme;\n/******/ var __webpack_exports__isPdfFile = __webpack_exports__.isPdfFile;\n/******/ var __webpack_exports__noContextMenu = __webpack_exports__.noContextMenu;\n/******/ var __webpack_exports__normalizeUnicode = __webpack_exports__.normalizeUnicode;\n/******/ var __webpack_exports__renderTextLayer = __webpack_exports__.renderTextLayer;\n/******/ var __webpack_exports__setLayerDimensions = __webpack_exports__.setLayerDimensions;\n/******/ var __webpack_exports__shadow = __webpack_exports__.shadow;\n/******/ var __webpack_exports__updateTextLayer = __webpack_exports__.updateTextLayer;\n/******/ var __webpack_exports__version = __webpack_exports__.version;\n/******/ export { __webpack_exports__AbortException as AbortException, __webpack_exports__AnnotationEditorLayer as AnnotationEditorLayer, __webpack_exports__AnnotationEditorParamsType as AnnotationEditorParamsType, __webpack_exports__AnnotationEditorType as AnnotationEditorType, __webpack_exports__AnnotationEditorUIManager as AnnotationEditorUIManager, __webpack_exports__AnnotationLayer as AnnotationLayer, __webpack_exports__AnnotationMode as AnnotationMode, __webpack_exports__CMapCompressionType as CMapCompressionType, __webpack_exports__ColorPicker as ColorPicker, __webpack_exports__DOMSVGFactory as DOMSVGFactory, __webpack_exports__DrawLayer as DrawLayer, __webpack_exports__FeatureTest as FeatureTest, __webpack_exports__GlobalWorkerOptions as GlobalWorkerOptions, __webpack_exports__ImageKind as ImageKind, __webpack_exports__InvalidPDFException as InvalidPDFException, __webpack_exports__MissingPDFException as MissingPDFException, __webpack_exports__OPS as OPS, __webpack_exports__Outliner as Outliner, __webpack_exports__PDFDataRangeTransport as PDFDataRangeTransport, __webpack_exports__PDFDateString as PDFDateString, __webpack_exports__PDFWorker as PDFWorker, __webpack_exports__PasswordResponses as PasswordResponses, __webpack_exports__PermissionFlag as PermissionFlag, __webpack_exports__PixelsPerInch as PixelsPerInch, __webpack_exports__RenderingCancelledException as RenderingCancelledException, __webpack_exports__UnexpectedResponseException as UnexpectedResponseException, __webpack_exports__Util as Util, __webpack_exports__VerbosityLevel as VerbosityLevel, __webpack_exports__XfaLayer as XfaLayer, __webpack_exports__build as build, __webpack_exports__createValidAbsoluteUrl as createValidAbsoluteUrl, __webpack_exports__fetchData as fetchData, __webpack_exports__getDocument as getDocument, __webpack_exports__getFilenameFromUrl as getFilenameFromUrl, __webpack_exports__getPdfFilenameFromUrl as getPdfFilenameFromUrl, __webpack_exports__getXfaPageViewport as getXfaPageViewport, __webpack_exports__isDataScheme as isDataScheme, __webpack_exports__isPdfFile as isPdfFile, __webpack_exports__noContextMenu as noContextMenu, __webpack_exports__normalizeUnicode as normalizeUnicode, __webpack_exports__renderTextLayer as renderTextLayer, __webpack_exports__setLayerDimensions as setLayerDimensions, __webpack_exports__shadow as shadow, __webpack_exports__updateTextLayer as updateTextLayer, __webpack_exports__version as version };\n/******/ \n\n//# sourceMappingURL=pdf.mjs.map"
  },
  {
    "path": "src/StaffWebUI/wwwroot/pdfjs-4.2.67-dist/build/pdf.sandbox.mjs",
    "content": "/**\n * @licstart The following is the entire license notice for the\n * JavaScript code in this page\n *\n * Copyright 2023 Mozilla Foundation\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 * @licend The above is the entire license notice for the\n * JavaScript code in this page\n */\n\n/******/ // The require scope\n/******/ var __webpack_require__ = {};\n/******/ \n/************************************************************************/\n/******/ /* webpack/runtime/define property getters */\n/******/ (() => {\n/******/ \t// define getter functions for harmony exports\n/******/ \t__webpack_require__.d = (exports, definition) => {\n/******/ \t\tfor(var key in definition) {\n/******/ \t\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n/******/ \t\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n/******/ \t\t\t}\n/******/ \t\t}\n/******/ \t};\n/******/ })();\n/******/ \n/******/ /* webpack/runtime/hasOwnProperty shorthand */\n/******/ (() => {\n/******/ \t__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))\n/******/ })();\n/******/ \n/************************************************************************/\nvar __webpack_exports__ = globalThis.pdfjsSandbox = {};\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, {\n  QuickJSSandbox: () => (/* binding */ QuickJSSandbox)\n});\n\n;// CONCATENATED MODULE: ./external/quickjs/quickjs-eval.js\nvar Module=(()=>{var _scriptDir=typeof document!=='undefined'&&document.currentScript?document.currentScript.src:undefined;return function(moduleArg={}){var d=moduleArg,k,n;d.ready=new Promise((a,b)=>{k=a;n=b;});var p=Object.assign({},d),q=\"\";\"undefined\"!=typeof document&&document.currentScript&&(q=document.currentScript.src);_scriptDir&&(q=_scriptDir);q.startsWith(\"blob:\")?q=\"\":q=q.substr(0,q.replace(/[?#].*/,\"\").lastIndexOf(\"/\")+1);var aa=d.print||console.log.bind(console),u=d.printErr||console.error.bind(console);Object.assign(d,p);p=null;var v;d.wasmBinary&&(v=d.wasmBinary);\"object\"!=typeof WebAssembly&&w(\"no native wasm support detected\");var x,y=!1,z,A,B,C;function D(){var a=x.buffer;d.HEAP8=z=new Int8Array(a);d.HEAP16=new Int16Array(a);d.HEAPU8=A=new Uint8Array(a);d.HEAPU16=new Uint16Array(a);d.HEAP32=B=new Int32Array(a);d.HEAPU32=C=new Uint32Array(a);d.HEAPF32=new Float32Array(a);d.HEAPF64=new Float64Array(a);}var E=[],F=[],G=[];function ba(){var a=d.preRun.shift();E.unshift(a);}var H=0,I=null,J=null;function w(a){d.onAbort?.(a);a=\"Aborted(\"+a+\")\";u(a);y=!0;a=new WebAssembly.RuntimeError(a+\". Build with -sASSERTIONS for more info.\");n(a);throw a;}var K=a=>a.startsWith(\"data:application/octet-stream;base64,\"),L;L=\"data:application/octet-stream;base64,AGFzbQEAAAABzgZtYAJ/fwBgA39/fwF/YAR/fn9/AX5gAn9/AX9gBX9+f39/AX5gAX8Bf2ADf39/AGAEf39/fwF/YAJ/fgF+YAF/AGABfAF8YAV/f39/fwF/YAJ/fgBgAn9+AX9gAn9/AX5gA39/fgF/YAN/fn8BfmAGf35/f39/AX5gA39+fwBgA39+fwF/YAZ/f39/f38Bf2AEf39/fwBgBn9+fn9/fwF+YAR/f35/AX9gA39+fgF+YAN/f38BfmADf35+AX9gBH9/f38BfmAFf35+fn4AYAJ8fAF8YAF/AX5gBH9/f34Bf2AFf35+f38BfmAFf39/f38AYAd/fn9+fn5/AX9gBX9/f35+AX9gB39/f39/f38Bf2AAAGAFf35/fn8Bf2AEf35+fwBgBH9+fn8BfmAFf35+fn8Bf2AFf39/f38BfmAEf39+fgF/YAF+AX9gBH9+f34BfmAEf35/fwBgBH9+fn8Bf2AJf39/f39/f39/AX9gCH9/f39/f39/AX9gA39+fgBgBH9+f38Bf2AGf35/fn5/AX9gBX9+fn9/AGABfgF+YAd/fn9/f39/AX5gAX8BfGADf39+AGAEf35/fgF/YAV/f35/fwF/YAR/fn5+AX9gBn9/f39/fwF+YAN+f38Bf2AHf39/f39/fwBgAnx/AXxgA39/fgF+YAJ+fwF/YAN8fH8BfGAEf39+fwBgBH9+fn4BfmAAAX9gBn98f39/fwF/YAABfGAFf35/fn8BfmAGf39+fn5+AX9gAn5/AGACf3wAYAV/f39/fgF+YAR/f35/AX5gBH9+f34AYAd/fn5+f39/AX5gBH5+fn4Bf2AKf39/f39/f39/fwF/YAd/f39/f39+AX5gBX9+f39/AGAHfH9/f39/fwBgBX98f39/AX5gAXwBf2AFf39+f38AYAZ/fn5+fn8Bf2AGf35/f39/AX9gBH98f38Bf2AGf39/f39/AGAEf39/fgF+YAV/fn9/fwF/YAV/fn5+fgF/YAJ/fwF8YAV/fn5/fwF/YAV/f35+fgF+YAV/f35+fwF/YAJ8fwF/YAJ8fAF/YAh/fn5+fn9+fgF+YAN/fnwBfmAAAX5gB39/f35+fn8Bf2ACfn4BfGADfn5+AX9gA39/fAACSQwBYQFhABUBYQFiACUBYQFjAAcBYQFkAAYBYQFlAEgBYQFmAAABYQFn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IAILLQEBfwJAIAAoAgAiAUUNACAAKAIQIgBFDQAgASgCACAAQQAgASgCBBEBABoLCzEAIAFBAE4EQCAAQbYBEA0gACABEDggACgCQCIAKAKkAiABQRRsaiAAKAKEAjYCBAsLJwEBfyMAQRBrIgIkACACIAE2AgwgACACQQxqQQQQchogAkEQaiQACxcAIAAgASACQoCAgIAwIAMgBEECENIBCxgBAX4gASkDACEDIAEgAjcDACAAIAMQDAszAQF/IAIEQCAAIQMDQCADIAEtAAA6AAAgA0EBaiEDIAFBAWohASACQQFrIgINAAsLIAALwQUCAn4GfyMAQeAAayIJJAAgA0EAIANBAEobIQsDQCAKIAtHBEAgACACIApBBHRqIgMoAgAQsAUhBiADLQAEIQdCgICAgDAhBAJAAkACQAJAAkACQAJAAkACQAJAIAMtAAUOCgECAgUHAwQIBQAGCyAAIAMoAggQsAUhCAJ+AkACQAJAIAMoAgxBAWoOAwIAAQkLIAAgACkDwAEiBCAIIARBABARDAILIAAgACgCKCkDECIEIAggBEEAEBEMAQsgACABIAggAUEAEBELIQQgACAIEBAgBkHLAUYEQEEBIQcMCAsgBkHUAUcNB0EAIQcMBwsCQCAGQcsBRgRAQQEhBwwBCyAGQdQBRw0AQQAhBwsgACABIAZBAiADIAcQgAMaDAcLIAAgASAGQoCAgIAwIAMoAggEfiAJIAMoAgA2AhAgCUEgaiIIQcAAQeEqIAlBEGoQSBogACADKAIIIAhBAEEKQQggAy0ABUECRhsgAy4BBhCCAQVCgICAgDALIgQgAygCDAR+IAkgAygCADYCACAJQSBqIghBwABB2iogCRBIGiAAIAMoAgwgCEEBQQtBCSADLQAFQQJGGyADLgEGEIIBBUKAgICAMAsiBSAHQYA6chBqGiAAIAQQDCAAIAUQDAwGCyADKQMIIgRCgICAgAh8Qv////8PWARAIARC/////w+DIQQMBQtCgICAgMB+IAS5vSIEQoCAgIDAgYD8/wB9IARC////////////AINCgICAgICAgPj/AFYbIQQMBAtCgICAgMB+IAMpAwgiBEKAgICAwIGA/P8AfSAEQv///////////wCDQoCAgICAgID4/wBWGyEEDAMLIAAgASAGQQIgAyAHEIADGgwDCxABAAsgAzUCCCEECyAAIAEgBiAEIAcQFRoLIAAgBhAQIApBAWohCgwBCwsgCUHgAGokAAuMAgICfgF/AkACQAJAAkACQAJAAkACQAJAQQcgAUIgiKciBCAEQQdrQW5JG0EKag4SAgAGBAAAAAAAAQMFAAAAAAEDAAsgAEGbHkEAEBJCgICAgOAADwsgBEF1SQ0GIAGnIgAgACgCAEEBajYCAAwGCyAAQSEQhgEhAgwECyAAQQQQhgEhAgwDCyAAIABBBRCGASICQTAgAacpAgRC/////weDQQAQFRoMAgsgAEEGEIYBIQIMAQsgAEEHEIYBIQILQoCAgIDgACEDIAJCgICAgHCDQoCAgIDgAFIEfiAEQXVPBEAgAaciBCAEKAIAQQFqNgIACyAAIAIgARC9ASACBUKAgICA4AALDwsgAQsyAQF/AkAgAUIgiKdBdUkNACABpyICIAIoAgAiAkEBazYCACACQQFKDQAgACABEJcFCwsLACAAQeweQQAQEgujBAELfyAAKAIAIQUjAEEQayIIIAI2AgxBfyEJAkADQAJAIAggAiIDQQRqIgI2AgwgAygCACIHQX9GDQAgACgCBCEKA0AgASIEIApODQMgBCAEIAVqIgwtAAAiBkECdEHgrgFqIg0tAABqIgEgCkoNAyAGQcYBRgRAIAwoAAEhCQwBCwsgBiAHRwRAIAdBGHYgBkYgBiAHQRB2Qf8BcUZyIAYgB0H/AXFGckUgBiAHQQh2Qf8BcUdxIAZFIAdBgAJJcnINAyAAIAY2AhALIARBAWohBAJAAkACQAJAAkACQAJAAkAgDS0AA0EFaw4YAAkACQkBCQkBCQkBAQECAgICBAUGBwkDCQsgBCAFai0AACEEIAggA0EIaiICNgIMIAMoAgQiA0F/RgRAIAAgBDYCFAwJCyADIARGDQgMCQsgBCAFai8AACEEIAggA0EIaiICNgIMIAMoAgQiA0F/RgRAIAAgBDYCFAwICyADIARGDQcMCAsgACAEIAVqKAAANgIYDAYLIAAgBCAFaiIDKAAANgIYIAAgAy8ABDYCHAwFCyAAIAQgBWooAAA2AiAMBAsgACAEIAVqIgMoAAA2AiAgACADLQAENgIcDAMLIAAgBCAFaiIDKAAANgIgIAAgAy8ABDYCHAwCCyAAIAQgBWoiAygAADYCICAAIAMoAAQ2AhggACADLQAINgIcDAELCyAAIAk2AgwgACABNgIIQQEhCwsgCwskAQF/IAAoAhAiAkEQaiABIAIoAgARAwAiAUUEQCAAEHALIAELCwAgACABQQAQjQQLJwEBfyMAQRBrIgIkACACIAE7AQ4gACACQQ5qQQIQchogAkEQaiQAC9QBAgR/An5BfyECAkACQAJAAkACQAJAAkAgAUIgiKciA0EKag4RAwUFAgUFBQUFBAABAQEFBQYFCyABp0EARw8LIAGnDwsgAacpAgQhByAAIAEQDCAHQv////8Hg0IAUg8LIAGnKAIMIQQgACABEAwgBEH/////B2pBfkkPCyABpywABSEFIAAgARAMIAVBAE4PCyADQQdrQW1NBEAgAUKAgICAwIGA/P8AfEL///////////8Ag0IBfUKAgICAgICA+P8AVA8LIAAgARAMQQEhAgsgAgs/AQJ/IwBBEGsiAiQAAn8gASAAKAIQRwRAIAIgATYCACAAQcyQASACEBNBfwwBCyAAEA8LIQMgAkEQaiQAIAMLCwAgACABQQEQ6QULGQAgAEEAEFAaIABCgICAgPD/////ADcCBAvDCgIFfxF+IwBB4ABrIgUkACAEQv///////z+DIQwgAiAEhUKAgICAgICAgIB/gyEKIAJC////////P4MiDUIgiCEOIARCMIinQf//AXEhBwJAAkAgAkIwiKdB//8BcSIJQf//AWtBgoB+TwRAIAdB//8Ba0GBgH5LDQELIAFQIAJC////////////AIMiC0KAgICAgIDA//8AVCALQoCAgICAgMD//wBRG0UEQCACQoCAgICAgCCEIQoMAgsgA1AgBEL///////////8AgyICQoCAgICAgMD//wBUIAJCgICAgICAwP//AFEbRQRAIARCgICAgICAIIQhCiADIQEMAgsgASALQoCAgICAgMD//wCFhFAEQCACIAOEUARAQoCAgICAgOD//wAhCkIAIQEMAwsgCkKAgICAgIDA//8AhCEKQgAhAQwCCyADIAJCgICAgICAwP//AIWEUARAIAEgC4QhGUIAIQEgGVAEQEKAgICAgIDg//8AIQoMAwsgCkKAgICAgIDA//8AhCEKDAILIAEgC4RQBEBCACEBDAILIAIgA4RQBEBCACEBDAILIAtC////////P1gEQCAFQdAAaiABIA0gASANIA1QIgYbeSAG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////B4OENwIEIABBADYCBCABrUKAgICAkH+ECwsPACAAKAJAQYACaiABEBsLEwAgACABIAIgAyABQYCAARDQAQsNACAAIAEgAkEGEMgCCx8BAX8gACgCJCIBIAEoAgBBAWo2AgAgACABQQIQ5wULZwECfwJ/IAAoAggiAiAAKAIMTgRAQX8gACACQQFqIAEQxAINARoLIAAgACgCCCIDQQFqNgIIIAAoAgRBEGohAgJAIAAoAhAEQCACIANBAXRqIAE7AQAMAQsgAiADaiABOgAAC0EACwt6AQN/AkACQCAAIgFBA3FFDQAgAS0AAEUEQEEADwsDQCABQQFqIgFBA3FFDQEgAS0AAA0ACwwBCwNAIAEiAkEEaiEBIAIoAgAiA0F/cyADQYGChAhrcUGAgYKEeHFFDQALA0AgAiIBQQFqIQIgAS0AAA0ACwsgASAAawsNACAAIAEgAkEAEJkDCywBAX8jAEEQayIDJAAgAyACNgIMIABB3ABqQYABIAEgAhDJAhogA0EQaiQAC+gDAQl/IwBBIGsiBSQAIAEgAiABKAIMIAIoAgxJIgYbIgcoAgQgAiABIAYbIggoAgRzIQoCQAJAIAcoAgwiAkUEQAJAIAgoAggiAUH/////B0cEQCAHKAIIIgJB/////wdHDQELIAAQKkEAIQIMAwsgAUH+////B0cgAkH+////B0dxRQRAAkAgAUH+////B0YEQCACQYCAgIB4Rg0BDAQLIAFBgICAgHhHIAJB/v///wdHcg0DCyAAECpBASECDAMLIAAgChCAAUEAIQIMAgsgCCgCDCILIQkgAiEGIARBB3FBBkYEQCACIANBIWpBBXYiASABIAJKGyEGIAsgASABIAtKGyEJCwJ/AkAgACAIRg0AIAAgB0YNACAADAELIAAoAgAhASAFQgA3AhggBUKAgICAgICAgIB/NwIQIAUgATYCDCAAIQwgBUEMagshASAHKAIQIQAgCCgCECENAn8gASAGIAlqEFAEQCABECpBIAwBCyABKAIQIA0gC0ECdGogCUECdGsgCSAAIAJBAnRqIAZBAnRrIAYQ8AEgASAKNgIEIAEgBygCCCAIKAIIajYCCCABIAMgBBCbAgshAiABIAVBDGoiAEcNASAMIAAQvwQMAQsgACAKEH9BACECCyAFQSBqJAAgAgsKACAAIAFBARBHCygB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ajAAAEL/////D4MPCyAEKAIoIANNDQggBCgCJCADajEAAA8LIAQoAiggA00NByAEKAIkIANBAXRqMgEAQv////8Pgw8LIAQoAiggA00NBiAEKAIkIANBAXRqMwEADwsgBCgCKCADTQ0FIAQoAiQgA0ECdGo1AgAPCyAEKAIoIANNDQQgBCgCJCADQQJ0aigCACIAQQBOBEAgAK0PC0KAgICAwH4gALi9IgFCgICAgMCBgPz/AH0gAUKAgICAgICA+P8AVhsPCyAEKAIoIANNDQMgACAEKAIkIANBA3RqKQMAEL8CDwsgBCgCKCADTQ0CIAAgBCgCJCADQQN0aikDABCIBA8LIAQoAiggA00NAUKAgICAwH4gBCgCJCADQQJ0aioCALu9IgFCgICAgMCBgPz/AH0gAUL///////////8Ag0KAgICAgICA+P8AVhsPCyAEKAIoIANNDQBCgICAgMB+IAQoAiQgA0EDdGopAwAiAUKAgICAwIGA/P8AfSABQv///////////wCDQoCAgICAgID4/wBWGw8LIAAgAhAwIQMgACACEAwgA0UEQEKAgICA4AAPCyAAIAEgAyABQQAQESEBIAAgAxAQCyABC4IDAgR/An4CQCAAKQNwIgVQRSAFIAApA3ggACgCBCIBIAAoAiwiAmusfCIGV3FFBEAjAEEQayICJABBfyEBAkACfyAAIAAoAkgiA0EBayADcjYCSCAAKAIUIAAoAhxHBEAgAEEAQQAgACgCJBEBABoLIABBADYCHCAAQgA3AxAgACgCACIDQQRxBEAgACADQSByNgIAQX8MAQsgACAAKAIsIAAoAjBqIgQ2AgggACAENgIEIANBG3RBH3ULDQAgACACQQ9qQQEgACgCIBEBAEEBRw0AIAItAA8hAQsgAkEQaiQAIAEiA0EATg0BIAAoAgQhASAAKAIsIQILIABCfzcDcCAAIAE2AmggACAGIAIgAWusfDcDeEF/DwsgBkIBfCEGIAAoAgQhASAAKAIIIQICQCAAKQNwIgVQDQAgBSAGfSIFIAIgAWusWQ0AIAEgBadqIQILIAAgAjYCaCAAIAYgACgCLCIAIAFrrHw3A3ggACABTwRAIAFBAWsgAzoAAAsgAwtPAQF/An9BACAAKAIMIAFGDQAaIAAoAgAiAigCACAAKAIQIAFBAnQgAigCBBEBACECIAEEQEF/IAJFDQEaCyAAIAE2AgwgACACNgIQQQALC9EBAQZ/IABBAWohBQJAAkAgAC0AACIDwCIHQQBOBEAgBSEBDAELQX8hBCAHQUBrQf8BcSIDQT1LDQEgA0ECdEGU9gFqKAIAIgYgAU4NASAGQQFrIQggACAGakEBaiEBIAcgBkHz9QFqLQAAcSEDQQAhAANAIAAgBkcEQCAFLAAAIgRBv39KBEBBfw8FIARBP3EgA0EGdHIhAyAAQQFqIQAgBUEBaiEFDAILAAsLQX8hBCADIAhBAnRBgPYBaigCAEkNAQsgAiABNgIAIAMhBAsgBAsLACAAIAFBABDpBQsJACAAQQEQrQELugEBAn8CQAJAIAJC/////wdYBEAgACABIAKnQYCAgIB4chBuIgRBAEwNASAAIAEgAhBOIgJCgICAgHCDQoCAgIDgAFINAkF/IQQMAgsgACACEIsDIgVFBEBBfyEEDAELAkAgACABIAUQbiIEQQBMBEBCgICAgDAhAgwBCyAAIAEgBSABQQAQESICQoCAgIBwg0KAgICA4ABSDQBBfyEECyAAIAUQEAwBC0KAgICAMCECCyADIAI3AwAgBAsbAQF/IAAgARA1BH9BAAUgAEH7OUEAEBJBfwsLYwEBfyACQiCIp0F1TwRAIAKnIgUgBSgCAEEBajYCAAsCQCAAIAEgAhDTBSIFDQACQCABKAIAIgBBAEgEQCAAIARqIgBBACAAQQBKGyEDDAELIAAgA0wNAQsgASADNgIACyAFCxgAIAAtAABBIHFFBEAgASACIAAQlwQaCwsPACAAKAJAQYACaiABEA4LrgIAAkACQAJAAkAgAkEDTARAAkACQAJAAkACQAJAAkACQAJAIAFB2ABrDgkAAQIDBAUGBwgKCyAAIAJBO2tB/wFxEA4PCyAAIAJBN2tB/wFxEA4PCyAAIAJBM2tB/wFxEA4PCyAAIAJBL2tB/wFxEA4PCyAAIAJBK2tB/wFxEA4PCyAAIAJBJ2tB/wFxEA4PCyAAIAJBI2tB/wFxEA4PCyAAIAJBH2tB/wFxEA4PCyAAIAJBG2tB/wFxEA4PCyACQf8BSw0BAkACQAJAIAFB2ABrDgMAAQIECyAAQcIBEA4MBQsgAEHDARAODAQLIABBxAEQDgwDCyABQSJGDQELIAAgAUH/AXEQDiAAIAJB//8DcRAmDwsgACACQRJrQf8BcRAODwsgACACQf8BcRAOCzgBAX8CQAJAIAFCgICAgHBUDQAgAaciAy8BBiACRw0AIAMoAiAiAw0BCyAAIAIQigNBACEDCyADC0EBAX8gAQRAA0AgAiADRkUEQCAAIAEgA0EDdGooAgQQECADQQFqIQMMAQsLIAAoAhAiAEEQaiABIAAoAgQRAAALCywBAX8gACgCECICQRBqIAEgAigCABEDACICBEAgAkEAIAEQLA8LIAAQcCACC20BAX8jAEGAAmsiBSQAIARBgMAEcSACIANMckUEQCAFIAFB/wFxIAIgA2siA0GAAiADQYACSSIBGxAsGiABRQRAA0AgACAFQYACEFcgA0GAAmsiA0H/AUsNAAsLIAAgBSADEFcLIAVBgAJqJAALvgECAn4BfwJAAkAgAUKAgICAcINCgICAgDBRBEAgACgCKCACQQN0aikDACIDQiCIp0F0Sw0BDAILIAAgAUE8IAFBABARIgNCgICAgHCDQoCAgIDgAFEEQCADDwsgA0L/////b1YNASAAIAMQDCAAIAEQ/AIiBUUEQEKAgICA4AAPCyAFKAIoIAJBA3RqKQMAIgNCIIinQXVJDQELIAOnIgUgBSgCAEEBajYCAAsgACADIAIQRyEEIAAgAxAMIAQLDAAgAEHZ6gBBABASCw0AIAAgASABED0Q6gELdQEBfiAAIAEgBH4gAiADfnwgA0IgiCICIAFCIIgiBH58IANC/////w+DIgMgAUL/////D4MiAX4iBUIgiCADIAR+fCIDQiCIfCABIAJ+IANC/////w+DfCIBQiCIfDcDCCAAIAVC/////w+DIAFCIIaENwMAC1ABAX4CQCADQcAAcQRAIAEgA0FAaq2GIQJCACEBDAELIANFDQAgAiADrSIEhiABQcAAIANrrYiEIQIgASAEhiEBCyAAIAE3AwAgACACNwMIC2QAAkACQCABQQBIDQAgACgCrAIgAUwNACAAKAKkAiABQRRsaiIAIAAoAgAgAmoiADYCACAAQQBIDQEgAA8LQdwXQajsAEHzpwFBr8MAEAAAC0HphQFBqOwAQfanAUGvwwAQAAALcAECfyAEIAMoAgBKBH8jAEEQayIFJAAgACABKAIAIAQgAygCAEEDbEECbSIAIAAgBEgbIgAgAmwgBUEMahCnASIEBH8gAyAFKAIMIAJu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EGsiBCQAAkAgAkIgiKciA0ECTQRAIAEgAqe3OQMAQQAhAwwBCyADQQdrQW1NBEAgASACQoCAgIDAgYD8/wB8NwMAQQAhAwwBCwJ/IAAgAhCWASICQoCAgIBwg0KAgICA4ABRBEBEAAAAAAAA+H8hBUF/DAELAnwCQAJAQQcgAkIgiKciAyADQQdrQW5JGyIDQXZHBEAgA0EHRg0CIAMNASACp7cMAwsgAqdBBGogBEEIahCxBCAAIAIQDCAEKwMIIQVBAAwDCxABAAsgAkKAgICAwIGA/P8AfL8LIQVBAAshAyABIAU5AwALIARBEGokACADC90BAQN/AkAgAUKAgICAcFoEQCABpyEDA0ACQCADLQAFQQRxRQ0AIAAoAhAoAkQgAy8BBkEYbGooAhQiBEUNACAEKAIQIgRFDQAgAyADKAIAQQFqNgIAIAAgA61CgICAgHCEIgEgAiAEERMAIQUgACABEAwgBQ8LIAMgAygCAEEBajYCACAAQQAgAyACEEMhBCAAIAOtQoCAgIBwhBAMIAQNAgJAIAMvAQZBFWtB//8DcUEKSw0AIAAgAhCTAyIERQ0AIARBH3UPCyADKAIQKAIsIgMNAAsLQQAhBAsgBAvNCQIEfwV+IwBB8ABrIgYkACAEQv///////////wCDIQkCQAJAIAFQIgUgAkL///////////8AgyIKQoCAgICAgMD//wB9QoCAgICAgMCAgH9UIApQG0UEQCADQgBSIAlCgICAgICAwP//AH0iC0KAgICAgIDAgIB/ViALQoCAgICAgMCAgH9RGw0BCyAFIApCgICAgICAwP//AFQgCkKAgICAgIDA//8AURtFBEAgAkKAgICAgIAghCEEIAEhAwwCCyADUCAJQoCAgICAgMD//wBUIAlCgICAgICAwP//AFEbRQRAIARCgICAgICAIIQhBAwCCyABIApCgICAgICAwP//AIWEUARAQoCAgICAgOD//wAgAiABIAOFIAIgBIVCgICAgICAgICAf4WEUCIFGyEEQgAgASAFGyEDDAILIAMgCUKAgICAgIDA//8AhYRQDQEgASAKhFAEQCADIAmEQgBSDQIgASADgyEDIAIgBIMhBAwCCyADIAmEUEUNACABIQMgAiEEDAELIAMgASABIANUIAkgClYgCSAKURsiCBshCiAEIAIgCBsiDEL/////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/wBWGwsQTgtTAQF/IAAoAhAiBEEQaiABIAIgBCgCCBEBACIBIAJFckUEQCAAEHAgAQ8LIAMEQCADIAEgACgCECgCDBEFACIAIAJrIgJBACAAIAJPGzYCAAsgAQsNACAAQQAgAUEAEJoDC/kBAgN+An8jAEEQayIFJAACfiABvSIEQv///////////wCDIgJCgICAgICAgAh9Qv/////////v/wBYBEAgAkI8hiEDIAJCBIhCgICAgICAgIA8fAwBCyACQoCAgICAgID4/wBaBEAgBEI8hiEDIARCBIhCgICAgICAwP//AIQMAQsgAlAEQEIADAELIAUgAkIAIAKnZ0EgaiACQiCIp2cgAkKAgICAEFQbIgZBMWoQYiAFKQMAIQMgBSkDCEKAgICAgIDAAIVBjPgAIAZrrUIwhoQLIQIgACADNwMAIAAgAiAEQoCAgICAgICAgH+DhDcDCCAFQRBqJAALKgEBfyMAQRBrIgMkACADIAI2AgwgACABIAJBpANBABCUBBogA0EQaiQAC0cAIAAgAUkEQCAAIAEgAhAeGg8LIAIEQCAAIAJqIQAgASACaiEBA0AgAEEBayIAIAFBAWsiAS0AADoAACACQQFrIgINAAsLCyABAX4gACAAIAIgASADQQRBABCCASIFIAEgBBC/ASAFC4sMAQZ/IwBBIGsiAyQAAkACQAJAAkACQAJ/IAAoAhAiAkGDf0cEQEEAIAJBV0cNARogACgCQCIELQBsQQFxRQRAIABBl+AAQQAQEwwDCyAEKAJkRQRAIABB6jtBABATDAMLQX8hBSAAEA8NBQJAAkACQAJAIAAoAhAiBEEpaw4EAgEBAgALIARB3QBGIARBOmtBAklyIARB/QBGcg0BCyAAKAIwDQBBACECIARBKkYEQCAAEA8NCEEBIQILIAAgARCtAUUNAQwHCyAAQQYQDUEAIQILIAAoAkAtAGwhASACBEAgABAtIQUgABAtIQIgAEGAAUH/ACABQQNGGxANIABBDhANIABBBhANIABBBhANIAAgBRAaIABBhgEQDSABQQNHIgdFBEAgAEGMARANCyAAQYMBEA0gAEHCABANIABB6gAQFyAAQesAQX8QGCEGIAAgAhAaQYoBIQQgACAHBH9BigEFIABBwQAQDSAAQcEAEBdBiwELEA0gAEEREA0gAEHrAEF/EBghBCAA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AqcQvAJFIQQMBgsgAacgAqdGIAVBeEZxIQQMBQsgBUF/Rw0EIAGnIAKnRiEEDAQLIAGntyEIIAVBB0cEQCAFDQQgAqe3DAILIAJCgICAgMCBgPz/AHy/DAELIAFCgICAgMCBgPz/AHy/IQggBQRAIAVBB0cNAyACQoCAgIDAgYD8/wB8vwwBCyACp7cLIQkCQCADBEACQAJAIAi9IgFC////////////AIMiAkKBgICAgICA+P8AWgRAIAm9Qv///////////wCDQoGAgICAgID4/wBUIQQMAQsgCb0iCkL///////////8Ag0KBgICAgICA+P8AVA0BCyAEIAJCgICAgICAgPj/AFZzIQQMBQsgA0ECRw0BCyAIIAlhIQQMAwsgASAKUSEEDAILIAVBdkcNACAAIAdBHGoiBiABEK0CIgMgACAHQQhqIAIQrQIiBRC9AiEEIAMgBkYEQCAGEBkLIAUgB0EIaiIDRw0AIAMQGQsgACABEAwgACACEAwLIAdBMGokACAECy8BAX8jAEHQAGsiAyQAIAMgACADQRBqIAEQgQE2AgAgACACIAMQEiADQdAAaiQACw0AIAAgASABED0QnQMLHQEBfyAAIAFB/wFxEA4gACgCBCEDIAAgAhAbIAMLEgAgACABIAIgAyAEQZQDELEDC1IBAX8gACgCDCIDRQRAQQAPCyAAIAAoAghB/////wNBgYCAgHwgASABQYGAgIB8TBsiASABQf////8DThtqNgIIIABB/////wMgAiADQQAQ3AILHwEBfyAAKAIMIgNFBEBBAA8LIAAgASACIANBABDcAgsgACABQgA3AgwgAUKAgICAgICAgIB/NwIEIAEgADYCAAtmAQF/An9BACAAKAIIIgIgAU8NABpBfyAAKAIMDQAaIAAoAhQgACgCACACQQNsQQF2IgIgASABIAJJGyIBIAAoAhARAQAiAkUEQCAAQQE2AgxBfw8LIAAgATYCCCAAIAI2AgBBAAsLZwECfwJAIAFCgICAgHBUDQAgAaciAy8BBkEEayIEQR1LQQEgBHRBz4CAgAJxRXINACAAIAMpAyAQDCADIAI3AyAPCyAAIAIQDCABQoCAgIBwg0KAgICA4ABSBEAgAEHu0gBBABASCwshAQF/IAAgASAAIAIQtgEiAiADIAQQFSEFIAAgAhAQIAULRwIBfgF/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PEdxRQRAIAAgBigCNBCeAQsgACAEEBoLIAAgBigCMCAGKAIsIAYoAjQgBigCPEEBIAwQwQELIAAoAhBB3QBGDQAgB0Glf0YEQEGQ0wAhCAwECyAAQSwQKEUNAQwFCwsgAEGFARANIAAoAkAiASABKAKwAigCADYCsAIgABAPDQMLAkAgBUUNACAAKAIQQT1HDQBBfyEHIABB7ABBfxAYIQEgABAPDQQgACAKEBogAwRAIABBDhANCyAAEFMNBCAAQewAIAsQGBogACABEBpBASEHDAQLIANFBEAgAEHDPUEAEBMMAwsgACgCQCgCgAIgDWpBswEgDiANaxAsGiAAKAJAKAKkAiAKQRRsaiIAIAAoAgBBAWs2AgBBACEHDAMLIAAgCEEAEBMMAQsgACgCACAGKAI0EBALQX8hBwsgBkFAayQAIAcLKwAgACgCQCgCpAFBAE4EQCAAQQYQDSAAQdkAEA0gACAAKAJALwGkARAUCwsTACAAIAEgAiADIARBAEEAEN0BC6YBAQF/IwBBEGsiAyQAIAMgAjcDCAJAIAAgAUGHASABQQAQESICQoCAgIBwg0KAgICA4ABRDQAgACACEDUEQCAAIAIgAUEBIANBCGoQNiICQv////9vViACQoCAgICwf4NCgICAgCBRcg0BIAAgAhAMIABBpcEAQQAQEkKAgICA4AAhAgwBCyAAIAIQDCAAIAEgACADQQhqEIoFIQILIANBEGokACACC6MBAgN/AX4gAEEQaiECIAEoAgAiBEEBaiEDAkAgACkCBCIFQoCAgIAIg1BFBEAgAiAEQQF0ai8BACIAQYD4A3FBgLADRyADIAWnQf////8HcU5yDQEgAiADQQF0ai8BACICQYD4A3FBgLgDRw0BIABBCnRBgPg/cSACQf8HcXJBgIAEaiEAIARBAmohAwwBCyACIARqLQAAIQALIAEgAzYCACAACxIAIAFB2AFOBEAgACABEIYFCwthACAAIAEgAkKAgICACHxC/////w9YBH4gAkL/////D4MFQoCAgIDAfiACub0iAkKAgICAwIGA/P8AfSACQv///////////wCDQoCAgICAgID4/wBWGwsgAyAEQQdyEJQBCzkAIABB/wBNBEAgAEEDdkH8////AXFBsP8BaigCACAAdkEBcQ8LIABBfnFBjMAARiAAEJYGQQBHcgs1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QfD//wFxayIYJAAgBSEVIAYEQCAHIAQgByAIGyIIQQAgCEEAShsiCGsiCUEAIAcgCU8bIREDQAJAIAggCkYEQANAIAggEUYNAiAYIAhBA3RqQoCAgIAwNwMAIAhBAWohCAwACwALIAUgCkEDdCIJaikDACIBQiCIp0F1TwRAIAGnIhUgFSgCAEEBajYCAAsgCSAYaiABNwMAIBFBAWohESAKQQFqIQoMAQsLIA4gBzYCVCAYIRULIA4gFTYCQCAOIBggBkEDdGoiETYCREEAIQgDQCAIIBdHBEAgESAIQQN0akKAgICAMDcDACAIQQFqIQgMAQsLIBIoAhQhBiAOIBYoAowBNgIwIBYgDkEwaiIUNgKMASASKAIwIQkgESAXQQN0aiIIIRcLQQAMAQtBAQshBwNAAkACQAJAAkAgB0UEQCAEQQN0ISMgA0KAgICAcIMhOyARQQhqIRogEUEQaiEbIBFBGGohHCAVQQhqIR0gFUEQaiEeIBVBGGohHyAUQRhqISQgAkIgiKciIEF+cSElIANCIIinISYgBK0hOiADpyEhIA5BMGohJyAOQegAaiEiIAghBwJAA0ACQCAGQQFqIQxCgICAgDAhNQJ/AkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJ/AkACQAJAAkACQAJAAkACQAJAAkACQAJA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AAsgCCABNwMQIAhBGGohBwzeAQsgCCAIQQhrIgYpAwA3AwAgCEEQaykDACIBQiCIp0F1TwRAIAGnIgcgBygCAEEBajYCAAsgBiABNwMAIAhBCGohBwzdAQsgCCAIQQhrIgYpAwAiATcDACAGIAhBEGsiBikDADcDACABQiCIp0F1TwRAIAGnIgcgBygCAEEBajYCAAsgBiABNwMAIAhBCGohBwzcAQsgCCAIQQhrIgYpAwAiATcDACAIQRBrIgcpAwAhNSAHIAhBGGsiBykDADcDACAGIDU3AwAgAUIgiKdBdU8EQCABpyIGIAYoAgBBAWo2AgALIAcgATcDACAIQQhqIQcM2wELIAggCEEIayIGKQMAIgE3AwAgCEEQayIHKQMAITUgByAIQRhrIgcpAwA3AwAgBiA1NwMAIAcgCEEgayIGKQMANwMAIAFCIIinQXVPBEAgAaciByAHKAIAQQFqNgIACyAGIAE3AwAgCEEIaiEHDNoBCyAIQRBrIgYpAwAhASAGIAhBGGsiBikDADcDACAGIAE3AwAM0wELIAhBGGsiBikDACEBIAYgCEEQayIGKQMANwMAIAhBCGsiBykDACE1IAcgATcDACAGIDU3AwAM0gELIAhBIGsiBikDACEBIAYgCEEYayIGKQMANwMAIAhBEGsiBykDACE1IAcgCEEIayIHKQMANwMAIAYgNTcDACAHIAE3AwAM0QELIAhBKGsiBikDACEBIAYgCEEgayIGKQMANwMAIAhBGGsiBykDACE1IAcgCEEQayIHKQMANwMAIAYgNTcDACAHIAhBCGsiBikDADcDACAGIAE3AwAM0AELIAhBCGsiBikDACEBIAYgCEEQayIGKQMANwMAIAhBGGsiBykDACE1IAcgATcDACAGIDU3AwAMzwELIAhBEGsiBikDACEBIAYgCEEYayIGKQMANwMAIAhBIGsiBykDACE1IAcgATcDACAGIDU3AwAMzgELIAhBEGsiBikDACEBIAYgCEEYayIGKQMANwMAIAhBIGsiBykDACE1IAcgCEEoayIHKQMANwMAIAYgNTcDACAHIAE3AwAMzQELIAhBCGsiBikDACEBIAYgCEEQayIGKQMANwMAIAYgATcDAAzMAQsgCEEgayIGKQMAIQEgBiAIQRBrIgYpAwA3AwAgCEEIayIHKQMAITUgByAIQRhr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xH4iAUIAUg0EIA0gD3JBAE4NBSALQoCAgIDA/v8DNwMADA0LIAtCgICAgMB+IA+3IA23o70iAUKAgICAwIGA/P8AfSABQv///////////wCDQoCAgICAgID4/wBWGzcDAAwMCyANQQBKIA9BAE5xRQRAIAsCfiAPtyANtxCZBCI8vSIBAn8gPJlEAAAAAAAA4EFjBEAgPKoMAQtBgICAgHgLIgq3vVEEQCAKrQwBC0KAgICAwH4gAUKAgICAwIGA/P8AfSABQv///////////wCDQoCAgICAgID4/wBWGws3AwAMDAsgDyANcK0hAQwCCyAPtyE8IAsCfgJ8IA23Ij29QoCAgICAgID4/wCDQoCAgICAgID4/wBRBEBEAAAAAAAA+H8gPJlEAAAAAAAA8D9hDQEaCyA8ID0QowMLIjy9IgECfyA8mUQAAAAAAADgQWMEQCA8qgwBC0GAgICAeAsiCre9UQRAIAqtDAELQoCAgIDAfiABQoCAgIDAgYD8/wB9IAFC////////////AINCgICAgICAgPj/AFYbCzcDAAwKCyA1xCABxH0hAQsgAUKAgICACHxC/////w9WDQEgASE2CyA2Qv////8PgwwBC0KAgICAwH4gAbm9IgFCgICAgMCBgPz/AH0gAUL///////////8Ag0KAgICAgICA+P8AVhsLNwMADAULIBBBdkcgD0F2R3FFBEAgCSAKIAsgNSABIAkoAhAoAqwCESMADQcMBQsgCSAHQQhqIDUQbQ0FIAkgByABEG0NBgsCQAJAAkACQCAKQZsBaw4GAAECBAUDBAsgBysDCCAHKwMAogwFCyAHKwMIIAcrAwCjDAQLIAcrAwggBysDABCZBAwDCyAHKwMIITwgBysDACI9vUKAgICAgICA+P8Ag0KAgICAgICA+P8AUQRARAAAAAAAAPh/IDyZRAAAAAAAAPA/YQ0DGgsgPCA9EKMDDAILEAEACyAHKwMIIAcrAwChCyE8IAtCgICAgMB+IDy9IgFCgICAgMCBgPz/AH0gAUL///////////8Ag0KAgICAgICA+P8AVhs3AwALQQAMAgsgCSABEAwLIAtCgICAgDA3AwAgDUKAgICAMDcDAEF/CyEwIAdBEGokACAwDUsgCEEIayEHDEcLIAhBBGsoAgAiB0UgB0EHa0FuSXINQCAIIQcgCSAIQY4BEOEBRQ1GDEoLAkACfCAIQQhrIgcpAwAiAUIgiKciCkUEQEQAAAAAAAAAgCABpyIGRQ0BGkQAAAAAAADgQSAGQYCAgIB4Rg0BGiAHQgAgAX1C/////w+DNwMADEILIApBB2tBbUsNASABQoCAgIDA/v8Dfb8LITwgB0KAgICAwH4gPL0iAUKAgICAwIGA/P8AfSABQv///////////wCDQoCAgICAgID4/wBWGzcDAAxACyAIIQcgCSAIQY0BEOEBRQ1FDEkLIAhBCGsiBykDACIBQv////8PViABQv////8HUXJFBEAgByABQgF8Qv////8PgzcDAAw/CyAIIQcgCSAIQZABEOEBRQ1EDEgLIAhBCGsiBykDACIBQv////8PViABQoCAgIAIUXJFBEAgByABQgF9Qv////8PgzcDAAw+CyAIIQcgCSAIQY8BEOEBRQ1DDEcLIAkgCEEIayIHKQMAEGUiAUKAgICAcINCgICAgOAAUQRAIAdCgICAgDA3AwAMRwsgByABNwMAIAFCIIinQXVPBEAgAaciByAHKAIAQQFqNgIACyAIIAE3AwAgCSAIQQhqIgcgCkECaxDhAUUNQgxGCyAGQQJqIQwgESAGLQABQQN0aiIHKQMAIgFC/////w9WIAFC/////wdRckUEQCAHIAFCAXxC/////w+DNwMADDwLIAFCIIinQXVPBEAgAaciCiAKKAIAQQFqNgIACyAOIAE3A2AgCSAiQZABEOEBDUUgCSAHIA4pA2AQHQw7CyAGQQJqIQwgESAGLQABQQN0aiIHKQMAIgFC/////w9WIAFCgICAgAhRckUEQCAHIAFCAX1C/////w+DNwMADDsLIAFCIIinQXVPBEAgAaciCiAKKAIAQQFqNgIACyAOIAE3A2AgCSAiQY8BEOEBDUQgCSAHIA4pA2AQHQw6CyAIQQhrIgcpAwAiAUL/////D1gEQCAHIAFC/////w+FNwMADDoLIAghByMAQRBrIgokAAJ/AkACQCAJIAhBCGsiCykDABBlIgFCgICAgHCDIjVCgICAgOAAUQ0AIDVCgICAgOB+UQRAIAkgC0GWASABIAkoAhAoAqgCER8ADQEMAgsgCSAKQQxqIAEQlQENACALIAo1AgxC/////w+FNwMADAELIAtCgICAgDA3AwBBfwwBC0EACyExIApBEGok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//8AgyIGQoCAgICAgMD//wBWIAZCgICAgICAwP//AFEbDQAgACAChCAFIAaEhFAEQEEADwsgASADg0IAWQRAQX8hBCAAIAJUIAEgA1MgASADURsNASAAIAKFIAEgA4WEQgBSDwtBfyEEIAAgAlYgASADVSABIANRGw0AIAAgAoUgASADhYRCAFIhBAsgBAuhAgEFfwNAAkACQAJAAkACfyACIAdMIgkgBCAGTHJFBEAgASAHQQJ0aigCACIIIAMgBkECdGooAgAiCUkEQCAIDAILIAggCUcNAyAGQQFqIQYgB0EBaiEHIAghCQwECyAJDQEgASAHQQJ0aigCAAshCSAHQQFqIQcMAgsgBCAGTA0CIAMgBkECdGooAgAhCQsgBkEBaiEGCwJ/AkACQAJAAkAgBQ4DAwABAgsgBiAHcUEBcQwDCyAGIAdzQQFxDAILEAEACyAGIAdyQQFxCyAAKAIAIghBAXFGDQEgACgCBCAITARAIAAgCEEBahDRAgRAQX8PCyAAKAIAIQgLIAAgCEEBajYCACAAKAIIIAhBAnRqIAk2AgAMAQsLIAAQmAZBAAvmAQAgAAJ/IAEoAggiAEH+////B04EQEEAIAJBAXENARpB/////wcgAEH+////B0cNARogASgCBEH/////B2oMAQtBACAAQQBMDQAaIABBH00EQEEAIAEoAhAgASgCDEECdGpBBGsoAgBBICAAa3YiAGsgACABKAIEGwwBCyACQQFxRQRAQf////8HIAEoAgRFDQEaQYCAgIB4IABBIEcNARogASgCECABKAIMQQJ0akEEaygCABpBgICAgHgMAQtBACABKAIQIAEoAgwiAiACQQV0IABrEHEiAGsgACABKAIEGws2AgALEgAgACABIAIgAyAEQZMDELEDCw4AIABBACABQRByELoBC58BAgR/An4gAzUCACEJA0AgAiAFRkUEQCAAIAVBAnQiB2ogBq0gASAHajUCACAJfnwiCj4CACAFQQFqIQUgCkIgiKchBgwBCwsgACACQQJ0IgdqIAY2AgBBASAEIARBAU0bIQRBASEFA0AgBCAFRkUEQCAAIAVBAnQiBmoiCCAHaiAIIAEgAiADIAZqKAIAEL0ENgIAIAVBAWohBQwBCwsLWgEFfyADQQAgA0EAShshBgNAIAUgBkcEQCAAIAVBAnQiA2ogASAD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gICAgOAAUg0AIAEhAgwBCwJAIAKnIgUpAgQiCkL/////B4NQDQAgAaciAykCBCELAkAgAygCAEEBRyAKIAuFQoCAgIAIg0IAUnINACADIAAoAhAoAgwRBQAgBSkCBCIKpyIEQf////8HcSIHIAMpAgQiC6ciBkH/////B3EiCGogBEEfdnQgBkEfdiIJQRFzakkNACAFQRBqIQYgA0EQaiEEIAkEQCAEIAhBAXRqIAYgB0EBdBAeGiADIAMpAgQiCiAFKQIEfEL/////B4MgCkKAgICAeIOENwIEDAILIAQgCGogBiAHEB4aIAMgAykCBCIKIAUpAgR8Qv////8HgyILIApCgICAgHiDhDcCBCAEIAunakEAOgAADAELAn4CQAJAIAunQf////8HcSAKp0H/////B3FqIgdBgICAgARPBEAgAEHkyABBABA6DAELIAAgByAKIAuEpyIGQR92EOkBIggNAQtCgICAgOAADAELIAhBEGohBAJAIAZBAE4EQCAEIANBEGogAygCBEH/////B3EQHiIEIAMoAgRB/////wdxaiAFQRBqIAUoAgRB/////wdxEB4aIAQgB2pBADoAAAwBCyAEIAMgAygCBEH/////B3EQkwUgBCADKAIEQQF0aiAFIAUoAgRB/////wdxEJMFCyAIrUKAgICAkH+ECyEKIAAgARAMDAELIAEhCgsgACACEAwgCgsPACAAIAFCgICAgDAQggILCwAgAEGfCUEAEBILjgIBA38jAEEQayIFJAAgBSAAOQMIIAUgAUEBayIHNgIAIAZBgAFB9t8AIAUQSBogAyAGLQAAQS1GNgIAIAQgBi0AAToAACABQQJOBEAgBEEBaiAGQQNqIAcQHhoLIAEgBGpBADoAACACIQkgASAGaiABQQFKakECaiEBA0AgASICQQFqIQEgAiwAACIDEI8GDQALQQEhBAJAAkACQCADQf8BcUEraw4DAQIAAgtBACEECyABLAAAIQMgASECC0EAIQEgA0EwayIDQQlNBEADQCABQQpsIANrIQEgAiwAASEIIAJBAWohAiAIQTBrIgNBCkkNAAsLIAlBACABayABIAQbQQFqNgIAIAVBEGokAAuADAIHfwV+IwBBoANrIgUkAAJAIAG9IgxCgICAgICAgPj/AINCgICAgICAgPj/AFEEQCAMQv//////////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QCAHqwwBC0EACyIDNgIcIAcgA7hhDQMMAQsgAwRAQX8hAyAAIAIQlgEiAkKAgICAcINCgICAgOAAUQ0EIAAgBEEcaiACQQEQvgJFDQMMBAsgACAEQRxqIAIQdQRAIAAgAhAMDAILQX8hAyAAIAIQlgEiAkKAgICAcINCgICAgOAAUQ0DIAAgBEEEaiACQQAQvgINAyAEKAIEIAQoAhxGDQILIABBiscAQQAQRAtBfyEDDAELIAEgBCgCHDYCAEEAIQMLIARBIGokACADC0ABAX4gABDiASICQoCAgIBwg0KAgICA4ABSBEAgAqdBBGogARCcAkUEQCACDwsgACACEAwgABBwC0KAgICA4AALMgEBfyMAQdAAayICJAAgAiAAIAJBEGogARCBATYCACAAQbzpACACEMMCIAJB0ABqJAALoAECAX8BfiMAQRBrIgUkACAFIAQ2AgxBfyEEIAAgASAFQQxqENMBRQRAIAMoAgAiAEF8cSABIAIgAygCBCAAQQNxQQJ0QYS3AWooAgARGwAhBiADEOAFIAUoAgwiACAAKAIAQf////8DcTYCACADQoCAgIAwIAYgBkKAgICAcINCgICAgOAAUSIAGzcDAEF/QQAgABshBAsgBUEQaiQAIAQLFQECfiAAIAEQ6AEhAyAAIAEQDCADCw0AIAAgASACQQIQyAIL1QEBA38jAEEQayIFJABBfyEDAkAgACgCFA0AAkACQCABQYCAgIAETgRAIAAoAgBB5MgAQQAQOgwBCyABIAAoAgxBA2xBAm0iBCABIARKGyEBIAAoAhAiBCACQYACSHJFBEAgACABEOADIQMMAwsgACgCACAAKAIEIAEgBHQgBGtBEWogBUEMahCnASICDQELIAAQ9wIMAQsgBSgCDCEDIAAgAjYCBCAAQf////8DIAMgACgCEHYgAWoiACAAQf////8DThs2AgxBACEDCyAFQRBqJAAgAwsqAQF/IAAoAhAiA0EQaiABIAIgAygCCBEBACIBIAJFckUEQCAAEHALIAELgQECAn8BfgJAIAEpAgQiBEL//////////79/VgRAIAEoAgwhAAwBCyAAKAI0IARCIIinIAAoAiRBAWtxQQJ0aiECIAAoAjghAwNAIAMgAigCACIAQQJ0aigCACICIAFGDQEgAkEMaiECIAANAAtBxocBQajsAEH/FEH4DhAAAAsgAAupBwIJfwF+AkACQAJAAn8gAkECTARAIAIgASkCBCIMQj6Ip0YEQCAAIAEQxgIiBEHXAUoNBSABIAEoAgBBAWs2AgAgBA8LIAAoAjQgACgCJEEBayABIAIQ6wVB/////wNxIgdxIgpBAnRqIQMgDKdB/////wdxIQUDQCACIAMoAgAiBEUNAhoCQCAAKAI4IARBAnRqKAIAIgMpAgQiDKdB/////wdxIAVHIAxCPoinIAJHciAMQiCIp0H/////A3EgB0dyDQAgAyABIAUQ6gUNACAEQdgBSA0EIAMgAygCAEEBajYCAAwECyADQQxqIQMMAAsACyACQQNHIQdBAwshBQJAIAAoAjwNAEEAIQQgAEEQaiILIAAoAjhB0wEgACgCLEEDbEECbSICIAJB0wFMGyICQQJ0IAAoAggRAQAiCEUNASAAKAIsIgkhAyAJRQRAIAtBECAAKAIAEQMAIgZFBEAgCyAIIAAoAgQRAAAMAwsgBkKAgICAgICAgEA3AgQgBkEBNgIAIAZBADYADCAIIAY2AgAgACAAKAIoQQFqNgIoQQEhAwsgACADNgI8IAAgCDYCOCAAIAI2AiwgCSACIAIgCUkbIQQgAkEBayEGA0AgAyAERg0BIAAoAjggA0ECdGpBASADQQFqIgJBAXRBAXIgAyAGRhs2AgAgAiEDDAALAAsCQCABBEAgASkCBCIMQv//////////P1gEQCABIAwgBa1CPoaENwIEDAILIABBEGogDKciAkEfdSACQf////8HcSACQR92dGpBEWogACgCABEDACICRQRAQQAhBAwECyACQQE2AgAgAiACKQIEQv////93gyABKQIEQoCAgIAIg4QiDDcCBCACIAxCgICAgHiDIAEpAgRC/////weDhDcCBCACQRBqIAFBEGogASgCBCIDQf////8HcSADQR92dCADQX9zQR92ahAeGiAAIAEQkAQgAiEBDAELIABBEGpBECAAKAIAEQMAIgFFBEBBAA8LIAFCgYCAgICAgICAfzcCAAsgACAAKAI4IAAoAjwiBEECdGoiAigCAEEBdjYCPCACIAE2AgAgASAENgIMIAEgATUCBCAHrUIghoQgBa1CPoaENwIEIAAgACgCKEEBajYCKCAFQQNGDQIgASAAKAI0IApBAnRqIgEoAgA2AgwgASAENgIAIAAo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QQAQEgwBCwJAIARFIAJBAExyRQRAIAAgBSAHQgAgAUF/EPMCDQIMAQsgASEICyACQQAgAkEAShutIQlCACEBA0AgASAJUgRAIAMgAadBA3RqKQMAIgdCIIinQXVPBEAgB6ciAiACKAIAQQFqNgIACyABIAh8IQogAUIBfCEBIAAgBSAKIAcQe0EATg0BDAILCyAAIAVBMCAGQoCAgIAIfCIIQv////8PWAR+IAZC/////w+DBUKAgICAwH4gBrm9IgFCgICAgMCBgPz/AH0gAUL///////////8Ag0KAgICAgICA+P8AVhsLEDlBAEgNACAAIAUQDCAGQv////8PgyAIQv////8PWA0BGkKAgICAwH4gBrm9IgFCgICAgMCBgPz/AH0gAUL///////////8Ag0KAgICAgICA+P8AVhsMAQsgACAFEAxCgICAgOAACyELIAxBEGokACALCxUBAn4gACABEIcFIQMgACABEAwgAwv5DgIKfgR/IwBBEGsiECQAIBAgAjcDCAJAAkACfgJAAkACQAJAAkACQAJAAkACQAJAQQcgAkIgiKciDiAOQQdrQW5JGyIOQQdqDg8EAwMDAwMABQUFAwMDAwECCwJAAkACQAJAIAKnIg4vAQYiD0EEaw4DAQACAwtCgICAgDAhByAAIAIQNCICQoCAgIBwg0KAgICA4ABRDQsgACACEO4DIgJCgICAgHCDQoCAgIDgAFENCyABKAIoIAIQhAEhDgwOC0KAgICAMCEHIAAgAhCWASICQoCAgIBwg0KAgICA4ABRDQogASgCKCACEIQBIQ4MDQsgASgCKCAOKQMgEI0BIQ4gACACEAwMDAsgD0EhRg0HQoCAgIAwIQYgACABKQMIQQEgEEEIahDxAyIEQoCAgIDwAINCgICAgOAAUQ0GIAAgBBAnBEAgAEHJ3wBBABASDAcLIANCIIinQXVPBEAgA6ciDiAOKAIAQQFqNgIACyABKQMYIgRCIIinQXVPBEAgBKciDiAOKAIAQQFqNgIACwJAAkACQAJAIAAgAyAEELYCIghCgICAgHCDQoCAgIDgAFEEQEKAgICAMCEHDAELIAEpAxgiBEKAgICAcINCgICAgJB/UQRAIASnKAIEQf////8HcUUNAwsgCEIgiKdBdU8EQCAIpyIOIA4oAgBBAWo2AgALIABB65YBIAhB7JYB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BEAgAiAANgIAC0EBC4cDAgN+BH8CQCABKAIIIgZB/v///wdOBEBBASEHIAJBAXENAUL///////////8AIQMgBkH+////B0cNASABNAIEQv///////////wB8IQMMAQsgBkEATARADAELIAZBP00EQCABKAIQIAEoAgwiCEECdGoiCUEEaygCACECQgAgBkEgTQR+IAJBICAGa3atBSAIQQJPBH4gCUEIazUCAAVCAAsgAq1CIIaEQcAAIAZrrYgLIgN9IAMgASgCBBshAwwBCyACQQFxRQRAIAEoAgRFBEBC////////////ACEDQQEhBwwCC0KAgICAgICAgIB/IQNBASEHIAZBwABHDQEgASgCECABKAIMIgFBAnRqIgJBBGs1AgBCIIYhBCABQQJPBH4gAkEIazUCAAVCAAsgBIRCgICAgICAgICAf1IhBwwBC0IAIAEoAhAiCCABKAIMIgIgAkEFdCAGayIGEHGtIAggAiAGQSBqEHGtQiCGhCIDfSADIAEoAgQbIQMLIAAgAzcDACAHC60CAgJ/An4jAEEgayICJAACQCAAKAIIQf////8HRgRAQoCAgICAgID8/wAhBAwBCyAAKAIAIQMgAkIANwIYIAJCgICAgICAgICAfzcCECACIAM2AgwgAkEMaiIDIAAQSRoCfiACKAIUIgBB/f///wdMBEAgA0E1QcgEELoBGiACKAIUIQALQoCAgICAgID4/wAgAEH+////B0YNABpCACAAQYCAgIB4Rg0AGiACKAIcIQMCfiACKAIYQQJGBEAgAykCAAwBCyADNQIAQiCGCyEEIABBgnhMBEAgBEGOeCAAa62IIQRCAAwBCyAEQguIQv////////8HgyEEIABB/gdqrUI0hgshBSAEIAWEIAI1AhBCP4aEIQQgAkEMahAZCyABIAQ3AwAgAkEgaiQACw0AIAAgASACQQIQsAMLIwACQAJAAkAgAg4CAAECCyAAIAFyDwsgACABcw8LIAAgAXEL4QgBEX8gAigCBCAFcyIFIAEoAgQiBnMhDQJAIAEgAhDyASIIIA1Fcg0AIAEoAghB/f///wdKDQAgACAEQQdxQQJGEIABQQAPCyAFIAYgCEEASCIGGyEFIAEgAiAGGyEKAkACQAJAIAIgASAGGyIIKAIMIgcEQCAKKAIMIgsNAQsgCCgCCCIBQf7///8H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CyAAIAsQDCAAIAgQDCAAIAoQDCAAIAEQDAwBCyABIQ0LIAVBIGokACANC0sBAn8gACABRwRAIAAoAhAiAgRAIAAoAgAiAygCACACQQAgAygCBBEBABoLIAAgASkCADcCACAAIAEoAhA2AhAgACABKQIINwIICwv0AQIDfgF/AkAgAykDACIEQoCAgIBwWgRAIAMpAwgiBUL/////b1YNAQsgABAiQoCAgIDgAA8LQoCAgIDgACEGIABCgICAgCBBLBBHIgFCgICAgHCDQoCAgIDgAFIEfiAAQRgQJCICRQRAIAAgARAMQoCAgIDgAA8LIASnIgMgAygCAEEBajYCACACIAQ3AwAgBaciByAHKAIAQQFqNgIAIAIgBTcDCCAAIAQQNSEAIAJBADoAESACIAA6ABAgAUKAgICAcFoEQCABpyIAIAI2AiAgACAALQAFQe8BcSADLQAFQRBxcjoABQsgAQVCgICAgOAACwsbACAAEBkgAEIANwIQIABCADcCCCAAQgA3AgALCQAgASACEPgFCxMAIABBEGogASACIAAoAggRAQALqAECAX8CfiAAvSIEQv///////////wCDQoGAgICAgID4/wBaBEAgAb1C////////////AINCgYCAgICAgPj/AFQPC0F/IQICQCAAIAFjDQAgAb0iA0L///////////8Ag0KAgICAgICA+P8AVg0AQQEhAiAAIAFkDQBBACECIABEAAAAAAAAAABiDQAgBEIAUwRAIANCP4enQX9zDwsgA0I/iKchAgsgAgvKBQIFfwN+IwBBMGsiAiQAIAIgATcDECACQQA2AgwgAiAANgIIIAIgAykDACIKNwMYAkACQCAKQoCAgIBwgyILQoCAgIAwUgRAQoCAgIDgACEJIAAgChBVDQELQoCAgIDgACEJIAAgARCKASIFQQBIDQACQCAFQQJJDQAgAaciAy8BBkEVayIEQf//A3FBC08NAiACIARBAnRB/P8PcSIEQZz1AWooAgA2AiBBASADLwEGQcqeAWotAAAiBnQhCCADKAIkIQcgC0KAgICAMFIEQCAAIAVBAnQQJCIERQ0CQQAhAwNAIAMgBUZFBEAgBCADQQJ0aiADNgIAIANBAWohAwwBCwsgAiAINgIoIAIgBzYCJCAEIAVBBEHLACACQQhqENcBAkACQAJAAkAgAigCDA4CAAEDCyAAIAUgBnQiAxAkIgYNAQsgACgCECIAQRBqIAQgACgCBBEAAAwECyAGIAcgAxAeIQZBACEDAkACQAJAAkACQCAIQQFrDggAAQkCCQkJAwkLA0AgAyAFRg0EIAMgB2ogBiAEIANBAnRqKAIAai0AADoAACADQQFqIQMMAAsACwNAIAMgBUYNAyAHIANBAXRqIAYgBCADQQJ0aigCAEEBdGovAQA7AQAgA0EBaiEDDAALAAsDQCADIAVGDQIgByADQQJ0IghqIAYgBCAIaigCAEECdGooAgA2AgAgA0EBaiEDDAALAAsDQCADIAVGDQEgByADQQN0aiAGIAQgA0ECdGooAgBBA3RqKQMANwMAIANBAWohAwwACwALIAAoAhAiA0EQaiAGIAMoAgQRAAALIAAoAhAiAEEQaiAEIAAoAgQRAAAMAQsgByAFIAggBEHI9QFqKAIAIAJBCGoQ1wEgAigCDA0BCyABQiCIp0F1TwRAIAGnIgAgACgCAEEBajYCAAsgASEJCyACQTBqJAAgCQ8LEAEAC+cCAQF+IAAgARCKASICQQBIBEBCgICAgOAADwsCQCACRQ0AAkACQAJAAkACQCABpyIALwEGQcqeAWotAAAOBAABAgMECyAAKAIkIgAgAmohAgNAIAAgAkEBayICTw0FIAAtAAAhAyAAIAItAAA6AAAgAiADOgAAIABBAWohAAwACwALIAAoAiQiACACQQF0aiECA0AgACACQQJrIgJPDQQgAC8BACEDIAAgAi8BADsBACACIAM7AQAgAEECaiEADAALAAsgACgCJCIAIAJBAnRqIQIDQCAAIAJBBGsiAk8NAyAAKAIAIQMgACACKAIANgIAIAIgAzYCACAAQQRqIQAMAAsACyAAKAIkIgAgAkEDdGohAgNAIAAgAkEIayICTw0CIAApAwAhBCAAIAIpAwA3AwAgAiAENwMAIABBCGohAAwACwALEAEACyABQiCIp0F1TwRAIAGnIgAgACgCAEEBajYCAAsgAQtRAgF/AX5CgICAgOAAIQQgACABIAIQayIDBH4gAygCICIDKAIMKAIgLQAEBEAgAkUEQEIADwsgABBfQoCAgIDgAA8LIAM1AhAFQoCAgIDgAAsLNwAgACABIAIQayIARQRAQoCAgIDgAA8LIAAoAiAoAgwiACAAKAIAQQFqNgIAIACtQoCAgIBwhAsMACAAKAIQIAEQ5wML2gEBAn4CQAJAIAJFBEAgAUKAgICAcIMhBSAAQS8QKSEEDAELAn4gAUKAgICAcIMiBUKAgICAMFIgAykDACIEQoCAgIBwg0KAgICAgH9SckUEQCAAQbmMASAAIAAoAhAgBKcQxgIQKUGrjAEQsgEMAQsgACAEECULIgRCgICAgHCDQoCAgIDgAFENAQsgBUKAgICAMFENACAAIAFBBRBeIgFCgICAgHCDQoCAgIDgAFIEQCAAIAEgBBC9ASAAIAFBMCAEpykCBEL/////B4NBABAVGgsgASEECyAEC0YBAX8CQCAAKAIIIAJqIgMgACgCDEoEQCAAIAMgARDEAg0BCwNAIAJBAEwEQEEADwsgAkEBayECIAAgARCHAUUNAAsLQX8LlQECBX8BfiABKQIEIginQf////8HcSIDRQRAIAIPCyAAKAIEQf////8HcSEHAn8gCEKAgICACINQRQRAIAEvARAMAQsgAS0AEAshBSADQQFrIQYgByADayEEAkADQCACIARKDQEgACAFIAIQoAEiA0EASCADIARKcg0BIAAgASADQQFqIgJBASAGELwDDQALIAMPC0F/C6cBAgN/AX4CQAJAIAAgARD2AyIDQQBIDQAgA0UNAUGbHiECIAAgACABQe4AIAFBABARIgVCgICAgHCDIgFCgICAgCBRIAFCgICAgDBRcgR/QZseBSABQoCAgIDgAFENASAAIAUQNCIBQoCAgIBwg0KAgICA4ABRDQFBACECIAGnQecAQQAQoAEhBCAAIAEQDCAEQQBODQJB2ssAC0EAEBILQX8hAgsgAguhAQIDfwF+AkACQCAAKQIEIgRCgICAgAiDUA0AIABBEGohAiAEp0H/////B3EhA0EAIQADQCAAIANODQECQCACIABBAXRqLwEAIgFBgPADcUGAsANHBEAgACEBDAELIAFB/7cDSw0DIABBAWoiASADTg0DIAIgAUEBdGovAQBBgEBrQf//A3FBgPgDSQ0DCyABQQFqIQAMAAsAC0F/IQALIAALVQEBfwJAAkACQCABQiCIp0EBag4DAAECAQsgAaciAi8BBkEGRw0AIAIpAyAiAUKAgICAcINCgICAgBBRDQELIABBlMAAQQAQEkKAgICA4AAhAQsgAQsQAEHOkQEgAEELEJICQQBHC4kB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ADcCECAAQRBqIAIgACgCBBEAAAwBCyACQoCAgIAwNwMoIAJCgICAgDA3AyAgAkEBNgIECyABIAEoAgxBAWs2AgwLC4YBACAAIAEgBEEiahBaIgJFBEBCgICAgOAADwsgACACIAMpAwAiAUIAIAFCIIinQQdrQW5PGyABIAFCgICAgMCBgPz/AHxC////////////AINQGxDyAiIARQRAQoCAgIAwDwsgACkDKCIBQiCIp0F1TwRAIAGnIgAgACgCAEEBajYCAAsgAQu7BQIDfgd/IwBBEGsiCyQAQoCAgIDgACEHAkAgACABIARBImoQWiICRQ0AIAIoAgBFIAMpAwAiBUIAIAVCIIinQQdrQW5PGyAFIAVCgICAgMCBgPz/AHxC////////////AINQGyIFQv////9vVnJFBEAgABAiDAELQoCAgIAwIQYgBEEBcUUEQCADKQMIIQYLAkAgACACIAUQ8gIiAwRAIAAgAykDKBAMDAELIABBMBAkIgNFDQEgAyACNgIIIANCATcDAAJAIAIoAgAEQCADIAWnIgQoAhg2AgwgBCADNgIYDAELIAVCIIinQXVJDQAgBaciBCAEKAIAQQFqNgIACyADIAU3AyAgAigCECIJIAIoAhQiBEEBayAFENkDcUEDdGoiCCgCACIKIANBGGoiDDYCBCADIAg2AhwgAyAKNgIYIAggDDYCACACKAIEIgggA0EQaiIKNgIEIAMgAkEEaiIMNgIUIAMgCDYCECACIAo2AgQgAiACKAIMQQFqIgg2AgwgCCACKAIYSQ0AIAAgCUEEIARBAXQgBEEBRhsiAEEDdCALQQxqEKcBIghFDQAgCygCDEEDdiAAaiEEQQAhAANAIAAgBEZFBEAgCCAAQQN0aiIJIAk2AgQgCSAJNgIAIABBAWohAAwBCwsgBEEBayEKIAJBCGohAANAIAwgACgCACIARwRAIABBDGsoAgBFBEAgCCAAKQMQENkDIApxQQN0aiIJKAIAIg0gAEEIaiIONgIEIAAgCTYCDCAAIA02AgggCSAONgIACyAAQQRqIQAMAQsLIAIgBDYCFCACIAg2AhAgAiAEQQF0NgIYCyAGQiCIp0F1TwRAIAanIgAgACgCAEEBajYCAAsgAyAGNwMoIAFCIIinQXVPBEAgAaciACAAKAIAQQFqNgIACyABIQcLIAtBEGok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AmoQI0UNDAJAIAMoAqgGIgVBAEgEQCADKALYBiEFDAELIAMgBTYC2AYLIAEgAygCxAYgBRAuIANBwAZqQfIBEA4gAygCrAZBAXMhBQwSCyADQX82AogDIANCw/aAgOABNwOAAyADQZwGaiAEIANBgANqECNFDQsCQCADKAKoBiICQQBIBEAgAygC2AYhAgwBCyADIAI2AtgGCyABIAMoAsQGIAIQLiADQcAGaiICIAMtAKwGEA4gAiADKAK8BhAbDBALIANBfzYCuAMgA0LZuP2CcDcDsAMgA0GcBmogBCADQbADahAjRQ0KIAMoAqgGIgJBAE4EQCADIAI2AtgGCyADQo6AgIBwNwOgAyADKAKsBiIFQQFqIQYCQCADQZwGaiADKAKkBiICIANBoANqECMEfyADKAKoBiICQQBOBEAgAyACNgLYBgsgAyADKAKwBjYClANBfyEEIANBfzYCmAMgAyAFQQFrNgKQAyADQZwGaiADKAKkBiICIANBkANqECNFDQEgAygCpAYhAiADKAKoBgVBfwshBCAGIQULIAEgAygCxAYgAygC2AYQLiADQcAGaiAFIAMoArAGEFkgBEEASA0TIAMgBDYC2AYMEwsgBi8AASICQf8BSw0JIANCjoCAgHA3AswEIAMgAjYCyAQgA0KRpYKAkAs3A8AEAkAgA0GcBmoiBiAEIANBwARqECNFBEAgA0KOgICAcDcDsAQgAyACNgKsBCADQdkANgKoBCADQo+hgoCQAjcDoAQgBiAEIANBoARqECNFDQELAkAgAygCqAYiBUEASARAIAMoAtgGIQUMAQsgAyAFNgLYBgsgASADKALEBiAFEC4gA0HABmoiBEGUAUGTASADKAKsBkF9cUGQAUYbEA4gBCACQf8BcRAODA8LIANCjoCAgHA3ApQEIAMgAjYCkAQgA0KRgICAkAs3A4gEIANChICAgOATNwOABCADQZwGaiAEIANBgARqECMEQAJAIAMoAqgGIgVBAEgEQCADKALYBiEFDAELIAMgBTYC2AYLIAEgAygCxAYgBRAuAkAgAygCvAZBL0YEQCADQcAGakHBARAODAELIANBwAZqIgRBBBAOIAQgAygCvAYQGwsgA0HABmoiBEGVARAOIAQgAkH/AXEQDgwPCyADQo6AgIBwNwL0AyADIAI2AvADIANCkYCAgJALNwPoAyADQoGAgIDgEzcD4AMgA0GcBmogBCADQeADahAjBEACQCADKAKoBiIFQQBIBEAgAygC2AYhBQwBCyADIAU2AtgGCyABIAMoAsQGIAUQLiADQcAGaiIEIAMoArQGEM4DIARBlQEQDiAEIAJB/wFxEA4MDwsgA0KOgICAcDcD2AMgAyACNgLUAyADQdkANgLQAyADQp6BgICQAjcDyAMgA0LYtvmCcDcDwAMgA0GcBmogBCADQcADahAjBEACQCADKAKoBiIFQQBIBEAgAygC2AYhBQwBCyADIAU2AtgGCyABIAMoAsQGIAUQLiADQcAGaiIEIAMoAqwGIAMoArAGEFkgBEGVARAOIAQgAkH/AXEQDgwPCyABIAMoAsQGIAMoAtgGEC4gA0HABmpB2AAgAhBZIAQhAgwSCyAGLwABIQIgASADKALEBiADKALYBhAuIANBwAZqIAUgAhBZIAQhAgwRCyADIAYvAAEiAjYC5AQgA0F/NgLoBCADIAVBAWs2AuAEIANBnAZqIAQgA0HgBGoQIwRAAkAgAygCqAYiBEEASARAIAMoAtgGIQQMAQsgAyAENgLYBgsgASADKALEBiAEEC4gA0HABmogBUEBaiACEFkMDQsgASADKALEBiADKALYBhAuIANBwAZqIAUgAhBZIAQhAgwQCyABIAogCCAEIANB2AZqEKUCIQQMBgsgASgC1AIhCyABKALMAiEGQQAhCUEAIQgDQAJAIAkgC0gEQEEDIQogBigCACICQeoAa0EDTwRAIAJB7QFHDQJBASEKCwJAIAEoAqQCIAYoAgxBFGxqKAIMIAYoAggiBWsiBEGAf0ggBCAKQf8AakpyRQRAIAZBATYCBCACQe0BRgRAQewBIQIgBkHsATYCAAwCCyAGIAJBgAFqIgI2AgAMAQsgAkHsAEcgBEGAgAJqQf//A0tyDQIgBkLtgYCAIDcCAEECIQpB7QEhAgsgAygCwAYgBWpBAWsgAjoAACAGKAIEIgIgAygCwAYgBWpqIgQgBCAKaiADKALEBiAFIApqIAJqaxCrASADIAMoAsQGIAprNgLEBkEAIQQgASgCrAIiAkEAIAJBAEobIQcgASgCpAIhAgNAIAQgB0YEQCABKALUAiELIAYhByAJIQQDQAJAIAsgBEEBaiIETARAQQAhAiABKALgAiIEQQAgBEEAShshBANAIAIgBEYNAiAFIAEoAtgCIAJBA3RqIgcoAgAiDEkEQCAHIAwgCms2AgALIAJBAWohAgwACwALIAciAkEQaiEHIAIoAhgiDCAFTA0BIAIgDCAKazYCGAwBCwsgCEEBaiEIDAMLIAUgAigCDCILSARAIAIgCyAKazYCDAsgAkEUaiECIARBAWohBAwACwALIAEoAswCIQIgCARAQQAhBQNAIAUgC0gEQCABKAKkAiACKAIMQRRsaigCDCACKAIIIgRrIQYCQAJAAkACQCACKAIEQQFrDgQAAQMCAwsgAygCwAYgBGogBjoAACABKALUAiELDAILIAMoAsAGIARqIAY7AAAMAQsgAygCwAYgBGogBjYAAAsgAkEQaiECIAVBAWohBQwBCwsgASgCzAIhAgsgACgCECIEQRBqIAIgBCgCBBEAACABQQA2AswCIAAoAhAiAkEQaiABKAKkAiACKAIEEQAAIAFBADYCpAIgASgC2AIhAgJAIAEtAG5BAnEEQCACIQUMAQtBACEFIAJFDQAgASgC8AIhByABKAIAIAFB9AJqIggQgwJBACECQQAhCgNAIAEoAtgCIQUgAiABKALgAk4NAQJAIAUgAkEDdGoiBigCBCIEQQBIIAQgB0ZyDQAgBigCACIGIAprIgVBAEgNAAJAIAQgB2siB0EBaiIKQQRLIAVBMktyRQRAIAggCiAFQQVsakEBakH/AXEQDgwBCyAIQQAQDiAIIAUQsQUgCCAHQQF0IAdBH3VzELEFCyAGIQogBCEHCyACQQFqIQIMAAsACyAAKAIQIgJBEGogBSACKAIEEQAAIAFBADYC2AIgDRCJASANIAMpAtAGNwIQIA0gAykCyAY3AgggDSADKQLABjcCACABQQE2AqACIAEoAowCBEAgABBwDCALIAEoAoACIQcgAyABKAKEAiIENgKcBiADIAAgBEEBdBAkIgY2AqQGIAZFDR9BACECIARBACAEQQBKGyEFA0AgAiAFRwRAIAYgAkEBdGpB//8DOwEAIAJBAWohAgwBCwsgA0EANgKsBiADIAAgBEECdBAkIgI2AqgGAkAgAkUNACADQgA3ArAGIANBADYCoAYgACADQZwGakEAQQBBAEF/ELABDQADQCADKAKsBiECAkACQAJAIAMoArAGIgRBAEoEQCADIARBAWsiBDYCsAYgByACIARBAnRq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IAIgCTYCSCACIAo2AkQgAkHBAEHQACAHQQxIGzYCTCACIAdBC2pBDG9BAWo2AkAgAkGQAmogA2pBwAAgA2tB5vQAIAJBQGsQSCADaiEDCyAAIAJBkAJqIAMQ6gEhEQsgAkHQAmokACARCzcCA38BfiMAQRBrIgAkACAAEI0GIAApAwAhAyAAKAIIIQIgAEEQaiQAIAJB6AdtrCADQugHfnwLhwEBAXwgACADKQMAEKgBIgJFBEBCgICAgOAADwsgAhAHIQQgACACEDEgBL0iAQJ/IASZRAAAAAAAAOBBYwRAIASqDAELQYCAgIB4CyIAt71RBEAgAK0PC0KAgICAwH4gAUKAgICAwIGA/P8AfSABQv///////////wCDQoCAgICAgID4/wBWGwvxAQIGfwF+IABBCBAkIgRFBEBBfw8LIARCATcCACACpyEGIAJCIIinQXVJIQgDQAJAAkAgA0ECRg0AIAAgACkDMCADQS5yEEciCUKAgICAcINCgICAgOAAUgRAIABBEBAkIgUNAiAAIAkQDAtBfyEHIANFDQAgACABKQMAEAwLIAAoAhAgBBD/BCAHDwsgBCAEKAIAQQFqNgIAIAUgBDYCCCAIRQRAIAYgBigCAEEBajYCAAsgBSACNwMAIAlCgICAgHBaBEAgCacgBTYCIAsgACAJQS9BARCYAyABIANBA3RqIAk3AwAgA0EBaiEDDAALAAt/AQV/IABBEGohBCABQQxqIQUgASgCECECA0AgAiAFRkUEQCACKAIEIQYgACACKQMQECEgACACKQMYECEgACACKQMgECEgACACKQMoECEgBCACIAAoAgQRAAAgBiECDAELCyABKAIIIgMEQCAAIAMQzgELIAQgASAAKAIEEQAAC+EDAgR/An4jAEFAaiICJAAgAiAAIAEQsQIiBjcDOAJAAkAgASgCIARAIAZCgICAgHCDQoCAgIDgAFENASAAIAEpAyhCgICAgDBBASACQThqEBwhBiAAIAIpAzgQDCAAIAYQDAwCCyACIAEoAmRBCGsiAykDADcDKCADQoCAgIAwNwMAIAAgBhAMQQAhAyAAIAApA1AgACACQShqQQAQ3gEhBiAAIAIpAygQDCAGQoCAgIBwg0KAgICA4ABRDQADQAJAIANBAkcEQCACQRBqIANBA3RqIAAgACkDMCADQTFqEEciBzcD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aiIGKAIEIAJBABARIgNCgICAgHCDQoCAgIDgAFENAyAGKAIEIQYCfyAEBEAgACABIAYgAxA5DAELIAAgASAGIANBBxAVC0EASA0DCyAFQQFqIQUMAQsLIAAgCCALEFtBACEJDAELIAAgCCALEFsLIAdBMGokACAJC6YBAQF+AkACQAJ+IARBBHEEQEEpIQIgACABEEoMAQtBKCECIAAgARAgCyIBQoCAgIBwg0KAgICA4ABRDQAgACACEIYBIgVCgICAgHCDQoCAgIDgAFENACAAQRAQJCICBEAgAkEANgIMIAIgBEEDcTYCCCACIAE3AwAgBUKAgICAcFQNAiAFpyACNgIgDAILIAAgBRAMCyAAIAEQDEKAgICA4AAPCyAFC8QBAQR/IAGnIgUgAjYCICAFQgA3AiQCQCACKAI8IgZFDQACQCAAIAZBAnQQXCIIRQ0AIAUgCDYCJEEAIQUDQCAFIAIoAjxODQIgAigCJCAFQQN0aiIHLwECIQYCQCAHLQAAIgdBAXEEQCAAIAQgBiAHQQF2QQFxEP8DIgYNAQwDCyADIAZBAnRqKAIAIgYgBigCAEEBajYCAAsgCCAFQQJ0aiAGNgIAIAVBAWohBQwACwALIAAgARAMQoCAgIDgACEBCyABC4IBAQJ+IAAgARApIQICQCABQQBIDQAgACgCECgCOCABQQJ0aigCACkCBCIDp0GAgICAeEYgA0KAgICA8P///z+DUCADQv//////////v39WcSADQoCAgICAgICAQINCgICAgICAgICAf1FyRXINACAAQa/wACACQa3wABCyASECCyACC2QBAn8CQAJAIAFCgICAgHBUDQAgARCUBQ0AQX8hAyAAIAIQMCIERQ0BIAAgBBDEBSECIAAgBBAQIAJCgICAgHCDQoCAgIDgAFENASAAIAFBNyACQQEQFUEASA0BC0EAIQMLIAMLNQACQCACRSABQoCAgIBwVHINACABEJQFDQAgACABQTcgACACEClBARAVQQBODQBBfw8LQQALDAAgACABQbYVELUBC2gCAX8BfgJAIAAgAUHqACABQQAQESIEQoCAgIBwg0KAgICA4ABSBEAgACAEECchAyAAIAFBwQAgAUEAEBEiAUKAgICAcINCgICAgOAAUg0BC0EAIQNCgICAgOAAIQELIAIgAzYCACABCxQBAn4gACABECAhAyAAIAEQDCADC/sBAgR/AX4gACgCyAEiBSgCECIEQTBqIQYgBCAEKAIYIAFxQX9zQQJ0aigCACEEAkADQCAERQ0BIAEgBiAEQQFrIgdBA3RqIgQoAgRHBEAgBCgCAEH///8fcSEEDAELCyAFKAIUIAdBA3RqIQUCQCADQQFGDQAgBTUCBEIghkKAgICAwABRBEAgACACEAwgACAEKAIEENEBQX8PCyAELQADQQhxDQAgACACEAwgAEGAgAEgARDnAQ8LIAAgBSACEB1BAA8LIAAgACkDwAEiCCABIAIgCAJ/IAAoAhAoAowBIgMEQEGAgAYgAygCKEEBcQ0BGgtBgIACCxDQAQuKAQEBfwJAIAJCgICAgHCDQoCAgICQf1EgA0KAgICAcINCgICAgJB/UXFFBEAgAEGl5gBBABASDAELIAAgAUESEF4iAUKAgICAcINCgICAgOAAUQ0AIAGnIgQgAz4CJCAEIAI+AiAgACABQdYAQgBBAhAVGiABDwsgACADEAwgACACEAxCgICAgOAACw0AIAAgAUHMjQEQgQMLZwEBfwJAIAFBAE4EQCAAKAIQIgIoAiwgAU0NASACKAI4IAFBAnRqKAIAIgEgASgCAEEBajYCACAAIAFBBBDmAw8LQYaJAUGo7ABB1RdBycAAEAAAC0GQzgBBqOwAQdYXQcnAABAAAAuxAgEEfwJAAkACQAJAIAJCgICAgHBUDQAgAqciAy8BBhDgAUUNACADKAIoIgRFDQAgBCgCECIDQTBqIQUgAyADKAIYQX9zQQJ0QdR5cmooAgAhAwNAIANFDQMgBSADQQFrIgNBA3RqIgYoAgRBygFHBEAgBigCAEH///8fcSEDDAELCyABQoCAgIBwVA0AIAQoAhQgA0EDdGopAwAiAkKAgICAcINCgICAgIB/UQ0BCyAAECIMAgsgACACEIgCIQMgAacoAhAiAEEwaiEEIAAgAyAAKAIYcUF/c0ECdGooAgAhAANAIABFBEBBAA8LIAQgAEEDdGoiBUEIayEAIAMgBUEEaygCAEYEQCAAQQBHDwUgACgCAEH///8fcSEADAELAAsACyAAQZ3kAEEAEBILQX8LRAEBfyAAQeQBaiECIABB4AFqIQADfyAAIAIoAgAiAkYEQEEADwsgASACQQRrKAIARgR/IAJBCGsFIAJBBGohAgwBCwsLiQECA38BfgJAIAAoAhAoAowBIgJFDQADQCABQQBMBEADQCACKQMIIgRCgICAgHBUDQMgBKciAS8BBhDgAUUNAyABKAIgIgEvABEiA0GAwABxRQRAIANBgAhxRQ0EIAAgASgCQBAWDwsgAigCACICDQAMAwsACyABQQFrIQEgAigCACICDQALC0EACykBAX8gAkIgiKdBdU8EQCACpyIDIAMoAgBBAWo2AgALIAAgASACEIUEC/QBAwF+An8BfANAAkBBfyEEAkACQAJAQQcgAkIgiKciBSAFQQdrQW5JGw4IAAAAAAICAwECCyACxCEDQQAhBAwCC0EAIQQgAkKAgICAwIGA/P8AfCICQv///////////wCDQoCAgICAgID4/wBWDQFCgICAgICAgICAfyEDIAK/IgZEAAAAAAAA4MNjDQFC////////////ACEDIAZEAAAAAAAA4ENkDQEgBplEAAAAAAAA4ENjBEAgBrAhAwwCC0KAgICAgICAgIB/IQMMAQsgACACEJYBIgJCgICAgHCDQoCAgIDgAFINAQsLIAEgAzcDACAEC+YBAgN/AXwDQAJAQX8hBAJAAkACQEEHIAJCIIinIgUgBUEHa0FuSRsOCAAAAAACAgMBAgsgAqchA0EAIQQMAgtBACEEIAJCgICAgMCBgPz/AHwiAkL///////////8Ag0KAgICAgICA+P8AVgRADAILQYCAgIB4IQMgAr8iBkQAAAAAAADgwWMNAUH/////ByEDIAZEAADA////30FkDQEgBplEAAAAAAAA4EFjBEAgBqohAwwCC0GAgICAeCEDDAELIAAgAhCWASICQoCAgIBwg0KAgICA4ABSDQELCyABIAM2AgAgBAttAAJAAkACQAJAAkAgAkEEdkEDcUEBaw4DAAECAwsgASgCACICBEAgACACrUKAgICAcIQQIQsgASgCBCIBRQ0DIAAgAa1CgICAgHCEECEPCyAAIAEoAgAQ5QEPCyABEOAFDwsgACABKQMAECELC/UBAQl/QX8hAiABIAFBAWtxRQRAIABBEGoiCCABQQJ0IgMgACgCABEDACIFBH8gBUEAIAMQLCEGIAFB/////wNqQf////8DcSEJIAAoAjQhBwNAIAQgACgCJE9FBEAgByAEQQJ0aigCACECA0AgAgRAIAAoAjggAkECdGooAgAiAygC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QQpPBH8gAEHBAGsgA00EQCAAQTdrDwsgAiAAQdcAayAAQeEAayABTxsFIAQLC6IDAQJ/IAAgASgCBBAQA0AgASgCECEDIAIgASgCFE5FBEAgACADIAJBA3RqKAIAEBAgAkEBaiECDAELCyAAKAIQIgJBEGogAyACKAIEEQAAQQAhAgNAAkAgASgCHCEDIAIgASgCIE4NACADIAJBFGxqIgMoAghFBEAgACgCECADKAIEEOUBCyAAIAMoAhAQECAAIAMoAgwQECACQQFqIQIMAQsLIAAoAhAiAkEQaiADIAIoAgQRAAAgACgCECICQRBqIAEoAiggAigCBBEAAEEAIQIDQCABKAI0IQMgAiABKAI4TkUEQCAAIAMgAkEMbGooAgQQECACQQFqIQIMAQsLIAAoAhAiAkEQaiADIAIoAgQRAAAgACgCECICQRBqIAEoAmQgAigCBBEAACAAIAEpA0AQDCAAIAEpA0gQDCAAIAEpA6gBEAwgACABKQOwARAMIAAgASkDiAEQDCAAIAEpA5ABEAwgACABKQOYARAMIAEoAggiAiABKAIMIgM2AgQgAyACNgIAIAFCADcCCCAAKAIQIgBBEGogASAAKAIEEQAAC9IDAgJ+An8jAEEgayIEJAACQCABQv///////////wCDIgNCgICAgICAwIA8fSADQoCAgICAgMD/wwB9VARAIAFCBIYgAEI8iIQhAyAAQv//////////D4MiAEKBgICAgICAgAhaBEAgA0KBgICAgICAgMAAfCECDAILIANCgICAgICAgIBAfSECIABCgICAgICAgIAIUg0BIAIgA0IBg3whAgwBCyAAUCADQoCAgICAgMD//wBUIANCgICAgICAwP//AFEbRQRAIAFCBIYgAEI8iIRC/////////wODQoCAgICAgID8/wCEIQIMAQtCgICAgICAgPj/ACECIANC////////v//DAFYNAEIAIQIgA0IwiKciBUGR9wBJDQAgBEEQaiAAIAFC////////P4NCgICAgICAwACEIgIgBUGB9wBrEGIgBCAAIAJBgfgAIAVrEI0CIAQpAwhCBIYgBCkDACIAQjyIhCECIAQpAxAgBCkDGIRCAFKtIABC//////////8Pg4QiAEKBgICAgICAgAhaBEAgAkIBfCECDAELIABCgICAgICAgIAIUg0AIAJCAYMgAnwhAgsgBEEgaiQAIAIgAUKAgICAgICAgIB/g4S/C6oPAgV/D34jAEHQAmsiBSQAIARC////////P4MhCiACQv///////z+DIQsgAiAEhUKAgICAgICAgIB/gyEMIARCMIinQf//AXEhCAJAAkAgAkIwiKdB//8BcSIJQf//AWtBgoB+TwRAIAhB//8Ba0GBgH5LDQELIAFQIAJC////////////AIMiDUKAgICAgIDA//8AVCANQoCAgICAgMD//wBRG0UEQCACQoCAgICAgCCEIQwMAgsgA1AgBEL///////////8AgyICQoCAgICAgMD//wBUIAJCgICAgICAwP//AFEbRQRAIARCgICAgICAIIQhDCADIQEMAgsgASANQoCAgICAgMD//wCFhFAEQCADIAJCgICAgICAwP//AIWEUARAQgAhAUKAgICAgIDg//8AIQwMAwsgDEKAgICAgIDA//8AhCEMQgAhAQwCCyADIAJCgICAgICAwP//AIWEUARAQgAhAQwCCyABIA2EUARAQoCAgICAgOD//wAgDCACIAOEUBshDEIAIQEMAgsgAiADhFAEQCAMQoCAgICAgMD//wCEIQxCACEBDAILIA1C////////P1gEQCAFQcACaiABIAsgASALIAtQIgYbeSAGQQZ0rXynIgZBD2sQYkEQIAZrIQYgBSkDyAIhCyAFKQPAAiEBCyACQv///////z9WDQAgBUGwAmogAyAKIAMgCiAKUCIHG3kgB0EGdK18pyIHQQ9rEGIgBiAHakEQayEGIAUpA7gCIQogBSkDsAIhAwsgBUGgAmogCkKAgICAgIDAAIQiEkIPhiADQjGIhCICQgBCgICAgLDmvIL1ACACfSIEQgAQYSAFQZACakIAIAUpA6gCfUIAIARCABBhIAVBgAJqIAUpA5gCQgGGIAUpA5ACQj+IhCIEQgAgAkIAEGEgBUHwAWogBEIAQgAgBSkDiAJ9QgAQYSAFQeABaiAFKQP4AUIBhiAFKQPwAUI/iIQiBEIAIAJCABBhIAVB0AFqIARCAEIAIAUpA+gBfUIAEGEgBUHAAWogBSkD2AFCAYYgBSkD0AFCP4iEIgRCACACQgAQYSAFQbABaiAEQgBCACAFKQPIAX1CABBhIAVBoAFqIAJCACAFKQO4AUIBhiAFKQOwAUI/iIRCAX0iAkIA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IAUgA0E5ShshAwJAIBdCB1cEQCADIAdBBHRqIQcMAQsgF0IcWARAIAJBMGogAxB4IAJBIGogHCAYQgBCgICAgICAwP0/ECsgAkEQaiACKQMwIAIpAzggAikDICIcIAIpAygiGBArIAIgAikDECACKQMYIBkgGxBvIAIpAwghGyACKQMAIRkMAQsgA0UgCHINACACQdAAaiAcIBhCAEKAgICAgICA/z8QKyACQUBrIAIpA1AgAikDWCAZIBsQbyACKQNIIRtBASEIIAIpA0AhGQsgF0IBfCEXQQEhCQsgACgCBCIDIAAoAmhHBH8gACADQQFqNgIEIAMtAAAFIAAQTwshAwwBCwsCfiAJRQRAIAApA3BCAFkEQAJAIAAgACgCBCIDQQFrNgIEIAAgA0ECazYCBCABRQ0AIAAgA0EDazYCBAsLIAJB4ABqIAS3RAAAAAAAAAAAohCpASACKQNgIRkgAikDaAwBCyAXQgdXBEAgFyEYA0AgB0EEdCEHIBhCAXwiGEIIUg0ACwsCQAJAAkAgA0FfcUHQAEYEQCAAEIEGIhhCgICAgICAgICAf1INAyAAKQNwQgBZDQEMAgtCACEYIAApA3BCAFMNAgsgACAAKAIEQQFrNgIEC0IAIRgLIAdFBEAgAkHwAGogBLdEAAAAAAAAAACiEKkBIAIpA3AhGSACKQN4DAELIBogFyABG0IChiAYfEIgfSIXQQAgD2utVQRAQcTUBEHEADYCACACQaABaiAEEHggAkGQAWogAikDoAEgAikDqAFCf0L///////+///8AECsgAkGAAWogAikDkAEgAikDmAFCf0L///////+///8AECsgAikDgAEhGSACKQOIAQwBCyAPQeIBa6wgF1cEQCAHQQBOBEADQCACQaADaiAZIBtCAEKAgICAgIDA/79/EG8gGSAbQoCAgICAgID/PxD1BSEAIAJBkANqIBkgGyACKQOgAyAZIABBAE4iABsgAikDqAMgGyAAGxBvIBdCAX0hFyACKQOYAyEbIAIpA5ADIRkgB0EBdCAAciIHQQBODQALCwJ+IBcgD6x9QiB8IhinIgBBACAAQQBKGyANIBggDa1TGyIAQfEATgRAIAJBgANqIAQQeCACKQOIAyEaIAIpA4ADIRxCAAwBCyACQeACakQAAAAAAADwP0GQASAAaxDVARCpASACQdAC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QQFqNgIEIAEtAAAMAQsgABBPC0Ewa0EKSQ0ACwsgACkDcEIAWQRAIAAgACgCBEEBazYCBAtCACAFfSAFIAMbIQUMAQtCgICAgICAgICAfyEFIAApA3BCAFMNACAAIAAoAgRBAWs2AgRCgICAgICAgICAfw8LIAULygYCBX8EfiMAQYABayIFJAACQAJAAkAgAyAEQgBCABDrAUUNAAJ/IARC////////P4MhCwJ/IARCMIinQf//AXEiBkH//wFHBEBBBCAGDQEaQQJBAyADIAuEUBsMAgsgAyALhFALCyEJIAJCMIinIghB//8BcSIHQf//AUYNACAJDQELIAVBEGogASACIAMgBBArIAUgBSkDECICIAUpAxgiASACIAEQ9AUgBSkDCCECIAUpAwAhBAwBCyABIAJC////////////AIMiCyADIARC////////////AIMiChDrAUEATARAIAEgCyADIAoQ6wEEQCABIQQMAgsgBUHwAGogASACQgBCABArIAUpA3ghAiAFKQNwIQQMAQsgBEIwiKdB//8BcSEGIAcEfiABBSAFQeAAaiABIAtCAEKAgICAgIDAu8AAECsgBSkDaCILQjCIp0H4AGshByAFKQNgCyEEIAZFBEAgBUHQAGogAyAKQgBCgICAgICAwLvAABArIAUpA1giCkIwiKdB+ABrIQYgBSkDUCEDCyAKQv///////z+DQoCAgICAgMAAhCEMIAtC////////P4NCgICAgICAwACEIQsgBiAHSARAA0ACfiALIAx9IAMgBFatfSIKQgBZBEAgCiAEIAN9IgSEUARAIAVBIGogASACQgBCABArIAUpAyghAiAFKQMgIQQMBQsgCkIBhiAEQj+IhAwBCyALQgGGIARCP4iECyELIARCAYYhBCAHQQFrIgcgBkoNAAsgBiEHCwJAIAsgDH0gAyAEVq19IgpCAFMEQCALIQoMAQsgCiAEIAN9IgSEQgBSDQAgBUEwaiABIAJCAEIAECsgBSkDOCECIAUpAzAhBAwBCyAKQv///////z9YBEADQCAEQj+IIQ0gB0EBayEHIARCAYYhBCANIApCAYaEIgpCgICAgICAwABUDQALCyAIQYCAAnEhBiAHQQBMBEAgBUFAayAEIApC////////P4MgB0H4AGogBnKtQjCGhEIAQoCAgICAgMDDPxArIAUpA0ghAiAFKQNAIQQMAQsgCkL///////8/gyAGIAdyrUIwhoQhAgsgACAENwMAIAAgAjcDCCAFQYABaiQAC78CAQF/IwBB0ABrIgQkAAJAIANBgIABTgRAIARBIGogASACQgBCgICAgICAgP//ABArIAQpAyghAiAEKQMgIQEgA0H//wFJBEAgA0H//wBrIQMMAgsgBEEQaiABIAJCAEKAgICAgICA//8AECtB/f8CIAMgA0H9/wJOG0H+/wFrIQMgBCkDGCECIAQpAxAhAQwBCyADQYGAf0oNACAEQUBrIAEgAkIAQoCAgICAgIA5ECsgBCkDSCECIAQpA0AhASADQfSAfksEQCADQY3/AGohAwwBCyAEQTBqIAEgAkIAQoCAgICAgIA5ECtB6IF9IAMgA0HogX1MG0Ga/gFqIQMgBCkDOCECIAQpAzAhAQsgBCABIAJCACADQf//AGqtQjCGECsgACAEKQMINwMIIAAgBCkDADcDACAEQdAAaiQACzwAIAAgATcDACAAIAJC////////P4MgAkKAgICAgIDA//8Ag0IwiKcgBEIwiKdBgIACcXKtQjCGhDcDCAsxAQJ/An8gABA9QQFqIQEDQEEAIAFFDQEaIAAgAUEBayIBaiICLQAAQS9HDQALIAILCxcBAX8gAEEAIAEQkgIiAiAAayABIAIbC9EBAQF/AkACQCAAIAFzQQNxBEAgAS0AACECDAELIAFBA3EEQANAIAAgAS0AACICOgAAIAJFDQMgAEEBaiEAIAFBAWoiAUEDcQ0ACwsgASgCACICQX9zIAJBgYKECGtxQYCBgoR4cQ0AA0AgACACNgIAIAEoAgQhAiAAQQRqIQAgAUEEaiEBIAJBgYKECGsgAkF/c3FBgIGChHhxRQ0ACwsgACACOgAAIAJB/wFxRQ0AA0AgACABLQABIgI6AAEgAEEBaiEAIAFBAWohASACDQALCwtFAQJ8IAAgAiACoiIEOQMAIAEgAiACRAAAAAIAAKBBoiIDIAIgA6GgIgKhIgMgA6IgAiACoCADoiACIAKiIAShoKA5AwALMwAgAQJ/IAIoAkxBAEgEQCAAIAEgAhCXBAwBCyAAIAEgAhCXBAsiAEYEQA8LIAAgAW4aC30BAn8jAEEQayIBJAAgAUEKOgAPAkACQCAAKAIQIgIEfyACBSAAEJgEDQIgACgCEAsgACgCFCICRg0AIAAoAlBBCkYNACAAIAJBAWo2AhQgAkEKOgAADAELIAAgAUEPakEBIAAoAiQRAQBBAUcNACABLQAPGgsgAUEQaiQAC9sBAQR/IAAoAlQhAwJAIAAoAhQiBiAAKAIcIgVHBEAgACAFNgIUIAAgBSAGIAVrIgUQiwYgBUkNAQsCQCADKAIQQeEARwRAIAMoAgAhBAwBCyADIAMoAgQiBDYCAAsgAygCDCAEaiABIAMoAgggBGsiASACIAEgAkkbIgQQHhogAyADKAIAIARqIgE2AgAgASADKAIETQ0AIAMgATYCBAJ/IAMoAggiAiABSwRAIAMoAgwgAWoMAQsgAkUNASAAKAIAQQRxRQ0BIAMoAgwgAmpBAWsLQQA6AAALIAQLGAEBfyMAQRBrIgEgADkDCCABKwMIIACiC3UCAnwBfiAAAn4QBCIBRAAAAAAAQI9AoyICmUQAAAAAAADgQ2MEQCACsAwBC0KAgICAgICAgIB/CyIDNwMAIAACfyABIANC6Ad+uaFEAAAAAABAj0CiIgGZRAAAAAAAAOBBYwRAIAGqDAELQYCAgIB4CzYCCAsoACABRAAAAAAAAMB/oiAARIvdGhVmIJbAoBCaBKJEAAAAAAAAwH+iCxAAIABBIEYgAEEJa0EFSXILjAMCAn4DfyMAQSBrIgIkAEKAgICA4AAhBAJAIAAgAykDACIFEFUNACAAIAFBLRBeIgFCgICAgHCDQoCAgIDgAFENACAAAn4CQCAAQSAQXCIGRQ0AQQAhAyAGQQA2AhQgBkEANgIAIAZBBGohCANAIANBAkZFBEAgCCADQQN0aiIHIAc2AgQgByAHNgIAIANBAWohAwwBCwsgBkKAgICAMDcDGCABQoCAgIBwWgRAIAGnIAY2AiALIAAgAkEQaiIDIAEQqgUNAAJAIAAgBUKAgICAMEECIAMQHCIFQoCAgIBwg0KAgICA4ABRBEAgACgCECIDKQOAASEEIANCgICAgCA3A4ABIAIgBDcDCCAAIAIpAxhCgICAgDBBASACQQhqEBwhBCAAIAIpAwgQDCAEQoCAgIBwg0KAgICA4ABRDQEgACAEEAwLIAAgBRAMIAAgAikDEBAMIAEhBCACKQMYDAILIAAgAikDEBAMIAAgAikDGBAMQoCAgIDgACEECyABCxAMCyACQSBqJAAgBAuLAgEHfyABQQJ0QaCDBGooAgAiAiABQQF0QfCEBGovAQBqIQhBACEBAkADQCACIAhPDQEgAkEBaiEGAkACQCACLQAAIgRBP00EQCADIARBA3ZqQQFqIQIgAQRAIAAgAyACEGkNAwsgAUEBcyEBIARBB3EgAmpBAWohBQwBCwJ/IAMgBGpB/wBrIATAQQBIDQAaIAYtAAAhBSAEQd8ATQRAIAJBAmohBiADIARBCHRqIAVqQf//AGsMAQsgAkEDaiEGIAItAAIgAyAEQRB0aiAFQQh0ampB////AmsLIQUgAyECCyABBEAgACACIAUQaQ0BCyABQQFzIQEgBiECIAUhAwwBCwtBfyEHCyAHC7UCAQp/IAFBBnEhByABQQJ2QQFxIQoCQANAIANB6x5KDQEgAiEEIANBsOQDai0AACIFQR9xIQkCfyADQQFqIAVBBXYiAkEHRw0AGiADQQJqIQUgA0Gx5ANqLAAAIgJB/wFxIQYgAkEATgRAIAZBB2ohAiAFDAELIAVBsOQDai0AACEFIAJBv39NBEAgBkEIdCAFckH5/gFrIQIgA0EDagwBCyADQbPkA2otAAAgBkEQdHIgBUEIdHJB+f7+BWshAiADQQRqCyEDIAIgBGpBAWohAgJAAkAgCUEfRgRAIAdFDQMgB0EGRg0BIAQgCmohBANAIAIgBE0NBCAAIAQgBEEBahBpIQsgBEECaiEEIAtFDQALDAILIAEgCXZBAXFFDQILIAAgBCACEGlFDQELC0F/IQgLIAgLOABB8NECIAEQnQQiAUEASARAQX4PCyAAIAFBHU0Ef0IBIAGthqcFIAFBAnRBmNYCaigCAAsQkgYLmgYBBH9BASEJIAJBAXRBwPkCai8BACECIAVFBEAgACACNgIAQQEPCyACQcCEA2ohBkESIQcCQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCAFQQFrDiIAAAAAAAAAAQECAgICAgQDAwMDAwMFBQUFBQUFBQYHCAkJCwsgBiABIANrIAVsQQF0aiEBQQAhAgNAIAIgBUYEQCAFDwsgACACQQJ0aiABIAJBAXRqLwAAIgM2AgAgAkEBaiECIAMNAAsMCwsgBUEHayIIIAEgA2tsIQcgBiAEIAhsQQF0aiEBQQAhAgNAIAIgCEYNCiAGIAdBAXQiA2ovAAAgASAHQQJ2ai0AACADQQZxdkEQdEGAgAxxciIDRQ0LIAAgAkECdGogAzYCACACQQFqIQIgB0EBaiEHDAALAAsgBiAFQQlrIgggASADa2xqIQFBACECA0AgAiAIRg0JIAAgAkECdGogASACai0AABCkAyIDNgIAIAJBAWohAiADDQALDAkLIAVBAXEgBUEQayICQQFLaiEIIAJBAXZBAmohCQsgASADayEBQQAhAgNAIAIgCUYEQCAJDwUgACACQQJ0aiAGIAJBAXRqLwAAIAFBACACIAhGG2o2AgAgAkEBaiECDAELAAsACyAFQRVrIQcLIAYgByABIANrbGpBAmohASAGLwAAIQNBACECA0AgAiAHRgRAIAcPBSAAIAJBAnRqQSAgAyABIAJqLQAAIgRqIARB/wFGGzYCACACQQFqIQIMAQsACwALIAAgBiABIANrQQNsaiIBLwAAIgI2AgAgAkUNAyAAIAEtAAIQpAM2AgQMAgsgACAGLwACNgIIIAAgBi8AADYCACAAIAYgASADa0EBdGovAAQ2AgRBAw8LIAEgA2shAQJ/IAVBIUYEQCAGIAFBfnFqIgJBAWohAyACLQAAEKQDDAELIAYgAUEBdkEDbGoiAkECaiEDIAIvAAALIQIgAEEgQSBBASACQZAIa0EgSRsgAkGAAkkbIAJqIAIgAUEBcRs2AgAgACADLQAAEKQDNgIEC0ECIQgLIAgPC0EAC7QCAQh/IwBB0ABrIgckACACQQAgAkEAShshCwNAAkACQCAGIAtHBEAgASAGQQJ0aigCACIFQYDYAmsiAkGj1wBNDQFBugUhAkEAIQQCQANAIAIgBEgNASAFIAIgBGpBAm0iCEECdEHQ4wJqKAIAIglBDnYiCkkEQCAIQQFrIQIMAQsgBSAJQQd2Qf8AcSIEIApqTwRAIAhBAWohBAwBCwsgCUEBcSADSw0AIAcgBSAIIAogBCAJQQF2QT9xEJQGIgJFDQAgACAHIAIgAxCVBgwDCyAAIAUQGwwCCyAHQdAAaiQADwsgACACQf//A3EiBUHMBG4iBEGAInIQGyAAIAIgBEHMBGxrQf//A3FBHG5B4SJqEBsgBUEccCICRQ0AIAAgAkGnI2oQGwsgBkEBaiEGDAALAAsiAQF/QQEhASAAEJ4EBH9BAQUgAEHgnQJBgKMCQRUQpQMLC00BBX8gACgCCCEDIABBADYCCCAAKAIAIQQgAEIANwIAIAAoAhAhBSAAKAIMIQcgACADIAQgASACQQAQ7AEhACAHIANBACAFEQEAGiAAC7EBAQd/IAAoAggiA0EEaiEFIAAoAgAhBgNAIAFBAWoiAiAGTkUEQAJAIAMgAUECdGooAgAiByADIAJBAnRqKAIARgRAIAEhAgwBCwNAIAYgASICQQNqSgRAIAUgAUECdGooAgAgAyABQQJqIgFBAnRqKAIARg0BCwsgAyAEQQJ0aiIBIAc2AgAgASAFIAJBAnRqKAIANgIEIARBAmohBAsgAkECaiEBDAELCyAAIAQ2AgALEQAgAEHgjQJB0JMCQRcQpQMLzwEBA38gASACLwAAIAItAAJBEHRBgID8AHFySQRAIABBADYCAEEADwtBfyEFIAEgAiADQQFrIgRBA2xqIgMvAAAgAy0AAkEQdHJJBH9BACEDA0AgBCADa0ECSEUEQCADIARqQQJtIgUgBCACIAVBA2xqIgQvAAAgBC0AAkEQdEGAgPwAcXIgAUsiBhshBCADIAUgBhshAwwBCwsgACACIANBA2xqIgAvAAAgAC0AAiIAQRB0QYCA/ABxcjYCACADQQV0IABBBXZyQSBqBUF/CwtuAQV/QfECIQEDQCABIAJOBEAgACABIAJqQQF2IgNBAnRBoIACaigCACIEQQ92IgVJBEAgA0EBayEBDAILIAAgBEEIdkH/AHEgBWpJBEBBAQ8FIANBAWohAgwCCwALCyAAQfCLAkHAjQJBBxClAwupAQECfyMAQRBrIgQkAAJ/IAMEQCAEQQRqIABBAiABIAIQoARBAUYEQCAEKAIEDAILQYX2AyAAQYb2A0YNARpBkAcgAEHTP0YNARpBsAcgACAAQeM/RhsMAQsgAEEgayAAIABB4QBrQRpJGyAAQf8ATQ0AGiAEQQRqIABBACABIAIQoAQhASAEKAIEIgIgACACQf8ASxsgACABQQFGGwshBSAEQRBqJAAgBQupAQEFfwJAIAFB/wBLBEBB8QIhAwNAIAMgBEgNAiABIAMgBGpBAXYiBUECdEGggAJqKAIAIgZBD3YiB0kEQCAFQQFrIQMMAQsgASAGQQh2Qf8AcSAHak8EQCAFQQFqIQQMAQsLIAAgASACIAUgBhCgBA8LIAIEQCABQSByIAEgAUHBAGtBGkkbIQEMAQsgAUEgayABIAFB4QBrQRpJGyEBCyAAIAE2AgBBAQuRAgEDfyABKAIAIgJB/v8HTwRAIABBkClBABA/QX8PCwJAIAJBAU0EQCAAQQJBfxC3ARoMAQsgASgCCCACQQJ0aiIEQQRrKAIAIgNBf0YEQCAEQQhrKAIAIQMLIAJBAXYhAiADQf//A00EQCAAQRUgAhChBEEAIQIDQCACIAEoAgBODQIgACACQQJ0IgMgASgCCGovAQAQJiAAQX8gASgCCCADaigCBEEBayIDIANBfkYbQf//A3EQJiACQQJqIQIMAAsACyAAQRYgAhChBEEAIQIDQCACIAEoAgBODQEgACACQQJ0IgMgASgCCGooAgAQGyAAIAEoAgggA2ooAgRBAWsQGyACQQJqIQIMAAsAC0EACzUBAn8jAEEQayIDJAAgAyABNgIIIAMgAkEBajYCDCAAIANBCGpBAhCXBiEEIANBEGokACAECyYBAX8gACgCOCIBQQBIBEAgACAAIABBPGpBABChBiIBNgI4CyABC9sCAQZ/IwBBkAFrIgQkACABQQA2AgAgACgCICEDQQEhBgNAIAQgAzYCjAECQAJAAkAgACgCHCIHIANNBEAgBiEFDAELAkACQAJAAkAgAy0AACIFQdsAaw4CAQIACyAFQShHDQUgAy0AAUE/Rw0CIAMtAAJBPEcNBSADLQADIgVBIUYgBUE9RnINBSABQQE2AgACQCACRQ0AIAQgA0EDajYCjAEgBCAEQYwBahCkBA0AIAQgAhCWBEUNBQsgBkEBaiEFIAZB/QFKDQMgBCgCjAEhAyAFIQYMBQsDQCAEIAMiBUEBaiIDNgKMASADIAdPDQUCQCADLQAAQdwAaw4CAAYBCyAEIAVBAmoiAzYCjAEMAAsACyAEIANBAWoiAzYCjAEMAwsgBkH9AUohCCAGQQFqIgUhBiAIRQ0CC0F/IAUgAhshBgsgBEGQAWokACAGDwsgA0EBaiEDDAALAAtdAQR/IAEQPSEDIAAoAkQiAiAAKAJIaiEEQQEhAANAAkAgAiAETwRAQX8hAAwBCyADIAIQPSIFRgRAIAEgAiADEGhFDQELIABBAWohACACIAVqQQFqIQIMAQsLIAAL0xoBDX8gAkEEayEPIAAoAgQhDSAAKAIIIQwDQCAFIQcgBEEBaiEIAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACfwJAAkACQAJAIAQtAAAiCUEBaw4cAwIJCgcIBhUVAAsLDA8NDhEREhIaGQUFEAEYFxYLQQEhCSAGRQ0fIAcPCyAIIQQgByACIANBAWsiA0ECdGooAgBHDSIMHQtBBSEKIAgoAAAMAQtBAyEKIAgvAAALIQggByANTw0aAkAgDEUEQCAHQQFqIQUgBy0AACEJDAELIAcvAQAiCUGA+ANxQYCwA0cgDEECR3IgDSAHQQJqIgVNcg0AIAUvAQAiC0GA+ANxQYC4A0cNACAJQQp0QYD4P3EgC0H/B3FyQYCABGohCSAHQQRqIQULIAQgCmohBCAAKAIYBH8gCSAAKAIcENYBBSAJCyAIRg0fDBoLIAAgASACIAMgBCgAASAEQQVqIgRqIAcgCUEWa0EAEKYEQQBODR4MGAsgCCAIKAAAakEEaiEEDBYLIAghBCAFIAAoAgAiB0YNHCAAKAIURQ0XAkAgDEUEQCAFQQFrLQAAIQoMAQsgBUECay8BACIKQYD4A3FBgLgDRyAMQQJHcg0AIAcgBUEEayIHSw0AIAcvAQAiB0GA+ANxQYCwA0cNACAKQf8HcSAHQf8HcUEKdHJBgIAEaiEKCyAKEKUEDRwMFwsgCCEEIAcgDSIFRg0bIAAoAhRFDRYCQCAMRQRAIActAAAhCQwBCyAHLwEAIglBgPgDcUGAsANHIAxBAkdyIAdBAmogDU9yDQAgBy8BAiIFQYD4A3FBgLgDRw0AIAlBCnRBgPg/cSAFQf8HcXJBgIAEaiEJCyAHIQUgCRClBA0bDBYLIAcgDUYNFQJAIAxFBEAgB0EBaiEFIActAAAhCQwBCyAHLwEAIglBgPgDcUGAsANHIAxBAkdyIA0gB0ECaiIFTXINACAFLwEAIgRBgPgDcUGAuANHDQAgCUEKdEGA+D9xIARB/wdxckGAgARqIQkgB0EEaiEFCyAIIQQgCRClBEUNGgwVCyAHIA1GDRQgDEUEQCAHQQFqIQUgCCEEDBoLIAdBAmohBSAIIQQgBy8BAEGA+ANxQYCwA0cgDEECR3IgBSANT3INGSAHQQRqIAUgBy8BAkGA+ANxQYC4A0YbIQUMGQsgCC0AACIFIAAoAgxPDQggASAFQQN0aiAJQQJ0akEsayAHNgIAIARBAmohBAwRCyAELQACIgkgACgCDE8NBiAEQQNqIQQgCC0AACEFA0AgBSAJSw0RIAEgBUEDdGpCADcCACAFQQFqIQUMAAsACyACIANBAnRqIAQoAAE2AgAgA0EBaiEDIARBBWohBAwPCyADQQFrIQMMDQsgBCgAASEFIA8gA0ECdGoiCCAIKAIAQQFrIgg2AgAgBCAFQQAgCBtqQQVqIQQMDQsgAiADQQJ0aiAHNgIAIANBAWohAwwLC0EAIQtBACEKIAAoAgAiBCAHRwRAAkAgDEUEQCAHQQFrLQAAIQUMAQsgB0ECay8BACIFQYD4A3FBgLgDRyAMQQJHcg0AIAQgB0EEayIESw0AIAQvAQAiBEGA+ANxQYCwA0cNACAFQf8HcSAEQf8HcUEKdHJBgIAEaiEFCyAFEKcDIQoLIAcgDUkEQAJAIAxFBEAgBy0AACEFDAELIAcvAQAiBUGA+ANxQYCwA0cgDEECR3IgB0ECaiANT3INACAHLwECIgRBgPgDcUGAuANHDQAgBUEKdEGA+D9xIARB/wdxckGAgARqIQULIAUQpwMhCwsgByEFIAghBEESIAlrIAogC3NGDRIMDQsgBC0AASIIIAAoAgxPDQwgBEECaiEEIAEgCEEDdGoiBygCACIIRQ0RIAcoAgQiCkUNESAJQRNGDQgDQCAIIApPDRIgBSAAKAIAIg5GDQ0CQAJAAkAgDARAIApBAmsiBy8BACIJQYD4A3FBgLgDRyAHIAhNciAMQQJHcg0BIApBBGsiCi8BACILQYD4A3FBgLADRw0BIAlB/wdxIAtB/wdxQQp0ckGAgARqIQkMAgsgBUEBayIFLQAAIQsgCkEBayIKLQAAIQkMAgsgByEKCwJAIAVBAmsiBy8BACILQYD4A3FBgLgDRyAHIA5NciAMQQJHcg0AIAVBBGsiBS8BACIOQYD4A3FBgLADRw0AIAtB/wdxIA5B/wdxQQp0ckGAgARqIQsMAQsgByEFCyAAKAIYBH8gCSAAKAIcENYBIQkgCyAAKAIcENYBBSALCyAJRg0ACwwMC0G7GEG/7ABBjhFB98UAEAAAC0GkGEG/7ABBhRFB98UAEAAACyAEQQVqIgggCCAEKAABaiIKIAlBCUYiCxshBEF/IQkgACABIAIgAyAKIAggCxsgB0EAQQAQpgRBAE4NDgwLCxABAAsgBEERaiIQIAQoAAFqIRIgBCgABSEOQQAhCiAEKAAJIgRB/////wdGIREDQAJAAkAgACABIAIgAyAQIAVBARCjBiIJQQFqDgIMAQALIAkhBSAEIApBAWoiCksgEXINAQsLIAogDkkNByASIQQgCiAOTQ0MIAAgASACIAMgCCAFQQMgCiAOaxCmBEEATg0MDAYLIAcgACgCACIJRg0GIAxFBEAgB0EBayEFIAghBAwMCyAHQQJrIQUgCCEEIAxBAkcNCyAFLwEAQYD4A3FBgLgDRyAFIAlNcg0LIAdBBGsiByAFIAcvAQBBgPgDcUGAsANGGyEFDAsLIAcgDU8NBQJAIAxFBEAgB0EBaiEFIActAAAhCAwBCyAHLwEAIghBgPgDcUGAsANHIAxBAkdyIA0gB0ECaiIFTXINACAFLwEAIglBgPgDcUGAuANHDQAgCEEKdEGA+D9xIAlB/wdxckGAgARqIQggB0EEaiEFCyAELwABIQogACgCGARAIAggACgCHBDWASEICyAIIARBA2oiBygAAEkNBUEAIQkgCCAHIApBAWsiBEEDdGooAARLDQUDQCAEIAlJDQYgByAEIAlqQQF2IgtBA3RqIg4oAAAgCEsEQCALQQFrIQQMAQsgDigABCAISQRAIAtBAWohCQwBCwsgByAKQQN0aiEEDAoLIAcgDU8NBAJAIAxFBEAgB0EBaiEFIActAAAhCAwBCyAHLwEAIghBgPgDcUGAsANHIAxBAkdyIA0gB0ECaiIFTXINACAFLwEAIglBgPgDcUGAuANHDQAgCEEKdEGA+D9xIAlB/wdxckGAgARqIQggB0EEaiEFCyAELwABIQogACgCGARAIAggACgCHBDWASEICyAIIARBA2oiBy8AAEkNBAJAIAcgCkEBayIEQQJ0ai8AAiIJQf//A0YgCEH//wNPcQ0AIAggCUsNBUEAIQkDQCAEIAlJDQYgByAEIAlqQQF2IgtBAnRqIg4vAAAgCEsEQCALQQFrIQQMAQsgDi8AAiAIQf//A3FPDQEgC0EBaiEJDAALAAsgByAKQQJ0aiEEDAkLA0AgCCAKTw0JIAUgDU8NBAJ/An8CQCAMBEAgCC8BACIJQYD4A3FBgLADRyAMQQJHciAIQQJqIgcgCk9yDQEgBy8BACILQYD4A3FBgLgDRw0BIAlBCnRBgPg/cSALQf8HcXJBgIAEaiEJIAhBBGoMAgsgBS0AACELIAgtAAAhCSAIQQFqIQggBUEBagwCCyAHCyEIAkAgBS8BACILQYD4A3FBgLADRyAMQQJHciAFQQJqIgcgDU9yDQAgBy8BACIOQYD4A3FBgLgDRw0AIAtBCnRBgPg/cSAOQf8HcXJBgIAEaiELIAVBBGoMAQsgBwshBSAAKAIYBH8gCSAAKAIcENYBIQkgCyAAKAIcENYBBSALCyAJRg0ACwwDCyAIIQQMBwsgByEFDAYLQX8PC0EAIQkgBg0BCyAAKAIwIQUDQCAJIQMgBUUEQCAJDwsCQAJAAkACQCAAKAIoIAVBAWsiBSAAKAIkbGoiCC0AACIEDgQAAgIBAgtBASEJIAMNAgwFC0EBIQkgAw0BIAEgCEEQaiIDIAAoAgxBA3QQHhogAiADIAAoAgxBA3RqIAgtAAEiA0ECdBAeGiAIKAIIIQUgCCgCDCIJKAAMIQpBACEEA0ACfwJAIAQgCkcEQCAFQQFrIAxFDQIaIAVBAmshByAMQQJHDQEgBy8BAEGA+ANxQYC4A0cNASAHIAAoAgBNDQEgBUEEayIFIAcgBS8BAEGA+ANxQYCwA0YbDAILIAkoAAAhEyAIIAU2AgggCCAIKAIEQQFrIgc2AgQgEyAJakEQaiEEIAcNCSAAIAAoAjBBAWs2AjAMCQsgBwshBSAEQQFqIQQMAAsACyADQQAgBEEBRhsNBEEAIQkgAw0AIARBAkYNAwsgACAFNgIwDAALAAsgCQ8LIAEgCEEQaiAAKAIMQQN0EB4aCyAIKAIIIQUgCCgCDCEEIAIgCCAAKAIMQQN0akEQaiAILQABIgNBAnQQHhogACAAKAIwQQFrNgIwDAALAAucAgEFfyMAQUBqIgckACAHIAEtAAAiCEEBdkEBcTYCJCAHIAhBAnZBAXE2AiAgByAIQQR2QQFxIgg2AiggByABLQABIgk2AhggAS0AAiEKIAdBADYCPCAHIAY2AiwgByAFQQIgBSAIGyAFQQFHGzYCFCAHIAIgBCAFdGo2AhAgByACNgIMIAcgCjYCHCAHQgA3AjQgByAKQQJ0IgYgCUEDdGpBEGo2AjAgCUEBdCEEQQAhCANAIAQgCEZFBEAgACAIQQJ0akEANgIAIAhBAWohCAwBCwsgByAGQQ9qQfAPcWsiBCQAIAdBDGogACAEQQAgAUEHaiACIAMgBXRqQQAQowYhCyAHKAIsIAcoAjRBABD3AxogB0FAayQAIAsLriQBIH8jAEHQAGsiBCQAQQwgAWshFyABQQtqIRggAEHEAGohFCABQRNqIRkgAEHcAGohDyAAKAIEIRMCQAJAAkADQCAAKAIYIgIgACgCHE8NAyACLQAAIgNBKUYgA0H8AEZyDQMgACgCBCEQIAQgAjYCHAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgA0HbAGsOBAIBAwkACwJAAkACQAJAAkAgA0Ekaw4LAQkJCQQJFhYJCQIACyADQfsAaw4DAggGBwsgBCACQQFqIgc2AhwgAEEGEA4MEQsgBCACQQFqNgIcIAAoAjQhDSABRQ0IIABBGxAOIABBBEEDIAAoAjAbEA4gAEEbEA4MCQsgACgCKARAIABB0C1BABA/DBQLIAItAAFBOmtBdkkNBSAEIAJBAWo2AjggBEE4akEBENQCGgJAIAQoAjgiAi0AACIFQSxHDQAgBCACQQFqNgI4IAItAAEiBUE6a0F2SQ0AIARBOGpBARDUAhogBCgCOC0AACEFCyAFQf8BcUH9AEcNBQwSCwJAIAItAAFBP0YEQEEDIQlBACENQQAhCEEAIQMCQAJAAkACQCACLQACIgZBOmsOBAADAQ8CCyAAIAJBA2o2AhggACgCNCENIAAgARCoAw0XIAQgACgCGDYCHCAQIQIgACAEQRxqQSkQpgNFDQ8MFwtBASEIQQQhCSACLQADIgZBPUYEQEEBIQMMDgtBASEDIAZBIUYNDSAEIAJBA2o2AhwgDyAEQRxqEKQEBEAgAEHr1QBBABA/DBcLIAAgDxCiBkEASgRAIABB1tUAQQAQPwwXCyAUIA8gDxA9QQFqEHIaIABBATYCPAwDCyAGQSFGDQwLIABB9jZBABA/DBQLIAQgAkEBajYCHCAUQQAQDgsgACgCNCINQf8BTgRAIABBtCdBABA/DBMLIAAgDUEBajYCNCAAKAIEIQIgACAYIA0Q1gIgACAEKAIcNgIYIAAgARCoAw0SIAQgACgCGDYCHCAAIBcgDRDWAiAAIARBHGpBKRCmA0UNCgwSCwJAAkACQAJAAkACQAJAIAItAAEiA0Ewaw4TAwQEBAQEBAQEBAoKCgoKCgoKAQALIANB6wBGDQEgA0HiAEcNCQsgAEERQRIgA0HiAEYbEA4gAkECaiEHDA8LAkAgAi0AAkE8RwRAQcHVACEFIAAoAigNASAAEKMEDQEMCQsgBCACQQNqNgI4IA8gBEE4ahCkBARAQevVACEFIAAoAigNASAAEKMEDQEMCQsgACAPEKIGIgZBAE4NAyAAIARBJGogDxChBiIGQQBODQNB0OkAIQUgACgCKA0AIAAQowRFDQgLIAAgBUEAED8MFQsgBCACQQJqNgIcIAItAAIhAyAAKAIoBEBBACEGIANBOmtBdkkNCCAAQYY8QQAQPwwVC0EAIQYgA0H4AXFBMEcNByAEIAJBA2o2AhwgA0EwayEGIAItAAMiA0H4AXFBMEcNByAEIAJBBGo2AhwgBkEDdCADakEwayEGDAcLIAQgAkEBaiIINgIcIARBHGpBABDUAiIGQQBOBEAgBiAAKAI0SA0CIAAQoAYgBkoNAgsgACgCKEUEQCAEIAg2AhwgCC0AACIGQTdNBEBBACEDIAZBM00EQCAEIAJBAmoiCDYCHCAGQTBrIQMgAi0AAiEGCyAGQfgBcUEwRwRAIAMhBgwJCyAEIAhBAWo2AhwgBkH/AXEgA0EDdGpBMGshBiAILQABIgJB+AFxQTBHDQggBCAIQQJqNgIcIAZBA3QgAmpBMGshBgwICyAEIAJBAmo2AhwMBwsgAEGzPEEAED8MEwsgBCAEKAI4NgIcCyAAKAI0IQ0gACgCBCECIAAgGSAGENYCDAkLIAAoAjQhDSABBEAgAEEbEA4LIARBOGogACgCQBDSAiAEIAJBAWoiBjYCTCACLQABQd4ARyIaRQRAIAQgAkECaiIGNgJMCwJAA0ACQAJAIAYtAABB3QBHBEAgACAEQSRqIgMgBEHMAGpBARCiBCICQQBIDQQCQAJAAkACQCAEKAJMIgYtAABBLUcNACAGLQABQd0ARg0AIAQgBkEBajYCICACQYCAgIAETwRAIAAoAihFDQEgAxCbAQwDCyAAIARBJGoiCCAEQSBqQQEQogQiA0EASA0IIANBgICAgARJDQEgCBCbASAAKAIoDQILIAJBgICAgARJDQIgBEE4aiAEKAIsIAQoAiQQlwYhHiAEQSRqEJsBIB5FDQYMBQsgBCAEKAIgIgY2AkwgAiADTQ0DCyAAQbTaAEEAED8MBQsgBEE4aiACIAIQnwZFDQMMAgsgACgCLARAIAAoAighEkEAIQdBACEJQQAhDiMAQdAAayIFJAAgBEE4aiILKAIQIQMgBSALKAIMIgI2AjQgBUEANgIwIAVCADcCKCAFIAI2AkggBUEANgJEIAVCADcCPCAFIAI2AiAgBUEANgIcIAVCADcCFCAFIAI2AgwgBUEANgIIIAVCADcCACAFIANBmwMgAxsiAjYCOCAFIAI2AkwgBSACNgIkIAUgAjYCECAFQShqIgJBBEEBIBIbEM8CIQMgBSgCMCEMAkACQCADDQAgBUE8aiAMIAUoAiggCygCCCALKAIAQQEQ7AENACACEJQCIR8gBSgCMCEMIB8NACAFIAwgBSgCKCALKAIIIAsoAgBBARDsAQ0AQbC0ggEhEUHBACEKQRohFSAFKAJEIRYgBSgCPCEbQX8hA0F/IQgCQANAIA4gG0kEQCAWIA5BAnRqIgIoAgAiByACKAIEIgIgAiAHSRshHANAIAcgHEcEQANAIAcgCiAVakkgByAKT3FFBEAgCUEBaiIJQfICTw0GIAlBAnRBoIACaigCACIRQQ92IQogEUEIdkH/AHEhFQwBCwsgByAJIBEgEhCcBiECAkAgA0F/RwRAIAIgCEYEQCAIIQIMAgsgBUEUaiADIAgQaRoLIAIhAwsgB0EBaiEHIAJBAWohCAwBCwsgDkECaiEODAELCwJAIANBf0YEQCAFKAIcIQcMAQsgBUEUaiADIAgQaSEgIAUoAhwhByAgDQILQQAhCiAHIAUoAhQiA0ECbUEIQZwDQQAQ1wFBACECA0AgAyAKSwRAIAcgCkECdGoiCCgCACEOIAgoAgQhCQNAAkAgCkECaiIKIANPDQAgByAKQQJ0aiIIKAIAIAlLDQAgCCgCBCIIIAkgCCAJSxshCQwBCwsgByACQQJ0aiIIIA42AgAgCCAJNgIEIAJBAmohAgwBCwtBACEJIAtBADYCACALIAcgAiAFKAIIIgogBSgCAEEAEOwBDQEgBSgCSCAWQQAgBSgCTBEBABogBSgCNCAMQQAgBSgCOBEBABogBSgCICAHQQAgBSgCJBEBABoMAgtB4YsBQe3sAEGTC0HlzgAQAAALIAUoAkggBSgCREEAIAUoAkwRAQAaIAUoAjQgDEEAIAUoAjgRAQAaIAUoAiAgB0EAIAUoAiQRAQAaQX8hCSAFKAIIIQoLIAUoAgwgCkEAIAUoAhARAQAaIAVB0ABqJAAgCQ0CCyAaRQRAIARBOGoQlAINAgsgACAEQThqIgIQngYNAyACEJsBIAQgBkEBajYCHCABRQ0JIABBGxAODAkLIARBOGogAiADEJ8GRQ0BCwsgABDVAgsgBEE4ahCbAQwQCyAAKAIoRQ0BIABB0C1BABA/DA8LIANBP0YNDQsgACAEQQhqIARBHGpBABCiBCIGQQBIDQ0LIAAoAjQhDSAAKAIEIQIgAQRAIABBGxAOCwJAIAZBgICAgAROBEAgACAEQQhqIgMQngYhISADEJsBICFFDQEMDgsgACgCLARAIAYgACgCKBDWASEGCyAGQf//A0wEQCAAQQEgBhChBAwBCyAAQQIgBhC3ARoLIAFFDQQgAEEbEA4MBAsgAEEEQQMgACgCMBsQDgsgECECDAILIAQgAkEBaiIHNgIcIABBBRAODAULIAIgCWohBUF/IQICQCAIDQAgACgCKA0AIAAoAjQhDSAQIQILIABBGEEXIAZBIUYbQQAQtwEhBiAAIAU2AhggACADEKgDDQggBCAAKAIYNgIcIAAgBEEcakEpEKYDDQggAEEKEA4gACgCDA0IIAAoAgAgBmogACgCBCAGa0EEazYAAAsgBCgCHCEHIAJBAEgNAwJAAkACQAJAAkAgBy0AACIDQSprDgIBAgALIANBP0YNAiADQfsARw0HIActAAFBOmtBdUsNAyAAKAIoRQ0HDAgLIAdBAWohB0EAIQtB/////wchCgwFC0EBIQsgBCAHQQFqIgc2AhxB/////wchCgwEC0EBIQogBCAHQQFqIgc2AhxBACELDAMLIAQgB0EBajYCHCAEQRxqQQEQ1AIiCyEKAkAgBCgCHCIDLQAAIgVBLEcNACAEIANBAWo2AhxB/////wchCiADLQABIgVBOmtBdkkNACAEQRxqQQEQ1AIiCiALSA0FIAQoAhwtAAAhBQsgBUH/AXFB/QBGDQEgACgCKA0BCyAEIAc2AhwMAgsgACAEQRxqQf0AEKYDDQUgBCgCHCEHCwJAAkAgBy0AAEE/RgRAIAQgB0EBaiIHNgIcIAAoAgQgAmshCUEAIQxBACEDDAELIAAoAgwhCAJAIApBAEwNACAIDQIgACgCBCACayEMIAAoAgAgAmohDkEAIQVBACEJA0AgBSAMSARAIAUgDmoiES0AACISQYCAAmotAAAhBkECIQMCQAJAAkACQCASQQFrDhYCAgICAwMGBgYGBgYGBgYGAwMGBgEABgtBAyEDCyARLwABIAN0IAZqIQYLIAlBAWohCQsgBSAGaiEFDAELCyAJQQBMDQAgAEEKEA4gACACQREQlgINAiAAKAIAIAJqQRw6AAAgACgCBCEGIAAoAgAgAmoiAyAJNgANIAMgCjYACSADIAs2AAUgAyAGIAJrQRFrNgABDAMLIAgNASAAKAIEIAJrIQkgACgCACACaiERQQAhBUEBIQgDQCAFIAlOBEBBASEMIAghAwwCCyAFIBFqIg4tAAAiEkGAgAJqLQAAIQZBASEMQQEhAwJAAkACQAJAIBJBAWsOGwICAgIDAwUFBQUDAwMFAwMDAwMDAAEFBQMFAwULIA4vAAFBAnQgBmohBgwBCyAOLwABQQN0IAZqIQYLQQAhCAsgBSAGaiEFDAALAAsgC0UEQCAAKAI0IA1HBEAgACACQQMQlgINAiAAKAIAIAJqQQ06AAAgACgCACACaiANOgABIAAoAgAgAmogAC0ANEEBazoAAiACQQNqIQILIApFBEAgACACNgIEDAMLIApB/////wdGIgZFIApBAUdxRQRAIAAgAiADQQVqEJYCDQIgACgCACACaiAMQQhyOgAAIAAoAgAgAmoiCCADQQF0QQVBACAGG2ogCWo2AAEgAwRAIAhBGToABSAAQRoQDgsgCkH/////B0cNAyAAQQcgAhCVAgwDCyAAIAIgA0EKahCWAg0BIAAoAgAgAmpBDzoAACAAKAIAIAJqIgYgDEEIcjoABSAGIAo2AAEgACgCACACaiIGIANBAXQgCWpBBWo2AAYgAwRAIAZBGToACiAAQRoQDgsgAEEOIAJBBWoQlQIgAEEQEA4MAgsgAyALQQFHIApB/////wdHcnJFBEAgACAMQQlzIAIQlQIMAgsgC0EBRwRAIAAgAkEFEJYCDQEgACgCACACakEPOgAAIAAoAgAgAmogCzYAASAAQQ4gAkEFaiICEJUCIABBEBAOCyAKQf////8HRgRAIAAoAgQhBiAAIAxBCHIgA0EBdCAJakEFahC3ARoCQCADBEAgAEEZEA4gACACIAkQ3wIgAEEaEA4MAQsgACACIAkQ3wILIABBByAGEJUCDAILIAogC0wNASAAQQ8gCiALaxC3ARogACgCBCEGIAAgDEEIciADQQF0IAlqQQVqELcBGgJAIAMEQCAAQRkQDiAAIAIgCRDfAiAAQRoQDgwBCyAAIAIgCRDfAgsgAEEOIAYQlQIgAEEQEA4MAQsgABDVAgwECyAAIAc2AhggAUUNASAAIAAoAgQiAiAQayIQIAJqELwBDQMgACgCACATaiIDIBBqIAMgAiATaxCrASAAKAIAIgMgE2ogAiADaiAQEB4aDAELCyAAQegYQQAQPwwBCyAAQdEfQQAQPwtBfyEdCyAEQdAAaiQAIB0LoggCCH4EfyMAQRBrIg0kACAEQcqeAWotAAAiD60hCgJAAkAgAykDACIGQv////9vWARAQoCAgIDgACEFIAAgDUEIaiAGEKQBDQJCACEGIABCgICAgDAgDSkDCCIIIAqGEPoCIgdCgICAgHCDQoCAgIDgAFENAgwBCwJAAkAgBqciDi8BBiICQRNrQf//A3FBAU0EQCAOKAIgIQ5CgICAgOAAIQUgACANIAMpAwgQpAENBCAOLQAEDQICQCANKQMAIgZBfyAPdEF/cyIPrYNQBEAgDigCACICrCIHIAZaDQELIABB/htBABBEDAULAkAgAykDECIIQoCAgIBwg0KAgICAMFEEQCACIA9xDQEgByAGfSAKiCEIDAMLIAAgDUEIaiAIEKQBDQUgDi0ABA0DIA40AgAgDSkDCCIIIAqGIAZ8Wg0CCyAAQbvHAEEAEEQMBAsgAkEVa0H//wNxQQpNBEAgACABIAYgBBD5AiEFDAQLQoCAgIDgACEFIAAgASAEEF4iCEKAgICAcINCgICAgOAAUQ0DQoCAgIAwIQECfgJAAkAgACAGQcwBIAZBABARIgxCgICAgHCDIgVCgICAgCBRIAVCgICAgDBRckUEQCAFQoCAgIDgAFENAkIAIQUCQCAAEDsiB0KAgICAcINCgICAgOAAUQRAQoCAgIDgACEBDAELQoCAgIDgACEBQoCAgIAwIQsCQCAAIAYgDBDkAyIJQoCAgIBwg0KAgICA4ABRDQBBACEEIAAgCUHrACAJQQAQESILQoCAgIBwg0KAgICA4ABRDQADQCAAIAkgCyANQQhqEJEBIgZCgICAgHCDQoCAgIDgAFENASANKAIIBEAgACAGEAwgACALEAwgACAJEAwgBK0hBSAHIQEMAwsgACAHIAStIAZBgIABEMgBQQBIDQEgBEEBaiEEDAALAAsgACALEAwgACAJEAwgACAHEAwLIAAgDBAMIAFCgICAgHCDQoCAgIDgAFINAQwCCyAAIA1BCGogBhAvDQEgDiAOKAIAQQFqNgIAIA0pAwghBSAGIQELIABCgICAgDAgBSAKhhD6AiIHQoCAgIBwg0KAgICA4ABRDQAgACAIIAdCACAFEOMDDQBBACEEA0AgCCAErSAFWQ0CGiAAIAEgBBCmASIHQoCAgIBwg0KAgICA4ABRDQEgACAIIAQgBxCGAiEQIARBAWohBCAQQQBODQALCyAAIAEQDCAIIQFCgICAgOAACyEFIAAgARAMDAMLIAMpAwAiB0IgiKdBdUkNASAHpyICIAIoAgBBAWo2AgAMAQsgABBfDAELIAAgASAEEF4iAUKAgICAcINCgICAgOAAUQRAIAAgBxAMDAELIAAgASAHIAYgCBDjA0UEQCABIQUMAQsgACABEAwLIA1BEGokACAFC9IEAgZ/AX4jAEEgayIFJAAgACgCACEEIAVCADcCGCAFQoCAgICAgICAgH83AhAgBSAENgIMIAVBDGoiBCABIAJBIGoiAUHmDxCqAyAEIAQgAyABQeYPEEAaAkAgBSgCFEH/////B0YEQCAAECoMAQsjAEEwayICJAACQCAFQQxqIgMgAEcEQCAAKAIAIQcgAkIANwIoIAJCgICAgICAgICAfzcCICACIAc2AhwCfyADKAIIIgZBAEgEQEF/QQAgAygCBBsMAQsgAkEcaiIEQSBBARCYAiAEIAMgBEEgQQIQiAEaIAJBGGogBEEAEO0BIAMoAgghBiACKAIYCyEIIAJBHGoiBCABIAZBACAGQQBKG2ogAUEBayABQQFqQQF2ELkEIgZuQQFqIgkgBmpBAXRqQRpqIgFBBhCYAiAEIAQgCKwgAUEAENgCIAQgAyAEIAFBABDuARogBEEAIAZrQQEQuQEaIAJCADcCECACQoCAgICAgICAgH83AgggAiAHNgIEIABCARAyGiAJrSEKA0AgCqdBAEoEQCACQQRqIgMgChAyGiADIAJBHGogAyABQQAQiAEaIAAgACADIAFBABBAGiAAIABCASABQQAQehogCkIBfSEKDAELC0EAIQMgBkEAIAZBAEobIQQgAkEEahAZIAJBHGoQGQNAIAMgBEcEQCAAIAAgACABQeAPEEAaIANBAWohAwwBCwsgACAIQeEPELkBGiACQTBqJAAMAQtB6e0AQdjsAEHUIUGzxAAQAAALCyAFQQxqEBkgBUEgaiQAQRALrwEBAn8jAEEgayIEJAAgACgCACEFIARBCGogA0EAEO0BIAAgASAEKAIIIgEgAUEfdSIBcyABayIBIAJBwAAgAUEBa2dBAXRrQQAgAUECTxtqQQhqIgJB4A8QrwMhASADKAIEBEAgBEIANwIYIARCgICAgICAgICAfzcCECAEIAU2AgwgBEEMaiIDQgEQMhogACADIAAgAkHgDxCIASABciEBIAMQGQsgBEEgaiQAIAELkAYCCH8BfiMAQfAAayIDJAAgACABRwRAIAAoAgAhBCADQgA3AmggA0KAgICAgICAgIB/NwJgIAMgBDYCXCADQdwAaiIFIAEQSRogA0IANwJUIANCgICAgICAgICAfzcCTCADIAQ2AkggAygCZCEGIANBADYCZCADQcgAaiIBQqrVqtUKEDIaIANBADYCUCAFIAEQrAIEQCADIAMoAmRBAWo2AmQgBkEBayEGCyADQcgAahAZIAJBAWpBAXYQuQQhBSADQgA3AlQgA0KAgICAgICAgIB/NwJMIAMgBDYCSCADQgA3AkAgA0KAgICAgICAgIB/NwI4IAMgBDYCNCADQdwAaiIBIAFCf0H/////A0EAEHoaIAVBACAFQQBKGyEJIAIgBWogAiAFQQF0bkEBaiIKQQF0akEgaiECQQAhAQNAIAEgCUZFBEAgA0HIAGoiByADQdwAaiIIQgEgAkEAEHoaIANBNGoiCyAHIAJBBhC1BCAHIAtCASACQQAQehogCCAIIAcgAkEAEIgBGiABQQFqIQEMAQsLIANCADcCLCADQoCAgICAgICAgH83AiQgAyAENgIgIANCADcCGCADQoCAgICAgICAgH83AhAgAyAENgIMIANBIGoiASADQdwAaiIEQgIgAkEAEHoaIAEgBCABIAJBABCIARogA0EMaiABIAEgAkEAEEAaIABCABAyGiAKrSEMA0AgDKdBAExFBEAgA0HIAGoiAUIBEDIaIANBNGoiBCAMQgGGQv7///8Pg0IBhBAyGiABIAEgBCACQQAQiAEaIAAgACABIAJBABC4ARogACAAIANBDGogAkEAEEAaIAxCAX0hDAwBCwsgACAAQgEgAkEAEHoaIAAgACADQSBqIgEgAkEAEEAaIAEQGSADQQxqEBkgA0E0ahAZ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C0KAgICAMCEFIAZCgICAgHCDQoCAgIAwUQ0DIAAgBkEBEJABGgwDC0KAgICAMCEJQoCAgIAwIQZCgICAgDAhBSAAIAQQICIHQoCAgIBwg0KAgICA4ABRDQILIAAgDUEIaiAHEC9BAEgNACANAn4gDSkDCCIEQoCAgIAIfEL/////D1gEQCAEQv////8PgwwBC0KAgICAwH4gBLm9IgVCgICAgMCBgPz/AH0gBUL///////////8Ag0KAgICAgICA+P8AVhsLIgg3AyAgACABQQEgDUEgahC/AyEFIAAgCBAMAkAgBUKAgICAcINCgICAgOAAUQ0AQgAhCCAEQgAgBEIAVRshDANAIAggDFENBCAAIAcgCBBsIgRCgICAgHCDQoCAgIDgAFENAQJAIA4EQCAEIQEMAQsgDSAENwMgIA0gCEL/////D4M3AyggACAKIAtBAiANQSBqEBwhASAAIAQQDCABQoCAgIBwg0KAgICA4ABRDQILIAAgBSAIIAEQeyERIAhCAXwhCCARQQBODQALCwwBC0KAgICAMCEFCyAAIAUQDEKAgICA4AAhBQsgACAHEAwgACAGEAwgACAJEAwgDUEwaiQAIAULDwAgACsDACABKwMAEMQECzkBAX5CgICAgMB+IAEpAwAiAkKAgICAwIGA/P8AfSACQv///////////wCDQoCAgICAgID4/wBWGwsRACAAKgIAuyABKgIAuxDEBAs7AQF+QoCAgIDAfiABKgIAu70iAkKAgICAwIGA/P8AfSACQv///////////wCDQoCAgICAgID4/wBWGwsZAQJ+IAEpAwAiAyAAKQMAIgRUIAMgBFZrCwwAIAAgASkDABCIBAsZAQJ+IAEpAwAiAyAAKQMAIgRTIAMgBFVrCwwAIAAgASkDABC/AgsXACABKAIAIgEgACgCACIASSAAIAFJaws9AQF+IAEoAgAiAEEATgRAIACtDwtCgICAgMB+IAC4vSICQoCAgIDAgYD8/wB9IAJCgICAgICAgPj/AFYbC9sFAwV/A34BfCMAQUBqIgUkAAJAAnwCQAJAAkACQAJAIAJBACABQoCAgIBwgyILQoCAgIAwUhsiAg4CAgABCwJAIAMpAwAiCUKAgICAcFQNACAJpyIELwEGQQpHDQAgBCkDICIKQiCIpyIEQQAgBEELakESSRsNACAAIAUg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IQULIAJBEGokACAFCx0AIAAgAUEAEGsiAEUEQEKAgICA4AAPCyAANQIoCz0BAX5CgICAgBAhASADKQMAIgRCgICAgHBaBH4gBKcvAQZBFWtB//8DcUEMSa1CgICAgBCEBUKAgICAEAsL7gMCBX4CfyMAQSBrIgokAEKAgICA4AAhBQJAIAAgASAEEFoiC0UNACALLQAEBEAgABBfDAELIAAgCkEYaiADKQMAQgAgCzQCACIGIAYQZg0AIAogBjcDECADKQMIIgdCgICAgHCDQoCAgIAwUgRAIAAgCkEQaiAHQgAgBiAGEGYNASAKKQMQIQYLIAopAxghCSAAIAFCgICAgDAQ/QEiB0KAgICAcIMiBUKAgICA4ABRBEAgByEFDAELIAYgCX0iBkIAIAZCAFUbIQgCQCAFQoCAgIAwUQRAIABCgICAgDAgCCAEEOUDIQUMAQsgCiAGQv////8HVwR+IAhC/////w+DBUKAgICAwH4gCLm9IgVCgICAgMCBgPz/AH0gBUL///////////8Ag0KAgICAgICA+P8AVhsLNwMIIAAgB0EBIApBCGoQowEhBSAAIAcQDCAAIAopAwgQDAsgBUKAgICAcINCgICAgOAAUQ0AAkAgACAFIAQQWiICRQ0AIAAgBSABEE0EQCAAQco0QQAQEgwBCwJAIAItAAQNACACNAIAIAhTBEAgAEHOwgBBABASDAILIAstAAQNACACKAIIIAsoAgggCadqIAinEB4aDAILIAAQXwsgACAFEAxCgICAgOAAIQULIApBIGokACAFC1EAIAAgASACEFoiAEUEQEKAgICA4AAPCyAAKAIAIgBBAE4EQCAArQ8LQoCAgIDAfiAAuL0iAUKAgICAwIGA/P8AfSABQoCAgICAgID4/wBWGwv/AwICfwF+AkACQAJAAkACQAJAIAFCgICAgHBaBEAgAaciAi8BBkErRg0BCyAEQQE2AgAMAQsgAigCICEGIARBATYCACAGDQELIABBsS1BABASDAELIAYoAgQhAgJAAkACQAJ/AkACQAJAAkAgBigCACIHQQFrDgQCAgcBAAsgBUUNAiAAIAYQyQQLQoCAgIAwIQEgBUEBaw4CAwQHCyADKQMAIgFCIIinQXVPBEAgAaciAyADKAIAQQFqNgIACwJAIAVBAkcNAEEBIQMgB0EBRw0AIAAgARCYASAGKAIEDAILIAIoAmQiAyAFrTcDACADQQhrIAE3AwAgAiADQQhqNgJkC0EAIQMgAgsiBSADNgIcIAZBAzYCACAAIAUQsQIhASAGQQE2AgAgBigCBCgCIARAIAAgBhDJBCABDwsgAUKAgICAEFoNBSACKAJkQQhrIgApAwAhCCAAQoCAgIAwNwMAIAFCAlEEQCAGQQI2AgAgBEECNgIAIAgPCyAEQQA2AgAgCA8LIAMpAwAiAUIgiKdBdUkNAyABpyIAIAAoAgBBAWo2AgAgAQ8LIAMpAwAiAUIgiKdBdU8EQCABpyICIAIoAgBBAWo2AgALIAAgARCYAQwBCyAAQY8tQQAQEgtCgICAgOAAIQELIAEPC0HW8QBBqOwAQaCUAUHEFBAAAAt3AQF+IAMpAwAiAUKAgICAcINCgICAgIB/UgRAIABBkcEAQQAQEkKAgICA4AAPC0KAgICAMCEEIAGnIgApAgRCgICAgICAgIBAg0KAgICAgICAgIB/UQR+IAAgACgCAEEBajYCACABQoCAgICQf4QFQoCAgIAwCws8AQF+QoCAgIDgACEBIAAgAykDABAlIgRCgICAgHCDQoCAgIDgAFIEfiAAIASnQQIQ5gMFQoCAgIDgAAsLVgIBfgF/IAAgARC7AyIBQoCAgIBwg0KAgICA4ABRBEAgAQ8LQoCAgIAwIQIgAaciAygCBEGAgICAeEcEQCAAIAAoAhAgAxDGAhApIQILIAAgARAMIAILCQAgACABELsDC1sBAX4jAEEQayICJAAgAiAAIAEQuwMiATcDCAJAIAFCgICAgHCDQoCAgIDgAFEEQCABIQQMAQsgAEKAgICAMEEBIAJBCGoQygQhBCAAIAEQDAsgAkEQaiQAIAQLLQBCgICAgOAAIAAgAykDACADKQMIQQAQiQIiAEEAR61CgICAgBCEIABBAEgbC6ABAQN+IAMpAwAiBSEEIAJBBE4EQCADKQMYIQQLIAVC/////29YBEAgABAiQoCAgIDgAA8LIAMpAxAhAUKAgICA4AAhBgJAIAAgAykDCBAwIgJFDQAgAUIgiKdBdU8EQCABpyIDIAMoAgBBAWo2AgALIAAgBSACIAEgBEEAENABIQMgACACEBAgA0EASA0AIANBAEetQoCAgIAQhCEGCyAGCyoAIAMpAwAiAUL/////b1gEQCAAECJCgICAgOAADwsgACABQQNBABCyAgtjAQF+IAMpAwAiBEL/////b1gEQCAAECJCgICAgOAADwtCgICAgOAAIQECQCAAIAMpAwgQMCICRQ0AIAAgBCACEG4hAyAAIAIQECADQQBIDQAgA0EAR61CgICAgBCEIQELIAELYwEDfgJAAkAgAykDACIBQv////9vWARAIAAQIgwBCyADKQMIIQUgASEEIAJBA04EQCADKQMQIQQLIAAgBRAwIgINAQtCgICAgOAADwsgACABIAIgBEEAEBEhBiAAIAIQECAGC2YBAX4gAykDACIEQv////9vWARAIAAQIkKAgICA4AAPC0KAgICA4AAhAQJAIAAgAykDCBAwIgJFDQAgACAEIAJBABDNASEDIAAgAhAQIANBAEgNACADQQBHrUKAgICAEIQhAQsgAQuaAQIBfwJ+IwBBEGsiBCQAIAMpAwghBSADKQMAIgYhAQJAAkACQAJAIAJBA0gNACADKQMQIgFCgICAgHBaBEAgAactAAVBEHENAQsgAEGdLEEAEBIMAQsgACAEQQxqIAUQ/QMiAg0BC0KAgICA4AAhAQwBCyAAIAYgASAEKAIMIgMgAhD+AiEBIAAgAiADEIYDCyAEQRBqJAAgAQt5AQF/IAFCgICAgHCDQoCAgIAwUgRAIABBnSxBABASQoCAgIDgAA8LAn4CQCACRQ0AIAMpAwAiAUKAgICAcINCgICAgDBRDQBCgICAgOAAIAAgARAlIgFCgICAgHCDQoCAgIDgAFENARogAachBAsgACAEQQMQ5gMLCxUAIAAgAykDACADIANBCGpBAhCIAws3ACMAQRBrIgIkACAAIAJBDGogAykDABB1IQAgAigCDCEDIAJBEGokAEKAgICA4AAgA2etIAAbC04AIwBBEGsiAiQAQoCAgIDgACEBAkAgACACQQxqIAMpAwAQdQ0AIAAgAkEIaiADKQMIEHUNACACKAIIIAIoAgxsrSEBCyACQRBqJAAgAQsGACAAtrsLfwAgACAAKQPQASIBQgyIIAGFIgFCGYYgAYUiAUIbiCABhSIBNwPQAUKAgICAwH4gAUKdurP7lJL9oiV+QgyIQoCAgICAgID4P4S/RAAAAAAAAPC/oL0iAUKAgICAwIGA/P8AfSABQv///////////wCDQoCAgICAgID4/wBWGwuIBAMFfAV/AX4jAEEQayIKJAAgCkIANwMIAkACQCACQQBMDQBCgICAgOAAIQEgACAKQQhqIAMpAwAQQg0BQQEhCyAKKwMIIQQgAkEBRwRAA0AgAiALRg0CIAAgCiADIAtBA3RqKQMAEEINAyALQQFqIQsgCisDACEFIwBBIGsiCSQAAkAgBJkiByAFmSIGIAe9IAa9VCIMGyIEvSIOQjSIpyINQf8PRg0AIAYgByAMGyEFAkAgDlANACAFvUI0iKciDEH/D0YNACAMIA1rQcEATgRAIAcgBqAhBAwCCwJ8IAxB/gtPBEAgBEQAAAAAAAAwFKIhBCAFRAAAAAAAADAUoiEFRAAAAAAAALBrDAELRAAAAAAAAPA/IA1BvARLDQAaIAREAAAAAAAAsGuiIQQgBUQAAAAAAACwa6IhBUQAAAAAAAAwFAshCCAJQRhqIAlBEGogBRCIBiAJQQhqIAkgBBCIBiAIIAkrAwAgCSsDEKAgCSsDCKAgCSsDGKCfoiEEDAELIAUhBAsgCUEgaiQADAALAAsgBJkhBAsgBL0iAQJ/IASZRAAAAAAAAOBBYwRAIASqDAELQYCAgIB4CyIAt71RBEAgAK0hAQwBC0KAgICAwH4gAUKAgICAwIGA/P8AfSABQv///////////wCDQoCAgICAgID4/wBWGyEBCyAKQRBqJAAgAQtOACAAIABEAAAAAAAA8L9EAAAAAAAA8D8gAEQAAAAAAAAAAGMbIAC9Qv///////////wCDQoCAgICAgID4/wBWGyAARAAAAAAAAAAAYRsLgwECAn4BfyAAvSIBQjSIp0H/D3EiA0H+B00EQCABQoCAgICAgICAgH+DIQIgA0H+B0cgAUKAgICAgICA8L9/UXJFBEAgAkKAgICAgICA+D+Evw8LIAK/DwsgA0GyCE0EfCABQj+HIAF8QgFBswggA2uthiIBQgGIfEIAIAF9g78FIAALC4IFAwJ8BX8CfiMAQRBrIgkkAAJ+QoCAgIDA/v/7/wBCgICAgMD+/3sgBBsgAkUNABoCfCADKQMAIgFC/////w9YBEBBASACIAJBAUwbIQogAachCEEBIQcDQCAHIApHBEAgCLcgAyAHQQN0aikDACIBQoCAgIAQWg0DGiAIIAGnIgsgCCALShsgCCALIAggC0gbIAQbIQggB0EBaiEHDAELCyAIrQwCC0KAgICA4AAgACAJQQhqIAEQQg0BGkEBIQcgCSsDCAshBSAHIAIgAiAHSBshAgNAIAIgB0cEQEKAgICA4AAgACAJIAMgB0EDdGopAwAQQg0CGgJAIAW9IgxC////////////AINCgICAgICAgPj/AFYNACAJKwMAIga9IgFC////////////AINCgICAgICAgPj/AFYEQCAGIQUMAQsgBUQAAAAAAAAAAGEgBkQAAAAAAAAAAGFxIQogBARAIAoEQCABIAyDvyEFDAILIAUgBSAGpSAGvUL///////////8Ag0KAgICAgICA+P8AVhsgBiAFvUL///////////8Ag0KAgICAgICA+P8AWBshBQwBCyAKBEAgASAMhL8hBQwBCyAFIAUgBqQgBr1C////////////AINCgICAgICAgPj/AFYbIAYgBb1C////////////AINCgICAgICAgPj/AFgbIQULIAdBAWohBwwBCwsgBb0iAQJ/IAWZRAAAAAAAAOBBYwRAIAWqDAELQYCAgIB4CyIAt71RBEAgAK0MAQtCgICAgMB+IAFCgICAgMCBgPz/AH0gAUL///////////8Ag0KAgICAgICA+P8AVhsLIQ0gCUEQaiQAIA0L4wECAX4CfyMAQRBrIgIkAAJAIAAgAUEpEFoiA0UEQCAEQQA2AgBCgICAgOAAIQEMAQtCgICAgDAhAQJAIAMpAwAiBkKAgICAcINCgICAgDBSBEAgAiADKAIMIgU2AgwgBSAGpyIHKAIEQf////8HcUkNASAAIAYQDCADQoCAgIAwNwMACyAEQQE2AgAMAQsgByACQQxqEMYBIQggAyACKAIMNgIMIARBADYCACAIQf//A00EQCAAIAhB//8DcRCUAyEBDAELIAAgByAFQQF0akEQakECEJIDIQELIAJBEGokACABC5EDAgN/An4jAEEgayICJABCgICAgOAAIQgCQCAAIAEQSiIBQoCAgIBwg0KAgICA4ABRDQAgACACQQhqIgVBBxA+GiAFQTwQPBogBSAEQQN0IgRB0OEBaigCACIGEIMBGiAEQdThAWooAgAiBARAIAVBIBA8GiAFIAQQgwEaIAVB2pEBEIMBGiAAIAMpAwAQSiIJQoCAgIBwg0KAgICA4ABRBEAgACABEAwgAigCCCgCECIAQRBqIAIoAgwgACgCBBEAAAwCCyAJpyIH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QdAAaiQAIAYLuAICA38DfiMAQSBrIgIkAEKAgICA4AAhBwJAAkACQCAAIAEQSiIBQoCAgIBwg0KAgICA4ABRDQAgACACIAMpAwAQ4wENACACKQMAIghCgICAgAhaBEAgAEHTGEEAEEQMAQsgCKciA0EBRg0BIAGnIgQpAgQiCaciBkH/////B3EiBUUNASAJQv////8HgyAIfkKAgICABFoEQCAAQeTIAEEAEDoMAQsgACACQQhqIAMgBWwgBkEfdhCZAw0AAkAgBUEBRwRAA0AgA0EATA0CIAJBCGogBEEAIAUQSxogA0EBayEDDAALAAsgAkEIagJ/IAQtAAdBgAFxBEAgBC8BEAwBCyAELQAQCyADEMsEGgsgACABEAwgAkEIahA3IQcMAgsgACABEAwMAQsgASEHCyACQSBqJAAgBwtYAQF+IAAgAykDABDkAUEAR61CgICAgBCEIQQgAUKAgICAcINCgICAgDBRBEAgBA8LIAAgAUEGEF4iAUKAgICAcINCgICAgOAAUgRAIAAgASAEEL0BCyABC8EBAgJ/An4jAEEQayIEJABCgICAgOAAIQYCQCAAIAEQSiIBQoCAgIBwg0KAgICA4ABRBEAgASEGDAELAkAgACAEQQxqIAMpAwAgAaciBSgCBEH/////B3EiAiACEFYNACAEIAI2AgggAykDCCIHQoCAgIBwg0KAgICAMFIEQCAAIARBCGogByACIAIQVg0BIAQoAgghAgsgACAFIAQoAgwiAyACIAMgAiADShsQjgEhBgsgACABEAwLIARBEGokACAGC8ABAgN/An4jAEEQayICJABCgICAgOAAIQcCQCAAIAEQSiIBQoCAgIBwg0KAgICA4ABRBEAgASEHDAELAkAgACACQQxqIAMpAwAgAaciBigCBEH/////B3EiBCAEEFYNACACIAQgAigCDCIFayIENgIIIAAgBiAFIAMpAwgiCEKAgICAcINCgICAgDBSBH8gACACQQhqIAggBEEAEFYNASACKAIIBSAECyAFahCOASEHCyAAIAEQDAsgAkEQaiQAIAcL0wECAn8CfiMAQRBrIgIkAEKAgICA4AAhBgJAIAAgARBKIgFCgICAgHCDQoCAgIDgAFEEQCABIQYMAQsCQCAAIAJBDGogAykDACABpyIFKAIEQf////8HcUEAEFYNACACIAUoAgRB/////wdxIgQ2AgggAykDCCIHQoCAgIBwg0KAgICAMFIEQCAAIAJBCGogByAEQQAQVg0BIAIoAgghBAsgACAFIAIoAgwiAyAEIAMgBEgbIAMgBCADIARKGxCOASEGCyAAIAEQDAsgAkEQaiQAIAYLoQUCC34DfyMAQRBrIgIkAAJAIAFCgICAgBCEQoCAgIBwg0KAgICAMFEEQCAAQZseQQAQEkKAgICA4AAhBwwBCyADKQMIIQQCQCADKQMAIgVCgICAgHCDIglCgICAgBCEQoCAgIAwUQ0AIAAgBUHRASAFQQAQESIGQoCAgIBwgyIHQoCAgIAgUSAHQoCAgIAwUXINACAHQoCAgIDgAFENASACIAQ3AwggAiABNwMAIAAgBiAFQQIgAhA2IQcMAQtCgICAgOAAIQdCgICAgDAhCCAAAn5CgICAgDAgACABECUiCkKAgICAcINCgICAgOAAUQ0AGkKAgICA4AAgABA7IgFCgICAgHCDQoCAgIDgAFENABoCQAJAIARCgICAgHCDQoCAgIAwUQRAIAJBfzYCAAwBCyAAIAIgBBB1QQBIDQELIAqnIgMpAgQhCyAAIAUQJSIIQoCAgIBwg0KAgICA4ABRDQACQCACKAIAIhBFDQBCACEGAkAgCUKAgICAMFENACAIpyIRKQIEQv////8HgyEFIAtC/////weDIgRQRQRAIAQgBX0gBVCtIgl9IQwgEK0hDUIAIQQDQAJAIAQgCXwiDiAMVQ0AIAMgESAOpxDMBCIPQQBIDQAgACADIASnIA8QjgEiBEKAgICAcINCgICAgOAAUQ0FIAAgASAGIARBABDIAUEASA0FIAUgD6x8IQQgBkIBfCIGIA1SDQEMBAsLIAZC/////w+DIQYgBKchDwwBCyAFUA0BCyAAIAMgDyALp0H/////B3EQjgEiBUKAgICAcINCgICAgOAAUQ0BIAAgASAGIAVBABDIAUEASA0BCyAAIAoQDCAAIAgQDCABIQcMAgsgAQsQDCAAIAoQDCAAIAgQDAsgAkEQaiQAIAcLoAMBBH4jAEEwayICJAAgAiABNwMoAkAgAUKAgICAEIRCgICAgHCDQoCAgIAwUQRAIABBmx5BABASQoCAgIDgACEGDAELAkAgAykDACIFQoCAgIAQhEKAgICAcINCgICAgDBRDQBCgICAgOAAIQYgACAFIAQgBUEAEBEiB0KAgICAcIMiCEKAgICA4ABRDQECQCAEQc4BRw0AIAAgBRDNBEEATg0AIAAgBxAMDAILIAhCgICAgBCEQoCAgIAwUQ0AIAAgByAFQQEgAkEoahA2IQYMAQsgAiAAIAEQJSIHNwMIQoCAgIDgACEGIAdCgICAgHCDQoCAgIDgAFENACACIAU3AxACQAJAAn8gBEHOAUcEQEKAgICAMCEBQQEMAQsgAEH2ywAQYCIBQoCAgIBwg0KAgICA4ABRDQEgAiABNwMYQQILIQMgACAAKQNIIAMgAkEQahCjASEFIAAgARAMIAVCgICAgHCDQoCAgIDgAFINAQsgACAHEAwMAQsgACAFIARBASACQQhqEKcCIQYgACACKQMIEAwLIAJBMGokACAGC4sDAgd/A34jAEEQayIGJAACQCAAIAEQSiIMQoCAgIBwg0KAgICA4ABRBEAgDCEBDAELAkAgACADKQMAEPYDIgUEQEKAgICA4AAhAUKAgICAMCENIAVBAEwNASAAQfrkAEEAEBIMAQtCgICAgOAAIQEgACADKQMAECUiDUKAgICAcINCgICAgOAAUQ0AIA2nIgcoAgQhCCAGIAynIgkoAgRB/////wdxIgVBACAEQQJGGzYCDAJAIAJBAkgNACADKQMIIg5CgICAgHCDQoCAgIAwUQ0AIAAgBkEMaiAOIAVBABBWDQELIAUgCEH/////B3EiBWshAiAGKAIMIQMCQAJAAkAgBA4CAgABCyACIANIIQpCgICAgBAhASADIQIgCkUNAQwCCyADIAVrIgMhAgtCgICAgBAhASADQQBIIAIgA0hyDQADQCAJIAcgA0EAIAUQvANFBEBCgYCAgBAhAQwCCyACIANHIQsgA0EBaiEDIAsNAAsLIAAgDBAMIAAgDRAMCyAGQRBqJAAgAQurAwMHfwJ+AXwjAEEQayIFJABCgICAgOAAIQwCQCAAIAEQSiIBQoCAgIBwg0KAgICA4ABRBEAgASEMDAELAkAgACADKQMAECUiDUKAgICAcINCgICAgOAAUQ0AIA2nIgkoAgRB/////wdxIQYgAaciCigCBEH/////B3EhBwJAIAQEQCAFIAcgBmsiCzYCDEF/IQhBACEEIAJBAkgNASAAIAUgAykDCBBCDQIgBSsDACIOvUL///////////8Ag0KAgICAgICA+P8AVg0BIA5EAAAAAAAAAABlBEAgBUEANgIMDAILIA4gC7djRQ0BIAUCfyAOmUQAAAAAAADgQWMEQCAOqgwBC0GAgICAeAs2AgwMAQsgBUEANgIMIAJBAk4EQCAAIAVBDGogAykDCCAHQQAQVg0CCyAHIAZrIQRBASEIC0L/////DyEMIAYgB0sNACAEIAUoAgwiA2sgCGxBAEgNAANAAkAgCiAJIANBACAGELwDBH8gAyAERw0BQX8FIAMLrSEMDAILIAMgCGohAwwACwALIAAgARAMIAAgDRAMCyAFQRBqJAAgDAv4AQICfgF/IwBBEGsiBiQAAkACQAJAIAJFBEAMAQsgAykDACIEQiCIp0F1TwRAIASnIgIgAigCAEEBajYCAAsgACAEEGUiBEKAgICAcIMiBUKAgICA4ABRDQEgBUKAgICA4H5SDQAgBKdBBGogBkEIahCxBCAAIAQQDEKAgICAwH4gBikDCCIEQoCAgIDAgYD8/wB9IARC////////////AINCgICAgICAgPj/AFYbIQQLIAFCgICAgHCDQoCAgIAwUQ0AIAAgAUEEEF4iAUKAgICAcINCgICAgOAAUQ0BIAAgASAEEL0BDAELIAQhAQsgBkEQaiQAIAELgwICAn4Df0KAgICA4AAhBAJAIAAgARBKIgFCgICAgHCDQoCAgIDgAFENACABpyIDEM4EIgJBAEgEQCABIQQMAQsgACADQRBqIAMoAgRB/////wdxEJIDIQUgACABEAwgBUKAgICAcINCgICAgOAAUQ0AIAWnIgZBEGohAwNAIAYoAgRB/////wdxIgAgAkwEQCAFDwUCQCADIAJBAXRqIgcvAQAiCEGA8ANxQYCwA0YEQAJAIAhB/7cDSw0AIAAgAkEBaiIATA0AIAMgAEEBdGovAQBBgEBrQf//A3FB//cDSw0CCyAHQf3/AzsBAAsgAiEACyAAQQFqIQIMAQsACwALIAQLTAIBfgF/QoCAgIDgACEEIAAgARBKIgFCgICAgHCDQoCAgIDgAFIEfiABpxDOBCEFIAAgARAMIAVBH3atQoCAgIAQhAVCgICAgOAACwuSAQIBfgJ/IwBBEGsiAiQAQoCAgIDgACEEAkAgACABEEoiAUKAgICAcINCgICAgOAAUQRAIAEhBAwBCwJAIAAgAkEMaiIFIAMpAwAQswENAEKAgICAMCEEIAIoAgwiA0EASA0AIAMgAaciBigCBEH/////B3FPDQAgBiAFEMYBrSEECyAAIAEQDAsgAkEQaiQAIAQLaQICfwF+IAAgARBKIQEDQCACIARMIAFCgICAgHCDQoCAgIDgAFFyRQRAIAMgBEEDdGopAwAiBkIgiKdBdU8EQCAGpyIFIAUoAgBBAWo2AgALIARBAWohBCAAIAEgBhC2AiEBDAELCyABC7gBAgJ+AX8jAEEQayICJABCgICAgOAAIQQCQCAAIAEQSiIBQoCAgIBwg0KAgICA4ABRBEAgASEEDAELAkAgACACQQxqIAMpAwAQswENAEKAgICAwH4hBCACKAIMIgNBAEgNACADIAGnIgYpAgQiBadB/////wdxTw0AIAZBEGohBiAFQoCAgIAIg1BFBEAgBiADQQF0ajMBACEEDAELIAMgBmoxAAAhBAsgACABEAwLIAJBEGokACAEC/QBAgF+AX8jAEEQayICJABCgICAgOAAIQUCQCAAIAEQSiIBQoCAgIBwg0KAgICA4ABRBEAgASEFDAELAkAgACACQQxqIAMpAwAQswENACABpyEGIARFIAIoAgwiA0EATnJFBEAgBigCBEH/////B3EgA2ohAwsCQCADQQBOBEAgAyAGKQIEIgWnQf////8HcUkNAQtCgICAgDAhBSAEDQEgAEEvECkhBQwBCyAGQRBqIQQgAAJ/IAVCgICAgAiDUEUEQCAEIANBAXRqLwEADAELIAMgBGotAAALQf//A3EQlAMhBQsgACABEAwLIAJBEGokACAFC8wCAgJ/B34jAEEgayIEJAAgACAEQQhqQQAQPhpCgICAgOAAIQlCgICAgDAhBgJAAkACQCAAIAMpAwAQICIHQoCAgIBwg0KAgICA4ABRDQAgACAAIAdB8QAgB0EAEBEQyQUiBkKAgICAcINCgICAgOAAUQ0AIAAgBCAGEC9BAEgNAEIAIQEgBCkDACIIQgAgCEIAVRshCiAIQgF9IQggAqwhCwNAIAEgClENAiAAIAAgBiABEGwQNCIMQoCAgIBwg0KAgICA4ABRDQEgBEEIaiIFIAwQhAEaIAEgCFkhAiABQgF8IQEgASALWSACcg0AIAUgAyABp0EDdGopAwAQjQFFDQALCyAAIAcQDCAAIAYQDCAEKAIIKAIQIgBBEGogBCgCDCAAKAIEEQAADAELIAAgBxAMIAAgBhAMIARBCGoQNyEJCyAEQSBqJAAgCQuFAgMDfwF8AX4jAEEgayIEJAACfgJAIAAgBCACED4NACACQQAgAkEAShshBgJAA0AgBSAGRwRAAkAgAyAFQQN0aikDACIBQv////8PWARAIAGnIgJB///DAE0NAQwECyAAIARBGGogARBCDQQgBCsDGCIHRAAAAAAAAAAAYyAHRAAAAAD//zBBZHINAyAHAn8gB5lEAAAAAAAA4EFjBEAgB6oMAQtBgICAgHgLIgK3Yg0DCyAFQQFqIQUgBCACELEBRQ0BDAMLCyAEEDcMAgsgAEGGGUEAEEQLIAQoAgAoAhAiAEEQaiAEKAIEIAAoAgQRAABCgICAgOAACyEIIARBIGokACAIC54BAgJ/AX4jAEEgayIEJAAgACAEQQhqIAIQPhogAkEAIAJBAEobIQICfgNAIAIgBUcEQAJAIAAgBEEEaiADIAVBA3RqKQMAEHVFBEAgBEEIaiAELwEEEIcBRQ0BCyAEKAIIKAIQIgBBEGogBCgCDCAAKAIEEQAAQoCAgIDgAAwDCyAFQQFqIQUMAQsLIARBCGoQNwshBiAEQSBqJAAgBguuJwMOfwx+AnwjAEHQAWsiByQAQbDUBCgCAARAAn9BgAgQjwIiDCEAQcMRQSsQnwMhAQJAAkBB5e0AQcMRLAAAEJ8DRQRAQcTUBEEcNgIADAELIABBAXJFBEBBxNQEQTA2AgAMAQtBsAlBsBEgABsQjwIiAw0BC0EADAELIANBAEGkARAsGiADQX82AlAgA0F/NgI8IAMgA0GQAWo2AlQgA0GACDYCMCADIANBrAFqNgIsIABFBEAgA0GsCWoiAEEAQYAIECwaCyADQYAINgKYASADIAA2ApwBIANBwxEsAAA2AqABIAFFBEAgA0EIQQRBwxEtAABB8gBGGzYCAAsCQAJAQcMRLQAAIgJB4QBHBEAgAkHyAEcNASADQYAINgKUAQwCCyADIABBgAgQhgYiADYClAEgAyAANgKQAQwBCyABRQ0AIABBADoAAAsgA0GdAzYCKCADQZ4DNgIkIANBnwM2AiAgA0GgAzYCDEHd1AQtAABFBEAgA0F/NgJMCyADQZjVBCgCACIANgI4IAAEQCAAIAM2AjQLQZjVBCADNgIAIAMLIQNBsNQEKAIAIQkjAEFAaiIAJAAgAEEAQcAAECwhBCAHQQBB0AEQLCIAIAk1AhA3AxggACAJNQIUNwMAIAk1AhghDiAAQgI3AyAgACAONwMIIAAgCSgCQEEDdEHAAmqtNwMQIAlBzABqIQEgCUHIAGohCgNAIAogASgCACIGRwRAIAYoAhAhASAAIAApAyBCAnw3AyAgACAAKQMQIAkoAkBBA3RB+AFqrXw3AxAgACAAKQPAASAGMwEIfDcDwAEgACAAKQPIASAGNAIMfDcDyAECQCABRQ0AIAEtABANACABKAIYIQIgACAAKQNoQgF8NwNoIAAgACkDcCACQQJ0IAEoAhxBA3RqQTRqrXw3A3ALIAZB0AFqIQEgBkHMAWohCwNAIAsgASgCACICRwRAIAAgACkDICIQQgF8Ig83AyAgACAAKQMQQrgBfCIONwMQIAIoAggEQCAAIBBCAnwiDzcDICAAIA4gAigCDEEDdK18Ig43AxALAkAgAigCFEUNACAAIA9CAXw3AyAgACAOIAIoAhgiBUEUbK18NwMQQQAhAQNAIAEgBU4NAQJAIAIoAhQgAUEUbGoiCCgCCA0AIAgoAgRFDQAgACAAKQMgQgF8NwMgIAgoAgQpAxggBBCZASACKAIYIQULIAFBAWohAQwACwALIAIoAiAEQCAAIAApAyBCAXw3AyAgACAAKQMQIAIoAiRBAnStfDcDEAsgAigCLARAIAAgACkDIEIBfDcDICAAIAApAxAgAigCMEEMbK18NwMQCyACKQM4IAQQmQEgAikDQCAEEJkBIAJBBGohAQwBCwsgBkEEaiEBDAELCyAJQdQAaiEBIAlB0ABqIQoDQCAKIAEoAgAiAkcEQAJAAkACQCACQQRrLQAAQQ9xDgIBAAILIAIoAhgEfyACLwEiIAIvASBqQQR0QUBrBUHAAAshBSACKAIsBEBBACEBIAIoAjAiCCEGA0AgASAGSARAIAIoAiwgAUEDdGopAwAgBBCZASABQQFqIQEgAigCMCEGDAELCyAIQQN0IAVqIQULIAIoAhwEQCACKAI0QQN0IAVqIQULAkAgAi8ACSIBQYAgcQ0AIAIoAgxFDQAgBCAEKQMoIAI0AhB8NwMoCwJ/QQAgAUGACHFFDQAaAn8gAigCTEUEQCAFQRhqIQVBAAwBCyAFIAIoAkBqQRlqIQVBAQsiASACKAJEIgZFDQAaIAQgBCkDMEIBfDcDMCAEIAQpAzggBqx8NwM4IAFBAWoLIQEgBCAEKQMYQgF8NwMYIAQgBCsDICAFt6A5AyAgBCAEKwMAIAG3oDkDAAwBCyACKAIIIQggACAAKQNIQgF8NwNIAkAgAigCDEUNACAAIAApAyBCAXw3AyAgACAAKQNgIAgoAhxBA3StfDcDYCAAIAApA1ggCCgCICIFrHw3A1ggCEEwaiEBQQAhBgNAIAUgBkwNAQJAIAEoAgRFDQAgASgCAEH/////A0sNACACKAIMIAZBA3RqKQMAIAQQmQEgCCgCICEFCyAGQQFqIQYgAUEIaiEBDAALAAsgCC0AEEUEQCAIKAIYIQEgACAAKQNoQgF8NwNoIAAgACkDcCABQQJ0IAgoAhxBA3RqQTRqrXw3A3ALAkACQAJAAkACQAJAAkACQAJAAkAgAkECay8BAEECaw4gAAkBAQEBAAkBCQIDBAUJBwYICAkJCQkJCQkJCQkJCQEJCyAAIAApA6gBQgF8NwOoASACQQNrLQAAQQhxRQ0JIAAgACkDsAFCAXw3A7ABIAIoAhxFDQkgACAAKQMgQgF8NwMgIAAgACkDECACKAIgQQN0rXw3AxAgACAAKQO4ASACNQIgfDcDuAFBACEBA0AgASACKAIgTw0KIAIoAhwgAUEDdGopAwAgBBCZASABQQFqIQEMAAsACyACKQMYIAQQmQEMCAsgACAAKQOgAUIBfDcDoAEMBwsgAigCHCILRQ0GIAIoAhghCCAAIAApAyBCAXw3AyAgACAAKQOAASAIKAI8IgVBAnStfDcDgAFBACEBA0AgASAFTg0HAkAgCyABQQJ0aigCACIGRQ0AIAACfkQAAAAAAADwPyAGKAIAtyIaoyAAKQMguaAiG5lEAAAAAAAA4ENjBEAgG7AMAQtCgICAgICAgICAfws3AyAgAAJ+RAAAAAAAAERAIBqjIAApA4ABuaAiGplEAAAAAAAA4ENjBEAgGrAMAQtCgICAgICAgICAfws3A4ABIAYoAhAiDSAGQRhqRw0AIA0pAwAgBBCZASAIKAI8IQULIAFBAWohAQwACwALIAIoAhgiBUEYaiEGQQAhAQNAIAUoAhAiCCABSgRAIAYgAUEDdGopAwAgBBCZASABQQFqIQEMAQsLIAAgACkDIEIBfDcDICAAIAApAxAgCEEDdEEYaq18NwMQDAULIAIoAhgiBUUNBCAFQQhqIQZBACEBA0AgBS0ABSIIIAFLBEAgBiABQQN0aikDACAEEJkBIAFBAWohAQwBCwsgACAAKQMgQgF8NwMgIAAgACkDECAIrUIDhnxCCHw3AxAMBAsgAigCGCAEEIwEIAIoAhwgBBCMBAwDCyACKAIYIgFFDQIgASkDACAEEJkBIAAgACkDIEIBfDcDICAAIAApAxBCGHw3AxAMAgsgAigCGCIBRQ0BIAAgACkDICIOQgF8NwMgIAAgACkDEEIcfCIPNwMQIAEoAghFDQEgACAOQgJ8NwMgIAAgDyABNAIAfDcDEAwBCyACKAIYRQ0AIAAgACkDIEIBfDcDIAsgAkEEaiEBDAELCyAAIAApA1AgACkDSCIPQjB+fCIQNwNQIAAgACkDECAJKALYASIBQQJ0rXwiETcDEEEAIQYgAUEAIAFBAEobIQIgACkDICEOA0AgAiAGRwRAIAkoAuABIAZBAnRqIQEDQCABKAIAIgEEQCABKAIYIQUgACAAKQNoQgF8NwNoIAAgACkDcCAFQQJ0IAEoAhxBA3RqQTRqrXw3A3AgAUEoaiEBDAELCyAGQQFqIQYMAQsLIAAgDkIDfCISNwMgIAAgCSgCKCIFrDcDKCAAIAkoAiwiAiAJKAIkakECdK0iDjcDMEEAIQEgAkEAIAJBAEobIQYDQCABIAZHBEAgCSgCOCABQQJ0aigCACICQQFxRQRAIAAgDiACKAIEIgJBH3UgAkH/////B3EgAkEfdnRqQRFqrXwiDjcDMAsgAUEBaiEBDAELCyAAAn4gBCsDCBCgAyIamUQAAAAAAADgQ2MEQCAasAwBC0KAgICAgICAgIB/CyITNwM4IAACfiAEKwMQEKADIhqZRAAAAAAAAOBDYwRAIBqwDAELQoCAgICAgICAgH8LIhQ3A0AgACAEKQMYIhU3A3ggAAJ+IAQrAyAQoAMiGplEAAAAAAAA4ENjBEAgGrAMAQtCgICAgICAgICAfwsiFjcDgAEgACAEKQMoIhc3A4gBIAAgBCkDMCIYNwOQASAAIAQpAzgiGTcDmAEgBCsDACEaIAAgACkDcCAAKQNgIBkgFyAQIBF8IBR8IBZ8fHwgDnx8fDcDECAAAn4gGhCgAyAFt6AgE7mgIA+5oCAAKQNouaAgFbmgIBi5oCASuaAiGplEAAAAAAAA4ENjBEAgGrAMAQtCgICAgICAgICAfws3AyAgBEFAayQAQbDUBCgCACECQQAhAUEAIQYjAEHABmsiACQAIAAgBzQCCDcDmAQgAEEgNgKQBCADQamWASAAQZAEahCaASACBEAgAkEQaiEFA0AgAUEFRwRAIAUgAUEDdCIIQeSbAWooAgAiBCACKAIAEQMAIgkEQCAEIAkgAigCDBEFACIKTQRAIAAgCEHgmwFqKAIANgKIBCAAIAQ2AoAEIAAgCiAEazYChAQgA0HrkgEgAEGABGoQmgFBASEGCyAFIAkgAigCBBEAAAsgAUEBaiEBDAELCyAGRQRAQf2SAUEhIAMQiQYLIABB4ARqQQBB3AEQLBogAkHUAGohASACQdAAaiEEA0AgBCABKAIAIgFHBEAgAUEEay0AAEEPcUUEQCAAQeAEakE2IAFBAmsvAQAiBSAFQTZPG0ECdGoiBSAFKAIAQQFqNgIACyABQQRqIQEMAQsLQbiSAUESIAMQiQYgACgC4AQiAQRAIABBi9MANgL4AyAAQQA2AvQDIAAgATYC8AMgA0HakgEgAEHwA2oQmgELQQEhAQNAIAFBNkcEQAJAIABB4ARqIAFBAnRqKAIAIgRFDQAgASACKAJATg0AIAAgAiAAQaAEaiACKAJEIAFBGGxqKAIEEOUFNgLoAyAAIAE2AuQDIAAgBDYC4AMgA0HakgEgAEHgA2oQmgELIAFBAWohAQwBCwsgACgCuAYiAQRAIABBxTM2AtgDIABBADYC1AMgACABNgLQAyADQdqSASAAQdADahCaAQsCQAJAIAMoAkwiAUEATgRAIAFFDQFBtNUEKAIAIAFB/////wNxRw0BCwJAIAMoAlBBCkYNACADKAIUIgEgAygCEEYNACADIAFBAWo2AhQgAUEKOgAADAILIAMQigYMAQsgAyADKAJMIgFB/////wMgARs2AkwCQAJAIAMoAlBBCkYNACADKAIUIgEgAygCEEYNACADIAFBAWo2AhQgAUEKOgAADAELIAMQigYLIAMoAkwaIANBADYCTAsLIABB2/gANgLIAyAAQdDxADYCxAMgAEH0+AA2AsADIANBy5IBIABBwANqEJoBIAcpAxgiDlBFBEAgACAHKQMAIg83A7ADIAAgDjcDqAMgACAPuSAOuaM5A7gDIABBwecANgKgAyADQf+UASAAQaADahCqASAHKQMgIQ4gBykDACEQIAcpAxAhDyAAQQg2AogDIAAgDzcDgAMgACAQIA99uSAOuaM5A5ADIAAgDjcD+AIgAEHS5wA2AvACIANBpZUBIABB8AJqEKoBCyAHKQMoIg5QRQRAIAAgBykDMCIPNwPgAiAAIA43A9gCIAAgD7kgDrmjOQPoAiAAQdUlNgLQAiADQdqUASAAQdACahCqAQsgBykDOCIOUEUEQCAAIAcpA0AiDzcDwAIgACAONwO4AiAAIA+5IA65ozkDyAIgAEG5JjYCsAIgA0HclQEgAEGwAmoQqgELIAcpA0giDlBFBEAgACAHKQNQIg83A6ACIAAgDjcDmAIgACAPuSAOuaM5A6gCIABBiyI2ApACIANBipQBIABBkAJqEKoBIAcpA1ghDiAHKQNIIQ8gACAHKQNgNwOAAiAAIA65IA+5ozkDiAIgACAONwP4ASAAQd4oNgLwASADQYqUASAAQfABahCqASAHKQNoIQ4gACAHKQNwIg83A+ABIAAgD7kgDrmjOQPoASAAIA43A9gBIABBxic2AtABIANBg5YBIABB0AFqEKoBCwJAIAcpA3giDlANACAAIAcpA4ABNwPAASAAIA43A7gBIABB/iQ2ArABIANBrJMBIABBsAFqEJoBIAcpA3ghDiAAIAcpA4gBIg83A6ABIAAgD7kgDrmjOQOoASAAIA43A5gBIABBrtwANgKQASADQbGUASAAQZABahCqASAHKQOQASIOUA0AIAAgBykDmAEiDzcDgAEgACAONwN4IAAgD7kgDrmjOQOIASAAQbzTADYCcCADQbGUASAAQfAAahCqAQsgBykDoAEiDlBFBEAgACAONwNoIABBkSU2AmAgA0GfkwEgAEHgAGoQmgELAkAgBykDqAEiDlANACAAIA43A1ggAEHMIDYCUCADQZ+TASAAQdAAahCaASAHKQOwASIOUA0AIAAgDjcDSCAAQcUgNgJAIANBn5MBIABBQGsQmgEgBykDsAEhDyAAIAcpA7gBIg5CA4Y3AzAgACAOuSAPuaM5AzggACAONwMoIABB4CE2AiAgA0HfkwEgAEEgahCqAQsgBykDwAEiDlBFBEAgACAHKQPIATcDECAAIA43AwggAEGEIjYCACADQayTASAAEJoBCyAAQcAGaiQAIAMoAkwaIAMQogMaIAMgAygCDBEFABogAy0AAEEBcUUEQCADKAI4IQAgAygCNCIBBEAgASAANgI4CyAABEAgACABNgI0CyADQZjVBCgCAEYEQEGY1QQgADYCAAsgAygCYBDUASADENQBCyAMEAogDBDUAQsgB0HQAWokAAsJACAAIAEQzwQLLAAgACABEM8EIgFCgICAgHCDQoCAgIDgAFIEfiAAQQNBAiABpxsQKQUgAQsLkAECAXwBfiMAQRBrIgIkAAJ+IAMpAwAiAUIgiKciAwRAQoCAgIAQIANBC2pBEkkNARoLQoCAgIDgACAAIAJBCGogARBCDQAaIAIrAwgiBJlE////////P0NlIAS9QoCAgICAgID4/wCDQoCAgICAgID4/wBSIAScIARhcXGtQoCAgIAQhAshBSACQRBqJAAgBQsmAEKAgICA4AAgACADKQMAENkFIgBBAEetQoCAgIAQhCAAQQBIGwsvAQF+An4gAygCBCICBEBCgICAgBAiBCACQQtqQRJJDQEaCyAAIAQgAyADENIECwsvAQF+An4gAygCBCICBEBCgICAgBAiBCACQQtqQRJJDQEaCyAAIAQgAyADENMECwsJACAAIAEQngILowECAn4BfyMAQRBrIgIkAAJ+IAAgARCeAiIFQoCAgIBwg0KAgICA4ABRBEAgBQwBC0EKIQcCQAJAIAQNACADKQMAIgFCgICAgHCDQoCAgIAwUQ0AIAAgARDbBCIHQQBIDQELQoCAgIDgACAAIAJBCGogBRBtDQEaIAAgAisDCCAHQQBBABC6AgwBCyAAIAUQDEKAgICA4AALIQYgAkEQaiQAIAYLkAICAX4BfCMAQRBrIgIkAEKAgICA4AAhBAJAIAAgARCeAiIBQoCAgIBwg0KAgICA4ABRBEAgASEEDAELIAAgAiABEG0NAAJAAkAgAykDACIBQoCAgIBwg0KAgICAMFEEQCACKwMAIgW9IQEMAQsgACACQQxqIAEQswENAiACKwMAIgW9IgFCgICAgICAgPj/AINCgICAgICAgPj/AFINAQsgAEKAgICAwH4gAUKAgICAwIGA/P8AfSAFvUL///////////8Ag0KAgICAgICA+P8AVhsQNCEEDAELIAIoAgwiA0HlAGtBm39NBEAgAEHrIUEAEEQMAQsgACAFQQogA0EBELoCIQQLIAJBEGokACAEC80BAgF+AnwjAEEQ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IAQgCjcDACAEQQhqIQQgCEIBfCEIDAELCyAJIAx8IQgDQCAIIAtZDQIgBiAIp0EDdGopAwAiCUIgiKdBdU8EQCAJpyIDIAMoAgBBAWo2AgALIAQgCTcDACAEQQhqIQQgCEIBfCEIDAALAAsDQAJAIAkgClEEQCADQRBqIQNCACEJA0AgCSAPUQ0CIAMgCadBA3RqKQMAIhBCIIinQXVPBEAgEKciBiAGKAIAQQFqNgIACyAEIBA3AwAgBEEIaiEEIAlCAXwhCQwACwALIAAgDiAJIAQQVEF/Rg0DIARBCGohBCAJQgF8IQkMAQsLIAogDHwhCQNAIAkgC1kNASAAIA4gCSAEEFRBf0YNAiAEQQhqIQQgCUIBfCEJDAALAAsgAiAERgRAIAFCgICAgDAgACABQTAgDUKAgICACFoEfkKAgICAwH4gDbm9IghCgICAgMCBgPz/AH0gCEL///////////8Ag0KAgICAgICA+P8AVhsFIA0LEDlBAEgiAxshC0KAgICA4AAgASADGyEIIAIhBAwDC0GJFkGo7ABB4rkCQfHqABAAAAsgASELDAELQQAhAkKAgICAMCELCwNAIAIgBEZFBEAgBEKAgICAMDcDACAEQQhqIQQMAQsLIAAgCxAMIAAgDhAMIAVBMGokACAIC8gIAgl+A38jAEEwayIOJABCgICAgDAhBQJAAkAgACAOQSBqIAAgARAgIgoQLw0AIAAgDkEYaiADKQMAQgAgDikDICIGIAYQZg0AAkAgBARAAkACQAJAIAIOAgIAAQsgBiAOKQMYfSEHQQAhAgwBCyAAIA5BEGogAykDCEIAIAYgDikDGH1CABBmDQMgAkECayECIA4pAxAhBwsgBiACrXwgB31CgICAgICAgBBTDQEgAEH0yABBABASDAILIA4gBjcDECAGIQEgAykDCCINQoCAgIBwg0KAgICAMFIEfiAAIA5BEGogDUIAIAEgARBmDQIgDikDEAUgAQsgDikDGH0iAUIAIAFCAFUbIQdBACECCyAAIAogB0KAgICACHxC/////w9YBH4gB0L/////D4MFQoCAgIDAfiAHub0iAUKAgICAwIGA/P8AfSABQv///////////wCDQoCAgICAgID4/wBWGwsiBRCfAiEBIAAgBRAMAkAgAUKAgICAcINCgICAgOAAUQ0AIA4pAxgiDSAH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AiAAIAFBNyABQQAQESIBQoCAgIBwg0KAgICAMFEEfiAAQS8QKQUgAQtBnggQsgELC+EFAwN+B38DfAJAIAAgARBVDQAgACAAKQMwQQ4QRyIFQoCAgIBwg0KAgICA4ABRDQAgBaciCSABQoCAgIBwWgR/IAGnLQAFQRBxBUEACyAJLQAFQe8BcXI6AAUCQCAAQQEgAiACQQFMGyIKQQFrIghBA3RBGGoQJCIHRQ0AIAFCIIinQXVPBEAgAaciAiACKAIAQQFqNgIACyAHIAE3AwAgAykDACIEQiCIp0F1TwRAIASnIgIgAigCAEEBajYCAAsgByAINgIQIAcgBDcDCCAHQRhqIQtBACECA0AgAiAIRwRAIAMgAkEBaiIMQQN0aikDACIEQiCIp0F1TwRAIASnIg0gDSgCAEEBajYCAAsgCyACQQN0aiAENwMAIAwhAgwBCwsgCSAHNgIgAn8gAUL/////b1gEQCAAECJBfwwBCyAAQQAgAadBMBBDCyICQQBIDQACQCACRQ0AIAAgAUEwIAFBABARIgRCgICAgHCDQoCAgIDgAFENASAEQv////8PWARAIASnIgIgCGtBACACIApOG60hBgwBCyAEQiCIp0EHa0FtTQRAAkAgBEKAgICAwIGA/P8AfCIEQv///////////wCDQoCAgICAgID4/wBWDQAgBL+dIg8gCLciEGUNACAPIBChIQ4LIA69IgQCfyAOmUQAAAAAAADgQWMEQCAOqgwBC0GAgICAeAsiAre9UQRAIAKtIQYMAgtCgICAgMB+IARCgICAgMCBgPz/AH0gBEL///////////8Ag0KAgICAgICA+P8AVhshBgwBCyAAIAQQDAsgACAFQTAgBkEBEBUaIABBgJIBIAAgAUE3IAFBABARIgFCgICAgHCDIgRCgICAgJB/UgR+IARCgICAgOAAUQ0BIAAgARAMIABBLxApBSABC0HslgEQsgEiAUKAgICAcINCgICAgOAAUQ0AIAAgBUE3IAFBARAVGiAFDwsgACAFEAwLQoCAgIDgAAswACACQQBMBEAgACABQoCAgIAwQQBBABAcDwsgACABIAMpAwAgAkEBayADQQhqEBwLgwICAX4BfyMAQSBrIgIkAEKAgICA4AAhBQJAAkAgACABECAiAUKAgICAcINCgICAgOAAUQ0AIAAgAykDABAw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ARAgCzYAIAMpAwAiAUIgiKciAkF/RiAERSACQX5xQQJHcXJFBEAgABAiQoCAgIDgAA8LIAAgARDoAQuJAQEBfiADKQMAIgFC/////29WIAFCgICAgHCDQoCAgIAgUXJFBEAgAEHe0gBBABASQoCAgIDgAA8LAkAgACABEEEiAUKAgICAcINCgICAgOAAUgRAIAMpAwgiBEKAgICAcINCgICAgDBRDQEgACABIAQQ2gRFDQEgACABEAwLQoCAgIDgAA8LIAELnwIBA34gAUL/////b1gEQCAAECJCgICAgOAADwtCgICAgOAAIQUCfiAAIAFBNyABQQAQESIEQoCAgIBwg0KAgICAMFEEQCAAQZQBECkMAQsgACAEEDQLIgRCgICAgHCDIgZCgICAgOAAUgR+An4gACABQTMgAUEAEBEiAUKAgICAcINCgICAgDBRBEAgAEEvECkMAQsgACABEDQLIgFCgICAgHCDIgVCgICAgOAAUQRAIAAgBBAMQoCAgIDgAA8LAkAgBkKAgICAkH9RBEAgBKcoAgRB/////wdxRQ0BCyAFQoCAgICQf1EEQCABpygCBEH/////B3FFDQELIABB7JYBIARBpJIBELIBIQQLIAAgBCABELYCBUKAgICA4AALC5UCAgF+An8jAEEwayICJABCgICAgOAAIQECQCAAIAJBKGogAykDABCkAQ0AIAAQ4gEiBUKAgICAcINCgICAgOAAUQ0AIAAgAkEUaiADKQMIEK4CIgZFBEAgACAFEAwMAQsgACgC2AEgAhC7ASACQgEQMhogAiACKQMoIgGnIgdBARC5ARogAiACQn9B/////wNBARB6GiAFp0EEaiIDIAYgAhCyBBoCQCAERSABUHINACACQgEQMhogAiAHQQFrQQEQuQEaIAMgAhDyAUEASA0AIAJCARAyGiACIAdBARC5ARogAyADIAJB/////wNBARDuARoLIAIQGSAAIAYgAkEUahDmASAFEK8CIQELIAJBMGokACABCwkAIAAgARDcBAt0AgJ+AX8gACABENwEIgFCgICAgHCDQoCAgIDgAFEEQCABDwtBCiEGAn4CQCACRQ0AIAMpAwAiBEKAgICAcINCgICAgDBRDQAgACAEENsEIgZBAE4NAEKAgICA4AAMAQsgACABIAYQogULIQUgACABEAwgBQvOAQIBfwJ+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/////////wCDQoCAgICAgID4/wBWGwvvAQEDfiMAQRBrIgIkAEKAgICA4AAhBAJAIAAgACABECAiAUEBELsCIgVCgICAgHCDQoCAgIDgAFENACAFQiCIpyIDQQAgA0ELakESSRtFBEAgACACQQhqIAUQQkEASA0BQoCAgIAgIQQgAikDCEKAgICAgICA+P8Ag0KAgICAgICA+P8AUQ0BC0KAgICA4AAhBCAAIAFB48oAEIcCIgZCgICAgHCDQoCAgIDgAFENACAAIAYQNUUEQCAAQergAEEAEBIgACAGEAwMAQsgACAGIAFBAEEAEDYhBAsgACABEAwgACAFEAwgAkEQaiQAIAQLjAIDAXwBfgF/IwBBEGsiAiQAQoCAgIDgACEFAkAgACACQQhqIgYgARCmAg0AIAAgBiADKQMAEEINACACAn4gAisDCCIEvUKAgICAgICA+P8Ag0KAgICAgICA+P8AUgRAIASdIgREAAAAAACwnUCgIAQgBEQAAAAAAABZQGMbIAQgBEQAAAAAAAAAAGYbIQQLIAS9IgUCfyAEmUQAAAAAAADgQWMEQCAEqgwBC0GAgICAeAsiA7e9UQRAIAOtDAELQoCAgIDAfiAFQoCAgIDAgYD8/wB9IAVC////////////AINCgICAgICAgPj/AFYbCzcDACAAIAFBASACQREQ+AQhBQsgAkEQaiQAIAULigEDAX4BfAF/IwBBEGsiAiQAQoCAgIDgACEEAkAgACACQQhqIgYgARCmAg0AIAAgBiADKQMAEEINACAAIAEgAisDCCIFnUQAAAAAAAAAAKBEAAAAAAAA+H8gBUQAANzCCLI+Q2UbRAAAAAAAAPh/IAVEAADcwgiyPsNmGxD5BCEECyACQRBqJAAgBAvZAQIBfAF+IwBB0ABrIgIkAAJ+QoCAgIDgACAAIAEgAiAEQQ9xQQAQ1QMiAEEASA0AGkKAgICAwH4gAEUNABogBEGAAnEEQCACIAIrAwBEAAAAAACwncCgOQMACyACIARBBHZBD3FBA3RqKwMAIgW9IgECfyAFmUQAAAAAAADgQWMEQCAFqgwBC0GAgICAeAsiBLe9UQRAIAStDAELQoCAgIDAfiABQoCAgIDAgYD8/wB9IAFC////////////AINCgICAgICAgPj/AFYbCyEGIAJB0ABqJAAgBguHAQIBfAF+IwBBEGsiAiQAAn5CgICAgOAAIAAgAkEIaiABEKYCDQAaQoCAgIDAfiACKwMIIgS9Qv///////////wCDQoCAgICAgID4/wBWDQAaAn4gBJ0iBJlEAAAAAAAA4ENjBEAgBLAMAQtCgICAgICAgICAfwsQ1AOtCyEFIAJBEGokACAFC4MBAQF+AkAgAUL/////b1gEQCAAECIMAQsCQCADKQMAIgRCgICAgHCDQoCAgICQf1INACAAIAQQMCICRQ0BIAAgAhAQQREhAwJAAkACQCACQccAaw4DAgMBAAsgAkEWRw0CC0EQIQMLIAAgASADELsCDwsgAEGnGUEAEBILQoCAgIDgAAuYAQIBfAF+IwBBEGsiAiQAAn5CgICAgOAAIAAgAkEIaiABEKYCDQAaIAIrAwgiBL0iAQJ/IASZRAAAAAAAAOBBYwRAIASqDAELQYCAgIB4CyIAt71RBEAgAK0MAQtCgICAgMB+IAFCgICAgMCBgPz/AH0gAUL///////////8Ag0KAgICAgICA+P8AVhsLIQUgAkEQaiQAIAULngIBAX9BACECAkAgBSkDACIBQoCAgIBwVA0AIAGnIgUvAQZBNUcNACAFKAIgIQILIARBAXEhBSACKAIEIQYgAykDACEBAkACQAJAIARBAk4EQCAGQX5xQQRHDQIgAkEFNgIEIAUEQCAAIAIgARDWAwwCCyAAIAIgAUEBEPECDAELIAZBA0cNAiACKAIIIgQgBTYCHCABQiCIpyEDAkAgBQRAIANBdU8EQCABpyIDIAMoAgBBAWo2AgALIAAgARCYAQwBCyADQXVPBEAgAaciAyADKAIAQQFqNgIACyAEKAJkQQhrIAE3AwALIAAgAhD9BAtCgICAgDAPC0HL+QBBqOwAQdGYAUG5ORAAAAtBofcAQajsAEHamAFBuTkQAAALjQMCAn8CfiMAQSBrIgIkAAJAIAFCgICAgHBUDQAgAaciBS8BBkE1Rw0AIAUoAiAhBgsCQCAAIAJBEGoQtwIiAUKAgICAcINCgICAgOAAUgRAIAZFBEAgAEH+HUEAEBIgACgCECIDKQOAASEHIANCgICAgCA3A4ABIAIgBzcDCCAAIAIpAxgiB0KAgICAMEEBIAJBCGoQHCEIIAAgAikDCBAMIAAgCBAMIAAgAikDEBAMIAAgBxAMDAILIABBMBBcIgUEQCAFIAQ2AgggAykDACIHQiCIp0F1TwRAIAenIgMgAygCAEEBajYCAAsgBSAHNwMQIAFCIIinQXVPBEAgAaciAyADKAIAQQFqNgIACyAFIAE3AxggBSACKQMQNwMgIAUgAikDGDcDKCAGKAIMIgMgBTYCBCAFIAZBDGo2AgQgBSADNgIAIAYgBTYCDCAGKAIEQQNGDQIgACAGEP0EDAILIAAgAikDEBAMIAAgAikDGBAMIAAgARAMC0KAgICA4AAhAQsgAkEgaiQAIAELNAAgAykDACIBQiCIp0F1TwRAIAGnIgIgAigCAEEBajYCAAsgACABIAAgBSkDABDkARCCAwuIBgIDfwN+IwBBQGoiBSQAAn5CgICAgOAAIAAgBUEgahC3AiIJQoCAgIBwg0KAgICA4ABRDQAaAkAgACAFQSBqAn8CQAJAAkACQCABQoCAgIBwVA0AIAGnIgYvAQZBM0cNACAGKAIgIgYNAQsgAEHvLEEAEBIMAQsCQCAERQRAIAYpAwgiCEIgiKdBdUkNASAIpyIEIAQoAgBBAWo2AgAMAQsgACAGKQMAIgFBBkEXIARBAUYbIAFBABARIghCgICAgHCDIgFCgICAgCBSBEAgAUKAgICA4ABRDQIgAUKAgICAMFINAQsgAykDACIBQiCIpyECIARBAUYEQCACQXVPBEAgAaciAiACKAIAQQFqNgIACyAFIAAgAUEBEIIDNwMAQQAMBAsgAkF1TwRAIAGnIgIgAigCAEEBajYCAAsMAgsgBSAAIAYpAwAgCCACQQBKIAMgBUEUaiICEJEFIgE3AxggACAIEAwgAUKAgICAcINCgICAgOAAUQ0AIAUoAhRBAkYEQCAFIAAgASACEMgFIgg3AxggACABEAwgCEKAgICAcINCgICAgOAAUQ0BCyAAIAApA1AgBSAFQRhqQQAQ3gEiAUKAgICAcINCgICAgOAAUQRAIAAgBSkDGBAMDAELIAUgBSgCFEEAR61CgICAgBCENwM4IAUgAEHIAEEBQQBBASAFQThqEIUBIgg3AwACQCAIQoCAgIBwg0KAgICA4ABSBEAgACAFKQMYEAwgBUKAgICAMDcDCCAAIAEgBSAFQSBqEKkCIQcgACAIEAwgACABEAwgACAFKQMgEAwgACAFKQMoEAwgBw0BDAULIAAgARAMIAAgBSkDGBAMIAAgBSkDIBAMIAAgBSkDKBAMCyAAIAkQDEKAgICA4AAMBAsgACgCECICKQOAASEBIAJCgICAgCA3A4ABCyAFIAE3AwBBAQtBA3RyKQMAQoCAgIAwQQEgBRAcIQEgACAFKQMAEAwgACABEAwgACAFKQMgEAwgACAFKQMoEAwLIAkLIQogBUFAayQAIAoLIAAgAUIgiKdBdU8EQCABpyIAIAAoAgBBAWo2AgALIAELwgEBAX4jAEEQayICJAACQCABQv////9vWARAIAAQIkKAgICA4AAhAQwBCyAAIAIgARCCAiIEQoCAgIBwg0KAgICA4ABRBEAgBCEBDAELIAAQMyIBQoCAgIBwg0KAgICA4ABRBEAgACACKQMAEAwgACACKQMIEAwgACAEEAxCgICAgOAAIQEMAQsgACABQYMBIARBBxAVGiAAIAFBgQEgAikDAEEHEBUaIAAgAUGCASACKQMIQQcQFRoLIAJBEGokACABC+UDAQV+IwBBMGsiAiQAAkAgAUL/////b1gEQCAAECJCgICAgOAAIQUMAQsgACACQSBqIAEQggIiBUKAgICAcINCgICAgOAAUQ0AQoCAgIAwIQZCgICAgDAhBAJAAkAgACABQYEBIAFBABARIghCgICAgHCDQoCAgIDgAFENACAAIAgQVQ0AIAAgAykDAEEAEMsBIgRCgICAgHCDQoCAgIDgAFEEQAwBCyAAIARB6wAgBEEAEBEiBkKAgICAcINCgICAgOAAUQ0AA0AgAiAAIAQgBiACQRRqEJEBIgc3AxggB0KAgICAcINCgICAgOAAUQ0BIAIoAhQNAiAAIAggAUEBIAJBGGoQHCEHIAAgAikDGBAMIAdCgICAgHCDQoCAgIDgAFIEQCAAIAAgB0GAAUECIAJBIGoQpwIQ/wFFDQELCyAAIARBARCQARoLIAAoAhAiAykDgAEhASADQoCAgIAgNwOAASACIAE3AwggACACKQMoQoCAgIAwQQEgAkEIahAcIQEgACACKQMIEAwgACAFIAEgAUKAgICAcINCgICAgOAAUSIDGxAMQoCAgIDgACAFIAMbIQULIAAgCBAMIAAgBhAMIAAgBBAMIAAgAikDIBAMIAAgAikDKBAMCyACQTBqJAAgBQvzAwIFfgF/IwBBIGsiAiQAIAAgBSkDABDkASELIAIgBSkDECIINwMYIAUpAyAhCiAFKQMYIQkCQAJAIAAgAkEUaiAFKQMIEHUNAAJAIAsNACAFQoGAgIAQNwMAAkAgBEEDcSIFQQFGBEBCgICAgOAAIQEgABAzIgZCgICAgHCDQoCAgIDgAFENBAJAIABBoOcAQabqACAEQQRxIgQbEGAiB0KAgICAcINCgICAgOAAUQ0AIAAgBkGKASAHQQcQFUEASA0AIAMpAwAiB0IgiKdBdU8EQCAHpyIDIAMoAgBBAWo2AgALIAAgBkGLAUHBACAEGyAHQQcQFUEATg0CCyAAIAYQDAwECyADKQMAIgZCIIinQXVJDQAgBqciAyADKAIAQQFqNgIACyAAIAggAigCFCAGQQcQkwFBAEgNAUKAgICA4AAhASAAIApBfxDYAyIDQQBIDQIgA0UNAAJAIAVBAkYEQCACIAAgCBD+BCIGNwMIIAZCgICAgHCDQoCAgIDgAFENBCAAIAlCgICAgDBBASACQQhqEBwhASAAIAIpAwgQDAwBCyAAIAlCgICAgDBBASACQRhqEBwhAQsgAUKAgICAcINCgICAgOAAUQ0CIAAgARAMC0KAgICAMCEBDAELQoCAgIDgACEBCyACQSBqJAAgAQukCAINfgN/IwBB8ABrIgIkACACQoCAgIAwNwNQAkAgAUL/////b1gEQCAAECJCgICAgOAAIQkMAQsgACACQeAAaiABEIICIglCgICAgHCDQoCAgIDgAFENAEKAgICAMCEKQoCAgIAwIQVCgICAgDAhCAJAAkAgACABQYEBIAFBABARIg9CgICAgHCDQoCAgIDgAFENACAAIA8QVQ0AAkAgACADKQMAQQAQywEiCEKAgICAcINCgICAgOAAUQRADAELIAAgCEHrACAIQQAQESIKQoCAgIBwg0KAgICA4ABRDQAgAiAAEDsiCzcDUCALQoCAgIBwg0KAgICA4ABRDQAgABA7IgVCgICAgHCDQoCAgIDgAFEEQEKAgICA4AAhBQwCCyAAIAVCAEIBQQcQlAFBAEgNASACQeAAaiAEQQJGQQN0ciEDIAIpA2AiEUIgiKdBdEshEiACKQNoIhBCIIinQXVJIRQCQAJAAkADQCACIAAgCCAKIAJBDGoQkQEiBjcDWCAGQoCAgIBwg0KAgICA4ABRDQUgAigCDEUEQCAAIA8gAUEBIAJB2ABqEBwhDiAAIAIpA1gQDCAOQoCAgIBwg0KAgICA4ABRDQQgAiALNwMgIAIgDTcDGCACQoCAgIAQNwMQIAMpAwAhBiACIAU3AzAgAiAGNwMoIABBxwBBASAEQQUgAkEQaiITEIUBIgdCgICAgHCDQoCAgIDgAFENAgJAIARBAUYEQCAHIQwgAEHHAEEBQQVBBSATEIUBIgdCgICAgHCDQoCAgIDgAFENBAwBCwJAIARBAkYEQCAAIAsgDadCgICAgDBBBxCTAUEASA0HIBEiBiEMIBINAQwCCyAHIQwgECIGIQcgFA0BCyAGpyITIBMoAgBBAWo2AgALIAAgBUEBENgDQQBIBEAgACAOEAwgACAMEAwMBAsgAiAHNwNIIAIgDDcDQCAAIA5BgAFBAiACQUBrEKcCIQYgACAMEAwgACAHEAwgDUIBfCENIAAgBhD/AUUNAQwECwsgACAFQX8Q2AMiEkEASA0EIBJFDQUgBEECRgRAIAAgCxD+BCIBQoCAgIBwg0KAgICA4ABRDQUgACALEAwgAiABNwNQCyAAIAAgAykDAEKAgICAMEEBIAJB0ABqEBwQ/wENBAwFCyAOIQcLIAAgBxAMCyAAIAhBARCQARoMAQsLIAAoAhAiAykDgAEhASADQoCAgIAgNwOAASACIAE3AwAgACACKQNoIhBCgICAgDBBASACEBwhASAAIAIpAwAQDCAAIAkgASABQoCAgIBwg0KAgICA4ABRIgMbEAxCgICAgOAAIAkgAxshCQsgACAPEAwgACAFEAwgACACKQNQEAwgACAKEAwgACAIEAwgACACKQNgEAwgACAQEAwLIAJB8ABqJAAgCQslACAFKQMAIgFCIIinQXVPBEAgAaciACAAKAIAQQFqNgIACyABCzEAIAUpAwAiAUIgiKdBdU8EQCABpyICIAIoAgBBAWo2AgALIAAgARCYAUKAgICA4AAL2AEBAn4jAEEQayICJAAgBSkDACEGIAIgACAFKQMIQoCAgIAwQQBBABAcIgE3AwgCQCABQoCAgIBwg0KAgICA4ABRDQAgACAGIAIgAkEIakEAEN4BIQYgACACKQMIEAwgBkKAgICAcINCgICAgOAAUQRAIAYhAQwBCyACIABBxQBBxgAgBBtBAEEAQQEgAxCFASIHNwMAQoCAgIDgACEBIAAgB0KAgICAcINCgICAgOAAUgR+IAAgBkGAAUEBIAIQpwIhASACKQMABSAGCxAMCyACQRBqJAAgAQuiAgECfiMAQSBrIgIkACADKQMAIQQCQCAAIAFCgICAgDAQ/QEiBUKAgICAcINCgICAgOAAUQ0AAkAgACAEEDVFBEAgBEIgiKdBdU8EQCAEpyIDIAMoAgBBAmo2AgALIAIgBDcDGCACIAQ3AxAMAQsgAiAENwMIIAIgBTcDAEEAIQMDQCADQQJGDQEgAkEQaiADQQN0aiAAQcQAQQEgA0ECIAIQhQEiBDcDACAEQoCAgIBwg0KAgICA4ABRBEAgA0EBRgRAIAAgAikDEBAMCyAAIAUQDEKAgICA4AAhBQwDBSADQQFqIQMMAQsACwALIAAgBRAMIAAgAUGAAUECIAJBEGoQswIhBSAAIAIpAxAQDCAAIAIpAxgQDAsgAkEgaiQAIAULOwEBfiMAQRBrIgIkACACQoCAgIAwNwMAIAIgAykDADcDCCAAIAFBgAFBAiACELMCIQQgAkEQaiQAIAQLzwEBA38CQCABQoCAgIBwVA0AIAGnIgMvAQZBNUcNACADKAIgIgRFDQAgBEEQaiEDIARBDGohBQNAIAUgAygCACIDRwRAIAMpAxAiAUKAgICAYFoEQCAAIAGnIAIRAAALIAMpAxgiAUKAgICAYFoEQCAAIAGnIAIRAAALIAMpAyAiAUKAgICAYFoEQCAAIAGnIAIRAAALIAMpAygiAUKAgICAYFoEQCAAIAGnIAIRAAALIANBBGohAwwBCwsgBCgCCCIDRQ0AIAAgAyACEQAACwswAQF/AkAgAUKAgICAcFQNACABpyICLwEGQTVHDQAgAigCICICRQ0AIAAgAhCrBQsLDQAgACABIAJBMxDvBQsLACAAIAFBMxDwBQsWAQF/IAGnKAIgIgIEQCAAIAIQzgELCzEBAX8gAacoAiAiAgRAIAAgAigCCBD/BCAAIAIpAwAQISAAQRBqIAIgACgCBBEAAAsLzQEBBX8CQCABQoCAgIBwVA0AIAGnIgMvAQZBLUcNACADKAIgIgVFDQAgBUEEaiEGA0AgBEECRkUEQCAGIARBA3RqIgchAwNAIAcgAygCBCIDRwRAIAMpAwgiAUKAgICAYFoEQCAAIAGnIAIRAAALIAMpAxAiAUKAgICAYFoEQCAAIAGnIAIRAAALIAMpAxgiAUKAgICAYFQNASAAIAGnIAIRAAAMAQsLIARBAWohBAwBCwsgBSkDGCIBQoCAgIBgVA0AIAAgAacgAhEAAAsLjAEBB38CQCABQoCAgIBwVA0AIAGnIgIvAQZBLUcNACACKAIgIgRFDQAgBEEEaiEFA0AgA0ECRkUEQCAFIANBA3RqIgYoAgQhAgNAIAIgBkZFBEAgAigCBCEIIAAgAhCoAiAIIQIMAQsLIANBAWohAwwBCwsgACAEKQMYECEgAEEQaiAEIAAoAgQRAAALC9sGAgl+AX8jAEEwayICJABCgICAgOAAIQkCQCAAIAMpAwgiDRBVDQAgACADKQMAQQAQywEiCEKAgICAcINCgICAgOAAUQ0AQoCAgIAwIQcCQAJAAkAgACAIQesAIAhBABARIgxCgICAgHCDQoCAgIDgAFEEQEKAgICAMCEFQoCAgIAwIQYMAQsCQAJ+IAQEQCAAQoCAgIAwQQBBAEEAEL4EDAELIABCgICAgCAQQQsiBkKAgICAcINCgICAgOAAUQ0AA0ACQAJ+AkACQAJAIApC/////////w9RBEAgAEHOIUEAEBJCgICAgDAhBwwBCyACIAAgCCAMIAJBDGoQkQEiBzcDECAHQoCAgIBwg0KAgICA4ABRBEBBACEODAcLIAIoAgwEQCAGIQkMCgsgAiAHNwMgIAIgCiIBQoCAgIAIWgR+QoCAgIDAfiABub0iAUKAgICAwIGA/P8AfSABQv///////////wCDQoCAgICAgID4/wBWGwUgAQs3AyggAiAAIA0gACkDwAFBAiACQSBqEBwiBTcDGCAFQoCAgIBwg0KAgICA4ABRDQEgBARAQQAhDiAAIAYgACACQRhqQQAQgQUMBAsgACAFEDAhDiAAIAUQDCAODQILQoCAgIAwIQULIAAgCEEBEJABGkEAIQ4MBQtCgICAgDAhBSAAIAYgDiAGQQAQEQsiAUKAgICAcIMiC0KAgICAMFIEQCALQoCAgIDgAFENBQwBCyAAEDsiAUKAgICAcINCgICAgOAAUQRAQoCAgIDgACEBDAULIAQEQCACIAE3AyggAiAFNwMgIAAgBiAAIAJBIGpBABCCBSILQoCAgIBwg0KAgICA4ABRDQUgACALEAwMAQsgAUIgiKdBdU8EQCABpyIDIAMoAgBBAWo2AgALIAAgBiAOIAFBBxAVQQBIDQQLIAAgAUEBIAJBEGpBABDtA0KAgICAcINCgICAgOAAUQ0DIAAgARAMIAAgBRAMIAAgDhAQIAAgBxAMIAJCgICAgDA3AxAgAkKAgICAMDcDGCAKQgF8IQoMAAsAC0KAgICAMCEFC0KAgICAMCEBCyAAIA4QECAAIAEQDCAAIAUQDCAAIAcQDCAAIAYQDAsgACAIEAwgACAMEAwLIAJBMGokACAJC6sDAgN/AX4jAEEQayIHJAACQCAAIAEgBUEmahBaIgNFBEAgBEEANgIAQoCAgIDgACEBDAELQoCAgIAwIQECQCADKQMAIglCgICAgHCDQoCAgIAwUQ0AAkAgCUKAgICAcFQNACAJpyICLwEGIAVBImpHDQAgAigCICIGRQ0AAkAgAygCDCIIRQRAIAYoAgghAgwBCyAIKAIUIQIgACgCECAIEOIDCyAGQQRqIQYDQCACIAZGBEAgA0EANgIMIAAgAykDABAMIANCgICAgDA3AwAMAwsgAkEMaygCAARAIAIoAgQhAgwBCwsgAkEQayIGIAYoAgBBAWo2AgAgAyAGNgIMIARBADYCACADKAIIIgNFBEAgAikDECIBQiCIp0F1SQ0DIAGnIgAgACgCAEEBajYCAAwDCyAHIAIpAxAiATcDACAFRQRAIAIpAxghAQsgByABNwMIIANBAUYEQCABQiCIp0F1SQ0DIAGnIgAgACgCAEEBajYCAAwDCyAAQQIgBxD9AiEBDAILQdr1AEGo7ABBgvMCQa8UEAAACyAEQQE2AgALIAdBEGokACABC7MBAQJ+IAAgASAEQQNxIgJBImoQWkUEQEKAgICA4AAPC0KAgICA4AAhBiAAIAJBJmoQhgEiBUKAgICAcINCgICAgOAAUgR+IABBEBAkIgJFBEAgACAFEAxCgICAgOAADwsgAUIgiKdBdU8EQCABpyIAIAAoAgBBAWo2AgALIAJBADYCDCACIARBAnU2AgggAiABNwMAIAVCgICAgHBaBEAgBacgAjYCIAsgBQVCgICAgOAACwvSAgIDfgN/IwBBIGsiCCQAQoCAgIDgACEFAkAgACABIARBImoQWiIJRQ0AIAMpAwAhB0KAgICAMCEGIAJBAk4EQCADKQMIIQYLIAAgBxBVDQAgCUEEaiEKIAkoAgghAwNAIAMgCkYEQEKAgICAMCEFDAILIANBDGsoAgAEQCADKAIEIQMFIANBEGsiAiACKAIAQQFqNgIAIAMpAxAiBUIgiKdBdU8EQCAFpyIJIAkoAgBBAWo2AgALIAggBTcDCAJAIAQNACADKQMYIgVCIIinQXVJDQAgBaciCSAJKAIAQQFqNgIACyAIIAE3AxAgCCAFNwMAIAAgByAGQQMgCBAcIQUgACAIKQMAEAwgBEUEQCAAIAgpAwgQDAsgAygCBCEDIAAoAhAgAhDiAyAFQoCAgIBwg0KAgICA4ABRDQIgACAFEAwLDAALAAsgCEEgaiQAIAULVAAgACABIAJBImoQWiIARQRAQoCAgIDgAA8LIAAoAgwiAEEATgRAIACtDwtCgICAgMB+IAC4vSIBQoCAgIDAgYD8/wB9IAFCgICAgICAgPj/AFYbC1kBAX8gACABIARBImoQWiICRQRAQoCAgIDgAA8LIAJBBGohAyACKAIIIQQDfiADIARGBH5CgICAgDAFIARBEGshBSAEKAIEIQQgACgCECACIAUQgAUMAQsLC3UAIAAgASAEQSJqEFoiAkUEQEKAgICA4AAPCyAAIAIgAykDACIBQgAgAUIgiKdBB2tBbk8bIAEgAUKAgICAwIGA/P8AfEL///////////8Ag1AbEPICIgNFBEBCgICAgBAPCyAAKAIQIAIgAxCABUKBgICAEAthACAAIAEgBEEiahBaIgJFBEBCgICAgOAADwsgACACIAMpAwAiAUIAIAFCIIinQQdrQW5PGyABIAFCgICAgMCBgPz/AHxC////////////AINQGxDyAkEAR61CgICAgBCECwgAQoCAgIAwC0oAAkAgBSkDACIBQoCAgIBwVA0AIAGnIgIvAQZBLEcNACACKAIgIgJFDQAgAkEBOgARIAAgARAMIAVCgICAgCA3AwALQoCAgIAwC88BAQN+IwBBEGsiAiQAQoCAgIDgACEFAkACQAJ+QoCAgIAwIABCgICAgDAgACADEMAEIgRCgICAgHCDQoCAgIDgAFENABogAiAENwMIQoCAgIDgACAAQcMAQQBBAEEBIAJBCGoQhQEiBkKAgICAcINCgICAgOAAUQ0AGiAAEDMiAUKAgICAcINCgICAgOAAUg0BIAYLIQEgACAEEAwgACABEAwMAQsgACABQYQBIARBBxAVGiAAIAFBhQEgBkEHEBUaIAEhBQsgAkEQaiQAIAULswMCA38CfiMAQdAAayIGJABBfyEHAkAgACAG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QoCAgIBwg0KAgICA4ABRcg0AIAAgAykDCCIGEDVFDQBCgICAgOAAIQQCQCAAEDMiBUKAgICAcINCgICAgOAAUQRAIAEhBQwBCyAAIAVBLyABQQcQFUEASA0AIAAgBUEvIAYQhQUhBAsgACAFEAwMAQsgASEECyAHQRBqJAAgBAsQACAAIAMpAwBBESAEELICC6UDAQR+IwBBEGsiAyQAIAQCfwJAAkACQAJAIAAgAUEqEFoiAkUEQEKAgICAMCEBDAELIAIoAhgEQEKAgICAMCEBQQEMBQsgACACKQMAIgggAikDCCIGEMUBIgFCgICAgHCDIgdCgICAgOAAUg0BC0KAgICAMCEHDAELIAdCgICAgCBRBEAgAkEBNgIYQoCAgIAwIQFBAQwDCyACKAIQBEAgACAAIAFCABBOEDQiB0KAgICAcIMiCUKAgICA4ABRDQECQCAJQoCAgICQf1INACAHpygCBEH/////B3ENACAAIANBCGogACAIQdYAIAhBABAREKEBQQBIDQIgACAIQdYAAn4gBqcgAykDCCACKAIUEPQCIgZCgICAgAh8Qv////8PWARAIAZC/////w+DDAELQoCAgIDAfiAGub0iBkKAgICAwIGA/P8AfSAGQv///////////wCDQoCAgICAgID4/wBWGwsQOUEASA0CCyAAIAcQDAwCCyACQQE2AhgMAQsgACABEAwgACAHEAxCgICAgOAAIQELQQALNgIAIANBEGokACABCyAAIAFCIIinQXVPBEAgAaciACAAKAIAQQFqNgIACyABC/EHAgR/C34jAEEwayIEJAACQCABQv////9vWARAIAAQIkKAgICA4AAhAQwBC0KAgICAMCEIAkACQCAAIAMpAwAQJSIPQoCAgIBwg0KAgICA4ABRBEBCgICAgDAhDEKAgICAMCEBQoCAgIAwIQ1CgICAgDAhEAwBCyAAIAEgACkDSBD9ASIQQoCAgIBwg0KAgICA4ABRBEBCgICAgDAhDEKAgICAMCEBQoCAgIAwIQ0MAQsCQAJAIAAgACABQe4AIAFBABAREDQiDUKAgICAcINCgICAgOAAUQ0AIA2nIgJB9QBBABCgASEGIAJB+QBBABCgAUEASARAIABB7JYBIA1B0A4QsgEiDUKAgICAcINCgICAgOAAUQ0BCyAEIA03AyggBCABNwMgIAAgEEECIARBIGoQowEiDEKAgICAcINCgICAgOAAUQ0BIAAQOyIBQoCAgIBwg0KAgICA4ABRBEBCgICAgOAAIQEMAwtBfyECAkAgAykDCCIJQoCAgIBwg0KAgICAMFENACAAIARBHGogCRB1QQBIDQMgBCgCHCICDQAMBAsCQAJAIA+nIgcpAgQiCKdB/////wdxIgUEQCAGQX9zQR92IQYgCEL/////B4MhESACrSESQgAhCUKAgICAMCEIQQAhAgNAIAKtIQogAiEDA0AgAyAFTw0DIAAgDEHWACADrSIOEDlBAEgNByAAIAgQDAJAIAAgDCAPEMUBIghCgICAgHCDIgtCgICAgCBRDQAgC0KAgICA4ABRDQggACAEQRBqIAAgDEHWACAMQQAQERChAQ0IIAQgBCkDECILIBEgCyARUxsiCzcDECAKIAtRDQAgACAHIAIgAxCOASIKQoCAgIBwg0KAgICA4ABRDQggACABIAkgChBnQQBIDQggCUIBfCIKIBJRDQkgACAEQQhqIAgQLw0IIAunIQJCASELIAlCASAEKQMIIg4gDkIBVxt8IQkDQCAJIApRDQMgACAAIAggCxBsEDQiDkKAgICAcINCgICAgOAAUQ0JIAAgASAKIA4QZ0EASA0JIAtCAXwhCyAKQgF8IgogElINAAsMCQsgByAOIAYQ9AKnIQMMAAsACwALIAAgDCAPEMUBIghCgICAgHCDIglCgICAgCBSDQFCACEJQQAhAgsgACAHIAIgBSACIAVJGyAFEI4BIgpCgICAgHCDQoCAgIDgAFENAyAAIAEgCSAKEGdBAEgNAwwECyAJQoCAgIDgAFINAwwCC0KAgICAMCEMC0KAgICAMCEBCyAAIAEQDEKAgICA4AAhAQsgACAPEAwgACAQEAwgACAMEAwgACANEAwgACAIEAwLIARBMGokACABC+ACAQd+IAFC/////29YBEAgABAiQoCAgIDgAA8LQoCAgIDgACEIQoCAgIAwIQYCQAJAAkAgACADKQMAECUiB0KAgICAcINCgICAgOAAUQRAQoCAgIAwIQQMAQsgACABQdYAIAFBABARIgRCgICAgHCDQoCAgIDgAFENACAAIARCABBNRQRAIAAgAUHWAEIAEDlBAEgNAQsgACABIAcQxQEiBUKAgICAcIMiCUKAgICA4ABRDQEgACABQdYAIAFBABARIgZCgICAgHCDQoCAgIDgAFENAQJAIAAgBiAEEE0EQCAAIAQQDAwBCyAAIAFB1gAgBBA5QQBODQBCgICAgDAhBAwCCyAAIAcQDCAAIAYQDEL/////DyEIIAlCgICAgCBRDQIgACAFQdgAIAVBABARIQogACAFEAwgCg8LQoCAgIAwIQULIAAgBRAMIAAgBxAMIAAgBhAMIAAgBBAMCyAIC84EAgZ+AX8jAEEgayICJAACQCABQv////9vWARAIAAQIkKAgICA4AAhBwwBC0KAgICA4AAhB0KAgICAMCEIAkAgACADKQMAECUiCUKAgICAcINCgICAgOAAUQRAQoCAgIAwIQRCgICAgDAhBUKAgICAMCEGDAELAkACQCAAIAEgACkDSBD9ASIGQoCAgIBwg0KAgICA4ABRBEBCgICAgDAhBAwBCyAAIAAgAUHuACABQQAQERA0IgRCgICAgHCDQoCAgIDgAFINAQtCgICAgDAhBQwBCyACIAQ3AxggAiABNwMQIAAgBkECIAJBEGoQowEiBUKAgICAcINCgICAgOAAUQ0AIAAgAkEIaiAAIAFB1gAgAUEAEBEQoQENACAAIAVB1gACfiACKQMIIgFCgICAgAh8Qv////8PWARAIAFC/////w+DDAELQoCAgIDAfiABub0iAUKAgICAwIGA/P8AfSABQv///////////wCDQoCAgICAgID4/wBWGwsQOUEASA0AQoCAgIDgACEIIABBKhCGASIBQoCAgIBwg0KAgICA4ABRDQAgAEEgECQiA0UEQCABIQgMAQsgAyAJNwMIIAMgBTcDACADIASnIgpB5wBBABCgAUF/c0EfdjYCECAKQfUAQQAQoAEhCiADQQA2AhggAyAKQX9zQR92NgIUIAFCgICAgHBaBEAgAacgAzYCIAsgACAGEAwgACAEEAwgASEHDAELIAAgCRAMIAAgBhAMIAAgBBAMIAAgBRAMIAAgCBAMCyACQSBqJAAgBwv+BAIIfgJ/IwBBEGsiAiQAAkAgAUL/////b1gEQCAAECJCgICAgOAAIQcMAQtCgICAgOAAIQdCgICAgDAhBQJAAkACQCAAIAMpAwAQJSIJQoCAgIBwg0KAgICA4ABRBEBCgICAgDAhCAwBCyAAIAFB7gAgAUEAEBEiCEKAgICAcINCgICAgOAAUQ0AIAAgCBA0IghCgICAgHCDQoCAgIDgAFENACAIp0HnAEEAEKABQX9GBEAgACABIAkQxQEhBwwDCyAAIAAgAUHwACABQQAQERAnIgxBAEgNACAAIAFB1gBCABA5QQBIDQAgABA7IgZCgICAgHCDQoCAgIDgAFEEQEKAgICA4AAhBgwCCyAJpyENA0ACQCAAIAUQDCAAIAEgCRDFASIFQoCAgIBwgyIEQoCAgIAgUQ0AIARCgICAgOAAUQ0DAkAgACAAIAVCABBOEDQiBEKAgICAcIMiC0KAgICAkH9SBEBBACEDIAtCgICAgOAAUQ0FDAELIASnKAIEQf////8HcUUhAwsgACAGIAogBBB7QQBIDQMgCkIBfCEKIANFDQEgACACQQhqIAAgAUHWACABQQAQERChAUEASA0DIAAgAUHWAAJ+IA0gAikDCCAMEPQCIgRCgICAgAh8Qv////8PWARAIARC/////w+DDAELQoCAgIDAfiAEub0iBEKAgICAwIGA/P8AfSAEQv///////////wCDQoCAgICAgID4/wBWGwsQOUEATg0BDAMLCyAKpwRAIAYhBwwDCyAAIAYQDEKAgICAICEHDAILQoCAgIAwIQYLIAAgBhAMCyAAIAUQDCAAIAgQDCAAIAkQDAsgAkEQaiQAIAcLjgEBAn8gASgCACICQQBKBEAgASACQQFrIgI2AgACQCACDQAgAS0ABEHwAXFBEEcNACABKAIIIgIgASgCDCIDNgIEIAMgAjYCACABQQA2AgggACgCYCICIAFBCGoiAzYCBCABIABB4ABqNgIMIAEgAjYCCCAAIAM2AmALDwtB5oQBQajsAEHWLEHN4wAQAAAL8BQCDn8OfiMAQZABayIEJAACQCABQv////9vWARAIAAQIkKAgICA4AAhFQwBCyADKQMIIR4gACAEQThqQQAQPhogBEEANgIwIARCgICAgMAANwMoIAQgADYCACAEIARBCGoiBzYCBEKAgICA4AAhFUKAgICAMCEWQoCAgIAwIRdCgICAgDAhE0KAgICAMCEUQoCAgIAwIR1CgICAgDAhHAJAAkAgACADKQMAECUiGEKAgICAcINCgICAgOAAUQ0AIAAgHhA1IglFBEAgACAeECUiHUKAgICAcINCgICAgOAAUQ0BIB2nIQULAkACQCAAIAFB7gAgAUEAEBEiHEKAgICA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QQRqIQMMAAsACwuaAQEHfyABpygCICIDBEAgAEEQaiEEIANBBGohBiADKAIIIQIDQCACIAZHBEAgAigCBCEIIAJBEGshBSACQQxrKAIARQRAAkAgAygCAARAIAUQnAUMAQsgACACKQMQECELIAAgAikDGBAhCyAEIAUgACgCBBEAACAIIQIMAQsLIAQgAygCECAAKAIEEQAAIAQgAyAAKAIEEQAACwsbAQF/IAGnKAIgIgMEQCAAIAMoAgwgAhEAAAsLUgEDfyABpygCICICBEAgAigCBCIDBEAgAigCACIEIAM2AgQgAyAENgIAIAJCADcCAAsgACACNQIMQoCAgIBwhBAhIABBEGogAiAAKAIEEQAACwupAQEGfyABpygCICIDBEAgA0EMaiEFIAMoAhAhAgNAIAIgBUcEQCACKAIEIQcgAkIANwIAIAIoAgghBCAHIQIgBC8BBkEgRg0BIARCADcCJAwBCwsCQAJAIAMtAAVFDQAgACgCyAEiAkUNACAAKALQASADKAIIIAIRAAAMAQsgAygCGCICRQ0AIAAgAygCFCADKAIIIAIRBgALIABBEGogAyAAKAIEEQAACwspAQF/IAAgAaciAjUCJEKAgICAkH+EECEgACACNQIgQoCAgICQf4QQIQshACABpygCICkDACIBQoCAgIBgWgRAIAAgAacgAhEAAAsLaQEDfyAAIAGnKAIgIgIpAwAQISACLQARRQRAA0AgAigCFCEEIAMgAigCDE9FBEAgACAEIANBA3RqKAIEEMcBIANBAWohAwwBCwsgAEEQaiAEIAAoAgQRAAALIABBEGogAiAAKAIEEQAAC2wBA38CQCABQoCAgIBwVA0AIAGnIgMvAQZBD0cNACADKAIgIgRFDQAgBEEIaiEFQQAhAwNAIAMgBC0ABU8NASAFIANBA3RqKQMAIgFCgICAgGBaBEAgACABpyACEQAACyADQQFqIQMMAAsACwtqAQN/AkAgAUKAgICAcFQNACABpyICLwEGQQ9HDQAgAigCICIDRQ0AIANBCGohBEEAIQIDQCACIAMtAAVPRQRAIAAgBCACQQN0aikDABAhIAJBAWohAgwBCwsgAEEQaiADIAAoAgQRAAALC38BA38gAacoAiAiBCkDACIBQoCAgIBgWgRAIAAgAacgAhEAAAsgBCkDCCIBQoCAgIBgWgRAIAAgAacgAhEAAAsgBEEYaiEFA0AgBCgCECADSgRAIAUgA0EDdGopAwAiAUKAgICAYFoEQCAAIAGnIAIRAAALIANBAWohAwwBCwsLWQEDfyAAIAGnKAIgIgIpAwAQISAAIAIpAwgQISACQRhqIQQDQCADIAIoAhBORQRAIAAgBCADQQN0aikDABAhIANBAWohAwwBCwsgAEEQaiACIAAoAgQRAAALcgEEfyABpyIDKAIgIQQgAygCJCEFIAMoAigiAwRAIAAgAyACEQAACyAEBEACQCAFRQ0AQQAhAwNAIAMgBCgCPE4NASAFIANBAnRqKAIAIgYEQCAAIAYgAhEAAAsgA0EBaiEDDAALAAsgACAEIAIRAAALC3wBA38gAaciAigCKCIDBEAgACADrUKAgICAcIQQIQsgAigCICIDBEAgAigCJCIEBEBBACECA0AgAiADKAI8TkUEQCAAIAQgAkECdGooAgAQ5QEgAkEBaiECDAELCyAAQRBqIAQgACgCBBEAAAsgACADrUKAgICAYIQQIQsLEgAgAacoAiAiAARAIAAQngMLCx4AIAGnKQMgIgFCgICAgGBaBEAgACABpyACEQAACwsZACAAIAGnIgApAyAQISAAQoCAgIAwNwMgC0QBAn8gAachBANAIAQoAiggA0sEQCAEKAIkIANBA3RqKQMAIgFCgICAgGBaBEAgACABpyACEQAACyADQQFqIQMMAQsLC0YBA38gAachAwNAIAMoAiQhBCACIAMoAihPRQRAIAAgBCACQQN0aikDABAhIAJBAWohAgwBCwsgAEEQaiAEIAAoAgQRAAALEQAgAEEQaiACIAAoAgQRAAAL2wECAX8CfiMAQSBrIgMkACABQQNGBEAgAikDECEEIAIpAwghBQJAIAAgA0EQaiACKQMAEKoFQQBIBEBCgICAgOAAIQQMAQsgACAEIAVBAiADQRBqEBwiBEKAgICAcINCgICAgOAAUQRAIAAoAhAiASkDgAEhBCABQoCAgIAgNwOAASADIAQ3AwggACADKQMYQoCAgIAwQQEgA0EIahAcIQQgACADKQMIEAwLIAAgAykDEBAMIAAgAykDGBAMCyADQSBqJAAgBA8LQZuCAUGo7ABBy/UCQaDtABAAAAuIAQIBfgF/QQAhAkKAgICAMCEBA0ACQCACQQJHBH4gBSACQQN0IgRq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Y29kZV0KfQBjYW5ub3QgbWl4ID8/IHdpdGggJiYgb3IgfHwAcHJveHk6IHByb3BlcnR5IG5vdCBwcmVzZW50IGluIHRhcmdldCB3ZXJlIHJldHVybmVkIGJ5IG5vbiBleHRlbnNpYmxlIHByb3h5AHJldm9rZWQgcHJveHkAUHJveHkAYWRkX3Byb3BlcnR5AHByb3h5OiBjYW5ub3Qgc2V0IHByb3BlcnR5AG5vIHNldHRlciBmb3IgcHJvcGVydHkAdmFsdWUgaGFzIG5vIHByb3BlcnR5AGNvdWxkIG5vdCBkZWxldGUgcHJvcGVydHkAcHJveHk6IGR1cGxpY2F0ZSBwcm9wZXJ0eQBKU19EZWZpbmVBdXRvSW5pdFByb3BlcnR5AGhhc093blByb3BlcnR5AHByb3h5OiBpbmNvbnNpc3RlbnQgZGVsZXRlUHJvcGVydHkAcHJveHk6IGluY29uc2lzdGVudCBkZWZpbmVQcm9wZXJ0eQBKU19EZWZpbmVQcm9wZXJ0eQAhbXItPmVtcHR5AGluZmluaXR5AEluZmluaXR5AG91dCBvZiBtZW1vcnkAdW5rbm93biB1bmljb2RlIGdlbmVyYWwgY2F0ZWdvcnkAR2VuZXJhbF9DYXRlZ29yeQBldmVyeQBhbnkAYXBwbHkAJyVzJyBpcyByZWFkLW9ubHkAZXhwZWN0aW5nIGNhdGNoIG9yIGZpbmFsbHkAc3RpY2t5AGJpZ2ludCBhcmUgZm9yYmlkZGVuIGluIEpTT04uc3RyaW5naWZ5AHN1YmFycmF5AGVtcHR5IGFycmF5AG5vbiBpbnRlZ2VyIGluZGV4IGluIHR5cGVkIGFycmF5AG5lZ2F0aXZlIGluZGV4IGluIHR5cGVkIGFycmF5AG91dC1vZi1ib3VuZCBpbmRleCBpbiB0eXBlZCBhcnJheQBjYW5ub3QgY3JlYXRlIG51bWVyaWMgaW5kZXggaW4gdHlwZWQgYXJyYXkAaXNBcnJheQBUeXBlZEFycmF5AGdldERheQBnZXRVVENEYXkAZ3JvdXBCeQBtLT5kZnNfYW5jZXN0b3JfaW5kZXggPD0gbS0+ZGZzX2luZGV4AGpzX2dldF9hdG9tX2luZGV4AGludmFsaWQgYXJyYXkgaW5kZXgASlNfQXRvbUlzQXJyYXlJbmRleABmaW5kTGFzdEluZGV4AGZpbmRJbmRleABpbnZhbGlkIGV4cG9ydCBzeW50YXgAaW52YWxpZCBhc3NpZ25tZW50IHN5bnRheABtYXgAXHUlMDR4AGludmFsaWQgb3Bjb2RlOiBwYz0ldSBvcGNvZGU9MHglMDJ4AC0rICAgMFgweAAtMFgrMFggMFgtMHgrMHggMHgAbGluZSB0ZXJtaW5hdG9yIG5vdCBhbGxvd2VkIGFmdGVyIHRocm93AGJmX3BvdwBub3cAaW50ZWdlciBvdmVyZmxvdwBzdGFjayBvdmVyZmxvdwBtdXN0IGJlIGNhbGxlZCB3aXRoIG5ldwBpc1ZpZXcARGF0YVZpZXcAcmF3ACV1AGNsYXNzIGRlY2xhcmF0aW9ucyBjYW4ndCBhcHBlYXIgaW4gc2luZ2xlLXN0YXRlbWVudCBjb250ZXh0AGZ1bmN0aW9uIGRlY2xhcmF0aW9ucyBjYW4ndCBhcHBlYXIgaW4gc2luZ2xlLXN0YXRlbWVudCBjb250ZXh0AGxleGljYWwgZGVjbGFyYXRpb25zIGNhbid0IGFwcGVhciBpbiBzaW5nbGUtc3RhdGVtZW50IGNvbnRleHQAZHVwbGljYXRlIGFyZ3VtZW50IG5hbWVzIG5vdCBhbGxvd2VkIGluIHRoaXMgY29udGV4dABkdXBsaWNhdGUgcGFyYW1ldGVyIG5hbWVzIG5vdCBhbGxvd2VkIGluIHRoaXMgY29udGV4dABpbXBvcnQubWV0YSBub3Qgc3VwcG9ydGVkIGluIHRoaXMgY29udGV4dABKU19GcmVlQ29udGV4dABKU0NvbnRleHQAanNfbWFwX2l0ZXJhdG9yX25leHQAanNfZ2VuZXJhdG9yX25leHQAanNfYXN5bmNfZ2VuZXJhdG9yX3Jlc3VtZV9uZXh0AHVuZXhwZWN0ZWQgZW5kIG9mIGlucHV0AHR0AGV4cG9ydGVkIHZhcmlhYmxlICclcycgZG9lcyBub3QgZXhpc3QAcHJpdmF0ZSBjbGFzcyBmaWVsZCAnJXMnIGRvZXMgbm90IGV4aXN0AHRlc3QAYXNzaWdubWVudCByZXN0IHByb3BlcnR5IG11c3QgYmUgbGFzdABwdmFsID09IGxhc3QAZmluZExhc3QAYmZfc3FydABzb3J0AGNicnQAdHJpbVN0YXJ0AHBhZFN0YXJ0AHVua25vd24gdW5pY29kZSBzY3JpcHQAU2NyaXB0AGh5cG90AGZyZWVfemVyb19yZWZjb3VudABzdHJfaW5kZXggPT0gbnVtX2tleXNfY291bnQgKyBzdHJfa2V5c19jb3VudABudW1faW5kZXggPT0gbnVtX2tleXNfY291bnQAc3ltX2luZGV4ID09IGF0b21fY291bnQAbGFiZWwgPj0gMCAmJiBsYWJlbCA8IHMtPmxhYmVsX2NvdW50AGxhYjEgPj0gMCAmJiBsYWIxIDwgcy0+bGFiZWxfY291bnQAdmFsIDwgcy0+Y2FwdHVyZV9jb3VudAB2YWwyIDwgcy0+Y2FwdHVyZV9jb3VudABpbnZhbGlkIHJlcGVhdCBjb3VudABpbnZhbGlkIHJlcGV0aXRpb24gY291bnQAZm9udABpbnZhbGlkIGNvZGUgcG9pbnQAZnJvbUNvZGVQb2ludABpbnZhbGlkIGhpbnQAY2Fubm90IGNvbnZlcnQgTmFOIG9yIEluZmluaXR5IHRvIGJpZ2ludABjYW5ub3QgY29udmVydCB0byBiaWdpbnQAYm90aCBvcGVyYW5kcyBtdXN0IGJlIGJpZ2ludABub3QgYSBiaWdpbnQAcHJpdmF0ZSBtZXRob2QgaXMgYWxyZWFkeSBwcmVzZW50AGVuY29kZVVSSUNvbXBvbmVudABkZWNvZGVVUklDb21wb25lbnQAdW5leHBlY3RlZCBlbmQgb2YgY29tbWVudABpbnZhbGlkIHN3aXRjaCBzdGF0ZW1lbnQAQmlnSW50AHBhcnNlSW50AGR1cGxpY2F0ZSBkZWZhdWx0AHNwbGl0AGV4cGVjdGluZyBoZXggZGlnaXQAdHJpbVJpZ2h0AHJlZHVjZVJpZ2h0AHVuc2hpZnQAdHJpbUxlZnQAaW52YWxpZCBvZmZzZXQAaW52YWxpZCBieXRlT2Zmc2V0AGdldFRpbWV6b25lT2Zmc2V0AHJlc29sdmluZyBmdW5jdGlvbiBhbHJlYWR5IHNldABwcm94eTogaW5jb25zaXN0ZW50IHNldABmaW5kX2p1bXBfdGFyZ2V0AGV4cGVjdGluZyB0YXJnZXQAaW52YWxpZCBkZXN0cnVjdHVyaW5nIHRhcmdldABwcm94eTogaW5jb25zaXN0ZW50IGdldABXZWFrU2V0AGNvbnN0cnVjdABKU19GcmVlQXRvbVN0cnVjdAB1c2Ugc3RyaWN0AFJlZmxlY3QAcmVqZWN0AG5vdCBhbiBBc3luY0dlbmVyYXRvciBvYmplY3QAY2Fubm90IGNvbnZlcnQgdG8gb2JqZWN0AGludmFsaWQgYnJhbmQgb24gb2JqZWN0AG9wZXJhbmQgJ3Byb3RvdHlwZScgcHJvcGVydHkgaXMgbm90IGFuIG9iamVjdABpdGVyYXRvciBtdXN0IHJldHVybiBhbiBvYmplY3QAbm90IGEgRGF0ZSBvYmplY3QAbm90IGEgb2JqZWN0AEpTT2JqZWN0AHBhcnNlRmxvYXQAZmxhdABub3RoaW5nIHRvIHJlcGVhdABjb25jYXQAY29kZVBvaW50QXQAY2hhckF0AGNoYXJDb2RlQXQAa2V5cwBwcm94eTogdGFyZ2V0IHByb3BlcnR5IG11c3QgYmUgcHJlc2VudCBpbiBwcm94eSBvd25LZXlzACAgZmFzdCBhcnJheXMAZXhwb3J0ICclcycgaW4gbW9kdWxlICclcycgaXMgYW1iaWd1b3VzAHByaXZhdGUgY2xhc3MgZmllbGQgJyVzJyBhbHJlYWR5IGV4aXN0cwB0b28gbWFueSBhcmd1bWVudHMAVG9vIG1hbnkgY2FsbCBhcmd1bWVudHMAdG9vIG1hbnkgZWxlbWVudHMAICBlbGVtZW50cwBpbnZhbGlkIG51bWJlciBvZiBkaWdpdHMAYmluYXJ5IG9iamVjdHMAaW52YWxpZCBwcm9wZXJ0eSBhY2Nlc3MAanNfb3BfZGVmaW5lX2NsYXNzAGZkLT5ieXRlX2NvZGUuYnVmW2RlZmluZV9jbGFzc19wb3NdID09IE9QX2RlZmluZV9jbGFzcwBfX2dldENsYXNzAHNldEhvdXJzAGdldEhvdXJzAHNldFVUQ0hvdXJzAGdldFVUQ0hvdXJzAGdhdGhlcl9hdmFpbGFibGVfYW5jZXN0b3JzAGdldE93blByb3BlcnR5RGVzY3JpcHRvcnMAd2l0aFJlc29sdmVycwB0b28gbWFueSBpbWJyaWNhdGVkIHF1YW50aWZpZXJzAHVuaWNvZGVfcHJvcF9vcHMAYWNvcwBmb3IgYXdhaXQgaXMgb25seSB2YWxpZCBpbiBhc3luY2hyb25vdXMgZnVuY3Rpb25zAG5ldy50YXJnZXQgb25seSBhbGxvd2VkIHdpdGhpbiBmdW5jdGlvbnMAYnl0ZWNvZGUgZnVuY3Rpb25zAEMgZnVuY3Rpb25zAHByb3h5OiBpbmNvbnNpc3RlbnQgcHJldmVudEV4dGVuc2lvbnMAU2NyaXB0X0V4dGVuc2lvbnMAYXRvbXMAcHJveHk6IHByb3BlcnRpZXMgbXVzdCBiZSBzdHJpbmdzIG9yIHN5bWJvbHMAZ2V0T3duUHJvcGVydHlTeW1ib2xzAHJlc29sdmVfbGFiZWxzAEpTX0V2YWxUaGlzAHN0cmluZ3MAaW52YWxpZCBkZXNjcmlwdG9yIGZsYWdzAGludmFsaWQgcmVndWxhciBleHByZXNzaW9uIGZsYWdzAHZhbHVlcwBzZXRNaW51dGVzAGdldE1pbnV0ZXMAc2V0VVRDTWludXRlcwBnZXRVVENNaW51dGVzAHRvbyBtYW55IGNhcHR1cmVzACAgc2hhcGVzAGdldE93blByb3BlcnR5TmFtZXMAZ2NfZnJlZV9jeWNsZXMAYWRkX2V2YWxfdmFyaWFibGVzAHJlc29sdmVfdmFyaWFibGVzAHRvbyBtYW55IGxvY2FsIHZhcmlhYmxlcwB0b28gbWFueSBjbG9zdXJlIHZhcmlhYmxlcwBjb21wYWN0X3Byb3BlcnRpZXMAICBwcm9wZXJ0aWVzAGRlZmluZVByb3BlcnRpZXMAZW50cmllcwBmcm9tRW50cmllcwB0b28gbWFueSByYW5nZXMAaW5jbHVkZXMAaGFzSW5kaWNlcwBzZXRNaWxsaXNlY29uZHMAZ2V0TWlsbGlzZWNvbmRzAHNldFVUQ01pbGxpc2Vjb25kcwBnZXRVVENNaWxsaXNlY29uZHMAc2V0U2Vjb25kcwBnZXRTZWNvbmRzAHNldFVUQ1NlY29uZHMAZ2V0VVRDU2Vjb25kcwBpdGFsaWNzAGFicwBwcm94eTogaW5jb25zaXN0ZW50IGhhcwAlLipzACAoJXMAc2V0ICVzAGdldCAlcwAgICAgYXQgJXMAbm90IGEgJXMAdW5zdXBwb3J0ZWQga2V5d29yZDogJXMAc3Vic3RyAHByb3h5OiBpbmNvbnNpc3RlbnQgZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yAHN1cGVyKCkgaXMgb25seSB2YWxpZCBpbiBhIGRlcml2ZWQgY2xhc3MgY29uc3RydWN0b3IAcGFyZW50IGNsYXNzIG11c3QgYmUgY29uc3RydWN0b3IAbm90IGEgY29uc3RydWN0b3IAQXJyYXkgSXRlcmF0b3IAU2V0IEl0ZXJhdG9yAE1hcCBJdGVyYXRvcgBSZWdFeHAgU3RyaW5nIEl0ZXJhdG9yAG5vdCBhbiBBc3luYy1mcm9tLVN5bmMgSXRlcmF0b3IAY2Fubm90IGludm9rZSBhIHJ1bm5pbmcgZ2VuZXJhdG9yAG5vdCBhIGdlbmVyYXRvcgBBc3luY0dlbmVyYXRvcgBzeW50YXggZXJyb3IAU3ludGF4RXJyb3IARXZhbEVycm9yAEludGVybmFsRXJyb3IAQWdncmVnYXRlRXJyb3IAVHlwZUVycm9yAFJhbmdlRXJyb3IAUmVmZXJlbmNlRXJyb3IAVVJJRXJyb3IAZmxvb3IAZm9udGNvbG9yAGFuY2hvcgBmb3IAa2V5Rm9yAGV4cGVjdGluZyBzdXJyb2dhdGUgcGFpcgBhIGRlY2xhcmF0aW9uIGluIHRoZSBoZWFkIG9mIGEgZm9yLSVzIGxvb3AgY2FuJ3QgaGF2ZSBhbiBpbml0aWFsaXplcgAnYXJndW1lbnRzJyBpZGVudGlmaWVyIGlzIG5vdCBhbGxvd2VkIGluIGNsYXNzIGZpZWxkIGluaXRpYWxpemVyAGludmFsaWQgbnVtYmVyIG9mIGFyZ3VtZW50cyBmb3IgZ2V0dGVyIG9yIHNldHRlcgBpbnZhbGlkIHNldHRlcgBpbnZhbGlkIGdldHRlcgBmaWx0ZXIAbWlzc2luZyBmb3JtYWwgcGFyYW1ldGVyACJ1c2Ugc3RyaWN0IiBub3QgYWxsb3dlZCBpbiBmdW5jdGlvbiB3aXRoIGRlZmF1bHQgb3IgZGVzdHJ1Y3R1cmluZyBwYXJhbWV0ZXIAaW52YWxpZCBjaGFyYWN0ZXIAdW5leHBlY3RlZCBjaGFyYWN0ZXIAcHJpdmF0ZSBjbGFzcyBmaWVsZCBmb3JiaWRkZW4gYWZ0ZXIgc3VwZXIAaW52YWxpZCByZWRlZmluaXRpb24gb2YgbGV4aWNhbCBpZGVudGlmaWVyACdsZXQnIGlzIG5vdCBhIHZhbGlkIGxleGljYWwgaWRlbnRpZmllcgBpbnZhbGlkIHJlZGVmaW5pdGlvbiBvZiBnbG9iYWwgaWRlbnRpZmllcgB5aWVsZCBpcyBhIHJlc2VydmVkIGlkZW50aWZpZXIAJyVzJyBpcyBhIHJlc2VydmVkIGlkZW50aWZpZXIAb3RoZXIAYXRvbTFfaXNfaW50ZWdlciAmJiBhdG9tMl9pc19pbnRlZ2VyAGNhbm5vdCBjb252ZXJ0IHRvIGJpZ2ludDogbm90IGFuIGludGVnZXIAaXNJbnRlZ2VyAGlzU2FmZUludGVnZXIAYnVmZmVyAFNoYXJlZEFycmF5QnVmZmVyAGNhbm5vdCB1c2UgaWRlbnRpY2FsIEFycmF5QnVmZmVyAGNhbm5vdCBjb252ZXJ0IGJpZ2ludCB0byBudW1iZXIAY2Fubm90IGNvbnZlcnQgc3ltYm9sIHRvIG51bWJlcgBub3QgYSBudW1iZXIAbGluZU51bWJlcgBtYWxmb3JtZWQgdW5pY29kZSBjaGFyAGNsZWFyAHNldFllYXIAZ2V0WWVhcgBzZXRGdWxsWWVhcgBnZXRGdWxsWWVhcgBzZXRVVENGdWxsWWVhcgBnZXRVVENGdWxsWWVhcgBxICE9IHIAdW5leHBlY3RlZCBsaW5lIHRlcm1pbmF0b3IgaW4gcmVnZXhwAHVuZXhwZWN0ZWQgZW5kIG9mIHJlZ2V4cABSZWdFeHAAc3VwAGludmFsaWQgZ3JvdXAAcG9wAGNvbnRpbnVlIG11c3QgYmUgaW5zaWRlIGxvb3AAYmZfbG9naWNfb3AAZHVtcABudW1fa2V5c19jbXAAdXNlIHN0cmlwAG1hcABmbGF0TWFwAFdlYWtNYXAAZXhwZWN0aW5nICd7JyBhZnRlciBccABsb2cxcABkaXZpc2lvbiBieSB6ZXJvADBvAGhhc093bgByZXR1cm4AcHJvbWlzZSBzZWxmIHJlc29sdXRpb24Ab3V0IG9mIG1lbW9yeSBpbiByZWdleHAgZXhlY3V0aW9uAGRlc2NyaXB0aW9uACFtLT5ldmFsX2hhc19leGNlcHRpb24AIW1vZHVsZS0+ZXZhbF9oYXNfZXhjZXB0aW9uAHByb3h5OiBkZWZpbmVQcm9wZXJ0eSBleGNlcHRpb24AanNfYXN5bmNfZ2VuZXJhdG9yX3Jlc29sdmVfZnVuY3Rpb24AanNfY3JlYXRlX2Z1bmN0aW9uAHNldC9hZGQgaXMgbm90IGEgZnVuY3Rpb24AcmV0dXJuIG5vdCBpbiBhIGZ1bmN0aW9uAEFzeW5jR2VuZXJhdG9yRnVuY3Rpb24AY2FsbEV4dGVybmFsRnVuY3Rpb24AQXN5bmNGdW5jdGlvbgBqc19pbm5lcl9tb2R1bGVfZXZhbHVhdGlvbgAhbS0+YXN5bmNfZXZhbHVhdGlvbgBtb2R1bGUtPmFzeW5jX2V2YWx1YXRpb24AaW52YWxpZCBvcGVyYXRpb24AdW5zdXBwb3J0ZWQgb3BlcmF0aW9uAGF3YWl0IGluIGRlZmF1bHQgZXhwcmVzc2lvbgB5aWVsZCBpbiBkZWZhdWx0IGV4cHJlc3Npb24AaW52YWxpZCBkZWNpbWFsIGVzY2FwZSBpbiByZWd1bGFyIGV4cHJlc3Npb24AYmFjayByZWZlcmVuY2Ugb3V0IG9mIHJhbmdlIGluIHJlZ3VsYXIgZXhwcmVzc2lvbgBpbnZhbGlkIGVzY2FwZSBzZXF1ZW5jZSBpbiByZWd1bGFyIGV4cHJlc3Npb24AZXhwZWN0ZWQgJ29mJyBvciAnaW4nIGluIGZvciBjb250cm9sIGV4cHJlc3Npb24AdG9vIGNvbXBsaWNhdGVkIGRlc3RydWN0dXJpbmcgZXhwcmVzc2lvbgBleHBlY3RlZCAnfScgYWZ0ZXIgdGVtcGxhdGUgZXhwcmVzc2lvbgB0b1ByZWNpc2lvbgBhc2luAGpvaW4AbWluAGNvcHlXaXRoaW4AdGVtcGxhdGUgbGl0ZXJhbCBjYW5ub3QgYXBwZWFyIGluIGFuIG9wdGlvbmFsIGNoYWluAGNpcmN1bGFyIHByb3RvdHlwZSBjaGFpbgBhc3NpZ24AIXktPnNpZ24AaXNGcm96ZW4AKHBvcyArIGxlbikgPD0gYmNfYnVmX2xlbgB1bmV4cGVjdGVkIGVsbGlwc2lzIHRva2VuAHRoZW4Ac2V0dGVyIGlzIGZvcmJpZGRlbgBudWxsIG9yIHVuZGVmaW5lZCBhcmUgZm9yYmlkZGVuAGF0YW4AbmFuAG5vdCBhIGJvb2xlYW4AQm9vbGVhbgBnY19zY2FuAGJhZCBub3JtYWxpemF0aW9uIGZvcm0ASlNfTmV3U3ltYm9sRnJvbUF0b20AZnJvbQByYW5kb20AdHJpbQBiZl9kaXZyZW0AbS0+Y3ljbGVfcm9vdCA9PSBtAGltdWwAbm90IGEgc3ltYm9sAFN5bWJvbABSZWdFeHAgZXhlYyBtZXRob2QgbXVzdCByZXR1cm4gYW4gb2JqZWN0IG9yIG51bGwAcGFyZW50IHByb3RvdHlwZSBtdXN0IGJlIGFuIG9iamVjdCBvciBudWxsAGNhbm5vdCBzZXQgcHJvcGVydHkgJyVzJyBvZiBudWxsAGNhbm5vdCByZWFkIHByb3BlcnR5ICclcycgb2YgbnVsbABOdWxsAGZpbGwAbmV3IEFycmF5QnVmZmVyIGlzIHRvbyBzbWFsbABUeXBlZEFycmF5IGxlbmd0aCBpcyB0b28gc21hbGwAY2FsbABkb3RBbGwAbWF0Y2hBbGwAcmVwbGFjZUFsbABjZWlsAHVwZGF0ZV9sYWJlbABiY19idWZbcG9zXSA9PSBPUF9sYWJlbABldmFsAGludmFsaWQgYmlnaW50IGxpdGVyYWwAaW52YWxpZCBudW1iZXIgbGl0ZXJhbABtYWxmb3JtZWQgZXNjYXBlIHNlcXVlbmNlIGluIHN0cmluZyBsaXRlcmFsAGJmX2V4cF9pbnRlcm5hbABiZl9sb2dfaW50ZXJuYWwAYmZfZnRvYV9pbnRlcm5hbABKU19TZXRQcm9wZXJ0eUludGVybmFsAEpTX0dldE93blByb3BlcnR5TmFtZXNJbnRlcm5hbABfX0pTX0V2YWxJbnRlcm5hbAB0b0V4cG9uZW50aWFsAHNlYWwAZ2xvYmFsAGJsaW5rAHJldHVybiBpbiBhIHN0YXRpYyBpbml0aWFsaXplciBibG9jawBzdGFjawBscmVfZXhlY19iYWNrdHJhY2sAcy0+aXNfd2VhawBiZl9wb3dfdWkAc2V0TW9udGgAZ2V0TW9udGgAc2V0VVRDTW9udGgAZ2V0VVRDTW9udGgAaW52YWxpZCBrZXl3b3JkOiB3aXRoAHN0YXJ0c1dpdGgAZW5kc1dpdGgAcHJvcCA9PSBKU19BVE9NX2xlbmd0aABpbnZhbGlkIGFycmF5IGxlbmd0aABpbnZhbGlkIGFycmF5IGJ1ZmZlciBsZW5ndGgAaW52YWxpZCBsZW5ndGgAaW52YWxpZCBieXRlTGVuZ3RoAE1hdGgAcHVzaABhY29zaABKU19SZXNpemVBdG9tSGFzaABhc2luaABhdGFuaABicmVhayBtdXN0IGJlIGluc2lkZSBsb29wIG9yIHN3aXRjaABtYXRjaABuaXBfY2F0Y2gAc2VhcmNoAGZvckVhY2gAYmZfbG9nAEFycmF5IHRvbyBsb25nAHN0cmluZyB0b28gbG9uZwBBcnJheSBsb28gbG9uZwBzdWJzdHJpbmcAY2Fubm90IGNvbnZlcnQgc3ltYm9sIHRvIHN0cmluZwB1bmV4cGVjdGVkIGVuZCBvZiBzdHJpbmcAbm90IGEgc3RyaW5nAGludmFsaWQgY2hhcmFjdGVyIGluIGEgSlNPTiBzdHJpbmcAdG9TdHJpbmcAdG9EYXRlU3RyaW5nAHRvTG9jYWxlRGF0ZVN0cmluZwB0b1RpbWVTdHJpbmcAdG9Mb2NhbGVUaW1lU3RyaW5nAHRvTG9jYWxlU3RyaW5nAHRvR01UU3RyaW5nAEpTU3RyaW5nAHRvSVNPU3RyaW5nAHRvVVRDU3RyaW5nAGpzX2lubmVyX21vZHVsZV9saW5raW5nAGR1cGxpY2F0ZSBpbXBvcnQgYmluZGluZwBpbnZhbGlkIGltcG9ydCBiaW5kaW5nAHByb21pc2UgaXMgcGVuZGluZwBiaWcAcmVnZXhwIG11c3QgaGF2ZSB0aGUgJ2cnIGZsYWcAb2YAaW5mAEluZgBkaWZmID09IChpbnQ4X3QpZGlmZgBkaWZmID09IChpbnQxNl90KWRpZmYAaHJlZgBnY19kZWNyZWYAZnJlZV92YXJfcmVmAG9wdGltaXplX3Njb3BlX21ha2VfZ2xvYmFsX3JlZgByZXNldF93ZWFrX3JlZgBkZWxldGVfd2Vha19yZWYAb3B0aW1pemVfc2NvcGVfbWFrZV9yZWYAaW5kZXhPZgBsYXN0SW5kZXhPZgB2YWx1ZU9mAHNldFByb3RvdHlwZU9mAGdldFByb3RvdHlwZU9mAGlzUHJvdG90eXBlT2YAJS4qZgBmb250c2l6ZQBuZXdfc2l6ZSA8PSBzaC0+cHJvcF9zaXplAGRlc2NyIDwgcnQtPmF0b21fc2l6ZQBhdG9tIDwgcnQtPmF0b21fc2l6ZQBjb21wdXRlX3N0YWNrX3NpemUAbiA8IGJ1Zl9zaXplAG5vcm1hbGl6ZQBjcl9yZWdleHBfY2Fub25pY2FsaXplAGZyZWV6ZQByZXNvbHZlAHRvUHJpbWl0aXZlAHB1dF9sdmFsdWUAdW5rbm93biB1bmljb2RlIHByb3BlcnR5IHZhbHVlAHJlc3QgZWxlbWVudCBjYW5ub3QgaGF2ZSBhIGRlZmF1bHQgdmFsdWUAaW52YWxpZCByZXQgdmFsdWUAX19KU19BdG9tVG9WYWx1ZQBfX3F1b3RlAGlzRmluaXRlAGRlbGV0ZQBjcmVhdGUAc2V0RGF0ZQBnZXREYXRlAHNldFVUQ0RhdGUAZ2V0VVRDRGF0ZQBJbnZhbGlkIERhdGUAcmV2ZXJzZQBwYXJzZQBwcm94eSBwcmV2ZW50RXh0ZW5zaW9ucyBoYW5kbGVyIHJldHVybmVkIGZhbHNlAG1vZHVsZSBuYW1lc3BhY2UgcHJvcGVydGllcyBoYXZlIHdyaXRhYmxlID0gZmFsc2UAUHJvbWlzZQB0b0xvd2VyQ2FzZQB0b0xvY2FsZUxvd2VyQ2FzZQB0b1VwcGVyQ2FzZQB0b0xvY2FsZVVwcGVyQ2FzZQBpZ25vcmVDYXNlAGxvY2FsZUNvbXBhcmUAcHJveHk6IGluY29uc2lzdGVudCBwcm90b3R5cGUAcHJveHk6IGJhZCBwcm90b3R5cGUAbm90IGEgcHJvdG90eXBlAGludmFsaWQgb2JqZWN0IHR5cGUAdW5lc2NhcGUAbm9uZQByZXN0IGVsZW1lbnQgbXVzdCBiZSB0aGUgbGFzdCBvbmUAbXVsdGlsaW5lACAgcGMybGluZQBhc3luY19mdW5jX3Jlc3VtZQBzb21lAEpTX0ZyZWVSdW50aW1lAEpTUnVudGltZQBzZXRUaW1lAGdldFRpbWUAYXN5bmNfZnVuY19mcmVlX2ZyYW1lAHNldF9vYmplY3RfbmFtZQBleHBlY3RpbmcgcHJvcGVydHkgbmFtZQB1bmtub3duIHVuaWNvZGUgcHJvcGVydHkgbmFtZQBpbnZhbGlkIHByb3BlcnR5IG5hbWUAZHVwbGljYXRlIF9fcHJvdG9fXyBwcm9wZXJ0eSBuYW1lAGludmFsaWQgcmVkZWZpbml0aW9uIG9mIHBhcmFtZXRlciBuYW1lAGV4cGVjdGluZyBncm91cCBuYW1lAGR1cGxpY2F0ZSBncm91cCBuYW1lAGludmFsaWQgZ3JvdXAgbmFtZQBkdXBsaWNhdGUgbGFiZWwgbmFtZQBpbnZhbGlkIGZpcnN0IGNoYXJhY3RlciBvZiBwcml2YXRlIG5hbWUAaW52YWxpZCBsZXhpY2FsIHZhcmlhYmxlIG5hbWUAaW52YWxpZCBtZXRob2QgbmFtZQBleHBlY3RpbmcgZmllbGQgbmFtZQBpbnZhbGlkIGZpZWxkIG5hbWUAY2xhc3Mgc3RhdGVtZW50IHJlcXVpcmVzIGEgbmFtZQBmaWxlTmFtZQBqc19saW5rX21vZHVsZQBqc19ldmFsdWF0ZV9tb2R1bGUAbW9kdWxlLT5jeWNsZV9yb290ID09IG1vZHVsZQBjb21waWxlAG9iamVjdCBpcyBub3QgZXh0ZW5zaWJsZQBwcm94eTogaW5jb25zaXN0ZW50IGlzRXh0ZW5zaWJsZQBjYW5ub3QgaGF2ZSBzZXR0ZXIvZ2V0dGVyIGFuZCB2YWx1ZSBvciB3cml0YWJsZQBwcm9wZXJ0eSBpcyBub3QgY29uZmlndXJhYmxlAHZhbHVlIGlzIG5vdCBpdGVyYWJsZQBwcm9wZXJ0eUlzRW51bWVyYWJsZQBtaXNzaW5nIGluaXRpYWxpemVyIGZvciBjb25zdCB2YXJpYWJsZQBsZXhpY2FsIHZhcmlhYmxlAGludmFsaWQgcmVkZWZpbml0aW9uIG9mIGEgdmFyaWFibGUAcmV2b2NhYmxlAHN0cmlrZQBtcF9kaXZub3JtX2xhcmdlAGludmFsaWQgY2xhc3MgcmFuZ2UAbWVzc2FnZQBpbnZhbGlkIGx2YWx1ZSBpbiBzdHJpY3QgbW9kZQBpbnZhbGlkIHZhcmlhYmxlIG5hbWUgaW4gc3RyaWN0IG1vZGUAY2Fubm90IGRlbGV0ZSBhIGRpcmVjdCByZWZlcmVuY2UgaW4gc3RyaWN0IG1vZGUAb2N0YWwgZXNjYXBlIHNlcXVlbmNlcyBhcmUgbm90IGFsbG93ZWQgaW4gc3RyaWN0IG1vZGUAb2N0YWwgbGl0ZXJhbHMgYXJlIGRlcHJlY2F0ZWQgaW4gc3RyaWN0IG1vZGUAdW5pY29kZQAgIGJ5dGVjb2RlAEpTRnVuY3Rpb25CeXRlY29kZQBza2lwX2RlYWRfY29kZQBpbnZhbGlkIGFyZ3VtZW50IG5hbWUgaW4gc3RyaWN0IGNvZGUAaW52YWxpZCBmdW5jdGlvbiBuYW1lIGluIHN0cmljdCBjb2RlAGludmFsaWQgcmVkZWZpbml0aW9uIG9mIGdsb2JhbCBpZGVudGlmaWVyIGluIG1vZHVsZSBjb2RlAGltcG9ydC5tZXRhIG9ubHkgdmFsaWQgaW4gbW9kdWxlIGNvZGUAZnJvbUNoYXJDb2RlAGludmFsaWQgZm9yIGluL29mIGxlZnQgaGFuZC1zaWRlAGludmFsaWQgYXNzaWdubWVudCBsZWZ0LWhhbmQgc2lkZQByZWR1Y2UAc291cmNlACd0aGlzJyBjYW4gYmUgaW5pdGlhbGl6ZWQgb25seSBvbmNlAHByb3BlcnR5IGNvbnN0cnVjdG9yIGFwcGVhcnMgbW9yZSB0aGFuIG9uY2UAaW52YWxpZCBVVEYtOCBzZXF1ZW5jZQBjaXJjdWxhciByZWZlcmVuY2UAc2xpY2UAc3BsaWNlAHJhY2UAcmVwbGFjZQAlKy4qZQB1bmV4cGVjdGVkICdhd2FpdCcga2V5d29yZAB1bmV4cGVjdGVkICd5aWVsZCcga2V5d29yZABtYXBfZGVjcmVmX3JlY29yZABpdGVyYXRvciBkb2VzIG5vdCBoYXZlIGEgdGhyb3cgbWV0aG9kAG9iamVjdCBuZWVkcyB0b0lTT1N0cmluZyBtZXRob2QAJ3N1cGVyJyBpcyBvbmx5IHZhbGlkIGluIGEgbWV0aG9kAGZyb3VuZABfX2JmX3JvdW5kAGJyZWFrL2NvbnRpbnVlIGxhYmVsIG5vdCBmb3VuZABvdXQgb2YgYm91bmQAZmluZABiaW5kAGludmFsaWQgaW5kZXggZm9yIGFwcGVuZABleHRyYW5lb3VzIGNoYXJhY3RlcnMgYXQgdGhlIGVuZAB1bmV4cGVjdGVkIGRhdGEgYXQgdGhlIGVuZAB1bmV4cGVjdGVkIGVuZABpbnZhbGlkIGluY3JlbWVudC9kZWNyZW1lbnQgb3BlcmFuZABpbnZhbGlkICdpbnN0YW5jZW9mJyByaWdodCBvcGVyYW5kAGludmFsaWQgJ2luJyBvcGVyYW5kAHRyaW1FbmQAcGFkRW5kAGJvbGQAJWxsZABnY19kZWNyZWZfY2hpbGQAcmVzb2x2ZV9zY29wZV9wcml2YXRlX2ZpZWxkAGNhbm5vdCBkZWxldGUgYSBwcml2YXRlIGNsYXNzIGZpZWxkAGV4cGVjdGluZyA8YnJhbmQ+IHByaXZhdGUgZmllbGQAJXMgaXMgbm90IGluaXRpYWxpemVkAGZpeGVkAHRvRml4ZWQAc2V0X29iamVjdF9uYW1lX2NvbXB1dGVkAHJlZ2V4IG5vdCBzdXBwb3J0ZWQAZXZhbCBpcyBub3Qgc3VwcG9ydGVkAFJlZ0V4cCBhcmUgbm90IHN1cHBvcnRlZAB0b1NvcnRlZABpbnRlcnJ1cHRlZAAhcy0+aXNfY29tcGxldGVkACVzIG9iamVjdCBleHBlY3RlZABpZGVudGlmaWVyIGV4cGVjdGVkAGJ5dGVjb2RlIGZ1bmN0aW9uIGV4cGVjdGVkAHN0cmluZyBleHBlY3RlZABmcm9tIGNsYXVzZSBleHBlY3RlZABmdW5jdGlvbiBuYW1lIGV4cGVjdGVkAHZhcmlhYmxlIG5hbWUgZXhwZWN0ZWQAbWV0YSBleHBlY3RlZABqc19hc3luY19tb2R1bGVfZXhlY3V0aW9uX3JlamVjdGVkAGpzX3NldF9tb2R1bGVfZXZhbHVhdGVkAG1lbW9yeSBhbGxvY2F0ZWQAbWVtb3J5IHVzZWQAdG9SZXZlcnNlZABkZXJpdmVkIGNsYXNzIGNvbnN0cnVjdG9yIG11c3QgcmV0dXJuIGFuIG9iamVjdCBvciB1bmRlZmluZWQAY2Fubm90IHNldCBwcm9wZXJ0eSAnJXMnIG9mIHVuZGVmaW5lZABjYW5ub3QgcmVhZCBwcm9wZXJ0eSAnJXMnIG9mIHVuZGVmaW5lZABmbGFncyBtdXN0IGJlIHVuZGVmaW5lZABVbmRlZmluZWQAcHJpdmF0ZSBjbGFzcyBmaWVsZCBpcyBhbHJlYWR5IGRlZmluZWQAJyVzJyBpcyBub3QgZGVmaW5lZABncm91cCBuYW1lIG5vdCBkZWZpbmVkAGlzV2VsbEZvcm1lZAB0b1dlbGxGb3JtZWQAYWxsU2V0dGxlZABqc19hc3luY19tb2R1bGVfZXhlY3V0aW9uX2Z1bGZpbGxlZABjYW5ub3QgYmUgY2FsbGVkAGlzU2VhbGVkACFzaC0+aXNfaGFzaGVkAEFycmF5QnVmZmVyIGlzIGRldGFjaGVkAGpzX2FycmF5X3RvU3BsaWNlZABhZGQAJSswN2QAJTA0ZAAlMDJkJTAyZABwJStkACVjJStkACUwMmQvJTAyZC8lMCpkACUuM3MgJS4zcyAlMDJkICUwKmQAcCVkACVjJWQAOiVkAGludmFsaWQgdGhyb3cgdmFyIHR5cGUgJWQAc2MAanNfZGVmX21hbGxvYwB0cnVuYwBnYwBleGVjAGJmX2ludGVnZXJfdG9fcmFkaXhfcmVjAC90bXAvcXVpY2tqcy9xdWlja2pzLmMAL3RtcC9xdWlja2pzL2xpYnJlZ2V4cC5jAC90bXAvcXVpY2tqcy9saWJiZi5jAC90bXAvcXVpY2tqcy9saWJ1bmljb2RlLmMAc3ViAHByb21pc2VfcmVhY3Rpb25fam9iAGpzX3Byb21pc2VfcmVzb2x2ZV90aGVuYWJsZV9qb2IAMGIAciAhPSBhICYmIHIgIT0gYgBxICE9IGEgJiYgcSAhPSBiAHJ3YQByICE9IGEAX19sb29rdXBTZXR0ZXJfXwBfX2RlZmluZVNldHRlcl9fAF9fbG9va3VwR2V0dGVyX18AX19kZWZpbmVHZXR0ZXJfXwBfX3Byb3RvX18AW1N5bWJvbC5zcGxpdF0AW1N5bWJvbC5zcGVjaWVzXQBbU3ltYm9sLml0ZXJhdG9yXQBbU3ltYm9sLmFzeW5jSXRlcmF0b3JdAFtTeW1ib2wubWF0Y2hBbGxdAFtTeW1ib2wubWF0Y2hdAFtTeW1ib2wuc2VhcmNoXQBbU3ltYm9sLnRvU3RyaW5nVGFnXQBbU3ltYm9sLnRvUHJpbWl0aXZlXQBbdW5zdXBwb3J0ZWQgdHlwZV0AW2Z1bmN0aW9uIGJ5dGVjb2RlXQBbU3ltYm9sLmhhc0luc3RhbmNlXQBbU3ltYm9sLnJlcGxhY2VdAFsAJTAyZDolMDJkOiUwMmQuJTAzZFoAUE9TSVRJVkVfSU5GSU5JVFkATkVHQVRJVkVfSU5GSU5JVFkAcC0+Y2xhc3NfaWQgPT0gSlNfQ0xBU1NfQVJSQVkAc3RhY2tfbGVuIDwgUE9QX1NUQUNLX0xFTl9NQVgALSUwMmQtJTAyZFQASlNfQXRvbUdldFN0clJUAG9wY29kZSA8IFJFT1BfQ09VTlQASlNfVkFMVUVfR0VUX1RBRyhmdW5jX3JldCkgPT0gSlNfVEFHX0lOVABCWVRFU19QRVJfRUxFTUVOVAAlMDJkOiUwMmQ6JTAyZCBHTVQASlNfVkFMVUVfR0VUX1RBRyhzZi0+Y3VyX2Z1bmMpID09IEpTX1RBR19PQkpFQ1QAdmFyX2tpbmQgPT0gSlNfVkFSX1BSSVZBVEVfU0VUVEVSAE1BWF9TQUZFX0lOVEVHRVIATUlOX1NBRkVfSU5URUdFUgBhc1VpbnROAGFzSW50TgBpc05hTgBEYXRlIHZhbHVlIGlzIE5hTgB0b0pTT04ARVBTSUxPTgBwLT5nY19vYmpfdHlwZSA9PSBKU19HQ19PQkpfVFlQRV9KU19PQkpFQ1QgfHwgcC0+Z2Nfb2JqX3R5cGUgPT0gSlNfR0NfT0JKX1RZUEVfRlVOQ1RJT05fQllURUNPREUgfHwgcC0+Z2Nfb2JqX3R5cGUgPT0gSlNfR0NfT0JKX1RZUEVfQVNZTkNfRlVOQ1RJT04ATkFOACUwMmQ6JTAyZDolMDJkICVjTQBzdGFja190b3AgPT0gTlVMTABzLT5sYWJlbF9zbG90c1tsYWJlbF0uZmlyc3RfcmVsb2MgPT0gTlVMTABsYWJlbF9zbG90c1tpXS5maXJzdF9yZWxvYyA9PSBOVUxMAHBycyAhPSBOVUxMAHNmLT5jdXJfc3AgIT0gTlVMTABzZiAhPSBOVUxMAG1yMSAhPSBOVUxMAHZhcl9raW5kICE9IEpTX1ZBUl9OT1JNQUwAYi0+ZnVuY19raW5kID09IEpTX0ZVTkNfTk9STUFMAGVuY29kZVVSSQBkZWNvZGVVUkkAUEkAc3BlY2lhbCA9PSBQVVRfTFZBTFVFX05PS0VFUCB8fCBzcGVjaWFsID09IFBVVF9MVkFMVUVfTk9LRUVQX0RFUFRIAHMtPnN0YXRlID09IEpTX0FTWU5DX0dFTkVSQVRPUl9TVEFURV9FWEVDVVRJTkcAbTEtPnN0YXR1cyA9PSBKU19NT0RVTEVfU1RBVFVTX0VWQUxVQVRJTkcAbTEtPnN0YXR1cyA9PSBKU19NT0RVTEVfU1RBVFVTX0xJTktJTkcAcHJlYyAhPSBCRl9QUkVDX0lORgBwcmVjMSAhPSBCRl9QUkVDX0lORgAwMTIzNDU2Nzg5QUJDREVGAFNJWkUATUFYX1ZBTFVFAE1JTl9WQUxVRQBOQU1FAGV2YWxfdHlwZSA9PSBKU19FVkFMX1RZUEVfR0xPQkFMIHx8IGV2YWxfdHlwZSA9PSBKU19FVkFMX1RZUEVfTU9EVUxFAExPRzJFAExPRzEwRQBzLT5zdGF0ZSA9PSBKU19BU1lOQ19HRU5FUkFUT1JfU1RBVEVfQVdBSVRJTkdfUkVUVVJOIHx8IHMtPnN0YXRlID09IEpTX0FTWU5DX0dFTkVSQVRPUl9TVEFURV9DT01QTEVURUQAbS0+c3RhdHVzID09IEpTX01PRFVMRV9TVEFUVVNfVU5MSU5LRUQgfHwgbS0+c3RhdHVzID09IEpTX01PRFVMRV9TVEFUVVNfTElOS0VEIHx8IG0tPnN0YXR1cyA9PSBKU19NT0RVTEVfU1RBVFVTX0VWQUxVQVRJTkdfQVNZTkMgfHwgbS0+c3RhdHVzID09IEpTX01PRFVMRV9TVEFUVVNfRVZBTFVBVEVEAG0xLT5zdGF0dXMgPT0gSlNfTU9EVUxFX1NUQVRVU19FVkFMVUFUSU5HIHx8IG0xLT5zdGF0dXMgPT0gSlNfTU9EVUxFX1NUQVRVU19FVkFMVUFUSU5HX0FTWU5DIHx8IG0xLT5zdGF0dXMgPT0gSlNfTU9EVUxFX1NUQVRVU19FVkFMVUFURUQAbTEtPnN0YXR1cyA9PSBKU19NT0RVTEVfU1RBVFVTX0xJTktJTkcgfHwgbTEtPnN0YXR1cyA9PSBKU19NT0RVTEVfU1RBVFVTX0xJTktFRCB8fCBtMS0+c3RhdHVzID09IEpTX01PRFVMRV9TVEFUVVNfRVZBTFVBVElOR19BU1lOQyB8fCBtMS0+c3RhdHVzID09IEpTX01PRFVMRV9TVEFUVVNfRVZBTFVBVEVEAG0tPnN0YXR1cyA9PSBKU19NT0RVTEVfU1RBVFVTX0xJTktFRABtLT5zdGF0dXMgPT0gSlNfTU9EVUxFX1NUQVRVU19VTkxJTktFRABVVEMAbS0+c3RhdHVzID09IEpTX01PRFVMRV9TVEFUVVNfRVZBTFVBVElOR19BU1lOQwBtb2R1bGUtPnN0YXR1cyA9PSBKU19NT0RVTEVfU1RBVFVTX0VWQUxVQVRJTkdfQVNZTkMAPGlucHV0PgA8aW5pdFNjcmlwdD4APGV2YWxTY3JpcHQ+ADxzZXQ+ADxhbm9ueW1vdXM+ADxjb21tRnVuPgA8Y2FsbEV4dGVybmFsRnVuY3Rpb24+ADxudWxsPgBiaWdpbnQgb3BlcmFuZHMgYXJlIGZvcmJpZGRlbiBmb3IgPj4+ACZxdW90OwBzZXRVaW50OABnZXRVaW50OABzZXRJbnQ4AGdldEludDgAbWFsZm9ybWVkIFVURi04AHJhZGl4IG11c3QgYmUgYmV0d2VlbiAyIGFuZCAzNgBzZXRVaW50MTYAZ2V0VWludDE2AHNldEludDE2AGdldEludDE2AGFyZ2MgPT0gNQBzZXRCaWdVaW50NjQAZ2V0QmlnVWludDY0AHNldEJpZ0ludDY0AGdldEJpZ0ludDY0AHNldEZsb2F0NjQAZ2V0RmxvYXQ2NABhcmdjID09IDMAYXRhbjIAbG9nMgBTUVJUMV8yAFNRUlQyAExOMgBjbHozMgBzZXRVaW50MzIAZ2V0VWludDMyAHNldEludDMyAGdldEludDMyAHNldEZsb2F0MzIAZ2V0RmxvYXQzMgBzdGFja19sZW4gPj0gMgBKU19BdG9tSXNOdW1lcmljSW5kZXgxAGpzX2ZjdnQxAEpTX0NvbXBhY3RCaWdJbnQxAGV4cG0xAHIgIT0gYTEgJiYgciAhPSBiMQBscy0+YWRkciA9PSAtMQBucSA+PSAxAHN0YWNrX2xlbiA+PSAxAHAtPmhlYWRlci5yZWZfY291bnQgPT0gMQBwLT5zaGFwZS0+aGVhZGVyLnJlZl9jb3VudCA9PSAxAHN0YWNrX2xlbiA9PSAxAGpzX2ZyZWVfc2hhcGUwAGxvZzEwAExOMTAAcC0+cmVmX2NvdW50ID4gMAB2YXJfcmVmLT5oZWFkZXIucmVmX2NvdW50ID4gMABtLT5wZW5kaW5nX2FzeW5jX2RlcGVuZGVuY2llcyA+IDAAc3RhY2tfc2l6ZSA+IDAAY3Bvb2xfaWR4ID49IDAAcnQtPmF0b21fY291bnQgPj0gMABscy0+cmVmX2NvdW50ID49IDAAcy0+aXNfZXZhbCB8fCBzLT5jbG9zdXJlX3Zhcl9jb3VudCA9PSAwAHAtPnJlZl9jb3VudCA9PSAwAGN0eC0+aGVhZGVyLnJlZl9jb3VudCA9PSAwAHNoLT5oZWFkZXIucmVmX2NvdW50ID09IDAAcC0+bWFyayA9PSAwAChwci0+dS5pbml0LnJlYWxtX2FuZF9pZCAmIDMpID09IDAAKG5ld19oYXNoX3NpemUgJiAobmV3X2hhc2hfc2l6ZSAtIDEpKSA9PSAwAGkgIT0gMABzaXplICE9IDAAXiRcLiorPygpW117fXwvADwvADAuAG1pc3NpbmcgYmluZGluZyBwYXR0ZXJuLi4uAGJpZ2ludCBhcmd1bWVudCB3aXRoIHVuYXJ5ICsAYXN5bmMgZnVuY3Rpb24gKgAKfSkAbGlzdF9lbXB0eSgmcnQtPmdjX29ial9saXN0KQBqID09IChzaC0+cHJvcF9jb3VudCAtIHNoLT5kZWxldGVkX3Byb3BfY291bnQpACFfX0pTX0F0b21Jc1RhZ2dlZEludChkZXNjcikAIWF0b21faXNfZnJlZShwKQAobnVsbCkAIChuYXRpdmUpAGpzX2NsYXNzX2hhc19ieXRlY29kZShwLT5jbGFzc19pZCkAbmlwX2NhdGNoOiBubyBjYXRjaCBvcCAocGM9JWQpAGluY29uc2lzdGVudCBjYXRjaCBwb3NpdGlvbjogJWQgJWQgKHBjPSVkKQBpbmNvbnNpc3RlbnQgc3RhY2sgc2l6ZTogJWQgJWQgKHBjPSVkKQBieXRlY29kZSBidWZmZXIgb3ZlcmZsb3cgKG9wPSVkLCBwYz0lZCkAc3RhY2sgb3ZlcmZsb3cgKG9wPSVkLCBwYz0lZCkAc3RhY2sgdW5kZXJmbG93IChvcD0lZCwgcGM9JWQpAGludmFsaWQgb3Bjb2RlIChvcD0lZCwgcGM9JWQpACg/OikAaWR4IDwgY291bnRvZihjYXNlX2NvbnZfdGFibGUxKQBubyBmdW5jdGlvbiBmaWxlbmFtZSBmb3IgaW1wb3J0KCkALV8uIX4qJygpACBhbm9ueW1vdXMoAFN5bWJvbCgAZXhwZWN0aW5nICd9JwBjbGFzcyBjb25zdHJ1Y3RvcnMgbXVzdCBiZSBpbnZva2VkIHdpdGggJ25ldycAZXhwZWN0aW5nICdhcycAdW5leHBlY3RlZCB0b2tlbiBpbiBleHByZXNzaW9uOiAnJS4qcycAdW5leHBlY3RlZCB0b2tlbjogJyUuKnMnAHJlZGVjbGFyYXRpb24gb2YgJyVzJwBkdXBsaWNhdGUgZXhwb3J0ZWQgbmFtZSAn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XwAAcF8AAAwLBQQCAgAAuwAAAHoAAAB7AAAAvAAAAHwAAAB9AAAAvQAAAHwAAAB9AAAAvgAAAFIAAABTAAAAvwAAAH4AAAB/AAAAwAAAAH4AAAB/AAAALwAAAIAAAACBAAAAwQAAAFIAAABTAAAAwgAAAIIAAACDAAAAAAAAAOkWAAAaFwAAJRcAAN0WAAAQFwAANBcAAPMWAAABFwAAY29weVdpdGhpbgBlbnRyaWVzAGZpbGwAZmluZABmaW5kSW5kZXgAZmluZExhc3QAZmluZExhc3RJbmRleABmbGF0AGZsYXRNYXAAaW5jbHVkZXMAa2V5cwB0b1JldmVyc2VkAHRvU29ydGVkAHRvU3BsaWNlZAB2YWx1ZXMAAAAAAAEBAgIDAwIDAAAAAAAAbnVsbABmYWxzZQB0cnVlAGlmAGVsc2UAcmV0dXJuAHZhcgB0aGlzAGRlbGV0ZQB2b2lkAHR5cGVvZgBuZXcAaW4AaW5zdGFuY2VvZgBkbwB3aGlsZQBmb3IAYnJlYWsAY29udGludWUAc3dpdGNoAGNhc2UAZGVmYXVsdAB0aHJvdwB0cnkAY2F0Y2gAZmluYWxseQBmdW5jdGlvbgBkZWJ1Z2dlcgB3aXRoAGNsYXNzAGNvbnN0AGVudW0AZXhwb3J0AGV4dGVuZHMAaW1wb3J0AHN1cGVyAGltcGxlbWVudHMAaW50ZXJmYWNlAGxldABwYWNrYWdlAHByaXZhdGUAcHJvdGVjdGVkAHB1YmxpYwBzdGF0aWMAeWllbGQAYXdhaXQAAGxlbmd0aABmaWxlTmFtZQBsaW5lTnVtYmVyAG1lc3NhZ2UAY2F1c2UAZXJyb3JzAHN0YWNrAG5hbWUAdG9TdHJpbmcAdG9Mb2NhbGVTdHJpbmcAdmFsdWVPZgBldmFsAHByb3RvdHlwZQBjb25zdHJ1Y3RvcgBjb25maWd1cmFibGUAd3JpdGFibGUAZW51bWVyYWJsZQB2YWx1ZQBnZXQAc2V0AG9mAF9fcHJvdG9fXwB1bmRlZmluZWQAbnVtYmVyAGJvb2xlYW4Ac3RyaW5nAG9iamVjdABzeW1ib2wAaW50ZWdlcgB1bmtub3duAGFyZ3VtZW50cwBjYWxsZWUAY2FsbGVyADxldmFsPgA8cmV0PgA8dmFyPgA8YXJnX3Zhcj4APHdpdGg+AGxhc3RJbmRleAB0YXJnZXQAaW5kZXgAaW5wdXQAZGVmaW5lUHJvcGVydGllcwBhcHBseQBqb2luAGNvbmNhdABzcGxpdABjb25zdHJ1Y3QAZ2V0UHJvdG90eXBlT2YAc2V0UHJvdG90eXBlT2YAaXNFeHRlbnNpYmxlAHByZXZlbnRFeHRlbnNpb25zAGhhcwBkZWxldGVQcm9wZXJ0eQBkZWZpbmVQcm9wZXJ0eQBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IAb3duS2V5cwBhZGQAZG9uZQBuZXh0AHZhbHVlcwBzb3VyY2UAZmxhZ3MAZ2xvYmFsAHVuaWNvZGUAcmF3AG5ldy50YXJnZXQAdGhpcy5hY3RpdmVfZnVuYwA8aG9tZV9vYmplY3Q+ADxjb21wdXRlZF9maWVsZD4APHN0YXRpY19jb21wdXRlZF9maWVsZD4APGNsYXNzX2ZpZWxkc19pbml0PgA8YnJhbmQ+ACNjb25zdHJ1Y3RvcgBhcwBmcm9tAG1ldGEAKmRlZmF1bHQqACoATW9kdWxlAHRoZW4AcmVzb2x2ZQByZWplY3QAcHJvbWlzZQBwcm94eQByZXZva2UAYXN5bmMAZXhlYwBncm91cHMAaW5kaWNlcwBzdGF0dXMAcmVhc29uAGdsb2JhbFRoaXMAYmlnaW50AG5vdC1lcXVhbAB0aW1lZC1vdXQAb2sAdG9KU09OAE9iamVjdABBcnJheQBFcnJvcgBOdW1iZXIAU3RyaW5nAEJvb2xlYW4AU3ltYm9sAEFyZ3VtZW50cwBNYXRoAEpTT04ARGF0ZQBGdW5jdGlvbgBHZW5lcmF0b3JGdW5jdGlvbgBGb3JJbkl0ZXJhdG9yAFJlZ0V4cABBcnJheUJ1ZmZlcgBTaGFyZWRBcnJheUJ1ZmZlcgBVaW50OENsYW1wZWRBcnJheQBJbnQ4QXJyYXkAVWludDhBcnJheQBJbnQxNkFycmF5AFVpbnQxNkFycmF5AEludDMyQXJyYXkAVWludDMyQXJyYXkAQmlnSW50NjRBcnJheQBCaWdVaW50NjRBcnJheQBGbG9hdDMyQXJyYXkARmxvYXQ2NEFycmF5AERhdGFWaWV3AEJpZ0ludABNYXAAU2V0AFdlYWtNYXAAV2Vha1NldABNYXAgSXRlcmF0b3IAU2V0IEl0ZXJhdG9yAEFycmF5IEl0ZXJhdG9yAFN0cmluZyBJdGVyYXRvcgBSZWdFeHAgU3RyaW5nIEl0ZXJhdG9yAEdlbmVyYXRvcgBQcm94eQBQcm9taXNlAFByb21pc2VSZXNvbHZlRnVuY3Rpb24AUHJvbWlzZVJlamVjdEZ1bmN0aW9uAEFzeW5jRnVuY3Rpb24AQXN5bmNGdW5jdGlvblJlc29sdmUAQXN5bmNGdW5jdGlvblJlamVjdABBc3luY0dlbmVyYXRvckZ1bmN0aW9uAEFzeW5jR2VuZXJhdG9yAEV2YWxFcnJvcgBSYW5nZUVycm9yAFJlZmVyZW5jZUVycm9yAFN5bnRheEVycm9yAFR5cGVFcnJvcgBVUklFcnJvcgBJbnRlcm5hbEVycm9yADxicmFuZD4AU3ltYm9sLnRvUHJpbWl0aXZlAFN5bWJvbC5pdGVyYXRvcgBTeW1ib2wubWF0Y2gAU3ltYm9sLm1hdGNoQWxsAFN5bWJvbC5yZXBsYWNlAFN5bWJvbC5zZWFyY2gAU3ltYm9sLnNwbGl0AFN5bWJvbC50b1N0cmluZ1RhZwBTeW1ib2wuaXNDb25jYXRTcHJlYWRhYmxlAFN5bWJvbC5oYXNJbnN0YW5jZQBTeW1ib2wuc3BlY2llcwBTeW1ib2wudW5zY29wYWJsZXMAU3ltYm9sLmFzeW5jSXRlcmF0b3IAAAAAAAEAAAAFAAEUBQABFQUAARUFAAEXBQABFwEAAQABAAEAAQABAAEAAQABAAEAAQABAAIAAQUDAAEKAQEAAAECAQABAwIAAQECAAECAwABAgQAAQMGAAECAwABAwQAAQQFAAEDAwABBAQAAQUFAAECAgABBAQAAQMDAAEDAwABBAQAAQUFAAMCAQ0DAQENAwEADQMCAQ0DAgANAwABDQMDAQoBAQAAAQAAAAEBAgABAAAAAQICAAECAAABAQAAAQEAAAYAABgFAQEPAwIBCgECAQABAQEAAQEBAAUAARcFAAEXBQABFwUBABcFAQAXBQIAFwECAwABAwAABgAAGAYAABgGAQAYBQEBFwUBAhcFAgAXAQIBAAEDAAABAwEAAQIBAAECAgABAwAAAQMBAAEEAAAFAgEXBQEBFwECAgABAgEAAQICAAEDAgABAwIAAgMDBQYCARgCAwEFBgICGAYDAxgDAAEQAwEAEAMBARAD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BOOAQJ+GiIlBY4C8jUHxjUPVhuw0iVKViWwFBUDvAEGAowILhBP6BgBwCQDwCkBXDADwDWDHDyDqF0AFGwBBIAAMqIA3qiBQ/iA6DSF0EQFaFCFEGYFaHaH1aiFF0kGv4iHwAQ4AQWRsYW0sQWRsbQBBaG9tLEFob20AQW5hdG9saWFuX0hpZXJvZ2x5cGhzLEhsdXcAQXJhYmljLEFyYWIAQXJtZW5pYW4sQXJtbgBBdmVzdGFuLEF2c3QAQmFsaW5lc2UsQmFsaQBCYW11bSxCYW11AEJhc3NhX1ZhaCxCYXNzAEJhdGFrLEJhdGsAQmVuZ2FsaSxCZW5nAEJoYWlrc3VraSxCaGtzAEJvcG9tb2ZvLEJvcG8AQnJhaG1pLEJyYWgAQnJhaWxsZSxCcmFpAEJ1Z2luZXNlLEJ1Z2kAQnVoaWQsQnVoZABDYW5hZGlhbl9BYm9yaWdpbmFsLENhbnMAQ2FyaWFuLENhcmkAQ2F1Y2FzaWFuX0FsYmFuaWFuLEFnaGIAQ2hha21hLENha20AQ2hhbSxDaGFtAENoZXJva2VlLENoZXIAQ2hvcmFzbWlhbixDaHJzAENvbW1vbixaeXl5AENvcHRpYyxDb3B0LFFhYWMAQ3VuZWlmb3JtLFhzdXgAQ3lwcmlvdCxDcHJ0AEN5cmlsbGljLEN5cmwAQ3lwcm9fTWlub2FuLENwbW4ARGVzZXJldCxEc3J0AERldmFuYWdhcmksRGV2YQBEaXZlc19Ba3VydSxEaWFrAERvZ3JhLERvZ3IARHVwbG95YW4sRHVwbABFZ3lwdGlhbl9IaWVyb2dseXBocyxFZ3lwAEVsYmFzYW4sRWxiYQBFbHltYWljLEVseW0ARXRoaW9waWMsRXRoaQBHZW9yZ2lhbixHZW9yAEdsYWdvbGl0aWMsR2xhZwBHb3RoaWMsR290aABHcmFudGhhLEdyYW4AR3JlZWssR3JlawBHdWphcmF0aSxHdWpyAEd1bmphbGFfR29uZGksR29uZwBHdXJtdWtoaSxHdXJ1AEhhbixIYW5pAEhhbmd1bCxIYW5nAEhhbmlmaV9Sb2hpbmd5YSxSb2hnAEhhbnVub28sSGFubwBIYXRyYW4sSGF0cgBIZWJyZXcsSGVicgBIaXJhZ2FuYSxIaXJhAEltcGVyaWFsX0FyYW1haWMsQXJtaQBJbmhlcml0ZWQsWmluaCxRYWFpAEluc2NyaXB0aW9uYWxfUGFobGF2aSxQaGxpAEluc2NyaXB0aW9uYWxfUGFydGhpYW4sUHJ0aQBKYXZhbmVzZSxKYXZhAEthaXRoaSxLdGhpAEthbm5hZGEsS25kYQBLYXRha2FuYSxLYW5hAEthd2ksS2F3aQBLYXlhaF9MaSxLYWxpAEtoYXJvc2h0aGksS2hhcgBLaG1lcixLaG1yAEtob2praSxLaG9qAEtoaXRhbl9TbWFsbF9TY3JpcHQsS2l0cwBLaHVkYXdhZGksU2luZABMYW8sTGFvbwBMYXRpbixMYXRuAExlcGNoYSxMZXBjAExpbWJ1LExpbWIATGluZWFyX0EsTGluYQBMaW5lYXJfQixMaW5iAExpc3UsTGlzdQBMeWNpYW4sTHljaQBMeWRpYW4sTHlkaQBNYWthc2FyLE1ha2EATWFoYWphbmksTWFoagBNYWxheWFsYW0sTWx5bQBNYW5kYWljLE1hbmQATWFuaWNoYWVhbixNYW5pAE1hcmNoZW4sTWFyYwBNYXNhcmFtX0dvbmRpLEdvbm0ATWVkZWZhaWRyaW4sTWVkZgBNZWV0ZWlfTWF5ZWssTXRlaQBNZW5kZV9LaWtha3VpLE1lbmQATWVyb2l0aWNfQ3Vyc2l2ZSxNZXJjAE1lcm9pdGljX0hpZXJvZ2x5cGhzLE1lcm8ATWlhbyxQbHJkAE1vZGksTW9kaQBNb25nb2xpYW4sTW9uZwBNcm8sTXJvbwBNdWx0YW5pLE11bHQATXlhbm1hcixNeW1yAE5hYmF0YWVhbixOYmF0AE5hZ19NdW5kYXJpLE5hZ20ATmFuZGluYWdhcmksTmFuZABOZXdfVGFpX0x1ZSxUYWx1AE5ld2EsTmV3YQBOa28sTmtvbwBOdXNodSxOc2h1AE55aWFrZW5nX1B1YWNodWVfSG1vbmcsSG1ucABPZ2hhbSxPZ2FtAE9sX0NoaWtpLE9sY2sAT2xkX0h1bmdhcmlhbixIdW5nAE9sZF9JdGFsaWMsSXRhbABPbGRfTm9ydGhfQXJhYmlhbixOYXJiAE9sZF9QZXJtaWMsUGVybQBPbGRfUGVyc2lhbixYcGVvAE9sZF9Tb2dkaWFuLFNvZ28AT2xkX1NvdXRoX0FyYWJpYW4sU2FyYgBPbGRfVHVya2ljLE9ya2gAT2xkX1V5Z2h1cixPdWdyAE9yaXlhLE9yeWEAT3NhZ2UsT3NnZQBPc21hbnlhLE9zbWEAUGFoYXdoX0htb25nLEhtbmcAUGFsbXlyZW5lLFBhbG0AUGF1X0Npbl9IYXUsUGF1YwBQaGFnc19QYSxQaGFnAFBob2VuaWNpYW4sUGhueABQc2FsdGVyX1BhaGxhdmksUGhscABSZWphbmcsUmpuZwBSdW5pYyxSdW5yAFNhbWFyaXRhbixTYW1yAFNhdXJhc2h0cmEsU2F1cgBTaGFyYWRhLFNocmQAU2hhdmlhbixTaGF3AFNpZGRoYW0sU2lkZABTaWduV3JpdGluZyxTZ253AFNpbmhhbGEsU2luaABTb2dkaWFuLFNvZ2QAU29yYV9Tb21wZW5nLFNvcmEAU295b21ibyxTb3lvAFN1bmRhbmVzZSxTdW5kAFN5bG90aV9OYWdyaSxTeWxvAFN5cmlhYyxTeXJjAFRhZ2Fsb2csVGdsZwBUYWdiYW53YSxUYWdiAFRhaV9MZSxUYWxlAFRhaV9UaGFtLExhbmEAVGFpX1ZpZXQsVGF2dABUYWtyaSxUYWtyAFRhbWlsLFRhbWwAVGFuZ3V0LFRhbmcAVGVsdWd1LFRlbHUAVGhhYW5hLFRoYWEAVGhhaSxUaGFpAFRpYmV0YW4sVGlidABUaWZpbmFnaCxUZm5nAFRpcmh1dGEsVGlyaABUYW5nc2EsVG5zYQBUb3RvLFRvdG8AVWdhcml0aWMsVWdhcgBWYWksVmFpaQBWaXRoa3VxaSxWaXRoAFdhbmNobyxXY2hvAFdhcmFuZ19DaXRpLFdhcmEAWWV6aWRpLFllemkAWWksWWlpaQBaYW5hYmF6YXJfU3F1YXJlLFphbmIAQZC2AgvyIMAZmUeFGZlHrhmAR44ZgEeEGZZHgBmeR4AZ4WBHphmER4QZgQ2TGeAPOIMsgBmCLAGDLIAZgCwDgCyAGYAsgBmCLACALACTLAC+LI0ajyzgJB2BOOBIHQClBQGxBQGCBQC2NQeaNQOFNQqEBIAZhQSAGY0EgBmCBIAZnwSAGYkEijiZBIA44AsEgBmhBI2LALuLAYKLrwSxlQ26ZgGCZq1/AY5/AJtSAYBSAIqLBJ4EAIEEBckEgBmcBNAggziOIIEZmSCDCwCHCwGBCwGVCwCGCwCACwKDCwGI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eW1ib2wAU28sT3RoZXJfU3ltYm9sAFBjLENvbm5lY3Rvcl9QdW5jdHVhdGlvbgBQZCxEYXNoX1B1bmN0dWF0aW9uAFBzLE9wZW5fUHVuY3R1YXRpb24AUGUsQ2xvc2VfUHVuY3R1YXRpb24AUGksSW5pdGlhbF9QdW5jdHVhdGlvbgBQZixGaW5hbF9QdW5jdHVhdGlvbgBQbyxPdGhlcl9QdW5jdHVhdGlvbgBacyxTcGFjZV9TZXBhcmF0b3IAWmwsTGluZV9TZXBhcmF0b3IAWnAsUGFyYWdyYXBoX1NlcGFyYXRvcgBDYyxDb250cm9sLGNudHJsAENmLEZvcm1hdABDcyxTdXJyb2dhdGUAQ28sUHJpdmF0ZV9Vc2UATEMsQ2FzZWRfTGV0dGVyAEwsTGV0dGVyAE0sTWFyayxDb21iaW5pbmdfTWFyawBOLE51bWJlcgBTLFN5bWJvbABQLFB1bmN0dWF0aW9uLHB1bmN0AFosU2VwYXJhdG9yAEMsT3RoZXIAQZDXAguwCA4AAAA+AAAAwAEAAAAOAAAA8AAAAAB/AAAAgAMBAAA8QVNDSUlfSGV4X0RpZ2l0LEFIZXgAQmlkaV9Db250cm9sLEJpZGlfQwBEYXNoAERlcHJlY2F0ZWQsRGVwAERpYWNyaXRpYyxEaWEARXh0ZW5kZXIsRXh0AEhleF9EaWdpdCxIZXgASURTX0JpbmFyeV9PcGVyYXRvcixJRFNCAElEU19UcmluYXJ5X09wZXJhdG9yLElEU1QASWRlb2dyYXBoaWMsSWRlbwBKb2luX0NvbnRyb2wsSm9pbl9DAExvZ2ljYWxfT3JkZXJfRXhjZXB0aW9uLExPRQBOb25jaGFyYWN0ZXJfQ29kZV9Qb2ludCxOQ2hhcgBQYXR0ZXJuX1N5bnRheCxQYXRfU3luAFBhdHRlcm5fV2hpdGVfU3BhY2UsUGF0X1dTAFF1b3RhdGlvbl9NYXJrLFFNYXJrAFJhZGljYWwAUmVnaW9uYWxfSW5kaWNhdG9yLFJJAFNlbnRlbmNlX1Rlcm1pbmFsLFNUZXJtAFNvZnRfRG90dGVkLFNEAFRlcm1pbmFsX1B1bmN0dWF0aW9uLFRlcm0AVW5pZmllZF9JZGVvZ3JhcGgsVUlkZW8AVmFyaWF0aW9uX1NlbGVjdG9yLFZTAFdoaXRlX1NwYWNlLHNwYWNlAEJpZGlfTWlycm9yZWQsQmlkaV9NAEVtb2ppAEVtb2ppX0NvbXBvbmVudCxFQ29tcABFbW9qaV9Nb2RpZmllcixFTW9kAEVtb2ppX01vZGlmaWVyX0Jhc2UsRUJhc2UARW1vamlfUHJlc2VudGF0aW9uLEVQcmVzAEV4dGVuZGVkX1BpY3RvZ3JhcGhpYyxFeHRQaWN0AERlZmF1bHRfSWdub3JhYmxlX0NvZGVfUG9pbnQsREkASURfU3RhcnQsSURTAENhc2VfSWdub3JhYmxlLENJAEFTQ0lJAEFscGhhYmV0aWMsQWxwaGEAQW55AEFzc2lnbmVkAENhc2VkAENoYW5nZXNfV2hlbl9DYXNlZm9sZGVkLENXQ0YAQ2hhbmdlc19XaGVuX0Nhc2VtYXBwZWQsQ1dDTQBDaGFuZ2VzX1doZW5fTG93ZXJjYXNlZCxDV0wAQ2hhbmdlc19XaGVuX05GS0NfQ2FzZWZvbGRlZCxDV0tDRgBDaGFuZ2VzX1doZW5fVGl0bGVjYXNlZCxDV1QAQ2hhbmdlc19XaGVuX1VwcGVyY2FzZWQsQ1dVAEdyYXBoZW1lX0Jhc2UsR3JfQmFzZQBHcmFwaGVtZV9FeHRlbmQsR3JfRXh0AElEX0NvbnRpbnVlLElEQwBMb3dlcmNhc2UsTG93ZXIATWF0aABVcHBlcmNhc2UsVXBwZXIAWElEX0NvbnRpbnVlLFhJREMAWElEX1N0YXJ0LFhJRFMAQdDfAgvyAgEAnAYHTQMEEACPCwAAEQAIAFNKUQBSAFMAOlRVAFdZP11cAEZhY0JkAGYAaABqAGwAbgAAQAAAAAAaAJMAACA1ACcAIQAkIioAE2ttACYkJxQWGBscPh4/Hzk9IiFBHkAlJSYoICpILEMuSzBMMkRCmQAAlY99foOEEoCCdncSe6N8eHmKkpimoIUAmqGTdTOVAI4AdJmYl5YAAJ4AnAChoBUuLzC0tU+qqRIUHiEiIio0NaanNh9JAACXAVraHTYFAMTDxsXIx8rJzMvE1UXWQtdG2M7Q0tTa2e72/g4HD4CfACGAo+0AwEDGYOfb5pnAAAAGYNwp/RUSBhb43QYVEoQIxhb/3wPAQABGYN7gbTc4ORUUFxYAGhkcGwBft2VERwBPYk5QAABIAAAAo6SlAAAAAAC2AABaAEcAW1ZY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n4PLdYFAzXWfjM11gcDTdS0D1HWfiNV1gcDZdZ8D2nWBwNt1nwzcdYFA4nUtg+J1nwjkdYFA6HWfg+h1gUDqdZ+M6nWBwPB1LQTxdR+F83UfBfZ1H4X4dR8F+3Ufhf11nwQMeJ9BDnifBQ94A8IReK3QEngDARt4LQKAe61NgXsDQoh7gcCJey1FinsDBI17gYCQewPckXstBaB7rciie4NEqHutyKp7lwBAfCFFQHwlDUR8h4BKfBXBSnwXQUt8Hw1MfBeCUnyZgFN8l8BTfJeBWnyXAGR8LwGAfIGAgHwDFoR8wQSQfAMBlHwfBfx+rAEAvhDRAL6sRwm+EDkNviyHKb4sAi2+kDcuvpD/Sb4QvGm+AAAAACAAAABhAAIABAAGALwDCAAKAAwAFQCVAKUAuQDBAMMAxwDLANEA1wDdAOAA5gD4AAgBCgFzABABEgEUASABLAFEAU0BUwFiAWgBagF2AZIBlAGpAbsBxwHRAdUBuQLXATsA2QHbAbcA4QH8AQwCGAIdAiMCJwKjAzMCPwJCAksCTgJRAl0CYAJpAmwCbwJ1AngCgQKKApwCnwKjAq8CuQLFAskCzQLRAtUC5wLtAvEC9QL5Av0CBQMJAw0DEwMXAxsDIwMnAysDLwM1Az0DQQNJA00DUQMLD1cDWwNfA2MDZwNrA28DcwN5A30DgQOFA4kDjQORA5UDmQOdA6ED3BClA8kDzQPZA90D4QPvA/EDPQRPBJkE8AQCBUoFZAVsBXAFcwWaBfoF/gUHBgsGFAYYBh4GIgYoBo4GlAaYBp4GogarBqwD8watA/YGrgP5Bq8D/AbMA/8GzQMCB84DBQcJBw0HEQeGAzIHNQe5AzcHOweIA1MHiQNWB5ADaweKA3cHsAOJB44DmQefB6MHjAO4B48Duwe0AL4HwAfCBxAgywcuAM0HzwcgANIH1gfbB98H5AfqB/AHIAD2BxIiAQgFCAcIHQglCCcIQwAtCDAIkAE2CDkITgBFCEcITAhOCFEIWgCpA1oAUwhXCGAIaQBiCGUIbwh0CHoIfgiiCEkApAimCKkIVgCrCK0IsAi0CFgAtgi4CLsIwAjCCMUIdgDHCMkIzAjQCHgA0gjUCNcI2wjeCOQI5wjwCPMI9gj5CAIJBgkLCQ8JFAkXCRoJIwksCTsJPglBCUQJRwlKCVYJXAlgCWIJZAloCWoJ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\";if(!K(L)){var M=L;L=d.locateFile?d.locateFile(M,q):q+M;}function ca(){var a=L;return Promise.resolve().then(()=>{if(a==L&&v)var b=new Uint8Array(v);else{if(K(a)){b=atob(a.slice(37));for(var c=new Uint8Array(b.length),e=0;e<b.length;++e)c[e]=b.charCodeAt(e);b=c;}else b=void 0;if(!b)throw\"both async and sync fetching of the wasm failed\";}return b;});}function da(a,b){return ca().then(c=>WebAssembly.instantiate(c,a)).then(c=>c).then(b,c=>{u(`failed to asynchronously prepare wasm: ${c}`);w(c);});}function ea(a,b){return da(a,b);}var N=a=>{for(;0<a.length;)a.shift()(d);},O=\"undefined\"!=typeof TextDecoder?new TextDecoder(\"utf8\"):void 0,P=(a,b)=>{for(var c=b+NaN,e=b;a[e]&&!(e>=c);)++e;if(16<e-b&&a.buffer&&O)return O.decode(a.subarray(b,e));for(c=\"\";b<e;){var f=a[b++];if(f&128){var g=a[b++]&63;if(192==(f&224))c+=String.fromCharCode((f&31)<<6|g);else{var l=a[b++]&63;f=224==(f&240)?(f&15)<<12|g<<6|l:(f&7)<<18|g<<12|l<<6|a[b++]&63;65536>f?c+=String.fromCharCode(f):(f-=65536,c+=String.fromCharCode(55296|f>>10,56320|f&1023));}}else c+=String.fromCharCode(f);}return c;},fa=[0,31,60,91,121,152,182,213,244,274,305,335],ha=[0,31,59,90,120,151,181,212,243,273,304,334],Q=a=>{for(var b=0,c=0;c<a.length;++c){var e=a.charCodeAt(c);127>=e?b++:2047>=e?b+=2:55296<=e&&57343>=e?(b+=4,++c):b+=3;}return b;},R=(a,b,c)=>{var e=A;if(0<c){c=b+c-1;for(var f=0;f<a.length;++f){var g=a.charCodeAt(f);if(55296<=g&&57343>=g){var l=a.charCodeAt(++f);g=65536+((g&1023)<<10)|l&1023;}if(127>=g){if(b>=c)break;e[b++]=g;}else{if(2047>=g){if(b+1>=c)break;e[b++]=192|g>>6;}else{if(65535>=g){if(b+2>=c)break;e[b++]=224|g>>12;}else{if(b+3>=c)break;e[b++]=240|g>>18;e[b++]=128|g>>12&63;}e[b++]=128|g>>6&63;}e[b++]=128|g&63;}}e[b]=0;}},T=a=>{var b=Q(a)+1,c=S(b);c&&R(a,c,b);return c;};function U(){}var ia=[null,[],[]],ka=(a,b,c,e)=>{var f={string:h=>{var r=0;if(null!==h&&void 0!==h&&0!==h){r=Q(h)+1;var Y=V(r);R(h,Y,r);r=Y;}return r;},array:h=>{var r=V(h.length);z.set(h,r);return r;}};a=d[\"_\"+a];var g=[],l=0;if(e)for(var m=0;m<e.length;m++){var t=f[c[m]];t?(0===l&&(l=W()),g[m]=t(e[m])):g[m]=e[m];}c=a.apply(null,g);return c=function(h){0!==l&&ja(l);return\"string\"===b?h?P(A,h):\"\":\"boolean\"===b?!!h:h;}(c);};U=(a,b,c)=>{a=a?P(A,a):\"\";b=null!==b?JSON.parse(b?P(A,b):\"\"):[];try{const e=d.externalCall(a,b);return e?T(e):null;}catch(e){return d.HEAPU8[c]=1,T(e.message);}};var la={a:(a,b,c,e)=>{w(`Assertion failed: ${a?P(A,a):\"\"}, at: `+[b?b?P(A,b):\"\":\"unknown filename\",c,e?e?P(A,e):\"\":\"unknown function\"]);},i:function(a,b,c){a=new Date(1E3*(b+2097152>>>0<4194305-!!a?(a>>>0)+4294967296*b:NaN));B[c>>2]=a.getSeconds();B[c+4>>2]=a.getMinutes();B[c+8>>2]=a.getHours();B[c+12>>2]=a.getDate();B[c+16>>2]=a.getMonth();B[c+20>>2]=a.getFullYear()-1900;B[c+24>>2]=a.getDay();b=a.getFullYear();B[c+28>>2]=(0!==b%4||0===b%100&&0!==b%400?ha:fa)[a.getMonth()]+a.getDate()-1|0;B[c+36>>2]=-(60*a.getTimezoneOffset());b=new Date(a.getFullYear(),6,1).getTimezoneOffset();var e=new Date(a.getFullYear(),0,1).getTimezoneOffset();B[c+32>>2]=(b!=e&&a.getTimezoneOffset()==Math.min(e,b))|0;},d:(a,b,c)=>{function e(t){return(t=t.toTimeString().match(/\\(([A-Za-z ]+)\\)$/))?t[1]:\"GMT\";}var f=new Date().getFullYear(),g=new Date(f,0,1),l=new Date(f,6,1);f=g.getTimezoneOffset();var m=l.getTimezoneOffset();C[a>>2]=60*Math.max(f,m);B[b>>2]=Number(f!=m);a=e(g);b=e(l);a=T(a);b=T(b);m<f?(C[c>>2]=a,C[c+4>>2]=b):(C[c>>2]=b,C[c+4>>2]=a);},b:()=>{w(\"\");},g:U,f:function(a,b){a=a?P(A,a):\"\";let c;try{c=window.JSON.parse(a);}catch(e){c=a;}0!==b?window.alert(a):window.console.log(\"DUMP\",c);},e:()=>Date.now(),j:a=>{var b=A.length;a>>>=0;if(2147483648<a)return!1;for(var c=1;4>=c;c*=2){var e=b*(1+.2/c);e=Math.min(e,a+100663296);var f=Math;e=Math.max(a,e);a:{f=(f.min.call(f,2147483648,e+(65536-e%65536)%65536)-x.buffer.byteLength+65535)/65536;try{x.grow(f);D();var g=1;break a;}catch(l){}g=void 0;}if(g)return!0;}return!1;},c:(a,b,c,e)=>{for(var f=0,g=0;g<c;g++){var l=C[b>>2],m=C[b+4>>2];b+=8;for(var t=0;t<m;t++){var h=A[l+t],r=ia[a];0===h||10===h?((1===a?aa:u)(P(r,0)),r.length=0):r.push(h);}f+=m;}C[e>>2]=f;return 0;},k:function(a){a=a?P(A,a):\"\";window.console.log(a);},h:function(a){a=a?P(A,a):\"\";return Date.parse(a);},l:function(a,b,c,e){a=a?P(A,a):\"\";b=b?P(A,b):\"\";c=c?P(A,c):\"\";c=`Quickjs -- ${a}: ${b}\\n${c}`;0!==e?window.alert(c):window.console.error(c);}},X=function(){function a(c){X=c.exports;x=X.m;D();F.unshift(X.n);H--;d.monitorRunDependencies?.(H);0==H&&(null!==I&&(clearInterval(I),I=null),J&&(c=J,J=null,c()));return X;}var b={a:la};H++;d.monitorRunDependencies?.(H);if(d.instantiateWasm)try{return d.instantiateWasm(b,a);}catch(c){u(`Module.instantiateWasm callback failed with error: ${c}`),n(c);}ea(b,function(c){a(c.instance);}).catch(n);return{};}();d._evalInSandbox=(a,b)=>(d._evalInSandbox=X.o)(a,b);d._nukeSandbox=()=>(d._nukeSandbox=X.p)();d._init=(a,b)=>(d._init=X.q)(a,b);d._commFun=(a,b)=>(d._commFun=X.r)(a,b);d._dumpMemoryUse=()=>(d._dumpMemoryUse=X.s)();var S=a=>(S=X.t)(a);d._free=a=>(d._free=X.u)(a);var W=()=>(W=X.w)(),ja=a=>(ja=X.x)(a),V=a=>(V=X.y)(a);d.ccall=ka;d.cwrap=(a,b,c,e)=>{var f=!c||c.every(g=>\"number\"===g||\"boolean\"===g);return\"string\"!==b&&f&&!e?d[\"_\"+a]:function(){return ka(a,b,c,arguments,e);};};d.stringToNewUTF8=T;var Z;J=function ma(){Z||na();Z||(J=ma);};function na(){function a(){if(!Z&&(Z=!0,d.calledRun=!0,!y)){N(F);k(d);if(d.onRuntimeInitialized)d.onRuntimeInitialized();if(d.postRun)for(\"function\"==typeof d.postRun&&(d.postRun=[d.postRun]);d.postRun.length;){var b=d.postRun.shift();G.unshift(b);}N(G);}}if(!(0<H)){if(d.preRun)for(\"function\"==typeof d.preRun&&(d.preRun=[d.preRun]);d.preRun.length;)ba();N(E);0<H||(d.setStatus?(d.setStatus(\"Running...\"),setTimeout(function(){setTimeout(function(){d.setStatus(\"\");},1);a();},1)):a());}}if(d.preInit)for(\"function\"==typeof d.preInit&&(d.preInit=[d.preInit]);0<d.preInit.length;)d.preInit.pop()();na();return moduleArg.ready;};})();/* harmony default export */ const quickjs_eval = (Module);\n;// CONCATENATED MODULE: ./src/pdf.sandbox.external.js\nclass SandboxSupportBase {\n  constructor(win) {\n    this.win = win;\n    this.timeoutIds = new Map();\n    this.commFun = null;\n  }\n  destroy() {\n    this.commFun = null;\n    for (const id of this.timeoutIds.values()) {\n      this.win.clearTimeout(id);\n    }\n    this.timeoutIds = null;\n  }\n  exportValueToSandbox(val) {\n    throw new Error(\"Not implemented\");\n  }\n  importValueFromSandbox(val) {\n    throw new Error(\"Not implemented\");\n  }\n  createErrorForSandbox(errorMessage) {\n    throw new Error(\"Not implemented\");\n  }\n  callSandboxFunction(name, args) {\n    try {\n      args = this.exportValueToSandbox(args);\n      this.commFun(name, args);\n    } catch (e) {\n      this.win.console.error(e);\n    }\n  }\n  createSandboxExternals() {\n    const externals = {\n      setTimeout: (callbackId, nMilliseconds) => {\n        if (typeof callbackId !== \"number\" || typeof nMilliseconds !== \"number\") {\n          return;\n        }\n        if (callbackId === 0) {\n          this.win.clearTimeout(this.timeoutIds.get(callbackId));\n        }\n        const id = this.win.setTimeout(() => {\n          this.timeoutIds.delete(callbackId);\n          this.callSandboxFunction(\"timeoutCb\", {\n            callbackId,\n            interval: false\n          });\n        }, nMilliseconds);\n        this.timeoutIds.set(callbackId, id);\n      },\n      clearTimeout: callbackId => {\n        this.win.clearTimeout(this.timeoutIds.get(callbackId));\n        this.timeoutIds.delete(callbackId);\n      },\n      setInterval: (callbackId, nMilliseconds) => {\n        if (typeof callbackId !== \"number\" || typeof nMilliseconds !== \"number\") {\n          return;\n        }\n        const id = this.win.setInterval(() => {\n          this.callSandboxFunction(\"timeoutCb\", {\n            callbackId,\n            interval: true\n          });\n        }, nMilliseconds);\n        this.timeoutIds.set(callbackId, id);\n      },\n      clearInterval: callbackId => {\n        this.win.clearInterval(this.timeoutIds.get(callbackId));\n        this.timeoutIds.delete(callbackId);\n      },\n      alert: cMsg => {\n        if (typeof cMsg !== \"string\") {\n          return;\n        }\n        this.win.alert(cMsg);\n      },\n      confirm: cMsg => {\n        if (typeof cMsg !== \"string\") {\n          return false;\n        }\n        return this.win.confirm(cMsg);\n      },\n      prompt: (cQuestion, cDefault) => {\n        if (typeof cQuestion !== \"string\" || typeof cDefault !== \"string\") {\n          return null;\n        }\n        return this.win.prompt(cQuestion, cDefault);\n      },\n      parseURL: cUrl => {\n        const url = new this.win.URL(cUrl);\n        const props = [\"hash\", \"host\", \"hostname\", \"href\", \"origin\", \"password\", \"pathname\", \"port\", \"protocol\", \"search\", \"searchParams\", \"username\"];\n        return Object.fromEntries(props.map(name => [name, url[name].toString()]));\n      },\n      send: data => {\n        if (!data) {\n          return;\n        }\n        const event = new this.win.CustomEvent(\"updatefromsandbox\", {\n          detail: this.importValueFromSandbox(data)\n        });\n        this.win.dispatchEvent(event);\n      }\n    };\n    Object.setPrototypeOf(externals, null);\n    return (name, args) => {\n      try {\n        const result = externals[name](...args);\n        return this.exportValueToSandbox(result);\n      } catch (error) {\n        throw this.createErrorForSandbox(error?.toString() ?? \"\");\n      }\n    };\n  }\n}\n;// CONCATENATED MODULE: ./src/pdf.sandbox.js\n\n\nconst pdfjsVersion = \"4.2.67\";\nconst pdfjsBuild = \"49b388101\";\nclass SandboxSupport extends SandboxSupportBase {\n  exportValueToSandbox(val) {\n    return JSON.stringify(val);\n  }\n  importValueFromSandbox(val) {\n    return val;\n  }\n  createErrorForSandbox(errorMessage) {\n    return new Error(errorMessage);\n  }\n}\nclass Sandbox {\n  constructor(win, module) {\n    this.support = new SandboxSupport(win, this);\n    module.externalCall = this.support.createSandboxExternals();\n    this._module = module;\n    this._alertOnError = 0;\n  }\n  create(data) {\n    const code = [\"var __webpack_exports__ = globalThis.pdfjsSandbox = {};\\n\\n;// CONCATENATED MODULE: ./src/scripting_api/constants.js\\nconst Border = Object.freeze({\\n  s: \\\"solid\\\",\\n  d: \\\"dashed\\\",\\n  b: \\\"beveled\\\",\\n  i: \\\"inset\\\",\\n  u: \\\"underline\\\"\\n});\\nconst Cursor = Object.freeze({\\n  visible: 0,\\n  hidden: 1,\\n  delay: 2\\n});\\nconst Display = Object.freeze({\\n  visible: 0,\\n  hidden: 1,\\n  noPrint: 2,\\n  noView: 3\\n});\\nconst Font = Object.freeze({\\n  Times: \\\"Times-Roman\\\",\\n  TimesB: \\\"Times-Bold\\\",\\n  TimesI: \\\"Times-Italic\\\",\\n  TimesBI: \\\"Times-BoldItalic\\\",\\n  Helv: \\\"Helvetica\\\",\\n  HelvB: \\\"Helvetica-Bold\\\",\\n  HelvI: \\\"Helvetica-Oblique\\\",\\n  HelvBI: \\\"Helvetica-BoldOblique\\\",\\n  Cour: \\\"Courier\\\",\\n  CourB: \\\"Courier-Bold\\\",\\n  CourI: \\\"Courier-Oblique\\\",\\n  CourBI: \\\"Courier-BoldOblique\\\",\\n  Symbol: \\\"Symbol\\\",\\n  ZapfD: \\\"ZapfDingbats\\\",\\n  KaGo: \\\"HeiseiKakuGo-W5-UniJIS-UCS2-H\\\",\\n  KaMi: \\\"HeiseiMin-W3-UniJIS-UCS2-H\\\"\\n});\\nconst Highlight = Object.freeze({\\n  n: \\\"none\\\",\\n  i: \\\"invert\\\",\\n  p: \\\"push\\\",\\n  o: \\\"outline\\\"\\n});\\nconst Position = Object.freeze({\\n  textOnly: 0,\\n  iconOnly: 1,\\n  iconTextV: 2,\\n  textIconV: 3,\\n  iconTextH: 4,\\n  textIconH: 5,\\n  overlay: 6\\n});\\nconst ScaleHow = Object.freeze({\\n  proportional: 0,\\n  anamorphic: 1\\n});\\nconst ScaleWhen = Object.freeze({\\n  always: 0,\\n  never: 1,\\n  tooBig: 2,\\n  tooSmall: 3\\n});\\nconst Style = Object.freeze({\\n  ch: \\\"check\\\",\\n  cr: \\\"cross\\\",\\n  di: \\\"diamond\\\",\\n  ci: \\\"circle\\\",\\n  st: \\\"star\\\",\\n  sq: \\\"square\\\"\\n});\\nconst Trans = Object.freeze({\\n  blindsH: \\\"BlindsHorizontal\\\",\\n  blindsV: \\\"BlindsVertical\\\",\\n  boxI: \\\"BoxIn\\\",\\n  boxO: \\\"BoxOut\\\",\\n  dissolve: \\\"Dissolve\\\",\\n  glitterD: \\\"GlitterDown\\\",\\n  glitterR: \\\"GlitterRight\\\",\\n  glitterRD: \\\"GlitterRightDown\\\",\\n  random: \\\"Random\\\",\\n  replace: \\\"Replace\\\",\\n  splitHI: \\\"SplitHorizontalIn\\\",\\n  splitHO: \\\"SplitHorizontalOut\\\",\\n  splitVI: \\\"SplitVerticalIn\\\",\\n  splitVO: \\\"SplitVerticalOut\\\",\\n  wipeD: \\\"WipeDown\\\",\\n  wipeL: \\\"WipeLeft\\\",\\n  wipeR: \\\"WipeRight\\\",\\n  wipeU: \\\"WipeUp\\\"\\n});\\nconst ZoomType = Object.freeze({\\n  none: \\\"NoVary\\\",\\n  fitP: \\\"FitPage\\\",\\n  fitW: \\\"FitWidth\\\",\\n  fitH: \\\"FitHeight\\\",\\n  fitV: \\\"FitVisibleWidth\\\",\\n  pref: \\\"Preferred\\\",\\n  refW: \\\"ReflowWidth\\\"\\n});\\nconst GlobalConstants = Object.freeze({\\n  IDS_GREATER_THAN: \\\"Invalid value: must be greater than or equal to % s.\\\",\\n  IDS_GT_AND_LT: \\\"Invalid value: must be greater than or equal to % s \\\" + \\\"and less than or equal to % s.\\\",\\n  IDS_LESS_THAN: \\\"Invalid value: must be less than or equal to % s.\\\",\\n  IDS_INVALID_MONTH: \\\"** Invalid **\\\",\\n  IDS_INVALID_DATE: \\\"Invalid date / time: please ensure that the date / time exists. Field\\\",\\n  IDS_INVALID_DATE2: \\\" should match format \\\",\\n  IDS_INVALID_VALUE: \\\"The value entered does not match the format of the field\\\",\\n  IDS_AM: \\\"am\\\",\\n  IDS_PM: \\\"pm\\\",\\n  IDS_MONTH_INFO: \\\"January[1] February[2] March[3] April[4] May[5] \\\" + \\\"June[6] July[7] August[8] September[9] October[10] \\\" + \\\"November[11] December[12] Sept[9] Jan[1] Feb[2] Mar[3] \\\" + \\\"Apr[4] Jun[6] Jul[7] Aug[8] Sep[9] Oct[10] Nov[11] Dec[12]\\\",\\n  IDS_STARTUP_CONSOLE_MSG: \\\"** ^ _ ^ **\\\",\\n  RE_NUMBER_ENTRY_DOT_SEP: [\\\"[+-]?\\\\\\\\d*\\\\\\\\.?\\\\\\\\d*\\\"],\\n  RE_NUMBER_COMMIT_DOT_SEP: [\\\"[+-]?\\\\\\\\d+(\\\\\\\\.\\\\\\\\d+)?\\\", \\\"[+-]?\\\\\\\\.\\\\\\\\d+\\\", \\\"[+-]?\\\\\\\\d+\\\\\\\\.\\\"],\\n  RE_NUMBER_ENTRY_COMMA_SEP: [\\\"[+-]?\\\\\\\\d*,?\\\\\\\\d*\\\"],\\n  RE_NUMBER_COMMIT_COMMA_SEP: [\\\"[+-]?\\\\\\\\d+([.,]\\\\\\\\d+)?\\\", \\\"[+-]?[.,]\\\\\\\\d+\\\", \\\"[+-]?\\\\\\\\d+[.,]\\\"],\\n  RE_ZIP_ENTRY: [\\\"\\\\\\\\d{0,5}\\\"],\\n  RE_ZIP_COMMIT: [\\\"\\\\\\\\d{5}\\\"],\\n  RE_ZIP4_ENTRY: [\\\"\\\\\\\\d{0,5}(\\\\\\\\.|[- ])?\\\\\\\\d{0,4}\\\"],\\n  RE_ZIP4_COMMIT: [\\\"\\\\\\\\d{5}(\\\\\\\\.|[- ])?\\\\\\\\d{4}\\\"],\\n  RE_PHONE_ENTRY: [\\\"\\\\\\\\d{0,3}(\\\\\\\\.|[- ])?\\\\\\\\d{0,3}(\\\\\\\\.|[- ])?\\\\\\\\d{0,4}\\\", \\\"\\\\\\\\(\\\\\\\\d{0,3}\\\", \\\"\\\\\\\\(\\\\\\\\d{0,3}\\\\\\\\)(\\\\\\\\.|[- ])?\\\\\\\\d{0,3}(\\\\\\\\.|[- ])?\\\\\\\\d{0,4}\\\", \\\"\\\\\\\\(\\\\\\\\d{0,3}(\\\\\\\\.|[- ])?\\\\\\\\d{0,3}(\\\\\\\\.|[- ])?\\\\\\\\d{0,4}\\\", \\\"\\\\\\\\d{0,3}\\\\\\\\)(\\\\\\\\.|[- ])?\\\\\\\\d{0,3}(\\\\\\\\.|[- ])?\\\\\\\\d{0,4}\\\", \\\"011(\\\\\\\\.|[- \\\\\\\\d])*\\\"],\\n  RE_PHONE_COMMIT: [\\\"\\\\\\\\d{3}(\\\\\\\\.|[- ])?\\\\\\\\d{4}\\\", \\\"\\\\\\\\d{3}(\\\\\\\\.|[- ])?\\\\\\\\d{3}(\\\\\\\\.|[- ])?\\\\\\\\d{4}\\\", \\\"\\\\\\\\(\\\\\\\\d{3}\\\\\\\\)(\\\\\\\\.|[- ])?\\\\\\\\d{3}(\\\\\\\\.|[- ])?\\\\\\\\d{4}\\\", \\\"011(\\\\\\\\.|[- \\\\\\\\d])*\\\"],\\n  RE_SSN_ENTRY: [\\\"\\\\\\\\d{0,3}(\\\\\\\\.|[- ])?\\\\\\\\d{0,2}(\\\\\\\\.|[- ])?\\\\\\\\d{0,4}\\\"],\\n  RE_SSN_COMMIT: [\\\"\\\\\\\\d{3}(\\\\\\\\.|[- ])?\\\\\\\\d{2}(\\\\\\\\.|[- ])?\\\\\\\\d{4}\\\"]\\n});\\n\\n;// CONCATENATED MODULE: ./src/scripting_api/common.js\\nconst FieldType = {\\n  none: 0,\\n  number: 1,\\n  percent: 2,\\n  date: 3,\\n  time: 4\\n};\\nfunction createActionsMap(actions) {\\n  const actionsMap = new Map();\\n  if (actions) {\\n    for (const [eventType, actionsForEvent] of Object.entries(actions)) {\\n      actionsMap.set(eventType, actionsForEvent);\\n    }\\n  }\\n  return actionsMap;\\n}\\nfunction getFieldType(actions) {\\n  let format = actions.get(\\\"Format\\\");\\n  if (!format) {\\n    return FieldType.none;\\n  }\\n  format = format[0];\\n  format = format.trim();\\n  if (format.startsWith(\\\"AFNumber_\\\")) {\\n    return FieldType.number;\\n  }\\n  if (format.startsWith(\\\"AFPercent_\\\")) {\\n    return FieldType.percent;\\n  }\\n  if (format.startsWith(\\\"AFDate_\\\")) {\\n    return FieldType.date;\\n  }\\n  if (format.startsWith(\\\"AFTime_\\\")) {\\n    return FieldType.time;\\n  }\\n  return FieldType.none;\\n}\\n\\n;// CONCATENATED MODULE: ./src/shared/scripting_utils.js\\nfunction makeColorComp(n) {\\n  return Math.floor(Math.max(0, Math.min(1, n)) * 255).toString(16).padStart(2, \\\"0\\\");\\n}\\nfunction scaleAndClamp(x) {\\n  return Math.max(0, Math.min(255, 255 * x));\\n}\\nclass ColorConverters {\\n  static CMYK_G([c, y, m, k]) {\\n    return [\\\"G\\\", 1 - Math.min(1, 0.3 * c + 0.59 * m + 0.11 * y + k)];\\n  }\\n  static G_CMYK([g]) {\\n    return [\\\"CMYK\\\", 0, 0, 0, 1 - g];\\n  }\\n  static G_RGB([g]) {\\n    return [\\\"RGB\\\", g, g, g];\\n  }\\n  static G_rgb([g]) {\\n    g = scaleAndClamp(g);\\n    return [g, g, g];\\n  }\\n  static G_HTML([g]) {\\n    const G = makeColorComp(g);\\n    return `#${G}${G}${G}`;\\n  }\\n  static RGB_G([r, g, b]) {\\n    return [\\\"G\\\", 0.3 * r + 0.59 * g + 0.11 * b];\\n  }\\n  static RGB_rgb(color) {\\n    return color.map(scaleAndClamp);\\n  }\\n  static RGB_HTML(color) {\\n    return `#${color.map(makeColorComp).join(\\\"\\\")}`;\\n  }\\n  static T_HTML() {\\n    return \\\"#00000000\\\";\\n  }\\n  static T_rgb() {\\n    return [null];\\n  }\\n  static CMYK_RGB([c, y, m, k]) {\\n    return [\\\"RGB\\\", 1 - Math.min(1, c + k), 1 - Math.min(1, m + k), 1 - Math.min(1, y + k)];\\n  }\\n  static CMYK_rgb([c, y, m, k]) {\\n    return [scaleAndClamp(1 - Math.min(1, c + k)), scaleAndClamp(1 - Math.min(1, m + k)), scaleAndClamp(1 - Math.min(1, y + k))];\\n  }\\n  static CMYK_HTML(components) {\\n    const rgb = this.CMYK_RGB(components).slice(1);\\n    return this.RGB_HTML(rgb);\\n  }\\n  static RGB_CMYK([r, g, b]) {\\n    const c = 1 - r;\\n    const m = 1 - g;\\n    const y = 1 - b;\\n    const k = Math.min(c, m, y);\\n    return [\\\"CMYK\\\", c, m, y, k];\\n  }\\n}\\n\\n;// CONCATENATED MODULE: ./src/scripting_api/pdf_object.js\\nclass PDFObject {\\n  constructor(data) {\\n    this._expandos = Object.create(null);\\n    this._send = data.send || null;\\n    this._id = data.id || null;\\n  }\\n}\\n\\n;// CONCATENATED MODULE: ./src/scripting_api/color.js\\n\\n\\nclass Color extends PDFObject {\\n  constructor() {\\n    super({});\\n    this.transparent = [\\\"T\\\"];\\n    this.black = [\\\"G\\\", 0];\\n    this.white = [\\\"G\\\", 1];\\n    this.red = [\\\"RGB\\\", 1, 0, 0];\\n    this.green = [\\\"RGB\\\", 0, 1, 0];\\n    this.blue = [\\\"RGB\\\", 0, 0, 1];\\n    this.cyan = [\\\"CMYK\\\", 1, 0, 0, 0];\\n    this.magenta = [\\\"CMYK\\\", 0, 1, 0, 0];\\n    this.yellow = [\\\"CMYK\\\", 0, 0, 1, 0];\\n    this.dkGray = [\\\"G\\\", 0.25];\\n    this.gray = [\\\"G\\\", 0.5];\\n    this.ltGray = [\\\"G\\\", 0.75];\\n  }\\n  static _isValidSpace(cColorSpace) {\\n    return typeof cColorSpace === \\\"string\\\" && (cColorSpace === \\\"T\\\" || cColorSpace === \\\"G\\\" || cColorSpace === \\\"RGB\\\" || cColorSpace === \\\"CMYK\\\");\\n  }\\n  static _isValidColor(colorArray) {\\n    if (!Array.isArray(colorArray) || colorArray.length === 0) {\\n      return false;\\n    }\\n    const space = colorArray[0];\\n    if (!Color._isValidSpace(space)) {\\n      return false;\\n    }\\n    switch (space) {\\n      case \\\"T\\\":\\n        if (colorArray.length !== 1) {\\n          return false;\\n        }\\n        break;\\n      case \\\"G\\\":\\n        if (colorArray.length !== 2) {\\n          return false;\\n        }\\n        break;\\n      case \\\"RGB\\\":\\n        if (colorArray.length !== 4) {\\n          return false;\\n        }\\n        break;\\n      case \\\"CMYK\\\":\\n        if (colorArray.length !== 5) {\\n          return false;\\n        }\\n        break;\\n      default:\\n        return false;\\n    }\\n    return colorArray.slice(1).every(c => typeof c === \\\"number\\\" && c >= 0 && c <= 1);\\n  }\\n  static _getCorrectColor(colorArray) {\\n    return Color._isValidColor(colorArray) ? colorArray : [\\\"G\\\", 0];\\n  }\\n  convert(colorArray, cColorSpace) {\\n    if (!Color._isValidSpace(cColorSpace)) {\\n      return this.black;\\n    }\\n    if (cColorSpace === \\\"T\\\") {\\n      return [\\\"T\\\"];\\n    }\\n    colorArray = Color._getCorrectColor(colorArray);\\n    if (colorArray[0] === cColorSpace) {\\n      return colorArray;\\n    }\\n    if (colorArray[0] === \\\"T\\\") {\\n      return this.convert(this.black, cColorSpace);\\n    }\\n    return ColorConverters[`${colorArray[0]}_${cColorSpace}`](colorArray.slice(1));\\n  }\\n  equal(colorArray1, colorArray2) {\\n    colorArray1 = Color._getCorrectColor(colorArray1);\\n    colorArray2 = Color._getCorrectColor(colorArray2);\\n    if (colorArray1[0] === \\\"T\\\" || colorArray2[0] === \\\"T\\\") {\\n      return colorArray1[0] === \\\"T\\\" && colorArray2[0] === \\\"T\\\";\\n    }\\n    if (colorArray1[0] !== colorArray2[0]) {\\n      colorArray2 = this.convert(colorArray2, colorArray1[0]);\\n    }\\n    return colorArray1.slice(1).every((c, i) => c === colorArray2[i + 1]);\\n  }\\n}\\n\\n;// CONCATENATED MODULE: ./src/scripting_api/field.js\\n\\n\\n\\nclass Field extends PDFObject {\\n  constructor(data) {\\n    super(data);\\n    this.alignment = data.alignment || \\\"left\\\";\\n    this.borderStyle = data.borderStyle || \\\"\\\";\\n    this.buttonAlignX = data.buttonAlignX || 50;\\n    this.buttonAlignY = data.buttonAlignY || 50;\\n    this.buttonFitBounds = data.buttonFitBounds;\\n    this.buttonPosition = data.buttonPosition;\\n    this.buttonScaleHow = data.buttonScaleHow;\\n    this.ButtonScaleWhen = data.buttonScaleWhen;\\n    this.calcOrderIndex = data.calcOrderIndex;\\n    this.comb = data.comb;\\n    this.commitOnSelChange = data.commitOnSelChange;\\n    this.currentValueIndices = data.currentValueIndices;\\n    this.defaultStyle = data.defaultStyle;\\n    this.defaultValue = data.defaultValue;\\n    this.doNotScroll = data.doNotScroll;\\n    this.doNotSpellCheck = data.doNotSpellCheck;\\n    this.delay = data.delay;\\n    this.display = data.display;\\n    this.doc = data.doc.wrapped;\\n    this.editable = data.editable;\\n    this.exportValues = data.exportValues;\\n    this.fileSelect = data.fileSelect;\\n    this.hidden = data.hidden;\\n    this.highlight = data.highlight;\\n    this.lineWidth = data.lineWidth;\\n    this.multiline = data.multiline;\\n    this.multipleSelection = !!data.multipleSelection;\\n    this.name = data.name;\\n    this.password = data.password;\\n    this.print = data.print;\\n    this.radiosInUnison = data.radiosInUnison;\\n    this.readonly = data.readonly;\\n    this.rect = data.rect;\\n    this.required = data.required;\\n    this.richText = data.richText;\\n    this.richValue = data.richValue;\\n    this.style = data.style;\\n    this.submitName = data.submitName;\\n    this.textFont = data.textFont;\\n    this.textSize = data.textSize;\\n    this.type = data.type;\\n    this.userName = data.userName;\\n    this._actions = createActionsMap(data.actions);\\n    this._browseForFileToSubmit = data.browseForFileToSubmit || null;\\n    this._buttonCaption = null;\\n    this._buttonIcon = null;\\n    this._charLimit = data.charLimit;\\n    this._children = null;\\n    this._currentValueIndices = data.currentValueIndices || 0;\\n    this._document = data.doc;\\n    this._fieldPath = data.fieldPath;\\n    this._fillColor = data.fillColor || [\\\"T\\\"];\\n    this._isChoice = Array.isArray(data.items);\\n    this._items = data.items || [];\\n    this._hasValue = data.hasOwnProperty(\\\"value\\\");\\n    this._page = data.page || 0;\\n    this._strokeColor = data.strokeColor || [\\\"G\\\", 0];\\n    this._textColor = data.textColor || [\\\"G\\\", 0];\\n    this._value = null;\\n    this._kidIds = data.kidIds || null;\\n    this._fieldType = getFieldType(this._actions);\\n    this._siblings = data.siblings || null;\\n    this._rotation = data.rotation || 0;\\n    this._globalEval = data.globalEval;\\n    this._appObjects = data.appObjects;\\n    this.value = data.value || \\\"\\\";\\n  }\\n  get currentValueIndices() {\\n    if (!this._isChoice) {\\n      return 0;\\n    }\\n    return this._currentValueIndices;\\n  }\\n  set currentValueIndices(indices) {\\n    if (!this._isChoice) {\\n      return;\\n    }\\n    if (!Array.isArray(indices)) {\\n      indices = [indices];\\n    }\\n    if (!indices.every(i => typeof i === \\\"number\\\" && Number.isInteger(i) && i >= 0 && i < this.numItems)) {\\n      return;\\n    }\\n    indices.sort();\\n    if (this.multipleSelection) {\\n      this._currentValueIndices = indices;\\n      this._value = [];\\n      indices.forEach(i => {\\n        this._value.push(this._items[i].displayValue);\\n      });\\n    } else if (indices.length > 0) {\\n      indices = indices.splice(1, indices.length - 1);\\n      this._currentValueIndices = indices[0];\\n      this._value = this._items[this._currentValueIndices];\\n    }\\n    this._send({\\n      id: this._id,\\n      indices\\n    });\\n  }\\n  get fillColor() {\\n    return this._fillColor;\\n  }\\n  set fillColor(color) {\\n    if (Color._isValidColor(color)) {\\n      this._fillColor = color;\\n    }\\n  }\\n  get bgColor() {\\n    return this.fillColor;\\n  }\\n  set bgColor(color) {\\n    this.fillColor = color;\\n  }\\n  get charLimit() {\\n    return this._charLimit;\\n  }\\n  set charLimit(limit) {\\n    if (typeof limit !== \\\"number\\\") {\\n      throw new Error(\\\"Invalid argument value\\\");\\n    }\\n    this._charLimit = Math.max(0, Math.floor(limit));\\n  }\\n  get numItems() {\\n    if (!this._isChoice) {\\n      throw new Error(\\\"Not a choice widget\\\");\\n    }\\n    return this._items.length;\\n  }\\n  set numItems(_) {\\n    throw new Error(\\\"field.numItems is read-only\\\");\\n  }\\n  get strokeColor() {\\n    return this._strokeColor;\\n  }\\n  set strokeColor(color) {\\n    if (Color._isValidColor(color)) {\\n      this._strokeColor = color;\\n    }\\n  }\\n  get borderColor() {\\n    return this.strokeColor;\\n  }\\n  set borderColor(color) {\\n    this.strokeColor = color;\\n  }\\n  get page() {\\n    return this._page;\\n  }\\n  set page(_) {\\n    throw new Error(\\\"field.page is read-only\\\");\\n  }\\n  get rotation() {\\n    return this._rotation;\\n  }\\n  set rotation(angle) {\\n    angle = Math.floor(angle);\\n    if (angle % 90 !== 0) {\\n      throw new Error(\\\"Invalid rotation: must be a multiple of 90\\\");\\n    }\\n    angle %= 360;\\n    if (angle < 0) {\\n      angle += 360;\\n    }\\n    this._rotation = angle;\\n  }\\n  get textColor() {\\n    return this._textColor;\\n  }\\n  set textColor(color) {\\n    if (Color._isValidColor(color)) {\\n      this._textColor = color;\\n    }\\n  }\\n  get fgColor() {\\n    return this.textColor;\\n  }\\n  set fgColor(color) {\\n    this.textColor = color;\\n  }\\n  get value() {\\n    return this._value;\\n  }\\n  set value(value) {\\n    if (this._isChoice) {\\n      this._setChoiceValue(value);\\n      return;\\n    }\\n    if (value === \\\"\\\" || typeof value !== \\\"string\\\" || this._fieldType >= FieldType.date) {\\n      this._originalValue = undefined;\\n      this._value = value;\\n      return;\\n    }\\n    this._originalValue = value;\\n    const _value = value.trim().replace(\\\",\\\", \\\".\\\");\\n    this._value = !isNaN(_value) ? parseFloat(_value) : value;\\n  }\\n  _getValue() {\\n    return this._originalValue ?? this.value;\\n  }\\n  _setChoiceValue(value) {\\n    if (this.multipleSelection) {\\n      if (!Array.isArray(value)) {\\n        value = [value];\\n      }\\n      const values = new Set(value);\\n      if (Array.isArray(this._currentValueIndices)) {\\n        this._currentValueIndices.length = 0;\\n        this._value.length = 0;\\n      } else {\\n        this._currentValueIndices = [];\\n        this._value = [];\\n      }\\n      this._items.forEach((item, i) => {\\n        if (values.has(item.exportValue)) {\\n          this._currentValueIndices.push(i);\\n          this._value.push(item.exportValue);\\n        }\\n      });\\n    } else {\\n      if (Array.isArray(value)) {\\n        value = value[0];\\n      }\\n      const index = this._items.findIndex(({\\n        exportValue\\n      }) => value === exportValue);\\n      if (index !== -1) {\\n        this._currentValueIndices = index;\\n        this._value = this._items[index].exportValue;\\n      }\\n    }\\n  }\\n  get valueAsString() {\\n    return (this._value ?? \\\"\\\").toString();\\n  }\\n  set valueAsString(_) {}\\n  browseForFileToSubmit() {\\n    if (this._browseForFileToSubmit) {\\n      this._browseForFileToSubmit();\\n    }\\n  }\\n  buttonGetCaption(nFace = 0) {\\n    if (this._buttonCaption) {\\n      return this._buttonCaption[nFace];\\n    }\\n    return \\\"\\\";\\n  }\\n  buttonGetIcon(nFace = 0) {\\n    if (this._buttonIcon) {\\n      return this._buttonIcon[nFace];\\n    }\\n    return null;\\n  }\\n  buttonImportIcon(cPath = null, nPave = 0) {}\\n  buttonSetCaption(cCaption, nFace = 0) {\\n    if (!this._buttonCaption) {\\n      this._buttonCaption = [\\\"\\\", \\\"\\\", \\\"\\\"];\\n    }\\n    this._buttonCaption[nFace] = cCaption;\\n  }\\n  buttonSetIcon(oIcon, nFace = 0) {\\n    if (!this._buttonIcon) {\\n      this._buttonIcon = [null, null, null];\\n    }\\n    this._buttonIcon[nFace] = oIcon;\\n  }\\n  checkThisBox(nWidget, bCheckIt = true) {}\\n  clearItems() {\\n    if (!this._isChoice) {\\n      throw new Error(\\\"Not a choice widget\\\");\\n    }\\n    this._items = [];\\n    this._send({\\n      id: this._id,\\n      clear: null\\n    });\\n  }\\n  deleteItemAt(nIdx = null) {\\n    if (!this._isChoice) {\\n      throw new Error(\\\"Not a choice widget\\\");\\n    }\\n    if (!this.numItems) {\\n      return;\\n    }\\n    if (nIdx === null) {\\n      nIdx = Array.isArray(this._currentValueIndices) ? this._currentValueIndices[0] : this._currentValueIndices;\\n      nIdx ||= 0;\\n    }\\n    if (nIdx < 0 || nIdx >= this.numItems) {\\n      nIdx = this.numItems - 1;\\n    }\\n    this._items.splice(nIdx, 1);\\n    if (Array.isArray(this._currentValueIndices)) {\\n      let index = this._currentValueIndices.findIndex(i => i >= nIdx);\\n      if (index !== -1) {\\n        if (this._currentValueIndices[index] === nIdx) {\\n          this._currentValueIndices.splice(index, 1);\\n        }\\n        for (const ii = this._currentValueIndices.length; index < ii; index++) {\\n          --this._currentValueIndices[index];\\n        }\\n      }\\n    } else if (this._currentValueIndices === nIdx) {\\n      this._currentValueIndices = this.numItems > 0 ? 0 : -1;\\n    } else if (this._currentValueIndices > nIdx) {\\n      --this._currentValueIndices;\\n    }\\n    this._send({\\n      id: this._id,\\n      remove: nIdx\\n    });\\n  }\\n  getItemAt(nIdx = -1, bExportValue = false) {\\n    if (!this._isChoice) {\\n      throw new Error(\\\"Not a choice widget\\\");\\n    }\\n    if (nIdx < 0 || nIdx >= this.numItems) {\\n      nIdx = this.numItems - 1;\\n    }\\n    const item = this._items[nIdx];\\n    return bExportValue ? item.exportValue : item.displayValue;\\n  }\\n  getArray() {\\n    if (this._kidIds) {\\n      const array = [];\\n      const fillArrayWithKids = kidIds => {\\n        for (const id of kidIds) {\\n          const obj = this._appObjects[id];\\n          if (!obj) {\\n            continue;\\n          }\\n          if (obj.obj._hasValue) {\\n            array.push(obj.wrapped);\\n          }\\n          if (obj.obj._kidIds) {\\n            fillArrayWithKids(obj.obj._kidIds);\\n          }\\n        }\\n      };\\n      fillArrayWithKids(this._kidIds);\\n      return array;\\n    }\\n    if (this._children === null) {\\n      this._children = this._document.obj._getTerminalChildren(this._fieldPath);\\n    }\\n    return this._children;\\n  }\\n  getLock() {\\n    return undefined;\\n  }\\n  isBoxChecked(nWidget) {\\n    return false;\\n  }\\n  isDefaultChecked(nWidget) {\\n    return false;\\n  }\\n  insertItemAt(cName, cExport = undefined, nIdx = 0) {\\n    if (!this._isChoice) {\\n      throw new Error(\\\"Not a choice widget\\\");\\n    }\\n    if (!cName) {\\n      return;\\n    }\\n    if (nIdx < 0 || nIdx > this.numItems) {\\n      nIdx = this.numItems;\\n    }\\n    if (this._items.some(({\\n      displayValue\\n    }) => displayValue === cName)) {\\n      return;\\n    }\\n    if (cExport === undefined) {\\n      cExport = cName;\\n    }\\n    const data = {\\n      displayValue: cName,\\n      exportValue: cExport\\n    };\\n    this._items.splice(nIdx, 0, data);\\n    if (Array.isArray(this._currentValueIndices)) {\\n      let index = this._currentValueIndices.findIndex(i => i >= nIdx);\\n      if (index !== -1) {\\n        for (const ii = this._currentValueIndices.length; index < ii; index++) {\\n          ++this._currentValueIndices[index];\\n        }\\n      }\\n    } else if (this._currentValueIndices >= nIdx) {\\n      ++this._currentValueIndices;\\n    }\\n    this._send({\\n      id: this._id,\\n      insert: {\\n        index: nIdx,\\n        ...data\\n      }\\n    });\\n  }\\n  setAction(cTrigger, cScript) {\\n    if (typeof cTrigger !== \\\"string\\\" || typeof cScript !== \\\"string\\\") {\\n      return;\\n    }\\n    if (!(cTrigger in this._actions)) {\\n      this._actions[cTrigger] = [];\\n    }\\n    this._actions[cTrigger].push(cScript);\\n  }\\n  setFocus() {\\n    this._send({\\n      id: this._id,\\n      focus: true\\n    });\\n  }\\n  setItems(oArray) {\\n    if (!this._isChoice) {\\n      throw new Error(\\\"Not a choice widget\\\");\\n    }\\n    this._items.length = 0;\\n    for (const element of oArray) {\\n      let displayValue, exportValue;\\n      if (Array.isArray(element)) {\\n        displayValue = element[0]?.toString() || \\\"\\\";\\n        exportValue = element[1]?.toString() || \\\"\\\";\\n      } else {\\n        displayValue = exportValue = element?.toString() || \\\"\\\";\\n      }\\n      this._items.push({\\n        displayValue,\\n        exportValue\\n      });\\n    }\\n    this._currentValueIndices = 0;\\n    this._send({\\n      id: this._id,\\n      items: this._items\\n    });\\n  }\\n  setLock() {}\\n  signatureGetModifications() {}\\n  signatureGetSeedValue() {}\\n  signatureInfo() {}\\n  signatureSetSeedValue() {}\\n  signatureSign() {}\\n  signatureValidate() {}\\n  _isButton() {\\n    return false;\\n  }\\n  _reset() {\\n    this.value = this.defaultValue;\\n  }\\n  _runActions(event) {\\n    const eventName = event.name;\\n    if (!this._actions.has(eventName)) {\\n      return false;\\n    }\\n    const actions = this._actions.get(eventName);\\n    try {\\n      for (const action of actions) {\\n        this._globalEval(action);\\n      }\\n    } catch (error) {\\n      event.rc = false;\\n      throw error;\\n    }\\n    return true;\\n  }\\n}\\nclass RadioButtonField extends Field {\\n  constructor(otherButtons, data) {\\n    super(data);\\n    this.exportValues = [this.exportValues];\\n    this._radioIds = [this._id];\\n    this._radioActions = [this._actions];\\n    for (const radioData of otherButtons) {\\n      this.exportValues.push(radioData.exportValues);\\n      this._radioIds.push(radioData.id);\\n      this._radioActions.push(createActionsMap(radioData.actions));\\n      if (this._value === radioData.exportValues) {\\n        this._id = radioData.id;\\n      }\\n    }\\n    this._hasBeenInitialized = true;\\n    this._value = data.value || \\\"\\\";\\n  }\\n  get value() {\\n    return this._value;\\n  }\\n  set value(value) {\\n    if (!this._hasBeenInitialized) {\\n      return;\\n    }\\n    if (value === null || value === undefined) {\\n      this._value = \\\"\\\";\\n    }\\n    const i = this.exportValues.indexOf(value);\\n    if (0 <= i && i < this._radioIds.length) {\\n      this._id = this._radioIds[i];\\n      this._value = value;\\n    } else if (value === \\\"Off\\\" && this._radioIds.length === 2) {\\n      const nextI = (1 + this._radioIds.indexOf(this._id)) % 2;\\n      this._id = this._radioIds[nextI];\\n      this._value = this.exportValues[nextI];\\n    }\\n  }\\n  checkThisBox(nWidget, bCheckIt = true) {\\n    if (nWidget < 0 || nWidget >= this._radioIds.length || !bCheckIt) {\\n      return;\\n    }\\n    this._id = this._radioIds[nWidget];\\n    this._value = this.exportValues[nWidget];\\n    this._send({\\n      id: this._id,\\n      value: this._value\\n    });\\n  }\\n  isBoxChecked(nWidget) {\\n    return nWidget >= 0 && nWidget < this._radioIds.length && this._id === this._radioIds[nWidget];\\n  }\\n  isDefaultChecked(nWidget) {\\n    return nWidget >= 0 && nWidget < this.exportValues.length && this.defaultValue === this.exportValues[nWidget];\\n  }\\n  _getExportValue(state) {\\n    const i = this._radioIds.indexOf(this._id);\\n    return this.exportValues[i];\\n  }\\n  _runActions(event) {\\n    const i = this._radioIds.indexOf(this._id);\\n    this._actions = this._radioActions[i];\\n    return super._runActions(event);\\n  }\\n  _isButton() {\\n    return true;\\n  }\\n}\\nclass CheckboxField extends RadioButtonField {\\n  get value() {\\n    return this._value;\\n  }\\n  set value(value) {\\n    if (!value || value === \\\"Off\\\") {\\n      this._value = \\\"Off\\\";\\n    } else {\\n      super.value = value;\\n    }\\n  }\\n  _getExportValue(state) {\\n    return state ? super._getExportValue(state) : \\\"Off\\\";\\n  }\\n  isBoxChecked(nWidget) {\\n    if (this._value === \\\"Off\\\") {\\n      return false;\\n    }\\n    return super.isBoxChecked(nWidget);\\n  }\\n  isDefaultChecked(nWidget) {\\n    if (this.defaultValue === \\\"Off\\\") {\\n      return this._value === \\\"Off\\\";\\n    }\\n    return super.isDefaultChecked(nWidget);\\n  }\\n  checkThisBox(nWidget, bCheckIt = true) {\\n    if (nWidget < 0 || nWidget >= this._radioIds.length) {\\n      return;\\n    }\\n    this._id = this._radioIds[nWidget];\\n    this._value = bCheckIt ? this.exportValues[nWidget] : \\\"Off\\\";\\n    this._send({\\n      id: this._id,\\n      value: this._value\\n    });\\n  }\\n}\\n\\n;// CONCATENATED MODULE: ./src/scripting_api/aform.js\\n\\nclass AForm {\\n  constructor(document, app, util, color) {\\n    this._document = document;\\n    this._app = app;\\n    this._util = util;\\n    this._color = color;\\n    this._dateFormats = [\\\"m/d\\\", \\\"m/d/yy\\\", \\\"mm/dd/yy\\\", \\\"mm/yy\\\", \\\"d-mmm\\\", \\\"d-mmm-yy\\\", \\\"dd-mmm-yy\\\", \\\"yy-mm-dd\\\", \\\"mmm-yy\\\", \\\"mmmm-yy\\\", \\\"mmm d, yyyy\\\", \\\"mmmm d, yyyy\\\", \\\"m/d/yy h:MM tt\\\", \\\"m/d/yy HH:MM\\\"];\\n    this._timeFormats = [\\\"HH:MM\\\", \\\"h:MM tt\\\", \\\"HH:MM:ss\\\", \\\"h:MM:ss tt\\\"];\\n    this._dateActionsCache = new Map();\\n    this._emailRegex = new RegExp(\\\"^[a-zA-Z0-9.!#$%&'*+\\\\\\\\/=?^_`{|}~-]+\\\" + \\\"@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\\" + \\\"(?:\\\\\\\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$\\\");\\n  }\\n  _mkTargetName(event) {\\n    return event.target ? `[ ${event.target.name} ]` : \\\"\\\";\\n  }\\n  _tryToGuessDate(cFormat, cDate) {\\n    let actions = this._dateActionsCache.get(cFormat);\\n    if (!actions) {\\n      actions = [];\\n      this._dateActionsCache.set(cFormat, actions);\\n      cFormat.replaceAll(/(d+)|(m+)|(y+)|(H+)|(M+)|(s+)/g, function (match, d, m, y, H, M, s) {\\n        if (d) {\\n          actions.push((n, date) => {\\n            if (n >= 1 && n <= 31) {\\n              date.setDate(n);\\n              return true;\\n            }\\n            return false;\\n          });\\n        } else if (m) {\\n          actions.push((n, date) => {\\n            if (n >= 1 && n <= 12) {\\n              date.setMonth(n - 1);\\n              return true;\\n            }\\n            return false;\\n          });\\n        } else if (y) {\\n          actions.push((n, date) => {\\n            if (n < 50) {\\n              n += 2000;\\n            } else if (n < 100) {\\n              n += 1900;\\n            }\\n            date.setYear(n);\\n            return true;\\n          });\\n        } else if (H) {\\n          actions.push((n, date) => {\\n            if (n >= 0 && n <= 23) {\\n              date.setHours(n);\\n              return true;\\n            }\\n            return false;\\n          });\\n        } else if (M) {\\n          actions.push((n, date) => {\\n            if (n >= 0 && n <= 59) {\\n              date.setMinutes(n);\\n              return true;\\n            }\\n            return false;\\n          });\\n        } else if (s) {\\n          actions.push((n, date) => {\\n            if (n >= 0 && n <= 59) {\\n              date.setSeconds(n);\\n              return true;\\n            }\\n            return false;\\n          });\\n        }\\n        return \\\"\\\";\\n      });\\n    }\\n    const number = /\\\\d+/g;\\n    let i = 0;\\n    let array;\\n    const date = new Date();\\n    while ((array = number.exec(cDate)) !== null) {\\n      if (i < actions.length) {\\n        if (!actions[i++](parseInt(array[0]), date)) {\\n          return null;\\n        }\\n      } else {\\n        break;\\n      }\\n    }\\n    if (i === 0) {\\n      return null;\\n    }\\n    return date;\\n  }\\n  _parseDate(cFormat, cDate) {\\n    let date = null;\\n    try {\\n      date = this._util.scand(cFormat, cDate);\\n    } catch {}\\n    if (!date) {\\n      date = Date.parse(cDate);\\n      date = isNaN(date) ? this._tryToGuessDate(cFormat, cDate) : new Date(date);\\n    }\\n    return date;\\n  }\\n  AFMergeChange(event = globalThis.event) {\\n    if (event.willCommit) {\\n      return event.value.toString();\\n    }\\n    return this._app._eventDispatcher.mergeChange(event);\\n  }\\n  AFParseDateEx(cString, cOrder) {\\n    return this._parseDate(cOrder, cString);\\n  }\\n  AFExtractNums(str) {\\n    if (typeof str === \\\"number\\\") {\\n      return [str];\\n    }\\n    if (!str || typeof str !== \\\"string\\\") {\\n      return null;\\n    }\\n    const first = str.charAt(0);\\n    if (first === \\\".\\\" || first === \\\",\\\") {\\n      str = `0${str}`;\\n    }\\n    const numbers = str.match(/(\\\\d+)/g);\\n    if (numbers.length === 0) {\\n      return null;\\n    }\\n    return numbers;\\n  }\\n  AFMakeNumber(str) {\\n    if (typeof str === \\\"number\\\") {\\n      return str;\\n    }\\n    if (typeof str !== \\\"string\\\") {\\n      return null;\\n    }\\n    str = str.trim().replace(\\\",\\\", \\\".\\\");\\n    const number = parseFloat(str);\\n    if (isNaN(number) || !isFinite(number)) {\\n      return null;\\n    }\\n    return number;\\n  }\\n  AFMakeArrayFromList(string) {\\n    if (typeof string === \\\"string\\\") {\\n      return string.split(/, ?/g);\\n    }\\n    return string;\\n  }\\n  AFNumber_Format(nDec, sepStyle, negStyle, currStyle, strCurrency, bCurrencyPrepend) {\\n    const event = globalThis.event;\\n    let value = this.AFMakeNumber(event.value);\\n    if (value === null) {\\n      event.value = \\\"\\\";\\n      return;\\n    }\\n    const sign = Math.sign(value);\\n    const buf = [];\\n    let hasParen = false;\\n    if (sign === -1 && bCurrencyPrepend && negStyle === 0) {\\n      buf.push(\\\"-\\\");\\n    }\\n    if ((negStyle === 2 || negStyle === 3) && sign === -1) {\\n      buf.push(\\\"(\\\");\\n      hasParen = true;\\n    }\\n    if (bCurrencyPrepend) {\\n      buf.push(strCurrency);\\n    }\\n    sepStyle = Math.min(Math.max(0, Math.floor(sepStyle)), 4);\\n    buf.push(\\\"%,\\\", sepStyle, \\\".\\\", nDec.toString(), \\\"f\\\");\\n    if (!bCurrencyPrepend) {\\n      buf.push(strCurrency);\\n    }\\n    if (hasParen) {\\n      buf.push(\\\")\\\");\\n    }\\n    if (negStyle === 1 || negStyle === 3) {\\n      event.target.textColor = sign === 1 ? this._color.black : this._color.red;\\n    }\\n    if ((negStyle !== 0 || bCurrencyPrepend) && sign === -1) {\\n      value = -value;\\n    }\\n    const formatStr = buf.join(\\\"\\\");\\n    event.value = this._util.printf(formatStr, value);\\n  }\\n  AFNumber_Keystroke(nDec, sepStyle, negStyle, currStyle, strCurrency, bCurrencyPrepend) {\\n    const event = globalThis.event;\\n    let value = this.AFMergeChange(event);\\n    if (!value) {\\n      return;\\n    }\\n    value = value.trim();\\n    let pattern;\\n    if (sepStyle > 1) {\\n      pattern = event.willCommit ? /^[+-]?(\\\\d+(,\\\\d*)?|,\\\\d+)$/ : /^[+-]?\\\\d*,?\\\\d*$/;\\n    } else {\\n      pattern = event.willCommit ? /^[+-]?(\\\\d+(\\\\.\\\\d*)?|\\\\.\\\\d+)$/ : /^[+-]?\\\\d*\\\\.?\\\\d*$/;\\n    }\\n    if (!pattern.test(value)) {\\n      if (event.willCommit) {\\n        const err = `${GlobalConstants.IDS_INVALID_VALUE} ${this._mkTargetName(event)}`;\\n        this._app.alert(err);\\n      }\\n      event.rc = false;\\n    }\\n    if (event.willCommit && sepStyle > 1) {\\n      event.value = parseFloat(value.replace(\\\",\\\", \\\".\\\"));\\n    }\\n  }\\n  AFPercent_Format(nDec, sepStyle, percentPrepend = false) {\\n    if (typeof nDec !== \\\"number\\\") {\\n      return;\\n    }\\n    if (typeof sepStyle !== \\\"number\\\") {\\n      return;\\n    }\\n    if (nDec < 0) {\\n      throw new Error(\\\"Invalid nDec value in AFPercent_Format\\\");\\n    }\\n    const event = globalThis.event;\\n    if (nDec > 512) {\\n      event.value = \\\"%\\\";\\n      return;\\n    }\\n    nDec = Math.floor(nDec);\\n    sepStyle = Math.min(Math.max(0, Math.floor(sepStyle)), 4);\\n    let value = this.AFMakeNumber(event.value);\\n    if (value === null) {\\n      event.value = \\\"%\\\";\\n      return;\\n    }\\n    const formatStr = `%,${sepStyle}.${nDec}f`;\\n    value = this._util.printf(formatStr, value * 100);\\n    event.value = percentPrepend ? `%${value}` : `${value}%`;\\n  }\\n  AFPercent_Keystroke(nDec, sepStyle) {\\n    this.AFNumber_Keystroke(nDec, sepStyle, 0, 0, \\\"\\\", true);\\n  }\\n  AFDate_FormatEx(cFormat) {\\n    const event = globalThis.event;\\n    const value = event.value;\\n    if (!value) {\\n      return;\\n    }\\n    const date = this._parseDate(cFormat, value);\\n    if (date !== null) {\\n      event.value = this._util.printd(cFormat, date);\\n    }\\n  }\\n  AFDate_Format(pdf) {\\n    if (pdf >= 0 && pdf < this._dateFormats.length) {\\n      this.AFDate_FormatEx(this._dateFormats[pdf]);\\n    }\\n  }\\n  AFDate_KeystrokeEx(cFormat) {\\n    const event = globalThis.event;\\n    if (!event.willCommit) {\\n      return;\\n    }\\n    const value = this.AFMergeChange(event);\\n    if (!value) {\\n      return;\\n    }\\n    if (this._parseDate(cFormat, value) === null) {\\n      const invalid = GlobalConstants.IDS_INVALID_DATE;\\n      const invalid2 = GlobalConstants.IDS_INVALID_DATE2;\\n      const err = `${invalid} ${this._mkTargetName(event)}${invalid2}${cFormat}`;\\n      this._app.alert(err);\\n      event.rc = false;\\n    }\\n  }\\n  AFDate_Keystroke(pdf) {\\n    if (pdf >= 0 && pdf < this._dateFormats.length) {\\n      this.AFDate_KeystrokeEx(this._dateFormats[pdf]);\\n    }\\n  }\\n  AFRange_Validate(bGreaterThan, nGreaterThan, bLessThan, nLessThan) {\\n    const event = globalThis.event;\\n    if (!event.value) {\\n      return;\\n    }\\n    const value = this.AFMakeNumber(event.value);\\n    if (value === null) {\\n      return;\\n    }\\n    bGreaterThan = !!bGreaterThan;\\n    bLessThan = !!bLessThan;\\n    if (bGreaterThan) {\\n      nGreaterThan = this.AFMakeNumber(nGreaterThan);\\n      if (nGreaterThan === null) {\\n        return;\\n      }\\n    }\\n    if (bLessThan) {\\n      nLessThan = this.AFMakeNumber(nLessThan);\\n      if (nLessThan === null) {\\n        return;\\n      }\\n    }\\n    let err = \\\"\\\";\\n    if (bGreaterThan && bLessThan) {\\n      if (value < nGreaterThan || value > nLessThan) {\\n        err = this._util.printf(GlobalConstants.IDS_GT_AND_LT, nGreaterThan, nLessThan);\\n      }\\n    } else if (bGreaterThan) {\\n      if (value < nGreaterThan) {\\n        err = this._util.printf(GlobalConstants.IDS_GREATER_THAN, nGreaterThan);\\n      }\\n    } else if (value > nLessThan) {\\n      err = this._util.printf(GlobalConstants.IDS_LESS_THAN, nLessThan);\\n    }\\n    if (err) {\\n      this._app.alert(err);\\n      event.rc = false;\\n    }\\n  }\\n  AFSimple(cFunction, nValue1, nValue2) {\\n    const value1 = this.AFMakeNumber(nValue1);\\n    if (value1 === null) {\\n      throw new Error(\\\"Invalid nValue1 in AFSimple\\\");\\n    }\\n    const value2 = this.AFMakeNumber(nValue2);\\n    if (value2 === null) {\\n      throw new Error(\\\"Invalid nValue2 in AFSimple\\\");\\n    }\\n    switch (cFunction) {\\n      case \\\"AVG\\\":\\n        return (value1 + value2) / 2;\\n      case \\\"SUM\\\":\\n        return value1 + value2;\\n      case \\\"PRD\\\":\\n        return value1 * value2;\\n      case \\\"MIN\\\":\\n        return Math.min(value1, value2);\\n      case \\\"MAX\\\":\\n        return Math.max(value1, value2);\\n    }\\n    throw new Error(\\\"Invalid cFunction in AFSimple\\\");\\n  }\\n  AFSimple_Calculate(cFunction, cFields) {\\n    const actions = {\\n      AVG: args => args.reduce((acc, value) => acc + value, 0) / args.length,\\n      SUM: args => args.reduce((acc, value) => acc + value, 0),\\n      PRD: args => args.reduce((acc, value) => acc * value, 1),\\n      MIN: args => args.reduce((acc, value) => Math.min(acc, value), Number.MAX_VALUE),\\n      MAX: args => args.reduce((acc, value) => Math.max(acc, value), Number.MIN_VALUE)\\n    };\\n    if (!(cFunction in actions)) {\\n      throw new TypeError(\\\"Invalid function in AFSimple_Calculate\\\");\\n    }\\n    const event = globalThis.event;\\n    const values = [];\\n    cFields = this.AFMakeArrayFromList(cFields);\\n    for (const cField of cFields) {\\n      const field = this._document.getField(cField);\\n      if (!field) {\\n        continue;\\n      }\\n      for (const child of field.getArray()) {\\n        const number = this.AFMakeNumber(child.value);\\n        if (number !== null) {\\n          values.push(number);\\n        }\\n      }\\n    }\\n    if (values.length === 0) {\\n      event.value = cFunction === \\\"PRD\\\" ? 1 : 0;\\n      return;\\n    }\\n    const res = actions[cFunction](values);\\n    event.value = Math.round(1e6 * res) / 1e6;\\n  }\\n  AFSpecial_Format(psf) {\\n    const event = globalThis.event;\\n    if (!event.value) {\\n      return;\\n    }\\n    psf = this.AFMakeNumber(psf);\\n    let formatStr;\\n    switch (psf) {\\n      case 0:\\n        formatStr = \\\"99999\\\";\\n        break;\\n      case 1:\\n        formatStr = \\\"99999-9999\\\";\\n        break;\\n      case 2:\\n        formatStr = this._util.printx(\\\"9999999999\\\", event.value).length >= 10 ? \\\"(999) 999-9999\\\" : \\\"999-9999\\\";\\n        break;\\n      case 3:\\n        formatStr = \\\"999-99-9999\\\";\\n        break;\\n      default:\\n        throw new Error(\\\"Invalid psf in AFSpecial_Format\\\");\\n    }\\n    event.value = this._util.printx(formatStr, event.value);\\n  }\\n  AFSpecial_KeystrokeEx(cMask) {\\n    if (!cMask) {\\n      return;\\n    }\\n    const event = globalThis.event;\\n    const value = this.AFMergeChange(event);\\n    if (!value) {\\n      return;\\n    }\\n    const checkers = new Map([[\\\"9\\\", char => char >= \\\"0\\\" && char <= \\\"9\\\"], [\\\"A\\\", char => \\\"a\\\" <= char && char <= \\\"z\\\" || \\\"A\\\" <= char && char <= \\\"Z\\\"], [\\\"O\\\", char => \\\"a\\\" <= char && char <= \\\"z\\\" || \\\"A\\\" <= char && char <= \\\"Z\\\" || \\\"0\\\" <= char && char <= \\\"9\\\"], [\\\"X\\\", char => true]]);\\n    function _checkValidity(_value, _cMask) {\\n      for (let i = 0, ii = _value.length; i < ii; i++) {\\n        const mask = _cMask.charAt(i);\\n        const char = _value.charAt(i);\\n        const checker = checkers.get(mask);\\n        if (checker) {\\n          if (!checker(char)) {\\n            return false;\\n          }\\n        } else if (mask !== char) {\\n          return false;\\n        }\\n      }\\n      return true;\\n    }\\n    const err = `${GlobalConstants.IDS_INVALID_VALUE} = \\\"${cMask}\\\"`;\\n    if (value.length > cMask.length) {\\n      this._app.alert(err);\\n      event.rc = false;\\n      return;\\n    }\\n    if (event.willCommit) {\\n      if (value.length < cMask.length) {\\n        this._app.alert(err);\\n        event.rc = false;\\n        return;\\n      }\\n      if (!_checkValidity(value, cMask)) {\\n        this._app.alert(err);\\n        event.rc = false;\\n        return;\\n      }\\n      event.value += cMask.substring(value.length);\\n      return;\\n    }\\n    if (value.length < cMask.length) {\\n      cMask = cMask.substring(0, value.length);\\n    }\\n    if (!_checkValidity(value, cMask)) {\\n      this._app.alert(err);\\n      event.rc = false;\\n    }\\n  }\\n  AFSpecial_Keystroke(psf) {\\n    const event = globalThis.event;\\n    psf = this.AFMakeNumber(psf);\\n    let formatStr;\\n    switch (psf) {\\n      case 0:\\n        formatStr = \\\"99999\\\";\\n        break;\\n      case 1:\\n        formatStr = \\\"99999-9999\\\";\\n        break;\\n      case 2:\\n        const value = this.AFMergeChange(event);\\n        formatStr = value.length > 8 || value.startsWith(\\\"(\\\") ? \\\"(999) 999-9999\\\" : \\\"999-9999\\\";\\n        break;\\n      case 3:\\n        formatStr = \\\"999-99-9999\\\";\\n        break;\\n      default:\\n        throw new Error(\\\"Invalid psf in AFSpecial_Keystroke\\\");\\n    }\\n    this.AFSpecial_KeystrokeEx(formatStr);\\n  }\\n  AFTime_FormatEx(cFormat) {\\n    this.AFDate_FormatEx(cFormat);\\n  }\\n  AFTime_Format(pdf) {\\n    if (pdf >= 0 && pdf < this._timeFormats.length) {\\n      this.AFDate_FormatEx(this._timeFormats[pdf]);\\n    }\\n  }\\n  AFTime_KeystrokeEx(cFormat) {\\n    this.AFDate_KeystrokeEx(cFormat);\\n  }\\n  AFTime_Keystroke(pdf) {\\n    if (pdf >= 0 && pdf < this._timeFormats.length) {\\n      this.AFDate_KeystrokeEx(this._timeFormats[pdf]);\\n    }\\n  }\\n  eMailValidate(str) {\\n    return this._emailRegex.test(str);\\n  }\\n  AFExactMatch(rePatterns, str) {\\n    if (rePatterns instanceof RegExp) {\\n      return str.match(rePatterns)?.[0] === str || 0;\\n    }\\n    return rePatterns.findIndex(re => str.match(re)?.[0] === str) + 1;\\n  }\\n}\\n\\n;// CONCATENATED MODULE: ./src/scripting_api/app_utils.js\\nconst VIEWER_TYPE = \\\"PDF.js\\\";\\nconst VIEWER_VARIATION = \\\"Full\\\";\\nconst VIEWER_VERSION = 21.00720099;\\nconst FORMS_VERSION = 21.00720099;\\nconst USERACTIVATION_CALLBACKID = 0;\\nconst USERACTIVATION_MAXTIME_VALIDITY = 5000;\\nfunction serializeError(error) {\\n  const value = `${error.toString()}\\\\n${error.stack}`;\\n  return {\\n    command: \\\"error\\\",\\n    value\\n  };\\n}\\n\\n;// CONCATENATED MODULE: ./src/scripting_api/event.js\\n\\nclass Event {\\n  constructor(data) {\\n    this.change = data.change || \\\"\\\";\\n    this.changeEx = data.changeEx || null;\\n    this.commitKey = data.commitKey || 0;\\n    this.fieldFull = data.fieldFull || false;\\n    this.keyDown = data.keyDown || false;\\n    this.modifier = data.modifier || false;\\n    this.name = data.name;\\n    this.rc = true;\\n    this.richChange = data.richChange || [];\\n    this.richChangeEx = data.richChangeEx || [];\\n    this.richValue = data.richValue || [];\\n    this.selEnd = data.selEnd ?? -1;\\n    this.selStart = data.selStart ?? -1;\\n    this.shift = data.shift || false;\\n    this.source = data.source || null;\\n    this.target = data.target || null;\\n    this.targetName = \\\"\\\";\\n    this.type = \\\"Field\\\";\\n    this.value = data.value || \\\"\\\";\\n    this.willCommit = data.willCommit || false;\\n  }\\n}\\nclass EventDispatcher {\\n  constructor(document, calculationOrder, objects, externalCall) {\\n    this._document = document;\\n    this._calculationOrder = calculationOrder;\\n    this._objects = objects;\\n    this._externalCall = externalCall;\\n    this._document.obj._eventDispatcher = this;\\n    this._isCalculating = false;\\n  }\\n  mergeChange(event) {\\n    let value = event.value;\\n    if (Array.isArray(value)) {\\n      return value;\\n    }\\n    if (typeof value !== \\\"string\\\") {\\n      value = value.toString();\\n    }\\n    const prefix = event.selStart >= 0 ? value.substring(0, event.selStart) : \\\"\\\";\\n    const postfix = event.selEnd >= 0 && event.selEnd <= value.length ? value.substring(event.selEnd) : \\\"\\\";\\n    return `${prefix}${event.change}${postfix}`;\\n  }\\n  userActivation() {\\n    this._document.obj._userActivation = true;\\n    this._externalCall(\\\"setTimeout\\\", [USERACTIVATION_CALLBACKID, USERACTIVATION_MAXTIME_VALIDITY]);\\n  }\\n  dispatch(baseEvent) {\\n    const id = baseEvent.id;\\n    if (!(id in this._objects)) {\\n      let event;\\n      if (id === \\\"doc\\\" || id === \\\"page\\\") {\\n        event = globalThis.event = new Event(baseEvent);\\n        event.source = event.target = this._document.wrapped;\\n        event.name = baseEvent.name;\\n      }\\n      if (id === \\\"doc\\\") {\\n        const eventName = event.name;\\n        if (eventName === \\\"Open\\\") {\\n          this.userActivation();\\n          this._document.obj._initActions();\\n          this.formatAll();\\n        }\\n        if (![\\\"DidPrint\\\", \\\"DidSave\\\", \\\"WillPrint\\\", \\\"WillSave\\\"].includes(eventName)) {\\n          this.userActivation();\\n        }\\n        this._document.obj._dispatchDocEvent(event.name);\\n      } else if (id === \\\"page\\\") {\\n        this.userActivation();\\n        this._document.obj._dispatchPageEvent(event.name, baseEvent.actions, baseEvent.pageNumber);\\n      } else if (id === \\\"app\\\" && baseEvent.name === \\\"ResetForm\\\") {\\n        this.userActivation();\\n        for (const fieldId of baseEvent.ids) {\\n          const obj = this._objects[fieldId];\\n          obj?.obj._reset();\\n        }\\n      }\\n      return;\\n    }\\n    const name = baseEvent.name;\\n    const source = this._objects[id];\\n    const event = globalThis.event = new Event(baseEvent);\\n    let savedChange;\\n    this.userActivation();\\n    if (source.obj._isButton()) {\\n      source.obj._id = id;\\n      event.value = source.obj._getExportValue(event.value);\\n      if (name === \\\"Action\\\") {\\n        source.obj._value = event.value;\\n      }\\n    }\\n    switch (name) {\\n      case \\\"Keystroke\\\":\\n        savedChange = {\\n          value: event.value,\\n          changeEx: event.changeEx,\\n          change: event.change,\\n          selStart: event.selStart,\\n          selEnd: event.selEnd\\n        };\\n        break;\\n      case \\\"Blur\\\":\\n      case \\\"Focus\\\":\\n        Object.defineProperty(event, \\\"value\\\", {\\n          configurable: false,\\n          writable: false,\\n          enumerable: true,\\n          value: event.value\\n        });\\n        break;\\n      case \\\"Validate\\\":\\n        this.runValidation(source, event);\\n        return;\\n      case \\\"Action\\\":\\n        this.runActions(source, source, event, name);\\n        this.runCalculate(source, event);\\n        return;\\n    }\\n    this.runActions(source, source, event, name);\\n    if (name !== \\\"Keystroke\\\") {\\n      return;\\n    }\\n    if (event.rc) {\\n      if (event.willCommit) {\\n        this.runValidation(source, event);\\n      } else {\\n        if (source.obj._isChoice) {\\n          source.obj.value = savedChange.changeEx;\\n          source.obj._send({\\n            id: source.obj._id,\\n            siblings: source.obj._siblings,\\n            value: source.obj.value\\n          });\\n          return;\\n        }\\n        const value = source.obj.value = this.mergeChange(event);\\n        let selStart, selEnd;\\n        if (event.selStart !== savedChange.selStart || event.selEnd !== savedChange.selEnd) {\\n          selStart = event.selStart;\\n          selEnd = event.selEnd;\\n        } else {\\n          selEnd = selStart = savedChange.selStart + event.change.length;\\n        }\\n        source.obj._send({\\n          id: source.obj._id,\\n          siblings: source.obj._siblings,\\n          value,\\n          selRange: [selStart, selEnd]\\n        });\\n      }\\n    } else if (!event.willCommit) {\\n      source.obj._send({\\n        id: source.obj._id,\\n        siblings: source.obj._siblings,\\n        value: savedChange.value,\\n        selRange: [savedChange.selStart, savedChange.selEnd]\\n      });\\n    } else {\\n      source.obj._send({\\n        id: source.obj._id,\\n        siblings: source.obj._siblings,\\n        value: \\\"\\\",\\n        formattedValue: null,\\n        selRange: [0, 0]\\n      });\\n    }\\n  }\\n  formatAll() {\\n    const event = globalThis.event = new Event({});\\n    for (const source of Object.values(this._objects)) {\\n      event.value = source.obj._getValue();\\n      this.runActions(source, source, event, \\\"Format\\\");\\n    }\\n  }\\n  runValidation(source, event) {\\n    const didValidateRun = this.runActions(source, source, event, \\\"Validate\\\");\\n    if (event.rc) {\\n      source.obj.value = event.value;\\n      this.runCalculate(source, event);\\n      const savedValue = event.value = source.obj._getValue();\\n      let formattedValue = null;\\n      if (this.runActions(source, source, event, \\\"Format\\\")) {\\n        formattedValue = event.value?.toString?.();\\n      }\\n      source.obj._send({\\n        id: source.obj._id,\\n        siblings: source.obj._siblings,\\n        value: savedValue,\\n        formattedValue\\n      });\\n      event.value = savedValue;\\n    } else if (didValidateRun) {\\n      source.obj._send({\\n        id: source.obj._id,\\n        siblings: source.obj._siblings,\\n        value: \\\"\\\",\\n        formattedValue: null,\\n        selRange: [0, 0],\\n        focus: true\\n      });\\n    }\\n  }\\n  runActions(source, target, event, eventName) {\\n    event.source = source.wrapped;\\n    event.target = target.wrapped;\\n    event.name = eventName;\\n    event.targetName = target.obj.name;\\n    event.rc = true;\\n    return target.obj._runActions(event);\\n  }\\n  calculateNow() {\\n    if (!this._calculationOrder || this._isCalculating || !this._document.obj.calculate) {\\n      return;\\n    }\\n    this._isCalculating = true;\\n    const first = this._calculationOrder[0];\\n    const source = this._objects[first];\\n    globalThis.event = new Event({});\\n    try {\\n      this.runCalculate(source, globalThis.event);\\n    } catch (error) {\\n      this._isCalculating = false;\\n      throw error;\\n    }\\n    this._isCalculating = false;\\n  }\\n  runCalculate(source, event) {\\n    if (!this._calculationOrder || !this._document.obj.calculate) {\\n      return;\\n    }\\n    for (const targetId of this._calculationOrder) {\\n      if (!(targetId in this._objects)) {\\n        continue;\\n      }\\n      if (!this._document.obj.calculate) {\\n        break;\\n      }\\n      event.value = null;\\n      const target = this._objects[targetId];\\n      let savedValue = target.obj._getValue();\\n      this.runActions(source, target, event, \\\"Calculate\\\");\\n      if (!event.rc) {\\n        continue;\\n      }\\n      if (event.value !== null) {\\n        target.obj.value = event.value;\\n      } else {\\n        event.value = target.obj._getValue();\\n      }\\n      this.runActions(target, target, event, \\\"Validate\\\");\\n      if (!event.rc) {\\n        if (target.obj._getValue() !== savedValue) {\\n          target.wrapped.value = savedValue;\\n        }\\n        continue;\\n      }\\n      if (event.value === null) {\\n        event.value = target.obj._getValue();\\n      }\\n      savedValue = target.obj._getValue();\\n      let formattedValue = null;\\n      if (this.runActions(target, target, event, \\\"Format\\\")) {\\n        formattedValue = event.value?.toString?.();\\n      }\\n      target.obj._send({\\n        id: target.obj._id,\\n        siblings: target.obj._siblings,\\n        value: savedValue,\\n        formattedValue\\n      });\\n    }\\n  }\\n}\\n\\n;// CONCATENATED MODULE: ./src/scripting_api/fullscreen.js\\n\\n\\nclass FullScreen extends PDFObject {\\n  constructor(data) {\\n    super(data);\\n    this._backgroundColor = [];\\n    this._clickAdvances = true;\\n    this._cursor = Cursor.hidden;\\n    this._defaultTransition = \\\"\\\";\\n    this._escapeExits = true;\\n    this._isFullScreen = true;\\n    this._loop = false;\\n    this._timeDelay = 3600;\\n    this._usePageTiming = false;\\n    this._useTimer = false;\\n  }\\n  get backgroundColor() {\\n    return this._backgroundColor;\\n  }\\n  set backgroundColor(_) {}\\n  get clickAdvances() {\\n    return this._clickAdvances;\\n  }\\n  set clickAdvances(_) {}\\n  get cursor() {\\n    return this._cursor;\\n  }\\n  set cursor(_) {}\\n  get defaultTransition() {\\n    return this._defaultTransition;\\n  }\\n  set defaultTransition(_) {}\\n  get escapeExits() {\\n    return this._escapeExits;\\n  }\\n  set escapeExits(_) {}\\n  get isFullScreen() {\\n    return this._isFullScreen;\\n  }\\n  set isFullScreen(_) {}\\n  get loop() {\\n    return this._loop;\\n  }\\n  set loop(_) {}\\n  get timeDelay() {\\n    return this._timeDelay;\\n  }\\n  set timeDelay(_) {}\\n  get transitions() {\\n    return [\\\"Replace\\\", \\\"WipeRight\\\", \\\"WipeLeft\\\", \\\"WipeDown\\\", \\\"WipeUp\\\", \\\"SplitHorizontalIn\\\", \\\"SplitHorizontalOut\\\", \\\"SplitVerticalIn\\\", \\\"SplitVerticalOut\\\", \\\"BlindsHorizontal\\\", \\\"BlindsVertical\\\", \\\"BoxIn\\\", \\\"BoxOut\\\", \\\"GlitterRight\\\", \\\"GlitterDown\\\", \\\"GlitterRightDown\\\", \\\"Dissolve\\\", \\\"Random\\\"];\\n  }\\n  set transitions(_) {\\n    throw new Error(\\\"fullscreen.transitions is read-only\\\");\\n  }\\n  get usePageTiming() {\\n    return this._usePageTiming;\\n  }\\n  set usePageTiming(_) {}\\n  get useTimer() {\\n    return this._useTimer;\\n  }\\n  set useTimer(_) {}\\n}\\n\\n;// CONCATENATED MODULE: ./src/scripting_api/thermometer.js\\n\\nclass Thermometer extends PDFObject {\\n  constructor(data) {\\n    super(data);\\n    this._cancelled = false;\\n    this._duration = 100;\\n    this._text = \\\"\\\";\\n    this._value = 0;\\n  }\\n  get cancelled() {\\n    return this._cancelled;\\n  }\\n  set cancelled(_) {\\n    throw new Error(\\\"thermometer.cancelled is read-only\\\");\\n  }\\n  get duration() {\\n    return this._duration;\\n  }\\n  set duration(val) {\\n    this._duration = val;\\n  }\\n  get text() {\\n    return this._text;\\n  }\\n  set text(val) {\\n    this._text = val;\\n  }\\n  get value() {\\n    return this._value;\\n  }\\n  set value(val) {\\n    this._value = val;\\n  }\\n  begin() {}\\n  end() {}\\n}\\n\\n;// CONCATENATED MODULE: ./src/scripting_api/app.js\\n\\n\\n\\n\\n\\n\\nclass App extends PDFObject {\\n  constructor(data) {\\n    super(data);\\n    this._constants = null;\\n    this._focusRect = true;\\n    this._fs = null;\\n    this._language = App._getLanguage(data.language);\\n    this._openInPlace = false;\\n    this._platform = App._getPlatform(data.platform);\\n    this._runtimeHighlight = false;\\n    this._runtimeHighlightColor = [\\\"T\\\"];\\n    this._thermometer = null;\\n    this._toolbar = false;\\n    this._document = data._document;\\n    this._proxyHandler = data.proxyHandler;\\n    this._objects = Object.create(null);\\n    this._eventDispatcher = new EventDispatcher(this._document, data.calculationOrder, this._objects, data.externalCall);\\n    this._timeoutIds = new WeakMap();\\n    if (typeof FinalizationRegistry !== \\\"undefined\\\") {\\n      this._timeoutIdsRegistry = new FinalizationRegistry(this._cleanTimeout.bind(this));\\n    } else {\\n      this._timeoutIdsRegistry = null;\\n    }\\n    this._timeoutCallbackIds = new Map();\\n    this._timeoutCallbackId = USERACTIVATION_CALLBACKID + 1;\\n    this._globalEval = data.globalEval;\\n    this._externalCall = data.externalCall;\\n  }\\n  _dispatchEvent(pdfEvent) {\\n    this._eventDispatcher.dispatch(pdfEvent);\\n  }\\n  _registerTimeoutCallback(cExpr) {\\n    const id = this._timeoutCallbackId++;\\n    this._timeoutCallbackIds.set(id, cExpr);\\n    return id;\\n  }\\n  _unregisterTimeoutCallback(id) {\\n    this._timeoutCallbackIds.delete(id);\\n  }\\n  _evalCallback({\\n    callbackId,\\n    interval\\n  }) {\\n    if (callbackId === USERACTIVATION_CALLBACKID) {\\n      this._document.obj._userActivation = false;\\n      return;\\n    }\\n    const expr = this._timeoutCallbackIds.get(callbackId);\\n    if (!interval) {\\n      this._unregisterTimeoutCallback(callbackId);\\n    }\\n    if (expr) {\\n      this._globalEval(expr);\\n    }\\n  }\\n  _registerTimeout(callbackId, interval) {\\n    const timeout = Object.create(null);\\n    const id = {\\n      callbackId,\\n      interval\\n    };\\n    this._timeoutIds.set(timeout, id);\\n    this._timeoutIdsRegistry?.register(timeout, id);\\n    return timeout;\\n  }\\n  _unregisterTimeout(timeout) {\\n    this._timeoutIdsRegistry?.unregister(timeout);\\n    const data = this._timeoutIds.get(timeout);\\n    if (!data) {\\n      return;\\n    }\\n    this._timeoutIds.delete(timeout);\\n    this._cleanTimeout(data);\\n  }\\n  _cleanTimeout({\\n    callbackId,\\n    interval\\n  }) {\\n    this._unregisterTimeoutCallback(callbackId);\\n    if (interval) {\\n      this._externalCall(\\\"clearInterval\\\", [callbackId]);\\n    } else {\\n      this._externalCall(\\\"clearTimeout\\\", [callbackId]);\\n    }\\n  }\\n  static _getPlatform(platform) {\\n    if (typeof platform === \\\"string\\\") {\\n      platform = platform.toLowerCase();\\n      if (platform.includes(\\\"win\\\")) {\\n        return \\\"WIN\\\";\\n      } else if (platform.includes(\\\"mac\\\")) {\\n        return \\\"MAC\\\";\\n      }\\n    }\\n    return \\\"UNIX\\\";\\n  }\\n  static _getLanguage(language) {\\n    const [main, sub] = language.toLowerCase().split(/[-_]/);\\n    switch (main) {\\n      case \\\"zh\\\":\\n        if (sub === \\\"cn\\\" || sub === \\\"sg\\\") {\\n          return \\\"CHS\\\";\\n        }\\n        return \\\"CHT\\\";\\n      case \\\"da\\\":\\n        return \\\"DAN\\\";\\n      case \\\"de\\\":\\n        return \\\"DEU\\\";\\n      case \\\"es\\\":\\n        return \\\"ESP\\\";\\n      case \\\"fr\\\":\\n        return \\\"FRA\\\";\\n      case \\\"it\\\":\\n        return \\\"ITA\\\";\\n      case \\\"ko\\\":\\n        return \\\"KOR\\\";\\n      case \\\"ja\\\":\\n        return \\\"JPN\\\";\\n      case \\\"nl\\\":\\n        return \\\"NLD\\\";\\n      case \\\"no\\\":\\n        return \\\"NOR\\\";\\n      case \\\"pt\\\":\\n        if (sub === \\\"br\\\") {\\n          return \\\"PTB\\\";\\n        }\\n        return \\\"ENU\\\";\\n      case \\\"fi\\\":\\n        return \\\"SUO\\\";\\n      case \\\"SV\\\":\\n        return \\\"SVE\\\";\\n      default:\\n        return \\\"ENU\\\";\\n    }\\n  }\\n  get activeDocs() {\\n    return [this._document.wrapped];\\n  }\\n  set activeDocs(_) {\\n    throw new Error(\\\"app.activeDocs is read-only\\\");\\n  }\\n  get calculate() {\\n    return this._document.obj.calculate;\\n  }\\n  set calculate(calculate) {\\n    this._document.obj.calculate = calculate;\\n  }\\n  get constants() {\\n    if (!this._constants) {\\n      this._constants = Object.freeze({\\n        align: Object.freeze({\\n          left: 0,\\n          center: 1,\\n          right: 2,\\n          top: 3,\\n          bottom: 4\\n        })\\n      });\\n    }\\n    return this._constants;\\n  }\\n  set constants(_) {\\n    throw new Error(\\\"app.constants is read-only\\\");\\n  }\\n  get focusRect() {\\n    return this._focusRect;\\n  }\\n  set focusRect(val) {\\n    this._focusRect = val;\\n  }\\n  get formsVersion() {\\n    return FORMS_VERSION;\\n  }\\n  set formsVersion(_) {\\n    throw new Error(\\\"app.formsVersion is read-only\\\");\\n  }\\n  get fromPDFConverters() {\\n    return [];\\n  }\\n  set fromPDFConverters(_) {\\n    throw new Error(\\\"app.fromPDFConverters is read-only\\\");\\n  }\\n  get fs() {\\n    if (this._fs === null) {\\n      this._fs = new Proxy(new FullScreen({\\n        send: this._send\\n      }), this._proxyHandler);\\n    }\\n    return this._fs;\\n  }\\n  set fs(_) {\\n    throw new Error(\\\"app.fs is read-only\\\");\\n  }\\n  get language() {\\n    return this._language;\\n  }\\n  set language(_) {\\n    throw new Error(\\\"app.language is read-only\\\");\\n  }\\n  get media() {\\n    return undefined;\\n  }\\n  set media(_) {\\n    throw new Error(\\\"app.media is read-only\\\");\\n  }\\n  get monitors() {\\n    return [];\\n  }\\n  set monitors(_) {\\n    throw new Error(\\\"app.monitors is read-only\\\");\\n  }\\n  get numPlugins() {\\n    return 0;\\n  }\\n  set numPlugins(_) {\\n    throw new Error(\\\"app.numPlugins is read-only\\\");\\n  }\\n  get openInPlace() {\\n    return this._openInPlace;\\n  }\\n  set openInPlace(val) {\\n    this._openInPlace = val;\\n  }\\n  get platform() {\\n    return this._platform;\\n  }\\n  set platform(_) {\\n    throw new Error(\\\"app.platform is read-only\\\");\\n  }\\n  get plugins() {\\n    return [];\\n  }\\n  set plugins(_) {\\n    throw new Error(\\\"app.plugins is read-only\\\");\\n  }\\n  get printColorProfiles() {\\n    return [];\\n  }\\n  set printColorProfiles(_) {\\n    throw new Error(\\\"app.printColorProfiles is read-only\\\");\\n  }\\n  get printerNames() {\\n    return [];\\n  }\\n  set printerNames(_) {\\n    throw new Error(\\\"app.printerNames is read-only\\\");\\n  }\\n  get runtimeHighlight() {\\n    return this._runtimeHighlight;\\n  }\\n  set runtimeHighlight(val) {\\n    this._runtimeHighlight = val;\\n  }\\n  get runtimeHighlightColor() {\\n    return this._runtimeHighlightColor;\\n  }\\n  set runtimeHighlightColor(val) {\\n    if (Color._isValidColor(val)) {\\n      this._runtimeHighlightColor = val;\\n    }\\n  }\\n  get thermometer() {\\n    if (this._thermometer === null) {\\n      this._thermometer = new Proxy(new Thermometer({\\n        send: this._send\\n      }), this._proxyHandler);\\n    }\\n    return this._thermometer;\\n  }\\n  set thermometer(_) {\\n    throw new Error(\\\"app.thermometer is read-only\\\");\\n  }\\n  get toolbar() {\\n    return this._toolbar;\\n  }\\n  set toolbar(val) {\\n    this._toolbar = val;\\n  }\\n  get toolbarHorizontal() {\\n    return this.toolbar;\\n  }\\n  set toolbarHorizontal(value) {\\n    this.toolbar = value;\\n  }\\n  get toolbarVertical() {\\n    return this.toolbar;\\n  }\\n  set toolbarVertical(value) {\\n    this.toolbar = value;\\n  }\\n  get viewerType() {\\n    return VIEWER_TYPE;\\n  }\\n  set viewerType(_) {\\n    throw new Error(\\\"app.viewerType is read-only\\\");\\n  }\\n  get viewerVariation() {\\n    return VIEWER_VARIATION;\\n  }\\n  set viewerVariation(_) {\\n    throw new Error(\\\"app.viewerVariation is read-only\\\");\\n  }\\n  get viewerVersion() {\\n    return VIEWER_VERSION;\\n  }\\n  set viewerVersion(_) {\\n    throw new Error(\\\"app.viewerVersion is read-only\\\");\\n  }\\n  addMenuItem() {}\\n  addSubMenu() {}\\n  addToolButton() {}\\n  alert(cMsg, nIcon = 0, nType = 0, cTitle = \\\"PDF.js\\\", oDoc = null, oCheckbox = null) {\\n    if (!this._document.obj._userActivation) {\\n      return 0;\\n    }\\n    this._document.obj._userActivation = false;\\n    if (cMsg && typeof cMsg === \\\"object\\\") {\\n      nType = cMsg.nType;\\n      cMsg = cMsg.cMsg;\\n    }\\n    cMsg = (cMsg || \\\"\\\").toString();\\n    nType = typeof nType !== \\\"number\\\" || isNaN(nType) || nType < 0 || nType > 3 ? 0 : nType;\\n    if (nType >= 2) {\\n      return this._externalCall(\\\"confirm\\\", [cMsg]) ? 4 : 3;\\n    }\\n    this._externalCall(\\\"alert\\\", [cMsg]);\\n    return 1;\\n  }\\n  beep() {}\\n  beginPriv() {}\\n  browseForDoc() {}\\n  clearInterval(oInterval) {\\n    this._unregisterTimeout(oInterval);\\n  }\\n  clearTimeOut(oTime) {\\n    this._unregisterTimeout(oTime);\\n  }\\n  endPriv() {}\\n  execDialog() {}\\n  execMenuItem(item) {\\n    if (!this._document.obj._userActivation) {\\n      return;\\n    }\\n    this._document.obj._userActivation = false;\\n    switch (item) {\\n      case \\\"SaveAs\\\":\\n        if (this._document.obj._disableSaving) {\\n          return;\\n        }\\n        this._send({\\n          command: item\\n        });\\n        break;\\n      case \\\"FirstPage\\\":\\n      case \\\"LastPage\\\":\\n      case \\\"NextPage\\\":\\n      case \\\"PrevPage\\\":\\n      case \\\"ZoomViewIn\\\":\\n      case \\\"ZoomViewOut\\\":\\n        this._send({\\n          command: item\\n        });\\n        break;\\n      case \\\"FitPage\\\":\\n        this._send({\\n          command: \\\"zoom\\\",\\n          value: \\\"page-fit\\\"\\n        });\\n        break;\\n      case \\\"Print\\\":\\n        if (this._document.obj._disablePrinting) {\\n          return;\\n        }\\n        this._send({\\n          command: \\\"print\\\"\\n        });\\n        break;\\n    }\\n  }\\n  getNthPlugInName() {}\\n  getPath() {}\\n  goBack() {}\\n  goForward() {}\\n  hideMenuItem() {}\\n  hideToolbarButton() {}\\n  launchURL() {}\\n  listMenuItems() {}\\n  listToolbarButtons() {}\\n  loadPolicyFile() {}\\n  mailGetAddrs() {}\\n  mailMsg() {}\\n  newDoc() {}\\n  newCollection() {}\\n  newFDF() {}\\n  openDoc() {}\\n  openFDF() {}\\n  popUpMenu() {}\\n  popUpMenuEx() {}\\n  removeToolButton() {}\\n  response(cQuestion, cTitle = \\\"\\\", cDefault = \\\"\\\", bPassword = \\\"\\\", cLabel = \\\"\\\") {\\n    if (cQuestion && typeof cQuestion === \\\"object\\\") {\\n      cDefault = cQuestion.cDefault;\\n      cQuestion = cQuestion.cQuestion;\\n    }\\n    cQuestion = (cQuestion || \\\"\\\").toString();\\n    cDefault = (cDefault || \\\"\\\").toString();\\n    return this._externalCall(\\\"prompt\\\", [cQuestion, cDefault || \\\"\\\"]);\\n  }\\n  setInterval(cExpr, nMilliseconds = 0) {\\n    if (cExpr && typeof cExpr === \\\"object\\\") {\\n      nMilliseconds = cExpr.nMilliseconds || 0;\\n      cExpr = cExpr.cExpr;\\n    }\\n    if (typeof cExpr !== \\\"string\\\") {\\n      throw new TypeError(\\\"First argument of app.setInterval must be a string\\\");\\n    }\\n    if (typeof nMilliseconds !== \\\"number\\\") {\\n      throw new TypeError(\\\"Second argument of app.setInterval must be a number\\\");\\n    }\\n    const callbackId = this._registerTimeoutCallback(cExpr);\\n    this._externalCall(\\\"setInterval\\\", [callbackId, nMilliseconds]);\\n    return this._registerTimeout(callbackId, true);\\n  }\\n  setTimeOut(cExpr, nMilliseconds = 0) {\\n    if (cExpr && typeof cExpr === \\\"object\\\") {\\n      nMilliseconds = cExpr.nMilliseconds || 0;\\n      cExpr = cExpr.cExpr;\\n    }\\n    if (typeof cExpr !== \\\"string\\\") {\\n      throw new TypeError(\\\"First argument of app.setTimeOut must be a string\\\");\\n    }\\n    if (typeof nMilliseconds !== \\\"number\\\") {\\n      throw new TypeError(\\\"Second argument of app.setTimeOut must be a number\\\");\\n    }\\n    const callbackId = this._registerTimeoutCallback(cExpr);\\n    this._externalCall(\\\"setTimeout\\\", [callbackId, nMilliseconds]);\\n    return this._registerTimeout(callbackId, false);\\n  }\\n  trustedFunction() {}\\n  trustPropagatorFunction() {}\\n}\\n\\n;// CONCATENATED MODULE: ./src/scripting_api/console.js\\n\\nclass Console extends PDFObject {\\n  clear() {\\n    this._send({\\n      id: \\\"clear\\\"\\n    });\\n  }\\n  hide() {}\\n  println(msg) {\\n    if (typeof msg === \\\"string\\\") {\\n      this._send({\\n        command: \\\"println\\\",\\n        value: \\\"PDF.js Console:: \\\" + msg\\n      });\\n    }\\n  }\\n  show() {}\\n}\\n\\n;// CONCATENATED MODULE: ./src/scripting_api/print_params.js\\nclass PrintParams {\\n  constructor(data) {\\n    this.binaryOk = true;\\n    this.bitmapDPI = 150;\\n    this.booklet = {\\n      binding: 0,\\n      duplexMode: 0,\\n      subsetFrom: 0,\\n      subsetTo: -1\\n    };\\n    this.colorOverride = 0;\\n    this.colorProfile = \\\"\\\";\\n    this.constants = Object.freeze({\\n      bookletBindings: Object.freeze({\\n        Left: 0,\\n        Right: 1,\\n        LeftTall: 2,\\n        RightTall: 3\\n      }),\\n      bookletDuplexMode: Object.freeze({\\n        BothSides: 0,\\n        FrontSideOnly: 1,\\n        BasicSideOnly: 2\\n      }),\\n      colorOverrides: Object.freeze({\\n        auto: 0,\\n        gray: 1,\\n        mono: 2\\n      }),\\n      fontPolicies: Object.freeze({\\n        everyPage: 0,\\n        jobStart: 1,\\n        pageRange: 2\\n      }),\\n      handling: Object.freeze({\\n        none: 0,\\n        fit: 1,\\n        shrink: 2,\\n        tileAll: 3,\\n        tileLarge: 4,\\n        nUp: 5,\\n        booklet: 6\\n      }),\\n      interactionLevel: Object.freeze({\\n        automatic: 0,\\n        full: 1,\\n        silent: 2\\n      }),\\n      nUpPageOrders: Object.freeze({\\n        Horizontal: 0,\\n        HorizontalReversed: 1,\\n        Vertical: 2\\n      }),\\n      printContents: Object.freeze({\\n        doc: 0,\\n        docAndComments: 1,\\n        formFieldsOnly: 2\\n      }),\\n      flagValues: Object.freeze({\\n        applyOverPrint: 1,\\n        applySoftProofSettings: 1 << 1,\\n        applyWorkingColorSpaces: 1 << 2,\\n        emitHalftones: 1 << 3,\\n        emitPostScriptXObjects: 1 << 4,\\n        emitFormsAsPSForms: 1 << 5,\\n        maxJP2KRes: 1 << 6,\\n        setPageSize: 1 << 7,\\n        suppressBG: 1 << 8,\\n        suppressCenter: 1 << 9,\\n        suppressCJKFontSubst: 1 << 10,\\n        suppressCropClip: 1 << 1,\\n        suppressRotate: 1 << 12,\\n        suppressTransfer: 1 << 13,\\n        suppressUCR: 1 << 14,\\n        useTrapAnnots: 1 << 15,\\n        usePrintersMarks: 1 << 16\\n      }),\\n      rasterFlagValues: Object.freeze({\\n        textToOutline: 1,\\n        strokesToOutline: 1 << 1,\\n        allowComplexClip: 1 << 2,\\n        preserveOverprint: 1 << 3\\n      }),\\n      subsets: Object.freeze({\\n        all: 0,\\n        even: 1,\\n        odd: 2\\n      }),\\n      tileMarks: Object.freeze({\\n        none: 0,\\n        west: 1,\\n        east: 2\\n      }),\\n      usages: Object.freeze({\\n        auto: 0,\\n        use: 1,\\n        noUse: 2\\n      })\\n    });\\n    this.downloadFarEastFonts = false;\\n    this.fileName = \\\"\\\";\\n    this.firstPage = 0;\\n    this.flags = 0;\\n    this.fontPolicy = 0;\\n    this.gradientDPI = 150;\\n    this.interactive = 1;\\n    this.lastPage = data.lastPage;\\n    this.npUpAutoRotate = false;\\n    this.npUpNumPagesH = 2;\\n    this.npUpNumPagesV = 2;\\n    this.npUpPageBorder = false;\\n    this.npUpPageOrder = 0;\\n    this.pageHandling = 0;\\n    this.pageSubset = 0;\\n    this.printAsImage = false;\\n    this.printContent = 0;\\n    this.printerName = \\\"\\\";\\n    this.psLevel = 0;\\n    this.rasterFlags = 0;\\n    this.reversePages = false;\\n    this.tileLabel = false;\\n    this.tileMark = 0;\\n    this.tileOverlap = 0;\\n    this.tileScale = 1.0;\\n    this.transparencyLevel = 75;\\n    this.usePrinterCRD = 0;\\n    this.useT1Conversion = 0;\\n  }\\n}\\n\\n;// CONCATENATED MODULE: ./src/scripting_api/doc.js\\n\\n\\n\\n\\n\\nconst DOC_EXTERNAL = false;\\nclass InfoProxyHandler {\\n  static get(obj, prop) {\\n    return obj[prop.toLowerCase()];\\n  }\\n  static set(obj, prop, value) {\\n    throw new Error(`doc.info.${prop} is read-only`);\\n  }\\n}\\nclass Doc extends PDFObject {\\n  constructor(data) {\\n    super(data);\\n    this._expandos = globalThis;\\n    this._baseURL = data.baseURL || \\\"\\\";\\n    this._calculate = true;\\n    this._delay = false;\\n    this._dirty = false;\\n    this._disclosed = false;\\n    this._media = undefined;\\n    this._metadata = data.metadata || \\\"\\\";\\n    this._noautocomplete = undefined;\\n    this._nocache = undefined;\\n    this._spellDictionaryOrder = [];\\n    this._spellLanguageOrder = [];\\n    this._printParams = null;\\n    this._fields = new Map();\\n    this._fieldNames = [];\\n    this._event = null;\\n    this._author = data.Author || \\\"\\\";\\n    this._creator = data.Creator || \\\"\\\";\\n    this._creationDate = this._getDate(data.CreationDate) || null;\\n    this._docID = data.docID || [\\\"\\\", \\\"\\\"];\\n    this._documentFileName = data.filename || \\\"\\\";\\n    this._filesize = data.filesize || 0;\\n    this._keywords = data.Keywords || \\\"\\\";\\n    this._layout = data.layout || \\\"\\\";\\n    this._modDate = this._getDate(data.ModDate) || null;\\n    this._numFields = 0;\\n    this._numPages = data.numPages || 1;\\n    this._pageNum = data.pageNum || 0;\\n    this._producer = data.Producer || \\\"\\\";\\n    this._securityHandler = data.EncryptFilterName || null;\\n    this._subject = data.Subject || \\\"\\\";\\n    this._title = data.Title || \\\"\\\";\\n    this._URL = data.URL || \\\"\\\";\\n    this._info = new Proxy({\\n      title: this._title,\\n      author: this._author,\\n      authors: data.authors || [this._author],\\n      subject: this._subject,\\n      keywords: this._keywords,\\n      creator: this._creator,\\n      producer: this._producer,\\n      creationdate: this._creationDate,\\n      moddate: this._modDate,\\n      trapped: data.Trapped || \\\"Unknown\\\"\\n    }, InfoProxyHandler);\\n    this._zoomType = ZoomType.none;\\n    this._zoom = data.zoom || 100;\\n    this._actions = createActionsMap(data.actions);\\n    this._globalEval = data.globalEval;\\n    this._pageActions = new Map();\\n    this._userActivation = false;\\n    this._disablePrinting = false;\\n    this._disableSaving = false;\\n  }\\n  _initActions() {\\n    const dontRun = new Set([\\\"WillClose\\\", \\\"WillSave\\\", \\\"DidSave\\\", \\\"WillPrint\\\", \\\"DidPrint\\\", \\\"OpenAction\\\"]);\\n    this._disableSaving = true;\\n    for (const actionName of this._actions.keys()) {\\n      if (!dontRun.has(actionName)) {\\n        this._runActions(actionName);\\n      }\\n    }\\n    this._runActions(\\\"OpenAction\\\");\\n    this._disableSaving = false;\\n  }\\n  _dispatchDocEvent(name) {\\n    switch (name) {\\n      case \\\"Open\\\":\\n        this._disableSaving = true;\\n        this._runActions(\\\"OpenAction\\\");\\n        this._disableSaving = false;\\n        break;\\n      case \\\"WillPrint\\\":\\n        this._disablePrinting = true;\\n        try {\\n          this._runActions(name);\\n        } catch (error) {\\n          this._send(serializeError(error));\\n        }\\n        this._send({\\n          command: \\\"WillPrintFinished\\\"\\n        });\\n        this._disablePrinting = false;\\n        break;\\n      case \\\"WillSave\\\":\\n        this._disableSaving = true;\\n        this._runActions(name);\\n        this._disableSaving = false;\\n        break;\\n      default:\\n        this._runActions(name);\\n    }\\n  }\\n  _dispatchPageEvent(name, actions, pageNumber) {\\n    if (name === \\\"PageOpen\\\") {\\n      if (!this._pageActions.has(pageNumber)) {\\n        this._pageActions.set(pageNumber, createActionsMap(actions));\\n      }\\n      this._pageNum = pageNumber - 1;\\n    }\\n    actions = this._pageActions.get(pageNumber)?.get(name);\\n    if (actions) {\\n      for (const action of actions) {\\n        this._globalEval(action);\\n      }\\n    }\\n  }\\n  _runActions(name) {\\n    const actions = this._actions.get(name);\\n    if (actions) {\\n      for (const action of actions) {\\n        this._globalEval(action);\\n      }\\n    }\\n  }\\n  _addField(name, field) {\\n    this._fields.set(name, field);\\n    this._fieldNames.push(name);\\n    this._numFields++;\\n  }\\n  _getDate(date) {\\n    if (!date || date.length < 15 || !date.startsWith(\\\"D:\\\")) {\\n      return date;\\n    }\\n    date = date.substring(2);\\n    const year = date.substring(0, 4);\\n    const month = date.substring(4, 6);\\n    const day = date.substring(6, 8);\\n    const hour = date.substring(8, 10);\\n    const minute = date.substring(10, 12);\\n    const o = date.charAt(12);\\n    let second, offsetPos;\\n    if (o === \\\"Z\\\" || o === \\\"+\\\" || o === \\\"-\\\") {\\n      second = \\\"00\\\";\\n      offsetPos = 12;\\n    } else {\\n      second = date.substring(12, 14);\\n      offsetPos = 14;\\n    }\\n    const offset = date.substring(offsetPos).replaceAll(\\\"'\\\", \\\"\\\");\\n    return new Date(`${year}-${month}-${day}T${hour}:${minute}:${second}${offset}`);\\n  }\\n  get author() {\\n    return this._author;\\n  }\\n  set author(_) {\\n    throw new Error(\\\"doc.author is read-only\\\");\\n  }\\n  get baseURL() {\\n    return this._baseURL;\\n  }\\n  set baseURL(baseURL) {\\n    this._baseURL = baseURL;\\n  }\\n  get bookmarkRoot() {\\n    return undefined;\\n  }\\n  set bookmarkRoot(_) {\\n    throw new Error(\\\"doc.bookmarkRoot is read-only\\\");\\n  }\\n  get calculate() {\\n    return this._calculate;\\n  }\\n  set calculate(calculate) {\\n    this._calculate = calculate;\\n  }\\n  get creator() {\\n    return this._creator;\\n  }\\n  set creator(_) {\\n    throw new Error(\\\"doc.creator is read-only\\\");\\n  }\\n  get dataObjects() {\\n    return [];\\n  }\\n  set dataObjects(_) {\\n    throw new Error(\\\"doc.dataObjects is read-only\\\");\\n  }\\n  get delay() {\\n    return this._delay;\\n  }\\n  set delay(delay) {\\n    this._delay = delay;\\n  }\\n  get dirty() {\\n    return this._dirty;\\n  }\\n  set dirty(dirty) {\\n    this._dirty = dirty;\\n  }\\n  get disclosed() {\\n    return this._disclosed;\\n  }\\n  set disclosed(disclosed) {\\n    this._disclosed = disclosed;\\n  }\\n  get docID() {\\n    return this._docID;\\n  }\\n  set docID(_) {\\n    throw new Error(\\\"doc.docID is read-only\\\");\\n  }\\n  get documentFileName() {\\n    return this._documentFileName;\\n  }\\n  set documentFileName(_) {\\n    throw new Error(\\\"doc.documentFileName is read-only\\\");\\n  }\\n  get dynamicXFAForm() {\\n    return false;\\n  }\\n  set dynamicXFAForm(_) {\\n    throw new Error(\\\"doc.dynamicXFAForm is read-only\\\");\\n  }\\n  get external() {\\n    return DOC_EXTERNAL;\\n  }\\n  set external(_) {\\n    throw new Error(\\\"doc.external is read-only\\\");\\n  }\\n  get filesize() {\\n    return this._filesize;\\n  }\\n  set filesize(_) {\\n    throw new Error(\\\"doc.filesize is read-only\\\");\\n  }\\n  get hidden() {\\n    return false;\\n  }\\n  set hidden(_) {\\n    throw new Error(\\\"doc.hidden is read-only\\\");\\n  }\\n  get hostContainer() {\\n    return undefined;\\n  }\\n  set hostContainer(_) {\\n    throw new Error(\\\"doc.hostContainer is read-only\\\");\\n  }\\n  get icons() {\\n    return undefined;\\n  }\\n  set icons(_) {\\n    throw new Error(\\\"doc.icons is read-only\\\");\\n  }\\n  get info() {\\n    return this._info;\\n  }\\n  set info(_) {\\n    throw new Error(\\\"doc.info is read-only\\\");\\n  }\\n  get innerAppWindowRect() {\\n    return [0, 0, 0, 0];\\n  }\\n  set innerAppWindowRect(_) {\\n    throw new Error(\\\"doc.innerAppWindowRect is read-only\\\");\\n  }\\n  get innerDocWindowRect() {\\n    return [0, 0, 0, 0];\\n  }\\n  set innerDocWindowRect(_) {\\n    throw new Error(\\\"doc.innerDocWindowRect is read-only\\\");\\n  }\\n  get isModal() {\\n    return false;\\n  }\\n  set isModal(_) {\\n    throw new Error(\\\"doc.isModal is read-only\\\");\\n  }\\n  get keywords() {\\n    return this._keywords;\\n  }\\n  set keywords(_) {\\n    throw new Error(\\\"doc.keywords is read-only\\\");\\n  }\\n  get layout() {\\n    return this._layout;\\n  }\\n  set layout(value) {\\n    if (!this._userActivation) {\\n      return;\\n    }\\n    this._userActivation = false;\\n    if (typeof value !== \\\"string\\\") {\\n      return;\\n    }\\n    if (value !== \\\"SinglePage\\\" && value !== \\\"OneColumn\\\" && value !== \\\"TwoColumnLeft\\\" && value !== \\\"TwoPageLeft\\\" && value !== \\\"TwoColumnRight\\\" && value !== \\\"TwoPageRight\\\") {\\n      value = \\\"SinglePage\\\";\\n    }\\n    this._send({\\n      command: \\\"layout\\\",\\n      value\\n    });\\n    this._layout = value;\\n  }\\n  get media() {\\n    return this._media;\\n  }\\n  set media(media) {\\n    this._media = media;\\n  }\\n  get metadata() {\\n    return this._metadata;\\n  }\\n  set metadata(metadata) {\\n    this._metadata = metadata;\\n  }\\n  get modDate() {\\n    return this._modDate;\\n  }\\n  set modDate(_) {\\n    throw new Error(\\\"doc.modDate is read-only\\\");\\n  }\\n  get mouseX() {\\n    return 0;\\n  }\\n  set mouseX(_) {\\n    throw new Error(\\\"doc.mouseX is read-only\\\");\\n  }\\n  get mouseY() {\\n    return 0;\\n  }\\n  set mouseY(_) {\\n    throw new Error(\\\"doc.mouseY is read-only\\\");\\n  }\\n  get noautocomplete() {\\n    return this._noautocomplete;\\n  }\\n  set noautocomplete(noautocomplete) {\\n    this._noautocomplete = noautocomplete;\\n  }\\n  get nocache() {\\n    return this._nocache;\\n  }\\n  set nocache(nocache) {\\n    this._nocache = nocache;\\n  }\\n  get numFields() {\\n    return this._numFields;\\n  }\\n  set numFields(_) {\\n    throw new Error(\\\"doc.numFields is read-only\\\");\\n  }\\n  get numPages() {\\n    return this._numPages;\\n  }\\n  set numPages(_) {\\n    throw new Error(\\\"doc.numPages is read-only\\\");\\n  }\\n  get numTemplates() {\\n    return 0;\\n  }\\n  set numTemplates(_) {\\n    throw new Error(\\\"doc.numTemplates is read-only\\\");\\n  }\\n  get outerAppWindowRect() {\\n    return [0, 0, 0, 0];\\n  }\\n  set outerAppWindowRect(_) {\\n    throw new Error(\\\"doc.outerAppWindowRect is read-only\\\");\\n  }\\n  get outerDocWindowRect() {\\n    return [0, 0, 0, 0];\\n  }\\n  set outerDocWindowRect(_) {\\n    throw new Error(\\\"doc.outerDocWindowRect is read-only\\\");\\n  }\\n  get pageNum() {\\n    return this._pageNum;\\n  }\\n  set pageNum(value) {\\n    if (!this._userActivation) {\\n      return;\\n    }\\n    this._userActivation = false;\\n    if (typeof value !== \\\"number\\\" || value < 0 || value >= this._numPages) {\\n      return;\\n    }\\n    this._send({\\n      command: \\\"page-num\\\",\\n      value\\n    });\\n    this._pageNum = value;\\n  }\\n  get pageWindowRect() {\\n    return [0, 0, 0, 0];\\n  }\\n  set pageWindowRect(_) {\\n    throw new Error(\\\"doc.pageWindowRect is read-only\\\");\\n  }\\n  get path() {\\n    return \\\"\\\";\\n  }\\n  set path(_) {\\n    throw new Error(\\\"doc.path is read-only\\\");\\n  }\\n  get permStatusReady() {\\n    return true;\\n  }\\n  set permStatusReady(_) {\\n    throw new Error(\\\"doc.permStatusReady is read-only\\\");\\n  }\\n  get producer() {\\n    return this._producer;\\n  }\\n  set producer(_) {\\n    throw new Error(\\\"doc.producer is read-only\\\");\\n  }\\n  get requiresFullSave() {\\n    return false;\\n  }\\n  set requiresFullSave(_) {\\n    throw new Error(\\\"doc.requiresFullSave is read-only\\\");\\n  }\\n  get securityHandler() {\\n    return this._securityHandler;\\n  }\\n  set securityHandler(_) {\\n    throw new Error(\\\"doc.securityHandler is read-only\\\");\\n  }\\n  get selectedAnnots() {\\n    return [];\\n  }\\n  set selectedAnnots(_) {\\n    throw new Error(\\\"doc.selectedAnnots is read-only\\\");\\n  }\\n  get sounds() {\\n    return [];\\n  }\\n  set sounds(_) {\\n    throw new Error(\\\"doc.sounds is read-only\\\");\\n  }\\n  get spellDictionaryOrder() {\\n    return this._spellDictionaryOrder;\\n  }\\n  set spellDictionaryOrder(spellDictionaryOrder) {\\n    this._spellDictionaryOrder = spellDictionaryOrder;\\n  }\\n  get spellLanguageOrder() {\\n    return this._spellLanguageOrder;\\n  }\\n  set spellLanguageOrder(spellLanguageOrder) {\\n    this._spellLanguageOrder = spellLanguageOrder;\\n  }\\n  get subject() {\\n    return this._subject;\\n  }\\n  set subject(_) {\\n    throw new Error(\\\"doc.subject is read-only\\\");\\n  }\\n  get templates() {\\n    return [];\\n  }\\n  set templates(_) {\\n    throw new Error(\\\"doc.templates is read-only\\\");\\n  }\\n  get title() {\\n    return this._title;\\n  }\\n  set title(_) {\\n    throw new Error(\\\"doc.title is read-only\\\");\\n  }\\n  get URL() {\\n    return this._URL;\\n  }\\n  set URL(_) {\\n    throw new Error(\\\"doc.URL is read-only\\\");\\n  }\\n  get viewState() {\\n    return undefined;\\n  }\\n  set viewState(_) {\\n    throw new Error(\\\"doc.viewState is read-only\\\");\\n  }\\n  get xfa() {\\n    return this._xfa;\\n  }\\n  set xfa(_) {\\n    throw new Error(\\\"doc.xfa is read-only\\\");\\n  }\\n  get XFAForeground() {\\n    return false;\\n  }\\n  set XFAForeground(_) {\\n    throw new Error(\\\"doc.XFAForeground is read-only\\\");\\n  }\\n  get zoomType() {\\n    return this._zoomType;\\n  }\\n  set zoomType(type) {\\n    if (!this._userActivation) {\\n      return;\\n    }\\n    this._userActivation = false;\\n    if (typeof type !== \\\"string\\\") {\\n      return;\\n    }\\n    switch (type) {\\n      case ZoomType.none:\\n        this._send({\\n          command: \\\"zoom\\\",\\n          value: 1\\n        });\\n        break;\\n      case ZoomType.fitP:\\n        this._send({\\n          command: \\\"zoom\\\",\\n          value: \\\"page-fit\\\"\\n        });\\n        break;\\n      case ZoomType.fitW:\\n        this._send({\\n          command: \\\"zoom\\\",\\n          value: \\\"page-width\\\"\\n        });\\n        break;\\n      case ZoomType.fitH:\\n        this._send({\\n          command: \\\"zoom\\\",\\n          value: \\\"page-height\\\"\\n        });\\n        break;\\n      case ZoomType.fitV:\\n        this._send({\\n          command: \\\"zoom\\\",\\n          value: \\\"auto\\\"\\n        });\\n        break;\\n      case ZoomType.pref:\\n      case ZoomType.refW:\\n        break;\\n      default:\\n        return;\\n    }\\n    this._zoomType = type;\\n  }\\n  get zoom() {\\n    return this._zoom;\\n  }\\n  set zoom(value) {\\n    if (!this._userActivation) {\\n      return;\\n    }\\n    this._userActivation = false;\\n    if (typeof value !== \\\"number\\\" || value < 8.33 || value > 6400) {\\n      return;\\n    }\\n    this._send({\\n      command: \\\"zoom\\\",\\n      value: value / 100\\n    });\\n  }\\n  addAnnot() {}\\n  addField() {}\\n  addIcon() {}\\n  addLink() {}\\n  addRecipientListCryptFilter() {}\\n  addRequirement() {}\\n  addScript() {}\\n  addThumbnails() {}\\n  addWatermarkFromFile() {}\\n  addWatermarkFromText() {}\\n  addWeblinks() {}\\n  bringToFront() {}\\n  calculateNow() {\\n    this._eventDispatcher.calculateNow();\\n  }\\n  closeDoc() {}\\n  colorConvertPage() {}\\n  createDataObject() {}\\n  createTemplate() {}\\n  deletePages() {}\\n  deleteSound() {}\\n  embedDocAsDataObject() {}\\n  embedOutputIntent() {}\\n  encryptForRecipients() {}\\n  encryptUsingPolicy() {}\\n  exportAsFDF() {}\\n  exportAsFDFStr() {}\\n  exportAsText() {}\\n  exportAsXFDF() {}\\n  exportAsXFDFStr() {}\\n  exportDataObject() {}\\n  exportXFAData() {}\\n  extractPages() {}\\n  flattenPages() {}\\n  getAnnot() {}\\n  getAnnots() {}\\n  getAnnot3D() {}\\n  getAnnots3D() {}\\n  getColorConvertAction() {}\\n  getDataObject() {}\\n  getDataObjectContents() {}\\n  _getField(cName) {\\n    if (cName && typeof cName === \\\"object\\\") {\\n      cName = cName.cName;\\n    }\\n    if (typeof cName !== \\\"string\\\") {\\n      throw new TypeError(\\\"Invalid field name: must be a string\\\");\\n    }\\n    const searchedField = this._fields.get(cName);\\n    if (searchedField) {\\n      return searchedField;\\n    }\\n    const parts = cName.split(\\\"#\\\");\\n    let childIndex = NaN;\\n    if (parts.length === 2) {\\n      childIndex = Math.floor(parseFloat(parts[1]));\\n      cName = parts[0];\\n    }\\n    for (const [name, field] of this._fields.entries()) {\\n      if (name.endsWith(cName)) {\\n        if (!isNaN(childIndex)) {\\n          const children = this._getChildren(name);\\n          if (childIndex < 0 || childIndex >= children.length) {\\n            childIndex = 0;\\n          }\\n          if (childIndex < children.length) {\\n            this._fields.set(cName, children[childIndex]);\\n            return children[childIndex];\\n          }\\n        }\\n        this._fields.set(cName, field);\\n        return field;\\n      }\\n    }\\n    return null;\\n  }\\n  getField(cName) {\\n    const field = this._getField(cName);\\n    if (!field) {\\n      return null;\\n    }\\n    return field.wrapped;\\n  }\\n  _getChildren(fieldName) {\\n    const len = fieldName.length;\\n    const children = [];\\n    const pattern = /^\\\\.[^.]+$/;\\n    for (const [name, field] of this._fields.entries()) {\\n      if (name.startsWith(fieldName)) {\\n        const finalPart = name.slice(len);\\n        if (pattern.test(finalPart)) {\\n          children.push(field);\\n        }\\n      }\\n    }\\n    return children;\\n  }\\n  _getTerminalChildren(fieldName) {\\n    const children = [];\\n    const len = fieldName.length;\\n    for (const [name, field] of this._fields.entries()) {\\n      if (name.startsWith(fieldName)) {\\n        const finalPart = name.slice(len);\\n        if (field.obj._hasValue && (finalPart === \\\"\\\" || finalPart.startsWith(\\\".\\\"))) {\\n          children.push(field.wrapped);\\n        }\\n      }\\n    }\\n    return children;\\n  }\\n  getIcon() {}\\n  getLegalWarnings() {}\\n  getLinks() {}\\n  getNthFieldName(nIndex) {\\n    if (nIndex && typeof nIndex === \\\"object\\\") {\\n      nIndex = nIndex.nIndex;\\n    }\\n    if (typeof nIndex !== \\\"number\\\") {\\n      throw new TypeError(\\\"Invalid field index: must be a number\\\");\\n    }\\n    if (0 <= nIndex && nIndex < this.numFields) {\\n      return this._fieldNames[Math.trunc(nIndex)];\\n    }\\n    return null;\\n  }\\n  getNthTemplate() {\\n    return null;\\n  }\\n  getOCGs() {}\\n  getOCGOrder() {}\\n  getPageBox() {}\\n  getPageLabel() {}\\n  getPageNthWord() {}\\n  getPageNthWordQuads() {}\\n  getPageNumWords() {}\\n  getPageRotation() {}\\n  getPageTransition() {}\\n  getPrintParams() {\\n    return this._printParams ||= new PrintParams({\\n      lastPage: this._numPages - 1\\n    });\\n  }\\n  getSound() {}\\n  getTemplate() {}\\n  getURL() {}\\n  gotoNamedDest() {}\\n  importAnFDF() {}\\n  importAnXFDF() {}\\n  importDataObject() {}\\n  importIcon() {}\\n  importSound() {}\\n  importTextData() {}\\n  importXFAData() {}\\n  insertPages() {}\\n  mailDoc() {}\\n  mailForm() {}\\n  movePage() {}\\n  newPage() {}\\n  openDataObject() {}\\n  print(bUI = true, nStart = 0, nEnd = -1, bSilent = false, bShrinkToFit = false, bPrintAsImage = false, bReverse = false, bAnnotations = true, printParams = null) {\\n    if (this._disablePrinting || !this._userActivation) {\\n      return;\\n    }\\n    this._userActivation = false;\\n    if (bUI && typeof bUI === \\\"object\\\") {\\n      nStart = bUI.nStart;\\n      nEnd = bUI.nEnd;\\n      bSilent = bUI.bSilent;\\n      bShrinkToFit = bUI.bShrinkToFit;\\n      bPrintAsImage = bUI.bPrintAsImage;\\n      bReverse = bUI.bReverse;\\n      bAnnotations = bUI.bAnnotations;\\n      printParams = bUI.printParams;\\n      bUI = bUI.bUI;\\n    }\\n    if (printParams) {\\n      nStart = printParams.firstPage;\\n      nEnd = printParams.lastPage;\\n    }\\n    nStart = typeof nStart === \\\"number\\\" ? Math.max(0, Math.trunc(nStart)) : 0;\\n    nEnd = typeof nEnd === \\\"number\\\" ? Math.max(0, Math.trunc(nEnd)) : -1;\\n    this._send({\\n      command: \\\"print\\\",\\n      start: nStart,\\n      end: nEnd\\n    });\\n  }\\n  removeDataObject() {}\\n  removeField() {}\\n  removeIcon() {}\\n  removeLinks() {}\\n  removeRequirement() {}\\n  removeScript() {}\\n  removeTemplate() {}\\n  removeThumbnails() {}\\n  removeWeblinks() {}\\n  replacePages() {}\\n  resetForm(aFields = null) {\\n    if (aFields && typeof aFields === \\\"object\\\" && !Array.isArray(aFields)) {\\n      aFields = aFields.aFields;\\n    }\\n    if (aFields && !Array.isArray(aFields)) {\\n      aFields = [aFields];\\n    }\\n    let mustCalculate = false;\\n    let fieldsToReset;\\n    if (aFields) {\\n      fieldsToReset = [];\\n      for (const fieldName of aFields) {\\n        if (!fieldName) {\\n          continue;\\n        }\\n        if (typeof fieldName !== \\\"string\\\") {\\n          fieldsToReset = null;\\n          break;\\n        }\\n        const field = this._getField(fieldName);\\n        if (!field) {\\n          continue;\\n        }\\n        fieldsToReset.push(field);\\n        mustCalculate = true;\\n      }\\n    }\\n    if (!fieldsToReset) {\\n      fieldsToReset = this._fields.values();\\n      mustCalculate = this._fields.size !== 0;\\n    }\\n    for (const field of fieldsToReset) {\\n      field.obj.value = field.obj.defaultValue;\\n      this._send({\\n        id: field.obj._id,\\n        siblings: field.obj._siblings,\\n        value: field.obj.defaultValue,\\n        formattedValue: null,\\n        selRange: [0, 0]\\n      });\\n    }\\n    if (mustCalculate) {\\n      this.calculateNow();\\n    }\\n  }\\n  saveAs() {}\\n  scroll() {}\\n  selectPageNthWord() {}\\n  setAction() {}\\n  setDataObjectContents() {}\\n  setOCGOrder() {}\\n  setPageAction() {}\\n  setPageBoxes() {}\\n  setPageLabels() {}\\n  setPageRotations() {}\\n  setPageTabOrder() {}\\n  setPageTransitions() {}\\n  spawnPageFromTemplate() {}\\n  submitForm() {}\\n  syncAnnotScan() {}\\n}\\n\\n;// CONCATENATED MODULE: ./src/scripting_api/proxy.js\\nclass ProxyHandler {\\n  constructor() {\\n    this.nosend = new Set([\\\"delay\\\"]);\\n  }\\n  get(obj, prop) {\\n    if (prop in obj._expandos) {\\n      const val = obj._expandos[prop];\\n      if (typeof val === \\\"function\\\") {\\n        return val.bind(obj);\\n      }\\n      return val;\\n    }\\n    if (typeof prop === \\\"string\\\" && !prop.startsWith(\\\"_\\\") && prop in obj) {\\n      const val = obj[prop];\\n      if (typeof val === \\\"function\\\") {\\n        return val.bind(obj);\\n      }\\n      return val;\\n    }\\n    return undefined;\\n  }\\n  set(obj, prop, value) {\\n    if (obj._kidIds) {\\n      obj._kidIds.forEach(id => {\\n        obj._appObjects[id].wrapped[prop] = value;\\n      });\\n    }\\n    if (typeof prop === \\\"string\\\" && !prop.startsWith(\\\"_\\\") && prop in obj) {\\n      const old = obj[prop];\\n      obj[prop] = value;\\n      if (!this.nosend.has(prop) && obj._send && obj._id !== null && typeof old !== \\\"function\\\") {\\n        const data = {\\n          id: obj._id\\n        };\\n        data[prop] = prop === \\\"value\\\" ? obj._getValue() : obj[prop];\\n        if (!obj._siblings) {\\n          obj._send(data);\\n        } else {\\n          data.siblings = obj._siblings;\\n          obj._send(data);\\n        }\\n      }\\n    } else {\\n      obj._expandos[prop] = value;\\n    }\\n    return true;\\n  }\\n  has(obj, prop) {\\n    return prop in obj._expandos || typeof prop === \\\"string\\\" && !prop.startsWith(\\\"_\\\") && prop in obj;\\n  }\\n  getPrototypeOf(obj) {\\n    return null;\\n  }\\n  setPrototypeOf(obj, proto) {\\n    return false;\\n  }\\n  isExtensible(obj) {\\n    return true;\\n  }\\n  preventExtensions(obj) {\\n    return false;\\n  }\\n  getOwnPropertyDescriptor(obj, prop) {\\n    if (prop in obj._expandos) {\\n      return {\\n        configurable: true,\\n        enumerable: true,\\n        value: obj._expandos[prop]\\n      };\\n    }\\n    if (typeof prop === \\\"string\\\" && !prop.startsWith(\\\"_\\\") && prop in obj) {\\n      return {\\n        configurable: true,\\n        enumerable: true,\\n        value: obj[prop]\\n      };\\n    }\\n    return undefined;\\n  }\\n  defineProperty(obj, key, descriptor) {\\n    Object.defineProperty(obj._expandos, key, descriptor);\\n    return true;\\n  }\\n  deleteProperty(obj, prop) {\\n    if (prop in obj._expandos) {\\n      delete obj._expandos[prop];\\n    }\\n  }\\n  ownKeys(obj) {\\n    const fromExpandos = Reflect.ownKeys(obj._expandos);\\n    const fromObj = Reflect.ownKeys(obj).filter(k => !k.startsWith(\\\"_\\\"));\\n    return fromExpandos.concat(fromObj);\\n  }\\n}\\n\\n;// CONCATENATED MODULE: ./src/scripting_api/util.js\\n\\nclass Util extends PDFObject {\\n  constructor(data) {\\n    super(data);\\n    this._scandCache = new Map();\\n    this._months = [\\\"January\\\", \\\"February\\\", \\\"March\\\", \\\"April\\\", \\\"May\\\", \\\"June\\\", \\\"July\\\", \\\"August\\\", \\\"September\\\", \\\"October\\\", \\\"November\\\", \\\"December\\\"];\\n    this._days = [\\\"Sunday\\\", \\\"Monday\\\", \\\"Tuesday\\\", \\\"Wednesday\\\", \\\"Thursday\\\", \\\"Friday\\\", \\\"Saturday\\\"];\\n    this.MILLISECONDS_IN_DAY = 86400000;\\n    this.MILLISECONDS_IN_WEEK = 604800000;\\n    this._externalCall = data.externalCall;\\n  }\\n  printf(...args) {\\n    if (args.length === 0) {\\n      throw new Error(\\\"Invalid number of params in printf\\\");\\n    }\\n    if (typeof args[0] !== \\\"string\\\") {\\n      throw new TypeError(\\\"First argument of printf must be a string\\\");\\n    }\\n    const pattern = /%(,[0-4])?([+ 0#]+)?(\\\\d+)?(\\\\.\\\\d+)?(.)/g;\\n    const PLUS = 1;\\n    const SPACE = 2;\\n    const ZERO = 4;\\n    const HASH = 8;\\n    let i = 0;\\n    return args[0].replaceAll(pattern, function (match, nDecSep, cFlags, nWidth, nPrecision, cConvChar) {\\n      if (cConvChar !== \\\"d\\\" && cConvChar !== \\\"f\\\" && cConvChar !== \\\"s\\\" && cConvChar !== \\\"x\\\") {\\n        const buf = [\\\"%\\\"];\\n        for (const str of [nDecSep, cFlags, nWidth, nPrecision, cConvChar]) {\\n          if (str) {\\n            buf.push(str);\\n          }\\n        }\\n        return buf.join(\\\"\\\");\\n      }\\n      i++;\\n      if (i === args.length) {\\n        throw new Error(\\\"Not enough arguments in printf\\\");\\n      }\\n      const arg = args[i];\\n      if (cConvChar === \\\"s\\\") {\\n        return arg.toString();\\n      }\\n      let flags = 0;\\n      if (cFlags) {\\n        for (const flag of cFlags) {\\n          switch (flag) {\\n            case \\\"+\\\":\\n              flags |= PLUS;\\n              break;\\n            case \\\" \\\":\\n              flags |= SPACE;\\n              break;\\n            case \\\"0\\\":\\n              flags |= ZERO;\\n              break;\\n            case \\\"#\\\":\\n              flags |= HASH;\\n              break;\\n          }\\n        }\\n      }\\n      cFlags = flags;\\n      if (nWidth) {\\n        nWidth = parseInt(nWidth);\\n      }\\n      let intPart = Math.trunc(arg);\\n      if (cConvChar === \\\"x\\\") {\\n        let hex = Math.abs(intPart).toString(16).toUpperCase();\\n        if (nWidth !== undefined) {\\n          hex = hex.padStart(nWidth, cFlags & ZERO ? \\\"0\\\" : \\\" \\\");\\n        }\\n        if (cFlags & HASH) {\\n          hex = `0x${hex}`;\\n        }\\n        return hex;\\n      }\\n      if (nPrecision) {\\n        nPrecision = parseInt(nPrecision.substring(1));\\n      }\\n      nDecSep = nDecSep ? nDecSep.substring(1) : \\\"0\\\";\\n      const separators = {\\n        0: [\\\",\\\", \\\".\\\"],\\n        1: [\\\"\\\", \\\".\\\"],\\n        2: [\\\".\\\", \\\",\\\"],\\n        3: [\\\"\\\", \\\",\\\"],\\n        4: [\\\"'\\\", \\\".\\\"]\\n      };\\n      const [thousandSep, decimalSep] = separators[nDecSep];\\n      let decPart = \\\"\\\";\\n      if (cConvChar === \\\"f\\\") {\\n        decPart = nPrecision !== undefined ? Math.abs(arg - intPart).toFixed(nPrecision) : Math.abs(arg - intPart).toString();\\n        if (decPart.length > 2) {\\n          decPart = `${decimalSep}${decPart.substring(2)}`;\\n        } else {\\n          if (decPart === \\\"1\\\") {\\n            intPart += Math.sign(arg);\\n          }\\n          decPart = cFlags & HASH ? \\\".\\\" : \\\"\\\";\\n        }\\n      }\\n      let sign = \\\"\\\";\\n      if (intPart < 0) {\\n        sign = \\\"-\\\";\\n        intPart = -intPart;\\n      } else if (cFlags & PLUS) {\\n        sign = \\\"+\\\";\\n      } else if (cFlags & SPACE) {\\n        sign = \\\" \\\";\\n      }\\n      if (thousandSep && intPart >= 1000) {\\n        const buf = [];\\n        while (true) {\\n          buf.push((intPart % 1000).toString().padStart(3, \\\"0\\\"));\\n          intPart = Math.trunc(intPart / 1000);\\n          if (intPart < 1000) {\\n            buf.push(intPart.toString());\\n            break;\\n          }\\n        }\\n        intPart = buf.reverse().join(thousandSep);\\n      } else {\\n        intPart = intPart.toString();\\n      }\\n      let n = `${intPart}${decPart}`;\\n      if (nWidth !== undefined) {\\n        n = n.padStart(nWidth - sign.length, cFlags & ZERO ? \\\"0\\\" : \\\" \\\");\\n      }\\n      return `${sign}${n}`;\\n    });\\n  }\\n  iconStreamFromIcon() {}\\n  printd(cFormat, oDate) {\\n    switch (cFormat) {\\n      case 0:\\n        return this.printd(\\\"D:yyyymmddHHMMss\\\", oDate);\\n      case 1:\\n        return this.printd(\\\"yyyy.mm.dd HH:MM:ss\\\", oDate);\\n      case 2:\\n        return this.printd(\\\"m/d/yy h:MM:ss tt\\\", oDate);\\n    }\\n    const handlers = {\\n      mmmm: data => this._months[data.month],\\n      mmm: data => this._months[data.month].substring(0, 3),\\n      mm: data => (data.month + 1).toString().padStart(2, \\\"0\\\"),\\n      m: data => (data.month + 1).toString(),\\n      dddd: data => this._days[data.dayOfWeek],\\n      ddd: data => this._days[data.dayOfWeek].substring(0, 3),\\n      dd: data => data.day.toString().padStart(2, \\\"0\\\"),\\n      d: data => data.day.toString(),\\n      yyyy: data => data.year.toString(),\\n      yy: data => (data.year % 100).toString().padStart(2, \\\"0\\\"),\\n      HH: data => data.hours.toString().padStart(2, \\\"0\\\"),\\n      H: data => data.hours.toString(),\\n      hh: data => (1 + (data.hours + 11) % 12).toString().padStart(2, \\\"0\\\"),\\n      h: data => (1 + (data.hours + 11) % 12).toString(),\\n      MM: data => data.minutes.toString().padStart(2, \\\"0\\\"),\\n      M: data => data.minutes.toString(),\\n      ss: data => data.seconds.toString().padStart(2, \\\"0\\\"),\\n      s: data => data.seconds.toString(),\\n      tt: data => data.hours < 12 ? \\\"am\\\" : \\\"pm\\\",\\n      t: data => data.hours < 12 ? \\\"a\\\" : \\\"p\\\"\\n    };\\n    const data = {\\n      year: oDate.getFullYear(),\\n      month: oDate.getMonth(),\\n      day: oDate.getDate(),\\n      dayOfWeek: oDate.getDay(),\\n      hours: oDate.getHours(),\\n      minutes: oDate.getMinutes(),\\n      seconds: oDate.getSeconds()\\n    };\\n    const patterns = /(mmmm|mmm|mm|m|dddd|ddd|dd|d|yyyy|yy|HH|H|hh|h|MM|M|ss|s|tt|t|\\\\\\\\.)/g;\\n    return cFormat.replaceAll(patterns, function (match, pattern) {\\n      if (pattern in handlers) {\\n        return handlers[pattern](data);\\n      }\\n      return pattern.charCodeAt(1);\\n    });\\n  }\\n  printx(cFormat, cSource) {\\n    cSource = (cSource ?? \\\"\\\").toString();\\n    const handlers = [x => x, x => x.toUpperCase(), x => x.toLowerCase()];\\n    const buf = [];\\n    let i = 0;\\n    const ii = cSource.length;\\n    let currCase = handlers[0];\\n    let escaped = false;\\n    for (const command of cFormat) {\\n      if (escaped) {\\n        buf.push(command);\\n        escaped = false;\\n        continue;\\n      }\\n      if (i >= ii) {\\n        break;\\n      }\\n      switch (command) {\\n        case \\\"?\\\":\\n          buf.push(currCase(cSource.charAt(i++)));\\n          break;\\n        case \\\"X\\\":\\n          while (i < ii) {\\n            const char = cSource.charAt(i++);\\n            if (\\\"a\\\" <= char && char <= \\\"z\\\" || \\\"A\\\" <= char && char <= \\\"Z\\\" || \\\"0\\\" <= char && char <= \\\"9\\\") {\\n              buf.push(currCase(char));\\n              break;\\n            }\\n          }\\n          break;\\n        case \\\"A\\\":\\n          while (i < ii) {\\n            const char = cSource.charAt(i++);\\n            if (\\\"a\\\" <= char && char <= \\\"z\\\" || \\\"A\\\" <= char && char <= \\\"Z\\\") {\\n              buf.push(currCase(char));\\n              break;\\n            }\\n          }\\n          break;\\n        case \\\"9\\\":\\n          while (i < ii) {\\n            const char = cSource.charAt(i++);\\n            if (\\\"0\\\" <= char && char <= \\\"9\\\") {\\n              buf.push(char);\\n              break;\\n            }\\n          }\\n          break;\\n        case \\\"*\\\":\\n          while (i < ii) {\\n            buf.push(currCase(cSource.charAt(i++)));\\n          }\\n          break;\\n        case \\\"\\\\\\\\\\\":\\n          escaped = true;\\n          break;\\n        case \\\">\\\":\\n          currCase = handlers[1];\\n          break;\\n        case \\\"<\\\":\\n          currCase = handlers[2];\\n          break;\\n        case \\\"=\\\":\\n          currCase = handlers[0];\\n          break;\\n        default:\\n          buf.push(command);\\n      }\\n    }\\n    return buf.join(\\\"\\\");\\n  }\\n  scand(cFormat, cDate) {\\n    if (typeof cDate !== \\\"string\\\") {\\n      return new Date(cDate);\\n    }\\n    if (cDate === \\\"\\\") {\\n      return new Date();\\n    }\\n    switch (cFormat) {\\n      case 0:\\n        return this.scand(\\\"D:yyyymmddHHMMss\\\", cDate);\\n      case 1:\\n        return this.scand(\\\"yyyy.mm.dd HH:MM:ss\\\", cDate);\\n      case 2:\\n        return this.scand(\\\"m/d/yy h:MM:ss tt\\\", cDate);\\n    }\\n    if (!this._scandCache.has(cFormat)) {\\n      const months = this._months;\\n      const days = this._days;\\n      const handlers = {\\n        mmmm: {\\n          pattern: `(${months.join(\\\"|\\\")})`,\\n          action: (value, data) => {\\n            data.month = months.indexOf(value);\\n          }\\n        },\\n        mmm: {\\n          pattern: `(${months.map(month => month.substring(0, 3)).join(\\\"|\\\")})`,\\n          action: (value, data) => {\\n            data.month = months.findIndex(month => month.substring(0, 3) === value);\\n          }\\n        },\\n        mm: {\\n          pattern: `(\\\\\\\\d{2})`,\\n          action: (value, data) => {\\n            data.month = parseInt(value) - 1;\\n          }\\n        },\\n        m: {\\n          pattern: `(\\\\\\\\d{1,2})`,\\n          action: (value, data) => {\\n            data.month = parseInt(value) - 1;\\n          }\\n        },\\n        dddd: {\\n          pattern: `(${days.join(\\\"|\\\")})`,\\n          action: (value, data) => {\\n            data.day = days.indexOf(value);\\n          }\\n        },\\n        ddd: {\\n          pattern: `(${days.map(day => day.substring(0, 3)).join(\\\"|\\\")})`,\\n          action: (value, data) => {\\n            data.day = days.findIndex(day => day.substring(0, 3) === value);\\n          }\\n        },\\n        dd: {\\n          pattern: \\\"(\\\\\\\\d{2})\\\",\\n          action: (value, data) => {\\n            data.day = parseInt(value);\\n          }\\n        },\\n        d: {\\n          pattern: \\\"(\\\\\\\\d{1,2})\\\",\\n          action: (value, data) => {\\n            data.day = parseInt(value);\\n          }\\n        },\\n        yyyy: {\\n          pattern: \\\"(\\\\\\\\d{4})\\\",\\n          action: (value, data) => {\\n            data.year = parseInt(value);\\n          }\\n        },\\n        yy: {\\n          pattern: \\\"(\\\\\\\\d{2})\\\",\\n          action: (value, data) => {\\n            data.year = 2000 + parseInt(value);\\n          }\\n        },\\n        HH: {\\n          pattern: \\\"(\\\\\\\\d{2})\\\",\\n          action: (value, data) => {\\n            data.hours = parseInt(value);\\n          }\\n        },\\n        H: {\\n          pattern: \\\"(\\\\\\\\d{1,2})\\\",\\n          action: (value, data) => {\\n            data.hours = parseInt(value);\\n          }\\n        },\\n        hh: {\\n          pattern: \\\"(\\\\\\\\d{2})\\\",\\n          action: (value, data) => {\\n            data.hours = parseInt(value);\\n          }\\n        },\\n        h: {\\n          pattern: \\\"(\\\\\\\\d{1,2})\\\",\\n          action: (value, data) => {\\n            data.hours = parseInt(value);\\n          }\\n        },\\n        MM: {\\n          pattern: \\\"(\\\\\\\\d{2})\\\",\\n          action: (value, data) => {\\n            data.minutes = parseInt(value);\\n          }\\n        },\\n        M: {\\n          pattern: \\\"(\\\\\\\\d{1,2})\\\",\\n          action: (value, data) => {\\n            data.minutes = parseInt(value);\\n          }\\n        },\\n        ss: {\\n          pattern: \\\"(\\\\\\\\d{2})\\\",\\n          action: (value, data) => {\\n            data.seconds = parseInt(value);\\n          }\\n        },\\n        s: {\\n          pattern: \\\"(\\\\\\\\d{1,2})\\\",\\n          action: (value, data) => {\\n            data.seconds = parseInt(value);\\n          }\\n        },\\n        tt: {\\n          pattern: \\\"([aApP][mM])\\\",\\n          action: (value, data) => {\\n            const char = value.charAt(0);\\n            data.am = char === \\\"a\\\" || char === \\\"A\\\";\\n          }\\n        },\\n        t: {\\n          pattern: \\\"([aApP])\\\",\\n          action: (value, data) => {\\n            data.am = value === \\\"a\\\" || value === \\\"A\\\";\\n          }\\n        }\\n      };\\n      const escapedFormat = cFormat.replaceAll(/[.*+\\\\-?^${}()|[\\\\]\\\\\\\\]/g, \\\"\\\\\\\\$&\\\");\\n      const patterns = /(mmmm|mmm|mm|m|dddd|ddd|dd|d|yyyy|yy|HH|H|hh|h|MM|M|ss|s|tt|t)/g;\\n      const actions = [];\\n      const re = escapedFormat.replaceAll(patterns, function (match, patternElement) {\\n        const {\\n          pattern,\\n          action\\n        } = handlers[patternElement];\\n        actions.push(action);\\n        return pattern;\\n      });\\n      this._scandCache.set(cFormat, [re, actions]);\\n    }\\n    const [re, actions] = this._scandCache.get(cFormat);\\n    const matches = new RegExp(`^${re}$`, \\\"g\\\").exec(cDate);\\n    if (!matches || matches.length !== actions.length + 1) {\\n      return null;\\n    }\\n    const data = {\\n      year: 2000,\\n      month: 0,\\n      day: 1,\\n      hours: 0,\\n      minutes: 0,\\n      seconds: 0,\\n      am: null\\n    };\\n    actions.forEach((action, i) => action(matches[i + 1], data));\\n    if (data.am !== null) {\\n      data.hours = data.hours % 12 + (data.am ? 0 : 12);\\n    }\\n    return new Date(data.year, data.month, data.day, data.hours, data.minutes, data.seconds);\\n  }\\n  spansToXML() {}\\n  stringFromStream() {}\\n  xmlToSpans() {}\\n}\\n\\n;// CONCATENATED MODULE: ./src/scripting_api/initialization.js\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\nfunction initSandbox(params) {\\n  delete globalThis.pdfjsScripting;\\n  const externalCall = globalThis.callExternalFunction;\\n  delete globalThis.callExternalFunction;\\n  const globalEval = code => globalThis.eval(code);\\n  const send = data => externalCall(\\\"send\\\", [data]);\\n  const proxyHandler = new ProxyHandler();\\n  const {\\n    data\\n  } = params;\\n  const doc = new Doc({\\n    send,\\n    globalEval,\\n    ...data.docInfo\\n  });\\n  const _document = {\\n    obj: doc,\\n    wrapped: new Proxy(doc, proxyHandler)\\n  };\\n  const app = new App({\\n    send,\\n    globalEval,\\n    externalCall,\\n    _document,\\n    calculationOrder: data.calculationOrder,\\n    proxyHandler,\\n    ...data.appInfo\\n  });\\n  const util = new Util({\\n    externalCall\\n  });\\n  const appObjects = app._objects;\\n  if (data.objects) {\\n    const annotations = [];\\n    for (const [name, objs] of Object.entries(data.objects)) {\\n      annotations.length = 0;\\n      let container = null;\\n      for (const obj of objs) {\\n        if (obj.type !== \\\"\\\") {\\n          annotations.push(obj);\\n        } else {\\n          container = obj;\\n        }\\n      }\\n      let obj = container;\\n      if (annotations.length > 0) {\\n        obj = annotations[0];\\n        obj.send = send;\\n      }\\n      obj.globalEval = globalEval;\\n      obj.doc = _document;\\n      obj.fieldPath = name;\\n      obj.appObjects = appObjects;\\n      let field;\\n      switch (obj.type) {\\n        case \\\"radiobutton\\\":\\n          {\\n            const otherButtons = annotations.slice(1);\\n            field = new RadioButtonField(otherButtons, obj);\\n            break;\\n          }\\n        case \\\"checkbox\\\":\\n          {\\n            const otherButtons = annotations.slice(1);\\n            field = new CheckboxField(otherButtons, obj);\\n            break;\\n          }\\n        case \\\"text\\\":\\n          if (annotations.length <= 1) {\\n            field = new Field(obj);\\n            break;\\n          }\\n          obj.siblings = annotations.map(x => x.id).slice(1);\\n          field = new Field(obj);\\n          break;\\n        default:\\n          field = new Field(obj);\\n      }\\n      const wrapped = new Proxy(field, proxyHandler);\\n      const _object = {\\n        obj: field,\\n        wrapped\\n      };\\n      doc._addField(name, _object);\\n      for (const object of objs) {\\n        appObjects[object.id] = _object;\\n      }\\n      if (container) {\\n        appObjects[container.id] = _object;\\n      }\\n    }\\n  }\\n  const color = new Color();\\n  globalThis.event = null;\\n  globalThis.global = Object.create(null);\\n  globalThis.app = new Proxy(app, proxyHandler);\\n  globalThis.color = new Proxy(color, proxyHandler);\\n  globalThis.console = new Proxy(new Console({\\n    send\\n  }), proxyHandler);\\n  globalThis.util = new Proxy(util, proxyHandler);\\n  globalThis.border = Border;\\n  globalThis.cursor = Cursor;\\n  globalThis.display = Display;\\n  globalThis.font = Font;\\n  globalThis.highlight = Highlight;\\n  globalThis.position = Position;\\n  globalThis.scaleHow = ScaleHow;\\n  globalThis.scaleWhen = ScaleWhen;\\n  globalThis.style = Style;\\n  globalThis.trans = Trans;\\n  globalThis.zoomtype = ZoomType;\\n  globalThis.ADBE = {\\n    Reader_Value_Asked: true,\\n    Viewer_Value_Asked: true\\n  };\\n  const aform = new AForm(doc, app, util, color);\\n  for (const name of Object.getOwnPropertyNames(AForm.prototype)) {\\n    if (name !== \\\"constructor\\\" && !name.startsWith(\\\"_\\\")) {\\n      globalThis[name] = aform[name].bind(aform);\\n    }\\n  }\\n  for (const [name, value] of Object.entries(GlobalConstants)) {\\n    Object.defineProperty(globalThis, name, {\\n      value,\\n      writable: false\\n    });\\n  }\\n  Object.defineProperties(globalThis, {\\n    ColorConvert: {\\n      value: color.convert.bind(color),\\n      writable: true\\n    },\\n    ColorEqual: {\\n      value: color.equal.bind(color),\\n      writable: true\\n    }\\n  });\\n  const properties = Object.create(null);\\n  for (const name of Object.getOwnPropertyNames(Doc.prototype)) {\\n    if (name === \\\"constructor\\\" || name.startsWith(\\\"_\\\")) {\\n      continue;\\n    }\\n    const descriptor = Object.getOwnPropertyDescriptor(Doc.prototype, name);\\n    if (descriptor.get) {\\n      properties[name] = {\\n        get: descriptor.get.bind(doc),\\n        set: descriptor.set.bind(doc)\\n      };\\n    } else {\\n      properties[name] = {\\n        value: Doc.prototype[name].bind(doc)\\n      };\\n    }\\n  }\\n  Object.defineProperties(globalThis, properties);\\n  const functions = {\\n    dispatchEvent: app._dispatchEvent.bind(app),\\n    timeoutCb: app._evalCallback.bind(app)\\n  };\\n  return (name, args) => {\\n    try {\\n      functions[name](args);\\n    } catch (error) {\\n      send(serializeError(error));\\n    }\\n  };\\n}\\n\\n;// CONCATENATED MODULE: ./src/pdf.scripting.js\\n\\nconst pdfjsVersion = \\\"4.2.67\\\";\\nconst pdfjsBuild = \\\"49b388101\\\";\\nglobalThis.pdfjsScripting = {\\n  initSandbox: initSandbox\\n};\\n\"];\n    code.push(\"delete dump;\");\n    let success = false;\n    let buf = 0;\n    try {\n      const sandboxData = JSON.stringify(data);\n      code.push(`pdfjsScripting.initSandbox({ data: ${sandboxData} })`);\n      buf = this._module.stringToNewUTF8(code.join(\"\\n\"));\n      success = !!this._module.ccall(\"init\", \"number\", [\"number\", \"number\"], [buf, this._alertOnError]);\n    } catch (error) {\n      console.error(error);\n    } finally {\n      if (buf) {\n        this._module.ccall(\"free\", \"number\", [\"number\"], [buf]);\n      }\n    }\n    if (success) {\n      this.support.commFun = this._module.cwrap(\"commFun\", null, [\"string\", \"string\"]);\n    } else {\n      this.nukeSandbox();\n      throw new Error(\"Cannot start sandbox\");\n    }\n  }\n  dispatchEvent(event) {\n    this.support?.callSandboxFunction(\"dispatchEvent\", event);\n  }\n  dumpMemoryUse() {\n    this._module?.ccall(\"dumpMemoryUse\", null, []);\n  }\n  nukeSandbox() {\n    if (this._module !== null) {\n      this.support.destroy();\n      this.support = null;\n      this._module.ccall(\"nukeSandbox\", null, []);\n      this._module = null;\n    }\n  }\n  evalForTesting(code, key) {\n    throw new Error(\"Not implemented: evalForTesting\");\n  }\n}\nfunction QuickJSSandbox() {\n  return quickjs_eval().then(module => new Sandbox(window, module));\n}\n\nvar __webpack_exports__QuickJSSandbox = __webpack_exports__.QuickJSSandbox;\nexport { __webpack_exports__QuickJSSandbox as QuickJSSandbox };\n\n//# sourceMappingURL=pdf.sandbox.mjs.map"
  },
  {
    "path": "src/StaffWebUI/wwwroot/pdfjs-4.2.67-dist/build/pdf.worker.mjs",
    "content": "/**\n * @licstart The following is the entire license notice for the\n * JavaScript code in this page\n *\n * Copyright 2023 Mozilla Foundation\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 * @licend The above is the entire license notice for the\n * JavaScript code in this page\n */\n\n/******/ // The require scope\n/******/ var __webpack_require__ = {};\n/******/ \n/************************************************************************/\n/******/ /* webpack/runtime/define property getters */\n/******/ (() => {\n/******/ \t// define getter functions for harmony exports\n/******/ \t__webpack_require__.d = (exports, definition) => {\n/******/ \t\tfor(var key in definition) {\n/******/ \t\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n/******/ \t\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n/******/ \t\t\t}\n/******/ \t\t}\n/******/ \t};\n/******/ })();\n/******/ \n/******/ /* webpack/runtime/hasOwnProperty shorthand */\n/******/ (() => {\n/******/ \t__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))\n/******/ })();\n/******/ \n/************************************************************************/\nvar __webpack_exports__ = globalThis.pdfjsWorker = {};\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, {\n  WorkerMessageHandler: () => (/* reexport */ WorkerMessageHandler)\n});\n\n;// CONCATENATED MODULE: ./src/shared/util.js\nconst isNodeJS = typeof process === \"object\" && process + \"\" === \"[object process]\" && !process.versions.nw && !(process.versions.electron && process.type && process.type !== \"browser\");\nconst IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];\nconst FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];\nconst MAX_IMAGE_SIZE_TO_CACHE = 10e6;\nconst LINE_FACTOR = 1.35;\nconst LINE_DESCENT_FACTOR = 0.35;\nconst BASELINE_FACTOR = LINE_DESCENT_FACTOR / LINE_FACTOR;\nconst RenderingIntentFlag = {\n  ANY: 0x01,\n  DISPLAY: 0x02,\n  PRINT: 0x04,\n  SAVE: 0x08,\n  ANNOTATIONS_FORMS: 0x10,\n  ANNOTATIONS_STORAGE: 0x20,\n  ANNOTATIONS_DISABLE: 0x40,\n  OPLIST: 0x100\n};\nconst AnnotationMode = {\n  DISABLE: 0,\n  ENABLE: 1,\n  ENABLE_FORMS: 2,\n  ENABLE_STORAGE: 3\n};\nconst AnnotationEditorPrefix = \"pdfjs_internal_editor_\";\nconst AnnotationEditorType = {\n  DISABLE: -1,\n  NONE: 0,\n  FREETEXT: 3,\n  HIGHLIGHT: 9,\n  STAMP: 13,\n  INK: 15\n};\nconst AnnotationEditorParamsType = {\n  RESIZE: 1,\n  CREATE: 2,\n  FREETEXT_SIZE: 11,\n  FREETEXT_COLOR: 12,\n  FREETEXT_OPACITY: 13,\n  INK_COLOR: 21,\n  INK_THICKNESS: 22,\n  INK_OPACITY: 23,\n  HIGHLIGHT_COLOR: 31,\n  HIGHLIGHT_DEFAULT_COLOR: 32,\n  HIGHLIGHT_THICKNESS: 33,\n  HIGHLIGHT_FREE: 34,\n  HIGHLIGHT_SHOW_ALL: 35\n};\nconst PermissionFlag = {\n  PRINT: 0x04,\n  MODIFY_CONTENTS: 0x08,\n  COPY: 0x10,\n  MODIFY_ANNOTATIONS: 0x20,\n  FILL_INTERACTIVE_FORMS: 0x100,\n  COPY_FOR_ACCESSIBILITY: 0x200,\n  ASSEMBLE: 0x400,\n  PRINT_HIGH_QUALITY: 0x800\n};\nconst TextRenderingMode = {\n  FILL: 0,\n  STROKE: 1,\n  FILL_STROKE: 2,\n  INVISIBLE: 3,\n  FILL_ADD_TO_PATH: 4,\n  STROKE_ADD_TO_PATH: 5,\n  FILL_STROKE_ADD_TO_PATH: 6,\n  ADD_TO_PATH: 7,\n  FILL_STROKE_MASK: 3,\n  ADD_TO_PATH_FLAG: 4\n};\nconst ImageKind = {\n  GRAYSCALE_1BPP: 1,\n  RGB_24BPP: 2,\n  RGBA_32BPP: 3\n};\nconst AnnotationType = {\n  TEXT: 1,\n  LINK: 2,\n  FREETEXT: 3,\n  LINE: 4,\n  SQUARE: 5,\n  CIRCLE: 6,\n  POLYGON: 7,\n  POLYLINE: 8,\n  HIGHLIGHT: 9,\n  UNDERLINE: 10,\n  SQUIGGLY: 11,\n  STRIKEOUT: 12,\n  STAMP: 13,\n  CARET: 14,\n  INK: 15,\n  POPUP: 16,\n  FILEATTACHMENT: 17,\n  SOUND: 18,\n  MOVIE: 19,\n  WIDGET: 20,\n  SCREEN: 21,\n  PRINTERMARK: 22,\n  TRAPNET: 23,\n  WATERMARK: 24,\n  THREED: 25,\n  REDACT: 26\n};\nconst AnnotationReplyType = {\n  GROUP: \"Group\",\n  REPLY: \"R\"\n};\nconst AnnotationFlag = {\n  INVISIBLE: 0x01,\n  HIDDEN: 0x02,\n  PRINT: 0x04,\n  NOZOOM: 0x08,\n  NOROTATE: 0x10,\n  NOVIEW: 0x20,\n  READONLY: 0x40,\n  LOCKED: 0x80,\n  TOGGLENOVIEW: 0x100,\n  LOCKEDCONTENTS: 0x200\n};\nconst AnnotationFieldFlag = {\n  READONLY: 0x0000001,\n  REQUIRED: 0x0000002,\n  NOEXPORT: 0x0000004,\n  MULTILINE: 0x0001000,\n  PASSWORD: 0x0002000,\n  NOTOGGLETOOFF: 0x0004000,\n  RADIO: 0x0008000,\n  PUSHBUTTON: 0x0010000,\n  COMBO: 0x0020000,\n  EDIT: 0x0040000,\n  SORT: 0x0080000,\n  FILESELECT: 0x0100000,\n  MULTISELECT: 0x0200000,\n  DONOTSPELLCHECK: 0x0400000,\n  DONOTSCROLL: 0x0800000,\n  COMB: 0x1000000,\n  RICHTEXT: 0x2000000,\n  RADIOSINUNISON: 0x2000000,\n  COMMITONSELCHANGE: 0x4000000\n};\nconst AnnotationBorderStyleType = {\n  SOLID: 1,\n  DASHED: 2,\n  BEVELED: 3,\n  INSET: 4,\n  UNDERLINE: 5\n};\nconst AnnotationActionEventType = {\n  E: \"Mouse Enter\",\n  X: \"Mouse Exit\",\n  D: \"Mouse Down\",\n  U: \"Mouse Up\",\n  Fo: \"Focus\",\n  Bl: \"Blur\",\n  PO: \"PageOpen\",\n  PC: \"PageClose\",\n  PV: \"PageVisible\",\n  PI: \"PageInvisible\",\n  K: \"Keystroke\",\n  F: \"Format\",\n  V: \"Validate\",\n  C: \"Calculate\"\n};\nconst DocumentActionEventType = {\n  WC: \"WillClose\",\n  WS: \"WillSave\",\n  DS: \"DidSave\",\n  WP: \"WillPrint\",\n  DP: \"DidPrint\"\n};\nconst PageActionEventType = {\n  O: \"PageOpen\",\n  C: \"PageClose\"\n};\nconst VerbosityLevel = {\n  ERRORS: 0,\n  WARNINGS: 1,\n  INFOS: 5\n};\nconst CMapCompressionType = {\n  NONE: 0,\n  BINARY: 1\n};\nconst OPS = {\n  dependency: 1,\n  setLineWidth: 2,\n  setLineCap: 3,\n  setLineJoin: 4,\n  setMiterLimit: 5,\n  setDash: 6,\n  setRenderingIntent: 7,\n  setFlatness: 8,\n  setGState: 9,\n  save: 10,\n  restore: 11,\n  transform: 12,\n  moveTo: 13,\n  lineTo: 14,\n  curveTo: 15,\n  curveTo2: 16,\n  curveTo3: 17,\n  closePath: 18,\n  rectangle: 19,\n  stroke: 20,\n  closeStroke: 21,\n  fill: 22,\n  eoFill: 23,\n  fillStroke: 24,\n  eoFillStroke: 25,\n  closeFillStroke: 26,\n  closeEOFillStroke: 27,\n  endPath: 28,\n  clip: 29,\n  eoClip: 30,\n  beginText: 31,\n  endText: 32,\n  setCharSpacing: 33,\n  setWordSpacing: 34,\n  setHScale: 35,\n  setLeading: 36,\n  setFont: 37,\n  setTextRenderingMode: 38,\n  setTextRise: 39,\n  moveText: 40,\n  setLeadingMoveText: 41,\n  setTextMatrix: 42,\n  nextLine: 43,\n  showText: 44,\n  showSpacedText: 45,\n  nextLineShowText: 46,\n  nextLineSetSpacingShowText: 47,\n  setCharWidth: 48,\n  setCharWidthAndBounds: 49,\n  setStrokeColorSpace: 50,\n  setFillColorSpace: 51,\n  setStrokeColor: 52,\n  setStrokeColorN: 53,\n  setFillColor: 54,\n  setFillColorN: 55,\n  setStrokeGray: 56,\n  setFillGray: 57,\n  setStrokeRGBColor: 58,\n  setFillRGBColor: 59,\n  setStrokeCMYKColor: 60,\n  setFillCMYKColor: 61,\n  shadingFill: 62,\n  beginInlineImage: 63,\n  beginImageData: 64,\n  endInlineImage: 65,\n  paintXObject: 66,\n  markPoint: 67,\n  markPointProps: 68,\n  beginMarkedContent: 69,\n  beginMarkedContentProps: 70,\n  endMarkedContent: 71,\n  beginCompat: 72,\n  endCompat: 73,\n  paintFormXObjectBegin: 74,\n  paintFormXObjectEnd: 75,\n  beginGroup: 76,\n  endGroup: 77,\n  beginAnnotation: 80,\n  endAnnotation: 81,\n  paintImageMaskXObject: 83,\n  paintImageMaskXObjectGroup: 84,\n  paintImageXObject: 85,\n  paintInlineImageXObject: 86,\n  paintInlineImageXObjectGroup: 87,\n  paintImageXObjectRepeat: 88,\n  paintImageMaskXObjectRepeat: 89,\n  paintSolidColorImageMask: 90,\n  constructPath: 91\n};\nconst PasswordResponses = {\n  NEED_PASSWORD: 1,\n  INCORRECT_PASSWORD: 2\n};\nlet verbosity = VerbosityLevel.WARNINGS;\nfunction setVerbosityLevel(level) {\n  if (Number.isInteger(level)) {\n    verbosity = level;\n  }\n}\nfunction getVerbosityLevel() {\n  return verbosity;\n}\nfunction info(msg) {\n  if (verbosity >= VerbosityLevel.INFOS) {\n    console.log(`Info: ${msg}`);\n  }\n}\nfunction warn(msg) {\n  if (verbosity >= VerbosityLevel.WARNINGS) {\n    console.log(`Warning: ${msg}`);\n  }\n}\nfunction unreachable(msg) {\n  throw new Error(msg);\n}\nfunction assert(cond, msg) {\n  if (!cond) {\n    unreachable(msg);\n  }\n}\nfunction _isValidProtocol(url) {\n  switch (url?.protocol) {\n    case \"http:\":\n    case \"https:\":\n    case \"ftp:\":\n    case \"mailto:\":\n    case \"tel:\":\n      return true;\n    default:\n      return false;\n  }\n}\nfunction createValidAbsoluteUrl(url, baseUrl = null, options = null) {\n  if (!url) {\n    return null;\n  }\n  try {\n    if (options && typeof url === \"string\") {\n      if (options.addDefaultProtocol && url.startsWith(\"www.\")) {\n        const dots = url.match(/\\./g);\n        if (dots?.length >= 2) {\n          url = `http://${url}`;\n        }\n      }\n      if (options.tryConvertEncoding) {\n        try {\n          url = stringToUTF8String(url);\n        } catch {}\n      }\n    }\n    const absoluteUrl = baseUrl ? new URL(url, baseUrl) : new URL(url);\n    if (_isValidProtocol(absoluteUrl)) {\n      return absoluteUrl;\n    }\n  } catch {}\n  return null;\n}\nfunction shadow(obj, prop, value, nonSerializable = false) {\n  Object.defineProperty(obj, prop, {\n    value,\n    enumerable: !nonSerializable,\n    configurable: true,\n    writable: false\n  });\n  return value;\n}\nconst BaseException = function BaseExceptionClosure() {\n  function BaseException(message, name) {\n    if (this.constructor === BaseException) {\n      unreachable(\"Cannot initialize BaseException.\");\n    }\n    this.message = message;\n    this.name = name;\n  }\n  BaseException.prototype = new Error();\n  BaseException.constructor = BaseException;\n  return BaseException;\n}();\nclass PasswordException extends BaseException {\n  constructor(msg, code) {\n    super(msg, \"PasswordException\");\n    this.code = code;\n  }\n}\nclass UnknownErrorException extends BaseException {\n  constructor(msg, details) {\n    super(msg, \"UnknownErrorException\");\n    this.details = details;\n  }\n}\nclass InvalidPDFException extends BaseException {\n  constructor(msg) {\n    super(msg, \"InvalidPDFException\");\n  }\n}\nclass MissingPDFException extends BaseException {\n  constructor(msg) {\n    super(msg, \"MissingPDFException\");\n  }\n}\nclass UnexpectedResponseException extends BaseException {\n  constructor(msg, status) {\n    super(msg, \"UnexpectedResponseException\");\n    this.status = status;\n  }\n}\nclass FormatError extends BaseException {\n  constructor(msg) {\n    super(msg, \"FormatError\");\n  }\n}\nclass AbortException extends BaseException {\n  constructor(msg) {\n    super(msg, \"AbortException\");\n  }\n}\nfunction bytesToString(bytes) {\n  if (typeof bytes !== \"object\" || bytes?.length === undefined) {\n    unreachable(\"Invalid argument for bytesToString\");\n  }\n  const length = bytes.length;\n  const MAX_ARGUMENT_COUNT = 8192;\n  if (length < MAX_ARGUMENT_COUNT) {\n    return String.fromCharCode.apply(null, bytes);\n  }\n  const strBuf = [];\n  for (let i = 0; i < length; i += MAX_ARGUMENT_COUNT) {\n    const chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length);\n    const chunk = bytes.subarray(i, chunkEnd);\n    strBuf.push(String.fromCharCode.apply(null, chunk));\n  }\n  return strBuf.join(\"\");\n}\nfunction stringToBytes(str) {\n  if (typeof str !== \"string\") {\n    unreachable(\"Invalid argument for stringToBytes\");\n  }\n  const length = str.length;\n  const bytes = new Uint8Array(length);\n  for (let i = 0; i < length; ++i) {\n    bytes[i] = str.charCodeAt(i) & 0xff;\n  }\n  return bytes;\n}\nfunction string32(value) {\n  return String.fromCharCode(value >> 24 & 0xff, value >> 16 & 0xff, value >> 8 & 0xff, value & 0xff);\n}\nfunction objectSize(obj) {\n  return Object.keys(obj).length;\n}\nfunction objectFromMap(map) {\n  const obj = Object.create(null);\n  for (const [key, value] of map) {\n    obj[key] = value;\n  }\n  return obj;\n}\nfunction isLittleEndian() {\n  const buffer8 = new Uint8Array(4);\n  buffer8[0] = 1;\n  const view32 = new Uint32Array(buffer8.buffer, 0, 1);\n  return view32[0] === 1;\n}\nfunction isEvalSupported() {\n  try {\n    new Function(\"\");\n    return true;\n  } catch {\n    return false;\n  }\n}\nclass FeatureTest {\n  static get isLittleEndian() {\n    return shadow(this, \"isLittleEndian\", isLittleEndian());\n  }\n  static get isEvalSupported() {\n    return shadow(this, \"isEvalSupported\", isEvalSupported());\n  }\n  static get isOffscreenCanvasSupported() {\n    return shadow(this, \"isOffscreenCanvasSupported\", typeof OffscreenCanvas !== \"undefined\");\n  }\n  static get platform() {\n    if (typeof navigator !== \"undefined\" && typeof navigator?.platform === \"string\") {\n      return shadow(this, \"platform\", {\n        isMac: navigator.platform.includes(\"Mac\")\n      });\n    }\n    return shadow(this, \"platform\", {\n      isMac: false\n    });\n  }\n  static get isCSSRoundSupported() {\n    return shadow(this, \"isCSSRoundSupported\", globalThis.CSS?.supports?.(\"width: round(1.5px, 1px)\"));\n  }\n}\nconst hexNumbers = Array.from(Array(256).keys(), n => n.toString(16).padStart(2, \"0\"));\nclass Util {\n  static makeHexColor(r, g, b) {\n    return `#${hexNumbers[r]}${hexNumbers[g]}${hexNumbers[b]}`;\n  }\n  static scaleMinMax(transform, minMax) {\n    let temp;\n    if (transform[0]) {\n      if (transform[0] < 0) {\n        temp = minMax[0];\n        minMax[0] = minMax[2];\n        minMax[2] = temp;\n      }\n      minMax[0] *= transform[0];\n      minMax[2] *= transform[0];\n      if (transform[3] < 0) {\n        temp = minMax[1];\n        minMax[1] = minMax[3];\n        minMax[3] = temp;\n      }\n      minMax[1] *= transform[3];\n      minMax[3] *= transform[3];\n    } else {\n      temp = minMax[0];\n      minMax[0] = minMax[1];\n      minMax[1] = temp;\n      temp = minMax[2];\n      minMax[2] = minMax[3];\n      minMax[3] = temp;\n      if (transform[1] < 0) {\n        temp = minMax[1];\n        minMax[1] = minMax[3];\n        minMax[3] = temp;\n      }\n      minMax[1] *= transform[1];\n      minMax[3] *= transform[1];\n      if (transform[2] < 0) {\n        temp = minMax[0];\n        minMax[0] = minMax[2];\n        minMax[2] = temp;\n      }\n      minMax[0] *= transform[2];\n      minMax[2] *= transform[2];\n    }\n    minMax[0] += transform[4];\n    minMax[1] += transform[5];\n    minMax[2] += transform[4];\n    minMax[3] += transform[5];\n  }\n  static transform(m1, m2) {\n    return [m1[0] * m2[0] + m1[2] * m2[1], m1[1] * m2[0] + m1[3] * m2[1], m1[0] * m2[2] + m1[2] * m2[3], m1[1] * m2[2] + m1[3] * m2[3], m1[0] * m2[4] + m1[2] * m2[5] + m1[4], m1[1] * m2[4] + m1[3] * m2[5] + m1[5]];\n  }\n  static applyTransform(p, m) {\n    const xt = p[0] * m[0] + p[1] * m[2] + m[4];\n    const yt = p[0] * m[1] + p[1] * m[3] + m[5];\n    return [xt, yt];\n  }\n  static applyInverseTransform(p, m) {\n    const d = m[0] * m[3] - m[1] * m[2];\n    const xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d;\n    const yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d;\n    return [xt, yt];\n  }\n  static getAxialAlignedBoundingBox(r, m) {\n    const p1 = this.applyTransform(r, m);\n    const p2 = this.applyTransform(r.slice(2, 4), m);\n    const p3 = this.applyTransform([r[0], r[3]], m);\n    const p4 = this.applyTransform([r[2], r[1]], m);\n    return [Math.min(p1[0], p2[0], p3[0], p4[0]), Math.min(p1[1], p2[1], p3[1], p4[1]), Math.max(p1[0], p2[0], p3[0], p4[0]), Math.max(p1[1], p2[1], p3[1], p4[1])];\n  }\n  static inverseTransform(m) {\n    const d = m[0] * m[3] - m[1] * m[2];\n    return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d, (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d];\n  }\n  static singularValueDecompose2dScale(m) {\n    const transpose = [m[0], m[2], m[1], m[3]];\n    const a = m[0] * transpose[0] + m[1] * transpose[2];\n    const b = m[0] * transpose[1] + m[1] * transpose[3];\n    const c = m[2] * transpose[0] + m[3] * transpose[2];\n    const d = m[2] * transpose[1] + m[3] * transpose[3];\n    const first = (a + d) / 2;\n    const second = Math.sqrt((a + d) ** 2 - 4 * (a * d - c * b)) / 2;\n    const sx = first + second || 1;\n    const sy = first - second || 1;\n    return [Math.sqrt(sx), Math.sqrt(sy)];\n  }\n  static normalizeRect(rect) {\n    const r = rect.slice(0);\n    if (rect[0] > rect[2]) {\n      r[0] = rect[2];\n      r[2] = rect[0];\n    }\n    if (rect[1] > rect[3]) {\n      r[1] = rect[3];\n      r[3] = rect[1];\n    }\n    return r;\n  }\n  static intersect(rect1, rect2) {\n    const xLow = Math.max(Math.min(rect1[0], rect1[2]), Math.min(rect2[0], rect2[2]));\n    const xHigh = Math.min(Math.max(rect1[0], rect1[2]), Math.max(rect2[0], rect2[2]));\n    if (xLow > xHigh) {\n      return null;\n    }\n    const yLow = Math.max(Math.min(rect1[1], rect1[3]), Math.min(rect2[1], rect2[3]));\n    const yHigh = Math.min(Math.max(rect1[1], rect1[3]), Math.max(rect2[1], rect2[3]));\n    if (yLow > yHigh) {\n      return null;\n    }\n    return [xLow, yLow, xHigh, yHigh];\n  }\n  static #getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, t, minMax) {\n    if (t <= 0 || t >= 1) {\n      return;\n    }\n    const mt = 1 - t;\n    const tt = t * t;\n    const ttt = tt * t;\n    const x = mt * (mt * (mt * x0 + 3 * t * x1) + 3 * tt * x2) + ttt * x3;\n    const y = mt * (mt * (mt * y0 + 3 * t * y1) + 3 * tt * y2) + ttt * y3;\n    minMax[0] = Math.min(minMax[0], x);\n    minMax[1] = Math.min(minMax[1], y);\n    minMax[2] = Math.max(minMax[2], x);\n    minMax[3] = Math.max(minMax[3], y);\n  }\n  static #getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, a, b, c, minMax) {\n    if (Math.abs(a) < 1e-12) {\n      if (Math.abs(b) >= 1e-12) {\n        this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, -c / b, minMax);\n      }\n      return;\n    }\n    const delta = b ** 2 - 4 * c * a;\n    if (delta < 0) {\n      return;\n    }\n    const sqrtDelta = Math.sqrt(delta);\n    const a2 = 2 * a;\n    this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, (-b + sqrtDelta) / a2, minMax);\n    this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, (-b - sqrtDelta) / a2, minMax);\n  }\n  static bezierBoundingBox(x0, y0, x1, y1, x2, y2, x3, y3, minMax) {\n    if (minMax) {\n      minMax[0] = Math.min(minMax[0], x0, x3);\n      minMax[1] = Math.min(minMax[1], y0, y3);\n      minMax[2] = Math.max(minMax[2], x0, x3);\n      minMax[3] = Math.max(minMax[3], y0, y3);\n    } else {\n      minMax = [Math.min(x0, x3), Math.min(y0, y3), Math.max(x0, x3), Math.max(y0, y3)];\n    }\n    this.#getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, 3 * (-x0 + 3 * (x1 - x2) + x3), 6 * (x0 - 2 * x1 + x2), 3 * (x1 - x0), minMax);\n    this.#getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, 3 * (-y0 + 3 * (y1 - y2) + y3), 6 * (y0 - 2 * y1 + y2), 3 * (y1 - y0), minMax);\n    return minMax;\n  }\n}\nconst PDFStringTranslateTable = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2d8, 0x2c7, 0x2c6, 0x2d9, 0x2dd, 0x2db, 0x2da, 0x2dc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x192, 0x2044, 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018, 0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x141, 0x152, 0x160, 0x178, 0x17d, 0x131, 0x142, 0x153, 0x161, 0x17e, 0, 0x20ac];\nfunction stringToPDFString(str) {\n  if (str[0] >= \"\\xEF\") {\n    let encoding;\n    if (str[0] === \"\\xFE\" && str[1] === \"\\xFF\") {\n      encoding = \"utf-16be\";\n      if (str.length % 2 === 1) {\n        str = str.slice(0, -1);\n      }\n    } else if (str[0] === \"\\xFF\" && str[1] === \"\\xFE\") {\n      encoding = \"utf-16le\";\n      if (str.length % 2 === 1) {\n        str = str.slice(0, -1);\n      }\n    } else if (str[0] === \"\\xEF\" && str[1] === \"\\xBB\" && str[2] === \"\\xBF\") {\n      encoding = \"utf-8\";\n    }\n    if (encoding) {\n      try {\n        const decoder = new TextDecoder(encoding, {\n          fatal: true\n        });\n        const buffer = stringToBytes(str);\n        const decoded = decoder.decode(buffer);\n        if (!decoded.includes(\"\\x1b\")) {\n          return decoded;\n        }\n        return decoded.replaceAll(/\\x1b[^\\x1b]*(?:\\x1b|$)/g, \"\");\n      } catch (ex) {\n        warn(`stringToPDFString: \"${ex}\".`);\n      }\n    }\n  }\n  const strBuf = [];\n  for (let i = 0, ii = str.length; i < ii; i++) {\n    const charCode = str.charCodeAt(i);\n    if (charCode === 0x1b) {\n      while (++i < ii && str.charCodeAt(i) !== 0x1b) {}\n      continue;\n    }\n    const code = PDFStringTranslateTable[charCode];\n    strBuf.push(code ? String.fromCharCode(code) : str.charAt(i));\n  }\n  return strBuf.join(\"\");\n}\nfunction stringToUTF8String(str) {\n  return decodeURIComponent(escape(str));\n}\nfunction utf8StringToString(str) {\n  return unescape(encodeURIComponent(str));\n}\nfunction isArrayEqual(arr1, arr2) {\n  if (arr1.length !== arr2.length) {\n    return false;\n  }\n  for (let i = 0, ii = arr1.length; i < ii; i++) {\n    if (arr1[i] !== arr2[i]) {\n      return false;\n    }\n  }\n  return true;\n}\nfunction getModificationDate(date = new Date()) {\n  const buffer = [date.getUTCFullYear().toString(), (date.getUTCMonth() + 1).toString().padStart(2, \"0\"), date.getUTCDate().toString().padStart(2, \"0\"), date.getUTCHours().toString().padStart(2, \"0\"), date.getUTCMinutes().toString().padStart(2, \"0\"), date.getUTCSeconds().toString().padStart(2, \"0\")];\n  return buffer.join(\"\");\n}\nlet NormalizeRegex = null;\nlet NormalizationMap = null;\nfunction normalizeUnicode(str) {\n  if (!NormalizeRegex) {\n    NormalizeRegex = /([\\u00a0\\u00b5\\u037e\\u0eb3\\u2000-\\u200a\\u202f\\u2126\\ufb00-\\ufb04\\ufb06\\ufb20-\\ufb36\\ufb38-\\ufb3c\\ufb3e\\ufb40-\\ufb41\\ufb43-\\ufb44\\ufb46-\\ufba1\\ufba4-\\ufba9\\ufbae-\\ufbb1\\ufbd3-\\ufbdc\\ufbde-\\ufbe7\\ufbea-\\ufbf8\\ufbfc-\\ufbfd\\ufc00-\\ufc5d\\ufc64-\\ufcf1\\ufcf5-\\ufd3d\\ufd88\\ufdf4\\ufdfa-\\ufdfb\\ufe71\\ufe77\\ufe79\\ufe7b\\ufe7d]+)|(\\ufb05+)/gu;\n    NormalizationMap = new Map([[\"ﬅ\", \"ſt\"]]);\n  }\n  return str.replaceAll(NormalizeRegex, (_, p1, p2) => p1 ? p1.normalize(\"NFKC\") : NormalizationMap.get(p2));\n}\nfunction getUuid() {\n  if (typeof crypto !== \"undefined\" && typeof crypto?.randomUUID === \"function\") {\n    return crypto.randomUUID();\n  }\n  const buf = new Uint8Array(32);\n  if (typeof crypto !== \"undefined\" && typeof crypto?.getRandomValues === \"function\") {\n    crypto.getRandomValues(buf);\n  } else {\n    for (let i = 0; i < 32; i++) {\n      buf[i] = Math.floor(Math.random() * 255);\n    }\n  }\n  return bytesToString(buf);\n}\nconst AnnotationPrefix = \"pdfjs_internal_id_\";\nconst FontRenderOps = {\n  BEZIER_CURVE_TO: 0,\n  MOVE_TO: 1,\n  LINE_TO: 2,\n  QUADRATIC_CURVE_TO: 3,\n  RESTORE: 4,\n  SAVE: 5,\n  SCALE: 6,\n  TRANSFORM: 7,\n  TRANSLATE: 8\n};\n\n;// CONCATENATED MODULE: ./src/core/primitives.js\n\nconst CIRCULAR_REF = Symbol(\"CIRCULAR_REF\");\nconst EOF = Symbol(\"EOF\");\nlet CmdCache = Object.create(null);\nlet NameCache = Object.create(null);\nlet RefCache = Object.create(null);\nfunction clearPrimitiveCaches() {\n  CmdCache = Object.create(null);\n  NameCache = Object.create(null);\n  RefCache = Object.create(null);\n}\nclass Name {\n  constructor(name) {\n    this.name = name;\n  }\n  static get(name) {\n    return NameCache[name] ||= new Name(name);\n  }\n}\nclass Cmd {\n  constructor(cmd) {\n    this.cmd = cmd;\n  }\n  static get(cmd) {\n    return CmdCache[cmd] ||= new Cmd(cmd);\n  }\n}\nconst nonSerializable = function nonSerializableClosure() {\n  return nonSerializable;\n};\nclass Dict {\n  constructor(xref = null) {\n    this._map = Object.create(null);\n    this.xref = xref;\n    this.objId = null;\n    this.suppressEncryption = false;\n    this.__nonSerializable__ = nonSerializable;\n  }\n  assignXref(newXref) {\n    this.xref = newXref;\n  }\n  get size() {\n    return Object.keys(this._map).length;\n  }\n  get(key1, key2, key3) {\n    let value = this._map[key1];\n    if (value === undefined && key2 !== undefined) {\n      value = this._map[key2];\n      if (value === undefined && key3 !== undefined) {\n        value = this._map[key3];\n      }\n    }\n    if (value instanceof Ref && this.xref) {\n      return this.xref.fetch(value, this.suppressEncryption);\n    }\n    return value;\n  }\n  async getAsync(key1, key2, key3) {\n    let value = this._map[key1];\n    if (value === undefined && key2 !== undefined) {\n      value = this._map[key2];\n      if (value === undefined && key3 !== undefined) {\n        value = this._map[key3];\n      }\n    }\n    if (value instanceof Ref && this.xref) {\n      return this.xref.fetchAsync(value, this.suppressEncryption);\n    }\n    return value;\n  }\n  getArray(key1, key2, key3) {\n    let value = this._map[key1];\n    if (value === undefined && key2 !== undefined) {\n      value = this._map[key2];\n      if (value === undefined && key3 !== undefined) {\n        value = this._map[key3];\n      }\n    }\n    if (value instanceof Ref && this.xref) {\n      value = this.xref.fetch(value, this.suppressEncryption);\n    }\n    if (Array.isArray(value)) {\n      value = value.slice();\n      for (let i = 0, ii = value.length; i < ii; i++) {\n        if (value[i] instanceof Ref && this.xref) {\n          value[i] = this.xref.fetch(value[i], this.suppressEncryption);\n        }\n      }\n    }\n    return value;\n  }\n  getRaw(key) {\n    return this._map[key];\n  }\n  getKeys() {\n    return Object.keys(this._map);\n  }\n  getRawValues() {\n    return Object.values(this._map);\n  }\n  set(key, value) {\n    this._map[key] = value;\n  }\n  has(key) {\n    return this._map[key] !== undefined;\n  }\n  forEach(callback) {\n    for (const key in this._map) {\n      callback(key, this.get(key));\n    }\n  }\n  static get empty() {\n    const emptyDict = new Dict(null);\n    emptyDict.set = (key, value) => {\n      unreachable(\"Should not call `set` on the empty dictionary.\");\n    };\n    return shadow(this, \"empty\", emptyDict);\n  }\n  static merge({\n    xref,\n    dictArray,\n    mergeSubDicts = false\n  }) {\n    const mergedDict = new Dict(xref),\n      properties = new Map();\n    for (const dict of dictArray) {\n      if (!(dict instanceof Dict)) {\n        continue;\n      }\n      for (const [key, value] of Object.entries(dict._map)) {\n        let property = properties.get(key);\n        if (property === undefined) {\n          property = [];\n          properties.set(key, property);\n        } else if (!mergeSubDicts || !(value instanceof Dict)) {\n          continue;\n        }\n        property.push(value);\n      }\n    }\n    for (const [name, values] of properties) {\n      if (values.length === 1 || !(values[0] instanceof Dict)) {\n        mergedDict._map[name] = values[0];\n        continue;\n      }\n      const subDict = new Dict(xref);\n      for (const dict of values) {\n        for (const [key, value] of Object.entries(dict._map)) {\n          if (subDict._map[key] === undefined) {\n            subDict._map[key] = value;\n          }\n        }\n      }\n      if (subDict.size > 0) {\n        mergedDict._map[name] = subDict;\n      }\n    }\n    properties.clear();\n    return mergedDict.size > 0 ? mergedDict : Dict.empty;\n  }\n  clone() {\n    const dict = new Dict(this.xref);\n    for (const key of this.getKeys()) {\n      dict.set(key, this.getRaw(key));\n    }\n    return dict;\n  }\n}\nclass Ref {\n  constructor(num, gen) {\n    this.num = num;\n    this.gen = gen;\n  }\n  toString() {\n    if (this.gen === 0) {\n      return `${this.num}R`;\n    }\n    return `${this.num}R${this.gen}`;\n  }\n  static fromString(str) {\n    const ref = RefCache[str];\n    if (ref) {\n      return ref;\n    }\n    const m = /^(\\d+)R(\\d*)$/.exec(str);\n    if (!m || m[1] === \"0\") {\n      return null;\n    }\n    return RefCache[str] = new Ref(parseInt(m[1]), !m[2] ? 0 : parseInt(m[2]));\n  }\n  static get(num, gen) {\n    const key = gen === 0 ? `${num}R` : `${num}R${gen}`;\n    return RefCache[key] ||= new Ref(num, gen);\n  }\n}\nclass RefSet {\n  constructor(parent = null) {\n    this._set = new Set(parent?._set);\n  }\n  has(ref) {\n    return this._set.has(ref.toString());\n  }\n  put(ref) {\n    this._set.add(ref.toString());\n  }\n  remove(ref) {\n    this._set.delete(ref.toString());\n  }\n  [Symbol.iterator]() {\n    return this._set.values();\n  }\n  clear() {\n    this._set.clear();\n  }\n}\nclass RefSetCache {\n  constructor() {\n    this._map = new Map();\n  }\n  get size() {\n    return this._map.size;\n  }\n  get(ref) {\n    return this._map.get(ref.toString());\n  }\n  has(ref) {\n    return this._map.has(ref.toString());\n  }\n  put(ref, obj) {\n    this._map.set(ref.toString(), obj);\n  }\n  putAlias(ref, aliasRef) {\n    this._map.set(ref.toString(), this.get(aliasRef));\n  }\n  [Symbol.iterator]() {\n    return this._map.values();\n  }\n  clear() {\n    this._map.clear();\n  }\n  *items() {\n    for (const [ref, value] of this._map) {\n      yield [Ref.fromString(ref), value];\n    }\n  }\n}\nfunction isName(v, name) {\n  return v instanceof Name && (name === undefined || v.name === name);\n}\nfunction isCmd(v, cmd) {\n  return v instanceof Cmd && (cmd === undefined || v.cmd === cmd);\n}\nfunction isDict(v, type) {\n  return v instanceof Dict && (type === undefined || isName(v.get(\"Type\"), type));\n}\nfunction isRefsEqual(v1, v2) {\n  return v1.num === v2.num && v1.gen === v2.gen;\n}\n\n;// CONCATENATED MODULE: ./src/core/base_stream.js\n\nclass BaseStream {\n  constructor() {\n    if (this.constructor === BaseStream) {\n      unreachable(\"Cannot initialize BaseStream.\");\n    }\n  }\n  get length() {\n    unreachable(\"Abstract getter `length` accessed\");\n  }\n  get isEmpty() {\n    unreachable(\"Abstract getter `isEmpty` accessed\");\n  }\n  get isDataLoaded() {\n    return shadow(this, \"isDataLoaded\", true);\n  }\n  getByte() {\n    unreachable(\"Abstract method `getByte` called\");\n  }\n  getBytes(length) {\n    unreachable(\"Abstract method `getBytes` called\");\n  }\n  peekByte() {\n    const peekedByte = this.getByte();\n    if (peekedByte !== -1) {\n      this.pos--;\n    }\n    return peekedByte;\n  }\n  peekBytes(length) {\n    const bytes = this.getBytes(length);\n    this.pos -= bytes.length;\n    return bytes;\n  }\n  getUint16() {\n    const b0 = this.getByte();\n    const b1 = this.getByte();\n    if (b0 === -1 || b1 === -1) {\n      return -1;\n    }\n    return (b0 << 8) + b1;\n  }\n  getInt32() {\n    const b0 = this.getByte();\n    const b1 = this.getByte();\n    const b2 = this.getByte();\n    const b3 = this.getByte();\n    return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;\n  }\n  getByteRange(begin, end) {\n    unreachable(\"Abstract method `getByteRange` called\");\n  }\n  getString(length) {\n    return bytesToString(this.getBytes(length));\n  }\n  skip(n) {\n    this.pos += n || 1;\n  }\n  reset() {\n    unreachable(\"Abstract method `reset` called\");\n  }\n  moveStart() {\n    unreachable(\"Abstract method `moveStart` called\");\n  }\n  makeSubStream(start, length, dict = null) {\n    unreachable(\"Abstract method `makeSubStream` called\");\n  }\n  getBaseStreams() {\n    return null;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/core_utils.js\n\n\n\nconst PDF_VERSION_REGEXP = /^[1-9]\\.\\d$/;\nfunction getLookupTableFactory(initializer) {\n  let lookup;\n  return function () {\n    if (initializer) {\n      lookup = Object.create(null);\n      initializer(lookup);\n      initializer = null;\n    }\n    return lookup;\n  };\n}\nclass MissingDataException extends BaseException {\n  constructor(begin, end) {\n    super(`Missing data [${begin}, ${end})`, \"MissingDataException\");\n    this.begin = begin;\n    this.end = end;\n  }\n}\nclass ParserEOFException extends BaseException {\n  constructor(msg) {\n    super(msg, \"ParserEOFException\");\n  }\n}\nclass XRefEntryException extends BaseException {\n  constructor(msg) {\n    super(msg, \"XRefEntryException\");\n  }\n}\nclass XRefParseException extends BaseException {\n  constructor(msg) {\n    super(msg, \"XRefParseException\");\n  }\n}\nfunction arrayBuffersToBytes(arr) {\n  const length = arr.length;\n  if (length === 0) {\n    return new Uint8Array(0);\n  }\n  if (length === 1) {\n    return new Uint8Array(arr[0]);\n  }\n  let dataLength = 0;\n  for (let i = 0; i < length; i++) {\n    dataLength += arr[i].byteLength;\n  }\n  const data = new Uint8Array(dataLength);\n  let pos = 0;\n  for (let i = 0; i < length; i++) {\n    const item = new Uint8Array(arr[i]);\n    data.set(item, pos);\n    pos += item.byteLength;\n  }\n  return data;\n}\nfunction getInheritableProperty({\n  dict,\n  key,\n  getArray = false,\n  stopWhenFound = true\n}) {\n  let values;\n  const visited = new RefSet();\n  while (dict instanceof Dict && !(dict.objId && visited.has(dict.objId))) {\n    if (dict.objId) {\n      visited.put(dict.objId);\n    }\n    const value = getArray ? dict.getArray(key) : dict.get(key);\n    if (value !== undefined) {\n      if (stopWhenFound) {\n        return value;\n      }\n      (values ||= []).push(value);\n    }\n    dict = dict.get(\"Parent\");\n  }\n  return values;\n}\nconst ROMAN_NUMBER_MAP = [\"\", \"C\", \"CC\", \"CCC\", \"CD\", \"D\", \"DC\", \"DCC\", \"DCCC\", \"CM\", \"\", \"X\", \"XX\", \"XXX\", \"XL\", \"L\", \"LX\", \"LXX\", \"LXXX\", \"XC\", \"\", \"I\", \"II\", \"III\", \"IV\", \"V\", \"VI\", \"VII\", \"VIII\", \"IX\"];\nfunction toRomanNumerals(number, lowerCase = false) {\n  assert(Number.isInteger(number) && number > 0, \"The number should be a positive integer.\");\n  const romanBuf = [];\n  let pos;\n  while (number >= 1000) {\n    number -= 1000;\n    romanBuf.push(\"M\");\n  }\n  pos = number / 100 | 0;\n  number %= 100;\n  romanBuf.push(ROMAN_NUMBER_MAP[pos]);\n  pos = number / 10 | 0;\n  number %= 10;\n  romanBuf.push(ROMAN_NUMBER_MAP[10 + pos]);\n  romanBuf.push(ROMAN_NUMBER_MAP[20 + number]);\n  const romanStr = romanBuf.join(\"\");\n  return lowerCase ? romanStr.toLowerCase() : romanStr;\n}\nfunction log2(x) {\n  if (x <= 0) {\n    return 0;\n  }\n  return Math.ceil(Math.log2(x));\n}\nfunction readInt8(data, offset) {\n  return data[offset] << 24 >> 24;\n}\nfunction readUint16(data, offset) {\n  return data[offset] << 8 | data[offset + 1];\n}\nfunction readUint32(data, offset) {\n  return (data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]) >>> 0;\n}\nfunction isWhiteSpace(ch) {\n  return ch === 0x20 || ch === 0x09 || ch === 0x0d || ch === 0x0a;\n}\nfunction isNumberArray(arr, len) {\n  return Array.isArray(arr) && (len === null || arr.length === len) && arr.every(x => typeof x === \"number\");\n}\nfunction parseXFAPath(path) {\n  const positionPattern = /(.+)\\[(\\d+)\\]$/;\n  return path.split(\".\").map(component => {\n    const m = component.match(positionPattern);\n    if (m) {\n      return {\n        name: m[1],\n        pos: parseInt(m[2], 10)\n      };\n    }\n    return {\n      name: component,\n      pos: 0\n    };\n  });\n}\nfunction escapePDFName(str) {\n  const buffer = [];\n  let start = 0;\n  for (let i = 0, ii = str.length; i < ii; i++) {\n    const char = str.charCodeAt(i);\n    if (char < 0x21 || char > 0x7e || char === 0x23 || char === 0x28 || char === 0x29 || char === 0x3c || char === 0x3e || char === 0x5b || char === 0x5d || char === 0x7b || char === 0x7d || char === 0x2f || char === 0x25) {\n      if (start < i) {\n        buffer.push(str.substring(start, i));\n      }\n      buffer.push(`#${char.toString(16)}`);\n      start = i + 1;\n    }\n  }\n  if (buffer.length === 0) {\n    return str;\n  }\n  if (start < str.length) {\n    buffer.push(str.substring(start, str.length));\n  }\n  return buffer.join(\"\");\n}\nfunction escapeString(str) {\n  return str.replaceAll(/([()\\\\\\n\\r])/g, match => {\n    if (match === \"\\n\") {\n      return \"\\\\n\";\n    } else if (match === \"\\r\") {\n      return \"\\\\r\";\n    }\n    return `\\\\${match}`;\n  });\n}\nfunction _collectJS(entry, xref, list, parents) {\n  if (!entry) {\n    return;\n  }\n  let parent = null;\n  if (entry instanceof Ref) {\n    if (parents.has(entry)) {\n      return;\n    }\n    parent = entry;\n    parents.put(parent);\n    entry = xref.fetch(entry);\n  }\n  if (Array.isArray(entry)) {\n    for (const element of entry) {\n      _collectJS(element, xref, list, parents);\n    }\n  } else if (entry instanceof Dict) {\n    if (isName(entry.get(\"S\"), \"JavaScript\")) {\n      const js = entry.get(\"JS\");\n      let code;\n      if (js instanceof BaseStream) {\n        code = js.getString();\n      } else if (typeof js === \"string\") {\n        code = js;\n      }\n      code &&= stringToPDFString(code).replaceAll(\"\\x00\", \"\");\n      if (code) {\n        list.push(code);\n      }\n    }\n    _collectJS(entry.getRaw(\"Next\"), xref, list, parents);\n  }\n  if (parent) {\n    parents.remove(parent);\n  }\n}\nfunction collectActions(xref, dict, eventType) {\n  const actions = Object.create(null);\n  const additionalActionsDicts = getInheritableProperty({\n    dict,\n    key: \"AA\",\n    stopWhenFound: false\n  });\n  if (additionalActionsDicts) {\n    for (let i = additionalActionsDicts.length - 1; i >= 0; i--) {\n      const additionalActions = additionalActionsDicts[i];\n      if (!(additionalActions instanceof Dict)) {\n        continue;\n      }\n      for (const key of additionalActions.getKeys()) {\n        const action = eventType[key];\n        if (!action) {\n          continue;\n        }\n        const actionDict = additionalActions.getRaw(key);\n        const parents = new RefSet();\n        const list = [];\n        _collectJS(actionDict, xref, list, parents);\n        if (list.length > 0) {\n          actions[action] = list;\n        }\n      }\n    }\n  }\n  if (dict.has(\"A\")) {\n    const actionDict = dict.get(\"A\");\n    const parents = new RefSet();\n    const list = [];\n    _collectJS(actionDict, xref, list, parents);\n    if (list.length > 0) {\n      actions.Action = list;\n    }\n  }\n  return objectSize(actions) > 0 ? actions : null;\n}\nconst XMLEntities = {\n  0x3c: \"&lt;\",\n  0x3e: \"&gt;\",\n  0x26: \"&amp;\",\n  0x22: \"&quot;\",\n  0x27: \"&apos;\"\n};\nfunction* codePointIter(str) {\n  for (let i = 0, ii = str.length; i < ii; i++) {\n    const char = str.codePointAt(i);\n    if (char > 0xd7ff && (char < 0xe000 || char > 0xfffd)) {\n      i++;\n    }\n    yield char;\n  }\n}\nfunction encodeToXmlString(str) {\n  const buffer = [];\n  let start = 0;\n  for (let i = 0, ii = str.length; i < ii; i++) {\n    const char = str.codePointAt(i);\n    if (0x20 <= char && char <= 0x7e) {\n      const entity = XMLEntities[char];\n      if (entity) {\n        if (start < i) {\n          buffer.push(str.substring(start, i));\n        }\n        buffer.push(entity);\n        start = i + 1;\n      }\n    } else {\n      if (start < i) {\n        buffer.push(str.substring(start, i));\n      }\n      buffer.push(`&#x${char.toString(16).toUpperCase()};`);\n      if (char > 0xd7ff && (char < 0xe000 || char > 0xfffd)) {\n        i++;\n      }\n      start = i + 1;\n    }\n  }\n  if (buffer.length === 0) {\n    return str;\n  }\n  if (start < str.length) {\n    buffer.push(str.substring(start, str.length));\n  }\n  return buffer.join(\"\");\n}\nfunction validateFontName(fontFamily, mustWarn = false) {\n  const m = /^(\"|').*(\"|')$/.exec(fontFamily);\n  if (m && m[1] === m[2]) {\n    const re = new RegExp(`[^\\\\\\\\]${m[1]}`);\n    if (re.test(fontFamily.slice(1, -1))) {\n      if (mustWarn) {\n        warn(`FontFamily contains unescaped ${m[1]}: ${fontFamily}.`);\n      }\n      return false;\n    }\n  } else {\n    for (const ident of fontFamily.split(/[ \\t]+/)) {\n      if (/^(\\d|(-(\\d|-)))/.test(ident) || !/^[\\w-\\\\]+$/.test(ident)) {\n        if (mustWarn) {\n          warn(`FontFamily contains invalid <custom-ident>: ${fontFamily}.`);\n        }\n        return false;\n      }\n    }\n  }\n  return true;\n}\nfunction validateCSSFont(cssFontInfo) {\n  const DEFAULT_CSS_FONT_OBLIQUE = \"14\";\n  const DEFAULT_CSS_FONT_WEIGHT = \"400\";\n  const CSS_FONT_WEIGHT_VALUES = new Set([\"100\", \"200\", \"300\", \"400\", \"500\", \"600\", \"700\", \"800\", \"900\", \"1000\", \"normal\", \"bold\", \"bolder\", \"lighter\"]);\n  const {\n    fontFamily,\n    fontWeight,\n    italicAngle\n  } = cssFontInfo;\n  if (!validateFontName(fontFamily, true)) {\n    return false;\n  }\n  const weight = fontWeight ? fontWeight.toString() : \"\";\n  cssFontInfo.fontWeight = CSS_FONT_WEIGHT_VALUES.has(weight) ? weight : DEFAULT_CSS_FONT_WEIGHT;\n  const angle = parseFloat(italicAngle);\n  cssFontInfo.italicAngle = isNaN(angle) || angle < -90 || angle > 90 ? DEFAULT_CSS_FONT_OBLIQUE : italicAngle.toString();\n  return true;\n}\nfunction recoverJsURL(str) {\n  const URL_OPEN_METHODS = [\"app.launchURL\", \"window.open\", \"xfa.host.gotoURL\"];\n  const regex = new RegExp(\"^\\\\s*(\" + URL_OPEN_METHODS.join(\"|\").replaceAll(\".\", \"\\\\.\") + \")\\\\((?:'|\\\")([^'\\\"]*)(?:'|\\\")(?:,\\\\s*(\\\\w+)\\\\)|\\\\))\", \"i\");\n  const jsUrl = regex.exec(str);\n  if (jsUrl?.[2]) {\n    const url = jsUrl[2];\n    let newWindow = false;\n    if (jsUrl[3] === \"true\" && jsUrl[1] === \"app.launchURL\") {\n      newWindow = true;\n    }\n    return {\n      url,\n      newWindow\n    };\n  }\n  return null;\n}\nfunction numberToString(value) {\n  if (Number.isInteger(value)) {\n    return value.toString();\n  }\n  const roundedValue = Math.round(value * 100);\n  if (roundedValue % 100 === 0) {\n    return (roundedValue / 100).toString();\n  }\n  if (roundedValue % 10 === 0) {\n    return value.toFixed(1);\n  }\n  return value.toFixed(2);\n}\nfunction getNewAnnotationsMap(annotationStorage) {\n  if (!annotationStorage) {\n    return null;\n  }\n  const newAnnotationsByPage = new Map();\n  for (const [key, value] of annotationStorage) {\n    if (!key.startsWith(AnnotationEditorPrefix)) {\n      continue;\n    }\n    let annotations = newAnnotationsByPage.get(value.pageIndex);\n    if (!annotations) {\n      annotations = [];\n      newAnnotationsByPage.set(value.pageIndex, annotations);\n    }\n    annotations.push(value);\n  }\n  return newAnnotationsByPage.size > 0 ? newAnnotationsByPage : null;\n}\nfunction isAscii(str) {\n  return /^[\\x00-\\x7F]*$/.test(str);\n}\nfunction stringToUTF16HexString(str) {\n  const buf = [];\n  for (let i = 0, ii = str.length; i < ii; i++) {\n    const char = str.charCodeAt(i);\n    buf.push((char >> 8 & 0xff).toString(16).padStart(2, \"0\"), (char & 0xff).toString(16).padStart(2, \"0\"));\n  }\n  return buf.join(\"\");\n}\nfunction stringToUTF16String(str, bigEndian = false) {\n  const buf = [];\n  if (bigEndian) {\n    buf.push(\"\\xFE\\xFF\");\n  }\n  for (let i = 0, ii = str.length; i < ii; i++) {\n    const char = str.charCodeAt(i);\n    buf.push(String.fromCharCode(char >> 8 & 0xff), String.fromCharCode(char & 0xff));\n  }\n  return buf.join(\"\");\n}\nfunction getRotationMatrix(rotation, width, height) {\n  switch (rotation) {\n    case 90:\n      return [0, 1, -1, 0, width, 0];\n    case 180:\n      return [-1, 0, 0, -1, width, height];\n    case 270:\n      return [0, -1, 1, 0, 0, height];\n    default:\n      throw new Error(\"Invalid rotation\");\n  }\n}\nfunction getSizeInBytes(x) {\n  return Math.ceil(Math.ceil(Math.log2(1 + x)) / 8);\n}\n\n;// CONCATENATED MODULE: ./src/core/stream.js\n\n\nclass Stream extends BaseStream {\n  constructor(arrayBuffer, start, length, dict) {\n    super();\n    this.bytes = arrayBuffer instanceof Uint8Array ? arrayBuffer : new Uint8Array(arrayBuffer);\n    this.start = start || 0;\n    this.pos = this.start;\n    this.end = start + length || this.bytes.length;\n    this.dict = dict;\n  }\n  get length() {\n    return this.end - this.start;\n  }\n  get isEmpty() {\n    return this.length === 0;\n  }\n  getByte() {\n    if (this.pos >= this.end) {\n      return -1;\n    }\n    return this.bytes[this.pos++];\n  }\n  getBytes(length) {\n    const bytes = this.bytes;\n    const pos = this.pos;\n    const strEnd = this.end;\n    if (!length) {\n      return bytes.subarray(pos, strEnd);\n    }\n    let end = pos + length;\n    if (end > strEnd) {\n      end = strEnd;\n    }\n    this.pos = end;\n    return bytes.subarray(pos, end);\n  }\n  getByteRange(begin, end) {\n    if (begin < 0) {\n      begin = 0;\n    }\n    if (end > this.end) {\n      end = this.end;\n    }\n    return this.bytes.subarray(begin, end);\n  }\n  reset() {\n    this.pos = this.start;\n  }\n  moveStart() {\n    this.start = this.pos;\n  }\n  makeSubStream(start, length, dict = null) {\n    return new Stream(this.bytes.buffer, start, length, dict);\n  }\n}\nclass StringStream extends Stream {\n  constructor(str) {\n    super(stringToBytes(str));\n  }\n}\nclass NullStream extends Stream {\n  constructor() {\n    super(new Uint8Array(0));\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/chunked_stream.js\n\n\n\nclass ChunkedStream extends Stream {\n  constructor(length, chunkSize, manager) {\n    super(new Uint8Array(length), 0, length, null);\n    this.chunkSize = chunkSize;\n    this._loadedChunks = new Set();\n    this.numChunks = Math.ceil(length / chunkSize);\n    this.manager = manager;\n    this.progressiveDataLength = 0;\n    this.lastSuccessfulEnsureByteChunk = -1;\n  }\n  getMissingChunks() {\n    const chunks = [];\n    for (let chunk = 0, n = this.numChunks; chunk < n; ++chunk) {\n      if (!this._loadedChunks.has(chunk)) {\n        chunks.push(chunk);\n      }\n    }\n    return chunks;\n  }\n  get numChunksLoaded() {\n    return this._loadedChunks.size;\n  }\n  get isDataLoaded() {\n    return this.numChunksLoaded === this.numChunks;\n  }\n  onReceiveData(begin, chunk) {\n    const chunkSize = this.chunkSize;\n    if (begin % chunkSize !== 0) {\n      throw new Error(`Bad begin offset: ${begin}`);\n    }\n    const end = begin + chunk.byteLength;\n    if (end % chunkSize !== 0 && end !== this.bytes.length) {\n      throw new Error(`Bad end offset: ${end}`);\n    }\n    this.bytes.set(new Uint8Array(chunk), begin);\n    const beginChunk = Math.floor(begin / chunkSize);\n    const endChunk = Math.floor((end - 1) / chunkSize) + 1;\n    for (let curChunk = beginChunk; curChunk < endChunk; ++curChunk) {\n      this._loadedChunks.add(curChunk);\n    }\n  }\n  onReceiveProgressiveData(data) {\n    let position = this.progressiveDataLength;\n    const beginChunk = Math.floor(position / this.chunkSize);\n    this.bytes.set(new Uint8Array(data), position);\n    position += data.byteLength;\n    this.progressiveDataLength = position;\n    const endChunk = position >= this.end ? this.numChunks : Math.floor(position / this.chunkSize);\n    for (let curChunk = beginChunk; curChunk < endChunk; ++curChunk) {\n      this._loadedChunks.add(curChunk);\n    }\n  }\n  ensureByte(pos) {\n    if (pos < this.progressiveDataLength) {\n      return;\n    }\n    const chunk = Math.floor(pos / this.chunkSize);\n    if (chunk > this.numChunks) {\n      return;\n    }\n    if (chunk === this.lastSuccessfulEnsureByteChunk) {\n      return;\n    }\n    if (!this._loadedChunks.has(chunk)) {\n      throw new MissingDataException(pos, pos + 1);\n    }\n    this.lastSuccessfulEnsureByteChunk = chunk;\n  }\n  ensureRange(begin, end) {\n    if (begin >= end) {\n      return;\n    }\n    if (end <= this.progressiveDataLength) {\n      return;\n    }\n    const beginChunk = Math.floor(begin / this.chunkSize);\n    if (beginChunk > this.numChunks) {\n      return;\n    }\n    const endChunk = Math.min(Math.floor((end - 1) / this.chunkSize) + 1, this.numChunks);\n    for (let chunk = beginChunk; chunk < endChunk; ++chunk) {\n      if (!this._loadedChunks.has(chunk)) {\n        throw new MissingDataException(begin, end);\n      }\n    }\n  }\n  nextEmptyChunk(beginChunk) {\n    const numChunks = this.numChunks;\n    for (let i = 0; i < numChunks; ++i) {\n      const chunk = (beginChunk + i) % numChunks;\n      if (!this._loadedChunks.has(chunk)) {\n        return chunk;\n      }\n    }\n    return null;\n  }\n  hasChunk(chunk) {\n    return this._loadedChunks.has(chunk);\n  }\n  getByte() {\n    const pos = this.pos;\n    if (pos >= this.end) {\n      return -1;\n    }\n    if (pos >= this.progressiveDataLength) {\n      this.ensureByte(pos);\n    }\n    return this.bytes[this.pos++];\n  }\n  getBytes(length) {\n    const bytes = this.bytes;\n    const pos = this.pos;\n    const strEnd = this.end;\n    if (!length) {\n      if (strEnd > this.progressiveDataLength) {\n        this.ensureRange(pos, strEnd);\n      }\n      return bytes.subarray(pos, strEnd);\n    }\n    let end = pos + length;\n    if (end > strEnd) {\n      end = strEnd;\n    }\n    if (end > this.progressiveDataLength) {\n      this.ensureRange(pos, end);\n    }\n    this.pos = end;\n    return bytes.subarray(pos, end);\n  }\n  getByteRange(begin, end) {\n    if (begin < 0) {\n      begin = 0;\n    }\n    if (end > this.end) {\n      end = this.end;\n    }\n    if (end > this.progressiveDataLength) {\n      this.ensureRange(begin, end);\n    }\n    return this.bytes.subarray(begin, end);\n  }\n  makeSubStream(start, length, dict = null) {\n    if (length) {\n      if (start + length > this.progressiveDataLength) {\n        this.ensureRange(start, start + length);\n      }\n    } else if (start >= this.progressiveDataLength) {\n      this.ensureByte(start);\n    }\n    function ChunkedStreamSubstream() {}\n    ChunkedStreamSubstream.prototype = Object.create(this);\n    ChunkedStreamSubstream.prototype.getMissingChunks = function () {\n      const chunkSize = this.chunkSize;\n      const beginChunk = Math.floor(this.start / chunkSize);\n      const endChunk = Math.floor((this.end - 1) / chunkSize) + 1;\n      const missingChunks = [];\n      for (let chunk = beginChunk; chunk < endChunk; ++chunk) {\n        if (!this._loadedChunks.has(chunk)) {\n          missingChunks.push(chunk);\n        }\n      }\n      return missingChunks;\n    };\n    Object.defineProperty(ChunkedStreamSubstream.prototype, \"isDataLoaded\", {\n      get() {\n        if (this.numChunksLoaded === this.numChunks) {\n          return true;\n        }\n        return this.getMissingChunks().length === 0;\n      },\n      configurable: true\n    });\n    const subStream = new ChunkedStreamSubstream();\n    subStream.pos = subStream.start = start;\n    subStream.end = start + length || this.end;\n    subStream.dict = dict;\n    return subStream;\n  }\n  getBaseStreams() {\n    return [this];\n  }\n}\nclass ChunkedStreamManager {\n  constructor(pdfNetworkStream, args) {\n    this.length = args.length;\n    this.chunkSize = args.rangeChunkSize;\n    this.stream = new ChunkedStream(this.length, this.chunkSize, this);\n    this.pdfNetworkStream = pdfNetworkStream;\n    this.disableAutoFetch = args.disableAutoFetch;\n    this.msgHandler = args.msgHandler;\n    this.currRequestId = 0;\n    this._chunksNeededByRequest = new Map();\n    this._requestsByChunk = new Map();\n    this._promisesByRequest = new Map();\n    this.progressiveDataLength = 0;\n    this.aborted = false;\n    this._loadedStreamCapability = Promise.withResolvers();\n  }\n  sendRequest(begin, end) {\n    const rangeReader = this.pdfNetworkStream.getRangeReader(begin, end);\n    if (!rangeReader.isStreamingSupported) {\n      rangeReader.onProgress = this.onProgress.bind(this);\n    }\n    let chunks = [],\n      loaded = 0;\n    return new Promise((resolve, reject) => {\n      const readChunk = ({\n        value,\n        done\n      }) => {\n        try {\n          if (done) {\n            const chunkData = arrayBuffersToBytes(chunks);\n            chunks = null;\n            resolve(chunkData);\n            return;\n          }\n          loaded += value.byteLength;\n          if (rangeReader.isStreamingSupported) {\n            this.onProgress({\n              loaded\n            });\n          }\n          chunks.push(value);\n          rangeReader.read().then(readChunk, reject);\n        } catch (e) {\n          reject(e);\n        }\n      };\n      rangeReader.read().then(readChunk, reject);\n    }).then(data => {\n      if (this.aborted) {\n        return;\n      }\n      this.onReceiveData({\n        chunk: data,\n        begin\n      });\n    });\n  }\n  requestAllChunks(noFetch = false) {\n    if (!noFetch) {\n      const missingChunks = this.stream.getMissingChunks();\n      this._requestChunks(missingChunks);\n    }\n    return this._loadedStreamCapability.promise;\n  }\n  _requestChunks(chunks) {\n    const requestId = this.currRequestId++;\n    const chunksNeeded = new Set();\n    this._chunksNeededByRequest.set(requestId, chunksNeeded);\n    for (const chunk of chunks) {\n      if (!this.stream.hasChunk(chunk)) {\n        chunksNeeded.add(chunk);\n      }\n    }\n    if (chunksNeeded.size === 0) {\n      return Promise.resolve();\n    }\n    const capability = Promise.withResolvers();\n    this._promisesByRequest.set(requestId, capability);\n    const chunksToRequest = [];\n    for (const chunk of chunksNeeded) {\n      let requestIds = this._requestsByChunk.get(chunk);\n      if (!requestIds) {\n        requestIds = [];\n        this._requestsByChunk.set(chunk, requestIds);\n        chunksToRequest.push(chunk);\n      }\n      requestIds.push(requestId);\n    }\n    if (chunksToRequest.length > 0) {\n      const groupedChunksToRequest = this.groupChunks(chunksToRequest);\n      for (const groupedChunk of groupedChunksToRequest) {\n        const begin = groupedChunk.beginChunk * this.chunkSize;\n        const end = Math.min(groupedChunk.endChunk * this.chunkSize, this.length);\n        this.sendRequest(begin, end).catch(capability.reject);\n      }\n    }\n    return capability.promise.catch(reason => {\n      if (this.aborted) {\n        return;\n      }\n      throw reason;\n    });\n  }\n  getStream() {\n    return this.stream;\n  }\n  requestRange(begin, end) {\n    end = Math.min(end, this.length);\n    const beginChunk = this.getBeginChunk(begin);\n    const endChunk = this.getEndChunk(end);\n    const chunks = [];\n    for (let chunk = beginChunk; chunk < endChunk; ++chunk) {\n      chunks.push(chunk);\n    }\n    return this._requestChunks(chunks);\n  }\n  requestRanges(ranges = []) {\n    const chunksToRequest = [];\n    for (const range of ranges) {\n      const beginChunk = this.getBeginChunk(range.begin);\n      const endChunk = this.getEndChunk(range.end);\n      for (let chunk = beginChunk; chunk < endChunk; ++chunk) {\n        if (!chunksToRequest.includes(chunk)) {\n          chunksToRequest.push(chunk);\n        }\n      }\n    }\n    chunksToRequest.sort(function (a, b) {\n      return a - b;\n    });\n    return this._requestChunks(chunksToRequest);\n  }\n  groupChunks(chunks) {\n    const groupedChunks = [];\n    let beginChunk = -1;\n    let prevChunk = -1;\n    for (let i = 0, ii = chunks.length; i < ii; ++i) {\n      const chunk = chunks[i];\n      if (beginChunk < 0) {\n        beginChunk = chunk;\n      }\n      if (prevChunk >= 0 && prevChunk + 1 !== chunk) {\n        groupedChunks.push({\n          beginChunk,\n          endChunk: prevChunk + 1\n        });\n        beginChunk = chunk;\n      }\n      if (i + 1 === chunks.length) {\n        groupedChunks.push({\n          beginChunk,\n          endChunk: chunk + 1\n        });\n      }\n      prevChunk = chunk;\n    }\n    return groupedChunks;\n  }\n  onProgress(args) {\n    this.msgHandler.send(\"DocProgress\", {\n      loaded: this.stream.numChunksLoaded * this.chunkSize + args.loaded,\n      total: this.length\n    });\n  }\n  onReceiveData(args) {\n    const chunk = args.chunk;\n    const isProgressive = args.begin === undefined;\n    const begin = isProgressive ? this.progressiveDataLength : args.begin;\n    const end = begin + chunk.byteLength;\n    const beginChunk = Math.floor(begin / this.chunkSize);\n    const endChunk = end < this.length ? Math.floor(end / this.chunkSize) : Math.ceil(end / this.chunkSize);\n    if (isProgressive) {\n      this.stream.onReceiveProgressiveData(chunk);\n      this.progressiveDataLength = end;\n    } else {\n      this.stream.onReceiveData(begin, chunk);\n    }\n    if (this.stream.isDataLoaded) {\n      this._loadedStreamCapability.resolve(this.stream);\n    }\n    const loadedRequests = [];\n    for (let curChunk = beginChunk; curChunk < endChunk; ++curChunk) {\n      const requestIds = this._requestsByChunk.get(curChunk);\n      if (!requestIds) {\n        continue;\n      }\n      this._requestsByChunk.delete(curChunk);\n      for (const requestId of requestIds) {\n        const chunksNeeded = this._chunksNeededByRequest.get(requestId);\n        if (chunksNeeded.has(curChunk)) {\n          chunksNeeded.delete(curChunk);\n        }\n        if (chunksNeeded.size > 0) {\n          continue;\n        }\n        loadedRequests.push(requestId);\n      }\n    }\n    if (!this.disableAutoFetch && this._requestsByChunk.size === 0) {\n      let nextEmptyChunk;\n      if (this.stream.numChunksLoaded === 1) {\n        const lastChunk = this.stream.numChunks - 1;\n        if (!this.stream.hasChunk(lastChunk)) {\n          nextEmptyChunk = lastChunk;\n        }\n      } else {\n        nextEmptyChunk = this.stream.nextEmptyChunk(endChunk);\n      }\n      if (Number.isInteger(nextEmptyChunk)) {\n        this._requestChunks([nextEmptyChunk]);\n      }\n    }\n    for (const requestId of loadedRequests) {\n      const capability = this._promisesByRequest.get(requestId);\n      this._promisesByRequest.delete(requestId);\n      capability.resolve();\n    }\n    this.msgHandler.send(\"DocProgress\", {\n      loaded: this.stream.numChunksLoaded * this.chunkSize,\n      total: this.length\n    });\n  }\n  onError(err) {\n    this._loadedStreamCapability.reject(err);\n  }\n  getBeginChunk(begin) {\n    return Math.floor(begin / this.chunkSize);\n  }\n  getEndChunk(end) {\n    return Math.floor((end - 1) / this.chunkSize) + 1;\n  }\n  abort(reason) {\n    this.aborted = true;\n    this.pdfNetworkStream?.cancelAllRequests(reason);\n    for (const capability of this._promisesByRequest.values()) {\n      capability.reject(reason);\n    }\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/colorspace.js\n\n\n\n\nfunction resizeRgbImage(src, dest, w1, h1, w2, h2, alpha01) {\n  const COMPONENTS = 3;\n  alpha01 = alpha01 !== 1 ? 0 : alpha01;\n  const xRatio = w1 / w2;\n  const yRatio = h1 / h2;\n  let newIndex = 0,\n    oldIndex;\n  const xScaled = new Uint16Array(w2);\n  const w1Scanline = w1 * COMPONENTS;\n  for (let i = 0; i < w2; i++) {\n    xScaled[i] = Math.floor(i * xRatio) * COMPONENTS;\n  }\n  for (let i = 0; i < h2; i++) {\n    const py = Math.floor(i * yRatio) * w1Scanline;\n    for (let j = 0; j < w2; j++) {\n      oldIndex = py + xScaled[j];\n      dest[newIndex++] = src[oldIndex++];\n      dest[newIndex++] = src[oldIndex++];\n      dest[newIndex++] = src[oldIndex++];\n      newIndex += alpha01;\n    }\n  }\n}\nclass ColorSpace {\n  constructor(name, numComps) {\n    if (this.constructor === ColorSpace) {\n      unreachable(\"Cannot initialize ColorSpace.\");\n    }\n    this.name = name;\n    this.numComps = numComps;\n  }\n  getRgb(src, srcOffset) {\n    const rgb = new Uint8ClampedArray(3);\n    this.getRgbItem(src, srcOffset, rgb, 0);\n    return rgb;\n  }\n  getRgbItem(src, srcOffset, dest, destOffset) {\n    unreachable(\"Should not call ColorSpace.getRgbItem\");\n  }\n  getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {\n    unreachable(\"Should not call ColorSpace.getRgbBuffer\");\n  }\n  getOutputLength(inputLength, alpha01) {\n    unreachable(\"Should not call ColorSpace.getOutputLength\");\n  }\n  isPassthrough(bits) {\n    return false;\n  }\n  isDefaultDecode(decodeMap, bpc) {\n    return ColorSpace.isDefaultDecode(decodeMap, this.numComps);\n  }\n  fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, bpc, comps, alpha01) {\n    const count = originalWidth * originalHeight;\n    let rgbBuf = null;\n    const numComponentColors = 1 << bpc;\n    const needsResizing = originalHeight !== height || originalWidth !== width;\n    if (this.isPassthrough(bpc)) {\n      rgbBuf = comps;\n    } else if (this.numComps === 1 && count > numComponentColors && this.name !== \"DeviceGray\" && this.name !== \"DeviceRGB\") {\n      const allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : new Uint16Array(numComponentColors);\n      for (let i = 0; i < numComponentColors; i++) {\n        allColors[i] = i;\n      }\n      const colorMap = new Uint8ClampedArray(numComponentColors * 3);\n      this.getRgbBuffer(allColors, 0, numComponentColors, colorMap, 0, bpc, 0);\n      if (!needsResizing) {\n        let destPos = 0;\n        for (let i = 0; i < count; ++i) {\n          const key = comps[i] * 3;\n          dest[destPos++] = colorMap[key];\n          dest[destPos++] = colorMap[key + 1];\n          dest[destPos++] = colorMap[key + 2];\n          destPos += alpha01;\n        }\n      } else {\n        rgbBuf = new Uint8Array(count * 3);\n        let rgbPos = 0;\n        for (let i = 0; i < count; ++i) {\n          const key = comps[i] * 3;\n          rgbBuf[rgbPos++] = colorMap[key];\n          rgbBuf[rgbPos++] = colorMap[key + 1];\n          rgbBuf[rgbPos++] = colorMap[key + 2];\n        }\n      }\n    } else if (!needsResizing) {\n      this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, alpha01);\n    } else {\n      rgbBuf = new Uint8ClampedArray(count * 3);\n      this.getRgbBuffer(comps, 0, count, rgbBuf, 0, bpc, 0);\n    }\n    if (rgbBuf) {\n      if (needsResizing) {\n        resizeRgbImage(rgbBuf, dest, originalWidth, originalHeight, width, height, alpha01);\n      } else {\n        let destPos = 0,\n          rgbPos = 0;\n        for (let i = 0, ii = width * actualHeight; i < ii; i++) {\n          dest[destPos++] = rgbBuf[rgbPos++];\n          dest[destPos++] = rgbBuf[rgbPos++];\n          dest[destPos++] = rgbBuf[rgbPos++];\n          destPos += alpha01;\n        }\n      }\n    }\n  }\n  get usesZeroToOneRange() {\n    return shadow(this, \"usesZeroToOneRange\", true);\n  }\n  static _cache(cacheKey, xref, localColorSpaceCache, parsedColorSpace) {\n    if (!localColorSpaceCache) {\n      throw new Error('ColorSpace._cache - expected \"localColorSpaceCache\" argument.');\n    }\n    if (!parsedColorSpace) {\n      throw new Error('ColorSpace._cache - expected \"parsedColorSpace\" argument.');\n    }\n    let csName, csRef;\n    if (cacheKey instanceof Ref) {\n      csRef = cacheKey;\n      cacheKey = xref.fetch(cacheKey);\n    }\n    if (cacheKey instanceof Name) {\n      csName = cacheKey.name;\n    }\n    if (csName || csRef) {\n      localColorSpaceCache.set(csName, csRef, parsedColorSpace);\n    }\n  }\n  static getCached(cacheKey, xref, localColorSpaceCache) {\n    if (!localColorSpaceCache) {\n      throw new Error('ColorSpace.getCached - expected \"localColorSpaceCache\" argument.');\n    }\n    if (cacheKey instanceof Ref) {\n      const localColorSpace = localColorSpaceCache.getByRef(cacheKey);\n      if (localColorSpace) {\n        return localColorSpace;\n      }\n      try {\n        cacheKey = xref.fetch(cacheKey);\n      } catch (ex) {\n        if (ex instanceof MissingDataException) {\n          throw ex;\n        }\n      }\n    }\n    if (cacheKey instanceof Name) {\n      const localColorSpace = localColorSpaceCache.getByName(cacheKey.name);\n      if (localColorSpace) {\n        return localColorSpace;\n      }\n    }\n    return null;\n  }\n  static async parseAsync({\n    cs,\n    xref,\n    resources = null,\n    pdfFunctionFactory,\n    localColorSpaceCache\n  }) {\n    const parsedColorSpace = this._parse(cs, xref, resources, pdfFunctionFactory);\n    this._cache(cs, xref, localColorSpaceCache, parsedColorSpace);\n    return parsedColorSpace;\n  }\n  static parse({\n    cs,\n    xref,\n    resources = null,\n    pdfFunctionFactory,\n    localColorSpaceCache\n  }) {\n    const cachedColorSpace = this.getCached(cs, xref, localColorSpaceCache);\n    if (cachedColorSpace) {\n      return cachedColorSpace;\n    }\n    const parsedColorSpace = this._parse(cs, xref, resources, pdfFunctionFactory);\n    this._cache(cs, xref, localColorSpaceCache, parsedColorSpace);\n    return parsedColorSpace;\n  }\n  static _parse(cs, xref, resources = null, pdfFunctionFactory) {\n    cs = xref.fetchIfRef(cs);\n    if (cs instanceof Name) {\n      switch (cs.name) {\n        case \"G\":\n        case \"DeviceGray\":\n          return this.singletons.gray;\n        case \"RGB\":\n        case \"DeviceRGB\":\n          return this.singletons.rgb;\n        case \"CMYK\":\n        case \"DeviceCMYK\":\n          return this.singletons.cmyk;\n        case \"Pattern\":\n          return new PatternCS(null);\n        default:\n          if (resources instanceof Dict) {\n            const colorSpaces = resources.get(\"ColorSpace\");\n            if (colorSpaces instanceof Dict) {\n              const resourcesCS = colorSpaces.get(cs.name);\n              if (resourcesCS) {\n                if (resourcesCS instanceof Name) {\n                  return this._parse(resourcesCS, xref, resources, pdfFunctionFactory);\n                }\n                cs = resourcesCS;\n                break;\n              }\n            }\n          }\n          throw new FormatError(`Unrecognized ColorSpace: ${cs.name}`);\n      }\n    }\n    if (Array.isArray(cs)) {\n      const mode = xref.fetchIfRef(cs[0]).name;\n      let params, numComps, baseCS, whitePoint, blackPoint, gamma;\n      switch (mode) {\n        case \"G\":\n        case \"DeviceGray\":\n          return this.singletons.gray;\n        case \"RGB\":\n        case \"DeviceRGB\":\n          return this.singletons.rgb;\n        case \"CMYK\":\n        case \"DeviceCMYK\":\n          return this.singletons.cmyk;\n        case \"CalGray\":\n          params = xref.fetchIfRef(cs[1]);\n          whitePoint = params.getArray(\"WhitePoint\");\n          blackPoint = params.getArray(\"BlackPoint\");\n          gamma = params.get(\"Gamma\");\n          return new CalGrayCS(whitePoint, blackPoint, gamma);\n        case \"CalRGB\":\n          params = xref.fetchIfRef(cs[1]);\n          whitePoint = params.getArray(\"WhitePoint\");\n          blackPoint = params.getArray(\"BlackPoint\");\n          gamma = params.getArray(\"Gamma\");\n          const matrix = params.getArray(\"Matrix\");\n          return new CalRGBCS(whitePoint, blackPoint, gamma, matrix);\n        case \"ICCBased\":\n          const stream = xref.fetchIfRef(cs[1]);\n          const dict = stream.dict;\n          numComps = dict.get(\"N\");\n          const alt = dict.get(\"Alternate\");\n          if (alt) {\n            const altCS = this._parse(alt, xref, resources, pdfFunctionFactory);\n            if (altCS.numComps === numComps) {\n              return altCS;\n            }\n            warn(\"ICCBased color space: Ignoring incorrect /Alternate entry.\");\n          }\n          if (numComps === 1) {\n            return this.singletons.gray;\n          } else if (numComps === 3) {\n            return this.singletons.rgb;\n          } else if (numComps === 4) {\n            return this.singletons.cmyk;\n          }\n          break;\n        case \"Pattern\":\n          baseCS = cs[1] || null;\n          if (baseCS) {\n            baseCS = this._parse(baseCS, xref, resources, pdfFunctionFactory);\n          }\n          return new PatternCS(baseCS);\n        case \"I\":\n        case \"Indexed\":\n          baseCS = this._parse(cs[1], xref, resources, pdfFunctionFactory);\n          const hiVal = xref.fetchIfRef(cs[2]) + 1;\n          const lookup = xref.fetchIfRef(cs[3]);\n          return new IndexedCS(baseCS, hiVal, lookup);\n        case \"Separation\":\n        case \"DeviceN\":\n          const name = xref.fetchIfRef(cs[1]);\n          numComps = Array.isArray(name) ? name.length : 1;\n          baseCS = this._parse(cs[2], xref, resources, pdfFunctionFactory);\n          const tintFn = pdfFunctionFactory.create(cs[3]);\n          return new AlternateCS(numComps, baseCS, tintFn);\n        case \"Lab\":\n          params = xref.fetchIfRef(cs[1]);\n          whitePoint = params.getArray(\"WhitePoint\");\n          blackPoint = params.getArray(\"BlackPoint\");\n          const range = params.getArray(\"Range\");\n          return new LabCS(whitePoint, blackPoint, range);\n        default:\n          throw new FormatError(`Unimplemented ColorSpace object: ${mode}`);\n      }\n    }\n    throw new FormatError(`Unrecognized ColorSpace object: ${cs}`);\n  }\n  static isDefaultDecode(decode, numComps) {\n    if (!Array.isArray(decode)) {\n      return true;\n    }\n    if (numComps * 2 !== decode.length) {\n      warn(\"The decode map is not the correct length\");\n      return true;\n    }\n    for (let i = 0, ii = decode.length; i < ii; i += 2) {\n      if (decode[i] !== 0 || decode[i + 1] !== 1) {\n        return false;\n      }\n    }\n    return true;\n  }\n  static get singletons() {\n    return shadow(this, \"singletons\", {\n      get gray() {\n        return shadow(this, \"gray\", new DeviceGrayCS());\n      },\n      get rgb() {\n        return shadow(this, \"rgb\", new DeviceRgbCS());\n      },\n      get cmyk() {\n        return shadow(this, \"cmyk\", new DeviceCmykCS());\n      }\n    });\n  }\n}\nclass AlternateCS extends ColorSpace {\n  constructor(numComps, base, tintFn) {\n    super(\"Alternate\", numComps);\n    this.base = base;\n    this.tintFn = tintFn;\n    this.tmpBuf = new Float32Array(base.numComps);\n  }\n  getRgbItem(src, srcOffset, dest, destOffset) {\n    const tmpBuf = this.tmpBuf;\n    this.tintFn(src, srcOffset, tmpBuf, 0);\n    this.base.getRgbItem(tmpBuf, 0, dest, destOffset);\n  }\n  getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {\n    const tintFn = this.tintFn;\n    const base = this.base;\n    const scale = 1 / ((1 << bits) - 1);\n    const baseNumComps = base.numComps;\n    const usesZeroToOneRange = base.usesZeroToOneRange;\n    const isPassthrough = (base.isPassthrough(8) || !usesZeroToOneRange) && alpha01 === 0;\n    let pos = isPassthrough ? destOffset : 0;\n    const baseBuf = isPassthrough ? dest : new Uint8ClampedArray(baseNumComps * count);\n    const numComps = this.numComps;\n    const scaled = new Float32Array(numComps);\n    const tinted = new Float32Array(baseNumComps);\n    let i, j;\n    for (i = 0; i < count; i++) {\n      for (j = 0; j < numComps; j++) {\n        scaled[j] = src[srcOffset++] * scale;\n      }\n      tintFn(scaled, 0, tinted, 0);\n      if (usesZeroToOneRange) {\n        for (j = 0; j < baseNumComps; j++) {\n          baseBuf[pos++] = tinted[j] * 255;\n        }\n      } else {\n        base.getRgbItem(tinted, 0, baseBuf, pos);\n        pos += baseNumComps;\n      }\n    }\n    if (!isPassthrough) {\n      base.getRgbBuffer(baseBuf, 0, count, dest, destOffset, 8, alpha01);\n    }\n  }\n  getOutputLength(inputLength, alpha01) {\n    return this.base.getOutputLength(inputLength * this.base.numComps / this.numComps, alpha01);\n  }\n}\nclass PatternCS extends ColorSpace {\n  constructor(baseCS) {\n    super(\"Pattern\", null);\n    this.base = baseCS;\n  }\n  isDefaultDecode(decodeMap, bpc) {\n    unreachable(\"Should not call PatternCS.isDefaultDecode\");\n  }\n}\nclass IndexedCS extends ColorSpace {\n  constructor(base, highVal, lookup) {\n    super(\"Indexed\", 1);\n    this.base = base;\n    this.highVal = highVal;\n    const length = base.numComps * highVal;\n    this.lookup = new Uint8Array(length);\n    if (lookup instanceof BaseStream) {\n      const bytes = lookup.getBytes(length);\n      this.lookup.set(bytes);\n    } else if (typeof lookup === \"string\") {\n      for (let i = 0; i < length; ++i) {\n        this.lookup[i] = lookup.charCodeAt(i) & 0xff;\n      }\n    } else {\n      throw new FormatError(`IndexedCS - unrecognized lookup table: ${lookup}`);\n    }\n  }\n  getRgbItem(src, srcOffset, dest, destOffset) {\n    const numComps = this.base.numComps;\n    const start = src[srcOffset] * numComps;\n    this.base.getRgbBuffer(this.lookup, start, 1, dest, destOffset, 8, 0);\n  }\n  getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {\n    const base = this.base;\n    const numComps = base.numComps;\n    const outputDelta = base.getOutputLength(numComps, alpha01);\n    const lookup = this.lookup;\n    for (let i = 0; i < count; ++i) {\n      const lookupPos = src[srcOffset++] * numComps;\n      base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8, alpha01);\n      destOffset += outputDelta;\n    }\n  }\n  getOutputLength(inputLength, alpha01) {\n    return this.base.getOutputLength(inputLength * this.base.numComps, alpha01);\n  }\n  isDefaultDecode(decodeMap, bpc) {\n    if (!Array.isArray(decodeMap)) {\n      return true;\n    }\n    if (decodeMap.length !== 2) {\n      warn(\"Decode map length is not correct\");\n      return true;\n    }\n    if (!Number.isInteger(bpc) || bpc < 1) {\n      warn(\"Bits per component is not correct\");\n      return true;\n    }\n    return decodeMap[0] === 0 && decodeMap[1] === (1 << bpc) - 1;\n  }\n}\nclass DeviceGrayCS extends ColorSpace {\n  constructor() {\n    super(\"DeviceGray\", 1);\n  }\n  getRgbItem(src, srcOffset, dest, destOffset) {\n    const c = src[srcOffset] * 255;\n    dest[destOffset] = dest[destOffset + 1] = dest[destOffset + 2] = c;\n  }\n  getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {\n    const scale = 255 / ((1 << bits) - 1);\n    let j = srcOffset,\n      q = destOffset;\n    for (let i = 0; i < count; ++i) {\n      const c = scale * src[j++];\n      dest[q++] = c;\n      dest[q++] = c;\n      dest[q++] = c;\n      q += alpha01;\n    }\n  }\n  getOutputLength(inputLength, alpha01) {\n    return inputLength * (3 + alpha01);\n  }\n}\nclass DeviceRgbCS extends ColorSpace {\n  constructor() {\n    super(\"DeviceRGB\", 3);\n  }\n  getRgbItem(src, srcOffset, dest, destOffset) {\n    dest[destOffset] = src[srcOffset] * 255;\n    dest[destOffset + 1] = src[srcOffset + 1] * 255;\n    dest[destOffset + 2] = src[srcOffset + 2] * 255;\n  }\n  getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {\n    if (bits === 8 && alpha01 === 0) {\n      dest.set(src.subarray(srcOffset, srcOffset + count * 3), destOffset);\n      return;\n    }\n    const scale = 255 / ((1 << bits) - 1);\n    let j = srcOffset,\n      q = destOffset;\n    for (let i = 0; i < count; ++i) {\n      dest[q++] = scale * src[j++];\n      dest[q++] = scale * src[j++];\n      dest[q++] = scale * src[j++];\n      q += alpha01;\n    }\n  }\n  getOutputLength(inputLength, alpha01) {\n    return inputLength * (3 + alpha01) / 3 | 0;\n  }\n  isPassthrough(bits) {\n    return bits === 8;\n  }\n}\nclass DeviceCmykCS extends ColorSpace {\n  constructor() {\n    super(\"DeviceCMYK\", 4);\n  }\n  #toRgb(src, srcOffset, srcScale, dest, destOffset) {\n    const c = src[srcOffset] * srcScale;\n    const m = src[srcOffset + 1] * srcScale;\n    const y = src[srcOffset + 2] * srcScale;\n    const k = src[srcOffset + 3] * srcScale;\n    dest[destOffset] = 255 + c * (-4.387332384609988 * c + 54.48615194189176 * m + 18.82290502165302 * y + 212.25662451639585 * k + -285.2331026137004) + m * (1.7149763477362134 * m - 5.6096736904047315 * y + -17.873870861415444 * k - 5.497006427196366) + y * (-2.5217340131683033 * y - 21.248923337353073 * k + 17.5119270841813) + k * (-21.86122147463605 * k - 189.48180835922747);\n    dest[destOffset + 1] = 255 + c * (8.841041422036149 * c + 60.118027045597366 * m + 6.871425592049007 * y + 31.159100130055922 * k + -79.2970844816548) + m * (-15.310361306967817 * m + 17.575251261109482 * y + 131.35250912493976 * k - 190.9453302588951) + y * (4.444339102852739 * y + 9.8632861493405 * k - 24.86741582555878) + k * (-20.737325471181034 * k - 187.80453709719578);\n    dest[destOffset + 2] = 255 + c * (0.8842522430003296 * c + 8.078677503112928 * m + 30.89978309703729 * y - 0.23883238689178934 * k + -14.183576799673286) + m * (10.49593273432072 * m + 63.02378494754052 * y + 50.606957656360734 * k - 112.23884253719248) + y * (0.03296041114873217 * y + 115.60384449646641 * k + -193.58209356861505) + k * (-22.33816807309886 * k - 180.12613974708367);\n  }\n  getRgbItem(src, srcOffset, dest, destOffset) {\n    this.#toRgb(src, srcOffset, 1, dest, destOffset);\n  }\n  getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {\n    const scale = 1 / ((1 << bits) - 1);\n    for (let i = 0; i < count; i++) {\n      this.#toRgb(src, srcOffset, scale, dest, destOffset);\n      srcOffset += 4;\n      destOffset += 3 + alpha01;\n    }\n  }\n  getOutputLength(inputLength, alpha01) {\n    return inputLength / 4 * (3 + alpha01) | 0;\n  }\n}\nclass CalGrayCS extends ColorSpace {\n  constructor(whitePoint, blackPoint, gamma) {\n    super(\"CalGray\", 1);\n    if (!whitePoint) {\n      throw new FormatError(\"WhitePoint missing - required for color space CalGray\");\n    }\n    [this.XW, this.YW, this.ZW] = whitePoint;\n    [this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];\n    this.G = gamma || 1;\n    if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {\n      throw new FormatError(`Invalid WhitePoint components for ${this.name}, no fallback available`);\n    }\n    if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {\n      info(`Invalid BlackPoint for ${this.name}, falling back to default.`);\n      this.XB = this.YB = this.ZB = 0;\n    }\n    if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) {\n      warn(`${this.name}, BlackPoint: XB: ${this.XB}, YB: ${this.YB}, ` + `ZB: ${this.ZB}, only default values are supported.`);\n    }\n    if (this.G < 1) {\n      info(`Invalid Gamma: ${this.G} for ${this.name}, falling back to default.`);\n      this.G = 1;\n    }\n  }\n  #toRgb(src, srcOffset, dest, destOffset, scale) {\n    const A = src[srcOffset] * scale;\n    const AG = A ** this.G;\n    const L = this.YW * AG;\n    const val = Math.max(295.8 * L ** 0.3333333333333333 - 40.8, 0);\n    dest[destOffset] = val;\n    dest[destOffset + 1] = val;\n    dest[destOffset + 2] = val;\n  }\n  getRgbItem(src, srcOffset, dest, destOffset) {\n    this.#toRgb(src, srcOffset, dest, destOffset, 1);\n  }\n  getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {\n    const scale = 1 / ((1 << bits) - 1);\n    for (let i = 0; i < count; ++i) {\n      this.#toRgb(src, srcOffset, dest, destOffset, scale);\n      srcOffset += 1;\n      destOffset += 3 + alpha01;\n    }\n  }\n  getOutputLength(inputLength, alpha01) {\n    return inputLength * (3 + alpha01);\n  }\n}\nclass CalRGBCS extends ColorSpace {\n  static #BRADFORD_SCALE_MATRIX = new Float32Array([0.8951, 0.2664, -0.1614, -0.7502, 1.7135, 0.0367, 0.0389, -0.0685, 1.0296]);\n  static #BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([0.9869929, -0.1470543, 0.1599627, 0.4323053, 0.5183603, 0.0492912, -0.0085287, 0.0400428, 0.9684867]);\n  static #SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([3.2404542, -1.5371385, -0.4985314, -0.9692660, 1.8760108, 0.0415560, 0.0556434, -0.2040259, 1.0572252]);\n  static #FLAT_WHITEPOINT_MATRIX = new Float32Array([1, 1, 1]);\n  static #tempNormalizeMatrix = new Float32Array(3);\n  static #tempConvertMatrix1 = new Float32Array(3);\n  static #tempConvertMatrix2 = new Float32Array(3);\n  static #DECODE_L_CONSTANT = ((8 + 16) / 116) ** 3 / 8.0;\n  constructor(whitePoint, blackPoint, gamma, matrix) {\n    super(\"CalRGB\", 3);\n    if (!whitePoint) {\n      throw new FormatError(\"WhitePoint missing - required for color space CalRGB\");\n    }\n    const [XW, YW, ZW] = this.whitePoint = whitePoint;\n    const [XB, YB, ZB] = this.blackPoint = blackPoint || new Float32Array(3);\n    [this.GR, this.GG, this.GB] = gamma || new Float32Array([1, 1, 1]);\n    [this.MXA, this.MYA, this.MZA, this.MXB, this.MYB, this.MZB, this.MXC, this.MYC, this.MZC] = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]);\n    if (XW < 0 || ZW < 0 || YW !== 1) {\n      throw new FormatError(`Invalid WhitePoint components for ${this.name}, no fallback available`);\n    }\n    if (XB < 0 || YB < 0 || ZB < 0) {\n      info(`Invalid BlackPoint for ${this.name} [${XB}, ${YB}, ${ZB}], ` + \"falling back to default.\");\n      this.blackPoint = new Float32Array(3);\n    }\n    if (this.GR < 0 || this.GG < 0 || this.GB < 0) {\n      info(`Invalid Gamma [${this.GR}, ${this.GG}, ${this.GB}] for ` + `${this.name}, falling back to default.`);\n      this.GR = this.GG = this.GB = 1;\n    }\n  }\n  #matrixProduct(a, b, result) {\n    result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];\n    result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2];\n    result[2] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2];\n  }\n  #toFlat(sourceWhitePoint, LMS, result) {\n    result[0] = LMS[0] * 1 / sourceWhitePoint[0];\n    result[1] = LMS[1] * 1 / sourceWhitePoint[1];\n    result[2] = LMS[2] * 1 / sourceWhitePoint[2];\n  }\n  #toD65(sourceWhitePoint, LMS, result) {\n    const D65X = 0.95047;\n    const D65Y = 1;\n    const D65Z = 1.08883;\n    result[0] = LMS[0] * D65X / sourceWhitePoint[0];\n    result[1] = LMS[1] * D65Y / sourceWhitePoint[1];\n    result[2] = LMS[2] * D65Z / sourceWhitePoint[2];\n  }\n  #sRGBTransferFunction(color) {\n    if (color <= 0.0031308) {\n      return this.#adjustToRange(0, 1, 12.92 * color);\n    }\n    if (color >= 0.99554525) {\n      return 1;\n    }\n    return this.#adjustToRange(0, 1, (1 + 0.055) * color ** (1 / 2.4) - 0.055);\n  }\n  #adjustToRange(min, max, value) {\n    return Math.max(min, Math.min(max, value));\n  }\n  #decodeL(L) {\n    if (L < 0) {\n      return -this.#decodeL(-L);\n    }\n    if (L > 8.0) {\n      return ((L + 16) / 116) ** 3;\n    }\n    return L * CalRGBCS.#DECODE_L_CONSTANT;\n  }\n  #compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) {\n    if (sourceBlackPoint[0] === 0 && sourceBlackPoint[1] === 0 && sourceBlackPoint[2] === 0) {\n      result[0] = XYZ_Flat[0];\n      result[1] = XYZ_Flat[1];\n      result[2] = XYZ_Flat[2];\n      return;\n    }\n    const zeroDecodeL = this.#decodeL(0);\n    const X_DST = zeroDecodeL;\n    const X_SRC = this.#decodeL(sourceBlackPoint[0]);\n    const Y_DST = zeroDecodeL;\n    const Y_SRC = this.#decodeL(sourceBlackPoint[1]);\n    const Z_DST = zeroDecodeL;\n    const Z_SRC = this.#decodeL(sourceBlackPoint[2]);\n    const X_Scale = (1 - X_DST) / (1 - X_SRC);\n    const X_Offset = 1 - X_Scale;\n    const Y_Scale = (1 - Y_DST) / (1 - Y_SRC);\n    const Y_Offset = 1 - Y_Scale;\n    const Z_Scale = (1 - Z_DST) / (1 - Z_SRC);\n    const Z_Offset = 1 - Z_Scale;\n    result[0] = XYZ_Flat[0] * X_Scale + X_Offset;\n    result[1] = XYZ_Flat[1] * Y_Scale + Y_Offset;\n    result[2] = XYZ_Flat[2] * Z_Scale + Z_Offset;\n  }\n  #normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result) {\n    if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) {\n      result[0] = XYZ_In[0];\n      result[1] = XYZ_In[1];\n      result[2] = XYZ_In[2];\n      return;\n    }\n    const LMS = result;\n    this.#matrixProduct(CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);\n    const LMS_Flat = CalRGBCS.#tempNormalizeMatrix;\n    this.#toFlat(sourceWhitePoint, LMS, LMS_Flat);\n    this.#matrixProduct(CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX, LMS_Flat, result);\n  }\n  #normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result) {\n    const LMS = result;\n    this.#matrixProduct(CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS);\n    const LMS_D65 = CalRGBCS.#tempNormalizeMatrix;\n    this.#toD65(sourceWhitePoint, LMS, LMS_D65);\n    this.#matrixProduct(CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX, LMS_D65, result);\n  }\n  #toRgb(src, srcOffset, dest, destOffset, scale) {\n    const A = this.#adjustToRange(0, 1, src[srcOffset] * scale);\n    const B = this.#adjustToRange(0, 1, src[srcOffset + 1] * scale);\n    const C = this.#adjustToRange(0, 1, src[srcOffset + 2] * scale);\n    const AGR = A === 1 ? 1 : A ** this.GR;\n    const BGG = B === 1 ? 1 : B ** this.GG;\n    const CGB = C === 1 ? 1 : C ** this.GB;\n    const X = this.MXA * AGR + this.MXB * BGG + this.MXC * CGB;\n    const Y = this.MYA * AGR + this.MYB * BGG + this.MYC * CGB;\n    const Z = this.MZA * AGR + this.MZB * BGG + this.MZC * CGB;\n    const XYZ = CalRGBCS.#tempConvertMatrix1;\n    XYZ[0] = X;\n    XYZ[1] = Y;\n    XYZ[2] = Z;\n    const XYZ_Flat = CalRGBCS.#tempConvertMatrix2;\n    this.#normalizeWhitePointToFlat(this.whitePoint, XYZ, XYZ_Flat);\n    const XYZ_Black = CalRGBCS.#tempConvertMatrix1;\n    this.#compensateBlackPoint(this.blackPoint, XYZ_Flat, XYZ_Black);\n    const XYZ_D65 = CalRGBCS.#tempConvertMatrix2;\n    this.#normalizeWhitePointToD65(CalRGBCS.#FLAT_WHITEPOINT_MATRIX, XYZ_Black, XYZ_D65);\n    const SRGB = CalRGBCS.#tempConvertMatrix1;\n    this.#matrixProduct(CalRGBCS.#SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB);\n    dest[destOffset] = this.#sRGBTransferFunction(SRGB[0]) * 255;\n    dest[destOffset + 1] = this.#sRGBTransferFunction(SRGB[1]) * 255;\n    dest[destOffset + 2] = this.#sRGBTransferFunction(SRGB[2]) * 255;\n  }\n  getRgbItem(src, srcOffset, dest, destOffset) {\n    this.#toRgb(src, srcOffset, dest, destOffset, 1);\n  }\n  getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {\n    const scale = 1 / ((1 << bits) - 1);\n    for (let i = 0; i < count; ++i) {\n      this.#toRgb(src, srcOffset, dest, destOffset, scale);\n      srcOffset += 3;\n      destOffset += 3 + alpha01;\n    }\n  }\n  getOutputLength(inputLength, alpha01) {\n    return inputLength * (3 + alpha01) / 3 | 0;\n  }\n}\nclass LabCS extends ColorSpace {\n  constructor(whitePoint, blackPoint, range) {\n    super(\"Lab\", 3);\n    if (!whitePoint) {\n      throw new FormatError(\"WhitePoint missing - required for color space Lab\");\n    }\n    [this.XW, this.YW, this.ZW] = whitePoint;\n    [this.amin, this.amax, this.bmin, this.bmax] = range || [-100, 100, -100, 100];\n    [this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0];\n    if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {\n      throw new FormatError(\"Invalid WhitePoint components, no fallback available\");\n    }\n    if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {\n      info(\"Invalid BlackPoint, falling back to default\");\n      this.XB = this.YB = this.ZB = 0;\n    }\n    if (this.amin > this.amax || this.bmin > this.bmax) {\n      info(\"Invalid Range, falling back to defaults\");\n      this.amin = -100;\n      this.amax = 100;\n      this.bmin = -100;\n      this.bmax = 100;\n    }\n  }\n  #fn_g(x) {\n    return x >= 6 / 29 ? x ** 3 : 108 / 841 * (x - 4 / 29);\n  }\n  #decode(value, high1, low2, high2) {\n    return low2 + value * (high2 - low2) / high1;\n  }\n  #toRgb(src, srcOffset, maxVal, dest, destOffset) {\n    let Ls = src[srcOffset];\n    let as = src[srcOffset + 1];\n    let bs = src[srcOffset + 2];\n    if (maxVal !== false) {\n      Ls = this.#decode(Ls, maxVal, 0, 100);\n      as = this.#decode(as, maxVal, this.amin, this.amax);\n      bs = this.#decode(bs, maxVal, this.bmin, this.bmax);\n    }\n    if (as > this.amax) {\n      as = this.amax;\n    } else if (as < this.amin) {\n      as = this.amin;\n    }\n    if (bs > this.bmax) {\n      bs = this.bmax;\n    } else if (bs < this.bmin) {\n      bs = this.bmin;\n    }\n    const M = (Ls + 16) / 116;\n    const L = M + as / 500;\n    const N = M - bs / 200;\n    const X = this.XW * this.#fn_g(L);\n    const Y = this.YW * this.#fn_g(M);\n    const Z = this.ZW * this.#fn_g(N);\n    let r, g, b;\n    if (this.ZW < 1) {\n      r = X * 3.1339 + Y * -1.617 + Z * -0.4906;\n      g = X * -0.9785 + Y * 1.916 + Z * 0.0333;\n      b = X * 0.072 + Y * -0.229 + Z * 1.4057;\n    } else {\n      r = X * 3.2406 + Y * -1.5372 + Z * -0.4986;\n      g = X * -0.9689 + Y * 1.8758 + Z * 0.0415;\n      b = X * 0.0557 + Y * -0.204 + Z * 1.057;\n    }\n    dest[destOffset] = Math.sqrt(r) * 255;\n    dest[destOffset + 1] = Math.sqrt(g) * 255;\n    dest[destOffset + 2] = Math.sqrt(b) * 255;\n  }\n  getRgbItem(src, srcOffset, dest, destOffset) {\n    this.#toRgb(src, srcOffset, false, dest, destOffset);\n  }\n  getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {\n    const maxVal = (1 << bits) - 1;\n    for (let i = 0; i < count; i++) {\n      this.#toRgb(src, srcOffset, maxVal, dest, destOffset);\n      srcOffset += 3;\n      destOffset += 3 + alpha01;\n    }\n  }\n  getOutputLength(inputLength, alpha01) {\n    return inputLength * (3 + alpha01) / 3 | 0;\n  }\n  isDefaultDecode(decodeMap, bpc) {\n    return true;\n  }\n  get usesZeroToOneRange() {\n    return shadow(this, \"usesZeroToOneRange\", false);\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/binary_cmap.js\n\nfunction hexToInt(a, size) {\n  let n = 0;\n  for (let i = 0; i <= size; i++) {\n    n = n << 8 | a[i];\n  }\n  return n >>> 0;\n}\nfunction hexToStr(a, size) {\n  if (size === 1) {\n    return String.fromCharCode(a[0], a[1]);\n  }\n  if (size === 3) {\n    return String.fromCharCode(a[0], a[1], a[2], a[3]);\n  }\n  return String.fromCharCode(...a.subarray(0, size + 1));\n}\nfunction addHex(a, b, size) {\n  let c = 0;\n  for (let i = size; i >= 0; i--) {\n    c += a[i] + b[i];\n    a[i] = c & 255;\n    c >>= 8;\n  }\n}\nfunction incHex(a, size) {\n  let c = 1;\n  for (let i = size; i >= 0 && c > 0; i--) {\n    c += a[i];\n    a[i] = c & 255;\n    c >>= 8;\n  }\n}\nconst MAX_NUM_SIZE = 16;\nconst MAX_ENCODED_NUM_SIZE = 19;\nclass BinaryCMapStream {\n  constructor(data) {\n    this.buffer = data;\n    this.pos = 0;\n    this.end = data.length;\n    this.tmpBuf = new Uint8Array(MAX_ENCODED_NUM_SIZE);\n  }\n  readByte() {\n    if (this.pos >= this.end) {\n      return -1;\n    }\n    return this.buffer[this.pos++];\n  }\n  readNumber() {\n    let n = 0;\n    let last;\n    do {\n      const b = this.readByte();\n      if (b < 0) {\n        throw new FormatError(\"unexpected EOF in bcmap\");\n      }\n      last = !(b & 0x80);\n      n = n << 7 | b & 0x7f;\n    } while (!last);\n    return n;\n  }\n  readSigned() {\n    const n = this.readNumber();\n    return n & 1 ? ~(n >>> 1) : n >>> 1;\n  }\n  readHex(num, size) {\n    num.set(this.buffer.subarray(this.pos, this.pos + size + 1));\n    this.pos += size + 1;\n  }\n  readHexNumber(num, size) {\n    let last;\n    const stack = this.tmpBuf;\n    let sp = 0;\n    do {\n      const b = this.readByte();\n      if (b < 0) {\n        throw new FormatError(\"unexpected EOF in bcmap\");\n      }\n      last = !(b & 0x80);\n      stack[sp++] = b & 0x7f;\n    } while (!last);\n    let i = size,\n      buffer = 0,\n      bufferSize = 0;\n    while (i >= 0) {\n      while (bufferSize < 8 && stack.length > 0) {\n        buffer |= stack[--sp] << bufferSize;\n        bufferSize += 7;\n      }\n      num[i] = buffer & 255;\n      i--;\n      buffer >>= 8;\n      bufferSize -= 8;\n    }\n  }\n  readHexSigned(num, size) {\n    this.readHexNumber(num, size);\n    const sign = num[size] & 1 ? 255 : 0;\n    let c = 0;\n    for (let i = 0; i <= size; i++) {\n      c = (c & 1) << 8 | num[i];\n      num[i] = c >> 1 ^ sign;\n    }\n  }\n  readString() {\n    const len = this.readNumber(),\n      buf = new Array(len);\n    for (let i = 0; i < len; i++) {\n      buf[i] = this.readNumber();\n    }\n    return String.fromCharCode(...buf);\n  }\n}\nclass BinaryCMapReader {\n  async process(data, cMap, extend) {\n    const stream = new BinaryCMapStream(data);\n    const header = stream.readByte();\n    cMap.vertical = !!(header & 1);\n    let useCMap = null;\n    const start = new Uint8Array(MAX_NUM_SIZE);\n    const end = new Uint8Array(MAX_NUM_SIZE);\n    const char = new Uint8Array(MAX_NUM_SIZE);\n    const charCode = new Uint8Array(MAX_NUM_SIZE);\n    const tmp = new Uint8Array(MAX_NUM_SIZE);\n    let code;\n    let b;\n    while ((b = stream.readByte()) >= 0) {\n      const type = b >> 5;\n      if (type === 7) {\n        switch (b & 0x1f) {\n          case 0:\n            stream.readString();\n            break;\n          case 1:\n            useCMap = stream.readString();\n            break;\n        }\n        continue;\n      }\n      const sequence = !!(b & 0x10);\n      const dataSize = b & 15;\n      if (dataSize + 1 > MAX_NUM_SIZE) {\n        throw new Error(\"BinaryCMapReader.process: Invalid dataSize.\");\n      }\n      const ucs2DataSize = 1;\n      const subitemsCount = stream.readNumber();\n      switch (type) {\n        case 0:\n          stream.readHex(start, dataSize);\n          stream.readHexNumber(end, dataSize);\n          addHex(end, start, dataSize);\n          cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize), hexToInt(end, dataSize));\n          for (let i = 1; i < subitemsCount; i++) {\n            incHex(end, dataSize);\n            stream.readHexNumber(start, dataSize);\n            addHex(start, end, dataSize);\n            stream.readHexNumber(end, dataSize);\n            addHex(end, start, dataSize);\n            cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize), hexToInt(end, dataSize));\n          }\n          break;\n        case 1:\n          stream.readHex(start, dataSize);\n          stream.readHexNumber(end, dataSize);\n          addHex(end, start, dataSize);\n          stream.readNumber();\n          for (let i = 1; i < subitemsCount; i++) {\n            incHex(end, dataSize);\n            stream.readHexNumber(start, dataSize);\n            addHex(start, end, dataSize);\n            stream.readHexNumber(end, dataSize);\n            addHex(end, start, dataSize);\n            stream.readNumber();\n          }\n          break;\n        case 2:\n          stream.readHex(char, dataSize);\n          code = stream.readNumber();\n          cMap.mapOne(hexToInt(char, dataSize), code);\n          for (let i = 1; i < subitemsCount; i++) {\n            incHex(char, dataSize);\n            if (!sequence) {\n              stream.readHexNumber(tmp, dataSize);\n              addHex(char, tmp, dataSize);\n            }\n            code = stream.readSigned() + (code + 1);\n            cMap.mapOne(hexToInt(char, dataSize), code);\n          }\n          break;\n        case 3:\n          stream.readHex(start, dataSize);\n          stream.readHexNumber(end, dataSize);\n          addHex(end, start, dataSize);\n          code = stream.readNumber();\n          cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize), code);\n          for (let i = 1; i < subitemsCount; i++) {\n            incHex(end, dataSize);\n            if (!sequence) {\n              stream.readHexNumber(start, dataSize);\n              addHex(start, end, dataSize);\n            } else {\n              start.set(end);\n            }\n            stream.readHexNumber(end, dataSize);\n            addHex(end, start, dataSize);\n            code = stream.readNumber();\n            cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize), code);\n          }\n          break;\n        case 4:\n          stream.readHex(char, ucs2DataSize);\n          stream.readHex(charCode, dataSize);\n          cMap.mapOne(hexToInt(char, ucs2DataSize), hexToStr(charCode, dataSize));\n          for (let i = 1; i < subitemsCount; i++) {\n            incHex(char, ucs2DataSize);\n            if (!sequence) {\n              stream.readHexNumber(tmp, ucs2DataSize);\n              addHex(char, tmp, ucs2DataSize);\n            }\n            incHex(charCode, dataSize);\n            stream.readHexSigned(tmp, dataSize);\n            addHex(charCode, tmp, dataSize);\n            cMap.mapOne(hexToInt(char, ucs2DataSize), hexToStr(charCode, dataSize));\n          }\n          break;\n        case 5:\n          stream.readHex(start, ucs2DataSize);\n          stream.readHexNumber(end, ucs2DataSize);\n          addHex(end, start, ucs2DataSize);\n          stream.readHex(charCode, dataSize);\n          cMap.mapBfRange(hexToInt(start, ucs2DataSize), hexToInt(end, ucs2DataSize), hexToStr(charCode, dataSize));\n          for (let i = 1; i < subitemsCount; i++) {\n            incHex(end, ucs2DataSize);\n            if (!sequence) {\n              stream.readHexNumber(start, ucs2DataSize);\n              addHex(start, end, ucs2DataSize);\n            } else {\n              start.set(end);\n            }\n            stream.readHexNumber(end, ucs2DataSize);\n            addHex(end, start, ucs2DataSize);\n            stream.readHex(charCode, dataSize);\n            cMap.mapBfRange(hexToInt(start, ucs2DataSize), hexToInt(end, ucs2DataSize), hexToStr(charCode, dataSize));\n          }\n          break;\n        default:\n          throw new Error(`BinaryCMapReader.process - unknown type: ${type}`);\n      }\n    }\n    if (useCMap) {\n      return extend(useCMap);\n    }\n    return cMap;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/decode_stream.js\n\n\nconst emptyBuffer = new Uint8Array(0);\nclass DecodeStream extends BaseStream {\n  constructor(maybeMinBufferLength) {\n    super();\n    this._rawMinBufferLength = maybeMinBufferLength || 0;\n    this.pos = 0;\n    this.bufferLength = 0;\n    this.eof = false;\n    this.buffer = emptyBuffer;\n    this.minBufferLength = 512;\n    if (maybeMinBufferLength) {\n      while (this.minBufferLength < maybeMinBufferLength) {\n        this.minBufferLength *= 2;\n      }\n    }\n  }\n  get isEmpty() {\n    while (!this.eof && this.bufferLength === 0) {\n      this.readBlock();\n    }\n    return this.bufferLength === 0;\n  }\n  ensureBuffer(requested) {\n    const buffer = this.buffer;\n    if (requested <= buffer.byteLength) {\n      return buffer;\n    }\n    let size = this.minBufferLength;\n    while (size < requested) {\n      size *= 2;\n    }\n    const buffer2 = new Uint8Array(size);\n    buffer2.set(buffer);\n    return this.buffer = buffer2;\n  }\n  getByte() {\n    const pos = this.pos;\n    while (this.bufferLength <= pos) {\n      if (this.eof) {\n        return -1;\n      }\n      this.readBlock();\n    }\n    return this.buffer[this.pos++];\n  }\n  getBytes(length, ignoreColorSpace = false) {\n    const pos = this.pos;\n    let end;\n    if (length) {\n      this.ensureBuffer(pos + length);\n      end = pos + length;\n      while (!this.eof && this.bufferLength < end) {\n        this.readBlock(ignoreColorSpace);\n      }\n      const bufEnd = this.bufferLength;\n      if (end > bufEnd) {\n        end = bufEnd;\n      }\n    } else {\n      while (!this.eof) {\n        this.readBlock(ignoreColorSpace);\n      }\n      end = this.bufferLength;\n    }\n    this.pos = end;\n    return this.buffer.subarray(pos, end);\n  }\n  reset() {\n    this.pos = 0;\n  }\n  makeSubStream(start, length, dict = null) {\n    if (length === undefined) {\n      while (!this.eof) {\n        this.readBlock();\n      }\n    } else {\n      const end = start + length;\n      while (this.bufferLength <= end && !this.eof) {\n        this.readBlock();\n      }\n    }\n    return new Stream(this.buffer, start, length, dict);\n  }\n  getBaseStreams() {\n    return this.str ? this.str.getBaseStreams() : null;\n  }\n}\nclass StreamsSequenceStream extends DecodeStream {\n  constructor(streams, onError = null) {\n    let maybeLength = 0;\n    for (const stream of streams) {\n      maybeLength += stream instanceof DecodeStream ? stream._rawMinBufferLength : stream.length;\n    }\n    super(maybeLength);\n    this.streams = streams;\n    this._onError = onError;\n  }\n  readBlock() {\n    const streams = this.streams;\n    if (streams.length === 0) {\n      this.eof = true;\n      return;\n    }\n    const stream = streams.shift();\n    let chunk;\n    try {\n      chunk = stream.getBytes();\n    } catch (reason) {\n      if (this._onError) {\n        this._onError(reason, stream.dict?.objId);\n        return;\n      }\n      throw reason;\n    }\n    const bufferLength = this.bufferLength;\n    const newLength = bufferLength + chunk.length;\n    const buffer = this.ensureBuffer(newLength);\n    buffer.set(chunk, bufferLength);\n    this.bufferLength = newLength;\n  }\n  getBaseStreams() {\n    const baseStreamsBuf = [];\n    for (const stream of this.streams) {\n      const baseStreams = stream.getBaseStreams();\n      if (baseStreams) {\n        baseStreamsBuf.push(...baseStreams);\n      }\n    }\n    return baseStreamsBuf.length > 0 ? baseStreamsBuf : null;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/ascii_85_stream.js\n\n\nclass Ascii85Stream extends DecodeStream {\n  constructor(str, maybeLength) {\n    if (maybeLength) {\n      maybeLength *= 0.8;\n    }\n    super(maybeLength);\n    this.str = str;\n    this.dict = str.dict;\n    this.input = new Uint8Array(5);\n  }\n  readBlock() {\n    const TILDA_CHAR = 0x7e;\n    const Z_LOWER_CHAR = 0x7a;\n    const EOF = -1;\n    const str = this.str;\n    let c = str.getByte();\n    while (isWhiteSpace(c)) {\n      c = str.getByte();\n    }\n    if (c === EOF || c === TILDA_CHAR) {\n      this.eof = true;\n      return;\n    }\n    const bufferLength = this.bufferLength;\n    let buffer, i;\n    if (c === Z_LOWER_CHAR) {\n      buffer = this.ensureBuffer(bufferLength + 4);\n      for (i = 0; i < 4; ++i) {\n        buffer[bufferLength + i] = 0;\n      }\n      this.bufferLength += 4;\n    } else {\n      const input = this.input;\n      input[0] = c;\n      for (i = 1; i < 5; ++i) {\n        c = str.getByte();\n        while (isWhiteSpace(c)) {\n          c = str.getByte();\n        }\n        input[i] = c;\n        if (c === EOF || c === TILDA_CHAR) {\n          break;\n        }\n      }\n      buffer = this.ensureBuffer(bufferLength + i - 1);\n      this.bufferLength += i - 1;\n      if (i < 5) {\n        for (; i < 5; ++i) {\n          input[i] = 0x21 + 84;\n        }\n        this.eof = true;\n      }\n      let t = 0;\n      for (i = 0; i < 5; ++i) {\n        t = t * 85 + (input[i] - 0x21);\n      }\n      for (i = 3; i >= 0; --i) {\n        buffer[bufferLength + i] = t & 0xff;\n        t >>= 8;\n      }\n    }\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/ascii_hex_stream.js\n\nclass AsciiHexStream extends DecodeStream {\n  constructor(str, maybeLength) {\n    if (maybeLength) {\n      maybeLength *= 0.5;\n    }\n    super(maybeLength);\n    this.str = str;\n    this.dict = str.dict;\n    this.firstDigit = -1;\n  }\n  readBlock() {\n    const UPSTREAM_BLOCK_SIZE = 8000;\n    const bytes = this.str.getBytes(UPSTREAM_BLOCK_SIZE);\n    if (!bytes.length) {\n      this.eof = true;\n      return;\n    }\n    const maxDecodeLength = bytes.length + 1 >> 1;\n    const buffer = this.ensureBuffer(this.bufferLength + maxDecodeLength);\n    let bufferLength = this.bufferLength;\n    let firstDigit = this.firstDigit;\n    for (const ch of bytes) {\n      let digit;\n      if (ch >= 0x30 && ch <= 0x39) {\n        digit = ch & 0x0f;\n      } else if (ch >= 0x41 && ch <= 0x46 || ch >= 0x61 && ch <= 0x66) {\n        digit = (ch & 0x0f) + 9;\n      } else if (ch === 0x3e) {\n        this.eof = true;\n        break;\n      } else {\n        continue;\n      }\n      if (firstDigit < 0) {\n        firstDigit = digit;\n      } else {\n        buffer[bufferLength++] = firstDigit << 4 | digit;\n        firstDigit = -1;\n      }\n    }\n    if (firstDigit >= 0 && this.eof) {\n      buffer[bufferLength++] = firstDigit << 4;\n      firstDigit = -1;\n    }\n    this.firstDigit = firstDigit;\n    this.bufferLength = bufferLength;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/ccitt.js\n\nconst ccittEOL = -2;\nconst ccittEOF = -1;\nconst twoDimPass = 0;\nconst twoDimHoriz = 1;\nconst twoDimVert0 = 2;\nconst twoDimVertR1 = 3;\nconst twoDimVertL1 = 4;\nconst twoDimVertR2 = 5;\nconst twoDimVertL2 = 6;\nconst twoDimVertR3 = 7;\nconst twoDimVertL3 = 8;\nconst twoDimTable = [[-1, -1], [-1, -1], [7, twoDimVertL3], [7, twoDimVertR3], [6, twoDimVertL2], [6, twoDimVertL2], [6, twoDimVertR2], [6, twoDimVertR2], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0]];\nconst whiteTable1 = [[-1, -1], [12, ccittEOL], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [11, 1792], [11, 1792], [12, 1984], [12, 2048], [12, 2112], [12, 2176], [12, 2240], [12, 2304], [11, 1856], [11, 1856], [11, 1920], [11, 1920], [12, 2368], [12, 2432], [12, 2496], [12, 2560]];\nconst whiteTable2 = [[-1, -1], [-1, -1], [-1, -1], [-1, -1], [8, 29], [8, 29], [8, 30], [8, 30], [8, 45], [8, 45], [8, 46], [8, 46], [7, 22], [7, 22], [7, 22], [7, 22], [7, 23], [7, 23], [7, 23], [7, 23], [8, 47], [8, 47], [8, 48], [8, 48], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [7, 20], [7, 20], [7, 20], [7, 20], [8, 33], [8, 33], [8, 34], [8, 34], [8, 35], [8, 35], [8, 36], [8, 36], [8, 37], [8, 37], [8, 38], [8, 38], [7, 19], [7, 19], [7, 19], [7, 19], [8, 31], [8, 31], [8, 32], [8, 32], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [8, 53], [8, 53], [8, 54], [8, 54], [7, 26], [7, 26], [7, 26], [7, 26], [8, 39], [8, 39], [8, 40], [8, 40], [8, 41], [8, 41], [8, 42], [8, 42], [8, 43], [8, 43], [8, 44], [8, 44], [7, 21], [7, 21], [7, 21], [7, 21], [7, 28], [7, 28], [7, 28], [7, 28], [8, 61], [8, 61], [8, 62], [8, 62], [8, 63], [8, 63], [8, 0], [8, 0], [8, 320], [8, 320], [8, 384], [8, 384], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [7, 27], [7, 27], [7, 27], [7, 27], [8, 59], [8, 59], [8, 60], [8, 60], [9, 1472], [9, 1536], [9, 1600], [9, 1728], [7, 18], [7, 18], [7, 18], [7, 18], [7, 24], [7, 24], [7, 24], [7, 24], [8, 49], [8, 49], [8, 50], [8, 50], [8, 51], [8, 51], [8, 52], [8, 52], [7, 25], [7, 25], [7, 25], [7, 25], [8, 55], [8, 55], [8, 56], [8, 56], [8, 57], [8, 57], [8, 58], [8, 58], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [8, 448], [8, 448], [8, 512], [8, 512], [9, 704], [9, 768], [8, 640], [8, 640], [8, 576], [8, 576], [9, 832], [9, 896], [9, 960], [9, 1024], [9, 1088], [9, 1152], [9, 1216], [9, 1280], [9, 1344], [9, 1408], [7, 256], [7, 256], [7, 256], [7, 256], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [6, 16], [6, 16], [6, 16], [6, 16], [6, 16], [6, 16], [6, 16], [6, 16], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7]];\nconst blackTable1 = [[-1, -1], [-1, -1], [12, ccittEOL], [12, ccittEOL], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [11, 1792], [11, 1792], [11, 1792], [11, 1792], [12, 1984], [12, 1984], [12, 2048], [12, 2048], [12, 2112], [12, 2112], [12, 2176], [12, 2176], [12, 2240], [12, 2240], [12, 2304], [12, 2304], [11, 1856], [11, 1856], [11, 1856], [11, 1856], [11, 1920], [11, 1920], [11, 1920], [11, 1920], [12, 2368], [12, 2368], [12, 2432], [12, 2432], [12, 2496], [12, 2496], [12, 2560], [12, 2560], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [12, 52], [12, 52], [13, 640], [13, 704], [13, 768], [13, 832], [12, 55], [12, 55], [12, 56], [12, 56], [13, 1280], [13, 1344], [13, 1408], [13, 1472], [12, 59], [12, 59], [12, 60], [12, 60], [13, 1536], [13, 1600], [11, 24], [11, 24], [11, 24], [11, 24], [11, 25], [11, 25], [11, 25], [11, 25], [13, 1664], [13, 1728], [12, 320], [12, 320], [12, 384], [12, 384], [12, 448], [12, 448], [13, 512], [13, 576], [12, 53], [12, 53], [12, 54], [12, 54], [13, 896], [13, 960], [13, 1024], [13, 1088], [13, 1152], [13, 1216], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64]];\nconst blackTable2 = [[8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [11, 23], [11, 23], [12, 50], [12, 51], [12, 44], [12, 45], [12, 46], [12, 47], [12, 57], [12, 58], [12, 61], [12, 256], [10, 16], [10, 16], [10, 16], [10, 16], [10, 17], [10, 17], [10, 17], [10, 17], [12, 48], [12, 49], [12, 62], [12, 63], [12, 30], [12, 31], [12, 32], [12, 33], [12, 40], [12, 41], [11, 22], [11, 22], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [9, 15], [9, 15], [9, 15], [9, 15], [9, 15], [9, 15], [9, 15], [9, 15], [12, 128], [12, 192], [12, 26], [12, 27], [12, 28], [12, 29], [11, 19], [11, 19], [11, 20], [11, 20], [12, 34], [12, 35], [12, 36], [12, 37], [12, 38], [12, 39], [11, 21], [11, 21], [12, 42], [12, 43], [10, 0], [10, 0], [10, 0], [10, 0], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12]];\nconst blackTable3 = [[-1, -1], [-1, -1], [-1, -1], [-1, -1], [6, 9], [6, 8], [5, 7], [5, 7], [4, 6], [4, 6], [4, 6], [4, 6], [4, 5], [4, 5], [4, 5], [4, 5], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2]];\nclass CCITTFaxDecoder {\n  constructor(source, options = {}) {\n    if (!source || typeof source.next !== \"function\") {\n      throw new Error('CCITTFaxDecoder - invalid \"source\" parameter.');\n    }\n    this.source = source;\n    this.eof = false;\n    this.encoding = options.K || 0;\n    this.eoline = options.EndOfLine || false;\n    this.byteAlign = options.EncodedByteAlign || false;\n    this.columns = options.Columns || 1728;\n    this.rows = options.Rows || 0;\n    this.eoblock = options.EndOfBlock ?? true;\n    this.black = options.BlackIs1 || false;\n    this.codingLine = new Uint32Array(this.columns + 1);\n    this.refLine = new Uint32Array(this.columns + 2);\n    this.codingLine[0] = this.columns;\n    this.codingPos = 0;\n    this.row = 0;\n    this.nextLine2D = this.encoding < 0;\n    this.inputBits = 0;\n    this.inputBuf = 0;\n    this.outputBits = 0;\n    this.rowsDone = false;\n    let code1;\n    while ((code1 = this._lookBits(12)) === 0) {\n      this._eatBits(1);\n    }\n    if (code1 === 1) {\n      this._eatBits(12);\n    }\n    if (this.encoding > 0) {\n      this.nextLine2D = !this._lookBits(1);\n      this._eatBits(1);\n    }\n  }\n  readNextChar() {\n    if (this.eof) {\n      return -1;\n    }\n    const refLine = this.refLine;\n    const codingLine = this.codingLine;\n    const columns = this.columns;\n    let refPos, blackPixels, bits, i;\n    if (this.outputBits === 0) {\n      if (this.rowsDone) {\n        this.eof = true;\n      }\n      if (this.eof) {\n        return -1;\n      }\n      this.err = false;\n      let code1, code2, code3;\n      if (this.nextLine2D) {\n        for (i = 0; codingLine[i] < columns; ++i) {\n          refLine[i] = codingLine[i];\n        }\n        refLine[i++] = columns;\n        refLine[i] = columns;\n        codingLine[0] = 0;\n        this.codingPos = 0;\n        refPos = 0;\n        blackPixels = 0;\n        while (codingLine[this.codingPos] < columns) {\n          code1 = this._getTwoDimCode();\n          switch (code1) {\n            case twoDimPass:\n              this._addPixels(refLine[refPos + 1], blackPixels);\n              if (refLine[refPos + 1] < columns) {\n                refPos += 2;\n              }\n              break;\n            case twoDimHoriz:\n              code1 = code2 = 0;\n              if (blackPixels) {\n                do {\n                  code1 += code3 = this._getBlackCode();\n                } while (code3 >= 64);\n                do {\n                  code2 += code3 = this._getWhiteCode();\n                } while (code3 >= 64);\n              } else {\n                do {\n                  code1 += code3 = this._getWhiteCode();\n                } while (code3 >= 64);\n                do {\n                  code2 += code3 = this._getBlackCode();\n                } while (code3 >= 64);\n              }\n              this._addPixels(codingLine[this.codingPos] + code1, blackPixels);\n              if (codingLine[this.codingPos] < columns) {\n                this._addPixels(codingLine[this.codingPos] + code2, blackPixels ^ 1);\n              }\n              while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {\n                refPos += 2;\n              }\n              break;\n            case twoDimVertR3:\n              this._addPixels(refLine[refPos] + 3, blackPixels);\n              blackPixels ^= 1;\n              if (codingLine[this.codingPos] < columns) {\n                ++refPos;\n                while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {\n                  refPos += 2;\n                }\n              }\n              break;\n            case twoDimVertR2:\n              this._addPixels(refLine[refPos] + 2, blackPixels);\n              blackPixels ^= 1;\n              if (codingLine[this.codingPos] < columns) {\n                ++refPos;\n                while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {\n                  refPos += 2;\n                }\n              }\n              break;\n            case twoDimVertR1:\n              this._addPixels(refLine[refPos] + 1, blackPixels);\n              blackPixels ^= 1;\n              if (codingLine[this.codingPos] < columns) {\n                ++refPos;\n                while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {\n                  refPos += 2;\n                }\n              }\n              break;\n            case twoDimVert0:\n              this._addPixels(refLine[refPos], blackPixels);\n              blackPixels ^= 1;\n              if (codingLine[this.codingPos] < columns) {\n                ++refPos;\n                while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {\n                  refPos += 2;\n                }\n              }\n              break;\n            case twoDimVertL3:\n              this._addPixelsNeg(refLine[refPos] - 3, blackPixels);\n              blackPixels ^= 1;\n              if (codingLine[this.codingPos] < columns) {\n                if (refPos > 0) {\n                  --refPos;\n                } else {\n                  ++refPos;\n                }\n                while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {\n                  refPos += 2;\n                }\n              }\n              break;\n            case twoDimVertL2:\n              this._addPixelsNeg(refLine[refPos] - 2, blackPixels);\n              blackPixels ^= 1;\n              if (codingLine[this.codingPos] < columns) {\n                if (refPos > 0) {\n                  --refPos;\n                } else {\n                  ++refPos;\n                }\n                while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {\n                  refPos += 2;\n                }\n              }\n              break;\n            case twoDimVertL1:\n              this._addPixelsNeg(refLine[refPos] - 1, blackPixels);\n              blackPixels ^= 1;\n              if (codingLine[this.codingPos] < columns) {\n                if (refPos > 0) {\n                  --refPos;\n                } else {\n                  ++refPos;\n                }\n                while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {\n                  refPos += 2;\n                }\n              }\n              break;\n            case ccittEOF:\n              this._addPixels(columns, 0);\n              this.eof = true;\n              break;\n            default:\n              info(\"bad 2d code\");\n              this._addPixels(columns, 0);\n              this.err = true;\n          }\n        }\n      } else {\n        codingLine[0] = 0;\n        this.codingPos = 0;\n        blackPixels = 0;\n        while (codingLine[this.codingPos] < columns) {\n          code1 = 0;\n          if (blackPixels) {\n            do {\n              code1 += code3 = this._getBlackCode();\n            } while (code3 >= 64);\n          } else {\n            do {\n              code1 += code3 = this._getWhiteCode();\n            } while (code3 >= 64);\n          }\n          this._addPixels(codingLine[this.codingPos] + code1, blackPixels);\n          blackPixels ^= 1;\n        }\n      }\n      let gotEOL = false;\n      if (this.byteAlign) {\n        this.inputBits &= ~7;\n      }\n      if (!this.eoblock && this.row === this.rows - 1) {\n        this.rowsDone = true;\n      } else {\n        code1 = this._lookBits(12);\n        if (this.eoline) {\n          while (code1 !== ccittEOF && code1 !== 1) {\n            this._eatBits(1);\n            code1 = this._lookBits(12);\n          }\n        } else {\n          while (code1 === 0) {\n            this._eatBits(1);\n            code1 = this._lookBits(12);\n          }\n        }\n        if (code1 === 1) {\n          this._eatBits(12);\n          gotEOL = true;\n        } else if (code1 === ccittEOF) {\n          this.eof = true;\n        }\n      }\n      if (!this.eof && this.encoding > 0 && !this.rowsDone) {\n        this.nextLine2D = !this._lookBits(1);\n        this._eatBits(1);\n      }\n      if (this.eoblock && gotEOL && this.byteAlign) {\n        code1 = this._lookBits(12);\n        if (code1 === 1) {\n          this._eatBits(12);\n          if (this.encoding > 0) {\n            this._lookBits(1);\n            this._eatBits(1);\n          }\n          if (this.encoding >= 0) {\n            for (i = 0; i < 4; ++i) {\n              code1 = this._lookBits(12);\n              if (code1 !== 1) {\n                info(\"bad rtc code: \" + code1);\n              }\n              this._eatBits(12);\n              if (this.encoding > 0) {\n                this._lookBits(1);\n                this._eatBits(1);\n              }\n            }\n          }\n          this.eof = true;\n        }\n      } else if (this.err && this.eoline) {\n        while (true) {\n          code1 = this._lookBits(13);\n          if (code1 === ccittEOF) {\n            this.eof = true;\n            return -1;\n          }\n          if (code1 >> 1 === 1) {\n            break;\n          }\n          this._eatBits(1);\n        }\n        this._eatBits(12);\n        if (this.encoding > 0) {\n          this._eatBits(1);\n          this.nextLine2D = !(code1 & 1);\n        }\n      }\n      this.outputBits = codingLine[0] > 0 ? codingLine[this.codingPos = 0] : codingLine[this.codingPos = 1];\n      this.row++;\n    }\n    let c;\n    if (this.outputBits >= 8) {\n      c = this.codingPos & 1 ? 0 : 0xff;\n      this.outputBits -= 8;\n      if (this.outputBits === 0 && codingLine[this.codingPos] < columns) {\n        this.codingPos++;\n        this.outputBits = codingLine[this.codingPos] - codingLine[this.codingPos - 1];\n      }\n    } else {\n      bits = 8;\n      c = 0;\n      do {\n        if (typeof this.outputBits !== \"number\") {\n          throw new FormatError('Invalid /CCITTFaxDecode data, \"outputBits\" must be a number.');\n        }\n        if (this.outputBits > bits) {\n          c <<= bits;\n          if (!(this.codingPos & 1)) {\n            c |= 0xff >> 8 - bits;\n          }\n          this.outputBits -= bits;\n          bits = 0;\n        } else {\n          c <<= this.outputBits;\n          if (!(this.codingPos & 1)) {\n            c |= 0xff >> 8 - this.outputBits;\n          }\n          bits -= this.outputBits;\n          this.outputBits = 0;\n          if (codingLine[this.codingPos] < columns) {\n            this.codingPos++;\n            this.outputBits = codingLine[this.codingPos] - codingLine[this.codingPos - 1];\n          } else if (bits > 0) {\n            c <<= bits;\n            bits = 0;\n          }\n        }\n      } while (bits);\n    }\n    if (this.black) {\n      c ^= 0xff;\n    }\n    return c;\n  }\n  _addPixels(a1, blackPixels) {\n    const codingLine = this.codingLine;\n    let codingPos = this.codingPos;\n    if (a1 > codingLine[codingPos]) {\n      if (a1 > this.columns) {\n        info(\"row is wrong length\");\n        this.err = true;\n        a1 = this.columns;\n      }\n      if (codingPos & 1 ^ blackPixels) {\n        ++codingPos;\n      }\n      codingLine[codingPos] = a1;\n    }\n    this.codingPos = codingPos;\n  }\n  _addPixelsNeg(a1, blackPixels) {\n    const codingLine = this.codingLine;\n    let codingPos = this.codingPos;\n    if (a1 > codingLine[codingPos]) {\n      if (a1 > this.columns) {\n        info(\"row is wrong length\");\n        this.err = true;\n        a1 = this.columns;\n      }\n      if (codingPos & 1 ^ blackPixels) {\n        ++codingPos;\n      }\n      codingLine[codingPos] = a1;\n    } else if (a1 < codingLine[codingPos]) {\n      if (a1 < 0) {\n        info(\"invalid code\");\n        this.err = true;\n        a1 = 0;\n      }\n      while (codingPos > 0 && a1 < codingLine[codingPos - 1]) {\n        --codingPos;\n      }\n      codingLine[codingPos] = a1;\n    }\n    this.codingPos = codingPos;\n  }\n  _findTableCode(start, end, table, limit) {\n    const limitValue = limit || 0;\n    for (let i = start; i <= end; ++i) {\n      let code = this._lookBits(i);\n      if (code === ccittEOF) {\n        return [true, 1, false];\n      }\n      if (i < end) {\n        code <<= end - i;\n      }\n      if (!limitValue || code >= limitValue) {\n        const p = table[code - limitValue];\n        if (p[0] === i) {\n          this._eatBits(i);\n          return [true, p[1], true];\n        }\n      }\n    }\n    return [false, 0, false];\n  }\n  _getTwoDimCode() {\n    let code = 0;\n    let p;\n    if (this.eoblock) {\n      code = this._lookBits(7);\n      p = twoDimTable[code];\n      if (p?.[0] > 0) {\n        this._eatBits(p[0]);\n        return p[1];\n      }\n    } else {\n      const result = this._findTableCode(1, 7, twoDimTable);\n      if (result[0] && result[2]) {\n        return result[1];\n      }\n    }\n    info(\"Bad two dim code\");\n    return ccittEOF;\n  }\n  _getWhiteCode() {\n    let code = 0;\n    let p;\n    if (this.eoblock) {\n      code = this._lookBits(12);\n      if (code === ccittEOF) {\n        return 1;\n      }\n      p = code >> 5 === 0 ? whiteTable1[code] : whiteTable2[code >> 3];\n      if (p[0] > 0) {\n        this._eatBits(p[0]);\n        return p[1];\n      }\n    } else {\n      let result = this._findTableCode(1, 9, whiteTable2);\n      if (result[0]) {\n        return result[1];\n      }\n      result = this._findTableCode(11, 12, whiteTable1);\n      if (result[0]) {\n        return result[1];\n      }\n    }\n    info(\"bad white code\");\n    this._eatBits(1);\n    return 1;\n  }\n  _getBlackCode() {\n    let code, p;\n    if (this.eoblock) {\n      code = this._lookBits(13);\n      if (code === ccittEOF) {\n        return 1;\n      }\n      if (code >> 7 === 0) {\n        p = blackTable1[code];\n      } else if (code >> 9 === 0 && code >> 7 !== 0) {\n        p = blackTable2[(code >> 1) - 64];\n      } else {\n        p = blackTable3[code >> 7];\n      }\n      if (p[0] > 0) {\n        this._eatBits(p[0]);\n        return p[1];\n      }\n    } else {\n      let result = this._findTableCode(2, 6, blackTable3);\n      if (result[0]) {\n        return result[1];\n      }\n      result = this._findTableCode(7, 12, blackTable2, 64);\n      if (result[0]) {\n        return result[1];\n      }\n      result = this._findTableCode(10, 13, blackTable1);\n      if (result[0]) {\n        return result[1];\n      }\n    }\n    info(\"bad black code\");\n    this._eatBits(1);\n    return 1;\n  }\n  _lookBits(n) {\n    let c;\n    while (this.inputBits < n) {\n      if ((c = this.source.next()) === -1) {\n        if (this.inputBits === 0) {\n          return ccittEOF;\n        }\n        return this.inputBuf << n - this.inputBits & 0xffff >> 16 - n;\n      }\n      this.inputBuf = this.inputBuf << 8 | c;\n      this.inputBits += 8;\n    }\n    return this.inputBuf >> this.inputBits - n & 0xffff >> 16 - n;\n  }\n  _eatBits(n) {\n    if ((this.inputBits -= n) < 0) {\n      this.inputBits = 0;\n    }\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/ccitt_stream.js\n\n\n\nclass CCITTFaxStream extends DecodeStream {\n  constructor(str, maybeLength, params) {\n    super(maybeLength);\n    this.str = str;\n    this.dict = str.dict;\n    if (!(params instanceof Dict)) {\n      params = Dict.empty;\n    }\n    const source = {\n      next() {\n        return str.getByte();\n      }\n    };\n    this.ccittFaxDecoder = new CCITTFaxDecoder(source, {\n      K: params.get(\"K\"),\n      EndOfLine: params.get(\"EndOfLine\"),\n      EncodedByteAlign: params.get(\"EncodedByteAlign\"),\n      Columns: params.get(\"Columns\"),\n      Rows: params.get(\"Rows\"),\n      EndOfBlock: params.get(\"EndOfBlock\"),\n      BlackIs1: params.get(\"BlackIs1\")\n    });\n  }\n  readBlock() {\n    while (!this.eof) {\n      const c = this.ccittFaxDecoder.readNextChar();\n      if (c === -1) {\n        this.eof = true;\n        return;\n      }\n      this.ensureBuffer(this.bufferLength + 1);\n      this.buffer[this.bufferLength++] = c;\n    }\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/flate_stream.js\n\n\nconst codeLenCodeMap = new Int32Array([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);\nconst lengthDecode = new Int32Array([0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009, 0x0000a, 0x1000b, 0x1000d, 0x1000f, 0x10011, 0x20013, 0x20017, 0x2001b, 0x2001f, 0x30023, 0x3002b, 0x30033, 0x3003b, 0x40043, 0x40053, 0x40063, 0x40073, 0x50083, 0x500a3, 0x500c3, 0x500e3, 0x00102, 0x00102, 0x00102]);\nconst distDecode = new Int32Array([0x00001, 0x00002, 0x00003, 0x00004, 0x10005, 0x10007, 0x20009, 0x2000d, 0x30011, 0x30019, 0x40021, 0x40031, 0x50041, 0x50061, 0x60081, 0x600c1, 0x70101, 0x70181, 0x80201, 0x80301, 0x90401, 0x90601, 0xa0801, 0xa0c01, 0xb1001, 0xb1801, 0xc2001, 0xc3001, 0xd4001, 0xd6001]);\nconst fixedLitCodeTab = [new Int32Array([0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c0, 0x70108, 0x80060, 0x80020, 0x900a0, 0x80000, 0x80080, 0x80040, 0x900e0, 0x70104, 0x80058, 0x80018, 0x90090, 0x70114, 0x80078, 0x80038, 0x900d0, 0x7010c, 0x80068, 0x80028, 0x900b0, 0x80008, 0x80088, 0x80048, 0x900f0, 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c8, 0x7010a, 0x80064, 0x80024, 0x900a8, 0x80004, 0x80084, 0x80044, 0x900e8, 0x70106, 0x8005c, 0x8001c, 0x90098, 0x70116, 0x8007c, 0x8003c, 0x900d8, 0x7010e, 0x8006c, 0x8002c, 0x900b8, 0x8000c, 0x8008c, 0x8004c, 0x900f8, 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c4, 0x70109, 0x80062, 0x80022, 0x900a4, 0x80002, 0x80082, 0x80042, 0x900e4, 0x70105, 0x8005a, 0x8001a, 0x90094, 0x70115, 0x8007a, 0x8003a, 0x900d4, 0x7010d, 0x8006a, 0x8002a, 0x900b4, 0x8000a, 0x8008a, 0x8004a, 0x900f4, 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cc, 0x7010b, 0x80066, 0x80026, 0x900ac, 0x80006, 0x80086, 0x80046, 0x900ec, 0x70107, 0x8005e, 0x8001e, 0x9009c, 0x70117, 0x8007e, 0x8003e, 0x900dc, 0x7010f, 0x8006e, 0x8002e, 0x900bc, 0x8000e, 0x8008e, 0x8004e, 0x900fc, 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c2, 0x70108, 0x80061, 0x80021, 0x900a2, 0x80001, 0x80081, 0x80041, 0x900e2, 0x70104, 0x80059, 0x80019, 0x90092, 0x70114, 0x80079, 0x80039, 0x900d2, 0x7010c, 0x80069, 0x80029, 0x900b2, 0x80009, 0x80089, 0x80049, 0x900f2, 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900ca, 0x7010a, 0x80065, 0x80025, 0x900aa, 0x80005, 0x80085, 0x80045, 0x900ea, 0x70106, 0x8005d, 0x8001d, 0x9009a, 0x70116, 0x8007d, 0x8003d, 0x900da, 0x7010e, 0x8006d, 0x8002d, 0x900ba, 0x8000d, 0x8008d, 0x8004d, 0x900fa, 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c6, 0x70109, 0x80063, 0x80023, 0x900a6, 0x80003, 0x80083, 0x80043, 0x900e6, 0x70105, 0x8005b, 0x8001b, 0x90096, 0x70115, 0x8007b, 0x8003b, 0x900d6, 0x7010d, 0x8006b, 0x8002b, 0x900b6, 0x8000b, 0x8008b, 0x8004b, 0x900f6, 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900ce, 0x7010b, 0x80067, 0x80027, 0x900ae, 0x80007, 0x80087, 0x80047, 0x900ee, 0x70107, 0x8005f, 0x8001f, 0x9009e, 0x70117, 0x8007f, 0x8003f, 0x900de, 0x7010f, 0x8006f, 0x8002f, 0x900be, 0x8000f, 0x8008f, 0x8004f, 0x900fe, 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c1, 0x70108, 0x80060, 0x80020, 0x900a1, 0x80000, 0x80080, 0x80040, 0x900e1, 0x70104, 0x80058, 0x80018, 0x90091, 0x70114, 0x80078, 0x80038, 0x900d1, 0x7010c, 0x80068, 0x80028, 0x900b1, 0x80008, 0x80088, 0x80048, 0x900f1, 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c9, 0x7010a, 0x80064, 0x80024, 0x900a9, 0x80004, 0x80084, 0x80044, 0x900e9, 0x70106, 0x8005c, 0x8001c, 0x90099, 0x70116, 0x8007c, 0x8003c, 0x900d9, 0x7010e, 0x8006c, 0x8002c, 0x900b9, 0x8000c, 0x8008c, 0x8004c, 0x900f9, 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c5, 0x70109, 0x80062, 0x80022, 0x900a5, 0x80002, 0x80082, 0x80042, 0x900e5, 0x70105, 0x8005a, 0x8001a, 0x90095, 0x70115, 0x8007a, 0x8003a, 0x900d5, 0x7010d, 0x8006a, 0x8002a, 0x900b5, 0x8000a, 0x8008a, 0x8004a, 0x900f5, 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cd, 0x7010b, 0x80066, 0x80026, 0x900ad, 0x80006, 0x80086, 0x80046, 0x900ed, 0x70107, 0x8005e, 0x8001e, 0x9009d, 0x70117, 0x8007e, 0x8003e, 0x900dd, 0x7010f, 0x8006e, 0x8002e, 0x900bd, 0x8000e, 0x8008e, 0x8004e, 0x900fd, 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c3, 0x70108, 0x80061, 0x80021, 0x900a3, 0x80001, 0x80081, 0x80041, 0x900e3, 0x70104, 0x80059, 0x80019, 0x90093, 0x70114, 0x80079, 0x80039, 0x900d3, 0x7010c, 0x80069, 0x80029, 0x900b3, 0x80009, 0x80089, 0x80049, 0x900f3, 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900cb, 0x7010a, 0x80065, 0x80025, 0x900ab, 0x80005, 0x80085, 0x80045, 0x900eb, 0x70106, 0x8005d, 0x8001d, 0x9009b, 0x70116, 0x8007d, 0x8003d, 0x900db, 0x7010e, 0x8006d, 0x8002d, 0x900bb, 0x8000d, 0x8008d, 0x8004d, 0x900fb, 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c7, 0x70109, 0x80063, 0x80023, 0x900a7, 0x80003, 0x80083, 0x80043, 0x900e7, 0x70105, 0x8005b, 0x8001b, 0x90097, 0x70115, 0x8007b, 0x8003b, 0x900d7, 0x7010d, 0x8006b, 0x8002b, 0x900b7, 0x8000b, 0x8008b, 0x8004b, 0x900f7, 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900cf, 0x7010b, 0x80067, 0x80027, 0x900af, 0x80007, 0x80087, 0x80047, 0x900ef, 0x70107, 0x8005f, 0x8001f, 0x9009f, 0x70117, 0x8007f, 0x8003f, 0x900df, 0x7010f, 0x8006f, 0x8002f, 0x900bf, 0x8000f, 0x8008f, 0x8004f, 0x900ff]), 9];\nconst fixedDistCodeTab = [new Int32Array([0x50000, 0x50010, 0x50008, 0x50018, 0x50004, 0x50014, 0x5000c, 0x5001c, 0x50002, 0x50012, 0x5000a, 0x5001a, 0x50006, 0x50016, 0x5000e, 0x00000, 0x50001, 0x50011, 0x50009, 0x50019, 0x50005, 0x50015, 0x5000d, 0x5001d, 0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000]), 5];\nclass FlateStream extends DecodeStream {\n  constructor(str, maybeLength) {\n    super(maybeLength);\n    this.str = str;\n    this.dict = str.dict;\n    const cmf = str.getByte();\n    const flg = str.getByte();\n    if (cmf === -1 || flg === -1) {\n      throw new FormatError(`Invalid header in flate stream: ${cmf}, ${flg}`);\n    }\n    if ((cmf & 0x0f) !== 0x08) {\n      throw new FormatError(`Unknown compression method in flate stream: ${cmf}, ${flg}`);\n    }\n    if (((cmf << 8) + flg) % 31 !== 0) {\n      throw new FormatError(`Bad FCHECK in flate stream: ${cmf}, ${flg}`);\n    }\n    if (flg & 0x20) {\n      throw new FormatError(`FDICT bit set in flate stream: ${cmf}, ${flg}`);\n    }\n    this.codeSize = 0;\n    this.codeBuf = 0;\n  }\n  getBits(bits) {\n    const str = this.str;\n    let codeSize = this.codeSize;\n    let codeBuf = this.codeBuf;\n    let b;\n    while (codeSize < bits) {\n      if ((b = str.getByte()) === -1) {\n        throw new FormatError(\"Bad encoding in flate stream\");\n      }\n      codeBuf |= b << codeSize;\n      codeSize += 8;\n    }\n    b = codeBuf & (1 << bits) - 1;\n    this.codeBuf = codeBuf >> bits;\n    this.codeSize = codeSize -= bits;\n    return b;\n  }\n  getCode(table) {\n    const str = this.str;\n    const codes = table[0];\n    const maxLen = table[1];\n    let codeSize = this.codeSize;\n    let codeBuf = this.codeBuf;\n    let b;\n    while (codeSize < maxLen) {\n      if ((b = str.getByte()) === -1) {\n        break;\n      }\n      codeBuf |= b << codeSize;\n      codeSize += 8;\n    }\n    const code = codes[codeBuf & (1 << maxLen) - 1];\n    const codeLen = code >> 16;\n    const codeVal = code & 0xffff;\n    if (codeLen < 1 || codeSize < codeLen) {\n      throw new FormatError(\"Bad encoding in flate stream\");\n    }\n    this.codeBuf = codeBuf >> codeLen;\n    this.codeSize = codeSize - codeLen;\n    return codeVal;\n  }\n  generateHuffmanTable(lengths) {\n    const n = lengths.length;\n    let maxLen = 0;\n    let i;\n    for (i = 0; i < n; ++i) {\n      if (lengths[i] > maxLen) {\n        maxLen = lengths[i];\n      }\n    }\n    const size = 1 << maxLen;\n    const codes = new Int32Array(size);\n    for (let len = 1, code = 0, skip = 2; len <= maxLen; ++len, code <<= 1, skip <<= 1) {\n      for (let val = 0; val < n; ++val) {\n        if (lengths[val] === len) {\n          let code2 = 0;\n          let t = code;\n          for (i = 0; i < len; ++i) {\n            code2 = code2 << 1 | t & 1;\n            t >>= 1;\n          }\n          for (i = code2; i < size; i += skip) {\n            codes[i] = len << 16 | val;\n          }\n          ++code;\n        }\n      }\n    }\n    return [codes, maxLen];\n  }\n  #endsStreamOnError(err) {\n    info(err);\n    this.eof = true;\n  }\n  readBlock() {\n    let buffer, len;\n    const str = this.str;\n    let hdr = this.getBits(3);\n    if (hdr & 1) {\n      this.eof = true;\n    }\n    hdr >>= 1;\n    if (hdr === 0) {\n      let b;\n      if ((b = str.getByte()) === -1) {\n        this.#endsStreamOnError(\"Bad block header in flate stream\");\n        return;\n      }\n      let blockLen = b;\n      if ((b = str.getByte()) === -1) {\n        this.#endsStreamOnError(\"Bad block header in flate stream\");\n        return;\n      }\n      blockLen |= b << 8;\n      if ((b = str.getByte()) === -1) {\n        this.#endsStreamOnError(\"Bad block header in flate stream\");\n        return;\n      }\n      let check = b;\n      if ((b = str.getByte()) === -1) {\n        this.#endsStreamOnError(\"Bad block header in flate stream\");\n        return;\n      }\n      check |= b << 8;\n      if (check !== (~blockLen & 0xffff) && (blockLen !== 0 || check !== 0)) {\n        throw new FormatError(\"Bad uncompressed block length in flate stream\");\n      }\n      this.codeBuf = 0;\n      this.codeSize = 0;\n      const bufferLength = this.bufferLength,\n        end = bufferLength + blockLen;\n      buffer = this.ensureBuffer(end);\n      this.bufferLength = end;\n      if (blockLen === 0) {\n        if (str.peekByte() === -1) {\n          this.eof = true;\n        }\n      } else {\n        const block = str.getBytes(blockLen);\n        buffer.set(block, bufferLength);\n        if (block.length < blockLen) {\n          this.eof = true;\n        }\n      }\n      return;\n    }\n    let litCodeTable;\n    let distCodeTable;\n    if (hdr === 1) {\n      litCodeTable = fixedLitCodeTab;\n      distCodeTable = fixedDistCodeTab;\n    } else if (hdr === 2) {\n      const numLitCodes = this.getBits(5) + 257;\n      const numDistCodes = this.getBits(5) + 1;\n      const numCodeLenCodes = this.getBits(4) + 4;\n      const codeLenCodeLengths = new Uint8Array(codeLenCodeMap.length);\n      let i;\n      for (i = 0; i < numCodeLenCodes; ++i) {\n        codeLenCodeLengths[codeLenCodeMap[i]] = this.getBits(3);\n      }\n      const codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths);\n      len = 0;\n      i = 0;\n      const codes = numLitCodes + numDistCodes;\n      const codeLengths = new Uint8Array(codes);\n      let bitsLength, bitsOffset, what;\n      while (i < codes) {\n        const code = this.getCode(codeLenCodeTab);\n        if (code === 16) {\n          bitsLength = 2;\n          bitsOffset = 3;\n          what = len;\n        } else if (code === 17) {\n          bitsLength = 3;\n          bitsOffset = 3;\n          what = len = 0;\n        } else if (code === 18) {\n          bitsLength = 7;\n          bitsOffset = 11;\n          what = len = 0;\n        } else {\n          codeLengths[i++] = len = code;\n          continue;\n        }\n        let repeatLength = this.getBits(bitsLength) + bitsOffset;\n        while (repeatLength-- > 0) {\n          codeLengths[i++] = what;\n        }\n      }\n      litCodeTable = this.generateHuffmanTable(codeLengths.subarray(0, numLitCodes));\n      distCodeTable = this.generateHuffmanTable(codeLengths.subarray(numLitCodes, codes));\n    } else {\n      throw new FormatError(\"Unknown block type in flate stream\");\n    }\n    buffer = this.buffer;\n    let limit = buffer ? buffer.length : 0;\n    let pos = this.bufferLength;\n    while (true) {\n      let code1 = this.getCode(litCodeTable);\n      if (code1 < 256) {\n        if (pos + 1 >= limit) {\n          buffer = this.ensureBuffer(pos + 1);\n          limit = buffer.length;\n        }\n        buffer[pos++] = code1;\n        continue;\n      }\n      if (code1 === 256) {\n        this.bufferLength = pos;\n        return;\n      }\n      code1 -= 257;\n      code1 = lengthDecode[code1];\n      let code2 = code1 >> 16;\n      if (code2 > 0) {\n        code2 = this.getBits(code2);\n      }\n      len = (code1 & 0xffff) + code2;\n      code1 = this.getCode(distCodeTable);\n      code1 = distDecode[code1];\n      code2 = code1 >> 16;\n      if (code2 > 0) {\n        code2 = this.getBits(code2);\n      }\n      const dist = (code1 & 0xffff) + code2;\n      if (pos + len >= limit) {\n        buffer = this.ensureBuffer(pos + len);\n        limit = buffer.length;\n      }\n      for (let k = 0; k < len; ++k, ++pos) {\n        buffer[pos] = buffer[pos - dist];\n      }\n    }\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/arithmetic_decoder.js\nconst QeTable = [{\n  qe: 0x5601,\n  nmps: 1,\n  nlps: 1,\n  switchFlag: 1\n}, {\n  qe: 0x3401,\n  nmps: 2,\n  nlps: 6,\n  switchFlag: 0\n}, {\n  qe: 0x1801,\n  nmps: 3,\n  nlps: 9,\n  switchFlag: 0\n}, {\n  qe: 0x0ac1,\n  nmps: 4,\n  nlps: 12,\n  switchFlag: 0\n}, {\n  qe: 0x0521,\n  nmps: 5,\n  nlps: 29,\n  switchFlag: 0\n}, {\n  qe: 0x0221,\n  nmps: 38,\n  nlps: 33,\n  switchFlag: 0\n}, {\n  qe: 0x5601,\n  nmps: 7,\n  nlps: 6,\n  switchFlag: 1\n}, {\n  qe: 0x5401,\n  nmps: 8,\n  nlps: 14,\n  switchFlag: 0\n}, {\n  qe: 0x4801,\n  nmps: 9,\n  nlps: 14,\n  switchFlag: 0\n}, {\n  qe: 0x3801,\n  nmps: 10,\n  nlps: 14,\n  switchFlag: 0\n}, {\n  qe: 0x3001,\n  nmps: 11,\n  nlps: 17,\n  switchFlag: 0\n}, {\n  qe: 0x2401,\n  nmps: 12,\n  nlps: 18,\n  switchFlag: 0\n}, {\n  qe: 0x1c01,\n  nmps: 13,\n  nlps: 20,\n  switchFlag: 0\n}, {\n  qe: 0x1601,\n  nmps: 29,\n  nlps: 21,\n  switchFlag: 0\n}, {\n  qe: 0x5601,\n  nmps: 15,\n  nlps: 14,\n  switchFlag: 1\n}, {\n  qe: 0x5401,\n  nmps: 16,\n  nlps: 14,\n  switchFlag: 0\n}, {\n  qe: 0x5101,\n  nmps: 17,\n  nlps: 15,\n  switchFlag: 0\n}, {\n  qe: 0x4801,\n  nmps: 18,\n  nlps: 16,\n  switchFlag: 0\n}, {\n  qe: 0x3801,\n  nmps: 19,\n  nlps: 17,\n  switchFlag: 0\n}, {\n  qe: 0x3401,\n  nmps: 20,\n  nlps: 18,\n  switchFlag: 0\n}, {\n  qe: 0x3001,\n  nmps: 21,\n  nlps: 19,\n  switchFlag: 0\n}, {\n  qe: 0x2801,\n  nmps: 22,\n  nlps: 19,\n  switchFlag: 0\n}, {\n  qe: 0x2401,\n  nmps: 23,\n  nlps: 20,\n  switchFlag: 0\n}, {\n  qe: 0x2201,\n  nmps: 24,\n  nlps: 21,\n  switchFlag: 0\n}, {\n  qe: 0x1c01,\n  nmps: 25,\n  nlps: 22,\n  switchFlag: 0\n}, {\n  qe: 0x1801,\n  nmps: 26,\n  nlps: 23,\n  switchFlag: 0\n}, {\n  qe: 0x1601,\n  nmps: 27,\n  nlps: 24,\n  switchFlag: 0\n}, {\n  qe: 0x1401,\n  nmps: 28,\n  nlps: 25,\n  switchFlag: 0\n}, {\n  qe: 0x1201,\n  nmps: 29,\n  nlps: 26,\n  switchFlag: 0\n}, {\n  qe: 0x1101,\n  nmps: 30,\n  nlps: 27,\n  switchFlag: 0\n}, {\n  qe: 0x0ac1,\n  nmps: 31,\n  nlps: 28,\n  switchFlag: 0\n}, {\n  qe: 0x09c1,\n  nmps: 32,\n  nlps: 29,\n  switchFlag: 0\n}, {\n  qe: 0x08a1,\n  nmps: 33,\n  nlps: 30,\n  switchFlag: 0\n}, {\n  qe: 0x0521,\n  nmps: 34,\n  nlps: 31,\n  switchFlag: 0\n}, {\n  qe: 0x0441,\n  nmps: 35,\n  nlps: 32,\n  switchFlag: 0\n}, {\n  qe: 0x02a1,\n  nmps: 36,\n  nlps: 33,\n  switchFlag: 0\n}, {\n  qe: 0x0221,\n  nmps: 37,\n  nlps: 34,\n  switchFlag: 0\n}, {\n  qe: 0x0141,\n  nmps: 38,\n  nlps: 35,\n  switchFlag: 0\n}, {\n  qe: 0x0111,\n  nmps: 39,\n  nlps: 36,\n  switchFlag: 0\n}, {\n  qe: 0x0085,\n  nmps: 40,\n  nlps: 37,\n  switchFlag: 0\n}, {\n  qe: 0x0049,\n  nmps: 41,\n  nlps: 38,\n  switchFlag: 0\n}, {\n  qe: 0x0025,\n  nmps: 42,\n  nlps: 39,\n  switchFlag: 0\n}, {\n  qe: 0x0015,\n  nmps: 43,\n  nlps: 40,\n  switchFlag: 0\n}, {\n  qe: 0x0009,\n  nmps: 44,\n  nlps: 41,\n  switchFlag: 0\n}, {\n  qe: 0x0005,\n  nmps: 45,\n  nlps: 42,\n  switchFlag: 0\n}, {\n  qe: 0x0001,\n  nmps: 45,\n  nlps: 43,\n  switchFlag: 0\n}, {\n  qe: 0x5601,\n  nmps: 46,\n  nlps: 46,\n  switchFlag: 0\n}];\nclass ArithmeticDecoder {\n  constructor(data, start, end) {\n    this.data = data;\n    this.bp = start;\n    this.dataEnd = end;\n    this.chigh = data[start];\n    this.clow = 0;\n    this.byteIn();\n    this.chigh = this.chigh << 7 & 0xffff | this.clow >> 9 & 0x7f;\n    this.clow = this.clow << 7 & 0xffff;\n    this.ct -= 7;\n    this.a = 0x8000;\n  }\n  byteIn() {\n    const data = this.data;\n    let bp = this.bp;\n    if (data[bp] === 0xff) {\n      if (data[bp + 1] > 0x8f) {\n        this.clow += 0xff00;\n        this.ct = 8;\n      } else {\n        bp++;\n        this.clow += data[bp] << 9;\n        this.ct = 7;\n        this.bp = bp;\n      }\n    } else {\n      bp++;\n      this.clow += bp < this.dataEnd ? data[bp] << 8 : 0xff00;\n      this.ct = 8;\n      this.bp = bp;\n    }\n    if (this.clow > 0xffff) {\n      this.chigh += this.clow >> 16;\n      this.clow &= 0xffff;\n    }\n  }\n  readBit(contexts, pos) {\n    let cx_index = contexts[pos] >> 1,\n      cx_mps = contexts[pos] & 1;\n    const qeTableIcx = QeTable[cx_index];\n    const qeIcx = qeTableIcx.qe;\n    let d;\n    let a = this.a - qeIcx;\n    if (this.chigh < qeIcx) {\n      if (a < qeIcx) {\n        a = qeIcx;\n        d = cx_mps;\n        cx_index = qeTableIcx.nmps;\n      } else {\n        a = qeIcx;\n        d = 1 ^ cx_mps;\n        if (qeTableIcx.switchFlag === 1) {\n          cx_mps = d;\n        }\n        cx_index = qeTableIcx.nlps;\n      }\n    } else {\n      this.chigh -= qeIcx;\n      if ((a & 0x8000) !== 0) {\n        this.a = a;\n        return cx_mps;\n      }\n      if (a < qeIcx) {\n        d = 1 ^ cx_mps;\n        if (qeTableIcx.switchFlag === 1) {\n          cx_mps = d;\n        }\n        cx_index = qeTableIcx.nlps;\n      } else {\n        d = cx_mps;\n        cx_index = qeTableIcx.nmps;\n      }\n    }\n    do {\n      if (this.ct === 0) {\n        this.byteIn();\n      }\n      a <<= 1;\n      this.chigh = this.chigh << 1 & 0xffff | this.clow >> 15 & 1;\n      this.clow = this.clow << 1 & 0xffff;\n      this.ct--;\n    } while ((a & 0x8000) === 0);\n    this.a = a;\n    contexts[pos] = cx_index << 1 | cx_mps;\n    return d;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/jbig2.js\n\n\n\n\nclass Jbig2Error extends BaseException {\n  constructor(msg) {\n    super(msg, \"Jbig2Error\");\n  }\n}\nclass ContextCache {\n  getContexts(id) {\n    if (id in this) {\n      return this[id];\n    }\n    return this[id] = new Int8Array(1 << 16);\n  }\n}\nclass DecodingContext {\n  constructor(data, start, end) {\n    this.data = data;\n    this.start = start;\n    this.end = end;\n  }\n  get decoder() {\n    const decoder = new ArithmeticDecoder(this.data, this.start, this.end);\n    return shadow(this, \"decoder\", decoder);\n  }\n  get contextCache() {\n    const cache = new ContextCache();\n    return shadow(this, \"contextCache\", cache);\n  }\n}\nconst MAX_INT_32 = 2 ** 31 - 1;\nconst MIN_INT_32 = -(2 ** 31);\nfunction decodeInteger(contextCache, procedure, decoder) {\n  const contexts = contextCache.getContexts(procedure);\n  let prev = 1;\n  function readBits(length) {\n    let v = 0;\n    for (let i = 0; i < length; i++) {\n      const bit = decoder.readBit(contexts, prev);\n      prev = prev < 256 ? prev << 1 | bit : (prev << 1 | bit) & 511 | 256;\n      v = v << 1 | bit;\n    }\n    return v >>> 0;\n  }\n  const sign = readBits(1);\n  const value = readBits(1) ? readBits(1) ? readBits(1) ? readBits(1) ? readBits(1) ? readBits(32) + 4436 : readBits(12) + 340 : readBits(8) + 84 : readBits(6) + 20 : readBits(4) + 4 : readBits(2);\n  let signedValue;\n  if (sign === 0) {\n    signedValue = value;\n  } else if (value > 0) {\n    signedValue = -value;\n  }\n  if (signedValue >= MIN_INT_32 && signedValue <= MAX_INT_32) {\n    return signedValue;\n  }\n  return null;\n}\nfunction decodeIAID(contextCache, decoder, codeLength) {\n  const contexts = contextCache.getContexts(\"IAID\");\n  let prev = 1;\n  for (let i = 0; i < codeLength; i++) {\n    const bit = decoder.readBit(contexts, prev);\n    prev = prev << 1 | bit;\n  }\n  if (codeLength < 31) {\n    return prev & (1 << codeLength) - 1;\n  }\n  return prev & 0x7fffffff;\n}\nconst SegmentTypes = [\"SymbolDictionary\", null, null, null, \"IntermediateTextRegion\", null, \"ImmediateTextRegion\", \"ImmediateLosslessTextRegion\", null, null, null, null, null, null, null, null, \"PatternDictionary\", null, null, null, \"IntermediateHalftoneRegion\", null, \"ImmediateHalftoneRegion\", \"ImmediateLosslessHalftoneRegion\", null, null, null, null, null, null, null, null, null, null, null, null, \"IntermediateGenericRegion\", null, \"ImmediateGenericRegion\", \"ImmediateLosslessGenericRegion\", \"IntermediateGenericRefinementRegion\", null, \"ImmediateGenericRefinementRegion\", \"ImmediateLosslessGenericRefinementRegion\", null, null, null, null, \"PageInformation\", \"EndOfPage\", \"EndOfStripe\", \"EndOfFile\", \"Profiles\", \"Tables\", null, null, null, null, null, null, null, null, \"Extension\"];\nconst CodingTemplates = [[{\n  x: -1,\n  y: -2\n}, {\n  x: 0,\n  y: -2\n}, {\n  x: 1,\n  y: -2\n}, {\n  x: -2,\n  y: -1\n}, {\n  x: -1,\n  y: -1\n}, {\n  x: 0,\n  y: -1\n}, {\n  x: 1,\n  y: -1\n}, {\n  x: 2,\n  y: -1\n}, {\n  x: -4,\n  y: 0\n}, {\n  x: -3,\n  y: 0\n}, {\n  x: -2,\n  y: 0\n}, {\n  x: -1,\n  y: 0\n}], [{\n  x: -1,\n  y: -2\n}, {\n  x: 0,\n  y: -2\n}, {\n  x: 1,\n  y: -2\n}, {\n  x: 2,\n  y: -2\n}, {\n  x: -2,\n  y: -1\n}, {\n  x: -1,\n  y: -1\n}, {\n  x: 0,\n  y: -1\n}, {\n  x: 1,\n  y: -1\n}, {\n  x: 2,\n  y: -1\n}, {\n  x: -3,\n  y: 0\n}, {\n  x: -2,\n  y: 0\n}, {\n  x: -1,\n  y: 0\n}], [{\n  x: -1,\n  y: -2\n}, {\n  x: 0,\n  y: -2\n}, {\n  x: 1,\n  y: -2\n}, {\n  x: -2,\n  y: -1\n}, {\n  x: -1,\n  y: -1\n}, {\n  x: 0,\n  y: -1\n}, {\n  x: 1,\n  y: -1\n}, {\n  x: -2,\n  y: 0\n}, {\n  x: -1,\n  y: 0\n}], [{\n  x: -3,\n  y: -1\n}, {\n  x: -2,\n  y: -1\n}, {\n  x: -1,\n  y: -1\n}, {\n  x: 0,\n  y: -1\n}, {\n  x: 1,\n  y: -1\n}, {\n  x: -4,\n  y: 0\n}, {\n  x: -3,\n  y: 0\n}, {\n  x: -2,\n  y: 0\n}, {\n  x: -1,\n  y: 0\n}]];\nconst RefinementTemplates = [{\n  coding: [{\n    x: 0,\n    y: -1\n  }, {\n    x: 1,\n    y: -1\n  }, {\n    x: -1,\n    y: 0\n  }],\n  reference: [{\n    x: 0,\n    y: -1\n  }, {\n    x: 1,\n    y: -1\n  }, {\n    x: -1,\n    y: 0\n  }, {\n    x: 0,\n    y: 0\n  }, {\n    x: 1,\n    y: 0\n  }, {\n    x: -1,\n    y: 1\n  }, {\n    x: 0,\n    y: 1\n  }, {\n    x: 1,\n    y: 1\n  }]\n}, {\n  coding: [{\n    x: -1,\n    y: -1\n  }, {\n    x: 0,\n    y: -1\n  }, {\n    x: 1,\n    y: -1\n  }, {\n    x: -1,\n    y: 0\n  }],\n  reference: [{\n    x: 0,\n    y: -1\n  }, {\n    x: -1,\n    y: 0\n  }, {\n    x: 0,\n    y: 0\n  }, {\n    x: 1,\n    y: 0\n  }, {\n    x: 0,\n    y: 1\n  }, {\n    x: 1,\n    y: 1\n  }]\n}];\nconst ReusedContexts = [0x9b25, 0x0795, 0x00e5, 0x0195];\nconst RefinementReusedContexts = [0x0020, 0x0008];\nfunction decodeBitmapTemplate0(width, height, decodingContext) {\n  const decoder = decodingContext.decoder;\n  const contexts = decodingContext.contextCache.getContexts(\"GB\");\n  const bitmap = [];\n  let contextLabel, i, j, pixel, row, row1, row2;\n  const OLD_PIXEL_MASK = 0x7bf7;\n  for (i = 0; i < height; i++) {\n    row = bitmap[i] = new Uint8Array(width);\n    row1 = i < 1 ? row : bitmap[i - 1];\n    row2 = i < 2 ? row : bitmap[i - 2];\n    contextLabel = row2[0] << 13 | row2[1] << 12 | row2[2] << 11 | row1[0] << 7 | row1[1] << 6 | row1[2] << 5 | row1[3] << 4;\n    for (j = 0; j < width; j++) {\n      row[j] = pixel = decoder.readBit(contexts, contextLabel);\n      contextLabel = (contextLabel & OLD_PIXEL_MASK) << 1 | (j + 3 < width ? row2[j + 3] << 11 : 0) | (j + 4 < width ? row1[j + 4] << 4 : 0) | pixel;\n    }\n  }\n  return bitmap;\n}\nfunction decodeBitmap(mmr, width, height, templateIndex, prediction, skip, at, decodingContext) {\n  if (mmr) {\n    const input = new Reader(decodingContext.data, decodingContext.start, decodingContext.end);\n    return decodeMMRBitmap(input, width, height, false);\n  }\n  if (templateIndex === 0 && !skip && !prediction && at.length === 4 && at[0].x === 3 && at[0].y === -1 && at[1].x === -3 && at[1].y === -1 && at[2].x === 2 && at[2].y === -2 && at[3].x === -2 && at[3].y === -2) {\n    return decodeBitmapTemplate0(width, height, decodingContext);\n  }\n  const useskip = !!skip;\n  const template = CodingTemplates[templateIndex].concat(at);\n  template.sort(function (a, b) {\n    return a.y - b.y || a.x - b.x;\n  });\n  const templateLength = template.length;\n  const templateX = new Int8Array(templateLength);\n  const templateY = new Int8Array(templateLength);\n  const changingTemplateEntries = [];\n  let reuseMask = 0,\n    minX = 0,\n    maxX = 0,\n    minY = 0;\n  let c, k;\n  for (k = 0; k < templateLength; k++) {\n    templateX[k] = template[k].x;\n    templateY[k] = template[k].y;\n    minX = Math.min(minX, template[k].x);\n    maxX = Math.max(maxX, template[k].x);\n    minY = Math.min(minY, template[k].y);\n    if (k < templateLength - 1 && template[k].y === template[k + 1].y && template[k].x === template[k + 1].x - 1) {\n      reuseMask |= 1 << templateLength - 1 - k;\n    } else {\n      changingTemplateEntries.push(k);\n    }\n  }\n  const changingEntriesLength = changingTemplateEntries.length;\n  const changingTemplateX = new Int8Array(changingEntriesLength);\n  const changingTemplateY = new Int8Array(changingEntriesLength);\n  const changingTemplateBit = new Uint16Array(changingEntriesLength);\n  for (c = 0; c < changingEntriesLength; c++) {\n    k = changingTemplateEntries[c];\n    changingTemplateX[c] = template[k].x;\n    changingTemplateY[c] = template[k].y;\n    changingTemplateBit[c] = 1 << templateLength - 1 - k;\n  }\n  const sbb_left = -minX;\n  const sbb_top = -minY;\n  const sbb_right = width - maxX;\n  const pseudoPixelContext = ReusedContexts[templateIndex];\n  let row = new Uint8Array(width);\n  const bitmap = [];\n  const decoder = decodingContext.decoder;\n  const contexts = decodingContext.contextCache.getContexts(\"GB\");\n  let ltp = 0,\n    j,\n    i0,\n    j0,\n    contextLabel = 0,\n    bit,\n    shift;\n  for (let i = 0; i < height; i++) {\n    if (prediction) {\n      const sltp = decoder.readBit(contexts, pseudoPixelContext);\n      ltp ^= sltp;\n      if (ltp) {\n        bitmap.push(row);\n        continue;\n      }\n    }\n    row = new Uint8Array(row);\n    bitmap.push(row);\n    for (j = 0; j < width; j++) {\n      if (useskip && skip[i][j]) {\n        row[j] = 0;\n        continue;\n      }\n      if (j >= sbb_left && j < sbb_right && i >= sbb_top) {\n        contextLabel = contextLabel << 1 & reuseMask;\n        for (k = 0; k < changingEntriesLength; k++) {\n          i0 = i + changingTemplateY[k];\n          j0 = j + changingTemplateX[k];\n          bit = bitmap[i0][j0];\n          if (bit) {\n            bit = changingTemplateBit[k];\n            contextLabel |= bit;\n          }\n        }\n      } else {\n        contextLabel = 0;\n        shift = templateLength - 1;\n        for (k = 0; k < templateLength; k++, shift--) {\n          j0 = j + templateX[k];\n          if (j0 >= 0 && j0 < width) {\n            i0 = i + templateY[k];\n            if (i0 >= 0) {\n              bit = bitmap[i0][j0];\n              if (bit) {\n                contextLabel |= bit << shift;\n              }\n            }\n          }\n        }\n      }\n      const pixel = decoder.readBit(contexts, contextLabel);\n      row[j] = pixel;\n    }\n  }\n  return bitmap;\n}\nfunction decodeRefinement(width, height, templateIndex, referenceBitmap, offsetX, offsetY, prediction, at, decodingContext) {\n  let codingTemplate = RefinementTemplates[templateIndex].coding;\n  if (templateIndex === 0) {\n    codingTemplate = codingTemplate.concat([at[0]]);\n  }\n  const codingTemplateLength = codingTemplate.length;\n  const codingTemplateX = new Int32Array(codingTemplateLength);\n  const codingTemplateY = new Int32Array(codingTemplateLength);\n  let k;\n  for (k = 0; k < codingTemplateLength; k++) {\n    codingTemplateX[k] = codingTemplate[k].x;\n    codingTemplateY[k] = codingTemplate[k].y;\n  }\n  let referenceTemplate = RefinementTemplates[templateIndex].reference;\n  if (templateIndex === 0) {\n    referenceTemplate = referenceTemplate.concat([at[1]]);\n  }\n  const referenceTemplateLength = referenceTemplate.length;\n  const referenceTemplateX = new Int32Array(referenceTemplateLength);\n  const referenceTemplateY = new Int32Array(referenceTemplateLength);\n  for (k = 0; k < referenceTemplateLength; k++) {\n    referenceTemplateX[k] = referenceTemplate[k].x;\n    referenceTemplateY[k] = referenceTemplate[k].y;\n  }\n  const referenceWidth = referenceBitmap[0].length;\n  const referenceHeight = referenceBitmap.length;\n  const pseudoPixelContext = RefinementReusedContexts[templateIndex];\n  const bitmap = [];\n  const decoder = decodingContext.decoder;\n  const contexts = decodingContext.contextCache.getContexts(\"GR\");\n  let ltp = 0;\n  for (let i = 0; i < height; i++) {\n    if (prediction) {\n      const sltp = decoder.readBit(contexts, pseudoPixelContext);\n      ltp ^= sltp;\n      if (ltp) {\n        throw new Jbig2Error(\"prediction is not supported\");\n      }\n    }\n    const row = new Uint8Array(width);\n    bitmap.push(row);\n    for (let j = 0; j < width; j++) {\n      let i0, j0;\n      let contextLabel = 0;\n      for (k = 0; k < codingTemplateLength; k++) {\n        i0 = i + codingTemplateY[k];\n        j0 = j + codingTemplateX[k];\n        if (i0 < 0 || j0 < 0 || j0 >= width) {\n          contextLabel <<= 1;\n        } else {\n          contextLabel = contextLabel << 1 | bitmap[i0][j0];\n        }\n      }\n      for (k = 0; k < referenceTemplateLength; k++) {\n        i0 = i + referenceTemplateY[k] - offsetY;\n        j0 = j + referenceTemplateX[k] - offsetX;\n        if (i0 < 0 || i0 >= referenceHeight || j0 < 0 || j0 >= referenceWidth) {\n          contextLabel <<= 1;\n        } else {\n          contextLabel = contextLabel << 1 | referenceBitmap[i0][j0];\n        }\n      }\n      const pixel = decoder.readBit(contexts, contextLabel);\n      row[j] = pixel;\n    }\n  }\n  return bitmap;\n}\nfunction decodeSymbolDictionary(huffman, refinement, symbols, numberOfNewSymbols, numberOfExportedSymbols, huffmanTables, templateIndex, at, refinementTemplateIndex, refinementAt, decodingContext, huffmanInput) {\n  if (huffman && refinement) {\n    throw new Jbig2Error(\"symbol refinement with Huffman is not supported\");\n  }\n  const newSymbols = [];\n  let currentHeight = 0;\n  let symbolCodeLength = log2(symbols.length + numberOfNewSymbols);\n  const decoder = decodingContext.decoder;\n  const contextCache = decodingContext.contextCache;\n  let tableB1, symbolWidths;\n  if (huffman) {\n    tableB1 = getStandardTable(1);\n    symbolWidths = [];\n    symbolCodeLength = Math.max(symbolCodeLength, 1);\n  }\n  while (newSymbols.length < numberOfNewSymbols) {\n    const deltaHeight = huffman ? huffmanTables.tableDeltaHeight.decode(huffmanInput) : decodeInteger(contextCache, \"IADH\", decoder);\n    currentHeight += deltaHeight;\n    let currentWidth = 0,\n      totalWidth = 0;\n    const firstSymbol = huffman ? symbolWidths.length : 0;\n    while (true) {\n      const deltaWidth = huffman ? huffmanTables.tableDeltaWidth.decode(huffmanInput) : decodeInteger(contextCache, \"IADW\", decoder);\n      if (deltaWidth === null) {\n        break;\n      }\n      currentWidth += deltaWidth;\n      totalWidth += currentWidth;\n      let bitmap;\n      if (refinement) {\n        const numberOfInstances = decodeInteger(contextCache, \"IAAI\", decoder);\n        if (numberOfInstances > 1) {\n          bitmap = decodeTextRegion(huffman, refinement, currentWidth, currentHeight, 0, numberOfInstances, 1, symbols.concat(newSymbols), symbolCodeLength, 0, 0, 1, 0, huffmanTables, refinementTemplateIndex, refinementAt, decodingContext, 0, huffmanInput);\n        } else {\n          const symbolId = decodeIAID(contextCache, decoder, symbolCodeLength);\n          const rdx = decodeInteger(contextCache, \"IARDX\", decoder);\n          const rdy = decodeInteger(contextCache, \"IARDY\", decoder);\n          const symbol = symbolId < symbols.length ? symbols[symbolId] : newSymbols[symbolId - symbols.length];\n          bitmap = decodeRefinement(currentWidth, currentHeight, refinementTemplateIndex, symbol, rdx, rdy, false, refinementAt, decodingContext);\n        }\n        newSymbols.push(bitmap);\n      } else if (huffman) {\n        symbolWidths.push(currentWidth);\n      } else {\n        bitmap = decodeBitmap(false, currentWidth, currentHeight, templateIndex, false, null, at, decodingContext);\n        newSymbols.push(bitmap);\n      }\n    }\n    if (huffman && !refinement) {\n      const bitmapSize = huffmanTables.tableBitmapSize.decode(huffmanInput);\n      huffmanInput.byteAlign();\n      let collectiveBitmap;\n      if (bitmapSize === 0) {\n        collectiveBitmap = readUncompressedBitmap(huffmanInput, totalWidth, currentHeight);\n      } else {\n        const originalEnd = huffmanInput.end;\n        const bitmapEnd = huffmanInput.position + bitmapSize;\n        huffmanInput.end = bitmapEnd;\n        collectiveBitmap = decodeMMRBitmap(huffmanInput, totalWidth, currentHeight, false);\n        huffmanInput.end = originalEnd;\n        huffmanInput.position = bitmapEnd;\n      }\n      const numberOfSymbolsDecoded = symbolWidths.length;\n      if (firstSymbol === numberOfSymbolsDecoded - 1) {\n        newSymbols.push(collectiveBitmap);\n      } else {\n        let i,\n          y,\n          xMin = 0,\n          xMax,\n          bitmapWidth,\n          symbolBitmap;\n        for (i = firstSymbol; i < numberOfSymbolsDecoded; i++) {\n          bitmapWidth = symbolWidths[i];\n          xMax = xMin + bitmapWidth;\n          symbolBitmap = [];\n          for (y = 0; y < currentHeight; y++) {\n            symbolBitmap.push(collectiveBitmap[y].subarray(xMin, xMax));\n          }\n          newSymbols.push(symbolBitmap);\n          xMin = xMax;\n        }\n      }\n    }\n  }\n  const exportedSymbols = [],\n    flags = [];\n  let currentFlag = false,\n    i,\n    ii;\n  const totalSymbolsLength = symbols.length + numberOfNewSymbols;\n  while (flags.length < totalSymbolsLength) {\n    let runLength = huffman ? tableB1.decode(huffmanInput) : decodeInteger(contextCache, \"IAEX\", decoder);\n    while (runLength--) {\n      flags.push(currentFlag);\n    }\n    currentFlag = !currentFlag;\n  }\n  for (i = 0, ii = symbols.length; i < ii; i++) {\n    if (flags[i]) {\n      exportedSymbols.push(symbols[i]);\n    }\n  }\n  for (let j = 0; j < numberOfNewSymbols; i++, j++) {\n    if (flags[i]) {\n      exportedSymbols.push(newSymbols[j]);\n    }\n  }\n  return exportedSymbols;\n}\nfunction decodeTextRegion(huffman, refinement, width, height, defaultPixelValue, numberOfSymbolInstances, stripSize, inputSymbols, symbolCodeLength, transposed, dsOffset, referenceCorner, combinationOperator, huffmanTables, refinementTemplateIndex, refinementAt, decodingContext, logStripSize, huffmanInput) {\n  if (huffman && refinement) {\n    throw new Jbig2Error(\"refinement with Huffman is not supported\");\n  }\n  const bitmap = [];\n  let i, row;\n  for (i = 0; i < height; i++) {\n    row = new Uint8Array(width);\n    if (defaultPixelValue) {\n      for (let j = 0; j < width; j++) {\n        row[j] = defaultPixelValue;\n      }\n    }\n    bitmap.push(row);\n  }\n  const decoder = decodingContext.decoder;\n  const contextCache = decodingContext.contextCache;\n  let stripT = huffman ? -huffmanTables.tableDeltaT.decode(huffmanInput) : -decodeInteger(contextCache, \"IADT\", decoder);\n  let firstS = 0;\n  i = 0;\n  while (i < numberOfSymbolInstances) {\n    const deltaT = huffman ? huffmanTables.tableDeltaT.decode(huffmanInput) : decodeInteger(contextCache, \"IADT\", decoder);\n    stripT += deltaT;\n    const deltaFirstS = huffman ? huffmanTables.tableFirstS.decode(huffmanInput) : decodeInteger(contextCache, \"IAFS\", decoder);\n    firstS += deltaFirstS;\n    let currentS = firstS;\n    do {\n      let currentT = 0;\n      if (stripSize > 1) {\n        currentT = huffman ? huffmanInput.readBits(logStripSize) : decodeInteger(contextCache, \"IAIT\", decoder);\n      }\n      const t = stripSize * stripT + currentT;\n      const symbolId = huffman ? huffmanTables.symbolIDTable.decode(huffmanInput) : decodeIAID(contextCache, decoder, symbolCodeLength);\n      const applyRefinement = refinement && (huffman ? huffmanInput.readBit() : decodeInteger(contextCache, \"IARI\", decoder));\n      let symbolBitmap = inputSymbols[symbolId];\n      let symbolWidth = symbolBitmap[0].length;\n      let symbolHeight = symbolBitmap.length;\n      if (applyRefinement) {\n        const rdw = decodeInteger(contextCache, \"IARDW\", decoder);\n        const rdh = decodeInteger(contextCache, \"IARDH\", decoder);\n        const rdx = decodeInteger(contextCache, \"IARDX\", decoder);\n        const rdy = decodeInteger(contextCache, \"IARDY\", decoder);\n        symbolWidth += rdw;\n        symbolHeight += rdh;\n        symbolBitmap = decodeRefinement(symbolWidth, symbolHeight, refinementTemplateIndex, symbolBitmap, (rdw >> 1) + rdx, (rdh >> 1) + rdy, false, refinementAt, decodingContext);\n      }\n      let increment = 0;\n      if (!transposed) {\n        if (referenceCorner > 1) {\n          currentS += symbolWidth - 1;\n        } else {\n          increment = symbolWidth - 1;\n        }\n      } else if (!(referenceCorner & 1)) {\n        currentS += symbolHeight - 1;\n      } else {\n        increment = symbolHeight - 1;\n      }\n      const offsetT = t - (referenceCorner & 1 ? 0 : symbolHeight - 1);\n      const offsetS = currentS - (referenceCorner & 2 ? symbolWidth - 1 : 0);\n      let s2, t2, symbolRow;\n      if (transposed) {\n        for (s2 = 0; s2 < symbolHeight; s2++) {\n          row = bitmap[offsetS + s2];\n          if (!row) {\n            continue;\n          }\n          symbolRow = symbolBitmap[s2];\n          const maxWidth = Math.min(width - offsetT, symbolWidth);\n          switch (combinationOperator) {\n            case 0:\n              for (t2 = 0; t2 < maxWidth; t2++) {\n                row[offsetT + t2] |= symbolRow[t2];\n              }\n              break;\n            case 2:\n              for (t2 = 0; t2 < maxWidth; t2++) {\n                row[offsetT + t2] ^= symbolRow[t2];\n              }\n              break;\n            default:\n              throw new Jbig2Error(`operator ${combinationOperator} is not supported`);\n          }\n        }\n      } else {\n        for (t2 = 0; t2 < symbolHeight; t2++) {\n          row = bitmap[offsetT + t2];\n          if (!row) {\n            continue;\n          }\n          symbolRow = symbolBitmap[t2];\n          switch (combinationOperator) {\n            case 0:\n              for (s2 = 0; s2 < symbolWidth; s2++) {\n                row[offsetS + s2] |= symbolRow[s2];\n              }\n              break;\n            case 2:\n              for (s2 = 0; s2 < symbolWidth; s2++) {\n                row[offsetS + s2] ^= symbolRow[s2];\n              }\n              break;\n            default:\n              throw new Jbig2Error(`operator ${combinationOperator} is not supported`);\n          }\n        }\n      }\n      i++;\n      const deltaS = huffman ? huffmanTables.tableDeltaS.decode(huffmanInput) : decodeInteger(contextCache, \"IADS\", decoder);\n      if (deltaS === null) {\n        break;\n      }\n      currentS += increment + deltaS + dsOffset;\n    } while (true);\n  }\n  return bitmap;\n}\nfunction decodePatternDictionary(mmr, patternWidth, patternHeight, maxPatternIndex, template, decodingContext) {\n  const at = [];\n  if (!mmr) {\n    at.push({\n      x: -patternWidth,\n      y: 0\n    });\n    if (template === 0) {\n      at.push({\n        x: -3,\n        y: -1\n      }, {\n        x: 2,\n        y: -2\n      }, {\n        x: -2,\n        y: -2\n      });\n    }\n  }\n  const collectiveWidth = (maxPatternIndex + 1) * patternWidth;\n  const collectiveBitmap = decodeBitmap(mmr, collectiveWidth, patternHeight, template, false, null, at, decodingContext);\n  const patterns = [];\n  for (let i = 0; i <= maxPatternIndex; i++) {\n    const patternBitmap = [];\n    const xMin = patternWidth * i;\n    const xMax = xMin + patternWidth;\n    for (let y = 0; y < patternHeight; y++) {\n      patternBitmap.push(collectiveBitmap[y].subarray(xMin, xMax));\n    }\n    patterns.push(patternBitmap);\n  }\n  return patterns;\n}\nfunction decodeHalftoneRegion(mmr, patterns, template, regionWidth, regionHeight, defaultPixelValue, enableSkip, combinationOperator, gridWidth, gridHeight, gridOffsetX, gridOffsetY, gridVectorX, gridVectorY, decodingContext) {\n  const skip = null;\n  if (enableSkip) {\n    throw new Jbig2Error(\"skip is not supported\");\n  }\n  if (combinationOperator !== 0) {\n    throw new Jbig2Error(`operator \"${combinationOperator}\" is not supported in halftone region`);\n  }\n  const regionBitmap = [];\n  let i, j, row;\n  for (i = 0; i < regionHeight; i++) {\n    row = new Uint8Array(regionWidth);\n    if (defaultPixelValue) {\n      for (j = 0; j < regionWidth; j++) {\n        row[j] = defaultPixelValue;\n      }\n    }\n    regionBitmap.push(row);\n  }\n  const numberOfPatterns = patterns.length;\n  const pattern0 = patterns[0];\n  const patternWidth = pattern0[0].length,\n    patternHeight = pattern0.length;\n  const bitsPerValue = log2(numberOfPatterns);\n  const at = [];\n  if (!mmr) {\n    at.push({\n      x: template <= 1 ? 3 : 2,\n      y: -1\n    });\n    if (template === 0) {\n      at.push({\n        x: -3,\n        y: -1\n      }, {\n        x: 2,\n        y: -2\n      }, {\n        x: -2,\n        y: -2\n      });\n    }\n  }\n  const grayScaleBitPlanes = [];\n  let mmrInput, bitmap;\n  if (mmr) {\n    mmrInput = new Reader(decodingContext.data, decodingContext.start, decodingContext.end);\n  }\n  for (i = bitsPerValue - 1; i >= 0; i--) {\n    if (mmr) {\n      bitmap = decodeMMRBitmap(mmrInput, gridWidth, gridHeight, true);\n    } else {\n      bitmap = decodeBitmap(false, gridWidth, gridHeight, template, false, skip, at, decodingContext);\n    }\n    grayScaleBitPlanes[i] = bitmap;\n  }\n  let mg, ng, bit, patternIndex, patternBitmap, x, y, patternRow, regionRow;\n  for (mg = 0; mg < gridHeight; mg++) {\n    for (ng = 0; ng < gridWidth; ng++) {\n      bit = 0;\n      patternIndex = 0;\n      for (j = bitsPerValue - 1; j >= 0; j--) {\n        bit ^= grayScaleBitPlanes[j][mg][ng];\n        patternIndex |= bit << j;\n      }\n      patternBitmap = patterns[patternIndex];\n      x = gridOffsetX + mg * gridVectorY + ng * gridVectorX >> 8;\n      y = gridOffsetY + mg * gridVectorX - ng * gridVectorY >> 8;\n      if (x >= 0 && x + patternWidth <= regionWidth && y >= 0 && y + patternHeight <= regionHeight) {\n        for (i = 0; i < patternHeight; i++) {\n          regionRow = regionBitmap[y + i];\n          patternRow = patternBitmap[i];\n          for (j = 0; j < patternWidth; j++) {\n            regionRow[x + j] |= patternRow[j];\n          }\n        }\n      } else {\n        let regionX, regionY;\n        for (i = 0; i < patternHeight; i++) {\n          regionY = y + i;\n          if (regionY < 0 || regionY >= regionHeight) {\n            continue;\n          }\n          regionRow = regionBitmap[regionY];\n          patternRow = patternBitmap[i];\n          for (j = 0; j < patternWidth; j++) {\n            regionX = x + j;\n            if (regionX >= 0 && regionX < regionWidth) {\n              regionRow[regionX] |= patternRow[j];\n            }\n          }\n        }\n      }\n    }\n  }\n  return regionBitmap;\n}\nfunction readSegmentHeader(data, start) {\n  const segmentHeader = {};\n  segmentHeader.number = readUint32(data, start);\n  const flags = data[start + 4];\n  const segmentType = flags & 0x3f;\n  if (!SegmentTypes[segmentType]) {\n    throw new Jbig2Error(\"invalid segment type: \" + segmentType);\n  }\n  segmentHeader.type = segmentType;\n  segmentHeader.typeName = SegmentTypes[segmentType];\n  segmentHeader.deferredNonRetain = !!(flags & 0x80);\n  const pageAssociationFieldSize = !!(flags & 0x40);\n  const referredFlags = data[start + 5];\n  let referredToCount = referredFlags >> 5 & 7;\n  const retainBits = [referredFlags & 31];\n  let position = start + 6;\n  if (referredFlags === 7) {\n    referredToCount = readUint32(data, position - 1) & 0x1fffffff;\n    position += 3;\n    let bytes = referredToCount + 7 >> 3;\n    retainBits[0] = data[position++];\n    while (--bytes > 0) {\n      retainBits.push(data[position++]);\n    }\n  } else if (referredFlags === 5 || referredFlags === 6) {\n    throw new Jbig2Error(\"invalid referred-to flags\");\n  }\n  segmentHeader.retainBits = retainBits;\n  let referredToSegmentNumberSize = 4;\n  if (segmentHeader.number <= 256) {\n    referredToSegmentNumberSize = 1;\n  } else if (segmentHeader.number <= 65536) {\n    referredToSegmentNumberSize = 2;\n  }\n  const referredTo = [];\n  let i, ii;\n  for (i = 0; i < referredToCount; i++) {\n    let number;\n    if (referredToSegmentNumberSize === 1) {\n      number = data[position];\n    } else if (referredToSegmentNumberSize === 2) {\n      number = readUint16(data, position);\n    } else {\n      number = readUint32(data, position);\n    }\n    referredTo.push(number);\n    position += referredToSegmentNumberSize;\n  }\n  segmentHeader.referredTo = referredTo;\n  if (!pageAssociationFieldSize) {\n    segmentHeader.pageAssociation = data[position++];\n  } else {\n    segmentHeader.pageAssociation = readUint32(data, position);\n    position += 4;\n  }\n  segmentHeader.length = readUint32(data, position);\n  position += 4;\n  if (segmentHeader.length === 0xffffffff) {\n    if (segmentType === 38) {\n      const genericRegionInfo = readRegionSegmentInformation(data, position);\n      const genericRegionSegmentFlags = data[position + RegionSegmentInformationFieldLength];\n      const genericRegionMmr = !!(genericRegionSegmentFlags & 1);\n      const searchPatternLength = 6;\n      const searchPattern = new Uint8Array(searchPatternLength);\n      if (!genericRegionMmr) {\n        searchPattern[0] = 0xff;\n        searchPattern[1] = 0xac;\n      }\n      searchPattern[2] = genericRegionInfo.height >>> 24 & 0xff;\n      searchPattern[3] = genericRegionInfo.height >> 16 & 0xff;\n      searchPattern[4] = genericRegionInfo.height >> 8 & 0xff;\n      searchPattern[5] = genericRegionInfo.height & 0xff;\n      for (i = position, ii = data.length; i < ii; i++) {\n        let j = 0;\n        while (j < searchPatternLength && searchPattern[j] === data[i + j]) {\n          j++;\n        }\n        if (j === searchPatternLength) {\n          segmentHeader.length = i + searchPatternLength;\n          break;\n        }\n      }\n      if (segmentHeader.length === 0xffffffff) {\n        throw new Jbig2Error(\"segment end was not found\");\n      }\n    } else {\n      throw new Jbig2Error(\"invalid unknown segment length\");\n    }\n  }\n  segmentHeader.headerEnd = position;\n  return segmentHeader;\n}\nfunction readSegments(header, data, start, end) {\n  const segments = [];\n  let position = start;\n  while (position < end) {\n    const segmentHeader = readSegmentHeader(data, position);\n    position = segmentHeader.headerEnd;\n    const segment = {\n      header: segmentHeader,\n      data\n    };\n    if (!header.randomAccess) {\n      segment.start = position;\n      position += segmentHeader.length;\n      segment.end = position;\n    }\n    segments.push(segment);\n    if (segmentHeader.type === 51) {\n      break;\n    }\n  }\n  if (header.randomAccess) {\n    for (let i = 0, ii = segments.length; i < ii; i++) {\n      segments[i].start = position;\n      position += segments[i].header.length;\n      segments[i].end = position;\n    }\n  }\n  return segments;\n}\nfunction readRegionSegmentInformation(data, start) {\n  return {\n    width: readUint32(data, start),\n    height: readUint32(data, start + 4),\n    x: readUint32(data, start + 8),\n    y: readUint32(data, start + 12),\n    combinationOperator: data[start + 16] & 7\n  };\n}\nconst RegionSegmentInformationFieldLength = 17;\nfunction processSegment(segment, visitor) {\n  const header = segment.header;\n  const data = segment.data,\n    end = segment.end;\n  let position = segment.start;\n  let args, at, i, atLength;\n  switch (header.type) {\n    case 0:\n      const dictionary = {};\n      const dictionaryFlags = readUint16(data, position);\n      dictionary.huffman = !!(dictionaryFlags & 1);\n      dictionary.refinement = !!(dictionaryFlags & 2);\n      dictionary.huffmanDHSelector = dictionaryFlags >> 2 & 3;\n      dictionary.huffmanDWSelector = dictionaryFlags >> 4 & 3;\n      dictionary.bitmapSizeSelector = dictionaryFlags >> 6 & 1;\n      dictionary.aggregationInstancesSelector = dictionaryFlags >> 7 & 1;\n      dictionary.bitmapCodingContextUsed = !!(dictionaryFlags & 256);\n      dictionary.bitmapCodingContextRetained = !!(dictionaryFlags & 512);\n      dictionary.template = dictionaryFlags >> 10 & 3;\n      dictionary.refinementTemplate = dictionaryFlags >> 12 & 1;\n      position += 2;\n      if (!dictionary.huffman) {\n        atLength = dictionary.template === 0 ? 4 : 1;\n        at = [];\n        for (i = 0; i < atLength; i++) {\n          at.push({\n            x: readInt8(data, position),\n            y: readInt8(data, position + 1)\n          });\n          position += 2;\n        }\n        dictionary.at = at;\n      }\n      if (dictionary.refinement && !dictionary.refinementTemplate) {\n        at = [];\n        for (i = 0; i < 2; i++) {\n          at.push({\n            x: readInt8(data, position),\n            y: readInt8(data, position + 1)\n          });\n          position += 2;\n        }\n        dictionary.refinementAt = at;\n      }\n      dictionary.numberOfExportedSymbols = readUint32(data, position);\n      position += 4;\n      dictionary.numberOfNewSymbols = readUint32(data, position);\n      position += 4;\n      args = [dictionary, header.number, header.referredTo, data, position, end];\n      break;\n    case 6:\n    case 7:\n      const textRegion = {};\n      textRegion.info = readRegionSegmentInformation(data, position);\n      position += RegionSegmentInformationFieldLength;\n      const textRegionSegmentFlags = readUint16(data, position);\n      position += 2;\n      textRegion.huffman = !!(textRegionSegmentFlags & 1);\n      textRegion.refinement = !!(textRegionSegmentFlags & 2);\n      textRegion.logStripSize = textRegionSegmentFlags >> 2 & 3;\n      textRegion.stripSize = 1 << textRegion.logStripSize;\n      textRegion.referenceCorner = textRegionSegmentFlags >> 4 & 3;\n      textRegion.transposed = !!(textRegionSegmentFlags & 64);\n      textRegion.combinationOperator = textRegionSegmentFlags >> 7 & 3;\n      textRegion.defaultPixelValue = textRegionSegmentFlags >> 9 & 1;\n      textRegion.dsOffset = textRegionSegmentFlags << 17 >> 27;\n      textRegion.refinementTemplate = textRegionSegmentFlags >> 15 & 1;\n      if (textRegion.huffman) {\n        const textRegionHuffmanFlags = readUint16(data, position);\n        position += 2;\n        textRegion.huffmanFS = textRegionHuffmanFlags & 3;\n        textRegion.huffmanDS = textRegionHuffmanFlags >> 2 & 3;\n        textRegion.huffmanDT = textRegionHuffmanFlags >> 4 & 3;\n        textRegion.huffmanRefinementDW = textRegionHuffmanFlags >> 6 & 3;\n        textRegion.huffmanRefinementDH = textRegionHuffmanFlags >> 8 & 3;\n        textRegion.huffmanRefinementDX = textRegionHuffmanFlags >> 10 & 3;\n        textRegion.huffmanRefinementDY = textRegionHuffmanFlags >> 12 & 3;\n        textRegion.huffmanRefinementSizeSelector = !!(textRegionHuffmanFlags & 0x4000);\n      }\n      if (textRegion.refinement && !textRegion.refinementTemplate) {\n        at = [];\n        for (i = 0; i < 2; i++) {\n          at.push({\n            x: readInt8(data, position),\n            y: readInt8(data, position + 1)\n          });\n          position += 2;\n        }\n        textRegion.refinementAt = at;\n      }\n      textRegion.numberOfSymbolInstances = readUint32(data, position);\n      position += 4;\n      args = [textRegion, header.referredTo, data, position, end];\n      break;\n    case 16:\n      const patternDictionary = {};\n      const patternDictionaryFlags = data[position++];\n      patternDictionary.mmr = !!(patternDictionaryFlags & 1);\n      patternDictionary.template = patternDictionaryFlags >> 1 & 3;\n      patternDictionary.patternWidth = data[position++];\n      patternDictionary.patternHeight = data[position++];\n      patternDictionary.maxPatternIndex = readUint32(data, position);\n      position += 4;\n      args = [patternDictionary, header.number, data, position, end];\n      break;\n    case 22:\n    case 23:\n      const halftoneRegion = {};\n      halftoneRegion.info = readRegionSegmentInformation(data, position);\n      position += RegionSegmentInformationFieldLength;\n      const halftoneRegionFlags = data[position++];\n      halftoneRegion.mmr = !!(halftoneRegionFlags & 1);\n      halftoneRegion.template = halftoneRegionFlags >> 1 & 3;\n      halftoneRegion.enableSkip = !!(halftoneRegionFlags & 8);\n      halftoneRegion.combinationOperator = halftoneRegionFlags >> 4 & 7;\n      halftoneRegion.defaultPixelValue = halftoneRegionFlags >> 7 & 1;\n      halftoneRegion.gridWidth = readUint32(data, position);\n      position += 4;\n      halftoneRegion.gridHeight = readUint32(data, position);\n      position += 4;\n      halftoneRegion.gridOffsetX = readUint32(data, position) & 0xffffffff;\n      position += 4;\n      halftoneRegion.gridOffsetY = readUint32(data, position) & 0xffffffff;\n      position += 4;\n      halftoneRegion.gridVectorX = readUint16(data, position);\n      position += 2;\n      halftoneRegion.gridVectorY = readUint16(data, position);\n      position += 2;\n      args = [halftoneRegion, header.referredTo, data, position, end];\n      break;\n    case 38:\n    case 39:\n      const genericRegion = {};\n      genericRegion.info = readRegionSegmentInformation(data, position);\n      position += RegionSegmentInformationFieldLength;\n      const genericRegionSegmentFlags = data[position++];\n      genericRegion.mmr = !!(genericRegionSegmentFlags & 1);\n      genericRegion.template = genericRegionSegmentFlags >> 1 & 3;\n      genericRegion.prediction = !!(genericRegionSegmentFlags & 8);\n      if (!genericRegion.mmr) {\n        atLength = genericRegion.template === 0 ? 4 : 1;\n        at = [];\n        for (i = 0; i < atLength; i++) {\n          at.push({\n            x: readInt8(data, position),\n            y: readInt8(data, position + 1)\n          });\n          position += 2;\n        }\n        genericRegion.at = at;\n      }\n      args = [genericRegion, data, position, end];\n      break;\n    case 48:\n      const pageInfo = {\n        width: readUint32(data, position),\n        height: readUint32(data, position + 4),\n        resolutionX: readUint32(data, position + 8),\n        resolutionY: readUint32(data, position + 12)\n      };\n      if (pageInfo.height === 0xffffffff) {\n        delete pageInfo.height;\n      }\n      const pageSegmentFlags = data[position + 16];\n      readUint16(data, position + 17);\n      pageInfo.lossless = !!(pageSegmentFlags & 1);\n      pageInfo.refinement = !!(pageSegmentFlags & 2);\n      pageInfo.defaultPixelValue = pageSegmentFlags >> 2 & 1;\n      pageInfo.combinationOperator = pageSegmentFlags >> 3 & 3;\n      pageInfo.requiresBuffer = !!(pageSegmentFlags & 32);\n      pageInfo.combinationOperatorOverride = !!(pageSegmentFlags & 64);\n      args = [pageInfo];\n      break;\n    case 49:\n      break;\n    case 50:\n      break;\n    case 51:\n      break;\n    case 53:\n      args = [header.number, data, position, end];\n      break;\n    case 62:\n      break;\n    default:\n      throw new Jbig2Error(`segment type ${header.typeName}(${header.type}) is not implemented`);\n  }\n  const callbackName = \"on\" + header.typeName;\n  if (callbackName in visitor) {\n    visitor[callbackName].apply(visitor, args);\n  }\n}\nfunction processSegments(segments, visitor) {\n  for (let i = 0, ii = segments.length; i < ii; i++) {\n    processSegment(segments[i], visitor);\n  }\n}\nfunction parseJbig2Chunks(chunks) {\n  const visitor = new SimpleSegmentVisitor();\n  for (let i = 0, ii = chunks.length; i < ii; i++) {\n    const chunk = chunks[i];\n    const segments = readSegments({}, chunk.data, chunk.start, chunk.end);\n    processSegments(segments, visitor);\n  }\n  return visitor.buffer;\n}\nfunction parseJbig2(data) {\n  throw new Error(\"Not implemented: parseJbig2\");\n}\nclass SimpleSegmentVisitor {\n  onPageInformation(info) {\n    this.currentPageInfo = info;\n    const rowSize = info.width + 7 >> 3;\n    const buffer = new Uint8ClampedArray(rowSize * info.height);\n    if (info.defaultPixelValue) {\n      buffer.fill(0xff);\n    }\n    this.buffer = buffer;\n  }\n  drawBitmap(regionInfo, bitmap) {\n    const pageInfo = this.currentPageInfo;\n    const width = regionInfo.width,\n      height = regionInfo.height;\n    const rowSize = pageInfo.width + 7 >> 3;\n    const combinationOperator = pageInfo.combinationOperatorOverride ? regionInfo.combinationOperator : pageInfo.combinationOperator;\n    const buffer = this.buffer;\n    const mask0 = 128 >> (regionInfo.x & 7);\n    let offset0 = regionInfo.y * rowSize + (regionInfo.x >> 3);\n    let i, j, mask, offset;\n    switch (combinationOperator) {\n      case 0:\n        for (i = 0; i < height; i++) {\n          mask = mask0;\n          offset = offset0;\n          for (j = 0; j < width; j++) {\n            if (bitmap[i][j]) {\n              buffer[offset] |= mask;\n            }\n            mask >>= 1;\n            if (!mask) {\n              mask = 128;\n              offset++;\n            }\n          }\n          offset0 += rowSize;\n        }\n        break;\n      case 2:\n        for (i = 0; i < height; i++) {\n          mask = mask0;\n          offset = offset0;\n          for (j = 0; j < width; j++) {\n            if (bitmap[i][j]) {\n              buffer[offset] ^= mask;\n            }\n            mask >>= 1;\n            if (!mask) {\n              mask = 128;\n              offset++;\n            }\n          }\n          offset0 += rowSize;\n        }\n        break;\n      default:\n        throw new Jbig2Error(`operator ${combinationOperator} is not supported`);\n    }\n  }\n  onImmediateGenericRegion(region, data, start, end) {\n    const regionInfo = region.info;\n    const decodingContext = new DecodingContext(data, start, end);\n    const bitmap = decodeBitmap(region.mmr, regionInfo.width, regionInfo.height, region.template, region.prediction, null, region.at, decodingContext);\n    this.drawBitmap(regionInfo, bitmap);\n  }\n  onImmediateLosslessGenericRegion() {\n    this.onImmediateGenericRegion(...arguments);\n  }\n  onSymbolDictionary(dictionary, currentSegment, referredSegments, data, start, end) {\n    let huffmanTables, huffmanInput;\n    if (dictionary.huffman) {\n      huffmanTables = getSymbolDictionaryHuffmanTables(dictionary, referredSegments, this.customTables);\n      huffmanInput = new Reader(data, start, end);\n    }\n    let symbols = this.symbols;\n    if (!symbols) {\n      this.symbols = symbols = {};\n    }\n    const inputSymbols = [];\n    for (const referredSegment of referredSegments) {\n      const referredSymbols = symbols[referredSegment];\n      if (referredSymbols) {\n        inputSymbols.push(...referredSymbols);\n      }\n    }\n    const decodingContext = new DecodingContext(data, start, end);\n    symbols[currentSegment] = decodeSymbolDictionary(dictionary.huffman, dictionary.refinement, inputSymbols, dictionary.numberOfNewSymbols, dictionary.numberOfExportedSymbols, huffmanTables, dictionary.template, dictionary.at, dictionary.refinementTemplate, dictionary.refinementAt, decodingContext, huffmanInput);\n  }\n  onImmediateTextRegion(region, referredSegments, data, start, end) {\n    const regionInfo = region.info;\n    let huffmanTables, huffmanInput;\n    const symbols = this.symbols;\n    const inputSymbols = [];\n    for (const referredSegment of referredSegments) {\n      const referredSymbols = symbols[referredSegment];\n      if (referredSymbols) {\n        inputSymbols.push(...referredSymbols);\n      }\n    }\n    const symbolCodeLength = log2(inputSymbols.length);\n    if (region.huffman) {\n      huffmanInput = new Reader(data, start, end);\n      huffmanTables = getTextRegionHuffmanTables(region, referredSegments, this.customTables, inputSymbols.length, huffmanInput);\n    }\n    const decodingContext = new DecodingContext(data, start, end);\n    const bitmap = decodeTextRegion(region.huffman, region.refinement, regionInfo.width, regionInfo.height, region.defaultPixelValue, region.numberOfSymbolInstances, region.stripSize, inputSymbols, symbolCodeLength, region.transposed, region.dsOffset, region.referenceCorner, region.combinationOperator, huffmanTables, region.refinementTemplate, region.refinementAt, decodingContext, region.logStripSize, huffmanInput);\n    this.drawBitmap(regionInfo, bitmap);\n  }\n  onImmediateLosslessTextRegion() {\n    this.onImmediateTextRegion(...arguments);\n  }\n  onPatternDictionary(dictionary, currentSegment, data, start, end) {\n    let patterns = this.patterns;\n    if (!patterns) {\n      this.patterns = patterns = {};\n    }\n    const decodingContext = new DecodingContext(data, start, end);\n    patterns[currentSegment] = decodePatternDictionary(dictionary.mmr, dictionary.patternWidth, dictionary.patternHeight, dictionary.maxPatternIndex, dictionary.template, decodingContext);\n  }\n  onImmediateHalftoneRegion(region, referredSegments, data, start, end) {\n    const patterns = this.patterns[referredSegments[0]];\n    const regionInfo = region.info;\n    const decodingContext = new DecodingContext(data, start, end);\n    const bitmap = decodeHalftoneRegion(region.mmr, patterns, region.template, regionInfo.width, regionInfo.height, region.defaultPixelValue, region.enableSkip, region.combinationOperator, region.gridWidth, region.gridHeight, region.gridOffsetX, region.gridOffsetY, region.gridVectorX, region.gridVectorY, decodingContext);\n    this.drawBitmap(regionInfo, bitmap);\n  }\n  onImmediateLosslessHalftoneRegion() {\n    this.onImmediateHalftoneRegion(...arguments);\n  }\n  onTables(currentSegment, data, start, end) {\n    let customTables = this.customTables;\n    if (!customTables) {\n      this.customTables = customTables = {};\n    }\n    customTables[currentSegment] = decodeTablesSegment(data, start, end);\n  }\n}\nclass HuffmanLine {\n  constructor(lineData) {\n    if (lineData.length === 2) {\n      this.isOOB = true;\n      this.rangeLow = 0;\n      this.prefixLength = lineData[0];\n      this.rangeLength = 0;\n      this.prefixCode = lineData[1];\n      this.isLowerRange = false;\n    } else {\n      this.isOOB = false;\n      this.rangeLow = lineData[0];\n      this.prefixLength = lineData[1];\n      this.rangeLength = lineData[2];\n      this.prefixCode = lineData[3];\n      this.isLowerRange = lineData[4] === \"lower\";\n    }\n  }\n}\nclass HuffmanTreeNode {\n  constructor(line) {\n    this.children = [];\n    if (line) {\n      this.isLeaf = true;\n      this.rangeLength = line.rangeLength;\n      this.rangeLow = line.rangeLow;\n      this.isLowerRange = line.isLowerRange;\n      this.isOOB = line.isOOB;\n    } else {\n      this.isLeaf = false;\n    }\n  }\n  buildTree(line, shift) {\n    const bit = line.prefixCode >> shift & 1;\n    if (shift <= 0) {\n      this.children[bit] = new HuffmanTreeNode(line);\n    } else {\n      let node = this.children[bit];\n      if (!node) {\n        this.children[bit] = node = new HuffmanTreeNode(null);\n      }\n      node.buildTree(line, shift - 1);\n    }\n  }\n  decodeNode(reader) {\n    if (this.isLeaf) {\n      if (this.isOOB) {\n        return null;\n      }\n      const htOffset = reader.readBits(this.rangeLength);\n      return this.rangeLow + (this.isLowerRange ? -htOffset : htOffset);\n    }\n    const node = this.children[reader.readBit()];\n    if (!node) {\n      throw new Jbig2Error(\"invalid Huffman data\");\n    }\n    return node.decodeNode(reader);\n  }\n}\nclass HuffmanTable {\n  constructor(lines, prefixCodesDone) {\n    if (!prefixCodesDone) {\n      this.assignPrefixCodes(lines);\n    }\n    this.rootNode = new HuffmanTreeNode(null);\n    for (let i = 0, ii = lines.length; i < ii; i++) {\n      const line = lines[i];\n      if (line.prefixLength > 0) {\n        this.rootNode.buildTree(line, line.prefixLength - 1);\n      }\n    }\n  }\n  decode(reader) {\n    return this.rootNode.decodeNode(reader);\n  }\n  assignPrefixCodes(lines) {\n    const linesLength = lines.length;\n    let prefixLengthMax = 0;\n    for (let i = 0; i < linesLength; i++) {\n      prefixLengthMax = Math.max(prefixLengthMax, lines[i].prefixLength);\n    }\n    const histogram = new Uint32Array(prefixLengthMax + 1);\n    for (let i = 0; i < linesLength; i++) {\n      histogram[lines[i].prefixLength]++;\n    }\n    let currentLength = 1,\n      firstCode = 0,\n      currentCode,\n      currentTemp,\n      line;\n    histogram[0] = 0;\n    while (currentLength <= prefixLengthMax) {\n      firstCode = firstCode + histogram[currentLength - 1] << 1;\n      currentCode = firstCode;\n      currentTemp = 0;\n      while (currentTemp < linesLength) {\n        line = lines[currentTemp];\n        if (line.prefixLength === currentLength) {\n          line.prefixCode = currentCode;\n          currentCode++;\n        }\n        currentTemp++;\n      }\n      currentLength++;\n    }\n  }\n}\nfunction decodeTablesSegment(data, start, end) {\n  const flags = data[start];\n  const lowestValue = readUint32(data, start + 1) & 0xffffffff;\n  const highestValue = readUint32(data, start + 5) & 0xffffffff;\n  const reader = new Reader(data, start + 9, end);\n  const prefixSizeBits = (flags >> 1 & 7) + 1;\n  const rangeSizeBits = (flags >> 4 & 7) + 1;\n  const lines = [];\n  let prefixLength,\n    rangeLength,\n    currentRangeLow = lowestValue;\n  do {\n    prefixLength = reader.readBits(prefixSizeBits);\n    rangeLength = reader.readBits(rangeSizeBits);\n    lines.push(new HuffmanLine([currentRangeLow, prefixLength, rangeLength, 0]));\n    currentRangeLow += 1 << rangeLength;\n  } while (currentRangeLow < highestValue);\n  prefixLength = reader.readBits(prefixSizeBits);\n  lines.push(new HuffmanLine([lowestValue - 1, prefixLength, 32, 0, \"lower\"]));\n  prefixLength = reader.readBits(prefixSizeBits);\n  lines.push(new HuffmanLine([highestValue, prefixLength, 32, 0]));\n  if (flags & 1) {\n    prefixLength = reader.readBits(prefixSizeBits);\n    lines.push(new HuffmanLine([prefixLength, 0]));\n  }\n  return new HuffmanTable(lines, false);\n}\nconst standardTablesCache = {};\nfunction getStandardTable(number) {\n  let table = standardTablesCache[number];\n  if (table) {\n    return table;\n  }\n  let lines;\n  switch (number) {\n    case 1:\n      lines = [[0, 1, 4, 0x0], [16, 2, 8, 0x2], [272, 3, 16, 0x6], [65808, 3, 32, 0x7]];\n      break;\n    case 2:\n      lines = [[0, 1, 0, 0x0], [1, 2, 0, 0x2], [2, 3, 0, 0x6], [3, 4, 3, 0xe], [11, 5, 6, 0x1e], [75, 6, 32, 0x3e], [6, 0x3f]];\n      break;\n    case 3:\n      lines = [[-256, 8, 8, 0xfe], [0, 1, 0, 0x0], [1, 2, 0, 0x2], [2, 3, 0, 0x6], [3, 4, 3, 0xe], [11, 5, 6, 0x1e], [-257, 8, 32, 0xff, \"lower\"], [75, 7, 32, 0x7e], [6, 0x3e]];\n      break;\n    case 4:\n      lines = [[1, 1, 0, 0x0], [2, 2, 0, 0x2], [3, 3, 0, 0x6], [4, 4, 3, 0xe], [12, 5, 6, 0x1e], [76, 5, 32, 0x1f]];\n      break;\n    case 5:\n      lines = [[-255, 7, 8, 0x7e], [1, 1, 0, 0x0], [2, 2, 0, 0x2], [3, 3, 0, 0x6], [4, 4, 3, 0xe], [12, 5, 6, 0x1e], [-256, 7, 32, 0x7f, \"lower\"], [76, 6, 32, 0x3e]];\n      break;\n    case 6:\n      lines = [[-2048, 5, 10, 0x1c], [-1024, 4, 9, 0x8], [-512, 4, 8, 0x9], [-256, 4, 7, 0xa], [-128, 5, 6, 0x1d], [-64, 5, 5, 0x1e], [-32, 4, 5, 0xb], [0, 2, 7, 0x0], [128, 3, 7, 0x2], [256, 3, 8, 0x3], [512, 4, 9, 0xc], [1024, 4, 10, 0xd], [-2049, 6, 32, 0x3e, \"lower\"], [2048, 6, 32, 0x3f]];\n      break;\n    case 7:\n      lines = [[-1024, 4, 9, 0x8], [-512, 3, 8, 0x0], [-256, 4, 7, 0x9], [-128, 5, 6, 0x1a], [-64, 5, 5, 0x1b], [-32, 4, 5, 0xa], [0, 4, 5, 0xb], [32, 5, 5, 0x1c], [64, 5, 6, 0x1d], [128, 4, 7, 0xc], [256, 3, 8, 0x1], [512, 3, 9, 0x2], [1024, 3, 10, 0x3], [-1025, 5, 32, 0x1e, \"lower\"], [2048, 5, 32, 0x1f]];\n      break;\n    case 8:\n      lines = [[-15, 8, 3, 0xfc], [-7, 9, 1, 0x1fc], [-5, 8, 1, 0xfd], [-3, 9, 0, 0x1fd], [-2, 7, 0, 0x7c], [-1, 4, 0, 0xa], [0, 2, 1, 0x0], [2, 5, 0, 0x1a], [3, 6, 0, 0x3a], [4, 3, 4, 0x4], [20, 6, 1, 0x3b], [22, 4, 4, 0xb], [38, 4, 5, 0xc], [70, 5, 6, 0x1b], [134, 5, 7, 0x1c], [262, 6, 7, 0x3c], [390, 7, 8, 0x7d], [646, 6, 10, 0x3d], [-16, 9, 32, 0x1fe, \"lower\"], [1670, 9, 32, 0x1ff], [2, 0x1]];\n      break;\n    case 9:\n      lines = [[-31, 8, 4, 0xfc], [-15, 9, 2, 0x1fc], [-11, 8, 2, 0xfd], [-7, 9, 1, 0x1fd], [-5, 7, 1, 0x7c], [-3, 4, 1, 0xa], [-1, 3, 1, 0x2], [1, 3, 1, 0x3], [3, 5, 1, 0x1a], [5, 6, 1, 0x3a], [7, 3, 5, 0x4], [39, 6, 2, 0x3b], [43, 4, 5, 0xb], [75, 4, 6, 0xc], [139, 5, 7, 0x1b], [267, 5, 8, 0x1c], [523, 6, 8, 0x3c], [779, 7, 9, 0x7d], [1291, 6, 11, 0x3d], [-32, 9, 32, 0x1fe, \"lower\"], [3339, 9, 32, 0x1ff], [2, 0x0]];\n      break;\n    case 10:\n      lines = [[-21, 7, 4, 0x7a], [-5, 8, 0, 0xfc], [-4, 7, 0, 0x7b], [-3, 5, 0, 0x18], [-2, 2, 2, 0x0], [2, 5, 0, 0x19], [3, 6, 0, 0x36], [4, 7, 0, 0x7c], [5, 8, 0, 0xfd], [6, 2, 6, 0x1], [70, 5, 5, 0x1a], [102, 6, 5, 0x37], [134, 6, 6, 0x38], [198, 6, 7, 0x39], [326, 6, 8, 0x3a], [582, 6, 9, 0x3b], [1094, 6, 10, 0x3c], [2118, 7, 11, 0x7d], [-22, 8, 32, 0xfe, \"lower\"], [4166, 8, 32, 0xff], [2, 0x2]];\n      break;\n    case 11:\n      lines = [[1, 1, 0, 0x0], [2, 2, 1, 0x2], [4, 4, 0, 0xc], [5, 4, 1, 0xd], [7, 5, 1, 0x1c], [9, 5, 2, 0x1d], [13, 6, 2, 0x3c], [17, 7, 2, 0x7a], [21, 7, 3, 0x7b], [29, 7, 4, 0x7c], [45, 7, 5, 0x7d], [77, 7, 6, 0x7e], [141, 7, 32, 0x7f]];\n      break;\n    case 12:\n      lines = [[1, 1, 0, 0x0], [2, 2, 0, 0x2], [3, 3, 1, 0x6], [5, 5, 0, 0x1c], [6, 5, 1, 0x1d], [8, 6, 1, 0x3c], [10, 7, 0, 0x7a], [11, 7, 1, 0x7b], [13, 7, 2, 0x7c], [17, 7, 3, 0x7d], [25, 7, 4, 0x7e], [41, 8, 5, 0xfe], [73, 8, 32, 0xff]];\n      break;\n    case 13:\n      lines = [[1, 1, 0, 0x0], [2, 3, 0, 0x4], [3, 4, 0, 0xc], [4, 5, 0, 0x1c], [5, 4, 1, 0xd], [7, 3, 3, 0x5], [15, 6, 1, 0x3a], [17, 6, 2, 0x3b], [21, 6, 3, 0x3c], [29, 6, 4, 0x3d], [45, 6, 5, 0x3e], [77, 7, 6, 0x7e], [141, 7, 32, 0x7f]];\n      break;\n    case 14:\n      lines = [[-2, 3, 0, 0x4], [-1, 3, 0, 0x5], [0, 1, 0, 0x0], [1, 3, 0, 0x6], [2, 3, 0, 0x7]];\n      break;\n    case 15:\n      lines = [[-24, 7, 4, 0x7c], [-8, 6, 2, 0x3c], [-4, 5, 1, 0x1c], [-2, 4, 0, 0xc], [-1, 3, 0, 0x4], [0, 1, 0, 0x0], [1, 3, 0, 0x5], [2, 4, 0, 0xd], [3, 5, 1, 0x1d], [5, 6, 2, 0x3d], [9, 7, 4, 0x7d], [-25, 7, 32, 0x7e, \"lower\"], [25, 7, 32, 0x7f]];\n      break;\n    default:\n      throw new Jbig2Error(`standard table B.${number} does not exist`);\n  }\n  for (let i = 0, ii = lines.length; i < ii; i++) {\n    lines[i] = new HuffmanLine(lines[i]);\n  }\n  table = new HuffmanTable(lines, true);\n  standardTablesCache[number] = table;\n  return table;\n}\nclass Reader {\n  constructor(data, start, end) {\n    this.data = data;\n    this.start = start;\n    this.end = end;\n    this.position = start;\n    this.shift = -1;\n    this.currentByte = 0;\n  }\n  readBit() {\n    if (this.shift < 0) {\n      if (this.position >= this.end) {\n        throw new Jbig2Error(\"end of data while reading bit\");\n      }\n      this.currentByte = this.data[this.position++];\n      this.shift = 7;\n    }\n    const bit = this.currentByte >> this.shift & 1;\n    this.shift--;\n    return bit;\n  }\n  readBits(numBits) {\n    let result = 0,\n      i;\n    for (i = numBits - 1; i >= 0; i--) {\n      result |= this.readBit() << i;\n    }\n    return result;\n  }\n  byteAlign() {\n    this.shift = -1;\n  }\n  next() {\n    if (this.position >= this.end) {\n      return -1;\n    }\n    return this.data[this.position++];\n  }\n}\nfunction getCustomHuffmanTable(index, referredTo, customTables) {\n  let currentIndex = 0;\n  for (let i = 0, ii = referredTo.length; i < ii; i++) {\n    const table = customTables[referredTo[i]];\n    if (table) {\n      if (index === currentIndex) {\n        return table;\n      }\n      currentIndex++;\n    }\n  }\n  throw new Jbig2Error(\"can't find custom Huffman table\");\n}\nfunction getTextRegionHuffmanTables(textRegion, referredTo, customTables, numberOfSymbols, reader) {\n  const codes = [];\n  for (let i = 0; i <= 34; i++) {\n    const codeLength = reader.readBits(4);\n    codes.push(new HuffmanLine([i, codeLength, 0, 0]));\n  }\n  const runCodesTable = new HuffmanTable(codes, false);\n  codes.length = 0;\n  for (let i = 0; i < numberOfSymbols;) {\n    const codeLength = runCodesTable.decode(reader);\n    if (codeLength >= 32) {\n      let repeatedLength, numberOfRepeats, j;\n      switch (codeLength) {\n        case 32:\n          if (i === 0) {\n            throw new Jbig2Error(\"no previous value in symbol ID table\");\n          }\n          numberOfRepeats = reader.readBits(2) + 3;\n          repeatedLength = codes[i - 1].prefixLength;\n          break;\n        case 33:\n          numberOfRepeats = reader.readBits(3) + 3;\n          repeatedLength = 0;\n          break;\n        case 34:\n          numberOfRepeats = reader.readBits(7) + 11;\n          repeatedLength = 0;\n          break;\n        default:\n          throw new Jbig2Error(\"invalid code length in symbol ID table\");\n      }\n      for (j = 0; j < numberOfRepeats; j++) {\n        codes.push(new HuffmanLine([i, repeatedLength, 0, 0]));\n        i++;\n      }\n    } else {\n      codes.push(new HuffmanLine([i, codeLength, 0, 0]));\n      i++;\n    }\n  }\n  reader.byteAlign();\n  const symbolIDTable = new HuffmanTable(codes, false);\n  let customIndex = 0,\n    tableFirstS,\n    tableDeltaS,\n    tableDeltaT;\n  switch (textRegion.huffmanFS) {\n    case 0:\n    case 1:\n      tableFirstS = getStandardTable(textRegion.huffmanFS + 6);\n      break;\n    case 3:\n      tableFirstS = getCustomHuffmanTable(customIndex, referredTo, customTables);\n      customIndex++;\n      break;\n    default:\n      throw new Jbig2Error(\"invalid Huffman FS selector\");\n  }\n  switch (textRegion.huffmanDS) {\n    case 0:\n    case 1:\n    case 2:\n      tableDeltaS = getStandardTable(textRegion.huffmanDS + 8);\n      break;\n    case 3:\n      tableDeltaS = getCustomHuffmanTable(customIndex, referredTo, customTables);\n      customIndex++;\n      break;\n    default:\n      throw new Jbig2Error(\"invalid Huffman DS selector\");\n  }\n  switch (textRegion.huffmanDT) {\n    case 0:\n    case 1:\n    case 2:\n      tableDeltaT = getStandardTable(textRegion.huffmanDT + 11);\n      break;\n    case 3:\n      tableDeltaT = getCustomHuffmanTable(customIndex, referredTo, customTables);\n      customIndex++;\n      break;\n    default:\n      throw new Jbig2Error(\"invalid Huffman DT selector\");\n  }\n  if (textRegion.refinement) {\n    throw new Jbig2Error(\"refinement with Huffman is not supported\");\n  }\n  return {\n    symbolIDTable,\n    tableFirstS,\n    tableDeltaS,\n    tableDeltaT\n  };\n}\nfunction getSymbolDictionaryHuffmanTables(dictionary, referredTo, customTables) {\n  let customIndex = 0,\n    tableDeltaHeight,\n    tableDeltaWidth;\n  switch (dictionary.huffmanDHSelector) {\n    case 0:\n    case 1:\n      tableDeltaHeight = getStandardTable(dictionary.huffmanDHSelector + 4);\n      break;\n    case 3:\n      tableDeltaHeight = getCustomHuffmanTable(customIndex, referredTo, customTables);\n      customIndex++;\n      break;\n    default:\n      throw new Jbig2Error(\"invalid Huffman DH selector\");\n  }\n  switch (dictionary.huffmanDWSelector) {\n    case 0:\n    case 1:\n      tableDeltaWidth = getStandardTable(dictionary.huffmanDWSelector + 2);\n      break;\n    case 3:\n      tableDeltaWidth = getCustomHuffmanTable(customIndex, referredTo, customTables);\n      customIndex++;\n      break;\n    default:\n      throw new Jbig2Error(\"invalid Huffman DW selector\");\n  }\n  let tableBitmapSize, tableAggregateInstances;\n  if (dictionary.bitmapSizeSelector) {\n    tableBitmapSize = getCustomHuffmanTable(customIndex, referredTo, customTables);\n    customIndex++;\n  } else {\n    tableBitmapSize = getStandardTable(1);\n  }\n  if (dictionary.aggregationInstancesSelector) {\n    tableAggregateInstances = getCustomHuffmanTable(customIndex, referredTo, customTables);\n  } else {\n    tableAggregateInstances = getStandardTable(1);\n  }\n  return {\n    tableDeltaHeight,\n    tableDeltaWidth,\n    tableBitmapSize,\n    tableAggregateInstances\n  };\n}\nfunction readUncompressedBitmap(reader, width, height) {\n  const bitmap = [];\n  for (let y = 0; y < height; y++) {\n    const row = new Uint8Array(width);\n    bitmap.push(row);\n    for (let x = 0; x < width; x++) {\n      row[x] = reader.readBit();\n    }\n    reader.byteAlign();\n  }\n  return bitmap;\n}\nfunction decodeMMRBitmap(input, width, height, endOfBlock) {\n  const params = {\n    K: -1,\n    Columns: width,\n    Rows: height,\n    BlackIs1: true,\n    EndOfBlock: endOfBlock\n  };\n  const decoder = new CCITTFaxDecoder(input, params);\n  const bitmap = [];\n  let currentByte,\n    eof = false;\n  for (let y = 0; y < height; y++) {\n    const row = new Uint8Array(width);\n    bitmap.push(row);\n    let shift = -1;\n    for (let x = 0; x < width; x++) {\n      if (shift < 0) {\n        currentByte = decoder.readNextChar();\n        if (currentByte === -1) {\n          currentByte = 0;\n          eof = true;\n        }\n        shift = 7;\n      }\n      row[x] = currentByte >> shift & 1;\n      shift--;\n    }\n  }\n  if (endOfBlock && !eof) {\n    const lookForEOFLimit = 5;\n    for (let i = 0; i < lookForEOFLimit; i++) {\n      if (decoder.readNextChar() === -1) {\n        break;\n      }\n    }\n  }\n  return bitmap;\n}\nclass Jbig2Image {\n  parseChunks(chunks) {\n    return parseJbig2Chunks(chunks);\n  }\n  parse(data) {\n    throw new Error(\"Not implemented: Jbig2Image.parse\");\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/jbig2_stream.js\n\n\n\n\n\nclass Jbig2Stream extends DecodeStream {\n  constructor(stream, maybeLength, params) {\n    super(maybeLength);\n    this.stream = stream;\n    this.dict = stream.dict;\n    this.maybeLength = maybeLength;\n    this.params = params;\n  }\n  get bytes() {\n    return shadow(this, \"bytes\", this.stream.getBytes(this.maybeLength));\n  }\n  ensureBuffer(requested) {}\n  readBlock() {\n    if (this.eof) {\n      return;\n    }\n    const jbig2Image = new Jbig2Image();\n    const chunks = [];\n    if (this.params instanceof Dict) {\n      const globalsStream = this.params.get(\"JBIG2Globals\");\n      if (globalsStream instanceof BaseStream) {\n        const globals = globalsStream.getBytes();\n        chunks.push({\n          data: globals,\n          start: 0,\n          end: globals.length\n        });\n      }\n    }\n    chunks.push({\n      data: this.bytes,\n      start: 0,\n      end: this.bytes.length\n    });\n    const data = jbig2Image.parseChunks(chunks);\n    const dataLength = data.length;\n    for (let i = 0; i < dataLength; i++) {\n      data[i] ^= 0xff;\n    }\n    this.buffer = data;\n    this.bufferLength = dataLength;\n    this.eof = true;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/shared/image_utils.js\n\nfunction convertToRGBA(params) {\n  switch (params.kind) {\n    case ImageKind.GRAYSCALE_1BPP:\n      return convertBlackAndWhiteToRGBA(params);\n    case ImageKind.RGB_24BPP:\n      return convertRGBToRGBA(params);\n  }\n  return null;\n}\nfunction convertBlackAndWhiteToRGBA({\n  src,\n  srcPos = 0,\n  dest,\n  width,\n  height,\n  nonBlackColor = 0xffffffff,\n  inverseDecode = false\n}) {\n  const black = FeatureTest.isLittleEndian ? 0xff000000 : 0x000000ff;\n  const [zeroMapping, oneMapping] = inverseDecode ? [nonBlackColor, black] : [black, nonBlackColor];\n  const widthInSource = width >> 3;\n  const widthRemainder = width & 7;\n  const srcLength = src.length;\n  dest = new Uint32Array(dest.buffer);\n  let destPos = 0;\n  for (let i = 0; i < height; i++) {\n    for (const max = srcPos + widthInSource; srcPos < max; srcPos++) {\n      const elem = srcPos < srcLength ? src[srcPos] : 255;\n      dest[destPos++] = elem & 0b10000000 ? oneMapping : zeroMapping;\n      dest[destPos++] = elem & 0b1000000 ? oneMapping : zeroMapping;\n      dest[destPos++] = elem & 0b100000 ? oneMapping : zeroMapping;\n      dest[destPos++] = elem & 0b10000 ? oneMapping : zeroMapping;\n      dest[destPos++] = elem & 0b1000 ? oneMapping : zeroMapping;\n      dest[destPos++] = elem & 0b100 ? oneMapping : zeroMapping;\n      dest[destPos++] = elem & 0b10 ? oneMapping : zeroMapping;\n      dest[destPos++] = elem & 0b1 ? oneMapping : zeroMapping;\n    }\n    if (widthRemainder === 0) {\n      continue;\n    }\n    const elem = srcPos < srcLength ? src[srcPos++] : 255;\n    for (let j = 0; j < widthRemainder; j++) {\n      dest[destPos++] = elem & 1 << 7 - j ? oneMapping : zeroMapping;\n    }\n  }\n  return {\n    srcPos,\n    destPos\n  };\n}\nfunction convertRGBToRGBA({\n  src,\n  srcPos = 0,\n  dest,\n  destPos = 0,\n  width,\n  height\n}) {\n  let i = 0;\n  const len32 = src.length >> 2;\n  const src32 = new Uint32Array(src.buffer, srcPos, len32);\n  if (FeatureTest.isLittleEndian) {\n    for (; i < len32 - 2; i += 3, destPos += 4) {\n      const s1 = src32[i];\n      const s2 = src32[i + 1];\n      const s3 = src32[i + 2];\n      dest[destPos] = s1 | 0xff000000;\n      dest[destPos + 1] = s1 >>> 24 | s2 << 8 | 0xff000000;\n      dest[destPos + 2] = s2 >>> 16 | s3 << 16 | 0xff000000;\n      dest[destPos + 3] = s3 >>> 8 | 0xff000000;\n    }\n    for (let j = i * 4, jj = src.length; j < jj; j += 3) {\n      dest[destPos++] = src[j] | src[j + 1] << 8 | src[j + 2] << 16 | 0xff000000;\n    }\n  } else {\n    for (; i < len32 - 2; i += 3, destPos += 4) {\n      const s1 = src32[i];\n      const s2 = src32[i + 1];\n      const s3 = src32[i + 2];\n      dest[destPos] = s1 | 0xff;\n      dest[destPos + 1] = s1 << 24 | s2 >>> 8 | 0xff;\n      dest[destPos + 2] = s2 << 16 | s3 >>> 16 | 0xff;\n      dest[destPos + 3] = s3 << 8 | 0xff;\n    }\n    for (let j = i * 4, jj = src.length; j < jj; j += 3) {\n      dest[destPos++] = src[j] << 24 | src[j + 1] << 16 | src[j + 2] << 8 | 0xff;\n    }\n  }\n  return {\n    srcPos,\n    destPos\n  };\n}\nfunction grayToRGBA(src, dest) {\n  if (FeatureTest.isLittleEndian) {\n    for (let i = 0, ii = src.length; i < ii; i++) {\n      dest[i] = src[i] * 0x10101 | 0xff000000;\n    }\n  } else {\n    for (let i = 0, ii = src.length; i < ii; i++) {\n      dest[i] = src[i] * 0x1010100 | 0x000000ff;\n    }\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/jpg.js\n\n\n\nclass JpegError extends BaseException {\n  constructor(msg) {\n    super(msg, \"JpegError\");\n  }\n}\nclass DNLMarkerError extends BaseException {\n  constructor(message, scanLines) {\n    super(message, \"DNLMarkerError\");\n    this.scanLines = scanLines;\n  }\n}\nclass EOIMarkerError extends BaseException {\n  constructor(msg) {\n    super(msg, \"EOIMarkerError\");\n  }\n}\nconst dctZigZag = new Uint8Array([0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63]);\nconst dctCos1 = 4017;\nconst dctSin1 = 799;\nconst dctCos3 = 3406;\nconst dctSin3 = 2276;\nconst dctCos6 = 1567;\nconst dctSin6 = 3784;\nconst dctSqrt2 = 5793;\nconst dctSqrt1d2 = 2896;\nfunction buildHuffmanTable(codeLengths, values) {\n  let k = 0,\n    i,\n    j,\n    length = 16;\n  while (length > 0 && !codeLengths[length - 1]) {\n    length--;\n  }\n  const code = [{\n    children: [],\n    index: 0\n  }];\n  let p = code[0],\n    q;\n  for (i = 0; i < length; i++) {\n    for (j = 0; j < codeLengths[i]; j++) {\n      p = code.pop();\n      p.children[p.index] = values[k];\n      while (p.index > 0) {\n        p = code.pop();\n      }\n      p.index++;\n      code.push(p);\n      while (code.length <= i) {\n        code.push(q = {\n          children: [],\n          index: 0\n        });\n        p.children[p.index] = q.children;\n        p = q;\n      }\n      k++;\n    }\n    if (i + 1 < length) {\n      code.push(q = {\n        children: [],\n        index: 0\n      });\n      p.children[p.index] = q.children;\n      p = q;\n    }\n  }\n  return code[0].children;\n}\nfunction getBlockBufferOffset(component, row, col) {\n  return 64 * ((component.blocksPerLine + 1) * row + col);\n}\nfunction decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successivePrev, successive, parseDNLMarker = false) {\n  const mcusPerLine = frame.mcusPerLine;\n  const progressive = frame.progressive;\n  const startOffset = offset;\n  let bitsData = 0,\n    bitsCount = 0;\n  function readBit() {\n    if (bitsCount > 0) {\n      bitsCount--;\n      return bitsData >> bitsCount & 1;\n    }\n    bitsData = data[offset++];\n    if (bitsData === 0xff) {\n      const nextByte = data[offset++];\n      if (nextByte) {\n        if (nextByte === 0xdc && parseDNLMarker) {\n          offset += 2;\n          const scanLines = readUint16(data, offset);\n          offset += 2;\n          if (scanLines > 0 && scanLines !== frame.scanLines) {\n            throw new DNLMarkerError(\"Found DNL marker (0xFFDC) while parsing scan data\", scanLines);\n          }\n        } else if (nextByte === 0xd9) {\n          if (parseDNLMarker) {\n            const maybeScanLines = blockRow * (frame.precision === 8 ? 8 : 0);\n            if (maybeScanLines > 0 && Math.round(frame.scanLines / maybeScanLines) >= 5) {\n              throw new DNLMarkerError(\"Found EOI marker (0xFFD9) while parsing scan data, \" + \"possibly caused by incorrect `scanLines` parameter\", maybeScanLines);\n            }\n          }\n          throw new EOIMarkerError(\"Found EOI marker (0xFFD9) while parsing scan data\");\n        }\n        throw new JpegError(`unexpected marker ${(bitsData << 8 | nextByte).toString(16)}`);\n      }\n    }\n    bitsCount = 7;\n    return bitsData >>> 7;\n  }\n  function decodeHuffman(tree) {\n    let node = tree;\n    while (true) {\n      node = node[readBit()];\n      switch (typeof node) {\n        case \"number\":\n          return node;\n        case \"object\":\n          continue;\n      }\n      throw new JpegError(\"invalid huffman sequence\");\n    }\n  }\n  function receive(length) {\n    let n = 0;\n    while (length > 0) {\n      n = n << 1 | readBit();\n      length--;\n    }\n    return n;\n  }\n  function receiveAndExtend(length) {\n    if (length === 1) {\n      return readBit() === 1 ? 1 : -1;\n    }\n    const n = receive(length);\n    if (n >= 1 << length - 1) {\n      return n;\n    }\n    return n + (-1 << length) + 1;\n  }\n  function decodeBaseline(component, blockOffset) {\n    const t = decodeHuffman(component.huffmanTableDC);\n    const diff = t === 0 ? 0 : receiveAndExtend(t);\n    component.blockData[blockOffset] = component.pred += diff;\n    let k = 1;\n    while (k < 64) {\n      const rs = decodeHuffman(component.huffmanTableAC);\n      const s = rs & 15,\n        r = rs >> 4;\n      if (s === 0) {\n        if (r < 15) {\n          break;\n        }\n        k += 16;\n        continue;\n      }\n      k += r;\n      const z = dctZigZag[k];\n      component.blockData[blockOffset + z] = receiveAndExtend(s);\n      k++;\n    }\n  }\n  function decodeDCFirst(component, blockOffset) {\n    const t = decodeHuffman(component.huffmanTableDC);\n    const diff = t === 0 ? 0 : receiveAndExtend(t) << successive;\n    component.blockData[blockOffset] = component.pred += diff;\n  }\n  function decodeDCSuccessive(component, blockOffset) {\n    component.blockData[blockOffset] |= readBit() << successive;\n  }\n  let eobrun = 0;\n  function decodeACFirst(component, blockOffset) {\n    if (eobrun > 0) {\n      eobrun--;\n      return;\n    }\n    let k = spectralStart;\n    const e = spectralEnd;\n    while (k <= e) {\n      const rs = decodeHuffman(component.huffmanTableAC);\n      const s = rs & 15,\n        r = rs >> 4;\n      if (s === 0) {\n        if (r < 15) {\n          eobrun = receive(r) + (1 << r) - 1;\n          break;\n        }\n        k += 16;\n        continue;\n      }\n      k += r;\n      const z = dctZigZag[k];\n      component.blockData[blockOffset + z] = receiveAndExtend(s) * (1 << successive);\n      k++;\n    }\n  }\n  let successiveACState = 0,\n    successiveACNextValue;\n  function decodeACSuccessive(component, blockOffset) {\n    let k = spectralStart;\n    const e = spectralEnd;\n    let r = 0;\n    let s;\n    let rs;\n    while (k <= e) {\n      const offsetZ = blockOffset + dctZigZag[k];\n      const sign = component.blockData[offsetZ] < 0 ? -1 : 1;\n      switch (successiveACState) {\n        case 0:\n          rs = decodeHuffman(component.huffmanTableAC);\n          s = rs & 15;\n          r = rs >> 4;\n          if (s === 0) {\n            if (r < 15) {\n              eobrun = receive(r) + (1 << r);\n              successiveACState = 4;\n            } else {\n              r = 16;\n              successiveACState = 1;\n            }\n          } else {\n            if (s !== 1) {\n              throw new JpegError(\"invalid ACn encoding\");\n            }\n            successiveACNextValue = receiveAndExtend(s);\n            successiveACState = r ? 2 : 3;\n          }\n          continue;\n        case 1:\n        case 2:\n          if (component.blockData[offsetZ]) {\n            component.blockData[offsetZ] += sign * (readBit() << successive);\n          } else {\n            r--;\n            if (r === 0) {\n              successiveACState = successiveACState === 2 ? 3 : 0;\n            }\n          }\n          break;\n        case 3:\n          if (component.blockData[offsetZ]) {\n            component.blockData[offsetZ] += sign * (readBit() << successive);\n          } else {\n            component.blockData[offsetZ] = successiveACNextValue << successive;\n            successiveACState = 0;\n          }\n          break;\n        case 4:\n          if (component.blockData[offsetZ]) {\n            component.blockData[offsetZ] += sign * (readBit() << successive);\n          }\n          break;\n      }\n      k++;\n    }\n    if (successiveACState === 4) {\n      eobrun--;\n      if (eobrun === 0) {\n        successiveACState = 0;\n      }\n    }\n  }\n  let blockRow = 0;\n  function decodeMcu(component, decode, mcu, row, col) {\n    const mcuRow = mcu / mcusPerLine | 0;\n    const mcuCol = mcu % mcusPerLine;\n    blockRow = mcuRow * component.v + row;\n    const blockCol = mcuCol * component.h + col;\n    const blockOffset = getBlockBufferOffset(component, blockRow, blockCol);\n    decode(component, blockOffset);\n  }\n  function decodeBlock(component, decode, mcu) {\n    blockRow = mcu / component.blocksPerLine | 0;\n    const blockCol = mcu % component.blocksPerLine;\n    const blockOffset = getBlockBufferOffset(component, blockRow, blockCol);\n    decode(component, blockOffset);\n  }\n  const componentsLength = components.length;\n  let component, i, j, k, n;\n  let decodeFn;\n  if (progressive) {\n    if (spectralStart === 0) {\n      decodeFn = successivePrev === 0 ? decodeDCFirst : decodeDCSuccessive;\n    } else {\n      decodeFn = successivePrev === 0 ? decodeACFirst : decodeACSuccessive;\n    }\n  } else {\n    decodeFn = decodeBaseline;\n  }\n  let mcu = 0,\n    fileMarker;\n  const mcuExpected = componentsLength === 1 ? components[0].blocksPerLine * components[0].blocksPerColumn : mcusPerLine * frame.mcusPerColumn;\n  let h, v;\n  while (mcu <= mcuExpected) {\n    const mcuToRead = resetInterval ? Math.min(mcuExpected - mcu, resetInterval) : mcuExpected;\n    if (mcuToRead > 0) {\n      for (i = 0; i < componentsLength; i++) {\n        components[i].pred = 0;\n      }\n      eobrun = 0;\n      if (componentsLength === 1) {\n        component = components[0];\n        for (n = 0; n < mcuToRead; n++) {\n          decodeBlock(component, decodeFn, mcu);\n          mcu++;\n        }\n      } else {\n        for (n = 0; n < mcuToRead; n++) {\n          for (i = 0; i < componentsLength; i++) {\n            component = components[i];\n            h = component.h;\n            v = component.v;\n            for (j = 0; j < v; j++) {\n              for (k = 0; k < h; k++) {\n                decodeMcu(component, decodeFn, mcu, j, k);\n              }\n            }\n          }\n          mcu++;\n        }\n      }\n    }\n    bitsCount = 0;\n    fileMarker = findNextFileMarker(data, offset);\n    if (!fileMarker) {\n      break;\n    }\n    if (fileMarker.invalid) {\n      const partialMsg = mcuToRead > 0 ? \"unexpected\" : \"excessive\";\n      warn(`decodeScan - ${partialMsg} MCU data, current marker is: ${fileMarker.invalid}`);\n      offset = fileMarker.offset;\n    }\n    if (fileMarker.marker >= 0xffd0 && fileMarker.marker <= 0xffd7) {\n      offset += 2;\n    } else {\n      break;\n    }\n  }\n  return offset - startOffset;\n}\nfunction quantizeAndInverse(component, blockBufferOffset, p) {\n  const qt = component.quantizationTable,\n    blockData = component.blockData;\n  let v0, v1, v2, v3, v4, v5, v6, v7;\n  let p0, p1, p2, p3, p4, p5, p6, p7;\n  let t;\n  if (!qt) {\n    throw new JpegError(\"missing required Quantization Table.\");\n  }\n  for (let row = 0; row < 64; row += 8) {\n    p0 = blockData[blockBufferOffset + row];\n    p1 = blockData[blockBufferOffset + row + 1];\n    p2 = blockData[blockBufferOffset + row + 2];\n    p3 = blockData[blockBufferOffset + row + 3];\n    p4 = blockData[blockBufferOffset + row + 4];\n    p5 = blockData[blockBufferOffset + row + 5];\n    p6 = blockData[blockBufferOffset + row + 6];\n    p7 = blockData[blockBufferOffset + row + 7];\n    p0 *= qt[row];\n    if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) {\n      t = dctSqrt2 * p0 + 512 >> 10;\n      p[row] = t;\n      p[row + 1] = t;\n      p[row + 2] = t;\n      p[row + 3] = t;\n      p[row + 4] = t;\n      p[row + 5] = t;\n      p[row + 6] = t;\n      p[row + 7] = t;\n      continue;\n    }\n    p1 *= qt[row + 1];\n    p2 *= qt[row + 2];\n    p3 *= qt[row + 3];\n    p4 *= qt[row + 4];\n    p5 *= qt[row + 5];\n    p6 *= qt[row + 6];\n    p7 *= qt[row + 7];\n    v0 = dctSqrt2 * p0 + 128 >> 8;\n    v1 = dctSqrt2 * p4 + 128 >> 8;\n    v2 = p2;\n    v3 = p6;\n    v4 = dctSqrt1d2 * (p1 - p7) + 128 >> 8;\n    v7 = dctSqrt1d2 * (p1 + p7) + 128 >> 8;\n    v5 = p3 << 4;\n    v6 = p5 << 4;\n    v0 = v0 + v1 + 1 >> 1;\n    v1 = v0 - v1;\n    t = v2 * dctSin6 + v3 * dctCos6 + 128 >> 8;\n    v2 = v2 * dctCos6 - v3 * dctSin6 + 128 >> 8;\n    v3 = t;\n    v4 = v4 + v6 + 1 >> 1;\n    v6 = v4 - v6;\n    v7 = v7 + v5 + 1 >> 1;\n    v5 = v7 - v5;\n    v0 = v0 + v3 + 1 >> 1;\n    v3 = v0 - v3;\n    v1 = v1 + v2 + 1 >> 1;\n    v2 = v1 - v2;\n    t = v4 * dctSin3 + v7 * dctCos3 + 2048 >> 12;\n    v4 = v4 * dctCos3 - v7 * dctSin3 + 2048 >> 12;\n    v7 = t;\n    t = v5 * dctSin1 + v6 * dctCos1 + 2048 >> 12;\n    v5 = v5 * dctCos1 - v6 * dctSin1 + 2048 >> 12;\n    v6 = t;\n    p[row] = v0 + v7;\n    p[row + 7] = v0 - v7;\n    p[row + 1] = v1 + v6;\n    p[row + 6] = v1 - v6;\n    p[row + 2] = v2 + v5;\n    p[row + 5] = v2 - v5;\n    p[row + 3] = v3 + v4;\n    p[row + 4] = v3 - v4;\n  }\n  for (let col = 0; col < 8; ++col) {\n    p0 = p[col];\n    p1 = p[col + 8];\n    p2 = p[col + 16];\n    p3 = p[col + 24];\n    p4 = p[col + 32];\n    p5 = p[col + 40];\n    p6 = p[col + 48];\n    p7 = p[col + 56];\n    if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) {\n      t = dctSqrt2 * p0 + 8192 >> 14;\n      if (t < -2040) {\n        t = 0;\n      } else if (t >= 2024) {\n        t = 255;\n      } else {\n        t = t + 2056 >> 4;\n      }\n      blockData[blockBufferOffset + col] = t;\n      blockData[blockBufferOffset + col + 8] = t;\n      blockData[blockBufferOffset + col + 16] = t;\n      blockData[blockBufferOffset + col + 24] = t;\n      blockData[blockBufferOffset + col + 32] = t;\n      blockData[blockBufferOffset + col + 40] = t;\n      blockData[blockBufferOffset + col + 48] = t;\n      blockData[blockBufferOffset + col + 56] = t;\n      continue;\n    }\n    v0 = dctSqrt2 * p0 + 2048 >> 12;\n    v1 = dctSqrt2 * p4 + 2048 >> 12;\n    v2 = p2;\n    v3 = p6;\n    v4 = dctSqrt1d2 * (p1 - p7) + 2048 >> 12;\n    v7 = dctSqrt1d2 * (p1 + p7) + 2048 >> 12;\n    v5 = p3;\n    v6 = p5;\n    v0 = (v0 + v1 + 1 >> 1) + 4112;\n    v1 = v0 - v1;\n    t = v2 * dctSin6 + v3 * dctCos6 + 2048 >> 12;\n    v2 = v2 * dctCos6 - v3 * dctSin6 + 2048 >> 12;\n    v3 = t;\n    v4 = v4 + v6 + 1 >> 1;\n    v6 = v4 - v6;\n    v7 = v7 + v5 + 1 >> 1;\n    v5 = v7 - v5;\n    v0 = v0 + v3 + 1 >> 1;\n    v3 = v0 - v3;\n    v1 = v1 + v2 + 1 >> 1;\n    v2 = v1 - v2;\n    t = v4 * dctSin3 + v7 * dctCos3 + 2048 >> 12;\n    v4 = v4 * dctCos3 - v7 * dctSin3 + 2048 >> 12;\n    v7 = t;\n    t = v5 * dctSin1 + v6 * dctCos1 + 2048 >> 12;\n    v5 = v5 * dctCos1 - v6 * dctSin1 + 2048 >> 12;\n    v6 = t;\n    p0 = v0 + v7;\n    p7 = v0 - v7;\n    p1 = v1 + v6;\n    p6 = v1 - v6;\n    p2 = v2 + v5;\n    p5 = v2 - v5;\n    p3 = v3 + v4;\n    p4 = v3 - v4;\n    if (p0 < 16) {\n      p0 = 0;\n    } else if (p0 >= 4080) {\n      p0 = 255;\n    } else {\n      p0 >>= 4;\n    }\n    if (p1 < 16) {\n      p1 = 0;\n    } else if (p1 >= 4080) {\n      p1 = 255;\n    } else {\n      p1 >>= 4;\n    }\n    if (p2 < 16) {\n      p2 = 0;\n    } else if (p2 >= 4080) {\n      p2 = 255;\n    } else {\n      p2 >>= 4;\n    }\n    if (p3 < 16) {\n      p3 = 0;\n    } else if (p3 >= 4080) {\n      p3 = 255;\n    } else {\n      p3 >>= 4;\n    }\n    if (p4 < 16) {\n      p4 = 0;\n    } else if (p4 >= 4080) {\n      p4 = 255;\n    } else {\n      p4 >>= 4;\n    }\n    if (p5 < 16) {\n      p5 = 0;\n    } else if (p5 >= 4080) {\n      p5 = 255;\n    } else {\n      p5 >>= 4;\n    }\n    if (p6 < 16) {\n      p6 = 0;\n    } else if (p6 >= 4080) {\n      p6 = 255;\n    } else {\n      p6 >>= 4;\n    }\n    if (p7 < 16) {\n      p7 = 0;\n    } else if (p7 >= 4080) {\n      p7 = 255;\n    } else {\n      p7 >>= 4;\n    }\n    blockData[blockBufferOffset + col] = p0;\n    blockData[blockBufferOffset + col + 8] = p1;\n    blockData[blockBufferOffset + col + 16] = p2;\n    blockData[blockBufferOffset + col + 24] = p3;\n    blockData[blockBufferOffset + col + 32] = p4;\n    blockData[blockBufferOffset + col + 40] = p5;\n    blockData[blockBufferOffset + col + 48] = p6;\n    blockData[blockBufferOffset + col + 56] = p7;\n  }\n}\nfunction buildComponentData(frame, component) {\n  const blocksPerLine = component.blocksPerLine;\n  const blocksPerColumn = component.blocksPerColumn;\n  const computationBuffer = new Int16Array(64);\n  for (let blockRow = 0; blockRow < blocksPerColumn; blockRow++) {\n    for (let blockCol = 0; blockCol < blocksPerLine; blockCol++) {\n      const offset = getBlockBufferOffset(component, blockRow, blockCol);\n      quantizeAndInverse(component, offset, computationBuffer);\n    }\n  }\n  return component.blockData;\n}\nfunction findNextFileMarker(data, currentPos, startPos = currentPos) {\n  const maxPos = data.length - 1;\n  let newPos = startPos < currentPos ? startPos : currentPos;\n  if (currentPos >= maxPos) {\n    return null;\n  }\n  const currentMarker = readUint16(data, currentPos);\n  if (currentMarker >= 0xffc0 && currentMarker <= 0xfffe) {\n    return {\n      invalid: null,\n      marker: currentMarker,\n      offset: currentPos\n    };\n  }\n  let newMarker = readUint16(data, newPos);\n  while (!(newMarker >= 0xffc0 && newMarker <= 0xfffe)) {\n    if (++newPos >= maxPos) {\n      return null;\n    }\n    newMarker = readUint16(data, newPos);\n  }\n  return {\n    invalid: currentMarker.toString(16),\n    marker: newMarker,\n    offset: newPos\n  };\n}\nclass JpegImage {\n  constructor({\n    decodeTransform = null,\n    colorTransform = -1\n  } = {}) {\n    this._decodeTransform = decodeTransform;\n    this._colorTransform = colorTransform;\n  }\n  parse(data, {\n    dnlScanLines = null\n  } = {}) {\n    function readDataBlock() {\n      const length = readUint16(data, offset);\n      offset += 2;\n      let endOffset = offset + length - 2;\n      const fileMarker = findNextFileMarker(data, endOffset, offset);\n      if (fileMarker?.invalid) {\n        warn(\"readDataBlock - incorrect length, current marker is: \" + fileMarker.invalid);\n        endOffset = fileMarker.offset;\n      }\n      const array = data.subarray(offset, endOffset);\n      offset += array.length;\n      return array;\n    }\n    function prepareComponents(frame) {\n      const mcusPerLine = Math.ceil(frame.samplesPerLine / 8 / frame.maxH);\n      const mcusPerColumn = Math.ceil(frame.scanLines / 8 / frame.maxV);\n      for (const component of frame.components) {\n        const blocksPerLine = Math.ceil(Math.ceil(frame.samplesPerLine / 8) * component.h / frame.maxH);\n        const blocksPerColumn = Math.ceil(Math.ceil(frame.scanLines / 8) * component.v / frame.maxV);\n        const blocksPerLineForMcu = mcusPerLine * component.h;\n        const blocksPerColumnForMcu = mcusPerColumn * component.v;\n        const blocksBufferSize = 64 * blocksPerColumnForMcu * (blocksPerLineForMcu + 1);\n        component.blockData = new Int16Array(blocksBufferSize);\n        component.blocksPerLine = blocksPerLine;\n        component.blocksPerColumn = blocksPerColumn;\n      }\n      frame.mcusPerLine = mcusPerLine;\n      frame.mcusPerColumn = mcusPerColumn;\n    }\n    let offset = 0;\n    let jfif = null;\n    let adobe = null;\n    let frame, resetInterval;\n    let numSOSMarkers = 0;\n    const quantizationTables = [];\n    const huffmanTablesAC = [],\n      huffmanTablesDC = [];\n    let fileMarker = readUint16(data, offset);\n    offset += 2;\n    if (fileMarker !== 0xffd8) {\n      throw new JpegError(\"SOI not found\");\n    }\n    fileMarker = readUint16(data, offset);\n    offset += 2;\n    markerLoop: while (fileMarker !== 0xffd9) {\n      let i, j, l;\n      switch (fileMarker) {\n        case 0xffe0:\n        case 0xffe1:\n        case 0xffe2:\n        case 0xffe3:\n        case 0xffe4:\n        case 0xffe5:\n        case 0xffe6:\n        case 0xffe7:\n        case 0xffe8:\n        case 0xffe9:\n        case 0xffea:\n        case 0xffeb:\n        case 0xffec:\n        case 0xffed:\n        case 0xffee:\n        case 0xffef:\n        case 0xfffe:\n          const appData = readDataBlock();\n          if (fileMarker === 0xffe0) {\n            if (appData[0] === 0x4a && appData[1] === 0x46 && appData[2] === 0x49 && appData[3] === 0x46 && appData[4] === 0) {\n              jfif = {\n                version: {\n                  major: appData[5],\n                  minor: appData[6]\n                },\n                densityUnits: appData[7],\n                xDensity: appData[8] << 8 | appData[9],\n                yDensity: appData[10] << 8 | appData[11],\n                thumbWidth: appData[12],\n                thumbHeight: appData[13],\n                thumbData: appData.subarray(14, 14 + 3 * appData[12] * appData[13])\n              };\n            }\n          }\n          if (fileMarker === 0xffee) {\n            if (appData[0] === 0x41 && appData[1] === 0x64 && appData[2] === 0x6f && appData[3] === 0x62 && appData[4] === 0x65) {\n              adobe = {\n                version: appData[5] << 8 | appData[6],\n                flags0: appData[7] << 8 | appData[8],\n                flags1: appData[9] << 8 | appData[10],\n                transformCode: appData[11]\n              };\n            }\n          }\n          break;\n        case 0xffdb:\n          const quantizationTablesLength = readUint16(data, offset);\n          offset += 2;\n          const quantizationTablesEnd = quantizationTablesLength + offset - 2;\n          let z;\n          while (offset < quantizationTablesEnd) {\n            const quantizationTableSpec = data[offset++];\n            const tableData = new Uint16Array(64);\n            if (quantizationTableSpec >> 4 === 0) {\n              for (j = 0; j < 64; j++) {\n                z = dctZigZag[j];\n                tableData[z] = data[offset++];\n              }\n            } else if (quantizationTableSpec >> 4 === 1) {\n              for (j = 0; j < 64; j++) {\n                z = dctZigZag[j];\n                tableData[z] = readUint16(data, offset);\n                offset += 2;\n              }\n            } else {\n              throw new JpegError(\"DQT - invalid table spec\");\n            }\n            quantizationTables[quantizationTableSpec & 15] = tableData;\n          }\n          break;\n        case 0xffc0:\n        case 0xffc1:\n        case 0xffc2:\n          if (frame) {\n            throw new JpegError(\"Only single frame JPEGs supported\");\n          }\n          offset += 2;\n          frame = {};\n          frame.extended = fileMarker === 0xffc1;\n          frame.progressive = fileMarker === 0xffc2;\n          frame.precision = data[offset++];\n          const sofScanLines = readUint16(data, offset);\n          offset += 2;\n          frame.scanLines = dnlScanLines || sofScanLines;\n          frame.samplesPerLine = readUint16(data, offset);\n          offset += 2;\n          frame.components = [];\n          frame.componentIds = {};\n          const componentsCount = data[offset++];\n          let maxH = 0,\n            maxV = 0;\n          for (i = 0; i < componentsCount; i++) {\n            const componentId = data[offset];\n            const h = data[offset + 1] >> 4;\n            const v = data[offset + 1] & 15;\n            if (maxH < h) {\n              maxH = h;\n            }\n            if (maxV < v) {\n              maxV = v;\n            }\n            const qId = data[offset + 2];\n            l = frame.components.push({\n              h,\n              v,\n              quantizationId: qId,\n              quantizationTable: null\n            });\n            frame.componentIds[componentId] = l - 1;\n            offset += 3;\n          }\n          frame.maxH = maxH;\n          frame.maxV = maxV;\n          prepareComponents(frame);\n          break;\n        case 0xffc4:\n          const huffmanLength = readUint16(data, offset);\n          offset += 2;\n          for (i = 2; i < huffmanLength;) {\n            const huffmanTableSpec = data[offset++];\n            const codeLengths = new Uint8Array(16);\n            let codeLengthSum = 0;\n            for (j = 0; j < 16; j++, offset++) {\n              codeLengthSum += codeLengths[j] = data[offset];\n            }\n            const huffmanValues = new Uint8Array(codeLengthSum);\n            for (j = 0; j < codeLengthSum; j++, offset++) {\n              huffmanValues[j] = data[offset];\n            }\n            i += 17 + codeLengthSum;\n            (huffmanTableSpec >> 4 === 0 ? huffmanTablesDC : huffmanTablesAC)[huffmanTableSpec & 15] = buildHuffmanTable(codeLengths, huffmanValues);\n          }\n          break;\n        case 0xffdd:\n          offset += 2;\n          resetInterval = readUint16(data, offset);\n          offset += 2;\n          break;\n        case 0xffda:\n          const parseDNLMarker = ++numSOSMarkers === 1 && !dnlScanLines;\n          offset += 2;\n          const selectorsCount = data[offset++],\n            components = [];\n          for (i = 0; i < selectorsCount; i++) {\n            const index = data[offset++];\n            const componentIndex = frame.componentIds[index];\n            const component = frame.components[componentIndex];\n            component.index = index;\n            const tableSpec = data[offset++];\n            component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4];\n            component.huffmanTableAC = huffmanTablesAC[tableSpec & 15];\n            components.push(component);\n          }\n          const spectralStart = data[offset++],\n            spectralEnd = data[offset++],\n            successiveApproximation = data[offset++];\n          try {\n            const processed = decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successiveApproximation >> 4, successiveApproximation & 15, parseDNLMarker);\n            offset += processed;\n          } catch (ex) {\n            if (ex instanceof DNLMarkerError) {\n              warn(`${ex.message} -- attempting to re-parse the JPEG image.`);\n              return this.parse(data, {\n                dnlScanLines: ex.scanLines\n              });\n            } else if (ex instanceof EOIMarkerError) {\n              warn(`${ex.message} -- ignoring the rest of the image data.`);\n              break markerLoop;\n            }\n            throw ex;\n          }\n          break;\n        case 0xffdc:\n          offset += 4;\n          break;\n        case 0xffff:\n          if (data[offset] !== 0xff) {\n            offset--;\n          }\n          break;\n        default:\n          const nextFileMarker = findNextFileMarker(data, offset - 2, offset - 3);\n          if (nextFileMarker?.invalid) {\n            warn(\"JpegImage.parse - unexpected data, current marker is: \" + nextFileMarker.invalid);\n            offset = nextFileMarker.offset;\n            break;\n          }\n          if (!nextFileMarker || offset >= data.length - 1) {\n            warn(\"JpegImage.parse - reached the end of the image data \" + \"without finding an EOI marker (0xFFD9).\");\n            break markerLoop;\n          }\n          throw new JpegError(\"JpegImage.parse - unknown marker: \" + fileMarker.toString(16));\n      }\n      fileMarker = readUint16(data, offset);\n      offset += 2;\n    }\n    if (!frame) {\n      throw new JpegError(\"JpegImage.parse - no frame data found.\");\n    }\n    this.width = frame.samplesPerLine;\n    this.height = frame.scanLines;\n    this.jfif = jfif;\n    this.adobe = adobe;\n    this.components = [];\n    for (const component of frame.components) {\n      const quantizationTable = quantizationTables[component.quantizationId];\n      if (quantizationTable) {\n        component.quantizationTable = quantizationTable;\n      }\n      this.components.push({\n        index: component.index,\n        output: buildComponentData(frame, component),\n        scaleX: component.h / frame.maxH,\n        scaleY: component.v / frame.maxV,\n        blocksPerLine: component.blocksPerLine,\n        blocksPerColumn: component.blocksPerColumn\n      });\n    }\n    this.numComponents = this.components.length;\n    return undefined;\n  }\n  _getLinearizedBlockData(width, height, isSourcePDF = false) {\n    const scaleX = this.width / width,\n      scaleY = this.height / height;\n    let component, componentScaleX, componentScaleY, blocksPerScanline;\n    let x, y, i, j, k;\n    let index;\n    let offset = 0;\n    let output;\n    const numComponents = this.components.length;\n    const dataLength = width * height * numComponents;\n    const data = new Uint8ClampedArray(dataLength);\n    const xScaleBlockOffset = new Uint32Array(width);\n    const mask3LSB = 0xfffffff8;\n    let lastComponentScaleX;\n    for (i = 0; i < numComponents; i++) {\n      component = this.components[i];\n      componentScaleX = component.scaleX * scaleX;\n      componentScaleY = component.scaleY * scaleY;\n      offset = i;\n      output = component.output;\n      blocksPerScanline = component.blocksPerLine + 1 << 3;\n      if (componentScaleX !== lastComponentScaleX) {\n        for (x = 0; x < width; x++) {\n          j = 0 | x * componentScaleX;\n          xScaleBlockOffset[x] = (j & mask3LSB) << 3 | j & 7;\n        }\n        lastComponentScaleX = componentScaleX;\n      }\n      for (y = 0; y < height; y++) {\n        j = 0 | y * componentScaleY;\n        index = blocksPerScanline * (j & mask3LSB) | (j & 7) << 3;\n        for (x = 0; x < width; x++) {\n          data[offset] = output[index + xScaleBlockOffset[x]];\n          offset += numComponents;\n        }\n      }\n    }\n    let transform = this._decodeTransform;\n    if (!isSourcePDF && numComponents === 4 && !transform) {\n      transform = new Int32Array([-256, 255, -256, 255, -256, 255, -256, 255]);\n    }\n    if (transform) {\n      for (i = 0; i < dataLength;) {\n        for (j = 0, k = 0; j < numComponents; j++, i++, k += 2) {\n          data[i] = (data[i] * transform[k] >> 8) + transform[k + 1];\n        }\n      }\n    }\n    return data;\n  }\n  get _isColorConversionNeeded() {\n    if (this.adobe) {\n      return !!this.adobe.transformCode;\n    }\n    if (this.numComponents === 3) {\n      if (this._colorTransform === 0) {\n        return false;\n      } else if (this.components[0].index === 0x52 && this.components[1].index === 0x47 && this.components[2].index === 0x42) {\n        return false;\n      }\n      return true;\n    }\n    if (this._colorTransform === 1) {\n      return true;\n    }\n    return false;\n  }\n  _convertYccToRgb(data) {\n    let Y, Cb, Cr;\n    for (let i = 0, length = data.length; i < length; i += 3) {\n      Y = data[i];\n      Cb = data[i + 1];\n      Cr = data[i + 2];\n      data[i] = Y - 179.456 + 1.402 * Cr;\n      data[i + 1] = Y + 135.459 - 0.344 * Cb - 0.714 * Cr;\n      data[i + 2] = Y - 226.816 + 1.772 * Cb;\n    }\n    return data;\n  }\n  _convertYccToRgba(data, out) {\n    for (let i = 0, j = 0, length = data.length; i < length; i += 3, j += 4) {\n      const Y = data[i];\n      const Cb = data[i + 1];\n      const Cr = data[i + 2];\n      out[j] = Y - 179.456 + 1.402 * Cr;\n      out[j + 1] = Y + 135.459 - 0.344 * Cb - 0.714 * Cr;\n      out[j + 2] = Y - 226.816 + 1.772 * Cb;\n      out[j + 3] = 255;\n    }\n    return out;\n  }\n  _convertYcckToRgb(data) {\n    let Y, Cb, Cr, k;\n    let offset = 0;\n    for (let i = 0, length = data.length; i < length; i += 4) {\n      Y = data[i];\n      Cb = data[i + 1];\n      Cr = data[i + 2];\n      k = data[i + 3];\n      data[offset++] = -122.67195406894 + Cb * (-6.60635669420364e-5 * Cb + 0.000437130475926232 * Cr - 5.4080610064599e-5 * Y + 0.00048449797120281 * k - 0.154362151871126) + Cr * (-0.000957964378445773 * Cr + 0.000817076911346625 * Y - 0.00477271405408747 * k + 1.53380253221734) + Y * (0.000961250184130688 * Y - 0.00266257332283933 * k + 0.48357088451265) + k * (-0.000336197177618394 * k + 0.484791561490776);\n      data[offset++] = 107.268039397724 + Cb * (2.19927104525741e-5 * Cb - 0.000640992018297945 * Cr + 0.000659397001245577 * Y + 0.000426105652938837 * k - 0.176491792462875) + Cr * (-0.000778269941513683 * Cr + 0.00130872261408275 * Y + 0.000770482631801132 * k - 0.151051492775562) + Y * (0.00126935368114843 * Y - 0.00265090189010898 * k + 0.25802910206845) + k * (-0.000318913117588328 * k - 0.213742400323665);\n      data[offset++] = -20.810012546947 + Cb * (-0.000570115196973677 * Cb - 2.63409051004589e-5 * Cr + 0.0020741088115012 * Y - 0.00288260236853442 * k + 0.814272968359295) + Cr * (-1.53496057440975e-5 * Cr - 0.000132689043961446 * Y + 0.000560833691242812 * k - 0.195152027534049) + Y * (0.00174418132927582 * Y - 0.00255243321439347 * k + 0.116935020465145) + k * (-0.000343531996510555 * k + 0.24165260232407);\n    }\n    return data.subarray(0, offset);\n  }\n  _convertYcckToRgba(data) {\n    for (let i = 0, length = data.length; i < length; i += 4) {\n      const Y = data[i];\n      const Cb = data[i + 1];\n      const Cr = data[i + 2];\n      const k = data[i + 3];\n      data[i] = -122.67195406894 + Cb * (-6.60635669420364e-5 * Cb + 0.000437130475926232 * Cr - 5.4080610064599e-5 * Y + 0.00048449797120281 * k - 0.154362151871126) + Cr * (-0.000957964378445773 * Cr + 0.000817076911346625 * Y - 0.00477271405408747 * k + 1.53380253221734) + Y * (0.000961250184130688 * Y - 0.00266257332283933 * k + 0.48357088451265) + k * (-0.000336197177618394 * k + 0.484791561490776);\n      data[i + 1] = 107.268039397724 + Cb * (2.19927104525741e-5 * Cb - 0.000640992018297945 * Cr + 0.000659397001245577 * Y + 0.000426105652938837 * k - 0.176491792462875) + Cr * (-0.000778269941513683 * Cr + 0.00130872261408275 * Y + 0.000770482631801132 * k - 0.151051492775562) + Y * (0.00126935368114843 * Y - 0.00265090189010898 * k + 0.25802910206845) + k * (-0.000318913117588328 * k - 0.213742400323665);\n      data[i + 2] = -20.810012546947 + Cb * (-0.000570115196973677 * Cb - 2.63409051004589e-5 * Cr + 0.0020741088115012 * Y - 0.00288260236853442 * k + 0.814272968359295) + Cr * (-1.53496057440975e-5 * Cr - 0.000132689043961446 * Y + 0.000560833691242812 * k - 0.195152027534049) + Y * (0.00174418132927582 * Y - 0.00255243321439347 * k + 0.116935020465145) + k * (-0.000343531996510555 * k + 0.24165260232407);\n      data[i + 3] = 255;\n    }\n    return data;\n  }\n  _convertYcckToCmyk(data) {\n    let Y, Cb, Cr;\n    for (let i = 0, length = data.length; i < length; i += 4) {\n      Y = data[i];\n      Cb = data[i + 1];\n      Cr = data[i + 2];\n      data[i] = 434.456 - Y - 1.402 * Cr;\n      data[i + 1] = 119.541 - Y + 0.344 * Cb + 0.714 * Cr;\n      data[i + 2] = 481.816 - Y - 1.772 * Cb;\n    }\n    return data;\n  }\n  _convertCmykToRgb(data) {\n    let c, m, y, k;\n    let offset = 0;\n    for (let i = 0, length = data.length; i < length; i += 4) {\n      c = data[i];\n      m = data[i + 1];\n      y = data[i + 2];\n      k = data[i + 3];\n      data[offset++] = 255 + c * (-0.00006747147073602441 * c + 0.0008379262121013727 * m + 0.0002894718188643294 * y + 0.003264231057537806 * k - 1.1185611867203937) + m * (0.000026374107616089405 * m - 0.00008626949158638572 * y - 0.0002748769067499491 * k - 0.02155688794978967) + y * (-0.00003878099212869363 * y - 0.0003267808279485286 * k + 0.0686742238595345) - k * (0.0003361971776183937 * k + 0.7430659151342254);\n      data[offset++] = 255 + c * (0.00013596372813588848 * c + 0.000924537132573585 * m + 0.00010567359618683593 * y + 0.0004791864687436512 * k - 0.3109689587515875) + m * (-0.00023545346108370344 * m + 0.0002702845253534714 * y + 0.0020200308977307156 * k - 0.7488052167015494) + y * (0.00006834815998235662 * y + 0.00015168452363460973 * k - 0.09751927774728933) - k * (0.0003189131175883281 * k + 0.7364883807733168);\n      data[offset++] = 255 + c * (0.000013598650411385307 * c + 0.00012423956175490851 * m + 0.0004751985097583589 * y - 0.0000036729317476630422 * k - 0.05562186980264034) + m * (0.00016141380598724676 * m + 0.0009692239130725186 * y + 0.0007782692450036253 * k - 0.44015232367526463) + y * (5.068882914068769e-7 * y + 0.0017778369011375071 * k - 0.7591454649749609) - k * (0.0003435319965105553 * k + 0.7063770186160144);\n    }\n    return data.subarray(0, offset);\n  }\n  _convertCmykToRgba(data) {\n    for (let i = 0, length = data.length; i < length; i += 4) {\n      const c = data[i];\n      const m = data[i + 1];\n      const y = data[i + 2];\n      const k = data[i + 3];\n      data[i] = 255 + c * (-0.00006747147073602441 * c + 0.0008379262121013727 * m + 0.0002894718188643294 * y + 0.003264231057537806 * k - 1.1185611867203937) + m * (0.000026374107616089405 * m - 0.00008626949158638572 * y - 0.0002748769067499491 * k - 0.02155688794978967) + y * (-0.00003878099212869363 * y - 0.0003267808279485286 * k + 0.0686742238595345) - k * (0.0003361971776183937 * k + 0.7430659151342254);\n      data[i + 1] = 255 + c * (0.00013596372813588848 * c + 0.000924537132573585 * m + 0.00010567359618683593 * y + 0.0004791864687436512 * k - 0.3109689587515875) + m * (-0.00023545346108370344 * m + 0.0002702845253534714 * y + 0.0020200308977307156 * k - 0.7488052167015494) + y * (0.00006834815998235662 * y + 0.00015168452363460973 * k - 0.09751927774728933) - k * (0.0003189131175883281 * k + 0.7364883807733168);\n      data[i + 2] = 255 + c * (0.000013598650411385307 * c + 0.00012423956175490851 * m + 0.0004751985097583589 * y - 0.0000036729317476630422 * k - 0.05562186980264034) + m * (0.00016141380598724676 * m + 0.0009692239130725186 * y + 0.0007782692450036253 * k - 0.44015232367526463) + y * (5.068882914068769e-7 * y + 0.0017778369011375071 * k - 0.7591454649749609) - k * (0.0003435319965105553 * k + 0.7063770186160144);\n      data[i + 3] = 255;\n    }\n    return data;\n  }\n  getData({\n    width,\n    height,\n    forceRGBA = false,\n    forceRGB = false,\n    isSourcePDF = false\n  }) {\n    if (this.numComponents > 4) {\n      throw new JpegError(\"Unsupported color mode\");\n    }\n    const data = this._getLinearizedBlockData(width, height, isSourcePDF);\n    if (this.numComponents === 1 && (forceRGBA || forceRGB)) {\n      const len = data.length * (forceRGBA ? 4 : 3);\n      const rgbaData = new Uint8ClampedArray(len);\n      let offset = 0;\n      if (forceRGBA) {\n        grayToRGBA(data, new Uint32Array(rgbaData.buffer));\n      } else {\n        for (const grayColor of data) {\n          rgbaData[offset++] = grayColor;\n          rgbaData[offset++] = grayColor;\n          rgbaData[offset++] = grayColor;\n        }\n      }\n      return rgbaData;\n    } else if (this.numComponents === 3 && this._isColorConversionNeeded) {\n      if (forceRGBA) {\n        const rgbaData = new Uint8ClampedArray(data.length / 3 * 4);\n        return this._convertYccToRgba(data, rgbaData);\n      }\n      return this._convertYccToRgb(data);\n    } else if (this.numComponents === 4) {\n      if (this._isColorConversionNeeded) {\n        if (forceRGBA) {\n          return this._convertYcckToRgba(data);\n        }\n        if (forceRGB) {\n          return this._convertYcckToRgb(data);\n        }\n        return this._convertYcckToCmyk(data);\n      } else if (forceRGBA) {\n        return this._convertCmykToRgba(data);\n      } else if (forceRGB) {\n        return this._convertCmykToRgb(data);\n      }\n    }\n    return data;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/jpeg_stream.js\n\n\n\n\nclass JpegStream extends DecodeStream {\n  constructor(stream, maybeLength, params) {\n    let ch;\n    while ((ch = stream.getByte()) !== -1) {\n      if (ch === 0xff) {\n        stream.skip(-1);\n        break;\n      }\n    }\n    super(maybeLength);\n    this.stream = stream;\n    this.dict = stream.dict;\n    this.maybeLength = maybeLength;\n    this.params = params;\n  }\n  get bytes() {\n    return shadow(this, \"bytes\", this.stream.getBytes(this.maybeLength));\n  }\n  ensureBuffer(requested) {}\n  readBlock() {\n    if (this.eof) {\n      return;\n    }\n    const jpegOptions = {\n      decodeTransform: undefined,\n      colorTransform: undefined\n    };\n    const decodeArr = this.dict.getArray(\"D\", \"Decode\");\n    if ((this.forceRGBA || this.forceRGB) && Array.isArray(decodeArr)) {\n      const bitsPerComponent = this.dict.get(\"BPC\", \"BitsPerComponent\") || 8;\n      const decodeArrLength = decodeArr.length;\n      const transform = new Int32Array(decodeArrLength);\n      let transformNeeded = false;\n      const maxValue = (1 << bitsPerComponent) - 1;\n      for (let i = 0; i < decodeArrLength; i += 2) {\n        transform[i] = (decodeArr[i + 1] - decodeArr[i]) * 256 | 0;\n        transform[i + 1] = decodeArr[i] * maxValue | 0;\n        if (transform[i] !== 256 || transform[i + 1] !== 0) {\n          transformNeeded = true;\n        }\n      }\n      if (transformNeeded) {\n        jpegOptions.decodeTransform = transform;\n      }\n    }\n    if (this.params instanceof Dict) {\n      const colorTransform = this.params.get(\"ColorTransform\");\n      if (Number.isInteger(colorTransform)) {\n        jpegOptions.colorTransform = colorTransform;\n      }\n    }\n    const jpegImage = new JpegImage(jpegOptions);\n    jpegImage.parse(this.bytes);\n    const data = jpegImage.getData({\n      width: this.drawWidth,\n      height: this.drawHeight,\n      forceRGBA: this.forceRGBA,\n      forceRGB: this.forceRGB,\n      isSourcePDF: true\n    });\n    this.buffer = data;\n    this.bufferLength = data.length;\n    this.eof = true;\n  }\n}\n\n;// CONCATENATED MODULE: ./external/openjpeg/openjpeg.js\nvar OpenJPEG = (() => {\n  var _scriptDir = \"file:///home/timvandermeij/Documenten/Ontwikkeling/pdf.js/Code/external/openjpeg/openjpeg.js\";\n  return function (moduleArg = {}) {\n    var Module = moduleArg;\n    var readyPromiseResolve, readyPromiseReject;\n    var readyPromise = new Promise((resolve, reject) => {\n      readyPromiseResolve = resolve;\n      readyPromiseReject = reject;\n    });\n    \"use strict\";\n    Module.decode = function (bytes, ignoreColorSpace) {\n      const size = bytes.length;\n      const ptr = Module._malloc(size);\n      Module.HEAPU8.set(bytes, ptr);\n      const ret = Module._jp2_decode(ptr, size, ignoreColorSpace ? 1 : 0);\n      Module._free(ptr);\n      if (ret) {\n        const {\n          errorMessages: errorMessages\n        } = Module;\n        if (errorMessages) {\n          delete Module.errorMessages;\n          return errorMessages;\n        }\n        return \"Unknown error\";\n      }\n      const {\n        imageData: imageData\n      } = Module;\n      Module.imageData = null;\n      return imageData;\n    };\n    var moduleOverrides = Object.assign({}, Module);\n    var arguments_ = [];\n    var thisProgram = \"./this.program\";\n    var quit_ = (status, toThrow) => {\n      throw toThrow;\n    };\n    var ENVIRONMENT_IS_WEB = true;\n    var ENVIRONMENT_IS_WORKER = false;\n    var scriptDirectory = \"\";\n    var read_, readAsync, readBinary;\n    if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {\n      if (ENVIRONMENT_IS_WORKER) {\n        scriptDirectory = self.location.href;\n      } else if (typeof document != \"undefined\" && document.currentScript) {\n        scriptDirectory = document.currentScript.src;\n      }\n      if (_scriptDir) {\n        scriptDirectory = _scriptDir;\n      }\n      if (scriptDirectory.startsWith(\"blob:\")) {\n        scriptDirectory = \"\";\n      } else {\n        scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, \"\").lastIndexOf(\"/\") + 1);\n      }\n      read_ = url => {\n        var xhr = new XMLHttpRequest();\n        xhr.open(\"GET\", url, false);\n        xhr.send(null);\n        return xhr.responseText;\n      };\n      if (ENVIRONMENT_IS_WORKER) {\n        readBinary = url => {\n          var xhr = new XMLHttpRequest();\n          xhr.open(\"GET\", url, false);\n          xhr.responseType = \"arraybuffer\";\n          xhr.send(null);\n          return new Uint8Array(xhr.response);\n        };\n      }\n      readAsync = (url, onload, onerror) => {\n        var xhr = new XMLHttpRequest();\n        xhr.open(\"GET\", url, true);\n        xhr.responseType = \"arraybuffer\";\n        xhr.onload = () => {\n          if (xhr.status == 200 || xhr.status == 0 && xhr.response) {\n            onload(xhr.response);\n            return;\n          }\n          onerror();\n        };\n        xhr.onerror = onerror;\n        xhr.send(null);\n      };\n    } else {}\n    var out = Module[\"print\"] || console.log.bind(console);\n    var err = Module[\"printErr\"] || console.error.bind(console);\n    Object.assign(Module, moduleOverrides);\n    moduleOverrides = null;\n    if (Module[\"arguments\"]) arguments_ = Module[\"arguments\"];\n    if (Module[\"thisProgram\"]) thisProgram = Module[\"thisProgram\"];\n    if (Module[\"quit\"]) quit_ = Module[\"quit\"];\n    var wasmBinary;\n    if (Module[\"wasmBinary\"]) wasmBinary = Module[\"wasmBinary\"];\n    function intArrayFromBase64(s) {\n      var decoded = atob(s);\n      var bytes = new Uint8Array(decoded.length);\n      for (var i = 0; i < decoded.length; ++i) {\n        bytes[i] = decoded.charCodeAt(i);\n      }\n      return bytes;\n    }\n    function tryParseAsDataURI(filename) {\n      if (!isDataURI(filename)) {\n        return;\n      }\n      return intArrayFromBase64(filename.slice(dataURIPrefix.length));\n    }\n    var wasmMemory;\n    var ABORT = false;\n    var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64;\n    function updateMemoryViews() {\n      var b = wasmMemory.buffer;\n      Module[\"HEAP8\"] = HEAP8 = new Int8Array(b);\n      Module[\"HEAP16\"] = HEAP16 = new Int16Array(b);\n      Module[\"HEAPU8\"] = HEAPU8 = new Uint8Array(b);\n      Module[\"HEAPU16\"] = HEAPU16 = new Uint16Array(b);\n      Module[\"HEAP32\"] = HEAP32 = new Int32Array(b);\n      Module[\"HEAPU32\"] = HEAPU32 = new Uint32Array(b);\n      Module[\"HEAPF32\"] = HEAPF32 = new Float32Array(b);\n      Module[\"HEAPF64\"] = HEAPF64 = new Float64Array(b);\n    }\n    var __ATPRERUN__ = [];\n    var __ATINIT__ = [];\n    var __ATPOSTRUN__ = [];\n    var runtimeInitialized = false;\n    function preRun() {\n      if (Module[\"preRun\"]) {\n        if (typeof Module[\"preRun\"] == \"function\") Module[\"preRun\"] = [Module[\"preRun\"]];\n        while (Module[\"preRun\"].length) {\n          addOnPreRun(Module[\"preRun\"].shift());\n        }\n      }\n      callRuntimeCallbacks(__ATPRERUN__);\n    }\n    function initRuntime() {\n      runtimeInitialized = true;\n      callRuntimeCallbacks(__ATINIT__);\n    }\n    function postRun() {\n      if (Module[\"postRun\"]) {\n        if (typeof Module[\"postRun\"] == \"function\") Module[\"postRun\"] = [Module[\"postRun\"]];\n        while (Module[\"postRun\"].length) {\n          addOnPostRun(Module[\"postRun\"].shift());\n        }\n      }\n      callRuntimeCallbacks(__ATPOSTRUN__);\n    }\n    function addOnPreRun(cb) {\n      __ATPRERUN__.unshift(cb);\n    }\n    function addOnInit(cb) {\n      __ATINIT__.unshift(cb);\n    }\n    function addOnPostRun(cb) {\n      __ATPOSTRUN__.unshift(cb);\n    }\n    var runDependencies = 0;\n    var runDependencyWatcher = null;\n    var dependenciesFulfilled = null;\n    function addRunDependency(id) {\n      runDependencies++;\n      Module[\"monitorRunDependencies\"]?.(runDependencies);\n    }\n    function removeRunDependency(id) {\n      runDependencies--;\n      Module[\"monitorRunDependencies\"]?.(runDependencies);\n      if (runDependencies == 0) {\n        if (runDependencyWatcher !== null) {\n          clearInterval(runDependencyWatcher);\n          runDependencyWatcher = null;\n        }\n        if (dependenciesFulfilled) {\n          var callback = dependenciesFulfilled;\n          dependenciesFulfilled = null;\n          callback();\n        }\n      }\n    }\n    var dataURIPrefix = \"data:application/octet-stream;base64,\";\n    var isDataURI = filename => filename.startsWith(dataURIPrefix);\n    var wasmBinaryFile;\n    wasmBinaryFile = \"data:application/octet-stream;base64,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AkAgFSAYIA1BAnRqQRBJckUEQANAIAEgAEECdCIEaiAEIAVq/QACAP0LAgAgAEEEaiIAIBNHDQALIBMiBCAIRg0BCyAEIQAgEQRAA0AgASAAIAJsQQJ0aiAFIABBAnRqKAIANgIAIABBAWohACAGQQFqIgYgEUcNAAsLIAQgCGtBfEsNAANAIAEgACACbEECdGogBSAAQQJ0aigCADYCACABIABBAWoiBCACbEECdGogBSAEQQJ0aigCADYCACABIABBAmoiBCACbEECdGogBSAEQQJ0aigCADYCACABIABBA2oiBCACbEECdGogBSAEQQJ0aigCADYCACAAQQRqIgAgCEcNAAsLIAFBBGohASANQQFqIg0gA0cNAAsMAQsCQAJAAkAgCEEBaw4CAAECCyADQQBMDQJBACECAkAgA0EESQRAIAEhAAwBCyABIANB/P///wdxIgJBAnRqIQADQCABIAZBAnRqIgQgBP0AAgAiIf0bAEECbf0RICH9GwFBAm39HAEgIf0bAkECbf0cAiAh/RsDQQJt/RwD/QsCACAGQQRqIgYgAkcNAAsgAiADRg0DCwNAIAAgACgCAEECbTYCACAAQQRqIQAgAkEBaiICIANHDQALDAILIANBAEwNASAAKAIAIQkgAiAKbEECdCEHA0AgCSABKAIAIAEgB2oiBCgCAEEBakEBdWsiADYCBCAJIAAgBCgCAGoiADYCACABIAA2AgAgASACQQJ0aiAJKAIENgIAIAFBBGohASAGQQFqIgYgA0cNAAsMAQsgCEEDSA0AIANBAEwNACAAKAIAIgUgCCAIQQFxIhRFIgZrQQRrIglBAXYiC0ECdCIHIAEgA0ECdCIAampJIAUgC0EDdGpBDGoiBCABQQRqS3EgBUEEaiAAIAEgCkECdGoiAGogB2pBCGpJIABBCGogBElxciEVIAJBAUcgCEEESXIhFiACQQFGIAlBBUtxIRcgCEH8////B3EhECAIQQNxIREgASAFayEYIAUgCEECdGpBBGshGSAFIAhBAmsiAEECdGohGiALQQFqIhJBfHEiDEEBciETIAxBAXRBAXIhCyACIApsQQJ0IRsgACAGa0ECSSEcIAhBAXZBAWsgAmxBAnQhHQNAIAUgASgCACABIBtqIg8gAkECdGooAgAiCSAPKAIAIgBqQQJqQQJ1ayIHIABqNgIA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aCk9AAkJCSBzdGVwc2l6ZXMgKG0sZSk9AC4AKG51bGwpACglZCwlZCkgACVzfQoACQkgfQoAW0RFVl0gRHVtcCBhbiBpbWFnZV9jb21wX2hlYWRlciBzdHJ1Y3QgewoAW0RFVl0gRHVtcCBhbiBpbWFnZV9oZWFkZXIgc3RydWN0IHsKAEltYWdlIGluZm8gewoACSBkZWZhdWx0IHRpbGUgewoAJXMJIGNvbXBvbmVudCAlZCB7CgAJCSBjb21wICVkIHsKAAkgVGlsZSBpbmRleDogewoACSBNYXJrZXIgbGlzdDogewoAQ29kZXN0cmVhbSBpbmRleCBmcm9tIG1haW4gaGVhZGVyOiB7CgBDb2Rlc3RyZWFtIGluZm8gZnJvbSBtYWluIGhlYWRlcjogewoAU3RyZWFtIGVycm9yIHdoaWxlIHJlYWRpbmcgSlAyIEhlYWRlciBib3gKAEZvdW5kIGEgbWlzcGxhY2VkICclYyVjJWMlYycgYm94IG91dHNpZGUganAyaCBib3gKAE1hbGZvcm1lZCBKUDIgZmlsZSBmb3JtYXQ6IGZpcnN0IGJveCBtdXN0IGJlIEpQRUcgMjAwMCBzaWduYXR1cmUgYm94CgBNYWxmb3JtZWQgSlAyIGZpbGUgZm9ybWF0OiBzZWNvbmQgYm94IG11c3QgYmUgZmlsZSB0eXBlIGJveAoATm90IGVub3VnaCBtZW1vcnkgdG8gaGFuZGxlIGpwZWcyMDAwIGJveAoATm90IGVub3VnaCBtZW1vcnkgd2l0aCBGVFlQIEJveAoAQSBtYXJrZXIgSUQgd2FzIGV4cGVjdGVkICgweGZmLS0pIGluc3RlYWQgb2YgJS44eAoACQkgbWN0PSV4CgAJCQkgY2Jsa3N0eT0lI3gKAAkJCSBjc3R5PSUjeAoACQkgcHJnPSUjeAoASW50ZWdlciBvdmVyZmxvdwoACSB0ZHg9JXUsIHRkeT0ldQoACSB0dz0ldSwgdGg9JXUKAAkgdHgwPSV1LCB0eTA9JXUKAEludmFsaWQgY29tcG9uZW50IGluZGV4OiAldQoAU3RyZWFtIHRvbyBzaG9ydAoATWFya2VyIGhhbmRsZXIgZnVuY3Rpb24gZmFpbGVkIHRvIHJlYWQgdGhlIG1hcmtlciBzZWdtZW50CgBOb3QgZW5vdWdoIG1lbW9yeSBmb3IgY3VycmVudCBwcmVjaW5jdCBjb2RlYmxvY2sgZWxlbWVudAoARXJyb3IgcmVhZGluZyBTUENvZCBTUENvYyBlbGVtZW50CgBFcnJvciByZWFkaW5nIFNRY2Qgb3IgU1FjYyBlbGVtZW50CgBBIEJQQ0MgaGVhZGVyIGJveCBpcyBhdmFpbGFibGUgYWx0aG91Z2ggQlBDIGdpdmVuIGJ5IHRoZSBJSERSIGJveCAoJWQpIGluZGljYXRlIGNvbXBvbmVudHMgYml0IGRlcHRoIGlzIGNvbnN0YW50CgBFcnJvciB3aXRoIFNJWiBtYXJrZXI6IGlsbGVnYWwgdGlsZSBvZmZzZXQKAEludmFsaWQgcHJlY2luY3QKAE5vdCBlbm91Z2ggbWVtb3J5IHRvIGhhbmRsZSBiYW5kIHByZWNpbnRzCgBGYWlsZWQgdG8gZGVjb2RlIGFsbCB1c2VkIGNvbXBvbmVudHMKAFNpemUgb2YgY29kZSBibG9jayBkYXRhIGV4Y2VlZHMgc3lzdGVtIGxpbWl0cwoAU2l6ZSBvZiB0aWxlIGRhdGEgZXhjZWVkcyBzeXN0ZW0gbGltaXRzCgBDYW5ub3QgdGFrZSBpbiBjaGFyZ2UgbXVsdGlwbGUgTUNUIG1hcmtlcnMKAENvcnJ1cHRlZCBQUE0gbWFya2VycwoATm90IGVub3VnaCBtZW1vcnkgZm9yIHRpbGUgcmVzb2x1dGlvbnMKAENhbm5vdCB0YWtlIGluIGNoYXJnZSBtdWx0aXBsZSBjb2xsZWN0aW9ucwoASW52YWxpZCBQQ0xSIGJveC4gUmVwb3J0cyAwIHBhbGV0dGUgY29sdW1ucwoAV2UgZG8gbm90IHN1cHBvcnQgUk9JIGluIGRlY29kaW5nIEhUIGNvZGVibG9ja3MKAENhbm5vdCBoYW5kbGUgYm94IG9mIHVuZGVmaW5lZCBzaXplcwoAQ2Fubm90IHRha2UgaW4gY2hhcmdlIGNvbGxlY3Rpb25zIHdpdGhvdXQgc2FtZSBudW1iZXIgb2YgaW5kaXhlcwoASW52YWxpZCB0aWxlYy0+d2luX3h4eCB2YWx1ZXMKAENhbm5vdCBoYW5kbGUgYm94IG9mIGxlc3MgdGhhbiA4IGJ5dGVzCgBDYW5ub3QgaGFuZGxlIFhMIGJveCBvZiBsZXNzIHRoYW4gMTYgYnl0ZXMKAENvbXBvbmVudCBpbmRleCAldSB1c2VkIHNldmVyYWwgdGltZXMKAEludmFsaWQgUENMUiBib3guIFJlcG9ydHMgJWQgZW50cmllcwoATm90IGVub3VnaCBtZW1vcnkgdG8gY3JlYXRlIFRhZy10cmVlIG5vZGVzCgBDYW5ub3QgdGFrZSBpbiBjaGFyZ2UgbWN0IGRhdGEgd2l0aGluIG11bHRpcGxlIE1DVCByZWNvcmRzCgBDYW5ub3QgZGVjb2RlIHRpbGUsIG1lbW9yeSBlcnJvcgoAb3BqX2oya19hcHBseV9uYl90aWxlX3BhcnRzX2NvcnJlY3Rpb24gZXJyb3IKAFByb2JsZW0gd2l0aCBza2lwcGluZyBKUEVHMjAwMCBib3gsIHN0cmVhbSBlcnJvcgoAUHJvYmxlbSB3aXRoIHJlYWRpbmcgSlBFRzIwMDAgYm94LCBzdHJlYW0gZXJyb3IKAFVua25vd24gbWFya2VyCgBOb3QgZW5vdWdoIG1lbW9yeSB0byBhZGQgdGwgbWFya2VyCgBOb3QgZW5vdWdoIG1lbW9yeSB0byBhZGQgbWggbWFya2VyCgBOb3QgZW5vdWdoIG1lbW9yeSB0byB0YWtlIGluIGNoYXJnZSBTSVogbWFya2VyCgBFcnJvciByZWFkaW5nIFBQVCBtYXJrZXIKAE5vdCBlbm91Z2ggbWVtb3J5IHRvIHJlYWQgUFBUIG1hcmtlcgoARXJyb3IgcmVhZGluZyBTT1QgbWFya2VyCgBFcnJvciByZWFkaW5nIFBMVCBtYXJrZXIKAEVycm9yIHJlYWRpbmcgTUNUIG1hcmtlcgoATm90IGVub3VnaCBtZW1vcnkgdG8gcmVhZCBNQ1QgbWFya2VyCgBOb3QgZW5vdWdoIHNwYWNlIGZvciBleHBlY3RlZCBTT1AgbWFya2VyCgBFeHBlY3RlZCBTT1AgbWFya2VyCgBFcnJvciByZWFkaW5nIE1DTyBtYXJrZXIKAEVycm9yIHJlYWRpbmcgUkdOIG1hcmtlcgoARXJyb3IgcmVhZGluZyBQUE0gbWFya2VyCgBOb3QgZW5vdWdoIG1lbW9yeSB0byByZWFkIFBQTSBtYXJrZXIKAEVycm9yIHJlYWRpbmcgVExNIG1hcmtlcgoARXJyb3IgcmVhZGluZyBQTE0gbWFya2VyCgBOb3QgZW5vdWdoIHNwYWNlIGZvciBleHBlY3RlZCBFUEggbWFya2VyCgBFeHBlY3RlZCBFUEggbWFya2VyCgBFcnJvciByZWFkaW5nIENSRyBtYXJrZXIKAFVua25vd24gcHJvZ3Jlc3Npb24gb3JkZXIgaW4gQ09EIG1hcmtlcgoAVW5rbm93biBTY29kIHZhbHVlIGluIENPRCBtYXJrZXIKAEVycm9yIHJlYWRpbmcgQ09EIG1hcmtlcgoARXJyb3IgcmVhZGluZyBRQ0QgbWFya2VyCgBDcnJvciByZWFkaW5nIENCRCBtYXJrZXIKAEVycm9yIHJlYWRpbmcgUE9DIG1hcmtlcgoARXJyb3IgcmVhZGluZyBDT0MgbWFya2VyCgBFcnJvciByZWFkaW5nIFFDQyBtYXJrZXIKAEVycm9yIHJlYWRpbmcgTUNDIG1hcmtlcgoATm90IGVub3VnaCBtZW1vcnkgdG8gcmVhZCBNQ0MgbWFya2VyCgByZXF1aXJlZCBTSVogbWFya2VyIG5vdCBmb3VuZCBpbiBtYWluIGhlYWRlcgoAcmVxdWlyZWQgQ09EIG1hcmtlciBub3QgZm91bmQgaW4gbWFpbiBoZWFkZXIKAHJlcXVpcmVkIFFDRCBtYXJrZXIgbm90IGZvdW5kIGluIG1haW4gaGVhZGVyCgBOb3QgZW5vdWdoIG1lbW9yeSB0byBoYW5kbGUganBlZzIwMDAgZmlsZSBoZWFkZXIKAE5vdCBlbm91Z2ggbWVtb3J5IHRvIHJlYWQgaGVhZGVyCgBFcnJvciB3aXRoIEpQIFNpZ25hdHVyZSA6IGJhZCBtYWdpYyBudW1iZXIKAEluIFNPVCBtYXJrZXIsIFRQU290ICglZCkgaXMgbm90IHZhbGlkIHJlZ2FyZHMgdG8gdGhlIGN1cnJlbnQgbnVtYmVyIG9mIHRpbGUtcGFydCAoJWQpLCBnaXZpbmcgdXAKAEluIFNPVCBtYXJrZXIsIFRQU290ICglZCkgaXMgbm90IHZhbGlkIHJlZ2FyZHMgdG8gdGhlIHByZXZpb3VzIG51bWJlciBvZiB0aWxlLXBhcnQgKCVkKSwgZ2l2aW5nIHVwCgBJbiBTT1QgbWFya2VyLCBUUFNvdCAoJWQpIGlzIG5vdCB2YWxpZCByZWdhcmRzIHRvIHRoZSBjdXJyZW50IG51bWJlciBvZiB0aWxlLXBhcnQgKGhlYWRlcikgKCVkKSwgZ2l2aW5nIHVwCgB0aWxlcyByZXF1aXJlIGF0IGxlYXN0IG9uZSByZXNvbHV0aW9uCgBNYXJrZXIgaXMgbm90IGNvbXBsaWFudCB3aXRoIGl0cyBwb3NpdGlvbgoAUHJvYmxlbSB3aXRoIHNlZWsgZnVuY3Rpb24KAEVycm9yIHJlYWRpbmcgU1BDb2QgU1BDb2MgZWxlbWVudCwgSW52YWxpZCBjYmxrdy9jYmxraCBjb21iaW5hdGlvbgoASW52YWxpZCBtdWx0aXBsZSBjb21wb25lbnQgdHJhbnNmb3JtYXRpb24KAENhbm5vdCB0YWtlIGluIGNoYXJnZSBjb2xsZWN0aW9ucyBvdGhlciB0aGFuIGFycmF5IGRlY29ycmVsYXRpb24KAFRvbyBsYXJnZSB2YWx1ZSBmb3IgTnBwbQoATm90IGVub3VnaCBieXRlcyB0byByZWFkIE5wcG0KAGJhZCBwbGFjZWQganBlZyBjb2Rlc3RyZWFtCgAJIE1haW4gaGVhZGVyIHN0YXJ0IHBvc2l0aW9uPSVsbGkKCSBNYWluIGhlYWRlciBlbmQgcG9zaXRpb249JWxsaQoATWFya2VyIHNpemUgaW5jb25zaXN0ZW50IHdpdGggc3RyZWFtIGxlbmd0aAoAVGlsZSBwYXJ0IGxlbmd0aCBzaXplIGluY29uc2lzdGVudCB3aXRoIHN0cmVhbSBsZW5ndGgKAENhbm5vdCB0YWtlIGluIGNoYXJnZSBtdWx0aXBsZSBkYXRhIHNwYW5uaW5nCgBXcm9uZyBmbGFnCgBFcnJvciB3aXRoIEZUWVAgc2lnbmF0dXJlIEJveCBzaXplCgBFcnJvciB3aXRoIEpQIHNpZ25hdHVyZSBCb3ggc2l6ZQoASW52YWxpZCBwcmVjaW5jdCBzaXplCgBJbmNvbnNpc3RlbnQgbWFya2VyIHNpemUKAEludmFsaWQgbWFya2VyIHNpemUKAEVycm9yIHdpdGggU0laIG1hcmtlciBzaXplCgBOb3QgZW5vdWdoIG1lbW9yeSB0byBhZGQgYSBuZXcgdmFsaWRhdGlvbiBwcm9jZWR1cmUKAE5vdCBlbm91Z2ggbWVtb3J5IHRvIGRlY29kZSB0aWxlCgBGYWlsZWQgdG8gZGVjb2RlIHRoZSBjb2Rlc3RyZWFtIGluIHRoZSBKUDIgZmlsZQoAQ2Fubm90IHRha2UgaW4gY2hhcmdlIGNvbGxlY3Rpb25zIHdpdGggaW5kaXggc2h1ZmZsZQoAQ2Fubm90IGFsbG9jYXRlIFRpZXIgMSBoYW5kbGUKAE5vIGRlY29kZWQgYXJlYSBwYXJhbWV0ZXJzLCBzZXQgdGhlIGRlY29kZWQgYXJlYSB0byB0aGUgd2hvbGUgaW1hZ2UKAE5vdCBlbm91Z2ggbWVtb3J5IHRvIGNyZWF0ZSBUYWctdHJlZQoATm90IGVub3VnaCBtZW1vcnkgdG8gcmVpbml0aWFsaXplIHRoZSB0YWcgdHJlZQoARXJyb3IgcmVhZGluZyBTUENvZCBTUENvYyBlbGVtZW50LCBJbnZhbGlkIHRyYW5zZm9ybWF0aW9uIGZvdW5kCgBFcnJvciByZWFkaW5nIFNQQ29kIFNQQ29jIGVsZW1lbnQuIFVuc3VwcG9ydGVkIE1peGVkIEhUIGNvZGUtYmxvY2sgc3R5bGUgZm91bmQKAFRpbGUgWSBjb29yZGluYXRlcyBhcmUgbm90IHN1cHBvcnRlZAoAVGlsZSBYIGNvb3JkaW5hdGVzIGFyZSBub3Qgc3VwcG9ydGVkCgBJbWFnZSBjb29yZGluYXRlcyBhYm92ZSBJTlRfTUFYIGFyZSBub3Qgc3VwcG9ydGVkCgBKUEVHMjAwMCBIZWFkZXIgYm94IG5vdCByZWFkIHlldCwgJyVjJWMlYyVjJyBib3ggd2lsbCBiZSBpZ25vcmVkCgBvcGpfajJrX21lcmdlX3BwdCgpIGhhcyBhbHJlYWR5IGJlZW4gY2FsbGVkCgBOb3QgZW5vdWdoIG1lbW9yeSB0byByZWFkIFNPVCBtYXJrZXIuIFRpbGUgaW5kZXggYWxsb2NhdGlvbiBmYWlsZWQKAElnbm9yaW5nIGloZHIgYm94LiBGaXJzdCBpaGRyIGJveCBhbHJlYWR5IHJlYWQKAFpwcHQgJXUgYWxyZWFkeSByZWFkCgBacHBtICV1IGFscmVhZHkgcmVhZAoAUFRFUk0gY2hlY2sgZmFpbHVyZTogJWQgc3ludGhldGl6ZWQgMHhGRiBtYXJrZXJzIHJlYWQKAAkJCSBjYmxrdz0yXiVkCgAJCQkgY2Jsa2g9Ml4lZAoACQkJIHFudHN0eT0lZAoAJXMgZHg9JWQsIGR5PSVkCgAJCQkgcm9pc2hpZnQ9JWQKAAkJCSBudW1nYml0cz0lZAoACQkgbnVtbGF5ZXJzPSVkCgAlcyBudW1jb21wcz0lZAoAb3BqX2pwMl9hcHBseV9jZGVmOiBhY249JWQsIG51bWNvbXBzPSVkCgBvcGpfanAyX2FwcGx5X2NkZWY6IGNuPSVkLCBudW1jb21wcz0lZAoACQkJIG51bXJlc29sdXRpb25zPSVkCgAJCSB0eXBlPSUjeCwgcG9zPSVsbGksIGxlbj0lZAoAJXMgc2duZD0lZAoACQkJIHFtZmJpZD0lZAoAJXMgcHJlYz0lZAoACQkgbmIgb2YgdGlsZS1wYXJ0IGluIHRpbGUgWyVkXT0lZAoAJXMgeDE9JWQsIHkxPSVkCgAlcyB4MD0lZCwgeTA9JWQKAEZhaWxlZCB0byBkZWNvZGUgdGlsZSAlZC8lZAoAU2V0dGluZyBkZWNvZGluZyBhcmVhIHRvICVkLCVkLCVkLCVkCgBGYWlsZWQgdG8gZGVjb2RlIGNvbXBvbmVudCAlZAoASW52YWxpZCB2YWx1ZSBmb3IgbnVtcmVzb2x1dGlvbnMgOiAlZCwgbWF4IHZhbHVlIGlzIHNldCBpbiBvcGVuanBlZy5oIGF0ICVkCgBJbnZhbGlkIGNvbXBvbmVudCBudW1iZXI6ICVkLCByZWdhcmRpbmcgdGhlIG51bWJlciBvZiBjb21wb25lbnRzICVkCgBUb28gbWFueSBQT0NzICVkCgBJbnZhbGlkIHRpbGUgbnVtYmVyICVkCgBJbnZhbGlkIHRpbGUgcGFydCBpbmRleCBmb3IgdGlsZSBudW1iZXIgJWQuIEdvdCAlZCwgZXhwZWN0ZWQgJWQKAEVycm9yIHdpdGggU0laIG1hcmtlcjogbnVtYmVyIG9mIGNvbXBvbmVudCBpcyBpbGxlZ2FsIC0+ICVkCgBOb3QgZW5vdWdoIG1lbW9yeSBmb3IgY2llbGFiCgBDYW5ub3QgYWxsb2NhdGUgY2Jsay0+ZGVjb2RlZF9kYXRhCgBGYWlsZWQgdG8gbWVyZ2UgUFBUIGRhdGEKAEZhaWxlZCB0byBtZXJnZSBQUE0gZGF0YQoASW52YWxpZCBudW1iZXIgb2YgbGF5ZXJzIGluIENPRCBtYXJrZXIgOiAlZCBub3QgaW4gcmFuZ2UgWzEtNjU1MzVdCgBTdHJlYW0gdG9vIHNob3J0LCBleHBlY3RlZCBTT1QKAFVuYWJsZSB0byBzZXQgdDEgaGFuZGxlIGFzIFRMUwoAU3RyZWFtIGRvZXMgbm90IGVuZCB3aXRoIEVPQwoAQ2Fubm90IGhhbmRsZSBib3ggc2l6ZXMgaGlnaGVyIHRoYW4gMl4zMgoAb3BqX3BpX25leHRfbHJjcCgpOiBpbnZhbGlkIGNvbXBubzAvY29tcG5vMQoAb3BqX3BpX25leHRfcmxjcCgpOiBpbnZhbGlkIGNvbXBubzAvY29tcG5vMQoAb3BqX3BpX25leHRfY3BybCgpOiBpbnZhbGlkIGNvbXBubzAvY29tcG5vMQoAb3BqX3BpX25leHRfcGNybCgpOiBpbnZhbGlkIGNvbXBubzAvY29tcG5vMQoAb3BqX3BpX25leHRfcnBjbCgpOiBpbnZhbGlkIGNvbXBubzAvY29tcG5vMQoAb3BqX3QxX2RlY29kZV9jYmxrKCk6IHVuc3VwcG9ydGVkIGJwbm9fcGx1c19vbmUgPSAlZCA+PSAzMQoARmFpbGVkIHRvIGRlY29kZSB0aWxlIDEvMQoASW5zdWZmaWNpZW50IGRhdGEgZm9yIENNQVAgYm94LgoATmVlZCB0byByZWFkIGEgUENMUiBib3ggYmVmb3JlIHRoZSBDTUFQIGJveC4KAEluc3VmZmljaWVudCBkYXRhIGZvciBDREVGIGJveC4KAE51bWJlciBvZiBjaGFubmVsIGRlc2NyaXB0aW9uIGlzIGVxdWFsIHRvIHplcm8gaW4gQ0RFRiBib3guCgBTdHJlYW0gZXJyb3Igd2hpbGUgcmVhZGluZyBKUDIgSGVhZGVyIGJveDogbm8gJ2loZHInIGJveC4KAE5vbiBjb25mb3JtYW50IGNvZGVzdHJlYW0gVFBzb3Q9PVROc290LgoAU3RyZWFtIGVycm9yIHdoaWxlIHJlYWRpbmcgSlAyIEhlYWRlciBib3g6IGJveCBsZW5ndGggaXMgaW5jb25zaXN0ZW50LgoAQm94IGxlbmd0aCBpcyBpbmNvbnNpc3RlbnQuCgBSZXNvbHV0aW9uIGZhY3RvciBpcyBncmVhdGVyIHRoYW4gdGhlIG1heGltdW0gcmVzb2x1dGlvbiBpbiB0aGUgY29tcG9uZW50LgoAQ29tcG9uZW50IG1hcHBpbmcgc2VlbXMgd3JvbmcuIFRyeWluZyB0byBjb3JyZWN0LgoASW5jb21wbGV0ZSBjaGFubmVsIGRlZmluaXRpb25zLgoATWFsZm9ybWVkIEhUIGNvZGVibG9jay4gSW52YWxpZCBjb2RlYmxvY2sgbGVuZ3RoIHZhbHVlcy4KAFdlIGRvIG5vdCBzdXBwb3J0IG1vcmUgdGhhbiAzIGNvZGluZyBwYXNzZXMgaW4gYW4gSFQgY29kZWJsb2NrOyBUaGlzIGNvZGVibG9ja3MgaGFzICVkIHBhc3Nlcy4KAE1hbGZvcm1lZCBIVCBjb2RlYmxvY2suIERlY29kaW5nIHRoaXMgY29kZWJsb2NrIGlzIHN0b3BwZWQuIFRoZXJlIGFyZSAlZCB6ZXJvIGJpdHBsYW5lcyBpbiAlZCBiaXRwbGFuZXMuCgBDYW5ub3QgdGFrZSBpbiBjaGFyZ2UgbXVsdGlwbGUgdHJhbnNmb3JtYXRpb24gc3RhZ2VzLgoAVW5rbm93biBtYXJrZXIgaGFzIGJlZW4gZGV0ZWN0ZWQgYW5kIGdlbmVyYXRlZCBlcnJvci4KAENvZGVjIHByb3ZpZGVkIHRvIHRoZSBvcGpfc2V0X2RlY29kZWRfY29tcG9uZW50cyBmdW5jdGlvbiBpcyBub3QgYSBkZWNvbXByZXNzb3IgaGFuZGxlci4KAENvZGVjIHByb3ZpZGVkIHRvIHRoZSBvcGpfc2V0dXBfZGVjb2RlciBmdW5jdGlvbiBpcyBub3QgYSBkZWNvbXByZXNzb3IgaGFuZGxlci4KAENvZGVjIHByb3ZpZGVkIHRvIHRoZSBvcGpfcmVhZF9oZWFkZXIgZnVuY3Rpb24gaXMgbm90IGEgZGVjb21wcmVzc29yIGhhbmRsZXIuCgBUaWxlcyBkb24ndCBhbGwgaGF2ZSB0aGUgc2FtZSBkaW1lbnNpb24uIFNraXAgdGhlIE1DVCBzdGVwLgoATnVtYmVyIG9mIGNvbXBvbmVudHMgKCVkKSBpcyBpbmNvbnNpc3RlbnQgd2l0aCBhIE1DVC4gU2tpcCB0aGUgTUNUIHN0ZXAuCgBKUDIgYm94IHdoaWNoIGFyZSBhZnRlciB0aGUgY29kZXN0cmVhbSB3aWxsIG5vdCBiZSByZWFkIGJ5IHRoaXMgZnVuY3Rpb24uCgBNYWxmb3JtZWQgSFQgY29kZWJsb2NrLiBXaGVuIHRoZSBudW1iZXIgb2YgemVybyBwbGFuZXMgYml0cGxhbmVzIGlzIGVxdWFsIHRvIHRoZSBudW1iZXIgb2YgYml0cGxhbmVzLCBvbmx5IHRoZSBjbGVhbnVwIHBhc3MgbWFrZXMgc2Vuc2UsIGJ1dCB3ZSBoYXZlICVkIHBhc3NlcyBpbiB0aGlzIGNvZGVibG9jay4gVGhlcmVmb3JlLCBvbmx5IHRoZSBjbGVhbnVwIHBhc3Mgd2lsbCBiZSBkZWNvZGVkLiBUaGlzIG1lc3NhZ2Ugd2lsbCBub3QgYmUgZGlzcGxheWVkIGFnYWluLgoASW1hZ2UgaGFzIGxlc3MgY29tcG9uZW50cyB0aGFuIGNvZGVzdHJlYW0uCgBOZWVkIHRvIGRlY29kZSB0aGUgbWFpbiBoZWFkZXIgYmVmb3JlIGJlZ2luIHRvIGRlY29kZSB0aGUgcmVtYWluaW5nIGNvZGVzdHJlYW0uCgBQc290IHZhbHVlIG9mIHRoZSBjdXJyZW50IHRpbGUtcGFydCBpcyBlcXVhbCB0byB6ZXJvLCB3ZSBhc3N1bWluZyBpdCBpcyB0aGUgbGFzdCB0aWxlLXBhcnQgb2YgdGhlIGNvZGVzdHJlYW0uCgBBIG1hbGZvcm1lZCBjb2RlYmxvY2sgdGhhdCBoYXMgbW9yZSB0aGFuIG9uZSBjb2RpbmcgcGFzcywgYnV0IHplcm8gbGVuZ3RoIGZvciAybmQgYW5kIHBvdGVudGlhbGx5IHRoZSAzcmQgcGFzcyBpbiBhbiBIVCBjb2RlYmxvY2suCgAJCQkgdGlsZS1wYXJ0WyVkXTogc3Rhcl9wb3M9JWxsaSwgZW5kX2hlYWRlcj0lbGxpLCBlbmRfcG9zPSVsbGkuCgBUaWxlICV1IGhhcyBUUHNvdCA9PSAwIGFuZCBUTnNvdCA9PSAwLCBidXQgbm8gb3RoZXIgdGlsZS1wYXJ0cyB3ZXJlIGZvdW5kLiBFT0MgaXMgYWxzbyBtaXNzaW5nLgoAQ29tcG9uZW50ICVkIGRvZXNuJ3QgaGF2ZSBhIG1hcHBpbmcuCgBBIGNvbmZvcm1pbmcgSlAyIHJlYWRlciBzaGFsbCBpZ25vcmUgYWxsIENvbG91ciBTcGVjaWZpY2F0aW9uIGJveGVzIGFmdGVyIHRoZSBmaXJzdCwgc28gd2UgaWdub3JlIHRoaXMgb25lLgoAVGhlIHNpZ25hdHVyZSBib3ggbXVzdCBiZSB0aGUgZmlyc3QgYm94IGluIHRoZSBmaWxlLgoAVGhlICBib3ggbXVzdCBiZSB0aGUgZmlyc3QgYm94IGluIHRoZSBmaWxlLgoAVGhlIGZ0eXAgYm94IG11c3QgYmUgdGhlIHNlY29uZCBib3ggaW4gdGhlIGZpbGUuCgBGYWlsZWQgdG8gZGVjb2RlLgoATWFsZm9ybWVkIEhUIGNvZGVibG9jay4gSW5jb3JyZWN0IE1FTCBzZWdtZW50IHNlcXVlbmNlLgoAQ29tcG9uZW50ICVkIGlzIG1hcHBlZCB0d2ljZS4KAE9ubHkgb25lIENNQVAgYm94IGlzIGFsbG93ZWQuCgBhcHBseV9jb2xvcl90cmFuc2Zvcm1zID0gT1BKX1RSVUUgaXMgbm90IHN1cHBvcnRlZC4KAFdlIG5lZWQgYW4gaW1hZ2UgcHJldmlvdXNseSBjcmVhdGVkLgoASUhEUiBib3hfbWlzc2luZy4gUmVxdWlyZWQuCgBKUDJIIGJveCBtaXNzaW5nLiBSZXF1aXJlZC4KAE5vdCBzdXJlIGhvdyB0aGF0IGhhcHBlbmVkLgoATWFpbiBoZWFkZXIgaGFzIGJlZW4gY29ycmVjdGx5IGRlY29kZWQuCgBUaWxlICVkLyVkIGhhcyBiZWVuIGRlY29kZWQuCgBIZWFkZXIgb2YgdGlsZSAlZCAvICVkIGhhcyBiZWVuIHJlYWQuCgBFbXB0eSBTT1QgbWFya2VyIGRldGVjdGVkOiBQc290PSVkLgoARGlyZWN0IHVzZSBhdCAjJWQgaG93ZXZlciBwY29sPSVkLgoASW1wbGVtZW50YXRpb24gbGltaXRhdGlvbjogZm9yIHBhbGV0dGUgbWFwcGluZywgcGNvbFslZF0gc2hvdWxkIGJlIGVxdWFsIHRvICVkLCBidXQgaXMgZXF1YWwgdG8gJWQuCgBJbnZhbGlkIGNvbXBvbmVudC9wYWxldHRlIGluZGV4IGZvciBkaXJlY3QgbWFwcGluZyAlZC4KAEludmFsaWQgdmFsdWUgZm9yIGNtYXBbJWRdLm10eXAgPSAlZC4KAFBzb3QgdmFsdWUgaXMgbm90IGNvcnJlY3QgcmVnYXJkcyB0byB0aGUgSlBFRzIwMDAgbm9ybTogJWQuCgBNYWxmb3JtZWQgSFQgY29kZWJsb2NrLiBWTEMgY29kZSBwcm9kdWNlcyBzaWduaWZpY2FudCBzYW1wbGVzIG91dHNpZGUgdGhlIGNvZGVibG9jayBhcmVhLgoAVW5leHBlY3RlZCBPT00uCgAzMiBiaXRzIGFyZSBub3QgZW5vdWdoIHRvIGRlY29kZSB0aGlzIGNvZGVibG9jaywgc2luY2UgdGhlIG51bWJlciBvZiBiaXRwbGFuZSwgJWQsIGlzIGxhcmdlciB0aGFuIDMwLgoAQm90dG9tIHBvc2l0aW9uIG9mIHRoZSBkZWNvZGVkIGFyZWEgKHJlZ2lvbl95MT0lZCkgc2hvdWxkIGJlID4gMC4KAFJpZ2h0IHBvc2l0aW9uIG9mIHRoZSBkZWNvZGVkIGFyZWEgKHJlZ2lvbl94MT0lZCkgc2hvdWxkIGJlID4gMC4KAFVwIHBvc2l0aW9uIG9mIHRoZSBkZWNvZGVkIGFyZWEgKHJlZ2lvbl95MD0lZCkgc2hvdWxkIGJlID49IDAuCgBMZWZ0IHBvc2l0aW9uIG9mIHRoZSBkZWNvZGVkIGFyZWEgKHJlZ2lvbl94MD0lZCkgc2hvdWxkIGJlID49IDAuCgBFcnJvciByZWFkaW5nIFBQVCBtYXJrZXI6IHBhY2tldCBoZWFkZXIgaGF2ZSBiZWVuIHByZXZpb3VzbHkgZm91bmQgaW4gdGhlIG1haW4gaGVhZGVyIChQUE0gbWFya2VyKS4KAFN0YXJ0IHRvIHJlYWQgajJrIG1haW4gaGVhZGVyICglbGxkKS4KAEJvdHRvbSBwb3NpdGlvbiBvZiB0aGUgZGVjb2RlZCBhcmVhIChyZWdpb25feTE9JWQpIGlzIG91dHNpZGUgdGhlIGltYWdlIGFyZWEgKFlzaXo9JWQpLgoAVXAgcG9zaXRpb24gb2YgdGhlIGRlY29kZWQgYXJlYSAocmVnaW9uX3kwPSVkKSBpcyBvdXRzaWRlIHRoZSBpbWFnZSBhcmVhIChZc2l6PSVkKS4KAFJpZ2h0IHBvc2l0aW9uIG9mIHRoZSBkZWNvZGVkIGFyZWEgKHJlZ2lvbl94MT0lZCkgaXMgb3V0c2lkZSB0aGUgaW1hZ2UgYXJlYSAoWHNpej0lZCkuCgBMZWZ0IHBvc2l0aW9uIG9mIHRoZSBkZWNvZGVkIGFyZWEgKHJlZ2lvbl94MD0lZCkgaXMgb3V0c2lkZSB0aGUgaW1hZ2UgYXJlYSAoWHNpej0lZCkuCgBCb3R0b20gcG9zaXRpb24gb2YgdGhlIGRlY29kZWQgYXJlYSAocmVnaW9uX3kxPSVkKSBpcyBvdXRzaWRlIHRoZSBpbWFnZSBhcmVhIChZT3Npej0lZCkuCgBVcCBwb3NpdGlvbiBvZiB0aGUgZGVjb2RlZCBhcmVhIChyZWdpb25feTA9JWQpIGlzIG91dHNpZGUgdGhlIGltYWdlIGFyZWEgKFlPc2l6PSVkKS4KAFJpZ2h0IHBvc2l0aW9uIG9mIHRoZSBkZWNvZGVkIGFyZWEgKHJlZ2lvbl94MT0lZCkgaXMgb3V0c2lkZSB0aGUgaW1hZ2UgYXJlYSAoWE9zaXo9JWQpLgoATGVmdCBwb3NpdGlvbiBvZiB0aGUgZGVjb2RlZCBhcmVhIChyZWdpb25feDA9JWQpIGlzIG91dHNpZGUgdGhlIGltYWdlIGFyZWEgKFhPc2l6PSVkKS4KAFNpemUgeCBvZiB0aGUgZGVjb2RlZCBjb21wb25lbnQgaW1hZ2UgaXMgaW5jb3JyZWN0IChjb21wWyVkXS53PSVkKS4KAFNpemUgeSBvZiB0aGUgZGVjb2RlZCBjb21wb25lbnQgaW1hZ2UgaXMgaW5jb3JyZWN0IChjb21wWyVkXS5oPSVkKS4KAFRpbGUgcmVhZCwgZGVjb2RlZCBhbmQgdXBkYXRlZCBpcyBub3QgdGhlIGRlc2lyZWQgb25lICglZCB2cyAlZCkuCgBJbnZhbGlkIGNvbXBvbmVudCBpbmRleCAlZCAoPj0gJWQpLgoAb3BqX3JlYWRfaGVhZGVyKCkgc2hvdWxkIGJlIGNhbGxlZCBiZWZvcmUgb3BqX3NldF9kZWNvZGVkX2NvbXBvbmVudHMoKS4KAE1lbW9yeSBhbGxvY2F0aW9uIGZhaWx1cmUgaW4gb3BqX2pwMl9hcHBseV9wY2xyKCkuCgBpbWFnZS0+Y29tcHNbJWRdLmRhdGEgPT0gTlVMTCBpbiBvcGpfanAyX2FwcGx5X3BjbHIoKS4KAGludmFsaWQgYm94IHNpemUgJWQgKCV4KQoARmFpbCB0byByZWFkIHRoZSBjdXJyZW50IG1hcmtlciBzZWdtZW50ICglI3gpCgBFcnJvciB3aXRoIFNJWiBtYXJrZXI6IElIRFIgdygldSkgaCgldSkgdnMuIFNJWiB3KCV1KSBoKCV1KQoARXJyb3IgcmVhZGluZyBDT0MgbWFya2VyIChiYWQgbnVtYmVyIG9mIGNvbXBvbmVudHMpCgBJbnZhbGlkIG51bWJlciBvZiB0aWxlcyA6ICV1IHggJXUgKG1heGltdW0gZml4ZWQgYnkganBlZzIwMDAgbm9ybSBpcyA2NTUzNSB0aWxlcykKAEludmFsaWQgbnVtYmVyIG9mIGNvbXBvbmVudHMgKGloZHIpCgBOb3QgZW5vdWdoIG1lbW9yeSB0byBoYW5kbGUgaW1hZ2UgaGVhZGVyIChpaGRyKQoAV3JvbmcgdmFsdWVzIGZvcjogdyglZCkgaCglZCkgbnVtY29tcHMoJWQpIChpaGRyKQoASW52YWxpZCB2YWx1ZXMgZm9yIGNvbXAgPSAlZCA6IGR4PSV1IGR5PSV1IChzaG91bGQgYmUgYmV0d2VlbiAxIGFuZCAyNTUgYWNjb3JkaW5nIHRvIHRoZSBKUEVHMjAwMCBub3JtKQoAQmFkIGltYWdlIGhlYWRlciBib3ggKGJhZCBzaXplKQoAQmFkIENPTFIgaGVhZGVyIGJveCAoYmFkIHNpemUpCgBCYWQgQlBDQyBoZWFkZXIgYm94IChiYWQgc2l6ZSkKAEVycm9yIHdpdGggU0laIG1hcmtlcjogbmVnYXRpdmUgb3IgemVybyBpbWFnZSBzaXplICglbGxkIHggJWxsZCkKAHNraXA6IHNlZ21lbnQgdG9vIGxvbmcgKCVkKSB3aXRoIG1heCAoJWQpIGZvciBjb2RlYmxvY2sgJWQgKHA9JWQsIGI9JWQsIHI9JWQsIGM9JWQpCgByZWFkOiBzZWdtZW50IHRvbyBsb25nICglZCkgd2l0aCBtYXggKCVkKSBmb3IgY29kZWJsb2NrICVkIChwPSVkLCBiPSVkLCByPSVkLCBjPSVkKQoARGVzcGl0ZSBKUDIgQlBDIT0yNTUsIHByZWNpc2lvbiBhbmQvb3Igc2duZCB2YWx1ZXMgZm9yIGNvbXBbJWRdIGlzIGRpZmZlcmVudCB0aGFuIGNvbXBbMF06CiAgICAgICAgWzBdIHByZWMoJWQpIHNnbmQoJWQpIFslZF0gcHJlYyglZCkgc2duZCglZCkKAGJhZCBjb21wb25lbnQgbnVtYmVyIGluIFJHTiAoJWQgd2hlbiB0aGVyZSBhcmUgb25seSAlZCkKAEVycm9yIHdpdGggU0laIG1hcmtlcjogbnVtYmVyIG9mIGNvbXBvbmVudCBpcyBub3QgY29tcGF0aWJsZSB3aXRoIHRoZSByZW1haW5pbmcgbnVtYmVyIG9mIHBhcmFtZXRlcnMgKCAlZCB2cyAlZCkKAEVycm9yIHdpdGggU0laIG1hcmtlcjogaW52YWxpZCB0aWxlIHNpemUgKHRkeDogJWQsIHRkeTogJWQpCgBCYWQgQ09MUiBoZWFkZXIgYm94IChiYWQgc2l6ZTogJWQpCgBCYWQgQ09MUiBoZWFkZXIgYm94IChDSUVMYWIsIGJhZCBzaXplOiAlZCkKAFBURVJNIGNoZWNrIGZhaWx1cmU6ICVkIHJlbWFpbmluZyBieXRlcyBpbiBjb2RlIGJsb2NrICglZCB1c2VkIC8gJWQpCgBNYWxmb3JtZWQgSFQgY29kZWJsb2NrLiBPbmUgb2YgdGhlIGZvbGxvd2luZyBjb25kaXRpb24gaXMgbm90IG1ldDogMiA8PSBTY3VwIDw9IG1pbihMY3VwLCA0MDc5KQoASW52YWxpZCB2YWx1ZXMgZm9yIGNvbXAgPSAlZCA6IHByZWM9JXUgKHNob3VsZCBiZSBiZXR3ZWVuIDEgYW5kIDM4IGFjY29yZGluZyB0byB0aGUgSlBFRzIwMDAgbm9ybS4gT3BlbkpwZWcgb25seSBzdXBwb3J0cyB1cCB0byAzMSkKAEludmFsaWQgYml0IG51bWJlciAlZCBpbiBvcGpfdDJfcmVhZF9wYWNrZXRfaGVhZGVyKCkKAFN0cmVhbSBlcnJvciEKAEVycm9yIG9uIHdyaXRpbmcgc3RyZWFtIQoAU3RyZWFtIHJlYWNoZWQgaXRzIGVuZCAhCgBFeHBlY3RlZCBhIFNPQyBtYXJrZXIgCgBJbnZhbGlkIGJveCBzaXplICVkIGZvciBib3ggJyVjJWMlYyVjJy4gTmVlZCAlZCBieXRlcywgJWQgYnl0ZXMgcmVtYWluaW5nIAoATWFsZm9ybWVkIEhUIGNvZGVibG9jay4gRGVjb2RpbmcgdGhpcyBjb2RlYmxvY2sgaXMgc3RvcHBlZC4gVV9xIGlzIGxhcmdlciB0aGFuIHplcm8gYml0cGxhbmVzICsgMSAKAE1hbGZvcm1lZCBIVCBjb2RlYmxvY2suIERlY29kaW5nIHRoaXMgY29kZWJsb2NrIGlzIHN0b3BwZWQuIFVfcSBpc2xhcmdlciB0aGFuIGJpdHBsYW5lcyArIDEgCgBDT0xSIEJPWCBtZXRoIHZhbHVlIGlzIG5vdCBhIHJlZ3VsYXIgdmFsdWUgKCVkKSwgc28gd2Ugd2lsbCBpZ25vcmUgdGhlIGVudGlyZSBDb2xvdXIgU3BlY2lmaWNhdGlvbiBib3guIAoAV2hpbGUgcmVhZGluZyBDQ1BfUU5UU1RZIGVsZW1lbnQgaW5zaWRlIFFDRCBvciBRQ0MgbWFya2VyIHNlZ21lbnQsIG51bWJlciBvZiBzdWJiYW5kcyAoJWQpIGlzIGdyZWF0ZXIgdG8gT1BKX0oyS19NQVhCQU5EUyAoJWQpLiBTbyB3ZSBsaW1pdCB0aGUgbnVtYmVyIG9mIGVsZW1lbnRzIHN0b3JlZCB0byBPUEpfSjJLX01BWEJBTkRTICglZCkgYW5kIHNraXAgdGhlIHJlc3QuIAoASlAyIElIRFIgYm94OiBjb21wcmVzc2lvbiB0eXBlIGluZGljYXRlIHRoYXQgdGhlIGZpbGUgaXMgbm90IGEgY29uZm9ybWluZyBKUDIgZmlsZSAoJWQpIAoAVGlsZSBpbmRleCBwcm92aWRlZCBieSB0aGUgdXNlciBpcyBpbmNvcnJlY3QgJWQgKG1heCA9ICVkKSAKAEVycm9yIGRlY29kaW5nIGNvbXBvbmVudCAlZC4KVGhlIG51bWJlciBvZiByZXNvbHV0aW9ucyB0byByZW1vdmUgKCVkKSBpcyBncmVhdGVyIG9yIGVxdWFsIHRoYW4gdGhlIG51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4E8AANBPAAABVgAAAQAAAPBPAADATwAAAVQAAAAAAAAAUAAAwFAAAAFUAAABAAAAEFAAANBQAAABSAAAAAAAACBQAADAUAAAAUgAAAEAAAAwUAAA0FAAAAE4AAAAAAAAQFAAAMBQAAABOAAAAQAAAFBQAADQUAAAATAAAAAAAABgUAAAIFEAAAEwAAABAAAAcFAAADBRAAABJAAAAAAAAIBQAABAUQAAASQAAAEAAACQUAAAUFEAAAEcAAAAAAAAoFAAAIBRAAABHAAAAQAAALBQAACQUQAAARYAAAAAAACgUgAAoFEAAAEWAAABAAAAsFIAALBRAAABVgAAAAAAAOBQAADQUAAAAVYAAAEAAADwUAAAwFAAAAFUAAAAAAAAAFEAAMBQAAABVAAAAQAAABBRAADQUAAAAVEAAAAAAAAgUQAA4FAAAAFRAAABAAAAMFEAAPBQAAABSAAAAAAAAEBRAAAAUQAAAUgAAAEAAABQUQAAEFEAAAE4AAAAAAAAYFEAACBRAAABOAAAAQAAAHBRAAAwUQAAATQAAAAAAACAUQAAQFEAAAE0AAABAAAAkFEAAFBRAAABMAAAAAAAAKBRAABgUQAAATAAAAEAAACwUQAAcFEAAAEoAAAAAAAAwFEAAGBRAAABKAAAAQAAANBRAABwUQAAASQAAAAAAADgUQAAgFEAAAEkAAABAAAA8FEAAJBRAAABIgAAAAAAAABSAACgUQAAASIAAAEAAAAQUgAAsFEAAAEcAAAAAAAAIFIAAMBRAAABHAAAAQAAADBSAADQUQAAARgAAAAAAABAUgAA4FEAAAEYAAABAAAAUFIAAPBRAAABFgAAAAAAAGBSAAAAUgAAARYAAAEAAABwUgAAEFIAAAEUAAAAAAAAgFIAACBSAAABFAAAAQAAAJBSAAAwUgAAARIAAAAAAACgUgAAQFIAAAESAAABAAAAsFIAAFBSAAABEQAAAAAAAMBSAABgUgAAAREAAAEAAADQUgAAcFIAAMEKAAAAAAAA4FIAAIBSAADBCgAAAQAAAPBSAACQUgAAwQkAAAAAAAAAUwAAoFIAAMEJAAABAAAAEFMAALBSAAChCAAAAAAAACBTAADAUgAAoQgAAAEAAAAwUwAA0FIAACEFAAAAAAAAQFMAAOBSAAAhBQAAAQAAAFBTAADwUgAAQQQAAAAAAABgUwAAAFMAAEEEAAABAAAAcFMAABBTAAChAgAAAAAAAIBTAAAgUwAAoQIAAAEAAACQUwAAMFMAACECAAAAAAAAoFMAAEBTAAAhAgAAAQAAALBTAABQUwAAQQEAAAAAAADAUwAAYFMAAEEBAAABAAAA0FMAAHBTAAARAQAAAAAAAOBTAACAUwAAEQEAAAEAAADwUwAAkFMAAIUAAAAAAAAAAFQAAKBTAACFAAAAAQAAABBUAACwUwAASQAAAAAAAAAgVAAAwFMAAEkAAAABAAAAMFQAANBTAAAlAAAAAAAAAEBUAADgUwAAJQAAAAEAAABQVAAA8FMAABUAAAAAAAAAYFQAAABUAAAVAAAAAQAAAHBUAAAQVAAACQAAAAAAAACAVAAAIFQAAAkAAAABAAAAkFQAADBUAAAFAAAAAAAAAKBUAABAVAAABQAAAAEAAACwVAAAUFQAAAEAAAAAAAAAoFQAAGBUAAABAAAAAQAAALBUAABwVAAAAVYAAAAAAADAVAAAwFQAAAFWAAABAAAA0FQAANBUAAAAAQMDAQIDAwUGBwcGBgcHAAEDAwECAwMFBgcHBgYHBwUGBwcGBgcHCAgICAgICAgFBgcHBgYHBwgICAgICAgIAQIDAwICAwMGBgcHBgYHBwECAwMCAgMDBgYHBwYGBwcGBgcHBgYHBwgICAgICAgIBgYHBwYGBwcICAgICAgICAMDBAQDAwQEBwcHBwcHBwcDAwQEAwMEBAcHBwcHBwcHBwcHBwcHBwcICAgICAgICAcHBwcHBwcHCAgICAgICAgDAwQEAwMEBAcHBwcHBwcHAwMEBAMDBAQHBwcHBwcHBwcHBwcHBwcHCAgICAgICAgHBwcHBwcHBwgICAgICAgIAQIDAwICAwMGBgcHBgYHBwECAwMCAgMDBgYHBwYGBwcGBgcHBgYHBwgICAgICAgIBgYHBwYGBwcICAgICAgICAICAwMCAgMDBgYHBwYGBwcCAgMDAgIDAwYGBwcGBgcHBgYHBwYGBwcICAgICAgICAYGBwcGBgcHCAgICAgICAgDAwQEAwMEBAcHBwcHBwcHAwMEBAMDBAQHBwcHBwcHBwcHBwcHBwcHCAgICAgICAgHBwcHBwcHBwgICAgICAgIAwMEBAMDBAQHBwcHBwcHBwMDBAQDAwQEBwcHBwcHBwcHBwcHBwcHBwgICAgICAgIBwcHBwcHBwcICAgICAgICAABBQYBAgYGAwMHBwMDBwcAAQUGAQIGBgMDBwcDAwcHAwMHBwMDBwcEBAcHBAQHBwMDBwcDAwcHBAQHBwQEBwcBAgYGAgIGBgMDBwcDAwcHAQIGBgICBgYDAwcHAwMHBwMDBwcDAwcHBAQHBwQEBwcDAwcHAwMHBwQEBwcEBAcHBQYICAYGCAgHBwgIBwcICAUGCAgGBggIBwcICAcHCAgHBwgIBwcICAcHCAgHBwgIBwcICAcHCAgHBwgIBwcICAYGCAgGBggIBwcICAcHCAgGBggIBgYICAcHCAgHBwgIBwcICAcHCAgHBwgIBwcICAcHCAgHBwgIBwcICAcHCAgBAgYGAgIGBgMDBwcDAwcHAQIGBgICBgYDAwcHAwMHBwMDBwcDAwcHBAQHBwQEBwcDAwcHAwMHBwQEBwcEBAcHAgIGBgICBgYDAwcHAwMHBwICBgYCAgYGAwMHBwMDBwcDAwcHAwMHBwQEBwcEBAcHAwMHBwMDBwcEBAcHBAQHBwYGCAgGBggIBwcICAcHCAgGBggIBgYICAcHCAgHBwgIBwcICAcHCAgHBwgIBwcICAcHCAgHBwgIBwcICAcHCAgGBggIBgYICAcHCAgHBwgIBgYICAYGCAgHBwgIBwcICAcHCAgHBwgIBwcICAcHCAgHBwgIBwcICAcHCAgHBwgIAAEDAwECAwMFBgcHBgYHBwABAwMBAgMDBQYHBwYGBwcFBgcHBgYHBwgICAgICAgIBQYHBwYGBwcICAgICAgICAECAwMCAgMDBgYHBwYGBwcBAgMDAgIDAwYGBwcGBgcHBgYHBwYGBwcICAgICAgICAYGBwcGBgcHCAgICAgICAgDAwQEAwMEBAcHBwcHBwcHAwMEBAMDBAQHBwcHBwcHBwcHBwcHBwcHCAgICAgICAgHBwcHBwcHBwgICAgICAgIAwMEBAMDBAQHBwcHBwcHBwMDBAQDAwQEBwcHBwcHBwcHBwcHBwcHBwgICAgICAgIBwcHBwcHBwcICAgICAgICAECAwMCAgMDBgYHBwYGBwcBAgMDAgIDAwYGBwcGBgcHBgYHBwYGBwcICAgICAgICAYGBwcGBgcHCAgICAgICAgCAgMDAgIDAwYGBwcGBgcHAgIDAwICAwMGBgcHBgYHBwYGBwcGBgcHCAgICAgICAgGBgcHBgYHBwgICAgICAgIAwMEBAMDBAQHBwcHBwcHBwMDBAQDAwQEBwcHBwcHBwcHBwcHBwcHBwgICAgICAgIBwcHBwcHBwcICAgICAgICAMDBAQDAwQEBwcHBwcHBwcDAwQEAwMEBAcHBwcHBwcHBwcHBwcHBwcICAgICAgICAcHBwcHBwcHCAgICAgICAgAAwEEAwYEBwEEAgUEBwUHAAMBBAMGBAcBBAIFBAcFBwEEAgUEBwUHAgUCBQUHBQcBBAIFBAcFBwIFAgUFBwUHAwYEBwYIBwgEBwUHBwgHCAMGBAcGCAcIBAcFBwcIBwgEBwUHBwgHCAUHBQcHCAcIBAcFBwcIBwgFBwUHBwgHCAEEAgUEBwUHAgUCBQUHBQcBBAIFBAcFBwIFAgUFBwUHAgUCBQUHBQcCBQIFBQcFBwIFAgUFBwUHAgUCBQUHBQcEBwUHBwgHCAUHBQcHCAcIBAcFBwcIBwgFBwUHBwgHCAUHBQcHCAcIBQcFBwcIBwgFBwUHBwgHCAUHBQcHCAcIAwYEBwYIBwgEBwUHBwgHCAMGBAcGCAcIBAcFBwcIBwgEBwUHBwgHCAUHBQcHCAcIBAcFBwcIBwgFBwUHBwgHCAYIBwgICAgIBwgHCAgICAgGCAcICAgICAcIBwgICAgIBwgHCAgICAgHCAcICAgICAcIBwgICAgIBwgHCAgICAgEBwUHBwgHCAUHBQcHCAcIBAcFBwcIBwgFBwUHBwgHCAUHBQcHCAcIBQcFBwcIBwgFBwUHBwgHCAUHBQcHCAcIBwgHCAgICAgHCAcICAgICAcIBwgICAgIBwgHCAgICAgHCAcICAgICAcIBwgICAgIBwgHCAgICAgHCAcICAgICAkJCgoJCQoKDAwNCwwMDQsJCQoKCQkKCgwMCw0MDAsNDAwNDQwMCwsMCQ0KCQwKCwwMCwsMDA0NDAkLCgkMCg0JCQoKCQkKCgwMDQsMDA0LCQkKCgkJCgoMDAsNDAwLDQwMDQ0MDAsLDAkNCgkMCgsMDAsLDAwNDQwJCwoJDAoNCgoKCgoKCgoNCw0LDQsNCwoKCQkKCgkJDQsMDA0LDAwNDQ0NCwsLCw0KDQoKCwoLDQ0MDAsLDAwNCgwJCgsJDAoKCQkKCgkJCw0MDAsNDAwKCgoKCgoKCgsNCw0LDQsNCwsMDA0NDAwLCgwJCg0JDAsLCwsNDQ0NCwoLCgoNCg0AQem7AQs3AQABAAEAAQAAAQEAAAEBAAEAAQABAAEAAAAAAQEBAQAAAAAAAQABAAAAAAEBAQEAAAABAAEBAQBBqbwBCzcBAAEAAQABAAABAQAAAQEAAQABAAEAAQAAAAABAQEBAAAAAAABAAEAAAAAAQEBAQAAAAEAAQEBAEHpvAELBwEAAQABAAEAQfm8AQuVAgEAAQABAAEAAAAAAQEBAQAAAAAAAQABAAAAAAEBAQEAAAAAAAEAAQEBAAABAQAAAAEAAQABAAEBAQEBAQEBAQABAAEAAQABAAAAAAEBAQEAAQAAAQEAAQAAAAABAQEBAAEAAQEBAQECAAAABAAAAAQAAAAIAAAAkP8AAAwAAAAYAAAAUv8AABQAAAAZAAAAU/8AABQAAAAaAAAAXv8AABQAAAAbAAAAXP8AABQAAAAcAAAAXf8AABQAAAAdAAAAX/8AABQAAAAeAAAAUf8AAAIAAAAfAAAAVf8AAAQAAAAgAAAAV/8AAAQAAAAhAAAAWP8AABAAAAAiAAAAYP8AAAQAAAAjAAAAYf8AABAAAAAkAAAAkf8AQZi/AQtlY/8AAAQAAAAlAAAAZP8AABQAAAAmAAAAdP8AABQAAAAnAAAAeP8AAAQAAAAoAAAAUP8AAAQAAAApAAAAWf8AAAQAAAAqAAAAdf8AABQAAAArAAAAd/8AABQAAAAsAAAAAAAAABQAQZDAAQs1LQAAAC4AAAAvAAAAMAAAADEAAAAyAAAAMwAAADQAAAAgIFBqNgAAAHB5dGY3AAAAaDJwajgAQdDAAQsycmRoaTkAAABybG9jOgAAAGNjcGI7AAAAcmxjcDwAAABwYW1jPQAAAGZlZGM+AAAAeGIAQZDBAQtBGQALABkZGQAAAAAFAAAAAAAACQAAAAALAAAAAAAAAAAZAAoKGRkZAwoHAAEACQsYAAAJBgsAAAsABhkAAAAZGRkAQeHBAQshDgAAAAAAAAAAGQALDRkZGQANAAACAAkOAAAACQAOAAAOAEGbwgELAQwAQafCAQsVEwAAAAATAAAAAAkMAAAAAAAMAAAMAEHVwgELARAAQeHCAQsVDwAAAAQPAAAAAAkQAAAAAAAQAAAQAEGPwwELARIAQZvDAQseEQAAAAARAAAAAAkSAAAAAAASAAASAAAaAAAAGhoaAEHSwwELDhoAAAAaGhoAAAAAAAAJAEGDxAELARQAQY/EAQsVFwAAAAAXAAAAAAkUAAAAAAAUAAAUAEG9xAELARYAQcnEAQsnFQAAAAAVAAAAAAkWAAAAAAAWAAAWAAAwMTIzNDU2Nzg5QUJDREVGAEHxxAELCGwBAAAAAAAFAEGExQELAWkAQZzFAQsOagAAAGsAAAD4ZwAAAAQAQbTFAQsBAQBBxMUBCwX/////Cg==\";\n    function getBinarySync(file) {\n      if (file == wasmBinaryFile && wasmBinary) {\n        return new Uint8Array(wasmBinary);\n      }\n      var binary = tryParseAsDataURI(file);\n      if (binary) {\n        return binary;\n      }\n      if (readBinary) {\n        return readBinary(file);\n      }\n      throw 'sync fetching of the wasm failed: you can preload it to Module[\"wasmBinary\"] manually, or emcc.py will do that for you when generating HTML (but not JS)';\n    }\n    function instantiateSync(file, info) {\n      var module;\n      var binary = getBinarySync(file);\n      module = new WebAssembly.Module(binary);\n      var instance = new WebAssembly.Instance(module, info);\n      return [instance, module];\n    }\n    function createWasm() {\n      var info = {\n        \"a\": wasmImports\n      };\n      function receiveInstance(instance, module) {\n        wasmExports = instance.exports;\n        wasmMemory = wasmExports[\"i\"];\n        updateMemoryViews();\n        addOnInit(wasmExports[\"j\"]);\n        removeRunDependency(\"wasm-instantiate\");\n        return wasmExports;\n      }\n      addRunDependency(\"wasm-instantiate\");\n      if (Module[\"instantiateWasm\"]) {\n        try {\n          return Module[\"instantiateWasm\"](info, receiveInstance);\n        } catch (e) {\n          err(`Module.instantiateWasm callback failed with error: ${e}`);\n          readyPromiseReject(e);\n        }\n      }\n      var result = instantiateSync(wasmBinaryFile, info);\n      return receiveInstance(result[0]);\n    }\n    var callRuntimeCallbacks = callbacks => {\n      while (callbacks.length > 0) {\n        callbacks.shift()(Module);\n      }\n    };\n    var noExitRuntime = Module[\"noExitRuntime\"] || true;\n    var __emscripten_memcpy_js = (dest, src, num) => HEAPU8.copyWithin(dest, src, src + num);\n    var getHeapMax = () => 2147483648;\n    var growMemory = size => {\n      var b = wasmMemory.buffer;\n      var pages = (size - b.byteLength + 65535) / 65536;\n      try {\n        wasmMemory.grow(pages);\n        updateMemoryViews();\n        return 1;\n      } catch (e) {}\n    };\n    var _emscripten_resize_heap = requestedSize => {\n      var oldSize = HEAPU8.length;\n      requestedSize >>>= 0;\n      var maxHeapSize = getHeapMax();\n      if (requestedSize > maxHeapSize) {\n        return false;\n      }\n      var alignUp = (x, multiple) => x + (multiple - x % multiple) % multiple;\n      for (var cutDown = 1; cutDown <= 4; cutDown *= 2) {\n        var overGrownHeapSize = oldSize * (1 + .2 / cutDown);\n        overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296);\n        var newSize = Math.min(maxHeapSize, alignUp(Math.max(requestedSize, overGrownHeapSize), 65536));\n        var replacement = growMemory(newSize);\n        if (replacement) {\n          return true;\n        }\n      }\n      return false;\n    };\n    var ENV = {};\n    var getExecutableName = () => thisProgram || \"./this.program\";\n    var getEnvStrings = () => {\n      if (!getEnvStrings.strings) {\n        var lang = (typeof navigator == \"object\" && navigator.languages && navigator.languages[0] || \"C\").replace(\"-\", \"_\") + \".UTF-8\";\n        var env = {\n          \"USER\": \"web_user\",\n          \"LOGNAME\": \"web_user\",\n          \"PATH\": \"/\",\n          \"PWD\": \"/\",\n          \"HOME\": \"/home/web_user\",\n          \"LANG\": lang,\n          \"_\": getExecutableName()\n        };\n        for (var x in ENV) {\n          if (ENV[x] === undefined) delete env[x];else env[x] = ENV[x];\n        }\n        var strings = [];\n        for (var x in env) {\n          strings.push(`${x}=${env[x]}`);\n        }\n        getEnvStrings.strings = strings;\n      }\n      return getEnvStrings.strings;\n    };\n    var stringToAscii = (str, buffer) => {\n      for (var i = 0; i < str.length; ++i) {\n        HEAP8[buffer++] = str.charCodeAt(i);\n      }\n      HEAP8[buffer] = 0;\n    };\n    var _environ_get = (__environ, environ_buf) => {\n      var bufSize = 0;\n      getEnvStrings().forEach((string, i) => {\n        var ptr = environ_buf + bufSize;\n        HEAPU32[__environ + i * 4 >> 2] = ptr;\n        stringToAscii(string, ptr);\n        bufSize += string.length + 1;\n      });\n      return 0;\n    };\n    var _environ_sizes_get = (penviron_count, penviron_buf_size) => {\n      var strings = getEnvStrings();\n      HEAPU32[penviron_count >> 2] = strings.length;\n      var bufSize = 0;\n      strings.forEach(string => bufSize += string.length + 1);\n      HEAPU32[penviron_buf_size >> 2] = bufSize;\n      return 0;\n    };\n    var printCharBuffers = [null, [], []];\n    var UTF8Decoder = typeof TextDecoder != \"undefined\" ? new TextDecoder(\"utf8\") : undefined;\n    var UTF8ArrayToString = (heapOrArray, idx, maxBytesToRead) => {\n      var endIdx = idx + maxBytesToRead;\n      var endPtr = idx;\n      while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr;\n      if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {\n        return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr));\n      }\n      var str = \"\";\n      while (idx < endPtr) {\n        var u0 = heapOrArray[idx++];\n        if (!(u0 & 128)) {\n          str += String.fromCharCode(u0);\n          continue;\n        }\n        var u1 = heapOrArray[idx++] & 63;\n        if ((u0 & 224) == 192) {\n          str += String.fromCharCode((u0 & 31) << 6 | u1);\n          continue;\n        }\n        var u2 = heapOrArray[idx++] & 63;\n        if ((u0 & 240) == 224) {\n          u0 = (u0 & 15) << 12 | u1 << 6 | u2;\n        } else {\n          u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | heapOrArray[idx++] & 63;\n        }\n        if (u0 < 65536) {\n          str += String.fromCharCode(u0);\n        } else {\n          var ch = u0 - 65536;\n          str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023);\n        }\n      }\n      return str;\n    };\n    var printChar = (stream, curr) => {\n      var buffer = printCharBuffers[stream];\n      if (curr === 0 || curr === 10) {\n        (stream === 1 ? out : err)(UTF8ArrayToString(buffer, 0));\n        buffer.length = 0;\n      } else {\n        buffer.push(curr);\n      }\n    };\n    var UTF8ToString = (ptr, maxBytesToRead) => ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : \"\";\n    var _fd_write = (fd, iov, iovcnt, pnum) => {\n      var num = 0;\n      for (var i = 0; i < iovcnt; i++) {\n        var ptr = HEAPU32[iov >> 2];\n        var len = HEAPU32[iov + 4 >> 2];\n        iov += 8;\n        for (var j = 0; j < len; j++) {\n          printChar(fd, HEAPU8[ptr + j]);\n        }\n        num += len;\n      }\n      HEAPU32[pnum >> 2] = num;\n      return 0;\n    };\n    function _jsPrintWarning(message_ptr) {\n      const message = UTF8ToString(message_ptr);\n      (Module.warn || console.warn)(`OpenJPEG: ${message}`);\n    }\n    function _setImageData(array_ptr, array_size) {\n      Module.imageData = new Uint8ClampedArray(Module.HEAPU8.subarray(array_ptr, array_ptr + array_size));\n    }\n    function _storeErrorMessage(message_ptr) {\n      const message = UTF8ToString(message_ptr);\n      if (!Module.errorMessages) {\n        Module.errorMessages = message;\n      } else {\n        Module.errorMessages += \"\\n\" + message;\n      }\n    }\n    var wasmImports = {\n      f: __emscripten_memcpy_js,\n      b: _emscripten_resize_heap,\n      c: _environ_get,\n      d: _environ_sizes_get,\n      e: _fd_write,\n      g: _jsPrintWarning,\n      h: _setImageData,\n      a: _storeErrorMessage\n    };\n    var wasmExports = createWasm();\n    var ___wasm_call_ctors = wasmExports[\"j\"];\n    var _malloc = Module[\"_malloc\"] = wasmExports[\"k\"];\n    var _free = Module[\"_free\"] = wasmExports[\"l\"];\n    var _jp2_decode = Module[\"_jp2_decode\"] = wasmExports[\"n\"];\n    var __emscripten_stack_restore = wasmExports[\"_emscripten_stack_restore\"];\n    var __emscripten_stack_alloc = wasmExports[\"_emscripten_stack_alloc\"];\n    var _emscripten_stack_get_current = wasmExports[\"emscripten_stack_get_current\"];\n    var calledRun;\n    dependenciesFulfilled = function runCaller() {\n      if (!calledRun) run();\n      if (!calledRun) dependenciesFulfilled = runCaller;\n    };\n    function run() {\n      if (runDependencies > 0) {\n        return;\n      }\n      preRun();\n      if (runDependencies > 0) {\n        return;\n      }\n      function doRun() {\n        if (calledRun) return;\n        calledRun = true;\n        Module[\"calledRun\"] = true;\n        if (ABORT) return;\n        initRuntime();\n        readyPromiseResolve(Module);\n        if (Module[\"onRuntimeInitialized\"]) Module[\"onRuntimeInitialized\"]();\n        postRun();\n      }\n      if (Module[\"setStatus\"]) {\n        Module[\"setStatus\"](\"Running...\");\n        setTimeout(function () {\n          setTimeout(function () {\n            Module[\"setStatus\"](\"\");\n          }, 1);\n          doRun();\n        }, 1);\n      } else {\n        doRun();\n      }\n    }\n    if (Module[\"preInit\"]) {\n      if (typeof Module[\"preInit\"] == \"function\") Module[\"preInit\"] = [Module[\"preInit\"]];\n      while (Module[\"preInit\"].length > 0) {\n        Module[\"preInit\"].pop()();\n      }\n    }\n    run();\n    return moduleArg;\n  };\n})();\n/* harmony default export */ const openjpeg = (OpenJPEG);\n;// CONCATENATED MODULE: ./src/core/jpx.js\n\n\n\nclass JpxError extends BaseException {\n  constructor(msg) {\n    super(msg, \"JpxError\");\n  }\n}\nclass JpxImage {\n  static #module = null;\n  static decode(data, ignoreColorSpace = false) {\n    this.#module ||= openjpeg({\n      warn: warn\n    });\n    const imageData = this.#module.decode(data, ignoreColorSpace);\n    if (typeof imageData === \"string\") {\n      throw new JpxError(imageData);\n    }\n    return imageData;\n  }\n  static cleanup() {\n    this.#module = null;\n  }\n  static parseImageProperties(stream) {\n    let newByte = stream.getByte();\n    while (newByte >= 0) {\n      const oldByte = newByte;\n      newByte = stream.getByte();\n      const code = oldByte << 8 | newByte;\n      if (code === 0xff51) {\n        stream.skip(4);\n        const Xsiz = stream.getInt32() >>> 0;\n        const Ysiz = stream.getInt32() >>> 0;\n        const XOsiz = stream.getInt32() >>> 0;\n        const YOsiz = stream.getInt32() >>> 0;\n        stream.skip(16);\n        const Csiz = stream.getUint16();\n        return {\n          width: Xsiz - XOsiz,\n          height: Ysiz - YOsiz,\n          bitsPerComponent: 8,\n          componentsCount: Csiz\n        };\n      }\n    }\n    throw new JpxError(\"No size marker found in JPX stream\");\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/jpx_stream.js\n\n\n\nclass JpxStream extends DecodeStream {\n  constructor(stream, maybeLength, params) {\n    super(maybeLength);\n    this.stream = stream;\n    this.dict = stream.dict;\n    this.maybeLength = maybeLength;\n    this.params = params;\n  }\n  get bytes() {\n    return shadow(this, \"bytes\", this.stream.getBytes(this.maybeLength));\n  }\n  ensureBuffer(requested) {}\n  readBlock(ignoreColorSpace) {\n    if (this.eof) {\n      return;\n    }\n    this.buffer = JpxImage.decode(this.bytes, ignoreColorSpace);\n    this.bufferLength = this.buffer.length;\n    this.eof = true;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/lzw_stream.js\n\nclass LZWStream extends DecodeStream {\n  constructor(str, maybeLength, earlyChange) {\n    super(maybeLength);\n    this.str = str;\n    this.dict = str.dict;\n    this.cachedData = 0;\n    this.bitsCached = 0;\n    const maxLzwDictionarySize = 4096;\n    const lzwState = {\n      earlyChange,\n      codeLength: 9,\n      nextCode: 258,\n      dictionaryValues: new Uint8Array(maxLzwDictionarySize),\n      dictionaryLengths: new Uint16Array(maxLzwDictionarySize),\n      dictionaryPrevCodes: new Uint16Array(maxLzwDictionarySize),\n      currentSequence: new Uint8Array(maxLzwDictionarySize),\n      currentSequenceLength: 0\n    };\n    for (let i = 0; i < 256; ++i) {\n      lzwState.dictionaryValues[i] = i;\n      lzwState.dictionaryLengths[i] = 1;\n    }\n    this.lzwState = lzwState;\n  }\n  readBits(n) {\n    let bitsCached = this.bitsCached;\n    let cachedData = this.cachedData;\n    while (bitsCached < n) {\n      const c = this.str.getByte();\n      if (c === -1) {\n        this.eof = true;\n        return null;\n      }\n      cachedData = cachedData << 8 | c;\n      bitsCached += 8;\n    }\n    this.bitsCached = bitsCached -= n;\n    this.cachedData = cachedData;\n    this.lastCode = null;\n    return cachedData >>> bitsCached & (1 << n) - 1;\n  }\n  readBlock() {\n    const blockSize = 512,\n      decodedSizeDelta = blockSize;\n    let estimatedDecodedSize = blockSize * 2;\n    let i, j, q;\n    const lzwState = this.lzwState;\n    if (!lzwState) {\n      return;\n    }\n    const earlyChange = lzwState.earlyChange;\n    let nextCode = lzwState.nextCode;\n    const dictionaryValues = lzwState.dictionaryValues;\n    const dictionaryLengths = lzwState.dictionaryLengths;\n    const dictionaryPrevCodes = lzwState.dictionaryPrevCodes;\n    let codeLength = lzwState.codeLength;\n    let prevCode = lzwState.prevCode;\n    const currentSequence = lzwState.currentSequence;\n    let currentSequenceLength = lzwState.currentSequenceLength;\n    let decodedLength = 0;\n    let currentBufferLength = this.bufferLength;\n    let buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize);\n    for (i = 0; i < blockSize; i++) {\n      const code = this.readBits(codeLength);\n      const hasPrev = currentSequenceLength > 0;\n      if (code < 256) {\n        currentSequence[0] = code;\n        currentSequenceLength = 1;\n      } else if (code >= 258) {\n        if (code < nextCode) {\n          currentSequenceLength = dictionaryLengths[code];\n          for (j = currentSequenceLength - 1, q = code; j >= 0; j--) {\n            currentSequence[j] = dictionaryValues[q];\n            q = dictionaryPrevCodes[q];\n          }\n        } else {\n          currentSequence[currentSequenceLength++] = currentSequence[0];\n        }\n      } else if (code === 256) {\n        codeLength = 9;\n        nextCode = 258;\n        currentSequenceLength = 0;\n        continue;\n      } else {\n        this.eof = true;\n        delete this.lzwState;\n        break;\n      }\n      if (hasPrev) {\n        dictionaryPrevCodes[nextCode] = prevCode;\n        dictionaryLengths[nextCode] = dictionaryLengths[prevCode] + 1;\n        dictionaryValues[nextCode] = currentSequence[0];\n        nextCode++;\n        codeLength = nextCode + earlyChange & nextCode + earlyChange - 1 ? codeLength : Math.min(Math.log(nextCode + earlyChange) / 0.6931471805599453 + 1, 12) | 0;\n      }\n      prevCode = code;\n      decodedLength += currentSequenceLength;\n      if (estimatedDecodedSize < decodedLength) {\n        do {\n          estimatedDecodedSize += decodedSizeDelta;\n        } while (estimatedDecodedSize < decodedLength);\n        buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize);\n      }\n      for (j = 0; j < currentSequenceLength; j++) {\n        buffer[currentBufferLength++] = currentSequence[j];\n      }\n    }\n    lzwState.nextCode = nextCode;\n    lzwState.codeLength = codeLength;\n    lzwState.prevCode = prevCode;\n    lzwState.currentSequenceLength = currentSequenceLength;\n    this.bufferLength = currentBufferLength;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/predictor_stream.js\n\n\n\nclass PredictorStream extends DecodeStream {\n  constructor(str, maybeLength, params) {\n    super(maybeLength);\n    if (!(params instanceof Dict)) {\n      return str;\n    }\n    const predictor = this.predictor = params.get(\"Predictor\") || 1;\n    if (predictor <= 1) {\n      return str;\n    }\n    if (predictor !== 2 && (predictor < 10 || predictor > 15)) {\n      throw new FormatError(`Unsupported predictor: ${predictor}`);\n    }\n    this.readBlock = predictor === 2 ? this.readBlockTiff : this.readBlockPng;\n    this.str = str;\n    this.dict = str.dict;\n    const colors = this.colors = params.get(\"Colors\") || 1;\n    const bits = this.bits = params.get(\"BPC\", \"BitsPerComponent\") || 8;\n    const columns = this.columns = params.get(\"Columns\") || 1;\n    this.pixBytes = colors * bits + 7 >> 3;\n    this.rowBytes = columns * colors * bits + 7 >> 3;\n    return this;\n  }\n  readBlockTiff() {\n    const rowBytes = this.rowBytes;\n    const bufferLength = this.bufferLength;\n    const buffer = this.ensureBuffer(bufferLength + rowBytes);\n    const bits = this.bits;\n    const colors = this.colors;\n    const rawBytes = this.str.getBytes(rowBytes);\n    this.eof = !rawBytes.length;\n    if (this.eof) {\n      return;\n    }\n    let inbuf = 0,\n      outbuf = 0;\n    let inbits = 0,\n      outbits = 0;\n    let pos = bufferLength;\n    let i;\n    if (bits === 1 && colors === 1) {\n      for (i = 0; i < rowBytes; ++i) {\n        let c = rawBytes[i] ^ inbuf;\n        c ^= c >> 1;\n        c ^= c >> 2;\n        c ^= c >> 4;\n        inbuf = (c & 1) << 7;\n        buffer[pos++] = c;\n      }\n    } else if (bits === 8) {\n      for (i = 0; i < colors; ++i) {\n        buffer[pos++] = rawBytes[i];\n      }\n      for (; i < rowBytes; ++i) {\n        buffer[pos] = buffer[pos - colors] + rawBytes[i];\n        pos++;\n      }\n    } else if (bits === 16) {\n      const bytesPerPixel = colors * 2;\n      for (i = 0; i < bytesPerPixel; ++i) {\n        buffer[pos++] = rawBytes[i];\n      }\n      for (; i < rowBytes; i += 2) {\n        const sum = ((rawBytes[i] & 0xff) << 8) + (rawBytes[i + 1] & 0xff) + ((buffer[pos - bytesPerPixel] & 0xff) << 8) + (buffer[pos - bytesPerPixel + 1] & 0xff);\n        buffer[pos++] = sum >> 8 & 0xff;\n        buffer[pos++] = sum & 0xff;\n      }\n    } else {\n      const compArray = new Uint8Array(colors + 1);\n      const bitMask = (1 << bits) - 1;\n      let j = 0,\n        k = bufferLength;\n      const columns = this.columns;\n      for (i = 0; i < columns; ++i) {\n        for (let kk = 0; kk < colors; ++kk) {\n          if (inbits < bits) {\n            inbuf = inbuf << 8 | rawBytes[j++] & 0xff;\n            inbits += 8;\n          }\n          compArray[kk] = compArray[kk] + (inbuf >> inbits - bits) & bitMask;\n          inbits -= bits;\n          outbuf = outbuf << bits | compArray[kk];\n          outbits += bits;\n          if (outbits >= 8) {\n            buffer[k++] = outbuf >> outbits - 8 & 0xff;\n            outbits -= 8;\n          }\n        }\n      }\n      if (outbits > 0) {\n        buffer[k++] = (outbuf << 8 - outbits) + (inbuf & (1 << 8 - outbits) - 1);\n      }\n    }\n    this.bufferLength += rowBytes;\n  }\n  readBlockPng() {\n    const rowBytes = this.rowBytes;\n    const pixBytes = this.pixBytes;\n    const predictor = this.str.getByte();\n    const rawBytes = this.str.getBytes(rowBytes);\n    this.eof = !rawBytes.length;\n    if (this.eof) {\n      return;\n    }\n    const bufferLength = this.bufferLength;\n    const buffer = this.ensureBuffer(bufferLength + rowBytes);\n    let prevRow = buffer.subarray(bufferLength - rowBytes, bufferLength);\n    if (prevRow.length === 0) {\n      prevRow = new Uint8Array(rowBytes);\n    }\n    let i,\n      j = bufferLength,\n      up,\n      c;\n    switch (predictor) {\n      case 0:\n        for (i = 0; i < rowBytes; ++i) {\n          buffer[j++] = rawBytes[i];\n        }\n        break;\n      case 1:\n        for (i = 0; i < pixBytes; ++i) {\n          buffer[j++] = rawBytes[i];\n        }\n        for (; i < rowBytes; ++i) {\n          buffer[j] = buffer[j - pixBytes] + rawBytes[i] & 0xff;\n          j++;\n        }\n        break;\n      case 2:\n        for (i = 0; i < rowBytes; ++i) {\n          buffer[j++] = prevRow[i] + rawBytes[i] & 0xff;\n        }\n        break;\n      case 3:\n        for (i = 0; i < pixBytes; ++i) {\n          buffer[j++] = (prevRow[i] >> 1) + rawBytes[i];\n        }\n        for (; i < rowBytes; ++i) {\n          buffer[j] = (prevRow[i] + buffer[j - pixBytes] >> 1) + rawBytes[i] & 0xff;\n          j++;\n        }\n        break;\n      case 4:\n        for (i = 0; i < pixBytes; ++i) {\n          up = prevRow[i];\n          c = rawBytes[i];\n          buffer[j++] = up + c;\n        }\n        for (; i < rowBytes; ++i) {\n          up = prevRow[i];\n          const upLeft = prevRow[i - pixBytes];\n          const left = buffer[j - pixBytes];\n          const p = left + up - upLeft;\n          let pa = p - left;\n          if (pa < 0) {\n            pa = -pa;\n          }\n          let pb = p - up;\n          if (pb < 0) {\n            pb = -pb;\n          }\n          let pc = p - upLeft;\n          if (pc < 0) {\n            pc = -pc;\n          }\n          c = rawBytes[i];\n          if (pa <= pb && pa <= pc) {\n            buffer[j++] = left + c;\n          } else if (pb <= pc) {\n            buffer[j++] = up + c;\n          } else {\n            buffer[j++] = upLeft + c;\n          }\n        }\n        break;\n      default:\n        throw new FormatError(`Unsupported predictor: ${predictor}`);\n    }\n    this.bufferLength += rowBytes;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/run_length_stream.js\n\nclass RunLengthStream extends DecodeStream {\n  constructor(str, maybeLength) {\n    super(maybeLength);\n    this.str = str;\n    this.dict = str.dict;\n  }\n  readBlock() {\n    const repeatHeader = this.str.getBytes(2);\n    if (!repeatHeader || repeatHeader.length < 2 || repeatHeader[0] === 128) {\n      this.eof = true;\n      return;\n    }\n    let buffer;\n    let bufferLength = this.bufferLength;\n    let n = repeatHeader[0];\n    if (n < 128) {\n      buffer = this.ensureBuffer(bufferLength + n + 1);\n      buffer[bufferLength++] = repeatHeader[1];\n      if (n > 0) {\n        const source = this.str.getBytes(n);\n        buffer.set(source, bufferLength);\n        bufferLength += n;\n      }\n    } else {\n      n = 257 - n;\n      const b = repeatHeader[1];\n      buffer = this.ensureBuffer(bufferLength + n + 1);\n      for (let i = 0; i < n; i++) {\n        buffer[bufferLength++] = b;\n      }\n    }\n    this.bufferLength = bufferLength;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/parser.js\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst MAX_LENGTH_TO_CACHE = 1000;\nfunction getInlineImageCacheKey(bytes) {\n  const strBuf = [],\n    ii = bytes.length;\n  let i = 0;\n  while (i < ii - 1) {\n    strBuf.push(bytes[i++] << 8 | bytes[i++]);\n  }\n  if (i < ii) {\n    strBuf.push(bytes[i]);\n  }\n  return ii + \"_\" + String.fromCharCode.apply(null, strBuf);\n}\nclass Parser {\n  constructor({\n    lexer,\n    xref,\n    allowStreams = false,\n    recoveryMode = false\n  }) {\n    this.lexer = lexer;\n    this.xref = xref;\n    this.allowStreams = allowStreams;\n    this.recoveryMode = recoveryMode;\n    this.imageCache = Object.create(null);\n    this._imageId = 0;\n    this.refill();\n  }\n  refill() {\n    this.buf1 = this.lexer.getObj();\n    this.buf2 = this.lexer.getObj();\n  }\n  shift() {\n    if (this.buf2 instanceof Cmd && this.buf2.cmd === \"ID\") {\n      this.buf1 = this.buf2;\n      this.buf2 = null;\n    } else {\n      this.buf1 = this.buf2;\n      this.buf2 = this.lexer.getObj();\n    }\n  }\n  tryShift() {\n    try {\n      this.shift();\n      return true;\n    } catch (e) {\n      if (e instanceof MissingDataException) {\n        throw e;\n      }\n      return false;\n    }\n  }\n  getObj(cipherTransform = null) {\n    const buf1 = this.buf1;\n    this.shift();\n    if (buf1 instanceof Cmd) {\n      switch (buf1.cmd) {\n        case \"BI\":\n          return this.makeInlineImage(cipherTransform);\n        case \"[\":\n          const array = [];\n          while (!isCmd(this.buf1, \"]\") && this.buf1 !== EOF) {\n            array.push(this.getObj(cipherTransform));\n          }\n          if (this.buf1 === EOF) {\n            if (this.recoveryMode) {\n              return array;\n            }\n            throw new ParserEOFException(\"End of file inside array.\");\n          }\n          this.shift();\n          return array;\n        case \"<<\":\n          const dict = new Dict(this.xref);\n          while (!isCmd(this.buf1, \">>\") && this.buf1 !== EOF) {\n            if (!(this.buf1 instanceof Name)) {\n              info(\"Malformed dictionary: key must be a name object\");\n              this.shift();\n              continue;\n            }\n            const key = this.buf1.name;\n            this.shift();\n            if (this.buf1 === EOF) {\n              break;\n            }\n            dict.set(key, this.getObj(cipherTransform));\n          }\n          if (this.buf1 === EOF) {\n            if (this.recoveryMode) {\n              return dict;\n            }\n            throw new ParserEOFException(\"End of file inside dictionary.\");\n          }\n          if (isCmd(this.buf2, \"stream\")) {\n            return this.allowStreams ? this.makeStream(dict, cipherTransform) : dict;\n          }\n          this.shift();\n          return dict;\n        default:\n          return buf1;\n      }\n    }\n    if (Number.isInteger(buf1)) {\n      if (Number.isInteger(this.buf1) && isCmd(this.buf2, \"R\")) {\n        const ref = Ref.get(buf1, this.buf1);\n        this.shift();\n        this.shift();\n        return ref;\n      }\n      return buf1;\n    }\n    if (typeof buf1 === \"string\") {\n      if (cipherTransform) {\n        return cipherTransform.decryptString(buf1);\n      }\n      return buf1;\n    }\n    return buf1;\n  }\n  findDefaultInlineStreamEnd(stream) {\n    const E = 0x45,\n      I = 0x49,\n      SPACE = 0x20,\n      LF = 0xa,\n      CR = 0xd,\n      NUL = 0x0;\n    const {\n        knownCommands\n      } = this.lexer,\n      startPos = stream.pos,\n      n = 15;\n    let state = 0,\n      ch,\n      maybeEIPos;\n    while ((ch = stream.getByte()) !== -1) {\n      if (state === 0) {\n        state = ch === E ? 1 : 0;\n      } else if (state === 1) {\n        state = ch === I ? 2 : 0;\n      } else {\n        if (ch === SPACE || ch === LF || ch === CR) {\n          maybeEIPos = stream.pos;\n          const followingBytes = stream.peekBytes(n);\n          const ii = followingBytes.length;\n          if (ii === 0) {\n            break;\n          }\n          for (let i = 0; i < ii; i++) {\n            ch = followingBytes[i];\n            if (ch === NUL && followingBytes[i + 1] !== NUL) {\n              continue;\n            }\n            if (ch !== LF && ch !== CR && (ch < SPACE || ch > 0x7f)) {\n              state = 0;\n              break;\n            }\n          }\n          if (state !== 2) {\n            continue;\n          }\n          if (!knownCommands) {\n            warn(\"findDefaultInlineStreamEnd - `lexer.knownCommands` is undefined.\");\n            continue;\n          }\n          const tmpLexer = new Lexer(new Stream(followingBytes.slice()), knownCommands);\n          tmpLexer._hexStringWarn = () => {};\n          let numArgs = 0;\n          while (true) {\n            const nextObj = tmpLexer.getObj();\n            if (nextObj === EOF) {\n              state = 0;\n              break;\n            }\n            if (nextObj instanceof Cmd) {\n              const knownCommand = knownCommands[nextObj.cmd];\n              if (!knownCommand) {\n                state = 0;\n                break;\n              } else if (knownCommand.variableArgs ? numArgs <= knownCommand.numArgs : numArgs === knownCommand.numArgs) {\n                break;\n              }\n              numArgs = 0;\n              continue;\n            }\n            numArgs++;\n          }\n          if (state === 2) {\n            break;\n          }\n        } else {\n          state = 0;\n        }\n      }\n    }\n    if (ch === -1) {\n      warn(\"findDefaultInlineStreamEnd: \" + \"Reached the end of the stream without finding a valid EI marker\");\n      if (maybeEIPos) {\n        warn('... trying to recover by using the last \"EI\" occurrence.');\n        stream.skip(-(stream.pos - maybeEIPos));\n      }\n    }\n    let endOffset = 4;\n    stream.skip(-endOffset);\n    ch = stream.peekByte();\n    stream.skip(endOffset);\n    if (!isWhiteSpace(ch)) {\n      endOffset--;\n    }\n    return stream.pos - endOffset - startPos;\n  }\n  findDCTDecodeInlineStreamEnd(stream) {\n    const startPos = stream.pos;\n    let foundEOI = false,\n      b,\n      markerLength;\n    while ((b = stream.getByte()) !== -1) {\n      if (b !== 0xff) {\n        continue;\n      }\n      switch (stream.getByte()) {\n        case 0x00:\n          break;\n        case 0xff:\n          stream.skip(-1);\n          break;\n        case 0xd9:\n          foundEOI = true;\n          break;\n        case 0xc0:\n        case 0xc1:\n        case 0xc2:\n        case 0xc3:\n        case 0xc5:\n        case 0xc6:\n        case 0xc7:\n        case 0xc9:\n        case 0xca:\n        case 0xcb:\n        case 0xcd:\n        case 0xce:\n        case 0xcf:\n        case 0xc4:\n        case 0xcc:\n        case 0xda:\n        case 0xdb:\n        case 0xdc:\n        case 0xdd:\n        case 0xde:\n        case 0xdf:\n        case 0xe0:\n        case 0xe1:\n        case 0xe2:\n        case 0xe3:\n        case 0xe4:\n        case 0xe5:\n        case 0xe6:\n        case 0xe7:\n        case 0xe8:\n        case 0xe9:\n        case 0xea:\n        case 0xeb:\n        case 0xec:\n        case 0xed:\n        case 0xee:\n        case 0xef:\n        case 0xfe:\n          markerLength = stream.getUint16();\n          if (markerLength > 2) {\n            stream.skip(markerLength - 2);\n          } else {\n            stream.skip(-2);\n          }\n          break;\n      }\n      if (foundEOI) {\n        break;\n      }\n    }\n    const length = stream.pos - startPos;\n    if (b === -1) {\n      warn(\"Inline DCTDecode image stream: \" + \"EOI marker not found, searching for /EI/ instead.\");\n      stream.skip(-length);\n      return this.findDefaultInlineStreamEnd(stream);\n    }\n    this.inlineStreamSkipEI(stream);\n    return length;\n  }\n  findASCII85DecodeInlineStreamEnd(stream) {\n    const TILDE = 0x7e,\n      GT = 0x3e;\n    const startPos = stream.pos;\n    let ch;\n    while ((ch = stream.getByte()) !== -1) {\n      if (ch === TILDE) {\n        const tildePos = stream.pos;\n        ch = stream.peekByte();\n        while (isWhiteSpace(ch)) {\n          stream.skip();\n          ch = stream.peekByte();\n        }\n        if (ch === GT) {\n          stream.skip();\n          break;\n        }\n        if (stream.pos > tildePos) {\n          const maybeEI = stream.peekBytes(2);\n          if (maybeEI[0] === 0x45 && maybeEI[1] === 0x49) {\n            break;\n          }\n        }\n      }\n    }\n    const length = stream.pos - startPos;\n    if (ch === -1) {\n      warn(\"Inline ASCII85Decode image stream: \" + \"EOD marker not found, searching for /EI/ instead.\");\n      stream.skip(-length);\n      return this.findDefaultInlineStreamEnd(stream);\n    }\n    this.inlineStreamSkipEI(stream);\n    return length;\n  }\n  findASCIIHexDecodeInlineStreamEnd(stream) {\n    const GT = 0x3e;\n    const startPos = stream.pos;\n    let ch;\n    while ((ch = stream.getByte()) !== -1) {\n      if (ch === GT) {\n        break;\n      }\n    }\n    const length = stream.pos - startPos;\n    if (ch === -1) {\n      warn(\"Inline ASCIIHexDecode image stream: \" + \"EOD marker not found, searching for /EI/ instead.\");\n      stream.skip(-length);\n      return this.findDefaultInlineStreamEnd(stream);\n    }\n    this.inlineStreamSkipEI(stream);\n    return length;\n  }\n  inlineStreamSkipEI(stream) {\n    const E = 0x45,\n      I = 0x49;\n    let state = 0,\n      ch;\n    while ((ch = stream.getByte()) !== -1) {\n      if (state === 0) {\n        state = ch === E ? 1 : 0;\n      } else if (state === 1) {\n        state = ch === I ? 2 : 0;\n      } else if (state === 2) {\n        break;\n      }\n    }\n  }\n  makeInlineImage(cipherTransform) {\n    const lexer = this.lexer;\n    const stream = lexer.stream;\n    const dictMap = Object.create(null);\n    let dictLength;\n    while (!isCmd(this.buf1, \"ID\") && this.buf1 !== EOF) {\n      if (!(this.buf1 instanceof Name)) {\n        throw new FormatError(\"Dictionary key must be a name object\");\n      }\n      const key = this.buf1.name;\n      this.shift();\n      if (this.buf1 === EOF) {\n        break;\n      }\n      dictMap[key] = this.getObj(cipherTransform);\n    }\n    if (lexer.beginInlineImagePos !== -1) {\n      dictLength = stream.pos - lexer.beginInlineImagePos;\n    }\n    const filter = this.xref.fetchIfRef(dictMap.F || dictMap.Filter);\n    let filterName;\n    if (filter instanceof Name) {\n      filterName = filter.name;\n    } else if (Array.isArray(filter)) {\n      const filterZero = this.xref.fetchIfRef(filter[0]);\n      if (filterZero instanceof Name) {\n        filterName = filterZero.name;\n      }\n    }\n    const startPos = stream.pos;\n    let length;\n    switch (filterName) {\n      case \"DCT\":\n      case \"DCTDecode\":\n        length = this.findDCTDecodeInlineStreamEnd(stream);\n        break;\n      case \"A85\":\n      case \"ASCII85Decode\":\n        length = this.findASCII85DecodeInlineStreamEnd(stream);\n        break;\n      case \"AHx\":\n      case \"ASCIIHexDecode\":\n        length = this.findASCIIHexDecodeInlineStreamEnd(stream);\n        break;\n      default:\n        length = this.findDefaultInlineStreamEnd(stream);\n    }\n    let cacheKey;\n    if (length < MAX_LENGTH_TO_CACHE && dictLength > 0) {\n      const initialStreamPos = stream.pos;\n      stream.pos = lexer.beginInlineImagePos;\n      cacheKey = getInlineImageCacheKey(stream.getBytes(dictLength + length));\n      stream.pos = initialStreamPos;\n      const cacheEntry = this.imageCache[cacheKey];\n      if (cacheEntry !== undefined) {\n        this.buf2 = Cmd.get(\"EI\");\n        this.shift();\n        cacheEntry.reset();\n        return cacheEntry;\n      }\n    }\n    const dict = new Dict(this.xref);\n    for (const key in dictMap) {\n      dict.set(key, dictMap[key]);\n    }\n    let imageStream = stream.makeSubStream(startPos, length, dict);\n    if (cipherTransform) {\n      imageStream = cipherTransform.createStream(imageStream, length);\n    }\n    imageStream = this.filter(imageStream, dict, length);\n    imageStream.dict = dict;\n    if (cacheKey !== undefined) {\n      imageStream.cacheKey = `inline_img_${++this._imageId}`;\n      this.imageCache[cacheKey] = imageStream;\n    }\n    this.buf2 = Cmd.get(\"EI\");\n    this.shift();\n    return imageStream;\n  }\n  _findStreamLength(startPos, signature) {\n    const {\n      stream\n    } = this.lexer;\n    stream.pos = startPos;\n    const SCAN_BLOCK_LENGTH = 2048;\n    const signatureLength = signature.length;\n    while (stream.pos < stream.end) {\n      const scanBytes = stream.peekBytes(SCAN_BLOCK_LENGTH);\n      const scanLength = scanBytes.length - signatureLength;\n      if (scanLength <= 0) {\n        break;\n      }\n      let pos = 0;\n      while (pos < scanLength) {\n        let j = 0;\n        while (j < signatureLength && scanBytes[pos + j] === signature[j]) {\n          j++;\n        }\n        if (j >= signatureLength) {\n          stream.pos += pos;\n          return stream.pos - startPos;\n        }\n        pos++;\n      }\n      stream.pos += scanLength;\n    }\n    return -1;\n  }\n  makeStream(dict, cipherTransform) {\n    const lexer = this.lexer;\n    let stream = lexer.stream;\n    lexer.skipToNextLine();\n    const startPos = stream.pos - 1;\n    let length = dict.get(\"Length\");\n    if (!Number.isInteger(length)) {\n      info(`Bad length \"${length && length.toString()}\" in stream.`);\n      length = 0;\n    }\n    stream.pos = startPos + length;\n    lexer.nextChar();\n    if (this.tryShift() && isCmd(this.buf2, \"endstream\")) {\n      this.shift();\n    } else {\n      const ENDSTREAM_SIGNATURE = new Uint8Array([0x65, 0x6e, 0x64, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d]);\n      let actualLength = this._findStreamLength(startPos, ENDSTREAM_SIGNATURE);\n      if (actualLength < 0) {\n        const MAX_TRUNCATION = 1;\n        for (let i = 1; i <= MAX_TRUNCATION; i++) {\n          const end = ENDSTREAM_SIGNATURE.length - i;\n          const TRUNCATED_SIGNATURE = ENDSTREAM_SIGNATURE.slice(0, end);\n          const maybeLength = this._findStreamLength(startPos, TRUNCATED_SIGNATURE);\n          if (maybeLength >= 0) {\n            const lastByte = stream.peekBytes(end + 1)[end];\n            if (!isWhiteSpace(lastByte)) {\n              break;\n            }\n            info(`Found \"${bytesToString(TRUNCATED_SIGNATURE)}\" when ` + \"searching for endstream command.\");\n            actualLength = maybeLength;\n            break;\n          }\n        }\n        if (actualLength < 0) {\n          throw new FormatError(\"Missing endstream command.\");\n        }\n      }\n      length = actualLength;\n      lexer.nextChar();\n      this.shift();\n      this.shift();\n    }\n    this.shift();\n    stream = stream.makeSubStream(startPos, length, dict);\n    if (cipherTransform) {\n      stream = cipherTransform.createStream(stream, length);\n    }\n    stream = this.filter(stream, dict, length);\n    stream.dict = dict;\n    return stream;\n  }\n  filter(stream, dict, length) {\n    let filter = dict.get(\"F\", \"Filter\");\n    let params = dict.get(\"DP\", \"DecodeParms\");\n    if (filter instanceof Name) {\n      if (Array.isArray(params)) {\n        warn(\"/DecodeParms should not be an Array, when /Filter is a Name.\");\n      }\n      return this.makeFilter(stream, filter.name, length, params);\n    }\n    let maybeLength = length;\n    if (Array.isArray(filter)) {\n      const filterArray = filter;\n      const paramsArray = params;\n      for (let i = 0, ii = filterArray.length; i < ii; ++i) {\n        filter = this.xref.fetchIfRef(filterArray[i]);\n        if (!(filter instanceof Name)) {\n          throw new FormatError(`Bad filter name \"${filter}\"`);\n        }\n        params = null;\n        if (Array.isArray(paramsArray) && i in paramsArray) {\n          params = this.xref.fetchIfRef(paramsArray[i]);\n        }\n        stream = this.makeFilter(stream, filter.name, maybeLength, params);\n        maybeLength = null;\n      }\n    }\n    return stream;\n  }\n  makeFilter(stream, name, maybeLength, params) {\n    if (maybeLength === 0) {\n      warn(`Empty \"${name}\" stream.`);\n      return new NullStream();\n    }\n    try {\n      switch (name) {\n        case \"Fl\":\n        case \"FlateDecode\":\n          if (params) {\n            return new PredictorStream(new FlateStream(stream, maybeLength), maybeLength, params);\n          }\n          return new FlateStream(stream, maybeLength);\n        case \"LZW\":\n        case \"LZWDecode\":\n          let earlyChange = 1;\n          if (params) {\n            if (params.has(\"EarlyChange\")) {\n              earlyChange = params.get(\"EarlyChange\");\n            }\n            return new PredictorStream(new LZWStream(stream, maybeLength, earlyChange), maybeLength, params);\n          }\n          return new LZWStream(stream, maybeLength, earlyChange);\n        case \"DCT\":\n        case \"DCTDecode\":\n          return new JpegStream(stream, maybeLength, params);\n        case \"JPX\":\n        case \"JPXDecode\":\n          return new JpxStream(stream, maybeLength, params);\n        case \"A85\":\n        case \"ASCII85Decode\":\n          return new Ascii85Stream(stream, maybeLength);\n        case \"AHx\":\n        case \"ASCIIHexDecode\":\n          return new AsciiHexStream(stream, maybeLength);\n        case \"CCF\":\n        case \"CCITTFaxDecode\":\n          return new CCITTFaxStream(stream, maybeLength, params);\n        case \"RL\":\n        case \"RunLengthDecode\":\n          return new RunLengthStream(stream, maybeLength);\n        case \"JBIG2Decode\":\n          return new Jbig2Stream(stream, maybeLength, params);\n      }\n      warn(`Filter \"${name}\" is not supported.`);\n      return stream;\n    } catch (ex) {\n      if (ex instanceof MissingDataException) {\n        throw ex;\n      }\n      warn(`Invalid stream: \"${ex}\"`);\n      return new NullStream();\n    }\n  }\n}\nconst specialChars = [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\nfunction toHexDigit(ch) {\n  if (ch >= 0x30 && ch <= 0x39) {\n    return ch & 0x0f;\n  }\n  if (ch >= 0x41 && ch <= 0x46 || ch >= 0x61 && ch <= 0x66) {\n    return (ch & 0x0f) + 9;\n  }\n  return -1;\n}\nclass Lexer {\n  constructor(stream, knownCommands = null) {\n    this.stream = stream;\n    this.nextChar();\n    this.strBuf = [];\n    this.knownCommands = knownCommands;\n    this._hexStringNumWarn = 0;\n    this.beginInlineImagePos = -1;\n  }\n  nextChar() {\n    return this.currentChar = this.stream.getByte();\n  }\n  peekChar() {\n    return this.stream.peekByte();\n  }\n  getNumber() {\n    let ch = this.currentChar;\n    let eNotation = false;\n    let divideBy = 0;\n    let sign = 1;\n    if (ch === 0x2d) {\n      sign = -1;\n      ch = this.nextChar();\n      if (ch === 0x2d) {\n        ch = this.nextChar();\n      }\n    } else if (ch === 0x2b) {\n      ch = this.nextChar();\n    }\n    if (ch === 0x0a || ch === 0x0d) {\n      do {\n        ch = this.nextChar();\n      } while (ch === 0x0a || ch === 0x0d);\n    }\n    if (ch === 0x2e) {\n      divideBy = 10;\n      ch = this.nextChar();\n    }\n    if (ch < 0x30 || ch > 0x39) {\n      const msg = `Invalid number: ${String.fromCharCode(ch)} (charCode ${ch})`;\n      if (isWhiteSpace(ch) || ch === -1) {\n        info(`Lexer.getNumber - \"${msg}\".`);\n        return 0;\n      }\n      throw new FormatError(msg);\n    }\n    let baseValue = ch - 0x30;\n    let powerValue = 0;\n    let powerValueSign = 1;\n    while ((ch = this.nextChar()) >= 0) {\n      if (ch >= 0x30 && ch <= 0x39) {\n        const currentDigit = ch - 0x30;\n        if (eNotation) {\n          powerValue = powerValue * 10 + currentDigit;\n        } else {\n          if (divideBy !== 0) {\n            divideBy *= 10;\n          }\n          baseValue = baseValue * 10 + currentDigit;\n        }\n      } else if (ch === 0x2e) {\n        if (divideBy === 0) {\n          divideBy = 1;\n        } else {\n          break;\n        }\n      } else if (ch === 0x2d) {\n        warn(\"Badly formatted number: minus sign in the middle\");\n      } else if (ch === 0x45 || ch === 0x65) {\n        ch = this.peekChar();\n        if (ch === 0x2b || ch === 0x2d) {\n          powerValueSign = ch === 0x2d ? -1 : 1;\n          this.nextChar();\n        } else if (ch < 0x30 || ch > 0x39) {\n          break;\n        }\n        eNotation = true;\n      } else {\n        break;\n      }\n    }\n    if (divideBy !== 0) {\n      baseValue /= divideBy;\n    }\n    if (eNotation) {\n      baseValue *= 10 ** (powerValueSign * powerValue);\n    }\n    return sign * baseValue;\n  }\n  getString() {\n    let numParen = 1;\n    let done = false;\n    const strBuf = this.strBuf;\n    strBuf.length = 0;\n    let ch = this.nextChar();\n    while (true) {\n      let charBuffered = false;\n      switch (ch | 0) {\n        case -1:\n          warn(\"Unterminated string\");\n          done = true;\n          break;\n        case 0x28:\n          ++numParen;\n          strBuf.push(\"(\");\n          break;\n        case 0x29:\n          if (--numParen === 0) {\n            this.nextChar();\n            done = true;\n          } else {\n            strBuf.push(\")\");\n          }\n          break;\n        case 0x5c:\n          ch = this.nextChar();\n          switch (ch) {\n            case -1:\n              warn(\"Unterminated string\");\n              done = true;\n              break;\n            case 0x6e:\n              strBuf.push(\"\\n\");\n              break;\n            case 0x72:\n              strBuf.push(\"\\r\");\n              break;\n            case 0x74:\n              strBuf.push(\"\\t\");\n              break;\n            case 0x62:\n              strBuf.push(\"\\b\");\n              break;\n            case 0x66:\n              strBuf.push(\"\\f\");\n              break;\n            case 0x5c:\n            case 0x28:\n            case 0x29:\n              strBuf.push(String.fromCharCode(ch));\n              break;\n            case 0x30:\n            case 0x31:\n            case 0x32:\n            case 0x33:\n            case 0x34:\n            case 0x35:\n            case 0x36:\n            case 0x37:\n              let x = ch & 0x0f;\n              ch = this.nextChar();\n              charBuffered = true;\n              if (ch >= 0x30 && ch <= 0x37) {\n                x = (x << 3) + (ch & 0x0f);\n                ch = this.nextChar();\n                if (ch >= 0x30 && ch <= 0x37) {\n                  charBuffered = false;\n                  x = (x << 3) + (ch & 0x0f);\n                }\n              }\n              strBuf.push(String.fromCharCode(x));\n              break;\n            case 0x0d:\n              if (this.peekChar() === 0x0a) {\n                this.nextChar();\n              }\n              break;\n            case 0x0a:\n              break;\n            default:\n              strBuf.push(String.fromCharCode(ch));\n              break;\n          }\n          break;\n        default:\n          strBuf.push(String.fromCharCode(ch));\n          break;\n      }\n      if (done) {\n        break;\n      }\n      if (!charBuffered) {\n        ch = this.nextChar();\n      }\n    }\n    return strBuf.join(\"\");\n  }\n  getName() {\n    let ch, previousCh;\n    const strBuf = this.strBuf;\n    strBuf.length = 0;\n    while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) {\n      if (ch === 0x23) {\n        ch = this.nextChar();\n        if (specialChars[ch]) {\n          warn(\"Lexer_getName: \" + \"NUMBER SIGN (#) should be followed by a hexadecimal number.\");\n          strBuf.push(\"#\");\n          break;\n        }\n        const x = toHexDigit(ch);\n        if (x !== -1) {\n          previousCh = ch;\n          ch = this.nextChar();\n          const x2 = toHexDigit(ch);\n          if (x2 === -1) {\n            warn(`Lexer_getName: Illegal digit (${String.fromCharCode(ch)}) ` + \"in hexadecimal number.\");\n            strBuf.push(\"#\", String.fromCharCode(previousCh));\n            if (specialChars[ch]) {\n              break;\n            }\n            strBuf.push(String.fromCharCode(ch));\n            continue;\n          }\n          strBuf.push(String.fromCharCode(x << 4 | x2));\n        } else {\n          strBuf.push(\"#\", String.fromCharCode(ch));\n        }\n      } else {\n        strBuf.push(String.fromCharCode(ch));\n      }\n    }\n    if (strBuf.length > 127) {\n      warn(`Name token is longer than allowed by the spec: ${strBuf.length}`);\n    }\n    return Name.get(strBuf.join(\"\"));\n  }\n  _hexStringWarn(ch) {\n    const MAX_HEX_STRING_NUM_WARN = 5;\n    if (this._hexStringNumWarn++ === MAX_HEX_STRING_NUM_WARN) {\n      warn(\"getHexString - ignoring additional invalid characters.\");\n      return;\n    }\n    if (this._hexStringNumWarn > MAX_HEX_STRING_NUM_WARN) {\n      return;\n    }\n    warn(`getHexString - ignoring invalid character: ${ch}`);\n  }\n  getHexString() {\n    const strBuf = this.strBuf;\n    strBuf.length = 0;\n    let ch = this.currentChar;\n    let isFirstHex = true;\n    let firstDigit, secondDigit;\n    this._hexStringNumWarn = 0;\n    while (true) {\n      if (ch < 0) {\n        warn(\"Unterminated hex string\");\n        break;\n      } else if (ch === 0x3e) {\n        this.nextChar();\n        break;\n      } else if (specialChars[ch] === 1) {\n        ch = this.nextChar();\n        continue;\n      } else {\n        if (isFirstHex) {\n          firstDigit = toHexDigit(ch);\n          if (firstDigit === -1) {\n            this._hexStringWarn(ch);\n            ch = this.nextChar();\n            continue;\n          }\n        } else {\n          secondDigit = toHexDigit(ch);\n          if (secondDigit === -1) {\n            this._hexStringWarn(ch);\n            ch = this.nextChar();\n            continue;\n          }\n          strBuf.push(String.fromCharCode(firstDigit << 4 | secondDigit));\n        }\n        isFirstHex = !isFirstHex;\n        ch = this.nextChar();\n      }\n    }\n    return strBuf.join(\"\");\n  }\n  getObj() {\n    let comment = false;\n    let ch = this.currentChar;\n    while (true) {\n      if (ch < 0) {\n        return EOF;\n      }\n      if (comment) {\n        if (ch === 0x0a || ch === 0x0d) {\n          comment = false;\n        }\n      } else if (ch === 0x25) {\n        comment = true;\n      } else if (specialChars[ch] !== 1) {\n        break;\n      }\n      ch = this.nextChar();\n    }\n    switch (ch | 0) {\n      case 0x30:\n      case 0x31:\n      case 0x32:\n      case 0x33:\n      case 0x34:\n      case 0x35:\n      case 0x36:\n      case 0x37:\n      case 0x38:\n      case 0x39:\n      case 0x2b:\n      case 0x2d:\n      case 0x2e:\n        return this.getNumber();\n      case 0x28:\n        return this.getString();\n      case 0x2f:\n        return this.getName();\n      case 0x5b:\n        this.nextChar();\n        return Cmd.get(\"[\");\n      case 0x5d:\n        this.nextChar();\n        return Cmd.get(\"]\");\n      case 0x3c:\n        ch = this.nextChar();\n        if (ch === 0x3c) {\n          this.nextChar();\n          return Cmd.get(\"<<\");\n        }\n        return this.getHexString();\n      case 0x3e:\n        ch = this.nextChar();\n        if (ch === 0x3e) {\n          this.nextChar();\n          return Cmd.get(\">>\");\n        }\n        return Cmd.get(\">\");\n      case 0x7b:\n        this.nextChar();\n        return Cmd.get(\"{\");\n      case 0x7d:\n        this.nextChar();\n        return Cmd.get(\"}\");\n      case 0x29:\n        this.nextChar();\n        throw new FormatError(`Illegal character: ${ch}`);\n    }\n    let str = String.fromCharCode(ch);\n    if (ch < 0x20 || ch > 0x7f) {\n      const nextCh = this.peekChar();\n      if (nextCh >= 0x20 && nextCh <= 0x7f) {\n        this.nextChar();\n        return Cmd.get(str);\n      }\n    }\n    const knownCommands = this.knownCommands;\n    let knownCommandFound = knownCommands?.[str] !== undefined;\n    while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) {\n      const possibleCommand = str + String.fromCharCode(ch);\n      if (knownCommandFound && knownCommands[possibleCommand] === undefined) {\n        break;\n      }\n      if (str.length === 128) {\n        throw new FormatError(`Command token too long: ${str.length}`);\n      }\n      str = possibleCommand;\n      knownCommandFound = knownCommands?.[str] !== undefined;\n    }\n    if (str === \"true\") {\n      return true;\n    }\n    if (str === \"false\") {\n      return false;\n    }\n    if (str === \"null\") {\n      return null;\n    }\n    if (str === \"BI\") {\n      this.beginInlineImagePos = this.stream.pos;\n    }\n    return Cmd.get(str);\n  }\n  skipToNextLine() {\n    let ch = this.currentChar;\n    while (ch >= 0) {\n      if (ch === 0x0d) {\n        ch = this.nextChar();\n        if (ch === 0x0a) {\n          this.nextChar();\n        }\n        break;\n      } else if (ch === 0x0a) {\n        this.nextChar();\n        break;\n      }\n      ch = this.nextChar();\n    }\n  }\n}\nclass Linearization {\n  static create(stream) {\n    function getInt(linDict, name, allowZeroValue = false) {\n      const obj = linDict.get(name);\n      if (Number.isInteger(obj) && (allowZeroValue ? obj >= 0 : obj > 0)) {\n        return obj;\n      }\n      throw new Error(`The \"${name}\" parameter in the linearization ` + \"dictionary is invalid.\");\n    }\n    function getHints(linDict) {\n      const hints = linDict.get(\"H\");\n      let hintsLength;\n      if (Array.isArray(hints) && ((hintsLength = hints.length) === 2 || hintsLength === 4)) {\n        for (let index = 0; index < hintsLength; index++) {\n          const hint = hints[index];\n          if (!(Number.isInteger(hint) && hint > 0)) {\n            throw new Error(`Hint (${index}) in the linearization dictionary is invalid.`);\n          }\n        }\n        return hints;\n      }\n      throw new Error(\"Hint array in the linearization dictionary is invalid.\");\n    }\n    const parser = new Parser({\n      lexer: new Lexer(stream),\n      xref: null\n    });\n    const obj1 = parser.getObj();\n    const obj2 = parser.getObj();\n    const obj3 = parser.getObj();\n    const linDict = parser.getObj();\n    let obj, length;\n    if (!(Number.isInteger(obj1) && Number.isInteger(obj2) && isCmd(obj3, \"obj\") && linDict instanceof Dict && typeof (obj = linDict.get(\"Linearized\")) === \"number\" && obj > 0)) {\n      return null;\n    } else if ((length = getInt(linDict, \"L\")) !== stream.length) {\n      throw new Error('The \"L\" parameter in the linearization dictionary ' + \"does not equal the stream length.\");\n    }\n    return {\n      length,\n      hints: getHints(linDict),\n      objectNumberFirst: getInt(linDict, \"O\"),\n      endFirst: getInt(linDict, \"E\"),\n      numPages: getInt(linDict, \"N\"),\n      mainXRefEntriesOffset: getInt(linDict, \"T\"),\n      pageFirst: linDict.has(\"P\") ? getInt(linDict, \"P\", true) : 0\n    };\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/cmap.js\n\n\n\n\n\n\n\nconst BUILT_IN_CMAPS = [\"Adobe-GB1-UCS2\", \"Adobe-CNS1-UCS2\", \"Adobe-Japan1-UCS2\", \"Adobe-Korea1-UCS2\", \"78-EUC-H\", \"78-EUC-V\", \"78-H\", \"78-RKSJ-H\", \"78-RKSJ-V\", \"78-V\", \"78ms-RKSJ-H\", \"78ms-RKSJ-V\", \"83pv-RKSJ-H\", \"90ms-RKSJ-H\", \"90ms-RKSJ-V\", \"90msp-RKSJ-H\", \"90msp-RKSJ-V\", \"90pv-RKSJ-H\", \"90pv-RKSJ-V\", \"Add-H\", \"Add-RKSJ-H\", \"Add-RKSJ-V\", \"Add-V\", \"Adobe-CNS1-0\", \"Adobe-CNS1-1\", \"Adobe-CNS1-2\", \"Adobe-CNS1-3\", \"Adobe-CNS1-4\", \"Adobe-CNS1-5\", \"Adobe-CNS1-6\", \"Adobe-GB1-0\", \"Adobe-GB1-1\", \"Adobe-GB1-2\", \"Adobe-GB1-3\", \"Adobe-GB1-4\", \"Adobe-GB1-5\", \"Adobe-Japan1-0\", \"Adobe-Japan1-1\", \"Adobe-Japan1-2\", \"Adobe-Japan1-3\", \"Adobe-Japan1-4\", \"Adobe-Japan1-5\", \"Adobe-Japan1-6\", \"Adobe-Korea1-0\", \"Adobe-Korea1-1\", \"Adobe-Korea1-2\", \"B5-H\", \"B5-V\", \"B5pc-H\", \"B5pc-V\", \"CNS-EUC-H\", \"CNS-EUC-V\", \"CNS1-H\", \"CNS1-V\", \"CNS2-H\", \"CNS2-V\", \"ETHK-B5-H\", \"ETHK-B5-V\", \"ETen-B5-H\", \"ETen-B5-V\", \"ETenms-B5-H\", \"ETenms-B5-V\", \"EUC-H\", \"EUC-V\", \"Ext-H\", \"Ext-RKSJ-H\", \"Ext-RKSJ-V\", \"Ext-V\", \"GB-EUC-H\", \"GB-EUC-V\", \"GB-H\", \"GB-V\", \"GBK-EUC-H\", \"GBK-EUC-V\", \"GBK2K-H\", \"GBK2K-V\", \"GBKp-EUC-H\", \"GBKp-EUC-V\", \"GBT-EUC-H\", \"GBT-EUC-V\", \"GBT-H\", \"GBT-V\", \"GBTpc-EUC-H\", \"GBTpc-EUC-V\", \"GBpc-EUC-H\", \"GBpc-EUC-V\", \"H\", \"HKdla-B5-H\", \"HKdla-B5-V\", \"HKdlb-B5-H\", \"HKdlb-B5-V\", \"HKgccs-B5-H\", \"HKgccs-B5-V\", \"HKm314-B5-H\", \"HKm314-B5-V\", \"HKm471-B5-H\", \"HKm471-B5-V\", \"HKscs-B5-H\", \"HKscs-B5-V\", \"Hankaku\", \"Hiragana\", \"KSC-EUC-H\", \"KSC-EUC-V\", \"KSC-H\", \"KSC-Johab-H\", \"KSC-Johab-V\", \"KSC-V\", \"KSCms-UHC-H\", \"KSCms-UHC-HW-H\", \"KSCms-UHC-HW-V\", \"KSCms-UHC-V\", \"KSCpc-EUC-H\", \"KSCpc-EUC-V\", \"Katakana\", \"NWP-H\", \"NWP-V\", \"RKSJ-H\", \"RKSJ-V\", \"Roman\", \"UniCNS-UCS2-H\", \"UniCNS-UCS2-V\", \"UniCNS-UTF16-H\", \"UniCNS-UTF16-V\", \"UniCNS-UTF32-H\", \"UniCNS-UTF32-V\", \"UniCNS-UTF8-H\", \"UniCNS-UTF8-V\", \"UniGB-UCS2-H\", \"UniGB-UCS2-V\", \"UniGB-UTF16-H\", \"UniGB-UTF16-V\", \"UniGB-UTF32-H\", \"UniGB-UTF32-V\", \"UniGB-UTF8-H\", \"UniGB-UTF8-V\", \"UniJIS-UCS2-H\", \"UniJIS-UCS2-HW-H\", \"UniJIS-UCS2-HW-V\", \"UniJIS-UCS2-V\", \"UniJIS-UTF16-H\", \"UniJIS-UTF16-V\", \"UniJIS-UTF32-H\", \"UniJIS-UTF32-V\", \"UniJIS-UTF8-H\", \"UniJIS-UTF8-V\", \"UniJIS2004-UTF16-H\", \"UniJIS2004-UTF16-V\", \"UniJIS2004-UTF32-H\", \"UniJIS2004-UTF32-V\", \"UniJIS2004-UTF8-H\", \"UniJIS2004-UTF8-V\", \"UniJISPro-UCS2-HW-V\", \"UniJISPro-UCS2-V\", \"UniJISPro-UTF8-V\", \"UniJISX0213-UTF32-H\", \"UniJISX0213-UTF32-V\", \"UniJISX02132004-UTF32-H\", \"UniJISX02132004-UTF32-V\", \"UniKS-UCS2-H\", \"UniKS-UCS2-V\", \"UniKS-UTF16-H\", \"UniKS-UTF16-V\", \"UniKS-UTF32-H\", \"UniKS-UTF32-V\", \"UniKS-UTF8-H\", \"UniKS-UTF8-V\", \"V\", \"WP-Symbol\"];\nconst MAX_MAP_RANGE = 2 ** 24 - 1;\nclass CMap {\n  constructor(builtInCMap = false) {\n    this.codespaceRanges = [[], [], [], []];\n    this.numCodespaceRanges = 0;\n    this._map = [];\n    this.name = \"\";\n    this.vertical = false;\n    this.useCMap = null;\n    this.builtInCMap = builtInCMap;\n  }\n  addCodespaceRange(n, low, high) {\n    this.codespaceRanges[n - 1].push(low, high);\n    this.numCodespaceRanges++;\n  }\n  mapCidRange(low, high, dstLow) {\n    if (high - low > MAX_MAP_RANGE) {\n      throw new Error(\"mapCidRange - ignoring data above MAX_MAP_RANGE.\");\n    }\n    while (low <= high) {\n      this._map[low++] = dstLow++;\n    }\n  }\n  mapBfRange(low, high, dstLow) {\n    if (high - low > MAX_MAP_RANGE) {\n      throw new Error(\"mapBfRange - ignoring data above MAX_MAP_RANGE.\");\n    }\n    const lastByte = dstLow.length - 1;\n    while (low <= high) {\n      this._map[low++] = dstLow;\n      const nextCharCode = dstLow.charCodeAt(lastByte) + 1;\n      if (nextCharCode > 0xff) {\n        dstLow = dstLow.substring(0, lastByte - 1) + String.fromCharCode(dstLow.charCodeAt(lastByte - 1) + 1) + \"\\x00\";\n        continue;\n      }\n      dstLow = dstLow.substring(0, lastByte) + String.fromCharCode(nextCharCode);\n    }\n  }\n  mapBfRangeToArray(low, high, array) {\n    if (high - low > MAX_MAP_RANGE) {\n      throw new Error(\"mapBfRangeToArray - ignoring data above MAX_MAP_RANGE.\");\n    }\n    const ii = array.length;\n    let i = 0;\n    while (low <= high && i < ii) {\n      this._map[low] = array[i++];\n      ++low;\n    }\n  }\n  mapOne(src, dst) {\n    this._map[src] = dst;\n  }\n  lookup(code) {\n    return this._map[code];\n  }\n  contains(code) {\n    return this._map[code] !== undefined;\n  }\n  forEach(callback) {\n    const map = this._map;\n    const length = map.length;\n    if (length <= 0x10000) {\n      for (let i = 0; i < length; i++) {\n        if (map[i] !== undefined) {\n          callback(i, map[i]);\n        }\n      }\n    } else {\n      for (const i in map) {\n        callback(i, map[i]);\n      }\n    }\n  }\n  charCodeOf(value) {\n    const map = this._map;\n    if (map.length <= 0x10000) {\n      return map.indexOf(value);\n    }\n    for (const charCode in map) {\n      if (map[charCode] === value) {\n        return charCode | 0;\n      }\n    }\n    return -1;\n  }\n  getMap() {\n    return this._map;\n  }\n  readCharCode(str, offset, out) {\n    let c = 0;\n    const codespaceRanges = this.codespaceRanges;\n    for (let n = 0, nn = codespaceRanges.length; n < nn; n++) {\n      c = (c << 8 | str.charCodeAt(offset + n)) >>> 0;\n      const codespaceRange = codespaceRanges[n];\n      for (let k = 0, kk = codespaceRange.length; k < kk;) {\n        const low = codespaceRange[k++];\n        const high = codespaceRange[k++];\n        if (c >= low && c <= high) {\n          out.charcode = c;\n          out.length = n + 1;\n          return;\n        }\n      }\n    }\n    out.charcode = 0;\n    out.length = 1;\n  }\n  getCharCodeLength(charCode) {\n    const codespaceRanges = this.codespaceRanges;\n    for (let n = 0, nn = codespaceRanges.length; n < nn; n++) {\n      const codespaceRange = codespaceRanges[n];\n      for (let k = 0, kk = codespaceRange.length; k < kk;) {\n        const low = codespaceRange[k++];\n        const high = codespaceRange[k++];\n        if (charCode >= low && charCode <= high) {\n          return n + 1;\n        }\n      }\n    }\n    return 1;\n  }\n  get length() {\n    return this._map.length;\n  }\n  get isIdentityCMap() {\n    if (!(this.name === \"Identity-H\" || this.name === \"Identity-V\")) {\n      return false;\n    }\n    if (this._map.length !== 0x10000) {\n      return false;\n    }\n    for (let i = 0; i < 0x10000; i++) {\n      if (this._map[i] !== i) {\n        return false;\n      }\n    }\n    return true;\n  }\n}\nclass IdentityCMap extends CMap {\n  constructor(vertical, n) {\n    super();\n    this.vertical = vertical;\n    this.addCodespaceRange(n, 0, 0xffff);\n  }\n  mapCidRange(low, high, dstLow) {\n    unreachable(\"should not call mapCidRange\");\n  }\n  mapBfRange(low, high, dstLow) {\n    unreachable(\"should not call mapBfRange\");\n  }\n  mapBfRangeToArray(low, high, array) {\n    unreachable(\"should not call mapBfRangeToArray\");\n  }\n  mapOne(src, dst) {\n    unreachable(\"should not call mapCidOne\");\n  }\n  lookup(code) {\n    return Number.isInteger(code) && code <= 0xffff ? code : undefined;\n  }\n  contains(code) {\n    return Number.isInteger(code) && code <= 0xffff;\n  }\n  forEach(callback) {\n    for (let i = 0; i <= 0xffff; i++) {\n      callback(i, i);\n    }\n  }\n  charCodeOf(value) {\n    return Number.isInteger(value) && value <= 0xffff ? value : -1;\n  }\n  getMap() {\n    const map = new Array(0x10000);\n    for (let i = 0; i <= 0xffff; i++) {\n      map[i] = i;\n    }\n    return map;\n  }\n  get length() {\n    return 0x10000;\n  }\n  get isIdentityCMap() {\n    unreachable(\"should not access .isIdentityCMap\");\n  }\n}\nfunction strToInt(str) {\n  let a = 0;\n  for (let i = 0; i < str.length; i++) {\n    a = a << 8 | str.charCodeAt(i);\n  }\n  return a >>> 0;\n}\nfunction expectString(obj) {\n  if (typeof obj !== \"string\") {\n    throw new FormatError(\"Malformed CMap: expected string.\");\n  }\n}\nfunction expectInt(obj) {\n  if (!Number.isInteger(obj)) {\n    throw new FormatError(\"Malformed CMap: expected int.\");\n  }\n}\nfunction parseBfChar(cMap, lexer) {\n  while (true) {\n    let obj = lexer.getObj();\n    if (obj === EOF) {\n      break;\n    }\n    if (isCmd(obj, \"endbfchar\")) {\n      return;\n    }\n    expectString(obj);\n    const src = strToInt(obj);\n    obj = lexer.getObj();\n    expectString(obj);\n    const dst = obj;\n    cMap.mapOne(src, dst);\n  }\n}\nfunction parseBfRange(cMap, lexer) {\n  while (true) {\n    let obj = lexer.getObj();\n    if (obj === EOF) {\n      break;\n    }\n    if (isCmd(obj, \"endbfrange\")) {\n      return;\n    }\n    expectString(obj);\n    const low = strToInt(obj);\n    obj = lexer.getObj();\n    expectString(obj);\n    const high = strToInt(obj);\n    obj = lexer.getObj();\n    if (Number.isInteger(obj) || typeof obj === \"string\") {\n      const dstLow = Number.isInteger(obj) ? String.fromCharCode(obj) : obj;\n      cMap.mapBfRange(low, high, dstLow);\n    } else if (isCmd(obj, \"[\")) {\n      obj = lexer.getObj();\n      const array = [];\n      while (!isCmd(obj, \"]\") && obj !== EOF) {\n        array.push(obj);\n        obj = lexer.getObj();\n      }\n      cMap.mapBfRangeToArray(low, high, array);\n    } else {\n      break;\n    }\n  }\n  throw new FormatError(\"Invalid bf range.\");\n}\nfunction parseCidChar(cMap, lexer) {\n  while (true) {\n    let obj = lexer.getObj();\n    if (obj === EOF) {\n      break;\n    }\n    if (isCmd(obj, \"endcidchar\")) {\n      return;\n    }\n    expectString(obj);\n    const src = strToInt(obj);\n    obj = lexer.getObj();\n    expectInt(obj);\n    const dst = obj;\n    cMap.mapOne(src, dst);\n  }\n}\nfunction parseCidRange(cMap, lexer) {\n  while (true) {\n    let obj = lexer.getObj();\n    if (obj === EOF) {\n      break;\n    }\n    if (isCmd(obj, \"endcidrange\")) {\n      return;\n    }\n    expectString(obj);\n    const low = strToInt(obj);\n    obj = lexer.getObj();\n    expectString(obj);\n    const high = strToInt(obj);\n    obj = lexer.getObj();\n    expectInt(obj);\n    const dstLow = obj;\n    cMap.mapCidRange(low, high, dstLow);\n  }\n}\nfunction parseCodespaceRange(cMap, lexer) {\n  while (true) {\n    let obj = lexer.getObj();\n    if (obj === EOF) {\n      break;\n    }\n    if (isCmd(obj, \"endcodespacerange\")) {\n      return;\n    }\n    if (typeof obj !== \"string\") {\n      break;\n    }\n    const low = strToInt(obj);\n    obj = lexer.getObj();\n    if (typeof obj !== \"string\") {\n      break;\n    }\n    const high = strToInt(obj);\n    cMap.addCodespaceRange(obj.length, low, high);\n  }\n  throw new FormatError(\"Invalid codespace range.\");\n}\nfunction parseWMode(cMap, lexer) {\n  const obj = lexer.getObj();\n  if (Number.isInteger(obj)) {\n    cMap.vertical = !!obj;\n  }\n}\nfunction parseCMapName(cMap, lexer) {\n  const obj = lexer.getObj();\n  if (obj instanceof Name) {\n    cMap.name = obj.name;\n  }\n}\nasync function parseCMap(cMap, lexer, fetchBuiltInCMap, useCMap) {\n  let previous, embeddedUseCMap;\n  objLoop: while (true) {\n    try {\n      const obj = lexer.getObj();\n      if (obj === EOF) {\n        break;\n      } else if (obj instanceof Name) {\n        if (obj.name === \"WMode\") {\n          parseWMode(cMap, lexer);\n        } else if (obj.name === \"CMapName\") {\n          parseCMapName(cMap, lexer);\n        }\n        previous = obj;\n      } else if (obj instanceof Cmd) {\n        switch (obj.cmd) {\n          case \"endcmap\":\n            break objLoop;\n          case \"usecmap\":\n            if (previous instanceof Name) {\n              embeddedUseCMap = previous.name;\n            }\n            break;\n          case \"begincodespacerange\":\n            parseCodespaceRange(cMap, lexer);\n            break;\n          case \"beginbfchar\":\n            parseBfChar(cMap, lexer);\n            break;\n          case \"begincidchar\":\n            parseCidChar(cMap, lexer);\n            break;\n          case \"beginbfrange\":\n            parseBfRange(cMap, lexer);\n            break;\n          case \"begincidrange\":\n            parseCidRange(cMap, lexer);\n            break;\n        }\n      }\n    } catch (ex) {\n      if (ex instanceof MissingDataException) {\n        throw ex;\n      }\n      warn(\"Invalid cMap data: \" + ex);\n      continue;\n    }\n  }\n  if (!useCMap && embeddedUseCMap) {\n    useCMap = embeddedUseCMap;\n  }\n  if (useCMap) {\n    return extendCMap(cMap, fetchBuiltInCMap, useCMap);\n  }\n  return cMap;\n}\nasync function extendCMap(cMap, fetchBuiltInCMap, useCMap) {\n  cMap.useCMap = await createBuiltInCMap(useCMap, fetchBuiltInCMap);\n  if (cMap.numCodespaceRanges === 0) {\n    const useCodespaceRanges = cMap.useCMap.codespaceRanges;\n    for (let i = 0; i < useCodespaceRanges.length; i++) {\n      cMap.codespaceRanges[i] = useCodespaceRanges[i].slice();\n    }\n    cMap.numCodespaceRanges = cMap.useCMap.numCodespaceRanges;\n  }\n  cMap.useCMap.forEach(function (key, value) {\n    if (!cMap.contains(key)) {\n      cMap.mapOne(key, cMap.useCMap.lookup(key));\n    }\n  });\n  return cMap;\n}\nasync function createBuiltInCMap(name, fetchBuiltInCMap) {\n  if (name === \"Identity-H\") {\n    return new IdentityCMap(false, 2);\n  } else if (name === \"Identity-V\") {\n    return new IdentityCMap(true, 2);\n  }\n  if (!BUILT_IN_CMAPS.includes(name)) {\n    throw new Error(\"Unknown CMap name: \" + name);\n  }\n  if (!fetchBuiltInCMap) {\n    throw new Error(\"Built-in CMap parameters are not provided.\");\n  }\n  const {\n    cMapData,\n    compressionType\n  } = await fetchBuiltInCMap(name);\n  const cMap = new CMap(true);\n  if (compressionType === CMapCompressionType.BINARY) {\n    return new BinaryCMapReader().process(cMapData, cMap, useCMap => extendCMap(cMap, fetchBuiltInCMap, useCMap));\n  }\n  if (compressionType === CMapCompressionType.NONE) {\n    const lexer = new Lexer(new Stream(cMapData));\n    return parseCMap(cMap, lexer, fetchBuiltInCMap, null);\n  }\n  throw new Error(`Invalid CMap \"compressionType\" value: ${compressionType}`);\n}\nclass CMapFactory {\n  static async create({\n    encoding,\n    fetchBuiltInCMap,\n    useCMap\n  }) {\n    if (encoding instanceof Name) {\n      return createBuiltInCMap(encoding.name, fetchBuiltInCMap);\n    } else if (encoding instanceof BaseStream) {\n      const parsedCMap = await parseCMap(new CMap(), new Lexer(encoding), fetchBuiltInCMap, useCMap);\n      if (parsedCMap.isIdentityCMap) {\n        return createBuiltInCMap(parsedCMap.name, fetchBuiltInCMap);\n      }\n      return parsedCMap;\n    }\n    throw new Error(\"Encoding required.\");\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/charsets.js\nconst ISOAdobeCharset = [\".notdef\", \"space\", \"exclam\", \"quotedbl\", \"numbersign\", \"dollar\", \"percent\", \"ampersand\", \"quoteright\", \"parenleft\", \"parenright\", \"asterisk\", \"plus\", \"comma\", \"hyphen\", \"period\", \"slash\", \"zero\", \"one\", \"two\", \"three\", \"four\", \"five\", \"six\", \"seven\", \"eight\", \"nine\", \"colon\", \"semicolon\", \"less\", \"equal\", \"greater\", \"question\", \"at\", \"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\", \"I\", \"J\", \"K\", \"L\", \"M\", \"N\", \"O\", \"P\", \"Q\", \"R\", \"S\", \"T\", \"U\", \"V\", \"W\", \"X\", \"Y\", \"Z\", \"bracketleft\", \"backslash\", \"bracketright\", \"asciicircum\", \"underscore\", \"quoteleft\", \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\", \"k\", \"l\", \"m\", \"n\", \"o\", \"p\", \"q\", \"r\", \"s\", \"t\", \"u\", \"v\", \"w\", \"x\", \"y\", \"z\", \"braceleft\", \"bar\", \"braceright\", \"asciitilde\", \"exclamdown\", \"cent\", \"sterling\", \"fraction\", \"yen\", \"florin\", \"section\", \"currency\", \"quotesingle\", \"quotedblleft\", \"guillemotleft\", \"guilsinglleft\", \"guilsinglright\", \"fi\", \"fl\", \"endash\", \"dagger\", \"daggerdbl\", \"periodcentered\", \"paragraph\", \"bullet\", \"quotesinglbase\", \"quotedblbase\", \"quotedblright\", \"guillemotright\", \"ellipsis\", \"perthousand\", \"questiondown\", \"grave\", \"acute\", \"circumflex\", \"tilde\", \"macron\", \"breve\", \"dotaccent\", \"dieresis\", \"ring\", \"cedilla\", \"hungarumlaut\", \"ogonek\", \"caron\", \"emdash\", \"AE\", \"ordfeminine\", \"Lslash\", \"Oslash\", \"OE\", \"ordmasculine\", \"ae\", \"dotlessi\", \"lslash\", \"oslash\", \"oe\", \"germandbls\", \"onesuperior\", \"logicalnot\", \"mu\", \"trademark\", \"Eth\", \"onehalf\", \"plusminus\", \"Thorn\", \"onequarter\", \"divide\", \"brokenbar\", \"degree\", \"thorn\", \"threequarters\", \"twosuperior\", \"registered\", \"minus\", \"eth\", \"multiply\", \"threesuperior\", \"copyright\", \"Aacute\", \"Acircumflex\", \"Adieresis\", \"Agrave\", \"Aring\", \"Atilde\", \"Ccedilla\", \"Eacute\", \"Ecircumflex\", \"Edieresis\", \"Egrave\", \"Iacute\", \"Icircumflex\", \"Idieresis\", \"Igrave\", \"Ntilde\", \"Oacute\", \"Ocircumflex\", \"Odieresis\", \"Ograve\", \"Otilde\", \"Scaron\", \"Uacute\", \"Ucircumflex\", \"Udieresis\", \"Ugrave\", \"Yacute\", \"Ydieresis\", \"Zcaron\", \"aacute\", \"acircumflex\", \"adieresis\", \"agrave\", \"aring\", \"atilde\", \"ccedilla\", \"eacute\", \"ecircumflex\", \"edieresis\", \"egrave\", \"iacute\", \"icircumflex\", \"idieresis\", \"igrave\", \"ntilde\", \"oacute\", \"ocircumflex\", \"odieresis\", \"ograve\", \"otilde\", \"scaron\", \"uacute\", \"ucircumflex\", \"udieresis\", \"ugrave\", \"yacute\", \"ydieresis\", \"zcaron\"];\nconst ExpertCharset = [\".notdef\", \"space\", \"exclamsmall\", \"Hungarumlautsmall\", \"dollaroldstyle\", \"dollarsuperior\", \"ampersandsmall\", \"Acutesmall\", \"parenleftsuperior\", \"parenrightsuperior\", \"twodotenleader\", \"onedotenleader\", \"comma\", \"hyphen\", \"period\", \"fraction\", \"zerooldstyle\", \"oneoldstyle\", \"twooldstyle\", \"threeoldstyle\", \"fouroldstyle\", \"fiveoldstyle\", \"sixoldstyle\", \"sevenoldstyle\", \"eightoldstyle\", \"nineoldstyle\", \"colon\", \"semicolon\", \"commasuperior\", \"threequartersemdash\", \"periodsuperior\", \"questionsmall\", \"asuperior\", \"bsuperior\", \"centsuperior\", \"dsuperior\", \"esuperior\", \"isuperior\", \"lsuperior\", \"msuperior\", \"nsuperior\", \"osuperior\", \"rsuperior\", \"ssuperior\", \"tsuperior\", \"ff\", \"fi\", \"fl\", \"ffi\", \"ffl\", \"parenleftinferior\", \"parenrightinferior\", \"Circumflexsmall\", \"hyphensuperior\", \"Gravesmall\", \"Asmall\", \"Bsmall\", \"Csmall\", \"Dsmall\", \"Esmall\", \"Fsmall\", \"Gsmall\", \"Hsmall\", \"Ismall\", \"Jsmall\", \"Ksmall\", \"Lsmall\", \"Msmall\", \"Nsmall\", \"Osmall\", \"Psmall\", \"Qsmall\", \"Rsmall\", \"Ssmall\", \"Tsmall\", \"Usmall\", \"Vsmall\", \"Wsmall\", \"Xsmall\", \"Ysmall\", \"Zsmall\", \"colonmonetary\", \"onefitted\", \"rupiah\", \"Tildesmall\", \"exclamdownsmall\", \"centoldstyle\", \"Lslashsmall\", \"Scaronsmall\", \"Zcaronsmall\", \"Dieresissmall\", \"Brevesmall\", \"Caronsmall\", \"Dotaccentsmall\", \"Macronsmall\", \"figuredash\", \"hypheninferior\", \"Ogoneksmall\", \"Ringsmall\", \"Cedillasmall\", \"onequarter\", \"onehalf\", \"threequarters\", \"questiondownsmall\", \"oneeighth\", \"threeeighths\", \"fiveeighths\", \"seveneighths\", \"onethird\", \"twothirds\", \"zerosuperior\", \"onesuperior\", \"twosuperior\", \"threesuperior\", \"foursuperior\", \"fivesuperior\", \"sixsuperior\", \"sevensuperior\", \"eightsuperior\", \"ninesuperior\", \"zeroinferior\", \"oneinferior\", \"twoinferior\", \"threeinferior\", \"fourinferior\", \"fiveinferior\", \"sixinferior\", \"seveninferior\", \"eightinferior\", \"nineinferior\", \"centinferior\", \"dollarinferior\", \"periodinferior\", \"commainferior\", \"Agravesmall\", \"Aacutesmall\", \"Acircumflexsmall\", \"Atildesmall\", \"Adieresissmall\", \"Aringsmall\", \"AEsmall\", \"Ccedillasmall\", \"Egravesmall\", \"Eacutesmall\", \"Ecircumflexsmall\", \"Edieresissmall\", \"Igravesmall\", \"Iacutesmall\", \"Icircumflexsmall\", \"Idieresissmall\", \"Ethsmall\", \"Ntildesmall\", \"Ogravesmall\", \"Oacutesmall\", \"Ocircumflexsmall\", \"Otildesmall\", \"Odieresissmall\", \"OEsmall\", \"Oslashsmall\", \"Ugravesmall\", \"Uacutesmall\", \"Ucircumflexsmall\", \"Udieresissmall\", \"Yacutesmall\", \"Thornsmall\", \"Ydieresissmall\"];\nconst ExpertSubsetCharset = [\".notdef\", \"space\", \"dollaroldstyle\", \"dollarsuperior\", \"parenleftsuperior\", \"parenrightsuperior\", \"twodotenleader\", \"onedotenleader\", \"comma\", \"hyphen\", \"period\", \"fraction\", \"zerooldstyle\", \"oneoldstyle\", \"twooldstyle\", \"threeoldstyle\", \"fouroldstyle\", \"fiveoldstyle\", \"sixoldstyle\", \"sevenoldstyle\", \"eightoldstyle\", \"nineoldstyle\", \"colon\", \"semicolon\", \"commasuperior\", \"threequartersemdash\", \"periodsuperior\", \"asuperior\", \"bsuperior\", \"centsuperior\", \"dsuperior\", \"esuperior\", \"isuperior\", \"lsuperior\", \"msuperior\", \"nsuperior\", \"osuperior\", \"rsuperior\", \"ssuperior\", \"tsuperior\", \"ff\", \"fi\", \"fl\", \"ffi\", \"ffl\", \"parenleftinferior\", \"parenrightinferior\", \"hyphensuperior\", \"colonmonetary\", \"onefitted\", \"rupiah\", \"centoldstyle\", \"figuredash\", \"hypheninferior\", \"onequarter\", \"onehalf\", \"threequarters\", \"oneeighth\", \"threeeighths\", \"fiveeighths\", \"seveneighths\", \"onethird\", \"twothirds\", \"zerosuperior\", \"onesuperior\", \"twosuperior\", \"threesuperior\", \"foursuperior\", \"fivesuperior\", \"sixsuperior\", \"sevensuperior\", \"eightsuperior\", \"ninesuperior\", \"zeroinferior\", \"oneinferior\", \"twoinferior\", \"threeinferior\", \"fourinferior\", \"fiveinferior\", \"sixinferior\", \"seveninferior\", \"eightinferior\", \"nineinferior\", \"centinferior\", \"dollarinferior\", \"periodinferior\", \"commainferior\"];\n\n;// CONCATENATED MODULE: ./src/core/encodings.js\nconst ExpertEncoding = [\"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"space\", \"exclamsmall\", \"Hungarumlautsmall\", \"\", \"dollaroldstyle\", \"dollarsuperior\", \"ampersandsmall\", \"Acutesmall\", \"parenleftsuperior\", \"parenrightsuperior\", \"twodotenleader\", \"onedotenleader\", \"comma\", \"hyphen\", \"period\", \"fraction\", \"zerooldstyle\", \"oneoldstyle\", \"twooldstyle\", \"threeoldstyle\", \"fouroldstyle\", \"fiveoldstyle\", \"sixoldstyle\", \"sevenoldstyle\", \"eightoldstyle\", \"nineoldstyle\", \"colon\", \"semicolon\", \"commasuperior\", \"threequartersemdash\", \"periodsuperior\", \"questionsmall\", \"\", \"asuperior\", \"bsuperior\", \"centsuperior\", \"dsuperior\", \"esuperior\", \"\", \"\", \"\", \"isuperior\", \"\", \"\", \"lsuperior\", \"msuperior\", \"nsuperior\", \"osuperior\", \"\", \"\", \"rsuperior\", \"ssuperior\", \"tsuperior\", \"\", \"ff\", \"fi\", \"fl\", \"ffi\", \"ffl\", \"parenleftinferior\", \"\", \"parenrightinferior\", \"Circumflexsmall\", \"hyphensuperior\", \"Gravesmall\", \"Asmall\", \"Bsmall\", \"Csmall\", \"Dsmall\", \"Esmall\", \"Fsmall\", \"Gsmall\", \"Hsmall\", \"Ismall\", \"Jsmall\", \"Ksmall\", \"Lsmall\", \"Msmall\", \"Nsmall\", \"Osmall\", \"Psmall\", \"Qsmall\", \"Rsmall\", \"Ssmall\", \"Tsmall\", \"Usmall\", \"Vsmall\", \"Wsmall\", \"Xsmall\", \"Ysmall\", \"Zsmall\", \"colonmonetary\", \"onefitted\", \"rupiah\", \"Tildesmall\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"exclamdownsmall\", \"centoldstyle\", \"Lslashsmall\", \"\", \"\", \"Scaronsmall\", \"Zcaronsmall\", \"Dieresissmall\", \"Brevesmall\", \"Caronsmall\", \"\", \"Dotaccentsmall\", \"\", \"\", \"Macronsmall\", \"\", \"\", \"figuredash\", \"hypheninferior\", \"\", \"\", \"Ogoneksmall\", \"Ringsmall\", \"Cedillasmall\", \"\", \"\", \"\", \"onequarter\", \"onehalf\", \"threequarters\", \"questiondownsmall\", \"oneeighth\", \"threeeighths\", \"fiveeighths\", \"seveneighths\", \"onethird\", \"twothirds\", \"\", \"\", \"zerosuperior\", \"onesuperior\", \"twosuperior\", \"threesuperior\", \"foursuperior\", \"fivesuperior\", \"sixsuperior\", \"sevensuperior\", \"eightsuperior\", \"ninesuperior\", \"zeroinferior\", \"oneinferior\", \"twoinferior\", \"threeinferior\", \"fourinferior\", \"fiveinferior\", \"sixinferior\", \"seveninferior\", \"eightinferior\", \"nineinferior\", \"centinferior\", \"dollarinferior\", \"periodinferior\", \"commainferior\", \"Agravesmall\", \"Aacutesmall\", \"Acircumflexsmall\", \"Atildesmall\", \"Adieresissmall\", \"Aringsmall\", \"AEsmall\", \"Ccedillasmall\", \"Egravesmall\", \"Eacutesmall\", \"Ecircumflexsmall\", \"Edieresissmall\", \"Igravesmall\", \"Iacutesmall\", \"Icircumflexsmall\", \"Idieresissmall\", \"Ethsmall\", \"Ntildesmall\", \"Ogravesmall\", \"Oacutesmall\", \"Ocircumflexsmall\", \"Otildesmall\", \"Odieresissmall\", \"OEsmall\", \"Oslashsmall\", \"Ugravesmall\", \"Uacutesmall\", \"Ucircumflexsmall\", \"Udieresissmall\", \"Yacutesmall\", \"Thornsmall\", \"Ydieresissmall\"];\nconst MacExpertEncoding = [\"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"space\", \"exclamsmall\", \"Hungarumlautsmall\", \"centoldstyle\", \"dollaroldstyle\", \"dollarsuperior\", \"ampersandsmall\", \"Acutesmall\", \"parenleftsuperior\", \"parenrightsuperior\", \"twodotenleader\", \"onedotenleader\", \"comma\", \"hyphen\", \"period\", \"fraction\", \"zerooldstyle\", \"oneoldstyle\", \"twooldstyle\", \"threeoldstyle\", \"fouroldstyle\", \"fiveoldstyle\", \"sixoldstyle\", \"sevenoldstyle\", \"eightoldstyle\", \"nineoldstyle\", \"colon\", \"semicolon\", \"\", \"threequartersemdash\", \"\", \"questionsmall\", \"\", \"\", \"\", \"\", \"Ethsmall\", \"\", \"\", \"onequarter\", \"onehalf\", \"threequarters\", \"oneeighth\", \"threeeighths\", \"fiveeighths\", \"seveneighths\", \"onethird\", \"twothirds\", \"\", \"\", \"\", \"\", \"\", \"\", \"ff\", \"fi\", \"fl\", \"ffi\", \"ffl\", \"parenleftinferior\", \"\", \"parenrightinferior\", \"Circumflexsmall\", \"hypheninferior\", \"Gravesmall\", \"Asmall\", \"Bsmall\", \"Csmall\", \"Dsmall\", \"Esmall\", \"Fsmall\", \"Gsmall\", \"Hsmall\", \"Ismall\", \"Jsmall\", \"Ksmall\", \"Lsmall\", \"Msmall\", \"Nsmall\", \"Osmall\", \"Psmall\", \"Qsmall\", \"Rsmall\", \"Ssmall\", \"Tsmall\", \"Usmall\", \"Vsmall\", \"Wsmall\", \"Xsmall\", \"Ysmall\", \"Zsmall\", \"colonmonetary\", \"onefitted\", \"rupiah\", \"Tildesmall\", \"\", \"\", \"asuperior\", \"centsuperior\", \"\", \"\", \"\", \"\", \"Aacutesmall\", \"Agravesmall\", \"Acircumflexsmall\", \"Adieresissmall\", \"Atildesmall\", \"Aringsmall\", \"Ccedillasmall\", \"Eacutesmall\", \"Egravesmall\", \"Ecircumflexsmall\", \"Edieresissmall\", \"Iacutesmall\", \"Igravesmall\", \"Icircumflexsmall\", \"Idieresissmall\", \"Ntildesmall\", \"Oacutesmall\", \"Ogravesmall\", \"Ocircumflexsmall\", \"Odieresissmall\", \"Otildesmall\", \"Uacutesmall\", \"Ugravesmall\", \"Ucircumflexsmall\", \"Udieresissmall\", \"\", \"eightsuperior\", \"fourinferior\", \"threeinferior\", \"sixinferior\", \"eightinferior\", \"seveninferior\", \"Scaronsmall\", \"\", \"centinferior\", \"twoinferior\", \"\", \"Dieresissmall\", \"\", \"Caronsmall\", \"osuperior\", \"fiveinferior\", \"\", \"commainferior\", \"periodinferior\", \"Yacutesmall\", \"\", \"dollarinferior\", \"\", \"\", \"Thornsmall\", \"\", \"nineinferior\", \"zeroinferior\", \"Zcaronsmall\", \"AEsmall\", \"Oslashsmall\", \"questiondownsmall\", \"oneinferior\", \"Lslashsmall\", \"\", \"\", \"\", \"\", \"\", \"\", \"Cedillasmall\", \"\", \"\", \"\", \"\", \"\", \"OEsmall\", \"figuredash\", \"hyphensuperior\", \"\", \"\", \"\", \"\", \"exclamdownsmall\", \"\", \"Ydieresissmall\", \"\", \"onesuperior\", \"twosuperior\", \"threesuperior\", \"foursuperior\", \"fivesuperior\", \"sixsuperior\", \"sevensuperior\", \"ninesuperior\", \"zerosuperior\", \"\", \"esuperior\", \"rsuperior\", \"tsuperior\", \"\", \"\", \"isuperior\", \"ssuperior\", \"dsuperior\", \"\", \"\", \"\", \"\", \"\", \"lsuperior\", \"Ogoneksmall\", \"Brevesmall\", \"Macronsmall\", \"bsuperior\", \"nsuperior\", \"msuperior\", \"commasuperior\", \"periodsuperior\", \"Dotaccentsmall\", \"Ringsmall\", \"\", \"\", \"\", \"\"];\nconst MacRomanEncoding = [\"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"space\", \"exclam\", \"quotedbl\", \"numbersign\", \"dollar\", \"percent\", \"ampersand\", \"quotesingle\", \"parenleft\", \"parenright\", \"asterisk\", \"plus\", \"comma\", \"hyphen\", \"period\", \"slash\", \"zero\", \"one\", \"two\", \"three\", \"four\", \"five\", \"six\", \"seven\", \"eight\", \"nine\", \"colon\", \"semicolon\", \"less\", \"equal\", \"greater\", \"question\", \"at\", \"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\", \"I\", \"J\", \"K\", \"L\", \"M\", \"N\", \"O\", \"P\", \"Q\", \"R\", \"S\", \"T\", \"U\", \"V\", \"W\", \"X\", \"Y\", \"Z\", \"bracketleft\", \"backslash\", \"bracketright\", \"asciicircum\", \"underscore\", \"grave\", \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\", \"k\", \"l\", \"m\", \"n\", \"o\", \"p\", \"q\", \"r\", \"s\", \"t\", \"u\", \"v\", \"w\", \"x\", \"y\", \"z\", \"braceleft\", \"bar\", \"braceright\", \"asciitilde\", \"\", \"Adieresis\", \"Aring\", \"Ccedilla\", \"Eacute\", \"Ntilde\", \"Odieresis\", \"Udieresis\", \"aacute\", \"agrave\", \"acircumflex\", \"adieresis\", \"atilde\", \"aring\", \"ccedilla\", \"eacute\", \"egrave\", \"ecircumflex\", \"edieresis\", \"iacute\", \"igrave\", \"icircumflex\", \"idieresis\", \"ntilde\", \"oacute\", \"ograve\", \"ocircumflex\", \"odieresis\", \"otilde\", \"uacute\", \"ugrave\", \"ucircumflex\", \"udieresis\", \"dagger\", \"degree\", \"cent\", \"sterling\", \"section\", \"bullet\", \"paragraph\", \"germandbls\", \"registered\", \"copyright\", \"trademark\", \"acute\", \"dieresis\", \"notequal\", \"AE\", \"Oslash\", \"infinity\", \"plusminus\", \"lessequal\", \"greaterequal\", \"yen\", \"mu\", \"partialdiff\", \"summation\", \"product\", \"pi\", \"integral\", \"ordfeminine\", \"ordmasculine\", \"Omega\", \"ae\", \"oslash\", \"questiondown\", \"exclamdown\", \"logicalnot\", \"radical\", \"florin\", \"approxequal\", \"Delta\", \"guillemotleft\", \"guillemotright\", \"ellipsis\", \"space\", \"Agrave\", \"Atilde\", \"Otilde\", \"OE\", \"oe\", \"endash\", \"emdash\", \"quotedblleft\", \"quotedblright\", \"quoteleft\", \"quoteright\", \"divide\", \"lozenge\", \"ydieresis\", \"Ydieresis\", \"fraction\", \"currency\", \"guilsinglleft\", \"guilsinglright\", \"fi\", \"fl\", \"daggerdbl\", \"periodcentered\", \"quotesinglbase\", \"quotedblbase\", \"perthousand\", \"Acircumflex\", \"Ecircumflex\", \"Aacute\", \"Edieresis\", \"Egrave\", \"Iacute\", \"Icircumflex\", \"Idieresis\", \"Igrave\", \"Oacute\", \"Ocircumflex\", \"apple\", \"Ograve\", \"Uacute\", \"Ucircumflex\", \"Ugrave\", \"dotlessi\", \"circumflex\", \"tilde\", \"macron\", \"breve\", \"dotaccent\", \"ring\", \"cedilla\", \"hungarumlaut\", \"ogonek\", \"caron\"];\nconst StandardEncoding = [\"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"space\", \"exclam\", \"quotedbl\", \"numbersign\", \"dollar\", \"percent\", \"ampersand\", \"quoteright\", \"parenleft\", \"parenright\", \"asterisk\", \"plus\", \"comma\", \"hyphen\", \"period\", \"slash\", \"zero\", \"one\", \"two\", \"three\", \"four\", \"five\", \"six\", \"seven\", \"eight\", \"nine\", \"colon\", \"semicolon\", \"less\", \"equal\", \"greater\", \"question\", \"at\", \"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\", \"I\", \"J\", \"K\", \"L\", \"M\", \"N\", \"O\", \"P\", \"Q\", \"R\", \"S\", \"T\", \"U\", \"V\", \"W\", \"X\", \"Y\", \"Z\", \"bracketleft\", \"backslash\", \"bracketright\", \"asciicircum\", \"underscore\", \"quoteleft\", \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\", \"k\", \"l\", \"m\", \"n\", \"o\", \"p\", \"q\", \"r\", \"s\", \"t\", \"u\", \"v\", \"w\", \"x\", \"y\", \"z\", \"braceleft\", \"bar\", \"braceright\", \"asciitilde\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"exclamdown\", \"cent\", \"sterling\", \"fraction\", \"yen\", \"florin\", \"section\", \"currency\", \"quotesingle\", \"quotedblleft\", \"guillemotleft\", \"guilsinglleft\", \"guilsinglright\", \"fi\", \"fl\", \"\", \"endash\", \"dagger\", \"daggerdbl\", \"periodcentered\", \"\", \"paragraph\", \"bullet\", \"quotesinglbase\", \"quotedblbase\", \"quotedblright\", \"guillemotright\", \"ellipsis\", \"perthousand\", \"\", \"questiondown\", \"\", \"grave\", \"acute\", \"circumflex\", \"tilde\", \"macron\", \"breve\", \"dotaccent\", \"dieresis\", \"\", \"ring\", \"cedilla\", \"\", \"hungarumlaut\", \"ogonek\", \"caron\", \"emdash\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"AE\", \"\", \"ordfeminine\", \"\", \"\", \"\", \"\", \"Lslash\", \"Oslash\", \"OE\", \"ordmasculine\", \"\", \"\", \"\", \"\", \"\", \"ae\", \"\", \"\", \"\", \"dotlessi\", \"\", \"\", \"lslash\", \"oslash\", \"oe\", \"germandbls\", \"\", \"\", \"\", \"\"];\nconst WinAnsiEncoding = [\"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"space\", \"exclam\", \"quotedbl\", \"numbersign\", \"dollar\", \"percent\", \"ampersand\", \"quotesingle\", \"parenleft\", \"parenright\", \"asterisk\", \"plus\", \"comma\", \"hyphen\", \"period\", \"slash\", \"zero\", \"one\", \"two\", \"three\", \"four\", \"five\", \"six\", \"seven\", \"eight\", \"nine\", \"colon\", \"semicolon\", \"less\", \"equal\", \"greater\", \"question\", \"at\", \"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\", \"I\", \"J\", \"K\", \"L\", \"M\", \"N\", \"O\", \"P\", \"Q\", \"R\", \"S\", \"T\", \"U\", \"V\", \"W\", \"X\", \"Y\", \"Z\", \"bracketleft\", \"backslash\", \"bracketright\", \"asciicircum\", \"underscore\", \"grave\", \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\", \"k\", \"l\", \"m\", \"n\", \"o\", \"p\", \"q\", \"r\", \"s\", \"t\", \"u\", \"v\", \"w\", \"x\", \"y\", \"z\", \"braceleft\", \"bar\", \"braceright\", \"asciitilde\", \"bullet\", \"Euro\", \"bullet\", \"quotesinglbase\", \"florin\", \"quotedblbase\", \"ellipsis\", \"dagger\", \"daggerdbl\", \"circumflex\", \"perthousand\", \"Scaron\", \"guilsinglleft\", \"OE\", \"bullet\", \"Zcaron\", \"bullet\", \"bullet\", \"quoteleft\", \"quoteright\", \"quotedblleft\", \"quotedblright\", \"bullet\", \"endash\", \"emdash\", \"tilde\", \"trademark\", \"scaron\", \"guilsinglright\", \"oe\", \"bullet\", \"zcaron\", \"Ydieresis\", \"space\", \"exclamdown\", \"cent\", \"sterling\", \"currency\", \"yen\", \"brokenbar\", \"section\", \"dieresis\", \"copyright\", \"ordfeminine\", \"guillemotleft\", \"logicalnot\", \"hyphen\", \"registered\", \"macron\", \"degree\", \"plusminus\", \"twosuperior\", \"threesuperior\", \"acute\", \"mu\", \"paragraph\", \"periodcentered\", \"cedilla\", \"onesuperior\", \"ordmasculine\", \"guillemotright\", \"onequarter\", \"onehalf\", \"threequarters\", \"questiondown\", \"Agrave\", \"Aacute\", \"Acircumflex\", \"Atilde\", \"Adieresis\", \"Aring\", \"AE\", \"Ccedilla\", \"Egrave\", \"Eacute\", \"Ecircumflex\", \"Edieresis\", \"Igrave\", \"Iacute\", \"Icircumflex\", \"Idieresis\", \"Eth\", \"Ntilde\", \"Ograve\", \"Oacute\", \"Ocircumflex\", \"Otilde\", \"Odieresis\", \"multiply\", \"Oslash\", \"Ugrave\", \"Uacute\", \"Ucircumflex\", \"Udieresis\", \"Yacute\", \"Thorn\", \"germandbls\", \"agrave\", \"aacute\", \"acircumflex\", \"atilde\", \"adieresis\", \"aring\", \"ae\", \"ccedilla\", \"egrave\", \"eacute\", \"ecircumflex\", \"edieresis\", \"igrave\", \"iacute\", \"icircumflex\", \"idieresis\", \"eth\", \"ntilde\", \"ograve\", \"oacute\", \"ocircumflex\", \"otilde\", \"odieresis\", \"divide\", \"oslash\", \"ugrave\", \"uacute\", \"ucircumflex\", \"udieresis\", \"yacute\", \"thorn\", \"ydieresis\"];\nconst SymbolSetEncoding = [\"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"space\", \"exclam\", \"universal\", \"numbersign\", \"existential\", \"percent\", \"ampersand\", \"suchthat\", \"parenleft\", \"parenright\", \"asteriskmath\", \"plus\", \"comma\", \"minus\", \"period\", \"slash\", \"zero\", \"one\", \"two\", \"three\", \"four\", \"five\", \"six\", \"seven\", \"eight\", \"nine\", \"colon\", \"semicolon\", \"less\", \"equal\", \"greater\", \"question\", \"congruent\", \"Alpha\", \"Beta\", \"Chi\", \"Delta\", \"Epsilon\", \"Phi\", \"Gamma\", \"Eta\", \"Iota\", \"theta1\", \"Kappa\", \"Lambda\", \"Mu\", \"Nu\", \"Omicron\", \"Pi\", \"Theta\", \"Rho\", \"Sigma\", \"Tau\", \"Upsilon\", \"sigma1\", \"Omega\", \"Xi\", \"Psi\", \"Zeta\", \"bracketleft\", \"therefore\", \"bracketright\", \"perpendicular\", \"underscore\", \"radicalex\", \"alpha\", \"beta\", \"chi\", \"delta\", \"epsilon\", \"phi\", \"gamma\", \"eta\", \"iota\", \"phi1\", \"kappa\", \"lambda\", \"mu\", \"nu\", \"omicron\", \"pi\", \"theta\", \"rho\", \"sigma\", \"tau\", \"upsilon\", \"omega1\", \"omega\", \"xi\", \"psi\", \"zeta\", \"braceleft\", \"bar\", \"braceright\", \"similar\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"Euro\", \"Upsilon1\", \"minute\", \"lessequal\", \"fraction\", \"infinity\", \"florin\", \"club\", \"diamond\", \"heart\", \"spade\", \"arrowboth\", \"arrowleft\", \"arrowup\", \"arrowright\", \"arrowdown\", \"degree\", \"plusminus\", \"second\", \"greaterequal\", \"multiply\", \"proportional\", \"partialdiff\", \"bullet\", \"divide\", \"notequal\", \"equivalence\", \"approxequal\", \"ellipsis\", \"arrowvertex\", \"arrowhorizex\", \"carriagereturn\", \"aleph\", \"Ifraktur\", \"Rfraktur\", \"weierstrass\", \"circlemultiply\", \"circleplus\", \"emptyset\", \"intersection\", \"union\", \"propersuperset\", \"reflexsuperset\", \"notsubset\", \"propersubset\", \"reflexsubset\", \"element\", \"notelement\", \"angle\", \"gradient\", \"registerserif\", \"copyrightserif\", \"trademarkserif\", \"product\", \"radical\", \"dotmath\", \"logicalnot\", \"logicaland\", \"logicalor\", \"arrowdblboth\", \"arrowdblleft\", \"arrowdblup\", \"arrowdblright\", \"arrowdbldown\", \"lozenge\", \"angleleft\", \"registersans\", \"copyrightsans\", \"trademarksans\", \"summation\", \"parenlefttp\", \"parenleftex\", \"parenleftbt\", \"bracketlefttp\", \"bracketleftex\", \"bracketleftbt\", \"bracelefttp\", \"braceleftmid\", \"braceleftbt\", \"braceex\", \"\", \"angleright\", \"integral\", \"integraltp\", \"integralex\", \"integralbt\", \"parenrighttp\", \"parenrightex\", \"parenrightbt\", \"bracketrighttp\", \"bracketrightex\", \"bracketrightbt\", \"bracerighttp\", \"bracerightmid\", \"bracerightbt\", \"\"];\nconst ZapfDingbatsEncoding = [\"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"space\", \"a1\", \"a2\", \"a202\", \"a3\", \"a4\", \"a5\", \"a119\", \"a118\", \"a117\", \"a11\", \"a12\", \"a13\", \"a14\", \"a15\", \"a16\", \"a105\", \"a17\", \"a18\", \"a19\", \"a20\", \"a21\", \"a22\", \"a23\", \"a24\", \"a25\", \"a26\", \"a27\", \"a28\", \"a6\", \"a7\", \"a8\", \"a9\", \"a10\", \"a29\", \"a30\", \"a31\", \"a32\", \"a33\", \"a34\", \"a35\", \"a36\", \"a37\", \"a38\", \"a39\", \"a40\", \"a41\", \"a42\", \"a43\", \"a44\", \"a45\", \"a46\", \"a47\", \"a48\", \"a49\", \"a50\", \"a51\", \"a52\", \"a53\", \"a54\", \"a55\", \"a56\", \"a57\", \"a58\", \"a59\", \"a60\", \"a61\", \"a62\", \"a63\", \"a64\", \"a65\", \"a66\", \"a67\", \"a68\", \"a69\", \"a70\", \"a71\", \"a72\", \"a73\", \"a74\", \"a203\", \"a75\", \"a204\", \"a76\", \"a77\", \"a78\", \"a79\", \"a81\", \"a82\", \"a83\", \"a84\", \"a97\", \"a98\", \"a99\", \"a100\", \"\", \"a89\", \"a90\", \"a93\", \"a94\", \"a91\", \"a92\", \"a205\", \"a85\", \"a206\", \"a86\", \"a87\", \"a88\", \"a95\", \"a96\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"a101\", \"a102\", \"a103\", \"a104\", \"a106\", \"a107\", \"a108\", \"a112\", \"a111\", \"a110\", \"a109\", \"a120\", \"a121\", \"a122\", \"a123\", \"a124\", \"a125\", \"a126\", \"a127\", \"a128\", \"a129\", \"a130\", \"a131\", \"a132\", \"a133\", \"a134\", \"a135\", \"a136\", \"a137\", \"a138\", \"a139\", \"a140\", \"a141\", \"a142\", \"a143\", \"a144\", \"a145\", \"a146\", \"a147\", \"a148\", \"a149\", \"a150\", \"a151\", \"a152\", \"a153\", \"a154\", \"a155\", \"a156\", \"a157\", \"a158\", \"a159\", \"a160\", \"a161\", \"a163\", \"a164\", \"a196\", \"a165\", \"a192\", \"a166\", \"a167\", \"a168\", \"a169\", \"a170\", \"a171\", \"a172\", \"a173\", \"a162\", \"a174\", \"a175\", \"a176\", \"a177\", \"a178\", \"a179\", \"a193\", \"a180\", \"a199\", \"a181\", \"a200\", \"a182\", \"\", \"a201\", \"a183\", \"a184\", \"a197\", \"a185\", \"a194\", \"a198\", \"a186\", \"a195\", \"a187\", \"a188\", \"a189\", \"a190\", \"a191\", \"\"];\nfunction getEncoding(encodingName) {\n  switch (encodingName) {\n    case \"WinAnsiEncoding\":\n      return WinAnsiEncoding;\n    case \"StandardEncoding\":\n      return StandardEncoding;\n    case \"MacRomanEncoding\":\n      return MacRomanEncoding;\n    case \"SymbolSetEncoding\":\n      return SymbolSetEncoding;\n    case \"ZapfDingbatsEncoding\":\n      return ZapfDingbatsEncoding;\n    case \"ExpertEncoding\":\n      return ExpertEncoding;\n    case \"MacExpertEncoding\":\n      return MacExpertEncoding;\n    default:\n      return null;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/cff_parser.js\n\n\n\nconst MAX_SUBR_NESTING = 10;\nconst CFFStandardStrings = [\".notdef\", \"space\", \"exclam\", \"quotedbl\", \"numbersign\", \"dollar\", \"percent\", \"ampersand\", \"quoteright\", \"parenleft\", \"parenright\", \"asterisk\", \"plus\", \"comma\", \"hyphen\", \"period\", \"slash\", \"zero\", \"one\", \"two\", \"three\", \"four\", \"five\", \"six\", \"seven\", \"eight\", \"nine\", \"colon\", \"semicolon\", \"less\", \"equal\", \"greater\", \"question\", \"at\", \"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\", \"I\", \"J\", \"K\", \"L\", \"M\", \"N\", \"O\", \"P\", \"Q\", \"R\", \"S\", \"T\", \"U\", \"V\", \"W\", \"X\", \"Y\", \"Z\", \"bracketleft\", \"backslash\", \"bracketright\", \"asciicircum\", \"underscore\", \"quoteleft\", \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\", \"k\", \"l\", \"m\", \"n\", \"o\", \"p\", \"q\", \"r\", \"s\", \"t\", \"u\", \"v\", \"w\", \"x\", \"y\", \"z\", \"braceleft\", \"bar\", \"braceright\", \"asciitilde\", \"exclamdown\", \"cent\", \"sterling\", \"fraction\", \"yen\", \"florin\", \"section\", \"currency\", \"quotesingle\", \"quotedblleft\", \"guillemotleft\", \"guilsinglleft\", \"guilsinglright\", \"fi\", \"fl\", \"endash\", \"dagger\", \"daggerdbl\", \"periodcentered\", \"paragraph\", \"bullet\", \"quotesinglbase\", \"quotedblbase\", \"quotedblright\", \"guillemotright\", \"ellipsis\", \"perthousand\", \"questiondown\", \"grave\", \"acute\", \"circumflex\", \"tilde\", \"macron\", \"breve\", \"dotaccent\", \"dieresis\", \"ring\", \"cedilla\", \"hungarumlaut\", \"ogonek\", \"caron\", \"emdash\", \"AE\", \"ordfeminine\", \"Lslash\", \"Oslash\", \"OE\", \"ordmasculine\", \"ae\", \"dotlessi\", \"lslash\", \"oslash\", \"oe\", \"germandbls\", \"onesuperior\", \"logicalnot\", \"mu\", \"trademark\", \"Eth\", \"onehalf\", \"plusminus\", \"Thorn\", \"onequarter\", \"divide\", \"brokenbar\", \"degree\", \"thorn\", \"threequarters\", \"twosuperior\", \"registered\", \"minus\", \"eth\", \"multiply\", \"threesuperior\", \"copyright\", \"Aacute\", \"Acircumflex\", \"Adieresis\", \"Agrave\", \"Aring\", \"Atilde\", \"Ccedilla\", \"Eacute\", \"Ecircumflex\", \"Edieresis\", \"Egrave\", \"Iacute\", \"Icircumflex\", \"Idieresis\", \"Igrave\", \"Ntilde\", \"Oacute\", \"Ocircumflex\", \"Odieresis\", \"Ograve\", \"Otilde\", \"Scaron\", \"Uacute\", \"Ucircumflex\", \"Udieresis\", \"Ugrave\", \"Yacute\", \"Ydieresis\", \"Zcaron\", \"aacute\", \"acircumflex\", \"adieresis\", \"agrave\", \"aring\", \"atilde\", \"ccedilla\", \"eacute\", \"ecircumflex\", \"edieresis\", \"egrave\", \"iacute\", \"icircumflex\", \"idieresis\", \"igrave\", \"ntilde\", \"oacute\", \"ocircumflex\", \"odieresis\", \"ograve\", \"otilde\", \"scaron\", \"uacute\", \"ucircumflex\", \"udieresis\", \"ugrave\", \"yacute\", \"ydieresis\", \"zcaron\", \"exclamsmall\", \"Hungarumlautsmall\", \"dollaroldstyle\", \"dollarsuperior\", \"ampersandsmall\", \"Acutesmall\", \"parenleftsuperior\", \"parenrightsuperior\", \"twodotenleader\", \"onedotenleader\", \"zerooldstyle\", \"oneoldstyle\", \"twooldstyle\", \"threeoldstyle\", \"fouroldstyle\", \"fiveoldstyle\", \"sixoldstyle\", \"sevenoldstyle\", \"eightoldstyle\", \"nineoldstyle\", \"commasuperior\", \"threequartersemdash\", \"periodsuperior\", \"questionsmall\", \"asuperior\", \"bsuperior\", \"centsuperior\", \"dsuperior\", \"esuperior\", \"isuperior\", \"lsuperior\", \"msuperior\", \"nsuperior\", \"osuperior\", \"rsuperior\", \"ssuperior\", \"tsuperior\", \"ff\", \"ffi\", \"ffl\", \"parenleftinferior\", \"parenrightinferior\", \"Circumflexsmall\", \"hyphensuperior\", \"Gravesmall\", \"Asmall\", \"Bsmall\", \"Csmall\", \"Dsmall\", \"Esmall\", \"Fsmall\", \"Gsmall\", \"Hsmall\", \"Ismall\", \"Jsmall\", \"Ksmall\", \"Lsmall\", \"Msmall\", \"Nsmall\", \"Osmall\", \"Psmall\", \"Qsmall\", \"Rsmall\", \"Ssmall\", \"Tsmall\", \"Usmall\", \"Vsmall\", \"Wsmall\", \"Xsmall\", \"Ysmall\", \"Zsmall\", \"colonmonetary\", \"onefitted\", \"rupiah\", \"Tildesmall\", \"exclamdownsmall\", \"centoldstyle\", \"Lslashsmall\", \"Scaronsmall\", \"Zcaronsmall\", \"Dieresissmall\", \"Brevesmall\", \"Caronsmall\", \"Dotaccentsmall\", \"Macronsmall\", \"figuredash\", \"hypheninferior\", \"Ogoneksmall\", \"Ringsmall\", \"Cedillasmall\", \"questiondownsmall\", \"oneeighth\", \"threeeighths\", \"fiveeighths\", \"seveneighths\", \"onethird\", \"twothirds\", \"zerosuperior\", \"foursuperior\", \"fivesuperior\", \"sixsuperior\", \"sevensuperior\", \"eightsuperior\", \"ninesuperior\", \"zeroinferior\", \"oneinferior\", \"twoinferior\", \"threeinferior\", \"fourinferior\", \"fiveinferior\", \"sixinferior\", \"seveninferior\", \"eightinferior\", \"nineinferior\", \"centinferior\", \"dollarinferior\", \"periodinferior\", \"commainferior\", \"Agravesmall\", \"Aacutesmall\", \"Acircumflexsmall\", \"Atildesmall\", \"Adieresissmall\", \"Aringsmall\", \"AEsmall\", \"Ccedillasmall\", \"Egravesmall\", \"Eacutesmall\", \"Ecircumflexsmall\", \"Edieresissmall\", \"Igravesmall\", \"Iacutesmall\", \"Icircumflexsmall\", \"Idieresissmall\", \"Ethsmall\", \"Ntildesmall\", \"Ogravesmall\", \"Oacutesmall\", \"Ocircumflexsmall\", \"Otildesmall\", \"Odieresissmall\", \"OEsmall\", \"Oslashsmall\", \"Ugravesmall\", \"Uacutesmall\", \"Ucircumflexsmall\", \"Udieresissmall\", \"Yacutesmall\", \"Thornsmall\", \"Ydieresissmall\", \"001.000\", \"001.001\", \"001.002\", \"001.003\", \"Black\", \"Bold\", \"Book\", \"Light\", \"Medium\", \"Regular\", \"Roman\", \"Semibold\"];\nconst NUM_STANDARD_CFF_STRINGS = 391;\nconst CharstringValidationData = [null, {\n  id: \"hstem\",\n  min: 2,\n  stackClearing: true,\n  stem: true\n}, null, {\n  id: \"vstem\",\n  min: 2,\n  stackClearing: true,\n  stem: true\n}, {\n  id: \"vmoveto\",\n  min: 1,\n  stackClearing: true\n}, {\n  id: \"rlineto\",\n  min: 2,\n  resetStack: true\n}, {\n  id: \"hlineto\",\n  min: 1,\n  resetStack: true\n}, {\n  id: \"vlineto\",\n  min: 1,\n  resetStack: true\n}, {\n  id: \"rrcurveto\",\n  min: 6,\n  resetStack: true\n}, null, {\n  id: \"callsubr\",\n  min: 1,\n  undefStack: true\n}, {\n  id: \"return\",\n  min: 0,\n  undefStack: true\n}, null, null, {\n  id: \"endchar\",\n  min: 0,\n  stackClearing: true\n}, null, null, null, {\n  id: \"hstemhm\",\n  min: 2,\n  stackClearing: true,\n  stem: true\n}, {\n  id: \"hintmask\",\n  min: 0,\n  stackClearing: true\n}, {\n  id: \"cntrmask\",\n  min: 0,\n  stackClearing: true\n}, {\n  id: \"rmoveto\",\n  min: 2,\n  stackClearing: true\n}, {\n  id: \"hmoveto\",\n  min: 1,\n  stackClearing: true\n}, {\n  id: \"vstemhm\",\n  min: 2,\n  stackClearing: true,\n  stem: true\n}, {\n  id: \"rcurveline\",\n  min: 8,\n  resetStack: true\n}, {\n  id: \"rlinecurve\",\n  min: 8,\n  resetStack: true\n}, {\n  id: \"vvcurveto\",\n  min: 4,\n  resetStack: true\n}, {\n  id: \"hhcurveto\",\n  min: 4,\n  resetStack: true\n}, null, {\n  id: \"callgsubr\",\n  min: 1,\n  undefStack: true\n}, {\n  id: \"vhcurveto\",\n  min: 4,\n  resetStack: true\n}, {\n  id: \"hvcurveto\",\n  min: 4,\n  resetStack: true\n}];\nconst CharstringValidationData12 = [null, null, null, {\n  id: \"and\",\n  min: 2,\n  stackDelta: -1\n}, {\n  id: \"or\",\n  min: 2,\n  stackDelta: -1\n}, {\n  id: \"not\",\n  min: 1,\n  stackDelta: 0\n}, null, null, null, {\n  id: \"abs\",\n  min: 1,\n  stackDelta: 0\n}, {\n  id: \"add\",\n  min: 2,\n  stackDelta: -1,\n  stackFn(stack, index) {\n    stack[index - 2] = stack[index - 2] + stack[index - 1];\n  }\n}, {\n  id: \"sub\",\n  min: 2,\n  stackDelta: -1,\n  stackFn(stack, index) {\n    stack[index - 2] = stack[index - 2] - stack[index - 1];\n  }\n}, {\n  id: \"div\",\n  min: 2,\n  stackDelta: -1,\n  stackFn(stack, index) {\n    stack[index - 2] = stack[index - 2] / stack[index - 1];\n  }\n}, null, {\n  id: \"neg\",\n  min: 1,\n  stackDelta: 0,\n  stackFn(stack, index) {\n    stack[index - 1] = -stack[index - 1];\n  }\n}, {\n  id: \"eq\",\n  min: 2,\n  stackDelta: -1\n}, null, null, {\n  id: \"drop\",\n  min: 1,\n  stackDelta: -1\n}, null, {\n  id: \"put\",\n  min: 2,\n  stackDelta: -2\n}, {\n  id: \"get\",\n  min: 1,\n  stackDelta: 0\n}, {\n  id: \"ifelse\",\n  min: 4,\n  stackDelta: -3\n}, {\n  id: \"random\",\n  min: 0,\n  stackDelta: 1\n}, {\n  id: \"mul\",\n  min: 2,\n  stackDelta: -1,\n  stackFn(stack, index) {\n    stack[index - 2] = stack[index - 2] * stack[index - 1];\n  }\n}, null, {\n  id: \"sqrt\",\n  min: 1,\n  stackDelta: 0\n}, {\n  id: \"dup\",\n  min: 1,\n  stackDelta: 1\n}, {\n  id: \"exch\",\n  min: 2,\n  stackDelta: 0\n}, {\n  id: \"index\",\n  min: 2,\n  stackDelta: 0\n}, {\n  id: \"roll\",\n  min: 3,\n  stackDelta: -2\n}, null, null, null, {\n  id: \"hflex\",\n  min: 7,\n  resetStack: true\n}, {\n  id: \"flex\",\n  min: 13,\n  resetStack: true\n}, {\n  id: \"hflex1\",\n  min: 9,\n  resetStack: true\n}, {\n  id: \"flex1\",\n  min: 11,\n  resetStack: true\n}];\nclass CFFParser {\n  constructor(file, properties, seacAnalysisEnabled) {\n    this.bytes = file.getBytes();\n    this.properties = properties;\n    this.seacAnalysisEnabled = !!seacAnalysisEnabled;\n  }\n  parse() {\n    const properties = this.properties;\n    const cff = new CFF();\n    this.cff = cff;\n    const header = this.parseHeader();\n    const nameIndex = this.parseIndex(header.endPos);\n    const topDictIndex = this.parseIndex(nameIndex.endPos);\n    const stringIndex = this.parseIndex(topDictIndex.endPos);\n    const globalSubrIndex = this.parseIndex(stringIndex.endPos);\n    const topDictParsed = this.parseDict(topDictIndex.obj.get(0));\n    const topDict = this.createDict(CFFTopDict, topDictParsed, cff.strings);\n    cff.header = header.obj;\n    cff.names = this.parseNameIndex(nameIndex.obj);\n    cff.strings = this.parseStringIndex(stringIndex.obj);\n    cff.topDict = topDict;\n    cff.globalSubrIndex = globalSubrIndex.obj;\n    this.parsePrivateDict(cff.topDict);\n    cff.isCIDFont = topDict.hasName(\"ROS\");\n    const charStringOffset = topDict.getByName(\"CharStrings\");\n    const charStringIndex = this.parseIndex(charStringOffset).obj;\n    const fontMatrix = topDict.getByName(\"FontMatrix\");\n    if (fontMatrix) {\n      properties.fontMatrix = fontMatrix;\n    }\n    const fontBBox = topDict.getByName(\"FontBBox\");\n    if (fontBBox) {\n      properties.ascent = Math.max(fontBBox[3], fontBBox[1]);\n      properties.descent = Math.min(fontBBox[1], fontBBox[3]);\n      properties.ascentScaled = true;\n    }\n    let charset, encoding;\n    if (cff.isCIDFont) {\n      const fdArrayIndex = this.parseIndex(topDict.getByName(\"FDArray\")).obj;\n      for (let i = 0, ii = fdArrayIndex.count; i < ii; ++i) {\n        const dictRaw = fdArrayIndex.get(i);\n        const fontDict = this.createDict(CFFTopDict, this.parseDict(dictRaw), cff.strings);\n        this.parsePrivateDict(fontDict);\n        cff.fdArray.push(fontDict);\n      }\n      encoding = null;\n      charset = this.parseCharsets(topDict.getByName(\"charset\"), charStringIndex.count, cff.strings, true);\n      cff.fdSelect = this.parseFDSelect(topDict.getByName(\"FDSelect\"), charStringIndex.count);\n    } else {\n      charset = this.parseCharsets(topDict.getByName(\"charset\"), charStringIndex.count, cff.strings, false);\n      encoding = this.parseEncoding(topDict.getByName(\"Encoding\"), properties, cff.strings, charset.charset);\n    }\n    cff.charset = charset;\n    cff.encoding = encoding;\n    const charStringsAndSeacs = this.parseCharStrings({\n      charStrings: charStringIndex,\n      localSubrIndex: topDict.privateDict.subrsIndex,\n      globalSubrIndex: globalSubrIndex.obj,\n      fdSelect: cff.fdSelect,\n      fdArray: cff.fdArray,\n      privateDict: topDict.privateDict\n    });\n    cff.charStrings = charStringsAndSeacs.charStrings;\n    cff.seacs = charStringsAndSeacs.seacs;\n    cff.widths = charStringsAndSeacs.widths;\n    return cff;\n  }\n  parseHeader() {\n    let bytes = this.bytes;\n    const bytesLength = bytes.length;\n    let offset = 0;\n    while (offset < bytesLength && bytes[offset] !== 1) {\n      ++offset;\n    }\n    if (offset >= bytesLength) {\n      throw new FormatError(\"Invalid CFF header\");\n    }\n    if (offset !== 0) {\n      info(\"cff data is shifted\");\n      bytes = bytes.subarray(offset);\n      this.bytes = bytes;\n    }\n    const major = bytes[0];\n    const minor = bytes[1];\n    const hdrSize = bytes[2];\n    const offSize = bytes[3];\n    const header = new CFFHeader(major, minor, hdrSize, offSize);\n    return {\n      obj: header,\n      endPos: hdrSize\n    };\n  }\n  parseDict(dict) {\n    let pos = 0;\n    function parseOperand() {\n      let value = dict[pos++];\n      if (value === 30) {\n        return parseFloatOperand();\n      } else if (value === 28) {\n        value = dict[pos++];\n        value = (value << 24 | dict[pos++] << 16) >> 16;\n        return value;\n      } else if (value === 29) {\n        value = dict[pos++];\n        value = value << 8 | dict[pos++];\n        value = value << 8 | dict[pos++];\n        value = value << 8 | dict[pos++];\n        return value;\n      } else if (value >= 32 && value <= 246) {\n        return value - 139;\n      } else if (value >= 247 && value <= 250) {\n        return (value - 247) * 256 + dict[pos++] + 108;\n      } else if (value >= 251 && value <= 254) {\n        return -((value - 251) * 256) - dict[pos++] - 108;\n      }\n      warn('CFFParser_parseDict: \"' + value + '\" is a reserved command.');\n      return NaN;\n    }\n    function parseFloatOperand() {\n      let str = \"\";\n      const eof = 15;\n      const lookup = [\"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \".\", \"E\", \"E-\", null, \"-\"];\n      const length = dict.length;\n      while (pos < length) {\n        const b = dict[pos++];\n        const b1 = b >> 4;\n        const b2 = b & 15;\n        if (b1 === eof) {\n          break;\n        }\n        str += lookup[b1];\n        if (b2 === eof) {\n          break;\n        }\n        str += lookup[b2];\n      }\n      return parseFloat(str);\n    }\n    let operands = [];\n    const entries = [];\n    pos = 0;\n    const end = dict.length;\n    while (pos < end) {\n      let b = dict[pos];\n      if (b <= 21) {\n        if (b === 12) {\n          b = b << 8 | dict[++pos];\n        }\n        entries.push([b, operands]);\n        operands = [];\n        ++pos;\n      } else {\n        operands.push(parseOperand());\n      }\n    }\n    return entries;\n  }\n  parseIndex(pos) {\n    const cffIndex = new CFFIndex();\n    const bytes = this.bytes;\n    const count = bytes[pos++] << 8 | bytes[pos++];\n    const offsets = [];\n    let end = pos;\n    let i, ii;\n    if (count !== 0) {\n      const offsetSize = bytes[pos++];\n      const startPos = pos + (count + 1) * offsetSize - 1;\n      for (i = 0, ii = count + 1; i < ii; ++i) {\n        let offset = 0;\n        for (let j = 0; j < offsetSize; ++j) {\n          offset <<= 8;\n          offset += bytes[pos++];\n        }\n        offsets.push(startPos + offset);\n      }\n      end = offsets[count];\n    }\n    for (i = 0, ii = offsets.length - 1; i < ii; ++i) {\n      const offsetStart = offsets[i];\n      const offsetEnd = offsets[i + 1];\n      cffIndex.add(bytes.subarray(offsetStart, offsetEnd));\n    }\n    return {\n      obj: cffIndex,\n      endPos: end\n    };\n  }\n  parseNameIndex(index) {\n    const names = [];\n    for (let i = 0, ii = index.count; i < ii; ++i) {\n      const name = index.get(i);\n      names.push(bytesToString(name));\n    }\n    return names;\n  }\n  parseStringIndex(index) {\n    const strings = new CFFStrings();\n    for (let i = 0, ii = index.count; i < ii; ++i) {\n      const data = index.get(i);\n      strings.add(bytesToString(data));\n    }\n    return strings;\n  }\n  createDict(Type, dict, strings) {\n    const cffDict = new Type(strings);\n    for (const [key, value] of dict) {\n      cffDict.setByKey(key, value);\n    }\n    return cffDict;\n  }\n  parseCharString(state, data, localSubrIndex, globalSubrIndex) {\n    if (!data || state.callDepth > MAX_SUBR_NESTING) {\n      return false;\n    }\n    let stackSize = state.stackSize;\n    const stack = state.stack;\n    let length = data.length;\n    for (let j = 0; j < length;) {\n      const value = data[j++];\n      let validationCommand = null;\n      if (value === 12) {\n        const q = data[j++];\n        if (q === 0) {\n          data[j - 2] = 139;\n          data[j - 1] = 22;\n          stackSize = 0;\n        } else {\n          validationCommand = CharstringValidationData12[q];\n        }\n      } else if (value === 28) {\n        stack[stackSize] = (data[j] << 24 | data[j + 1] << 16) >> 16;\n        j += 2;\n        stackSize++;\n      } else if (value === 14) {\n        if (stackSize >= 4) {\n          stackSize -= 4;\n          if (this.seacAnalysisEnabled) {\n            state.seac = stack.slice(stackSize, stackSize + 4);\n            return false;\n          }\n        }\n        validationCommand = CharstringValidationData[value];\n      } else if (value >= 32 && value <= 246) {\n        stack[stackSize] = value - 139;\n        stackSize++;\n      } else if (value >= 247 && value <= 254) {\n        stack[stackSize] = value < 251 ? (value - 247 << 8) + data[j] + 108 : -(value - 251 << 8) - data[j] - 108;\n        j++;\n        stackSize++;\n      } else if (value === 255) {\n        stack[stackSize] = (data[j] << 24 | data[j + 1] << 16 | data[j + 2] << 8 | data[j + 3]) / 65536;\n        j += 4;\n        stackSize++;\n      } else if (value === 19 || value === 20) {\n        state.hints += stackSize >> 1;\n        if (state.hints === 0) {\n          data.copyWithin(j - 1, j, -1);\n          j -= 1;\n          length -= 1;\n          continue;\n        }\n        j += state.hints + 7 >> 3;\n        stackSize %= 2;\n        validationCommand = CharstringValidationData[value];\n      } else if (value === 10 || value === 29) {\n        const subrsIndex = value === 10 ? localSubrIndex : globalSubrIndex;\n        if (!subrsIndex) {\n          validationCommand = CharstringValidationData[value];\n          warn(\"Missing subrsIndex for \" + validationCommand.id);\n          return false;\n        }\n        let bias = 32768;\n        if (subrsIndex.count < 1240) {\n          bias = 107;\n        } else if (subrsIndex.count < 33900) {\n          bias = 1131;\n        }\n        const subrNumber = stack[--stackSize] + bias;\n        if (subrNumber < 0 || subrNumber >= subrsIndex.count || isNaN(subrNumber)) {\n          validationCommand = CharstringValidationData[value];\n          warn(\"Out of bounds subrIndex for \" + validationCommand.id);\n          return false;\n        }\n        state.stackSize = stackSize;\n        state.callDepth++;\n        const valid = this.parseCharString(state, subrsIndex.get(subrNumber), localSubrIndex, globalSubrIndex);\n        if (!valid) {\n          return false;\n        }\n        state.callDepth--;\n        stackSize = state.stackSize;\n        continue;\n      } else if (value === 11) {\n        state.stackSize = stackSize;\n        return true;\n      } else if (value === 0 && j === data.length) {\n        data[j - 1] = 14;\n        validationCommand = CharstringValidationData[14];\n      } else if (value === 9) {\n        data.copyWithin(j - 1, j, -1);\n        j -= 1;\n        length -= 1;\n        continue;\n      } else {\n        validationCommand = CharstringValidationData[value];\n      }\n      if (validationCommand) {\n        if (validationCommand.stem) {\n          state.hints += stackSize >> 1;\n          if (value === 3 || value === 23) {\n            state.hasVStems = true;\n          } else if (state.hasVStems && (value === 1 || value === 18)) {\n            warn(\"CFF stem hints are in wrong order\");\n            data[j - 1] = value === 1 ? 3 : 23;\n          }\n        }\n        if (\"min\" in validationCommand) {\n          if (!state.undefStack && stackSize < validationCommand.min) {\n            warn(\"Not enough parameters for \" + validationCommand.id + \"; actual: \" + stackSize + \", expected: \" + validationCommand.min);\n            if (stackSize === 0) {\n              data[j - 1] = 14;\n              return true;\n            }\n            return false;\n          }\n        }\n        if (state.firstStackClearing && validationCommand.stackClearing) {\n          state.firstStackClearing = false;\n          stackSize -= validationCommand.min;\n          if (stackSize >= 2 && validationCommand.stem) {\n            stackSize %= 2;\n          } else if (stackSize > 1) {\n            warn(\"Found too many parameters for stack-clearing command\");\n          }\n          if (stackSize > 0) {\n            state.width = stack[stackSize - 1];\n          }\n        }\n        if (\"stackDelta\" in validationCommand) {\n          if (\"stackFn\" in validationCommand) {\n            validationCommand.stackFn(stack, stackSize);\n          }\n          stackSize += validationCommand.stackDelta;\n        } else if (validationCommand.stackClearing) {\n          stackSize = 0;\n        } else if (validationCommand.resetStack) {\n          stackSize = 0;\n          state.undefStack = false;\n        } else if (validationCommand.undefStack) {\n          stackSize = 0;\n          state.undefStack = true;\n          state.firstStackClearing = false;\n        }\n      }\n    }\n    if (length < data.length) {\n      data.fill(14, length);\n    }\n    state.stackSize = stackSize;\n    return true;\n  }\n  parseCharStrings({\n    charStrings,\n    localSubrIndex,\n    globalSubrIndex,\n    fdSelect,\n    fdArray,\n    privateDict\n  }) {\n    const seacs = [];\n    const widths = [];\n    const count = charStrings.count;\n    for (let i = 0; i < count; i++) {\n      const charstring = charStrings.get(i);\n      const state = {\n        callDepth: 0,\n        stackSize: 0,\n        stack: [],\n        undefStack: true,\n        hints: 0,\n        firstStackClearing: true,\n        seac: null,\n        width: null,\n        hasVStems: false\n      };\n      let valid = true;\n      let localSubrToUse = null;\n      let privateDictToUse = privateDict;\n      if (fdSelect && fdArray.length) {\n        const fdIndex = fdSelect.getFDIndex(i);\n        if (fdIndex === -1) {\n          warn(\"Glyph index is not in fd select.\");\n          valid = false;\n        }\n        if (fdIndex >= fdArray.length) {\n          warn(\"Invalid fd index for glyph index.\");\n          valid = false;\n        }\n        if (valid) {\n          privateDictToUse = fdArray[fdIndex].privateDict;\n          localSubrToUse = privateDictToUse.subrsIndex;\n        }\n      } else if (localSubrIndex) {\n        localSubrToUse = localSubrIndex;\n      }\n      if (valid) {\n        valid = this.parseCharString(state, charstring, localSubrToUse, globalSubrIndex);\n      }\n      if (state.width !== null) {\n        const nominalWidth = privateDictToUse.getByName(\"nominalWidthX\");\n        widths[i] = nominalWidth + state.width;\n      } else {\n        const defaultWidth = privateDictToUse.getByName(\"defaultWidthX\");\n        widths[i] = defaultWidth;\n      }\n      if (state.seac !== null) {\n        seacs[i] = state.seac;\n      }\n      if (!valid) {\n        charStrings.set(i, new Uint8Array([14]));\n      }\n    }\n    return {\n      charStrings,\n      seacs,\n      widths\n    };\n  }\n  emptyPrivateDictionary(parentDict) {\n    const privateDict = this.createDict(CFFPrivateDict, [], parentDict.strings);\n    parentDict.setByKey(18, [0, 0]);\n    parentDict.privateDict = privateDict;\n  }\n  parsePrivateDict(parentDict) {\n    if (!parentDict.hasName(\"Private\")) {\n      this.emptyPrivateDictionary(parentDict);\n      return;\n    }\n    const privateOffset = parentDict.getByName(\"Private\");\n    if (!Array.isArray(privateOffset) || privateOffset.length !== 2) {\n      parentDict.removeByName(\"Private\");\n      return;\n    }\n    const size = privateOffset[0];\n    const offset = privateOffset[1];\n    if (size === 0 || offset >= this.bytes.length) {\n      this.emptyPrivateDictionary(parentDict);\n      return;\n    }\n    const privateDictEnd = offset + size;\n    const dictData = this.bytes.subarray(offset, privateDictEnd);\n    const dict = this.parseDict(dictData);\n    const privateDict = this.createDict(CFFPrivateDict, dict, parentDict.strings);\n    parentDict.privateDict = privateDict;\n    if (privateDict.getByName(\"ExpansionFactor\") === 0) {\n      privateDict.setByName(\"ExpansionFactor\", 0.06);\n    }\n    if (!privateDict.getByName(\"Subrs\")) {\n      return;\n    }\n    const subrsOffset = privateDict.getByName(\"Subrs\");\n    const relativeOffset = offset + subrsOffset;\n    if (subrsOffset === 0 || relativeOffset >= this.bytes.length) {\n      this.emptyPrivateDictionary(parentDict);\n      return;\n    }\n    const subrsIndex = this.parseIndex(relativeOffset);\n    privateDict.subrsIndex = subrsIndex.obj;\n  }\n  parseCharsets(pos, length, strings, cid) {\n    if (pos === 0) {\n      return new CFFCharset(true, CFFCharsetPredefinedTypes.ISO_ADOBE, ISOAdobeCharset);\n    } else if (pos === 1) {\n      return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT, ExpertCharset);\n    } else if (pos === 2) {\n      return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT_SUBSET, ExpertSubsetCharset);\n    }\n    const bytes = this.bytes;\n    const start = pos;\n    const format = bytes[pos++];\n    const charset = [cid ? 0 : \".notdef\"];\n    let id, count, i;\n    length -= 1;\n    switch (format) {\n      case 0:\n        for (i = 0; i < length; i++) {\n          id = bytes[pos++] << 8 | bytes[pos++];\n          charset.push(cid ? id : strings.get(id));\n        }\n        break;\n      case 1:\n        while (charset.length <= length) {\n          id = bytes[pos++] << 8 | bytes[pos++];\n          count = bytes[pos++];\n          for (i = 0; i <= count; i++) {\n            charset.push(cid ? id++ : strings.get(id++));\n          }\n        }\n        break;\n      case 2:\n        while (charset.length <= length) {\n          id = bytes[pos++] << 8 | bytes[pos++];\n          count = bytes[pos++] << 8 | bytes[pos++];\n          for (i = 0; i <= count; i++) {\n            charset.push(cid ? id++ : strings.get(id++));\n          }\n        }\n        break;\n      default:\n        throw new FormatError(\"Unknown charset format\");\n    }\n    const end = pos;\n    const raw = bytes.subarray(start, end);\n    return new CFFCharset(false, format, charset, raw);\n  }\n  parseEncoding(pos, properties, strings, charset) {\n    const encoding = Object.create(null);\n    const bytes = this.bytes;\n    let predefined = false;\n    let format, i, ii;\n    let raw = null;\n    function readSupplement() {\n      const supplementsCount = bytes[pos++];\n      for (i = 0; i < supplementsCount; i++) {\n        const code = bytes[pos++];\n        const sid = (bytes[pos++] << 8) + (bytes[pos++] & 0xff);\n        encoding[code] = charset.indexOf(strings.get(sid));\n      }\n    }\n    if (pos === 0 || pos === 1) {\n      predefined = true;\n      format = pos;\n      const baseEncoding = pos ? ExpertEncoding : StandardEncoding;\n      for (i = 0, ii = charset.length; i < ii; i++) {\n        const index = baseEncoding.indexOf(charset[i]);\n        if (index !== -1) {\n          encoding[index] = i;\n        }\n      }\n    } else {\n      const dataStart = pos;\n      format = bytes[pos++];\n      switch (format & 0x7f) {\n        case 0:\n          const glyphsCount = bytes[pos++];\n          for (i = 1; i <= glyphsCount; i++) {\n            encoding[bytes[pos++]] = i;\n          }\n          break;\n        case 1:\n          const rangesCount = bytes[pos++];\n          let gid = 1;\n          for (i = 0; i < rangesCount; i++) {\n            const start = bytes[pos++];\n            const left = bytes[pos++];\n            for (let j = start; j <= start + left; j++) {\n              encoding[j] = gid++;\n            }\n          }\n          break;\n        default:\n          throw new FormatError(`Unknown encoding format: ${format} in CFF`);\n      }\n      const dataEnd = pos;\n      if (format & 0x80) {\n        bytes[dataStart] &= 0x7f;\n        readSupplement();\n      }\n      raw = bytes.subarray(dataStart, dataEnd);\n    }\n    format &= 0x7f;\n    return new CFFEncoding(predefined, format, encoding, raw);\n  }\n  parseFDSelect(pos, length) {\n    const bytes = this.bytes;\n    const format = bytes[pos++];\n    const fdSelect = [];\n    let i;\n    switch (format) {\n      case 0:\n        for (i = 0; i < length; ++i) {\n          const id = bytes[pos++];\n          fdSelect.push(id);\n        }\n        break;\n      case 3:\n        const rangesCount = bytes[pos++] << 8 | bytes[pos++];\n        for (i = 0; i < rangesCount; ++i) {\n          let first = bytes[pos++] << 8 | bytes[pos++];\n          if (i === 0 && first !== 0) {\n            warn(\"parseFDSelect: The first range must have a first GID of 0\" + \" -- trying to recover.\");\n            first = 0;\n          }\n          const fdIndex = bytes[pos++];\n          const next = bytes[pos] << 8 | bytes[pos + 1];\n          for (let j = first; j < next; ++j) {\n            fdSelect.push(fdIndex);\n          }\n        }\n        pos += 2;\n        break;\n      default:\n        throw new FormatError(`parseFDSelect: Unknown format \"${format}\".`);\n    }\n    if (fdSelect.length !== length) {\n      throw new FormatError(\"parseFDSelect: Invalid font data.\");\n    }\n    return new CFFFDSelect(format, fdSelect);\n  }\n}\nclass CFF {\n  constructor() {\n    this.header = null;\n    this.names = [];\n    this.topDict = null;\n    this.strings = new CFFStrings();\n    this.globalSubrIndex = null;\n    this.encoding = null;\n    this.charset = null;\n    this.charStrings = null;\n    this.fdArray = [];\n    this.fdSelect = null;\n    this.isCIDFont = false;\n  }\n  duplicateFirstGlyph() {\n    if (this.charStrings.count >= 65535) {\n      warn(\"Not enough space in charstrings to duplicate first glyph.\");\n      return;\n    }\n    const glyphZero = this.charStrings.get(0);\n    this.charStrings.add(glyphZero);\n    if (this.isCIDFont) {\n      this.fdSelect.fdSelect.push(this.fdSelect.fdSelect[0]);\n    }\n  }\n  hasGlyphId(id) {\n    if (id < 0 || id >= this.charStrings.count) {\n      return false;\n    }\n    const glyph = this.charStrings.get(id);\n    return glyph.length > 0;\n  }\n}\nclass CFFHeader {\n  constructor(major, minor, hdrSize, offSize) {\n    this.major = major;\n    this.minor = minor;\n    this.hdrSize = hdrSize;\n    this.offSize = offSize;\n  }\n}\nclass CFFStrings {\n  constructor() {\n    this.strings = [];\n  }\n  get(index) {\n    if (index >= 0 && index <= NUM_STANDARD_CFF_STRINGS - 1) {\n      return CFFStandardStrings[index];\n    }\n    if (index - NUM_STANDARD_CFF_STRINGS <= this.strings.length) {\n      return this.strings[index - NUM_STANDARD_CFF_STRINGS];\n    }\n    return CFFStandardStrings[0];\n  }\n  getSID(str) {\n    let index = CFFStandardStrings.indexOf(str);\n    if (index !== -1) {\n      return index;\n    }\n    index = this.strings.indexOf(str);\n    if (index !== -1) {\n      return index + NUM_STANDARD_CFF_STRINGS;\n    }\n    return -1;\n  }\n  add(value) {\n    this.strings.push(value);\n  }\n  get count() {\n    return this.strings.length;\n  }\n}\nclass CFFIndex {\n  constructor() {\n    this.objects = [];\n    this.length = 0;\n  }\n  add(data) {\n    this.length += data.length;\n    this.objects.push(data);\n  }\n  set(index, data) {\n    this.length += data.length - this.objects[index].length;\n    this.objects[index] = data;\n  }\n  get(index) {\n    return this.objects[index];\n  }\n  get count() {\n    return this.objects.length;\n  }\n}\nclass CFFDict {\n  constructor(tables, strings) {\n    this.keyToNameMap = tables.keyToNameMap;\n    this.nameToKeyMap = tables.nameToKeyMap;\n    this.defaults = tables.defaults;\n    this.types = tables.types;\n    this.opcodes = tables.opcodes;\n    this.order = tables.order;\n    this.strings = strings;\n    this.values = Object.create(null);\n  }\n  setByKey(key, value) {\n    if (!(key in this.keyToNameMap)) {\n      return false;\n    }\n    if (value.length === 0) {\n      return true;\n    }\n    for (const val of value) {\n      if (isNaN(val)) {\n        warn(`Invalid CFFDict value: \"${value}\" for key \"${key}\".`);\n        return true;\n      }\n    }\n    const type = this.types[key];\n    if (type === \"num\" || type === \"sid\" || type === \"offset\") {\n      value = value[0];\n    }\n    this.values[key] = value;\n    return true;\n  }\n  setByName(name, value) {\n    if (!(name in this.nameToKeyMap)) {\n      throw new FormatError(`Invalid dictionary name \"${name}\"`);\n    }\n    this.values[this.nameToKeyMap[name]] = value;\n  }\n  hasName(name) {\n    return this.nameToKeyMap[name] in this.values;\n  }\n  getByName(name) {\n    if (!(name in this.nameToKeyMap)) {\n      throw new FormatError(`Invalid dictionary name ${name}\"`);\n    }\n    const key = this.nameToKeyMap[name];\n    if (!(key in this.values)) {\n      return this.defaults[key];\n    }\n    return this.values[key];\n  }\n  removeByName(name) {\n    delete this.values[this.nameToKeyMap[name]];\n  }\n  static createTables(layout) {\n    const tables = {\n      keyToNameMap: {},\n      nameToKeyMap: {},\n      defaults: {},\n      types: {},\n      opcodes: {},\n      order: []\n    };\n    for (const entry of layout) {\n      const key = Array.isArray(entry[0]) ? (entry[0][0] << 8) + entry[0][1] : entry[0];\n      tables.keyToNameMap[key] = entry[1];\n      tables.nameToKeyMap[entry[1]] = key;\n      tables.types[key] = entry[2];\n      tables.defaults[key] = entry[3];\n      tables.opcodes[key] = Array.isArray(entry[0]) ? entry[0] : [entry[0]];\n      tables.order.push(key);\n    }\n    return tables;\n  }\n}\nconst CFFTopDictLayout = [[[12, 30], \"ROS\", [\"sid\", \"sid\", \"num\"], null], [[12, 20], \"SyntheticBase\", \"num\", null], [0, \"version\", \"sid\", null], [1, \"Notice\", \"sid\", null], [[12, 0], \"Copyright\", \"sid\", null], [2, \"FullName\", \"sid\", null], [3, \"FamilyName\", \"sid\", null], [4, \"Weight\", \"sid\", null], [[12, 1], \"isFixedPitch\", \"num\", 0], [[12, 2], \"ItalicAngle\", \"num\", 0], [[12, 3], \"UnderlinePosition\", \"num\", -100], [[12, 4], \"UnderlineThickness\", \"num\", 50], [[12, 5], \"PaintType\", \"num\", 0], [[12, 6], \"CharstringType\", \"num\", 2], [[12, 7], \"FontMatrix\", [\"num\", \"num\", \"num\", \"num\", \"num\", \"num\"], [0.001, 0, 0, 0.001, 0, 0]], [13, \"UniqueID\", \"num\", null], [5, \"FontBBox\", [\"num\", \"num\", \"num\", \"num\"], [0, 0, 0, 0]], [[12, 8], \"StrokeWidth\", \"num\", 0], [14, \"XUID\", \"array\", null], [15, \"charset\", \"offset\", 0], [16, \"Encoding\", \"offset\", 0], [17, \"CharStrings\", \"offset\", 0], [18, \"Private\", [\"offset\", \"offset\"], null], [[12, 21], \"PostScript\", \"sid\", null], [[12, 22], \"BaseFontName\", \"sid\", null], [[12, 23], \"BaseFontBlend\", \"delta\", null], [[12, 31], \"CIDFontVersion\", \"num\", 0], [[12, 32], \"CIDFontRevision\", \"num\", 0], [[12, 33], \"CIDFontType\", \"num\", 0], [[12, 34], \"CIDCount\", \"num\", 8720], [[12, 35], \"UIDBase\", \"num\", null], [[12, 37], \"FDSelect\", \"offset\", null], [[12, 36], \"FDArray\", \"offset\", null], [[12, 38], \"FontName\", \"sid\", null]];\nclass CFFTopDict extends CFFDict {\n  static get tables() {\n    return shadow(this, \"tables\", this.createTables(CFFTopDictLayout));\n  }\n  constructor(strings) {\n    super(CFFTopDict.tables, strings);\n    this.privateDict = null;\n  }\n}\nconst CFFPrivateDictLayout = [[6, \"BlueValues\", \"delta\", null], [7, \"OtherBlues\", \"delta\", null], [8, \"FamilyBlues\", \"delta\", null], [9, \"FamilyOtherBlues\", \"delta\", null], [[12, 9], \"BlueScale\", \"num\", 0.039625], [[12, 10], \"BlueShift\", \"num\", 7], [[12, 11], \"BlueFuzz\", \"num\", 1], [10, \"StdHW\", \"num\", null], [11, \"StdVW\", \"num\", null], [[12, 12], \"StemSnapH\", \"delta\", null], [[12, 13], \"StemSnapV\", \"delta\", null], [[12, 14], \"ForceBold\", \"num\", 0], [[12, 17], \"LanguageGroup\", \"num\", 0], [[12, 18], \"ExpansionFactor\", \"num\", 0.06], [[12, 19], \"initialRandomSeed\", \"num\", 0], [20, \"defaultWidthX\", \"num\", 0], [21, \"nominalWidthX\", \"num\", 0], [19, \"Subrs\", \"offset\", null]];\nclass CFFPrivateDict extends CFFDict {\n  static get tables() {\n    return shadow(this, \"tables\", this.createTables(CFFPrivateDictLayout));\n  }\n  constructor(strings) {\n    super(CFFPrivateDict.tables, strings);\n    this.subrsIndex = null;\n  }\n}\nconst CFFCharsetPredefinedTypes = {\n  ISO_ADOBE: 0,\n  EXPERT: 1,\n  EXPERT_SUBSET: 2\n};\nclass CFFCharset {\n  constructor(predefined, format, charset, raw) {\n    this.predefined = predefined;\n    this.format = format;\n    this.charset = charset;\n    this.raw = raw;\n  }\n}\nclass CFFEncoding {\n  constructor(predefined, format, encoding, raw) {\n    this.predefined = predefined;\n    this.format = format;\n    this.encoding = encoding;\n    this.raw = raw;\n  }\n}\nclass CFFFDSelect {\n  constructor(format, fdSelect) {\n    this.format = format;\n    this.fdSelect = fdSelect;\n  }\n  getFDIndex(glyphIndex) {\n    if (glyphIndex < 0 || glyphIndex >= this.fdSelect.length) {\n      return -1;\n    }\n    return this.fdSelect[glyphIndex];\n  }\n}\nclass CFFOffsetTracker {\n  constructor() {\n    this.offsets = Object.create(null);\n  }\n  isTracking(key) {\n    return key in this.offsets;\n  }\n  track(key, location) {\n    if (key in this.offsets) {\n      throw new FormatError(`Already tracking location of ${key}`);\n    }\n    this.offsets[key] = location;\n  }\n  offset(value) {\n    for (const key in this.offsets) {\n      this.offsets[key] += value;\n    }\n  }\n  setEntryLocation(key, values, output) {\n    if (!(key in this.offsets)) {\n      throw new FormatError(`Not tracking location of ${key}`);\n    }\n    const data = output.data;\n    const dataOffset = this.offsets[key];\n    const size = 5;\n    for (let i = 0, ii = values.length; i < ii; ++i) {\n      const offset0 = i * size + dataOffset;\n      const offset1 = offset0 + 1;\n      const offset2 = offset0 + 2;\n      const offset3 = offset0 + 3;\n      const offset4 = offset0 + 4;\n      if (data[offset0] !== 0x1d || data[offset1] !== 0 || data[offset2] !== 0 || data[offset3] !== 0 || data[offset4] !== 0) {\n        throw new FormatError(\"writing to an offset that is not empty\");\n      }\n      const value = values[i];\n      data[offset0] = 0x1d;\n      data[offset1] = value >> 24 & 0xff;\n      data[offset2] = value >> 16 & 0xff;\n      data[offset3] = value >> 8 & 0xff;\n      data[offset4] = value & 0xff;\n    }\n  }\n}\nclass CFFCompiler {\n  constructor(cff) {\n    this.cff = cff;\n  }\n  compile() {\n    const cff = this.cff;\n    const output = {\n      data: [],\n      length: 0,\n      add(data) {\n        try {\n          this.data.push(...data);\n        } catch {\n          this.data = this.data.concat(data);\n        }\n        this.length = this.data.length;\n      }\n    };\n    const header = this.compileHeader(cff.header);\n    output.add(header);\n    const nameIndex = this.compileNameIndex(cff.names);\n    output.add(nameIndex);\n    if (cff.isCIDFont) {\n      if (cff.topDict.hasName(\"FontMatrix\")) {\n        const base = cff.topDict.getByName(\"FontMatrix\");\n        cff.topDict.removeByName(\"FontMatrix\");\n        for (const subDict of cff.fdArray) {\n          let matrix = base.slice(0);\n          if (subDict.hasName(\"FontMatrix\")) {\n            matrix = Util.transform(matrix, subDict.getByName(\"FontMatrix\"));\n          }\n          subDict.setByName(\"FontMatrix\", matrix);\n        }\n      }\n    }\n    const xuid = cff.topDict.getByName(\"XUID\");\n    if (xuid?.length > 16) {\n      cff.topDict.removeByName(\"XUID\");\n    }\n    cff.topDict.setByName(\"charset\", 0);\n    let compiled = this.compileTopDicts([cff.topDict], output.length, cff.isCIDFont);\n    output.add(compiled.output);\n    const topDictTracker = compiled.trackers[0];\n    const stringIndex = this.compileStringIndex(cff.strings.strings);\n    output.add(stringIndex);\n    const globalSubrIndex = this.compileIndex(cff.globalSubrIndex);\n    output.add(globalSubrIndex);\n    if (cff.encoding && cff.topDict.hasName(\"Encoding\")) {\n      if (cff.encoding.predefined) {\n        topDictTracker.setEntryLocation(\"Encoding\", [cff.encoding.format], output);\n      } else {\n        const encoding = this.compileEncoding(cff.encoding);\n        topDictTracker.setEntryLocation(\"Encoding\", [output.length], output);\n        output.add(encoding);\n      }\n    }\n    const charset = this.compileCharset(cff.charset, cff.charStrings.count, cff.strings, cff.isCIDFont);\n    topDictTracker.setEntryLocation(\"charset\", [output.length], output);\n    output.add(charset);\n    const charStrings = this.compileCharStrings(cff.charStrings);\n    topDictTracker.setEntryLocation(\"CharStrings\", [output.length], output);\n    output.add(charStrings);\n    if (cff.isCIDFont) {\n      topDictTracker.setEntryLocation(\"FDSelect\", [output.length], output);\n      const fdSelect = this.compileFDSelect(cff.fdSelect);\n      output.add(fdSelect);\n      compiled = this.compileTopDicts(cff.fdArray, output.length, true);\n      topDictTracker.setEntryLocation(\"FDArray\", [output.length], output);\n      output.add(compiled.output);\n      const fontDictTrackers = compiled.trackers;\n      this.compilePrivateDicts(cff.fdArray, fontDictTrackers, output);\n    }\n    this.compilePrivateDicts([cff.topDict], [topDictTracker], output);\n    output.add([0]);\n    return output.data;\n  }\n  encodeNumber(value) {\n    if (Number.isInteger(value)) {\n      return this.encodeInteger(value);\n    }\n    return this.encodeFloat(value);\n  }\n  static get EncodeFloatRegExp() {\n    return shadow(this, \"EncodeFloatRegExp\", /\\.(\\d*?)(?:9{5,20}|0{5,20})\\d{0,2}(?:e(.+)|$)/);\n  }\n  encodeFloat(num) {\n    let value = num.toString();\n    const m = CFFCompiler.EncodeFloatRegExp.exec(value);\n    if (m) {\n      const epsilon = parseFloat(\"1e\" + ((m[2] ? +m[2] : 0) + m[1].length));\n      value = (Math.round(num * epsilon) / epsilon).toString();\n    }\n    let nibbles = \"\";\n    let i, ii;\n    for (i = 0, ii = value.length; i < ii; ++i) {\n      const a = value[i];\n      if (a === \"e\") {\n        nibbles += value[++i] === \"-\" ? \"c\" : \"b\";\n      } else if (a === \".\") {\n        nibbles += \"a\";\n      } else if (a === \"-\") {\n        nibbles += \"e\";\n      } else {\n        nibbles += a;\n      }\n    }\n    nibbles += nibbles.length & 1 ? \"f\" : \"ff\";\n    const out = [30];\n    for (i = 0, ii = nibbles.length; i < ii; i += 2) {\n      out.push(parseInt(nibbles.substring(i, i + 2), 16));\n    }\n    return out;\n  }\n  encodeInteger(value) {\n    let code;\n    if (value >= -107 && value <= 107) {\n      code = [value + 139];\n    } else if (value >= 108 && value <= 1131) {\n      value -= 108;\n      code = [(value >> 8) + 247, value & 0xff];\n    } else if (value >= -1131 && value <= -108) {\n      value = -value - 108;\n      code = [(value >> 8) + 251, value & 0xff];\n    } else if (value >= -32768 && value <= 32767) {\n      code = [0x1c, value >> 8 & 0xff, value & 0xff];\n    } else {\n      code = [0x1d, value >> 24 & 0xff, value >> 16 & 0xff, value >> 8 & 0xff, value & 0xff];\n    }\n    return code;\n  }\n  compileHeader(header) {\n    return [header.major, header.minor, 4, header.offSize];\n  }\n  compileNameIndex(names) {\n    const nameIndex = new CFFIndex();\n    for (const name of names) {\n      const length = Math.min(name.length, 127);\n      let sanitizedName = new Array(length);\n      for (let j = 0; j < length; j++) {\n        let char = name[j];\n        if (char < \"!\" || char > \"~\" || char === \"[\" || char === \"]\" || char === \"(\" || char === \")\" || char === \"{\" || char === \"}\" || char === \"<\" || char === \">\" || char === \"/\" || char === \"%\") {\n          char = \"_\";\n        }\n        sanitizedName[j] = char;\n      }\n      sanitizedName = sanitizedName.join(\"\");\n      if (sanitizedName === \"\") {\n        sanitizedName = \"Bad_Font_Name\";\n      }\n      nameIndex.add(stringToBytes(sanitizedName));\n    }\n    return this.compileIndex(nameIndex);\n  }\n  compileTopDicts(dicts, length, removeCidKeys) {\n    const fontDictTrackers = [];\n    let fdArrayIndex = new CFFIndex();\n    for (const fontDict of dicts) {\n      if (removeCidKeys) {\n        fontDict.removeByName(\"CIDFontVersion\");\n        fontDict.removeByName(\"CIDFontRevision\");\n        fontDict.removeByName(\"CIDFontType\");\n        fontDict.removeByName(\"CIDCount\");\n        fontDict.removeByName(\"UIDBase\");\n      }\n      const fontDictTracker = new CFFOffsetTracker();\n      const fontDictData = this.compileDict(fontDict, fontDictTracker);\n      fontDictTrackers.push(fontDictTracker);\n      fdArrayIndex.add(fontDictData);\n      fontDictTracker.offset(length);\n    }\n    fdArrayIndex = this.compileIndex(fdArrayIndex, fontDictTrackers);\n    return {\n      trackers: fontDictTrackers,\n      output: fdArrayIndex\n    };\n  }\n  compilePrivateDicts(dicts, trackers, output) {\n    for (let i = 0, ii = dicts.length; i < ii; ++i) {\n      const fontDict = dicts[i];\n      const privateDict = fontDict.privateDict;\n      if (!privateDict || !fontDict.hasName(\"Private\")) {\n        throw new FormatError(\"There must be a private dictionary.\");\n      }\n      const privateDictTracker = new CFFOffsetTracker();\n      const privateDictData = this.compileDict(privateDict, privateDictTracker);\n      let outputLength = output.length;\n      privateDictTracker.offset(outputLength);\n      if (!privateDictData.length) {\n        outputLength = 0;\n      }\n      trackers[i].setEntryLocation(\"Private\", [privateDictData.length, outputLength], output);\n      output.add(privateDictData);\n      if (privateDict.subrsIndex && privateDict.hasName(\"Subrs\")) {\n        const subrs = this.compileIndex(privateDict.subrsIndex);\n        privateDictTracker.setEntryLocation(\"Subrs\", [privateDictData.length], output);\n        output.add(subrs);\n      }\n    }\n  }\n  compileDict(dict, offsetTracker) {\n    const out = [];\n    for (const key of dict.order) {\n      if (!(key in dict.values)) {\n        continue;\n      }\n      let values = dict.values[key];\n      let types = dict.types[key];\n      if (!Array.isArray(types)) {\n        types = [types];\n      }\n      if (!Array.isArray(values)) {\n        values = [values];\n      }\n      if (values.length === 0) {\n        continue;\n      }\n      for (let j = 0, jj = types.length; j < jj; ++j) {\n        const type = types[j];\n        const value = values[j];\n        switch (type) {\n          case \"num\":\n          case \"sid\":\n            out.push(...this.encodeNumber(value));\n            break;\n          case \"offset\":\n            const name = dict.keyToNameMap[key];\n            if (!offsetTracker.isTracking(name)) {\n              offsetTracker.track(name, out.length);\n            }\n            out.push(0x1d, 0, 0, 0, 0);\n            break;\n          case \"array\":\n          case \"delta\":\n            out.push(...this.encodeNumber(value));\n            for (let k = 1, kk = values.length; k < kk; ++k) {\n              out.push(...this.encodeNumber(values[k]));\n            }\n            break;\n          default:\n            throw new FormatError(`Unknown data type of ${type}`);\n        }\n      }\n      out.push(...dict.opcodes[key]);\n    }\n    return out;\n  }\n  compileStringIndex(strings) {\n    const stringIndex = new CFFIndex();\n    for (const string of strings) {\n      stringIndex.add(stringToBytes(string));\n    }\n    return this.compileIndex(stringIndex);\n  }\n  compileCharStrings(charStrings) {\n    const charStringsIndex = new CFFIndex();\n    for (let i = 0; i < charStrings.count; i++) {\n      const glyph = charStrings.get(i);\n      if (glyph.length === 0) {\n        charStringsIndex.add(new Uint8Array([0x8b, 0x0e]));\n        continue;\n      }\n      charStringsIndex.add(glyph);\n    }\n    return this.compileIndex(charStringsIndex);\n  }\n  compileCharset(charset, numGlyphs, strings, isCIDFont) {\n    let out;\n    const numGlyphsLessNotDef = numGlyphs - 1;\n    if (isCIDFont) {\n      out = new Uint8Array([2, 0, 0, numGlyphsLessNotDef >> 8 & 0xff, numGlyphsLessNotDef & 0xff]);\n    } else {\n      const length = 1 + numGlyphsLessNotDef * 2;\n      out = new Uint8Array(length);\n      out[0] = 0;\n      let charsetIndex = 0;\n      const numCharsets = charset.charset.length;\n      let warned = false;\n      for (let i = 1; i < out.length; i += 2) {\n        let sid = 0;\n        if (charsetIndex < numCharsets) {\n          const name = charset.charset[charsetIndex++];\n          sid = strings.getSID(name);\n          if (sid === -1) {\n            sid = 0;\n            if (!warned) {\n              warned = true;\n              warn(`Couldn't find ${name} in CFF strings`);\n            }\n          }\n        }\n        out[i] = sid >> 8 & 0xff;\n        out[i + 1] = sid & 0xff;\n      }\n    }\n    return this.compileTypedArray(out);\n  }\n  compileEncoding(encoding) {\n    return this.compileTypedArray(encoding.raw);\n  }\n  compileFDSelect(fdSelect) {\n    const format = fdSelect.format;\n    let out, i;\n    switch (format) {\n      case 0:\n        out = new Uint8Array(1 + fdSelect.fdSelect.length);\n        out[0] = format;\n        for (i = 0; i < fdSelect.fdSelect.length; i++) {\n          out[i + 1] = fdSelect.fdSelect[i];\n        }\n        break;\n      case 3:\n        const start = 0;\n        let lastFD = fdSelect.fdSelect[0];\n        const ranges = [format, 0, 0, start >> 8 & 0xff, start & 0xff, lastFD];\n        for (i = 1; i < fdSelect.fdSelect.length; i++) {\n          const currentFD = fdSelect.fdSelect[i];\n          if (currentFD !== lastFD) {\n            ranges.push(i >> 8 & 0xff, i & 0xff, currentFD);\n            lastFD = currentFD;\n          }\n        }\n        const numRanges = (ranges.length - 3) / 3;\n        ranges[1] = numRanges >> 8 & 0xff;\n        ranges[2] = numRanges & 0xff;\n        ranges.push(i >> 8 & 0xff, i & 0xff);\n        out = new Uint8Array(ranges);\n        break;\n    }\n    return this.compileTypedArray(out);\n  }\n  compileTypedArray(data) {\n    return Array.from(data);\n  }\n  compileIndex(index, trackers = []) {\n    const objects = index.objects;\n    const count = objects.length;\n    if (count === 0) {\n      return [0, 0];\n    }\n    const data = [count >> 8 & 0xff, count & 0xff];\n    let lastOffset = 1,\n      i;\n    for (i = 0; i < count; ++i) {\n      lastOffset += objects[i].length;\n    }\n    let offsetSize;\n    if (lastOffset < 0x100) {\n      offsetSize = 1;\n    } else if (lastOffset < 0x10000) {\n      offsetSize = 2;\n    } else if (lastOffset < 0x1000000) {\n      offsetSize = 3;\n    } else {\n      offsetSize = 4;\n    }\n    data.push(offsetSize);\n    let relativeOffset = 1;\n    for (i = 0; i < count + 1; i++) {\n      if (offsetSize === 1) {\n        data.push(relativeOffset & 0xff);\n      } else if (offsetSize === 2) {\n        data.push(relativeOffset >> 8 & 0xff, relativeOffset & 0xff);\n      } else if (offsetSize === 3) {\n        data.push(relativeOffset >> 16 & 0xff, relativeOffset >> 8 & 0xff, relativeOffset & 0xff);\n      } else {\n        data.push(relativeOffset >>> 24 & 0xff, relativeOffset >> 16 & 0xff, relativeOffset >> 8 & 0xff, relativeOffset & 0xff);\n      }\n      if (objects[i]) {\n        relativeOffset += objects[i].length;\n      }\n    }\n    for (i = 0; i < count; i++) {\n      if (trackers[i]) {\n        trackers[i].offset(data.length);\n      }\n      data.push(...objects[i]);\n    }\n    return data;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/glyphlist.js\n\nconst getGlyphsUnicode = getLookupTableFactory(function (t) {\n  t.A = 0x0041;\n  t.AE = 0x00c6;\n  t.AEacute = 0x01fc;\n  t.AEmacron = 0x01e2;\n  t.AEsmall = 0xf7e6;\n  t.Aacute = 0x00c1;\n  t.Aacutesmall = 0xf7e1;\n  t.Abreve = 0x0102;\n  t.Abreveacute = 0x1eae;\n  t.Abrevecyrillic = 0x04d0;\n  t.Abrevedotbelow = 0x1eb6;\n  t.Abrevegrave = 0x1eb0;\n  t.Abrevehookabove = 0x1eb2;\n  t.Abrevetilde = 0x1eb4;\n  t.Acaron = 0x01cd;\n  t.Acircle = 0x24b6;\n  t.Acircumflex = 0x00c2;\n  t.Acircumflexacute = 0x1ea4;\n  t.Acircumflexdotbelow = 0x1eac;\n  t.Acircumflexgrave = 0x1ea6;\n  t.Acircumflexhookabove = 0x1ea8;\n  t.Acircumflexsmall = 0xf7e2;\n  t.Acircumflextilde = 0x1eaa;\n  t.Acute = 0xf6c9;\n  t.Acutesmall = 0xf7b4;\n  t.Acyrillic = 0x0410;\n  t.Adblgrave = 0x0200;\n  t.Adieresis = 0x00c4;\n  t.Adieresiscyrillic = 0x04d2;\n  t.Adieresismacron = 0x01de;\n  t.Adieresissmall = 0xf7e4;\n  t.Adotbelow = 0x1ea0;\n  t.Adotmacron = 0x01e0;\n  t.Agrave = 0x00c0;\n  t.Agravesmall = 0xf7e0;\n  t.Ahookabove = 0x1ea2;\n  t.Aiecyrillic = 0x04d4;\n  t.Ainvertedbreve = 0x0202;\n  t.Alpha = 0x0391;\n  t.Alphatonos = 0x0386;\n  t.Amacron = 0x0100;\n  t.Amonospace = 0xff21;\n  t.Aogonek = 0x0104;\n  t.Aring = 0x00c5;\n  t.Aringacute = 0x01fa;\n  t.Aringbelow = 0x1e00;\n  t.Aringsmall = 0xf7e5;\n  t.Asmall = 0xf761;\n  t.Atilde = 0x00c3;\n  t.Atildesmall = 0xf7e3;\n  t.Aybarmenian = 0x0531;\n  t.B = 0x0042;\n  t.Bcircle = 0x24b7;\n  t.Bdotaccent = 0x1e02;\n  t.Bdotbelow = 0x1e04;\n  t.Becyrillic = 0x0411;\n  t.Benarmenian = 0x0532;\n  t.Beta = 0x0392;\n  t.Bhook = 0x0181;\n  t.Blinebelow = 0x1e06;\n  t.Bmonospace = 0xff22;\n  t.Brevesmall = 0xf6f4;\n  t.Bsmall = 0xf762;\n  t.Btopbar = 0x0182;\n  t.C = 0x0043;\n  t.Caarmenian = 0x053e;\n  t.Cacute = 0x0106;\n  t.Caron = 0xf6ca;\n  t.Caronsmall = 0xf6f5;\n  t.Ccaron = 0x010c;\n  t.Ccedilla = 0x00c7;\n  t.Ccedillaacute = 0x1e08;\n  t.Ccedillasmall = 0xf7e7;\n  t.Ccircle = 0x24b8;\n  t.Ccircumflex = 0x0108;\n  t.Cdot = 0x010a;\n  t.Cdotaccent = 0x010a;\n  t.Cedillasmall = 0xf7b8;\n  t.Chaarmenian = 0x0549;\n  t.Cheabkhasiancyrillic = 0x04bc;\n  t.Checyrillic = 0x0427;\n  t.Chedescenderabkhasiancyrillic = 0x04be;\n  t.Chedescendercyrillic = 0x04b6;\n  t.Chedieresiscyrillic = 0x04f4;\n  t.Cheharmenian = 0x0543;\n  t.Chekhakassiancyrillic = 0x04cb;\n  t.Cheverticalstrokecyrillic = 0x04b8;\n  t.Chi = 0x03a7;\n  t.Chook = 0x0187;\n  t.Circumflexsmall = 0xf6f6;\n  t.Cmonospace = 0xff23;\n  t.Coarmenian = 0x0551;\n  t.Csmall = 0xf763;\n  t.D = 0x0044;\n  t.DZ = 0x01f1;\n  t.DZcaron = 0x01c4;\n  t.Daarmenian = 0x0534;\n  t.Dafrican = 0x0189;\n  t.Dcaron = 0x010e;\n  t.Dcedilla = 0x1e10;\n  t.Dcircle = 0x24b9;\n  t.Dcircumflexbelow = 0x1e12;\n  t.Dcroat = 0x0110;\n  t.Ddotaccent = 0x1e0a;\n  t.Ddotbelow = 0x1e0c;\n  t.Decyrillic = 0x0414;\n  t.Deicoptic = 0x03ee;\n  t.Delta = 0x2206;\n  t.Deltagreek = 0x0394;\n  t.Dhook = 0x018a;\n  t.Dieresis = 0xf6cb;\n  t.DieresisAcute = 0xf6cc;\n  t.DieresisGrave = 0xf6cd;\n  t.Dieresissmall = 0xf7a8;\n  t.Digammagreek = 0x03dc;\n  t.Djecyrillic = 0x0402;\n  t.Dlinebelow = 0x1e0e;\n  t.Dmonospace = 0xff24;\n  t.Dotaccentsmall = 0xf6f7;\n  t.Dslash = 0x0110;\n  t.Dsmall = 0xf764;\n  t.Dtopbar = 0x018b;\n  t.Dz = 0x01f2;\n  t.Dzcaron = 0x01c5;\n  t.Dzeabkhasiancyrillic = 0x04e0;\n  t.Dzecyrillic = 0x0405;\n  t.Dzhecyrillic = 0x040f;\n  t.E = 0x0045;\n  t.Eacute = 0x00c9;\n  t.Eacutesmall = 0xf7e9;\n  t.Ebreve = 0x0114;\n  t.Ecaron = 0x011a;\n  t.Ecedillabreve = 0x1e1c;\n  t.Echarmenian = 0x0535;\n  t.Ecircle = 0x24ba;\n  t.Ecircumflex = 0x00ca;\n  t.Ecircumflexacute = 0x1ebe;\n  t.Ecircumflexbelow = 0x1e18;\n  t.Ecircumflexdotbelow = 0x1ec6;\n  t.Ecircumflexgrave = 0x1ec0;\n  t.Ecircumflexhookabove = 0x1ec2;\n  t.Ecircumflexsmall = 0xf7ea;\n  t.Ecircumflextilde = 0x1ec4;\n  t.Ecyrillic = 0x0404;\n  t.Edblgrave = 0x0204;\n  t.Edieresis = 0x00cb;\n  t.Edieresissmall = 0xf7eb;\n  t.Edot = 0x0116;\n  t.Edotaccent = 0x0116;\n  t.Edotbelow = 0x1eb8;\n  t.Efcyrillic = 0x0424;\n  t.Egrave = 0x00c8;\n  t.Egravesmall = 0xf7e8;\n  t.Eharmenian = 0x0537;\n  t.Ehookabove = 0x1eba;\n  t.Eightroman = 0x2167;\n  t.Einvertedbreve = 0x0206;\n  t.Eiotifiedcyrillic = 0x0464;\n  t.Elcyrillic = 0x041b;\n  t.Elevenroman = 0x216a;\n  t.Emacron = 0x0112;\n  t.Emacronacute = 0x1e16;\n  t.Emacrongrave = 0x1e14;\n  t.Emcyrillic = 0x041c;\n  t.Emonospace = 0xff25;\n  t.Encyrillic = 0x041d;\n  t.Endescendercyrillic = 0x04a2;\n  t.Eng = 0x014a;\n  t.Enghecyrillic = 0x04a4;\n  t.Enhookcyrillic = 0x04c7;\n  t.Eogonek = 0x0118;\n  t.Eopen = 0x0190;\n  t.Epsilon = 0x0395;\n  t.Epsilontonos = 0x0388;\n  t.Ercyrillic = 0x0420;\n  t.Ereversed = 0x018e;\n  t.Ereversedcyrillic = 0x042d;\n  t.Escyrillic = 0x0421;\n  t.Esdescendercyrillic = 0x04aa;\n  t.Esh = 0x01a9;\n  t.Esmall = 0xf765;\n  t.Eta = 0x0397;\n  t.Etarmenian = 0x0538;\n  t.Etatonos = 0x0389;\n  t.Eth = 0x00d0;\n  t.Ethsmall = 0xf7f0;\n  t.Etilde = 0x1ebc;\n  t.Etildebelow = 0x1e1a;\n  t.Euro = 0x20ac;\n  t.Ezh = 0x01b7;\n  t.Ezhcaron = 0x01ee;\n  t.Ezhreversed = 0x01b8;\n  t.F = 0x0046;\n  t.Fcircle = 0x24bb;\n  t.Fdotaccent = 0x1e1e;\n  t.Feharmenian = 0x0556;\n  t.Feicoptic = 0x03e4;\n  t.Fhook = 0x0191;\n  t.Fitacyrillic = 0x0472;\n  t.Fiveroman = 0x2164;\n  t.Fmonospace = 0xff26;\n  t.Fourroman = 0x2163;\n  t.Fsmall = 0xf766;\n  t.G = 0x0047;\n  t.GBsquare = 0x3387;\n  t.Gacute = 0x01f4;\n  t.Gamma = 0x0393;\n  t.Gammaafrican = 0x0194;\n  t.Gangiacoptic = 0x03ea;\n  t.Gbreve = 0x011e;\n  t.Gcaron = 0x01e6;\n  t.Gcedilla = 0x0122;\n  t.Gcircle = 0x24bc;\n  t.Gcircumflex = 0x011c;\n  t.Gcommaaccent = 0x0122;\n  t.Gdot = 0x0120;\n  t.Gdotaccent = 0x0120;\n  t.Gecyrillic = 0x0413;\n  t.Ghadarmenian = 0x0542;\n  t.Ghemiddlehookcyrillic = 0x0494;\n  t.Ghestrokecyrillic = 0x0492;\n  t.Gheupturncyrillic = 0x0490;\n  t.Ghook = 0x0193;\n  t.Gimarmenian = 0x0533;\n  t.Gjecyrillic = 0x0403;\n  t.Gmacron = 0x1e20;\n  t.Gmonospace = 0xff27;\n  t.Grave = 0xf6ce;\n  t.Gravesmall = 0xf760;\n  t.Gsmall = 0xf767;\n  t.Gsmallhook = 0x029b;\n  t.Gstroke = 0x01e4;\n  t.H = 0x0048;\n  t.H18533 = 0x25cf;\n  t.H18543 = 0x25aa;\n  t.H18551 = 0x25ab;\n  t.H22073 = 0x25a1;\n  t.HPsquare = 0x33cb;\n  t.Haabkhasiancyrillic = 0x04a8;\n  t.Hadescendercyrillic = 0x04b2;\n  t.Hardsigncyrillic = 0x042a;\n  t.Hbar = 0x0126;\n  t.Hbrevebelow = 0x1e2a;\n  t.Hcedilla = 0x1e28;\n  t.Hcircle = 0x24bd;\n  t.Hcircumflex = 0x0124;\n  t.Hdieresis = 0x1e26;\n  t.Hdotaccent = 0x1e22;\n  t.Hdotbelow = 0x1e24;\n  t.Hmonospace = 0xff28;\n  t.Hoarmenian = 0x0540;\n  t.Horicoptic = 0x03e8;\n  t.Hsmall = 0xf768;\n  t.Hungarumlaut = 0xf6cf;\n  t.Hungarumlautsmall = 0xf6f8;\n  t.Hzsquare = 0x3390;\n  t.I = 0x0049;\n  t.IAcyrillic = 0x042f;\n  t.IJ = 0x0132;\n  t.IUcyrillic = 0x042e;\n  t.Iacute = 0x00cd;\n  t.Iacutesmall = 0xf7ed;\n  t.Ibreve = 0x012c;\n  t.Icaron = 0x01cf;\n  t.Icircle = 0x24be;\n  t.Icircumflex = 0x00ce;\n  t.Icircumflexsmall = 0xf7ee;\n  t.Icyrillic = 0x0406;\n  t.Idblgrave = 0x0208;\n  t.Idieresis = 0x00cf;\n  t.Idieresisacute = 0x1e2e;\n  t.Idieresiscyrillic = 0x04e4;\n  t.Idieresissmall = 0xf7ef;\n  t.Idot = 0x0130;\n  t.Idotaccent = 0x0130;\n  t.Idotbelow = 0x1eca;\n  t.Iebrevecyrillic = 0x04d6;\n  t.Iecyrillic = 0x0415;\n  t.Ifraktur = 0x2111;\n  t.Igrave = 0x00cc;\n  t.Igravesmall = 0xf7ec;\n  t.Ihookabove = 0x1ec8;\n  t.Iicyrillic = 0x0418;\n  t.Iinvertedbreve = 0x020a;\n  t.Iishortcyrillic = 0x0419;\n  t.Imacron = 0x012a;\n  t.Imacroncyrillic = 0x04e2;\n  t.Imonospace = 0xff29;\n  t.Iniarmenian = 0x053b;\n  t.Iocyrillic = 0x0401;\n  t.Iogonek = 0x012e;\n  t.Iota = 0x0399;\n  t.Iotaafrican = 0x0196;\n  t.Iotadieresis = 0x03aa;\n  t.Iotatonos = 0x038a;\n  t.Ismall = 0xf769;\n  t.Istroke = 0x0197;\n  t.Itilde = 0x0128;\n  t.Itildebelow = 0x1e2c;\n  t.Izhitsacyrillic = 0x0474;\n  t.Izhitsadblgravecyrillic = 0x0476;\n  t.J = 0x004a;\n  t.Jaarmenian = 0x0541;\n  t.Jcircle = 0x24bf;\n  t.Jcircumflex = 0x0134;\n  t.Jecyrillic = 0x0408;\n  t.Jheharmenian = 0x054b;\n  t.Jmonospace = 0xff2a;\n  t.Jsmall = 0xf76a;\n  t.K = 0x004b;\n  t.KBsquare = 0x3385;\n  t.KKsquare = 0x33cd;\n  t.Kabashkircyrillic = 0x04a0;\n  t.Kacute = 0x1e30;\n  t.Kacyrillic = 0x041a;\n  t.Kadescendercyrillic = 0x049a;\n  t.Kahookcyrillic = 0x04c3;\n  t.Kappa = 0x039a;\n  t.Kastrokecyrillic = 0x049e;\n  t.Kaverticalstrokecyrillic = 0x049c;\n  t.Kcaron = 0x01e8;\n  t.Kcedilla = 0x0136;\n  t.Kcircle = 0x24c0;\n  t.Kcommaaccent = 0x0136;\n  t.Kdotbelow = 0x1e32;\n  t.Keharmenian = 0x0554;\n  t.Kenarmenian = 0x053f;\n  t.Khacyrillic = 0x0425;\n  t.Kheicoptic = 0x03e6;\n  t.Khook = 0x0198;\n  t.Kjecyrillic = 0x040c;\n  t.Klinebelow = 0x1e34;\n  t.Kmonospace = 0xff2b;\n  t.Koppacyrillic = 0x0480;\n  t.Koppagreek = 0x03de;\n  t.Ksicyrillic = 0x046e;\n  t.Ksmall = 0xf76b;\n  t.L = 0x004c;\n  t.LJ = 0x01c7;\n  t.LL = 0xf6bf;\n  t.Lacute = 0x0139;\n  t.Lambda = 0x039b;\n  t.Lcaron = 0x013d;\n  t.Lcedilla = 0x013b;\n  t.Lcircle = 0x24c1;\n  t.Lcircumflexbelow = 0x1e3c;\n  t.Lcommaaccent = 0x013b;\n  t.Ldot = 0x013f;\n  t.Ldotaccent = 0x013f;\n  t.Ldotbelow = 0x1e36;\n  t.Ldotbelowmacron = 0x1e38;\n  t.Liwnarmenian = 0x053c;\n  t.Lj = 0x01c8;\n  t.Ljecyrillic = 0x0409;\n  t.Llinebelow = 0x1e3a;\n  t.Lmonospace = 0xff2c;\n  t.Lslash = 0x0141;\n  t.Lslashsmall = 0xf6f9;\n  t.Lsmall = 0xf76c;\n  t.M = 0x004d;\n  t.MBsquare = 0x3386;\n  t.Macron = 0xf6d0;\n  t.Macronsmall = 0xf7af;\n  t.Macute = 0x1e3e;\n  t.Mcircle = 0x24c2;\n  t.Mdotaccent = 0x1e40;\n  t.Mdotbelow = 0x1e42;\n  t.Menarmenian = 0x0544;\n  t.Mmonospace = 0xff2d;\n  t.Msmall = 0xf76d;\n  t.Mturned = 0x019c;\n  t.Mu = 0x039c;\n  t.N = 0x004e;\n  t.NJ = 0x01ca;\n  t.Nacute = 0x0143;\n  t.Ncaron = 0x0147;\n  t.Ncedilla = 0x0145;\n  t.Ncircle = 0x24c3;\n  t.Ncircumflexbelow = 0x1e4a;\n  t.Ncommaaccent = 0x0145;\n  t.Ndotaccent = 0x1e44;\n  t.Ndotbelow = 0x1e46;\n  t.Nhookleft = 0x019d;\n  t.Nineroman = 0x2168;\n  t.Nj = 0x01cb;\n  t.Njecyrillic = 0x040a;\n  t.Nlinebelow = 0x1e48;\n  t.Nmonospace = 0xff2e;\n  t.Nowarmenian = 0x0546;\n  t.Nsmall = 0xf76e;\n  t.Ntilde = 0x00d1;\n  t.Ntildesmall = 0xf7f1;\n  t.Nu = 0x039d;\n  t.O = 0x004f;\n  t.OE = 0x0152;\n  t.OEsmall = 0xf6fa;\n  t.Oacute = 0x00d3;\n  t.Oacutesmall = 0xf7f3;\n  t.Obarredcyrillic = 0x04e8;\n  t.Obarreddieresiscyrillic = 0x04ea;\n  t.Obreve = 0x014e;\n  t.Ocaron = 0x01d1;\n  t.Ocenteredtilde = 0x019f;\n  t.Ocircle = 0x24c4;\n  t.Ocircumflex = 0x00d4;\n  t.Ocircumflexacute = 0x1ed0;\n  t.Ocircumflexdotbelow = 0x1ed8;\n  t.Ocircumflexgrave = 0x1ed2;\n  t.Ocircumflexhookabove = 0x1ed4;\n  t.Ocircumflexsmall = 0xf7f4;\n  t.Ocircumflextilde = 0x1ed6;\n  t.Ocyrillic = 0x041e;\n  t.Odblacute = 0x0150;\n  t.Odblgrave = 0x020c;\n  t.Odieresis = 0x00d6;\n  t.Odieresiscyrillic = 0x04e6;\n  t.Odieresissmall = 0xf7f6;\n  t.Odotbelow = 0x1ecc;\n  t.Ogoneksmall = 0xf6fb;\n  t.Ograve = 0x00d2;\n  t.Ogravesmall = 0xf7f2;\n  t.Oharmenian = 0x0555;\n  t.Ohm = 0x2126;\n  t.Ohookabove = 0x1ece;\n  t.Ohorn = 0x01a0;\n  t.Ohornacute = 0x1eda;\n  t.Ohorndotbelow = 0x1ee2;\n  t.Ohorngrave = 0x1edc;\n  t.Ohornhookabove = 0x1ede;\n  t.Ohorntilde = 0x1ee0;\n  t.Ohungarumlaut = 0x0150;\n  t.Oi = 0x01a2;\n  t.Oinvertedbreve = 0x020e;\n  t.Omacron = 0x014c;\n  t.Omacronacute = 0x1e52;\n  t.Omacrongrave = 0x1e50;\n  t.Omega = 0x2126;\n  t.Omegacyrillic = 0x0460;\n  t.Omegagreek = 0x03a9;\n  t.Omegaroundcyrillic = 0x047a;\n  t.Omegatitlocyrillic = 0x047c;\n  t.Omegatonos = 0x038f;\n  t.Omicron = 0x039f;\n  t.Omicrontonos = 0x038c;\n  t.Omonospace = 0xff2f;\n  t.Oneroman = 0x2160;\n  t.Oogonek = 0x01ea;\n  t.Oogonekmacron = 0x01ec;\n  t.Oopen = 0x0186;\n  t.Oslash = 0x00d8;\n  t.Oslashacute = 0x01fe;\n  t.Oslashsmall = 0xf7f8;\n  t.Osmall = 0xf76f;\n  t.Ostrokeacute = 0x01fe;\n  t.Otcyrillic = 0x047e;\n  t.Otilde = 0x00d5;\n  t.Otildeacute = 0x1e4c;\n  t.Otildedieresis = 0x1e4e;\n  t.Otildesmall = 0xf7f5;\n  t.P = 0x0050;\n  t.Pacute = 0x1e54;\n  t.Pcircle = 0x24c5;\n  t.Pdotaccent = 0x1e56;\n  t.Pecyrillic = 0x041f;\n  t.Peharmenian = 0x054a;\n  t.Pemiddlehookcyrillic = 0x04a6;\n  t.Phi = 0x03a6;\n  t.Phook = 0x01a4;\n  t.Pi = 0x03a0;\n  t.Piwrarmenian = 0x0553;\n  t.Pmonospace = 0xff30;\n  t.Psi = 0x03a8;\n  t.Psicyrillic = 0x0470;\n  t.Psmall = 0xf770;\n  t.Q = 0x0051;\n  t.Qcircle = 0x24c6;\n  t.Qmonospace = 0xff31;\n  t.Qsmall = 0xf771;\n  t.R = 0x0052;\n  t.Raarmenian = 0x054c;\n  t.Racute = 0x0154;\n  t.Rcaron = 0x0158;\n  t.Rcedilla = 0x0156;\n  t.Rcircle = 0x24c7;\n  t.Rcommaaccent = 0x0156;\n  t.Rdblgrave = 0x0210;\n  t.Rdotaccent = 0x1e58;\n  t.Rdotbelow = 0x1e5a;\n  t.Rdotbelowmacron = 0x1e5c;\n  t.Reharmenian = 0x0550;\n  t.Rfraktur = 0x211c;\n  t.Rho = 0x03a1;\n  t.Ringsmall = 0xf6fc;\n  t.Rinvertedbreve = 0x0212;\n  t.Rlinebelow = 0x1e5e;\n  t.Rmonospace = 0xff32;\n  t.Rsmall = 0xf772;\n  t.Rsmallinverted = 0x0281;\n  t.Rsmallinvertedsuperior = 0x02b6;\n  t.S = 0x0053;\n  t.SF010000 = 0x250c;\n  t.SF020000 = 0x2514;\n  t.SF030000 = 0x2510;\n  t.SF040000 = 0x2518;\n  t.SF050000 = 0x253c;\n  t.SF060000 = 0x252c;\n  t.SF070000 = 0x2534;\n  t.SF080000 = 0x251c;\n  t.SF090000 = 0x2524;\n  t.SF100000 = 0x2500;\n  t.SF110000 = 0x2502;\n  t.SF190000 = 0x2561;\n  t.SF200000 = 0x2562;\n  t.SF210000 = 0x2556;\n  t.SF220000 = 0x2555;\n  t.SF230000 = 0x2563;\n  t.SF240000 = 0x2551;\n  t.SF250000 = 0x2557;\n  t.SF260000 = 0x255d;\n  t.SF270000 = 0x255c;\n  t.SF280000 = 0x255b;\n  t.SF360000 = 0x255e;\n  t.SF370000 = 0x255f;\n  t.SF380000 = 0x255a;\n  t.SF390000 = 0x2554;\n  t.SF400000 = 0x2569;\n  t.SF410000 = 0x2566;\n  t.SF420000 = 0x2560;\n  t.SF430000 = 0x2550;\n  t.SF440000 = 0x256c;\n  t.SF450000 = 0x2567;\n  t.SF460000 = 0x2568;\n  t.SF470000 = 0x2564;\n  t.SF480000 = 0x2565;\n  t.SF490000 = 0x2559;\n  t.SF500000 = 0x2558;\n  t.SF510000 = 0x2552;\n  t.SF520000 = 0x2553;\n  t.SF530000 = 0x256b;\n  t.SF540000 = 0x256a;\n  t.Sacute = 0x015a;\n  t.Sacutedotaccent = 0x1e64;\n  t.Sampigreek = 0x03e0;\n  t.Scaron = 0x0160;\n  t.Scarondotaccent = 0x1e66;\n  t.Scaronsmall = 0xf6fd;\n  t.Scedilla = 0x015e;\n  t.Schwa = 0x018f;\n  t.Schwacyrillic = 0x04d8;\n  t.Schwadieresiscyrillic = 0x04da;\n  t.Scircle = 0x24c8;\n  t.Scircumflex = 0x015c;\n  t.Scommaaccent = 0x0218;\n  t.Sdotaccent = 0x1e60;\n  t.Sdotbelow = 0x1e62;\n  t.Sdotbelowdotaccent = 0x1e68;\n  t.Seharmenian = 0x054d;\n  t.Sevenroman = 0x2166;\n  t.Shaarmenian = 0x0547;\n  t.Shacyrillic = 0x0428;\n  t.Shchacyrillic = 0x0429;\n  t.Sheicoptic = 0x03e2;\n  t.Shhacyrillic = 0x04ba;\n  t.Shimacoptic = 0x03ec;\n  t.Sigma = 0x03a3;\n  t.Sixroman = 0x2165;\n  t.Smonospace = 0xff33;\n  t.Softsigncyrillic = 0x042c;\n  t.Ssmall = 0xf773;\n  t.Stigmagreek = 0x03da;\n  t.T = 0x0054;\n  t.Tau = 0x03a4;\n  t.Tbar = 0x0166;\n  t.Tcaron = 0x0164;\n  t.Tcedilla = 0x0162;\n  t.Tcircle = 0x24c9;\n  t.Tcircumflexbelow = 0x1e70;\n  t.Tcommaaccent = 0x0162;\n  t.Tdotaccent = 0x1e6a;\n  t.Tdotbelow = 0x1e6c;\n  t.Tecyrillic = 0x0422;\n  t.Tedescendercyrillic = 0x04ac;\n  t.Tenroman = 0x2169;\n  t.Tetsecyrillic = 0x04b4;\n  t.Theta = 0x0398;\n  t.Thook = 0x01ac;\n  t.Thorn = 0x00de;\n  t.Thornsmall = 0xf7fe;\n  t.Threeroman = 0x2162;\n  t.Tildesmall = 0xf6fe;\n  t.Tiwnarmenian = 0x054f;\n  t.Tlinebelow = 0x1e6e;\n  t.Tmonospace = 0xff34;\n  t.Toarmenian = 0x0539;\n  t.Tonefive = 0x01bc;\n  t.Tonesix = 0x0184;\n  t.Tonetwo = 0x01a7;\n  t.Tretroflexhook = 0x01ae;\n  t.Tsecyrillic = 0x0426;\n  t.Tshecyrillic = 0x040b;\n  t.Tsmall = 0xf774;\n  t.Twelveroman = 0x216b;\n  t.Tworoman = 0x2161;\n  t.U = 0x0055;\n  t.Uacute = 0x00da;\n  t.Uacutesmall = 0xf7fa;\n  t.Ubreve = 0x016c;\n  t.Ucaron = 0x01d3;\n  t.Ucircle = 0x24ca;\n  t.Ucircumflex = 0x00db;\n  t.Ucircumflexbelow = 0x1e76;\n  t.Ucircumflexsmall = 0xf7fb;\n  t.Ucyrillic = 0x0423;\n  t.Udblacute = 0x0170;\n  t.Udblgrave = 0x0214;\n  t.Udieresis = 0x00dc;\n  t.Udieresisacute = 0x01d7;\n  t.Udieresisbelow = 0x1e72;\n  t.Udieresiscaron = 0x01d9;\n  t.Udieresiscyrillic = 0x04f0;\n  t.Udieresisgrave = 0x01db;\n  t.Udieresismacron = 0x01d5;\n  t.Udieresissmall = 0xf7fc;\n  t.Udotbelow = 0x1ee4;\n  t.Ugrave = 0x00d9;\n  t.Ugravesmall = 0xf7f9;\n  t.Uhookabove = 0x1ee6;\n  t.Uhorn = 0x01af;\n  t.Uhornacute = 0x1ee8;\n  t.Uhorndotbelow = 0x1ef0;\n  t.Uhorngrave = 0x1eea;\n  t.Uhornhookabove = 0x1eec;\n  t.Uhorntilde = 0x1eee;\n  t.Uhungarumlaut = 0x0170;\n  t.Uhungarumlautcyrillic = 0x04f2;\n  t.Uinvertedbreve = 0x0216;\n  t.Ukcyrillic = 0x0478;\n  t.Umacron = 0x016a;\n  t.Umacroncyrillic = 0x04ee;\n  t.Umacrondieresis = 0x1e7a;\n  t.Umonospace = 0xff35;\n  t.Uogonek = 0x0172;\n  t.Upsilon = 0x03a5;\n  t.Upsilon1 = 0x03d2;\n  t.Upsilonacutehooksymbolgreek = 0x03d3;\n  t.Upsilonafrican = 0x01b1;\n  t.Upsilondieresis = 0x03ab;\n  t.Upsilondieresishooksymbolgreek = 0x03d4;\n  t.Upsilonhooksymbol = 0x03d2;\n  t.Upsilontonos = 0x038e;\n  t.Uring = 0x016e;\n  t.Ushortcyrillic = 0x040e;\n  t.Usmall = 0xf775;\n  t.Ustraightcyrillic = 0x04ae;\n  t.Ustraightstrokecyrillic = 0x04b0;\n  t.Utilde = 0x0168;\n  t.Utildeacute = 0x1e78;\n  t.Utildebelow = 0x1e74;\n  t.V = 0x0056;\n  t.Vcircle = 0x24cb;\n  t.Vdotbelow = 0x1e7e;\n  t.Vecyrillic = 0x0412;\n  t.Vewarmenian = 0x054e;\n  t.Vhook = 0x01b2;\n  t.Vmonospace = 0xff36;\n  t.Voarmenian = 0x0548;\n  t.Vsmall = 0xf776;\n  t.Vtilde = 0x1e7c;\n  t.W = 0x0057;\n  t.Wacute = 0x1e82;\n  t.Wcircle = 0x24cc;\n  t.Wcircumflex = 0x0174;\n  t.Wdieresis = 0x1e84;\n  t.Wdotaccent = 0x1e86;\n  t.Wdotbelow = 0x1e88;\n  t.Wgrave = 0x1e80;\n  t.Wmonospace = 0xff37;\n  t.Wsmall = 0xf777;\n  t.X = 0x0058;\n  t.Xcircle = 0x24cd;\n  t.Xdieresis = 0x1e8c;\n  t.Xdotaccent = 0x1e8a;\n  t.Xeharmenian = 0x053d;\n  t.Xi = 0x039e;\n  t.Xmonospace = 0xff38;\n  t.Xsmall = 0xf778;\n  t.Y = 0x0059;\n  t.Yacute = 0x00dd;\n  t.Yacutesmall = 0xf7fd;\n  t.Yatcyrillic = 0x0462;\n  t.Ycircle = 0x24ce;\n  t.Ycircumflex = 0x0176;\n  t.Ydieresis = 0x0178;\n  t.Ydieresissmall = 0xf7ff;\n  t.Ydotaccent = 0x1e8e;\n  t.Ydotbelow = 0x1ef4;\n  t.Yericyrillic = 0x042b;\n  t.Yerudieresiscyrillic = 0x04f8;\n  t.Ygrave = 0x1ef2;\n  t.Yhook = 0x01b3;\n  t.Yhookabove = 0x1ef6;\n  t.Yiarmenian = 0x0545;\n  t.Yicyrillic = 0x0407;\n  t.Yiwnarmenian = 0x0552;\n  t.Ymonospace = 0xff39;\n  t.Ysmall = 0xf779;\n  t.Ytilde = 0x1ef8;\n  t.Yusbigcyrillic = 0x046a;\n  t.Yusbigiotifiedcyrillic = 0x046c;\n  t.Yuslittlecyrillic = 0x0466;\n  t.Yuslittleiotifiedcyrillic = 0x0468;\n  t.Z = 0x005a;\n  t.Zaarmenian = 0x0536;\n  t.Zacute = 0x0179;\n  t.Zcaron = 0x017d;\n  t.Zcaronsmall = 0xf6ff;\n  t.Zcircle = 0x24cf;\n  t.Zcircumflex = 0x1e90;\n  t.Zdot = 0x017b;\n  t.Zdotaccent = 0x017b;\n  t.Zdotbelow = 0x1e92;\n  t.Zecyrillic = 0x0417;\n  t.Zedescendercyrillic = 0x0498;\n  t.Zedieresiscyrillic = 0x04de;\n  t.Zeta = 0x0396;\n  t.Zhearmenian = 0x053a;\n  t.Zhebrevecyrillic = 0x04c1;\n  t.Zhecyrillic = 0x0416;\n  t.Zhedescendercyrillic = 0x0496;\n  t.Zhedieresiscyrillic = 0x04dc;\n  t.Zlinebelow = 0x1e94;\n  t.Zmonospace = 0xff3a;\n  t.Zsmall = 0xf77a;\n  t.Zstroke = 0x01b5;\n  t.a = 0x0061;\n  t.aabengali = 0x0986;\n  t.aacute = 0x00e1;\n  t.aadeva = 0x0906;\n  t.aagujarati = 0x0a86;\n  t.aagurmukhi = 0x0a06;\n  t.aamatragurmukhi = 0x0a3e;\n  t.aarusquare = 0x3303;\n  t.aavowelsignbengali = 0x09be;\n  t.aavowelsigndeva = 0x093e;\n  t.aavowelsigngujarati = 0x0abe;\n  t.abbreviationmarkarmenian = 0x055f;\n  t.abbreviationsigndeva = 0x0970;\n  t.abengali = 0x0985;\n  t.abopomofo = 0x311a;\n  t.abreve = 0x0103;\n  t.abreveacute = 0x1eaf;\n  t.abrevecyrillic = 0x04d1;\n  t.abrevedotbelow = 0x1eb7;\n  t.abrevegrave = 0x1eb1;\n  t.abrevehookabove = 0x1eb3;\n  t.abrevetilde = 0x1eb5;\n  t.acaron = 0x01ce;\n  t.acircle = 0x24d0;\n  t.acircumflex = 0x00e2;\n  t.acircumflexacute = 0x1ea5;\n  t.acircumflexdotbelow = 0x1ead;\n  t.acircumflexgrave = 0x1ea7;\n  t.acircumflexhookabove = 0x1ea9;\n  t.acircumflextilde = 0x1eab;\n  t.acute = 0x00b4;\n  t.acutebelowcmb = 0x0317;\n  t.acutecmb = 0x0301;\n  t.acutecomb = 0x0301;\n  t.acutedeva = 0x0954;\n  t.acutelowmod = 0x02cf;\n  t.acutetonecmb = 0x0341;\n  t.acyrillic = 0x0430;\n  t.adblgrave = 0x0201;\n  t.addakgurmukhi = 0x0a71;\n  t.adeva = 0x0905;\n  t.adieresis = 0x00e4;\n  t.adieresiscyrillic = 0x04d3;\n  t.adieresismacron = 0x01df;\n  t.adotbelow = 0x1ea1;\n  t.adotmacron = 0x01e1;\n  t.ae = 0x00e6;\n  t.aeacute = 0x01fd;\n  t.aekorean = 0x3150;\n  t.aemacron = 0x01e3;\n  t.afii00208 = 0x2015;\n  t.afii08941 = 0x20a4;\n  t.afii10017 = 0x0410;\n  t.afii10018 = 0x0411;\n  t.afii10019 = 0x0412;\n  t.afii10020 = 0x0413;\n  t.afii10021 = 0x0414;\n  t.afii10022 = 0x0415;\n  t.afii10023 = 0x0401;\n  t.afii10024 = 0x0416;\n  t.afii10025 = 0x0417;\n  t.afii10026 = 0x0418;\n  t.afii10027 = 0x0419;\n  t.afii10028 = 0x041a;\n  t.afii10029 = 0x041b;\n  t.afii10030 = 0x041c;\n  t.afii10031 = 0x041d;\n  t.afii10032 = 0x041e;\n  t.afii10033 = 0x041f;\n  t.afii10034 = 0x0420;\n  t.afii10035 = 0x0421;\n  t.afii10036 = 0x0422;\n  t.afii10037 = 0x0423;\n  t.afii10038 = 0x0424;\n  t.afii10039 = 0x0425;\n  t.afii10040 = 0x0426;\n  t.afii10041 = 0x0427;\n  t.afii10042 = 0x0428;\n  t.afii10043 = 0x0429;\n  t.afii10044 = 0x042a;\n  t.afii10045 = 0x042b;\n  t.afii10046 = 0x042c;\n  t.afii10047 = 0x042d;\n  t.afii10048 = 0x042e;\n  t.afii10049 = 0x042f;\n  t.afii10050 = 0x0490;\n  t.afii10051 = 0x0402;\n  t.afii10052 = 0x0403;\n  t.afii10053 = 0x0404;\n  t.afii10054 = 0x0405;\n  t.afii10055 = 0x0406;\n  t.afii10056 = 0x0407;\n  t.afii10057 = 0x0408;\n  t.afii10058 = 0x0409;\n  t.afii10059 = 0x040a;\n  t.afii10060 = 0x040b;\n  t.afii10061 = 0x040c;\n  t.afii10062 = 0x040e;\n  t.afii10063 = 0xf6c4;\n  t.afii10064 = 0xf6c5;\n  t.afii10065 = 0x0430;\n  t.afii10066 = 0x0431;\n  t.afii10067 = 0x0432;\n  t.afii10068 = 0x0433;\n  t.afii10069 = 0x0434;\n  t.afii10070 = 0x0435;\n  t.afii10071 = 0x0451;\n  t.afii10072 = 0x0436;\n  t.afii10073 = 0x0437;\n  t.afii10074 = 0x0438;\n  t.afii10075 = 0x0439;\n  t.afii10076 = 0x043a;\n  t.afii10077 = 0x043b;\n  t.afii10078 = 0x043c;\n  t.afii10079 = 0x043d;\n  t.afii10080 = 0x043e;\n  t.afii10081 = 0x043f;\n  t.afii10082 = 0x0440;\n  t.afii10083 = 0x0441;\n  t.afii10084 = 0x0442;\n  t.afii10085 = 0x0443;\n  t.afii10086 = 0x0444;\n  t.afii10087 = 0x0445;\n  t.afii10088 = 0x0446;\n  t.afii10089 = 0x0447;\n  t.afii10090 = 0x0448;\n  t.afii10091 = 0x0449;\n  t.afii10092 = 0x044a;\n  t.afii10093 = 0x044b;\n  t.afii10094 = 0x044c;\n  t.afii10095 = 0x044d;\n  t.afii10096 = 0x044e;\n  t.afii10097 = 0x044f;\n  t.afii10098 = 0x0491;\n  t.afii10099 = 0x0452;\n  t.afii10100 = 0x0453;\n  t.afii10101 = 0x0454;\n  t.afii10102 = 0x0455;\n  t.afii10103 = 0x0456;\n  t.afii10104 = 0x0457;\n  t.afii10105 = 0x0458;\n  t.afii10106 = 0x0459;\n  t.afii10107 = 0x045a;\n  t.afii10108 = 0x045b;\n  t.afii10109 = 0x045c;\n  t.afii10110 = 0x045e;\n  t.afii10145 = 0x040f;\n  t.afii10146 = 0x0462;\n  t.afii10147 = 0x0472;\n  t.afii10148 = 0x0474;\n  t.afii10192 = 0xf6c6;\n  t.afii10193 = 0x045f;\n  t.afii10194 = 0x0463;\n  t.afii10195 = 0x0473;\n  t.afii10196 = 0x0475;\n  t.afii10831 = 0xf6c7;\n  t.afii10832 = 0xf6c8;\n  t.afii10846 = 0x04d9;\n  t.afii299 = 0x200e;\n  t.afii300 = 0x200f;\n  t.afii301 = 0x200d;\n  t.afii57381 = 0x066a;\n  t.afii57388 = 0x060c;\n  t.afii57392 = 0x0660;\n  t.afii57393 = 0x0661;\n  t.afii57394 = 0x0662;\n  t.afii57395 = 0x0663;\n  t.afii57396 = 0x0664;\n  t.afii57397 = 0x0665;\n  t.afii57398 = 0x0666;\n  t.afii57399 = 0x0667;\n  t.afii57400 = 0x0668;\n  t.afii57401 = 0x0669;\n  t.afii57403 = 0x061b;\n  t.afii57407 = 0x061f;\n  t.afii57409 = 0x0621;\n  t.afii57410 = 0x0622;\n  t.afii57411 = 0x0623;\n  t.afii57412 = 0x0624;\n  t.afii57413 = 0x0625;\n  t.afii57414 = 0x0626;\n  t.afii57415 = 0x0627;\n  t.afii57416 = 0x0628;\n  t.afii57417 = 0x0629;\n  t.afii57418 = 0x062a;\n  t.afii57419 = 0x062b;\n  t.afii57420 = 0x062c;\n  t.afii57421 = 0x062d;\n  t.afii57422 = 0x062e;\n  t.afii57423 = 0x062f;\n  t.afii57424 = 0x0630;\n  t.afii57425 = 0x0631;\n  t.afii57426 = 0x0632;\n  t.afii57427 = 0x0633;\n  t.afii57428 = 0x0634;\n  t.afii57429 = 0x0635;\n  t.afii57430 = 0x0636;\n  t.afii57431 = 0x0637;\n  t.afii57432 = 0x0638;\n  t.afii57433 = 0x0639;\n  t.afii57434 = 0x063a;\n  t.afii57440 = 0x0640;\n  t.afii57441 = 0x0641;\n  t.afii57442 = 0x0642;\n  t.afii57443 = 0x0643;\n  t.afii57444 = 0x0644;\n  t.afii57445 = 0x0645;\n  t.afii57446 = 0x0646;\n  t.afii57448 = 0x0648;\n  t.afii57449 = 0x0649;\n  t.afii57450 = 0x064a;\n  t.afii57451 = 0x064b;\n  t.afii57452 = 0x064c;\n  t.afii57453 = 0x064d;\n  t.afii57454 = 0x064e;\n  t.afii57455 = 0x064f;\n  t.afii57456 = 0x0650;\n  t.afii57457 = 0x0651;\n  t.afii57458 = 0x0652;\n  t.afii57470 = 0x0647;\n  t.afii57505 = 0x06a4;\n  t.afii57506 = 0x067e;\n  t.afii57507 = 0x0686;\n  t.afii57508 = 0x0698;\n  t.afii57509 = 0x06af;\n  t.afii57511 = 0x0679;\n  t.afii57512 = 0x0688;\n  t.afii57513 = 0x0691;\n  t.afii57514 = 0x06ba;\n  t.afii57519 = 0x06d2;\n  t.afii57534 = 0x06d5;\n  t.afii57636 = 0x20aa;\n  t.afii57645 = 0x05be;\n  t.afii57658 = 0x05c3;\n  t.afii57664 = 0x05d0;\n  t.afii57665 = 0x05d1;\n  t.afii57666 = 0x05d2;\n  t.afii57667 = 0x05d3;\n  t.afii57668 = 0x05d4;\n  t.afii57669 = 0x05d5;\n  t.afii57670 = 0x05d6;\n  t.afii57671 = 0x05d7;\n  t.afii57672 = 0x05d8;\n  t.afii57673 = 0x05d9;\n  t.afii57674 = 0x05da;\n  t.afii57675 = 0x05db;\n  t.afii57676 = 0x05dc;\n  t.afii57677 = 0x05dd;\n  t.afii57678 = 0x05de;\n  t.afii57679 = 0x05df;\n  t.afii57680 = 0x05e0;\n  t.afii57681 = 0x05e1;\n  t.afii57682 = 0x05e2;\n  t.afii57683 = 0x05e3;\n  t.afii57684 = 0x05e4;\n  t.afii57685 = 0x05e5;\n  t.afii57686 = 0x05e6;\n  t.afii57687 = 0x05e7;\n  t.afii57688 = 0x05e8;\n  t.afii57689 = 0x05e9;\n  t.afii57690 = 0x05ea;\n  t.afii57694 = 0xfb2a;\n  t.afii57695 = 0xfb2b;\n  t.afii57700 = 0xfb4b;\n  t.afii57705 = 0xfb1f;\n  t.afii57716 = 0x05f0;\n  t.afii57717 = 0x05f1;\n  t.afii57718 = 0x05f2;\n  t.afii57723 = 0xfb35;\n  t.afii57793 = 0x05b4;\n  t.afii57794 = 0x05b5;\n  t.afii57795 = 0x05b6;\n  t.afii57796 = 0x05bb;\n  t.afii57797 = 0x05b8;\n  t.afii57798 = 0x05b7;\n  t.afii57799 = 0x05b0;\n  t.afii57800 = 0x05b2;\n  t.afii57801 = 0x05b1;\n  t.afii57802 = 0x05b3;\n  t.afii57803 = 0x05c2;\n  t.afii57804 = 0x05c1;\n  t.afii57806 = 0x05b9;\n  t.afii57807 = 0x05bc;\n  t.afii57839 = 0x05bd;\n  t.afii57841 = 0x05bf;\n  t.afii57842 = 0x05c0;\n  t.afii57929 = 0x02bc;\n  t.afii61248 = 0x2105;\n  t.afii61289 = 0x2113;\n  t.afii61352 = 0x2116;\n  t.afii61573 = 0x202c;\n  t.afii61574 = 0x202d;\n  t.afii61575 = 0x202e;\n  t.afii61664 = 0x200c;\n  t.afii63167 = 0x066d;\n  t.afii64937 = 0x02bd;\n  t.agrave = 0x00e0;\n  t.agujarati = 0x0a85;\n  t.agurmukhi = 0x0a05;\n  t.ahiragana = 0x3042;\n  t.ahookabove = 0x1ea3;\n  t.aibengali = 0x0990;\n  t.aibopomofo = 0x311e;\n  t.aideva = 0x0910;\n  t.aiecyrillic = 0x04d5;\n  t.aigujarati = 0x0a90;\n  t.aigurmukhi = 0x0a10;\n  t.aimatragurmukhi = 0x0a48;\n  t.ainarabic = 0x0639;\n  t.ainfinalarabic = 0xfeca;\n  t.aininitialarabic = 0xfecb;\n  t.ainmedialarabic = 0xfecc;\n  t.ainvertedbreve = 0x0203;\n  t.aivowelsignbengali = 0x09c8;\n  t.aivowelsigndeva = 0x0948;\n  t.aivowelsigngujarati = 0x0ac8;\n  t.akatakana = 0x30a2;\n  t.akatakanahalfwidth = 0xff71;\n  t.akorean = 0x314f;\n  t.alef = 0x05d0;\n  t.alefarabic = 0x0627;\n  t.alefdageshhebrew = 0xfb30;\n  t.aleffinalarabic = 0xfe8e;\n  t.alefhamzaabovearabic = 0x0623;\n  t.alefhamzaabovefinalarabic = 0xfe84;\n  t.alefhamzabelowarabic = 0x0625;\n  t.alefhamzabelowfinalarabic = 0xfe88;\n  t.alefhebrew = 0x05d0;\n  t.aleflamedhebrew = 0xfb4f;\n  t.alefmaddaabovearabic = 0x0622;\n  t.alefmaddaabovefinalarabic = 0xfe82;\n  t.alefmaksuraarabic = 0x0649;\n  t.alefmaksurafinalarabic = 0xfef0;\n  t.alefmaksurainitialarabic = 0xfef3;\n  t.alefmaksuramedialarabic = 0xfef4;\n  t.alefpatahhebrew = 0xfb2e;\n  t.alefqamatshebrew = 0xfb2f;\n  t.aleph = 0x2135;\n  t.allequal = 0x224c;\n  t.alpha = 0x03b1;\n  t.alphatonos = 0x03ac;\n  t.amacron = 0x0101;\n  t.amonospace = 0xff41;\n  t.ampersand = 0x0026;\n  t.ampersandmonospace = 0xff06;\n  t.ampersandsmall = 0xf726;\n  t.amsquare = 0x33c2;\n  t.anbopomofo = 0x3122;\n  t.angbopomofo = 0x3124;\n  t.angbracketleft = 0x3008;\n  t.angbracketright = 0x3009;\n  t.angkhankhuthai = 0x0e5a;\n  t.angle = 0x2220;\n  t.anglebracketleft = 0x3008;\n  t.anglebracketleftvertical = 0xfe3f;\n  t.anglebracketright = 0x3009;\n  t.anglebracketrightvertical = 0xfe40;\n  t.angleleft = 0x2329;\n  t.angleright = 0x232a;\n  t.angstrom = 0x212b;\n  t.anoteleia = 0x0387;\n  t.anudattadeva = 0x0952;\n  t.anusvarabengali = 0x0982;\n  t.anusvaradeva = 0x0902;\n  t.anusvaragujarati = 0x0a82;\n  t.aogonek = 0x0105;\n  t.apaatosquare = 0x3300;\n  t.aparen = 0x249c;\n  t.apostrophearmenian = 0x055a;\n  t.apostrophemod = 0x02bc;\n  t.apple = 0xf8ff;\n  t.approaches = 0x2250;\n  t.approxequal = 0x2248;\n  t.approxequalorimage = 0x2252;\n  t.approximatelyequal = 0x2245;\n  t.araeaekorean = 0x318e;\n  t.araeakorean = 0x318d;\n  t.arc = 0x2312;\n  t.arighthalfring = 0x1e9a;\n  t.aring = 0x00e5;\n  t.aringacute = 0x01fb;\n  t.aringbelow = 0x1e01;\n  t.arrowboth = 0x2194;\n  t.arrowdashdown = 0x21e3;\n  t.arrowdashleft = 0x21e0;\n  t.arrowdashright = 0x21e2;\n  t.arrowdashup = 0x21e1;\n  t.arrowdblboth = 0x21d4;\n  t.arrowdbldown = 0x21d3;\n  t.arrowdblleft = 0x21d0;\n  t.arrowdblright = 0x21d2;\n  t.arrowdblup = 0x21d1;\n  t.arrowdown = 0x2193;\n  t.arrowdownleft = 0x2199;\n  t.arrowdownright = 0x2198;\n  t.arrowdownwhite = 0x21e9;\n  t.arrowheaddownmod = 0x02c5;\n  t.arrowheadleftmod = 0x02c2;\n  t.arrowheadrightmod = 0x02c3;\n  t.arrowheadupmod = 0x02c4;\n  t.arrowhorizex = 0xf8e7;\n  t.arrowleft = 0x2190;\n  t.arrowleftdbl = 0x21d0;\n  t.arrowleftdblstroke = 0x21cd;\n  t.arrowleftoverright = 0x21c6;\n  t.arrowleftwhite = 0x21e6;\n  t.arrowright = 0x2192;\n  t.arrowrightdblstroke = 0x21cf;\n  t.arrowrightheavy = 0x279e;\n  t.arrowrightoverleft = 0x21c4;\n  t.arrowrightwhite = 0x21e8;\n  t.arrowtableft = 0x21e4;\n  t.arrowtabright = 0x21e5;\n  t.arrowup = 0x2191;\n  t.arrowupdn = 0x2195;\n  t.arrowupdnbse = 0x21a8;\n  t.arrowupdownbase = 0x21a8;\n  t.arrowupleft = 0x2196;\n  t.arrowupleftofdown = 0x21c5;\n  t.arrowupright = 0x2197;\n  t.arrowupwhite = 0x21e7;\n  t.arrowvertex = 0xf8e6;\n  t.asciicircum = 0x005e;\n  t.asciicircummonospace = 0xff3e;\n  t.asciitilde = 0x007e;\n  t.asciitildemonospace = 0xff5e;\n  t.ascript = 0x0251;\n  t.ascriptturned = 0x0252;\n  t.asmallhiragana = 0x3041;\n  t.asmallkatakana = 0x30a1;\n  t.asmallkatakanahalfwidth = 0xff67;\n  t.asterisk = 0x002a;\n  t.asteriskaltonearabic = 0x066d;\n  t.asteriskarabic = 0x066d;\n  t.asteriskmath = 0x2217;\n  t.asteriskmonospace = 0xff0a;\n  t.asterisksmall = 0xfe61;\n  t.asterism = 0x2042;\n  t.asuperior = 0xf6e9;\n  t.asymptoticallyequal = 0x2243;\n  t.at = 0x0040;\n  t.atilde = 0x00e3;\n  t.atmonospace = 0xff20;\n  t.atsmall = 0xfe6b;\n  t.aturned = 0x0250;\n  t.aubengali = 0x0994;\n  t.aubopomofo = 0x3120;\n  t.audeva = 0x0914;\n  t.augujarati = 0x0a94;\n  t.augurmukhi = 0x0a14;\n  t.aulengthmarkbengali = 0x09d7;\n  t.aumatragurmukhi = 0x0a4c;\n  t.auvowelsignbengali = 0x09cc;\n  t.auvowelsigndeva = 0x094c;\n  t.auvowelsigngujarati = 0x0acc;\n  t.avagrahadeva = 0x093d;\n  t.aybarmenian = 0x0561;\n  t.ayin = 0x05e2;\n  t.ayinaltonehebrew = 0xfb20;\n  t.ayinhebrew = 0x05e2;\n  t.b = 0x0062;\n  t.babengali = 0x09ac;\n  t.backslash = 0x005c;\n  t.backslashmonospace = 0xff3c;\n  t.badeva = 0x092c;\n  t.bagujarati = 0x0aac;\n  t.bagurmukhi = 0x0a2c;\n  t.bahiragana = 0x3070;\n  t.bahtthai = 0x0e3f;\n  t.bakatakana = 0x30d0;\n  t.bar = 0x007c;\n  t.barmonospace = 0xff5c;\n  t.bbopomofo = 0x3105;\n  t.bcircle = 0x24d1;\n  t.bdotaccent = 0x1e03;\n  t.bdotbelow = 0x1e05;\n  t.beamedsixteenthnotes = 0x266c;\n  t.because = 0x2235;\n  t.becyrillic = 0x0431;\n  t.beharabic = 0x0628;\n  t.behfinalarabic = 0xfe90;\n  t.behinitialarabic = 0xfe91;\n  t.behiragana = 0x3079;\n  t.behmedialarabic = 0xfe92;\n  t.behmeeminitialarabic = 0xfc9f;\n  t.behmeemisolatedarabic = 0xfc08;\n  t.behnoonfinalarabic = 0xfc6d;\n  t.bekatakana = 0x30d9;\n  t.benarmenian = 0x0562;\n  t.bet = 0x05d1;\n  t.beta = 0x03b2;\n  t.betasymbolgreek = 0x03d0;\n  t.betdagesh = 0xfb31;\n  t.betdageshhebrew = 0xfb31;\n  t.bethebrew = 0x05d1;\n  t.betrafehebrew = 0xfb4c;\n  t.bhabengali = 0x09ad;\n  t.bhadeva = 0x092d;\n  t.bhagujarati = 0x0aad;\n  t.bhagurmukhi = 0x0a2d;\n  t.bhook = 0x0253;\n  t.bihiragana = 0x3073;\n  t.bikatakana = 0x30d3;\n  t.bilabialclick = 0x0298;\n  t.bindigurmukhi = 0x0a02;\n  t.birusquare = 0x3331;\n  t.blackcircle = 0x25cf;\n  t.blackdiamond = 0x25c6;\n  t.blackdownpointingtriangle = 0x25bc;\n  t.blackleftpointingpointer = 0x25c4;\n  t.blackleftpointingtriangle = 0x25c0;\n  t.blacklenticularbracketleft = 0x3010;\n  t.blacklenticularbracketleftvertical = 0xfe3b;\n  t.blacklenticularbracketright = 0x3011;\n  t.blacklenticularbracketrightvertical = 0xfe3c;\n  t.blacklowerlefttriangle = 0x25e3;\n  t.blacklowerrighttriangle = 0x25e2;\n  t.blackrectangle = 0x25ac;\n  t.blackrightpointingpointer = 0x25ba;\n  t.blackrightpointingtriangle = 0x25b6;\n  t.blacksmallsquare = 0x25aa;\n  t.blacksmilingface = 0x263b;\n  t.blacksquare = 0x25a0;\n  t.blackstar = 0x2605;\n  t.blackupperlefttriangle = 0x25e4;\n  t.blackupperrighttriangle = 0x25e5;\n  t.blackuppointingsmalltriangle = 0x25b4;\n  t.blackuppointingtriangle = 0x25b2;\n  t.blank = 0x2423;\n  t.blinebelow = 0x1e07;\n  t.block = 0x2588;\n  t.bmonospace = 0xff42;\n  t.bobaimaithai = 0x0e1a;\n  t.bohiragana = 0x307c;\n  t.bokatakana = 0x30dc;\n  t.bparen = 0x249d;\n  t.bqsquare = 0x33c3;\n  t.braceex = 0xf8f4;\n  t.braceleft = 0x007b;\n  t.braceleftbt = 0xf8f3;\n  t.braceleftmid = 0xf8f2;\n  t.braceleftmonospace = 0xff5b;\n  t.braceleftsmall = 0xfe5b;\n  t.bracelefttp = 0xf8f1;\n  t.braceleftvertical = 0xfe37;\n  t.braceright = 0x007d;\n  t.bracerightbt = 0xf8fe;\n  t.bracerightmid = 0xf8fd;\n  t.bracerightmonospace = 0xff5d;\n  t.bracerightsmall = 0xfe5c;\n  t.bracerighttp = 0xf8fc;\n  t.bracerightvertical = 0xfe38;\n  t.bracketleft = 0x005b;\n  t.bracketleftbt = 0xf8f0;\n  t.bracketleftex = 0xf8ef;\n  t.bracketleftmonospace = 0xff3b;\n  t.bracketlefttp = 0xf8ee;\n  t.bracketright = 0x005d;\n  t.bracketrightbt = 0xf8fb;\n  t.bracketrightex = 0xf8fa;\n  t.bracketrightmonospace = 0xff3d;\n  t.bracketrighttp = 0xf8f9;\n  t.breve = 0x02d8;\n  t.brevebelowcmb = 0x032e;\n  t.brevecmb = 0x0306;\n  t.breveinvertedbelowcmb = 0x032f;\n  t.breveinvertedcmb = 0x0311;\n  t.breveinverteddoublecmb = 0x0361;\n  t.bridgebelowcmb = 0x032a;\n  t.bridgeinvertedbelowcmb = 0x033a;\n  t.brokenbar = 0x00a6;\n  t.bstroke = 0x0180;\n  t.bsuperior = 0xf6ea;\n  t.btopbar = 0x0183;\n  t.buhiragana = 0x3076;\n  t.bukatakana = 0x30d6;\n  t.bullet = 0x2022;\n  t.bulletinverse = 0x25d8;\n  t.bulletoperator = 0x2219;\n  t.bullseye = 0x25ce;\n  t.c = 0x0063;\n  t.caarmenian = 0x056e;\n  t.cabengali = 0x099a;\n  t.cacute = 0x0107;\n  t.cadeva = 0x091a;\n  t.cagujarati = 0x0a9a;\n  t.cagurmukhi = 0x0a1a;\n  t.calsquare = 0x3388;\n  t.candrabindubengali = 0x0981;\n  t.candrabinducmb = 0x0310;\n  t.candrabindudeva = 0x0901;\n  t.candrabindugujarati = 0x0a81;\n  t.capslock = 0x21ea;\n  t.careof = 0x2105;\n  t.caron = 0x02c7;\n  t.caronbelowcmb = 0x032c;\n  t.caroncmb = 0x030c;\n  t.carriagereturn = 0x21b5;\n  t.cbopomofo = 0x3118;\n  t.ccaron = 0x010d;\n  t.ccedilla = 0x00e7;\n  t.ccedillaacute = 0x1e09;\n  t.ccircle = 0x24d2;\n  t.ccircumflex = 0x0109;\n  t.ccurl = 0x0255;\n  t.cdot = 0x010b;\n  t.cdotaccent = 0x010b;\n  t.cdsquare = 0x33c5;\n  t.cedilla = 0x00b8;\n  t.cedillacmb = 0x0327;\n  t.cent = 0x00a2;\n  t.centigrade = 0x2103;\n  t.centinferior = 0xf6df;\n  t.centmonospace = 0xffe0;\n  t.centoldstyle = 0xf7a2;\n  t.centsuperior = 0xf6e0;\n  t.chaarmenian = 0x0579;\n  t.chabengali = 0x099b;\n  t.chadeva = 0x091b;\n  t.chagujarati = 0x0a9b;\n  t.chagurmukhi = 0x0a1b;\n  t.chbopomofo = 0x3114;\n  t.cheabkhasiancyrillic = 0x04bd;\n  t.checkmark = 0x2713;\n  t.checyrillic = 0x0447;\n  t.chedescenderabkhasiancyrillic = 0x04bf;\n  t.chedescendercyrillic = 0x04b7;\n  t.chedieresiscyrillic = 0x04f5;\n  t.cheharmenian = 0x0573;\n  t.chekhakassiancyrillic = 0x04cc;\n  t.cheverticalstrokecyrillic = 0x04b9;\n  t.chi = 0x03c7;\n  t.chieuchacirclekorean = 0x3277;\n  t.chieuchaparenkorean = 0x3217;\n  t.chieuchcirclekorean = 0x3269;\n  t.chieuchkorean = 0x314a;\n  t.chieuchparenkorean = 0x3209;\n  t.chochangthai = 0x0e0a;\n  t.chochanthai = 0x0e08;\n  t.chochingthai = 0x0e09;\n  t.chochoethai = 0x0e0c;\n  t.chook = 0x0188;\n  t.cieucacirclekorean = 0x3276;\n  t.cieucaparenkorean = 0x3216;\n  t.cieuccirclekorean = 0x3268;\n  t.cieuckorean = 0x3148;\n  t.cieucparenkorean = 0x3208;\n  t.cieucuparenkorean = 0x321c;\n  t.circle = 0x25cb;\n  t.circlecopyrt = 0x00a9;\n  t.circlemultiply = 0x2297;\n  t.circleot = 0x2299;\n  t.circleplus = 0x2295;\n  t.circlepostalmark = 0x3036;\n  t.circlewithlefthalfblack = 0x25d0;\n  t.circlewithrighthalfblack = 0x25d1;\n  t.circumflex = 0x02c6;\n  t.circumflexbelowcmb = 0x032d;\n  t.circumflexcmb = 0x0302;\n  t.clear = 0x2327;\n  t.clickalveolar = 0x01c2;\n  t.clickdental = 0x01c0;\n  t.clicklateral = 0x01c1;\n  t.clickretroflex = 0x01c3;\n  t.club = 0x2663;\n  t.clubsuitblack = 0x2663;\n  t.clubsuitwhite = 0x2667;\n  t.cmcubedsquare = 0x33a4;\n  t.cmonospace = 0xff43;\n  t.cmsquaredsquare = 0x33a0;\n  t.coarmenian = 0x0581;\n  t.colon = 0x003a;\n  t.colonmonetary = 0x20a1;\n  t.colonmonospace = 0xff1a;\n  t.colonsign = 0x20a1;\n  t.colonsmall = 0xfe55;\n  t.colontriangularhalfmod = 0x02d1;\n  t.colontriangularmod = 0x02d0;\n  t.comma = 0x002c;\n  t.commaabovecmb = 0x0313;\n  t.commaaboverightcmb = 0x0315;\n  t.commaaccent = 0xf6c3;\n  t.commaarabic = 0x060c;\n  t.commaarmenian = 0x055d;\n  t.commainferior = 0xf6e1;\n  t.commamonospace = 0xff0c;\n  t.commareversedabovecmb = 0x0314;\n  t.commareversedmod = 0x02bd;\n  t.commasmall = 0xfe50;\n  t.commasuperior = 0xf6e2;\n  t.commaturnedabovecmb = 0x0312;\n  t.commaturnedmod = 0x02bb;\n  t.compass = 0x263c;\n  t.congruent = 0x2245;\n  t.contourintegral = 0x222e;\n  t.control = 0x2303;\n  t.controlACK = 0x0006;\n  t.controlBEL = 0x0007;\n  t.controlBS = 0x0008;\n  t.controlCAN = 0x0018;\n  t.controlCR = 0x000d;\n  t.controlDC1 = 0x0011;\n  t.controlDC2 = 0x0012;\n  t.controlDC3 = 0x0013;\n  t.controlDC4 = 0x0014;\n  t.controlDEL = 0x007f;\n  t.controlDLE = 0x0010;\n  t.controlEM = 0x0019;\n  t.controlENQ = 0x0005;\n  t.controlEOT = 0x0004;\n  t.controlESC = 0x001b;\n  t.controlETB = 0x0017;\n  t.controlETX = 0x0003;\n  t.controlFF = 0x000c;\n  t.controlFS = 0x001c;\n  t.controlGS = 0x001d;\n  t.controlHT = 0x0009;\n  t.controlLF = 0x000a;\n  t.controlNAK = 0x0015;\n  t.controlNULL = 0x0000;\n  t.controlRS = 0x001e;\n  t.controlSI = 0x000f;\n  t.controlSO = 0x000e;\n  t.controlSOT = 0x0002;\n  t.controlSTX = 0x0001;\n  t.controlSUB = 0x001a;\n  t.controlSYN = 0x0016;\n  t.controlUS = 0x001f;\n  t.controlVT = 0x000b;\n  t.copyright = 0x00a9;\n  t.copyrightsans = 0xf8e9;\n  t.copyrightserif = 0xf6d9;\n  t.cornerbracketleft = 0x300c;\n  t.cornerbracketlefthalfwidth = 0xff62;\n  t.cornerbracketleftvertical = 0xfe41;\n  t.cornerbracketright = 0x300d;\n  t.cornerbracketrighthalfwidth = 0xff63;\n  t.cornerbracketrightvertical = 0xfe42;\n  t.corporationsquare = 0x337f;\n  t.cosquare = 0x33c7;\n  t.coverkgsquare = 0x33c6;\n  t.cparen = 0x249e;\n  t.cruzeiro = 0x20a2;\n  t.cstretched = 0x0297;\n  t.curlyand = 0x22cf;\n  t.curlyor = 0x22ce;\n  t.currency = 0x00a4;\n  t.cyrBreve = 0xf6d1;\n  t.cyrFlex = 0xf6d2;\n  t.cyrbreve = 0xf6d4;\n  t.cyrflex = 0xf6d5;\n  t.d = 0x0064;\n  t.daarmenian = 0x0564;\n  t.dabengali = 0x09a6;\n  t.dadarabic = 0x0636;\n  t.dadeva = 0x0926;\n  t.dadfinalarabic = 0xfebe;\n  t.dadinitialarabic = 0xfebf;\n  t.dadmedialarabic = 0xfec0;\n  t.dagesh = 0x05bc;\n  t.dageshhebrew = 0x05bc;\n  t.dagger = 0x2020;\n  t.daggerdbl = 0x2021;\n  t.dagujarati = 0x0aa6;\n  t.dagurmukhi = 0x0a26;\n  t.dahiragana = 0x3060;\n  t.dakatakana = 0x30c0;\n  t.dalarabic = 0x062f;\n  t.dalet = 0x05d3;\n  t.daletdagesh = 0xfb33;\n  t.daletdageshhebrew = 0xfb33;\n  t.dalethebrew = 0x05d3;\n  t.dalfinalarabic = 0xfeaa;\n  t.dammaarabic = 0x064f;\n  t.dammalowarabic = 0x064f;\n  t.dammatanaltonearabic = 0x064c;\n  t.dammatanarabic = 0x064c;\n  t.danda = 0x0964;\n  t.dargahebrew = 0x05a7;\n  t.dargalefthebrew = 0x05a7;\n  t.dasiapneumatacyrilliccmb = 0x0485;\n  t.dblGrave = 0xf6d3;\n  t.dblanglebracketleft = 0x300a;\n  t.dblanglebracketleftvertical = 0xfe3d;\n  t.dblanglebracketright = 0x300b;\n  t.dblanglebracketrightvertical = 0xfe3e;\n  t.dblarchinvertedbelowcmb = 0x032b;\n  t.dblarrowleft = 0x21d4;\n  t.dblarrowright = 0x21d2;\n  t.dbldanda = 0x0965;\n  t.dblgrave = 0xf6d6;\n  t.dblgravecmb = 0x030f;\n  t.dblintegral = 0x222c;\n  t.dbllowline = 0x2017;\n  t.dbllowlinecmb = 0x0333;\n  t.dbloverlinecmb = 0x033f;\n  t.dblprimemod = 0x02ba;\n  t.dblverticalbar = 0x2016;\n  t.dblverticallineabovecmb = 0x030e;\n  t.dbopomofo = 0x3109;\n  t.dbsquare = 0x33c8;\n  t.dcaron = 0x010f;\n  t.dcedilla = 0x1e11;\n  t.dcircle = 0x24d3;\n  t.dcircumflexbelow = 0x1e13;\n  t.dcroat = 0x0111;\n  t.ddabengali = 0x09a1;\n  t.ddadeva = 0x0921;\n  t.ddagujarati = 0x0aa1;\n  t.ddagurmukhi = 0x0a21;\n  t.ddalarabic = 0x0688;\n  t.ddalfinalarabic = 0xfb89;\n  t.dddhadeva = 0x095c;\n  t.ddhabengali = 0x09a2;\n  t.ddhadeva = 0x0922;\n  t.ddhagujarati = 0x0aa2;\n  t.ddhagurmukhi = 0x0a22;\n  t.ddotaccent = 0x1e0b;\n  t.ddotbelow = 0x1e0d;\n  t.decimalseparatorarabic = 0x066b;\n  t.decimalseparatorpersian = 0x066b;\n  t.decyrillic = 0x0434;\n  t.degree = 0x00b0;\n  t.dehihebrew = 0x05ad;\n  t.dehiragana = 0x3067;\n  t.deicoptic = 0x03ef;\n  t.dekatakana = 0x30c7;\n  t.deleteleft = 0x232b;\n  t.deleteright = 0x2326;\n  t.delta = 0x03b4;\n  t.deltaturned = 0x018d;\n  t.denominatorminusonenumeratorbengali = 0x09f8;\n  t.dezh = 0x02a4;\n  t.dhabengali = 0x09a7;\n  t.dhadeva = 0x0927;\n  t.dhagujarati = 0x0aa7;\n  t.dhagurmukhi = 0x0a27;\n  t.dhook = 0x0257;\n  t.dialytikatonos = 0x0385;\n  t.dialytikatonoscmb = 0x0344;\n  t.diamond = 0x2666;\n  t.diamondsuitwhite = 0x2662;\n  t.dieresis = 0x00a8;\n  t.dieresisacute = 0xf6d7;\n  t.dieresisbelowcmb = 0x0324;\n  t.dieresiscmb = 0x0308;\n  t.dieresisgrave = 0xf6d8;\n  t.dieresistonos = 0x0385;\n  t.dihiragana = 0x3062;\n  t.dikatakana = 0x30c2;\n  t.dittomark = 0x3003;\n  t.divide = 0x00f7;\n  t.divides = 0x2223;\n  t.divisionslash = 0x2215;\n  t.djecyrillic = 0x0452;\n  t.dkshade = 0x2593;\n  t.dlinebelow = 0x1e0f;\n  t.dlsquare = 0x3397;\n  t.dmacron = 0x0111;\n  t.dmonospace = 0xff44;\n  t.dnblock = 0x2584;\n  t.dochadathai = 0x0e0e;\n  t.dodekthai = 0x0e14;\n  t.dohiragana = 0x3069;\n  t.dokatakana = 0x30c9;\n  t.dollar = 0x0024;\n  t.dollarinferior = 0xf6e3;\n  t.dollarmonospace = 0xff04;\n  t.dollaroldstyle = 0xf724;\n  t.dollarsmall = 0xfe69;\n  t.dollarsuperior = 0xf6e4;\n  t.dong = 0x20ab;\n  t.dorusquare = 0x3326;\n  t.dotaccent = 0x02d9;\n  t.dotaccentcmb = 0x0307;\n  t.dotbelowcmb = 0x0323;\n  t.dotbelowcomb = 0x0323;\n  t.dotkatakana = 0x30fb;\n  t.dotlessi = 0x0131;\n  t.dotlessj = 0xf6be;\n  t.dotlessjstrokehook = 0x0284;\n  t.dotmath = 0x22c5;\n  t.dottedcircle = 0x25cc;\n  t.doubleyodpatah = 0xfb1f;\n  t.doubleyodpatahhebrew = 0xfb1f;\n  t.downtackbelowcmb = 0x031e;\n  t.downtackmod = 0x02d5;\n  t.dparen = 0x249f;\n  t.dsuperior = 0xf6eb;\n  t.dtail = 0x0256;\n  t.dtopbar = 0x018c;\n  t.duhiragana = 0x3065;\n  t.dukatakana = 0x30c5;\n  t.dz = 0x01f3;\n  t.dzaltone = 0x02a3;\n  t.dzcaron = 0x01c6;\n  t.dzcurl = 0x02a5;\n  t.dzeabkhasiancyrillic = 0x04e1;\n  t.dzecyrillic = 0x0455;\n  t.dzhecyrillic = 0x045f;\n  t.e = 0x0065;\n  t.eacute = 0x00e9;\n  t.earth = 0x2641;\n  t.ebengali = 0x098f;\n  t.ebopomofo = 0x311c;\n  t.ebreve = 0x0115;\n  t.ecandradeva = 0x090d;\n  t.ecandragujarati = 0x0a8d;\n  t.ecandravowelsigndeva = 0x0945;\n  t.ecandravowelsigngujarati = 0x0ac5;\n  t.ecaron = 0x011b;\n  t.ecedillabreve = 0x1e1d;\n  t.echarmenian = 0x0565;\n  t.echyiwnarmenian = 0x0587;\n  t.ecircle = 0x24d4;\n  t.ecircumflex = 0x00ea;\n  t.ecircumflexacute = 0x1ebf;\n  t.ecircumflexbelow = 0x1e19;\n  t.ecircumflexdotbelow = 0x1ec7;\n  t.ecircumflexgrave = 0x1ec1;\n  t.ecircumflexhookabove = 0x1ec3;\n  t.ecircumflextilde = 0x1ec5;\n  t.ecyrillic = 0x0454;\n  t.edblgrave = 0x0205;\n  t.edeva = 0x090f;\n  t.edieresis = 0x00eb;\n  t.edot = 0x0117;\n  t.edotaccent = 0x0117;\n  t.edotbelow = 0x1eb9;\n  t.eegurmukhi = 0x0a0f;\n  t.eematragurmukhi = 0x0a47;\n  t.efcyrillic = 0x0444;\n  t.egrave = 0x00e8;\n  t.egujarati = 0x0a8f;\n  t.eharmenian = 0x0567;\n  t.ehbopomofo = 0x311d;\n  t.ehiragana = 0x3048;\n  t.ehookabove = 0x1ebb;\n  t.eibopomofo = 0x311f;\n  t.eight = 0x0038;\n  t.eightarabic = 0x0668;\n  t.eightbengali = 0x09ee;\n  t.eightcircle = 0x2467;\n  t.eightcircleinversesansserif = 0x2791;\n  t.eightdeva = 0x096e;\n  t.eighteencircle = 0x2471;\n  t.eighteenparen = 0x2485;\n  t.eighteenperiod = 0x2499;\n  t.eightgujarati = 0x0aee;\n  t.eightgurmukhi = 0x0a6e;\n  t.eighthackarabic = 0x0668;\n  t.eighthangzhou = 0x3028;\n  t.eighthnotebeamed = 0x266b;\n  t.eightideographicparen = 0x3227;\n  t.eightinferior = 0x2088;\n  t.eightmonospace = 0xff18;\n  t.eightoldstyle = 0xf738;\n  t.eightparen = 0x247b;\n  t.eightperiod = 0x248f;\n  t.eightpersian = 0x06f8;\n  t.eightroman = 0x2177;\n  t.eightsuperior = 0x2078;\n  t.eightthai = 0x0e58;\n  t.einvertedbreve = 0x0207;\n  t.eiotifiedcyrillic = 0x0465;\n  t.ekatakana = 0x30a8;\n  t.ekatakanahalfwidth = 0xff74;\n  t.ekonkargurmukhi = 0x0a74;\n  t.ekorean = 0x3154;\n  t.elcyrillic = 0x043b;\n  t.element = 0x2208;\n  t.elevencircle = 0x246a;\n  t.elevenparen = 0x247e;\n  t.elevenperiod = 0x2492;\n  t.elevenroman = 0x217a;\n  t.ellipsis = 0x2026;\n  t.ellipsisvertical = 0x22ee;\n  t.emacron = 0x0113;\n  t.emacronacute = 0x1e17;\n  t.emacrongrave = 0x1e15;\n  t.emcyrillic = 0x043c;\n  t.emdash = 0x2014;\n  t.emdashvertical = 0xfe31;\n  t.emonospace = 0xff45;\n  t.emphasismarkarmenian = 0x055b;\n  t.emptyset = 0x2205;\n  t.enbopomofo = 0x3123;\n  t.encyrillic = 0x043d;\n  t.endash = 0x2013;\n  t.endashvertical = 0xfe32;\n  t.endescendercyrillic = 0x04a3;\n  t.eng = 0x014b;\n  t.engbopomofo = 0x3125;\n  t.enghecyrillic = 0x04a5;\n  t.enhookcyrillic = 0x04c8;\n  t.enspace = 0x2002;\n  t.eogonek = 0x0119;\n  t.eokorean = 0x3153;\n  t.eopen = 0x025b;\n  t.eopenclosed = 0x029a;\n  t.eopenreversed = 0x025c;\n  t.eopenreversedclosed = 0x025e;\n  t.eopenreversedhook = 0x025d;\n  t.eparen = 0x24a0;\n  t.epsilon = 0x03b5;\n  t.epsilontonos = 0x03ad;\n  t.equal = 0x003d;\n  t.equalmonospace = 0xff1d;\n  t.equalsmall = 0xfe66;\n  t.equalsuperior = 0x207c;\n  t.equivalence = 0x2261;\n  t.erbopomofo = 0x3126;\n  t.ercyrillic = 0x0440;\n  t.ereversed = 0x0258;\n  t.ereversedcyrillic = 0x044d;\n  t.escyrillic = 0x0441;\n  t.esdescendercyrillic = 0x04ab;\n  t.esh = 0x0283;\n  t.eshcurl = 0x0286;\n  t.eshortdeva = 0x090e;\n  t.eshortvowelsigndeva = 0x0946;\n  t.eshreversedloop = 0x01aa;\n  t.eshsquatreversed = 0x0285;\n  t.esmallhiragana = 0x3047;\n  t.esmallkatakana = 0x30a7;\n  t.esmallkatakanahalfwidth = 0xff6a;\n  t.estimated = 0x212e;\n  t.esuperior = 0xf6ec;\n  t.eta = 0x03b7;\n  t.etarmenian = 0x0568;\n  t.etatonos = 0x03ae;\n  t.eth = 0x00f0;\n  t.etilde = 0x1ebd;\n  t.etildebelow = 0x1e1b;\n  t.etnahtafoukhhebrew = 0x0591;\n  t.etnahtafoukhlefthebrew = 0x0591;\n  t.etnahtahebrew = 0x0591;\n  t.etnahtalefthebrew = 0x0591;\n  t.eturned = 0x01dd;\n  t.eukorean = 0x3161;\n  t.euro = 0x20ac;\n  t.evowelsignbengali = 0x09c7;\n  t.evowelsigndeva = 0x0947;\n  t.evowelsigngujarati = 0x0ac7;\n  t.exclam = 0x0021;\n  t.exclamarmenian = 0x055c;\n  t.exclamdbl = 0x203c;\n  t.exclamdown = 0x00a1;\n  t.exclamdownsmall = 0xf7a1;\n  t.exclammonospace = 0xff01;\n  t.exclamsmall = 0xf721;\n  t.existential = 0x2203;\n  t.ezh = 0x0292;\n  t.ezhcaron = 0x01ef;\n  t.ezhcurl = 0x0293;\n  t.ezhreversed = 0x01b9;\n  t.ezhtail = 0x01ba;\n  t.f = 0x0066;\n  t.fadeva = 0x095e;\n  t.fagurmukhi = 0x0a5e;\n  t.fahrenheit = 0x2109;\n  t.fathaarabic = 0x064e;\n  t.fathalowarabic = 0x064e;\n  t.fathatanarabic = 0x064b;\n  t.fbopomofo = 0x3108;\n  t.fcircle = 0x24d5;\n  t.fdotaccent = 0x1e1f;\n  t.feharabic = 0x0641;\n  t.feharmenian = 0x0586;\n  t.fehfinalarabic = 0xfed2;\n  t.fehinitialarabic = 0xfed3;\n  t.fehmedialarabic = 0xfed4;\n  t.feicoptic = 0x03e5;\n  t.female = 0x2640;\n  t.ff = 0xfb00;\n  t.f_f = 0xfb00;\n  t.ffi = 0xfb03;\n  t.f_f_i = 0xfb03;\n  t.ffl = 0xfb04;\n  t.f_f_l = 0xfb04;\n  t.fi = 0xfb01;\n  t.f_i = 0xfb01;\n  t.fifteencircle = 0x246e;\n  t.fifteenparen = 0x2482;\n  t.fifteenperiod = 0x2496;\n  t.figuredash = 0x2012;\n  t.filledbox = 0x25a0;\n  t.filledrect = 0x25ac;\n  t.finalkaf = 0x05da;\n  t.finalkafdagesh = 0xfb3a;\n  t.finalkafdageshhebrew = 0xfb3a;\n  t.finalkafhebrew = 0x05da;\n  t.finalmem = 0x05dd;\n  t.finalmemhebrew = 0x05dd;\n  t.finalnun = 0x05df;\n  t.finalnunhebrew = 0x05df;\n  t.finalpe = 0x05e3;\n  t.finalpehebrew = 0x05e3;\n  t.finaltsadi = 0x05e5;\n  t.finaltsadihebrew = 0x05e5;\n  t.firsttonechinese = 0x02c9;\n  t.fisheye = 0x25c9;\n  t.fitacyrillic = 0x0473;\n  t.five = 0x0035;\n  t.fivearabic = 0x0665;\n  t.fivebengali = 0x09eb;\n  t.fivecircle = 0x2464;\n  t.fivecircleinversesansserif = 0x278e;\n  t.fivedeva = 0x096b;\n  t.fiveeighths = 0x215d;\n  t.fivegujarati = 0x0aeb;\n  t.fivegurmukhi = 0x0a6b;\n  t.fivehackarabic = 0x0665;\n  t.fivehangzhou = 0x3025;\n  t.fiveideographicparen = 0x3224;\n  t.fiveinferior = 0x2085;\n  t.fivemonospace = 0xff15;\n  t.fiveoldstyle = 0xf735;\n  t.fiveparen = 0x2478;\n  t.fiveperiod = 0x248c;\n  t.fivepersian = 0x06f5;\n  t.fiveroman = 0x2174;\n  t.fivesuperior = 0x2075;\n  t.fivethai = 0x0e55;\n  t.fl = 0xfb02;\n  t.f_l = 0xfb02;\n  t.florin = 0x0192;\n  t.fmonospace = 0xff46;\n  t.fmsquare = 0x3399;\n  t.fofanthai = 0x0e1f;\n  t.fofathai = 0x0e1d;\n  t.fongmanthai = 0x0e4f;\n  t.forall = 0x2200;\n  t.four = 0x0034;\n  t.fourarabic = 0x0664;\n  t.fourbengali = 0x09ea;\n  t.fourcircle = 0x2463;\n  t.fourcircleinversesansserif = 0x278d;\n  t.fourdeva = 0x096a;\n  t.fourgujarati = 0x0aea;\n  t.fourgurmukhi = 0x0a6a;\n  t.fourhackarabic = 0x0664;\n  t.fourhangzhou = 0x3024;\n  t.fourideographicparen = 0x3223;\n  t.fourinferior = 0x2084;\n  t.fourmonospace = 0xff14;\n  t.fournumeratorbengali = 0x09f7;\n  t.fouroldstyle = 0xf734;\n  t.fourparen = 0x2477;\n  t.fourperiod = 0x248b;\n  t.fourpersian = 0x06f4;\n  t.fourroman = 0x2173;\n  t.foursuperior = 0x2074;\n  t.fourteencircle = 0x246d;\n  t.fourteenparen = 0x2481;\n  t.fourteenperiod = 0x2495;\n  t.fourthai = 0x0e54;\n  t.fourthtonechinese = 0x02cb;\n  t.fparen = 0x24a1;\n  t.fraction = 0x2044;\n  t.franc = 0x20a3;\n  t.g = 0x0067;\n  t.gabengali = 0x0997;\n  t.gacute = 0x01f5;\n  t.gadeva = 0x0917;\n  t.gafarabic = 0x06af;\n  t.gaffinalarabic = 0xfb93;\n  t.gafinitialarabic = 0xfb94;\n  t.gafmedialarabic = 0xfb95;\n  t.gagujarati = 0x0a97;\n  t.gagurmukhi = 0x0a17;\n  t.gahiragana = 0x304c;\n  t.gakatakana = 0x30ac;\n  t.gamma = 0x03b3;\n  t.gammalatinsmall = 0x0263;\n  t.gammasuperior = 0x02e0;\n  t.gangiacoptic = 0x03eb;\n  t.gbopomofo = 0x310d;\n  t.gbreve = 0x011f;\n  t.gcaron = 0x01e7;\n  t.gcedilla = 0x0123;\n  t.gcircle = 0x24d6;\n  t.gcircumflex = 0x011d;\n  t.gcommaaccent = 0x0123;\n  t.gdot = 0x0121;\n  t.gdotaccent = 0x0121;\n  t.gecyrillic = 0x0433;\n  t.gehiragana = 0x3052;\n  t.gekatakana = 0x30b2;\n  t.geometricallyequal = 0x2251;\n  t.gereshaccenthebrew = 0x059c;\n  t.gereshhebrew = 0x05f3;\n  t.gereshmuqdamhebrew = 0x059d;\n  t.germandbls = 0x00df;\n  t.gershayimaccenthebrew = 0x059e;\n  t.gershayimhebrew = 0x05f4;\n  t.getamark = 0x3013;\n  t.ghabengali = 0x0998;\n  t.ghadarmenian = 0x0572;\n  t.ghadeva = 0x0918;\n  t.ghagujarati = 0x0a98;\n  t.ghagurmukhi = 0x0a18;\n  t.ghainarabic = 0x063a;\n  t.ghainfinalarabic = 0xfece;\n  t.ghaininitialarabic = 0xfecf;\n  t.ghainmedialarabic = 0xfed0;\n  t.ghemiddlehookcyrillic = 0x0495;\n  t.ghestrokecyrillic = 0x0493;\n  t.gheupturncyrillic = 0x0491;\n  t.ghhadeva = 0x095a;\n  t.ghhagurmukhi = 0x0a5a;\n  t.ghook = 0x0260;\n  t.ghzsquare = 0x3393;\n  t.gihiragana = 0x304e;\n  t.gikatakana = 0x30ae;\n  t.gimarmenian = 0x0563;\n  t.gimel = 0x05d2;\n  t.gimeldagesh = 0xfb32;\n  t.gimeldageshhebrew = 0xfb32;\n  t.gimelhebrew = 0x05d2;\n  t.gjecyrillic = 0x0453;\n  t.glottalinvertedstroke = 0x01be;\n  t.glottalstop = 0x0294;\n  t.glottalstopinverted = 0x0296;\n  t.glottalstopmod = 0x02c0;\n  t.glottalstopreversed = 0x0295;\n  t.glottalstopreversedmod = 0x02c1;\n  t.glottalstopreversedsuperior = 0x02e4;\n  t.glottalstopstroke = 0x02a1;\n  t.glottalstopstrokereversed = 0x02a2;\n  t.gmacron = 0x1e21;\n  t.gmonospace = 0xff47;\n  t.gohiragana = 0x3054;\n  t.gokatakana = 0x30b4;\n  t.gparen = 0x24a2;\n  t.gpasquare = 0x33ac;\n  t.gradient = 0x2207;\n  t.grave = 0x0060;\n  t.gravebelowcmb = 0x0316;\n  t.gravecmb = 0x0300;\n  t.gravecomb = 0x0300;\n  t.gravedeva = 0x0953;\n  t.gravelowmod = 0x02ce;\n  t.gravemonospace = 0xff40;\n  t.gravetonecmb = 0x0340;\n  t.greater = 0x003e;\n  t.greaterequal = 0x2265;\n  t.greaterequalorless = 0x22db;\n  t.greatermonospace = 0xff1e;\n  t.greaterorequivalent = 0x2273;\n  t.greaterorless = 0x2277;\n  t.greateroverequal = 0x2267;\n  t.greatersmall = 0xfe65;\n  t.gscript = 0x0261;\n  t.gstroke = 0x01e5;\n  t.guhiragana = 0x3050;\n  t.guillemotleft = 0x00ab;\n  t.guillemotright = 0x00bb;\n  t.guilsinglleft = 0x2039;\n  t.guilsinglright = 0x203a;\n  t.gukatakana = 0x30b0;\n  t.guramusquare = 0x3318;\n  t.gysquare = 0x33c9;\n  t.h = 0x0068;\n  t.haabkhasiancyrillic = 0x04a9;\n  t.haaltonearabic = 0x06c1;\n  t.habengali = 0x09b9;\n  t.hadescendercyrillic = 0x04b3;\n  t.hadeva = 0x0939;\n  t.hagujarati = 0x0ab9;\n  t.hagurmukhi = 0x0a39;\n  t.haharabic = 0x062d;\n  t.hahfinalarabic = 0xfea2;\n  t.hahinitialarabic = 0xfea3;\n  t.hahiragana = 0x306f;\n  t.hahmedialarabic = 0xfea4;\n  t.haitusquare = 0x332a;\n  t.hakatakana = 0x30cf;\n  t.hakatakanahalfwidth = 0xff8a;\n  t.halantgurmukhi = 0x0a4d;\n  t.hamzaarabic = 0x0621;\n  t.hamzalowarabic = 0x0621;\n  t.hangulfiller = 0x3164;\n  t.hardsigncyrillic = 0x044a;\n  t.harpoonleftbarbup = 0x21bc;\n  t.harpoonrightbarbup = 0x21c0;\n  t.hasquare = 0x33ca;\n  t.hatafpatah = 0x05b2;\n  t.hatafpatah16 = 0x05b2;\n  t.hatafpatah23 = 0x05b2;\n  t.hatafpatah2f = 0x05b2;\n  t.hatafpatahhebrew = 0x05b2;\n  t.hatafpatahnarrowhebrew = 0x05b2;\n  t.hatafpatahquarterhebrew = 0x05b2;\n  t.hatafpatahwidehebrew = 0x05b2;\n  t.hatafqamats = 0x05b3;\n  t.hatafqamats1b = 0x05b3;\n  t.hatafqamats28 = 0x05b3;\n  t.hatafqamats34 = 0x05b3;\n  t.hatafqamatshebrew = 0x05b3;\n  t.hatafqamatsnarrowhebrew = 0x05b3;\n  t.hatafqamatsquarterhebrew = 0x05b3;\n  t.hatafqamatswidehebrew = 0x05b3;\n  t.hatafsegol = 0x05b1;\n  t.hatafsegol17 = 0x05b1;\n  t.hatafsegol24 = 0x05b1;\n  t.hatafsegol30 = 0x05b1;\n  t.hatafsegolhebrew = 0x05b1;\n  t.hatafsegolnarrowhebrew = 0x05b1;\n  t.hatafsegolquarterhebrew = 0x05b1;\n  t.hatafsegolwidehebrew = 0x05b1;\n  t.hbar = 0x0127;\n  t.hbopomofo = 0x310f;\n  t.hbrevebelow = 0x1e2b;\n  t.hcedilla = 0x1e29;\n  t.hcircle = 0x24d7;\n  t.hcircumflex = 0x0125;\n  t.hdieresis = 0x1e27;\n  t.hdotaccent = 0x1e23;\n  t.hdotbelow = 0x1e25;\n  t.he = 0x05d4;\n  t.heart = 0x2665;\n  t.heartsuitblack = 0x2665;\n  t.heartsuitwhite = 0x2661;\n  t.hedagesh = 0xfb34;\n  t.hedageshhebrew = 0xfb34;\n  t.hehaltonearabic = 0x06c1;\n  t.heharabic = 0x0647;\n  t.hehebrew = 0x05d4;\n  t.hehfinalaltonearabic = 0xfba7;\n  t.hehfinalalttwoarabic = 0xfeea;\n  t.hehfinalarabic = 0xfeea;\n  t.hehhamzaabovefinalarabic = 0xfba5;\n  t.hehhamzaaboveisolatedarabic = 0xfba4;\n  t.hehinitialaltonearabic = 0xfba8;\n  t.hehinitialarabic = 0xfeeb;\n  t.hehiragana = 0x3078;\n  t.hehmedialaltonearabic = 0xfba9;\n  t.hehmedialarabic = 0xfeec;\n  t.heiseierasquare = 0x337b;\n  t.hekatakana = 0x30d8;\n  t.hekatakanahalfwidth = 0xff8d;\n  t.hekutaarusquare = 0x3336;\n  t.henghook = 0x0267;\n  t.herutusquare = 0x3339;\n  t.het = 0x05d7;\n  t.hethebrew = 0x05d7;\n  t.hhook = 0x0266;\n  t.hhooksuperior = 0x02b1;\n  t.hieuhacirclekorean = 0x327b;\n  t.hieuhaparenkorean = 0x321b;\n  t.hieuhcirclekorean = 0x326d;\n  t.hieuhkorean = 0x314e;\n  t.hieuhparenkorean = 0x320d;\n  t.hihiragana = 0x3072;\n  t.hikatakana = 0x30d2;\n  t.hikatakanahalfwidth = 0xff8b;\n  t.hiriq = 0x05b4;\n  t.hiriq14 = 0x05b4;\n  t.hiriq21 = 0x05b4;\n  t.hiriq2d = 0x05b4;\n  t.hiriqhebrew = 0x05b4;\n  t.hiriqnarrowhebrew = 0x05b4;\n  t.hiriqquarterhebrew = 0x05b4;\n  t.hiriqwidehebrew = 0x05b4;\n  t.hlinebelow = 0x1e96;\n  t.hmonospace = 0xff48;\n  t.hoarmenian = 0x0570;\n  t.hohipthai = 0x0e2b;\n  t.hohiragana = 0x307b;\n  t.hokatakana = 0x30db;\n  t.hokatakanahalfwidth = 0xff8e;\n  t.holam = 0x05b9;\n  t.holam19 = 0x05b9;\n  t.holam26 = 0x05b9;\n  t.holam32 = 0x05b9;\n  t.holamhebrew = 0x05b9;\n  t.holamnarrowhebrew = 0x05b9;\n  t.holamquarterhebrew = 0x05b9;\n  t.holamwidehebrew = 0x05b9;\n  t.honokhukthai = 0x0e2e;\n  t.hookabovecomb = 0x0309;\n  t.hookcmb = 0x0309;\n  t.hookpalatalizedbelowcmb = 0x0321;\n  t.hookretroflexbelowcmb = 0x0322;\n  t.hoonsquare = 0x3342;\n  t.horicoptic = 0x03e9;\n  t.horizontalbar = 0x2015;\n  t.horncmb = 0x031b;\n  t.hotsprings = 0x2668;\n  t.house = 0x2302;\n  t.hparen = 0x24a3;\n  t.hsuperior = 0x02b0;\n  t.hturned = 0x0265;\n  t.huhiragana = 0x3075;\n  t.huiitosquare = 0x3333;\n  t.hukatakana = 0x30d5;\n  t.hukatakanahalfwidth = 0xff8c;\n  t.hungarumlaut = 0x02dd;\n  t.hungarumlautcmb = 0x030b;\n  t.hv = 0x0195;\n  t.hyphen = 0x002d;\n  t.hypheninferior = 0xf6e5;\n  t.hyphenmonospace = 0xff0d;\n  t.hyphensmall = 0xfe63;\n  t.hyphensuperior = 0xf6e6;\n  t.hyphentwo = 0x2010;\n  t.i = 0x0069;\n  t.iacute = 0x00ed;\n  t.iacyrillic = 0x044f;\n  t.ibengali = 0x0987;\n  t.ibopomofo = 0x3127;\n  t.ibreve = 0x012d;\n  t.icaron = 0x01d0;\n  t.icircle = 0x24d8;\n  t.icircumflex = 0x00ee;\n  t.icyrillic = 0x0456;\n  t.idblgrave = 0x0209;\n  t.ideographearthcircle = 0x328f;\n  t.ideographfirecircle = 0x328b;\n  t.ideographicallianceparen = 0x323f;\n  t.ideographiccallparen = 0x323a;\n  t.ideographiccentrecircle = 0x32a5;\n  t.ideographicclose = 0x3006;\n  t.ideographiccomma = 0x3001;\n  t.ideographiccommaleft = 0xff64;\n  t.ideographiccongratulationparen = 0x3237;\n  t.ideographiccorrectcircle = 0x32a3;\n  t.ideographicearthparen = 0x322f;\n  t.ideographicenterpriseparen = 0x323d;\n  t.ideographicexcellentcircle = 0x329d;\n  t.ideographicfestivalparen = 0x3240;\n  t.ideographicfinancialcircle = 0x3296;\n  t.ideographicfinancialparen = 0x3236;\n  t.ideographicfireparen = 0x322b;\n  t.ideographichaveparen = 0x3232;\n  t.ideographichighcircle = 0x32a4;\n  t.ideographiciterationmark = 0x3005;\n  t.ideographiclaborcircle = 0x3298;\n  t.ideographiclaborparen = 0x3238;\n  t.ideographicleftcircle = 0x32a7;\n  t.ideographiclowcircle = 0x32a6;\n  t.ideographicmedicinecircle = 0x32a9;\n  t.ideographicmetalparen = 0x322e;\n  t.ideographicmoonparen = 0x322a;\n  t.ideographicnameparen = 0x3234;\n  t.ideographicperiod = 0x3002;\n  t.ideographicprintcircle = 0x329e;\n  t.ideographicreachparen = 0x3243;\n  t.ideographicrepresentparen = 0x3239;\n  t.ideographicresourceparen = 0x323e;\n  t.ideographicrightcircle = 0x32a8;\n  t.ideographicsecretcircle = 0x3299;\n  t.ideographicselfparen = 0x3242;\n  t.ideographicsocietyparen = 0x3233;\n  t.ideographicspace = 0x3000;\n  t.ideographicspecialparen = 0x3235;\n  t.ideographicstockparen = 0x3231;\n  t.ideographicstudyparen = 0x323b;\n  t.ideographicsunparen = 0x3230;\n  t.ideographicsuperviseparen = 0x323c;\n  t.ideographicwaterparen = 0x322c;\n  t.ideographicwoodparen = 0x322d;\n  t.ideographiczero = 0x3007;\n  t.ideographmetalcircle = 0x328e;\n  t.ideographmooncircle = 0x328a;\n  t.ideographnamecircle = 0x3294;\n  t.ideographsuncircle = 0x3290;\n  t.ideographwatercircle = 0x328c;\n  t.ideographwoodcircle = 0x328d;\n  t.ideva = 0x0907;\n  t.idieresis = 0x00ef;\n  t.idieresisacute = 0x1e2f;\n  t.idieresiscyrillic = 0x04e5;\n  t.idotbelow = 0x1ecb;\n  t.iebrevecyrillic = 0x04d7;\n  t.iecyrillic = 0x0435;\n  t.ieungacirclekorean = 0x3275;\n  t.ieungaparenkorean = 0x3215;\n  t.ieungcirclekorean = 0x3267;\n  t.ieungkorean = 0x3147;\n  t.ieungparenkorean = 0x3207;\n  t.igrave = 0x00ec;\n  t.igujarati = 0x0a87;\n  t.igurmukhi = 0x0a07;\n  t.ihiragana = 0x3044;\n  t.ihookabove = 0x1ec9;\n  t.iibengali = 0x0988;\n  t.iicyrillic = 0x0438;\n  t.iideva = 0x0908;\n  t.iigujarati = 0x0a88;\n  t.iigurmukhi = 0x0a08;\n  t.iimatragurmukhi = 0x0a40;\n  t.iinvertedbreve = 0x020b;\n  t.iishortcyrillic = 0x0439;\n  t.iivowelsignbengali = 0x09c0;\n  t.iivowelsigndeva = 0x0940;\n  t.iivowelsigngujarati = 0x0ac0;\n  t.ij = 0x0133;\n  t.ikatakana = 0x30a4;\n  t.ikatakanahalfwidth = 0xff72;\n  t.ikorean = 0x3163;\n  t.ilde = 0x02dc;\n  t.iluyhebrew = 0x05ac;\n  t.imacron = 0x012b;\n  t.imacroncyrillic = 0x04e3;\n  t.imageorapproximatelyequal = 0x2253;\n  t.imatragurmukhi = 0x0a3f;\n  t.imonospace = 0xff49;\n  t.increment = 0x2206;\n  t.infinity = 0x221e;\n  t.iniarmenian = 0x056b;\n  t.integral = 0x222b;\n  t.integralbottom = 0x2321;\n  t.integralbt = 0x2321;\n  t.integralex = 0xf8f5;\n  t.integraltop = 0x2320;\n  t.integraltp = 0x2320;\n  t.intersection = 0x2229;\n  t.intisquare = 0x3305;\n  t.invbullet = 0x25d8;\n  t.invcircle = 0x25d9;\n  t.invsmileface = 0x263b;\n  t.iocyrillic = 0x0451;\n  t.iogonek = 0x012f;\n  t.iota = 0x03b9;\n  t.iotadieresis = 0x03ca;\n  t.iotadieresistonos = 0x0390;\n  t.iotalatin = 0x0269;\n  t.iotatonos = 0x03af;\n  t.iparen = 0x24a4;\n  t.irigurmukhi = 0x0a72;\n  t.ismallhiragana = 0x3043;\n  t.ismallkatakana = 0x30a3;\n  t.ismallkatakanahalfwidth = 0xff68;\n  t.issharbengali = 0x09fa;\n  t.istroke = 0x0268;\n  t.isuperior = 0xf6ed;\n  t.iterationhiragana = 0x309d;\n  t.iterationkatakana = 0x30fd;\n  t.itilde = 0x0129;\n  t.itildebelow = 0x1e2d;\n  t.iubopomofo = 0x3129;\n  t.iucyrillic = 0x044e;\n  t.ivowelsignbengali = 0x09bf;\n  t.ivowelsigndeva = 0x093f;\n  t.ivowelsigngujarati = 0x0abf;\n  t.izhitsacyrillic = 0x0475;\n  t.izhitsadblgravecyrillic = 0x0477;\n  t.j = 0x006a;\n  t.jaarmenian = 0x0571;\n  t.jabengali = 0x099c;\n  t.jadeva = 0x091c;\n  t.jagujarati = 0x0a9c;\n  t.jagurmukhi = 0x0a1c;\n  t.jbopomofo = 0x3110;\n  t.jcaron = 0x01f0;\n  t.jcircle = 0x24d9;\n  t.jcircumflex = 0x0135;\n  t.jcrossedtail = 0x029d;\n  t.jdotlessstroke = 0x025f;\n  t.jecyrillic = 0x0458;\n  t.jeemarabic = 0x062c;\n  t.jeemfinalarabic = 0xfe9e;\n  t.jeeminitialarabic = 0xfe9f;\n  t.jeemmedialarabic = 0xfea0;\n  t.jeharabic = 0x0698;\n  t.jehfinalarabic = 0xfb8b;\n  t.jhabengali = 0x099d;\n  t.jhadeva = 0x091d;\n  t.jhagujarati = 0x0a9d;\n  t.jhagurmukhi = 0x0a1d;\n  t.jheharmenian = 0x057b;\n  t.jis = 0x3004;\n  t.jmonospace = 0xff4a;\n  t.jparen = 0x24a5;\n  t.jsuperior = 0x02b2;\n  t.k = 0x006b;\n  t.kabashkircyrillic = 0x04a1;\n  t.kabengali = 0x0995;\n  t.kacute = 0x1e31;\n  t.kacyrillic = 0x043a;\n  t.kadescendercyrillic = 0x049b;\n  t.kadeva = 0x0915;\n  t.kaf = 0x05db;\n  t.kafarabic = 0x0643;\n  t.kafdagesh = 0xfb3b;\n  t.kafdageshhebrew = 0xfb3b;\n  t.kaffinalarabic = 0xfeda;\n  t.kafhebrew = 0x05db;\n  t.kafinitialarabic = 0xfedb;\n  t.kafmedialarabic = 0xfedc;\n  t.kafrafehebrew = 0xfb4d;\n  t.kagujarati = 0x0a95;\n  t.kagurmukhi = 0x0a15;\n  t.kahiragana = 0x304b;\n  t.kahookcyrillic = 0x04c4;\n  t.kakatakana = 0x30ab;\n  t.kakatakanahalfwidth = 0xff76;\n  t.kappa = 0x03ba;\n  t.kappasymbolgreek = 0x03f0;\n  t.kapyeounmieumkorean = 0x3171;\n  t.kapyeounphieuphkorean = 0x3184;\n  t.kapyeounpieupkorean = 0x3178;\n  t.kapyeounssangpieupkorean = 0x3179;\n  t.karoriisquare = 0x330d;\n  t.kashidaautoarabic = 0x0640;\n  t.kashidaautonosidebearingarabic = 0x0640;\n  t.kasmallkatakana = 0x30f5;\n  t.kasquare = 0x3384;\n  t.kasraarabic = 0x0650;\n  t.kasratanarabic = 0x064d;\n  t.kastrokecyrillic = 0x049f;\n  t.katahiraprolongmarkhalfwidth = 0xff70;\n  t.kaverticalstrokecyrillic = 0x049d;\n  t.kbopomofo = 0x310e;\n  t.kcalsquare = 0x3389;\n  t.kcaron = 0x01e9;\n  t.kcedilla = 0x0137;\n  t.kcircle = 0x24da;\n  t.kcommaaccent = 0x0137;\n  t.kdotbelow = 0x1e33;\n  t.keharmenian = 0x0584;\n  t.kehiragana = 0x3051;\n  t.kekatakana = 0x30b1;\n  t.kekatakanahalfwidth = 0xff79;\n  t.kenarmenian = 0x056f;\n  t.kesmallkatakana = 0x30f6;\n  t.kgreenlandic = 0x0138;\n  t.khabengali = 0x0996;\n  t.khacyrillic = 0x0445;\n  t.khadeva = 0x0916;\n  t.khagujarati = 0x0a96;\n  t.khagurmukhi = 0x0a16;\n  t.khaharabic = 0x062e;\n  t.khahfinalarabic = 0xfea6;\n  t.khahinitialarabic = 0xfea7;\n  t.khahmedialarabic = 0xfea8;\n  t.kheicoptic = 0x03e7;\n  t.khhadeva = 0x0959;\n  t.khhagurmukhi = 0x0a59;\n  t.khieukhacirclekorean = 0x3278;\n  t.khieukhaparenkorean = 0x3218;\n  t.khieukhcirclekorean = 0x326a;\n  t.khieukhkorean = 0x314b;\n  t.khieukhparenkorean = 0x320a;\n  t.khokhaithai = 0x0e02;\n  t.khokhonthai = 0x0e05;\n  t.khokhuatthai = 0x0e03;\n  t.khokhwaithai = 0x0e04;\n  t.khomutthai = 0x0e5b;\n  t.khook = 0x0199;\n  t.khorakhangthai = 0x0e06;\n  t.khzsquare = 0x3391;\n  t.kihiragana = 0x304d;\n  t.kikatakana = 0x30ad;\n  t.kikatakanahalfwidth = 0xff77;\n  t.kiroguramusquare = 0x3315;\n  t.kiromeetorusquare = 0x3316;\n  t.kirosquare = 0x3314;\n  t.kiyeokacirclekorean = 0x326e;\n  t.kiyeokaparenkorean = 0x320e;\n  t.kiyeokcirclekorean = 0x3260;\n  t.kiyeokkorean = 0x3131;\n  t.kiyeokparenkorean = 0x3200;\n  t.kiyeoksioskorean = 0x3133;\n  t.kjecyrillic = 0x045c;\n  t.klinebelow = 0x1e35;\n  t.klsquare = 0x3398;\n  t.kmcubedsquare = 0x33a6;\n  t.kmonospace = 0xff4b;\n  t.kmsquaredsquare = 0x33a2;\n  t.kohiragana = 0x3053;\n  t.kohmsquare = 0x33c0;\n  t.kokaithai = 0x0e01;\n  t.kokatakana = 0x30b3;\n  t.kokatakanahalfwidth = 0xff7a;\n  t.kooposquare = 0x331e;\n  t.koppacyrillic = 0x0481;\n  t.koreanstandardsymbol = 0x327f;\n  t.koroniscmb = 0x0343;\n  t.kparen = 0x24a6;\n  t.kpasquare = 0x33aa;\n  t.ksicyrillic = 0x046f;\n  t.ktsquare = 0x33cf;\n  t.kturned = 0x029e;\n  t.kuhiragana = 0x304f;\n  t.kukatakana = 0x30af;\n  t.kukatakanahalfwidth = 0xff78;\n  t.kvsquare = 0x33b8;\n  t.kwsquare = 0x33be;\n  t.l = 0x006c;\n  t.labengali = 0x09b2;\n  t.lacute = 0x013a;\n  t.ladeva = 0x0932;\n  t.lagujarati = 0x0ab2;\n  t.lagurmukhi = 0x0a32;\n  t.lakkhangyaothai = 0x0e45;\n  t.lamaleffinalarabic = 0xfefc;\n  t.lamalefhamzaabovefinalarabic = 0xfef8;\n  t.lamalefhamzaaboveisolatedarabic = 0xfef7;\n  t.lamalefhamzabelowfinalarabic = 0xfefa;\n  t.lamalefhamzabelowisolatedarabic = 0xfef9;\n  t.lamalefisolatedarabic = 0xfefb;\n  t.lamalefmaddaabovefinalarabic = 0xfef6;\n  t.lamalefmaddaaboveisolatedarabic = 0xfef5;\n  t.lamarabic = 0x0644;\n  t.lambda = 0x03bb;\n  t.lambdastroke = 0x019b;\n  t.lamed = 0x05dc;\n  t.lameddagesh = 0xfb3c;\n  t.lameddageshhebrew = 0xfb3c;\n  t.lamedhebrew = 0x05dc;\n  t.lamfinalarabic = 0xfede;\n  t.lamhahinitialarabic = 0xfcca;\n  t.laminitialarabic = 0xfedf;\n  t.lamjeeminitialarabic = 0xfcc9;\n  t.lamkhahinitialarabic = 0xfccb;\n  t.lamlamhehisolatedarabic = 0xfdf2;\n  t.lammedialarabic = 0xfee0;\n  t.lammeemhahinitialarabic = 0xfd88;\n  t.lammeeminitialarabic = 0xfccc;\n  t.largecircle = 0x25ef;\n  t.lbar = 0x019a;\n  t.lbelt = 0x026c;\n  t.lbopomofo = 0x310c;\n  t.lcaron = 0x013e;\n  t.lcedilla = 0x013c;\n  t.lcircle = 0x24db;\n  t.lcircumflexbelow = 0x1e3d;\n  t.lcommaaccent = 0x013c;\n  t.ldot = 0x0140;\n  t.ldotaccent = 0x0140;\n  t.ldotbelow = 0x1e37;\n  t.ldotbelowmacron = 0x1e39;\n  t.leftangleabovecmb = 0x031a;\n  t.lefttackbelowcmb = 0x0318;\n  t.less = 0x003c;\n  t.lessequal = 0x2264;\n  t.lessequalorgreater = 0x22da;\n  t.lessmonospace = 0xff1c;\n  t.lessorequivalent = 0x2272;\n  t.lessorgreater = 0x2276;\n  t.lessoverequal = 0x2266;\n  t.lesssmall = 0xfe64;\n  t.lezh = 0x026e;\n  t.lfblock = 0x258c;\n  t.lhookretroflex = 0x026d;\n  t.lira = 0x20a4;\n  t.liwnarmenian = 0x056c;\n  t.lj = 0x01c9;\n  t.ljecyrillic = 0x0459;\n  t.ll = 0xf6c0;\n  t.lladeva = 0x0933;\n  t.llagujarati = 0x0ab3;\n  t.llinebelow = 0x1e3b;\n  t.llladeva = 0x0934;\n  t.llvocalicbengali = 0x09e1;\n  t.llvocalicdeva = 0x0961;\n  t.llvocalicvowelsignbengali = 0x09e3;\n  t.llvocalicvowelsigndeva = 0x0963;\n  t.lmiddletilde = 0x026b;\n  t.lmonospace = 0xff4c;\n  t.lmsquare = 0x33d0;\n  t.lochulathai = 0x0e2c;\n  t.logicaland = 0x2227;\n  t.logicalnot = 0x00ac;\n  t.logicalnotreversed = 0x2310;\n  t.logicalor = 0x2228;\n  t.lolingthai = 0x0e25;\n  t.longs = 0x017f;\n  t.lowlinecenterline = 0xfe4e;\n  t.lowlinecmb = 0x0332;\n  t.lowlinedashed = 0xfe4d;\n  t.lozenge = 0x25ca;\n  t.lparen = 0x24a7;\n  t.lslash = 0x0142;\n  t.lsquare = 0x2113;\n  t.lsuperior = 0xf6ee;\n  t.ltshade = 0x2591;\n  t.luthai = 0x0e26;\n  t.lvocalicbengali = 0x098c;\n  t.lvocalicdeva = 0x090c;\n  t.lvocalicvowelsignbengali = 0x09e2;\n  t.lvocalicvowelsigndeva = 0x0962;\n  t.lxsquare = 0x33d3;\n  t.m = 0x006d;\n  t.mabengali = 0x09ae;\n  t.macron = 0x00af;\n  t.macronbelowcmb = 0x0331;\n  t.macroncmb = 0x0304;\n  t.macronlowmod = 0x02cd;\n  t.macronmonospace = 0xffe3;\n  t.macute = 0x1e3f;\n  t.madeva = 0x092e;\n  t.magujarati = 0x0aae;\n  t.magurmukhi = 0x0a2e;\n  t.mahapakhhebrew = 0x05a4;\n  t.mahapakhlefthebrew = 0x05a4;\n  t.mahiragana = 0x307e;\n  t.maichattawalowleftthai = 0xf895;\n  t.maichattawalowrightthai = 0xf894;\n  t.maichattawathai = 0x0e4b;\n  t.maichattawaupperleftthai = 0xf893;\n  t.maieklowleftthai = 0xf88c;\n  t.maieklowrightthai = 0xf88b;\n  t.maiekthai = 0x0e48;\n  t.maiekupperleftthai = 0xf88a;\n  t.maihanakatleftthai = 0xf884;\n  t.maihanakatthai = 0x0e31;\n  t.maitaikhuleftthai = 0xf889;\n  t.maitaikhuthai = 0x0e47;\n  t.maitholowleftthai = 0xf88f;\n  t.maitholowrightthai = 0xf88e;\n  t.maithothai = 0x0e49;\n  t.maithoupperleftthai = 0xf88d;\n  t.maitrilowleftthai = 0xf892;\n  t.maitrilowrightthai = 0xf891;\n  t.maitrithai = 0x0e4a;\n  t.maitriupperleftthai = 0xf890;\n  t.maiyamokthai = 0x0e46;\n  t.makatakana = 0x30de;\n  t.makatakanahalfwidth = 0xff8f;\n  t.male = 0x2642;\n  t.mansyonsquare = 0x3347;\n  t.maqafhebrew = 0x05be;\n  t.mars = 0x2642;\n  t.masoracirclehebrew = 0x05af;\n  t.masquare = 0x3383;\n  t.mbopomofo = 0x3107;\n  t.mbsquare = 0x33d4;\n  t.mcircle = 0x24dc;\n  t.mcubedsquare = 0x33a5;\n  t.mdotaccent = 0x1e41;\n  t.mdotbelow = 0x1e43;\n  t.meemarabic = 0x0645;\n  t.meemfinalarabic = 0xfee2;\n  t.meeminitialarabic = 0xfee3;\n  t.meemmedialarabic = 0xfee4;\n  t.meemmeeminitialarabic = 0xfcd1;\n  t.meemmeemisolatedarabic = 0xfc48;\n  t.meetorusquare = 0x334d;\n  t.mehiragana = 0x3081;\n  t.meizierasquare = 0x337e;\n  t.mekatakana = 0x30e1;\n  t.mekatakanahalfwidth = 0xff92;\n  t.mem = 0x05de;\n  t.memdagesh = 0xfb3e;\n  t.memdageshhebrew = 0xfb3e;\n  t.memhebrew = 0x05de;\n  t.menarmenian = 0x0574;\n  t.merkhahebrew = 0x05a5;\n  t.merkhakefulahebrew = 0x05a6;\n  t.merkhakefulalefthebrew = 0x05a6;\n  t.merkhalefthebrew = 0x05a5;\n  t.mhook = 0x0271;\n  t.mhzsquare = 0x3392;\n  t.middledotkatakanahalfwidth = 0xff65;\n  t.middot = 0x00b7;\n  t.mieumacirclekorean = 0x3272;\n  t.mieumaparenkorean = 0x3212;\n  t.mieumcirclekorean = 0x3264;\n  t.mieumkorean = 0x3141;\n  t.mieumpansioskorean = 0x3170;\n  t.mieumparenkorean = 0x3204;\n  t.mieumpieupkorean = 0x316e;\n  t.mieumsioskorean = 0x316f;\n  t.mihiragana = 0x307f;\n  t.mikatakana = 0x30df;\n  t.mikatakanahalfwidth = 0xff90;\n  t.minus = 0x2212;\n  t.minusbelowcmb = 0x0320;\n  t.minuscircle = 0x2296;\n  t.minusmod = 0x02d7;\n  t.minusplus = 0x2213;\n  t.minute = 0x2032;\n  t.miribaarusquare = 0x334a;\n  t.mirisquare = 0x3349;\n  t.mlonglegturned = 0x0270;\n  t.mlsquare = 0x3396;\n  t.mmcubedsquare = 0x33a3;\n  t.mmonospace = 0xff4d;\n  t.mmsquaredsquare = 0x339f;\n  t.mohiragana = 0x3082;\n  t.mohmsquare = 0x33c1;\n  t.mokatakana = 0x30e2;\n  t.mokatakanahalfwidth = 0xff93;\n  t.molsquare = 0x33d6;\n  t.momathai = 0x0e21;\n  t.moverssquare = 0x33a7;\n  t.moverssquaredsquare = 0x33a8;\n  t.mparen = 0x24a8;\n  t.mpasquare = 0x33ab;\n  t.mssquare = 0x33b3;\n  t.msuperior = 0xf6ef;\n  t.mturned = 0x026f;\n  t.mu = 0x00b5;\n  t.mu1 = 0x00b5;\n  t.muasquare = 0x3382;\n  t.muchgreater = 0x226b;\n  t.muchless = 0x226a;\n  t.mufsquare = 0x338c;\n  t.mugreek = 0x03bc;\n  t.mugsquare = 0x338d;\n  t.muhiragana = 0x3080;\n  t.mukatakana = 0x30e0;\n  t.mukatakanahalfwidth = 0xff91;\n  t.mulsquare = 0x3395;\n  t.multiply = 0x00d7;\n  t.mumsquare = 0x339b;\n  t.munahhebrew = 0x05a3;\n  t.munahlefthebrew = 0x05a3;\n  t.musicalnote = 0x266a;\n  t.musicalnotedbl = 0x266b;\n  t.musicflatsign = 0x266d;\n  t.musicsharpsign = 0x266f;\n  t.mussquare = 0x33b2;\n  t.muvsquare = 0x33b6;\n  t.muwsquare = 0x33bc;\n  t.mvmegasquare = 0x33b9;\n  t.mvsquare = 0x33b7;\n  t.mwmegasquare = 0x33bf;\n  t.mwsquare = 0x33bd;\n  t.n = 0x006e;\n  t.nabengali = 0x09a8;\n  t.nabla = 0x2207;\n  t.nacute = 0x0144;\n  t.nadeva = 0x0928;\n  t.nagujarati = 0x0aa8;\n  t.nagurmukhi = 0x0a28;\n  t.nahiragana = 0x306a;\n  t.nakatakana = 0x30ca;\n  t.nakatakanahalfwidth = 0xff85;\n  t.napostrophe = 0x0149;\n  t.nasquare = 0x3381;\n  t.nbopomofo = 0x310b;\n  t.nbspace = 0x00a0;\n  t.ncaron = 0x0148;\n  t.ncedilla = 0x0146;\n  t.ncircle = 0x24dd;\n  t.ncircumflexbelow = 0x1e4b;\n  t.ncommaaccent = 0x0146;\n  t.ndotaccent = 0x1e45;\n  t.ndotbelow = 0x1e47;\n  t.nehiragana = 0x306d;\n  t.nekatakana = 0x30cd;\n  t.nekatakanahalfwidth = 0xff88;\n  t.newsheqelsign = 0x20aa;\n  t.nfsquare = 0x338b;\n  t.ngabengali = 0x0999;\n  t.ngadeva = 0x0919;\n  t.ngagujarati = 0x0a99;\n  t.ngagurmukhi = 0x0a19;\n  t.ngonguthai = 0x0e07;\n  t.nhiragana = 0x3093;\n  t.nhookleft = 0x0272;\n  t.nhookretroflex = 0x0273;\n  t.nieunacirclekorean = 0x326f;\n  t.nieunaparenkorean = 0x320f;\n  t.nieuncieuckorean = 0x3135;\n  t.nieuncirclekorean = 0x3261;\n  t.nieunhieuhkorean = 0x3136;\n  t.nieunkorean = 0x3134;\n  t.nieunpansioskorean = 0x3168;\n  t.nieunparenkorean = 0x3201;\n  t.nieunsioskorean = 0x3167;\n  t.nieuntikeutkorean = 0x3166;\n  t.nihiragana = 0x306b;\n  t.nikatakana = 0x30cb;\n  t.nikatakanahalfwidth = 0xff86;\n  t.nikhahitleftthai = 0xf899;\n  t.nikhahitthai = 0x0e4d;\n  t.nine = 0x0039;\n  t.ninearabic = 0x0669;\n  t.ninebengali = 0x09ef;\n  t.ninecircle = 0x2468;\n  t.ninecircleinversesansserif = 0x2792;\n  t.ninedeva = 0x096f;\n  t.ninegujarati = 0x0aef;\n  t.ninegurmukhi = 0x0a6f;\n  t.ninehackarabic = 0x0669;\n  t.ninehangzhou = 0x3029;\n  t.nineideographicparen = 0x3228;\n  t.nineinferior = 0x2089;\n  t.ninemonospace = 0xff19;\n  t.nineoldstyle = 0xf739;\n  t.nineparen = 0x247c;\n  t.nineperiod = 0x2490;\n  t.ninepersian = 0x06f9;\n  t.nineroman = 0x2178;\n  t.ninesuperior = 0x2079;\n  t.nineteencircle = 0x2472;\n  t.nineteenparen = 0x2486;\n  t.nineteenperiod = 0x249a;\n  t.ninethai = 0x0e59;\n  t.nj = 0x01cc;\n  t.njecyrillic = 0x045a;\n  t.nkatakana = 0x30f3;\n  t.nkatakanahalfwidth = 0xff9d;\n  t.nlegrightlong = 0x019e;\n  t.nlinebelow = 0x1e49;\n  t.nmonospace = 0xff4e;\n  t.nmsquare = 0x339a;\n  t.nnabengali = 0x09a3;\n  t.nnadeva = 0x0923;\n  t.nnagujarati = 0x0aa3;\n  t.nnagurmukhi = 0x0a23;\n  t.nnnadeva = 0x0929;\n  t.nohiragana = 0x306e;\n  t.nokatakana = 0x30ce;\n  t.nokatakanahalfwidth = 0xff89;\n  t.nonbreakingspace = 0x00a0;\n  t.nonenthai = 0x0e13;\n  t.nonuthai = 0x0e19;\n  t.noonarabic = 0x0646;\n  t.noonfinalarabic = 0xfee6;\n  t.noonghunnaarabic = 0x06ba;\n  t.noonghunnafinalarabic = 0xfb9f;\n  t.nooninitialarabic = 0xfee7;\n  t.noonjeeminitialarabic = 0xfcd2;\n  t.noonjeemisolatedarabic = 0xfc4b;\n  t.noonmedialarabic = 0xfee8;\n  t.noonmeeminitialarabic = 0xfcd5;\n  t.noonmeemisolatedarabic = 0xfc4e;\n  t.noonnoonfinalarabic = 0xfc8d;\n  t.notcontains = 0x220c;\n  t.notelement = 0x2209;\n  t.notelementof = 0x2209;\n  t.notequal = 0x2260;\n  t.notgreater = 0x226f;\n  t.notgreaternorequal = 0x2271;\n  t.notgreaternorless = 0x2279;\n  t.notidentical = 0x2262;\n  t.notless = 0x226e;\n  t.notlessnorequal = 0x2270;\n  t.notparallel = 0x2226;\n  t.notprecedes = 0x2280;\n  t.notsubset = 0x2284;\n  t.notsucceeds = 0x2281;\n  t.notsuperset = 0x2285;\n  t.nowarmenian = 0x0576;\n  t.nparen = 0x24a9;\n  t.nssquare = 0x33b1;\n  t.nsuperior = 0x207f;\n  t.ntilde = 0x00f1;\n  t.nu = 0x03bd;\n  t.nuhiragana = 0x306c;\n  t.nukatakana = 0x30cc;\n  t.nukatakanahalfwidth = 0xff87;\n  t.nuktabengali = 0x09bc;\n  t.nuktadeva = 0x093c;\n  t.nuktagujarati = 0x0abc;\n  t.nuktagurmukhi = 0x0a3c;\n  t.numbersign = 0x0023;\n  t.numbersignmonospace = 0xff03;\n  t.numbersignsmall = 0xfe5f;\n  t.numeralsigngreek = 0x0374;\n  t.numeralsignlowergreek = 0x0375;\n  t.numero = 0x2116;\n  t.nun = 0x05e0;\n  t.nundagesh = 0xfb40;\n  t.nundageshhebrew = 0xfb40;\n  t.nunhebrew = 0x05e0;\n  t.nvsquare = 0x33b5;\n  t.nwsquare = 0x33bb;\n  t.nyabengali = 0x099e;\n  t.nyadeva = 0x091e;\n  t.nyagujarati = 0x0a9e;\n  t.nyagurmukhi = 0x0a1e;\n  t.o = 0x006f;\n  t.oacute = 0x00f3;\n  t.oangthai = 0x0e2d;\n  t.obarred = 0x0275;\n  t.obarredcyrillic = 0x04e9;\n  t.obarreddieresiscyrillic = 0x04eb;\n  t.obengali = 0x0993;\n  t.obopomofo = 0x311b;\n  t.obreve = 0x014f;\n  t.ocandradeva = 0x0911;\n  t.ocandragujarati = 0x0a91;\n  t.ocandravowelsigndeva = 0x0949;\n  t.ocandravowelsigngujarati = 0x0ac9;\n  t.ocaron = 0x01d2;\n  t.ocircle = 0x24de;\n  t.ocircumflex = 0x00f4;\n  t.ocircumflexacute = 0x1ed1;\n  t.ocircumflexdotbelow = 0x1ed9;\n  t.ocircumflexgrave = 0x1ed3;\n  t.ocircumflexhookabove = 0x1ed5;\n  t.ocircumflextilde = 0x1ed7;\n  t.ocyrillic = 0x043e;\n  t.odblacute = 0x0151;\n  t.odblgrave = 0x020d;\n  t.odeva = 0x0913;\n  t.odieresis = 0x00f6;\n  t.odieresiscyrillic = 0x04e7;\n  t.odotbelow = 0x1ecd;\n  t.oe = 0x0153;\n  t.oekorean = 0x315a;\n  t.ogonek = 0x02db;\n  t.ogonekcmb = 0x0328;\n  t.ograve = 0x00f2;\n  t.ogujarati = 0x0a93;\n  t.oharmenian = 0x0585;\n  t.ohiragana = 0x304a;\n  t.ohookabove = 0x1ecf;\n  t.ohorn = 0x01a1;\n  t.ohornacute = 0x1edb;\n  t.ohorndotbelow = 0x1ee3;\n  t.ohorngrave = 0x1edd;\n  t.ohornhookabove = 0x1edf;\n  t.ohorntilde = 0x1ee1;\n  t.ohungarumlaut = 0x0151;\n  t.oi = 0x01a3;\n  t.oinvertedbreve = 0x020f;\n  t.okatakana = 0x30aa;\n  t.okatakanahalfwidth = 0xff75;\n  t.okorean = 0x3157;\n  t.olehebrew = 0x05ab;\n  t.omacron = 0x014d;\n  t.omacronacute = 0x1e53;\n  t.omacrongrave = 0x1e51;\n  t.omdeva = 0x0950;\n  t.omega = 0x03c9;\n  t.omega1 = 0x03d6;\n  t.omegacyrillic = 0x0461;\n  t.omegalatinclosed = 0x0277;\n  t.omegaroundcyrillic = 0x047b;\n  t.omegatitlocyrillic = 0x047d;\n  t.omegatonos = 0x03ce;\n  t.omgujarati = 0x0ad0;\n  t.omicron = 0x03bf;\n  t.omicrontonos = 0x03cc;\n  t.omonospace = 0xff4f;\n  t.one = 0x0031;\n  t.onearabic = 0x0661;\n  t.onebengali = 0x09e7;\n  t.onecircle = 0x2460;\n  t.onecircleinversesansserif = 0x278a;\n  t.onedeva = 0x0967;\n  t.onedotenleader = 0x2024;\n  t.oneeighth = 0x215b;\n  t.onefitted = 0xf6dc;\n  t.onegujarati = 0x0ae7;\n  t.onegurmukhi = 0x0a67;\n  t.onehackarabic = 0x0661;\n  t.onehalf = 0x00bd;\n  t.onehangzhou = 0x3021;\n  t.oneideographicparen = 0x3220;\n  t.oneinferior = 0x2081;\n  t.onemonospace = 0xff11;\n  t.onenumeratorbengali = 0x09f4;\n  t.oneoldstyle = 0xf731;\n  t.oneparen = 0x2474;\n  t.oneperiod = 0x2488;\n  t.onepersian = 0x06f1;\n  t.onequarter = 0x00bc;\n  t.oneroman = 0x2170;\n  t.onesuperior = 0x00b9;\n  t.onethai = 0x0e51;\n  t.onethird = 0x2153;\n  t.oogonek = 0x01eb;\n  t.oogonekmacron = 0x01ed;\n  t.oogurmukhi = 0x0a13;\n  t.oomatragurmukhi = 0x0a4b;\n  t.oopen = 0x0254;\n  t.oparen = 0x24aa;\n  t.openbullet = 0x25e6;\n  t.option = 0x2325;\n  t.ordfeminine = 0x00aa;\n  t.ordmasculine = 0x00ba;\n  t.orthogonal = 0x221f;\n  t.oshortdeva = 0x0912;\n  t.oshortvowelsigndeva = 0x094a;\n  t.oslash = 0x00f8;\n  t.oslashacute = 0x01ff;\n  t.osmallhiragana = 0x3049;\n  t.osmallkatakana = 0x30a9;\n  t.osmallkatakanahalfwidth = 0xff6b;\n  t.ostrokeacute = 0x01ff;\n  t.osuperior = 0xf6f0;\n  t.otcyrillic = 0x047f;\n  t.otilde = 0x00f5;\n  t.otildeacute = 0x1e4d;\n  t.otildedieresis = 0x1e4f;\n  t.oubopomofo = 0x3121;\n  t.overline = 0x203e;\n  t.overlinecenterline = 0xfe4a;\n  t.overlinecmb = 0x0305;\n  t.overlinedashed = 0xfe49;\n  t.overlinedblwavy = 0xfe4c;\n  t.overlinewavy = 0xfe4b;\n  t.overscore = 0x00af;\n  t.ovowelsignbengali = 0x09cb;\n  t.ovowelsigndeva = 0x094b;\n  t.ovowelsigngujarati = 0x0acb;\n  t.p = 0x0070;\n  t.paampssquare = 0x3380;\n  t.paasentosquare = 0x332b;\n  t.pabengali = 0x09aa;\n  t.pacute = 0x1e55;\n  t.padeva = 0x092a;\n  t.pagedown = 0x21df;\n  t.pageup = 0x21de;\n  t.pagujarati = 0x0aaa;\n  t.pagurmukhi = 0x0a2a;\n  t.pahiragana = 0x3071;\n  t.paiyannoithai = 0x0e2f;\n  t.pakatakana = 0x30d1;\n  t.palatalizationcyrilliccmb = 0x0484;\n  t.palochkacyrillic = 0x04c0;\n  t.pansioskorean = 0x317f;\n  t.paragraph = 0x00b6;\n  t.parallel = 0x2225;\n  t.parenleft = 0x0028;\n  t.parenleftaltonearabic = 0xfd3e;\n  t.parenleftbt = 0xf8ed;\n  t.parenleftex = 0xf8ec;\n  t.parenleftinferior = 0x208d;\n  t.parenleftmonospace = 0xff08;\n  t.parenleftsmall = 0xfe59;\n  t.parenleftsuperior = 0x207d;\n  t.parenlefttp = 0xf8eb;\n  t.parenleftvertical = 0xfe35;\n  t.parenright = 0x0029;\n  t.parenrightaltonearabic = 0xfd3f;\n  t.parenrightbt = 0xf8f8;\n  t.parenrightex = 0xf8f7;\n  t.parenrightinferior = 0x208e;\n  t.parenrightmonospace = 0xff09;\n  t.parenrightsmall = 0xfe5a;\n  t.parenrightsuperior = 0x207e;\n  t.parenrighttp = 0xf8f6;\n  t.parenrightvertical = 0xfe36;\n  t.partialdiff = 0x2202;\n  t.paseqhebrew = 0x05c0;\n  t.pashtahebrew = 0x0599;\n  t.pasquare = 0x33a9;\n  t.patah = 0x05b7;\n  t.patah11 = 0x05b7;\n  t.patah1d = 0x05b7;\n  t.patah2a = 0x05b7;\n  t.patahhebrew = 0x05b7;\n  t.patahnarrowhebrew = 0x05b7;\n  t.patahquarterhebrew = 0x05b7;\n  t.patahwidehebrew = 0x05b7;\n  t.pazerhebrew = 0x05a1;\n  t.pbopomofo = 0x3106;\n  t.pcircle = 0x24df;\n  t.pdotaccent = 0x1e57;\n  t.pe = 0x05e4;\n  t.pecyrillic = 0x043f;\n  t.pedagesh = 0xfb44;\n  t.pedageshhebrew = 0xfb44;\n  t.peezisquare = 0x333b;\n  t.pefinaldageshhebrew = 0xfb43;\n  t.peharabic = 0x067e;\n  t.peharmenian = 0x057a;\n  t.pehebrew = 0x05e4;\n  t.pehfinalarabic = 0xfb57;\n  t.pehinitialarabic = 0xfb58;\n  t.pehiragana = 0x307a;\n  t.pehmedialarabic = 0xfb59;\n  t.pekatakana = 0x30da;\n  t.pemiddlehookcyrillic = 0x04a7;\n  t.perafehebrew = 0xfb4e;\n  t.percent = 0x0025;\n  t.percentarabic = 0x066a;\n  t.percentmonospace = 0xff05;\n  t.percentsmall = 0xfe6a;\n  t.period = 0x002e;\n  t.periodarmenian = 0x0589;\n  t.periodcentered = 0x00b7;\n  t.periodhalfwidth = 0xff61;\n  t.periodinferior = 0xf6e7;\n  t.periodmonospace = 0xff0e;\n  t.periodsmall = 0xfe52;\n  t.periodsuperior = 0xf6e8;\n  t.perispomenigreekcmb = 0x0342;\n  t.perpendicular = 0x22a5;\n  t.perthousand = 0x2030;\n  t.peseta = 0x20a7;\n  t.pfsquare = 0x338a;\n  t.phabengali = 0x09ab;\n  t.phadeva = 0x092b;\n  t.phagujarati = 0x0aab;\n  t.phagurmukhi = 0x0a2b;\n  t.phi = 0x03c6;\n  t.phi1 = 0x03d5;\n  t.phieuphacirclekorean = 0x327a;\n  t.phieuphaparenkorean = 0x321a;\n  t.phieuphcirclekorean = 0x326c;\n  t.phieuphkorean = 0x314d;\n  t.phieuphparenkorean = 0x320c;\n  t.philatin = 0x0278;\n  t.phinthuthai = 0x0e3a;\n  t.phisymbolgreek = 0x03d5;\n  t.phook = 0x01a5;\n  t.phophanthai = 0x0e1e;\n  t.phophungthai = 0x0e1c;\n  t.phosamphaothai = 0x0e20;\n  t.pi = 0x03c0;\n  t.pieupacirclekorean = 0x3273;\n  t.pieupaparenkorean = 0x3213;\n  t.pieupcieuckorean = 0x3176;\n  t.pieupcirclekorean = 0x3265;\n  t.pieupkiyeokkorean = 0x3172;\n  t.pieupkorean = 0x3142;\n  t.pieupparenkorean = 0x3205;\n  t.pieupsioskiyeokkorean = 0x3174;\n  t.pieupsioskorean = 0x3144;\n  t.pieupsiostikeutkorean = 0x3175;\n  t.pieupthieuthkorean = 0x3177;\n  t.pieuptikeutkorean = 0x3173;\n  t.pihiragana = 0x3074;\n  t.pikatakana = 0x30d4;\n  t.pisymbolgreek = 0x03d6;\n  t.piwrarmenian = 0x0583;\n  t.planckover2pi = 0x210f;\n  t.planckover2pi1 = 0x210f;\n  t.plus = 0x002b;\n  t.plusbelowcmb = 0x031f;\n  t.pluscircle = 0x2295;\n  t.plusminus = 0x00b1;\n  t.plusmod = 0x02d6;\n  t.plusmonospace = 0xff0b;\n  t.plussmall = 0xfe62;\n  t.plussuperior = 0x207a;\n  t.pmonospace = 0xff50;\n  t.pmsquare = 0x33d8;\n  t.pohiragana = 0x307d;\n  t.pointingindexdownwhite = 0x261f;\n  t.pointingindexleftwhite = 0x261c;\n  t.pointingindexrightwhite = 0x261e;\n  t.pointingindexupwhite = 0x261d;\n  t.pokatakana = 0x30dd;\n  t.poplathai = 0x0e1b;\n  t.postalmark = 0x3012;\n  t.postalmarkface = 0x3020;\n  t.pparen = 0x24ab;\n  t.precedes = 0x227a;\n  t.prescription = 0x211e;\n  t.primemod = 0x02b9;\n  t.primereversed = 0x2035;\n  t.product = 0x220f;\n  t.projective = 0x2305;\n  t.prolongedkana = 0x30fc;\n  t.propellor = 0x2318;\n  t.propersubset = 0x2282;\n  t.propersuperset = 0x2283;\n  t.proportion = 0x2237;\n  t.proportional = 0x221d;\n  t.psi = 0x03c8;\n  t.psicyrillic = 0x0471;\n  t.psilipneumatacyrilliccmb = 0x0486;\n  t.pssquare = 0x33b0;\n  t.puhiragana = 0x3077;\n  t.pukatakana = 0x30d7;\n  t.pvsquare = 0x33b4;\n  t.pwsquare = 0x33ba;\n  t.q = 0x0071;\n  t.qadeva = 0x0958;\n  t.qadmahebrew = 0x05a8;\n  t.qafarabic = 0x0642;\n  t.qaffinalarabic = 0xfed6;\n  t.qafinitialarabic = 0xfed7;\n  t.qafmedialarabic = 0xfed8;\n  t.qamats = 0x05b8;\n  t.qamats10 = 0x05b8;\n  t.qamats1a = 0x05b8;\n  t.qamats1c = 0x05b8;\n  t.qamats27 = 0x05b8;\n  t.qamats29 = 0x05b8;\n  t.qamats33 = 0x05b8;\n  t.qamatsde = 0x05b8;\n  t.qamatshebrew = 0x05b8;\n  t.qamatsnarrowhebrew = 0x05b8;\n  t.qamatsqatanhebrew = 0x05b8;\n  t.qamatsqatannarrowhebrew = 0x05b8;\n  t.qamatsqatanquarterhebrew = 0x05b8;\n  t.qamatsqatanwidehebrew = 0x05b8;\n  t.qamatsquarterhebrew = 0x05b8;\n  t.qamatswidehebrew = 0x05b8;\n  t.qarneyparahebrew = 0x059f;\n  t.qbopomofo = 0x3111;\n  t.qcircle = 0x24e0;\n  t.qhook = 0x02a0;\n  t.qmonospace = 0xff51;\n  t.qof = 0x05e7;\n  t.qofdagesh = 0xfb47;\n  t.qofdageshhebrew = 0xfb47;\n  t.qofhebrew = 0x05e7;\n  t.qparen = 0x24ac;\n  t.quarternote = 0x2669;\n  t.qubuts = 0x05bb;\n  t.qubuts18 = 0x05bb;\n  t.qubuts25 = 0x05bb;\n  t.qubuts31 = 0x05bb;\n  t.qubutshebrew = 0x05bb;\n  t.qubutsnarrowhebrew = 0x05bb;\n  t.qubutsquarterhebrew = 0x05bb;\n  t.qubutswidehebrew = 0x05bb;\n  t.question = 0x003f;\n  t.questionarabic = 0x061f;\n  t.questionarmenian = 0x055e;\n  t.questiondown = 0x00bf;\n  t.questiondownsmall = 0xf7bf;\n  t.questiongreek = 0x037e;\n  t.questionmonospace = 0xff1f;\n  t.questionsmall = 0xf73f;\n  t.quotedbl = 0x0022;\n  t.quotedblbase = 0x201e;\n  t.quotedblleft = 0x201c;\n  t.quotedblmonospace = 0xff02;\n  t.quotedblprime = 0x301e;\n  t.quotedblprimereversed = 0x301d;\n  t.quotedblright = 0x201d;\n  t.quoteleft = 0x2018;\n  t.quoteleftreversed = 0x201b;\n  t.quotereversed = 0x201b;\n  t.quoteright = 0x2019;\n  t.quoterightn = 0x0149;\n  t.quotesinglbase = 0x201a;\n  t.quotesingle = 0x0027;\n  t.quotesinglemonospace = 0xff07;\n  t.r = 0x0072;\n  t.raarmenian = 0x057c;\n  t.rabengali = 0x09b0;\n  t.racute = 0x0155;\n  t.radeva = 0x0930;\n  t.radical = 0x221a;\n  t.radicalex = 0xf8e5;\n  t.radoverssquare = 0x33ae;\n  t.radoverssquaredsquare = 0x33af;\n  t.radsquare = 0x33ad;\n  t.rafe = 0x05bf;\n  t.rafehebrew = 0x05bf;\n  t.ragujarati = 0x0ab0;\n  t.ragurmukhi = 0x0a30;\n  t.rahiragana = 0x3089;\n  t.rakatakana = 0x30e9;\n  t.rakatakanahalfwidth = 0xff97;\n  t.ralowerdiagonalbengali = 0x09f1;\n  t.ramiddlediagonalbengali = 0x09f0;\n  t.ramshorn = 0x0264;\n  t.ratio = 0x2236;\n  t.rbopomofo = 0x3116;\n  t.rcaron = 0x0159;\n  t.rcedilla = 0x0157;\n  t.rcircle = 0x24e1;\n  t.rcommaaccent = 0x0157;\n  t.rdblgrave = 0x0211;\n  t.rdotaccent = 0x1e59;\n  t.rdotbelow = 0x1e5b;\n  t.rdotbelowmacron = 0x1e5d;\n  t.referencemark = 0x203b;\n  t.reflexsubset = 0x2286;\n  t.reflexsuperset = 0x2287;\n  t.registered = 0x00ae;\n  t.registersans = 0xf8e8;\n  t.registerserif = 0xf6da;\n  t.reharabic = 0x0631;\n  t.reharmenian = 0x0580;\n  t.rehfinalarabic = 0xfeae;\n  t.rehiragana = 0x308c;\n  t.rekatakana = 0x30ec;\n  t.rekatakanahalfwidth = 0xff9a;\n  t.resh = 0x05e8;\n  t.reshdageshhebrew = 0xfb48;\n  t.reshhebrew = 0x05e8;\n  t.reversedtilde = 0x223d;\n  t.reviahebrew = 0x0597;\n  t.reviamugrashhebrew = 0x0597;\n  t.revlogicalnot = 0x2310;\n  t.rfishhook = 0x027e;\n  t.rfishhookreversed = 0x027f;\n  t.rhabengali = 0x09dd;\n  t.rhadeva = 0x095d;\n  t.rho = 0x03c1;\n  t.rhook = 0x027d;\n  t.rhookturned = 0x027b;\n  t.rhookturnedsuperior = 0x02b5;\n  t.rhosymbolgreek = 0x03f1;\n  t.rhotichookmod = 0x02de;\n  t.rieulacirclekorean = 0x3271;\n  t.rieulaparenkorean = 0x3211;\n  t.rieulcirclekorean = 0x3263;\n  t.rieulhieuhkorean = 0x3140;\n  t.rieulkiyeokkorean = 0x313a;\n  t.rieulkiyeoksioskorean = 0x3169;\n  t.rieulkorean = 0x3139;\n  t.rieulmieumkorean = 0x313b;\n  t.rieulpansioskorean = 0x316c;\n  t.rieulparenkorean = 0x3203;\n  t.rieulphieuphkorean = 0x313f;\n  t.rieulpieupkorean = 0x313c;\n  t.rieulpieupsioskorean = 0x316b;\n  t.rieulsioskorean = 0x313d;\n  t.rieulthieuthkorean = 0x313e;\n  t.rieultikeutkorean = 0x316a;\n  t.rieulyeorinhieuhkorean = 0x316d;\n  t.rightangle = 0x221f;\n  t.righttackbelowcmb = 0x0319;\n  t.righttriangle = 0x22bf;\n  t.rihiragana = 0x308a;\n  t.rikatakana = 0x30ea;\n  t.rikatakanahalfwidth = 0xff98;\n  t.ring = 0x02da;\n  t.ringbelowcmb = 0x0325;\n  t.ringcmb = 0x030a;\n  t.ringhalfleft = 0x02bf;\n  t.ringhalfleftarmenian = 0x0559;\n  t.ringhalfleftbelowcmb = 0x031c;\n  t.ringhalfleftcentered = 0x02d3;\n  t.ringhalfright = 0x02be;\n  t.ringhalfrightbelowcmb = 0x0339;\n  t.ringhalfrightcentered = 0x02d2;\n  t.rinvertedbreve = 0x0213;\n  t.rittorusquare = 0x3351;\n  t.rlinebelow = 0x1e5f;\n  t.rlongleg = 0x027c;\n  t.rlonglegturned = 0x027a;\n  t.rmonospace = 0xff52;\n  t.rohiragana = 0x308d;\n  t.rokatakana = 0x30ed;\n  t.rokatakanahalfwidth = 0xff9b;\n  t.roruathai = 0x0e23;\n  t.rparen = 0x24ad;\n  t.rrabengali = 0x09dc;\n  t.rradeva = 0x0931;\n  t.rragurmukhi = 0x0a5c;\n  t.rreharabic = 0x0691;\n  t.rrehfinalarabic = 0xfb8d;\n  t.rrvocalicbengali = 0x09e0;\n  t.rrvocalicdeva = 0x0960;\n  t.rrvocalicgujarati = 0x0ae0;\n  t.rrvocalicvowelsignbengali = 0x09c4;\n  t.rrvocalicvowelsigndeva = 0x0944;\n  t.rrvocalicvowelsigngujarati = 0x0ac4;\n  t.rsuperior = 0xf6f1;\n  t.rtblock = 0x2590;\n  t.rturned = 0x0279;\n  t.rturnedsuperior = 0x02b4;\n  t.ruhiragana = 0x308b;\n  t.rukatakana = 0x30eb;\n  t.rukatakanahalfwidth = 0xff99;\n  t.rupeemarkbengali = 0x09f2;\n  t.rupeesignbengali = 0x09f3;\n  t.rupiah = 0xf6dd;\n  t.ruthai = 0x0e24;\n  t.rvocalicbengali = 0x098b;\n  t.rvocalicdeva = 0x090b;\n  t.rvocalicgujarati = 0x0a8b;\n  t.rvocalicvowelsignbengali = 0x09c3;\n  t.rvocalicvowelsigndeva = 0x0943;\n  t.rvocalicvowelsigngujarati = 0x0ac3;\n  t.s = 0x0073;\n  t.sabengali = 0x09b8;\n  t.sacute = 0x015b;\n  t.sacutedotaccent = 0x1e65;\n  t.sadarabic = 0x0635;\n  t.sadeva = 0x0938;\n  t.sadfinalarabic = 0xfeba;\n  t.sadinitialarabic = 0xfebb;\n  t.sadmedialarabic = 0xfebc;\n  t.sagujarati = 0x0ab8;\n  t.sagurmukhi = 0x0a38;\n  t.sahiragana = 0x3055;\n  t.sakatakana = 0x30b5;\n  t.sakatakanahalfwidth = 0xff7b;\n  t.sallallahoualayhewasallamarabic = 0xfdfa;\n  t.samekh = 0x05e1;\n  t.samekhdagesh = 0xfb41;\n  t.samekhdageshhebrew = 0xfb41;\n  t.samekhhebrew = 0x05e1;\n  t.saraaathai = 0x0e32;\n  t.saraaethai = 0x0e41;\n  t.saraaimaimalaithai = 0x0e44;\n  t.saraaimaimuanthai = 0x0e43;\n  t.saraamthai = 0x0e33;\n  t.saraathai = 0x0e30;\n  t.saraethai = 0x0e40;\n  t.saraiileftthai = 0xf886;\n  t.saraiithai = 0x0e35;\n  t.saraileftthai = 0xf885;\n  t.saraithai = 0x0e34;\n  t.saraothai = 0x0e42;\n  t.saraueeleftthai = 0xf888;\n  t.saraueethai = 0x0e37;\n  t.saraueleftthai = 0xf887;\n  t.sarauethai = 0x0e36;\n  t.sarauthai = 0x0e38;\n  t.sarauuthai = 0x0e39;\n  t.sbopomofo = 0x3119;\n  t.scaron = 0x0161;\n  t.scarondotaccent = 0x1e67;\n  t.scedilla = 0x015f;\n  t.schwa = 0x0259;\n  t.schwacyrillic = 0x04d9;\n  t.schwadieresiscyrillic = 0x04db;\n  t.schwahook = 0x025a;\n  t.scircle = 0x24e2;\n  t.scircumflex = 0x015d;\n  t.scommaaccent = 0x0219;\n  t.sdotaccent = 0x1e61;\n  t.sdotbelow = 0x1e63;\n  t.sdotbelowdotaccent = 0x1e69;\n  t.seagullbelowcmb = 0x033c;\n  t.second = 0x2033;\n  t.secondtonechinese = 0x02ca;\n  t.section = 0x00a7;\n  t.seenarabic = 0x0633;\n  t.seenfinalarabic = 0xfeb2;\n  t.seeninitialarabic = 0xfeb3;\n  t.seenmedialarabic = 0xfeb4;\n  t.segol = 0x05b6;\n  t.segol13 = 0x05b6;\n  t.segol1f = 0x05b6;\n  t.segol2c = 0x05b6;\n  t.segolhebrew = 0x05b6;\n  t.segolnarrowhebrew = 0x05b6;\n  t.segolquarterhebrew = 0x05b6;\n  t.segoltahebrew = 0x0592;\n  t.segolwidehebrew = 0x05b6;\n  t.seharmenian = 0x057d;\n  t.sehiragana = 0x305b;\n  t.sekatakana = 0x30bb;\n  t.sekatakanahalfwidth = 0xff7e;\n  t.semicolon = 0x003b;\n  t.semicolonarabic = 0x061b;\n  t.semicolonmonospace = 0xff1b;\n  t.semicolonsmall = 0xfe54;\n  t.semivoicedmarkkana = 0x309c;\n  t.semivoicedmarkkanahalfwidth = 0xff9f;\n  t.sentisquare = 0x3322;\n  t.sentosquare = 0x3323;\n  t.seven = 0x0037;\n  t.sevenarabic = 0x0667;\n  t.sevenbengali = 0x09ed;\n  t.sevencircle = 0x2466;\n  t.sevencircleinversesansserif = 0x2790;\n  t.sevendeva = 0x096d;\n  t.seveneighths = 0x215e;\n  t.sevengujarati = 0x0aed;\n  t.sevengurmukhi = 0x0a6d;\n  t.sevenhackarabic = 0x0667;\n  t.sevenhangzhou = 0x3027;\n  t.sevenideographicparen = 0x3226;\n  t.seveninferior = 0x2087;\n  t.sevenmonospace = 0xff17;\n  t.sevenoldstyle = 0xf737;\n  t.sevenparen = 0x247a;\n  t.sevenperiod = 0x248e;\n  t.sevenpersian = 0x06f7;\n  t.sevenroman = 0x2176;\n  t.sevensuperior = 0x2077;\n  t.seventeencircle = 0x2470;\n  t.seventeenparen = 0x2484;\n  t.seventeenperiod = 0x2498;\n  t.seventhai = 0x0e57;\n  t.sfthyphen = 0x00ad;\n  t.shaarmenian = 0x0577;\n  t.shabengali = 0x09b6;\n  t.shacyrillic = 0x0448;\n  t.shaddaarabic = 0x0651;\n  t.shaddadammaarabic = 0xfc61;\n  t.shaddadammatanarabic = 0xfc5e;\n  t.shaddafathaarabic = 0xfc60;\n  t.shaddakasraarabic = 0xfc62;\n  t.shaddakasratanarabic = 0xfc5f;\n  t.shade = 0x2592;\n  t.shadedark = 0x2593;\n  t.shadelight = 0x2591;\n  t.shademedium = 0x2592;\n  t.shadeva = 0x0936;\n  t.shagujarati = 0x0ab6;\n  t.shagurmukhi = 0x0a36;\n  t.shalshelethebrew = 0x0593;\n  t.shbopomofo = 0x3115;\n  t.shchacyrillic = 0x0449;\n  t.sheenarabic = 0x0634;\n  t.sheenfinalarabic = 0xfeb6;\n  t.sheeninitialarabic = 0xfeb7;\n  t.sheenmedialarabic = 0xfeb8;\n  t.sheicoptic = 0x03e3;\n  t.sheqel = 0x20aa;\n  t.sheqelhebrew = 0x20aa;\n  t.sheva = 0x05b0;\n  t.sheva115 = 0x05b0;\n  t.sheva15 = 0x05b0;\n  t.sheva22 = 0x05b0;\n  t.sheva2e = 0x05b0;\n  t.shevahebrew = 0x05b0;\n  t.shevanarrowhebrew = 0x05b0;\n  t.shevaquarterhebrew = 0x05b0;\n  t.shevawidehebrew = 0x05b0;\n  t.shhacyrillic = 0x04bb;\n  t.shimacoptic = 0x03ed;\n  t.shin = 0x05e9;\n  t.shindagesh = 0xfb49;\n  t.shindageshhebrew = 0xfb49;\n  t.shindageshshindot = 0xfb2c;\n  t.shindageshshindothebrew = 0xfb2c;\n  t.shindageshsindot = 0xfb2d;\n  t.shindageshsindothebrew = 0xfb2d;\n  t.shindothebrew = 0x05c1;\n  t.shinhebrew = 0x05e9;\n  t.shinshindot = 0xfb2a;\n  t.shinshindothebrew = 0xfb2a;\n  t.shinsindot = 0xfb2b;\n  t.shinsindothebrew = 0xfb2b;\n  t.shook = 0x0282;\n  t.sigma = 0x03c3;\n  t.sigma1 = 0x03c2;\n  t.sigmafinal = 0x03c2;\n  t.sigmalunatesymbolgreek = 0x03f2;\n  t.sihiragana = 0x3057;\n  t.sikatakana = 0x30b7;\n  t.sikatakanahalfwidth = 0xff7c;\n  t.siluqhebrew = 0x05bd;\n  t.siluqlefthebrew = 0x05bd;\n  t.similar = 0x223c;\n  t.sindothebrew = 0x05c2;\n  t.siosacirclekorean = 0x3274;\n  t.siosaparenkorean = 0x3214;\n  t.sioscieuckorean = 0x317e;\n  t.sioscirclekorean = 0x3266;\n  t.sioskiyeokkorean = 0x317a;\n  t.sioskorean = 0x3145;\n  t.siosnieunkorean = 0x317b;\n  t.siosparenkorean = 0x3206;\n  t.siospieupkorean = 0x317d;\n  t.siostikeutkorean = 0x317c;\n  t.six = 0x0036;\n  t.sixarabic = 0x0666;\n  t.sixbengali = 0x09ec;\n  t.sixcircle = 0x2465;\n  t.sixcircleinversesansserif = 0x278f;\n  t.sixdeva = 0x096c;\n  t.sixgujarati = 0x0aec;\n  t.sixgurmukhi = 0x0a6c;\n  t.sixhackarabic = 0x0666;\n  t.sixhangzhou = 0x3026;\n  t.sixideographicparen = 0x3225;\n  t.sixinferior = 0x2086;\n  t.sixmonospace = 0xff16;\n  t.sixoldstyle = 0xf736;\n  t.sixparen = 0x2479;\n  t.sixperiod = 0x248d;\n  t.sixpersian = 0x06f6;\n  t.sixroman = 0x2175;\n  t.sixsuperior = 0x2076;\n  t.sixteencircle = 0x246f;\n  t.sixteencurrencydenominatorbengali = 0x09f9;\n  t.sixteenparen = 0x2483;\n  t.sixteenperiod = 0x2497;\n  t.sixthai = 0x0e56;\n  t.slash = 0x002f;\n  t.slashmonospace = 0xff0f;\n  t.slong = 0x017f;\n  t.slongdotaccent = 0x1e9b;\n  t.smileface = 0x263a;\n  t.smonospace = 0xff53;\n  t.sofpasuqhebrew = 0x05c3;\n  t.softhyphen = 0x00ad;\n  t.softsigncyrillic = 0x044c;\n  t.sohiragana = 0x305d;\n  t.sokatakana = 0x30bd;\n  t.sokatakanahalfwidth = 0xff7f;\n  t.soliduslongoverlaycmb = 0x0338;\n  t.solidusshortoverlaycmb = 0x0337;\n  t.sorusithai = 0x0e29;\n  t.sosalathai = 0x0e28;\n  t.sosothai = 0x0e0b;\n  t.sosuathai = 0x0e2a;\n  t.space = 0x0020;\n  t.spacehackarabic = 0x0020;\n  t.spade = 0x2660;\n  t.spadesuitblack = 0x2660;\n  t.spadesuitwhite = 0x2664;\n  t.sparen = 0x24ae;\n  t.squarebelowcmb = 0x033b;\n  t.squarecc = 0x33c4;\n  t.squarecm = 0x339d;\n  t.squarediagonalcrosshatchfill = 0x25a9;\n  t.squarehorizontalfill = 0x25a4;\n  t.squarekg = 0x338f;\n  t.squarekm = 0x339e;\n  t.squarekmcapital = 0x33ce;\n  t.squareln = 0x33d1;\n  t.squarelog = 0x33d2;\n  t.squaremg = 0x338e;\n  t.squaremil = 0x33d5;\n  t.squaremm = 0x339c;\n  t.squaremsquared = 0x33a1;\n  t.squareorthogonalcrosshatchfill = 0x25a6;\n  t.squareupperlefttolowerrightfill = 0x25a7;\n  t.squareupperrighttolowerleftfill = 0x25a8;\n  t.squareverticalfill = 0x25a5;\n  t.squarewhitewithsmallblack = 0x25a3;\n  t.srsquare = 0x33db;\n  t.ssabengali = 0x09b7;\n  t.ssadeva = 0x0937;\n  t.ssagujarati = 0x0ab7;\n  t.ssangcieuckorean = 0x3149;\n  t.ssanghieuhkorean = 0x3185;\n  t.ssangieungkorean = 0x3180;\n  t.ssangkiyeokkorean = 0x3132;\n  t.ssangnieunkorean = 0x3165;\n  t.ssangpieupkorean = 0x3143;\n  t.ssangsioskorean = 0x3146;\n  t.ssangtikeutkorean = 0x3138;\n  t.ssuperior = 0xf6f2;\n  t.sterling = 0x00a3;\n  t.sterlingmonospace = 0xffe1;\n  t.strokelongoverlaycmb = 0x0336;\n  t.strokeshortoverlaycmb = 0x0335;\n  t.subset = 0x2282;\n  t.subsetnotequal = 0x228a;\n  t.subsetorequal = 0x2286;\n  t.succeeds = 0x227b;\n  t.suchthat = 0x220b;\n  t.suhiragana = 0x3059;\n  t.sukatakana = 0x30b9;\n  t.sukatakanahalfwidth = 0xff7d;\n  t.sukunarabic = 0x0652;\n  t.summation = 0x2211;\n  t.sun = 0x263c;\n  t.superset = 0x2283;\n  t.supersetnotequal = 0x228b;\n  t.supersetorequal = 0x2287;\n  t.svsquare = 0x33dc;\n  t.syouwaerasquare = 0x337c;\n  t.t = 0x0074;\n  t.tabengali = 0x09a4;\n  t.tackdown = 0x22a4;\n  t.tackleft = 0x22a3;\n  t.tadeva = 0x0924;\n  t.tagujarati = 0x0aa4;\n  t.tagurmukhi = 0x0a24;\n  t.taharabic = 0x0637;\n  t.tahfinalarabic = 0xfec2;\n  t.tahinitialarabic = 0xfec3;\n  t.tahiragana = 0x305f;\n  t.tahmedialarabic = 0xfec4;\n  t.taisyouerasquare = 0x337d;\n  t.takatakana = 0x30bf;\n  t.takatakanahalfwidth = 0xff80;\n  t.tatweelarabic = 0x0640;\n  t.tau = 0x03c4;\n  t.tav = 0x05ea;\n  t.tavdages = 0xfb4a;\n  t.tavdagesh = 0xfb4a;\n  t.tavdageshhebrew = 0xfb4a;\n  t.tavhebrew = 0x05ea;\n  t.tbar = 0x0167;\n  t.tbopomofo = 0x310a;\n  t.tcaron = 0x0165;\n  t.tccurl = 0x02a8;\n  t.tcedilla = 0x0163;\n  t.tcheharabic = 0x0686;\n  t.tchehfinalarabic = 0xfb7b;\n  t.tchehinitialarabic = 0xfb7c;\n  t.tchehmedialarabic = 0xfb7d;\n  t.tcircle = 0x24e3;\n  t.tcircumflexbelow = 0x1e71;\n  t.tcommaaccent = 0x0163;\n  t.tdieresis = 0x1e97;\n  t.tdotaccent = 0x1e6b;\n  t.tdotbelow = 0x1e6d;\n  t.tecyrillic = 0x0442;\n  t.tedescendercyrillic = 0x04ad;\n  t.teharabic = 0x062a;\n  t.tehfinalarabic = 0xfe96;\n  t.tehhahinitialarabic = 0xfca2;\n  t.tehhahisolatedarabic = 0xfc0c;\n  t.tehinitialarabic = 0xfe97;\n  t.tehiragana = 0x3066;\n  t.tehjeeminitialarabic = 0xfca1;\n  t.tehjeemisolatedarabic = 0xfc0b;\n  t.tehmarbutaarabic = 0x0629;\n  t.tehmarbutafinalarabic = 0xfe94;\n  t.tehmedialarabic = 0xfe98;\n  t.tehmeeminitialarabic = 0xfca4;\n  t.tehmeemisolatedarabic = 0xfc0e;\n  t.tehnoonfinalarabic = 0xfc73;\n  t.tekatakana = 0x30c6;\n  t.tekatakanahalfwidth = 0xff83;\n  t.telephone = 0x2121;\n  t.telephoneblack = 0x260e;\n  t.telishagedolahebrew = 0x05a0;\n  t.telishaqetanahebrew = 0x05a9;\n  t.tencircle = 0x2469;\n  t.tenideographicparen = 0x3229;\n  t.tenparen = 0x247d;\n  t.tenperiod = 0x2491;\n  t.tenroman = 0x2179;\n  t.tesh = 0x02a7;\n  t.tet = 0x05d8;\n  t.tetdagesh = 0xfb38;\n  t.tetdageshhebrew = 0xfb38;\n  t.tethebrew = 0x05d8;\n  t.tetsecyrillic = 0x04b5;\n  t.tevirhebrew = 0x059b;\n  t.tevirlefthebrew = 0x059b;\n  t.thabengali = 0x09a5;\n  t.thadeva = 0x0925;\n  t.thagujarati = 0x0aa5;\n  t.thagurmukhi = 0x0a25;\n  t.thalarabic = 0x0630;\n  t.thalfinalarabic = 0xfeac;\n  t.thanthakhatlowleftthai = 0xf898;\n  t.thanthakhatlowrightthai = 0xf897;\n  t.thanthakhatthai = 0x0e4c;\n  t.thanthakhatupperleftthai = 0xf896;\n  t.theharabic = 0x062b;\n  t.thehfinalarabic = 0xfe9a;\n  t.thehinitialarabic = 0xfe9b;\n  t.thehmedialarabic = 0xfe9c;\n  t.thereexists = 0x2203;\n  t.therefore = 0x2234;\n  t.theta = 0x03b8;\n  t.theta1 = 0x03d1;\n  t.thetasymbolgreek = 0x03d1;\n  t.thieuthacirclekorean = 0x3279;\n  t.thieuthaparenkorean = 0x3219;\n  t.thieuthcirclekorean = 0x326b;\n  t.thieuthkorean = 0x314c;\n  t.thieuthparenkorean = 0x320b;\n  t.thirteencircle = 0x246c;\n  t.thirteenparen = 0x2480;\n  t.thirteenperiod = 0x2494;\n  t.thonangmonthothai = 0x0e11;\n  t.thook = 0x01ad;\n  t.thophuthaothai = 0x0e12;\n  t.thorn = 0x00fe;\n  t.thothahanthai = 0x0e17;\n  t.thothanthai = 0x0e10;\n  t.thothongthai = 0x0e18;\n  t.thothungthai = 0x0e16;\n  t.thousandcyrillic = 0x0482;\n  t.thousandsseparatorarabic = 0x066c;\n  t.thousandsseparatorpersian = 0x066c;\n  t.three = 0x0033;\n  t.threearabic = 0x0663;\n  t.threebengali = 0x09e9;\n  t.threecircle = 0x2462;\n  t.threecircleinversesansserif = 0x278c;\n  t.threedeva = 0x0969;\n  t.threeeighths = 0x215c;\n  t.threegujarati = 0x0ae9;\n  t.threegurmukhi = 0x0a69;\n  t.threehackarabic = 0x0663;\n  t.threehangzhou = 0x3023;\n  t.threeideographicparen = 0x3222;\n  t.threeinferior = 0x2083;\n  t.threemonospace = 0xff13;\n  t.threenumeratorbengali = 0x09f6;\n  t.threeoldstyle = 0xf733;\n  t.threeparen = 0x2476;\n  t.threeperiod = 0x248a;\n  t.threepersian = 0x06f3;\n  t.threequarters = 0x00be;\n  t.threequartersemdash = 0xf6de;\n  t.threeroman = 0x2172;\n  t.threesuperior = 0x00b3;\n  t.threethai = 0x0e53;\n  t.thzsquare = 0x3394;\n  t.tihiragana = 0x3061;\n  t.tikatakana = 0x30c1;\n  t.tikatakanahalfwidth = 0xff81;\n  t.tikeutacirclekorean = 0x3270;\n  t.tikeutaparenkorean = 0x3210;\n  t.tikeutcirclekorean = 0x3262;\n  t.tikeutkorean = 0x3137;\n  t.tikeutparenkorean = 0x3202;\n  t.tilde = 0x02dc;\n  t.tildebelowcmb = 0x0330;\n  t.tildecmb = 0x0303;\n  t.tildecomb = 0x0303;\n  t.tildedoublecmb = 0x0360;\n  t.tildeoperator = 0x223c;\n  t.tildeoverlaycmb = 0x0334;\n  t.tildeverticalcmb = 0x033e;\n  t.timescircle = 0x2297;\n  t.tipehahebrew = 0x0596;\n  t.tipehalefthebrew = 0x0596;\n  t.tippigurmukhi = 0x0a70;\n  t.titlocyrilliccmb = 0x0483;\n  t.tiwnarmenian = 0x057f;\n  t.tlinebelow = 0x1e6f;\n  t.tmonospace = 0xff54;\n  t.toarmenian = 0x0569;\n  t.tohiragana = 0x3068;\n  t.tokatakana = 0x30c8;\n  t.tokatakanahalfwidth = 0xff84;\n  t.tonebarextrahighmod = 0x02e5;\n  t.tonebarextralowmod = 0x02e9;\n  t.tonebarhighmod = 0x02e6;\n  t.tonebarlowmod = 0x02e8;\n  t.tonebarmidmod = 0x02e7;\n  t.tonefive = 0x01bd;\n  t.tonesix = 0x0185;\n  t.tonetwo = 0x01a8;\n  t.tonos = 0x0384;\n  t.tonsquare = 0x3327;\n  t.topatakthai = 0x0e0f;\n  t.tortoiseshellbracketleft = 0x3014;\n  t.tortoiseshellbracketleftsmall = 0xfe5d;\n  t.tortoiseshellbracketleftvertical = 0xfe39;\n  t.tortoiseshellbracketright = 0x3015;\n  t.tortoiseshellbracketrightsmall = 0xfe5e;\n  t.tortoiseshellbracketrightvertical = 0xfe3a;\n  t.totaothai = 0x0e15;\n  t.tpalatalhook = 0x01ab;\n  t.tparen = 0x24af;\n  t.trademark = 0x2122;\n  t.trademarksans = 0xf8ea;\n  t.trademarkserif = 0xf6db;\n  t.tretroflexhook = 0x0288;\n  t.triagdn = 0x25bc;\n  t.triaglf = 0x25c4;\n  t.triagrt = 0x25ba;\n  t.triagup = 0x25b2;\n  t.ts = 0x02a6;\n  t.tsadi = 0x05e6;\n  t.tsadidagesh = 0xfb46;\n  t.tsadidageshhebrew = 0xfb46;\n  t.tsadihebrew = 0x05e6;\n  t.tsecyrillic = 0x0446;\n  t.tsere = 0x05b5;\n  t.tsere12 = 0x05b5;\n  t.tsere1e = 0x05b5;\n  t.tsere2b = 0x05b5;\n  t.tserehebrew = 0x05b5;\n  t.tserenarrowhebrew = 0x05b5;\n  t.tserequarterhebrew = 0x05b5;\n  t.tserewidehebrew = 0x05b5;\n  t.tshecyrillic = 0x045b;\n  t.tsuperior = 0xf6f3;\n  t.ttabengali = 0x099f;\n  t.ttadeva = 0x091f;\n  t.ttagujarati = 0x0a9f;\n  t.ttagurmukhi = 0x0a1f;\n  t.tteharabic = 0x0679;\n  t.ttehfinalarabic = 0xfb67;\n  t.ttehinitialarabic = 0xfb68;\n  t.ttehmedialarabic = 0xfb69;\n  t.tthabengali = 0x09a0;\n  t.tthadeva = 0x0920;\n  t.tthagujarati = 0x0aa0;\n  t.tthagurmukhi = 0x0a20;\n  t.tturned = 0x0287;\n  t.tuhiragana = 0x3064;\n  t.tukatakana = 0x30c4;\n  t.tukatakanahalfwidth = 0xff82;\n  t.tusmallhiragana = 0x3063;\n  t.tusmallkatakana = 0x30c3;\n  t.tusmallkatakanahalfwidth = 0xff6f;\n  t.twelvecircle = 0x246b;\n  t.twelveparen = 0x247f;\n  t.twelveperiod = 0x2493;\n  t.twelveroman = 0x217b;\n  t.twentycircle = 0x2473;\n  t.twentyhangzhou = 0x5344;\n  t.twentyparen = 0x2487;\n  t.twentyperiod = 0x249b;\n  t.two = 0x0032;\n  t.twoarabic = 0x0662;\n  t.twobengali = 0x09e8;\n  t.twocircle = 0x2461;\n  t.twocircleinversesansserif = 0x278b;\n  t.twodeva = 0x0968;\n  t.twodotenleader = 0x2025;\n  t.twodotleader = 0x2025;\n  t.twodotleadervertical = 0xfe30;\n  t.twogujarati = 0x0ae8;\n  t.twogurmukhi = 0x0a68;\n  t.twohackarabic = 0x0662;\n  t.twohangzhou = 0x3022;\n  t.twoideographicparen = 0x3221;\n  t.twoinferior = 0x2082;\n  t.twomonospace = 0xff12;\n  t.twonumeratorbengali = 0x09f5;\n  t.twooldstyle = 0xf732;\n  t.twoparen = 0x2475;\n  t.twoperiod = 0x2489;\n  t.twopersian = 0x06f2;\n  t.tworoman = 0x2171;\n  t.twostroke = 0x01bb;\n  t.twosuperior = 0x00b2;\n  t.twothai = 0x0e52;\n  t.twothirds = 0x2154;\n  t.u = 0x0075;\n  t.uacute = 0x00fa;\n  t.ubar = 0x0289;\n  t.ubengali = 0x0989;\n  t.ubopomofo = 0x3128;\n  t.ubreve = 0x016d;\n  t.ucaron = 0x01d4;\n  t.ucircle = 0x24e4;\n  t.ucircumflex = 0x00fb;\n  t.ucircumflexbelow = 0x1e77;\n  t.ucyrillic = 0x0443;\n  t.udattadeva = 0x0951;\n  t.udblacute = 0x0171;\n  t.udblgrave = 0x0215;\n  t.udeva = 0x0909;\n  t.udieresis = 0x00fc;\n  t.udieresisacute = 0x01d8;\n  t.udieresisbelow = 0x1e73;\n  t.udieresiscaron = 0x01da;\n  t.udieresiscyrillic = 0x04f1;\n  t.udieresisgrave = 0x01dc;\n  t.udieresismacron = 0x01d6;\n  t.udotbelow = 0x1ee5;\n  t.ugrave = 0x00f9;\n  t.ugujarati = 0x0a89;\n  t.ugurmukhi = 0x0a09;\n  t.uhiragana = 0x3046;\n  t.uhookabove = 0x1ee7;\n  t.uhorn = 0x01b0;\n  t.uhornacute = 0x1ee9;\n  t.uhorndotbelow = 0x1ef1;\n  t.uhorngrave = 0x1eeb;\n  t.uhornhookabove = 0x1eed;\n  t.uhorntilde = 0x1eef;\n  t.uhungarumlaut = 0x0171;\n  t.uhungarumlautcyrillic = 0x04f3;\n  t.uinvertedbreve = 0x0217;\n  t.ukatakana = 0x30a6;\n  t.ukatakanahalfwidth = 0xff73;\n  t.ukcyrillic = 0x0479;\n  t.ukorean = 0x315c;\n  t.umacron = 0x016b;\n  t.umacroncyrillic = 0x04ef;\n  t.umacrondieresis = 0x1e7b;\n  t.umatragurmukhi = 0x0a41;\n  t.umonospace = 0xff55;\n  t.underscore = 0x005f;\n  t.underscoredbl = 0x2017;\n  t.underscoremonospace = 0xff3f;\n  t.underscorevertical = 0xfe33;\n  t.underscorewavy = 0xfe4f;\n  t.union = 0x222a;\n  t.universal = 0x2200;\n  t.uogonek = 0x0173;\n  t.uparen = 0x24b0;\n  t.upblock = 0x2580;\n  t.upperdothebrew = 0x05c4;\n  t.upsilon = 0x03c5;\n  t.upsilondieresis = 0x03cb;\n  t.upsilondieresistonos = 0x03b0;\n  t.upsilonlatin = 0x028a;\n  t.upsilontonos = 0x03cd;\n  t.uptackbelowcmb = 0x031d;\n  t.uptackmod = 0x02d4;\n  t.uragurmukhi = 0x0a73;\n  t.uring = 0x016f;\n  t.ushortcyrillic = 0x045e;\n  t.usmallhiragana = 0x3045;\n  t.usmallkatakana = 0x30a5;\n  t.usmallkatakanahalfwidth = 0xff69;\n  t.ustraightcyrillic = 0x04af;\n  t.ustraightstrokecyrillic = 0x04b1;\n  t.utilde = 0x0169;\n  t.utildeacute = 0x1e79;\n  t.utildebelow = 0x1e75;\n  t.uubengali = 0x098a;\n  t.uudeva = 0x090a;\n  t.uugujarati = 0x0a8a;\n  t.uugurmukhi = 0x0a0a;\n  t.uumatragurmukhi = 0x0a42;\n  t.uuvowelsignbengali = 0x09c2;\n  t.uuvowelsigndeva = 0x0942;\n  t.uuvowelsigngujarati = 0x0ac2;\n  t.uvowelsignbengali = 0x09c1;\n  t.uvowelsigndeva = 0x0941;\n  t.uvowelsigngujarati = 0x0ac1;\n  t.v = 0x0076;\n  t.vadeva = 0x0935;\n  t.vagujarati = 0x0ab5;\n  t.vagurmukhi = 0x0a35;\n  t.vakatakana = 0x30f7;\n  t.vav = 0x05d5;\n  t.vavdagesh = 0xfb35;\n  t.vavdagesh65 = 0xfb35;\n  t.vavdageshhebrew = 0xfb35;\n  t.vavhebrew = 0x05d5;\n  t.vavholam = 0xfb4b;\n  t.vavholamhebrew = 0xfb4b;\n  t.vavvavhebrew = 0x05f0;\n  t.vavyodhebrew = 0x05f1;\n  t.vcircle = 0x24e5;\n  t.vdotbelow = 0x1e7f;\n  t.vecyrillic = 0x0432;\n  t.veharabic = 0x06a4;\n  t.vehfinalarabic = 0xfb6b;\n  t.vehinitialarabic = 0xfb6c;\n  t.vehmedialarabic = 0xfb6d;\n  t.vekatakana = 0x30f9;\n  t.venus = 0x2640;\n  t.verticalbar = 0x007c;\n  t.verticallineabovecmb = 0x030d;\n  t.verticallinebelowcmb = 0x0329;\n  t.verticallinelowmod = 0x02cc;\n  t.verticallinemod = 0x02c8;\n  t.vewarmenian = 0x057e;\n  t.vhook = 0x028b;\n  t.vikatakana = 0x30f8;\n  t.viramabengali = 0x09cd;\n  t.viramadeva = 0x094d;\n  t.viramagujarati = 0x0acd;\n  t.visargabengali = 0x0983;\n  t.visargadeva = 0x0903;\n  t.visargagujarati = 0x0a83;\n  t.vmonospace = 0xff56;\n  t.voarmenian = 0x0578;\n  t.voicediterationhiragana = 0x309e;\n  t.voicediterationkatakana = 0x30fe;\n  t.voicedmarkkana = 0x309b;\n  t.voicedmarkkanahalfwidth = 0xff9e;\n  t.vokatakana = 0x30fa;\n  t.vparen = 0x24b1;\n  t.vtilde = 0x1e7d;\n  t.vturned = 0x028c;\n  t.vuhiragana = 0x3094;\n  t.vukatakana = 0x30f4;\n  t.w = 0x0077;\n  t.wacute = 0x1e83;\n  t.waekorean = 0x3159;\n  t.wahiragana = 0x308f;\n  t.wakatakana = 0x30ef;\n  t.wakatakanahalfwidth = 0xff9c;\n  t.wakorean = 0x3158;\n  t.wasmallhiragana = 0x308e;\n  t.wasmallkatakana = 0x30ee;\n  t.wattosquare = 0x3357;\n  t.wavedash = 0x301c;\n  t.wavyunderscorevertical = 0xfe34;\n  t.wawarabic = 0x0648;\n  t.wawfinalarabic = 0xfeee;\n  t.wawhamzaabovearabic = 0x0624;\n  t.wawhamzaabovefinalarabic = 0xfe86;\n  t.wbsquare = 0x33dd;\n  t.wcircle = 0x24e6;\n  t.wcircumflex = 0x0175;\n  t.wdieresis = 0x1e85;\n  t.wdotaccent = 0x1e87;\n  t.wdotbelow = 0x1e89;\n  t.wehiragana = 0x3091;\n  t.weierstrass = 0x2118;\n  t.wekatakana = 0x30f1;\n  t.wekorean = 0x315e;\n  t.weokorean = 0x315d;\n  t.wgrave = 0x1e81;\n  t.whitebullet = 0x25e6;\n  t.whitecircle = 0x25cb;\n  t.whitecircleinverse = 0x25d9;\n  t.whitecornerbracketleft = 0x300e;\n  t.whitecornerbracketleftvertical = 0xfe43;\n  t.whitecornerbracketright = 0x300f;\n  t.whitecornerbracketrightvertical = 0xfe44;\n  t.whitediamond = 0x25c7;\n  t.whitediamondcontainingblacksmalldiamond = 0x25c8;\n  t.whitedownpointingsmalltriangle = 0x25bf;\n  t.whitedownpointingtriangle = 0x25bd;\n  t.whiteleftpointingsmalltriangle = 0x25c3;\n  t.whiteleftpointingtriangle = 0x25c1;\n  t.whitelenticularbracketleft = 0x3016;\n  t.whitelenticularbracketright = 0x3017;\n  t.whiterightpointingsmalltriangle = 0x25b9;\n  t.whiterightpointingtriangle = 0x25b7;\n  t.whitesmallsquare = 0x25ab;\n  t.whitesmilingface = 0x263a;\n  t.whitesquare = 0x25a1;\n  t.whitestar = 0x2606;\n  t.whitetelephone = 0x260f;\n  t.whitetortoiseshellbracketleft = 0x3018;\n  t.whitetortoiseshellbracketright = 0x3019;\n  t.whiteuppointingsmalltriangle = 0x25b5;\n  t.whiteuppointingtriangle = 0x25b3;\n  t.wihiragana = 0x3090;\n  t.wikatakana = 0x30f0;\n  t.wikorean = 0x315f;\n  t.wmonospace = 0xff57;\n  t.wohiragana = 0x3092;\n  t.wokatakana = 0x30f2;\n  t.wokatakanahalfwidth = 0xff66;\n  t.won = 0x20a9;\n  t.wonmonospace = 0xffe6;\n  t.wowaenthai = 0x0e27;\n  t.wparen = 0x24b2;\n  t.wring = 0x1e98;\n  t.wsuperior = 0x02b7;\n  t.wturned = 0x028d;\n  t.wynn = 0x01bf;\n  t.x = 0x0078;\n  t.xabovecmb = 0x033d;\n  t.xbopomofo = 0x3112;\n  t.xcircle = 0x24e7;\n  t.xdieresis = 0x1e8d;\n  t.xdotaccent = 0x1e8b;\n  t.xeharmenian = 0x056d;\n  t.xi = 0x03be;\n  t.xmonospace = 0xff58;\n  t.xparen = 0x24b3;\n  t.xsuperior = 0x02e3;\n  t.y = 0x0079;\n  t.yaadosquare = 0x334e;\n  t.yabengali = 0x09af;\n  t.yacute = 0x00fd;\n  t.yadeva = 0x092f;\n  t.yaekorean = 0x3152;\n  t.yagujarati = 0x0aaf;\n  t.yagurmukhi = 0x0a2f;\n  t.yahiragana = 0x3084;\n  t.yakatakana = 0x30e4;\n  t.yakatakanahalfwidth = 0xff94;\n  t.yakorean = 0x3151;\n  t.yamakkanthai = 0x0e4e;\n  t.yasmallhiragana = 0x3083;\n  t.yasmallkatakana = 0x30e3;\n  t.yasmallkatakanahalfwidth = 0xff6c;\n  t.yatcyrillic = 0x0463;\n  t.ycircle = 0x24e8;\n  t.ycircumflex = 0x0177;\n  t.ydieresis = 0x00ff;\n  t.ydotaccent = 0x1e8f;\n  t.ydotbelow = 0x1ef5;\n  t.yeharabic = 0x064a;\n  t.yehbarreearabic = 0x06d2;\n  t.yehbarreefinalarabic = 0xfbaf;\n  t.yehfinalarabic = 0xfef2;\n  t.yehhamzaabovearabic = 0x0626;\n  t.yehhamzaabovefinalarabic = 0xfe8a;\n  t.yehhamzaaboveinitialarabic = 0xfe8b;\n  t.yehhamzaabovemedialarabic = 0xfe8c;\n  t.yehinitialarabic = 0xfef3;\n  t.yehmedialarabic = 0xfef4;\n  t.yehmeeminitialarabic = 0xfcdd;\n  t.yehmeemisolatedarabic = 0xfc58;\n  t.yehnoonfinalarabic = 0xfc94;\n  t.yehthreedotsbelowarabic = 0x06d1;\n  t.yekorean = 0x3156;\n  t.yen = 0x00a5;\n  t.yenmonospace = 0xffe5;\n  t.yeokorean = 0x3155;\n  t.yeorinhieuhkorean = 0x3186;\n  t.yerahbenyomohebrew = 0x05aa;\n  t.yerahbenyomolefthebrew = 0x05aa;\n  t.yericyrillic = 0x044b;\n  t.yerudieresiscyrillic = 0x04f9;\n  t.yesieungkorean = 0x3181;\n  t.yesieungpansioskorean = 0x3183;\n  t.yesieungsioskorean = 0x3182;\n  t.yetivhebrew = 0x059a;\n  t.ygrave = 0x1ef3;\n  t.yhook = 0x01b4;\n  t.yhookabove = 0x1ef7;\n  t.yiarmenian = 0x0575;\n  t.yicyrillic = 0x0457;\n  t.yikorean = 0x3162;\n  t.yinyang = 0x262f;\n  t.yiwnarmenian = 0x0582;\n  t.ymonospace = 0xff59;\n  t.yod = 0x05d9;\n  t.yoddagesh = 0xfb39;\n  t.yoddageshhebrew = 0xfb39;\n  t.yodhebrew = 0x05d9;\n  t.yodyodhebrew = 0x05f2;\n  t.yodyodpatahhebrew = 0xfb1f;\n  t.yohiragana = 0x3088;\n  t.yoikorean = 0x3189;\n  t.yokatakana = 0x30e8;\n  t.yokatakanahalfwidth = 0xff96;\n  t.yokorean = 0x315b;\n  t.yosmallhiragana = 0x3087;\n  t.yosmallkatakana = 0x30e7;\n  t.yosmallkatakanahalfwidth = 0xff6e;\n  t.yotgreek = 0x03f3;\n  t.yoyaekorean = 0x3188;\n  t.yoyakorean = 0x3187;\n  t.yoyakthai = 0x0e22;\n  t.yoyingthai = 0x0e0d;\n  t.yparen = 0x24b4;\n  t.ypogegrammeni = 0x037a;\n  t.ypogegrammenigreekcmb = 0x0345;\n  t.yr = 0x01a6;\n  t.yring = 0x1e99;\n  t.ysuperior = 0x02b8;\n  t.ytilde = 0x1ef9;\n  t.yturned = 0x028e;\n  t.yuhiragana = 0x3086;\n  t.yuikorean = 0x318c;\n  t.yukatakana = 0x30e6;\n  t.yukatakanahalfwidth = 0xff95;\n  t.yukorean = 0x3160;\n  t.yusbigcyrillic = 0x046b;\n  t.yusbigiotifiedcyrillic = 0x046d;\n  t.yuslittlecyrillic = 0x0467;\n  t.yuslittleiotifiedcyrillic = 0x0469;\n  t.yusmallhiragana = 0x3085;\n  t.yusmallkatakana = 0x30e5;\n  t.yusmallkatakanahalfwidth = 0xff6d;\n  t.yuyekorean = 0x318b;\n  t.yuyeokorean = 0x318a;\n  t.yyabengali = 0x09df;\n  t.yyadeva = 0x095f;\n  t.z = 0x007a;\n  t.zaarmenian = 0x0566;\n  t.zacute = 0x017a;\n  t.zadeva = 0x095b;\n  t.zagurmukhi = 0x0a5b;\n  t.zaharabic = 0x0638;\n  t.zahfinalarabic = 0xfec6;\n  t.zahinitialarabic = 0xfec7;\n  t.zahiragana = 0x3056;\n  t.zahmedialarabic = 0xfec8;\n  t.zainarabic = 0x0632;\n  t.zainfinalarabic = 0xfeb0;\n  t.zakatakana = 0x30b6;\n  t.zaqefgadolhebrew = 0x0595;\n  t.zaqefqatanhebrew = 0x0594;\n  t.zarqahebrew = 0x0598;\n  t.zayin = 0x05d6;\n  t.zayindagesh = 0xfb36;\n  t.zayindageshhebrew = 0xfb36;\n  t.zayinhebrew = 0x05d6;\n  t.zbopomofo = 0x3117;\n  t.zcaron = 0x017e;\n  t.zcircle = 0x24e9;\n  t.zcircumflex = 0x1e91;\n  t.zcurl = 0x0291;\n  t.zdot = 0x017c;\n  t.zdotaccent = 0x017c;\n  t.zdotbelow = 0x1e93;\n  t.zecyrillic = 0x0437;\n  t.zedescendercyrillic = 0x0499;\n  t.zedieresiscyrillic = 0x04df;\n  t.zehiragana = 0x305c;\n  t.zekatakana = 0x30bc;\n  t.zero = 0x0030;\n  t.zeroarabic = 0x0660;\n  t.zerobengali = 0x09e6;\n  t.zerodeva = 0x0966;\n  t.zerogujarati = 0x0ae6;\n  t.zerogurmukhi = 0x0a66;\n  t.zerohackarabic = 0x0660;\n  t.zeroinferior = 0x2080;\n  t.zeromonospace = 0xff10;\n  t.zerooldstyle = 0xf730;\n  t.zeropersian = 0x06f0;\n  t.zerosuperior = 0x2070;\n  t.zerothai = 0x0e50;\n  t.zerowidthjoiner = 0xfeff;\n  t.zerowidthnonjoiner = 0x200c;\n  t.zerowidthspace = 0x200b;\n  t.zeta = 0x03b6;\n  t.zhbopomofo = 0x3113;\n  t.zhearmenian = 0x056a;\n  t.zhebrevecyrillic = 0x04c2;\n  t.zhecyrillic = 0x0436;\n  t.zhedescendercyrillic = 0x0497;\n  t.zhedieresiscyrillic = 0x04dd;\n  t.zihiragana = 0x3058;\n  t.zikatakana = 0x30b8;\n  t.zinorhebrew = 0x05ae;\n  t.zlinebelow = 0x1e95;\n  t.zmonospace = 0xff5a;\n  t.zohiragana = 0x305e;\n  t.zokatakana = 0x30be;\n  t.zparen = 0x24b5;\n  t.zretroflexhook = 0x0290;\n  t.zstroke = 0x01b6;\n  t.zuhiragana = 0x305a;\n  t.zukatakana = 0x30ba;\n  t[\".notdef\"] = 0x0000;\n  t.angbracketleftbig = 0x2329;\n  t.angbracketleftBig = 0x2329;\n  t.angbracketleftbigg = 0x2329;\n  t.angbracketleftBigg = 0x2329;\n  t.angbracketrightBig = 0x232a;\n  t.angbracketrightbig = 0x232a;\n  t.angbracketrightBigg = 0x232a;\n  t.angbracketrightbigg = 0x232a;\n  t.arrowhookleft = 0x21aa;\n  t.arrowhookright = 0x21a9;\n  t.arrowlefttophalf = 0x21bc;\n  t.arrowleftbothalf = 0x21bd;\n  t.arrownortheast = 0x2197;\n  t.arrownorthwest = 0x2196;\n  t.arrowrighttophalf = 0x21c0;\n  t.arrowrightbothalf = 0x21c1;\n  t.arrowsoutheast = 0x2198;\n  t.arrowsouthwest = 0x2199;\n  t.backslashbig = 0x2216;\n  t.backslashBig = 0x2216;\n  t.backslashBigg = 0x2216;\n  t.backslashbigg = 0x2216;\n  t.bardbl = 0x2016;\n  t.bracehtipdownleft = 0xfe37;\n  t.bracehtipdownright = 0xfe37;\n  t.bracehtipupleft = 0xfe38;\n  t.bracehtipupright = 0xfe38;\n  t.braceleftBig = 0x007b;\n  t.braceleftbig = 0x007b;\n  t.braceleftbigg = 0x007b;\n  t.braceleftBigg = 0x007b;\n  t.bracerightBig = 0x007d;\n  t.bracerightbig = 0x007d;\n  t.bracerightbigg = 0x007d;\n  t.bracerightBigg = 0x007d;\n  t.bracketleftbig = 0x005b;\n  t.bracketleftBig = 0x005b;\n  t.bracketleftbigg = 0x005b;\n  t.bracketleftBigg = 0x005b;\n  t.bracketrightBig = 0x005d;\n  t.bracketrightbig = 0x005d;\n  t.bracketrightbigg = 0x005d;\n  t.bracketrightBigg = 0x005d;\n  t.ceilingleftbig = 0x2308;\n  t.ceilingleftBig = 0x2308;\n  t.ceilingleftBigg = 0x2308;\n  t.ceilingleftbigg = 0x2308;\n  t.ceilingrightbig = 0x2309;\n  t.ceilingrightBig = 0x2309;\n  t.ceilingrightbigg = 0x2309;\n  t.ceilingrightBigg = 0x2309;\n  t.circledotdisplay = 0x2299;\n  t.circledottext = 0x2299;\n  t.circlemultiplydisplay = 0x2297;\n  t.circlemultiplytext = 0x2297;\n  t.circleplusdisplay = 0x2295;\n  t.circleplustext = 0x2295;\n  t.contintegraldisplay = 0x222e;\n  t.contintegraltext = 0x222e;\n  t.coproductdisplay = 0x2210;\n  t.coproducttext = 0x2210;\n  t.floorleftBig = 0x230a;\n  t.floorleftbig = 0x230a;\n  t.floorleftbigg = 0x230a;\n  t.floorleftBigg = 0x230a;\n  t.floorrightbig = 0x230b;\n  t.floorrightBig = 0x230b;\n  t.floorrightBigg = 0x230b;\n  t.floorrightbigg = 0x230b;\n  t.hatwide = 0x0302;\n  t.hatwider = 0x0302;\n  t.hatwidest = 0x0302;\n  t.intercal = 0x1d40;\n  t.integraldisplay = 0x222b;\n  t.integraltext = 0x222b;\n  t.intersectiondisplay = 0x22c2;\n  t.intersectiontext = 0x22c2;\n  t.logicalanddisplay = 0x2227;\n  t.logicalandtext = 0x2227;\n  t.logicalordisplay = 0x2228;\n  t.logicalortext = 0x2228;\n  t.parenleftBig = 0x0028;\n  t.parenleftbig = 0x0028;\n  t.parenleftBigg = 0x0028;\n  t.parenleftbigg = 0x0028;\n  t.parenrightBig = 0x0029;\n  t.parenrightbig = 0x0029;\n  t.parenrightBigg = 0x0029;\n  t.parenrightbigg = 0x0029;\n  t.prime = 0x2032;\n  t.productdisplay = 0x220f;\n  t.producttext = 0x220f;\n  t.radicalbig = 0x221a;\n  t.radicalBig = 0x221a;\n  t.radicalBigg = 0x221a;\n  t.radicalbigg = 0x221a;\n  t.radicalbt = 0x221a;\n  t.radicaltp = 0x221a;\n  t.radicalvertex = 0x221a;\n  t.slashbig = 0x002f;\n  t.slashBig = 0x002f;\n  t.slashBigg = 0x002f;\n  t.slashbigg = 0x002f;\n  t.summationdisplay = 0x2211;\n  t.summationtext = 0x2211;\n  t.tildewide = 0x02dc;\n  t.tildewider = 0x02dc;\n  t.tildewidest = 0x02dc;\n  t.uniondisplay = 0x22c3;\n  t.unionmultidisplay = 0x228e;\n  t.unionmultitext = 0x228e;\n  t.unionsqdisplay = 0x2294;\n  t.unionsqtext = 0x2294;\n  t.uniontext = 0x22c3;\n  t.vextenddouble = 0x2225;\n  t.vextendsingle = 0x2223;\n});\nconst getDingbatsGlyphsUnicode = getLookupTableFactory(function (t) {\n  t.space = 0x0020;\n  t.a1 = 0x2701;\n  t.a2 = 0x2702;\n  t.a202 = 0x2703;\n  t.a3 = 0x2704;\n  t.a4 = 0x260e;\n  t.a5 = 0x2706;\n  t.a119 = 0x2707;\n  t.a118 = 0x2708;\n  t.a117 = 0x2709;\n  t.a11 = 0x261b;\n  t.a12 = 0x261e;\n  t.a13 = 0x270c;\n  t.a14 = 0x270d;\n  t.a15 = 0x270e;\n  t.a16 = 0x270f;\n  t.a105 = 0x2710;\n  t.a17 = 0x2711;\n  t.a18 = 0x2712;\n  t.a19 = 0x2713;\n  t.a20 = 0x2714;\n  t.a21 = 0x2715;\n  t.a22 = 0x2716;\n  t.a23 = 0x2717;\n  t.a24 = 0x2718;\n  t.a25 = 0x2719;\n  t.a26 = 0x271a;\n  t.a27 = 0x271b;\n  t.a28 = 0x271c;\n  t.a6 = 0x271d;\n  t.a7 = 0x271e;\n  t.a8 = 0x271f;\n  t.a9 = 0x2720;\n  t.a10 = 0x2721;\n  t.a29 = 0x2722;\n  t.a30 = 0x2723;\n  t.a31 = 0x2724;\n  t.a32 = 0x2725;\n  t.a33 = 0x2726;\n  t.a34 = 0x2727;\n  t.a35 = 0x2605;\n  t.a36 = 0x2729;\n  t.a37 = 0x272a;\n  t.a38 = 0x272b;\n  t.a39 = 0x272c;\n  t.a40 = 0x272d;\n  t.a41 = 0x272e;\n  t.a42 = 0x272f;\n  t.a43 = 0x2730;\n  t.a44 = 0x2731;\n  t.a45 = 0x2732;\n  t.a46 = 0x2733;\n  t.a47 = 0x2734;\n  t.a48 = 0x2735;\n  t.a49 = 0x2736;\n  t.a50 = 0x2737;\n  t.a51 = 0x2738;\n  t.a52 = 0x2739;\n  t.a53 = 0x273a;\n  t.a54 = 0x273b;\n  t.a55 = 0x273c;\n  t.a56 = 0x273d;\n  t.a57 = 0x273e;\n  t.a58 = 0x273f;\n  t.a59 = 0x2740;\n  t.a60 = 0x2741;\n  t.a61 = 0x2742;\n  t.a62 = 0x2743;\n  t.a63 = 0x2744;\n  t.a64 = 0x2745;\n  t.a65 = 0x2746;\n  t.a66 = 0x2747;\n  t.a67 = 0x2748;\n  t.a68 = 0x2749;\n  t.a69 = 0x274a;\n  t.a70 = 0x274b;\n  t.a71 = 0x25cf;\n  t.a72 = 0x274d;\n  t.a73 = 0x25a0;\n  t.a74 = 0x274f;\n  t.a203 = 0x2750;\n  t.a75 = 0x2751;\n  t.a204 = 0x2752;\n  t.a76 = 0x25b2;\n  t.a77 = 0x25bc;\n  t.a78 = 0x25c6;\n  t.a79 = 0x2756;\n  t.a81 = 0x25d7;\n  t.a82 = 0x2758;\n  t.a83 = 0x2759;\n  t.a84 = 0x275a;\n  t.a97 = 0x275b;\n  t.a98 = 0x275c;\n  t.a99 = 0x275d;\n  t.a100 = 0x275e;\n  t.a101 = 0x2761;\n  t.a102 = 0x2762;\n  t.a103 = 0x2763;\n  t.a104 = 0x2764;\n  t.a106 = 0x2765;\n  t.a107 = 0x2766;\n  t.a108 = 0x2767;\n  t.a112 = 0x2663;\n  t.a111 = 0x2666;\n  t.a110 = 0x2665;\n  t.a109 = 0x2660;\n  t.a120 = 0x2460;\n  t.a121 = 0x2461;\n  t.a122 = 0x2462;\n  t.a123 = 0x2463;\n  t.a124 = 0x2464;\n  t.a125 = 0x2465;\n  t.a126 = 0x2466;\n  t.a127 = 0x2467;\n  t.a128 = 0x2468;\n  t.a129 = 0x2469;\n  t.a130 = 0x2776;\n  t.a131 = 0x2777;\n  t.a132 = 0x2778;\n  t.a133 = 0x2779;\n  t.a134 = 0x277a;\n  t.a135 = 0x277b;\n  t.a136 = 0x277c;\n  t.a137 = 0x277d;\n  t.a138 = 0x277e;\n  t.a139 = 0x277f;\n  t.a140 = 0x2780;\n  t.a141 = 0x2781;\n  t.a142 = 0x2782;\n  t.a143 = 0x2783;\n  t.a144 = 0x2784;\n  t.a145 = 0x2785;\n  t.a146 = 0x2786;\n  t.a147 = 0x2787;\n  t.a148 = 0x2788;\n  t.a149 = 0x2789;\n  t.a150 = 0x278a;\n  t.a151 = 0x278b;\n  t.a152 = 0x278c;\n  t.a153 = 0x278d;\n  t.a154 = 0x278e;\n  t.a155 = 0x278f;\n  t.a156 = 0x2790;\n  t.a157 = 0x2791;\n  t.a158 = 0x2792;\n  t.a159 = 0x2793;\n  t.a160 = 0x2794;\n  t.a161 = 0x2192;\n  t.a163 = 0x2194;\n  t.a164 = 0x2195;\n  t.a196 = 0x2798;\n  t.a165 = 0x2799;\n  t.a192 = 0x279a;\n  t.a166 = 0x279b;\n  t.a167 = 0x279c;\n  t.a168 = 0x279d;\n  t.a169 = 0x279e;\n  t.a170 = 0x279f;\n  t.a171 = 0x27a0;\n  t.a172 = 0x27a1;\n  t.a173 = 0x27a2;\n  t.a162 = 0x27a3;\n  t.a174 = 0x27a4;\n  t.a175 = 0x27a5;\n  t.a176 = 0x27a6;\n  t.a177 = 0x27a7;\n  t.a178 = 0x27a8;\n  t.a179 = 0x27a9;\n  t.a193 = 0x27aa;\n  t.a180 = 0x27ab;\n  t.a199 = 0x27ac;\n  t.a181 = 0x27ad;\n  t.a200 = 0x27ae;\n  t.a182 = 0x27af;\n  t.a201 = 0x27b1;\n  t.a183 = 0x27b2;\n  t.a184 = 0x27b3;\n  t.a197 = 0x27b4;\n  t.a185 = 0x27b5;\n  t.a194 = 0x27b6;\n  t.a198 = 0x27b7;\n  t.a186 = 0x27b8;\n  t.a195 = 0x27b9;\n  t.a187 = 0x27ba;\n  t.a188 = 0x27bb;\n  t.a189 = 0x27bc;\n  t.a190 = 0x27bd;\n  t.a191 = 0x27be;\n  t.a89 = 0x2768;\n  t.a90 = 0x2769;\n  t.a93 = 0x276a;\n  t.a94 = 0x276b;\n  t.a91 = 0x276c;\n  t.a92 = 0x276d;\n  t.a205 = 0x276e;\n  t.a85 = 0x276f;\n  t.a206 = 0x2770;\n  t.a86 = 0x2771;\n  t.a87 = 0x2772;\n  t.a88 = 0x2773;\n  t.a95 = 0x2774;\n  t.a96 = 0x2775;\n  t[\".notdef\"] = 0x0000;\n});\n\n;// CONCATENATED MODULE: ./src/core/unicode.js\n\nconst getSpecialPUASymbols = getLookupTableFactory(function (t) {\n  t[63721] = 0x00a9;\n  t[63193] = 0x00a9;\n  t[63720] = 0x00ae;\n  t[63194] = 0x00ae;\n  t[63722] = 0x2122;\n  t[63195] = 0x2122;\n  t[63729] = 0x23a7;\n  t[63730] = 0x23a8;\n  t[63731] = 0x23a9;\n  t[63740] = 0x23ab;\n  t[63741] = 0x23ac;\n  t[63742] = 0x23ad;\n  t[63726] = 0x23a1;\n  t[63727] = 0x23a2;\n  t[63728] = 0x23a3;\n  t[63737] = 0x23a4;\n  t[63738] = 0x23a5;\n  t[63739] = 0x23a6;\n  t[63723] = 0x239b;\n  t[63724] = 0x239c;\n  t[63725] = 0x239d;\n  t[63734] = 0x239e;\n  t[63735] = 0x239f;\n  t[63736] = 0x23a0;\n});\nfunction mapSpecialUnicodeValues(code) {\n  if (code >= 0xfff0 && code <= 0xffff) {\n    return 0;\n  } else if (code >= 0xf600 && code <= 0xf8ff) {\n    return getSpecialPUASymbols()[code] || code;\n  } else if (code === 0x00ad) {\n    return 0x002d;\n  }\n  return code;\n}\nfunction getUnicodeForGlyph(name, glyphsUnicodeMap) {\n  let unicode = glyphsUnicodeMap[name];\n  if (unicode !== undefined) {\n    return unicode;\n  }\n  if (!name) {\n    return -1;\n  }\n  if (name[0] === \"u\") {\n    const nameLen = name.length;\n    let hexStr;\n    if (nameLen === 7 && name[1] === \"n\" && name[2] === \"i\") {\n      hexStr = name.substring(3);\n    } else if (nameLen >= 5 && nameLen <= 7) {\n      hexStr = name.substring(1);\n    } else {\n      return -1;\n    }\n    if (hexStr === hexStr.toUpperCase()) {\n      unicode = parseInt(hexStr, 16);\n      if (unicode >= 0) {\n        return unicode;\n      }\n    }\n  }\n  return -1;\n}\nconst UnicodeRanges = [[0x0000, 0x007f], [0x0080, 0x00ff], [0x0100, 0x017f], [0x0180, 0x024f], [0x0250, 0x02af, 0x1d00, 0x1d7f, 0x1d80, 0x1dbf], [0x02b0, 0x02ff, 0xa700, 0xa71f], [0x0300, 0x036f, 0x1dc0, 0x1dff], [0x0370, 0x03ff], [0x2c80, 0x2cff], [0x0400, 0x04ff, 0x0500, 0x052f, 0x2de0, 0x2dff, 0xa640, 0xa69f], [0x0530, 0x058f], [0x0590, 0x05ff], [0xa500, 0xa63f], [0x0600, 0x06ff, 0x0750, 0x077f], [0x07c0, 0x07ff], [0x0900, 0x097f], [0x0980, 0x09ff], [0x0a00, 0x0a7f], [0x0a80, 0x0aff], [0x0b00, 0x0b7f], [0x0b80, 0x0bff], [0x0c00, 0x0c7f], [0x0c80, 0x0cff], [0x0d00, 0x0d7f], [0x0e00, 0x0e7f], [0x0e80, 0x0eff], [0x10a0, 0x10ff, 0x2d00, 0x2d2f], [0x1b00, 0x1b7f], [0x1100, 0x11ff], [0x1e00, 0x1eff, 0x2c60, 0x2c7f, 0xa720, 0xa7ff], [0x1f00, 0x1fff], [0x2000, 0x206f, 0x2e00, 0x2e7f], [0x2070, 0x209f], [0x20a0, 0x20cf], [0x20d0, 0x20ff], [0x2100, 0x214f], [0x2150, 0x218f], [0x2190, 0x21ff, 0x27f0, 0x27ff, 0x2900, 0x297f, 0x2b00, 0x2bff], [0x2200, 0x22ff, 0x2a00, 0x2aff, 0x27c0, 0x27ef, 0x2980, 0x29ff], [0x2300, 0x23ff], [0x2400, 0x243f], [0x2440, 0x245f], [0x2460, 0x24ff], [0x2500, 0x257f], [0x2580, 0x259f], [0x25a0, 0x25ff], [0x2600, 0x26ff], [0x2700, 0x27bf], [0x3000, 0x303f], [0x3040, 0x309f], [0x30a0, 0x30ff, 0x31f0, 0x31ff], [0x3100, 0x312f, 0x31a0, 0x31bf], [0x3130, 0x318f], [0xa840, 0xa87f], [0x3200, 0x32ff], [0x3300, 0x33ff], [0xac00, 0xd7af], [0xd800, 0xdfff], [0x10900, 0x1091f], [0x4e00, 0x9fff, 0x2e80, 0x2eff, 0x2f00, 0x2fdf, 0x2ff0, 0x2fff, 0x3400, 0x4dbf, 0x20000, 0x2a6df, 0x3190, 0x319f], [0xe000, 0xf8ff], [0x31c0, 0x31ef, 0xf900, 0xfaff, 0x2f800, 0x2fa1f], [0xfb00, 0xfb4f], [0xfb50, 0xfdff], [0xfe20, 0xfe2f], [0xfe10, 0xfe1f], [0xfe50, 0xfe6f], [0xfe70, 0xfeff], [0xff00, 0xffef], [0xfff0, 0xffff], [0x0f00, 0x0fff], [0x0700, 0x074f], [0x0780, 0x07bf], [0x0d80, 0x0dff], [0x1000, 0x109f], [0x1200, 0x137f, 0x1380, 0x139f, 0x2d80, 0x2ddf], [0x13a0, 0x13ff], [0x1400, 0x167f], [0x1680, 0x169f], [0x16a0, 0x16ff], [0x1780, 0x17ff], [0x1800, 0x18af], [0x2800, 0x28ff], [0xa000, 0xa48f], [0x1700, 0x171f, 0x1720, 0x173f, 0x1740, 0x175f, 0x1760, 0x177f], [0x10300, 0x1032f], [0x10330, 0x1034f], [0x10400, 0x1044f], [0x1d000, 0x1d0ff, 0x1d100, 0x1d1ff, 0x1d200, 0x1d24f], [0x1d400, 0x1d7ff], [0xff000, 0xffffd], [0xfe00, 0xfe0f, 0xe0100, 0xe01ef], [0xe0000, 0xe007f], [0x1900, 0x194f], [0x1950, 0x197f], [0x1980, 0x19df], [0x1a00, 0x1a1f], [0x2c00, 0x2c5f], [0x2d30, 0x2d7f], [0x4dc0, 0x4dff], [0xa800, 0xa82f], [0x10000, 0x1007f, 0x10080, 0x100ff, 0x10100, 0x1013f], [0x10140, 0x1018f], [0x10380, 0x1039f], [0x103a0, 0x103df], [0x10450, 0x1047f], [0x10480, 0x104af], [0x10800, 0x1083f], [0x10a00, 0x10a5f], [0x1d300, 0x1d35f], [0x12000, 0x123ff, 0x12400, 0x1247f], [0x1d360, 0x1d37f], [0x1b80, 0x1bbf], [0x1c00, 0x1c4f], [0x1c50, 0x1c7f], [0xa880, 0xa8df], [0xa900, 0xa92f], [0xa930, 0xa95f], [0xaa00, 0xaa5f], [0x10190, 0x101cf], [0x101d0, 0x101ff], [0x102a0, 0x102df, 0x10280, 0x1029f, 0x10920, 0x1093f], [0x1f030, 0x1f09f, 0x1f000, 0x1f02f]];\nfunction getUnicodeRangeFor(value, lastPosition = -1) {\n  if (lastPosition !== -1) {\n    const range = UnicodeRanges[lastPosition];\n    for (let i = 0, ii = range.length; i < ii; i += 2) {\n      if (value >= range[i] && value <= range[i + 1]) {\n        return lastPosition;\n      }\n    }\n  }\n  for (let i = 0, ii = UnicodeRanges.length; i < ii; i++) {\n    const range = UnicodeRanges[i];\n    for (let j = 0, jj = range.length; j < jj; j += 2) {\n      if (value >= range[j] && value <= range[j + 1]) {\n        return i;\n      }\n    }\n  }\n  return -1;\n}\nconst SpecialCharRegExp = new RegExp(\"^(\\\\s)|(\\\\p{Mn})|(\\\\p{Cf})$\", \"u\");\nconst CategoryCache = new Map();\nfunction getCharUnicodeCategory(char) {\n  const cachedCategory = CategoryCache.get(char);\n  if (cachedCategory) {\n    return cachedCategory;\n  }\n  const groups = char.match(SpecialCharRegExp);\n  const category = {\n    isWhitespace: !!groups?.[1],\n    isZeroWidthDiacritic: !!groups?.[2],\n    isInvisibleFormatMark: !!groups?.[3]\n  };\n  CategoryCache.set(char, category);\n  return category;\n}\nfunction clearUnicodeCaches() {\n  CategoryCache.clear();\n}\n\n;// CONCATENATED MODULE: ./src/core/fonts_utils.js\n\n\n\n\nconst SEAC_ANALYSIS_ENABLED = true;\nconst FontFlags = {\n  FixedPitch: 1,\n  Serif: 2,\n  Symbolic: 4,\n  Script: 8,\n  Nonsymbolic: 32,\n  Italic: 64,\n  AllCap: 65536,\n  SmallCap: 131072,\n  ForceBold: 262144\n};\nconst MacStandardGlyphOrdering = [\".notdef\", \".null\", \"nonmarkingreturn\", \"space\", \"exclam\", \"quotedbl\", \"numbersign\", \"dollar\", \"percent\", \"ampersand\", \"quotesingle\", \"parenleft\", \"parenright\", \"asterisk\", \"plus\", \"comma\", \"hyphen\", \"period\", \"slash\", \"zero\", \"one\", \"two\", \"three\", \"four\", \"five\", \"six\", \"seven\", \"eight\", \"nine\", \"colon\", \"semicolon\", \"less\", \"equal\", \"greater\", \"question\", \"at\", \"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\", \"I\", \"J\", \"K\", \"L\", \"M\", \"N\", \"O\", \"P\", \"Q\", \"R\", \"S\", \"T\", \"U\", \"V\", \"W\", \"X\", \"Y\", \"Z\", \"bracketleft\", \"backslash\", \"bracketright\", \"asciicircum\", \"underscore\", \"grave\", \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\", \"k\", \"l\", \"m\", \"n\", \"o\", \"p\", \"q\", \"r\", \"s\", \"t\", \"u\", \"v\", \"w\", \"x\", \"y\", \"z\", \"braceleft\", \"bar\", \"braceright\", \"asciitilde\", \"Adieresis\", \"Aring\", \"Ccedilla\", \"Eacute\", \"Ntilde\", \"Odieresis\", \"Udieresis\", \"aacute\", \"agrave\", \"acircumflex\", \"adieresis\", \"atilde\", \"aring\", \"ccedilla\", \"eacute\", \"egrave\", \"ecircumflex\", \"edieresis\", \"iacute\", \"igrave\", \"icircumflex\", \"idieresis\", \"ntilde\", \"oacute\", \"ograve\", \"ocircumflex\", \"odieresis\", \"otilde\", \"uacute\", \"ugrave\", \"ucircumflex\", \"udieresis\", \"dagger\", \"degree\", \"cent\", \"sterling\", \"section\", \"bullet\", \"paragraph\", \"germandbls\", \"registered\", \"copyright\", \"trademark\", \"acute\", \"dieresis\", \"notequal\", \"AE\", \"Oslash\", \"infinity\", \"plusminus\", \"lessequal\", \"greaterequal\", \"yen\", \"mu\", \"partialdiff\", \"summation\", \"product\", \"pi\", \"integral\", \"ordfeminine\", \"ordmasculine\", \"Omega\", \"ae\", \"oslash\", \"questiondown\", \"exclamdown\", \"logicalnot\", \"radical\", \"florin\", \"approxequal\", \"Delta\", \"guillemotleft\", \"guillemotright\", \"ellipsis\", \"nonbreakingspace\", \"Agrave\", \"Atilde\", \"Otilde\", \"OE\", \"oe\", \"endash\", \"emdash\", \"quotedblleft\", \"quotedblright\", \"quoteleft\", \"quoteright\", \"divide\", \"lozenge\", \"ydieresis\", \"Ydieresis\", \"fraction\", \"currency\", \"guilsinglleft\", \"guilsinglright\", \"fi\", \"fl\", \"daggerdbl\", \"periodcentered\", \"quotesinglbase\", \"quotedblbase\", \"perthousand\", \"Acircumflex\", \"Ecircumflex\", \"Aacute\", \"Edieresis\", \"Egrave\", \"Iacute\", \"Icircumflex\", \"Idieresis\", \"Igrave\", \"Oacute\", \"Ocircumflex\", \"apple\", \"Ograve\", \"Uacute\", \"Ucircumflex\", \"Ugrave\", \"dotlessi\", \"circumflex\", \"tilde\", \"macron\", \"breve\", \"dotaccent\", \"ring\", \"cedilla\", \"hungarumlaut\", \"ogonek\", \"caron\", \"Lslash\", \"lslash\", \"Scaron\", \"scaron\", \"Zcaron\", \"zcaron\", \"brokenbar\", \"Eth\", \"eth\", \"Yacute\", \"yacute\", \"Thorn\", \"thorn\", \"minus\", \"multiply\", \"onesuperior\", \"twosuperior\", \"threesuperior\", \"onehalf\", \"onequarter\", \"threequarters\", \"franc\", \"Gbreve\", \"gbreve\", \"Idotaccent\", \"Scedilla\", \"scedilla\", \"Cacute\", \"cacute\", \"Ccaron\", \"ccaron\", \"dcroat\"];\nfunction recoverGlyphName(name, glyphsUnicodeMap) {\n  if (glyphsUnicodeMap[name] !== undefined) {\n    return name;\n  }\n  const unicode = getUnicodeForGlyph(name, glyphsUnicodeMap);\n  if (unicode !== -1) {\n    for (const key in glyphsUnicodeMap) {\n      if (glyphsUnicodeMap[key] === unicode) {\n        return key;\n      }\n    }\n  }\n  info(\"Unable to recover a standard glyph name for: \" + name);\n  return name;\n}\nfunction type1FontGlyphMapping(properties, builtInEncoding, glyphNames) {\n  const charCodeToGlyphId = Object.create(null);\n  let glyphId, charCode, baseEncoding;\n  const isSymbolicFont = !!(properties.flags & FontFlags.Symbolic);\n  if (properties.isInternalFont) {\n    baseEncoding = builtInEncoding;\n    for (charCode = 0; charCode < baseEncoding.length; charCode++) {\n      glyphId = glyphNames.indexOf(baseEncoding[charCode]);\n      charCodeToGlyphId[charCode] = glyphId >= 0 ? glyphId : 0;\n    }\n  } else if (properties.baseEncodingName) {\n    baseEncoding = getEncoding(properties.baseEncodingName);\n    for (charCode = 0; charCode < baseEncoding.length; charCode++) {\n      glyphId = glyphNames.indexOf(baseEncoding[charCode]);\n      charCodeToGlyphId[charCode] = glyphId >= 0 ? glyphId : 0;\n    }\n  } else if (isSymbolicFont) {\n    for (charCode in builtInEncoding) {\n      charCodeToGlyphId[charCode] = builtInEncoding[charCode];\n    }\n  } else {\n    baseEncoding = StandardEncoding;\n    for (charCode = 0; charCode < baseEncoding.length; charCode++) {\n      glyphId = glyphNames.indexOf(baseEncoding[charCode]);\n      charCodeToGlyphId[charCode] = glyphId >= 0 ? glyphId : 0;\n    }\n  }\n  const differences = properties.differences;\n  let glyphsUnicodeMap;\n  if (differences) {\n    for (charCode in differences) {\n      const glyphName = differences[charCode];\n      glyphId = glyphNames.indexOf(glyphName);\n      if (glyphId === -1) {\n        if (!glyphsUnicodeMap) {\n          glyphsUnicodeMap = getGlyphsUnicode();\n        }\n        const standardGlyphName = recoverGlyphName(glyphName, glyphsUnicodeMap);\n        if (standardGlyphName !== glyphName) {\n          glyphId = glyphNames.indexOf(standardGlyphName);\n        }\n      }\n      charCodeToGlyphId[charCode] = glyphId >= 0 ? glyphId : 0;\n    }\n  }\n  return charCodeToGlyphId;\n}\nfunction normalizeFontName(name) {\n  return name.replaceAll(/[,_]/g, \"-\").replaceAll(/\\s/g, \"\");\n}\n\n;// CONCATENATED MODULE: ./src/core/standard_fonts.js\n\n\nconst getStdFontMap = getLookupTableFactory(function (t) {\n  t[\"Times-Roman\"] = \"Times-Roman\";\n  t.Helvetica = \"Helvetica\";\n  t.Courier = \"Courier\";\n  t.Symbol = \"Symbol\";\n  t[\"Times-Bold\"] = \"Times-Bold\";\n  t[\"Helvetica-Bold\"] = \"Helvetica-Bold\";\n  t[\"Courier-Bold\"] = \"Courier-Bold\";\n  t.ZapfDingbats = \"ZapfDingbats\";\n  t[\"Times-Italic\"] = \"Times-Italic\";\n  t[\"Helvetica-Oblique\"] = \"Helvetica-Oblique\";\n  t[\"Courier-Oblique\"] = \"Courier-Oblique\";\n  t[\"Times-BoldItalic\"] = \"Times-BoldItalic\";\n  t[\"Helvetica-BoldOblique\"] = \"Helvetica-BoldOblique\";\n  t[\"Courier-BoldOblique\"] = \"Courier-BoldOblique\";\n  t.ArialNarrow = \"Helvetica\";\n  t[\"ArialNarrow-Bold\"] = \"Helvetica-Bold\";\n  t[\"ArialNarrow-BoldItalic\"] = \"Helvetica-BoldOblique\";\n  t[\"ArialNarrow-Italic\"] = \"Helvetica-Oblique\";\n  t.ArialBlack = \"Helvetica\";\n  t[\"ArialBlack-Bold\"] = \"Helvetica-Bold\";\n  t[\"ArialBlack-BoldItalic\"] = \"Helvetica-BoldOblique\";\n  t[\"ArialBlack-Italic\"] = \"Helvetica-Oblique\";\n  t[\"Arial-Black\"] = \"Helvetica\";\n  t[\"Arial-Black-Bold\"] = \"Helvetica-Bold\";\n  t[\"Arial-Black-BoldItalic\"] = \"Helvetica-BoldOblique\";\n  t[\"Arial-Black-Italic\"] = \"Helvetica-Oblique\";\n  t.Arial = \"Helvetica\";\n  t[\"Arial-Bold\"] = \"Helvetica-Bold\";\n  t[\"Arial-BoldItalic\"] = \"Helvetica-BoldOblique\";\n  t[\"Arial-Italic\"] = \"Helvetica-Oblique\";\n  t.ArialMT = \"Helvetica\";\n  t[\"Arial-BoldItalicMT\"] = \"Helvetica-BoldOblique\";\n  t[\"Arial-BoldMT\"] = \"Helvetica-Bold\";\n  t[\"Arial-ItalicMT\"] = \"Helvetica-Oblique\";\n  t[\"Arial-BoldItalicMT-BoldItalic\"] = \"Helvetica-BoldOblique\";\n  t[\"Arial-BoldMT-Bold\"] = \"Helvetica-Bold\";\n  t[\"Arial-ItalicMT-Italic\"] = \"Helvetica-Oblique\";\n  t.ArialUnicodeMS = \"Helvetica\";\n  t[\"ArialUnicodeMS-Bold\"] = \"Helvetica-Bold\";\n  t[\"ArialUnicodeMS-BoldItalic\"] = \"Helvetica-BoldOblique\";\n  t[\"ArialUnicodeMS-Italic\"] = \"Helvetica-Oblique\";\n  t[\"Courier-BoldItalic\"] = \"Courier-BoldOblique\";\n  t[\"Courier-Italic\"] = \"Courier-Oblique\";\n  t.CourierNew = \"Courier\";\n  t[\"CourierNew-Bold\"] = \"Courier-Bold\";\n  t[\"CourierNew-BoldItalic\"] = \"Courier-BoldOblique\";\n  t[\"CourierNew-Italic\"] = \"Courier-Oblique\";\n  t[\"CourierNewPS-BoldItalicMT\"] = \"Courier-BoldOblique\";\n  t[\"CourierNewPS-BoldMT\"] = \"Courier-Bold\";\n  t[\"CourierNewPS-ItalicMT\"] = \"Courier-Oblique\";\n  t.CourierNewPSMT = \"Courier\";\n  t[\"Helvetica-BoldItalic\"] = \"Helvetica-BoldOblique\";\n  t[\"Helvetica-Italic\"] = \"Helvetica-Oblique\";\n  t[\"Symbol-Bold\"] = \"Symbol\";\n  t[\"Symbol-BoldItalic\"] = \"Symbol\";\n  t[\"Symbol-Italic\"] = \"Symbol\";\n  t.TimesNewRoman = \"Times-Roman\";\n  t[\"TimesNewRoman-Bold\"] = \"Times-Bold\";\n  t[\"TimesNewRoman-BoldItalic\"] = \"Times-BoldItalic\";\n  t[\"TimesNewRoman-Italic\"] = \"Times-Italic\";\n  t.TimesNewRomanPS = \"Times-Roman\";\n  t[\"TimesNewRomanPS-Bold\"] = \"Times-Bold\";\n  t[\"TimesNewRomanPS-BoldItalic\"] = \"Times-BoldItalic\";\n  t[\"TimesNewRomanPS-BoldItalicMT\"] = \"Times-BoldItalic\";\n  t[\"TimesNewRomanPS-BoldMT\"] = \"Times-Bold\";\n  t[\"TimesNewRomanPS-Italic\"] = \"Times-Italic\";\n  t[\"TimesNewRomanPS-ItalicMT\"] = \"Times-Italic\";\n  t.TimesNewRomanPSMT = \"Times-Roman\";\n  t[\"TimesNewRomanPSMT-Bold\"] = \"Times-Bold\";\n  t[\"TimesNewRomanPSMT-BoldItalic\"] = \"Times-BoldItalic\";\n  t[\"TimesNewRomanPSMT-Italic\"] = \"Times-Italic\";\n});\nconst getFontNameToFileMap = getLookupTableFactory(function (t) {\n  t.Courier = \"FoxitFixed.pfb\";\n  t[\"Courier-Bold\"] = \"FoxitFixedBold.pfb\";\n  t[\"Courier-BoldOblique\"] = \"FoxitFixedBoldItalic.pfb\";\n  t[\"Courier-Oblique\"] = \"FoxitFixedItalic.pfb\";\n  t.Helvetica = \"LiberationSans-Regular.ttf\";\n  t[\"Helvetica-Bold\"] = \"LiberationSans-Bold.ttf\";\n  t[\"Helvetica-BoldOblique\"] = \"LiberationSans-BoldItalic.ttf\";\n  t[\"Helvetica-Oblique\"] = \"LiberationSans-Italic.ttf\";\n  t[\"Times-Roman\"] = \"FoxitSerif.pfb\";\n  t[\"Times-Bold\"] = \"FoxitSerifBold.pfb\";\n  t[\"Times-BoldItalic\"] = \"FoxitSerifBoldItalic.pfb\";\n  t[\"Times-Italic\"] = \"FoxitSerifItalic.pfb\";\n  t.Symbol = \"FoxitSymbol.pfb\";\n  t.ZapfDingbats = \"FoxitDingbats.pfb\";\n  t[\"LiberationSans-Regular\"] = \"LiberationSans-Regular.ttf\";\n  t[\"LiberationSans-Bold\"] = \"LiberationSans-Bold.ttf\";\n  t[\"LiberationSans-Italic\"] = \"LiberationSans-Italic.ttf\";\n  t[\"LiberationSans-BoldItalic\"] = \"LiberationSans-BoldItalic.ttf\";\n});\nconst getNonStdFontMap = getLookupTableFactory(function (t) {\n  t.Calibri = \"Helvetica\";\n  t[\"Calibri-Bold\"] = \"Helvetica-Bold\";\n  t[\"Calibri-BoldItalic\"] = \"Helvetica-BoldOblique\";\n  t[\"Calibri-Italic\"] = \"Helvetica-Oblique\";\n  t.CenturyGothic = \"Helvetica\";\n  t[\"CenturyGothic-Bold\"] = \"Helvetica-Bold\";\n  t[\"CenturyGothic-BoldItalic\"] = \"Helvetica-BoldOblique\";\n  t[\"CenturyGothic-Italic\"] = \"Helvetica-Oblique\";\n  t.ComicSansMS = \"Comic Sans MS\";\n  t[\"ComicSansMS-Bold\"] = \"Comic Sans MS-Bold\";\n  t[\"ComicSansMS-BoldItalic\"] = \"Comic Sans MS-BoldItalic\";\n  t[\"ComicSansMS-Italic\"] = \"Comic Sans MS-Italic\";\n  t.Impact = \"Helvetica\";\n  t[\"ItcSymbol-Bold\"] = \"Helvetica-Bold\";\n  t[\"ItcSymbol-BoldItalic\"] = \"Helvetica-BoldOblique\";\n  t[\"ItcSymbol-Book\"] = \"Helvetica\";\n  t[\"ItcSymbol-BookItalic\"] = \"Helvetica-Oblique\";\n  t[\"ItcSymbol-Medium\"] = \"Helvetica\";\n  t[\"ItcSymbol-MediumItalic\"] = \"Helvetica-Oblique\";\n  t.LucidaConsole = \"Courier\";\n  t[\"LucidaConsole-Bold\"] = \"Courier-Bold\";\n  t[\"LucidaConsole-BoldItalic\"] = \"Courier-BoldOblique\";\n  t[\"LucidaConsole-Italic\"] = \"Courier-Oblique\";\n  t[\"LucidaSans-Demi\"] = \"Helvetica-Bold\";\n  t[\"MS-Gothic\"] = \"MS Gothic\";\n  t[\"MS-Gothic-Bold\"] = \"MS Gothic-Bold\";\n  t[\"MS-Gothic-BoldItalic\"] = \"MS Gothic-BoldItalic\";\n  t[\"MS-Gothic-Italic\"] = \"MS Gothic-Italic\";\n  t[\"MS-Mincho\"] = \"MS Mincho\";\n  t[\"MS-Mincho-Bold\"] = \"MS Mincho-Bold\";\n  t[\"MS-Mincho-BoldItalic\"] = \"MS Mincho-BoldItalic\";\n  t[\"MS-Mincho-Italic\"] = \"MS Mincho-Italic\";\n  t[\"MS-PGothic\"] = \"MS PGothic\";\n  t[\"MS-PGothic-Bold\"] = \"MS PGothic-Bold\";\n  t[\"MS-PGothic-BoldItalic\"] = \"MS PGothic-BoldItalic\";\n  t[\"MS-PGothic-Italic\"] = \"MS PGothic-Italic\";\n  t[\"MS-PMincho\"] = \"MS PMincho\";\n  t[\"MS-PMincho-Bold\"] = \"MS PMincho-Bold\";\n  t[\"MS-PMincho-BoldItalic\"] = \"MS PMincho-BoldItalic\";\n  t[\"MS-PMincho-Italic\"] = \"MS PMincho-Italic\";\n  t.NuptialScript = \"Times-Italic\";\n  t.SegoeUISymbol = \"Helvetica\";\n});\nconst getSerifFonts = getLookupTableFactory(function (t) {\n  t[\"Adobe Jenson\"] = true;\n  t[\"Adobe Text\"] = true;\n  t.Albertus = true;\n  t.Aldus = true;\n  t.Alexandria = true;\n  t.Algerian = true;\n  t[\"American Typewriter\"] = true;\n  t.Antiqua = true;\n  t.Apex = true;\n  t.Arno = true;\n  t.Aster = true;\n  t.Aurora = true;\n  t.Baskerville = true;\n  t.Bell = true;\n  t.Bembo = true;\n  t[\"Bembo Schoolbook\"] = true;\n  t.Benguiat = true;\n  t[\"Berkeley Old Style\"] = true;\n  t[\"Bernhard Modern\"] = true;\n  t[\"Berthold City\"] = true;\n  t.Bodoni = true;\n  t[\"Bauer Bodoni\"] = true;\n  t[\"Book Antiqua\"] = true;\n  t.Bookman = true;\n  t[\"Bordeaux Roman\"] = true;\n  t[\"Californian FB\"] = true;\n  t.Calisto = true;\n  t.Calvert = true;\n  t.Capitals = true;\n  t.Cambria = true;\n  t.Cartier = true;\n  t.Caslon = true;\n  t.Catull = true;\n  t.Centaur = true;\n  t[\"Century Old Style\"] = true;\n  t[\"Century Schoolbook\"] = true;\n  t.Chaparral = true;\n  t[\"Charis SIL\"] = true;\n  t.Cheltenham = true;\n  t[\"Cholla Slab\"] = true;\n  t.Clarendon = true;\n  t.Clearface = true;\n  t.Cochin = true;\n  t.Colonna = true;\n  t[\"Computer Modern\"] = true;\n  t[\"Concrete Roman\"] = true;\n  t.Constantia = true;\n  t[\"Cooper Black\"] = true;\n  t.Corona = true;\n  t.Ecotype = true;\n  t.Egyptienne = true;\n  t.Elephant = true;\n  t.Excelsior = true;\n  t.Fairfield = true;\n  t[\"FF Scala\"] = true;\n  t.Folkard = true;\n  t.Footlight = true;\n  t.FreeSerif = true;\n  t[\"Friz Quadrata\"] = true;\n  t.Garamond = true;\n  t.Gentium = true;\n  t.Georgia = true;\n  t.Gloucester = true;\n  t[\"Goudy Old Style\"] = true;\n  t[\"Goudy Schoolbook\"] = true;\n  t[\"Goudy Pro Font\"] = true;\n  t.Granjon = true;\n  t[\"Guardian Egyptian\"] = true;\n  t.Heather = true;\n  t.Hercules = true;\n  t[\"High Tower Text\"] = true;\n  t.Hiroshige = true;\n  t[\"Hoefler Text\"] = true;\n  t[\"Humana Serif\"] = true;\n  t.Imprint = true;\n  t[\"Ionic No. 5\"] = true;\n  t.Janson = true;\n  t.Joanna = true;\n  t.Korinna = true;\n  t.Lexicon = true;\n  t.LiberationSerif = true;\n  t[\"Liberation Serif\"] = true;\n  t[\"Linux Libertine\"] = true;\n  t.Literaturnaya = true;\n  t.Lucida = true;\n  t[\"Lucida Bright\"] = true;\n  t.Melior = true;\n  t.Memphis = true;\n  t.Miller = true;\n  t.Minion = true;\n  t.Modern = true;\n  t[\"Mona Lisa\"] = true;\n  t[\"Mrs Eaves\"] = true;\n  t[\"MS Serif\"] = true;\n  t[\"Museo Slab\"] = true;\n  t[\"New York\"] = true;\n  t[\"Nimbus Roman\"] = true;\n  t[\"NPS Rawlinson Roadway\"] = true;\n  t.NuptialScript = true;\n  t.Palatino = true;\n  t.Perpetua = true;\n  t.Plantin = true;\n  t[\"Plantin Schoolbook\"] = true;\n  t.Playbill = true;\n  t[\"Poor Richard\"] = true;\n  t[\"Rawlinson Roadway\"] = true;\n  t.Renault = true;\n  t.Requiem = true;\n  t.Rockwell = true;\n  t.Roman = true;\n  t[\"Rotis Serif\"] = true;\n  t.Sabon = true;\n  t.Scala = true;\n  t.Seagull = true;\n  t.Sistina = true;\n  t.Souvenir = true;\n  t.STIX = true;\n  t[\"Stone Informal\"] = true;\n  t[\"Stone Serif\"] = true;\n  t.Sylfaen = true;\n  t.Times = true;\n  t.Trajan = true;\n  t[\"Trinité\"] = true;\n  t[\"Trump Mediaeval\"] = true;\n  t.Utopia = true;\n  t[\"Vale Type\"] = true;\n  t[\"Bitstream Vera\"] = true;\n  t[\"Vera Serif\"] = true;\n  t.Versailles = true;\n  t.Wanted = true;\n  t.Weiss = true;\n  t[\"Wide Latin\"] = true;\n  t.Windsor = true;\n  t.XITS = true;\n});\nconst getSymbolsFonts = getLookupTableFactory(function (t) {\n  t.Dingbats = true;\n  t.Symbol = true;\n  t.ZapfDingbats = true;\n  t.Wingdings = true;\n  t[\"Wingdings-Bold\"] = true;\n  t[\"Wingdings-Regular\"] = true;\n});\nconst getGlyphMapForStandardFonts = getLookupTableFactory(function (t) {\n  t[2] = 10;\n  t[3] = 32;\n  t[4] = 33;\n  t[5] = 34;\n  t[6] = 35;\n  t[7] = 36;\n  t[8] = 37;\n  t[9] = 38;\n  t[10] = 39;\n  t[11] = 40;\n  t[12] = 41;\n  t[13] = 42;\n  t[14] = 43;\n  t[15] = 44;\n  t[16] = 45;\n  t[17] = 46;\n  t[18] = 47;\n  t[19] = 48;\n  t[20] = 49;\n  t[21] = 50;\n  t[22] = 51;\n  t[23] = 52;\n  t[24] = 53;\n  t[25] = 54;\n  t[26] = 55;\n  t[27] = 56;\n  t[28] = 57;\n  t[29] = 58;\n  t[30] = 894;\n  t[31] = 60;\n  t[32] = 61;\n  t[33] = 62;\n  t[34] = 63;\n  t[35] = 64;\n  t[36] = 65;\n  t[37] = 66;\n  t[38] = 67;\n  t[39] = 68;\n  t[40] = 69;\n  t[41] = 70;\n  t[42] = 71;\n  t[43] = 72;\n  t[44] = 73;\n  t[45] = 74;\n  t[46] = 75;\n  t[47] = 76;\n  t[48] = 77;\n  t[49] = 78;\n  t[50] = 79;\n  t[51] = 80;\n  t[52] = 81;\n  t[53] = 82;\n  t[54] = 83;\n  t[55] = 84;\n  t[56] = 85;\n  t[57] = 86;\n  t[58] = 87;\n  t[59] = 88;\n  t[60] = 89;\n  t[61] = 90;\n  t[62] = 91;\n  t[63] = 92;\n  t[64] = 93;\n  t[65] = 94;\n  t[66] = 95;\n  t[67] = 96;\n  t[68] = 97;\n  t[69] = 98;\n  t[70] = 99;\n  t[71] = 100;\n  t[72] = 101;\n  t[73] = 102;\n  t[74] = 103;\n  t[75] = 104;\n  t[76] = 105;\n  t[77] = 106;\n  t[78] = 107;\n  t[79] = 108;\n  t[80] = 109;\n  t[81] = 110;\n  t[82] = 111;\n  t[83] = 112;\n  t[84] = 113;\n  t[85] = 114;\n  t[86] = 115;\n  t[87] = 116;\n  t[88] = 117;\n  t[89] = 118;\n  t[90] = 119;\n  t[91] = 120;\n  t[92] = 121;\n  t[93] = 122;\n  t[94] = 123;\n  t[95] = 124;\n  t[96] = 125;\n  t[97] = 126;\n  t[98] = 196;\n  t[99] = 197;\n  t[100] = 199;\n  t[101] = 201;\n  t[102] = 209;\n  t[103] = 214;\n  t[104] = 220;\n  t[105] = 225;\n  t[106] = 224;\n  t[107] = 226;\n  t[108] = 228;\n  t[109] = 227;\n  t[110] = 229;\n  t[111] = 231;\n  t[112] = 233;\n  t[113] = 232;\n  t[114] = 234;\n  t[115] = 235;\n  t[116] = 237;\n  t[117] = 236;\n  t[118] = 238;\n  t[119] = 239;\n  t[120] = 241;\n  t[121] = 243;\n  t[122] = 242;\n  t[123] = 244;\n  t[124] = 246;\n  t[125] = 245;\n  t[126] = 250;\n  t[127] = 249;\n  t[128] = 251;\n  t[129] = 252;\n  t[130] = 8224;\n  t[131] = 176;\n  t[132] = 162;\n  t[133] = 163;\n  t[134] = 167;\n  t[135] = 8226;\n  t[136] = 182;\n  t[137] = 223;\n  t[138] = 174;\n  t[139] = 169;\n  t[140] = 8482;\n  t[141] = 180;\n  t[142] = 168;\n  t[143] = 8800;\n  t[144] = 198;\n  t[145] = 216;\n  t[146] = 8734;\n  t[147] = 177;\n  t[148] = 8804;\n  t[149] = 8805;\n  t[150] = 165;\n  t[151] = 181;\n  t[152] = 8706;\n  t[153] = 8721;\n  t[154] = 8719;\n  t[156] = 8747;\n  t[157] = 170;\n  t[158] = 186;\n  t[159] = 8486;\n  t[160] = 230;\n  t[161] = 248;\n  t[162] = 191;\n  t[163] = 161;\n  t[164] = 172;\n  t[165] = 8730;\n  t[166] = 402;\n  t[167] = 8776;\n  t[168] = 8710;\n  t[169] = 171;\n  t[170] = 187;\n  t[171] = 8230;\n  t[179] = 8220;\n  t[180] = 8221;\n  t[181] = 8216;\n  t[182] = 8217;\n  t[200] = 193;\n  t[203] = 205;\n  t[207] = 211;\n  t[210] = 218;\n  t[223] = 711;\n  t[224] = 321;\n  t[225] = 322;\n  t[226] = 352;\n  t[227] = 353;\n  t[228] = 381;\n  t[229] = 382;\n  t[233] = 221;\n  t[234] = 253;\n  t[252] = 263;\n  t[253] = 268;\n  t[254] = 269;\n  t[258] = 258;\n  t[260] = 260;\n  t[261] = 261;\n  t[265] = 280;\n  t[266] = 281;\n  t[267] = 282;\n  t[268] = 283;\n  t[269] = 313;\n  t[275] = 323;\n  t[276] = 324;\n  t[278] = 328;\n  t[283] = 344;\n  t[284] = 345;\n  t[285] = 346;\n  t[286] = 347;\n  t[292] = 367;\n  t[295] = 377;\n  t[296] = 378;\n  t[298] = 380;\n  t[305] = 963;\n  t[306] = 964;\n  t[307] = 966;\n  t[308] = 8215;\n  t[309] = 8252;\n  t[310] = 8319;\n  t[311] = 8359;\n  t[312] = 8592;\n  t[313] = 8593;\n  t[337] = 9552;\n  t[493] = 1039;\n  t[494] = 1040;\n  t[672] = 1488;\n  t[673] = 1489;\n  t[674] = 1490;\n  t[675] = 1491;\n  t[676] = 1492;\n  t[677] = 1493;\n  t[678] = 1494;\n  t[679] = 1495;\n  t[680] = 1496;\n  t[681] = 1497;\n  t[682] = 1498;\n  t[683] = 1499;\n  t[684] = 1500;\n  t[685] = 1501;\n  t[686] = 1502;\n  t[687] = 1503;\n  t[688] = 1504;\n  t[689] = 1505;\n  t[690] = 1506;\n  t[691] = 1507;\n  t[692] = 1508;\n  t[693] = 1509;\n  t[694] = 1510;\n  t[695] = 1511;\n  t[696] = 1512;\n  t[697] = 1513;\n  t[698] = 1514;\n  t[705] = 1524;\n  t[706] = 8362;\n  t[710] = 64288;\n  t[711] = 64298;\n  t[759] = 1617;\n  t[761] = 1776;\n  t[763] = 1778;\n  t[775] = 1652;\n  t[777] = 1764;\n  t[778] = 1780;\n  t[779] = 1781;\n  t[780] = 1782;\n  t[782] = 771;\n  t[783] = 64726;\n  t[786] = 8363;\n  t[788] = 8532;\n  t[790] = 768;\n  t[791] = 769;\n  t[792] = 768;\n  t[795] = 803;\n  t[797] = 64336;\n  t[798] = 64337;\n  t[799] = 64342;\n  t[800] = 64343;\n  t[801] = 64344;\n  t[802] = 64345;\n  t[803] = 64362;\n  t[804] = 64363;\n  t[805] = 64364;\n  t[2424] = 7821;\n  t[2425] = 7822;\n  t[2426] = 7823;\n  t[2427] = 7824;\n  t[2428] = 7825;\n  t[2429] = 7826;\n  t[2430] = 7827;\n  t[2433] = 7682;\n  t[2678] = 8045;\n  t[2679] = 8046;\n  t[2830] = 1552;\n  t[2838] = 686;\n  t[2840] = 751;\n  t[2842] = 753;\n  t[2843] = 754;\n  t[2844] = 755;\n  t[2846] = 757;\n  t[2856] = 767;\n  t[2857] = 848;\n  t[2858] = 849;\n  t[2862] = 853;\n  t[2863] = 854;\n  t[2864] = 855;\n  t[2865] = 861;\n  t[2866] = 862;\n  t[2906] = 7460;\n  t[2908] = 7462;\n  t[2909] = 7463;\n  t[2910] = 7464;\n  t[2912] = 7466;\n  t[2913] = 7467;\n  t[2914] = 7468;\n  t[2916] = 7470;\n  t[2917] = 7471;\n  t[2918] = 7472;\n  t[2920] = 7474;\n  t[2921] = 7475;\n  t[2922] = 7476;\n  t[2924] = 7478;\n  t[2925] = 7479;\n  t[2926] = 7480;\n  t[2928] = 7482;\n  t[2929] = 7483;\n  t[2930] = 7484;\n  t[2932] = 7486;\n  t[2933] = 7487;\n  t[2934] = 7488;\n  t[2936] = 7490;\n  t[2937] = 7491;\n  t[2938] = 7492;\n  t[2940] = 7494;\n  t[2941] = 7495;\n  t[2942] = 7496;\n  t[2944] = 7498;\n  t[2946] = 7500;\n  t[2948] = 7502;\n  t[2950] = 7504;\n  t[2951] = 7505;\n  t[2952] = 7506;\n  t[2954] = 7508;\n  t[2955] = 7509;\n  t[2956] = 7510;\n  t[2958] = 7512;\n  t[2959] = 7513;\n  t[2960] = 7514;\n  t[2962] = 7516;\n  t[2963] = 7517;\n  t[2964] = 7518;\n  t[2966] = 7520;\n  t[2967] = 7521;\n  t[2968] = 7522;\n  t[2970] = 7524;\n  t[2971] = 7525;\n  t[2972] = 7526;\n  t[2974] = 7528;\n  t[2975] = 7529;\n  t[2976] = 7530;\n  t[2978] = 1537;\n  t[2979] = 1538;\n  t[2980] = 1539;\n  t[2982] = 1549;\n  t[2983] = 1551;\n  t[2984] = 1552;\n  t[2986] = 1554;\n  t[2987] = 1555;\n  t[2988] = 1556;\n  t[2990] = 1623;\n  t[2991] = 1624;\n  t[2995] = 1775;\n  t[2999] = 1791;\n  t[3002] = 64290;\n  t[3003] = 64291;\n  t[3004] = 64292;\n  t[3006] = 64294;\n  t[3007] = 64295;\n  t[3008] = 64296;\n  t[3011] = 1900;\n  t[3014] = 8223;\n  t[3015] = 8244;\n  t[3017] = 7532;\n  t[3018] = 7533;\n  t[3019] = 7534;\n  t[3075] = 7590;\n  t[3076] = 7591;\n  t[3079] = 7594;\n  t[3080] = 7595;\n  t[3083] = 7598;\n  t[3084] = 7599;\n  t[3087] = 7602;\n  t[3088] = 7603;\n  t[3091] = 7606;\n  t[3092] = 7607;\n  t[3095] = 7610;\n  t[3096] = 7611;\n  t[3099] = 7614;\n  t[3100] = 7615;\n  t[3103] = 7618;\n  t[3104] = 7619;\n  t[3107] = 8337;\n  t[3108] = 8338;\n  t[3116] = 1884;\n  t[3119] = 1885;\n  t[3120] = 1885;\n  t[3123] = 1886;\n  t[3124] = 1886;\n  t[3127] = 1887;\n  t[3128] = 1887;\n  t[3131] = 1888;\n  t[3132] = 1888;\n  t[3135] = 1889;\n  t[3136] = 1889;\n  t[3139] = 1890;\n  t[3140] = 1890;\n  t[3143] = 1891;\n  t[3144] = 1891;\n  t[3147] = 1892;\n  t[3148] = 1892;\n  t[3153] = 580;\n  t[3154] = 581;\n  t[3157] = 584;\n  t[3158] = 585;\n  t[3161] = 588;\n  t[3162] = 589;\n  t[3165] = 891;\n  t[3166] = 892;\n  t[3169] = 1274;\n  t[3170] = 1275;\n  t[3173] = 1278;\n  t[3174] = 1279;\n  t[3181] = 7622;\n  t[3182] = 7623;\n  t[3282] = 11799;\n  t[3316] = 578;\n  t[3379] = 42785;\n  t[3393] = 1159;\n  t[3416] = 8377;\n});\nconst getSupplementalGlyphMapForArialBlack = getLookupTableFactory(function (t) {\n  t[227] = 322;\n  t[264] = 261;\n  t[291] = 346;\n});\nconst getSupplementalGlyphMapForCalibri = getLookupTableFactory(function (t) {\n  t[1] = 32;\n  t[4] = 65;\n  t[5] = 192;\n  t[6] = 193;\n  t[9] = 196;\n  t[17] = 66;\n  t[18] = 67;\n  t[21] = 268;\n  t[24] = 68;\n  t[28] = 69;\n  t[29] = 200;\n  t[30] = 201;\n  t[32] = 282;\n  t[38] = 70;\n  t[39] = 71;\n  t[44] = 72;\n  t[47] = 73;\n  t[48] = 204;\n  t[49] = 205;\n  t[58] = 74;\n  t[60] = 75;\n  t[62] = 76;\n  t[68] = 77;\n  t[69] = 78;\n  t[75] = 79;\n  t[76] = 210;\n  t[80] = 214;\n  t[87] = 80;\n  t[89] = 81;\n  t[90] = 82;\n  t[92] = 344;\n  t[94] = 83;\n  t[97] = 352;\n  t[100] = 84;\n  t[104] = 85;\n  t[109] = 220;\n  t[115] = 86;\n  t[116] = 87;\n  t[121] = 88;\n  t[122] = 89;\n  t[124] = 221;\n  t[127] = 90;\n  t[129] = 381;\n  t[258] = 97;\n  t[259] = 224;\n  t[260] = 225;\n  t[263] = 228;\n  t[268] = 261;\n  t[271] = 98;\n  t[272] = 99;\n  t[273] = 263;\n  t[275] = 269;\n  t[282] = 100;\n  t[286] = 101;\n  t[287] = 232;\n  t[288] = 233;\n  t[290] = 283;\n  t[295] = 281;\n  t[296] = 102;\n  t[336] = 103;\n  t[346] = 104;\n  t[349] = 105;\n  t[350] = 236;\n  t[351] = 237;\n  t[361] = 106;\n  t[364] = 107;\n  t[367] = 108;\n  t[371] = 322;\n  t[373] = 109;\n  t[374] = 110;\n  t[381] = 111;\n  t[382] = 242;\n  t[383] = 243;\n  t[386] = 246;\n  t[393] = 112;\n  t[395] = 113;\n  t[396] = 114;\n  t[398] = 345;\n  t[400] = 115;\n  t[401] = 347;\n  t[403] = 353;\n  t[410] = 116;\n  t[437] = 117;\n  t[442] = 252;\n  t[448] = 118;\n  t[449] = 119;\n  t[454] = 120;\n  t[455] = 121;\n  t[457] = 253;\n  t[460] = 122;\n  t[462] = 382;\n  t[463] = 380;\n  t[853] = 44;\n  t[855] = 58;\n  t[856] = 46;\n  t[876] = 47;\n  t[878] = 45;\n  t[882] = 45;\n  t[894] = 40;\n  t[895] = 41;\n  t[896] = 91;\n  t[897] = 93;\n  t[923] = 64;\n  t[1004] = 48;\n  t[1005] = 49;\n  t[1006] = 50;\n  t[1007] = 51;\n  t[1008] = 52;\n  t[1009] = 53;\n  t[1010] = 54;\n  t[1011] = 55;\n  t[1012] = 56;\n  t[1013] = 57;\n  t[1081] = 37;\n  t[1085] = 43;\n  t[1086] = 45;\n});\nfunction getStandardFontName(name) {\n  const fontName = normalizeFontName(name);\n  const stdFontMap = getStdFontMap();\n  return stdFontMap[fontName];\n}\nfunction isKnownFontName(name) {\n  const fontName = normalizeFontName(name);\n  return !!(getStdFontMap()[fontName] || getNonStdFontMap()[fontName] || getSerifFonts()[fontName] || getSymbolsFonts()[fontName]);\n}\n\n;// CONCATENATED MODULE: ./src/core/to_unicode_map.js\n\nclass ToUnicodeMap {\n  constructor(cmap = []) {\n    this._map = cmap;\n  }\n  get length() {\n    return this._map.length;\n  }\n  forEach(callback) {\n    for (const charCode in this._map) {\n      callback(charCode, this._map[charCode].charCodeAt(0));\n    }\n  }\n  has(i) {\n    return this._map[i] !== undefined;\n  }\n  get(i) {\n    return this._map[i];\n  }\n  charCodeOf(value) {\n    const map = this._map;\n    if (map.length <= 0x10000) {\n      return map.indexOf(value);\n    }\n    for (const charCode in map) {\n      if (map[charCode] === value) {\n        return charCode | 0;\n      }\n    }\n    return -1;\n  }\n  amend(map) {\n    for (const charCode in map) {\n      this._map[charCode] = map[charCode];\n    }\n  }\n}\nclass IdentityToUnicodeMap {\n  constructor(firstChar, lastChar) {\n    this.firstChar = firstChar;\n    this.lastChar = lastChar;\n  }\n  get length() {\n    return this.lastChar + 1 - this.firstChar;\n  }\n  forEach(callback) {\n    for (let i = this.firstChar, ii = this.lastChar; i <= ii; i++) {\n      callback(i, i);\n    }\n  }\n  has(i) {\n    return this.firstChar <= i && i <= this.lastChar;\n  }\n  get(i) {\n    if (this.firstChar <= i && i <= this.lastChar) {\n      return String.fromCharCode(i);\n    }\n    return undefined;\n  }\n  charCodeOf(v) {\n    return Number.isInteger(v) && v >= this.firstChar && v <= this.lastChar ? v : -1;\n  }\n  amend(map) {\n    unreachable(\"Should not call amend()\");\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/cff_font.js\n\n\n\nclass CFFFont {\n  constructor(file, properties) {\n    this.properties = properties;\n    const parser = new CFFParser(file, properties, SEAC_ANALYSIS_ENABLED);\n    this.cff = parser.parse();\n    this.cff.duplicateFirstGlyph();\n    const compiler = new CFFCompiler(this.cff);\n    this.seacs = this.cff.seacs;\n    try {\n      this.data = compiler.compile();\n    } catch {\n      warn(\"Failed to compile font \" + properties.loadedName);\n      this.data = file;\n    }\n    this._createBuiltInEncoding();\n  }\n  get numGlyphs() {\n    return this.cff.charStrings.count;\n  }\n  getCharset() {\n    return this.cff.charset.charset;\n  }\n  getGlyphMapping() {\n    const cff = this.cff;\n    const properties = this.properties;\n    const {\n      cidToGidMap,\n      cMap\n    } = properties;\n    const charsets = cff.charset.charset;\n    let charCodeToGlyphId;\n    let glyphId;\n    if (properties.composite) {\n      let invCidToGidMap;\n      if (cidToGidMap?.length > 0) {\n        invCidToGidMap = Object.create(null);\n        for (let i = 0, ii = cidToGidMap.length; i < ii; i++) {\n          const gid = cidToGidMap[i];\n          if (gid !== undefined) {\n            invCidToGidMap[gid] = i;\n          }\n        }\n      }\n      charCodeToGlyphId = Object.create(null);\n      let charCode;\n      if (cff.isCIDFont) {\n        for (glyphId = 0; glyphId < charsets.length; glyphId++) {\n          const cid = charsets[glyphId];\n          charCode = cMap.charCodeOf(cid);\n          if (invCidToGidMap?.[charCode] !== undefined) {\n            charCode = invCidToGidMap[charCode];\n          }\n          charCodeToGlyphId[charCode] = glyphId;\n        }\n      } else {\n        for (glyphId = 0; glyphId < cff.charStrings.count; glyphId++) {\n          charCode = cMap.charCodeOf(glyphId);\n          charCodeToGlyphId[charCode] = glyphId;\n        }\n      }\n      return charCodeToGlyphId;\n    }\n    let encoding = cff.encoding ? cff.encoding.encoding : null;\n    if (properties.isInternalFont) {\n      encoding = properties.defaultEncoding;\n    }\n    charCodeToGlyphId = type1FontGlyphMapping(properties, encoding, charsets);\n    return charCodeToGlyphId;\n  }\n  hasGlyphId(id) {\n    return this.cff.hasGlyphId(id);\n  }\n  _createBuiltInEncoding() {\n    const {\n      charset,\n      encoding\n    } = this.cff;\n    if (!charset || !encoding) {\n      return;\n    }\n    const charsets = charset.charset,\n      encodings = encoding.encoding;\n    const map = [];\n    for (const charCode in encodings) {\n      const glyphId = encodings[charCode];\n      if (glyphId >= 0) {\n        const glyphName = charsets[glyphId];\n        if (glyphName) {\n          map[charCode] = glyphName;\n        }\n      }\n    }\n    if (map.length > 0) {\n      this.properties.builtInEncoding = map;\n    }\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/font_renderer.js\n\n\n\n\n\n\nfunction getUint32(data, offset) {\n  return (data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]) >>> 0;\n}\nfunction getUint16(data, offset) {\n  return data[offset] << 8 | data[offset + 1];\n}\nfunction getInt16(data, offset) {\n  return (data[offset] << 24 | data[offset + 1] << 16) >> 16;\n}\nfunction getInt8(data, offset) {\n  return data[offset] << 24 >> 24;\n}\nfunction getFloat214(data, offset) {\n  return getInt16(data, offset) / 16384;\n}\nfunction getSubroutineBias(subrs) {\n  const numSubrs = subrs.length;\n  let bias = 32768;\n  if (numSubrs < 1240) {\n    bias = 107;\n  } else if (numSubrs < 33900) {\n    bias = 1131;\n  }\n  return bias;\n}\nfunction parseCmap(data, start, end) {\n  const offset = getUint16(data, start + 2) === 1 ? getUint32(data, start + 8) : getUint32(data, start + 16);\n  const format = getUint16(data, start + offset);\n  let ranges, p, i;\n  if (format === 4) {\n    getUint16(data, start + offset + 2);\n    const segCount = getUint16(data, start + offset + 6) >> 1;\n    p = start + offset + 14;\n    ranges = [];\n    for (i = 0; i < segCount; i++, p += 2) {\n      ranges[i] = {\n        end: getUint16(data, p)\n      };\n    }\n    p += 2;\n    for (i = 0; i < segCount; i++, p += 2) {\n      ranges[i].start = getUint16(data, p);\n    }\n    for (i = 0; i < segCount; i++, p += 2) {\n      ranges[i].idDelta = getUint16(data, p);\n    }\n    for (i = 0; i < segCount; i++, p += 2) {\n      let idOffset = getUint16(data, p);\n      if (idOffset === 0) {\n        continue;\n      }\n      ranges[i].ids = [];\n      for (let j = 0, jj = ranges[i].end - ranges[i].start + 1; j < jj; j++) {\n        ranges[i].ids[j] = getUint16(data, p + idOffset);\n        idOffset += 2;\n      }\n    }\n    return ranges;\n  } else if (format === 12) {\n    const groups = getUint32(data, start + offset + 12);\n    p = start + offset + 16;\n    ranges = [];\n    for (i = 0; i < groups; i++) {\n      start = getUint32(data, p);\n      ranges.push({\n        start,\n        end: getUint32(data, p + 4),\n        idDelta: getUint32(data, p + 8) - start\n      });\n      p += 12;\n    }\n    return ranges;\n  }\n  throw new FormatError(`unsupported cmap: ${format}`);\n}\nfunction parseCff(data, start, end, seacAnalysisEnabled) {\n  const properties = {};\n  const parser = new CFFParser(new Stream(data, start, end - start), properties, seacAnalysisEnabled);\n  const cff = parser.parse();\n  return {\n    glyphs: cff.charStrings.objects,\n    subrs: cff.topDict.privateDict?.subrsIndex?.objects,\n    gsubrs: cff.globalSubrIndex?.objects,\n    isCFFCIDFont: cff.isCIDFont,\n    fdSelect: cff.fdSelect,\n    fdArray: cff.fdArray\n  };\n}\nfunction parseGlyfTable(glyf, loca, isGlyphLocationsLong) {\n  let itemSize, itemDecode;\n  if (isGlyphLocationsLong) {\n    itemSize = 4;\n    itemDecode = getUint32;\n  } else {\n    itemSize = 2;\n    itemDecode = (data, offset) => 2 * getUint16(data, offset);\n  }\n  const glyphs = [];\n  let startOffset = itemDecode(loca, 0);\n  for (let j = itemSize; j < loca.length; j += itemSize) {\n    const endOffset = itemDecode(loca, j);\n    glyphs.push(glyf.subarray(startOffset, endOffset));\n    startOffset = endOffset;\n  }\n  return glyphs;\n}\nfunction lookupCmap(ranges, unicode) {\n  const code = unicode.codePointAt(0);\n  let gid = 0,\n    l = 0,\n    r = ranges.length - 1;\n  while (l < r) {\n    const c = l + r + 1 >> 1;\n    if (code < ranges[c].start) {\n      r = c - 1;\n    } else {\n      l = c;\n    }\n  }\n  if (ranges[l].start <= code && code <= ranges[l].end) {\n    gid = ranges[l].idDelta + (ranges[l].ids ? ranges[l].ids[code - ranges[l].start] : code) & 0xffff;\n  }\n  return {\n    charCode: code,\n    glyphId: gid\n  };\n}\nfunction compileGlyf(code, cmds, font) {\n  function moveTo(x, y) {\n    cmds.add(FontRenderOps.MOVE_TO, [x, y]);\n  }\n  function lineTo(x, y) {\n    cmds.add(FontRenderOps.LINE_TO, [x, y]);\n  }\n  function quadraticCurveTo(xa, ya, x, y) {\n    cmds.add(FontRenderOps.QUADRATIC_CURVE_TO, [xa, ya, x, y]);\n  }\n  let i = 0;\n  const numberOfContours = getInt16(code, i);\n  let flags;\n  let x = 0,\n    y = 0;\n  i += 10;\n  if (numberOfContours < 0) {\n    do {\n      flags = getUint16(code, i);\n      const glyphIndex = getUint16(code, i + 2);\n      i += 4;\n      let arg1, arg2;\n      if (flags & 0x01) {\n        if (flags & 0x02) {\n          arg1 = getInt16(code, i);\n          arg2 = getInt16(code, i + 2);\n        } else {\n          arg1 = getUint16(code, i);\n          arg2 = getUint16(code, i + 2);\n        }\n        i += 4;\n      } else if (flags & 0x02) {\n        arg1 = getInt8(code, i++);\n        arg2 = getInt8(code, i++);\n      } else {\n        arg1 = code[i++];\n        arg2 = code[i++];\n      }\n      if (flags & 0x02) {\n        x = arg1;\n        y = arg2;\n      } else {\n        x = 0;\n        y = 0;\n      }\n      let scaleX = 1,\n        scaleY = 1,\n        scale01 = 0,\n        scale10 = 0;\n      if (flags & 0x08) {\n        scaleX = scaleY = getFloat214(code, i);\n        i += 2;\n      } else if (flags & 0x40) {\n        scaleX = getFloat214(code, i);\n        scaleY = getFloat214(code, i + 2);\n        i += 4;\n      } else if (flags & 0x80) {\n        scaleX = getFloat214(code, i);\n        scale01 = getFloat214(code, i + 2);\n        scale10 = getFloat214(code, i + 4);\n        scaleY = getFloat214(code, i + 6);\n        i += 8;\n      }\n      const subglyph = font.glyphs[glyphIndex];\n      if (subglyph) {\n        cmds.add(FontRenderOps.SAVE);\n        cmds.add(FontRenderOps.TRANSFORM, [scaleX, scale01, scale10, scaleY, x, y]);\n        if (!(flags & 0x02)) {}\n        compileGlyf(subglyph, cmds, font);\n        cmds.add(FontRenderOps.RESTORE);\n      }\n    } while (flags & 0x20);\n  } else {\n    const endPtsOfContours = [];\n    let j, jj;\n    for (j = 0; j < numberOfContours; j++) {\n      endPtsOfContours.push(getUint16(code, i));\n      i += 2;\n    }\n    const instructionLength = getUint16(code, i);\n    i += 2 + instructionLength;\n    const numberOfPoints = endPtsOfContours.at(-1) + 1;\n    const points = [];\n    while (points.length < numberOfPoints) {\n      flags = code[i++];\n      let repeat = 1;\n      if (flags & 0x08) {\n        repeat += code[i++];\n      }\n      while (repeat-- > 0) {\n        points.push({\n          flags\n        });\n      }\n    }\n    for (j = 0; j < numberOfPoints; j++) {\n      switch (points[j].flags & 0x12) {\n        case 0x00:\n          x += getInt16(code, i);\n          i += 2;\n          break;\n        case 0x02:\n          x -= code[i++];\n          break;\n        case 0x12:\n          x += code[i++];\n          break;\n      }\n      points[j].x = x;\n    }\n    for (j = 0; j < numberOfPoints; j++) {\n      switch (points[j].flags & 0x24) {\n        case 0x00:\n          y += getInt16(code, i);\n          i += 2;\n          break;\n        case 0x04:\n          y -= code[i++];\n          break;\n        case 0x24:\n          y += code[i++];\n          break;\n      }\n      points[j].y = y;\n    }\n    let startPoint = 0;\n    for (i = 0; i < numberOfContours; i++) {\n      const endPoint = endPtsOfContours[i];\n      const contour = points.slice(startPoint, endPoint + 1);\n      if (contour[0].flags & 1) {\n        contour.push(contour[0]);\n      } else if (contour.at(-1).flags & 1) {\n        contour.unshift(contour.at(-1));\n      } else {\n        const p = {\n          flags: 1,\n          x: (contour[0].x + contour.at(-1).x) / 2,\n          y: (contour[0].y + contour.at(-1).y) / 2\n        };\n        contour.unshift(p);\n        contour.push(p);\n      }\n      moveTo(contour[0].x, contour[0].y);\n      for (j = 1, jj = contour.length; j < jj; j++) {\n        if (contour[j].flags & 1) {\n          lineTo(contour[j].x, contour[j].y);\n        } else if (contour[j + 1].flags & 1) {\n          quadraticCurveTo(contour[j].x, contour[j].y, contour[j + 1].x, contour[j + 1].y);\n          j++;\n        } else {\n          quadraticCurveTo(contour[j].x, contour[j].y, (contour[j].x + contour[j + 1].x) / 2, (contour[j].y + contour[j + 1].y) / 2);\n        }\n      }\n      startPoint = endPoint + 1;\n    }\n  }\n}\nfunction compileCharString(charStringCode, cmds, font, glyphId) {\n  function moveTo(x, y) {\n    cmds.add(FontRenderOps.MOVE_TO, [x, y]);\n  }\n  function lineTo(x, y) {\n    cmds.add(FontRenderOps.LINE_TO, [x, y]);\n  }\n  function bezierCurveTo(x1, y1, x2, y2, x, y) {\n    cmds.add(FontRenderOps.BEZIER_CURVE_TO, [x1, y1, x2, y2, x, y]);\n  }\n  const stack = [];\n  let x = 0,\n    y = 0;\n  let stems = 0;\n  function parse(code) {\n    let i = 0;\n    while (i < code.length) {\n      let stackClean = false;\n      let v = code[i++];\n      let xa, xb, ya, yb, y1, y2, y3, n, subrCode;\n      switch (v) {\n        case 1:\n          stems += stack.length >> 1;\n          stackClean = true;\n          break;\n        case 3:\n          stems += stack.length >> 1;\n          stackClean = true;\n          break;\n        case 4:\n          y += stack.pop();\n          moveTo(x, y);\n          stackClean = true;\n          break;\n        case 5:\n          while (stack.length > 0) {\n            x += stack.shift();\n            y += stack.shift();\n            lineTo(x, y);\n          }\n          break;\n        case 6:\n          while (stack.length > 0) {\n            x += stack.shift();\n            lineTo(x, y);\n            if (stack.length === 0) {\n              break;\n            }\n            y += stack.shift();\n            lineTo(x, y);\n          }\n          break;\n        case 7:\n          while (stack.length > 0) {\n            y += stack.shift();\n            lineTo(x, y);\n            if (stack.length === 0) {\n              break;\n            }\n            x += stack.shift();\n            lineTo(x, y);\n          }\n          break;\n        case 8:\n          while (stack.length > 0) {\n            xa = x + stack.shift();\n            ya = y + stack.shift();\n            xb = xa + stack.shift();\n            yb = ya + stack.shift();\n            x = xb + stack.shift();\n            y = yb + stack.shift();\n            bezierCurveTo(xa, ya, xb, yb, x, y);\n          }\n          break;\n        case 10:\n          n = stack.pop();\n          subrCode = null;\n          if (font.isCFFCIDFont) {\n            const fdIndex = font.fdSelect.getFDIndex(glyphId);\n            if (fdIndex >= 0 && fdIndex < font.fdArray.length) {\n              const fontDict = font.fdArray[fdIndex];\n              let subrs;\n              if (fontDict.privateDict?.subrsIndex) {\n                subrs = fontDict.privateDict.subrsIndex.objects;\n              }\n              if (subrs) {\n                n += getSubroutineBias(subrs);\n                subrCode = subrs[n];\n              }\n            } else {\n              warn(\"Invalid fd index for glyph index.\");\n            }\n          } else {\n            subrCode = font.subrs[n + font.subrsBias];\n          }\n          if (subrCode) {\n            parse(subrCode);\n          }\n          break;\n        case 11:\n          return;\n        case 12:\n          v = code[i++];\n          switch (v) {\n            case 34:\n              xa = x + stack.shift();\n              xb = xa + stack.shift();\n              y1 = y + stack.shift();\n              x = xb + stack.shift();\n              bezierCurveTo(xa, y, xb, y1, x, y1);\n              xa = x + stack.shift();\n              xb = xa + stack.shift();\n              x = xb + stack.shift();\n              bezierCurveTo(xa, y1, xb, y, x, y);\n              break;\n            case 35:\n              xa = x + stack.shift();\n              ya = y + stack.shift();\n              xb = xa + stack.shift();\n              yb = ya + stack.shift();\n              x = xb + stack.shift();\n              y = yb + stack.shift();\n              bezierCurveTo(xa, ya, xb, yb, x, y);\n              xa = x + stack.shift();\n              ya = y + stack.shift();\n              xb = xa + stack.shift();\n              yb = ya + stack.shift();\n              x = xb + stack.shift();\n              y = yb + stack.shift();\n              bezierCurveTo(xa, ya, xb, yb, x, y);\n              stack.pop();\n              break;\n            case 36:\n              xa = x + stack.shift();\n              y1 = y + stack.shift();\n              xb = xa + stack.shift();\n              y2 = y1 + stack.shift();\n              x = xb + stack.shift();\n              bezierCurveTo(xa, y1, xb, y2, x, y2);\n              xa = x + stack.shift();\n              xb = xa + stack.shift();\n              y3 = y2 + stack.shift();\n              x = xb + stack.shift();\n              bezierCurveTo(xa, y2, xb, y3, x, y);\n              break;\n            case 37:\n              const x0 = x,\n                y0 = y;\n              xa = x + stack.shift();\n              ya = y + stack.shift();\n              xb = xa + stack.shift();\n              yb = ya + stack.shift();\n              x = xb + stack.shift();\n              y = yb + stack.shift();\n              bezierCurveTo(xa, ya, xb, yb, x, y);\n              xa = x + stack.shift();\n              ya = y + stack.shift();\n              xb = xa + stack.shift();\n              yb = ya + stack.shift();\n              x = xb;\n              y = yb;\n              if (Math.abs(x - x0) > Math.abs(y - y0)) {\n                x += stack.shift();\n              } else {\n                y += stack.shift();\n              }\n              bezierCurveTo(xa, ya, xb, yb, x, y);\n              break;\n            default:\n              throw new FormatError(`unknown operator: 12 ${v}`);\n          }\n          break;\n        case 14:\n          if (stack.length >= 4) {\n            const achar = stack.pop();\n            const bchar = stack.pop();\n            y = stack.pop();\n            x = stack.pop();\n            cmds.add(FontRenderOps.SAVE);\n            cmds.add(FontRenderOps.TRANSLATE, [x, y]);\n            let cmap = lookupCmap(font.cmap, String.fromCharCode(font.glyphNameMap[StandardEncoding[achar]]));\n            compileCharString(font.glyphs[cmap.glyphId], cmds, font, cmap.glyphId);\n            cmds.add(FontRenderOps.RESTORE);\n            cmap = lookupCmap(font.cmap, String.fromCharCode(font.glyphNameMap[StandardEncoding[bchar]]));\n            compileCharString(font.glyphs[cmap.glyphId], cmds, font, cmap.glyphId);\n          }\n          return;\n        case 18:\n          stems += stack.length >> 1;\n          stackClean = true;\n          break;\n        case 19:\n          stems += stack.length >> 1;\n          i += stems + 7 >> 3;\n          stackClean = true;\n          break;\n        case 20:\n          stems += stack.length >> 1;\n          i += stems + 7 >> 3;\n          stackClean = true;\n          break;\n        case 21:\n          y += stack.pop();\n          x += stack.pop();\n          moveTo(x, y);\n          stackClean = true;\n          break;\n        case 22:\n          x += stack.pop();\n          moveTo(x, y);\n          stackClean = true;\n          break;\n        case 23:\n          stems += stack.length >> 1;\n          stackClean = true;\n          break;\n        case 24:\n          while (stack.length > 2) {\n            xa = x + stack.shift();\n            ya = y + stack.shift();\n            xb = xa + stack.shift();\n            yb = ya + stack.shift();\n            x = xb + stack.shift();\n            y = yb + stack.shift();\n            bezierCurveTo(xa, ya, xb, yb, x, y);\n          }\n          x += stack.shift();\n          y += stack.shift();\n          lineTo(x, y);\n          break;\n        case 25:\n          while (stack.length > 6) {\n            x += stack.shift();\n            y += stack.shift();\n            lineTo(x, y);\n          }\n          xa = x + stack.shift();\n          ya = y + stack.shift();\n          xb = xa + stack.shift();\n          yb = ya + stack.shift();\n          x = xb + stack.shift();\n          y = yb + stack.shift();\n          bezierCurveTo(xa, ya, xb, yb, x, y);\n          break;\n        case 26:\n          if (stack.length % 2) {\n            x += stack.shift();\n          }\n          while (stack.length > 0) {\n            xa = x;\n            ya = y + stack.shift();\n            xb = xa + stack.shift();\n            yb = ya + stack.shift();\n            x = xb;\n            y = yb + stack.shift();\n            bezierCurveTo(xa, ya, xb, yb, x, y);\n          }\n          break;\n        case 27:\n          if (stack.length % 2) {\n            y += stack.shift();\n          }\n          while (stack.length > 0) {\n            xa = x + stack.shift();\n            ya = y;\n            xb = xa + stack.shift();\n            yb = ya + stack.shift();\n            x = xb + stack.shift();\n            y = yb;\n            bezierCurveTo(xa, ya, xb, yb, x, y);\n          }\n          break;\n        case 28:\n          stack.push((code[i] << 24 | code[i + 1] << 16) >> 16);\n          i += 2;\n          break;\n        case 29:\n          n = stack.pop() + font.gsubrsBias;\n          subrCode = font.gsubrs[n];\n          if (subrCode) {\n            parse(subrCode);\n          }\n          break;\n        case 30:\n          while (stack.length > 0) {\n            xa = x;\n            ya = y + stack.shift();\n            xb = xa + stack.shift();\n            yb = ya + stack.shift();\n            x = xb + stack.shift();\n            y = yb + (stack.length === 1 ? stack.shift() : 0);\n            bezierCurveTo(xa, ya, xb, yb, x, y);\n            if (stack.length === 0) {\n              break;\n            }\n            xa = x + stack.shift();\n            ya = y;\n            xb = xa + stack.shift();\n            yb = ya + stack.shift();\n            y = yb + stack.shift();\n            x = xb + (stack.length === 1 ? stack.shift() : 0);\n            bezierCurveTo(xa, ya, xb, yb, x, y);\n          }\n          break;\n        case 31:\n          while (stack.length > 0) {\n            xa = x + stack.shift();\n            ya = y;\n            xb = xa + stack.shift();\n            yb = ya + stack.shift();\n            y = yb + stack.shift();\n            x = xb + (stack.length === 1 ? stack.shift() : 0);\n            bezierCurveTo(xa, ya, xb, yb, x, y);\n            if (stack.length === 0) {\n              break;\n            }\n            xa = x;\n            ya = y + stack.shift();\n            xb = xa + stack.shift();\n            yb = ya + stack.shift();\n            x = xb + stack.shift();\n            y = yb + (stack.length === 1 ? stack.shift() : 0);\n            bezierCurveTo(xa, ya, xb, yb, x, y);\n          }\n          break;\n        default:\n          if (v < 32) {\n            throw new FormatError(`unknown operator: ${v}`);\n          }\n          if (v < 247) {\n            stack.push(v - 139);\n          } else if (v < 251) {\n            stack.push((v - 247) * 256 + code[i++] + 108);\n          } else if (v < 255) {\n            stack.push(-(v - 251) * 256 - code[i++] - 108);\n          } else {\n            stack.push((code[i] << 24 | code[i + 1] << 16 | code[i + 2] << 8 | code[i + 3]) / 65536);\n            i += 4;\n          }\n          break;\n      }\n      if (stackClean) {\n        stack.length = 0;\n      }\n    }\n  }\n  parse(charStringCode);\n}\nconst NOOP = [];\nclass Commands {\n  cmds = [];\n  add(cmd, args) {\n    if (args) {\n      if (!isNumberArray(args, null)) {\n        warn(`Commands.add - \"${cmd}\" has at least one non-number arg: \"${args}\".`);\n        const newArgs = args.map(arg => typeof arg === \"number\" ? arg : 0);\n        this.cmds.push(cmd, ...newArgs);\n      } else {\n        this.cmds.push(cmd, ...args);\n      }\n    } else {\n      this.cmds.push(cmd);\n    }\n  }\n}\nclass CompiledFont {\n  constructor(fontMatrix) {\n    if (this.constructor === CompiledFont) {\n      unreachable(\"Cannot initialize CompiledFont.\");\n    }\n    this.fontMatrix = fontMatrix;\n    this.compiledGlyphs = Object.create(null);\n    this.compiledCharCodeToGlyphId = Object.create(null);\n  }\n  getPathJs(unicode) {\n    const {\n      charCode,\n      glyphId\n    } = lookupCmap(this.cmap, unicode);\n    let fn = this.compiledGlyphs[glyphId],\n      compileEx;\n    if (!fn) {\n      try {\n        fn = this.compileGlyph(this.glyphs[glyphId], glyphId);\n      } catch (ex) {\n        fn = NOOP;\n        compileEx = ex;\n      }\n      this.compiledGlyphs[glyphId] = fn;\n    }\n    this.compiledCharCodeToGlyphId[charCode] ??= glyphId;\n    if (compileEx) {\n      throw compileEx;\n    }\n    return fn;\n  }\n  compileGlyph(code, glyphId) {\n    if (!code || code.length === 0 || code[0] === 14) {\n      return NOOP;\n    }\n    let fontMatrix = this.fontMatrix;\n    if (this.isCFFCIDFont) {\n      const fdIndex = this.fdSelect.getFDIndex(glyphId);\n      if (fdIndex >= 0 && fdIndex < this.fdArray.length) {\n        const fontDict = this.fdArray[fdIndex];\n        fontMatrix = fontDict.getByName(\"FontMatrix\") || FONT_IDENTITY_MATRIX;\n      } else {\n        warn(\"Invalid fd index for glyph index.\");\n      }\n    }\n    const cmds = new Commands();\n    cmds.add(FontRenderOps.SAVE);\n    cmds.add(FontRenderOps.TRANSFORM, fontMatrix.slice());\n    cmds.add(FontRenderOps.SCALE);\n    this.compileGlyphImpl(code, cmds, glyphId);\n    cmds.add(FontRenderOps.RESTORE);\n    return cmds.cmds;\n  }\n  compileGlyphImpl() {\n    unreachable(\"Children classes should implement this.\");\n  }\n  hasBuiltPath(unicode) {\n    const {\n      charCode,\n      glyphId\n    } = lookupCmap(this.cmap, unicode);\n    return this.compiledGlyphs[glyphId] !== undefined && this.compiledCharCodeToGlyphId[charCode] !== undefined;\n  }\n}\nclass TrueTypeCompiled extends CompiledFont {\n  constructor(glyphs, cmap, fontMatrix) {\n    super(fontMatrix || [0.000488, 0, 0, 0.000488, 0, 0]);\n    this.glyphs = glyphs;\n    this.cmap = cmap;\n  }\n  compileGlyphImpl(code, cmds) {\n    compileGlyf(code, cmds, this);\n  }\n}\nclass Type2Compiled extends CompiledFont {\n  constructor(cffInfo, cmap, fontMatrix, glyphNameMap) {\n    super(fontMatrix || [0.001, 0, 0, 0.001, 0, 0]);\n    this.glyphs = cffInfo.glyphs;\n    this.gsubrs = cffInfo.gsubrs || [];\n    this.subrs = cffInfo.subrs || [];\n    this.cmap = cmap;\n    this.glyphNameMap = glyphNameMap || getGlyphsUnicode();\n    this.gsubrsBias = getSubroutineBias(this.gsubrs);\n    this.subrsBias = getSubroutineBias(this.subrs);\n    this.isCFFCIDFont = cffInfo.isCFFCIDFont;\n    this.fdSelect = cffInfo.fdSelect;\n    this.fdArray = cffInfo.fdArray;\n  }\n  compileGlyphImpl(code, cmds, glyphId) {\n    compileCharString(code, cmds, this, glyphId);\n  }\n}\nclass FontRendererFactory {\n  static create(font, seacAnalysisEnabled) {\n    const data = new Uint8Array(font.data);\n    let cmap, glyf, loca, cff, indexToLocFormat, unitsPerEm;\n    const numTables = getUint16(data, 4);\n    for (let i = 0, p = 12; i < numTables; i++, p += 16) {\n      const tag = bytesToString(data.subarray(p, p + 4));\n      const offset = getUint32(data, p + 8);\n      const length = getUint32(data, p + 12);\n      switch (tag) {\n        case \"cmap\":\n          cmap = parseCmap(data, offset, offset + length);\n          break;\n        case \"glyf\":\n          glyf = data.subarray(offset, offset + length);\n          break;\n        case \"loca\":\n          loca = data.subarray(offset, offset + length);\n          break;\n        case \"head\":\n          unitsPerEm = getUint16(data, offset + 18);\n          indexToLocFormat = getUint16(data, offset + 50);\n          break;\n        case \"CFF \":\n          cff = parseCff(data, offset, offset + length, seacAnalysisEnabled);\n          break;\n      }\n    }\n    if (glyf) {\n      const fontMatrix = !unitsPerEm ? font.fontMatrix : [1 / unitsPerEm, 0, 0, 1 / unitsPerEm, 0, 0];\n      return new TrueTypeCompiled(parseGlyfTable(glyf, loca, indexToLocFormat), cmap, fontMatrix);\n    }\n    return new Type2Compiled(cff, cmap, font.fontMatrix, font.glyphNameMap);\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/metrics.js\n\nconst getMetrics = getLookupTableFactory(function (t) {\n  t.Courier = 600;\n  t[\"Courier-Bold\"] = 600;\n  t[\"Courier-BoldOblique\"] = 600;\n  t[\"Courier-Oblique\"] = 600;\n  t.Helvetica = getLookupTableFactory(function (t) {\n    t.space = 278;\n    t.exclam = 278;\n    t.quotedbl = 355;\n    t.numbersign = 556;\n    t.dollar = 556;\n    t.percent = 889;\n    t.ampersand = 667;\n    t.quoteright = 222;\n    t.parenleft = 333;\n    t.parenright = 333;\n    t.asterisk = 389;\n    t.plus = 584;\n    t.comma = 278;\n    t.hyphen = 333;\n    t.period = 278;\n    t.slash = 278;\n    t.zero = 556;\n    t.one = 556;\n    t.two = 556;\n    t.three = 556;\n    t.four = 556;\n    t.five = 556;\n    t.six = 556;\n    t.seven = 556;\n    t.eight = 556;\n    t.nine = 556;\n    t.colon = 278;\n    t.semicolon = 278;\n    t.less = 584;\n    t.equal = 584;\n    t.greater = 584;\n    t.question = 556;\n    t.at = 1015;\n    t.A = 667;\n    t.B = 667;\n    t.C = 722;\n    t.D = 722;\n    t.E = 667;\n    t.F = 611;\n    t.G = 778;\n    t.H = 722;\n    t.I = 278;\n    t.J = 500;\n    t.K = 667;\n    t.L = 556;\n    t.M = 833;\n    t.N = 722;\n    t.O = 778;\n    t.P = 667;\n    t.Q = 778;\n    t.R = 722;\n    t.S = 667;\n    t.T = 611;\n    t.U = 722;\n    t.V = 667;\n    t.W = 944;\n    t.X = 667;\n    t.Y = 667;\n    t.Z = 611;\n    t.bracketleft = 278;\n    t.backslash = 278;\n    t.bracketright = 278;\n    t.asciicircum = 469;\n    t.underscore = 556;\n    t.quoteleft = 222;\n    t.a = 556;\n    t.b = 556;\n    t.c = 500;\n    t.d = 556;\n    t.e = 556;\n    t.f = 278;\n    t.g = 556;\n    t.h = 556;\n    t.i = 222;\n    t.j = 222;\n    t.k = 500;\n    t.l = 222;\n    t.m = 833;\n    t.n = 556;\n    t.o = 556;\n    t.p = 556;\n    t.q = 556;\n    t.r = 333;\n    t.s = 500;\n    t.t = 278;\n    t.u = 556;\n    t.v = 500;\n    t.w = 722;\n    t.x = 500;\n    t.y = 500;\n    t.z = 500;\n    t.braceleft = 334;\n    t.bar = 260;\n    t.braceright = 334;\n    t.asciitilde = 584;\n    t.exclamdown = 333;\n    t.cent = 556;\n    t.sterling = 556;\n    t.fraction = 167;\n    t.yen = 556;\n    t.florin = 556;\n    t.section = 556;\n    t.currency = 556;\n    t.quotesingle = 191;\n    t.quotedblleft = 333;\n    t.guillemotleft = 556;\n    t.guilsinglleft = 333;\n    t.guilsinglright = 333;\n    t.fi = 500;\n    t.fl = 500;\n    t.endash = 556;\n    t.dagger = 556;\n    t.daggerdbl = 556;\n    t.periodcentered = 278;\n    t.paragraph = 537;\n    t.bullet = 350;\n    t.quotesinglbase = 222;\n    t.quotedblbase = 333;\n    t.quotedblright = 333;\n    t.guillemotright = 556;\n    t.ellipsis = 1000;\n    t.perthousand = 1000;\n    t.questiondown = 611;\n    t.grave = 333;\n    t.acute = 333;\n    t.circumflex = 333;\n    t.tilde = 333;\n    t.macron = 333;\n    t.breve = 333;\n    t.dotaccent = 333;\n    t.dieresis = 333;\n    t.ring = 333;\n    t.cedilla = 333;\n    t.hungarumlaut = 333;\n    t.ogonek = 333;\n    t.caron = 333;\n    t.emdash = 1000;\n    t.AE = 1000;\n    t.ordfeminine = 370;\n    t.Lslash = 556;\n    t.Oslash = 778;\n    t.OE = 1000;\n    t.ordmasculine = 365;\n    t.ae = 889;\n    t.dotlessi = 278;\n    t.lslash = 222;\n    t.oslash = 611;\n    t.oe = 944;\n    t.germandbls = 611;\n    t.Idieresis = 278;\n    t.eacute = 556;\n    t.abreve = 556;\n    t.uhungarumlaut = 556;\n    t.ecaron = 556;\n    t.Ydieresis = 667;\n    t.divide = 584;\n    t.Yacute = 667;\n    t.Acircumflex = 667;\n    t.aacute = 556;\n    t.Ucircumflex = 722;\n    t.yacute = 500;\n    t.scommaaccent = 500;\n    t.ecircumflex = 556;\n    t.Uring = 722;\n    t.Udieresis = 722;\n    t.aogonek = 556;\n    t.Uacute = 722;\n    t.uogonek = 556;\n    t.Edieresis = 667;\n    t.Dcroat = 722;\n    t.commaaccent = 250;\n    t.copyright = 737;\n    t.Emacron = 667;\n    t.ccaron = 500;\n    t.aring = 556;\n    t.Ncommaaccent = 722;\n    t.lacute = 222;\n    t.agrave = 556;\n    t.Tcommaaccent = 611;\n    t.Cacute = 722;\n    t.atilde = 556;\n    t.Edotaccent = 667;\n    t.scaron = 500;\n    t.scedilla = 500;\n    t.iacute = 278;\n    t.lozenge = 471;\n    t.Rcaron = 722;\n    t.Gcommaaccent = 778;\n    t.ucircumflex = 556;\n    t.acircumflex = 556;\n    t.Amacron = 667;\n    t.rcaron = 333;\n    t.ccedilla = 500;\n    t.Zdotaccent = 611;\n    t.Thorn = 667;\n    t.Omacron = 778;\n    t.Racute = 722;\n    t.Sacute = 667;\n    t.dcaron = 643;\n    t.Umacron = 722;\n    t.uring = 556;\n    t.threesuperior = 333;\n    t.Ograve = 778;\n    t.Agrave = 667;\n    t.Abreve = 667;\n    t.multiply = 584;\n    t.uacute = 556;\n    t.Tcaron = 611;\n    t.partialdiff = 476;\n    t.ydieresis = 500;\n    t.Nacute = 722;\n    t.icircumflex = 278;\n    t.Ecircumflex = 667;\n    t.adieresis = 556;\n    t.edieresis = 556;\n    t.cacute = 500;\n    t.nacute = 556;\n    t.umacron = 556;\n    t.Ncaron = 722;\n    t.Iacute = 278;\n    t.plusminus = 584;\n    t.brokenbar = 260;\n    t.registered = 737;\n    t.Gbreve = 778;\n    t.Idotaccent = 278;\n    t.summation = 600;\n    t.Egrave = 667;\n    t.racute = 333;\n    t.omacron = 556;\n    t.Zacute = 611;\n    t.Zcaron = 611;\n    t.greaterequal = 549;\n    t.Eth = 722;\n    t.Ccedilla = 722;\n    t.lcommaaccent = 222;\n    t.tcaron = 317;\n    t.eogonek = 556;\n    t.Uogonek = 722;\n    t.Aacute = 667;\n    t.Adieresis = 667;\n    t.egrave = 556;\n    t.zacute = 500;\n    t.iogonek = 222;\n    t.Oacute = 778;\n    t.oacute = 556;\n    t.amacron = 556;\n    t.sacute = 500;\n    t.idieresis = 278;\n    t.Ocircumflex = 778;\n    t.Ugrave = 722;\n    t.Delta = 612;\n    t.thorn = 556;\n    t.twosuperior = 333;\n    t.Odieresis = 778;\n    t.mu = 556;\n    t.igrave = 278;\n    t.ohungarumlaut = 556;\n    t.Eogonek = 667;\n    t.dcroat = 556;\n    t.threequarters = 834;\n    t.Scedilla = 667;\n    t.lcaron = 299;\n    t.Kcommaaccent = 667;\n    t.Lacute = 556;\n    t.trademark = 1000;\n    t.edotaccent = 556;\n    t.Igrave = 278;\n    t.Imacron = 278;\n    t.Lcaron = 556;\n    t.onehalf = 834;\n    t.lessequal = 549;\n    t.ocircumflex = 556;\n    t.ntilde = 556;\n    t.Uhungarumlaut = 722;\n    t.Eacute = 667;\n    t.emacron = 556;\n    t.gbreve = 556;\n    t.onequarter = 834;\n    t.Scaron = 667;\n    t.Scommaaccent = 667;\n    t.Ohungarumlaut = 778;\n    t.degree = 400;\n    t.ograve = 556;\n    t.Ccaron = 722;\n    t.ugrave = 556;\n    t.radical = 453;\n    t.Dcaron = 722;\n    t.rcommaaccent = 333;\n    t.Ntilde = 722;\n    t.otilde = 556;\n    t.Rcommaaccent = 722;\n    t.Lcommaaccent = 556;\n    t.Atilde = 667;\n    t.Aogonek = 667;\n    t.Aring = 667;\n    t.Otilde = 778;\n    t.zdotaccent = 500;\n    t.Ecaron = 667;\n    t.Iogonek = 278;\n    t.kcommaaccent = 500;\n    t.minus = 584;\n    t.Icircumflex = 278;\n    t.ncaron = 556;\n    t.tcommaaccent = 278;\n    t.logicalnot = 584;\n    t.odieresis = 556;\n    t.udieresis = 556;\n    t.notequal = 549;\n    t.gcommaaccent = 556;\n    t.eth = 556;\n    t.zcaron = 500;\n    t.ncommaaccent = 556;\n    t.onesuperior = 333;\n    t.imacron = 278;\n    t.Euro = 556;\n  });\n  t[\"Helvetica-Bold\"] = getLookupTableFactory(function (t) {\n    t.space = 278;\n    t.exclam = 333;\n    t.quotedbl = 474;\n    t.numbersign = 556;\n    t.dollar = 556;\n    t.percent = 889;\n    t.ampersand = 722;\n    t.quoteright = 278;\n    t.parenleft = 333;\n    t.parenright = 333;\n    t.asterisk = 389;\n    t.plus = 584;\n    t.comma = 278;\n    t.hyphen = 333;\n    t.period = 278;\n    t.slash = 278;\n    t.zero = 556;\n    t.one = 556;\n    t.two = 556;\n    t.three = 556;\n    t.four = 556;\n    t.five = 556;\n    t.six = 556;\n    t.seven = 556;\n    t.eight = 556;\n    t.nine = 556;\n    t.colon = 333;\n    t.semicolon = 333;\n    t.less = 584;\n    t.equal = 584;\n    t.greater = 584;\n    t.question = 611;\n    t.at = 975;\n    t.A = 722;\n    t.B = 722;\n    t.C = 722;\n    t.D = 722;\n    t.E = 667;\n    t.F = 611;\n    t.G = 778;\n    t.H = 722;\n    t.I = 278;\n    t.J = 556;\n    t.K = 722;\n    t.L = 611;\n    t.M = 833;\n    t.N = 722;\n    t.O = 778;\n    t.P = 667;\n    t.Q = 778;\n    t.R = 722;\n    t.S = 667;\n    t.T = 611;\n    t.U = 722;\n    t.V = 667;\n    t.W = 944;\n    t.X = 667;\n    t.Y = 667;\n    t.Z = 611;\n    t.bracketleft = 333;\n    t.backslash = 278;\n    t.bracketright = 333;\n    t.asciicircum = 584;\n    t.underscore = 556;\n    t.quoteleft = 278;\n    t.a = 556;\n    t.b = 611;\n    t.c = 556;\n    t.d = 611;\n    t.e = 556;\n    t.f = 333;\n    t.g = 611;\n    t.h = 611;\n    t.i = 278;\n    t.j = 278;\n    t.k = 556;\n    t.l = 278;\n    t.m = 889;\n    t.n = 611;\n    t.o = 611;\n    t.p = 611;\n    t.q = 611;\n    t.r = 389;\n    t.s = 556;\n    t.t = 333;\n    t.u = 611;\n    t.v = 556;\n    t.w = 778;\n    t.x = 556;\n    t.y = 556;\n    t.z = 500;\n    t.braceleft = 389;\n    t.bar = 280;\n    t.braceright = 389;\n    t.asciitilde = 584;\n    t.exclamdown = 333;\n    t.cent = 556;\n    t.sterling = 556;\n    t.fraction = 167;\n    t.yen = 556;\n    t.florin = 556;\n    t.section = 556;\n    t.currency = 556;\n    t.quotesingle = 238;\n    t.quotedblleft = 500;\n    t.guillemotleft = 556;\n    t.guilsinglleft = 333;\n    t.guilsinglright = 333;\n    t.fi = 611;\n    t.fl = 611;\n    t.endash = 556;\n    t.dagger = 556;\n    t.daggerdbl = 556;\n    t.periodcentered = 278;\n    t.paragraph = 556;\n    t.bullet = 350;\n    t.quotesinglbase = 278;\n    t.quotedblbase = 500;\n    t.quotedblright = 500;\n    t.guillemotright = 556;\n    t.ellipsis = 1000;\n    t.perthousand = 1000;\n    t.questiondown = 611;\n    t.grave = 333;\n    t.acute = 333;\n    t.circumflex = 333;\n    t.tilde = 333;\n    t.macron = 333;\n    t.breve = 333;\n    t.dotaccent = 333;\n    t.dieresis = 333;\n    t.ring = 333;\n    t.cedilla = 333;\n    t.hungarumlaut = 333;\n    t.ogonek = 333;\n    t.caron = 333;\n    t.emdash = 1000;\n    t.AE = 1000;\n    t.ordfeminine = 370;\n    t.Lslash = 611;\n    t.Oslash = 778;\n    t.OE = 1000;\n    t.ordmasculine = 365;\n    t.ae = 889;\n    t.dotlessi = 278;\n    t.lslash = 278;\n    t.oslash = 611;\n    t.oe = 944;\n    t.germandbls = 611;\n    t.Idieresis = 278;\n    t.eacute = 556;\n    t.abreve = 556;\n    t.uhungarumlaut = 611;\n    t.ecaron = 556;\n    t.Ydieresis = 667;\n    t.divide = 584;\n    t.Yacute = 667;\n    t.Acircumflex = 722;\n    t.aacute = 556;\n    t.Ucircumflex = 722;\n    t.yacute = 556;\n    t.scommaaccent = 556;\n    t.ecircumflex = 556;\n    t.Uring = 722;\n    t.Udieresis = 722;\n    t.aogonek = 556;\n    t.Uacute = 722;\n    t.uogonek = 611;\n    t.Edieresis = 667;\n    t.Dcroat = 722;\n    t.commaaccent = 250;\n    t.copyright = 737;\n    t.Emacron = 667;\n    t.ccaron = 556;\n    t.aring = 556;\n    t.Ncommaaccent = 722;\n    t.lacute = 278;\n    t.agrave = 556;\n    t.Tcommaaccent = 611;\n    t.Cacute = 722;\n    t.atilde = 556;\n    t.Edotaccent = 667;\n    t.scaron = 556;\n    t.scedilla = 556;\n    t.iacute = 278;\n    t.lozenge = 494;\n    t.Rcaron = 722;\n    t.Gcommaaccent = 778;\n    t.ucircumflex = 611;\n    t.acircumflex = 556;\n    t.Amacron = 722;\n    t.rcaron = 389;\n    t.ccedilla = 556;\n    t.Zdotaccent = 611;\n    t.Thorn = 667;\n    t.Omacron = 778;\n    t.Racute = 722;\n    t.Sacute = 667;\n    t.dcaron = 743;\n    t.Umacron = 722;\n    t.uring = 611;\n    t.threesuperior = 333;\n    t.Ograve = 778;\n    t.Agrave = 722;\n    t.Abreve = 722;\n    t.multiply = 584;\n    t.uacute = 611;\n    t.Tcaron = 611;\n    t.partialdiff = 494;\n    t.ydieresis = 556;\n    t.Nacute = 722;\n    t.icircumflex = 278;\n    t.Ecircumflex = 667;\n    t.adieresis = 556;\n    t.edieresis = 556;\n    t.cacute = 556;\n    t.nacute = 611;\n    t.umacron = 611;\n    t.Ncaron = 722;\n    t.Iacute = 278;\n    t.plusminus = 584;\n    t.brokenbar = 280;\n    t.registered = 737;\n    t.Gbreve = 778;\n    t.Idotaccent = 278;\n    t.summation = 600;\n    t.Egrave = 667;\n    t.racute = 389;\n    t.omacron = 611;\n    t.Zacute = 611;\n    t.Zcaron = 611;\n    t.greaterequal = 549;\n    t.Eth = 722;\n    t.Ccedilla = 722;\n    t.lcommaaccent = 278;\n    t.tcaron = 389;\n    t.eogonek = 556;\n    t.Uogonek = 722;\n    t.Aacute = 722;\n    t.Adieresis = 722;\n    t.egrave = 556;\n    t.zacute = 500;\n    t.iogonek = 278;\n    t.Oacute = 778;\n    t.oacute = 611;\n    t.amacron = 556;\n    t.sacute = 556;\n    t.idieresis = 278;\n    t.Ocircumflex = 778;\n    t.Ugrave = 722;\n    t.Delta = 612;\n    t.thorn = 611;\n    t.twosuperior = 333;\n    t.Odieresis = 778;\n    t.mu = 611;\n    t.igrave = 278;\n    t.ohungarumlaut = 611;\n    t.Eogonek = 667;\n    t.dcroat = 611;\n    t.threequarters = 834;\n    t.Scedilla = 667;\n    t.lcaron = 400;\n    t.Kcommaaccent = 722;\n    t.Lacute = 611;\n    t.trademark = 1000;\n    t.edotaccent = 556;\n    t.Igrave = 278;\n    t.Imacron = 278;\n    t.Lcaron = 611;\n    t.onehalf = 834;\n    t.lessequal = 549;\n    t.ocircumflex = 611;\n    t.ntilde = 611;\n    t.Uhungarumlaut = 722;\n    t.Eacute = 667;\n    t.emacron = 556;\n    t.gbreve = 611;\n    t.onequarter = 834;\n    t.Scaron = 667;\n    t.Scommaaccent = 667;\n    t.Ohungarumlaut = 778;\n    t.degree = 400;\n    t.ograve = 611;\n    t.Ccaron = 722;\n    t.ugrave = 611;\n    t.radical = 549;\n    t.Dcaron = 722;\n    t.rcommaaccent = 389;\n    t.Ntilde = 722;\n    t.otilde = 611;\n    t.Rcommaaccent = 722;\n    t.Lcommaaccent = 611;\n    t.Atilde = 722;\n    t.Aogonek = 722;\n    t.Aring = 722;\n    t.Otilde = 778;\n    t.zdotaccent = 500;\n    t.Ecaron = 667;\n    t.Iogonek = 278;\n    t.kcommaaccent = 556;\n    t.minus = 584;\n    t.Icircumflex = 278;\n    t.ncaron = 611;\n    t.tcommaaccent = 333;\n    t.logicalnot = 584;\n    t.odieresis = 611;\n    t.udieresis = 611;\n    t.notequal = 549;\n    t.gcommaaccent = 611;\n    t.eth = 611;\n    t.zcaron = 500;\n    t.ncommaaccent = 611;\n    t.onesuperior = 333;\n    t.imacron = 278;\n    t.Euro = 556;\n  });\n  t[\"Helvetica-BoldOblique\"] = getLookupTableFactory(function (t) {\n    t.space = 278;\n    t.exclam = 333;\n    t.quotedbl = 474;\n    t.numbersign = 556;\n    t.dollar = 556;\n    t.percent = 889;\n    t.ampersand = 722;\n    t.quoteright = 278;\n    t.parenleft = 333;\n    t.parenright = 333;\n    t.asterisk = 389;\n    t.plus = 584;\n    t.comma = 278;\n    t.hyphen = 333;\n    t.period = 278;\n    t.slash = 278;\n    t.zero = 556;\n    t.one = 556;\n    t.two = 556;\n    t.three = 556;\n    t.four = 556;\n    t.five = 556;\n    t.six = 556;\n    t.seven = 556;\n    t.eight = 556;\n    t.nine = 556;\n    t.colon = 333;\n    t.semicolon = 333;\n    t.less = 584;\n    t.equal = 584;\n    t.greater = 584;\n    t.question = 611;\n    t.at = 975;\n    t.A = 722;\n    t.B = 722;\n    t.C = 722;\n    t.D = 722;\n    t.E = 667;\n    t.F = 611;\n    t.G = 778;\n    t.H = 722;\n    t.I = 278;\n    t.J = 556;\n    t.K = 722;\n    t.L = 611;\n    t.M = 833;\n    t.N = 722;\n    t.O = 778;\n    t.P = 667;\n    t.Q = 778;\n    t.R = 722;\n    t.S = 667;\n    t.T = 611;\n    t.U = 722;\n    t.V = 667;\n    t.W = 944;\n    t.X = 667;\n    t.Y = 667;\n    t.Z = 611;\n    t.bracketleft = 333;\n    t.backslash = 278;\n    t.bracketright = 333;\n    t.asciicircum = 584;\n    t.underscore = 556;\n    t.quoteleft = 278;\n    t.a = 556;\n    t.b = 611;\n    t.c = 556;\n    t.d = 611;\n    t.e = 556;\n    t.f = 333;\n    t.g = 611;\n    t.h = 611;\n    t.i = 278;\n    t.j = 278;\n    t.k = 556;\n    t.l = 278;\n    t.m = 889;\n    t.n = 611;\n    t.o = 611;\n    t.p = 611;\n    t.q = 611;\n    t.r = 389;\n    t.s = 556;\n    t.t = 333;\n    t.u = 611;\n    t.v = 556;\n    t.w = 778;\n    t.x = 556;\n    t.y = 556;\n    t.z = 500;\n    t.braceleft = 389;\n    t.bar = 280;\n    t.braceright = 389;\n    t.asciitilde = 584;\n    t.exclamdown = 333;\n    t.cent = 556;\n    t.sterling = 556;\n    t.fraction = 167;\n    t.yen = 556;\n    t.florin = 556;\n    t.section = 556;\n    t.currency = 556;\n    t.quotesingle = 238;\n    t.quotedblleft = 500;\n    t.guillemotleft = 556;\n    t.guilsinglleft = 333;\n    t.guilsinglright = 333;\n    t.fi = 611;\n    t.fl = 611;\n    t.endash = 556;\n    t.dagger = 556;\n    t.daggerdbl = 556;\n    t.periodcentered = 278;\n    t.paragraph = 556;\n    t.bullet = 350;\n    t.quotesinglbase = 278;\n    t.quotedblbase = 500;\n    t.quotedblright = 500;\n    t.guillemotright = 556;\n    t.ellipsis = 1000;\n    t.perthousand = 1000;\n    t.questiondown = 611;\n    t.grave = 333;\n    t.acute = 333;\n    t.circumflex = 333;\n    t.tilde = 333;\n    t.macron = 333;\n    t.breve = 333;\n    t.dotaccent = 333;\n    t.dieresis = 333;\n    t.ring = 333;\n    t.cedilla = 333;\n    t.hungarumlaut = 333;\n    t.ogonek = 333;\n    t.caron = 333;\n    t.emdash = 1000;\n    t.AE = 1000;\n    t.ordfeminine = 370;\n    t.Lslash = 611;\n    t.Oslash = 778;\n    t.OE = 1000;\n    t.ordmasculine = 365;\n    t.ae = 889;\n    t.dotlessi = 278;\n    t.lslash = 278;\n    t.oslash = 611;\n    t.oe = 944;\n    t.germandbls = 611;\n    t.Idieresis = 278;\n    t.eacute = 556;\n    t.abreve = 556;\n    t.uhungarumlaut = 611;\n    t.ecaron = 556;\n    t.Ydieresis = 667;\n    t.divide = 584;\n    t.Yacute = 667;\n    t.Acircumflex = 722;\n    t.aacute = 556;\n    t.Ucircumflex = 722;\n    t.yacute = 556;\n    t.scommaaccent = 556;\n    t.ecircumflex = 556;\n    t.Uring = 722;\n    t.Udieresis = 722;\n    t.aogonek = 556;\n    t.Uacute = 722;\n    t.uogonek = 611;\n    t.Edieresis = 667;\n    t.Dcroat = 722;\n    t.commaaccent = 250;\n    t.copyright = 737;\n    t.Emacron = 667;\n    t.ccaron = 556;\n    t.aring = 556;\n    t.Ncommaaccent = 722;\n    t.lacute = 278;\n    t.agrave = 556;\n    t.Tcommaaccent = 611;\n    t.Cacute = 722;\n    t.atilde = 556;\n    t.Edotaccent = 667;\n    t.scaron = 556;\n    t.scedilla = 556;\n    t.iacute = 278;\n    t.lozenge = 494;\n    t.Rcaron = 722;\n    t.Gcommaaccent = 778;\n    t.ucircumflex = 611;\n    t.acircumflex = 556;\n    t.Amacron = 722;\n    t.rcaron = 389;\n    t.ccedilla = 556;\n    t.Zdotaccent = 611;\n    t.Thorn = 667;\n    t.Omacron = 778;\n    t.Racute = 722;\n    t.Sacute = 667;\n    t.dcaron = 743;\n    t.Umacron = 722;\n    t.uring = 611;\n    t.threesuperior = 333;\n    t.Ograve = 778;\n    t.Agrave = 722;\n    t.Abreve = 722;\n    t.multiply = 584;\n    t.uacute = 611;\n    t.Tcaron = 611;\n    t.partialdiff = 494;\n    t.ydieresis = 556;\n    t.Nacute = 722;\n    t.icircumflex = 278;\n    t.Ecircumflex = 667;\n    t.adieresis = 556;\n    t.edieresis = 556;\n    t.cacute = 556;\n    t.nacute = 611;\n    t.umacron = 611;\n    t.Ncaron = 722;\n    t.Iacute = 278;\n    t.plusminus = 584;\n    t.brokenbar = 280;\n    t.registered = 737;\n    t.Gbreve = 778;\n    t.Idotaccent = 278;\n    t.summation = 600;\n    t.Egrave = 667;\n    t.racute = 389;\n    t.omacron = 611;\n    t.Zacute = 611;\n    t.Zcaron = 611;\n    t.greaterequal = 549;\n    t.Eth = 722;\n    t.Ccedilla = 722;\n    t.lcommaaccent = 278;\n    t.tcaron = 389;\n    t.eogonek = 556;\n    t.Uogonek = 722;\n    t.Aacute = 722;\n    t.Adieresis = 722;\n    t.egrave = 556;\n    t.zacute = 500;\n    t.iogonek = 278;\n    t.Oacute = 778;\n    t.oacute = 611;\n    t.amacron = 556;\n    t.sacute = 556;\n    t.idieresis = 278;\n    t.Ocircumflex = 778;\n    t.Ugrave = 722;\n    t.Delta = 612;\n    t.thorn = 611;\n    t.twosuperior = 333;\n    t.Odieresis = 778;\n    t.mu = 611;\n    t.igrave = 278;\n    t.ohungarumlaut = 611;\n    t.Eogonek = 667;\n    t.dcroat = 611;\n    t.threequarters = 834;\n    t.Scedilla = 667;\n    t.lcaron = 400;\n    t.Kcommaaccent = 722;\n    t.Lacute = 611;\n    t.trademark = 1000;\n    t.edotaccent = 556;\n    t.Igrave = 278;\n    t.Imacron = 278;\n    t.Lcaron = 611;\n    t.onehalf = 834;\n    t.lessequal = 549;\n    t.ocircumflex = 611;\n    t.ntilde = 611;\n    t.Uhungarumlaut = 722;\n    t.Eacute = 667;\n    t.emacron = 556;\n    t.gbreve = 611;\n    t.onequarter = 834;\n    t.Scaron = 667;\n    t.Scommaaccent = 667;\n    t.Ohungarumlaut = 778;\n    t.degree = 400;\n    t.ograve = 611;\n    t.Ccaron = 722;\n    t.ugrave = 611;\n    t.radical = 549;\n    t.Dcaron = 722;\n    t.rcommaaccent = 389;\n    t.Ntilde = 722;\n    t.otilde = 611;\n    t.Rcommaaccent = 722;\n    t.Lcommaaccent = 611;\n    t.Atilde = 722;\n    t.Aogonek = 722;\n    t.Aring = 722;\n    t.Otilde = 778;\n    t.zdotaccent = 500;\n    t.Ecaron = 667;\n    t.Iogonek = 278;\n    t.kcommaaccent = 556;\n    t.minus = 584;\n    t.Icircumflex = 278;\n    t.ncaron = 611;\n    t.tcommaaccent = 333;\n    t.logicalnot = 584;\n    t.odieresis = 611;\n    t.udieresis = 611;\n    t.notequal = 549;\n    t.gcommaaccent = 611;\n    t.eth = 611;\n    t.zcaron = 500;\n    t.ncommaaccent = 611;\n    t.onesuperior = 333;\n    t.imacron = 278;\n    t.Euro = 556;\n  });\n  t[\"Helvetica-Oblique\"] = getLookupTableFactory(function (t) {\n    t.space = 278;\n    t.exclam = 278;\n    t.quotedbl = 355;\n    t.numbersign = 556;\n    t.dollar = 556;\n    t.percent = 889;\n    t.ampersand = 667;\n    t.quoteright = 222;\n    t.parenleft = 333;\n    t.parenright = 333;\n    t.asterisk = 389;\n    t.plus = 584;\n    t.comma = 278;\n    t.hyphen = 333;\n    t.period = 278;\n    t.slash = 278;\n    t.zero = 556;\n    t.one = 556;\n    t.two = 556;\n    t.three = 556;\n    t.four = 556;\n    t.five = 556;\n    t.six = 556;\n    t.seven = 556;\n    t.eight = 556;\n    t.nine = 556;\n    t.colon = 278;\n    t.semicolon = 278;\n    t.less = 584;\n    t.equal = 584;\n    t.greater = 584;\n    t.question = 556;\n    t.at = 1015;\n    t.A = 667;\n    t.B = 667;\n    t.C = 722;\n    t.D = 722;\n    t.E = 667;\n    t.F = 611;\n    t.G = 778;\n    t.H = 722;\n    t.I = 278;\n    t.J = 500;\n    t.K = 667;\n    t.L = 556;\n    t.M = 833;\n    t.N = 722;\n    t.O = 778;\n    t.P = 667;\n    t.Q = 778;\n    t.R = 722;\n    t.S = 667;\n    t.T = 611;\n    t.U = 722;\n    t.V = 667;\n    t.W = 944;\n    t.X = 667;\n    t.Y = 667;\n    t.Z = 611;\n    t.bracketleft = 278;\n    t.backslash = 278;\n    t.bracketright = 278;\n    t.asciicircum = 469;\n    t.underscore = 556;\n    t.quoteleft = 222;\n    t.a = 556;\n    t.b = 556;\n    t.c = 500;\n    t.d = 556;\n    t.e = 556;\n    t.f = 278;\n    t.g = 556;\n    t.h = 556;\n    t.i = 222;\n    t.j = 222;\n    t.k = 500;\n    t.l = 222;\n    t.m = 833;\n    t.n = 556;\n    t.o = 556;\n    t.p = 556;\n    t.q = 556;\n    t.r = 333;\n    t.s = 500;\n    t.t = 278;\n    t.u = 556;\n    t.v = 500;\n    t.w = 722;\n    t.x = 500;\n    t.y = 500;\n    t.z = 500;\n    t.braceleft = 334;\n    t.bar = 260;\n    t.braceright = 334;\n    t.asciitilde = 584;\n    t.exclamdown = 333;\n    t.cent = 556;\n    t.sterling = 556;\n    t.fraction = 167;\n    t.yen = 556;\n    t.florin = 556;\n    t.section = 556;\n    t.currency = 556;\n    t.quotesingle = 191;\n    t.quotedblleft = 333;\n    t.guillemotleft = 556;\n    t.guilsinglleft = 333;\n    t.guilsinglright = 333;\n    t.fi = 500;\n    t.fl = 500;\n    t.endash = 556;\n    t.dagger = 556;\n    t.daggerdbl = 556;\n    t.periodcentered = 278;\n    t.paragraph = 537;\n    t.bullet = 350;\n    t.quotesinglbase = 222;\n    t.quotedblbase = 333;\n    t.quotedblright = 333;\n    t.guillemotright = 556;\n    t.ellipsis = 1000;\n    t.perthousand = 1000;\n    t.questiondown = 611;\n    t.grave = 333;\n    t.acute = 333;\n    t.circumflex = 333;\n    t.tilde = 333;\n    t.macron = 333;\n    t.breve = 333;\n    t.dotaccent = 333;\n    t.dieresis = 333;\n    t.ring = 333;\n    t.cedilla = 333;\n    t.hungarumlaut = 333;\n    t.ogonek = 333;\n    t.caron = 333;\n    t.emdash = 1000;\n    t.AE = 1000;\n    t.ordfeminine = 370;\n    t.Lslash = 556;\n    t.Oslash = 778;\n    t.OE = 1000;\n    t.ordmasculine = 365;\n    t.ae = 889;\n    t.dotlessi = 278;\n    t.lslash = 222;\n    t.oslash = 611;\n    t.oe = 944;\n    t.germandbls = 611;\n    t.Idieresis = 278;\n    t.eacute = 556;\n    t.abreve = 556;\n    t.uhungarumlaut = 556;\n    t.ecaron = 556;\n    t.Ydieresis = 667;\n    t.divide = 584;\n    t.Yacute = 667;\n    t.Acircumflex = 667;\n    t.aacute = 556;\n    t.Ucircumflex = 722;\n    t.yacute = 500;\n    t.scommaaccent = 500;\n    t.ecircumflex = 556;\n    t.Uring = 722;\n    t.Udieresis = 722;\n    t.aogonek = 556;\n    t.Uacute = 722;\n    t.uogonek = 556;\n    t.Edieresis = 667;\n    t.Dcroat = 722;\n    t.commaaccent = 250;\n    t.copyright = 737;\n    t.Emacron = 667;\n    t.ccaron = 500;\n    t.aring = 556;\n    t.Ncommaaccent = 722;\n    t.lacute = 222;\n    t.agrave = 556;\n    t.Tcommaaccent = 611;\n    t.Cacute = 722;\n    t.atilde = 556;\n    t.Edotaccent = 667;\n    t.scaron = 500;\n    t.scedilla = 500;\n    t.iacute = 278;\n    t.lozenge = 471;\n    t.Rcaron = 722;\n    t.Gcommaaccent = 778;\n    t.ucircumflex = 556;\n    t.acircumflex = 556;\n    t.Amacron = 667;\n    t.rcaron = 333;\n    t.ccedilla = 500;\n    t.Zdotaccent = 611;\n    t.Thorn = 667;\n    t.Omacron = 778;\n    t.Racute = 722;\n    t.Sacute = 667;\n    t.dcaron = 643;\n    t.Umacron = 722;\n    t.uring = 556;\n    t.threesuperior = 333;\n    t.Ograve = 778;\n    t.Agrave = 667;\n    t.Abreve = 667;\n    t.multiply = 584;\n    t.uacute = 556;\n    t.Tcaron = 611;\n    t.partialdiff = 476;\n    t.ydieresis = 500;\n    t.Nacute = 722;\n    t.icircumflex = 278;\n    t.Ecircumflex = 667;\n    t.adieresis = 556;\n    t.edieresis = 556;\n    t.cacute = 500;\n    t.nacute = 556;\n    t.umacron = 556;\n    t.Ncaron = 722;\n    t.Iacute = 278;\n    t.plusminus = 584;\n    t.brokenbar = 260;\n    t.registered = 737;\n    t.Gbreve = 778;\n    t.Idotaccent = 278;\n    t.summation = 600;\n    t.Egrave = 667;\n    t.racute = 333;\n    t.omacron = 556;\n    t.Zacute = 611;\n    t.Zcaron = 611;\n    t.greaterequal = 549;\n    t.Eth = 722;\n    t.Ccedilla = 722;\n    t.lcommaaccent = 222;\n    t.tcaron = 317;\n    t.eogonek = 556;\n    t.Uogonek = 722;\n    t.Aacute = 667;\n    t.Adieresis = 667;\n    t.egrave = 556;\n    t.zacute = 500;\n    t.iogonek = 222;\n    t.Oacute = 778;\n    t.oacute = 556;\n    t.amacron = 556;\n    t.sacute = 500;\n    t.idieresis = 278;\n    t.Ocircumflex = 778;\n    t.Ugrave = 722;\n    t.Delta = 612;\n    t.thorn = 556;\n    t.twosuperior = 333;\n    t.Odieresis = 778;\n    t.mu = 556;\n    t.igrave = 278;\n    t.ohungarumlaut = 556;\n    t.Eogonek = 667;\n    t.dcroat = 556;\n    t.threequarters = 834;\n    t.Scedilla = 667;\n    t.lcaron = 299;\n    t.Kcommaaccent = 667;\n    t.Lacute = 556;\n    t.trademark = 1000;\n    t.edotaccent = 556;\n    t.Igrave = 278;\n    t.Imacron = 278;\n    t.Lcaron = 556;\n    t.onehalf = 834;\n    t.lessequal = 549;\n    t.ocircumflex = 556;\n    t.ntilde = 556;\n    t.Uhungarumlaut = 722;\n    t.Eacute = 667;\n    t.emacron = 556;\n    t.gbreve = 556;\n    t.onequarter = 834;\n    t.Scaron = 667;\n    t.Scommaaccent = 667;\n    t.Ohungarumlaut = 778;\n    t.degree = 400;\n    t.ograve = 556;\n    t.Ccaron = 722;\n    t.ugrave = 556;\n    t.radical = 453;\n    t.Dcaron = 722;\n    t.rcommaaccent = 333;\n    t.Ntilde = 722;\n    t.otilde = 556;\n    t.Rcommaaccent = 722;\n    t.Lcommaaccent = 556;\n    t.Atilde = 667;\n    t.Aogonek = 667;\n    t.Aring = 667;\n    t.Otilde = 778;\n    t.zdotaccent = 500;\n    t.Ecaron = 667;\n    t.Iogonek = 278;\n    t.kcommaaccent = 500;\n    t.minus = 584;\n    t.Icircumflex = 278;\n    t.ncaron = 556;\n    t.tcommaaccent = 278;\n    t.logicalnot = 584;\n    t.odieresis = 556;\n    t.udieresis = 556;\n    t.notequal = 549;\n    t.gcommaaccent = 556;\n    t.eth = 556;\n    t.zcaron = 500;\n    t.ncommaaccent = 556;\n    t.onesuperior = 333;\n    t.imacron = 278;\n    t.Euro = 556;\n  });\n  t.Symbol = getLookupTableFactory(function (t) {\n    t.space = 250;\n    t.exclam = 333;\n    t.universal = 713;\n    t.numbersign = 500;\n    t.existential = 549;\n    t.percent = 833;\n    t.ampersand = 778;\n    t.suchthat = 439;\n    t.parenleft = 333;\n    t.parenright = 333;\n    t.asteriskmath = 500;\n    t.plus = 549;\n    t.comma = 250;\n    t.minus = 549;\n    t.period = 250;\n    t.slash = 278;\n    t.zero = 500;\n    t.one = 500;\n    t.two = 500;\n    t.three = 500;\n    t.four = 500;\n    t.five = 500;\n    t.six = 500;\n    t.seven = 500;\n    t.eight = 500;\n    t.nine = 500;\n    t.colon = 278;\n    t.semicolon = 278;\n    t.less = 549;\n    t.equal = 549;\n    t.greater = 549;\n    t.question = 444;\n    t.congruent = 549;\n    t.Alpha = 722;\n    t.Beta = 667;\n    t.Chi = 722;\n    t.Delta = 612;\n    t.Epsilon = 611;\n    t.Phi = 763;\n    t.Gamma = 603;\n    t.Eta = 722;\n    t.Iota = 333;\n    t.theta1 = 631;\n    t.Kappa = 722;\n    t.Lambda = 686;\n    t.Mu = 889;\n    t.Nu = 722;\n    t.Omicron = 722;\n    t.Pi = 768;\n    t.Theta = 741;\n    t.Rho = 556;\n    t.Sigma = 592;\n    t.Tau = 611;\n    t.Upsilon = 690;\n    t.sigma1 = 439;\n    t.Omega = 768;\n    t.Xi = 645;\n    t.Psi = 795;\n    t.Zeta = 611;\n    t.bracketleft = 333;\n    t.therefore = 863;\n    t.bracketright = 333;\n    t.perpendicular = 658;\n    t.underscore = 500;\n    t.radicalex = 500;\n    t.alpha = 631;\n    t.beta = 549;\n    t.chi = 549;\n    t.delta = 494;\n    t.epsilon = 439;\n    t.phi = 521;\n    t.gamma = 411;\n    t.eta = 603;\n    t.iota = 329;\n    t.phi1 = 603;\n    t.kappa = 549;\n    t.lambda = 549;\n    t.mu = 576;\n    t.nu = 521;\n    t.omicron = 549;\n    t.pi = 549;\n    t.theta = 521;\n    t.rho = 549;\n    t.sigma = 603;\n    t.tau = 439;\n    t.upsilon = 576;\n    t.omega1 = 713;\n    t.omega = 686;\n    t.xi = 493;\n    t.psi = 686;\n    t.zeta = 494;\n    t.braceleft = 480;\n    t.bar = 200;\n    t.braceright = 480;\n    t.similar = 549;\n    t.Euro = 750;\n    t.Upsilon1 = 620;\n    t.minute = 247;\n    t.lessequal = 549;\n    t.fraction = 167;\n    t.infinity = 713;\n    t.florin = 500;\n    t.club = 753;\n    t.diamond = 753;\n    t.heart = 753;\n    t.spade = 753;\n    t.arrowboth = 1042;\n    t.arrowleft = 987;\n    t.arrowup = 603;\n    t.arrowright = 987;\n    t.arrowdown = 603;\n    t.degree = 400;\n    t.plusminus = 549;\n    t.second = 411;\n    t.greaterequal = 549;\n    t.multiply = 549;\n    t.proportional = 713;\n    t.partialdiff = 494;\n    t.bullet = 460;\n    t.divide = 549;\n    t.notequal = 549;\n    t.equivalence = 549;\n    t.approxequal = 549;\n    t.ellipsis = 1000;\n    t.arrowvertex = 603;\n    t.arrowhorizex = 1000;\n    t.carriagereturn = 658;\n    t.aleph = 823;\n    t.Ifraktur = 686;\n    t.Rfraktur = 795;\n    t.weierstrass = 987;\n    t.circlemultiply = 768;\n    t.circleplus = 768;\n    t.emptyset = 823;\n    t.intersection = 768;\n    t.union = 768;\n    t.propersuperset = 713;\n    t.reflexsuperset = 713;\n    t.notsubset = 713;\n    t.propersubset = 713;\n    t.reflexsubset = 713;\n    t.element = 713;\n    t.notelement = 713;\n    t.angle = 768;\n    t.gradient = 713;\n    t.registerserif = 790;\n    t.copyrightserif = 790;\n    t.trademarkserif = 890;\n    t.product = 823;\n    t.radical = 549;\n    t.dotmath = 250;\n    t.logicalnot = 713;\n    t.logicaland = 603;\n    t.logicalor = 603;\n    t.arrowdblboth = 1042;\n    t.arrowdblleft = 987;\n    t.arrowdblup = 603;\n    t.arrowdblright = 987;\n    t.arrowdbldown = 603;\n    t.lozenge = 494;\n    t.angleleft = 329;\n    t.registersans = 790;\n    t.copyrightsans = 790;\n    t.trademarksans = 786;\n    t.summation = 713;\n    t.parenlefttp = 384;\n    t.parenleftex = 384;\n    t.parenleftbt = 384;\n    t.bracketlefttp = 384;\n    t.bracketleftex = 384;\n    t.bracketleftbt = 384;\n    t.bracelefttp = 494;\n    t.braceleftmid = 494;\n    t.braceleftbt = 494;\n    t.braceex = 494;\n    t.angleright = 329;\n    t.integral = 274;\n    t.integraltp = 686;\n    t.integralex = 686;\n    t.integralbt = 686;\n    t.parenrighttp = 384;\n    t.parenrightex = 384;\n    t.parenrightbt = 384;\n    t.bracketrighttp = 384;\n    t.bracketrightex = 384;\n    t.bracketrightbt = 384;\n    t.bracerighttp = 494;\n    t.bracerightmid = 494;\n    t.bracerightbt = 494;\n    t.apple = 790;\n  });\n  t[\"Times-Roman\"] = getLookupTableFactory(function (t) {\n    t.space = 250;\n    t.exclam = 333;\n    t.quotedbl = 408;\n    t.numbersign = 500;\n    t.dollar = 500;\n    t.percent = 833;\n    t.ampersand = 778;\n    t.quoteright = 333;\n    t.parenleft = 333;\n    t.parenright = 333;\n    t.asterisk = 500;\n    t.plus = 564;\n    t.comma = 250;\n    t.hyphen = 333;\n    t.period = 250;\n    t.slash = 278;\n    t.zero = 500;\n    t.one = 500;\n    t.two = 500;\n    t.three = 500;\n    t.four = 500;\n    t.five = 500;\n    t.six = 500;\n    t.seven = 500;\n    t.eight = 500;\n    t.nine = 500;\n    t.colon = 278;\n    t.semicolon = 278;\n    t.less = 564;\n    t.equal = 564;\n    t.greater = 564;\n    t.question = 444;\n    t.at = 921;\n    t.A = 722;\n    t.B = 667;\n    t.C = 667;\n    t.D = 722;\n    t.E = 611;\n    t.F = 556;\n    t.G = 722;\n    t.H = 722;\n    t.I = 333;\n    t.J = 389;\n    t.K = 722;\n    t.L = 611;\n    t.M = 889;\n    t.N = 722;\n    t.O = 722;\n    t.P = 556;\n    t.Q = 722;\n    t.R = 667;\n    t.S = 556;\n    t.T = 611;\n    t.U = 722;\n    t.V = 722;\n    t.W = 944;\n    t.X = 722;\n    t.Y = 722;\n    t.Z = 611;\n    t.bracketleft = 333;\n    t.backslash = 278;\n    t.bracketright = 333;\n    t.asciicircum = 469;\n    t.underscore = 500;\n    t.quoteleft = 333;\n    t.a = 444;\n    t.b = 500;\n    t.c = 444;\n    t.d = 500;\n    t.e = 444;\n    t.f = 333;\n    t.g = 500;\n    t.h = 500;\n    t.i = 278;\n    t.j = 278;\n    t.k = 500;\n    t.l = 278;\n    t.m = 778;\n    t.n = 500;\n    t.o = 500;\n    t.p = 500;\n    t.q = 500;\n    t.r = 333;\n    t.s = 389;\n    t.t = 278;\n    t.u = 500;\n    t.v = 500;\n    t.w = 722;\n    t.x = 500;\n    t.y = 500;\n    t.z = 444;\n    t.braceleft = 480;\n    t.bar = 200;\n    t.braceright = 480;\n    t.asciitilde = 541;\n    t.exclamdown = 333;\n    t.cent = 500;\n    t.sterling = 500;\n    t.fraction = 167;\n    t.yen = 500;\n    t.florin = 500;\n    t.section = 500;\n    t.currency = 500;\n    t.quotesingle = 180;\n    t.quotedblleft = 444;\n    t.guillemotleft = 500;\n    t.guilsinglleft = 333;\n    t.guilsinglright = 333;\n    t.fi = 556;\n    t.fl = 556;\n    t.endash = 500;\n    t.dagger = 500;\n    t.daggerdbl = 500;\n    t.periodcentered = 250;\n    t.paragraph = 453;\n    t.bullet = 350;\n    t.quotesinglbase = 333;\n    t.quotedblbase = 444;\n    t.quotedblright = 444;\n    t.guillemotright = 500;\n    t.ellipsis = 1000;\n    t.perthousand = 1000;\n    t.questiondown = 444;\n    t.grave = 333;\n    t.acute = 333;\n    t.circumflex = 333;\n    t.tilde = 333;\n    t.macron = 333;\n    t.breve = 333;\n    t.dotaccent = 333;\n    t.dieresis = 333;\n    t.ring = 333;\n    t.cedilla = 333;\n    t.hungarumlaut = 333;\n    t.ogonek = 333;\n    t.caron = 333;\n    t.emdash = 1000;\n    t.AE = 889;\n    t.ordfeminine = 276;\n    t.Lslash = 611;\n    t.Oslash = 722;\n    t.OE = 889;\n    t.ordmasculine = 310;\n    t.ae = 667;\n    t.dotlessi = 278;\n    t.lslash = 278;\n    t.oslash = 500;\n    t.oe = 722;\n    t.germandbls = 500;\n    t.Idieresis = 333;\n    t.eacute = 444;\n    t.abreve = 444;\n    t.uhungarumlaut = 500;\n    t.ecaron = 444;\n    t.Ydieresis = 722;\n    t.divide = 564;\n    t.Yacute = 722;\n    t.Acircumflex = 722;\n    t.aacute = 444;\n    t.Ucircumflex = 722;\n    t.yacute = 500;\n    t.scommaaccent = 389;\n    t.ecircumflex = 444;\n    t.Uring = 722;\n    t.Udieresis = 722;\n    t.aogonek = 444;\n    t.Uacute = 722;\n    t.uogonek = 500;\n    t.Edieresis = 611;\n    t.Dcroat = 722;\n    t.commaaccent = 250;\n    t.copyright = 760;\n    t.Emacron = 611;\n    t.ccaron = 444;\n    t.aring = 444;\n    t.Ncommaaccent = 722;\n    t.lacute = 278;\n    t.agrave = 444;\n    t.Tcommaaccent = 611;\n    t.Cacute = 667;\n    t.atilde = 444;\n    t.Edotaccent = 611;\n    t.scaron = 389;\n    t.scedilla = 389;\n    t.iacute = 278;\n    t.lozenge = 471;\n    t.Rcaron = 667;\n    t.Gcommaaccent = 722;\n    t.ucircumflex = 500;\n    t.acircumflex = 444;\n    t.Amacron = 722;\n    t.rcaron = 333;\n    t.ccedilla = 444;\n    t.Zdotaccent = 611;\n    t.Thorn = 556;\n    t.Omacron = 722;\n    t.Racute = 667;\n    t.Sacute = 556;\n    t.dcaron = 588;\n    t.Umacron = 722;\n    t.uring = 500;\n    t.threesuperior = 300;\n    t.Ograve = 722;\n    t.Agrave = 722;\n    t.Abreve = 722;\n    t.multiply = 564;\n    t.uacute = 500;\n    t.Tcaron = 611;\n    t.partialdiff = 476;\n    t.ydieresis = 500;\n    t.Nacute = 722;\n    t.icircumflex = 278;\n    t.Ecircumflex = 611;\n    t.adieresis = 444;\n    t.edieresis = 444;\n    t.cacute = 444;\n    t.nacute = 500;\n    t.umacron = 500;\n    t.Ncaron = 722;\n    t.Iacute = 333;\n    t.plusminus = 564;\n    t.brokenbar = 200;\n    t.registered = 760;\n    t.Gbreve = 722;\n    t.Idotaccent = 333;\n    t.summation = 600;\n    t.Egrave = 611;\n    t.racute = 333;\n    t.omacron = 500;\n    t.Zacute = 611;\n    t.Zcaron = 611;\n    t.greaterequal = 549;\n    t.Eth = 722;\n    t.Ccedilla = 667;\n    t.lcommaaccent = 278;\n    t.tcaron = 326;\n    t.eogonek = 444;\n    t.Uogonek = 722;\n    t.Aacute = 722;\n    t.Adieresis = 722;\n    t.egrave = 444;\n    t.zacute = 444;\n    t.iogonek = 278;\n    t.Oacute = 722;\n    t.oacute = 500;\n    t.amacron = 444;\n    t.sacute = 389;\n    t.idieresis = 278;\n    t.Ocircumflex = 722;\n    t.Ugrave = 722;\n    t.Delta = 612;\n    t.thorn = 500;\n    t.twosuperior = 300;\n    t.Odieresis = 722;\n    t.mu = 500;\n    t.igrave = 278;\n    t.ohungarumlaut = 500;\n    t.Eogonek = 611;\n    t.dcroat = 500;\n    t.threequarters = 750;\n    t.Scedilla = 556;\n    t.lcaron = 344;\n    t.Kcommaaccent = 722;\n    t.Lacute = 611;\n    t.trademark = 980;\n    t.edotaccent = 444;\n    t.Igrave = 333;\n    t.Imacron = 333;\n    t.Lcaron = 611;\n    t.onehalf = 750;\n    t.lessequal = 549;\n    t.ocircumflex = 500;\n    t.ntilde = 500;\n    t.Uhungarumlaut = 722;\n    t.Eacute = 611;\n    t.emacron = 444;\n    t.gbreve = 500;\n    t.onequarter = 750;\n    t.Scaron = 556;\n    t.Scommaaccent = 556;\n    t.Ohungarumlaut = 722;\n    t.degree = 400;\n    t.ograve = 500;\n    t.Ccaron = 667;\n    t.ugrave = 500;\n    t.radical = 453;\n    t.Dcaron = 722;\n    t.rcommaaccent = 333;\n    t.Ntilde = 722;\n    t.otilde = 500;\n    t.Rcommaaccent = 667;\n    t.Lcommaaccent = 611;\n    t.Atilde = 722;\n    t.Aogonek = 722;\n    t.Aring = 722;\n    t.Otilde = 722;\n    t.zdotaccent = 444;\n    t.Ecaron = 611;\n    t.Iogonek = 333;\n    t.kcommaaccent = 500;\n    t.minus = 564;\n    t.Icircumflex = 333;\n    t.ncaron = 500;\n    t.tcommaaccent = 278;\n    t.logicalnot = 564;\n    t.odieresis = 500;\n    t.udieresis = 500;\n    t.notequal = 549;\n    t.gcommaaccent = 500;\n    t.eth = 500;\n    t.zcaron = 444;\n    t.ncommaaccent = 500;\n    t.onesuperior = 300;\n    t.imacron = 278;\n    t.Euro = 500;\n  });\n  t[\"Times-Bold\"] = getLookupTableFactory(function (t) {\n    t.space = 250;\n    t.exclam = 333;\n    t.quotedbl = 555;\n    t.numbersign = 500;\n    t.dollar = 500;\n    t.percent = 1000;\n    t.ampersand = 833;\n    t.quoteright = 333;\n    t.parenleft = 333;\n    t.parenright = 333;\n    t.asterisk = 500;\n    t.plus = 570;\n    t.comma = 250;\n    t.hyphen = 333;\n    t.period = 250;\n    t.slash = 278;\n    t.zero = 500;\n    t.one = 500;\n    t.two = 500;\n    t.three = 500;\n    t.four = 500;\n    t.five = 500;\n    t.six = 500;\n    t.seven = 500;\n    t.eight = 500;\n    t.nine = 500;\n    t.colon = 333;\n    t.semicolon = 333;\n    t.less = 570;\n    t.equal = 570;\n    t.greater = 570;\n    t.question = 500;\n    t.at = 930;\n    t.A = 722;\n    t.B = 667;\n    t.C = 722;\n    t.D = 722;\n    t.E = 667;\n    t.F = 611;\n    t.G = 778;\n    t.H = 778;\n    t.I = 389;\n    t.J = 500;\n    t.K = 778;\n    t.L = 667;\n    t.M = 944;\n    t.N = 722;\n    t.O = 778;\n    t.P = 611;\n    t.Q = 778;\n    t.R = 722;\n    t.S = 556;\n    t.T = 667;\n    t.U = 722;\n    t.V = 722;\n    t.W = 1000;\n    t.X = 722;\n    t.Y = 722;\n    t.Z = 667;\n    t.bracketleft = 333;\n    t.backslash = 278;\n    t.bracketright = 333;\n    t.asciicircum = 581;\n    t.underscore = 500;\n    t.quoteleft = 333;\n    t.a = 500;\n    t.b = 556;\n    t.c = 444;\n    t.d = 556;\n    t.e = 444;\n    t.f = 333;\n    t.g = 500;\n    t.h = 556;\n    t.i = 278;\n    t.j = 333;\n    t.k = 556;\n    t.l = 278;\n    t.m = 833;\n    t.n = 556;\n    t.o = 500;\n    t.p = 556;\n    t.q = 556;\n    t.r = 444;\n    t.s = 389;\n    t.t = 333;\n    t.u = 556;\n    t.v = 500;\n    t.w = 722;\n    t.x = 500;\n    t.y = 500;\n    t.z = 444;\n    t.braceleft = 394;\n    t.bar = 220;\n    t.braceright = 394;\n    t.asciitilde = 520;\n    t.exclamdown = 333;\n    t.cent = 500;\n    t.sterling = 500;\n    t.fraction = 167;\n    t.yen = 500;\n    t.florin = 500;\n    t.section = 500;\n    t.currency = 500;\n    t.quotesingle = 278;\n    t.quotedblleft = 500;\n    t.guillemotleft = 500;\n    t.guilsinglleft = 333;\n    t.guilsinglright = 333;\n    t.fi = 556;\n    t.fl = 556;\n    t.endash = 500;\n    t.dagger = 500;\n    t.daggerdbl = 500;\n    t.periodcentered = 250;\n    t.paragraph = 540;\n    t.bullet = 350;\n    t.quotesinglbase = 333;\n    t.quotedblbase = 500;\n    t.quotedblright = 500;\n    t.guillemotright = 500;\n    t.ellipsis = 1000;\n    t.perthousand = 1000;\n    t.questiondown = 500;\n    t.grave = 333;\n    t.acute = 333;\n    t.circumflex = 333;\n    t.tilde = 333;\n    t.macron = 333;\n    t.breve = 333;\n    t.dotaccent = 333;\n    t.dieresis = 333;\n    t.ring = 333;\n    t.cedilla = 333;\n    t.hungarumlaut = 333;\n    t.ogonek = 333;\n    t.caron = 333;\n    t.emdash = 1000;\n    t.AE = 1000;\n    t.ordfeminine = 300;\n    t.Lslash = 667;\n    t.Oslash = 778;\n    t.OE = 1000;\n    t.ordmasculine = 330;\n    t.ae = 722;\n    t.dotlessi = 278;\n    t.lslash = 278;\n    t.oslash = 500;\n    t.oe = 722;\n    t.germandbls = 556;\n    t.Idieresis = 389;\n    t.eacute = 444;\n    t.abreve = 500;\n    t.uhungarumlaut = 556;\n    t.ecaron = 444;\n    t.Ydieresis = 722;\n    t.divide = 570;\n    t.Yacute = 722;\n    t.Acircumflex = 722;\n    t.aacute = 500;\n    t.Ucircumflex = 722;\n    t.yacute = 500;\n    t.scommaaccent = 389;\n    t.ecircumflex = 444;\n    t.Uring = 722;\n    t.Udieresis = 722;\n    t.aogonek = 500;\n    t.Uacute = 722;\n    t.uogonek = 556;\n    t.Edieresis = 667;\n    t.Dcroat = 722;\n    t.commaaccent = 250;\n    t.copyright = 747;\n    t.Emacron = 667;\n    t.ccaron = 444;\n    t.aring = 500;\n    t.Ncommaaccent = 722;\n    t.lacute = 278;\n    t.agrave = 500;\n    t.Tcommaaccent = 667;\n    t.Cacute = 722;\n    t.atilde = 500;\n    t.Edotaccent = 667;\n    t.scaron = 389;\n    t.scedilla = 389;\n    t.iacute = 278;\n    t.lozenge = 494;\n    t.Rcaron = 722;\n    t.Gcommaaccent = 778;\n    t.ucircumflex = 556;\n    t.acircumflex = 500;\n    t.Amacron = 722;\n    t.rcaron = 444;\n    t.ccedilla = 444;\n    t.Zdotaccent = 667;\n    t.Thorn = 611;\n    t.Omacron = 778;\n    t.Racute = 722;\n    t.Sacute = 556;\n    t.dcaron = 672;\n    t.Umacron = 722;\n    t.uring = 556;\n    t.threesuperior = 300;\n    t.Ograve = 778;\n    t.Agrave = 722;\n    t.Abreve = 722;\n    t.multiply = 570;\n    t.uacute = 556;\n    t.Tcaron = 667;\n    t.partialdiff = 494;\n    t.ydieresis = 500;\n    t.Nacute = 722;\n    t.icircumflex = 278;\n    t.Ecircumflex = 667;\n    t.adieresis = 500;\n    t.edieresis = 444;\n    t.cacute = 444;\n    t.nacute = 556;\n    t.umacron = 556;\n    t.Ncaron = 722;\n    t.Iacute = 389;\n    t.plusminus = 570;\n    t.brokenbar = 220;\n    t.registered = 747;\n    t.Gbreve = 778;\n    t.Idotaccent = 389;\n    t.summation = 600;\n    t.Egrave = 667;\n    t.racute = 444;\n    t.omacron = 500;\n    t.Zacute = 667;\n    t.Zcaron = 667;\n    t.greaterequal = 549;\n    t.Eth = 722;\n    t.Ccedilla = 722;\n    t.lcommaaccent = 278;\n    t.tcaron = 416;\n    t.eogonek = 444;\n    t.Uogonek = 722;\n    t.Aacute = 722;\n    t.Adieresis = 722;\n    t.egrave = 444;\n    t.zacute = 444;\n    t.iogonek = 278;\n    t.Oacute = 778;\n    t.oacute = 500;\n    t.amacron = 500;\n    t.sacute = 389;\n    t.idieresis = 278;\n    t.Ocircumflex = 778;\n    t.Ugrave = 722;\n    t.Delta = 612;\n    t.thorn = 556;\n    t.twosuperior = 300;\n    t.Odieresis = 778;\n    t.mu = 556;\n    t.igrave = 278;\n    t.ohungarumlaut = 500;\n    t.Eogonek = 667;\n    t.dcroat = 556;\n    t.threequarters = 750;\n    t.Scedilla = 556;\n    t.lcaron = 394;\n    t.Kcommaaccent = 778;\n    t.Lacute = 667;\n    t.trademark = 1000;\n    t.edotaccent = 444;\n    t.Igrave = 389;\n    t.Imacron = 389;\n    t.Lcaron = 667;\n    t.onehalf = 750;\n    t.lessequal = 549;\n    t.ocircumflex = 500;\n    t.ntilde = 556;\n    t.Uhungarumlaut = 722;\n    t.Eacute = 667;\n    t.emacron = 444;\n    t.gbreve = 500;\n    t.onequarter = 750;\n    t.Scaron = 556;\n    t.Scommaaccent = 556;\n    t.Ohungarumlaut = 778;\n    t.degree = 400;\n    t.ograve = 500;\n    t.Ccaron = 722;\n    t.ugrave = 556;\n    t.radical = 549;\n    t.Dcaron = 722;\n    t.rcommaaccent = 444;\n    t.Ntilde = 722;\n    t.otilde = 500;\n    t.Rcommaaccent = 722;\n    t.Lcommaaccent = 667;\n    t.Atilde = 722;\n    t.Aogonek = 722;\n    t.Aring = 722;\n    t.Otilde = 778;\n    t.zdotaccent = 444;\n    t.Ecaron = 667;\n    t.Iogonek = 389;\n    t.kcommaaccent = 556;\n    t.minus = 570;\n    t.Icircumflex = 389;\n    t.ncaron = 556;\n    t.tcommaaccent = 333;\n    t.logicalnot = 570;\n    t.odieresis = 500;\n    t.udieresis = 556;\n    t.notequal = 549;\n    t.gcommaaccent = 500;\n    t.eth = 500;\n    t.zcaron = 444;\n    t.ncommaaccent = 556;\n    t.onesuperior = 300;\n    t.imacron = 278;\n    t.Euro = 500;\n  });\n  t[\"Times-BoldItalic\"] = getLookupTableFactory(function (t) {\n    t.space = 250;\n    t.exclam = 389;\n    t.quotedbl = 555;\n    t.numbersign = 500;\n    t.dollar = 500;\n    t.percent = 833;\n    t.ampersand = 778;\n    t.quoteright = 333;\n    t.parenleft = 333;\n    t.parenright = 333;\n    t.asterisk = 500;\n    t.plus = 570;\n    t.comma = 250;\n    t.hyphen = 333;\n    t.period = 250;\n    t.slash = 278;\n    t.zero = 500;\n    t.one = 500;\n    t.two = 500;\n    t.three = 500;\n    t.four = 500;\n    t.five = 500;\n    t.six = 500;\n    t.seven = 500;\n    t.eight = 500;\n    t.nine = 500;\n    t.colon = 333;\n    t.semicolon = 333;\n    t.less = 570;\n    t.equal = 570;\n    t.greater = 570;\n    t.question = 500;\n    t.at = 832;\n    t.A = 667;\n    t.B = 667;\n    t.C = 667;\n    t.D = 722;\n    t.E = 667;\n    t.F = 667;\n    t.G = 722;\n    t.H = 778;\n    t.I = 389;\n    t.J = 500;\n    t.K = 667;\n    t.L = 611;\n    t.M = 889;\n    t.N = 722;\n    t.O = 722;\n    t.P = 611;\n    t.Q = 722;\n    t.R = 667;\n    t.S = 556;\n    t.T = 611;\n    t.U = 722;\n    t.V = 667;\n    t.W = 889;\n    t.X = 667;\n    t.Y = 611;\n    t.Z = 611;\n    t.bracketleft = 333;\n    t.backslash = 278;\n    t.bracketright = 333;\n    t.asciicircum = 570;\n    t.underscore = 500;\n    t.quoteleft = 333;\n    t.a = 500;\n    t.b = 500;\n    t.c = 444;\n    t.d = 500;\n    t.e = 444;\n    t.f = 333;\n    t.g = 500;\n    t.h = 556;\n    t.i = 278;\n    t.j = 278;\n    t.k = 500;\n    t.l = 278;\n    t.m = 778;\n    t.n = 556;\n    t.o = 500;\n    t.p = 500;\n    t.q = 500;\n    t.r = 389;\n    t.s = 389;\n    t.t = 278;\n    t.u = 556;\n    t.v = 444;\n    t.w = 667;\n    t.x = 500;\n    t.y = 444;\n    t.z = 389;\n    t.braceleft = 348;\n    t.bar = 220;\n    t.braceright = 348;\n    t.asciitilde = 570;\n    t.exclamdown = 389;\n    t.cent = 500;\n    t.sterling = 500;\n    t.fraction = 167;\n    t.yen = 500;\n    t.florin = 500;\n    t.section = 500;\n    t.currency = 500;\n    t.quotesingle = 278;\n    t.quotedblleft = 500;\n    t.guillemotleft = 500;\n    t.guilsinglleft = 333;\n    t.guilsinglright = 333;\n    t.fi = 556;\n    t.fl = 556;\n    t.endash = 500;\n    t.dagger = 500;\n    t.daggerdbl = 500;\n    t.periodcentered = 250;\n    t.paragraph = 500;\n    t.bullet = 350;\n    t.quotesinglbase = 333;\n    t.quotedblbase = 500;\n    t.quotedblright = 500;\n    t.guillemotright = 500;\n    t.ellipsis = 1000;\n    t.perthousand = 1000;\n    t.questiondown = 500;\n    t.grave = 333;\n    t.acute = 333;\n    t.circumflex = 333;\n    t.tilde = 333;\n    t.macron = 333;\n    t.breve = 333;\n    t.dotaccent = 333;\n    t.dieresis = 333;\n    t.ring = 333;\n    t.cedilla = 333;\n    t.hungarumlaut = 333;\n    t.ogonek = 333;\n    t.caron = 333;\n    t.emdash = 1000;\n    t.AE = 944;\n    t.ordfeminine = 266;\n    t.Lslash = 611;\n    t.Oslash = 722;\n    t.OE = 944;\n    t.ordmasculine = 300;\n    t.ae = 722;\n    t.dotlessi = 278;\n    t.lslash = 278;\n    t.oslash = 500;\n    t.oe = 722;\n    t.germandbls = 500;\n    t.Idieresis = 389;\n    t.eacute = 444;\n    t.abreve = 500;\n    t.uhungarumlaut = 556;\n    t.ecaron = 444;\n    t.Ydieresis = 611;\n    t.divide = 570;\n    t.Yacute = 611;\n    t.Acircumflex = 667;\n    t.aacute = 500;\n    t.Ucircumflex = 722;\n    t.yacute = 444;\n    t.scommaaccent = 389;\n    t.ecircumflex = 444;\n    t.Uring = 722;\n    t.Udieresis = 722;\n    t.aogonek = 500;\n    t.Uacute = 722;\n    t.uogonek = 556;\n    t.Edieresis = 667;\n    t.Dcroat = 722;\n    t.commaaccent = 250;\n    t.copyright = 747;\n    t.Emacron = 667;\n    t.ccaron = 444;\n    t.aring = 500;\n    t.Ncommaaccent = 722;\n    t.lacute = 278;\n    t.agrave = 500;\n    t.Tcommaaccent = 611;\n    t.Cacute = 667;\n    t.atilde = 500;\n    t.Edotaccent = 667;\n    t.scaron = 389;\n    t.scedilla = 389;\n    t.iacute = 278;\n    t.lozenge = 494;\n    t.Rcaron = 667;\n    t.Gcommaaccent = 722;\n    t.ucircumflex = 556;\n    t.acircumflex = 500;\n    t.Amacron = 667;\n    t.rcaron = 389;\n    t.ccedilla = 444;\n    t.Zdotaccent = 611;\n    t.Thorn = 611;\n    t.Omacron = 722;\n    t.Racute = 667;\n    t.Sacute = 556;\n    t.dcaron = 608;\n    t.Umacron = 722;\n    t.uring = 556;\n    t.threesuperior = 300;\n    t.Ograve = 722;\n    t.Agrave = 667;\n    t.Abreve = 667;\n    t.multiply = 570;\n    t.uacute = 556;\n    t.Tcaron = 611;\n    t.partialdiff = 494;\n    t.ydieresis = 444;\n    t.Nacute = 722;\n    t.icircumflex = 278;\n    t.Ecircumflex = 667;\n    t.adieresis = 500;\n    t.edieresis = 444;\n    t.cacute = 444;\n    t.nacute = 556;\n    t.umacron = 556;\n    t.Ncaron = 722;\n    t.Iacute = 389;\n    t.plusminus = 570;\n    t.brokenbar = 220;\n    t.registered = 747;\n    t.Gbreve = 722;\n    t.Idotaccent = 389;\n    t.summation = 600;\n    t.Egrave = 667;\n    t.racute = 389;\n    t.omacron = 500;\n    t.Zacute = 611;\n    t.Zcaron = 611;\n    t.greaterequal = 549;\n    t.Eth = 722;\n    t.Ccedilla = 667;\n    t.lcommaaccent = 278;\n    t.tcaron = 366;\n    t.eogonek = 444;\n    t.Uogonek = 722;\n    t.Aacute = 667;\n    t.Adieresis = 667;\n    t.egrave = 444;\n    t.zacute = 389;\n    t.iogonek = 278;\n    t.Oacute = 722;\n    t.oacute = 500;\n    t.amacron = 500;\n    t.sacute = 389;\n    t.idieresis = 278;\n    t.Ocircumflex = 722;\n    t.Ugrave = 722;\n    t.Delta = 612;\n    t.thorn = 500;\n    t.twosuperior = 300;\n    t.Odieresis = 722;\n    t.mu = 576;\n    t.igrave = 278;\n    t.ohungarumlaut = 500;\n    t.Eogonek = 667;\n    t.dcroat = 500;\n    t.threequarters = 750;\n    t.Scedilla = 556;\n    t.lcaron = 382;\n    t.Kcommaaccent = 667;\n    t.Lacute = 611;\n    t.trademark = 1000;\n    t.edotaccent = 444;\n    t.Igrave = 389;\n    t.Imacron = 389;\n    t.Lcaron = 611;\n    t.onehalf = 750;\n    t.lessequal = 549;\n    t.ocircumflex = 500;\n    t.ntilde = 556;\n    t.Uhungarumlaut = 722;\n    t.Eacute = 667;\n    t.emacron = 444;\n    t.gbreve = 500;\n    t.onequarter = 750;\n    t.Scaron = 556;\n    t.Scommaaccent = 556;\n    t.Ohungarumlaut = 722;\n    t.degree = 400;\n    t.ograve = 500;\n    t.Ccaron = 667;\n    t.ugrave = 556;\n    t.radical = 549;\n    t.Dcaron = 722;\n    t.rcommaaccent = 389;\n    t.Ntilde = 722;\n    t.otilde = 500;\n    t.Rcommaaccent = 667;\n    t.Lcommaaccent = 611;\n    t.Atilde = 667;\n    t.Aogonek = 667;\n    t.Aring = 667;\n    t.Otilde = 722;\n    t.zdotaccent = 389;\n    t.Ecaron = 667;\n    t.Iogonek = 389;\n    t.kcommaaccent = 500;\n    t.minus = 606;\n    t.Icircumflex = 389;\n    t.ncaron = 556;\n    t.tcommaaccent = 278;\n    t.logicalnot = 606;\n    t.odieresis = 500;\n    t.udieresis = 556;\n    t.notequal = 549;\n    t.gcommaaccent = 500;\n    t.eth = 500;\n    t.zcaron = 389;\n    t.ncommaaccent = 556;\n    t.onesuperior = 300;\n    t.imacron = 278;\n    t.Euro = 500;\n  });\n  t[\"Times-Italic\"] = getLookupTableFactory(function (t) {\n    t.space = 250;\n    t.exclam = 333;\n    t.quotedbl = 420;\n    t.numbersign = 500;\n    t.dollar = 500;\n    t.percent = 833;\n    t.ampersand = 778;\n    t.quoteright = 333;\n    t.parenleft = 333;\n    t.parenright = 333;\n    t.asterisk = 500;\n    t.plus = 675;\n    t.comma = 250;\n    t.hyphen = 333;\n    t.period = 250;\n    t.slash = 278;\n    t.zero = 500;\n    t.one = 500;\n    t.two = 500;\n    t.three = 500;\n    t.four = 500;\n    t.five = 500;\n    t.six = 500;\n    t.seven = 500;\n    t.eight = 500;\n    t.nine = 500;\n    t.colon = 333;\n    t.semicolon = 333;\n    t.less = 675;\n    t.equal = 675;\n    t.greater = 675;\n    t.question = 500;\n    t.at = 920;\n    t.A = 611;\n    t.B = 611;\n    t.C = 667;\n    t.D = 722;\n    t.E = 611;\n    t.F = 611;\n    t.G = 722;\n    t.H = 722;\n    t.I = 333;\n    t.J = 444;\n    t.K = 667;\n    t.L = 556;\n    t.M = 833;\n    t.N = 667;\n    t.O = 722;\n    t.P = 611;\n    t.Q = 722;\n    t.R = 611;\n    t.S = 500;\n    t.T = 556;\n    t.U = 722;\n    t.V = 611;\n    t.W = 833;\n    t.X = 611;\n    t.Y = 556;\n    t.Z = 556;\n    t.bracketleft = 389;\n    t.backslash = 278;\n    t.bracketright = 389;\n    t.asciicircum = 422;\n    t.underscore = 500;\n    t.quoteleft = 333;\n    t.a = 500;\n    t.b = 500;\n    t.c = 444;\n    t.d = 500;\n    t.e = 444;\n    t.f = 278;\n    t.g = 500;\n    t.h = 500;\n    t.i = 278;\n    t.j = 278;\n    t.k = 444;\n    t.l = 278;\n    t.m = 722;\n    t.n = 500;\n    t.o = 500;\n    t.p = 500;\n    t.q = 500;\n    t.r = 389;\n    t.s = 389;\n    t.t = 278;\n    t.u = 500;\n    t.v = 444;\n    t.w = 667;\n    t.x = 444;\n    t.y = 444;\n    t.z = 389;\n    t.braceleft = 400;\n    t.bar = 275;\n    t.braceright = 400;\n    t.asciitilde = 541;\n    t.exclamdown = 389;\n    t.cent = 500;\n    t.sterling = 500;\n    t.fraction = 167;\n    t.yen = 500;\n    t.florin = 500;\n    t.section = 500;\n    t.currency = 500;\n    t.quotesingle = 214;\n    t.quotedblleft = 556;\n    t.guillemotleft = 500;\n    t.guilsinglleft = 333;\n    t.guilsinglright = 333;\n    t.fi = 500;\n    t.fl = 500;\n    t.endash = 500;\n    t.dagger = 500;\n    t.daggerdbl = 500;\n    t.periodcentered = 250;\n    t.paragraph = 523;\n    t.bullet = 350;\n    t.quotesinglbase = 333;\n    t.quotedblbase = 556;\n    t.quotedblright = 556;\n    t.guillemotright = 500;\n    t.ellipsis = 889;\n    t.perthousand = 1000;\n    t.questiondown = 500;\n    t.grave = 333;\n    t.acute = 333;\n    t.circumflex = 333;\n    t.tilde = 333;\n    t.macron = 333;\n    t.breve = 333;\n    t.dotaccent = 333;\n    t.dieresis = 333;\n    t.ring = 333;\n    t.cedilla = 333;\n    t.hungarumlaut = 333;\n    t.ogonek = 333;\n    t.caron = 333;\n    t.emdash = 889;\n    t.AE = 889;\n    t.ordfeminine = 276;\n    t.Lslash = 556;\n    t.Oslash = 722;\n    t.OE = 944;\n    t.ordmasculine = 310;\n    t.ae = 667;\n    t.dotlessi = 278;\n    t.lslash = 278;\n    t.oslash = 500;\n    t.oe = 667;\n    t.germandbls = 500;\n    t.Idieresis = 333;\n    t.eacute = 444;\n    t.abreve = 500;\n    t.uhungarumlaut = 500;\n    t.ecaron = 444;\n    t.Ydieresis = 556;\n    t.divide = 675;\n    t.Yacute = 556;\n    t.Acircumflex = 611;\n    t.aacute = 500;\n    t.Ucircumflex = 722;\n    t.yacute = 444;\n    t.scommaaccent = 389;\n    t.ecircumflex = 444;\n    t.Uring = 722;\n    t.Udieresis = 722;\n    t.aogonek = 500;\n    t.Uacute = 722;\n    t.uogonek = 500;\n    t.Edieresis = 611;\n    t.Dcroat = 722;\n    t.commaaccent = 250;\n    t.copyright = 760;\n    t.Emacron = 611;\n    t.ccaron = 444;\n    t.aring = 500;\n    t.Ncommaaccent = 667;\n    t.lacute = 278;\n    t.agrave = 500;\n    t.Tcommaaccent = 556;\n    t.Cacute = 667;\n    t.atilde = 500;\n    t.Edotaccent = 611;\n    t.scaron = 389;\n    t.scedilla = 389;\n    t.iacute = 278;\n    t.lozenge = 471;\n    t.Rcaron = 611;\n    t.Gcommaaccent = 722;\n    t.ucircumflex = 500;\n    t.acircumflex = 500;\n    t.Amacron = 611;\n    t.rcaron = 389;\n    t.ccedilla = 444;\n    t.Zdotaccent = 556;\n    t.Thorn = 611;\n    t.Omacron = 722;\n    t.Racute = 611;\n    t.Sacute = 500;\n    t.dcaron = 544;\n    t.Umacron = 722;\n    t.uring = 500;\n    t.threesuperior = 300;\n    t.Ograve = 722;\n    t.Agrave = 611;\n    t.Abreve = 611;\n    t.multiply = 675;\n    t.uacute = 500;\n    t.Tcaron = 556;\n    t.partialdiff = 476;\n    t.ydieresis = 444;\n    t.Nacute = 667;\n    t.icircumflex = 278;\n    t.Ecircumflex = 611;\n    t.adieresis = 500;\n    t.edieresis = 444;\n    t.cacute = 444;\n    t.nacute = 500;\n    t.umacron = 500;\n    t.Ncaron = 667;\n    t.Iacute = 333;\n    t.plusminus = 675;\n    t.brokenbar = 275;\n    t.registered = 760;\n    t.Gbreve = 722;\n    t.Idotaccent = 333;\n    t.summation = 600;\n    t.Egrave = 611;\n    t.racute = 389;\n    t.omacron = 500;\n    t.Zacute = 556;\n    t.Zcaron = 556;\n    t.greaterequal = 549;\n    t.Eth = 722;\n    t.Ccedilla = 667;\n    t.lcommaaccent = 278;\n    t.tcaron = 300;\n    t.eogonek = 444;\n    t.Uogonek = 722;\n    t.Aacute = 611;\n    t.Adieresis = 611;\n    t.egrave = 444;\n    t.zacute = 389;\n    t.iogonek = 278;\n    t.Oacute = 722;\n    t.oacute = 500;\n    t.amacron = 500;\n    t.sacute = 389;\n    t.idieresis = 278;\n    t.Ocircumflex = 722;\n    t.Ugrave = 722;\n    t.Delta = 612;\n    t.thorn = 500;\n    t.twosuperior = 300;\n    t.Odieresis = 722;\n    t.mu = 500;\n    t.igrave = 278;\n    t.ohungarumlaut = 500;\n    t.Eogonek = 611;\n    t.dcroat = 500;\n    t.threequarters = 750;\n    t.Scedilla = 500;\n    t.lcaron = 300;\n    t.Kcommaaccent = 667;\n    t.Lacute = 556;\n    t.trademark = 980;\n    t.edotaccent = 444;\n    t.Igrave = 333;\n    t.Imacron = 333;\n    t.Lcaron = 611;\n    t.onehalf = 750;\n    t.lessequal = 549;\n    t.ocircumflex = 500;\n    t.ntilde = 500;\n    t.Uhungarumlaut = 722;\n    t.Eacute = 611;\n    t.emacron = 444;\n    t.gbreve = 500;\n    t.onequarter = 750;\n    t.Scaron = 500;\n    t.Scommaaccent = 500;\n    t.Ohungarumlaut = 722;\n    t.degree = 400;\n    t.ograve = 500;\n    t.Ccaron = 667;\n    t.ugrave = 500;\n    t.radical = 453;\n    t.Dcaron = 722;\n    t.rcommaaccent = 389;\n    t.Ntilde = 667;\n    t.otilde = 500;\n    t.Rcommaaccent = 611;\n    t.Lcommaaccent = 556;\n    t.Atilde = 611;\n    t.Aogonek = 611;\n    t.Aring = 611;\n    t.Otilde = 722;\n    t.zdotaccent = 389;\n    t.Ecaron = 611;\n    t.Iogonek = 333;\n    t.kcommaaccent = 444;\n    t.minus = 675;\n    t.Icircumflex = 333;\n    t.ncaron = 500;\n    t.tcommaaccent = 278;\n    t.logicalnot = 675;\n    t.odieresis = 500;\n    t.udieresis = 500;\n    t.notequal = 549;\n    t.gcommaaccent = 500;\n    t.eth = 500;\n    t.zcaron = 389;\n    t.ncommaaccent = 500;\n    t.onesuperior = 300;\n    t.imacron = 278;\n    t.Euro = 500;\n  });\n  t.ZapfDingbats = getLookupTableFactory(function (t) {\n    t.space = 278;\n    t.a1 = 974;\n    t.a2 = 961;\n    t.a202 = 974;\n    t.a3 = 980;\n    t.a4 = 719;\n    t.a5 = 789;\n    t.a119 = 790;\n    t.a118 = 791;\n    t.a117 = 690;\n    t.a11 = 960;\n    t.a12 = 939;\n    t.a13 = 549;\n    t.a14 = 855;\n    t.a15 = 911;\n    t.a16 = 933;\n    t.a105 = 911;\n    t.a17 = 945;\n    t.a18 = 974;\n    t.a19 = 755;\n    t.a20 = 846;\n    t.a21 = 762;\n    t.a22 = 761;\n    t.a23 = 571;\n    t.a24 = 677;\n    t.a25 = 763;\n    t.a26 = 760;\n    t.a27 = 759;\n    t.a28 = 754;\n    t.a6 = 494;\n    t.a7 = 552;\n    t.a8 = 537;\n    t.a9 = 577;\n    t.a10 = 692;\n    t.a29 = 786;\n    t.a30 = 788;\n    t.a31 = 788;\n    t.a32 = 790;\n    t.a33 = 793;\n    t.a34 = 794;\n    t.a35 = 816;\n    t.a36 = 823;\n    t.a37 = 789;\n    t.a38 = 841;\n    t.a39 = 823;\n    t.a40 = 833;\n    t.a41 = 816;\n    t.a42 = 831;\n    t.a43 = 923;\n    t.a44 = 744;\n    t.a45 = 723;\n    t.a46 = 749;\n    t.a47 = 790;\n    t.a48 = 792;\n    t.a49 = 695;\n    t.a50 = 776;\n    t.a51 = 768;\n    t.a52 = 792;\n    t.a53 = 759;\n    t.a54 = 707;\n    t.a55 = 708;\n    t.a56 = 682;\n    t.a57 = 701;\n    t.a58 = 826;\n    t.a59 = 815;\n    t.a60 = 789;\n    t.a61 = 789;\n    t.a62 = 707;\n    t.a63 = 687;\n    t.a64 = 696;\n    t.a65 = 689;\n    t.a66 = 786;\n    t.a67 = 787;\n    t.a68 = 713;\n    t.a69 = 791;\n    t.a70 = 785;\n    t.a71 = 791;\n    t.a72 = 873;\n    t.a73 = 761;\n    t.a74 = 762;\n    t.a203 = 762;\n    t.a75 = 759;\n    t.a204 = 759;\n    t.a76 = 892;\n    t.a77 = 892;\n    t.a78 = 788;\n    t.a79 = 784;\n    t.a81 = 438;\n    t.a82 = 138;\n    t.a83 = 277;\n    t.a84 = 415;\n    t.a97 = 392;\n    t.a98 = 392;\n    t.a99 = 668;\n    t.a100 = 668;\n    t.a89 = 390;\n    t.a90 = 390;\n    t.a93 = 317;\n    t.a94 = 317;\n    t.a91 = 276;\n    t.a92 = 276;\n    t.a205 = 509;\n    t.a85 = 509;\n    t.a206 = 410;\n    t.a86 = 410;\n    t.a87 = 234;\n    t.a88 = 234;\n    t.a95 = 334;\n    t.a96 = 334;\n    t.a101 = 732;\n    t.a102 = 544;\n    t.a103 = 544;\n    t.a104 = 910;\n    t.a106 = 667;\n    t.a107 = 760;\n    t.a108 = 760;\n    t.a112 = 776;\n    t.a111 = 595;\n    t.a110 = 694;\n    t.a109 = 626;\n    t.a120 = 788;\n    t.a121 = 788;\n    t.a122 = 788;\n    t.a123 = 788;\n    t.a124 = 788;\n    t.a125 = 788;\n    t.a126 = 788;\n    t.a127 = 788;\n    t.a128 = 788;\n    t.a129 = 788;\n    t.a130 = 788;\n    t.a131 = 788;\n    t.a132 = 788;\n    t.a133 = 788;\n    t.a134 = 788;\n    t.a135 = 788;\n    t.a136 = 788;\n    t.a137 = 788;\n    t.a138 = 788;\n    t.a139 = 788;\n    t.a140 = 788;\n    t.a141 = 788;\n    t.a142 = 788;\n    t.a143 = 788;\n    t.a144 = 788;\n    t.a145 = 788;\n    t.a146 = 788;\n    t.a147 = 788;\n    t.a148 = 788;\n    t.a149 = 788;\n    t.a150 = 788;\n    t.a151 = 788;\n    t.a152 = 788;\n    t.a153 = 788;\n    t.a154 = 788;\n    t.a155 = 788;\n    t.a156 = 788;\n    t.a157 = 788;\n    t.a158 = 788;\n    t.a159 = 788;\n    t.a160 = 894;\n    t.a161 = 838;\n    t.a163 = 1016;\n    t.a164 = 458;\n    t.a196 = 748;\n    t.a165 = 924;\n    t.a192 = 748;\n    t.a166 = 918;\n    t.a167 = 927;\n    t.a168 = 928;\n    t.a169 = 928;\n    t.a170 = 834;\n    t.a171 = 873;\n    t.a172 = 828;\n    t.a173 = 924;\n    t.a162 = 924;\n    t.a174 = 917;\n    t.a175 = 930;\n    t.a176 = 931;\n    t.a177 = 463;\n    t.a178 = 883;\n    t.a179 = 836;\n    t.a193 = 836;\n    t.a180 = 867;\n    t.a199 = 867;\n    t.a181 = 696;\n    t.a200 = 696;\n    t.a182 = 874;\n    t.a201 = 874;\n    t.a183 = 760;\n    t.a184 = 946;\n    t.a197 = 771;\n    t.a185 = 865;\n    t.a194 = 771;\n    t.a198 = 888;\n    t.a186 = 967;\n    t.a195 = 888;\n    t.a187 = 831;\n    t.a188 = 873;\n    t.a189 = 927;\n    t.a190 = 970;\n    t.a191 = 918;\n  });\n});\nconst getFontBasicMetrics = getLookupTableFactory(function (t) {\n  t.Courier = {\n    ascent: 629,\n    descent: -157,\n    capHeight: 562,\n    xHeight: -426\n  };\n  t[\"Courier-Bold\"] = {\n    ascent: 629,\n    descent: -157,\n    capHeight: 562,\n    xHeight: 439\n  };\n  t[\"Courier-Oblique\"] = {\n    ascent: 629,\n    descent: -157,\n    capHeight: 562,\n    xHeight: 426\n  };\n  t[\"Courier-BoldOblique\"] = {\n    ascent: 629,\n    descent: -157,\n    capHeight: 562,\n    xHeight: 426\n  };\n  t.Helvetica = {\n    ascent: 718,\n    descent: -207,\n    capHeight: 718,\n    xHeight: 523\n  };\n  t[\"Helvetica-Bold\"] = {\n    ascent: 718,\n    descent: -207,\n    capHeight: 718,\n    xHeight: 532\n  };\n  t[\"Helvetica-Oblique\"] = {\n    ascent: 718,\n    descent: -207,\n    capHeight: 718,\n    xHeight: 523\n  };\n  t[\"Helvetica-BoldOblique\"] = {\n    ascent: 718,\n    descent: -207,\n    capHeight: 718,\n    xHeight: 532\n  };\n  t[\"Times-Roman\"] = {\n    ascent: 683,\n    descent: -217,\n    capHeight: 662,\n    xHeight: 450\n  };\n  t[\"Times-Bold\"] = {\n    ascent: 683,\n    descent: -217,\n    capHeight: 676,\n    xHeight: 461\n  };\n  t[\"Times-Italic\"] = {\n    ascent: 683,\n    descent: -217,\n    capHeight: 653,\n    xHeight: 441\n  };\n  t[\"Times-BoldItalic\"] = {\n    ascent: 683,\n    descent: -217,\n    capHeight: 669,\n    xHeight: 462\n  };\n  t.Symbol = {\n    ascent: Math.NaN,\n    descent: Math.NaN,\n    capHeight: Math.NaN,\n    xHeight: Math.NaN\n  };\n  t.ZapfDingbats = {\n    ascent: Math.NaN,\n    descent: Math.NaN,\n    capHeight: Math.NaN,\n    xHeight: Math.NaN\n  };\n});\n\n;// CONCATENATED MODULE: ./src/core/glyf.js\nconst ON_CURVE_POINT = 1 << 0;\nconst X_SHORT_VECTOR = 1 << 1;\nconst Y_SHORT_VECTOR = 1 << 2;\nconst REPEAT_FLAG = 1 << 3;\nconst X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR = 1 << 4;\nconst Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR = 1 << 5;\nconst OVERLAP_SIMPLE = 1 << 6;\nconst ARG_1_AND_2_ARE_WORDS = 1 << 0;\nconst ARGS_ARE_XY_VALUES = 1 << 1;\nconst WE_HAVE_A_SCALE = 1 << 3;\nconst MORE_COMPONENTS = 1 << 5;\nconst WE_HAVE_AN_X_AND_Y_SCALE = 1 << 6;\nconst WE_HAVE_A_TWO_BY_TWO = 1 << 7;\nconst WE_HAVE_INSTRUCTIONS = 1 << 8;\nclass GlyfTable {\n  constructor({\n    glyfTable,\n    isGlyphLocationsLong,\n    locaTable,\n    numGlyphs\n  }) {\n    this.glyphs = [];\n    const loca = new DataView(locaTable.buffer, locaTable.byteOffset, locaTable.byteLength);\n    const glyf = new DataView(glyfTable.buffer, glyfTable.byteOffset, glyfTable.byteLength);\n    const offsetSize = isGlyphLocationsLong ? 4 : 2;\n    let prev = isGlyphLocationsLong ? loca.getUint32(0) : 2 * loca.getUint16(0);\n    let pos = 0;\n    for (let i = 0; i < numGlyphs; i++) {\n      pos += offsetSize;\n      const next = isGlyphLocationsLong ? loca.getUint32(pos) : 2 * loca.getUint16(pos);\n      if (next === prev) {\n        this.glyphs.push(new Glyph({}));\n        continue;\n      }\n      const glyph = Glyph.parse(prev, glyf);\n      this.glyphs.push(glyph);\n      prev = next;\n    }\n  }\n  getSize() {\n    return this.glyphs.reduce((a, g) => {\n      const size = g.getSize();\n      return a + (size + 3 & ~3);\n    }, 0);\n  }\n  write() {\n    const totalSize = this.getSize();\n    const glyfTable = new DataView(new ArrayBuffer(totalSize));\n    const isLocationLong = totalSize > 0x1fffe;\n    const offsetSize = isLocationLong ? 4 : 2;\n    const locaTable = new DataView(new ArrayBuffer((this.glyphs.length + 1) * offsetSize));\n    if (isLocationLong) {\n      locaTable.setUint32(0, 0);\n    } else {\n      locaTable.setUint16(0, 0);\n    }\n    let pos = 0;\n    let locaIndex = 0;\n    for (const glyph of this.glyphs) {\n      pos += glyph.write(pos, glyfTable);\n      pos = pos + 3 & ~3;\n      locaIndex += offsetSize;\n      if (isLocationLong) {\n        locaTable.setUint32(locaIndex, pos);\n      } else {\n        locaTable.setUint16(locaIndex, pos >> 1);\n      }\n    }\n    return {\n      isLocationLong,\n      loca: new Uint8Array(locaTable.buffer),\n      glyf: new Uint8Array(glyfTable.buffer)\n    };\n  }\n  scale(factors) {\n    for (let i = 0, ii = this.glyphs.length; i < ii; i++) {\n      this.glyphs[i].scale(factors[i]);\n    }\n  }\n}\nclass Glyph {\n  constructor({\n    header = null,\n    simple = null,\n    composites = null\n  }) {\n    this.header = header;\n    this.simple = simple;\n    this.composites = composites;\n  }\n  static parse(pos, glyf) {\n    const [read, header] = GlyphHeader.parse(pos, glyf);\n    pos += read;\n    if (header.numberOfContours < 0) {\n      const composites = [];\n      while (true) {\n        const [n, composite] = CompositeGlyph.parse(pos, glyf);\n        pos += n;\n        composites.push(composite);\n        if (!(composite.flags & MORE_COMPONENTS)) {\n          break;\n        }\n      }\n      return new Glyph({\n        header,\n        composites\n      });\n    }\n    const simple = SimpleGlyph.parse(pos, glyf, header.numberOfContours);\n    return new Glyph({\n      header,\n      simple\n    });\n  }\n  getSize() {\n    if (!this.header) {\n      return 0;\n    }\n    const size = this.simple ? this.simple.getSize() : this.composites.reduce((a, c) => a + c.getSize(), 0);\n    return this.header.getSize() + size;\n  }\n  write(pos, buf) {\n    if (!this.header) {\n      return 0;\n    }\n    const spos = pos;\n    pos += this.header.write(pos, buf);\n    if (this.simple) {\n      pos += this.simple.write(pos, buf);\n    } else {\n      for (const composite of this.composites) {\n        pos += composite.write(pos, buf);\n      }\n    }\n    return pos - spos;\n  }\n  scale(factor) {\n    if (!this.header) {\n      return;\n    }\n    const xMiddle = (this.header.xMin + this.header.xMax) / 2;\n    this.header.scale(xMiddle, factor);\n    if (this.simple) {\n      this.simple.scale(xMiddle, factor);\n    } else {\n      for (const composite of this.composites) {\n        composite.scale(xMiddle, factor);\n      }\n    }\n  }\n}\nclass GlyphHeader {\n  constructor({\n    numberOfContours,\n    xMin,\n    yMin,\n    xMax,\n    yMax\n  }) {\n    this.numberOfContours = numberOfContours;\n    this.xMin = xMin;\n    this.yMin = yMin;\n    this.xMax = xMax;\n    this.yMax = yMax;\n  }\n  static parse(pos, glyf) {\n    return [10, new GlyphHeader({\n      numberOfContours: glyf.getInt16(pos),\n      xMin: glyf.getInt16(pos + 2),\n      yMin: glyf.getInt16(pos + 4),\n      xMax: glyf.getInt16(pos + 6),\n      yMax: glyf.getInt16(pos + 8)\n    })];\n  }\n  getSize() {\n    return 10;\n  }\n  write(pos, buf) {\n    buf.setInt16(pos, this.numberOfContours);\n    buf.setInt16(pos + 2, this.xMin);\n    buf.setInt16(pos + 4, this.yMin);\n    buf.setInt16(pos + 6, this.xMax);\n    buf.setInt16(pos + 8, this.yMax);\n    return 10;\n  }\n  scale(x, factor) {\n    this.xMin = Math.round(x + (this.xMin - x) * factor);\n    this.xMax = Math.round(x + (this.xMax - x) * factor);\n  }\n}\nclass Contour {\n  constructor({\n    flags,\n    xCoordinates,\n    yCoordinates\n  }) {\n    this.xCoordinates = xCoordinates;\n    this.yCoordinates = yCoordinates;\n    this.flags = flags;\n  }\n}\nclass SimpleGlyph {\n  constructor({\n    contours,\n    instructions\n  }) {\n    this.contours = contours;\n    this.instructions = instructions;\n  }\n  static parse(pos, glyf, numberOfContours) {\n    const endPtsOfContours = [];\n    for (let i = 0; i < numberOfContours; i++) {\n      const endPt = glyf.getUint16(pos);\n      pos += 2;\n      endPtsOfContours.push(endPt);\n    }\n    const numberOfPt = endPtsOfContours[numberOfContours - 1] + 1;\n    const instructionLength = glyf.getUint16(pos);\n    pos += 2;\n    const instructions = new Uint8Array(glyf).slice(pos, pos + instructionLength);\n    pos += instructionLength;\n    const flags = [];\n    for (let i = 0; i < numberOfPt; pos++, i++) {\n      let flag = glyf.getUint8(pos);\n      flags.push(flag);\n      if (flag & REPEAT_FLAG) {\n        const count = glyf.getUint8(++pos);\n        flag ^= REPEAT_FLAG;\n        for (let m = 0; m < count; m++) {\n          flags.push(flag);\n        }\n        i += count;\n      }\n    }\n    const allXCoordinates = [];\n    let xCoordinates = [];\n    let yCoordinates = [];\n    let pointFlags = [];\n    const contours = [];\n    let endPtsOfContoursIndex = 0;\n    let lastCoordinate = 0;\n    for (let i = 0; i < numberOfPt; i++) {\n      const flag = flags[i];\n      if (flag & X_SHORT_VECTOR) {\n        const x = glyf.getUint8(pos++);\n        lastCoordinate += flag & X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR ? x : -x;\n        xCoordinates.push(lastCoordinate);\n      } else if (flag & X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) {\n        xCoordinates.push(lastCoordinate);\n      } else {\n        lastCoordinate += glyf.getInt16(pos);\n        pos += 2;\n        xCoordinates.push(lastCoordinate);\n      }\n      if (endPtsOfContours[endPtsOfContoursIndex] === i) {\n        endPtsOfContoursIndex++;\n        allXCoordinates.push(xCoordinates);\n        xCoordinates = [];\n      }\n    }\n    lastCoordinate = 0;\n    endPtsOfContoursIndex = 0;\n    for (let i = 0; i < numberOfPt; i++) {\n      const flag = flags[i];\n      if (flag & Y_SHORT_VECTOR) {\n        const y = glyf.getUint8(pos++);\n        lastCoordinate += flag & Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR ? y : -y;\n        yCoordinates.push(lastCoordinate);\n      } else if (flag & Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) {\n        yCoordinates.push(lastCoordinate);\n      } else {\n        lastCoordinate += glyf.getInt16(pos);\n        pos += 2;\n        yCoordinates.push(lastCoordinate);\n      }\n      pointFlags.push(flag & ON_CURVE_POINT | flag & OVERLAP_SIMPLE);\n      if (endPtsOfContours[endPtsOfContoursIndex] === i) {\n        xCoordinates = allXCoordinates[endPtsOfContoursIndex];\n        endPtsOfContoursIndex++;\n        contours.push(new Contour({\n          flags: pointFlags,\n          xCoordinates,\n          yCoordinates\n        }));\n        yCoordinates = [];\n        pointFlags = [];\n      }\n    }\n    return new SimpleGlyph({\n      contours,\n      instructions\n    });\n  }\n  getSize() {\n    let size = this.contours.length * 2 + 2 + this.instructions.length;\n    let lastX = 0;\n    let lastY = 0;\n    for (const contour of this.contours) {\n      size += contour.flags.length;\n      for (let i = 0, ii = contour.xCoordinates.length; i < ii; i++) {\n        const x = contour.xCoordinates[i];\n        const y = contour.yCoordinates[i];\n        let abs = Math.abs(x - lastX);\n        if (abs > 255) {\n          size += 2;\n        } else if (abs > 0) {\n          size += 1;\n        }\n        lastX = x;\n        abs = Math.abs(y - lastY);\n        if (abs > 255) {\n          size += 2;\n        } else if (abs > 0) {\n          size += 1;\n        }\n        lastY = y;\n      }\n    }\n    return size;\n  }\n  write(pos, buf) {\n    const spos = pos;\n    const xCoordinates = [];\n    const yCoordinates = [];\n    const flags = [];\n    let lastX = 0;\n    let lastY = 0;\n    for (const contour of this.contours) {\n      for (let i = 0, ii = contour.xCoordinates.length; i < ii; i++) {\n        let flag = contour.flags[i];\n        const x = contour.xCoordinates[i];\n        let delta = x - lastX;\n        if (delta === 0) {\n          flag |= X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR;\n          xCoordinates.push(0);\n        } else {\n          const abs = Math.abs(delta);\n          if (abs <= 255) {\n            flag |= delta >= 0 ? X_SHORT_VECTOR | X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR : X_SHORT_VECTOR;\n            xCoordinates.push(abs);\n          } else {\n            xCoordinates.push(delta);\n          }\n        }\n        lastX = x;\n        const y = contour.yCoordinates[i];\n        delta = y - lastY;\n        if (delta === 0) {\n          flag |= Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR;\n          yCoordinates.push(0);\n        } else {\n          const abs = Math.abs(delta);\n          if (abs <= 255) {\n            flag |= delta >= 0 ? Y_SHORT_VECTOR | Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR : Y_SHORT_VECTOR;\n            yCoordinates.push(abs);\n          } else {\n            yCoordinates.push(delta);\n          }\n        }\n        lastY = y;\n        flags.push(flag);\n      }\n      buf.setUint16(pos, xCoordinates.length - 1);\n      pos += 2;\n    }\n    buf.setUint16(pos, this.instructions.length);\n    pos += 2;\n    if (this.instructions.length) {\n      new Uint8Array(buf.buffer, 0, buf.buffer.byteLength).set(this.instructions, pos);\n      pos += this.instructions.length;\n    }\n    for (const flag of flags) {\n      buf.setUint8(pos++, flag);\n    }\n    for (let i = 0, ii = xCoordinates.length; i < ii; i++) {\n      const x = xCoordinates[i];\n      const flag = flags[i];\n      if (flag & X_SHORT_VECTOR) {\n        buf.setUint8(pos++, x);\n      } else if (!(flag & X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR)) {\n        buf.setInt16(pos, x);\n        pos += 2;\n      }\n    }\n    for (let i = 0, ii = yCoordinates.length; i < ii; i++) {\n      const y = yCoordinates[i];\n      const flag = flags[i];\n      if (flag & Y_SHORT_VECTOR) {\n        buf.setUint8(pos++, y);\n      } else if (!(flag & Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR)) {\n        buf.setInt16(pos, y);\n        pos += 2;\n      }\n    }\n    return pos - spos;\n  }\n  scale(x, factor) {\n    for (const contour of this.contours) {\n      if (contour.xCoordinates.length === 0) {\n        continue;\n      }\n      for (let i = 0, ii = contour.xCoordinates.length; i < ii; i++) {\n        contour.xCoordinates[i] = Math.round(x + (contour.xCoordinates[i] - x) * factor);\n      }\n    }\n  }\n}\nclass CompositeGlyph {\n  constructor({\n    flags,\n    glyphIndex,\n    argument1,\n    argument2,\n    transf,\n    instructions\n  }) {\n    this.flags = flags;\n    this.glyphIndex = glyphIndex;\n    this.argument1 = argument1;\n    this.argument2 = argument2;\n    this.transf = transf;\n    this.instructions = instructions;\n  }\n  static parse(pos, glyf) {\n    const spos = pos;\n    const transf = [];\n    let flags = glyf.getUint16(pos);\n    const glyphIndex = glyf.getUint16(pos + 2);\n    pos += 4;\n    let argument1, argument2;\n    if (flags & ARG_1_AND_2_ARE_WORDS) {\n      if (flags & ARGS_ARE_XY_VALUES) {\n        argument1 = glyf.getInt16(pos);\n        argument2 = glyf.getInt16(pos + 2);\n      } else {\n        argument1 = glyf.getUint16(pos);\n        argument2 = glyf.getUint16(pos + 2);\n      }\n      pos += 4;\n      flags ^= ARG_1_AND_2_ARE_WORDS;\n    } else {\n      if (flags & ARGS_ARE_XY_VALUES) {\n        argument1 = glyf.getInt8(pos);\n        argument2 = glyf.getInt8(pos + 1);\n      } else {\n        argument1 = glyf.getUint8(pos);\n        argument2 = glyf.getUint8(pos + 1);\n      }\n      pos += 2;\n    }\n    if (flags & WE_HAVE_A_SCALE) {\n      transf.push(glyf.getUint16(pos));\n      pos += 2;\n    } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {\n      transf.push(glyf.getUint16(pos), glyf.getUint16(pos + 2));\n      pos += 4;\n    } else if (flags & WE_HAVE_A_TWO_BY_TWO) {\n      transf.push(glyf.getUint16(pos), glyf.getUint16(pos + 2), glyf.getUint16(pos + 4), glyf.getUint16(pos + 6));\n      pos += 8;\n    }\n    let instructions = null;\n    if (flags & WE_HAVE_INSTRUCTIONS) {\n      const instructionLength = glyf.getUint16(pos);\n      pos += 2;\n      instructions = new Uint8Array(glyf).slice(pos, pos + instructionLength);\n      pos += instructionLength;\n    }\n    return [pos - spos, new CompositeGlyph({\n      flags,\n      glyphIndex,\n      argument1,\n      argument2,\n      transf,\n      instructions\n    })];\n  }\n  getSize() {\n    let size = 2 + 2 + this.transf.length * 2;\n    if (this.flags & WE_HAVE_INSTRUCTIONS) {\n      size += 2 + this.instructions.length;\n    }\n    size += 2;\n    if (this.flags & 2) {\n      if (!(this.argument1 >= -128 && this.argument1 <= 127 && this.argument2 >= -128 && this.argument2 <= 127)) {\n        size += 2;\n      }\n    } else if (!(this.argument1 >= 0 && this.argument1 <= 255 && this.argument2 >= 0 && this.argument2 <= 255)) {\n      size += 2;\n    }\n    return size;\n  }\n  write(pos, buf) {\n    const spos = pos;\n    if (this.flags & ARGS_ARE_XY_VALUES) {\n      if (!(this.argument1 >= -128 && this.argument1 <= 127 && this.argument2 >= -128 && this.argument2 <= 127)) {\n        this.flags |= ARG_1_AND_2_ARE_WORDS;\n      }\n    } else if (!(this.argument1 >= 0 && this.argument1 <= 255 && this.argument2 >= 0 && this.argument2 <= 255)) {\n      this.flags |= ARG_1_AND_2_ARE_WORDS;\n    }\n    buf.setUint16(pos, this.flags);\n    buf.setUint16(pos + 2, this.glyphIndex);\n    pos += 4;\n    if (this.flags & ARG_1_AND_2_ARE_WORDS) {\n      if (this.flags & ARGS_ARE_XY_VALUES) {\n        buf.setInt16(pos, this.argument1);\n        buf.setInt16(pos + 2, this.argument2);\n      } else {\n        buf.setUint16(pos, this.argument1);\n        buf.setUint16(pos + 2, this.argument2);\n      }\n      pos += 4;\n    } else {\n      buf.setUint8(pos, this.argument1);\n      buf.setUint8(pos + 1, this.argument2);\n      pos += 2;\n    }\n    if (this.flags & WE_HAVE_INSTRUCTIONS) {\n      buf.setUint16(pos, this.instructions.length);\n      pos += 2;\n      if (this.instructions.length) {\n        new Uint8Array(buf.buffer, 0, buf.buffer.byteLength).set(this.instructions, pos);\n        pos += this.instructions.length;\n      }\n    }\n    return pos - spos;\n  }\n  scale(x, factor) {}\n}\n\n;// CONCATENATED MODULE: ./src/core/opentype_file_builder.js\n\n\nfunction writeInt16(dest, offset, num) {\n  dest[offset] = num >> 8 & 0xff;\n  dest[offset + 1] = num & 0xff;\n}\nfunction writeInt32(dest, offset, num) {\n  dest[offset] = num >> 24 & 0xff;\n  dest[offset + 1] = num >> 16 & 0xff;\n  dest[offset + 2] = num >> 8 & 0xff;\n  dest[offset + 3] = num & 0xff;\n}\nfunction writeData(dest, offset, data) {\n  if (data instanceof Uint8Array) {\n    dest.set(data, offset);\n  } else if (typeof data === \"string\") {\n    for (let i = 0, ii = data.length; i < ii; i++) {\n      dest[offset++] = data.charCodeAt(i) & 0xff;\n    }\n  } else {\n    for (const num of data) {\n      dest[offset++] = num & 0xff;\n    }\n  }\n}\nconst OTF_HEADER_SIZE = 12;\nconst OTF_TABLE_ENTRY_SIZE = 16;\nclass OpenTypeFileBuilder {\n  constructor(sfnt) {\n    this.sfnt = sfnt;\n    this.tables = Object.create(null);\n  }\n  static getSearchParams(entriesCount, entrySize) {\n    let maxPower2 = 1,\n      log2 = 0;\n    while ((maxPower2 ^ entriesCount) > maxPower2) {\n      maxPower2 <<= 1;\n      log2++;\n    }\n    const searchRange = maxPower2 * entrySize;\n    return {\n      range: searchRange,\n      entry: log2,\n      rangeShift: entrySize * entriesCount - searchRange\n    };\n  }\n  toArray() {\n    let sfnt = this.sfnt;\n    const tables = this.tables;\n    const tablesNames = Object.keys(tables);\n    tablesNames.sort();\n    const numTables = tablesNames.length;\n    let i, j, jj, table, tableName;\n    let offset = OTF_HEADER_SIZE + numTables * OTF_TABLE_ENTRY_SIZE;\n    const tableOffsets = [offset];\n    for (i = 0; i < numTables; i++) {\n      table = tables[tablesNames[i]];\n      const paddedLength = (table.length + 3 & ~3) >>> 0;\n      offset += paddedLength;\n      tableOffsets.push(offset);\n    }\n    const file = new Uint8Array(offset);\n    for (i = 0; i < numTables; i++) {\n      table = tables[tablesNames[i]];\n      writeData(file, tableOffsets[i], table);\n    }\n    if (sfnt === \"true\") {\n      sfnt = string32(0x00010000);\n    }\n    file[0] = sfnt.charCodeAt(0) & 0xff;\n    file[1] = sfnt.charCodeAt(1) & 0xff;\n    file[2] = sfnt.charCodeAt(2) & 0xff;\n    file[3] = sfnt.charCodeAt(3) & 0xff;\n    writeInt16(file, 4, numTables);\n    const searchParams = OpenTypeFileBuilder.getSearchParams(numTables, 16);\n    writeInt16(file, 6, searchParams.range);\n    writeInt16(file, 8, searchParams.entry);\n    writeInt16(file, 10, searchParams.rangeShift);\n    offset = OTF_HEADER_SIZE;\n    for (i = 0; i < numTables; i++) {\n      tableName = tablesNames[i];\n      file[offset] = tableName.charCodeAt(0) & 0xff;\n      file[offset + 1] = tableName.charCodeAt(1) & 0xff;\n      file[offset + 2] = tableName.charCodeAt(2) & 0xff;\n      file[offset + 3] = tableName.charCodeAt(3) & 0xff;\n      let checksum = 0;\n      for (j = tableOffsets[i], jj = tableOffsets[i + 1]; j < jj; j += 4) {\n        const quad = readUint32(file, j);\n        checksum = checksum + quad >>> 0;\n      }\n      writeInt32(file, offset + 4, checksum);\n      writeInt32(file, offset + 8, tableOffsets[i]);\n      writeInt32(file, offset + 12, tables[tableName].length);\n      offset += OTF_TABLE_ENTRY_SIZE;\n    }\n    return file;\n  }\n  addTable(tag, data) {\n    if (tag in this.tables) {\n      throw new Error(\"Table \" + tag + \" already exists\");\n    }\n    this.tables[tag] = data;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/type1_parser.js\n\n\n\n\nconst HINTING_ENABLED = false;\nconst COMMAND_MAP = {\n  hstem: [1],\n  vstem: [3],\n  vmoveto: [4],\n  rlineto: [5],\n  hlineto: [6],\n  vlineto: [7],\n  rrcurveto: [8],\n  callsubr: [10],\n  flex: [12, 35],\n  drop: [12, 18],\n  endchar: [14],\n  rmoveto: [21],\n  hmoveto: [22],\n  vhcurveto: [30],\n  hvcurveto: [31]\n};\nclass Type1CharString {\n  constructor() {\n    this.width = 0;\n    this.lsb = 0;\n    this.flexing = false;\n    this.output = [];\n    this.stack = [];\n  }\n  convert(encoded, subrs, seacAnalysisEnabled) {\n    const count = encoded.length;\n    let error = false;\n    let wx, sbx, subrNumber;\n    for (let i = 0; i < count; i++) {\n      let value = encoded[i];\n      if (value < 32) {\n        if (value === 12) {\n          value = (value << 8) + encoded[++i];\n        }\n        switch (value) {\n          case 1:\n            if (!HINTING_ENABLED) {\n              this.stack = [];\n              break;\n            }\n            error = this.executeCommand(2, COMMAND_MAP.hstem);\n            break;\n          case 3:\n            if (!HINTING_ENABLED) {\n              this.stack = [];\n              break;\n            }\n            error = this.executeCommand(2, COMMAND_MAP.vstem);\n            break;\n          case 4:\n            if (this.flexing) {\n              if (this.stack.length < 1) {\n                error = true;\n                break;\n              }\n              const dy = this.stack.pop();\n              this.stack.push(0, dy);\n              break;\n            }\n            error = this.executeCommand(1, COMMAND_MAP.vmoveto);\n            break;\n          case 5:\n            error = this.executeCommand(2, COMMAND_MAP.rlineto);\n            break;\n          case 6:\n            error = this.executeCommand(1, COMMAND_MAP.hlineto);\n            break;\n          case 7:\n            error = this.executeCommand(1, COMMAND_MAP.vlineto);\n            break;\n          case 8:\n            error = this.executeCommand(6, COMMAND_MAP.rrcurveto);\n            break;\n          case 9:\n            this.stack = [];\n            break;\n          case 10:\n            if (this.stack.length < 1) {\n              error = true;\n              break;\n            }\n            subrNumber = this.stack.pop();\n            if (!subrs[subrNumber]) {\n              error = true;\n              break;\n            }\n            error = this.convert(subrs[subrNumber], subrs, seacAnalysisEnabled);\n            break;\n          case 11:\n            return error;\n          case 13:\n            if (this.stack.length < 2) {\n              error = true;\n              break;\n            }\n            wx = this.stack.pop();\n            sbx = this.stack.pop();\n            this.lsb = sbx;\n            this.width = wx;\n            this.stack.push(wx, sbx);\n            error = this.executeCommand(2, COMMAND_MAP.hmoveto);\n            break;\n          case 14:\n            this.output.push(COMMAND_MAP.endchar[0]);\n            break;\n          case 21:\n            if (this.flexing) {\n              break;\n            }\n            error = this.executeCommand(2, COMMAND_MAP.rmoveto);\n            break;\n          case 22:\n            if (this.flexing) {\n              this.stack.push(0);\n              break;\n            }\n            error = this.executeCommand(1, COMMAND_MAP.hmoveto);\n            break;\n          case 30:\n            error = this.executeCommand(4, COMMAND_MAP.vhcurveto);\n            break;\n          case 31:\n            error = this.executeCommand(4, COMMAND_MAP.hvcurveto);\n            break;\n          case (12 << 8) + 0:\n            this.stack = [];\n            break;\n          case (12 << 8) + 1:\n            if (!HINTING_ENABLED) {\n              this.stack = [];\n              break;\n            }\n            error = this.executeCommand(2, COMMAND_MAP.vstem);\n            break;\n          case (12 << 8) + 2:\n            if (!HINTING_ENABLED) {\n              this.stack = [];\n              break;\n            }\n            error = this.executeCommand(2, COMMAND_MAP.hstem);\n            break;\n          case (12 << 8) + 6:\n            if (seacAnalysisEnabled) {\n              const asb = this.stack.at(-5);\n              this.seac = this.stack.splice(-4, 4);\n              this.seac[0] += this.lsb - asb;\n              error = this.executeCommand(0, COMMAND_MAP.endchar);\n            } else {\n              error = this.executeCommand(4, COMMAND_MAP.endchar);\n            }\n            break;\n          case (12 << 8) + 7:\n            if (this.stack.length < 4) {\n              error = true;\n              break;\n            }\n            this.stack.pop();\n            wx = this.stack.pop();\n            const sby = this.stack.pop();\n            sbx = this.stack.pop();\n            this.lsb = sbx;\n            this.width = wx;\n            this.stack.push(wx, sbx, sby);\n            error = this.executeCommand(3, COMMAND_MAP.rmoveto);\n            break;\n          case (12 << 8) + 12:\n            if (this.stack.length < 2) {\n              error = true;\n              break;\n            }\n            const num2 = this.stack.pop();\n            const num1 = this.stack.pop();\n            this.stack.push(num1 / num2);\n            break;\n          case (12 << 8) + 16:\n            if (this.stack.length < 2) {\n              error = true;\n              break;\n            }\n            subrNumber = this.stack.pop();\n            const numArgs = this.stack.pop();\n            if (subrNumber === 0 && numArgs === 3) {\n              const flexArgs = this.stack.splice(-17, 17);\n              this.stack.push(flexArgs[2] + flexArgs[0], flexArgs[3] + flexArgs[1], flexArgs[4], flexArgs[5], flexArgs[6], flexArgs[7], flexArgs[8], flexArgs[9], flexArgs[10], flexArgs[11], flexArgs[12], flexArgs[13], flexArgs[14]);\n              error = this.executeCommand(13, COMMAND_MAP.flex, true);\n              this.flexing = false;\n              this.stack.push(flexArgs[15], flexArgs[16]);\n            } else if (subrNumber === 1 && numArgs === 0) {\n              this.flexing = true;\n            }\n            break;\n          case (12 << 8) + 17:\n            break;\n          case (12 << 8) + 33:\n            this.stack = [];\n            break;\n          default:\n            warn('Unknown type 1 charstring command of \"' + value + '\"');\n            break;\n        }\n        if (error) {\n          break;\n        }\n        continue;\n      } else if (value <= 246) {\n        value -= 139;\n      } else if (value <= 250) {\n        value = (value - 247) * 256 + encoded[++i] + 108;\n      } else if (value <= 254) {\n        value = -((value - 251) * 256) - encoded[++i] - 108;\n      } else {\n        value = (encoded[++i] & 0xff) << 24 | (encoded[++i] & 0xff) << 16 | (encoded[++i] & 0xff) << 8 | (encoded[++i] & 0xff) << 0;\n      }\n      this.stack.push(value);\n    }\n    return error;\n  }\n  executeCommand(howManyArgs, command, keepStack) {\n    const stackLength = this.stack.length;\n    if (howManyArgs > stackLength) {\n      return true;\n    }\n    const start = stackLength - howManyArgs;\n    for (let i = start; i < stackLength; i++) {\n      let value = this.stack[i];\n      if (Number.isInteger(value)) {\n        this.output.push(28, value >> 8 & 0xff, value & 0xff);\n      } else {\n        value = 65536 * value | 0;\n        this.output.push(255, value >> 24 & 0xff, value >> 16 & 0xff, value >> 8 & 0xff, value & 0xff);\n      }\n    }\n    this.output.push(...command);\n    if (keepStack) {\n      this.stack.splice(start, howManyArgs);\n    } else {\n      this.stack.length = 0;\n    }\n    return false;\n  }\n}\nconst EEXEC_ENCRYPT_KEY = 55665;\nconst CHAR_STRS_ENCRYPT_KEY = 4330;\nfunction isHexDigit(code) {\n  return code >= 48 && code <= 57 || code >= 65 && code <= 70 || code >= 97 && code <= 102;\n}\nfunction decrypt(data, key, discardNumber) {\n  if (discardNumber >= data.length) {\n    return new Uint8Array(0);\n  }\n  const c1 = 52845,\n    c2 = 22719;\n  let r = key | 0,\n    i,\n    j;\n  for (i = 0; i < discardNumber; i++) {\n    r = (data[i] + r) * c1 + c2 & (1 << 16) - 1;\n  }\n  const count = data.length - discardNumber;\n  const decrypted = new Uint8Array(count);\n  for (i = discardNumber, j = 0; j < count; i++, j++) {\n    const value = data[i];\n    decrypted[j] = value ^ r >> 8;\n    r = (value + r) * c1 + c2 & (1 << 16) - 1;\n  }\n  return decrypted;\n}\nfunction decryptAscii(data, key, discardNumber) {\n  const c1 = 52845,\n    c2 = 22719;\n  let r = key | 0;\n  const count = data.length,\n    maybeLength = count >>> 1;\n  const decrypted = new Uint8Array(maybeLength);\n  let i, j;\n  for (i = 0, j = 0; i < count; i++) {\n    const digit1 = data[i];\n    if (!isHexDigit(digit1)) {\n      continue;\n    }\n    i++;\n    let digit2;\n    while (i < count && !isHexDigit(digit2 = data[i])) {\n      i++;\n    }\n    if (i < count) {\n      const value = parseInt(String.fromCharCode(digit1, digit2), 16);\n      decrypted[j++] = value ^ r >> 8;\n      r = (value + r) * c1 + c2 & (1 << 16) - 1;\n    }\n  }\n  return decrypted.slice(discardNumber, j);\n}\nfunction isSpecial(c) {\n  return c === 0x2f || c === 0x5b || c === 0x5d || c === 0x7b || c === 0x7d || c === 0x28 || c === 0x29;\n}\nclass Type1Parser {\n  constructor(stream, encrypted, seacAnalysisEnabled) {\n    if (encrypted) {\n      const data = stream.getBytes();\n      const isBinary = !((isHexDigit(data[0]) || isWhiteSpace(data[0])) && isHexDigit(data[1]) && isHexDigit(data[2]) && isHexDigit(data[3]) && isHexDigit(data[4]) && isHexDigit(data[5]) && isHexDigit(data[6]) && isHexDigit(data[7]));\n      stream = new Stream(isBinary ? decrypt(data, EEXEC_ENCRYPT_KEY, 4) : decryptAscii(data, EEXEC_ENCRYPT_KEY, 4));\n    }\n    this.seacAnalysisEnabled = !!seacAnalysisEnabled;\n    this.stream = stream;\n    this.nextChar();\n  }\n  readNumberArray() {\n    this.getToken();\n    const array = [];\n    while (true) {\n      const token = this.getToken();\n      if (token === null || token === \"]\" || token === \"}\") {\n        break;\n      }\n      array.push(parseFloat(token || 0));\n    }\n    return array;\n  }\n  readNumber() {\n    const token = this.getToken();\n    return parseFloat(token || 0);\n  }\n  readInt() {\n    const token = this.getToken();\n    return parseInt(token || 0, 10) | 0;\n  }\n  readBoolean() {\n    const token = this.getToken();\n    return token === \"true\" ? 1 : 0;\n  }\n  nextChar() {\n    return this.currentChar = this.stream.getByte();\n  }\n  prevChar() {\n    this.stream.skip(-2);\n    return this.currentChar = this.stream.getByte();\n  }\n  getToken() {\n    let comment = false;\n    let ch = this.currentChar;\n    while (true) {\n      if (ch === -1) {\n        return null;\n      }\n      if (comment) {\n        if (ch === 0x0a || ch === 0x0d) {\n          comment = false;\n        }\n      } else if (ch === 0x25) {\n        comment = true;\n      } else if (!isWhiteSpace(ch)) {\n        break;\n      }\n      ch = this.nextChar();\n    }\n    if (isSpecial(ch)) {\n      this.nextChar();\n      return String.fromCharCode(ch);\n    }\n    let token = \"\";\n    do {\n      token += String.fromCharCode(ch);\n      ch = this.nextChar();\n    } while (ch >= 0 && !isWhiteSpace(ch) && !isSpecial(ch));\n    return token;\n  }\n  readCharStrings(bytes, lenIV) {\n    if (lenIV === -1) {\n      return bytes;\n    }\n    return decrypt(bytes, CHAR_STRS_ENCRYPT_KEY, lenIV);\n  }\n  extractFontProgram(properties) {\n    const stream = this.stream;\n    const subrs = [],\n      charstrings = [];\n    const privateData = Object.create(null);\n    privateData.lenIV = 4;\n    const program = {\n      subrs: [],\n      charstrings: [],\n      properties: {\n        privateData\n      }\n    };\n    let token, length, data, lenIV;\n    while ((token = this.getToken()) !== null) {\n      if (token !== \"/\") {\n        continue;\n      }\n      token = this.getToken();\n      switch (token) {\n        case \"CharStrings\":\n          this.getToken();\n          this.getToken();\n          this.getToken();\n          this.getToken();\n          while (true) {\n            token = this.getToken();\n            if (token === null || token === \"end\") {\n              break;\n            }\n            if (token !== \"/\") {\n              continue;\n            }\n            const glyph = this.getToken();\n            length = this.readInt();\n            this.getToken();\n            data = length > 0 ? stream.getBytes(length) : new Uint8Array(0);\n            lenIV = program.properties.privateData.lenIV;\n            const encoded = this.readCharStrings(data, lenIV);\n            this.nextChar();\n            token = this.getToken();\n            if (token === \"noaccess\") {\n              this.getToken();\n            } else if (token === \"/\") {\n              this.prevChar();\n            }\n            charstrings.push({\n              glyph,\n              encoded\n            });\n          }\n          break;\n        case \"Subrs\":\n          this.readInt();\n          this.getToken();\n          while (this.getToken() === \"dup\") {\n            const index = this.readInt();\n            length = this.readInt();\n            this.getToken();\n            data = length > 0 ? stream.getBytes(length) : new Uint8Array(0);\n            lenIV = program.properties.privateData.lenIV;\n            const encoded = this.readCharStrings(data, lenIV);\n            this.nextChar();\n            token = this.getToken();\n            if (token === \"noaccess\") {\n              this.getToken();\n            }\n            subrs[index] = encoded;\n          }\n          break;\n        case \"BlueValues\":\n        case \"OtherBlues\":\n        case \"FamilyBlues\":\n        case \"FamilyOtherBlues\":\n          const blueArray = this.readNumberArray();\n          if (blueArray.length > 0 && blueArray.length % 2 === 0 && HINTING_ENABLED) {\n            program.properties.privateData[token] = blueArray;\n          }\n          break;\n        case \"StemSnapH\":\n        case \"StemSnapV\":\n          program.properties.privateData[token] = this.readNumberArray();\n          break;\n        case \"StdHW\":\n        case \"StdVW\":\n          program.properties.privateData[token] = this.readNumberArray()[0];\n          break;\n        case \"BlueShift\":\n        case \"lenIV\":\n        case \"BlueFuzz\":\n        case \"BlueScale\":\n        case \"LanguageGroup\":\n          program.properties.privateData[token] = this.readNumber();\n          break;\n        case \"ExpansionFactor\":\n          program.properties.privateData[token] = this.readNumber() || 0.06;\n          break;\n        case \"ForceBold\":\n          program.properties.privateData[token] = this.readBoolean();\n          break;\n      }\n    }\n    for (const {\n      encoded,\n      glyph\n    } of charstrings) {\n      const charString = new Type1CharString();\n      const error = charString.convert(encoded, subrs, this.seacAnalysisEnabled);\n      let output = charString.output;\n      if (error) {\n        output = [14];\n      }\n      const charStringObject = {\n        glyphName: glyph,\n        charstring: output,\n        width: charString.width,\n        lsb: charString.lsb,\n        seac: charString.seac\n      };\n      if (glyph === \".notdef\") {\n        program.charstrings.unshift(charStringObject);\n      } else {\n        program.charstrings.push(charStringObject);\n      }\n      if (properties.builtInEncoding) {\n        const index = properties.builtInEncoding.indexOf(glyph);\n        if (index > -1 && properties.widths[index] === undefined && index >= properties.firstChar && index <= properties.lastChar) {\n          properties.widths[index] = charString.width;\n        }\n      }\n    }\n    return program;\n  }\n  extractFontHeader(properties) {\n    let token;\n    while ((token = this.getToken()) !== null) {\n      if (token !== \"/\") {\n        continue;\n      }\n      token = this.getToken();\n      switch (token) {\n        case \"FontMatrix\":\n          const matrix = this.readNumberArray();\n          properties.fontMatrix = matrix;\n          break;\n        case \"Encoding\":\n          const encodingArg = this.getToken();\n          let encoding;\n          if (!/^\\d+$/.test(encodingArg)) {\n            encoding = getEncoding(encodingArg);\n          } else {\n            encoding = [];\n            const size = parseInt(encodingArg, 10) | 0;\n            this.getToken();\n            for (let j = 0; j < size; j++) {\n              token = this.getToken();\n              while (token !== \"dup\" && token !== \"def\") {\n                token = this.getToken();\n                if (token === null) {\n                  return;\n                }\n              }\n              if (token === \"def\") {\n                break;\n              }\n              const index = this.readInt();\n              this.getToken();\n              const glyph = this.getToken();\n              encoding[index] = glyph;\n              this.getToken();\n            }\n          }\n          properties.builtInEncoding = encoding;\n          break;\n        case \"FontBBox\":\n          const fontBBox = this.readNumberArray();\n          properties.ascent = Math.max(fontBBox[3], fontBBox[1]);\n          properties.descent = Math.min(fontBBox[1], fontBBox[3]);\n          properties.ascentScaled = true;\n          break;\n      }\n    }\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/type1_font.js\n\n\n\n\n\n\nfunction findBlock(streamBytes, signature, startIndex) {\n  const streamBytesLength = streamBytes.length;\n  const signatureLength = signature.length;\n  const scanLength = streamBytesLength - signatureLength;\n  let i = startIndex,\n    found = false;\n  while (i < scanLength) {\n    let j = 0;\n    while (j < signatureLength && streamBytes[i + j] === signature[j]) {\n      j++;\n    }\n    if (j >= signatureLength) {\n      i += j;\n      while (i < streamBytesLength && isWhiteSpace(streamBytes[i])) {\n        i++;\n      }\n      found = true;\n      break;\n    }\n    i++;\n  }\n  return {\n    found,\n    length: i\n  };\n}\nfunction getHeaderBlock(stream, suggestedLength) {\n  const EEXEC_SIGNATURE = [0x65, 0x65, 0x78, 0x65, 0x63];\n  const streamStartPos = stream.pos;\n  let headerBytes, headerBytesLength, block;\n  try {\n    headerBytes = stream.getBytes(suggestedLength);\n    headerBytesLength = headerBytes.length;\n  } catch {}\n  if (headerBytesLength === suggestedLength) {\n    block = findBlock(headerBytes, EEXEC_SIGNATURE, suggestedLength - 2 * EEXEC_SIGNATURE.length);\n    if (block.found && block.length === suggestedLength) {\n      return {\n        stream: new Stream(headerBytes),\n        length: suggestedLength\n      };\n    }\n  }\n  warn('Invalid \"Length1\" property in Type1 font -- trying to recover.');\n  stream.pos = streamStartPos;\n  const SCAN_BLOCK_LENGTH = 2048;\n  let actualLength;\n  while (true) {\n    const scanBytes = stream.peekBytes(SCAN_BLOCK_LENGTH);\n    block = findBlock(scanBytes, EEXEC_SIGNATURE, 0);\n    if (block.length === 0) {\n      break;\n    }\n    stream.pos += block.length;\n    if (block.found) {\n      actualLength = stream.pos - streamStartPos;\n      break;\n    }\n  }\n  stream.pos = streamStartPos;\n  if (actualLength) {\n    return {\n      stream: new Stream(stream.getBytes(actualLength)),\n      length: actualLength\n    };\n  }\n  warn('Unable to recover \"Length1\" property in Type1 font -- using as is.');\n  return {\n    stream: new Stream(stream.getBytes(suggestedLength)),\n    length: suggestedLength\n  };\n}\nfunction getEexecBlock(stream, suggestedLength) {\n  const eexecBytes = stream.getBytes();\n  if (eexecBytes.length === 0) {\n    throw new FormatError(\"getEexecBlock - no font program found.\");\n  }\n  return {\n    stream: new Stream(eexecBytes),\n    length: eexecBytes.length\n  };\n}\nclass Type1Font {\n  constructor(name, file, properties) {\n    const PFB_HEADER_SIZE = 6;\n    let headerBlockLength = properties.length1;\n    let eexecBlockLength = properties.length2;\n    let pfbHeader = file.peekBytes(PFB_HEADER_SIZE);\n    const pfbHeaderPresent = pfbHeader[0] === 0x80 && pfbHeader[1] === 0x01;\n    if (pfbHeaderPresent) {\n      file.skip(PFB_HEADER_SIZE);\n      headerBlockLength = pfbHeader[5] << 24 | pfbHeader[4] << 16 | pfbHeader[3] << 8 | pfbHeader[2];\n    }\n    const headerBlock = getHeaderBlock(file, headerBlockLength);\n    const headerBlockParser = new Type1Parser(headerBlock.stream, false, SEAC_ANALYSIS_ENABLED);\n    headerBlockParser.extractFontHeader(properties);\n    if (pfbHeaderPresent) {\n      pfbHeader = file.getBytes(PFB_HEADER_SIZE);\n      eexecBlockLength = pfbHeader[5] << 24 | pfbHeader[4] << 16 | pfbHeader[3] << 8 | pfbHeader[2];\n    }\n    const eexecBlock = getEexecBlock(file, eexecBlockLength);\n    const eexecBlockParser = new Type1Parser(eexecBlock.stream, true, SEAC_ANALYSIS_ENABLED);\n    const data = eexecBlockParser.extractFontProgram(properties);\n    for (const key in data.properties) {\n      properties[key] = data.properties[key];\n    }\n    const charstrings = data.charstrings;\n    const type2Charstrings = this.getType2Charstrings(charstrings);\n    const subrs = this.getType2Subrs(data.subrs);\n    this.charstrings = charstrings;\n    this.data = this.wrap(name, type2Charstrings, this.charstrings, subrs, properties);\n    this.seacs = this.getSeacs(data.charstrings);\n  }\n  get numGlyphs() {\n    return this.charstrings.length + 1;\n  }\n  getCharset() {\n    const charset = [\".notdef\"];\n    for (const {\n      glyphName\n    } of this.charstrings) {\n      charset.push(glyphName);\n    }\n    return charset;\n  }\n  getGlyphMapping(properties) {\n    const charstrings = this.charstrings;\n    if (properties.composite) {\n      const charCodeToGlyphId = Object.create(null);\n      for (let glyphId = 0, charstringsLen = charstrings.length; glyphId < charstringsLen; glyphId++) {\n        const charCode = properties.cMap.charCodeOf(glyphId);\n        charCodeToGlyphId[charCode] = glyphId + 1;\n      }\n      return charCodeToGlyphId;\n    }\n    const glyphNames = [\".notdef\"];\n    let builtInEncoding, glyphId;\n    for (glyphId = 0; glyphId < charstrings.length; glyphId++) {\n      glyphNames.push(charstrings[glyphId].glyphName);\n    }\n    const encoding = properties.builtInEncoding;\n    if (encoding) {\n      builtInEncoding = Object.create(null);\n      for (const charCode in encoding) {\n        glyphId = glyphNames.indexOf(encoding[charCode]);\n        if (glyphId >= 0) {\n          builtInEncoding[charCode] = glyphId;\n        }\n      }\n    }\n    return type1FontGlyphMapping(properties, builtInEncoding, glyphNames);\n  }\n  hasGlyphId(id) {\n    if (id < 0 || id >= this.numGlyphs) {\n      return false;\n    }\n    if (id === 0) {\n      return true;\n    }\n    const glyph = this.charstrings[id - 1];\n    return glyph.charstring.length > 0;\n  }\n  getSeacs(charstrings) {\n    const seacMap = [];\n    for (let i = 0, ii = charstrings.length; i < ii; i++) {\n      const charstring = charstrings[i];\n      if (charstring.seac) {\n        seacMap[i + 1] = charstring.seac;\n      }\n    }\n    return seacMap;\n  }\n  getType2Charstrings(type1Charstrings) {\n    const type2Charstrings = [];\n    for (const type1Charstring of type1Charstrings) {\n      type2Charstrings.push(type1Charstring.charstring);\n    }\n    return type2Charstrings;\n  }\n  getType2Subrs(type1Subrs) {\n    let bias = 0;\n    const count = type1Subrs.length;\n    if (count < 1133) {\n      bias = 107;\n    } else if (count < 33769) {\n      bias = 1131;\n    } else {\n      bias = 32768;\n    }\n    const type2Subrs = [];\n    let i;\n    for (i = 0; i < bias; i++) {\n      type2Subrs.push([0x0b]);\n    }\n    for (i = 0; i < count; i++) {\n      type2Subrs.push(type1Subrs[i]);\n    }\n    return type2Subrs;\n  }\n  wrap(name, glyphs, charstrings, subrs, properties) {\n    const cff = new CFF();\n    cff.header = new CFFHeader(1, 0, 4, 4);\n    cff.names = [name];\n    const topDict = new CFFTopDict();\n    topDict.setByName(\"version\", 391);\n    topDict.setByName(\"Notice\", 392);\n    topDict.setByName(\"FullName\", 393);\n    topDict.setByName(\"FamilyName\", 394);\n    topDict.setByName(\"Weight\", 395);\n    topDict.setByName(\"Encoding\", null);\n    topDict.setByName(\"FontMatrix\", properties.fontMatrix);\n    topDict.setByName(\"FontBBox\", properties.bbox);\n    topDict.setByName(\"charset\", null);\n    topDict.setByName(\"CharStrings\", null);\n    topDict.setByName(\"Private\", null);\n    cff.topDict = topDict;\n    const strings = new CFFStrings();\n    strings.add(\"Version 0.11\");\n    strings.add(\"See original notice\");\n    strings.add(name);\n    strings.add(name);\n    strings.add(\"Medium\");\n    cff.strings = strings;\n    cff.globalSubrIndex = new CFFIndex();\n    const count = glyphs.length;\n    const charsetArray = [\".notdef\"];\n    let i, ii;\n    for (i = 0; i < count; i++) {\n      const glyphName = charstrings[i].glyphName;\n      const index = CFFStandardStrings.indexOf(glyphName);\n      if (index === -1) {\n        strings.add(glyphName);\n      }\n      charsetArray.push(glyphName);\n    }\n    cff.charset = new CFFCharset(false, 0, charsetArray);\n    const charStringsIndex = new CFFIndex();\n    charStringsIndex.add([0x8b, 0x0e]);\n    for (i = 0; i < count; i++) {\n      charStringsIndex.add(glyphs[i]);\n    }\n    cff.charStrings = charStringsIndex;\n    const privateDict = new CFFPrivateDict();\n    privateDict.setByName(\"Subrs\", null);\n    const fields = [\"BlueValues\", \"OtherBlues\", \"FamilyBlues\", \"FamilyOtherBlues\", \"StemSnapH\", \"StemSnapV\", \"BlueShift\", \"BlueFuzz\", \"BlueScale\", \"LanguageGroup\", \"ExpansionFactor\", \"ForceBold\", \"StdHW\", \"StdVW\"];\n    for (i = 0, ii = fields.length; i < ii; i++) {\n      const field = fields[i];\n      if (!(field in properties.privateData)) {\n        continue;\n      }\n      const value = properties.privateData[field];\n      if (Array.isArray(value)) {\n        for (let j = value.length - 1; j > 0; j--) {\n          value[j] -= value[j - 1];\n        }\n      }\n      privateDict.setByName(field, value);\n    }\n    cff.topDict.privateDict = privateDict;\n    const subrIndex = new CFFIndex();\n    for (i = 0, ii = subrs.length; i < ii; i++) {\n      subrIndex.add(subrs[i]);\n    }\n    privateDict.subrsIndex = subrIndex;\n    const compiler = new CFFCompiler(cff);\n    return compiler.compile();\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/fonts.js\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst PRIVATE_USE_AREAS = [[0xe000, 0xf8ff], [0x100000, 0x10fffd]];\nconst PDF_GLYPH_SPACE_UNITS = 1000;\nconst EXPORT_DATA_PROPERTIES = [\"ascent\", \"bbox\", \"black\", \"bold\", \"charProcOperatorList\", \"composite\", \"cssFontInfo\", \"data\", \"defaultVMetrics\", \"defaultWidth\", \"descent\", \"fallbackName\", \"fontMatrix\", \"isInvalidPDFjsFont\", \"isType3Font\", \"italic\", \"loadedName\", \"mimetype\", \"missingFile\", \"name\", \"remeasure\", \"subtype\", \"systemFontInfo\", \"type\", \"vertical\"];\nconst EXPORT_DATA_EXTRA_PROPERTIES = [\"cMap\", \"defaultEncoding\", \"differences\", \"isMonospace\", \"isSerifFont\", \"isSymbolicFont\", \"seacMap\", \"toFontChar\", \"toUnicode\", \"vmetrics\", \"widths\"];\nfunction adjustWidths(properties) {\n  if (!properties.fontMatrix) {\n    return;\n  }\n  if (properties.fontMatrix[0] === FONT_IDENTITY_MATRIX[0]) {\n    return;\n  }\n  const scale = 0.001 / properties.fontMatrix[0];\n  const glyphsWidths = properties.widths;\n  for (const glyph in glyphsWidths) {\n    glyphsWidths[glyph] *= scale;\n  }\n  properties.defaultWidth *= scale;\n}\nfunction adjustTrueTypeToUnicode(properties, isSymbolicFont, nameRecords) {\n  if (properties.isInternalFont) {\n    return;\n  }\n  if (properties.hasIncludedToUnicodeMap) {\n    return;\n  }\n  if (properties.hasEncoding) {\n    return;\n  }\n  if (properties.toUnicode instanceof IdentityToUnicodeMap) {\n    return;\n  }\n  if (!isSymbolicFont) {\n    return;\n  }\n  if (nameRecords.length === 0) {\n    return;\n  }\n  if (properties.defaultEncoding === WinAnsiEncoding) {\n    return;\n  }\n  for (const r of nameRecords) {\n    if (!isWinNameRecord(r)) {\n      return;\n    }\n  }\n  const encoding = WinAnsiEncoding;\n  const toUnicode = [],\n    glyphsUnicodeMap = getGlyphsUnicode();\n  for (const charCode in encoding) {\n    const glyphName = encoding[charCode];\n    if (glyphName === \"\") {\n      continue;\n    }\n    const unicode = glyphsUnicodeMap[glyphName];\n    if (unicode === undefined) {\n      continue;\n    }\n    toUnicode[charCode] = String.fromCharCode(unicode);\n  }\n  if (toUnicode.length > 0) {\n    properties.toUnicode.amend(toUnicode);\n  }\n}\nfunction adjustType1ToUnicode(properties, builtInEncoding) {\n  if (properties.isInternalFont) {\n    return;\n  }\n  if (properties.hasIncludedToUnicodeMap) {\n    return;\n  }\n  if (builtInEncoding === properties.defaultEncoding) {\n    return;\n  }\n  if (properties.toUnicode instanceof IdentityToUnicodeMap) {\n    return;\n  }\n  const toUnicode = [],\n    glyphsUnicodeMap = getGlyphsUnicode();\n  for (const charCode in builtInEncoding) {\n    if (properties.hasEncoding) {\n      if (properties.baseEncodingName || properties.differences[charCode] !== undefined) {\n        continue;\n      }\n    }\n    const glyphName = builtInEncoding[charCode];\n    const unicode = getUnicodeForGlyph(glyphName, glyphsUnicodeMap);\n    if (unicode !== -1) {\n      toUnicode[charCode] = String.fromCharCode(unicode);\n    }\n  }\n  if (toUnicode.length > 0) {\n    properties.toUnicode.amend(toUnicode);\n  }\n}\nfunction amendFallbackToUnicode(properties) {\n  if (!properties.fallbackToUnicode) {\n    return;\n  }\n  if (properties.toUnicode instanceof IdentityToUnicodeMap) {\n    return;\n  }\n  const toUnicode = [];\n  for (const charCode in properties.fallbackToUnicode) {\n    if (properties.toUnicode.has(charCode)) {\n      continue;\n    }\n    toUnicode[charCode] = properties.fallbackToUnicode[charCode];\n  }\n  if (toUnicode.length > 0) {\n    properties.toUnicode.amend(toUnicode);\n  }\n}\nclass fonts_Glyph {\n  constructor(originalCharCode, fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont) {\n    this.originalCharCode = originalCharCode;\n    this.fontChar = fontChar;\n    this.unicode = unicode;\n    this.accent = accent;\n    this.width = width;\n    this.vmetric = vmetric;\n    this.operatorListId = operatorListId;\n    this.isSpace = isSpace;\n    this.isInFont = isInFont;\n  }\n  get category() {\n    return shadow(this, \"category\", getCharUnicodeCategory(this.unicode), true);\n  }\n}\nfunction int16(b0, b1) {\n  return (b0 << 8) + b1;\n}\nfunction writeSignedInt16(bytes, index, value) {\n  bytes[index + 1] = value;\n  bytes[index] = value >>> 8;\n}\nfunction signedInt16(b0, b1) {\n  const value = (b0 << 8) + b1;\n  return value & 1 << 15 ? value - 0x10000 : value;\n}\nfunction writeUint32(bytes, index, value) {\n  bytes[index + 3] = value & 0xff;\n  bytes[index + 2] = value >>> 8;\n  bytes[index + 1] = value >>> 16;\n  bytes[index] = value >>> 24;\n}\nfunction int32(b0, b1, b2, b3) {\n  return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;\n}\nfunction string16(value) {\n  return String.fromCharCode(value >> 8 & 0xff, value & 0xff);\n}\nfunction safeString16(value) {\n  if (value > 0x7fff) {\n    value = 0x7fff;\n  } else if (value < -0x8000) {\n    value = -0x8000;\n  }\n  return String.fromCharCode(value >> 8 & 0xff, value & 0xff);\n}\nfunction isTrueTypeFile(file) {\n  const header = file.peekBytes(4);\n  return readUint32(header, 0) === 0x00010000 || bytesToString(header) === \"true\";\n}\nfunction isTrueTypeCollectionFile(file) {\n  const header = file.peekBytes(4);\n  return bytesToString(header) === \"ttcf\";\n}\nfunction isOpenTypeFile(file) {\n  const header = file.peekBytes(4);\n  return bytesToString(header) === \"OTTO\";\n}\nfunction isType1File(file) {\n  const header = file.peekBytes(2);\n  if (header[0] === 0x25 && header[1] === 0x21) {\n    return true;\n  }\n  if (header[0] === 0x80 && header[1] === 0x01) {\n    return true;\n  }\n  return false;\n}\nfunction isCFFFile(file) {\n  const header = file.peekBytes(4);\n  if (header[0] >= 1 && header[3] >= 1 && header[3] <= 4) {\n    return true;\n  }\n  return false;\n}\nfunction getFontFileType(file, {\n  type,\n  subtype,\n  composite\n}) {\n  let fileType, fileSubtype;\n  if (isTrueTypeFile(file) || isTrueTypeCollectionFile(file)) {\n    fileType = composite ? \"CIDFontType2\" : \"TrueType\";\n  } else if (isOpenTypeFile(file)) {\n    fileType = composite ? \"CIDFontType2\" : \"OpenType\";\n  } else if (isType1File(file)) {\n    if (composite) {\n      fileType = \"CIDFontType0\";\n    } else {\n      fileType = type === \"MMType1\" ? \"MMType1\" : \"Type1\";\n    }\n  } else if (isCFFFile(file)) {\n    if (composite) {\n      fileType = \"CIDFontType0\";\n      fileSubtype = \"CIDFontType0C\";\n    } else {\n      fileType = type === \"MMType1\" ? \"MMType1\" : \"Type1\";\n      fileSubtype = \"Type1C\";\n    }\n  } else {\n    warn(\"getFontFileType: Unable to detect correct font file Type/Subtype.\");\n    fileType = type;\n    fileSubtype = subtype;\n  }\n  return [fileType, fileSubtype];\n}\nfunction applyStandardFontGlyphMap(map, glyphMap) {\n  for (const charCode in glyphMap) {\n    map[+charCode] = glyphMap[charCode];\n  }\n}\nfunction buildToFontChar(encoding, glyphsUnicodeMap, differences) {\n  const toFontChar = [];\n  let unicode;\n  for (let i = 0, ii = encoding.length; i < ii; i++) {\n    unicode = getUnicodeForGlyph(encoding[i], glyphsUnicodeMap);\n    if (unicode !== -1) {\n      toFontChar[i] = unicode;\n    }\n  }\n  for (const charCode in differences) {\n    unicode = getUnicodeForGlyph(differences[charCode], glyphsUnicodeMap);\n    if (unicode !== -1) {\n      toFontChar[+charCode] = unicode;\n    }\n  }\n  return toFontChar;\n}\nfunction isMacNameRecord(r) {\n  return r.platform === 1 && r.encoding === 0 && r.language === 0;\n}\nfunction isWinNameRecord(r) {\n  return r.platform === 3 && r.encoding === 1 && r.language === 0x409;\n}\nfunction convertCidString(charCode, cid, shouldThrow = false) {\n  switch (cid.length) {\n    case 1:\n      return cid.charCodeAt(0);\n    case 2:\n      return cid.charCodeAt(0) << 8 | cid.charCodeAt(1);\n  }\n  const msg = `Unsupported CID string (charCode ${charCode}): \"${cid}\".`;\n  if (shouldThrow) {\n    throw new FormatError(msg);\n  }\n  warn(msg);\n  return cid;\n}\nfunction adjustMapping(charCodeToGlyphId, hasGlyph, newGlyphZeroId, toUnicode) {\n  const newMap = Object.create(null);\n  const toUnicodeExtraMap = new Map();\n  const toFontChar = [];\n  const usedGlyphIds = new Set();\n  let privateUseAreaIndex = 0;\n  const privateUseOffetStart = PRIVATE_USE_AREAS[privateUseAreaIndex][0];\n  let nextAvailableFontCharCode = privateUseOffetStart;\n  let privateUseOffetEnd = PRIVATE_USE_AREAS[privateUseAreaIndex][1];\n  const isInPrivateArea = code => PRIVATE_USE_AREAS[0][0] <= code && code <= PRIVATE_USE_AREAS[0][1] || PRIVATE_USE_AREAS[1][0] <= code && code <= PRIVATE_USE_AREAS[1][1];\n  for (let originalCharCode in charCodeToGlyphId) {\n    originalCharCode |= 0;\n    let glyphId = charCodeToGlyphId[originalCharCode];\n    if (!hasGlyph(glyphId)) {\n      continue;\n    }\n    if (nextAvailableFontCharCode > privateUseOffetEnd) {\n      privateUseAreaIndex++;\n      if (privateUseAreaIndex >= PRIVATE_USE_AREAS.length) {\n        warn(\"Ran out of space in font private use area.\");\n        break;\n      }\n      nextAvailableFontCharCode = PRIVATE_USE_AREAS[privateUseAreaIndex][0];\n      privateUseOffetEnd = PRIVATE_USE_AREAS[privateUseAreaIndex][1];\n    }\n    const fontCharCode = nextAvailableFontCharCode++;\n    if (glyphId === 0) {\n      glyphId = newGlyphZeroId;\n    }\n    let unicode = toUnicode.get(originalCharCode);\n    if (typeof unicode === \"string\") {\n      unicode = unicode.codePointAt(0);\n    }\n    if (unicode && !isInPrivateArea(unicode) && !usedGlyphIds.has(glyphId)) {\n      toUnicodeExtraMap.set(unicode, glyphId);\n      usedGlyphIds.add(glyphId);\n    }\n    newMap[fontCharCode] = glyphId;\n    toFontChar[originalCharCode] = fontCharCode;\n  }\n  return {\n    toFontChar,\n    charCodeToGlyphId: newMap,\n    toUnicodeExtraMap,\n    nextAvailableFontCharCode\n  };\n}\nfunction getRanges(glyphs, toUnicodeExtraMap, numGlyphs) {\n  const codes = [];\n  for (const charCode in glyphs) {\n    if (glyphs[charCode] >= numGlyphs) {\n      continue;\n    }\n    codes.push({\n      fontCharCode: charCode | 0,\n      glyphId: glyphs[charCode]\n    });\n  }\n  if (toUnicodeExtraMap) {\n    for (const [unicode, glyphId] of toUnicodeExtraMap) {\n      if (glyphId >= numGlyphs) {\n        continue;\n      }\n      codes.push({\n        fontCharCode: unicode,\n        glyphId\n      });\n    }\n  }\n  if (codes.length === 0) {\n    codes.push({\n      fontCharCode: 0,\n      glyphId: 0\n    });\n  }\n  codes.sort(function fontGetRangesSort(a, b) {\n    return a.fontCharCode - b.fontCharCode;\n  });\n  const ranges = [];\n  const length = codes.length;\n  for (let n = 0; n < length;) {\n    const start = codes[n].fontCharCode;\n    const codeIndices = [codes[n].glyphId];\n    ++n;\n    let end = start;\n    while (n < length && end + 1 === codes[n].fontCharCode) {\n      codeIndices.push(codes[n].glyphId);\n      ++end;\n      ++n;\n      if (end === 0xffff) {\n        break;\n      }\n    }\n    ranges.push([start, end, codeIndices]);\n  }\n  return ranges;\n}\nfunction createCmapTable(glyphs, toUnicodeExtraMap, numGlyphs) {\n  const ranges = getRanges(glyphs, toUnicodeExtraMap, numGlyphs);\n  const numTables = ranges.at(-1)[1] > 0xffff ? 2 : 1;\n  let cmap = \"\\x00\\x00\" + string16(numTables) + \"\\x00\\x03\" + \"\\x00\\x01\" + string32(4 + numTables * 8);\n  let i, ii, j, jj;\n  for (i = ranges.length - 1; i >= 0; --i) {\n    if (ranges[i][0] <= 0xffff) {\n      break;\n    }\n  }\n  const bmpLength = i + 1;\n  if (ranges[i][0] < 0xffff && ranges[i][1] === 0xffff) {\n    ranges[i][1] = 0xfffe;\n  }\n  const trailingRangesCount = ranges[i][1] < 0xffff ? 1 : 0;\n  const segCount = bmpLength + trailingRangesCount;\n  const searchParams = OpenTypeFileBuilder.getSearchParams(segCount, 2);\n  let startCount = \"\";\n  let endCount = \"\";\n  let idDeltas = \"\";\n  let idRangeOffsets = \"\";\n  let glyphsIds = \"\";\n  let bias = 0;\n  let range, start, end, codes;\n  for (i = 0, ii = bmpLength; i < ii; i++) {\n    range = ranges[i];\n    start = range[0];\n    end = range[1];\n    startCount += string16(start);\n    endCount += string16(end);\n    codes = range[2];\n    let contiguous = true;\n    for (j = 1, jj = codes.length; j < jj; ++j) {\n      if (codes[j] !== codes[j - 1] + 1) {\n        contiguous = false;\n        break;\n      }\n    }\n    if (!contiguous) {\n      const offset = (segCount - i) * 2 + bias * 2;\n      bias += end - start + 1;\n      idDeltas += string16(0);\n      idRangeOffsets += string16(offset);\n      for (j = 0, jj = codes.length; j < jj; ++j) {\n        glyphsIds += string16(codes[j]);\n      }\n    } else {\n      const startCode = codes[0];\n      idDeltas += string16(startCode - start & 0xffff);\n      idRangeOffsets += string16(0);\n    }\n  }\n  if (trailingRangesCount > 0) {\n    endCount += \"\\xFF\\xFF\";\n    startCount += \"\\xFF\\xFF\";\n    idDeltas += \"\\x00\\x01\";\n    idRangeOffsets += \"\\x00\\x00\";\n  }\n  const format314 = \"\\x00\\x00\" + string16(2 * segCount) + string16(searchParams.range) + string16(searchParams.entry) + string16(searchParams.rangeShift) + endCount + \"\\x00\\x00\" + startCount + idDeltas + idRangeOffsets + glyphsIds;\n  let format31012 = \"\";\n  let header31012 = \"\";\n  if (numTables > 1) {\n    cmap += \"\\x00\\x03\" + \"\\x00\\x0A\" + string32(4 + numTables * 8 + 4 + format314.length);\n    format31012 = \"\";\n    for (i = 0, ii = ranges.length; i < ii; i++) {\n      range = ranges[i];\n      start = range[0];\n      codes = range[2];\n      let code = codes[0];\n      for (j = 1, jj = codes.length; j < jj; ++j) {\n        if (codes[j] !== codes[j - 1] + 1) {\n          end = range[0] + j - 1;\n          format31012 += string32(start) + string32(end) + string32(code);\n          start = end + 1;\n          code = codes[j];\n        }\n      }\n      format31012 += string32(start) + string32(range[1]) + string32(code);\n    }\n    header31012 = \"\\x00\\x0C\" + \"\\x00\\x00\" + string32(format31012.length + 16) + \"\\x00\\x00\\x00\\x00\" + string32(format31012.length / 12);\n  }\n  return cmap + \"\\x00\\x04\" + string16(format314.length + 4) + format314 + header31012 + format31012;\n}\nfunction validateOS2Table(os2, file) {\n  file.pos = (file.start || 0) + os2.offset;\n  const version = file.getUint16();\n  file.skip(60);\n  const selection = file.getUint16();\n  if (version < 4 && selection & 0x0300) {\n    return false;\n  }\n  const firstChar = file.getUint16();\n  const lastChar = file.getUint16();\n  if (firstChar > lastChar) {\n    return false;\n  }\n  file.skip(6);\n  const usWinAscent = file.getUint16();\n  if (usWinAscent === 0) {\n    return false;\n  }\n  os2.data[8] = os2.data[9] = 0;\n  return true;\n}\nfunction createOS2Table(properties, charstrings, override) {\n  override ||= {\n    unitsPerEm: 0,\n    yMax: 0,\n    yMin: 0,\n    ascent: 0,\n    descent: 0\n  };\n  let ulUnicodeRange1 = 0;\n  let ulUnicodeRange2 = 0;\n  let ulUnicodeRange3 = 0;\n  let ulUnicodeRange4 = 0;\n  let firstCharIndex = null;\n  let lastCharIndex = 0;\n  let position = -1;\n  if (charstrings) {\n    for (let code in charstrings) {\n      code |= 0;\n      if (firstCharIndex > code || !firstCharIndex) {\n        firstCharIndex = code;\n      }\n      if (lastCharIndex < code) {\n        lastCharIndex = code;\n      }\n      position = getUnicodeRangeFor(code, position);\n      if (position < 32) {\n        ulUnicodeRange1 |= 1 << position;\n      } else if (position < 64) {\n        ulUnicodeRange2 |= 1 << position - 32;\n      } else if (position < 96) {\n        ulUnicodeRange3 |= 1 << position - 64;\n      } else if (position < 123) {\n        ulUnicodeRange4 |= 1 << position - 96;\n      } else {\n        throw new FormatError(\"Unicode ranges Bits > 123 are reserved for internal usage\");\n      }\n    }\n    if (lastCharIndex > 0xffff) {\n      lastCharIndex = 0xffff;\n    }\n  } else {\n    firstCharIndex = 0;\n    lastCharIndex = 255;\n  }\n  const bbox = properties.bbox || [0, 0, 0, 0];\n  const unitsPerEm = override.unitsPerEm || 1 / (properties.fontMatrix || FONT_IDENTITY_MATRIX)[0];\n  const scale = properties.ascentScaled ? 1.0 : unitsPerEm / PDF_GLYPH_SPACE_UNITS;\n  const typoAscent = override.ascent || Math.round(scale * (properties.ascent || bbox[3]));\n  let typoDescent = override.descent || Math.round(scale * (properties.descent || bbox[1]));\n  if (typoDescent > 0 && properties.descent > 0 && bbox[1] < 0) {\n    typoDescent = -typoDescent;\n  }\n  const winAscent = override.yMax || typoAscent;\n  const winDescent = -override.yMin || -typoDescent;\n  return \"\\x00\\x03\" + \"\\x02\\x24\" + \"\\x01\\xF4\" + \"\\x00\\x05\" + \"\\x00\\x00\" + \"\\x02\\x8A\" + \"\\x02\\xBB\" + \"\\x00\\x00\" + \"\\x00\\x8C\" + \"\\x02\\x8A\" + \"\\x02\\xBB\" + \"\\x00\\x00\" + \"\\x01\\xDF\" + \"\\x00\\x31\" + \"\\x01\\x02\" + \"\\x00\\x00\" + \"\\x00\\x00\\x06\" + String.fromCharCode(properties.fixedPitch ? 0x09 : 0x00) + \"\\x00\\x00\\x00\\x00\\x00\\x00\" + string32(ulUnicodeRange1) + string32(ulUnicodeRange2) + string32(ulUnicodeRange3) + string32(ulUnicodeRange4) + \"\\x2A\\x32\\x31\\x2A\" + string16(properties.italicAngle ? 1 : 0) + string16(firstCharIndex || properties.firstChar) + string16(lastCharIndex || properties.lastChar) + string16(typoAscent) + string16(typoDescent) + \"\\x00\\x64\" + string16(winAscent) + string16(winDescent) + \"\\x00\\x00\\x00\\x00\" + \"\\x00\\x00\\x00\\x00\" + string16(properties.xHeight) + string16(properties.capHeight) + string16(0) + string16(firstCharIndex || properties.firstChar) + \"\\x00\\x03\";\n}\nfunction createPostTable(properties) {\n  const angle = Math.floor(properties.italicAngle * 2 ** 16);\n  return \"\\x00\\x03\\x00\\x00\" + string32(angle) + \"\\x00\\x00\" + \"\\x00\\x00\" + string32(properties.fixedPitch ? 1 : 0) + \"\\x00\\x00\\x00\\x00\" + \"\\x00\\x00\\x00\\x00\" + \"\\x00\\x00\\x00\\x00\" + \"\\x00\\x00\\x00\\x00\";\n}\nfunction createPostscriptName(name) {\n  return name.replaceAll(/[^\\x21-\\x7E]|[[\\](){}<>/%]/g, \"\").slice(0, 63);\n}\nfunction createNameTable(name, proto) {\n  if (!proto) {\n    proto = [[], []];\n  }\n  const strings = [proto[0][0] || \"Original licence\", proto[0][1] || name, proto[0][2] || \"Unknown\", proto[0][3] || \"uniqueID\", proto[0][4] || name, proto[0][5] || \"Version 0.11\", proto[0][6] || createPostscriptName(name), proto[0][7] || \"Unknown\", proto[0][8] || \"Unknown\", proto[0][9] || \"Unknown\"];\n  const stringsUnicode = [];\n  let i, ii, j, jj, str;\n  for (i = 0, ii = strings.length; i < ii; i++) {\n    str = proto[1][i] || strings[i];\n    const strBufUnicode = [];\n    for (j = 0, jj = str.length; j < jj; j++) {\n      strBufUnicode.push(string16(str.charCodeAt(j)));\n    }\n    stringsUnicode.push(strBufUnicode.join(\"\"));\n  }\n  const names = [strings, stringsUnicode];\n  const platforms = [\"\\x00\\x01\", \"\\x00\\x03\"];\n  const encodings = [\"\\x00\\x00\", \"\\x00\\x01\"];\n  const languages = [\"\\x00\\x00\", \"\\x04\\x09\"];\n  const namesRecordCount = strings.length * platforms.length;\n  let nameTable = \"\\x00\\x00\" + string16(namesRecordCount) + string16(namesRecordCount * 12 + 6);\n  let strOffset = 0;\n  for (i = 0, ii = platforms.length; i < ii; i++) {\n    const strs = names[i];\n    for (j = 0, jj = strs.length; j < jj; j++) {\n      str = strs[j];\n      const nameRecord = platforms[i] + encodings[i] + languages[i] + string16(j) + string16(str.length) + string16(strOffset);\n      nameTable += nameRecord;\n      strOffset += str.length;\n    }\n  }\n  nameTable += strings.join(\"\") + stringsUnicode.join(\"\");\n  return nameTable;\n}\nclass Font {\n  constructor(name, file, properties) {\n    this.name = name;\n    this.psName = null;\n    this.mimetype = null;\n    this.disableFontFace = false;\n    this.loadedName = properties.loadedName;\n    this.isType3Font = properties.isType3Font;\n    this.missingFile = false;\n    this.cssFontInfo = properties.cssFontInfo;\n    this._charsCache = Object.create(null);\n    this._glyphCache = Object.create(null);\n    let isSerifFont = !!(properties.flags & FontFlags.Serif);\n    if (!isSerifFont && !properties.isSimulatedFlags) {\n      const baseName = name.replaceAll(/[,_]/g, \"-\").split(\"-\", 1)[0],\n        serifFonts = getSerifFonts();\n      for (const namePart of baseName.split(\"+\")) {\n        if (serifFonts[namePart]) {\n          isSerifFont = true;\n          break;\n        }\n      }\n    }\n    this.isSerifFont = isSerifFont;\n    this.isSymbolicFont = !!(properties.flags & FontFlags.Symbolic);\n    this.isMonospace = !!(properties.flags & FontFlags.FixedPitch);\n    let {\n      type,\n      subtype\n    } = properties;\n    this.type = type;\n    this.subtype = subtype;\n    this.systemFontInfo = properties.systemFontInfo;\n    const matches = name.match(/^InvalidPDFjsFont_(.*)_\\d+$/);\n    this.isInvalidPDFjsFont = !!matches;\n    if (this.isInvalidPDFjsFont) {\n      this.fallbackName = matches[1];\n    } else if (this.isMonospace) {\n      this.fallbackName = \"monospace\";\n    } else if (this.isSerifFont) {\n      this.fallbackName = \"serif\";\n    } else {\n      this.fallbackName = \"sans-serif\";\n    }\n    if (this.systemFontInfo?.guessFallback) {\n      this.systemFontInfo.guessFallback = false;\n      this.systemFontInfo.css += `,${this.fallbackName}`;\n    }\n    this.differences = properties.differences;\n    this.widths = properties.widths;\n    this.defaultWidth = properties.defaultWidth;\n    this.composite = properties.composite;\n    this.cMap = properties.cMap;\n    this.capHeight = properties.capHeight / PDF_GLYPH_SPACE_UNITS;\n    this.ascent = properties.ascent / PDF_GLYPH_SPACE_UNITS;\n    this.descent = properties.descent / PDF_GLYPH_SPACE_UNITS;\n    this.lineHeight = this.ascent - this.descent;\n    this.fontMatrix = properties.fontMatrix;\n    this.bbox = properties.bbox;\n    this.defaultEncoding = properties.defaultEncoding;\n    this.toUnicode = properties.toUnicode;\n    this.toFontChar = [];\n    if (properties.type === \"Type3\") {\n      for (let charCode = 0; charCode < 256; charCode++) {\n        this.toFontChar[charCode] = this.differences[charCode] || properties.defaultEncoding[charCode];\n      }\n      return;\n    }\n    this.cidEncoding = properties.cidEncoding || \"\";\n    this.vertical = !!properties.vertical;\n    if (this.vertical) {\n      this.vmetrics = properties.vmetrics;\n      this.defaultVMetrics = properties.defaultVMetrics;\n    }\n    if (!file || file.isEmpty) {\n      if (file) {\n        warn('Font file is empty in \"' + name + '\" (' + this.loadedName + \")\");\n      }\n      this.fallbackToSystemFont(properties);\n      return;\n    }\n    [type, subtype] = getFontFileType(file, properties);\n    if (type !== this.type || subtype !== this.subtype) {\n      info(\"Inconsistent font file Type/SubType, expected: \" + `${this.type}/${this.subtype} but found: ${type}/${subtype}.`);\n    }\n    let data;\n    try {\n      switch (type) {\n        case \"MMType1\":\n          info(\"MMType1 font (\" + name + \"), falling back to Type1.\");\n        case \"Type1\":\n        case \"CIDFontType0\":\n          this.mimetype = \"font/opentype\";\n          const cff = subtype === \"Type1C\" || subtype === \"CIDFontType0C\" ? new CFFFont(file, properties) : new Type1Font(name, file, properties);\n          adjustWidths(properties);\n          data = this.convert(name, cff, properties);\n          break;\n        case \"OpenType\":\n        case \"TrueType\":\n        case \"CIDFontType2\":\n          this.mimetype = \"font/opentype\";\n          data = this.checkAndRepair(name, file, properties);\n          if (this.isOpenType) {\n            adjustWidths(properties);\n            type = \"OpenType\";\n          }\n          break;\n        default:\n          throw new FormatError(`Font ${type} is not supported`);\n      }\n    } catch (e) {\n      warn(e);\n      this.fallbackToSystemFont(properties);\n      return;\n    }\n    amendFallbackToUnicode(properties);\n    this.data = data;\n    this.type = type;\n    this.subtype = subtype;\n    this.fontMatrix = properties.fontMatrix;\n    this.widths = properties.widths;\n    this.defaultWidth = properties.defaultWidth;\n    this.toUnicode = properties.toUnicode;\n    this.seacMap = properties.seacMap;\n  }\n  get renderer() {\n    const renderer = FontRendererFactory.create(this, SEAC_ANALYSIS_ENABLED);\n    return shadow(this, \"renderer\", renderer);\n  }\n  exportData(extraProperties = false) {\n    const exportDataProperties = extraProperties ? [...EXPORT_DATA_PROPERTIES, ...EXPORT_DATA_EXTRA_PROPERTIES] : EXPORT_DATA_PROPERTIES;\n    const data = Object.create(null);\n    let property, value;\n    for (property of exportDataProperties) {\n      value = this[property];\n      if (value !== undefined) {\n        data[property] = value;\n      }\n    }\n    return data;\n  }\n  fallbackToSystemFont(properties) {\n    this.missingFile = true;\n    const {\n      name,\n      type\n    } = this;\n    let fontName = normalizeFontName(name);\n    const stdFontMap = getStdFontMap(),\n      nonStdFontMap = getNonStdFontMap();\n    const isStandardFont = !!stdFontMap[fontName];\n    const isMappedToStandardFont = !!(nonStdFontMap[fontName] && stdFontMap[nonStdFontMap[fontName]]);\n    fontName = stdFontMap[fontName] || nonStdFontMap[fontName] || fontName;\n    const fontBasicMetricsMap = getFontBasicMetrics();\n    const metrics = fontBasicMetricsMap[fontName];\n    if (metrics) {\n      if (isNaN(this.ascent)) {\n        this.ascent = metrics.ascent / PDF_GLYPH_SPACE_UNITS;\n      }\n      if (isNaN(this.descent)) {\n        this.descent = metrics.descent / PDF_GLYPH_SPACE_UNITS;\n      }\n      if (isNaN(this.capHeight)) {\n        this.capHeight = metrics.capHeight / PDF_GLYPH_SPACE_UNITS;\n      }\n    }\n    this.bold = /bold/gi.test(fontName);\n    this.italic = /oblique|italic/gi.test(fontName);\n    this.black = /Black/g.test(name);\n    const isNarrow = /Narrow/g.test(name);\n    this.remeasure = (!isStandardFont || isNarrow) && Object.keys(this.widths).length > 0;\n    if ((isStandardFont || isMappedToStandardFont) && type === \"CIDFontType2\" && this.cidEncoding.startsWith(\"Identity-\")) {\n      const cidToGidMap = properties.cidToGidMap;\n      const map = [];\n      applyStandardFontGlyphMap(map, getGlyphMapForStandardFonts());\n      if (/Arial-?Black/i.test(name)) {\n        applyStandardFontGlyphMap(map, getSupplementalGlyphMapForArialBlack());\n      } else if (/Calibri/i.test(name)) {\n        applyStandardFontGlyphMap(map, getSupplementalGlyphMapForCalibri());\n      }\n      if (cidToGidMap) {\n        for (const charCode in map) {\n          const cid = map[charCode];\n          if (cidToGidMap[cid] !== undefined) {\n            map[+charCode] = cidToGidMap[cid];\n          }\n        }\n        if (cidToGidMap.length !== this.toUnicode.length && properties.hasIncludedToUnicodeMap && this.toUnicode instanceof IdentityToUnicodeMap) {\n          this.toUnicode.forEach(function (charCode, unicodeCharCode) {\n            const cid = map[charCode];\n            if (cidToGidMap[cid] === undefined) {\n              map[+charCode] = unicodeCharCode;\n            }\n          });\n        }\n      }\n      if (!(this.toUnicode instanceof IdentityToUnicodeMap)) {\n        this.toUnicode.forEach(function (charCode, unicodeCharCode) {\n          map[+charCode] = unicodeCharCode;\n        });\n      }\n      this.toFontChar = map;\n      this.toUnicode = new ToUnicodeMap(map);\n    } else if (/Symbol/i.test(fontName)) {\n      this.toFontChar = buildToFontChar(SymbolSetEncoding, getGlyphsUnicode(), this.differences);\n    } else if (/Dingbats/i.test(fontName)) {\n      this.toFontChar = buildToFontChar(ZapfDingbatsEncoding, getDingbatsGlyphsUnicode(), this.differences);\n    } else if (isStandardFont) {\n      const map = buildToFontChar(this.defaultEncoding, getGlyphsUnicode(), this.differences);\n      if (type === \"CIDFontType2\" && !this.cidEncoding.startsWith(\"Identity-\") && !(this.toUnicode instanceof IdentityToUnicodeMap)) {\n        this.toUnicode.forEach(function (charCode, unicodeCharCode) {\n          map[+charCode] = unicodeCharCode;\n        });\n      }\n      this.toFontChar = map;\n    } else {\n      const glyphsUnicodeMap = getGlyphsUnicode();\n      const map = [];\n      this.toUnicode.forEach((charCode, unicodeCharCode) => {\n        if (!this.composite) {\n          const glyphName = this.differences[charCode] || this.defaultEncoding[charCode];\n          const unicode = getUnicodeForGlyph(glyphName, glyphsUnicodeMap);\n          if (unicode !== -1) {\n            unicodeCharCode = unicode;\n          }\n        }\n        map[+charCode] = unicodeCharCode;\n      });\n      if (this.composite && this.toUnicode instanceof IdentityToUnicodeMap) {\n        if (/Tahoma|Verdana/i.test(name)) {\n          applyStandardFontGlyphMap(map, getGlyphMapForStandardFonts());\n        }\n      }\n      this.toFontChar = map;\n    }\n    amendFallbackToUnicode(properties);\n    this.loadedName = fontName.split(\"-\", 1)[0];\n  }\n  checkAndRepair(name, font, properties) {\n    const VALID_TABLES = [\"OS/2\", \"cmap\", \"head\", \"hhea\", \"hmtx\", \"maxp\", \"name\", \"post\", \"loca\", \"glyf\", \"fpgm\", \"prep\", \"cvt \", \"CFF \"];\n    function readTables(file, numTables) {\n      const tables = Object.create(null);\n      tables[\"OS/2\"] = null;\n      tables.cmap = null;\n      tables.head = null;\n      tables.hhea = null;\n      tables.hmtx = null;\n      tables.maxp = null;\n      tables.name = null;\n      tables.post = null;\n      for (let i = 0; i < numTables; i++) {\n        const table = readTableEntry(file);\n        if (!VALID_TABLES.includes(table.tag)) {\n          continue;\n        }\n        if (table.length === 0) {\n          continue;\n        }\n        tables[table.tag] = table;\n      }\n      return tables;\n    }\n    function readTableEntry(file) {\n      const tag = file.getString(4);\n      const checksum = file.getInt32() >>> 0;\n      const offset = file.getInt32() >>> 0;\n      const length = file.getInt32() >>> 0;\n      const previousPosition = file.pos;\n      file.pos = file.start || 0;\n      file.skip(offset);\n      const data = file.getBytes(length);\n      file.pos = previousPosition;\n      if (tag === \"head\") {\n        data[8] = data[9] = data[10] = data[11] = 0;\n        data[17] |= 0x20;\n      }\n      return {\n        tag,\n        checksum,\n        length,\n        offset,\n        data\n      };\n    }\n    function readOpenTypeHeader(ttf) {\n      return {\n        version: ttf.getString(4),\n        numTables: ttf.getUint16(),\n        searchRange: ttf.getUint16(),\n        entrySelector: ttf.getUint16(),\n        rangeShift: ttf.getUint16()\n      };\n    }\n    function readTrueTypeCollectionHeader(ttc) {\n      const ttcTag = ttc.getString(4);\n      assert(ttcTag === \"ttcf\", \"Must be a TrueType Collection font.\");\n      const majorVersion = ttc.getUint16();\n      const minorVersion = ttc.getUint16();\n      const numFonts = ttc.getInt32() >>> 0;\n      const offsetTable = [];\n      for (let i = 0; i < numFonts; i++) {\n        offsetTable.push(ttc.getInt32() >>> 0);\n      }\n      const header = {\n        ttcTag,\n        majorVersion,\n        minorVersion,\n        numFonts,\n        offsetTable\n      };\n      switch (majorVersion) {\n        case 1:\n          return header;\n        case 2:\n          header.dsigTag = ttc.getInt32() >>> 0;\n          header.dsigLength = ttc.getInt32() >>> 0;\n          header.dsigOffset = ttc.getInt32() >>> 0;\n          return header;\n      }\n      throw new FormatError(`Invalid TrueType Collection majorVersion: ${majorVersion}.`);\n    }\n    function readTrueTypeCollectionData(ttc, fontName) {\n      const {\n        numFonts,\n        offsetTable\n      } = readTrueTypeCollectionHeader(ttc);\n      const fontNameParts = fontName.split(\"+\");\n      let fallbackData;\n      for (let i = 0; i < numFonts; i++) {\n        ttc.pos = (ttc.start || 0) + offsetTable[i];\n        const potentialHeader = readOpenTypeHeader(ttc);\n        const potentialTables = readTables(ttc, potentialHeader.numTables);\n        if (!potentialTables.name) {\n          throw new FormatError('TrueType Collection font must contain a \"name\" table.');\n        }\n        const [nameTable] = readNameTable(potentialTables.name);\n        for (let j = 0, jj = nameTable.length; j < jj; j++) {\n          for (let k = 0, kk = nameTable[j].length; k < kk; k++) {\n            const nameEntry = nameTable[j][k]?.replaceAll(/\\s/g, \"\");\n            if (!nameEntry) {\n              continue;\n            }\n            if (nameEntry === fontName) {\n              return {\n                header: potentialHeader,\n                tables: potentialTables\n              };\n            }\n            if (fontNameParts.length < 2) {\n              continue;\n            }\n            for (const part of fontNameParts) {\n              if (nameEntry === part) {\n                fallbackData = {\n                  name: part,\n                  header: potentialHeader,\n                  tables: potentialTables\n                };\n              }\n            }\n          }\n        }\n      }\n      if (fallbackData) {\n        warn(`TrueType Collection does not contain \"${fontName}\" font, ` + `falling back to \"${fallbackData.name}\" font instead.`);\n        return {\n          header: fallbackData.header,\n          tables: fallbackData.tables\n        };\n      }\n      throw new FormatError(`TrueType Collection does not contain \"${fontName}\" font.`);\n    }\n    function readCmapTable(cmap, file, isSymbolicFont, hasEncoding) {\n      if (!cmap) {\n        warn(\"No cmap table available.\");\n        return {\n          platformId: -1,\n          encodingId: -1,\n          mappings: [],\n          hasShortCmap: false\n        };\n      }\n      let segment;\n      let start = (file.start || 0) + cmap.offset;\n      file.pos = start;\n      file.skip(2);\n      const numTables = file.getUint16();\n      let potentialTable;\n      let canBreak = false;\n      for (let i = 0; i < numTables; i++) {\n        const platformId = file.getUint16();\n        const encodingId = file.getUint16();\n        const offset = file.getInt32() >>> 0;\n        let useTable = false;\n        if (potentialTable?.platformId === platformId && potentialTable?.encodingId === encodingId) {\n          continue;\n        }\n        if (platformId === 0 && (encodingId === 0 || encodingId === 1 || encodingId === 3)) {\n          useTable = true;\n        } else if (platformId === 1 && encodingId === 0) {\n          useTable = true;\n        } else if (platformId === 3 && encodingId === 1 && (hasEncoding || !potentialTable)) {\n          useTable = true;\n          if (!isSymbolicFont) {\n            canBreak = true;\n          }\n        } else if (isSymbolicFont && platformId === 3 && encodingId === 0) {\n          useTable = true;\n          let correctlySorted = true;\n          if (i < numTables - 1) {\n            const nextBytes = file.peekBytes(2),\n              nextPlatformId = int16(nextBytes[0], nextBytes[1]);\n            if (nextPlatformId < platformId) {\n              correctlySorted = false;\n            }\n          }\n          if (correctlySorted) {\n            canBreak = true;\n          }\n        }\n        if (useTable) {\n          potentialTable = {\n            platformId,\n            encodingId,\n            offset\n          };\n        }\n        if (canBreak) {\n          break;\n        }\n      }\n      if (potentialTable) {\n        file.pos = start + potentialTable.offset;\n      }\n      if (!potentialTable || file.peekByte() === -1) {\n        warn(\"Could not find a preferred cmap table.\");\n        return {\n          platformId: -1,\n          encodingId: -1,\n          mappings: [],\n          hasShortCmap: false\n        };\n      }\n      const format = file.getUint16();\n      let hasShortCmap = false;\n      const mappings = [];\n      let j, glyphId;\n      if (format === 0) {\n        file.skip(2 + 2);\n        for (j = 0; j < 256; j++) {\n          const index = file.getByte();\n          if (!index) {\n            continue;\n          }\n          mappings.push({\n            charCode: j,\n            glyphId: index\n          });\n        }\n        hasShortCmap = true;\n      } else if (format === 2) {\n        file.skip(2 + 2);\n        const subHeaderKeys = [];\n        let maxSubHeaderKey = 0;\n        for (let i = 0; i < 256; i++) {\n          const subHeaderKey = file.getUint16() >> 3;\n          subHeaderKeys.push(subHeaderKey);\n          maxSubHeaderKey = Math.max(subHeaderKey, maxSubHeaderKey);\n        }\n        const subHeaders = [];\n        for (let i = 0; i <= maxSubHeaderKey; i++) {\n          subHeaders.push({\n            firstCode: file.getUint16(),\n            entryCount: file.getUint16(),\n            idDelta: signedInt16(file.getByte(), file.getByte()),\n            idRangePos: file.pos + file.getUint16()\n          });\n        }\n        for (let i = 0; i < 256; i++) {\n          if (subHeaderKeys[i] === 0) {\n            file.pos = subHeaders[0].idRangePos + 2 * i;\n            glyphId = file.getUint16();\n            mappings.push({\n              charCode: i,\n              glyphId\n            });\n          } else {\n            const s = subHeaders[subHeaderKeys[i]];\n            for (j = 0; j < s.entryCount; j++) {\n              const charCode = (i << 8) + j + s.firstCode;\n              file.pos = s.idRangePos + 2 * j;\n              glyphId = file.getUint16();\n              if (glyphId !== 0) {\n                glyphId = (glyphId + s.idDelta) % 65536;\n              }\n              mappings.push({\n                charCode,\n                glyphId\n              });\n            }\n          }\n        }\n      } else if (format === 4) {\n        file.skip(2 + 2);\n        const segCount = file.getUint16() >> 1;\n        file.skip(6);\n        const segments = [];\n        let segIndex;\n        for (segIndex = 0; segIndex < segCount; segIndex++) {\n          segments.push({\n            end: file.getUint16()\n          });\n        }\n        file.skip(2);\n        for (segIndex = 0; segIndex < segCount; segIndex++) {\n          segments[segIndex].start = file.getUint16();\n        }\n        for (segIndex = 0; segIndex < segCount; segIndex++) {\n          segments[segIndex].delta = file.getUint16();\n        }\n        let offsetsCount = 0,\n          offsetIndex;\n        for (segIndex = 0; segIndex < segCount; segIndex++) {\n          segment = segments[segIndex];\n          const rangeOffset = file.getUint16();\n          if (!rangeOffset) {\n            segment.offsetIndex = -1;\n            continue;\n          }\n          offsetIndex = (rangeOffset >> 1) - (segCount - segIndex);\n          segment.offsetIndex = offsetIndex;\n          offsetsCount = Math.max(offsetsCount, offsetIndex + segment.end - segment.start + 1);\n        }\n        const offsets = [];\n        for (j = 0; j < offsetsCount; j++) {\n          offsets.push(file.getUint16());\n        }\n        for (segIndex = 0; segIndex < segCount; segIndex++) {\n          segment = segments[segIndex];\n          start = segment.start;\n          const end = segment.end;\n          const delta = segment.delta;\n          offsetIndex = segment.offsetIndex;\n          for (j = start; j <= end; j++) {\n            if (j === 0xffff) {\n              continue;\n            }\n            glyphId = offsetIndex < 0 ? j : offsets[offsetIndex + j - start];\n            glyphId = glyphId + delta & 0xffff;\n            mappings.push({\n              charCode: j,\n              glyphId\n            });\n          }\n        }\n      } else if (format === 6) {\n        file.skip(2 + 2);\n        const firstCode = file.getUint16();\n        const entryCount = file.getUint16();\n        for (j = 0; j < entryCount; j++) {\n          glyphId = file.getUint16();\n          const charCode = firstCode + j;\n          mappings.push({\n            charCode,\n            glyphId\n          });\n        }\n      } else if (format === 12) {\n        file.skip(2 + 4 + 4);\n        const nGroups = file.getInt32() >>> 0;\n        for (j = 0; j < nGroups; j++) {\n          const startCharCode = file.getInt32() >>> 0;\n          const endCharCode = file.getInt32() >>> 0;\n          let glyphCode = file.getInt32() >>> 0;\n          for (let charCode = startCharCode; charCode <= endCharCode; charCode++) {\n            mappings.push({\n              charCode,\n              glyphId: glyphCode++\n            });\n          }\n        }\n      } else {\n        warn(\"cmap table has unsupported format: \" + format);\n        return {\n          platformId: -1,\n          encodingId: -1,\n          mappings: [],\n          hasShortCmap: false\n        };\n      }\n      mappings.sort(function (a, b) {\n        return a.charCode - b.charCode;\n      });\n      for (let i = 1; i < mappings.length; i++) {\n        if (mappings[i - 1].charCode === mappings[i].charCode) {\n          mappings.splice(i, 1);\n          i--;\n        }\n      }\n      return {\n        platformId: potentialTable.platformId,\n        encodingId: potentialTable.encodingId,\n        mappings,\n        hasShortCmap\n      };\n    }\n    function sanitizeMetrics(file, header, metrics, headTable, numGlyphs, dupFirstEntry) {\n      if (!header) {\n        if (metrics) {\n          metrics.data = null;\n        }\n        return;\n      }\n      file.pos = (file.start || 0) + header.offset;\n      file.pos += 4;\n      file.pos += 2;\n      file.pos += 2;\n      file.pos += 2;\n      file.pos += 2;\n      file.pos += 2;\n      file.pos += 2;\n      file.pos += 2;\n      file.pos += 2;\n      file.pos += 2;\n      const caretOffset = file.getUint16();\n      file.pos += 8;\n      file.pos += 2;\n      let numOfMetrics = file.getUint16();\n      if (caretOffset !== 0) {\n        const macStyle = int16(headTable.data[44], headTable.data[45]);\n        if (!(macStyle & 2)) {\n          header.data[22] = 0;\n          header.data[23] = 0;\n        }\n      }\n      if (numOfMetrics > numGlyphs) {\n        info(`The numOfMetrics (${numOfMetrics}) should not be ` + `greater than the numGlyphs (${numGlyphs}).`);\n        numOfMetrics = numGlyphs;\n        header.data[34] = (numOfMetrics & 0xff00) >> 8;\n        header.data[35] = numOfMetrics & 0x00ff;\n      }\n      const numOfSidebearings = numGlyphs - numOfMetrics;\n      const numMissing = numOfSidebearings - (metrics.length - numOfMetrics * 4 >> 1);\n      if (numMissing > 0) {\n        const entries = new Uint8Array(metrics.length + numMissing * 2);\n        entries.set(metrics.data);\n        if (dupFirstEntry) {\n          entries[metrics.length] = metrics.data[2];\n          entries[metrics.length + 1] = metrics.data[3];\n        }\n        metrics.data = entries;\n      }\n    }\n    function sanitizeGlyph(source, sourceStart, sourceEnd, dest, destStart, hintsValid) {\n      const glyphProfile = {\n        length: 0,\n        sizeOfInstructions: 0\n      };\n      if (sourceStart < 0 || sourceStart >= source.length || sourceEnd > source.length || sourceEnd - sourceStart <= 12) {\n        return glyphProfile;\n      }\n      const glyf = source.subarray(sourceStart, sourceEnd);\n      const xMin = signedInt16(glyf[2], glyf[3]);\n      const yMin = signedInt16(glyf[4], glyf[5]);\n      const xMax = signedInt16(glyf[6], glyf[7]);\n      const yMax = signedInt16(glyf[8], glyf[9]);\n      if (xMin > xMax) {\n        writeSignedInt16(glyf, 2, xMax);\n        writeSignedInt16(glyf, 6, xMin);\n      }\n      if (yMin > yMax) {\n        writeSignedInt16(glyf, 4, yMax);\n        writeSignedInt16(glyf, 8, yMin);\n      }\n      const contoursCount = signedInt16(glyf[0], glyf[1]);\n      if (contoursCount < 0) {\n        if (contoursCount < -1) {\n          return glyphProfile;\n        }\n        dest.set(glyf, destStart);\n        glyphProfile.length = glyf.length;\n        return glyphProfile;\n      }\n      let i,\n        j = 10,\n        flagsCount = 0;\n      for (i = 0; i < contoursCount; i++) {\n        const endPoint = glyf[j] << 8 | glyf[j + 1];\n        flagsCount = endPoint + 1;\n        j += 2;\n      }\n      const instructionsStart = j;\n      const instructionsLength = glyf[j] << 8 | glyf[j + 1];\n      glyphProfile.sizeOfInstructions = instructionsLength;\n      j += 2 + instructionsLength;\n      const instructionsEnd = j;\n      let coordinatesLength = 0;\n      for (i = 0; i < flagsCount; i++) {\n        const flag = glyf[j++];\n        if (flag & 0xc0) {\n          glyf[j - 1] = flag & 0x3f;\n        }\n        let xLength = 2;\n        if (flag & 2) {\n          xLength = 1;\n        } else if (flag & 16) {\n          xLength = 0;\n        }\n        let yLength = 2;\n        if (flag & 4) {\n          yLength = 1;\n        } else if (flag & 32) {\n          yLength = 0;\n        }\n        const xyLength = xLength + yLength;\n        coordinatesLength += xyLength;\n        if (flag & 8) {\n          const repeat = glyf[j++];\n          if (repeat === 0) {\n            glyf[j - 1] ^= 8;\n          }\n          i += repeat;\n          coordinatesLength += repeat * xyLength;\n        }\n      }\n      if (coordinatesLength === 0) {\n        return glyphProfile;\n      }\n      let glyphDataLength = j + coordinatesLength;\n      if (glyphDataLength > glyf.length) {\n        return glyphProfile;\n      }\n      if (!hintsValid && instructionsLength > 0) {\n        dest.set(glyf.subarray(0, instructionsStart), destStart);\n        dest.set([0, 0], destStart + instructionsStart);\n        dest.set(glyf.subarray(instructionsEnd, glyphDataLength), destStart + instructionsStart + 2);\n        glyphDataLength -= instructionsLength;\n        if (glyf.length - glyphDataLength > 3) {\n          glyphDataLength = glyphDataLength + 3 & ~3;\n        }\n        glyphProfile.length = glyphDataLength;\n        return glyphProfile;\n      }\n      if (glyf.length - glyphDataLength > 3) {\n        glyphDataLength = glyphDataLength + 3 & ~3;\n        dest.set(glyf.subarray(0, glyphDataLength), destStart);\n        glyphProfile.length = glyphDataLength;\n        return glyphProfile;\n      }\n      dest.set(glyf, destStart);\n      glyphProfile.length = glyf.length;\n      return glyphProfile;\n    }\n    function sanitizeHead(head, numGlyphs, locaLength) {\n      const data = head.data;\n      const version = int32(data[0], data[1], data[2], data[3]);\n      if (version >> 16 !== 1) {\n        info(\"Attempting to fix invalid version in head table: \" + version);\n        data[0] = 0;\n        data[1] = 1;\n        data[2] = 0;\n        data[3] = 0;\n      }\n      const indexToLocFormat = int16(data[50], data[51]);\n      if (indexToLocFormat < 0 || indexToLocFormat > 1) {\n        info(\"Attempting to fix invalid indexToLocFormat in head table: \" + indexToLocFormat);\n        const numGlyphsPlusOne = numGlyphs + 1;\n        if (locaLength === numGlyphsPlusOne << 1) {\n          data[50] = 0;\n          data[51] = 0;\n        } else if (locaLength === numGlyphsPlusOne << 2) {\n          data[50] = 0;\n          data[51] = 1;\n        } else {\n          throw new FormatError(\"Could not fix indexToLocFormat: \" + indexToLocFormat);\n        }\n      }\n    }\n    function sanitizeGlyphLocations(loca, glyf, numGlyphs, isGlyphLocationsLong, hintsValid, dupFirstEntry, maxSizeOfInstructions) {\n      let itemSize, itemDecode, itemEncode;\n      if (isGlyphLocationsLong) {\n        itemSize = 4;\n        itemDecode = function fontItemDecodeLong(data, offset) {\n          return data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3];\n        };\n        itemEncode = function fontItemEncodeLong(data, offset, value) {\n          data[offset] = value >>> 24 & 0xff;\n          data[offset + 1] = value >> 16 & 0xff;\n          data[offset + 2] = value >> 8 & 0xff;\n          data[offset + 3] = value & 0xff;\n        };\n      } else {\n        itemSize = 2;\n        itemDecode = function fontItemDecode(data, offset) {\n          return data[offset] << 9 | data[offset + 1] << 1;\n        };\n        itemEncode = function fontItemEncode(data, offset, value) {\n          data[offset] = value >> 9 & 0xff;\n          data[offset + 1] = value >> 1 & 0xff;\n        };\n      }\n      const numGlyphsOut = dupFirstEntry ? numGlyphs + 1 : numGlyphs;\n      const locaDataSize = itemSize * (1 + numGlyphsOut);\n      const locaData = new Uint8Array(locaDataSize);\n      locaData.set(loca.data.subarray(0, locaDataSize));\n      loca.data = locaData;\n      const oldGlyfData = glyf.data;\n      const oldGlyfDataLength = oldGlyfData.length;\n      const newGlyfData = new Uint8Array(oldGlyfDataLength);\n      let i, j;\n      const locaEntries = [];\n      for (i = 0, j = 0; i < numGlyphs + 1; i++, j += itemSize) {\n        let offset = itemDecode(locaData, j);\n        if (offset > oldGlyfDataLength) {\n          offset = oldGlyfDataLength;\n        }\n        locaEntries.push({\n          index: i,\n          offset,\n          endOffset: 0\n        });\n      }\n      locaEntries.sort((a, b) => a.offset - b.offset);\n      for (i = 0; i < numGlyphs; i++) {\n        locaEntries[i].endOffset = locaEntries[i + 1].offset;\n      }\n      locaEntries.sort((a, b) => a.index - b.index);\n      for (i = 0; i < numGlyphs; i++) {\n        const {\n          offset,\n          endOffset\n        } = locaEntries[i];\n        if (offset !== 0 || endOffset !== 0) {\n          break;\n        }\n        const nextOffset = locaEntries[i + 1].offset;\n        if (nextOffset === 0) {\n          continue;\n        }\n        locaEntries[i].endOffset = nextOffset;\n        break;\n      }\n      const last = locaEntries.at(-2);\n      if (last.offset !== 0 && last.endOffset === 0) {\n        last.endOffset = oldGlyfDataLength;\n      }\n      const missingGlyphs = Object.create(null);\n      let writeOffset = 0;\n      itemEncode(locaData, 0, writeOffset);\n      for (i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) {\n        const glyphProfile = sanitizeGlyph(oldGlyfData, locaEntries[i].offset, locaEntries[i].endOffset, newGlyfData, writeOffset, hintsValid);\n        const newLength = glyphProfile.length;\n        if (newLength === 0) {\n          missingGlyphs[i] = true;\n        }\n        if (glyphProfile.sizeOfInstructions > maxSizeOfInstructions) {\n          maxSizeOfInstructions = glyphProfile.sizeOfInstructions;\n        }\n        writeOffset += newLength;\n        itemEncode(locaData, j, writeOffset);\n      }\n      if (writeOffset === 0) {\n        const simpleGlyph = new Uint8Array([0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0]);\n        for (i = 0, j = itemSize; i < numGlyphsOut; i++, j += itemSize) {\n          itemEncode(locaData, j, simpleGlyph.length);\n        }\n        glyf.data = simpleGlyph;\n      } else if (dupFirstEntry) {\n        const firstEntryLength = itemDecode(locaData, itemSize);\n        if (newGlyfData.length > firstEntryLength + writeOffset) {\n          glyf.data = newGlyfData.subarray(0, firstEntryLength + writeOffset);\n        } else {\n          glyf.data = new Uint8Array(firstEntryLength + writeOffset);\n          glyf.data.set(newGlyfData.subarray(0, writeOffset));\n        }\n        glyf.data.set(newGlyfData.subarray(0, firstEntryLength), writeOffset);\n        itemEncode(loca.data, locaData.length - itemSize, writeOffset + firstEntryLength);\n      } else {\n        glyf.data = newGlyfData.subarray(0, writeOffset);\n      }\n      return {\n        missingGlyphs,\n        maxSizeOfInstructions\n      };\n    }\n    function readPostScriptTable(post, propertiesObj, maxpNumGlyphs) {\n      const start = (font.start || 0) + post.offset;\n      font.pos = start;\n      const length = post.length,\n        end = start + length;\n      const version = font.getInt32();\n      font.skip(28);\n      let glyphNames;\n      let valid = true;\n      let i;\n      switch (version) {\n        case 0x00010000:\n          glyphNames = MacStandardGlyphOrdering;\n          break;\n        case 0x00020000:\n          const numGlyphs = font.getUint16();\n          if (numGlyphs !== maxpNumGlyphs) {\n            valid = false;\n            break;\n          }\n          const glyphNameIndexes = [];\n          for (i = 0; i < numGlyphs; ++i) {\n            const index = font.getUint16();\n            if (index >= 32768) {\n              valid = false;\n              break;\n            }\n            glyphNameIndexes.push(index);\n          }\n          if (!valid) {\n            break;\n          }\n          const customNames = [],\n            strBuf = [];\n          while (font.pos < end) {\n            const stringLength = font.getByte();\n            strBuf.length = stringLength;\n            for (i = 0; i < stringLength; ++i) {\n              strBuf[i] = String.fromCharCode(font.getByte());\n            }\n            customNames.push(strBuf.join(\"\"));\n          }\n          glyphNames = [];\n          for (i = 0; i < numGlyphs; ++i) {\n            const j = glyphNameIndexes[i];\n            if (j < 258) {\n              glyphNames.push(MacStandardGlyphOrdering[j]);\n              continue;\n            }\n            glyphNames.push(customNames[j - 258]);\n          }\n          break;\n        case 0x00030000:\n          break;\n        default:\n          warn(\"Unknown/unsupported post table version \" + version);\n          valid = false;\n          if (propertiesObj.defaultEncoding) {\n            glyphNames = propertiesObj.defaultEncoding;\n          }\n          break;\n      }\n      propertiesObj.glyphNames = glyphNames;\n      return valid;\n    }\n    function readNameTable(nameTable) {\n      const start = (font.start || 0) + nameTable.offset;\n      font.pos = start;\n      const names = [[], []],\n        records = [];\n      const length = nameTable.length,\n        end = start + length;\n      const format = font.getUint16();\n      const FORMAT_0_HEADER_LENGTH = 6;\n      if (format !== 0 || length < FORMAT_0_HEADER_LENGTH) {\n        return [names, records];\n      }\n      const numRecords = font.getUint16();\n      const stringsStart = font.getUint16();\n      const NAME_RECORD_LENGTH = 12;\n      let i, ii;\n      for (i = 0; i < numRecords && font.pos + NAME_RECORD_LENGTH <= end; i++) {\n        const r = {\n          platform: font.getUint16(),\n          encoding: font.getUint16(),\n          language: font.getUint16(),\n          name: font.getUint16(),\n          length: font.getUint16(),\n          offset: font.getUint16()\n        };\n        if (isMacNameRecord(r) || isWinNameRecord(r)) {\n          records.push(r);\n        }\n      }\n      for (i = 0, ii = records.length; i < ii; i++) {\n        const record = records[i];\n        if (record.length <= 0) {\n          continue;\n        }\n        const pos = start + stringsStart + record.offset;\n        if (pos + record.length > end) {\n          continue;\n        }\n        font.pos = pos;\n        const nameIndex = record.name;\n        if (record.encoding) {\n          let str = \"\";\n          for (let j = 0, jj = record.length; j < jj; j += 2) {\n            str += String.fromCharCode(font.getUint16());\n          }\n          names[1][nameIndex] = str;\n        } else {\n          names[0][nameIndex] = font.getString(record.length);\n        }\n      }\n      return [names, records];\n    }\n    const TTOpsStackDeltas = [0, 0, 0, 0, 0, 0, 0, 0, -2, -2, -2, -2, 0, 0, -2, -5, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, -1, -1, 1, -1, -999, 0, 1, 0, -1, -2, 0, -1, -2, -1, -1, 0, -1, -1, 0, 0, -999, -999, -1, -1, -1, -1, -2, -999, -2, -2, -999, 0, -2, -2, 0, 0, -2, 0, -2, 0, 0, 0, -2, -1, -1, 1, 1, 0, 0, -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, 0, -999, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -999, -999, -999, -999, -999, -1, -1, -2, -2, 0, 0, 0, 0, -1, -1, -999, -2, -2, 0, 0, -1, -2, -2, 0, 0, 0, -1, -1, -1, -2];\n    function sanitizeTTProgram(table, ttContext) {\n      let data = table.data;\n      let i = 0,\n        j,\n        n,\n        b,\n        funcId,\n        pc,\n        lastEndf = 0,\n        lastDeff = 0;\n      const stack = [];\n      const callstack = [];\n      const functionsCalled = [];\n      let tooComplexToFollowFunctions = ttContext.tooComplexToFollowFunctions;\n      let inFDEF = false,\n        ifLevel = 0,\n        inELSE = 0;\n      for (let ii = data.length; i < ii;) {\n        const op = data[i++];\n        if (op === 0x40) {\n          n = data[i++];\n          if (inFDEF || inELSE) {\n            i += n;\n          } else {\n            for (j = 0; j < n; j++) {\n              stack.push(data[i++]);\n            }\n          }\n        } else if (op === 0x41) {\n          n = data[i++];\n          if (inFDEF || inELSE) {\n            i += n * 2;\n          } else {\n            for (j = 0; j < n; j++) {\n              b = data[i++];\n              stack.push(b << 8 | data[i++]);\n            }\n          }\n        } else if ((op & 0xf8) === 0xb0) {\n          n = op - 0xb0 + 1;\n          if (inFDEF || inELSE) {\n            i += n;\n          } else {\n            for (j = 0; j < n; j++) {\n              stack.push(data[i++]);\n            }\n          }\n        } else if ((op & 0xf8) === 0xb8) {\n          n = op - 0xb8 + 1;\n          if (inFDEF || inELSE) {\n            i += n * 2;\n          } else {\n            for (j = 0; j < n; j++) {\n              b = data[i++];\n              stack.push(b << 8 | data[i++]);\n            }\n          }\n        } else if (op === 0x2b && !tooComplexToFollowFunctions) {\n          if (!inFDEF && !inELSE) {\n            funcId = stack.at(-1);\n            if (isNaN(funcId)) {\n              info(\"TT: CALL empty stack (or invalid entry).\");\n            } else {\n              ttContext.functionsUsed[funcId] = true;\n              if (funcId in ttContext.functionsStackDeltas) {\n                const newStackLength = stack.length + ttContext.functionsStackDeltas[funcId];\n                if (newStackLength < 0) {\n                  warn(\"TT: CALL invalid functions stack delta.\");\n                  ttContext.hintsValid = false;\n                  return;\n                }\n                stack.length = newStackLength;\n              } else if (funcId in ttContext.functionsDefined && !functionsCalled.includes(funcId)) {\n                callstack.push({\n                  data,\n                  i,\n                  stackTop: stack.length - 1\n                });\n                functionsCalled.push(funcId);\n                pc = ttContext.functionsDefined[funcId];\n                if (!pc) {\n                  warn(\"TT: CALL non-existent function\");\n                  ttContext.hintsValid = false;\n                  return;\n                }\n                data = pc.data;\n                i = pc.i;\n              }\n            }\n          }\n        } else if (op === 0x2c && !tooComplexToFollowFunctions) {\n          if (inFDEF || inELSE) {\n            warn(\"TT: nested FDEFs not allowed\");\n            tooComplexToFollowFunctions = true;\n          }\n          inFDEF = true;\n          lastDeff = i;\n          funcId = stack.pop();\n          ttContext.functionsDefined[funcId] = {\n            data,\n            i\n          };\n        } else if (op === 0x2d) {\n          if (inFDEF) {\n            inFDEF = false;\n            lastEndf = i;\n          } else {\n            pc = callstack.pop();\n            if (!pc) {\n              warn(\"TT: ENDF bad stack\");\n              ttContext.hintsValid = false;\n              return;\n            }\n            funcId = functionsCalled.pop();\n            data = pc.data;\n            i = pc.i;\n            ttContext.functionsStackDeltas[funcId] = stack.length - pc.stackTop;\n          }\n        } else if (op === 0x89) {\n          if (inFDEF || inELSE) {\n            warn(\"TT: nested IDEFs not allowed\");\n            tooComplexToFollowFunctions = true;\n          }\n          inFDEF = true;\n          lastDeff = i;\n        } else if (op === 0x58) {\n          ++ifLevel;\n        } else if (op === 0x1b) {\n          inELSE = ifLevel;\n        } else if (op === 0x59) {\n          if (inELSE === ifLevel) {\n            inELSE = 0;\n          }\n          --ifLevel;\n        } else if (op === 0x1c) {\n          if (!inFDEF && !inELSE) {\n            const offset = stack.at(-1);\n            if (offset > 0) {\n              i += offset - 1;\n            }\n          }\n        }\n        if (!inFDEF && !inELSE) {\n          let stackDelta = 0;\n          if (op <= 0x8e) {\n            stackDelta = TTOpsStackDeltas[op];\n          } else if (op >= 0xc0 && op <= 0xdf) {\n            stackDelta = -1;\n          } else if (op >= 0xe0) {\n            stackDelta = -2;\n          }\n          if (op >= 0x71 && op <= 0x75) {\n            n = stack.pop();\n            if (!isNaN(n)) {\n              stackDelta = -n * 2;\n            }\n          }\n          while (stackDelta < 0 && stack.length > 0) {\n            stack.pop();\n            stackDelta++;\n          }\n          while (stackDelta > 0) {\n            stack.push(NaN);\n            stackDelta--;\n          }\n        }\n      }\n      ttContext.tooComplexToFollowFunctions = tooComplexToFollowFunctions;\n      const content = [data];\n      if (i > data.length) {\n        content.push(new Uint8Array(i - data.length));\n      }\n      if (lastDeff > lastEndf) {\n        warn(\"TT: complementing a missing function tail\");\n        content.push(new Uint8Array([0x22, 0x2d]));\n      }\n      foldTTTable(table, content);\n    }\n    function checkInvalidFunctions(ttContext, maxFunctionDefs) {\n      if (ttContext.tooComplexToFollowFunctions) {\n        return;\n      }\n      if (ttContext.functionsDefined.length > maxFunctionDefs) {\n        warn(\"TT: more functions defined than expected\");\n        ttContext.hintsValid = false;\n        return;\n      }\n      for (let j = 0, jj = ttContext.functionsUsed.length; j < jj; j++) {\n        if (j > maxFunctionDefs) {\n          warn(\"TT: invalid function id: \" + j);\n          ttContext.hintsValid = false;\n          return;\n        }\n        if (ttContext.functionsUsed[j] && !ttContext.functionsDefined[j]) {\n          warn(\"TT: undefined function: \" + j);\n          ttContext.hintsValid = false;\n          return;\n        }\n      }\n    }\n    function foldTTTable(table, content) {\n      if (content.length > 1) {\n        let newLength = 0;\n        let j, jj;\n        for (j = 0, jj = content.length; j < jj; j++) {\n          newLength += content[j].length;\n        }\n        newLength = newLength + 3 & ~3;\n        const result = new Uint8Array(newLength);\n        let pos = 0;\n        for (j = 0, jj = content.length; j < jj; j++) {\n          result.set(content[j], pos);\n          pos += content[j].length;\n        }\n        table.data = result;\n        table.length = newLength;\n      }\n    }\n    function sanitizeTTPrograms(fpgm, prep, cvt, maxFunctionDefs) {\n      const ttContext = {\n        functionsDefined: [],\n        functionsUsed: [],\n        functionsStackDeltas: [],\n        tooComplexToFollowFunctions: false,\n        hintsValid: true\n      };\n      if (fpgm) {\n        sanitizeTTProgram(fpgm, ttContext);\n      }\n      if (prep) {\n        sanitizeTTProgram(prep, ttContext);\n      }\n      if (fpgm) {\n        checkInvalidFunctions(ttContext, maxFunctionDefs);\n      }\n      if (cvt && cvt.length & 1) {\n        const cvtData = new Uint8Array(cvt.length + 1);\n        cvtData.set(cvt.data);\n        cvt.data = cvtData;\n      }\n      return ttContext.hintsValid;\n    }\n    font = new Stream(new Uint8Array(font.getBytes()));\n    let header, tables;\n    if (isTrueTypeCollectionFile(font)) {\n      const ttcData = readTrueTypeCollectionData(font, this.name);\n      header = ttcData.header;\n      tables = ttcData.tables;\n    } else {\n      header = readOpenTypeHeader(font);\n      tables = readTables(font, header.numTables);\n    }\n    let cff, cffFile;\n    const isTrueType = !tables[\"CFF \"];\n    if (!isTrueType) {\n      const isComposite = properties.composite && (properties.cidToGidMap?.length > 0 || !(properties.cMap instanceof IdentityCMap));\n      if (header.version === \"OTTO\" && !isComposite || !tables.head || !tables.hhea || !tables.maxp || !tables.post) {\n        cffFile = new Stream(tables[\"CFF \"].data);\n        cff = new CFFFont(cffFile, properties);\n        adjustWidths(properties);\n        return this.convert(name, cff, properties);\n      }\n      delete tables.glyf;\n      delete tables.loca;\n      delete tables.fpgm;\n      delete tables.prep;\n      delete tables[\"cvt \"];\n      this.isOpenType = true;\n    } else {\n      if (!tables.loca) {\n        throw new FormatError('Required \"loca\" table is not found');\n      }\n      if (!tables.glyf) {\n        warn('Required \"glyf\" table is not found -- trying to recover.');\n        tables.glyf = {\n          tag: \"glyf\",\n          data: new Uint8Array(0)\n        };\n      }\n      this.isOpenType = false;\n    }\n    if (!tables.maxp) {\n      throw new FormatError('Required \"maxp\" table is not found');\n    }\n    font.pos = (font.start || 0) + tables.maxp.offset;\n    let version = font.getInt32();\n    const numGlyphs = font.getUint16();\n    if (version !== 0x00010000 && version !== 0x00005000) {\n      if (tables.maxp.length === 6) {\n        version = 0x0005000;\n      } else if (tables.maxp.length >= 32) {\n        version = 0x00010000;\n      } else {\n        throw new FormatError(`\"maxp\" table has a wrong version number`);\n      }\n      writeUint32(tables.maxp.data, 0, version);\n    }\n    if (properties.scaleFactors?.length === numGlyphs && isTrueType) {\n      const {\n        scaleFactors\n      } = properties;\n      const isGlyphLocationsLong = int16(tables.head.data[50], tables.head.data[51]);\n      const glyphs = new GlyfTable({\n        glyfTable: tables.glyf.data,\n        isGlyphLocationsLong,\n        locaTable: tables.loca.data,\n        numGlyphs\n      });\n      glyphs.scale(scaleFactors);\n      const {\n        glyf,\n        loca,\n        isLocationLong\n      } = glyphs.write();\n      tables.glyf.data = glyf;\n      tables.loca.data = loca;\n      if (isLocationLong !== !!isGlyphLocationsLong) {\n        tables.head.data[50] = 0;\n        tables.head.data[51] = isLocationLong ? 1 : 0;\n      }\n      const metrics = tables.hmtx.data;\n      for (let i = 0; i < numGlyphs; i++) {\n        const j = 4 * i;\n        const advanceWidth = Math.round(scaleFactors[i] * int16(metrics[j], metrics[j + 1]));\n        metrics[j] = advanceWidth >> 8 & 0xff;\n        metrics[j + 1] = advanceWidth & 0xff;\n        const lsb = Math.round(scaleFactors[i] * signedInt16(metrics[j + 2], metrics[j + 3]));\n        writeSignedInt16(metrics, j + 2, lsb);\n      }\n    }\n    let numGlyphsOut = numGlyphs + 1;\n    let dupFirstEntry = true;\n    if (numGlyphsOut > 0xffff) {\n      dupFirstEntry = false;\n      numGlyphsOut = numGlyphs;\n      warn(\"Not enough space in glyfs to duplicate first glyph.\");\n    }\n    let maxFunctionDefs = 0;\n    let maxSizeOfInstructions = 0;\n    if (version >= 0x00010000 && tables.maxp.length >= 32) {\n      font.pos += 8;\n      const maxZones = font.getUint16();\n      if (maxZones > 2) {\n        tables.maxp.data[14] = 0;\n        tables.maxp.data[15] = 2;\n      }\n      font.pos += 4;\n      maxFunctionDefs = font.getUint16();\n      font.pos += 4;\n      maxSizeOfInstructions = font.getUint16();\n    }\n    tables.maxp.data[4] = numGlyphsOut >> 8;\n    tables.maxp.data[5] = numGlyphsOut & 255;\n    const hintsValid = sanitizeTTPrograms(tables.fpgm, tables.prep, tables[\"cvt \"], maxFunctionDefs);\n    if (!hintsValid) {\n      delete tables.fpgm;\n      delete tables.prep;\n      delete tables[\"cvt \"];\n    }\n    sanitizeMetrics(font, tables.hhea, tables.hmtx, tables.head, numGlyphsOut, dupFirstEntry);\n    if (!tables.head) {\n      throw new FormatError('Required \"head\" table is not found');\n    }\n    sanitizeHead(tables.head, numGlyphs, isTrueType ? tables.loca.length : 0);\n    let missingGlyphs = Object.create(null);\n    if (isTrueType) {\n      const isGlyphLocationsLong = int16(tables.head.data[50], tables.head.data[51]);\n      const glyphsInfo = sanitizeGlyphLocations(tables.loca, tables.glyf, numGlyphs, isGlyphLocationsLong, hintsValid, dupFirstEntry, maxSizeOfInstructions);\n      missingGlyphs = glyphsInfo.missingGlyphs;\n      if (version >= 0x00010000 && tables.maxp.length >= 32) {\n        tables.maxp.data[26] = glyphsInfo.maxSizeOfInstructions >> 8;\n        tables.maxp.data[27] = glyphsInfo.maxSizeOfInstructions & 255;\n      }\n    }\n    if (!tables.hhea) {\n      throw new FormatError('Required \"hhea\" table is not found');\n    }\n    if (tables.hhea.data[10] === 0 && tables.hhea.data[11] === 0) {\n      tables.hhea.data[10] = 0xff;\n      tables.hhea.data[11] = 0xff;\n    }\n    const metricsOverride = {\n      unitsPerEm: int16(tables.head.data[18], tables.head.data[19]),\n      yMax: signedInt16(tables.head.data[42], tables.head.data[43]),\n      yMin: signedInt16(tables.head.data[38], tables.head.data[39]),\n      ascent: signedInt16(tables.hhea.data[4], tables.hhea.data[5]),\n      descent: signedInt16(tables.hhea.data[6], tables.hhea.data[7]),\n      lineGap: signedInt16(tables.hhea.data[8], tables.hhea.data[9])\n    };\n    this.ascent = metricsOverride.ascent / metricsOverride.unitsPerEm;\n    this.descent = metricsOverride.descent / metricsOverride.unitsPerEm;\n    this.lineGap = metricsOverride.lineGap / metricsOverride.unitsPerEm;\n    if (this.cssFontInfo?.lineHeight) {\n      this.lineHeight = this.cssFontInfo.metrics.lineHeight;\n      this.lineGap = this.cssFontInfo.metrics.lineGap;\n    } else {\n      this.lineHeight = this.ascent - this.descent + this.lineGap;\n    }\n    if (tables.post) {\n      readPostScriptTable(tables.post, properties, numGlyphs);\n    }\n    tables.post = {\n      tag: \"post\",\n      data: createPostTable(properties)\n    };\n    const charCodeToGlyphId = [];\n    function hasGlyph(glyphId) {\n      return !missingGlyphs[glyphId];\n    }\n    if (properties.composite) {\n      const cidToGidMap = properties.cidToGidMap || [];\n      const isCidToGidMapEmpty = cidToGidMap.length === 0;\n      properties.cMap.forEach(function (charCode, cid) {\n        if (typeof cid === \"string\") {\n          cid = convertCidString(charCode, cid, true);\n        }\n        if (cid > 0xffff) {\n          throw new FormatError(\"Max size of CID is 65,535\");\n        }\n        let glyphId = -1;\n        if (isCidToGidMapEmpty) {\n          glyphId = cid;\n        } else if (cidToGidMap[cid] !== undefined) {\n          glyphId = cidToGidMap[cid];\n        }\n        if (glyphId >= 0 && glyphId < numGlyphs && hasGlyph(glyphId)) {\n          charCodeToGlyphId[charCode] = glyphId;\n        }\n      });\n    } else {\n      const cmapTable = readCmapTable(tables.cmap, font, this.isSymbolicFont, properties.hasEncoding);\n      const cmapPlatformId = cmapTable.platformId;\n      const cmapEncodingId = cmapTable.encodingId;\n      const cmapMappings = cmapTable.mappings;\n      let baseEncoding = [],\n        forcePostTable = false;\n      if (properties.hasEncoding && (properties.baseEncodingName === \"MacRomanEncoding\" || properties.baseEncodingName === \"WinAnsiEncoding\")) {\n        baseEncoding = getEncoding(properties.baseEncodingName);\n      }\n      if (properties.hasEncoding && !this.isSymbolicFont && (cmapPlatformId === 3 && cmapEncodingId === 1 || cmapPlatformId === 1 && cmapEncodingId === 0)) {\n        const glyphsUnicodeMap = getGlyphsUnicode();\n        for (let charCode = 0; charCode < 256; charCode++) {\n          let glyphName;\n          if (this.differences[charCode] !== undefined) {\n            glyphName = this.differences[charCode];\n          } else if (baseEncoding.length && baseEncoding[charCode] !== \"\") {\n            glyphName = baseEncoding[charCode];\n          } else {\n            glyphName = StandardEncoding[charCode];\n          }\n          if (!glyphName) {\n            continue;\n          }\n          const standardGlyphName = recoverGlyphName(glyphName, glyphsUnicodeMap);\n          let unicodeOrCharCode;\n          if (cmapPlatformId === 3 && cmapEncodingId === 1) {\n            unicodeOrCharCode = glyphsUnicodeMap[standardGlyphName];\n          } else if (cmapPlatformId === 1 && cmapEncodingId === 0) {\n            unicodeOrCharCode = MacRomanEncoding.indexOf(standardGlyphName);\n          }\n          if (unicodeOrCharCode === undefined) {\n            if (!properties.glyphNames && properties.hasIncludedToUnicodeMap && !(this.toUnicode instanceof IdentityToUnicodeMap)) {\n              const unicode = this.toUnicode.get(charCode);\n              if (unicode) {\n                unicodeOrCharCode = unicode.codePointAt(0);\n              }\n            }\n            if (unicodeOrCharCode === undefined) {\n              continue;\n            }\n          }\n          for (const mapping of cmapMappings) {\n            if (mapping.charCode !== unicodeOrCharCode) {\n              continue;\n            }\n            charCodeToGlyphId[charCode] = mapping.glyphId;\n            break;\n          }\n        }\n      } else if (cmapPlatformId === 0) {\n        for (const mapping of cmapMappings) {\n          charCodeToGlyphId[mapping.charCode] = mapping.glyphId;\n        }\n        forcePostTable = true;\n      } else if (cmapPlatformId === 3 && cmapEncodingId === 0) {\n        for (const mapping of cmapMappings) {\n          let charCode = mapping.charCode;\n          if (charCode >= 0xf000 && charCode <= 0xf0ff) {\n            charCode &= 0xff;\n          }\n          charCodeToGlyphId[charCode] = mapping.glyphId;\n        }\n      } else {\n        for (const mapping of cmapMappings) {\n          charCodeToGlyphId[mapping.charCode] = mapping.glyphId;\n        }\n      }\n      if (properties.glyphNames && (baseEncoding.length || this.differences.length)) {\n        for (let i = 0; i < 256; ++i) {\n          if (!forcePostTable && charCodeToGlyphId[i] !== undefined) {\n            continue;\n          }\n          const glyphName = this.differences[i] || baseEncoding[i];\n          if (!glyphName) {\n            continue;\n          }\n          const glyphId = properties.glyphNames.indexOf(glyphName);\n          if (glyphId > 0 && hasGlyph(glyphId)) {\n            charCodeToGlyphId[i] = glyphId;\n          }\n        }\n      }\n    }\n    if (charCodeToGlyphId.length === 0) {\n      charCodeToGlyphId[0] = 0;\n    }\n    let glyphZeroId = numGlyphsOut - 1;\n    if (!dupFirstEntry) {\n      glyphZeroId = 0;\n    }\n    if (!properties.cssFontInfo) {\n      const newMapping = adjustMapping(charCodeToGlyphId, hasGlyph, glyphZeroId, this.toUnicode);\n      this.toFontChar = newMapping.toFontChar;\n      tables.cmap = {\n        tag: \"cmap\",\n        data: createCmapTable(newMapping.charCodeToGlyphId, newMapping.toUnicodeExtraMap, numGlyphsOut)\n      };\n      if (!tables[\"OS/2\"] || !validateOS2Table(tables[\"OS/2\"], font)) {\n        tables[\"OS/2\"] = {\n          tag: \"OS/2\",\n          data: createOS2Table(properties, newMapping.charCodeToGlyphId, metricsOverride)\n        };\n      }\n    }\n    if (!isTrueType) {\n      try {\n        cffFile = new Stream(tables[\"CFF \"].data);\n        const parser = new CFFParser(cffFile, properties, SEAC_ANALYSIS_ENABLED);\n        cff = parser.parse();\n        cff.duplicateFirstGlyph();\n        const compiler = new CFFCompiler(cff);\n        tables[\"CFF \"].data = compiler.compile();\n      } catch {\n        warn(\"Failed to compile font \" + properties.loadedName);\n      }\n    }\n    if (!tables.name) {\n      tables.name = {\n        tag: \"name\",\n        data: createNameTable(this.name)\n      };\n    } else {\n      const [namePrototype, nameRecords] = readNameTable(tables.name);\n      tables.name.data = createNameTable(name, namePrototype);\n      this.psName = namePrototype[0][6] || null;\n      if (!properties.composite) {\n        adjustTrueTypeToUnicode(properties, this.isSymbolicFont, nameRecords);\n      }\n    }\n    const builder = new OpenTypeFileBuilder(header.version);\n    for (const tableTag in tables) {\n      builder.addTable(tableTag, tables[tableTag].data);\n    }\n    return builder.toArray();\n  }\n  convert(fontName, font, properties) {\n    properties.fixedPitch = false;\n    if (properties.builtInEncoding) {\n      adjustType1ToUnicode(properties, properties.builtInEncoding);\n    }\n    let glyphZeroId = 1;\n    if (font instanceof CFFFont) {\n      glyphZeroId = font.numGlyphs - 1;\n    }\n    const mapping = font.getGlyphMapping(properties);\n    let newMapping = null;\n    let newCharCodeToGlyphId = mapping;\n    let toUnicodeExtraMap = null;\n    if (!properties.cssFontInfo) {\n      newMapping = adjustMapping(mapping, font.hasGlyphId.bind(font), glyphZeroId, this.toUnicode);\n      this.toFontChar = newMapping.toFontChar;\n      newCharCodeToGlyphId = newMapping.charCodeToGlyphId;\n      toUnicodeExtraMap = newMapping.toUnicodeExtraMap;\n    }\n    const numGlyphs = font.numGlyphs;\n    function getCharCodes(charCodeToGlyphId, glyphId) {\n      let charCodes = null;\n      for (const charCode in charCodeToGlyphId) {\n        if (glyphId === charCodeToGlyphId[charCode]) {\n          (charCodes ||= []).push(charCode | 0);\n        }\n      }\n      return charCodes;\n    }\n    function createCharCode(charCodeToGlyphId, glyphId) {\n      for (const charCode in charCodeToGlyphId) {\n        if (glyphId === charCodeToGlyphId[charCode]) {\n          return charCode | 0;\n        }\n      }\n      newMapping.charCodeToGlyphId[newMapping.nextAvailableFontCharCode] = glyphId;\n      return newMapping.nextAvailableFontCharCode++;\n    }\n    const seacs = font.seacs;\n    if (newMapping && SEAC_ANALYSIS_ENABLED && seacs?.length) {\n      const matrix = properties.fontMatrix || FONT_IDENTITY_MATRIX;\n      const charset = font.getCharset();\n      const seacMap = Object.create(null);\n      for (let glyphId in seacs) {\n        glyphId |= 0;\n        const seac = seacs[glyphId];\n        const baseGlyphName = StandardEncoding[seac[2]];\n        const accentGlyphName = StandardEncoding[seac[3]];\n        const baseGlyphId = charset.indexOf(baseGlyphName);\n        const accentGlyphId = charset.indexOf(accentGlyphName);\n        if (baseGlyphId < 0 || accentGlyphId < 0) {\n          continue;\n        }\n        const accentOffset = {\n          x: seac[0] * matrix[0] + seac[1] * matrix[2] + matrix[4],\n          y: seac[0] * matrix[1] + seac[1] * matrix[3] + matrix[5]\n        };\n        const charCodes = getCharCodes(mapping, glyphId);\n        if (!charCodes) {\n          continue;\n        }\n        for (const charCode of charCodes) {\n          const charCodeToGlyphId = newMapping.charCodeToGlyphId;\n          const baseFontCharCode = createCharCode(charCodeToGlyphId, baseGlyphId);\n          const accentFontCharCode = createCharCode(charCodeToGlyphId, accentGlyphId);\n          seacMap[charCode] = {\n            baseFontCharCode,\n            accentFontCharCode,\n            accentOffset\n          };\n        }\n      }\n      properties.seacMap = seacMap;\n    }\n    const unitsPerEm = 1 / (properties.fontMatrix || FONT_IDENTITY_MATRIX)[0];\n    const builder = new OpenTypeFileBuilder(\"\\x4F\\x54\\x54\\x4F\");\n    builder.addTable(\"CFF \", font.data);\n    builder.addTable(\"OS/2\", createOS2Table(properties, newCharCodeToGlyphId));\n    builder.addTable(\"cmap\", createCmapTable(newCharCodeToGlyphId, toUnicodeExtraMap, numGlyphs));\n    builder.addTable(\"head\", \"\\x00\\x01\\x00\\x00\" + \"\\x00\\x00\\x10\\x00\" + \"\\x00\\x00\\x00\\x00\" + \"\\x5F\\x0F\\x3C\\xF5\" + \"\\x00\\x00\" + safeString16(unitsPerEm) + \"\\x00\\x00\\x00\\x00\\x9e\\x0b\\x7e\\x27\" + \"\\x00\\x00\\x00\\x00\\x9e\\x0b\\x7e\\x27\" + \"\\x00\\x00\" + safeString16(properties.descent) + \"\\x0F\\xFF\" + safeString16(properties.ascent) + string16(properties.italicAngle ? 2 : 0) + \"\\x00\\x11\" + \"\\x00\\x00\" + \"\\x00\\x00\" + \"\\x00\\x00\");\n    builder.addTable(\"hhea\", \"\\x00\\x01\\x00\\x00\" + safeString16(properties.ascent) + safeString16(properties.descent) + \"\\x00\\x00\" + \"\\xFF\\xFF\" + \"\\x00\\x00\" + \"\\x00\\x00\" + \"\\x00\\x00\" + safeString16(properties.capHeight) + safeString16(Math.tan(properties.italicAngle) * properties.xHeight) + \"\\x00\\x00\" + \"\\x00\\x00\" + \"\\x00\\x00\" + \"\\x00\\x00\" + \"\\x00\\x00\" + \"\\x00\\x00\" + string16(numGlyphs));\n    builder.addTable(\"hmtx\", function fontFieldsHmtx() {\n      const charstrings = font.charstrings;\n      const cffWidths = font.cff ? font.cff.widths : null;\n      let hmtx = \"\\x00\\x00\\x00\\x00\";\n      for (let i = 1, ii = numGlyphs; i < ii; i++) {\n        let width = 0;\n        if (charstrings) {\n          const charstring = charstrings[i - 1];\n          width = \"width\" in charstring ? charstring.width : 0;\n        } else if (cffWidths) {\n          width = Math.ceil(cffWidths[i] || 0);\n        }\n        hmtx += string16(width) + string16(0);\n      }\n      return hmtx;\n    }());\n    builder.addTable(\"maxp\", \"\\x00\\x00\\x50\\x00\" + string16(numGlyphs));\n    builder.addTable(\"name\", createNameTable(fontName));\n    builder.addTable(\"post\", createPostTable(properties));\n    return builder.toArray();\n  }\n  get spaceWidth() {\n    const possibleSpaceReplacements = [\"space\", \"minus\", \"one\", \"i\", \"I\"];\n    let width;\n    for (const glyphName of possibleSpaceReplacements) {\n      if (glyphName in this.widths) {\n        width = this.widths[glyphName];\n        break;\n      }\n      const glyphsUnicodeMap = getGlyphsUnicode();\n      const glyphUnicode = glyphsUnicodeMap[glyphName];\n      let charcode = 0;\n      if (this.composite && this.cMap.contains(glyphUnicode)) {\n        charcode = this.cMap.lookup(glyphUnicode);\n        if (typeof charcode === \"string\") {\n          charcode = convertCidString(glyphUnicode, charcode);\n        }\n      }\n      if (!charcode && this.toUnicode) {\n        charcode = this.toUnicode.charCodeOf(glyphUnicode);\n      }\n      if (charcode <= 0) {\n        charcode = glyphUnicode;\n      }\n      width = this.widths[charcode];\n      if (width) {\n        break;\n      }\n    }\n    return shadow(this, \"spaceWidth\", width || this.defaultWidth);\n  }\n  _charToGlyph(charcode, isSpace = false) {\n    let glyph = this._glyphCache[charcode];\n    if (glyph?.isSpace === isSpace) {\n      return glyph;\n    }\n    let fontCharCode, width, operatorListId;\n    let widthCode = charcode;\n    if (this.cMap?.contains(charcode)) {\n      widthCode = this.cMap.lookup(charcode);\n      if (typeof widthCode === \"string\") {\n        widthCode = convertCidString(charcode, widthCode);\n      }\n    }\n    width = this.widths[widthCode];\n    if (typeof width !== \"number\") {\n      width = this.defaultWidth;\n    }\n    const vmetric = this.vmetrics?.[widthCode];\n    let unicode = this.toUnicode.get(charcode) || charcode;\n    if (typeof unicode === \"number\") {\n      unicode = String.fromCharCode(unicode);\n    }\n    let isInFont = this.toFontChar[charcode] !== undefined;\n    fontCharCode = this.toFontChar[charcode] || charcode;\n    if (this.missingFile) {\n      const glyphName = this.differences[charcode] || this.defaultEncoding[charcode];\n      if ((glyphName === \".notdef\" || glyphName === \"\") && this.type === \"Type1\") {\n        fontCharCode = 0x20;\n      }\n      fontCharCode = mapSpecialUnicodeValues(fontCharCode);\n    }\n    if (this.isType3Font) {\n      operatorListId = fontCharCode;\n    }\n    let accent = null;\n    if (this.seacMap?.[charcode]) {\n      isInFont = true;\n      const seac = this.seacMap[charcode];\n      fontCharCode = seac.baseFontCharCode;\n      accent = {\n        fontChar: String.fromCodePoint(seac.accentFontCharCode),\n        offset: seac.accentOffset\n      };\n    }\n    let fontChar = \"\";\n    if (typeof fontCharCode === \"number\") {\n      if (fontCharCode <= 0x10ffff) {\n        fontChar = String.fromCodePoint(fontCharCode);\n      } else {\n        warn(`charToGlyph - invalid fontCharCode: ${fontCharCode}`);\n      }\n    }\n    glyph = new fonts_Glyph(charcode, fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont);\n    return this._glyphCache[charcode] = glyph;\n  }\n  charsToGlyphs(chars) {\n    let glyphs = this._charsCache[chars];\n    if (glyphs) {\n      return glyphs;\n    }\n    glyphs = [];\n    if (this.cMap) {\n      const c = Object.create(null),\n        ii = chars.length;\n      let i = 0;\n      while (i < ii) {\n        this.cMap.readCharCode(chars, i, c);\n        const {\n          charcode,\n          length\n        } = c;\n        i += length;\n        const glyph = this._charToGlyph(charcode, length === 1 && chars.charCodeAt(i - 1) === 0x20);\n        glyphs.push(glyph);\n      }\n    } else {\n      for (let i = 0, ii = chars.length; i < ii; ++i) {\n        const charcode = chars.charCodeAt(i);\n        const glyph = this._charToGlyph(charcode, charcode === 0x20);\n        glyphs.push(glyph);\n      }\n    }\n    return this._charsCache[chars] = glyphs;\n  }\n  getCharPositions(chars) {\n    const positions = [];\n    if (this.cMap) {\n      const c = Object.create(null);\n      let i = 0;\n      while (i < chars.length) {\n        this.cMap.readCharCode(chars, i, c);\n        const length = c.length;\n        positions.push([i, i + length]);\n        i += length;\n      }\n    } else {\n      for (let i = 0, ii = chars.length; i < ii; ++i) {\n        positions.push([i, i + 1]);\n      }\n    }\n    return positions;\n  }\n  get glyphCacheValues() {\n    return Object.values(this._glyphCache);\n  }\n  encodeString(str) {\n    const buffers = [];\n    const currentBuf = [];\n    const hasCurrentBufErrors = () => buffers.length % 2 === 1;\n    const getCharCode = this.toUnicode instanceof IdentityToUnicodeMap ? unicode => this.toUnicode.charCodeOf(unicode) : unicode => this.toUnicode.charCodeOf(String.fromCodePoint(unicode));\n    for (let i = 0, ii = str.length; i < ii; i++) {\n      const unicode = str.codePointAt(i);\n      if (unicode > 0xd7ff && (unicode < 0xe000 || unicode > 0xfffd)) {\n        i++;\n      }\n      if (this.toUnicode) {\n        const charCode = getCharCode(unicode);\n        if (charCode !== -1) {\n          if (hasCurrentBufErrors()) {\n            buffers.push(currentBuf.join(\"\"));\n            currentBuf.length = 0;\n          }\n          const charCodeLength = this.cMap ? this.cMap.getCharCodeLength(charCode) : 1;\n          for (let j = charCodeLength - 1; j >= 0; j--) {\n            currentBuf.push(String.fromCharCode(charCode >> 8 * j & 0xff));\n          }\n          continue;\n        }\n      }\n      if (!hasCurrentBufErrors()) {\n        buffers.push(currentBuf.join(\"\"));\n        currentBuf.length = 0;\n      }\n      currentBuf.push(String.fromCodePoint(unicode));\n    }\n    buffers.push(currentBuf.join(\"\"));\n    return buffers;\n  }\n}\nclass ErrorFont {\n  constructor(error) {\n    this.error = error;\n    this.loadedName = \"g_font_error\";\n    this.missingFile = true;\n  }\n  charsToGlyphs() {\n    return [];\n  }\n  encodeString(chars) {\n    return [chars];\n  }\n  exportData(extraProperties = false) {\n    return {\n      error: this.error\n    };\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/pattern.js\n\n\n\n\nconst ShadingType = {\n  FUNCTION_BASED: 1,\n  AXIAL: 2,\n  RADIAL: 3,\n  FREE_FORM_MESH: 4,\n  LATTICE_FORM_MESH: 5,\n  COONS_PATCH_MESH: 6,\n  TENSOR_PATCH_MESH: 7\n};\nclass Pattern {\n  constructor() {\n    unreachable(\"Cannot initialize Pattern.\");\n  }\n  static parseShading(shading, xref, res, pdfFunctionFactory, localColorSpaceCache) {\n    const dict = shading instanceof BaseStream ? shading.dict : shading;\n    const type = dict.get(\"ShadingType\");\n    try {\n      switch (type) {\n        case ShadingType.AXIAL:\n        case ShadingType.RADIAL:\n          return new RadialAxialShading(dict, xref, res, pdfFunctionFactory, localColorSpaceCache);\n        case ShadingType.FREE_FORM_MESH:\n        case ShadingType.LATTICE_FORM_MESH:\n        case ShadingType.COONS_PATCH_MESH:\n        case ShadingType.TENSOR_PATCH_MESH:\n          return new MeshShading(shading, xref, res, pdfFunctionFactory, localColorSpaceCache);\n        default:\n          throw new FormatError(\"Unsupported ShadingType: \" + type);\n      }\n    } catch (ex) {\n      if (ex instanceof MissingDataException) {\n        throw ex;\n      }\n      warn(ex);\n      return new DummyShading();\n    }\n  }\n}\nclass BaseShading {\n  static SMALL_NUMBER = 1e-6;\n  constructor() {\n    if (this.constructor === BaseShading) {\n      unreachable(\"Cannot initialize BaseShading.\");\n    }\n  }\n  getIR() {\n    unreachable(\"Abstract method `getIR` called.\");\n  }\n}\nclass RadialAxialShading extends BaseShading {\n  constructor(dict, xref, resources, pdfFunctionFactory, localColorSpaceCache) {\n    super();\n    this.coordsArr = dict.getArray(\"Coords\");\n    this.shadingType = dict.get(\"ShadingType\");\n    const cs = ColorSpace.parse({\n      cs: dict.getRaw(\"CS\") || dict.getRaw(\"ColorSpace\"),\n      xref,\n      resources,\n      pdfFunctionFactory,\n      localColorSpaceCache\n    });\n    const bbox = dict.getArray(\"BBox\");\n    this.bbox = Array.isArray(bbox) && bbox.length === 4 ? Util.normalizeRect(bbox) : null;\n    let t0 = 0.0,\n      t1 = 1.0;\n    if (dict.has(\"Domain\")) {\n      const domainArr = dict.getArray(\"Domain\");\n      t0 = domainArr[0];\n      t1 = domainArr[1];\n    }\n    let extendStart = false,\n      extendEnd = false;\n    if (dict.has(\"Extend\")) {\n      const extendArr = dict.getArray(\"Extend\");\n      extendStart = extendArr[0];\n      extendEnd = extendArr[1];\n    }\n    if (this.shadingType === ShadingType.RADIAL && (!extendStart || !extendEnd)) {\n      const [x1, y1, r1, x2, y2, r2] = this.coordsArr;\n      const distance = Math.hypot(x1 - x2, y1 - y2);\n      if (r1 <= r2 + distance && r2 <= r1 + distance) {\n        warn(\"Unsupported radial gradient.\");\n      }\n    }\n    this.extendStart = extendStart;\n    this.extendEnd = extendEnd;\n    const fnObj = dict.getRaw(\"Function\");\n    const fn = pdfFunctionFactory.createFromArray(fnObj);\n    const NUMBER_OF_SAMPLES = 840;\n    const step = (t1 - t0) / NUMBER_OF_SAMPLES;\n    const colorStops = this.colorStops = [];\n    if (t0 >= t1 || step <= 0) {\n      info(\"Bad shading domain.\");\n      return;\n    }\n    const color = new Float32Array(cs.numComps),\n      ratio = new Float32Array(1);\n    let rgbColor;\n    let iBase = 0;\n    ratio[0] = t0;\n    fn(ratio, 0, color, 0);\n    let rgbBase = cs.getRgb(color, 0);\n    const cssColorBase = Util.makeHexColor(rgbBase[0], rgbBase[1], rgbBase[2]);\n    colorStops.push([0, cssColorBase]);\n    let iPrev = 1;\n    ratio[0] = t0 + step;\n    fn(ratio, 0, color, 0);\n    let rgbPrev = cs.getRgb(color, 0);\n    let maxSlopeR = rgbPrev[0] - rgbBase[0] + 1;\n    let maxSlopeG = rgbPrev[1] - rgbBase[1] + 1;\n    let maxSlopeB = rgbPrev[2] - rgbBase[2] + 1;\n    let minSlopeR = rgbPrev[0] - rgbBase[0] - 1;\n    let minSlopeG = rgbPrev[1] - rgbBase[1] - 1;\n    let minSlopeB = rgbPrev[2] - rgbBase[2] - 1;\n    for (let i = 2; i < NUMBER_OF_SAMPLES; i++) {\n      ratio[0] = t0 + i * step;\n      fn(ratio, 0, color, 0);\n      rgbColor = cs.getRgb(color, 0);\n      const run = i - iBase;\n      maxSlopeR = Math.min(maxSlopeR, (rgbColor[0] - rgbBase[0] + 1) / run);\n      maxSlopeG = Math.min(maxSlopeG, (rgbColor[1] - rgbBase[1] + 1) / run);\n      maxSlopeB = Math.min(maxSlopeB, (rgbColor[2] - rgbBase[2] + 1) / run);\n      minSlopeR = Math.max(minSlopeR, (rgbColor[0] - rgbBase[0] - 1) / run);\n      minSlopeG = Math.max(minSlopeG, (rgbColor[1] - rgbBase[1] - 1) / run);\n      minSlopeB = Math.max(minSlopeB, (rgbColor[2] - rgbBase[2] - 1) / run);\n      const slopesExist = minSlopeR <= maxSlopeR && minSlopeG <= maxSlopeG && minSlopeB <= maxSlopeB;\n      if (!slopesExist) {\n        const cssColor = Util.makeHexColor(rgbPrev[0], rgbPrev[1], rgbPrev[2]);\n        colorStops.push([iPrev / NUMBER_OF_SAMPLES, cssColor]);\n        maxSlopeR = rgbColor[0] - rgbPrev[0] + 1;\n        maxSlopeG = rgbColor[1] - rgbPrev[1] + 1;\n        maxSlopeB = rgbColor[2] - rgbPrev[2] + 1;\n        minSlopeR = rgbColor[0] - rgbPrev[0] - 1;\n        minSlopeG = rgbColor[1] - rgbPrev[1] - 1;\n        minSlopeB = rgbColor[2] - rgbPrev[2] - 1;\n        iBase = iPrev;\n        rgbBase = rgbPrev;\n      }\n      iPrev = i;\n      rgbPrev = rgbColor;\n    }\n    const cssColor = Util.makeHexColor(rgbPrev[0], rgbPrev[1], rgbPrev[2]);\n    colorStops.push([1, cssColor]);\n    let background = \"transparent\";\n    if (dict.has(\"Background\")) {\n      rgbColor = cs.getRgb(dict.get(\"Background\"), 0);\n      background = Util.makeHexColor(rgbColor[0], rgbColor[1], rgbColor[2]);\n    }\n    if (!extendStart) {\n      colorStops.unshift([0, background]);\n      colorStops[1][0] += BaseShading.SMALL_NUMBER;\n    }\n    if (!extendEnd) {\n      colorStops.at(-1)[0] -= BaseShading.SMALL_NUMBER;\n      colorStops.push([1, background]);\n    }\n    this.colorStops = colorStops;\n  }\n  getIR() {\n    const coordsArr = this.coordsArr;\n    const shadingType = this.shadingType;\n    let type, p0, p1, r0, r1;\n    if (shadingType === ShadingType.AXIAL) {\n      p0 = [coordsArr[0], coordsArr[1]];\n      p1 = [coordsArr[2], coordsArr[3]];\n      r0 = null;\n      r1 = null;\n      type = \"axial\";\n    } else if (shadingType === ShadingType.RADIAL) {\n      p0 = [coordsArr[0], coordsArr[1]];\n      p1 = [coordsArr[3], coordsArr[4]];\n      r0 = coordsArr[2];\n      r1 = coordsArr[5];\n      type = \"radial\";\n    } else {\n      unreachable(`getPattern type unknown: ${shadingType}`);\n    }\n    return [\"RadialAxial\", type, this.bbox, this.colorStops, p0, p1, r0, r1];\n  }\n}\nclass MeshStreamReader {\n  constructor(stream, context) {\n    this.stream = stream;\n    this.context = context;\n    this.buffer = 0;\n    this.bufferLength = 0;\n    const numComps = context.numComps;\n    this.tmpCompsBuf = new Float32Array(numComps);\n    const csNumComps = context.colorSpace.numComps;\n    this.tmpCsCompsBuf = context.colorFn ? new Float32Array(csNumComps) : this.tmpCompsBuf;\n  }\n  get hasData() {\n    if (this.stream.end) {\n      return this.stream.pos < this.stream.end;\n    }\n    if (this.bufferLength > 0) {\n      return true;\n    }\n    const nextByte = this.stream.getByte();\n    if (nextByte < 0) {\n      return false;\n    }\n    this.buffer = nextByte;\n    this.bufferLength = 8;\n    return true;\n  }\n  readBits(n) {\n    let buffer = this.buffer;\n    let bufferLength = this.bufferLength;\n    if (n === 32) {\n      if (bufferLength === 0) {\n        return (this.stream.getByte() << 24 | this.stream.getByte() << 16 | this.stream.getByte() << 8 | this.stream.getByte()) >>> 0;\n      }\n      buffer = buffer << 24 | this.stream.getByte() << 16 | this.stream.getByte() << 8 | this.stream.getByte();\n      const nextByte = this.stream.getByte();\n      this.buffer = nextByte & (1 << bufferLength) - 1;\n      return (buffer << 8 - bufferLength | (nextByte & 0xff) >> bufferLength) >>> 0;\n    }\n    if (n === 8 && bufferLength === 0) {\n      return this.stream.getByte();\n    }\n    while (bufferLength < n) {\n      buffer = buffer << 8 | this.stream.getByte();\n      bufferLength += 8;\n    }\n    bufferLength -= n;\n    this.bufferLength = bufferLength;\n    this.buffer = buffer & (1 << bufferLength) - 1;\n    return buffer >> bufferLength;\n  }\n  align() {\n    this.buffer = 0;\n    this.bufferLength = 0;\n  }\n  readFlag() {\n    return this.readBits(this.context.bitsPerFlag);\n  }\n  readCoordinate() {\n    const bitsPerCoordinate = this.context.bitsPerCoordinate;\n    const xi = this.readBits(bitsPerCoordinate);\n    const yi = this.readBits(bitsPerCoordinate);\n    const decode = this.context.decode;\n    const scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) : 2.3283064365386963e-10;\n    return [xi * scale * (decode[1] - decode[0]) + decode[0], yi * scale * (decode[3] - decode[2]) + decode[2]];\n  }\n  readComponents() {\n    const numComps = this.context.numComps;\n    const bitsPerComponent = this.context.bitsPerComponent;\n    const scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) : 2.3283064365386963e-10;\n    const decode = this.context.decode;\n    const components = this.tmpCompsBuf;\n    for (let i = 0, j = 4; i < numComps; i++, j += 2) {\n      const ci = this.readBits(bitsPerComponent);\n      components[i] = ci * scale * (decode[j + 1] - decode[j]) + decode[j];\n    }\n    const color = this.tmpCsCompsBuf;\n    if (this.context.colorFn) {\n      this.context.colorFn(components, 0, color, 0);\n    }\n    return this.context.colorSpace.getRgb(color, 0);\n  }\n}\nlet bCache = Object.create(null);\nfunction buildB(count) {\n  const lut = [];\n  for (let i = 0; i <= count; i++) {\n    const t = i / count,\n      t_ = 1 - t;\n    lut.push(new Float32Array([t_ ** 3, 3 * t * t_ ** 2, 3 * t ** 2 * t_, t ** 3]));\n  }\n  return lut;\n}\nfunction getB(count) {\n  return bCache[count] ||= buildB(count);\n}\nfunction clearPatternCaches() {\n  bCache = Object.create(null);\n}\nclass MeshShading extends BaseShading {\n  static MIN_SPLIT_PATCH_CHUNKS_AMOUNT = 3;\n  static MAX_SPLIT_PATCH_CHUNKS_AMOUNT = 20;\n  static TRIANGLE_DENSITY = 20;\n  constructor(stream, xref, resources, pdfFunctionFactory, localColorSpaceCache) {\n    super();\n    if (!(stream instanceof BaseStream)) {\n      throw new FormatError(\"Mesh data is not a stream\");\n    }\n    const dict = stream.dict;\n    this.shadingType = dict.get(\"ShadingType\");\n    const bbox = dict.getArray(\"BBox\");\n    this.bbox = Array.isArray(bbox) && bbox.length === 4 ? Util.normalizeRect(bbox) : null;\n    const cs = ColorSpace.parse({\n      cs: dict.getRaw(\"CS\") || dict.getRaw(\"ColorSpace\"),\n      xref,\n      resources,\n      pdfFunctionFactory,\n      localColorSpaceCache\n    });\n    this.background = dict.has(\"Background\") ? cs.getRgb(dict.get(\"Background\"), 0) : null;\n    const fnObj = dict.getRaw(\"Function\");\n    const fn = fnObj ? pdfFunctionFactory.createFromArray(fnObj) : null;\n    this.coords = [];\n    this.colors = [];\n    this.figures = [];\n    const decodeContext = {\n      bitsPerCoordinate: dict.get(\"BitsPerCoordinate\"),\n      bitsPerComponent: dict.get(\"BitsPerComponent\"),\n      bitsPerFlag: dict.get(\"BitsPerFlag\"),\n      decode: dict.getArray(\"Decode\"),\n      colorFn: fn,\n      colorSpace: cs,\n      numComps: fn ? 1 : cs.numComps\n    };\n    const reader = new MeshStreamReader(stream, decodeContext);\n    let patchMesh = false;\n    switch (this.shadingType) {\n      case ShadingType.FREE_FORM_MESH:\n        this._decodeType4Shading(reader);\n        break;\n      case ShadingType.LATTICE_FORM_MESH:\n        const verticesPerRow = dict.get(\"VerticesPerRow\") | 0;\n        if (verticesPerRow < 2) {\n          throw new FormatError(\"Invalid VerticesPerRow\");\n        }\n        this._decodeType5Shading(reader, verticesPerRow);\n        break;\n      case ShadingType.COONS_PATCH_MESH:\n        this._decodeType6Shading(reader);\n        patchMesh = true;\n        break;\n      case ShadingType.TENSOR_PATCH_MESH:\n        this._decodeType7Shading(reader);\n        patchMesh = true;\n        break;\n      default:\n        unreachable(\"Unsupported mesh type.\");\n        break;\n    }\n    if (patchMesh) {\n      this._updateBounds();\n      for (let i = 0, ii = this.figures.length; i < ii; i++) {\n        this._buildFigureFromPatch(i);\n      }\n    }\n    this._updateBounds();\n    this._packData();\n  }\n  _decodeType4Shading(reader) {\n    const coords = this.coords;\n    const colors = this.colors;\n    const operators = [];\n    const ps = [];\n    let verticesLeft = 0;\n    while (reader.hasData) {\n      const f = reader.readFlag();\n      const coord = reader.readCoordinate();\n      const color = reader.readComponents();\n      if (verticesLeft === 0) {\n        if (!(0 <= f && f <= 2)) {\n          throw new FormatError(\"Unknown type4 flag\");\n        }\n        switch (f) {\n          case 0:\n            verticesLeft = 3;\n            break;\n          case 1:\n            ps.push(ps.at(-2), ps.at(-1));\n            verticesLeft = 1;\n            break;\n          case 2:\n            ps.push(ps.at(-3), ps.at(-1));\n            verticesLeft = 1;\n            break;\n        }\n        operators.push(f);\n      }\n      ps.push(coords.length);\n      coords.push(coord);\n      colors.push(color);\n      verticesLeft--;\n      reader.align();\n    }\n    this.figures.push({\n      type: \"triangles\",\n      coords: new Int32Array(ps),\n      colors: new Int32Array(ps)\n    });\n  }\n  _decodeType5Shading(reader, verticesPerRow) {\n    const coords = this.coords;\n    const colors = this.colors;\n    const ps = [];\n    while (reader.hasData) {\n      const coord = reader.readCoordinate();\n      const color = reader.readComponents();\n      ps.push(coords.length);\n      coords.push(coord);\n      colors.push(color);\n    }\n    this.figures.push({\n      type: \"lattice\",\n      coords: new Int32Array(ps),\n      colors: new Int32Array(ps),\n      verticesPerRow\n    });\n  }\n  _decodeType6Shading(reader) {\n    const coords = this.coords;\n    const colors = this.colors;\n    const ps = new Int32Array(16);\n    const cs = new Int32Array(4);\n    while (reader.hasData) {\n      const f = reader.readFlag();\n      if (!(0 <= f && f <= 3)) {\n        throw new FormatError(\"Unknown type6 flag\");\n      }\n      const pi = coords.length;\n      for (let i = 0, ii = f !== 0 ? 8 : 12; i < ii; i++) {\n        coords.push(reader.readCoordinate());\n      }\n      const ci = colors.length;\n      for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {\n        colors.push(reader.readComponents());\n      }\n      let tmp1, tmp2, tmp3, tmp4;\n      switch (f) {\n        case 0:\n          ps[12] = pi + 3;\n          ps[13] = pi + 4;\n          ps[14] = pi + 5;\n          ps[15] = pi + 6;\n          ps[8] = pi + 2;\n          ps[11] = pi + 7;\n          ps[4] = pi + 1;\n          ps[7] = pi + 8;\n          ps[0] = pi;\n          ps[1] = pi + 11;\n          ps[2] = pi + 10;\n          ps[3] = pi + 9;\n          cs[2] = ci + 1;\n          cs[3] = ci + 2;\n          cs[0] = ci;\n          cs[1] = ci + 3;\n          break;\n        case 1:\n          tmp1 = ps[12];\n          tmp2 = ps[13];\n          tmp3 = ps[14];\n          tmp4 = ps[15];\n          ps[12] = tmp4;\n          ps[13] = pi + 0;\n          ps[14] = pi + 1;\n          ps[15] = pi + 2;\n          ps[8] = tmp3;\n          ps[11] = pi + 3;\n          ps[4] = tmp2;\n          ps[7] = pi + 4;\n          ps[0] = tmp1;\n          ps[1] = pi + 7;\n          ps[2] = pi + 6;\n          ps[3] = pi + 5;\n          tmp1 = cs[2];\n          tmp2 = cs[3];\n          cs[2] = tmp2;\n          cs[3] = ci;\n          cs[0] = tmp1;\n          cs[1] = ci + 1;\n          break;\n        case 2:\n          tmp1 = ps[15];\n          tmp2 = ps[11];\n          ps[12] = ps[3];\n          ps[13] = pi + 0;\n          ps[14] = pi + 1;\n          ps[15] = pi + 2;\n          ps[8] = ps[7];\n          ps[11] = pi + 3;\n          ps[4] = tmp2;\n          ps[7] = pi + 4;\n          ps[0] = tmp1;\n          ps[1] = pi + 7;\n          ps[2] = pi + 6;\n          ps[3] = pi + 5;\n          tmp1 = cs[3];\n          cs[2] = cs[1];\n          cs[3] = ci;\n          cs[0] = tmp1;\n          cs[1] = ci + 1;\n          break;\n        case 3:\n          ps[12] = ps[0];\n          ps[13] = pi + 0;\n          ps[14] = pi + 1;\n          ps[15] = pi + 2;\n          ps[8] = ps[1];\n          ps[11] = pi + 3;\n          ps[4] = ps[2];\n          ps[7] = pi + 4;\n          ps[0] = ps[3];\n          ps[1] = pi + 7;\n          ps[2] = pi + 6;\n          ps[3] = pi + 5;\n          cs[2] = cs[0];\n          cs[3] = ci;\n          cs[0] = cs[1];\n          cs[1] = ci + 1;\n          break;\n      }\n      ps[5] = coords.length;\n      coords.push([(-4 * coords[ps[0]][0] - coords[ps[15]][0] + 6 * (coords[ps[4]][0] + coords[ps[1]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[13]][0] + coords[ps[7]][0])) / 9, (-4 * coords[ps[0]][1] - coords[ps[15]][1] + 6 * (coords[ps[4]][1] + coords[ps[1]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[13]][1] + coords[ps[7]][1])) / 9]);\n      ps[6] = coords.length;\n      coords.push([(-4 * coords[ps[3]][0] - coords[ps[12]][0] + 6 * (coords[ps[2]][0] + coords[ps[7]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[4]][0] + coords[ps[14]][0])) / 9, (-4 * coords[ps[3]][1] - coords[ps[12]][1] + 6 * (coords[ps[2]][1] + coords[ps[7]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[4]][1] + coords[ps[14]][1])) / 9]);\n      ps[9] = coords.length;\n      coords.push([(-4 * coords[ps[12]][0] - coords[ps[3]][0] + 6 * (coords[ps[8]][0] + coords[ps[13]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[11]][0] + coords[ps[1]][0])) / 9, (-4 * coords[ps[12]][1] - coords[ps[3]][1] + 6 * (coords[ps[8]][1] + coords[ps[13]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[11]][1] + coords[ps[1]][1])) / 9]);\n      ps[10] = coords.length;\n      coords.push([(-4 * coords[ps[15]][0] - coords[ps[0]][0] + 6 * (coords[ps[11]][0] + coords[ps[14]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[2]][0] + coords[ps[8]][0])) / 9, (-4 * coords[ps[15]][1] - coords[ps[0]][1] + 6 * (coords[ps[11]][1] + coords[ps[14]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[2]][1] + coords[ps[8]][1])) / 9]);\n      this.figures.push({\n        type: \"patch\",\n        coords: new Int32Array(ps),\n        colors: new Int32Array(cs)\n      });\n    }\n  }\n  _decodeType7Shading(reader) {\n    const coords = this.coords;\n    const colors = this.colors;\n    const ps = new Int32Array(16);\n    const cs = new Int32Array(4);\n    while (reader.hasData) {\n      const f = reader.readFlag();\n      if (!(0 <= f && f <= 3)) {\n        throw new FormatError(\"Unknown type7 flag\");\n      }\n      const pi = coords.length;\n      for (let i = 0, ii = f !== 0 ? 12 : 16; i < ii; i++) {\n        coords.push(reader.readCoordinate());\n      }\n      const ci = colors.length;\n      for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {\n        colors.push(reader.readComponents());\n      }\n      let tmp1, tmp2, tmp3, tmp4;\n      switch (f) {\n        case 0:\n          ps[12] = pi + 3;\n          ps[13] = pi + 4;\n          ps[14] = pi + 5;\n          ps[15] = pi + 6;\n          ps[8] = pi + 2;\n          ps[9] = pi + 13;\n          ps[10] = pi + 14;\n          ps[11] = pi + 7;\n          ps[4] = pi + 1;\n          ps[5] = pi + 12;\n          ps[6] = pi + 15;\n          ps[7] = pi + 8;\n          ps[0] = pi;\n          ps[1] = pi + 11;\n          ps[2] = pi + 10;\n          ps[3] = pi + 9;\n          cs[2] = ci + 1;\n          cs[3] = ci + 2;\n          cs[0] = ci;\n          cs[1] = ci + 3;\n          break;\n        case 1:\n          tmp1 = ps[12];\n          tmp2 = ps[13];\n          tmp3 = ps[14];\n          tmp4 = ps[15];\n          ps[12] = tmp4;\n          ps[13] = pi + 0;\n          ps[14] = pi + 1;\n          ps[15] = pi + 2;\n          ps[8] = tmp3;\n          ps[9] = pi + 9;\n          ps[10] = pi + 10;\n          ps[11] = pi + 3;\n          ps[4] = tmp2;\n          ps[5] = pi + 8;\n          ps[6] = pi + 11;\n          ps[7] = pi + 4;\n          ps[0] = tmp1;\n          ps[1] = pi + 7;\n          ps[2] = pi + 6;\n          ps[3] = pi + 5;\n          tmp1 = cs[2];\n          tmp2 = cs[3];\n          cs[2] = tmp2;\n          cs[3] = ci;\n          cs[0] = tmp1;\n          cs[1] = ci + 1;\n          break;\n        case 2:\n          tmp1 = ps[15];\n          tmp2 = ps[11];\n          ps[12] = ps[3];\n          ps[13] = pi + 0;\n          ps[14] = pi + 1;\n          ps[15] = pi + 2;\n          ps[8] = ps[7];\n          ps[9] = pi + 9;\n          ps[10] = pi + 10;\n          ps[11] = pi + 3;\n          ps[4] = tmp2;\n          ps[5] = pi + 8;\n          ps[6] = pi + 11;\n          ps[7] = pi + 4;\n          ps[0] = tmp1;\n          ps[1] = pi + 7;\n          ps[2] = pi + 6;\n          ps[3] = pi + 5;\n          tmp1 = cs[3];\n          cs[2] = cs[1];\n          cs[3] = ci;\n          cs[0] = tmp1;\n          cs[1] = ci + 1;\n          break;\n        case 3:\n          ps[12] = ps[0];\n          ps[13] = pi + 0;\n          ps[14] = pi + 1;\n          ps[15] = pi + 2;\n          ps[8] = ps[1];\n          ps[9] = pi + 9;\n          ps[10] = pi + 10;\n          ps[11] = pi + 3;\n          ps[4] = ps[2];\n          ps[5] = pi + 8;\n          ps[6] = pi + 11;\n          ps[7] = pi + 4;\n          ps[0] = ps[3];\n          ps[1] = pi + 7;\n          ps[2] = pi + 6;\n          ps[3] = pi + 5;\n          cs[2] = cs[0];\n          cs[3] = ci;\n          cs[0] = cs[1];\n          cs[1] = ci + 1;\n          break;\n      }\n      this.figures.push({\n        type: \"patch\",\n        coords: new Int32Array(ps),\n        colors: new Int32Array(cs)\n      });\n    }\n  }\n  _buildFigureFromPatch(index) {\n    const figure = this.figures[index];\n    assert(figure.type === \"patch\", \"Unexpected patch mesh figure\");\n    const coords = this.coords,\n      colors = this.colors;\n    const pi = figure.coords;\n    const ci = figure.colors;\n    const figureMinX = Math.min(coords[pi[0]][0], coords[pi[3]][0], coords[pi[12]][0], coords[pi[15]][0]);\n    const figureMinY = Math.min(coords[pi[0]][1], coords[pi[3]][1], coords[pi[12]][1], coords[pi[15]][1]);\n    const figureMaxX = Math.max(coords[pi[0]][0], coords[pi[3]][0], coords[pi[12]][0], coords[pi[15]][0]);\n    const figureMaxY = Math.max(coords[pi[0]][1], coords[pi[3]][1], coords[pi[12]][1], coords[pi[15]][1]);\n    let splitXBy = Math.ceil((figureMaxX - figureMinX) * MeshShading.TRIANGLE_DENSITY / (this.bounds[2] - this.bounds[0]));\n    splitXBy = Math.max(MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT, Math.min(MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitXBy));\n    let splitYBy = Math.ceil((figureMaxY - figureMinY) * MeshShading.TRIANGLE_DENSITY / (this.bounds[3] - this.bounds[1]));\n    splitYBy = Math.max(MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT, Math.min(MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitYBy));\n    const verticesPerRow = splitXBy + 1;\n    const figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow);\n    const figureColors = new Int32Array((splitYBy + 1) * verticesPerRow);\n    let k = 0;\n    const cl = new Uint8Array(3),\n      cr = new Uint8Array(3);\n    const c0 = colors[ci[0]],\n      c1 = colors[ci[1]],\n      c2 = colors[ci[2]],\n      c3 = colors[ci[3]];\n    const bRow = getB(splitYBy),\n      bCol = getB(splitXBy);\n    for (let row = 0; row <= splitYBy; row++) {\n      cl[0] = (c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy | 0;\n      cl[1] = (c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy | 0;\n      cl[2] = (c0[2] * (splitYBy - row) + c2[2] * row) / splitYBy | 0;\n      cr[0] = (c1[0] * (splitYBy - row) + c3[0] * row) / splitYBy | 0;\n      cr[1] = (c1[1] * (splitYBy - row) + c3[1] * row) / splitYBy | 0;\n      cr[2] = (c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy | 0;\n      for (let col = 0; col <= splitXBy; col++, k++) {\n        if ((row === 0 || row === splitYBy) && (col === 0 || col === splitXBy)) {\n          continue;\n        }\n        let x = 0,\n          y = 0;\n        let q = 0;\n        for (let i = 0; i <= 3; i++) {\n          for (let j = 0; j <= 3; j++, q++) {\n            const m = bRow[row][i] * bCol[col][j];\n            x += coords[pi[q]][0] * m;\n            y += coords[pi[q]][1] * m;\n          }\n        }\n        figureCoords[k] = coords.length;\n        coords.push([x, y]);\n        figureColors[k] = colors.length;\n        const newColor = new Uint8Array(3);\n        newColor[0] = (cl[0] * (splitXBy - col) + cr[0] * col) / splitXBy | 0;\n        newColor[1] = (cl[1] * (splitXBy - col) + cr[1] * col) / splitXBy | 0;\n        newColor[2] = (cl[2] * (splitXBy - col) + cr[2] * col) / splitXBy | 0;\n        colors.push(newColor);\n      }\n    }\n    figureCoords[0] = pi[0];\n    figureColors[0] = ci[0];\n    figureCoords[splitXBy] = pi[3];\n    figureColors[splitXBy] = ci[1];\n    figureCoords[verticesPerRow * splitYBy] = pi[12];\n    figureColors[verticesPerRow * splitYBy] = ci[2];\n    figureCoords[verticesPerRow * splitYBy + splitXBy] = pi[15];\n    figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3];\n    this.figures[index] = {\n      type: \"lattice\",\n      coords: figureCoords,\n      colors: figureColors,\n      verticesPerRow\n    };\n  }\n  _updateBounds() {\n    let minX = this.coords[0][0],\n      minY = this.coords[0][1],\n      maxX = minX,\n      maxY = minY;\n    for (let i = 1, ii = this.coords.length; i < ii; i++) {\n      const x = this.coords[i][0],\n        y = this.coords[i][1];\n      minX = minX > x ? x : minX;\n      minY = minY > y ? y : minY;\n      maxX = maxX < x ? x : maxX;\n      maxY = maxY < y ? y : maxY;\n    }\n    this.bounds = [minX, minY, maxX, maxY];\n  }\n  _packData() {\n    let i, ii, j, jj;\n    const coords = this.coords;\n    const coordsPacked = new Float32Array(coords.length * 2);\n    for (i = 0, j = 0, ii = coords.length; i < ii; i++) {\n      const xy = coords[i];\n      coordsPacked[j++] = xy[0];\n      coordsPacked[j++] = xy[1];\n    }\n    this.coords = coordsPacked;\n    const colors = this.colors;\n    const colorsPacked = new Uint8Array(colors.length * 3);\n    for (i = 0, j = 0, ii = colors.length; i < ii; i++) {\n      const c = colors[i];\n      colorsPacked[j++] = c[0];\n      colorsPacked[j++] = c[1];\n      colorsPacked[j++] = c[2];\n    }\n    this.colors = colorsPacked;\n    const figures = this.figures;\n    for (i = 0, ii = figures.length; i < ii; i++) {\n      const figure = figures[i],\n        ps = figure.coords,\n        cs = figure.colors;\n      for (j = 0, jj = ps.length; j < jj; j++) {\n        ps[j] *= 2;\n        cs[j] *= 3;\n      }\n    }\n  }\n  getIR() {\n    const {\n      bounds\n    } = this;\n    if (bounds[2] - bounds[0] === 0 || bounds[3] - bounds[1] === 0) {\n      throw new FormatError(`Invalid MeshShading bounds: [${bounds}].`);\n    }\n    return [\"Mesh\", this.shadingType, this.coords, this.colors, this.figures, bounds, this.bbox, this.background];\n  }\n}\nclass DummyShading extends BaseShading {\n  getIR() {\n    return [\"Dummy\"];\n  }\n}\nfunction getTilingPatternIR(operatorList, dict, color) {\n  const matrix = dict.getArray(\"Matrix\");\n  const bbox = Util.normalizeRect(dict.getArray(\"BBox\"));\n  const xstep = dict.get(\"XStep\");\n  const ystep = dict.get(\"YStep\");\n  const paintType = dict.get(\"PaintType\");\n  const tilingType = dict.get(\"TilingType\");\n  if (bbox[2] - bbox[0] === 0 || bbox[3] - bbox[1] === 0) {\n    throw new FormatError(`Invalid getTilingPatternIR /BBox array: [${bbox}].`);\n  }\n  return [\"TilingPattern\", color, operatorList, matrix, bbox, xstep, ystep, paintType, tilingType];\n}\n\n;// CONCATENATED MODULE: ./src/core/calibri_factors.js\nconst CalibriBoldFactors = [1.3877, 1, 1, 1, 0.97801, 0.92482, 0.89552, 0.91133, 0.81988, 0.97566, 0.98152, 0.93548, 0.93548, 1.2798, 0.85284, 0.92794, 1, 0.96134, 1.54657, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.82845, 0.82845, 0.85284, 0.85284, 0.85284, 0.75859, 0.92138, 0.83908, 0.7762, 0.73293, 0.87289, 0.73133, 0.7514, 0.81921, 0.87356, 0.95958, 0.59526, 0.75727, 0.69225, 1.04924, 0.9121, 0.86943, 0.79795, 0.88198, 0.77958, 0.70864, 0.81055, 0.90399, 0.88653, 0.96017, 0.82577, 0.77892, 0.78257, 0.97507, 1.54657, 0.97507, 0.85284, 0.89552, 0.90176, 0.88762, 0.8785, 0.75241, 0.8785, 0.90518, 0.95015, 0.77618, 0.8785, 0.88401, 0.91916, 0.86304, 0.88401, 0.91488, 0.8785, 0.8801, 0.8785, 0.8785, 0.91343, 0.7173, 1.04106, 0.8785, 0.85075, 0.95794, 0.82616, 0.85162, 0.79492, 0.88331, 1.69808, 0.88331, 0.85284, 0.97801, 0.89552, 0.91133, 0.89552, 0.91133, 1.7801, 0.89552, 1.24487, 1.13254, 1.12401, 0.96839, 0.85284, 0.68787, 0.70645, 0.85592, 0.90747, 1.01466, 1.0088, 0.90323, 1, 1.07463, 1, 0.91056, 0.75806, 1.19118, 0.96839, 0.78864, 0.82845, 0.84133, 0.75859, 0.83908, 0.83908, 0.83908, 0.83908, 0.83908, 0.83908, 0.77539, 0.73293, 0.73133, 0.73133, 0.73133, 0.73133, 0.95958, 0.95958, 0.95958, 0.95958, 0.88506, 0.9121, 0.86943, 0.86943, 0.86943, 0.86943, 0.86943, 0.85284, 0.87508, 0.90399, 0.90399, 0.90399, 0.90399, 0.77892, 0.79795, 0.90807, 0.88762, 0.88762, 0.88762, 0.88762, 0.88762, 0.88762, 0.8715, 0.75241, 0.90518, 0.90518, 0.90518, 0.90518, 0.88401, 0.88401, 0.88401, 0.88401, 0.8785, 0.8785, 0.8801, 0.8801, 0.8801, 0.8801, 0.8801, 0.90747, 0.89049, 0.8785, 0.8785, 0.8785, 0.8785, 0.85162, 0.8785, 0.85162, 0.83908, 0.88762, 0.83908, 0.88762, 0.83908, 0.88762, 0.73293, 0.75241, 0.73293, 0.75241, 0.73293, 0.75241, 0.73293, 0.75241, 0.87289, 0.83016, 0.88506, 0.93125, 0.73133, 0.90518, 0.73133, 0.90518, 0.73133, 0.90518, 0.73133, 0.90518, 0.73133, 0.90518, 0.81921, 0.77618, 0.81921, 0.77618, 0.81921, 0.77618, 1, 1, 0.87356, 0.8785, 0.91075, 0.89608, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.76229, 0.90167, 0.59526, 0.91916, 1, 1, 0.86304, 0.69225, 0.88401, 1, 1, 0.70424, 0.79468, 0.91926, 0.88175, 0.70823, 0.94903, 0.9121, 0.8785, 1, 1, 0.9121, 0.8785, 0.87802, 0.88656, 0.8785, 0.86943, 0.8801, 0.86943, 0.8801, 0.86943, 0.8801, 0.87402, 0.89291, 0.77958, 0.91343, 1, 1, 0.77958, 0.91343, 0.70864, 0.7173, 0.70864, 0.7173, 0.70864, 0.7173, 0.70864, 0.7173, 1, 1, 0.81055, 0.75841, 0.81055, 1.06452, 0.90399, 0.8785, 0.90399, 0.8785, 0.90399, 0.8785, 0.90399, 0.8785, 0.90399, 0.8785, 0.90399, 0.8785, 0.96017, 0.95794, 0.77892, 0.85162, 0.77892, 0.78257, 0.79492, 0.78257, 0.79492, 0.78257, 0.79492, 0.9297, 0.56892, 0.83908, 0.88762, 0.77539, 0.8715, 0.87508, 0.89049, 1, 1, 0.81055, 1.04106, 1.20528, 1.20528, 1, 1.15543, 0.70674, 0.98387, 0.94721, 1.33431, 1.45894, 0.95161, 1.06303, 0.83908, 0.80352, 0.57184, 0.6965, 0.56289, 0.82001, 0.56029, 0.81235, 1.02988, 0.83908, 0.7762, 0.68156, 0.80367, 0.73133, 0.78257, 0.87356, 0.86943, 0.95958, 0.75727, 0.89019, 1.04924, 0.9121, 0.7648, 0.86943, 0.87356, 0.79795, 0.78275, 0.81055, 0.77892, 0.9762, 0.82577, 0.99819, 0.84896, 0.95958, 0.77892, 0.96108, 1.01407, 0.89049, 1.02988, 0.94211, 0.96108, 0.8936, 0.84021, 0.87842, 0.96399, 0.79109, 0.89049, 1.00813, 1.02988, 0.86077, 0.87445, 0.92099, 0.84723, 0.86513, 0.8801, 0.75638, 0.85714, 0.78216, 0.79586, 0.87965, 0.94211, 0.97747, 0.78287, 0.97926, 0.84971, 1.02988, 0.94211, 0.8801, 0.94211, 0.84971, 0.73133, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90264, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90518, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90548, 1, 1, 1, 1, 1, 1, 0.96017, 0.95794, 0.96017, 0.95794, 0.96017, 0.95794, 0.77892, 0.85162, 1, 1, 0.89552, 0.90527, 1, 0.90363, 0.92794, 0.92794, 0.92794, 0.92794, 0.87012, 0.87012, 0.87012, 0.89552, 0.89552, 1.42259, 0.71143, 1.06152, 1, 1, 1.03372, 1.03372, 0.97171, 1.4956, 2.2807, 0.93835, 0.83406, 0.91133, 0.84107, 0.91133, 1, 1, 1, 0.72021, 1, 1.23108, 0.83489, 0.88525, 0.88525, 0.81499, 0.90527, 1.81055, 0.90527, 1.81055, 1.31006, 1.53711, 0.94434, 1.08696, 1, 0.95018, 0.77192, 0.85284, 0.90747, 1.17534, 0.69825, 0.9716, 1.37077, 0.90747, 0.90747, 0.85356, 0.90747, 0.90747, 1.44947, 0.85284, 0.8941, 0.8941, 0.70572, 0.8, 0.70572, 0.70572, 0.70572, 0.70572, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.99862, 0.99862, 1, 1, 1, 1, 1, 1.08004, 0.91027, 1, 1, 1, 0.99862, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90727, 0.90727, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];\nconst CalibriBoldMetrics = {\n  lineHeight: 1.2207,\n  lineGap: 0.2207\n};\nconst CalibriBoldItalicFactors = [1.3877, 1, 1, 1, 0.97801, 0.92482, 0.89552, 0.91133, 0.81988, 0.97566, 0.98152, 0.93548, 0.93548, 1.2798, 0.85284, 0.92794, 1, 0.96134, 1.56239, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.82845, 0.82845, 0.85284, 0.85284, 0.85284, 0.75859, 0.92138, 0.83908, 0.7762, 0.71805, 0.87289, 0.73133, 0.7514, 0.81921, 0.87356, 0.95958, 0.59526, 0.75727, 0.69225, 1.04924, 0.90872, 0.85938, 0.79795, 0.87068, 0.77958, 0.69766, 0.81055, 0.90399, 0.88653, 0.96068, 0.82577, 0.77892, 0.78257, 0.97507, 1.529, 0.97507, 0.85284, 0.89552, 0.90176, 0.94908, 0.86411, 0.74012, 0.86411, 0.88323, 0.95015, 0.86411, 0.86331, 0.88401, 0.91916, 0.86304, 0.88401, 0.9039, 0.86331, 0.86331, 0.86411, 0.86411, 0.90464, 0.70852, 1.04106, 0.86331, 0.84372, 0.95794, 0.82616, 0.84548, 0.79492, 0.88331, 1.69808, 0.88331, 0.85284, 0.97801, 0.89552, 0.91133, 0.89552, 0.91133, 1.7801, 0.89552, 1.24487, 1.13254, 1.19129, 0.96839, 0.85284, 0.68787, 0.70645, 0.85592, 0.90747, 1.01466, 1.0088, 0.90323, 1, 1.07463, 1, 0.91056, 0.75806, 1.19118, 0.96839, 0.78864, 0.82845, 0.84133, 0.75859, 0.83908, 0.83908, 0.83908, 0.83908, 0.83908, 0.83908, 0.77539, 0.71805, 0.73133, 0.73133, 0.73133, 0.73133, 0.95958, 0.95958, 0.95958, 0.95958, 0.88506, 0.90872, 0.85938, 0.85938, 0.85938, 0.85938, 0.85938, 0.85284, 0.87068, 0.90399, 0.90399, 0.90399, 0.90399, 0.77892, 0.79795, 0.90807, 0.94908, 0.94908, 0.94908, 0.94908, 0.94908, 0.94908, 0.85887, 0.74012, 0.88323, 0.88323, 0.88323, 0.88323, 0.88401, 0.88401, 0.88401, 0.88401, 0.8785, 0.86331, 0.86331, 0.86331, 0.86331, 0.86331, 0.86331, 0.90747, 0.89049, 0.86331, 0.86331, 0.86331, 0.86331, 0.84548, 0.86411, 0.84548, 0.83908, 0.94908, 0.83908, 0.94908, 0.83908, 0.94908, 0.71805, 0.74012, 0.71805, 0.74012, 0.71805, 0.74012, 0.71805, 0.74012, 0.87289, 0.79538, 0.88506, 0.92726, 0.73133, 0.88323, 0.73133, 0.88323, 0.73133, 0.88323, 0.73133, 0.88323, 0.73133, 0.88323, 0.81921, 0.86411, 0.81921, 0.86411, 0.81921, 0.86411, 1, 1, 0.87356, 0.86331, 0.91075, 0.8777, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.76467, 0.90167, 0.59526, 0.91916, 1, 1, 0.86304, 0.69225, 0.88401, 1, 1, 0.70424, 0.77312, 0.91926, 0.88175, 0.70823, 0.94903, 0.90872, 0.86331, 1, 1, 0.90872, 0.86331, 0.86906, 0.88116, 0.86331, 0.85938, 0.86331, 0.85938, 0.86331, 0.85938, 0.86331, 0.87402, 0.86549, 0.77958, 0.90464, 1, 1, 0.77958, 0.90464, 0.69766, 0.70852, 0.69766, 0.70852, 0.69766, 0.70852, 0.69766, 0.70852, 1, 1, 0.81055, 0.75841, 0.81055, 1.06452, 0.90399, 0.86331, 0.90399, 0.86331, 0.90399, 0.86331, 0.90399, 0.86331, 0.90399, 0.86331, 0.90399, 0.86331, 0.96068, 0.95794, 0.77892, 0.84548, 0.77892, 0.78257, 0.79492, 0.78257, 0.79492, 0.78257, 0.79492, 0.9297, 0.56892, 0.83908, 0.94908, 0.77539, 0.85887, 0.87068, 0.89049, 1, 1, 0.81055, 1.04106, 1.20528, 1.20528, 1, 1.15543, 0.70088, 0.98387, 0.94721, 1.33431, 1.45894, 0.95161, 1.48387, 0.83908, 0.80352, 0.57118, 0.6965, 0.56347, 0.79179, 0.55853, 0.80346, 1.02988, 0.83908, 0.7762, 0.67174, 0.86036, 0.73133, 0.78257, 0.87356, 0.86441, 0.95958, 0.75727, 0.89019, 1.04924, 0.90872, 0.74889, 0.85938, 0.87891, 0.79795, 0.7957, 0.81055, 0.77892, 0.97447, 0.82577, 0.97466, 0.87179, 0.95958, 0.77892, 0.94252, 0.95612, 0.8753, 1.02988, 0.92733, 0.94252, 0.87411, 0.84021, 0.8728, 0.95612, 0.74081, 0.8753, 1.02189, 1.02988, 0.84814, 0.87445, 0.91822, 0.84723, 0.85668, 0.86331, 0.81344, 0.87581, 0.76422, 0.82046, 0.96057, 0.92733, 0.99375, 0.78022, 0.95452, 0.86015, 1.02988, 0.92733, 0.86331, 0.92733, 0.86015, 0.73133, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90631, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.88323, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.85174, 1, 1, 1, 1, 1, 1, 0.96068, 0.95794, 0.96068, 0.95794, 0.96068, 0.95794, 0.77892, 0.84548, 1, 1, 0.89552, 0.90527, 1, 0.90363, 0.92794, 0.92794, 0.92794, 0.89807, 0.87012, 0.87012, 0.87012, 0.89552, 0.89552, 1.42259, 0.71094, 1.06152, 1, 1, 1.03372, 1.03372, 0.97171, 1.4956, 2.2807, 0.92972, 0.83406, 0.91133, 0.83326, 0.91133, 1, 1, 1, 0.72021, 1, 1.23108, 0.83489, 0.88525, 0.88525, 0.81499, 0.90616, 1.81055, 0.90527, 1.81055, 1.3107, 1.53711, 0.94434, 1.08696, 1, 0.95018, 0.77192, 0.85284, 0.90747, 1.17534, 0.69825, 0.9716, 1.37077, 0.90747, 0.90747, 0.85356, 0.90747, 0.90747, 1.44947, 0.85284, 0.8941, 0.8941, 0.70572, 0.8, 0.70572, 0.70572, 0.70572, 0.70572, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.99862, 0.99862, 1, 1, 1, 1, 1, 1.08004, 0.91027, 1, 1, 1, 0.99862, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90727, 0.90727, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];\nconst CalibriBoldItalicMetrics = {\n  lineHeight: 1.2207,\n  lineGap: 0.2207\n};\nconst CalibriItalicFactors = [1.3877, 1, 1, 1, 1.17223, 1.1293, 0.89552, 0.91133, 0.80395, 1.02269, 1.15601, 0.91056, 0.91056, 1.2798, 0.85284, 0.89807, 1, 0.90861, 1.39543, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.96309, 0.96309, 0.85284, 0.85284, 0.85284, 0.83319, 0.88071, 0.8675, 0.81552, 0.72346, 0.85193, 0.73206, 0.7522, 0.81105, 0.86275, 0.90685, 0.6377, 0.77892, 0.75593, 1.02638, 0.89249, 0.84118, 0.77452, 0.85374, 0.75186, 0.67789, 0.79776, 0.88844, 0.85066, 0.94309, 0.77818, 0.7306, 0.76659, 1.10369, 1.38313, 1.10369, 1.06139, 0.89552, 0.8739, 0.9245, 0.9245, 0.83203, 0.9245, 0.85865, 1.09842, 0.9245, 0.9245, 1.03297, 1.07692, 0.90918, 1.03297, 0.94959, 0.9245, 0.92274, 0.9245, 0.9245, 1.02933, 0.77832, 1.20562, 0.9245, 0.8916, 0.98986, 0.86621, 0.89453, 0.79004, 0.94152, 1.77256, 0.94152, 0.85284, 0.97801, 0.89552, 0.91133, 0.89552, 0.91133, 1.91729, 0.89552, 1.17889, 1.13254, 1.16359, 0.92098, 0.85284, 0.68787, 0.71353, 0.84737, 0.90747, 1.0088, 1.0044, 0.87683, 1, 1.09091, 1, 0.92229, 0.739, 1.15642, 0.92098, 0.76288, 0.80504, 0.80972, 0.75859, 0.8675, 0.8675, 0.8675, 0.8675, 0.8675, 0.8675, 0.76318, 0.72346, 0.73206, 0.73206, 0.73206, 0.73206, 0.90685, 0.90685, 0.90685, 0.90685, 0.86477, 0.89249, 0.84118, 0.84118, 0.84118, 0.84118, 0.84118, 0.85284, 0.84557, 0.88844, 0.88844, 0.88844, 0.88844, 0.7306, 0.77452, 0.86331, 0.9245, 0.9245, 0.9245, 0.9245, 0.9245, 0.9245, 0.84843, 0.83203, 0.85865, 0.85865, 0.85865, 0.85865, 0.82601, 0.82601, 0.82601, 0.82601, 0.94469, 0.9245, 0.92274, 0.92274, 0.92274, 0.92274, 0.92274, 0.90747, 0.86651, 0.9245, 0.9245, 0.9245, 0.9245, 0.89453, 0.9245, 0.89453, 0.8675, 0.9245, 0.8675, 0.9245, 0.8675, 0.9245, 0.72346, 0.83203, 0.72346, 0.83203, 0.72346, 0.83203, 0.72346, 0.83203, 0.85193, 0.8875, 0.86477, 0.99034, 0.73206, 0.85865, 0.73206, 0.85865, 0.73206, 0.85865, 0.73206, 0.85865, 0.73206, 0.85865, 0.81105, 0.9245, 0.81105, 0.9245, 0.81105, 0.9245, 1, 1, 0.86275, 0.9245, 0.90872, 0.93591, 0.90685, 0.82601, 0.90685, 0.82601, 0.90685, 0.82601, 0.90685, 1.03297, 0.90685, 0.82601, 0.77896, 1.05611, 0.6377, 1.07692, 1, 1, 0.90918, 0.75593, 1.03297, 1, 1, 0.76032, 0.9375, 0.98156, 0.93407, 0.77261, 1.11429, 0.89249, 0.9245, 1, 1, 0.89249, 0.9245, 0.92534, 0.86698, 0.9245, 0.84118, 0.92274, 0.84118, 0.92274, 0.84118, 0.92274, 0.8667, 0.86291, 0.75186, 1.02933, 1, 1, 0.75186, 1.02933, 0.67789, 0.77832, 0.67789, 0.77832, 0.67789, 0.77832, 0.67789, 0.77832, 1, 1, 0.79776, 0.97655, 0.79776, 1.23023, 0.88844, 0.9245, 0.88844, 0.9245, 0.88844, 0.9245, 0.88844, 0.9245, 0.88844, 0.9245, 0.88844, 0.9245, 0.94309, 0.98986, 0.7306, 0.89453, 0.7306, 0.76659, 0.79004, 0.76659, 0.79004, 0.76659, 0.79004, 1.09231, 0.54873, 0.8675, 0.9245, 0.76318, 0.84843, 0.84557, 0.86651, 1, 1, 0.79776, 1.20562, 1.18622, 1.18622, 1, 1.1437, 0.67009, 0.96334, 0.93695, 1.35191, 1.40909, 0.95161, 1.48387, 0.8675, 0.90861, 0.6192, 0.7363, 0.64824, 0.82411, 0.56321, 0.85696, 1.23516, 0.8675, 0.81552, 0.7286, 0.84134, 0.73206, 0.76659, 0.86275, 0.84369, 0.90685, 0.77892, 0.85871, 1.02638, 0.89249, 0.75828, 0.84118, 0.85984, 0.77452, 0.76466, 0.79776, 0.7306, 0.90782, 0.77818, 0.903, 0.87291, 0.90685, 0.7306, 0.99058, 1.03667, 0.94635, 1.23516, 0.9849, 0.99058, 0.92393, 0.8916, 0.942, 1.03667, 0.75026, 0.94635, 1.0297, 1.23516, 0.90918, 0.94048, 0.98217, 0.89746, 0.84153, 0.92274, 0.82507, 0.88832, 0.84438, 0.88178, 1.03525, 0.9849, 1.00225, 0.78086, 0.97248, 0.89404, 1.23516, 0.9849, 0.92274, 0.9849, 0.89404, 0.73206, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.89693, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.85865, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90933, 1, 1, 1, 1, 1, 1, 0.94309, 0.98986, 0.94309, 0.98986, 0.94309, 0.98986, 0.7306, 0.89453, 1, 1, 0.89552, 0.90527, 1, 0.90186, 1.12308, 1.12308, 1.12308, 1.12308, 1.2566, 1.2566, 1.2566, 0.89552, 0.89552, 1.42259, 0.68994, 1.03809, 1, 1, 1.0176, 1.0176, 1.11523, 1.4956, 2.01462, 0.97858, 0.82616, 0.91133, 0.83437, 0.91133, 1, 1, 1, 0.70508, 1, 1.23108, 0.79801, 0.84426, 0.84426, 0.774, 0.90572, 1.81055, 0.90749, 1.81055, 1.28809, 1.55469, 0.94434, 1.07806, 1, 0.97094, 0.7589, 0.85284, 0.90747, 1.19658, 0.69825, 0.97622, 1.33512, 0.90747, 0.90747, 0.85284, 0.90747, 0.90747, 1.44947, 0.85284, 0.8941, 0.8941, 0.70572, 0.8, 0.70572, 0.70572, 0.70572, 0.70572, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.99862, 0.99862, 1, 1, 1, 1, 1, 1.0336, 0.91027, 1, 1, 1, 0.99862, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.05859, 1.05859, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];\nconst CalibriItalicMetrics = {\n  lineHeight: 1.2207,\n  lineGap: 0.2207\n};\nconst CalibriRegularFactors = [1.3877, 1, 1, 1, 1.17223, 1.1293, 0.89552, 0.91133, 0.80395, 1.02269, 1.15601, 0.91056, 0.91056, 1.2798, 0.85284, 0.89807, 1, 0.90861, 1.39016, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.96309, 0.96309, 0.85284, 0.85284, 0.85284, 0.83319, 0.88071, 0.8675, 0.81552, 0.73834, 0.85193, 0.73206, 0.7522, 0.81105, 0.86275, 0.90685, 0.6377, 0.77892, 0.75593, 1.02638, 0.89385, 0.85122, 0.77452, 0.86503, 0.75186, 0.68887, 0.79776, 0.88844, 0.85066, 0.94258, 0.77818, 0.7306, 0.76659, 1.10369, 1.39016, 1.10369, 1.06139, 0.89552, 0.8739, 0.86128, 0.94469, 0.8457, 0.94469, 0.89464, 1.09842, 0.84636, 0.94469, 1.03297, 1.07692, 0.90918, 1.03297, 0.95897, 0.94469, 0.9482, 0.94469, 0.94469, 1.04692, 0.78223, 1.20562, 0.94469, 0.90332, 0.98986, 0.86621, 0.90527, 0.79004, 0.94152, 1.77256, 0.94152, 0.85284, 0.97801, 0.89552, 0.91133, 0.89552, 0.91133, 1.91729, 0.89552, 1.17889, 1.13254, 1.08707, 0.92098, 0.85284, 0.68787, 0.71353, 0.84737, 0.90747, 1.0088, 1.0044, 0.87683, 1, 1.09091, 1, 0.92229, 0.739, 1.15642, 0.92098, 0.76288, 0.80504, 0.80972, 0.75859, 0.8675, 0.8675, 0.8675, 0.8675, 0.8675, 0.8675, 0.76318, 0.73834, 0.73206, 0.73206, 0.73206, 0.73206, 0.90685, 0.90685, 0.90685, 0.90685, 0.86477, 0.89385, 0.85122, 0.85122, 0.85122, 0.85122, 0.85122, 0.85284, 0.85311, 0.88844, 0.88844, 0.88844, 0.88844, 0.7306, 0.77452, 0.86331, 0.86128, 0.86128, 0.86128, 0.86128, 0.86128, 0.86128, 0.8693, 0.8457, 0.89464, 0.89464, 0.89464, 0.89464, 0.82601, 0.82601, 0.82601, 0.82601, 0.94469, 0.94469, 0.9482, 0.9482, 0.9482, 0.9482, 0.9482, 0.90747, 0.86651, 0.94469, 0.94469, 0.94469, 0.94469, 0.90527, 0.94469, 0.90527, 0.8675, 0.86128, 0.8675, 0.86128, 0.8675, 0.86128, 0.73834, 0.8457, 0.73834, 0.8457, 0.73834, 0.8457, 0.73834, 0.8457, 0.85193, 0.92454, 0.86477, 0.9921, 0.73206, 0.89464, 0.73206, 0.89464, 0.73206, 0.89464, 0.73206, 0.89464, 0.73206, 0.89464, 0.81105, 0.84636, 0.81105, 0.84636, 0.81105, 0.84636, 1, 1, 0.86275, 0.94469, 0.90872, 0.95786, 0.90685, 0.82601, 0.90685, 0.82601, 0.90685, 0.82601, 0.90685, 1.03297, 0.90685, 0.82601, 0.77741, 1.05611, 0.6377, 1.07692, 1, 1, 0.90918, 0.75593, 1.03297, 1, 1, 0.76032, 0.90452, 0.98156, 1.11842, 0.77261, 1.11429, 0.89385, 0.94469, 1, 1, 0.89385, 0.94469, 0.95877, 0.86901, 0.94469, 0.85122, 0.9482, 0.85122, 0.9482, 0.85122, 0.9482, 0.8667, 0.90016, 0.75186, 1.04692, 1, 1, 0.75186, 1.04692, 0.68887, 0.78223, 0.68887, 0.78223, 0.68887, 0.78223, 0.68887, 0.78223, 1, 1, 0.79776, 0.92188, 0.79776, 1.23023, 0.88844, 0.94469, 0.88844, 0.94469, 0.88844, 0.94469, 0.88844, 0.94469, 0.88844, 0.94469, 0.88844, 0.94469, 0.94258, 0.98986, 0.7306, 0.90527, 0.7306, 0.76659, 0.79004, 0.76659, 0.79004, 0.76659, 0.79004, 1.09231, 0.54873, 0.8675, 0.86128, 0.76318, 0.8693, 0.85311, 0.86651, 1, 1, 0.79776, 1.20562, 1.18622, 1.18622, 1, 1.1437, 0.67742, 0.96334, 0.93695, 1.35191, 1.40909, 0.95161, 1.48387, 0.86686, 0.90861, 0.62267, 0.74359, 0.65649, 0.85498, 0.56963, 0.88254, 1.23516, 0.8675, 0.81552, 0.75443, 0.84503, 0.73206, 0.76659, 0.86275, 0.85122, 0.90685, 0.77892, 0.85746, 1.02638, 0.89385, 0.75657, 0.85122, 0.86275, 0.77452, 0.74171, 0.79776, 0.7306, 0.95165, 0.77818, 0.89772, 0.88831, 0.90685, 0.7306, 0.98142, 1.02191, 0.96576, 1.23516, 0.99018, 0.98142, 0.9236, 0.89258, 0.94035, 1.02191, 0.78848, 0.96576, 0.9561, 1.23516, 0.90918, 0.92578, 0.95424, 0.89746, 0.83969, 0.9482, 0.80113, 0.89442, 0.85208, 0.86155, 0.98022, 0.99018, 1.00452, 0.81209, 0.99247, 0.89181, 1.23516, 0.99018, 0.9482, 0.99018, 0.89181, 0.73206, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.88844, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.89464, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.96766, 1, 1, 1, 1, 1, 1, 0.94258, 0.98986, 0.94258, 0.98986, 0.94258, 0.98986, 0.7306, 0.90527, 1, 1, 0.89552, 0.90527, 1, 0.90186, 1.12308, 1.12308, 1.12308, 1.12308, 1.2566, 1.2566, 1.2566, 0.89552, 0.89552, 1.42259, 0.69043, 1.03809, 1, 1, 1.0176, 1.0176, 1.11523, 1.4956, 2.01462, 0.99331, 0.82616, 0.91133, 0.84286, 0.91133, 1, 1, 1, 0.70508, 1, 1.23108, 0.79801, 0.84426, 0.84426, 0.774, 0.90527, 1.81055, 0.90527, 1.81055, 1.28809, 1.55469, 0.94434, 1.07806, 1, 0.97094, 0.7589, 0.85284, 0.90747, 1.19658, 0.69825, 0.97622, 1.33512, 0.90747, 0.90747, 0.85356, 0.90747, 0.90747, 1.44947, 0.85284, 0.8941, 0.8941, 0.70572, 0.8, 0.70572, 0.70572, 0.70572, 0.70572, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.99862, 0.99862, 1, 1, 1, 1, 1, 1.0336, 0.91027, 1, 1, 1, 0.99862, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.05859, 1.05859, 1, 1, 1, 1.07185, 0.99413, 0.96334, 1.08065, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];\nconst CalibriRegularMetrics = {\n  lineHeight: 1.2207,\n  lineGap: 0.2207\n};\n\n;// CONCATENATED MODULE: ./src/core/helvetica_factors.js\nconst HelveticaBoldFactors = [0.76116, 1, 1, 1.0006, 0.99998, 0.99974, 0.99973, 0.99973, 0.99982, 0.99977, 1.00087, 0.99998, 0.99998, 0.99959, 1.00003, 1.0006, 0.99998, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99998, 1, 1.00003, 1.00003, 1.00003, 1.00026, 0.9999, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00026, 1.00022, 0.99977, 1.0006, 0.99973, 0.99977, 1.00026, 0.99999, 0.99977, 1.00022, 1.00001, 1.00022, 0.99977, 1.00001, 1.00026, 0.99977, 1.00001, 1.00016, 1.00001, 1.00001, 1.00026, 0.99998, 1.0006, 0.99998, 1.00003, 0.99973, 0.99998, 0.99973, 1.00026, 0.99973, 1.00026, 0.99973, 0.99998, 1.00026, 1.00026, 1.0006, 1.0006, 0.99973, 1.0006, 0.99982, 1.00026, 1.00026, 1.00026, 1.00026, 0.99959, 0.99973, 0.99998, 1.00026, 0.99973, 1.00022, 0.99973, 0.99973, 1, 0.99959, 1.00077, 0.99959, 1.00003, 0.99998, 0.99973, 0.99973, 0.99973, 0.99973, 1.00077, 0.99973, 0.99998, 1.00025, 0.99968, 0.99973, 1.00003, 1.00025, 0.60299, 1.00024, 1.06409, 1, 1, 0.99998, 1, 0.99973, 1.0006, 0.99998, 1, 0.99936, 0.99973, 1.00002, 1.00002, 1.00002, 1.00026, 0.99977, 0.99977, 0.99977, 0.99977, 0.99977, 0.99977, 1, 0.99977, 1.00001, 1.00001, 1.00001, 1.00001, 1.0006, 1.0006, 1.0006, 1.0006, 0.99977, 0.99977, 1.00022, 1.00022, 1.00022, 1.00022, 1.00022, 1.00003, 1.00022, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00001, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99982, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.06409, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 0.99973, 1.00026, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 1.03374, 0.99977, 1.00026, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.00042, 0.99973, 0.99973, 1.0006, 0.99977, 0.99973, 0.99973, 1.00026, 1.0006, 1.00026, 1.0006, 1.00026, 1.03828, 1.00026, 0.99999, 1.00026, 1.0006, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.9993, 0.9998, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1, 1.00016, 0.99977, 0.99959, 0.99977, 0.99959, 0.99977, 0.99959, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00026, 0.99998, 1.00026, 0.8121, 1.00026, 0.99998, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 1.00016, 1.00022, 1.00001, 0.99973, 1.00001, 1.00026, 1, 1.00026, 1, 1.00026, 1, 1.0006, 0.99973, 0.99977, 0.99973, 1, 0.99982, 1.00022, 1.00026, 1.00001, 0.99973, 1.00026, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 1.00034, 0.99977, 1, 0.99997, 1.00026, 1.00078, 1.00036, 0.99973, 1.00013, 1.0006, 0.99977, 0.99977, 0.99988, 0.85148, 1.00001, 1.00026, 0.99977, 1.00022, 1.0006, 0.99977, 1.00001, 0.99999, 0.99977, 1.00069, 1.00022, 0.99977, 1.00001, 0.99984, 1.00026, 1.00001, 1.00024, 1.00001, 0.9999, 1, 1.0006, 1.00001, 1.00041, 0.99962, 1.00026, 1.0006, 0.99995, 1.00041, 0.99942, 0.99973, 0.99927, 1.00082, 0.99902, 1.00026, 1.00087, 1.0006, 1.00069, 0.99973, 0.99867, 0.99973, 0.9993, 1.00026, 1.00049, 1.00056, 1, 0.99988, 0.99935, 0.99995, 0.99954, 1.00055, 0.99945, 1.00032, 1.0006, 0.99995, 1.00026, 0.99995, 1.00032, 1.00001, 1.00008, 0.99971, 1.00019, 0.9994, 1.00001, 1.0006, 1.00044, 0.99973, 1.00023, 1.00047, 1, 0.99942, 0.99561, 0.99989, 1.00035, 0.99977, 1.00035, 0.99977, 1.00019, 0.99944, 1.00001, 1.00021, 0.99926, 1.00035, 1.00035, 0.99942, 1.00048, 0.99999, 0.99977, 1.00022, 1.00035, 1.00001, 0.99977, 1.00026, 0.99989, 1.00057, 1.00001, 0.99936, 1.00052, 1.00012, 0.99996, 1.00043, 1, 1.00035, 0.9994, 0.99976, 1.00035, 0.99973, 1.00052, 1.00041, 1.00119, 1.00037, 0.99973, 1.00002, 0.99986, 1.00041, 1.00041, 0.99902, 0.9996, 1.00034, 0.99999, 1.00026, 0.99999, 1.00026, 0.99973, 1.00052, 0.99973, 1, 0.99973, 1.00041, 1.00075, 0.9994, 1.0003, 0.99999, 1, 1.00041, 0.99955, 1, 0.99915, 0.99973, 0.99973, 1.00026, 1.00119, 0.99955, 0.99973, 1.0006, 0.99911, 1.0006, 1.00026, 0.99972, 1.00026, 0.99902, 1.00041, 0.99973, 0.99999, 1, 1, 1.00038, 1.0005, 1.00016, 1.00022, 1.00016, 1.00022, 1.00016, 1.00022, 1.00001, 0.99973, 1, 1, 0.99973, 1, 1, 0.99955, 1.0006, 1.0006, 1.0006, 1.0006, 1, 1, 1, 0.99973, 0.99973, 0.99972, 1, 1, 1.00106, 0.99999, 0.99998, 0.99998, 0.99999, 0.99998, 1.66475, 1, 0.99973, 0.99973, 1.00023, 0.99973, 0.99971, 1.00047, 1.00023, 1, 0.99991, 0.99984, 1.00002, 1.00002, 1.00002, 1.00002, 1, 1, 1, 1, 1, 1, 1, 0.99972, 1, 1.20985, 1.39713, 1.00003, 1.00031, 1.00015, 1, 0.99561, 1.00027, 1.00031, 1.00031, 0.99915, 1.00031, 1.00031, 0.99999, 1.00003, 0.99999, 0.99999, 1.41144, 1.6, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.40579, 1.40579, 1.36625, 0.99999, 1, 0.99861, 0.99861, 1, 1.00026, 1.00026, 1.00026, 1.00026, 0.99972, 0.99999, 0.99999, 0.99999, 0.99999, 1.40483, 1, 0.99977, 1.00054, 1, 1, 0.99953, 0.99962, 1.00042, 0.9995, 1, 1, 1, 1, 1, 1, 1, 1, 0.99998, 0.99998, 0.99998, 0.99998, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];\nconst HelveticaBoldMetrics = {\n  lineHeight: 1.2,\n  lineGap: 0.2\n};\nconst HelveticaBoldItalicFactors = [0.76116, 1, 1, 1.0006, 0.99998, 0.99974, 0.99973, 0.99973, 0.99982, 0.99977, 1.00087, 0.99998, 0.99998, 0.99959, 1.00003, 1.0006, 0.99998, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99998, 1, 1.00003, 1.00003, 1.00003, 1.00026, 0.9999, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00026, 1.00022, 0.99977, 1.0006, 0.99973, 0.99977, 1.00026, 0.99999, 0.99977, 1.00022, 1.00001, 1.00022, 0.99977, 1.00001, 1.00026, 0.99977, 1.00001, 1.00016, 1.00001, 1.00001, 1.00026, 0.99998, 1.0006, 0.99998, 1.00003, 0.99973, 0.99998, 0.99973, 1.00026, 0.99973, 1.00026, 0.99973, 0.99998, 1.00026, 1.00026, 1.0006, 1.0006, 0.99973, 1.0006, 0.99982, 1.00026, 1.00026, 1.00026, 1.00026, 0.99959, 0.99973, 0.99998, 1.00026, 0.99973, 1.00022, 0.99973, 0.99973, 1, 0.99959, 1.00077, 0.99959, 1.00003, 0.99998, 0.99973, 0.99973, 0.99973, 0.99973, 1.00077, 0.99973, 0.99998, 1.00025, 0.99968, 0.99973, 1.00003, 1.00025, 0.60299, 1.00024, 1.06409, 1, 1, 0.99998, 1, 0.99973, 1.0006, 0.99998, 1, 0.99936, 0.99973, 1.00002, 1.00002, 1.00002, 1.00026, 0.99977, 0.99977, 0.99977, 0.99977, 0.99977, 0.99977, 1, 0.99977, 1.00001, 1.00001, 1.00001, 1.00001, 1.0006, 1.0006, 1.0006, 1.0006, 0.99977, 0.99977, 1.00022, 1.00022, 1.00022, 1.00022, 1.00022, 1.00003, 1.00022, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00001, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99982, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.06409, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 0.99973, 1.00026, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 1.0044, 0.99977, 1.00026, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 0.99971, 0.99973, 0.99973, 1.0006, 0.99977, 0.99973, 0.99973, 1.00026, 1.0006, 1.00026, 1.0006, 1.00026, 1.01011, 1.00026, 0.99999, 1.00026, 1.0006, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.9993, 0.9998, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1, 1.00016, 0.99977, 0.99959, 0.99977, 0.99959, 0.99977, 0.99959, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00026, 0.99998, 1.00026, 0.8121, 1.00026, 0.99998, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 1.00016, 1.00022, 1.00001, 0.99973, 1.00001, 1.00026, 1, 1.00026, 1, 1.00026, 1, 1.0006, 0.99973, 0.99977, 0.99973, 1, 0.99982, 1.00022, 1.00026, 1.00001, 0.99973, 1.00026, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99977, 1, 1, 1.00026, 0.99969, 0.99972, 0.99981, 0.9998, 1.0006, 0.99977, 0.99977, 1.00022, 0.91155, 1.00001, 1.00026, 0.99977, 1.00022, 1.0006, 0.99977, 1.00001, 0.99999, 0.99977, 0.99966, 1.00022, 1.00032, 1.00001, 0.99944, 1.00026, 1.00001, 0.99968, 1.00001, 1.00047, 1, 1.0006, 1.00001, 0.99981, 1.00101, 1.00026, 1.0006, 0.99948, 0.99981, 1.00064, 0.99973, 0.99942, 1.00101, 1.00061, 1.00026, 1.00069, 1.0006, 1.00014, 0.99973, 1.01322, 0.99973, 1.00065, 1.00026, 1.00012, 0.99923, 1, 1.00064, 1.00076, 0.99948, 1.00055, 1.00063, 1.00007, 0.99943, 1.0006, 0.99948, 1.00026, 0.99948, 0.99943, 1.00001, 1.00001, 1.00029, 1.00038, 1.00035, 1.00001, 1.0006, 1.0006, 0.99973, 0.99978, 1.00001, 1.00057, 0.99989, 0.99967, 0.99964, 0.99967, 0.99977, 0.99999, 0.99977, 1.00038, 0.99977, 1.00001, 0.99973, 1.00066, 0.99967, 0.99967, 1.00041, 0.99998, 0.99999, 0.99977, 1.00022, 0.99967, 1.00001, 0.99977, 1.00026, 0.99964, 1.00031, 1.00001, 0.99999, 0.99999, 1, 1.00023, 1, 1, 0.99999, 1.00035, 1.00001, 0.99999, 0.99973, 0.99977, 0.99999, 1.00058, 0.99973, 0.99973, 0.99955, 0.9995, 1.00026, 1.00026, 1.00032, 0.99989, 1.00034, 0.99999, 1.00026, 1.00026, 1.00026, 0.99973, 0.45998, 0.99973, 1.00026, 0.99973, 1.00001, 0.99999, 0.99982, 0.99994, 0.99996, 1, 1.00042, 1.00044, 1.00029, 1.00023, 0.99973, 0.99973, 1.00026, 0.99949, 1.00002, 0.99973, 1.0006, 1.0006, 1.0006, 0.99975, 1.00026, 1.00026, 1.00032, 0.98685, 0.99973, 1.00026, 1, 1, 0.99966, 1.00044, 1.00016, 1.00022, 1.00016, 1.00022, 1.00016, 1.00022, 1.00001, 0.99973, 1, 1, 0.99973, 1, 1, 0.99955, 1.0006, 1.0006, 1.0006, 1.0006, 1, 1, 1, 0.99973, 0.99973, 0.99972, 1, 1, 1.00106, 0.99999, 0.99998, 0.99998, 0.99999, 0.99998, 1.66475, 1, 0.99973, 0.99973, 1, 0.99973, 0.99971, 0.99978, 1, 1, 0.99991, 0.99984, 1.00002, 1.00002, 1.00002, 1.00002, 1.00098, 1, 1, 1, 1.00049, 1, 1, 0.99972, 1, 1.20985, 1.39713, 1.00003, 1.00031, 1.00015, 1, 0.99561, 1.00027, 1.00031, 1.00031, 0.99915, 1.00031, 1.00031, 0.99999, 1.00003, 0.99999, 0.99999, 1.41144, 1.6, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.40579, 1.40579, 1.36625, 0.99999, 1, 0.99861, 0.99861, 1, 1.00026, 1.00026, 1.00026, 1.00026, 0.99972, 0.99999, 0.99999, 0.99999, 0.99999, 1.40483, 1, 0.99977, 1.00054, 1, 1, 0.99953, 0.99962, 1.00042, 0.9995, 1, 1, 1, 1, 1, 1, 1, 1, 0.99998, 0.99998, 0.99998, 0.99998, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];\nconst HelveticaBoldItalicMetrics = {\n  lineHeight: 1.35,\n  lineGap: 0.2\n};\nconst HelveticaItalicFactors = [0.76116, 1, 1, 1.0006, 1.0006, 1.00006, 0.99973, 0.99973, 0.99982, 1.00001, 1.00043, 0.99998, 0.99998, 0.99959, 1.00003, 1.0006, 0.99998, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1, 1.00003, 1.00003, 1.00003, 0.99973, 0.99987, 1.00001, 1.00001, 0.99977, 0.99977, 1.00001, 1.00026, 1.00022, 0.99977, 1.0006, 1, 1.00001, 0.99973, 0.99999, 0.99977, 1.00022, 1.00001, 1.00022, 0.99977, 1.00001, 1.00026, 0.99977, 1.00001, 1.00016, 1.00001, 1.00001, 1.00026, 1.0006, 1.0006, 1.0006, 0.99949, 0.99973, 0.99998, 0.99973, 0.99973, 1, 0.99973, 0.99973, 1.0006, 0.99973, 0.99973, 0.99924, 0.99924, 1, 0.99924, 0.99999, 0.99973, 0.99973, 0.99973, 0.99973, 0.99998, 1, 1.0006, 0.99973, 1, 0.99977, 1, 1, 1, 1.00005, 1.0009, 1.00005, 1.00003, 0.99998, 0.99973, 0.99973, 0.99973, 0.99973, 1.0009, 0.99973, 0.99998, 1.00025, 0.99968, 0.99973, 1.00003, 1.00025, 0.60299, 1.00024, 1.06409, 1, 1, 0.99998, 1, 0.9998, 1.0006, 0.99998, 1, 0.99936, 0.99973, 1.00002, 1.00002, 1.00002, 1.00026, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1, 0.99977, 1.00001, 1.00001, 1.00001, 1.00001, 1.0006, 1.0006, 1.0006, 1.0006, 0.99977, 0.99977, 1.00022, 1.00022, 1.00022, 1.00022, 1.00022, 1.00003, 1.00022, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00001, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99982, 1, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.06409, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 1, 0.99973, 1, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 0.99977, 1, 0.99977, 1, 0.99977, 1, 0.99977, 1, 0.99977, 1.0288, 0.99977, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 0.99924, 1.0006, 1.0006, 0.99946, 1.00034, 1, 0.99924, 1.00001, 1, 1, 0.99973, 0.99924, 0.99973, 0.99924, 0.99973, 1.06311, 0.99973, 1.00024, 0.99973, 0.99924, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 1.00041, 0.9998, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1, 1.00016, 0.99977, 0.99998, 0.99977, 0.99998, 0.99977, 0.99998, 1.00001, 1, 1.00001, 1, 1.00001, 1, 1.00001, 1, 1.00026, 1.0006, 1.00026, 0.89547, 1.00026, 1.0006, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 1.00016, 0.99977, 1.00001, 1, 1.00001, 1.00026, 1, 1.00026, 1, 1.00026, 1, 0.99924, 0.99973, 1.00001, 0.99973, 1, 0.99982, 1.00022, 1.00026, 1.00001, 1, 1.00026, 1.0006, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 1.00001, 1, 1.00054, 0.99977, 1.00084, 1.00007, 0.99973, 1.00013, 0.99924, 1.00001, 1.00001, 0.99945, 0.91221, 1.00001, 1.00026, 0.99977, 1.00022, 1.0006, 1.00001, 1.00001, 0.99999, 0.99977, 0.99933, 1.00022, 1.00054, 1.00001, 1.00065, 1.00026, 1.00001, 1.0001, 1.00001, 1.00052, 1, 1.0006, 1.00001, 0.99945, 0.99897, 0.99968, 0.99924, 1.00036, 0.99945, 0.99949, 1, 1.0006, 0.99897, 0.99918, 0.99968, 0.99911, 0.99924, 1, 0.99962, 1.01487, 1, 1.0005, 0.99973, 1.00012, 1.00043, 1, 0.99995, 0.99994, 1.00036, 0.99947, 1.00019, 1.00063, 1.00025, 0.99924, 1.00036, 0.99973, 1.00036, 1.00025, 1.00001, 1.00001, 1.00027, 1.0001, 1.00068, 1.00001, 1.0006, 1.0006, 1, 1.00008, 0.99957, 0.99972, 0.9994, 0.99954, 0.99975, 1.00051, 1.00001, 1.00019, 1.00001, 1.0001, 0.99986, 1.00001, 1.00001, 1.00038, 0.99954, 0.99954, 0.9994, 1.00066, 0.99999, 0.99977, 1.00022, 1.00054, 1.00001, 0.99977, 1.00026, 0.99975, 1.0001, 1.00001, 0.99993, 0.9995, 0.99955, 1.00016, 0.99978, 0.99974, 1.00019, 1.00022, 0.99955, 1.00053, 0.99973, 1.00089, 1.00005, 0.99967, 1.00048, 0.99973, 1.00002, 1.00034, 0.99973, 0.99973, 0.99964, 1.00006, 1.00066, 0.99947, 0.99973, 0.98894, 0.99973, 1, 0.44898, 1, 0.99946, 1, 1.00039, 1.00082, 0.99991, 0.99991, 0.99985, 1.00022, 1.00023, 1.00061, 1.00006, 0.99966, 0.99973, 0.99973, 0.99973, 1.00019, 1.0008, 1, 0.99924, 0.99924, 0.99924, 0.99983, 1.00044, 0.99973, 0.99964, 0.98332, 1, 0.99973, 1, 1, 0.99962, 0.99895, 1.00016, 0.99977, 1.00016, 0.99977, 1.00016, 0.99977, 1.00001, 1, 1, 1, 0.99973, 1, 1, 0.99955, 0.99924, 0.99924, 0.99924, 0.99924, 0.99998, 0.99998, 0.99998, 0.99973, 0.99973, 0.99972, 1, 1, 1.00267, 0.99999, 0.99998, 0.99998, 1, 0.99998, 1.66475, 1, 0.99973, 0.99973, 1.00023, 0.99973, 1.00423, 0.99925, 0.99999, 1, 0.99991, 0.99984, 1.00002, 1.00002, 1.00002, 1.00002, 1.00049, 1, 1.00245, 1, 1, 1, 1, 0.96329, 1, 1.20985, 1.39713, 1.00003, 0.8254, 1.00015, 1, 1.00035, 1.00027, 1.00031, 1.00031, 1.00003, 1.00031, 1.00031, 0.99999, 1.00003, 0.99999, 0.99999, 1.41144, 1.6, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.40579, 1.40579, 1.36625, 0.99999, 1, 0.99861, 0.99861, 1, 1.00026, 1.00026, 1.00026, 1.00026, 0.95317, 0.99999, 0.99999, 0.99999, 0.99999, 1.40483, 1, 0.99977, 1.00054, 1, 1, 0.99953, 0.99962, 1.00042, 0.9995, 1, 1, 1, 1, 1, 1, 1, 1, 0.99998, 0.99998, 0.99998, 0.99998, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];\nconst HelveticaItalicMetrics = {\n  lineHeight: 1.35,\n  lineGap: 0.2\n};\nconst HelveticaRegularFactors = [0.76116, 1, 1, 1.0006, 1.0006, 1.00006, 0.99973, 0.99973, 0.99982, 1.00001, 1.00043, 0.99998, 0.99998, 0.99959, 1.00003, 1.0006, 0.99998, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1, 1.00003, 1.00003, 1.00003, 0.99973, 0.99987, 1.00001, 1.00001, 0.99977, 0.99977, 1.00001, 1.00026, 1.00022, 0.99977, 1.0006, 1, 1.00001, 0.99973, 0.99999, 0.99977, 1.00022, 1.00001, 1.00022, 0.99977, 1.00001, 1.00026, 0.99977, 1.00001, 1.00016, 1.00001, 1.00001, 1.00026, 1.0006, 1.0006, 1.0006, 0.99949, 0.99973, 0.99998, 0.99973, 0.99973, 1, 0.99973, 0.99973, 1.0006, 0.99973, 0.99973, 0.99924, 0.99924, 1, 0.99924, 0.99999, 0.99973, 0.99973, 0.99973, 0.99973, 0.99998, 1, 1.0006, 0.99973, 1, 0.99977, 1, 1, 1, 1.00005, 1.0009, 1.00005, 1.00003, 0.99998, 0.99973, 0.99973, 0.99973, 0.99973, 1.0009, 0.99973, 0.99998, 1.00025, 0.99968, 0.99973, 1.00003, 1.00025, 0.60299, 1.00024, 1.06409, 1, 1, 0.99998, 1, 0.9998, 1.0006, 0.99998, 1, 0.99936, 0.99973, 1.00002, 1.00002, 1.00002, 1.00026, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1, 0.99977, 1.00001, 1.00001, 1.00001, 1.00001, 1.0006, 1.0006, 1.0006, 1.0006, 0.99977, 0.99977, 1.00022, 1.00022, 1.00022, 1.00022, 1.00022, 1.00003, 1.00022, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00001, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99982, 1, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.06409, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 1, 0.99973, 1, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 0.99977, 1, 0.99977, 1, 0.99977, 1, 0.99977, 1, 0.99977, 1.04596, 0.99977, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 0.99924, 1.0006, 1.0006, 1.00019, 1.00034, 1, 0.99924, 1.00001, 1, 1, 0.99973, 0.99924, 0.99973, 0.99924, 0.99973, 1.02572, 0.99973, 1.00005, 0.99973, 0.99924, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99999, 0.9998, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1, 1.00016, 0.99977, 0.99998, 0.99977, 0.99998, 0.99977, 0.99998, 1.00001, 1, 1.00001, 1, 1.00001, 1, 1.00001, 1, 1.00026, 1.0006, 1.00026, 0.84533, 1.00026, 1.0006, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 1.00016, 0.99977, 1.00001, 1, 1.00001, 1.00026, 1, 1.00026, 1, 1.00026, 1, 0.99924, 0.99973, 1.00001, 0.99973, 1, 0.99982, 1.00022, 1.00026, 1.00001, 1, 1.00026, 1.0006, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99928, 1, 0.99977, 1.00013, 1.00055, 0.99947, 0.99945, 0.99941, 0.99924, 1.00001, 1.00001, 1.0004, 0.91621, 1.00001, 1.00026, 0.99977, 1.00022, 1.0006, 1.00001, 1.00005, 0.99999, 0.99977, 1.00015, 1.00022, 0.99977, 1.00001, 0.99973, 1.00026, 1.00001, 1.00019, 1.00001, 0.99946, 1, 1.0006, 1.00001, 0.99978, 1.00045, 0.99973, 0.99924, 1.00023, 0.99978, 0.99966, 1, 1.00065, 1.00045, 1.00019, 0.99973, 0.99973, 0.99924, 1, 1, 0.96499, 1, 1.00055, 0.99973, 1.00008, 1.00027, 1, 0.9997, 0.99995, 1.00023, 0.99933, 1.00019, 1.00015, 1.00031, 0.99924, 1.00023, 0.99973, 1.00023, 1.00031, 1.00001, 0.99928, 1.00029, 1.00092, 1.00035, 1.00001, 1.0006, 1.0006, 1, 0.99988, 0.99975, 1, 1.00082, 0.99561, 0.9996, 1.00035, 1.00001, 0.99962, 1.00001, 1.00092, 0.99964, 1.00001, 0.99963, 0.99999, 1.00035, 1.00035, 1.00082, 0.99962, 0.99999, 0.99977, 1.00022, 1.00035, 1.00001, 0.99977, 1.00026, 0.9996, 0.99967, 1.00001, 1.00034, 1.00074, 1.00054, 1.00053, 1.00063, 0.99971, 0.99962, 1.00035, 0.99975, 0.99977, 0.99973, 1.00043, 0.99953, 1.0007, 0.99915, 0.99973, 1.00008, 0.99892, 1.00073, 1.00073, 1.00114, 0.99915, 1.00073, 0.99955, 0.99973, 1.00092, 0.99973, 1, 0.99998, 1, 1.0003, 1, 1.00043, 1.00001, 0.99969, 1.0003, 1, 1.00035, 1.00001, 0.9995, 1, 1.00092, 0.99973, 0.99973, 0.99973, 1.0007, 0.9995, 1, 0.99924, 1.0006, 0.99924, 0.99972, 1.00062, 0.99973, 1.00114, 1.00073, 1, 0.99955, 1, 1, 1.00047, 0.99968, 1.00016, 0.99977, 1.00016, 0.99977, 1.00016, 0.99977, 1.00001, 1, 1, 1, 0.99973, 1, 1, 0.99955, 0.99924, 0.99924, 0.99924, 0.99924, 0.99998, 0.99998, 0.99998, 0.99973, 0.99973, 0.99972, 1, 1, 1.00267, 0.99999, 0.99998, 0.99998, 1, 0.99998, 1.66475, 1, 0.99973, 0.99973, 1.00023, 0.99973, 0.99971, 0.99925, 1.00023, 1, 0.99991, 0.99984, 1.00002, 1.00002, 1.00002, 1.00002, 1, 1, 1, 1, 1, 1, 1, 0.96329, 1, 1.20985, 1.39713, 1.00003, 0.8254, 1.00015, 1, 1.00035, 1.00027, 1.00031, 1.00031, 0.99915, 1.00031, 1.00031, 0.99999, 1.00003, 0.99999, 0.99999, 1.41144, 1.6, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.40579, 1.40579, 1.36625, 0.99999, 1, 0.99861, 0.99861, 1, 1.00026, 1.00026, 1.00026, 1.00026, 0.95317, 0.99999, 0.99999, 0.99999, 0.99999, 1.40483, 1, 0.99977, 1.00054, 1, 1, 0.99953, 0.99962, 1.00042, 0.9995, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];\nconst HelveticaRegularMetrics = {\n  lineHeight: 1.2,\n  lineGap: 0.2\n};\n\n;// CONCATENATED MODULE: ./src/core/liberationsans_widths.js\nconst LiberationSansBoldWidths = [365, 0, 333, 278, 333, 474, 556, 556, 889, 722, 238, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 333, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584, 333, 556, 556, 556, 556, 280, 556, 333, 737, 370, 556, 584, 737, 552, 400, 549, 333, 333, 333, 576, 556, 278, 333, 333, 365, 556, 834, 834, 834, 611, 722, 722, 722, 722, 722, 722, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 556, 556, 556, 556, 556, 278, 278, 278, 278, 611, 611, 611, 611, 611, 611, 611, 549, 611, 611, 611, 611, 611, 556, 611, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 719, 722, 611, 667, 556, 667, 556, 667, 556, 667, 556, 667, 556, 778, 611, 778, 611, 778, 611, 778, 611, 722, 611, 722, 611, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 785, 556, 556, 278, 722, 556, 556, 611, 278, 611, 278, 611, 385, 611, 479, 611, 278, 722, 611, 722, 611, 722, 611, 708, 723, 611, 778, 611, 778, 611, 778, 611, 1000, 944, 722, 389, 722, 389, 722, 389, 667, 556, 667, 556, 667, 556, 667, 556, 611, 333, 611, 479, 611, 333, 722, 611, 722, 611, 722, 611, 722, 611, 722, 611, 722, 611, 944, 778, 667, 556, 667, 611, 500, 611, 500, 611, 500, 278, 556, 722, 556, 1000, 889, 778, 611, 667, 556, 611, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 465, 722, 333, 853, 906, 474, 825, 927, 838, 278, 722, 722, 601, 719, 667, 611, 722, 778, 278, 722, 667, 833, 722, 644, 778, 722, 667, 600, 611, 667, 821, 667, 809, 802, 278, 667, 615, 451, 611, 278, 582, 615, 610, 556, 606, 475, 460, 611, 541, 278, 558, 556, 612, 556, 445, 611, 766, 619, 520, 684, 446, 582, 715, 576, 753, 845, 278, 582, 611, 582, 845, 667, 669, 885, 567, 711, 667, 278, 276, 556, 1094, 1062, 875, 610, 722, 622, 719, 722, 719, 722, 567, 712, 667, 904, 626, 719, 719, 610, 702, 833, 722, 778, 719, 667, 722, 611, 622, 854, 667, 730, 703, 1005, 1019, 870, 979, 719, 711, 1031, 719, 556, 618, 615, 417, 635, 556, 709, 497, 615, 615, 500, 635, 740, 604, 611, 604, 611, 556, 490, 556, 875, 556, 615, 581, 833, 844, 729, 854, 615, 552, 854, 583, 556, 556, 611, 417, 552, 556, 278, 281, 278, 969, 906, 611, 500, 615, 556, 604, 778, 611, 487, 447, 944, 778, 944, 778, 944, 778, 667, 556, 333, 333, 556, 1000, 1000, 552, 278, 278, 278, 278, 500, 500, 500, 556, 556, 350, 1000, 1000, 240, 479, 333, 333, 604, 333, 167, 396, 556, 556, 1094, 556, 885, 489, 1115, 1000, 768, 600, 834, 834, 834, 834, 1000, 500, 1000, 500, 1000, 500, 500, 494, 612, 823, 713, 584, 549, 713, 979, 722, 274, 549, 549, 583, 549, 549, 604, 584, 604, 604, 708, 625, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 729, 604, 604, 354, 354, 1000, 990, 990, 990, 990, 494, 604, 604, 604, 604, 354, 1021, 1052, 917, 750, 750, 531, 656, 594, 510, 500, 750, 750, 611, 611, 333, 333, 333, 333, 333, 333, 333, 333, 222, 222, 333, 333, 333, 333, 333, 333, 333, 333];\nconst LiberationSansBoldMapping = [-1, -1, -1, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 402, 506, 507, 508, 509, 510, 511, 536, 537, 538, 539, 710, 711, 713, 728, 729, 730, 731, 732, 733, 900, 901, 902, 903, 904, 905, 906, 908, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1138, 1139, 1168, 1169, 7808, 7809, 7810, 7811, 7812, 7813, 7922, 7923, 8208, 8209, 8211, 8212, 8213, 8215, 8216, 8217, 8218, 8219, 8220, 8221, 8222, 8224, 8225, 8226, 8230, 8240, 8242, 8243, 8249, 8250, 8252, 8254, 8260, 8319, 8355, 8356, 8359, 8364, 8453, 8467, 8470, 8482, 8486, 8494, 8539, 8540, 8541, 8542, 8592, 8593, 8594, 8595, 8596, 8597, 8616, 8706, 8710, 8719, 8721, 8722, 8730, 8734, 8735, 8745, 8747, 8776, 8800, 8801, 8804, 8805, 8962, 8976, 8992, 8993, 9472, 9474, 9484, 9488, 9492, 9496, 9500, 9508, 9516, 9524, 9532, 9552, 9553, 9554, 9555, 9556, 9557, 9558, 9559, 9560, 9561, 9562, 9563, 9564, 9565, 9566, 9567, 9568, 9569, 9570, 9571, 9572, 9573, 9574, 9575, 9576, 9577, 9578, 9579, 9580, 9600, 9604, 9608, 9612, 9616, 9617, 9618, 9619, 9632, 9633, 9642, 9643, 9644, 9650, 9658, 9660, 9668, 9674, 9675, 9679, 9688, 9689, 9702, 9786, 9787, 9788, 9792, 9794, 9824, 9827, 9829, 9830, 9834, 9835, 9836, 61441, 61442, 61445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1];\nconst LiberationSansBoldItalicWidths = [365, 0, 333, 278, 333, 474, 556, 556, 889, 722, 238, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 333, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584, 333, 556, 556, 556, 556, 280, 556, 333, 737, 370, 556, 584, 737, 552, 400, 549, 333, 333, 333, 576, 556, 278, 333, 333, 365, 556, 834, 834, 834, 611, 722, 722, 722, 722, 722, 722, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 556, 556, 556, 556, 556, 278, 278, 278, 278, 611, 611, 611, 611, 611, 611, 611, 549, 611, 611, 611, 611, 611, 556, 611, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 740, 722, 611, 667, 556, 667, 556, 667, 556, 667, 556, 667, 556, 778, 611, 778, 611, 778, 611, 778, 611, 722, 611, 722, 611, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 782, 556, 556, 278, 722, 556, 556, 611, 278, 611, 278, 611, 396, 611, 479, 611, 278, 722, 611, 722, 611, 722, 611, 708, 723, 611, 778, 611, 778, 611, 778, 611, 1000, 944, 722, 389, 722, 389, 722, 389, 667, 556, 667, 556, 667, 556, 667, 556, 611, 333, 611, 479, 611, 333, 722, 611, 722, 611, 722, 611, 722, 611, 722, 611, 722, 611, 944, 778, 667, 556, 667, 611, 500, 611, 500, 611, 500, 278, 556, 722, 556, 1000, 889, 778, 611, 667, 556, 611, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 722, 333, 854, 906, 473, 844, 930, 847, 278, 722, 722, 610, 671, 667, 611, 722, 778, 278, 722, 667, 833, 722, 657, 778, 718, 667, 590, 611, 667, 822, 667, 829, 781, 278, 667, 620, 479, 611, 278, 591, 620, 621, 556, 610, 479, 492, 611, 558, 278, 566, 556, 603, 556, 450, 611, 712, 605, 532, 664, 409, 591, 704, 578, 773, 834, 278, 591, 611, 591, 834, 667, 667, 886, 614, 719, 667, 278, 278, 556, 1094, 1042, 854, 622, 719, 677, 719, 722, 708, 722, 614, 722, 667, 927, 643, 719, 719, 615, 687, 833, 722, 778, 719, 667, 722, 611, 677, 781, 667, 729, 708, 979, 989, 854, 1000, 708, 719, 1042, 729, 556, 619, 604, 534, 618, 556, 736, 510, 611, 611, 507, 622, 740, 604, 611, 611, 611, 556, 889, 556, 885, 556, 646, 583, 889, 935, 707, 854, 594, 552, 865, 589, 556, 556, 611, 469, 563, 556, 278, 278, 278, 969, 906, 611, 507, 619, 556, 611, 778, 611, 575, 467, 944, 778, 944, 778, 944, 778, 667, 556, 333, 333, 556, 1000, 1000, 552, 278, 278, 278, 278, 500, 500, 500, 556, 556, 350, 1000, 1000, 240, 479, 333, 333, 604, 333, 167, 396, 556, 556, 1104, 556, 885, 516, 1146, 1000, 768, 600, 834, 834, 834, 834, 999, 500, 1000, 500, 1000, 500, 500, 494, 612, 823, 713, 584, 549, 713, 979, 722, 274, 549, 549, 583, 549, 549, 604, 584, 604, 604, 708, 625, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 729, 604, 604, 354, 354, 1000, 990, 990, 990, 990, 494, 604, 604, 604, 604, 354, 1021, 1052, 917, 750, 750, 531, 656, 594, 510, 500, 750, 750, 611, 611, 333, 333, 333, 333, 333, 333, 333, 333, 222, 222, 333, 333, 333, 333, 333, 333, 333, 333];\nconst LiberationSansBoldItalicMapping = [-1, -1, -1, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 402, 506, 507, 508, 509, 510, 511, 536, 537, 538, 539, 710, 711, 713, 728, 729, 730, 731, 732, 733, 900, 901, 902, 903, 904, 905, 906, 908, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1138, 1139, 1168, 1169, 7808, 7809, 7810, 7811, 7812, 7813, 7922, 7923, 8208, 8209, 8211, 8212, 8213, 8215, 8216, 8217, 8218, 8219, 8220, 8221, 8222, 8224, 8225, 8226, 8230, 8240, 8242, 8243, 8249, 8250, 8252, 8254, 8260, 8319, 8355, 8356, 8359, 8364, 8453, 8467, 8470, 8482, 8486, 8494, 8539, 8540, 8541, 8542, 8592, 8593, 8594, 8595, 8596, 8597, 8616, 8706, 8710, 8719, 8721, 8722, 8730, 8734, 8735, 8745, 8747, 8776, 8800, 8801, 8804, 8805, 8962, 8976, 8992, 8993, 9472, 9474, 9484, 9488, 9492, 9496, 9500, 9508, 9516, 9524, 9532, 9552, 9553, 9554, 9555, 9556, 9557, 9558, 9559, 9560, 9561, 9562, 9563, 9564, 9565, 9566, 9567, 9568, 9569, 9570, 9571, 9572, 9573, 9574, 9575, 9576, 9577, 9578, 9579, 9580, 9600, 9604, 9608, 9612, 9616, 9617, 9618, 9619, 9632, 9633, 9642, 9643, 9644, 9650, 9658, 9660, 9668, 9674, 9675, 9679, 9688, 9689, 9702, 9786, 9787, 9788, 9792, 9794, 9824, 9827, 9829, 9830, 9834, 9835, 9836, 61441, 61442, 61445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1];\nconst LiberationSansItalicWidths = [365, 0, 333, 278, 278, 355, 556, 556, 889, 667, 191, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 333, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584, 333, 556, 556, 556, 556, 260, 556, 333, 737, 370, 556, 584, 737, 552, 400, 549, 333, 333, 333, 576, 537, 278, 333, 333, 365, 556, 834, 834, 834, 611, 667, 667, 667, 667, 667, 667, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 500, 556, 556, 556, 556, 278, 278, 278, 278, 556, 556, 556, 556, 556, 556, 556, 549, 611, 556, 556, 556, 556, 500, 556, 500, 667, 556, 667, 556, 667, 556, 722, 500, 722, 500, 722, 500, 722, 500, 722, 625, 722, 556, 667, 556, 667, 556, 667, 556, 667, 556, 667, 556, 778, 556, 778, 556, 778, 556, 778, 556, 722, 556, 722, 556, 278, 278, 278, 278, 278, 278, 278, 222, 278, 278, 733, 444, 500, 222, 667, 500, 500, 556, 222, 556, 222, 556, 281, 556, 400, 556, 222, 722, 556, 722, 556, 722, 556, 615, 723, 556, 778, 556, 778, 556, 778, 556, 1000, 944, 722, 333, 722, 333, 722, 333, 667, 500, 667, 500, 667, 500, 667, 500, 611, 278, 611, 354, 611, 278, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 944, 722, 667, 500, 667, 611, 500, 611, 500, 611, 500, 222, 556, 667, 556, 1000, 889, 778, 611, 667, 500, 611, 278, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 667, 278, 789, 846, 389, 794, 865, 775, 222, 667, 667, 570, 671, 667, 611, 722, 778, 278, 667, 667, 833, 722, 648, 778, 725, 667, 600, 611, 667, 837, 667, 831, 761, 278, 667, 570, 439, 555, 222, 550, 570, 571, 500, 556, 439, 463, 555, 542, 222, 500, 492, 548, 500, 447, 556, 670, 573, 486, 603, 374, 550, 652, 546, 728, 779, 222, 550, 556, 550, 779, 667, 667, 843, 544, 708, 667, 278, 278, 500, 1066, 982, 844, 589, 715, 639, 724, 667, 651, 667, 544, 704, 667, 917, 614, 715, 715, 589, 686, 833, 722, 778, 725, 667, 722, 611, 639, 795, 667, 727, 673, 920, 923, 805, 886, 651, 694, 1022, 682, 556, 562, 522, 493, 553, 556, 688, 465, 556, 556, 472, 564, 686, 550, 556, 556, 556, 500, 833, 500, 835, 500, 572, 518, 830, 851, 621, 736, 526, 492, 752, 534, 556, 556, 556, 378, 496, 500, 222, 222, 222, 910, 828, 556, 472, 565, 500, 556, 778, 556, 492, 339, 944, 722, 944, 722, 944, 722, 667, 500, 333, 333, 556, 1000, 1000, 552, 222, 222, 222, 222, 333, 333, 333, 556, 556, 350, 1000, 1000, 188, 354, 333, 333, 500, 333, 167, 365, 556, 556, 1094, 556, 885, 323, 1083, 1000, 768, 600, 834, 834, 834, 834, 1000, 500, 998, 500, 1000, 500, 500, 494, 612, 823, 713, 584, 549, 713, 979, 719, 274, 549, 549, 584, 549, 549, 604, 584, 604, 604, 708, 625, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 729, 604, 604, 354, 354, 1000, 990, 990, 990, 990, 494, 604, 604, 604, 604, 354, 1021, 1052, 917, 750, 750, 531, 656, 594, 510, 500, 750, 750, 500, 500, 333, 333, 333, 333, 333, 333, 333, 333, 222, 222, 294, 294, 324, 324, 316, 328, 398, 285];\nconst LiberationSansItalicMapping = [-1, -1, -1, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 402, 506, 507, 508, 509, 510, 511, 536, 537, 538, 539, 710, 711, 713, 728, 729, 730, 731, 732, 733, 900, 901, 902, 903, 904, 905, 906, 908, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1138, 1139, 1168, 1169, 7808, 7809, 7810, 7811, 7812, 7813, 7922, 7923, 8208, 8209, 8211, 8212, 8213, 8215, 8216, 8217, 8218, 8219, 8220, 8221, 8222, 8224, 8225, 8226, 8230, 8240, 8242, 8243, 8249, 8250, 8252, 8254, 8260, 8319, 8355, 8356, 8359, 8364, 8453, 8467, 8470, 8482, 8486, 8494, 8539, 8540, 8541, 8542, 8592, 8593, 8594, 8595, 8596, 8597, 8616, 8706, 8710, 8719, 8721, 8722, 8730, 8734, 8735, 8745, 8747, 8776, 8800, 8801, 8804, 8805, 8962, 8976, 8992, 8993, 9472, 9474, 9484, 9488, 9492, 9496, 9500, 9508, 9516, 9524, 9532, 9552, 9553, 9554, 9555, 9556, 9557, 9558, 9559, 9560, 9561, 9562, 9563, 9564, 9565, 9566, 9567, 9568, 9569, 9570, 9571, 9572, 9573, 9574, 9575, 9576, 9577, 9578, 9579, 9580, 9600, 9604, 9608, 9612, 9616, 9617, 9618, 9619, 9632, 9633, 9642, 9643, 9644, 9650, 9658, 9660, 9668, 9674, 9675, 9679, 9688, 9689, 9702, 9786, 9787, 9788, 9792, 9794, 9824, 9827, 9829, 9830, 9834, 9835, 9836, 61441, 61442, 61445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1];\nconst LiberationSansRegularWidths = [365, 0, 333, 278, 278, 355, 556, 556, 889, 667, 191, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 333, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584, 333, 556, 556, 556, 556, 260, 556, 333, 737, 370, 556, 584, 737, 552, 400, 549, 333, 333, 333, 576, 537, 278, 333, 333, 365, 556, 834, 834, 834, 611, 667, 667, 667, 667, 667, 667, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 500, 556, 556, 556, 556, 278, 278, 278, 278, 556, 556, 556, 556, 556, 556, 556, 549, 611, 556, 556, 556, 556, 500, 556, 500, 667, 556, 667, 556, 667, 556, 722, 500, 722, 500, 722, 500, 722, 500, 722, 615, 722, 556, 667, 556, 667, 556, 667, 556, 667, 556, 667, 556, 778, 556, 778, 556, 778, 556, 778, 556, 722, 556, 722, 556, 278, 278, 278, 278, 278, 278, 278, 222, 278, 278, 735, 444, 500, 222, 667, 500, 500, 556, 222, 556, 222, 556, 292, 556, 334, 556, 222, 722, 556, 722, 556, 722, 556, 604, 723, 556, 778, 556, 778, 556, 778, 556, 1000, 944, 722, 333, 722, 333, 722, 333, 667, 500, 667, 500, 667, 500, 667, 500, 611, 278, 611, 375, 611, 278, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 944, 722, 667, 500, 667, 611, 500, 611, 500, 611, 500, 222, 556, 667, 556, 1000, 889, 778, 611, 667, 500, 611, 278, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 667, 278, 784, 838, 384, 774, 855, 752, 222, 667, 667, 551, 668, 667, 611, 722, 778, 278, 667, 668, 833, 722, 650, 778, 722, 667, 618, 611, 667, 798, 667, 835, 748, 278, 667, 578, 446, 556, 222, 547, 578, 575, 500, 557, 446, 441, 556, 556, 222, 500, 500, 576, 500, 448, 556, 690, 569, 482, 617, 395, 547, 648, 525, 713, 781, 222, 547, 556, 547, 781, 667, 667, 865, 542, 719, 667, 278, 278, 500, 1057, 1010, 854, 583, 722, 635, 719, 667, 656, 667, 542, 677, 667, 923, 604, 719, 719, 583, 656, 833, 722, 778, 719, 667, 722, 611, 635, 760, 667, 740, 667, 917, 938, 792, 885, 656, 719, 1010, 722, 556, 573, 531, 365, 583, 556, 669, 458, 559, 559, 438, 583, 688, 552, 556, 542, 556, 500, 458, 500, 823, 500, 573, 521, 802, 823, 625, 719, 521, 510, 750, 542, 556, 556, 556, 365, 510, 500, 222, 278, 222, 906, 812, 556, 438, 559, 500, 552, 778, 556, 489, 411, 944, 722, 944, 722, 944, 722, 667, 500, 333, 333, 556, 1000, 1000, 552, 222, 222, 222, 222, 333, 333, 333, 556, 556, 350, 1000, 1000, 188, 354, 333, 333, 500, 333, 167, 365, 556, 556, 1094, 556, 885, 323, 1073, 1000, 768, 600, 834, 834, 834, 834, 1000, 500, 1000, 500, 1000, 500, 500, 494, 612, 823, 713, 584, 549, 713, 979, 719, 274, 549, 549, 583, 549, 549, 604, 584, 604, 604, 708, 625, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 729, 604, 604, 354, 354, 1000, 990, 990, 990, 990, 494, 604, 604, 604, 604, 354, 1021, 1052, 917, 750, 750, 531, 656, 594, 510, 500, 750, 750, 500, 500, 333, 333, 333, 333, 333, 333, 333, 333, 222, 222, 294, 294, 324, 324, 316, 328, 398, 285];\nconst LiberationSansRegularMapping = [-1, -1, -1, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 402, 506, 507, 508, 509, 510, 511, 536, 537, 538, 539, 710, 711, 713, 728, 729, 730, 731, 732, 733, 900, 901, 902, 903, 904, 905, 906, 908, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1138, 1139, 1168, 1169, 7808, 7809, 7810, 7811, 7812, 7813, 7922, 7923, 8208, 8209, 8211, 8212, 8213, 8215, 8216, 8217, 8218, 8219, 8220, 8221, 8222, 8224, 8225, 8226, 8230, 8240, 8242, 8243, 8249, 8250, 8252, 8254, 8260, 8319, 8355, 8356, 8359, 8364, 8453, 8467, 8470, 8482, 8486, 8494, 8539, 8540, 8541, 8542, 8592, 8593, 8594, 8595, 8596, 8597, 8616, 8706, 8710, 8719, 8721, 8722, 8730, 8734, 8735, 8745, 8747, 8776, 8800, 8801, 8804, 8805, 8962, 8976, 8992, 8993, 9472, 9474, 9484, 9488, 9492, 9496, 9500, 9508, 9516, 9524, 9532, 9552, 9553, 9554, 9555, 9556, 9557, 9558, 9559, 9560, 9561, 9562, 9563, 9564, 9565, 9566, 9567, 9568, 9569, 9570, 9571, 9572, 9573, 9574, 9575, 9576, 9577, 9578, 9579, 9580, 9600, 9604, 9608, 9612, 9616, 9617, 9618, 9619, 9632, 9633, 9642, 9643, 9644, 9650, 9658, 9660, 9668, 9674, 9675, 9679, 9688, 9689, 9702, 9786, 9787, 9788, 9792, 9794, 9824, 9827, 9829, 9830, 9834, 9835, 9836, 61441, 61442, 61445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1];\n\n;// CONCATENATED MODULE: ./src/core/myriadpro_factors.js\nconst MyriadProBoldFactors = [1.36898, 1, 1, 0.72706, 0.80479, 0.83734, 0.98894, 0.99793, 0.9897, 0.93884, 0.86209, 0.94292, 0.94292, 1.16661, 1.02058, 0.93582, 0.96694, 0.93582, 1.19137, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.78076, 0.78076, 1.02058, 1.02058, 1.02058, 0.72851, 0.78966, 0.90838, 0.83637, 0.82391, 0.96376, 0.80061, 0.86275, 0.8768, 0.95407, 1.0258, 0.73901, 0.85022, 0.83655, 1.0156, 0.95546, 0.92179, 0.87107, 0.92179, 0.82114, 0.8096, 0.89713, 0.94438, 0.95353, 0.94083, 0.91905, 0.90406, 0.9446, 0.94292, 1.18777, 0.94292, 1.02058, 0.89903, 0.90088, 0.94938, 0.97898, 0.81093, 0.97571, 0.94938, 1.024, 0.9577, 0.95933, 0.98621, 1.0474, 0.97455, 0.98981, 0.9672, 0.95933, 0.9446, 0.97898, 0.97407, 0.97646, 0.78036, 1.10208, 0.95442, 0.95298, 0.97579, 0.9332, 0.94039, 0.938, 0.80687, 1.01149, 0.80687, 1.02058, 0.80479, 0.99793, 0.99793, 0.99793, 0.99793, 1.01149, 1.00872, 0.90088, 0.91882, 1.0213, 0.8361, 1.02058, 0.62295, 0.54324, 0.89022, 1.08595, 1, 1, 0.90088, 1, 0.97455, 0.93582, 0.90088, 1, 1.05686, 0.8361, 0.99642, 0.99642, 0.99642, 0.72851, 0.90838, 0.90838, 0.90838, 0.90838, 0.90838, 0.90838, 0.868, 0.82391, 0.80061, 0.80061, 0.80061, 0.80061, 1.0258, 1.0258, 1.0258, 1.0258, 0.97484, 0.95546, 0.92179, 0.92179, 0.92179, 0.92179, 0.92179, 1.02058, 0.92179, 0.94438, 0.94438, 0.94438, 0.94438, 0.90406, 0.86958, 0.98225, 0.94938, 0.94938, 0.94938, 0.94938, 0.94938, 0.94938, 0.9031, 0.81093, 0.94938, 0.94938, 0.94938, 0.94938, 0.98621, 0.98621, 0.98621, 0.98621, 0.93969, 0.95933, 0.9446, 0.9446, 0.9446, 0.9446, 0.9446, 1.08595, 0.9446, 0.95442, 0.95442, 0.95442, 0.95442, 0.94039, 0.97898, 0.94039, 0.90838, 0.94938, 0.90838, 0.94938, 0.90838, 0.94938, 0.82391, 0.81093, 0.82391, 0.81093, 0.82391, 0.81093, 0.82391, 0.81093, 0.96376, 0.84313, 0.97484, 0.97571, 0.80061, 0.94938, 0.80061, 0.94938, 0.80061, 0.94938, 0.80061, 0.94938, 0.80061, 0.94938, 0.8768, 0.9577, 0.8768, 0.9577, 0.8768, 0.9577, 1, 1, 0.95407, 0.95933, 0.97069, 0.95933, 1.0258, 0.98621, 1.0258, 0.98621, 1.0258, 0.98621, 1.0258, 0.98621, 1.0258, 0.98621, 0.887, 1.01591, 0.73901, 1.0474, 1, 1, 0.97455, 0.83655, 0.98981, 1, 1, 0.83655, 0.73977, 0.83655, 0.73903, 0.84638, 1.033, 0.95546, 0.95933, 1, 1, 0.95546, 0.95933, 0.8271, 0.95417, 0.95933, 0.92179, 0.9446, 0.92179, 0.9446, 0.92179, 0.9446, 0.936, 0.91964, 0.82114, 0.97646, 1, 1, 0.82114, 0.97646, 0.8096, 0.78036, 0.8096, 0.78036, 1, 1, 0.8096, 0.78036, 1, 1, 0.89713, 0.77452, 0.89713, 1.10208, 0.94438, 0.95442, 0.94438, 0.95442, 0.94438, 0.95442, 0.94438, 0.95442, 0.94438, 0.95442, 0.94438, 0.95442, 0.94083, 0.97579, 0.90406, 0.94039, 0.90406, 0.9446, 0.938, 0.9446, 0.938, 0.9446, 0.938, 1, 0.99793, 0.90838, 0.94938, 0.868, 0.9031, 0.92179, 0.9446, 1, 1, 0.89713, 1.10208, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90989, 0.9358, 0.91945, 0.83181, 0.75261, 0.87992, 0.82976, 0.96034, 0.83689, 0.97268, 1.0078, 0.90838, 0.83637, 0.8019, 0.90157, 0.80061, 0.9446, 0.95407, 0.92436, 1.0258, 0.85022, 0.97153, 1.0156, 0.95546, 0.89192, 0.92179, 0.92361, 0.87107, 0.96318, 0.89713, 0.93704, 0.95638, 0.91905, 0.91709, 0.92796, 1.0258, 0.93704, 0.94836, 1.0373, 0.95933, 1.0078, 0.95871, 0.94836, 0.96174, 0.92601, 0.9498, 0.98607, 0.95776, 0.95933, 1.05453, 1.0078, 0.98275, 0.9314, 0.95617, 0.91701, 1.05993, 0.9446, 0.78367, 0.9553, 1, 0.86832, 1.0128, 0.95871, 0.99394, 0.87548, 0.96361, 0.86774, 1.0078, 0.95871, 0.9446, 0.95871, 0.86774, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.94083, 0.97579, 0.94083, 0.97579, 0.94083, 0.97579, 0.90406, 0.94039, 0.96694, 1, 0.89903, 1, 1, 1, 0.93582, 0.93582, 0.93582, 1, 0.908, 0.908, 0.918, 0.94219, 0.94219, 0.96544, 1, 1.285, 1, 1, 0.81079, 0.81079, 1, 1, 0.74854, 1, 1, 1, 1, 0.99793, 1, 1, 1, 0.65, 1, 1.36145, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.17173, 1, 0.80535, 0.76169, 1.02058, 1.0732, 1.05486, 1, 1, 1.30692, 1.08595, 1.08595, 1, 1.08595, 1.08595, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.16161, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];\nconst MyriadProBoldMetrics = {\n  lineHeight: 1.2,\n  lineGap: 0.2\n};\nconst MyriadProBoldItalicFactors = [1.36898, 1, 1, 0.66227, 0.80779, 0.81625, 0.97276, 0.97276, 0.97733, 0.92222, 0.83266, 0.94292, 0.94292, 1.16148, 1.02058, 0.93582, 0.96694, 0.93582, 1.17337, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.78076, 0.78076, 1.02058, 1.02058, 1.02058, 0.71541, 0.76813, 0.85576, 0.80591, 0.80729, 0.94299, 0.77512, 0.83655, 0.86523, 0.92222, 0.98621, 0.71743, 0.81698, 0.79726, 0.98558, 0.92222, 0.90637, 0.83809, 0.90637, 0.80729, 0.76463, 0.86275, 0.90699, 0.91605, 0.9154, 0.85308, 0.85458, 0.90531, 0.94292, 1.21296, 0.94292, 1.02058, 0.89903, 1.18616, 0.99613, 0.91677, 0.78216, 0.91677, 0.90083, 0.98796, 0.9135, 0.92168, 0.95381, 0.98981, 0.95298, 0.95381, 0.93459, 0.92168, 0.91513, 0.92004, 0.91677, 0.95077, 0.748, 1.04502, 0.91677, 0.92061, 0.94236, 0.89544, 0.89364, 0.9, 0.80687, 0.8578, 0.80687, 1.02058, 0.80779, 0.97276, 0.97276, 0.97276, 0.97276, 0.8578, 0.99973, 1.18616, 0.91339, 1.08074, 0.82891, 1.02058, 0.55509, 0.71526, 0.89022, 1.08595, 1, 1, 1.18616, 1, 0.96736, 0.93582, 1.18616, 1, 1.04864, 0.82711, 0.99043, 0.99043, 0.99043, 0.71541, 0.85576, 0.85576, 0.85576, 0.85576, 0.85576, 0.85576, 0.845, 0.80729, 0.77512, 0.77512, 0.77512, 0.77512, 0.98621, 0.98621, 0.98621, 0.98621, 0.95961, 0.92222, 0.90637, 0.90637, 0.90637, 0.90637, 0.90637, 1.02058, 0.90251, 0.90699, 0.90699, 0.90699, 0.90699, 0.85458, 0.83659, 0.94951, 0.99613, 0.99613, 0.99613, 0.99613, 0.99613, 0.99613, 0.85811, 0.78216, 0.90083, 0.90083, 0.90083, 0.90083, 0.95381, 0.95381, 0.95381, 0.95381, 0.9135, 0.92168, 0.91513, 0.91513, 0.91513, 0.91513, 0.91513, 1.08595, 0.91677, 0.91677, 0.91677, 0.91677, 0.91677, 0.89364, 0.92332, 0.89364, 0.85576, 0.99613, 0.85576, 0.99613, 0.85576, 0.99613, 0.80729, 0.78216, 0.80729, 0.78216, 0.80729, 0.78216, 0.80729, 0.78216, 0.94299, 0.76783, 0.95961, 0.91677, 0.77512, 0.90083, 0.77512, 0.90083, 0.77512, 0.90083, 0.77512, 0.90083, 0.77512, 0.90083, 0.86523, 0.9135, 0.86523, 0.9135, 0.86523, 0.9135, 1, 1, 0.92222, 0.92168, 0.92222, 0.92168, 0.98621, 0.95381, 0.98621, 0.95381, 0.98621, 0.95381, 0.98621, 0.95381, 0.98621, 0.95381, 0.86036, 0.97096, 0.71743, 0.98981, 1, 1, 0.95298, 0.79726, 0.95381, 1, 1, 0.79726, 0.6894, 0.79726, 0.74321, 0.81691, 1.0006, 0.92222, 0.92168, 1, 1, 0.92222, 0.92168, 0.79464, 0.92098, 0.92168, 0.90637, 0.91513, 0.90637, 0.91513, 0.90637, 0.91513, 0.909, 0.87514, 0.80729, 0.95077, 1, 1, 0.80729, 0.95077, 0.76463, 0.748, 0.76463, 0.748, 1, 1, 0.76463, 0.748, 1, 1, 0.86275, 0.72651, 0.86275, 1.04502, 0.90699, 0.91677, 0.90699, 0.91677, 0.90699, 0.91677, 0.90699, 0.91677, 0.90699, 0.91677, 0.90699, 0.91677, 0.9154, 0.94236, 0.85458, 0.89364, 0.85458, 0.90531, 0.9, 0.90531, 0.9, 0.90531, 0.9, 1, 0.97276, 0.85576, 0.99613, 0.845, 0.85811, 0.90251, 0.91677, 1, 1, 0.86275, 1.04502, 1.18616, 1.18616, 1.18616, 1.18616, 1.18616, 1.18616, 1.18616, 1.18616, 1.18616, 1.00899, 1.30628, 0.85576, 0.80178, 0.66862, 0.7927, 0.69323, 0.88127, 0.72459, 0.89711, 0.95381, 0.85576, 0.80591, 0.7805, 0.94729, 0.77512, 0.90531, 0.92222, 0.90637, 0.98621, 0.81698, 0.92655, 0.98558, 0.92222, 0.85359, 0.90637, 0.90976, 0.83809, 0.94523, 0.86275, 0.83509, 0.93157, 0.85308, 0.83392, 0.92346, 0.98621, 0.83509, 0.92886, 0.91324, 0.92168, 0.95381, 0.90646, 0.92886, 0.90557, 0.86847, 0.90276, 0.91324, 0.86842, 0.92168, 0.99531, 0.95381, 0.9224, 0.85408, 0.92699, 0.86847, 1.0051, 0.91513, 0.80487, 0.93481, 1, 0.88159, 1.05214, 0.90646, 0.97355, 0.81539, 0.89398, 0.85923, 0.95381, 0.90646, 0.91513, 0.90646, 0.85923, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9154, 0.94236, 0.9154, 0.94236, 0.9154, 0.94236, 0.85458, 0.89364, 0.96694, 1, 0.89903, 1, 1, 1, 0.91782, 0.91782, 0.91782, 1, 0.896, 0.896, 0.896, 0.9332, 0.9332, 0.95973, 1, 1.26, 1, 1, 0.80479, 0.80178, 1, 1, 0.85633, 1, 1, 1, 1, 0.97276, 1, 1, 1, 0.698, 1, 1.36145, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.14542, 1, 0.79199, 0.78694, 1.02058, 1.03493, 1.05486, 1, 1, 1.23026, 1.08595, 1.08595, 1, 1.08595, 1.08595, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.20006, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];\nconst MyriadProBoldItalicMetrics = {\n  lineHeight: 1.2,\n  lineGap: 0.2\n};\nconst MyriadProItalicFactors = [1.36898, 1, 1, 0.65507, 0.84943, 0.85639, 0.88465, 0.88465, 0.86936, 0.88307, 0.86948, 0.85283, 0.85283, 1.06383, 1.02058, 0.75945, 0.9219, 0.75945, 1.17337, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.75945, 0.75945, 1.02058, 1.02058, 1.02058, 0.69046, 0.70926, 0.85158, 0.77812, 0.76852, 0.89591, 0.70466, 0.76125, 0.80094, 0.86822, 0.83864, 0.728, 0.77212, 0.79475, 0.93637, 0.87514, 0.8588, 0.76013, 0.8588, 0.72421, 0.69866, 0.77598, 0.85991, 0.80811, 0.87832, 0.78112, 0.77512, 0.8562, 1.0222, 1.18417, 1.0222, 1.27014, 0.89903, 1.15012, 0.93859, 0.94399, 0.846, 0.94399, 0.81453, 1.0186, 0.94219, 0.96017, 1.03075, 1.02175, 0.912, 1.03075, 0.96998, 0.96017, 0.93859, 0.94399, 0.94399, 0.95493, 0.746, 1.12658, 0.94578, 0.91, 0.979, 0.882, 0.882, 0.83, 0.85034, 0.83537, 0.85034, 1.02058, 0.70869, 0.88465, 0.88465, 0.88465, 0.88465, 0.83537, 0.90083, 1.15012, 0.9161, 0.94565, 0.73541, 1.02058, 0.53609, 0.69353, 0.79519, 1.08595, 1, 1, 1.15012, 1, 0.91974, 0.75945, 1.15012, 1, 0.9446, 0.73361, 0.9005, 0.9005, 0.9005, 0.62864, 0.85158, 0.85158, 0.85158, 0.85158, 0.85158, 0.85158, 0.773, 0.76852, 0.70466, 0.70466, 0.70466, 0.70466, 0.83864, 0.83864, 0.83864, 0.83864, 0.90561, 0.87514, 0.8588, 0.8588, 0.8588, 0.8588, 0.8588, 1.02058, 0.85751, 0.85991, 0.85991, 0.85991, 0.85991, 0.77512, 0.76013, 0.88075, 0.93859, 0.93859, 0.93859, 0.93859, 0.93859, 0.93859, 0.8075, 0.846, 0.81453, 0.81453, 0.81453, 0.81453, 0.82424, 0.82424, 0.82424, 0.82424, 0.9278, 0.96017, 0.93859, 0.93859, 0.93859, 0.93859, 0.93859, 1.08595, 0.8562, 0.94578, 0.94578, 0.94578, 0.94578, 0.882, 0.94578, 0.882, 0.85158, 0.93859, 0.85158, 0.93859, 0.85158, 0.93859, 0.76852, 0.846, 0.76852, 0.846, 0.76852, 0.846, 0.76852, 0.846, 0.89591, 0.8544, 0.90561, 0.94399, 0.70466, 0.81453, 0.70466, 0.81453, 0.70466, 0.81453, 0.70466, 0.81453, 0.70466, 0.81453, 0.80094, 0.94219, 0.80094, 0.94219, 0.80094, 0.94219, 1, 1, 0.86822, 0.96017, 0.86822, 0.96017, 0.83864, 0.82424, 0.83864, 0.82424, 0.83864, 0.82424, 0.83864, 1.03075, 0.83864, 0.82424, 0.81402, 1.02738, 0.728, 1.02175, 1, 1, 0.912, 0.79475, 1.03075, 1, 1, 0.79475, 0.83911, 0.79475, 0.66266, 0.80553, 1.06676, 0.87514, 0.96017, 1, 1, 0.87514, 0.96017, 0.86865, 0.87396, 0.96017, 0.8588, 0.93859, 0.8588, 0.93859, 0.8588, 0.93859, 0.867, 0.84759, 0.72421, 0.95493, 1, 1, 0.72421, 0.95493, 0.69866, 0.746, 0.69866, 0.746, 1, 1, 0.69866, 0.746, 1, 1, 0.77598, 0.88417, 0.77598, 1.12658, 0.85991, 0.94578, 0.85991, 0.94578, 0.85991, 0.94578, 0.85991, 0.94578, 0.85991, 0.94578, 0.85991, 0.94578, 0.87832, 0.979, 0.77512, 0.882, 0.77512, 0.8562, 0.83, 0.8562, 0.83, 0.8562, 0.83, 1, 0.88465, 0.85158, 0.93859, 0.773, 0.8075, 0.85751, 0.8562, 1, 1, 0.77598, 1.12658, 1.15012, 1.15012, 1.15012, 1.15012, 1.15012, 1.15313, 1.15012, 1.15012, 1.15012, 1.08106, 1.03901, 0.85158, 0.77025, 0.62264, 0.7646, 0.65351, 0.86026, 0.69461, 0.89947, 1.03075, 0.85158, 0.77812, 0.76449, 0.88836, 0.70466, 0.8562, 0.86822, 0.8588, 0.83864, 0.77212, 0.85308, 0.93637, 0.87514, 0.82352, 0.8588, 0.85701, 0.76013, 0.89058, 0.77598, 0.8156, 0.82565, 0.78112, 0.77899, 0.89386, 0.83864, 0.8156, 0.9486, 0.92388, 0.96186, 1.03075, 0.91123, 0.9486, 0.93298, 0.878, 0.93942, 0.92388, 0.84596, 0.96186, 0.95119, 1.03075, 0.922, 0.88787, 0.95829, 0.88, 0.93559, 0.93859, 0.78815, 0.93758, 1, 0.89217, 1.03737, 0.91123, 0.93969, 0.77487, 0.85769, 0.86799, 1.03075, 0.91123, 0.93859, 0.91123, 0.86799, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.87832, 0.979, 0.87832, 0.979, 0.87832, 0.979, 0.77512, 0.882, 0.9219, 1, 0.89903, 1, 1, 1, 0.87321, 0.87321, 0.87321, 1, 1.027, 1.027, 1.027, 0.86847, 0.86847, 0.79121, 1, 1.124, 1, 1, 0.73572, 0.73572, 1, 1, 0.85034, 1, 1, 1, 1, 0.88465, 1, 1, 1, 0.669, 1, 1.36145, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.04828, 1, 0.74948, 0.75187, 1.02058, 0.98391, 1.02119, 1, 1, 1.06233, 1.08595, 1.08595, 1, 1.08595, 1.08595, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.05233, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];\nconst MyriadProItalicMetrics = {\n  lineHeight: 1.2,\n  lineGap: 0.2\n};\nconst MyriadProRegularFactors = [1.36898, 1, 1, 0.76305, 0.82784, 0.94935, 0.89364, 0.92241, 0.89073, 0.90706, 0.98472, 0.85283, 0.85283, 1.0664, 1.02058, 0.74505, 0.9219, 0.74505, 1.23456, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.74505, 0.74505, 1.02058, 1.02058, 1.02058, 0.73002, 0.72601, 0.91755, 0.8126, 0.80314, 0.92222, 0.73764, 0.79726, 0.83051, 0.90284, 0.86023, 0.74, 0.8126, 0.84869, 0.96518, 0.91115, 0.8858, 0.79761, 0.8858, 0.74498, 0.73914, 0.81363, 0.89591, 0.83659, 0.89633, 0.85608, 0.8111, 0.90531, 1.0222, 1.22736, 1.0222, 1.27014, 0.89903, 0.90088, 0.86667, 1.0231, 0.896, 1.01411, 0.90083, 1.05099, 1.00512, 0.99793, 1.05326, 1.09377, 0.938, 1.06226, 1.00119, 0.99793, 0.98714, 1.0231, 1.01231, 0.98196, 0.792, 1.19137, 0.99074, 0.962, 1.01915, 0.926, 0.942, 0.856, 0.85034, 0.92006, 0.85034, 1.02058, 0.69067, 0.92241, 0.92241, 0.92241, 0.92241, 0.92006, 0.9332, 0.90088, 0.91882, 0.93484, 0.75339, 1.02058, 0.56866, 0.54324, 0.79519, 1.08595, 1, 1, 0.90088, 1, 0.95325, 0.74505, 0.90088, 1, 0.97198, 0.75339, 0.91009, 0.91009, 0.91009, 0.66466, 0.91755, 0.91755, 0.91755, 0.91755, 0.91755, 0.91755, 0.788, 0.80314, 0.73764, 0.73764, 0.73764, 0.73764, 0.86023, 0.86023, 0.86023, 0.86023, 0.92915, 0.91115, 0.8858, 0.8858, 0.8858, 0.8858, 0.8858, 1.02058, 0.8858, 0.89591, 0.89591, 0.89591, 0.89591, 0.8111, 0.79611, 0.89713, 0.86667, 0.86667, 0.86667, 0.86667, 0.86667, 0.86667, 0.86936, 0.896, 0.90083, 0.90083, 0.90083, 0.90083, 0.84224, 0.84224, 0.84224, 0.84224, 0.97276, 0.99793, 0.98714, 0.98714, 0.98714, 0.98714, 0.98714, 1.08595, 0.89876, 0.99074, 0.99074, 0.99074, 0.99074, 0.942, 1.0231, 0.942, 0.91755, 0.86667, 0.91755, 0.86667, 0.91755, 0.86667, 0.80314, 0.896, 0.80314, 0.896, 0.80314, 0.896, 0.80314, 0.896, 0.92222, 0.93372, 0.92915, 1.01411, 0.73764, 0.90083, 0.73764, 0.90083, 0.73764, 0.90083, 0.73764, 0.90083, 0.73764, 0.90083, 0.83051, 1.00512, 0.83051, 1.00512, 0.83051, 1.00512, 1, 1, 0.90284, 0.99793, 0.90976, 0.99793, 0.86023, 0.84224, 0.86023, 0.84224, 0.86023, 0.84224, 0.86023, 1.05326, 0.86023, 0.84224, 0.82873, 1.07469, 0.74, 1.09377, 1, 1, 0.938, 0.84869, 1.06226, 1, 1, 0.84869, 0.83704, 0.84869, 0.81441, 0.85588, 1.08927, 0.91115, 0.99793, 1, 1, 0.91115, 0.99793, 0.91887, 0.90991, 0.99793, 0.8858, 0.98714, 0.8858, 0.98714, 0.8858, 0.98714, 0.894, 0.91434, 0.74498, 0.98196, 1, 1, 0.74498, 0.98196, 0.73914, 0.792, 0.73914, 0.792, 1, 1, 0.73914, 0.792, 1, 1, 0.81363, 0.904, 0.81363, 1.19137, 0.89591, 0.99074, 0.89591, 0.99074, 0.89591, 0.99074, 0.89591, 0.99074, 0.89591, 0.99074, 0.89591, 0.99074, 0.89633, 1.01915, 0.8111, 0.942, 0.8111, 0.90531, 0.856, 0.90531, 0.856, 0.90531, 0.856, 1, 0.92241, 0.91755, 0.86667, 0.788, 0.86936, 0.8858, 0.89876, 1, 1, 0.81363, 1.19137, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90388, 1.03901, 0.92138, 0.78105, 0.7154, 0.86169, 0.80513, 0.94007, 0.82528, 0.98612, 1.06226, 0.91755, 0.8126, 0.81884, 0.92819, 0.73764, 0.90531, 0.90284, 0.8858, 0.86023, 0.8126, 0.91172, 0.96518, 0.91115, 0.83089, 0.8858, 0.87791, 0.79761, 0.89297, 0.81363, 0.88157, 0.89992, 0.85608, 0.81992, 0.94307, 0.86023, 0.88157, 0.95308, 0.98699, 0.99793, 1.06226, 0.95817, 0.95308, 0.97358, 0.928, 0.98088, 0.98699, 0.92761, 0.99793, 0.96017, 1.06226, 0.986, 0.944, 0.95978, 0.938, 0.96705, 0.98714, 0.80442, 0.98972, 1, 0.89762, 1.04552, 0.95817, 0.99007, 0.87064, 0.91879, 0.88888, 1.06226, 0.95817, 0.98714, 0.95817, 0.88888, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.89633, 1.01915, 0.89633, 1.01915, 0.89633, 1.01915, 0.8111, 0.942, 0.9219, 1, 0.89903, 1, 1, 1, 0.93173, 0.93173, 0.93173, 1, 1.06304, 1.06304, 1.06904, 0.89903, 0.89903, 0.80549, 1, 1.156, 1, 1, 0.76575, 0.76575, 1, 1, 0.72458, 1, 1, 1, 1, 0.92241, 1, 1, 1, 0.619, 1, 1.36145, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.07257, 1, 0.74705, 0.71119, 1.02058, 1.024, 1.02119, 1, 1, 1.1536, 1.08595, 1.08595, 1, 1.08595, 1.08595, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.05638, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];\nconst MyriadProRegularMetrics = {\n  lineHeight: 1.2,\n  lineGap: 0.2\n};\n\n;// CONCATENATED MODULE: ./src/core/segoeui_factors.js\nconst SegoeuiBoldFactors = [1.76738, 1, 1, 0.99297, 0.9824, 1.04016, 1.06497, 1.03424, 0.97529, 1.17647, 1.23203, 1.1085, 1.1085, 1.16939, 1.2107, 0.9754, 1.21408, 0.9754, 1.59578, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 0.81378, 0.81378, 1.2107, 1.2107, 1.2107, 0.71703, 0.97847, 0.97363, 0.88776, 0.8641, 1.02096, 0.79795, 0.85132, 0.914, 1.06085, 1.1406, 0.8007, 0.89858, 0.83693, 1.14889, 1.09398, 0.97489, 0.92094, 0.97489, 0.90399, 0.84041, 0.95923, 1.00135, 1, 1.06467, 0.98243, 0.90996, 0.99361, 1.1085, 1.56942, 1.1085, 1.2107, 0.74627, 0.94282, 0.96752, 1.01519, 0.86304, 1.01359, 0.97278, 1.15103, 1.01359, 0.98561, 1.02285, 1.02285, 1.00527, 1.02285, 1.0302, 0.99041, 1.0008, 1.01519, 1.01359, 1.02258, 0.79104, 1.16862, 0.99041, 0.97454, 1.02511, 0.99298, 0.96752, 0.95801, 0.94856, 1.16579, 0.94856, 1.2107, 0.9824, 1.03424, 1.03424, 1, 1.03424, 1.16579, 0.8727, 1.3871, 1.18622, 1.10818, 1.04478, 1.2107, 1.18622, 0.75155, 0.94994, 1.28826, 1.21408, 1.21408, 0.91056, 1, 0.91572, 0.9754, 0.64663, 1.18328, 1.24866, 1.04478, 1.14169, 1.15749, 1.17389, 0.71703, 0.97363, 0.97363, 0.97363, 0.97363, 0.97363, 0.97363, 0.93506, 0.8641, 0.79795, 0.79795, 0.79795, 0.79795, 1.1406, 1.1406, 1.1406, 1.1406, 1.02096, 1.09398, 0.97426, 0.97426, 0.97426, 0.97426, 0.97426, 1.2107, 0.97489, 1.00135, 1.00135, 1.00135, 1.00135, 0.90996, 0.92094, 1.02798, 0.96752, 0.96752, 0.96752, 0.96752, 0.96752, 0.96752, 0.93136, 0.86304, 0.97278, 0.97278, 0.97278, 0.97278, 1.02285, 1.02285, 1.02285, 1.02285, 0.97122, 0.99041, 1, 1, 1, 1, 1, 1.28826, 1.0008, 0.99041, 0.99041, 0.99041, 0.99041, 0.96752, 1.01519, 0.96752, 0.97363, 0.96752, 0.97363, 0.96752, 0.97363, 0.96752, 0.8641, 0.86304, 0.8641, 0.86304, 0.8641, 0.86304, 0.8641, 0.86304, 1.02096, 1.03057, 1.02096, 1.03517, 0.79795, 0.97278, 0.79795, 0.97278, 0.79795, 0.97278, 0.79795, 0.97278, 0.79795, 0.97278, 0.914, 1.01359, 0.914, 1.01359, 0.914, 1.01359, 1, 1, 1.06085, 0.98561, 1.06085, 1.00879, 1.1406, 1.02285, 1.1406, 1.02285, 1.1406, 1.02285, 1.1406, 1.02285, 1.1406, 1.02285, 0.97138, 1.08692, 0.8007, 1.02285, 1, 1, 1.00527, 0.83693, 1.02285, 1, 1, 0.83693, 0.9455, 0.83693, 0.90418, 0.83693, 1.13005, 1.09398, 0.99041, 1, 1, 1.09398, 0.99041, 0.96692, 1.09251, 0.99041, 0.97489, 1.0008, 0.97489, 1.0008, 0.97489, 1.0008, 0.93994, 0.97931, 0.90399, 1.02258, 1, 1, 0.90399, 1.02258, 0.84041, 0.79104, 0.84041, 0.79104, 0.84041, 0.79104, 0.84041, 0.79104, 1, 1, 0.95923, 1.07034, 0.95923, 1.16862, 1.00135, 0.99041, 1.00135, 0.99041, 1.00135, 0.99041, 1.00135, 0.99041, 1.00135, 0.99041, 1.00135, 0.99041, 1.06467, 1.02511, 0.90996, 0.96752, 0.90996, 0.99361, 0.95801, 0.99361, 0.95801, 0.99361, 0.95801, 1.07733, 1.03424, 0.97363, 0.96752, 0.93506, 0.93136, 0.97489, 1.0008, 1, 1, 0.95923, 1.16862, 1.15103, 1.15103, 1.01173, 1.03959, 0.75953, 0.81378, 0.79912, 1.15103, 1.21994, 0.95161, 0.87815, 1.01149, 0.81525, 0.7676, 0.98167, 1.01134, 1.02546, 0.84097, 1.03089, 1.18102, 0.97363, 0.88776, 0.85134, 0.97826, 0.79795, 0.99361, 1.06085, 0.97489, 1.1406, 0.89858, 1.0388, 1.14889, 1.09398, 0.86039, 0.97489, 1.0595, 0.92094, 0.94793, 0.95923, 0.90996, 0.99346, 0.98243, 1.02112, 0.95493, 1.1406, 0.90996, 1.03574, 1.02597, 1.0008, 1.18102, 1.06628, 1.03574, 1.0192, 1.01932, 1.00886, 0.97531, 1.0106, 1.0008, 1.13189, 1.18102, 1.02277, 0.98683, 1.0016, 0.99561, 1.07237, 1.0008, 0.90434, 0.99921, 0.93803, 0.8965, 1.23085, 1.06628, 1.04983, 0.96268, 1.0499, 0.98439, 1.18102, 1.06628, 1.0008, 1.06628, 0.98439, 0.79795, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.09466, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.97278, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.02065, 1, 1, 1, 1, 1, 1, 1.06467, 1.02511, 1.06467, 1.02511, 1.06467, 1.02511, 0.90996, 0.96752, 1, 1.21408, 0.89903, 1, 1, 0.75155, 1.04394, 1.04394, 1.04394, 1.04394, 0.98633, 0.98633, 0.98633, 0.73047, 0.73047, 1.20642, 0.91211, 1.25635, 1.222, 1.02956, 1.03372, 1.03372, 0.96039, 1.24633, 1, 1.12454, 0.93503, 1.03424, 1.19687, 1.03424, 1, 1, 1, 0.771, 1, 1, 1.15749, 1.15749, 1.15749, 1.10948, 0.86279, 0.94434, 0.86279, 0.94434, 0.86182, 1, 1, 1.16897, 1, 0.96085, 0.90137, 1.2107, 1.18416, 1.13973, 0.69825, 0.9716, 2.10339, 1.29004, 1.29004, 1.21172, 1.29004, 1.29004, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.42603, 1, 0.99862, 0.99862, 1, 0.87025, 0.87025, 0.87025, 0.87025, 1.18874, 1.42603, 1, 1.42603, 1.42603, 0.99862, 1, 1, 1, 1, 1, 1.2886, 1.04315, 1.15296, 1.34163, 1, 1, 1, 1.09193, 1.09193, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];\nconst SegoeuiBoldMetrics = {\n  lineHeight: 1.33008,\n  lineGap: 0\n};\nconst SegoeuiBoldItalicFactors = [1.76738, 1, 1, 0.98946, 1.03959, 1.04016, 1.02809, 1.036, 0.97639, 1.10953, 1.23203, 1.11144, 1.11144, 1.16939, 1.21237, 0.9754, 1.21261, 0.9754, 1.59754, 1.036, 1.036, 1.036, 1.036, 1.036, 1.036, 1.036, 1.036, 1.036, 1.036, 0.81378, 0.81378, 1.21237, 1.21237, 1.21237, 0.73541, 0.97847, 0.97363, 0.89723, 0.87897, 1.0426, 0.79429, 0.85292, 0.91149, 1.05815, 1.1406, 0.79631, 0.90128, 0.83853, 1.04396, 1.10615, 0.97552, 0.94436, 0.97552, 0.88641, 0.80527, 0.96083, 1.00135, 1, 1.06777, 0.9817, 0.91142, 0.99361, 1.11144, 1.57293, 1.11144, 1.21237, 0.74627, 1.31818, 1.06585, 0.97042, 0.83055, 0.97042, 0.93503, 1.1261, 0.97042, 0.97922, 1.14236, 0.94552, 1.01054, 1.14236, 1.02471, 0.97922, 0.94165, 0.97042, 0.97042, 1.0276, 0.78929, 1.1261, 0.97922, 0.95874, 1.02197, 0.98507, 0.96752, 0.97168, 0.95107, 1.16579, 0.95107, 1.21237, 1.03959, 1.036, 1.036, 1, 1.036, 1.16579, 0.87357, 1.31818, 1.18754, 1.26781, 1.05356, 1.21237, 1.18622, 0.79487, 0.94994, 1.29004, 1.24047, 1.24047, 1.31818, 1, 0.91484, 0.9754, 1.31818, 1.1349, 1.24866, 1.05356, 1.13934, 1.15574, 1.17389, 0.73541, 0.97363, 0.97363, 0.97363, 0.97363, 0.97363, 0.97363, 0.94385, 0.87897, 0.79429, 0.79429, 0.79429, 0.79429, 1.1406, 1.1406, 1.1406, 1.1406, 1.0426, 1.10615, 0.97552, 0.97552, 0.97552, 0.97552, 0.97552, 1.21237, 0.97552, 1.00135, 1.00135, 1.00135, 1.00135, 0.91142, 0.94436, 0.98721, 1.06585, 1.06585, 1.06585, 1.06585, 1.06585, 1.06585, 0.96705, 0.83055, 0.93503, 0.93503, 0.93503, 0.93503, 1.14236, 1.14236, 1.14236, 1.14236, 0.93125, 0.97922, 0.94165, 0.94165, 0.94165, 0.94165, 0.94165, 1.29004, 0.94165, 0.97922, 0.97922, 0.97922, 0.97922, 0.96752, 0.97042, 0.96752, 0.97363, 1.06585, 0.97363, 1.06585, 0.97363, 1.06585, 0.87897, 0.83055, 0.87897, 0.83055, 0.87897, 0.83055, 0.87897, 0.83055, 1.0426, 1.0033, 1.0426, 0.97042, 0.79429, 0.93503, 0.79429, 0.93503, 0.79429, 0.93503, 0.79429, 0.93503, 0.79429, 0.93503, 0.91149, 0.97042, 0.91149, 0.97042, 0.91149, 0.97042, 1, 1, 1.05815, 0.97922, 1.05815, 0.97922, 1.1406, 1.14236, 1.1406, 1.14236, 1.1406, 1.14236, 1.1406, 1.14236, 1.1406, 1.14236, 0.97441, 1.04302, 0.79631, 1.01582, 1, 1, 1.01054, 0.83853, 1.14236, 1, 1, 0.83853, 1.09125, 0.83853, 0.90418, 0.83853, 1.19508, 1.10615, 0.97922, 1, 1, 1.10615, 0.97922, 1.01034, 1.10466, 0.97922, 0.97552, 0.94165, 0.97552, 0.94165, 0.97552, 0.94165, 0.91602, 0.91981, 0.88641, 1.0276, 1, 1, 0.88641, 1.0276, 0.80527, 0.78929, 0.80527, 0.78929, 0.80527, 0.78929, 0.80527, 0.78929, 1, 1, 0.96083, 1.05403, 0.95923, 1.16862, 1.00135, 0.97922, 1.00135, 0.97922, 1.00135, 0.97922, 1.00135, 0.97922, 1.00135, 0.97922, 1.00135, 0.97922, 1.06777, 1.02197, 0.91142, 0.96752, 0.91142, 0.99361, 0.97168, 0.99361, 0.97168, 0.99361, 0.97168, 1.23199, 1.036, 0.97363, 1.06585, 0.94385, 0.96705, 0.97552, 0.94165, 1, 1, 0.96083, 1.1261, 1.31818, 1.31818, 1.31818, 1.31818, 1.31818, 1.31818, 1.31818, 1.31818, 1.31818, 0.95161, 1.27126, 1.00811, 0.83284, 0.77702, 0.99137, 0.95253, 1.0347, 0.86142, 1.07205, 1.14236, 0.97363, 0.89723, 0.86869, 1.09818, 0.79429, 0.99361, 1.05815, 0.97552, 1.1406, 0.90128, 1.06662, 1.04396, 1.10615, 0.84918, 0.97552, 1.04694, 0.94436, 0.98015, 0.96083, 0.91142, 1.00356, 0.9817, 1.01945, 0.98999, 1.1406, 0.91142, 1.04961, 0.9898, 1.00639, 1.14236, 1.07514, 1.04961, 0.99607, 1.02897, 1.008, 0.9898, 0.95134, 1.00639, 1.11121, 1.14236, 1.00518, 0.97981, 1.02186, 1, 1.08578, 0.94165, 0.99314, 0.98387, 0.93028, 0.93377, 1.35125, 1.07514, 1.10687, 0.93491, 1.04232, 1.00351, 1.14236, 1.07514, 0.94165, 1.07514, 1.00351, 0.79429, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.09097, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.93503, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.96609, 1, 1, 1, 1, 1, 1, 1.06777, 1.02197, 1.06777, 1.02197, 1.06777, 1.02197, 0.91142, 0.96752, 1, 1.21261, 0.89903, 1, 1, 0.75155, 1.04745, 1.04745, 1.04745, 1.04394, 0.98633, 0.98633, 0.98633, 0.72959, 0.72959, 1.20502, 0.91406, 1.26514, 1.222, 1.02956, 1.03372, 1.03372, 0.96039, 1.24633, 1, 1.09125, 0.93327, 1.03336, 1.16541, 1.036, 1, 1, 1, 0.771, 1, 1, 1.15574, 1.15574, 1.15574, 1.15574, 0.86364, 0.94434, 0.86279, 0.94434, 0.86224, 1, 1, 1.16798, 1, 0.96085, 0.90068, 1.21237, 1.18416, 1.13904, 0.69825, 0.9716, 2.10339, 1.29004, 1.29004, 1.21339, 1.29004, 1.29004, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.42603, 1, 0.99862, 0.99862, 1, 0.87025, 0.87025, 0.87025, 0.87025, 1.18775, 1.42603, 1, 1.42603, 1.42603, 0.99862, 1, 1, 1, 1, 1, 1.2886, 1.04315, 1.15296, 1.34163, 1, 1, 1, 1.13269, 1.13269, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];\nconst SegoeuiBoldItalicMetrics = {\n  lineHeight: 1.33008,\n  lineGap: 0\n};\nconst SegoeuiItalicFactors = [1.76738, 1, 1, 0.98946, 1.14763, 1.05365, 1.06234, 0.96927, 0.92586, 1.15373, 1.18414, 0.91349, 0.91349, 1.07403, 1.17308, 0.78383, 1.20088, 0.78383, 1.42531, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.78383, 0.78383, 1.17308, 1.17308, 1.17308, 0.77349, 0.94565, 0.94729, 0.85944, 0.88506, 0.9858, 0.74817, 0.80016, 0.88449, 0.98039, 0.95782, 0.69238, 0.89898, 0.83231, 0.98183, 1.03989, 0.96924, 0.86237, 0.96924, 0.80595, 0.74524, 0.86091, 0.95402, 0.94143, 0.98448, 0.8858, 0.83089, 0.93285, 1.0949, 1.39016, 1.0949, 1.45994, 0.74627, 1.04839, 0.97454, 0.97454, 0.87207, 0.97454, 0.87533, 1.06151, 0.97454, 1.00176, 1.16484, 1.08132, 0.98047, 1.16484, 1.02989, 1.01054, 0.96225, 0.97454, 0.97454, 1.06598, 0.79004, 1.16344, 1.00351, 0.94629, 0.9973, 0.91016, 0.96777, 0.9043, 0.91082, 0.92481, 0.91082, 1.17308, 0.95748, 0.96927, 0.96927, 1, 0.96927, 0.92481, 0.80597, 1.04839, 1.23393, 1.1781, 0.9245, 1.17308, 1.20808, 0.63218, 0.94261, 1.24822, 1.09971, 1.09971, 1.04839, 1, 0.85273, 0.78032, 1.04839, 1.09971, 1.22326, 0.9245, 1.09836, 1.13525, 1.15222, 0.70424, 0.94729, 0.94729, 0.94729, 0.94729, 0.94729, 0.94729, 0.85498, 0.88506, 0.74817, 0.74817, 0.74817, 0.74817, 0.95782, 0.95782, 0.95782, 0.95782, 0.9858, 1.03989, 0.96924, 0.96924, 0.96924, 0.96924, 0.96924, 1.17308, 0.96924, 0.95402, 0.95402, 0.95402, 0.95402, 0.83089, 0.86237, 0.88409, 0.97454, 0.97454, 0.97454, 0.97454, 0.97454, 0.97454, 0.92916, 0.87207, 0.87533, 0.87533, 0.87533, 0.87533, 0.93146, 0.93146, 0.93146, 0.93146, 0.93854, 1.01054, 0.96225, 0.96225, 0.96225, 0.96225, 0.96225, 1.24822, 0.8761, 1.00351, 1.00351, 1.00351, 1.00351, 0.96777, 0.97454, 0.96777, 0.94729, 0.97454, 0.94729, 0.97454, 0.94729, 0.97454, 0.88506, 0.87207, 0.88506, 0.87207, 0.88506, 0.87207, 0.88506, 0.87207, 0.9858, 0.95391, 0.9858, 0.97454, 0.74817, 0.87533, 0.74817, 0.87533, 0.74817, 0.87533, 0.74817, 0.87533, 0.74817, 0.87533, 0.88449, 0.97454, 0.88449, 0.97454, 0.88449, 0.97454, 1, 1, 0.98039, 1.00176, 0.98039, 1.00176, 0.95782, 0.93146, 0.95782, 0.93146, 0.95782, 0.93146, 0.95782, 1.16484, 0.95782, 0.93146, 0.84421, 1.12761, 0.69238, 1.08132, 1, 1, 0.98047, 0.83231, 1.16484, 1, 1, 0.84723, 1.04861, 0.84723, 0.78755, 0.83231, 1.23736, 1.03989, 1.01054, 1, 1, 1.03989, 1.01054, 0.9857, 1.03849, 1.01054, 0.96924, 0.96225, 0.96924, 0.96225, 0.96924, 0.96225, 0.92383, 0.90171, 0.80595, 1.06598, 1, 1, 0.80595, 1.06598, 0.74524, 0.79004, 0.74524, 0.79004, 0.74524, 0.79004, 0.74524, 0.79004, 1, 1, 0.86091, 1.02759, 0.85771, 1.16344, 0.95402, 1.00351, 0.95402, 1.00351, 0.95402, 1.00351, 0.95402, 1.00351, 0.95402, 1.00351, 0.95402, 1.00351, 0.98448, 0.9973, 0.83089, 0.96777, 0.83089, 0.93285, 0.9043, 0.93285, 0.9043, 0.93285, 0.9043, 1.31868, 0.96927, 0.94729, 0.97454, 0.85498, 0.92916, 0.96924, 0.8761, 1, 1, 0.86091, 1.16344, 1.04839, 1.04839, 1.04839, 1.04839, 1.04839, 1.04839, 1.04839, 1.04839, 1.04839, 0.81965, 0.81965, 0.94729, 0.78032, 0.71022, 0.90883, 0.84171, 0.99877, 0.77596, 1.05734, 1.2, 0.94729, 0.85944, 0.82791, 0.9607, 0.74817, 0.93285, 0.98039, 0.96924, 0.95782, 0.89898, 0.98316, 0.98183, 1.03989, 0.78614, 0.96924, 0.97642, 0.86237, 0.86075, 0.86091, 0.83089, 0.90082, 0.8858, 0.97296, 1.01284, 0.95782, 0.83089, 1.0976, 1.04, 1.03342, 1.2, 1.0675, 1.0976, 0.98205, 1.03809, 1.05097, 1.04, 0.95364, 1.03342, 1.05401, 1.2, 1.02148, 1.0119, 1.04724, 1.0127, 1.02732, 0.96225, 0.8965, 0.97783, 0.93574, 0.94818, 1.30679, 1.0675, 1.11826, 0.99821, 1.0557, 1.0326, 1.2, 1.0675, 0.96225, 1.0675, 1.0326, 0.74817, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.03754, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.87533, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.98705, 1, 1, 1, 1, 1, 1, 0.98448, 0.9973, 0.98448, 0.9973, 0.98448, 0.9973, 0.83089, 0.96777, 1, 1.20088, 0.89903, 1, 1, 0.75155, 0.94945, 0.94945, 0.94945, 0.94945, 1.12317, 1.12317, 1.12317, 0.67603, 0.67603, 1.15621, 0.73584, 1.21191, 1.22135, 1.06483, 0.94868, 0.94868, 0.95996, 1.24633, 1, 1.07497, 0.87709, 0.96927, 1.01473, 0.96927, 1, 1, 1, 0.77295, 1, 1, 1.09836, 1.09836, 1.09836, 1.01522, 0.86321, 0.94434, 0.8649, 0.94434, 0.86182, 1, 1, 1.083, 1, 0.91578, 0.86438, 1.17308, 1.18416, 1.14589, 0.69825, 0.97622, 1.96791, 1.24822, 1.24822, 1.17308, 1.24822, 1.24822, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.42603, 1, 0.99862, 0.99862, 1, 0.87025, 0.87025, 0.87025, 0.87025, 1.17984, 1.42603, 1, 1.42603, 1.42603, 0.99862, 1, 1, 1, 1, 1, 1.2886, 1.04315, 1.15296, 1.34163, 1, 1, 1, 1.10742, 1.10742, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];\nconst SegoeuiItalicMetrics = {\n  lineHeight: 1.33008,\n  lineGap: 0\n};\nconst SegoeuiRegularFactors = [1.76738, 1, 1, 0.98594, 1.02285, 1.10454, 1.06234, 0.96927, 0.92037, 1.19985, 1.2046, 0.90616, 0.90616, 1.07152, 1.1714, 0.78032, 1.20088, 0.78032, 1.40246, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.78032, 0.78032, 1.1714, 1.1714, 1.1714, 0.80597, 0.94084, 0.96706, 0.85944, 0.85734, 0.97093, 0.75842, 0.79936, 0.88198, 0.9831, 0.95782, 0.71387, 0.86969, 0.84636, 1.07796, 1.03584, 0.96924, 0.83968, 0.96924, 0.82826, 0.79649, 0.85771, 0.95132, 0.93119, 0.98965, 0.88433, 0.8287, 0.93365, 1.08612, 1.3638, 1.08612, 1.45786, 0.74627, 0.80499, 0.91484, 1.05707, 0.92383, 1.05882, 0.9403, 1.12654, 1.05882, 1.01756, 1.09011, 1.09011, 0.99414, 1.09011, 1.034, 1.01756, 1.05356, 1.05707, 1.05882, 1.04399, 0.84863, 1.21968, 1.01756, 0.95801, 1.00068, 0.91797, 0.96777, 0.9043, 0.90351, 0.92105, 0.90351, 1.1714, 0.85337, 0.96927, 0.96927, 0.99912, 0.96927, 0.92105, 0.80597, 1.2434, 1.20808, 1.05937, 0.90957, 1.1714, 1.20808, 0.75155, 0.94261, 1.24644, 1.09971, 1.09971, 0.84751, 1, 0.85273, 0.78032, 0.61584, 1.05425, 1.17914, 0.90957, 1.08665, 1.11593, 1.14169, 0.73381, 0.96706, 0.96706, 0.96706, 0.96706, 0.96706, 0.96706, 0.86035, 0.85734, 0.75842, 0.75842, 0.75842, 0.75842, 0.95782, 0.95782, 0.95782, 0.95782, 0.97093, 1.03584, 0.96924, 0.96924, 0.96924, 0.96924, 0.96924, 1.1714, 0.96924, 0.95132, 0.95132, 0.95132, 0.95132, 0.8287, 0.83968, 0.89049, 0.91484, 0.91484, 0.91484, 0.91484, 0.91484, 0.91484, 0.93575, 0.92383, 0.9403, 0.9403, 0.9403, 0.9403, 0.8717, 0.8717, 0.8717, 0.8717, 1.00527, 1.01756, 1.05356, 1.05356, 1.05356, 1.05356, 1.05356, 1.24644, 0.95923, 1.01756, 1.01756, 1.01756, 1.01756, 0.96777, 1.05707, 0.96777, 0.96706, 0.91484, 0.96706, 0.91484, 0.96706, 0.91484, 0.85734, 0.92383, 0.85734, 0.92383, 0.85734, 0.92383, 0.85734, 0.92383, 0.97093, 1.0969, 0.97093, 1.05882, 0.75842, 0.9403, 0.75842, 0.9403, 0.75842, 0.9403, 0.75842, 0.9403, 0.75842, 0.9403, 0.88198, 1.05882, 0.88198, 1.05882, 0.88198, 1.05882, 1, 1, 0.9831, 1.01756, 0.9831, 1.01756, 0.95782, 0.8717, 0.95782, 0.8717, 0.95782, 0.8717, 0.95782, 1.09011, 0.95782, 0.8717, 0.84784, 1.11551, 0.71387, 1.09011, 1, 1, 0.99414, 0.84636, 1.09011, 1, 1, 0.84636, 1.0536, 0.84636, 0.94298, 0.84636, 1.23297, 1.03584, 1.01756, 1, 1, 1.03584, 1.01756, 1.00323, 1.03444, 1.01756, 0.96924, 1.05356, 0.96924, 1.05356, 0.96924, 1.05356, 0.93066, 0.98293, 0.82826, 1.04399, 1, 1, 0.82826, 1.04399, 0.79649, 0.84863, 0.79649, 0.84863, 0.79649, 0.84863, 0.79649, 0.84863, 1, 1, 0.85771, 1.17318, 0.85771, 1.21968, 0.95132, 1.01756, 0.95132, 1.01756, 0.95132, 1.01756, 0.95132, 1.01756, 0.95132, 1.01756, 0.95132, 1.01756, 0.98965, 1.00068, 0.8287, 0.96777, 0.8287, 0.93365, 0.9043, 0.93365, 0.9043, 0.93365, 0.9043, 1.08571, 0.96927, 0.96706, 0.91484, 0.86035, 0.93575, 0.96924, 0.95923, 1, 1, 0.85771, 1.21968, 1.11437, 1.11437, 0.93109, 0.91202, 0.60411, 0.84164, 0.55572, 1.01173, 0.97361, 0.81818, 0.81818, 0.96635, 0.78032, 0.72727, 0.92366, 0.98601, 1.03405, 0.77968, 1.09799, 1.2, 0.96706, 0.85944, 0.85638, 0.96491, 0.75842, 0.93365, 0.9831, 0.96924, 0.95782, 0.86969, 0.94152, 1.07796, 1.03584, 0.78437, 0.96924, 0.98715, 0.83968, 0.83491, 0.85771, 0.8287, 0.94492, 0.88433, 0.9287, 1.0098, 0.95782, 0.8287, 1.0625, 0.98248, 1.03424, 1.2, 1.01071, 1.0625, 0.95246, 1.03809, 1.04912, 0.98248, 1.00221, 1.03424, 1.05443, 1.2, 1.04785, 0.99609, 1.00169, 1.05176, 0.99346, 1.05356, 0.9087, 1.03004, 0.95542, 0.93117, 1.23362, 1.01071, 1.07831, 1.02512, 1.05205, 1.03502, 1.2, 1.01071, 1.05356, 1.01071, 1.03502, 0.75842, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.03719, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9403, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.04021, 1, 1, 1, 1, 1, 1, 0.98965, 1.00068, 0.98965, 1.00068, 0.98965, 1.00068, 0.8287, 0.96777, 1, 1.20088, 0.89903, 1, 1, 0.75155, 1.03077, 1.03077, 1.03077, 1.03077, 1.13196, 1.13196, 1.13196, 0.67428, 0.67428, 1.16039, 0.73291, 1.20996, 1.22135, 1.06483, 0.94868, 0.94868, 0.95996, 1.24633, 1, 1.07497, 0.87796, 0.96927, 1.01518, 0.96927, 1, 1, 1, 0.77295, 1, 1, 1.10539, 1.10539, 1.11358, 1.06967, 0.86279, 0.94434, 0.86279, 0.94434, 0.86182, 1, 1, 1.083, 1, 0.91578, 0.86507, 1.1714, 1.18416, 1.14589, 0.69825, 0.97622, 1.9697, 1.24822, 1.24822, 1.17238, 1.24822, 1.24822, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.42603, 1, 0.99862, 0.99862, 1, 0.87025, 0.87025, 0.87025, 0.87025, 1.18083, 1.42603, 1, 1.42603, 1.42603, 0.99862, 1, 1, 1, 1, 1, 1.2886, 1.04315, 1.15296, 1.34163, 1, 1, 1, 1.10938, 1.10938, 1, 1, 1, 1.05425, 1.09971, 1.09971, 1.09971, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];\nconst SegoeuiRegularMetrics = {\n  lineHeight: 1.33008,\n  lineGap: 0\n};\n\n;// CONCATENATED MODULE: ./src/core/xfa_fonts.js\n\n\n\n\n\n\n\n\nconst getXFAFontMap = getLookupTableFactory(function (t) {\n  t[\"MyriadPro-Regular\"] = t[\"PdfJS-Fallback-Regular\"] = {\n    name: \"LiberationSans-Regular\",\n    factors: MyriadProRegularFactors,\n    baseWidths: LiberationSansRegularWidths,\n    baseMapping: LiberationSansRegularMapping,\n    metrics: MyriadProRegularMetrics\n  };\n  t[\"MyriadPro-Bold\"] = t[\"PdfJS-Fallback-Bold\"] = {\n    name: \"LiberationSans-Bold\",\n    factors: MyriadProBoldFactors,\n    baseWidths: LiberationSansBoldWidths,\n    baseMapping: LiberationSansBoldMapping,\n    metrics: MyriadProBoldMetrics\n  };\n  t[\"MyriadPro-It\"] = t[\"MyriadPro-Italic\"] = t[\"PdfJS-Fallback-Italic\"] = {\n    name: \"LiberationSans-Italic\",\n    factors: MyriadProItalicFactors,\n    baseWidths: LiberationSansItalicWidths,\n    baseMapping: LiberationSansItalicMapping,\n    metrics: MyriadProItalicMetrics\n  };\n  t[\"MyriadPro-BoldIt\"] = t[\"MyriadPro-BoldItalic\"] = t[\"PdfJS-Fallback-BoldItalic\"] = {\n    name: \"LiberationSans-BoldItalic\",\n    factors: MyriadProBoldItalicFactors,\n    baseWidths: LiberationSansBoldItalicWidths,\n    baseMapping: LiberationSansBoldItalicMapping,\n    metrics: MyriadProBoldItalicMetrics\n  };\n  t.ArialMT = t.Arial = t[\"Arial-Regular\"] = {\n    name: \"LiberationSans-Regular\",\n    baseWidths: LiberationSansRegularWidths,\n    baseMapping: LiberationSansRegularMapping\n  };\n  t[\"Arial-BoldMT\"] = t[\"Arial-Bold\"] = {\n    name: \"LiberationSans-Bold\",\n    baseWidths: LiberationSansBoldWidths,\n    baseMapping: LiberationSansBoldMapping\n  };\n  t[\"Arial-ItalicMT\"] = t[\"Arial-Italic\"] = {\n    name: \"LiberationSans-Italic\",\n    baseWidths: LiberationSansItalicWidths,\n    baseMapping: LiberationSansItalicMapping\n  };\n  t[\"Arial-BoldItalicMT\"] = t[\"Arial-BoldItalic\"] = {\n    name: \"LiberationSans-BoldItalic\",\n    baseWidths: LiberationSansBoldItalicWidths,\n    baseMapping: LiberationSansBoldItalicMapping\n  };\n  t[\"Calibri-Regular\"] = {\n    name: \"LiberationSans-Regular\",\n    factors: CalibriRegularFactors,\n    baseWidths: LiberationSansRegularWidths,\n    baseMapping: LiberationSansRegularMapping,\n    metrics: CalibriRegularMetrics\n  };\n  t[\"Calibri-Bold\"] = {\n    name: \"LiberationSans-Bold\",\n    factors: CalibriBoldFactors,\n    baseWidths: LiberationSansBoldWidths,\n    baseMapping: LiberationSansBoldMapping,\n    metrics: CalibriBoldMetrics\n  };\n  t[\"Calibri-Italic\"] = {\n    name: \"LiberationSans-Italic\",\n    factors: CalibriItalicFactors,\n    baseWidths: LiberationSansItalicWidths,\n    baseMapping: LiberationSansItalicMapping,\n    metrics: CalibriItalicMetrics\n  };\n  t[\"Calibri-BoldItalic\"] = {\n    name: \"LiberationSans-BoldItalic\",\n    factors: CalibriBoldItalicFactors,\n    baseWidths: LiberationSansBoldItalicWidths,\n    baseMapping: LiberationSansBoldItalicMapping,\n    metrics: CalibriBoldItalicMetrics\n  };\n  t[\"Segoeui-Regular\"] = {\n    name: \"LiberationSans-Regular\",\n    factors: SegoeuiRegularFactors,\n    baseWidths: LiberationSansRegularWidths,\n    baseMapping: LiberationSansRegularMapping,\n    metrics: SegoeuiRegularMetrics\n  };\n  t[\"Segoeui-Bold\"] = {\n    name: \"LiberationSans-Bold\",\n    factors: SegoeuiBoldFactors,\n    baseWidths: LiberationSansBoldWidths,\n    baseMapping: LiberationSansBoldMapping,\n    metrics: SegoeuiBoldMetrics\n  };\n  t[\"Segoeui-Italic\"] = {\n    name: \"LiberationSans-Italic\",\n    factors: SegoeuiItalicFactors,\n    baseWidths: LiberationSansItalicWidths,\n    baseMapping: LiberationSansItalicMapping,\n    metrics: SegoeuiItalicMetrics\n  };\n  t[\"Segoeui-BoldItalic\"] = {\n    name: \"LiberationSans-BoldItalic\",\n    factors: SegoeuiBoldItalicFactors,\n    baseWidths: LiberationSansBoldItalicWidths,\n    baseMapping: LiberationSansBoldItalicMapping,\n    metrics: SegoeuiBoldItalicMetrics\n  };\n  t[\"Helvetica-Regular\"] = t.Helvetica = {\n    name: \"LiberationSans-Regular\",\n    factors: HelveticaRegularFactors,\n    baseWidths: LiberationSansRegularWidths,\n    baseMapping: LiberationSansRegularMapping,\n    metrics: HelveticaRegularMetrics\n  };\n  t[\"Helvetica-Bold\"] = {\n    name: \"LiberationSans-Bold\",\n    factors: HelveticaBoldFactors,\n    baseWidths: LiberationSansBoldWidths,\n    baseMapping: LiberationSansBoldMapping,\n    metrics: HelveticaBoldMetrics\n  };\n  t[\"Helvetica-Italic\"] = {\n    name: \"LiberationSans-Italic\",\n    factors: HelveticaItalicFactors,\n    baseWidths: LiberationSansItalicWidths,\n    baseMapping: LiberationSansItalicMapping,\n    metrics: HelveticaItalicMetrics\n  };\n  t[\"Helvetica-BoldItalic\"] = {\n    name: \"LiberationSans-BoldItalic\",\n    factors: HelveticaBoldItalicFactors,\n    baseWidths: LiberationSansBoldItalicWidths,\n    baseMapping: LiberationSansBoldItalicMapping,\n    metrics: HelveticaBoldItalicMetrics\n  };\n});\nfunction getXfaFontName(name) {\n  const fontName = normalizeFontName(name);\n  const fontMap = getXFAFontMap();\n  return fontMap[fontName];\n}\nfunction getXfaFontWidths(name) {\n  const info = getXfaFontName(name);\n  if (!info) {\n    return null;\n  }\n  const {\n    baseWidths,\n    baseMapping,\n    factors\n  } = info;\n  const rescaledBaseWidths = !factors ? baseWidths : baseWidths.map((w, i) => w * factors[i]);\n  let currentCode = -2;\n  let currentArray;\n  const newWidths = [];\n  for (const [unicode, glyphIndex] of baseMapping.map((charUnicode, index) => [charUnicode, index]).sort(([unicode1], [unicode2]) => unicode1 - unicode2)) {\n    if (unicode === -1) {\n      continue;\n    }\n    if (unicode === currentCode + 1) {\n      currentArray.push(rescaledBaseWidths[glyphIndex]);\n      currentCode += 1;\n    } else {\n      currentCode = unicode;\n      currentArray = [rescaledBaseWidths[glyphIndex]];\n      newWidths.push(unicode, currentArray);\n    }\n  }\n  return newWidths;\n}\nfunction getXfaFontDict(name) {\n  const widths = getXfaFontWidths(name);\n  const dict = new Dict(null);\n  dict.set(\"BaseFont\", Name.get(name));\n  dict.set(\"Type\", Name.get(\"Font\"));\n  dict.set(\"Subtype\", Name.get(\"CIDFontType2\"));\n  dict.set(\"Encoding\", Name.get(\"Identity-H\"));\n  dict.set(\"CIDToGIDMap\", Name.get(\"Identity\"));\n  dict.set(\"W\", widths);\n  dict.set(\"FirstChar\", widths[0]);\n  dict.set(\"LastChar\", widths.at(-2) + widths.at(-1).length - 1);\n  const descriptor = new Dict(null);\n  dict.set(\"FontDescriptor\", descriptor);\n  const systemInfo = new Dict(null);\n  systemInfo.set(\"Ordering\", \"Identity\");\n  systemInfo.set(\"Registry\", \"Adobe\");\n  systemInfo.set(\"Supplement\", 0);\n  dict.set(\"CIDSystemInfo\", systemInfo);\n  return dict;\n}\n\n;// CONCATENATED MODULE: ./src/core/ps_parser.js\n\n\n\nclass PostScriptParser {\n  constructor(lexer) {\n    this.lexer = lexer;\n    this.operators = [];\n    this.token = null;\n    this.prev = null;\n  }\n  nextToken() {\n    this.prev = this.token;\n    this.token = this.lexer.getToken();\n  }\n  accept(type) {\n    if (this.token.type === type) {\n      this.nextToken();\n      return true;\n    }\n    return false;\n  }\n  expect(type) {\n    if (this.accept(type)) {\n      return true;\n    }\n    throw new FormatError(`Unexpected symbol: found ${this.token.type} expected ${type}.`);\n  }\n  parse() {\n    this.nextToken();\n    this.expect(PostScriptTokenTypes.LBRACE);\n    this.parseBlock();\n    this.expect(PostScriptTokenTypes.RBRACE);\n    return this.operators;\n  }\n  parseBlock() {\n    while (true) {\n      if (this.accept(PostScriptTokenTypes.NUMBER)) {\n        this.operators.push(this.prev.value);\n      } else if (this.accept(PostScriptTokenTypes.OPERATOR)) {\n        this.operators.push(this.prev.value);\n      } else if (this.accept(PostScriptTokenTypes.LBRACE)) {\n        this.parseCondition();\n      } else {\n        return;\n      }\n    }\n  }\n  parseCondition() {\n    const conditionLocation = this.operators.length;\n    this.operators.push(null, null);\n    this.parseBlock();\n    this.expect(PostScriptTokenTypes.RBRACE);\n    if (this.accept(PostScriptTokenTypes.IF)) {\n      this.operators[conditionLocation] = this.operators.length;\n      this.operators[conditionLocation + 1] = \"jz\";\n    } else if (this.accept(PostScriptTokenTypes.LBRACE)) {\n      const jumpLocation = this.operators.length;\n      this.operators.push(null, null);\n      const endOfTrue = this.operators.length;\n      this.parseBlock();\n      this.expect(PostScriptTokenTypes.RBRACE);\n      this.expect(PostScriptTokenTypes.IFELSE);\n      this.operators[jumpLocation] = this.operators.length;\n      this.operators[jumpLocation + 1] = \"j\";\n      this.operators[conditionLocation] = endOfTrue;\n      this.operators[conditionLocation + 1] = \"jz\";\n    } else {\n      throw new FormatError(\"PS Function: error parsing conditional.\");\n    }\n  }\n}\nconst PostScriptTokenTypes = {\n  LBRACE: 0,\n  RBRACE: 1,\n  NUMBER: 2,\n  OPERATOR: 3,\n  IF: 4,\n  IFELSE: 5\n};\nclass PostScriptToken {\n  static get opCache() {\n    return shadow(this, \"opCache\", Object.create(null));\n  }\n  constructor(type, value) {\n    this.type = type;\n    this.value = value;\n  }\n  static getOperator(op) {\n    return PostScriptToken.opCache[op] ||= new PostScriptToken(PostScriptTokenTypes.OPERATOR, op);\n  }\n  static get LBRACE() {\n    return shadow(this, \"LBRACE\", new PostScriptToken(PostScriptTokenTypes.LBRACE, \"{\"));\n  }\n  static get RBRACE() {\n    return shadow(this, \"RBRACE\", new PostScriptToken(PostScriptTokenTypes.RBRACE, \"}\"));\n  }\n  static get IF() {\n    return shadow(this, \"IF\", new PostScriptToken(PostScriptTokenTypes.IF, \"IF\"));\n  }\n  static get IFELSE() {\n    return shadow(this, \"IFELSE\", new PostScriptToken(PostScriptTokenTypes.IFELSE, \"IFELSE\"));\n  }\n}\nclass PostScriptLexer {\n  constructor(stream) {\n    this.stream = stream;\n    this.nextChar();\n    this.strBuf = [];\n  }\n  nextChar() {\n    return this.currentChar = this.stream.getByte();\n  }\n  getToken() {\n    let comment = false;\n    let ch = this.currentChar;\n    while (true) {\n      if (ch < 0) {\n        return EOF;\n      }\n      if (comment) {\n        if (ch === 0x0a || ch === 0x0d) {\n          comment = false;\n        }\n      } else if (ch === 0x25) {\n        comment = true;\n      } else if (!isWhiteSpace(ch)) {\n        break;\n      }\n      ch = this.nextChar();\n    }\n    switch (ch | 0) {\n      case 0x30:\n      case 0x31:\n      case 0x32:\n      case 0x33:\n      case 0x34:\n      case 0x35:\n      case 0x36:\n      case 0x37:\n      case 0x38:\n      case 0x39:\n      case 0x2b:\n      case 0x2d:\n      case 0x2e:\n        return new PostScriptToken(PostScriptTokenTypes.NUMBER, this.getNumber());\n      case 0x7b:\n        this.nextChar();\n        return PostScriptToken.LBRACE;\n      case 0x7d:\n        this.nextChar();\n        return PostScriptToken.RBRACE;\n    }\n    const strBuf = this.strBuf;\n    strBuf.length = 0;\n    strBuf[0] = String.fromCharCode(ch);\n    while ((ch = this.nextChar()) >= 0 && (ch >= 0x41 && ch <= 0x5a || ch >= 0x61 && ch <= 0x7a)) {\n      strBuf.push(String.fromCharCode(ch));\n    }\n    const str = strBuf.join(\"\");\n    switch (str.toLowerCase()) {\n      case \"if\":\n        return PostScriptToken.IF;\n      case \"ifelse\":\n        return PostScriptToken.IFELSE;\n      default:\n        return PostScriptToken.getOperator(str);\n    }\n  }\n  getNumber() {\n    let ch = this.currentChar;\n    const strBuf = this.strBuf;\n    strBuf.length = 0;\n    strBuf[0] = String.fromCharCode(ch);\n    while ((ch = this.nextChar()) >= 0) {\n      if (ch >= 0x30 && ch <= 0x39 || ch === 0x2d || ch === 0x2e) {\n        strBuf.push(String.fromCharCode(ch));\n      } else {\n        break;\n      }\n    }\n    const value = parseFloat(strBuf.join(\"\"));\n    if (isNaN(value)) {\n      throw new FormatError(`Invalid floating point number: ${value}`);\n    }\n    return value;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/image_utils.js\n\n\nclass BaseLocalCache {\n  constructor(options) {\n    if (this.constructor === BaseLocalCache) {\n      unreachable(\"Cannot initialize BaseLocalCache.\");\n    }\n    this._onlyRefs = options?.onlyRefs === true;\n    if (!this._onlyRefs) {\n      this._nameRefMap = new Map();\n      this._imageMap = new Map();\n    }\n    this._imageCache = new RefSetCache();\n  }\n  getByName(name) {\n    if (this._onlyRefs) {\n      unreachable(\"Should not call `getByName` method.\");\n    }\n    const ref = this._nameRefMap.get(name);\n    if (ref) {\n      return this.getByRef(ref);\n    }\n    return this._imageMap.get(name) || null;\n  }\n  getByRef(ref) {\n    return this._imageCache.get(ref) || null;\n  }\n  set(name, ref, data) {\n    unreachable(\"Abstract method `set` called.\");\n  }\n}\nclass LocalImageCache extends BaseLocalCache {\n  set(name, ref = null, data) {\n    if (typeof name !== \"string\") {\n      throw new Error('LocalImageCache.set - expected \"name\" argument.');\n    }\n    if (ref) {\n      if (this._imageCache.has(ref)) {\n        return;\n      }\n      this._nameRefMap.set(name, ref);\n      this._imageCache.put(ref, data);\n      return;\n    }\n    if (this._imageMap.has(name)) {\n      return;\n    }\n    this._imageMap.set(name, data);\n  }\n}\nclass LocalColorSpaceCache extends BaseLocalCache {\n  set(name = null, ref = null, data) {\n    if (typeof name !== \"string\" && !ref) {\n      throw new Error('LocalColorSpaceCache.set - expected \"name\" and/or \"ref\" argument.');\n    }\n    if (ref) {\n      if (this._imageCache.has(ref)) {\n        return;\n      }\n      if (name !== null) {\n        this._nameRefMap.set(name, ref);\n      }\n      this._imageCache.put(ref, data);\n      return;\n    }\n    if (this._imageMap.has(name)) {\n      return;\n    }\n    this._imageMap.set(name, data);\n  }\n}\nclass LocalFunctionCache extends BaseLocalCache {\n  constructor(options) {\n    super({\n      onlyRefs: true\n    });\n  }\n  set(name = null, ref, data) {\n    if (!ref) {\n      throw new Error('LocalFunctionCache.set - expected \"ref\" argument.');\n    }\n    if (this._imageCache.has(ref)) {\n      return;\n    }\n    this._imageCache.put(ref, data);\n  }\n}\nclass LocalGStateCache extends BaseLocalCache {\n  set(name, ref = null, data) {\n    if (typeof name !== \"string\") {\n      throw new Error('LocalGStateCache.set - expected \"name\" argument.');\n    }\n    if (ref) {\n      if (this._imageCache.has(ref)) {\n        return;\n      }\n      this._nameRefMap.set(name, ref);\n      this._imageCache.put(ref, data);\n      return;\n    }\n    if (this._imageMap.has(name)) {\n      return;\n    }\n    this._imageMap.set(name, data);\n  }\n}\nclass LocalTilingPatternCache extends BaseLocalCache {\n  constructor(options) {\n    super({\n      onlyRefs: true\n    });\n  }\n  set(name = null, ref, data) {\n    if (!ref) {\n      throw new Error('LocalTilingPatternCache.set - expected \"ref\" argument.');\n    }\n    if (this._imageCache.has(ref)) {\n      return;\n    }\n    this._imageCache.put(ref, data);\n  }\n}\nclass RegionalImageCache extends BaseLocalCache {\n  constructor(options) {\n    super({\n      onlyRefs: true\n    });\n  }\n  set(name = null, ref, data) {\n    if (!ref) {\n      throw new Error('RegionalImageCache.set - expected \"ref\" argument.');\n    }\n    if (this._imageCache.has(ref)) {\n      return;\n    }\n    this._imageCache.put(ref, data);\n  }\n}\nclass GlobalImageCache {\n  static NUM_PAGES_THRESHOLD = 2;\n  static MIN_IMAGES_TO_CACHE = 10;\n  static MAX_BYTE_SIZE = 5 * MAX_IMAGE_SIZE_TO_CACHE;\n  constructor() {\n    this._refCache = new RefSetCache();\n    this._imageCache = new RefSetCache();\n  }\n  get _byteSize() {\n    let byteSize = 0;\n    for (const imageData of this._imageCache) {\n      byteSize += imageData.byteSize;\n    }\n    return byteSize;\n  }\n  get _cacheLimitReached() {\n    if (this._imageCache.size < GlobalImageCache.MIN_IMAGES_TO_CACHE) {\n      return false;\n    }\n    if (this._byteSize < GlobalImageCache.MAX_BYTE_SIZE) {\n      return false;\n    }\n    return true;\n  }\n  shouldCache(ref, pageIndex) {\n    let pageIndexSet = this._refCache.get(ref);\n    if (!pageIndexSet) {\n      pageIndexSet = new Set();\n      this._refCache.put(ref, pageIndexSet);\n    }\n    pageIndexSet.add(pageIndex);\n    if (pageIndexSet.size < GlobalImageCache.NUM_PAGES_THRESHOLD) {\n      return false;\n    }\n    if (!this._imageCache.has(ref) && this._cacheLimitReached) {\n      return false;\n    }\n    return true;\n  }\n  addByteSize(ref, byteSize) {\n    const imageData = this._imageCache.get(ref);\n    if (!imageData) {\n      return;\n    }\n    if (imageData.byteSize) {\n      return;\n    }\n    imageData.byteSize = byteSize;\n  }\n  getData(ref, pageIndex) {\n    const pageIndexSet = this._refCache.get(ref);\n    if (!pageIndexSet) {\n      return null;\n    }\n    if (pageIndexSet.size < GlobalImageCache.NUM_PAGES_THRESHOLD) {\n      return null;\n    }\n    const imageData = this._imageCache.get(ref);\n    if (!imageData) {\n      return null;\n    }\n    pageIndexSet.add(pageIndex);\n    return imageData;\n  }\n  setData(ref, data) {\n    if (!this._refCache.has(ref)) {\n      throw new Error('GlobalImageCache.setData - expected \"shouldCache\" to have been called.');\n    }\n    if (this._imageCache.has(ref)) {\n      return;\n    }\n    if (this._cacheLimitReached) {\n      warn(\"GlobalImageCache.setData - cache limit reached.\");\n      return;\n    }\n    this._imageCache.put(ref, data);\n  }\n  clear(onlyData = false) {\n    if (!onlyData) {\n      this._refCache.clear();\n    }\n    this._imageCache.clear();\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/function.js\n\n\n\n\n\n\nclass PDFFunctionFactory {\n  constructor({\n    xref,\n    isEvalSupported = true\n  }) {\n    this.xref = xref;\n    this.isEvalSupported = isEvalSupported !== false;\n  }\n  create(fn) {\n    const cachedFunction = this.getCached(fn);\n    if (cachedFunction) {\n      return cachedFunction;\n    }\n    const parsedFunction = PDFFunction.parse({\n      xref: this.xref,\n      isEvalSupported: this.isEvalSupported,\n      fn: fn instanceof Ref ? this.xref.fetch(fn) : fn\n    });\n    this._cache(fn, parsedFunction);\n    return parsedFunction;\n  }\n  createFromArray(fnObj) {\n    const cachedFunction = this.getCached(fnObj);\n    if (cachedFunction) {\n      return cachedFunction;\n    }\n    const parsedFunction = PDFFunction.parseArray({\n      xref: this.xref,\n      isEvalSupported: this.isEvalSupported,\n      fnObj: fnObj instanceof Ref ? this.xref.fetch(fnObj) : fnObj\n    });\n    this._cache(fnObj, parsedFunction);\n    return parsedFunction;\n  }\n  getCached(cacheKey) {\n    let fnRef;\n    if (cacheKey instanceof Ref) {\n      fnRef = cacheKey;\n    } else if (cacheKey instanceof Dict) {\n      fnRef = cacheKey.objId;\n    } else if (cacheKey instanceof BaseStream) {\n      fnRef = cacheKey.dict?.objId;\n    }\n    if (fnRef) {\n      const localFunction = this._localFunctionCache.getByRef(fnRef);\n      if (localFunction) {\n        return localFunction;\n      }\n    }\n    return null;\n  }\n  _cache(cacheKey, parsedFunction) {\n    if (!parsedFunction) {\n      throw new Error('PDFFunctionFactory._cache - expected \"parsedFunction\" argument.');\n    }\n    let fnRef;\n    if (cacheKey instanceof Ref) {\n      fnRef = cacheKey;\n    } else if (cacheKey instanceof Dict) {\n      fnRef = cacheKey.objId;\n    } else if (cacheKey instanceof BaseStream) {\n      fnRef = cacheKey.dict?.objId;\n    }\n    if (fnRef) {\n      this._localFunctionCache.set(null, fnRef, parsedFunction);\n    }\n  }\n  get _localFunctionCache() {\n    return shadow(this, \"_localFunctionCache\", new LocalFunctionCache());\n  }\n}\nfunction toNumberArray(arr) {\n  if (!Array.isArray(arr)) {\n    return null;\n  }\n  if (!isNumberArray(arr, null)) {\n    return arr.map(x => +x);\n  }\n  return arr;\n}\nclass PDFFunction {\n  static getSampleArray(size, outputSize, bps, stream) {\n    let i, ii;\n    let length = 1;\n    for (i = 0, ii = size.length; i < ii; i++) {\n      length *= size[i];\n    }\n    length *= outputSize;\n    const array = new Array(length);\n    let codeSize = 0;\n    let codeBuf = 0;\n    const sampleMul = 1.0 / (2.0 ** bps - 1);\n    const strBytes = stream.getBytes((length * bps + 7) / 8);\n    let strIdx = 0;\n    for (i = 0; i < length; i++) {\n      while (codeSize < bps) {\n        codeBuf <<= 8;\n        codeBuf |= strBytes[strIdx++];\n        codeSize += 8;\n      }\n      codeSize -= bps;\n      array[i] = (codeBuf >> codeSize) * sampleMul;\n      codeBuf &= (1 << codeSize) - 1;\n    }\n    return array;\n  }\n  static parse({\n    xref,\n    isEvalSupported,\n    fn\n  }) {\n    const dict = fn.dict || fn;\n    const typeNum = dict.get(\"FunctionType\");\n    switch (typeNum) {\n      case 0:\n        return this.constructSampled({\n          xref,\n          isEvalSupported,\n          fn,\n          dict\n        });\n      case 1:\n        break;\n      case 2:\n        return this.constructInterpolated({\n          xref,\n          isEvalSupported,\n          dict\n        });\n      case 3:\n        return this.constructStiched({\n          xref,\n          isEvalSupported,\n          dict\n        });\n      case 4:\n        return this.constructPostScript({\n          xref,\n          isEvalSupported,\n          fn,\n          dict\n        });\n    }\n    throw new FormatError(\"Unknown type of function\");\n  }\n  static parseArray({\n    xref,\n    isEvalSupported,\n    fnObj\n  }) {\n    if (!Array.isArray(fnObj)) {\n      return this.parse({\n        xref,\n        isEvalSupported,\n        fn: fnObj\n      });\n    }\n    const fnArray = [];\n    for (const fn of fnObj) {\n      fnArray.push(this.parse({\n        xref,\n        isEvalSupported,\n        fn: xref.fetchIfRef(fn)\n      }));\n    }\n    return function (src, srcOffset, dest, destOffset) {\n      for (let i = 0, ii = fnArray.length; i < ii; i++) {\n        fnArray[i](src, srcOffset, dest, destOffset + i);\n      }\n    };\n  }\n  static constructSampled({\n    xref,\n    isEvalSupported,\n    fn,\n    dict\n  }) {\n    function toMultiArray(arr) {\n      const inputLength = arr.length;\n      const out = [];\n      let index = 0;\n      for (let i = 0; i < inputLength; i += 2) {\n        out[index++] = [arr[i], arr[i + 1]];\n      }\n      return out;\n    }\n    function interpolate(x, xmin, xmax, ymin, ymax) {\n      return ymin + (x - xmin) * ((ymax - ymin) / (xmax - xmin));\n    }\n    let domain = toNumberArray(dict.getArray(\"Domain\"));\n    let range = toNumberArray(dict.getArray(\"Range\"));\n    if (!domain || !range) {\n      throw new FormatError(\"No domain or range\");\n    }\n    const inputSize = domain.length / 2;\n    const outputSize = range.length / 2;\n    domain = toMultiArray(domain);\n    range = toMultiArray(range);\n    const size = toNumberArray(dict.getArray(\"Size\"));\n    const bps = dict.get(\"BitsPerSample\");\n    const order = dict.get(\"Order\") || 1;\n    if (order !== 1) {\n      info(\"No support for cubic spline interpolation: \" + order);\n    }\n    let encode = toNumberArray(dict.getArray(\"Encode\"));\n    if (!encode) {\n      encode = [];\n      for (let i = 0; i < inputSize; ++i) {\n        encode.push([0, size[i] - 1]);\n      }\n    } else {\n      encode = toMultiArray(encode);\n    }\n    let decode = toNumberArray(dict.getArray(\"Decode\"));\n    decode = !decode ? range : toMultiArray(decode);\n    const samples = this.getSampleArray(size, outputSize, bps, fn);\n    return function constructSampledFn(src, srcOffset, dest, destOffset) {\n      const cubeVertices = 1 << inputSize;\n      const cubeN = new Float64Array(cubeVertices);\n      const cubeVertex = new Uint32Array(cubeVertices);\n      let i, j;\n      for (j = 0; j < cubeVertices; j++) {\n        cubeN[j] = 1;\n      }\n      let k = outputSize,\n        pos = 1;\n      for (i = 0; i < inputSize; ++i) {\n        const domain_2i = domain[i][0];\n        const domain_2i_1 = domain[i][1];\n        const xi = Math.min(Math.max(src[srcOffset + i], domain_2i), domain_2i_1);\n        let e = interpolate(xi, domain_2i, domain_2i_1, encode[i][0], encode[i][1]);\n        const size_i = size[i];\n        e = Math.min(Math.max(e, 0), size_i - 1);\n        const e0 = e < size_i - 1 ? Math.floor(e) : e - 1;\n        const n0 = e0 + 1 - e;\n        const n1 = e - e0;\n        const offset0 = e0 * k;\n        const offset1 = offset0 + k;\n        for (j = 0; j < cubeVertices; j++) {\n          if (j & pos) {\n            cubeN[j] *= n1;\n            cubeVertex[j] += offset1;\n          } else {\n            cubeN[j] *= n0;\n            cubeVertex[j] += offset0;\n          }\n        }\n        k *= size_i;\n        pos <<= 1;\n      }\n      for (j = 0; j < outputSize; ++j) {\n        let rj = 0;\n        for (i = 0; i < cubeVertices; i++) {\n          rj += samples[cubeVertex[i] + j] * cubeN[i];\n        }\n        rj = interpolate(rj, 0, 1, decode[j][0], decode[j][1]);\n        dest[destOffset + j] = Math.min(Math.max(rj, range[j][0]), range[j][1]);\n      }\n    };\n  }\n  static constructInterpolated({\n    xref,\n    isEvalSupported,\n    dict\n  }) {\n    const c0 = toNumberArray(dict.getArray(\"C0\")) || [0];\n    const c1 = toNumberArray(dict.getArray(\"C1\")) || [1];\n    const n = dict.get(\"N\");\n    const diff = [];\n    for (let i = 0, ii = c0.length; i < ii; ++i) {\n      diff.push(c1[i] - c0[i]);\n    }\n    const length = diff.length;\n    return function constructInterpolatedFn(src, srcOffset, dest, destOffset) {\n      const x = n === 1 ? src[srcOffset] : src[srcOffset] ** n;\n      for (let j = 0; j < length; ++j) {\n        dest[destOffset + j] = c0[j] + x * diff[j];\n      }\n    };\n  }\n  static constructStiched({\n    xref,\n    isEvalSupported,\n    dict\n  }) {\n    const domain = toNumberArray(dict.getArray(\"Domain\"));\n    if (!domain) {\n      throw new FormatError(\"No domain\");\n    }\n    const inputSize = domain.length / 2;\n    if (inputSize !== 1) {\n      throw new FormatError(\"Bad domain for stiched function\");\n    }\n    const fns = [];\n    for (const fn of dict.get(\"Functions\")) {\n      fns.push(this.parse({\n        xref,\n        isEvalSupported,\n        fn: xref.fetchIfRef(fn)\n      }));\n    }\n    const bounds = toNumberArray(dict.getArray(\"Bounds\"));\n    const encode = toNumberArray(dict.getArray(\"Encode\"));\n    const tmpBuf = new Float32Array(1);\n    return function constructStichedFn(src, srcOffset, dest, destOffset) {\n      const clip = function constructStichedFromIRClip(v, min, max) {\n        if (v > max) {\n          v = max;\n        } else if (v < min) {\n          v = min;\n        }\n        return v;\n      };\n      const v = clip(src[srcOffset], domain[0], domain[1]);\n      const length = bounds.length;\n      let i;\n      for (i = 0; i < length; ++i) {\n        if (v < bounds[i]) {\n          break;\n        }\n      }\n      let dmin = domain[0];\n      if (i > 0) {\n        dmin = bounds[i - 1];\n      }\n      let dmax = domain[1];\n      if (i < bounds.length) {\n        dmax = bounds[i];\n      }\n      const rmin = encode[2 * i];\n      const rmax = encode[2 * i + 1];\n      tmpBuf[0] = dmin === dmax ? rmin : rmin + (v - dmin) * (rmax - rmin) / (dmax - dmin);\n      fns[i](tmpBuf, 0, dest, destOffset);\n    };\n  }\n  static constructPostScript({\n    xref,\n    isEvalSupported,\n    fn,\n    dict\n  }) {\n    const domain = toNumberArray(dict.getArray(\"Domain\"));\n    const range = toNumberArray(dict.getArray(\"Range\"));\n    if (!domain) {\n      throw new FormatError(\"No domain.\");\n    }\n    if (!range) {\n      throw new FormatError(\"No range.\");\n    }\n    const lexer = new PostScriptLexer(fn);\n    const parser = new PostScriptParser(lexer);\n    const code = parser.parse();\n    if (isEvalSupported && FeatureTest.isEvalSupported) {\n      const compiled = new PostScriptCompiler().compile(code, domain, range);\n      if (compiled) {\n        return new Function(\"src\", \"srcOffset\", \"dest\", \"destOffset\", compiled);\n      }\n    }\n    info(\"Unable to compile PS function\");\n    const numOutputs = range.length >> 1;\n    const numInputs = domain.length >> 1;\n    const evaluator = new PostScriptEvaluator(code);\n    const cache = Object.create(null);\n    const MAX_CACHE_SIZE = 2048 * 4;\n    let cache_available = MAX_CACHE_SIZE;\n    const tmpBuf = new Float32Array(numInputs);\n    return function constructPostScriptFn(src, srcOffset, dest, destOffset) {\n      let i, value;\n      let key = \"\";\n      const input = tmpBuf;\n      for (i = 0; i < numInputs; i++) {\n        value = src[srcOffset + i];\n        input[i] = value;\n        key += value + \"_\";\n      }\n      const cachedValue = cache[key];\n      if (cachedValue !== undefined) {\n        dest.set(cachedValue, destOffset);\n        return;\n      }\n      const output = new Float32Array(numOutputs);\n      const stack = evaluator.execute(input);\n      const stackIndex = stack.length - numOutputs;\n      for (i = 0; i < numOutputs; i++) {\n        value = stack[stackIndex + i];\n        let bound = range[i * 2];\n        if (value < bound) {\n          value = bound;\n        } else {\n          bound = range[i * 2 + 1];\n          if (value > bound) {\n            value = bound;\n          }\n        }\n        output[i] = value;\n      }\n      if (cache_available > 0) {\n        cache_available--;\n        cache[key] = output;\n      }\n      dest.set(output, destOffset);\n    };\n  }\n}\nfunction isPDFFunction(v) {\n  let fnDict;\n  if (v instanceof Dict) {\n    fnDict = v;\n  } else if (v instanceof BaseStream) {\n    fnDict = v.dict;\n  } else {\n    return false;\n  }\n  return fnDict.has(\"FunctionType\");\n}\nclass PostScriptStack {\n  static MAX_STACK_SIZE = 100;\n  constructor(initialStack) {\n    this.stack = initialStack ? Array.from(initialStack) : [];\n  }\n  push(value) {\n    if (this.stack.length >= PostScriptStack.MAX_STACK_SIZE) {\n      throw new Error(\"PostScript function stack overflow.\");\n    }\n    this.stack.push(value);\n  }\n  pop() {\n    if (this.stack.length <= 0) {\n      throw new Error(\"PostScript function stack underflow.\");\n    }\n    return this.stack.pop();\n  }\n  copy(n) {\n    if (this.stack.length + n >= PostScriptStack.MAX_STACK_SIZE) {\n      throw new Error(\"PostScript function stack overflow.\");\n    }\n    const stack = this.stack;\n    for (let i = stack.length - n, j = n - 1; j >= 0; j--, i++) {\n      stack.push(stack[i]);\n    }\n  }\n  index(n) {\n    this.push(this.stack[this.stack.length - n - 1]);\n  }\n  roll(n, p) {\n    const stack = this.stack;\n    const l = stack.length - n;\n    const r = stack.length - 1;\n    const c = l + (p - Math.floor(p / n) * n);\n    for (let i = l, j = r; i < j; i++, j--) {\n      const t = stack[i];\n      stack[i] = stack[j];\n      stack[j] = t;\n    }\n    for (let i = l, j = c - 1; i < j; i++, j--) {\n      const t = stack[i];\n      stack[i] = stack[j];\n      stack[j] = t;\n    }\n    for (let i = c, j = r; i < j; i++, j--) {\n      const t = stack[i];\n      stack[i] = stack[j];\n      stack[j] = t;\n    }\n  }\n}\nclass PostScriptEvaluator {\n  constructor(operators) {\n    this.operators = operators;\n  }\n  execute(initialStack) {\n    const stack = new PostScriptStack(initialStack);\n    let counter = 0;\n    const operators = this.operators;\n    const length = operators.length;\n    let operator, a, b;\n    while (counter < length) {\n      operator = operators[counter++];\n      if (typeof operator === \"number\") {\n        stack.push(operator);\n        continue;\n      }\n      switch (operator) {\n        case \"jz\":\n          b = stack.pop();\n          a = stack.pop();\n          if (!a) {\n            counter = b;\n          }\n          break;\n        case \"j\":\n          a = stack.pop();\n          counter = a;\n          break;\n        case \"abs\":\n          a = stack.pop();\n          stack.push(Math.abs(a));\n          break;\n        case \"add\":\n          b = stack.pop();\n          a = stack.pop();\n          stack.push(a + b);\n          break;\n        case \"and\":\n          b = stack.pop();\n          a = stack.pop();\n          if (typeof a === \"boolean\" && typeof b === \"boolean\") {\n            stack.push(a && b);\n          } else {\n            stack.push(a & b);\n          }\n          break;\n        case \"atan\":\n          b = stack.pop();\n          a = stack.pop();\n          a = Math.atan2(a, b) / Math.PI * 180;\n          if (a < 0) {\n            a += 360;\n          }\n          stack.push(a);\n          break;\n        case \"bitshift\":\n          b = stack.pop();\n          a = stack.pop();\n          if (a > 0) {\n            stack.push(a << b);\n          } else {\n            stack.push(a >> b);\n          }\n          break;\n        case \"ceiling\":\n          a = stack.pop();\n          stack.push(Math.ceil(a));\n          break;\n        case \"copy\":\n          a = stack.pop();\n          stack.copy(a);\n          break;\n        case \"cos\":\n          a = stack.pop();\n          stack.push(Math.cos(a % 360 / 180 * Math.PI));\n          break;\n        case \"cvi\":\n          a = stack.pop() | 0;\n          stack.push(a);\n          break;\n        case \"cvr\":\n          break;\n        case \"div\":\n          b = stack.pop();\n          a = stack.pop();\n          stack.push(a / b);\n          break;\n        case \"dup\":\n          stack.copy(1);\n          break;\n        case \"eq\":\n          b = stack.pop();\n          a = stack.pop();\n          stack.push(a === b);\n          break;\n        case \"exch\":\n          stack.roll(2, 1);\n          break;\n        case \"exp\":\n          b = stack.pop();\n          a = stack.pop();\n          stack.push(a ** b);\n          break;\n        case \"false\":\n          stack.push(false);\n          break;\n        case \"floor\":\n          a = stack.pop();\n          stack.push(Math.floor(a));\n          break;\n        case \"ge\":\n          b = stack.pop();\n          a = stack.pop();\n          stack.push(a >= b);\n          break;\n        case \"gt\":\n          b = stack.pop();\n          a = stack.pop();\n          stack.push(a > b);\n          break;\n        case \"idiv\":\n          b = stack.pop();\n          a = stack.pop();\n          stack.push(a / b | 0);\n          break;\n        case \"index\":\n          a = stack.pop();\n          stack.index(a);\n          break;\n        case \"le\":\n          b = stack.pop();\n          a = stack.pop();\n          stack.push(a <= b);\n          break;\n        case \"ln\":\n          a = stack.pop();\n          stack.push(Math.log(a));\n          break;\n        case \"log\":\n          a = stack.pop();\n          stack.push(Math.log10(a));\n          break;\n        case \"lt\":\n          b = stack.pop();\n          a = stack.pop();\n          stack.push(a < b);\n          break;\n        case \"mod\":\n          b = stack.pop();\n          a = stack.pop();\n          stack.push(a % b);\n          break;\n        case \"mul\":\n          b = stack.pop();\n          a = stack.pop();\n          stack.push(a * b);\n          break;\n        case \"ne\":\n          b = stack.pop();\n          a = stack.pop();\n          stack.push(a !== b);\n          break;\n        case \"neg\":\n          a = stack.pop();\n          stack.push(-a);\n          break;\n        case \"not\":\n          a = stack.pop();\n          if (typeof a === \"boolean\") {\n            stack.push(!a);\n          } else {\n            stack.push(~a);\n          }\n          break;\n        case \"or\":\n          b = stack.pop();\n          a = stack.pop();\n          if (typeof a === \"boolean\" && typeof b === \"boolean\") {\n            stack.push(a || b);\n          } else {\n            stack.push(a | b);\n          }\n          break;\n        case \"pop\":\n          stack.pop();\n          break;\n        case \"roll\":\n          b = stack.pop();\n          a = stack.pop();\n          stack.roll(a, b);\n          break;\n        case \"round\":\n          a = stack.pop();\n          stack.push(Math.round(a));\n          break;\n        case \"sin\":\n          a = stack.pop();\n          stack.push(Math.sin(a % 360 / 180 * Math.PI));\n          break;\n        case \"sqrt\":\n          a = stack.pop();\n          stack.push(Math.sqrt(a));\n          break;\n        case \"sub\":\n          b = stack.pop();\n          a = stack.pop();\n          stack.push(a - b);\n          break;\n        case \"true\":\n          stack.push(true);\n          break;\n        case \"truncate\":\n          a = stack.pop();\n          a = a < 0 ? Math.ceil(a) : Math.floor(a);\n          stack.push(a);\n          break;\n        case \"xor\":\n          b = stack.pop();\n          a = stack.pop();\n          if (typeof a === \"boolean\" && typeof b === \"boolean\") {\n            stack.push(a !== b);\n          } else {\n            stack.push(a ^ b);\n          }\n          break;\n        default:\n          throw new FormatError(`Unknown operator ${operator}`);\n      }\n    }\n    return stack.stack;\n  }\n}\nclass AstNode {\n  constructor(type) {\n    this.type = type;\n  }\n  visit(visitor) {\n    unreachable(\"abstract method\");\n  }\n}\nclass AstArgument extends AstNode {\n  constructor(index, min, max) {\n    super(\"args\");\n    this.index = index;\n    this.min = min;\n    this.max = max;\n  }\n  visit(visitor) {\n    visitor.visitArgument(this);\n  }\n}\nclass AstLiteral extends AstNode {\n  constructor(number) {\n    super(\"literal\");\n    this.number = number;\n    this.min = number;\n    this.max = number;\n  }\n  visit(visitor) {\n    visitor.visitLiteral(this);\n  }\n}\nclass AstBinaryOperation extends AstNode {\n  constructor(op, arg1, arg2, min, max) {\n    super(\"binary\");\n    this.op = op;\n    this.arg1 = arg1;\n    this.arg2 = arg2;\n    this.min = min;\n    this.max = max;\n  }\n  visit(visitor) {\n    visitor.visitBinaryOperation(this);\n  }\n}\nclass AstMin extends AstNode {\n  constructor(arg, max) {\n    super(\"max\");\n    this.arg = arg;\n    this.min = arg.min;\n    this.max = max;\n  }\n  visit(visitor) {\n    visitor.visitMin(this);\n  }\n}\nclass AstVariable extends AstNode {\n  constructor(index, min, max) {\n    super(\"var\");\n    this.index = index;\n    this.min = min;\n    this.max = max;\n  }\n  visit(visitor) {\n    visitor.visitVariable(this);\n  }\n}\nclass AstVariableDefinition extends AstNode {\n  constructor(variable, arg) {\n    super(\"definition\");\n    this.variable = variable;\n    this.arg = arg;\n  }\n  visit(visitor) {\n    visitor.visitVariableDefinition(this);\n  }\n}\nclass ExpressionBuilderVisitor {\n  constructor() {\n    this.parts = [];\n  }\n  visitArgument(arg) {\n    this.parts.push(\"Math.max(\", arg.min, \", Math.min(\", arg.max, \", src[srcOffset + \", arg.index, \"]))\");\n  }\n  visitVariable(variable) {\n    this.parts.push(\"v\", variable.index);\n  }\n  visitLiteral(literal) {\n    this.parts.push(literal.number);\n  }\n  visitBinaryOperation(operation) {\n    this.parts.push(\"(\");\n    operation.arg1.visit(this);\n    this.parts.push(\" \", operation.op, \" \");\n    operation.arg2.visit(this);\n    this.parts.push(\")\");\n  }\n  visitVariableDefinition(definition) {\n    this.parts.push(\"var \");\n    definition.variable.visit(this);\n    this.parts.push(\" = \");\n    definition.arg.visit(this);\n    this.parts.push(\";\");\n  }\n  visitMin(max) {\n    this.parts.push(\"Math.min(\");\n    max.arg.visit(this);\n    this.parts.push(\", \", max.max, \")\");\n  }\n  toString() {\n    return this.parts.join(\"\");\n  }\n}\nfunction buildAddOperation(num1, num2) {\n  if (num2.type === \"literal\" && num2.number === 0) {\n    return num1;\n  }\n  if (num1.type === \"literal\" && num1.number === 0) {\n    return num2;\n  }\n  if (num2.type === \"literal\" && num1.type === \"literal\") {\n    return new AstLiteral(num1.number + num2.number);\n  }\n  return new AstBinaryOperation(\"+\", num1, num2, num1.min + num2.min, num1.max + num2.max);\n}\nfunction buildMulOperation(num1, num2) {\n  if (num2.type === \"literal\") {\n    if (num2.number === 0) {\n      return new AstLiteral(0);\n    } else if (num2.number === 1) {\n      return num1;\n    } else if (num1.type === \"literal\") {\n      return new AstLiteral(num1.number * num2.number);\n    }\n  }\n  if (num1.type === \"literal\") {\n    if (num1.number === 0) {\n      return new AstLiteral(0);\n    } else if (num1.number === 1) {\n      return num2;\n    }\n  }\n  const min = Math.min(num1.min * num2.min, num1.min * num2.max, num1.max * num2.min, num1.max * num2.max);\n  const max = Math.max(num1.min * num2.min, num1.min * num2.max, num1.max * num2.min, num1.max * num2.max);\n  return new AstBinaryOperation(\"*\", num1, num2, min, max);\n}\nfunction buildSubOperation(num1, num2) {\n  if (num2.type === \"literal\") {\n    if (num2.number === 0) {\n      return num1;\n    } else if (num1.type === \"literal\") {\n      return new AstLiteral(num1.number - num2.number);\n    }\n  }\n  if (num2.type === \"binary\" && num2.op === \"-\" && num1.type === \"literal\" && num1.number === 1 && num2.arg1.type === \"literal\" && num2.arg1.number === 1) {\n    return num2.arg2;\n  }\n  return new AstBinaryOperation(\"-\", num1, num2, num1.min - num2.max, num1.max - num2.min);\n}\nfunction buildMinOperation(num1, max) {\n  if (num1.min >= max) {\n    return new AstLiteral(max);\n  } else if (num1.max <= max) {\n    return num1;\n  }\n  return new AstMin(num1, max);\n}\nclass PostScriptCompiler {\n  compile(code, domain, range) {\n    const stack = [];\n    const instructions = [];\n    const inputSize = domain.length >> 1,\n      outputSize = range.length >> 1;\n    let lastRegister = 0;\n    let n, j;\n    let num1, num2, ast1, ast2, tmpVar, item;\n    for (let i = 0; i < inputSize; i++) {\n      stack.push(new AstArgument(i, domain[i * 2], domain[i * 2 + 1]));\n    }\n    for (let i = 0, ii = code.length; i < ii; i++) {\n      item = code[i];\n      if (typeof item === \"number\") {\n        stack.push(new AstLiteral(item));\n        continue;\n      }\n      switch (item) {\n        case \"add\":\n          if (stack.length < 2) {\n            return null;\n          }\n          num2 = stack.pop();\n          num1 = stack.pop();\n          stack.push(buildAddOperation(num1, num2));\n          break;\n        case \"cvr\":\n          if (stack.length < 1) {\n            return null;\n          }\n          break;\n        case \"mul\":\n          if (stack.length < 2) {\n            return null;\n          }\n          num2 = stack.pop();\n          num1 = stack.pop();\n          stack.push(buildMulOperation(num1, num2));\n          break;\n        case \"sub\":\n          if (stack.length < 2) {\n            return null;\n          }\n          num2 = stack.pop();\n          num1 = stack.pop();\n          stack.push(buildSubOperation(num1, num2));\n          break;\n        case \"exch\":\n          if (stack.length < 2) {\n            return null;\n          }\n          ast1 = stack.pop();\n          ast2 = stack.pop();\n          stack.push(ast1, ast2);\n          break;\n        case \"pop\":\n          if (stack.length < 1) {\n            return null;\n          }\n          stack.pop();\n          break;\n        case \"index\":\n          if (stack.length < 1) {\n            return null;\n          }\n          num1 = stack.pop();\n          if (num1.type !== \"literal\") {\n            return null;\n          }\n          n = num1.number;\n          if (n < 0 || !Number.isInteger(n) || stack.length < n) {\n            return null;\n          }\n          ast1 = stack[stack.length - n - 1];\n          if (ast1.type === \"literal\" || ast1.type === \"var\") {\n            stack.push(ast1);\n            break;\n          }\n          tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max);\n          stack[stack.length - n - 1] = tmpVar;\n          stack.push(tmpVar);\n          instructions.push(new AstVariableDefinition(tmpVar, ast1));\n          break;\n        case \"dup\":\n          if (stack.length < 1) {\n            return null;\n          }\n          if (typeof code[i + 1] === \"number\" && code[i + 2] === \"gt\" && code[i + 3] === i + 7 && code[i + 4] === \"jz\" && code[i + 5] === \"pop\" && code[i + 6] === code[i + 1]) {\n            num1 = stack.pop();\n            stack.push(buildMinOperation(num1, code[i + 1]));\n            i += 6;\n            break;\n          }\n          ast1 = stack.at(-1);\n          if (ast1.type === \"literal\" || ast1.type === \"var\") {\n            stack.push(ast1);\n            break;\n          }\n          tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max);\n          stack[stack.length - 1] = tmpVar;\n          stack.push(tmpVar);\n          instructions.push(new AstVariableDefinition(tmpVar, ast1));\n          break;\n        case \"roll\":\n          if (stack.length < 2) {\n            return null;\n          }\n          num2 = stack.pop();\n          num1 = stack.pop();\n          if (num2.type !== \"literal\" || num1.type !== \"literal\") {\n            return null;\n          }\n          j = num2.number;\n          n = num1.number;\n          if (n <= 0 || !Number.isInteger(n) || !Number.isInteger(j) || stack.length < n) {\n            return null;\n          }\n          j = (j % n + n) % n;\n          if (j === 0) {\n            break;\n          }\n          stack.push(...stack.splice(stack.length - n, n - j));\n          break;\n        default:\n          return null;\n      }\n    }\n    if (stack.length !== outputSize) {\n      return null;\n    }\n    const result = [];\n    for (const instruction of instructions) {\n      const statementBuilder = new ExpressionBuilderVisitor();\n      instruction.visit(statementBuilder);\n      result.push(statementBuilder.toString());\n    }\n    for (let i = 0, ii = stack.length; i < ii; i++) {\n      const expr = stack[i],\n        statementBuilder = new ExpressionBuilderVisitor();\n      expr.visit(statementBuilder);\n      const min = range[i * 2],\n        max = range[i * 2 + 1];\n      const out = [statementBuilder.toString()];\n      if (min > expr.min) {\n        out.unshift(\"Math.max(\", min, \", \");\n        out.push(\")\");\n      }\n      if (max < expr.max) {\n        out.unshift(\"Math.min(\", max, \", \");\n        out.push(\")\");\n      }\n      out.unshift(\"dest[destOffset + \", i, \"] = \");\n      out.push(\";\");\n      result.push(out.join(\"\"));\n    }\n    return result.join(\"\\n\");\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/bidi.js\n\nconst baseTypes = [\"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"S\", \"B\", \"S\", \"WS\", \"B\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"B\", \"B\", \"B\", \"S\", \"WS\", \"ON\", \"ON\", \"ET\", \"ET\", \"ET\", \"ON\", \"ON\", \"ON\", \"ON\", \"ON\", \"ES\", \"CS\", \"ES\", \"CS\", \"CS\", \"EN\", \"EN\", \"EN\", \"EN\", \"EN\", \"EN\", \"EN\", \"EN\", \"EN\", \"EN\", \"CS\", \"ON\", \"ON\", \"ON\", \"ON\", \"ON\", \"ON\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"ON\", \"ON\", \"ON\", \"ON\", \"ON\", \"ON\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"ON\", \"ON\", \"ON\", \"ON\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"B\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"BN\", \"CS\", \"ON\", \"ET\", \"ET\", \"ET\", \"ET\", \"ON\", \"ON\", \"ON\", \"ON\", \"L\", \"ON\", \"ON\", \"BN\", \"ON\", \"ON\", \"ET\", \"ET\", \"EN\", \"EN\", \"ON\", \"L\", \"ON\", \"ON\", \"ON\", \"EN\", \"L\", \"ON\", \"ON\", \"ON\", \"ON\", \"ON\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"ON\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"ON\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\", \"L\"];\nconst arabicTypes = [\"AN\", \"AN\", \"AN\", \"AN\", \"AN\", \"AN\", \"ON\", \"ON\", \"AL\", \"ET\", \"ET\", \"AL\", \"CS\", \"AL\", \"ON\", \"ON\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"AL\", \"AL\", \"\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"AN\", \"AN\", \"AN\", \"AN\", \"AN\", \"AN\", \"AN\", \"AN\", \"AN\", \"AN\", \"ET\", \"AN\", \"AN\", \"AL\", \"AL\", \"AL\", \"NSM\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"AN\", \"ON\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"AL\", \"AL\", \"NSM\", \"NSM\", \"ON\", \"NSM\", \"NSM\", \"NSM\", \"NSM\", \"AL\", \"AL\", \"EN\", \"EN\", \"EN\", \"EN\", \"EN\", \"EN\", \"EN\", \"EN\", \"EN\", \"EN\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\", \"AL\"];\nfunction isOdd(i) {\n  return (i & 1) !== 0;\n}\nfunction isEven(i) {\n  return (i & 1) === 0;\n}\nfunction findUnequal(arr, start, value) {\n  let j, jj;\n  for (j = start, jj = arr.length; j < jj; ++j) {\n    if (arr[j] !== value) {\n      return j;\n    }\n  }\n  return j;\n}\nfunction setValues(arr, start, end, value) {\n  for (let j = start; j < end; ++j) {\n    arr[j] = value;\n  }\n}\nfunction reverseValues(arr, start, end) {\n  for (let i = start, j = end - 1; i < j; ++i, --j) {\n    const temp = arr[i];\n    arr[i] = arr[j];\n    arr[j] = temp;\n  }\n}\nfunction createBidiText(str, isLTR, vertical = false) {\n  let dir = \"ltr\";\n  if (vertical) {\n    dir = \"ttb\";\n  } else if (!isLTR) {\n    dir = \"rtl\";\n  }\n  return {\n    str,\n    dir\n  };\n}\nconst chars = [];\nconst types = [];\nfunction bidi(str, startLevel = -1, vertical = false) {\n  let isLTR = true;\n  const strLength = str.length;\n  if (strLength === 0 || vertical) {\n    return createBidiText(str, isLTR, vertical);\n  }\n  chars.length = strLength;\n  types.length = strLength;\n  let numBidi = 0;\n  let i, ii;\n  for (i = 0; i < strLength; ++i) {\n    chars[i] = str.charAt(i);\n    const charCode = str.charCodeAt(i);\n    let charType = \"L\";\n    if (charCode <= 0x00ff) {\n      charType = baseTypes[charCode];\n    } else if (0x0590 <= charCode && charCode <= 0x05f4) {\n      charType = \"R\";\n    } else if (0x0600 <= charCode && charCode <= 0x06ff) {\n      charType = arabicTypes[charCode & 0xff];\n      if (!charType) {\n        warn(\"Bidi: invalid Unicode character \" + charCode.toString(16));\n      }\n    } else if (0x0700 <= charCode && charCode <= 0x08ac || 0xfb50 <= charCode && charCode <= 0xfdff || 0xfe70 <= charCode && charCode <= 0xfeff) {\n      charType = \"AL\";\n    }\n    if (charType === \"R\" || charType === \"AL\" || charType === \"AN\") {\n      numBidi++;\n    }\n    types[i] = charType;\n  }\n  if (numBidi === 0) {\n    isLTR = true;\n    return createBidiText(str, isLTR);\n  }\n  if (startLevel === -1) {\n    if (numBidi / strLength < 0.3 && strLength > 4) {\n      isLTR = true;\n      startLevel = 0;\n    } else {\n      isLTR = false;\n      startLevel = 1;\n    }\n  }\n  const levels = [];\n  for (i = 0; i < strLength; ++i) {\n    levels[i] = startLevel;\n  }\n  const e = isOdd(startLevel) ? \"R\" : \"L\";\n  const sor = e;\n  const eor = sor;\n  let lastType = sor;\n  for (i = 0; i < strLength; ++i) {\n    if (types[i] === \"NSM\") {\n      types[i] = lastType;\n    } else {\n      lastType = types[i];\n    }\n  }\n  lastType = sor;\n  let t;\n  for (i = 0; i < strLength; ++i) {\n    t = types[i];\n    if (t === \"EN\") {\n      types[i] = lastType === \"AL\" ? \"AN\" : \"EN\";\n    } else if (t === \"R\" || t === \"L\" || t === \"AL\") {\n      lastType = t;\n    }\n  }\n  for (i = 0; i < strLength; ++i) {\n    t = types[i];\n    if (t === \"AL\") {\n      types[i] = \"R\";\n    }\n  }\n  for (i = 1; i < strLength - 1; ++i) {\n    if (types[i] === \"ES\" && types[i - 1] === \"EN\" && types[i + 1] === \"EN\") {\n      types[i] = \"EN\";\n    }\n    if (types[i] === \"CS\" && (types[i - 1] === \"EN\" || types[i - 1] === \"AN\") && types[i + 1] === types[i - 1]) {\n      types[i] = types[i - 1];\n    }\n  }\n  for (i = 0; i < strLength; ++i) {\n    if (types[i] === \"EN\") {\n      for (let j = i - 1; j >= 0; --j) {\n        if (types[j] !== \"ET\") {\n          break;\n        }\n        types[j] = \"EN\";\n      }\n      for (let j = i + 1; j < strLength; ++j) {\n        if (types[j] !== \"ET\") {\n          break;\n        }\n        types[j] = \"EN\";\n      }\n    }\n  }\n  for (i = 0; i < strLength; ++i) {\n    t = types[i];\n    if (t === \"WS\" || t === \"ES\" || t === \"ET\" || t === \"CS\") {\n      types[i] = \"ON\";\n    }\n  }\n  lastType = sor;\n  for (i = 0; i < strLength; ++i) {\n    t = types[i];\n    if (t === \"EN\") {\n      types[i] = lastType === \"L\" ? \"L\" : \"EN\";\n    } else if (t === \"R\" || t === \"L\") {\n      lastType = t;\n    }\n  }\n  for (i = 0; i < strLength; ++i) {\n    if (types[i] === \"ON\") {\n      const end = findUnequal(types, i + 1, \"ON\");\n      let before = sor;\n      if (i > 0) {\n        before = types[i - 1];\n      }\n      let after = eor;\n      if (end + 1 < strLength) {\n        after = types[end + 1];\n      }\n      if (before !== \"L\") {\n        before = \"R\";\n      }\n      if (after !== \"L\") {\n        after = \"R\";\n      }\n      if (before === after) {\n        setValues(types, i, end, before);\n      }\n      i = end - 1;\n    }\n  }\n  for (i = 0; i < strLength; ++i) {\n    if (types[i] === \"ON\") {\n      types[i] = e;\n    }\n  }\n  for (i = 0; i < strLength; ++i) {\n    t = types[i];\n    if (isEven(levels[i])) {\n      if (t === \"R\") {\n        levels[i] += 1;\n      } else if (t === \"AN\" || t === \"EN\") {\n        levels[i] += 2;\n      }\n    } else if (t === \"L\" || t === \"AN\" || t === \"EN\") {\n      levels[i] += 1;\n    }\n  }\n  let highestLevel = -1;\n  let lowestOddLevel = 99;\n  let level;\n  for (i = 0, ii = levels.length; i < ii; ++i) {\n    level = levels[i];\n    if (highestLevel < level) {\n      highestLevel = level;\n    }\n    if (lowestOddLevel > level && isOdd(level)) {\n      lowestOddLevel = level;\n    }\n  }\n  for (level = highestLevel; level >= lowestOddLevel; --level) {\n    let start = -1;\n    for (i = 0, ii = levels.length; i < ii; ++i) {\n      if (levels[i] < level) {\n        if (start >= 0) {\n          reverseValues(chars, start, i);\n          start = -1;\n        }\n      } else if (start < 0) {\n        start = i;\n      }\n    }\n    if (start >= 0) {\n      reverseValues(chars, start, levels.length);\n    }\n  }\n  for (i = 0, ii = chars.length; i < ii; ++i) {\n    const ch = chars[i];\n    if (ch === \"<\" || ch === \">\") {\n      chars[i] = \"\";\n    }\n  }\n  return createBidiText(chars.join(\"\"), isLTR);\n}\n\n;// CONCATENATED MODULE: ./src/core/font_substitutions.js\n\n\n\nconst NORMAL = {\n  style: \"normal\",\n  weight: \"normal\"\n};\nconst BOLD = {\n  style: \"normal\",\n  weight: \"bold\"\n};\nconst ITALIC = {\n  style: \"italic\",\n  weight: \"normal\"\n};\nconst BOLDITALIC = {\n  style: \"italic\",\n  weight: \"bold\"\n};\nconst substitutionMap = new Map([[\"Times-Roman\", {\n  local: [\"Times New Roman\", \"Times-Roman\", \"Times\", \"Liberation Serif\", \"Nimbus Roman\", \"Nimbus Roman L\", \"Tinos\", \"Thorndale\", \"TeX Gyre Termes\", \"FreeSerif\", \"Linux Libertine O\", \"Libertinus Serif\", \"DejaVu Serif\", \"Bitstream Vera Serif\", \"Ubuntu\"],\n  style: NORMAL,\n  ultimate: \"serif\"\n}], [\"Times-Bold\", {\n  alias: \"Times-Roman\",\n  style: BOLD,\n  ultimate: \"serif\"\n}], [\"Times-Italic\", {\n  alias: \"Times-Roman\",\n  style: ITALIC,\n  ultimate: \"serif\"\n}], [\"Times-BoldItalic\", {\n  alias: \"Times-Roman\",\n  style: BOLDITALIC,\n  ultimate: \"serif\"\n}], [\"Helvetica\", {\n  local: [\"Helvetica\", \"Helvetica Neue\", \"Arial\", \"Arial Nova\", \"Liberation Sans\", \"Arimo\", \"Nimbus Sans\", \"Nimbus Sans L\", \"A030\", \"TeX Gyre Heros\", \"FreeSans\", \"DejaVu Sans\", \"Albany\", \"Bitstream Vera Sans\", \"Arial Unicode MS\", \"Microsoft Sans Serif\", \"Apple Symbols\", \"Cantarell\"],\n  path: \"LiberationSans-Regular.ttf\",\n  style: NORMAL,\n  ultimate: \"sans-serif\"\n}], [\"Helvetica-Bold\", {\n  alias: \"Helvetica\",\n  path: \"LiberationSans-Bold.ttf\",\n  style: BOLD,\n  ultimate: \"sans-serif\"\n}], [\"Helvetica-Oblique\", {\n  alias: \"Helvetica\",\n  path: \"LiberationSans-Italic.ttf\",\n  style: ITALIC,\n  ultimate: \"sans-serif\"\n}], [\"Helvetica-BoldOblique\", {\n  alias: \"Helvetica\",\n  path: \"LiberationSans-BoldItalic.ttf\",\n  style: BOLDITALIC,\n  ultimate: \"sans-serif\"\n}], [\"Courier\", {\n  local: [\"Courier\", \"Courier New\", \"Liberation Mono\", \"Nimbus Mono\", \"Nimbus Mono L\", \"Cousine\", \"Cumberland\", \"TeX Gyre Cursor\", \"FreeMono\", \"Linux Libertine Mono O\", \"Libertinus Mono\"],\n  style: NORMAL,\n  ultimate: \"monospace\"\n}], [\"Courier-Bold\", {\n  alias: \"Courier\",\n  style: BOLD,\n  ultimate: \"monospace\"\n}], [\"Courier-Oblique\", {\n  alias: \"Courier\",\n  style: ITALIC,\n  ultimate: \"monospace\"\n}], [\"Courier-BoldOblique\", {\n  alias: \"Courier\",\n  style: BOLDITALIC,\n  ultimate: \"monospace\"\n}], [\"ArialBlack\", {\n  local: [\"Arial Black\"],\n  style: {\n    style: \"normal\",\n    weight: \"900\"\n  },\n  fallback: \"Helvetica-Bold\"\n}], [\"ArialBlack-Bold\", {\n  alias: \"ArialBlack\"\n}], [\"ArialBlack-Italic\", {\n  alias: \"ArialBlack\",\n  style: {\n    style: \"italic\",\n    weight: \"900\"\n  },\n  fallback: \"Helvetica-BoldOblique\"\n}], [\"ArialBlack-BoldItalic\", {\n  alias: \"ArialBlack-Italic\"\n}], [\"ArialNarrow\", {\n  local: [\"Arial Narrow\", \"Liberation Sans Narrow\", \"Helvetica Condensed\", \"Nimbus Sans Narrow\", \"TeX Gyre Heros Cn\"],\n  style: NORMAL,\n  fallback: \"Helvetica\"\n}], [\"ArialNarrow-Bold\", {\n  alias: \"ArialNarrow\",\n  style: BOLD,\n  fallback: \"Helvetica-Bold\"\n}], [\"ArialNarrow-Italic\", {\n  alias: \"ArialNarrow\",\n  style: ITALIC,\n  fallback: \"Helvetica-Oblique\"\n}], [\"ArialNarrow-BoldItalic\", {\n  alias: \"ArialNarrow\",\n  style: BOLDITALIC,\n  fallback: \"Helvetica-BoldOblique\"\n}], [\"Calibri\", {\n  local: [\"Calibri\", \"Carlito\"],\n  style: NORMAL,\n  fallback: \"Helvetica\"\n}], [\"Calibri-Bold\", {\n  alias: \"Calibri\",\n  style: BOLD,\n  fallback: \"Helvetica-Bold\"\n}], [\"Calibri-Italic\", {\n  alias: \"Calibri\",\n  style: ITALIC,\n  fallback: \"Helvetica-Oblique\"\n}], [\"Calibri-BoldItalic\", {\n  alias: \"Calibri\",\n  style: BOLDITALIC,\n  fallback: \"Helvetica-BoldOblique\"\n}], [\"Wingdings\", {\n  local: [\"Wingdings\", \"URW Dingbats\"],\n  style: NORMAL\n}], [\"Wingdings-Regular\", {\n  alias: \"Wingdings\"\n}], [\"Wingdings-Bold\", {\n  alias: \"Wingdings\"\n}]]);\nconst fontAliases = new Map([[\"Arial-Black\", \"ArialBlack\"]]);\nfunction getStyleToAppend(style) {\n  switch (style) {\n    case BOLD:\n      return \"Bold\";\n    case ITALIC:\n      return \"Italic\";\n    case BOLDITALIC:\n      return \"Bold Italic\";\n    default:\n      if (style?.weight === \"bold\") {\n        return \"Bold\";\n      }\n      if (style?.style === \"italic\") {\n        return \"Italic\";\n      }\n  }\n  return \"\";\n}\nfunction getFamilyName(str) {\n  const keywords = new Set([\"thin\", \"extralight\", \"ultralight\", \"demilight\", \"semilight\", \"light\", \"book\", \"regular\", \"normal\", \"medium\", \"demibold\", \"semibold\", \"bold\", \"extrabold\", \"ultrabold\", \"black\", \"heavy\", \"extrablack\", \"ultrablack\", \"roman\", \"italic\", \"oblique\", \"ultracondensed\", \"extracondensed\", \"condensed\", \"semicondensed\", \"normal\", \"semiexpanded\", \"expanded\", \"extraexpanded\", \"ultraexpanded\", \"bolditalic\"]);\n  return str.split(/[- ,+]+/g).filter(tok => !keywords.has(tok.toLowerCase())).join(\" \");\n}\nfunction generateFont({\n  alias,\n  local,\n  path,\n  fallback,\n  style,\n  ultimate\n}, src, localFontPath, useFallback = true, usePath = true, append = \"\") {\n  const result = {\n    style: null,\n    ultimate: null\n  };\n  if (local) {\n    const extra = append ? ` ${append}` : \"\";\n    for (const name of local) {\n      src.push(`local(${name}${extra})`);\n    }\n  }\n  if (alias) {\n    const substitution = substitutionMap.get(alias);\n    const aliasAppend = append || getStyleToAppend(style);\n    Object.assign(result, generateFont(substitution, src, localFontPath, useFallback && !fallback, usePath && !path, aliasAppend));\n  }\n  if (style) {\n    result.style = style;\n  }\n  if (ultimate) {\n    result.ultimate = ultimate;\n  }\n  if (useFallback && fallback) {\n    const fallbackInfo = substitutionMap.get(fallback);\n    const {\n      ultimate: fallbackUltimate\n    } = generateFont(fallbackInfo, src, localFontPath, useFallback, usePath && !path, append);\n    result.ultimate ||= fallbackUltimate;\n  }\n  if (usePath && path && localFontPath) {\n    src.push(`url(${localFontPath}${path})`);\n  }\n  return result;\n}\nfunction getFontSubstitution(systemFontCache, idFactory, localFontPath, baseFontName, standardFontName, type) {\n  if (baseFontName.startsWith(\"InvalidPDFjsFont_\")) {\n    return null;\n  }\n  if ((type === \"TrueType\" || type === \"Type1\") && /^[A-Z]{6}\\+/.test(baseFontName)) {\n    baseFontName = baseFontName.slice(7);\n  }\n  baseFontName = normalizeFontName(baseFontName);\n  const key = baseFontName;\n  let substitutionInfo = systemFontCache.get(key);\n  if (substitutionInfo) {\n    return substitutionInfo;\n  }\n  let substitution = substitutionMap.get(baseFontName);\n  if (!substitution) {\n    for (const [alias, subst] of fontAliases) {\n      if (baseFontName.startsWith(alias)) {\n        baseFontName = `${subst}${baseFontName.substring(alias.length)}`;\n        substitution = substitutionMap.get(baseFontName);\n        break;\n      }\n    }\n  }\n  let mustAddBaseFont = false;\n  if (!substitution) {\n    substitution = substitutionMap.get(standardFontName);\n    mustAddBaseFont = true;\n  }\n  const loadedName = `${idFactory.getDocId()}_s${idFactory.createFontId()}`;\n  if (!substitution) {\n    if (!validateFontName(baseFontName)) {\n      warn(`Cannot substitute the font because of its name: ${baseFontName}`);\n      systemFontCache.set(key, null);\n      return null;\n    }\n    const bold = /bold/gi.test(baseFontName);\n    const italic = /oblique|italic/gi.test(baseFontName);\n    const style = bold && italic && BOLDITALIC || bold && BOLD || italic && ITALIC || NORMAL;\n    substitutionInfo = {\n      css: `\"${getFamilyName(baseFontName)}\",${loadedName}`,\n      guessFallback: true,\n      loadedName,\n      baseFontName,\n      src: `local(${baseFontName})`,\n      style\n    };\n    systemFontCache.set(key, substitutionInfo);\n    return substitutionInfo;\n  }\n  const src = [];\n  if (mustAddBaseFont && validateFontName(baseFontName)) {\n    src.push(`local(${baseFontName})`);\n  }\n  const {\n    style,\n    ultimate\n  } = generateFont(substitution, src, localFontPath);\n  const guessFallback = ultimate === null;\n  const fallback = guessFallback ? \"\" : `,${ultimate}`;\n  substitutionInfo = {\n    css: `\"${getFamilyName(baseFontName)}\",${loadedName}${fallback}`,\n    guessFallback,\n    loadedName,\n    baseFontName,\n    src: src.join(\",\"),\n    style\n  };\n  systemFontCache.set(key, substitutionInfo);\n  return substitutionInfo;\n}\n\n;// CONCATENATED MODULE: ./src/core/image_resizer.js\n\nconst MIN_IMAGE_DIM = 2048;\nconst MAX_IMAGE_DIM = 65537;\nconst MAX_ERROR = 128;\nclass ImageResizer {\n  constructor(imgData, isMask) {\n    this._imgData = imgData;\n    this._isMask = isMask;\n  }\n  static needsToBeResized(width, height) {\n    if (width <= this._goodSquareLength && height <= this._goodSquareLength) {\n      return false;\n    }\n    const {\n      MAX_DIM\n    } = this;\n    if (width > MAX_DIM || height > MAX_DIM) {\n      return true;\n    }\n    const area = width * height;\n    if (this._hasMaxArea) {\n      return area > this.MAX_AREA;\n    }\n    if (area < this._goodSquareLength ** 2) {\n      return false;\n    }\n    if (this._areGoodDims(width, height)) {\n      this._goodSquareLength = Math.max(this._goodSquareLength, Math.floor(Math.sqrt(width * height)));\n      return false;\n    }\n    this._goodSquareLength = this._guessMax(this._goodSquareLength, MAX_DIM, MAX_ERROR, 0);\n    const maxArea = this.MAX_AREA = this._goodSquareLength ** 2;\n    return area > maxArea;\n  }\n  static get MAX_DIM() {\n    return shadow(this, \"MAX_DIM\", this._guessMax(MIN_IMAGE_DIM, MAX_IMAGE_DIM, 0, 1));\n  }\n  static get MAX_AREA() {\n    this._hasMaxArea = true;\n    return shadow(this, \"MAX_AREA\", this._guessMax(ImageResizer._goodSquareLength, this.MAX_DIM, MAX_ERROR, 0) ** 2);\n  }\n  static set MAX_AREA(area) {\n    if (area >= 0) {\n      this._hasMaxArea = true;\n      shadow(this, \"MAX_AREA\", area);\n    }\n  }\n  static setMaxArea(area) {\n    if (!this._hasMaxArea) {\n      this.MAX_AREA = area >> 2;\n    }\n  }\n  static _areGoodDims(width, height) {\n    try {\n      const canvas = new OffscreenCanvas(width, height);\n      const ctx = canvas.getContext(\"2d\");\n      ctx.fillRect(0, 0, 1, 1);\n      const opacity = ctx.getImageData(0, 0, 1, 1).data[3];\n      canvas.width = canvas.height = 1;\n      return opacity !== 0;\n    } catch {\n      return false;\n    }\n  }\n  static _guessMax(start, end, tolerance, defaultHeight) {\n    while (start + tolerance + 1 < end) {\n      const middle = Math.floor((start + end) / 2);\n      const height = defaultHeight || middle;\n      if (this._areGoodDims(middle, height)) {\n        start = middle;\n      } else {\n        end = middle;\n      }\n    }\n    return start;\n  }\n  static async createImage(imgData, isMask = false) {\n    return new ImageResizer(imgData, isMask)._createImage();\n  }\n  async _createImage() {\n    const data = this._encodeBMP();\n    const blob = new Blob([data.buffer], {\n      type: \"image/bmp\"\n    });\n    const bitmapPromise = createImageBitmap(blob);\n    const {\n      MAX_AREA,\n      MAX_DIM\n    } = ImageResizer;\n    const {\n      _imgData: imgData\n    } = this;\n    const {\n      width,\n      height\n    } = imgData;\n    const minFactor = Math.max(width / MAX_DIM, height / MAX_DIM, Math.sqrt(width * height / MAX_AREA));\n    const firstFactor = Math.max(minFactor, 2);\n    const factor = Math.round(10 * (minFactor + 1.25)) / 10 / firstFactor;\n    const N = Math.floor(Math.log2(factor));\n    const steps = new Array(N + 2).fill(2);\n    steps[0] = firstFactor;\n    steps.splice(-1, 1, factor / (1 << N));\n    let newWidth = width;\n    let newHeight = height;\n    let bitmap = await bitmapPromise;\n    for (const step of steps) {\n      const prevWidth = newWidth;\n      const prevHeight = newHeight;\n      newWidth = Math.floor(newWidth / step) - 1;\n      newHeight = Math.floor(newHeight / step) - 1;\n      const canvas = new OffscreenCanvas(newWidth, newHeight);\n      const ctx = canvas.getContext(\"2d\");\n      ctx.drawImage(bitmap, 0, 0, prevWidth, prevHeight, 0, 0, newWidth, newHeight);\n      bitmap = canvas.transferToImageBitmap();\n    }\n    imgData.data = null;\n    imgData.bitmap = bitmap;\n    imgData.width = newWidth;\n    imgData.height = newHeight;\n    return imgData;\n  }\n  _encodeBMP() {\n    const {\n      width,\n      height,\n      kind\n    } = this._imgData;\n    let data = this._imgData.data;\n    let bitPerPixel;\n    let colorTable = new Uint8Array(0);\n    let maskTable = colorTable;\n    let compression = 0;\n    switch (kind) {\n      case ImageKind.GRAYSCALE_1BPP:\n        {\n          bitPerPixel = 1;\n          colorTable = new Uint8Array(this._isMask ? [255, 255, 255, 255, 0, 0, 0, 0] : [0, 0, 0, 0, 255, 255, 255, 255]);\n          const rowLen = width + 7 >> 3;\n          const rowSize = rowLen + 3 & -4;\n          if (rowLen !== rowSize) {\n            const newData = new Uint8Array(rowSize * height);\n            let k = 0;\n            for (let i = 0, ii = height * rowLen; i < ii; i += rowLen, k += rowSize) {\n              newData.set(data.subarray(i, i + rowLen), k);\n            }\n            data = newData;\n          }\n          break;\n        }\n      case ImageKind.RGB_24BPP:\n        {\n          bitPerPixel = 24;\n          if (width & 3) {\n            const rowLen = 3 * width;\n            const rowSize = rowLen + 3 & -4;\n            const extraLen = rowSize - rowLen;\n            const newData = new Uint8Array(rowSize * height);\n            let k = 0;\n            for (let i = 0, ii = height * rowLen; i < ii; i += rowLen) {\n              const row = data.subarray(i, i + rowLen);\n              for (let j = 0; j < rowLen; j += 3) {\n                newData[k++] = row[j + 2];\n                newData[k++] = row[j + 1];\n                newData[k++] = row[j];\n              }\n              k += extraLen;\n            }\n            data = newData;\n          } else {\n            for (let i = 0, ii = data.length; i < ii; i += 3) {\n              const tmp = data[i];\n              data[i] = data[i + 2];\n              data[i + 2] = tmp;\n            }\n          }\n          break;\n        }\n      case ImageKind.RGBA_32BPP:\n        bitPerPixel = 32;\n        compression = 3;\n        maskTable = new Uint8Array(4 + 4 + 4 + 4 + 52);\n        const view = new DataView(maskTable.buffer);\n        if (FeatureTest.isLittleEndian) {\n          view.setUint32(0, 0x000000ff, true);\n          view.setUint32(4, 0x0000ff00, true);\n          view.setUint32(8, 0x00ff0000, true);\n          view.setUint32(12, 0xff000000, true);\n        } else {\n          view.setUint32(0, 0xff000000, true);\n          view.setUint32(4, 0x00ff0000, true);\n          view.setUint32(8, 0x0000ff00, true);\n          view.setUint32(12, 0x000000ff, true);\n        }\n        break;\n      default:\n        throw new Error(\"invalid format\");\n    }\n    let i = 0;\n    const headerLength = 40 + maskTable.length;\n    const fileLength = 14 + headerLength + colorTable.length + data.length;\n    const bmpData = new Uint8Array(fileLength);\n    const view = new DataView(bmpData.buffer);\n    view.setUint16(i, 0x4d42, true);\n    i += 2;\n    view.setUint32(i, fileLength, true);\n    i += 4;\n    view.setUint32(i, 0, true);\n    i += 4;\n    view.setUint32(i, 14 + headerLength + colorTable.length, true);\n    i += 4;\n    view.setUint32(i, headerLength, true);\n    i += 4;\n    view.setInt32(i, width, true);\n    i += 4;\n    view.setInt32(i, -height, true);\n    i += 4;\n    view.setUint16(i, 1, true);\n    i += 2;\n    view.setUint16(i, bitPerPixel, true);\n    i += 2;\n    view.setUint32(i, compression, true);\n    i += 4;\n    view.setUint32(i, 0, true);\n    i += 4;\n    view.setInt32(i, 0, true);\n    i += 4;\n    view.setInt32(i, 0, true);\n    i += 4;\n    view.setUint32(i, colorTable.length / 4, true);\n    i += 4;\n    view.setUint32(i, 0, true);\n    i += 4;\n    bmpData.set(maskTable, i);\n    i += maskTable.length;\n    bmpData.set(colorTable, i);\n    i += colorTable.length;\n    bmpData.set(data, i);\n    return bmpData;\n  }\n}\nImageResizer._goodSquareLength = MIN_IMAGE_DIM;\n\n;// CONCATENATED MODULE: ./src/shared/murmurhash3.js\nconst SEED = 0xc3d2e1f0;\nconst MASK_HIGH = 0xffff0000;\nconst MASK_LOW = 0xffff;\nclass MurmurHash3_64 {\n  constructor(seed) {\n    this.h1 = seed ? seed & 0xffffffff : SEED;\n    this.h2 = seed ? seed & 0xffffffff : SEED;\n  }\n  update(input) {\n    let data, length;\n    if (typeof input === \"string\") {\n      data = new Uint8Array(input.length * 2);\n      length = 0;\n      for (let i = 0, ii = input.length; i < ii; i++) {\n        const code = input.charCodeAt(i);\n        if (code <= 0xff) {\n          data[length++] = code;\n        } else {\n          data[length++] = code >>> 8;\n          data[length++] = code & 0xff;\n        }\n      }\n    } else if (ArrayBuffer.isView(input)) {\n      data = input.slice();\n      length = data.byteLength;\n    } else {\n      throw new Error(\"Invalid data format, must be a string or TypedArray.\");\n    }\n    const blockCounts = length >> 2;\n    const tailLength = length - blockCounts * 4;\n    const dataUint32 = new Uint32Array(data.buffer, 0, blockCounts);\n    let k1 = 0,\n      k2 = 0;\n    let h1 = this.h1,\n      h2 = this.h2;\n    const C1 = 0xcc9e2d51,\n      C2 = 0x1b873593;\n    const C1_LOW = C1 & MASK_LOW,\n      C2_LOW = C2 & MASK_LOW;\n    for (let i = 0; i < blockCounts; i++) {\n      if (i & 1) {\n        k1 = dataUint32[i];\n        k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW;\n        k1 = k1 << 15 | k1 >>> 17;\n        k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW;\n        h1 ^= k1;\n        h1 = h1 << 13 | h1 >>> 19;\n        h1 = h1 * 5 + 0xe6546b64;\n      } else {\n        k2 = dataUint32[i];\n        k2 = k2 * C1 & MASK_HIGH | k2 * C1_LOW & MASK_LOW;\n        k2 = k2 << 15 | k2 >>> 17;\n        k2 = k2 * C2 & MASK_HIGH | k2 * C2_LOW & MASK_LOW;\n        h2 ^= k2;\n        h2 = h2 << 13 | h2 >>> 19;\n        h2 = h2 * 5 + 0xe6546b64;\n      }\n    }\n    k1 = 0;\n    switch (tailLength) {\n      case 3:\n        k1 ^= data[blockCounts * 4 + 2] << 16;\n      case 2:\n        k1 ^= data[blockCounts * 4 + 1] << 8;\n      case 1:\n        k1 ^= data[blockCounts * 4];\n        k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW;\n        k1 = k1 << 15 | k1 >>> 17;\n        k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW;\n        if (blockCounts & 1) {\n          h1 ^= k1;\n        } else {\n          h2 ^= k1;\n        }\n    }\n    this.h1 = h1;\n    this.h2 = h2;\n  }\n  hexdigest() {\n    let h1 = this.h1,\n      h2 = this.h2;\n    h1 ^= h2 >>> 1;\n    h1 = h1 * 0xed558ccd & MASK_HIGH | h1 * 0x8ccd & MASK_LOW;\n    h2 = h2 * 0xff51afd7 & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xafd7ed55 & MASK_HIGH) >>> 16;\n    h1 ^= h2 >>> 1;\n    h1 = h1 * 0x1a85ec53 & MASK_HIGH | h1 * 0xec53 & MASK_LOW;\n    h2 = h2 * 0xc4ceb9fe & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xb9fe1a85 & MASK_HIGH) >>> 16;\n    h1 ^= h2 >>> 1;\n    return (h1 >>> 0).toString(16).padStart(8, \"0\") + (h2 >>> 0).toString(16).padStart(8, \"0\");\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/operator_list.js\n\nfunction addState(parentState, pattern, checkFn, iterateFn, processFn) {\n  let state = parentState;\n  for (let i = 0, ii = pattern.length - 1; i < ii; i++) {\n    const item = pattern[i];\n    state = state[item] ||= [];\n  }\n  state[pattern.at(-1)] = {\n    checkFn,\n    iterateFn,\n    processFn\n  };\n}\nconst InitialState = [];\naddState(InitialState, [OPS.save, OPS.transform, OPS.paintInlineImageXObject, OPS.restore], null, function iterateInlineImageGroup(context, i) {\n  const fnArray = context.fnArray;\n  const iFirstSave = context.iCurr - 3;\n  const pos = (i - iFirstSave) % 4;\n  switch (pos) {\n    case 0:\n      return fnArray[i] === OPS.save;\n    case 1:\n      return fnArray[i] === OPS.transform;\n    case 2:\n      return fnArray[i] === OPS.paintInlineImageXObject;\n    case 3:\n      return fnArray[i] === OPS.restore;\n  }\n  throw new Error(`iterateInlineImageGroup - invalid pos: ${pos}`);\n}, function foundInlineImageGroup(context, i) {\n  const MIN_IMAGES_IN_INLINE_IMAGES_BLOCK = 10;\n  const MAX_IMAGES_IN_INLINE_IMAGES_BLOCK = 200;\n  const MAX_WIDTH = 1000;\n  const IMAGE_PADDING = 1;\n  const fnArray = context.fnArray,\n    argsArray = context.argsArray;\n  const curr = context.iCurr;\n  const iFirstSave = curr - 3;\n  const iFirstTransform = curr - 2;\n  const iFirstPIIXO = curr - 1;\n  const count = Math.min(Math.floor((i - iFirstSave) / 4), MAX_IMAGES_IN_INLINE_IMAGES_BLOCK);\n  if (count < MIN_IMAGES_IN_INLINE_IMAGES_BLOCK) {\n    return i - (i - iFirstSave) % 4;\n  }\n  let maxX = 0;\n  const map = [];\n  let maxLineHeight = 0;\n  let currentX = IMAGE_PADDING,\n    currentY = IMAGE_PADDING;\n  for (let q = 0; q < count; q++) {\n    const transform = argsArray[iFirstTransform + (q << 2)];\n    const img = argsArray[iFirstPIIXO + (q << 2)][0];\n    if (currentX + img.width > MAX_WIDTH) {\n      maxX = Math.max(maxX, currentX);\n      currentY += maxLineHeight + 2 * IMAGE_PADDING;\n      currentX = 0;\n      maxLineHeight = 0;\n    }\n    map.push({\n      transform,\n      x: currentX,\n      y: currentY,\n      w: img.width,\n      h: img.height\n    });\n    currentX += img.width + 2 * IMAGE_PADDING;\n    maxLineHeight = Math.max(maxLineHeight, img.height);\n  }\n  const imgWidth = Math.max(maxX, currentX) + IMAGE_PADDING;\n  const imgHeight = currentY + maxLineHeight + IMAGE_PADDING;\n  const imgData = new Uint8Array(imgWidth * imgHeight * 4);\n  const imgRowSize = imgWidth << 2;\n  for (let q = 0; q < count; q++) {\n    const data = argsArray[iFirstPIIXO + (q << 2)][0].data;\n    const rowSize = map[q].w << 2;\n    let dataOffset = 0;\n    let offset = map[q].x + map[q].y * imgWidth << 2;\n    imgData.set(data.subarray(0, rowSize), offset - imgRowSize);\n    for (let k = 0, kk = map[q].h; k < kk; k++) {\n      imgData.set(data.subarray(dataOffset, dataOffset + rowSize), offset);\n      dataOffset += rowSize;\n      offset += imgRowSize;\n    }\n    imgData.set(data.subarray(dataOffset - rowSize, dataOffset), offset);\n    while (offset >= 0) {\n      data[offset - 4] = data[offset];\n      data[offset - 3] = data[offset + 1];\n      data[offset - 2] = data[offset + 2];\n      data[offset - 1] = data[offset + 3];\n      data[offset + rowSize] = data[offset + rowSize - 4];\n      data[offset + rowSize + 1] = data[offset + rowSize - 3];\n      data[offset + rowSize + 2] = data[offset + rowSize - 2];\n      data[offset + rowSize + 3] = data[offset + rowSize - 1];\n      offset -= imgRowSize;\n    }\n  }\n  const img = {\n    width: imgWidth,\n    height: imgHeight\n  };\n  if (context.isOffscreenCanvasSupported) {\n    const canvas = new OffscreenCanvas(imgWidth, imgHeight);\n    const ctx = canvas.getContext(\"2d\");\n    ctx.putImageData(new ImageData(new Uint8ClampedArray(imgData.buffer), imgWidth, imgHeight), 0, 0);\n    img.bitmap = canvas.transferToImageBitmap();\n    img.data = null;\n  } else {\n    img.kind = ImageKind.RGBA_32BPP;\n    img.data = imgData;\n  }\n  fnArray.splice(iFirstSave, count * 4, OPS.paintInlineImageXObjectGroup);\n  argsArray.splice(iFirstSave, count * 4, [img, map]);\n  return iFirstSave + 1;\n});\naddState(InitialState, [OPS.save, OPS.transform, OPS.paintImageMaskXObject, OPS.restore], null, function iterateImageMaskGroup(context, i) {\n  const fnArray = context.fnArray;\n  const iFirstSave = context.iCurr - 3;\n  const pos = (i - iFirstSave) % 4;\n  switch (pos) {\n    case 0:\n      return fnArray[i] === OPS.save;\n    case 1:\n      return fnArray[i] === OPS.transform;\n    case 2:\n      return fnArray[i] === OPS.paintImageMaskXObject;\n    case 3:\n      return fnArray[i] === OPS.restore;\n  }\n  throw new Error(`iterateImageMaskGroup - invalid pos: ${pos}`);\n}, function foundImageMaskGroup(context, i) {\n  const MIN_IMAGES_IN_MASKS_BLOCK = 10;\n  const MAX_IMAGES_IN_MASKS_BLOCK = 100;\n  const MAX_SAME_IMAGES_IN_MASKS_BLOCK = 1000;\n  const fnArray = context.fnArray,\n    argsArray = context.argsArray;\n  const curr = context.iCurr;\n  const iFirstSave = curr - 3;\n  const iFirstTransform = curr - 2;\n  const iFirstPIMXO = curr - 1;\n  let count = Math.floor((i - iFirstSave) / 4);\n  if (count < MIN_IMAGES_IN_MASKS_BLOCK) {\n    return i - (i - iFirstSave) % 4;\n  }\n  let isSameImage = false;\n  let iTransform, transformArgs;\n  const firstPIMXOArg0 = argsArray[iFirstPIMXO][0];\n  const firstTransformArg0 = argsArray[iFirstTransform][0],\n    firstTransformArg1 = argsArray[iFirstTransform][1],\n    firstTransformArg2 = argsArray[iFirstTransform][2],\n    firstTransformArg3 = argsArray[iFirstTransform][3];\n  if (firstTransformArg1 === firstTransformArg2) {\n    isSameImage = true;\n    iTransform = iFirstTransform + 4;\n    let iPIMXO = iFirstPIMXO + 4;\n    for (let q = 1; q < count; q++, iTransform += 4, iPIMXO += 4) {\n      transformArgs = argsArray[iTransform];\n      if (argsArray[iPIMXO][0] !== firstPIMXOArg0 || transformArgs[0] !== firstTransformArg0 || transformArgs[1] !== firstTransformArg1 || transformArgs[2] !== firstTransformArg2 || transformArgs[3] !== firstTransformArg3) {\n        if (q < MIN_IMAGES_IN_MASKS_BLOCK) {\n          isSameImage = false;\n        } else {\n          count = q;\n        }\n        break;\n      }\n    }\n  }\n  if (isSameImage) {\n    count = Math.min(count, MAX_SAME_IMAGES_IN_MASKS_BLOCK);\n    const positions = new Float32Array(count * 2);\n    iTransform = iFirstTransform;\n    for (let q = 0; q < count; q++, iTransform += 4) {\n      transformArgs = argsArray[iTransform];\n      positions[q << 1] = transformArgs[4];\n      positions[(q << 1) + 1] = transformArgs[5];\n    }\n    fnArray.splice(iFirstSave, count * 4, OPS.paintImageMaskXObjectRepeat);\n    argsArray.splice(iFirstSave, count * 4, [firstPIMXOArg0, firstTransformArg0, firstTransformArg1, firstTransformArg2, firstTransformArg3, positions]);\n  } else {\n    count = Math.min(count, MAX_IMAGES_IN_MASKS_BLOCK);\n    const images = [];\n    for (let q = 0; q < count; q++) {\n      transformArgs = argsArray[iFirstTransform + (q << 2)];\n      const maskParams = argsArray[iFirstPIMXO + (q << 2)][0];\n      images.push({\n        data: maskParams.data,\n        width: maskParams.width,\n        height: maskParams.height,\n        interpolate: maskParams.interpolate,\n        count: maskParams.count,\n        transform: transformArgs\n      });\n    }\n    fnArray.splice(iFirstSave, count * 4, OPS.paintImageMaskXObjectGroup);\n    argsArray.splice(iFirstSave, count * 4, [images]);\n  }\n  return iFirstSave + 1;\n});\naddState(InitialState, [OPS.save, OPS.transform, OPS.paintImageXObject, OPS.restore], function (context) {\n  const argsArray = context.argsArray;\n  const iFirstTransform = context.iCurr - 2;\n  return argsArray[iFirstTransform][1] === 0 && argsArray[iFirstTransform][2] === 0;\n}, function iterateImageGroup(context, i) {\n  const fnArray = context.fnArray,\n    argsArray = context.argsArray;\n  const iFirstSave = context.iCurr - 3;\n  const pos = (i - iFirstSave) % 4;\n  switch (pos) {\n    case 0:\n      return fnArray[i] === OPS.save;\n    case 1:\n      if (fnArray[i] !== OPS.transform) {\n        return false;\n      }\n      const iFirstTransform = context.iCurr - 2;\n      const firstTransformArg0 = argsArray[iFirstTransform][0];\n      const firstTransformArg3 = argsArray[iFirstTransform][3];\n      if (argsArray[i][0] !== firstTransformArg0 || argsArray[i][1] !== 0 || argsArray[i][2] !== 0 || argsArray[i][3] !== firstTransformArg3) {\n        return false;\n      }\n      return true;\n    case 2:\n      if (fnArray[i] !== OPS.paintImageXObject) {\n        return false;\n      }\n      const iFirstPIXO = context.iCurr - 1;\n      const firstPIXOArg0 = argsArray[iFirstPIXO][0];\n      if (argsArray[i][0] !== firstPIXOArg0) {\n        return false;\n      }\n      return true;\n    case 3:\n      return fnArray[i] === OPS.restore;\n  }\n  throw new Error(`iterateImageGroup - invalid pos: ${pos}`);\n}, function (context, i) {\n  const MIN_IMAGES_IN_BLOCK = 3;\n  const MAX_IMAGES_IN_BLOCK = 1000;\n  const fnArray = context.fnArray,\n    argsArray = context.argsArray;\n  const curr = context.iCurr;\n  const iFirstSave = curr - 3;\n  const iFirstTransform = curr - 2;\n  const iFirstPIXO = curr - 1;\n  const firstPIXOArg0 = argsArray[iFirstPIXO][0];\n  const firstTransformArg0 = argsArray[iFirstTransform][0];\n  const firstTransformArg3 = argsArray[iFirstTransform][3];\n  const count = Math.min(Math.floor((i - iFirstSave) / 4), MAX_IMAGES_IN_BLOCK);\n  if (count < MIN_IMAGES_IN_BLOCK) {\n    return i - (i - iFirstSave) % 4;\n  }\n  const positions = new Float32Array(count * 2);\n  let iTransform = iFirstTransform;\n  for (let q = 0; q < count; q++, iTransform += 4) {\n    const transformArgs = argsArray[iTransform];\n    positions[q << 1] = transformArgs[4];\n    positions[(q << 1) + 1] = transformArgs[5];\n  }\n  const args = [firstPIXOArg0, firstTransformArg0, firstTransformArg3, positions];\n  fnArray.splice(iFirstSave, count * 4, OPS.paintImageXObjectRepeat);\n  argsArray.splice(iFirstSave, count * 4, args);\n  return iFirstSave + 1;\n});\naddState(InitialState, [OPS.beginText, OPS.setFont, OPS.setTextMatrix, OPS.showText, OPS.endText], null, function iterateShowTextGroup(context, i) {\n  const fnArray = context.fnArray,\n    argsArray = context.argsArray;\n  const iFirstSave = context.iCurr - 4;\n  const pos = (i - iFirstSave) % 5;\n  switch (pos) {\n    case 0:\n      return fnArray[i] === OPS.beginText;\n    case 1:\n      return fnArray[i] === OPS.setFont;\n    case 2:\n      return fnArray[i] === OPS.setTextMatrix;\n    case 3:\n      if (fnArray[i] !== OPS.showText) {\n        return false;\n      }\n      const iFirstSetFont = context.iCurr - 3;\n      const firstSetFontArg0 = argsArray[iFirstSetFont][0];\n      const firstSetFontArg1 = argsArray[iFirstSetFont][1];\n      if (argsArray[i][0] !== firstSetFontArg0 || argsArray[i][1] !== firstSetFontArg1) {\n        return false;\n      }\n      return true;\n    case 4:\n      return fnArray[i] === OPS.endText;\n  }\n  throw new Error(`iterateShowTextGroup - invalid pos: ${pos}`);\n}, function (context, i) {\n  const MIN_CHARS_IN_BLOCK = 3;\n  const MAX_CHARS_IN_BLOCK = 1000;\n  const fnArray = context.fnArray,\n    argsArray = context.argsArray;\n  const curr = context.iCurr;\n  const iFirstBeginText = curr - 4;\n  const iFirstSetFont = curr - 3;\n  const iFirstSetTextMatrix = curr - 2;\n  const iFirstShowText = curr - 1;\n  const iFirstEndText = curr;\n  const firstSetFontArg0 = argsArray[iFirstSetFont][0];\n  const firstSetFontArg1 = argsArray[iFirstSetFont][1];\n  let count = Math.min(Math.floor((i - iFirstBeginText) / 5), MAX_CHARS_IN_BLOCK);\n  if (count < MIN_CHARS_IN_BLOCK) {\n    return i - (i - iFirstBeginText) % 5;\n  }\n  let iFirst = iFirstBeginText;\n  if (iFirstBeginText >= 4 && fnArray[iFirstBeginText - 4] === fnArray[iFirstSetFont] && fnArray[iFirstBeginText - 3] === fnArray[iFirstSetTextMatrix] && fnArray[iFirstBeginText - 2] === fnArray[iFirstShowText] && fnArray[iFirstBeginText - 1] === fnArray[iFirstEndText] && argsArray[iFirstBeginText - 4][0] === firstSetFontArg0 && argsArray[iFirstBeginText - 4][1] === firstSetFontArg1) {\n    count++;\n    iFirst -= 5;\n  }\n  let iEndText = iFirst + 4;\n  for (let q = 1; q < count; q++) {\n    fnArray.splice(iEndText, 3);\n    argsArray.splice(iEndText, 3);\n    iEndText += 2;\n  }\n  return iEndText + 1;\n});\nclass NullOptimizer {\n  constructor(queue) {\n    this.queue = queue;\n  }\n  _optimize() {}\n  push(fn, args) {\n    this.queue.fnArray.push(fn);\n    this.queue.argsArray.push(args);\n    this._optimize();\n  }\n  flush() {}\n  reset() {}\n}\nclass QueueOptimizer extends NullOptimizer {\n  constructor(queue) {\n    super(queue);\n    this.state = null;\n    this.context = {\n      iCurr: 0,\n      fnArray: queue.fnArray,\n      argsArray: queue.argsArray,\n      isOffscreenCanvasSupported: false\n    };\n    this.match = null;\n    this.lastProcessed = 0;\n  }\n  set isOffscreenCanvasSupported(value) {\n    this.context.isOffscreenCanvasSupported = value;\n  }\n  _optimize() {\n    const fnArray = this.queue.fnArray;\n    let i = this.lastProcessed,\n      ii = fnArray.length;\n    let state = this.state;\n    let match = this.match;\n    if (!state && !match && i + 1 === ii && !InitialState[fnArray[i]]) {\n      this.lastProcessed = ii;\n      return;\n    }\n    const context = this.context;\n    while (i < ii) {\n      if (match) {\n        const iterate = (0, match.iterateFn)(context, i);\n        if (iterate) {\n          i++;\n          continue;\n        }\n        i = (0, match.processFn)(context, i + 1);\n        ii = fnArray.length;\n        match = null;\n        state = null;\n        if (i >= ii) {\n          break;\n        }\n      }\n      state = (state || InitialState)[fnArray[i]];\n      if (!state || Array.isArray(state)) {\n        i++;\n        continue;\n      }\n      context.iCurr = i;\n      i++;\n      if (state.checkFn && !(0, state.checkFn)(context)) {\n        state = null;\n        continue;\n      }\n      match = state;\n      state = null;\n    }\n    this.state = state;\n    this.match = match;\n    this.lastProcessed = i;\n  }\n  flush() {\n    while (this.match) {\n      const length = this.queue.fnArray.length;\n      this.lastProcessed = (0, this.match.processFn)(this.context, length);\n      this.match = null;\n      this.state = null;\n      this._optimize();\n    }\n  }\n  reset() {\n    this.state = null;\n    this.match = null;\n    this.lastProcessed = 0;\n  }\n}\nclass OperatorList {\n  static CHUNK_SIZE = 1000;\n  static CHUNK_SIZE_ABOUT = this.CHUNK_SIZE - 5;\n  constructor(intent = 0, streamSink) {\n    this._streamSink = streamSink;\n    this.fnArray = [];\n    this.argsArray = [];\n    this.optimizer = streamSink && !(intent & RenderingIntentFlag.OPLIST) ? new QueueOptimizer(this) : new NullOptimizer(this);\n    this.dependencies = new Set();\n    this._totalLength = 0;\n    this.weight = 0;\n    this._resolved = streamSink ? null : Promise.resolve();\n  }\n  set isOffscreenCanvasSupported(value) {\n    this.optimizer.isOffscreenCanvasSupported = value;\n  }\n  get length() {\n    return this.argsArray.length;\n  }\n  get ready() {\n    return this._resolved || this._streamSink.ready;\n  }\n  get totalLength() {\n    return this._totalLength + this.length;\n  }\n  addOp(fn, args) {\n    this.optimizer.push(fn, args);\n    this.weight++;\n    if (this._streamSink) {\n      if (this.weight >= OperatorList.CHUNK_SIZE) {\n        this.flush();\n      } else if (this.weight >= OperatorList.CHUNK_SIZE_ABOUT && (fn === OPS.restore || fn === OPS.endText)) {\n        this.flush();\n      }\n    }\n  }\n  addImageOps(fn, args, optionalContent) {\n    if (optionalContent !== undefined) {\n      this.addOp(OPS.beginMarkedContentProps, [\"OC\", optionalContent]);\n    }\n    this.addOp(fn, args);\n    if (optionalContent !== undefined) {\n      this.addOp(OPS.endMarkedContent, []);\n    }\n  }\n  addDependency(dependency) {\n    if (this.dependencies.has(dependency)) {\n      return;\n    }\n    this.dependencies.add(dependency);\n    this.addOp(OPS.dependency, [dependency]);\n  }\n  addDependencies(dependencies) {\n    for (const dependency of dependencies) {\n      this.addDependency(dependency);\n    }\n  }\n  addOpList(opList) {\n    if (!(opList instanceof OperatorList)) {\n      warn('addOpList - ignoring invalid \"opList\" parameter.');\n      return;\n    }\n    for (const dependency of opList.dependencies) {\n      this.dependencies.add(dependency);\n    }\n    for (let i = 0, ii = opList.length; i < ii; i++) {\n      this.addOp(opList.fnArray[i], opList.argsArray[i]);\n    }\n  }\n  getIR() {\n    return {\n      fnArray: this.fnArray,\n      argsArray: this.argsArray,\n      length: this.length\n    };\n  }\n  get _transfers() {\n    const transfers = [];\n    const {\n      fnArray,\n      argsArray,\n      length\n    } = this;\n    for (let i = 0; i < length; i++) {\n      switch (fnArray[i]) {\n        case OPS.paintInlineImageXObject:\n        case OPS.paintInlineImageXObjectGroup:\n        case OPS.paintImageMaskXObject:\n          const arg = argsArray[i][0];\n          if (!arg.cached && arg.data?.buffer instanceof ArrayBuffer) {\n            transfers.push(arg.data.buffer);\n          }\n          break;\n      }\n    }\n    return transfers;\n  }\n  flush(lastChunk = false, separateAnnots = null) {\n    this.optimizer.flush();\n    const length = this.length;\n    this._totalLength += length;\n    this._streamSink.enqueue({\n      fnArray: this.fnArray,\n      argsArray: this.argsArray,\n      lastChunk,\n      separateAnnots,\n      length\n    }, 1, this._transfers);\n    this.dependencies.clear();\n    this.fnArray.length = 0;\n    this.argsArray.length = 0;\n    this.weight = 0;\n    this.optimizer.reset();\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/image.js\n\n\n\n\n\n\n\n\n\nfunction decodeAndClamp(value, addend, coefficient, max) {\n  value = addend + value * coefficient;\n  if (value < 0) {\n    value = 0;\n  } else if (value > max) {\n    value = max;\n  }\n  return value;\n}\nfunction resizeImageMask(src, bpc, w1, h1, w2, h2) {\n  const length = w2 * h2;\n  let dest;\n  if (bpc <= 8) {\n    dest = new Uint8Array(length);\n  } else if (bpc <= 16) {\n    dest = new Uint16Array(length);\n  } else {\n    dest = new Uint32Array(length);\n  }\n  const xRatio = w1 / w2;\n  const yRatio = h1 / h2;\n  let i,\n    j,\n    py,\n    newIndex = 0,\n    oldIndex;\n  const xScaled = new Uint16Array(w2);\n  const w1Scanline = w1;\n  for (i = 0; i < w2; i++) {\n    xScaled[i] = Math.floor(i * xRatio);\n  }\n  for (i = 0; i < h2; i++) {\n    py = Math.floor(i * yRatio) * w1Scanline;\n    for (j = 0; j < w2; j++) {\n      oldIndex = py + xScaled[j];\n      dest[newIndex++] = src[oldIndex];\n    }\n  }\n  return dest;\n}\nclass PDFImage {\n  constructor({\n    xref,\n    res,\n    image,\n    isInline = false,\n    smask = null,\n    mask = null,\n    isMask = false,\n    pdfFunctionFactory,\n    localColorSpaceCache\n  }) {\n    this.image = image;\n    let jpxDecode = false;\n    const dict = image.dict;\n    const filter = dict.get(\"F\", \"Filter\");\n    let filterName;\n    if (filter instanceof Name) {\n      filterName = filter.name;\n    } else if (Array.isArray(filter)) {\n      const filterZero = xref.fetchIfRef(filter[0]);\n      if (filterZero instanceof Name) {\n        filterName = filterZero.name;\n      }\n    }\n    switch (filterName) {\n      case \"JPXDecode\":\n        ({\n          width: image.width,\n          height: image.height,\n          componentsCount: image.numComps,\n          bitsPerComponent: image.bitsPerComponent\n        } = JpxImage.parseImageProperties(image.stream));\n        image.stream.reset();\n        jpxDecode = true;\n        break;\n      case \"JBIG2Decode\":\n        image.bitsPerComponent = 1;\n        image.numComps = 1;\n        break;\n    }\n    let width = dict.get(\"W\", \"Width\");\n    let height = dict.get(\"H\", \"Height\");\n    if (Number.isInteger(image.width) && image.width > 0 && Number.isInteger(image.height) && image.height > 0 && (image.width !== width || image.height !== height)) {\n      warn(\"PDFImage - using the Width/Height of the image data, \" + \"rather than the image dictionary.\");\n      width = image.width;\n      height = image.height;\n    }\n    if (width < 1 || height < 1) {\n      throw new FormatError(`Invalid image width: ${width} or height: ${height}`);\n    }\n    this.width = width;\n    this.height = height;\n    this.interpolate = dict.get(\"I\", \"Interpolate\");\n    this.imageMask = dict.get(\"IM\", \"ImageMask\") || false;\n    this.matte = dict.get(\"Matte\") || false;\n    let bitsPerComponent = image.bitsPerComponent;\n    if (!bitsPerComponent) {\n      bitsPerComponent = dict.get(\"BPC\", \"BitsPerComponent\");\n      if (!bitsPerComponent) {\n        if (this.imageMask) {\n          bitsPerComponent = 1;\n        } else {\n          throw new FormatError(`Bits per component missing in image: ${this.imageMask}`);\n        }\n      }\n    }\n    this.bpc = bitsPerComponent;\n    if (!this.imageMask) {\n      let colorSpace = dict.getRaw(\"CS\") || dict.getRaw(\"ColorSpace\");\n      if (!colorSpace) {\n        info(\"JPX images (which do not require color spaces)\");\n        switch (image.numComps) {\n          case 1:\n            colorSpace = Name.get(\"DeviceGray\");\n            break;\n          case 3:\n            colorSpace = Name.get(\"DeviceRGB\");\n            break;\n          case 4:\n            colorSpace = Name.get(\"DeviceCMYK\");\n            break;\n          default:\n            throw new Error(`JPX images with ${image.numComps} color components not supported.`);\n        }\n      }\n      this.colorSpace = ColorSpace.parse({\n        cs: colorSpace,\n        xref,\n        resources: isInline ? res : null,\n        pdfFunctionFactory,\n        localColorSpaceCache\n      });\n      this.numComps = this.colorSpace.numComps;\n      this.ignoreColorSpace = jpxDecode && this.colorSpace.name === \"Indexed\";\n    }\n    this.decode = dict.getArray(\"D\", \"Decode\");\n    this.needsDecode = false;\n    if (this.decode && (this.colorSpace && !this.colorSpace.isDefaultDecode(this.decode, bitsPerComponent) || isMask && !ColorSpace.isDefaultDecode(this.decode, 1))) {\n      this.needsDecode = true;\n      const max = (1 << bitsPerComponent) - 1;\n      this.decodeCoefficients = [];\n      this.decodeAddends = [];\n      const isIndexed = this.colorSpace?.name === \"Indexed\";\n      for (let i = 0, j = 0; i < this.decode.length; i += 2, ++j) {\n        const dmin = this.decode[i];\n        const dmax = this.decode[i + 1];\n        this.decodeCoefficients[j] = isIndexed ? (dmax - dmin) / max : dmax - dmin;\n        this.decodeAddends[j] = isIndexed ? dmin : max * dmin;\n      }\n    }\n    if (smask) {\n      this.smask = new PDFImage({\n        xref,\n        res,\n        image: smask,\n        isInline,\n        pdfFunctionFactory,\n        localColorSpaceCache\n      });\n    } else if (mask) {\n      if (mask instanceof BaseStream) {\n        const maskDict = mask.dict,\n          imageMask = maskDict.get(\"IM\", \"ImageMask\");\n        if (!imageMask) {\n          warn(\"Ignoring /Mask in image without /ImageMask.\");\n        } else {\n          this.mask = new PDFImage({\n            xref,\n            res,\n            image: mask,\n            isInline,\n            isMask: true,\n            pdfFunctionFactory,\n            localColorSpaceCache\n          });\n        }\n      } else {\n        this.mask = mask;\n      }\n    }\n  }\n  static async buildImage({\n    xref,\n    res,\n    image,\n    isInline = false,\n    pdfFunctionFactory,\n    localColorSpaceCache\n  }) {\n    const imageData = image;\n    let smaskData = null;\n    let maskData = null;\n    const smask = image.dict.get(\"SMask\");\n    const mask = image.dict.get(\"Mask\");\n    if (smask) {\n      if (smask instanceof BaseStream) {\n        smaskData = smask;\n      } else {\n        warn(\"Unsupported /SMask format.\");\n      }\n    } else if (mask) {\n      if (mask instanceof BaseStream || Array.isArray(mask)) {\n        maskData = mask;\n      } else {\n        warn(\"Unsupported /Mask format.\");\n      }\n    }\n    return new PDFImage({\n      xref,\n      res,\n      image: imageData,\n      isInline,\n      smask: smaskData,\n      mask: maskData,\n      pdfFunctionFactory,\n      localColorSpaceCache\n    });\n  }\n  static createRawMask({\n    imgArray,\n    width,\n    height,\n    imageIsFromDecodeStream,\n    inverseDecode,\n    interpolate\n  }) {\n    const computedLength = (width + 7 >> 3) * height;\n    const actualLength = imgArray.byteLength;\n    const haveFullData = computedLength === actualLength;\n    let data, i;\n    if (imageIsFromDecodeStream && (!inverseDecode || haveFullData)) {\n      data = imgArray;\n    } else if (!inverseDecode) {\n      data = new Uint8Array(imgArray);\n    } else {\n      data = new Uint8Array(computedLength);\n      data.set(imgArray);\n      data.fill(0xff, actualLength);\n    }\n    if (inverseDecode) {\n      for (i = 0; i < actualLength; i++) {\n        data[i] ^= 0xff;\n      }\n    }\n    return {\n      data,\n      width,\n      height,\n      interpolate\n    };\n  }\n  static async createMask({\n    imgArray,\n    width,\n    height,\n    imageIsFromDecodeStream,\n    inverseDecode,\n    interpolate,\n    isOffscreenCanvasSupported = false\n  }) {\n    const isSingleOpaquePixel = width === 1 && height === 1 && inverseDecode === (imgArray.length === 0 || !!(imgArray[0] & 128));\n    if (isSingleOpaquePixel) {\n      return {\n        isSingleOpaquePixel\n      };\n    }\n    if (isOffscreenCanvasSupported) {\n      if (ImageResizer.needsToBeResized(width, height)) {\n        const data = new Uint8ClampedArray(width * height * 4);\n        convertBlackAndWhiteToRGBA({\n          src: imgArray,\n          dest: data,\n          width,\n          height,\n          nonBlackColor: 0,\n          inverseDecode\n        });\n        return ImageResizer.createImage({\n          kind: ImageKind.RGBA_32BPP,\n          data,\n          width,\n          height,\n          interpolate\n        });\n      }\n      const canvas = new OffscreenCanvas(width, height);\n      const ctx = canvas.getContext(\"2d\");\n      const imgData = ctx.createImageData(width, height);\n      convertBlackAndWhiteToRGBA({\n        src: imgArray,\n        dest: imgData.data,\n        width,\n        height,\n        nonBlackColor: 0,\n        inverseDecode\n      });\n      ctx.putImageData(imgData, 0, 0);\n      const bitmap = canvas.transferToImageBitmap();\n      return {\n        data: null,\n        width,\n        height,\n        interpolate,\n        bitmap\n      };\n    }\n    return this.createRawMask({\n      imgArray,\n      width,\n      height,\n      inverseDecode,\n      imageIsFromDecodeStream,\n      interpolate\n    });\n  }\n  get drawWidth() {\n    return Math.max(this.width, this.smask?.width || 0, this.mask?.width || 0);\n  }\n  get drawHeight() {\n    return Math.max(this.height, this.smask?.height || 0, this.mask?.height || 0);\n  }\n  decodeBuffer(buffer) {\n    const bpc = this.bpc;\n    const numComps = this.numComps;\n    const decodeAddends = this.decodeAddends;\n    const decodeCoefficients = this.decodeCoefficients;\n    const max = (1 << bpc) - 1;\n    let i, ii;\n    if (bpc === 1) {\n      for (i = 0, ii = buffer.length; i < ii; i++) {\n        buffer[i] = +!buffer[i];\n      }\n      return;\n    }\n    let index = 0;\n    for (i = 0, ii = this.width * this.height; i < ii; i++) {\n      for (let j = 0; j < numComps; j++) {\n        buffer[index] = decodeAndClamp(buffer[index], decodeAddends[j], decodeCoefficients[j], max);\n        index++;\n      }\n    }\n  }\n  getComponents(buffer) {\n    const bpc = this.bpc;\n    if (bpc === 8) {\n      return buffer;\n    }\n    const width = this.width;\n    const height = this.height;\n    const numComps = this.numComps;\n    const length = width * height * numComps;\n    let bufferPos = 0;\n    let output;\n    if (bpc <= 8) {\n      output = new Uint8Array(length);\n    } else if (bpc <= 16) {\n      output = new Uint16Array(length);\n    } else {\n      output = new Uint32Array(length);\n    }\n    const rowComps = width * numComps;\n    const max = (1 << bpc) - 1;\n    let i = 0,\n      ii,\n      buf;\n    if (bpc === 1) {\n      let mask, loop1End, loop2End;\n      for (let j = 0; j < height; j++) {\n        loop1End = i + (rowComps & ~7);\n        loop2End = i + rowComps;\n        while (i < loop1End) {\n          buf = buffer[bufferPos++];\n          output[i] = buf >> 7 & 1;\n          output[i + 1] = buf >> 6 & 1;\n          output[i + 2] = buf >> 5 & 1;\n          output[i + 3] = buf >> 4 & 1;\n          output[i + 4] = buf >> 3 & 1;\n          output[i + 5] = buf >> 2 & 1;\n          output[i + 6] = buf >> 1 & 1;\n          output[i + 7] = buf & 1;\n          i += 8;\n        }\n        if (i < loop2End) {\n          buf = buffer[bufferPos++];\n          mask = 128;\n          while (i < loop2End) {\n            output[i++] = +!!(buf & mask);\n            mask >>= 1;\n          }\n        }\n      }\n    } else {\n      let bits = 0;\n      buf = 0;\n      for (i = 0, ii = length; i < ii; ++i) {\n        if (i % rowComps === 0) {\n          buf = 0;\n          bits = 0;\n        }\n        while (bits < bpc) {\n          buf = buf << 8 | buffer[bufferPos++];\n          bits += 8;\n        }\n        const remainingBits = bits - bpc;\n        let value = buf >> remainingBits;\n        if (value < 0) {\n          value = 0;\n        } else if (value > max) {\n          value = max;\n        }\n        output[i] = value;\n        buf &= (1 << remainingBits) - 1;\n        bits = remainingBits;\n      }\n    }\n    return output;\n  }\n  fillOpacity(rgbaBuf, width, height, actualHeight, image) {\n    const smask = this.smask;\n    const mask = this.mask;\n    let alphaBuf, sw, sh, i, ii, j;\n    if (smask) {\n      sw = smask.width;\n      sh = smask.height;\n      alphaBuf = new Uint8ClampedArray(sw * sh);\n      smask.fillGrayBuffer(alphaBuf);\n      if (sw !== width || sh !== height) {\n        alphaBuf = resizeImageMask(alphaBuf, smask.bpc, sw, sh, width, height);\n      }\n    } else if (mask) {\n      if (mask instanceof PDFImage) {\n        sw = mask.width;\n        sh = mask.height;\n        alphaBuf = new Uint8ClampedArray(sw * sh);\n        mask.numComps = 1;\n        mask.fillGrayBuffer(alphaBuf);\n        for (i = 0, ii = sw * sh; i < ii; ++i) {\n          alphaBuf[i] = 255 - alphaBuf[i];\n        }\n        if (sw !== width || sh !== height) {\n          alphaBuf = resizeImageMask(alphaBuf, mask.bpc, sw, sh, width, height);\n        }\n      } else if (Array.isArray(mask)) {\n        alphaBuf = new Uint8ClampedArray(width * height);\n        const numComps = this.numComps;\n        for (i = 0, ii = width * height; i < ii; ++i) {\n          let opacity = 0;\n          const imageOffset = i * numComps;\n          for (j = 0; j < numComps; ++j) {\n            const color = image[imageOffset + j];\n            const maskOffset = j * 2;\n            if (color < mask[maskOffset] || color > mask[maskOffset + 1]) {\n              opacity = 255;\n              break;\n            }\n          }\n          alphaBuf[i] = opacity;\n        }\n      } else {\n        throw new FormatError(\"Unknown mask format.\");\n      }\n    }\n    if (alphaBuf) {\n      for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) {\n        rgbaBuf[j] = alphaBuf[i];\n      }\n    } else {\n      for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) {\n        rgbaBuf[j] = 255;\n      }\n    }\n  }\n  undoPreblend(buffer, width, height) {\n    const matte = this.smask?.matte;\n    if (!matte) {\n      return;\n    }\n    const matteRgb = this.colorSpace.getRgb(matte, 0);\n    const matteR = matteRgb[0];\n    const matteG = matteRgb[1];\n    const matteB = matteRgb[2];\n    const length = width * height * 4;\n    for (let i = 0; i < length; i += 4) {\n      const alpha = buffer[i + 3];\n      if (alpha === 0) {\n        buffer[i] = 255;\n        buffer[i + 1] = 255;\n        buffer[i + 2] = 255;\n        continue;\n      }\n      const k = 255 / alpha;\n      buffer[i] = (buffer[i] - matteR) * k + matteR;\n      buffer[i + 1] = (buffer[i + 1] - matteG) * k + matteG;\n      buffer[i + 2] = (buffer[i + 2] - matteB) * k + matteB;\n    }\n  }\n  async createImageData(forceRGBA = false, isOffscreenCanvasSupported = false) {\n    const drawWidth = this.drawWidth;\n    const drawHeight = this.drawHeight;\n    const imgData = {\n      width: drawWidth,\n      height: drawHeight,\n      interpolate: this.interpolate,\n      kind: 0,\n      data: null\n    };\n    const numComps = this.numComps;\n    const originalWidth = this.width;\n    const originalHeight = this.height;\n    const bpc = this.bpc;\n    const rowBytes = originalWidth * numComps * bpc + 7 >> 3;\n    const mustBeResized = isOffscreenCanvasSupported && ImageResizer.needsToBeResized(drawWidth, drawHeight);\n    if (!forceRGBA) {\n      let kind;\n      if (this.colorSpace.name === \"DeviceGray\" && bpc === 1) {\n        kind = ImageKind.GRAYSCALE_1BPP;\n      } else if (this.colorSpace.name === \"DeviceRGB\" && bpc === 8 && !this.needsDecode) {\n        kind = ImageKind.RGB_24BPP;\n      }\n      if (kind && !this.smask && !this.mask && drawWidth === originalWidth && drawHeight === originalHeight) {\n        const data = this.getImageBytes(originalHeight * rowBytes, {});\n        if (isOffscreenCanvasSupported) {\n          if (mustBeResized) {\n            return ImageResizer.createImage({\n              data,\n              kind,\n              width: drawWidth,\n              height: drawHeight,\n              interpolate: this.interpolate\n            }, this.needsDecode);\n          }\n          return this.createBitmap(kind, originalWidth, originalHeight, data);\n        }\n        imgData.kind = kind;\n        imgData.data = data;\n        if (this.needsDecode) {\n          assert(kind === ImageKind.GRAYSCALE_1BPP, \"PDFImage.createImageData: The image must be grayscale.\");\n          const buffer = imgData.data;\n          for (let i = 0, ii = buffer.length; i < ii; i++) {\n            buffer[i] ^= 0xff;\n          }\n        }\n        return imgData;\n      }\n      if (this.image instanceof JpegStream && !this.smask && !this.mask && !this.needsDecode) {\n        let imageLength = originalHeight * rowBytes;\n        if (isOffscreenCanvasSupported && !mustBeResized) {\n          let isHandled = false;\n          switch (this.colorSpace.name) {\n            case \"DeviceGray\":\n              imageLength *= 4;\n              isHandled = true;\n              break;\n            case \"DeviceRGB\":\n              imageLength = imageLength / 3 * 4;\n              isHandled = true;\n              break;\n            case \"DeviceCMYK\":\n              isHandled = true;\n              break;\n          }\n          if (isHandled) {\n            const rgba = this.getImageBytes(imageLength, {\n              drawWidth,\n              drawHeight,\n              forceRGBA: true\n            });\n            return this.createBitmap(ImageKind.RGBA_32BPP, drawWidth, drawHeight, rgba);\n          }\n        } else {\n          switch (this.colorSpace.name) {\n            case \"DeviceGray\":\n              imageLength *= 3;\n            case \"DeviceRGB\":\n            case \"DeviceCMYK\":\n              imgData.kind = ImageKind.RGB_24BPP;\n              imgData.data = this.getImageBytes(imageLength, {\n                drawWidth,\n                drawHeight,\n                forceRGB: true\n              });\n              if (mustBeResized) {\n                return ImageResizer.createImage(imgData);\n              }\n              return imgData;\n          }\n        }\n      }\n    }\n    const imgArray = this.getImageBytes(originalHeight * rowBytes, {\n      internal: true\n    });\n    const actualHeight = 0 | imgArray.length / rowBytes * drawHeight / originalHeight;\n    const comps = this.getComponents(imgArray);\n    let alpha01, maybeUndoPreblend;\n    let canvas, ctx, canvasImgData, data;\n    if (isOffscreenCanvasSupported && !mustBeResized) {\n      canvas = new OffscreenCanvas(drawWidth, drawHeight);\n      ctx = canvas.getContext(\"2d\");\n      canvasImgData = ctx.createImageData(drawWidth, drawHeight);\n      data = canvasImgData.data;\n    }\n    imgData.kind = ImageKind.RGBA_32BPP;\n    if (!forceRGBA && !this.smask && !this.mask) {\n      if (!isOffscreenCanvasSupported || mustBeResized) {\n        imgData.kind = ImageKind.RGB_24BPP;\n        data = new Uint8ClampedArray(drawWidth * drawHeight * 3);\n        alpha01 = 0;\n      } else {\n        const arr = new Uint32Array(data.buffer);\n        arr.fill(FeatureTest.isLittleEndian ? 0xff000000 : 0x000000ff);\n        alpha01 = 1;\n      }\n      maybeUndoPreblend = false;\n    } else {\n      if (!isOffscreenCanvasSupported || mustBeResized) {\n        data = new Uint8ClampedArray(drawWidth * drawHeight * 4);\n      }\n      alpha01 = 1;\n      maybeUndoPreblend = true;\n      this.fillOpacity(data, drawWidth, drawHeight, actualHeight, comps);\n    }\n    if (this.needsDecode) {\n      this.decodeBuffer(comps);\n    }\n    this.colorSpace.fillRgb(data, originalWidth, originalHeight, drawWidth, drawHeight, actualHeight, bpc, comps, alpha01);\n    if (maybeUndoPreblend) {\n      this.undoPreblend(data, drawWidth, actualHeight);\n    }\n    if (isOffscreenCanvasSupported && !mustBeResized) {\n      ctx.putImageData(canvasImgData, 0, 0);\n      const bitmap = canvas.transferToImageBitmap();\n      return {\n        data: null,\n        width: drawWidth,\n        height: drawHeight,\n        bitmap,\n        interpolate: this.interpolate\n      };\n    }\n    imgData.data = data;\n    if (mustBeResized) {\n      return ImageResizer.createImage(imgData);\n    }\n    return imgData;\n  }\n  fillGrayBuffer(buffer) {\n    const numComps = this.numComps;\n    if (numComps !== 1) {\n      throw new FormatError(`Reading gray scale from a color image: ${numComps}`);\n    }\n    const width = this.width;\n    const height = this.height;\n    const bpc = this.bpc;\n    const rowBytes = width * numComps * bpc + 7 >> 3;\n    const imgArray = this.getImageBytes(height * rowBytes, {\n      internal: true\n    });\n    const comps = this.getComponents(imgArray);\n    let i, length;\n    if (bpc === 1) {\n      length = width * height;\n      if (this.needsDecode) {\n        for (i = 0; i < length; ++i) {\n          buffer[i] = comps[i] - 1 & 255;\n        }\n      } else {\n        for (i = 0; i < length; ++i) {\n          buffer[i] = -comps[i] & 255;\n        }\n      }\n      return;\n    }\n    if (this.needsDecode) {\n      this.decodeBuffer(comps);\n    }\n    length = width * height;\n    const scale = 255 / ((1 << bpc) - 1);\n    for (i = 0; i < length; ++i) {\n      buffer[i] = scale * comps[i];\n    }\n  }\n  createBitmap(kind, width, height, src) {\n    const canvas = new OffscreenCanvas(width, height);\n    const ctx = canvas.getContext(\"2d\");\n    let imgData;\n    if (kind === ImageKind.RGBA_32BPP) {\n      imgData = new ImageData(src, width, height);\n    } else {\n      imgData = ctx.createImageData(width, height);\n      convertToRGBA({\n        kind,\n        src,\n        dest: new Uint32Array(imgData.data.buffer),\n        width,\n        height,\n        inverseDecode: this.needsDecode\n      });\n    }\n    ctx.putImageData(imgData, 0, 0);\n    const bitmap = canvas.transferToImageBitmap();\n    return {\n      data: null,\n      width,\n      height,\n      bitmap,\n      interpolate: this.interpolate\n    };\n  }\n  getImageBytes(length, {\n    drawWidth,\n    drawHeight,\n    forceRGBA = false,\n    forceRGB = false,\n    internal = false\n  }) {\n    this.image.reset();\n    this.image.drawWidth = drawWidth || this.width;\n    this.image.drawHeight = drawHeight || this.height;\n    this.image.forceRGBA = !!forceRGBA;\n    this.image.forceRGB = !!forceRGB;\n    const imageBytes = this.image.getBytes(length, this.ignoreColorSpace);\n    if (internal || this.image instanceof DecodeStream) {\n      return imageBytes;\n    }\n    assert(imageBytes instanceof Uint8Array, 'PDFImage.getImageBytes: Unsupported \"imageBytes\" type.');\n    return new Uint8Array(imageBytes);\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/evaluator.js\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst DefaultPartialEvaluatorOptions = Object.freeze({\n  maxImageSize: -1,\n  disableFontFace: false,\n  ignoreErrors: false,\n  isEvalSupported: true,\n  isOffscreenCanvasSupported: false,\n  canvasMaxAreaInBytes: -1,\n  fontExtraProperties: false,\n  useSystemFonts: true,\n  cMapUrl: null,\n  standardFontDataUrl: null\n});\nconst PatternType = {\n  TILING: 1,\n  SHADING: 2\n};\nconst TEXT_CHUNK_BATCH_SIZE = 10;\nconst deferred = Promise.resolve();\nfunction normalizeBlendMode(value, parsingArray = false) {\n  if (Array.isArray(value)) {\n    for (const val of value) {\n      const maybeBM = normalizeBlendMode(val, true);\n      if (maybeBM) {\n        return maybeBM;\n      }\n    }\n    warn(`Unsupported blend mode Array: ${value}`);\n    return \"source-over\";\n  }\n  if (!(value instanceof Name)) {\n    if (parsingArray) {\n      return null;\n    }\n    return \"source-over\";\n  }\n  switch (value.name) {\n    case \"Normal\":\n    case \"Compatible\":\n      return \"source-over\";\n    case \"Multiply\":\n      return \"multiply\";\n    case \"Screen\":\n      return \"screen\";\n    case \"Overlay\":\n      return \"overlay\";\n    case \"Darken\":\n      return \"darken\";\n    case \"Lighten\":\n      return \"lighten\";\n    case \"ColorDodge\":\n      return \"color-dodge\";\n    case \"ColorBurn\":\n      return \"color-burn\";\n    case \"HardLight\":\n      return \"hard-light\";\n    case \"SoftLight\":\n      return \"soft-light\";\n    case \"Difference\":\n      return \"difference\";\n    case \"Exclusion\":\n      return \"exclusion\";\n    case \"Hue\":\n      return \"hue\";\n    case \"Saturation\":\n      return \"saturation\";\n    case \"Color\":\n      return \"color\";\n    case \"Luminosity\":\n      return \"luminosity\";\n  }\n  if (parsingArray) {\n    return null;\n  }\n  warn(`Unsupported blend mode: ${value.name}`);\n  return \"source-over\";\n}\nfunction incrementCachedImageMaskCount(data) {\n  if (data.fn === OPS.paintImageMaskXObject && data.args[0]?.count > 0) {\n    data.args[0].count++;\n  }\n}\nclass TimeSlotManager {\n  static TIME_SLOT_DURATION_MS = 20;\n  static CHECK_TIME_EVERY = 100;\n  constructor() {\n    this.reset();\n  }\n  check() {\n    if (++this.checked < TimeSlotManager.CHECK_TIME_EVERY) {\n      return false;\n    }\n    this.checked = 0;\n    return this.endTime <= Date.now();\n  }\n  reset() {\n    this.endTime = Date.now() + TimeSlotManager.TIME_SLOT_DURATION_MS;\n    this.checked = 0;\n  }\n}\nclass PartialEvaluator {\n  constructor({\n    xref,\n    handler,\n    pageIndex,\n    idFactory,\n    fontCache,\n    builtInCMapCache,\n    standardFontDataCache,\n    globalImageCache,\n    systemFontCache,\n    options = null\n  }) {\n    this.xref = xref;\n    this.handler = handler;\n    this.pageIndex = pageIndex;\n    this.idFactory = idFactory;\n    this.fontCache = fontCache;\n    this.builtInCMapCache = builtInCMapCache;\n    this.standardFontDataCache = standardFontDataCache;\n    this.globalImageCache = globalImageCache;\n    this.systemFontCache = systemFontCache;\n    this.options = options || DefaultPartialEvaluatorOptions;\n    this.parsingType3Font = false;\n    this._regionalImageCache = new RegionalImageCache();\n    this._fetchBuiltInCMapBound = this.fetchBuiltInCMap.bind(this);\n    ImageResizer.setMaxArea(this.options.canvasMaxAreaInBytes);\n  }\n  get _pdfFunctionFactory() {\n    const pdfFunctionFactory = new PDFFunctionFactory({\n      xref: this.xref,\n      isEvalSupported: this.options.isEvalSupported\n    });\n    return shadow(this, \"_pdfFunctionFactory\", pdfFunctionFactory);\n  }\n  clone(newOptions = null) {\n    const newEvaluator = Object.create(this);\n    newEvaluator.options = Object.assign(Object.create(null), this.options, newOptions);\n    return newEvaluator;\n  }\n  hasBlendModes(resources, nonBlendModesSet) {\n    if (!(resources instanceof Dict)) {\n      return false;\n    }\n    if (resources.objId && nonBlendModesSet.has(resources.objId)) {\n      return false;\n    }\n    const processed = new RefSet(nonBlendModesSet);\n    if (resources.objId) {\n      processed.put(resources.objId);\n    }\n    const nodes = [resources],\n      xref = this.xref;\n    while (nodes.length) {\n      const node = nodes.shift();\n      const graphicStates = node.get(\"ExtGState\");\n      if (graphicStates instanceof Dict) {\n        for (let graphicState of graphicStates.getRawValues()) {\n          if (graphicState instanceof Ref) {\n            if (processed.has(graphicState)) {\n              continue;\n            }\n            try {\n              graphicState = xref.fetch(graphicState);\n            } catch (ex) {\n              processed.put(graphicState);\n              info(`hasBlendModes - ignoring ExtGState: \"${ex}\".`);\n              continue;\n            }\n          }\n          if (!(graphicState instanceof Dict)) {\n            continue;\n          }\n          if (graphicState.objId) {\n            processed.put(graphicState.objId);\n          }\n          const bm = graphicState.get(\"BM\");\n          if (bm instanceof Name) {\n            if (bm.name !== \"Normal\") {\n              return true;\n            }\n            continue;\n          }\n          if (bm !== undefined && Array.isArray(bm)) {\n            for (const element of bm) {\n              if (element instanceof Name && element.name !== \"Normal\") {\n                return true;\n              }\n            }\n          }\n        }\n      }\n      const xObjects = node.get(\"XObject\");\n      if (!(xObjects instanceof Dict)) {\n        continue;\n      }\n      for (let xObject of xObjects.getRawValues()) {\n        if (xObject instanceof Ref) {\n          if (processed.has(xObject)) {\n            continue;\n          }\n          try {\n            xObject = xref.fetch(xObject);\n          } catch (ex) {\n            processed.put(xObject);\n            info(`hasBlendModes - ignoring XObject: \"${ex}\".`);\n            continue;\n          }\n        }\n        if (!(xObject instanceof BaseStream)) {\n          continue;\n        }\n        if (xObject.dict.objId) {\n          processed.put(xObject.dict.objId);\n        }\n        const xResources = xObject.dict.get(\"Resources\");\n        if (!(xResources instanceof Dict)) {\n          continue;\n        }\n        if (xResources.objId && processed.has(xResources.objId)) {\n          continue;\n        }\n        nodes.push(xResources);\n        if (xResources.objId) {\n          processed.put(xResources.objId);\n        }\n      }\n    }\n    for (const ref of processed) {\n      nonBlendModesSet.put(ref);\n    }\n    return false;\n  }\n  async fetchBuiltInCMap(name) {\n    const cachedData = this.builtInCMapCache.get(name);\n    if (cachedData) {\n      return cachedData;\n    }\n    let data;\n    if (this.options.cMapUrl !== null) {\n      const url = `${this.options.cMapUrl}${name}.bcmap`;\n      const response = await fetch(url);\n      if (!response.ok) {\n        throw new Error(`fetchBuiltInCMap: failed to fetch file \"${url}\" with \"${response.statusText}\".`);\n      }\n      data = {\n        cMapData: new Uint8Array(await response.arrayBuffer()),\n        compressionType: CMapCompressionType.BINARY\n      };\n    } else {\n      data = await this.handler.sendWithPromise(\"FetchBuiltInCMap\", {\n        name\n      });\n    }\n    if (data.compressionType !== CMapCompressionType.NONE) {\n      this.builtInCMapCache.set(name, data);\n    }\n    return data;\n  }\n  async fetchStandardFontData(name) {\n    const cachedData = this.standardFontDataCache.get(name);\n    if (cachedData) {\n      return new Stream(cachedData);\n    }\n    if (this.options.useSystemFonts && name !== \"Symbol\" && name !== \"ZapfDingbats\") {\n      return null;\n    }\n    const standardFontNameToFileName = getFontNameToFileMap(),\n      filename = standardFontNameToFileName[name];\n    let data;\n    if (this.options.standardFontDataUrl !== null) {\n      const url = `${this.options.standardFontDataUrl}${filename}`;\n      const response = await fetch(url);\n      if (!response.ok) {\n        warn(`fetchStandardFontData: failed to fetch file \"${url}\" with \"${response.statusText}\".`);\n      } else {\n        data = new Uint8Array(await response.arrayBuffer());\n      }\n    } else {\n      try {\n        data = await this.handler.sendWithPromise(\"FetchStandardFontData\", {\n          filename\n        });\n      } catch (e) {\n        warn(`fetchStandardFontData: failed to fetch file \"${filename}\" with \"${e}\".`);\n      }\n    }\n    if (!data) {\n      return null;\n    }\n    this.standardFontDataCache.set(name, data);\n    return new Stream(data);\n  }\n  async buildFormXObject(resources, xobj, smask, operatorList, task, initialState, localColorSpaceCache) {\n    const dict = xobj.dict;\n    const matrix = dict.getArray(\"Matrix\");\n    let bbox = dict.getArray(\"BBox\");\n    bbox = Array.isArray(bbox) && bbox.length === 4 ? Util.normalizeRect(bbox) : null;\n    let optionalContent, groupOptions;\n    if (dict.has(\"OC\")) {\n      optionalContent = await this.parseMarkedContentProps(dict.get(\"OC\"), resources);\n    }\n    if (optionalContent !== undefined) {\n      operatorList.addOp(OPS.beginMarkedContentProps, [\"OC\", optionalContent]);\n    }\n    const group = dict.get(\"Group\");\n    if (group) {\n      groupOptions = {\n        matrix,\n        bbox,\n        smask,\n        isolated: false,\n        knockout: false\n      };\n      const groupSubtype = group.get(\"S\");\n      let colorSpace = null;\n      if (isName(groupSubtype, \"Transparency\")) {\n        groupOptions.isolated = group.get(\"I\") || false;\n        groupOptions.knockout = group.get(\"K\") || false;\n        if (group.has(\"CS\")) {\n          const cs = group.getRaw(\"CS\");\n          const cachedColorSpace = ColorSpace.getCached(cs, this.xref, localColorSpaceCache);\n          if (cachedColorSpace) {\n            colorSpace = cachedColorSpace;\n          } else {\n            colorSpace = await this.parseColorSpace({\n              cs,\n              resources,\n              localColorSpaceCache\n            });\n          }\n        }\n      }\n      if (smask?.backdrop) {\n        colorSpace ||= ColorSpace.singletons.rgb;\n        smask.backdrop = colorSpace.getRgb(smask.backdrop, 0);\n      }\n      operatorList.addOp(OPS.beginGroup, [groupOptions]);\n    }\n    const args = group ? [matrix, null] : [matrix, bbox];\n    operatorList.addOp(OPS.paintFormXObjectBegin, args);\n    await this.getOperatorList({\n      stream: xobj,\n      task,\n      resources: dict.get(\"Resources\") || resources,\n      operatorList,\n      initialState\n    });\n    operatorList.addOp(OPS.paintFormXObjectEnd, []);\n    if (group) {\n      operatorList.addOp(OPS.endGroup, [groupOptions]);\n    }\n    if (optionalContent !== undefined) {\n      operatorList.addOp(OPS.endMarkedContent, []);\n    }\n  }\n  _sendImgData(objId, imgData, cacheGlobally = false) {\n    const transfers = imgData ? [imgData.bitmap || imgData.data.buffer] : null;\n    if (this.parsingType3Font || cacheGlobally) {\n      return this.handler.send(\"commonobj\", [objId, \"Image\", imgData], transfers);\n    }\n    return this.handler.send(\"obj\", [objId, this.pageIndex, \"Image\", imgData], transfers);\n  }\n  async buildPaintImageXObject({\n    resources,\n    image,\n    isInline = false,\n    operatorList,\n    cacheKey,\n    localImageCache,\n    localColorSpaceCache\n  }) {\n    const dict = image.dict;\n    const imageRef = dict.objId;\n    const w = dict.get(\"W\", \"Width\");\n    const h = dict.get(\"H\", \"Height\");\n    if (!(w && typeof w === \"number\") || !(h && typeof h === \"number\")) {\n      warn(\"Image dimensions are missing, or not numbers.\");\n      return;\n    }\n    const maxImageSize = this.options.maxImageSize;\n    if (maxImageSize !== -1 && w * h > maxImageSize) {\n      const msg = \"Image exceeded maximum allowed size and was removed.\";\n      if (this.options.ignoreErrors) {\n        warn(msg);\n        return;\n      }\n      throw new Error(msg);\n    }\n    let optionalContent;\n    if (dict.has(\"OC\")) {\n      optionalContent = await this.parseMarkedContentProps(dict.get(\"OC\"), resources);\n    }\n    const imageMask = dict.get(\"IM\", \"ImageMask\") || false;\n    let imgData, args;\n    if (imageMask) {\n      const interpolate = dict.get(\"I\", \"Interpolate\");\n      const bitStrideLength = w + 7 >> 3;\n      const imgArray = image.getBytes(bitStrideLength * h);\n      const decode = dict.getArray(\"D\", \"Decode\");\n      if (this.parsingType3Font) {\n        imgData = PDFImage.createRawMask({\n          imgArray,\n          width: w,\n          height: h,\n          imageIsFromDecodeStream: image instanceof DecodeStream,\n          inverseDecode: decode?.[0] > 0,\n          interpolate\n        });\n        imgData.cached = !!cacheKey;\n        args = [imgData];\n        operatorList.addImageOps(OPS.paintImageMaskXObject, args, optionalContent);\n        if (cacheKey) {\n          const cacheData = {\n            fn: OPS.paintImageMaskXObject,\n            args,\n            optionalContent\n          };\n          localImageCache.set(cacheKey, imageRef, cacheData);\n          if (imageRef) {\n            this._regionalImageCache.set(null, imageRef, cacheData);\n          }\n        }\n        return;\n      }\n      imgData = await PDFImage.createMask({\n        imgArray,\n        width: w,\n        height: h,\n        imageIsFromDecodeStream: image instanceof DecodeStream,\n        inverseDecode: decode?.[0] > 0,\n        interpolate,\n        isOffscreenCanvasSupported: this.options.isOffscreenCanvasSupported\n      });\n      if (imgData.isSingleOpaquePixel) {\n        operatorList.addImageOps(OPS.paintSolidColorImageMask, [], optionalContent);\n        if (cacheKey) {\n          const cacheData = {\n            fn: OPS.paintSolidColorImageMask,\n            args: [],\n            optionalContent\n          };\n          localImageCache.set(cacheKey, imageRef, cacheData);\n          if (imageRef) {\n            this._regionalImageCache.set(null, imageRef, cacheData);\n          }\n        }\n        return;\n      }\n      const objId = `mask_${this.idFactory.createObjId()}`;\n      operatorList.addDependency(objId);\n      imgData.dataLen = imgData.bitmap ? imgData.width * imgData.height * 4 : imgData.data.length;\n      this._sendImgData(objId, imgData);\n      args = [{\n        data: objId,\n        width: imgData.width,\n        height: imgData.height,\n        interpolate: imgData.interpolate,\n        count: 1\n      }];\n      operatorList.addImageOps(OPS.paintImageMaskXObject, args, optionalContent);\n      if (cacheKey) {\n        const cacheData = {\n          fn: OPS.paintImageMaskXObject,\n          args,\n          optionalContent\n        };\n        localImageCache.set(cacheKey, imageRef, cacheData);\n        if (imageRef) {\n          this._regionalImageCache.set(null, imageRef, cacheData);\n        }\n      }\n      return;\n    }\n    const SMALL_IMAGE_DIMENSIONS = 200;\n    if (isInline && w + h < SMALL_IMAGE_DIMENSIONS && !dict.has(\"SMask\") && !dict.has(\"Mask\")) {\n      try {\n        const imageObj = new PDFImage({\n          xref: this.xref,\n          res: resources,\n          image,\n          isInline,\n          pdfFunctionFactory: this._pdfFunctionFactory,\n          localColorSpaceCache\n        });\n        imgData = await imageObj.createImageData(true, false);\n        operatorList.isOffscreenCanvasSupported = this.options.isOffscreenCanvasSupported;\n        operatorList.addImageOps(OPS.paintInlineImageXObject, [imgData], optionalContent);\n      } catch (reason) {\n        const msg = `Unable to decode inline image: \"${reason}\".`;\n        if (!this.options.ignoreErrors) {\n          throw new Error(msg);\n        }\n        warn(msg);\n      }\n      return;\n    }\n    let objId = `img_${this.idFactory.createObjId()}`,\n      cacheGlobally = false;\n    if (this.parsingType3Font) {\n      objId = `${this.idFactory.getDocId()}_type3_${objId}`;\n    } else if (cacheKey && imageRef) {\n      cacheGlobally = this.globalImageCache.shouldCache(imageRef, this.pageIndex);\n      if (cacheGlobally) {\n        assert(!isInline, \"Cannot cache an inline image globally.\");\n        objId = `${this.idFactory.getDocId()}_${objId}`;\n      }\n    }\n    operatorList.addDependency(objId);\n    args = [objId, w, h];\n    operatorList.addImageOps(OPS.paintImageXObject, args, optionalContent);\n    if (cacheGlobally && (w * h > 250000 || dict.has(\"SMask\") || dict.has(\"Mask\"))) {\n      const localLength = await this.handler.sendWithPromise(\"commonobj\", [objId, \"CopyLocalImage\", {\n        imageRef\n      }]);\n      if (localLength) {\n        this.globalImageCache.setData(imageRef, {\n          objId,\n          fn: OPS.paintImageXObject,\n          args,\n          optionalContent,\n          byteSize: 0\n        });\n        this.globalImageCache.addByteSize(imageRef, localLength);\n        return;\n      }\n    }\n    PDFImage.buildImage({\n      xref: this.xref,\n      res: resources,\n      image,\n      isInline,\n      pdfFunctionFactory: this._pdfFunctionFactory,\n      localColorSpaceCache\n    }).then(async imageObj => {\n      imgData = await imageObj.createImageData(false, this.options.isOffscreenCanvasSupported);\n      imgData.dataLen = imgData.bitmap ? imgData.width * imgData.height * 4 : imgData.data.length;\n      imgData.ref = imageRef;\n      if (cacheGlobally) {\n        this.globalImageCache.addByteSize(imageRef, imgData.dataLen);\n      }\n      return this._sendImgData(objId, imgData, cacheGlobally);\n    }).catch(reason => {\n      warn(`Unable to decode image \"${objId}\": \"${reason}\".`);\n      return this._sendImgData(objId, null, cacheGlobally);\n    });\n    if (cacheKey) {\n      const cacheData = {\n        fn: OPS.paintImageXObject,\n        args,\n        optionalContent\n      };\n      localImageCache.set(cacheKey, imageRef, cacheData);\n      if (imageRef) {\n        this._regionalImageCache.set(null, imageRef, cacheData);\n        if (cacheGlobally) {\n          this.globalImageCache.setData(imageRef, {\n            objId,\n            fn: OPS.paintImageXObject,\n            args,\n            optionalContent,\n            byteSize: 0\n          });\n        }\n      }\n    }\n  }\n  handleSMask(smask, resources, operatorList, task, stateManager, localColorSpaceCache) {\n    const smaskContent = smask.get(\"G\");\n    const smaskOptions = {\n      subtype: smask.get(\"S\").name,\n      backdrop: smask.get(\"BC\")\n    };\n    const transferObj = smask.get(\"TR\");\n    if (isPDFFunction(transferObj)) {\n      const transferFn = this._pdfFunctionFactory.create(transferObj);\n      const transferMap = new Uint8Array(256);\n      const tmp = new Float32Array(1);\n      for (let i = 0; i < 256; i++) {\n        tmp[0] = i / 255;\n        transferFn(tmp, 0, tmp, 0);\n        transferMap[i] = tmp[0] * 255 | 0;\n      }\n      smaskOptions.transferMap = transferMap;\n    }\n    return this.buildFormXObject(resources, smaskContent, smaskOptions, operatorList, task, stateManager.state.clone(), localColorSpaceCache);\n  }\n  handleTransferFunction(tr) {\n    let transferArray;\n    if (Array.isArray(tr)) {\n      transferArray = tr;\n    } else if (isPDFFunction(tr)) {\n      transferArray = [tr];\n    } else {\n      return null;\n    }\n    const transferMaps = [];\n    let numFns = 0,\n      numEffectfulFns = 0;\n    for (const entry of transferArray) {\n      const transferObj = this.xref.fetchIfRef(entry);\n      numFns++;\n      if (isName(transferObj, \"Identity\")) {\n        transferMaps.push(null);\n        continue;\n      } else if (!isPDFFunction(transferObj)) {\n        return null;\n      }\n      const transferFn = this._pdfFunctionFactory.create(transferObj);\n      const transferMap = new Uint8Array(256),\n        tmp = new Float32Array(1);\n      for (let j = 0; j < 256; j++) {\n        tmp[0] = j / 255;\n        transferFn(tmp, 0, tmp, 0);\n        transferMap[j] = tmp[0] * 255 | 0;\n      }\n      transferMaps.push(transferMap);\n      numEffectfulFns++;\n    }\n    if (!(numFns === 1 || numFns === 4)) {\n      return null;\n    }\n    if (numEffectfulFns === 0) {\n      return null;\n    }\n    return transferMaps;\n  }\n  handleTilingType(fn, color, resources, pattern, patternDict, operatorList, task, localTilingPatternCache) {\n    const tilingOpList = new OperatorList();\n    const patternResources = Dict.merge({\n      xref: this.xref,\n      dictArray: [patternDict.get(\"Resources\"), resources]\n    });\n    return this.getOperatorList({\n      stream: pattern,\n      task,\n      resources: patternResources,\n      operatorList: tilingOpList\n    }).then(function () {\n      const operatorListIR = tilingOpList.getIR();\n      const tilingPatternIR = getTilingPatternIR(operatorListIR, patternDict, color);\n      operatorList.addDependencies(tilingOpList.dependencies);\n      operatorList.addOp(fn, tilingPatternIR);\n      if (patternDict.objId) {\n        localTilingPatternCache.set(null, patternDict.objId, {\n          operatorListIR,\n          dict: patternDict\n        });\n      }\n    }).catch(reason => {\n      if (reason instanceof AbortException) {\n        return;\n      }\n      if (this.options.ignoreErrors) {\n        warn(`handleTilingType - ignoring pattern: \"${reason}\".`);\n        return;\n      }\n      throw reason;\n    });\n  }\n  async handleSetFont(resources, fontArgs, fontRef, operatorList, task, state, fallbackFontDict = null, cssFontInfo = null) {\n    const fontName = fontArgs?.[0] instanceof Name ? fontArgs[0].name : null;\n    let translated = await this.loadFont(fontName, fontRef, resources, fallbackFontDict, cssFontInfo);\n    if (translated.font.isType3Font) {\n      try {\n        await translated.loadType3Data(this, resources, task);\n        operatorList.addDependencies(translated.type3Dependencies);\n      } catch (reason) {\n        translated = new TranslatedFont({\n          loadedName: \"g_font_error\",\n          font: new ErrorFont(`Type3 font load error: ${reason}`),\n          dict: translated.font,\n          evaluatorOptions: this.options\n        });\n      }\n    }\n    state.font = translated.font;\n    translated.send(this.handler);\n    return translated.loadedName;\n  }\n  handleText(chars, state) {\n    const font = state.font;\n    const glyphs = font.charsToGlyphs(chars);\n    if (font.data) {\n      const isAddToPathSet = !!(state.textRenderingMode & TextRenderingMode.ADD_TO_PATH_FLAG);\n      if (isAddToPathSet || state.fillColorSpace.name === \"Pattern\" || font.disableFontFace || this.options.disableFontFace) {\n        PartialEvaluator.buildFontPaths(font, glyphs, this.handler, this.options);\n      }\n    }\n    return glyphs;\n  }\n  ensureStateFont(state) {\n    if (state.font) {\n      return;\n    }\n    const reason = new FormatError(\"Missing setFont (Tf) operator before text rendering operator.\");\n    if (this.options.ignoreErrors) {\n      warn(`ensureStateFont: \"${reason}\".`);\n      return;\n    }\n    throw reason;\n  }\n  async setGState({\n    resources,\n    gState,\n    operatorList,\n    cacheKey,\n    task,\n    stateManager,\n    localGStateCache,\n    localColorSpaceCache\n  }) {\n    const gStateRef = gState.objId;\n    let isSimpleGState = true;\n    const gStateObj = [];\n    let promise = Promise.resolve();\n    for (const key of gState.getKeys()) {\n      const value = gState.get(key);\n      switch (key) {\n        case \"Type\":\n          break;\n        case \"LW\":\n        case \"LC\":\n        case \"LJ\":\n        case \"ML\":\n        case \"D\":\n        case \"RI\":\n        case \"FL\":\n        case \"CA\":\n        case \"ca\":\n          gStateObj.push([key, value]);\n          break;\n        case \"Font\":\n          isSimpleGState = false;\n          promise = promise.then(() => this.handleSetFont(resources, null, value[0], operatorList, task, stateManager.state).then(function (loadedName) {\n            operatorList.addDependency(loadedName);\n            gStateObj.push([key, [loadedName, value[1]]]);\n          }));\n          break;\n        case \"BM\":\n          gStateObj.push([key, normalizeBlendMode(value)]);\n          break;\n        case \"SMask\":\n          if (isName(value, \"None\")) {\n            gStateObj.push([key, false]);\n            break;\n          }\n          if (value instanceof Dict) {\n            isSimpleGState = false;\n            promise = promise.then(() => this.handleSMask(value, resources, operatorList, task, stateManager, localColorSpaceCache));\n            gStateObj.push([key, true]);\n          } else {\n            warn(\"Unsupported SMask type\");\n          }\n          break;\n        case \"TR\":\n          const transferMaps = this.handleTransferFunction(value);\n          gStateObj.push([key, transferMaps]);\n          break;\n        case \"OP\":\n        case \"op\":\n        case \"OPM\":\n        case \"BG\":\n        case \"BG2\":\n        case \"UCR\":\n        case \"UCR2\":\n        case \"TR2\":\n        case \"HT\":\n        case \"SM\":\n        case \"SA\":\n        case \"AIS\":\n        case \"TK\":\n          info(\"graphic state operator \" + key);\n          break;\n        default:\n          info(\"Unknown graphic state operator \" + key);\n          break;\n      }\n    }\n    await promise;\n    if (gStateObj.length > 0) {\n      operatorList.addOp(OPS.setGState, [gStateObj]);\n    }\n    if (isSimpleGState) {\n      localGStateCache.set(cacheKey, gStateRef, gStateObj);\n    }\n  }\n  loadFont(fontName, font, resources, fallbackFontDict = null, cssFontInfo = null) {\n    const errorFont = async () => {\n      return new TranslatedFont({\n        loadedName: \"g_font_error\",\n        font: new ErrorFont(`Font \"${fontName}\" is not available.`),\n        dict: font,\n        evaluatorOptions: this.options\n      });\n    };\n    let fontRef;\n    if (font) {\n      if (font instanceof Ref) {\n        fontRef = font;\n      }\n    } else {\n      const fontRes = resources.get(\"Font\");\n      if (fontRes) {\n        fontRef = fontRes.getRaw(fontName);\n      }\n    }\n    if (fontRef) {\n      if (this.parsingType3Font && this.type3FontRefs.has(fontRef)) {\n        return errorFont();\n      }\n      if (this.fontCache.has(fontRef)) {\n        return this.fontCache.get(fontRef);\n      }\n      font = this.xref.fetchIfRef(fontRef);\n    }\n    if (!(font instanceof Dict)) {\n      if (!this.options.ignoreErrors && !this.parsingType3Font) {\n        warn(`Font \"${fontName}\" is not available.`);\n        return errorFont();\n      }\n      warn(`Font \"${fontName}\" is not available -- attempting to fallback to a default font.`);\n      font = fallbackFontDict || PartialEvaluator.fallbackFontDict;\n    }\n    if (font.cacheKey && this.fontCache.has(font.cacheKey)) {\n      return this.fontCache.get(font.cacheKey);\n    }\n    const {\n      promise,\n      resolve\n    } = Promise.withResolvers();\n    let preEvaluatedFont;\n    try {\n      preEvaluatedFont = this.preEvaluateFont(font);\n      preEvaluatedFont.cssFontInfo = cssFontInfo;\n    } catch (reason) {\n      warn(`loadFont - preEvaluateFont failed: \"${reason}\".`);\n      return errorFont();\n    }\n    const {\n      descriptor,\n      hash\n    } = preEvaluatedFont;\n    const fontRefIsRef = fontRef instanceof Ref;\n    let fontID;\n    if (hash && descriptor instanceof Dict) {\n      const fontAliases = descriptor.fontAliases ||= Object.create(null);\n      if (fontAliases[hash]) {\n        const aliasFontRef = fontAliases[hash].aliasRef;\n        if (fontRefIsRef && aliasFontRef && this.fontCache.has(aliasFontRef)) {\n          this.fontCache.putAlias(fontRef, aliasFontRef);\n          return this.fontCache.get(fontRef);\n        }\n      } else {\n        fontAliases[hash] = {\n          fontID: this.idFactory.createFontId()\n        };\n      }\n      if (fontRefIsRef) {\n        fontAliases[hash].aliasRef = fontRef;\n      }\n      fontID = fontAliases[hash].fontID;\n    } else {\n      fontID = this.idFactory.createFontId();\n    }\n    assert(fontID?.startsWith(\"f\"), 'The \"fontID\" must be (correctly) defined.');\n    if (fontRefIsRef) {\n      this.fontCache.put(fontRef, promise);\n    } else {\n      font.cacheKey = `cacheKey_${fontID}`;\n      this.fontCache.put(font.cacheKey, promise);\n    }\n    font.loadedName = `${this.idFactory.getDocId()}_${fontID}`;\n    this.translateFont(preEvaluatedFont).then(translatedFont => {\n      resolve(new TranslatedFont({\n        loadedName: font.loadedName,\n        font: translatedFont,\n        dict: font,\n        evaluatorOptions: this.options\n      }));\n    }).catch(reason => {\n      warn(`loadFont - translateFont failed: \"${reason}\".`);\n      resolve(new TranslatedFont({\n        loadedName: font.loadedName,\n        font: new ErrorFont(reason instanceof Error ? reason.message : reason),\n        dict: font,\n        evaluatorOptions: this.options\n      }));\n    });\n    return promise;\n  }\n  buildPath(operatorList, fn, args, parsingText = false) {\n    const lastIndex = operatorList.length - 1;\n    if (!args) {\n      args = [];\n    }\n    if (lastIndex < 0 || operatorList.fnArray[lastIndex] !== OPS.constructPath) {\n      if (parsingText) {\n        warn(`Encountered path operator \"${fn}\" inside of a text object.`);\n        operatorList.addOp(OPS.save, null);\n      }\n      let minMax;\n      switch (fn) {\n        case OPS.rectangle:\n          const x = args[0] + args[2];\n          const y = args[1] + args[3];\n          minMax = [Math.min(args[0], x), Math.min(args[1], y), Math.max(args[0], x), Math.max(args[1], y)];\n          break;\n        case OPS.moveTo:\n        case OPS.lineTo:\n          minMax = [args[0], args[1], args[0], args[1]];\n          break;\n        default:\n          minMax = [Infinity, Infinity, -Infinity, -Infinity];\n          break;\n      }\n      operatorList.addOp(OPS.constructPath, [[fn], args, minMax]);\n      if (parsingText) {\n        operatorList.addOp(OPS.restore, null);\n      }\n    } else {\n      const opArgs = operatorList.argsArray[lastIndex];\n      opArgs[0].push(fn);\n      opArgs[1].push(...args);\n      const minMax = opArgs[2];\n      switch (fn) {\n        case OPS.rectangle:\n          const x = args[0] + args[2];\n          const y = args[1] + args[3];\n          minMax[0] = Math.min(minMax[0], args[0], x);\n          minMax[1] = Math.min(minMax[1], args[1], y);\n          minMax[2] = Math.max(minMax[2], args[0], x);\n          minMax[3] = Math.max(minMax[3], args[1], y);\n          break;\n        case OPS.moveTo:\n        case OPS.lineTo:\n          minMax[0] = Math.min(minMax[0], args[0]);\n          minMax[1] = Math.min(minMax[1], args[1]);\n          minMax[2] = Math.max(minMax[2], args[0]);\n          minMax[3] = Math.max(minMax[3], args[1]);\n          break;\n      }\n    }\n  }\n  parseColorSpace({\n    cs,\n    resources,\n    localColorSpaceCache\n  }) {\n    return ColorSpace.parseAsync({\n      cs,\n      xref: this.xref,\n      resources,\n      pdfFunctionFactory: this._pdfFunctionFactory,\n      localColorSpaceCache\n    }).catch(reason => {\n      if (reason instanceof AbortException) {\n        return null;\n      }\n      if (this.options.ignoreErrors) {\n        warn(`parseColorSpace - ignoring ColorSpace: \"${reason}\".`);\n        return null;\n      }\n      throw reason;\n    });\n  }\n  parseShading({\n    shading,\n    resources,\n    localColorSpaceCache,\n    localShadingPatternCache\n  }) {\n    let id = localShadingPatternCache.get(shading);\n    if (id) {\n      return id;\n    }\n    let patternIR;\n    try {\n      const shadingFill = Pattern.parseShading(shading, this.xref, resources, this._pdfFunctionFactory, localColorSpaceCache);\n      patternIR = shadingFill.getIR();\n    } catch (reason) {\n      if (reason instanceof AbortException) {\n        return null;\n      }\n      if (this.options.ignoreErrors) {\n        warn(`parseShading - ignoring shading: \"${reason}\".`);\n        localShadingPatternCache.set(shading, null);\n        return null;\n      }\n      throw reason;\n    }\n    id = `pattern_${this.idFactory.createObjId()}`;\n    if (this.parsingType3Font) {\n      id = `${this.idFactory.getDocId()}_type3_${id}`;\n    }\n    localShadingPatternCache.set(shading, id);\n    if (this.parsingType3Font) {\n      this.handler.send(\"commonobj\", [id, \"Pattern\", patternIR]);\n    } else {\n      this.handler.send(\"obj\", [id, this.pageIndex, \"Pattern\", patternIR]);\n    }\n    return id;\n  }\n  handleColorN(operatorList, fn, args, cs, patterns, resources, task, localColorSpaceCache, localTilingPatternCache, localShadingPatternCache) {\n    const patternName = args.pop();\n    if (patternName instanceof Name) {\n      const rawPattern = patterns.getRaw(patternName.name);\n      const localTilingPattern = rawPattern instanceof Ref && localTilingPatternCache.getByRef(rawPattern);\n      if (localTilingPattern) {\n        try {\n          const color = cs.base ? cs.base.getRgb(args, 0) : null;\n          const tilingPatternIR = getTilingPatternIR(localTilingPattern.operatorListIR, localTilingPattern.dict, color);\n          operatorList.addOp(fn, tilingPatternIR);\n          return undefined;\n        } catch {}\n      }\n      const pattern = this.xref.fetchIfRef(rawPattern);\n      if (pattern) {\n        const dict = pattern instanceof BaseStream ? pattern.dict : pattern;\n        const typeNum = dict.get(\"PatternType\");\n        if (typeNum === PatternType.TILING) {\n          const color = cs.base ? cs.base.getRgb(args, 0) : null;\n          return this.handleTilingType(fn, color, resources, pattern, dict, operatorList, task, localTilingPatternCache);\n        } else if (typeNum === PatternType.SHADING) {\n          const shading = dict.get(\"Shading\");\n          const objId = this.parseShading({\n            shading,\n            resources,\n            localColorSpaceCache,\n            localShadingPatternCache\n          });\n          if (objId) {\n            const matrix = dict.getArray(\"Matrix\");\n            operatorList.addOp(fn, [\"Shading\", objId, matrix]);\n          }\n          return undefined;\n        }\n        throw new FormatError(`Unknown PatternType: ${typeNum}`);\n      }\n    }\n    throw new FormatError(`Unknown PatternName: ${patternName}`);\n  }\n  _parseVisibilityExpression(array, nestingCounter, currentResult) {\n    const MAX_NESTING = 10;\n    if (++nestingCounter > MAX_NESTING) {\n      warn(\"Visibility expression is too deeply nested\");\n      return;\n    }\n    const length = array.length;\n    const operator = this.xref.fetchIfRef(array[0]);\n    if (length < 2 || !(operator instanceof Name)) {\n      warn(\"Invalid visibility expression\");\n      return;\n    }\n    switch (operator.name) {\n      case \"And\":\n      case \"Or\":\n      case \"Not\":\n        currentResult.push(operator.name);\n        break;\n      default:\n        warn(`Invalid operator ${operator.name} in visibility expression`);\n        return;\n    }\n    for (let i = 1; i < length; i++) {\n      const raw = array[i];\n      const object = this.xref.fetchIfRef(raw);\n      if (Array.isArray(object)) {\n        const nestedResult = [];\n        currentResult.push(nestedResult);\n        this._parseVisibilityExpression(object, nestingCounter, nestedResult);\n      } else if (raw instanceof Ref) {\n        currentResult.push(raw.toString());\n      }\n    }\n  }\n  async parseMarkedContentProps(contentProperties, resources) {\n    let optionalContent;\n    if (contentProperties instanceof Name) {\n      const properties = resources.get(\"Properties\");\n      optionalContent = properties.get(contentProperties.name);\n    } else if (contentProperties instanceof Dict) {\n      optionalContent = contentProperties;\n    } else {\n      throw new FormatError(\"Optional content properties malformed.\");\n    }\n    const optionalContentType = optionalContent.get(\"Type\")?.name;\n    if (optionalContentType === \"OCG\") {\n      return {\n        type: optionalContentType,\n        id: optionalContent.objId\n      };\n    } else if (optionalContentType === \"OCMD\") {\n      const expression = optionalContent.get(\"VE\");\n      if (Array.isArray(expression)) {\n        const result = [];\n        this._parseVisibilityExpression(expression, 0, result);\n        if (result.length > 0) {\n          return {\n            type: \"OCMD\",\n            expression: result\n          };\n        }\n      }\n      const optionalContentGroups = optionalContent.get(\"OCGs\");\n      if (Array.isArray(optionalContentGroups) || optionalContentGroups instanceof Dict) {\n        const groupIds = [];\n        if (Array.isArray(optionalContentGroups)) {\n          for (const ocg of optionalContentGroups) {\n            groupIds.push(ocg.toString());\n          }\n        } else {\n          groupIds.push(optionalContentGroups.objId);\n        }\n        return {\n          type: optionalContentType,\n          ids: groupIds,\n          policy: optionalContent.get(\"P\") instanceof Name ? optionalContent.get(\"P\").name : null,\n          expression: null\n        };\n      } else if (optionalContentGroups instanceof Ref) {\n        return {\n          type: optionalContentType,\n          id: optionalContentGroups.toString()\n        };\n      }\n    }\n    return null;\n  }\n  getOperatorList({\n    stream,\n    task,\n    resources,\n    operatorList,\n    initialState = null,\n    fallbackFontDict = null\n  }) {\n    resources ||= Dict.empty;\n    initialState ||= new EvalState();\n    if (!operatorList) {\n      throw new Error('getOperatorList: missing \"operatorList\" parameter');\n    }\n    const self = this;\n    const xref = this.xref;\n    let parsingText = false;\n    const localImageCache = new LocalImageCache();\n    const localColorSpaceCache = new LocalColorSpaceCache();\n    const localGStateCache = new LocalGStateCache();\n    const localTilingPatternCache = new LocalTilingPatternCache();\n    const localShadingPatternCache = new Map();\n    const xobjs = resources.get(\"XObject\") || Dict.empty;\n    const patterns = resources.get(\"Pattern\") || Dict.empty;\n    const stateManager = new StateManager(initialState);\n    const preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager);\n    const timeSlotManager = new TimeSlotManager();\n    function closePendingRestoreOPS(argument) {\n      for (let i = 0, ii = preprocessor.savedStatesDepth; i < ii; i++) {\n        operatorList.addOp(OPS.restore, []);\n      }\n    }\n    return new Promise(function promiseBody(resolve, reject) {\n      const next = function (promise) {\n        Promise.all([promise, operatorList.ready]).then(function () {\n          try {\n            promiseBody(resolve, reject);\n          } catch (ex) {\n            reject(ex);\n          }\n        }, reject);\n      };\n      task.ensureNotTerminated();\n      timeSlotManager.reset();\n      const operation = {};\n      let stop, i, ii, cs, name, isValidName;\n      while (!(stop = timeSlotManager.check())) {\n        operation.args = null;\n        if (!preprocessor.read(operation)) {\n          break;\n        }\n        let args = operation.args;\n        let fn = operation.fn;\n        switch (fn | 0) {\n          case OPS.paintXObject:\n            isValidName = args[0] instanceof Name;\n            name = args[0].name;\n            if (isValidName) {\n              const localImage = localImageCache.getByName(name);\n              if (localImage) {\n                operatorList.addImageOps(localImage.fn, localImage.args, localImage.optionalContent);\n                incrementCachedImageMaskCount(localImage);\n                args = null;\n                continue;\n              }\n            }\n            next(new Promise(function (resolveXObject, rejectXObject) {\n              if (!isValidName) {\n                throw new FormatError(\"XObject must be referred to by name.\");\n              }\n              let xobj = xobjs.getRaw(name);\n              if (xobj instanceof Ref) {\n                const localImage = localImageCache.getByRef(xobj) || self._regionalImageCache.getByRef(xobj);\n                if (localImage) {\n                  operatorList.addImageOps(localImage.fn, localImage.args, localImage.optionalContent);\n                  incrementCachedImageMaskCount(localImage);\n                  resolveXObject();\n                  return;\n                }\n                const globalImage = self.globalImageCache.getData(xobj, self.pageIndex);\n                if (globalImage) {\n                  operatorList.addDependency(globalImage.objId);\n                  operatorList.addImageOps(globalImage.fn, globalImage.args, globalImage.optionalContent);\n                  resolveXObject();\n                  return;\n                }\n                xobj = xref.fetch(xobj);\n              }\n              if (!(xobj instanceof BaseStream)) {\n                throw new FormatError(\"XObject should be a stream\");\n              }\n              const type = xobj.dict.get(\"Subtype\");\n              if (!(type instanceof Name)) {\n                throw new FormatError(\"XObject should have a Name subtype\");\n              }\n              if (type.name === \"Form\") {\n                stateManager.save();\n                self.buildFormXObject(resources, xobj, null, operatorList, task, stateManager.state.clone(), localColorSpaceCache).then(function () {\n                  stateManager.restore();\n                  resolveXObject();\n                }, rejectXObject);\n                return;\n              } else if (type.name === \"Image\") {\n                self.buildPaintImageXObject({\n                  resources,\n                  image: xobj,\n                  operatorList,\n                  cacheKey: name,\n                  localImageCache,\n                  localColorSpaceCache\n                }).then(resolveXObject, rejectXObject);\n                return;\n              } else if (type.name === \"PS\") {\n                info(\"Ignored XObject subtype PS\");\n              } else {\n                throw new FormatError(`Unhandled XObject subtype ${type.name}`);\n              }\n              resolveXObject();\n            }).catch(function (reason) {\n              if (reason instanceof AbortException) {\n                return;\n              }\n              if (self.options.ignoreErrors) {\n                warn(`getOperatorList - ignoring XObject: \"${reason}\".`);\n                return;\n              }\n              throw reason;\n            }));\n            return;\n          case OPS.setFont:\n            var fontSize = args[1];\n            next(self.handleSetFont(resources, args, null, operatorList, task, stateManager.state, fallbackFontDict).then(function (loadedName) {\n              operatorList.addDependency(loadedName);\n              operatorList.addOp(OPS.setFont, [loadedName, fontSize]);\n            }));\n            return;\n          case OPS.beginText:\n            parsingText = true;\n            break;\n          case OPS.endText:\n            parsingText = false;\n            break;\n          case OPS.endInlineImage:\n            var cacheKey = args[0].cacheKey;\n            if (cacheKey) {\n              const localImage = localImageCache.getByName(cacheKey);\n              if (localImage) {\n                operatorList.addImageOps(localImage.fn, localImage.args, localImage.optionalContent);\n                incrementCachedImageMaskCount(localImage);\n                args = null;\n                continue;\n              }\n            }\n            next(self.buildPaintImageXObject({\n              resources,\n              image: args[0],\n              isInline: true,\n              operatorList,\n              cacheKey,\n              localImageCache,\n              localColorSpaceCache\n            }));\n            return;\n          case OPS.showText:\n            if (!stateManager.state.font) {\n              self.ensureStateFont(stateManager.state);\n              continue;\n            }\n            args[0] = self.handleText(args[0], stateManager.state);\n            break;\n          case OPS.showSpacedText:\n            if (!stateManager.state.font) {\n              self.ensureStateFont(stateManager.state);\n              continue;\n            }\n            var combinedGlyphs = [];\n            var state = stateManager.state;\n            for (const arrItem of args[0]) {\n              if (typeof arrItem === \"string\") {\n                combinedGlyphs.push(...self.handleText(arrItem, state));\n              } else if (typeof arrItem === \"number\") {\n                combinedGlyphs.push(arrItem);\n              }\n            }\n            args[0] = combinedGlyphs;\n            fn = OPS.showText;\n            break;\n          case OPS.nextLineShowText:\n            if (!stateManager.state.font) {\n              self.ensureStateFont(stateManager.state);\n              continue;\n            }\n            operatorList.addOp(OPS.nextLine);\n            args[0] = self.handleText(args[0], stateManager.state);\n            fn = OPS.showText;\n            break;\n          case OPS.nextLineSetSpacingShowText:\n            if (!stateManager.state.font) {\n              self.ensureStateFont(stateManager.state);\n              continue;\n            }\n            operatorList.addOp(OPS.nextLine);\n            operatorList.addOp(OPS.setWordSpacing, [args.shift()]);\n            operatorList.addOp(OPS.setCharSpacing, [args.shift()]);\n            args[0] = self.handleText(args[0], stateManager.state);\n            fn = OPS.showText;\n            break;\n          case OPS.setTextRenderingMode:\n            stateManager.state.textRenderingMode = args[0];\n            break;\n          case OPS.setFillColorSpace:\n            {\n              const cachedColorSpace = ColorSpace.getCached(args[0], xref, localColorSpaceCache);\n              if (cachedColorSpace) {\n                stateManager.state.fillColorSpace = cachedColorSpace;\n                continue;\n              }\n              next(self.parseColorSpace({\n                cs: args[0],\n                resources,\n                localColorSpaceCache\n              }).then(function (colorSpace) {\n                if (colorSpace) {\n                  stateManager.state.fillColorSpace = colorSpace;\n                }\n              }));\n              return;\n            }\n          case OPS.setStrokeColorSpace:\n            {\n              const cachedColorSpace = ColorSpace.getCached(args[0], xref, localColorSpaceCache);\n              if (cachedColorSpace) {\n                stateManager.state.strokeColorSpace = cachedColorSpace;\n                continue;\n              }\n              next(self.parseColorSpace({\n                cs: args[0],\n                resources,\n                localColorSpaceCache\n              }).then(function (colorSpace) {\n                if (colorSpace) {\n                  stateManager.state.strokeColorSpace = colorSpace;\n                }\n              }));\n              return;\n            }\n          case OPS.setFillColor:\n            cs = stateManager.state.fillColorSpace;\n            args = cs.getRgb(args, 0);\n            fn = OPS.setFillRGBColor;\n            break;\n          case OPS.setStrokeColor:\n            cs = stateManager.state.strokeColorSpace;\n            args = cs.getRgb(args, 0);\n            fn = OPS.setStrokeRGBColor;\n            break;\n          case OPS.setFillGray:\n            stateManager.state.fillColorSpace = ColorSpace.singletons.gray;\n            args = ColorSpace.singletons.gray.getRgb(args, 0);\n            fn = OPS.setFillRGBColor;\n            break;\n          case OPS.setStrokeGray:\n            stateManager.state.strokeColorSpace = ColorSpace.singletons.gray;\n            args = ColorSpace.singletons.gray.getRgb(args, 0);\n            fn = OPS.setStrokeRGBColor;\n            break;\n          case OPS.setFillCMYKColor:\n            stateManager.state.fillColorSpace = ColorSpace.singletons.cmyk;\n            args = ColorSpace.singletons.cmyk.getRgb(args, 0);\n            fn = OPS.setFillRGBColor;\n            break;\n          case OPS.setStrokeCMYKColor:\n            stateManager.state.strokeColorSpace = ColorSpace.singletons.cmyk;\n            args = ColorSpace.singletons.cmyk.getRgb(args, 0);\n            fn = OPS.setStrokeRGBColor;\n            break;\n          case OPS.setFillRGBColor:\n            stateManager.state.fillColorSpace = ColorSpace.singletons.rgb;\n            args = ColorSpace.singletons.rgb.getRgb(args, 0);\n            break;\n          case OPS.setStrokeRGBColor:\n            stateManager.state.strokeColorSpace = ColorSpace.singletons.rgb;\n            args = ColorSpace.singletons.rgb.getRgb(args, 0);\n            break;\n          case OPS.setFillColorN:\n            cs = stateManager.state.fillColorSpace;\n            if (cs.name === \"Pattern\") {\n              next(self.handleColorN(operatorList, OPS.setFillColorN, args, cs, patterns, resources, task, localColorSpaceCache, localTilingPatternCache, localShadingPatternCache));\n              return;\n            }\n            args = cs.getRgb(args, 0);\n            fn = OPS.setFillRGBColor;\n            break;\n          case OPS.setStrokeColorN:\n            cs = stateManager.state.strokeColorSpace;\n            if (cs.name === \"Pattern\") {\n              next(self.handleColorN(operatorList, OPS.setStrokeColorN, args, cs, patterns, resources, task, localColorSpaceCache, localTilingPatternCache, localShadingPatternCache));\n              return;\n            }\n            args = cs.getRgb(args, 0);\n            fn = OPS.setStrokeRGBColor;\n            break;\n          case OPS.shadingFill:\n            var shadingRes = resources.get(\"Shading\");\n            if (!shadingRes) {\n              throw new FormatError(\"No shading resource found\");\n            }\n            var shading = shadingRes.get(args[0].name);\n            if (!shading) {\n              throw new FormatError(\"No shading object found\");\n            }\n            const patternId = self.parseShading({\n              shading,\n              resources,\n              localColorSpaceCache,\n              localShadingPatternCache\n            });\n            if (!patternId) {\n              continue;\n            }\n            args = [patternId];\n            fn = OPS.shadingFill;\n            break;\n          case OPS.setGState:\n            isValidName = args[0] instanceof Name;\n            name = args[0].name;\n            if (isValidName) {\n              const localGStateObj = localGStateCache.getByName(name);\n              if (localGStateObj) {\n                if (localGStateObj.length > 0) {\n                  operatorList.addOp(OPS.setGState, [localGStateObj]);\n                }\n                args = null;\n                continue;\n              }\n            }\n            next(new Promise(function (resolveGState, rejectGState) {\n              if (!isValidName) {\n                throw new FormatError(\"GState must be referred to by name.\");\n              }\n              const extGState = resources.get(\"ExtGState\");\n              if (!(extGState instanceof Dict)) {\n                throw new FormatError(\"ExtGState should be a dictionary.\");\n              }\n              const gState = extGState.get(name);\n              if (!(gState instanceof Dict)) {\n                throw new FormatError(\"GState should be a dictionary.\");\n              }\n              self.setGState({\n                resources,\n                gState,\n                operatorList,\n                cacheKey: name,\n                task,\n                stateManager,\n                localGStateCache,\n                localColorSpaceCache\n              }).then(resolveGState, rejectGState);\n            }).catch(function (reason) {\n              if (reason instanceof AbortException) {\n                return;\n              }\n              if (self.options.ignoreErrors) {\n                warn(`getOperatorList - ignoring ExtGState: \"${reason}\".`);\n                return;\n              }\n              throw reason;\n            }));\n            return;\n          case OPS.moveTo:\n          case OPS.lineTo:\n          case OPS.curveTo:\n          case OPS.curveTo2:\n          case OPS.curveTo3:\n          case OPS.closePath:\n          case OPS.rectangle:\n            self.buildPath(operatorList, fn, args, parsingText);\n            continue;\n          case OPS.markPoint:\n          case OPS.markPointProps:\n          case OPS.beginCompat:\n          case OPS.endCompat:\n            continue;\n          case OPS.beginMarkedContentProps:\n            if (!(args[0] instanceof Name)) {\n              warn(`Expected name for beginMarkedContentProps arg0=${args[0]}`);\n              operatorList.addOp(OPS.beginMarkedContentProps, [\"OC\", null]);\n              continue;\n            }\n            if (args[0].name === \"OC\") {\n              next(self.parseMarkedContentProps(args[1], resources).then(data => {\n                operatorList.addOp(OPS.beginMarkedContentProps, [\"OC\", data]);\n              }).catch(reason => {\n                if (reason instanceof AbortException) {\n                  return;\n                }\n                if (self.options.ignoreErrors) {\n                  warn(`getOperatorList - ignoring beginMarkedContentProps: \"${reason}\".`);\n                  operatorList.addOp(OPS.beginMarkedContentProps, [\"OC\", null]);\n                  return;\n                }\n                throw reason;\n              }));\n              return;\n            }\n            args = [args[0].name, args[1] instanceof Dict ? args[1].get(\"MCID\") : null];\n            break;\n          case OPS.beginMarkedContent:\n          case OPS.endMarkedContent:\n          default:\n            if (args !== null) {\n              for (i = 0, ii = args.length; i < ii; i++) {\n                if (args[i] instanceof Dict) {\n                  break;\n                }\n              }\n              if (i < ii) {\n                warn(\"getOperatorList - ignoring operator: \" + fn);\n                continue;\n              }\n            }\n        }\n        operatorList.addOp(fn, args);\n      }\n      if (stop) {\n        next(deferred);\n        return;\n      }\n      closePendingRestoreOPS();\n      resolve();\n    }).catch(reason => {\n      if (reason instanceof AbortException) {\n        return;\n      }\n      if (this.options.ignoreErrors) {\n        warn(`getOperatorList - ignoring errors during \"${task.name}\" ` + `task: \"${reason}\".`);\n        closePendingRestoreOPS();\n        return;\n      }\n      throw reason;\n    });\n  }\n  getTextContent({\n    stream,\n    task,\n    resources,\n    stateManager = null,\n    includeMarkedContent = false,\n    sink,\n    seenStyles = new Set(),\n    viewBox,\n    markedContentData = null,\n    disableNormalization = false,\n    keepWhiteSpace = false\n  }) {\n    resources ||= Dict.empty;\n    stateManager ||= new StateManager(new TextState());\n    if (includeMarkedContent) {\n      markedContentData ||= {\n        level: 0\n      };\n    }\n    const textContent = {\n      items: [],\n      styles: Object.create(null)\n    };\n    const textContentItem = {\n      initialized: false,\n      str: [],\n      totalWidth: 0,\n      totalHeight: 0,\n      width: 0,\n      height: 0,\n      vertical: false,\n      prevTransform: null,\n      textAdvanceScale: 0,\n      spaceInFlowMin: 0,\n      spaceInFlowMax: 0,\n      trackingSpaceMin: Infinity,\n      negativeSpaceMax: -Infinity,\n      notASpace: -Infinity,\n      transform: null,\n      fontName: null,\n      hasEOL: false\n    };\n    const twoLastChars = [\" \", \" \"];\n    let twoLastCharsPos = 0;\n    function saveLastChar(char) {\n      const nextPos = (twoLastCharsPos + 1) % 2;\n      const ret = twoLastChars[twoLastCharsPos] !== \" \" && twoLastChars[nextPos] === \" \";\n      twoLastChars[twoLastCharsPos] = char;\n      twoLastCharsPos = nextPos;\n      return !keepWhiteSpace && ret;\n    }\n    function shouldAddWhitepsace() {\n      return !keepWhiteSpace && twoLastChars[twoLastCharsPos] !== \" \" && twoLastChars[(twoLastCharsPos + 1) % 2] === \" \";\n    }\n    function resetLastChars() {\n      twoLastChars[0] = twoLastChars[1] = \" \";\n      twoLastCharsPos = 0;\n    }\n    const TRACKING_SPACE_FACTOR = 0.102;\n    const NOT_A_SPACE_FACTOR = 0.03;\n    const NEGATIVE_SPACE_FACTOR = -0.2;\n    const SPACE_IN_FLOW_MIN_FACTOR = 0.102;\n    const SPACE_IN_FLOW_MAX_FACTOR = 0.6;\n    const VERTICAL_SHIFT_RATIO = 0.25;\n    const self = this;\n    const xref = this.xref;\n    const showSpacedTextBuffer = [];\n    let xobjs = null;\n    const emptyXObjectCache = new LocalImageCache();\n    const emptyGStateCache = new LocalGStateCache();\n    const preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager);\n    let textState;\n    function pushWhitespace({\n      width = 0,\n      height = 0,\n      transform = textContentItem.prevTransform,\n      fontName = textContentItem.fontName\n    }) {\n      textContent.items.push({\n        str: \" \",\n        dir: \"ltr\",\n        width,\n        height,\n        transform,\n        fontName,\n        hasEOL: false\n      });\n    }\n    function getCurrentTextTransform() {\n      const font = textState.font;\n      const tsm = [textState.fontSize * textState.textHScale, 0, 0, textState.fontSize, 0, textState.textRise];\n      if (font.isType3Font && (textState.fontSize <= 1 || font.isCharBBox) && !isArrayEqual(textState.fontMatrix, FONT_IDENTITY_MATRIX)) {\n        const glyphHeight = font.bbox[3] - font.bbox[1];\n        if (glyphHeight > 0) {\n          tsm[3] *= glyphHeight * textState.fontMatrix[3];\n        }\n      }\n      return Util.transform(textState.ctm, Util.transform(textState.textMatrix, tsm));\n    }\n    function ensureTextContentItem() {\n      if (textContentItem.initialized) {\n        return textContentItem;\n      }\n      const {\n        font,\n        loadedName\n      } = textState;\n      if (!seenStyles.has(loadedName)) {\n        seenStyles.add(loadedName);\n        textContent.styles[loadedName] = {\n          fontFamily: font.fallbackName,\n          ascent: font.ascent,\n          descent: font.descent,\n          vertical: font.vertical\n        };\n        if (self.options.fontExtraProperties && font.systemFontInfo) {\n          const style = textContent.styles[loadedName];\n          style.fontSubstitution = font.systemFontInfo.css;\n          style.fontSubstitutionLoadedName = font.systemFontInfo.loadedName;\n        }\n      }\n      textContentItem.fontName = loadedName;\n      const trm = textContentItem.transform = getCurrentTextTransform();\n      if (!font.vertical) {\n        textContentItem.width = textContentItem.totalWidth = 0;\n        textContentItem.height = textContentItem.totalHeight = Math.hypot(trm[2], trm[3]);\n        textContentItem.vertical = false;\n      } else {\n        textContentItem.width = textContentItem.totalWidth = Math.hypot(trm[0], trm[1]);\n        textContentItem.height = textContentItem.totalHeight = 0;\n        textContentItem.vertical = true;\n      }\n      const scaleLineX = Math.hypot(textState.textLineMatrix[0], textState.textLineMatrix[1]);\n      const scaleCtmX = Math.hypot(textState.ctm[0], textState.ctm[1]);\n      textContentItem.textAdvanceScale = scaleCtmX * scaleLineX;\n      const {\n        fontSize\n      } = textState;\n      textContentItem.trackingSpaceMin = fontSize * TRACKING_SPACE_FACTOR;\n      textContentItem.notASpace = fontSize * NOT_A_SPACE_FACTOR;\n      textContentItem.negativeSpaceMax = fontSize * NEGATIVE_SPACE_FACTOR;\n      textContentItem.spaceInFlowMin = fontSize * SPACE_IN_FLOW_MIN_FACTOR;\n      textContentItem.spaceInFlowMax = fontSize * SPACE_IN_FLOW_MAX_FACTOR;\n      textContentItem.hasEOL = false;\n      textContentItem.initialized = true;\n      return textContentItem;\n    }\n    function updateAdvanceScale() {\n      if (!textContentItem.initialized) {\n        return;\n      }\n      const scaleLineX = Math.hypot(textState.textLineMatrix[0], textState.textLineMatrix[1]);\n      const scaleCtmX = Math.hypot(textState.ctm[0], textState.ctm[1]);\n      const scaleFactor = scaleCtmX * scaleLineX;\n      if (scaleFactor === textContentItem.textAdvanceScale) {\n        return;\n      }\n      if (!textContentItem.vertical) {\n        textContentItem.totalWidth += textContentItem.width * textContentItem.textAdvanceScale;\n        textContentItem.width = 0;\n      } else {\n        textContentItem.totalHeight += textContentItem.height * textContentItem.textAdvanceScale;\n        textContentItem.height = 0;\n      }\n      textContentItem.textAdvanceScale = scaleFactor;\n    }\n    function runBidiTransform(textChunk) {\n      let text = textChunk.str.join(\"\");\n      if (!disableNormalization) {\n        text = normalizeUnicode(text);\n      }\n      const bidiResult = bidi(text, -1, textChunk.vertical);\n      return {\n        str: bidiResult.str,\n        dir: bidiResult.dir,\n        width: Math.abs(textChunk.totalWidth),\n        height: Math.abs(textChunk.totalHeight),\n        transform: textChunk.transform,\n        fontName: textChunk.fontName,\n        hasEOL: textChunk.hasEOL\n      };\n    }\n    async function handleSetFont(fontName, fontRef) {\n      const translated = await self.loadFont(fontName, fontRef, resources);\n      if (translated.font.isType3Font) {\n        try {\n          await translated.loadType3Data(self, resources, task);\n        } catch {}\n      }\n      textState.loadedName = translated.loadedName;\n      textState.font = translated.font;\n      textState.fontMatrix = translated.font.fontMatrix || FONT_IDENTITY_MATRIX;\n    }\n    function applyInverseRotation(x, y, matrix) {\n      const scale = Math.hypot(matrix[0], matrix[1]);\n      return [(matrix[0] * x + matrix[1] * y) / scale, (matrix[2] * x + matrix[3] * y) / scale];\n    }\n    function compareWithLastPosition(glyphWidth) {\n      const currentTransform = getCurrentTextTransform();\n      let posX = currentTransform[4];\n      let posY = currentTransform[5];\n      if (textState.font?.vertical) {\n        if (posX < viewBox[0] || posX > viewBox[2] || posY + glyphWidth < viewBox[1] || posY > viewBox[3]) {\n          return false;\n        }\n      } else if (posX + glyphWidth < viewBox[0] || posX > viewBox[2] || posY < viewBox[1] || posY > viewBox[3]) {\n        return false;\n      }\n      if (!textState.font || !textContentItem.prevTransform) {\n        return true;\n      }\n      let lastPosX = textContentItem.prevTransform[4];\n      let lastPosY = textContentItem.prevTransform[5];\n      if (lastPosX === posX && lastPosY === posY) {\n        return true;\n      }\n      let rotate = -1;\n      if (currentTransform[0] && currentTransform[1] === 0 && currentTransform[2] === 0) {\n        rotate = currentTransform[0] > 0 ? 0 : 180;\n      } else if (currentTransform[1] && currentTransform[0] === 0 && currentTransform[3] === 0) {\n        rotate = currentTransform[1] > 0 ? 90 : 270;\n      }\n      switch (rotate) {\n        case 0:\n          break;\n        case 90:\n          [posX, posY] = [posY, posX];\n          [lastPosX, lastPosY] = [lastPosY, lastPosX];\n          break;\n        case 180:\n          [posX, posY, lastPosX, lastPosY] = [-posX, -posY, -lastPosX, -lastPosY];\n          break;\n        case 270:\n          [posX, posY] = [-posY, -posX];\n          [lastPosX, lastPosY] = [-lastPosY, -lastPosX];\n          break;\n        default:\n          [posX, posY] = applyInverseRotation(posX, posY, currentTransform);\n          [lastPosX, lastPosY] = applyInverseRotation(lastPosX, lastPosY, textContentItem.prevTransform);\n      }\n      if (textState.font.vertical) {\n        const advanceY = (lastPosY - posY) / textContentItem.textAdvanceScale;\n        const advanceX = posX - lastPosX;\n        const textOrientation = Math.sign(textContentItem.height);\n        if (advanceY < textOrientation * textContentItem.negativeSpaceMax) {\n          if (Math.abs(advanceX) > 0.5 * textContentItem.width) {\n            appendEOL();\n            return true;\n          }\n          resetLastChars();\n          flushTextContentItem();\n          return true;\n        }\n        if (Math.abs(advanceX) > textContentItem.width) {\n          appendEOL();\n          return true;\n        }\n        if (advanceY <= textOrientation * textContentItem.notASpace) {\n          resetLastChars();\n        }\n        if (advanceY <= textOrientation * textContentItem.trackingSpaceMin) {\n          if (shouldAddWhitepsace()) {\n            resetLastChars();\n            flushTextContentItem();\n            pushWhitespace({\n              height: Math.abs(advanceY)\n            });\n          } else {\n            textContentItem.height += advanceY;\n          }\n        } else if (!addFakeSpaces(advanceY, textContentItem.prevTransform, textOrientation)) {\n          if (textContentItem.str.length === 0) {\n            resetLastChars();\n            pushWhitespace({\n              height: Math.abs(advanceY)\n            });\n          } else {\n            textContentItem.height += advanceY;\n          }\n        }\n        if (Math.abs(advanceX) > textContentItem.width * VERTICAL_SHIFT_RATIO) {\n          flushTextContentItem();\n        }\n        return true;\n      }\n      const advanceX = (posX - lastPosX) / textContentItem.textAdvanceScale;\n      const advanceY = posY - lastPosY;\n      const textOrientation = Math.sign(textContentItem.width);\n      if (advanceX < textOrientation * textContentItem.negativeSpaceMax) {\n        if (Math.abs(advanceY) > 0.5 * textContentItem.height) {\n          appendEOL();\n          return true;\n        }\n        resetLastChars();\n        flushTextContentItem();\n        return true;\n      }\n      if (Math.abs(advanceY) > textContentItem.height) {\n        appendEOL();\n        return true;\n      }\n      if (advanceX <= textOrientation * textContentItem.notASpace) {\n        resetLastChars();\n      }\n      if (advanceX <= textOrientation * textContentItem.trackingSpaceMin) {\n        if (shouldAddWhitepsace()) {\n          resetLastChars();\n          flushTextContentItem();\n          pushWhitespace({\n            width: Math.abs(advanceX)\n          });\n        } else {\n          textContentItem.width += advanceX;\n        }\n      } else if (!addFakeSpaces(advanceX, textContentItem.prevTransform, textOrientation)) {\n        if (textContentItem.str.length === 0) {\n          resetLastChars();\n          pushWhitespace({\n            width: Math.abs(advanceX)\n          });\n        } else {\n          textContentItem.width += advanceX;\n        }\n      }\n      if (Math.abs(advanceY) > textContentItem.height * VERTICAL_SHIFT_RATIO) {\n        flushTextContentItem();\n      }\n      return true;\n    }\n    function buildTextContentItem({\n      chars,\n      extraSpacing\n    }) {\n      const font = textState.font;\n      if (!chars) {\n        const charSpacing = textState.charSpacing + extraSpacing;\n        if (charSpacing) {\n          if (!font.vertical) {\n            textState.translateTextMatrix(charSpacing * textState.textHScale, 0);\n          } else {\n            textState.translateTextMatrix(0, -charSpacing);\n          }\n        }\n        if (keepWhiteSpace) {\n          compareWithLastPosition(0);\n        }\n        return;\n      }\n      const glyphs = font.charsToGlyphs(chars);\n      const scale = textState.fontMatrix[0] * textState.fontSize;\n      for (let i = 0, ii = glyphs.length; i < ii; i++) {\n        const glyph = glyphs[i];\n        const {\n          category\n        } = glyph;\n        if (category.isInvisibleFormatMark) {\n          continue;\n        }\n        let charSpacing = textState.charSpacing + (i + 1 === ii ? extraSpacing : 0);\n        let glyphWidth = glyph.width;\n        if (font.vertical) {\n          glyphWidth = glyph.vmetric ? glyph.vmetric[0] : -glyphWidth;\n        }\n        let scaledDim = glyphWidth * scale;\n        if (!keepWhiteSpace && category.isWhitespace) {\n          if (!font.vertical) {\n            charSpacing += scaledDim + textState.wordSpacing;\n            textState.translateTextMatrix(charSpacing * textState.textHScale, 0);\n          } else {\n            charSpacing += -scaledDim + textState.wordSpacing;\n            textState.translateTextMatrix(0, -charSpacing);\n          }\n          saveLastChar(\" \");\n          continue;\n        }\n        if (!category.isZeroWidthDiacritic && !compareWithLastPosition(scaledDim)) {\n          if (!font.vertical) {\n            textState.translateTextMatrix(scaledDim * textState.textHScale, 0);\n          } else {\n            textState.translateTextMatrix(0, scaledDim);\n          }\n          continue;\n        }\n        const textChunk = ensureTextContentItem();\n        if (category.isZeroWidthDiacritic) {\n          scaledDim = 0;\n        }\n        if (!font.vertical) {\n          scaledDim *= textState.textHScale;\n          textState.translateTextMatrix(scaledDim, 0);\n          textChunk.width += scaledDim;\n        } else {\n          textState.translateTextMatrix(0, scaledDim);\n          scaledDim = Math.abs(scaledDim);\n          textChunk.height += scaledDim;\n        }\n        if (scaledDim) {\n          textChunk.prevTransform = getCurrentTextTransform();\n        }\n        const glyphUnicode = glyph.unicode;\n        if (saveLastChar(glyphUnicode)) {\n          textChunk.str.push(\" \");\n        }\n        textChunk.str.push(glyphUnicode);\n        if (charSpacing) {\n          if (!font.vertical) {\n            textState.translateTextMatrix(charSpacing * textState.textHScale, 0);\n          } else {\n            textState.translateTextMatrix(0, -charSpacing);\n          }\n        }\n      }\n    }\n    function appendEOL() {\n      resetLastChars();\n      if (textContentItem.initialized) {\n        textContentItem.hasEOL = true;\n        flushTextContentItem();\n      } else {\n        textContent.items.push({\n          str: \"\",\n          dir: \"ltr\",\n          width: 0,\n          height: 0,\n          transform: getCurrentTextTransform(),\n          fontName: textState.loadedName,\n          hasEOL: true\n        });\n      }\n    }\n    function addFakeSpaces(width, transf, textOrientation) {\n      if (textOrientation * textContentItem.spaceInFlowMin <= width && width <= textOrientation * textContentItem.spaceInFlowMax) {\n        if (textContentItem.initialized) {\n          resetLastChars();\n          textContentItem.str.push(\" \");\n        }\n        return false;\n      }\n      const fontName = textContentItem.fontName;\n      let height = 0;\n      if (textContentItem.vertical) {\n        height = width;\n        width = 0;\n      }\n      flushTextContentItem();\n      resetLastChars();\n      pushWhitespace({\n        width: Math.abs(width),\n        height: Math.abs(height),\n        transform: transf || getCurrentTextTransform(),\n        fontName\n      });\n      return true;\n    }\n    function flushTextContentItem() {\n      if (!textContentItem.initialized || !textContentItem.str) {\n        return;\n      }\n      if (!textContentItem.vertical) {\n        textContentItem.totalWidth += textContentItem.width * textContentItem.textAdvanceScale;\n      } else {\n        textContentItem.totalHeight += textContentItem.height * textContentItem.textAdvanceScale;\n      }\n      textContent.items.push(runBidiTransform(textContentItem));\n      textContentItem.initialized = false;\n      textContentItem.str.length = 0;\n    }\n    function enqueueChunk(batch = false) {\n      const length = textContent.items.length;\n      if (length === 0) {\n        return;\n      }\n      if (batch && length < TEXT_CHUNK_BATCH_SIZE) {\n        return;\n      }\n      sink.enqueue(textContent, length);\n      textContent.items = [];\n      textContent.styles = Object.create(null);\n    }\n    const timeSlotManager = new TimeSlotManager();\n    return new Promise(function promiseBody(resolve, reject) {\n      const next = function (promise) {\n        enqueueChunk(true);\n        Promise.all([promise, sink.ready]).then(function () {\n          try {\n            promiseBody(resolve, reject);\n          } catch (ex) {\n            reject(ex);\n          }\n        }, reject);\n      };\n      task.ensureNotTerminated();\n      timeSlotManager.reset();\n      const operation = {};\n      let stop,\n        args = [];\n      while (!(stop = timeSlotManager.check())) {\n        args.length = 0;\n        operation.args = args;\n        if (!preprocessor.read(operation)) {\n          break;\n        }\n        const previousState = textState;\n        textState = stateManager.state;\n        const fn = operation.fn;\n        args = operation.args;\n        switch (fn | 0) {\n          case OPS.setFont:\n            var fontNameArg = args[0].name,\n              fontSizeArg = args[1];\n            if (textState.font && fontNameArg === textState.fontName && fontSizeArg === textState.fontSize) {\n              break;\n            }\n            flushTextContentItem();\n            textState.fontName = fontNameArg;\n            textState.fontSize = fontSizeArg;\n            next(handleSetFont(fontNameArg, null));\n            return;\n          case OPS.setTextRise:\n            textState.textRise = args[0];\n            break;\n          case OPS.setHScale:\n            textState.textHScale = args[0] / 100;\n            break;\n          case OPS.setLeading:\n            textState.leading = args[0];\n            break;\n          case OPS.moveText:\n            textState.translateTextLineMatrix(args[0], args[1]);\n            textState.textMatrix = textState.textLineMatrix.slice();\n            break;\n          case OPS.setLeadingMoveText:\n            textState.leading = -args[1];\n            textState.translateTextLineMatrix(args[0], args[1]);\n            textState.textMatrix = textState.textLineMatrix.slice();\n            break;\n          case OPS.nextLine:\n            textState.carriageReturn();\n            break;\n          case OPS.setTextMatrix:\n            textState.setTextMatrix(args[0], args[1], args[2], args[3], args[4], args[5]);\n            textState.setTextLineMatrix(args[0], args[1], args[2], args[3], args[4], args[5]);\n            updateAdvanceScale();\n            break;\n          case OPS.setCharSpacing:\n            textState.charSpacing = args[0];\n            break;\n          case OPS.setWordSpacing:\n            textState.wordSpacing = args[0];\n            break;\n          case OPS.beginText:\n            textState.textMatrix = IDENTITY_MATRIX.slice();\n            textState.textLineMatrix = IDENTITY_MATRIX.slice();\n            break;\n          case OPS.showSpacedText:\n            if (!stateManager.state.font) {\n              self.ensureStateFont(stateManager.state);\n              continue;\n            }\n            const spaceFactor = (textState.font.vertical ? 1 : -1) * textState.fontSize / 1000;\n            const elements = args[0];\n            for (let i = 0, ii = elements.length; i < ii; i++) {\n              const item = elements[i];\n              if (typeof item === \"string\") {\n                showSpacedTextBuffer.push(item);\n              } else if (typeof item === \"number\" && item !== 0) {\n                const str = showSpacedTextBuffer.join(\"\");\n                showSpacedTextBuffer.length = 0;\n                buildTextContentItem({\n                  chars: str,\n                  extraSpacing: item * spaceFactor\n                });\n              }\n            }\n            if (showSpacedTextBuffer.length > 0) {\n              const str = showSpacedTextBuffer.join(\"\");\n              showSpacedTextBuffer.length = 0;\n              buildTextContentItem({\n                chars: str,\n                extraSpacing: 0\n              });\n            }\n            break;\n          case OPS.showText:\n            if (!stateManager.state.font) {\n              self.ensureStateFont(stateManager.state);\n              continue;\n            }\n            buildTextContentItem({\n              chars: args[0],\n              extraSpacing: 0\n            });\n            break;\n          case OPS.nextLineShowText:\n            if (!stateManager.state.font) {\n              self.ensureStateFont(stateManager.state);\n              continue;\n            }\n            textState.carriageReturn();\n            buildTextContentItem({\n              chars: args[0],\n              extraSpacing: 0\n            });\n            break;\n          case OPS.nextLineSetSpacingShowText:\n            if (!stateManager.state.font) {\n              self.ensureStateFont(stateManager.state);\n              continue;\n            }\n            textState.wordSpacing = args[0];\n            textState.charSpacing = args[1];\n            textState.carriageReturn();\n            buildTextContentItem({\n              chars: args[2],\n              extraSpacing: 0\n            });\n            break;\n          case OPS.paintXObject:\n            flushTextContentItem();\n            if (!xobjs) {\n              xobjs = resources.get(\"XObject\") || Dict.empty;\n            }\n            var isValidName = args[0] instanceof Name;\n            var name = args[0].name;\n            if (isValidName && emptyXObjectCache.getByName(name)) {\n              break;\n            }\n            next(new Promise(function (resolveXObject, rejectXObject) {\n              if (!isValidName) {\n                throw new FormatError(\"XObject must be referred to by name.\");\n              }\n              let xobj = xobjs.getRaw(name);\n              if (xobj instanceof Ref) {\n                if (emptyXObjectCache.getByRef(xobj)) {\n                  resolveXObject();\n                  return;\n                }\n                const globalImage = self.globalImageCache.getData(xobj, self.pageIndex);\n                if (globalImage) {\n                  resolveXObject();\n                  return;\n                }\n                xobj = xref.fetch(xobj);\n              }\n              if (!(xobj instanceof BaseStream)) {\n                throw new FormatError(\"XObject should be a stream\");\n              }\n              const type = xobj.dict.get(\"Subtype\");\n              if (!(type instanceof Name)) {\n                throw new FormatError(\"XObject should have a Name subtype\");\n              }\n              if (type.name !== \"Form\") {\n                emptyXObjectCache.set(name, xobj.dict.objId, true);\n                resolveXObject();\n                return;\n              }\n              const currentState = stateManager.state.clone();\n              const xObjStateManager = new StateManager(currentState);\n              const matrix = xobj.dict.getArray(\"Matrix\");\n              if (Array.isArray(matrix) && matrix.length === 6) {\n                xObjStateManager.transform(matrix);\n              }\n              enqueueChunk();\n              const sinkWrapper = {\n                enqueueInvoked: false,\n                enqueue(chunk, size) {\n                  this.enqueueInvoked = true;\n                  sink.enqueue(chunk, size);\n                },\n                get desiredSize() {\n                  return sink.desiredSize;\n                },\n                get ready() {\n                  return sink.ready;\n                }\n              };\n              self.getTextContent({\n                stream: xobj,\n                task,\n                resources: xobj.dict.get(\"Resources\") || resources,\n                stateManager: xObjStateManager,\n                includeMarkedContent,\n                sink: sinkWrapper,\n                seenStyles,\n                viewBox,\n                markedContentData,\n                disableNormalization,\n                keepWhiteSpace\n              }).then(function () {\n                if (!sinkWrapper.enqueueInvoked) {\n                  emptyXObjectCache.set(name, xobj.dict.objId, true);\n                }\n                resolveXObject();\n              }, rejectXObject);\n            }).catch(function (reason) {\n              if (reason instanceof AbortException) {\n                return;\n              }\n              if (self.options.ignoreErrors) {\n                warn(`getTextContent - ignoring XObject: \"${reason}\".`);\n                return;\n              }\n              throw reason;\n            }));\n            return;\n          case OPS.setGState:\n            isValidName = args[0] instanceof Name;\n            name = args[0].name;\n            if (isValidName && emptyGStateCache.getByName(name)) {\n              break;\n            }\n            next(new Promise(function (resolveGState, rejectGState) {\n              if (!isValidName) {\n                throw new FormatError(\"GState must be referred to by name.\");\n              }\n              const extGState = resources.get(\"ExtGState\");\n              if (!(extGState instanceof Dict)) {\n                throw new FormatError(\"ExtGState should be a dictionary.\");\n              }\n              const gState = extGState.get(name);\n              if (!(gState instanceof Dict)) {\n                throw new FormatError(\"GState should be a dictionary.\");\n              }\n              const gStateFont = gState.get(\"Font\");\n              if (!gStateFont) {\n                emptyGStateCache.set(name, gState.objId, true);\n                resolveGState();\n                return;\n              }\n              flushTextContentItem();\n              textState.fontName = null;\n              textState.fontSize = gStateFont[1];\n              handleSetFont(null, gStateFont[0]).then(resolveGState, rejectGState);\n            }).catch(function (reason) {\n              if (reason instanceof AbortException) {\n                return;\n              }\n              if (self.options.ignoreErrors) {\n                warn(`getTextContent - ignoring ExtGState: \"${reason}\".`);\n                return;\n              }\n              throw reason;\n            }));\n            return;\n          case OPS.beginMarkedContent:\n            flushTextContentItem();\n            if (includeMarkedContent) {\n              markedContentData.level++;\n              textContent.items.push({\n                type: \"beginMarkedContent\",\n                tag: args[0] instanceof Name ? args[0].name : null\n              });\n            }\n            break;\n          case OPS.beginMarkedContentProps:\n            flushTextContentItem();\n            if (includeMarkedContent) {\n              markedContentData.level++;\n              let mcid = null;\n              if (args[1] instanceof Dict) {\n                mcid = args[1].get(\"MCID\");\n              }\n              textContent.items.push({\n                type: \"beginMarkedContentProps\",\n                id: Number.isInteger(mcid) ? `${self.idFactory.getPageObjId()}_mc${mcid}` : null,\n                tag: args[0] instanceof Name ? args[0].name : null\n              });\n            }\n            break;\n          case OPS.endMarkedContent:\n            flushTextContentItem();\n            if (includeMarkedContent) {\n              if (markedContentData.level === 0) {\n                break;\n              }\n              markedContentData.level--;\n              textContent.items.push({\n                type: \"endMarkedContent\"\n              });\n            }\n            break;\n          case OPS.restore:\n            if (previousState && (previousState.font !== textState.font || previousState.fontSize !== textState.fontSize || previousState.fontName !== textState.fontName)) {\n              flushTextContentItem();\n            }\n            break;\n        }\n        if (textContent.items.length >= sink.desiredSize) {\n          stop = true;\n          break;\n        }\n      }\n      if (stop) {\n        next(deferred);\n        return;\n      }\n      flushTextContentItem();\n      enqueueChunk();\n      resolve();\n    }).catch(reason => {\n      if (reason instanceof AbortException) {\n        return;\n      }\n      if (this.options.ignoreErrors) {\n        warn(`getTextContent - ignoring errors during \"${task.name}\" ` + `task: \"${reason}\".`);\n        flushTextContentItem();\n        enqueueChunk();\n        return;\n      }\n      throw reason;\n    });\n  }\n  async extractDataStructures(dict, properties) {\n    const xref = this.xref;\n    let cidToGidBytes;\n    const toUnicodePromise = this.readToUnicode(properties.toUnicode);\n    if (properties.composite) {\n      const cidSystemInfo = dict.get(\"CIDSystemInfo\");\n      if (cidSystemInfo instanceof Dict) {\n        properties.cidSystemInfo = {\n          registry: stringToPDFString(cidSystemInfo.get(\"Registry\")),\n          ordering: stringToPDFString(cidSystemInfo.get(\"Ordering\")),\n          supplement: cidSystemInfo.get(\"Supplement\")\n        };\n      }\n      try {\n        const cidToGidMap = dict.get(\"CIDToGIDMap\");\n        if (cidToGidMap instanceof BaseStream) {\n          cidToGidBytes = cidToGidMap.getBytes();\n        }\n      } catch (ex) {\n        if (!this.options.ignoreErrors) {\n          throw ex;\n        }\n        warn(`extractDataStructures - ignoring CIDToGIDMap data: \"${ex}\".`);\n      }\n    }\n    const differences = [];\n    let baseEncodingName = null;\n    let encoding;\n    if (dict.has(\"Encoding\")) {\n      encoding = dict.get(\"Encoding\");\n      if (encoding instanceof Dict) {\n        baseEncodingName = encoding.get(\"BaseEncoding\");\n        baseEncodingName = baseEncodingName instanceof Name ? baseEncodingName.name : null;\n        if (encoding.has(\"Differences\")) {\n          const diffEncoding = encoding.get(\"Differences\");\n          let index = 0;\n          for (const entry of diffEncoding) {\n            const data = xref.fetchIfRef(entry);\n            if (typeof data === \"number\") {\n              index = data;\n            } else if (data instanceof Name) {\n              differences[index++] = data.name;\n            } else {\n              throw new FormatError(`Invalid entry in 'Differences' array: ${data}`);\n            }\n          }\n        }\n      } else if (encoding instanceof Name) {\n        baseEncodingName = encoding.name;\n      } else {\n        const msg = \"Encoding is not a Name nor a Dict\";\n        if (!this.options.ignoreErrors) {\n          throw new FormatError(msg);\n        }\n        warn(msg);\n      }\n      if (baseEncodingName !== \"MacRomanEncoding\" && baseEncodingName !== \"MacExpertEncoding\" && baseEncodingName !== \"WinAnsiEncoding\") {\n        baseEncodingName = null;\n      }\n    }\n    const nonEmbeddedFont = !properties.file || properties.isInternalFont,\n      isSymbolsFontName = getSymbolsFonts()[properties.name];\n    if (baseEncodingName && nonEmbeddedFont && isSymbolsFontName) {\n      baseEncodingName = null;\n    }\n    if (baseEncodingName) {\n      properties.defaultEncoding = getEncoding(baseEncodingName);\n    } else {\n      const isSymbolicFont = !!(properties.flags & FontFlags.Symbolic);\n      const isNonsymbolicFont = !!(properties.flags & FontFlags.Nonsymbolic);\n      encoding = StandardEncoding;\n      if (properties.type === \"TrueType\" && !isNonsymbolicFont) {\n        encoding = WinAnsiEncoding;\n      }\n      if (isSymbolicFont || isSymbolsFontName) {\n        encoding = MacRomanEncoding;\n        if (nonEmbeddedFont) {\n          if (/Symbol/i.test(properties.name)) {\n            encoding = SymbolSetEncoding;\n          } else if (/Dingbats/i.test(properties.name)) {\n            encoding = ZapfDingbatsEncoding;\n          } else if (/Wingdings/i.test(properties.name)) {\n            encoding = WinAnsiEncoding;\n          }\n        }\n      }\n      properties.defaultEncoding = encoding;\n    }\n    properties.differences = differences;\n    properties.baseEncodingName = baseEncodingName;\n    properties.hasEncoding = !!baseEncodingName || differences.length > 0;\n    properties.dict = dict;\n    properties.toUnicode = await toUnicodePromise;\n    const builtToUnicode = await this.buildToUnicode(properties);\n    properties.toUnicode = builtToUnicode;\n    if (cidToGidBytes) {\n      properties.cidToGidMap = this.readCidToGidMap(cidToGidBytes, builtToUnicode);\n    }\n    return properties;\n  }\n  _simpleFontToUnicode(properties, forceGlyphs = false) {\n    assert(!properties.composite, \"Must be a simple font.\");\n    const toUnicode = [];\n    const encoding = properties.defaultEncoding.slice();\n    const baseEncodingName = properties.baseEncodingName;\n    const differences = properties.differences;\n    for (const charcode in differences) {\n      const glyphName = differences[charcode];\n      if (glyphName === \".notdef\") {\n        continue;\n      }\n      encoding[charcode] = glyphName;\n    }\n    const glyphsUnicodeMap = getGlyphsUnicode();\n    for (const charcode in encoding) {\n      let glyphName = encoding[charcode];\n      if (glyphName === \"\") {\n        continue;\n      }\n      let unicode = glyphsUnicodeMap[glyphName];\n      if (unicode !== undefined) {\n        toUnicode[charcode] = String.fromCharCode(unicode);\n        continue;\n      }\n      let code = 0;\n      switch (glyphName[0]) {\n        case \"G\":\n          if (glyphName.length === 3) {\n            code = parseInt(glyphName.substring(1), 16);\n          }\n          break;\n        case \"g\":\n          if (glyphName.length === 5) {\n            code = parseInt(glyphName.substring(1), 16);\n          }\n          break;\n        case \"C\":\n        case \"c\":\n          if (glyphName.length >= 3 && glyphName.length <= 4) {\n            const codeStr = glyphName.substring(1);\n            if (forceGlyphs) {\n              code = parseInt(codeStr, 16);\n              break;\n            }\n            code = +codeStr;\n            if (Number.isNaN(code) && Number.isInteger(parseInt(codeStr, 16))) {\n              return this._simpleFontToUnicode(properties, true);\n            }\n          }\n          break;\n        case \"u\":\n          unicode = getUnicodeForGlyph(glyphName, glyphsUnicodeMap);\n          if (unicode !== -1) {\n            code = unicode;\n          }\n          break;\n        default:\n          switch (glyphName) {\n            case \"f_h\":\n            case \"f_t\":\n            case \"T_h\":\n              toUnicode[charcode] = glyphName.replaceAll(\"_\", \"\");\n              continue;\n          }\n          break;\n      }\n      if (code > 0 && code <= 0x10ffff && Number.isInteger(code)) {\n        if (baseEncodingName && code === +charcode) {\n          const baseEncoding = getEncoding(baseEncodingName);\n          if (baseEncoding && (glyphName = baseEncoding[charcode])) {\n            toUnicode[charcode] = String.fromCharCode(glyphsUnicodeMap[glyphName]);\n            continue;\n          }\n        }\n        toUnicode[charcode] = String.fromCodePoint(code);\n      }\n    }\n    return toUnicode;\n  }\n  async buildToUnicode(properties) {\n    properties.hasIncludedToUnicodeMap = properties.toUnicode?.length > 0;\n    if (properties.hasIncludedToUnicodeMap) {\n      if (!properties.composite && properties.hasEncoding) {\n        properties.fallbackToUnicode = this._simpleFontToUnicode(properties);\n      }\n      return properties.toUnicode;\n    }\n    if (!properties.composite) {\n      return new ToUnicodeMap(this._simpleFontToUnicode(properties));\n    }\n    if (properties.composite && (properties.cMap.builtInCMap && !(properties.cMap instanceof IdentityCMap) || properties.cidSystemInfo?.registry === \"Adobe\" && (properties.cidSystemInfo.ordering === \"GB1\" || properties.cidSystemInfo.ordering === \"CNS1\" || properties.cidSystemInfo.ordering === \"Japan1\" || properties.cidSystemInfo.ordering === \"Korea1\"))) {\n      const {\n        registry,\n        ordering\n      } = properties.cidSystemInfo;\n      const ucs2CMapName = Name.get(`${registry}-${ordering}-UCS2`);\n      const ucs2CMap = await CMapFactory.create({\n        encoding: ucs2CMapName,\n        fetchBuiltInCMap: this._fetchBuiltInCMapBound,\n        useCMap: null\n      });\n      const toUnicode = [],\n        buf = [];\n      properties.cMap.forEach(function (charcode, cid) {\n        if (cid > 0xffff) {\n          throw new FormatError(\"Max size of CID is 65,535\");\n        }\n        const ucs2 = ucs2CMap.lookup(cid);\n        if (ucs2) {\n          buf.length = 0;\n          for (let i = 0, ii = ucs2.length; i < ii; i += 2) {\n            buf.push((ucs2.charCodeAt(i) << 8) + ucs2.charCodeAt(i + 1));\n          }\n          toUnicode[charcode] = String.fromCharCode(...buf);\n        }\n      });\n      return new ToUnicodeMap(toUnicode);\n    }\n    return new IdentityToUnicodeMap(properties.firstChar, properties.lastChar);\n  }\n  async readToUnicode(cmapObj) {\n    if (!cmapObj) {\n      return null;\n    }\n    if (cmapObj instanceof Name) {\n      const cmap = await CMapFactory.create({\n        encoding: cmapObj,\n        fetchBuiltInCMap: this._fetchBuiltInCMapBound,\n        useCMap: null\n      });\n      if (cmap instanceof IdentityCMap) {\n        return new IdentityToUnicodeMap(0, 0xffff);\n      }\n      return new ToUnicodeMap(cmap.getMap());\n    }\n    if (cmapObj instanceof BaseStream) {\n      try {\n        const cmap = await CMapFactory.create({\n          encoding: cmapObj,\n          fetchBuiltInCMap: this._fetchBuiltInCMapBound,\n          useCMap: null\n        });\n        if (cmap instanceof IdentityCMap) {\n          return new IdentityToUnicodeMap(0, 0xffff);\n        }\n        const map = new Array(cmap.length);\n        cmap.forEach(function (charCode, token) {\n          if (typeof token === \"number\") {\n            map[charCode] = String.fromCodePoint(token);\n            return;\n          }\n          const str = [];\n          for (let k = 0; k < token.length; k += 2) {\n            const w1 = token.charCodeAt(k) << 8 | token.charCodeAt(k + 1);\n            if ((w1 & 0xf800) !== 0xd800) {\n              str.push(w1);\n              continue;\n            }\n            k += 2;\n            const w2 = token.charCodeAt(k) << 8 | token.charCodeAt(k + 1);\n            str.push(((w1 & 0x3ff) << 10) + (w2 & 0x3ff) + 0x10000);\n          }\n          map[charCode] = String.fromCodePoint(...str);\n        });\n        return new ToUnicodeMap(map);\n      } catch (reason) {\n        if (reason instanceof AbortException) {\n          return null;\n        }\n        if (this.options.ignoreErrors) {\n          warn(`readToUnicode - ignoring ToUnicode data: \"${reason}\".`);\n          return null;\n        }\n        throw reason;\n      }\n    }\n    return null;\n  }\n  readCidToGidMap(glyphsData, toUnicode) {\n    const result = [];\n    for (let j = 0, jj = glyphsData.length; j < jj; j++) {\n      const glyphID = glyphsData[j++] << 8 | glyphsData[j];\n      const code = j >> 1;\n      if (glyphID === 0 && !toUnicode.has(code)) {\n        continue;\n      }\n      result[code] = glyphID;\n    }\n    return result;\n  }\n  extractWidths(dict, descriptor, properties) {\n    const xref = this.xref;\n    let glyphsWidths = [];\n    let defaultWidth = 0;\n    const glyphsVMetrics = [];\n    let defaultVMetrics;\n    if (properties.composite) {\n      const dw = dict.get(\"DW\");\n      defaultWidth = Number.isInteger(dw) ? dw : 1000;\n      const widths = dict.get(\"W\");\n      if (Array.isArray(widths)) {\n        for (let i = 0, ii = widths.length; i < ii; i++) {\n          let start = xref.fetchIfRef(widths[i++]);\n          if (!Number.isInteger(start)) {\n            break;\n          }\n          const code = xref.fetchIfRef(widths[i]);\n          if (Array.isArray(code)) {\n            for (const c of code) {\n              const width = xref.fetchIfRef(c);\n              if (typeof width === \"number\") {\n                glyphsWidths[start] = width;\n              }\n              start++;\n            }\n          } else if (Number.isInteger(code)) {\n            const width = xref.fetchIfRef(widths[++i]);\n            if (typeof width !== \"number\") {\n              continue;\n            }\n            for (let j = start; j <= code; j++) {\n              glyphsWidths[j] = width;\n            }\n          } else {\n            break;\n          }\n        }\n      }\n      if (properties.vertical) {\n        const dw2 = dict.getArray(\"DW2\");\n        let vmetrics = isNumberArray(dw2, 2) ? dw2 : [880, -1000];\n        defaultVMetrics = [vmetrics[1], defaultWidth * 0.5, vmetrics[0]];\n        vmetrics = dict.get(\"W2\");\n        if (Array.isArray(vmetrics)) {\n          for (let i = 0, ii = vmetrics.length; i < ii; i++) {\n            let start = xref.fetchIfRef(vmetrics[i++]);\n            if (!Number.isInteger(start)) {\n              break;\n            }\n            const code = xref.fetchIfRef(vmetrics[i]);\n            if (Array.isArray(code)) {\n              for (let j = 0, jj = code.length; j < jj; j++) {\n                const vmetric = [xref.fetchIfRef(code[j++]), xref.fetchIfRef(code[j++]), xref.fetchIfRef(code[j])];\n                if (isNumberArray(vmetric, null)) {\n                  glyphsVMetrics[start] = vmetric;\n                }\n                start++;\n              }\n            } else if (Number.isInteger(code)) {\n              const vmetric = [xref.fetchIfRef(vmetrics[++i]), xref.fetchIfRef(vmetrics[++i]), xref.fetchIfRef(vmetrics[++i])];\n              if (!isNumberArray(vmetric, null)) {\n                continue;\n              }\n              for (let j = start; j <= code; j++) {\n                glyphsVMetrics[j] = vmetric;\n              }\n            } else {\n              break;\n            }\n          }\n        }\n      }\n    } else {\n      const widths = dict.get(\"Widths\");\n      if (Array.isArray(widths)) {\n        let j = properties.firstChar;\n        for (const w of widths) {\n          const width = xref.fetchIfRef(w);\n          if (typeof width === \"number\") {\n            glyphsWidths[j] = width;\n          }\n          j++;\n        }\n        const missingWidth = descriptor.get(\"MissingWidth\");\n        defaultWidth = typeof missingWidth === \"number\" ? missingWidth : 0;\n      } else {\n        const baseFontName = dict.get(\"BaseFont\");\n        if (baseFontName instanceof Name) {\n          const metrics = this.getBaseFontMetrics(baseFontName.name);\n          glyphsWidths = this.buildCharCodeToWidth(metrics.widths, properties);\n          defaultWidth = metrics.defaultWidth;\n        }\n      }\n    }\n    let isMonospace = true;\n    let firstWidth = defaultWidth;\n    for (const glyph in glyphsWidths) {\n      const glyphWidth = glyphsWidths[glyph];\n      if (!glyphWidth) {\n        continue;\n      }\n      if (!firstWidth) {\n        firstWidth = glyphWidth;\n        continue;\n      }\n      if (firstWidth !== glyphWidth) {\n        isMonospace = false;\n        break;\n      }\n    }\n    if (isMonospace) {\n      properties.flags |= FontFlags.FixedPitch;\n    } else {\n      properties.flags &= ~FontFlags.FixedPitch;\n    }\n    properties.defaultWidth = defaultWidth;\n    properties.widths = glyphsWidths;\n    properties.defaultVMetrics = defaultVMetrics;\n    properties.vmetrics = glyphsVMetrics;\n  }\n  isSerifFont(baseFontName) {\n    const fontNameWoStyle = baseFontName.split(\"-\", 1)[0];\n    return fontNameWoStyle in getSerifFonts() || /serif/gi.test(fontNameWoStyle);\n  }\n  getBaseFontMetrics(name) {\n    let defaultWidth = 0;\n    let widths = Object.create(null);\n    let monospace = false;\n    const stdFontMap = getStdFontMap();\n    let lookupName = stdFontMap[name] || name;\n    const Metrics = getMetrics();\n    if (!(lookupName in Metrics)) {\n      lookupName = this.isSerifFont(name) ? \"Times-Roman\" : \"Helvetica\";\n    }\n    const glyphWidths = Metrics[lookupName];\n    if (typeof glyphWidths === \"number\") {\n      defaultWidth = glyphWidths;\n      monospace = true;\n    } else {\n      widths = glyphWidths();\n    }\n    return {\n      defaultWidth,\n      monospace,\n      widths\n    };\n  }\n  buildCharCodeToWidth(widthsByGlyphName, properties) {\n    const widths = Object.create(null);\n    const differences = properties.differences;\n    const encoding = properties.defaultEncoding;\n    for (let charCode = 0; charCode < 256; charCode++) {\n      if (charCode in differences && widthsByGlyphName[differences[charCode]]) {\n        widths[charCode] = widthsByGlyphName[differences[charCode]];\n        continue;\n      }\n      if (charCode in encoding && widthsByGlyphName[encoding[charCode]]) {\n        widths[charCode] = widthsByGlyphName[encoding[charCode]];\n        continue;\n      }\n    }\n    return widths;\n  }\n  preEvaluateFont(dict) {\n    const baseDict = dict;\n    let type = dict.get(\"Subtype\");\n    if (!(type instanceof Name)) {\n      throw new FormatError(\"invalid font Subtype\");\n    }\n    let composite = false;\n    let hash;\n    if (type.name === \"Type0\") {\n      const df = dict.get(\"DescendantFonts\");\n      if (!df) {\n        throw new FormatError(\"Descendant fonts are not specified\");\n      }\n      dict = Array.isArray(df) ? this.xref.fetchIfRef(df[0]) : df;\n      if (!(dict instanceof Dict)) {\n        throw new FormatError(\"Descendant font is not a dictionary.\");\n      }\n      type = dict.get(\"Subtype\");\n      if (!(type instanceof Name)) {\n        throw new FormatError(\"invalid font Subtype\");\n      }\n      composite = true;\n    }\n    let firstChar = dict.get(\"FirstChar\");\n    if (!Number.isInteger(firstChar)) {\n      firstChar = 0;\n    }\n    let lastChar = dict.get(\"LastChar\");\n    if (!Number.isInteger(lastChar)) {\n      lastChar = composite ? 0xffff : 0xff;\n    }\n    const descriptor = dict.get(\"FontDescriptor\");\n    const toUnicode = dict.get(\"ToUnicode\") || baseDict.get(\"ToUnicode\");\n    if (descriptor) {\n      hash = new MurmurHash3_64();\n      const encoding = baseDict.getRaw(\"Encoding\");\n      if (encoding instanceof Name) {\n        hash.update(encoding.name);\n      } else if (encoding instanceof Ref) {\n        hash.update(encoding.toString());\n      } else if (encoding instanceof Dict) {\n        for (const entry of encoding.getRawValues()) {\n          if (entry instanceof Name) {\n            hash.update(entry.name);\n          } else if (entry instanceof Ref) {\n            hash.update(entry.toString());\n          } else if (Array.isArray(entry)) {\n            const diffLength = entry.length,\n              diffBuf = new Array(diffLength);\n            for (let j = 0; j < diffLength; j++) {\n              const diffEntry = entry[j];\n              if (diffEntry instanceof Name) {\n                diffBuf[j] = diffEntry.name;\n              } else if (typeof diffEntry === \"number\" || diffEntry instanceof Ref) {\n                diffBuf[j] = diffEntry.toString();\n              }\n            }\n            hash.update(diffBuf.join());\n          }\n        }\n      }\n      hash.update(`${firstChar}-${lastChar}`);\n      if (toUnicode instanceof BaseStream) {\n        const stream = toUnicode.str || toUnicode;\n        const uint8array = stream.buffer ? new Uint8Array(stream.buffer.buffer, 0, stream.bufferLength) : new Uint8Array(stream.bytes.buffer, stream.start, stream.end - stream.start);\n        hash.update(uint8array);\n      } else if (toUnicode instanceof Name) {\n        hash.update(toUnicode.name);\n      }\n      const widths = dict.get(\"Widths\") || baseDict.get(\"Widths\");\n      if (Array.isArray(widths)) {\n        const widthsBuf = [];\n        for (const entry of widths) {\n          if (typeof entry === \"number\" || entry instanceof Ref) {\n            widthsBuf.push(entry.toString());\n          }\n        }\n        hash.update(widthsBuf.join());\n      }\n      if (composite) {\n        hash.update(\"compositeFont\");\n        const compositeWidths = dict.get(\"W\") || baseDict.get(\"W\");\n        if (Array.isArray(compositeWidths)) {\n          const widthsBuf = [];\n          for (const entry of compositeWidths) {\n            if (typeof entry === \"number\" || entry instanceof Ref) {\n              widthsBuf.push(entry.toString());\n            } else if (Array.isArray(entry)) {\n              const subWidthsBuf = [];\n              for (const element of entry) {\n                if (typeof element === \"number\" || element instanceof Ref) {\n                  subWidthsBuf.push(element.toString());\n                }\n              }\n              widthsBuf.push(`[${subWidthsBuf.join()}]`);\n            }\n          }\n          hash.update(widthsBuf.join());\n        }\n        const cidToGidMap = dict.getRaw(\"CIDToGIDMap\") || baseDict.getRaw(\"CIDToGIDMap\");\n        if (cidToGidMap instanceof Name) {\n          hash.update(cidToGidMap.name);\n        } else if (cidToGidMap instanceof Ref) {\n          hash.update(cidToGidMap.toString());\n        } else if (cidToGidMap instanceof BaseStream) {\n          hash.update(cidToGidMap.peekBytes());\n        }\n      }\n    }\n    return {\n      descriptor,\n      dict,\n      baseDict,\n      composite,\n      type: type.name,\n      firstChar,\n      lastChar,\n      toUnicode,\n      hash: hash ? hash.hexdigest() : \"\"\n    };\n  }\n  async translateFont({\n    descriptor,\n    dict,\n    baseDict,\n    composite,\n    type,\n    firstChar,\n    lastChar,\n    toUnicode,\n    cssFontInfo\n  }) {\n    const isType3Font = type === \"Type3\";\n    if (!descriptor) {\n      if (isType3Font) {\n        let bbox = dict.getArray(\"FontBBox\");\n        if (!isNumberArray(bbox, 4)) {\n          bbox = [0, 0, 0, 0];\n        }\n        descriptor = new Dict(null);\n        descriptor.set(\"FontName\", Name.get(type));\n        descriptor.set(\"FontBBox\", bbox);\n      } else {\n        let baseFontName = dict.get(\"BaseFont\");\n        if (!(baseFontName instanceof Name)) {\n          throw new FormatError(\"Base font is not specified\");\n        }\n        baseFontName = baseFontName.name.replaceAll(/[,_]/g, \"-\");\n        const metrics = this.getBaseFontMetrics(baseFontName);\n        const fontNameWoStyle = baseFontName.split(\"-\", 1)[0];\n        const flags = (this.isSerifFont(fontNameWoStyle) ? FontFlags.Serif : 0) | (metrics.monospace ? FontFlags.FixedPitch : 0) | (getSymbolsFonts()[fontNameWoStyle] ? FontFlags.Symbolic : FontFlags.Nonsymbolic);\n        const properties = {\n          type,\n          name: baseFontName,\n          loadedName: baseDict.loadedName,\n          systemFontInfo: null,\n          widths: metrics.widths,\n          defaultWidth: metrics.defaultWidth,\n          isSimulatedFlags: true,\n          flags,\n          firstChar,\n          lastChar,\n          toUnicode,\n          xHeight: 0,\n          capHeight: 0,\n          italicAngle: 0,\n          isType3Font\n        };\n        const widths = dict.get(\"Widths\");\n        const standardFontName = getStandardFontName(baseFontName);\n        let file = null;\n        if (standardFontName) {\n          file = await this.fetchStandardFontData(standardFontName);\n          properties.isInternalFont = !!file;\n        }\n        if (!properties.isInternalFont && this.options.useSystemFonts) {\n          properties.systemFontInfo = getFontSubstitution(this.systemFontCache, this.idFactory, this.options.standardFontDataUrl, baseFontName, standardFontName, type);\n        }\n        const newProperties = await this.extractDataStructures(dict, properties);\n        if (widths) {\n          const glyphWidths = [];\n          let j = firstChar;\n          for (const width of widths) {\n            glyphWidths[j++] = this.xref.fetchIfRef(width);\n          }\n          newProperties.widths = glyphWidths;\n        } else {\n          newProperties.widths = this.buildCharCodeToWidth(metrics.widths, newProperties);\n        }\n        return new Font(baseFontName, file, newProperties);\n      }\n    }\n    let fontName = descriptor.get(\"FontName\");\n    let baseFont = dict.get(\"BaseFont\");\n    if (typeof fontName === \"string\") {\n      fontName = Name.get(fontName);\n    }\n    if (typeof baseFont === \"string\") {\n      baseFont = Name.get(baseFont);\n    }\n    const fontNameStr = fontName?.name;\n    const baseFontStr = baseFont?.name;\n    if (!isType3Font && fontNameStr !== baseFontStr) {\n      info(`The FontDescriptor's FontName is \"${fontNameStr}\" but ` + `should be the same as the Font's BaseFont \"${baseFontStr}\".`);\n      if (fontNameStr && baseFontStr && (baseFontStr.startsWith(fontNameStr) || !isKnownFontName(fontNameStr) && isKnownFontName(baseFontStr))) {\n        fontName = null;\n      }\n    }\n    fontName ||= baseFont;\n    if (!(fontName instanceof Name)) {\n      throw new FormatError(\"invalid font name\");\n    }\n    let fontFile, subtype, length1, length2, length3;\n    try {\n      fontFile = descriptor.get(\"FontFile\", \"FontFile2\", \"FontFile3\");\n    } catch (ex) {\n      if (!this.options.ignoreErrors) {\n        throw ex;\n      }\n      warn(`translateFont - fetching \"${fontName.name}\" font file: \"${ex}\".`);\n      fontFile = new NullStream();\n    }\n    let isInternalFont = false;\n    let glyphScaleFactors = null;\n    let systemFontInfo = null;\n    if (fontFile) {\n      if (fontFile.dict) {\n        const subtypeEntry = fontFile.dict.get(\"Subtype\");\n        if (subtypeEntry instanceof Name) {\n          subtype = subtypeEntry.name;\n        }\n        length1 = fontFile.dict.get(\"Length1\");\n        length2 = fontFile.dict.get(\"Length2\");\n        length3 = fontFile.dict.get(\"Length3\");\n      }\n    } else if (cssFontInfo) {\n      const standardFontName = getXfaFontName(fontName.name);\n      if (standardFontName) {\n        cssFontInfo.fontFamily = `${cssFontInfo.fontFamily}-PdfJS-XFA`;\n        cssFontInfo.metrics = standardFontName.metrics || null;\n        glyphScaleFactors = standardFontName.factors || null;\n        fontFile = await this.fetchStandardFontData(standardFontName.name);\n        isInternalFont = !!fontFile;\n        baseDict = dict = getXfaFontDict(fontName.name);\n        composite = true;\n      }\n    } else if (!isType3Font) {\n      const standardFontName = getStandardFontName(fontName.name);\n      if (standardFontName) {\n        fontFile = await this.fetchStandardFontData(standardFontName);\n        isInternalFont = !!fontFile;\n      }\n      if (!isInternalFont && this.options.useSystemFonts) {\n        systemFontInfo = getFontSubstitution(this.systemFontCache, this.idFactory, this.options.standardFontDataUrl, fontName.name, standardFontName, type);\n      }\n    }\n    let fontMatrix = dict.getArray(\"FontMatrix\");\n    if (!isNumberArray(fontMatrix, 6)) {\n      fontMatrix = FONT_IDENTITY_MATRIX;\n    }\n    let bbox = descriptor.getArray(\"FontBBox\") || dict.getArray(\"FontBBox\");\n    if (!isNumberArray(bbox, 4)) {\n      bbox = undefined;\n    }\n    let ascent = descriptor.get(\"Ascent\");\n    if (typeof ascent !== \"number\") {\n      ascent = undefined;\n    }\n    let descent = descriptor.get(\"Descent\");\n    if (typeof descent !== \"number\") {\n      descent = undefined;\n    }\n    let xHeight = descriptor.get(\"XHeight\");\n    if (typeof xHeight !== \"number\") {\n      xHeight = 0;\n    }\n    let capHeight = descriptor.get(\"CapHeight\");\n    if (typeof capHeight !== \"number\") {\n      capHeight = 0;\n    }\n    let flags = descriptor.get(\"Flags\");\n    if (!Number.isInteger(flags)) {\n      flags = 0;\n    }\n    let italicAngle = descriptor.get(\"ItalicAngle\");\n    if (typeof italicAngle !== \"number\") {\n      italicAngle = 0;\n    }\n    const properties = {\n      type,\n      name: fontName.name,\n      subtype,\n      file: fontFile,\n      length1,\n      length2,\n      length3,\n      isInternalFont,\n      loadedName: baseDict.loadedName,\n      composite,\n      fixedPitch: false,\n      fontMatrix,\n      firstChar,\n      lastChar,\n      toUnicode,\n      bbox,\n      ascent,\n      descent,\n      xHeight,\n      capHeight,\n      flags,\n      italicAngle,\n      isType3Font,\n      cssFontInfo,\n      scaleFactors: glyphScaleFactors,\n      systemFontInfo\n    };\n    if (composite) {\n      const cidEncoding = baseDict.get(\"Encoding\");\n      if (cidEncoding instanceof Name) {\n        properties.cidEncoding = cidEncoding.name;\n      }\n      const cMap = await CMapFactory.create({\n        encoding: cidEncoding,\n        fetchBuiltInCMap: this._fetchBuiltInCMapBound,\n        useCMap: null\n      });\n      properties.cMap = cMap;\n      properties.vertical = properties.cMap.vertical;\n    }\n    const newProperties = await this.extractDataStructures(dict, properties);\n    this.extractWidths(dict, descriptor, newProperties);\n    return new Font(fontName.name, fontFile, newProperties);\n  }\n  static buildFontPaths(font, glyphs, handler, evaluatorOptions) {\n    function buildPath(fontChar) {\n      const glyphName = `${font.loadedName}_path_${fontChar}`;\n      try {\n        if (font.renderer.hasBuiltPath(fontChar)) {\n          return;\n        }\n        handler.send(\"commonobj\", [glyphName, \"FontPath\", font.renderer.getPathJs(fontChar)]);\n      } catch (reason) {\n        if (evaluatorOptions.ignoreErrors) {\n          warn(`buildFontPaths - ignoring ${glyphName} glyph: \"${reason}\".`);\n          return;\n        }\n        throw reason;\n      }\n    }\n    for (const glyph of glyphs) {\n      buildPath(glyph.fontChar);\n      const accent = glyph.accent;\n      if (accent?.fontChar) {\n        buildPath(accent.fontChar);\n      }\n    }\n  }\n  static get fallbackFontDict() {\n    const dict = new Dict();\n    dict.set(\"BaseFont\", Name.get(\"Helvetica\"));\n    dict.set(\"Type\", Name.get(\"FallbackType\"));\n    dict.set(\"Subtype\", Name.get(\"FallbackType\"));\n    dict.set(\"Encoding\", Name.get(\"WinAnsiEncoding\"));\n    return shadow(this, \"fallbackFontDict\", dict);\n  }\n}\nclass TranslatedFont {\n  constructor({\n    loadedName,\n    font,\n    dict,\n    evaluatorOptions\n  }) {\n    this.loadedName = loadedName;\n    this.font = font;\n    this.dict = dict;\n    this._evaluatorOptions = evaluatorOptions || DefaultPartialEvaluatorOptions;\n    this.type3Loaded = null;\n    this.type3Dependencies = font.isType3Font ? new Set() : null;\n    this.sent = false;\n  }\n  send(handler) {\n    if (this.sent) {\n      return;\n    }\n    this.sent = true;\n    handler.send(\"commonobj\", [this.loadedName, \"Font\", this.font.exportData(this._evaluatorOptions.fontExtraProperties)]);\n  }\n  fallback(handler) {\n    if (!this.font.data) {\n      return;\n    }\n    this.font.disableFontFace = true;\n    PartialEvaluator.buildFontPaths(this.font, this.font.glyphCacheValues, handler, this._evaluatorOptions);\n  }\n  loadType3Data(evaluator, resources, task) {\n    if (this.type3Loaded) {\n      return this.type3Loaded;\n    }\n    if (!this.font.isType3Font) {\n      throw new Error(\"Must be a Type3 font.\");\n    }\n    const type3Evaluator = evaluator.clone({\n      ignoreErrors: false\n    });\n    type3Evaluator.parsingType3Font = true;\n    const type3FontRefs = new RefSet(evaluator.type3FontRefs);\n    if (this.dict.objId && !type3FontRefs.has(this.dict.objId)) {\n      type3FontRefs.put(this.dict.objId);\n    }\n    type3Evaluator.type3FontRefs = type3FontRefs;\n    const translatedFont = this.font,\n      type3Dependencies = this.type3Dependencies;\n    let loadCharProcsPromise = Promise.resolve();\n    const charProcs = this.dict.get(\"CharProcs\");\n    const fontResources = this.dict.get(\"Resources\") || resources;\n    const charProcOperatorList = Object.create(null);\n    const fontBBox = Util.normalizeRect(translatedFont.bbox || [0, 0, 0, 0]),\n      width = fontBBox[2] - fontBBox[0],\n      height = fontBBox[3] - fontBBox[1];\n    const fontBBoxSize = Math.hypot(width, height);\n    for (const key of charProcs.getKeys()) {\n      loadCharProcsPromise = loadCharProcsPromise.then(() => {\n        const glyphStream = charProcs.get(key);\n        const operatorList = new OperatorList();\n        return type3Evaluator.getOperatorList({\n          stream: glyphStream,\n          task,\n          resources: fontResources,\n          operatorList\n        }).then(() => {\n          if (operatorList.fnArray[0] === OPS.setCharWidthAndBounds) {\n            this._removeType3ColorOperators(operatorList, fontBBoxSize);\n          }\n          charProcOperatorList[key] = operatorList.getIR();\n          for (const dependency of operatorList.dependencies) {\n            type3Dependencies.add(dependency);\n          }\n        }).catch(function (reason) {\n          warn(`Type3 font resource \"${key}\" is not available.`);\n          const dummyOperatorList = new OperatorList();\n          charProcOperatorList[key] = dummyOperatorList.getIR();\n        });\n      });\n    }\n    this.type3Loaded = loadCharProcsPromise.then(() => {\n      translatedFont.charProcOperatorList = charProcOperatorList;\n      if (this._bbox) {\n        translatedFont.isCharBBox = true;\n        translatedFont.bbox = this._bbox;\n      }\n    });\n    return this.type3Loaded;\n  }\n  _removeType3ColorOperators(operatorList, fontBBoxSize = NaN) {\n    const charBBox = Util.normalizeRect(operatorList.argsArray[0].slice(2)),\n      width = charBBox[2] - charBBox[0],\n      height = charBBox[3] - charBBox[1];\n    const charBBoxSize = Math.hypot(width, height);\n    if (width === 0 || height === 0) {\n      operatorList.fnArray.splice(0, 1);\n      operatorList.argsArray.splice(0, 1);\n    } else if (fontBBoxSize === 0 || Math.round(charBBoxSize / fontBBoxSize) >= 10) {\n      if (!this._bbox) {\n        this._bbox = [Infinity, Infinity, -Infinity, -Infinity];\n      }\n      this._bbox[0] = Math.min(this._bbox[0], charBBox[0]);\n      this._bbox[1] = Math.min(this._bbox[1], charBBox[1]);\n      this._bbox[2] = Math.max(this._bbox[2], charBBox[2]);\n      this._bbox[3] = Math.max(this._bbox[3], charBBox[3]);\n    }\n    let i = 0,\n      ii = operatorList.length;\n    while (i < ii) {\n      switch (operatorList.fnArray[i]) {\n        case OPS.setCharWidthAndBounds:\n          break;\n        case OPS.setStrokeColorSpace:\n        case OPS.setFillColorSpace:\n        case OPS.setStrokeColor:\n        case OPS.setStrokeColorN:\n        case OPS.setFillColor:\n        case OPS.setFillColorN:\n        case OPS.setStrokeGray:\n        case OPS.setFillGray:\n        case OPS.setStrokeRGBColor:\n        case OPS.setFillRGBColor:\n        case OPS.setStrokeCMYKColor:\n        case OPS.setFillCMYKColor:\n        case OPS.shadingFill:\n        case OPS.setRenderingIntent:\n          operatorList.fnArray.splice(i, 1);\n          operatorList.argsArray.splice(i, 1);\n          ii--;\n          continue;\n        case OPS.setGState:\n          const [gStateObj] = operatorList.argsArray[i];\n          let j = 0,\n            jj = gStateObj.length;\n          while (j < jj) {\n            const [gStateKey] = gStateObj[j];\n            switch (gStateKey) {\n              case \"TR\":\n              case \"TR2\":\n              case \"HT\":\n              case \"BG\":\n              case \"BG2\":\n              case \"UCR\":\n              case \"UCR2\":\n                gStateObj.splice(j, 1);\n                jj--;\n                continue;\n            }\n            j++;\n          }\n          break;\n      }\n      i++;\n    }\n  }\n}\nclass StateManager {\n  constructor(initialState = new EvalState()) {\n    this.state = initialState;\n    this.stateStack = [];\n  }\n  save() {\n    const old = this.state;\n    this.stateStack.push(this.state);\n    this.state = old.clone();\n  }\n  restore() {\n    const prev = this.stateStack.pop();\n    if (prev) {\n      this.state = prev;\n    }\n  }\n  transform(args) {\n    this.state.ctm = Util.transform(this.state.ctm, args);\n  }\n}\nclass TextState {\n  constructor() {\n    this.ctm = new Float32Array(IDENTITY_MATRIX);\n    this.fontName = null;\n    this.fontSize = 0;\n    this.loadedName = null;\n    this.font = null;\n    this.fontMatrix = FONT_IDENTITY_MATRIX;\n    this.textMatrix = IDENTITY_MATRIX.slice();\n    this.textLineMatrix = IDENTITY_MATRIX.slice();\n    this.charSpacing = 0;\n    this.wordSpacing = 0;\n    this.leading = 0;\n    this.textHScale = 1;\n    this.textRise = 0;\n  }\n  setTextMatrix(a, b, c, d, e, f) {\n    const m = this.textMatrix;\n    m[0] = a;\n    m[1] = b;\n    m[2] = c;\n    m[3] = d;\n    m[4] = e;\n    m[5] = f;\n  }\n  setTextLineMatrix(a, b, c, d, e, f) {\n    const m = this.textLineMatrix;\n    m[0] = a;\n    m[1] = b;\n    m[2] = c;\n    m[3] = d;\n    m[4] = e;\n    m[5] = f;\n  }\n  translateTextMatrix(x, y) {\n    const m = this.textMatrix;\n    m[4] = m[0] * x + m[2] * y + m[4];\n    m[5] = m[1] * x + m[3] * y + m[5];\n  }\n  translateTextLineMatrix(x, y) {\n    const m = this.textLineMatrix;\n    m[4] = m[0] * x + m[2] * y + m[4];\n    m[5] = m[1] * x + m[3] * y + m[5];\n  }\n  carriageReturn() {\n    this.translateTextLineMatrix(0, -this.leading);\n    this.textMatrix = this.textLineMatrix.slice();\n  }\n  clone() {\n    const clone = Object.create(this);\n    clone.textMatrix = this.textMatrix.slice();\n    clone.textLineMatrix = this.textLineMatrix.slice();\n    clone.fontMatrix = this.fontMatrix.slice();\n    return clone;\n  }\n}\nclass EvalState {\n  constructor() {\n    this.ctm = new Float32Array(IDENTITY_MATRIX);\n    this.font = null;\n    this.textRenderingMode = TextRenderingMode.FILL;\n    this.fillColorSpace = ColorSpace.singletons.gray;\n    this.strokeColorSpace = ColorSpace.singletons.gray;\n  }\n  clone() {\n    return Object.create(this);\n  }\n}\nclass EvaluatorPreprocessor {\n  static get opMap() {\n    return shadow(this, \"opMap\", Object.assign(Object.create(null), {\n      w: {\n        id: OPS.setLineWidth,\n        numArgs: 1,\n        variableArgs: false\n      },\n      J: {\n        id: OPS.setLineCap,\n        numArgs: 1,\n        variableArgs: false\n      },\n      j: {\n        id: OPS.setLineJoin,\n        numArgs: 1,\n        variableArgs: false\n      },\n      M: {\n        id: OPS.setMiterLimit,\n        numArgs: 1,\n        variableArgs: false\n      },\n      d: {\n        id: OPS.setDash,\n        numArgs: 2,\n        variableArgs: false\n      },\n      ri: {\n        id: OPS.setRenderingIntent,\n        numArgs: 1,\n        variableArgs: false\n      },\n      i: {\n        id: OPS.setFlatness,\n        numArgs: 1,\n        variableArgs: false\n      },\n      gs: {\n        id: OPS.setGState,\n        numArgs: 1,\n        variableArgs: false\n      },\n      q: {\n        id: OPS.save,\n        numArgs: 0,\n        variableArgs: false\n      },\n      Q: {\n        id: OPS.restore,\n        numArgs: 0,\n        variableArgs: false\n      },\n      cm: {\n        id: OPS.transform,\n        numArgs: 6,\n        variableArgs: false\n      },\n      m: {\n        id: OPS.moveTo,\n        numArgs: 2,\n        variableArgs: false\n      },\n      l: {\n        id: OPS.lineTo,\n        numArgs: 2,\n        variableArgs: false\n      },\n      c: {\n        id: OPS.curveTo,\n        numArgs: 6,\n        variableArgs: false\n      },\n      v: {\n        id: OPS.curveTo2,\n        numArgs: 4,\n        variableArgs: false\n      },\n      y: {\n        id: OPS.curveTo3,\n        numArgs: 4,\n        variableArgs: false\n      },\n      h: {\n        id: OPS.closePath,\n        numArgs: 0,\n        variableArgs: false\n      },\n      re: {\n        id: OPS.rectangle,\n        numArgs: 4,\n        variableArgs: false\n      },\n      S: {\n        id: OPS.stroke,\n        numArgs: 0,\n        variableArgs: false\n      },\n      s: {\n        id: OPS.closeStroke,\n        numArgs: 0,\n        variableArgs: false\n      },\n      f: {\n        id: OPS.fill,\n        numArgs: 0,\n        variableArgs: false\n      },\n      F: {\n        id: OPS.fill,\n        numArgs: 0,\n        variableArgs: false\n      },\n      \"f*\": {\n        id: OPS.eoFill,\n        numArgs: 0,\n        variableArgs: false\n      },\n      B: {\n        id: OPS.fillStroke,\n        numArgs: 0,\n        variableArgs: false\n      },\n      \"B*\": {\n        id: OPS.eoFillStroke,\n        numArgs: 0,\n        variableArgs: false\n      },\n      b: {\n        id: OPS.closeFillStroke,\n        numArgs: 0,\n        variableArgs: false\n      },\n      \"b*\": {\n        id: OPS.closeEOFillStroke,\n        numArgs: 0,\n        variableArgs: false\n      },\n      n: {\n        id: OPS.endPath,\n        numArgs: 0,\n        variableArgs: false\n      },\n      W: {\n        id: OPS.clip,\n        numArgs: 0,\n        variableArgs: false\n      },\n      \"W*\": {\n        id: OPS.eoClip,\n        numArgs: 0,\n        variableArgs: false\n      },\n      BT: {\n        id: OPS.beginText,\n        numArgs: 0,\n        variableArgs: false\n      },\n      ET: {\n        id: OPS.endText,\n        numArgs: 0,\n        variableArgs: false\n      },\n      Tc: {\n        id: OPS.setCharSpacing,\n        numArgs: 1,\n        variableArgs: false\n      },\n      Tw: {\n        id: OPS.setWordSpacing,\n        numArgs: 1,\n        variableArgs: false\n      },\n      Tz: {\n        id: OPS.setHScale,\n        numArgs: 1,\n        variableArgs: false\n      },\n      TL: {\n        id: OPS.setLeading,\n        numArgs: 1,\n        variableArgs: false\n      },\n      Tf: {\n        id: OPS.setFont,\n        numArgs: 2,\n        variableArgs: false\n      },\n      Tr: {\n        id: OPS.setTextRenderingMode,\n        numArgs: 1,\n        variableArgs: false\n      },\n      Ts: {\n        id: OPS.setTextRise,\n        numArgs: 1,\n        variableArgs: false\n      },\n      Td: {\n        id: OPS.moveText,\n        numArgs: 2,\n        variableArgs: false\n      },\n      TD: {\n        id: OPS.setLeadingMoveText,\n        numArgs: 2,\n        variableArgs: false\n      },\n      Tm: {\n        id: OPS.setTextMatrix,\n        numArgs: 6,\n        variableArgs: false\n      },\n      \"T*\": {\n        id: OPS.nextLine,\n        numArgs: 0,\n        variableArgs: false\n      },\n      Tj: {\n        id: OPS.showText,\n        numArgs: 1,\n        variableArgs: false\n      },\n      TJ: {\n        id: OPS.showSpacedText,\n        numArgs: 1,\n        variableArgs: false\n      },\n      \"'\": {\n        id: OPS.nextLineShowText,\n        numArgs: 1,\n        variableArgs: false\n      },\n      '\"': {\n        id: OPS.nextLineSetSpacingShowText,\n        numArgs: 3,\n        variableArgs: false\n      },\n      d0: {\n        id: OPS.setCharWidth,\n        numArgs: 2,\n        variableArgs: false\n      },\n      d1: {\n        id: OPS.setCharWidthAndBounds,\n        numArgs: 6,\n        variableArgs: false\n      },\n      CS: {\n        id: OPS.setStrokeColorSpace,\n        numArgs: 1,\n        variableArgs: false\n      },\n      cs: {\n        id: OPS.setFillColorSpace,\n        numArgs: 1,\n        variableArgs: false\n      },\n      SC: {\n        id: OPS.setStrokeColor,\n        numArgs: 4,\n        variableArgs: true\n      },\n      SCN: {\n        id: OPS.setStrokeColorN,\n        numArgs: 33,\n        variableArgs: true\n      },\n      sc: {\n        id: OPS.setFillColor,\n        numArgs: 4,\n        variableArgs: true\n      },\n      scn: {\n        id: OPS.setFillColorN,\n        numArgs: 33,\n        variableArgs: true\n      },\n      G: {\n        id: OPS.setStrokeGray,\n        numArgs: 1,\n        variableArgs: false\n      },\n      g: {\n        id: OPS.setFillGray,\n        numArgs: 1,\n        variableArgs: false\n      },\n      RG: {\n        id: OPS.setStrokeRGBColor,\n        numArgs: 3,\n        variableArgs: false\n      },\n      rg: {\n        id: OPS.setFillRGBColor,\n        numArgs: 3,\n        variableArgs: false\n      },\n      K: {\n        id: OPS.setStrokeCMYKColor,\n        numArgs: 4,\n        variableArgs: false\n      },\n      k: {\n        id: OPS.setFillCMYKColor,\n        numArgs: 4,\n        variableArgs: false\n      },\n      sh: {\n        id: OPS.shadingFill,\n        numArgs: 1,\n        variableArgs: false\n      },\n      BI: {\n        id: OPS.beginInlineImage,\n        numArgs: 0,\n        variableArgs: false\n      },\n      ID: {\n        id: OPS.beginImageData,\n        numArgs: 0,\n        variableArgs: false\n      },\n      EI: {\n        id: OPS.endInlineImage,\n        numArgs: 1,\n        variableArgs: false\n      },\n      Do: {\n        id: OPS.paintXObject,\n        numArgs: 1,\n        variableArgs: false\n      },\n      MP: {\n        id: OPS.markPoint,\n        numArgs: 1,\n        variableArgs: false\n      },\n      DP: {\n        id: OPS.markPointProps,\n        numArgs: 2,\n        variableArgs: false\n      },\n      BMC: {\n        id: OPS.beginMarkedContent,\n        numArgs: 1,\n        variableArgs: false\n      },\n      BDC: {\n        id: OPS.beginMarkedContentProps,\n        numArgs: 2,\n        variableArgs: false\n      },\n      EMC: {\n        id: OPS.endMarkedContent,\n        numArgs: 0,\n        variableArgs: false\n      },\n      BX: {\n        id: OPS.beginCompat,\n        numArgs: 0,\n        variableArgs: false\n      },\n      EX: {\n        id: OPS.endCompat,\n        numArgs: 0,\n        variableArgs: false\n      },\n      BM: null,\n      BD: null,\n      true: null,\n      fa: null,\n      fal: null,\n      fals: null,\n      false: null,\n      nu: null,\n      nul: null,\n      null: null\n    }));\n  }\n  static MAX_INVALID_PATH_OPS = 10;\n  constructor(stream, xref, stateManager = new StateManager()) {\n    this.parser = new Parser({\n      lexer: new Lexer(stream, EvaluatorPreprocessor.opMap),\n      xref\n    });\n    this.stateManager = stateManager;\n    this.nonProcessedArgs = [];\n    this._isPathOp = false;\n    this._numInvalidPathOPS = 0;\n  }\n  get savedStatesDepth() {\n    return this.stateManager.stateStack.length;\n  }\n  read(operation) {\n    let args = operation.args;\n    while (true) {\n      const obj = this.parser.getObj();\n      if (obj instanceof Cmd) {\n        const cmd = obj.cmd;\n        const opSpec = EvaluatorPreprocessor.opMap[cmd];\n        if (!opSpec) {\n          warn(`Unknown command \"${cmd}\".`);\n          continue;\n        }\n        const fn = opSpec.id;\n        const numArgs = opSpec.numArgs;\n        let argsLength = args !== null ? args.length : 0;\n        if (!this._isPathOp) {\n          this._numInvalidPathOPS = 0;\n        }\n        this._isPathOp = fn >= OPS.moveTo && fn <= OPS.endPath;\n        if (!opSpec.variableArgs) {\n          if (argsLength !== numArgs) {\n            const nonProcessedArgs = this.nonProcessedArgs;\n            while (argsLength > numArgs) {\n              nonProcessedArgs.push(args.shift());\n              argsLength--;\n            }\n            while (argsLength < numArgs && nonProcessedArgs.length !== 0) {\n              if (args === null) {\n                args = [];\n              }\n              args.unshift(nonProcessedArgs.pop());\n              argsLength++;\n            }\n          }\n          if (argsLength < numArgs) {\n            const partialMsg = `command ${cmd}: expected ${numArgs} args, ` + `but received ${argsLength} args.`;\n            if (this._isPathOp && ++this._numInvalidPathOPS > EvaluatorPreprocessor.MAX_INVALID_PATH_OPS) {\n              throw new FormatError(`Invalid ${partialMsg}`);\n            }\n            warn(`Skipping ${partialMsg}`);\n            if (args !== null) {\n              args.length = 0;\n            }\n            continue;\n          }\n        } else if (argsLength > numArgs) {\n          info(`Command ${cmd}: expected [0, ${numArgs}] args, ` + `but received ${argsLength} args.`);\n        }\n        this.preprocessCommand(fn, args);\n        operation.fn = fn;\n        operation.args = args;\n        return true;\n      }\n      if (obj === EOF) {\n        return false;\n      }\n      if (obj !== null) {\n        if (args === null) {\n          args = [];\n        }\n        args.push(obj);\n        if (args.length > 33) {\n          throw new FormatError(\"Too many arguments\");\n        }\n      }\n    }\n  }\n  preprocessCommand(fn, args) {\n    switch (fn | 0) {\n      case OPS.save:\n        this.stateManager.save();\n        break;\n      case OPS.restore:\n        this.stateManager.restore();\n        break;\n      case OPS.transform:\n        this.stateManager.transform(args);\n        break;\n    }\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/default_appearance.js\n\n\n\n\n\n\n\n\nclass DefaultAppearanceEvaluator extends EvaluatorPreprocessor {\n  constructor(str) {\n    super(new StringStream(str));\n  }\n  parse() {\n    const operation = {\n      fn: 0,\n      args: []\n    };\n    const result = {\n      fontSize: 0,\n      fontName: \"\",\n      fontColor: new Uint8ClampedArray(3)\n    };\n    try {\n      while (true) {\n        operation.args.length = 0;\n        if (!this.read(operation)) {\n          break;\n        }\n        if (this.savedStatesDepth !== 0) {\n          continue;\n        }\n        const {\n          fn,\n          args\n        } = operation;\n        switch (fn | 0) {\n          case OPS.setFont:\n            const [fontName, fontSize] = args;\n            if (fontName instanceof Name) {\n              result.fontName = fontName.name;\n            }\n            if (typeof fontSize === \"number\" && fontSize > 0) {\n              result.fontSize = fontSize;\n            }\n            break;\n          case OPS.setFillRGBColor:\n            ColorSpace.singletons.rgb.getRgbItem(args, 0, result.fontColor, 0);\n            break;\n          case OPS.setFillGray:\n            ColorSpace.singletons.gray.getRgbItem(args, 0, result.fontColor, 0);\n            break;\n          case OPS.setFillCMYKColor:\n            ColorSpace.singletons.cmyk.getRgbItem(args, 0, result.fontColor, 0);\n            break;\n        }\n      }\n    } catch (reason) {\n      warn(`parseDefaultAppearance - ignoring errors: \"${reason}\".`);\n    }\n    return result;\n  }\n}\nfunction parseDefaultAppearance(str) {\n  return new DefaultAppearanceEvaluator(str).parse();\n}\nclass AppearanceStreamEvaluator extends EvaluatorPreprocessor {\n  constructor(stream, evaluatorOptions, xref) {\n    super(stream);\n    this.stream = stream;\n    this.evaluatorOptions = evaluatorOptions;\n    this.xref = xref;\n    this.resources = stream.dict?.get(\"Resources\");\n  }\n  parse() {\n    const operation = {\n      fn: 0,\n      args: []\n    };\n    let result = {\n      scaleFactor: 1,\n      fontSize: 0,\n      fontName: \"\",\n      fontColor: new Uint8ClampedArray(3),\n      fillColorSpace: ColorSpace.singletons.gray\n    };\n    let breakLoop = false;\n    const stack = [];\n    try {\n      while (true) {\n        operation.args.length = 0;\n        if (breakLoop || !this.read(operation)) {\n          break;\n        }\n        const {\n          fn,\n          args\n        } = operation;\n        switch (fn | 0) {\n          case OPS.save:\n            stack.push({\n              scaleFactor: result.scaleFactor,\n              fontSize: result.fontSize,\n              fontName: result.fontName,\n              fontColor: result.fontColor.slice(),\n              fillColorSpace: result.fillColorSpace\n            });\n            break;\n          case OPS.restore:\n            result = stack.pop() || result;\n            break;\n          case OPS.setTextMatrix:\n            result.scaleFactor *= Math.hypot(args[0], args[1]);\n            break;\n          case OPS.setFont:\n            const [fontName, fontSize] = args;\n            if (fontName instanceof Name) {\n              result.fontName = fontName.name;\n            }\n            if (typeof fontSize === \"number\" && fontSize > 0) {\n              result.fontSize = fontSize * result.scaleFactor;\n            }\n            break;\n          case OPS.setFillColorSpace:\n            result.fillColorSpace = ColorSpace.parse({\n              cs: args[0],\n              xref: this.xref,\n              resources: this.resources,\n              pdfFunctionFactory: this._pdfFunctionFactory,\n              localColorSpaceCache: this._localColorSpaceCache\n            });\n            break;\n          case OPS.setFillColor:\n            const cs = result.fillColorSpace;\n            cs.getRgbItem(args, 0, result.fontColor, 0);\n            break;\n          case OPS.setFillRGBColor:\n            ColorSpace.singletons.rgb.getRgbItem(args, 0, result.fontColor, 0);\n            break;\n          case OPS.setFillGray:\n            ColorSpace.singletons.gray.getRgbItem(args, 0, result.fontColor, 0);\n            break;\n          case OPS.setFillCMYKColor:\n            ColorSpace.singletons.cmyk.getRgbItem(args, 0, result.fontColor, 0);\n            break;\n          case OPS.showText:\n          case OPS.showSpacedText:\n          case OPS.nextLineShowText:\n          case OPS.nextLineSetSpacingShowText:\n            breakLoop = true;\n            break;\n        }\n      }\n    } catch (reason) {\n      warn(`parseAppearanceStream - ignoring errors: \"${reason}\".`);\n    }\n    this.stream.reset();\n    delete result.scaleFactor;\n    delete result.fillColorSpace;\n    return result;\n  }\n  get _localColorSpaceCache() {\n    return shadow(this, \"_localColorSpaceCache\", new LocalColorSpaceCache());\n  }\n  get _pdfFunctionFactory() {\n    const pdfFunctionFactory = new PDFFunctionFactory({\n      xref: this.xref,\n      isEvalSupported: this.evaluatorOptions.isEvalSupported\n    });\n    return shadow(this, \"_pdfFunctionFactory\", pdfFunctionFactory);\n  }\n}\nfunction parseAppearanceStream(stream, evaluatorOptions, xref) {\n  return new AppearanceStreamEvaluator(stream, evaluatorOptions, xref).parse();\n}\nfunction getPdfColor(color, isFill) {\n  if (color[0] === color[1] && color[1] === color[2]) {\n    const gray = color[0] / 255;\n    return `${numberToString(gray)} ${isFill ? \"g\" : \"G\"}`;\n  }\n  return Array.from(color, c => numberToString(c / 255)).join(\" \") + ` ${isFill ? \"rg\" : \"RG\"}`;\n}\nfunction createDefaultAppearance({\n  fontSize,\n  fontName,\n  fontColor\n}) {\n  return `/${escapePDFName(fontName)} ${fontSize} Tf ${getPdfColor(fontColor, true)}`;\n}\nclass FakeUnicodeFont {\n  constructor(xref, fontFamily) {\n    this.xref = xref;\n    this.widths = null;\n    this.firstChar = Infinity;\n    this.lastChar = -Infinity;\n    this.fontFamily = fontFamily;\n    const canvas = new OffscreenCanvas(1, 1);\n    this.ctxMeasure = canvas.getContext(\"2d\");\n    if (!FakeUnicodeFont._fontNameId) {\n      FakeUnicodeFont._fontNameId = 1;\n    }\n    this.fontName = Name.get(`InvalidPDFjsFont_${fontFamily}_${FakeUnicodeFont._fontNameId++}`);\n  }\n  get fontDescriptorRef() {\n    if (!FakeUnicodeFont._fontDescriptorRef) {\n      const fontDescriptor = new Dict(this.xref);\n      fontDescriptor.set(\"Type\", Name.get(\"FontDescriptor\"));\n      fontDescriptor.set(\"FontName\", this.fontName);\n      fontDescriptor.set(\"FontFamily\", \"MyriadPro Regular\");\n      fontDescriptor.set(\"FontBBox\", [0, 0, 0, 0]);\n      fontDescriptor.set(\"FontStretch\", Name.get(\"Normal\"));\n      fontDescriptor.set(\"FontWeight\", 400);\n      fontDescriptor.set(\"ItalicAngle\", 0);\n      FakeUnicodeFont._fontDescriptorRef = this.xref.getNewPersistentRef(fontDescriptor);\n    }\n    return FakeUnicodeFont._fontDescriptorRef;\n  }\n  get descendantFontRef() {\n    const descendantFont = new Dict(this.xref);\n    descendantFont.set(\"BaseFont\", this.fontName);\n    descendantFont.set(\"Type\", Name.get(\"Font\"));\n    descendantFont.set(\"Subtype\", Name.get(\"CIDFontType0\"));\n    descendantFont.set(\"CIDToGIDMap\", Name.get(\"Identity\"));\n    descendantFont.set(\"FirstChar\", this.firstChar);\n    descendantFont.set(\"LastChar\", this.lastChar);\n    descendantFont.set(\"FontDescriptor\", this.fontDescriptorRef);\n    descendantFont.set(\"DW\", 1000);\n    const widths = [];\n    const chars = [...this.widths.entries()].sort();\n    let currentChar = null;\n    let currentWidths = null;\n    for (const [char, width] of chars) {\n      if (!currentChar) {\n        currentChar = char;\n        currentWidths = [width];\n        continue;\n      }\n      if (char === currentChar + currentWidths.length) {\n        currentWidths.push(width);\n      } else {\n        widths.push(currentChar, currentWidths);\n        currentChar = char;\n        currentWidths = [width];\n      }\n    }\n    if (currentChar) {\n      widths.push(currentChar, currentWidths);\n    }\n    descendantFont.set(\"W\", widths);\n    const cidSystemInfo = new Dict(this.xref);\n    cidSystemInfo.set(\"Ordering\", \"Identity\");\n    cidSystemInfo.set(\"Registry\", \"Adobe\");\n    cidSystemInfo.set(\"Supplement\", 0);\n    descendantFont.set(\"CIDSystemInfo\", cidSystemInfo);\n    return this.xref.getNewPersistentRef(descendantFont);\n  }\n  get baseFontRef() {\n    const baseFont = new Dict(this.xref);\n    baseFont.set(\"BaseFont\", this.fontName);\n    baseFont.set(\"Type\", Name.get(\"Font\"));\n    baseFont.set(\"Subtype\", Name.get(\"Type0\"));\n    baseFont.set(\"Encoding\", Name.get(\"Identity-H\"));\n    baseFont.set(\"DescendantFonts\", [this.descendantFontRef]);\n    baseFont.set(\"ToUnicode\", Name.get(\"Identity-H\"));\n    return this.xref.getNewPersistentRef(baseFont);\n  }\n  get resources() {\n    const resources = new Dict(this.xref);\n    const font = new Dict(this.xref);\n    font.set(this.fontName.name, this.baseFontRef);\n    resources.set(\"Font\", font);\n    return resources;\n  }\n  _createContext() {\n    this.widths = new Map();\n    this.ctxMeasure.font = `1000px ${this.fontFamily}`;\n    return this.ctxMeasure;\n  }\n  createFontResources(text) {\n    const ctx = this._createContext();\n    for (const line of text.split(/\\r\\n?|\\n/)) {\n      for (const char of line.split(\"\")) {\n        const code = char.charCodeAt(0);\n        if (this.widths.has(code)) {\n          continue;\n        }\n        const metrics = ctx.measureText(char);\n        const width = Math.ceil(metrics.width);\n        this.widths.set(code, width);\n        this.firstChar = Math.min(code, this.firstChar);\n        this.lastChar = Math.max(code, this.lastChar);\n      }\n    }\n    return this.resources;\n  }\n  static getFirstPositionInfo(rect, rotation, fontSize) {\n    const [x1, y1, x2, y2] = rect;\n    let w = x2 - x1;\n    let h = y2 - y1;\n    if (rotation % 180 !== 0) {\n      [w, h] = [h, w];\n    }\n    const lineHeight = LINE_FACTOR * fontSize;\n    const lineDescent = LINE_DESCENT_FACTOR * fontSize;\n    return {\n      coords: [0, h + lineDescent - lineHeight],\n      bbox: [0, 0, w, h],\n      matrix: rotation !== 0 ? getRotationMatrix(rotation, h, lineHeight) : undefined\n    };\n  }\n  createAppearance(text, rect, rotation, fontSize, bgColor, strokeAlpha) {\n    const ctx = this._createContext();\n    const lines = [];\n    let maxWidth = -Infinity;\n    for (const line of text.split(/\\r\\n?|\\n/)) {\n      lines.push(line);\n      const lineWidth = ctx.measureText(line).width;\n      maxWidth = Math.max(maxWidth, lineWidth);\n      for (const code of codePointIter(line)) {\n        const char = String.fromCodePoint(code);\n        let width = this.widths.get(code);\n        if (width === undefined) {\n          const metrics = ctx.measureText(char);\n          width = Math.ceil(metrics.width);\n          this.widths.set(code, width);\n          this.firstChar = Math.min(code, this.firstChar);\n          this.lastChar = Math.max(code, this.lastChar);\n        }\n      }\n    }\n    maxWidth *= fontSize / 1000;\n    const [x1, y1, x2, y2] = rect;\n    let w = x2 - x1;\n    let h = y2 - y1;\n    if (rotation % 180 !== 0) {\n      [w, h] = [h, w];\n    }\n    let hscale = 1;\n    if (maxWidth > w) {\n      hscale = w / maxWidth;\n    }\n    let vscale = 1;\n    const lineHeight = LINE_FACTOR * fontSize;\n    const lineDescent = LINE_DESCENT_FACTOR * fontSize;\n    const maxHeight = lineHeight * lines.length;\n    if (maxHeight > h) {\n      vscale = h / maxHeight;\n    }\n    const fscale = Math.min(hscale, vscale);\n    const newFontSize = fontSize * fscale;\n    const buffer = [\"q\", `0 0 ${numberToString(w)} ${numberToString(h)} re W n`, `BT`, `1 0 0 1 0 ${numberToString(h + lineDescent)} Tm 0 Tc ${getPdfColor(bgColor, true)}`, `/${this.fontName.name} ${numberToString(newFontSize)} Tf`];\n    const {\n      resources\n    } = this;\n    strokeAlpha = typeof strokeAlpha === \"number\" && strokeAlpha >= 0 && strokeAlpha <= 1 ? strokeAlpha : 1;\n    if (strokeAlpha !== 1) {\n      buffer.push(\"/R0 gs\");\n      const extGState = new Dict(this.xref);\n      const r0 = new Dict(this.xref);\n      r0.set(\"ca\", strokeAlpha);\n      r0.set(\"CA\", strokeAlpha);\n      r0.set(\"Type\", Name.get(\"ExtGState\"));\n      extGState.set(\"R0\", r0);\n      resources.set(\"ExtGState\", extGState);\n    }\n    const vShift = numberToString(lineHeight);\n    for (const line of lines) {\n      buffer.push(`0 -${vShift} Td <${stringToUTF16HexString(line)}> Tj`);\n    }\n    buffer.push(\"ET\", \"Q\");\n    const appearance = buffer.join(\"\\n\");\n    const appearanceStreamDict = new Dict(this.xref);\n    appearanceStreamDict.set(\"Subtype\", Name.get(\"Form\"));\n    appearanceStreamDict.set(\"Type\", Name.get(\"XObject\"));\n    appearanceStreamDict.set(\"BBox\", [0, 0, w, h]);\n    appearanceStreamDict.set(\"Length\", appearance.length);\n    appearanceStreamDict.set(\"Resources\", resources);\n    if (rotation) {\n      const matrix = getRotationMatrix(rotation, w, h);\n      appearanceStreamDict.set(\"Matrix\", matrix);\n    }\n    const ap = new StringStream(appearance);\n    ap.dict = appearanceStreamDict;\n    return ap;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/name_number_tree.js\n\n\nclass NameOrNumberTree {\n  constructor(root, xref, type) {\n    if (this.constructor === NameOrNumberTree) {\n      unreachable(\"Cannot initialize NameOrNumberTree.\");\n    }\n    this.root = root;\n    this.xref = xref;\n    this._type = type;\n  }\n  getAll() {\n    const map = new Map();\n    if (!this.root) {\n      return map;\n    }\n    const xref = this.xref;\n    const processed = new RefSet();\n    processed.put(this.root);\n    const queue = [this.root];\n    while (queue.length > 0) {\n      const obj = xref.fetchIfRef(queue.shift());\n      if (!(obj instanceof Dict)) {\n        continue;\n      }\n      if (obj.has(\"Kids\")) {\n        const kids = obj.get(\"Kids\");\n        if (!Array.isArray(kids)) {\n          continue;\n        }\n        for (const kid of kids) {\n          if (processed.has(kid)) {\n            throw new FormatError(`Duplicate entry in \"${this._type}\" tree.`);\n          }\n          queue.push(kid);\n          processed.put(kid);\n        }\n        continue;\n      }\n      const entries = obj.get(this._type);\n      if (!Array.isArray(entries)) {\n        continue;\n      }\n      for (let i = 0, ii = entries.length; i < ii; i += 2) {\n        map.set(xref.fetchIfRef(entries[i]), xref.fetchIfRef(entries[i + 1]));\n      }\n    }\n    return map;\n  }\n  get(key) {\n    if (!this.root) {\n      return null;\n    }\n    const xref = this.xref;\n    let kidsOrEntries = xref.fetchIfRef(this.root);\n    let loopCount = 0;\n    const MAX_LEVELS = 10;\n    while (kidsOrEntries.has(\"Kids\")) {\n      if (++loopCount > MAX_LEVELS) {\n        warn(`Search depth limit reached for \"${this._type}\" tree.`);\n        return null;\n      }\n      const kids = kidsOrEntries.get(\"Kids\");\n      if (!Array.isArray(kids)) {\n        return null;\n      }\n      let l = 0,\n        r = kids.length - 1;\n      while (l <= r) {\n        const m = l + r >> 1;\n        const kid = xref.fetchIfRef(kids[m]);\n        const limits = kid.get(\"Limits\");\n        if (key < xref.fetchIfRef(limits[0])) {\n          r = m - 1;\n        } else if (key > xref.fetchIfRef(limits[1])) {\n          l = m + 1;\n        } else {\n          kidsOrEntries = kid;\n          break;\n        }\n      }\n      if (l > r) {\n        return null;\n      }\n    }\n    const entries = kidsOrEntries.get(this._type);\n    if (Array.isArray(entries)) {\n      let l = 0,\n        r = entries.length - 2;\n      while (l <= r) {\n        const tmp = l + r >> 1,\n          m = tmp + (tmp & 1);\n        const currentKey = xref.fetchIfRef(entries[m]);\n        if (key < currentKey) {\n          r = m - 2;\n        } else if (key > currentKey) {\n          l = m + 2;\n        } else {\n          return xref.fetchIfRef(entries[m + 1]);\n        }\n      }\n    }\n    return null;\n  }\n}\nclass NameTree extends NameOrNumberTree {\n  constructor(root, xref) {\n    super(root, xref, \"Names\");\n  }\n}\nclass NumberTree extends NameOrNumberTree {\n  constructor(root, xref) {\n    super(root, xref, \"Nums\");\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/cleanup_helper.js\n\n\n\n\nfunction clearGlobalCaches() {\n  clearPatternCaches();\n  clearPrimitiveCaches();\n  clearUnicodeCaches();\n  JpxImage.cleanup();\n}\n\n;// CONCATENATED MODULE: ./src/core/file_spec.js\n\n\n\nfunction pickPlatformItem(dict) {\n  if (dict.has(\"UF\")) {\n    return dict.get(\"UF\");\n  } else if (dict.has(\"F\")) {\n    return dict.get(\"F\");\n  } else if (dict.has(\"Unix\")) {\n    return dict.get(\"Unix\");\n  } else if (dict.has(\"Mac\")) {\n    return dict.get(\"Mac\");\n  } else if (dict.has(\"DOS\")) {\n    return dict.get(\"DOS\");\n  }\n  return null;\n}\nclass FileSpec {\n  #contentAvailable = false;\n  constructor(root, xref, skipContent = false) {\n    if (!(root instanceof Dict)) {\n      return;\n    }\n    this.xref = xref;\n    this.root = root;\n    if (root.has(\"FS\")) {\n      this.fs = root.get(\"FS\");\n    }\n    this.description = root.has(\"Desc\") ? stringToPDFString(root.get(\"Desc\")) : \"\";\n    if (root.has(\"RF\")) {\n      warn(\"Related file specifications are not supported\");\n    }\n    if (!skipContent) {\n      if (root.has(\"EF\")) {\n        this.#contentAvailable = true;\n      } else {\n        warn(\"Non-embedded file specifications are not supported\");\n      }\n    }\n  }\n  get filename() {\n    if (!this._filename && this.root) {\n      const filename = pickPlatformItem(this.root) || \"unnamed\";\n      this._filename = stringToPDFString(filename).replaceAll(\"\\\\\\\\\", \"\\\\\").replaceAll(\"\\\\/\", \"/\").replaceAll(\"\\\\\", \"/\");\n    }\n    return this._filename;\n  }\n  get content() {\n    if (!this.#contentAvailable) {\n      return null;\n    }\n    if (!this.contentRef && this.root) {\n      this.contentRef = pickPlatformItem(this.root.get(\"EF\"));\n    }\n    let content = null;\n    if (this.contentRef) {\n      const fileObj = this.xref.fetchIfRef(this.contentRef);\n      if (fileObj instanceof BaseStream) {\n        content = fileObj.getBytes();\n      } else {\n        warn(\"Embedded file specification points to non-existing/invalid content\");\n      }\n    } else {\n      warn(\"Embedded file specification does not have a content\");\n    }\n    return content;\n  }\n  get serializable() {\n    return {\n      filename: this.filename,\n      content: this.content\n    };\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/xml_parser.js\n\nconst XMLParserErrorCode = {\n  NoError: 0,\n  EndOfDocument: -1,\n  UnterminatedCdat: -2,\n  UnterminatedXmlDeclaration: -3,\n  UnterminatedDoctypeDeclaration: -4,\n  UnterminatedComment: -5,\n  MalformedElement: -6,\n  OutOfMemory: -7,\n  UnterminatedAttributeValue: -8,\n  UnterminatedElement: -9,\n  ElementNeverBegun: -10\n};\nfunction isWhitespace(s, index) {\n  const ch = s[index];\n  return ch === \" \" || ch === \"\\n\" || ch === \"\\r\" || ch === \"\\t\";\n}\nfunction isWhitespaceString(s) {\n  for (let i = 0, ii = s.length; i < ii; i++) {\n    if (!isWhitespace(s, i)) {\n      return false;\n    }\n  }\n  return true;\n}\nclass XMLParserBase {\n  _resolveEntities(s) {\n    return s.replaceAll(/&([^;]+);/g, (all, entity) => {\n      if (entity.substring(0, 2) === \"#x\") {\n        return String.fromCodePoint(parseInt(entity.substring(2), 16));\n      } else if (entity.substring(0, 1) === \"#\") {\n        return String.fromCodePoint(parseInt(entity.substring(1), 10));\n      }\n      switch (entity) {\n        case \"lt\":\n          return \"<\";\n        case \"gt\":\n          return \">\";\n        case \"amp\":\n          return \"&\";\n        case \"quot\":\n          return '\"';\n        case \"apos\":\n          return \"'\";\n      }\n      return this.onResolveEntity(entity);\n    });\n  }\n  _parseContent(s, start) {\n    const attributes = [];\n    let pos = start;\n    function skipWs() {\n      while (pos < s.length && isWhitespace(s, pos)) {\n        ++pos;\n      }\n    }\n    while (pos < s.length && !isWhitespace(s, pos) && s[pos] !== \">\" && s[pos] !== \"/\") {\n      ++pos;\n    }\n    const name = s.substring(start, pos);\n    skipWs();\n    while (pos < s.length && s[pos] !== \">\" && s[pos] !== \"/\" && s[pos] !== \"?\") {\n      skipWs();\n      let attrName = \"\",\n        attrValue = \"\";\n      while (pos < s.length && !isWhitespace(s, pos) && s[pos] !== \"=\") {\n        attrName += s[pos];\n        ++pos;\n      }\n      skipWs();\n      if (s[pos] !== \"=\") {\n        return null;\n      }\n      ++pos;\n      skipWs();\n      const attrEndChar = s[pos];\n      if (attrEndChar !== '\"' && attrEndChar !== \"'\") {\n        return null;\n      }\n      const attrEndIndex = s.indexOf(attrEndChar, ++pos);\n      if (attrEndIndex < 0) {\n        return null;\n      }\n      attrValue = s.substring(pos, attrEndIndex);\n      attributes.push({\n        name: attrName,\n        value: this._resolveEntities(attrValue)\n      });\n      pos = attrEndIndex + 1;\n      skipWs();\n    }\n    return {\n      name,\n      attributes,\n      parsed: pos - start\n    };\n  }\n  _parseProcessingInstruction(s, start) {\n    let pos = start;\n    function skipWs() {\n      while (pos < s.length && isWhitespace(s, pos)) {\n        ++pos;\n      }\n    }\n    while (pos < s.length && !isWhitespace(s, pos) && s[pos] !== \">\" && s[pos] !== \"?\" && s[pos] !== \"/\") {\n      ++pos;\n    }\n    const name = s.substring(start, pos);\n    skipWs();\n    const attrStart = pos;\n    while (pos < s.length && (s[pos] !== \"?\" || s[pos + 1] !== \">\")) {\n      ++pos;\n    }\n    const value = s.substring(attrStart, pos);\n    return {\n      name,\n      value,\n      parsed: pos - start\n    };\n  }\n  parseXml(s) {\n    let i = 0;\n    while (i < s.length) {\n      const ch = s[i];\n      let j = i;\n      if (ch === \"<\") {\n        ++j;\n        const ch2 = s[j];\n        let q;\n        switch (ch2) {\n          case \"/\":\n            ++j;\n            q = s.indexOf(\">\", j);\n            if (q < 0) {\n              this.onError(XMLParserErrorCode.UnterminatedElement);\n              return;\n            }\n            this.onEndElement(s.substring(j, q));\n            j = q + 1;\n            break;\n          case \"?\":\n            ++j;\n            const pi = this._parseProcessingInstruction(s, j);\n            if (s.substring(j + pi.parsed, j + pi.parsed + 2) !== \"?>\") {\n              this.onError(XMLParserErrorCode.UnterminatedXmlDeclaration);\n              return;\n            }\n            this.onPi(pi.name, pi.value);\n            j += pi.parsed + 2;\n            break;\n          case \"!\":\n            if (s.substring(j + 1, j + 3) === \"--\") {\n              q = s.indexOf(\"-->\", j + 3);\n              if (q < 0) {\n                this.onError(XMLParserErrorCode.UnterminatedComment);\n                return;\n              }\n              this.onComment(s.substring(j + 3, q));\n              j = q + 3;\n            } else if (s.substring(j + 1, j + 8) === \"[CDATA[\") {\n              q = s.indexOf(\"]]>\", j + 8);\n              if (q < 0) {\n                this.onError(XMLParserErrorCode.UnterminatedCdat);\n                return;\n              }\n              this.onCdata(s.substring(j + 8, q));\n              j = q + 3;\n            } else if (s.substring(j + 1, j + 8) === \"DOCTYPE\") {\n              const q2 = s.indexOf(\"[\", j + 8);\n              let complexDoctype = false;\n              q = s.indexOf(\">\", j + 8);\n              if (q < 0) {\n                this.onError(XMLParserErrorCode.UnterminatedDoctypeDeclaration);\n                return;\n              }\n              if (q2 > 0 && q > q2) {\n                q = s.indexOf(\"]>\", j + 8);\n                if (q < 0) {\n                  this.onError(XMLParserErrorCode.UnterminatedDoctypeDeclaration);\n                  return;\n                }\n                complexDoctype = true;\n              }\n              const doctypeContent = s.substring(j + 8, q + (complexDoctype ? 1 : 0));\n              this.onDoctype(doctypeContent);\n              j = q + (complexDoctype ? 2 : 1);\n            } else {\n              this.onError(XMLParserErrorCode.MalformedElement);\n              return;\n            }\n            break;\n          default:\n            const content = this._parseContent(s, j);\n            if (content === null) {\n              this.onError(XMLParserErrorCode.MalformedElement);\n              return;\n            }\n            let isClosed = false;\n            if (s.substring(j + content.parsed, j + content.parsed + 2) === \"/>\") {\n              isClosed = true;\n            } else if (s.substring(j + content.parsed, j + content.parsed + 1) !== \">\") {\n              this.onError(XMLParserErrorCode.UnterminatedElement);\n              return;\n            }\n            this.onBeginElement(content.name, content.attributes, isClosed);\n            j += content.parsed + (isClosed ? 2 : 1);\n            break;\n        }\n      } else {\n        while (j < s.length && s[j] !== \"<\") {\n          j++;\n        }\n        const text = s.substring(i, j);\n        this.onText(this._resolveEntities(text));\n      }\n      i = j;\n    }\n  }\n  onResolveEntity(name) {\n    return `&${name};`;\n  }\n  onPi(name, value) {}\n  onComment(text) {}\n  onCdata(text) {}\n  onDoctype(doctypeContent) {}\n  onText(text) {}\n  onBeginElement(name, attributes, isEmpty) {}\n  onEndElement(name) {}\n  onError(code) {}\n}\nclass SimpleDOMNode {\n  constructor(nodeName, nodeValue) {\n    this.nodeName = nodeName;\n    this.nodeValue = nodeValue;\n    Object.defineProperty(this, \"parentNode\", {\n      value: null,\n      writable: true\n    });\n  }\n  get firstChild() {\n    return this.childNodes?.[0];\n  }\n  get nextSibling() {\n    const childNodes = this.parentNode.childNodes;\n    if (!childNodes) {\n      return undefined;\n    }\n    const index = childNodes.indexOf(this);\n    if (index === -1) {\n      return undefined;\n    }\n    return childNodes[index + 1];\n  }\n  get textContent() {\n    if (!this.childNodes) {\n      return this.nodeValue || \"\";\n    }\n    return this.childNodes.map(function (child) {\n      return child.textContent;\n    }).join(\"\");\n  }\n  get children() {\n    return this.childNodes || [];\n  }\n  hasChildNodes() {\n    return this.childNodes?.length > 0;\n  }\n  searchNode(paths, pos) {\n    if (pos >= paths.length) {\n      return this;\n    }\n    const component = paths[pos];\n    if (component.name.startsWith(\"#\") && pos < paths.length - 1) {\n      return this.searchNode(paths, pos + 1);\n    }\n    const stack = [];\n    let node = this;\n    while (true) {\n      if (component.name === node.nodeName) {\n        if (component.pos === 0) {\n          const res = node.searchNode(paths, pos + 1);\n          if (res !== null) {\n            return res;\n          }\n        } else if (stack.length === 0) {\n          return null;\n        } else {\n          const [parent] = stack.pop();\n          let siblingPos = 0;\n          for (const child of parent.childNodes) {\n            if (component.name === child.nodeName) {\n              if (siblingPos === component.pos) {\n                return child.searchNode(paths, pos + 1);\n              }\n              siblingPos++;\n            }\n          }\n          return node.searchNode(paths, pos + 1);\n        }\n      }\n      if (node.childNodes?.length > 0) {\n        stack.push([node, 0]);\n        node = node.childNodes[0];\n      } else if (stack.length === 0) {\n        return null;\n      } else {\n        while (stack.length !== 0) {\n          const [parent, currentPos] = stack.pop();\n          const newPos = currentPos + 1;\n          if (newPos < parent.childNodes.length) {\n            stack.push([parent, newPos]);\n            node = parent.childNodes[newPos];\n            break;\n          }\n        }\n        if (stack.length === 0) {\n          return null;\n        }\n      }\n    }\n  }\n  dump(buffer) {\n    if (this.nodeName === \"#text\") {\n      buffer.push(encodeToXmlString(this.nodeValue));\n      return;\n    }\n    buffer.push(`<${this.nodeName}`);\n    if (this.attributes) {\n      for (const attribute of this.attributes) {\n        buffer.push(` ${attribute.name}=\"${encodeToXmlString(attribute.value)}\"`);\n      }\n    }\n    if (this.hasChildNodes()) {\n      buffer.push(\">\");\n      for (const child of this.childNodes) {\n        child.dump(buffer);\n      }\n      buffer.push(`</${this.nodeName}>`);\n    } else if (this.nodeValue) {\n      buffer.push(`>${encodeToXmlString(this.nodeValue)}</${this.nodeName}>`);\n    } else {\n      buffer.push(\"/>\");\n    }\n  }\n}\nclass SimpleXMLParser extends XMLParserBase {\n  constructor({\n    hasAttributes = false,\n    lowerCaseName = false\n  }) {\n    super();\n    this._currentFragment = null;\n    this._stack = null;\n    this._errorCode = XMLParserErrorCode.NoError;\n    this._hasAttributes = hasAttributes;\n    this._lowerCaseName = lowerCaseName;\n  }\n  parseFromString(data) {\n    this._currentFragment = [];\n    this._stack = [];\n    this._errorCode = XMLParserErrorCode.NoError;\n    this.parseXml(data);\n    if (this._errorCode !== XMLParserErrorCode.NoError) {\n      return undefined;\n    }\n    const [documentElement] = this._currentFragment;\n    if (!documentElement) {\n      return undefined;\n    }\n    return {\n      documentElement\n    };\n  }\n  onText(text) {\n    if (isWhitespaceString(text)) {\n      return;\n    }\n    const node = new SimpleDOMNode(\"#text\", text);\n    this._currentFragment.push(node);\n  }\n  onCdata(text) {\n    const node = new SimpleDOMNode(\"#text\", text);\n    this._currentFragment.push(node);\n  }\n  onBeginElement(name, attributes, isEmpty) {\n    if (this._lowerCaseName) {\n      name = name.toLowerCase();\n    }\n    const node = new SimpleDOMNode(name);\n    node.childNodes = [];\n    if (this._hasAttributes) {\n      node.attributes = attributes;\n    }\n    this._currentFragment.push(node);\n    if (isEmpty) {\n      return;\n    }\n    this._stack.push(this._currentFragment);\n    this._currentFragment = node.childNodes;\n  }\n  onEndElement(name) {\n    this._currentFragment = this._stack.pop() || [];\n    const lastElement = this._currentFragment.at(-1);\n    if (!lastElement) {\n      return null;\n    }\n    for (const childNode of lastElement.childNodes) {\n      childNode.parentNode = lastElement;\n    }\n    return lastElement;\n  }\n  onError(code) {\n    this._errorCode = code;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/metadata_parser.js\n\nclass MetadataParser {\n  constructor(data) {\n    data = this._repair(data);\n    const parser = new SimpleXMLParser({\n      lowerCaseName: true\n    });\n    const xmlDocument = parser.parseFromString(data);\n    this._metadataMap = new Map();\n    this._data = data;\n    if (xmlDocument) {\n      this._parse(xmlDocument);\n    }\n  }\n  _repair(data) {\n    return data.replace(/^[^<]+/, \"\").replaceAll(/>\\\\376\\\\377([^<]+)/g, function (all, codes) {\n      const bytes = codes.replaceAll(/\\\\([0-3])([0-7])([0-7])/g, function (code, d1, d2, d3) {\n        return String.fromCharCode(d1 * 64 + d2 * 8 + d3 * 1);\n      }).replaceAll(/&(amp|apos|gt|lt|quot);/g, function (str, name) {\n        switch (name) {\n          case \"amp\":\n            return \"&\";\n          case \"apos\":\n            return \"'\";\n          case \"gt\":\n            return \">\";\n          case \"lt\":\n            return \"<\";\n          case \"quot\":\n            return '\"';\n        }\n        throw new Error(`_repair: ${name} isn't defined.`);\n      });\n      const charBuf = [\">\"];\n      for (let i = 0, ii = bytes.length; i < ii; i += 2) {\n        const code = bytes.charCodeAt(i) * 256 + bytes.charCodeAt(i + 1);\n        if (code >= 32 && code < 127 && code !== 60 && code !== 62 && code !== 38) {\n          charBuf.push(String.fromCharCode(code));\n        } else {\n          charBuf.push(\"&#x\" + (0x10000 + code).toString(16).substring(1) + \";\");\n        }\n      }\n      return charBuf.join(\"\");\n    });\n  }\n  _getSequence(entry) {\n    const name = entry.nodeName;\n    if (name !== \"rdf:bag\" && name !== \"rdf:seq\" && name !== \"rdf:alt\") {\n      return null;\n    }\n    return entry.childNodes.filter(node => node.nodeName === \"rdf:li\");\n  }\n  _parseArray(entry) {\n    if (!entry.hasChildNodes()) {\n      return;\n    }\n    const [seqNode] = entry.childNodes;\n    const sequence = this._getSequence(seqNode) || [];\n    this._metadataMap.set(entry.nodeName, sequence.map(node => node.textContent.trim()));\n  }\n  _parse(xmlDocument) {\n    let rdf = xmlDocument.documentElement;\n    if (rdf.nodeName !== \"rdf:rdf\") {\n      rdf = rdf.firstChild;\n      while (rdf && rdf.nodeName !== \"rdf:rdf\") {\n        rdf = rdf.nextSibling;\n      }\n    }\n    if (!rdf || rdf.nodeName !== \"rdf:rdf\" || !rdf.hasChildNodes()) {\n      return;\n    }\n    for (const desc of rdf.childNodes) {\n      if (desc.nodeName !== \"rdf:description\") {\n        continue;\n      }\n      for (const entry of desc.childNodes) {\n        const name = entry.nodeName;\n        switch (name) {\n          case \"#text\":\n            continue;\n          case \"dc:creator\":\n          case \"dc:subject\":\n            this._parseArray(entry);\n            continue;\n        }\n        this._metadataMap.set(name, entry.textContent.trim());\n      }\n    }\n  }\n  get serializable() {\n    return {\n      parsedData: this._metadataMap,\n      rawData: this._data\n    };\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/decrypt_stream.js\n\nconst chunkSize = 512;\nclass DecryptStream extends DecodeStream {\n  constructor(str, maybeLength, decrypt) {\n    super(maybeLength);\n    this.str = str;\n    this.dict = str.dict;\n    this.decrypt = decrypt;\n    this.nextChunk = null;\n    this.initialized = false;\n  }\n  readBlock() {\n    let chunk;\n    if (this.initialized) {\n      chunk = this.nextChunk;\n    } else {\n      chunk = this.str.getBytes(chunkSize);\n      this.initialized = true;\n    }\n    if (!chunk || chunk.length === 0) {\n      this.eof = true;\n      return;\n    }\n    this.nextChunk = this.str.getBytes(chunkSize);\n    const hasMoreData = this.nextChunk?.length > 0;\n    const decrypt = this.decrypt;\n    chunk = decrypt(chunk, !hasMoreData);\n    const bufferLength = this.bufferLength,\n      newLength = bufferLength + chunk.length,\n      buffer = this.ensureBuffer(newLength);\n    buffer.set(chunk, bufferLength);\n    this.bufferLength = newLength;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/crypto.js\n\n\n\nclass ARCFourCipher {\n  constructor(key) {\n    this.a = 0;\n    this.b = 0;\n    const s = new Uint8Array(256);\n    const keyLength = key.length;\n    for (let i = 0; i < 256; ++i) {\n      s[i] = i;\n    }\n    for (let i = 0, j = 0; i < 256; ++i) {\n      const tmp = s[i];\n      j = j + tmp + key[i % keyLength] & 0xff;\n      s[i] = s[j];\n      s[j] = tmp;\n    }\n    this.s = s;\n  }\n  encryptBlock(data) {\n    let a = this.a,\n      b = this.b;\n    const s = this.s;\n    const n = data.length;\n    const output = new Uint8Array(n);\n    for (let i = 0; i < n; ++i) {\n      a = a + 1 & 0xff;\n      const tmp = s[a];\n      b = b + tmp & 0xff;\n      const tmp2 = s[b];\n      s[a] = tmp2;\n      s[b] = tmp;\n      output[i] = data[i] ^ s[tmp + tmp2 & 0xff];\n    }\n    this.a = a;\n    this.b = b;\n    return output;\n  }\n  decryptBlock(data) {\n    return this.encryptBlock(data);\n  }\n  encrypt(data) {\n    return this.encryptBlock(data);\n  }\n}\nconst calculateMD5 = function calculateMD5Closure() {\n  const r = new Uint8Array([7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]);\n  const k = new Int32Array([-680876936, -389564586, 606105819, -1044525330, -176418897, 1200080426, -1473231341, -45705983, 1770035416, -1958414417, -42063, -1990404162, 1804603682, -40341101, -1502002290, 1236535329, -165796510, -1069501632, 643717713, -373897302, -701558691, 38016083, -660478335, -405537848, 568446438, -1019803690, -187363961, 1163531501, -1444681467, -51403784, 1735328473, -1926607734, -378558, -2022574463, 1839030562, -35309556, -1530992060, 1272893353, -155497632, -1094730640, 681279174, -358537222, -722521979, 76029189, -640364487, -421815835, 530742520, -995338651, -198630844, 1126891415, -1416354905, -57434055, 1700485571, -1894986606, -1051523, -2054922799, 1873313359, -30611744, -1560198380, 1309151649, -145523070, -1120210379, 718787259, -343485551]);\n  function hash(data, offset, length) {\n    let h0 = 1732584193,\n      h1 = -271733879,\n      h2 = -1732584194,\n      h3 = 271733878;\n    const paddedLength = length + 72 & ~63;\n    const padded = new Uint8Array(paddedLength);\n    let i, j;\n    for (i = 0; i < length; ++i) {\n      padded[i] = data[offset++];\n    }\n    padded[i++] = 0x80;\n    const n = paddedLength - 8;\n    while (i < n) {\n      padded[i++] = 0;\n    }\n    padded[i++] = length << 3 & 0xff;\n    padded[i++] = length >> 5 & 0xff;\n    padded[i++] = length >> 13 & 0xff;\n    padded[i++] = length >> 21 & 0xff;\n    padded[i++] = length >>> 29 & 0xff;\n    padded[i++] = 0;\n    padded[i++] = 0;\n    padded[i++] = 0;\n    const w = new Int32Array(16);\n    for (i = 0; i < paddedLength;) {\n      for (j = 0; j < 16; ++j, i += 4) {\n        w[j] = padded[i] | padded[i + 1] << 8 | padded[i + 2] << 16 | padded[i + 3] << 24;\n      }\n      let a = h0,\n        b = h1,\n        c = h2,\n        d = h3,\n        f,\n        g;\n      for (j = 0; j < 64; ++j) {\n        if (j < 16) {\n          f = b & c | ~b & d;\n          g = j;\n        } else if (j < 32) {\n          f = d & b | ~d & c;\n          g = 5 * j + 1 & 15;\n        } else if (j < 48) {\n          f = b ^ c ^ d;\n          g = 3 * j + 5 & 15;\n        } else {\n          f = c ^ (b | ~d);\n          g = 7 * j & 15;\n        }\n        const tmp = d,\n          rotateArg = a + f + k[j] + w[g] | 0,\n          rotate = r[j];\n        d = c;\n        c = b;\n        b = b + (rotateArg << rotate | rotateArg >>> 32 - rotate) | 0;\n        a = tmp;\n      }\n      h0 = h0 + a | 0;\n      h1 = h1 + b | 0;\n      h2 = h2 + c | 0;\n      h3 = h3 + d | 0;\n    }\n    return new Uint8Array([h0 & 0xFF, h0 >> 8 & 0xFF, h0 >> 16 & 0xFF, h0 >>> 24 & 0xFF, h1 & 0xFF, h1 >> 8 & 0xFF, h1 >> 16 & 0xFF, h1 >>> 24 & 0xFF, h2 & 0xFF, h2 >> 8 & 0xFF, h2 >> 16 & 0xFF, h2 >>> 24 & 0xFF, h3 & 0xFF, h3 >> 8 & 0xFF, h3 >> 16 & 0xFF, h3 >>> 24 & 0xFF]);\n  }\n  return hash;\n}();\nclass Word64 {\n  constructor(highInteger, lowInteger) {\n    this.high = highInteger | 0;\n    this.low = lowInteger | 0;\n  }\n  and(word) {\n    this.high &= word.high;\n    this.low &= word.low;\n  }\n  xor(word) {\n    this.high ^= word.high;\n    this.low ^= word.low;\n  }\n  or(word) {\n    this.high |= word.high;\n    this.low |= word.low;\n  }\n  shiftRight(places) {\n    if (places >= 32) {\n      this.low = this.high >>> places - 32 | 0;\n      this.high = 0;\n    } else {\n      this.low = this.low >>> places | this.high << 32 - places;\n      this.high = this.high >>> places | 0;\n    }\n  }\n  shiftLeft(places) {\n    if (places >= 32) {\n      this.high = this.low << places - 32;\n      this.low = 0;\n    } else {\n      this.high = this.high << places | this.low >>> 32 - places;\n      this.low <<= places;\n    }\n  }\n  rotateRight(places) {\n    let low, high;\n    if (places & 32) {\n      high = this.low;\n      low = this.high;\n    } else {\n      low = this.low;\n      high = this.high;\n    }\n    places &= 31;\n    this.low = low >>> places | high << 32 - places;\n    this.high = high >>> places | low << 32 - places;\n  }\n  not() {\n    this.high = ~this.high;\n    this.low = ~this.low;\n  }\n  add(word) {\n    const lowAdd = (this.low >>> 0) + (word.low >>> 0);\n    let highAdd = (this.high >>> 0) + (word.high >>> 0);\n    if (lowAdd > 0xffffffff) {\n      highAdd += 1;\n    }\n    this.low = lowAdd | 0;\n    this.high = highAdd | 0;\n  }\n  copyTo(bytes, offset) {\n    bytes[offset] = this.high >>> 24 & 0xff;\n    bytes[offset + 1] = this.high >> 16 & 0xff;\n    bytes[offset + 2] = this.high >> 8 & 0xff;\n    bytes[offset + 3] = this.high & 0xff;\n    bytes[offset + 4] = this.low >>> 24 & 0xff;\n    bytes[offset + 5] = this.low >> 16 & 0xff;\n    bytes[offset + 6] = this.low >> 8 & 0xff;\n    bytes[offset + 7] = this.low & 0xff;\n  }\n  assign(word) {\n    this.high = word.high;\n    this.low = word.low;\n  }\n}\nconst calculateSHA256 = function calculateSHA256Closure() {\n  function rotr(x, n) {\n    return x >>> n | x << 32 - n;\n  }\n  function ch(x, y, z) {\n    return x & y ^ ~x & z;\n  }\n  function maj(x, y, z) {\n    return x & y ^ x & z ^ y & z;\n  }\n  function sigma(x) {\n    return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22);\n  }\n  function sigmaPrime(x) {\n    return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25);\n  }\n  function littleSigma(x) {\n    return rotr(x, 7) ^ rotr(x, 18) ^ x >>> 3;\n  }\n  function littleSigmaPrime(x) {\n    return rotr(x, 17) ^ rotr(x, 19) ^ x >>> 10;\n  }\n  const k = [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2];\n  function hash(data, offset, length) {\n    let h0 = 0x6a09e667,\n      h1 = 0xbb67ae85,\n      h2 = 0x3c6ef372,\n      h3 = 0xa54ff53a,\n      h4 = 0x510e527f,\n      h5 = 0x9b05688c,\n      h6 = 0x1f83d9ab,\n      h7 = 0x5be0cd19;\n    const paddedLength = Math.ceil((length + 9) / 64) * 64;\n    const padded = new Uint8Array(paddedLength);\n    let i, j;\n    for (i = 0; i < length; ++i) {\n      padded[i] = data[offset++];\n    }\n    padded[i++] = 0x80;\n    const n = paddedLength - 8;\n    while (i < n) {\n      padded[i++] = 0;\n    }\n    padded[i++] = 0;\n    padded[i++] = 0;\n    padded[i++] = 0;\n    padded[i++] = length >>> 29 & 0xff;\n    padded[i++] = length >> 21 & 0xff;\n    padded[i++] = length >> 13 & 0xff;\n    padded[i++] = length >> 5 & 0xff;\n    padded[i++] = length << 3 & 0xff;\n    const w = new Uint32Array(64);\n    for (i = 0; i < paddedLength;) {\n      for (j = 0; j < 16; ++j) {\n        w[j] = padded[i] << 24 | padded[i + 1] << 16 | padded[i + 2] << 8 | padded[i + 3];\n        i += 4;\n      }\n      for (j = 16; j < 64; ++j) {\n        w[j] = littleSigmaPrime(w[j - 2]) + w[j - 7] + littleSigma(w[j - 15]) + w[j - 16] | 0;\n      }\n      let a = h0,\n        b = h1,\n        c = h2,\n        d = h3,\n        e = h4,\n        f = h5,\n        g = h6,\n        h = h7,\n        t1,\n        t2;\n      for (j = 0; j < 64; ++j) {\n        t1 = h + sigmaPrime(e) + ch(e, f, g) + k[j] + w[j];\n        t2 = sigma(a) + maj(a, b, c);\n        h = g;\n        g = f;\n        f = e;\n        e = d + t1 | 0;\n        d = c;\n        c = b;\n        b = a;\n        a = t1 + t2 | 0;\n      }\n      h0 = h0 + a | 0;\n      h1 = h1 + b | 0;\n      h2 = h2 + c | 0;\n      h3 = h3 + d | 0;\n      h4 = h4 + e | 0;\n      h5 = h5 + f | 0;\n      h6 = h6 + g | 0;\n      h7 = h7 + h | 0;\n    }\n    return new Uint8Array([h0 >> 24 & 0xFF, h0 >> 16 & 0xFF, h0 >> 8 & 0xFF, h0 & 0xFF, h1 >> 24 & 0xFF, h1 >> 16 & 0xFF, h1 >> 8 & 0xFF, h1 & 0xFF, h2 >> 24 & 0xFF, h2 >> 16 & 0xFF, h2 >> 8 & 0xFF, h2 & 0xFF, h3 >> 24 & 0xFF, h3 >> 16 & 0xFF, h3 >> 8 & 0xFF, h3 & 0xFF, h4 >> 24 & 0xFF, h4 >> 16 & 0xFF, h4 >> 8 & 0xFF, h4 & 0xFF, h5 >> 24 & 0xFF, h5 >> 16 & 0xFF, h5 >> 8 & 0xFF, h5 & 0xFF, h6 >> 24 & 0xFF, h6 >> 16 & 0xFF, h6 >> 8 & 0xFF, h6 & 0xFF, h7 >> 24 & 0xFF, h7 >> 16 & 0xFF, h7 >> 8 & 0xFF, h7 & 0xFF]);\n  }\n  return hash;\n}();\nconst calculateSHA512 = function calculateSHA512Closure() {\n  function ch(result, x, y, z, tmp) {\n    result.assign(x);\n    result.and(y);\n    tmp.assign(x);\n    tmp.not();\n    tmp.and(z);\n    result.xor(tmp);\n  }\n  function maj(result, x, y, z, tmp) {\n    result.assign(x);\n    result.and(y);\n    tmp.assign(x);\n    tmp.and(z);\n    result.xor(tmp);\n    tmp.assign(y);\n    tmp.and(z);\n    result.xor(tmp);\n  }\n  function sigma(result, x, tmp) {\n    result.assign(x);\n    result.rotateRight(28);\n    tmp.assign(x);\n    tmp.rotateRight(34);\n    result.xor(tmp);\n    tmp.assign(x);\n    tmp.rotateRight(39);\n    result.xor(tmp);\n  }\n  function sigmaPrime(result, x, tmp) {\n    result.assign(x);\n    result.rotateRight(14);\n    tmp.assign(x);\n    tmp.rotateRight(18);\n    result.xor(tmp);\n    tmp.assign(x);\n    tmp.rotateRight(41);\n    result.xor(tmp);\n  }\n  function littleSigma(result, x, tmp) {\n    result.assign(x);\n    result.rotateRight(1);\n    tmp.assign(x);\n    tmp.rotateRight(8);\n    result.xor(tmp);\n    tmp.assign(x);\n    tmp.shiftRight(7);\n    result.xor(tmp);\n  }\n  function littleSigmaPrime(result, x, tmp) {\n    result.assign(x);\n    result.rotateRight(19);\n    tmp.assign(x);\n    tmp.rotateRight(61);\n    result.xor(tmp);\n    tmp.assign(x);\n    tmp.shiftRight(6);\n    result.xor(tmp);\n  }\n  const k = [new Word64(0x428a2f98, 0xd728ae22), new Word64(0x71374491, 0x23ef65cd), new Word64(0xb5c0fbcf, 0xec4d3b2f), new Word64(0xe9b5dba5, 0x8189dbbc), new Word64(0x3956c25b, 0xf348b538), new Word64(0x59f111f1, 0xb605d019), new Word64(0x923f82a4, 0xaf194f9b), new Word64(0xab1c5ed5, 0xda6d8118), new Word64(0xd807aa98, 0xa3030242), new Word64(0x12835b01, 0x45706fbe), new Word64(0x243185be, 0x4ee4b28c), new Word64(0x550c7dc3, 0xd5ffb4e2), new Word64(0x72be5d74, 0xf27b896f), new Word64(0x80deb1fe, 0x3b1696b1), new Word64(0x9bdc06a7, 0x25c71235), new Word64(0xc19bf174, 0xcf692694), new Word64(0xe49b69c1, 0x9ef14ad2), new Word64(0xefbe4786, 0x384f25e3), new Word64(0x0fc19dc6, 0x8b8cd5b5), new Word64(0x240ca1cc, 0x77ac9c65), new Word64(0x2de92c6f, 0x592b0275), new Word64(0x4a7484aa, 0x6ea6e483), new Word64(0x5cb0a9dc, 0xbd41fbd4), new Word64(0x76f988da, 0x831153b5), new Word64(0x983e5152, 0xee66dfab), new Word64(0xa831c66d, 0x2db43210), new Word64(0xb00327c8, 0x98fb213f), new Word64(0xbf597fc7, 0xbeef0ee4), new Word64(0xc6e00bf3, 0x3da88fc2), new Word64(0xd5a79147, 0x930aa725), new Word64(0x06ca6351, 0xe003826f), new Word64(0x14292967, 0x0a0e6e70), new Word64(0x27b70a85, 0x46d22ffc), new Word64(0x2e1b2138, 0x5c26c926), new Word64(0x4d2c6dfc, 0x5ac42aed), new Word64(0x53380d13, 0x9d95b3df), new Word64(0x650a7354, 0x8baf63de), new Word64(0x766a0abb, 0x3c77b2a8), new Word64(0x81c2c92e, 0x47edaee6), new Word64(0x92722c85, 0x1482353b), new Word64(0xa2bfe8a1, 0x4cf10364), new Word64(0xa81a664b, 0xbc423001), new Word64(0xc24b8b70, 0xd0f89791), new Word64(0xc76c51a3, 0x0654be30), new Word64(0xd192e819, 0xd6ef5218), new Word64(0xd6990624, 0x5565a910), new Word64(0xf40e3585, 0x5771202a), new Word64(0x106aa070, 0x32bbd1b8), new Word64(0x19a4c116, 0xb8d2d0c8), new Word64(0x1e376c08, 0x5141ab53), new Word64(0x2748774c, 0xdf8eeb99), new Word64(0x34b0bcb5, 0xe19b48a8), new Word64(0x391c0cb3, 0xc5c95a63), new Word64(0x4ed8aa4a, 0xe3418acb), new Word64(0x5b9cca4f, 0x7763e373), new Word64(0x682e6ff3, 0xd6b2b8a3), new Word64(0x748f82ee, 0x5defb2fc), new Word64(0x78a5636f, 0x43172f60), new Word64(0x84c87814, 0xa1f0ab72), new Word64(0x8cc70208, 0x1a6439ec), new Word64(0x90befffa, 0x23631e28), new Word64(0xa4506ceb, 0xde82bde9), new Word64(0xbef9a3f7, 0xb2c67915), new Word64(0xc67178f2, 0xe372532b), new Word64(0xca273ece, 0xea26619c), new Word64(0xd186b8c7, 0x21c0c207), new Word64(0xeada7dd6, 0xcde0eb1e), new Word64(0xf57d4f7f, 0xee6ed178), new Word64(0x06f067aa, 0x72176fba), new Word64(0x0a637dc5, 0xa2c898a6), new Word64(0x113f9804, 0xbef90dae), new Word64(0x1b710b35, 0x131c471b), new Word64(0x28db77f5, 0x23047d84), new Word64(0x32caab7b, 0x40c72493), new Word64(0x3c9ebe0a, 0x15c9bebc), new Word64(0x431d67c4, 0x9c100d4c), new Word64(0x4cc5d4be, 0xcb3e42b6), new Word64(0x597f299c, 0xfc657e2a), new Word64(0x5fcb6fab, 0x3ad6faec), new Word64(0x6c44198c, 0x4a475817)];\n  function hash(data, offset, length, mode384 = false) {\n    let h0, h1, h2, h3, h4, h5, h6, h7;\n    if (!mode384) {\n      h0 = new Word64(0x6a09e667, 0xf3bcc908);\n      h1 = new Word64(0xbb67ae85, 0x84caa73b);\n      h2 = new Word64(0x3c6ef372, 0xfe94f82b);\n      h3 = new Word64(0xa54ff53a, 0x5f1d36f1);\n      h4 = new Word64(0x510e527f, 0xade682d1);\n      h5 = new Word64(0x9b05688c, 0x2b3e6c1f);\n      h6 = new Word64(0x1f83d9ab, 0xfb41bd6b);\n      h7 = new Word64(0x5be0cd19, 0x137e2179);\n    } else {\n      h0 = new Word64(0xcbbb9d5d, 0xc1059ed8);\n      h1 = new Word64(0x629a292a, 0x367cd507);\n      h2 = new Word64(0x9159015a, 0x3070dd17);\n      h3 = new Word64(0x152fecd8, 0xf70e5939);\n      h4 = new Word64(0x67332667, 0xffc00b31);\n      h5 = new Word64(0x8eb44a87, 0x68581511);\n      h6 = new Word64(0xdb0c2e0d, 0x64f98fa7);\n      h7 = new Word64(0x47b5481d, 0xbefa4fa4);\n    }\n    const paddedLength = Math.ceil((length + 17) / 128) * 128;\n    const padded = new Uint8Array(paddedLength);\n    let i, j;\n    for (i = 0; i < length; ++i) {\n      padded[i] = data[offset++];\n    }\n    padded[i++] = 0x80;\n    const n = paddedLength - 16;\n    while (i < n) {\n      padded[i++] = 0;\n    }\n    padded[i++] = 0;\n    padded[i++] = 0;\n    padded[i++] = 0;\n    padded[i++] = 0;\n    padded[i++] = 0;\n    padded[i++] = 0;\n    padded[i++] = 0;\n    padded[i++] = 0;\n    padded[i++] = 0;\n    padded[i++] = 0;\n    padded[i++] = 0;\n    padded[i++] = length >>> 29 & 0xff;\n    padded[i++] = length >> 21 & 0xff;\n    padded[i++] = length >> 13 & 0xff;\n    padded[i++] = length >> 5 & 0xff;\n    padded[i++] = length << 3 & 0xff;\n    const w = new Array(80);\n    for (i = 0; i < 80; i++) {\n      w[i] = new Word64(0, 0);\n    }\n    let a = new Word64(0, 0),\n      b = new Word64(0, 0),\n      c = new Word64(0, 0);\n    let d = new Word64(0, 0),\n      e = new Word64(0, 0),\n      f = new Word64(0, 0);\n    let g = new Word64(0, 0),\n      h = new Word64(0, 0);\n    const t1 = new Word64(0, 0),\n      t2 = new Word64(0, 0);\n    const tmp1 = new Word64(0, 0),\n      tmp2 = new Word64(0, 0);\n    let tmp3;\n    for (i = 0; i < paddedLength;) {\n      for (j = 0; j < 16; ++j) {\n        w[j].high = padded[i] << 24 | padded[i + 1] << 16 | padded[i + 2] << 8 | padded[i + 3];\n        w[j].low = padded[i + 4] << 24 | padded[i + 5] << 16 | padded[i + 6] << 8 | padded[i + 7];\n        i += 8;\n      }\n      for (j = 16; j < 80; ++j) {\n        tmp3 = w[j];\n        littleSigmaPrime(tmp3, w[j - 2], tmp2);\n        tmp3.add(w[j - 7]);\n        littleSigma(tmp1, w[j - 15], tmp2);\n        tmp3.add(tmp1);\n        tmp3.add(w[j - 16]);\n      }\n      a.assign(h0);\n      b.assign(h1);\n      c.assign(h2);\n      d.assign(h3);\n      e.assign(h4);\n      f.assign(h5);\n      g.assign(h6);\n      h.assign(h7);\n      for (j = 0; j < 80; ++j) {\n        t1.assign(h);\n        sigmaPrime(tmp1, e, tmp2);\n        t1.add(tmp1);\n        ch(tmp1, e, f, g, tmp2);\n        t1.add(tmp1);\n        t1.add(k[j]);\n        t1.add(w[j]);\n        sigma(t2, a, tmp2);\n        maj(tmp1, a, b, c, tmp2);\n        t2.add(tmp1);\n        tmp3 = h;\n        h = g;\n        g = f;\n        f = e;\n        d.add(t1);\n        e = d;\n        d = c;\n        c = b;\n        b = a;\n        tmp3.assign(t1);\n        tmp3.add(t2);\n        a = tmp3;\n      }\n      h0.add(a);\n      h1.add(b);\n      h2.add(c);\n      h3.add(d);\n      h4.add(e);\n      h5.add(f);\n      h6.add(g);\n      h7.add(h);\n    }\n    let result;\n    if (!mode384) {\n      result = new Uint8Array(64);\n      h0.copyTo(result, 0);\n      h1.copyTo(result, 8);\n      h2.copyTo(result, 16);\n      h3.copyTo(result, 24);\n      h4.copyTo(result, 32);\n      h5.copyTo(result, 40);\n      h6.copyTo(result, 48);\n      h7.copyTo(result, 56);\n    } else {\n      result = new Uint8Array(48);\n      h0.copyTo(result, 0);\n      h1.copyTo(result, 8);\n      h2.copyTo(result, 16);\n      h3.copyTo(result, 24);\n      h4.copyTo(result, 32);\n      h5.copyTo(result, 40);\n    }\n    return result;\n  }\n  return hash;\n}();\nfunction calculateSHA384(data, offset, length) {\n  return calculateSHA512(data, offset, length, true);\n}\nclass NullCipher {\n  decryptBlock(data) {\n    return data;\n  }\n  encrypt(data) {\n    return data;\n  }\n}\nclass AESBaseCipher {\n  constructor() {\n    if (this.constructor === AESBaseCipher) {\n      unreachable(\"Cannot initialize AESBaseCipher.\");\n    }\n    this._s = new Uint8Array([0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16]);\n    this._inv_s = new Uint8Array([0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d]);\n    this._mix = new Uint32Array([0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f, 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba, 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3]);\n    this._mixCol = new Uint8Array(256);\n    for (let i = 0; i < 256; i++) {\n      this._mixCol[i] = i < 128 ? i << 1 : i << 1 ^ 0x1b;\n    }\n    this.buffer = new Uint8Array(16);\n    this.bufferPosition = 0;\n  }\n  _expandKey(cipherKey) {\n    unreachable(\"Cannot call `_expandKey` on the base class\");\n  }\n  _decrypt(input, key) {\n    let t, u, v;\n    const state = new Uint8Array(16);\n    state.set(input);\n    for (let j = 0, k = this._keySize; j < 16; ++j, ++k) {\n      state[j] ^= key[k];\n    }\n    for (let i = this._cyclesOfRepetition - 1; i >= 1; --i) {\n      t = state[13];\n      state[13] = state[9];\n      state[9] = state[5];\n      state[5] = state[1];\n      state[1] = t;\n      t = state[14];\n      u = state[10];\n      state[14] = state[6];\n      state[10] = state[2];\n      state[6] = t;\n      state[2] = u;\n      t = state[15];\n      u = state[11];\n      v = state[7];\n      state[15] = state[3];\n      state[11] = t;\n      state[7] = u;\n      state[3] = v;\n      for (let j = 0; j < 16; ++j) {\n        state[j] = this._inv_s[state[j]];\n      }\n      for (let j = 0, k = i * 16; j < 16; ++j, ++k) {\n        state[j] ^= key[k];\n      }\n      for (let j = 0; j < 16; j += 4) {\n        const s0 = this._mix[state[j]];\n        const s1 = this._mix[state[j + 1]];\n        const s2 = this._mix[state[j + 2]];\n        const s3 = this._mix[state[j + 3]];\n        t = s0 ^ s1 >>> 8 ^ s1 << 24 ^ s2 >>> 16 ^ s2 << 16 ^ s3 >>> 24 ^ s3 << 8;\n        state[j] = t >>> 24 & 0xff;\n        state[j + 1] = t >> 16 & 0xff;\n        state[j + 2] = t >> 8 & 0xff;\n        state[j + 3] = t & 0xff;\n      }\n    }\n    t = state[13];\n    state[13] = state[9];\n    state[9] = state[5];\n    state[5] = state[1];\n    state[1] = t;\n    t = state[14];\n    u = state[10];\n    state[14] = state[6];\n    state[10] = state[2];\n    state[6] = t;\n    state[2] = u;\n    t = state[15];\n    u = state[11];\n    v = state[7];\n    state[15] = state[3];\n    state[11] = t;\n    state[7] = u;\n    state[3] = v;\n    for (let j = 0; j < 16; ++j) {\n      state[j] = this._inv_s[state[j]];\n      state[j] ^= key[j];\n    }\n    return state;\n  }\n  _encrypt(input, key) {\n    const s = this._s;\n    let t, u, v;\n    const state = new Uint8Array(16);\n    state.set(input);\n    for (let j = 0; j < 16; ++j) {\n      state[j] ^= key[j];\n    }\n    for (let i = 1; i < this._cyclesOfRepetition; i++) {\n      for (let j = 0; j < 16; ++j) {\n        state[j] = s[state[j]];\n      }\n      v = state[1];\n      state[1] = state[5];\n      state[5] = state[9];\n      state[9] = state[13];\n      state[13] = v;\n      v = state[2];\n      u = state[6];\n      state[2] = state[10];\n      state[6] = state[14];\n      state[10] = v;\n      state[14] = u;\n      v = state[3];\n      u = state[7];\n      t = state[11];\n      state[3] = state[15];\n      state[7] = v;\n      state[11] = u;\n      state[15] = t;\n      for (let j = 0; j < 16; j += 4) {\n        const s0 = state[j + 0];\n        const s1 = state[j + 1];\n        const s2 = state[j + 2];\n        const s3 = state[j + 3];\n        t = s0 ^ s1 ^ s2 ^ s3;\n        state[j + 0] ^= t ^ this._mixCol[s0 ^ s1];\n        state[j + 1] ^= t ^ this._mixCol[s1 ^ s2];\n        state[j + 2] ^= t ^ this._mixCol[s2 ^ s3];\n        state[j + 3] ^= t ^ this._mixCol[s3 ^ s0];\n      }\n      for (let j = 0, k = i * 16; j < 16; ++j, ++k) {\n        state[j] ^= key[k];\n      }\n    }\n    for (let j = 0; j < 16; ++j) {\n      state[j] = s[state[j]];\n    }\n    v = state[1];\n    state[1] = state[5];\n    state[5] = state[9];\n    state[9] = state[13];\n    state[13] = v;\n    v = state[2];\n    u = state[6];\n    state[2] = state[10];\n    state[6] = state[14];\n    state[10] = v;\n    state[14] = u;\n    v = state[3];\n    u = state[7];\n    t = state[11];\n    state[3] = state[15];\n    state[7] = v;\n    state[11] = u;\n    state[15] = t;\n    for (let j = 0, k = this._keySize; j < 16; ++j, ++k) {\n      state[j] ^= key[k];\n    }\n    return state;\n  }\n  _decryptBlock2(data, finalize) {\n    const sourceLength = data.length;\n    let buffer = this.buffer,\n      bufferLength = this.bufferPosition;\n    const result = [];\n    let iv = this.iv;\n    for (let i = 0; i < sourceLength; ++i) {\n      buffer[bufferLength] = data[i];\n      ++bufferLength;\n      if (bufferLength < 16) {\n        continue;\n      }\n      const plain = this._decrypt(buffer, this._key);\n      for (let j = 0; j < 16; ++j) {\n        plain[j] ^= iv[j];\n      }\n      iv = buffer;\n      result.push(plain);\n      buffer = new Uint8Array(16);\n      bufferLength = 0;\n    }\n    this.buffer = buffer;\n    this.bufferLength = bufferLength;\n    this.iv = iv;\n    if (result.length === 0) {\n      return new Uint8Array(0);\n    }\n    let outputLength = 16 * result.length;\n    if (finalize) {\n      const lastBlock = result.at(-1);\n      let psLen = lastBlock[15];\n      if (psLen <= 16) {\n        for (let i = 15, ii = 16 - psLen; i >= ii; --i) {\n          if (lastBlock[i] !== psLen) {\n            psLen = 0;\n            break;\n          }\n        }\n        outputLength -= psLen;\n        result[result.length - 1] = lastBlock.subarray(0, 16 - psLen);\n      }\n    }\n    const output = new Uint8Array(outputLength);\n    for (let i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) {\n      output.set(result[i], j);\n    }\n    return output;\n  }\n  decryptBlock(data, finalize, iv = null) {\n    const sourceLength = data.length;\n    const buffer = this.buffer;\n    let bufferLength = this.bufferPosition;\n    if (iv) {\n      this.iv = iv;\n    } else {\n      for (let i = 0; bufferLength < 16 && i < sourceLength; ++i, ++bufferLength) {\n        buffer[bufferLength] = data[i];\n      }\n      if (bufferLength < 16) {\n        this.bufferLength = bufferLength;\n        return new Uint8Array(0);\n      }\n      this.iv = buffer;\n      data = data.subarray(16);\n    }\n    this.buffer = new Uint8Array(16);\n    this.bufferLength = 0;\n    this.decryptBlock = this._decryptBlock2;\n    return this.decryptBlock(data, finalize);\n  }\n  encrypt(data, iv) {\n    const sourceLength = data.length;\n    let buffer = this.buffer,\n      bufferLength = this.bufferPosition;\n    const result = [];\n    if (!iv) {\n      iv = new Uint8Array(16);\n    }\n    for (let i = 0; i < sourceLength; ++i) {\n      buffer[bufferLength] = data[i];\n      ++bufferLength;\n      if (bufferLength < 16) {\n        continue;\n      }\n      for (let j = 0; j < 16; ++j) {\n        buffer[j] ^= iv[j];\n      }\n      const cipher = this._encrypt(buffer, this._key);\n      iv = cipher;\n      result.push(cipher);\n      buffer = new Uint8Array(16);\n      bufferLength = 0;\n    }\n    this.buffer = buffer;\n    this.bufferLength = bufferLength;\n    this.iv = iv;\n    if (result.length === 0) {\n      return new Uint8Array(0);\n    }\n    const outputLength = 16 * result.length;\n    const output = new Uint8Array(outputLength);\n    for (let i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) {\n      output.set(result[i], j);\n    }\n    return output;\n  }\n}\nclass AES128Cipher extends AESBaseCipher {\n  constructor(key) {\n    super();\n    this._cyclesOfRepetition = 10;\n    this._keySize = 160;\n    this._rcon = new Uint8Array([0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d]);\n    this._key = this._expandKey(key);\n  }\n  _expandKey(cipherKey) {\n    const b = 176;\n    const s = this._s;\n    const rcon = this._rcon;\n    const result = new Uint8Array(b);\n    result.set(cipherKey);\n    for (let j = 16, i = 1; j < b; ++i) {\n      let t1 = result[j - 3];\n      let t2 = result[j - 2];\n      let t3 = result[j - 1];\n      let t4 = result[j - 4];\n      t1 = s[t1];\n      t2 = s[t2];\n      t3 = s[t3];\n      t4 = s[t4];\n      t1 ^= rcon[i];\n      for (let n = 0; n < 4; ++n) {\n        result[j] = t1 ^= result[j - 16];\n        j++;\n        result[j] = t2 ^= result[j - 16];\n        j++;\n        result[j] = t3 ^= result[j - 16];\n        j++;\n        result[j] = t4 ^= result[j - 16];\n        j++;\n      }\n    }\n    return result;\n  }\n}\nclass AES256Cipher extends AESBaseCipher {\n  constructor(key) {\n    super();\n    this._cyclesOfRepetition = 14;\n    this._keySize = 224;\n    this._key = this._expandKey(key);\n  }\n  _expandKey(cipherKey) {\n    const b = 240;\n    const s = this._s;\n    const result = new Uint8Array(b);\n    result.set(cipherKey);\n    let r = 1;\n    let t1, t2, t3, t4;\n    for (let j = 32, i = 1; j < b; ++i) {\n      if (j % 32 === 16) {\n        t1 = s[t1];\n        t2 = s[t2];\n        t3 = s[t3];\n        t4 = s[t4];\n      } else if (j % 32 === 0) {\n        t1 = result[j - 3];\n        t2 = result[j - 2];\n        t3 = result[j - 1];\n        t4 = result[j - 4];\n        t1 = s[t1];\n        t2 = s[t2];\n        t3 = s[t3];\n        t4 = s[t4];\n        t1 ^= r;\n        if ((r <<= 1) >= 256) {\n          r = (r ^ 0x1b) & 0xff;\n        }\n      }\n      for (let n = 0; n < 4; ++n) {\n        result[j] = t1 ^= result[j - 32];\n        j++;\n        result[j] = t2 ^= result[j - 32];\n        j++;\n        result[j] = t3 ^= result[j - 32];\n        j++;\n        result[j] = t4 ^= result[j - 32];\n        j++;\n      }\n    }\n    return result;\n  }\n}\nclass PDF17 {\n  checkOwnerPassword(password, ownerValidationSalt, userBytes, ownerPassword) {\n    const hashData = new Uint8Array(password.length + 56);\n    hashData.set(password, 0);\n    hashData.set(ownerValidationSalt, password.length);\n    hashData.set(userBytes, password.length + ownerValidationSalt.length);\n    const result = calculateSHA256(hashData, 0, hashData.length);\n    return isArrayEqual(result, ownerPassword);\n  }\n  checkUserPassword(password, userValidationSalt, userPassword) {\n    const hashData = new Uint8Array(password.length + 8);\n    hashData.set(password, 0);\n    hashData.set(userValidationSalt, password.length);\n    const result = calculateSHA256(hashData, 0, hashData.length);\n    return isArrayEqual(result, userPassword);\n  }\n  getOwnerKey(password, ownerKeySalt, userBytes, ownerEncryption) {\n    const hashData = new Uint8Array(password.length + 56);\n    hashData.set(password, 0);\n    hashData.set(ownerKeySalt, password.length);\n    hashData.set(userBytes, password.length + ownerKeySalt.length);\n    const key = calculateSHA256(hashData, 0, hashData.length);\n    const cipher = new AES256Cipher(key);\n    return cipher.decryptBlock(ownerEncryption, false, new Uint8Array(16));\n  }\n  getUserKey(password, userKeySalt, userEncryption) {\n    const hashData = new Uint8Array(password.length + 8);\n    hashData.set(password, 0);\n    hashData.set(userKeySalt, password.length);\n    const key = calculateSHA256(hashData, 0, hashData.length);\n    const cipher = new AES256Cipher(key);\n    return cipher.decryptBlock(userEncryption, false, new Uint8Array(16));\n  }\n}\nclass PDF20 {\n  _hash(password, input, userBytes) {\n    let k = calculateSHA256(input, 0, input.length).subarray(0, 32);\n    let e = [0];\n    let i = 0;\n    while (i < 64 || e.at(-1) > i - 32) {\n      const combinedLength = password.length + k.length + userBytes.length,\n        combinedArray = new Uint8Array(combinedLength);\n      let writeOffset = 0;\n      combinedArray.set(password, writeOffset);\n      writeOffset += password.length;\n      combinedArray.set(k, writeOffset);\n      writeOffset += k.length;\n      combinedArray.set(userBytes, writeOffset);\n      const k1 = new Uint8Array(combinedLength * 64);\n      for (let j = 0, pos = 0; j < 64; j++, pos += combinedLength) {\n        k1.set(combinedArray, pos);\n      }\n      const cipher = new AES128Cipher(k.subarray(0, 16));\n      e = cipher.encrypt(k1, k.subarray(16, 32));\n      const remainder = e.slice(0, 16).reduce((a, b) => a + b, 0) % 3;\n      if (remainder === 0) {\n        k = calculateSHA256(e, 0, e.length);\n      } else if (remainder === 1) {\n        k = calculateSHA384(e, 0, e.length);\n      } else if (remainder === 2) {\n        k = calculateSHA512(e, 0, e.length);\n      }\n      i++;\n    }\n    return k.subarray(0, 32);\n  }\n  checkOwnerPassword(password, ownerValidationSalt, userBytes, ownerPassword) {\n    const hashData = new Uint8Array(password.length + 56);\n    hashData.set(password, 0);\n    hashData.set(ownerValidationSalt, password.length);\n    hashData.set(userBytes, password.length + ownerValidationSalt.length);\n    const result = this._hash(password, hashData, userBytes);\n    return isArrayEqual(result, ownerPassword);\n  }\n  checkUserPassword(password, userValidationSalt, userPassword) {\n    const hashData = new Uint8Array(password.length + 8);\n    hashData.set(password, 0);\n    hashData.set(userValidationSalt, password.length);\n    const result = this._hash(password, hashData, []);\n    return isArrayEqual(result, userPassword);\n  }\n  getOwnerKey(password, ownerKeySalt, userBytes, ownerEncryption) {\n    const hashData = new Uint8Array(password.length + 56);\n    hashData.set(password, 0);\n    hashData.set(ownerKeySalt, password.length);\n    hashData.set(userBytes, password.length + ownerKeySalt.length);\n    const key = this._hash(password, hashData, userBytes);\n    const cipher = new AES256Cipher(key);\n    return cipher.decryptBlock(ownerEncryption, false, new Uint8Array(16));\n  }\n  getUserKey(password, userKeySalt, userEncryption) {\n    const hashData = new Uint8Array(password.length + 8);\n    hashData.set(password, 0);\n    hashData.set(userKeySalt, password.length);\n    const key = this._hash(password, hashData, []);\n    const cipher = new AES256Cipher(key);\n    return cipher.decryptBlock(userEncryption, false, new Uint8Array(16));\n  }\n}\nclass CipherTransform {\n  constructor(stringCipherConstructor, streamCipherConstructor) {\n    this.StringCipherConstructor = stringCipherConstructor;\n    this.StreamCipherConstructor = streamCipherConstructor;\n  }\n  createStream(stream, length) {\n    const cipher = new this.StreamCipherConstructor();\n    return new DecryptStream(stream, length, function cipherTransformDecryptStream(data, finalize) {\n      return cipher.decryptBlock(data, finalize);\n    });\n  }\n  decryptString(s) {\n    const cipher = new this.StringCipherConstructor();\n    let data = stringToBytes(s);\n    data = cipher.decryptBlock(data, true);\n    return bytesToString(data);\n  }\n  encryptString(s) {\n    const cipher = new this.StringCipherConstructor();\n    if (cipher instanceof AESBaseCipher) {\n      const strLen = s.length;\n      const pad = 16 - strLen % 16;\n      s += String.fromCharCode(pad).repeat(pad);\n      const iv = new Uint8Array(16);\n      if (typeof crypto !== \"undefined\") {\n        crypto.getRandomValues(iv);\n      } else {\n        for (let i = 0; i < 16; i++) {\n          iv[i] = Math.floor(256 * Math.random());\n        }\n      }\n      let data = stringToBytes(s);\n      data = cipher.encrypt(data, iv);\n      const buf = new Uint8Array(16 + data.length);\n      buf.set(iv);\n      buf.set(data, 16);\n      return bytesToString(buf);\n    }\n    let data = stringToBytes(s);\n    data = cipher.encrypt(data);\n    return bytesToString(data);\n  }\n}\nclass CipherTransformFactory {\n  static #defaultPasswordBytes = new Uint8Array([0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08, 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80, 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a]);\n  #createEncryptionKey20(revision, password, ownerPassword, ownerValidationSalt, ownerKeySalt, uBytes, userPassword, userValidationSalt, userKeySalt, ownerEncryption, userEncryption, perms) {\n    if (password) {\n      const passwordLength = Math.min(127, password.length);\n      password = password.subarray(0, passwordLength);\n    } else {\n      password = [];\n    }\n    const pdfAlgorithm = revision === 6 ? new PDF20() : new PDF17();\n    if (pdfAlgorithm.checkUserPassword(password, userValidationSalt, userPassword)) {\n      return pdfAlgorithm.getUserKey(password, userKeySalt, userEncryption);\n    } else if (password.length && pdfAlgorithm.checkOwnerPassword(password, ownerValidationSalt, uBytes, ownerPassword)) {\n      return pdfAlgorithm.getOwnerKey(password, ownerKeySalt, uBytes, ownerEncryption);\n    }\n    return null;\n  }\n  #prepareKeyData(fileId, password, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata) {\n    const hashDataSize = 40 + ownerPassword.length + fileId.length;\n    const hashData = new Uint8Array(hashDataSize);\n    let i = 0,\n      j,\n      n;\n    if (password) {\n      n = Math.min(32, password.length);\n      for (; i < n; ++i) {\n        hashData[i] = password[i];\n      }\n    }\n    j = 0;\n    while (i < 32) {\n      hashData[i++] = CipherTransformFactory.#defaultPasswordBytes[j++];\n    }\n    for (j = 0, n = ownerPassword.length; j < n; ++j) {\n      hashData[i++] = ownerPassword[j];\n    }\n    hashData[i++] = flags & 0xff;\n    hashData[i++] = flags >> 8 & 0xff;\n    hashData[i++] = flags >> 16 & 0xff;\n    hashData[i++] = flags >>> 24 & 0xff;\n    for (j = 0, n = fileId.length; j < n; ++j) {\n      hashData[i++] = fileId[j];\n    }\n    if (revision >= 4 && !encryptMetadata) {\n      hashData[i++] = 0xff;\n      hashData[i++] = 0xff;\n      hashData[i++] = 0xff;\n      hashData[i++] = 0xff;\n    }\n    let hash = calculateMD5(hashData, 0, i);\n    const keyLengthInBytes = keyLength >> 3;\n    if (revision >= 3) {\n      for (j = 0; j < 50; ++j) {\n        hash = calculateMD5(hash, 0, keyLengthInBytes);\n      }\n    }\n    const encryptionKey = hash.subarray(0, keyLengthInBytes);\n    let cipher, checkData;\n    if (revision >= 3) {\n      for (i = 0; i < 32; ++i) {\n        hashData[i] = CipherTransformFactory.#defaultPasswordBytes[i];\n      }\n      for (j = 0, n = fileId.length; j < n; ++j) {\n        hashData[i++] = fileId[j];\n      }\n      cipher = new ARCFourCipher(encryptionKey);\n      checkData = cipher.encryptBlock(calculateMD5(hashData, 0, i));\n      n = encryptionKey.length;\n      const derivedKey = new Uint8Array(n);\n      for (j = 1; j <= 19; ++j) {\n        for (let k = 0; k < n; ++k) {\n          derivedKey[k] = encryptionKey[k] ^ j;\n        }\n        cipher = new ARCFourCipher(derivedKey);\n        checkData = cipher.encryptBlock(checkData);\n      }\n      for (j = 0, n = checkData.length; j < n; ++j) {\n        if (userPassword[j] !== checkData[j]) {\n          return null;\n        }\n      }\n    } else {\n      cipher = new ARCFourCipher(encryptionKey);\n      checkData = cipher.encryptBlock(CipherTransformFactory.#defaultPasswordBytes);\n      for (j = 0, n = checkData.length; j < n; ++j) {\n        if (userPassword[j] !== checkData[j]) {\n          return null;\n        }\n      }\n    }\n    return encryptionKey;\n  }\n  #decodeUserPassword(password, ownerPassword, revision, keyLength) {\n    const hashData = new Uint8Array(32);\n    let i = 0;\n    const n = Math.min(32, password.length);\n    for (; i < n; ++i) {\n      hashData[i] = password[i];\n    }\n    let j = 0;\n    while (i < 32) {\n      hashData[i++] = CipherTransformFactory.#defaultPasswordBytes[j++];\n    }\n    let hash = calculateMD5(hashData, 0, i);\n    const keyLengthInBytes = keyLength >> 3;\n    if (revision >= 3) {\n      for (j = 0; j < 50; ++j) {\n        hash = calculateMD5(hash, 0, hash.length);\n      }\n    }\n    let cipher, userPassword;\n    if (revision >= 3) {\n      userPassword = ownerPassword;\n      const derivedKey = new Uint8Array(keyLengthInBytes);\n      for (j = 19; j >= 0; j--) {\n        for (let k = 0; k < keyLengthInBytes; ++k) {\n          derivedKey[k] = hash[k] ^ j;\n        }\n        cipher = new ARCFourCipher(derivedKey);\n        userPassword = cipher.encryptBlock(userPassword);\n      }\n    } else {\n      cipher = new ARCFourCipher(hash.subarray(0, keyLengthInBytes));\n      userPassword = cipher.encryptBlock(ownerPassword);\n    }\n    return userPassword;\n  }\n  #buildObjectKey(num, gen, encryptionKey, isAes = false) {\n    const key = new Uint8Array(encryptionKey.length + 9);\n    const n = encryptionKey.length;\n    let i;\n    for (i = 0; i < n; ++i) {\n      key[i] = encryptionKey[i];\n    }\n    key[i++] = num & 0xff;\n    key[i++] = num >> 8 & 0xff;\n    key[i++] = num >> 16 & 0xff;\n    key[i++] = gen & 0xff;\n    key[i++] = gen >> 8 & 0xff;\n    if (isAes) {\n      key[i++] = 0x73;\n      key[i++] = 0x41;\n      key[i++] = 0x6c;\n      key[i++] = 0x54;\n    }\n    const hash = calculateMD5(key, 0, i);\n    return hash.subarray(0, Math.min(encryptionKey.length + 5, 16));\n  }\n  #buildCipherConstructor(cf, name, num, gen, key) {\n    if (!(name instanceof Name)) {\n      throw new FormatError(\"Invalid crypt filter name.\");\n    }\n    const self = this;\n    const cryptFilter = cf.get(name.name);\n    const cfm = cryptFilter?.get(\"CFM\");\n    if (!cfm || cfm.name === \"None\") {\n      return function () {\n        return new NullCipher();\n      };\n    }\n    if (cfm.name === \"V2\") {\n      return function () {\n        return new ARCFourCipher(self.#buildObjectKey(num, gen, key, false));\n      };\n    }\n    if (cfm.name === \"AESV2\") {\n      return function () {\n        return new AES128Cipher(self.#buildObjectKey(num, gen, key, true));\n      };\n    }\n    if (cfm.name === \"AESV3\") {\n      return function () {\n        return new AES256Cipher(key);\n      };\n    }\n    throw new FormatError(\"Unknown crypto method\");\n  }\n  constructor(dict, fileId, password) {\n    const filter = dict.get(\"Filter\");\n    if (!isName(filter, \"Standard\")) {\n      throw new FormatError(\"unknown encryption method\");\n    }\n    this.filterName = filter.name;\n    this.dict = dict;\n    const algorithm = dict.get(\"V\");\n    if (!Number.isInteger(algorithm) || algorithm !== 1 && algorithm !== 2 && algorithm !== 4 && algorithm !== 5) {\n      throw new FormatError(\"unsupported encryption algorithm\");\n    }\n    this.algorithm = algorithm;\n    let keyLength = dict.get(\"Length\");\n    if (!keyLength) {\n      if (algorithm <= 3) {\n        keyLength = 40;\n      } else {\n        const cfDict = dict.get(\"CF\");\n        const streamCryptoName = dict.get(\"StmF\");\n        if (cfDict instanceof Dict && streamCryptoName instanceof Name) {\n          cfDict.suppressEncryption = true;\n          const handlerDict = cfDict.get(streamCryptoName.name);\n          keyLength = handlerDict?.get(\"Length\") || 128;\n          if (keyLength < 40) {\n            keyLength <<= 3;\n          }\n        }\n      }\n    }\n    if (!Number.isInteger(keyLength) || keyLength < 40 || keyLength % 8 !== 0) {\n      throw new FormatError(\"invalid key length\");\n    }\n    const ownerBytes = stringToBytes(dict.get(\"O\")),\n      userBytes = stringToBytes(dict.get(\"U\"));\n    const ownerPassword = ownerBytes.subarray(0, 32);\n    const userPassword = userBytes.subarray(0, 32);\n    const flags = dict.get(\"P\");\n    const revision = dict.get(\"R\");\n    const encryptMetadata = (algorithm === 4 || algorithm === 5) && dict.get(\"EncryptMetadata\") !== false;\n    this.encryptMetadata = encryptMetadata;\n    const fileIdBytes = stringToBytes(fileId);\n    let passwordBytes;\n    if (password) {\n      if (revision === 6) {\n        try {\n          password = utf8StringToString(password);\n        } catch {\n          warn(\"CipherTransformFactory: Unable to convert UTF8 encoded password.\");\n        }\n      }\n      passwordBytes = stringToBytes(password);\n    }\n    let encryptionKey;\n    if (algorithm !== 5) {\n      encryptionKey = this.#prepareKeyData(fileIdBytes, passwordBytes, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata);\n    } else {\n      const ownerValidationSalt = ownerBytes.subarray(32, 40);\n      const ownerKeySalt = ownerBytes.subarray(40, 48);\n      const uBytes = userBytes.subarray(0, 48);\n      const userValidationSalt = userBytes.subarray(32, 40);\n      const userKeySalt = userBytes.subarray(40, 48);\n      const ownerEncryption = stringToBytes(dict.get(\"OE\"));\n      const userEncryption = stringToBytes(dict.get(\"UE\"));\n      const perms = stringToBytes(dict.get(\"Perms\"));\n      encryptionKey = this.#createEncryptionKey20(revision, passwordBytes, ownerPassword, ownerValidationSalt, ownerKeySalt, uBytes, userPassword, userValidationSalt, userKeySalt, ownerEncryption, userEncryption, perms);\n    }\n    if (!encryptionKey && !password) {\n      throw new PasswordException(\"No password given\", PasswordResponses.NEED_PASSWORD);\n    } else if (!encryptionKey && password) {\n      const decodedPassword = this.#decodeUserPassword(passwordBytes, ownerPassword, revision, keyLength);\n      encryptionKey = this.#prepareKeyData(fileIdBytes, decodedPassword, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata);\n    }\n    if (!encryptionKey) {\n      throw new PasswordException(\"Incorrect Password\", PasswordResponses.INCORRECT_PASSWORD);\n    }\n    this.encryptionKey = encryptionKey;\n    if (algorithm >= 4) {\n      const cf = dict.get(\"CF\");\n      if (cf instanceof Dict) {\n        cf.suppressEncryption = true;\n      }\n      this.cf = cf;\n      this.stmf = dict.get(\"StmF\") || Name.get(\"Identity\");\n      this.strf = dict.get(\"StrF\") || Name.get(\"Identity\");\n      this.eff = dict.get(\"EFF\") || this.stmf;\n    }\n  }\n  createCipherTransform(num, gen) {\n    if (this.algorithm === 4 || this.algorithm === 5) {\n      return new CipherTransform(this.#buildCipherConstructor(this.cf, this.strf, num, gen, this.encryptionKey), this.#buildCipherConstructor(this.cf, this.stmf, num, gen, this.encryptionKey));\n    }\n    const key = this.#buildObjectKey(num, gen, this.encryptionKey, false);\n    const cipherConstructor = function () {\n      return new ARCFourCipher(key);\n    };\n    return new CipherTransform(cipherConstructor, cipherConstructor);\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/writer.js\n\n\n\n\n\n\n\nasync function writeObject(ref, obj, buffer, {\n  encrypt = null\n}) {\n  const transform = encrypt?.createCipherTransform(ref.num, ref.gen);\n  buffer.push(`${ref.num} ${ref.gen} obj\\n`);\n  if (obj instanceof Dict) {\n    await writeDict(obj, buffer, transform);\n  } else if (obj instanceof BaseStream) {\n    await writeStream(obj, buffer, transform);\n  } else if (Array.isArray(obj) || ArrayBuffer.isView(obj)) {\n    await writeArray(obj, buffer, transform);\n  }\n  buffer.push(\"\\nendobj\\n\");\n}\nasync function writeDict(dict, buffer, transform) {\n  buffer.push(\"<<\");\n  for (const key of dict.getKeys()) {\n    buffer.push(` /${escapePDFName(key)} `);\n    await writeValue(dict.getRaw(key), buffer, transform);\n  }\n  buffer.push(\">>\");\n}\nasync function writeStream(stream, buffer, transform) {\n  let bytes = stream.getBytes();\n  const {\n    dict\n  } = stream;\n  const [filter, params] = await Promise.all([dict.getAsync(\"Filter\"), dict.getAsync(\"DecodeParms\")]);\n  const filterZero = Array.isArray(filter) ? await dict.xref.fetchIfRefAsync(filter[0]) : filter;\n  const isFilterZeroFlateDecode = isName(filterZero, \"FlateDecode\");\n  const MIN_LENGTH_FOR_COMPRESSING = 256;\n  if (bytes.length >= MIN_LENGTH_FOR_COMPRESSING || isFilterZeroFlateDecode) {\n    try {\n      const cs = new CompressionStream(\"deflate\");\n      const writer = cs.writable.getWriter();\n      writer.write(bytes);\n      writer.close();\n      const buf = await new Response(cs.readable).arrayBuffer();\n      bytes = new Uint8Array(buf);\n      let newFilter, newParams;\n      if (!filter) {\n        newFilter = Name.get(\"FlateDecode\");\n      } else if (!isFilterZeroFlateDecode) {\n        newFilter = Array.isArray(filter) ? [Name.get(\"FlateDecode\"), ...filter] : [Name.get(\"FlateDecode\"), filter];\n        if (params) {\n          newParams = Array.isArray(params) ? [null, ...params] : [null, params];\n        }\n      }\n      if (newFilter) {\n        dict.set(\"Filter\", newFilter);\n      }\n      if (newParams) {\n        dict.set(\"DecodeParms\", newParams);\n      }\n    } catch (ex) {\n      info(`writeStream - cannot compress data: \"${ex}\".`);\n    }\n  }\n  let string = bytesToString(bytes);\n  if (transform) {\n    string = transform.encryptString(string);\n  }\n  dict.set(\"Length\", string.length);\n  await writeDict(dict, buffer, transform);\n  buffer.push(\" stream\\n\", string, \"\\nendstream\");\n}\nasync function writeArray(array, buffer, transform) {\n  buffer.push(\"[\");\n  let first = true;\n  for (const val of array) {\n    if (!first) {\n      buffer.push(\" \");\n    } else {\n      first = false;\n    }\n    await writeValue(val, buffer, transform);\n  }\n  buffer.push(\"]\");\n}\nasync function writeValue(value, buffer, transform) {\n  if (value instanceof Name) {\n    buffer.push(`/${escapePDFName(value.name)}`);\n  } else if (value instanceof Ref) {\n    buffer.push(`${value.num} ${value.gen} R`);\n  } else if (Array.isArray(value) || ArrayBuffer.isView(value)) {\n    await writeArray(value, buffer, transform);\n  } else if (typeof value === \"string\") {\n    if (transform) {\n      value = transform.encryptString(value);\n    }\n    buffer.push(`(${escapeString(value)})`);\n  } else if (typeof value === \"number\") {\n    buffer.push(numberToString(value));\n  } else if (typeof value === \"boolean\") {\n    buffer.push(value.toString());\n  } else if (value instanceof Dict) {\n    await writeDict(value, buffer, transform);\n  } else if (value instanceof BaseStream) {\n    await writeStream(value, buffer, transform);\n  } else if (value === null) {\n    buffer.push(\"null\");\n  } else {\n    warn(`Unhandled value in writer: ${typeof value}, please file a bug.`);\n  }\n}\nfunction writeInt(number, size, offset, buffer) {\n  for (let i = size + offset - 1; i > offset - 1; i--) {\n    buffer[i] = number & 0xff;\n    number >>= 8;\n  }\n  return offset + size;\n}\nfunction writeString(string, offset, buffer) {\n  for (let i = 0, len = string.length; i < len; i++) {\n    buffer[offset + i] = string.charCodeAt(i) & 0xff;\n  }\n}\nfunction computeMD5(filesize, xrefInfo) {\n  const time = Math.floor(Date.now() / 1000);\n  const filename = xrefInfo.filename || \"\";\n  const md5Buffer = [time.toString(), filename, filesize.toString()];\n  let md5BufferLen = md5Buffer.reduce((a, str) => a + str.length, 0);\n  for (const value of Object.values(xrefInfo.info)) {\n    md5Buffer.push(value);\n    md5BufferLen += value.length;\n  }\n  const array = new Uint8Array(md5BufferLen);\n  let offset = 0;\n  for (const str of md5Buffer) {\n    writeString(str, offset, array);\n    offset += str.length;\n  }\n  return bytesToString(calculateMD5(array));\n}\nfunction writeXFADataForAcroform(str, newRefs) {\n  const xml = new SimpleXMLParser({\n    hasAttributes: true\n  }).parseFromString(str);\n  for (const {\n    xfa\n  } of newRefs) {\n    if (!xfa) {\n      continue;\n    }\n    const {\n      path,\n      value\n    } = xfa;\n    if (!path) {\n      continue;\n    }\n    const nodePath = parseXFAPath(path);\n    let node = xml.documentElement.searchNode(nodePath, 0);\n    if (!node && nodePath.length > 1) {\n      node = xml.documentElement.searchNode([nodePath.at(-1)], 0);\n    }\n    if (node) {\n      node.childNodes = Array.isArray(value) ? value.map(val => new SimpleDOMNode(\"value\", val)) : [new SimpleDOMNode(\"#text\", value)];\n    } else {\n      warn(`Node not found for path: ${path}`);\n    }\n  }\n  const buffer = [];\n  xml.documentElement.dump(buffer);\n  return buffer.join(\"\");\n}\nasync function updateAcroform({\n  xref,\n  acroForm,\n  acroFormRef,\n  hasXfa,\n  hasXfaDatasetsEntry,\n  xfaDatasetsRef,\n  needAppearances,\n  newRefs\n}) {\n  if (hasXfa && !hasXfaDatasetsEntry && !xfaDatasetsRef) {\n    warn(\"XFA - Cannot save it\");\n  }\n  if (!needAppearances && (!hasXfa || !xfaDatasetsRef || hasXfaDatasetsEntry)) {\n    return;\n  }\n  const dict = acroForm.clone();\n  if (hasXfa && !hasXfaDatasetsEntry) {\n    const newXfa = acroForm.get(\"XFA\").slice();\n    newXfa.splice(2, 0, \"datasets\");\n    newXfa.splice(3, 0, xfaDatasetsRef);\n    dict.set(\"XFA\", newXfa);\n  }\n  if (needAppearances) {\n    dict.set(\"NeedAppearances\", true);\n  }\n  const buffer = [];\n  await writeObject(acroFormRef, dict, buffer, xref);\n  newRefs.push({\n    ref: acroFormRef,\n    data: buffer.join(\"\")\n  });\n}\nfunction updateXFA({\n  xfaData,\n  xfaDatasetsRef,\n  newRefs,\n  xref\n}) {\n  if (xfaData === null) {\n    const datasets = xref.fetchIfRef(xfaDatasetsRef);\n    xfaData = writeXFADataForAcroform(datasets.getString(), newRefs);\n  }\n  const encrypt = xref.encrypt;\n  if (encrypt) {\n    const transform = encrypt.createCipherTransform(xfaDatasetsRef.num, xfaDatasetsRef.gen);\n    xfaData = transform.encryptString(xfaData);\n  }\n  const data = `${xfaDatasetsRef.num} ${xfaDatasetsRef.gen} obj\\n` + `<< /Type /EmbeddedFile /Length ${xfaData.length}>>\\nstream\\n` + xfaData + \"\\nendstream\\nendobj\\n\";\n  newRefs.push({\n    ref: xfaDatasetsRef,\n    data\n  });\n}\nasync function getXRefTable(xrefInfo, baseOffset, newRefs, newXref, buffer) {\n  buffer.push(\"xref\\n\");\n  const indexes = getIndexes(newRefs);\n  let indexesPosition = 0;\n  for (const {\n    ref,\n    data\n  } of newRefs) {\n    if (ref.num === indexes[indexesPosition]) {\n      buffer.push(`${indexes[indexesPosition]} ${indexes[indexesPosition + 1]}\\n`);\n      indexesPosition += 2;\n    }\n    if (data !== null) {\n      buffer.push(`${baseOffset.toString().padStart(10, \"0\")} ${Math.min(ref.gen, 0xffff).toString().padStart(5, \"0\")} n\\r\\n`);\n      baseOffset += data.length;\n    } else {\n      buffer.push(`0000000000 ${Math.min(ref.gen + 1, 0xffff).toString().padStart(5, \"0\")} f\\r\\n`);\n    }\n  }\n  computeIDs(baseOffset, xrefInfo, newXref);\n  buffer.push(\"trailer\\n\");\n  await writeDict(newXref, buffer);\n  buffer.push(\"\\nstartxref\\n\", baseOffset.toString(), \"\\n%%EOF\\n\");\n}\nfunction getIndexes(newRefs) {\n  const indexes = [];\n  for (const {\n    ref\n  } of newRefs) {\n    if (ref.num === indexes.at(-2) + indexes.at(-1)) {\n      indexes[indexes.length - 1] += 1;\n    } else {\n      indexes.push(ref.num, 1);\n    }\n  }\n  return indexes;\n}\nasync function getXRefStreamTable(xrefInfo, baseOffset, newRefs, newXref, buffer) {\n  const xrefTableData = [];\n  let maxOffset = 0;\n  let maxGen = 0;\n  for (const {\n    ref,\n    data\n  } of newRefs) {\n    let gen;\n    maxOffset = Math.max(maxOffset, baseOffset);\n    if (data !== null) {\n      gen = Math.min(ref.gen, 0xffff);\n      xrefTableData.push([1, baseOffset, gen]);\n      baseOffset += data.length;\n    } else {\n      gen = Math.min(ref.gen + 1, 0xffff);\n      xrefTableData.push([0, 0, gen]);\n    }\n    maxGen = Math.max(maxGen, gen);\n  }\n  newXref.set(\"Index\", getIndexes(newRefs));\n  const offsetSize = getSizeInBytes(maxOffset);\n  const maxGenSize = getSizeInBytes(maxGen);\n  const sizes = [1, offsetSize, maxGenSize];\n  newXref.set(\"W\", sizes);\n  computeIDs(baseOffset, xrefInfo, newXref);\n  const structSize = sizes.reduce((a, x) => a + x, 0);\n  const data = new Uint8Array(structSize * xrefTableData.length);\n  const stream = new Stream(data);\n  stream.dict = newXref;\n  let offset = 0;\n  for (const [type, objOffset, gen] of xrefTableData) {\n    offset = writeInt(type, sizes[0], offset, data);\n    offset = writeInt(objOffset, sizes[1], offset, data);\n    offset = writeInt(gen, sizes[2], offset, data);\n  }\n  await writeObject(xrefInfo.newRef, stream, buffer, {});\n  buffer.push(\"startxref\\n\", baseOffset.toString(), \"\\n%%EOF\\n\");\n}\nfunction computeIDs(baseOffset, xrefInfo, newXref) {\n  if (Array.isArray(xrefInfo.fileIds) && xrefInfo.fileIds.length > 0) {\n    const md5 = computeMD5(baseOffset, xrefInfo);\n    newXref.set(\"ID\", [xrefInfo.fileIds[0], md5]);\n  }\n}\nfunction getTrailerDict(xrefInfo, newRefs, useXrefStream) {\n  const newXref = new Dict(null);\n  newXref.set(\"Prev\", xrefInfo.startXRef);\n  const refForXrefTable = xrefInfo.newRef;\n  if (useXrefStream) {\n    newRefs.push({\n      ref: refForXrefTable,\n      data: \"\"\n    });\n    newXref.set(\"Size\", refForXrefTable.num + 1);\n    newXref.set(\"Type\", Name.get(\"XRef\"));\n  } else {\n    newXref.set(\"Size\", refForXrefTable.num);\n  }\n  if (xrefInfo.rootRef !== null) {\n    newXref.set(\"Root\", xrefInfo.rootRef);\n  }\n  if (xrefInfo.infoRef !== null) {\n    newXref.set(\"Info\", xrefInfo.infoRef);\n  }\n  if (xrefInfo.encryptRef !== null) {\n    newXref.set(\"Encrypt\", xrefInfo.encryptRef);\n  }\n  return newXref;\n}\nasync function incrementalUpdate({\n  originalData,\n  xrefInfo,\n  newRefs,\n  xref = null,\n  hasXfa = false,\n  xfaDatasetsRef = null,\n  hasXfaDatasetsEntry = false,\n  needAppearances,\n  acroFormRef = null,\n  acroForm = null,\n  xfaData = null,\n  useXrefStream = false\n}) {\n  await updateAcroform({\n    xref,\n    acroForm,\n    acroFormRef,\n    hasXfa,\n    hasXfaDatasetsEntry,\n    xfaDatasetsRef,\n    needAppearances,\n    newRefs\n  });\n  if (hasXfa) {\n    updateXFA({\n      xfaData,\n      xfaDatasetsRef,\n      newRefs,\n      xref\n    });\n  }\n  const buffer = [];\n  let baseOffset = originalData.length;\n  const lastByte = originalData.at(-1);\n  if (lastByte !== 0x0a && lastByte !== 0x0d) {\n    buffer.push(\"\\n\");\n    baseOffset += 1;\n  }\n  const newXref = getTrailerDict(xrefInfo, newRefs, useXrefStream);\n  newRefs = newRefs.sort((a, b) => a.ref.num - b.ref.num);\n  for (const {\n    data\n  } of newRefs) {\n    if (data !== null) {\n      buffer.push(data);\n    }\n  }\n  await (useXrefStream ? getXRefStreamTable(xrefInfo, baseOffset, newRefs, newXref, buffer) : getXRefTable(xrefInfo, baseOffset, newRefs, newXref, buffer));\n  const totalLength = buffer.reduce((a, str) => a + str.length, originalData.length);\n  const array = new Uint8Array(totalLength);\n  array.set(originalData);\n  let offset = originalData.length;\n  for (const str of buffer) {\n    writeString(str, offset, array);\n    offset += str.length;\n  }\n  return array;\n}\n\n;// CONCATENATED MODULE: ./src/core/struct_tree.js\n\n\n\n\nconst MAX_DEPTH = 40;\nconst StructElementType = {\n  PAGE_CONTENT: 1,\n  STREAM_CONTENT: 2,\n  OBJECT: 3,\n  ANNOTATION: 4,\n  ELEMENT: 5\n};\nclass StructTreeRoot {\n  constructor(rootDict, rootRef) {\n    this.dict = rootDict;\n    this.ref = rootRef instanceof Ref ? rootRef : null;\n    this.roleMap = new Map();\n    this.structParentIds = null;\n  }\n  init() {\n    this.readRoleMap();\n  }\n  #addIdToPage(pageRef, id, type) {\n    if (!(pageRef instanceof Ref) || id < 0) {\n      return;\n    }\n    this.structParentIds ||= new RefSetCache();\n    let ids = this.structParentIds.get(pageRef);\n    if (!ids) {\n      ids = [];\n      this.structParentIds.put(pageRef, ids);\n    }\n    ids.push([id, type]);\n  }\n  addAnnotationIdToPage(pageRef, id) {\n    this.#addIdToPage(pageRef, id, StructElementType.ANNOTATION);\n  }\n  readRoleMap() {\n    const roleMapDict = this.dict.get(\"RoleMap\");\n    if (!(roleMapDict instanceof Dict)) {\n      return;\n    }\n    roleMapDict.forEach((key, value) => {\n      if (!(value instanceof Name)) {\n        return;\n      }\n      this.roleMap.set(key, value.name);\n    });\n  }\n  static async canCreateStructureTree({\n    catalogRef,\n    pdfManager,\n    newAnnotationsByPage\n  }) {\n    if (!(catalogRef instanceof Ref)) {\n      warn(\"Cannot save the struct tree: no catalog reference.\");\n      return false;\n    }\n    let nextKey = 0;\n    let hasNothingToUpdate = true;\n    for (const [pageIndex, elements] of newAnnotationsByPage) {\n      const {\n        ref: pageRef\n      } = await pdfManager.getPage(pageIndex);\n      if (!(pageRef instanceof Ref)) {\n        warn(`Cannot save the struct tree: page ${pageIndex} has no ref.`);\n        hasNothingToUpdate = true;\n        break;\n      }\n      for (const element of elements) {\n        if (element.accessibilityData?.type) {\n          element.parentTreeId = nextKey++;\n          hasNothingToUpdate = false;\n        }\n      }\n    }\n    if (hasNothingToUpdate) {\n      for (const elements of newAnnotationsByPage.values()) {\n        for (const element of elements) {\n          delete element.parentTreeId;\n        }\n      }\n      return false;\n    }\n    return true;\n  }\n  static async createStructureTree({\n    newAnnotationsByPage,\n    xref,\n    catalogRef,\n    pdfManager,\n    newRefs\n  }) {\n    const root = pdfManager.catalog.cloneDict();\n    const cache = new RefSetCache();\n    cache.put(catalogRef, root);\n    const structTreeRootRef = xref.getNewTemporaryRef();\n    root.set(\"StructTreeRoot\", structTreeRootRef);\n    const structTreeRoot = new Dict(xref);\n    structTreeRoot.set(\"Type\", Name.get(\"StructTreeRoot\"));\n    const parentTreeRef = xref.getNewTemporaryRef();\n    structTreeRoot.set(\"ParentTree\", parentTreeRef);\n    const kids = [];\n    structTreeRoot.set(\"K\", kids);\n    cache.put(structTreeRootRef, structTreeRoot);\n    const parentTree = new Dict(xref);\n    const nums = [];\n    parentTree.set(\"Nums\", nums);\n    const nextKey = await this.#writeKids({\n      newAnnotationsByPage,\n      structTreeRootRef,\n      kids,\n      nums,\n      xref,\n      pdfManager,\n      cache\n    });\n    structTreeRoot.set(\"ParentTreeNextKey\", nextKey);\n    cache.put(parentTreeRef, parentTree);\n    const buffer = [];\n    for (const [ref, obj] of cache.items()) {\n      buffer.length = 0;\n      await writeObject(ref, obj, buffer, xref);\n      newRefs.push({\n        ref,\n        data: buffer.join(\"\")\n      });\n    }\n  }\n  async canUpdateStructTree({\n    pdfManager,\n    xref,\n    newAnnotationsByPage\n  }) {\n    if (!this.ref) {\n      warn(\"Cannot update the struct tree: no root reference.\");\n      return false;\n    }\n    let nextKey = this.dict.get(\"ParentTreeNextKey\");\n    if (!Number.isInteger(nextKey) || nextKey < 0) {\n      warn(\"Cannot update the struct tree: invalid next key.\");\n      return false;\n    }\n    const parentTree = this.dict.get(\"ParentTree\");\n    if (!(parentTree instanceof Dict)) {\n      warn(\"Cannot update the struct tree: ParentTree isn't a dict.\");\n      return false;\n    }\n    const nums = parentTree.get(\"Nums\");\n    if (!Array.isArray(nums)) {\n      warn(\"Cannot update the struct tree: nums isn't an array.\");\n      return false;\n    }\n    const numberTree = new NumberTree(parentTree, xref);\n    for (const pageIndex of newAnnotationsByPage.keys()) {\n      const {\n        pageDict\n      } = await pdfManager.getPage(pageIndex);\n      if (!pageDict.has(\"StructParents\")) {\n        continue;\n      }\n      const id = pageDict.get(\"StructParents\");\n      if (!Number.isInteger(id) || !Array.isArray(numberTree.get(id))) {\n        warn(`Cannot save the struct tree: page ${pageIndex} has a wrong id.`);\n        return false;\n      }\n    }\n    let hasNothingToUpdate = true;\n    for (const [pageIndex, elements] of newAnnotationsByPage) {\n      const {\n        pageDict\n      } = await pdfManager.getPage(pageIndex);\n      StructTreeRoot.#collectParents({\n        elements,\n        xref: this.dict.xref,\n        pageDict,\n        numberTree\n      });\n      for (const element of elements) {\n        if (element.accessibilityData?.type) {\n          element.parentTreeId = nextKey++;\n          hasNothingToUpdate = false;\n        }\n      }\n    }\n    if (hasNothingToUpdate) {\n      for (const elements of newAnnotationsByPage.values()) {\n        for (const element of elements) {\n          delete element.parentTreeId;\n          delete element.structTreeParent;\n        }\n      }\n      return false;\n    }\n    return true;\n  }\n  async updateStructureTree({\n    newAnnotationsByPage,\n    pdfManager,\n    newRefs\n  }) {\n    const xref = this.dict.xref;\n    const structTreeRoot = this.dict.clone();\n    const structTreeRootRef = this.ref;\n    const cache = new RefSetCache();\n    cache.put(structTreeRootRef, structTreeRoot);\n    let parentTreeRef = structTreeRoot.getRaw(\"ParentTree\");\n    let parentTree;\n    if (parentTreeRef instanceof Ref) {\n      parentTree = xref.fetch(parentTreeRef);\n    } else {\n      parentTree = parentTreeRef;\n      parentTreeRef = xref.getNewTemporaryRef();\n      structTreeRoot.set(\"ParentTree\", parentTreeRef);\n    }\n    parentTree = parentTree.clone();\n    cache.put(parentTreeRef, parentTree);\n    let nums = parentTree.getRaw(\"Nums\");\n    let numsRef = null;\n    if (nums instanceof Ref) {\n      numsRef = nums;\n      nums = xref.fetch(numsRef);\n    }\n    nums = nums.slice();\n    if (!numsRef) {\n      parentTree.set(\"Nums\", nums);\n    }\n    const newNextkey = await StructTreeRoot.#writeKids({\n      newAnnotationsByPage,\n      structTreeRootRef,\n      kids: null,\n      nums,\n      xref,\n      pdfManager,\n      cache\n    });\n    structTreeRoot.set(\"ParentTreeNextKey\", newNextkey);\n    if (numsRef) {\n      cache.put(numsRef, nums);\n    }\n    const buffer = [];\n    for (const [ref, obj] of cache.items()) {\n      buffer.length = 0;\n      await writeObject(ref, obj, buffer, xref);\n      newRefs.push({\n        ref,\n        data: buffer.join(\"\")\n      });\n    }\n  }\n  static async #writeKids({\n    newAnnotationsByPage,\n    structTreeRootRef,\n    kids,\n    nums,\n    xref,\n    pdfManager,\n    cache\n  }) {\n    const objr = Name.get(\"OBJR\");\n    let nextKey = -Infinity;\n    for (const [pageIndex, elements] of newAnnotationsByPage) {\n      const {\n        ref: pageRef\n      } = await pdfManager.getPage(pageIndex);\n      const isPageRef = pageRef instanceof Ref;\n      for (const {\n        accessibilityData,\n        ref,\n        parentTreeId,\n        structTreeParent\n      } of elements) {\n        if (!accessibilityData?.type) {\n          continue;\n        }\n        const {\n          type,\n          title,\n          lang,\n          alt,\n          expanded,\n          actualText\n        } = accessibilityData;\n        nextKey = Math.max(nextKey, parentTreeId);\n        const tagRef = xref.getNewTemporaryRef();\n        const tagDict = new Dict(xref);\n        tagDict.set(\"S\", Name.get(type));\n        if (title) {\n          tagDict.set(\"T\", title);\n        }\n        if (lang) {\n          tagDict.set(\"Lang\", lang);\n        }\n        if (alt) {\n          tagDict.set(\"Alt\", alt);\n        }\n        if (expanded) {\n          tagDict.set(\"E\", expanded);\n        }\n        if (actualText) {\n          tagDict.set(\"ActualText\", actualText);\n        }\n        await this.#updateParentTag({\n          structTreeParent,\n          tagDict,\n          newTagRef: tagRef,\n          structTreeRootRef,\n          fallbackKids: kids,\n          xref,\n          cache\n        });\n        const objDict = new Dict(xref);\n        tagDict.set(\"K\", objDict);\n        objDict.set(\"Type\", objr);\n        if (isPageRef) {\n          objDict.set(\"Pg\", pageRef);\n        }\n        objDict.set(\"Obj\", ref);\n        cache.put(tagRef, tagDict);\n        nums.push(parentTreeId, tagRef);\n      }\n    }\n    return nextKey + 1;\n  }\n  static #collectParents({\n    elements,\n    xref,\n    pageDict,\n    numberTree\n  }) {\n    const idToElements = new Map();\n    for (const element of elements) {\n      if (element.structTreeParentId) {\n        const id = parseInt(element.structTreeParentId.split(\"_mc\")[1], 10);\n        let elems = idToElements.get(id);\n        if (!elems) {\n          elems = [];\n          idToElements.set(id, elems);\n        }\n        elems.push(element);\n      }\n    }\n    const id = pageDict.get(\"StructParents\");\n    if (!Number.isInteger(id)) {\n      return;\n    }\n    const parentArray = numberTree.get(id);\n    const updateElement = (kid, pageKid, kidRef) => {\n      const elems = idToElements.get(kid);\n      if (elems) {\n        const parentRef = pageKid.getRaw(\"P\");\n        const parentDict = xref.fetchIfRef(parentRef);\n        if (parentRef instanceof Ref && parentDict instanceof Dict) {\n          const params = {\n            ref: kidRef,\n            dict: pageKid\n          };\n          for (const element of elems) {\n            element.structTreeParent = params;\n          }\n        }\n        return true;\n      }\n      return false;\n    };\n    for (const kidRef of parentArray) {\n      if (!(kidRef instanceof Ref)) {\n        continue;\n      }\n      const pageKid = xref.fetch(kidRef);\n      const k = pageKid.get(\"K\");\n      if (Number.isInteger(k)) {\n        updateElement(k, pageKid, kidRef);\n        continue;\n      }\n      if (!Array.isArray(k)) {\n        continue;\n      }\n      for (let kid of k) {\n        kid = xref.fetchIfRef(kid);\n        if (Number.isInteger(kid) && updateElement(kid, pageKid, kidRef)) {\n          break;\n        }\n        if (!(kid instanceof Dict)) {\n          continue;\n        }\n        if (!isName(kid.get(\"Type\"), \"MCR\")) {\n          break;\n        }\n        const mcid = kid.get(\"MCID\");\n        if (Number.isInteger(mcid) && updateElement(mcid, pageKid, kidRef)) {\n          break;\n        }\n      }\n    }\n  }\n  static async #updateParentTag({\n    structTreeParent,\n    tagDict,\n    newTagRef,\n    structTreeRootRef,\n    fallbackKids,\n    xref,\n    cache\n  }) {\n    let ref = null;\n    let parentRef;\n    if (structTreeParent) {\n      ({\n        ref\n      } = structTreeParent);\n      parentRef = structTreeParent.dict.getRaw(\"P\") || structTreeRootRef;\n    } else {\n      parentRef = structTreeRootRef;\n    }\n    tagDict.set(\"P\", parentRef);\n    const parentDict = xref.fetchIfRef(parentRef);\n    if (!parentDict) {\n      fallbackKids.push(newTagRef);\n      return;\n    }\n    let cachedParentDict = cache.get(parentRef);\n    if (!cachedParentDict) {\n      cachedParentDict = parentDict.clone();\n      cache.put(parentRef, cachedParentDict);\n    }\n    const parentKidsRaw = cachedParentDict.getRaw(\"K\");\n    let cachedParentKids = parentKidsRaw instanceof Ref ? cache.get(parentKidsRaw) : null;\n    if (!cachedParentKids) {\n      cachedParentKids = xref.fetchIfRef(parentKidsRaw);\n      cachedParentKids = Array.isArray(cachedParentKids) ? cachedParentKids.slice() : [parentKidsRaw];\n      const parentKidsRef = xref.getNewTemporaryRef();\n      cachedParentDict.set(\"K\", parentKidsRef);\n      cache.put(parentKidsRef, cachedParentKids);\n    }\n    const index = cachedParentKids.indexOf(ref);\n    cachedParentKids.splice(index >= 0 ? index + 1 : cachedParentKids.length, 0, newTagRef);\n  }\n}\nclass StructElementNode {\n  constructor(tree, dict) {\n    this.tree = tree;\n    this.dict = dict;\n    this.kids = [];\n    this.parseKids();\n  }\n  get role() {\n    const nameObj = this.dict.get(\"S\");\n    const name = nameObj instanceof Name ? nameObj.name : \"\";\n    const {\n      root\n    } = this.tree;\n    if (root.roleMap.has(name)) {\n      return root.roleMap.get(name);\n    }\n    return name;\n  }\n  parseKids() {\n    let pageObjId = null;\n    const objRef = this.dict.getRaw(\"Pg\");\n    if (objRef instanceof Ref) {\n      pageObjId = objRef.toString();\n    }\n    const kids = this.dict.get(\"K\");\n    if (Array.isArray(kids)) {\n      for (const kid of kids) {\n        const element = this.parseKid(pageObjId, kid);\n        if (element) {\n          this.kids.push(element);\n        }\n      }\n    } else {\n      const element = this.parseKid(pageObjId, kids);\n      if (element) {\n        this.kids.push(element);\n      }\n    }\n  }\n  parseKid(pageObjId, kid) {\n    if (Number.isInteger(kid)) {\n      if (this.tree.pageDict.objId !== pageObjId) {\n        return null;\n      }\n      return new StructElement({\n        type: StructElementType.PAGE_CONTENT,\n        mcid: kid,\n        pageObjId\n      });\n    }\n    let kidDict = null;\n    if (kid instanceof Ref) {\n      kidDict = this.dict.xref.fetch(kid);\n    } else if (kid instanceof Dict) {\n      kidDict = kid;\n    }\n    if (!kidDict) {\n      return null;\n    }\n    const pageRef = kidDict.getRaw(\"Pg\");\n    if (pageRef instanceof Ref) {\n      pageObjId = pageRef.toString();\n    }\n    const type = kidDict.get(\"Type\") instanceof Name ? kidDict.get(\"Type\").name : null;\n    if (type === \"MCR\") {\n      if (this.tree.pageDict.objId !== pageObjId) {\n        return null;\n      }\n      const kidRef = kidDict.getRaw(\"Stm\");\n      return new StructElement({\n        type: StructElementType.STREAM_CONTENT,\n        refObjId: kidRef instanceof Ref ? kidRef.toString() : null,\n        pageObjId,\n        mcid: kidDict.get(\"MCID\")\n      });\n    }\n    if (type === \"OBJR\") {\n      if (this.tree.pageDict.objId !== pageObjId) {\n        return null;\n      }\n      const kidRef = kidDict.getRaw(\"Obj\");\n      return new StructElement({\n        type: StructElementType.OBJECT,\n        refObjId: kidRef instanceof Ref ? kidRef.toString() : null,\n        pageObjId\n      });\n    }\n    return new StructElement({\n      type: StructElementType.ELEMENT,\n      dict: kidDict\n    });\n  }\n}\nclass StructElement {\n  constructor({\n    type,\n    dict = null,\n    mcid = null,\n    pageObjId = null,\n    refObjId = null\n  }) {\n    this.type = type;\n    this.dict = dict;\n    this.mcid = mcid;\n    this.pageObjId = pageObjId;\n    this.refObjId = refObjId;\n    this.parentNode = null;\n  }\n}\nclass StructTreePage {\n  constructor(structTreeRoot, pageDict) {\n    this.root = structTreeRoot;\n    this.rootDict = structTreeRoot ? structTreeRoot.dict : null;\n    this.pageDict = pageDict;\n    this.nodes = [];\n  }\n  parse(pageRef) {\n    if (!this.root || !this.rootDict) {\n      return;\n    }\n    const parentTree = this.rootDict.get(\"ParentTree\");\n    if (!parentTree) {\n      return;\n    }\n    const id = this.pageDict.get(\"StructParents\");\n    const ids = pageRef instanceof Ref && this.root.structParentIds?.get(pageRef);\n    if (!Number.isInteger(id) && !ids) {\n      return;\n    }\n    const map = new Map();\n    const numberTree = new NumberTree(parentTree, this.rootDict.xref);\n    if (Number.isInteger(id)) {\n      const parentArray = numberTree.get(id);\n      if (Array.isArray(parentArray)) {\n        for (const ref of parentArray) {\n          if (ref instanceof Ref) {\n            this.addNode(this.rootDict.xref.fetch(ref), map);\n          }\n        }\n      }\n    }\n    if (!ids) {\n      return;\n    }\n    for (const [elemId, type] of ids) {\n      const obj = numberTree.get(elemId);\n      if (obj) {\n        const elem = this.addNode(this.rootDict.xref.fetchIfRef(obj), map);\n        if (elem?.kids?.length === 1 && elem.kids[0].type === StructElementType.OBJECT) {\n          elem.kids[0].type = type;\n        }\n      }\n    }\n  }\n  addNode(dict, map, level = 0) {\n    if (level > MAX_DEPTH) {\n      warn(\"StructTree MAX_DEPTH reached.\");\n      return null;\n    }\n    if (map.has(dict)) {\n      return map.get(dict);\n    }\n    const element = new StructElementNode(this, dict);\n    map.set(dict, element);\n    const parent = dict.get(\"P\");\n    if (!parent || isName(parent.get(\"Type\"), \"StructTreeRoot\")) {\n      if (!this.addTopLevelNode(dict, element)) {\n        map.delete(dict);\n      }\n      return element;\n    }\n    const parentNode = this.addNode(parent, map, level + 1);\n    if (!parentNode) {\n      return element;\n    }\n    let save = false;\n    for (const kid of parentNode.kids) {\n      if (kid.type === StructElementType.ELEMENT && kid.dict === dict) {\n        kid.parentNode = element;\n        save = true;\n      }\n    }\n    if (!save) {\n      map.delete(dict);\n    }\n    return element;\n  }\n  addTopLevelNode(dict, element) {\n    const obj = this.rootDict.get(\"K\");\n    if (!obj) {\n      return false;\n    }\n    if (obj instanceof Dict) {\n      if (obj.objId !== dict.objId) {\n        return false;\n      }\n      this.nodes[0] = element;\n      return true;\n    }\n    if (!Array.isArray(obj)) {\n      return true;\n    }\n    let save = false;\n    for (let i = 0; i < obj.length; i++) {\n      const kidRef = obj[i];\n      if (kidRef?.toString() === dict.objId) {\n        this.nodes[i] = element;\n        save = true;\n      }\n    }\n    return save;\n  }\n  get serializable() {\n    function nodeToSerializable(node, parent, level = 0) {\n      if (level > MAX_DEPTH) {\n        warn(\"StructTree too deep to be fully serialized.\");\n        return;\n      }\n      const obj = Object.create(null);\n      obj.role = node.role;\n      obj.children = [];\n      parent.children.push(obj);\n      const alt = node.dict.get(\"Alt\");\n      if (typeof alt === \"string\") {\n        obj.alt = stringToPDFString(alt);\n      }\n      const lang = node.dict.get(\"Lang\");\n      if (typeof lang === \"string\") {\n        obj.lang = stringToPDFString(lang);\n      }\n      for (const kid of node.kids) {\n        const kidElement = kid.type === StructElementType.ELEMENT ? kid.parentNode : null;\n        if (kidElement) {\n          nodeToSerializable(kidElement, obj, level + 1);\n          continue;\n        } else if (kid.type === StructElementType.PAGE_CONTENT || kid.type === StructElementType.STREAM_CONTENT) {\n          obj.children.push({\n            type: \"content\",\n            id: `p${kid.pageObjId}_mc${kid.mcid}`\n          });\n        } else if (kid.type === StructElementType.OBJECT) {\n          obj.children.push({\n            type: \"object\",\n            id: kid.refObjId\n          });\n        } else if (kid.type === StructElementType.ANNOTATION) {\n          obj.children.push({\n            type: \"annotation\",\n            id: `${AnnotationPrefix}${kid.refObjId}`\n          });\n        }\n      }\n    }\n    const root = Object.create(null);\n    root.children = [];\n    root.role = \"Root\";\n    for (const child of this.nodes) {\n      if (!child) {\n        continue;\n      }\n      nodeToSerializable(child, root);\n    }\n    return root;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/catalog.js\n\n\n\n\n\n\n\n\n\n\n\nfunction isValidExplicitDest(dest) {\n  if (!Array.isArray(dest) || dest.length < 2) {\n    return false;\n  }\n  const [page, zoom, ...args] = dest;\n  if (!(page instanceof Ref) && !Number.isInteger(page)) {\n    return false;\n  }\n  if (!(zoom instanceof Name)) {\n    return false;\n  }\n  let allowNull = true;\n  switch (zoom.name) {\n    case \"XYZ\":\n      if (args.length !== 3) {\n        return false;\n      }\n      break;\n    case \"Fit\":\n    case \"FitB\":\n      return args.length === 0;\n    case \"FitH\":\n    case \"FitBH\":\n    case \"FitV\":\n    case \"FitBV\":\n      if (args.length !== 1) {\n        return false;\n      }\n      break;\n    case \"FitR\":\n      if (args.length !== 4) {\n        return false;\n      }\n      allowNull = false;\n      break;\n    default:\n      return false;\n  }\n  for (const arg of args) {\n    if (!(typeof arg === \"number\" || allowNull && arg === null)) {\n      return false;\n    }\n  }\n  return true;\n}\nfunction fetchDest(dest) {\n  if (dest instanceof Dict) {\n    dest = dest.get(\"D\");\n  }\n  return isValidExplicitDest(dest) ? dest : null;\n}\nfunction fetchRemoteDest(action) {\n  let dest = action.get(\"D\");\n  if (dest) {\n    if (dest instanceof Name) {\n      dest = dest.name;\n    }\n    if (typeof dest === \"string\") {\n      return stringToPDFString(dest);\n    } else if (isValidExplicitDest(dest)) {\n      return JSON.stringify(dest);\n    }\n  }\n  return null;\n}\nclass Catalog {\n  constructor(pdfManager, xref) {\n    this.pdfManager = pdfManager;\n    this.xref = xref;\n    this._catDict = xref.getCatalogObj();\n    if (!(this._catDict instanceof Dict)) {\n      throw new FormatError(\"Catalog object is not a dictionary.\");\n    }\n    this.toplevelPagesDict;\n    this._actualNumPages = null;\n    this.fontCache = new RefSetCache();\n    this.builtInCMapCache = new Map();\n    this.standardFontDataCache = new Map();\n    this.globalImageCache = new GlobalImageCache();\n    this.pageKidsCountCache = new RefSetCache();\n    this.pageIndexCache = new RefSetCache();\n    this.nonBlendModesSet = new RefSet();\n    this.systemFontCache = new Map();\n  }\n  cloneDict() {\n    return this._catDict.clone();\n  }\n  get version() {\n    const version = this._catDict.get(\"Version\");\n    if (version instanceof Name) {\n      if (PDF_VERSION_REGEXP.test(version.name)) {\n        return shadow(this, \"version\", version.name);\n      }\n      warn(`Invalid PDF catalog version: ${version.name}`);\n    }\n    return shadow(this, \"version\", null);\n  }\n  get lang() {\n    const lang = this._catDict.get(\"Lang\");\n    return shadow(this, \"lang\", typeof lang === \"string\" ? stringToPDFString(lang) : null);\n  }\n  get needsRendering() {\n    const needsRendering = this._catDict.get(\"NeedsRendering\");\n    return shadow(this, \"needsRendering\", typeof needsRendering === \"boolean\" ? needsRendering : false);\n  }\n  get collection() {\n    let collection = null;\n    try {\n      const obj = this._catDict.get(\"Collection\");\n      if (obj instanceof Dict && obj.size > 0) {\n        collection = obj;\n      }\n    } catch (ex) {\n      if (ex instanceof MissingDataException) {\n        throw ex;\n      }\n      info(\"Cannot fetch Collection entry; assuming no collection is present.\");\n    }\n    return shadow(this, \"collection\", collection);\n  }\n  get acroForm() {\n    let acroForm = null;\n    try {\n      const obj = this._catDict.get(\"AcroForm\");\n      if (obj instanceof Dict && obj.size > 0) {\n        acroForm = obj;\n      }\n    } catch (ex) {\n      if (ex instanceof MissingDataException) {\n        throw ex;\n      }\n      info(\"Cannot fetch AcroForm entry; assuming no forms are present.\");\n    }\n    return shadow(this, \"acroForm\", acroForm);\n  }\n  get acroFormRef() {\n    const value = this._catDict.getRaw(\"AcroForm\");\n    return shadow(this, \"acroFormRef\", value instanceof Ref ? value : null);\n  }\n  get metadata() {\n    const streamRef = this._catDict.getRaw(\"Metadata\");\n    if (!(streamRef instanceof Ref)) {\n      return shadow(this, \"metadata\", null);\n    }\n    let metadata = null;\n    try {\n      const stream = this.xref.fetch(streamRef, !this.xref.encrypt?.encryptMetadata);\n      if (stream instanceof BaseStream && stream.dict instanceof Dict) {\n        const type = stream.dict.get(\"Type\");\n        const subtype = stream.dict.get(\"Subtype\");\n        if (isName(type, \"Metadata\") && isName(subtype, \"XML\")) {\n          const data = stringToUTF8String(stream.getString());\n          if (data) {\n            metadata = new MetadataParser(data).serializable;\n          }\n        }\n      }\n    } catch (ex) {\n      if (ex instanceof MissingDataException) {\n        throw ex;\n      }\n      info(`Skipping invalid Metadata: \"${ex}\".`);\n    }\n    return shadow(this, \"metadata\", metadata);\n  }\n  get markInfo() {\n    let markInfo = null;\n    try {\n      markInfo = this._readMarkInfo();\n    } catch (ex) {\n      if (ex instanceof MissingDataException) {\n        throw ex;\n      }\n      warn(\"Unable to read mark info.\");\n    }\n    return shadow(this, \"markInfo\", markInfo);\n  }\n  _readMarkInfo() {\n    const obj = this._catDict.get(\"MarkInfo\");\n    if (!(obj instanceof Dict)) {\n      return null;\n    }\n    const markInfo = {\n      Marked: false,\n      UserProperties: false,\n      Suspects: false\n    };\n    for (const key in markInfo) {\n      const value = obj.get(key);\n      if (typeof value === \"boolean\") {\n        markInfo[key] = value;\n      }\n    }\n    return markInfo;\n  }\n  get structTreeRoot() {\n    let structTree = null;\n    try {\n      structTree = this._readStructTreeRoot();\n    } catch (ex) {\n      if (ex instanceof MissingDataException) {\n        throw ex;\n      }\n      warn(\"Unable read to structTreeRoot info.\");\n    }\n    return shadow(this, \"structTreeRoot\", structTree);\n  }\n  _readStructTreeRoot() {\n    const rawObj = this._catDict.getRaw(\"StructTreeRoot\");\n    const obj = this.xref.fetchIfRef(rawObj);\n    if (!(obj instanceof Dict)) {\n      return null;\n    }\n    const root = new StructTreeRoot(obj, rawObj);\n    root.init();\n    return root;\n  }\n  get toplevelPagesDict() {\n    const pagesObj = this._catDict.get(\"Pages\");\n    if (!(pagesObj instanceof Dict)) {\n      throw new FormatError(\"Invalid top-level pages dictionary.\");\n    }\n    return shadow(this, \"toplevelPagesDict\", pagesObj);\n  }\n  get documentOutline() {\n    let obj = null;\n    try {\n      obj = this._readDocumentOutline();\n    } catch (ex) {\n      if (ex instanceof MissingDataException) {\n        throw ex;\n      }\n      warn(\"Unable to read document outline.\");\n    }\n    return shadow(this, \"documentOutline\", obj);\n  }\n  _readDocumentOutline() {\n    let obj = this._catDict.get(\"Outlines\");\n    if (!(obj instanceof Dict)) {\n      return null;\n    }\n    obj = obj.getRaw(\"First\");\n    if (!(obj instanceof Ref)) {\n      return null;\n    }\n    const root = {\n      items: []\n    };\n    const queue = [{\n      obj,\n      parent: root\n    }];\n    const processed = new RefSet();\n    processed.put(obj);\n    const xref = this.xref,\n      blackColor = new Uint8ClampedArray(3);\n    while (queue.length > 0) {\n      const i = queue.shift();\n      const outlineDict = xref.fetchIfRef(i.obj);\n      if (outlineDict === null) {\n        continue;\n      }\n      if (!outlineDict.has(\"Title\")) {\n        warn(\"Invalid outline item encountered.\");\n      }\n      const data = {\n        url: null,\n        dest: null,\n        action: null\n      };\n      Catalog.parseDestDictionary({\n        destDict: outlineDict,\n        resultObj: data,\n        docBaseUrl: this.baseUrl,\n        docAttachments: this.attachments\n      });\n      const title = outlineDict.get(\"Title\");\n      const flags = outlineDict.get(\"F\") || 0;\n      const color = outlineDict.getArray(\"C\");\n      const count = outlineDict.get(\"Count\");\n      let rgbColor = blackColor;\n      if (Array.isArray(color) && color.length === 3 && (color[0] !== 0 || color[1] !== 0 || color[2] !== 0)) {\n        rgbColor = ColorSpace.singletons.rgb.getRgb(color, 0);\n      }\n      const outlineItem = {\n        action: data.action,\n        attachment: data.attachment,\n        dest: data.dest,\n        url: data.url,\n        unsafeUrl: data.unsafeUrl,\n        newWindow: data.newWindow,\n        setOCGState: data.setOCGState,\n        title: typeof title === \"string\" ? stringToPDFString(title) : \"\",\n        color: rgbColor,\n        count: Number.isInteger(count) ? count : undefined,\n        bold: !!(flags & 2),\n        italic: !!(flags & 1),\n        items: []\n      };\n      i.parent.items.push(outlineItem);\n      obj = outlineDict.getRaw(\"First\");\n      if (obj instanceof Ref && !processed.has(obj)) {\n        queue.push({\n          obj,\n          parent: outlineItem\n        });\n        processed.put(obj);\n      }\n      obj = outlineDict.getRaw(\"Next\");\n      if (obj instanceof Ref && !processed.has(obj)) {\n        queue.push({\n          obj,\n          parent: i.parent\n        });\n        processed.put(obj);\n      }\n    }\n    return root.items.length > 0 ? root.items : null;\n  }\n  get permissions() {\n    let permissions = null;\n    try {\n      permissions = this._readPermissions();\n    } catch (ex) {\n      if (ex instanceof MissingDataException) {\n        throw ex;\n      }\n      warn(\"Unable to read permissions.\");\n    }\n    return shadow(this, \"permissions\", permissions);\n  }\n  _readPermissions() {\n    const encrypt = this.xref.trailer.get(\"Encrypt\");\n    if (!(encrypt instanceof Dict)) {\n      return null;\n    }\n    let flags = encrypt.get(\"P\");\n    if (typeof flags !== \"number\") {\n      return null;\n    }\n    flags += 2 ** 32;\n    const permissions = [];\n    for (const key in PermissionFlag) {\n      const value = PermissionFlag[key];\n      if (flags & value) {\n        permissions.push(value);\n      }\n    }\n    return permissions;\n  }\n  get optionalContentConfig() {\n    let config = null;\n    try {\n      const properties = this._catDict.get(\"OCProperties\");\n      if (!properties) {\n        return shadow(this, \"optionalContentConfig\", null);\n      }\n      const defaultConfig = properties.get(\"D\");\n      if (!defaultConfig) {\n        return shadow(this, \"optionalContentConfig\", null);\n      }\n      const groupsData = properties.get(\"OCGs\");\n      if (!Array.isArray(groupsData)) {\n        return shadow(this, \"optionalContentConfig\", null);\n      }\n      const groups = [];\n      const groupRefs = new RefSet();\n      for (const groupRef of groupsData) {\n        if (!(groupRef instanceof Ref) || groupRefs.has(groupRef)) {\n          continue;\n        }\n        groupRefs.put(groupRef);\n        groups.push(this.#readOptionalContentGroup(groupRef));\n      }\n      config = this.#readOptionalContentConfig(defaultConfig, groupRefs);\n      config.groups = groups;\n    } catch (ex) {\n      if (ex instanceof MissingDataException) {\n        throw ex;\n      }\n      warn(`Unable to read optional content config: ${ex}`);\n    }\n    return shadow(this, \"optionalContentConfig\", config);\n  }\n  #readOptionalContentGroup(groupRef) {\n    const group = this.xref.fetch(groupRef);\n    const obj = {\n      id: groupRef.toString(),\n      name: null,\n      intent: null,\n      usage: {\n        print: null,\n        view: null\n      }\n    };\n    const name = group.get(\"Name\");\n    if (typeof name === \"string\") {\n      obj.name = stringToPDFString(name);\n    }\n    let intent = group.getArray(\"Intent\");\n    if (!Array.isArray(intent)) {\n      intent = [intent];\n    }\n    if (intent.every(i => i instanceof Name)) {\n      obj.intent = intent.map(i => i.name);\n    }\n    const usage = group.get(\"Usage\");\n    if (!(usage instanceof Dict)) {\n      return obj;\n    }\n    const usageObj = obj.usage;\n    const print = usage.get(\"Print\");\n    if (print instanceof Dict) {\n      const printState = print.get(\"PrintState\");\n      if (printState instanceof Name) {\n        switch (printState.name) {\n          case \"ON\":\n          case \"OFF\":\n            usageObj.print = {\n              printState: printState.name\n            };\n        }\n      }\n    }\n    const view = usage.get(\"View\");\n    if (view instanceof Dict) {\n      const viewState = view.get(\"ViewState\");\n      if (viewState instanceof Name) {\n        switch (viewState.name) {\n          case \"ON\":\n          case \"OFF\":\n            usageObj.view = {\n              viewState: viewState.name\n            };\n        }\n      }\n    }\n    return obj;\n  }\n  #readOptionalContentConfig(config, contentGroupRefs) {\n    function parseOnOff(refs) {\n      const onParsed = [];\n      if (Array.isArray(refs)) {\n        for (const value of refs) {\n          if (!(value instanceof Ref)) {\n            continue;\n          }\n          if (contentGroupRefs.has(value)) {\n            onParsed.push(value.toString());\n          }\n        }\n      }\n      return onParsed;\n    }\n    function parseOrder(refs, nestedLevels = 0) {\n      if (!Array.isArray(refs)) {\n        return null;\n      }\n      const order = [];\n      for (const value of refs) {\n        if (value instanceof Ref && contentGroupRefs.has(value)) {\n          parsedOrderRefs.put(value);\n          order.push(value.toString());\n          continue;\n        }\n        const nestedOrder = parseNestedOrder(value, nestedLevels);\n        if (nestedOrder) {\n          order.push(nestedOrder);\n        }\n      }\n      if (nestedLevels > 0) {\n        return order;\n      }\n      const hiddenGroups = [];\n      for (const groupRef of contentGroupRefs) {\n        if (parsedOrderRefs.has(groupRef)) {\n          continue;\n        }\n        hiddenGroups.push(groupRef.toString());\n      }\n      if (hiddenGroups.length) {\n        order.push({\n          name: null,\n          order: hiddenGroups\n        });\n      }\n      return order;\n    }\n    function parseNestedOrder(ref, nestedLevels) {\n      if (++nestedLevels > MAX_NESTED_LEVELS) {\n        warn(\"parseNestedOrder - reached MAX_NESTED_LEVELS.\");\n        return null;\n      }\n      const value = xref.fetchIfRef(ref);\n      if (!Array.isArray(value)) {\n        return null;\n      }\n      const nestedName = xref.fetchIfRef(value[0]);\n      if (typeof nestedName !== \"string\") {\n        return null;\n      }\n      const nestedOrder = parseOrder(value.slice(1), nestedLevels);\n      if (!nestedOrder || !nestedOrder.length) {\n        return null;\n      }\n      return {\n        name: stringToPDFString(nestedName),\n        order: nestedOrder\n      };\n    }\n    const xref = this.xref,\n      parsedOrderRefs = new RefSet(),\n      MAX_NESTED_LEVELS = 10;\n    return {\n      name: typeof config.get(\"Name\") === \"string\" ? stringToPDFString(config.get(\"Name\")) : null,\n      creator: typeof config.get(\"Creator\") === \"string\" ? stringToPDFString(config.get(\"Creator\")) : null,\n      baseState: config.get(\"BaseState\") instanceof Name ? config.get(\"BaseState\").name : null,\n      on: parseOnOff(config.get(\"ON\")),\n      off: parseOnOff(config.get(\"OFF\")),\n      order: parseOrder(config.get(\"Order\")),\n      groups: null\n    };\n  }\n  setActualNumPages(num = null) {\n    this._actualNumPages = num;\n  }\n  get hasActualNumPages() {\n    return this._actualNumPages !== null;\n  }\n  get _pagesCount() {\n    const obj = this.toplevelPagesDict.get(\"Count\");\n    if (!Number.isInteger(obj)) {\n      throw new FormatError(\"Page count in top-level pages dictionary is not an integer.\");\n    }\n    return shadow(this, \"_pagesCount\", obj);\n  }\n  get numPages() {\n    return this.hasActualNumPages ? this._actualNumPages : this._pagesCount;\n  }\n  get destinations() {\n    const obj = this._readDests(),\n      dests = Object.create(null);\n    if (obj instanceof NameTree) {\n      for (const [key, value] of obj.getAll()) {\n        const dest = fetchDest(value);\n        if (dest) {\n          dests[stringToPDFString(key)] = dest;\n        }\n      }\n    } else if (obj instanceof Dict) {\n      obj.forEach(function (key, value) {\n        const dest = fetchDest(value);\n        if (dest) {\n          dests[key] = dest;\n        }\n      });\n    }\n    return shadow(this, \"destinations\", dests);\n  }\n  getDestination(id) {\n    const obj = this._readDests();\n    if (obj instanceof NameTree) {\n      const dest = fetchDest(obj.get(id));\n      if (dest) {\n        return dest;\n      }\n      const allDest = this.destinations[id];\n      if (allDest) {\n        warn(`Found \"${id}\" at an incorrect position in the NameTree.`);\n        return allDest;\n      }\n    } else if (obj instanceof Dict) {\n      const dest = fetchDest(obj.get(id));\n      if (dest) {\n        return dest;\n      }\n    }\n    return null;\n  }\n  _readDests() {\n    const obj = this._catDict.get(\"Names\");\n    if (obj?.has(\"Dests\")) {\n      return new NameTree(obj.getRaw(\"Dests\"), this.xref);\n    } else if (this._catDict.has(\"Dests\")) {\n      return this._catDict.get(\"Dests\");\n    }\n    return undefined;\n  }\n  get pageLabels() {\n    let obj = null;\n    try {\n      obj = this._readPageLabels();\n    } catch (ex) {\n      if (ex instanceof MissingDataException) {\n        throw ex;\n      }\n      warn(\"Unable to read page labels.\");\n    }\n    return shadow(this, \"pageLabels\", obj);\n  }\n  _readPageLabels() {\n    const obj = this._catDict.getRaw(\"PageLabels\");\n    if (!obj) {\n      return null;\n    }\n    const pageLabels = new Array(this.numPages);\n    let style = null,\n      prefix = \"\";\n    const numberTree = new NumberTree(obj, this.xref);\n    const nums = numberTree.getAll();\n    let currentLabel = \"\",\n      currentIndex = 1;\n    for (let i = 0, ii = this.numPages; i < ii; i++) {\n      const labelDict = nums.get(i);\n      if (labelDict !== undefined) {\n        if (!(labelDict instanceof Dict)) {\n          throw new FormatError(\"PageLabel is not a dictionary.\");\n        }\n        if (labelDict.has(\"Type\") && !isName(labelDict.get(\"Type\"), \"PageLabel\")) {\n          throw new FormatError(\"Invalid type in PageLabel dictionary.\");\n        }\n        if (labelDict.has(\"S\")) {\n          const s = labelDict.get(\"S\");\n          if (!(s instanceof Name)) {\n            throw new FormatError(\"Invalid style in PageLabel dictionary.\");\n          }\n          style = s.name;\n        } else {\n          style = null;\n        }\n        if (labelDict.has(\"P\")) {\n          const p = labelDict.get(\"P\");\n          if (typeof p !== \"string\") {\n            throw new FormatError(\"Invalid prefix in PageLabel dictionary.\");\n          }\n          prefix = stringToPDFString(p);\n        } else {\n          prefix = \"\";\n        }\n        if (labelDict.has(\"St\")) {\n          const st = labelDict.get(\"St\");\n          if (!(Number.isInteger(st) && st >= 1)) {\n            throw new FormatError(\"Invalid start in PageLabel dictionary.\");\n          }\n          currentIndex = st;\n        } else {\n          currentIndex = 1;\n        }\n      }\n      switch (style) {\n        case \"D\":\n          currentLabel = currentIndex;\n          break;\n        case \"R\":\n        case \"r\":\n          currentLabel = toRomanNumerals(currentIndex, style === \"r\");\n          break;\n        case \"A\":\n        case \"a\":\n          const LIMIT = 26;\n          const A_UPPER_CASE = 0x41,\n            A_LOWER_CASE = 0x61;\n          const baseCharCode = style === \"a\" ? A_LOWER_CASE : A_UPPER_CASE;\n          const letterIndex = currentIndex - 1;\n          const character = String.fromCharCode(baseCharCode + letterIndex % LIMIT);\n          currentLabel = character.repeat(Math.floor(letterIndex / LIMIT) + 1);\n          break;\n        default:\n          if (style) {\n            throw new FormatError(`Invalid style \"${style}\" in PageLabel dictionary.`);\n          }\n          currentLabel = \"\";\n      }\n      pageLabels[i] = prefix + currentLabel;\n      currentIndex++;\n    }\n    return pageLabels;\n  }\n  get pageLayout() {\n    const obj = this._catDict.get(\"PageLayout\");\n    let pageLayout = \"\";\n    if (obj instanceof Name) {\n      switch (obj.name) {\n        case \"SinglePage\":\n        case \"OneColumn\":\n        case \"TwoColumnLeft\":\n        case \"TwoColumnRight\":\n        case \"TwoPageLeft\":\n        case \"TwoPageRight\":\n          pageLayout = obj.name;\n      }\n    }\n    return shadow(this, \"pageLayout\", pageLayout);\n  }\n  get pageMode() {\n    const obj = this._catDict.get(\"PageMode\");\n    let pageMode = \"UseNone\";\n    if (obj instanceof Name) {\n      switch (obj.name) {\n        case \"UseNone\":\n        case \"UseOutlines\":\n        case \"UseThumbs\":\n        case \"FullScreen\":\n        case \"UseOC\":\n        case \"UseAttachments\":\n          pageMode = obj.name;\n      }\n    }\n    return shadow(this, \"pageMode\", pageMode);\n  }\n  get viewerPreferences() {\n    const obj = this._catDict.get(\"ViewerPreferences\");\n    if (!(obj instanceof Dict)) {\n      return shadow(this, \"viewerPreferences\", null);\n    }\n    let prefs = null;\n    for (const key of obj.getKeys()) {\n      const value = obj.get(key);\n      let prefValue;\n      switch (key) {\n        case \"HideToolbar\":\n        case \"HideMenubar\":\n        case \"HideWindowUI\":\n        case \"FitWindow\":\n        case \"CenterWindow\":\n        case \"DisplayDocTitle\":\n        case \"PickTrayByPDFSize\":\n          if (typeof value === \"boolean\") {\n            prefValue = value;\n          }\n          break;\n        case \"NonFullScreenPageMode\":\n          if (value instanceof Name) {\n            switch (value.name) {\n              case \"UseNone\":\n              case \"UseOutlines\":\n              case \"UseThumbs\":\n              case \"UseOC\":\n                prefValue = value.name;\n                break;\n              default:\n                prefValue = \"UseNone\";\n            }\n          }\n          break;\n        case \"Direction\":\n          if (value instanceof Name) {\n            switch (value.name) {\n              case \"L2R\":\n              case \"R2L\":\n                prefValue = value.name;\n                break;\n              default:\n                prefValue = \"L2R\";\n            }\n          }\n          break;\n        case \"ViewArea\":\n        case \"ViewClip\":\n        case \"PrintArea\":\n        case \"PrintClip\":\n          if (value instanceof Name) {\n            switch (value.name) {\n              case \"MediaBox\":\n              case \"CropBox\":\n              case \"BleedBox\":\n              case \"TrimBox\":\n              case \"ArtBox\":\n                prefValue = value.name;\n                break;\n              default:\n                prefValue = \"CropBox\";\n            }\n          }\n          break;\n        case \"PrintScaling\":\n          if (value instanceof Name) {\n            switch (value.name) {\n              case \"None\":\n              case \"AppDefault\":\n                prefValue = value.name;\n                break;\n              default:\n                prefValue = \"AppDefault\";\n            }\n          }\n          break;\n        case \"Duplex\":\n          if (value instanceof Name) {\n            switch (value.name) {\n              case \"Simplex\":\n              case \"DuplexFlipShortEdge\":\n              case \"DuplexFlipLongEdge\":\n                prefValue = value.name;\n                break;\n              default:\n                prefValue = \"None\";\n            }\n          }\n          break;\n        case \"PrintPageRange\":\n          if (Array.isArray(value) && value.length % 2 === 0) {\n            const isValid = value.every((page, i, arr) => Number.isInteger(page) && page > 0 && (i === 0 || page >= arr[i - 1]) && page <= this.numPages);\n            if (isValid) {\n              prefValue = value;\n            }\n          }\n          break;\n        case \"NumCopies\":\n          if (Number.isInteger(value) && value > 0) {\n            prefValue = value;\n          }\n          break;\n        default:\n          warn(`Ignoring non-standard key in ViewerPreferences: ${key}.`);\n          continue;\n      }\n      if (prefValue === undefined) {\n        warn(`Bad value, for key \"${key}\", in ViewerPreferences: ${value}.`);\n        continue;\n      }\n      if (!prefs) {\n        prefs = Object.create(null);\n      }\n      prefs[key] = prefValue;\n    }\n    return shadow(this, \"viewerPreferences\", prefs);\n  }\n  get openAction() {\n    const obj = this._catDict.get(\"OpenAction\");\n    const openAction = Object.create(null);\n    if (obj instanceof Dict) {\n      const destDict = new Dict(this.xref);\n      destDict.set(\"A\", obj);\n      const resultObj = {\n        url: null,\n        dest: null,\n        action: null\n      };\n      Catalog.parseDestDictionary({\n        destDict,\n        resultObj\n      });\n      if (Array.isArray(resultObj.dest)) {\n        openAction.dest = resultObj.dest;\n      } else if (resultObj.action) {\n        openAction.action = resultObj.action;\n      }\n    } else if (Array.isArray(obj)) {\n      openAction.dest = obj;\n    }\n    return shadow(this, \"openAction\", objectSize(openAction) > 0 ? openAction : null);\n  }\n  get attachments() {\n    const obj = this._catDict.get(\"Names\");\n    let attachments = null;\n    if (obj instanceof Dict && obj.has(\"EmbeddedFiles\")) {\n      const nameTree = new NameTree(obj.getRaw(\"EmbeddedFiles\"), this.xref);\n      for (const [key, value] of nameTree.getAll()) {\n        const fs = new FileSpec(value, this.xref);\n        if (!attachments) {\n          attachments = Object.create(null);\n        }\n        attachments[stringToPDFString(key)] = fs.serializable;\n      }\n    }\n    return shadow(this, \"attachments\", attachments);\n  }\n  get xfaImages() {\n    const obj = this._catDict.get(\"Names\");\n    let xfaImages = null;\n    if (obj instanceof Dict && obj.has(\"XFAImages\")) {\n      const nameTree = new NameTree(obj.getRaw(\"XFAImages\"), this.xref);\n      for (const [key, value] of nameTree.getAll()) {\n        if (!xfaImages) {\n          xfaImages = new Dict(this.xref);\n        }\n        xfaImages.set(stringToPDFString(key), value);\n      }\n    }\n    return shadow(this, \"xfaImages\", xfaImages);\n  }\n  _collectJavaScript() {\n    const obj = this._catDict.get(\"Names\");\n    let javaScript = null;\n    function appendIfJavaScriptDict(name, jsDict) {\n      if (!(jsDict instanceof Dict)) {\n        return;\n      }\n      if (!isName(jsDict.get(\"S\"), \"JavaScript\")) {\n        return;\n      }\n      let js = jsDict.get(\"JS\");\n      if (js instanceof BaseStream) {\n        js = js.getString();\n      } else if (typeof js !== \"string\") {\n        return;\n      }\n      js = stringToPDFString(js).replaceAll(\"\\x00\", \"\");\n      if (js) {\n        (javaScript ||= new Map()).set(name, js);\n      }\n    }\n    if (obj instanceof Dict && obj.has(\"JavaScript\")) {\n      const nameTree = new NameTree(obj.getRaw(\"JavaScript\"), this.xref);\n      for (const [key, value] of nameTree.getAll()) {\n        appendIfJavaScriptDict(stringToPDFString(key), value);\n      }\n    }\n    const openAction = this._catDict.get(\"OpenAction\");\n    if (openAction) {\n      appendIfJavaScriptDict(\"OpenAction\", openAction);\n    }\n    return javaScript;\n  }\n  get jsActions() {\n    const javaScript = this._collectJavaScript();\n    let actions = collectActions(this.xref, this._catDict, DocumentActionEventType);\n    if (javaScript) {\n      actions ||= Object.create(null);\n      for (const [key, val] of javaScript) {\n        if (key in actions) {\n          actions[key].push(val);\n        } else {\n          actions[key] = [val];\n        }\n      }\n    }\n    return shadow(this, \"jsActions\", actions);\n  }\n  async fontFallback(id, handler) {\n    const translatedFonts = await Promise.all(this.fontCache);\n    for (const translatedFont of translatedFonts) {\n      if (translatedFont.loadedName === id) {\n        translatedFont.fallback(handler);\n        return;\n      }\n    }\n  }\n  async cleanup(manuallyTriggered = false) {\n    clearGlobalCaches();\n    this.globalImageCache.clear(manuallyTriggered);\n    this.pageKidsCountCache.clear();\n    this.pageIndexCache.clear();\n    this.nonBlendModesSet.clear();\n    const translatedFonts = await Promise.all(this.fontCache);\n    for (const {\n      dict\n    } of translatedFonts) {\n      delete dict.cacheKey;\n    }\n    this.fontCache.clear();\n    this.builtInCMapCache.clear();\n    this.standardFontDataCache.clear();\n    this.systemFontCache.clear();\n  }\n  async getPageDict(pageIndex) {\n    const nodesToVisit = [this.toplevelPagesDict];\n    const visitedNodes = new RefSet();\n    const pagesRef = this._catDict.getRaw(\"Pages\");\n    if (pagesRef instanceof Ref) {\n      visitedNodes.put(pagesRef);\n    }\n    const xref = this.xref,\n      pageKidsCountCache = this.pageKidsCountCache,\n      pageIndexCache = this.pageIndexCache;\n    let currentPageIndex = 0;\n    while (nodesToVisit.length) {\n      const currentNode = nodesToVisit.pop();\n      if (currentNode instanceof Ref) {\n        const count = pageKidsCountCache.get(currentNode);\n        if (count >= 0 && currentPageIndex + count <= pageIndex) {\n          currentPageIndex += count;\n          continue;\n        }\n        if (visitedNodes.has(currentNode)) {\n          throw new FormatError(\"Pages tree contains circular reference.\");\n        }\n        visitedNodes.put(currentNode);\n        const obj = await xref.fetchAsync(currentNode);\n        if (obj instanceof Dict) {\n          let type = obj.getRaw(\"Type\");\n          if (type instanceof Ref) {\n            type = await xref.fetchAsync(type);\n          }\n          if (isName(type, \"Page\") || !obj.has(\"Kids\")) {\n            if (!pageKidsCountCache.has(currentNode)) {\n              pageKidsCountCache.put(currentNode, 1);\n            }\n            if (!pageIndexCache.has(currentNode)) {\n              pageIndexCache.put(currentNode, currentPageIndex);\n            }\n            if (currentPageIndex === pageIndex) {\n              return [obj, currentNode];\n            }\n            currentPageIndex++;\n            continue;\n          }\n        }\n        nodesToVisit.push(obj);\n        continue;\n      }\n      if (!(currentNode instanceof Dict)) {\n        throw new FormatError(\"Page dictionary kid reference points to wrong type of object.\");\n      }\n      const {\n        objId\n      } = currentNode;\n      let count = currentNode.getRaw(\"Count\");\n      if (count instanceof Ref) {\n        count = await xref.fetchAsync(count);\n      }\n      if (Number.isInteger(count) && count >= 0) {\n        if (objId && !pageKidsCountCache.has(objId)) {\n          pageKidsCountCache.put(objId, count);\n        }\n        if (currentPageIndex + count <= pageIndex) {\n          currentPageIndex += count;\n          continue;\n        }\n      }\n      let kids = currentNode.getRaw(\"Kids\");\n      if (kids instanceof Ref) {\n        kids = await xref.fetchAsync(kids);\n      }\n      if (!Array.isArray(kids)) {\n        let type = currentNode.getRaw(\"Type\");\n        if (type instanceof Ref) {\n          type = await xref.fetchAsync(type);\n        }\n        if (isName(type, \"Page\") || !currentNode.has(\"Kids\")) {\n          if (currentPageIndex === pageIndex) {\n            return [currentNode, null];\n          }\n          currentPageIndex++;\n          continue;\n        }\n        throw new FormatError(\"Page dictionary kids object is not an array.\");\n      }\n      for (let last = kids.length - 1; last >= 0; last--) {\n        nodesToVisit.push(kids[last]);\n      }\n    }\n    throw new Error(`Page index ${pageIndex} not found.`);\n  }\n  async getAllPageDicts(recoveryMode = false) {\n    const {\n      ignoreErrors\n    } = this.pdfManager.evaluatorOptions;\n    const queue = [{\n      currentNode: this.toplevelPagesDict,\n      posInKids: 0\n    }];\n    const visitedNodes = new RefSet();\n    const pagesRef = this._catDict.getRaw(\"Pages\");\n    if (pagesRef instanceof Ref) {\n      visitedNodes.put(pagesRef);\n    }\n    const map = new Map(),\n      xref = this.xref,\n      pageIndexCache = this.pageIndexCache;\n    let pageIndex = 0;\n    function addPageDict(pageDict, pageRef) {\n      if (pageRef && !pageIndexCache.has(pageRef)) {\n        pageIndexCache.put(pageRef, pageIndex);\n      }\n      map.set(pageIndex++, [pageDict, pageRef]);\n    }\n    function addPageError(error) {\n      if (error instanceof XRefEntryException && !recoveryMode) {\n        throw error;\n      }\n      if (recoveryMode && ignoreErrors && pageIndex === 0) {\n        warn(`getAllPageDicts - Skipping invalid first page: \"${error}\".`);\n        error = Dict.empty;\n      }\n      map.set(pageIndex++, [error, null]);\n    }\n    while (queue.length > 0) {\n      const queueItem = queue.at(-1);\n      const {\n        currentNode,\n        posInKids\n      } = queueItem;\n      let kids = currentNode.getRaw(\"Kids\");\n      if (kids instanceof Ref) {\n        try {\n          kids = await xref.fetchAsync(kids);\n        } catch (ex) {\n          addPageError(ex);\n          break;\n        }\n      }\n      if (!Array.isArray(kids)) {\n        addPageError(new FormatError(\"Page dictionary kids object is not an array.\"));\n        break;\n      }\n      if (posInKids >= kids.length) {\n        queue.pop();\n        continue;\n      }\n      const kidObj = kids[posInKids];\n      let obj;\n      if (kidObj instanceof Ref) {\n        if (visitedNodes.has(kidObj)) {\n          addPageError(new FormatError(\"Pages tree contains circular reference.\"));\n          break;\n        }\n        visitedNodes.put(kidObj);\n        try {\n          obj = await xref.fetchAsync(kidObj);\n        } catch (ex) {\n          addPageError(ex);\n          break;\n        }\n      } else {\n        obj = kidObj;\n      }\n      if (!(obj instanceof Dict)) {\n        addPageError(new FormatError(\"Page dictionary kid reference points to wrong type of object.\"));\n        break;\n      }\n      let type = obj.getRaw(\"Type\");\n      if (type instanceof Ref) {\n        try {\n          type = await xref.fetchAsync(type);\n        } catch (ex) {\n          addPageError(ex);\n          break;\n        }\n      }\n      if (isName(type, \"Page\") || !obj.has(\"Kids\")) {\n        addPageDict(obj, kidObj instanceof Ref ? kidObj : null);\n      } else {\n        queue.push({\n          currentNode: obj,\n          posInKids: 0\n        });\n      }\n      queueItem.posInKids++;\n    }\n    return map;\n  }\n  getPageIndex(pageRef) {\n    const cachedPageIndex = this.pageIndexCache.get(pageRef);\n    if (cachedPageIndex !== undefined) {\n      return Promise.resolve(cachedPageIndex);\n    }\n    const xref = this.xref;\n    function pagesBeforeRef(kidRef) {\n      let total = 0,\n        parentRef;\n      return xref.fetchAsync(kidRef).then(function (node) {\n        if (isRefsEqual(kidRef, pageRef) && !isDict(node, \"Page\") && !(node instanceof Dict && !node.has(\"Type\") && node.has(\"Contents\"))) {\n          throw new FormatError(\"The reference does not point to a /Page dictionary.\");\n        }\n        if (!node) {\n          return null;\n        }\n        if (!(node instanceof Dict)) {\n          throw new FormatError(\"Node must be a dictionary.\");\n        }\n        parentRef = node.getRaw(\"Parent\");\n        return node.getAsync(\"Parent\");\n      }).then(function (parent) {\n        if (!parent) {\n          return null;\n        }\n        if (!(parent instanceof Dict)) {\n          throw new FormatError(\"Parent must be a dictionary.\");\n        }\n        return parent.getAsync(\"Kids\");\n      }).then(function (kids) {\n        if (!kids) {\n          return null;\n        }\n        const kidPromises = [];\n        let found = false;\n        for (const kid of kids) {\n          if (!(kid instanceof Ref)) {\n            throw new FormatError(\"Kid must be a reference.\");\n          }\n          if (isRefsEqual(kid, kidRef)) {\n            found = true;\n            break;\n          }\n          kidPromises.push(xref.fetchAsync(kid).then(function (obj) {\n            if (!(obj instanceof Dict)) {\n              throw new FormatError(\"Kid node must be a dictionary.\");\n            }\n            if (obj.has(\"Count\")) {\n              total += obj.get(\"Count\");\n            } else {\n              total++;\n            }\n          }));\n        }\n        if (!found) {\n          throw new FormatError(\"Kid reference not found in parent's kids.\");\n        }\n        return Promise.all(kidPromises).then(function () {\n          return [total, parentRef];\n        });\n      });\n    }\n    let total = 0;\n    const next = ref => pagesBeforeRef(ref).then(args => {\n      if (!args) {\n        this.pageIndexCache.put(pageRef, total);\n        return total;\n      }\n      const [count, parentRef] = args;\n      total += count;\n      return next(parentRef);\n    });\n    return next(pageRef);\n  }\n  get baseUrl() {\n    const uri = this._catDict.get(\"URI\");\n    if (uri instanceof Dict) {\n      const base = uri.get(\"Base\");\n      if (typeof base === \"string\") {\n        const absoluteUrl = createValidAbsoluteUrl(base, null, {\n          tryConvertEncoding: true\n        });\n        if (absoluteUrl) {\n          return shadow(this, \"baseUrl\", absoluteUrl.href);\n        }\n      }\n    }\n    return shadow(this, \"baseUrl\", this.pdfManager.docBaseUrl);\n  }\n  static parseDestDictionary({\n    destDict,\n    resultObj,\n    docBaseUrl = null,\n    docAttachments = null\n  }) {\n    if (!(destDict instanceof Dict)) {\n      warn(\"parseDestDictionary: `destDict` must be a dictionary.\");\n      return;\n    }\n    let action = destDict.get(\"A\"),\n      url,\n      dest;\n    if (!(action instanceof Dict)) {\n      if (destDict.has(\"Dest\")) {\n        action = destDict.get(\"Dest\");\n      } else {\n        action = destDict.get(\"AA\");\n        if (action instanceof Dict) {\n          if (action.has(\"D\")) {\n            action = action.get(\"D\");\n          } else if (action.has(\"U\")) {\n            action = action.get(\"U\");\n          }\n        }\n      }\n    }\n    if (action instanceof Dict) {\n      const actionType = action.get(\"S\");\n      if (!(actionType instanceof Name)) {\n        warn(\"parseDestDictionary: Invalid type in Action dictionary.\");\n        return;\n      }\n      const actionName = actionType.name;\n      switch (actionName) {\n        case \"ResetForm\":\n          const flags = action.get(\"Flags\");\n          const include = ((typeof flags === \"number\" ? flags : 0) & 1) === 0;\n          const fields = [];\n          const refs = [];\n          for (const obj of action.get(\"Fields\") || []) {\n            if (obj instanceof Ref) {\n              refs.push(obj.toString());\n            } else if (typeof obj === \"string\") {\n              fields.push(stringToPDFString(obj));\n            }\n          }\n          resultObj.resetForm = {\n            fields,\n            refs,\n            include\n          };\n          break;\n        case \"URI\":\n          url = action.get(\"URI\");\n          if (url instanceof Name) {\n            url = \"/\" + url.name;\n          }\n          break;\n        case \"GoTo\":\n          dest = action.get(\"D\");\n          break;\n        case \"Launch\":\n        case \"GoToR\":\n          const urlDict = action.get(\"F\");\n          if (urlDict instanceof Dict) {\n            const fs = new FileSpec(urlDict, null, true);\n            const {\n              filename\n            } = fs.serializable;\n            url = filename;\n          } else if (typeof urlDict === \"string\") {\n            url = urlDict;\n          }\n          const remoteDest = fetchRemoteDest(action);\n          if (remoteDest && typeof url === \"string\") {\n            url = url.split(\"#\", 1)[0] + \"#\" + remoteDest;\n          }\n          const newWindow = action.get(\"NewWindow\");\n          if (typeof newWindow === \"boolean\") {\n            resultObj.newWindow = newWindow;\n          }\n          break;\n        case \"GoToE\":\n          const target = action.get(\"T\");\n          let attachment;\n          if (docAttachments && target instanceof Dict) {\n            const relationship = target.get(\"R\");\n            const name = target.get(\"N\");\n            if (isName(relationship, \"C\") && typeof name === \"string\") {\n              attachment = docAttachments[stringToPDFString(name)];\n            }\n          }\n          if (attachment) {\n            resultObj.attachment = attachment;\n            const attachmentDest = fetchRemoteDest(action);\n            if (attachmentDest) {\n              resultObj.attachmentDest = attachmentDest;\n            }\n          } else {\n            warn(`parseDestDictionary - unimplemented \"GoToE\" action.`);\n          }\n          break;\n        case \"Named\":\n          const namedAction = action.get(\"N\");\n          if (namedAction instanceof Name) {\n            resultObj.action = namedAction.name;\n          }\n          break;\n        case \"SetOCGState\":\n          const state = action.get(\"State\");\n          const preserveRB = action.get(\"PreserveRB\");\n          if (!Array.isArray(state) || state.length === 0) {\n            break;\n          }\n          const stateArr = [];\n          for (const elem of state) {\n            if (elem instanceof Name) {\n              switch (elem.name) {\n                case \"ON\":\n                case \"OFF\":\n                case \"Toggle\":\n                  stateArr.push(elem.name);\n                  break;\n              }\n            } else if (elem instanceof Ref) {\n              stateArr.push(elem.toString());\n            }\n          }\n          if (stateArr.length !== state.length) {\n            break;\n          }\n          resultObj.setOCGState = {\n            state: stateArr,\n            preserveRB: typeof preserveRB === \"boolean\" ? preserveRB : true\n          };\n          break;\n        case \"JavaScript\":\n          const jsAction = action.get(\"JS\");\n          let js;\n          if (jsAction instanceof BaseStream) {\n            js = jsAction.getString();\n          } else if (typeof jsAction === \"string\") {\n            js = jsAction;\n          }\n          const jsURL = js && recoverJsURL(stringToPDFString(js));\n          if (jsURL) {\n            url = jsURL.url;\n            resultObj.newWindow = jsURL.newWindow;\n            break;\n          }\n        default:\n          if (actionName === \"JavaScript\" || actionName === \"SubmitForm\") {\n            break;\n          }\n          warn(`parseDestDictionary - unsupported action: \"${actionName}\".`);\n          break;\n      }\n    } else if (destDict.has(\"Dest\")) {\n      dest = destDict.get(\"Dest\");\n    }\n    if (typeof url === \"string\") {\n      const absoluteUrl = createValidAbsoluteUrl(url, docBaseUrl, {\n        addDefaultProtocol: true,\n        tryConvertEncoding: true\n      });\n      if (absoluteUrl) {\n        resultObj.url = absoluteUrl.href;\n      }\n      resultObj.unsafeUrl = url;\n    }\n    if (dest) {\n      if (dest instanceof Name) {\n        dest = dest.name;\n      }\n      if (typeof dest === \"string\") {\n        resultObj.dest = stringToPDFString(dest);\n      } else if (isValidExplicitDest(dest)) {\n        resultObj.dest = dest;\n      }\n    }\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/object_loader.js\n\n\n\n\nfunction mayHaveChildren(value) {\n  return value instanceof Ref || value instanceof Dict || value instanceof BaseStream || Array.isArray(value);\n}\nfunction addChildren(node, nodesToVisit) {\n  if (node instanceof Dict) {\n    node = node.getRawValues();\n  } else if (node instanceof BaseStream) {\n    node = node.dict.getRawValues();\n  } else if (!Array.isArray(node)) {\n    return;\n  }\n  for (const rawValue of node) {\n    if (mayHaveChildren(rawValue)) {\n      nodesToVisit.push(rawValue);\n    }\n  }\n}\nclass ObjectLoader {\n  constructor(dict, keys, xref) {\n    this.dict = dict;\n    this.keys = keys;\n    this.xref = xref;\n    this.refSet = null;\n  }\n  async load() {\n    if (this.xref.stream.isDataLoaded) {\n      return undefined;\n    }\n    const {\n      keys,\n      dict\n    } = this;\n    this.refSet = new RefSet();\n    const nodesToVisit = [];\n    for (const key of keys) {\n      const rawValue = dict.getRaw(key);\n      if (rawValue !== undefined) {\n        nodesToVisit.push(rawValue);\n      }\n    }\n    return this._walk(nodesToVisit);\n  }\n  async _walk(nodesToVisit) {\n    const nodesToRevisit = [];\n    const pendingRequests = [];\n    while (nodesToVisit.length) {\n      let currentNode = nodesToVisit.pop();\n      if (currentNode instanceof Ref) {\n        if (this.refSet.has(currentNode)) {\n          continue;\n        }\n        try {\n          this.refSet.put(currentNode);\n          currentNode = this.xref.fetch(currentNode);\n        } catch (ex) {\n          if (!(ex instanceof MissingDataException)) {\n            warn(`ObjectLoader._walk - requesting all data: \"${ex}\".`);\n            this.refSet = null;\n            const {\n              manager\n            } = this.xref.stream;\n            return manager.requestAllChunks();\n          }\n          nodesToRevisit.push(currentNode);\n          pendingRequests.push({\n            begin: ex.begin,\n            end: ex.end\n          });\n        }\n      }\n      if (currentNode instanceof BaseStream) {\n        const baseStreams = currentNode.getBaseStreams();\n        if (baseStreams) {\n          let foundMissingData = false;\n          for (const stream of baseStreams) {\n            if (stream.isDataLoaded) {\n              continue;\n            }\n            foundMissingData = true;\n            pendingRequests.push({\n              begin: stream.start,\n              end: stream.end\n            });\n          }\n          if (foundMissingData) {\n            nodesToRevisit.push(currentNode);\n          }\n        }\n      }\n      addChildren(currentNode, nodesToVisit);\n    }\n    if (pendingRequests.length) {\n      await this.xref.stream.manager.requestRanges(pendingRequests);\n      for (const node of nodesToRevisit) {\n        if (node instanceof Ref) {\n          this.refSet.remove(node);\n        }\n      }\n      return this._walk(nodesToRevisit);\n    }\n    this.refSet = null;\n    return undefined;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/xfa/symbol_utils.js\nconst $acceptWhitespace = Symbol();\nconst $addHTML = Symbol();\nconst $appendChild = Symbol();\nconst $childrenToHTML = Symbol();\nconst $clean = Symbol();\nconst $cleanPage = Symbol();\nconst $cleanup = Symbol();\nconst $clone = Symbol();\nconst $consumed = Symbol();\nconst $content = Symbol(\"content\");\nconst $data = Symbol(\"data\");\nconst $dump = Symbol();\nconst $extra = Symbol(\"extra\");\nconst $finalize = Symbol();\nconst $flushHTML = Symbol();\nconst $getAttributeIt = Symbol();\nconst $getAttributes = Symbol();\nconst $getAvailableSpace = Symbol();\nconst $getChildrenByClass = Symbol();\nconst $getChildrenByName = Symbol();\nconst $getChildrenByNameIt = Symbol();\nconst $getDataValue = Symbol();\nconst $getExtra = Symbol();\nconst $getRealChildrenByNameIt = Symbol();\nconst $getChildren = Symbol();\nconst $getContainedChildren = Symbol();\nconst $getNextPage = Symbol();\nconst $getSubformParent = Symbol();\nconst $getParent = Symbol();\nconst $getTemplateRoot = Symbol();\nconst $globalData = Symbol();\nconst $hasSettableValue = Symbol();\nconst $ids = Symbol();\nconst $indexOf = Symbol();\nconst $insertAt = Symbol();\nconst $isCDATAXml = Symbol();\nconst $isBindable = Symbol();\nconst $isDataValue = Symbol();\nconst $isDescendent = Symbol();\nconst $isNsAgnostic = Symbol();\nconst $isSplittable = Symbol();\nconst $isThereMoreWidth = Symbol();\nconst $isTransparent = Symbol();\nconst $isUsable = Symbol();\nconst $lastAttribute = Symbol();\nconst $namespaceId = Symbol(\"namespaceId\");\nconst $nodeName = Symbol(\"nodeName\");\nconst $nsAttributes = Symbol();\nconst $onChild = Symbol();\nconst $onChildCheck = Symbol();\nconst $onText = Symbol();\nconst $pushGlyphs = Symbol();\nconst $popPara = Symbol();\nconst $pushPara = Symbol();\nconst $removeChild = Symbol();\nconst $root = Symbol(\"root\");\nconst $resolvePrototypes = Symbol();\nconst $searchNode = Symbol();\nconst $setId = Symbol();\nconst $setSetAttributes = Symbol();\nconst $setValue = Symbol();\nconst $tabIndex = Symbol();\nconst $text = Symbol();\nconst $toPages = Symbol();\nconst $toHTML = Symbol();\nconst $toString = Symbol();\nconst $toStyle = Symbol();\nconst $uid = Symbol(\"uid\");\n\n;// CONCATENATED MODULE: ./src/core/xfa/namespaces.js\nconst $buildXFAObject = Symbol();\nconst NamespaceIds = {\n  config: {\n    id: 0,\n    check: ns => ns.startsWith(\"http://www.xfa.org/schema/xci/\")\n  },\n  connectionSet: {\n    id: 1,\n    check: ns => ns.startsWith(\"http://www.xfa.org/schema/xfa-connection-set/\")\n  },\n  datasets: {\n    id: 2,\n    check: ns => ns.startsWith(\"http://www.xfa.org/schema/xfa-data/\")\n  },\n  form: {\n    id: 3,\n    check: ns => ns.startsWith(\"http://www.xfa.org/schema/xfa-form/\")\n  },\n  localeSet: {\n    id: 4,\n    check: ns => ns.startsWith(\"http://www.xfa.org/schema/xfa-locale-set/\")\n  },\n  pdf: {\n    id: 5,\n    check: ns => ns === \"http://ns.adobe.com/xdp/pdf/\"\n  },\n  signature: {\n    id: 6,\n    check: ns => ns === \"http://www.w3.org/2000/09/xmldsig#\"\n  },\n  sourceSet: {\n    id: 7,\n    check: ns => ns.startsWith(\"http://www.xfa.org/schema/xfa-source-set/\")\n  },\n  stylesheet: {\n    id: 8,\n    check: ns => ns === \"http://www.w3.org/1999/XSL/Transform\"\n  },\n  template: {\n    id: 9,\n    check: ns => ns.startsWith(\"http://www.xfa.org/schema/xfa-template/\")\n  },\n  xdc: {\n    id: 10,\n    check: ns => ns.startsWith(\"http://www.xfa.org/schema/xdc/\")\n  },\n  xdp: {\n    id: 11,\n    check: ns => ns === \"http://ns.adobe.com/xdp/\"\n  },\n  xfdf: {\n    id: 12,\n    check: ns => ns === \"http://ns.adobe.com/xfdf/\"\n  },\n  xhtml: {\n    id: 13,\n    check: ns => ns === \"http://www.w3.org/1999/xhtml\"\n  },\n  xmpmeta: {\n    id: 14,\n    check: ns => ns === \"http://ns.adobe.com/xmpmeta/\"\n  }\n};\n\n;// CONCATENATED MODULE: ./src/core/xfa/utils.js\n\nconst dimConverters = {\n  pt: x => x,\n  cm: x => x / 2.54 * 72,\n  mm: x => x / (10 * 2.54) * 72,\n  in: x => x * 72,\n  px: x => x\n};\nconst measurementPattern = /([+-]?\\d+\\.?\\d*)(.*)/;\nfunction stripQuotes(str) {\n  if (str.startsWith(\"'\") || str.startsWith('\"')) {\n    return str.slice(1, -1);\n  }\n  return str;\n}\nfunction getInteger({\n  data,\n  defaultValue,\n  validate\n}) {\n  if (!data) {\n    return defaultValue;\n  }\n  data = data.trim();\n  const n = parseInt(data, 10);\n  if (!isNaN(n) && validate(n)) {\n    return n;\n  }\n  return defaultValue;\n}\nfunction getFloat({\n  data,\n  defaultValue,\n  validate\n}) {\n  if (!data) {\n    return defaultValue;\n  }\n  data = data.trim();\n  const n = parseFloat(data);\n  if (!isNaN(n) && validate(n)) {\n    return n;\n  }\n  return defaultValue;\n}\nfunction getKeyword({\n  data,\n  defaultValue,\n  validate\n}) {\n  if (!data) {\n    return defaultValue;\n  }\n  data = data.trim();\n  if (validate(data)) {\n    return data;\n  }\n  return defaultValue;\n}\nfunction getStringOption(data, options) {\n  return getKeyword({\n    data,\n    defaultValue: options[0],\n    validate: k => options.includes(k)\n  });\n}\nfunction getMeasurement(str, def = \"0\") {\n  def ||= \"0\";\n  if (!str) {\n    return getMeasurement(def);\n  }\n  const match = str.trim().match(measurementPattern);\n  if (!match) {\n    return getMeasurement(def);\n  }\n  const [, valueStr, unit] = match;\n  const value = parseFloat(valueStr);\n  if (isNaN(value)) {\n    return getMeasurement(def);\n  }\n  if (value === 0) {\n    return 0;\n  }\n  const conv = dimConverters[unit];\n  if (conv) {\n    return conv(value);\n  }\n  return value;\n}\nfunction getRatio(data) {\n  if (!data) {\n    return {\n      num: 1,\n      den: 1\n    };\n  }\n  const ratio = data.trim().split(/\\s*:\\s*/).map(x => parseFloat(x)).filter(x => !isNaN(x));\n  if (ratio.length === 1) {\n    ratio.push(1);\n  }\n  if (ratio.length === 0) {\n    return {\n      num: 1,\n      den: 1\n    };\n  }\n  const [num, den] = ratio;\n  return {\n    num,\n    den\n  };\n}\nfunction getRelevant(data) {\n  if (!data) {\n    return [];\n  }\n  return data.trim().split(/\\s+/).map(e => ({\n    excluded: e[0] === \"-\",\n    viewname: e.substring(1)\n  }));\n}\nfunction getColor(data, def = [0, 0, 0]) {\n  let [r, g, b] = def;\n  if (!data) {\n    return {\n      r,\n      g,\n      b\n    };\n  }\n  const color = data.trim().split(/\\s*,\\s*/).map(c => Math.min(Math.max(0, parseInt(c.trim(), 10)), 255)).map(c => isNaN(c) ? 0 : c);\n  if (color.length < 3) {\n    return {\n      r,\n      g,\n      b\n    };\n  }\n  [r, g, b] = color;\n  return {\n    r,\n    g,\n    b\n  };\n}\nfunction getBBox(data) {\n  const def = -1;\n  if (!data) {\n    return {\n      x: def,\n      y: def,\n      width: def,\n      height: def\n    };\n  }\n  const bbox = data.trim().split(/\\s*,\\s*/).map(m => getMeasurement(m, \"-1\"));\n  if (bbox.length < 4 || bbox[2] < 0 || bbox[3] < 0) {\n    return {\n      x: def,\n      y: def,\n      width: def,\n      height: def\n    };\n  }\n  const [x, y, width, height] = bbox;\n  return {\n    x,\n    y,\n    width,\n    height\n  };\n}\nclass HTMLResult {\n  static get FAILURE() {\n    return shadow(this, \"FAILURE\", new HTMLResult(false, null, null, null));\n  }\n  static get EMPTY() {\n    return shadow(this, \"EMPTY\", new HTMLResult(true, null, null, null));\n  }\n  constructor(success, html, bbox, breakNode) {\n    this.success = success;\n    this.html = html;\n    this.bbox = bbox;\n    this.breakNode = breakNode;\n  }\n  isBreak() {\n    return !!this.breakNode;\n  }\n  static breakNode(node) {\n    return new HTMLResult(false, null, null, node);\n  }\n  static success(html, bbox = null) {\n    return new HTMLResult(true, html, bbox, null);\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/xfa/fonts.js\n\n\n\nclass FontFinder {\n  constructor(pdfFonts) {\n    this.fonts = new Map();\n    this.cache = new Map();\n    this.warned = new Set();\n    this.defaultFont = null;\n    this.add(pdfFonts);\n  }\n  add(pdfFonts, reallyMissingFonts = null) {\n    for (const pdfFont of pdfFonts) {\n      this.addPdfFont(pdfFont);\n    }\n    for (const pdfFont of this.fonts.values()) {\n      if (!pdfFont.regular) {\n        pdfFont.regular = pdfFont.italic || pdfFont.bold || pdfFont.bolditalic;\n      }\n    }\n    if (!reallyMissingFonts || reallyMissingFonts.size === 0) {\n      return;\n    }\n    const myriad = this.fonts.get(\"PdfJS-Fallback-PdfJS-XFA\");\n    for (const missing of reallyMissingFonts) {\n      this.fonts.set(missing, myriad);\n    }\n  }\n  addPdfFont(pdfFont) {\n    const cssFontInfo = pdfFont.cssFontInfo;\n    const name = cssFontInfo.fontFamily;\n    let font = this.fonts.get(name);\n    if (!font) {\n      font = Object.create(null);\n      this.fonts.set(name, font);\n      if (!this.defaultFont) {\n        this.defaultFont = font;\n      }\n    }\n    let property = \"\";\n    const fontWeight = parseFloat(cssFontInfo.fontWeight);\n    if (parseFloat(cssFontInfo.italicAngle) !== 0) {\n      property = fontWeight >= 700 ? \"bolditalic\" : \"italic\";\n    } else if (fontWeight >= 700) {\n      property = \"bold\";\n    }\n    if (!property) {\n      if (pdfFont.name.includes(\"Bold\") || pdfFont.psName?.includes(\"Bold\")) {\n        property = \"bold\";\n      }\n      if (pdfFont.name.includes(\"Italic\") || pdfFont.name.endsWith(\"It\") || pdfFont.psName?.includes(\"Italic\") || pdfFont.psName?.endsWith(\"It\")) {\n        property += \"italic\";\n      }\n    }\n    if (!property) {\n      property = \"regular\";\n    }\n    font[property] = pdfFont;\n  }\n  getDefault() {\n    return this.defaultFont;\n  }\n  find(fontName, mustWarn = true) {\n    let font = this.fonts.get(fontName) || this.cache.get(fontName);\n    if (font) {\n      return font;\n    }\n    const pattern = /,|-|_| |bolditalic|bold|italic|regular|it/gi;\n    let name = fontName.replaceAll(pattern, \"\");\n    font = this.fonts.get(name);\n    if (font) {\n      this.cache.set(fontName, font);\n      return font;\n    }\n    name = name.toLowerCase();\n    const maybe = [];\n    for (const [family, pdfFont] of this.fonts.entries()) {\n      if (family.replaceAll(pattern, \"\").toLowerCase().startsWith(name)) {\n        maybe.push(pdfFont);\n      }\n    }\n    if (maybe.length === 0) {\n      for (const [, pdfFont] of this.fonts.entries()) {\n        if (pdfFont.regular.name?.replaceAll(pattern, \"\").toLowerCase().startsWith(name)) {\n          maybe.push(pdfFont);\n        }\n      }\n    }\n    if (maybe.length === 0) {\n      name = name.replaceAll(/psmt|mt/gi, \"\");\n      for (const [family, pdfFont] of this.fonts.entries()) {\n        if (family.replaceAll(pattern, \"\").toLowerCase().startsWith(name)) {\n          maybe.push(pdfFont);\n        }\n      }\n    }\n    if (maybe.length === 0) {\n      for (const pdfFont of this.fonts.values()) {\n        if (pdfFont.regular.name?.replaceAll(pattern, \"\").toLowerCase().startsWith(name)) {\n          maybe.push(pdfFont);\n        }\n      }\n    }\n    if (maybe.length >= 1) {\n      if (maybe.length !== 1 && mustWarn) {\n        warn(`XFA - Too many choices to guess the correct font: ${fontName}`);\n      }\n      this.cache.set(fontName, maybe[0]);\n      return maybe[0];\n    }\n    if (mustWarn && !this.warned.has(fontName)) {\n      this.warned.add(fontName);\n      warn(`XFA - Cannot find the font: ${fontName}`);\n    }\n    return null;\n  }\n}\nfunction selectFont(xfaFont, typeface) {\n  if (xfaFont.posture === \"italic\") {\n    if (xfaFont.weight === \"bold\") {\n      return typeface.bolditalic;\n    }\n    return typeface.italic;\n  } else if (xfaFont.weight === \"bold\") {\n    return typeface.bold;\n  }\n  return typeface.regular;\n}\nfunction fonts_getMetrics(xfaFont, real = false) {\n  let pdfFont = null;\n  if (xfaFont) {\n    const name = stripQuotes(xfaFont.typeface);\n    const typeface = xfaFont[$globalData].fontFinder.find(name);\n    pdfFont = selectFont(xfaFont, typeface);\n  }\n  if (!pdfFont) {\n    return {\n      lineHeight: 12,\n      lineGap: 2,\n      lineNoGap: 10\n    };\n  }\n  const size = xfaFont.size || 10;\n  const lineHeight = pdfFont.lineHeight ? Math.max(real ? 0 : 1.2, pdfFont.lineHeight) : 1.2;\n  const lineGap = pdfFont.lineGap === undefined ? 0.2 : pdfFont.lineGap;\n  return {\n    lineHeight: lineHeight * size,\n    lineGap: lineGap * size,\n    lineNoGap: Math.max(1, lineHeight - lineGap) * size\n  };\n}\n\n;// CONCATENATED MODULE: ./src/core/xfa/text.js\n\nconst WIDTH_FACTOR = 1.02;\nclass FontInfo {\n  constructor(xfaFont, margin, lineHeight, fontFinder) {\n    this.lineHeight = lineHeight;\n    this.paraMargin = margin || {\n      top: 0,\n      bottom: 0,\n      left: 0,\n      right: 0\n    };\n    if (!xfaFont) {\n      [this.pdfFont, this.xfaFont] = this.defaultFont(fontFinder);\n      return;\n    }\n    this.xfaFont = {\n      typeface: xfaFont.typeface,\n      posture: xfaFont.posture,\n      weight: xfaFont.weight,\n      size: xfaFont.size,\n      letterSpacing: xfaFont.letterSpacing\n    };\n    const typeface = fontFinder.find(xfaFont.typeface);\n    if (!typeface) {\n      [this.pdfFont, this.xfaFont] = this.defaultFont(fontFinder);\n      return;\n    }\n    this.pdfFont = selectFont(xfaFont, typeface);\n    if (!this.pdfFont) {\n      [this.pdfFont, this.xfaFont] = this.defaultFont(fontFinder);\n    }\n  }\n  defaultFont(fontFinder) {\n    const font = fontFinder.find(\"Helvetica\", false) || fontFinder.find(\"Myriad Pro\", false) || fontFinder.find(\"Arial\", false) || fontFinder.getDefault();\n    if (font?.regular) {\n      const pdfFont = font.regular;\n      const info = pdfFont.cssFontInfo;\n      const xfaFont = {\n        typeface: info.fontFamily,\n        posture: \"normal\",\n        weight: \"normal\",\n        size: 10,\n        letterSpacing: 0\n      };\n      return [pdfFont, xfaFont];\n    }\n    const xfaFont = {\n      typeface: \"Courier\",\n      posture: \"normal\",\n      weight: \"normal\",\n      size: 10,\n      letterSpacing: 0\n    };\n    return [null, xfaFont];\n  }\n}\nclass FontSelector {\n  constructor(defaultXfaFont, defaultParaMargin, defaultLineHeight, fontFinder) {\n    this.fontFinder = fontFinder;\n    this.stack = [new FontInfo(defaultXfaFont, defaultParaMargin, defaultLineHeight, fontFinder)];\n  }\n  pushData(xfaFont, margin, lineHeight) {\n    const lastFont = this.stack.at(-1);\n    for (const name of [\"typeface\", \"posture\", \"weight\", \"size\", \"letterSpacing\"]) {\n      if (!xfaFont[name]) {\n        xfaFont[name] = lastFont.xfaFont[name];\n      }\n    }\n    for (const name of [\"top\", \"bottom\", \"left\", \"right\"]) {\n      if (isNaN(margin[name])) {\n        margin[name] = lastFont.paraMargin[name];\n      }\n    }\n    const fontInfo = new FontInfo(xfaFont, margin, lineHeight || lastFont.lineHeight, this.fontFinder);\n    if (!fontInfo.pdfFont) {\n      fontInfo.pdfFont = lastFont.pdfFont;\n    }\n    this.stack.push(fontInfo);\n  }\n  popFont() {\n    this.stack.pop();\n  }\n  topFont() {\n    return this.stack.at(-1);\n  }\n}\nclass TextMeasure {\n  constructor(defaultXfaFont, defaultParaMargin, defaultLineHeight, fonts) {\n    this.glyphs = [];\n    this.fontSelector = new FontSelector(defaultXfaFont, defaultParaMargin, defaultLineHeight, fonts);\n    this.extraHeight = 0;\n  }\n  pushData(xfaFont, margin, lineHeight) {\n    this.fontSelector.pushData(xfaFont, margin, lineHeight);\n  }\n  popFont(xfaFont) {\n    return this.fontSelector.popFont();\n  }\n  addPara() {\n    const lastFont = this.fontSelector.topFont();\n    this.extraHeight += lastFont.paraMargin.top + lastFont.paraMargin.bottom;\n  }\n  addString(str) {\n    if (!str) {\n      return;\n    }\n    const lastFont = this.fontSelector.topFont();\n    const fontSize = lastFont.xfaFont.size;\n    if (lastFont.pdfFont) {\n      const letterSpacing = lastFont.xfaFont.letterSpacing;\n      const pdfFont = lastFont.pdfFont;\n      const fontLineHeight = pdfFont.lineHeight || 1.2;\n      const lineHeight = lastFont.lineHeight || Math.max(1.2, fontLineHeight) * fontSize;\n      const lineGap = pdfFont.lineGap === undefined ? 0.2 : pdfFont.lineGap;\n      const noGap = fontLineHeight - lineGap;\n      const firstLineHeight = Math.max(1, noGap) * fontSize;\n      const scale = fontSize / 1000;\n      const fallbackWidth = pdfFont.defaultWidth || pdfFont.charsToGlyphs(\" \")[0].width;\n      for (const line of str.split(/[\\u2029\\n]/)) {\n        const encodedLine = pdfFont.encodeString(line).join(\"\");\n        const glyphs = pdfFont.charsToGlyphs(encodedLine);\n        for (const glyph of glyphs) {\n          const width = glyph.width || fallbackWidth;\n          this.glyphs.push([width * scale + letterSpacing, lineHeight, firstLineHeight, glyph.unicode, false]);\n        }\n        this.glyphs.push([0, 0, 0, \"\\n\", true]);\n      }\n      this.glyphs.pop();\n      return;\n    }\n    for (const line of str.split(/[\\u2029\\n]/)) {\n      for (const char of line.split(\"\")) {\n        this.glyphs.push([fontSize, 1.2 * fontSize, fontSize, char, false]);\n      }\n      this.glyphs.push([0, 0, 0, \"\\n\", true]);\n    }\n    this.glyphs.pop();\n  }\n  compute(maxWidth) {\n    let lastSpacePos = -1,\n      lastSpaceWidth = 0,\n      width = 0,\n      height = 0,\n      currentLineWidth = 0,\n      currentLineHeight = 0;\n    let isBroken = false;\n    let isFirstLine = true;\n    for (let i = 0, ii = this.glyphs.length; i < ii; i++) {\n      const [glyphWidth, lineHeight, firstLineHeight, char, isEOL] = this.glyphs[i];\n      const isSpace = char === \" \";\n      const glyphHeight = isFirstLine ? firstLineHeight : lineHeight;\n      if (isEOL) {\n        width = Math.max(width, currentLineWidth);\n        currentLineWidth = 0;\n        height += currentLineHeight;\n        currentLineHeight = glyphHeight;\n        lastSpacePos = -1;\n        lastSpaceWidth = 0;\n        isFirstLine = false;\n        continue;\n      }\n      if (isSpace) {\n        if (currentLineWidth + glyphWidth > maxWidth) {\n          width = Math.max(width, currentLineWidth);\n          currentLineWidth = 0;\n          height += currentLineHeight;\n          currentLineHeight = glyphHeight;\n          lastSpacePos = -1;\n          lastSpaceWidth = 0;\n          isBroken = true;\n          isFirstLine = false;\n        } else {\n          currentLineHeight = Math.max(glyphHeight, currentLineHeight);\n          lastSpaceWidth = currentLineWidth;\n          currentLineWidth += glyphWidth;\n          lastSpacePos = i;\n        }\n        continue;\n      }\n      if (currentLineWidth + glyphWidth > maxWidth) {\n        height += currentLineHeight;\n        currentLineHeight = glyphHeight;\n        if (lastSpacePos !== -1) {\n          i = lastSpacePos;\n          width = Math.max(width, lastSpaceWidth);\n          currentLineWidth = 0;\n          lastSpacePos = -1;\n          lastSpaceWidth = 0;\n        } else {\n          width = Math.max(width, currentLineWidth);\n          currentLineWidth = glyphWidth;\n        }\n        isBroken = true;\n        isFirstLine = false;\n        continue;\n      }\n      currentLineWidth += glyphWidth;\n      currentLineHeight = Math.max(glyphHeight, currentLineHeight);\n    }\n    width = Math.max(width, currentLineWidth);\n    height += currentLineHeight + this.extraHeight;\n    return {\n      width: WIDTH_FACTOR * width,\n      height,\n      isBroken\n    };\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/xfa/som.js\n\n\nconst namePattern = /^[^.[]+/;\nconst indexPattern = /^[^\\]]+/;\nconst operators = {\n  dot: 0,\n  dotDot: 1,\n  dotHash: 2,\n  dotBracket: 3,\n  dotParen: 4\n};\nconst shortcuts = new Map([[\"$data\", (root, current) => root.datasets ? root.datasets.data : root], [\"$record\", (root, current) => (root.datasets ? root.datasets.data : root)[$getChildren]()[0]], [\"$template\", (root, current) => root.template], [\"$connectionSet\", (root, current) => root.connectionSet], [\"$form\", (root, current) => root.form], [\"$layout\", (root, current) => root.layout], [\"$host\", (root, current) => root.host], [\"$dataWindow\", (root, current) => root.dataWindow], [\"$event\", (root, current) => root.event], [\"!\", (root, current) => root.datasets], [\"$xfa\", (root, current) => root], [\"xfa\", (root, current) => root], [\"$\", (root, current) => current]]);\nconst somCache = new WeakMap();\nfunction parseIndex(index) {\n  index = index.trim();\n  if (index === \"*\") {\n    return Infinity;\n  }\n  return parseInt(index, 10) || 0;\n}\nfunction parseExpression(expr, dotDotAllowed, noExpr = true) {\n  let match = expr.match(namePattern);\n  if (!match) {\n    return null;\n  }\n  let [name] = match;\n  const parsed = [{\n    name,\n    cacheName: \".\" + name,\n    index: 0,\n    js: null,\n    formCalc: null,\n    operator: operators.dot\n  }];\n  let pos = name.length;\n  while (pos < expr.length) {\n    const spos = pos;\n    const char = expr.charAt(pos++);\n    if (char === \"[\") {\n      match = expr.slice(pos).match(indexPattern);\n      if (!match) {\n        warn(\"XFA - Invalid index in SOM expression\");\n        return null;\n      }\n      parsed.at(-1).index = parseIndex(match[0]);\n      pos += match[0].length + 1;\n      continue;\n    }\n    let operator;\n    switch (expr.charAt(pos)) {\n      case \".\":\n        if (!dotDotAllowed) {\n          return null;\n        }\n        pos++;\n        operator = operators.dotDot;\n        break;\n      case \"#\":\n        pos++;\n        operator = operators.dotHash;\n        break;\n      case \"[\":\n        if (noExpr) {\n          warn(\"XFA - SOM expression contains a FormCalc subexpression which is not supported for now.\");\n          return null;\n        }\n        operator = operators.dotBracket;\n        break;\n      case \"(\":\n        if (noExpr) {\n          warn(\"XFA - SOM expression contains a JavaScript subexpression which is not supported for now.\");\n          return null;\n        }\n        operator = operators.dotParen;\n        break;\n      default:\n        operator = operators.dot;\n        break;\n    }\n    match = expr.slice(pos).match(namePattern);\n    if (!match) {\n      break;\n    }\n    [name] = match;\n    pos += name.length;\n    parsed.push({\n      name,\n      cacheName: expr.slice(spos, pos),\n      operator,\n      index: 0,\n      js: null,\n      formCalc: null\n    });\n  }\n  return parsed;\n}\nfunction searchNode(root, container, expr, dotDotAllowed = true, useCache = true) {\n  const parsed = parseExpression(expr, dotDotAllowed);\n  if (!parsed) {\n    return null;\n  }\n  const fn = shortcuts.get(parsed[0].name);\n  let i = 0;\n  let isQualified;\n  if (fn) {\n    isQualified = true;\n    root = [fn(root, container)];\n    i = 1;\n  } else {\n    isQualified = container === null;\n    root = [container || root];\n  }\n  for (let ii = parsed.length; i < ii; i++) {\n    const {\n      name,\n      cacheName,\n      operator,\n      index\n    } = parsed[i];\n    const nodes = [];\n    for (const node of root) {\n      if (!node.isXFAObject) {\n        continue;\n      }\n      let children, cached;\n      if (useCache) {\n        cached = somCache.get(node);\n        if (!cached) {\n          cached = new Map();\n          somCache.set(node, cached);\n        }\n        children = cached.get(cacheName);\n      }\n      if (!children) {\n        switch (operator) {\n          case operators.dot:\n            children = node[$getChildrenByName](name, false);\n            break;\n          case operators.dotDot:\n            children = node[$getChildrenByName](name, true);\n            break;\n          case operators.dotHash:\n            children = node[$getChildrenByClass](name);\n            children = children.isXFAObjectArray ? children.children : [children];\n            break;\n          default:\n            break;\n        }\n        if (useCache) {\n          cached.set(cacheName, children);\n        }\n      }\n      if (children.length > 0) {\n        nodes.push(children);\n      }\n    }\n    if (nodes.length === 0 && !isQualified && i === 0) {\n      const parent = container[$getParent]();\n      container = parent;\n      if (!container) {\n        return null;\n      }\n      i = -1;\n      root = [container];\n      continue;\n    }\n    root = isFinite(index) ? nodes.filter(node => index < node.length).map(node => node[index]) : nodes.flat();\n  }\n  if (root.length === 0) {\n    return null;\n  }\n  return root;\n}\nfunction createDataNode(root, container, expr) {\n  const parsed = parseExpression(expr);\n  if (!parsed) {\n    return null;\n  }\n  if (parsed.some(x => x.operator === operators.dotDot)) {\n    return null;\n  }\n  const fn = shortcuts.get(parsed[0].name);\n  let i = 0;\n  if (fn) {\n    root = fn(root, container);\n    i = 1;\n  } else {\n    root = container || root;\n  }\n  for (let ii = parsed.length; i < ii; i++) {\n    const {\n      name,\n      operator,\n      index\n    } = parsed[i];\n    if (!isFinite(index)) {\n      parsed[i].index = 0;\n      return root.createNodes(parsed.slice(i));\n    }\n    let children;\n    switch (operator) {\n      case operators.dot:\n        children = root[$getChildrenByName](name, false);\n        break;\n      case operators.dotDot:\n        children = root[$getChildrenByName](name, true);\n        break;\n      case operators.dotHash:\n        children = root[$getChildrenByClass](name);\n        children = children.isXFAObjectArray ? children.children : [children];\n        break;\n      default:\n        break;\n    }\n    if (children.length === 0) {\n      return root.createNodes(parsed.slice(i));\n    }\n    if (index < children.length) {\n      const child = children[index];\n      if (!child.isXFAObject) {\n        warn(`XFA - Cannot create a node.`);\n        return null;\n      }\n      root = child;\n    } else {\n      parsed[i].index = index - children.length;\n      return root.createNodes(parsed.slice(i));\n    }\n  }\n  return null;\n}\n\n;// CONCATENATED MODULE: ./src/core/xfa/xfa_object.js\n\n\n\n\n\n\nconst _applyPrototype = Symbol();\nconst _attributes = Symbol();\nconst _attributeNames = Symbol();\nconst _children = Symbol(\"_children\");\nconst _cloneAttribute = Symbol();\nconst _dataValue = Symbol();\nconst _defaultValue = Symbol();\nconst _filteredChildrenGenerator = Symbol();\nconst _getPrototype = Symbol();\nconst _getUnsetAttributes = Symbol();\nconst _hasChildren = Symbol();\nconst _max = Symbol();\nconst _options = Symbol();\nconst _parent = Symbol(\"parent\");\nconst _resolvePrototypesHelper = Symbol();\nconst _setAttributes = Symbol();\nconst _validator = Symbol();\nlet uid = 0;\nconst NS_DATASETS = NamespaceIds.datasets.id;\nclass XFAObject {\n  constructor(nsId, name, hasChildren = false) {\n    this[$namespaceId] = nsId;\n    this[$nodeName] = name;\n    this[_hasChildren] = hasChildren;\n    this[_parent] = null;\n    this[_children] = [];\n    this[$uid] = `${name}${uid++}`;\n    this[$globalData] = null;\n  }\n  get isXFAObject() {\n    return true;\n  }\n  get isXFAObjectArray() {\n    return false;\n  }\n  createNodes(path) {\n    let root = this,\n      node = null;\n    for (const {\n      name,\n      index\n    } of path) {\n      for (let i = 0, ii = isFinite(index) ? index : 0; i <= ii; i++) {\n        const nsId = root[$namespaceId] === NS_DATASETS ? -1 : root[$namespaceId];\n        node = new XmlObject(nsId, name);\n        root[$appendChild](node);\n      }\n      root = node;\n    }\n    return node;\n  }\n  [$onChild](child) {\n    if (!this[_hasChildren] || !this[$onChildCheck](child)) {\n      return false;\n    }\n    const name = child[$nodeName];\n    const node = this[name];\n    if (node instanceof XFAObjectArray) {\n      if (node.push(child)) {\n        this[$appendChild](child);\n        return true;\n      }\n    } else {\n      if (node !== null) {\n        this[$removeChild](node);\n      }\n      this[name] = child;\n      this[$appendChild](child);\n      return true;\n    }\n    let id = \"\";\n    if (this.id) {\n      id = ` (id: ${this.id})`;\n    } else if (this.name) {\n      id = ` (name: ${this.name} ${this.h.value})`;\n    }\n    warn(`XFA - node \"${this[$nodeName]}\"${id} has already enough \"${name}\"!`);\n    return false;\n  }\n  [$onChildCheck](child) {\n    return this.hasOwnProperty(child[$nodeName]) && child[$namespaceId] === this[$namespaceId];\n  }\n  [$isNsAgnostic]() {\n    return false;\n  }\n  [$acceptWhitespace]() {\n    return false;\n  }\n  [$isCDATAXml]() {\n    return false;\n  }\n  [$isBindable]() {\n    return false;\n  }\n  [$popPara]() {\n    if (this.para) {\n      this[$getTemplateRoot]()[$extra].paraStack.pop();\n    }\n  }\n  [$pushPara]() {\n    this[$getTemplateRoot]()[$extra].paraStack.push(this.para);\n  }\n  [$setId](ids) {\n    if (this.id && this[$namespaceId] === NamespaceIds.template.id) {\n      ids.set(this.id, this);\n    }\n  }\n  [$getTemplateRoot]() {\n    return this[$globalData].template;\n  }\n  [$isSplittable]() {\n    return false;\n  }\n  [$isThereMoreWidth]() {\n    return false;\n  }\n  [$appendChild](child) {\n    child[_parent] = this;\n    this[_children].push(child);\n    if (!child[$globalData] && this[$globalData]) {\n      child[$globalData] = this[$globalData];\n    }\n  }\n  [$removeChild](child) {\n    const i = this[_children].indexOf(child);\n    this[_children].splice(i, 1);\n  }\n  [$hasSettableValue]() {\n    return this.hasOwnProperty(\"value\");\n  }\n  [$setValue](_) {}\n  [$onText](_) {}\n  [$finalize]() {}\n  [$clean](builder) {\n    delete this[_hasChildren];\n    if (this[$cleanup]) {\n      builder.clean(this[$cleanup]);\n      delete this[$cleanup];\n    }\n  }\n  [$indexOf](child) {\n    return this[_children].indexOf(child);\n  }\n  [$insertAt](i, child) {\n    child[_parent] = this;\n    this[_children].splice(i, 0, child);\n    if (!child[$globalData] && this[$globalData]) {\n      child[$globalData] = this[$globalData];\n    }\n  }\n  [$isTransparent]() {\n    return !this.name;\n  }\n  [$lastAttribute]() {\n    return \"\";\n  }\n  [$text]() {\n    if (this[_children].length === 0) {\n      return this[$content];\n    }\n    return this[_children].map(c => c[$text]()).join(\"\");\n  }\n  get [_attributeNames]() {\n    const proto = Object.getPrototypeOf(this);\n    if (!proto._attributes) {\n      const attributes = proto._attributes = new Set();\n      for (const name of Object.getOwnPropertyNames(this)) {\n        if (this[name] === null || this[name] instanceof XFAObject || this[name] instanceof XFAObjectArray) {\n          break;\n        }\n        attributes.add(name);\n      }\n    }\n    return shadow(this, _attributeNames, proto._attributes);\n  }\n  [$isDescendent](parent) {\n    let node = this;\n    while (node) {\n      if (node === parent) {\n        return true;\n      }\n      node = node[$getParent]();\n    }\n    return false;\n  }\n  [$getParent]() {\n    return this[_parent];\n  }\n  [$getSubformParent]() {\n    return this[$getParent]();\n  }\n  [$getChildren](name = null) {\n    if (!name) {\n      return this[_children];\n    }\n    return this[name];\n  }\n  [$dump]() {\n    const dumped = Object.create(null);\n    if (this[$content]) {\n      dumped.$content = this[$content];\n    }\n    for (const name of Object.getOwnPropertyNames(this)) {\n      const value = this[name];\n      if (value === null) {\n        continue;\n      }\n      if (value instanceof XFAObject) {\n        dumped[name] = value[$dump]();\n      } else if (value instanceof XFAObjectArray) {\n        if (!value.isEmpty()) {\n          dumped[name] = value.dump();\n        }\n      } else {\n        dumped[name] = value;\n      }\n    }\n    return dumped;\n  }\n  [$toStyle]() {\n    return null;\n  }\n  [$toHTML]() {\n    return HTMLResult.EMPTY;\n  }\n  *[$getContainedChildren]() {\n    for (const node of this[$getChildren]()) {\n      yield node;\n    }\n  }\n  *[_filteredChildrenGenerator](filter, include) {\n    for (const node of this[$getContainedChildren]()) {\n      if (!filter || include === filter.has(node[$nodeName])) {\n        const availableSpace = this[$getAvailableSpace]();\n        const res = node[$toHTML](availableSpace);\n        if (!res.success) {\n          this[$extra].failingNode = node;\n        }\n        yield res;\n      }\n    }\n  }\n  [$flushHTML]() {\n    return null;\n  }\n  [$addHTML](html, bbox) {\n    this[$extra].children.push(html);\n  }\n  [$getAvailableSpace]() {}\n  [$childrenToHTML]({\n    filter = null,\n    include = true\n  }) {\n    if (!this[$extra].generator) {\n      this[$extra].generator = this[_filteredChildrenGenerator](filter, include);\n    } else {\n      const availableSpace = this[$getAvailableSpace]();\n      const res = this[$extra].failingNode[$toHTML](availableSpace);\n      if (!res.success) {\n        return res;\n      }\n      if (res.html) {\n        this[$addHTML](res.html, res.bbox);\n      }\n      delete this[$extra].failingNode;\n    }\n    while (true) {\n      const gen = this[$extra].generator.next();\n      if (gen.done) {\n        break;\n      }\n      const res = gen.value;\n      if (!res.success) {\n        return res;\n      }\n      if (res.html) {\n        this[$addHTML](res.html, res.bbox);\n      }\n    }\n    this[$extra].generator = null;\n    return HTMLResult.EMPTY;\n  }\n  [$setSetAttributes](attributes) {\n    this[_setAttributes] = new Set(Object.keys(attributes));\n  }\n  [_getUnsetAttributes](protoAttributes) {\n    const allAttr = this[_attributeNames];\n    const setAttr = this[_setAttributes];\n    return [...protoAttributes].filter(x => allAttr.has(x) && !setAttr.has(x));\n  }\n  [$resolvePrototypes](ids, ancestors = new Set()) {\n    for (const child of this[_children]) {\n      child[_resolvePrototypesHelper](ids, ancestors);\n    }\n  }\n  [_resolvePrototypesHelper](ids, ancestors) {\n    const proto = this[_getPrototype](ids, ancestors);\n    if (proto) {\n      this[_applyPrototype](proto, ids, ancestors);\n    } else {\n      this[$resolvePrototypes](ids, ancestors);\n    }\n  }\n  [_getPrototype](ids, ancestors) {\n    const {\n      use,\n      usehref\n    } = this;\n    if (!use && !usehref) {\n      return null;\n    }\n    let proto = null;\n    let somExpression = null;\n    let id = null;\n    let ref = use;\n    if (usehref) {\n      ref = usehref;\n      if (usehref.startsWith(\"#som(\") && usehref.endsWith(\")\")) {\n        somExpression = usehref.slice(\"#som(\".length, -1);\n      } else if (usehref.startsWith(\".#som(\") && usehref.endsWith(\")\")) {\n        somExpression = usehref.slice(\".#som(\".length, -1);\n      } else if (usehref.startsWith(\"#\")) {\n        id = usehref.slice(1);\n      } else if (usehref.startsWith(\".#\")) {\n        id = usehref.slice(2);\n      }\n    } else if (use.startsWith(\"#\")) {\n      id = use.slice(1);\n    } else {\n      somExpression = use;\n    }\n    this.use = this.usehref = \"\";\n    if (id) {\n      proto = ids.get(id);\n    } else {\n      proto = searchNode(ids.get($root), this, somExpression, true, false);\n      if (proto) {\n        proto = proto[0];\n      }\n    }\n    if (!proto) {\n      warn(`XFA - Invalid prototype reference: ${ref}.`);\n      return null;\n    }\n    if (proto[$nodeName] !== this[$nodeName]) {\n      warn(`XFA - Incompatible prototype: ${proto[$nodeName]} !== ${this[$nodeName]}.`);\n      return null;\n    }\n    if (ancestors.has(proto)) {\n      warn(`XFA - Cycle detected in prototypes use.`);\n      return null;\n    }\n    ancestors.add(proto);\n    const protoProto = proto[_getPrototype](ids, ancestors);\n    if (protoProto) {\n      proto[_applyPrototype](protoProto, ids, ancestors);\n    }\n    proto[$resolvePrototypes](ids, ancestors);\n    ancestors.delete(proto);\n    return proto;\n  }\n  [_applyPrototype](proto, ids, ancestors) {\n    if (ancestors.has(proto)) {\n      warn(`XFA - Cycle detected in prototypes use.`);\n      return;\n    }\n    if (!this[$content] && proto[$content]) {\n      this[$content] = proto[$content];\n    }\n    const newAncestors = new Set(ancestors);\n    newAncestors.add(proto);\n    for (const unsetAttrName of this[_getUnsetAttributes](proto[_setAttributes])) {\n      this[unsetAttrName] = proto[unsetAttrName];\n      if (this[_setAttributes]) {\n        this[_setAttributes].add(unsetAttrName);\n      }\n    }\n    for (const name of Object.getOwnPropertyNames(this)) {\n      if (this[_attributeNames].has(name)) {\n        continue;\n      }\n      const value = this[name];\n      const protoValue = proto[name];\n      if (value instanceof XFAObjectArray) {\n        for (const child of value[_children]) {\n          child[_resolvePrototypesHelper](ids, ancestors);\n        }\n        for (let i = value[_children].length, ii = protoValue[_children].length; i < ii; i++) {\n          const child = proto[_children][i][$clone]();\n          if (value.push(child)) {\n            child[_parent] = this;\n            this[_children].push(child);\n            child[_resolvePrototypesHelper](ids, ancestors);\n          } else {\n            break;\n          }\n        }\n        continue;\n      }\n      if (value !== null) {\n        value[$resolvePrototypes](ids, ancestors);\n        if (protoValue) {\n          value[_applyPrototype](protoValue, ids, ancestors);\n        }\n        continue;\n      }\n      if (protoValue !== null) {\n        const child = protoValue[$clone]();\n        child[_parent] = this;\n        this[name] = child;\n        this[_children].push(child);\n        child[_resolvePrototypesHelper](ids, ancestors);\n      }\n    }\n  }\n  static [_cloneAttribute](obj) {\n    if (Array.isArray(obj)) {\n      return obj.map(x => XFAObject[_cloneAttribute](x));\n    }\n    if (typeof obj === \"object\" && obj !== null) {\n      return Object.assign({}, obj);\n    }\n    return obj;\n  }\n  [$clone]() {\n    const clone = Object.create(Object.getPrototypeOf(this));\n    for (const $symbol of Object.getOwnPropertySymbols(this)) {\n      try {\n        clone[$symbol] = this[$symbol];\n      } catch {\n        shadow(clone, $symbol, this[$symbol]);\n      }\n    }\n    clone[$uid] = `${clone[$nodeName]}${uid++}`;\n    clone[_children] = [];\n    for (const name of Object.getOwnPropertyNames(this)) {\n      if (this[_attributeNames].has(name)) {\n        clone[name] = XFAObject[_cloneAttribute](this[name]);\n        continue;\n      }\n      const value = this[name];\n      clone[name] = value instanceof XFAObjectArray ? new XFAObjectArray(value[_max]) : null;\n    }\n    for (const child of this[_children]) {\n      const name = child[$nodeName];\n      const clonedChild = child[$clone]();\n      clone[_children].push(clonedChild);\n      clonedChild[_parent] = clone;\n      if (clone[name] === null) {\n        clone[name] = clonedChild;\n      } else {\n        clone[name][_children].push(clonedChild);\n      }\n    }\n    return clone;\n  }\n  [$getChildren](name = null) {\n    if (!name) {\n      return this[_children];\n    }\n    return this[_children].filter(c => c[$nodeName] === name);\n  }\n  [$getChildrenByClass](name) {\n    return this[name];\n  }\n  [$getChildrenByName](name, allTransparent, first = true) {\n    return Array.from(this[$getChildrenByNameIt](name, allTransparent, first));\n  }\n  *[$getChildrenByNameIt](name, allTransparent, first = true) {\n    if (name === \"parent\") {\n      yield this[_parent];\n      return;\n    }\n    for (const child of this[_children]) {\n      if (child[$nodeName] === name) {\n        yield child;\n      }\n      if (child.name === name) {\n        yield child;\n      }\n      if (allTransparent || child[$isTransparent]()) {\n        yield* child[$getChildrenByNameIt](name, allTransparent, false);\n      }\n    }\n    if (first && this[_attributeNames].has(name)) {\n      yield new XFAAttribute(this, name, this[name]);\n    }\n  }\n}\nclass XFAObjectArray {\n  constructor(max = Infinity) {\n    this[_max] = max;\n    this[_children] = [];\n  }\n  get isXFAObject() {\n    return false;\n  }\n  get isXFAObjectArray() {\n    return true;\n  }\n  push(child) {\n    const len = this[_children].length;\n    if (len <= this[_max]) {\n      this[_children].push(child);\n      return true;\n    }\n    warn(`XFA - node \"${child[$nodeName]}\" accepts no more than ${this[_max]} children`);\n    return false;\n  }\n  isEmpty() {\n    return this[_children].length === 0;\n  }\n  dump() {\n    return this[_children].length === 1 ? this[_children][0][$dump]() : this[_children].map(x => x[$dump]());\n  }\n  [$clone]() {\n    const clone = new XFAObjectArray(this[_max]);\n    clone[_children] = this[_children].map(c => c[$clone]());\n    return clone;\n  }\n  get children() {\n    return this[_children];\n  }\n  clear() {\n    this[_children].length = 0;\n  }\n}\nclass XFAAttribute {\n  constructor(node, name, value) {\n    this[_parent] = node;\n    this[$nodeName] = name;\n    this[$content] = value;\n    this[$consumed] = false;\n    this[$uid] = `attribute${uid++}`;\n  }\n  [$getParent]() {\n    return this[_parent];\n  }\n  [$isDataValue]() {\n    return true;\n  }\n  [$getDataValue]() {\n    return this[$content].trim();\n  }\n  [$setValue](value) {\n    value = value.value || \"\";\n    this[$content] = value.toString();\n  }\n  [$text]() {\n    return this[$content];\n  }\n  [$isDescendent](parent) {\n    return this[_parent] === parent || this[_parent][$isDescendent](parent);\n  }\n}\nclass XmlObject extends XFAObject {\n  constructor(nsId, name, attributes = {}) {\n    super(nsId, name);\n    this[$content] = \"\";\n    this[_dataValue] = null;\n    if (name !== \"#text\") {\n      const map = new Map();\n      this[_attributes] = map;\n      for (const [attrName, value] of Object.entries(attributes)) {\n        map.set(attrName, new XFAAttribute(this, attrName, value));\n      }\n      if (attributes.hasOwnProperty($nsAttributes)) {\n        const dataNode = attributes[$nsAttributes].xfa.dataNode;\n        if (dataNode !== undefined) {\n          if (dataNode === \"dataGroup\") {\n            this[_dataValue] = false;\n          } else if (dataNode === \"dataValue\") {\n            this[_dataValue] = true;\n          }\n        }\n      }\n    }\n    this[$consumed] = false;\n  }\n  [$toString](buf) {\n    const tagName = this[$nodeName];\n    if (tagName === \"#text\") {\n      buf.push(encodeToXmlString(this[$content]));\n      return;\n    }\n    const utf8TagName = utf8StringToString(tagName);\n    const prefix = this[$namespaceId] === NS_DATASETS ? \"xfa:\" : \"\";\n    buf.push(`<${prefix}${utf8TagName}`);\n    for (const [name, value] of this[_attributes].entries()) {\n      const utf8Name = utf8StringToString(name);\n      buf.push(` ${utf8Name}=\"${encodeToXmlString(value[$content])}\"`);\n    }\n    if (this[_dataValue] !== null) {\n      if (this[_dataValue]) {\n        buf.push(` xfa:dataNode=\"dataValue\"`);\n      } else {\n        buf.push(` xfa:dataNode=\"dataGroup\"`);\n      }\n    }\n    if (!this[$content] && this[_children].length === 0) {\n      buf.push(\"/>\");\n      return;\n    }\n    buf.push(\">\");\n    if (this[$content]) {\n      if (typeof this[$content] === \"string\") {\n        buf.push(encodeToXmlString(this[$content]));\n      } else {\n        this[$content][$toString](buf);\n      }\n    } else {\n      for (const child of this[_children]) {\n        child[$toString](buf);\n      }\n    }\n    buf.push(`</${prefix}${utf8TagName}>`);\n  }\n  [$onChild](child) {\n    if (this[$content]) {\n      const node = new XmlObject(this[$namespaceId], \"#text\");\n      this[$appendChild](node);\n      node[$content] = this[$content];\n      this[$content] = \"\";\n    }\n    this[$appendChild](child);\n    return true;\n  }\n  [$onText](str) {\n    this[$content] += str;\n  }\n  [$finalize]() {\n    if (this[$content] && this[_children].length > 0) {\n      const node = new XmlObject(this[$namespaceId], \"#text\");\n      this[$appendChild](node);\n      node[$content] = this[$content];\n      delete this[$content];\n    }\n  }\n  [$toHTML]() {\n    if (this[$nodeName] === \"#text\") {\n      return HTMLResult.success({\n        name: \"#text\",\n        value: this[$content]\n      });\n    }\n    return HTMLResult.EMPTY;\n  }\n  [$getChildren](name = null) {\n    if (!name) {\n      return this[_children];\n    }\n    return this[_children].filter(c => c[$nodeName] === name);\n  }\n  [$getAttributes]() {\n    return this[_attributes];\n  }\n  [$getChildrenByClass](name) {\n    const value = this[_attributes].get(name);\n    if (value !== undefined) {\n      return value;\n    }\n    return this[$getChildren](name);\n  }\n  *[$getChildrenByNameIt](name, allTransparent) {\n    const value = this[_attributes].get(name);\n    if (value) {\n      yield value;\n    }\n    for (const child of this[_children]) {\n      if (child[$nodeName] === name) {\n        yield child;\n      }\n      if (allTransparent) {\n        yield* child[$getChildrenByNameIt](name, allTransparent);\n      }\n    }\n  }\n  *[$getAttributeIt](name, skipConsumed) {\n    const value = this[_attributes].get(name);\n    if (value && (!skipConsumed || !value[$consumed])) {\n      yield value;\n    }\n    for (const child of this[_children]) {\n      yield* child[$getAttributeIt](name, skipConsumed);\n    }\n  }\n  *[$getRealChildrenByNameIt](name, allTransparent, skipConsumed) {\n    for (const child of this[_children]) {\n      if (child[$nodeName] === name && (!skipConsumed || !child[$consumed])) {\n        yield child;\n      }\n      if (allTransparent) {\n        yield* child[$getRealChildrenByNameIt](name, allTransparent, skipConsumed);\n      }\n    }\n  }\n  [$isDataValue]() {\n    if (this[_dataValue] === null) {\n      return this[_children].length === 0 || this[_children][0][$namespaceId] === NamespaceIds.xhtml.id;\n    }\n    return this[_dataValue];\n  }\n  [$getDataValue]() {\n    if (this[_dataValue] === null) {\n      if (this[_children].length === 0) {\n        return this[$content].trim();\n      }\n      if (this[_children][0][$namespaceId] === NamespaceIds.xhtml.id) {\n        return this[_children][0][$text]().trim();\n      }\n      return null;\n    }\n    return this[$content].trim();\n  }\n  [$setValue](value) {\n    value = value.value || \"\";\n    this[$content] = value.toString();\n  }\n  [$dump](hasNS = false) {\n    const dumped = Object.create(null);\n    if (hasNS) {\n      dumped.$ns = this[$namespaceId];\n    }\n    if (this[$content]) {\n      dumped.$content = this[$content];\n    }\n    dumped.$name = this[$nodeName];\n    dumped.children = [];\n    for (const child of this[_children]) {\n      dumped.children.push(child[$dump](hasNS));\n    }\n    dumped.attributes = Object.create(null);\n    for (const [name, value] of this[_attributes]) {\n      dumped.attributes[name] = value[$content];\n    }\n    return dumped;\n  }\n}\nclass ContentObject extends XFAObject {\n  constructor(nsId, name) {\n    super(nsId, name);\n    this[$content] = \"\";\n  }\n  [$onText](text) {\n    this[$content] += text;\n  }\n  [$finalize]() {}\n}\nclass OptionObject extends ContentObject {\n  constructor(nsId, name, options) {\n    super(nsId, name);\n    this[_options] = options;\n  }\n  [$finalize]() {\n    this[$content] = getKeyword({\n      data: this[$content],\n      defaultValue: this[_options][0],\n      validate: k => this[_options].includes(k)\n    });\n  }\n  [$clean](builder) {\n    super[$clean](builder);\n    delete this[_options];\n  }\n}\nclass StringObject extends ContentObject {\n  [$finalize]() {\n    this[$content] = this[$content].trim();\n  }\n}\nclass IntegerObject extends ContentObject {\n  constructor(nsId, name, defaultValue, validator) {\n    super(nsId, name);\n    this[_defaultValue] = defaultValue;\n    this[_validator] = validator;\n  }\n  [$finalize]() {\n    this[$content] = getInteger({\n      data: this[$content],\n      defaultValue: this[_defaultValue],\n      validate: this[_validator]\n    });\n  }\n  [$clean](builder) {\n    super[$clean](builder);\n    delete this[_defaultValue];\n    delete this[_validator];\n  }\n}\nclass Option01 extends IntegerObject {\n  constructor(nsId, name) {\n    super(nsId, name, 0, n => n === 1);\n  }\n}\nclass Option10 extends IntegerObject {\n  constructor(nsId, name) {\n    super(nsId, name, 1, n => n === 0);\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/xfa/html_utils.js\n\n\n\n\n\n\nfunction measureToString(m) {\n  if (typeof m === \"string\") {\n    return \"0px\";\n  }\n  return Number.isInteger(m) ? `${m}px` : `${m.toFixed(2)}px`;\n}\nconst converters = {\n  anchorType(node, style) {\n    const parent = node[$getSubformParent]();\n    if (!parent || parent.layout && parent.layout !== \"position\") {\n      return;\n    }\n    if (!(\"transform\" in style)) {\n      style.transform = \"\";\n    }\n    switch (node.anchorType) {\n      case \"bottomCenter\":\n        style.transform += \"translate(-50%, -100%)\";\n        break;\n      case \"bottomLeft\":\n        style.transform += \"translate(0,-100%)\";\n        break;\n      case \"bottomRight\":\n        style.transform += \"translate(-100%,-100%)\";\n        break;\n      case \"middleCenter\":\n        style.transform += \"translate(-50%,-50%)\";\n        break;\n      case \"middleLeft\":\n        style.transform += \"translate(0,-50%)\";\n        break;\n      case \"middleRight\":\n        style.transform += \"translate(-100%,-50%)\";\n        break;\n      case \"topCenter\":\n        style.transform += \"translate(-50%,0)\";\n        break;\n      case \"topRight\":\n        style.transform += \"translate(-100%,0)\";\n        break;\n    }\n  },\n  dimensions(node, style) {\n    const parent = node[$getSubformParent]();\n    let width = node.w;\n    const height = node.h;\n    if (parent.layout?.includes(\"row\")) {\n      const extra = parent[$extra];\n      const colSpan = node.colSpan;\n      let w;\n      if (colSpan === -1) {\n        w = extra.columnWidths.slice(extra.currentColumn).reduce((a, x) => a + x, 0);\n        extra.currentColumn = 0;\n      } else {\n        w = extra.columnWidths.slice(extra.currentColumn, extra.currentColumn + colSpan).reduce((a, x) => a + x, 0);\n        extra.currentColumn = (extra.currentColumn + node.colSpan) % extra.columnWidths.length;\n      }\n      if (!isNaN(w)) {\n        width = node.w = w;\n      }\n    }\n    style.width = width !== \"\" ? measureToString(width) : \"auto\";\n    style.height = height !== \"\" ? measureToString(height) : \"auto\";\n  },\n  position(node, style) {\n    const parent = node[$getSubformParent]();\n    if (parent?.layout && parent.layout !== \"position\") {\n      return;\n    }\n    style.position = \"absolute\";\n    style.left = measureToString(node.x);\n    style.top = measureToString(node.y);\n  },\n  rotate(node, style) {\n    if (node.rotate) {\n      if (!(\"transform\" in style)) {\n        style.transform = \"\";\n      }\n      style.transform += `rotate(-${node.rotate}deg)`;\n      style.transformOrigin = \"top left\";\n    }\n  },\n  presence(node, style) {\n    switch (node.presence) {\n      case \"invisible\":\n        style.visibility = \"hidden\";\n        break;\n      case \"hidden\":\n      case \"inactive\":\n        style.display = \"none\";\n        break;\n    }\n  },\n  hAlign(node, style) {\n    if (node[$nodeName] === \"para\") {\n      switch (node.hAlign) {\n        case \"justifyAll\":\n          style.textAlign = \"justify-all\";\n          break;\n        case \"radix\":\n          style.textAlign = \"left\";\n          break;\n        default:\n          style.textAlign = node.hAlign;\n      }\n    } else {\n      switch (node.hAlign) {\n        case \"left\":\n          style.alignSelf = \"start\";\n          break;\n        case \"center\":\n          style.alignSelf = \"center\";\n          break;\n        case \"right\":\n          style.alignSelf = \"end\";\n          break;\n      }\n    }\n  },\n  margin(node, style) {\n    if (node.margin) {\n      style.margin = node.margin[$toStyle]().margin;\n    }\n  }\n};\nfunction setMinMaxDimensions(node, style) {\n  const parent = node[$getSubformParent]();\n  if (parent.layout === \"position\") {\n    if (node.minW > 0) {\n      style.minWidth = measureToString(node.minW);\n    }\n    if (node.maxW > 0) {\n      style.maxWidth = measureToString(node.maxW);\n    }\n    if (node.minH > 0) {\n      style.minHeight = measureToString(node.minH);\n    }\n    if (node.maxH > 0) {\n      style.maxHeight = measureToString(node.maxH);\n    }\n  }\n}\nfunction layoutText(text, xfaFont, margin, lineHeight, fontFinder, width) {\n  const measure = new TextMeasure(xfaFont, margin, lineHeight, fontFinder);\n  if (typeof text === \"string\") {\n    measure.addString(text);\n  } else {\n    text[$pushGlyphs](measure);\n  }\n  return measure.compute(width);\n}\nfunction layoutNode(node, availableSpace) {\n  let height = null;\n  let width = null;\n  let isBroken = false;\n  if ((!node.w || !node.h) && node.value) {\n    let marginH = 0;\n    let marginV = 0;\n    if (node.margin) {\n      marginH = node.margin.leftInset + node.margin.rightInset;\n      marginV = node.margin.topInset + node.margin.bottomInset;\n    }\n    let lineHeight = null;\n    let margin = null;\n    if (node.para) {\n      margin = Object.create(null);\n      lineHeight = node.para.lineHeight === \"\" ? null : node.para.lineHeight;\n      margin.top = node.para.spaceAbove === \"\" ? 0 : node.para.spaceAbove;\n      margin.bottom = node.para.spaceBelow === \"\" ? 0 : node.para.spaceBelow;\n      margin.left = node.para.marginLeft === \"\" ? 0 : node.para.marginLeft;\n      margin.right = node.para.marginRight === \"\" ? 0 : node.para.marginRight;\n    }\n    let font = node.font;\n    if (!font) {\n      const root = node[$getTemplateRoot]();\n      let parent = node[$getParent]();\n      while (parent && parent !== root) {\n        if (parent.font) {\n          font = parent.font;\n          break;\n        }\n        parent = parent[$getParent]();\n      }\n    }\n    const maxWidth = (node.w || availableSpace.width) - marginH;\n    const fontFinder = node[$globalData].fontFinder;\n    if (node.value.exData && node.value.exData[$content] && node.value.exData.contentType === \"text/html\") {\n      const res = layoutText(node.value.exData[$content], font, margin, lineHeight, fontFinder, maxWidth);\n      width = res.width;\n      height = res.height;\n      isBroken = res.isBroken;\n    } else {\n      const text = node.value[$text]();\n      if (text) {\n        const res = layoutText(text, font, margin, lineHeight, fontFinder, maxWidth);\n        width = res.width;\n        height = res.height;\n        isBroken = res.isBroken;\n      }\n    }\n    if (width !== null && !node.w) {\n      width += marginH;\n    }\n    if (height !== null && !node.h) {\n      height += marginV;\n    }\n  }\n  return {\n    w: width,\n    h: height,\n    isBroken\n  };\n}\nfunction computeBbox(node, html, availableSpace) {\n  let bbox;\n  if (node.w !== \"\" && node.h !== \"\") {\n    bbox = [node.x, node.y, node.w, node.h];\n  } else {\n    if (!availableSpace) {\n      return null;\n    }\n    let width = node.w;\n    if (width === \"\") {\n      if (node.maxW === 0) {\n        const parent = node[$getSubformParent]();\n        width = parent.layout === \"position\" && parent.w !== \"\" ? 0 : node.minW;\n      } else {\n        width = Math.min(node.maxW, availableSpace.width);\n      }\n      html.attributes.style.width = measureToString(width);\n    }\n    let height = node.h;\n    if (height === \"\") {\n      if (node.maxH === 0) {\n        const parent = node[$getSubformParent]();\n        height = parent.layout === \"position\" && parent.h !== \"\" ? 0 : node.minH;\n      } else {\n        height = Math.min(node.maxH, availableSpace.height);\n      }\n      html.attributes.style.height = measureToString(height);\n    }\n    bbox = [node.x, node.y, width, height];\n  }\n  return bbox;\n}\nfunction fixDimensions(node) {\n  const parent = node[$getSubformParent]();\n  if (parent.layout?.includes(\"row\")) {\n    const extra = parent[$extra];\n    const colSpan = node.colSpan;\n    let width;\n    if (colSpan === -1) {\n      width = extra.columnWidths.slice(extra.currentColumn).reduce((a, w) => a + w, 0);\n    } else {\n      width = extra.columnWidths.slice(extra.currentColumn, extra.currentColumn + colSpan).reduce((a, w) => a + w, 0);\n    }\n    if (!isNaN(width)) {\n      node.w = width;\n    }\n  }\n  if (parent.layout && parent.layout !== \"position\") {\n    node.x = node.y = 0;\n  }\n  if (node.layout === \"table\") {\n    if (node.w === \"\" && Array.isArray(node.columnWidths)) {\n      node.w = node.columnWidths.reduce((a, x) => a + x, 0);\n    }\n  }\n}\nfunction layoutClass(node) {\n  switch (node.layout) {\n    case \"position\":\n      return \"xfaPosition\";\n    case \"lr-tb\":\n      return \"xfaLrTb\";\n    case \"rl-row\":\n      return \"xfaRlRow\";\n    case \"rl-tb\":\n      return \"xfaRlTb\";\n    case \"row\":\n      return \"xfaRow\";\n    case \"table\":\n      return \"xfaTable\";\n    case \"tb\":\n      return \"xfaTb\";\n    default:\n      return \"xfaPosition\";\n  }\n}\nfunction toStyle(node, ...names) {\n  const style = Object.create(null);\n  for (const name of names) {\n    const value = node[name];\n    if (value === null) {\n      continue;\n    }\n    if (converters.hasOwnProperty(name)) {\n      converters[name](node, style);\n      continue;\n    }\n    if (value instanceof XFAObject) {\n      const newStyle = value[$toStyle]();\n      if (newStyle) {\n        Object.assign(style, newStyle);\n      } else {\n        warn(`(DEBUG) - XFA - style for ${name} not implemented yet`);\n      }\n    }\n  }\n  return style;\n}\nfunction createWrapper(node, html) {\n  const {\n    attributes\n  } = html;\n  const {\n    style\n  } = attributes;\n  const wrapper = {\n    name: \"div\",\n    attributes: {\n      class: [\"xfaWrapper\"],\n      style: Object.create(null)\n    },\n    children: []\n  };\n  attributes.class.push(\"xfaWrapped\");\n  if (node.border) {\n    const {\n      widths,\n      insets\n    } = node.border[$extra];\n    let width, height;\n    let top = insets[0];\n    let left = insets[3];\n    const insetsH = insets[0] + insets[2];\n    const insetsW = insets[1] + insets[3];\n    switch (node.border.hand) {\n      case \"even\":\n        top -= widths[0] / 2;\n        left -= widths[3] / 2;\n        width = `calc(100% + ${(widths[1] + widths[3]) / 2 - insetsW}px)`;\n        height = `calc(100% + ${(widths[0] + widths[2]) / 2 - insetsH}px)`;\n        break;\n      case \"left\":\n        top -= widths[0];\n        left -= widths[3];\n        width = `calc(100% + ${widths[1] + widths[3] - insetsW}px)`;\n        height = `calc(100% + ${widths[0] + widths[2] - insetsH}px)`;\n        break;\n      case \"right\":\n        width = insetsW ? `calc(100% - ${insetsW}px)` : \"100%\";\n        height = insetsH ? `calc(100% - ${insetsH}px)` : \"100%\";\n        break;\n    }\n    const classNames = [\"xfaBorder\"];\n    if (isPrintOnly(node.border)) {\n      classNames.push(\"xfaPrintOnly\");\n    }\n    const border = {\n      name: \"div\",\n      attributes: {\n        class: classNames,\n        style: {\n          top: `${top}px`,\n          left: `${left}px`,\n          width,\n          height\n        }\n      },\n      children: []\n    };\n    for (const key of [\"border\", \"borderWidth\", \"borderColor\", \"borderRadius\", \"borderStyle\"]) {\n      if (style[key] !== undefined) {\n        border.attributes.style[key] = style[key];\n        delete style[key];\n      }\n    }\n    wrapper.children.push(border, html);\n  } else {\n    wrapper.children.push(html);\n  }\n  for (const key of [\"background\", \"backgroundClip\", \"top\", \"left\", \"width\", \"height\", \"minWidth\", \"minHeight\", \"maxWidth\", \"maxHeight\", \"transform\", \"transformOrigin\", \"visibility\"]) {\n    if (style[key] !== undefined) {\n      wrapper.attributes.style[key] = style[key];\n      delete style[key];\n    }\n  }\n  wrapper.attributes.style.position = style.position === \"absolute\" ? \"absolute\" : \"relative\";\n  delete style.position;\n  if (style.alignSelf) {\n    wrapper.attributes.style.alignSelf = style.alignSelf;\n    delete style.alignSelf;\n  }\n  return wrapper;\n}\nfunction fixTextIndent(styles) {\n  const indent = getMeasurement(styles.textIndent, \"0px\");\n  if (indent >= 0) {\n    return;\n  }\n  const align = styles.textAlign === \"right\" ? \"right\" : \"left\";\n  const name = \"padding\" + (align === \"left\" ? \"Left\" : \"Right\");\n  const padding = getMeasurement(styles[name], \"0px\");\n  styles[name] = `${padding - indent}px`;\n}\nfunction setAccess(node, classNames) {\n  switch (node.access) {\n    case \"nonInteractive\":\n      classNames.push(\"xfaNonInteractive\");\n      break;\n    case \"readOnly\":\n      classNames.push(\"xfaReadOnly\");\n      break;\n    case \"protected\":\n      classNames.push(\"xfaDisabled\");\n      break;\n  }\n}\nfunction isPrintOnly(node) {\n  return node.relevant.length > 0 && !node.relevant[0].excluded && node.relevant[0].viewname === \"print\";\n}\nfunction getCurrentPara(node) {\n  const stack = node[$getTemplateRoot]()[$extra].paraStack;\n  return stack.length ? stack.at(-1) : null;\n}\nfunction setPara(node, nodeStyle, value) {\n  if (value.attributes.class?.includes(\"xfaRich\")) {\n    if (nodeStyle) {\n      if (node.h === \"\") {\n        nodeStyle.height = \"auto\";\n      }\n      if (node.w === \"\") {\n        nodeStyle.width = \"auto\";\n      }\n    }\n    const para = getCurrentPara(node);\n    if (para) {\n      const valueStyle = value.attributes.style;\n      valueStyle.display = \"flex\";\n      valueStyle.flexDirection = \"column\";\n      switch (para.vAlign) {\n        case \"top\":\n          valueStyle.justifyContent = \"start\";\n          break;\n        case \"bottom\":\n          valueStyle.justifyContent = \"end\";\n          break;\n        case \"middle\":\n          valueStyle.justifyContent = \"center\";\n          break;\n      }\n      const paraStyle = para[$toStyle]();\n      for (const [key, val] of Object.entries(paraStyle)) {\n        if (!(key in valueStyle)) {\n          valueStyle[key] = val;\n        }\n      }\n    }\n  }\n}\nfunction setFontFamily(xfaFont, node, fontFinder, style) {\n  if (!fontFinder) {\n    delete style.fontFamily;\n    return;\n  }\n  const name = stripQuotes(xfaFont.typeface);\n  style.fontFamily = `\"${name}\"`;\n  const typeface = fontFinder.find(name);\n  if (typeface) {\n    const {\n      fontFamily\n    } = typeface.regular.cssFontInfo;\n    if (fontFamily !== name) {\n      style.fontFamily = `\"${fontFamily}\"`;\n    }\n    const para = getCurrentPara(node);\n    if (para && para.lineHeight !== \"\") {\n      return;\n    }\n    if (style.lineHeight) {\n      return;\n    }\n    const pdfFont = selectFont(xfaFont, typeface);\n    if (pdfFont) {\n      style.lineHeight = Math.max(1.2, pdfFont.lineHeight);\n    }\n  }\n}\nfunction fixURL(str) {\n  const absoluteUrl = createValidAbsoluteUrl(str, null, {\n    addDefaultProtocol: true,\n    tryConvertEncoding: true\n  });\n  return absoluteUrl ? absoluteUrl.href : null;\n}\n\n;// CONCATENATED MODULE: ./src/core/xfa/layout.js\n\n\nfunction createLine(node, children) {\n  return {\n    name: \"div\",\n    attributes: {\n      class: [node.layout === \"lr-tb\" ? \"xfaLr\" : \"xfaRl\"]\n    },\n    children\n  };\n}\nfunction flushHTML(node) {\n  if (!node[$extra]) {\n    return null;\n  }\n  const attributes = node[$extra].attributes;\n  const html = {\n    name: \"div\",\n    attributes,\n    children: node[$extra].children\n  };\n  if (node[$extra].failingNode) {\n    const htmlFromFailing = node[$extra].failingNode[$flushHTML]();\n    if (htmlFromFailing) {\n      if (node.layout.endsWith(\"-tb\")) {\n        html.children.push(createLine(node, [htmlFromFailing]));\n      } else {\n        html.children.push(htmlFromFailing);\n      }\n    }\n  }\n  if (html.children.length === 0) {\n    return null;\n  }\n  return html;\n}\nfunction addHTML(node, html, bbox) {\n  const extra = node[$extra];\n  const availableSpace = extra.availableSpace;\n  const [x, y, w, h] = bbox;\n  switch (node.layout) {\n    case \"position\":\n      {\n        extra.width = Math.max(extra.width, x + w);\n        extra.height = Math.max(extra.height, y + h);\n        extra.children.push(html);\n        break;\n      }\n    case \"lr-tb\":\n    case \"rl-tb\":\n      if (!extra.line || extra.attempt === 1) {\n        extra.line = createLine(node, []);\n        extra.children.push(extra.line);\n        extra.numberInLine = 0;\n      }\n      extra.numberInLine += 1;\n      extra.line.children.push(html);\n      if (extra.attempt === 0) {\n        extra.currentWidth += w;\n        extra.height = Math.max(extra.height, extra.prevHeight + h);\n      } else {\n        extra.currentWidth = w;\n        extra.prevHeight = extra.height;\n        extra.height += h;\n        extra.attempt = 0;\n      }\n      extra.width = Math.max(extra.width, extra.currentWidth);\n      break;\n    case \"rl-row\":\n    case \"row\":\n      {\n        extra.children.push(html);\n        extra.width += w;\n        extra.height = Math.max(extra.height, h);\n        const height = measureToString(extra.height);\n        for (const child of extra.children) {\n          child.attributes.style.height = height;\n        }\n        break;\n      }\n    case \"table\":\n      {\n        extra.width = Math.min(availableSpace.width, Math.max(extra.width, w));\n        extra.height += h;\n        extra.children.push(html);\n        break;\n      }\n    case \"tb\":\n      {\n        extra.width = Math.min(availableSpace.width, Math.max(extra.width, w));\n        extra.height += h;\n        extra.children.push(html);\n        break;\n      }\n  }\n}\nfunction getAvailableSpace(node) {\n  const availableSpace = node[$extra].availableSpace;\n  const marginV = node.margin ? node.margin.topInset + node.margin.bottomInset : 0;\n  const marginH = node.margin ? node.margin.leftInset + node.margin.rightInset : 0;\n  switch (node.layout) {\n    case \"lr-tb\":\n    case \"rl-tb\":\n      if (node[$extra].attempt === 0) {\n        return {\n          width: availableSpace.width - marginH - node[$extra].currentWidth,\n          height: availableSpace.height - marginV - node[$extra].prevHeight\n        };\n      }\n      return {\n        width: availableSpace.width - marginH,\n        height: availableSpace.height - marginV - node[$extra].height\n      };\n    case \"rl-row\":\n    case \"row\":\n      const width = node[$extra].columnWidths.slice(node[$extra].currentColumn).reduce((a, x) => a + x);\n      return {\n        width,\n        height: availableSpace.height - marginH\n      };\n    case \"table\":\n    case \"tb\":\n      return {\n        width: availableSpace.width - marginH,\n        height: availableSpace.height - marginV - node[$extra].height\n      };\n    case \"position\":\n    default:\n      return availableSpace;\n  }\n}\nfunction getTransformedBBox(node) {\n  let w = node.w === \"\" ? NaN : node.w;\n  let h = node.h === \"\" ? NaN : node.h;\n  let [centerX, centerY] = [0, 0];\n  switch (node.anchorType || \"\") {\n    case \"bottomCenter\":\n      [centerX, centerY] = [w / 2, h];\n      break;\n    case \"bottomLeft\":\n      [centerX, centerY] = [0, h];\n      break;\n    case \"bottomRight\":\n      [centerX, centerY] = [w, h];\n      break;\n    case \"middleCenter\":\n      [centerX, centerY] = [w / 2, h / 2];\n      break;\n    case \"middleLeft\":\n      [centerX, centerY] = [0, h / 2];\n      break;\n    case \"middleRight\":\n      [centerX, centerY] = [w, h / 2];\n      break;\n    case \"topCenter\":\n      [centerX, centerY] = [w / 2, 0];\n      break;\n    case \"topRight\":\n      [centerX, centerY] = [w, 0];\n      break;\n  }\n  let x, y;\n  switch (node.rotate || 0) {\n    case 0:\n      [x, y] = [-centerX, -centerY];\n      break;\n    case 90:\n      [x, y] = [-centerY, centerX];\n      [w, h] = [h, -w];\n      break;\n    case 180:\n      [x, y] = [centerX, centerY];\n      [w, h] = [-w, -h];\n      break;\n    case 270:\n      [x, y] = [centerY, -centerX];\n      [w, h] = [-h, w];\n      break;\n  }\n  return [node.x + x + Math.min(0, w), node.y + y + Math.min(0, h), Math.abs(w), Math.abs(h)];\n}\nfunction checkDimensions(node, space) {\n  if (node[$getTemplateRoot]()[$extra].firstUnsplittable === null) {\n    return true;\n  }\n  if (node.w === 0 || node.h === 0) {\n    return true;\n  }\n  const ERROR = 2;\n  const parent = node[$getSubformParent]();\n  const attempt = parent[$extra]?.attempt || 0;\n  const [, y, w, h] = getTransformedBBox(node);\n  switch (parent.layout) {\n    case \"lr-tb\":\n    case \"rl-tb\":\n      if (attempt === 0) {\n        if (!node[$getTemplateRoot]()[$extra].noLayoutFailure) {\n          if (node.h !== \"\" && Math.round(h - space.height) > ERROR) {\n            return false;\n          }\n          if (node.w !== \"\") {\n            if (Math.round(w - space.width) <= ERROR) {\n              return true;\n            }\n            if (parent[$extra].numberInLine === 0) {\n              return space.height > ERROR;\n            }\n            return false;\n          }\n          return space.width > ERROR;\n        }\n        if (node.w !== \"\") {\n          return Math.round(w - space.width) <= ERROR;\n        }\n        return space.width > ERROR;\n      }\n      if (node[$getTemplateRoot]()[$extra].noLayoutFailure) {\n        return true;\n      }\n      if (node.h !== \"\" && Math.round(h - space.height) > ERROR) {\n        return false;\n      }\n      if (node.w === \"\" || Math.round(w - space.width) <= ERROR) {\n        return space.height > ERROR;\n      }\n      if (parent[$isThereMoreWidth]()) {\n        return false;\n      }\n      return space.height > ERROR;\n    case \"table\":\n    case \"tb\":\n      if (node[$getTemplateRoot]()[$extra].noLayoutFailure) {\n        return true;\n      }\n      if (node.h !== \"\" && !node[$isSplittable]()) {\n        return Math.round(h - space.height) <= ERROR;\n      }\n      if (node.w === \"\" || Math.round(w - space.width) <= ERROR) {\n        return space.height > ERROR;\n      }\n      if (parent[$isThereMoreWidth]()) {\n        return false;\n      }\n      return space.height > ERROR;\n    case \"position\":\n      if (node[$getTemplateRoot]()[$extra].noLayoutFailure) {\n        return true;\n      }\n      if (node.h === \"\" || Math.round(h + y - space.height) <= ERROR) {\n        return true;\n      }\n      const area = node[$getTemplateRoot]()[$extra].currentContentArea;\n      return h + y > area.h;\n    case \"rl-row\":\n    case \"row\":\n      if (node[$getTemplateRoot]()[$extra].noLayoutFailure) {\n        return true;\n      }\n      if (node.h !== \"\") {\n        return Math.round(h - space.height) <= ERROR;\n      }\n      return true;\n    default:\n      return true;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/xfa/template.js\n\n\n\n\n\n\n\n\n\n\nconst TEMPLATE_NS_ID = NamespaceIds.template.id;\nconst SVG_NS = \"http://www.w3.org/2000/svg\";\nconst MAX_ATTEMPTS_FOR_LRTB_LAYOUT = 2;\nconst MAX_EMPTY_PAGES = 3;\nconst DEFAULT_TAB_INDEX = 5000;\nconst HEADING_PATTERN = /^H(\\d+)$/;\nconst MIMES = new Set([\"image/gif\", \"image/jpeg\", \"image/jpg\", \"image/pjpeg\", \"image/png\", \"image/apng\", \"image/x-png\", \"image/bmp\", \"image/x-ms-bmp\", \"image/tiff\", \"image/tif\", \"application/octet-stream\"]);\nconst IMAGES_HEADERS = [[[0x42, 0x4d], \"image/bmp\"], [[0xff, 0xd8, 0xff], \"image/jpeg\"], [[0x49, 0x49, 0x2a, 0x00], \"image/tiff\"], [[0x4d, 0x4d, 0x00, 0x2a], \"image/tiff\"], [[0x47, 0x49, 0x46, 0x38, 0x39, 0x61], \"image/gif\"], [[0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a], \"image/png\"]];\nfunction getBorderDims(node) {\n  if (!node || !node.border) {\n    return {\n      w: 0,\n      h: 0\n    };\n  }\n  const borderExtra = node.border[$getExtra]();\n  if (!borderExtra) {\n    return {\n      w: 0,\n      h: 0\n    };\n  }\n  return {\n    w: borderExtra.widths[0] + borderExtra.widths[2] + borderExtra.insets[0] + borderExtra.insets[2],\n    h: borderExtra.widths[1] + borderExtra.widths[3] + borderExtra.insets[1] + borderExtra.insets[3]\n  };\n}\nfunction hasMargin(node) {\n  return node.margin && (node.margin.topInset || node.margin.rightInset || node.margin.bottomInset || node.margin.leftInset);\n}\nfunction _setValue(templateNode, value) {\n  if (!templateNode.value) {\n    const nodeValue = new Value({});\n    templateNode[$appendChild](nodeValue);\n    templateNode.value = nodeValue;\n  }\n  templateNode.value[$setValue](value);\n}\nfunction* getContainedChildren(node) {\n  for (const child of node[$getChildren]()) {\n    if (child instanceof SubformSet) {\n      yield* child[$getContainedChildren]();\n      continue;\n    }\n    yield child;\n  }\n}\nfunction isRequired(node) {\n  return node.validate?.nullTest === \"error\";\n}\nfunction setTabIndex(node) {\n  while (node) {\n    if (!node.traversal) {\n      node[$tabIndex] = node[$getParent]()[$tabIndex];\n      return;\n    }\n    if (node[$tabIndex]) {\n      return;\n    }\n    let next = null;\n    for (const child of node.traversal[$getChildren]()) {\n      if (child.operation === \"next\") {\n        next = child;\n        break;\n      }\n    }\n    if (!next || !next.ref) {\n      node[$tabIndex] = node[$getParent]()[$tabIndex];\n      return;\n    }\n    const root = node[$getTemplateRoot]();\n    node[$tabIndex] = ++root[$tabIndex];\n    const ref = root[$searchNode](next.ref, node);\n    if (!ref) {\n      return;\n    }\n    node = ref[0];\n  }\n}\nfunction applyAssist(obj, attributes) {\n  const assist = obj.assist;\n  if (assist) {\n    const assistTitle = assist[$toHTML]();\n    if (assistTitle) {\n      attributes.title = assistTitle;\n    }\n    const role = assist.role;\n    const match = role.match(HEADING_PATTERN);\n    if (match) {\n      const ariaRole = \"heading\";\n      const ariaLevel = match[1];\n      attributes.role = ariaRole;\n      attributes[\"aria-level\"] = ariaLevel;\n    }\n  }\n  if (obj.layout === \"table\") {\n    attributes.role = \"table\";\n  } else if (obj.layout === \"row\") {\n    attributes.role = \"row\";\n  } else {\n    const parent = obj[$getParent]();\n    if (parent.layout === \"row\") {\n      attributes.role = parent.assist?.role === \"TH\" ? \"columnheader\" : \"cell\";\n    }\n  }\n}\nfunction ariaLabel(obj) {\n  if (!obj.assist) {\n    return null;\n  }\n  const assist = obj.assist;\n  if (assist.speak && assist.speak[$content] !== \"\") {\n    return assist.speak[$content];\n  }\n  if (assist.toolTip) {\n    return assist.toolTip[$content];\n  }\n  return null;\n}\nfunction valueToHtml(value) {\n  return HTMLResult.success({\n    name: \"div\",\n    attributes: {\n      class: [\"xfaRich\"],\n      style: Object.create(null)\n    },\n    children: [{\n      name: \"span\",\n      attributes: {\n        style: Object.create(null)\n      },\n      value\n    }]\n  });\n}\nfunction setFirstUnsplittable(node) {\n  const root = node[$getTemplateRoot]();\n  if (root[$extra].firstUnsplittable === null) {\n    root[$extra].firstUnsplittable = node;\n    root[$extra].noLayoutFailure = true;\n  }\n}\nfunction unsetFirstUnsplittable(node) {\n  const root = node[$getTemplateRoot]();\n  if (root[$extra].firstUnsplittable === node) {\n    root[$extra].noLayoutFailure = false;\n  }\n}\nfunction handleBreak(node) {\n  if (node[$extra]) {\n    return false;\n  }\n  node[$extra] = Object.create(null);\n  if (node.targetType === \"auto\") {\n    return false;\n  }\n  const root = node[$getTemplateRoot]();\n  let target = null;\n  if (node.target) {\n    target = root[$searchNode](node.target, node[$getParent]());\n    if (!target) {\n      return false;\n    }\n    target = target[0];\n  }\n  const {\n    currentPageArea,\n    currentContentArea\n  } = root[$extra];\n  if (node.targetType === \"pageArea\") {\n    if (!(target instanceof PageArea)) {\n      target = null;\n    }\n    if (node.startNew) {\n      node[$extra].target = target || currentPageArea;\n      return true;\n    } else if (target && target !== currentPageArea) {\n      node[$extra].target = target;\n      return true;\n    }\n    return false;\n  }\n  if (!(target instanceof ContentArea)) {\n    target = null;\n  }\n  const pageArea = target && target[$getParent]();\n  let index;\n  let nextPageArea = pageArea;\n  if (node.startNew) {\n    if (target) {\n      const contentAreas = pageArea.contentArea.children;\n      const indexForCurrent = contentAreas.indexOf(currentContentArea);\n      const indexForTarget = contentAreas.indexOf(target);\n      if (indexForCurrent !== -1 && indexForCurrent < indexForTarget) {\n        nextPageArea = null;\n      }\n      index = indexForTarget - 1;\n    } else {\n      index = currentPageArea.contentArea.children.indexOf(currentContentArea);\n    }\n  } else if (target && target !== currentContentArea) {\n    const contentAreas = pageArea.contentArea.children;\n    index = contentAreas.indexOf(target) - 1;\n    nextPageArea = pageArea === currentPageArea ? null : pageArea;\n  } else {\n    return false;\n  }\n  node[$extra].target = nextPageArea;\n  node[$extra].index = index;\n  return true;\n}\nfunction handleOverflow(node, extraNode, space) {\n  const root = node[$getTemplateRoot]();\n  const saved = root[$extra].noLayoutFailure;\n  const savedMethod = extraNode[$getSubformParent];\n  extraNode[$getSubformParent] = () => node;\n  root[$extra].noLayoutFailure = true;\n  const res = extraNode[$toHTML](space);\n  node[$addHTML](res.html, res.bbox);\n  root[$extra].noLayoutFailure = saved;\n  extraNode[$getSubformParent] = savedMethod;\n}\nclass AppearanceFilter extends StringObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"appearanceFilter\");\n    this.id = attributes.id || \"\";\n    this.type = getStringOption(attributes.type, [\"optional\", \"required\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass Arc extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"arc\", true);\n    this.circular = getInteger({\n      data: attributes.circular,\n      defaultValue: 0,\n      validate: x => x === 1\n    });\n    this.hand = getStringOption(attributes.hand, [\"even\", \"left\", \"right\"]);\n    this.id = attributes.id || \"\";\n    this.startAngle = getFloat({\n      data: attributes.startAngle,\n      defaultValue: 0,\n      validate: x => true\n    });\n    this.sweepAngle = getFloat({\n      data: attributes.sweepAngle,\n      defaultValue: 360,\n      validate: x => true\n    });\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.edge = null;\n    this.fill = null;\n  }\n  [$toHTML]() {\n    const edge = this.edge || new Edge({});\n    const edgeStyle = edge[$toStyle]();\n    const style = Object.create(null);\n    if (this.fill?.presence === \"visible\") {\n      Object.assign(style, this.fill[$toStyle]());\n    } else {\n      style.fill = \"transparent\";\n    }\n    style.strokeWidth = measureToString(edge.presence === \"visible\" ? edge.thickness : 0);\n    style.stroke = edgeStyle.color;\n    let arc;\n    const attributes = {\n      xmlns: SVG_NS,\n      style: {\n        width: \"100%\",\n        height: \"100%\",\n        overflow: \"visible\"\n      }\n    };\n    if (this.sweepAngle === 360) {\n      arc = {\n        name: \"ellipse\",\n        attributes: {\n          xmlns: SVG_NS,\n          cx: \"50%\",\n          cy: \"50%\",\n          rx: \"50%\",\n          ry: \"50%\",\n          style\n        }\n      };\n    } else {\n      const startAngle = this.startAngle * Math.PI / 180;\n      const sweepAngle = this.sweepAngle * Math.PI / 180;\n      const largeArc = this.sweepAngle > 180 ? 1 : 0;\n      const [x1, y1, x2, y2] = [50 * (1 + Math.cos(startAngle)), 50 * (1 - Math.sin(startAngle)), 50 * (1 + Math.cos(startAngle + sweepAngle)), 50 * (1 - Math.sin(startAngle + sweepAngle))];\n      arc = {\n        name: \"path\",\n        attributes: {\n          xmlns: SVG_NS,\n          d: `M ${x1} ${y1} A 50 50 0 ${largeArc} 0 ${x2} ${y2}`,\n          vectorEffect: \"non-scaling-stroke\",\n          style\n        }\n      };\n      Object.assign(attributes, {\n        viewBox: \"0 0 100 100\",\n        preserveAspectRatio: \"none\"\n      });\n    }\n    const svg = {\n      name: \"svg\",\n      children: [arc],\n      attributes\n    };\n    const parent = this[$getParent]()[$getParent]();\n    if (hasMargin(parent)) {\n      return HTMLResult.success({\n        name: \"div\",\n        attributes: {\n          style: {\n            display: \"inline\",\n            width: \"100%\",\n            height: \"100%\"\n          }\n        },\n        children: [svg]\n      });\n    }\n    svg.attributes.style.position = \"absolute\";\n    return HTMLResult.success(svg);\n  }\n}\nclass Area extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"area\", true);\n    this.colSpan = getInteger({\n      data: attributes.colSpan,\n      defaultValue: 1,\n      validate: n => n >= 1 || n === -1\n    });\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.relevant = getRelevant(attributes.relevant);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.x = getMeasurement(attributes.x, \"0pt\");\n    this.y = getMeasurement(attributes.y, \"0pt\");\n    this.desc = null;\n    this.extras = null;\n    this.area = new XFAObjectArray();\n    this.draw = new XFAObjectArray();\n    this.exObject = new XFAObjectArray();\n    this.exclGroup = new XFAObjectArray();\n    this.field = new XFAObjectArray();\n    this.subform = new XFAObjectArray();\n    this.subformSet = new XFAObjectArray();\n  }\n  *[$getContainedChildren]() {\n    yield* getContainedChildren(this);\n  }\n  [$isTransparent]() {\n    return true;\n  }\n  [$isBindable]() {\n    return true;\n  }\n  [$addHTML](html, bbox) {\n    const [x, y, w, h] = bbox;\n    this[$extra].width = Math.max(this[$extra].width, x + w);\n    this[$extra].height = Math.max(this[$extra].height, y + h);\n    this[$extra].children.push(html);\n  }\n  [$getAvailableSpace]() {\n    return this[$extra].availableSpace;\n  }\n  [$toHTML](availableSpace) {\n    const style = toStyle(this, \"position\");\n    const attributes = {\n      style,\n      id: this[$uid],\n      class: [\"xfaArea\"]\n    };\n    if (isPrintOnly(this)) {\n      attributes.class.push(\"xfaPrintOnly\");\n    }\n    if (this.name) {\n      attributes.xfaName = this.name;\n    }\n    const children = [];\n    this[$extra] = {\n      children,\n      width: 0,\n      height: 0,\n      availableSpace\n    };\n    const result = this[$childrenToHTML]({\n      filter: new Set([\"area\", \"draw\", \"field\", \"exclGroup\", \"subform\", \"subformSet\"]),\n      include: true\n    });\n    if (!result.success) {\n      if (result.isBreak()) {\n        return result;\n      }\n      delete this[$extra];\n      return HTMLResult.FAILURE;\n    }\n    style.width = measureToString(this[$extra].width);\n    style.height = measureToString(this[$extra].height);\n    const html = {\n      name: \"div\",\n      attributes,\n      children\n    };\n    const bbox = [this.x, this.y, this[$extra].width, this[$extra].height];\n    delete this[$extra];\n    return HTMLResult.success(html, bbox);\n  }\n}\nclass Assist extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"assist\", true);\n    this.id = attributes.id || \"\";\n    this.role = attributes.role || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.speak = null;\n    this.toolTip = null;\n  }\n  [$toHTML]() {\n    return this.toolTip?.[$content] || null;\n  }\n}\nclass Barcode extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"barcode\", true);\n    this.charEncoding = getKeyword({\n      data: attributes.charEncoding ? attributes.charEncoding.toLowerCase() : \"\",\n      defaultValue: \"\",\n      validate: k => [\"utf-8\", \"big-five\", \"fontspecific\", \"gbk\", \"gb-18030\", \"gb-2312\", \"ksc-5601\", \"none\", \"shift-jis\", \"ucs-2\", \"utf-16\"].includes(k) || k.match(/iso-8859-\\d{2}/)\n    });\n    this.checksum = getStringOption(attributes.checksum, [\"none\", \"1mod10\", \"1mod10_1mod11\", \"2mod10\", \"auto\"]);\n    this.dataColumnCount = getInteger({\n      data: attributes.dataColumnCount,\n      defaultValue: -1,\n      validate: x => x >= 0\n    });\n    this.dataLength = getInteger({\n      data: attributes.dataLength,\n      defaultValue: -1,\n      validate: x => x >= 0\n    });\n    this.dataPrep = getStringOption(attributes.dataPrep, [\"none\", \"flateCompress\"]);\n    this.dataRowCount = getInteger({\n      data: attributes.dataRowCount,\n      defaultValue: -1,\n      validate: x => x >= 0\n    });\n    this.endChar = attributes.endChar || \"\";\n    this.errorCorrectionLevel = getInteger({\n      data: attributes.errorCorrectionLevel,\n      defaultValue: -1,\n      validate: x => x >= 0 && x <= 8\n    });\n    this.id = attributes.id || \"\";\n    this.moduleHeight = getMeasurement(attributes.moduleHeight, \"5mm\");\n    this.moduleWidth = getMeasurement(attributes.moduleWidth, \"0.25mm\");\n    this.printCheckDigit = getInteger({\n      data: attributes.printCheckDigit,\n      defaultValue: 0,\n      validate: x => x === 1\n    });\n    this.rowColumnRatio = getRatio(attributes.rowColumnRatio);\n    this.startChar = attributes.startChar || \"\";\n    this.textLocation = getStringOption(attributes.textLocation, [\"below\", \"above\", \"aboveEmbedded\", \"belowEmbedded\", \"none\"]);\n    this.truncate = getInteger({\n      data: attributes.truncate,\n      defaultValue: 0,\n      validate: x => x === 1\n    });\n    this.type = getStringOption(attributes.type ? attributes.type.toLowerCase() : \"\", [\"aztec\", \"codabar\", \"code2of5industrial\", \"code2of5interleaved\", \"code2of5matrix\", \"code2of5standard\", \"code3of9\", \"code3of9extended\", \"code11\", \"code49\", \"code93\", \"code128\", \"code128a\", \"code128b\", \"code128c\", \"code128sscc\", \"datamatrix\", \"ean8\", \"ean8add2\", \"ean8add5\", \"ean13\", \"ean13add2\", \"ean13add5\", \"ean13pwcd\", \"fim\", \"logmars\", \"maxicode\", \"msi\", \"pdf417\", \"pdf417macro\", \"plessey\", \"postauscust2\", \"postauscust3\", \"postausreplypaid\", \"postausstandard\", \"postukrm4scc\", \"postusdpbc\", \"postusimb\", \"postusstandard\", \"postus5zip\", \"qrcode\", \"rfid\", \"rss14\", \"rss14expanded\", \"rss14limited\", \"rss14stacked\", \"rss14stackedomni\", \"rss14truncated\", \"telepen\", \"ucc128\", \"ucc128random\", \"ucc128sscc\", \"upca\", \"upcaadd2\", \"upcaadd5\", \"upcapwcd\", \"upce\", \"upceadd2\", \"upceadd5\", \"upcean2\", \"upcean5\", \"upsmaxicode\"]);\n    this.upsMode = getStringOption(attributes.upsMode, [\"usCarrier\", \"internationalCarrier\", \"secureSymbol\", \"standardSymbol\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.wideNarrowRatio = getRatio(attributes.wideNarrowRatio);\n    this.encrypt = null;\n    this.extras = null;\n  }\n}\nclass Bind extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"bind\", true);\n    this.match = getStringOption(attributes.match, [\"once\", \"dataRef\", \"global\", \"none\"]);\n    this.ref = attributes.ref || \"\";\n    this.picture = null;\n  }\n}\nclass BindItems extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"bindItems\");\n    this.connection = attributes.connection || \"\";\n    this.labelRef = attributes.labelRef || \"\";\n    this.ref = attributes.ref || \"\";\n    this.valueRef = attributes.valueRef || \"\";\n  }\n}\nclass Bookend extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"bookend\");\n    this.id = attributes.id || \"\";\n    this.leader = attributes.leader || \"\";\n    this.trailer = attributes.trailer || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass BooleanElement extends Option01 {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"boolean\");\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n  [$toHTML](availableSpace) {\n    return valueToHtml(this[$content] === 1 ? \"1\" : \"0\");\n  }\n}\nclass Border extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"border\", true);\n    this.break = getStringOption(attributes.break, [\"close\", \"open\"]);\n    this.hand = getStringOption(attributes.hand, [\"even\", \"left\", \"right\"]);\n    this.id = attributes.id || \"\";\n    this.presence = getStringOption(attributes.presence, [\"visible\", \"hidden\", \"inactive\", \"invisible\"]);\n    this.relevant = getRelevant(attributes.relevant);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.corner = new XFAObjectArray(4);\n    this.edge = new XFAObjectArray(4);\n    this.extras = null;\n    this.fill = null;\n    this.margin = null;\n  }\n  [$getExtra]() {\n    if (!this[$extra]) {\n      const edges = this.edge.children.slice();\n      if (edges.length < 4) {\n        const defaultEdge = edges.at(-1) || new Edge({});\n        for (let i = edges.length; i < 4; i++) {\n          edges.push(defaultEdge);\n        }\n      }\n      const widths = edges.map(edge => edge.thickness);\n      const insets = [0, 0, 0, 0];\n      if (this.margin) {\n        insets[0] = this.margin.topInset;\n        insets[1] = this.margin.rightInset;\n        insets[2] = this.margin.bottomInset;\n        insets[3] = this.margin.leftInset;\n      }\n      this[$extra] = {\n        widths,\n        insets,\n        edges\n      };\n    }\n    return this[$extra];\n  }\n  [$toStyle]() {\n    const {\n      edges\n    } = this[$getExtra]();\n    const edgeStyles = edges.map(node => {\n      const style = node[$toStyle]();\n      style.color ||= \"#000000\";\n      return style;\n    });\n    const style = Object.create(null);\n    if (this.margin) {\n      Object.assign(style, this.margin[$toStyle]());\n    }\n    if (this.fill?.presence === \"visible\") {\n      Object.assign(style, this.fill[$toStyle]());\n    }\n    if (this.corner.children.some(node => node.radius !== 0)) {\n      const cornerStyles = this.corner.children.map(node => node[$toStyle]());\n      if (cornerStyles.length === 2 || cornerStyles.length === 3) {\n        const last = cornerStyles.at(-1);\n        for (let i = cornerStyles.length; i < 4; i++) {\n          cornerStyles.push(last);\n        }\n      }\n      style.borderRadius = cornerStyles.map(s => s.radius).join(\" \");\n    }\n    switch (this.presence) {\n      case \"invisible\":\n      case \"hidden\":\n        style.borderStyle = \"\";\n        break;\n      case \"inactive\":\n        style.borderStyle = \"none\";\n        break;\n      default:\n        style.borderStyle = edgeStyles.map(s => s.style).join(\" \");\n        break;\n    }\n    style.borderWidth = edgeStyles.map(s => s.width).join(\" \");\n    style.borderColor = edgeStyles.map(s => s.color).join(\" \");\n    return style;\n  }\n}\nclass Break extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"break\", true);\n    this.after = getStringOption(attributes.after, [\"auto\", \"contentArea\", \"pageArea\", \"pageEven\", \"pageOdd\"]);\n    this.afterTarget = attributes.afterTarget || \"\";\n    this.before = getStringOption(attributes.before, [\"auto\", \"contentArea\", \"pageArea\", \"pageEven\", \"pageOdd\"]);\n    this.beforeTarget = attributes.beforeTarget || \"\";\n    this.bookendLeader = attributes.bookendLeader || \"\";\n    this.bookendTrailer = attributes.bookendTrailer || \"\";\n    this.id = attributes.id || \"\";\n    this.overflowLeader = attributes.overflowLeader || \"\";\n    this.overflowTarget = attributes.overflowTarget || \"\";\n    this.overflowTrailer = attributes.overflowTrailer || \"\";\n    this.startNew = getInteger({\n      data: attributes.startNew,\n      defaultValue: 0,\n      validate: x => x === 1\n    });\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.extras = null;\n  }\n}\nclass BreakAfter extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"breakAfter\", true);\n    this.id = attributes.id || \"\";\n    this.leader = attributes.leader || \"\";\n    this.startNew = getInteger({\n      data: attributes.startNew,\n      defaultValue: 0,\n      validate: x => x === 1\n    });\n    this.target = attributes.target || \"\";\n    this.targetType = getStringOption(attributes.targetType, [\"auto\", \"contentArea\", \"pageArea\"]);\n    this.trailer = attributes.trailer || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.script = null;\n  }\n}\nclass BreakBefore extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"breakBefore\", true);\n    this.id = attributes.id || \"\";\n    this.leader = attributes.leader || \"\";\n    this.startNew = getInteger({\n      data: attributes.startNew,\n      defaultValue: 0,\n      validate: x => x === 1\n    });\n    this.target = attributes.target || \"\";\n    this.targetType = getStringOption(attributes.targetType, [\"auto\", \"contentArea\", \"pageArea\"]);\n    this.trailer = attributes.trailer || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.script = null;\n  }\n  [$toHTML](availableSpace) {\n    this[$extra] = {};\n    return HTMLResult.FAILURE;\n  }\n}\nclass Button extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"button\", true);\n    this.highlight = getStringOption(attributes.highlight, [\"inverted\", \"none\", \"outline\", \"push\"]);\n    this.id = attributes.id || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.extras = null;\n  }\n  [$toHTML](availableSpace) {\n    const parent = this[$getParent]();\n    const grandpa = parent[$getParent]();\n    const htmlButton = {\n      name: \"button\",\n      attributes: {\n        id: this[$uid],\n        class: [\"xfaButton\"],\n        style: {}\n      },\n      children: []\n    };\n    for (const event of grandpa.event.children) {\n      if (event.activity !== \"click\" || !event.script) {\n        continue;\n      }\n      const jsURL = recoverJsURL(event.script[$content]);\n      if (!jsURL) {\n        continue;\n      }\n      const href = fixURL(jsURL.url);\n      if (!href) {\n        continue;\n      }\n      htmlButton.children.push({\n        name: \"a\",\n        attributes: {\n          id: \"link\" + this[$uid],\n          href,\n          newWindow: jsURL.newWindow,\n          class: [\"xfaLink\"],\n          style: {}\n        },\n        children: []\n      });\n    }\n    return HTMLResult.success(htmlButton);\n  }\n}\nclass Calculate extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"calculate\", true);\n    this.id = attributes.id || \"\";\n    this.override = getStringOption(attributes.override, [\"disabled\", \"error\", \"ignore\", \"warning\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.extras = null;\n    this.message = null;\n    this.script = null;\n  }\n}\nclass Caption extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"caption\", true);\n    this.id = attributes.id || \"\";\n    this.placement = getStringOption(attributes.placement, [\"left\", \"bottom\", \"inline\", \"right\", \"top\"]);\n    this.presence = getStringOption(attributes.presence, [\"visible\", \"hidden\", \"inactive\", \"invisible\"]);\n    this.reserve = Math.ceil(getMeasurement(attributes.reserve));\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.extras = null;\n    this.font = null;\n    this.margin = null;\n    this.para = null;\n    this.value = null;\n  }\n  [$setValue](value) {\n    _setValue(this, value);\n  }\n  [$getExtra](availableSpace) {\n    if (!this[$extra]) {\n      let {\n        width,\n        height\n      } = availableSpace;\n      switch (this.placement) {\n        case \"left\":\n        case \"right\":\n        case \"inline\":\n          width = this.reserve <= 0 ? width : this.reserve;\n          break;\n        case \"top\":\n        case \"bottom\":\n          height = this.reserve <= 0 ? height : this.reserve;\n          break;\n      }\n      this[$extra] = layoutNode(this, {\n        width,\n        height\n      });\n    }\n    return this[$extra];\n  }\n  [$toHTML](availableSpace) {\n    if (!this.value) {\n      return HTMLResult.EMPTY;\n    }\n    this[$pushPara]();\n    const value = this.value[$toHTML](availableSpace).html;\n    if (!value) {\n      this[$popPara]();\n      return HTMLResult.EMPTY;\n    }\n    const savedReserve = this.reserve;\n    if (this.reserve <= 0) {\n      const {\n        w,\n        h\n      } = this[$getExtra](availableSpace);\n      switch (this.placement) {\n        case \"left\":\n        case \"right\":\n        case \"inline\":\n          this.reserve = w;\n          break;\n        case \"top\":\n        case \"bottom\":\n          this.reserve = h;\n          break;\n      }\n    }\n    const children = [];\n    if (typeof value === \"string\") {\n      children.push({\n        name: \"#text\",\n        value\n      });\n    } else {\n      children.push(value);\n    }\n    const style = toStyle(this, \"font\", \"margin\", \"visibility\");\n    switch (this.placement) {\n      case \"left\":\n      case \"right\":\n        if (this.reserve > 0) {\n          style.width = measureToString(this.reserve);\n        }\n        break;\n      case \"top\":\n      case \"bottom\":\n        if (this.reserve > 0) {\n          style.height = measureToString(this.reserve);\n        }\n        break;\n    }\n    setPara(this, null, value);\n    this[$popPara]();\n    this.reserve = savedReserve;\n    return HTMLResult.success({\n      name: \"div\",\n      attributes: {\n        style,\n        class: [\"xfaCaption\"]\n      },\n      children\n    });\n  }\n}\nclass Certificate extends StringObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"certificate\");\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass Certificates extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"certificates\", true);\n    this.credentialServerPolicy = getStringOption(attributes.credentialServerPolicy, [\"optional\", \"required\"]);\n    this.id = attributes.id || \"\";\n    this.url = attributes.url || \"\";\n    this.urlPolicy = attributes.urlPolicy || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.encryption = null;\n    this.issuers = null;\n    this.keyUsage = null;\n    this.oids = null;\n    this.signing = null;\n    this.subjectDNs = null;\n  }\n}\nclass CheckButton extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"checkButton\", true);\n    this.id = attributes.id || \"\";\n    this.mark = getStringOption(attributes.mark, [\"default\", \"check\", \"circle\", \"cross\", \"diamond\", \"square\", \"star\"]);\n    this.shape = getStringOption(attributes.shape, [\"square\", \"round\"]);\n    this.size = getMeasurement(attributes.size, \"10pt\");\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.border = null;\n    this.extras = null;\n    this.margin = null;\n  }\n  [$toHTML](availableSpace) {\n    const style = toStyle(\"margin\");\n    const size = measureToString(this.size);\n    style.width = style.height = size;\n    let type;\n    let className;\n    let groupId;\n    const field = this[$getParent]()[$getParent]();\n    const items = field.items.children.length && field.items.children[0][$toHTML]().html || [];\n    const exportedValue = {\n      on: (items[0] !== undefined ? items[0] : \"on\").toString(),\n      off: (items[1] !== undefined ? items[1] : \"off\").toString()\n    };\n    const value = field.value?.[$text]() || \"off\";\n    const checked = value === exportedValue.on || undefined;\n    const container = field[$getSubformParent]();\n    const fieldId = field[$uid];\n    let dataId;\n    if (container instanceof ExclGroup) {\n      groupId = container[$uid];\n      type = \"radio\";\n      className = \"xfaRadio\";\n      dataId = container[$data]?.[$uid] || container[$uid];\n    } else {\n      type = \"checkbox\";\n      className = \"xfaCheckbox\";\n      dataId = field[$data]?.[$uid] || field[$uid];\n    }\n    const input = {\n      name: \"input\",\n      attributes: {\n        class: [className],\n        style,\n        fieldId,\n        dataId,\n        type,\n        checked,\n        xfaOn: exportedValue.on,\n        xfaOff: exportedValue.off,\n        \"aria-label\": ariaLabel(field),\n        \"aria-required\": false\n      }\n    };\n    if (groupId) {\n      input.attributes.name = groupId;\n    }\n    if (isRequired(field)) {\n      input.attributes[\"aria-required\"] = true;\n      input.attributes.required = true;\n    }\n    return HTMLResult.success({\n      name: \"label\",\n      attributes: {\n        class: [\"xfaLabel\"]\n      },\n      children: [input]\n    });\n  }\n}\nclass ChoiceList extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"choiceList\", true);\n    this.commitOn = getStringOption(attributes.commitOn, [\"select\", \"exit\"]);\n    this.id = attributes.id || \"\";\n    this.open = getStringOption(attributes.open, [\"userControl\", \"always\", \"multiSelect\", \"onEntry\"]);\n    this.textEntry = getInteger({\n      data: attributes.textEntry,\n      defaultValue: 0,\n      validate: x => x === 1\n    });\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.border = null;\n    this.extras = null;\n    this.margin = null;\n  }\n  [$toHTML](availableSpace) {\n    const style = toStyle(this, \"border\", \"margin\");\n    const ui = this[$getParent]();\n    const field = ui[$getParent]();\n    const fontSize = field.font?.size || 10;\n    const optionStyle = {\n      fontSize: `calc(${fontSize}px * var(--scale-factor))`\n    };\n    const children = [];\n    if (field.items.children.length > 0) {\n      const items = field.items;\n      let displayedIndex = 0;\n      let saveIndex = 0;\n      if (items.children.length === 2) {\n        displayedIndex = items.children[0].save;\n        saveIndex = 1 - displayedIndex;\n      }\n      const displayed = items.children[displayedIndex][$toHTML]().html;\n      const values = items.children[saveIndex][$toHTML]().html;\n      let selected = false;\n      const value = field.value?.[$text]() || \"\";\n      for (let i = 0, ii = displayed.length; i < ii; i++) {\n        const option = {\n          name: \"option\",\n          attributes: {\n            value: values[i] || displayed[i],\n            style: optionStyle\n          },\n          value: displayed[i]\n        };\n        if (values[i] === value) {\n          option.attributes.selected = selected = true;\n        }\n        children.push(option);\n      }\n      if (!selected) {\n        children.splice(0, 0, {\n          name: \"option\",\n          attributes: {\n            hidden: true,\n            selected: true\n          },\n          value: \" \"\n        });\n      }\n    }\n    const selectAttributes = {\n      class: [\"xfaSelect\"],\n      fieldId: field[$uid],\n      dataId: field[$data]?.[$uid] || field[$uid],\n      style,\n      \"aria-label\": ariaLabel(field),\n      \"aria-required\": false\n    };\n    if (isRequired(field)) {\n      selectAttributes[\"aria-required\"] = true;\n      selectAttributes.required = true;\n    }\n    if (this.open === \"multiSelect\") {\n      selectAttributes.multiple = true;\n    }\n    return HTMLResult.success({\n      name: \"label\",\n      attributes: {\n        class: [\"xfaLabel\"]\n      },\n      children: [{\n        name: \"select\",\n        children,\n        attributes: selectAttributes\n      }]\n    });\n  }\n}\nclass Color extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"color\", true);\n    this.cSpace = getStringOption(attributes.cSpace, [\"SRGB\"]);\n    this.id = attributes.id || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.value = attributes.value ? getColor(attributes.value) : \"\";\n    this.extras = null;\n  }\n  [$hasSettableValue]() {\n    return false;\n  }\n  [$toStyle]() {\n    return this.value ? Util.makeHexColor(this.value.r, this.value.g, this.value.b) : null;\n  }\n}\nclass Comb extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"comb\");\n    this.id = attributes.id || \"\";\n    this.numberOfCells = getInteger({\n      data: attributes.numberOfCells,\n      defaultValue: 0,\n      validate: x => x >= 0\n    });\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass Connect extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"connect\", true);\n    this.connection = attributes.connection || \"\";\n    this.id = attributes.id || \"\";\n    this.ref = attributes.ref || \"\";\n    this.usage = getStringOption(attributes.usage, [\"exportAndImport\", \"exportOnly\", \"importOnly\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.picture = null;\n  }\n}\nclass ContentArea extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"contentArea\", true);\n    this.h = getMeasurement(attributes.h);\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.relevant = getRelevant(attributes.relevant);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.w = getMeasurement(attributes.w);\n    this.x = getMeasurement(attributes.x, \"0pt\");\n    this.y = getMeasurement(attributes.y, \"0pt\");\n    this.desc = null;\n    this.extras = null;\n  }\n  [$toHTML](availableSpace) {\n    const left = measureToString(this.x);\n    const top = measureToString(this.y);\n    const style = {\n      left,\n      top,\n      width: measureToString(this.w),\n      height: measureToString(this.h)\n    };\n    const classNames = [\"xfaContentarea\"];\n    if (isPrintOnly(this)) {\n      classNames.push(\"xfaPrintOnly\");\n    }\n    return HTMLResult.success({\n      name: \"div\",\n      children: [],\n      attributes: {\n        style,\n        class: classNames,\n        id: this[$uid]\n      }\n    });\n  }\n}\nclass Corner extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"corner\", true);\n    this.id = attributes.id || \"\";\n    this.inverted = getInteger({\n      data: attributes.inverted,\n      defaultValue: 0,\n      validate: x => x === 1\n    });\n    this.join = getStringOption(attributes.join, [\"square\", \"round\"]);\n    this.presence = getStringOption(attributes.presence, [\"visible\", \"hidden\", \"inactive\", \"invisible\"]);\n    this.radius = getMeasurement(attributes.radius);\n    this.stroke = getStringOption(attributes.stroke, [\"solid\", \"dashDot\", \"dashDotDot\", \"dashed\", \"dotted\", \"embossed\", \"etched\", \"lowered\", \"raised\"]);\n    this.thickness = getMeasurement(attributes.thickness, \"0.5pt\");\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.color = null;\n    this.extras = null;\n  }\n  [$toStyle]() {\n    const style = toStyle(this, \"visibility\");\n    style.radius = measureToString(this.join === \"square\" ? 0 : this.radius);\n    return style;\n  }\n}\nclass DateElement extends ContentObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"date\");\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n  [$finalize]() {\n    const date = this[$content].trim();\n    this[$content] = date ? new Date(date) : null;\n  }\n  [$toHTML](availableSpace) {\n    return valueToHtml(this[$content] ? this[$content].toString() : \"\");\n  }\n}\nclass DateTime extends ContentObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"dateTime\");\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n  [$finalize]() {\n    const date = this[$content].trim();\n    this[$content] = date ? new Date(date) : null;\n  }\n  [$toHTML](availableSpace) {\n    return valueToHtml(this[$content] ? this[$content].toString() : \"\");\n  }\n}\nclass DateTimeEdit extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"dateTimeEdit\", true);\n    this.hScrollPolicy = getStringOption(attributes.hScrollPolicy, [\"auto\", \"off\", \"on\"]);\n    this.id = attributes.id || \"\";\n    this.picker = getStringOption(attributes.picker, [\"host\", \"none\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.border = null;\n    this.comb = null;\n    this.extras = null;\n    this.margin = null;\n  }\n  [$toHTML](availableSpace) {\n    const style = toStyle(this, \"border\", \"font\", \"margin\");\n    const field = this[$getParent]()[$getParent]();\n    const html = {\n      name: \"input\",\n      attributes: {\n        type: \"text\",\n        fieldId: field[$uid],\n        dataId: field[$data]?.[$uid] || field[$uid],\n        class: [\"xfaTextfield\"],\n        style,\n        \"aria-label\": ariaLabel(field),\n        \"aria-required\": false\n      }\n    };\n    if (isRequired(field)) {\n      html.attributes[\"aria-required\"] = true;\n      html.attributes.required = true;\n    }\n    return HTMLResult.success({\n      name: \"label\",\n      attributes: {\n        class: [\"xfaLabel\"]\n      },\n      children: [html]\n    });\n  }\n}\nclass Decimal extends ContentObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"decimal\");\n    this.fracDigits = getInteger({\n      data: attributes.fracDigits,\n      defaultValue: 2,\n      validate: x => true\n    });\n    this.id = attributes.id || \"\";\n    this.leadDigits = getInteger({\n      data: attributes.leadDigits,\n      defaultValue: -1,\n      validate: x => true\n    });\n    this.name = attributes.name || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n  [$finalize]() {\n    const number = parseFloat(this[$content].trim());\n    this[$content] = isNaN(number) ? null : number;\n  }\n  [$toHTML](availableSpace) {\n    return valueToHtml(this[$content] !== null ? this[$content].toString() : \"\");\n  }\n}\nclass DefaultUi extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"defaultUi\", true);\n    this.id = attributes.id || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.extras = null;\n  }\n}\nclass Desc extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"desc\", true);\n    this.id = attributes.id || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.boolean = new XFAObjectArray();\n    this.date = new XFAObjectArray();\n    this.dateTime = new XFAObjectArray();\n    this.decimal = new XFAObjectArray();\n    this.exData = new XFAObjectArray();\n    this.float = new XFAObjectArray();\n    this.image = new XFAObjectArray();\n    this.integer = new XFAObjectArray();\n    this.text = new XFAObjectArray();\n    this.time = new XFAObjectArray();\n  }\n}\nclass DigestMethod extends OptionObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"digestMethod\", [\"\", \"SHA1\", \"SHA256\", \"SHA512\", \"RIPEMD160\"]);\n    this.id = attributes.id || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass DigestMethods extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"digestMethods\", true);\n    this.id = attributes.id || \"\";\n    this.type = getStringOption(attributes.type, [\"optional\", \"required\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.digestMethod = new XFAObjectArray();\n  }\n}\nclass Draw extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"draw\", true);\n    this.anchorType = getStringOption(attributes.anchorType, [\"topLeft\", \"bottomCenter\", \"bottomLeft\", \"bottomRight\", \"middleCenter\", \"middleLeft\", \"middleRight\", \"topCenter\", \"topRight\"]);\n    this.colSpan = getInteger({\n      data: attributes.colSpan,\n      defaultValue: 1,\n      validate: n => n >= 1 || n === -1\n    });\n    this.h = attributes.h ? getMeasurement(attributes.h) : \"\";\n    this.hAlign = getStringOption(attributes.hAlign, [\"left\", \"center\", \"justify\", \"justifyAll\", \"radix\", \"right\"]);\n    this.id = attributes.id || \"\";\n    this.locale = attributes.locale || \"\";\n    this.maxH = getMeasurement(attributes.maxH, \"0pt\");\n    this.maxW = getMeasurement(attributes.maxW, \"0pt\");\n    this.minH = getMeasurement(attributes.minH, \"0pt\");\n    this.minW = getMeasurement(attributes.minW, \"0pt\");\n    this.name = attributes.name || \"\";\n    this.presence = getStringOption(attributes.presence, [\"visible\", \"hidden\", \"inactive\", \"invisible\"]);\n    this.relevant = getRelevant(attributes.relevant);\n    this.rotate = getInteger({\n      data: attributes.rotate,\n      defaultValue: 0,\n      validate: x => x % 90 === 0\n    });\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.w = attributes.w ? getMeasurement(attributes.w) : \"\";\n    this.x = getMeasurement(attributes.x, \"0pt\");\n    this.y = getMeasurement(attributes.y, \"0pt\");\n    this.assist = null;\n    this.border = null;\n    this.caption = null;\n    this.desc = null;\n    this.extras = null;\n    this.font = null;\n    this.keep = null;\n    this.margin = null;\n    this.para = null;\n    this.traversal = null;\n    this.ui = null;\n    this.value = null;\n    this.setProperty = new XFAObjectArray();\n  }\n  [$setValue](value) {\n    _setValue(this, value);\n  }\n  [$toHTML](availableSpace) {\n    setTabIndex(this);\n    if (this.presence === \"hidden\" || this.presence === \"inactive\") {\n      return HTMLResult.EMPTY;\n    }\n    fixDimensions(this);\n    this[$pushPara]();\n    const savedW = this.w;\n    const savedH = this.h;\n    const {\n      w,\n      h,\n      isBroken\n    } = layoutNode(this, availableSpace);\n    if (w && this.w === \"\") {\n      if (isBroken && this[$getSubformParent]()[$isThereMoreWidth]()) {\n        this[$popPara]();\n        return HTMLResult.FAILURE;\n      }\n      this.w = w;\n    }\n    if (h && this.h === \"\") {\n      this.h = h;\n    }\n    setFirstUnsplittable(this);\n    if (!checkDimensions(this, availableSpace)) {\n      this.w = savedW;\n      this.h = savedH;\n      this[$popPara]();\n      return HTMLResult.FAILURE;\n    }\n    unsetFirstUnsplittable(this);\n    const style = toStyle(this, \"font\", \"hAlign\", \"dimensions\", \"position\", \"presence\", \"rotate\", \"anchorType\", \"border\", \"margin\");\n    setMinMaxDimensions(this, style);\n    if (style.margin) {\n      style.padding = style.margin;\n      delete style.margin;\n    }\n    const classNames = [\"xfaDraw\"];\n    if (this.font) {\n      classNames.push(\"xfaFont\");\n    }\n    if (isPrintOnly(this)) {\n      classNames.push(\"xfaPrintOnly\");\n    }\n    const attributes = {\n      style,\n      id: this[$uid],\n      class: classNames\n    };\n    if (this.name) {\n      attributes.xfaName = this.name;\n    }\n    const html = {\n      name: \"div\",\n      attributes,\n      children: []\n    };\n    applyAssist(this, attributes);\n    const bbox = computeBbox(this, html, availableSpace);\n    const value = this.value ? this.value[$toHTML](availableSpace).html : null;\n    if (value === null) {\n      this.w = savedW;\n      this.h = savedH;\n      this[$popPara]();\n      return HTMLResult.success(createWrapper(this, html), bbox);\n    }\n    html.children.push(value);\n    setPara(this, style, value);\n    this.w = savedW;\n    this.h = savedH;\n    this[$popPara]();\n    return HTMLResult.success(createWrapper(this, html), bbox);\n  }\n}\nclass Edge extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"edge\", true);\n    this.cap = getStringOption(attributes.cap, [\"square\", \"butt\", \"round\"]);\n    this.id = attributes.id || \"\";\n    this.presence = getStringOption(attributes.presence, [\"visible\", \"hidden\", \"inactive\", \"invisible\"]);\n    this.stroke = getStringOption(attributes.stroke, [\"solid\", \"dashDot\", \"dashDotDot\", \"dashed\", \"dotted\", \"embossed\", \"etched\", \"lowered\", \"raised\"]);\n    this.thickness = getMeasurement(attributes.thickness, \"0.5pt\");\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.color = null;\n    this.extras = null;\n  }\n  [$toStyle]() {\n    const style = toStyle(this, \"visibility\");\n    Object.assign(style, {\n      linecap: this.cap,\n      width: measureToString(this.thickness),\n      color: this.color ? this.color[$toStyle]() : \"#000000\",\n      style: \"\"\n    });\n    if (this.presence !== \"visible\") {\n      style.style = \"none\";\n    } else {\n      switch (this.stroke) {\n        case \"solid\":\n          style.style = \"solid\";\n          break;\n        case \"dashDot\":\n          style.style = \"dashed\";\n          break;\n        case \"dashDotDot\":\n          style.style = \"dashed\";\n          break;\n        case \"dashed\":\n          style.style = \"dashed\";\n          break;\n        case \"dotted\":\n          style.style = \"dotted\";\n          break;\n        case \"embossed\":\n          style.style = \"ridge\";\n          break;\n        case \"etched\":\n          style.style = \"groove\";\n          break;\n        case \"lowered\":\n          style.style = \"inset\";\n          break;\n        case \"raised\":\n          style.style = \"outset\";\n          break;\n      }\n    }\n    return style;\n  }\n}\nclass Encoding extends OptionObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"encoding\", [\"adbe.x509.rsa_sha1\", \"adbe.pkcs7.detached\", \"adbe.pkcs7.sha1\"]);\n    this.id = attributes.id || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass Encodings extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"encodings\", true);\n    this.id = attributes.id || \"\";\n    this.type = getStringOption(attributes.type, [\"optional\", \"required\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.encoding = new XFAObjectArray();\n  }\n}\nclass Encrypt extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"encrypt\", true);\n    this.id = attributes.id || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.certificate = null;\n  }\n}\nclass EncryptData extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"encryptData\", true);\n    this.id = attributes.id || \"\";\n    this.operation = getStringOption(attributes.operation, [\"encrypt\", \"decrypt\"]);\n    this.target = attributes.target || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.filter = null;\n    this.manifest = null;\n  }\n}\nclass Encryption extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"encryption\", true);\n    this.id = attributes.id || \"\";\n    this.type = getStringOption(attributes.type, [\"optional\", \"required\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.certificate = new XFAObjectArray();\n  }\n}\nclass EncryptionMethod extends OptionObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"encryptionMethod\", [\"\", \"AES256-CBC\", \"TRIPLEDES-CBC\", \"AES128-CBC\", \"AES192-CBC\"]);\n    this.id = attributes.id || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass EncryptionMethods extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"encryptionMethods\", true);\n    this.id = attributes.id || \"\";\n    this.type = getStringOption(attributes.type, [\"optional\", \"required\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.encryptionMethod = new XFAObjectArray();\n  }\n}\nclass Event extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"event\", true);\n    this.activity = getStringOption(attributes.activity, [\"click\", \"change\", \"docClose\", \"docReady\", \"enter\", \"exit\", \"full\", \"indexChange\", \"initialize\", \"mouseDown\", \"mouseEnter\", \"mouseExit\", \"mouseUp\", \"postExecute\", \"postOpen\", \"postPrint\", \"postSave\", \"postSign\", \"postSubmit\", \"preExecute\", \"preOpen\", \"prePrint\", \"preSave\", \"preSign\", \"preSubmit\", \"ready\", \"validationState\"]);\n    this.id = attributes.id || \"\";\n    this.listen = getStringOption(attributes.listen, [\"refOnly\", \"refAndDescendents\"]);\n    this.name = attributes.name || \"\";\n    this.ref = attributes.ref || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.extras = null;\n    this.encryptData = null;\n    this.execute = null;\n    this.script = null;\n    this.signData = null;\n    this.submit = null;\n  }\n}\nclass ExData extends ContentObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"exData\");\n    this.contentType = attributes.contentType || \"\";\n    this.href = attributes.href || \"\";\n    this.id = attributes.id || \"\";\n    this.maxLength = getInteger({\n      data: attributes.maxLength,\n      defaultValue: -1,\n      validate: x => x >= -1\n    });\n    this.name = attributes.name || \"\";\n    this.rid = attributes.rid || \"\";\n    this.transferEncoding = getStringOption(attributes.transferEncoding, [\"none\", \"base64\", \"package\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n  [$isCDATAXml]() {\n    return this.contentType === \"text/html\";\n  }\n  [$onChild](child) {\n    if (this.contentType === \"text/html\" && child[$namespaceId] === NamespaceIds.xhtml.id) {\n      this[$content] = child;\n      return true;\n    }\n    if (this.contentType === \"text/xml\") {\n      this[$content] = child;\n      return true;\n    }\n    return false;\n  }\n  [$toHTML](availableSpace) {\n    if (this.contentType !== \"text/html\" || !this[$content]) {\n      return HTMLResult.EMPTY;\n    }\n    return this[$content][$toHTML](availableSpace);\n  }\n}\nclass ExObject extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"exObject\", true);\n    this.archive = attributes.archive || \"\";\n    this.classId = attributes.classId || \"\";\n    this.codeBase = attributes.codeBase || \"\";\n    this.codeType = attributes.codeType || \"\";\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.extras = null;\n    this.boolean = new XFAObjectArray();\n    this.date = new XFAObjectArray();\n    this.dateTime = new XFAObjectArray();\n    this.decimal = new XFAObjectArray();\n    this.exData = new XFAObjectArray();\n    this.exObject = new XFAObjectArray();\n    this.float = new XFAObjectArray();\n    this.image = new XFAObjectArray();\n    this.integer = new XFAObjectArray();\n    this.text = new XFAObjectArray();\n    this.time = new XFAObjectArray();\n  }\n}\nclass ExclGroup extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"exclGroup\", true);\n    this.access = getStringOption(attributes.access, [\"open\", \"nonInteractive\", \"protected\", \"readOnly\"]);\n    this.accessKey = attributes.accessKey || \"\";\n    this.anchorType = getStringOption(attributes.anchorType, [\"topLeft\", \"bottomCenter\", \"bottomLeft\", \"bottomRight\", \"middleCenter\", \"middleLeft\", \"middleRight\", \"topCenter\", \"topRight\"]);\n    this.colSpan = getInteger({\n      data: attributes.colSpan,\n      defaultValue: 1,\n      validate: n => n >= 1 || n === -1\n    });\n    this.h = attributes.h ? getMeasurement(attributes.h) : \"\";\n    this.hAlign = getStringOption(attributes.hAlign, [\"left\", \"center\", \"justify\", \"justifyAll\", \"radix\", \"right\"]);\n    this.id = attributes.id || \"\";\n    this.layout = getStringOption(attributes.layout, [\"position\", \"lr-tb\", \"rl-row\", \"rl-tb\", \"row\", \"table\", \"tb\"]);\n    this.maxH = getMeasurement(attributes.maxH, \"0pt\");\n    this.maxW = getMeasurement(attributes.maxW, \"0pt\");\n    this.minH = getMeasurement(attributes.minH, \"0pt\");\n    this.minW = getMeasurement(attributes.minW, \"0pt\");\n    this.name = attributes.name || \"\";\n    this.presence = getStringOption(attributes.presence, [\"visible\", \"hidden\", \"inactive\", \"invisible\"]);\n    this.relevant = getRelevant(attributes.relevant);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.w = attributes.w ? getMeasurement(attributes.w) : \"\";\n    this.x = getMeasurement(attributes.x, \"0pt\");\n    this.y = getMeasurement(attributes.y, \"0pt\");\n    this.assist = null;\n    this.bind = null;\n    this.border = null;\n    this.calculate = null;\n    this.caption = null;\n    this.desc = null;\n    this.extras = null;\n    this.margin = null;\n    this.para = null;\n    this.traversal = null;\n    this.validate = null;\n    this.connect = new XFAObjectArray();\n    this.event = new XFAObjectArray();\n    this.field = new XFAObjectArray();\n    this.setProperty = new XFAObjectArray();\n  }\n  [$isBindable]() {\n    return true;\n  }\n  [$hasSettableValue]() {\n    return true;\n  }\n  [$setValue](value) {\n    for (const field of this.field.children) {\n      if (!field.value) {\n        const nodeValue = new Value({});\n        field[$appendChild](nodeValue);\n        field.value = nodeValue;\n      }\n      field.value[$setValue](value);\n    }\n  }\n  [$isThereMoreWidth]() {\n    return this.layout.endsWith(\"-tb\") && this[$extra].attempt === 0 && this[$extra].numberInLine > 0 || this[$getParent]()[$isThereMoreWidth]();\n  }\n  [$isSplittable]() {\n    const parent = this[$getSubformParent]();\n    if (!parent[$isSplittable]()) {\n      return false;\n    }\n    if (this[$extra]._isSplittable !== undefined) {\n      return this[$extra]._isSplittable;\n    }\n    if (this.layout === \"position\" || this.layout.includes(\"row\")) {\n      this[$extra]._isSplittable = false;\n      return false;\n    }\n    if (parent.layout?.endsWith(\"-tb\") && parent[$extra].numberInLine !== 0) {\n      return false;\n    }\n    this[$extra]._isSplittable = true;\n    return true;\n  }\n  [$flushHTML]() {\n    return flushHTML(this);\n  }\n  [$addHTML](html, bbox) {\n    addHTML(this, html, bbox);\n  }\n  [$getAvailableSpace]() {\n    return getAvailableSpace(this);\n  }\n  [$toHTML](availableSpace) {\n    setTabIndex(this);\n    if (this.presence === \"hidden\" || this.presence === \"inactive\" || this.h === 0 || this.w === 0) {\n      return HTMLResult.EMPTY;\n    }\n    fixDimensions(this);\n    const children = [];\n    const attributes = {\n      id: this[$uid],\n      class: []\n    };\n    setAccess(this, attributes.class);\n    if (!this[$extra]) {\n      this[$extra] = Object.create(null);\n    }\n    Object.assign(this[$extra], {\n      children,\n      attributes,\n      attempt: 0,\n      line: null,\n      numberInLine: 0,\n      availableSpace: {\n        width: Math.min(this.w || Infinity, availableSpace.width),\n        height: Math.min(this.h || Infinity, availableSpace.height)\n      },\n      width: 0,\n      height: 0,\n      prevHeight: 0,\n      currentWidth: 0\n    });\n    const isSplittable = this[$isSplittable]();\n    if (!isSplittable) {\n      setFirstUnsplittable(this);\n    }\n    if (!checkDimensions(this, availableSpace)) {\n      return HTMLResult.FAILURE;\n    }\n    const filter = new Set([\"field\"]);\n    if (this.layout.includes(\"row\")) {\n      const columnWidths = this[$getSubformParent]().columnWidths;\n      if (Array.isArray(columnWidths) && columnWidths.length > 0) {\n        this[$extra].columnWidths = columnWidths;\n        this[$extra].currentColumn = 0;\n      }\n    }\n    const style = toStyle(this, \"anchorType\", \"dimensions\", \"position\", \"presence\", \"border\", \"margin\", \"hAlign\");\n    const classNames = [\"xfaExclgroup\"];\n    const cl = layoutClass(this);\n    if (cl) {\n      classNames.push(cl);\n    }\n    if (isPrintOnly(this)) {\n      classNames.push(\"xfaPrintOnly\");\n    }\n    attributes.style = style;\n    attributes.class = classNames;\n    if (this.name) {\n      attributes.xfaName = this.name;\n    }\n    this[$pushPara]();\n    const isLrTb = this.layout === \"lr-tb\" || this.layout === \"rl-tb\";\n    const maxRun = isLrTb ? MAX_ATTEMPTS_FOR_LRTB_LAYOUT : 1;\n    for (; this[$extra].attempt < maxRun; this[$extra].attempt++) {\n      if (isLrTb && this[$extra].attempt === MAX_ATTEMPTS_FOR_LRTB_LAYOUT - 1) {\n        this[$extra].numberInLine = 0;\n      }\n      const result = this[$childrenToHTML]({\n        filter,\n        include: true\n      });\n      if (result.success) {\n        break;\n      }\n      if (result.isBreak()) {\n        this[$popPara]();\n        return result;\n      }\n      if (isLrTb && this[$extra].attempt === 0 && this[$extra].numberInLine === 0 && !this[$getTemplateRoot]()[$extra].noLayoutFailure) {\n        this[$extra].attempt = maxRun;\n        break;\n      }\n    }\n    this[$popPara]();\n    if (!isSplittable) {\n      unsetFirstUnsplittable(this);\n    }\n    if (this[$extra].attempt === maxRun) {\n      if (!isSplittable) {\n        delete this[$extra];\n      }\n      return HTMLResult.FAILURE;\n    }\n    let marginH = 0;\n    let marginV = 0;\n    if (this.margin) {\n      marginH = this.margin.leftInset + this.margin.rightInset;\n      marginV = this.margin.topInset + this.margin.bottomInset;\n    }\n    const width = Math.max(this[$extra].width + marginH, this.w || 0);\n    const height = Math.max(this[$extra].height + marginV, this.h || 0);\n    const bbox = [this.x, this.y, width, height];\n    if (this.w === \"\") {\n      style.width = measureToString(width);\n    }\n    if (this.h === \"\") {\n      style.height = measureToString(height);\n    }\n    const html = {\n      name: \"div\",\n      attributes,\n      children\n    };\n    applyAssist(this, attributes);\n    delete this[$extra];\n    return HTMLResult.success(createWrapper(this, html), bbox);\n  }\n}\nclass Execute extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"execute\");\n    this.connection = attributes.connection || \"\";\n    this.executeType = getStringOption(attributes.executeType, [\"import\", \"remerge\"]);\n    this.id = attributes.id || \"\";\n    this.runAt = getStringOption(attributes.runAt, [\"client\", \"both\", \"server\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass Extras extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"extras\", true);\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.boolean = new XFAObjectArray();\n    this.date = new XFAObjectArray();\n    this.dateTime = new XFAObjectArray();\n    this.decimal = new XFAObjectArray();\n    this.exData = new XFAObjectArray();\n    this.extras = new XFAObjectArray();\n    this.float = new XFAObjectArray();\n    this.image = new XFAObjectArray();\n    this.integer = new XFAObjectArray();\n    this.text = new XFAObjectArray();\n    this.time = new XFAObjectArray();\n  }\n}\nclass Field extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"field\", true);\n    this.access = getStringOption(attributes.access, [\"open\", \"nonInteractive\", \"protected\", \"readOnly\"]);\n    this.accessKey = attributes.accessKey || \"\";\n    this.anchorType = getStringOption(attributes.anchorType, [\"topLeft\", \"bottomCenter\", \"bottomLeft\", \"bottomRight\", \"middleCenter\", \"middleLeft\", \"middleRight\", \"topCenter\", \"topRight\"]);\n    this.colSpan = getInteger({\n      data: attributes.colSpan,\n      defaultValue: 1,\n      validate: n => n >= 1 || n === -1\n    });\n    this.h = attributes.h ? getMeasurement(attributes.h) : \"\";\n    this.hAlign = getStringOption(attributes.hAlign, [\"left\", \"center\", \"justify\", \"justifyAll\", \"radix\", \"right\"]);\n    this.id = attributes.id || \"\";\n    this.locale = attributes.locale || \"\";\n    this.maxH = getMeasurement(attributes.maxH, \"0pt\");\n    this.maxW = getMeasurement(attributes.maxW, \"0pt\");\n    this.minH = getMeasurement(attributes.minH, \"0pt\");\n    this.minW = getMeasurement(attributes.minW, \"0pt\");\n    this.name = attributes.name || \"\";\n    this.presence = getStringOption(attributes.presence, [\"visible\", \"hidden\", \"inactive\", \"invisible\"]);\n    this.relevant = getRelevant(attributes.relevant);\n    this.rotate = getInteger({\n      data: attributes.rotate,\n      defaultValue: 0,\n      validate: x => x % 90 === 0\n    });\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.w = attributes.w ? getMeasurement(attributes.w) : \"\";\n    this.x = getMeasurement(attributes.x, \"0pt\");\n    this.y = getMeasurement(attributes.y, \"0pt\");\n    this.assist = null;\n    this.bind = null;\n    this.border = null;\n    this.calculate = null;\n    this.caption = null;\n    this.desc = null;\n    this.extras = null;\n    this.font = null;\n    this.format = null;\n    this.items = new XFAObjectArray(2);\n    this.keep = null;\n    this.margin = null;\n    this.para = null;\n    this.traversal = null;\n    this.ui = null;\n    this.validate = null;\n    this.value = null;\n    this.bindItems = new XFAObjectArray();\n    this.connect = new XFAObjectArray();\n    this.event = new XFAObjectArray();\n    this.setProperty = new XFAObjectArray();\n  }\n  [$isBindable]() {\n    return true;\n  }\n  [$setValue](value) {\n    _setValue(this, value);\n  }\n  [$toHTML](availableSpace) {\n    setTabIndex(this);\n    if (!this.ui) {\n      this.ui = new Ui({});\n      this.ui[$globalData] = this[$globalData];\n      this[$appendChild](this.ui);\n      let node;\n      switch (this.items.children.length) {\n        case 0:\n          node = new TextEdit({});\n          this.ui.textEdit = node;\n          break;\n        case 1:\n          node = new CheckButton({});\n          this.ui.checkButton = node;\n          break;\n        case 2:\n          node = new ChoiceList({});\n          this.ui.choiceList = node;\n          break;\n      }\n      this.ui[$appendChild](node);\n    }\n    if (!this.ui || this.presence === \"hidden\" || this.presence === \"inactive\" || this.h === 0 || this.w === 0) {\n      return HTMLResult.EMPTY;\n    }\n    if (this.caption) {\n      delete this.caption[$extra];\n    }\n    this[$pushPara]();\n    const caption = this.caption ? this.caption[$toHTML](availableSpace).html : null;\n    const savedW = this.w;\n    const savedH = this.h;\n    let marginH = 0;\n    let marginV = 0;\n    if (this.margin) {\n      marginH = this.margin.leftInset + this.margin.rightInset;\n      marginV = this.margin.topInset + this.margin.bottomInset;\n    }\n    let borderDims = null;\n    if (this.w === \"\" || this.h === \"\") {\n      let width = null;\n      let height = null;\n      let uiW = 0;\n      let uiH = 0;\n      if (this.ui.checkButton) {\n        uiW = uiH = this.ui.checkButton.size;\n      } else {\n        const {\n          w,\n          h\n        } = layoutNode(this, availableSpace);\n        if (w !== null) {\n          uiW = w;\n          uiH = h;\n        } else {\n          uiH = fonts_getMetrics(this.font, true).lineNoGap;\n        }\n      }\n      borderDims = getBorderDims(this.ui[$getExtra]());\n      uiW += borderDims.w;\n      uiH += borderDims.h;\n      if (this.caption) {\n        const {\n          w,\n          h,\n          isBroken\n        } = this.caption[$getExtra](availableSpace);\n        if (isBroken && this[$getSubformParent]()[$isThereMoreWidth]()) {\n          this[$popPara]();\n          return HTMLResult.FAILURE;\n        }\n        width = w;\n        height = h;\n        switch (this.caption.placement) {\n          case \"left\":\n          case \"right\":\n          case \"inline\":\n            width += uiW;\n            break;\n          case \"top\":\n          case \"bottom\":\n            height += uiH;\n            break;\n        }\n      } else {\n        width = uiW;\n        height = uiH;\n      }\n      if (width && this.w === \"\") {\n        width += marginH;\n        this.w = Math.min(this.maxW <= 0 ? Infinity : this.maxW, this.minW + 1 < width ? width : this.minW);\n      }\n      if (height && this.h === \"\") {\n        height += marginV;\n        this.h = Math.min(this.maxH <= 0 ? Infinity : this.maxH, this.minH + 1 < height ? height : this.minH);\n      }\n    }\n    this[$popPara]();\n    fixDimensions(this);\n    setFirstUnsplittable(this);\n    if (!checkDimensions(this, availableSpace)) {\n      this.w = savedW;\n      this.h = savedH;\n      this[$popPara]();\n      return HTMLResult.FAILURE;\n    }\n    unsetFirstUnsplittable(this);\n    const style = toStyle(this, \"font\", \"dimensions\", \"position\", \"rotate\", \"anchorType\", \"presence\", \"margin\", \"hAlign\");\n    setMinMaxDimensions(this, style);\n    const classNames = [\"xfaField\"];\n    if (this.font) {\n      classNames.push(\"xfaFont\");\n    }\n    if (isPrintOnly(this)) {\n      classNames.push(\"xfaPrintOnly\");\n    }\n    const attributes = {\n      style,\n      id: this[$uid],\n      class: classNames\n    };\n    if (style.margin) {\n      style.padding = style.margin;\n      delete style.margin;\n    }\n    setAccess(this, classNames);\n    if (this.name) {\n      attributes.xfaName = this.name;\n    }\n    const children = [];\n    const html = {\n      name: \"div\",\n      attributes,\n      children\n    };\n    applyAssist(this, attributes);\n    const borderStyle = this.border ? this.border[$toStyle]() : null;\n    const bbox = computeBbox(this, html, availableSpace);\n    const ui = this.ui[$toHTML]().html;\n    if (!ui) {\n      Object.assign(style, borderStyle);\n      return HTMLResult.success(createWrapper(this, html), bbox);\n    }\n    if (this[$tabIndex]) {\n      if (ui.children?.[0]) {\n        ui.children[0].attributes.tabindex = this[$tabIndex];\n      } else {\n        ui.attributes.tabindex = this[$tabIndex];\n      }\n    }\n    if (!ui.attributes.style) {\n      ui.attributes.style = Object.create(null);\n    }\n    let aElement = null;\n    if (this.ui.button) {\n      if (ui.children.length === 1) {\n        [aElement] = ui.children.splice(0, 1);\n      }\n      Object.assign(ui.attributes.style, borderStyle);\n    } else {\n      Object.assign(style, borderStyle);\n    }\n    children.push(ui);\n    if (this.value) {\n      if (this.ui.imageEdit) {\n        ui.children.push(this.value[$toHTML]().html);\n      } else if (!this.ui.button) {\n        let value = \"\";\n        if (this.value.exData) {\n          value = this.value.exData[$text]();\n        } else if (this.value.text) {\n          value = this.value.text[$getExtra]();\n        } else {\n          const htmlValue = this.value[$toHTML]().html;\n          if (htmlValue !== null) {\n            value = htmlValue.children[0].value;\n          }\n        }\n        if (this.ui.textEdit && this.value.text?.maxChars) {\n          ui.children[0].attributes.maxLength = this.value.text.maxChars;\n        }\n        if (value) {\n          if (this.ui.numericEdit) {\n            value = parseFloat(value);\n            value = isNaN(value) ? \"\" : value.toString();\n          }\n          if (ui.children[0].name === \"textarea\") {\n            ui.children[0].attributes.textContent = value;\n          } else {\n            ui.children[0].attributes.value = value;\n          }\n        }\n      }\n    }\n    if (!this.ui.imageEdit && ui.children?.[0] && this.h) {\n      borderDims = borderDims || getBorderDims(this.ui[$getExtra]());\n      let captionHeight = 0;\n      if (this.caption && [\"top\", \"bottom\"].includes(this.caption.placement)) {\n        captionHeight = this.caption.reserve;\n        if (captionHeight <= 0) {\n          captionHeight = this.caption[$getExtra](availableSpace).h;\n        }\n        const inputHeight = this.h - captionHeight - marginV - borderDims.h;\n        ui.children[0].attributes.style.height = measureToString(inputHeight);\n      } else {\n        ui.children[0].attributes.style.height = \"100%\";\n      }\n    }\n    if (aElement) {\n      ui.children.push(aElement);\n    }\n    if (!caption) {\n      if (ui.attributes.class) {\n        ui.attributes.class.push(\"xfaLeft\");\n      }\n      this.w = savedW;\n      this.h = savedH;\n      return HTMLResult.success(createWrapper(this, html), bbox);\n    }\n    if (this.ui.button) {\n      if (style.padding) {\n        delete style.padding;\n      }\n      if (caption.name === \"div\") {\n        caption.name = \"span\";\n      }\n      ui.children.push(caption);\n      return HTMLResult.success(html, bbox);\n    } else if (this.ui.checkButton) {\n      caption.attributes.class[0] = \"xfaCaptionForCheckButton\";\n    }\n    if (!ui.attributes.class) {\n      ui.attributes.class = [];\n    }\n    ui.children.splice(0, 0, caption);\n    switch (this.caption.placement) {\n      case \"left\":\n        ui.attributes.class.push(\"xfaLeft\");\n        break;\n      case \"right\":\n        ui.attributes.class.push(\"xfaRight\");\n        break;\n      case \"top\":\n        ui.attributes.class.push(\"xfaTop\");\n        break;\n      case \"bottom\":\n        ui.attributes.class.push(\"xfaBottom\");\n        break;\n      case \"inline\":\n        ui.attributes.class.push(\"xfaLeft\");\n        break;\n    }\n    this.w = savedW;\n    this.h = savedH;\n    return HTMLResult.success(createWrapper(this, html), bbox);\n  }\n}\nclass Fill extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"fill\", true);\n    this.id = attributes.id || \"\";\n    this.presence = getStringOption(attributes.presence, [\"visible\", \"hidden\", \"inactive\", \"invisible\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.color = null;\n    this.extras = null;\n    this.linear = null;\n    this.pattern = null;\n    this.radial = null;\n    this.solid = null;\n    this.stipple = null;\n  }\n  [$toStyle]() {\n    const parent = this[$getParent]();\n    const grandpa = parent[$getParent]();\n    const ggrandpa = grandpa[$getParent]();\n    const style = Object.create(null);\n    let propName = \"color\";\n    let altPropName = propName;\n    if (parent instanceof Border) {\n      propName = \"background-color\";\n      altPropName = \"background\";\n      if (ggrandpa instanceof Ui) {\n        style.backgroundColor = \"white\";\n      }\n    }\n    if (parent instanceof Rectangle || parent instanceof Arc) {\n      propName = altPropName = \"fill\";\n      style.fill = \"white\";\n    }\n    for (const name of Object.getOwnPropertyNames(this)) {\n      if (name === \"extras\" || name === \"color\") {\n        continue;\n      }\n      const obj = this[name];\n      if (!(obj instanceof XFAObject)) {\n        continue;\n      }\n      const color = obj[$toStyle](this.color);\n      if (color) {\n        style[color.startsWith(\"#\") ? propName : altPropName] = color;\n      }\n      return style;\n    }\n    if (this.color?.value) {\n      const color = this.color[$toStyle]();\n      style[color.startsWith(\"#\") ? propName : altPropName] = color;\n    }\n    return style;\n  }\n}\nclass Filter extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"filter\", true);\n    this.addRevocationInfo = getStringOption(attributes.addRevocationInfo, [\"\", \"required\", \"optional\", \"none\"]);\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.version = getInteger({\n      data: this.version,\n      defaultValue: 5,\n      validate: x => x >= 1 && x <= 5\n    });\n    this.appearanceFilter = null;\n    this.certificates = null;\n    this.digestMethods = null;\n    this.encodings = null;\n    this.encryptionMethods = null;\n    this.handler = null;\n    this.lockDocument = null;\n    this.mdp = null;\n    this.reasons = null;\n    this.timeStamp = null;\n  }\n}\nclass Float extends ContentObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"float\");\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n  [$finalize]() {\n    const number = parseFloat(this[$content].trim());\n    this[$content] = isNaN(number) ? null : number;\n  }\n  [$toHTML](availableSpace) {\n    return valueToHtml(this[$content] !== null ? this[$content].toString() : \"\");\n  }\n}\nclass template_Font extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"font\", true);\n    this.baselineShift = getMeasurement(attributes.baselineShift);\n    this.fontHorizontalScale = getFloat({\n      data: attributes.fontHorizontalScale,\n      defaultValue: 100,\n      validate: x => x >= 0\n    });\n    this.fontVerticalScale = getFloat({\n      data: attributes.fontVerticalScale,\n      defaultValue: 100,\n      validate: x => x >= 0\n    });\n    this.id = attributes.id || \"\";\n    this.kerningMode = getStringOption(attributes.kerningMode, [\"none\", \"pair\"]);\n    this.letterSpacing = getMeasurement(attributes.letterSpacing, \"0\");\n    this.lineThrough = getInteger({\n      data: attributes.lineThrough,\n      defaultValue: 0,\n      validate: x => x === 1 || x === 2\n    });\n    this.lineThroughPeriod = getStringOption(attributes.lineThroughPeriod, [\"all\", \"word\"]);\n    this.overline = getInteger({\n      data: attributes.overline,\n      defaultValue: 0,\n      validate: x => x === 1 || x === 2\n    });\n    this.overlinePeriod = getStringOption(attributes.overlinePeriod, [\"all\", \"word\"]);\n    this.posture = getStringOption(attributes.posture, [\"normal\", \"italic\"]);\n    this.size = getMeasurement(attributes.size, \"10pt\");\n    this.typeface = attributes.typeface || \"Courier\";\n    this.underline = getInteger({\n      data: attributes.underline,\n      defaultValue: 0,\n      validate: x => x === 1 || x === 2\n    });\n    this.underlinePeriod = getStringOption(attributes.underlinePeriod, [\"all\", \"word\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.weight = getStringOption(attributes.weight, [\"normal\", \"bold\"]);\n    this.extras = null;\n    this.fill = null;\n  }\n  [$clean](builder) {\n    super[$clean](builder);\n    this[$globalData].usedTypefaces.add(this.typeface);\n  }\n  [$toStyle]() {\n    const style = toStyle(this, \"fill\");\n    const color = style.color;\n    if (color) {\n      if (color === \"#000000\") {\n        delete style.color;\n      } else if (!color.startsWith(\"#\")) {\n        style.background = color;\n        style.backgroundClip = \"text\";\n        style.color = \"transparent\";\n      }\n    }\n    if (this.baselineShift) {\n      style.verticalAlign = measureToString(this.baselineShift);\n    }\n    style.fontKerning = this.kerningMode === \"none\" ? \"none\" : \"normal\";\n    style.letterSpacing = measureToString(this.letterSpacing);\n    if (this.lineThrough !== 0) {\n      style.textDecoration = \"line-through\";\n      if (this.lineThrough === 2) {\n        style.textDecorationStyle = \"double\";\n      }\n    }\n    if (this.overline !== 0) {\n      style.textDecoration = \"overline\";\n      if (this.overline === 2) {\n        style.textDecorationStyle = \"double\";\n      }\n    }\n    style.fontStyle = this.posture;\n    style.fontSize = measureToString(0.99 * this.size);\n    setFontFamily(this, this, this[$globalData].fontFinder, style);\n    if (this.underline !== 0) {\n      style.textDecoration = \"underline\";\n      if (this.underline === 2) {\n        style.textDecorationStyle = \"double\";\n      }\n    }\n    style.fontWeight = this.weight;\n    return style;\n  }\n}\nclass Format extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"format\", true);\n    this.id = attributes.id || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.extras = null;\n    this.picture = null;\n  }\n}\nclass Handler extends StringObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"handler\");\n    this.id = attributes.id || \"\";\n    this.type = getStringOption(attributes.type, [\"optional\", \"required\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass Hyphenation extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"hyphenation\");\n    this.excludeAllCaps = getInteger({\n      data: attributes.excludeAllCaps,\n      defaultValue: 0,\n      validate: x => x === 1\n    });\n    this.excludeInitialCap = getInteger({\n      data: attributes.excludeInitialCap,\n      defaultValue: 0,\n      validate: x => x === 1\n    });\n    this.hyphenate = getInteger({\n      data: attributes.hyphenate,\n      defaultValue: 0,\n      validate: x => x === 1\n    });\n    this.id = attributes.id || \"\";\n    this.pushCharacterCount = getInteger({\n      data: attributes.pushCharacterCount,\n      defaultValue: 3,\n      validate: x => x >= 0\n    });\n    this.remainCharacterCount = getInteger({\n      data: attributes.remainCharacterCount,\n      defaultValue: 3,\n      validate: x => x >= 0\n    });\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.wordCharacterCount = getInteger({\n      data: attributes.wordCharacterCount,\n      defaultValue: 7,\n      validate: x => x >= 0\n    });\n  }\n}\nclass Image extends StringObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"image\");\n    this.aspect = getStringOption(attributes.aspect, [\"fit\", \"actual\", \"height\", \"none\", \"width\"]);\n    this.contentType = attributes.contentType || \"\";\n    this.href = attributes.href || \"\";\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.transferEncoding = getStringOption(attributes.transferEncoding, [\"base64\", \"none\", \"package\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n  [$toHTML]() {\n    if (this.contentType && !MIMES.has(this.contentType.toLowerCase())) {\n      return HTMLResult.EMPTY;\n    }\n    let buffer = this[$globalData].images && this[$globalData].images.get(this.href);\n    if (!buffer && (this.href || !this[$content])) {\n      return HTMLResult.EMPTY;\n    }\n    if (!buffer && this.transferEncoding === \"base64\") {\n      buffer = stringToBytes(atob(this[$content]));\n    }\n    if (!buffer) {\n      return HTMLResult.EMPTY;\n    }\n    if (!this.contentType) {\n      for (const [header, type] of IMAGES_HEADERS) {\n        if (buffer.length > header.length && header.every((x, i) => x === buffer[i])) {\n          this.contentType = type;\n          break;\n        }\n      }\n      if (!this.contentType) {\n        return HTMLResult.EMPTY;\n      }\n    }\n    const blob = new Blob([buffer], {\n      type: this.contentType\n    });\n    let style;\n    switch (this.aspect) {\n      case \"fit\":\n      case \"actual\":\n        break;\n      case \"height\":\n        style = {\n          height: \"100%\",\n          objectFit: \"fill\"\n        };\n        break;\n      case \"none\":\n        style = {\n          width: \"100%\",\n          height: \"100%\",\n          objectFit: \"fill\"\n        };\n        break;\n      case \"width\":\n        style = {\n          width: \"100%\",\n          objectFit: \"fill\"\n        };\n        break;\n    }\n    const parent = this[$getParent]();\n    return HTMLResult.success({\n      name: \"img\",\n      attributes: {\n        class: [\"xfaImage\"],\n        style,\n        src: URL.createObjectURL(blob),\n        alt: parent ? ariaLabel(parent[$getParent]()) : null\n      }\n    });\n  }\n}\nclass ImageEdit extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"imageEdit\", true);\n    this.data = getStringOption(attributes.data, [\"link\", \"embed\"]);\n    this.id = attributes.id || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.border = null;\n    this.extras = null;\n    this.margin = null;\n  }\n  [$toHTML](availableSpace) {\n    if (this.data === \"embed\") {\n      return HTMLResult.success({\n        name: \"div\",\n        children: [],\n        attributes: {}\n      });\n    }\n    return HTMLResult.EMPTY;\n  }\n}\nclass Integer extends ContentObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"integer\");\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n  [$finalize]() {\n    const number = parseInt(this[$content].trim(), 10);\n    this[$content] = isNaN(number) ? null : number;\n  }\n  [$toHTML](availableSpace) {\n    return valueToHtml(this[$content] !== null ? this[$content].toString() : \"\");\n  }\n}\nclass Issuers extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"issuers\", true);\n    this.id = attributes.id || \"\";\n    this.type = getStringOption(attributes.type, [\"optional\", \"required\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.certificate = new XFAObjectArray();\n  }\n}\nclass Items extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"items\", true);\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.presence = getStringOption(attributes.presence, [\"visible\", \"hidden\", \"inactive\", \"invisible\"]);\n    this.ref = attributes.ref || \"\";\n    this.save = getInteger({\n      data: attributes.save,\n      defaultValue: 0,\n      validate: x => x === 1\n    });\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.boolean = new XFAObjectArray();\n    this.date = new XFAObjectArray();\n    this.dateTime = new XFAObjectArray();\n    this.decimal = new XFAObjectArray();\n    this.exData = new XFAObjectArray();\n    this.float = new XFAObjectArray();\n    this.image = new XFAObjectArray();\n    this.integer = new XFAObjectArray();\n    this.text = new XFAObjectArray();\n    this.time = new XFAObjectArray();\n  }\n  [$toHTML]() {\n    const output = [];\n    for (const child of this[$getChildren]()) {\n      output.push(child[$text]());\n    }\n    return HTMLResult.success(output);\n  }\n}\nclass Keep extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"keep\", true);\n    this.id = attributes.id || \"\";\n    const options = [\"none\", \"contentArea\", \"pageArea\"];\n    this.intact = getStringOption(attributes.intact, options);\n    this.next = getStringOption(attributes.next, options);\n    this.previous = getStringOption(attributes.previous, options);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.extras = null;\n  }\n}\nclass KeyUsage extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"keyUsage\");\n    const options = [\"\", \"yes\", \"no\"];\n    this.crlSign = getStringOption(attributes.crlSign, options);\n    this.dataEncipherment = getStringOption(attributes.dataEncipherment, options);\n    this.decipherOnly = getStringOption(attributes.decipherOnly, options);\n    this.digitalSignature = getStringOption(attributes.digitalSignature, options);\n    this.encipherOnly = getStringOption(attributes.encipherOnly, options);\n    this.id = attributes.id || \"\";\n    this.keyAgreement = getStringOption(attributes.keyAgreement, options);\n    this.keyCertSign = getStringOption(attributes.keyCertSign, options);\n    this.keyEncipherment = getStringOption(attributes.keyEncipherment, options);\n    this.nonRepudiation = getStringOption(attributes.nonRepudiation, options);\n    this.type = getStringOption(attributes.type, [\"optional\", \"required\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass Line extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"line\", true);\n    this.hand = getStringOption(attributes.hand, [\"even\", \"left\", \"right\"]);\n    this.id = attributes.id || \"\";\n    this.slope = getStringOption(attributes.slope, [\"\\\\\", \"/\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.edge = null;\n  }\n  [$toHTML]() {\n    const parent = this[$getParent]()[$getParent]();\n    const edge = this.edge || new Edge({});\n    const edgeStyle = edge[$toStyle]();\n    const style = Object.create(null);\n    const thickness = edge.presence === \"visible\" ? edge.thickness : 0;\n    style.strokeWidth = measureToString(thickness);\n    style.stroke = edgeStyle.color;\n    let x1, y1, x2, y2;\n    let width = \"100%\";\n    let height = \"100%\";\n    if (parent.w <= thickness) {\n      [x1, y1, x2, y2] = [\"50%\", 0, \"50%\", \"100%\"];\n      width = style.strokeWidth;\n    } else if (parent.h <= thickness) {\n      [x1, y1, x2, y2] = [0, \"50%\", \"100%\", \"50%\"];\n      height = style.strokeWidth;\n    } else if (this.slope === \"\\\\\") {\n      [x1, y1, x2, y2] = [0, 0, \"100%\", \"100%\"];\n    } else {\n      [x1, y1, x2, y2] = [0, \"100%\", \"100%\", 0];\n    }\n    const line = {\n      name: \"line\",\n      attributes: {\n        xmlns: SVG_NS,\n        x1,\n        y1,\n        x2,\n        y2,\n        style\n      }\n    };\n    const svg = {\n      name: \"svg\",\n      children: [line],\n      attributes: {\n        xmlns: SVG_NS,\n        width,\n        height,\n        style: {\n          overflow: \"visible\"\n        }\n      }\n    };\n    if (hasMargin(parent)) {\n      return HTMLResult.success({\n        name: \"div\",\n        attributes: {\n          style: {\n            display: \"inline\",\n            width: \"100%\",\n            height: \"100%\"\n          }\n        },\n        children: [svg]\n      });\n    }\n    svg.attributes.style.position = \"absolute\";\n    return HTMLResult.success(svg);\n  }\n}\nclass Linear extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"linear\", true);\n    this.id = attributes.id || \"\";\n    this.type = getStringOption(attributes.type, [\"toRight\", \"toBottom\", \"toLeft\", \"toTop\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.color = null;\n    this.extras = null;\n  }\n  [$toStyle](startColor) {\n    startColor = startColor ? startColor[$toStyle]() : \"#FFFFFF\";\n    const transf = this.type.replace(/([RBLT])/, \" $1\").toLowerCase();\n    const endColor = this.color ? this.color[$toStyle]() : \"#000000\";\n    return `linear-gradient(${transf}, ${startColor}, ${endColor})`;\n  }\n}\nclass LockDocument extends ContentObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"lockDocument\");\n    this.id = attributes.id || \"\";\n    this.type = getStringOption(attributes.type, [\"optional\", \"required\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n  [$finalize]() {\n    this[$content] = getStringOption(this[$content], [\"auto\", \"0\", \"1\"]);\n  }\n}\nclass Manifest extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"manifest\", true);\n    this.action = getStringOption(attributes.action, [\"include\", \"all\", \"exclude\"]);\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.extras = null;\n    this.ref = new XFAObjectArray();\n  }\n}\nclass Margin extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"margin\", true);\n    this.bottomInset = getMeasurement(attributes.bottomInset, \"0\");\n    this.id = attributes.id || \"\";\n    this.leftInset = getMeasurement(attributes.leftInset, \"0\");\n    this.rightInset = getMeasurement(attributes.rightInset, \"0\");\n    this.topInset = getMeasurement(attributes.topInset, \"0\");\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.extras = null;\n  }\n  [$toStyle]() {\n    return {\n      margin: measureToString(this.topInset) + \" \" + measureToString(this.rightInset) + \" \" + measureToString(this.bottomInset) + \" \" + measureToString(this.leftInset)\n    };\n  }\n}\nclass Mdp extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"mdp\");\n    this.id = attributes.id || \"\";\n    this.permissions = getInteger({\n      data: attributes.permissions,\n      defaultValue: 2,\n      validate: x => x === 1 || x === 3\n    });\n    this.signatureType = getStringOption(attributes.signatureType, [\"filler\", \"author\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass Medium extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"medium\");\n    this.id = attributes.id || \"\";\n    this.imagingBBox = getBBox(attributes.imagingBBox);\n    this.long = getMeasurement(attributes.long);\n    this.orientation = getStringOption(attributes.orientation, [\"portrait\", \"landscape\"]);\n    this.short = getMeasurement(attributes.short);\n    this.stock = attributes.stock || \"\";\n    this.trayIn = getStringOption(attributes.trayIn, [\"auto\", \"delegate\", \"pageFront\"]);\n    this.trayOut = getStringOption(attributes.trayOut, [\"auto\", \"delegate\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass Message extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"message\", true);\n    this.id = attributes.id || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.text = new XFAObjectArray();\n  }\n}\nclass NumericEdit extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"numericEdit\", true);\n    this.hScrollPolicy = getStringOption(attributes.hScrollPolicy, [\"auto\", \"off\", \"on\"]);\n    this.id = attributes.id || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.border = null;\n    this.comb = null;\n    this.extras = null;\n    this.margin = null;\n  }\n  [$toHTML](availableSpace) {\n    const style = toStyle(this, \"border\", \"font\", \"margin\");\n    const field = this[$getParent]()[$getParent]();\n    const html = {\n      name: \"input\",\n      attributes: {\n        type: \"text\",\n        fieldId: field[$uid],\n        dataId: field[$data]?.[$uid] || field[$uid],\n        class: [\"xfaTextfield\"],\n        style,\n        \"aria-label\": ariaLabel(field),\n        \"aria-required\": false\n      }\n    };\n    if (isRequired(field)) {\n      html.attributes[\"aria-required\"] = true;\n      html.attributes.required = true;\n    }\n    return HTMLResult.success({\n      name: \"label\",\n      attributes: {\n        class: [\"xfaLabel\"]\n      },\n      children: [html]\n    });\n  }\n}\nclass Occur extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"occur\", true);\n    this.id = attributes.id || \"\";\n    this.initial = attributes.initial !== \"\" ? getInteger({\n      data: attributes.initial,\n      defaultValue: \"\",\n      validate: x => true\n    }) : \"\";\n    this.max = attributes.max !== \"\" ? getInteger({\n      data: attributes.max,\n      defaultValue: 1,\n      validate: x => true\n    }) : \"\";\n    this.min = attributes.min !== \"\" ? getInteger({\n      data: attributes.min,\n      defaultValue: 1,\n      validate: x => true\n    }) : \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.extras = null;\n  }\n  [$clean]() {\n    const parent = this[$getParent]();\n    const originalMin = this.min;\n    if (this.min === \"\") {\n      this.min = parent instanceof PageArea || parent instanceof PageSet ? 0 : 1;\n    }\n    if (this.max === \"\") {\n      if (originalMin === \"\") {\n        this.max = parent instanceof PageArea || parent instanceof PageSet ? -1 : 1;\n      } else {\n        this.max = this.min;\n      }\n    }\n    if (this.max !== -1 && this.max < this.min) {\n      this.max = this.min;\n    }\n    if (this.initial === \"\") {\n      this.initial = parent instanceof Template ? 1 : this.min;\n    }\n  }\n}\nclass Oid extends StringObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"oid\");\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass Oids extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"oids\", true);\n    this.id = attributes.id || \"\";\n    this.type = getStringOption(attributes.type, [\"optional\", \"required\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.oid = new XFAObjectArray();\n  }\n}\nclass Overflow extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"overflow\");\n    this.id = attributes.id || \"\";\n    this.leader = attributes.leader || \"\";\n    this.target = attributes.target || \"\";\n    this.trailer = attributes.trailer || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n  [$getExtra]() {\n    if (!this[$extra]) {\n      const parent = this[$getParent]();\n      const root = this[$getTemplateRoot]();\n      const target = root[$searchNode](this.target, parent);\n      const leader = root[$searchNode](this.leader, parent);\n      const trailer = root[$searchNode](this.trailer, parent);\n      this[$extra] = {\n        target: target?.[0] || null,\n        leader: leader?.[0] || null,\n        trailer: trailer?.[0] || null,\n        addLeader: false,\n        addTrailer: false\n      };\n    }\n    return this[$extra];\n  }\n}\nclass PageArea extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"pageArea\", true);\n    this.blankOrNotBlank = getStringOption(attributes.blankOrNotBlank, [\"any\", \"blank\", \"notBlank\"]);\n    this.id = attributes.id || \"\";\n    this.initialNumber = getInteger({\n      data: attributes.initialNumber,\n      defaultValue: 1,\n      validate: x => true\n    });\n    this.name = attributes.name || \"\";\n    this.numbered = getInteger({\n      data: attributes.numbered,\n      defaultValue: 1,\n      validate: x => true\n    });\n    this.oddOrEven = getStringOption(attributes.oddOrEven, [\"any\", \"even\", \"odd\"]);\n    this.pagePosition = getStringOption(attributes.pagePosition, [\"any\", \"first\", \"last\", \"only\", \"rest\"]);\n    this.relevant = getRelevant(attributes.relevant);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.desc = null;\n    this.extras = null;\n    this.medium = null;\n    this.occur = null;\n    this.area = new XFAObjectArray();\n    this.contentArea = new XFAObjectArray();\n    this.draw = new XFAObjectArray();\n    this.exclGroup = new XFAObjectArray();\n    this.field = new XFAObjectArray();\n    this.subform = new XFAObjectArray();\n  }\n  [$isUsable]() {\n    if (!this[$extra]) {\n      this[$extra] = {\n        numberOfUse: 0\n      };\n      return true;\n    }\n    return !this.occur || this.occur.max === -1 || this[$extra].numberOfUse < this.occur.max;\n  }\n  [$cleanPage]() {\n    delete this[$extra];\n  }\n  [$getNextPage]() {\n    if (!this[$extra]) {\n      this[$extra] = {\n        numberOfUse: 0\n      };\n    }\n    const parent = this[$getParent]();\n    if (parent.relation === \"orderedOccurrence\") {\n      if (this[$isUsable]()) {\n        this[$extra].numberOfUse += 1;\n        return this;\n      }\n    }\n    return parent[$getNextPage]();\n  }\n  [$getAvailableSpace]() {\n    return this[$extra].space || {\n      width: 0,\n      height: 0\n    };\n  }\n  [$toHTML]() {\n    if (!this[$extra]) {\n      this[$extra] = {\n        numberOfUse: 1\n      };\n    }\n    const children = [];\n    this[$extra].children = children;\n    const style = Object.create(null);\n    if (this.medium && this.medium.short && this.medium.long) {\n      style.width = measureToString(this.medium.short);\n      style.height = measureToString(this.medium.long);\n      this[$extra].space = {\n        width: this.medium.short,\n        height: this.medium.long\n      };\n      if (this.medium.orientation === \"landscape\") {\n        const x = style.width;\n        style.width = style.height;\n        style.height = x;\n        this[$extra].space = {\n          width: this.medium.long,\n          height: this.medium.short\n        };\n      }\n    } else {\n      warn(\"XFA - No medium specified in pageArea: please file a bug.\");\n    }\n    this[$childrenToHTML]({\n      filter: new Set([\"area\", \"draw\", \"field\", \"subform\"]),\n      include: true\n    });\n    this[$childrenToHTML]({\n      filter: new Set([\"contentArea\"]),\n      include: true\n    });\n    return HTMLResult.success({\n      name: \"div\",\n      children,\n      attributes: {\n        class: [\"xfaPage\"],\n        id: this[$uid],\n        style,\n        xfaName: this.name\n      }\n    });\n  }\n}\nclass PageSet extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"pageSet\", true);\n    this.duplexImposition = getStringOption(attributes.duplexImposition, [\"longEdge\", \"shortEdge\"]);\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.relation = getStringOption(attributes.relation, [\"orderedOccurrence\", \"duplexPaginated\", \"simplexPaginated\"]);\n    this.relevant = getRelevant(attributes.relevant);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.extras = null;\n    this.occur = null;\n    this.pageArea = new XFAObjectArray();\n    this.pageSet = new XFAObjectArray();\n  }\n  [$cleanPage]() {\n    for (const page of this.pageArea.children) {\n      page[$cleanPage]();\n    }\n    for (const page of this.pageSet.children) {\n      page[$cleanPage]();\n    }\n  }\n  [$isUsable]() {\n    return !this.occur || this.occur.max === -1 || this[$extra].numberOfUse < this.occur.max;\n  }\n  [$getNextPage]() {\n    if (!this[$extra]) {\n      this[$extra] = {\n        numberOfUse: 1,\n        pageIndex: -1,\n        pageSetIndex: -1\n      };\n    }\n    if (this.relation === \"orderedOccurrence\") {\n      if (this[$extra].pageIndex + 1 < this.pageArea.children.length) {\n        this[$extra].pageIndex += 1;\n        const pageArea = this.pageArea.children[this[$extra].pageIndex];\n        return pageArea[$getNextPage]();\n      }\n      if (this[$extra].pageSetIndex + 1 < this.pageSet.children.length) {\n        this[$extra].pageSetIndex += 1;\n        return this.pageSet.children[this[$extra].pageSetIndex][$getNextPage]();\n      }\n      if (this[$isUsable]()) {\n        this[$extra].numberOfUse += 1;\n        this[$extra].pageIndex = -1;\n        this[$extra].pageSetIndex = -1;\n        return this[$getNextPage]();\n      }\n      const parent = this[$getParent]();\n      if (parent instanceof PageSet) {\n        return parent[$getNextPage]();\n      }\n      this[$cleanPage]();\n      return this[$getNextPage]();\n    }\n    const pageNumber = this[$getTemplateRoot]()[$extra].pageNumber;\n    const parity = pageNumber % 2 === 0 ? \"even\" : \"odd\";\n    const position = pageNumber === 0 ? \"first\" : \"rest\";\n    let page = this.pageArea.children.find(p => p.oddOrEven === parity && p.pagePosition === position);\n    if (page) {\n      return page;\n    }\n    page = this.pageArea.children.find(p => p.oddOrEven === \"any\" && p.pagePosition === position);\n    if (page) {\n      return page;\n    }\n    page = this.pageArea.children.find(p => p.oddOrEven === \"any\" && p.pagePosition === \"any\");\n    if (page) {\n      return page;\n    }\n    return this.pageArea.children[0];\n  }\n}\nclass Para extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"para\", true);\n    this.hAlign = getStringOption(attributes.hAlign, [\"left\", \"center\", \"justify\", \"justifyAll\", \"radix\", \"right\"]);\n    this.id = attributes.id || \"\";\n    this.lineHeight = attributes.lineHeight ? getMeasurement(attributes.lineHeight, \"0pt\") : \"\";\n    this.marginLeft = attributes.marginLeft ? getMeasurement(attributes.marginLeft, \"0pt\") : \"\";\n    this.marginRight = attributes.marginRight ? getMeasurement(attributes.marginRight, \"0pt\") : \"\";\n    this.orphans = getInteger({\n      data: attributes.orphans,\n      defaultValue: 0,\n      validate: x => x >= 0\n    });\n    this.preserve = attributes.preserve || \"\";\n    this.radixOffset = attributes.radixOffset ? getMeasurement(attributes.radixOffset, \"0pt\") : \"\";\n    this.spaceAbove = attributes.spaceAbove ? getMeasurement(attributes.spaceAbove, \"0pt\") : \"\";\n    this.spaceBelow = attributes.spaceBelow ? getMeasurement(attributes.spaceBelow, \"0pt\") : \"\";\n    this.tabDefault = attributes.tabDefault ? getMeasurement(this.tabDefault) : \"\";\n    this.tabStops = (attributes.tabStops || \"\").trim().split(/\\s+/).map((x, i) => i % 2 === 1 ? getMeasurement(x) : x);\n    this.textIndent = attributes.textIndent ? getMeasurement(attributes.textIndent, \"0pt\") : \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.vAlign = getStringOption(attributes.vAlign, [\"top\", \"bottom\", \"middle\"]);\n    this.widows = getInteger({\n      data: attributes.widows,\n      defaultValue: 0,\n      validate: x => x >= 0\n    });\n    this.hyphenation = null;\n  }\n  [$toStyle]() {\n    const style = toStyle(this, \"hAlign\");\n    if (this.marginLeft !== \"\") {\n      style.paddingLeft = measureToString(this.marginLeft);\n    }\n    if (this.marginRight !== \"\") {\n      style.paddingight = measureToString(this.marginRight);\n    }\n    if (this.spaceAbove !== \"\") {\n      style.paddingTop = measureToString(this.spaceAbove);\n    }\n    if (this.spaceBelow !== \"\") {\n      style.paddingBottom = measureToString(this.spaceBelow);\n    }\n    if (this.textIndent !== \"\") {\n      style.textIndent = measureToString(this.textIndent);\n      fixTextIndent(style);\n    }\n    if (this.lineHeight > 0) {\n      style.lineHeight = measureToString(this.lineHeight);\n    }\n    if (this.tabDefault !== \"\") {\n      style.tabSize = measureToString(this.tabDefault);\n    }\n    if (this.tabStops.length > 0) {}\n    if (this.hyphenatation) {\n      Object.assign(style, this.hyphenatation[$toStyle]());\n    }\n    return style;\n  }\n}\nclass PasswordEdit extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"passwordEdit\", true);\n    this.hScrollPolicy = getStringOption(attributes.hScrollPolicy, [\"auto\", \"off\", \"on\"]);\n    this.id = attributes.id || \"\";\n    this.passwordChar = attributes.passwordChar || \"*\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.border = null;\n    this.extras = null;\n    this.margin = null;\n  }\n}\nclass template_Pattern extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"pattern\", true);\n    this.id = attributes.id || \"\";\n    this.type = getStringOption(attributes.type, [\"crossHatch\", \"crossDiagonal\", \"diagonalLeft\", \"diagonalRight\", \"horizontal\", \"vertical\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.color = null;\n    this.extras = null;\n  }\n  [$toStyle](startColor) {\n    startColor = startColor ? startColor[$toStyle]() : \"#FFFFFF\";\n    const endColor = this.color ? this.color[$toStyle]() : \"#000000\";\n    const width = 5;\n    const cmd = \"repeating-linear-gradient\";\n    const colors = `${startColor},${startColor} ${width}px,${endColor} ${width}px,${endColor} ${2 * width}px`;\n    switch (this.type) {\n      case \"crossHatch\":\n        return `${cmd}(to top,${colors}) ${cmd}(to right,${colors})`;\n      case \"crossDiagonal\":\n        return `${cmd}(45deg,${colors}) ${cmd}(-45deg,${colors})`;\n      case \"diagonalLeft\":\n        return `${cmd}(45deg,${colors})`;\n      case \"diagonalRight\":\n        return `${cmd}(-45deg,${colors})`;\n      case \"horizontal\":\n        return `${cmd}(to top,${colors})`;\n      case \"vertical\":\n        return `${cmd}(to right,${colors})`;\n    }\n    return \"\";\n  }\n}\nclass Picture extends StringObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"picture\");\n    this.id = attributes.id || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass Proto extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"proto\", true);\n    this.appearanceFilter = new XFAObjectArray();\n    this.arc = new XFAObjectArray();\n    this.area = new XFAObjectArray();\n    this.assist = new XFAObjectArray();\n    this.barcode = new XFAObjectArray();\n    this.bindItems = new XFAObjectArray();\n    this.bookend = new XFAObjectArray();\n    this.boolean = new XFAObjectArray();\n    this.border = new XFAObjectArray();\n    this.break = new XFAObjectArray();\n    this.breakAfter = new XFAObjectArray();\n    this.breakBefore = new XFAObjectArray();\n    this.button = new XFAObjectArray();\n    this.calculate = new XFAObjectArray();\n    this.caption = new XFAObjectArray();\n    this.certificate = new XFAObjectArray();\n    this.certificates = new XFAObjectArray();\n    this.checkButton = new XFAObjectArray();\n    this.choiceList = new XFAObjectArray();\n    this.color = new XFAObjectArray();\n    this.comb = new XFAObjectArray();\n    this.connect = new XFAObjectArray();\n    this.contentArea = new XFAObjectArray();\n    this.corner = new XFAObjectArray();\n    this.date = new XFAObjectArray();\n    this.dateTime = new XFAObjectArray();\n    this.dateTimeEdit = new XFAObjectArray();\n    this.decimal = new XFAObjectArray();\n    this.defaultUi = new XFAObjectArray();\n    this.desc = new XFAObjectArray();\n    this.digestMethod = new XFAObjectArray();\n    this.digestMethods = new XFAObjectArray();\n    this.draw = new XFAObjectArray();\n    this.edge = new XFAObjectArray();\n    this.encoding = new XFAObjectArray();\n    this.encodings = new XFAObjectArray();\n    this.encrypt = new XFAObjectArray();\n    this.encryptData = new XFAObjectArray();\n    this.encryption = new XFAObjectArray();\n    this.encryptionMethod = new XFAObjectArray();\n    this.encryptionMethods = new XFAObjectArray();\n    this.event = new XFAObjectArray();\n    this.exData = new XFAObjectArray();\n    this.exObject = new XFAObjectArray();\n    this.exclGroup = new XFAObjectArray();\n    this.execute = new XFAObjectArray();\n    this.extras = new XFAObjectArray();\n    this.field = new XFAObjectArray();\n    this.fill = new XFAObjectArray();\n    this.filter = new XFAObjectArray();\n    this.float = new XFAObjectArray();\n    this.font = new XFAObjectArray();\n    this.format = new XFAObjectArray();\n    this.handler = new XFAObjectArray();\n    this.hyphenation = new XFAObjectArray();\n    this.image = new XFAObjectArray();\n    this.imageEdit = new XFAObjectArray();\n    this.integer = new XFAObjectArray();\n    this.issuers = new XFAObjectArray();\n    this.items = new XFAObjectArray();\n    this.keep = new XFAObjectArray();\n    this.keyUsage = new XFAObjectArray();\n    this.line = new XFAObjectArray();\n    this.linear = new XFAObjectArray();\n    this.lockDocument = new XFAObjectArray();\n    this.manifest = new XFAObjectArray();\n    this.margin = new XFAObjectArray();\n    this.mdp = new XFAObjectArray();\n    this.medium = new XFAObjectArray();\n    this.message = new XFAObjectArray();\n    this.numericEdit = new XFAObjectArray();\n    this.occur = new XFAObjectArray();\n    this.oid = new XFAObjectArray();\n    this.oids = new XFAObjectArray();\n    this.overflow = new XFAObjectArray();\n    this.pageArea = new XFAObjectArray();\n    this.pageSet = new XFAObjectArray();\n    this.para = new XFAObjectArray();\n    this.passwordEdit = new XFAObjectArray();\n    this.pattern = new XFAObjectArray();\n    this.picture = new XFAObjectArray();\n    this.radial = new XFAObjectArray();\n    this.reason = new XFAObjectArray();\n    this.reasons = new XFAObjectArray();\n    this.rectangle = new XFAObjectArray();\n    this.ref = new XFAObjectArray();\n    this.script = new XFAObjectArray();\n    this.setProperty = new XFAObjectArray();\n    this.signData = new XFAObjectArray();\n    this.signature = new XFAObjectArray();\n    this.signing = new XFAObjectArray();\n    this.solid = new XFAObjectArray();\n    this.speak = new XFAObjectArray();\n    this.stipple = new XFAObjectArray();\n    this.subform = new XFAObjectArray();\n    this.subformSet = new XFAObjectArray();\n    this.subjectDN = new XFAObjectArray();\n    this.subjectDNs = new XFAObjectArray();\n    this.submit = new XFAObjectArray();\n    this.text = new XFAObjectArray();\n    this.textEdit = new XFAObjectArray();\n    this.time = new XFAObjectArray();\n    this.timeStamp = new XFAObjectArray();\n    this.toolTip = new XFAObjectArray();\n    this.traversal = new XFAObjectArray();\n    this.traverse = new XFAObjectArray();\n    this.ui = new XFAObjectArray();\n    this.validate = new XFAObjectArray();\n    this.value = new XFAObjectArray();\n    this.variables = new XFAObjectArray();\n  }\n}\nclass Radial extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"radial\", true);\n    this.id = attributes.id || \"\";\n    this.type = getStringOption(attributes.type, [\"toEdge\", \"toCenter\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.color = null;\n    this.extras = null;\n  }\n  [$toStyle](startColor) {\n    startColor = startColor ? startColor[$toStyle]() : \"#FFFFFF\";\n    const endColor = this.color ? this.color[$toStyle]() : \"#000000\";\n    const colors = this.type === \"toEdge\" ? `${startColor},${endColor}` : `${endColor},${startColor}`;\n    return `radial-gradient(circle at center, ${colors})`;\n  }\n}\nclass Reason extends StringObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"reason\");\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass Reasons extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"reasons\", true);\n    this.id = attributes.id || \"\";\n    this.type = getStringOption(attributes.type, [\"optional\", \"required\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.reason = new XFAObjectArray();\n  }\n}\nclass Rectangle extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"rectangle\", true);\n    this.hand = getStringOption(attributes.hand, [\"even\", \"left\", \"right\"]);\n    this.id = attributes.id || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.corner = new XFAObjectArray(4);\n    this.edge = new XFAObjectArray(4);\n    this.fill = null;\n  }\n  [$toHTML]() {\n    const edge = this.edge.children.length ? this.edge.children[0] : new Edge({});\n    const edgeStyle = edge[$toStyle]();\n    const style = Object.create(null);\n    if (this.fill?.presence === \"visible\") {\n      Object.assign(style, this.fill[$toStyle]());\n    } else {\n      style.fill = \"transparent\";\n    }\n    style.strokeWidth = measureToString(edge.presence === \"visible\" ? edge.thickness : 0);\n    style.stroke = edgeStyle.color;\n    const corner = this.corner.children.length ? this.corner.children[0] : new Corner({});\n    const cornerStyle = corner[$toStyle]();\n    const rect = {\n      name: \"rect\",\n      attributes: {\n        xmlns: SVG_NS,\n        width: \"100%\",\n        height: \"100%\",\n        x: 0,\n        y: 0,\n        rx: cornerStyle.radius,\n        ry: cornerStyle.radius,\n        style\n      }\n    };\n    const svg = {\n      name: \"svg\",\n      children: [rect],\n      attributes: {\n        xmlns: SVG_NS,\n        style: {\n          overflow: \"visible\"\n        },\n        width: \"100%\",\n        height: \"100%\"\n      }\n    };\n    const parent = this[$getParent]()[$getParent]();\n    if (hasMargin(parent)) {\n      return HTMLResult.success({\n        name: \"div\",\n        attributes: {\n          style: {\n            display: \"inline\",\n            width: \"100%\",\n            height: \"100%\"\n          }\n        },\n        children: [svg]\n      });\n    }\n    svg.attributes.style.position = \"absolute\";\n    return HTMLResult.success(svg);\n  }\n}\nclass RefElement extends StringObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"ref\");\n    this.id = attributes.id || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass Script extends StringObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"script\");\n    this.binding = attributes.binding || \"\";\n    this.contentType = attributes.contentType || \"\";\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.runAt = getStringOption(attributes.runAt, [\"client\", \"both\", \"server\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass SetProperty extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"setProperty\");\n    this.connection = attributes.connection || \"\";\n    this.ref = attributes.ref || \"\";\n    this.target = attributes.target || \"\";\n  }\n}\nclass SignData extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"signData\", true);\n    this.id = attributes.id || \"\";\n    this.operation = getStringOption(attributes.operation, [\"sign\", \"clear\", \"verify\"]);\n    this.ref = attributes.ref || \"\";\n    this.target = attributes.target || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.filter = null;\n    this.manifest = null;\n  }\n}\nclass Signature extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"signature\", true);\n    this.id = attributes.id || \"\";\n    this.type = getStringOption(attributes.type, [\"PDF1.3\", \"PDF1.6\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.border = null;\n    this.extras = null;\n    this.filter = null;\n    this.manifest = null;\n    this.margin = null;\n  }\n}\nclass Signing extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"signing\", true);\n    this.id = attributes.id || \"\";\n    this.type = getStringOption(attributes.type, [\"optional\", \"required\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.certificate = new XFAObjectArray();\n  }\n}\nclass Solid extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"solid\", true);\n    this.id = attributes.id || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.extras = null;\n  }\n  [$toStyle](startColor) {\n    return startColor ? startColor[$toStyle]() : \"#FFFFFF\";\n  }\n}\nclass Speak extends StringObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"speak\");\n    this.disable = getInteger({\n      data: attributes.disable,\n      defaultValue: 0,\n      validate: x => x === 1\n    });\n    this.id = attributes.id || \"\";\n    this.priority = getStringOption(attributes.priority, [\"custom\", \"caption\", \"name\", \"toolTip\"]);\n    this.rid = attributes.rid || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass Stipple extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"stipple\", true);\n    this.id = attributes.id || \"\";\n    this.rate = getInteger({\n      data: attributes.rate,\n      defaultValue: 50,\n      validate: x => x >= 0 && x <= 100\n    });\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.color = null;\n    this.extras = null;\n  }\n  [$toStyle](bgColor) {\n    const alpha = this.rate / 100;\n    return Util.makeHexColor(Math.round(bgColor.value.r * (1 - alpha) + this.value.r * alpha), Math.round(bgColor.value.g * (1 - alpha) + this.value.g * alpha), Math.round(bgColor.value.b * (1 - alpha) + this.value.b * alpha));\n  }\n}\nclass Subform extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"subform\", true);\n    this.access = getStringOption(attributes.access, [\"open\", \"nonInteractive\", \"protected\", \"readOnly\"]);\n    this.allowMacro = getInteger({\n      data: attributes.allowMacro,\n      defaultValue: 0,\n      validate: x => x === 1\n    });\n    this.anchorType = getStringOption(attributes.anchorType, [\"topLeft\", \"bottomCenter\", \"bottomLeft\", \"bottomRight\", \"middleCenter\", \"middleLeft\", \"middleRight\", \"topCenter\", \"topRight\"]);\n    this.colSpan = getInteger({\n      data: attributes.colSpan,\n      defaultValue: 1,\n      validate: n => n >= 1 || n === -1\n    });\n    this.columnWidths = (attributes.columnWidths || \"\").trim().split(/\\s+/).map(x => x === \"-1\" ? -1 : getMeasurement(x));\n    this.h = attributes.h ? getMeasurement(attributes.h) : \"\";\n    this.hAlign = getStringOption(attributes.hAlign, [\"left\", \"center\", \"justify\", \"justifyAll\", \"radix\", \"right\"]);\n    this.id = attributes.id || \"\";\n    this.layout = getStringOption(attributes.layout, [\"position\", \"lr-tb\", \"rl-row\", \"rl-tb\", \"row\", \"table\", \"tb\"]);\n    this.locale = attributes.locale || \"\";\n    this.maxH = getMeasurement(attributes.maxH, \"0pt\");\n    this.maxW = getMeasurement(attributes.maxW, \"0pt\");\n    this.mergeMode = getStringOption(attributes.mergeMode, [\"consumeData\", \"matchTemplate\"]);\n    this.minH = getMeasurement(attributes.minH, \"0pt\");\n    this.minW = getMeasurement(attributes.minW, \"0pt\");\n    this.name = attributes.name || \"\";\n    this.presence = getStringOption(attributes.presence, [\"visible\", \"hidden\", \"inactive\", \"invisible\"]);\n    this.relevant = getRelevant(attributes.relevant);\n    this.restoreState = getStringOption(attributes.restoreState, [\"manual\", \"auto\"]);\n    this.scope = getStringOption(attributes.scope, [\"name\", \"none\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.w = attributes.w ? getMeasurement(attributes.w) : \"\";\n    this.x = getMeasurement(attributes.x, \"0pt\");\n    this.y = getMeasurement(attributes.y, \"0pt\");\n    this.assist = null;\n    this.bind = null;\n    this.bookend = null;\n    this.border = null;\n    this.break = null;\n    this.calculate = null;\n    this.desc = null;\n    this.extras = null;\n    this.keep = null;\n    this.margin = null;\n    this.occur = null;\n    this.overflow = null;\n    this.pageSet = null;\n    this.para = null;\n    this.traversal = null;\n    this.validate = null;\n    this.variables = null;\n    this.area = new XFAObjectArray();\n    this.breakAfter = new XFAObjectArray();\n    this.breakBefore = new XFAObjectArray();\n    this.connect = new XFAObjectArray();\n    this.draw = new XFAObjectArray();\n    this.event = new XFAObjectArray();\n    this.exObject = new XFAObjectArray();\n    this.exclGroup = new XFAObjectArray();\n    this.field = new XFAObjectArray();\n    this.proto = new XFAObjectArray();\n    this.setProperty = new XFAObjectArray();\n    this.subform = new XFAObjectArray();\n    this.subformSet = new XFAObjectArray();\n  }\n  [$getSubformParent]() {\n    const parent = this[$getParent]();\n    if (parent instanceof SubformSet) {\n      return parent[$getSubformParent]();\n    }\n    return parent;\n  }\n  [$isBindable]() {\n    return true;\n  }\n  [$isThereMoreWidth]() {\n    return this.layout.endsWith(\"-tb\") && this[$extra].attempt === 0 && this[$extra].numberInLine > 0 || this[$getParent]()[$isThereMoreWidth]();\n  }\n  *[$getContainedChildren]() {\n    yield* getContainedChildren(this);\n  }\n  [$flushHTML]() {\n    return flushHTML(this);\n  }\n  [$addHTML](html, bbox) {\n    addHTML(this, html, bbox);\n  }\n  [$getAvailableSpace]() {\n    return getAvailableSpace(this);\n  }\n  [$isSplittable]() {\n    const parent = this[$getSubformParent]();\n    if (!parent[$isSplittable]()) {\n      return false;\n    }\n    if (this[$extra]._isSplittable !== undefined) {\n      return this[$extra]._isSplittable;\n    }\n    if (this.layout === \"position\" || this.layout.includes(\"row\")) {\n      this[$extra]._isSplittable = false;\n      return false;\n    }\n    if (this.keep && this.keep.intact !== \"none\") {\n      this[$extra]._isSplittable = false;\n      return false;\n    }\n    if (parent.layout?.endsWith(\"-tb\") && parent[$extra].numberInLine !== 0) {\n      return false;\n    }\n    this[$extra]._isSplittable = true;\n    return true;\n  }\n  [$toHTML](availableSpace) {\n    setTabIndex(this);\n    if (this.break) {\n      if (this.break.after !== \"auto\" || this.break.afterTarget !== \"\") {\n        const node = new BreakAfter({\n          targetType: this.break.after,\n          target: this.break.afterTarget,\n          startNew: this.break.startNew.toString()\n        });\n        node[$globalData] = this[$globalData];\n        this[$appendChild](node);\n        this.breakAfter.push(node);\n      }\n      if (this.break.before !== \"auto\" || this.break.beforeTarget !== \"\") {\n        const node = new BreakBefore({\n          targetType: this.break.before,\n          target: this.break.beforeTarget,\n          startNew: this.break.startNew.toString()\n        });\n        node[$globalData] = this[$globalData];\n        this[$appendChild](node);\n        this.breakBefore.push(node);\n      }\n      if (this.break.overflowTarget !== \"\") {\n        const node = new Overflow({\n          target: this.break.overflowTarget,\n          leader: this.break.overflowLeader,\n          trailer: this.break.overflowTrailer\n        });\n        node[$globalData] = this[$globalData];\n        this[$appendChild](node);\n        this.overflow.push(node);\n      }\n      this[$removeChild](this.break);\n      this.break = null;\n    }\n    if (this.presence === \"hidden\" || this.presence === \"inactive\") {\n      return HTMLResult.EMPTY;\n    }\n    if (this.breakBefore.children.length > 1 || this.breakAfter.children.length > 1) {\n      warn(\"XFA - Several breakBefore or breakAfter in subforms: please file a bug.\");\n    }\n    if (this.breakBefore.children.length >= 1) {\n      const breakBefore = this.breakBefore.children[0];\n      if (handleBreak(breakBefore)) {\n        return HTMLResult.breakNode(breakBefore);\n      }\n    }\n    if (this[$extra]?.afterBreakAfter) {\n      return HTMLResult.EMPTY;\n    }\n    fixDimensions(this);\n    const children = [];\n    const attributes = {\n      id: this[$uid],\n      class: []\n    };\n    setAccess(this, attributes.class);\n    if (!this[$extra]) {\n      this[$extra] = Object.create(null);\n    }\n    Object.assign(this[$extra], {\n      children,\n      line: null,\n      attributes,\n      attempt: 0,\n      numberInLine: 0,\n      availableSpace: {\n        width: Math.min(this.w || Infinity, availableSpace.width),\n        height: Math.min(this.h || Infinity, availableSpace.height)\n      },\n      width: 0,\n      height: 0,\n      prevHeight: 0,\n      currentWidth: 0\n    });\n    const root = this[$getTemplateRoot]();\n    const savedNoLayoutFailure = root[$extra].noLayoutFailure;\n    const isSplittable = this[$isSplittable]();\n    if (!isSplittable) {\n      setFirstUnsplittable(this);\n    }\n    if (!checkDimensions(this, availableSpace)) {\n      return HTMLResult.FAILURE;\n    }\n    const filter = new Set([\"area\", \"draw\", \"exclGroup\", \"field\", \"subform\", \"subformSet\"]);\n    if (this.layout.includes(\"row\")) {\n      const columnWidths = this[$getSubformParent]().columnWidths;\n      if (Array.isArray(columnWidths) && columnWidths.length > 0) {\n        this[$extra].columnWidths = columnWidths;\n        this[$extra].currentColumn = 0;\n      }\n    }\n    const style = toStyle(this, \"anchorType\", \"dimensions\", \"position\", \"presence\", \"border\", \"margin\", \"hAlign\");\n    const classNames = [\"xfaSubform\"];\n    const cl = layoutClass(this);\n    if (cl) {\n      classNames.push(cl);\n    }\n    attributes.style = style;\n    attributes.class = classNames;\n    if (this.name) {\n      attributes.xfaName = this.name;\n    }\n    if (this.overflow) {\n      const overflowExtra = this.overflow[$getExtra]();\n      if (overflowExtra.addLeader) {\n        overflowExtra.addLeader = false;\n        handleOverflow(this, overflowExtra.leader, availableSpace);\n      }\n    }\n    this[$pushPara]();\n    const isLrTb = this.layout === \"lr-tb\" || this.layout === \"rl-tb\";\n    const maxRun = isLrTb ? MAX_ATTEMPTS_FOR_LRTB_LAYOUT : 1;\n    for (; this[$extra].attempt < maxRun; this[$extra].attempt++) {\n      if (isLrTb && this[$extra].attempt === MAX_ATTEMPTS_FOR_LRTB_LAYOUT - 1) {\n        this[$extra].numberInLine = 0;\n      }\n      const result = this[$childrenToHTML]({\n        filter,\n        include: true\n      });\n      if (result.success) {\n        break;\n      }\n      if (result.isBreak()) {\n        this[$popPara]();\n        return result;\n      }\n      if (isLrTb && this[$extra].attempt === 0 && this[$extra].numberInLine === 0 && !root[$extra].noLayoutFailure) {\n        this[$extra].attempt = maxRun;\n        break;\n      }\n    }\n    this[$popPara]();\n    if (!isSplittable) {\n      unsetFirstUnsplittable(this);\n    }\n    root[$extra].noLayoutFailure = savedNoLayoutFailure;\n    if (this[$extra].attempt === maxRun) {\n      if (this.overflow) {\n        this[$getTemplateRoot]()[$extra].overflowNode = this.overflow;\n      }\n      if (!isSplittable) {\n        delete this[$extra];\n      }\n      return HTMLResult.FAILURE;\n    }\n    if (this.overflow) {\n      const overflowExtra = this.overflow[$getExtra]();\n      if (overflowExtra.addTrailer) {\n        overflowExtra.addTrailer = false;\n        handleOverflow(this, overflowExtra.trailer, availableSpace);\n      }\n    }\n    let marginH = 0;\n    let marginV = 0;\n    if (this.margin) {\n      marginH = this.margin.leftInset + this.margin.rightInset;\n      marginV = this.margin.topInset + this.margin.bottomInset;\n    }\n    const width = Math.max(this[$extra].width + marginH, this.w || 0);\n    const height = Math.max(this[$extra].height + marginV, this.h || 0);\n    const bbox = [this.x, this.y, width, height];\n    if (this.w === \"\") {\n      style.width = measureToString(width);\n    }\n    if (this.h === \"\") {\n      style.height = measureToString(height);\n    }\n    if ((style.width === \"0px\" || style.height === \"0px\") && children.length === 0) {\n      return HTMLResult.EMPTY;\n    }\n    const html = {\n      name: \"div\",\n      attributes,\n      children\n    };\n    applyAssist(this, attributes);\n    const result = HTMLResult.success(createWrapper(this, html), bbox);\n    if (this.breakAfter.children.length >= 1) {\n      const breakAfter = this.breakAfter.children[0];\n      if (handleBreak(breakAfter)) {\n        this[$extra].afterBreakAfter = result;\n        return HTMLResult.breakNode(breakAfter);\n      }\n    }\n    delete this[$extra];\n    return result;\n  }\n}\nclass SubformSet extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"subformSet\", true);\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.relation = getStringOption(attributes.relation, [\"ordered\", \"choice\", \"unordered\"]);\n    this.relevant = getRelevant(attributes.relevant);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.bookend = null;\n    this.break = null;\n    this.desc = null;\n    this.extras = null;\n    this.occur = null;\n    this.overflow = null;\n    this.breakAfter = new XFAObjectArray();\n    this.breakBefore = new XFAObjectArray();\n    this.subform = new XFAObjectArray();\n    this.subformSet = new XFAObjectArray();\n  }\n  *[$getContainedChildren]() {\n    yield* getContainedChildren(this);\n  }\n  [$getSubformParent]() {\n    let parent = this[$getParent]();\n    while (!(parent instanceof Subform)) {\n      parent = parent[$getParent]();\n    }\n    return parent;\n  }\n  [$isBindable]() {\n    return true;\n  }\n}\nclass SubjectDN extends ContentObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"subjectDN\");\n    this.delimiter = attributes.delimiter || \",\";\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n  [$finalize]() {\n    this[$content] = new Map(this[$content].split(this.delimiter).map(kv => {\n      kv = kv.split(\"=\", 2);\n      kv[0] = kv[0].trim();\n      return kv;\n    }));\n  }\n}\nclass SubjectDNs extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"subjectDNs\", true);\n    this.id = attributes.id || \"\";\n    this.type = getStringOption(attributes.type, [\"optional\", \"required\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.subjectDN = new XFAObjectArray();\n  }\n}\nclass Submit extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"submit\", true);\n    this.embedPDF = getInteger({\n      data: attributes.embedPDF,\n      defaultValue: 0,\n      validate: x => x === 1\n    });\n    this.format = getStringOption(attributes.format, [\"xdp\", \"formdata\", \"pdf\", \"urlencoded\", \"xfd\", \"xml\"]);\n    this.id = attributes.id || \"\";\n    this.target = attributes.target || \"\";\n    this.textEncoding = getKeyword({\n      data: attributes.textEncoding ? attributes.textEncoding.toLowerCase() : \"\",\n      defaultValue: \"\",\n      validate: k => [\"utf-8\", \"big-five\", \"fontspecific\", \"gbk\", \"gb-18030\", \"gb-2312\", \"ksc-5601\", \"none\", \"shift-jis\", \"ucs-2\", \"utf-16\"].includes(k) || k.match(/iso-8859-\\d{2}/)\n    });\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.xdpContent = attributes.xdpContent || \"\";\n    this.encrypt = null;\n    this.encryptData = new XFAObjectArray();\n    this.signData = new XFAObjectArray();\n  }\n}\nclass Template extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"template\", true);\n    this.baseProfile = getStringOption(attributes.baseProfile, [\"full\", \"interactiveForms\"]);\n    this.extras = null;\n    this.subform = new XFAObjectArray();\n  }\n  [$finalize]() {\n    if (this.subform.children.length === 0) {\n      warn(\"XFA - No subforms in template node.\");\n    }\n    if (this.subform.children.length >= 2) {\n      warn(\"XFA - Several subforms in template node: please file a bug.\");\n    }\n    this[$tabIndex] = DEFAULT_TAB_INDEX;\n  }\n  [$isSplittable]() {\n    return true;\n  }\n  [$searchNode](expr, container) {\n    if (expr.startsWith(\"#\")) {\n      return [this[$ids].get(expr.slice(1))];\n    }\n    return searchNode(this, container, expr, true, true);\n  }\n  *[$toPages]() {\n    if (!this.subform.children.length) {\n      return HTMLResult.success({\n        name: \"div\",\n        children: []\n      });\n    }\n    this[$extra] = {\n      overflowNode: null,\n      firstUnsplittable: null,\n      currentContentArea: null,\n      currentPageArea: null,\n      noLayoutFailure: false,\n      pageNumber: 1,\n      pagePosition: \"first\",\n      oddOrEven: \"odd\",\n      blankOrNotBlank: \"nonBlank\",\n      paraStack: []\n    };\n    const root = this.subform.children[0];\n    root.pageSet[$cleanPage]();\n    const pageAreas = root.pageSet.pageArea.children;\n    const mainHtml = {\n      name: \"div\",\n      children: []\n    };\n    let pageArea = null;\n    let breakBefore = null;\n    let breakBeforeTarget = null;\n    if (root.breakBefore.children.length >= 1) {\n      breakBefore = root.breakBefore.children[0];\n      breakBeforeTarget = breakBefore.target;\n    } else if (root.subform.children.length >= 1 && root.subform.children[0].breakBefore.children.length >= 1) {\n      breakBefore = root.subform.children[0].breakBefore.children[0];\n      breakBeforeTarget = breakBefore.target;\n    } else if (root.break?.beforeTarget) {\n      breakBefore = root.break;\n      breakBeforeTarget = breakBefore.beforeTarget;\n    } else if (root.subform.children.length >= 1 && root.subform.children[0].break?.beforeTarget) {\n      breakBefore = root.subform.children[0].break;\n      breakBeforeTarget = breakBefore.beforeTarget;\n    }\n    if (breakBefore) {\n      const target = this[$searchNode](breakBeforeTarget, breakBefore[$getParent]());\n      if (target instanceof PageArea) {\n        pageArea = target;\n        breakBefore[$extra] = {};\n      }\n    }\n    if (!pageArea) {\n      pageArea = pageAreas[0];\n    }\n    pageArea[$extra] = {\n      numberOfUse: 1\n    };\n    const pageAreaParent = pageArea[$getParent]();\n    pageAreaParent[$extra] = {\n      numberOfUse: 1,\n      pageIndex: pageAreaParent.pageArea.children.indexOf(pageArea),\n      pageSetIndex: 0\n    };\n    let targetPageArea;\n    let leader = null;\n    let trailer = null;\n    let hasSomething = true;\n    let hasSomethingCounter = 0;\n    let startIndex = 0;\n    while (true) {\n      if (!hasSomething) {\n        mainHtml.children.pop();\n        if (++hasSomethingCounter === MAX_EMPTY_PAGES) {\n          warn(\"XFA - Something goes wrong: please file a bug.\");\n          return mainHtml;\n        }\n      } else {\n        hasSomethingCounter = 0;\n      }\n      targetPageArea = null;\n      this[$extra].currentPageArea = pageArea;\n      const page = pageArea[$toHTML]().html;\n      mainHtml.children.push(page);\n      if (leader) {\n        this[$extra].noLayoutFailure = true;\n        page.children.push(leader[$toHTML](pageArea[$extra].space).html);\n        leader = null;\n      }\n      if (trailer) {\n        this[$extra].noLayoutFailure = true;\n        page.children.push(trailer[$toHTML](pageArea[$extra].space).html);\n        trailer = null;\n      }\n      const contentAreas = pageArea.contentArea.children;\n      const htmlContentAreas = page.children.filter(node => node.attributes.class.includes(\"xfaContentarea\"));\n      hasSomething = false;\n      this[$extra].firstUnsplittable = null;\n      this[$extra].noLayoutFailure = false;\n      const flush = index => {\n        const html = root[$flushHTML]();\n        if (html) {\n          hasSomething ||= html.children?.length > 0;\n          htmlContentAreas[index].children.push(html);\n        }\n      };\n      for (let i = startIndex, ii = contentAreas.length; i < ii; i++) {\n        const contentArea = this[$extra].currentContentArea = contentAreas[i];\n        const space = {\n          width: contentArea.w,\n          height: contentArea.h\n        };\n        startIndex = 0;\n        if (leader) {\n          htmlContentAreas[i].children.push(leader[$toHTML](space).html);\n          leader = null;\n        }\n        if (trailer) {\n          htmlContentAreas[i].children.push(trailer[$toHTML](space).html);\n          trailer = null;\n        }\n        const html = root[$toHTML](space);\n        if (html.success) {\n          if (html.html) {\n            hasSomething ||= html.html.children?.length > 0;\n            htmlContentAreas[i].children.push(html.html);\n          } else if (!hasSomething && mainHtml.children.length > 1) {\n            mainHtml.children.pop();\n          }\n          return mainHtml;\n        }\n        if (html.isBreak()) {\n          const node = html.breakNode;\n          flush(i);\n          if (node.targetType === \"auto\") {\n            continue;\n          }\n          if (node.leader) {\n            leader = this[$searchNode](node.leader, node[$getParent]());\n            leader = leader ? leader[0] : null;\n          }\n          if (node.trailer) {\n            trailer = this[$searchNode](node.trailer, node[$getParent]());\n            trailer = trailer ? trailer[0] : null;\n          }\n          if (node.targetType === \"pageArea\") {\n            targetPageArea = node[$extra].target;\n            i = Infinity;\n          } else if (!node[$extra].target) {\n            i = node[$extra].index;\n          } else {\n            targetPageArea = node[$extra].target;\n            startIndex = node[$extra].index + 1;\n            i = Infinity;\n          }\n          continue;\n        }\n        if (this[$extra].overflowNode) {\n          const node = this[$extra].overflowNode;\n          this[$extra].overflowNode = null;\n          const overflowExtra = node[$getExtra]();\n          const target = overflowExtra.target;\n          overflowExtra.addLeader = overflowExtra.leader !== null;\n          overflowExtra.addTrailer = overflowExtra.trailer !== null;\n          flush(i);\n          const currentIndex = i;\n          i = Infinity;\n          if (target instanceof PageArea) {\n            targetPageArea = target;\n          } else if (target instanceof ContentArea) {\n            const index = contentAreas.indexOf(target);\n            if (index !== -1) {\n              if (index > currentIndex) {\n                i = index - 1;\n              } else {\n                startIndex = index;\n              }\n            } else {\n              targetPageArea = target[$getParent]();\n              startIndex = targetPageArea.contentArea.children.indexOf(target);\n            }\n          }\n          continue;\n        }\n        flush(i);\n      }\n      this[$extra].pageNumber += 1;\n      if (targetPageArea) {\n        if (targetPageArea[$isUsable]()) {\n          targetPageArea[$extra].numberOfUse += 1;\n        } else {\n          targetPageArea = null;\n        }\n      }\n      pageArea = targetPageArea || pageArea[$getNextPage]();\n      yield null;\n    }\n  }\n}\nclass Text extends ContentObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"text\");\n    this.id = attributes.id || \"\";\n    this.maxChars = getInteger({\n      data: attributes.maxChars,\n      defaultValue: 0,\n      validate: x => x >= 0\n    });\n    this.name = attributes.name || \"\";\n    this.rid = attributes.rid || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n  [$acceptWhitespace]() {\n    return true;\n  }\n  [$onChild](child) {\n    if (child[$namespaceId] === NamespaceIds.xhtml.id) {\n      this[$content] = child;\n      return true;\n    }\n    warn(`XFA - Invalid content in Text: ${child[$nodeName]}.`);\n    return false;\n  }\n  [$onText](str) {\n    if (this[$content] instanceof XFAObject) {\n      return;\n    }\n    super[$onText](str);\n  }\n  [$finalize]() {\n    if (typeof this[$content] === \"string\") {\n      this[$content] = this[$content].replaceAll(\"\\r\\n\", \"\\n\");\n    }\n  }\n  [$getExtra]() {\n    if (typeof this[$content] === \"string\") {\n      return this[$content].split(/[\\u2029\\u2028\\n]/).reduce((acc, line) => {\n        if (line) {\n          acc.push(line);\n        }\n        return acc;\n      }, []).join(\"\\n\");\n    }\n    return this[$content][$text]();\n  }\n  [$toHTML](availableSpace) {\n    if (typeof this[$content] === \"string\") {\n      const html = valueToHtml(this[$content]).html;\n      if (this[$content].includes(\"\\u2029\")) {\n        html.name = \"div\";\n        html.children = [];\n        this[$content].split(\"\\u2029\").map(para => para.split(/[\\u2028\\n]/).reduce((acc, line) => {\n          acc.push({\n            name: \"span\",\n            value: line\n          }, {\n            name: \"br\"\n          });\n          return acc;\n        }, [])).forEach(lines => {\n          html.children.push({\n            name: \"p\",\n            children: lines\n          });\n        });\n      } else if (/[\\u2028\\n]/.test(this[$content])) {\n        html.name = \"div\";\n        html.children = [];\n        this[$content].split(/[\\u2028\\n]/).forEach(line => {\n          html.children.push({\n            name: \"span\",\n            value: line\n          }, {\n            name: \"br\"\n          });\n        });\n      }\n      return HTMLResult.success(html);\n    }\n    return this[$content][$toHTML](availableSpace);\n  }\n}\nclass TextEdit extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"textEdit\", true);\n    this.allowRichText = getInteger({\n      data: attributes.allowRichText,\n      defaultValue: 0,\n      validate: x => x === 1\n    });\n    this.hScrollPolicy = getStringOption(attributes.hScrollPolicy, [\"auto\", \"off\", \"on\"]);\n    this.id = attributes.id || \"\";\n    this.multiLine = getInteger({\n      data: attributes.multiLine,\n      defaultValue: \"\",\n      validate: x => x === 0 || x === 1\n    });\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.vScrollPolicy = getStringOption(attributes.vScrollPolicy, [\"auto\", \"off\", \"on\"]);\n    this.border = null;\n    this.comb = null;\n    this.extras = null;\n    this.margin = null;\n  }\n  [$toHTML](availableSpace) {\n    const style = toStyle(this, \"border\", \"font\", \"margin\");\n    let html;\n    const field = this[$getParent]()[$getParent]();\n    if (this.multiLine === \"\") {\n      this.multiLine = field instanceof Draw ? 1 : 0;\n    }\n    if (this.multiLine === 1) {\n      html = {\n        name: \"textarea\",\n        attributes: {\n          dataId: field[$data]?.[$uid] || field[$uid],\n          fieldId: field[$uid],\n          class: [\"xfaTextfield\"],\n          style,\n          \"aria-label\": ariaLabel(field),\n          \"aria-required\": false\n        }\n      };\n    } else {\n      html = {\n        name: \"input\",\n        attributes: {\n          type: \"text\",\n          dataId: field[$data]?.[$uid] || field[$uid],\n          fieldId: field[$uid],\n          class: [\"xfaTextfield\"],\n          style,\n          \"aria-label\": ariaLabel(field),\n          \"aria-required\": false\n        }\n      };\n    }\n    if (isRequired(field)) {\n      html.attributes[\"aria-required\"] = true;\n      html.attributes.required = true;\n    }\n    return HTMLResult.success({\n      name: \"label\",\n      attributes: {\n        class: [\"xfaLabel\"]\n      },\n      children: [html]\n    });\n  }\n}\nclass Time extends StringObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"time\");\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n  [$finalize]() {\n    const date = this[$content].trim();\n    this[$content] = date ? new Date(date) : null;\n  }\n  [$toHTML](availableSpace) {\n    return valueToHtml(this[$content] ? this[$content].toString() : \"\");\n  }\n}\nclass TimeStamp extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"timeStamp\");\n    this.id = attributes.id || \"\";\n    this.server = attributes.server || \"\";\n    this.type = getStringOption(attributes.type, [\"optional\", \"required\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass ToolTip extends StringObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"toolTip\");\n    this.id = attributes.id || \"\";\n    this.rid = attributes.rid || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass Traversal extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"traversal\", true);\n    this.id = attributes.id || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.extras = null;\n    this.traverse = new XFAObjectArray();\n  }\n}\nclass Traverse extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"traverse\", true);\n    this.id = attributes.id || \"\";\n    this.operation = getStringOption(attributes.operation, [\"next\", \"back\", \"down\", \"first\", \"left\", \"right\", \"up\"]);\n    this.ref = attributes.ref || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.extras = null;\n    this.script = null;\n  }\n  get name() {\n    return this.operation;\n  }\n  [$isTransparent]() {\n    return false;\n  }\n}\nclass Ui extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"ui\", true);\n    this.id = attributes.id || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.extras = null;\n    this.picture = null;\n    this.barcode = null;\n    this.button = null;\n    this.checkButton = null;\n    this.choiceList = null;\n    this.dateTimeEdit = null;\n    this.defaultUi = null;\n    this.imageEdit = null;\n    this.numericEdit = null;\n    this.passwordEdit = null;\n    this.signature = null;\n    this.textEdit = null;\n  }\n  [$getExtra]() {\n    if (this[$extra] === undefined) {\n      for (const name of Object.getOwnPropertyNames(this)) {\n        if (name === \"extras\" || name === \"picture\") {\n          continue;\n        }\n        const obj = this[name];\n        if (!(obj instanceof XFAObject)) {\n          continue;\n        }\n        this[$extra] = obj;\n        return obj;\n      }\n      this[$extra] = null;\n    }\n    return this[$extra];\n  }\n  [$toHTML](availableSpace) {\n    const obj = this[$getExtra]();\n    if (obj) {\n      return obj[$toHTML](availableSpace);\n    }\n    return HTMLResult.EMPTY;\n  }\n}\nclass Validate extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"validate\", true);\n    this.formatTest = getStringOption(attributes.formatTest, [\"warning\", \"disabled\", \"error\"]);\n    this.id = attributes.id || \"\";\n    this.nullTest = getStringOption(attributes.nullTest, [\"disabled\", \"error\", \"warning\"]);\n    this.scriptTest = getStringOption(attributes.scriptTest, [\"error\", \"disabled\", \"warning\"]);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.extras = null;\n    this.message = null;\n    this.picture = null;\n    this.script = null;\n  }\n}\nclass Value extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"value\", true);\n    this.id = attributes.id || \"\";\n    this.override = getInteger({\n      data: attributes.override,\n      defaultValue: 0,\n      validate: x => x === 1\n    });\n    this.relevant = getRelevant(attributes.relevant);\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.arc = null;\n    this.boolean = null;\n    this.date = null;\n    this.dateTime = null;\n    this.decimal = null;\n    this.exData = null;\n    this.float = null;\n    this.image = null;\n    this.integer = null;\n    this.line = null;\n    this.rectangle = null;\n    this.text = null;\n    this.time = null;\n  }\n  [$setValue](value) {\n    const parent = this[$getParent]();\n    if (parent instanceof Field) {\n      if (parent.ui?.imageEdit) {\n        if (!this.image) {\n          this.image = new Image({});\n          this[$appendChild](this.image);\n        }\n        this.image[$content] = value[$content];\n        return;\n      }\n    }\n    const valueName = value[$nodeName];\n    if (this[valueName] !== null) {\n      this[valueName][$content] = value[$content];\n      return;\n    }\n    for (const name of Object.getOwnPropertyNames(this)) {\n      const obj = this[name];\n      if (obj instanceof XFAObject) {\n        this[name] = null;\n        this[$removeChild](obj);\n      }\n    }\n    this[value[$nodeName]] = value;\n    this[$appendChild](value);\n  }\n  [$text]() {\n    if (this.exData) {\n      if (typeof this.exData[$content] === \"string\") {\n        return this.exData[$content].trim();\n      }\n      return this.exData[$content][$text]().trim();\n    }\n    for (const name of Object.getOwnPropertyNames(this)) {\n      if (name === \"image\") {\n        continue;\n      }\n      const obj = this[name];\n      if (obj instanceof XFAObject) {\n        return (obj[$content] || \"\").toString().trim();\n      }\n    }\n    return null;\n  }\n  [$toHTML](availableSpace) {\n    for (const name of Object.getOwnPropertyNames(this)) {\n      const obj = this[name];\n      if (!(obj instanceof XFAObject)) {\n        continue;\n      }\n      return obj[$toHTML](availableSpace);\n    }\n    return HTMLResult.EMPTY;\n  }\n}\nclass Variables extends XFAObject {\n  constructor(attributes) {\n    super(TEMPLATE_NS_ID, \"variables\", true);\n    this.id = attributes.id || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n    this.boolean = new XFAObjectArray();\n    this.date = new XFAObjectArray();\n    this.dateTime = new XFAObjectArray();\n    this.decimal = new XFAObjectArray();\n    this.exData = new XFAObjectArray();\n    this.float = new XFAObjectArray();\n    this.image = new XFAObjectArray();\n    this.integer = new XFAObjectArray();\n    this.manifest = new XFAObjectArray();\n    this.script = new XFAObjectArray();\n    this.text = new XFAObjectArray();\n    this.time = new XFAObjectArray();\n  }\n  [$isTransparent]() {\n    return true;\n  }\n}\nclass TemplateNamespace {\n  static [$buildXFAObject](name, attributes) {\n    if (TemplateNamespace.hasOwnProperty(name)) {\n      const node = TemplateNamespace[name](attributes);\n      node[$setSetAttributes](attributes);\n      return node;\n    }\n    return undefined;\n  }\n  static appearanceFilter(attrs) {\n    return new AppearanceFilter(attrs);\n  }\n  static arc(attrs) {\n    return new Arc(attrs);\n  }\n  static area(attrs) {\n    return new Area(attrs);\n  }\n  static assist(attrs) {\n    return new Assist(attrs);\n  }\n  static barcode(attrs) {\n    return new Barcode(attrs);\n  }\n  static bind(attrs) {\n    return new Bind(attrs);\n  }\n  static bindItems(attrs) {\n    return new BindItems(attrs);\n  }\n  static bookend(attrs) {\n    return new Bookend(attrs);\n  }\n  static boolean(attrs) {\n    return new BooleanElement(attrs);\n  }\n  static border(attrs) {\n    return new Border(attrs);\n  }\n  static break(attrs) {\n    return new Break(attrs);\n  }\n  static breakAfter(attrs) {\n    return new BreakAfter(attrs);\n  }\n  static breakBefore(attrs) {\n    return new BreakBefore(attrs);\n  }\n  static button(attrs) {\n    return new Button(attrs);\n  }\n  static calculate(attrs) {\n    return new Calculate(attrs);\n  }\n  static caption(attrs) {\n    return new Caption(attrs);\n  }\n  static certificate(attrs) {\n    return new Certificate(attrs);\n  }\n  static certificates(attrs) {\n    return new Certificates(attrs);\n  }\n  static checkButton(attrs) {\n    return new CheckButton(attrs);\n  }\n  static choiceList(attrs) {\n    return new ChoiceList(attrs);\n  }\n  static color(attrs) {\n    return new Color(attrs);\n  }\n  static comb(attrs) {\n    return new Comb(attrs);\n  }\n  static connect(attrs) {\n    return new Connect(attrs);\n  }\n  static contentArea(attrs) {\n    return new ContentArea(attrs);\n  }\n  static corner(attrs) {\n    return new Corner(attrs);\n  }\n  static date(attrs) {\n    return new DateElement(attrs);\n  }\n  static dateTime(attrs) {\n    return new DateTime(attrs);\n  }\n  static dateTimeEdit(attrs) {\n    return new DateTimeEdit(attrs);\n  }\n  static decimal(attrs) {\n    return new Decimal(attrs);\n  }\n  static defaultUi(attrs) {\n    return new DefaultUi(attrs);\n  }\n  static desc(attrs) {\n    return new Desc(attrs);\n  }\n  static digestMethod(attrs) {\n    return new DigestMethod(attrs);\n  }\n  static digestMethods(attrs) {\n    return new DigestMethods(attrs);\n  }\n  static draw(attrs) {\n    return new Draw(attrs);\n  }\n  static edge(attrs) {\n    return new Edge(attrs);\n  }\n  static encoding(attrs) {\n    return new Encoding(attrs);\n  }\n  static encodings(attrs) {\n    return new Encodings(attrs);\n  }\n  static encrypt(attrs) {\n    return new Encrypt(attrs);\n  }\n  static encryptData(attrs) {\n    return new EncryptData(attrs);\n  }\n  static encryption(attrs) {\n    return new Encryption(attrs);\n  }\n  static encryptionMethod(attrs) {\n    return new EncryptionMethod(attrs);\n  }\n  static encryptionMethods(attrs) {\n    return new EncryptionMethods(attrs);\n  }\n  static event(attrs) {\n    return new Event(attrs);\n  }\n  static exData(attrs) {\n    return new ExData(attrs);\n  }\n  static exObject(attrs) {\n    return new ExObject(attrs);\n  }\n  static exclGroup(attrs) {\n    return new ExclGroup(attrs);\n  }\n  static execute(attrs) {\n    return new Execute(attrs);\n  }\n  static extras(attrs) {\n    return new Extras(attrs);\n  }\n  static field(attrs) {\n    return new Field(attrs);\n  }\n  static fill(attrs) {\n    return new Fill(attrs);\n  }\n  static filter(attrs) {\n    return new Filter(attrs);\n  }\n  static float(attrs) {\n    return new Float(attrs);\n  }\n  static font(attrs) {\n    return new template_Font(attrs);\n  }\n  static format(attrs) {\n    return new Format(attrs);\n  }\n  static handler(attrs) {\n    return new Handler(attrs);\n  }\n  static hyphenation(attrs) {\n    return new Hyphenation(attrs);\n  }\n  static image(attrs) {\n    return new Image(attrs);\n  }\n  static imageEdit(attrs) {\n    return new ImageEdit(attrs);\n  }\n  static integer(attrs) {\n    return new Integer(attrs);\n  }\n  static issuers(attrs) {\n    return new Issuers(attrs);\n  }\n  static items(attrs) {\n    return new Items(attrs);\n  }\n  static keep(attrs) {\n    return new Keep(attrs);\n  }\n  static keyUsage(attrs) {\n    return new KeyUsage(attrs);\n  }\n  static line(attrs) {\n    return new Line(attrs);\n  }\n  static linear(attrs) {\n    return new Linear(attrs);\n  }\n  static lockDocument(attrs) {\n    return new LockDocument(attrs);\n  }\n  static manifest(attrs) {\n    return new Manifest(attrs);\n  }\n  static margin(attrs) {\n    return new Margin(attrs);\n  }\n  static mdp(attrs) {\n    return new Mdp(attrs);\n  }\n  static medium(attrs) {\n    return new Medium(attrs);\n  }\n  static message(attrs) {\n    return new Message(attrs);\n  }\n  static numericEdit(attrs) {\n    return new NumericEdit(attrs);\n  }\n  static occur(attrs) {\n    return new Occur(attrs);\n  }\n  static oid(attrs) {\n    return new Oid(attrs);\n  }\n  static oids(attrs) {\n    return new Oids(attrs);\n  }\n  static overflow(attrs) {\n    return new Overflow(attrs);\n  }\n  static pageArea(attrs) {\n    return new PageArea(attrs);\n  }\n  static pageSet(attrs) {\n    return new PageSet(attrs);\n  }\n  static para(attrs) {\n    return new Para(attrs);\n  }\n  static passwordEdit(attrs) {\n    return new PasswordEdit(attrs);\n  }\n  static pattern(attrs) {\n    return new template_Pattern(attrs);\n  }\n  static picture(attrs) {\n    return new Picture(attrs);\n  }\n  static proto(attrs) {\n    return new Proto(attrs);\n  }\n  static radial(attrs) {\n    return new Radial(attrs);\n  }\n  static reason(attrs) {\n    return new Reason(attrs);\n  }\n  static reasons(attrs) {\n    return new Reasons(attrs);\n  }\n  static rectangle(attrs) {\n    return new Rectangle(attrs);\n  }\n  static ref(attrs) {\n    return new RefElement(attrs);\n  }\n  static script(attrs) {\n    return new Script(attrs);\n  }\n  static setProperty(attrs) {\n    return new SetProperty(attrs);\n  }\n  static signData(attrs) {\n    return new SignData(attrs);\n  }\n  static signature(attrs) {\n    return new Signature(attrs);\n  }\n  static signing(attrs) {\n    return new Signing(attrs);\n  }\n  static solid(attrs) {\n    return new Solid(attrs);\n  }\n  static speak(attrs) {\n    return new Speak(attrs);\n  }\n  static stipple(attrs) {\n    return new Stipple(attrs);\n  }\n  static subform(attrs) {\n    return new Subform(attrs);\n  }\n  static subformSet(attrs) {\n    return new SubformSet(attrs);\n  }\n  static subjectDN(attrs) {\n    return new SubjectDN(attrs);\n  }\n  static subjectDNs(attrs) {\n    return new SubjectDNs(attrs);\n  }\n  static submit(attrs) {\n    return new Submit(attrs);\n  }\n  static template(attrs) {\n    return new Template(attrs);\n  }\n  static text(attrs) {\n    return new Text(attrs);\n  }\n  static textEdit(attrs) {\n    return new TextEdit(attrs);\n  }\n  static time(attrs) {\n    return new Time(attrs);\n  }\n  static timeStamp(attrs) {\n    return new TimeStamp(attrs);\n  }\n  static toolTip(attrs) {\n    return new ToolTip(attrs);\n  }\n  static traversal(attrs) {\n    return new Traversal(attrs);\n  }\n  static traverse(attrs) {\n    return new Traverse(attrs);\n  }\n  static ui(attrs) {\n    return new Ui(attrs);\n  }\n  static validate(attrs) {\n    return new Validate(attrs);\n  }\n  static value(attrs) {\n    return new Value(attrs);\n  }\n  static variables(attrs) {\n    return new Variables(attrs);\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/xfa/bind.js\n\n\n\n\n\n\nconst bind_NS_DATASETS = NamespaceIds.datasets.id;\nfunction createText(content) {\n  const node = new Text({});\n  node[$content] = content;\n  return node;\n}\nclass Binder {\n  constructor(root) {\n    this.root = root;\n    this.datasets = root.datasets;\n    this.data = root.datasets?.data || new XmlObject(NamespaceIds.datasets.id, \"data\");\n    this.emptyMerge = this.data[$getChildren]().length === 0;\n    this.root.form = this.form = root.template[$clone]();\n  }\n  _isConsumeData() {\n    return !this.emptyMerge && this._mergeMode;\n  }\n  _isMatchTemplate() {\n    return !this._isConsumeData();\n  }\n  bind() {\n    this._bindElement(this.form, this.data);\n    return this.form;\n  }\n  getData() {\n    return this.data;\n  }\n  _bindValue(formNode, data, picture) {\n    formNode[$data] = data;\n    if (formNode[$hasSettableValue]()) {\n      if (data[$isDataValue]()) {\n        const value = data[$getDataValue]();\n        formNode[$setValue](createText(value));\n      } else if (formNode instanceof Field && formNode.ui?.choiceList?.open === \"multiSelect\") {\n        const value = data[$getChildren]().map(child => child[$content].trim()).join(\"\\n\");\n        formNode[$setValue](createText(value));\n      } else if (this._isConsumeData()) {\n        warn(`XFA - Nodes haven't the same type.`);\n      }\n    } else if (!data[$isDataValue]() || this._isMatchTemplate()) {\n      this._bindElement(formNode, data);\n    } else {\n      warn(`XFA - Nodes haven't the same type.`);\n    }\n  }\n  _findDataByNameToConsume(name, isValue, dataNode, global) {\n    if (!name) {\n      return null;\n    }\n    let generator, match;\n    for (let i = 0; i < 3; i++) {\n      generator = dataNode[$getRealChildrenByNameIt](name, false, true);\n      while (true) {\n        match = generator.next().value;\n        if (!match) {\n          break;\n        }\n        if (isValue === match[$isDataValue]()) {\n          return match;\n        }\n      }\n      if (dataNode[$namespaceId] === NamespaceIds.datasets.id && dataNode[$nodeName] === \"data\") {\n        break;\n      }\n      dataNode = dataNode[$getParent]();\n    }\n    if (!global) {\n      return null;\n    }\n    generator = this.data[$getRealChildrenByNameIt](name, true, false);\n    match = generator.next().value;\n    if (match) {\n      return match;\n    }\n    generator = this.data[$getAttributeIt](name, true);\n    match = generator.next().value;\n    if (match?.[$isDataValue]()) {\n      return match;\n    }\n    return null;\n  }\n  _setProperties(formNode, dataNode) {\n    if (!formNode.hasOwnProperty(\"setProperty\")) {\n      return;\n    }\n    for (const {\n      ref,\n      target,\n      connection\n    } of formNode.setProperty.children) {\n      if (connection) {\n        continue;\n      }\n      if (!ref) {\n        continue;\n      }\n      const nodes = searchNode(this.root, dataNode, ref, false, false);\n      if (!nodes) {\n        warn(`XFA - Invalid reference: ${ref}.`);\n        continue;\n      }\n      const [node] = nodes;\n      if (!node[$isDescendent](this.data)) {\n        warn(`XFA - Invalid node: must be a data node.`);\n        continue;\n      }\n      const targetNodes = searchNode(this.root, formNode, target, false, false);\n      if (!targetNodes) {\n        warn(`XFA - Invalid target: ${target}.`);\n        continue;\n      }\n      const [targetNode] = targetNodes;\n      if (!targetNode[$isDescendent](formNode)) {\n        warn(`XFA - Invalid target: must be a property or subproperty.`);\n        continue;\n      }\n      const targetParent = targetNode[$getParent]();\n      if (targetNode instanceof SetProperty || targetParent instanceof SetProperty) {\n        warn(`XFA - Invalid target: cannot be a setProperty or one of its properties.`);\n        continue;\n      }\n      if (targetNode instanceof BindItems || targetParent instanceof BindItems) {\n        warn(`XFA - Invalid target: cannot be a bindItems or one of its properties.`);\n        continue;\n      }\n      const content = node[$text]();\n      const name = targetNode[$nodeName];\n      if (targetNode instanceof XFAAttribute) {\n        const attrs = Object.create(null);\n        attrs[name] = content;\n        const obj = Reflect.construct(Object.getPrototypeOf(targetParent).constructor, [attrs]);\n        targetParent[name] = obj[name];\n        continue;\n      }\n      if (!targetNode.hasOwnProperty($content)) {\n        warn(`XFA - Invalid node to use in setProperty`);\n        continue;\n      }\n      targetNode[$data] = node;\n      targetNode[$content] = content;\n      targetNode[$finalize]();\n    }\n  }\n  _bindItems(formNode, dataNode) {\n    if (!formNode.hasOwnProperty(\"items\") || !formNode.hasOwnProperty(\"bindItems\") || formNode.bindItems.isEmpty()) {\n      return;\n    }\n    for (const item of formNode.items.children) {\n      formNode[$removeChild](item);\n    }\n    formNode.items.clear();\n    const labels = new Items({});\n    const values = new Items({});\n    formNode[$appendChild](labels);\n    formNode.items.push(labels);\n    formNode[$appendChild](values);\n    formNode.items.push(values);\n    for (const {\n      ref,\n      labelRef,\n      valueRef,\n      connection\n    } of formNode.bindItems.children) {\n      if (connection) {\n        continue;\n      }\n      if (!ref) {\n        continue;\n      }\n      const nodes = searchNode(this.root, dataNode, ref, false, false);\n      if (!nodes) {\n        warn(`XFA - Invalid reference: ${ref}.`);\n        continue;\n      }\n      for (const node of nodes) {\n        if (!node[$isDescendent](this.datasets)) {\n          warn(`XFA - Invalid ref (${ref}): must be a datasets child.`);\n          continue;\n        }\n        const labelNodes = searchNode(this.root, node, labelRef, true, false);\n        if (!labelNodes) {\n          warn(`XFA - Invalid label: ${labelRef}.`);\n          continue;\n        }\n        const [labelNode] = labelNodes;\n        if (!labelNode[$isDescendent](this.datasets)) {\n          warn(`XFA - Invalid label: must be a datasets child.`);\n          continue;\n        }\n        const valueNodes = searchNode(this.root, node, valueRef, true, false);\n        if (!valueNodes) {\n          warn(`XFA - Invalid value: ${valueRef}.`);\n          continue;\n        }\n        const [valueNode] = valueNodes;\n        if (!valueNode[$isDescendent](this.datasets)) {\n          warn(`XFA - Invalid value: must be a datasets child.`);\n          continue;\n        }\n        const label = createText(labelNode[$text]());\n        const value = createText(valueNode[$text]());\n        labels[$appendChild](label);\n        labels.text.push(label);\n        values[$appendChild](value);\n        values.text.push(value);\n      }\n    }\n  }\n  _bindOccurrences(formNode, matches, picture) {\n    let baseClone;\n    if (matches.length > 1) {\n      baseClone = formNode[$clone]();\n      baseClone[$removeChild](baseClone.occur);\n      baseClone.occur = null;\n    }\n    this._bindValue(formNode, matches[0], picture);\n    this._setProperties(formNode, matches[0]);\n    this._bindItems(formNode, matches[0]);\n    if (matches.length === 1) {\n      return;\n    }\n    const parent = formNode[$getParent]();\n    const name = formNode[$nodeName];\n    const pos = parent[$indexOf](formNode);\n    for (let i = 1, ii = matches.length; i < ii; i++) {\n      const match = matches[i];\n      const clone = baseClone[$clone]();\n      parent[name].push(clone);\n      parent[$insertAt](pos + i, clone);\n      this._bindValue(clone, match, picture);\n      this._setProperties(clone, match);\n      this._bindItems(clone, match);\n    }\n  }\n  _createOccurrences(formNode) {\n    if (!this.emptyMerge) {\n      return;\n    }\n    const {\n      occur\n    } = formNode;\n    if (!occur || occur.initial <= 1) {\n      return;\n    }\n    const parent = formNode[$getParent]();\n    const name = formNode[$nodeName];\n    if (!(parent[name] instanceof XFAObjectArray)) {\n      return;\n    }\n    let currentNumber;\n    if (formNode.name) {\n      currentNumber = parent[name].children.filter(e => e.name === formNode.name).length;\n    } else {\n      currentNumber = parent[name].children.length;\n    }\n    const pos = parent[$indexOf](formNode) + 1;\n    const ii = occur.initial - currentNumber;\n    if (ii) {\n      const nodeClone = formNode[$clone]();\n      nodeClone[$removeChild](nodeClone.occur);\n      nodeClone.occur = null;\n      parent[name].push(nodeClone);\n      parent[$insertAt](pos, nodeClone);\n      for (let i = 1; i < ii; i++) {\n        const clone = nodeClone[$clone]();\n        parent[name].push(clone);\n        parent[$insertAt](pos + i, clone);\n      }\n    }\n  }\n  _getOccurInfo(formNode) {\n    const {\n      name,\n      occur\n    } = formNode;\n    if (!occur || !name) {\n      return [1, 1];\n    }\n    const max = occur.max === -1 ? Infinity : occur.max;\n    return [occur.min, max];\n  }\n  _setAndBind(formNode, dataNode) {\n    this._setProperties(formNode, dataNode);\n    this._bindItems(formNode, dataNode);\n    this._bindElement(formNode, dataNode);\n  }\n  _bindElement(formNode, dataNode) {\n    const uselessNodes = [];\n    this._createOccurrences(formNode);\n    for (const child of formNode[$getChildren]()) {\n      if (child[$data]) {\n        continue;\n      }\n      if (this._mergeMode === undefined && child[$nodeName] === \"subform\") {\n        this._mergeMode = child.mergeMode === \"consumeData\";\n        const dataChildren = dataNode[$getChildren]();\n        if (dataChildren.length > 0) {\n          this._bindOccurrences(child, [dataChildren[0]], null);\n        } else if (this.emptyMerge) {\n          const nsId = dataNode[$namespaceId] === bind_NS_DATASETS ? -1 : dataNode[$namespaceId];\n          const dataChild = child[$data] = new XmlObject(nsId, child.name || \"root\");\n          dataNode[$appendChild](dataChild);\n          this._bindElement(child, dataChild);\n        }\n        continue;\n      }\n      if (!child[$isBindable]()) {\n        continue;\n      }\n      let global = false;\n      let picture = null;\n      let ref = null;\n      let match = null;\n      if (child.bind) {\n        switch (child.bind.match) {\n          case \"none\":\n            this._setAndBind(child, dataNode);\n            continue;\n          case \"global\":\n            global = true;\n            break;\n          case \"dataRef\":\n            if (!child.bind.ref) {\n              warn(`XFA - ref is empty in node ${child[$nodeName]}.`);\n              this._setAndBind(child, dataNode);\n              continue;\n            }\n            ref = child.bind.ref;\n            break;\n          default:\n            break;\n        }\n        if (child.bind.picture) {\n          picture = child.bind.picture[$content];\n        }\n      }\n      const [min, max] = this._getOccurInfo(child);\n      if (ref) {\n        match = searchNode(this.root, dataNode, ref, true, false);\n        if (match === null) {\n          match = createDataNode(this.data, dataNode, ref);\n          if (!match) {\n            continue;\n          }\n          if (this._isConsumeData()) {\n            match[$consumed] = true;\n          }\n          this._setAndBind(child, match);\n          continue;\n        } else {\n          if (this._isConsumeData()) {\n            match = match.filter(node => !node[$consumed]);\n          }\n          if (match.length > max) {\n            match = match.slice(0, max);\n          } else if (match.length === 0) {\n            match = null;\n          }\n          if (match && this._isConsumeData()) {\n            match.forEach(node => {\n              node[$consumed] = true;\n            });\n          }\n        }\n      } else {\n        if (!child.name) {\n          this._setAndBind(child, dataNode);\n          continue;\n        }\n        if (this._isConsumeData()) {\n          const matches = [];\n          while (matches.length < max) {\n            const found = this._findDataByNameToConsume(child.name, child[$hasSettableValue](), dataNode, global);\n            if (!found) {\n              break;\n            }\n            found[$consumed] = true;\n            matches.push(found);\n          }\n          match = matches.length > 0 ? matches : null;\n        } else {\n          match = dataNode[$getRealChildrenByNameIt](child.name, false, this.emptyMerge).next().value;\n          if (!match) {\n            if (min === 0) {\n              uselessNodes.push(child);\n              continue;\n            }\n            const nsId = dataNode[$namespaceId] === bind_NS_DATASETS ? -1 : dataNode[$namespaceId];\n            match = child[$data] = new XmlObject(nsId, child.name);\n            if (this.emptyMerge) {\n              match[$consumed] = true;\n            }\n            dataNode[$appendChild](match);\n            this._setAndBind(child, match);\n            continue;\n          }\n          if (this.emptyMerge) {\n            match[$consumed] = true;\n          }\n          match = [match];\n        }\n      }\n      if (match) {\n        this._bindOccurrences(child, match, picture);\n      } else if (min > 0) {\n        this._setAndBind(child, dataNode);\n      } else {\n        uselessNodes.push(child);\n      }\n    }\n    uselessNodes.forEach(node => node[$getParent]()[$removeChild](node));\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/xfa/data.js\n\nclass DataHandler {\n  constructor(root, data) {\n    this.data = data;\n    this.dataset = root.datasets || null;\n  }\n  serialize(storage) {\n    const stack = [[-1, this.data[$getChildren]()]];\n    while (stack.length > 0) {\n      const last = stack.at(-1);\n      const [i, children] = last;\n      if (i + 1 === children.length) {\n        stack.pop();\n        continue;\n      }\n      const child = children[++last[0]];\n      const storageEntry = storage.get(child[$uid]);\n      if (storageEntry) {\n        child[$setValue](storageEntry);\n      } else {\n        const attributes = child[$getAttributes]();\n        for (const value of attributes.values()) {\n          const entry = storage.get(value[$uid]);\n          if (entry) {\n            value[$setValue](entry);\n            break;\n          }\n        }\n      }\n      const nodes = child[$getChildren]();\n      if (nodes.length > 0) {\n        stack.push([-1, nodes]);\n      }\n    }\n    const buf = [`<xfa:datasets xmlns:xfa=\"http://www.xfa.org/schema/xfa-data/1.0/\">`];\n    if (this.dataset) {\n      for (const child of this.dataset[$getChildren]()) {\n        if (child[$nodeName] !== \"data\") {\n          child[$toString](buf);\n        }\n      }\n    }\n    this.data[$toString](buf);\n    buf.push(\"</xfa:datasets>\");\n    return buf.join(\"\");\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/xfa/config.js\n\n\n\n\n\nconst CONFIG_NS_ID = NamespaceIds.config.id;\nclass Acrobat extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"acrobat\", true);\n    this.acrobat7 = null;\n    this.autoSave = null;\n    this.common = null;\n    this.validate = null;\n    this.validateApprovalSignatures = null;\n    this.submitUrl = new XFAObjectArray();\n  }\n}\nclass Acrobat7 extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"acrobat7\", true);\n    this.dynamicRender = null;\n  }\n}\nclass ADBE_JSConsole extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"ADBE_JSConsole\", [\"delegate\", \"Enable\", \"Disable\"]);\n  }\n}\nclass ADBE_JSDebugger extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"ADBE_JSDebugger\", [\"delegate\", \"Enable\", \"Disable\"]);\n  }\n}\nclass AddSilentPrint extends Option01 {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"addSilentPrint\");\n  }\n}\nclass AddViewerPreferences extends Option01 {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"addViewerPreferences\");\n  }\n}\nclass AdjustData extends Option10 {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"adjustData\");\n  }\n}\nclass AdobeExtensionLevel extends IntegerObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"adobeExtensionLevel\", 0, n => n >= 1 && n <= 8);\n  }\n}\nclass Agent extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"agent\", true);\n    this.name = attributes.name ? attributes.name.trim() : \"\";\n    this.common = new XFAObjectArray();\n  }\n}\nclass AlwaysEmbed extends ContentObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"alwaysEmbed\");\n  }\n}\nclass Amd extends StringObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"amd\");\n  }\n}\nclass config_Area extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"area\");\n    this.level = getInteger({\n      data: attributes.level,\n      defaultValue: 0,\n      validate: n => n >= 1 && n <= 3\n    });\n    this.name = getStringOption(attributes.name, [\"\", \"barcode\", \"coreinit\", \"deviceDriver\", \"font\", \"general\", \"layout\", \"merge\", \"script\", \"signature\", \"sourceSet\", \"templateCache\"]);\n  }\n}\nclass Attributes extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"attributes\", [\"preserve\", \"delegate\", \"ignore\"]);\n  }\n}\nclass AutoSave extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"autoSave\", [\"disabled\", \"enabled\"]);\n  }\n}\nclass Base extends StringObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"base\");\n  }\n}\nclass BatchOutput extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"batchOutput\");\n    this.format = getStringOption(attributes.format, [\"none\", \"concat\", \"zip\", \"zipCompress\"]);\n  }\n}\nclass BehaviorOverride extends ContentObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"behaviorOverride\");\n  }\n  [$finalize]() {\n    this[$content] = new Map(this[$content].trim().split(/\\s+/).filter(x => x.includes(\":\")).map(x => x.split(\":\", 2)));\n  }\n}\nclass Cache extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"cache\", true);\n    this.templateCache = null;\n  }\n}\nclass Change extends Option01 {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"change\");\n  }\n}\nclass Common extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"common\", true);\n    this.data = null;\n    this.locale = null;\n    this.localeSet = null;\n    this.messaging = null;\n    this.suppressBanner = null;\n    this.template = null;\n    this.validationMessaging = null;\n    this.versionControl = null;\n    this.log = new XFAObjectArray();\n  }\n}\nclass Compress extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"compress\");\n    this.scope = getStringOption(attributes.scope, [\"imageOnly\", \"document\"]);\n  }\n}\nclass CompressLogicalStructure extends Option01 {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"compressLogicalStructure\");\n  }\n}\nclass CompressObjectStream extends Option10 {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"compressObjectStream\");\n  }\n}\nclass Compression extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"compression\", true);\n    this.compressLogicalStructure = null;\n    this.compressObjectStream = null;\n    this.level = null;\n    this.type = null;\n  }\n}\nclass Config extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"config\", true);\n    this.acrobat = null;\n    this.present = null;\n    this.trace = null;\n    this.agent = new XFAObjectArray();\n  }\n}\nclass Conformance extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"conformance\", [\"A\", \"B\"]);\n  }\n}\nclass ContentCopy extends Option01 {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"contentCopy\");\n  }\n}\nclass Copies extends IntegerObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"copies\", 1, n => n >= 1);\n  }\n}\nclass Creator extends StringObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"creator\");\n  }\n}\nclass CurrentPage extends IntegerObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"currentPage\", 0, n => n >= 0);\n  }\n}\nclass Data extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"data\", true);\n    this.adjustData = null;\n    this.attributes = null;\n    this.incrementalLoad = null;\n    this.outputXSL = null;\n    this.range = null;\n    this.record = null;\n    this.startNode = null;\n    this.uri = null;\n    this.window = null;\n    this.xsl = null;\n    this.excludeNS = new XFAObjectArray();\n    this.transform = new XFAObjectArray();\n  }\n}\nclass Debug extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"debug\", true);\n    this.uri = null;\n  }\n}\nclass DefaultTypeface extends ContentObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"defaultTypeface\");\n    this.writingScript = getStringOption(attributes.writingScript, [\"*\", \"Arabic\", \"Cyrillic\", \"EastEuropeanRoman\", \"Greek\", \"Hebrew\", \"Japanese\", \"Korean\", \"Roman\", \"SimplifiedChinese\", \"Thai\", \"TraditionalChinese\", \"Vietnamese\"]);\n  }\n}\nclass Destination extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"destination\", [\"pdf\", \"pcl\", \"ps\", \"webClient\", \"zpl\"]);\n  }\n}\nclass DocumentAssembly extends Option01 {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"documentAssembly\");\n  }\n}\nclass Driver extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"driver\", true);\n    this.name = attributes.name ? attributes.name.trim() : \"\";\n    this.fontInfo = null;\n    this.xdc = null;\n  }\n}\nclass DuplexOption extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"duplexOption\", [\"simplex\", \"duplexFlipLongEdge\", \"duplexFlipShortEdge\"]);\n  }\n}\nclass DynamicRender extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"dynamicRender\", [\"forbidden\", \"required\"]);\n  }\n}\nclass Embed extends Option01 {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"embed\");\n  }\n}\nclass config_Encrypt extends Option01 {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"encrypt\");\n  }\n}\nclass config_Encryption extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"encryption\", true);\n    this.encrypt = null;\n    this.encryptionLevel = null;\n    this.permissions = null;\n  }\n}\nclass EncryptionLevel extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"encryptionLevel\", [\"40bit\", \"128bit\"]);\n  }\n}\nclass Enforce extends StringObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"enforce\");\n  }\n}\nclass Equate extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"equate\");\n    this.force = getInteger({\n      data: attributes.force,\n      defaultValue: 1,\n      validate: n => n === 0\n    });\n    this.from = attributes.from || \"\";\n    this.to = attributes.to || \"\";\n  }\n}\nclass EquateRange extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"equateRange\");\n    this.from = attributes.from || \"\";\n    this.to = attributes.to || \"\";\n    this._unicodeRange = attributes.unicodeRange || \"\";\n  }\n  get unicodeRange() {\n    const ranges = [];\n    const unicodeRegex = /U\\+([0-9a-fA-F]+)/;\n    const unicodeRange = this._unicodeRange;\n    for (let range of unicodeRange.split(\",\").map(x => x.trim()).filter(x => !!x)) {\n      range = range.split(\"-\", 2).map(x => {\n        const found = x.match(unicodeRegex);\n        if (!found) {\n          return 0;\n        }\n        return parseInt(found[1], 16);\n      });\n      if (range.length === 1) {\n        range.push(range[0]);\n      }\n      ranges.push(range);\n    }\n    return shadow(this, \"unicodeRange\", ranges);\n  }\n}\nclass Exclude extends ContentObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"exclude\");\n  }\n  [$finalize]() {\n    this[$content] = this[$content].trim().split(/\\s+/).filter(x => x && [\"calculate\", \"close\", \"enter\", \"exit\", \"initialize\", \"ready\", \"validate\"].includes(x));\n  }\n}\nclass ExcludeNS extends StringObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"excludeNS\");\n  }\n}\nclass FlipLabel extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"flipLabel\", [\"usePrinterSetting\", \"on\", \"off\"]);\n  }\n}\nclass config_FontInfo extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"fontInfo\", true);\n    this.embed = null;\n    this.map = null;\n    this.subsetBelow = null;\n    this.alwaysEmbed = new XFAObjectArray();\n    this.defaultTypeface = new XFAObjectArray();\n    this.neverEmbed = new XFAObjectArray();\n  }\n}\nclass FormFieldFilling extends Option01 {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"formFieldFilling\");\n  }\n}\nclass GroupParent extends StringObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"groupParent\");\n  }\n}\nclass IfEmpty extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"ifEmpty\", [\"dataValue\", \"dataGroup\", \"ignore\", \"remove\"]);\n  }\n}\nclass IncludeXDPContent extends StringObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"includeXDPContent\");\n  }\n}\nclass IncrementalLoad extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"incrementalLoad\", [\"none\", \"forwardOnly\"]);\n  }\n}\nclass IncrementalMerge extends Option01 {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"incrementalMerge\");\n  }\n}\nclass Interactive extends Option01 {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"interactive\");\n  }\n}\nclass Jog extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"jog\", [\"usePrinterSetting\", \"none\", \"pageSet\"]);\n  }\n}\nclass LabelPrinter extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"labelPrinter\", true);\n    this.name = getStringOption(attributes.name, [\"zpl\", \"dpl\", \"ipl\", \"tcpl\"]);\n    this.batchOutput = null;\n    this.flipLabel = null;\n    this.fontInfo = null;\n    this.xdc = null;\n  }\n}\nclass Layout extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"layout\", [\"paginate\", \"panel\"]);\n  }\n}\nclass Level extends IntegerObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"level\", 0, n => n > 0);\n  }\n}\nclass Linearized extends Option01 {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"linearized\");\n  }\n}\nclass Locale extends StringObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"locale\");\n  }\n}\nclass LocaleSet extends StringObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"localeSet\");\n  }\n}\nclass Log extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"log\", true);\n    this.mode = null;\n    this.threshold = null;\n    this.to = null;\n    this.uri = null;\n  }\n}\nclass MapElement extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"map\", true);\n    this.equate = new XFAObjectArray();\n    this.equateRange = new XFAObjectArray();\n  }\n}\nclass MediumInfo extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"mediumInfo\", true);\n    this.map = null;\n  }\n}\nclass config_Message extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"message\", true);\n    this.msgId = null;\n    this.severity = null;\n  }\n}\nclass Messaging extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"messaging\", true);\n    this.message = new XFAObjectArray();\n  }\n}\nclass Mode extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"mode\", [\"append\", \"overwrite\"]);\n  }\n}\nclass ModifyAnnots extends Option01 {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"modifyAnnots\");\n  }\n}\nclass MsgId extends IntegerObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"msgId\", 1, n => n >= 1);\n  }\n}\nclass NameAttr extends StringObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"nameAttr\");\n  }\n}\nclass NeverEmbed extends ContentObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"neverEmbed\");\n  }\n}\nclass NumberOfCopies extends IntegerObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"numberOfCopies\", null, n => n >= 2 && n <= 5);\n  }\n}\nclass OpenAction extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"openAction\", true);\n    this.destination = null;\n  }\n}\nclass Output extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"output\", true);\n    this.to = null;\n    this.type = null;\n    this.uri = null;\n  }\n}\nclass OutputBin extends StringObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"outputBin\");\n  }\n}\nclass OutputXSL extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"outputXSL\", true);\n    this.uri = null;\n  }\n}\nclass Overprint extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"overprint\", [\"none\", \"both\", \"draw\", \"field\"]);\n  }\n}\nclass Packets extends StringObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"packets\");\n  }\n  [$finalize]() {\n    if (this[$content] === \"*\") {\n      return;\n    }\n    this[$content] = this[$content].trim().split(/\\s+/).filter(x => [\"config\", \"datasets\", \"template\", \"xfdf\", \"xslt\"].includes(x));\n  }\n}\nclass PageOffset extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"pageOffset\");\n    this.x = getInteger({\n      data: attributes.x,\n      defaultValue: \"useXDCSetting\",\n      validate: n => true\n    });\n    this.y = getInteger({\n      data: attributes.y,\n      defaultValue: \"useXDCSetting\",\n      validate: n => true\n    });\n  }\n}\nclass PageRange extends StringObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"pageRange\");\n  }\n  [$finalize]() {\n    const numbers = this[$content].trim().split(/\\s+/).map(x => parseInt(x, 10));\n    const ranges = [];\n    for (let i = 0, ii = numbers.length; i < ii; i += 2) {\n      ranges.push(numbers.slice(i, i + 2));\n    }\n    this[$content] = ranges;\n  }\n}\nclass Pagination extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"pagination\", [\"simplex\", \"duplexShortEdge\", \"duplexLongEdge\"]);\n  }\n}\nclass PaginationOverride extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"paginationOverride\", [\"none\", \"forceDuplex\", \"forceDuplexLongEdge\", \"forceDuplexShortEdge\", \"forceSimplex\"]);\n  }\n}\nclass Part extends IntegerObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"part\", 1, n => false);\n  }\n}\nclass Pcl extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"pcl\", true);\n    this.name = attributes.name || \"\";\n    this.batchOutput = null;\n    this.fontInfo = null;\n    this.jog = null;\n    this.mediumInfo = null;\n    this.outputBin = null;\n    this.pageOffset = null;\n    this.staple = null;\n    this.xdc = null;\n  }\n}\nclass Pdf extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"pdf\", true);\n    this.name = attributes.name || \"\";\n    this.adobeExtensionLevel = null;\n    this.batchOutput = null;\n    this.compression = null;\n    this.creator = null;\n    this.encryption = null;\n    this.fontInfo = null;\n    this.interactive = null;\n    this.linearized = null;\n    this.openAction = null;\n    this.pdfa = null;\n    this.producer = null;\n    this.renderPolicy = null;\n    this.scriptModel = null;\n    this.silentPrint = null;\n    this.submitFormat = null;\n    this.tagged = null;\n    this.version = null;\n    this.viewerPreferences = null;\n    this.xdc = null;\n  }\n}\nclass Pdfa extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"pdfa\", true);\n    this.amd = null;\n    this.conformance = null;\n    this.includeXDPContent = null;\n    this.part = null;\n  }\n}\nclass Permissions extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"permissions\", true);\n    this.accessibleContent = null;\n    this.change = null;\n    this.contentCopy = null;\n    this.documentAssembly = null;\n    this.formFieldFilling = null;\n    this.modifyAnnots = null;\n    this.plaintextMetadata = null;\n    this.print = null;\n    this.printHighQuality = null;\n  }\n}\nclass PickTrayByPDFSize extends Option01 {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"pickTrayByPDFSize\");\n  }\n}\nclass config_Picture extends StringObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"picture\");\n  }\n}\nclass PlaintextMetadata extends Option01 {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"plaintextMetadata\");\n  }\n}\nclass Presence extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"presence\", [\"preserve\", \"dissolve\", \"dissolveStructure\", \"ignore\", \"remove\"]);\n  }\n}\nclass Present extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"present\", true);\n    this.behaviorOverride = null;\n    this.cache = null;\n    this.common = null;\n    this.copies = null;\n    this.destination = null;\n    this.incrementalMerge = null;\n    this.layout = null;\n    this.output = null;\n    this.overprint = null;\n    this.pagination = null;\n    this.paginationOverride = null;\n    this.script = null;\n    this.validate = null;\n    this.xdp = null;\n    this.driver = new XFAObjectArray();\n    this.labelPrinter = new XFAObjectArray();\n    this.pcl = new XFAObjectArray();\n    this.pdf = new XFAObjectArray();\n    this.ps = new XFAObjectArray();\n    this.submitUrl = new XFAObjectArray();\n    this.webClient = new XFAObjectArray();\n    this.zpl = new XFAObjectArray();\n  }\n}\nclass Print extends Option01 {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"print\");\n  }\n}\nclass PrintHighQuality extends Option01 {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"printHighQuality\");\n  }\n}\nclass PrintScaling extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"printScaling\", [\"appdefault\", \"noScaling\"]);\n  }\n}\nclass PrinterName extends StringObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"printerName\");\n  }\n}\nclass Producer extends StringObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"producer\");\n  }\n}\nclass Ps extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"ps\", true);\n    this.name = attributes.name || \"\";\n    this.batchOutput = null;\n    this.fontInfo = null;\n    this.jog = null;\n    this.mediumInfo = null;\n    this.outputBin = null;\n    this.staple = null;\n    this.xdc = null;\n  }\n}\nclass Range extends ContentObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"range\");\n  }\n  [$finalize]() {\n    this[$content] = this[$content].trim().split(/\\s*,\\s*/, 2).map(range => range.split(\"-\").map(x => parseInt(x.trim(), 10))).filter(range => range.every(x => !isNaN(x))).map(range => {\n      if (range.length === 1) {\n        range.push(range[0]);\n      }\n      return range;\n    });\n  }\n}\nclass Record extends ContentObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"record\");\n  }\n  [$finalize]() {\n    this[$content] = this[$content].trim();\n    const n = parseInt(this[$content], 10);\n    if (!isNaN(n) && n >= 0) {\n      this[$content] = n;\n    }\n  }\n}\nclass Relevant extends ContentObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"relevant\");\n  }\n  [$finalize]() {\n    this[$content] = this[$content].trim().split(/\\s+/);\n  }\n}\nclass Rename extends ContentObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"rename\");\n  }\n  [$finalize]() {\n    this[$content] = this[$content].trim();\n    if (this[$content].toLowerCase().startsWith(\"xml\") || new RegExp(\"[\\\\p{L}_][\\\\p{L}\\\\d._\\\\p{M}-]*\", \"u\").test(this[$content])) {\n      warn(\"XFA - Rename: invalid XFA name\");\n    }\n  }\n}\nclass RenderPolicy extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"renderPolicy\", [\"server\", \"client\"]);\n  }\n}\nclass RunScripts extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"runScripts\", [\"both\", \"client\", \"none\", \"server\"]);\n  }\n}\nclass config_Script extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"script\", true);\n    this.currentPage = null;\n    this.exclude = null;\n    this.runScripts = null;\n  }\n}\nclass ScriptModel extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"scriptModel\", [\"XFA\", \"none\"]);\n  }\n}\nclass Severity extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"severity\", [\"ignore\", \"error\", \"information\", \"trace\", \"warning\"]);\n  }\n}\nclass SilentPrint extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"silentPrint\", true);\n    this.addSilentPrint = null;\n    this.printerName = null;\n  }\n}\nclass Staple extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"staple\");\n    this.mode = getStringOption(attributes.mode, [\"usePrinterSetting\", \"on\", \"off\"]);\n  }\n}\nclass StartNode extends StringObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"startNode\");\n  }\n}\nclass StartPage extends IntegerObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"startPage\", 0, n => true);\n  }\n}\nclass SubmitFormat extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"submitFormat\", [\"html\", \"delegate\", \"fdf\", \"xml\", \"pdf\"]);\n  }\n}\nclass SubmitUrl extends StringObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"submitUrl\");\n  }\n}\nclass SubsetBelow extends IntegerObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"subsetBelow\", 100, n => n >= 0 && n <= 100);\n  }\n}\nclass SuppressBanner extends Option01 {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"suppressBanner\");\n  }\n}\nclass Tagged extends Option01 {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"tagged\");\n  }\n}\nclass config_Template extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"template\", true);\n    this.base = null;\n    this.relevant = null;\n    this.startPage = null;\n    this.uri = null;\n    this.xsl = null;\n  }\n}\nclass Threshold extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"threshold\", [\"trace\", \"error\", \"information\", \"warning\"]);\n  }\n}\nclass To extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"to\", [\"null\", \"memory\", \"stderr\", \"stdout\", \"system\", \"uri\"]);\n  }\n}\nclass TemplateCache extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"templateCache\");\n    this.maxEntries = getInteger({\n      data: attributes.maxEntries,\n      defaultValue: 5,\n      validate: n => n >= 0\n    });\n  }\n}\nclass Trace extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"trace\", true);\n    this.area = new XFAObjectArray();\n  }\n}\nclass Transform extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"transform\", true);\n    this.groupParent = null;\n    this.ifEmpty = null;\n    this.nameAttr = null;\n    this.picture = null;\n    this.presence = null;\n    this.rename = null;\n    this.whitespace = null;\n  }\n}\nclass Type extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"type\", [\"none\", \"ascii85\", \"asciiHex\", \"ccittfax\", \"flate\", \"lzw\", \"runLength\", \"native\", \"xdp\", \"mergedXDP\"]);\n  }\n}\nclass Uri extends StringObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"uri\");\n  }\n}\nclass config_Validate extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"validate\", [\"preSubmit\", \"prePrint\", \"preExecute\", \"preSave\"]);\n  }\n}\nclass ValidateApprovalSignatures extends ContentObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"validateApprovalSignatures\");\n  }\n  [$finalize]() {\n    this[$content] = this[$content].trim().split(/\\s+/).filter(x => [\"docReady\", \"postSign\"].includes(x));\n  }\n}\nclass ValidationMessaging extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"validationMessaging\", [\"allMessagesIndividually\", \"allMessagesTogether\", \"firstMessageOnly\", \"noMessages\"]);\n  }\n}\nclass Version extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"version\", [\"1.7\", \"1.6\", \"1.5\", \"1.4\", \"1.3\", \"1.2\"]);\n  }\n}\nclass VersionControl extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"VersionControl\");\n    this.outputBelow = getStringOption(attributes.outputBelow, [\"warn\", \"error\", \"update\"]);\n    this.sourceAbove = getStringOption(attributes.sourceAbove, [\"warn\", \"error\"]);\n    this.sourceBelow = getStringOption(attributes.sourceBelow, [\"update\", \"maintain\"]);\n  }\n}\nclass ViewerPreferences extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"viewerPreferences\", true);\n    this.ADBE_JSConsole = null;\n    this.ADBE_JSDebugger = null;\n    this.addViewerPreferences = null;\n    this.duplexOption = null;\n    this.enforce = null;\n    this.numberOfCopies = null;\n    this.pageRange = null;\n    this.pickTrayByPDFSize = null;\n    this.printScaling = null;\n  }\n}\nclass WebClient extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"webClient\", true);\n    this.name = attributes.name ? attributes.name.trim() : \"\";\n    this.fontInfo = null;\n    this.xdc = null;\n  }\n}\nclass Whitespace extends OptionObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"whitespace\", [\"preserve\", \"ltrim\", \"normalize\", \"rtrim\", \"trim\"]);\n  }\n}\nclass Window extends ContentObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"window\");\n  }\n  [$finalize]() {\n    const pair = this[$content].trim().split(/\\s*,\\s*/, 2).map(x => parseInt(x, 10));\n    if (pair.some(x => isNaN(x))) {\n      this[$content] = [0, 0];\n      return;\n    }\n    if (pair.length === 1) {\n      pair.push(pair[0]);\n    }\n    this[$content] = pair;\n  }\n}\nclass Xdc extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"xdc\", true);\n    this.uri = new XFAObjectArray();\n    this.xsl = new XFAObjectArray();\n  }\n}\nclass Xdp extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"xdp\", true);\n    this.packets = null;\n  }\n}\nclass Xsl extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"xsl\", true);\n    this.debug = null;\n    this.uri = null;\n  }\n}\nclass Zpl extends XFAObject {\n  constructor(attributes) {\n    super(CONFIG_NS_ID, \"zpl\", true);\n    this.name = attributes.name ? attributes.name.trim() : \"\";\n    this.batchOutput = null;\n    this.flipLabel = null;\n    this.fontInfo = null;\n    this.xdc = null;\n  }\n}\nclass ConfigNamespace {\n  static [$buildXFAObject](name, attributes) {\n    if (ConfigNamespace.hasOwnProperty(name)) {\n      return ConfigNamespace[name](attributes);\n    }\n    return undefined;\n  }\n  static acrobat(attrs) {\n    return new Acrobat(attrs);\n  }\n  static acrobat7(attrs) {\n    return new Acrobat7(attrs);\n  }\n  static ADBE_JSConsole(attrs) {\n    return new ADBE_JSConsole(attrs);\n  }\n  static ADBE_JSDebugger(attrs) {\n    return new ADBE_JSDebugger(attrs);\n  }\n  static addSilentPrint(attrs) {\n    return new AddSilentPrint(attrs);\n  }\n  static addViewerPreferences(attrs) {\n    return new AddViewerPreferences(attrs);\n  }\n  static adjustData(attrs) {\n    return new AdjustData(attrs);\n  }\n  static adobeExtensionLevel(attrs) {\n    return new AdobeExtensionLevel(attrs);\n  }\n  static agent(attrs) {\n    return new Agent(attrs);\n  }\n  static alwaysEmbed(attrs) {\n    return new AlwaysEmbed(attrs);\n  }\n  static amd(attrs) {\n    return new Amd(attrs);\n  }\n  static area(attrs) {\n    return new config_Area(attrs);\n  }\n  static attributes(attrs) {\n    return new Attributes(attrs);\n  }\n  static autoSave(attrs) {\n    return new AutoSave(attrs);\n  }\n  static base(attrs) {\n    return new Base(attrs);\n  }\n  static batchOutput(attrs) {\n    return new BatchOutput(attrs);\n  }\n  static behaviorOverride(attrs) {\n    return new BehaviorOverride(attrs);\n  }\n  static cache(attrs) {\n    return new Cache(attrs);\n  }\n  static change(attrs) {\n    return new Change(attrs);\n  }\n  static common(attrs) {\n    return new Common(attrs);\n  }\n  static compress(attrs) {\n    return new Compress(attrs);\n  }\n  static compressLogicalStructure(attrs) {\n    return new CompressLogicalStructure(attrs);\n  }\n  static compressObjectStream(attrs) {\n    return new CompressObjectStream(attrs);\n  }\n  static compression(attrs) {\n    return new Compression(attrs);\n  }\n  static config(attrs) {\n    return new Config(attrs);\n  }\n  static conformance(attrs) {\n    return new Conformance(attrs);\n  }\n  static contentCopy(attrs) {\n    return new ContentCopy(attrs);\n  }\n  static copies(attrs) {\n    return new Copies(attrs);\n  }\n  static creator(attrs) {\n    return new Creator(attrs);\n  }\n  static currentPage(attrs) {\n    return new CurrentPage(attrs);\n  }\n  static data(attrs) {\n    return new Data(attrs);\n  }\n  static debug(attrs) {\n    return new Debug(attrs);\n  }\n  static defaultTypeface(attrs) {\n    return new DefaultTypeface(attrs);\n  }\n  static destination(attrs) {\n    return new Destination(attrs);\n  }\n  static documentAssembly(attrs) {\n    return new DocumentAssembly(attrs);\n  }\n  static driver(attrs) {\n    return new Driver(attrs);\n  }\n  static duplexOption(attrs) {\n    return new DuplexOption(attrs);\n  }\n  static dynamicRender(attrs) {\n    return new DynamicRender(attrs);\n  }\n  static embed(attrs) {\n    return new Embed(attrs);\n  }\n  static encrypt(attrs) {\n    return new config_Encrypt(attrs);\n  }\n  static encryption(attrs) {\n    return new config_Encryption(attrs);\n  }\n  static encryptionLevel(attrs) {\n    return new EncryptionLevel(attrs);\n  }\n  static enforce(attrs) {\n    return new Enforce(attrs);\n  }\n  static equate(attrs) {\n    return new Equate(attrs);\n  }\n  static equateRange(attrs) {\n    return new EquateRange(attrs);\n  }\n  static exclude(attrs) {\n    return new Exclude(attrs);\n  }\n  static excludeNS(attrs) {\n    return new ExcludeNS(attrs);\n  }\n  static flipLabel(attrs) {\n    return new FlipLabel(attrs);\n  }\n  static fontInfo(attrs) {\n    return new config_FontInfo(attrs);\n  }\n  static formFieldFilling(attrs) {\n    return new FormFieldFilling(attrs);\n  }\n  static groupParent(attrs) {\n    return new GroupParent(attrs);\n  }\n  static ifEmpty(attrs) {\n    return new IfEmpty(attrs);\n  }\n  static includeXDPContent(attrs) {\n    return new IncludeXDPContent(attrs);\n  }\n  static incrementalLoad(attrs) {\n    return new IncrementalLoad(attrs);\n  }\n  static incrementalMerge(attrs) {\n    return new IncrementalMerge(attrs);\n  }\n  static interactive(attrs) {\n    return new Interactive(attrs);\n  }\n  static jog(attrs) {\n    return new Jog(attrs);\n  }\n  static labelPrinter(attrs) {\n    return new LabelPrinter(attrs);\n  }\n  static layout(attrs) {\n    return new Layout(attrs);\n  }\n  static level(attrs) {\n    return new Level(attrs);\n  }\n  static linearized(attrs) {\n    return new Linearized(attrs);\n  }\n  static locale(attrs) {\n    return new Locale(attrs);\n  }\n  static localeSet(attrs) {\n    return new LocaleSet(attrs);\n  }\n  static log(attrs) {\n    return new Log(attrs);\n  }\n  static map(attrs) {\n    return new MapElement(attrs);\n  }\n  static mediumInfo(attrs) {\n    return new MediumInfo(attrs);\n  }\n  static message(attrs) {\n    return new config_Message(attrs);\n  }\n  static messaging(attrs) {\n    return new Messaging(attrs);\n  }\n  static mode(attrs) {\n    return new Mode(attrs);\n  }\n  static modifyAnnots(attrs) {\n    return new ModifyAnnots(attrs);\n  }\n  static msgId(attrs) {\n    return new MsgId(attrs);\n  }\n  static nameAttr(attrs) {\n    return new NameAttr(attrs);\n  }\n  static neverEmbed(attrs) {\n    return new NeverEmbed(attrs);\n  }\n  static numberOfCopies(attrs) {\n    return new NumberOfCopies(attrs);\n  }\n  static openAction(attrs) {\n    return new OpenAction(attrs);\n  }\n  static output(attrs) {\n    return new Output(attrs);\n  }\n  static outputBin(attrs) {\n    return new OutputBin(attrs);\n  }\n  static outputXSL(attrs) {\n    return new OutputXSL(attrs);\n  }\n  static overprint(attrs) {\n    return new Overprint(attrs);\n  }\n  static packets(attrs) {\n    return new Packets(attrs);\n  }\n  static pageOffset(attrs) {\n    return new PageOffset(attrs);\n  }\n  static pageRange(attrs) {\n    return new PageRange(attrs);\n  }\n  static pagination(attrs) {\n    return new Pagination(attrs);\n  }\n  static paginationOverride(attrs) {\n    return new PaginationOverride(attrs);\n  }\n  static part(attrs) {\n    return new Part(attrs);\n  }\n  static pcl(attrs) {\n    return new Pcl(attrs);\n  }\n  static pdf(attrs) {\n    return new Pdf(attrs);\n  }\n  static pdfa(attrs) {\n    return new Pdfa(attrs);\n  }\n  static permissions(attrs) {\n    return new Permissions(attrs);\n  }\n  static pickTrayByPDFSize(attrs) {\n    return new PickTrayByPDFSize(attrs);\n  }\n  static picture(attrs) {\n    return new config_Picture(attrs);\n  }\n  static plaintextMetadata(attrs) {\n    return new PlaintextMetadata(attrs);\n  }\n  static presence(attrs) {\n    return new Presence(attrs);\n  }\n  static present(attrs) {\n    return new Present(attrs);\n  }\n  static print(attrs) {\n    return new Print(attrs);\n  }\n  static printHighQuality(attrs) {\n    return new PrintHighQuality(attrs);\n  }\n  static printScaling(attrs) {\n    return new PrintScaling(attrs);\n  }\n  static printerName(attrs) {\n    return new PrinterName(attrs);\n  }\n  static producer(attrs) {\n    return new Producer(attrs);\n  }\n  static ps(attrs) {\n    return new Ps(attrs);\n  }\n  static range(attrs) {\n    return new Range(attrs);\n  }\n  static record(attrs) {\n    return new Record(attrs);\n  }\n  static relevant(attrs) {\n    return new Relevant(attrs);\n  }\n  static rename(attrs) {\n    return new Rename(attrs);\n  }\n  static renderPolicy(attrs) {\n    return new RenderPolicy(attrs);\n  }\n  static runScripts(attrs) {\n    return new RunScripts(attrs);\n  }\n  static script(attrs) {\n    return new config_Script(attrs);\n  }\n  static scriptModel(attrs) {\n    return new ScriptModel(attrs);\n  }\n  static severity(attrs) {\n    return new Severity(attrs);\n  }\n  static silentPrint(attrs) {\n    return new SilentPrint(attrs);\n  }\n  static staple(attrs) {\n    return new Staple(attrs);\n  }\n  static startNode(attrs) {\n    return new StartNode(attrs);\n  }\n  static startPage(attrs) {\n    return new StartPage(attrs);\n  }\n  static submitFormat(attrs) {\n    return new SubmitFormat(attrs);\n  }\n  static submitUrl(attrs) {\n    return new SubmitUrl(attrs);\n  }\n  static subsetBelow(attrs) {\n    return new SubsetBelow(attrs);\n  }\n  static suppressBanner(attrs) {\n    return new SuppressBanner(attrs);\n  }\n  static tagged(attrs) {\n    return new Tagged(attrs);\n  }\n  static template(attrs) {\n    return new config_Template(attrs);\n  }\n  static templateCache(attrs) {\n    return new TemplateCache(attrs);\n  }\n  static threshold(attrs) {\n    return new Threshold(attrs);\n  }\n  static to(attrs) {\n    return new To(attrs);\n  }\n  static trace(attrs) {\n    return new Trace(attrs);\n  }\n  static transform(attrs) {\n    return new Transform(attrs);\n  }\n  static type(attrs) {\n    return new Type(attrs);\n  }\n  static uri(attrs) {\n    return new Uri(attrs);\n  }\n  static validate(attrs) {\n    return new config_Validate(attrs);\n  }\n  static validateApprovalSignatures(attrs) {\n    return new ValidateApprovalSignatures(attrs);\n  }\n  static validationMessaging(attrs) {\n    return new ValidationMessaging(attrs);\n  }\n  static version(attrs) {\n    return new Version(attrs);\n  }\n  static versionControl(attrs) {\n    return new VersionControl(attrs);\n  }\n  static viewerPreferences(attrs) {\n    return new ViewerPreferences(attrs);\n  }\n  static webClient(attrs) {\n    return new WebClient(attrs);\n  }\n  static whitespace(attrs) {\n    return new Whitespace(attrs);\n  }\n  static window(attrs) {\n    return new Window(attrs);\n  }\n  static xdc(attrs) {\n    return new Xdc(attrs);\n  }\n  static xdp(attrs) {\n    return new Xdp(attrs);\n  }\n  static xsl(attrs) {\n    return new Xsl(attrs);\n  }\n  static zpl(attrs) {\n    return new Zpl(attrs);\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/xfa/connection_set.js\n\n\nconst CONNECTION_SET_NS_ID = NamespaceIds.connectionSet.id;\nclass ConnectionSet extends XFAObject {\n  constructor(attributes) {\n    super(CONNECTION_SET_NS_ID, \"connectionSet\", true);\n    this.wsdlConnection = new XFAObjectArray();\n    this.xmlConnection = new XFAObjectArray();\n    this.xsdConnection = new XFAObjectArray();\n  }\n}\nclass EffectiveInputPolicy extends XFAObject {\n  constructor(attributes) {\n    super(CONNECTION_SET_NS_ID, \"effectiveInputPolicy\");\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass EffectiveOutputPolicy extends XFAObject {\n  constructor(attributes) {\n    super(CONNECTION_SET_NS_ID, \"effectiveOutputPolicy\");\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass Operation extends StringObject {\n  constructor(attributes) {\n    super(CONNECTION_SET_NS_ID, \"operation\");\n    this.id = attributes.id || \"\";\n    this.input = attributes.input || \"\";\n    this.name = attributes.name || \"\";\n    this.output = attributes.output || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass RootElement extends StringObject {\n  constructor(attributes) {\n    super(CONNECTION_SET_NS_ID, \"rootElement\");\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass SoapAction extends StringObject {\n  constructor(attributes) {\n    super(CONNECTION_SET_NS_ID, \"soapAction\");\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass SoapAddress extends StringObject {\n  constructor(attributes) {\n    super(CONNECTION_SET_NS_ID, \"soapAddress\");\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass connection_set_Uri extends StringObject {\n  constructor(attributes) {\n    super(CONNECTION_SET_NS_ID, \"uri\");\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass WsdlAddress extends StringObject {\n  constructor(attributes) {\n    super(CONNECTION_SET_NS_ID, \"wsdlAddress\");\n    this.id = attributes.id || \"\";\n    this.name = attributes.name || \"\";\n    this.use = attributes.use || \"\";\n    this.usehref = attributes.usehref || \"\";\n  }\n}\nclass WsdlConnection extends XFAObject {\n  constructor(attributes) {\n    super(CONNECTION_SET_NS_ID, \"wsdlConnection\", true);\n    this.dataDescription = attributes.dataDescription || \"\";\n    this.name = attributes.name || \"\";\n    this.effectiveInputPolicy = null;\n    this.effectiveOutputPolicy = null;\n    this.operation = null;\n    this.soapAction = null;\n    this.soapAddress = null;\n    this.wsdlAddress = null;\n  }\n}\nclass XmlConnection extends XFAObject {\n  constructor(attributes) {\n    super(CONNECTION_SET_NS_ID, \"xmlConnection\", true);\n    this.dataDescription = attributes.dataDescription || \"\";\n    this.name = attributes.name || \"\";\n    this.uri = null;\n  }\n}\nclass XsdConnection extends XFAObject {\n  constructor(attributes) {\n    super(CONNECTION_SET_NS_ID, \"xsdConnection\", true);\n    this.dataDescription = attributes.dataDescription || \"\";\n    this.name = attributes.name || \"\";\n    this.rootElement = null;\n    this.uri = null;\n  }\n}\nclass ConnectionSetNamespace {\n  static [$buildXFAObject](name, attributes) {\n    if (ConnectionSetNamespace.hasOwnProperty(name)) {\n      return ConnectionSetNamespace[name](attributes);\n    }\n    return undefined;\n  }\n  static connectionSet(attrs) {\n    return new ConnectionSet(attrs);\n  }\n  static effectiveInputPolicy(attrs) {\n    return new EffectiveInputPolicy(attrs);\n  }\n  static effectiveOutputPolicy(attrs) {\n    return new EffectiveOutputPolicy(attrs);\n  }\n  static operation(attrs) {\n    return new Operation(attrs);\n  }\n  static rootElement(attrs) {\n    return new RootElement(attrs);\n  }\n  static soapAction(attrs) {\n    return new SoapAction(attrs);\n  }\n  static soapAddress(attrs) {\n    return new SoapAddress(attrs);\n  }\n  static uri(attrs) {\n    return new connection_set_Uri(attrs);\n  }\n  static wsdlAddress(attrs) {\n    return new WsdlAddress(attrs);\n  }\n  static wsdlConnection(attrs) {\n    return new WsdlConnection(attrs);\n  }\n  static xmlConnection(attrs) {\n    return new XmlConnection(attrs);\n  }\n  static xsdConnection(attrs) {\n    return new XsdConnection(attrs);\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/xfa/datasets.js\n\n\n\nconst DATASETS_NS_ID = NamespaceIds.datasets.id;\nclass datasets_Data extends XmlObject {\n  constructor(attributes) {\n    super(DATASETS_NS_ID, \"data\", attributes);\n  }\n  [$isNsAgnostic]() {\n    return true;\n  }\n}\nclass Datasets extends XFAObject {\n  constructor(attributes) {\n    super(DATASETS_NS_ID, \"datasets\", true);\n    this.data = null;\n    this.Signature = null;\n  }\n  [$onChild](child) {\n    const name = child[$nodeName];\n    if (name === \"data\" && child[$namespaceId] === DATASETS_NS_ID || name === \"Signature\" && child[$namespaceId] === NamespaceIds.signature.id) {\n      this[name] = child;\n    }\n    this[$appendChild](child);\n  }\n}\nclass DatasetsNamespace {\n  static [$buildXFAObject](name, attributes) {\n    if (DatasetsNamespace.hasOwnProperty(name)) {\n      return DatasetsNamespace[name](attributes);\n    }\n    return undefined;\n  }\n  static datasets(attributes) {\n    return new Datasets(attributes);\n  }\n  static data(attributes) {\n    return new datasets_Data(attributes);\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/xfa/locale_set.js\n\n\n\nconst LOCALE_SET_NS_ID = NamespaceIds.localeSet.id;\nclass CalendarSymbols extends XFAObject {\n  constructor(attributes) {\n    super(LOCALE_SET_NS_ID, \"calendarSymbols\", true);\n    this.name = \"gregorian\";\n    this.dayNames = new XFAObjectArray(2);\n    this.eraNames = null;\n    this.meridiemNames = null;\n    this.monthNames = new XFAObjectArray(2);\n  }\n}\nclass CurrencySymbol extends StringObject {\n  constructor(attributes) {\n    super(LOCALE_SET_NS_ID, \"currencySymbol\");\n    this.name = getStringOption(attributes.name, [\"symbol\", \"isoname\", \"decimal\"]);\n  }\n}\nclass CurrencySymbols extends XFAObject {\n  constructor(attributes) {\n    super(LOCALE_SET_NS_ID, \"currencySymbols\", true);\n    this.currencySymbol = new XFAObjectArray(3);\n  }\n}\nclass DatePattern extends StringObject {\n  constructor(attributes) {\n    super(LOCALE_SET_NS_ID, \"datePattern\");\n    this.name = getStringOption(attributes.name, [\"full\", \"long\", \"med\", \"short\"]);\n  }\n}\nclass DatePatterns extends XFAObject {\n  constructor(attributes) {\n    super(LOCALE_SET_NS_ID, \"datePatterns\", true);\n    this.datePattern = new XFAObjectArray(4);\n  }\n}\nclass DateTimeSymbols extends ContentObject {\n  constructor(attributes) {\n    super(LOCALE_SET_NS_ID, \"dateTimeSymbols\");\n  }\n}\nclass Day extends StringObject {\n  constructor(attributes) {\n    super(LOCALE_SET_NS_ID, \"day\");\n  }\n}\nclass DayNames extends XFAObject {\n  constructor(attributes) {\n    super(LOCALE_SET_NS_ID, \"dayNames\", true);\n    this.abbr = getInteger({\n      data: attributes.abbr,\n      defaultValue: 0,\n      validate: x => x === 1\n    });\n    this.day = new XFAObjectArray(7);\n  }\n}\nclass Era extends StringObject {\n  constructor(attributes) {\n    super(LOCALE_SET_NS_ID, \"era\");\n  }\n}\nclass EraNames extends XFAObject {\n  constructor(attributes) {\n    super(LOCALE_SET_NS_ID, \"eraNames\", true);\n    this.era = new XFAObjectArray(2);\n  }\n}\nclass locale_set_Locale extends XFAObject {\n  constructor(attributes) {\n    super(LOCALE_SET_NS_ID, \"locale\", true);\n    this.desc = attributes.desc || \"\";\n    this.name = \"isoname\";\n    this.calendarSymbols = null;\n    this.currencySymbols = null;\n    this.datePatterns = null;\n    this.dateTimeSymbols = null;\n    this.numberPatterns = null;\n    this.numberSymbols = null;\n    this.timePatterns = null;\n    this.typeFaces = null;\n  }\n}\nclass locale_set_LocaleSet extends XFAObject {\n  constructor(attributes) {\n    super(LOCALE_SET_NS_ID, \"localeSet\", true);\n    this.locale = new XFAObjectArray();\n  }\n}\nclass Meridiem extends StringObject {\n  constructor(attributes) {\n    super(LOCALE_SET_NS_ID, \"meridiem\");\n  }\n}\nclass MeridiemNames extends XFAObject {\n  constructor(attributes) {\n    super(LOCALE_SET_NS_ID, \"meridiemNames\", true);\n    this.meridiem = new XFAObjectArray(2);\n  }\n}\nclass Month extends StringObject {\n  constructor(attributes) {\n    super(LOCALE_SET_NS_ID, \"month\");\n  }\n}\nclass MonthNames extends XFAObject {\n  constructor(attributes) {\n    super(LOCALE_SET_NS_ID, \"monthNames\", true);\n    this.abbr = getInteger({\n      data: attributes.abbr,\n      defaultValue: 0,\n      validate: x => x === 1\n    });\n    this.month = new XFAObjectArray(12);\n  }\n}\nclass NumberPattern extends StringObject {\n  constructor(attributes) {\n    super(LOCALE_SET_NS_ID, \"numberPattern\");\n    this.name = getStringOption(attributes.name, [\"full\", \"long\", \"med\", \"short\"]);\n  }\n}\nclass NumberPatterns extends XFAObject {\n  constructor(attributes) {\n    super(LOCALE_SET_NS_ID, \"numberPatterns\", true);\n    this.numberPattern = new XFAObjectArray(4);\n  }\n}\nclass NumberSymbol extends StringObject {\n  constructor(attributes) {\n    super(LOCALE_SET_NS_ID, \"numberSymbol\");\n    this.name = getStringOption(attributes.name, [\"decimal\", \"grouping\", \"percent\", \"minus\", \"zero\"]);\n  }\n}\nclass NumberSymbols extends XFAObject {\n  constructor(attributes) {\n    super(LOCALE_SET_NS_ID, \"numberSymbols\", true);\n    this.numberSymbol = new XFAObjectArray(5);\n  }\n}\nclass TimePattern extends StringObject {\n  constructor(attributes) {\n    super(LOCALE_SET_NS_ID, \"timePattern\");\n    this.name = getStringOption(attributes.name, [\"full\", \"long\", \"med\", \"short\"]);\n  }\n}\nclass TimePatterns extends XFAObject {\n  constructor(attributes) {\n    super(LOCALE_SET_NS_ID, \"timePatterns\", true);\n    this.timePattern = new XFAObjectArray(4);\n  }\n}\nclass TypeFace extends XFAObject {\n  constructor(attributes) {\n    super(LOCALE_SET_NS_ID, \"typeFace\", true);\n    this.name = attributes.name | \"\";\n  }\n}\nclass TypeFaces extends XFAObject {\n  constructor(attributes) {\n    super(LOCALE_SET_NS_ID, \"typeFaces\", true);\n    this.typeFace = new XFAObjectArray();\n  }\n}\nclass LocaleSetNamespace {\n  static [$buildXFAObject](name, attributes) {\n    if (LocaleSetNamespace.hasOwnProperty(name)) {\n      return LocaleSetNamespace[name](attributes);\n    }\n    return undefined;\n  }\n  static calendarSymbols(attrs) {\n    return new CalendarSymbols(attrs);\n  }\n  static currencySymbol(attrs) {\n    return new CurrencySymbol(attrs);\n  }\n  static currencySymbols(attrs) {\n    return new CurrencySymbols(attrs);\n  }\n  static datePattern(attrs) {\n    return new DatePattern(attrs);\n  }\n  static datePatterns(attrs) {\n    return new DatePatterns(attrs);\n  }\n  static dateTimeSymbols(attrs) {\n    return new DateTimeSymbols(attrs);\n  }\n  static day(attrs) {\n    return new Day(attrs);\n  }\n  static dayNames(attrs) {\n    return new DayNames(attrs);\n  }\n  static era(attrs) {\n    return new Era(attrs);\n  }\n  static eraNames(attrs) {\n    return new EraNames(attrs);\n  }\n  static locale(attrs) {\n    return new locale_set_Locale(attrs);\n  }\n  static localeSet(attrs) {\n    return new locale_set_LocaleSet(attrs);\n  }\n  static meridiem(attrs) {\n    return new Meridiem(attrs);\n  }\n  static meridiemNames(attrs) {\n    return new MeridiemNames(attrs);\n  }\n  static month(attrs) {\n    return new Month(attrs);\n  }\n  static monthNames(attrs) {\n    return new MonthNames(attrs);\n  }\n  static numberPattern(attrs) {\n    return new NumberPattern(attrs);\n  }\n  static numberPatterns(attrs) {\n    return new NumberPatterns(attrs);\n  }\n  static numberSymbol(attrs) {\n    return new NumberSymbol(attrs);\n  }\n  static numberSymbols(attrs) {\n    return new NumberSymbols(attrs);\n  }\n  static timePattern(attrs) {\n    return new TimePattern(attrs);\n  }\n  static timePatterns(attrs) {\n    return new TimePatterns(attrs);\n  }\n  static typeFace(attrs) {\n    return new TypeFace(attrs);\n  }\n  static typeFaces(attrs) {\n    return new TypeFaces(attrs);\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/xfa/signature.js\n\n\nconst SIGNATURE_NS_ID = NamespaceIds.signature.id;\nclass signature_Signature extends XFAObject {\n  constructor(attributes) {\n    super(SIGNATURE_NS_ID, \"signature\", true);\n  }\n}\nclass SignatureNamespace {\n  static [$buildXFAObject](name, attributes) {\n    if (SignatureNamespace.hasOwnProperty(name)) {\n      return SignatureNamespace[name](attributes);\n    }\n    return undefined;\n  }\n  static signature(attributes) {\n    return new signature_Signature(attributes);\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/xfa/stylesheet.js\n\n\nconst STYLESHEET_NS_ID = NamespaceIds.stylesheet.id;\nclass Stylesheet extends XFAObject {\n  constructor(attributes) {\n    super(STYLESHEET_NS_ID, \"stylesheet\", true);\n  }\n}\nclass StylesheetNamespace {\n  static [$buildXFAObject](name, attributes) {\n    if (StylesheetNamespace.hasOwnProperty(name)) {\n      return StylesheetNamespace[name](attributes);\n    }\n    return undefined;\n  }\n  static stylesheet(attributes) {\n    return new Stylesheet(attributes);\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/xfa/xdp.js\n\n\n\nconst XDP_NS_ID = NamespaceIds.xdp.id;\nclass xdp_Xdp extends XFAObject {\n  constructor(attributes) {\n    super(XDP_NS_ID, \"xdp\", true);\n    this.uuid = attributes.uuid || \"\";\n    this.timeStamp = attributes.timeStamp || \"\";\n    this.config = null;\n    this.connectionSet = null;\n    this.datasets = null;\n    this.localeSet = null;\n    this.stylesheet = new XFAObjectArray();\n    this.template = null;\n  }\n  [$onChildCheck](child) {\n    const ns = NamespaceIds[child[$nodeName]];\n    return ns && child[$namespaceId] === ns.id;\n  }\n}\nclass XdpNamespace {\n  static [$buildXFAObject](name, attributes) {\n    if (XdpNamespace.hasOwnProperty(name)) {\n      return XdpNamespace[name](attributes);\n    }\n    return undefined;\n  }\n  static xdp(attributes) {\n    return new xdp_Xdp(attributes);\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/xfa/xhtml.js\n\n\n\n\n\nconst XHTML_NS_ID = NamespaceIds.xhtml.id;\nconst $richText = Symbol();\nconst VALID_STYLES = new Set([\"color\", \"font\", \"font-family\", \"font-size\", \"font-stretch\", \"font-style\", \"font-weight\", \"margin\", \"margin-bottom\", \"margin-left\", \"margin-right\", \"margin-top\", \"letter-spacing\", \"line-height\", \"orphans\", \"page-break-after\", \"page-break-before\", \"page-break-inside\", \"tab-interval\", \"tab-stop\", \"text-align\", \"text-decoration\", \"text-indent\", \"vertical-align\", \"widows\", \"kerning-mode\", \"xfa-font-horizontal-scale\", \"xfa-font-vertical-scale\", \"xfa-spacerun\", \"xfa-tab-stops\"]);\nconst StyleMapping = new Map([[\"page-break-after\", \"breakAfter\"], [\"page-break-before\", \"breakBefore\"], [\"page-break-inside\", \"breakInside\"], [\"kerning-mode\", value => value === \"none\" ? \"none\" : \"normal\"], [\"xfa-font-horizontal-scale\", value => `scaleX(${Math.max(0, Math.min(parseInt(value) / 100)).toFixed(2)})`], [\"xfa-font-vertical-scale\", value => `scaleY(${Math.max(0, Math.min(parseInt(value) / 100)).toFixed(2)})`], [\"xfa-spacerun\", \"\"], [\"xfa-tab-stops\", \"\"], [\"font-size\", (value, original) => {\n  value = original.fontSize = getMeasurement(value);\n  return measureToString(0.99 * value);\n}], [\"letter-spacing\", value => measureToString(getMeasurement(value))], [\"line-height\", value => measureToString(getMeasurement(value))], [\"margin\", value => measureToString(getMeasurement(value))], [\"margin-bottom\", value => measureToString(getMeasurement(value))], [\"margin-left\", value => measureToString(getMeasurement(value))], [\"margin-right\", value => measureToString(getMeasurement(value))], [\"margin-top\", value => measureToString(getMeasurement(value))], [\"text-indent\", value => measureToString(getMeasurement(value))], [\"font-family\", value => value], [\"vertical-align\", value => measureToString(getMeasurement(value))]]);\nconst spacesRegExp = /\\s+/g;\nconst crlfRegExp = /[\\r\\n]+/g;\nconst crlfForRichTextRegExp = /\\r\\n?/g;\nfunction mapStyle(styleStr, node, richText) {\n  const style = Object.create(null);\n  if (!styleStr) {\n    return style;\n  }\n  const original = Object.create(null);\n  for (const [key, value] of styleStr.split(\";\").map(s => s.split(\":\", 2))) {\n    const mapping = StyleMapping.get(key);\n    if (mapping === \"\") {\n      continue;\n    }\n    let newValue = value;\n    if (mapping) {\n      newValue = typeof mapping === \"string\" ? mapping : mapping(value, original);\n    }\n    if (key.endsWith(\"scale\")) {\n      style.transform = style.transform ? `${style[key]} ${newValue}` : newValue;\n    } else {\n      style[key.replaceAll(/-([a-zA-Z])/g, (_, x) => x.toUpperCase())] = newValue;\n    }\n  }\n  if (style.fontFamily) {\n    setFontFamily({\n      typeface: style.fontFamily,\n      weight: style.fontWeight || \"normal\",\n      posture: style.fontStyle || \"normal\",\n      size: original.fontSize || 0\n    }, node, node[$globalData].fontFinder, style);\n  }\n  if (richText && style.verticalAlign && style.verticalAlign !== \"0px\" && style.fontSize) {\n    const SUB_SUPER_SCRIPT_FACTOR = 0.583;\n    const VERTICAL_FACTOR = 0.333;\n    const fontSize = getMeasurement(style.fontSize);\n    style.fontSize = measureToString(fontSize * SUB_SUPER_SCRIPT_FACTOR);\n    style.verticalAlign = measureToString(Math.sign(getMeasurement(style.verticalAlign)) * fontSize * VERTICAL_FACTOR);\n  }\n  if (richText && style.fontSize) {\n    style.fontSize = `calc(${style.fontSize} * var(--scale-factor))`;\n  }\n  fixTextIndent(style);\n  return style;\n}\nfunction checkStyle(node) {\n  if (!node.style) {\n    return \"\";\n  }\n  return node.style.trim().split(/\\s*;\\s*/).filter(s => !!s).map(s => s.split(/\\s*:\\s*/, 2)).filter(([key, value]) => {\n    if (key === \"font-family\") {\n      node[$globalData].usedTypefaces.add(value);\n    }\n    return VALID_STYLES.has(key);\n  }).map(kv => kv.join(\":\")).join(\";\");\n}\nconst NoWhites = new Set([\"body\", \"html\"]);\nclass XhtmlObject extends XmlObject {\n  constructor(attributes, name) {\n    super(XHTML_NS_ID, name);\n    this[$richText] = false;\n    this.style = attributes.style || \"\";\n  }\n  [$clean](builder) {\n    super[$clean](builder);\n    this.style = checkStyle(this);\n  }\n  [$acceptWhitespace]() {\n    return !NoWhites.has(this[$nodeName]);\n  }\n  [$onText](str, richText = false) {\n    if (!richText) {\n      str = str.replaceAll(crlfRegExp, \"\");\n      if (!this.style.includes(\"xfa-spacerun:yes\")) {\n        str = str.replaceAll(spacesRegExp, \" \");\n      }\n    } else {\n      this[$richText] = true;\n    }\n    if (str) {\n      this[$content] += str;\n    }\n  }\n  [$pushGlyphs](measure, mustPop = true) {\n    const xfaFont = Object.create(null);\n    const margin = {\n      top: NaN,\n      bottom: NaN,\n      left: NaN,\n      right: NaN\n    };\n    let lineHeight = null;\n    for (const [key, value] of this.style.split(\";\").map(s => s.split(\":\", 2))) {\n      switch (key) {\n        case \"font-family\":\n          xfaFont.typeface = stripQuotes(value);\n          break;\n        case \"font-size\":\n          xfaFont.size = getMeasurement(value);\n          break;\n        case \"font-weight\":\n          xfaFont.weight = value;\n          break;\n        case \"font-style\":\n          xfaFont.posture = value;\n          break;\n        case \"letter-spacing\":\n          xfaFont.letterSpacing = getMeasurement(value);\n          break;\n        case \"margin\":\n          const values = value.split(/ \\t/).map(x => getMeasurement(x));\n          switch (values.length) {\n            case 1:\n              margin.top = margin.bottom = margin.left = margin.right = values[0];\n              break;\n            case 2:\n              margin.top = margin.bottom = values[0];\n              margin.left = margin.right = values[1];\n              break;\n            case 3:\n              margin.top = values[0];\n              margin.bottom = values[2];\n              margin.left = margin.right = values[1];\n              break;\n            case 4:\n              margin.top = values[0];\n              margin.left = values[1];\n              margin.bottom = values[2];\n              margin.right = values[3];\n              break;\n          }\n          break;\n        case \"margin-top\":\n          margin.top = getMeasurement(value);\n          break;\n        case \"margin-bottom\":\n          margin.bottom = getMeasurement(value);\n          break;\n        case \"margin-left\":\n          margin.left = getMeasurement(value);\n          break;\n        case \"margin-right\":\n          margin.right = getMeasurement(value);\n          break;\n        case \"line-height\":\n          lineHeight = getMeasurement(value);\n          break;\n      }\n    }\n    measure.pushData(xfaFont, margin, lineHeight);\n    if (this[$content]) {\n      measure.addString(this[$content]);\n    } else {\n      for (const child of this[$getChildren]()) {\n        if (child[$nodeName] === \"#text\") {\n          measure.addString(child[$content]);\n          continue;\n        }\n        child[$pushGlyphs](measure);\n      }\n    }\n    if (mustPop) {\n      measure.popFont();\n    }\n  }\n  [$toHTML](availableSpace) {\n    const children = [];\n    this[$extra] = {\n      children\n    };\n    this[$childrenToHTML]({});\n    if (children.length === 0 && !this[$content]) {\n      return HTMLResult.EMPTY;\n    }\n    let value;\n    if (this[$richText]) {\n      value = this[$content] ? this[$content].replaceAll(crlfForRichTextRegExp, \"\\n\") : undefined;\n    } else {\n      value = this[$content] || undefined;\n    }\n    return HTMLResult.success({\n      name: this[$nodeName],\n      attributes: {\n        href: this.href,\n        style: mapStyle(this.style, this, this[$richText])\n      },\n      children,\n      value\n    });\n  }\n}\nclass A extends XhtmlObject {\n  constructor(attributes) {\n    super(attributes, \"a\");\n    this.href = fixURL(attributes.href) || \"\";\n  }\n}\nclass B extends XhtmlObject {\n  constructor(attributes) {\n    super(attributes, \"b\");\n  }\n  [$pushGlyphs](measure) {\n    measure.pushFont({\n      weight: \"bold\"\n    });\n    super[$pushGlyphs](measure);\n    measure.popFont();\n  }\n}\nclass Body extends XhtmlObject {\n  constructor(attributes) {\n    super(attributes, \"body\");\n  }\n  [$toHTML](availableSpace) {\n    const res = super[$toHTML](availableSpace);\n    const {\n      html\n    } = res;\n    if (!html) {\n      return HTMLResult.EMPTY;\n    }\n    html.name = \"div\";\n    html.attributes.class = [\"xfaRich\"];\n    return res;\n  }\n}\nclass Br extends XhtmlObject {\n  constructor(attributes) {\n    super(attributes, \"br\");\n  }\n  [$text]() {\n    return \"\\n\";\n  }\n  [$pushGlyphs](measure) {\n    measure.addString(\"\\n\");\n  }\n  [$toHTML](availableSpace) {\n    return HTMLResult.success({\n      name: \"br\"\n    });\n  }\n}\nclass Html extends XhtmlObject {\n  constructor(attributes) {\n    super(attributes, \"html\");\n  }\n  [$toHTML](availableSpace) {\n    const children = [];\n    this[$extra] = {\n      children\n    };\n    this[$childrenToHTML]({});\n    if (children.length === 0) {\n      return HTMLResult.success({\n        name: \"div\",\n        attributes: {\n          class: [\"xfaRich\"],\n          style: {}\n        },\n        value: this[$content] || \"\"\n      });\n    }\n    if (children.length === 1) {\n      const child = children[0];\n      if (child.attributes?.class.includes(\"xfaRich\")) {\n        return HTMLResult.success(child);\n      }\n    }\n    return HTMLResult.success({\n      name: \"div\",\n      attributes: {\n        class: [\"xfaRich\"],\n        style: {}\n      },\n      children\n    });\n  }\n}\nclass I extends XhtmlObject {\n  constructor(attributes) {\n    super(attributes, \"i\");\n  }\n  [$pushGlyphs](measure) {\n    measure.pushFont({\n      posture: \"italic\"\n    });\n    super[$pushGlyphs](measure);\n    measure.popFont();\n  }\n}\nclass Li extends XhtmlObject {\n  constructor(attributes) {\n    super(attributes, \"li\");\n  }\n}\nclass Ol extends XhtmlObject {\n  constructor(attributes) {\n    super(attributes, \"ol\");\n  }\n}\nclass P extends XhtmlObject {\n  constructor(attributes) {\n    super(attributes, \"p\");\n  }\n  [$pushGlyphs](measure) {\n    super[$pushGlyphs](measure, false);\n    measure.addString(\"\\n\");\n    measure.addPara();\n    measure.popFont();\n  }\n  [$text]() {\n    const siblings = this[$getParent]()[$getChildren]();\n    if (siblings.at(-1) === this) {\n      return super[$text]();\n    }\n    return super[$text]() + \"\\n\";\n  }\n}\nclass Span extends XhtmlObject {\n  constructor(attributes) {\n    super(attributes, \"span\");\n  }\n}\nclass Sub extends XhtmlObject {\n  constructor(attributes) {\n    super(attributes, \"sub\");\n  }\n}\nclass Sup extends XhtmlObject {\n  constructor(attributes) {\n    super(attributes, \"sup\");\n  }\n}\nclass Ul extends XhtmlObject {\n  constructor(attributes) {\n    super(attributes, \"ul\");\n  }\n}\nclass XhtmlNamespace {\n  static [$buildXFAObject](name, attributes) {\n    if (XhtmlNamespace.hasOwnProperty(name)) {\n      return XhtmlNamespace[name](attributes);\n    }\n    return undefined;\n  }\n  static a(attributes) {\n    return new A(attributes);\n  }\n  static b(attributes) {\n    return new B(attributes);\n  }\n  static body(attributes) {\n    return new Body(attributes);\n  }\n  static br(attributes) {\n    return new Br(attributes);\n  }\n  static html(attributes) {\n    return new Html(attributes);\n  }\n  static i(attributes) {\n    return new I(attributes);\n  }\n  static li(attributes) {\n    return new Li(attributes);\n  }\n  static ol(attributes) {\n    return new Ol(attributes);\n  }\n  static p(attributes) {\n    return new P(attributes);\n  }\n  static span(attributes) {\n    return new Span(attributes);\n  }\n  static sub(attributes) {\n    return new Sub(attributes);\n  }\n  static sup(attributes) {\n    return new Sup(attributes);\n  }\n  static ul(attributes) {\n    return new Ul(attributes);\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/xfa/setup.js\n\n\n\n\n\n\n\n\n\nconst NamespaceSetUp = {\n  config: ConfigNamespace,\n  connection: ConnectionSetNamespace,\n  datasets: DatasetsNamespace,\n  localeSet: LocaleSetNamespace,\n  signature: SignatureNamespace,\n  stylesheet: StylesheetNamespace,\n  template: TemplateNamespace,\n  xdp: XdpNamespace,\n  xhtml: XhtmlNamespace\n};\n\n;// CONCATENATED MODULE: ./src/core/xfa/unknown.js\n\n\nclass UnknownNamespace {\n  constructor(nsId) {\n    this.namespaceId = nsId;\n  }\n  [$buildXFAObject](name, attributes) {\n    return new XmlObject(this.namespaceId, name, attributes);\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/xfa/builder.js\n\n\n\n\n\n\n\nclass Root extends XFAObject {\n  constructor(ids) {\n    super(-1, \"root\", Object.create(null));\n    this.element = null;\n    this[$ids] = ids;\n  }\n  [$onChild](child) {\n    this.element = child;\n    return true;\n  }\n  [$finalize]() {\n    super[$finalize]();\n    if (this.element.template instanceof Template) {\n      this[$ids].set($root, this.element);\n      this.element.template[$resolvePrototypes](this[$ids]);\n      this.element.template[$ids] = this[$ids];\n    }\n  }\n}\nclass Empty extends XFAObject {\n  constructor() {\n    super(-1, \"\", Object.create(null));\n  }\n  [$onChild](_) {\n    return false;\n  }\n}\nclass Builder {\n  constructor(rootNameSpace = null) {\n    this._namespaceStack = [];\n    this._nsAgnosticLevel = 0;\n    this._namespacePrefixes = new Map();\n    this._namespaces = new Map();\n    this._nextNsId = Math.max(...Object.values(NamespaceIds).map(({\n      id\n    }) => id));\n    this._currentNamespace = rootNameSpace || new UnknownNamespace(++this._nextNsId);\n  }\n  buildRoot(ids) {\n    return new Root(ids);\n  }\n  build({\n    nsPrefix,\n    name,\n    attributes,\n    namespace,\n    prefixes\n  }) {\n    const hasNamespaceDef = namespace !== null;\n    if (hasNamespaceDef) {\n      this._namespaceStack.push(this._currentNamespace);\n      this._currentNamespace = this._searchNamespace(namespace);\n    }\n    if (prefixes) {\n      this._addNamespacePrefix(prefixes);\n    }\n    if (attributes.hasOwnProperty($nsAttributes)) {\n      const dataTemplate = NamespaceSetUp.datasets;\n      const nsAttrs = attributes[$nsAttributes];\n      let xfaAttrs = null;\n      for (const [ns, attrs] of Object.entries(nsAttrs)) {\n        const nsToUse = this._getNamespaceToUse(ns);\n        if (nsToUse === dataTemplate) {\n          xfaAttrs = {\n            xfa: attrs\n          };\n          break;\n        }\n      }\n      if (xfaAttrs) {\n        attributes[$nsAttributes] = xfaAttrs;\n      } else {\n        delete attributes[$nsAttributes];\n      }\n    }\n    const namespaceToUse = this._getNamespaceToUse(nsPrefix);\n    const node = namespaceToUse?.[$buildXFAObject](name, attributes) || new Empty();\n    if (node[$isNsAgnostic]()) {\n      this._nsAgnosticLevel++;\n    }\n    if (hasNamespaceDef || prefixes || node[$isNsAgnostic]()) {\n      node[$cleanup] = {\n        hasNamespace: hasNamespaceDef,\n        prefixes,\n        nsAgnostic: node[$isNsAgnostic]()\n      };\n    }\n    return node;\n  }\n  isNsAgnostic() {\n    return this._nsAgnosticLevel > 0;\n  }\n  _searchNamespace(nsName) {\n    let ns = this._namespaces.get(nsName);\n    if (ns) {\n      return ns;\n    }\n    for (const [name, {\n      check\n    }] of Object.entries(NamespaceIds)) {\n      if (check(nsName)) {\n        ns = NamespaceSetUp[name];\n        if (ns) {\n          this._namespaces.set(nsName, ns);\n          return ns;\n        }\n        break;\n      }\n    }\n    ns = new UnknownNamespace(++this._nextNsId);\n    this._namespaces.set(nsName, ns);\n    return ns;\n  }\n  _addNamespacePrefix(prefixes) {\n    for (const {\n      prefix,\n      value\n    } of prefixes) {\n      const namespace = this._searchNamespace(value);\n      let prefixStack = this._namespacePrefixes.get(prefix);\n      if (!prefixStack) {\n        prefixStack = [];\n        this._namespacePrefixes.set(prefix, prefixStack);\n      }\n      prefixStack.push(namespace);\n    }\n  }\n  _getNamespaceToUse(prefix) {\n    if (!prefix) {\n      return this._currentNamespace;\n    }\n    const prefixStack = this._namespacePrefixes.get(prefix);\n    if (prefixStack?.length > 0) {\n      return prefixStack.at(-1);\n    }\n    warn(`Unknown namespace prefix: ${prefix}.`);\n    return null;\n  }\n  clean(data) {\n    const {\n      hasNamespace,\n      prefixes,\n      nsAgnostic\n    } = data;\n    if (hasNamespace) {\n      this._currentNamespace = this._namespaceStack.pop();\n    }\n    if (prefixes) {\n      prefixes.forEach(({\n        prefix\n      }) => {\n        this._namespacePrefixes.get(prefix).pop();\n      });\n    }\n    if (nsAgnostic) {\n      this._nsAgnosticLevel--;\n    }\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/xfa/parser.js\n\n\n\n\nclass XFAParser extends XMLParserBase {\n  constructor(rootNameSpace = null, richText = false) {\n    super();\n    this._builder = new Builder(rootNameSpace);\n    this._stack = [];\n    this._globalData = {\n      usedTypefaces: new Set()\n    };\n    this._ids = new Map();\n    this._current = this._builder.buildRoot(this._ids);\n    this._errorCode = XMLParserErrorCode.NoError;\n    this._whiteRegex = /^\\s+$/;\n    this._nbsps = /\\xa0+/g;\n    this._richText = richText;\n  }\n  parse(data) {\n    this.parseXml(data);\n    if (this._errorCode !== XMLParserErrorCode.NoError) {\n      return undefined;\n    }\n    this._current[$finalize]();\n    return this._current.element;\n  }\n  onText(text) {\n    text = text.replace(this._nbsps, match => match.slice(1) + \" \");\n    if (this._richText || this._current[$acceptWhitespace]()) {\n      this._current[$onText](text, this._richText);\n      return;\n    }\n    if (this._whiteRegex.test(text)) {\n      return;\n    }\n    this._current[$onText](text.trim());\n  }\n  onCdata(text) {\n    this._current[$onText](text);\n  }\n  _mkAttributes(attributes, tagName) {\n    let namespace = null;\n    let prefixes = null;\n    const attributeObj = Object.create({});\n    for (const {\n      name,\n      value\n    } of attributes) {\n      if (name === \"xmlns\") {\n        if (!namespace) {\n          namespace = value;\n        } else {\n          warn(`XFA - multiple namespace definition in <${tagName}>`);\n        }\n      } else if (name.startsWith(\"xmlns:\")) {\n        const prefix = name.substring(\"xmlns:\".length);\n        if (!prefixes) {\n          prefixes = [];\n        }\n        prefixes.push({\n          prefix,\n          value\n        });\n      } else {\n        const i = name.indexOf(\":\");\n        if (i === -1) {\n          attributeObj[name] = value;\n        } else {\n          let nsAttrs = attributeObj[$nsAttributes];\n          if (!nsAttrs) {\n            nsAttrs = attributeObj[$nsAttributes] = Object.create(null);\n          }\n          const [ns, attrName] = [name.slice(0, i), name.slice(i + 1)];\n          const attrs = nsAttrs[ns] ||= Object.create(null);\n          attrs[attrName] = value;\n        }\n      }\n    }\n    return [namespace, prefixes, attributeObj];\n  }\n  _getNameAndPrefix(name, nsAgnostic) {\n    const i = name.indexOf(\":\");\n    if (i === -1) {\n      return [name, null];\n    }\n    return [name.substring(i + 1), nsAgnostic ? \"\" : name.substring(0, i)];\n  }\n  onBeginElement(tagName, attributes, isEmpty) {\n    const [namespace, prefixes, attributesObj] = this._mkAttributes(attributes, tagName);\n    const [name, nsPrefix] = this._getNameAndPrefix(tagName, this._builder.isNsAgnostic());\n    const node = this._builder.build({\n      nsPrefix,\n      name,\n      attributes: attributesObj,\n      namespace,\n      prefixes\n    });\n    node[$globalData] = this._globalData;\n    if (isEmpty) {\n      node[$finalize]();\n      if (this._current[$onChild](node)) {\n        node[$setId](this._ids);\n      }\n      node[$clean](this._builder);\n      return;\n    }\n    this._stack.push(this._current);\n    this._current = node;\n  }\n  onEndElement(name) {\n    const node = this._current;\n    if (node[$isCDATAXml]() && typeof node[$content] === \"string\") {\n      const parser = new XFAParser();\n      parser._globalData = this._globalData;\n      const root = parser.parse(node[$content]);\n      node[$content] = null;\n      node[$onChild](root);\n    }\n    node[$finalize]();\n    this._current = this._stack.pop();\n    if (this._current[$onChild](node)) {\n      node[$setId](this._ids);\n    }\n    node[$clean](this._builder);\n  }\n  onError(code) {\n    this._errorCode = code;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/xfa/factory.js\n\n\n\n\n\n\n\n\nclass XFAFactory {\n  constructor(data) {\n    try {\n      this.root = new XFAParser().parse(XFAFactory._createDocument(data));\n      const binder = new Binder(this.root);\n      this.form = binder.bind();\n      this.dataHandler = new DataHandler(this.root, binder.getData());\n      this.form[$globalData].template = this.form;\n    } catch (e) {\n      warn(`XFA - an error occurred during parsing and binding: ${e}`);\n    }\n  }\n  isValid() {\n    return this.root && this.form;\n  }\n  _createPagesHelper() {\n    const iterator = this.form[$toPages]();\n    return new Promise((resolve, reject) => {\n      const nextIteration = () => {\n        try {\n          const value = iterator.next();\n          if (value.done) {\n            resolve(value.value);\n          } else {\n            setTimeout(nextIteration, 0);\n          }\n        } catch (e) {\n          reject(e);\n        }\n      };\n      setTimeout(nextIteration, 0);\n    });\n  }\n  async _createPages() {\n    try {\n      this.pages = await this._createPagesHelper();\n      this.dims = this.pages.children.map(c => {\n        const {\n          width,\n          height\n        } = c.attributes.style;\n        return [0, 0, parseInt(width), parseInt(height)];\n      });\n    } catch (e) {\n      warn(`XFA - an error occurred during layout: ${e}`);\n    }\n  }\n  getBoundingBox(pageIndex) {\n    return this.dims[pageIndex];\n  }\n  async getNumPages() {\n    if (!this.pages) {\n      await this._createPages();\n    }\n    return this.dims.length;\n  }\n  setImages(images) {\n    this.form[$globalData].images = images;\n  }\n  setFonts(fonts) {\n    this.form[$globalData].fontFinder = new FontFinder(fonts);\n    const missingFonts = [];\n    for (let typeface of this.form[$globalData].usedTypefaces) {\n      typeface = stripQuotes(typeface);\n      const font = this.form[$globalData].fontFinder.find(typeface);\n      if (!font) {\n        missingFonts.push(typeface);\n      }\n    }\n    if (missingFonts.length > 0) {\n      return missingFonts;\n    }\n    return null;\n  }\n  appendFonts(fonts, reallyMissingFonts) {\n    this.form[$globalData].fontFinder.add(fonts, reallyMissingFonts);\n  }\n  async getPages() {\n    if (!this.pages) {\n      await this._createPages();\n    }\n    const pages = this.pages;\n    this.pages = null;\n    return pages;\n  }\n  serializeData(storage) {\n    return this.dataHandler.serialize(storage);\n  }\n  static _createDocument(data) {\n    if (!data[\"/xdp:xdp\"]) {\n      return data[\"xdp:xdp\"];\n    }\n    return Object.values(data).join(\"\");\n  }\n  static getRichTextAsHtml(rc) {\n    if (!rc || typeof rc !== \"string\") {\n      return null;\n    }\n    try {\n      let root = new XFAParser(XhtmlNamespace, true).parse(rc);\n      if (![\"body\", \"xhtml\"].includes(root[$nodeName])) {\n        const newRoot = XhtmlNamespace.body({});\n        newRoot[$appendChild](root);\n        root = newRoot;\n      }\n      const result = root[$toHTML]();\n      if (!result.success) {\n        return null;\n      }\n      const {\n        html\n      } = result;\n      const {\n        attributes\n      } = html;\n      if (attributes) {\n        if (attributes.class) {\n          attributes.class = attributes.class.filter(attr => !attr.startsWith(\"xfa\"));\n        }\n        attributes.dir = \"auto\";\n      }\n      return {\n        html,\n        str: root[$text]()\n      };\n    } catch (e) {\n      warn(`XFA - an error occurred during parsing of rich text: ${e}`);\n    }\n    return null;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/annotation.js\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nclass AnnotationFactory {\n  static createGlobals(pdfManager) {\n    return Promise.all([pdfManager.ensureCatalog(\"acroForm\"), pdfManager.ensureDoc(\"xfaDatasets\"), pdfManager.ensureCatalog(\"structTreeRoot\"), pdfManager.ensureCatalog(\"baseUrl\"), pdfManager.ensureCatalog(\"attachments\")]).then(([acroForm, xfaDatasets, structTreeRoot, baseUrl, attachments]) => {\n      return {\n        pdfManager,\n        acroForm: acroForm instanceof Dict ? acroForm : Dict.empty,\n        xfaDatasets,\n        structTreeRoot,\n        baseUrl,\n        attachments\n      };\n    }, reason => {\n      warn(`createGlobals: \"${reason}\".`);\n      return null;\n    });\n  }\n  static async create(xref, ref, annotationGlobals, idFactory, collectFields, pageRef) {\n    const pageIndex = collectFields ? await this._getPageIndex(xref, ref, annotationGlobals.pdfManager) : null;\n    return annotationGlobals.pdfManager.ensure(this, \"_create\", [xref, ref, annotationGlobals, idFactory, collectFields, pageIndex, pageRef]);\n  }\n  static _create(xref, ref, annotationGlobals, idFactory, collectFields = false, pageIndex = null, pageRef = null) {\n    const dict = xref.fetchIfRef(ref);\n    if (!(dict instanceof Dict)) {\n      return undefined;\n    }\n    const {\n      acroForm,\n      pdfManager\n    } = annotationGlobals;\n    const id = ref instanceof Ref ? ref.toString() : `annot_${idFactory.createObjId()}`;\n    let subtype = dict.get(\"Subtype\");\n    subtype = subtype instanceof Name ? subtype.name : null;\n    const parameters = {\n      xref,\n      ref,\n      dict,\n      subtype,\n      id,\n      annotationGlobals,\n      collectFields,\n      needAppearances: !collectFields && acroForm.get(\"NeedAppearances\") === true,\n      pageIndex,\n      evaluatorOptions: pdfManager.evaluatorOptions,\n      pageRef\n    };\n    switch (subtype) {\n      case \"Link\":\n        return new LinkAnnotation(parameters);\n      case \"Text\":\n        return new TextAnnotation(parameters);\n      case \"Widget\":\n        let fieldType = getInheritableProperty({\n          dict,\n          key: \"FT\"\n        });\n        fieldType = fieldType instanceof Name ? fieldType.name : null;\n        switch (fieldType) {\n          case \"Tx\":\n            return new TextWidgetAnnotation(parameters);\n          case \"Btn\":\n            return new ButtonWidgetAnnotation(parameters);\n          case \"Ch\":\n            return new ChoiceWidgetAnnotation(parameters);\n          case \"Sig\":\n            return new SignatureWidgetAnnotation(parameters);\n        }\n        warn(`Unimplemented widget field type \"${fieldType}\", ` + \"falling back to base field type.\");\n        return new WidgetAnnotation(parameters);\n      case \"Popup\":\n        return new PopupAnnotation(parameters);\n      case \"FreeText\":\n        return new FreeTextAnnotation(parameters);\n      case \"Line\":\n        return new LineAnnotation(parameters);\n      case \"Square\":\n        return new SquareAnnotation(parameters);\n      case \"Circle\":\n        return new CircleAnnotation(parameters);\n      case \"PolyLine\":\n        return new PolylineAnnotation(parameters);\n      case \"Polygon\":\n        return new PolygonAnnotation(parameters);\n      case \"Caret\":\n        return new CaretAnnotation(parameters);\n      case \"Ink\":\n        return new InkAnnotation(parameters);\n      case \"Highlight\":\n        return new HighlightAnnotation(parameters);\n      case \"Underline\":\n        return new UnderlineAnnotation(parameters);\n      case \"Squiggly\":\n        return new SquigglyAnnotation(parameters);\n      case \"StrikeOut\":\n        return new StrikeOutAnnotation(parameters);\n      case \"Stamp\":\n        return new StampAnnotation(parameters);\n      case \"FileAttachment\":\n        return new FileAttachmentAnnotation(parameters);\n      default:\n        if (!collectFields) {\n          if (!subtype) {\n            warn(\"Annotation is missing the required /Subtype.\");\n          } else {\n            warn(`Unimplemented annotation type \"${subtype}\", ` + \"falling back to base annotation.\");\n          }\n        }\n        return new Annotation(parameters);\n    }\n  }\n  static async _getPageIndex(xref, ref, pdfManager) {\n    try {\n      const annotDict = await xref.fetchIfRefAsync(ref);\n      if (!(annotDict instanceof Dict)) {\n        return -1;\n      }\n      const pageRef = annotDict.getRaw(\"P\");\n      if (pageRef instanceof Ref) {\n        try {\n          const pageIndex = await pdfManager.ensureCatalog(\"getPageIndex\", [pageRef]);\n          return pageIndex;\n        } catch (ex) {\n          info(`_getPageIndex -- not a valid page reference: \"${ex}\".`);\n        }\n      }\n      if (annotDict.has(\"Kids\")) {\n        return -1;\n      }\n      const numPages = await pdfManager.ensureDoc(\"numPages\");\n      for (let pageIndex = 0; pageIndex < numPages; pageIndex++) {\n        const page = await pdfManager.getPage(pageIndex);\n        const annotations = await pdfManager.ensure(page, \"annotations\");\n        for (const annotRef of annotations) {\n          if (annotRef instanceof Ref && isRefsEqual(annotRef, ref)) {\n            return pageIndex;\n          }\n        }\n      }\n    } catch (ex) {\n      warn(`_getPageIndex: \"${ex}\".`);\n    }\n    return -1;\n  }\n  static generateImages(annotations, xref, isOffscreenCanvasSupported) {\n    if (!isOffscreenCanvasSupported) {\n      warn(\"generateImages: OffscreenCanvas is not supported, cannot save or print some annotations with images.\");\n      return null;\n    }\n    let imagePromises;\n    for (const {\n      bitmapId,\n      bitmap\n    } of annotations) {\n      if (!bitmap) {\n        continue;\n      }\n      imagePromises ||= new Map();\n      imagePromises.set(bitmapId, StampAnnotation.createImage(bitmap, xref));\n    }\n    return imagePromises;\n  }\n  static async saveNewAnnotations(evaluator, task, annotations, imagePromises) {\n    const xref = evaluator.xref;\n    let baseFontRef;\n    const dependencies = [];\n    const promises = [];\n    const {\n      isOffscreenCanvasSupported\n    } = evaluator.options;\n    for (const annotation of annotations) {\n      if (annotation.deleted) {\n        continue;\n      }\n      switch (annotation.annotationType) {\n        case AnnotationEditorType.FREETEXT:\n          if (!baseFontRef) {\n            const baseFont = new Dict(xref);\n            baseFont.set(\"BaseFont\", Name.get(\"Helvetica\"));\n            baseFont.set(\"Type\", Name.get(\"Font\"));\n            baseFont.set(\"Subtype\", Name.get(\"Type1\"));\n            baseFont.set(\"Encoding\", Name.get(\"WinAnsiEncoding\"));\n            const buffer = [];\n            baseFontRef = xref.getNewTemporaryRef();\n            await writeObject(baseFontRef, baseFont, buffer, xref);\n            dependencies.push({\n              ref: baseFontRef,\n              data: buffer.join(\"\")\n            });\n          }\n          promises.push(FreeTextAnnotation.createNewAnnotation(xref, annotation, dependencies, {\n            evaluator,\n            task,\n            baseFontRef\n          }));\n          break;\n        case AnnotationEditorType.HIGHLIGHT:\n          if (annotation.quadPoints) {\n            promises.push(HighlightAnnotation.createNewAnnotation(xref, annotation, dependencies));\n          } else {\n            promises.push(InkAnnotation.createNewAnnotation(xref, annotation, dependencies));\n          }\n          break;\n        case AnnotationEditorType.INK:\n          promises.push(InkAnnotation.createNewAnnotation(xref, annotation, dependencies));\n          break;\n        case AnnotationEditorType.STAMP:\n          if (!isOffscreenCanvasSupported) {\n            break;\n          }\n          const image = await imagePromises.get(annotation.bitmapId);\n          if (image.imageStream) {\n            const {\n              imageStream,\n              smaskStream\n            } = image;\n            const buffer = [];\n            if (smaskStream) {\n              const smaskRef = xref.getNewTemporaryRef();\n              await writeObject(smaskRef, smaskStream, buffer, xref);\n              dependencies.push({\n                ref: smaskRef,\n                data: buffer.join(\"\")\n              });\n              imageStream.dict.set(\"SMask\", smaskRef);\n              buffer.length = 0;\n            }\n            const imageRef = image.imageRef = xref.getNewTemporaryRef();\n            await writeObject(imageRef, imageStream, buffer, xref);\n            dependencies.push({\n              ref: imageRef,\n              data: buffer.join(\"\")\n            });\n            image.imageStream = image.smaskStream = null;\n          }\n          promises.push(StampAnnotation.createNewAnnotation(xref, annotation, dependencies, {\n            image\n          }));\n          break;\n      }\n    }\n    return {\n      annotations: await Promise.all(promises),\n      dependencies\n    };\n  }\n  static async printNewAnnotations(annotationGlobals, evaluator, task, annotations, imagePromises) {\n    if (!annotations) {\n      return null;\n    }\n    const {\n      options,\n      xref\n    } = evaluator;\n    const promises = [];\n    for (const annotation of annotations) {\n      if (annotation.deleted) {\n        continue;\n      }\n      switch (annotation.annotationType) {\n        case AnnotationEditorType.FREETEXT:\n          promises.push(FreeTextAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, {\n            evaluator,\n            task,\n            evaluatorOptions: options\n          }));\n          break;\n        case AnnotationEditorType.HIGHLIGHT:\n          if (annotation.quadPoints) {\n            promises.push(HighlightAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, {\n              evaluatorOptions: options\n            }));\n          } else {\n            promises.push(InkAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, {\n              evaluatorOptions: options\n            }));\n          }\n          break;\n        case AnnotationEditorType.INK:\n          promises.push(InkAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, {\n            evaluatorOptions: options\n          }));\n          break;\n        case AnnotationEditorType.STAMP:\n          if (!options.isOffscreenCanvasSupported) {\n            break;\n          }\n          const image = await imagePromises.get(annotation.bitmapId);\n          if (image.imageStream) {\n            const {\n              imageStream,\n              smaskStream\n            } = image;\n            if (smaskStream) {\n              imageStream.dict.set(\"SMask\", smaskStream);\n            }\n            image.imageRef = new JpegStream(imageStream, imageStream.length);\n            image.imageStream = image.smaskStream = null;\n          }\n          promises.push(StampAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, {\n            image,\n            evaluatorOptions: options\n          }));\n          break;\n      }\n    }\n    return Promise.all(promises);\n  }\n}\nfunction getRgbColor(color, defaultColor = new Uint8ClampedArray(3)) {\n  if (!Array.isArray(color)) {\n    return defaultColor;\n  }\n  const rgbColor = defaultColor || new Uint8ClampedArray(3);\n  switch (color.length) {\n    case 0:\n      return null;\n    case 1:\n      ColorSpace.singletons.gray.getRgbItem(color, 0, rgbColor, 0);\n      return rgbColor;\n    case 3:\n      ColorSpace.singletons.rgb.getRgbItem(color, 0, rgbColor, 0);\n      return rgbColor;\n    case 4:\n      ColorSpace.singletons.cmyk.getRgbItem(color, 0, rgbColor, 0);\n      return rgbColor;\n    default:\n      return defaultColor;\n  }\n}\nfunction getPdfColorArray(color) {\n  return Array.from(color, c => c / 255);\n}\nfunction getQuadPoints(dict, rect) {\n  const quadPoints = dict.getArray(\"QuadPoints\");\n  if (!Array.isArray(quadPoints) || quadPoints.length === 0 || quadPoints.length % 8 > 0) {\n    return null;\n  }\n  const quadPointsLists = [];\n  for (let i = 0, ii = quadPoints.length / 8; i < ii; i++) {\n    let minX = Infinity,\n      maxX = -Infinity,\n      minY = Infinity,\n      maxY = -Infinity;\n    for (let j = i * 8, jj = i * 8 + 8; j < jj; j += 2) {\n      const x = quadPoints[j];\n      const y = quadPoints[j + 1];\n      minX = Math.min(x, minX);\n      maxX = Math.max(x, maxX);\n      minY = Math.min(y, minY);\n      maxY = Math.max(y, maxY);\n    }\n    if (rect !== null && (minX < rect[0] || maxX > rect[2] || minY < rect[1] || maxY > rect[3])) {\n      return null;\n    }\n    quadPointsLists.push([{\n      x: minX,\n      y: maxY\n    }, {\n      x: maxX,\n      y: maxY\n    }, {\n      x: minX,\n      y: minY\n    }, {\n      x: maxX,\n      y: minY\n    }]);\n  }\n  return quadPointsLists;\n}\nfunction getTransformMatrix(rect, bbox, matrix) {\n  const [minX, minY, maxX, maxY] = Util.getAxialAlignedBoundingBox(bbox, matrix);\n  if (minX === maxX || minY === maxY) {\n    return [1, 0, 0, 1, rect[0], rect[1]];\n  }\n  const xRatio = (rect[2] - rect[0]) / (maxX - minX);\n  const yRatio = (rect[3] - rect[1]) / (maxY - minY);\n  return [xRatio, 0, 0, yRatio, rect[0] - minX * xRatio, rect[1] - minY * yRatio];\n}\nclass Annotation {\n  constructor(params) {\n    const {\n      dict,\n      xref,\n      annotationGlobals\n    } = params;\n    this.setTitle(dict.get(\"T\"));\n    this.setContents(dict.get(\"Contents\"));\n    this.setModificationDate(dict.get(\"M\"));\n    this.setFlags(dict.get(\"F\"));\n    this.setRectangle(dict.getArray(\"Rect\"));\n    this.setColor(dict.getArray(\"C\"));\n    this.setBorderStyle(dict);\n    this.setAppearance(dict);\n    this.setOptionalContent(dict);\n    const MK = dict.get(\"MK\");\n    this.setBorderAndBackgroundColors(MK);\n    this.setRotation(MK, dict);\n    this.ref = params.ref instanceof Ref ? params.ref : null;\n    this._streams = [];\n    if (this.appearance) {\n      this._streams.push(this.appearance);\n    }\n    const isLocked = !!(this.flags & AnnotationFlag.LOCKED);\n    const isContentLocked = !!(this.flags & AnnotationFlag.LOCKEDCONTENTS);\n    if (annotationGlobals.structTreeRoot) {\n      let structParent = dict.get(\"StructParent\");\n      structParent = Number.isInteger(structParent) && structParent >= 0 ? structParent : -1;\n      annotationGlobals.structTreeRoot.addAnnotationIdToPage(params.pageRef, structParent);\n    }\n    this.data = {\n      annotationFlags: this.flags,\n      borderStyle: this.borderStyle,\n      color: this.color,\n      backgroundColor: this.backgroundColor,\n      borderColor: this.borderColor,\n      rotation: this.rotation,\n      contentsObj: this._contents,\n      hasAppearance: !!this.appearance,\n      id: params.id,\n      modificationDate: this.modificationDate,\n      rect: this.rectangle,\n      subtype: params.subtype,\n      hasOwnCanvas: false,\n      noRotate: !!(this.flags & AnnotationFlag.NOROTATE),\n      noHTML: isLocked && isContentLocked\n    };\n    if (params.collectFields) {\n      const kids = dict.get(\"Kids\");\n      if (Array.isArray(kids)) {\n        const kidIds = [];\n        for (const kid of kids) {\n          if (kid instanceof Ref) {\n            kidIds.push(kid.toString());\n          }\n        }\n        if (kidIds.length !== 0) {\n          this.data.kidIds = kidIds;\n        }\n      }\n      this.data.actions = collectActions(xref, dict, AnnotationActionEventType);\n      this.data.fieldName = this._constructFieldName(dict);\n      this.data.pageIndex = params.pageIndex;\n    }\n    this._isOffscreenCanvasSupported = params.evaluatorOptions.isOffscreenCanvasSupported;\n    this._fallbackFontDict = null;\n    this._needAppearances = false;\n  }\n  _hasFlag(flags, flag) {\n    return !!(flags & flag);\n  }\n  _isViewable(flags) {\n    return !this._hasFlag(flags, AnnotationFlag.INVISIBLE) && !this._hasFlag(flags, AnnotationFlag.NOVIEW);\n  }\n  _isPrintable(flags) {\n    return this._hasFlag(flags, AnnotationFlag.PRINT) && !this._hasFlag(flags, AnnotationFlag.HIDDEN) && !this._hasFlag(flags, AnnotationFlag.INVISIBLE);\n  }\n  mustBeViewed(annotationStorage, _renderForms) {\n    const noView = annotationStorage?.get(this.data.id)?.noView;\n    if (noView !== undefined) {\n      return !noView;\n    }\n    return this.viewable && !this._hasFlag(this.flags, AnnotationFlag.HIDDEN);\n  }\n  mustBePrinted(annotationStorage) {\n    const noPrint = annotationStorage?.get(this.data.id)?.noPrint;\n    if (noPrint !== undefined) {\n      return !noPrint;\n    }\n    return this.printable;\n  }\n  get viewable() {\n    if (this.data.quadPoints === null) {\n      return false;\n    }\n    if (this.flags === 0) {\n      return true;\n    }\n    return this._isViewable(this.flags);\n  }\n  get printable() {\n    if (this.data.quadPoints === null) {\n      return false;\n    }\n    if (this.flags === 0) {\n      return false;\n    }\n    return this._isPrintable(this.flags);\n  }\n  _parseStringHelper(data) {\n    const str = typeof data === \"string\" ? stringToPDFString(data) : \"\";\n    const dir = str && bidi(str).dir === \"rtl\" ? \"rtl\" : \"ltr\";\n    return {\n      str,\n      dir\n    };\n  }\n  setDefaultAppearance(params) {\n    const {\n      dict,\n      annotationGlobals\n    } = params;\n    const defaultAppearance = getInheritableProperty({\n      dict,\n      key: \"DA\"\n    }) || annotationGlobals.acroForm.get(\"DA\");\n    this._defaultAppearance = typeof defaultAppearance === \"string\" ? defaultAppearance : \"\";\n    this.data.defaultAppearanceData = parseDefaultAppearance(this._defaultAppearance);\n  }\n  setTitle(title) {\n    this._title = this._parseStringHelper(title);\n  }\n  setContents(contents) {\n    this._contents = this._parseStringHelper(contents);\n  }\n  setModificationDate(modificationDate) {\n    this.modificationDate = typeof modificationDate === \"string\" ? modificationDate : null;\n  }\n  setFlags(flags) {\n    this.flags = Number.isInteger(flags) && flags > 0 ? flags : 0;\n    if (this.flags & AnnotationFlag.INVISIBLE && this.constructor.name !== \"Annotation\") {\n      this.flags ^= AnnotationFlag.INVISIBLE;\n    }\n  }\n  hasFlag(flag) {\n    return this._hasFlag(this.flags, flag);\n  }\n  setRectangle(rectangle) {\n    this.rectangle = Array.isArray(rectangle) && rectangle.length === 4 ? Util.normalizeRect(rectangle) : [0, 0, 0, 0];\n  }\n  setColor(color) {\n    this.color = getRgbColor(color);\n  }\n  setLineEndings(lineEndings) {\n    this.lineEndings = [\"None\", \"None\"];\n    if (Array.isArray(lineEndings) && lineEndings.length === 2) {\n      for (let i = 0; i < 2; i++) {\n        const obj = lineEndings[i];\n        if (obj instanceof Name) {\n          switch (obj.name) {\n            case \"None\":\n              continue;\n            case \"Square\":\n            case \"Circle\":\n            case \"Diamond\":\n            case \"OpenArrow\":\n            case \"ClosedArrow\":\n            case \"Butt\":\n            case \"ROpenArrow\":\n            case \"RClosedArrow\":\n            case \"Slash\":\n              this.lineEndings[i] = obj.name;\n              continue;\n          }\n        }\n        warn(`Ignoring invalid lineEnding: ${obj}`);\n      }\n    }\n  }\n  setRotation(mk, dict) {\n    this.rotation = 0;\n    let angle = mk instanceof Dict ? mk.get(\"R\") || 0 : dict.get(\"Rotate\") || 0;\n    if (Number.isInteger(angle) && angle !== 0) {\n      angle %= 360;\n      if (angle < 0) {\n        angle += 360;\n      }\n      if (angle % 90 === 0) {\n        this.rotation = angle;\n      }\n    }\n  }\n  setBorderAndBackgroundColors(mk) {\n    if (mk instanceof Dict) {\n      this.borderColor = getRgbColor(mk.getArray(\"BC\"), null);\n      this.backgroundColor = getRgbColor(mk.getArray(\"BG\"), null);\n    } else {\n      this.borderColor = this.backgroundColor = null;\n    }\n  }\n  setBorderStyle(borderStyle) {\n    this.borderStyle = new AnnotationBorderStyle();\n    if (!(borderStyle instanceof Dict)) {\n      return;\n    }\n    if (borderStyle.has(\"BS\")) {\n      const dict = borderStyle.get(\"BS\");\n      if (dict instanceof Dict) {\n        const dictType = dict.get(\"Type\");\n        if (!dictType || isName(dictType, \"Border\")) {\n          this.borderStyle.setWidth(dict.get(\"W\"), this.rectangle);\n          this.borderStyle.setStyle(dict.get(\"S\"));\n          this.borderStyle.setDashArray(dict.getArray(\"D\"));\n        }\n      }\n    } else if (borderStyle.has(\"Border\")) {\n      const array = borderStyle.getArray(\"Border\");\n      if (Array.isArray(array) && array.length >= 3) {\n        this.borderStyle.setHorizontalCornerRadius(array[0]);\n        this.borderStyle.setVerticalCornerRadius(array[1]);\n        this.borderStyle.setWidth(array[2], this.rectangle);\n        if (array.length === 4) {\n          this.borderStyle.setDashArray(array[3], true);\n        }\n      }\n    } else {\n      this.borderStyle.setWidth(0);\n    }\n  }\n  setAppearance(dict) {\n    this.appearance = null;\n    const appearanceStates = dict.get(\"AP\");\n    if (!(appearanceStates instanceof Dict)) {\n      return;\n    }\n    const normalAppearanceState = appearanceStates.get(\"N\");\n    if (normalAppearanceState instanceof BaseStream) {\n      this.appearance = normalAppearanceState;\n      return;\n    }\n    if (!(normalAppearanceState instanceof Dict)) {\n      return;\n    }\n    const as = dict.get(\"AS\");\n    if (!(as instanceof Name) || !normalAppearanceState.has(as.name)) {\n      return;\n    }\n    const appearance = normalAppearanceState.get(as.name);\n    if (appearance instanceof BaseStream) {\n      this.appearance = appearance;\n    }\n  }\n  setOptionalContent(dict) {\n    this.oc = null;\n    const oc = dict.get(\"OC\");\n    if (oc instanceof Name) {\n      warn(\"setOptionalContent: Support for /Name-entry is not implemented.\");\n    } else if (oc instanceof Dict) {\n      this.oc = oc;\n    }\n  }\n  loadResources(keys, appearance) {\n    return appearance.dict.getAsync(\"Resources\").then(resources => {\n      if (!resources) {\n        return undefined;\n      }\n      const objectLoader = new ObjectLoader(resources, keys, resources.xref);\n      return objectLoader.load().then(function () {\n        return resources;\n      });\n    });\n  }\n  async getOperatorList(evaluator, task, intent, renderForms, annotationStorage) {\n    const {\n      hasOwnCanvas,\n      id,\n      rect\n    } = this.data;\n    let appearance = this.appearance;\n    const isUsingOwnCanvas = !!(hasOwnCanvas && intent & RenderingIntentFlag.DISPLAY);\n    if (isUsingOwnCanvas && (rect[0] === rect[2] || rect[1] === rect[3])) {\n      this.data.hasOwnCanvas = false;\n      return {\n        opList: new OperatorList(),\n        separateForm: false,\n        separateCanvas: false\n      };\n    }\n    if (!appearance) {\n      if (!isUsingOwnCanvas) {\n        return {\n          opList: new OperatorList(),\n          separateForm: false,\n          separateCanvas: false\n        };\n      }\n      appearance = new StringStream(\"\");\n      appearance.dict = new Dict();\n    }\n    const appearanceDict = appearance.dict;\n    const resources = await this.loadResources([\"ExtGState\", \"ColorSpace\", \"Pattern\", \"Shading\", \"XObject\", \"Font\"], appearance);\n    const bbox = appearanceDict.getArray(\"BBox\") || [0, 0, 1, 1];\n    const matrix = appearanceDict.getArray(\"Matrix\") || [1, 0, 0, 1, 0, 0];\n    const transform = getTransformMatrix(rect, bbox, matrix);\n    const opList = new OperatorList();\n    let optionalContent;\n    if (this.oc) {\n      optionalContent = await evaluator.parseMarkedContentProps(this.oc, null);\n    }\n    if (optionalContent !== undefined) {\n      opList.addOp(OPS.beginMarkedContentProps, [\"OC\", optionalContent]);\n    }\n    opList.addOp(OPS.beginAnnotation, [id, rect, transform, matrix, isUsingOwnCanvas]);\n    await evaluator.getOperatorList({\n      stream: appearance,\n      task,\n      resources,\n      operatorList: opList,\n      fallbackFontDict: this._fallbackFontDict\n    });\n    opList.addOp(OPS.endAnnotation, []);\n    if (optionalContent !== undefined) {\n      opList.addOp(OPS.endMarkedContent, []);\n    }\n    this.reset();\n    return {\n      opList,\n      separateForm: false,\n      separateCanvas: isUsingOwnCanvas\n    };\n  }\n  async save(evaluator, task, annotationStorage) {\n    return null;\n  }\n  get hasTextContent() {\n    return false;\n  }\n  async extractTextContent(evaluator, task, viewBox) {\n    if (!this.appearance) {\n      return;\n    }\n    const resources = await this.loadResources([\"ExtGState\", \"Font\", \"Properties\", \"XObject\"], this.appearance);\n    const text = [];\n    const buffer = [];\n    let firstPosition = null;\n    const sink = {\n      desiredSize: Math.Infinity,\n      ready: true,\n      enqueue(chunk, size) {\n        for (const item of chunk.items) {\n          if (item.str === undefined) {\n            continue;\n          }\n          firstPosition ||= item.transform.slice(-2);\n          buffer.push(item.str);\n          if (item.hasEOL) {\n            text.push(buffer.join(\"\").trimEnd());\n            buffer.length = 0;\n          }\n        }\n      }\n    };\n    await evaluator.getTextContent({\n      stream: this.appearance,\n      task,\n      resources,\n      includeMarkedContent: true,\n      keepWhiteSpace: true,\n      sink,\n      viewBox\n    });\n    this.reset();\n    if (buffer.length) {\n      text.push(buffer.join(\"\").trimEnd());\n    }\n    if (text.length > 1 || text[0]) {\n      const appearanceDict = this.appearance.dict;\n      this.data.textPosition = this._transformPoint(firstPosition, appearanceDict.getArray(\"BBox\"), appearanceDict.getArray(\"Matrix\"));\n      this.data.textContent = text;\n    }\n  }\n  _transformPoint(coords, bbox, matrix) {\n    const {\n      rect\n    } = this.data;\n    bbox ||= [0, 0, 1, 1];\n    matrix ||= [1, 0, 0, 1, 0, 0];\n    const transform = getTransformMatrix(rect, bbox, matrix);\n    transform[4] -= rect[0];\n    transform[5] -= rect[1];\n    coords = Util.applyTransform(coords, transform);\n    return Util.applyTransform(coords, matrix);\n  }\n  getFieldObject() {\n    if (this.data.kidIds) {\n      return {\n        id: this.data.id,\n        actions: this.data.actions,\n        name: this.data.fieldName,\n        strokeColor: this.data.borderColor,\n        fillColor: this.data.backgroundColor,\n        type: \"\",\n        kidIds: this.data.kidIds,\n        page: this.data.pageIndex,\n        rotation: this.rotation\n      };\n    }\n    return null;\n  }\n  reset() {\n    for (const stream of this._streams) {\n      stream.reset();\n    }\n  }\n  _constructFieldName(dict) {\n    if (!dict.has(\"T\") && !dict.has(\"Parent\")) {\n      warn(\"Unknown field name, falling back to empty field name.\");\n      return \"\";\n    }\n    if (!dict.has(\"Parent\")) {\n      return stringToPDFString(dict.get(\"T\"));\n    }\n    const fieldName = [];\n    if (dict.has(\"T\")) {\n      fieldName.unshift(stringToPDFString(dict.get(\"T\")));\n    }\n    let loopDict = dict;\n    const visited = new RefSet();\n    if (dict.objId) {\n      visited.put(dict.objId);\n    }\n    while (loopDict.has(\"Parent\")) {\n      loopDict = loopDict.get(\"Parent\");\n      if (!(loopDict instanceof Dict) || loopDict.objId && visited.has(loopDict.objId)) {\n        break;\n      }\n      if (loopDict.objId) {\n        visited.put(loopDict.objId);\n      }\n      if (loopDict.has(\"T\")) {\n        fieldName.unshift(stringToPDFString(loopDict.get(\"T\")));\n      }\n    }\n    return fieldName.join(\".\");\n  }\n}\nclass AnnotationBorderStyle {\n  constructor() {\n    this.width = 1;\n    this.style = AnnotationBorderStyleType.SOLID;\n    this.dashArray = [3];\n    this.horizontalCornerRadius = 0;\n    this.verticalCornerRadius = 0;\n  }\n  setWidth(width, rect = [0, 0, 0, 0]) {\n    if (width instanceof Name) {\n      this.width = 0;\n      return;\n    }\n    if (typeof width === \"number\") {\n      if (width > 0) {\n        const maxWidth = (rect[2] - rect[0]) / 2;\n        const maxHeight = (rect[3] - rect[1]) / 2;\n        if (maxWidth > 0 && maxHeight > 0 && (width > maxWidth || width > maxHeight)) {\n          warn(`AnnotationBorderStyle.setWidth - ignoring width: ${width}`);\n          width = 1;\n        }\n      }\n      this.width = width;\n    }\n  }\n  setStyle(style) {\n    if (!(style instanceof Name)) {\n      return;\n    }\n    switch (style.name) {\n      case \"S\":\n        this.style = AnnotationBorderStyleType.SOLID;\n        break;\n      case \"D\":\n        this.style = AnnotationBorderStyleType.DASHED;\n        break;\n      case \"B\":\n        this.style = AnnotationBorderStyleType.BEVELED;\n        break;\n      case \"I\":\n        this.style = AnnotationBorderStyleType.INSET;\n        break;\n      case \"U\":\n        this.style = AnnotationBorderStyleType.UNDERLINE;\n        break;\n      default:\n        break;\n    }\n  }\n  setDashArray(dashArray, forceStyle = false) {\n    if (Array.isArray(dashArray)) {\n      let isValid = true;\n      let allZeros = true;\n      for (const element of dashArray) {\n        const validNumber = +element >= 0;\n        if (!validNumber) {\n          isValid = false;\n          break;\n        } else if (element > 0) {\n          allZeros = false;\n        }\n      }\n      if (dashArray.length === 0 || isValid && !allZeros) {\n        this.dashArray = dashArray;\n        if (forceStyle) {\n          this.setStyle(Name.get(\"D\"));\n        }\n      } else {\n        this.width = 0;\n      }\n    } else if (dashArray) {\n      this.width = 0;\n    }\n  }\n  setHorizontalCornerRadius(radius) {\n    if (Number.isInteger(radius)) {\n      this.horizontalCornerRadius = radius;\n    }\n  }\n  setVerticalCornerRadius(radius) {\n    if (Number.isInteger(radius)) {\n      this.verticalCornerRadius = radius;\n    }\n  }\n}\nclass MarkupAnnotation extends Annotation {\n  constructor(params) {\n    super(params);\n    const {\n      dict\n    } = params;\n    if (dict.has(\"IRT\")) {\n      const rawIRT = dict.getRaw(\"IRT\");\n      this.data.inReplyTo = rawIRT instanceof Ref ? rawIRT.toString() : null;\n      const rt = dict.get(\"RT\");\n      this.data.replyType = rt instanceof Name ? rt.name : AnnotationReplyType.REPLY;\n    }\n    let popupRef = null;\n    if (this.data.replyType === AnnotationReplyType.GROUP) {\n      const parent = dict.get(\"IRT\");\n      this.setTitle(parent.get(\"T\"));\n      this.data.titleObj = this._title;\n      this.setContents(parent.get(\"Contents\"));\n      this.data.contentsObj = this._contents;\n      if (!parent.has(\"CreationDate\")) {\n        this.data.creationDate = null;\n      } else {\n        this.setCreationDate(parent.get(\"CreationDate\"));\n        this.data.creationDate = this.creationDate;\n      }\n      if (!parent.has(\"M\")) {\n        this.data.modificationDate = null;\n      } else {\n        this.setModificationDate(parent.get(\"M\"));\n        this.data.modificationDate = this.modificationDate;\n      }\n      popupRef = parent.getRaw(\"Popup\");\n      if (!parent.has(\"C\")) {\n        this.data.color = null;\n      } else {\n        this.setColor(parent.getArray(\"C\"));\n        this.data.color = this.color;\n      }\n    } else {\n      this.data.titleObj = this._title;\n      this.setCreationDate(dict.get(\"CreationDate\"));\n      this.data.creationDate = this.creationDate;\n      popupRef = dict.getRaw(\"Popup\");\n      if (!dict.has(\"C\")) {\n        this.data.color = null;\n      }\n    }\n    this.data.popupRef = popupRef instanceof Ref ? popupRef.toString() : null;\n    if (dict.has(\"RC\")) {\n      this.data.richText = XFAFactory.getRichTextAsHtml(dict.get(\"RC\"));\n    }\n  }\n  setCreationDate(creationDate) {\n    this.creationDate = typeof creationDate === \"string\" ? creationDate : null;\n  }\n  _setDefaultAppearance({\n    xref,\n    extra,\n    strokeColor,\n    fillColor,\n    blendMode,\n    strokeAlpha,\n    fillAlpha,\n    pointsCallback\n  }) {\n    let minX = Number.MAX_VALUE;\n    let minY = Number.MAX_VALUE;\n    let maxX = Number.MIN_VALUE;\n    let maxY = Number.MIN_VALUE;\n    const buffer = [\"q\"];\n    if (extra) {\n      buffer.push(extra);\n    }\n    if (strokeColor) {\n      buffer.push(`${strokeColor[0]} ${strokeColor[1]} ${strokeColor[2]} RG`);\n    }\n    if (fillColor) {\n      buffer.push(`${fillColor[0]} ${fillColor[1]} ${fillColor[2]} rg`);\n    }\n    let pointsArray = this.data.quadPoints;\n    if (!pointsArray) {\n      pointsArray = [[{\n        x: this.rectangle[0],\n        y: this.rectangle[3]\n      }, {\n        x: this.rectangle[2],\n        y: this.rectangle[3]\n      }, {\n        x: this.rectangle[0],\n        y: this.rectangle[1]\n      }, {\n        x: this.rectangle[2],\n        y: this.rectangle[1]\n      }]];\n    }\n    for (const points of pointsArray) {\n      const [mX, MX, mY, MY] = pointsCallback(buffer, points);\n      minX = Math.min(minX, mX);\n      maxX = Math.max(maxX, MX);\n      minY = Math.min(minY, mY);\n      maxY = Math.max(maxY, MY);\n    }\n    buffer.push(\"Q\");\n    const formDict = new Dict(xref);\n    const appearanceStreamDict = new Dict(xref);\n    appearanceStreamDict.set(\"Subtype\", Name.get(\"Form\"));\n    const appearanceStream = new StringStream(buffer.join(\" \"));\n    appearanceStream.dict = appearanceStreamDict;\n    formDict.set(\"Fm0\", appearanceStream);\n    const gsDict = new Dict(xref);\n    if (blendMode) {\n      gsDict.set(\"BM\", Name.get(blendMode));\n    }\n    if (typeof strokeAlpha === \"number\") {\n      gsDict.set(\"CA\", strokeAlpha);\n    }\n    if (typeof fillAlpha === \"number\") {\n      gsDict.set(\"ca\", fillAlpha);\n    }\n    const stateDict = new Dict(xref);\n    stateDict.set(\"GS0\", gsDict);\n    const resources = new Dict(xref);\n    resources.set(\"ExtGState\", stateDict);\n    resources.set(\"XObject\", formDict);\n    const appearanceDict = new Dict(xref);\n    appearanceDict.set(\"Resources\", resources);\n    const bbox = this.data.rect = [minX, minY, maxX, maxY];\n    appearanceDict.set(\"BBox\", bbox);\n    this.appearance = new StringStream(\"/GS0 gs /Fm0 Do\");\n    this.appearance.dict = appearanceDict;\n    this._streams.push(this.appearance, appearanceStream);\n  }\n  static async createNewAnnotation(xref, annotation, dependencies, params) {\n    const annotationRef = annotation.ref ||= xref.getNewTemporaryRef();\n    const ap = await this.createNewAppearanceStream(annotation, xref, params);\n    const buffer = [];\n    let annotationDict;\n    if (ap) {\n      const apRef = xref.getNewTemporaryRef();\n      annotationDict = this.createNewDict(annotation, xref, {\n        apRef\n      });\n      await writeObject(apRef, ap, buffer, xref);\n      dependencies.push({\n        ref: apRef,\n        data: buffer.join(\"\")\n      });\n    } else {\n      annotationDict = this.createNewDict(annotation, xref, {});\n    }\n    if (Number.isInteger(annotation.parentTreeId)) {\n      annotationDict.set(\"StructParent\", annotation.parentTreeId);\n    }\n    buffer.length = 0;\n    await writeObject(annotationRef, annotationDict, buffer, xref);\n    return {\n      ref: annotationRef,\n      data: buffer.join(\"\")\n    };\n  }\n  static async createNewPrintAnnotation(annotationGlobals, xref, annotation, params) {\n    const ap = await this.createNewAppearanceStream(annotation, xref, params);\n    const annotationDict = this.createNewDict(annotation, xref, {\n      ap\n    });\n    const newAnnotation = new this.prototype.constructor({\n      dict: annotationDict,\n      xref,\n      annotationGlobals,\n      evaluatorOptions: params.evaluatorOptions\n    });\n    if (annotation.ref) {\n      newAnnotation.ref = newAnnotation.refToReplace = annotation.ref;\n    }\n    return newAnnotation;\n  }\n}\nclass WidgetAnnotation extends Annotation {\n  constructor(params) {\n    super(params);\n    const {\n      dict,\n      xref,\n      annotationGlobals\n    } = params;\n    const data = this.data;\n    this._needAppearances = params.needAppearances;\n    data.annotationType = AnnotationType.WIDGET;\n    if (data.fieldName === undefined) {\n      data.fieldName = this._constructFieldName(dict);\n    }\n    if (data.actions === undefined) {\n      data.actions = collectActions(xref, dict, AnnotationActionEventType);\n    }\n    let fieldValue = getInheritableProperty({\n      dict,\n      key: \"V\",\n      getArray: true\n    });\n    data.fieldValue = this._decodeFormValue(fieldValue);\n    const defaultFieldValue = getInheritableProperty({\n      dict,\n      key: \"DV\",\n      getArray: true\n    });\n    data.defaultFieldValue = this._decodeFormValue(defaultFieldValue);\n    if (fieldValue === undefined && annotationGlobals.xfaDatasets) {\n      const path = this._title.str;\n      if (path) {\n        this._hasValueFromXFA = true;\n        data.fieldValue = fieldValue = annotationGlobals.xfaDatasets.getValue(path);\n      }\n    }\n    if (fieldValue === undefined && data.defaultFieldValue !== null) {\n      data.fieldValue = data.defaultFieldValue;\n    }\n    data.alternativeText = stringToPDFString(dict.get(\"TU\") || \"\");\n    this.setDefaultAppearance(params);\n    data.hasAppearance ||= this._needAppearances && data.fieldValue !== undefined && data.fieldValue !== null;\n    const fieldType = getInheritableProperty({\n      dict,\n      key: \"FT\"\n    });\n    data.fieldType = fieldType instanceof Name ? fieldType.name : null;\n    const localResources = getInheritableProperty({\n      dict,\n      key: \"DR\"\n    });\n    const acroFormResources = annotationGlobals.acroForm.get(\"DR\");\n    const appearanceResources = this.appearance?.dict.get(\"Resources\");\n    this._fieldResources = {\n      localResources,\n      acroFormResources,\n      appearanceResources,\n      mergedResources: Dict.merge({\n        xref,\n        dictArray: [localResources, appearanceResources, acroFormResources],\n        mergeSubDicts: true\n      })\n    };\n    data.fieldFlags = getInheritableProperty({\n      dict,\n      key: \"Ff\"\n    });\n    if (!Number.isInteger(data.fieldFlags) || data.fieldFlags < 0) {\n      data.fieldFlags = 0;\n    }\n    data.readOnly = this.hasFieldFlag(AnnotationFieldFlag.READONLY);\n    data.required = this.hasFieldFlag(AnnotationFieldFlag.REQUIRED);\n    data.hidden = this._hasFlag(data.annotationFlags, AnnotationFlag.HIDDEN) || this._hasFlag(data.annotationFlags, AnnotationFlag.NOVIEW);\n  }\n  _decodeFormValue(formValue) {\n    if (Array.isArray(formValue)) {\n      return formValue.filter(item => typeof item === \"string\").map(item => stringToPDFString(item));\n    } else if (formValue instanceof Name) {\n      return stringToPDFString(formValue.name);\n    } else if (typeof formValue === \"string\") {\n      return stringToPDFString(formValue);\n    }\n    return null;\n  }\n  hasFieldFlag(flag) {\n    return !!(this.data.fieldFlags & flag);\n  }\n  _isViewable(flags) {\n    return true;\n  }\n  mustBeViewed(annotationStorage, renderForms) {\n    if (renderForms) {\n      return this.viewable;\n    }\n    return super.mustBeViewed(annotationStorage, renderForms) && !this._hasFlag(this.flags, AnnotationFlag.NOVIEW);\n  }\n  getRotationMatrix(annotationStorage) {\n    let rotation = annotationStorage?.get(this.data.id)?.rotation;\n    if (rotation === undefined) {\n      rotation = this.rotation;\n    }\n    if (rotation === 0) {\n      return IDENTITY_MATRIX;\n    }\n    const width = this.data.rect[2] - this.data.rect[0];\n    const height = this.data.rect[3] - this.data.rect[1];\n    return getRotationMatrix(rotation, width, height);\n  }\n  getBorderAndBackgroundAppearances(annotationStorage) {\n    let rotation = annotationStorage?.get(this.data.id)?.rotation;\n    if (rotation === undefined) {\n      rotation = this.rotation;\n    }\n    if (!this.backgroundColor && !this.borderColor) {\n      return \"\";\n    }\n    const width = this.data.rect[2] - this.data.rect[0];\n    const height = this.data.rect[3] - this.data.rect[1];\n    const rect = rotation === 0 || rotation === 180 ? `0 0 ${width} ${height} re` : `0 0 ${height} ${width} re`;\n    let str = \"\";\n    if (this.backgroundColor) {\n      str = `${getPdfColor(this.backgroundColor, true)} ${rect} f `;\n    }\n    if (this.borderColor) {\n      const borderWidth = this.borderStyle.width || 1;\n      str += `${borderWidth} w ${getPdfColor(this.borderColor, false)} ${rect} S `;\n    }\n    return str;\n  }\n  async getOperatorList(evaluator, task, intent, renderForms, annotationStorage) {\n    if (renderForms && !(this instanceof SignatureWidgetAnnotation) && !this.data.noHTML && !this.data.hasOwnCanvas) {\n      return {\n        opList: new OperatorList(),\n        separateForm: true,\n        separateCanvas: false\n      };\n    }\n    if (!this._hasText) {\n      return super.getOperatorList(evaluator, task, intent, renderForms, annotationStorage);\n    }\n    const content = await this._getAppearance(evaluator, task, intent, annotationStorage);\n    if (this.appearance && content === null) {\n      return super.getOperatorList(evaluator, task, intent, renderForms, annotationStorage);\n    }\n    const opList = new OperatorList();\n    if (!this._defaultAppearance || content === null) {\n      return {\n        opList,\n        separateForm: false,\n        separateCanvas: false\n      };\n    }\n    const isUsingOwnCanvas = !!(this.data.hasOwnCanvas && intent & RenderingIntentFlag.DISPLAY);\n    const matrix = [1, 0, 0, 1, 0, 0];\n    const bbox = [0, 0, this.data.rect[2] - this.data.rect[0], this.data.rect[3] - this.data.rect[1]];\n    const transform = getTransformMatrix(this.data.rect, bbox, matrix);\n    let optionalContent;\n    if (this.oc) {\n      optionalContent = await evaluator.parseMarkedContentProps(this.oc, null);\n    }\n    if (optionalContent !== undefined) {\n      opList.addOp(OPS.beginMarkedContentProps, [\"OC\", optionalContent]);\n    }\n    opList.addOp(OPS.beginAnnotation, [this.data.id, this.data.rect, transform, this.getRotationMatrix(annotationStorage), isUsingOwnCanvas]);\n    const stream = new StringStream(content);\n    await evaluator.getOperatorList({\n      stream,\n      task,\n      resources: this._fieldResources.mergedResources,\n      operatorList: opList\n    });\n    opList.addOp(OPS.endAnnotation, []);\n    if (optionalContent !== undefined) {\n      opList.addOp(OPS.endMarkedContent, []);\n    }\n    return {\n      opList,\n      separateForm: false,\n      separateCanvas: isUsingOwnCanvas\n    };\n  }\n  _getMKDict(rotation) {\n    const mk = new Dict(null);\n    if (rotation) {\n      mk.set(\"R\", rotation);\n    }\n    if (this.borderColor) {\n      mk.set(\"BC\", getPdfColorArray(this.borderColor));\n    }\n    if (this.backgroundColor) {\n      mk.set(\"BG\", getPdfColorArray(this.backgroundColor));\n    }\n    return mk.size > 0 ? mk : null;\n  }\n  amendSavedDict(annotationStorage, dict) {}\n  async save(evaluator, task, annotationStorage) {\n    const storageEntry = annotationStorage?.get(this.data.id);\n    let value = storageEntry?.value,\n      rotation = storageEntry?.rotation;\n    if (value === this.data.fieldValue || value === undefined) {\n      if (!this._hasValueFromXFA && rotation === undefined) {\n        return null;\n      }\n      value ||= this.data.fieldValue;\n    }\n    if (rotation === undefined && !this._hasValueFromXFA && Array.isArray(value) && Array.isArray(this.data.fieldValue) && value.length === this.data.fieldValue.length && value.every((x, i) => x === this.data.fieldValue[i])) {\n      return null;\n    }\n    if (rotation === undefined) {\n      rotation = this.rotation;\n    }\n    let appearance = null;\n    if (!this._needAppearances) {\n      appearance = await this._getAppearance(evaluator, task, RenderingIntentFlag.SAVE, annotationStorage);\n      if (appearance === null) {\n        return null;\n      }\n    } else {}\n    let needAppearances = false;\n    if (appearance?.needAppearances) {\n      needAppearances = true;\n      appearance = null;\n    }\n    const {\n      xref\n    } = evaluator;\n    const originalDict = xref.fetchIfRef(this.ref);\n    if (!(originalDict instanceof Dict)) {\n      return null;\n    }\n    const dict = new Dict(xref);\n    for (const key of originalDict.getKeys()) {\n      if (key !== \"AP\") {\n        dict.set(key, originalDict.getRaw(key));\n      }\n    }\n    const xfa = {\n      path: this.data.fieldName,\n      value\n    };\n    const encoder = val => isAscii(val) ? val : stringToUTF16String(val, true);\n    dict.set(\"V\", Array.isArray(value) ? value.map(encoder) : encoder(value));\n    this.amendSavedDict(annotationStorage, dict);\n    const maybeMK = this._getMKDict(rotation);\n    if (maybeMK) {\n      dict.set(\"MK\", maybeMK);\n    }\n    const buffer = [];\n    const changes = [{\n      ref: this.ref,\n      data: \"\",\n      xfa,\n      needAppearances\n    }];\n    if (appearance !== null) {\n      const newRef = xref.getNewTemporaryRef();\n      const AP = new Dict(xref);\n      dict.set(\"AP\", AP);\n      AP.set(\"N\", newRef);\n      const resources = this._getSaveFieldResources(xref);\n      const appearanceStream = new StringStream(appearance);\n      const appearanceDict = appearanceStream.dict = new Dict(xref);\n      appearanceDict.set(\"Subtype\", Name.get(\"Form\"));\n      appearanceDict.set(\"Resources\", resources);\n      appearanceDict.set(\"BBox\", [0, 0, this.data.rect[2] - this.data.rect[0], this.data.rect[3] - this.data.rect[1]]);\n      const rotationMatrix = this.getRotationMatrix(annotationStorage);\n      if (rotationMatrix !== IDENTITY_MATRIX) {\n        appearanceDict.set(\"Matrix\", rotationMatrix);\n      }\n      await writeObject(newRef, appearanceStream, buffer, xref);\n      changes.push({\n        ref: newRef,\n        data: buffer.join(\"\"),\n        xfa: null,\n        needAppearances: false\n      });\n      buffer.length = 0;\n    }\n    dict.set(\"M\", `D:${getModificationDate()}`);\n    await writeObject(this.ref, dict, buffer, xref);\n    changes[0].data = buffer.join(\"\");\n    return changes;\n  }\n  async _getAppearance(evaluator, task, intent, annotationStorage) {\n    const isPassword = this.hasFieldFlag(AnnotationFieldFlag.PASSWORD);\n    if (isPassword) {\n      return null;\n    }\n    const storageEntry = annotationStorage?.get(this.data.id);\n    let value, rotation;\n    if (storageEntry) {\n      value = storageEntry.formattedValue || storageEntry.value;\n      rotation = storageEntry.rotation;\n    }\n    if (rotation === undefined && value === undefined && !this._needAppearances) {\n      if (!this._hasValueFromXFA || this.appearance) {\n        return null;\n      }\n    }\n    const colors = this.getBorderAndBackgroundAppearances(annotationStorage);\n    if (value === undefined) {\n      value = this.data.fieldValue;\n      if (!value) {\n        return `/Tx BMC q ${colors}Q EMC`;\n      }\n    }\n    if (Array.isArray(value) && value.length === 1) {\n      value = value[0];\n    }\n    assert(typeof value === \"string\", \"Expected `value` to be a string.\");\n    value = value.trim();\n    if (this.data.combo) {\n      const option = this.data.options.find(({\n        exportValue\n      }) => value === exportValue);\n      value = option?.displayValue || value;\n    }\n    if (value === \"\") {\n      return `/Tx BMC q ${colors}Q EMC`;\n    }\n    if (rotation === undefined) {\n      rotation = this.rotation;\n    }\n    let lineCount = -1;\n    let lines;\n    if (this.data.multiLine) {\n      lines = value.split(/\\r\\n?|\\n/).map(line => line.normalize(\"NFC\"));\n      lineCount = lines.length;\n    } else {\n      lines = [value.replace(/\\r\\n?|\\n/, \"\").normalize(\"NFC\")];\n    }\n    const defaultPadding = 1;\n    const defaultHPadding = 2;\n    let totalHeight = this.data.rect[3] - this.data.rect[1];\n    let totalWidth = this.data.rect[2] - this.data.rect[0];\n    if (rotation === 90 || rotation === 270) {\n      [totalWidth, totalHeight] = [totalHeight, totalWidth];\n    }\n    if (!this._defaultAppearance) {\n      this.data.defaultAppearanceData = parseDefaultAppearance(this._defaultAppearance = \"/Helvetica 0 Tf 0 g\");\n    }\n    let font = await WidgetAnnotation._getFontData(evaluator, task, this.data.defaultAppearanceData, this._fieldResources.mergedResources);\n    let defaultAppearance, fontSize, lineHeight;\n    const encodedLines = [];\n    let encodingError = false;\n    for (const line of lines) {\n      const encodedString = font.encodeString(line);\n      if (encodedString.length > 1) {\n        encodingError = true;\n      }\n      encodedLines.push(encodedString.join(\"\"));\n    }\n    if (encodingError && intent & RenderingIntentFlag.SAVE) {\n      return {\n        needAppearances: true\n      };\n    }\n    if (encodingError && this._isOffscreenCanvasSupported) {\n      const fontFamily = this.data.comb ? \"monospace\" : \"sans-serif\";\n      const fakeUnicodeFont = new FakeUnicodeFont(evaluator.xref, fontFamily);\n      const resources = fakeUnicodeFont.createFontResources(lines.join(\"\"));\n      const newFont = resources.getRaw(\"Font\");\n      if (this._fieldResources.mergedResources.has(\"Font\")) {\n        const oldFont = this._fieldResources.mergedResources.get(\"Font\");\n        for (const key of newFont.getKeys()) {\n          oldFont.set(key, newFont.getRaw(key));\n        }\n      } else {\n        this._fieldResources.mergedResources.set(\"Font\", newFont);\n      }\n      const fontName = fakeUnicodeFont.fontName.name;\n      font = await WidgetAnnotation._getFontData(evaluator, task, {\n        fontName,\n        fontSize: 0\n      }, resources);\n      for (let i = 0, ii = encodedLines.length; i < ii; i++) {\n        encodedLines[i] = stringToUTF16String(lines[i]);\n      }\n      const savedDefaultAppearance = Object.assign(Object.create(null), this.data.defaultAppearanceData);\n      this.data.defaultAppearanceData.fontSize = 0;\n      this.data.defaultAppearanceData.fontName = fontName;\n      [defaultAppearance, fontSize, lineHeight] = this._computeFontSize(totalHeight - 2 * defaultPadding, totalWidth - 2 * defaultHPadding, value, font, lineCount);\n      this.data.defaultAppearanceData = savedDefaultAppearance;\n    } else {\n      if (!this._isOffscreenCanvasSupported) {\n        warn(\"_getAppearance: OffscreenCanvas is not supported, annotation may not render correctly.\");\n      }\n      [defaultAppearance, fontSize, lineHeight] = this._computeFontSize(totalHeight - 2 * defaultPadding, totalWidth - 2 * defaultHPadding, value, font, lineCount);\n    }\n    let descent = font.descent;\n    if (isNaN(descent)) {\n      descent = BASELINE_FACTOR * lineHeight;\n    } else {\n      descent = Math.max(BASELINE_FACTOR * lineHeight, Math.abs(descent) * fontSize);\n    }\n    const defaultVPadding = Math.min(Math.floor((totalHeight - fontSize) / 2), defaultPadding);\n    const alignment = this.data.textAlignment;\n    if (this.data.multiLine) {\n      return this._getMultilineAppearance(defaultAppearance, encodedLines, font, fontSize, totalWidth, totalHeight, alignment, defaultHPadding, defaultVPadding, descent, lineHeight, annotationStorage);\n    }\n    if (this.data.comb) {\n      return this._getCombAppearance(defaultAppearance, font, encodedLines[0], fontSize, totalWidth, totalHeight, defaultHPadding, defaultVPadding, descent, lineHeight, annotationStorage);\n    }\n    const bottomPadding = defaultVPadding + descent;\n    if (alignment === 0 || alignment > 2) {\n      return `/Tx BMC q ${colors}BT ` + defaultAppearance + ` 1 0 0 1 ${numberToString(defaultHPadding)} ${numberToString(bottomPadding)} Tm (${escapeString(encodedLines[0])}) Tj` + \" ET Q EMC\";\n    }\n    const prevInfo = {\n      shift: 0\n    };\n    const renderedText = this._renderText(encodedLines[0], font, fontSize, totalWidth, alignment, prevInfo, defaultHPadding, bottomPadding);\n    return `/Tx BMC q ${colors}BT ` + defaultAppearance + ` 1 0 0 1 0 0 Tm ${renderedText}` + \" ET Q EMC\";\n  }\n  static async _getFontData(evaluator, task, appearanceData, resources) {\n    const operatorList = new OperatorList();\n    const initialState = {\n      font: null,\n      clone() {\n        return this;\n      }\n    };\n    const {\n      fontName,\n      fontSize\n    } = appearanceData;\n    await evaluator.handleSetFont(resources, [fontName && Name.get(fontName), fontSize], null, operatorList, task, initialState, null);\n    return initialState.font;\n  }\n  _getTextWidth(text, font) {\n    return font.charsToGlyphs(text).reduce((width, glyph) => width + glyph.width, 0) / 1000;\n  }\n  _computeFontSize(height, width, text, font, lineCount) {\n    let {\n      fontSize\n    } = this.data.defaultAppearanceData;\n    let lineHeight = (fontSize || 12) * LINE_FACTOR,\n      numberOfLines = Math.round(height / lineHeight);\n    if (!fontSize) {\n      const roundWithTwoDigits = x => Math.floor(x * 100) / 100;\n      if (lineCount === -1) {\n        const textWidth = this._getTextWidth(text, font);\n        fontSize = roundWithTwoDigits(Math.min(height / LINE_FACTOR, textWidth > width ? width / textWidth : Infinity));\n        numberOfLines = 1;\n      } else {\n        const lines = text.split(/\\r\\n?|\\n/);\n        const cachedLines = [];\n        for (const line of lines) {\n          const encoded = font.encodeString(line).join(\"\");\n          const glyphs = font.charsToGlyphs(encoded);\n          const positions = font.getCharPositions(encoded);\n          cachedLines.push({\n            line: encoded,\n            glyphs,\n            positions\n          });\n        }\n        const isTooBig = fsize => {\n          let totalHeight = 0;\n          for (const cache of cachedLines) {\n            const chunks = this._splitLine(null, font, fsize, width, cache);\n            totalHeight += chunks.length * fsize;\n            if (totalHeight > height) {\n              return true;\n            }\n          }\n          return false;\n        };\n        numberOfLines = Math.max(numberOfLines, lineCount);\n        while (true) {\n          lineHeight = height / numberOfLines;\n          fontSize = roundWithTwoDigits(lineHeight / LINE_FACTOR);\n          if (isTooBig(fontSize)) {\n            numberOfLines++;\n            continue;\n          }\n          break;\n        }\n      }\n      const {\n        fontName,\n        fontColor\n      } = this.data.defaultAppearanceData;\n      this._defaultAppearance = createDefaultAppearance({\n        fontSize,\n        fontName,\n        fontColor\n      });\n    }\n    return [this._defaultAppearance, fontSize, height / numberOfLines];\n  }\n  _renderText(text, font, fontSize, totalWidth, alignment, prevInfo, hPadding, vPadding) {\n    let shift;\n    if (alignment === 1) {\n      const width = this._getTextWidth(text, font) * fontSize;\n      shift = (totalWidth - width) / 2;\n    } else if (alignment === 2) {\n      const width = this._getTextWidth(text, font) * fontSize;\n      shift = totalWidth - width - hPadding;\n    } else {\n      shift = hPadding;\n    }\n    const shiftStr = numberToString(shift - prevInfo.shift);\n    prevInfo.shift = shift;\n    vPadding = numberToString(vPadding);\n    return `${shiftStr} ${vPadding} Td (${escapeString(text)}) Tj`;\n  }\n  _getSaveFieldResources(xref) {\n    const {\n      localResources,\n      appearanceResources,\n      acroFormResources\n    } = this._fieldResources;\n    const fontName = this.data.defaultAppearanceData?.fontName;\n    if (!fontName) {\n      return localResources || Dict.empty;\n    }\n    for (const resources of [localResources, appearanceResources]) {\n      if (resources instanceof Dict) {\n        const localFont = resources.get(\"Font\");\n        if (localFont instanceof Dict && localFont.has(fontName)) {\n          return resources;\n        }\n      }\n    }\n    if (acroFormResources instanceof Dict) {\n      const acroFormFont = acroFormResources.get(\"Font\");\n      if (acroFormFont instanceof Dict && acroFormFont.has(fontName)) {\n        const subFontDict = new Dict(xref);\n        subFontDict.set(fontName, acroFormFont.getRaw(fontName));\n        const subResourcesDict = new Dict(xref);\n        subResourcesDict.set(\"Font\", subFontDict);\n        return Dict.merge({\n          xref,\n          dictArray: [subResourcesDict, localResources],\n          mergeSubDicts: true\n        });\n      }\n    }\n    return localResources || Dict.empty;\n  }\n  getFieldObject() {\n    return null;\n  }\n}\nclass TextWidgetAnnotation extends WidgetAnnotation {\n  constructor(params) {\n    super(params);\n    this.data.hasOwnCanvas = this.data.readOnly && !this.data.noHTML;\n    this._hasText = true;\n    const dict = params.dict;\n    if (typeof this.data.fieldValue !== \"string\") {\n      this.data.fieldValue = \"\";\n    }\n    let alignment = getInheritableProperty({\n      dict,\n      key: \"Q\"\n    });\n    if (!Number.isInteger(alignment) || alignment < 0 || alignment > 2) {\n      alignment = null;\n    }\n    this.data.textAlignment = alignment;\n    let maximumLength = getInheritableProperty({\n      dict,\n      key: \"MaxLen\"\n    });\n    if (!Number.isInteger(maximumLength) || maximumLength < 0) {\n      maximumLength = 0;\n    }\n    this.data.maxLen = maximumLength;\n    this.data.multiLine = this.hasFieldFlag(AnnotationFieldFlag.MULTILINE);\n    this.data.comb = this.hasFieldFlag(AnnotationFieldFlag.COMB) && !this.hasFieldFlag(AnnotationFieldFlag.MULTILINE) && !this.hasFieldFlag(AnnotationFieldFlag.PASSWORD) && !this.hasFieldFlag(AnnotationFieldFlag.FILESELECT) && this.data.maxLen !== 0;\n    this.data.doNotScroll = this.hasFieldFlag(AnnotationFieldFlag.DONOTSCROLL);\n  }\n  get hasTextContent() {\n    return !!this.appearance && !this._needAppearances;\n  }\n  _getCombAppearance(defaultAppearance, font, text, fontSize, width, height, hPadding, vPadding, descent, lineHeight, annotationStorage) {\n    const combWidth = width / this.data.maxLen;\n    const colors = this.getBorderAndBackgroundAppearances(annotationStorage);\n    const buf = [];\n    const positions = font.getCharPositions(text);\n    for (const [start, end] of positions) {\n      buf.push(`(${escapeString(text.substring(start, end))}) Tj`);\n    }\n    const renderedComb = buf.join(` ${numberToString(combWidth)} 0 Td `);\n    return `/Tx BMC q ${colors}BT ` + defaultAppearance + ` 1 0 0 1 ${numberToString(hPadding)} ${numberToString(vPadding + descent)} Tm ${renderedComb}` + \" ET Q EMC\";\n  }\n  _getMultilineAppearance(defaultAppearance, lines, font, fontSize, width, height, alignment, hPadding, vPadding, descent, lineHeight, annotationStorage) {\n    const buf = [];\n    const totalWidth = width - 2 * hPadding;\n    const prevInfo = {\n      shift: 0\n    };\n    for (let i = 0, ii = lines.length; i < ii; i++) {\n      const line = lines[i];\n      const chunks = this._splitLine(line, font, fontSize, totalWidth);\n      for (let j = 0, jj = chunks.length; j < jj; j++) {\n        const chunk = chunks[j];\n        const vShift = i === 0 && j === 0 ? -vPadding - (lineHeight - descent) : -lineHeight;\n        buf.push(this._renderText(chunk, font, fontSize, width, alignment, prevInfo, hPadding, vShift));\n      }\n    }\n    const colors = this.getBorderAndBackgroundAppearances(annotationStorage);\n    const renderedText = buf.join(\"\\n\");\n    return `/Tx BMC q ${colors}BT ` + defaultAppearance + ` 1 0 0 1 0 ${numberToString(height)} Tm ${renderedText}` + \" ET Q EMC\";\n  }\n  _splitLine(line, font, fontSize, width, cache = {}) {\n    line = cache.line || line;\n    const glyphs = cache.glyphs || font.charsToGlyphs(line);\n    if (glyphs.length <= 1) {\n      return [line];\n    }\n    const positions = cache.positions || font.getCharPositions(line);\n    const scale = fontSize / 1000;\n    const chunks = [];\n    let lastSpacePosInStringStart = -1,\n      lastSpacePosInStringEnd = -1,\n      lastSpacePos = -1,\n      startChunk = 0,\n      currentWidth = 0;\n    for (let i = 0, ii = glyphs.length; i < ii; i++) {\n      const [start, end] = positions[i];\n      const glyph = glyphs[i];\n      const glyphWidth = glyph.width * scale;\n      if (glyph.unicode === \" \") {\n        if (currentWidth + glyphWidth > width) {\n          chunks.push(line.substring(startChunk, start));\n          startChunk = start;\n          currentWidth = glyphWidth;\n          lastSpacePosInStringStart = -1;\n          lastSpacePos = -1;\n        } else {\n          currentWidth += glyphWidth;\n          lastSpacePosInStringStart = start;\n          lastSpacePosInStringEnd = end;\n          lastSpacePos = i;\n        }\n      } else if (currentWidth + glyphWidth > width) {\n        if (lastSpacePosInStringStart !== -1) {\n          chunks.push(line.substring(startChunk, lastSpacePosInStringEnd));\n          startChunk = lastSpacePosInStringEnd;\n          i = lastSpacePos + 1;\n          lastSpacePosInStringStart = -1;\n          currentWidth = 0;\n        } else {\n          chunks.push(line.substring(startChunk, start));\n          startChunk = start;\n          currentWidth = glyphWidth;\n        }\n      } else {\n        currentWidth += glyphWidth;\n      }\n    }\n    if (startChunk < line.length) {\n      chunks.push(line.substring(startChunk, line.length));\n    }\n    return chunks;\n  }\n  getFieldObject() {\n    return {\n      id: this.data.id,\n      value: this.data.fieldValue,\n      defaultValue: this.data.defaultFieldValue || \"\",\n      multiline: this.data.multiLine,\n      password: this.hasFieldFlag(AnnotationFieldFlag.PASSWORD),\n      charLimit: this.data.maxLen,\n      comb: this.data.comb,\n      editable: !this.data.readOnly,\n      hidden: this.data.hidden,\n      name: this.data.fieldName,\n      rect: this.data.rect,\n      actions: this.data.actions,\n      page: this.data.pageIndex,\n      strokeColor: this.data.borderColor,\n      fillColor: this.data.backgroundColor,\n      rotation: this.rotation,\n      type: \"text\"\n    };\n  }\n}\nclass ButtonWidgetAnnotation extends WidgetAnnotation {\n  constructor(params) {\n    super(params);\n    this.checkedAppearance = null;\n    this.uncheckedAppearance = null;\n    this.data.checkBox = !this.hasFieldFlag(AnnotationFieldFlag.RADIO) && !this.hasFieldFlag(AnnotationFieldFlag.PUSHBUTTON);\n    this.data.radioButton = this.hasFieldFlag(AnnotationFieldFlag.RADIO) && !this.hasFieldFlag(AnnotationFieldFlag.PUSHBUTTON);\n    this.data.pushButton = this.hasFieldFlag(AnnotationFieldFlag.PUSHBUTTON);\n    this.data.isTooltipOnly = false;\n    if (this.data.checkBox) {\n      this._processCheckBox(params);\n    } else if (this.data.radioButton) {\n      this._processRadioButton(params);\n    } else if (this.data.pushButton) {\n      this.data.hasOwnCanvas = true;\n      this.data.noHTML = false;\n      this._processPushButton(params);\n    } else {\n      warn(\"Invalid field flags for button widget annotation\");\n    }\n  }\n  async getOperatorList(evaluator, task, intent, renderForms, annotationStorage) {\n    if (this.data.pushButton) {\n      return super.getOperatorList(evaluator, task, intent, false, annotationStorage);\n    }\n    let value = null;\n    let rotation = null;\n    if (annotationStorage) {\n      const storageEntry = annotationStorage.get(this.data.id);\n      value = storageEntry ? storageEntry.value : null;\n      rotation = storageEntry ? storageEntry.rotation : null;\n    }\n    if (value === null && this.appearance) {\n      return super.getOperatorList(evaluator, task, intent, renderForms, annotationStorage);\n    }\n    if (value === null || value === undefined) {\n      value = this.data.checkBox ? this.data.fieldValue === this.data.exportValue : this.data.fieldValue === this.data.buttonValue;\n    }\n    const appearance = value ? this.checkedAppearance : this.uncheckedAppearance;\n    if (appearance) {\n      const savedAppearance = this.appearance;\n      const savedMatrix = appearance.dict.getArray(\"Matrix\") || IDENTITY_MATRIX;\n      if (rotation) {\n        appearance.dict.set(\"Matrix\", this.getRotationMatrix(annotationStorage));\n      }\n      this.appearance = appearance;\n      const operatorList = super.getOperatorList(evaluator, task, intent, renderForms, annotationStorage);\n      this.appearance = savedAppearance;\n      appearance.dict.set(\"Matrix\", savedMatrix);\n      return operatorList;\n    }\n    return {\n      opList: new OperatorList(),\n      separateForm: false,\n      separateCanvas: false\n    };\n  }\n  async save(evaluator, task, annotationStorage) {\n    if (this.data.checkBox) {\n      return this._saveCheckbox(evaluator, task, annotationStorage);\n    }\n    if (this.data.radioButton) {\n      return this._saveRadioButton(evaluator, task, annotationStorage);\n    }\n    return null;\n  }\n  async _saveCheckbox(evaluator, task, annotationStorage) {\n    if (!annotationStorage) {\n      return null;\n    }\n    const storageEntry = annotationStorage.get(this.data.id);\n    let rotation = storageEntry?.rotation,\n      value = storageEntry?.value;\n    if (rotation === undefined) {\n      if (value === undefined) {\n        return null;\n      }\n      const defaultValue = this.data.fieldValue === this.data.exportValue;\n      if (defaultValue === value) {\n        return null;\n      }\n    }\n    const dict = evaluator.xref.fetchIfRef(this.ref);\n    if (!(dict instanceof Dict)) {\n      return null;\n    }\n    if (rotation === undefined) {\n      rotation = this.rotation;\n    }\n    if (value === undefined) {\n      value = this.data.fieldValue === this.data.exportValue;\n    }\n    const xfa = {\n      path: this.data.fieldName,\n      value: value ? this.data.exportValue : \"\"\n    };\n    const name = Name.get(value ? this.data.exportValue : \"Off\");\n    dict.set(\"V\", name);\n    dict.set(\"AS\", name);\n    dict.set(\"M\", `D:${getModificationDate()}`);\n    const maybeMK = this._getMKDict(rotation);\n    if (maybeMK) {\n      dict.set(\"MK\", maybeMK);\n    }\n    const buffer = [];\n    await writeObject(this.ref, dict, buffer, evaluator.xref);\n    return [{\n      ref: this.ref,\n      data: buffer.join(\"\"),\n      xfa\n    }];\n  }\n  async _saveRadioButton(evaluator, task, annotationStorage) {\n    if (!annotationStorage) {\n      return null;\n    }\n    const storageEntry = annotationStorage.get(this.data.id);\n    let rotation = storageEntry?.rotation,\n      value = storageEntry?.value;\n    if (rotation === undefined) {\n      if (value === undefined) {\n        return null;\n      }\n      const defaultValue = this.data.fieldValue === this.data.buttonValue;\n      if (defaultValue === value) {\n        return null;\n      }\n    }\n    const dict = evaluator.xref.fetchIfRef(this.ref);\n    if (!(dict instanceof Dict)) {\n      return null;\n    }\n    if (value === undefined) {\n      value = this.data.fieldValue === this.data.buttonValue;\n    }\n    if (rotation === undefined) {\n      rotation = this.rotation;\n    }\n    const xfa = {\n      path: this.data.fieldName,\n      value: value ? this.data.buttonValue : \"\"\n    };\n    const name = Name.get(value ? this.data.buttonValue : \"Off\");\n    const buffer = [];\n    let parentData = null;\n    if (value) {\n      if (this.parent instanceof Ref) {\n        const parent = evaluator.xref.fetch(this.parent);\n        parent.set(\"V\", name);\n        await writeObject(this.parent, parent, buffer, evaluator.xref);\n        parentData = buffer.join(\"\");\n        buffer.length = 0;\n      } else if (this.parent instanceof Dict) {\n        this.parent.set(\"V\", name);\n      }\n    }\n    dict.set(\"AS\", name);\n    dict.set(\"M\", `D:${getModificationDate()}`);\n    const maybeMK = this._getMKDict(rotation);\n    if (maybeMK) {\n      dict.set(\"MK\", maybeMK);\n    }\n    await writeObject(this.ref, dict, buffer, evaluator.xref);\n    const newRefs = [{\n      ref: this.ref,\n      data: buffer.join(\"\"),\n      xfa\n    }];\n    if (parentData) {\n      newRefs.push({\n        ref: this.parent,\n        data: parentData,\n        xfa: null\n      });\n    }\n    return newRefs;\n  }\n  _getDefaultCheckedAppearance(params, type) {\n    const width = this.data.rect[2] - this.data.rect[0];\n    const height = this.data.rect[3] - this.data.rect[1];\n    const bbox = [0, 0, width, height];\n    const FONT_RATIO = 0.8;\n    const fontSize = Math.min(width, height) * FONT_RATIO;\n    let metrics, char;\n    if (type === \"check\") {\n      metrics = {\n        width: 0.755 * fontSize,\n        height: 0.705 * fontSize\n      };\n      char = \"\\x33\";\n    } else if (type === \"disc\") {\n      metrics = {\n        width: 0.791 * fontSize,\n        height: 0.705 * fontSize\n      };\n      char = \"\\x6C\";\n    } else {\n      unreachable(`_getDefaultCheckedAppearance - unsupported type: ${type}`);\n    }\n    const xShift = numberToString((width - metrics.width) / 2);\n    const yShift = numberToString((height - metrics.height) / 2);\n    const appearance = `q BT /PdfJsZaDb ${fontSize} Tf 0 g ${xShift} ${yShift} Td (${char}) Tj ET Q`;\n    const appearanceStreamDict = new Dict(params.xref);\n    appearanceStreamDict.set(\"FormType\", 1);\n    appearanceStreamDict.set(\"Subtype\", Name.get(\"Form\"));\n    appearanceStreamDict.set(\"Type\", Name.get(\"XObject\"));\n    appearanceStreamDict.set(\"BBox\", bbox);\n    appearanceStreamDict.set(\"Matrix\", [1, 0, 0, 1, 0, 0]);\n    appearanceStreamDict.set(\"Length\", appearance.length);\n    const resources = new Dict(params.xref);\n    const font = new Dict(params.xref);\n    font.set(\"PdfJsZaDb\", this.fallbackFontDict);\n    resources.set(\"Font\", font);\n    appearanceStreamDict.set(\"Resources\", resources);\n    this.checkedAppearance = new StringStream(appearance);\n    this.checkedAppearance.dict = appearanceStreamDict;\n    this._streams.push(this.checkedAppearance);\n  }\n  _processCheckBox(params) {\n    const customAppearance = params.dict.get(\"AP\");\n    if (!(customAppearance instanceof Dict)) {\n      return;\n    }\n    const normalAppearance = customAppearance.get(\"N\");\n    if (!(normalAppearance instanceof Dict)) {\n      return;\n    }\n    const asValue = this._decodeFormValue(params.dict.get(\"AS\"));\n    if (typeof asValue === \"string\") {\n      this.data.fieldValue = asValue;\n    }\n    const yes = this.data.fieldValue !== null && this.data.fieldValue !== \"Off\" ? this.data.fieldValue : \"Yes\";\n    const exportValues = normalAppearance.getKeys();\n    if (exportValues.length === 0) {\n      exportValues.push(\"Off\", yes);\n    } else if (exportValues.length === 1) {\n      if (exportValues[0] === \"Off\") {\n        exportValues.push(yes);\n      } else {\n        exportValues.unshift(\"Off\");\n      }\n    } else if (exportValues.includes(yes)) {\n      exportValues.length = 0;\n      exportValues.push(\"Off\", yes);\n    } else {\n      const otherYes = exportValues.find(v => v !== \"Off\");\n      exportValues.length = 0;\n      exportValues.push(\"Off\", otherYes);\n    }\n    if (!exportValues.includes(this.data.fieldValue)) {\n      this.data.fieldValue = \"Off\";\n    }\n    this.data.exportValue = exportValues[1];\n    const checkedAppearance = normalAppearance.get(this.data.exportValue);\n    this.checkedAppearance = checkedAppearance instanceof BaseStream ? checkedAppearance : null;\n    const uncheckedAppearance = normalAppearance.get(\"Off\");\n    this.uncheckedAppearance = uncheckedAppearance instanceof BaseStream ? uncheckedAppearance : null;\n    if (this.checkedAppearance) {\n      this._streams.push(this.checkedAppearance);\n    } else {\n      this._getDefaultCheckedAppearance(params, \"check\");\n    }\n    if (this.uncheckedAppearance) {\n      this._streams.push(this.uncheckedAppearance);\n    }\n    this._fallbackFontDict = this.fallbackFontDict;\n    if (this.data.defaultFieldValue === null) {\n      this.data.defaultFieldValue = \"Off\";\n    }\n  }\n  _processRadioButton(params) {\n    this.data.buttonValue = null;\n    const fieldParent = params.dict.get(\"Parent\");\n    if (fieldParent instanceof Dict) {\n      this.parent = params.dict.getRaw(\"Parent\");\n      const fieldParentValue = fieldParent.get(\"V\");\n      if (fieldParentValue instanceof Name) {\n        this.data.fieldValue = this._decodeFormValue(fieldParentValue);\n      }\n    }\n    const appearanceStates = params.dict.get(\"AP\");\n    if (!(appearanceStates instanceof Dict)) {\n      return;\n    }\n    const normalAppearance = appearanceStates.get(\"N\");\n    if (!(normalAppearance instanceof Dict)) {\n      return;\n    }\n    for (const key of normalAppearance.getKeys()) {\n      if (key !== \"Off\") {\n        this.data.buttonValue = this._decodeFormValue(key);\n        break;\n      }\n    }\n    const checkedAppearance = normalAppearance.get(this.data.buttonValue);\n    this.checkedAppearance = checkedAppearance instanceof BaseStream ? checkedAppearance : null;\n    const uncheckedAppearance = normalAppearance.get(\"Off\");\n    this.uncheckedAppearance = uncheckedAppearance instanceof BaseStream ? uncheckedAppearance : null;\n    if (this.checkedAppearance) {\n      this._streams.push(this.checkedAppearance);\n    } else {\n      this._getDefaultCheckedAppearance(params, \"disc\");\n    }\n    if (this.uncheckedAppearance) {\n      this._streams.push(this.uncheckedAppearance);\n    }\n    this._fallbackFontDict = this.fallbackFontDict;\n    if (this.data.defaultFieldValue === null) {\n      this.data.defaultFieldValue = \"Off\";\n    }\n  }\n  _processPushButton(params) {\n    const {\n      dict,\n      annotationGlobals\n    } = params;\n    if (!dict.has(\"A\") && !dict.has(\"AA\") && !this.data.alternativeText) {\n      warn(\"Push buttons without action dictionaries are not supported\");\n      return;\n    }\n    this.data.isTooltipOnly = !dict.has(\"A\") && !dict.has(\"AA\");\n    Catalog.parseDestDictionary({\n      destDict: dict,\n      resultObj: this.data,\n      docBaseUrl: annotationGlobals.baseUrl,\n      docAttachments: annotationGlobals.attachments\n    });\n  }\n  getFieldObject() {\n    let type = \"button\";\n    let exportValues;\n    if (this.data.checkBox) {\n      type = \"checkbox\";\n      exportValues = this.data.exportValue;\n    } else if (this.data.radioButton) {\n      type = \"radiobutton\";\n      exportValues = this.data.buttonValue;\n    }\n    return {\n      id: this.data.id,\n      value: this.data.fieldValue || \"Off\",\n      defaultValue: this.data.defaultFieldValue,\n      exportValues,\n      editable: !this.data.readOnly,\n      name: this.data.fieldName,\n      rect: this.data.rect,\n      hidden: this.data.hidden,\n      actions: this.data.actions,\n      page: this.data.pageIndex,\n      strokeColor: this.data.borderColor,\n      fillColor: this.data.backgroundColor,\n      rotation: this.rotation,\n      type\n    };\n  }\n  get fallbackFontDict() {\n    const dict = new Dict();\n    dict.set(\"BaseFont\", Name.get(\"ZapfDingbats\"));\n    dict.set(\"Type\", Name.get(\"FallbackType\"));\n    dict.set(\"Subtype\", Name.get(\"FallbackType\"));\n    dict.set(\"Encoding\", Name.get(\"ZapfDingbatsEncoding\"));\n    return shadow(this, \"fallbackFontDict\", dict);\n  }\n}\nclass ChoiceWidgetAnnotation extends WidgetAnnotation {\n  constructor(params) {\n    super(params);\n    const {\n      dict,\n      xref\n    } = params;\n    this.indices = dict.getArray(\"I\");\n    this.hasIndices = Array.isArray(this.indices) && this.indices.length > 0;\n    this.data.options = [];\n    const options = getInheritableProperty({\n      dict,\n      key: \"Opt\"\n    });\n    if (Array.isArray(options)) {\n      for (let i = 0, ii = options.length; i < ii; i++) {\n        const option = xref.fetchIfRef(options[i]);\n        const isOptionArray = Array.isArray(option);\n        this.data.options[i] = {\n          exportValue: this._decodeFormValue(isOptionArray ? xref.fetchIfRef(option[0]) : option),\n          displayValue: this._decodeFormValue(isOptionArray ? xref.fetchIfRef(option[1]) : option)\n        };\n      }\n    }\n    if (!this.hasIndices) {\n      if (typeof this.data.fieldValue === \"string\") {\n        this.data.fieldValue = [this.data.fieldValue];\n      } else if (!this.data.fieldValue) {\n        this.data.fieldValue = [];\n      }\n    } else {\n      this.data.fieldValue = [];\n      const ii = this.data.options.length;\n      for (const i of this.indices) {\n        if (Number.isInteger(i) && i >= 0 && i < ii) {\n          this.data.fieldValue.push(this.data.options[i].exportValue);\n        }\n      }\n    }\n    this.data.combo = this.hasFieldFlag(AnnotationFieldFlag.COMBO);\n    this.data.multiSelect = this.hasFieldFlag(AnnotationFieldFlag.MULTISELECT);\n    this._hasText = true;\n  }\n  getFieldObject() {\n    const type = this.data.combo ? \"combobox\" : \"listbox\";\n    const value = this.data.fieldValue.length > 0 ? this.data.fieldValue[0] : null;\n    return {\n      id: this.data.id,\n      value,\n      defaultValue: this.data.defaultFieldValue,\n      editable: !this.data.readOnly,\n      name: this.data.fieldName,\n      rect: this.data.rect,\n      numItems: this.data.fieldValue.length,\n      multipleSelection: this.data.multiSelect,\n      hidden: this.data.hidden,\n      actions: this.data.actions,\n      items: this.data.options,\n      page: this.data.pageIndex,\n      strokeColor: this.data.borderColor,\n      fillColor: this.data.backgroundColor,\n      rotation: this.rotation,\n      type\n    };\n  }\n  amendSavedDict(annotationStorage, dict) {\n    if (!this.hasIndices) {\n      return;\n    }\n    let values = annotationStorage?.get(this.data.id)?.value;\n    if (!Array.isArray(values)) {\n      values = [values];\n    }\n    const indices = [];\n    const {\n      options\n    } = this.data;\n    for (let i = 0, j = 0, ii = options.length; i < ii; i++) {\n      if (options[i].exportValue === values[j]) {\n        indices.push(i);\n        j += 1;\n      }\n    }\n    dict.set(\"I\", indices);\n  }\n  async _getAppearance(evaluator, task, intent, annotationStorage) {\n    if (this.data.combo) {\n      return super._getAppearance(evaluator, task, intent, annotationStorage);\n    }\n    let exportedValue, rotation;\n    const storageEntry = annotationStorage?.get(this.data.id);\n    if (storageEntry) {\n      rotation = storageEntry.rotation;\n      exportedValue = storageEntry.value;\n    }\n    if (rotation === undefined && exportedValue === undefined && !this._needAppearances) {\n      return null;\n    }\n    if (exportedValue === undefined) {\n      exportedValue = this.data.fieldValue;\n    } else if (!Array.isArray(exportedValue)) {\n      exportedValue = [exportedValue];\n    }\n    const defaultPadding = 1;\n    const defaultHPadding = 2;\n    let totalHeight = this.data.rect[3] - this.data.rect[1];\n    let totalWidth = this.data.rect[2] - this.data.rect[0];\n    if (rotation === 90 || rotation === 270) {\n      [totalWidth, totalHeight] = [totalHeight, totalWidth];\n    }\n    const lineCount = this.data.options.length;\n    const valueIndices = [];\n    for (let i = 0; i < lineCount; i++) {\n      const {\n        exportValue\n      } = this.data.options[i];\n      if (exportedValue.includes(exportValue)) {\n        valueIndices.push(i);\n      }\n    }\n    if (!this._defaultAppearance) {\n      this.data.defaultAppearanceData = parseDefaultAppearance(this._defaultAppearance = \"/Helvetica 0 Tf 0 g\");\n    }\n    const font = await WidgetAnnotation._getFontData(evaluator, task, this.data.defaultAppearanceData, this._fieldResources.mergedResources);\n    let defaultAppearance;\n    let {\n      fontSize\n    } = this.data.defaultAppearanceData;\n    if (!fontSize) {\n      const lineHeight = (totalHeight - defaultPadding) / lineCount;\n      let lineWidth = -1;\n      let value;\n      for (const {\n        displayValue\n      } of this.data.options) {\n        const width = this._getTextWidth(displayValue, font);\n        if (width > lineWidth) {\n          lineWidth = width;\n          value = displayValue;\n        }\n      }\n      [defaultAppearance, fontSize] = this._computeFontSize(lineHeight, totalWidth - 2 * defaultHPadding, value, font, -1);\n    } else {\n      defaultAppearance = this._defaultAppearance;\n    }\n    const lineHeight = fontSize * LINE_FACTOR;\n    const vPadding = (lineHeight - fontSize) / 2;\n    const numberOfVisibleLines = Math.floor(totalHeight / lineHeight);\n    let firstIndex = 0;\n    if (valueIndices.length > 0) {\n      const minIndex = Math.min(...valueIndices);\n      const maxIndex = Math.max(...valueIndices);\n      firstIndex = Math.max(0, maxIndex - numberOfVisibleLines + 1);\n      if (firstIndex > minIndex) {\n        firstIndex = minIndex;\n      }\n    }\n    const end = Math.min(firstIndex + numberOfVisibleLines + 1, lineCount);\n    const buf = [\"/Tx BMC q\", `1 1 ${totalWidth} ${totalHeight} re W n`];\n    if (valueIndices.length) {\n      buf.push(\"0.600006 0.756866 0.854904 rg\");\n      for (const index of valueIndices) {\n        if (firstIndex <= index && index < end) {\n          buf.push(`1 ${totalHeight - (index - firstIndex + 1) * lineHeight} ${totalWidth} ${lineHeight} re f`);\n        }\n      }\n    }\n    buf.push(\"BT\", defaultAppearance, `1 0 0 1 0 ${totalHeight} Tm`);\n    const prevInfo = {\n      shift: 0\n    };\n    for (let i = firstIndex; i < end; i++) {\n      const {\n        displayValue\n      } = this.data.options[i];\n      const vpadding = i === firstIndex ? vPadding : 0;\n      buf.push(this._renderText(displayValue, font, fontSize, totalWidth, 0, prevInfo, defaultHPadding, -lineHeight + vpadding));\n    }\n    buf.push(\"ET Q EMC\");\n    return buf.join(\"\\n\");\n  }\n}\nclass SignatureWidgetAnnotation extends WidgetAnnotation {\n  constructor(params) {\n    super(params);\n    this.data.fieldValue = null;\n    this.data.hasOwnCanvas = this.data.noRotate;\n    this.data.noHTML = !this.data.hasOwnCanvas;\n  }\n  getFieldObject() {\n    return {\n      id: this.data.id,\n      value: null,\n      page: this.data.pageIndex,\n      type: \"signature\"\n    };\n  }\n}\nclass TextAnnotation extends MarkupAnnotation {\n  constructor(params) {\n    const DEFAULT_ICON_SIZE = 22;\n    super(params);\n    this.data.noRotate = true;\n    this.data.hasOwnCanvas = this.data.noRotate;\n    this.data.noHTML = false;\n    const {\n      dict\n    } = params;\n    this.data.annotationType = AnnotationType.TEXT;\n    if (this.data.hasAppearance) {\n      this.data.name = \"NoIcon\";\n    } else {\n      this.data.rect[1] = this.data.rect[3] - DEFAULT_ICON_SIZE;\n      this.data.rect[2] = this.data.rect[0] + DEFAULT_ICON_SIZE;\n      this.data.name = dict.has(\"Name\") ? dict.get(\"Name\").name : \"Note\";\n    }\n    if (dict.has(\"State\")) {\n      this.data.state = dict.get(\"State\") || null;\n      this.data.stateModel = dict.get(\"StateModel\") || null;\n    } else {\n      this.data.state = null;\n      this.data.stateModel = null;\n    }\n  }\n}\nclass LinkAnnotation extends Annotation {\n  constructor(params) {\n    super(params);\n    const {\n      dict,\n      annotationGlobals\n    } = params;\n    this.data.annotationType = AnnotationType.LINK;\n    this.data.noHTML = false;\n    const quadPoints = getQuadPoints(dict, this.rectangle);\n    if (quadPoints) {\n      this.data.quadPoints = quadPoints;\n    }\n    this.data.borderColor ||= this.data.color;\n    Catalog.parseDestDictionary({\n      destDict: dict,\n      resultObj: this.data,\n      docBaseUrl: annotationGlobals.baseUrl,\n      docAttachments: annotationGlobals.attachments\n    });\n  }\n}\nclass PopupAnnotation extends Annotation {\n  constructor(params) {\n    super(params);\n    const {\n      dict\n    } = params;\n    this.data.annotationType = AnnotationType.POPUP;\n    this.data.noHTML = false;\n    if (this.data.rect[0] === this.data.rect[2] || this.data.rect[1] === this.data.rect[3]) {\n      this.data.rect = null;\n    }\n    let parentItem = dict.get(\"Parent\");\n    if (!parentItem) {\n      warn(\"Popup annotation has a missing or invalid parent annotation.\");\n      return;\n    }\n    const parentRect = parentItem.getArray(\"Rect\");\n    this.data.parentRect = Array.isArray(parentRect) && parentRect.length === 4 ? Util.normalizeRect(parentRect) : null;\n    const rt = parentItem.get(\"RT\");\n    if (isName(rt, AnnotationReplyType.GROUP)) {\n      parentItem = parentItem.get(\"IRT\");\n    }\n    if (!parentItem.has(\"M\")) {\n      this.data.modificationDate = null;\n    } else {\n      this.setModificationDate(parentItem.get(\"M\"));\n      this.data.modificationDate = this.modificationDate;\n    }\n    if (!parentItem.has(\"C\")) {\n      this.data.color = null;\n    } else {\n      this.setColor(parentItem.getArray(\"C\"));\n      this.data.color = this.color;\n    }\n    if (!this.viewable) {\n      const parentFlags = parentItem.get(\"F\");\n      if (this._isViewable(parentFlags)) {\n        this.setFlags(parentFlags);\n      }\n    }\n    this.setTitle(parentItem.get(\"T\"));\n    this.data.titleObj = this._title;\n    this.setContents(parentItem.get(\"Contents\"));\n    this.data.contentsObj = this._contents;\n    if (parentItem.has(\"RC\")) {\n      this.data.richText = XFAFactory.getRichTextAsHtml(parentItem.get(\"RC\"));\n    }\n    this.data.open = !!dict.get(\"Open\");\n  }\n}\nclass FreeTextAnnotation extends MarkupAnnotation {\n  constructor(params) {\n    super(params);\n    this.data.hasOwnCanvas = !this.data.noHTML;\n    this.data.noHTML = false;\n    const {\n      evaluatorOptions,\n      xref\n    } = params;\n    this.data.annotationType = AnnotationType.FREETEXT;\n    this.setDefaultAppearance(params);\n    this._hasAppearance = !!this.appearance;\n    if (this._hasAppearance) {\n      const {\n        fontColor,\n        fontSize\n      } = parseAppearanceStream(this.appearance, evaluatorOptions, xref);\n      this.data.defaultAppearanceData.fontColor = fontColor;\n      this.data.defaultAppearanceData.fontSize = fontSize || 10;\n    } else {\n      this.data.defaultAppearanceData.fontSize ||= 10;\n      const {\n        fontColor,\n        fontSize\n      } = this.data.defaultAppearanceData;\n      if (this._contents.str) {\n        this.data.textContent = this._contents.str.split(/\\r\\n?|\\n/).map(line => line.trimEnd());\n        const {\n          coords,\n          bbox,\n          matrix\n        } = FakeUnicodeFont.getFirstPositionInfo(this.rectangle, this.rotation, fontSize);\n        this.data.textPosition = this._transformPoint(coords, bbox, matrix);\n      }\n      if (this._isOffscreenCanvasSupported) {\n        const strokeAlpha = params.dict.get(\"CA\");\n        const fakeUnicodeFont = new FakeUnicodeFont(xref, \"sans-serif\");\n        this.appearance = fakeUnicodeFont.createAppearance(this._contents.str, this.rectangle, this.rotation, fontSize, fontColor, strokeAlpha);\n        this._streams.push(this.appearance);\n      } else {\n        warn(\"FreeTextAnnotation: OffscreenCanvas is not supported, annotation may not render correctly.\");\n      }\n    }\n  }\n  get hasTextContent() {\n    return this._hasAppearance;\n  }\n  static createNewDict(annotation, xref, {\n    apRef,\n    ap\n  }) {\n    const {\n      color,\n      fontSize,\n      rect,\n      rotation,\n      user,\n      value\n    } = annotation;\n    const freetext = new Dict(xref);\n    freetext.set(\"Type\", Name.get(\"Annot\"));\n    freetext.set(\"Subtype\", Name.get(\"FreeText\"));\n    freetext.set(\"CreationDate\", `D:${getModificationDate()}`);\n    freetext.set(\"Rect\", rect);\n    const da = `/Helv ${fontSize} Tf ${getPdfColor(color, true)}`;\n    freetext.set(\"DA\", da);\n    freetext.set(\"Contents\", isAscii(value) ? value : stringToUTF16String(value, true));\n    freetext.set(\"F\", 4);\n    freetext.set(\"Border\", [0, 0, 0]);\n    freetext.set(\"Rotate\", rotation);\n    if (user) {\n      freetext.set(\"T\", isAscii(user) ? user : stringToUTF16String(user, true));\n    }\n    if (apRef || ap) {\n      const n = new Dict(xref);\n      freetext.set(\"AP\", n);\n      if (apRef) {\n        n.set(\"N\", apRef);\n      } else {\n        n.set(\"N\", ap);\n      }\n    }\n    return freetext;\n  }\n  static async createNewAppearanceStream(annotation, xref, params) {\n    const {\n      baseFontRef,\n      evaluator,\n      task\n    } = params;\n    const {\n      color,\n      fontSize,\n      rect,\n      rotation,\n      value\n    } = annotation;\n    const resources = new Dict(xref);\n    const font = new Dict(xref);\n    if (baseFontRef) {\n      font.set(\"Helv\", baseFontRef);\n    } else {\n      const baseFont = new Dict(xref);\n      baseFont.set(\"BaseFont\", Name.get(\"Helvetica\"));\n      baseFont.set(\"Type\", Name.get(\"Font\"));\n      baseFont.set(\"Subtype\", Name.get(\"Type1\"));\n      baseFont.set(\"Encoding\", Name.get(\"WinAnsiEncoding\"));\n      font.set(\"Helv\", baseFont);\n    }\n    resources.set(\"Font\", font);\n    const helv = await WidgetAnnotation._getFontData(evaluator, task, {\n      fontName: \"Helv\",\n      fontSize\n    }, resources);\n    const [x1, y1, x2, y2] = rect;\n    let w = x2 - x1;\n    let h = y2 - y1;\n    if (rotation % 180 !== 0) {\n      [w, h] = [h, w];\n    }\n    const lines = value.split(\"\\n\");\n    const scale = fontSize / 1000;\n    let totalWidth = -Infinity;\n    const encodedLines = [];\n    for (let line of lines) {\n      const encoded = helv.encodeString(line);\n      if (encoded.length > 1) {\n        return null;\n      }\n      line = encoded.join(\"\");\n      encodedLines.push(line);\n      let lineWidth = 0;\n      const glyphs = helv.charsToGlyphs(line);\n      for (const glyph of glyphs) {\n        lineWidth += glyph.width * scale;\n      }\n      totalWidth = Math.max(totalWidth, lineWidth);\n    }\n    let hscale = 1;\n    if (totalWidth > w) {\n      hscale = w / totalWidth;\n    }\n    let vscale = 1;\n    const lineHeight = LINE_FACTOR * fontSize;\n    const lineAscent = (LINE_FACTOR - LINE_DESCENT_FACTOR) * fontSize;\n    const totalHeight = lineHeight * lines.length;\n    if (totalHeight > h) {\n      vscale = h / totalHeight;\n    }\n    const fscale = Math.min(hscale, vscale);\n    const newFontSize = fontSize * fscale;\n    let firstPoint, clipBox, matrix;\n    switch (rotation) {\n      case 0:\n        matrix = [1, 0, 0, 1];\n        clipBox = [rect[0], rect[1], w, h];\n        firstPoint = [rect[0], rect[3] - lineAscent];\n        break;\n      case 90:\n        matrix = [0, 1, -1, 0];\n        clipBox = [rect[1], -rect[2], w, h];\n        firstPoint = [rect[1], -rect[0] - lineAscent];\n        break;\n      case 180:\n        matrix = [-1, 0, 0, -1];\n        clipBox = [-rect[2], -rect[3], w, h];\n        firstPoint = [-rect[2], -rect[1] - lineAscent];\n        break;\n      case 270:\n        matrix = [0, -1, 1, 0];\n        clipBox = [-rect[3], rect[0], w, h];\n        firstPoint = [-rect[3], rect[2] - lineAscent];\n        break;\n    }\n    const buffer = [\"q\", `${matrix.join(\" \")} 0 0 cm`, `${clipBox.join(\" \")} re W n`, `BT`, `${getPdfColor(color, true)}`, `0 Tc /Helv ${numberToString(newFontSize)} Tf`];\n    buffer.push(`${firstPoint.join(\" \")} Td (${escapeString(encodedLines[0])}) Tj`);\n    const vShift = numberToString(lineHeight);\n    for (let i = 1, ii = encodedLines.length; i < ii; i++) {\n      const line = encodedLines[i];\n      buffer.push(`0 -${vShift} Td (${escapeString(line)}) Tj`);\n    }\n    buffer.push(\"ET\", \"Q\");\n    const appearance = buffer.join(\"\\n\");\n    const appearanceStreamDict = new Dict(xref);\n    appearanceStreamDict.set(\"FormType\", 1);\n    appearanceStreamDict.set(\"Subtype\", Name.get(\"Form\"));\n    appearanceStreamDict.set(\"Type\", Name.get(\"XObject\"));\n    appearanceStreamDict.set(\"BBox\", rect);\n    appearanceStreamDict.set(\"Resources\", resources);\n    appearanceStreamDict.set(\"Matrix\", [1, 0, 0, 1, -rect[0], -rect[1]]);\n    const ap = new StringStream(appearance);\n    ap.dict = appearanceStreamDict;\n    return ap;\n  }\n}\nclass LineAnnotation extends MarkupAnnotation {\n  constructor(params) {\n    super(params);\n    const {\n      dict,\n      xref\n    } = params;\n    this.data.annotationType = AnnotationType.LINE;\n    this.data.hasOwnCanvas = this.data.noRotate;\n    this.data.noHTML = false;\n    const lineCoordinates = dict.getArray(\"L\");\n    this.data.lineCoordinates = Util.normalizeRect(lineCoordinates);\n    this.setLineEndings(dict.getArray(\"LE\"));\n    this.data.lineEndings = this.lineEndings;\n    if (!this.appearance) {\n      const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0];\n      const strokeAlpha = dict.get(\"CA\");\n      const interiorColor = getRgbColor(dict.getArray(\"IC\"), null);\n      const fillColor = interiorColor ? getPdfColorArray(interiorColor) : null;\n      const fillAlpha = fillColor ? strokeAlpha : null;\n      const borderWidth = this.borderStyle.width || 1,\n        borderAdjust = 2 * borderWidth;\n      const bbox = [this.data.lineCoordinates[0] - borderAdjust, this.data.lineCoordinates[1] - borderAdjust, this.data.lineCoordinates[2] + borderAdjust, this.data.lineCoordinates[3] + borderAdjust];\n      if (!Util.intersect(this.rectangle, bbox)) {\n        this.rectangle = bbox;\n      }\n      this._setDefaultAppearance({\n        xref,\n        extra: `${borderWidth} w`,\n        strokeColor,\n        fillColor,\n        strokeAlpha,\n        fillAlpha,\n        pointsCallback: (buffer, points) => {\n          buffer.push(`${lineCoordinates[0]} ${lineCoordinates[1]} m`, `${lineCoordinates[2]} ${lineCoordinates[3]} l`, \"S\");\n          return [points[0].x - borderWidth, points[1].x + borderWidth, points[3].y - borderWidth, points[1].y + borderWidth];\n        }\n      });\n    }\n  }\n}\nclass SquareAnnotation extends MarkupAnnotation {\n  constructor(params) {\n    super(params);\n    const {\n      dict,\n      xref\n    } = params;\n    this.data.annotationType = AnnotationType.SQUARE;\n    this.data.hasOwnCanvas = this.data.noRotate;\n    this.data.noHTML = false;\n    if (!this.appearance) {\n      const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0];\n      const strokeAlpha = dict.get(\"CA\");\n      const interiorColor = getRgbColor(dict.getArray(\"IC\"), null);\n      const fillColor = interiorColor ? getPdfColorArray(interiorColor) : null;\n      const fillAlpha = fillColor ? strokeAlpha : null;\n      if (this.borderStyle.width === 0 && !fillColor) {\n        return;\n      }\n      this._setDefaultAppearance({\n        xref,\n        extra: `${this.borderStyle.width} w`,\n        strokeColor,\n        fillColor,\n        strokeAlpha,\n        fillAlpha,\n        pointsCallback: (buffer, points) => {\n          const x = points[2].x + this.borderStyle.width / 2;\n          const y = points[2].y + this.borderStyle.width / 2;\n          const width = points[3].x - points[2].x - this.borderStyle.width;\n          const height = points[1].y - points[3].y - this.borderStyle.width;\n          buffer.push(`${x} ${y} ${width} ${height} re`);\n          if (fillColor) {\n            buffer.push(\"B\");\n          } else {\n            buffer.push(\"S\");\n          }\n          return [points[0].x, points[1].x, points[3].y, points[1].y];\n        }\n      });\n    }\n  }\n}\nclass CircleAnnotation extends MarkupAnnotation {\n  constructor(params) {\n    super(params);\n    const {\n      dict,\n      xref\n    } = params;\n    this.data.annotationType = AnnotationType.CIRCLE;\n    if (!this.appearance) {\n      const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0];\n      const strokeAlpha = dict.get(\"CA\");\n      const interiorColor = getRgbColor(dict.getArray(\"IC\"), null);\n      const fillColor = interiorColor ? getPdfColorArray(interiorColor) : null;\n      const fillAlpha = fillColor ? strokeAlpha : null;\n      if (this.borderStyle.width === 0 && !fillColor) {\n        return;\n      }\n      const controlPointsDistance = 4 / 3 * Math.tan(Math.PI / (2 * 4));\n      this._setDefaultAppearance({\n        xref,\n        extra: `${this.borderStyle.width} w`,\n        strokeColor,\n        fillColor,\n        strokeAlpha,\n        fillAlpha,\n        pointsCallback: (buffer, points) => {\n          const x0 = points[0].x + this.borderStyle.width / 2;\n          const y0 = points[0].y - this.borderStyle.width / 2;\n          const x1 = points[3].x - this.borderStyle.width / 2;\n          const y1 = points[3].y + this.borderStyle.width / 2;\n          const xMid = x0 + (x1 - x0) / 2;\n          const yMid = y0 + (y1 - y0) / 2;\n          const xOffset = (x1 - x0) / 2 * controlPointsDistance;\n          const yOffset = (y1 - y0) / 2 * controlPointsDistance;\n          buffer.push(`${xMid} ${y1} m`, `${xMid + xOffset} ${y1} ${x1} ${yMid + yOffset} ${x1} ${yMid} c`, `${x1} ${yMid - yOffset} ${xMid + xOffset} ${y0} ${xMid} ${y0} c`, `${xMid - xOffset} ${y0} ${x0} ${yMid - yOffset} ${x0} ${yMid} c`, `${x0} ${yMid + yOffset} ${xMid - xOffset} ${y1} ${xMid} ${y1} c`, \"h\");\n          if (fillColor) {\n            buffer.push(\"B\");\n          } else {\n            buffer.push(\"S\");\n          }\n          return [points[0].x, points[1].x, points[3].y, points[1].y];\n        }\n      });\n    }\n  }\n}\nclass PolylineAnnotation extends MarkupAnnotation {\n  constructor(params) {\n    super(params);\n    const {\n      dict,\n      xref\n    } = params;\n    this.data.annotationType = AnnotationType.POLYLINE;\n    this.data.hasOwnCanvas = this.data.noRotate;\n    this.data.noHTML = false;\n    this.data.vertices = [];\n    if (!(this instanceof PolygonAnnotation)) {\n      this.setLineEndings(dict.getArray(\"LE\"));\n      this.data.lineEndings = this.lineEndings;\n    }\n    const rawVertices = dict.getArray(\"Vertices\");\n    if (!Array.isArray(rawVertices)) {\n      return;\n    }\n    for (let i = 0, ii = rawVertices.length; i < ii; i += 2) {\n      this.data.vertices.push({\n        x: rawVertices[i],\n        y: rawVertices[i + 1]\n      });\n    }\n    if (!this.appearance) {\n      const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0];\n      const strokeAlpha = dict.get(\"CA\");\n      const borderWidth = this.borderStyle.width || 1,\n        borderAdjust = 2 * borderWidth;\n      const bbox = [Infinity, Infinity, -Infinity, -Infinity];\n      for (const vertex of this.data.vertices) {\n        bbox[0] = Math.min(bbox[0], vertex.x - borderAdjust);\n        bbox[1] = Math.min(bbox[1], vertex.y - borderAdjust);\n        bbox[2] = Math.max(bbox[2], vertex.x + borderAdjust);\n        bbox[3] = Math.max(bbox[3], vertex.y + borderAdjust);\n      }\n      if (!Util.intersect(this.rectangle, bbox)) {\n        this.rectangle = bbox;\n      }\n      this._setDefaultAppearance({\n        xref,\n        extra: `${borderWidth} w`,\n        strokeColor,\n        strokeAlpha,\n        pointsCallback: (buffer, points) => {\n          const vertices = this.data.vertices;\n          for (let i = 0, ii = vertices.length; i < ii; i++) {\n            buffer.push(`${vertices[i].x} ${vertices[i].y} ${i === 0 ? \"m\" : \"l\"}`);\n          }\n          buffer.push(\"S\");\n          return [points[0].x, points[1].x, points[3].y, points[1].y];\n        }\n      });\n    }\n  }\n}\nclass PolygonAnnotation extends PolylineAnnotation {\n  constructor(params) {\n    super(params);\n    this.data.annotationType = AnnotationType.POLYGON;\n  }\n}\nclass CaretAnnotation extends MarkupAnnotation {\n  constructor(params) {\n    super(params);\n    this.data.annotationType = AnnotationType.CARET;\n  }\n}\nclass InkAnnotation extends MarkupAnnotation {\n  constructor(params) {\n    super(params);\n    this.data.hasOwnCanvas = this.data.noRotate;\n    this.data.noHTML = false;\n    const {\n      dict,\n      xref\n    } = params;\n    this.data.annotationType = AnnotationType.INK;\n    this.data.inkLists = [];\n    const rawInkLists = dict.getArray(\"InkList\");\n    if (!Array.isArray(rawInkLists)) {\n      return;\n    }\n    for (let i = 0, ii = rawInkLists.length; i < ii; ++i) {\n      this.data.inkLists.push([]);\n      for (let j = 0, jj = rawInkLists[i].length; j < jj; j += 2) {\n        this.data.inkLists[i].push({\n          x: xref.fetchIfRef(rawInkLists[i][j]),\n          y: xref.fetchIfRef(rawInkLists[i][j + 1])\n        });\n      }\n    }\n    if (!this.appearance) {\n      const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0];\n      const strokeAlpha = dict.get(\"CA\");\n      const borderWidth = this.borderStyle.width || 1,\n        borderAdjust = 2 * borderWidth;\n      const bbox = [Infinity, Infinity, -Infinity, -Infinity];\n      for (const inkLists of this.data.inkLists) {\n        for (const vertex of inkLists) {\n          bbox[0] = Math.min(bbox[0], vertex.x - borderAdjust);\n          bbox[1] = Math.min(bbox[1], vertex.y - borderAdjust);\n          bbox[2] = Math.max(bbox[2], vertex.x + borderAdjust);\n          bbox[3] = Math.max(bbox[3], vertex.y + borderAdjust);\n        }\n      }\n      if (!Util.intersect(this.rectangle, bbox)) {\n        this.rectangle = bbox;\n      }\n      this._setDefaultAppearance({\n        xref,\n        extra: `${borderWidth} w`,\n        strokeColor,\n        strokeAlpha,\n        pointsCallback: (buffer, points) => {\n          for (const inkList of this.data.inkLists) {\n            for (let i = 0, ii = inkList.length; i < ii; i++) {\n              buffer.push(`${inkList[i].x} ${inkList[i].y} ${i === 0 ? \"m\" : \"l\"}`);\n            }\n            buffer.push(\"S\");\n          }\n          return [points[0].x, points[1].x, points[3].y, points[1].y];\n        }\n      });\n    }\n  }\n  static createNewDict(annotation, xref, {\n    apRef,\n    ap\n  }) {\n    const {\n      color,\n      opacity,\n      paths,\n      outlines,\n      rect,\n      rotation,\n      thickness\n    } = annotation;\n    const ink = new Dict(xref);\n    ink.set(\"Type\", Name.get(\"Annot\"));\n    ink.set(\"Subtype\", Name.get(\"Ink\"));\n    ink.set(\"CreationDate\", `D:${getModificationDate()}`);\n    ink.set(\"Rect\", rect);\n    ink.set(\"InkList\", outlines?.points || paths.map(p => p.points));\n    ink.set(\"F\", 4);\n    ink.set(\"Rotate\", rotation);\n    if (outlines) {\n      ink.set(\"IT\", Name.get(\"InkHighlight\"));\n    }\n    const bs = new Dict(xref);\n    ink.set(\"BS\", bs);\n    bs.set(\"W\", thickness);\n    ink.set(\"C\", Array.from(color, c => c / 255));\n    ink.set(\"CA\", opacity);\n    const n = new Dict(xref);\n    ink.set(\"AP\", n);\n    if (apRef) {\n      n.set(\"N\", apRef);\n    } else {\n      n.set(\"N\", ap);\n    }\n    return ink;\n  }\n  static async createNewAppearanceStream(annotation, xref, params) {\n    if (annotation.outlines) {\n      return this.createNewAppearanceStreamForHighlight(annotation, xref, params);\n    }\n    const {\n      color,\n      rect,\n      paths,\n      thickness,\n      opacity\n    } = annotation;\n    const appearanceBuffer = [`${thickness} w 1 J 1 j`, `${getPdfColor(color, false)}`];\n    if (opacity !== 1) {\n      appearanceBuffer.push(\"/R0 gs\");\n    }\n    const buffer = [];\n    for (const {\n      bezier\n    } of paths) {\n      buffer.length = 0;\n      buffer.push(`${numberToString(bezier[0])} ${numberToString(bezier[1])} m`);\n      if (bezier.length === 2) {\n        buffer.push(`${numberToString(bezier[0])} ${numberToString(bezier[1])} l S`);\n      } else {\n        for (let i = 2, ii = bezier.length; i < ii; i += 6) {\n          const curve = bezier.slice(i, i + 6).map(numberToString).join(\" \");\n          buffer.push(`${curve} c`);\n        }\n        buffer.push(\"S\");\n      }\n      appearanceBuffer.push(buffer.join(\"\\n\"));\n    }\n    const appearance = appearanceBuffer.join(\"\\n\");\n    const appearanceStreamDict = new Dict(xref);\n    appearanceStreamDict.set(\"FormType\", 1);\n    appearanceStreamDict.set(\"Subtype\", Name.get(\"Form\"));\n    appearanceStreamDict.set(\"Type\", Name.get(\"XObject\"));\n    appearanceStreamDict.set(\"BBox\", rect);\n    appearanceStreamDict.set(\"Length\", appearance.length);\n    if (opacity !== 1) {\n      const resources = new Dict(xref);\n      const extGState = new Dict(xref);\n      const r0 = new Dict(xref);\n      r0.set(\"CA\", opacity);\n      r0.set(\"Type\", Name.get(\"ExtGState\"));\n      extGState.set(\"R0\", r0);\n      resources.set(\"ExtGState\", extGState);\n      appearanceStreamDict.set(\"Resources\", resources);\n    }\n    const ap = new StringStream(appearance);\n    ap.dict = appearanceStreamDict;\n    return ap;\n  }\n  static async createNewAppearanceStreamForHighlight(annotation, xref, params) {\n    const {\n      color,\n      rect,\n      outlines: {\n        outline\n      },\n      opacity\n    } = annotation;\n    const appearanceBuffer = [`${getPdfColor(color, true)}`, \"/R0 gs\"];\n    appearanceBuffer.push(`${numberToString(outline[4])} ${numberToString(outline[5])} m`);\n    for (let i = 6, ii = outline.length; i < ii; i += 6) {\n      if (isNaN(outline[i]) || outline[i] === null) {\n        appearanceBuffer.push(`${numberToString(outline[i + 4])} ${numberToString(outline[i + 5])} l`);\n      } else {\n        const curve = outline.slice(i, i + 6).map(numberToString).join(\" \");\n        appearanceBuffer.push(`${curve} c`);\n      }\n    }\n    appearanceBuffer.push(\"h f\");\n    const appearance = appearanceBuffer.join(\"\\n\");\n    const appearanceStreamDict = new Dict(xref);\n    appearanceStreamDict.set(\"FormType\", 1);\n    appearanceStreamDict.set(\"Subtype\", Name.get(\"Form\"));\n    appearanceStreamDict.set(\"Type\", Name.get(\"XObject\"));\n    appearanceStreamDict.set(\"BBox\", rect);\n    appearanceStreamDict.set(\"Length\", appearance.length);\n    const resources = new Dict(xref);\n    const extGState = new Dict(xref);\n    resources.set(\"ExtGState\", extGState);\n    appearanceStreamDict.set(\"Resources\", resources);\n    const r0 = new Dict(xref);\n    extGState.set(\"R0\", r0);\n    r0.set(\"BM\", Name.get(\"Multiply\"));\n    if (opacity !== 1) {\n      r0.set(\"ca\", opacity);\n      r0.set(\"Type\", Name.get(\"ExtGState\"));\n    }\n    const ap = new StringStream(appearance);\n    ap.dict = appearanceStreamDict;\n    return ap;\n  }\n}\nclass HighlightAnnotation extends MarkupAnnotation {\n  constructor(params) {\n    super(params);\n    const {\n      dict,\n      xref\n    } = params;\n    this.data.annotationType = AnnotationType.HIGHLIGHT;\n    const quadPoints = this.data.quadPoints = getQuadPoints(dict, null);\n    if (quadPoints) {\n      const resources = this.appearance?.dict.get(\"Resources\");\n      if (!this.appearance || !resources?.has(\"ExtGState\")) {\n        if (this.appearance) {\n          warn(\"HighlightAnnotation - ignoring built-in appearance stream.\");\n        }\n        const fillColor = this.color ? getPdfColorArray(this.color) : [1, 1, 0];\n        const fillAlpha = dict.get(\"CA\");\n        this._setDefaultAppearance({\n          xref,\n          fillColor,\n          blendMode: \"Multiply\",\n          fillAlpha,\n          pointsCallback: (buffer, points) => {\n            buffer.push(`${points[0].x} ${points[0].y} m`, `${points[1].x} ${points[1].y} l`, `${points[3].x} ${points[3].y} l`, `${points[2].x} ${points[2].y} l`, \"f\");\n            return [points[0].x, points[1].x, points[3].y, points[1].y];\n          }\n        });\n      }\n    } else {\n      this.data.popupRef = null;\n    }\n  }\n  static createNewDict(annotation, xref, {\n    apRef,\n    ap\n  }) {\n    const {\n      color,\n      opacity,\n      rect,\n      rotation,\n      user,\n      quadPoints\n    } = annotation;\n    const highlight = new Dict(xref);\n    highlight.set(\"Type\", Name.get(\"Annot\"));\n    highlight.set(\"Subtype\", Name.get(\"Highlight\"));\n    highlight.set(\"CreationDate\", `D:${getModificationDate()}`);\n    highlight.set(\"Rect\", rect);\n    highlight.set(\"F\", 4);\n    highlight.set(\"Border\", [0, 0, 0]);\n    highlight.set(\"Rotate\", rotation);\n    highlight.set(\"QuadPoints\", quadPoints);\n    highlight.set(\"C\", Array.from(color, c => c / 255));\n    highlight.set(\"CA\", opacity);\n    if (user) {\n      highlight.set(\"T\", isAscii(user) ? user : stringToUTF16String(user, true));\n    }\n    if (apRef || ap) {\n      const n = new Dict(xref);\n      highlight.set(\"AP\", n);\n      n.set(\"N\", apRef || ap);\n    }\n    return highlight;\n  }\n  static async createNewAppearanceStream(annotation, xref, params) {\n    const {\n      color,\n      rect,\n      outlines,\n      opacity\n    } = annotation;\n    const appearanceBuffer = [`${getPdfColor(color, true)}`, \"/R0 gs\"];\n    const buffer = [];\n    for (const outline of outlines) {\n      buffer.length = 0;\n      buffer.push(`${numberToString(outline[0])} ${numberToString(outline[1])} m`);\n      for (let i = 2, ii = outline.length; i < ii; i += 2) {\n        buffer.push(`${numberToString(outline[i])} ${numberToString(outline[i + 1])} l`);\n      }\n      buffer.push(\"h\");\n      appearanceBuffer.push(buffer.join(\"\\n\"));\n    }\n    appearanceBuffer.push(\"f*\");\n    const appearance = appearanceBuffer.join(\"\\n\");\n    const appearanceStreamDict = new Dict(xref);\n    appearanceStreamDict.set(\"FormType\", 1);\n    appearanceStreamDict.set(\"Subtype\", Name.get(\"Form\"));\n    appearanceStreamDict.set(\"Type\", Name.get(\"XObject\"));\n    appearanceStreamDict.set(\"BBox\", rect);\n    appearanceStreamDict.set(\"Length\", appearance.length);\n    const resources = new Dict(xref);\n    const extGState = new Dict(xref);\n    resources.set(\"ExtGState\", extGState);\n    appearanceStreamDict.set(\"Resources\", resources);\n    const r0 = new Dict(xref);\n    extGState.set(\"R0\", r0);\n    r0.set(\"BM\", Name.get(\"Multiply\"));\n    if (opacity !== 1) {\n      r0.set(\"ca\", opacity);\n      r0.set(\"Type\", Name.get(\"ExtGState\"));\n    }\n    const ap = new StringStream(appearance);\n    ap.dict = appearanceStreamDict;\n    return ap;\n  }\n}\nclass UnderlineAnnotation extends MarkupAnnotation {\n  constructor(params) {\n    super(params);\n    const {\n      dict,\n      xref\n    } = params;\n    this.data.annotationType = AnnotationType.UNDERLINE;\n    const quadPoints = this.data.quadPoints = getQuadPoints(dict, null);\n    if (quadPoints) {\n      if (!this.appearance) {\n        const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0];\n        const strokeAlpha = dict.get(\"CA\");\n        this._setDefaultAppearance({\n          xref,\n          extra: \"[] 0 d 0.571 w\",\n          strokeColor,\n          strokeAlpha,\n          pointsCallback: (buffer, points) => {\n            buffer.push(`${points[2].x} ${points[2].y + 1.3} m`, `${points[3].x} ${points[3].y + 1.3} l`, \"S\");\n            return [points[0].x, points[1].x, points[3].y, points[1].y];\n          }\n        });\n      }\n    } else {\n      this.data.popupRef = null;\n    }\n  }\n}\nclass SquigglyAnnotation extends MarkupAnnotation {\n  constructor(params) {\n    super(params);\n    const {\n      dict,\n      xref\n    } = params;\n    this.data.annotationType = AnnotationType.SQUIGGLY;\n    const quadPoints = this.data.quadPoints = getQuadPoints(dict, null);\n    if (quadPoints) {\n      if (!this.appearance) {\n        const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0];\n        const strokeAlpha = dict.get(\"CA\");\n        this._setDefaultAppearance({\n          xref,\n          extra: \"[] 0 d 1 w\",\n          strokeColor,\n          strokeAlpha,\n          pointsCallback: (buffer, points) => {\n            const dy = (points[0].y - points[2].y) / 6;\n            let shift = dy;\n            let x = points[2].x;\n            const y = points[2].y;\n            const xEnd = points[3].x;\n            buffer.push(`${x} ${y + shift} m`);\n            do {\n              x += 2;\n              shift = shift === 0 ? dy : 0;\n              buffer.push(`${x} ${y + shift} l`);\n            } while (x < xEnd);\n            buffer.push(\"S\");\n            return [points[2].x, xEnd, y - 2 * dy, y + 2 * dy];\n          }\n        });\n      }\n    } else {\n      this.data.popupRef = null;\n    }\n  }\n}\nclass StrikeOutAnnotation extends MarkupAnnotation {\n  constructor(params) {\n    super(params);\n    const {\n      dict,\n      xref\n    } = params;\n    this.data.annotationType = AnnotationType.STRIKEOUT;\n    const quadPoints = this.data.quadPoints = getQuadPoints(dict, null);\n    if (quadPoints) {\n      if (!this.appearance) {\n        const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0];\n        const strokeAlpha = dict.get(\"CA\");\n        this._setDefaultAppearance({\n          xref,\n          extra: \"[] 0 d 1 w\",\n          strokeColor,\n          strokeAlpha,\n          pointsCallback: (buffer, points) => {\n            buffer.push(`${(points[0].x + points[2].x) / 2} ` + `${(points[0].y + points[2].y) / 2} m`, `${(points[1].x + points[3].x) / 2} ` + `${(points[1].y + points[3].y) / 2} l`, \"S\");\n            return [points[0].x, points[1].x, points[3].y, points[1].y];\n          }\n        });\n      }\n    } else {\n      this.data.popupRef = null;\n    }\n  }\n}\nclass StampAnnotation extends MarkupAnnotation {\n  constructor(params) {\n    super(params);\n    this.data.annotationType = AnnotationType.STAMP;\n    this.data.hasOwnCanvas = this.data.noRotate;\n    this.data.noHTML = false;\n  }\n  static async createImage(bitmap, xref) {\n    const {\n      width,\n      height\n    } = bitmap;\n    const canvas = new OffscreenCanvas(width, height);\n    const ctx = canvas.getContext(\"2d\", {\n      alpha: true\n    });\n    ctx.drawImage(bitmap, 0, 0);\n    const data = ctx.getImageData(0, 0, width, height).data;\n    const buf32 = new Uint32Array(data.buffer);\n    const hasAlpha = buf32.some(FeatureTest.isLittleEndian ? x => x >>> 24 !== 0xff : x => (x & 0xff) !== 0xff);\n    if (hasAlpha) {\n      ctx.fillStyle = \"white\";\n      ctx.fillRect(0, 0, width, height);\n      ctx.drawImage(bitmap, 0, 0);\n    }\n    const jpegBufferPromise = canvas.convertToBlob({\n      type: \"image/jpeg\",\n      quality: 1\n    }).then(blob => blob.arrayBuffer());\n    const xobjectName = Name.get(\"XObject\");\n    const imageName = Name.get(\"Image\");\n    const image = new Dict(xref);\n    image.set(\"Type\", xobjectName);\n    image.set(\"Subtype\", imageName);\n    image.set(\"BitsPerComponent\", 8);\n    image.set(\"ColorSpace\", Name.get(\"DeviceRGB\"));\n    image.set(\"Filter\", Name.get(\"DCTDecode\"));\n    image.set(\"BBox\", [0, 0, width, height]);\n    image.set(\"Width\", width);\n    image.set(\"Height\", height);\n    let smaskStream = null;\n    if (hasAlpha) {\n      const alphaBuffer = new Uint8Array(buf32.length);\n      if (FeatureTest.isLittleEndian) {\n        for (let i = 0, ii = buf32.length; i < ii; i++) {\n          alphaBuffer[i] = buf32[i] >>> 24;\n        }\n      } else {\n        for (let i = 0, ii = buf32.length; i < ii; i++) {\n          alphaBuffer[i] = buf32[i] & 0xff;\n        }\n      }\n      const smask = new Dict(xref);\n      smask.set(\"Type\", xobjectName);\n      smask.set(\"Subtype\", imageName);\n      smask.set(\"BitsPerComponent\", 8);\n      smask.set(\"ColorSpace\", Name.get(\"DeviceGray\"));\n      smask.set(\"Width\", width);\n      smask.set(\"Height\", height);\n      smaskStream = new Stream(alphaBuffer, 0, 0, smask);\n    }\n    const imageStream = new Stream(await jpegBufferPromise, 0, 0, image);\n    return {\n      imageStream,\n      smaskStream,\n      width,\n      height\n    };\n  }\n  static createNewDict(annotation, xref, {\n    apRef,\n    ap\n  }) {\n    const {\n      rect,\n      rotation,\n      user\n    } = annotation;\n    const stamp = new Dict(xref);\n    stamp.set(\"Type\", Name.get(\"Annot\"));\n    stamp.set(\"Subtype\", Name.get(\"Stamp\"));\n    stamp.set(\"CreationDate\", `D:${getModificationDate()}`);\n    stamp.set(\"Rect\", rect);\n    stamp.set(\"F\", 4);\n    stamp.set(\"Border\", [0, 0, 0]);\n    stamp.set(\"Rotate\", rotation);\n    if (user) {\n      stamp.set(\"T\", isAscii(user) ? user : stringToUTF16String(user, true));\n    }\n    if (apRef || ap) {\n      const n = new Dict(xref);\n      stamp.set(\"AP\", n);\n      if (apRef) {\n        n.set(\"N\", apRef);\n      } else {\n        n.set(\"N\", ap);\n      }\n    }\n    return stamp;\n  }\n  static async createNewAppearanceStream(annotation, xref, params) {\n    const {\n      rotation\n    } = annotation;\n    const {\n      imageRef,\n      width,\n      height\n    } = params.image;\n    const resources = new Dict(xref);\n    const xobject = new Dict(xref);\n    resources.set(\"XObject\", xobject);\n    xobject.set(\"Im0\", imageRef);\n    const appearance = `q ${width} 0 0 ${height} 0 0 cm /Im0 Do Q`;\n    const appearanceStreamDict = new Dict(xref);\n    appearanceStreamDict.set(\"FormType\", 1);\n    appearanceStreamDict.set(\"Subtype\", Name.get(\"Form\"));\n    appearanceStreamDict.set(\"Type\", Name.get(\"XObject\"));\n    appearanceStreamDict.set(\"BBox\", [0, 0, width, height]);\n    appearanceStreamDict.set(\"Resources\", resources);\n    if (rotation) {\n      const matrix = getRotationMatrix(rotation, width, height);\n      appearanceStreamDict.set(\"Matrix\", matrix);\n    }\n    const ap = new StringStream(appearance);\n    ap.dict = appearanceStreamDict;\n    return ap;\n  }\n}\nclass FileAttachmentAnnotation extends MarkupAnnotation {\n  constructor(params) {\n    super(params);\n    const {\n      dict,\n      xref\n    } = params;\n    const file = new FileSpec(dict.get(\"FS\"), xref);\n    this.data.annotationType = AnnotationType.FILEATTACHMENT;\n    this.data.hasOwnCanvas = this.data.noRotate;\n    this.data.noHTML = false;\n    this.data.file = file.serializable;\n    const name = dict.get(\"Name\");\n    this.data.name = name instanceof Name ? stringToPDFString(name.name) : \"PushPin\";\n    const fillAlpha = dict.get(\"ca\");\n    this.data.fillAlpha = typeof fillAlpha === \"number\" && fillAlpha >= 0 && fillAlpha <= 1 ? fillAlpha : null;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/dataset_reader.js\n\n\n\nfunction decodeString(str) {\n  try {\n    return stringToUTF8String(str);\n  } catch (ex) {\n    warn(`UTF-8 decoding failed: \"${ex}\".`);\n    return str;\n  }\n}\nclass DatasetXMLParser extends SimpleXMLParser {\n  constructor(options) {\n    super(options);\n    this.node = null;\n  }\n  onEndElement(name) {\n    const node = super.onEndElement(name);\n    if (node && name === \"xfa:datasets\") {\n      this.node = node;\n      throw new Error(\"Aborting DatasetXMLParser.\");\n    }\n  }\n}\nclass DatasetReader {\n  constructor(data) {\n    if (data.datasets) {\n      this.node = new SimpleXMLParser({\n        hasAttributes: true\n      }).parseFromString(data.datasets).documentElement;\n    } else {\n      const parser = new DatasetXMLParser({\n        hasAttributes: true\n      });\n      try {\n        parser.parseFromString(data[\"xdp:xdp\"]);\n      } catch {}\n      this.node = parser.node;\n    }\n  }\n  getValue(path) {\n    if (!this.node || !path) {\n      return \"\";\n    }\n    const node = this.node.searchNode(parseXFAPath(path), 0);\n    if (!node) {\n      return \"\";\n    }\n    const first = node.firstChild;\n    if (first?.nodeName === \"value\") {\n      return node.children.map(child => decodeString(child.textContent));\n    }\n    return decodeString(node.textContent);\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/xref.js\n\n\n\n\n\n\nclass XRef {\n  #firstXRefStmPos = null;\n  constructor(stream, pdfManager) {\n    this.stream = stream;\n    this.pdfManager = pdfManager;\n    this.entries = [];\n    this._xrefStms = new Set();\n    this._cacheMap = new Map();\n    this._pendingRefs = new RefSet();\n    this._newPersistentRefNum = null;\n    this._newTemporaryRefNum = null;\n    this._persistentRefsCache = null;\n  }\n  getNewPersistentRef(obj) {\n    if (this._newPersistentRefNum === null) {\n      this._newPersistentRefNum = this.entries.length || 1;\n    }\n    const num = this._newPersistentRefNum++;\n    this._cacheMap.set(num, obj);\n    return Ref.get(num, 0);\n  }\n  getNewTemporaryRef() {\n    if (this._newTemporaryRefNum === null) {\n      this._newTemporaryRefNum = this.entries.length || 1;\n      if (this._newPersistentRefNum) {\n        this._persistentRefsCache = new Map();\n        for (let i = this._newTemporaryRefNum; i < this._newPersistentRefNum; i++) {\n          this._persistentRefsCache.set(i, this._cacheMap.get(i));\n          this._cacheMap.delete(i);\n        }\n      }\n    }\n    return Ref.get(this._newTemporaryRefNum++, 0);\n  }\n  resetNewTemporaryRef() {\n    this._newTemporaryRefNum = null;\n    if (this._persistentRefsCache) {\n      for (const [num, obj] of this._persistentRefsCache) {\n        this._cacheMap.set(num, obj);\n      }\n    }\n    this._persistentRefsCache = null;\n  }\n  setStartXRef(startXRef) {\n    this.startXRefQueue = [startXRef];\n  }\n  parse(recoveryMode = false) {\n    let trailerDict;\n    if (!recoveryMode) {\n      trailerDict = this.readXRef();\n    } else {\n      warn(\"Indexing all PDF objects\");\n      trailerDict = this.indexObjects();\n    }\n    trailerDict.assignXref(this);\n    this.trailer = trailerDict;\n    let encrypt;\n    try {\n      encrypt = trailerDict.get(\"Encrypt\");\n    } catch (ex) {\n      if (ex instanceof MissingDataException) {\n        throw ex;\n      }\n      warn(`XRef.parse - Invalid \"Encrypt\" reference: \"${ex}\".`);\n    }\n    if (encrypt instanceof Dict) {\n      const ids = trailerDict.get(\"ID\");\n      const fileId = ids?.length ? ids[0] : \"\";\n      encrypt.suppressEncryption = true;\n      this.encrypt = new CipherTransformFactory(encrypt, fileId, this.pdfManager.password);\n    }\n    let root;\n    try {\n      root = trailerDict.get(\"Root\");\n    } catch (ex) {\n      if (ex instanceof MissingDataException) {\n        throw ex;\n      }\n      warn(`XRef.parse - Invalid \"Root\" reference: \"${ex}\".`);\n    }\n    if (root instanceof Dict) {\n      try {\n        const pages = root.get(\"Pages\");\n        if (pages instanceof Dict) {\n          this.root = root;\n          return;\n        }\n      } catch (ex) {\n        if (ex instanceof MissingDataException) {\n          throw ex;\n        }\n        warn(`XRef.parse - Invalid \"Pages\" reference: \"${ex}\".`);\n      }\n    }\n    if (!recoveryMode) {\n      throw new XRefParseException();\n    }\n    throw new InvalidPDFException(\"Invalid Root reference.\");\n  }\n  processXRefTable(parser) {\n    if (!(\"tableState\" in this)) {\n      this.tableState = {\n        entryNum: 0,\n        streamPos: parser.lexer.stream.pos,\n        parserBuf1: parser.buf1,\n        parserBuf2: parser.buf2\n      };\n    }\n    const obj = this.readXRefTable(parser);\n    if (!isCmd(obj, \"trailer\")) {\n      throw new FormatError(\"Invalid XRef table: could not find trailer dictionary\");\n    }\n    let dict = parser.getObj();\n    if (!(dict instanceof Dict) && dict.dict) {\n      dict = dict.dict;\n    }\n    if (!(dict instanceof Dict)) {\n      throw new FormatError(\"Invalid XRef table: could not parse trailer dictionary\");\n    }\n    delete this.tableState;\n    return dict;\n  }\n  readXRefTable(parser) {\n    const stream = parser.lexer.stream;\n    const tableState = this.tableState;\n    stream.pos = tableState.streamPos;\n    parser.buf1 = tableState.parserBuf1;\n    parser.buf2 = tableState.parserBuf2;\n    let obj;\n    while (true) {\n      if (!(\"firstEntryNum\" in tableState) || !(\"entryCount\" in tableState)) {\n        if (isCmd(obj = parser.getObj(), \"trailer\")) {\n          break;\n        }\n        tableState.firstEntryNum = obj;\n        tableState.entryCount = parser.getObj();\n      }\n      let first = tableState.firstEntryNum;\n      const count = tableState.entryCount;\n      if (!Number.isInteger(first) || !Number.isInteger(count)) {\n        throw new FormatError(\"Invalid XRef table: wrong types in subsection header\");\n      }\n      for (let i = tableState.entryNum; i < count; i++) {\n        tableState.streamPos = stream.pos;\n        tableState.entryNum = i;\n        tableState.parserBuf1 = parser.buf1;\n        tableState.parserBuf2 = parser.buf2;\n        const entry = {};\n        entry.offset = parser.getObj();\n        entry.gen = parser.getObj();\n        const type = parser.getObj();\n        if (type instanceof Cmd) {\n          switch (type.cmd) {\n            case \"f\":\n              entry.free = true;\n              break;\n            case \"n\":\n              entry.uncompressed = true;\n              break;\n          }\n        }\n        if (!Number.isInteger(entry.offset) || !Number.isInteger(entry.gen) || !(entry.free || entry.uncompressed)) {\n          throw new FormatError(`Invalid entry in XRef subsection: ${first}, ${count}`);\n        }\n        if (i === 0 && entry.free && first === 1) {\n          first = 0;\n        }\n        if (!this.entries[i + first]) {\n          this.entries[i + first] = entry;\n        }\n      }\n      tableState.entryNum = 0;\n      tableState.streamPos = stream.pos;\n      tableState.parserBuf1 = parser.buf1;\n      tableState.parserBuf2 = parser.buf2;\n      delete tableState.firstEntryNum;\n      delete tableState.entryCount;\n    }\n    if (this.entries[0] && !this.entries[0].free) {\n      throw new FormatError(\"Invalid XRef table: unexpected first object\");\n    }\n    return obj;\n  }\n  processXRefStream(stream) {\n    if (!(\"streamState\" in this)) {\n      const streamParameters = stream.dict;\n      const byteWidths = streamParameters.get(\"W\");\n      let range = streamParameters.get(\"Index\");\n      if (!range) {\n        range = [0, streamParameters.get(\"Size\")];\n      }\n      this.streamState = {\n        entryRanges: range,\n        byteWidths,\n        entryNum: 0,\n        streamPos: stream.pos\n      };\n    }\n    this.readXRefStream(stream);\n    delete this.streamState;\n    return stream.dict;\n  }\n  readXRefStream(stream) {\n    const streamState = this.streamState;\n    stream.pos = streamState.streamPos;\n    const [typeFieldWidth, offsetFieldWidth, generationFieldWidth] = streamState.byteWidths;\n    const entryRanges = streamState.entryRanges;\n    while (entryRanges.length > 0) {\n      const [first, n] = entryRanges;\n      if (!Number.isInteger(first) || !Number.isInteger(n)) {\n        throw new FormatError(`Invalid XRef range fields: ${first}, ${n}`);\n      }\n      if (!Number.isInteger(typeFieldWidth) || !Number.isInteger(offsetFieldWidth) || !Number.isInteger(generationFieldWidth)) {\n        throw new FormatError(`Invalid XRef entry fields length: ${first}, ${n}`);\n      }\n      for (let i = streamState.entryNum; i < n; ++i) {\n        streamState.entryNum = i;\n        streamState.streamPos = stream.pos;\n        let type = 0,\n          offset = 0,\n          generation = 0;\n        for (let j = 0; j < typeFieldWidth; ++j) {\n          const typeByte = stream.getByte();\n          if (typeByte === -1) {\n            throw new FormatError(\"Invalid XRef byteWidths 'type'.\");\n          }\n          type = type << 8 | typeByte;\n        }\n        if (typeFieldWidth === 0) {\n          type = 1;\n        }\n        for (let j = 0; j < offsetFieldWidth; ++j) {\n          const offsetByte = stream.getByte();\n          if (offsetByte === -1) {\n            throw new FormatError(\"Invalid XRef byteWidths 'offset'.\");\n          }\n          offset = offset << 8 | offsetByte;\n        }\n        for (let j = 0; j < generationFieldWidth; ++j) {\n          const generationByte = stream.getByte();\n          if (generationByte === -1) {\n            throw new FormatError(\"Invalid XRef byteWidths 'generation'.\");\n          }\n          generation = generation << 8 | generationByte;\n        }\n        const entry = {};\n        entry.offset = offset;\n        entry.gen = generation;\n        switch (type) {\n          case 0:\n            entry.free = true;\n            break;\n          case 1:\n            entry.uncompressed = true;\n            break;\n          case 2:\n            break;\n          default:\n            throw new FormatError(`Invalid XRef entry type: ${type}`);\n        }\n        if (!this.entries[first + i]) {\n          this.entries[first + i] = entry;\n        }\n      }\n      streamState.entryNum = 0;\n      streamState.streamPos = stream.pos;\n      entryRanges.splice(0, 2);\n    }\n  }\n  indexObjects() {\n    const TAB = 0x9,\n      LF = 0xa,\n      CR = 0xd,\n      SPACE = 0x20;\n    const PERCENT = 0x25,\n      LT = 0x3c;\n    function readToken(data, offset) {\n      let token = \"\",\n        ch = data[offset];\n      while (ch !== LF && ch !== CR && ch !== LT) {\n        if (++offset >= data.length) {\n          break;\n        }\n        token += String.fromCharCode(ch);\n        ch = data[offset];\n      }\n      return token;\n    }\n    function skipUntil(data, offset, what) {\n      const length = what.length,\n        dataLength = data.length;\n      let skipped = 0;\n      while (offset < dataLength) {\n        let i = 0;\n        while (i < length && data[offset + i] === what[i]) {\n          ++i;\n        }\n        if (i >= length) {\n          break;\n        }\n        offset++;\n        skipped++;\n      }\n      return skipped;\n    }\n    const gEndobjRegExp = /\\b(endobj|\\d+\\s+\\d+\\s+obj|xref|trailer\\s*<<)\\b/g;\n    const gStartxrefRegExp = /\\b(startxref|\\d+\\s+\\d+\\s+obj)\\b/g;\n    const objRegExp = /^(\\d+)\\s+(\\d+)\\s+obj\\b/;\n    const trailerBytes = new Uint8Array([116, 114, 97, 105, 108, 101, 114]);\n    const startxrefBytes = new Uint8Array([115, 116, 97, 114, 116, 120, 114, 101, 102]);\n    const xrefBytes = new Uint8Array([47, 88, 82, 101, 102]);\n    this.entries.length = 0;\n    this._cacheMap.clear();\n    const stream = this.stream;\n    stream.pos = 0;\n    const buffer = stream.getBytes(),\n      bufferStr = bytesToString(buffer),\n      length = buffer.length;\n    let position = stream.start;\n    const trailers = [],\n      xrefStms = [];\n    while (position < length) {\n      let ch = buffer[position];\n      if (ch === TAB || ch === LF || ch === CR || ch === SPACE) {\n        ++position;\n        continue;\n      }\n      if (ch === PERCENT) {\n        do {\n          ++position;\n          if (position >= length) {\n            break;\n          }\n          ch = buffer[position];\n        } while (ch !== LF && ch !== CR);\n        continue;\n      }\n      const token = readToken(buffer, position);\n      let m;\n      if (token.startsWith(\"xref\") && (token.length === 4 || /\\s/.test(token[4]))) {\n        position += skipUntil(buffer, position, trailerBytes);\n        trailers.push(position);\n        position += skipUntil(buffer, position, startxrefBytes);\n      } else if (m = objRegExp.exec(token)) {\n        const num = m[1] | 0,\n          gen = m[2] | 0;\n        const startPos = position + token.length;\n        let contentLength,\n          updateEntries = false;\n        if (!this.entries[num]) {\n          updateEntries = true;\n        } else if (this.entries[num].gen === gen) {\n          try {\n            const parser = new Parser({\n              lexer: new Lexer(stream.makeSubStream(startPos))\n            });\n            parser.getObj();\n            updateEntries = true;\n          } catch (ex) {\n            if (ex instanceof ParserEOFException) {\n              warn(`indexObjects -- checking object (${token}): \"${ex}\".`);\n            } else {\n              updateEntries = true;\n            }\n          }\n        }\n        if (updateEntries) {\n          this.entries[num] = {\n            offset: position - stream.start,\n            gen,\n            uncompressed: true\n          };\n        }\n        gEndobjRegExp.lastIndex = startPos;\n        const match = gEndobjRegExp.exec(bufferStr);\n        if (match) {\n          const endPos = gEndobjRegExp.lastIndex + 1;\n          contentLength = endPos - position;\n          if (match[1] !== \"endobj\") {\n            warn(`indexObjects: Found \"${match[1]}\" inside of another \"obj\", ` + 'caused by missing \"endobj\" -- trying to recover.');\n            contentLength -= match[1].length + 1;\n          }\n        } else {\n          contentLength = length - position;\n        }\n        const content = buffer.subarray(position, position + contentLength);\n        const xrefTagOffset = skipUntil(content, 0, xrefBytes);\n        if (xrefTagOffset < contentLength && content[xrefTagOffset + 5] < 64) {\n          xrefStms.push(position - stream.start);\n          this._xrefStms.add(position - stream.start);\n        }\n        position += contentLength;\n      } else if (token.startsWith(\"trailer\") && (token.length === 7 || /\\s/.test(token[7]))) {\n        trailers.push(position);\n        const startPos = position + token.length;\n        let contentLength;\n        gStartxrefRegExp.lastIndex = startPos;\n        const match = gStartxrefRegExp.exec(bufferStr);\n        if (match) {\n          const endPos = gStartxrefRegExp.lastIndex + 1;\n          contentLength = endPos - position;\n          if (match[1] !== \"startxref\") {\n            warn(`indexObjects: Found \"${match[1]}\" after \"trailer\", ` + 'caused by missing \"startxref\" -- trying to recover.');\n            contentLength -= match[1].length + 1;\n          }\n        } else {\n          contentLength = length - position;\n        }\n        position += contentLength;\n      } else {\n        position += token.length + 1;\n      }\n    }\n    for (const xrefStm of xrefStms) {\n      this.startXRefQueue.push(xrefStm);\n      this.readXRef(true);\n    }\n    const trailerDicts = [];\n    let isEncrypted = false;\n    for (const trailer of trailers) {\n      stream.pos = trailer;\n      const parser = new Parser({\n        lexer: new Lexer(stream),\n        xref: this,\n        allowStreams: true,\n        recoveryMode: true\n      });\n      const obj = parser.getObj();\n      if (!isCmd(obj, \"trailer\")) {\n        continue;\n      }\n      const dict = parser.getObj();\n      if (!(dict instanceof Dict)) {\n        continue;\n      }\n      trailerDicts.push(dict);\n      if (dict.has(\"Encrypt\")) {\n        isEncrypted = true;\n      }\n    }\n    let trailerDict, trailerError;\n    for (const dict of [...trailerDicts, \"genFallback\", ...trailerDicts]) {\n      if (dict === \"genFallback\") {\n        if (!trailerError) {\n          break;\n        }\n        this._generationFallback = true;\n        continue;\n      }\n      let validPagesDict = false;\n      try {\n        const rootDict = dict.get(\"Root\");\n        if (!(rootDict instanceof Dict)) {\n          continue;\n        }\n        const pagesDict = rootDict.get(\"Pages\");\n        if (!(pagesDict instanceof Dict)) {\n          continue;\n        }\n        const pagesCount = pagesDict.get(\"Count\");\n        if (Number.isInteger(pagesCount)) {\n          validPagesDict = true;\n        }\n      } catch (ex) {\n        trailerError = ex;\n        continue;\n      }\n      if (validPagesDict && (!isEncrypted || dict.has(\"Encrypt\")) && dict.has(\"ID\")) {\n        return dict;\n      }\n      trailerDict = dict;\n    }\n    if (trailerDict) {\n      return trailerDict;\n    }\n    if (this.topDict) {\n      return this.topDict;\n    }\n    throw new InvalidPDFException(\"Invalid PDF structure.\");\n  }\n  readXRef(recoveryMode = false) {\n    const stream = this.stream;\n    const startXRefParsedCache = new Set();\n    while (this.startXRefQueue.length) {\n      try {\n        const startXRef = this.startXRefQueue[0];\n        if (startXRefParsedCache.has(startXRef)) {\n          warn(\"readXRef - skipping XRef table since it was already parsed.\");\n          this.startXRefQueue.shift();\n          continue;\n        }\n        startXRefParsedCache.add(startXRef);\n        stream.pos = startXRef + stream.start;\n        const parser = new Parser({\n          lexer: new Lexer(stream),\n          xref: this,\n          allowStreams: true\n        });\n        let obj = parser.getObj();\n        let dict;\n        if (isCmd(obj, \"xref\")) {\n          dict = this.processXRefTable(parser);\n          if (!this.topDict) {\n            this.topDict = dict;\n          }\n          obj = dict.get(\"XRefStm\");\n          if (Number.isInteger(obj) && !this._xrefStms.has(obj)) {\n            this._xrefStms.add(obj);\n            this.startXRefQueue.push(obj);\n            this.#firstXRefStmPos ??= obj;\n          }\n        } else if (Number.isInteger(obj)) {\n          if (!Number.isInteger(parser.getObj()) || !isCmd(parser.getObj(), \"obj\") || !((obj = parser.getObj()) instanceof BaseStream)) {\n            throw new FormatError(\"Invalid XRef stream\");\n          }\n          dict = this.processXRefStream(obj);\n          if (!this.topDict) {\n            this.topDict = dict;\n          }\n          if (!dict) {\n            throw new FormatError(\"Failed to read XRef stream\");\n          }\n        } else {\n          throw new FormatError(\"Invalid XRef stream header\");\n        }\n        obj = dict.get(\"Prev\");\n        if (Number.isInteger(obj)) {\n          this.startXRefQueue.push(obj);\n        } else if (obj instanceof Ref) {\n          this.startXRefQueue.push(obj.num);\n        }\n      } catch (e) {\n        if (e instanceof MissingDataException) {\n          throw e;\n        }\n        info(\"(while reading XRef): \" + e);\n      }\n      this.startXRefQueue.shift();\n    }\n    if (this.topDict) {\n      return this.topDict;\n    }\n    if (recoveryMode) {\n      return undefined;\n    }\n    throw new XRefParseException();\n  }\n  get lastXRefStreamPos() {\n    return this.#firstXRefStmPos ?? (this._xrefStms.size > 0 ? Math.max(...this._xrefStms) : null);\n  }\n  getEntry(i) {\n    const xrefEntry = this.entries[i];\n    if (xrefEntry && !xrefEntry.free && xrefEntry.offset) {\n      return xrefEntry;\n    }\n    return null;\n  }\n  fetchIfRef(obj, suppressEncryption = false) {\n    if (obj instanceof Ref) {\n      return this.fetch(obj, suppressEncryption);\n    }\n    return obj;\n  }\n  fetch(ref, suppressEncryption = false) {\n    if (!(ref instanceof Ref)) {\n      throw new Error(\"ref object is not a reference\");\n    }\n    const num = ref.num;\n    const cacheEntry = this._cacheMap.get(num);\n    if (cacheEntry !== undefined) {\n      if (cacheEntry instanceof Dict && !cacheEntry.objId) {\n        cacheEntry.objId = ref.toString();\n      }\n      return cacheEntry;\n    }\n    let xrefEntry = this.getEntry(num);\n    if (xrefEntry === null) {\n      this._cacheMap.set(num, xrefEntry);\n      return xrefEntry;\n    }\n    if (this._pendingRefs.has(ref)) {\n      this._pendingRefs.remove(ref);\n      warn(`Ignoring circular reference: ${ref}.`);\n      return CIRCULAR_REF;\n    }\n    this._pendingRefs.put(ref);\n    try {\n      xrefEntry = xrefEntry.uncompressed ? this.fetchUncompressed(ref, xrefEntry, suppressEncryption) : this.fetchCompressed(ref, xrefEntry, suppressEncryption);\n      this._pendingRefs.remove(ref);\n    } catch (ex) {\n      this._pendingRefs.remove(ref);\n      throw ex;\n    }\n    if (xrefEntry instanceof Dict) {\n      xrefEntry.objId = ref.toString();\n    } else if (xrefEntry instanceof BaseStream) {\n      xrefEntry.dict.objId = ref.toString();\n    }\n    return xrefEntry;\n  }\n  fetchUncompressed(ref, xrefEntry, suppressEncryption = false) {\n    const gen = ref.gen;\n    let num = ref.num;\n    if (xrefEntry.gen !== gen) {\n      const msg = `Inconsistent generation in XRef: ${ref}`;\n      if (this._generationFallback && xrefEntry.gen < gen) {\n        warn(msg);\n        return this.fetchUncompressed(Ref.get(num, xrefEntry.gen), xrefEntry, suppressEncryption);\n      }\n      throw new XRefEntryException(msg);\n    }\n    const stream = this.stream.makeSubStream(xrefEntry.offset + this.stream.start);\n    const parser = new Parser({\n      lexer: new Lexer(stream),\n      xref: this,\n      allowStreams: true\n    });\n    const obj1 = parser.getObj();\n    const obj2 = parser.getObj();\n    const obj3 = parser.getObj();\n    if (obj1 !== num || obj2 !== gen || !(obj3 instanceof Cmd)) {\n      throw new XRefEntryException(`Bad (uncompressed) XRef entry: ${ref}`);\n    }\n    if (obj3.cmd !== \"obj\") {\n      if (obj3.cmd.startsWith(\"obj\")) {\n        num = parseInt(obj3.cmd.substring(3), 10);\n        if (!Number.isNaN(num)) {\n          return num;\n        }\n      }\n      throw new XRefEntryException(`Bad (uncompressed) XRef entry: ${ref}`);\n    }\n    xrefEntry = this.encrypt && !suppressEncryption ? parser.getObj(this.encrypt.createCipherTransform(num, gen)) : parser.getObj();\n    if (!(xrefEntry instanceof BaseStream)) {\n      this._cacheMap.set(num, xrefEntry);\n    }\n    return xrefEntry;\n  }\n  fetchCompressed(ref, xrefEntry, suppressEncryption = false) {\n    const tableOffset = xrefEntry.offset;\n    const stream = this.fetch(Ref.get(tableOffset, 0));\n    if (!(stream instanceof BaseStream)) {\n      throw new FormatError(\"bad ObjStm stream\");\n    }\n    const first = stream.dict.get(\"First\");\n    const n = stream.dict.get(\"N\");\n    if (!Number.isInteger(first) || !Number.isInteger(n)) {\n      throw new FormatError(\"invalid first and n parameters for ObjStm stream\");\n    }\n    let parser = new Parser({\n      lexer: new Lexer(stream),\n      xref: this,\n      allowStreams: true\n    });\n    const nums = new Array(n);\n    const offsets = new Array(n);\n    for (let i = 0; i < n; ++i) {\n      const num = parser.getObj();\n      if (!Number.isInteger(num)) {\n        throw new FormatError(`invalid object number in the ObjStm stream: ${num}`);\n      }\n      const offset = parser.getObj();\n      if (!Number.isInteger(offset)) {\n        throw new FormatError(`invalid object offset in the ObjStm stream: ${offset}`);\n      }\n      nums[i] = num;\n      offsets[i] = offset;\n    }\n    const start = (stream.start || 0) + first;\n    const entries = new Array(n);\n    for (let i = 0; i < n; ++i) {\n      const length = i < n - 1 ? offsets[i + 1] - offsets[i] : undefined;\n      if (length < 0) {\n        throw new FormatError(\"Invalid offset in the ObjStm stream.\");\n      }\n      parser = new Parser({\n        lexer: new Lexer(stream.makeSubStream(start + offsets[i], length, stream.dict)),\n        xref: this,\n        allowStreams: true\n      });\n      const obj = parser.getObj();\n      entries[i] = obj;\n      if (obj instanceof BaseStream) {\n        continue;\n      }\n      const num = nums[i],\n        entry = this.entries[num];\n      if (entry && entry.offset === tableOffset && entry.gen === i) {\n        this._cacheMap.set(num, obj);\n      }\n    }\n    xrefEntry = entries[xrefEntry.gen];\n    if (xrefEntry === undefined) {\n      throw new XRefEntryException(`Bad (compressed) XRef entry: ${ref}`);\n    }\n    return xrefEntry;\n  }\n  async fetchIfRefAsync(obj, suppressEncryption) {\n    if (obj instanceof Ref) {\n      return this.fetchAsync(obj, suppressEncryption);\n    }\n    return obj;\n  }\n  async fetchAsync(ref, suppressEncryption) {\n    try {\n      return this.fetch(ref, suppressEncryption);\n    } catch (ex) {\n      if (!(ex instanceof MissingDataException)) {\n        throw ex;\n      }\n      await this.pdfManager.requestRange(ex.begin, ex.end);\n      return this.fetchAsync(ref, suppressEncryption);\n    }\n  }\n  getCatalogObj() {\n    return this.root;\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/document.js\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst DEFAULT_USER_UNIT = 1.0;\nconst LETTER_SIZE_MEDIABOX = [0, 0, 612, 792];\nclass Page {\n  constructor({\n    pdfManager,\n    xref,\n    pageIndex,\n    pageDict,\n    ref,\n    globalIdFactory,\n    fontCache,\n    builtInCMapCache,\n    standardFontDataCache,\n    globalImageCache,\n    systemFontCache,\n    nonBlendModesSet,\n    xfaFactory\n  }) {\n    this.pdfManager = pdfManager;\n    this.pageIndex = pageIndex;\n    this.pageDict = pageDict;\n    this.xref = xref;\n    this.ref = ref;\n    this.fontCache = fontCache;\n    this.builtInCMapCache = builtInCMapCache;\n    this.standardFontDataCache = standardFontDataCache;\n    this.globalImageCache = globalImageCache;\n    this.systemFontCache = systemFontCache;\n    this.nonBlendModesSet = nonBlendModesSet;\n    this.evaluatorOptions = pdfManager.evaluatorOptions;\n    this.resourcesPromise = null;\n    this.xfaFactory = xfaFactory;\n    const idCounters = {\n      obj: 0\n    };\n    this._localIdFactory = class extends globalIdFactory {\n      static createObjId() {\n        return `p${pageIndex}_${++idCounters.obj}`;\n      }\n      static getPageObjId() {\n        return `p${ref.toString()}`;\n      }\n    };\n  }\n  _getInheritableProperty(key, getArray = false) {\n    const value = getInheritableProperty({\n      dict: this.pageDict,\n      key,\n      getArray,\n      stopWhenFound: false\n    });\n    if (!Array.isArray(value)) {\n      return value;\n    }\n    if (value.length === 1 || !(value[0] instanceof Dict)) {\n      return value[0];\n    }\n    return Dict.merge({\n      xref: this.xref,\n      dictArray: value\n    });\n  }\n  get content() {\n    return this.pageDict.getArray(\"Contents\");\n  }\n  get resources() {\n    const resources = this._getInheritableProperty(\"Resources\");\n    return shadow(this, \"resources\", resources instanceof Dict ? resources : Dict.empty);\n  }\n  _getBoundingBox(name) {\n    if (this.xfaData) {\n      return this.xfaData.bbox;\n    }\n    let box = this._getInheritableProperty(name, true);\n    if (Array.isArray(box) && box.length === 4) {\n      box = Util.normalizeRect(box);\n      if (box[2] - box[0] > 0 && box[3] - box[1] > 0) {\n        return box;\n      }\n      warn(`Empty, or invalid, /${name} entry.`);\n    }\n    return null;\n  }\n  get mediaBox() {\n    return shadow(this, \"mediaBox\", this._getBoundingBox(\"MediaBox\") || LETTER_SIZE_MEDIABOX);\n  }\n  get cropBox() {\n    return shadow(this, \"cropBox\", this._getBoundingBox(\"CropBox\") || this.mediaBox);\n  }\n  get userUnit() {\n    let obj = this.pageDict.get(\"UserUnit\");\n    if (typeof obj !== \"number\" || obj <= 0) {\n      obj = DEFAULT_USER_UNIT;\n    }\n    return shadow(this, \"userUnit\", obj);\n  }\n  get view() {\n    const {\n      cropBox,\n      mediaBox\n    } = this;\n    if (cropBox !== mediaBox && !isArrayEqual(cropBox, mediaBox)) {\n      const box = Util.intersect(cropBox, mediaBox);\n      if (box && box[2] - box[0] > 0 && box[3] - box[1] > 0) {\n        return shadow(this, \"view\", box);\n      }\n      warn(\"Empty /CropBox and /MediaBox intersection.\");\n    }\n    return shadow(this, \"view\", mediaBox);\n  }\n  get rotate() {\n    let rotate = this._getInheritableProperty(\"Rotate\") || 0;\n    if (rotate % 90 !== 0) {\n      rotate = 0;\n    } else if (rotate >= 360) {\n      rotate %= 360;\n    } else if (rotate < 0) {\n      rotate = (rotate % 360 + 360) % 360;\n    }\n    return shadow(this, \"rotate\", rotate);\n  }\n  _onSubStreamError(reason, objId) {\n    if (this.evaluatorOptions.ignoreErrors) {\n      warn(`getContentStream - ignoring sub-stream (${objId}): \"${reason}\".`);\n      return;\n    }\n    throw reason;\n  }\n  getContentStream() {\n    return this.pdfManager.ensure(this, \"content\").then(content => {\n      if (content instanceof BaseStream) {\n        return content;\n      }\n      if (Array.isArray(content)) {\n        return new StreamsSequenceStream(content, this._onSubStreamError.bind(this));\n      }\n      return new NullStream();\n    });\n  }\n  get xfaData() {\n    return shadow(this, \"xfaData\", this.xfaFactory ? {\n      bbox: this.xfaFactory.getBoundingBox(this.pageIndex)\n    } : null);\n  }\n  #replaceIdByRef(annotations, deletedAnnotations, existingAnnotations) {\n    for (const annotation of annotations) {\n      if (annotation.id) {\n        const ref = Ref.fromString(annotation.id);\n        if (!ref) {\n          warn(`A non-linked annotation cannot be modified: ${annotation.id}`);\n          continue;\n        }\n        if (annotation.deleted) {\n          deletedAnnotations.put(ref, ref);\n          continue;\n        }\n        existingAnnotations?.put(ref);\n        annotation.ref = ref;\n        delete annotation.id;\n      }\n    }\n  }\n  async saveNewAnnotations(handler, task, annotations, imagePromises) {\n    if (this.xfaFactory) {\n      throw new Error(\"XFA: Cannot save new annotations.\");\n    }\n    const partialEvaluator = new PartialEvaluator({\n      xref: this.xref,\n      handler,\n      pageIndex: this.pageIndex,\n      idFactory: this._localIdFactory,\n      fontCache: this.fontCache,\n      builtInCMapCache: this.builtInCMapCache,\n      standardFontDataCache: this.standardFontDataCache,\n      globalImageCache: this.globalImageCache,\n      systemFontCache: this.systemFontCache,\n      options: this.evaluatorOptions\n    });\n    const deletedAnnotations = new RefSetCache();\n    const existingAnnotations = new RefSet();\n    this.#replaceIdByRef(annotations, deletedAnnotations, existingAnnotations);\n    const pageDict = this.pageDict;\n    const annotationsArray = this.annotations.filter(a => !(a instanceof Ref && deletedAnnotations.has(a)));\n    const newData = await AnnotationFactory.saveNewAnnotations(partialEvaluator, task, annotations, imagePromises);\n    for (const {\n      ref\n    } of newData.annotations) {\n      if (ref instanceof Ref && !existingAnnotations.has(ref)) {\n        annotationsArray.push(ref);\n      }\n    }\n    const savedDict = pageDict.get(\"Annots\");\n    pageDict.set(\"Annots\", annotationsArray);\n    const buffer = [];\n    await writeObject(this.ref, pageDict, buffer, this.xref);\n    if (savedDict) {\n      pageDict.set(\"Annots\", savedDict);\n    }\n    const objects = newData.dependencies;\n    objects.push({\n      ref: this.ref,\n      data: buffer.join(\"\")\n    }, ...newData.annotations);\n    for (const deletedRef of deletedAnnotations) {\n      objects.push({\n        ref: deletedRef,\n        data: null\n      });\n    }\n    return objects;\n  }\n  save(handler, task, annotationStorage) {\n    const partialEvaluator = new PartialEvaluator({\n      xref: this.xref,\n      handler,\n      pageIndex: this.pageIndex,\n      idFactory: this._localIdFactory,\n      fontCache: this.fontCache,\n      builtInCMapCache: this.builtInCMapCache,\n      standardFontDataCache: this.standardFontDataCache,\n      globalImageCache: this.globalImageCache,\n      systemFontCache: this.systemFontCache,\n      options: this.evaluatorOptions\n    });\n    return this._parsedAnnotations.then(function (annotations) {\n      const newRefsPromises = [];\n      for (const annotation of annotations) {\n        if (!annotation.mustBePrinted(annotationStorage)) {\n          continue;\n        }\n        newRefsPromises.push(annotation.save(partialEvaluator, task, annotationStorage).catch(function (reason) {\n          warn(\"save - ignoring annotation data during \" + `\"${task.name}\" task: \"${reason}\".`);\n          return null;\n        }));\n      }\n      return Promise.all(newRefsPromises).then(function (newRefs) {\n        return newRefs.filter(newRef => !!newRef);\n      });\n    });\n  }\n  loadResources(keys) {\n    if (!this.resourcesPromise) {\n      this.resourcesPromise = this.pdfManager.ensure(this, \"resources\");\n    }\n    return this.resourcesPromise.then(() => {\n      const objectLoader = new ObjectLoader(this.resources, keys, this.xref);\n      return objectLoader.load();\n    });\n  }\n  getOperatorList({\n    handler,\n    sink,\n    task,\n    intent,\n    cacheKey,\n    annotationStorage = null\n  }) {\n    const contentStreamPromise = this.getContentStream();\n    const resourcesPromise = this.loadResources([\"ColorSpace\", \"ExtGState\", \"Font\", \"Pattern\", \"Properties\", \"Shading\", \"XObject\"]);\n    const partialEvaluator = new PartialEvaluator({\n      xref: this.xref,\n      handler,\n      pageIndex: this.pageIndex,\n      idFactory: this._localIdFactory,\n      fontCache: this.fontCache,\n      builtInCMapCache: this.builtInCMapCache,\n      standardFontDataCache: this.standardFontDataCache,\n      globalImageCache: this.globalImageCache,\n      systemFontCache: this.systemFontCache,\n      options: this.evaluatorOptions\n    });\n    const newAnnotationsByPage = !this.xfaFactory ? getNewAnnotationsMap(annotationStorage) : null;\n    let deletedAnnotations = null;\n    let newAnnotationsPromise = Promise.resolve(null);\n    if (newAnnotationsByPage) {\n      const newAnnotations = newAnnotationsByPage.get(this.pageIndex);\n      if (newAnnotations) {\n        const annotationGlobalsPromise = this.pdfManager.ensureDoc(\"annotationGlobals\");\n        let imagePromises;\n        const missingBitmaps = new Set();\n        for (const {\n          bitmapId,\n          bitmap\n        } of newAnnotations) {\n          if (bitmapId && !bitmap && !missingBitmaps.has(bitmapId)) {\n            missingBitmaps.add(bitmapId);\n          }\n        }\n        const {\n          isOffscreenCanvasSupported\n        } = this.evaluatorOptions;\n        if (missingBitmaps.size > 0) {\n          const annotationWithBitmaps = newAnnotations.slice();\n          for (const [key, annotation] of annotationStorage) {\n            if (!key.startsWith(AnnotationEditorPrefix)) {\n              continue;\n            }\n            if (annotation.bitmap && missingBitmaps.has(annotation.bitmapId)) {\n              annotationWithBitmaps.push(annotation);\n            }\n          }\n          imagePromises = AnnotationFactory.generateImages(annotationWithBitmaps, this.xref, isOffscreenCanvasSupported);\n        } else {\n          imagePromises = AnnotationFactory.generateImages(newAnnotations, this.xref, isOffscreenCanvasSupported);\n        }\n        deletedAnnotations = new RefSet();\n        this.#replaceIdByRef(newAnnotations, deletedAnnotations, null);\n        newAnnotationsPromise = annotationGlobalsPromise.then(annotationGlobals => {\n          if (!annotationGlobals) {\n            return null;\n          }\n          return AnnotationFactory.printNewAnnotations(annotationGlobals, partialEvaluator, task, newAnnotations, imagePromises);\n        });\n      }\n    }\n    const dataPromises = Promise.all([contentStreamPromise, resourcesPromise]);\n    const pageListPromise = dataPromises.then(([contentStream]) => {\n      const opList = new OperatorList(intent, sink);\n      handler.send(\"StartRenderPage\", {\n        transparency: partialEvaluator.hasBlendModes(this.resources, this.nonBlendModesSet),\n        pageIndex: this.pageIndex,\n        cacheKey\n      });\n      return partialEvaluator.getOperatorList({\n        stream: contentStream,\n        task,\n        resources: this.resources,\n        operatorList: opList\n      }).then(function () {\n        return opList;\n      });\n    });\n    return Promise.all([pageListPromise, this._parsedAnnotations, newAnnotationsPromise]).then(function ([pageOpList, annotations, newAnnotations]) {\n      if (newAnnotations) {\n        annotations = annotations.filter(a => !(a.ref && deletedAnnotations.has(a.ref)));\n        for (let i = 0, ii = newAnnotations.length; i < ii; i++) {\n          const newAnnotation = newAnnotations[i];\n          if (newAnnotation.refToReplace) {\n            const j = annotations.findIndex(a => a.ref && isRefsEqual(a.ref, newAnnotation.refToReplace));\n            if (j >= 0) {\n              annotations.splice(j, 1, newAnnotation);\n              newAnnotations.splice(i--, 1);\n              ii--;\n            }\n          }\n        }\n        annotations = annotations.concat(newAnnotations);\n      }\n      if (annotations.length === 0 || intent & RenderingIntentFlag.ANNOTATIONS_DISABLE) {\n        pageOpList.flush(true);\n        return {\n          length: pageOpList.totalLength\n        };\n      }\n      const renderForms = !!(intent & RenderingIntentFlag.ANNOTATIONS_FORMS),\n        intentAny = !!(intent & RenderingIntentFlag.ANY),\n        intentDisplay = !!(intent & RenderingIntentFlag.DISPLAY),\n        intentPrint = !!(intent & RenderingIntentFlag.PRINT);\n      const opListPromises = [];\n      for (const annotation of annotations) {\n        if (intentAny || intentDisplay && annotation.mustBeViewed(annotationStorage, renderForms) || intentPrint && annotation.mustBePrinted(annotationStorage)) {\n          opListPromises.push(annotation.getOperatorList(partialEvaluator, task, intent, renderForms, annotationStorage).catch(function (reason) {\n            warn(\"getOperatorList - ignoring annotation data during \" + `\"${task.name}\" task: \"${reason}\".`);\n            return {\n              opList: null,\n              separateForm: false,\n              separateCanvas: false\n            };\n          }));\n        }\n      }\n      return Promise.all(opListPromises).then(function (opLists) {\n        let form = false,\n          canvas = false;\n        for (const {\n          opList,\n          separateForm,\n          separateCanvas\n        } of opLists) {\n          pageOpList.addOpList(opList);\n          form ||= separateForm;\n          canvas ||= separateCanvas;\n        }\n        pageOpList.flush(true, {\n          form,\n          canvas\n        });\n        return {\n          length: pageOpList.totalLength\n        };\n      });\n    });\n  }\n  extractTextContent({\n    handler,\n    task,\n    includeMarkedContent,\n    disableNormalization,\n    sink\n  }) {\n    const contentStreamPromise = this.getContentStream();\n    const resourcesPromise = this.loadResources([\"ExtGState\", \"Font\", \"Properties\", \"XObject\"]);\n    const dataPromises = Promise.all([contentStreamPromise, resourcesPromise]);\n    return dataPromises.then(([contentStream]) => {\n      const partialEvaluator = new PartialEvaluator({\n        xref: this.xref,\n        handler,\n        pageIndex: this.pageIndex,\n        idFactory: this._localIdFactory,\n        fontCache: this.fontCache,\n        builtInCMapCache: this.builtInCMapCache,\n        standardFontDataCache: this.standardFontDataCache,\n        globalImageCache: this.globalImageCache,\n        systemFontCache: this.systemFontCache,\n        options: this.evaluatorOptions\n      });\n      return partialEvaluator.getTextContent({\n        stream: contentStream,\n        task,\n        resources: this.resources,\n        includeMarkedContent,\n        disableNormalization,\n        sink,\n        viewBox: this.view\n      });\n    });\n  }\n  async getStructTree() {\n    const structTreeRoot = await this.pdfManager.ensureCatalog(\"structTreeRoot\");\n    if (!structTreeRoot) {\n      return null;\n    }\n    await this._parsedAnnotations;\n    const structTree = await this.pdfManager.ensure(this, \"_parseStructTree\", [structTreeRoot]);\n    return structTree.serializable;\n  }\n  _parseStructTree(structTreeRoot) {\n    const tree = new StructTreePage(structTreeRoot, this.pageDict);\n    tree.parse(this.ref);\n    return tree;\n  }\n  async getAnnotationsData(handler, task, intent) {\n    const annotations = await this._parsedAnnotations;\n    if (annotations.length === 0) {\n      return annotations;\n    }\n    const annotationsData = [],\n      textContentPromises = [];\n    let partialEvaluator;\n    const intentAny = !!(intent & RenderingIntentFlag.ANY),\n      intentDisplay = !!(intent & RenderingIntentFlag.DISPLAY),\n      intentPrint = !!(intent & RenderingIntentFlag.PRINT);\n    for (const annotation of annotations) {\n      const isVisible = intentAny || intentDisplay && annotation.viewable;\n      if (isVisible || intentPrint && annotation.printable) {\n        annotationsData.push(annotation.data);\n      }\n      if (annotation.hasTextContent && isVisible) {\n        partialEvaluator ||= new PartialEvaluator({\n          xref: this.xref,\n          handler,\n          pageIndex: this.pageIndex,\n          idFactory: this._localIdFactory,\n          fontCache: this.fontCache,\n          builtInCMapCache: this.builtInCMapCache,\n          standardFontDataCache: this.standardFontDataCache,\n          globalImageCache: this.globalImageCache,\n          systemFontCache: this.systemFontCache,\n          options: this.evaluatorOptions\n        });\n        textContentPromises.push(annotation.extractTextContent(partialEvaluator, task, [-Infinity, -Infinity, Infinity, Infinity]).catch(function (reason) {\n          warn(`getAnnotationsData - ignoring textContent during \"${task.name}\" task: \"${reason}\".`);\n        }));\n      }\n    }\n    await Promise.all(textContentPromises);\n    return annotationsData;\n  }\n  get annotations() {\n    const annots = this._getInheritableProperty(\"Annots\");\n    return shadow(this, \"annotations\", Array.isArray(annots) ? annots : []);\n  }\n  get _parsedAnnotations() {\n    const promise = this.pdfManager.ensure(this, \"annotations\").then(async annots => {\n      if (annots.length === 0) {\n        return annots;\n      }\n      const annotationGlobals = await this.pdfManager.ensureDoc(\"annotationGlobals\");\n      if (!annotationGlobals) {\n        return [];\n      }\n      const annotationPromises = [];\n      for (const annotationRef of annots) {\n        annotationPromises.push(AnnotationFactory.create(this.xref, annotationRef, annotationGlobals, this._localIdFactory, false, this.ref).catch(function (reason) {\n          warn(`_parsedAnnotations: \"${reason}\".`);\n          return null;\n        }));\n      }\n      const sortedAnnotations = [];\n      let popupAnnotations, widgetAnnotations;\n      for (const annotation of await Promise.all(annotationPromises)) {\n        if (!annotation) {\n          continue;\n        }\n        if (annotation instanceof WidgetAnnotation) {\n          (widgetAnnotations ||= []).push(annotation);\n          continue;\n        }\n        if (annotation instanceof PopupAnnotation) {\n          (popupAnnotations ||= []).push(annotation);\n          continue;\n        }\n        sortedAnnotations.push(annotation);\n      }\n      if (widgetAnnotations) {\n        sortedAnnotations.push(...widgetAnnotations);\n      }\n      if (popupAnnotations) {\n        sortedAnnotations.push(...popupAnnotations);\n      }\n      return sortedAnnotations;\n    });\n    return shadow(this, \"_parsedAnnotations\", promise);\n  }\n  get jsActions() {\n    const actions = collectActions(this.xref, this.pageDict, PageActionEventType);\n    return shadow(this, \"jsActions\", actions);\n  }\n}\nconst PDF_HEADER_SIGNATURE = new Uint8Array([0x25, 0x50, 0x44, 0x46, 0x2d]);\nconst STARTXREF_SIGNATURE = new Uint8Array([0x73, 0x74, 0x61, 0x72, 0x74, 0x78, 0x72, 0x65, 0x66]);\nconst ENDOBJ_SIGNATURE = new Uint8Array([0x65, 0x6e, 0x64, 0x6f, 0x62, 0x6a]);\nconst FINGERPRINT_FIRST_BYTES = 1024;\nconst EMPTY_FINGERPRINT = \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\";\nfunction find(stream, signature, limit = 1024, backwards = false) {\n  const signatureLength = signature.length;\n  const scanBytes = stream.peekBytes(limit);\n  const scanLength = scanBytes.length - signatureLength;\n  if (scanLength <= 0) {\n    return false;\n  }\n  if (backwards) {\n    const signatureEnd = signatureLength - 1;\n    let pos = scanBytes.length - 1;\n    while (pos >= signatureEnd) {\n      let j = 0;\n      while (j < signatureLength && scanBytes[pos - j] === signature[signatureEnd - j]) {\n        j++;\n      }\n      if (j >= signatureLength) {\n        stream.pos += pos - signatureEnd;\n        return true;\n      }\n      pos--;\n    }\n  } else {\n    let pos = 0;\n    while (pos <= scanLength) {\n      let j = 0;\n      while (j < signatureLength && scanBytes[pos + j] === signature[j]) {\n        j++;\n      }\n      if (j >= signatureLength) {\n        stream.pos += pos;\n        return true;\n      }\n      pos++;\n    }\n  }\n  return false;\n}\nclass PDFDocument {\n  constructor(pdfManager, stream) {\n    if (stream.length <= 0) {\n      throw new InvalidPDFException(\"The PDF file is empty, i.e. its size is zero bytes.\");\n    }\n    this.pdfManager = pdfManager;\n    this.stream = stream;\n    this.xref = new XRef(stream, pdfManager);\n    this._pagePromises = new Map();\n    this._version = null;\n    const idCounters = {\n      font: 0\n    };\n    this._globalIdFactory = class {\n      static getDocId() {\n        return `g_${pdfManager.docId}`;\n      }\n      static createFontId() {\n        return `f${++idCounters.font}`;\n      }\n      static createObjId() {\n        unreachable(\"Abstract method `createObjId` called.\");\n      }\n      static getPageObjId() {\n        unreachable(\"Abstract method `getPageObjId` called.\");\n      }\n    };\n  }\n  parse(recoveryMode) {\n    this.xref.parse(recoveryMode);\n    this.catalog = new Catalog(this.pdfManager, this.xref);\n  }\n  get linearization() {\n    let linearization = null;\n    try {\n      linearization = Linearization.create(this.stream);\n    } catch (err) {\n      if (err instanceof MissingDataException) {\n        throw err;\n      }\n      info(err);\n    }\n    return shadow(this, \"linearization\", linearization);\n  }\n  get startXRef() {\n    const stream = this.stream;\n    let startXRef = 0;\n    if (this.linearization) {\n      stream.reset();\n      if (find(stream, ENDOBJ_SIGNATURE)) {\n        stream.skip(6);\n        let ch = stream.peekByte();\n        while (isWhiteSpace(ch)) {\n          stream.pos++;\n          ch = stream.peekByte();\n        }\n        startXRef = stream.pos - stream.start;\n      }\n    } else {\n      const step = 1024;\n      const startXRefLength = STARTXREF_SIGNATURE.length;\n      let found = false,\n        pos = stream.end;\n      while (!found && pos > 0) {\n        pos -= step - startXRefLength;\n        if (pos < 0) {\n          pos = 0;\n        }\n        stream.pos = pos;\n        found = find(stream, STARTXREF_SIGNATURE, step, true);\n      }\n      if (found) {\n        stream.skip(9);\n        let ch;\n        do {\n          ch = stream.getByte();\n        } while (isWhiteSpace(ch));\n        let str = \"\";\n        while (ch >= 0x20 && ch <= 0x39) {\n          str += String.fromCharCode(ch);\n          ch = stream.getByte();\n        }\n        startXRef = parseInt(str, 10);\n        if (isNaN(startXRef)) {\n          startXRef = 0;\n        }\n      }\n    }\n    return shadow(this, \"startXRef\", startXRef);\n  }\n  checkHeader() {\n    const stream = this.stream;\n    stream.reset();\n    if (!find(stream, PDF_HEADER_SIGNATURE)) {\n      return;\n    }\n    stream.moveStart();\n    stream.skip(PDF_HEADER_SIGNATURE.length);\n    let version = \"\",\n      ch;\n    while ((ch = stream.getByte()) > 0x20 && version.length < 7) {\n      version += String.fromCharCode(ch);\n    }\n    if (PDF_VERSION_REGEXP.test(version)) {\n      this._version = version;\n    } else {\n      warn(`Invalid PDF header version: ${version}`);\n    }\n  }\n  parseStartXRef() {\n    this.xref.setStartXRef(this.startXRef);\n  }\n  get numPages() {\n    let num = 0;\n    if (this.catalog.hasActualNumPages) {\n      num = this.catalog.numPages;\n    } else if (this.xfaFactory) {\n      num = this.xfaFactory.getNumPages();\n    } else if (this.linearization) {\n      num = this.linearization.numPages;\n    } else {\n      num = this.catalog.numPages;\n    }\n    return shadow(this, \"numPages\", num);\n  }\n  _hasOnlyDocumentSignatures(fields, recursionDepth = 0) {\n    const RECURSION_LIMIT = 10;\n    if (!Array.isArray(fields)) {\n      return false;\n    }\n    return fields.every(field => {\n      field = this.xref.fetchIfRef(field);\n      if (!(field instanceof Dict)) {\n        return false;\n      }\n      if (field.has(\"Kids\")) {\n        if (++recursionDepth > RECURSION_LIMIT) {\n          warn(\"_hasOnlyDocumentSignatures: maximum recursion depth reached\");\n          return false;\n        }\n        return this._hasOnlyDocumentSignatures(field.get(\"Kids\"), recursionDepth);\n      }\n      const isSignature = isName(field.get(\"FT\"), \"Sig\");\n      const rectangle = field.get(\"Rect\");\n      const isInvisible = Array.isArray(rectangle) && rectangle.every(value => value === 0);\n      return isSignature && isInvisible;\n    });\n  }\n  get _xfaStreams() {\n    const acroForm = this.catalog.acroForm;\n    if (!acroForm) {\n      return null;\n    }\n    const xfa = acroForm.get(\"XFA\");\n    const entries = {\n      \"xdp:xdp\": \"\",\n      template: \"\",\n      datasets: \"\",\n      config: \"\",\n      connectionSet: \"\",\n      localeSet: \"\",\n      stylesheet: \"\",\n      \"/xdp:xdp\": \"\"\n    };\n    if (xfa instanceof BaseStream && !xfa.isEmpty) {\n      entries[\"xdp:xdp\"] = xfa;\n      return entries;\n    }\n    if (!Array.isArray(xfa) || xfa.length === 0) {\n      return null;\n    }\n    for (let i = 0, ii = xfa.length; i < ii; i += 2) {\n      let name;\n      if (i === 0) {\n        name = \"xdp:xdp\";\n      } else if (i === ii - 2) {\n        name = \"/xdp:xdp\";\n      } else {\n        name = xfa[i];\n      }\n      if (!entries.hasOwnProperty(name)) {\n        continue;\n      }\n      const data = this.xref.fetchIfRef(xfa[i + 1]);\n      if (!(data instanceof BaseStream) || data.isEmpty) {\n        continue;\n      }\n      entries[name] = data;\n    }\n    return entries;\n  }\n  get xfaDatasets() {\n    const streams = this._xfaStreams;\n    if (!streams) {\n      return shadow(this, \"xfaDatasets\", null);\n    }\n    for (const key of [\"datasets\", \"xdp:xdp\"]) {\n      const stream = streams[key];\n      if (!stream) {\n        continue;\n      }\n      try {\n        const str = stringToUTF8String(stream.getString());\n        const data = {\n          [key]: str\n        };\n        return shadow(this, \"xfaDatasets\", new DatasetReader(data));\n      } catch {\n        warn(\"XFA - Invalid utf-8 string.\");\n        break;\n      }\n    }\n    return shadow(this, \"xfaDatasets\", null);\n  }\n  get xfaData() {\n    const streams = this._xfaStreams;\n    if (!streams) {\n      return null;\n    }\n    const data = Object.create(null);\n    for (const [key, stream] of Object.entries(streams)) {\n      if (!stream) {\n        continue;\n      }\n      try {\n        data[key] = stringToUTF8String(stream.getString());\n      } catch {\n        warn(\"XFA - Invalid utf-8 string.\");\n        return null;\n      }\n    }\n    return data;\n  }\n  get xfaFactory() {\n    let data;\n    if (this.pdfManager.enableXfa && this.catalog.needsRendering && this.formInfo.hasXfa && !this.formInfo.hasAcroForm) {\n      data = this.xfaData;\n    }\n    return shadow(this, \"xfaFactory\", data ? new XFAFactory(data) : null);\n  }\n  get isPureXfa() {\n    return this.xfaFactory ? this.xfaFactory.isValid() : false;\n  }\n  get htmlForXfa() {\n    return this.xfaFactory ? this.xfaFactory.getPages() : null;\n  }\n  async loadXfaImages() {\n    const xfaImagesDict = await this.pdfManager.ensureCatalog(\"xfaImages\");\n    if (!xfaImagesDict) {\n      return;\n    }\n    const keys = xfaImagesDict.getKeys();\n    const objectLoader = new ObjectLoader(xfaImagesDict, keys, this.xref);\n    await objectLoader.load();\n    const xfaImages = new Map();\n    for (const key of keys) {\n      const stream = xfaImagesDict.get(key);\n      if (stream instanceof BaseStream) {\n        xfaImages.set(key, stream.getBytes());\n      }\n    }\n    this.xfaFactory.setImages(xfaImages);\n  }\n  async loadXfaFonts(handler, task) {\n    const acroForm = await this.pdfManager.ensureCatalog(\"acroForm\");\n    if (!acroForm) {\n      return;\n    }\n    const resources = await acroForm.getAsync(\"DR\");\n    if (!(resources instanceof Dict)) {\n      return;\n    }\n    const objectLoader = new ObjectLoader(resources, [\"Font\"], this.xref);\n    await objectLoader.load();\n    const fontRes = resources.get(\"Font\");\n    if (!(fontRes instanceof Dict)) {\n      return;\n    }\n    const options = Object.assign(Object.create(null), this.pdfManager.evaluatorOptions);\n    options.useSystemFonts = false;\n    const partialEvaluator = new PartialEvaluator({\n      xref: this.xref,\n      handler,\n      pageIndex: -1,\n      idFactory: this._globalIdFactory,\n      fontCache: this.catalog.fontCache,\n      builtInCMapCache: this.catalog.builtInCMapCache,\n      standardFontDataCache: this.catalog.standardFontDataCache,\n      options\n    });\n    const operatorList = new OperatorList();\n    const pdfFonts = [];\n    const initialState = {\n      get font() {\n        return pdfFonts.at(-1);\n      },\n      set font(font) {\n        pdfFonts.push(font);\n      },\n      clone() {\n        return this;\n      }\n    };\n    const fonts = new Map();\n    fontRes.forEach((fontName, font) => {\n      fonts.set(fontName, font);\n    });\n    const promises = [];\n    for (const [fontName, font] of fonts) {\n      const descriptor = font.get(\"FontDescriptor\");\n      if (!(descriptor instanceof Dict)) {\n        continue;\n      }\n      let fontFamily = descriptor.get(\"FontFamily\");\n      fontFamily = fontFamily.replaceAll(/[ ]+(\\d)/g, \"$1\");\n      const fontWeight = descriptor.get(\"FontWeight\");\n      const italicAngle = -descriptor.get(\"ItalicAngle\");\n      const cssFontInfo = {\n        fontFamily,\n        fontWeight,\n        italicAngle\n      };\n      if (!validateCSSFont(cssFontInfo)) {\n        continue;\n      }\n      promises.push(partialEvaluator.handleSetFont(resources, [Name.get(fontName), 1], null, operatorList, task, initialState, null, cssFontInfo).catch(function (reason) {\n        warn(`loadXfaFonts: \"${reason}\".`);\n        return null;\n      }));\n    }\n    await Promise.all(promises);\n    const missingFonts = this.xfaFactory.setFonts(pdfFonts);\n    if (!missingFonts) {\n      return;\n    }\n    options.ignoreErrors = true;\n    promises.length = 0;\n    pdfFonts.length = 0;\n    const reallyMissingFonts = new Set();\n    for (const missing of missingFonts) {\n      if (!getXfaFontName(`${missing}-Regular`)) {\n        reallyMissingFonts.add(missing);\n      }\n    }\n    if (reallyMissingFonts.size) {\n      missingFonts.push(\"PdfJS-Fallback\");\n    }\n    for (const missing of missingFonts) {\n      if (reallyMissingFonts.has(missing)) {\n        continue;\n      }\n      for (const fontInfo of [{\n        name: \"Regular\",\n        fontWeight: 400,\n        italicAngle: 0\n      }, {\n        name: \"Bold\",\n        fontWeight: 700,\n        italicAngle: 0\n      }, {\n        name: \"Italic\",\n        fontWeight: 400,\n        italicAngle: 12\n      }, {\n        name: \"BoldItalic\",\n        fontWeight: 700,\n        italicAngle: 12\n      }]) {\n        const name = `${missing}-${fontInfo.name}`;\n        const dict = getXfaFontDict(name);\n        promises.push(partialEvaluator.handleSetFont(resources, [Name.get(name), 1], null, operatorList, task, initialState, dict, {\n          fontFamily: missing,\n          fontWeight: fontInfo.fontWeight,\n          italicAngle: fontInfo.italicAngle\n        }).catch(function (reason) {\n          warn(`loadXfaFonts: \"${reason}\".`);\n          return null;\n        }));\n      }\n    }\n    await Promise.all(promises);\n    this.xfaFactory.appendFonts(pdfFonts, reallyMissingFonts);\n  }\n  async serializeXfaData(annotationStorage) {\n    return this.xfaFactory ? this.xfaFactory.serializeData(annotationStorage) : null;\n  }\n  get version() {\n    return this.catalog.version || this._version;\n  }\n  get formInfo() {\n    const formInfo = {\n      hasFields: false,\n      hasAcroForm: false,\n      hasXfa: false,\n      hasSignatures: false\n    };\n    const acroForm = this.catalog.acroForm;\n    if (!acroForm) {\n      return shadow(this, \"formInfo\", formInfo);\n    }\n    try {\n      const fields = acroForm.get(\"Fields\");\n      const hasFields = Array.isArray(fields) && fields.length > 0;\n      formInfo.hasFields = hasFields;\n      const xfa = acroForm.get(\"XFA\");\n      formInfo.hasXfa = Array.isArray(xfa) && xfa.length > 0 || xfa instanceof BaseStream && !xfa.isEmpty;\n      const sigFlags = acroForm.get(\"SigFlags\");\n      const hasSignatures = !!(sigFlags & 0x1);\n      const hasOnlyDocumentSignatures = hasSignatures && this._hasOnlyDocumentSignatures(fields);\n      formInfo.hasAcroForm = hasFields && !hasOnlyDocumentSignatures;\n      formInfo.hasSignatures = hasSignatures;\n    } catch (ex) {\n      if (ex instanceof MissingDataException) {\n        throw ex;\n      }\n      warn(`Cannot fetch form information: \"${ex}\".`);\n    }\n    return shadow(this, \"formInfo\", formInfo);\n  }\n  get documentInfo() {\n    const docInfo = {\n      PDFFormatVersion: this.version,\n      Language: this.catalog.lang,\n      EncryptFilterName: this.xref.encrypt ? this.xref.encrypt.filterName : null,\n      IsLinearized: !!this.linearization,\n      IsAcroFormPresent: this.formInfo.hasAcroForm,\n      IsXFAPresent: this.formInfo.hasXfa,\n      IsCollectionPresent: !!this.catalog.collection,\n      IsSignaturesPresent: this.formInfo.hasSignatures\n    };\n    let infoDict;\n    try {\n      infoDict = this.xref.trailer.get(\"Info\");\n    } catch (err) {\n      if (err instanceof MissingDataException) {\n        throw err;\n      }\n      info(\"The document information dictionary is invalid.\");\n    }\n    if (!(infoDict instanceof Dict)) {\n      return shadow(this, \"documentInfo\", docInfo);\n    }\n    for (const key of infoDict.getKeys()) {\n      const value = infoDict.get(key);\n      switch (key) {\n        case \"Title\":\n        case \"Author\":\n        case \"Subject\":\n        case \"Keywords\":\n        case \"Creator\":\n        case \"Producer\":\n        case \"CreationDate\":\n        case \"ModDate\":\n          if (typeof value === \"string\") {\n            docInfo[key] = stringToPDFString(value);\n            continue;\n          }\n          break;\n        case \"Trapped\":\n          if (value instanceof Name) {\n            docInfo[key] = value;\n            continue;\n          }\n          break;\n        default:\n          let customValue;\n          switch (typeof value) {\n            case \"string\":\n              customValue = stringToPDFString(value);\n              break;\n            case \"number\":\n            case \"boolean\":\n              customValue = value;\n              break;\n            default:\n              if (value instanceof Name) {\n                customValue = value;\n              }\n              break;\n          }\n          if (customValue === undefined) {\n            warn(`Bad value, for custom key \"${key}\", in Info: ${value}.`);\n            continue;\n          }\n          if (!docInfo.Custom) {\n            docInfo.Custom = Object.create(null);\n          }\n          docInfo.Custom[key] = customValue;\n          continue;\n      }\n      warn(`Bad value, for key \"${key}\", in Info: ${value}.`);\n    }\n    return shadow(this, \"documentInfo\", docInfo);\n  }\n  get fingerprints() {\n    function validate(data) {\n      return typeof data === \"string\" && data.length > 0 && data !== EMPTY_FINGERPRINT;\n    }\n    function hexString(hash) {\n      const buf = [];\n      for (const num of hash) {\n        const hex = num.toString(16);\n        buf.push(hex.padStart(2, \"0\"));\n      }\n      return buf.join(\"\");\n    }\n    const idArray = this.xref.trailer.get(\"ID\");\n    let hashOriginal, hashModified;\n    if (Array.isArray(idArray) && validate(idArray[0])) {\n      hashOriginal = stringToBytes(idArray[0]);\n      if (idArray[1] !== idArray[0] && validate(idArray[1])) {\n        hashModified = stringToBytes(idArray[1]);\n      }\n    } else {\n      hashOriginal = calculateMD5(this.stream.getByteRange(0, FINGERPRINT_FIRST_BYTES), 0, FINGERPRINT_FIRST_BYTES);\n    }\n    return shadow(this, \"fingerprints\", [hexString(hashOriginal), hashModified ? hexString(hashModified) : null]);\n  }\n  async _getLinearizationPage(pageIndex) {\n    const {\n      catalog,\n      linearization,\n      xref\n    } = this;\n    const ref = Ref.get(linearization.objectNumberFirst, 0);\n    try {\n      const obj = await xref.fetchAsync(ref);\n      if (obj instanceof Dict) {\n        let type = obj.getRaw(\"Type\");\n        if (type instanceof Ref) {\n          type = await xref.fetchAsync(type);\n        }\n        if (isName(type, \"Page\") || !obj.has(\"Type\") && !obj.has(\"Kids\")) {\n          if (!catalog.pageKidsCountCache.has(ref)) {\n            catalog.pageKidsCountCache.put(ref, 1);\n          }\n          if (!catalog.pageIndexCache.has(ref)) {\n            catalog.pageIndexCache.put(ref, 0);\n          }\n          return [obj, ref];\n        }\n      }\n      throw new FormatError(\"The Linearization dictionary doesn't point to a valid Page dictionary.\");\n    } catch (reason) {\n      warn(`_getLinearizationPage: \"${reason.message}\".`);\n      return catalog.getPageDict(pageIndex);\n    }\n  }\n  getPage(pageIndex) {\n    const cachedPromise = this._pagePromises.get(pageIndex);\n    if (cachedPromise) {\n      return cachedPromise;\n    }\n    const {\n      catalog,\n      linearization,\n      xfaFactory\n    } = this;\n    let promise;\n    if (xfaFactory) {\n      promise = Promise.resolve([Dict.empty, null]);\n    } else if (linearization?.pageFirst === pageIndex) {\n      promise = this._getLinearizationPage(pageIndex);\n    } else {\n      promise = catalog.getPageDict(pageIndex);\n    }\n    promise = promise.then(([pageDict, ref]) => {\n      return new Page({\n        pdfManager: this.pdfManager,\n        xref: this.xref,\n        pageIndex,\n        pageDict,\n        ref,\n        globalIdFactory: this._globalIdFactory,\n        fontCache: catalog.fontCache,\n        builtInCMapCache: catalog.builtInCMapCache,\n        standardFontDataCache: catalog.standardFontDataCache,\n        globalImageCache: catalog.globalImageCache,\n        systemFontCache: catalog.systemFontCache,\n        nonBlendModesSet: catalog.nonBlendModesSet,\n        xfaFactory\n      });\n    });\n    this._pagePromises.set(pageIndex, promise);\n    return promise;\n  }\n  async checkFirstPage(recoveryMode = false) {\n    if (recoveryMode) {\n      return;\n    }\n    try {\n      await this.getPage(0);\n    } catch (reason) {\n      if (reason instanceof XRefEntryException) {\n        this._pagePromises.delete(0);\n        await this.cleanup();\n        throw new XRefParseException();\n      }\n    }\n  }\n  async checkLastPage(recoveryMode = false) {\n    const {\n      catalog,\n      pdfManager\n    } = this;\n    catalog.setActualNumPages();\n    let numPages;\n    try {\n      await Promise.all([pdfManager.ensureDoc(\"xfaFactory\"), pdfManager.ensureDoc(\"linearization\"), pdfManager.ensureCatalog(\"numPages\")]);\n      if (this.xfaFactory) {\n        return;\n      } else if (this.linearization) {\n        numPages = this.linearization.numPages;\n      } else {\n        numPages = catalog.numPages;\n      }\n      if (!Number.isInteger(numPages)) {\n        throw new FormatError(\"Page count is not an integer.\");\n      } else if (numPages <= 1) {\n        return;\n      }\n      await this.getPage(numPages - 1);\n    } catch (reason) {\n      this._pagePromises.delete(numPages - 1);\n      await this.cleanup();\n      if (reason instanceof XRefEntryException && !recoveryMode) {\n        throw new XRefParseException();\n      }\n      warn(`checkLastPage - invalid /Pages tree /Count: ${numPages}.`);\n      let pagesTree;\n      try {\n        pagesTree = await catalog.getAllPageDicts(recoveryMode);\n      } catch (reasonAll) {\n        if (reasonAll instanceof XRefEntryException && !recoveryMode) {\n          throw new XRefParseException();\n        }\n        catalog.setActualNumPages(1);\n        return;\n      }\n      for (const [pageIndex, [pageDict, ref]] of pagesTree) {\n        let promise;\n        if (pageDict instanceof Error) {\n          promise = Promise.reject(pageDict);\n          promise.catch(() => {});\n        } else {\n          promise = Promise.resolve(new Page({\n            pdfManager,\n            xref: this.xref,\n            pageIndex,\n            pageDict,\n            ref,\n            globalIdFactory: this._globalIdFactory,\n            fontCache: catalog.fontCache,\n            builtInCMapCache: catalog.builtInCMapCache,\n            standardFontDataCache: catalog.standardFontDataCache,\n            globalImageCache: catalog.globalImageCache,\n            systemFontCache: catalog.systemFontCache,\n            nonBlendModesSet: catalog.nonBlendModesSet,\n            xfaFactory: null\n          }));\n        }\n        this._pagePromises.set(pageIndex, promise);\n      }\n      catalog.setActualNumPages(pagesTree.size);\n    }\n  }\n  fontFallback(id, handler) {\n    return this.catalog.fontFallback(id, handler);\n  }\n  async cleanup(manuallyTriggered = false) {\n    return this.catalog ? this.catalog.cleanup(manuallyTriggered) : clearGlobalCaches();\n  }\n  async #collectFieldObjects(name, fieldRef, promises, annotationGlobals, visitedRefs) {\n    const {\n      xref\n    } = this;\n    if (!(fieldRef instanceof Ref) || visitedRefs.has(fieldRef)) {\n      return;\n    }\n    visitedRefs.put(fieldRef);\n    const field = await xref.fetchAsync(fieldRef);\n    if (!(field instanceof Dict)) {\n      return;\n    }\n    if (field.has(\"T\")) {\n      const partName = stringToPDFString(await field.getAsync(\"T\"));\n      name = name === \"\" ? partName : `${name}.${partName}`;\n    } else {\n      let obj = field;\n      while (true) {\n        obj = obj.getRaw(\"Parent\");\n        if (obj instanceof Ref) {\n          if (visitedRefs.has(obj)) {\n            break;\n          }\n          obj = await xref.fetchAsync(obj);\n        }\n        if (!(obj instanceof Dict)) {\n          break;\n        }\n        if (obj.has(\"T\")) {\n          const partName = stringToPDFString(await obj.getAsync(\"T\"));\n          name = name === \"\" ? partName : `${name}.${partName}`;\n          break;\n        }\n      }\n    }\n    if (!promises.has(name)) {\n      promises.set(name, []);\n    }\n    promises.get(name).push(AnnotationFactory.create(xref, fieldRef, annotationGlobals, null, true, null).then(annotation => annotation?.getFieldObject()).catch(function (reason) {\n      warn(`#collectFieldObjects: \"${reason}\".`);\n      return null;\n    }));\n    if (!field.has(\"Kids\")) {\n      return;\n    }\n    const kids = await field.getAsync(\"Kids\");\n    if (Array.isArray(kids)) {\n      for (const kid of kids) {\n        await this.#collectFieldObjects(name, kid, promises, annotationGlobals, visitedRefs);\n      }\n    }\n  }\n  get fieldObjects() {\n    if (!this.formInfo.hasFields) {\n      return shadow(this, \"fieldObjects\", Promise.resolve(null));\n    }\n    const promise = Promise.all([this.pdfManager.ensureDoc(\"annotationGlobals\"), this.pdfManager.ensureCatalog(\"acroForm\")]).then(async ([annotationGlobals, acroForm]) => {\n      if (!annotationGlobals) {\n        return null;\n      }\n      const visitedRefs = new RefSet();\n      const allFields = Object.create(null);\n      const fieldPromises = new Map();\n      for (const fieldRef of await acroForm.getAsync(\"Fields\")) {\n        await this.#collectFieldObjects(\"\", fieldRef, fieldPromises, annotationGlobals, visitedRefs);\n      }\n      const allPromises = [];\n      for (const [name, promises] of fieldPromises) {\n        allPromises.push(Promise.all(promises).then(fields => {\n          fields = fields.filter(field => !!field);\n          if (fields.length > 0) {\n            allFields[name] = fields;\n          }\n        }));\n      }\n      await Promise.all(allPromises);\n      return allFields;\n    });\n    return shadow(this, \"fieldObjects\", promise);\n  }\n  get hasJSActions() {\n    const promise = this.pdfManager.ensureDoc(\"_parseHasJSActions\");\n    return shadow(this, \"hasJSActions\", promise);\n  }\n  async _parseHasJSActions() {\n    const [catalogJsActions, fieldObjects] = await Promise.all([this.pdfManager.ensureCatalog(\"jsActions\"), this.pdfManager.ensureDoc(\"fieldObjects\")]);\n    if (catalogJsActions) {\n      return true;\n    }\n    if (fieldObjects) {\n      return Object.values(fieldObjects).some(fieldObject => fieldObject.some(object => object.actions !== null));\n    }\n    return false;\n  }\n  get calculationOrderIds() {\n    const acroForm = this.catalog.acroForm;\n    if (!acroForm?.has(\"CO\")) {\n      return shadow(this, \"calculationOrderIds\", null);\n    }\n    const calculationOrder = acroForm.get(\"CO\");\n    if (!Array.isArray(calculationOrder) || calculationOrder.length === 0) {\n      return shadow(this, \"calculationOrderIds\", null);\n    }\n    const ids = [];\n    for (const id of calculationOrder) {\n      if (id instanceof Ref) {\n        ids.push(id.toString());\n      }\n    }\n    if (ids.length === 0) {\n      return shadow(this, \"calculationOrderIds\", null);\n    }\n    return shadow(this, \"calculationOrderIds\", ids);\n  }\n  get annotationGlobals() {\n    return shadow(this, \"annotationGlobals\", AnnotationFactory.createGlobals(this.pdfManager));\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/pdf_manager.js\n\n\n\n\n\nfunction parseDocBaseUrl(url) {\n  if (url) {\n    const absoluteUrl = createValidAbsoluteUrl(url);\n    if (absoluteUrl) {\n      return absoluteUrl.href;\n    }\n    warn(`Invalid absolute docBaseUrl: \"${url}\".`);\n  }\n  return null;\n}\nclass BasePdfManager {\n  constructor(args) {\n    if (this.constructor === BasePdfManager) {\n      unreachable(\"Cannot initialize BasePdfManager.\");\n    }\n    this._docBaseUrl = parseDocBaseUrl(args.docBaseUrl);\n    this._docId = args.docId;\n    this._password = args.password;\n    this.enableXfa = args.enableXfa;\n    args.evaluatorOptions.isOffscreenCanvasSupported &&= FeatureTest.isOffscreenCanvasSupported;\n    this.evaluatorOptions = args.evaluatorOptions;\n  }\n  get docId() {\n    return this._docId;\n  }\n  get password() {\n    return this._password;\n  }\n  get docBaseUrl() {\n    return this._docBaseUrl;\n  }\n  get catalog() {\n    return this.pdfDocument.catalog;\n  }\n  ensureDoc(prop, args) {\n    return this.ensure(this.pdfDocument, prop, args);\n  }\n  ensureXRef(prop, args) {\n    return this.ensure(this.pdfDocument.xref, prop, args);\n  }\n  ensureCatalog(prop, args) {\n    return this.ensure(this.pdfDocument.catalog, prop, args);\n  }\n  getPage(pageIndex) {\n    return this.pdfDocument.getPage(pageIndex);\n  }\n  fontFallback(id, handler) {\n    return this.pdfDocument.fontFallback(id, handler);\n  }\n  loadXfaFonts(handler, task) {\n    return this.pdfDocument.loadXfaFonts(handler, task);\n  }\n  loadXfaImages() {\n    return this.pdfDocument.loadXfaImages();\n  }\n  serializeXfaData(annotationStorage) {\n    return this.pdfDocument.serializeXfaData(annotationStorage);\n  }\n  cleanup(manuallyTriggered = false) {\n    return this.pdfDocument.cleanup(manuallyTriggered);\n  }\n  async ensure(obj, prop, args) {\n    unreachable(\"Abstract method `ensure` called\");\n  }\n  requestRange(begin, end) {\n    unreachable(\"Abstract method `requestRange` called\");\n  }\n  requestLoadedStream(noFetch = false) {\n    unreachable(\"Abstract method `requestLoadedStream` called\");\n  }\n  sendProgressiveData(chunk) {\n    unreachable(\"Abstract method `sendProgressiveData` called\");\n  }\n  updatePassword(password) {\n    this._password = password;\n  }\n  terminate(reason) {\n    unreachable(\"Abstract method `terminate` called\");\n  }\n}\nclass LocalPdfManager extends BasePdfManager {\n  constructor(args) {\n    super(args);\n    const stream = new Stream(args.source);\n    this.pdfDocument = new PDFDocument(this, stream);\n    this._loadedStreamPromise = Promise.resolve(stream);\n  }\n  async ensure(obj, prop, args) {\n    const value = obj[prop];\n    if (typeof value === \"function\") {\n      return value.apply(obj, args);\n    }\n    return value;\n  }\n  requestRange(begin, end) {\n    return Promise.resolve();\n  }\n  requestLoadedStream(noFetch = false) {\n    return this._loadedStreamPromise;\n  }\n  terminate(reason) {}\n}\nclass NetworkPdfManager extends BasePdfManager {\n  constructor(args) {\n    super(args);\n    this.streamManager = new ChunkedStreamManager(args.source, {\n      msgHandler: args.handler,\n      length: args.length,\n      disableAutoFetch: args.disableAutoFetch,\n      rangeChunkSize: args.rangeChunkSize\n    });\n    this.pdfDocument = new PDFDocument(this, this.streamManager.getStream());\n  }\n  async ensure(obj, prop, args) {\n    try {\n      const value = obj[prop];\n      if (typeof value === \"function\") {\n        return value.apply(obj, args);\n      }\n      return value;\n    } catch (ex) {\n      if (!(ex instanceof MissingDataException)) {\n        throw ex;\n      }\n      await this.requestRange(ex.begin, ex.end);\n      return this.ensure(obj, prop, args);\n    }\n  }\n  requestRange(begin, end) {\n    return this.streamManager.requestRange(begin, end);\n  }\n  requestLoadedStream(noFetch = false) {\n    return this.streamManager.requestAllChunks(noFetch);\n  }\n  sendProgressiveData(chunk) {\n    this.streamManager.onReceiveData({\n      chunk\n    });\n  }\n  terminate(reason) {\n    this.streamManager.abort(reason);\n  }\n}\n\n;// CONCATENATED MODULE: ./src/shared/message_handler.js\n\nconst CallbackKind = {\n  UNKNOWN: 0,\n  DATA: 1,\n  ERROR: 2\n};\nconst StreamKind = {\n  UNKNOWN: 0,\n  CANCEL: 1,\n  CANCEL_COMPLETE: 2,\n  CLOSE: 3,\n  ENQUEUE: 4,\n  ERROR: 5,\n  PULL: 6,\n  PULL_COMPLETE: 7,\n  START_COMPLETE: 8\n};\nfunction wrapReason(reason) {\n  if (!(reason instanceof Error || typeof reason === \"object\" && reason !== null)) {\n    unreachable('wrapReason: Expected \"reason\" to be a (possibly cloned) Error.');\n  }\n  switch (reason.name) {\n    case \"AbortException\":\n      return new AbortException(reason.message);\n    case \"MissingPDFException\":\n      return new MissingPDFException(reason.message);\n    case \"PasswordException\":\n      return new PasswordException(reason.message, reason.code);\n    case \"UnexpectedResponseException\":\n      return new UnexpectedResponseException(reason.message, reason.status);\n    case \"UnknownErrorException\":\n      return new UnknownErrorException(reason.message, reason.details);\n    default:\n      return new UnknownErrorException(reason.message, reason.toString());\n  }\n}\nclass MessageHandler {\n  constructor(sourceName, targetName, comObj) {\n    this.sourceName = sourceName;\n    this.targetName = targetName;\n    this.comObj = comObj;\n    this.callbackId = 1;\n    this.streamId = 1;\n    this.streamSinks = Object.create(null);\n    this.streamControllers = Object.create(null);\n    this.callbackCapabilities = Object.create(null);\n    this.actionHandler = Object.create(null);\n    this._onComObjOnMessage = event => {\n      const data = event.data;\n      if (data.targetName !== this.sourceName) {\n        return;\n      }\n      if (data.stream) {\n        this.#processStreamMessage(data);\n        return;\n      }\n      if (data.callback) {\n        const callbackId = data.callbackId;\n        const capability = this.callbackCapabilities[callbackId];\n        if (!capability) {\n          throw new Error(`Cannot resolve callback ${callbackId}`);\n        }\n        delete this.callbackCapabilities[callbackId];\n        if (data.callback === CallbackKind.DATA) {\n          capability.resolve(data.data);\n        } else if (data.callback === CallbackKind.ERROR) {\n          capability.reject(wrapReason(data.reason));\n        } else {\n          throw new Error(\"Unexpected callback case\");\n        }\n        return;\n      }\n      const action = this.actionHandler[data.action];\n      if (!action) {\n        throw new Error(`Unknown action from worker: ${data.action}`);\n      }\n      if (data.callbackId) {\n        const cbSourceName = this.sourceName;\n        const cbTargetName = data.sourceName;\n        new Promise(function (resolve) {\n          resolve(action(data.data));\n        }).then(function (result) {\n          comObj.postMessage({\n            sourceName: cbSourceName,\n            targetName: cbTargetName,\n            callback: CallbackKind.DATA,\n            callbackId: data.callbackId,\n            data: result\n          });\n        }, function (reason) {\n          comObj.postMessage({\n            sourceName: cbSourceName,\n            targetName: cbTargetName,\n            callback: CallbackKind.ERROR,\n            callbackId: data.callbackId,\n            reason: wrapReason(reason)\n          });\n        });\n        return;\n      }\n      if (data.streamId) {\n        this.#createStreamSink(data);\n        return;\n      }\n      action(data.data);\n    };\n    comObj.addEventListener(\"message\", this._onComObjOnMessage);\n  }\n  on(actionName, handler) {\n    const ah = this.actionHandler;\n    if (ah[actionName]) {\n      throw new Error(`There is already an actionName called \"${actionName}\"`);\n    }\n    ah[actionName] = handler;\n  }\n  send(actionName, data, transfers) {\n    this.comObj.postMessage({\n      sourceName: this.sourceName,\n      targetName: this.targetName,\n      action: actionName,\n      data\n    }, transfers);\n  }\n  sendWithPromise(actionName, data, transfers) {\n    const callbackId = this.callbackId++;\n    const capability = Promise.withResolvers();\n    this.callbackCapabilities[callbackId] = capability;\n    try {\n      this.comObj.postMessage({\n        sourceName: this.sourceName,\n        targetName: this.targetName,\n        action: actionName,\n        callbackId,\n        data\n      }, transfers);\n    } catch (ex) {\n      capability.reject(ex);\n    }\n    return capability.promise;\n  }\n  sendWithStream(actionName, data, queueingStrategy, transfers) {\n    const streamId = this.streamId++,\n      sourceName = this.sourceName,\n      targetName = this.targetName,\n      comObj = this.comObj;\n    return new ReadableStream({\n      start: controller => {\n        const startCapability = Promise.withResolvers();\n        this.streamControllers[streamId] = {\n          controller,\n          startCall: startCapability,\n          pullCall: null,\n          cancelCall: null,\n          isClosed: false\n        };\n        comObj.postMessage({\n          sourceName,\n          targetName,\n          action: actionName,\n          streamId,\n          data,\n          desiredSize: controller.desiredSize\n        }, transfers);\n        return startCapability.promise;\n      },\n      pull: controller => {\n        const pullCapability = Promise.withResolvers();\n        this.streamControllers[streamId].pullCall = pullCapability;\n        comObj.postMessage({\n          sourceName,\n          targetName,\n          stream: StreamKind.PULL,\n          streamId,\n          desiredSize: controller.desiredSize\n        });\n        return pullCapability.promise;\n      },\n      cancel: reason => {\n        assert(reason instanceof Error, \"cancel must have a valid reason\");\n        const cancelCapability = Promise.withResolvers();\n        this.streamControllers[streamId].cancelCall = cancelCapability;\n        this.streamControllers[streamId].isClosed = true;\n        comObj.postMessage({\n          sourceName,\n          targetName,\n          stream: StreamKind.CANCEL,\n          streamId,\n          reason: wrapReason(reason)\n        });\n        return cancelCapability.promise;\n      }\n    }, queueingStrategy);\n  }\n  #createStreamSink(data) {\n    const streamId = data.streamId,\n      sourceName = this.sourceName,\n      targetName = data.sourceName,\n      comObj = this.comObj;\n    const self = this,\n      action = this.actionHandler[data.action];\n    const streamSink = {\n      enqueue(chunk, size = 1, transfers) {\n        if (this.isCancelled) {\n          return;\n        }\n        const lastDesiredSize = this.desiredSize;\n        this.desiredSize -= size;\n        if (lastDesiredSize > 0 && this.desiredSize <= 0) {\n          this.sinkCapability = Promise.withResolvers();\n          this.ready = this.sinkCapability.promise;\n        }\n        comObj.postMessage({\n          sourceName,\n          targetName,\n          stream: StreamKind.ENQUEUE,\n          streamId,\n          chunk\n        }, transfers);\n      },\n      close() {\n        if (this.isCancelled) {\n          return;\n        }\n        this.isCancelled = true;\n        comObj.postMessage({\n          sourceName,\n          targetName,\n          stream: StreamKind.CLOSE,\n          streamId\n        });\n        delete self.streamSinks[streamId];\n      },\n      error(reason) {\n        assert(reason instanceof Error, \"error must have a valid reason\");\n        if (this.isCancelled) {\n          return;\n        }\n        this.isCancelled = true;\n        comObj.postMessage({\n          sourceName,\n          targetName,\n          stream: StreamKind.ERROR,\n          streamId,\n          reason: wrapReason(reason)\n        });\n      },\n      sinkCapability: Promise.withResolvers(),\n      onPull: null,\n      onCancel: null,\n      isCancelled: false,\n      desiredSize: data.desiredSize,\n      ready: null\n    };\n    streamSink.sinkCapability.resolve();\n    streamSink.ready = streamSink.sinkCapability.promise;\n    this.streamSinks[streamId] = streamSink;\n    new Promise(function (resolve) {\n      resolve(action(data.data, streamSink));\n    }).then(function () {\n      comObj.postMessage({\n        sourceName,\n        targetName,\n        stream: StreamKind.START_COMPLETE,\n        streamId,\n        success: true\n      });\n    }, function (reason) {\n      comObj.postMessage({\n        sourceName,\n        targetName,\n        stream: StreamKind.START_COMPLETE,\n        streamId,\n        reason: wrapReason(reason)\n      });\n    });\n  }\n  #processStreamMessage(data) {\n    const streamId = data.streamId,\n      sourceName = this.sourceName,\n      targetName = data.sourceName,\n      comObj = this.comObj;\n    const streamController = this.streamControllers[streamId],\n      streamSink = this.streamSinks[streamId];\n    switch (data.stream) {\n      case StreamKind.START_COMPLETE:\n        if (data.success) {\n          streamController.startCall.resolve();\n        } else {\n          streamController.startCall.reject(wrapReason(data.reason));\n        }\n        break;\n      case StreamKind.PULL_COMPLETE:\n        if (data.success) {\n          streamController.pullCall.resolve();\n        } else {\n          streamController.pullCall.reject(wrapReason(data.reason));\n        }\n        break;\n      case StreamKind.PULL:\n        if (!streamSink) {\n          comObj.postMessage({\n            sourceName,\n            targetName,\n            stream: StreamKind.PULL_COMPLETE,\n            streamId,\n            success: true\n          });\n          break;\n        }\n        if (streamSink.desiredSize <= 0 && data.desiredSize > 0) {\n          streamSink.sinkCapability.resolve();\n        }\n        streamSink.desiredSize = data.desiredSize;\n        new Promise(function (resolve) {\n          resolve(streamSink.onPull?.());\n        }).then(function () {\n          comObj.postMessage({\n            sourceName,\n            targetName,\n            stream: StreamKind.PULL_COMPLETE,\n            streamId,\n            success: true\n          });\n        }, function (reason) {\n          comObj.postMessage({\n            sourceName,\n            targetName,\n            stream: StreamKind.PULL_COMPLETE,\n            streamId,\n            reason: wrapReason(reason)\n          });\n        });\n        break;\n      case StreamKind.ENQUEUE:\n        assert(streamController, \"enqueue should have stream controller\");\n        if (streamController.isClosed) {\n          break;\n        }\n        streamController.controller.enqueue(data.chunk);\n        break;\n      case StreamKind.CLOSE:\n        assert(streamController, \"close should have stream controller\");\n        if (streamController.isClosed) {\n          break;\n        }\n        streamController.isClosed = true;\n        streamController.controller.close();\n        this.#deleteStreamController(streamController, streamId);\n        break;\n      case StreamKind.ERROR:\n        assert(streamController, \"error should have stream controller\");\n        streamController.controller.error(wrapReason(data.reason));\n        this.#deleteStreamController(streamController, streamId);\n        break;\n      case StreamKind.CANCEL_COMPLETE:\n        if (data.success) {\n          streamController.cancelCall.resolve();\n        } else {\n          streamController.cancelCall.reject(wrapReason(data.reason));\n        }\n        this.#deleteStreamController(streamController, streamId);\n        break;\n      case StreamKind.CANCEL:\n        if (!streamSink) {\n          break;\n        }\n        new Promise(function (resolve) {\n          resolve(streamSink.onCancel?.(wrapReason(data.reason)));\n        }).then(function () {\n          comObj.postMessage({\n            sourceName,\n            targetName,\n            stream: StreamKind.CANCEL_COMPLETE,\n            streamId,\n            success: true\n          });\n        }, function (reason) {\n          comObj.postMessage({\n            sourceName,\n            targetName,\n            stream: StreamKind.CANCEL_COMPLETE,\n            streamId,\n            reason: wrapReason(reason)\n          });\n        });\n        streamSink.sinkCapability.reject(wrapReason(data.reason));\n        streamSink.isCancelled = true;\n        delete this.streamSinks[streamId];\n        break;\n      default:\n        throw new Error(\"Unexpected stream case\");\n    }\n  }\n  async #deleteStreamController(streamController, streamId) {\n    await Promise.allSettled([streamController.startCall?.promise, streamController.pullCall?.promise, streamController.cancelCall?.promise]);\n    delete this.streamControllers[streamId];\n  }\n  destroy() {\n    this.comObj.removeEventListener(\"message\", this._onComObjOnMessage);\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/worker_stream.js\n\nclass PDFWorkerStream {\n  constructor(msgHandler) {\n    this._msgHandler = msgHandler;\n    this._contentLength = null;\n    this._fullRequestReader = null;\n    this._rangeRequestReaders = [];\n  }\n  getFullReader() {\n    assert(!this._fullRequestReader, \"PDFWorkerStream.getFullReader can only be called once.\");\n    this._fullRequestReader = new PDFWorkerStreamReader(this._msgHandler);\n    return this._fullRequestReader;\n  }\n  getRangeReader(begin, end) {\n    const reader = new PDFWorkerStreamRangeReader(begin, end, this._msgHandler);\n    this._rangeRequestReaders.push(reader);\n    return reader;\n  }\n  cancelAllRequests(reason) {\n    this._fullRequestReader?.cancel(reason);\n    for (const reader of this._rangeRequestReaders.slice(0)) {\n      reader.cancel(reason);\n    }\n  }\n}\nclass PDFWorkerStreamReader {\n  constructor(msgHandler) {\n    this._msgHandler = msgHandler;\n    this.onProgress = null;\n    this._contentLength = null;\n    this._isRangeSupported = false;\n    this._isStreamingSupported = false;\n    const readableStream = this._msgHandler.sendWithStream(\"GetReader\");\n    this._reader = readableStream.getReader();\n    this._headersReady = this._msgHandler.sendWithPromise(\"ReaderHeadersReady\").then(data => {\n      this._isStreamingSupported = data.isStreamingSupported;\n      this._isRangeSupported = data.isRangeSupported;\n      this._contentLength = data.contentLength;\n    });\n  }\n  get headersReady() {\n    return this._headersReady;\n  }\n  get contentLength() {\n    return this._contentLength;\n  }\n  get isStreamingSupported() {\n    return this._isStreamingSupported;\n  }\n  get isRangeSupported() {\n    return this._isRangeSupported;\n  }\n  async read() {\n    const {\n      value,\n      done\n    } = await this._reader.read();\n    if (done) {\n      return {\n        value: undefined,\n        done: true\n      };\n    }\n    return {\n      value: value.buffer,\n      done: false\n    };\n  }\n  cancel(reason) {\n    this._reader.cancel(reason);\n  }\n}\nclass PDFWorkerStreamRangeReader {\n  constructor(begin, end, msgHandler) {\n    this._msgHandler = msgHandler;\n    this.onProgress = null;\n    const readableStream = this._msgHandler.sendWithStream(\"GetRangeReader\", {\n      begin,\n      end\n    });\n    this._reader = readableStream.getReader();\n  }\n  get isStreamingSupported() {\n    return false;\n  }\n  async read() {\n    const {\n      value,\n      done\n    } = await this._reader.read();\n    if (done) {\n      return {\n        value: undefined,\n        done: true\n      };\n    }\n    return {\n      value: value.buffer,\n      done: false\n    };\n  }\n  cancel(reason) {\n    this._reader.cancel(reason);\n  }\n}\n\n;// CONCATENATED MODULE: ./src/core/worker.js\n\n\n\n\n\n\n\n\n\n\nclass WorkerTask {\n  constructor(name) {\n    this.name = name;\n    this.terminated = false;\n    this._capability = Promise.withResolvers();\n  }\n  get finished() {\n    return this._capability.promise;\n  }\n  finish() {\n    this._capability.resolve();\n  }\n  terminate() {\n    this.terminated = true;\n  }\n  ensureNotTerminated() {\n    if (this.terminated) {\n      throw new Error(\"Worker task was terminated\");\n    }\n  }\n}\nclass WorkerMessageHandler {\n  static setup(handler, port) {\n    let testMessageProcessed = false;\n    handler.on(\"test\", function (data) {\n      if (testMessageProcessed) {\n        return;\n      }\n      testMessageProcessed = true;\n      handler.send(\"test\", data instanceof Uint8Array);\n    });\n    handler.on(\"configure\", function (data) {\n      setVerbosityLevel(data.verbosity);\n    });\n    handler.on(\"GetDocRequest\", function (data) {\n      return WorkerMessageHandler.createDocumentHandler(data, port);\n    });\n  }\n  static createDocumentHandler(docParams, port) {\n    let pdfManager;\n    let terminated = false;\n    let cancelXHRs = null;\n    const WorkerTasks = new Set();\n    const verbosity = getVerbosityLevel();\n    const {\n      docId,\n      apiVersion\n    } = docParams;\n    const workerVersion = \"4.2.67\";\n    if (apiVersion !== workerVersion) {\n      throw new Error(`The API version \"${apiVersion}\" does not match ` + `the Worker version \"${workerVersion}\".`);\n    }\n    const enumerableProperties = [];\n    for (const property in []) {\n      enumerableProperties.push(property);\n    }\n    if (enumerableProperties.length) {\n      throw new Error(\"The `Array.prototype` contains unexpected enumerable properties: \" + enumerableProperties.join(\", \") + \"; thus breaking e.g. `for...in` iteration of `Array`s.\");\n    }\n    const workerHandlerName = docId + \"_worker\";\n    let handler = new MessageHandler(workerHandlerName, docId, port);\n    function ensureNotTerminated() {\n      if (terminated) {\n        throw new Error(\"Worker was terminated\");\n      }\n    }\n    function startWorkerTask(task) {\n      WorkerTasks.add(task);\n    }\n    function finishWorkerTask(task) {\n      task.finish();\n      WorkerTasks.delete(task);\n    }\n    async function loadDocument(recoveryMode) {\n      await pdfManager.ensureDoc(\"checkHeader\");\n      await pdfManager.ensureDoc(\"parseStartXRef\");\n      await pdfManager.ensureDoc(\"parse\", [recoveryMode]);\n      await pdfManager.ensureDoc(\"checkFirstPage\", [recoveryMode]);\n      await pdfManager.ensureDoc(\"checkLastPage\", [recoveryMode]);\n      const isPureXfa = await pdfManager.ensureDoc(\"isPureXfa\");\n      if (isPureXfa) {\n        const task = new WorkerTask(\"loadXfaFonts\");\n        startWorkerTask(task);\n        await Promise.all([pdfManager.loadXfaFonts(handler, task).catch(reason => {}).then(() => finishWorkerTask(task)), pdfManager.loadXfaImages()]);\n      }\n      const [numPages, fingerprints] = await Promise.all([pdfManager.ensureDoc(\"numPages\"), pdfManager.ensureDoc(\"fingerprints\")]);\n      const htmlForXfa = isPureXfa ? await pdfManager.ensureDoc(\"htmlForXfa\") : null;\n      return {\n        numPages,\n        fingerprints,\n        htmlForXfa\n      };\n    }\n    function getPdfManager({\n      data,\n      password,\n      disableAutoFetch,\n      rangeChunkSize,\n      length,\n      docBaseUrl,\n      enableXfa,\n      evaluatorOptions\n    }) {\n      const pdfManagerArgs = {\n        source: null,\n        disableAutoFetch,\n        docBaseUrl,\n        docId,\n        enableXfa,\n        evaluatorOptions,\n        handler,\n        length,\n        password,\n        rangeChunkSize\n      };\n      const pdfManagerCapability = Promise.withResolvers();\n      let newPdfManager;\n      if (data) {\n        try {\n          pdfManagerArgs.source = data;\n          newPdfManager = new LocalPdfManager(pdfManagerArgs);\n          pdfManagerCapability.resolve(newPdfManager);\n        } catch (ex) {\n          pdfManagerCapability.reject(ex);\n        }\n        return pdfManagerCapability.promise;\n      }\n      let pdfStream,\n        cachedChunks = [];\n      try {\n        pdfStream = new PDFWorkerStream(handler);\n      } catch (ex) {\n        pdfManagerCapability.reject(ex);\n        return pdfManagerCapability.promise;\n      }\n      const fullRequest = pdfStream.getFullReader();\n      fullRequest.headersReady.then(function () {\n        if (!fullRequest.isRangeSupported) {\n          return;\n        }\n        pdfManagerArgs.source = pdfStream;\n        pdfManagerArgs.length = fullRequest.contentLength;\n        pdfManagerArgs.disableAutoFetch ||= fullRequest.isStreamingSupported;\n        newPdfManager = new NetworkPdfManager(pdfManagerArgs);\n        for (const chunk of cachedChunks) {\n          newPdfManager.sendProgressiveData(chunk);\n        }\n        cachedChunks = [];\n        pdfManagerCapability.resolve(newPdfManager);\n        cancelXHRs = null;\n      }).catch(function (reason) {\n        pdfManagerCapability.reject(reason);\n        cancelXHRs = null;\n      });\n      let loaded = 0;\n      const flushChunks = function () {\n        const pdfFile = arrayBuffersToBytes(cachedChunks);\n        if (length && pdfFile.length !== length) {\n          warn(\"reported HTTP length is different from actual\");\n        }\n        try {\n          pdfManagerArgs.source = pdfFile;\n          newPdfManager = new LocalPdfManager(pdfManagerArgs);\n          pdfManagerCapability.resolve(newPdfManager);\n        } catch (ex) {\n          pdfManagerCapability.reject(ex);\n        }\n        cachedChunks = [];\n      };\n      new Promise(function (resolve, reject) {\n        const readChunk = function ({\n          value,\n          done\n        }) {\n          try {\n            ensureNotTerminated();\n            if (done) {\n              if (!newPdfManager) {\n                flushChunks();\n              }\n              cancelXHRs = null;\n              return;\n            }\n            loaded += value.byteLength;\n            if (!fullRequest.isStreamingSupported) {\n              handler.send(\"DocProgress\", {\n                loaded,\n                total: Math.max(loaded, fullRequest.contentLength || 0)\n              });\n            }\n            if (newPdfManager) {\n              newPdfManager.sendProgressiveData(value);\n            } else {\n              cachedChunks.push(value);\n            }\n            fullRequest.read().then(readChunk, reject);\n          } catch (e) {\n            reject(e);\n          }\n        };\n        fullRequest.read().then(readChunk, reject);\n      }).catch(function (e) {\n        pdfManagerCapability.reject(e);\n        cancelXHRs = null;\n      });\n      cancelXHRs = function (reason) {\n        pdfStream.cancelAllRequests(reason);\n      };\n      return pdfManagerCapability.promise;\n    }\n    function setupDoc(data) {\n      function onSuccess(doc) {\n        ensureNotTerminated();\n        handler.send(\"GetDoc\", {\n          pdfInfo: doc\n        });\n      }\n      function onFailure(ex) {\n        ensureNotTerminated();\n        if (ex instanceof PasswordException) {\n          const task = new WorkerTask(`PasswordException: response ${ex.code}`);\n          startWorkerTask(task);\n          handler.sendWithPromise(\"PasswordRequest\", ex).then(function ({\n            password\n          }) {\n            finishWorkerTask(task);\n            pdfManager.updatePassword(password);\n            pdfManagerReady();\n          }).catch(function () {\n            finishWorkerTask(task);\n            handler.send(\"DocException\", ex);\n          });\n        } else if (ex instanceof InvalidPDFException || ex instanceof MissingPDFException || ex instanceof UnexpectedResponseException || ex instanceof UnknownErrorException) {\n          handler.send(\"DocException\", ex);\n        } else {\n          handler.send(\"DocException\", new UnknownErrorException(ex.message, ex.toString()));\n        }\n      }\n      function pdfManagerReady() {\n        ensureNotTerminated();\n        loadDocument(false).then(onSuccess, function (reason) {\n          ensureNotTerminated();\n          if (!(reason instanceof XRefParseException)) {\n            onFailure(reason);\n            return;\n          }\n          pdfManager.requestLoadedStream().then(function () {\n            ensureNotTerminated();\n            loadDocument(true).then(onSuccess, onFailure);\n          });\n        });\n      }\n      ensureNotTerminated();\n      getPdfManager(data).then(function (newPdfManager) {\n        if (terminated) {\n          newPdfManager.terminate(new AbortException(\"Worker was terminated.\"));\n          throw new Error(\"Worker was terminated\");\n        }\n        pdfManager = newPdfManager;\n        pdfManager.requestLoadedStream(true).then(stream => {\n          handler.send(\"DataLoaded\", {\n            length: stream.bytes.byteLength\n          });\n        });\n      }).then(pdfManagerReady, onFailure);\n    }\n    handler.on(\"GetPage\", function (data) {\n      return pdfManager.getPage(data.pageIndex).then(function (page) {\n        return Promise.all([pdfManager.ensure(page, \"rotate\"), pdfManager.ensure(page, \"ref\"), pdfManager.ensure(page, \"userUnit\"), pdfManager.ensure(page, \"view\")]).then(function ([rotate, ref, userUnit, view]) {\n          return {\n            rotate,\n            ref,\n            refStr: ref?.toString() ?? null,\n            userUnit,\n            view\n          };\n        });\n      });\n    });\n    handler.on(\"GetPageIndex\", function (data) {\n      const pageRef = Ref.get(data.num, data.gen);\n      return pdfManager.ensureCatalog(\"getPageIndex\", [pageRef]);\n    });\n    handler.on(\"GetDestinations\", function (data) {\n      return pdfManager.ensureCatalog(\"destinations\");\n    });\n    handler.on(\"GetDestination\", function (data) {\n      return pdfManager.ensureCatalog(\"getDestination\", [data.id]);\n    });\n    handler.on(\"GetPageLabels\", function (data) {\n      return pdfManager.ensureCatalog(\"pageLabels\");\n    });\n    handler.on(\"GetPageLayout\", function (data) {\n      return pdfManager.ensureCatalog(\"pageLayout\");\n    });\n    handler.on(\"GetPageMode\", function (data) {\n      return pdfManager.ensureCatalog(\"pageMode\");\n    });\n    handler.on(\"GetViewerPreferences\", function (data) {\n      return pdfManager.ensureCatalog(\"viewerPreferences\");\n    });\n    handler.on(\"GetOpenAction\", function (data) {\n      return pdfManager.ensureCatalog(\"openAction\");\n    });\n    handler.on(\"GetAttachments\", function (data) {\n      return pdfManager.ensureCatalog(\"attachments\");\n    });\n    handler.on(\"GetDocJSActions\", function (data) {\n      return pdfManager.ensureCatalog(\"jsActions\");\n    });\n    handler.on(\"GetPageJSActions\", function ({\n      pageIndex\n    }) {\n      return pdfManager.getPage(pageIndex).then(function (page) {\n        return pdfManager.ensure(page, \"jsActions\");\n      });\n    });\n    handler.on(\"GetOutline\", function (data) {\n      return pdfManager.ensureCatalog(\"documentOutline\");\n    });\n    handler.on(\"GetOptionalContentConfig\", function (data) {\n      return pdfManager.ensureCatalog(\"optionalContentConfig\");\n    });\n    handler.on(\"GetPermissions\", function (data) {\n      return pdfManager.ensureCatalog(\"permissions\");\n    });\n    handler.on(\"GetMetadata\", function (data) {\n      return Promise.all([pdfManager.ensureDoc(\"documentInfo\"), pdfManager.ensureCatalog(\"metadata\")]);\n    });\n    handler.on(\"GetMarkInfo\", function (data) {\n      return pdfManager.ensureCatalog(\"markInfo\");\n    });\n    handler.on(\"GetData\", function (data) {\n      return pdfManager.requestLoadedStream().then(function (stream) {\n        return stream.bytes;\n      });\n    });\n    handler.on(\"GetAnnotations\", function ({\n      pageIndex,\n      intent\n    }) {\n      return pdfManager.getPage(pageIndex).then(function (page) {\n        const task = new WorkerTask(`GetAnnotations: page ${pageIndex}`);\n        startWorkerTask(task);\n        return page.getAnnotationsData(handler, task, intent).then(data => {\n          finishWorkerTask(task);\n          return data;\n        }, reason => {\n          finishWorkerTask(task);\n          throw reason;\n        });\n      });\n    });\n    handler.on(\"GetFieldObjects\", function (data) {\n      return pdfManager.ensureDoc(\"fieldObjects\");\n    });\n    handler.on(\"HasJSActions\", function (data) {\n      return pdfManager.ensureDoc(\"hasJSActions\");\n    });\n    handler.on(\"GetCalculationOrderIds\", function (data) {\n      return pdfManager.ensureDoc(\"calculationOrderIds\");\n    });\n    handler.on(\"SaveDocument\", async function ({\n      isPureXfa,\n      numPages,\n      annotationStorage,\n      filename\n    }) {\n      const globalPromises = [pdfManager.requestLoadedStream(), pdfManager.ensureCatalog(\"acroForm\"), pdfManager.ensureCatalog(\"acroFormRef\"), pdfManager.ensureDoc(\"startXRef\"), pdfManager.ensureDoc(\"xref\"), pdfManager.ensureDoc(\"linearization\"), pdfManager.ensureCatalog(\"structTreeRoot\")];\n      const promises = [];\n      const newAnnotationsByPage = !isPureXfa ? getNewAnnotationsMap(annotationStorage) : null;\n      const [stream, acroForm, acroFormRef, startXRef, xref, linearization, _structTreeRoot] = await Promise.all(globalPromises);\n      const catalogRef = xref.trailer.getRaw(\"Root\") || null;\n      let structTreeRoot;\n      if (newAnnotationsByPage) {\n        if (!_structTreeRoot) {\n          if (await StructTreeRoot.canCreateStructureTree({\n            catalogRef,\n            pdfManager,\n            newAnnotationsByPage\n          })) {\n            structTreeRoot = null;\n          }\n        } else if (await _structTreeRoot.canUpdateStructTree({\n          pdfManager,\n          xref,\n          newAnnotationsByPage\n        })) {\n          structTreeRoot = _structTreeRoot;\n        }\n        const imagePromises = AnnotationFactory.generateImages(annotationStorage.values(), xref, pdfManager.evaluatorOptions.isOffscreenCanvasSupported);\n        const newAnnotationPromises = structTreeRoot === undefined ? promises : [];\n        for (const [pageIndex, annotations] of newAnnotationsByPage) {\n          newAnnotationPromises.push(pdfManager.getPage(pageIndex).then(page => {\n            const task = new WorkerTask(`Save (editor): page ${pageIndex}`);\n            return page.saveNewAnnotations(handler, task, annotations, imagePromises).finally(function () {\n              finishWorkerTask(task);\n            });\n          }));\n        }\n        if (structTreeRoot === null) {\n          promises.push(Promise.all(newAnnotationPromises).then(async newRefs => {\n            await StructTreeRoot.createStructureTree({\n              newAnnotationsByPage,\n              xref,\n              catalogRef,\n              pdfManager,\n              newRefs\n            });\n            return newRefs;\n          }));\n        } else if (structTreeRoot) {\n          promises.push(Promise.all(newAnnotationPromises).then(async newRefs => {\n            await structTreeRoot.updateStructureTree({\n              newAnnotationsByPage,\n              pdfManager,\n              newRefs\n            });\n            return newRefs;\n          }));\n        }\n      }\n      if (isPureXfa) {\n        promises.push(pdfManager.serializeXfaData(annotationStorage));\n      } else {\n        for (let pageIndex = 0; pageIndex < numPages; pageIndex++) {\n          promises.push(pdfManager.getPage(pageIndex).then(function (page) {\n            const task = new WorkerTask(`Save: page ${pageIndex}`);\n            return page.save(handler, task, annotationStorage).finally(function () {\n              finishWorkerTask(task);\n            });\n          }));\n        }\n      }\n      const refs = await Promise.all(promises);\n      let newRefs = [];\n      let xfaData = null;\n      if (isPureXfa) {\n        xfaData = refs[0];\n        if (!xfaData) {\n          return stream.bytes;\n        }\n      } else {\n        newRefs = refs.flat(2);\n        if (newRefs.length === 0) {\n          return stream.bytes;\n        }\n      }\n      const needAppearances = acroFormRef && acroForm instanceof Dict && newRefs.some(ref => ref.needAppearances);\n      const xfa = acroForm instanceof Dict && acroForm.get(\"XFA\") || null;\n      let xfaDatasetsRef = null;\n      let hasXfaDatasetsEntry = false;\n      if (Array.isArray(xfa)) {\n        for (let i = 0, ii = xfa.length; i < ii; i += 2) {\n          if (xfa[i] === \"datasets\") {\n            xfaDatasetsRef = xfa[i + 1];\n            hasXfaDatasetsEntry = true;\n          }\n        }\n        if (xfaDatasetsRef === null) {\n          xfaDatasetsRef = xref.getNewTemporaryRef();\n        }\n      } else if (xfa) {\n        warn(\"Unsupported XFA type.\");\n      }\n      let newXrefInfo = Object.create(null);\n      if (xref.trailer) {\n        const infoObj = Object.create(null);\n        const xrefInfo = xref.trailer.get(\"Info\") || null;\n        if (xrefInfo instanceof Dict) {\n          xrefInfo.forEach((key, value) => {\n            if (typeof value === \"string\") {\n              infoObj[key] = stringToPDFString(value);\n            }\n          });\n        }\n        newXrefInfo = {\n          rootRef: catalogRef,\n          encryptRef: xref.trailer.getRaw(\"Encrypt\") || null,\n          newRef: xref.getNewTemporaryRef(),\n          infoRef: xref.trailer.getRaw(\"Info\") || null,\n          info: infoObj,\n          fileIds: xref.trailer.get(\"ID\") || null,\n          startXRef: linearization ? startXRef : xref.lastXRefStreamPos ?? startXRef,\n          filename\n        };\n      }\n      return incrementalUpdate({\n        originalData: stream.bytes,\n        xrefInfo: newXrefInfo,\n        newRefs,\n        xref,\n        hasXfa: !!xfa,\n        xfaDatasetsRef,\n        hasXfaDatasetsEntry,\n        needAppearances,\n        acroFormRef,\n        acroForm,\n        xfaData,\n        useXrefStream: isDict(xref.topDict, \"XRef\")\n      }).finally(() => {\n        xref.resetNewTemporaryRef();\n      });\n    });\n    handler.on(\"GetOperatorList\", function (data, sink) {\n      const pageIndex = data.pageIndex;\n      pdfManager.getPage(pageIndex).then(function (page) {\n        const task = new WorkerTask(`GetOperatorList: page ${pageIndex}`);\n        startWorkerTask(task);\n        const start = verbosity >= VerbosityLevel.INFOS ? Date.now() : 0;\n        page.getOperatorList({\n          handler,\n          sink,\n          task,\n          intent: data.intent,\n          cacheKey: data.cacheKey,\n          annotationStorage: data.annotationStorage\n        }).then(function (operatorListInfo) {\n          finishWorkerTask(task);\n          if (start) {\n            info(`page=${pageIndex + 1} - getOperatorList: time=` + `${Date.now() - start}ms, len=${operatorListInfo.length}`);\n          }\n          sink.close();\n        }, function (reason) {\n          finishWorkerTask(task);\n          if (task.terminated) {\n            return;\n          }\n          sink.error(reason);\n        });\n      });\n    });\n    handler.on(\"GetTextContent\", function (data, sink) {\n      const {\n        pageIndex,\n        includeMarkedContent,\n        disableNormalization\n      } = data;\n      pdfManager.getPage(pageIndex).then(function (page) {\n        const task = new WorkerTask(\"GetTextContent: page \" + pageIndex);\n        startWorkerTask(task);\n        const start = verbosity >= VerbosityLevel.INFOS ? Date.now() : 0;\n        page.extractTextContent({\n          handler,\n          task,\n          sink,\n          includeMarkedContent,\n          disableNormalization\n        }).then(function () {\n          finishWorkerTask(task);\n          if (start) {\n            info(`page=${pageIndex + 1} - getTextContent: time=` + `${Date.now() - start}ms`);\n          }\n          sink.close();\n        }, function (reason) {\n          finishWorkerTask(task);\n          if (task.terminated) {\n            return;\n          }\n          sink.error(reason);\n        });\n      });\n    });\n    handler.on(\"GetStructTree\", function (data) {\n      return pdfManager.getPage(data.pageIndex).then(function (page) {\n        return pdfManager.ensure(page, \"getStructTree\");\n      });\n    });\n    handler.on(\"FontFallback\", function (data) {\n      return pdfManager.fontFallback(data.id, handler);\n    });\n    handler.on(\"Cleanup\", function (data) {\n      return pdfManager.cleanup(true);\n    });\n    handler.on(\"Terminate\", function (data) {\n      terminated = true;\n      const waitOn = [];\n      if (pdfManager) {\n        pdfManager.terminate(new AbortException(\"Worker was terminated.\"));\n        const cleanupPromise = pdfManager.cleanup();\n        waitOn.push(cleanupPromise);\n        pdfManager = null;\n      } else {\n        clearGlobalCaches();\n      }\n      if (cancelXHRs) {\n        cancelXHRs(new AbortException(\"Worker was terminated.\"));\n      }\n      for (const task of WorkerTasks) {\n        waitOn.push(task.finished);\n        task.terminate();\n      }\n      return Promise.all(waitOn).then(function () {\n        handler.destroy();\n        handler = null;\n      });\n    });\n    handler.on(\"Ready\", function (data) {\n      setupDoc(docParams);\n      docParams = null;\n    });\n    return workerHandlerName;\n  }\n  static initializeFromPort(port) {\n    const handler = new MessageHandler(\"worker\", \"main\", port);\n    WorkerMessageHandler.setup(handler, port);\n    handler.send(\"ready\", null);\n  }\n}\nfunction isMessagePort(maybePort) {\n  return typeof maybePort.postMessage === \"function\" && \"onmessage\" in maybePort;\n}\nif (typeof window === \"undefined\" && !isNodeJS && typeof self !== \"undefined\" && isMessagePort(self)) {\n  WorkerMessageHandler.initializeFromPort(self);\n}\n\n;// CONCATENATED MODULE: ./src/pdf.worker.js\n\nconst pdfjsVersion = \"4.2.67\";\nconst pdfjsBuild = \"49b388101\";\n\nvar __webpack_exports__WorkerMessageHandler = __webpack_exports__.WorkerMessageHandler;\nexport { __webpack_exports__WorkerMessageHandler as WorkerMessageHandler };\n\n//# sourceMappingURL=pdf.worker.mjs.map"
  },
  {
    "path": "src/StaffWebUI/wwwroot/pdfjs-4.2.67-dist/web/viewer.css",
    "content": "/* Copyright 2014 Mozilla Foundation\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\n.textLayer{\n  position:absolute;\n  text-align:initial;\n  inset:0;\n  overflow:hidden;\n  opacity:1;\n  line-height:1;\n  -webkit-text-size-adjust:none;\n     -moz-text-size-adjust:none;\n          text-size-adjust:none;\n  forced-color-adjust:none;\n  transform-origin:0 0;\n  caret-color:CanvasText;\n}\n\n.textLayer.highlighting{\n    touch-action:none;\n  }\n\n.textLayer :is(span, br){\n    color:transparent;\n    position:absolute;\n    white-space:pre;\n    cursor:text;\n    transform-origin:0% 0%;\n  }\n\n.textLayer span.markedContent{\n    top:0;\n    height:0;\n  }\n\n.textLayer .highlight{\n    --highlight-bg-color:rgb(180 0 170 / 0.25);\n    --highlight-selected-bg-color:rgb(0 100 0 / 0.25);\n    --highlight-backdrop-filter:none;\n    --highlight-selected-backdrop-filter:none;\n\n    margin:-1px;\n    padding:1px;\n    background-color:var(--highlight-bg-color);\n    -webkit-backdrop-filter:var(--highlight-backdrop-filter);\n            backdrop-filter:var(--highlight-backdrop-filter);\n    border-radius:4px;\n  }\n\n@media screen and (forced-colors: active){\n\n.textLayer .highlight{\n      --highlight-bg-color:transparent;\n      --highlight-selected-bg-color:transparent;\n      --highlight-backdrop-filter:var(--hcm-highlight-filter);\n      --highlight-selected-backdrop-filter:var(\n        --hcm-highlight-selected-filter\n      );\n  }\n    }\n\n.textLayer .highlight.appended{\n      position:initial;\n    }\n\n.textLayer .highlight.begin{\n      border-radius:4px 0 0 4px;\n    }\n\n.textLayer .highlight.end{\n      border-radius:0 4px 4px 0;\n    }\n\n.textLayer .highlight.middle{\n      border-radius:0;\n    }\n\n.textLayer .highlight.selected{\n      background-color:var(--highlight-selected-bg-color);\n      -webkit-backdrop-filter:var(--highlight-selected-backdrop-filter);\n              backdrop-filter:var(--highlight-selected-backdrop-filter);\n    }\n\n.textLayer ::-moz-selection{\n    background:rgba(0 0 255 / 0.25);\n    background:color-mix(in srgb, AccentColor, transparent 75%);\n  }\n\n.textLayer ::selection{\n    background:rgba(0 0 255 / 0.25);\n    background:color-mix(in srgb, AccentColor, transparent 75%);\n  }\n\n.textLayer br::-moz-selection{\n    background:transparent;\n  }\n\n.textLayer br::selection{\n    background:transparent;\n  }\n\n.textLayer .endOfContent{\n    display:block;\n    position:absolute;\n    inset:100% 0 0;\n    z-index:-1;\n    cursor:default;\n    -webkit-user-select:none;\n       -moz-user-select:none;\n            user-select:none;\n  }\n\n.textLayer .endOfContent.active{\n      top:0;\n    }\n\n.annotationLayer{\n  --annotation-unfocused-field-background:url(\"data:image/svg+xml;charset=UTF-8,<svg width='1px' height='1px' xmlns='http://www.w3.org/2000/svg'><rect width='100%' height='100%' style='fill:rgba(0, 54, 255, 0.13);'/></svg>\");\n  --input-focus-border-color:Highlight;\n  --input-focus-outline:1px solid Canvas;\n  --input-unfocused-border-color:transparent;\n  --input-disabled-border-color:transparent;\n  --input-hover-border-color:black;\n  --link-outline:none;\n\n  position:absolute;\n  top:0;\n  left:0;\n  pointer-events:none;\n  transform-origin:0 0;\n}\n\n@media screen and (forced-colors: active){\n\n.annotationLayer{\n    --input-focus-border-color:CanvasText;\n    --input-unfocused-border-color:ActiveText;\n    --input-disabled-border-color:GrayText;\n    --input-hover-border-color:Highlight;\n    --link-outline:1.5px solid LinkText;\n}\n\n    .annotationLayer .textWidgetAnnotation :is(input, textarea):required, .annotationLayer .choiceWidgetAnnotation select:required, .annotationLayer .buttonWidgetAnnotation:is(.checkBox, .radioButton) input:required{\n      outline:1.5px solid selectedItem;\n    }\n\n    .annotationLayer .linkAnnotation{\n      outline:var(--link-outline);\n    }\n\n      .annotationLayer .linkAnnotation:hover{\n        -webkit-backdrop-filter:var(--hcm-highlight-filter);\n                backdrop-filter:var(--hcm-highlight-filter);\n      }\n\n      .annotationLayer .linkAnnotation > a:hover{\n        opacity:0 !important;\n        background:none !important;\n        box-shadow:none;\n      }\n\n    .annotationLayer .popupAnnotation .popup{\n      outline:calc(1.5px * var(--scale-factor)) solid CanvasText !important;\n      background-color:ButtonFace !important;\n      color:ButtonText !important;\n    }\n\n    .annotationLayer .highlightArea:hover::after{\n      position:absolute;\n      top:0;\n      left:0;\n      width:100%;\n      height:100%;\n      -webkit-backdrop-filter:var(--hcm-highlight-filter);\n              backdrop-filter:var(--hcm-highlight-filter);\n      content:\"\";\n      pointer-events:none;\n    }\n\n    .annotationLayer .popupAnnotation.focused .popup{\n      outline:calc(3px * var(--scale-factor)) solid Highlight !important;\n    }\n  }\n\n.annotationLayer[data-main-rotation=\"90\"] .norotate{\n    transform:rotate(270deg) translateX(-100%);\n  }\n\n.annotationLayer[data-main-rotation=\"180\"] .norotate{\n    transform:rotate(180deg) translate(-100%, -100%);\n  }\n\n.annotationLayer[data-main-rotation=\"270\"] .norotate{\n    transform:rotate(90deg) translateY(-100%);\n  }\n\n.annotationLayer.disabled section,\n    .annotationLayer.disabled .popup{\n      pointer-events:none;\n    }\n\n.annotationLayer .annotationContent{\n    position:absolute;\n    width:100%;\n    height:100%;\n    pointer-events:none;\n  }\n\n.annotationLayer .annotationContent.freetext{\n      background:transparent;\n      border:none;\n      inset:0;\n      overflow:visible;\n      white-space:nowrap;\n      font:10px sans-serif;\n      line-height:1.35;\n      -webkit-user-select:none;\n         -moz-user-select:none;\n              user-select:none;\n    }\n\n.annotationLayer section{\n    position:absolute;\n    text-align:initial;\n    pointer-events:auto;\n    box-sizing:border-box;\n    transform-origin:0 0;\n  }\n\n.annotationLayer section:has(div.annotationContent) canvas.annotationContent{\n        display:none;\n      }\n\n.annotationLayer :is(.linkAnnotation, .buttonWidgetAnnotation.pushButton) > a{\n    position:absolute;\n    font-size:1em;\n    top:0;\n    left:0;\n    width:100%;\n    height:100%;\n  }\n\n.annotationLayer :is(.linkAnnotation, .buttonWidgetAnnotation.pushButton):not(.hasBorder)\n    > a:hover{\n    opacity:0.2;\n    background-color:rgb(255 255 0);\n    box-shadow:0 2px 10px rgb(255 255 0);\n  }\n\n.annotationLayer .linkAnnotation.hasBorder:hover{\n    background-color:rgb(255 255 0 / 0.2);\n  }\n\n.annotationLayer .hasBorder{\n    background-size:100% 100%;\n  }\n\n.annotationLayer .textAnnotation img{\n    position:absolute;\n    cursor:pointer;\n    width:100%;\n    height:100%;\n    top:0;\n    left:0;\n  }\n\n.annotationLayer .textWidgetAnnotation :is(input, textarea), .annotationLayer .choiceWidgetAnnotation select, .annotationLayer .buttonWidgetAnnotation:is(.checkBox, .radioButton) input{\n    background-image:var(--annotation-unfocused-field-background);\n    border:2px solid var(--input-unfocused-border-color);\n    box-sizing:border-box;\n    font:calc(9px * var(--scale-factor)) sans-serif;\n    height:100%;\n    margin:0;\n    vertical-align:top;\n    width:100%;\n  }\n\n.annotationLayer .textWidgetAnnotation :is(input, textarea):required, .annotationLayer .choiceWidgetAnnotation select:required, .annotationLayer .buttonWidgetAnnotation:is(.checkBox, .radioButton) input:required{\n    outline:1.5px solid red;\n  }\n\n.annotationLayer .choiceWidgetAnnotation select option{\n    padding:0;\n  }\n\n.annotationLayer .buttonWidgetAnnotation.radioButton input{\n    border-radius:50%;\n  }\n\n.annotationLayer .textWidgetAnnotation textarea{\n    resize:none;\n  }\n\n.annotationLayer .textWidgetAnnotation [disabled]:is(input, textarea), .annotationLayer .choiceWidgetAnnotation select[disabled], .annotationLayer .buttonWidgetAnnotation:is(.checkBox, .radioButton) input[disabled]{\n    background:none;\n    border:2px solid var(--input-disabled-border-color);\n    cursor:not-allowed;\n  }\n\n.annotationLayer .textWidgetAnnotation :is(input, textarea):hover, .annotationLayer .choiceWidgetAnnotation select:hover, .annotationLayer .buttonWidgetAnnotation:is(.checkBox, .radioButton) input:hover{\n    border:2px solid var(--input-hover-border-color);\n  }\n\n.annotationLayer .textWidgetAnnotation :is(input, textarea):hover, .annotationLayer .choiceWidgetAnnotation select:hover, .annotationLayer .buttonWidgetAnnotation.checkBox input:hover{\n    border-radius:2px;\n  }\n\n.annotationLayer .textWidgetAnnotation :is(input, textarea):focus, .annotationLayer .choiceWidgetAnnotation select:focus{\n    background:none;\n    border:2px solid var(--input-focus-border-color);\n    border-radius:2px;\n    outline:var(--input-focus-outline);\n  }\n\n.annotationLayer .buttonWidgetAnnotation:is(.checkBox, .radioButton) :focus{\n    background-image:none;\n    background-color:transparent;\n  }\n\n.annotationLayer .buttonWidgetAnnotation.checkBox :focus{\n    border:2px solid var(--input-focus-border-color);\n    border-radius:2px;\n    outline:var(--input-focus-outline);\n  }\n\n.annotationLayer .buttonWidgetAnnotation.radioButton :focus{\n    border:2px solid var(--input-focus-border-color);\n    outline:var(--input-focus-outline);\n  }\n\n.annotationLayer .buttonWidgetAnnotation.checkBox input:checked::before,\n  .annotationLayer .buttonWidgetAnnotation.checkBox input:checked::after,\n  .annotationLayer .buttonWidgetAnnotation.radioButton input:checked::before{\n    background-color:CanvasText;\n    content:\"\";\n    display:block;\n    position:absolute;\n  }\n\n.annotationLayer .buttonWidgetAnnotation.checkBox input:checked::before,\n  .annotationLayer .buttonWidgetAnnotation.checkBox input:checked::after{\n    height:80%;\n    left:45%;\n    width:1px;\n  }\n\n.annotationLayer .buttonWidgetAnnotation.checkBox input:checked::before{\n    transform:rotate(45deg);\n  }\n\n.annotationLayer .buttonWidgetAnnotation.checkBox input:checked::after{\n    transform:rotate(-45deg);\n  }\n\n.annotationLayer .buttonWidgetAnnotation.radioButton input:checked::before{\n    border-radius:50%;\n    height:50%;\n    left:25%;\n    top:25%;\n    width:50%;\n  }\n\n.annotationLayer .textWidgetAnnotation input.comb{\n    font-family:monospace;\n    padding-left:2px;\n    padding-right:0;\n  }\n\n.annotationLayer .textWidgetAnnotation input.comb:focus{\n    width:103%;\n  }\n\n.annotationLayer .buttonWidgetAnnotation:is(.checkBox, .radioButton) input{\n    -webkit-appearance:none;\n       -moz-appearance:none;\n            appearance:none;\n  }\n\n.annotationLayer .fileAttachmentAnnotation .popupTriggerArea{\n    height:100%;\n    width:100%;\n  }\n\n.annotationLayer .popupAnnotation{\n    position:absolute;\n    font-size:calc(9px * var(--scale-factor));\n    pointer-events:none;\n    width:-moz-max-content;\n    width:max-content;\n    max-width:45%;\n    height:auto;\n  }\n\n.annotationLayer .popup{\n    background-color:rgb(255 255 153);\n    box-shadow:0 calc(2px * var(--scale-factor)) calc(5px * var(--scale-factor)) rgb(136 136 136);\n    border-radius:calc(2px * var(--scale-factor));\n    outline:1.5px solid rgb(255 255 74);\n    padding:calc(6px * var(--scale-factor));\n    cursor:pointer;\n    font:message-box;\n    white-space:normal;\n    word-wrap:break-word;\n    pointer-events:auto;\n  }\n\n.annotationLayer .popupAnnotation.focused .popup{\n    outline-width:3px;\n  }\n\n.annotationLayer .popup *{\n    font-size:calc(9px * var(--scale-factor));\n  }\n\n.annotationLayer .popup > .header{\n    display:inline-block;\n  }\n\n.annotationLayer .popup > .header h1{\n    display:inline;\n  }\n\n.annotationLayer .popup > .header .popupDate{\n    display:inline-block;\n    margin-left:calc(5px * var(--scale-factor));\n    width:-moz-fit-content;\n    width:fit-content;\n  }\n\n.annotationLayer .popupContent{\n    border-top:1px solid rgb(51 51 51);\n    margin-top:calc(2px * var(--scale-factor));\n    padding-top:calc(2px * var(--scale-factor));\n  }\n\n.annotationLayer .richText > *{\n    white-space:pre-wrap;\n    font-size:calc(9px * var(--scale-factor));\n  }\n\n.annotationLayer .popupTriggerArea{\n    cursor:pointer;\n  }\n\n.annotationLayer section svg{\n    position:absolute;\n    width:100%;\n    height:100%;\n    top:0;\n    left:0;\n  }\n\n.annotationLayer .annotationTextContent{\n    position:absolute;\n    width:100%;\n    height:100%;\n    opacity:0;\n    color:transparent;\n    -webkit-user-select:none;\n       -moz-user-select:none;\n            user-select:none;\n    pointer-events:none;\n  }\n\n.annotationLayer .annotationTextContent span{\n      width:100%;\n      display:inline-block;\n    }\n\n.annotationLayer svg.quadrilateralsContainer{\n    contain:strict;\n    width:0;\n    height:0;\n    position:absolute;\n    top:0;\n    left:0;\n    z-index:-1;\n  }\n\n:root{\n  --xfa-unfocused-field-background:url(\"data:image/svg+xml;charset=UTF-8,<svg width='1px' height='1px' xmlns='http://www.w3.org/2000/svg'><rect width='100%' height='100%' style='fill:rgba(0, 54, 255, 0.13);'/></svg>\");\n  --xfa-focus-outline:auto;\n}\n\n@media screen and (forced-colors: active){\n  :root{\n    --xfa-focus-outline:2px solid CanvasText;\n  }\n  .xfaLayer *:required{\n    outline:1.5px solid selectedItem;\n  }\n}\n\n.xfaLayer{\n  background-color:transparent;\n}\n\n.xfaLayer .highlight{\n  margin:-1px;\n  padding:1px;\n  background-color:rgb(239 203 237);\n  border-radius:4px;\n}\n\n.xfaLayer .highlight.appended{\n  position:initial;\n}\n\n.xfaLayer .highlight.begin{\n  border-radius:4px 0 0 4px;\n}\n\n.xfaLayer .highlight.end{\n  border-radius:0 4px 4px 0;\n}\n\n.xfaLayer .highlight.middle{\n  border-radius:0;\n}\n\n.xfaLayer .highlight.selected{\n  background-color:rgb(203 223 203);\n}\n\n.xfaPage{\n  overflow:hidden;\n  position:relative;\n}\n\n.xfaContentarea{\n  position:absolute;\n}\n\n.xfaPrintOnly{\n  display:none;\n}\n\n.xfaLayer{\n  position:absolute;\n  text-align:initial;\n  top:0;\n  left:0;\n  transform-origin:0 0;\n  line-height:1.2;\n}\n\n.xfaLayer *{\n  color:inherit;\n  font:inherit;\n  font-style:inherit;\n  font-weight:inherit;\n  font-kerning:inherit;\n  letter-spacing:-0.01px;\n  text-align:inherit;\n  text-decoration:inherit;\n  box-sizing:border-box;\n  background-color:transparent;\n  padding:0;\n  margin:0;\n  pointer-events:auto;\n  line-height:inherit;\n}\n\n.xfaLayer *:required{\n  outline:1.5px solid red;\n}\n\n.xfaLayer div,\n.xfaLayer svg,\n.xfaLayer svg *{\n  pointer-events:none;\n}\n\n.xfaLayer a{\n  color:blue;\n}\n\n.xfaRich li{\n  margin-left:3em;\n}\n\n.xfaFont{\n  color:black;\n  font-weight:normal;\n  font-kerning:none;\n  font-size:10px;\n  font-style:normal;\n  letter-spacing:0;\n  text-decoration:none;\n  vertical-align:0;\n}\n\n.xfaCaption{\n  overflow:hidden;\n  flex:0 0 auto;\n}\n\n.xfaCaptionForCheckButton{\n  overflow:hidden;\n  flex:1 1 auto;\n}\n\n.xfaLabel{\n  height:100%;\n  width:100%;\n}\n\n.xfaLeft{\n  display:flex;\n  flex-direction:row;\n  align-items:center;\n}\n\n.xfaRight{\n  display:flex;\n  flex-direction:row-reverse;\n  align-items:center;\n}\n\n:is(.xfaLeft, .xfaRight) > :is(.xfaCaption, .xfaCaptionForCheckButton){\n  max-height:100%;\n}\n\n.xfaTop{\n  display:flex;\n  flex-direction:column;\n  align-items:flex-start;\n}\n\n.xfaBottom{\n  display:flex;\n  flex-direction:column-reverse;\n  align-items:flex-start;\n}\n\n:is(.xfaTop, .xfaBottom) > :is(.xfaCaption, .xfaCaptionForCheckButton){\n  width:100%;\n}\n\n.xfaBorder{\n  background-color:transparent;\n  position:absolute;\n  pointer-events:none;\n}\n\n.xfaWrapped{\n  width:100%;\n  height:100%;\n}\n\n:is(.xfaTextfield, .xfaSelect):focus{\n  background-image:none;\n  background-color:transparent;\n  outline:var(--xfa-focus-outline);\n  outline-offset:-1px;\n}\n\n:is(.xfaCheckbox, .xfaRadio):focus{\n  outline:var(--xfa-focus-outline);\n}\n\n.xfaTextfield,\n.xfaSelect{\n  height:100%;\n  width:100%;\n  flex:1 1 auto;\n  border:none;\n  resize:none;\n  background-image:var(--xfa-unfocused-field-background);\n}\n\n.xfaSelect{\n  padding-inline:2px;\n}\n\n:is(.xfaTop, .xfaBottom) > :is(.xfaTextfield, .xfaSelect){\n  flex:0 1 auto;\n}\n\n.xfaButton{\n  cursor:pointer;\n  width:100%;\n  height:100%;\n  border:none;\n  text-align:center;\n}\n\n.xfaLink{\n  width:100%;\n  height:100%;\n  position:absolute;\n  top:0;\n  left:0;\n}\n\n.xfaCheckbox,\n.xfaRadio{\n  width:100%;\n  height:100%;\n  flex:0 0 auto;\n  border:none;\n}\n\n.xfaRich{\n  white-space:pre-wrap;\n  width:100%;\n  height:100%;\n}\n\n.xfaImage{\n  -o-object-position:left top;\n     object-position:left top;\n  -o-object-fit:contain;\n     object-fit:contain;\n  width:100%;\n  height:100%;\n}\n\n.xfaLrTb,\n.xfaRlTb,\n.xfaTb{\n  display:flex;\n  flex-direction:column;\n  align-items:stretch;\n}\n\n.xfaLr{\n  display:flex;\n  flex-direction:row;\n  align-items:stretch;\n}\n\n.xfaRl{\n  display:flex;\n  flex-direction:row-reverse;\n  align-items:stretch;\n}\n\n.xfaTb > div{\n  justify-content:left;\n}\n\n.xfaPosition{\n  position:relative;\n}\n\n.xfaArea{\n  position:relative;\n}\n\n.xfaValignMiddle{\n  display:flex;\n  align-items:center;\n}\n\n.xfaTable{\n  display:flex;\n  flex-direction:column;\n  align-items:stretch;\n}\n\n.xfaTable .xfaRow{\n  display:flex;\n  flex-direction:row;\n  align-items:stretch;\n}\n\n.xfaTable .xfaRlRow{\n  display:flex;\n  flex-direction:row-reverse;\n  align-items:stretch;\n  flex:1;\n}\n\n.xfaTable .xfaRlRow > div{\n  flex:1;\n}\n\n:is(.xfaNonInteractive, .xfaDisabled, .xfaReadOnly) :is(input, textarea){\n  background:initial;\n}\n\n@media print{\n  .xfaTextfield,\n  .xfaSelect{\n    background:transparent;\n  }\n\n  .xfaSelect{\n    -webkit-appearance:none;\n       -moz-appearance:none;\n            appearance:none;\n    text-indent:1px;\n    text-overflow:\"\";\n  }\n}\n\n.canvasWrapper svg{\n    transform:none;\n  }\n\n.canvasWrapper svg[data-main-rotation=\"90\"] mask,\n      .canvasWrapper svg[data-main-rotation=\"90\"] use:not(.clip, .mask){\n        transform:matrix(0, 1, -1, 0, 1, 0);\n      }\n\n.canvasWrapper svg[data-main-rotation=\"180\"] mask,\n      .canvasWrapper svg[data-main-rotation=\"180\"] use:not(.clip, .mask){\n        transform:matrix(-1, 0, 0, -1, 1, 1);\n      }\n\n.canvasWrapper svg[data-main-rotation=\"270\"] mask,\n      .canvasWrapper svg[data-main-rotation=\"270\"] use:not(.clip, .mask){\n        transform:matrix(0, -1, 1, 0, 0, 1);\n      }\n\n.canvasWrapper svg.highlight{\n      --blend-mode:multiply;\n\n      position:absolute;\n      mix-blend-mode:var(--blend-mode);\n    }\n\n@media screen and (forced-colors: active){\n\n.canvasWrapper svg.highlight{\n        --blend-mode:difference;\n    }\n      }\n\n.canvasWrapper svg.highlight:not(.free){\n        fill-rule:evenodd;\n      }\n\n.canvasWrapper svg.highlightOutline{\n      position:absolute;\n      mix-blend-mode:normal;\n      fill-rule:evenodd;\n      fill:none;\n    }\n\n.canvasWrapper svg.highlightOutline.hovered:not(.free):not(.selected){\n          stroke:var(--hover-outline-color);\n          stroke-width:var(--outline-width);\n        }\n\n.canvasWrapper svg.highlightOutline.selected:not(.free) .mainOutline{\n            stroke:var(--outline-around-color);\n            stroke-width:calc(\n              var(--outline-width) + 2 * var(--outline-around-width)\n            );\n          }\n\n.canvasWrapper svg.highlightOutline.selected:not(.free) .secondaryOutline{\n            stroke:var(--outline-color);\n            stroke-width:var(--outline-width);\n          }\n\n.canvasWrapper svg.highlightOutline.free.hovered:not(.selected){\n          stroke:var(--hover-outline-color);\n          stroke-width:calc(2 * var(--outline-width));\n        }\n\n.canvasWrapper svg.highlightOutline.free.selected .mainOutline{\n            stroke:var(--outline-around-color);\n            stroke-width:calc(\n              2 * (var(--outline-width) + var(--outline-around-width))\n            );\n          }\n\n.canvasWrapper svg.highlightOutline.free.selected .secondaryOutline{\n            stroke:var(--outline-color);\n            stroke-width:calc(2 * var(--outline-width));\n          }\n\n.toggle-button{\n  --button-background-color:#f0f0f4;\n  --button-background-color-hover:#e0e0e6;\n  --button-background-color-active:#cfcfd8;\n  --color-accent-primary:#0060df;\n  --color-accent-primary-hover:#0250bb;\n  --color-accent-primary-active:#054096;\n  --border-interactive-color:#8f8f9d;\n  --border-radius-circle:9999px;\n  --border-width:1px;\n  --size-item-small:16px;\n  --size-item-large:32px;\n  --color-canvas:white;\n\n  --toggle-background-color:var(--button-background-color);\n  --toggle-background-color-hover:var(--button-background-color-hover);\n  --toggle-background-color-active:var(--button-background-color-active);\n  --toggle-background-color-pressed:var(--color-accent-primary);\n  --toggle-background-color-pressed-hover:var(--color-accent-primary-hover);\n  --toggle-background-color-pressed-active:var(--color-accent-primary-active);\n  --toggle-border-color:var(--border-interactive-color);\n  --toggle-border-color-hover:var(--toggle-border-color);\n  --toggle-border-color-active:var(--toggle-border-color);\n  --toggle-border-radius:var(--border-radius-circle);\n  --toggle-border-width:var(--border-width);\n  --toggle-height:var(--size-item-small);\n  --toggle-width:var(--size-item-large);\n  --toggle-dot-background-color:var(--toggle-border-color);\n  --toggle-dot-background-color-hover:var(--toggle-dot-background-color);\n  --toggle-dot-background-color-active:var(--toggle-dot-background-color);\n  --toggle-dot-background-color-on-pressed:var(--color-canvas);\n  --toggle-dot-margin:1px;\n  --toggle-dot-height:calc(\n    var(--toggle-height) - 2 * var(--toggle-dot-margin) - 2 *\n      var(--toggle-border-width)\n  );\n  --toggle-dot-width:var(--toggle-dot-height);\n  --toggle-dot-transform-x:calc(\n    var(--toggle-width) - 4 * var(--toggle-dot-margin) - var(--toggle-dot-width)\n  );\n\n  -webkit-appearance:none;\n\n     -moz-appearance:none;\n\n          appearance:none;\n  padding:0;\n  margin:0;\n  border:var(--toggle-border-width) solid var(--toggle-border-color);\n  height:var(--toggle-height);\n  width:var(--toggle-width);\n  border-radius:var(--toggle-border-radius);\n  background:var(--toggle-background-color);\n  box-sizing:border-box;\n  flex-shrink:0;\n}\n\n@media (prefers-color-scheme: dark){\n\n:where(html:not(.is-light)) .toggle-button{\n    --button-background-color:color-mix(in srgb, currentColor 7%, transparent);\n    --button-background-color-hover:color-mix(\n      in srgb,\n      currentColor 14%,\n      transparent\n    );\n    --button-background-color-active:color-mix(\n      in srgb,\n      currentColor 21%,\n      transparent\n    );\n    --color-accent-primary:#0df;\n    --color-accent-primary-hover:#80ebff;\n    --color-accent-primary-active:#aaf2ff;\n    --border-interactive-color:#bfbfc9;\n    --color-canvas:#1c1b22;\n}\n  }\n\n:where(html.is-dark) .toggle-button{\n    --button-background-color:color-mix(in srgb, currentColor 7%, transparent);\n    --button-background-color-hover:color-mix(\n      in srgb,\n      currentColor 14%,\n      transparent\n    );\n    --button-background-color-active:color-mix(\n      in srgb,\n      currentColor 21%,\n      transparent\n    );\n    --color-accent-primary:#0df;\n    --color-accent-primary-hover:#80ebff;\n    --color-accent-primary-active:#aaf2ff;\n    --border-interactive-color:#bfbfc9;\n    --color-canvas:#1c1b22;\n}\n\n@media (forced-colors: active){\n\n.toggle-button{\n    --color-accent-primary:ButtonText;\n    --color-accent-primary-hover:SelectedItem;\n    --color-accent-primary-active:SelectedItem;\n    --border-interactive-color:ButtonText;\n    --button-background-color:ButtonFace;\n    --border-interactive-color-hover:SelectedItem;\n    --border-interactive-color-active:SelectedItem;\n    --border-interactive-color-disabled:GrayText;\n    --color-canvas:ButtonText;\n}\n  }\n\n.toggle-button:focus-visible{\n    outline:var(--focus-outline);\n    outline-offset:var(--focus-outline-offset);\n  }\n\n.toggle-button:enabled:hover{\n    background:var(--toggle-background-color-hover);\n    border-color:var(--toggle-border-color);\n  }\n\n.toggle-button:enabled:active{\n    background:var(--toggle-background-color-active);\n    border-color:var(--toggle-border-color);\n  }\n\n.toggle-button[aria-pressed=\"true\"]{\n    background:var(--toggle-background-color-pressed);\n    border-color:transparent;\n  }\n\n.toggle-button[aria-pressed=\"true\"]:enabled:hover{\n    background:var(--toggle-background-color-pressed-hover);\n    border-color:transparent;\n  }\n\n.toggle-button[aria-pressed=\"true\"]:enabled:active{\n    background:var(--toggle-background-color-pressed-active);\n    border-color:transparent;\n  }\n\n.toggle-button::before{\n    display:block;\n    content:\"\";\n    background-color:var(--toggle-dot-background-color);\n    height:var(--toggle-dot-height);\n    width:var(--toggle-dot-width);\n    margin:var(--toggle-dot-margin);\n    border-radius:var(--toggle-border-radius);\n    translate:0;\n  }\n\n.toggle-button[aria-pressed=\"true\"]::before{\n    translate:var(--toggle-dot-transform-x);\n    background-color:var(--toggle-dot-background-color-on-pressed);\n  }\n\n.toggle-button[aria-pressed=\"true\"]:enabled:hover::before,\n  .toggle-button[aria-pressed=\"true\"]:enabled:active::before{\n    background-color:var(--toggle-dot-background-color-on-pressed);\n  }\n\n[dir=\"rtl\"] .toggle-button[aria-pressed=\"true\"]::before{\n    translate:calc(-1 * var(--toggle-dot-transform-x));\n  }\n\n@media (prefers-reduced-motion: no-preference){\n    .toggle-button::before{\n      transition:translate 100ms;\n    }\n  }\n\n@media (prefers-contrast){\n    .toggle-button:enabled:hover{\n      border-color:var(--toggle-border-color-hover);\n    }\n\n    .toggle-button:enabled:active{\n      border-color:var(--toggle-border-color-active);\n    }\n\n    .toggle-button[aria-pressed=\"true\"]:enabled{\n      border-color:var(--toggle-border-color);\n      position:relative;\n    }\n\n    .toggle-button[aria-pressed=\"true\"]:enabled:hover,\n    .toggle-button[aria-pressed=\"true\"]:enabled:hover:active{\n      border-color:var(--toggle-border-color-hover);\n    }\n\n    .toggle-button[aria-pressed=\"true\"]:enabled:active{\n      background-color:var(--toggle-dot-background-color-active);\n      border-color:var(--toggle-dot-background-color-hover);\n    }\n\n    .toggle-button:hover::before,\n    .toggle-button:active::before{\n      background-color:var(--toggle-dot-background-color-hover);\n    }\n  }\n\n@media (forced-colors){\n\n.toggle-button{\n    --toggle-dot-background-color:var(--color-accent-primary);\n    --toggle-dot-background-color-hover:var(--color-accent-primary-hover);\n    --toggle-dot-background-color-active:var(--color-accent-primary-active);\n    --toggle-dot-background-color-on-pressed:var(--button-background-color);\n    --toggle-background-color-disabled:var(--button-background-color-disabled);\n    --toggle-border-color-hover:var(--border-interactive-color-hover);\n    --toggle-border-color-active:var(--border-interactive-color-active);\n    --toggle-border-color-disabled:var(--border-interactive-color-disabled);\n}\n\n    .toggle-button[aria-pressed=\"true\"]:enabled::after{\n      border:1px solid var(--button-background-color);\n      content:\"\";\n      position:absolute;\n      height:var(--toggle-height);\n      width:var(--toggle-width);\n      display:block;\n      border-radius:var(--toggle-border-radius);\n      inset:-2px;\n    }\n\n    .toggle-button[aria-pressed=\"true\"]:enabled:active::after{\n      border-color:var(--toggle-border-color-active);\n    }\n  }\n\n:root{\n  --outline-width:2px;\n  --outline-color:#0060df;\n  --outline-around-width:1px;\n  --outline-around-color:#f0f0f4;\n  --hover-outline-around-color:var(--outline-around-color);\n  --focus-outline:solid var(--outline-width) var(--outline-color);\n  --unfocus-outline:solid var(--outline-width) transparent;\n  --focus-outline-around:solid var(--outline-around-width) var(--outline-around-color);\n  --hover-outline-color:#8f8f9d;\n  --hover-outline:solid var(--outline-width) var(--hover-outline-color);\n  --hover-outline-around:solid var(--outline-around-width) var(--hover-outline-around-color);\n  --freetext-line-height:1.35;\n  --freetext-padding:2px;\n  --resizer-bg-color:var(--outline-color);\n  --resizer-size:6px;\n  --resizer-shift:calc(\n    0px - (var(--outline-width) + var(--resizer-size)) / 2 -\n      var(--outline-around-width)\n  );\n  --editorFreeText-editing-cursor:text;\n  --editorInk-editing-cursor:url(images/cursor-editorInk.svg) 0 16, pointer;\n  --editorHighlight-editing-cursor:url(images/cursor-editorTextHighlight.svg) 24 24, text;\n  --editorFreeHighlight-editing-cursor:url(images/cursor-editorFreeHighlight.svg) 1 18, pointer;\n}\n.visuallyHidden{\n  position:absolute;\n  top:0;\n  left:0;\n  border:0;\n  margin:0;\n  padding:0;\n  width:0;\n  height:0;\n  overflow:hidden;\n  white-space:nowrap;\n  font-size:0;\n}\n\n.textLayer.highlighting{\n  cursor:var(--editorFreeHighlight-editing-cursor);\n}\n\n.textLayer.highlighting:not(.free) span{\n    cursor:var(--editorHighlight-editing-cursor);\n  }\n\n.textLayer.highlighting.free span{\n    cursor:var(--editorFreeHighlight-editing-cursor);\n  }\n\n@media (min-resolution: 1.1dppx){\n  :root{\n    --editorFreeText-editing-cursor:url(images/cursor-editorFreeText.svg) 0 16, text;\n  }\n}\n\n@media screen and (forced-colors: active){\n  :root{\n    --outline-color:CanvasText;\n    --outline-around-color:ButtonFace;\n    --resizer-bg-color:ButtonText;\n    --hover-outline-color:Highlight;\n    --hover-outline-around-color:SelectedItemText;\n  }\n}\n\n[data-editor-rotation=\"90\"]{\n  transform:rotate(90deg);\n}\n\n[data-editor-rotation=\"180\"]{\n  transform:rotate(180deg);\n}\n\n[data-editor-rotation=\"270\"]{\n  transform:rotate(270deg);\n}\n\n.annotationEditorLayer{\n  background:transparent;\n  position:absolute;\n  inset:0;\n  font-size:calc(100px * var(--scale-factor));\n  transform-origin:0 0;\n  cursor:auto;\n}\n\n.annotationEditorLayer.waiting{\n  content:\"\";\n  cursor:wait;\n  position:absolute;\n  inset:0;\n  width:100%;\n  height:100%;\n}\n\n.annotationEditorLayer.disabled{\n  pointer-events:none;\n}\n\n.annotationEditorLayer.freetextEditing{\n  cursor:var(--editorFreeText-editing-cursor);\n}\n\n.annotationEditorLayer.inkEditing{\n  cursor:var(--editorInk-editing-cursor);\n}\n\n.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor){\n  position:absolute;\n  background:transparent;\n  z-index:1;\n  transform-origin:0 0;\n  cursor:auto;\n  max-width:100%;\n  max-height:100%;\n  border:var(--unfocus-outline);\n}\n\n.annotationEditorLayer .draggable.selectedEditor:is(.freeTextEditor, .inkEditor, .stampEditor){\n    cursor:move;\n  }\n\n.annotationEditorLayer .moving:is(.freeTextEditor, .inkEditor, .stampEditor){\n    touch-action:none;\n  }\n\n.annotationEditorLayer .selectedEditor:is(.freeTextEditor, .inkEditor, .stampEditor){\n    border:var(--focus-outline);\n    outline:var(--focus-outline-around);\n  }\n\n.annotationEditorLayer .selectedEditor:is(.freeTextEditor, .inkEditor, .stampEditor)::before{\n      content:\"\";\n      position:absolute;\n      inset:0;\n      border:var(--focus-outline-around);\n      pointer-events:none;\n    }\n\n.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor):hover:not(.selectedEditor){\n    border:var(--hover-outline);\n    outline:var(--hover-outline-around);\n  }\n\n.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor):hover:not(.selectedEditor)::before{\n      content:\"\";\n      position:absolute;\n      inset:0;\n      border:var(--focus-outline-around);\n    }\n\n:is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar{\n    --editor-toolbar-delete-image:url(images/editor-toolbar-delete.svg);\n    --editor-toolbar-bg-color:#f0f0f4;\n    --editor-toolbar-highlight-image:url(images/toolbarButton-editorHighlight.svg);\n    --editor-toolbar-fg-color:#2e2e56;\n    --editor-toolbar-border-color:#8f8f9d;\n    --editor-toolbar-hover-border-color:var(--editor-toolbar-border-color);\n    --editor-toolbar-hover-bg-color:#e0e0e6;\n    --editor-toolbar-hover-fg-color:var(--editor-toolbar-fg-color);\n    --editor-toolbar-hover-outline:none;\n    --editor-toolbar-focus-outline-color:#0060df;\n    --editor-toolbar-shadow:0 2px 6px 0 rgb(58 57 68 / 0.2);\n    --editor-toolbar-vert-offset:6px;\n    --editor-toolbar-height:28px;\n    --editor-toolbar-padding:2px;\n\n    display:flex;\n    width:-moz-fit-content;\n    width:fit-content;\n    height:var(--editor-toolbar-height);\n    flex-direction:column;\n    justify-content:center;\n    align-items:center;\n    cursor:default;\n    pointer-events:auto;\n    box-sizing:content-box;\n    padding:var(--editor-toolbar-padding);\n\n    position:absolute;\n    inset-inline-end:0;\n    inset-block-start:calc(100% + var(--editor-toolbar-vert-offset));\n\n    border-radius:6px;\n    background-color:var(--editor-toolbar-bg-color);\n    border:1px solid var(--editor-toolbar-border-color);\n    box-shadow:var(--editor-toolbar-shadow);\n  }\n\n@media (prefers-color-scheme: dark){\n\n:where(html:not(.is-light)) :is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar{\n      --editor-toolbar-bg-color:#2b2a33;\n      --editor-toolbar-fg-color:#fbfbfe;\n      --editor-toolbar-hover-bg-color:#52525e;\n      --editor-toolbar-focus-outline-color:#0df;\n  }\n    }\n\n:where(html.is-dark) :is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar{\n      --editor-toolbar-bg-color:#2b2a33;\n      --editor-toolbar-fg-color:#fbfbfe;\n      --editor-toolbar-hover-bg-color:#52525e;\n      --editor-toolbar-focus-outline-color:#0df;\n  }\n\n@media screen and (forced-colors: active){\n\n:is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar{\n      --editor-toolbar-bg-color:ButtonFace;\n      --editor-toolbar-fg-color:ButtonText;\n      --editor-toolbar-border-color:ButtonText;\n      --editor-toolbar-hover-border-color:AccentColor;\n      --editor-toolbar-hover-bg-color:ButtonFace;\n      --editor-toolbar-hover-fg-color:AccentColor;\n      --editor-toolbar-hover-outline:2px solid var(--editor-toolbar-hover-border-color);\n      --editor-toolbar-focus-outline-color:ButtonBorder;\n      --editor-toolbar-shadow:none;\n  }\n    }\n\n:is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar.hidden{\n      display:none;\n    }\n\n:is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar:has(:focus-visible){\n      border-color:transparent;\n    }\n\n[dir=\"ltr\"] :is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar{\n      transform-origin:100% 0;\n    }\n\n[dir=\"rtl\"] :is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar{\n      transform-origin:0 0;\n    }\n\n:is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons{\n      display:flex;\n      justify-content:center;\n      align-items:center;\n      gap:0;\n      height:100%;\n    }\n\n:is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .divider{\n        width:1px;\n        height:calc(\n          2 * var(--editor-toolbar-padding) + var(--editor-toolbar-height)\n        );\n        background-color:var(--editor-toolbar-border-color);\n        display:inline-block;\n        margin-inline:2px;\n      }\n\n:is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .highlightButton{\n        width:var(--editor-toolbar-height);\n      }\n\n:is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .highlightButton::before{\n          content:\"\";\n          -webkit-mask-image:var(--editor-toolbar-highlight-image);\n                  mask-image:var(--editor-toolbar-highlight-image);\n          -webkit-mask-repeat:no-repeat;\n                  mask-repeat:no-repeat;\n          -webkit-mask-position:center;\n                  mask-position:center;\n          display:inline-block;\n          background-color:var(--editor-toolbar-fg-color);\n          width:100%;\n          height:100%;\n        }\n\n:is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .highlightButton:hover::before{\n          background-color:var(--editor-toolbar-hover-fg-color);\n        }\n\n:is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .delete{\n        width:var(--editor-toolbar-height);\n      }\n\n:is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .delete::before{\n          content:\"\";\n          -webkit-mask-image:var(--editor-toolbar-delete-image);\n                  mask-image:var(--editor-toolbar-delete-image);\n          -webkit-mask-repeat:no-repeat;\n                  mask-repeat:no-repeat;\n          -webkit-mask-position:center;\n                  mask-position:center;\n          display:inline-block;\n          background-color:var(--editor-toolbar-fg-color);\n          width:100%;\n          height:100%;\n        }\n\n:is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .delete:hover::before{\n          background-color:var(--editor-toolbar-hover-fg-color);\n        }\n\n:is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons > *{\n        height:var(--editor-toolbar-height);\n      }\n\n:is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons > :not(.divider){\n        border:none;\n        background-color:transparent;\n        cursor:pointer;\n      }\n\n:is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons > :not(.divider):hover{\n          border-radius:2px;\n          background-color:var(--editor-toolbar-hover-bg-color);\n          color:var(--editor-toolbar-hover-fg-color);\n          outline:var(--editor-toolbar-hover-outline);\n          outline-offset:1px;\n        }\n\n:is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons > :not(.divider):hover:active{\n            outline:none;\n          }\n\n:is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons > :not(.divider):focus-visible{\n          border-radius:2px;\n          outline:2px solid var(--editor-toolbar-focus-outline-color);\n        }\n\n:is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .altText{\n        --alt-text-add-image:url(images/altText_add.svg);\n        --alt-text-done-image:url(images/altText_done.svg);\n\n        display:flex;\n        align-items:center;\n        justify-content:center;\n        width:-moz-max-content;\n        width:max-content;\n        padding-inline:8px;\n        pointer-events:all;\n        font:menu;\n        font-weight:590;\n        font-size:12px;\n        color:var(--editor-toolbar-fg-color);\n      }\n\n:is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .altText:disabled{\n          pointer-events:none;\n        }\n\n:is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .altText::before{\n          content:\"\";\n          -webkit-mask-image:var(--alt-text-add-image);\n                  mask-image:var(--alt-text-add-image);\n          -webkit-mask-repeat:no-repeat;\n                  mask-repeat:no-repeat;\n          -webkit-mask-position:center;\n                  mask-position:center;\n          display:inline-block;\n          width:12px;\n          height:13px;\n          background-color:var(--editor-toolbar-fg-color);\n          margin-inline-end:4px;\n        }\n\n:is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .altText:hover::before{\n          background-color:var(--editor-toolbar-hover-fg-color);\n        }\n\n:is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .altText.done::before{\n          -webkit-mask-image:var(--alt-text-done-image);\n                  mask-image:var(--alt-text-done-image);\n        }\n\n:is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .altText .tooltip{\n          display:none;\n        }\n\n:is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .altText .tooltip.show{\n            --alt-text-tooltip-bg:#f0f0f4;\n            --alt-text-tooltip-fg:#15141a;\n            --alt-text-tooltip-border:#8f8f9d;\n            --alt-text-tooltip-shadow:0px 2px 6px 0px rgb(58 57 68 / 0.2);\n\n            display:inline-flex;\n            flex-direction:column;\n            align-items:center;\n            justify-content:center;\n            position:absolute;\n            top:calc(100% + 2px);\n            inset-inline-start:0;\n            padding-block:2px 3px;\n            padding-inline:3px;\n            max-width:300px;\n            width:-moz-max-content;\n            width:max-content;\n            height:auto;\n            font-size:12px;\n\n            border:0.5px solid var(--alt-text-tooltip-border);\n            background:var(--alt-text-tooltip-bg);\n            box-shadow:var(--alt-text-tooltip-shadow);\n            color:var(--alt-text-tooltip-fg);\n\n            pointer-events:none;\n          }\n\n@media (prefers-color-scheme: dark){\n\n:where(html:not(.is-light)) :is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .altText .tooltip.show{\n              --alt-text-tooltip-bg:#1c1b22;\n              --alt-text-tooltip-fg:#fbfbfe;\n              --alt-text-tooltip-shadow:0px 2px 6px 0px #15141a;\n          }\n            }\n\n:where(html.is-dark) :is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .altText .tooltip.show{\n              --alt-text-tooltip-bg:#1c1b22;\n              --alt-text-tooltip-fg:#fbfbfe;\n              --alt-text-tooltip-shadow:0px 2px 6px 0px #15141a;\n          }\n\n@media screen and (forced-colors: active){\n\n:is(.annotationEditorLayer\n  :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .altText .tooltip.show{\n              --alt-text-tooltip-bg:Canvas;\n              --alt-text-tooltip-fg:CanvasText;\n              --alt-text-tooltip-border:CanvasText;\n              --alt-text-tooltip-shadow:none;\n          }\n            }\n\n.annotationEditorLayer .freeTextEditor{\n  padding:calc(var(--freetext-padding) * var(--scale-factor));\n  width:auto;\n  height:auto;\n  touch-action:none;\n}\n\n.annotationEditorLayer .freeTextEditor .internal{\n  background:transparent;\n  border:none;\n  inset:0;\n  overflow:visible;\n  white-space:nowrap;\n  font:10px sans-serif;\n  line-height:var(--freetext-line-height);\n  -webkit-user-select:none;\n     -moz-user-select:none;\n          user-select:none;\n}\n\n.annotationEditorLayer .freeTextEditor .overlay{\n  position:absolute;\n  display:none;\n  background:transparent;\n  inset:0;\n  width:100%;\n  height:100%;\n}\n\n.annotationEditorLayer freeTextEditor .overlay.enabled{\n  display:block;\n}\n\n.annotationEditorLayer .freeTextEditor .internal:empty::before{\n  content:attr(default-content);\n  color:gray;\n}\n\n.annotationEditorLayer .freeTextEditor .internal:focus{\n  outline:none;\n  -webkit-user-select:auto;\n     -moz-user-select:auto;\n          user-select:auto;\n}\n\n.annotationEditorLayer .inkEditor{\n  width:100%;\n  height:100%;\n}\n\n.annotationEditorLayer .inkEditor.editing{\n  cursor:inherit;\n}\n\n.annotationEditorLayer .inkEditor .inkEditorCanvas{\n  position:absolute;\n  inset:0;\n  width:100%;\n  height:100%;\n  touch-action:none;\n}\n\n.annotationEditorLayer .stampEditor{\n  width:auto;\n  height:auto;\n}\n\n.annotationEditorLayer .stampEditor canvas{\n  width:100%;\n  height:100%;\n}\n\n.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor) > .resizers{\n      position:absolute;\n      inset:0;\n    }\n\n.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor) > .resizers.hidden{\n        display:none;\n      }\n\n.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor) > .resizers > .resizer{\n        width:var(--resizer-size);\n        height:var(--resizer-size);\n        background:content-box var(--resizer-bg-color);\n        border:var(--focus-outline-around);\n        border-radius:2px;\n        position:absolute;\n      }\n\n.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor) > .resizers > .resizer.topLeft{\n          top:var(--resizer-shift);\n          left:var(--resizer-shift);\n        }\n\n.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor) > .resizers > .resizer.topMiddle{\n          top:var(--resizer-shift);\n          left:calc(50% + var(--resizer-shift));\n        }\n\n.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor) > .resizers > .resizer.topRight{\n          top:var(--resizer-shift);\n          right:var(--resizer-shift);\n        }\n\n.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor) > .resizers > .resizer.middleRight{\n          top:calc(50% + var(--resizer-shift));\n          right:var(--resizer-shift);\n        }\n\n.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor) > .resizers > .resizer.bottomRight{\n          bottom:var(--resizer-shift);\n          right:var(--resizer-shift);\n        }\n\n.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor) > .resizers > .resizer.bottomMiddle{\n          bottom:var(--resizer-shift);\n          left:calc(50% + var(--resizer-shift));\n        }\n\n.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor) > .resizers > .resizer.bottomLeft{\n          bottom:var(--resizer-shift);\n          left:var(--resizer-shift);\n        }\n\n.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor) > .resizers > .resizer.middleLeft{\n          top:calc(50% + var(--resizer-shift));\n          left:var(--resizer-shift);\n        }\n\n.annotationEditorLayer[data-main-rotation=\"0\"]\n    :is([data-editor-rotation=\"0\"], [data-editor-rotation=\"180\"]) > .resizers > .resizer.topLeft,\n      .annotationEditorLayer[data-main-rotation=\"90\"]\n    :is([data-editor-rotation=\"270\"], [data-editor-rotation=\"90\"]) > .resizers > .resizer.topLeft,\n      .annotationEditorLayer[data-main-rotation=\"180\"]\n    :is([data-editor-rotation=\"180\"], [data-editor-rotation=\"0\"]) > .resizers > .resizer.topLeft,\n      .annotationEditorLayer[data-main-rotation=\"270\"]\n    :is([data-editor-rotation=\"90\"], [data-editor-rotation=\"270\"]) > .resizers > .resizer.topLeft,\n      .annotationEditorLayer[data-main-rotation=\"0\"]\n    :is([data-editor-rotation=\"0\"], [data-editor-rotation=\"180\"]) > .resizers > .resizer.bottomRight,\n      .annotationEditorLayer[data-main-rotation=\"90\"]\n    :is([data-editor-rotation=\"270\"], [data-editor-rotation=\"90\"]) > .resizers > .resizer.bottomRight,\n      .annotationEditorLayer[data-main-rotation=\"180\"]\n    :is([data-editor-rotation=\"180\"], [data-editor-rotation=\"0\"]) > .resizers > .resizer.bottomRight,\n      .annotationEditorLayer[data-main-rotation=\"270\"]\n    :is([data-editor-rotation=\"90\"], [data-editor-rotation=\"270\"]) > .resizers > .resizer.bottomRight{\n        cursor:nwse-resize;\n      }\n\n.annotationEditorLayer[data-main-rotation=\"0\"]\n    :is([data-editor-rotation=\"0\"], [data-editor-rotation=\"180\"]) > .resizers > .resizer.topMiddle,\n      .annotationEditorLayer[data-main-rotation=\"90\"]\n    :is([data-editor-rotation=\"270\"], [data-editor-rotation=\"90\"]) > .resizers > .resizer.topMiddle,\n      .annotationEditorLayer[data-main-rotation=\"180\"]\n    :is([data-editor-rotation=\"180\"], [data-editor-rotation=\"0\"]) > .resizers > .resizer.topMiddle,\n      .annotationEditorLayer[data-main-rotation=\"270\"]\n    :is([data-editor-rotation=\"90\"], [data-editor-rotation=\"270\"]) > .resizers > .resizer.topMiddle,\n      .annotationEditorLayer[data-main-rotation=\"0\"]\n    :is([data-editor-rotation=\"0\"], [data-editor-rotation=\"180\"]) > .resizers > .resizer.bottomMiddle,\n      .annotationEditorLayer[data-main-rotation=\"90\"]\n    :is([data-editor-rotation=\"270\"], [data-editor-rotation=\"90\"]) > .resizers > .resizer.bottomMiddle,\n      .annotationEditorLayer[data-main-rotation=\"180\"]\n    :is([data-editor-rotation=\"180\"], [data-editor-rotation=\"0\"]) > .resizers > .resizer.bottomMiddle,\n      .annotationEditorLayer[data-main-rotation=\"270\"]\n    :is([data-editor-rotation=\"90\"], [data-editor-rotation=\"270\"]) > .resizers > .resizer.bottomMiddle{\n        cursor:ns-resize;\n      }\n\n.annotationEditorLayer[data-main-rotation=\"0\"]\n    :is([data-editor-rotation=\"0\"], [data-editor-rotation=\"180\"]) > .resizers > .resizer.topRight,\n      .annotationEditorLayer[data-main-rotation=\"90\"]\n    :is([data-editor-rotation=\"270\"], [data-editor-rotation=\"90\"]) > .resizers > .resizer.topRight,\n      .annotationEditorLayer[data-main-rotation=\"180\"]\n    :is([data-editor-rotation=\"180\"], [data-editor-rotation=\"0\"]) > .resizers > .resizer.topRight,\n      .annotationEditorLayer[data-main-rotation=\"270\"]\n    :is([data-editor-rotation=\"90\"], [data-editor-rotation=\"270\"]) > .resizers > .resizer.topRight,\n      .annotationEditorLayer[data-main-rotation=\"0\"]\n    :is([data-editor-rotation=\"0\"], [data-editor-rotation=\"180\"]) > .resizers > .resizer.bottomLeft,\n      .annotationEditorLayer[data-main-rotation=\"90\"]\n    :is([data-editor-rotation=\"270\"], [data-editor-rotation=\"90\"]) > .resizers > .resizer.bottomLeft,\n      .annotationEditorLayer[data-main-rotation=\"180\"]\n    :is([data-editor-rotation=\"180\"], [data-editor-rotation=\"0\"]) > .resizers > .resizer.bottomLeft,\n      .annotationEditorLayer[data-main-rotation=\"270\"]\n    :is([data-editor-rotation=\"90\"], [data-editor-rotation=\"270\"]) > .resizers > .resizer.bottomLeft{\n        cursor:nesw-resize;\n      }\n\n.annotationEditorLayer[data-main-rotation=\"0\"]\n    :is([data-editor-rotation=\"0\"], [data-editor-rotation=\"180\"]) > .resizers > .resizer.middleRight,\n      .annotationEditorLayer[data-main-rotation=\"90\"]\n    :is([data-editor-rotation=\"270\"], [data-editor-rotation=\"90\"]) > .resizers > .resizer.middleRight,\n      .annotationEditorLayer[data-main-rotation=\"180\"]\n    :is([data-editor-rotation=\"180\"], [data-editor-rotation=\"0\"]) > .resizers > .resizer.middleRight,\n      .annotationEditorLayer[data-main-rotation=\"270\"]\n    :is([data-editor-rotation=\"90\"], [data-editor-rotation=\"270\"]) > .resizers > .resizer.middleRight,\n      .annotationEditorLayer[data-main-rotation=\"0\"]\n    :is([data-editor-rotation=\"0\"], [data-editor-rotation=\"180\"]) > .resizers > .resizer.middleLeft,\n      .annotationEditorLayer[data-main-rotation=\"90\"]\n    :is([data-editor-rotation=\"270\"], [data-editor-rotation=\"90\"]) > .resizers > .resizer.middleLeft,\n      .annotationEditorLayer[data-main-rotation=\"180\"]\n    :is([data-editor-rotation=\"180\"], [data-editor-rotation=\"0\"]) > .resizers > .resizer.middleLeft,\n      .annotationEditorLayer[data-main-rotation=\"270\"]\n    :is([data-editor-rotation=\"90\"], [data-editor-rotation=\"270\"]) > .resizers > .resizer.middleLeft{\n        cursor:ew-resize;\n      }\n\n.annotationEditorLayer[data-main-rotation=\"0\"]\n    :is([data-editor-rotation=\"90\"], [data-editor-rotation=\"270\"]) > .resizers > .resizer.topLeft,\n      .annotationEditorLayer[data-main-rotation=\"90\"]\n    :is([data-editor-rotation=\"0\"], [data-editor-rotation=\"180\"]) > .resizers > .resizer.topLeft,\n      .annotationEditorLayer[data-main-rotation=\"180\"]\n    :is([data-editor-rotation=\"270\"], [data-editor-rotation=\"90\"]) > .resizers > .resizer.topLeft,\n      .annotationEditorLayer[data-main-rotation=\"270\"]\n    :is([data-editor-rotation=\"180\"], [data-editor-rotation=\"0\"]) > .resizers > .resizer.topLeft,\n      .annotationEditorLayer[data-main-rotation=\"0\"]\n    :is([data-editor-rotation=\"90\"], [data-editor-rotation=\"270\"]) > .resizers > .resizer.bottomRight,\n      .annotationEditorLayer[data-main-rotation=\"90\"]\n    :is([data-editor-rotation=\"0\"], [data-editor-rotation=\"180\"]) > .resizers > .resizer.bottomRight,\n      .annotationEditorLayer[data-main-rotation=\"180\"]\n    :is([data-editor-rotation=\"270\"], [data-editor-rotation=\"90\"]) > .resizers > .resizer.bottomRight,\n      .annotationEditorLayer[data-main-rotation=\"270\"]\n    :is([data-editor-rotation=\"180\"], [data-editor-rotation=\"0\"]) > .resizers > .resizer.bottomRight{\n        cursor:nesw-resize;\n      }\n\n.annotationEditorLayer[data-main-rotation=\"0\"]\n    :is([data-editor-rotation=\"90\"], [data-editor-rotation=\"270\"]) > .resizers > .resizer.topMiddle,\n      .annotationEditorLayer[data-main-rotation=\"90\"]\n    :is([data-editor-rotation=\"0\"], [data-editor-rotation=\"180\"]) > .resizers > .resizer.topMiddle,\n      .annotationEditorLayer[data-main-rotation=\"180\"]\n    :is([data-editor-rotation=\"270\"], [data-editor-rotation=\"90\"]) > .resizers > .resizer.topMiddle,\n      .annotationEditorLayer[data-main-rotation=\"270\"]\n    :is([data-editor-rotation=\"180\"], [data-editor-rotation=\"0\"]) > .resizers > .resizer.topMiddle,\n      .annotationEditorLayer[data-main-rotation=\"0\"]\n    :is([data-editor-rotation=\"90\"], [data-editor-rotation=\"270\"]) > .resizers > .resizer.bottomMiddle,\n      .annotationEditorLayer[data-main-rotation=\"90\"]\n    :is([data-editor-rotation=\"0\"], [data-editor-rotation=\"180\"]) > .resizers > .resizer.bottomMiddle,\n      .annotationEditorLayer[data-main-rotation=\"180\"]\n    :is([data-editor-rotation=\"270\"], [data-editor-rotation=\"90\"]) > .resizers > .resizer.bottomMiddle,\n      .annotationEditorLayer[data-main-rotation=\"270\"]\n    :is([data-editor-rotation=\"180\"], [data-editor-rotation=\"0\"]) > .resizers > .resizer.bottomMiddle{\n        cursor:ew-resize;\n      }\n\n.annotationEditorLayer[data-main-rotation=\"0\"]\n    :is([data-editor-rotation=\"90\"], [data-editor-rotation=\"270\"]) > .resizers > .resizer.topRight,\n      .annotationEditorLayer[data-main-rotation=\"90\"]\n    :is([data-editor-rotation=\"0\"], [data-editor-rotation=\"180\"]) > .resizers > .resizer.topRight,\n      .annotationEditorLayer[data-main-rotation=\"180\"]\n    :is([data-editor-rotation=\"270\"], [data-editor-rotation=\"90\"]) > .resizers > .resizer.topRight,\n      .annotationEditorLayer[data-main-rotation=\"270\"]\n    :is([data-editor-rotation=\"180\"], [data-editor-rotation=\"0\"]) > .resizers > .resizer.topRight,\n      .annotationEditorLayer[data-main-rotation=\"0\"]\n    :is([data-editor-rotation=\"90\"], [data-editor-rotation=\"270\"]) > .resizers > .resizer.bottomLeft,\n      .annotationEditorLayer[data-main-rotation=\"90\"]\n    :is([data-editor-rotation=\"0\"], [data-editor-rotation=\"180\"]) > .resizers > .resizer.bottomLeft,\n      .annotationEditorLayer[data-main-rotation=\"180\"]\n    :is([data-editor-rotation=\"270\"], [data-editor-rotation=\"90\"]) > .resizers > .resizer.bottomLeft,\n      .annotationEditorLayer[data-main-rotation=\"270\"]\n    :is([data-editor-rotation=\"180\"], [data-editor-rotation=\"0\"]) > .resizers > .resizer.bottomLeft{\n        cursor:nwse-resize;\n      }\n\n.annotationEditorLayer[data-main-rotation=\"0\"]\n    :is([data-editor-rotation=\"90\"], [data-editor-rotation=\"270\"]) > .resizers > .resizer.middleRight,\n      .annotationEditorLayer[data-main-rotation=\"90\"]\n    :is([data-editor-rotation=\"0\"], [data-editor-rotation=\"180\"]) > .resizers > .resizer.middleRight,\n      .annotationEditorLayer[data-main-rotation=\"180\"]\n    :is([data-editor-rotation=\"270\"], [data-editor-rotation=\"90\"]) > .resizers > .resizer.middleRight,\n      .annotationEditorLayer[data-main-rotation=\"270\"]\n    :is([data-editor-rotation=\"180\"], [data-editor-rotation=\"0\"]) > .resizers > .resizer.middleRight,\n      .annotationEditorLayer[data-main-rotation=\"0\"]\n    :is([data-editor-rotation=\"90\"], [data-editor-rotation=\"270\"]) > .resizers > .resizer.middleLeft,\n      .annotationEditorLayer[data-main-rotation=\"90\"]\n    :is([data-editor-rotation=\"0\"], [data-editor-rotation=\"180\"]) > .resizers > .resizer.middleLeft,\n      .annotationEditorLayer[data-main-rotation=\"180\"]\n    :is([data-editor-rotation=\"270\"], [data-editor-rotation=\"90\"]) > .resizers > .resizer.middleLeft,\n      .annotationEditorLayer[data-main-rotation=\"270\"]\n    :is([data-editor-rotation=\"180\"], [data-editor-rotation=\"0\"]) > .resizers > .resizer.middleLeft{\n        cursor:ns-resize;\n      }\n\n.annotationEditorLayer\n    :is(\n      [data-main-rotation=\"0\"] [data-editor-rotation=\"90\"],\n      [data-main-rotation=\"90\"] [data-editor-rotation=\"0\"],\n      [data-main-rotation=\"180\"] [data-editor-rotation=\"270\"],\n      [data-main-rotation=\"270\"] [data-editor-rotation=\"180\"]\n    ) .editToolbar{\n      rotate:270deg;\n    }\n\n[dir=\"ltr\"] .annotationEditorLayer\n    :is(\n      [data-main-rotation=\"0\"] [data-editor-rotation=\"90\"],\n      [data-main-rotation=\"90\"] [data-editor-rotation=\"0\"],\n      [data-main-rotation=\"180\"] [data-editor-rotation=\"270\"],\n      [data-main-rotation=\"270\"] [data-editor-rotation=\"180\"]\n    ) .editToolbar{\n        inset-inline-end:calc(0px - var(--editor-toolbar-vert-offset));\n        inset-block-start:0;\n      }\n\n[dir=\"rtl\"] .annotationEditorLayer\n    :is(\n      [data-main-rotation=\"0\"] [data-editor-rotation=\"90\"],\n      [data-main-rotation=\"90\"] [data-editor-rotation=\"0\"],\n      [data-main-rotation=\"180\"] [data-editor-rotation=\"270\"],\n      [data-main-rotation=\"270\"] [data-editor-rotation=\"180\"]\n    ) .editToolbar{\n        inset-inline-end:calc(100% + var(--editor-toolbar-vert-offset));\n        inset-block-start:0;\n      }\n\n.annotationEditorLayer\n    :is(\n      [data-main-rotation=\"0\"] [data-editor-rotation=\"180\"],\n      [data-main-rotation=\"90\"] [data-editor-rotation=\"90\"],\n      [data-main-rotation=\"180\"] [data-editor-rotation=\"0\"],\n      [data-main-rotation=\"270\"] [data-editor-rotation=\"270\"]\n    ) .editToolbar{\n      rotate:180deg;\n      inset-inline-end:100%;\n      inset-block-start:calc(0pc - var(--editor-toolbar-vert-offset));\n    }\n\n.annotationEditorLayer\n    :is(\n      [data-main-rotation=\"0\"] [data-editor-rotation=\"270\"],\n      [data-main-rotation=\"90\"] [data-editor-rotation=\"180\"],\n      [data-main-rotation=\"180\"] [data-editor-rotation=\"90\"],\n      [data-main-rotation=\"270\"] [data-editor-rotation=\"0\"]\n    ) .editToolbar{\n      rotate:90deg;\n    }\n\n[dir=\"ltr\"] .annotationEditorLayer\n    :is(\n      [data-main-rotation=\"0\"] [data-editor-rotation=\"270\"],\n      [data-main-rotation=\"90\"] [data-editor-rotation=\"180\"],\n      [data-main-rotation=\"180\"] [data-editor-rotation=\"90\"],\n      [data-main-rotation=\"270\"] [data-editor-rotation=\"0\"]\n    ) .editToolbar{\n        inset-inline-end:calc(100% + var(--editor-toolbar-vert-offset));\n        inset-block-start:100%;\n      }\n\n[dir=\"rtl\"] .annotationEditorLayer\n    :is(\n      [data-main-rotation=\"0\"] [data-editor-rotation=\"270\"],\n      [data-main-rotation=\"90\"] [data-editor-rotation=\"180\"],\n      [data-main-rotation=\"180\"] [data-editor-rotation=\"90\"],\n      [data-main-rotation=\"270\"] [data-editor-rotation=\"0\"]\n    ) .editToolbar{\n        inset-inline-start:calc(0px - var(--editor-toolbar-vert-offset));\n        inset-block-start:0;\n      }\n\n#altTextDialog{\n  --dialog-bg-color:white;\n  --dialog-border-color:white;\n  --dialog-shadow:0 2px 14px 0 rgb(58 57 68 / 0.2);\n  --text-primary-color:#15141a;\n  --text-secondary-color:#5b5b66;\n  --hover-filter:brightness(0.9);\n  --focus-ring-color:#0060df;\n  --focus-ring-outline:2px solid var(--focus-ring-color);\n\n  --textarea-border-color:#8f8f9d;\n  --textarea-bg-color:white;\n  --textarea-fg-color:var(--text-secondary-color);\n\n  --radio-bg-color:#f0f0f4;\n  --radio-checked-bg-color:#fbfbfe;\n  --radio-border-color:#8f8f9d;\n  --radio-checked-border-color:#0060df;\n\n  --button-cancel-bg-color:#f0f0f4;\n  --button-cancel-fg-color:var(--text-primary-color);\n  --button-cancel-border-color:var(--button-cancel-bg-color);\n  --button-cancel-hover-bg-color:var(--button-cancel-bg-color);\n  --button-cancel-hover-fg-color:var(--button-cancel-fg-color);\n  --button-cancel-hover-border-color:var(--button-cancel-hover-bg-color);\n\n  --button-save-bg-color:#0060df;\n  --button-save-fg-color:#fbfbfe;\n  --button-save-hover-bg-color:var(--button-save-bg-color);\n  --button-save-hover-fg-color:var(--button-save-fg-color);\n  --button-save-hover-border-color:var(--button-save-hover-bg-color);\n\n  font:message-box;\n  font-size:13px;\n  font-weight:400;\n  line-height:150%;\n  border-radius:4px;\n  padding:12px 16px;\n  border:1px solid var(--dialog-border-color);\n  background:var(--dialog-bg-color);\n  color:var(--text-primary-color);\n  box-shadow:var(--dialog-shadow);\n}\n\n@media (prefers-color-scheme: dark){\n\n:where(html:not(.is-light)) #altTextDialog{\n    --dialog-bg-color:#1c1b22;\n    --dialog-border-color:#1c1b22;\n    --dialog-shadow:0 2px 14px 0 #15141a;\n    --text-primary-color:#fbfbfe;\n    --text-secondary-color:#cfcfd8;\n    --focus-ring-color:#0df;\n    --hover-filter:brightness(1.4);\n\n    --textarea-bg-color:#42414d;\n\n    --radio-bg-color:#2b2a33;\n    --radio-checked-bg-color:#15141a;\n    --radio-checked-border-color:#0df;\n\n    --button-cancel-bg-color:#2b2a33;\n    --button-save-bg-color:#0df;\n    --button-save-fg-color:#15141a;\n}\n  }\n\n:where(html.is-dark) #altTextDialog{\n    --dialog-bg-color:#1c1b22;\n    --dialog-border-color:#1c1b22;\n    --dialog-shadow:0 2px 14px 0 #15141a;\n    --text-primary-color:#fbfbfe;\n    --text-secondary-color:#cfcfd8;\n    --focus-ring-color:#0df;\n    --hover-filter:brightness(1.4);\n\n    --textarea-bg-color:#42414d;\n\n    --radio-bg-color:#2b2a33;\n    --radio-checked-bg-color:#15141a;\n    --radio-checked-border-color:#0df;\n\n    --button-cancel-bg-color:#2b2a33;\n    --button-save-bg-color:#0df;\n    --button-save-fg-color:#15141a;\n}\n\n@media screen and (forced-colors: active){\n\n#altTextDialog{\n    --dialog-bg-color:Canvas;\n    --dialog-border-color:CanvasText;\n    --dialog-shadow:none;\n    --text-primary-color:CanvasText;\n    --text-secondary-color:CanvasText;\n    --hover-filter:none;\n    --focus-ring-color:ButtonBorder;\n\n    --textarea-border-color:ButtonBorder;\n    --textarea-bg-color:Field;\n    --textarea-fg-color:ButtonText;\n\n    --radio-bg-color:ButtonFace;\n    --radio-checked-bg-color:ButtonFace;\n    --radio-border-color:ButtonText;\n    --radio-checked-border-color:ButtonText;\n\n    --button-cancel-bg-color:ButtonFace;\n    --button-cancel-fg-color:ButtonText;\n    --button-cancel-border-color:ButtonText;\n    --button-cancel-hover-bg-color:AccentColor;\n    --button-cancel-hover-fg-color:AccentColorText;\n\n    --button-save-bg-color:ButtonText;\n    --button-save-fg-color:ButtonFace;\n    --button-save-hover-bg-color:AccentColor;\n    --button-save-hover-fg-color:AccentColorText;\n}\n  }\n\n#altTextDialog::backdrop{\n    -webkit-mask:url(#alttext-manager-mask);\n            mask:url(#alttext-manager-mask);\n  }\n\n#altTextDialog.positioned{\n    margin:0;\n  }\n\n#altTextDialog #altTextContainer{\n    width:300px;\n    height:-moz-fit-content;\n    height:fit-content;\n    display:inline-flex;\n    flex-direction:column;\n    align-items:flex-start;\n    gap:16px;\n  }\n\n#altTextDialog #altTextContainer *:focus-visible{\n      outline:var(--focus-ring-outline);\n      outline-offset:2px;\n    }\n\n#altTextDialog #altTextContainer .radio{\n      display:flex;\n      flex-direction:column;\n      align-items:flex-start;\n      gap:4px;\n    }\n\n#altTextDialog #altTextContainer .radio .radioButton{\n        display:flex;\n        gap:8px;\n        align-self:stretch;\n        align-items:center;\n      }\n\n#altTextDialog #altTextContainer .radio .radioButton input{\n          -webkit-appearance:none;\n             -moz-appearance:none;\n                  appearance:none;\n          box-sizing:border-box;\n          width:16px;\n          height:16px;\n          border-radius:50%;\n          background-color:var(--radio-bg-color);\n          border:1px solid var(--radio-border-color);\n        }\n\n#altTextDialog #altTextContainer .radio .radioButton input:hover{\n            filter:var(--hover-filter);\n          }\n\n#altTextDialog #altTextContainer .radio .radioButton input:checked{\n            background-color:var(--radio-checked-bg-color);\n            border:4px solid var(--radio-checked-border-color);\n          }\n\n#altTextDialog #altTextContainer .radio .radioLabel{\n        display:flex;\n        padding-inline-start:24px;\n        align-items:flex-start;\n        gap:10px;\n        align-self:stretch;\n      }\n\n#altTextDialog #altTextContainer .radio .radioLabel span{\n          flex:1 0 0;\n          font-size:11px;\n          color:var(--text-secondary-color);\n        }\n\n#altTextDialog #altTextContainer #overallDescription{\n      display:flex;\n      flex-direction:column;\n      align-items:flex-start;\n      gap:4px;\n      align-self:stretch;\n    }\n\n#altTextDialog #altTextContainer #overallDescription span{\n        align-self:stretch;\n      }\n\n#altTextDialog #altTextContainer #overallDescription .title{\n        font-size:13px;\n        font-style:normal;\n        font-weight:590;\n      }\n\n#altTextDialog #altTextContainer #addDescription{\n      display:flex;\n      flex-direction:column;\n      align-items:stretch;\n      gap:8px;\n    }\n\n#altTextDialog #altTextContainer #addDescription .descriptionArea{\n        flex:1;\n        padding-inline:24px 10px;\n      }\n\n#altTextDialog #altTextContainer #addDescription .descriptionArea textarea{\n          font:inherit;\n          width:100%;\n          min-height:75px;\n          padding:8px;\n          resize:none;\n          margin:0;\n          box-sizing:border-box;\n          border-radius:4px;\n          border:1px solid var(--textarea-border-color);\n          background:var(--textarea-bg-color);\n          color:var(--textarea-fg-color);\n        }\n\n#altTextDialog #altTextContainer #addDescription .descriptionArea textarea:focus{\n            outline-offset:0;\n            border-color:transparent;\n          }\n\n#altTextDialog #altTextContainer #addDescription .descriptionArea textarea:disabled{\n            pointer-events:none;\n            opacity:0.4;\n          }\n\n#altTextDialog #altTextContainer #buttons{\n      display:flex;\n      justify-content:flex-end;\n      align-items:flex-start;\n      gap:8px;\n      align-self:stretch;\n    }\n\n#altTextDialog #altTextContainer #buttons button{\n        border-radius:4px;\n        border:1px solid;\n        font:menu;\n        font-weight:600;\n        padding:4px 16px;\n        width:auto;\n        height:32px;\n      }\n\n#altTextDialog #altTextContainer #buttons button:hover{\n          cursor:pointer;\n          filter:var(--hover-filter);\n        }\n\n#altTextDialog #altTextContainer #buttons button#altTextCancel{\n          color:var(--button-cancel-fg-color);\n          background-color:var(--button-cancel-bg-color);\n          border-color:var(--button-cancel-border-color);\n        }\n\n#altTextDialog #altTextContainer #buttons button#altTextCancel:hover{\n            color:var(--button-cancel-hover-fg-color);\n            background-color:var(--button-cancel-hover-bg-color);\n            border-color:var(--button-cancel-hover-border-color);\n          }\n\n#altTextDialog #altTextContainer #buttons button#altTextSave{\n          color:var(--button-save-hover-fg-color);\n          background-color:var(--button-save-hover-bg-color);\n          border-color:var(--button-save-hover-border-color);\n          opacity:1;\n        }\n\n#altTextDialog #altTextContainer #buttons button#altTextSave:hover{\n            color:var(--button-save-hover-fg-color);\n            background-color:var(--button-save-hover-bg-color);\n            border-color:var(--button-save-hover-border-color);\n          }\n\n.colorPicker{\n  --hover-outline-color:#0250bb;\n  --selected-outline-color:#0060df;\n  --swatch-border-color:#cfcfd8;\n}\n\n@media (prefers-color-scheme: dark){\n\n:where(html:not(.is-light)) .colorPicker{\n    --hover-outline-color:#80ebff;\n    --selected-outline-color:#aaf2ff;\n    --swatch-border-color:#52525e;\n}\n  }\n\n:where(html.is-dark) .colorPicker{\n    --hover-outline-color:#80ebff;\n    --selected-outline-color:#aaf2ff;\n    --swatch-border-color:#52525e;\n}\n\n@media screen and (forced-colors: active){\n\n.colorPicker{\n    --hover-outline-color:Highlight;\n    --selected-outline-color:var(--hover-outline-color);\n    --swatch-border-color:ButtonText;\n}\n  }\n\n.colorPicker .swatch{\n    width:16px;\n    height:16px;\n    border:1px solid var(--swatch-border-color);\n    border-radius:100%;\n    outline-offset:2px;\n    box-sizing:border-box;\n    forced-color-adjust:none;\n  }\n\n.colorPicker button:is(:hover, .selected) > .swatch{\n    border:none;\n  }\n\n.annotationEditorLayer[data-main-rotation=\"0\"] .highlightEditor:not(.free) > .editToolbar{\n      rotate:0deg;\n    }\n\n.annotationEditorLayer[data-main-rotation=\"90\"] .highlightEditor:not(.free) > .editToolbar{\n      rotate:270deg;\n    }\n\n.annotationEditorLayer[data-main-rotation=\"180\"] .highlightEditor:not(.free) > .editToolbar{\n      rotate:180deg;\n    }\n\n.annotationEditorLayer[data-main-rotation=\"270\"] .highlightEditor:not(.free) > .editToolbar{\n      rotate:90deg;\n    }\n\n.annotationEditorLayer .highlightEditor{\n    position:absolute;\n    background:transparent;\n    z-index:1;\n    cursor:auto;\n    max-width:100%;\n    max-height:100%;\n    border:none;\n    outline:none;\n    pointer-events:none;\n    transform-origin:0 0;\n  }\n\n.annotationEditorLayer .highlightEditor:not(.free){\n      transform:none;\n    }\n\n.annotationEditorLayer .highlightEditor .internal{\n      position:absolute;\n      top:0;\n      left:0;\n      width:100%;\n      height:100%;\n      pointer-events:auto;\n    }\n\n.annotationEditorLayer .highlightEditor.disabled .internal{\n      pointer-events:none;\n    }\n\n.annotationEditorLayer .highlightEditor.selectedEditor .internal{\n        cursor:pointer;\n      }\n\n.annotationEditorLayer .highlightEditor .editToolbar{\n      --editor-toolbar-colorpicker-arrow-image:url(images/toolbarButton-menuArrow.svg);\n\n      transform-origin:center !important;\n    }\n\n.annotationEditorLayer .highlightEditor .editToolbar .buttons .colorPicker{\n          position:relative;\n          width:auto;\n          display:flex;\n          justify-content:center;\n          align-items:center;\n          gap:4px;\n          padding:4px;\n        }\n\n.annotationEditorLayer .highlightEditor .editToolbar .buttons .colorPicker::after{\n            content:\"\";\n            -webkit-mask-image:var(--editor-toolbar-colorpicker-arrow-image);\n                    mask-image:var(--editor-toolbar-colorpicker-arrow-image);\n            -webkit-mask-repeat:no-repeat;\n                    mask-repeat:no-repeat;\n            -webkit-mask-position:center;\n                    mask-position:center;\n            display:inline-block;\n            background-color:var(--editor-toolbar-fg-color);\n            width:12px;\n            height:12px;\n          }\n\n.annotationEditorLayer .highlightEditor .editToolbar .buttons .colorPicker:hover::after{\n            background-color:var(--editor-toolbar-hover-fg-color);\n          }\n\n.annotationEditorLayer .highlightEditor .editToolbar .buttons .colorPicker:has(.dropdown:not(.hidden)){\n            background-color:var(--editor-toolbar-hover-bg-color);\n          }\n\n.annotationEditorLayer .highlightEditor .editToolbar .buttons .colorPicker:has(.dropdown:not(.hidden))::after{\n              scale:-1;\n            }\n\n.annotationEditorLayer .highlightEditor .editToolbar .buttons .colorPicker .dropdown{\n            position:absolute;\n            display:flex;\n            justify-content:center;\n            align-items:center;\n            flex-direction:column;\n            gap:11px;\n            padding-block:8px;\n            border-radius:6px;\n            background-color:var(--editor-toolbar-bg-color);\n            border:1px solid var(--editor-toolbar-border-color);\n            box-shadow:var(--editor-toolbar-shadow);\n            inset-block-start:calc(100% + 4px);\n            width:calc(100% + 2 * var(--editor-toolbar-padding));\n          }\n\n.annotationEditorLayer .highlightEditor .editToolbar .buttons .colorPicker .dropdown button{\n              width:100%;\n              height:auto;\n              border:none;\n              cursor:pointer;\n              display:flex;\n              justify-content:center;\n              align-items:center;\n              background:none;\n            }\n\n.annotationEditorLayer .highlightEditor .editToolbar .buttons .colorPicker .dropdown button:is(:active, :focus-visible){\n                outline:none;\n              }\n\n.annotationEditorLayer .highlightEditor .editToolbar .buttons .colorPicker .dropdown button > .swatch{\n                outline-offset:2px;\n              }\n\n.annotationEditorLayer .highlightEditor .editToolbar .buttons .colorPicker .dropdown button[aria-selected=\"true\"] > .swatch{\n                outline:2px solid var(--selected-outline-color);\n              }\n\n.annotationEditorLayer .highlightEditor .editToolbar .buttons .colorPicker .dropdown button:is(:hover, :active, :focus-visible) > .swatch{\n                outline:2px solid var(--hover-outline-color);\n              }\n\n.editorParamsToolbar:has(#highlightParamsToolbarContainer){\n  padding:unset;\n}\n\n#highlightParamsToolbarContainer{\n  height:auto;\n  padding-inline:10px;\n  padding-block:10px 16px;\n  gap:16px;\n  display:flex;\n  flex-direction:column;\n  box-sizing:border-box;\n}\n\n#highlightParamsToolbarContainer .editorParamsLabel{\n    width:-moz-fit-content;\n    width:fit-content;\n    inset-inline-start:0;\n  }\n\n#highlightParamsToolbarContainer .colorPicker{\n    display:flex;\n    flex-direction:column;\n    gap:8px;\n  }\n\n#highlightParamsToolbarContainer .colorPicker .dropdown{\n      display:flex;\n      justify-content:space-between;\n      align-items:center;\n      flex-direction:row;\n      height:auto;\n    }\n\n#highlightParamsToolbarContainer .colorPicker .dropdown button{\n        width:auto;\n        height:auto;\n        border:none;\n        cursor:pointer;\n        display:flex;\n        justify-content:center;\n        align-items:center;\n        background:none;\n        flex:0 0 auto;\n      }\n\n#highlightParamsToolbarContainer .colorPicker .dropdown button .swatch{\n          width:24px;\n          height:24px;\n        }\n\n#highlightParamsToolbarContainer .colorPicker .dropdown button:is(:active, :focus-visible){\n          outline:none;\n        }\n\n#highlightParamsToolbarContainer .colorPicker .dropdown button[aria-selected=\"true\"] > .swatch{\n          outline:2px solid var(--selected-outline-color);\n        }\n\n#highlightParamsToolbarContainer .colorPicker .dropdown button:is(:hover, :active, :focus-visible) > .swatch{\n          outline:2px solid var(--hover-outline-color);\n        }\n\n#highlightParamsToolbarContainer #editorHighlightThickness{\n    display:flex;\n    flex-direction:column;\n    align-items:center;\n    gap:4px;\n    align-self:stretch;\n  }\n\n#highlightParamsToolbarContainer #editorHighlightThickness .editorParamsLabel{\n      width:100%;\n      height:auto;\n      align-self:stretch;\n    }\n\n#highlightParamsToolbarContainer #editorHighlightThickness .thicknessPicker{\n      display:flex;\n      justify-content:space-between;\n      align-items:center;\n      align-self:stretch;\n\n      --example-color:#bfbfc9;\n    }\n\n@media (prefers-color-scheme: dark){\n\n:where(html:not(.is-light)) #highlightParamsToolbarContainer #editorHighlightThickness .thicknessPicker{\n        --example-color:#80808e;\n    }\n      }\n\n:where(html.is-dark) #highlightParamsToolbarContainer #editorHighlightThickness .thicknessPicker{\n        --example-color:#80808e;\n    }\n\n@media screen and (forced-colors: active){\n\n#highlightParamsToolbarContainer #editorHighlightThickness .thicknessPicker{\n        --example-color:CanvasText;\n    }\n      }\n\n:is(#highlightParamsToolbarContainer #editorHighlightThickness .thicknessPicker > .editorParamsSlider[disabled]){\n        opacity:0.4;\n      }\n\n#highlightParamsToolbarContainer #editorHighlightThickness .thicknessPicker::before,\n      #highlightParamsToolbarContainer #editorHighlightThickness .thicknessPicker::after{\n        content:\"\";\n        width:8px;\n        aspect-ratio:1;\n        display:block;\n        border-radius:100%;\n        background-color:var(--example-color);\n      }\n\n#highlightParamsToolbarContainer #editorHighlightThickness .thicknessPicker::after{\n        width:24px;\n      }\n\n#highlightParamsToolbarContainer #editorHighlightThickness .thicknessPicker .editorParamsSlider{\n        width:unset;\n        height:14px;\n      }\n\n#highlightParamsToolbarContainer #editorHighlightVisibility{\n    display:flex;\n    flex-direction:column;\n    align-items:flex-start;\n    gap:8px;\n    align-self:stretch;\n  }\n\n#highlightParamsToolbarContainer #editorHighlightVisibility .divider{\n      --divider-color:#d7d7db;\n\n      margin-block:4px;\n      width:100%;\n      height:1px;\n      background-color:var(--divider-color);\n    }\n\n@media (prefers-color-scheme: dark){\n\n:where(html:not(.is-light)) #highlightParamsToolbarContainer #editorHighlightVisibility .divider{\n        --divider-color:#8f8f9d;\n    }\n      }\n\n:where(html.is-dark) #highlightParamsToolbarContainer #editorHighlightVisibility .divider{\n        --divider-color:#8f8f9d;\n    }\n\n@media screen and (forced-colors: active){\n\n#highlightParamsToolbarContainer #editorHighlightVisibility .divider{\n        --divider-color:CanvasText;\n    }\n      }\n\n#highlightParamsToolbarContainer #editorHighlightVisibility .toggler{\n      display:flex;\n      justify-content:space-between;\n      align-items:center;\n      align-self:stretch;\n    }\n\n:root{\n  --viewer-container-height:0;\n  --pdfViewer-padding-bottom:0;\n  --page-margin:1px auto -8px;\n  --page-border:9px solid transparent;\n  --spreadHorizontalWrapped-margin-LR:-3.5px;\n  --loading-icon-delay:400ms;\n}\n\n@media screen and (forced-colors: active){\n  :root{\n    --pdfViewer-padding-bottom:9px;\n    --page-margin:8px auto -1px;\n    --page-border:1px solid CanvasText;\n    --spreadHorizontalWrapped-margin-LR:3.5px;\n  }\n}\n\n[data-main-rotation=\"90\"]{\n  transform:rotate(90deg) translateY(-100%);\n}\n[data-main-rotation=\"180\"]{\n  transform:rotate(180deg) translate(-100%, -100%);\n}\n[data-main-rotation=\"270\"]{\n  transform:rotate(270deg) translateX(-100%);\n}\n\n#hiddenCopyElement,\n.hiddenCanvasElement{\n  position:absolute;\n  top:0;\n  left:0;\n  width:0;\n  height:0;\n  display:none;\n}\n\n.pdfViewer{\n  --scale-factor:1;\n\n  padding-bottom:var(--pdfViewer-padding-bottom);\n\n  --hcm-highlight-filter:none;\n  --hcm-highlight-selected-filter:none;\n}\n\n@media screen and (forced-colors: active){\n\n.pdfViewer{\n    --hcm-highlight-filter:invert(100%);\n}\n  }\n\n.pdfViewer .canvasWrapper{\n  overflow:hidden;\n  width:100%;\n  height:100%;\n}\n\n.pdfViewer .page{\n  direction:ltr;\n  width:816px;\n  height:1056px;\n  margin:var(--page-margin);\n  position:relative;\n  overflow:visible;\n  border:var(--page-border);\n  background-clip:content-box;\n  background-color:rgb(255 255 255);\n}\n\n.pdfViewer .dummyPage{\n  position:relative;\n  width:0;\n  height:var(--viewer-container-height);\n}\n\n.pdfViewer.noUserSelect{\n  -webkit-user-select:none;\n     -moz-user-select:none;\n          user-select:none;\n}\n\n.pdfViewer.removePageBorders .page{\n  margin:0 auto 10px;\n  border:none;\n}\n\n.pdfViewer:is(.scrollHorizontal, .scrollWrapped),\n.spread{\n  margin-inline:3.5px;\n  text-align:center;\n}\n\n.pdfViewer.scrollHorizontal,\n.spread{\n  white-space:nowrap;\n}\n\n.pdfViewer.removePageBorders,\n.pdfViewer:is(.scrollHorizontal, .scrollWrapped) .spread{\n  margin-inline:0;\n}\n\n.spread :is(.page, .dummyPage),\n.pdfViewer:is(.scrollHorizontal, .scrollWrapped) :is(.page, .spread){\n  display:inline-block;\n  vertical-align:middle;\n}\n\n.spread .page,\n.pdfViewer:is(.scrollHorizontal, .scrollWrapped) .page{\n  margin-inline:var(--spreadHorizontalWrapped-margin-LR);\n}\n\n.pdfViewer.removePageBorders .spread .page,\n.pdfViewer.removePageBorders:is(.scrollHorizontal, .scrollWrapped) .page{\n  margin-inline:5px;\n}\n\n.pdfViewer .page canvas{\n  margin:0;\n  display:block;\n}\n\n.pdfViewer .page canvas .structTree{\n  contain:strict;\n}\n\n.pdfViewer .page canvas[hidden]{\n  display:none;\n}\n\n.pdfViewer .page canvas[zooming]{\n  width:100%;\n  height:100%;\n}\n\n.pdfViewer .page.loadingIcon::after{\n  position:absolute;\n  top:0;\n  left:0;\n  content:\"\";\n  width:100%;\n  height:100%;\n  background:url(\"images/loading-icon.gif\") center no-repeat;\n  display:none;\n  transition-property:display;\n  transition-delay:var(--loading-icon-delay);\n  z-index:5;\n  contain:strict;\n}\n\n.pdfViewer .page.loading::after{\n  display:block;\n}\n\n.pdfViewer .page:not(.loading)::after{\n  transition-property:none;\n  display:none;\n}\n\n.pdfPresentationMode .pdfViewer{\n  padding-bottom:0;\n}\n\n.pdfPresentationMode .spread{\n  margin:0;\n}\n\n.pdfPresentationMode .pdfViewer .page{\n  margin:0 auto;\n  border:2px solid transparent;\n}\n\n:root{\n  --dir-factor:1;\n  --inline-start:left;\n  --inline-end:right;\n\n  --sidebar-width:200px;\n  --sidebar-transition-duration:200ms;\n  --sidebar-transition-timing-function:ease;\n\n  --toolbar-icon-opacity:0.7;\n  --doorhanger-icon-opacity:0.9;\n  --editor-toolbar-base-offset:105px;\n\n  --main-color:rgb(12 12 13);\n  --body-bg-color:rgb(212 212 215);\n  --progressBar-color:rgb(10 132 255);\n  --progressBar-bg-color:rgb(221 221 222);\n  --progressBar-blend-color:rgb(116 177 239);\n  --scrollbar-color:auto;\n  --scrollbar-bg-color:auto;\n  --toolbar-icon-bg-color:rgb(0 0 0);\n  --toolbar-icon-hover-bg-color:rgb(0 0 0);\n\n  --sidebar-narrow-bg-color:rgb(212 212 215 / 0.9);\n  --sidebar-toolbar-bg-color:rgb(245 246 247);\n  --toolbar-bg-color:rgb(249 249 250);\n  --toolbar-border-color:rgb(184 184 184);\n  --toolbar-box-shadow:0 1px 0 var(--toolbar-border-color);\n  --toolbar-border-bottom:none;\n  --toolbarSidebar-box-shadow:inset calc(-1px * var(--dir-factor)) 0 0 rgb(0 0 0 / 0.25), 0 1px 0 rgb(0 0 0 / 0.15), 0 0 1px rgb(0 0 0 / 0.1);\n  --toolbarSidebar-border-bottom:none;\n  --button-hover-color:rgb(221 222 223);\n  --toggled-btn-color:rgb(0 0 0);\n  --toggled-btn-bg-color:rgb(0 0 0 / 0.3);\n  --toggled-hover-active-btn-color:rgb(0 0 0 / 0.4);\n  --toggled-hover-btn-outline:none;\n  --dropdown-btn-bg-color:rgb(215 215 219);\n  --dropdown-btn-border:none;\n  --separator-color:rgb(0 0 0 / 0.3);\n  --field-color:rgb(6 6 6);\n  --field-bg-color:rgb(255 255 255);\n  --field-border-color:rgb(187 187 188);\n  --treeitem-color:rgb(0 0 0 / 0.8);\n  --treeitem-bg-color:rgb(0 0 0 / 0.15);\n  --treeitem-hover-color:rgb(0 0 0 / 0.9);\n  --treeitem-selected-color:rgb(0 0 0 / 0.9);\n  --treeitem-selected-bg-color:rgb(0 0 0 / 0.25);\n  --thumbnail-hover-color:rgb(0 0 0 / 0.1);\n  --thumbnail-selected-color:rgb(0 0 0 / 0.2);\n  --doorhanger-bg-color:rgb(255 255 255);\n  --doorhanger-border-color:rgb(12 12 13 / 0.2);\n  --doorhanger-hover-color:rgb(12 12 13);\n  --doorhanger-hover-bg-color:rgb(237 237 237);\n  --doorhanger-separator-color:rgb(222 222 222);\n  --dialog-button-border:none;\n  --dialog-button-bg-color:rgb(12 12 13 / 0.1);\n  --dialog-button-hover-bg-color:rgb(12 12 13 / 0.3);\n\n  --loading-icon:url(images/loading.svg);\n  --treeitem-expanded-icon:url(images/treeitem-expanded.svg);\n  --treeitem-collapsed-icon:url(images/treeitem-collapsed.svg);\n  --toolbarButton-editorFreeText-icon:url(images/toolbarButton-editorFreeText.svg);\n  --toolbarButton-editorHighlight-icon:url(images/toolbarButton-editorHighlight.svg);\n  --toolbarButton-editorInk-icon:url(images/toolbarButton-editorInk.svg);\n  --toolbarButton-editorStamp-icon:url(images/toolbarButton-editorStamp.svg);\n  --toolbarButton-menuArrow-icon:url(images/toolbarButton-menuArrow.svg);\n  --toolbarButton-sidebarToggle-icon:url(images/toolbarButton-sidebarToggle.svg);\n  --toolbarButton-secondaryToolbarToggle-icon:url(images/toolbarButton-secondaryToolbarToggle.svg);\n  --toolbarButton-pageUp-icon:url(images/toolbarButton-pageUp.svg);\n  --toolbarButton-pageDown-icon:url(images/toolbarButton-pageDown.svg);\n  --toolbarButton-zoomOut-icon:url(images/toolbarButton-zoomOut.svg);\n  --toolbarButton-zoomIn-icon:url(images/toolbarButton-zoomIn.svg);\n  --toolbarButton-presentationMode-icon:url(images/toolbarButton-presentationMode.svg);\n  --toolbarButton-print-icon:url(images/toolbarButton-print.svg);\n  --toolbarButton-openFile-icon:url(images/toolbarButton-openFile.svg);\n  --toolbarButton-download-icon:url(images/toolbarButton-download.svg);\n  --toolbarButton-bookmark-icon:url(images/toolbarButton-bookmark.svg);\n  --toolbarButton-viewThumbnail-icon:url(images/toolbarButton-viewThumbnail.svg);\n  --toolbarButton-viewOutline-icon:url(images/toolbarButton-viewOutline.svg);\n  --toolbarButton-viewAttachments-icon:url(images/toolbarButton-viewAttachments.svg);\n  --toolbarButton-viewLayers-icon:url(images/toolbarButton-viewLayers.svg);\n  --toolbarButton-currentOutlineItem-icon:url(images/toolbarButton-currentOutlineItem.svg);\n  --toolbarButton-search-icon:url(images/toolbarButton-search.svg);\n  --findbarButton-previous-icon:url(images/findbarButton-previous.svg);\n  --findbarButton-next-icon:url(images/findbarButton-next.svg);\n  --secondaryToolbarButton-firstPage-icon:url(images/secondaryToolbarButton-firstPage.svg);\n  --secondaryToolbarButton-lastPage-icon:url(images/secondaryToolbarButton-lastPage.svg);\n  --secondaryToolbarButton-rotateCcw-icon:url(images/secondaryToolbarButton-rotateCcw.svg);\n  --secondaryToolbarButton-rotateCw-icon:url(images/secondaryToolbarButton-rotateCw.svg);\n  --secondaryToolbarButton-selectTool-icon:url(images/secondaryToolbarButton-selectTool.svg);\n  --secondaryToolbarButton-handTool-icon:url(images/secondaryToolbarButton-handTool.svg);\n  --secondaryToolbarButton-scrollPage-icon:url(images/secondaryToolbarButton-scrollPage.svg);\n  --secondaryToolbarButton-scrollVertical-icon:url(images/secondaryToolbarButton-scrollVertical.svg);\n  --secondaryToolbarButton-scrollHorizontal-icon:url(images/secondaryToolbarButton-scrollHorizontal.svg);\n  --secondaryToolbarButton-scrollWrapped-icon:url(images/secondaryToolbarButton-scrollWrapped.svg);\n  --secondaryToolbarButton-spreadNone-icon:url(images/secondaryToolbarButton-spreadNone.svg);\n  --secondaryToolbarButton-spreadOdd-icon:url(images/secondaryToolbarButton-spreadOdd.svg);\n  --secondaryToolbarButton-spreadEven-icon:url(images/secondaryToolbarButton-spreadEven.svg);\n  --secondaryToolbarButton-documentProperties-icon:url(images/secondaryToolbarButton-documentProperties.svg);\n  --editorParams-stampAddImage-icon:url(images/toolbarButton-zoomIn.svg);\n}\n\n[dir=\"rtl\"]:root{\n  --dir-factor:-1;\n  --inline-start:right;\n  --inline-end:left;\n}\n\n@media (prefers-color-scheme: dark){\n  :root:where(:not(.is-light)){\n    --main-color:rgb(249 249 250);\n    --body-bg-color:rgb(42 42 46);\n    --progressBar-color:rgb(0 96 223);\n    --progressBar-bg-color:rgb(40 40 43);\n    --progressBar-blend-color:rgb(20 68 133);\n    --scrollbar-color:rgb(121 121 123);\n    --scrollbar-bg-color:rgb(35 35 39);\n    --toolbar-icon-bg-color:rgb(255 255 255);\n    --toolbar-icon-hover-bg-color:rgb(255 255 255);\n\n    --sidebar-narrow-bg-color:rgb(42 42 46 / 0.9);\n    --sidebar-toolbar-bg-color:rgb(50 50 52);\n    --toolbar-bg-color:rgb(56 56 61);\n    --toolbar-border-color:rgb(12 12 13);\n    --button-hover-color:rgb(102 102 103);\n    --toggled-btn-color:rgb(255 255 255);\n    --toggled-btn-bg-color:rgb(0 0 0 / 0.3);\n    --toggled-hover-active-btn-color:rgb(0 0 0 / 0.4);\n    --dropdown-btn-bg-color:rgb(74 74 79);\n    --separator-color:rgb(0 0 0 / 0.3);\n    --field-color:rgb(250 250 250);\n    --field-bg-color:rgb(64 64 68);\n    --field-border-color:rgb(115 115 115);\n    --treeitem-color:rgb(255 255 255 / 0.8);\n    --treeitem-bg-color:rgb(255 255 255 / 0.15);\n    --treeitem-hover-color:rgb(255 255 255 / 0.9);\n    --treeitem-selected-color:rgb(255 255 255 / 0.9);\n    --treeitem-selected-bg-color:rgb(255 255 255 / 0.25);\n    --thumbnail-hover-color:rgb(255 255 255 / 0.1);\n    --thumbnail-selected-color:rgb(255 255 255 / 0.2);\n    --doorhanger-bg-color:rgb(74 74 79);\n    --doorhanger-border-color:rgb(39 39 43);\n    --doorhanger-hover-color:rgb(249 249 250);\n    --doorhanger-hover-bg-color:rgb(93 94 98);\n    --doorhanger-separator-color:rgb(92 92 97);\n    --dialog-button-bg-color:rgb(92 92 97);\n    --dialog-button-hover-bg-color:rgb(115 115 115);\n  }\n}\n\n:root:where(.is-dark){\n    --main-color:rgb(249 249 250);\n    --body-bg-color:rgb(42 42 46);\n    --progressBar-color:rgb(0 96 223);\n    --progressBar-bg-color:rgb(40 40 43);\n    --progressBar-blend-color:rgb(20 68 133);\n    --scrollbar-color:rgb(121 121 123);\n    --scrollbar-bg-color:rgb(35 35 39);\n    --toolbar-icon-bg-color:rgb(255 255 255);\n    --toolbar-icon-hover-bg-color:rgb(255 255 255);\n\n    --sidebar-narrow-bg-color:rgb(42 42 46 / 0.9);\n    --sidebar-toolbar-bg-color:rgb(50 50 52);\n    --toolbar-bg-color:rgb(56 56 61);\n    --toolbar-border-color:rgb(12 12 13);\n    --button-hover-color:rgb(102 102 103);\n    --toggled-btn-color:rgb(255 255 255);\n    --toggled-btn-bg-color:rgb(0 0 0 / 0.3);\n    --toggled-hover-active-btn-color:rgb(0 0 0 / 0.4);\n    --dropdown-btn-bg-color:rgb(74 74 79);\n    --separator-color:rgb(0 0 0 / 0.3);\n    --field-color:rgb(250 250 250);\n    --field-bg-color:rgb(64 64 68);\n    --field-border-color:rgb(115 115 115);\n    --treeitem-color:rgb(255 255 255 / 0.8);\n    --treeitem-bg-color:rgb(255 255 255 / 0.15);\n    --treeitem-hover-color:rgb(255 255 255 / 0.9);\n    --treeitem-selected-color:rgb(255 255 255 / 0.9);\n    --treeitem-selected-bg-color:rgb(255 255 255 / 0.25);\n    --thumbnail-hover-color:rgb(255 255 255 / 0.1);\n    --thumbnail-selected-color:rgb(255 255 255 / 0.2);\n    --doorhanger-bg-color:rgb(74 74 79);\n    --doorhanger-border-color:rgb(39 39 43);\n    --doorhanger-hover-color:rgb(249 249 250);\n    --doorhanger-hover-bg-color:rgb(93 94 98);\n    --doorhanger-separator-color:rgb(92 92 97);\n    --dialog-button-bg-color:rgb(92 92 97);\n    --dialog-button-hover-bg-color:rgb(115 115 115);\n  }\n\n@media screen and (forced-colors: active){\n  :root{\n    --button-hover-color:Highlight;\n    --doorhanger-hover-bg-color:Highlight;\n    --toolbar-icon-opacity:1;\n    --toolbar-icon-bg-color:ButtonText;\n    --toolbar-icon-hover-bg-color:ButtonFace;\n    --toggled-hover-active-btn-color:ButtonText;\n    --toggled-hover-btn-outline:2px solid ButtonBorder;\n    --toolbar-border-color:CanvasText;\n    --toolbar-border-bottom:1px solid var(--toolbar-border-color);\n    --toolbar-box-shadow:none;\n    --toggled-btn-color:HighlightText;\n    --toggled-btn-bg-color:LinkText;\n    --doorhanger-hover-color:ButtonFace;\n    --doorhanger-border-color-whcm:1px solid ButtonText;\n    --doorhanger-triangle-opacity-whcm:0;\n    --dialog-button-border:1px solid Highlight;\n    --dialog-button-hover-bg-color:Highlight;\n    --dialog-button-hover-color:ButtonFace;\n    --dropdown-btn-border:1px solid ButtonText;\n    --field-border-color:ButtonText;\n    --main-color:CanvasText;\n    --separator-color:GrayText;\n    --doorhanger-separator-color:GrayText;\n    --toolbarSidebar-box-shadow:none;\n    --toolbarSidebar-border-bottom:1px solid var(--toolbar-border-color);\n  }\n}\n\n@media screen and (prefers-reduced-motion: reduce){\n  :root{\n    --sidebar-transition-duration:0;\n  }\n}\n\n*{\n  padding:0;\n  margin:0;\n}\n\nhtml,\nbody{\n  height:100%;\n  width:100%;\n}\n\nbody{\n  background-color:var(--body-bg-color);\n  scrollbar-color:var(--scrollbar-color) var(--scrollbar-bg-color);\n}\n\n.hidden,\n[hidden]{\n  display:none !important;\n}\n\n#viewerContainer.pdfPresentationMode:fullscreen{\n  top:0;\n  background-color:rgb(0 0 0);\n  width:100%;\n  height:100%;\n  overflow:hidden;\n  cursor:none;\n  -webkit-user-select:none;\n     -moz-user-select:none;\n          user-select:none;\n}\n\n.pdfPresentationMode:fullscreen section:not([data-internal-link]){\n  pointer-events:none;\n}\n\n.pdfPresentationMode:fullscreen .textLayer span{\n  cursor:none;\n}\n\n.pdfPresentationMode.pdfPresentationModeControls > *,\n.pdfPresentationMode.pdfPresentationModeControls .textLayer span{\n  cursor:default;\n}\n\n#outerContainer{\n  width:100%;\n  height:100%;\n  position:relative;\n}\n\n#sidebarContainer{\n  position:absolute;\n  inset-block:32px 0;\n  inset-inline-start:calc(-1 * var(--sidebar-width));\n  width:var(--sidebar-width);\n  visibility:hidden;\n  z-index:100;\n  font:message-box;\n  border-top:1px solid rgb(51 51 51);\n  border-inline-end:var(--doorhanger-border-color-whcm);\n  transition-property:inset-inline-start;\n  transition-duration:var(--sidebar-transition-duration);\n  transition-timing-function:var(--sidebar-transition-timing-function);\n}\n\n#outerContainer:is(.sidebarMoving, .sidebarOpen) #sidebarContainer{\n  visibility:visible;\n}\n#outerContainer.sidebarOpen #sidebarContainer{\n  inset-inline-start:0;\n}\n\n#mainContainer{\n  position:absolute;\n  inset:0;\n  min-width:350px;\n}\n\n#sidebarContent{\n  inset-block:32px 0;\n  inset-inline-start:0;\n  overflow:auto;\n  position:absolute;\n  width:100%;\n  box-shadow:inset calc(-1px * var(--dir-factor)) 0 0 rgb(0 0 0 / 0.25);\n}\n\n#viewerContainer{\n  overflow:auto;\n  position:absolute;\n  inset:32px 0 0;\n  outline:none;\n}\n#viewerContainer:not(.pdfPresentationMode){\n  transition-duration:var(--sidebar-transition-duration);\n  transition-timing-function:var(--sidebar-transition-timing-function);\n}\n\n#outerContainer.sidebarOpen #viewerContainer:not(.pdfPresentationMode){\n  inset-inline-start:var(--sidebar-width);\n  transition-property:inset-inline-start;\n}\n\n.toolbar{\n  position:relative;\n  inset-inline:0;\n  z-index:9999;\n  cursor:default;\n  font:message-box;\n}\n\n:is(.toolbar, .editorParamsToolbar, .findbar, #sidebarContainer)\n  :is(input, button, select),\n.secondaryToolbar :is(input, button, a, select){\n  outline:none;\n  font:message-box;\n}\n\n#toolbarContainer{\n  width:100%;\n}\n\n#toolbarSidebar{\n  width:100%;\n  height:32px;\n  background-color:var(--sidebar-toolbar-bg-color);\n  box-shadow:var(--toolbarSidebar-box-shadow);\n  border-bottom:var(--toolbarSidebar-border-bottom);\n}\n\n#sidebarResizer{\n  position:absolute;\n  inset-block:0;\n  inset-inline-end:-6px;\n  width:6px;\n  z-index:200;\n  cursor:ew-resize;\n}\n\n#toolbarContainer,\n.findbar,\n.secondaryToolbar,\n.editorParamsToolbar{\n  position:relative;\n  height:32px;\n  background-color:var(--toolbar-bg-color);\n  box-shadow:var(--toolbar-box-shadow);\n  border-bottom:var(--toolbar-border-bottom);\n}\n\n#toolbarViewer{\n  height:32px;\n}\n\n#loadingBar{\n  --progressBar-percent:0%;\n  --progressBar-end-offset:0;\n\n  position:absolute;\n  inset-inline:0 var(--progressBar-end-offset);\n  height:4px;\n  background-color:var(--progressBar-bg-color);\n  border-bottom:1px solid var(--toolbar-border-color);\n  transition-property:inset-inline-start;\n  transition-duration:var(--sidebar-transition-duration);\n  transition-timing-function:var(--sidebar-transition-timing-function);\n}\n\n#outerContainer.sidebarOpen #loadingBar{\n  inset-inline-start:var(--sidebar-width);\n}\n\n#loadingBar .progress{\n  position:absolute;\n  top:0;\n  inset-inline-start:0;\n  width:100%;\n  transform:scaleX(var(--progressBar-percent));\n  transform-origin:calc(50% - 50% * var(--dir-factor)) 0;\n  height:100%;\n  background-color:var(--progressBar-color);\n  overflow:hidden;\n  transition:transform 200ms;\n}\n\n@keyframes progressIndeterminate{\n  0%{\n    transform:translateX(calc(-142px * var(--dir-factor)));\n  }\n  100%{\n    transform:translateX(0);\n  }\n}\n\n#loadingBar.indeterminate .progress{\n  transform:none;\n  background-color:var(--progressBar-bg-color);\n  transition:none;\n}\n\n#loadingBar.indeterminate .progress .glimmer{\n  position:absolute;\n  top:0;\n  inset-inline-start:0;\n  height:100%;\n  width:calc(100% + 150px);\n  background:repeating-linear-gradient(\n    135deg,\n    var(--progressBar-blend-color) 0,\n    var(--progressBar-bg-color) 5px,\n    var(--progressBar-bg-color) 45px,\n    var(--progressBar-color) 55px,\n    var(--progressBar-color) 95px,\n    var(--progressBar-blend-color) 100px\n  );\n  animation:progressIndeterminate 1s linear infinite;\n}\n\n#outerContainer.sidebarResizing\n  :is(#sidebarContainer, #viewerContainer, #loadingBar){\n  transition-duration:0s;\n}\n\n.findbar,\n.secondaryToolbar,\n.editorParamsToolbar{\n  top:32px;\n  position:absolute;\n  z-index:30000;\n  height:auto;\n  padding:0 4px;\n  margin:4px 2px;\n  font:message-box;\n  font-size:12px;\n  line-height:14px;\n  text-align:left;\n  cursor:default;\n}\n\n.findbar{\n  inset-inline-start:64px;\n  min-width:300px;\n  background-color:var(--toolbar-bg-color);\n}\n.findbar > div{\n  height:32px;\n}\n.findbar > div#findbarInputContainer{\n  margin-inline-end:4px;\n}\n.findbar.wrapContainers > div,\n.findbar.wrapContainers > div#findbarMessageContainer > *{\n  clear:both;\n}\n.findbar.wrapContainers > div#findbarMessageContainer{\n  height:auto;\n}\n\n.findbar input[type=\"checkbox\"]{\n  pointer-events:none;\n}\n\n.findbar label{\n  -webkit-user-select:none;\n     -moz-user-select:none;\n          user-select:none;\n}\n\n.findbar label:hover,\n.findbar input:focus-visible + label{\n  color:var(--toggled-btn-color);\n  background-color:var(--button-hover-color);\n}\n\n.findbar .toolbarField[type=\"checkbox\"]:checked + .toolbarLabel{\n  background-color:var(--toggled-btn-bg-color) !important;\n  color:var(--toggled-btn-color);\n}\n\n#findInput{\n  width:200px;\n}\n\n#findInput::-moz-placeholder{\n    font-style:normal;\n  }\n\n#findInput::placeholder{\n    font-style:normal;\n  }\n\n.loadingInput:has(> #findInput[data-status=\"pending\"])::after{\n    display:block;\n    visibility:visible;\n  }\n\n#findInput[data-status=\"notFound\"]{\n    background-color:rgb(255 102 102);\n  }\n\n.secondaryToolbar,\n.editorParamsToolbar{\n  padding:6px 0 10px;\n  inset-inline-end:4px;\n  height:auto;\n  background-color:var(--doorhanger-bg-color);\n}\n\n.editorParamsToolbarContainer{\n  width:220px;\n  margin-bottom:-4px;\n}\n\n.editorParamsToolbarContainer > .editorParamsSetter{\n  min-height:26px;\n  display:flex;\n  align-items:center;\n  justify-content:space-between;\n  padding-inline:10px;\n}\n\n.editorParamsToolbarContainer .editorParamsLabel{\n  padding-inline-end:10px;\n  flex:none;\n  font:menu;\n  font-size:13px;\n  font-style:normal;\n  font-weight:400;\n  line-height:150%;\n  color:var(--main-color);\n}\n\n.editorParamsToolbarContainer .editorParamsColor{\n  width:32px;\n  height:32px;\n  flex:none;\n}\n\n.editorParamsToolbarContainer .editorParamsSlider{\n  background-color:transparent;\n  width:90px;\n  flex:0 1 0;\n}\n\n.editorParamsToolbarContainer .editorParamsSlider::-moz-range-progress{\n  background-color:black;\n}\n\n.editorParamsToolbarContainer .editorParamsSlider::-webkit-slider-runnable-track,\n.editorParamsToolbarContainer .editorParamsSlider::-moz-range-track{\n  background-color:black;\n}\n\n.editorParamsToolbarContainer .editorParamsSlider::-webkit-slider-thumb,\n.editorParamsToolbarContainer .editorParamsSlider::-moz-range-thumb{\n  background-color:white;\n}\n\n#secondaryToolbarButtonContainer{\n  max-width:220px;\n  min-height:26px;\n  max-height:calc(var(--viewer-container-height) - 40px);\n  overflow-y:auto;\n  margin-bottom:-4px;\n}\n\n#editorStampParamsToolbar{\n  inset-inline-end:calc(var(--editor-toolbar-base-offset) + 0px);\n}\n\n#editorInkParamsToolbar{\n  inset-inline-end:calc(var(--editor-toolbar-base-offset) + 28px);\n}\n\n#editorFreeTextParamsToolbar{\n  inset-inline-end:calc(var(--editor-toolbar-base-offset) + 56px);\n}\n\n#editorHighlightParamsToolbar{\n  inset-inline-end:calc(var(--editor-toolbar-base-offset) + 84px);\n}\n\n#editorStampAddImage::before{\n  -webkit-mask-image:var(--editorParams-stampAddImage-icon);\n          mask-image:var(--editorParams-stampAddImage-icon);\n}\n\n.doorHanger,\n.doorHangerRight{\n  border-radius:2px;\n  box-shadow:0 1px 5px var(--doorhanger-border-color), 0 0 0 1px var(--doorhanger-border-color);\n  border:var(--doorhanger-border-color-whcm);\n}\n:is(.doorHanger, .doorHangerRight)::after,\n:is(.doorHanger, .doorHangerRight)::before{\n  bottom:100%;\n  border:8px solid rgb(0 0 0 / 0);\n  content:\" \";\n  height:0;\n  width:0;\n  position:absolute;\n  pointer-events:none;\n  opacity:var(--doorhanger-triangle-opacity-whcm);\n}\n.doorHanger::after{\n  inset-inline-start:10px;\n  margin-inline-start:-8px;\n  border-bottom-color:var(--toolbar-bg-color);\n}\n.doorHangerRight::after{\n  inset-inline-end:10px;\n  margin-inline-end:-8px;\n  border-bottom-color:var(--doorhanger-bg-color);\n}\n:is(.doorHanger, .doorHangerRight)::before{\n  border-bottom-color:var(--doorhanger-border-color);\n  border-width:9px;\n}\n.doorHanger::before{\n  inset-inline-start:10px;\n  margin-inline-start:-9px;\n}\n.doorHangerRight::before{\n  inset-inline-end:10px;\n  margin-inline-end:-9px;\n}\n\n#findResultsCount{\n  background-color:rgb(217 217 217);\n  color:rgb(82 82 82);\n  text-align:center;\n  padding:4px 5px;\n  margin:5px;\n}\n\n#findMsg[data-status=\"notFound\"]{\n  font-weight:bold;\n}\n\n:is(#findResultsCount, #findMsg):empty{\n  display:none;\n}\n\n#toolbarViewerMiddle{\n  position:absolute;\n  left:50%;\n  transform:translateX(-50%);\n}\n\n#toolbarViewerLeft,\n#toolbarSidebarLeft{\n  float:var(--inline-start);\n}\n#toolbarViewerRight,\n#toolbarSidebarRight{\n  float:var(--inline-end);\n}\n\n#toolbarViewerLeft > *,\n#toolbarViewerMiddle > *,\n#toolbarViewerRight > *,\n#toolbarSidebarLeft *,\n#toolbarSidebarRight *,\n.findbar *{\n  position:relative;\n  float:var(--inline-start);\n}\n\n#toolbarViewerLeft{\n  padding-inline-start:1px;\n}\n#toolbarViewerRight{\n  padding-inline-end:1px;\n}\n#toolbarSidebarRight{\n  padding-inline-end:2px;\n}\n\n.splitToolbarButton{\n  margin:2px;\n  display:inline-block;\n}\n.splitToolbarButton > .toolbarButton{\n  float:var(--inline-start);\n}\n\n.toolbarButton,\n.secondaryToolbarButton,\n.dialogButton{\n  border:none;\n  background:none;\n  width:28px;\n  height:28px;\n  outline:none;\n}\n\n.dialogButton:is(:hover, :focus-visible){\n  background-color:var(--dialog-button-hover-bg-color);\n}\n\n.dialogButton:is(:hover, :focus-visible) > span{\n  color:var(--dialog-button-hover-color);\n}\n\n.toolbarButton > span{\n  display:inline-block;\n  width:0;\n  height:0;\n  overflow:hidden;\n}\n\n:is(.toolbarButton, .secondaryToolbarButton, .dialogButton)[disabled]{\n  opacity:0.5;\n}\n\n.splitToolbarButton > .toolbarButton:is(:hover, :focus-visible),\n.dropdownToolbarButton:hover{\n  background-color:var(--button-hover-color);\n}\n.splitToolbarButton > .toolbarButton{\n  position:relative;\n  margin:0;\n}\n#toolbarSidebar .splitToolbarButton > .toolbarButton{\n  margin-inline-end:2px;\n}\n\n.splitToolbarButtonSeparator{\n  float:var(--inline-start);\n  margin:4px 0;\n  width:1px;\n  height:20px;\n  background-color:var(--separator-color);\n}\n\n.toolbarButton,\n.dropdownToolbarButton,\n.secondaryToolbarButton,\n.dialogButton{\n  min-width:16px;\n  margin:2px 1px;\n  padding:2px 6px 0;\n  border:none;\n  border-radius:2px;\n  color:var(--main-color);\n  font-size:12px;\n  line-height:14px;\n  -webkit-user-select:none;\n     -moz-user-select:none;\n          user-select:none;\n  cursor:default;\n  box-sizing:border-box;\n}\n\n.toolbarButton:is(:hover, :focus-visible){\n  background-color:var(--button-hover-color);\n}\n.secondaryToolbarButton:is(:hover, :focus-visible){\n  background-color:var(--doorhanger-hover-bg-color);\n  color:var(--doorhanger-hover-color);\n}\n\n:is(.toolbarButton, .secondaryToolbarButton).toggled,\n.splitToolbarButton.toggled > .toolbarButton.toggled{\n  background-color:var(--toggled-btn-bg-color);\n  color:var(--toggled-btn-color);\n}\n\n:is(.toolbarButton, .secondaryToolbarButton).toggled:hover,\n.splitToolbarButton.toggled > .toolbarButton.toggled:hover{\n  outline:var(--toggled-hover-btn-outline) !important;\n}\n\n:is(.toolbarButton, .secondaryToolbarButton).toggled::before{\n  background-color:var(--toggled-btn-color);\n}\n\n:is(.toolbarButton, .secondaryToolbarButton).toggled:hover:active,\n.splitToolbarButton.toggled > .toolbarButton.toggled:hover:active{\n  background-color:var(--toggled-hover-active-btn-color);\n}\n\n.dropdownToolbarButton{\n  display:flex;\n  width:-moz-fit-content;\n  width:fit-content;\n  min-width:140px;\n  padding:0;\n  background-color:var(--dropdown-btn-bg-color);\n  border:var(--dropdown-btn-border);\n}\n.dropdownToolbarButton::after{\n  top:6px;\n  inset-inline-end:6px;\n  pointer-events:none;\n  -webkit-mask-image:var(--toolbarButton-menuArrow-icon);\n          mask-image:var(--toolbarButton-menuArrow-icon);\n}\n\n.dropdownToolbarButton > select{\n  -webkit-appearance:none;\n     -moz-appearance:none;\n          appearance:none;\n  width:inherit;\n  min-width:inherit;\n  height:28px;\n  font-size:12px;\n  color:var(--main-color);\n  margin:0;\n  padding-block:1px 2px;\n  padding-inline:6px 38px;\n  border:none;\n  background-color:var(--dropdown-btn-bg-color);\n}\n.dropdownToolbarButton > select:is(:hover, :focus-visible){\n  background-color:var(--button-hover-color);\n  color:var(--toggled-btn-color);\n}\n.dropdownToolbarButton > select > option{\n  background:var(--doorhanger-bg-color);\n  color:var(--main-color);\n}\n\n.toolbarButtonSpacer{\n  width:30px;\n  display:inline-block;\n  height:1px;\n}\n\n:is(.toolbarButton, .secondaryToolbarButton, .treeItemToggler)::before,\n.dropdownToolbarButton::after{\n  position:absolute;\n  display:inline-block;\n  width:16px;\n  height:16px;\n\n  content:\"\";\n  background-color:var(--toolbar-icon-bg-color);\n  -webkit-mask-size:cover;\n          mask-size:cover;\n}\n\n.dropdownToolbarButton:is(:hover, :focus-visible, :active)::after{\n  background-color:var(--toolbar-icon-hover-bg-color);\n}\n\n.toolbarButton::before{\n  opacity:var(--toolbar-icon-opacity);\n  top:6px;\n  left:6px;\n}\n\n.toolbarButton:is(:hover, :focus-visible)::before,\n.secondaryToolbarButton:is(:hover, :focus-visible)::before{\n  background-color:var(--toolbar-icon-hover-bg-color);\n}\n\n.secondaryToolbarButton::before{\n  opacity:var(--doorhanger-icon-opacity);\n  top:5px;\n  inset-inline-start:12px;\n}\n\n#sidebarToggle::before{\n  -webkit-mask-image:var(--toolbarButton-sidebarToggle-icon);\n          mask-image:var(--toolbarButton-sidebarToggle-icon);\n  transform:scaleX(var(--dir-factor));\n}\n\n#secondaryToolbarToggle::before{\n  -webkit-mask-image:var(--toolbarButton-secondaryToolbarToggle-icon);\n          mask-image:var(--toolbarButton-secondaryToolbarToggle-icon);\n  transform:scaleX(var(--dir-factor));\n}\n\n#findPrevious::before{\n  -webkit-mask-image:var(--findbarButton-previous-icon);\n          mask-image:var(--findbarButton-previous-icon);\n}\n\n#findNext::before{\n  -webkit-mask-image:var(--findbarButton-next-icon);\n          mask-image:var(--findbarButton-next-icon);\n}\n\n#previous::before{\n  -webkit-mask-image:var(--toolbarButton-pageUp-icon);\n          mask-image:var(--toolbarButton-pageUp-icon);\n}\n\n#next::before{\n  -webkit-mask-image:var(--toolbarButton-pageDown-icon);\n          mask-image:var(--toolbarButton-pageDown-icon);\n}\n\n#zoomOut::before{\n  -webkit-mask-image:var(--toolbarButton-zoomOut-icon);\n          mask-image:var(--toolbarButton-zoomOut-icon);\n}\n\n#zoomIn::before{\n  -webkit-mask-image:var(--toolbarButton-zoomIn-icon);\n          mask-image:var(--toolbarButton-zoomIn-icon);\n}\n\n#presentationMode::before{\n  -webkit-mask-image:var(--toolbarButton-presentationMode-icon);\n          mask-image:var(--toolbarButton-presentationMode-icon);\n}\n\n#editorFreeText::before{\n  -webkit-mask-image:var(--toolbarButton-editorFreeText-icon);\n          mask-image:var(--toolbarButton-editorFreeText-icon);\n}\n\n#editorHighlight::before{\n  -webkit-mask-image:var(--toolbarButton-editorHighlight-icon);\n          mask-image:var(--toolbarButton-editorHighlight-icon);\n}\n\n#editorInk::before{\n  -webkit-mask-image:var(--toolbarButton-editorInk-icon);\n          mask-image:var(--toolbarButton-editorInk-icon);\n}\n\n#editorStamp::before{\n  -webkit-mask-image:var(--toolbarButton-editorStamp-icon);\n          mask-image:var(--toolbarButton-editorStamp-icon);\n}\n\n:is(#print, #secondaryPrint)::before{\n  -webkit-mask-image:var(--toolbarButton-print-icon);\n          mask-image:var(--toolbarButton-print-icon);\n}\n\n#secondaryOpenFile::before{\n  -webkit-mask-image:var(--toolbarButton-openFile-icon);\n          mask-image:var(--toolbarButton-openFile-icon);\n}\n\n:is(#download, #secondaryDownload)::before{\n  -webkit-mask-image:var(--toolbarButton-download-icon);\n          mask-image:var(--toolbarButton-download-icon);\n}\n\na.secondaryToolbarButton{\n  padding-top:5px;\n  text-decoration:none;\n}\na:is(.toolbarButton, .secondaryToolbarButton)[href=\"#\"]{\n  opacity:0.5;\n  pointer-events:none;\n}\n\n#viewBookmark::before{\n  -webkit-mask-image:var(--toolbarButton-bookmark-icon);\n          mask-image:var(--toolbarButton-bookmark-icon);\n}\n\n#viewThumbnail::before{\n  -webkit-mask-image:var(--toolbarButton-viewThumbnail-icon);\n          mask-image:var(--toolbarButton-viewThumbnail-icon);\n}\n\n#viewOutline::before{\n  -webkit-mask-image:var(--toolbarButton-viewOutline-icon);\n          mask-image:var(--toolbarButton-viewOutline-icon);\n  transform:scaleX(var(--dir-factor));\n}\n\n#viewAttachments::before{\n  -webkit-mask-image:var(--toolbarButton-viewAttachments-icon);\n          mask-image:var(--toolbarButton-viewAttachments-icon);\n}\n\n#viewLayers::before{\n  -webkit-mask-image:var(--toolbarButton-viewLayers-icon);\n          mask-image:var(--toolbarButton-viewLayers-icon);\n}\n\n#currentOutlineItem::before{\n  -webkit-mask-image:var(--toolbarButton-currentOutlineItem-icon);\n          mask-image:var(--toolbarButton-currentOutlineItem-icon);\n  transform:scaleX(var(--dir-factor));\n}\n\n#viewFind::before{\n  -webkit-mask-image:var(--toolbarButton-search-icon);\n          mask-image:var(--toolbarButton-search-icon);\n}\n\n.pdfSidebarNotification::after{\n  position:absolute;\n  display:inline-block;\n  top:2px;\n  inset-inline-end:2px;\n  content:\"\";\n  background-color:rgb(112 219 85);\n  height:9px;\n  width:9px;\n  border-radius:50%;\n}\n\n.secondaryToolbarButton{\n  position:relative;\n  margin:0;\n  padding:0 0 1px;\n  padding-inline-start:36px;\n  height:auto;\n  min-height:26px;\n  width:auto;\n  min-width:100%;\n  text-align:start;\n  white-space:normal;\n  border-radius:0;\n  box-sizing:border-box;\n  display:inline-block;\n}\n.secondaryToolbarButton > span{\n  padding-inline-end:4px;\n}\n\n#firstPage::before{\n  -webkit-mask-image:var(--secondaryToolbarButton-firstPage-icon);\n          mask-image:var(--secondaryToolbarButton-firstPage-icon);\n}\n\n#lastPage::before{\n  -webkit-mask-image:var(--secondaryToolbarButton-lastPage-icon);\n          mask-image:var(--secondaryToolbarButton-lastPage-icon);\n}\n\n#pageRotateCcw::before{\n  -webkit-mask-image:var(--secondaryToolbarButton-rotateCcw-icon);\n          mask-image:var(--secondaryToolbarButton-rotateCcw-icon);\n}\n\n#pageRotateCw::before{\n  -webkit-mask-image:var(--secondaryToolbarButton-rotateCw-icon);\n          mask-image:var(--secondaryToolbarButton-rotateCw-icon);\n}\n\n#cursorSelectTool::before{\n  -webkit-mask-image:var(--secondaryToolbarButton-selectTool-icon);\n          mask-image:var(--secondaryToolbarButton-selectTool-icon);\n}\n\n#cursorHandTool::before{\n  -webkit-mask-image:var(--secondaryToolbarButton-handTool-icon);\n          mask-image:var(--secondaryToolbarButton-handTool-icon);\n}\n\n#scrollPage::before{\n  -webkit-mask-image:var(--secondaryToolbarButton-scrollPage-icon);\n          mask-image:var(--secondaryToolbarButton-scrollPage-icon);\n}\n\n#scrollVertical::before{\n  -webkit-mask-image:var(--secondaryToolbarButton-scrollVertical-icon);\n          mask-image:var(--secondaryToolbarButton-scrollVertical-icon);\n}\n\n#scrollHorizontal::before{\n  -webkit-mask-image:var(--secondaryToolbarButton-scrollHorizontal-icon);\n          mask-image:var(--secondaryToolbarButton-scrollHorizontal-icon);\n}\n\n#scrollWrapped::before{\n  -webkit-mask-image:var(--secondaryToolbarButton-scrollWrapped-icon);\n          mask-image:var(--secondaryToolbarButton-scrollWrapped-icon);\n}\n\n#spreadNone::before{\n  -webkit-mask-image:var(--secondaryToolbarButton-spreadNone-icon);\n          mask-image:var(--secondaryToolbarButton-spreadNone-icon);\n}\n\n#spreadOdd::before{\n  -webkit-mask-image:var(--secondaryToolbarButton-spreadOdd-icon);\n          mask-image:var(--secondaryToolbarButton-spreadOdd-icon);\n}\n\n#spreadEven::before{\n  -webkit-mask-image:var(--secondaryToolbarButton-spreadEven-icon);\n          mask-image:var(--secondaryToolbarButton-spreadEven-icon);\n}\n\n#documentProperties::before{\n  -webkit-mask-image:var(--secondaryToolbarButton-documentProperties-icon);\n          mask-image:var(--secondaryToolbarButton-documentProperties-icon);\n}\n\n.verticalToolbarSeparator{\n  display:block;\n  margin:5px 2px;\n  width:1px;\n  height:22px;\n  background-color:var(--separator-color);\n}\n.horizontalToolbarSeparator{\n  display:block;\n  margin:6px 0;\n  height:1px;\n  width:100%;\n  background-color:var(--doorhanger-separator-color);\n}\n\n.toolbarField{\n  padding:4px 7px;\n  margin:3px 0;\n  border-radius:2px;\n  background-color:var(--field-bg-color);\n  background-clip:padding-box;\n  border:1px solid var(--field-border-color);\n  box-shadow:none;\n  color:var(--field-color);\n  font-size:12px;\n  line-height:16px;\n  outline:none;\n}\n\n.toolbarField[type=\"checkbox\"]{\n  opacity:0;\n  position:absolute !important;\n  left:0;\n  margin:10px 0 3px;\n  margin-inline-start:7px;\n}\n\n#pageNumber{\n  -moz-appearance:textfield;\n  text-align:end;\n  width:40px;\n  background-size:0 0;\n  transition-property:none;\n}\n\n#pageNumber::-webkit-inner-spin-button{\n    -webkit-appearance:none;\n  }\n\n.loadingInput:has(> #pageNumber.loading)::after{\n    display:block;\n    visibility:visible;\n\n    transition-property:visibility;\n    transition-delay:var(--loading-icon-delay);\n  }\n\n.loadingInput::after{\n    position:absolute;\n    visibility:hidden;\n    display:none;\n    top:calc(50% - 8px);\n    width:16px;\n    height:16px;\n\n    content:\"\";\n    background-color:var(--toolbar-icon-bg-color);\n    -webkit-mask-size:cover;\n            mask-size:cover;\n    -webkit-mask-image:var(--loading-icon);\n            mask-image:var(--loading-icon);\n  }\n\n.loadingInput.start::after{\n    inset-inline-start:4px;\n  }\n\n.loadingInput.end::after{\n    inset-inline-end:4px;\n  }\n\n.toolbarField:focus{\n  border-color:#0a84ff;\n}\n\n.toolbarLabel{\n  min-width:16px;\n  padding:7px;\n  margin:2px;\n  border-radius:2px;\n  color:var(--main-color);\n  font-size:12px;\n  line-height:14px;\n  text-align:left;\n  -webkit-user-select:none;\n     -moz-user-select:none;\n          user-select:none;\n  cursor:default;\n}\n\n#numPages.toolbarLabel{\n  padding-inline-start:3px;\n}\n\n#thumbnailView,\n#outlineView,\n#attachmentsView,\n#layersView{\n  position:absolute;\n  width:calc(100% - 8px);\n  inset-block:0;\n  padding:4px 4px 0;\n  overflow:auto;\n  -webkit-user-select:none;\n     -moz-user-select:none;\n          user-select:none;\n}\n#thumbnailView{\n  width:calc(100% - 60px);\n  padding:10px 30px 0;\n}\n\n#thumbnailView > a:is(:active, :focus){\n  outline:0;\n}\n\n.thumbnail{\n  --thumbnail-width:0;\n  --thumbnail-height:0;\n\n  float:var(--inline-start);\n  width:var(--thumbnail-width);\n  height:var(--thumbnail-height);\n  margin:0 10px 5px;\n  padding:1px;\n  border:7px solid transparent;\n  border-radius:2px;\n}\n\n#thumbnailView > a:last-of-type > .thumbnail{\n  margin-bottom:10px;\n}\n\na:focus > .thumbnail,\n.thumbnail:hover{\n  border-color:var(--thumbnail-hover-color);\n}\n.thumbnail.selected{\n  border-color:var(--thumbnail-selected-color) !important;\n}\n\n.thumbnailImage{\n  width:var(--thumbnail-width);\n  height:var(--thumbnail-height);\n  opacity:0.9;\n}\na:focus > .thumbnail > .thumbnailImage,\n.thumbnail:hover > .thumbnailImage{\n  opacity:0.95;\n}\n.thumbnail.selected > .thumbnailImage{\n  opacity:1 !important;\n}\n\n.thumbnail:not([data-loaded]) > .thumbnailImage{\n  width:calc(var(--thumbnail-width) - 2px);\n  height:calc(var(--thumbnail-height) - 2px);\n  border:1px dashed rgb(132 132 132);\n}\n\n.treeWithDeepNesting > .treeItem,\n.treeItem > .treeItems{\n  margin-inline-start:20px;\n}\n\n.treeItem > a{\n  text-decoration:none;\n  display:inline-block;\n  min-width:calc(100% - 4px);\n  height:auto;\n  margin-bottom:1px;\n  padding:2px 0 5px;\n  padding-inline-start:4px;\n  border-radius:2px;\n  color:var(--treeitem-color);\n  font-size:13px;\n  line-height:15px;\n  -webkit-user-select:none;\n     -moz-user-select:none;\n          user-select:none;\n  white-space:normal;\n  cursor:pointer;\n}\n\n#layersView .treeItem > a *{\n  cursor:pointer;\n}\n#layersView .treeItem > a > label{\n  padding-inline-start:4px;\n}\n#layersView .treeItem > a > label > input{\n  float:var(--inline-start);\n  margin-top:1px;\n}\n\n.treeItemToggler{\n  position:relative;\n  float:var(--inline-start);\n  height:0;\n  width:0;\n  color:rgb(255 255 255 / 0.5);\n}\n.treeItemToggler::before{\n  inset-inline-end:4px;\n  -webkit-mask-image:var(--treeitem-expanded-icon);\n          mask-image:var(--treeitem-expanded-icon);\n}\n.treeItemToggler.treeItemsHidden::before{\n  -webkit-mask-image:var(--treeitem-collapsed-icon);\n          mask-image:var(--treeitem-collapsed-icon);\n  transform:scaleX(var(--dir-factor));\n}\n.treeItemToggler.treeItemsHidden ~ .treeItems{\n  display:none;\n}\n\n.treeItem.selected > a{\n  background-color:var(--treeitem-selected-bg-color);\n  color:var(--treeitem-selected-color);\n}\n\n.treeItemToggler:hover,\n.treeItemToggler:hover + a,\n.treeItemToggler:hover ~ .treeItems,\n.treeItem > a:hover{\n  background-color:var(--treeitem-bg-color);\n  background-clip:padding-box;\n  border-radius:2px;\n  color:var(--treeitem-hover-color);\n}\n\n#outlineOptionsContainer{\n  display:none;\n}\n\n#sidebarContainer:has(#outlineView:not(.hidden)) #outlineOptionsContainer{\n    display:inherit;\n  }\n\n.dialogButton{\n  width:auto;\n  margin:3px 4px 2px !important;\n  padding:2px 11px;\n  color:var(--main-color);\n  background-color:var(--dialog-button-bg-color);\n  border:var(--dialog-button-border) !important;\n}\n\ndialog{\n  margin:auto;\n  padding:15px;\n  border-spacing:4px;\n  color:var(--main-color);\n  font:message-box;\n  font-size:12px;\n  line-height:14px;\n  background-color:var(--doorhanger-bg-color);\n  border:1px solid rgb(0 0 0 / 0.5);\n  border-radius:4px;\n  box-shadow:0 1px 4px rgb(0 0 0 / 0.3);\n}\ndialog::backdrop{\n  background-color:rgb(0 0 0 / 0.2);\n}\n\ndialog > .row{\n  display:table-row;\n}\n\ndialog > .row > *{\n  display:table-cell;\n}\n\ndialog .toolbarField{\n  margin:5px 0;\n}\n\ndialog .separator{\n  display:block;\n  margin:4px 0;\n  height:1px;\n  width:100%;\n  background-color:var(--separator-color);\n}\n\ndialog .buttonRow{\n  text-align:center;\n  vertical-align:middle;\n}\n\ndialog :link{\n  color:rgb(255 255 255);\n}\n\n#passwordDialog{\n  text-align:center;\n}\n#passwordDialog .toolbarField{\n  width:200px;\n}\n\n#documentPropertiesDialog{\n  text-align:left;\n}\n#documentPropertiesDialog .row > *{\n  min-width:100px;\n  text-align:start;\n}\n#documentPropertiesDialog .row > span{\n  width:125px;\n  word-wrap:break-word;\n}\n#documentPropertiesDialog .row > p{\n  max-width:225px;\n  word-wrap:break-word;\n}\n#documentPropertiesDialog .buttonRow{\n  margin-top:10px;\n}\n\n.grab-to-pan-grab{\n  cursor:grab !important;\n}\n.grab-to-pan-grab\n  *:not(input):not(textarea):not(button):not(select):not(:link){\n  cursor:inherit !important;\n}\n.grab-to-pan-grab:active,\n.grab-to-pan-grabbing{\n  cursor:grabbing !important;\n}\n.grab-to-pan-grabbing{\n  position:fixed;\n  background:rgb(0 0 0 / 0);\n  display:block;\n  inset:0;\n  overflow:hidden;\n  z-index:50000;\n}\n\n@page{\n  margin:0;\n}\n\n#printContainer{\n  display:none;\n}\n\n@media print{\n  body{\n    background:rgb(0 0 0 / 0) none;\n  }\n  body[data-pdfjsprinting] #outerContainer{\n    display:none;\n  }\n  body[data-pdfjsprinting] #printContainer{\n    display:block;\n  }\n  #printContainer{\n    height:100%;\n  }\n  #printContainer > .printedPage{\n    page-break-after:always;\n    page-break-inside:avoid;\n    height:100%;\n    width:100%;\n\n    display:flex;\n    flex-direction:column;\n    justify-content:center;\n    align-items:center;\n  }\n\n  #printContainer > .xfaPrintedPage .xfaPage{\n    position:absolute;\n  }\n\n  #printContainer > .xfaPrintedPage{\n    page-break-after:always;\n    page-break-inside:avoid;\n    width:100%;\n    height:100%;\n    position:relative;\n  }\n\n  #printContainer > .printedPage :is(canvas, img){\n    max-width:100%;\n    max-height:100%;\n\n    direction:ltr;\n    display:block;\n  }\n}\n\n.visibleMediumView{\n  display:none;\n}\n\n@media all and (max-width: 900px){\n  #toolbarViewerMiddle{\n    display:table;\n    margin:auto;\n    left:auto;\n    position:inherit;\n    transform:none;\n  }\n}\n\n@media all and (max-width: 840px){\n  #sidebarContainer{\n    background-color:var(--sidebar-narrow-bg-color);\n  }\n  #outerContainer.sidebarOpen #viewerContainer{\n    inset-inline-start:0 !important;\n  }\n}\n\n@media all and (max-width: 750px){\n  :root{\n    --editor-toolbar-base-offset:40px;\n  }\n  #outerContainer .hiddenMediumView{\n    display:none;\n  }\n  #outerContainer .visibleMediumView{\n    display:inherit;\n  }\n}\n\n@media all and (max-width: 690px){\n  .hiddenSmallView,\n  .hiddenSmallView *{\n    display:none;\n  }\n  .toolbarButtonSpacer{\n    width:0;\n  }\n  .findbar{\n    inset-inline-start:34px;\n  }\n}\n\n@media all and (max-width: 560px){\n  #scaleSelectContainer{\n    display:none;\n  }\n}\n"
  },
  {
    "path": "src/StaffWebUI/wwwroot/pdfjs-4.2.67-dist/web/viewer.html",
    "content": "<!DOCTYPE html>\n<!--\nCopyright 2012 Mozilla Foundation\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nAdobe CMap resources are covered by their own copyright but the same license:\n\n    Copyright 1990-2015 Adobe Systems Incorporated.\n\nSee https://github.com/adobe-type-tools/cmap-resources\n-->\n<html dir=\"ltr\" mozdisallowselectionprint>\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1\">\n    <meta name=\"google\" content=\"notranslate\">\n    <title>PDF.js viewer</title>\n\n<!-- This snippet is used in production (included from viewer.html) -->\n<link rel=\"resource\" type=\"application/l10n\" href=\"locale/locale.json\">\n<script src=\"../build/pdf.mjs\" type=\"module\"></script>\n\n    <link rel=\"stylesheet\" href=\"viewer.css\">\n    <style type=\"text/css\">\n        .textLayer .highlight.selected {\n            --highlight-selected-bg-color: yellow;\n            color: black;\n        }\n    </style>\n\n  <script src=\"viewer.mjs\" type=\"module\"></script>\n  </head>\n\n  <body tabindex=\"1\">\n    <div id=\"outerContainer\">\n\n      <div id=\"sidebarContainer\">\n        <div id=\"toolbarSidebar\">\n          <div id=\"toolbarSidebarLeft\">\n            <div id=\"sidebarViewButtons\" class=\"splitToolbarButton toggled\" role=\"radiogroup\">\n              <button id=\"viewThumbnail\" class=\"toolbarButton toggled\" title=\"Show Thumbnails\" tabindex=\"2\" data-l10n-id=\"pdfjs-thumbs-button\" role=\"radio\" aria-checked=\"true\" aria-controls=\"thumbnailView\">\n                 <span data-l10n-id=\"pdfjs-thumbs-button-label\">Thumbnails</span>\n              </button>\n              <button id=\"viewOutline\" class=\"toolbarButton\" title=\"Show Document Outline (double-click to expand/collapse all items)\" tabindex=\"3\" data-l10n-id=\"pdfjs-document-outline-button\" role=\"radio\" aria-checked=\"false\" aria-controls=\"outlineView\">\n                 <span data-l10n-id=\"pdfjs-document-outline-button-label\">Document Outline</span>\n              </button>\n              <button id=\"viewAttachments\" class=\"toolbarButton\" title=\"Show Attachments\" tabindex=\"4\" data-l10n-id=\"pdfjs-attachments-button\" role=\"radio\" aria-checked=\"false\" aria-controls=\"attachmentsView\">\n                 <span data-l10n-id=\"pdfjs-attachments-button-label\">Attachments</span>\n              </button>\n              <button id=\"viewLayers\" class=\"toolbarButton\" title=\"Show Layers (double-click to reset all layers to the default state)\" tabindex=\"5\" data-l10n-id=\"pdfjs-layers-button\" role=\"radio\" aria-checked=\"false\" aria-controls=\"layersView\">\n                 <span data-l10n-id=\"pdfjs-layers-button-label\">Layers</span>\n              </button>\n            </div>\n          </div>\n\n          <div id=\"toolbarSidebarRight\">\n            <div id=\"outlineOptionsContainer\">\n              <div class=\"verticalToolbarSeparator\"></div>\n\n              <button id=\"currentOutlineItem\" class=\"toolbarButton\" disabled=\"disabled\" title=\"Find Current Outline Item\" tabindex=\"6\" data-l10n-id=\"pdfjs-current-outline-item-button\">\n                <span data-l10n-id=\"pdfjs-current-outline-item-button-label\">Current Outline Item</span>\n              </button>\n            </div>\n          </div>\n        </div>\n        <div id=\"sidebarContent\">\n          <div id=\"thumbnailView\">\n          </div>\n          <div id=\"outlineView\" class=\"hidden\">\n          </div>\n          <div id=\"attachmentsView\" class=\"hidden\">\n          </div>\n          <div id=\"layersView\" class=\"hidden\">\n          </div>\n        </div>\n        <div id=\"sidebarResizer\"></div>\n      </div>  <!-- sidebarContainer -->\n\n      <div id=\"mainContainer\">\n        <div class=\"findbar hidden doorHanger\" id=\"findbar\">\n          <div id=\"findbarInputContainer\">\n            <span class=\"loadingInput end\">\n              <input id=\"findInput\" class=\"toolbarField\" title=\"Find\" placeholder=\"Find in document…\" tabindex=\"91\" data-l10n-id=\"pdfjs-find-input\" aria-invalid=\"false\">\n            </span>\n            <div class=\"splitToolbarButton\">\n              <button id=\"findPrevious\" class=\"toolbarButton\" title=\"Find the previous occurrence of the phrase\" tabindex=\"92\" data-l10n-id=\"pdfjs-find-previous-button\">\n                <span data-l10n-id=\"pdfjs-find-previous-button-label\">Previous</span>\n              </button>\n              <div class=\"splitToolbarButtonSeparator\"></div>\n              <button id=\"findNext\" class=\"toolbarButton\" title=\"Find the next occurrence of the phrase\" tabindex=\"93\" data-l10n-id=\"pdfjs-find-next-button\">\n                <span data-l10n-id=\"pdfjs-find-next-button-label\">Next</span>\n              </button>\n            </div>\n          </div>\n\n          <div id=\"findbarOptionsOneContainer\">\n            <input type=\"checkbox\" id=\"findHighlightAll\" class=\"toolbarField\" tabindex=\"94\">\n            <label for=\"findHighlightAll\" class=\"toolbarLabel\" data-l10n-id=\"pdfjs-find-highlight-checkbox\">Highlight All</label>\n            <input type=\"checkbox\" id=\"findMatchCase\" class=\"toolbarField\" tabindex=\"95\">\n            <label for=\"findMatchCase\" class=\"toolbarLabel\" data-l10n-id=\"pdfjs-find-match-case-checkbox-label\">Match Case</label>\n          </div>\n          <div id=\"findbarOptionsTwoContainer\">\n            <input type=\"checkbox\" id=\"findMatchDiacritics\" class=\"toolbarField\" tabindex=\"96\">\n            <label for=\"findMatchDiacritics\" class=\"toolbarLabel\" data-l10n-id=\"pdfjs-find-match-diacritics-checkbox-label\">Match Diacritics</label>\n            <input type=\"checkbox\" id=\"findEntireWord\" class=\"toolbarField\" tabindex=\"97\">\n            <label for=\"findEntireWord\" class=\"toolbarLabel\" data-l10n-id=\"pdfjs-find-entire-word-checkbox-label\">Whole Words</label>\n          </div>\n\n          <div id=\"findbarMessageContainer\" aria-live=\"polite\">\n            <span id=\"findResultsCount\" class=\"toolbarLabel\"></span>\n            <span id=\"findMsg\" class=\"toolbarLabel\"></span>\n          </div>\n        </div>  <!-- findbar -->\n\n        <div class=\"editorParamsToolbar hidden doorHangerRight\" id=\"editorHighlightParamsToolbar\">\n          <div id=\"highlightParamsToolbarContainer\" class=\"editorParamsToolbarContainer\">\n            <div id=\"editorHighlightColorPicker\" class=\"colorPicker\">\n              <span id=\"highlightColorPickerLabel\" class=\"editorParamsLabel\" data-l10n-id=\"pdfjs-editor-highlight-colorpicker-label\">Highlight color</span>\n            </div>\n            <div id=\"editorHighlightThickness\">\n              <label for=\"editorFreeHighlightThickness\" class=\"editorParamsLabel\" data-l10n-id=\"pdfjs-editor-free-highlight-thickness-input\">Thickness</label>\n              <div class=\"thicknessPicker\">\n                <input type=\"range\" id=\"editorFreeHighlightThickness\" class=\"editorParamsSlider\" data-l10n-id=\"pdfjs-editor-free-highlight-thickness-title\" value=\"12\" min=\"8\" max=\"24\" step=\"1\" tabindex=\"101\">\n              </div>\n            </div>\n            <div id=\"editorHighlightVisibility\">\n              <div class=\"divider\"></div>\n              <div class=\"toggler\">\n                <label for=\"editorHighlightShowAll\" class=\"editorParamsLabel\" data-l10n-id=\"pdfjs-editor-highlight-show-all-button-label\">Show all</label>\n                <button id=\"editorHighlightShowAll\" class=\"toggle-button\" data-l10n-id=\"pdfjs-editor-highlight-show-all-button\" aria-pressed=\"true\" tabindex=\"102\"></button>\n              </div>\n            </div>\n          </div>\n        </div>\n\n        <div class=\"editorParamsToolbar hidden doorHangerRight\" id=\"editorFreeTextParamsToolbar\">\n          <div class=\"editorParamsToolbarContainer\">\n            <div class=\"editorParamsSetter\">\n              <label for=\"editorFreeTextColor\" class=\"editorParamsLabel\" data-l10n-id=\"pdfjs-editor-free-text-color-input\">Color</label>\n              <input type=\"color\" id=\"editorFreeTextColor\" class=\"editorParamsColor\" tabindex=\"103\">\n            </div>\n            <div class=\"editorParamsSetter\">\n              <label for=\"editorFreeTextFontSize\" class=\"editorParamsLabel\" data-l10n-id=\"pdfjs-editor-free-text-size-input\">Size</label>\n              <input type=\"range\" id=\"editorFreeTextFontSize\" class=\"editorParamsSlider\" value=\"10\" min=\"5\" max=\"100\" step=\"1\" tabindex=\"104\">\n            </div>\n          </div>\n        </div>\n\n        <div class=\"editorParamsToolbar hidden doorHangerRight\" id=\"editorInkParamsToolbar\">\n          <div class=\"editorParamsToolbarContainer\">\n            <div class=\"editorParamsSetter\">\n              <label for=\"editorInkColor\" class=\"editorParamsLabel\" data-l10n-id=\"pdfjs-editor-ink-color-input\">Color</label>\n              <input type=\"color\" id=\"editorInkColor\" class=\"editorParamsColor\" tabindex=\"105\">\n            </div>\n            <div class=\"editorParamsSetter\">\n              <label for=\"editorInkThickness\" class=\"editorParamsLabel\" data-l10n-id=\"pdfjs-editor-ink-thickness-input\">Thickness</label>\n              <input type=\"range\" id=\"editorInkThickness\" class=\"editorParamsSlider\" value=\"1\" min=\"1\" max=\"20\" step=\"1\" tabindex=\"106\">\n            </div>\n            <div class=\"editorParamsSetter\">\n              <label for=\"editorInkOpacity\" class=\"editorParamsLabel\" data-l10n-id=\"pdfjs-editor-ink-opacity-input\">Opacity</label>\n              <input type=\"range\" id=\"editorInkOpacity\" class=\"editorParamsSlider\" value=\"100\" min=\"1\" max=\"100\" step=\"1\" tabindex=\"107\">\n            </div>\n          </div>\n        </div>\n\n        <div class=\"editorParamsToolbar hidden doorHangerRight\" id=\"editorStampParamsToolbar\">\n          <div class=\"editorParamsToolbarContainer\">\n            <button id=\"editorStampAddImage\" class=\"secondaryToolbarButton\" title=\"Add image\" tabindex=\"108\" data-l10n-id=\"pdfjs-editor-stamp-add-image-button\">\n              <span class=\"editorParamsLabel\" data-l10n-id=\"pdfjs-editor-stamp-add-image-button-label\">Add image</span>\n            </button>\n          </div>\n        </div>\n\n        <div id=\"secondaryToolbar\" class=\"secondaryToolbar hidden doorHangerRight\">\n          <div id=\"secondaryToolbarButtonContainer\">\n            <button id=\"secondaryOpenFile\" class=\"secondaryToolbarButton\" title=\"Open File\" tabindex=\"51\" data-l10n-id=\"pdfjs-open-file-button\">\n              <span data-l10n-id=\"pdfjs-open-file-button-label\">Open</span>\n            </button>\n\n            <button id=\"secondaryPrint\" class=\"secondaryToolbarButton visibleMediumView\" title=\"Print\" tabindex=\"52\" data-l10n-id=\"pdfjs-print-button\">\n              <span data-l10n-id=\"pdfjs-print-button-label\">Print</span>\n            </button>\n\n            <button id=\"secondaryDownload\" class=\"secondaryToolbarButton visibleMediumView\" title=\"Save\" tabindex=\"53\" data-l10n-id=\"pdfjs-save-button\">\n              <span data-l10n-id=\"pdfjs-save-button-label\">Save</span>\n            </button>\n\n            <div class=\"horizontalToolbarSeparator\"></div>\n\n            <button id=\"presentationMode\" class=\"secondaryToolbarButton\" title=\"Switch to Presentation Mode\" tabindex=\"54\" data-l10n-id=\"pdfjs-presentation-mode-button\">\n              <span data-l10n-id=\"pdfjs-presentation-mode-button-label\">Presentation Mode</span>\n            </button>\n\n            <a href=\"#\" id=\"viewBookmark\" class=\"secondaryToolbarButton\" title=\"Current Page (View URL from Current Page)\" tabindex=\"55\" data-l10n-id=\"pdfjs-bookmark-button\">\n              <span data-l10n-id=\"pdfjs-bookmark-button-label\">Current Page</span>\n            </a>\n\n            <div id=\"viewBookmarkSeparator\" class=\"horizontalToolbarSeparator\"></div>\n\n            <button id=\"firstPage\" class=\"secondaryToolbarButton\" title=\"Go to First Page\" tabindex=\"56\" data-l10n-id=\"pdfjs-first-page-button\">\n              <span data-l10n-id=\"pdfjs-first-page-button-label\">Go to First Page</span>\n            </button>\n            <button id=\"lastPage\" class=\"secondaryToolbarButton\" title=\"Go to Last Page\" tabindex=\"57\" data-l10n-id=\"pdfjs-last-page-button\">\n              <span data-l10n-id=\"pdfjs-last-page-button-label\">Go to Last Page</span>\n            </button>\n\n            <div class=\"horizontalToolbarSeparator\"></div>\n\n            <button id=\"pageRotateCw\" class=\"secondaryToolbarButton\" title=\"Rotate Clockwise\" tabindex=\"58\" data-l10n-id=\"pdfjs-page-rotate-cw-button\">\n              <span data-l10n-id=\"pdfjs-page-rotate-cw-button-label\">Rotate Clockwise</span>\n            </button>\n            <button id=\"pageRotateCcw\" class=\"secondaryToolbarButton\" title=\"Rotate Counterclockwise\" tabindex=\"59\" data-l10n-id=\"pdfjs-page-rotate-ccw-button\">\n              <span data-l10n-id=\"pdfjs-page-rotate-ccw-button-label\">Rotate Counterclockwise</span>\n            </button>\n\n            <div class=\"horizontalToolbarSeparator\"></div>\n\n            <div id=\"cursorToolButtons\" role=\"radiogroup\">\n              <button id=\"cursorSelectTool\" class=\"secondaryToolbarButton toggled\" title=\"Enable Text Selection Tool\" tabindex=\"60\" data-l10n-id=\"pdfjs-cursor-text-select-tool-button\" role=\"radio\" aria-checked=\"true\">\n                <span data-l10n-id=\"pdfjs-cursor-text-select-tool-button-label\">Text Selection Tool</span>\n              </button>\n              <button id=\"cursorHandTool\" class=\"secondaryToolbarButton\" title=\"Enable Hand Tool\" tabindex=\"61\" data-l10n-id=\"pdfjs-cursor-hand-tool-button\" role=\"radio\" aria-checked=\"false\">\n                <span data-l10n-id=\"pdfjs-cursor-hand-tool-button-label\">Hand Tool</span>\n              </button>\n            </div>\n\n            <div class=\"horizontalToolbarSeparator\"></div>\n\n            <div id=\"scrollModeButtons\" role=\"radiogroup\">\n              <button id=\"scrollPage\" class=\"secondaryToolbarButton\" title=\"Use Page Scrolling\" tabindex=\"62\" data-l10n-id=\"pdfjs-scroll-page-button\" role=\"radio\" aria-checked=\"false\">\n                <span data-l10n-id=\"pdfjs-scroll-page-button-label\">Page Scrolling</span>\n              </button>\n              <button id=\"scrollVertical\" class=\"secondaryToolbarButton toggled\" title=\"Use Vertical Scrolling\" tabindex=\"63\" data-l10n-id=\"pdfjs-scroll-vertical-button\" role=\"radio\" aria-checked=\"true\">\n                <span data-l10n-id=\"pdfjs-scroll-vertical-button-label\" >Vertical Scrolling</span>\n              </button>\n              <button id=\"scrollHorizontal\" class=\"secondaryToolbarButton\" title=\"Use Horizontal Scrolling\" tabindex=\"64\" data-l10n-id=\"pdfjs-scroll-horizontal-button\" role=\"radio\" aria-checked=\"false\">\n                <span data-l10n-id=\"pdfjs-scroll-horizontal-button-label\">Horizontal Scrolling</span>\n              </button>\n              <button id=\"scrollWrapped\" class=\"secondaryToolbarButton\" title=\"Use Wrapped Scrolling\" tabindex=\"65\" data-l10n-id=\"pdfjs-scroll-wrapped-button\" role=\"radio\" aria-checked=\"false\">\n                <span data-l10n-id=\"pdfjs-scroll-wrapped-button-label\">Wrapped Scrolling</span>\n              </button>\n            </div>\n\n            <div class=\"horizontalToolbarSeparator\"></div>\n\n            <div id=\"spreadModeButtons\" role=\"radiogroup\">\n              <button id=\"spreadNone\" class=\"secondaryToolbarButton toggled\" title=\"Do not join page spreads\" tabindex=\"66\" data-l10n-id=\"pdfjs-spread-none-button\" role=\"radio\" aria-checked=\"true\">\n                <span data-l10n-id=\"pdfjs-spread-none-button-label\">No Spreads</span>\n              </button>\n              <button id=\"spreadOdd\" class=\"secondaryToolbarButton\" title=\"Join page spreads starting with odd-numbered pages\" tabindex=\"67\" data-l10n-id=\"pdfjs-spread-odd-button\" role=\"radio\" aria-checked=\"false\">\n                <span data-l10n-id=\"pdfjs-spread-odd-button-label\">Odd Spreads</span>\n              </button>\n              <button id=\"spreadEven\" class=\"secondaryToolbarButton\" title=\"Join page spreads starting with even-numbered pages\" tabindex=\"68\" data-l10n-id=\"pdfjs-spread-even-button\" role=\"radio\" aria-checked=\"false\">\n                <span data-l10n-id=\"pdfjs-spread-even-button-label\">Even Spreads</span>\n              </button>\n            </div>\n\n            <div class=\"horizontalToolbarSeparator\"></div>\n\n            <button id=\"documentProperties\" class=\"secondaryToolbarButton\" title=\"Document Properties…\" tabindex=\"69\" data-l10n-id=\"pdfjs-document-properties-button\" aria-controls=\"documentPropertiesDialog\">\n              <span data-l10n-id=\"pdfjs-document-properties-button-label\">Document Properties…</span>\n            </button>\n          </div>\n        </div>  <!-- secondaryToolbar -->\n\n        <div class=\"toolbar\">\n          <div id=\"toolbarContainer\">\n            <div id=\"toolbarViewer\">\n              <div id=\"toolbarViewerLeft\">\n                <button id=\"sidebarToggle\" class=\"toolbarButton\" title=\"Toggle Sidebar\" tabindex=\"11\" data-l10n-id=\"pdfjs-toggle-sidebar-button\" aria-expanded=\"false\" aria-controls=\"sidebarContainer\">\n                  <span data-l10n-id=\"pdfjs-toggle-sidebar-button-label\">Toggle Sidebar</span>\n                </button>\n                <div class=\"toolbarButtonSpacer\"></div>\n                <button id=\"viewFind\" class=\"toolbarButton\" title=\"Find in Document\" tabindex=\"12\" data-l10n-id=\"pdfjs-findbar-button\" aria-expanded=\"false\" aria-controls=\"findbar\">\n                  <span data-l10n-id=\"pdfjs-findbar-button-label\">Find</span>\n                </button>\n                <div class=\"splitToolbarButton hiddenSmallView\">\n                  <button class=\"toolbarButton\" title=\"Previous Page\" id=\"previous\" tabindex=\"13\" data-l10n-id=\"pdfjs-previous-button\">\n                    <span data-l10n-id=\"pdfjs-previous-button-label\">Previous</span>\n                  </button>\n                  <div class=\"splitToolbarButtonSeparator\"></div>\n                  <button class=\"toolbarButton\" title=\"Next Page\" id=\"next\" tabindex=\"14\" data-l10n-id=\"pdfjs-next-button\">\n                    <span data-l10n-id=\"pdfjs-next-button-label\">Next</span>\n                  </button>\n                </div>\n                <span class=\"loadingInput start\">\n                  <input type=\"number\" id=\"pageNumber\" class=\"toolbarField\" title=\"Page\" value=\"1\" min=\"1\" tabindex=\"15\" data-l10n-id=\"pdfjs-page-input\" autocomplete=\"off\">\n                </span>\n                <span id=\"numPages\" class=\"toolbarLabel\"></span>\n              </div>\n              <div id=\"toolbarViewerRight\">\n                <div id=\"editorModeButtons\" class=\"splitToolbarButton toggled\" role=\"radiogroup\">\n                  <button id=\"editorHighlight\" class=\"toolbarButton\" hidden=\"true\" disabled=\"disabled\" title=\"Highlight\" role=\"radio\" aria-checked=\"false\" aria-controls=\"editorHighlightParamsToolbar\" tabindex=\"31\" data-l10n-id=\"pdfjs-editor-highlight-button\">\n                    <span data-l10n-id=\"pdfjs-editor-highlight-button-label\">Highlight</span>\n                  </button>\n                  <button id=\"editorFreeText\" class=\"toolbarButton\" disabled=\"disabled\" title=\"Text\" role=\"radio\" aria-checked=\"false\" aria-controls=\"editorFreeTextParamsToolbar\" tabindex=\"32\" data-l10n-id=\"pdfjs-editor-free-text-button\">\n                    <span data-l10n-id=\"pdfjs-editor-free-text-button-label\">Text</span>\n                  </button>\n                  <button id=\"editorInk\" class=\"toolbarButton\" disabled=\"disabled\" title=\"Draw\" role=\"radio\" aria-checked=\"false\" aria-controls=\"editorInkParamsToolbar\" tabindex=\"33\" data-l10n-id=\"pdfjs-editor-ink-button\">\n                    <span data-l10n-id=\"pdfjs-editor-ink-button-label\">Draw</span>\n                  </button>\n                  <button id=\"editorStamp\" class=\"toolbarButton hidden\" disabled=\"disabled\" title=\"Add or edit images\" role=\"radio\" aria-checked=\"false\" aria-controls=\"editorStampParamsToolbar\" tabindex=\"34\" data-l10n-id=\"pdfjs-editor-stamp-button\">\n                    <span data-l10n-id=\"pdfjs-editor-stamp-button-label\">Add or edit images</span>\n                  </button>\n                </div>\n\n                <div id=\"editorModeSeparator\" class=\"verticalToolbarSeparator\"></div>\n\n                <button id=\"print\" class=\"toolbarButton hiddenMediumView\" title=\"Print\" tabindex=\"41\" data-l10n-id=\"pdfjs-print-button\">\n                  <span data-l10n-id=\"pdfjs-print-button-label\">Print</span>\n                </button>\n\n                <button id=\"download\" class=\"toolbarButton hiddenMediumView\" title=\"Save\" tabindex=\"42\" data-l10n-id=\"pdfjs-save-button\">\n                  <span data-l10n-id=\"pdfjs-save-button-label\">Save</span>\n                </button>\n\n                <div class=\"verticalToolbarSeparator hiddenMediumView\"></div>\n\n                <button id=\"secondaryToolbarToggle\" class=\"toolbarButton\" title=\"Tools\" tabindex=\"43\" data-l10n-id=\"pdfjs-tools-button\" aria-expanded=\"false\" aria-controls=\"secondaryToolbar\">\n                  <span data-l10n-id=\"pdfjs-tools-button-label\">Tools</span>\n                </button>\n              </div>\n              <div id=\"toolbarViewerMiddle\">\n                <div class=\"splitToolbarButton\">\n                  <button id=\"zoomOut\" class=\"toolbarButton\" title=\"Zoom Out\" tabindex=\"21\" data-l10n-id=\"pdfjs-zoom-out-button\">\n                    <span data-l10n-id=\"pdfjs-zoom-out-button-label\">Zoom Out</span>\n                  </button>\n                  <div class=\"splitToolbarButtonSeparator\"></div>\n                  <button id=\"zoomIn\" class=\"toolbarButton\" title=\"Zoom In\" tabindex=\"22\" data-l10n-id=\"pdfjs-zoom-in-button\">\n                    <span data-l10n-id=\"pdfjs-zoom-in-button-label\">Zoom In</span>\n                   </button>\n                </div>\n                <span id=\"scaleSelectContainer\" class=\"dropdownToolbarButton\">\n                  <select id=\"scaleSelect\" title=\"Zoom\" tabindex=\"23\" data-l10n-id=\"pdfjs-zoom-select\">\n                    <option id=\"pageAutoOption\" title=\"\" value=\"auto\" selected=\"selected\" data-l10n-id=\"pdfjs-page-scale-auto\">Automatic Zoom</option>\n                    <option id=\"pageActualOption\" title=\"\" value=\"page-actual\" data-l10n-id=\"pdfjs-page-scale-actual\">Actual Size</option>\n                    <option id=\"pageFitOption\" title=\"\" value=\"page-fit\" data-l10n-id=\"pdfjs-page-scale-fit\">Page Fit</option>\n                    <option id=\"pageWidthOption\" title=\"\" value=\"page-width\" data-l10n-id=\"pdfjs-page-scale-width\">Page Width</option>\n                    <option id=\"customScaleOption\" title=\"\" value=\"custom\" disabled=\"disabled\" hidden=\"true\" data-l10n-id=\"pdfjs-page-scale-percent\" data-l10n-args='{ \"scale\": 0 }'>0%</option>\n                    <option title=\"\" value=\"0.5\" data-l10n-id=\"pdfjs-page-scale-percent\" data-l10n-args='{ \"scale\": 50 }'>50%</option>\n                    <option title=\"\" value=\"0.75\" data-l10n-id=\"pdfjs-page-scale-percent\" data-l10n-args='{ \"scale\": 75 }'>75%</option>\n                    <option title=\"\" value=\"1\" data-l10n-id=\"pdfjs-page-scale-percent\" data-l10n-args='{ \"scale\": 100 }'>100%</option>\n                    <option title=\"\" value=\"1.25\" data-l10n-id=\"pdfjs-page-scale-percent\" data-l10n-args='{ \"scale\": 125 }'>125%</option>\n                    <option title=\"\" value=\"1.5\" data-l10n-id=\"pdfjs-page-scale-percent\" data-l10n-args='{ \"scale\": 150 }'>150%</option>\n                    <option title=\"\" value=\"2\" data-l10n-id=\"pdfjs-page-scale-percent\" data-l10n-args='{ \"scale\": 200 }'>200%</option>\n                    <option title=\"\" value=\"3\" data-l10n-id=\"pdfjs-page-scale-percent\" data-l10n-args='{ \"scale\": 300 }'>300%</option>\n                    <option title=\"\" value=\"4\" data-l10n-id=\"pdfjs-page-scale-percent\" data-l10n-args='{ \"scale\": 400 }'>400%</option>\n                  </select>\n                </span>\n              </div>\n            </div>\n            <div id=\"loadingBar\">\n              <div class=\"progress\">\n                <div class=\"glimmer\">\n                </div>\n              </div>\n            </div>\n          </div>\n        </div>\n\n        <div id=\"viewerContainer\" tabindex=\"0\">\n          <div id=\"viewer\" class=\"pdfViewer\"></div>\n        </div>\n      </div> <!-- mainContainer -->\n\n      <div id=\"dialogContainer\">\n        <dialog id=\"passwordDialog\">\n          <div class=\"row\">\n            <label for=\"password\" id=\"passwordText\" data-l10n-id=\"pdfjs-password-label\">Enter the password to open this PDF file:</label>\n          </div>\n          <div class=\"row\">\n            <input type=\"password\" id=\"password\" class=\"toolbarField\">\n          </div>\n          <div class=\"buttonRow\">\n            <button id=\"passwordCancel\" class=\"dialogButton\"><span data-l10n-id=\"pdfjs-password-cancel-button\">Cancel</span></button>\n            <button id=\"passwordSubmit\" class=\"dialogButton\"><span data-l10n-id=\"pdfjs-password-ok-button\">OK</span></button>\n          </div>\n        </dialog>\n        <dialog id=\"documentPropertiesDialog\">\n          <div class=\"row\">\n            <span id=\"fileNameLabel\" data-l10n-id=\"pdfjs-document-properties-file-name\">File name:</span>\n            <p id=\"fileNameField\" aria-labelledby=\"fileNameLabel\">-</p>\n          </div>\n          <div class=\"row\">\n            <span id=\"fileSizeLabel\" data-l10n-id=\"pdfjs-document-properties-file-size\">File size:</span>\n            <p id=\"fileSizeField\" aria-labelledby=\"fileSizeLabel\">-</p>\n          </div>\n          <div class=\"separator\"></div>\n          <div class=\"row\">\n            <span id=\"titleLabel\" data-l10n-id=\"pdfjs-document-properties-title\">Title:</span>\n            <p id=\"titleField\" aria-labelledby=\"titleLabel\">-</p>\n          </div>\n          <div class=\"row\">\n            <span id=\"authorLabel\" data-l10n-id=\"pdfjs-document-properties-author\">Author:</span>\n            <p id=\"authorField\" aria-labelledby=\"authorLabel\">-</p>\n          </div>\n          <div class=\"row\">\n            <span id=\"subjectLabel\" data-l10n-id=\"pdfjs-document-properties-subject\">Subject:</span>\n            <p id=\"subjectField\" aria-labelledby=\"subjectLabel\">-</p>\n          </div>\n          <div class=\"row\">\n            <span id=\"keywordsLabel\" data-l10n-id=\"pdfjs-document-properties-keywords\">Keywords:</span>\n            <p id=\"keywordsField\" aria-labelledby=\"keywordsLabel\">-</p>\n          </div>\n          <div class=\"row\">\n            <span id=\"creationDateLabel\" data-l10n-id=\"pdfjs-document-properties-creation-date\">Creation Date:</span>\n            <p id=\"creationDateField\" aria-labelledby=\"creationDateLabel\">-</p>\n          </div>\n          <div class=\"row\">\n            <span id=\"modificationDateLabel\" data-l10n-id=\"pdfjs-document-properties-modification-date\">Modification Date:</span>\n            <p id=\"modificationDateField\" aria-labelledby=\"modificationDateLabel\">-</p>\n          </div>\n          <div class=\"row\">\n            <span id=\"creatorLabel\" data-l10n-id=\"pdfjs-document-properties-creator\">Creator:</span>\n            <p id=\"creatorField\" aria-labelledby=\"creatorLabel\">-</p>\n          </div>\n          <div class=\"separator\"></div>\n          <div class=\"row\">\n            <span id=\"producerLabel\" data-l10n-id=\"pdfjs-document-properties-producer\">PDF Producer:</span>\n            <p id=\"producerField\" aria-labelledby=\"producerLabel\">-</p>\n          </div>\n          <div class=\"row\">\n            <span id=\"versionLabel\" data-l10n-id=\"pdfjs-document-properties-version\">PDF Version:</span>\n            <p id=\"versionField\" aria-labelledby=\"versionLabel\">-</p>\n          </div>\n          <div class=\"row\">\n            <span id=\"pageCountLabel\" data-l10n-id=\"pdfjs-document-properties-page-count\">Page Count:</span>\n            <p id=\"pageCountField\" aria-labelledby=\"pageCountLabel\">-</p>\n          </div>\n          <div class=\"row\">\n            <span id=\"pageSizeLabel\" data-l10n-id=\"pdfjs-document-properties-page-size\">Page Size:</span>\n            <p id=\"pageSizeField\" aria-labelledby=\"pageSizeLabel\">-</p>\n          </div>\n          <div class=\"separator\"></div>\n          <div class=\"row\">\n            <span id=\"linearizedLabel\" data-l10n-id=\"pdfjs-document-properties-linearized\">Fast Web View:</span>\n            <p id=\"linearizedField\" aria-labelledby=\"linearizedLabel\">-</p>\n          </div>\n          <div class=\"buttonRow\">\n            <button id=\"documentPropertiesClose\" class=\"dialogButton\"><span data-l10n-id=\"pdfjs-document-properties-close-button\">Close</span></button>\n          </div>\n        </dialog>\n        <dialog id=\"altTextDialog\" aria-labelledby=\"dialogLabel\" aria-describedby=\"dialogDescription\">\n          <div id=\"altTextContainer\">\n            <div id=\"overallDescription\">\n              <span id=\"dialogLabel\" data-l10n-id=\"pdfjs-editor-alt-text-dialog-label\" class=\"title\">Choose an option</span>\n              <span id=\"dialogDescription\" data-l10n-id=\"pdfjs-editor-alt-text-dialog-description\">\n                Alt text (alternative text) helps when people can’t see the image or when it doesn’t load.\n              </span>\n            </div>\n            <div id=\"addDescription\">\n              <div class=\"radio\">\n                <div class=\"radioButton\">\n                  <input type=\"radio\" id=\"descriptionButton\" name=\"altTextOption\" tabindex=\"0\" aria-describedby=\"descriptionAreaLabel\" checked>\n                  <label for=\"descriptionButton\" data-l10n-id=\"pdfjs-editor-alt-text-add-description-label\">Add a description</label>\n                </div>\n                <div class=\"radioLabel\">\n                  <span id=\"descriptionAreaLabel\" data-l10n-id=\"pdfjs-editor-alt-text-add-description-description\">\n                    Aim for 1-2 sentences that describe the subject, setting, or actions.\n                  </span>\n                </div>\n              </div>\n              <div class=\"descriptionArea\">\n                <textarea id=\"descriptionTextarea\" placeholder=\"For example, “A young man sits down at a table to eat a meal”\" aria-labelledby=\"descriptionAreaLabel\" data-l10n-id=\"pdfjs-editor-alt-text-textarea\" tabindex=\"0\"></textarea>\n              </div>\n            </div>\n            <div id=\"markAsDecorative\">\n              <div class=\"radio\">\n                <div class=\"radioButton\">\n                  <input type=\"radio\" id=\"decorativeButton\" name=\"altTextOption\" aria-describedby=\"decorativeLabel\">\n                  <label for=\"decorativeButton\" data-l10n-id=\"pdfjs-editor-alt-text-mark-decorative-label\">Mark as decorative</label>\n                </div>\n                <div class=\"radioLabel\">\n                  <span id=\"decorativeLabel\" data-l10n-id=\"pdfjs-editor-alt-text-mark-decorative-description\">\n                    This is used for ornamental images, like borders or watermarks.\n                  </span>\n                </div>\n              </div>\n            </div>\n            <div id=\"buttons\">\n              <button id=\"altTextCancel\" tabindex=\"0\"><span data-l10n-id=\"pdfjs-editor-alt-text-cancel-button\">Cancel</span></button>\n              <button id=\"altTextSave\" tabindex=\"0\"><span data-l10n-id=\"pdfjs-editor-alt-text-save-button\">Save</span></button>\n            </div>\n          </div>\n        </dialog>\n        <dialog id=\"printServiceDialog\" style=\"min-width: 200px;\">\n          <div class=\"row\">\n            <span data-l10n-id=\"pdfjs-print-progress-message\">Preparing document for printing…</span>\n          </div>\n          <div class=\"row\">\n            <progress value=\"0\" max=\"100\"></progress>\n            <span data-l10n-id=\"pdfjs-print-progress-percent\" data-l10n-args='{ \"progress\": 0 }' class=\"relative-progress\">0%</span>\n          </div>\n          <div class=\"buttonRow\">\n            <button id=\"printCancel\" class=\"dialogButton\"><span data-l10n-id=\"pdfjs-print-progress-close-button\">Cancel</span></button>\n          </div>\n        </dialog>\n      </div>  <!-- dialogContainer -->\n\n    </div> <!-- outerContainer -->\n    <div id=\"printContainer\"></div>\n  </body>\n</html>\n"
  },
  {
    "path": "src/StaffWebUI/wwwroot/pdfjs-4.2.67-dist/web/viewer.mjs",
    "content": "/**\n * @licstart The following is the entire license notice for the\n * JavaScript code in this page\n *\n * Copyright 2023 Mozilla Foundation\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 * @licend The above is the entire license notice for the\n * JavaScript code in this page\n */\n\n/******/ var __webpack_modules__ = ({\n\n/***/ 588:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, {\n  FluentBundle: () => (/* reexport */ FluentBundle),\n  FluentResource: () => (/* reexport */ FluentResource)\n});\n\n// UNUSED EXPORTS: FluentDateTime, FluentNone, FluentNumber, FluentType\n\n;// CONCATENATED MODULE: ./node_modules/@fluent/bundle/esm/types.js\nclass FluentType {\n  constructor(value) {\n    this.value = value;\n  }\n  valueOf() {\n    return this.value;\n  }\n}\nclass FluentNone extends FluentType {\n  constructor(value = \"???\") {\n    super(value);\n  }\n  toString(scope) {\n    return `{${this.value}}`;\n  }\n}\nclass FluentNumber extends FluentType {\n  constructor(value, opts = {}) {\n    super(value);\n    this.opts = opts;\n  }\n  toString(scope) {\n    try {\n      const nf = scope.memoizeIntlObject(Intl.NumberFormat, this.opts);\n      return nf.format(this.value);\n    } catch (err) {\n      scope.reportError(err);\n      return this.value.toString(10);\n    }\n  }\n}\nclass FluentDateTime extends FluentType {\n  constructor(value, opts = {}) {\n    super(value);\n    this.opts = opts;\n  }\n  toString(scope) {\n    try {\n      const dtf = scope.memoizeIntlObject(Intl.DateTimeFormat, this.opts);\n      return dtf.format(this.value);\n    } catch (err) {\n      scope.reportError(err);\n      return new Date(this.value).toISOString();\n    }\n  }\n}\n;// CONCATENATED MODULE: ./node_modules/@fluent/bundle/esm/resolver.js\n\nconst MAX_PLACEABLES = 100;\nconst FSI = \"\\u2068\";\nconst PDI = \"\\u2069\";\nfunction match(scope, selector, key) {\n  if (key === selector) {\n    return true;\n  }\n  if (key instanceof FluentNumber && selector instanceof FluentNumber && key.value === selector.value) {\n    return true;\n  }\n  if (selector instanceof FluentNumber && typeof key === \"string\") {\n    let category = scope.memoizeIntlObject(Intl.PluralRules, selector.opts).select(selector.value);\n    if (key === category) {\n      return true;\n    }\n  }\n  return false;\n}\nfunction getDefault(scope, variants, star) {\n  if (variants[star]) {\n    return resolvePattern(scope, variants[star].value);\n  }\n  scope.reportError(new RangeError(\"No default\"));\n  return new FluentNone();\n}\nfunction getArguments(scope, args) {\n  const positional = [];\n  const named = Object.create(null);\n  for (const arg of args) {\n    if (arg.type === \"narg\") {\n      named[arg.name] = resolveExpression(scope, arg.value);\n    } else {\n      positional.push(resolveExpression(scope, arg));\n    }\n  }\n  return {\n    positional,\n    named\n  };\n}\nfunction resolveExpression(scope, expr) {\n  switch (expr.type) {\n    case \"str\":\n      return expr.value;\n    case \"num\":\n      return new FluentNumber(expr.value, {\n        minimumFractionDigits: expr.precision\n      });\n    case \"var\":\n      return resolveVariableReference(scope, expr);\n    case \"mesg\":\n      return resolveMessageReference(scope, expr);\n    case \"term\":\n      return resolveTermReference(scope, expr);\n    case \"func\":\n      return resolveFunctionReference(scope, expr);\n    case \"select\":\n      return resolveSelectExpression(scope, expr);\n    default:\n      return new FluentNone();\n  }\n}\nfunction resolveVariableReference(scope, {\n  name\n}) {\n  let arg;\n  if (scope.params) {\n    if (Object.prototype.hasOwnProperty.call(scope.params, name)) {\n      arg = scope.params[name];\n    } else {\n      return new FluentNone(`$${name}`);\n    }\n  } else if (scope.args && Object.prototype.hasOwnProperty.call(scope.args, name)) {\n    arg = scope.args[name];\n  } else {\n    scope.reportError(new ReferenceError(`Unknown variable: $${name}`));\n    return new FluentNone(`$${name}`);\n  }\n  if (arg instanceof FluentType) {\n    return arg;\n  }\n  switch (typeof arg) {\n    case \"string\":\n      return arg;\n    case \"number\":\n      return new FluentNumber(arg);\n    case \"object\":\n      if (arg instanceof Date) {\n        return new FluentDateTime(arg.getTime());\n      }\n    default:\n      scope.reportError(new TypeError(`Variable type not supported: $${name}, ${typeof arg}`));\n      return new FluentNone(`$${name}`);\n  }\n}\nfunction resolveMessageReference(scope, {\n  name,\n  attr\n}) {\n  const message = scope.bundle._messages.get(name);\n  if (!message) {\n    scope.reportError(new ReferenceError(`Unknown message: ${name}`));\n    return new FluentNone(name);\n  }\n  if (attr) {\n    const attribute = message.attributes[attr];\n    if (attribute) {\n      return resolvePattern(scope, attribute);\n    }\n    scope.reportError(new ReferenceError(`Unknown attribute: ${attr}`));\n    return new FluentNone(`${name}.${attr}`);\n  }\n  if (message.value) {\n    return resolvePattern(scope, message.value);\n  }\n  scope.reportError(new ReferenceError(`No value: ${name}`));\n  return new FluentNone(name);\n}\nfunction resolveTermReference(scope, {\n  name,\n  attr,\n  args\n}) {\n  const id = `-${name}`;\n  const term = scope.bundle._terms.get(id);\n  if (!term) {\n    scope.reportError(new ReferenceError(`Unknown term: ${id}`));\n    return new FluentNone(id);\n  }\n  if (attr) {\n    const attribute = term.attributes[attr];\n    if (attribute) {\n      scope.params = getArguments(scope, args).named;\n      const resolved = resolvePattern(scope, attribute);\n      scope.params = null;\n      return resolved;\n    }\n    scope.reportError(new ReferenceError(`Unknown attribute: ${attr}`));\n    return new FluentNone(`${id}.${attr}`);\n  }\n  scope.params = getArguments(scope, args).named;\n  const resolved = resolvePattern(scope, term.value);\n  scope.params = null;\n  return resolved;\n}\nfunction resolveFunctionReference(scope, {\n  name,\n  args\n}) {\n  let func = scope.bundle._functions[name];\n  if (!func) {\n    scope.reportError(new ReferenceError(`Unknown function: ${name}()`));\n    return new FluentNone(`${name}()`);\n  }\n  if (typeof func !== \"function\") {\n    scope.reportError(new TypeError(`Function ${name}() is not callable`));\n    return new FluentNone(`${name}()`);\n  }\n  try {\n    let resolved = getArguments(scope, args);\n    return func(resolved.positional, resolved.named);\n  } catch (err) {\n    scope.reportError(err);\n    return new FluentNone(`${name}()`);\n  }\n}\nfunction resolveSelectExpression(scope, {\n  selector,\n  variants,\n  star\n}) {\n  let sel = resolveExpression(scope, selector);\n  if (sel instanceof FluentNone) {\n    return getDefault(scope, variants, star);\n  }\n  for (const variant of variants) {\n    const key = resolveExpression(scope, variant.key);\n    if (match(scope, sel, key)) {\n      return resolvePattern(scope, variant.value);\n    }\n  }\n  return getDefault(scope, variants, star);\n}\nfunction resolveComplexPattern(scope, ptn) {\n  if (scope.dirty.has(ptn)) {\n    scope.reportError(new RangeError(\"Cyclic reference\"));\n    return new FluentNone();\n  }\n  scope.dirty.add(ptn);\n  const result = [];\n  const useIsolating = scope.bundle._useIsolating && ptn.length > 1;\n  for (const elem of ptn) {\n    if (typeof elem === \"string\") {\n      result.push(scope.bundle._transform(elem));\n      continue;\n    }\n    scope.placeables++;\n    if (scope.placeables > MAX_PLACEABLES) {\n      scope.dirty.delete(ptn);\n      throw new RangeError(`Too many placeables expanded: ${scope.placeables}, ` + `max allowed is ${MAX_PLACEABLES}`);\n    }\n    if (useIsolating) {\n      result.push(FSI);\n    }\n    result.push(resolveExpression(scope, elem).toString(scope));\n    if (useIsolating) {\n      result.push(PDI);\n    }\n  }\n  scope.dirty.delete(ptn);\n  return result.join(\"\");\n}\nfunction resolvePattern(scope, value) {\n  if (typeof value === \"string\") {\n    return scope.bundle._transform(value);\n  }\n  return resolveComplexPattern(scope, value);\n}\n;// CONCATENATED MODULE: ./node_modules/@fluent/bundle/esm/scope.js\nclass Scope {\n  constructor(bundle, errors, args) {\n    this.dirty = new WeakSet();\n    this.params = null;\n    this.placeables = 0;\n    this.bundle = bundle;\n    this.errors = errors;\n    this.args = args;\n  }\n  reportError(error) {\n    if (!this.errors || !(error instanceof Error)) {\n      throw error;\n    }\n    this.errors.push(error);\n  }\n  memoizeIntlObject(ctor, opts) {\n    let cache = this.bundle._intls.get(ctor);\n    if (!cache) {\n      cache = {};\n      this.bundle._intls.set(ctor, cache);\n    }\n    let id = JSON.stringify(opts);\n    if (!cache[id]) {\n      cache[id] = new ctor(this.bundle.locales, opts);\n    }\n    return cache[id];\n  }\n}\n;// CONCATENATED MODULE: ./node_modules/@fluent/bundle/esm/builtins.js\n\nfunction values(opts, allowed) {\n  const unwrapped = Object.create(null);\n  for (const [name, opt] of Object.entries(opts)) {\n    if (allowed.includes(name)) {\n      unwrapped[name] = opt.valueOf();\n    }\n  }\n  return unwrapped;\n}\nconst NUMBER_ALLOWED = [\"unitDisplay\", \"currencyDisplay\", \"useGrouping\", \"minimumIntegerDigits\", \"minimumFractionDigits\", \"maximumFractionDigits\", \"minimumSignificantDigits\", \"maximumSignificantDigits\"];\nfunction NUMBER(args, opts) {\n  let arg = args[0];\n  if (arg instanceof FluentNone) {\n    return new FluentNone(`NUMBER(${arg.valueOf()})`);\n  }\n  if (arg instanceof FluentNumber) {\n    return new FluentNumber(arg.valueOf(), {\n      ...arg.opts,\n      ...values(opts, NUMBER_ALLOWED)\n    });\n  }\n  if (arg instanceof FluentDateTime) {\n    return new FluentNumber(arg.valueOf(), {\n      ...values(opts, NUMBER_ALLOWED)\n    });\n  }\n  throw new TypeError(\"Invalid argument to NUMBER\");\n}\nconst DATETIME_ALLOWED = [\"dateStyle\", \"timeStyle\", \"fractionalSecondDigits\", \"dayPeriod\", \"hour12\", \"weekday\", \"era\", \"year\", \"month\", \"day\", \"hour\", \"minute\", \"second\", \"timeZoneName\"];\nfunction DATETIME(args, opts) {\n  let arg = args[0];\n  if (arg instanceof FluentNone) {\n    return new FluentNone(`DATETIME(${arg.valueOf()})`);\n  }\n  if (arg instanceof FluentDateTime) {\n    return new FluentDateTime(arg.valueOf(), {\n      ...arg.opts,\n      ...values(opts, DATETIME_ALLOWED)\n    });\n  }\n  if (arg instanceof FluentNumber) {\n    return new FluentDateTime(arg.valueOf(), {\n      ...values(opts, DATETIME_ALLOWED)\n    });\n  }\n  throw new TypeError(\"Invalid argument to DATETIME\");\n}\n;// CONCATENATED MODULE: ./node_modules/@fluent/bundle/esm/memoizer.js\nconst cache = new Map();\nfunction getMemoizerForLocale(locales) {\n  const stringLocale = Array.isArray(locales) ? locales.join(\" \") : locales;\n  let memoizer = cache.get(stringLocale);\n  if (memoizer === undefined) {\n    memoizer = new Map();\n    cache.set(stringLocale, memoizer);\n  }\n  return memoizer;\n}\n;// CONCATENATED MODULE: ./node_modules/@fluent/bundle/esm/bundle.js\n\n\n\n\n\nclass FluentBundle {\n  constructor(locales, {\n    functions,\n    useIsolating = true,\n    transform = v => v\n  } = {}) {\n    this._terms = new Map();\n    this._messages = new Map();\n    this.locales = Array.isArray(locales) ? locales : [locales];\n    this._functions = {\n      NUMBER: NUMBER,\n      DATETIME: DATETIME,\n      ...functions\n    };\n    this._useIsolating = useIsolating;\n    this._transform = transform;\n    this._intls = getMemoizerForLocale(locales);\n  }\n  hasMessage(id) {\n    return this._messages.has(id);\n  }\n  getMessage(id) {\n    return this._messages.get(id);\n  }\n  addResource(res, {\n    allowOverrides = false\n  } = {}) {\n    const errors = [];\n    for (let i = 0; i < res.body.length; i++) {\n      let entry = res.body[i];\n      if (entry.id.startsWith(\"-\")) {\n        if (allowOverrides === false && this._terms.has(entry.id)) {\n          errors.push(new Error(`Attempt to override an existing term: \"${entry.id}\"`));\n          continue;\n        }\n        this._terms.set(entry.id, entry);\n      } else {\n        if (allowOverrides === false && this._messages.has(entry.id)) {\n          errors.push(new Error(`Attempt to override an existing message: \"${entry.id}\"`));\n          continue;\n        }\n        this._messages.set(entry.id, entry);\n      }\n    }\n    return errors;\n  }\n  formatPattern(pattern, args = null, errors = null) {\n    if (typeof pattern === \"string\") {\n      return this._transform(pattern);\n    }\n    let scope = new Scope(this, errors, args);\n    try {\n      let value = resolveComplexPattern(scope, pattern);\n      return value.toString(scope);\n    } catch (err) {\n      if (scope.errors && err instanceof Error) {\n        scope.errors.push(err);\n        return new FluentNone().toString(scope);\n      }\n      throw err;\n    }\n  }\n}\n;// CONCATENATED MODULE: ./node_modules/@fluent/bundle/esm/resource.js\nconst RE_MESSAGE_START = /^(-?[a-zA-Z][\\w-]*) *= */gm;\nconst RE_ATTRIBUTE_START = /\\.([a-zA-Z][\\w-]*) *= */y;\nconst RE_VARIANT_START = /\\*?\\[/y;\nconst RE_NUMBER_LITERAL = /(-?[0-9]+(?:\\.([0-9]+))?)/y;\nconst RE_IDENTIFIER = /([a-zA-Z][\\w-]*)/y;\nconst RE_REFERENCE = /([$-])?([a-zA-Z][\\w-]*)(?:\\.([a-zA-Z][\\w-]*))?/y;\nconst RE_FUNCTION_NAME = /^[A-Z][A-Z0-9_-]*$/;\nconst RE_TEXT_RUN = /([^{}\\n\\r]+)/y;\nconst RE_STRING_RUN = /([^\\\\\"\\n\\r]*)/y;\nconst RE_STRING_ESCAPE = /\\\\([\\\\\"])/y;\nconst RE_UNICODE_ESCAPE = /\\\\u([a-fA-F0-9]{4})|\\\\U([a-fA-F0-9]{6})/y;\nconst RE_LEADING_NEWLINES = /^\\n+/;\nconst RE_TRAILING_SPACES = / +$/;\nconst RE_BLANK_LINES = / *\\r?\\n/g;\nconst RE_INDENT = /( *)$/;\nconst TOKEN_BRACE_OPEN = /{\\s*/y;\nconst TOKEN_BRACE_CLOSE = /\\s*}/y;\nconst TOKEN_BRACKET_OPEN = /\\[\\s*/y;\nconst TOKEN_BRACKET_CLOSE = /\\s*] */y;\nconst TOKEN_PAREN_OPEN = /\\s*\\(\\s*/y;\nconst TOKEN_ARROW = /\\s*->\\s*/y;\nconst TOKEN_COLON = /\\s*:\\s*/y;\nconst TOKEN_COMMA = /\\s*,?\\s*/y;\nconst TOKEN_BLANK = /\\s+/y;\nclass FluentResource {\n  constructor(source) {\n    this.body = [];\n    RE_MESSAGE_START.lastIndex = 0;\n    let cursor = 0;\n    while (true) {\n      let next = RE_MESSAGE_START.exec(source);\n      if (next === null) {\n        break;\n      }\n      cursor = RE_MESSAGE_START.lastIndex;\n      try {\n        this.body.push(parseMessage(next[1]));\n      } catch (err) {\n        if (err instanceof SyntaxError) {\n          continue;\n        }\n        throw err;\n      }\n    }\n    function test(re) {\n      re.lastIndex = cursor;\n      return re.test(source);\n    }\n    function consumeChar(char, errorClass) {\n      if (source[cursor] === char) {\n        cursor++;\n        return true;\n      }\n      if (errorClass) {\n        throw new errorClass(`Expected ${char}`);\n      }\n      return false;\n    }\n    function consumeToken(re, errorClass) {\n      if (test(re)) {\n        cursor = re.lastIndex;\n        return true;\n      }\n      if (errorClass) {\n        throw new errorClass(`Expected ${re.toString()}`);\n      }\n      return false;\n    }\n    function match(re) {\n      re.lastIndex = cursor;\n      let result = re.exec(source);\n      if (result === null) {\n        throw new SyntaxError(`Expected ${re.toString()}`);\n      }\n      cursor = re.lastIndex;\n      return result;\n    }\n    function match1(re) {\n      return match(re)[1];\n    }\n    function parseMessage(id) {\n      let value = parsePattern();\n      let attributes = parseAttributes();\n      if (value === null && Object.keys(attributes).length === 0) {\n        throw new SyntaxError(\"Expected message value or attributes\");\n      }\n      return {\n        id,\n        value,\n        attributes\n      };\n    }\n    function parseAttributes() {\n      let attrs = Object.create(null);\n      while (test(RE_ATTRIBUTE_START)) {\n        let name = match1(RE_ATTRIBUTE_START);\n        let value = parsePattern();\n        if (value === null) {\n          throw new SyntaxError(\"Expected attribute value\");\n        }\n        attrs[name] = value;\n      }\n      return attrs;\n    }\n    function parsePattern() {\n      let first;\n      if (test(RE_TEXT_RUN)) {\n        first = match1(RE_TEXT_RUN);\n      }\n      if (source[cursor] === \"{\" || source[cursor] === \"}\") {\n        return parsePatternElements(first ? [first] : [], Infinity);\n      }\n      let indent = parseIndent();\n      if (indent) {\n        if (first) {\n          return parsePatternElements([first, indent], indent.length);\n        }\n        indent.value = trim(indent.value, RE_LEADING_NEWLINES);\n        return parsePatternElements([indent], indent.length);\n      }\n      if (first) {\n        return trim(first, RE_TRAILING_SPACES);\n      }\n      return null;\n    }\n    function parsePatternElements(elements = [], commonIndent) {\n      while (true) {\n        if (test(RE_TEXT_RUN)) {\n          elements.push(match1(RE_TEXT_RUN));\n          continue;\n        }\n        if (source[cursor] === \"{\") {\n          elements.push(parsePlaceable());\n          continue;\n        }\n        if (source[cursor] === \"}\") {\n          throw new SyntaxError(\"Unbalanced closing brace\");\n        }\n        let indent = parseIndent();\n        if (indent) {\n          elements.push(indent);\n          commonIndent = Math.min(commonIndent, indent.length);\n          continue;\n        }\n        break;\n      }\n      let lastIndex = elements.length - 1;\n      let lastElement = elements[lastIndex];\n      if (typeof lastElement === \"string\") {\n        elements[lastIndex] = trim(lastElement, RE_TRAILING_SPACES);\n      }\n      let baked = [];\n      for (let element of elements) {\n        if (element instanceof Indent) {\n          element = element.value.slice(0, element.value.length - commonIndent);\n        }\n        if (element) {\n          baked.push(element);\n        }\n      }\n      return baked;\n    }\n    function parsePlaceable() {\n      consumeToken(TOKEN_BRACE_OPEN, SyntaxError);\n      let selector = parseInlineExpression();\n      if (consumeToken(TOKEN_BRACE_CLOSE)) {\n        return selector;\n      }\n      if (consumeToken(TOKEN_ARROW)) {\n        let variants = parseVariants();\n        consumeToken(TOKEN_BRACE_CLOSE, SyntaxError);\n        return {\n          type: \"select\",\n          selector,\n          ...variants\n        };\n      }\n      throw new SyntaxError(\"Unclosed placeable\");\n    }\n    function parseInlineExpression() {\n      if (source[cursor] === \"{\") {\n        return parsePlaceable();\n      }\n      if (test(RE_REFERENCE)) {\n        let [, sigil, name, attr = null] = match(RE_REFERENCE);\n        if (sigil === \"$\") {\n          return {\n            type: \"var\",\n            name\n          };\n        }\n        if (consumeToken(TOKEN_PAREN_OPEN)) {\n          let args = parseArguments();\n          if (sigil === \"-\") {\n            return {\n              type: \"term\",\n              name,\n              attr,\n              args\n            };\n          }\n          if (RE_FUNCTION_NAME.test(name)) {\n            return {\n              type: \"func\",\n              name,\n              args\n            };\n          }\n          throw new SyntaxError(\"Function names must be all upper-case\");\n        }\n        if (sigil === \"-\") {\n          return {\n            type: \"term\",\n            name,\n            attr,\n            args: []\n          };\n        }\n        return {\n          type: \"mesg\",\n          name,\n          attr\n        };\n      }\n      return parseLiteral();\n    }\n    function parseArguments() {\n      let args = [];\n      while (true) {\n        switch (source[cursor]) {\n          case \")\":\n            cursor++;\n            return args;\n          case undefined:\n            throw new SyntaxError(\"Unclosed argument list\");\n        }\n        args.push(parseArgument());\n        consumeToken(TOKEN_COMMA);\n      }\n    }\n    function parseArgument() {\n      let expr = parseInlineExpression();\n      if (expr.type !== \"mesg\") {\n        return expr;\n      }\n      if (consumeToken(TOKEN_COLON)) {\n        return {\n          type: \"narg\",\n          name: expr.name,\n          value: parseLiteral()\n        };\n      }\n      return expr;\n    }\n    function parseVariants() {\n      let variants = [];\n      let count = 0;\n      let star;\n      while (test(RE_VARIANT_START)) {\n        if (consumeChar(\"*\")) {\n          star = count;\n        }\n        let key = parseVariantKey();\n        let value = parsePattern();\n        if (value === null) {\n          throw new SyntaxError(\"Expected variant value\");\n        }\n        variants[count++] = {\n          key,\n          value\n        };\n      }\n      if (count === 0) {\n        return null;\n      }\n      if (star === undefined) {\n        throw new SyntaxError(\"Expected default variant\");\n      }\n      return {\n        variants,\n        star\n      };\n    }\n    function parseVariantKey() {\n      consumeToken(TOKEN_BRACKET_OPEN, SyntaxError);\n      let key;\n      if (test(RE_NUMBER_LITERAL)) {\n        key = parseNumberLiteral();\n      } else {\n        key = {\n          type: \"str\",\n          value: match1(RE_IDENTIFIER)\n        };\n      }\n      consumeToken(TOKEN_BRACKET_CLOSE, SyntaxError);\n      return key;\n    }\n    function parseLiteral() {\n      if (test(RE_NUMBER_LITERAL)) {\n        return parseNumberLiteral();\n      }\n      if (source[cursor] === '\"') {\n        return parseStringLiteral();\n      }\n      throw new SyntaxError(\"Invalid expression\");\n    }\n    function parseNumberLiteral() {\n      let [, value, fraction = \"\"] = match(RE_NUMBER_LITERAL);\n      let precision = fraction.length;\n      return {\n        type: \"num\",\n        value: parseFloat(value),\n        precision\n      };\n    }\n    function parseStringLiteral() {\n      consumeChar('\"', SyntaxError);\n      let value = \"\";\n      while (true) {\n        value += match1(RE_STRING_RUN);\n        if (source[cursor] === \"\\\\\") {\n          value += parseEscapeSequence();\n          continue;\n        }\n        if (consumeChar('\"')) {\n          return {\n            type: \"str\",\n            value\n          };\n        }\n        throw new SyntaxError(\"Unclosed string literal\");\n      }\n    }\n    function parseEscapeSequence() {\n      if (test(RE_STRING_ESCAPE)) {\n        return match1(RE_STRING_ESCAPE);\n      }\n      if (test(RE_UNICODE_ESCAPE)) {\n        let [, codepoint4, codepoint6] = match(RE_UNICODE_ESCAPE);\n        let codepoint = parseInt(codepoint4 || codepoint6, 16);\n        return codepoint <= 0xd7ff || 0xe000 <= codepoint ? String.fromCodePoint(codepoint) : \"�\";\n      }\n      throw new SyntaxError(\"Unknown escape sequence\");\n    }\n    function parseIndent() {\n      let start = cursor;\n      consumeToken(TOKEN_BLANK);\n      switch (source[cursor]) {\n        case \".\":\n        case \"[\":\n        case \"*\":\n        case \"}\":\n        case undefined:\n          return false;\n        case \"{\":\n          return makeIndent(source.slice(start, cursor));\n      }\n      if (source[cursor - 1] === \" \") {\n        return makeIndent(source.slice(start, cursor));\n      }\n      return false;\n    }\n    function trim(text, re) {\n      return text.replace(re, \"\");\n    }\n    function makeIndent(blank) {\n      let value = blank.replace(RE_BLANK_LINES, \"\\n\");\n      let length = RE_INDENT.exec(blank)[1].length;\n      return new Indent(value, length);\n    }\n  }\n}\nclass Indent {\n  constructor(value, length) {\n    this.value = value;\n    this.length = length;\n  }\n}\n;// CONCATENATED MODULE: ./node_modules/@fluent/bundle/esm/index.js\n\n\n\n\n/***/ }),\n\n/***/ 5273:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, {\n  DOMLocalization: () => (/* reexport */ DOMLocalization)\n});\n\n// UNUSED EXPORTS: Localization\n\n;// CONCATENATED MODULE: ./node_modules/@fluent/dom/esm/overlay.js\nconst reOverlay = /<|&#?\\w+;/;\nconst TEXT_LEVEL_ELEMENTS = {\n  \"http://www.w3.org/1999/xhtml\": [\"em\", \"strong\", \"small\", \"s\", \"cite\", \"q\", \"dfn\", \"abbr\", \"data\", \"time\", \"code\", \"var\", \"samp\", \"kbd\", \"sub\", \"sup\", \"i\", \"b\", \"u\", \"mark\", \"bdi\", \"bdo\", \"span\", \"br\", \"wbr\"]\n};\nconst LOCALIZABLE_ATTRIBUTES = {\n  \"http://www.w3.org/1999/xhtml\": {\n    global: [\"title\", \"aria-label\", \"aria-valuetext\"],\n    a: [\"download\"],\n    area: [\"download\", \"alt\"],\n    input: [\"alt\", \"placeholder\"],\n    menuitem: [\"label\"],\n    menu: [\"label\"],\n    optgroup: [\"label\"],\n    option: [\"label\"],\n    track: [\"label\"],\n    img: [\"alt\"],\n    textarea: [\"placeholder\"],\n    th: [\"abbr\"]\n  },\n  \"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul\": {\n    global: [\"accesskey\", \"aria-label\", \"aria-valuetext\", \"label\", \"title\", \"tooltiptext\"],\n    description: [\"value\"],\n    key: [\"key\", \"keycode\"],\n    label: [\"value\"],\n    textbox: [\"placeholder\", \"value\"]\n  }\n};\nfunction translateElement(element, translation) {\n  const {\n    value\n  } = translation;\n  if (typeof value === \"string\") {\n    if (element.localName === \"title\" && element.namespaceURI === \"http://www.w3.org/1999/xhtml\") {\n      element.textContent = value;\n    } else if (!reOverlay.test(value)) {\n      element.textContent = value;\n    } else {\n      const templateElement = element.ownerDocument.createElementNS(\"http://www.w3.org/1999/xhtml\", \"template\");\n      templateElement.innerHTML = value;\n      overlayChildNodes(templateElement.content, element);\n    }\n  }\n  overlayAttributes(translation, element);\n}\nfunction overlayChildNodes(fromFragment, toElement) {\n  for (const childNode of fromFragment.childNodes) {\n    if (childNode.nodeType === childNode.TEXT_NODE) {\n      continue;\n    }\n    if (childNode.hasAttribute(\"data-l10n-name\")) {\n      const sanitized = getNodeForNamedElement(toElement, childNode);\n      fromFragment.replaceChild(sanitized, childNode);\n      continue;\n    }\n    if (isElementAllowed(childNode)) {\n      const sanitized = createSanitizedElement(childNode);\n      fromFragment.replaceChild(sanitized, childNode);\n      continue;\n    }\n    console.warn(`An element of forbidden type \"${childNode.localName}\" was found in ` + \"the translation. Only safe text-level elements and elements with \" + \"data-l10n-name are allowed.\");\n    fromFragment.replaceChild(createTextNodeFromTextContent(childNode), childNode);\n  }\n  toElement.textContent = \"\";\n  toElement.appendChild(fromFragment);\n}\nfunction hasAttribute(attributes, name) {\n  if (!attributes) {\n    return false;\n  }\n  for (let attr of attributes) {\n    if (attr.name === name) {\n      return true;\n    }\n  }\n  return false;\n}\nfunction overlayAttributes(fromElement, toElement) {\n  const explicitlyAllowed = toElement.hasAttribute(\"data-l10n-attrs\") ? toElement.getAttribute(\"data-l10n-attrs\").split(\",\").map(i => i.trim()) : null;\n  for (const attr of Array.from(toElement.attributes)) {\n    if (isAttrNameLocalizable(attr.name, toElement, explicitlyAllowed) && !hasAttribute(fromElement.attributes, attr.name)) {\n      toElement.removeAttribute(attr.name);\n    }\n  }\n  if (!fromElement.attributes) {\n    return;\n  }\n  for (const attr of Array.from(fromElement.attributes)) {\n    if (isAttrNameLocalizable(attr.name, toElement, explicitlyAllowed) && toElement.getAttribute(attr.name) !== attr.value) {\n      toElement.setAttribute(attr.name, attr.value);\n    }\n  }\n}\nfunction getNodeForNamedElement(sourceElement, translatedChild) {\n  const childName = translatedChild.getAttribute(\"data-l10n-name\");\n  const sourceChild = sourceElement.querySelector(`[data-l10n-name=\"${childName}\"]`);\n  if (!sourceChild) {\n    console.warn(`An element named \"${childName}\" wasn't found in the source.`);\n    return createTextNodeFromTextContent(translatedChild);\n  }\n  if (sourceChild.localName !== translatedChild.localName) {\n    console.warn(`An element named \"${childName}\" was found in the translation ` + `but its type ${translatedChild.localName} didn't match the ` + `element found in the source (${sourceChild.localName}).`);\n    return createTextNodeFromTextContent(translatedChild);\n  }\n  sourceElement.removeChild(sourceChild);\n  const clone = sourceChild.cloneNode(false);\n  return shallowPopulateUsing(translatedChild, clone);\n}\nfunction createSanitizedElement(element) {\n  const clone = element.ownerDocument.createElement(element.localName);\n  return shallowPopulateUsing(element, clone);\n}\nfunction createTextNodeFromTextContent(element) {\n  return element.ownerDocument.createTextNode(element.textContent);\n}\nfunction isElementAllowed(element) {\n  const allowed = TEXT_LEVEL_ELEMENTS[element.namespaceURI];\n  return allowed && allowed.includes(element.localName);\n}\nfunction isAttrNameLocalizable(name, element, explicitlyAllowed = null) {\n  if (explicitlyAllowed && explicitlyAllowed.includes(name)) {\n    return true;\n  }\n  const allowed = LOCALIZABLE_ATTRIBUTES[element.namespaceURI];\n  if (!allowed) {\n    return false;\n  }\n  const attrName = name.toLowerCase();\n  const elemName = element.localName;\n  if (allowed.global.includes(attrName)) {\n    return true;\n  }\n  if (!allowed[elemName]) {\n    return false;\n  }\n  if (allowed[elemName].includes(attrName)) {\n    return true;\n  }\n  if (element.namespaceURI === \"http://www.w3.org/1999/xhtml\" && elemName === \"input\" && attrName === \"value\") {\n    const type = element.type.toLowerCase();\n    if (type === \"submit\" || type === \"button\" || type === \"reset\") {\n      return true;\n    }\n  }\n  return false;\n}\nfunction shallowPopulateUsing(fromElement, toElement) {\n  toElement.textContent = fromElement.textContent;\n  overlayAttributes(fromElement, toElement);\n  return toElement;\n}\n;// CONCATENATED MODULE: ./node_modules/cached-iterable/src/cached_iterable.mjs\nclass CachedIterable extends Array {\n  static from(iterable) {\n    if (iterable instanceof this) {\n      return iterable;\n    }\n    return new this(iterable);\n  }\n}\n;// CONCATENATED MODULE: ./node_modules/cached-iterable/src/cached_sync_iterable.mjs\n\nclass CachedSyncIterable extends CachedIterable {\n  constructor(iterable) {\n    super();\n    if (Symbol.iterator in Object(iterable)) {\n      this.iterator = iterable[Symbol.iterator]();\n    } else {\n      throw new TypeError(\"Argument must implement the iteration protocol.\");\n    }\n  }\n  [Symbol.iterator]() {\n    const cached = this;\n    let cur = 0;\n    return {\n      next() {\n        if (cached.length <= cur) {\n          cached.push(cached.iterator.next());\n        }\n        return cached[cur++];\n      }\n    };\n  }\n  touchNext(count = 1) {\n    let idx = 0;\n    while (idx++ < count) {\n      const last = this[this.length - 1];\n      if (last && last.done) {\n        break;\n      }\n      this.push(this.iterator.next());\n    }\n    return this[this.length - 1];\n  }\n}\n;// CONCATENATED MODULE: ./node_modules/cached-iterable/src/cached_async_iterable.mjs\n\nclass CachedAsyncIterable extends CachedIterable {\n  constructor(iterable) {\n    super();\n    if (Symbol.asyncIterator in Object(iterable)) {\n      this.iterator = iterable[Symbol.asyncIterator]();\n    } else if (Symbol.iterator in Object(iterable)) {\n      this.iterator = iterable[Symbol.iterator]();\n    } else {\n      throw new TypeError(\"Argument must implement the iteration protocol.\");\n    }\n  }\n  [Symbol.asyncIterator]() {\n    const cached = this;\n    let cur = 0;\n    return {\n      async next() {\n        if (cached.length <= cur) {\n          cached.push(cached.iterator.next());\n        }\n        return cached[cur++];\n      }\n    };\n  }\n  async touchNext(count = 1) {\n    let idx = 0;\n    while (idx++ < count) {\n      const last = this[this.length - 1];\n      if (last && (await last).done) {\n        break;\n      }\n      this.push(this.iterator.next());\n    }\n    return this[this.length - 1];\n  }\n}\n;// CONCATENATED MODULE: ./node_modules/cached-iterable/src/index.mjs\n\n\n;// CONCATENATED MODULE: ./node_modules/@fluent/dom/esm/localization.js\n\nclass Localization {\n  constructor(resourceIds = [], generateBundles) {\n    this.resourceIds = resourceIds;\n    this.generateBundles = generateBundles;\n    this.onChange(true);\n  }\n  addResourceIds(resourceIds, eager = false) {\n    this.resourceIds.push(...resourceIds);\n    this.onChange(eager);\n    return this.resourceIds.length;\n  }\n  removeResourceIds(resourceIds) {\n    this.resourceIds = this.resourceIds.filter(r => !resourceIds.includes(r));\n    this.onChange();\n    return this.resourceIds.length;\n  }\n  async formatWithFallback(keys, method) {\n    const translations = [];\n    let hasAtLeastOneBundle = false;\n    for await (const bundle of this.bundles) {\n      hasAtLeastOneBundle = true;\n      const missingIds = keysFromBundle(method, bundle, keys, translations);\n      if (missingIds.size === 0) {\n        break;\n      }\n      if (typeof console !== \"undefined\") {\n        const locale = bundle.locales[0];\n        const ids = Array.from(missingIds).join(\", \");\n        console.warn(`[fluent] Missing translations in ${locale}: ${ids}`);\n      }\n    }\n    if (!hasAtLeastOneBundle && typeof console !== \"undefined\") {\n      console.warn(`[fluent] Request for keys failed because no resource bundles got generated.\n  keys: ${JSON.stringify(keys)}.\n  resourceIds: ${JSON.stringify(this.resourceIds)}.`);\n    }\n    return translations;\n  }\n  formatMessages(keys) {\n    return this.formatWithFallback(keys, messageFromBundle);\n  }\n  formatValues(keys) {\n    return this.formatWithFallback(keys, valueFromBundle);\n  }\n  async formatValue(id, args) {\n    const [val] = await this.formatValues([{\n      id,\n      args\n    }]);\n    return val;\n  }\n  handleEvent() {\n    this.onChange();\n  }\n  onChange(eager = false) {\n    this.bundles = CachedAsyncIterable.from(this.generateBundles(this.resourceIds));\n    if (eager) {\n      this.bundles.touchNext(2);\n    }\n  }\n}\nfunction valueFromBundle(bundle, errors, message, args) {\n  if (message.value) {\n    return bundle.formatPattern(message.value, args, errors);\n  }\n  return null;\n}\nfunction messageFromBundle(bundle, errors, message, args) {\n  const formatted = {\n    value: null,\n    attributes: null\n  };\n  if (message.value) {\n    formatted.value = bundle.formatPattern(message.value, args, errors);\n  }\n  let attrNames = Object.keys(message.attributes);\n  if (attrNames.length > 0) {\n    formatted.attributes = new Array(attrNames.length);\n    for (let [i, name] of attrNames.entries()) {\n      let value = bundle.formatPattern(message.attributes[name], args, errors);\n      formatted.attributes[i] = {\n        name,\n        value\n      };\n    }\n  }\n  return formatted;\n}\nfunction keysFromBundle(method, bundle, keys, translations) {\n  const messageErrors = [];\n  const missingIds = new Set();\n  keys.forEach(({\n    id,\n    args\n  }, i) => {\n    if (translations[i] !== undefined) {\n      return;\n    }\n    let message = bundle.getMessage(id);\n    if (message) {\n      messageErrors.length = 0;\n      translations[i] = method(bundle, messageErrors, message, args);\n      if (messageErrors.length > 0 && typeof console !== \"undefined\") {\n        const locale = bundle.locales[0];\n        const errors = messageErrors.join(\", \");\n        console.warn(`[fluent][resolver] errors in ${locale}/${id}: ${errors}.`);\n      }\n    } else {\n      missingIds.add(id);\n    }\n  });\n  return missingIds;\n}\n;// CONCATENATED MODULE: ./node_modules/@fluent/dom/esm/dom_localization.js\n\n\nconst L10NID_ATTR_NAME = \"data-l10n-id\";\nconst L10NARGS_ATTR_NAME = \"data-l10n-args\";\nconst L10N_ELEMENT_QUERY = `[${L10NID_ATTR_NAME}]`;\nclass DOMLocalization extends Localization {\n  constructor(resourceIds, generateBundles) {\n    super(resourceIds, generateBundles);\n    this.roots = new Set();\n    this.pendingrAF = null;\n    this.pendingElements = new Set();\n    this.windowElement = null;\n    this.mutationObserver = null;\n    this.observerConfig = {\n      attributes: true,\n      characterData: false,\n      childList: true,\n      subtree: true,\n      attributeFilter: [L10NID_ATTR_NAME, L10NARGS_ATTR_NAME]\n    };\n  }\n  onChange(eager = false) {\n    super.onChange(eager);\n    if (this.roots) {\n      this.translateRoots();\n    }\n  }\n  setAttributes(element, id, args) {\n    element.setAttribute(L10NID_ATTR_NAME, id);\n    if (args) {\n      element.setAttribute(L10NARGS_ATTR_NAME, JSON.stringify(args));\n    } else {\n      element.removeAttribute(L10NARGS_ATTR_NAME);\n    }\n    return element;\n  }\n  getAttributes(element) {\n    return {\n      id: element.getAttribute(L10NID_ATTR_NAME),\n      args: JSON.parse(element.getAttribute(L10NARGS_ATTR_NAME) || null)\n    };\n  }\n  connectRoot(newRoot) {\n    for (const root of this.roots) {\n      if (root === newRoot || root.contains(newRoot) || newRoot.contains(root)) {\n        throw new Error(\"Cannot add a root that overlaps with existing root.\");\n      }\n    }\n    if (this.windowElement) {\n      if (this.windowElement !== newRoot.ownerDocument.defaultView) {\n        throw new Error(`Cannot connect a root:\n          DOMLocalization already has a root from a different window.`);\n      }\n    } else {\n      this.windowElement = newRoot.ownerDocument.defaultView;\n      this.mutationObserver = new this.windowElement.MutationObserver(mutations => this.translateMutations(mutations));\n    }\n    this.roots.add(newRoot);\n    this.mutationObserver.observe(newRoot, this.observerConfig);\n  }\n  disconnectRoot(root) {\n    this.roots.delete(root);\n    this.pauseObserving();\n    if (this.roots.size === 0) {\n      this.mutationObserver = null;\n      this.windowElement = null;\n      this.pendingrAF = null;\n      this.pendingElements.clear();\n      return true;\n    }\n    this.resumeObserving();\n    return false;\n  }\n  translateRoots() {\n    const roots = Array.from(this.roots);\n    return Promise.all(roots.map(root => this.translateFragment(root)));\n  }\n  pauseObserving() {\n    if (!this.mutationObserver) {\n      return;\n    }\n    this.translateMutations(this.mutationObserver.takeRecords());\n    this.mutationObserver.disconnect();\n  }\n  resumeObserving() {\n    if (!this.mutationObserver) {\n      return;\n    }\n    for (const root of this.roots) {\n      this.mutationObserver.observe(root, this.observerConfig);\n    }\n  }\n  translateMutations(mutations) {\n    for (const mutation of mutations) {\n      switch (mutation.type) {\n        case \"attributes\":\n          if (mutation.target.hasAttribute(\"data-l10n-id\")) {\n            this.pendingElements.add(mutation.target);\n          }\n          break;\n        case \"childList\":\n          for (const addedNode of mutation.addedNodes) {\n            if (addedNode.nodeType === addedNode.ELEMENT_NODE) {\n              if (addedNode.childElementCount) {\n                for (const element of this.getTranslatables(addedNode)) {\n                  this.pendingElements.add(element);\n                }\n              } else if (addedNode.hasAttribute(L10NID_ATTR_NAME)) {\n                this.pendingElements.add(addedNode);\n              }\n            }\n          }\n          break;\n      }\n    }\n    if (this.pendingElements.size > 0) {\n      if (this.pendingrAF === null) {\n        this.pendingrAF = this.windowElement.requestAnimationFrame(() => {\n          this.translateElements(Array.from(this.pendingElements));\n          this.pendingElements.clear();\n          this.pendingrAF = null;\n        });\n      }\n    }\n  }\n  translateFragment(frag) {\n    return this.translateElements(this.getTranslatables(frag));\n  }\n  async translateElements(elements) {\n    if (!elements.length) {\n      return undefined;\n    }\n    const keys = elements.map(this.getKeysForElement);\n    const translations = await this.formatMessages(keys);\n    return this.applyTranslations(elements, translations);\n  }\n  applyTranslations(elements, translations) {\n    this.pauseObserving();\n    for (let i = 0; i < elements.length; i++) {\n      if (translations[i] !== undefined) {\n        translateElement(elements[i], translations[i]);\n      }\n    }\n    this.resumeObserving();\n  }\n  getTranslatables(element) {\n    const nodes = Array.from(element.querySelectorAll(L10N_ELEMENT_QUERY));\n    if (typeof element.hasAttribute === \"function\" && element.hasAttribute(L10NID_ATTR_NAME)) {\n      nodes.push(element);\n    }\n    return nodes;\n  }\n  getKeysForElement(element) {\n    return {\n      id: element.getAttribute(L10NID_ATTR_NAME),\n      args: JSON.parse(element.getAttribute(L10NARGS_ATTR_NAME) || null)\n    };\n  }\n}\n;// CONCATENATED MODULE: ./node_modules/@fluent/dom/esm/index.js\n\n\n\n/***/ }),\n\n/***/ 259:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   AltTextManager: () => (/* binding */ AltTextManager)\n/* harmony export */ });\n/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__]);\npdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];\n\nclass AltTextManager {\n  #boundUpdateUIState = this.#updateUIState.bind(this);\n  #boundSetPosition = this.#setPosition.bind(this);\n  #boundOnClick = this.#onClick.bind(this);\n  #currentEditor = null;\n  #cancelButton;\n  #dialog;\n  #eventBus;\n  #hasUsedPointer = false;\n  #optionDescription;\n  #optionDecorative;\n  #overlayManager;\n  #saveButton;\n  #textarea;\n  #uiManager;\n  #previousAltText = null;\n  #svgElement = null;\n  #rectElement = null;\n  #container;\n  #telemetryData = null;\n  constructor({\n    dialog,\n    optionDescription,\n    optionDecorative,\n    textarea,\n    cancelButton,\n    saveButton\n  }, container, overlayManager, eventBus) {\n    this.#dialog = dialog;\n    this.#optionDescription = optionDescription;\n    this.#optionDecorative = optionDecorative;\n    this.#textarea = textarea;\n    this.#cancelButton = cancelButton;\n    this.#saveButton = saveButton;\n    this.#overlayManager = overlayManager;\n    this.#eventBus = eventBus;\n    this.#container = container;\n    dialog.addEventListener(\"close\", this.#close.bind(this));\n    dialog.addEventListener(\"contextmenu\", event => {\n      if (event.target !== this.#textarea) {\n        event.preventDefault();\n      }\n    });\n    cancelButton.addEventListener(\"click\", this.#finish.bind(this));\n    saveButton.addEventListener(\"click\", this.#save.bind(this));\n    optionDescription.addEventListener(\"change\", this.#boundUpdateUIState);\n    optionDecorative.addEventListener(\"change\", this.#boundUpdateUIState);\n    this.#overlayManager.register(dialog);\n  }\n  get _elements() {\n    return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, \"_elements\", [this.#optionDescription, this.#optionDecorative, this.#textarea, this.#saveButton, this.#cancelButton]);\n  }\n  #createSVGElement() {\n    if (this.#svgElement) {\n      return;\n    }\n    const svgFactory = new pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.DOMSVGFactory();\n    const svg = this.#svgElement = svgFactory.createElement(\"svg\");\n    svg.setAttribute(\"width\", \"0\");\n    svg.setAttribute(\"height\", \"0\");\n    const defs = svgFactory.createElement(\"defs\");\n    svg.append(defs);\n    const mask = svgFactory.createElement(\"mask\");\n    defs.append(mask);\n    mask.setAttribute(\"id\", \"alttext-manager-mask\");\n    mask.setAttribute(\"maskContentUnits\", \"objectBoundingBox\");\n    let rect = svgFactory.createElement(\"rect\");\n    mask.append(rect);\n    rect.setAttribute(\"fill\", \"white\");\n    rect.setAttribute(\"width\", \"1\");\n    rect.setAttribute(\"height\", \"1\");\n    rect.setAttribute(\"x\", \"0\");\n    rect.setAttribute(\"y\", \"0\");\n    rect = this.#rectElement = svgFactory.createElement(\"rect\");\n    mask.append(rect);\n    rect.setAttribute(\"fill\", \"black\");\n    this.#dialog.append(svg);\n  }\n  async editAltText(uiManager, editor) {\n    if (this.#currentEditor || !editor) {\n      return;\n    }\n    this.#createSVGElement();\n    this.#hasUsedPointer = false;\n    for (const element of this._elements) {\n      element.addEventListener(\"click\", this.#boundOnClick);\n    }\n    const {\n      altText,\n      decorative\n    } = editor.altTextData;\n    if (decorative === true) {\n      this.#optionDecorative.checked = true;\n      this.#optionDescription.checked = false;\n    } else {\n      this.#optionDecorative.checked = false;\n      this.#optionDescription.checked = true;\n    }\n    this.#previousAltText = this.#textarea.value = altText?.trim() || \"\";\n    this.#updateUIState();\n    this.#currentEditor = editor;\n    this.#uiManager = uiManager;\n    this.#uiManager.removeEditListeners();\n    this.#eventBus._on(\"resize\", this.#boundSetPosition);\n    try {\n      await this.#overlayManager.open(this.#dialog);\n      this.#setPosition();\n    } catch (ex) {\n      this.#close();\n      throw ex;\n    }\n  }\n  #setPosition() {\n    if (!this.#currentEditor) {\n      return;\n    }\n    const dialog = this.#dialog;\n    const {\n      style\n    } = dialog;\n    const {\n      x: containerX,\n      y: containerY,\n      width: containerW,\n      height: containerH\n    } = this.#container.getBoundingClientRect();\n    const {\n      innerWidth: windowW,\n      innerHeight: windowH\n    } = window;\n    const {\n      width: dialogW,\n      height: dialogH\n    } = dialog.getBoundingClientRect();\n    const {\n      x,\n      y,\n      width,\n      height\n    } = this.#currentEditor.getClientDimensions();\n    const MARGIN = 10;\n    const isLTR = this.#uiManager.direction === \"ltr\";\n    const xs = Math.max(x, containerX);\n    const xe = Math.min(x + width, containerX + containerW);\n    const ys = Math.max(y, containerY);\n    const ye = Math.min(y + height, containerY + containerH);\n    this.#rectElement.setAttribute(\"width\", `${(xe - xs) / windowW}`);\n    this.#rectElement.setAttribute(\"height\", `${(ye - ys) / windowH}`);\n    this.#rectElement.setAttribute(\"x\", `${xs / windowW}`);\n    this.#rectElement.setAttribute(\"y\", `${ys / windowH}`);\n    let left = null;\n    let top = Math.max(y, 0);\n    top += Math.min(windowH - (top + dialogH), 0);\n    if (isLTR) {\n      if (x + width + MARGIN + dialogW < windowW) {\n        left = x + width + MARGIN;\n      } else if (x > dialogW + MARGIN) {\n        left = x - dialogW - MARGIN;\n      }\n    } else if (x > dialogW + MARGIN) {\n      left = x - dialogW - MARGIN;\n    } else if (x + width + MARGIN + dialogW < windowW) {\n      left = x + width + MARGIN;\n    }\n    if (left === null) {\n      top = null;\n      left = Math.max(x, 0);\n      left += Math.min(windowW - (left + dialogW), 0);\n      if (y > dialogH + MARGIN) {\n        top = y - dialogH - MARGIN;\n      } else if (y + height + MARGIN + dialogH < windowH) {\n        top = y + height + MARGIN;\n      }\n    }\n    if (top !== null) {\n      dialog.classList.add(\"positioned\");\n      if (isLTR) {\n        style.left = `${left}px`;\n      } else {\n        style.right = `${windowW - left - dialogW}px`;\n      }\n      style.top = `${top}px`;\n    } else {\n      dialog.classList.remove(\"positioned\");\n      style.left = \"\";\n      style.top = \"\";\n    }\n  }\n  #finish() {\n    if (this.#overlayManager.active === this.#dialog) {\n      this.#overlayManager.close(this.#dialog);\n    }\n  }\n  #close() {\n    this.#currentEditor._reportTelemetry(this.#telemetryData || {\n      action: \"alt_text_cancel\",\n      alt_text_keyboard: !this.#hasUsedPointer\n    });\n    this.#telemetryData = null;\n    this.#removeOnClickListeners();\n    this.#uiManager?.addEditListeners();\n    this.#eventBus._off(\"resize\", this.#boundSetPosition);\n    this.#currentEditor.altTextFinish();\n    this.#currentEditor = null;\n    this.#uiManager = null;\n  }\n  #updateUIState() {\n    this.#textarea.disabled = this.#optionDecorative.checked;\n  }\n  #save() {\n    const altText = this.#textarea.value.trim();\n    const decorative = this.#optionDecorative.checked;\n    this.#currentEditor.altTextData = {\n      altText,\n      decorative\n    };\n    this.#telemetryData = {\n      action: \"alt_text_save\",\n      alt_text_description: !!altText,\n      alt_text_edit: !!this.#previousAltText && this.#previousAltText !== altText,\n      alt_text_decorative: decorative,\n      alt_text_keyboard: !this.#hasUsedPointer\n    };\n    this.#finish();\n  }\n  #onClick(evt) {\n    if (evt.detail === 0) {\n      return;\n    }\n    this.#hasUsedPointer = true;\n    this.#removeOnClickListeners();\n  }\n  #removeOnClickListeners() {\n    for (const element of this._elements) {\n      element.removeEventListener(\"click\", this.#boundOnClick);\n    }\n  }\n  destroy() {\n    this.#uiManager = null;\n    this.#finish();\n    this.#svgElement?.remove();\n    this.#svgElement = this.#rectElement = null;\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 283:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   AnnotationEditorLayerBuilder: () => (/* binding */ AnnotationEditorLayerBuilder)\n/* harmony export */ });\n/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603);\n/* harmony import */ var web_null_l10n__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(410);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__, web_null_l10n__WEBPACK_IMPORTED_MODULE_1__]);\n([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__, web_null_l10n__WEBPACK_IMPORTED_MODULE_1__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__);\n\n\nclass AnnotationEditorLayerBuilder {\n  #annotationLayer = null;\n  #drawLayer = null;\n  #onAppend = null;\n  #textLayer = null;\n  #uiManager;\n  constructor(options) {\n    this.pdfPage = options.pdfPage;\n    this.accessibilityManager = options.accessibilityManager;\n    this.l10n = options.l10n;\n    this.l10n ||= new web_null_l10n__WEBPACK_IMPORTED_MODULE_1__.GenericL10n();\n    this.annotationEditorLayer = null;\n    this.div = null;\n    this._cancelled = false;\n    this.#uiManager = options.uiManager;\n    this.#annotationLayer = options.annotationLayer || null;\n    this.#textLayer = options.textLayer || null;\n    this.#drawLayer = options.drawLayer || null;\n    this.#onAppend = options.onAppend || null;\n  }\n  async render(viewport, intent = \"display\") {\n    if (intent !== \"display\") {\n      return;\n    }\n    if (this._cancelled) {\n      return;\n    }\n    const clonedViewport = viewport.clone({\n      dontFlip: true\n    });\n    if (this.div) {\n      this.annotationEditorLayer.update({\n        viewport: clonedViewport\n      });\n      this.show();\n      return;\n    }\n    const div = this.div = document.createElement(\"div\");\n    div.className = \"annotationEditorLayer\";\n    div.hidden = true;\n    div.dir = this.#uiManager.direction;\n    this.#onAppend?.(div);\n    this.annotationEditorLayer = new pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorLayer({\n      uiManager: this.#uiManager,\n      div,\n      accessibilityManager: this.accessibilityManager,\n      pageIndex: this.pdfPage.pageNumber - 1,\n      l10n: this.l10n,\n      viewport: clonedViewport,\n      annotationLayer: this.#annotationLayer,\n      textLayer: this.#textLayer,\n      drawLayer: this.#drawLayer\n    });\n    const parameters = {\n      viewport: clonedViewport,\n      div,\n      annotations: null,\n      intent\n    };\n    this.annotationEditorLayer.render(parameters);\n    this.show();\n  }\n  cancel() {\n    this._cancelled = true;\n    if (!this.div) {\n      return;\n    }\n    this.annotationEditorLayer.destroy();\n  }\n  hide() {\n    if (!this.div) {\n      return;\n    }\n    this.div.hidden = true;\n  }\n  show() {\n    if (!this.div || this.annotationEditorLayer.isInvisible) {\n      return;\n    }\n    this.div.hidden = false;\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 226:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   AnnotationEditorParams: () => (/* binding */ AnnotationEditorParams)\n/* harmony export */ });\n/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__]);\npdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];\n\nclass AnnotationEditorParams {\n  constructor(options, eventBus) {\n    this.eventBus = eventBus;\n    this.#bindListeners(options);\n  }\n  #bindListeners({\n    editorFreeTextFontSize,\n    editorFreeTextColor,\n    editorInkColor,\n    editorInkThickness,\n    editorInkOpacity,\n    editorStampAddImage,\n    editorFreeHighlightThickness,\n    editorHighlightShowAll\n  }) {\n    const dispatchEvent = (typeStr, value) => {\n      this.eventBus.dispatch(\"switchannotationeditorparams\", {\n        source: this,\n        type: pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType[typeStr],\n        value\n      });\n    };\n    editorFreeTextFontSize.addEventListener(\"input\", function () {\n      dispatchEvent(\"FREETEXT_SIZE\", this.valueAsNumber);\n    });\n    editorFreeTextColor.addEventListener(\"input\", function () {\n      dispatchEvent(\"FREETEXT_COLOR\", this.value);\n    });\n    editorInkColor.addEventListener(\"input\", function () {\n      dispatchEvent(\"INK_COLOR\", this.value);\n    });\n    editorInkThickness.addEventListener(\"input\", function () {\n      dispatchEvent(\"INK_THICKNESS\", this.valueAsNumber);\n    });\n    editorInkOpacity.addEventListener(\"input\", function () {\n      dispatchEvent(\"INK_OPACITY\", this.valueAsNumber);\n    });\n    editorStampAddImage.addEventListener(\"click\", () => {\n      dispatchEvent(\"CREATE\");\n    });\n    editorFreeHighlightThickness.addEventListener(\"input\", function () {\n      dispatchEvent(\"HIGHLIGHT_THICKNESS\", this.valueAsNumber);\n    });\n    editorHighlightShowAll.addEventListener(\"click\", function () {\n      const checked = this.getAttribute(\"aria-pressed\") === \"true\";\n      this.setAttribute(\"aria-pressed\", !checked);\n      dispatchEvent(\"HIGHLIGHT_SHOW_ALL\", !checked);\n    });\n    this.eventBus._on(\"annotationeditorparamschanged\", evt => {\n      for (const [type, value] of evt.details) {\n        switch (type) {\n          case pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.FREETEXT_SIZE:\n            editorFreeTextFontSize.value = value;\n            break;\n          case pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.FREETEXT_COLOR:\n            editorFreeTextColor.value = value;\n            break;\n          case pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.INK_COLOR:\n            editorInkColor.value = value;\n            break;\n          case pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.INK_THICKNESS:\n            editorInkThickness.value = value;\n            break;\n          case pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.INK_OPACITY:\n            editorInkOpacity.value = value;\n            break;\n          case pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.HIGHLIGHT_THICKNESS:\n            editorFreeHighlightThickness.value = value;\n            break;\n          case pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.HIGHLIGHT_FREE:\n            editorFreeHighlightThickness.disabled = !value;\n            break;\n          case pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL:\n            editorHighlightShowAll.setAttribute(\"aria-pressed\", value);\n            break;\n        }\n      }\n    });\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 2707:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   AnnotationLayerBuilder: () => (/* binding */ AnnotationLayerBuilder)\n/* harmony export */ });\n/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603);\n/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7256);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__]);\npdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];\n\n\nclass AnnotationLayerBuilder {\n  #onAppend = null;\n  #eventAbortController = null;\n  constructor({\n    pdfPage,\n    linkService,\n    downloadManager,\n    annotationStorage = null,\n    imageResourcesPath = \"\",\n    renderForms = true,\n    enableScripting = false,\n    hasJSActionsPromise = null,\n    fieldObjectsPromise = null,\n    annotationCanvasMap = null,\n    accessibilityManager = null,\n    annotationEditorUIManager = null,\n    onAppend = null\n  }) {\n    this.pdfPage = pdfPage;\n    this.linkService = linkService;\n    this.downloadManager = downloadManager;\n    this.imageResourcesPath = imageResourcesPath;\n    this.renderForms = renderForms;\n    this.annotationStorage = annotationStorage;\n    this.enableScripting = enableScripting;\n    this._hasJSActionsPromise = hasJSActionsPromise || Promise.resolve(false);\n    this._fieldObjectsPromise = fieldObjectsPromise || Promise.resolve(null);\n    this._annotationCanvasMap = annotationCanvasMap;\n    this._accessibilityManager = accessibilityManager;\n    this._annotationEditorUIManager = annotationEditorUIManager;\n    this.#onAppend = onAppend;\n    this.annotationLayer = null;\n    this.div = null;\n    this._cancelled = false;\n    this._eventBus = linkService.eventBus;\n  }\n  async render(viewport, intent = \"display\") {\n    if (this.div) {\n      if (this._cancelled || !this.annotationLayer) {\n        return;\n      }\n      this.annotationLayer.update({\n        viewport: viewport.clone({\n          dontFlip: true\n        })\n      });\n      return;\n    }\n    const [annotations, hasJSActions, fieldObjects] = await Promise.all([this.pdfPage.getAnnotations({\n      intent\n    }), this._hasJSActionsPromise, this._fieldObjectsPromise]);\n    if (this._cancelled) {\n      return;\n    }\n    const div = this.div = document.createElement(\"div\");\n    div.className = \"annotationLayer\";\n    this.#onAppend?.(div);\n    if (annotations.length === 0) {\n      this.hide();\n      return;\n    }\n    this.annotationLayer = new pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationLayer({\n      div,\n      accessibilityManager: this._accessibilityManager,\n      annotationCanvasMap: this._annotationCanvasMap,\n      annotationEditorUIManager: this._annotationEditorUIManager,\n      page: this.pdfPage,\n      viewport: viewport.clone({\n        dontFlip: true\n      })\n    });\n    await this.annotationLayer.render({\n      annotations,\n      imageResourcesPath: this.imageResourcesPath,\n      renderForms: this.renderForms,\n      linkService: this.linkService,\n      downloadManager: this.downloadManager,\n      annotationStorage: this.annotationStorage,\n      enableScripting: this.enableScripting,\n      hasJSActions,\n      fieldObjects\n    });\n    if (this.linkService.isInPresentationMode) {\n      this.#updatePresentationModeState(_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.PresentationModeState.FULLSCREEN);\n    }\n    if (!this.#eventAbortController) {\n      this.#eventAbortController = new AbortController();\n      this._eventBus?._on(\"presentationmodechanged\", evt => {\n        this.#updatePresentationModeState(evt.state);\n      }, {\n        signal: this.#eventAbortController.signal\n      });\n    }\n  }\n  cancel() {\n    this._cancelled = true;\n    this.#eventAbortController?.abort();\n    this.#eventAbortController = null;\n  }\n  hide() {\n    if (!this.div) {\n      return;\n    }\n    this.div.hidden = true;\n  }\n  #updatePresentationModeState(state) {\n    if (!this.div) {\n      return;\n    }\n    let disableFormElements = false;\n    switch (state) {\n      case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.PresentationModeState.FULLSCREEN:\n        disableFormElements = true;\n        break;\n      case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.PresentationModeState.NORMAL:\n        break;\n      default:\n        return;\n    }\n    for (const section of this.div.childNodes) {\n      if (section.hasAttribute(\"data-internal-link\")) {\n        continue;\n      }\n      section.inert = disableFormElements;\n    }\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 1621:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   PDFViewerApplication: () => (/* binding */ PDFViewerApplication)\n/* harmony export */ });\n/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256);\n/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2603);\n/* harmony import */ var _app_options_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9840);\n/* harmony import */ var _event_utils_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5656);\n/* harmony import */ var web_external_services__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(6750);\n/* harmony import */ var _pdf_link_service_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(787);\n/* harmony import */ var web_alt_text_manager__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(259);\n/* harmony import */ var web_annotation_editor_params__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(226);\n/* harmony import */ var _caret_browsing_js__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(3973);\n/* harmony import */ var web_download_manager__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(1544);\n/* harmony import */ var _overlay_manager_js__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(6174);\n/* harmony import */ var _password_prompt_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(2690);\n/* harmony import */ var web_pdf_attachment_viewer__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(9251);\n/* harmony import */ var web_pdf_cursor_tools__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(5993);\n/* harmony import */ var web_pdf_document_properties__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(164);\n/* harmony import */ var web_pdf_find_bar__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(2226);\n/* harmony import */ var _pdf_find_controller_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(9814);\n/* harmony import */ var _pdf_history_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(8543);\n/* harmony import */ var web_pdf_layer_viewer__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(4275);\n/* harmony import */ var web_pdf_outline_viewer__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(5514);\n/* harmony import */ var web_pdf_presentation_mode__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(8917);\n/* harmony import */ var web_print_service__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(1144);\n/* harmony import */ var _pdf_rendering_queue_js__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(6615);\n/* harmony import */ var _pdf_scripting_manager_js__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(5942);\n/* harmony import */ var web_pdf_sidebar__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(2275);\n/* harmony import */ var web_pdf_thumbnail_viewer__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(8280);\n/* harmony import */ var _pdf_viewer_js__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(6285);\n/* harmony import */ var web_secondary_toolbar__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(1900);\n/* harmony import */ var web_toolbar__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(6297);\n/* harmony import */ var _view_history_js__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(9226);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__, web_external_services__WEBPACK_IMPORTED_MODULE_4__, web_alt_text_manager__WEBPACK_IMPORTED_MODULE_6__, web_annotation_editor_params__WEBPACK_IMPORTED_MODULE_7__, web_download_manager__WEBPACK_IMPORTED_MODULE_8__, _password_prompt_js__WEBPACK_IMPORTED_MODULE_9__, web_pdf_attachment_viewer__WEBPACK_IMPORTED_MODULE_10__, web_pdf_cursor_tools__WEBPACK_IMPORTED_MODULE_11__, web_pdf_document_properties__WEBPACK_IMPORTED_MODULE_12__, web_pdf_presentation_mode__WEBPACK_IMPORTED_MODULE_18__, web_print_service__WEBPACK_IMPORTED_MODULE_19__, _pdf_rendering_queue_js__WEBPACK_IMPORTED_MODULE_20__, _pdf_scripting_manager_js__WEBPACK_IMPORTED_MODULE_21__, web_pdf_thumbnail_viewer__WEBPACK_IMPORTED_MODULE_23__, _pdf_viewer_js__WEBPACK_IMPORTED_MODULE_24__, web_secondary_toolbar__WEBPACK_IMPORTED_MODULE_25__, web_toolbar__WEBPACK_IMPORTED_MODULE_26__]);\n([pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__, web_external_services__WEBPACK_IMPORTED_MODULE_4__, web_alt_text_manager__WEBPACK_IMPORTED_MODULE_6__, web_annotation_editor_params__WEBPACK_IMPORTED_MODULE_7__, web_download_manager__WEBPACK_IMPORTED_MODULE_8__, _password_prompt_js__WEBPACK_IMPORTED_MODULE_9__, web_pdf_attachment_viewer__WEBPACK_IMPORTED_MODULE_10__, web_pdf_cursor_tools__WEBPACK_IMPORTED_MODULE_11__, web_pdf_document_properties__WEBPACK_IMPORTED_MODULE_12__, web_pdf_presentation_mode__WEBPACK_IMPORTED_MODULE_18__, web_print_service__WEBPACK_IMPORTED_MODULE_19__, _pdf_rendering_queue_js__WEBPACK_IMPORTED_MODULE_20__, _pdf_scripting_manager_js__WEBPACK_IMPORTED_MODULE_21__, web_pdf_thumbnail_viewer__WEBPACK_IMPORTED_MODULE_23__, _pdf_viewer_js__WEBPACK_IMPORTED_MODULE_24__, web_secondary_toolbar__WEBPACK_IMPORTED_MODULE_25__, web_toolbar__WEBPACK_IMPORTED_MODULE_26__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__);\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst FORCE_PAGES_LOADED_TIMEOUT = 10000;\nconst WHEEL_ZOOM_DISABLED_TIMEOUT = 1000;\nconst ViewOnLoad = {\n  UNKNOWN: -1,\n  PREVIOUS: 0,\n  INITIAL: 1\n};\nconst PDFViewerApplication = {\n  initialBookmark: document.location.hash.substring(1),\n  _initializedCapability: {\n    ...Promise.withResolvers(),\n    settled: false\n  },\n  appConfig: null,\n  pdfDocument: null,\n  pdfLoadingTask: null,\n  printService: null,\n  pdfViewer: null,\n  pdfThumbnailViewer: null,\n  pdfRenderingQueue: null,\n  pdfPresentationMode: null,\n  pdfDocumentProperties: null,\n  pdfLinkService: null,\n  pdfHistory: null,\n  pdfSidebar: null,\n  pdfOutlineViewer: null,\n  pdfAttachmentViewer: null,\n  pdfLayerViewer: null,\n  pdfCursorTools: null,\n  pdfScriptingManager: null,\n  store: null,\n  downloadManager: null,\n  overlayManager: null,\n  preferences: null,\n  toolbar: null,\n  secondaryToolbar: null,\n  eventBus: null,\n  l10n: null,\n  annotationEditorParams: null,\n  isInitialViewSet: false,\n  downloadComplete: false,\n  isViewerEmbedded: window.parent !== window,\n  url: \"\",\n  baseUrl: \"\",\n  _downloadUrl: \"\",\n  _eventBusAbortController: null,\n  _windowAbortController: null,\n  documentInfo: null,\n  metadata: null,\n  _contentDispositionFilename: null,\n  _contentLength: null,\n  _saveInProgress: false,\n  _wheelUnusedTicks: 0,\n  _wheelUnusedFactor: 1,\n  _touchUnusedTicks: 0,\n  _touchUnusedFactor: 1,\n  _PDFBug: null,\n  _hasAnnotationEditors: false,\n  _title: document.title,\n  _printAnnotationStoragePromise: null,\n  _touchInfo: null,\n  _isCtrlKeyDown: false,\n  _nimbusDataPromise: null,\n  _caretBrowsing: null,\n  _isScrolling: false,\n  async initialize(appConfig) {\n    let l10nPromise;\n    this.appConfig = appConfig;\n    try {\n      await this.preferences.initializedPromise;\n    } catch (ex) {\n      console.error(`initialize: \"${ex.message}\".`);\n    }\n    if (_app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"pdfBugEnabled\")) {\n      await this._parseHashParams();\n    }\n    let mode;\n    switch (_app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"viewerCssTheme\")) {\n      case 1:\n        mode = \"is-light\";\n        break;\n      case 2:\n        mode = \"is-dark\";\n        break;\n    }\n    if (mode) {\n      document.documentElement.classList.add(mode);\n    }\n    l10nPromise = this.externalServices.createL10n();\n    this.l10n = await l10nPromise;\n    document.getElementsByTagName(\"html\")[0].dir = this.l10n.getDirection();\n    this.l10n.translate(appConfig.appContainer || document.documentElement);\n    if (this.isViewerEmbedded && _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"externalLinkTarget\") === _pdf_link_service_js__WEBPACK_IMPORTED_MODULE_5__.LinkTarget.NONE) {\n      _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.set(\"externalLinkTarget\", _pdf_link_service_js__WEBPACK_IMPORTED_MODULE_5__.LinkTarget.TOP);\n    }\n    await this._initializeViewerComponents();\n    this.bindEvents();\n    this.bindWindowEvents();\n    this._initializedCapability.settled = true;\n    this._initializedCapability.resolve();\n  },\n  async _parseHashParams() {\n    const hash = document.location.hash.substring(1);\n    if (!hash) {\n      return;\n    }\n    const {\n        mainContainer,\n        viewerContainer\n      } = this.appConfig,\n      params = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.parseQueryString)(hash);\n    if (params.get(\"disableworker\") === \"true\") {\n      try {\n        await loadFakeWorker();\n      } catch (ex) {\n        console.error(`_parseHashParams: \"${ex.message}\".`);\n      }\n    }\n    if (params.has(\"disablerange\")) {\n      _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.set(\"disableRange\", params.get(\"disablerange\") === \"true\");\n    }\n    if (params.has(\"disablestream\")) {\n      _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.set(\"disableStream\", params.get(\"disablestream\") === \"true\");\n    }\n    if (params.has(\"disableautofetch\")) {\n      _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.set(\"disableAutoFetch\", params.get(\"disableautofetch\") === \"true\");\n    }\n    if (params.has(\"disablefontface\")) {\n      _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.set(\"disableFontFace\", params.get(\"disablefontface\") === \"true\");\n    }\n    if (params.has(\"disablehistory\")) {\n      _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.set(\"disableHistory\", params.get(\"disablehistory\") === \"true\");\n    }\n    if (params.has(\"verbosity\")) {\n      _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.set(\"verbosity\", params.get(\"verbosity\") | 0);\n    }\n    if (params.has(\"textlayer\")) {\n      switch (params.get(\"textlayer\")) {\n        case \"off\":\n          _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.set(\"textLayerMode\", _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.TextLayerMode.DISABLE);\n          break;\n        case \"visible\":\n        case \"shadow\":\n        case \"hover\":\n          viewerContainer.classList.add(`textLayer-${params.get(\"textlayer\")}`);\n          try {\n            await loadPDFBug(this);\n            this._PDFBug.loadCSS();\n          } catch (ex) {\n            console.error(`_parseHashParams: \"${ex.message}\".`);\n          }\n          break;\n      }\n    }\n    if (params.has(\"pdfbug\")) {\n      _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.set(\"pdfBug\", true);\n      _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.set(\"fontExtraProperties\", true);\n      const enabled = params.get(\"pdfbug\").split(\",\");\n      try {\n        await loadPDFBug(this);\n        this._PDFBug.init(mainContainer, enabled);\n      } catch (ex) {\n        console.error(`_parseHashParams: \"${ex.message}\".`);\n      }\n    }\n    if (params.has(\"locale\")) {\n      _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.set(\"locale\", params.get(\"locale\"));\n    }\n  },\n  async _initializeViewerComponents() {\n    const {\n      appConfig,\n      externalServices,\n      l10n\n    } = this;\n    const eventBus = _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"isInAutomation\") ? new _event_utils_js__WEBPACK_IMPORTED_MODULE_3__.AutomationEventBus() : new _event_utils_js__WEBPACK_IMPORTED_MODULE_3__.EventBus();\n    this.eventBus = eventBus;\n    this.overlayManager = new _overlay_manager_js__WEBPACK_IMPORTED_MODULE_27__.OverlayManager();\n    const pdfRenderingQueue = new _pdf_rendering_queue_js__WEBPACK_IMPORTED_MODULE_20__.PDFRenderingQueue();\n    pdfRenderingQueue.onIdle = this._cleanup.bind(this);\n    this.pdfRenderingQueue = pdfRenderingQueue;\n    const pdfLinkService = new _pdf_link_service_js__WEBPACK_IMPORTED_MODULE_5__.PDFLinkService({\n      eventBus,\n      externalLinkTarget: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"externalLinkTarget\"),\n      externalLinkRel: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"externalLinkRel\"),\n      ignoreDestinationZoom: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"ignoreDestinationZoom\")\n    });\n    this.pdfLinkService = pdfLinkService;\n    const downloadManager = this.downloadManager = new web_download_manager__WEBPACK_IMPORTED_MODULE_8__.DownloadManager();\n    const findController = new _pdf_find_controller_js__WEBPACK_IMPORTED_MODULE_14__.PDFFindController({\n      linkService: pdfLinkService,\n      eventBus,\n      updateMatchesCountOnProgress: true\n    });\n    this.findController = findController;\n    const pdfScriptingManager = new _pdf_scripting_manager_js__WEBPACK_IMPORTED_MODULE_21__.PDFScriptingManager({\n      eventBus,\n      externalServices,\n      docProperties: this._scriptingDocProperties.bind(this)\n    });\n    this.pdfScriptingManager = pdfScriptingManager;\n    const container = appConfig.mainContainer,\n      viewer = appConfig.viewerContainer;\n    const annotationEditorMode = _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"annotationEditorMode\");\n    const pageColors = _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"forcePageColors\") || window.matchMedia(\"(forced-colors: active)\").matches ? {\n      background: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"pageColorsBackground\"),\n      foreground: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"pageColorsForeground\")\n    } : null;\n    const altTextManager = appConfig.altTextDialog ? new web_alt_text_manager__WEBPACK_IMPORTED_MODULE_6__.AltTextManager(appConfig.altTextDialog, container, this.overlayManager, eventBus) : null;\n    const pdfViewer = new _pdf_viewer_js__WEBPACK_IMPORTED_MODULE_24__.PDFViewer({\n      container,\n      viewer,\n      eventBus,\n      renderingQueue: pdfRenderingQueue,\n      linkService: pdfLinkService,\n      downloadManager,\n      altTextManager,\n      findController,\n      scriptingManager: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"enableScripting\") && pdfScriptingManager,\n      l10n,\n      textLayerMode: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"textLayerMode\"),\n      annotationMode: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"annotationMode\"),\n      annotationEditorMode,\n      annotationEditorHighlightColors: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"highlightEditorColors\"),\n      enableHighlightFloatingButton: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"enableHighlightFloatingButton\"),\n      imageResourcesPath: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"imageResourcesPath\"),\n      enablePrintAutoRotate: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"enablePrintAutoRotate\"),\n      maxCanvasPixels: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"maxCanvasPixels\"),\n      enablePermissions: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"enablePermissions\"),\n      pageColors,\n      mlManager: this.mlManager\n    });\n    this.pdfViewer = pdfViewer;\n    pdfRenderingQueue.setViewer(pdfViewer);\n    pdfLinkService.setViewer(pdfViewer);\n    pdfScriptingManager.setViewer(pdfViewer);\n    if (appConfig.sidebar?.thumbnailView) {\n      this.pdfThumbnailViewer = new web_pdf_thumbnail_viewer__WEBPACK_IMPORTED_MODULE_23__.PDFThumbnailViewer({\n        container: appConfig.sidebar.thumbnailView,\n        eventBus,\n        renderingQueue: pdfRenderingQueue,\n        linkService: pdfLinkService,\n        pageColors\n      });\n      pdfRenderingQueue.setThumbnailViewer(this.pdfThumbnailViewer);\n    }\n    if (!this.isViewerEmbedded && !_app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"disableHistory\")) {\n      this.pdfHistory = new _pdf_history_js__WEBPACK_IMPORTED_MODULE_15__.PDFHistory({\n        linkService: pdfLinkService,\n        eventBus\n      });\n      pdfLinkService.setHistory(this.pdfHistory);\n    }\n    if (!this.supportsIntegratedFind && appConfig.findBar) {\n      this.findBar = new web_pdf_find_bar__WEBPACK_IMPORTED_MODULE_13__.PDFFindBar(appConfig.findBar, eventBus);\n    }\n    if (appConfig.annotationEditorParams) {\n      if (annotationEditorMode !== pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.AnnotationEditorType.DISABLE) {\n        if (_app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"enableStampEditor\")) {\n          appConfig.toolbar?.editorStampButton?.classList.remove(\"hidden\");\n        }\n        const editorHighlightButton = appConfig.toolbar?.editorHighlightButton;\n        if (editorHighlightButton && _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"enableHighlightEditor\")) {\n          editorHighlightButton.hidden = false;\n        }\n        this.annotationEditorParams = new web_annotation_editor_params__WEBPACK_IMPORTED_MODULE_7__.AnnotationEditorParams(appConfig.annotationEditorParams, eventBus);\n      } else {\n        for (const id of [\"editorModeButtons\", \"editorModeSeparator\"]) {\n          document.getElementById(id)?.classList.add(\"hidden\");\n        }\n      }\n    }\n    if (appConfig.documentProperties) {\n      this.pdfDocumentProperties = new web_pdf_document_properties__WEBPACK_IMPORTED_MODULE_12__.PDFDocumentProperties(appConfig.documentProperties, this.overlayManager, eventBus, l10n, () => this._docFilename);\n    }\n    if (appConfig.secondaryToolbar?.cursorHandToolButton) {\n      this.pdfCursorTools = new web_pdf_cursor_tools__WEBPACK_IMPORTED_MODULE_11__.PDFCursorTools({\n        container,\n        eventBus,\n        cursorToolOnLoad: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"cursorToolOnLoad\")\n      });\n    }\n    if (appConfig.toolbar) {\n      this.toolbar = new web_toolbar__WEBPACK_IMPORTED_MODULE_26__.Toolbar(appConfig.toolbar, eventBus);\n    }\n    if (appConfig.secondaryToolbar) {\n      this.secondaryToolbar = new web_secondary_toolbar__WEBPACK_IMPORTED_MODULE_25__.SecondaryToolbar(appConfig.secondaryToolbar, eventBus);\n    }\n    if (this.supportsFullscreen && appConfig.secondaryToolbar?.presentationModeButton) {\n      this.pdfPresentationMode = new web_pdf_presentation_mode__WEBPACK_IMPORTED_MODULE_18__.PDFPresentationMode({\n        container,\n        pdfViewer,\n        eventBus\n      });\n    }\n    if (appConfig.passwordOverlay) {\n      this.passwordPrompt = new _password_prompt_js__WEBPACK_IMPORTED_MODULE_9__.PasswordPrompt(appConfig.passwordOverlay, this.overlayManager, this.isViewerEmbedded);\n    }\n    if (appConfig.sidebar?.outlineView) {\n      this.pdfOutlineViewer = new web_pdf_outline_viewer__WEBPACK_IMPORTED_MODULE_17__.PDFOutlineViewer({\n        container: appConfig.sidebar.outlineView,\n        eventBus,\n        l10n,\n        linkService: pdfLinkService,\n        downloadManager\n      });\n    }\n    if (appConfig.sidebar?.attachmentsView) {\n      this.pdfAttachmentViewer = new web_pdf_attachment_viewer__WEBPACK_IMPORTED_MODULE_10__.PDFAttachmentViewer({\n        container: appConfig.sidebar.attachmentsView,\n        eventBus,\n        l10n,\n        downloadManager\n      });\n    }\n    if (appConfig.sidebar?.layersView) {\n      this.pdfLayerViewer = new web_pdf_layer_viewer__WEBPACK_IMPORTED_MODULE_16__.PDFLayerViewer({\n        container: appConfig.sidebar.layersView,\n        eventBus,\n        l10n\n      });\n    }\n    if (appConfig.sidebar) {\n      this.pdfSidebar = new web_pdf_sidebar__WEBPACK_IMPORTED_MODULE_22__.PDFSidebar({\n        elements: appConfig.sidebar,\n        eventBus,\n        l10n\n      });\n      this.pdfSidebar.onToggled = this.forceRendering.bind(this);\n      this.pdfSidebar.onUpdateThumbnails = () => {\n        for (const pageView of pdfViewer.getCachedPageViews()) {\n          if (pageView.renderingState === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.FINISHED) {\n            this.pdfThumbnailViewer.getThumbnail(pageView.id - 1)?.setImage(pageView);\n          }\n        }\n        this.pdfThumbnailViewer.scrollThumbnailIntoView(pdfViewer.currentPageNumber);\n      };\n    }\n  },\n  async run(config) {\n    this.preferences = new web_external_services__WEBPACK_IMPORTED_MODULE_4__.Preferences();\n    await this.initialize(config);\n    const {\n      appConfig,\n      eventBus\n    } = this;\n    let file;\n    const queryString = document.location.search.substring(1);\n    const params = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.parseQueryString)(queryString);\n    file = params.get(\"file\") ?? _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"defaultUrl\");\n    validateFileURL(file);\n    const fileInput = this._openFileInput = document.createElement(\"input\");\n    fileInput.id = \"fileInput\";\n    fileInput.hidden = true;\n    fileInput.type = \"file\";\n    fileInput.value = null;\n    document.body.append(fileInput);\n    fileInput.addEventListener(\"change\", function (evt) {\n      const {\n        files\n      } = evt.target;\n      if (!files || files.length === 0) {\n        return;\n      }\n      eventBus.dispatch(\"fileinputchange\", {\n        source: this,\n        fileInput: evt.target\n      });\n    });\n    appConfig.mainContainer.addEventListener(\"dragover\", function (evt) {\n      evt.preventDefault();\n      evt.dataTransfer.dropEffect = evt.dataTransfer.effectAllowed === \"copy\" ? \"copy\" : \"move\";\n    });\n    appConfig.mainContainer.addEventListener(\"drop\", function (evt) {\n      evt.preventDefault();\n      const {\n        files\n      } = evt.dataTransfer;\n      if (!files || files.length === 0) {\n        return;\n      }\n      eventBus.dispatch(\"fileinputchange\", {\n        source: this,\n        fileInput: evt.dataTransfer\n      });\n    });\n    if (!_app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"supportsDocumentFonts\")) {\n      _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.set(\"disableFontFace\", true);\n      this.l10n.get(\"pdfjs-web-fonts-disabled\").then(msg => {\n        console.warn(msg);\n      });\n    }\n    if (!this.supportsPrinting) {\n      appConfig.toolbar?.print?.classList.add(\"hidden\");\n      appConfig.secondaryToolbar?.printButton.classList.add(\"hidden\");\n    }\n    if (!this.supportsFullscreen) {\n      appConfig.secondaryToolbar?.presentationModeButton.classList.add(\"hidden\");\n    }\n    if (this.supportsIntegratedFind) {\n      appConfig.toolbar?.viewFind?.classList.add(\"hidden\");\n    }\n    if (file) {\n      this.open({\n        url: file\n      });\n    } else {\n      this._hideViewBookmark();\n    }\n  },\n  get externalServices() {\n    return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.shadow)(this, \"externalServices\", new web_external_services__WEBPACK_IMPORTED_MODULE_4__.ExternalServices());\n  },\n  get mlManager() {\n    return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.shadow)(this, \"mlManager\", _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"enableML\") === true ? new web_external_services__WEBPACK_IMPORTED_MODULE_4__.MLManager() : null);\n  },\n  get initialized() {\n    return this._initializedCapability.settled;\n  },\n  get initializedPromise() {\n    return this._initializedCapability.promise;\n  },\n  zoomIn(steps, scaleFactor) {\n    if (this.pdfViewer.isInPresentationMode) {\n      return;\n    }\n    this.pdfViewer.increaseScale({\n      drawingDelay: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"defaultZoomDelay\"),\n      steps,\n      scaleFactor\n    });\n  },\n  zoomOut(steps, scaleFactor) {\n    if (this.pdfViewer.isInPresentationMode) {\n      return;\n    }\n    this.pdfViewer.decreaseScale({\n      drawingDelay: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"defaultZoomDelay\"),\n      steps,\n      scaleFactor\n    });\n  },\n  zoomReset() {\n    if (this.pdfViewer.isInPresentationMode) {\n      return;\n    }\n    this.pdfViewer.currentScaleValue = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.DEFAULT_SCALE_VALUE;\n  },\n  get pagesCount() {\n    return this.pdfDocument ? this.pdfDocument.numPages : 0;\n  },\n  get page() {\n    return this.pdfViewer.currentPageNumber;\n  },\n  set page(val) {\n    this.pdfViewer.currentPageNumber = val;\n  },\n  get supportsPrinting() {\n    return web_print_service__WEBPACK_IMPORTED_MODULE_19__.PDFPrintServiceFactory.supportsPrinting;\n  },\n  get supportsFullscreen() {\n    return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.shadow)(this, \"supportsFullscreen\", document.fullscreenEnabled);\n  },\n  get supportsPinchToZoom() {\n    return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.shadow)(this, \"supportsPinchToZoom\", _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"supportsPinchToZoom\"));\n  },\n  get supportsIntegratedFind() {\n    return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.shadow)(this, \"supportsIntegratedFind\", _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"supportsIntegratedFind\"));\n  },\n  get loadingBar() {\n    const barElement = document.getElementById(\"loadingBar\");\n    const bar = barElement ? new _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ProgressBar(barElement) : null;\n    return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.shadow)(this, \"loadingBar\", bar);\n  },\n  get supportsMouseWheelZoomCtrlKey() {\n    return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.shadow)(this, \"supportsMouseWheelZoomCtrlKey\", _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"supportsMouseWheelZoomCtrlKey\"));\n  },\n  get supportsMouseWheelZoomMetaKey() {\n    return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.shadow)(this, \"supportsMouseWheelZoomMetaKey\", _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"supportsMouseWheelZoomMetaKey\"));\n  },\n  get supportsCaretBrowsingMode() {\n    return _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"supportsCaretBrowsingMode\");\n  },\n  moveCaret(isUp, select) {\n    this._caretBrowsing ||= new _caret_browsing_js__WEBPACK_IMPORTED_MODULE_28__.CaretBrowsingMode(this.appConfig.mainContainer, this.appConfig.viewerContainer, this.appConfig.toolbar?.container);\n    this._caretBrowsing.moveCaret(isUp, select);\n  },\n  setTitleUsingUrl(url = \"\", downloadUrl = null) {\n    this.url = url;\n    this.baseUrl = url.split(\"#\", 1)[0];\n    if (downloadUrl) {\n      this._downloadUrl = downloadUrl === url ? this.baseUrl : downloadUrl.split(\"#\", 1)[0];\n    }\n    if ((0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.isDataScheme)(url)) {\n      this._hideViewBookmark();\n    }\n    let title = (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.getPdfFilenameFromUrl)(url, \"\");\n    if (!title) {\n      try {\n        title = decodeURIComponent((0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.getFilenameFromUrl)(url)) || url;\n      } catch {\n        title = url;\n      }\n    }\n    this.setTitle(title);\n  },\n  setTitle(title = this._title) {\n    this._title = title;\n    if (this.isViewerEmbedded) {\n      return;\n    }\n    const editorIndicator = this._hasAnnotationEditors && !this.pdfRenderingQueue.printing;\n    document.title = `${editorIndicator ? \"* \" : \"\"}${title}`;\n  },\n  get _docFilename() {\n    return this._contentDispositionFilename || (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.getPdfFilenameFromUrl)(this.url);\n  },\n  _hideViewBookmark() {\n    const {\n      secondaryToolbar\n    } = this.appConfig;\n    secondaryToolbar?.viewBookmarkButton.classList.add(\"hidden\");\n    if (secondaryToolbar?.presentationModeButton.classList.contains(\"hidden\")) {\n      document.getElementById(\"viewBookmarkSeparator\")?.classList.add(\"hidden\");\n    }\n  },\n  async close() {\n    this._unblockDocumentLoadEvent();\n    this._hideViewBookmark();\n    if (!this.pdfLoadingTask) {\n      return;\n    }\n    if (this.pdfDocument?.annotationStorage.size > 0 && this._annotationStorageModified) {\n      try {\n        await this.save();\n      } catch {}\n    }\n    const promises = [];\n    promises.push(this.pdfLoadingTask.destroy());\n    this.pdfLoadingTask = null;\n    if (this.pdfDocument) {\n      this.pdfDocument = null;\n      this.pdfThumbnailViewer?.setDocument(null);\n      this.pdfViewer.setDocument(null);\n      this.pdfLinkService.setDocument(null);\n      this.pdfDocumentProperties?.setDocument(null);\n    }\n    this.pdfLinkService.externalLinkEnabled = true;\n    this.store = null;\n    this.isInitialViewSet = false;\n    this.downloadComplete = false;\n    this.url = \"\";\n    this.baseUrl = \"\";\n    this._downloadUrl = \"\";\n    this.documentInfo = null;\n    this.metadata = null;\n    this._contentDispositionFilename = null;\n    this._contentLength = null;\n    this._saveInProgress = false;\n    this._hasAnnotationEditors = false;\n    promises.push(this.pdfScriptingManager.destroyPromise, this.passwordPrompt.close());\n    this.setTitle();\n    this.pdfSidebar?.reset();\n    this.pdfOutlineViewer?.reset();\n    this.pdfAttachmentViewer?.reset();\n    this.pdfLayerViewer?.reset();\n    this.pdfHistory?.reset();\n    this.findBar?.reset();\n    this.toolbar?.reset();\n    this.secondaryToolbar?.reset();\n    this._PDFBug?.cleanup();\n    await Promise.all(promises);\n  },\n  async open(args) {\n    if (this.pdfLoadingTask) {\n      await this.close();\n    }\n    const workerParams = _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.getAll(_app_options_js__WEBPACK_IMPORTED_MODULE_2__.OptionKind.WORKER);\n    Object.assign(pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.GlobalWorkerOptions, workerParams);\n    if (args.url) {\n      this.setTitleUsingUrl(args.originalUrl || args.url, args.url);\n    }\n    const apiParams = _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.getAll(_app_options_js__WEBPACK_IMPORTED_MODULE_2__.OptionKind.API);\n    const loadingTask = (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.getDocument)({\n      ...apiParams,\n      ...args\n    });\n    this.pdfLoadingTask = loadingTask;\n    loadingTask.onPassword = (updateCallback, reason) => {\n      if (this.isViewerEmbedded) {\n        this._unblockDocumentLoadEvent();\n      }\n      this.pdfLinkService.externalLinkEnabled = false;\n      this.passwordPrompt.setUpdateCallback(updateCallback, reason);\n      this.passwordPrompt.open();\n    };\n    loadingTask.onProgress = ({\n      loaded,\n      total\n    }) => {\n      this.progress(loaded / total);\n    };\n    return loadingTask.promise.then(pdfDocument => {\n      this.load(pdfDocument);\n    }, reason => {\n      if (loadingTask !== this.pdfLoadingTask) {\n        return undefined;\n      }\n      let key = \"pdfjs-loading-error\";\n      if (reason instanceof pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.InvalidPDFException) {\n        key = \"pdfjs-invalid-file-error\";\n      } else if (reason instanceof pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.MissingPDFException) {\n        key = \"pdfjs-missing-file-error\";\n      } else if (reason instanceof pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.UnexpectedResponseException) {\n        key = \"pdfjs-unexpected-response-error\";\n      }\n      return this._documentError(key, {\n        message: reason.message\n      }).then(() => {\n        throw reason;\n      });\n    });\n  },\n  _ensureDownloadComplete() {\n    if (this.pdfDocument && this.downloadComplete) {\n      return;\n    }\n    throw new Error(\"PDF document not downloaded.\");\n  },\n  async download(options = {}) {\n    const url = this._downloadUrl,\n      filename = this._docFilename;\n    try {\n      this._ensureDownloadComplete();\n      const data = await this.pdfDocument.getData();\n      const blob = new Blob([data], {\n        type: \"application/pdf\"\n      });\n      await this.downloadManager.download(blob, url, filename, options);\n    } catch {\n      await this.downloadManager.downloadUrl(url, filename, options);\n    }\n  },\n  async save(options = {}) {\n    if (this._saveInProgress) {\n      return;\n    }\n    this._saveInProgress = true;\n    await this.pdfScriptingManager.dispatchWillSave();\n    const url = this._downloadUrl,\n      filename = this._docFilename;\n    try {\n      this._ensureDownloadComplete();\n      const data = await this.pdfDocument.saveDocument();\n      const blob = new Blob([data], {\n        type: \"application/pdf\"\n      });\n      await this.downloadManager.download(blob, url, filename, options);\n    } catch (reason) {\n      console.error(`Error when saving the document: ${reason.message}`);\n      await this.download(options);\n    } finally {\n      await this.pdfScriptingManager.dispatchDidSave();\n      this._saveInProgress = false;\n    }\n    if (this._hasAnnotationEditors) {\n      this.externalServices.reportTelemetry({\n        type: \"editing\",\n        data: {\n          type: \"save\",\n          stats: this.pdfDocument?.annotationStorage.editorStats\n        }\n      });\n    }\n  },\n  downloadOrSave(options = {}) {\n    if (this.pdfDocument?.annotationStorage.size > 0) {\n      this.save(options);\n    } else {\n      this.download(options);\n    }\n  },\n  async _documentError(key, moreInfo = null) {\n    this._unblockDocumentLoadEvent();\n    const message = await this._otherError(key || \"pdfjs-loading-error\", moreInfo);\n    this.eventBus.dispatch(\"documenterror\", {\n      source: this,\n      message,\n      reason: moreInfo?.message ?? null\n    });\n  },\n  async _otherError(key, moreInfo = null) {\n    const message = await this.l10n.get(key);\n    const moreInfoText = [`PDF.js v${pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.version || \"?\"} (build: ${pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.build || \"?\"})`];\n    if (moreInfo) {\n      moreInfoText.push(`Message: ${moreInfo.message}`);\n      if (moreInfo.stack) {\n        moreInfoText.push(`Stack: ${moreInfo.stack}`);\n      } else {\n        if (moreInfo.filename) {\n          moreInfoText.push(`File: ${moreInfo.filename}`);\n        }\n        if (moreInfo.lineNumber) {\n          moreInfoText.push(`Line: ${moreInfo.lineNumber}`);\n        }\n      }\n    }\n    console.error(`${message}\\n\\n${moreInfoText.join(\"\\n\")}`);\n    return message;\n  },\n  progress(level) {\n    if (!this.loadingBar || this.downloadComplete) {\n      return;\n    }\n    const percent = Math.round(level * 100);\n    if (percent <= this.loadingBar.percent) {\n      return;\n    }\n    this.loadingBar.percent = percent;\n    if (this.pdfDocument?.loadingParams.disableAutoFetch ?? _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"disableAutoFetch\")) {\n      this.loadingBar.setDisableAutoFetch();\n    }\n  },\n  load(pdfDocument) {\n    this.pdfDocument = pdfDocument;\n    pdfDocument.getDownloadInfo().then(({\n      length\n    }) => {\n      this._contentLength = length;\n      this.downloadComplete = true;\n      this.loadingBar?.hide();\n      firstPagePromise.then(() => {\n        this.eventBus.dispatch(\"documentloaded\", {\n          source: this\n        });\n      });\n    });\n    const pageLayoutPromise = pdfDocument.getPageLayout().catch(() => {});\n    const pageModePromise = pdfDocument.getPageMode().catch(() => {});\n    const openActionPromise = pdfDocument.getOpenAction().catch(() => {});\n    this.toolbar?.setPagesCount(pdfDocument.numPages, false);\n    this.secondaryToolbar?.setPagesCount(pdfDocument.numPages);\n    this.pdfLinkService.setDocument(pdfDocument);\n    this.pdfDocumentProperties?.setDocument(pdfDocument);\n    const pdfViewer = this.pdfViewer;\n    pdfViewer.setDocument(pdfDocument);\n    const {\n      firstPagePromise,\n      onePageRendered,\n      pagesPromise\n    } = pdfViewer;\n    this.pdfThumbnailViewer?.setDocument(pdfDocument);\n    const storedPromise = (this.store = new _view_history_js__WEBPACK_IMPORTED_MODULE_29__.ViewHistory(pdfDocument.fingerprints[0])).getMultiple({\n      page: null,\n      zoom: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.DEFAULT_SCALE_VALUE,\n      scrollLeft: \"0\",\n      scrollTop: \"0\",\n      rotation: null,\n      sidebarView: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.UNKNOWN,\n      scrollMode: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.UNKNOWN,\n      spreadMode: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SpreadMode.UNKNOWN\n    }).catch(() => {});\n    firstPagePromise.then(pdfPage => {\n      this.loadingBar?.setWidth(this.appConfig.viewerContainer);\n      this._initializeAnnotationStorageCallbacks(pdfDocument);\n      Promise.all([_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.animationStarted, storedPromise, pageLayoutPromise, pageModePromise, openActionPromise]).then(async ([timeStamp, stored, pageLayout, pageMode, openAction]) => {\n        const viewOnLoad = _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"viewOnLoad\");\n        this._initializePdfHistory({\n          fingerprint: pdfDocument.fingerprints[0],\n          viewOnLoad,\n          initialDest: openAction?.dest\n        });\n        const initialBookmark = this.initialBookmark;\n        const zoom = _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"defaultZoomValue\");\n        let hash = zoom ? `zoom=${zoom}` : null;\n        let rotation = null;\n        let sidebarView = _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"sidebarViewOnLoad\");\n        let scrollMode = _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"scrollModeOnLoad\");\n        let spreadMode = _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"spreadModeOnLoad\");\n        if (stored?.page && viewOnLoad !== ViewOnLoad.INITIAL) {\n          hash = `page=${stored.page}&zoom=${zoom || stored.zoom},` + `${stored.scrollLeft},${stored.scrollTop}`;\n          rotation = parseInt(stored.rotation, 10);\n          if (sidebarView === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.UNKNOWN) {\n            sidebarView = stored.sidebarView | 0;\n          }\n          if (scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.UNKNOWN) {\n            scrollMode = stored.scrollMode | 0;\n          }\n          if (spreadMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SpreadMode.UNKNOWN) {\n            spreadMode = stored.spreadMode | 0;\n          }\n        }\n        if (pageMode && sidebarView === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.UNKNOWN) {\n          sidebarView = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.apiPageModeToSidebarView)(pageMode);\n        }\n        if (pageLayout && scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.UNKNOWN && spreadMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SpreadMode.UNKNOWN) {\n          const modes = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.apiPageLayoutToViewerModes)(pageLayout);\n          spreadMode = modes.spreadMode;\n        }\n        this.setInitialView(hash, {\n          rotation,\n          sidebarView,\n          scrollMode,\n          spreadMode\n        });\n        this.eventBus.dispatch(\"documentinit\", {\n          source: this\n        });\n        if (!this.isViewerEmbedded) {\n          pdfViewer.focus();\n        }\n        await Promise.race([pagesPromise, new Promise(resolve => {\n          setTimeout(resolve, FORCE_PAGES_LOADED_TIMEOUT);\n        })]);\n        if (!initialBookmark && !hash) {\n          return;\n        }\n        if (pdfViewer.hasEqualPageSizes) {\n          return;\n        }\n        this.initialBookmark = initialBookmark;\n        pdfViewer.currentScaleValue = pdfViewer.currentScaleValue;\n        this.setInitialView(hash);\n      }).catch(() => {\n        this.setInitialView();\n      }).then(function () {\n        pdfViewer.update();\n      });\n    });\n    pagesPromise.then(() => {\n      this._unblockDocumentLoadEvent();\n      this._initializeAutoPrint(pdfDocument, openActionPromise);\n    }, reason => {\n      this._documentError(\"pdfjs-loading-error\", {\n        message: reason.message\n      });\n    });\n    onePageRendered.then(data => {\n      this.externalServices.reportTelemetry({\n        type: \"pageInfo\",\n        timestamp: data.timestamp\n      });\n      if (this.pdfOutlineViewer) {\n        pdfDocument.getOutline().then(outline => {\n          if (pdfDocument !== this.pdfDocument) {\n            return;\n          }\n          this.pdfOutlineViewer.render({\n            outline,\n            pdfDocument\n          });\n        });\n      }\n      if (this.pdfAttachmentViewer) {\n        pdfDocument.getAttachments().then(attachments => {\n          if (pdfDocument !== this.pdfDocument) {\n            return;\n          }\n          this.pdfAttachmentViewer.render({\n            attachments\n          });\n        });\n      }\n      if (this.pdfLayerViewer) {\n        pdfViewer.optionalContentConfigPromise.then(optionalContentConfig => {\n          if (pdfDocument !== this.pdfDocument) {\n            return;\n          }\n          this.pdfLayerViewer.render({\n            optionalContentConfig,\n            pdfDocument\n          });\n        });\n      }\n    });\n    this._initializePageLabels(pdfDocument);\n    this._initializeMetadata(pdfDocument);\n  },\n  async _scriptingDocProperties(pdfDocument) {\n    if (!this.documentInfo) {\n      await new Promise(resolve => {\n        this.eventBus._on(\"metadataloaded\", resolve, {\n          once: true\n        });\n      });\n      if (pdfDocument !== this.pdfDocument) {\n        return null;\n      }\n    }\n    if (!this._contentLength) {\n      await new Promise(resolve => {\n        this.eventBus._on(\"documentloaded\", resolve, {\n          once: true\n        });\n      });\n      if (pdfDocument !== this.pdfDocument) {\n        return null;\n      }\n    }\n    return {\n      ...this.documentInfo,\n      baseURL: this.baseUrl,\n      filesize: this._contentLength,\n      filename: this._docFilename,\n      metadata: this.metadata?.getRaw(),\n      authors: this.metadata?.get(\"dc:creator\"),\n      numPages: this.pagesCount,\n      URL: this.url\n    };\n  },\n  async _initializeAutoPrint(pdfDocument, openActionPromise) {\n    const [openAction, jsActions] = await Promise.all([openActionPromise, this.pdfViewer.enableScripting ? null : pdfDocument.getJSActions()]);\n    if (pdfDocument !== this.pdfDocument) {\n      return;\n    }\n    let triggerAutoPrint = openAction?.action === \"Print\";\n    if (jsActions) {\n      console.warn(\"Warning: JavaScript support is not enabled\");\n      for (const name in jsActions) {\n        if (triggerAutoPrint) {\n          break;\n        }\n        switch (name) {\n          case \"WillClose\":\n          case \"WillSave\":\n          case \"DidSave\":\n          case \"WillPrint\":\n          case \"DidPrint\":\n            continue;\n        }\n        triggerAutoPrint = jsActions[name].some(js => _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.AutoPrintRegExp.test(js));\n      }\n    }\n    if (triggerAutoPrint) {\n      this.triggerPrinting();\n    }\n  },\n  async _initializeMetadata(pdfDocument) {\n    const {\n      info,\n      metadata,\n      contentDispositionFilename,\n      contentLength\n    } = await pdfDocument.getMetadata();\n    if (pdfDocument !== this.pdfDocument) {\n      return;\n    }\n    this.documentInfo = info;\n    this.metadata = metadata;\n    this._contentDispositionFilename ??= contentDispositionFilename;\n    this._contentLength ??= contentLength;\n    console.log(`PDF ${pdfDocument.fingerprints[0]} [${info.PDFFormatVersion} ` + `${(info.Producer || \"-\").trim()} / ${(info.Creator || \"-\").trim()}] ` + `(PDF.js: ${pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.version || \"?\"} [${pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.build || \"?\"}])`);\n    let pdfTitle = info.Title;\n    const metadataTitle = metadata?.get(\"dc:title\");\n    if (metadataTitle) {\n      if (metadataTitle !== \"Untitled\" && !/[\\uFFF0-\\uFFFF]/g.test(metadataTitle)) {\n        pdfTitle = metadataTitle;\n      }\n    }\n    if (pdfTitle) {\n      this.setTitle(`${pdfTitle} - ${this._contentDispositionFilename || this._title}`);\n    } else if (this._contentDispositionFilename) {\n      this.setTitle(this._contentDispositionFilename);\n    }\n    if (info.IsXFAPresent && !info.IsAcroFormPresent && !pdfDocument.isPureXfa) {\n      if (pdfDocument.loadingParams.enableXfa) {\n        console.warn(\"Warning: XFA Foreground documents are not supported\");\n      } else {\n        console.warn(\"Warning: XFA support is not enabled\");\n      }\n    } else if ((info.IsAcroFormPresent || info.IsXFAPresent) && !this.pdfViewer.renderForms) {\n      console.warn(\"Warning: Interactive form support is not enabled\");\n    }\n    if (info.IsSignaturesPresent) {\n      console.warn(\"Warning: Digital signatures validation is not supported\");\n    }\n    this.eventBus.dispatch(\"metadataloaded\", {\n      source: this\n    });\n  },\n  async _initializePageLabels(pdfDocument) {\n    const labels = await pdfDocument.getPageLabels();\n    if (pdfDocument !== this.pdfDocument) {\n      return;\n    }\n    if (!labels || _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"disablePageLabels\")) {\n      return;\n    }\n    const numLabels = labels.length;\n    let standardLabels = 0,\n      emptyLabels = 0;\n    for (let i = 0; i < numLabels; i++) {\n      const label = labels[i];\n      if (label === (i + 1).toString()) {\n        standardLabels++;\n      } else if (label === \"\") {\n        emptyLabels++;\n      } else {\n        break;\n      }\n    }\n    if (standardLabels >= numLabels || emptyLabels >= numLabels) {\n      return;\n    }\n    const {\n      pdfViewer,\n      pdfThumbnailViewer,\n      toolbar\n    } = this;\n    pdfViewer.setPageLabels(labels);\n    pdfThumbnailViewer?.setPageLabels(labels);\n    toolbar?.setPagesCount(numLabels, true);\n    toolbar?.setPageNumber(pdfViewer.currentPageNumber, pdfViewer.currentPageLabel);\n  },\n  _initializePdfHistory({\n    fingerprint,\n    viewOnLoad,\n    initialDest = null\n  }) {\n    if (!this.pdfHistory) {\n      return;\n    }\n    this.pdfHistory.initialize({\n      fingerprint,\n      resetHistory: viewOnLoad === ViewOnLoad.INITIAL,\n      updateUrl: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"historyUpdateUrl\")\n    });\n    if (this.pdfHistory.initialBookmark) {\n      this.initialBookmark = this.pdfHistory.initialBookmark;\n      this.initialRotation = this.pdfHistory.initialRotation;\n    }\n    if (initialDest && !this.initialBookmark && viewOnLoad === ViewOnLoad.UNKNOWN) {\n      this.initialBookmark = JSON.stringify(initialDest);\n      this.pdfHistory.push({\n        explicitDest: initialDest,\n        pageNumber: null\n      });\n    }\n  },\n  _initializeAnnotationStorageCallbacks(pdfDocument) {\n    if (pdfDocument !== this.pdfDocument) {\n      return;\n    }\n    const {\n      annotationStorage\n    } = pdfDocument;\n    annotationStorage.onSetModified = () => {\n      window.addEventListener(\"beforeunload\", beforeUnload);\n      this._annotationStorageModified = true;\n    };\n    annotationStorage.onResetModified = () => {\n      window.removeEventListener(\"beforeunload\", beforeUnload);\n      delete this._annotationStorageModified;\n    };\n    annotationStorage.onAnnotationEditor = typeStr => {\n      this._hasAnnotationEditors = !!typeStr;\n      this.setTitle();\n    };\n  },\n  setInitialView(storedHash, {\n    rotation,\n    sidebarView,\n    scrollMode,\n    spreadMode\n  } = {}) {\n    const setRotation = angle => {\n      if ((0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.isValidRotation)(angle)) {\n        this.pdfViewer.pagesRotation = angle;\n      }\n    };\n    const setViewerModes = (scroll, spread) => {\n      if ((0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.isValidScrollMode)(scroll)) {\n        this.pdfViewer.scrollMode = scroll;\n      }\n      if ((0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.isValidSpreadMode)(spread)) {\n        this.pdfViewer.spreadMode = spread;\n      }\n    };\n    this.isInitialViewSet = true;\n    this.pdfSidebar?.setInitialView(sidebarView);\n    setViewerModes(scrollMode, spreadMode);\n    if (this.initialBookmark) {\n      setRotation(this.initialRotation);\n      delete this.initialRotation;\n      this.pdfLinkService.setHash(this.initialBookmark);\n      this.initialBookmark = null;\n    } else if (storedHash) {\n      setRotation(rotation);\n      this.pdfLinkService.setHash(storedHash);\n    }\n    this.toolbar?.setPageNumber(this.pdfViewer.currentPageNumber, this.pdfViewer.currentPageLabel);\n    this.secondaryToolbar?.setPageNumber(this.pdfViewer.currentPageNumber);\n    if (!this.pdfViewer.currentScaleValue) {\n      this.pdfViewer.currentScaleValue = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.DEFAULT_SCALE_VALUE;\n    }\n  },\n  _cleanup() {\n    if (!this.pdfDocument) {\n      return;\n    }\n    this.pdfViewer.cleanup();\n    this.pdfThumbnailViewer?.cleanup();\n    this.pdfDocument.cleanup(_app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"fontExtraProperties\"));\n  },\n  forceRendering() {\n    this.pdfRenderingQueue.printing = !!this.printService;\n    this.pdfRenderingQueue.isThumbnailViewEnabled = this.pdfSidebar?.visibleView === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.THUMBS;\n    this.pdfRenderingQueue.renderHighestPriority();\n  },\n  beforePrint() {\n    this._printAnnotationStoragePromise = this.pdfScriptingManager.dispatchWillPrint().catch(() => {}).then(() => this.pdfDocument?.annotationStorage.print);\n    if (this.printService) {\n      return;\n    }\n    if (!this.supportsPrinting) {\n      this._otherError(\"pdfjs-printing-not-supported\");\n      return;\n    }\n    if (!this.pdfViewer.pageViewsReady) {\n      this.l10n.get(\"pdfjs-printing-not-ready\").then(msg => {\n        window.alert(msg);\n      });\n      return;\n    }\n    this.printService = web_print_service__WEBPACK_IMPORTED_MODULE_19__.PDFPrintServiceFactory.createPrintService({\n      pdfDocument: this.pdfDocument,\n      pagesOverview: this.pdfViewer.getPagesOverview(),\n      printContainer: this.appConfig.printContainer,\n      printResolution: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"printResolution\"),\n      printAnnotationStoragePromise: this._printAnnotationStoragePromise\n    });\n    this.forceRendering();\n    this.setTitle();\n    this.printService.layout();\n    if (this._hasAnnotationEditors) {\n      this.externalServices.reportTelemetry({\n        type: \"editing\",\n        data: {\n          type: \"print\",\n          stats: this.pdfDocument?.annotationStorage.editorStats\n        }\n      });\n    }\n  },\n  afterPrint() {\n    if (this._printAnnotationStoragePromise) {\n      this._printAnnotationStoragePromise.then(() => {\n        this.pdfScriptingManager.dispatchDidPrint();\n      });\n      this._printAnnotationStoragePromise = null;\n    }\n    if (this.printService) {\n      this.printService.destroy();\n      this.printService = null;\n      this.pdfDocument?.annotationStorage.resetModified();\n    }\n    this.forceRendering();\n    this.setTitle();\n  },\n  rotatePages(delta) {\n    this.pdfViewer.pagesRotation += delta;\n  },\n  requestPresentationMode() {\n    this.pdfPresentationMode?.request();\n  },\n  triggerPrinting() {\n    if (!this.supportsPrinting) {\n      return;\n    }\n    window.print();\n  },\n  bindEvents() {\n    if (this._eventBusAbortController) {\n      return;\n    }\n    this._eventBusAbortController = new AbortController();\n    const {\n      eventBus,\n      _eventBusAbortController: {\n        signal\n      }\n    } = this;\n    eventBus._on(\"resize\", webViewerResize, {\n      signal\n    });\n    eventBus._on(\"hashchange\", webViewerHashchange, {\n      signal\n    });\n    eventBus._on(\"beforeprint\", this.beforePrint.bind(this), {\n      signal\n    });\n    eventBus._on(\"afterprint\", this.afterPrint.bind(this), {\n      signal\n    });\n    eventBus._on(\"pagerender\", webViewerPageRender, {\n      signal\n    });\n    eventBus._on(\"pagerendered\", webViewerPageRendered, {\n      signal\n    });\n    eventBus._on(\"updateviewarea\", webViewerUpdateViewarea, {\n      signal\n    });\n    eventBus._on(\"pagechanging\", webViewerPageChanging, {\n      signal\n    });\n    eventBus._on(\"scalechanging\", webViewerScaleChanging, {\n      signal\n    });\n    eventBus._on(\"rotationchanging\", webViewerRotationChanging, {\n      signal\n    });\n    eventBus._on(\"sidebarviewchanged\", webViewerSidebarViewChanged, {\n      signal\n    });\n    eventBus._on(\"pagemode\", webViewerPageMode, {\n      signal\n    });\n    eventBus._on(\"namedaction\", webViewerNamedAction, {\n      signal\n    });\n    eventBus._on(\"presentationmodechanged\", webViewerPresentationModeChanged, {\n      signal\n    });\n    eventBus._on(\"presentationmode\", webViewerPresentationMode, {\n      signal\n    });\n    eventBus._on(\"switchannotationeditormode\", webViewerSwitchAnnotationEditorMode, {\n      signal\n    });\n    eventBus._on(\"switchannotationeditorparams\", webViewerSwitchAnnotationEditorParams, {\n      signal\n    });\n    eventBus._on(\"print\", webViewerPrint, {\n      signal\n    });\n    eventBus._on(\"download\", webViewerDownload, {\n      signal\n    });\n    eventBus._on(\"firstpage\", webViewerFirstPage, {\n      signal\n    });\n    eventBus._on(\"lastpage\", webViewerLastPage, {\n      signal\n    });\n    eventBus._on(\"nextpage\", webViewerNextPage, {\n      signal\n    });\n    eventBus._on(\"previouspage\", webViewerPreviousPage, {\n      signal\n    });\n    eventBus._on(\"zoomin\", webViewerZoomIn, {\n      signal\n    });\n    eventBus._on(\"zoomout\", webViewerZoomOut, {\n      signal\n    });\n    eventBus._on(\"zoomreset\", webViewerZoomReset, {\n      signal\n    });\n    eventBus._on(\"pagenumberchanged\", webViewerPageNumberChanged, {\n      signal\n    });\n    eventBus._on(\"scalechanged\", webViewerScaleChanged, {\n      signal\n    });\n    eventBus._on(\"rotatecw\", webViewerRotateCw, {\n      signal\n    });\n    eventBus._on(\"rotateccw\", webViewerRotateCcw, {\n      signal\n    });\n    eventBus._on(\"optionalcontentconfig\", webViewerOptionalContentConfig, {\n      signal\n    });\n    eventBus._on(\"switchscrollmode\", webViewerSwitchScrollMode, {\n      signal\n    });\n    eventBus._on(\"scrollmodechanged\", webViewerScrollModeChanged, {\n      signal\n    });\n    eventBus._on(\"switchspreadmode\", webViewerSwitchSpreadMode, {\n      signal\n    });\n    eventBus._on(\"spreadmodechanged\", webViewerSpreadModeChanged, {\n      signal\n    });\n    eventBus._on(\"documentproperties\", webViewerDocumentProperties, {\n      signal\n    });\n    eventBus._on(\"findfromurlhash\", webViewerFindFromUrlHash, {\n      signal\n    });\n    eventBus._on(\"updatefindmatchescount\", webViewerUpdateFindMatchesCount, {\n      signal\n    });\n    eventBus._on(\"updatefindcontrolstate\", webViewerUpdateFindControlState, {\n      signal\n    });\n    if (_app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"pdfBug\")) {\n      eventBus._on(\"pagerendered\", reportPageStatsPDFBug, {\n        signal\n      });\n      eventBus._on(\"pagechanging\", reportPageStatsPDFBug, {\n        signal\n      });\n    }\n    eventBus._on(\"fileinputchange\", webViewerFileInputChange, {\n      signal\n    });\n    eventBus._on(\"openfile\", webViewerOpenFile, {\n      signal\n    });\n  },\n  bindWindowEvents() {\n    if (this._windowAbortController) {\n      return;\n    }\n    this._windowAbortController = new AbortController();\n    const {\n      eventBus,\n      appConfig: {\n        mainContainer\n      },\n      _windowAbortController: {\n        signal\n      }\n    } = this;\n    function addWindowResolutionChange(evt = null) {\n      if (evt) {\n        webViewerResolutionChange(evt);\n      }\n      const mediaQueryList = window.matchMedia(`(resolution: ${window.devicePixelRatio || 1}dppx)`);\n      mediaQueryList.addEventListener(\"change\", addWindowResolutionChange, {\n        once: true,\n        signal\n      });\n    }\n    addWindowResolutionChange();\n    window.addEventListener(\"visibilitychange\", webViewerVisibilityChange, {\n      signal\n    });\n    window.addEventListener(\"wheel\", webViewerWheel, {\n      passive: false,\n      signal\n    });\n    window.addEventListener(\"touchstart\", webViewerTouchStart, {\n      passive: false,\n      signal\n    });\n    window.addEventListener(\"touchmove\", webViewerTouchMove, {\n      passive: false,\n      signal\n    });\n    window.addEventListener(\"touchend\", webViewerTouchEnd, {\n      passive: false,\n      signal\n    });\n    window.addEventListener(\"click\", webViewerClick, {\n      signal\n    });\n    window.addEventListener(\"keydown\", webViewerKeyDown, {\n      signal\n    });\n    window.addEventListener(\"keyup\", webViewerKeyUp, {\n      signal\n    });\n    window.addEventListener(\"resize\", () => {\n      eventBus.dispatch(\"resize\", {\n        source: window\n      });\n    }, {\n      signal\n    });\n    window.addEventListener(\"hashchange\", () => {\n      eventBus.dispatch(\"hashchange\", {\n        source: window,\n        hash: document.location.hash.substring(1)\n      });\n    }, {\n      signal\n    });\n    window.addEventListener(\"beforeprint\", () => {\n      eventBus.dispatch(\"beforeprint\", {\n        source: window\n      });\n    }, {\n      signal\n    });\n    window.addEventListener(\"afterprint\", () => {\n      eventBus.dispatch(\"afterprint\", {\n        source: window\n      });\n    }, {\n      signal\n    });\n    window.addEventListener(\"updatefromsandbox\", event => {\n      eventBus.dispatch(\"updatefromsandbox\", {\n        source: window,\n        detail: event.detail\n      });\n    }, {\n      signal\n    });\n    if (!(\"onscrollend\" in document.documentElement)) {\n      return;\n    }\n    ({\n      scrollTop: this._lastScrollTop,\n      scrollLeft: this._lastScrollLeft\n    } = mainContainer);\n    const scrollend = () => {\n      ({\n        scrollTop: this._lastScrollTop,\n        scrollLeft: this._lastScrollLeft\n      } = mainContainer);\n      this._isScrolling = false;\n      mainContainer.addEventListener(\"scroll\", scroll, {\n        passive: true,\n        signal\n      });\n      mainContainer.removeEventListener(\"scrollend\", scrollend, {\n        signal\n      });\n      mainContainer.removeEventListener(\"blur\", scrollend, {\n        signal\n      });\n    };\n    const scroll = () => {\n      if (this._isCtrlKeyDown) {\n        return;\n      }\n      if (this._lastScrollTop === mainContainer.scrollTop && this._lastScrollLeft === mainContainer.scrollLeft) {\n        return;\n      }\n      mainContainer.removeEventListener(\"scroll\", scroll, {\n        passive: true,\n        signal\n      });\n      this._isScrolling = true;\n      mainContainer.addEventListener(\"scrollend\", scrollend, {\n        signal\n      });\n      mainContainer.addEventListener(\"blur\", scrollend, {\n        signal\n      });\n    };\n    mainContainer.addEventListener(\"scroll\", scroll, {\n      passive: true,\n      signal\n    });\n  },\n  unbindEvents() {\n    this._eventBusAbortController?.abort();\n    this._eventBusAbortController = null;\n  },\n  unbindWindowEvents() {\n    this._windowAbortController?.abort();\n    this._windowAbortController = null;\n  },\n  _accumulateTicks(ticks, prop) {\n    if (this[prop] > 0 && ticks < 0 || this[prop] < 0 && ticks > 0) {\n      this[prop] = 0;\n    }\n    this[prop] += ticks;\n    const wholeTicks = Math.trunc(this[prop]);\n    this[prop] -= wholeTicks;\n    return wholeTicks;\n  },\n  _accumulateFactor(previousScale, factor, prop) {\n    if (factor === 1) {\n      return 1;\n    }\n    if (this[prop] > 1 && factor < 1 || this[prop] < 1 && factor > 1) {\n      this[prop] = 1;\n    }\n    const newFactor = Math.floor(previousScale * factor * this[prop] * 100) / (100 * previousScale);\n    this[prop] = factor / newFactor;\n    return newFactor;\n  },\n  _centerAtPos(previousScale, x, y) {\n    const {\n      pdfViewer\n    } = this;\n    const scaleDiff = pdfViewer.currentScale / previousScale - 1;\n    if (scaleDiff !== 0) {\n      const [top, left] = pdfViewer.containerTopLeft;\n      pdfViewer.container.scrollLeft += (x - left) * scaleDiff;\n      pdfViewer.container.scrollTop += (y - top) * scaleDiff;\n    }\n  },\n  _unblockDocumentLoadEvent() {\n    document.blockUnblockOnload?.(false);\n    this._unblockDocumentLoadEvent = () => {};\n  },\n  get scriptingReady() {\n    return this.pdfScriptingManager.ready;\n  }\n};\n(0,web_external_services__WEBPACK_IMPORTED_MODULE_4__.initCom)(PDFViewerApplication);\n{\n  web_print_service__WEBPACK_IMPORTED_MODULE_19__.PDFPrintServiceFactory.initGlobals(PDFViewerApplication);\n}\n{\n  const HOSTED_VIEWER_ORIGINS = [\"null\", \"http://mozilla.github.io\", \"https://mozilla.github.io\"];\n  var validateFileURL = function (file) {\n    if (!file) {\n      return;\n    }\n    try {\n      const viewerOrigin = new URL(window.location.href).origin || \"null\";\n      if (HOSTED_VIEWER_ORIGINS.includes(viewerOrigin)) {\n        return;\n      }\n      const fileOrigin = new URL(file, window.location.href).origin;\n      if (fileOrigin !== viewerOrigin) {\n        throw new Error(\"file origin does not match viewer's\");\n      }\n    } catch (ex) {\n      PDFViewerApplication._documentError(\"pdfjs-loading-error\", {\n        message: ex.message\n      });\n      throw ex;\n    }\n  };\n}\nasync function loadFakeWorker() {\n  pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.GlobalWorkerOptions.workerSrc ||= _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"workerSrc\");\n  await import( /*webpackIgnore: true*/pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.PDFWorker.workerSrc);\n}\nasync function loadPDFBug(self) {\n  const {\n    PDFBug\n  } = await import( /*webpackIgnore: true*/_app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get(\"debuggerSrc\"));\n  self._PDFBug = PDFBug;\n}\nfunction reportPageStatsPDFBug({\n  pageNumber\n}) {\n  if (!globalThis.Stats?.enabled) {\n    return;\n  }\n  const pageView = PDFViewerApplication.pdfViewer.getPageView(pageNumber - 1);\n  globalThis.Stats.add(pageNumber, pageView?.pdfPage?.stats);\n}\nfunction webViewerPageRender({\n  pageNumber\n}) {\n  if (pageNumber === PDFViewerApplication.page) {\n    PDFViewerApplication.toolbar?.updateLoadingIndicatorState(true);\n  }\n}\nfunction webViewerPageRendered({\n  pageNumber,\n  error\n}) {\n  if (pageNumber === PDFViewerApplication.page) {\n    PDFViewerApplication.toolbar?.updateLoadingIndicatorState(false);\n  }\n  if (PDFViewerApplication.pdfSidebar?.visibleView === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.THUMBS) {\n    const pageView = PDFViewerApplication.pdfViewer.getPageView(pageNumber - 1);\n    const thumbnailView = PDFViewerApplication.pdfThumbnailViewer?.getThumbnail(pageNumber - 1);\n    if (pageView) {\n      thumbnailView?.setImage(pageView);\n    }\n  }\n  if (error) {\n    PDFViewerApplication._otherError(\"pdfjs-rendering-error\", error);\n  }\n}\nfunction webViewerPageMode({\n  mode\n}) {\n  let view;\n  switch (mode) {\n    case \"thumbs\":\n      view = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.THUMBS;\n      break;\n    case \"bookmarks\":\n    case \"outline\":\n      view = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.OUTLINE;\n      break;\n    case \"attachments\":\n      view = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.ATTACHMENTS;\n      break;\n    case \"layers\":\n      view = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.LAYERS;\n      break;\n    case \"none\":\n      view = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.NONE;\n      break;\n    default:\n      console.error('Invalid \"pagemode\" hash parameter: ' + mode);\n      return;\n  }\n  PDFViewerApplication.pdfSidebar?.switchView(view, true);\n}\nfunction webViewerNamedAction(evt) {\n  switch (evt.action) {\n    case \"GoToPage\":\n      PDFViewerApplication.appConfig.toolbar?.pageNumber.select();\n      break;\n    case \"Find\":\n      if (!PDFViewerApplication.supportsIntegratedFind) {\n        PDFViewerApplication.findBar?.toggle();\n      }\n      break;\n    case \"Print\":\n      PDFViewerApplication.triggerPrinting();\n      break;\n    case \"SaveAs\":\n      PDFViewerApplication.downloadOrSave();\n      break;\n  }\n}\nfunction webViewerPresentationModeChanged(evt) {\n  PDFViewerApplication.pdfViewer.presentationModeState = evt.state;\n}\nfunction webViewerSidebarViewChanged({\n  view\n}) {\n  PDFViewerApplication.pdfRenderingQueue.isThumbnailViewEnabled = view === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.THUMBS;\n  if (PDFViewerApplication.isInitialViewSet) {\n    PDFViewerApplication.store?.set(\"sidebarView\", view).catch(() => {});\n  }\n}\nfunction webViewerUpdateViewarea({\n  location\n}) {\n  if (PDFViewerApplication.isInitialViewSet) {\n    PDFViewerApplication.store?.setMultiple({\n      page: location.pageNumber,\n      zoom: location.scale,\n      scrollLeft: location.left,\n      scrollTop: location.top,\n      rotation: location.rotation\n    }).catch(() => {});\n  }\n  if (PDFViewerApplication.appConfig.secondaryToolbar) {\n    const href = PDFViewerApplication.pdfLinkService.getAnchorUrl(location.pdfOpenParams);\n    PDFViewerApplication.appConfig.secondaryToolbar.viewBookmarkButton.href = href;\n  }\n}\nfunction webViewerScrollModeChanged(evt) {\n  if (PDFViewerApplication.isInitialViewSet && !PDFViewerApplication.pdfViewer.isInPresentationMode) {\n    PDFViewerApplication.store?.set(\"scrollMode\", evt.mode).catch(() => {});\n  }\n}\nfunction webViewerSpreadModeChanged(evt) {\n  if (PDFViewerApplication.isInitialViewSet && !PDFViewerApplication.pdfViewer.isInPresentationMode) {\n    PDFViewerApplication.store?.set(\"spreadMode\", evt.mode).catch(() => {});\n  }\n}\nfunction webViewerResize() {\n  const {\n    pdfDocument,\n    pdfViewer,\n    pdfRenderingQueue\n  } = PDFViewerApplication;\n  if (pdfRenderingQueue.printing && window.matchMedia(\"print\").matches) {\n    return;\n  }\n  if (!pdfDocument) {\n    return;\n  }\n  const currentScaleValue = pdfViewer.currentScaleValue;\n  if (currentScaleValue === \"auto\" || currentScaleValue === \"page-fit\" || currentScaleValue === \"page-width\") {\n    pdfViewer.currentScaleValue = currentScaleValue;\n  }\n  pdfViewer.update();\n}\nfunction webViewerHashchange(evt) {\n  const hash = evt.hash;\n  if (!hash) {\n    return;\n  }\n  if (!PDFViewerApplication.isInitialViewSet) {\n    PDFViewerApplication.initialBookmark = hash;\n  } else if (!PDFViewerApplication.pdfHistory?.popStateInProgress) {\n    PDFViewerApplication.pdfLinkService.setHash(hash);\n  }\n}\n{\n  var webViewerFileInputChange = function (evt) {\n    if (PDFViewerApplication.pdfViewer?.isInPresentationMode) {\n      return;\n    }\n    const file = evt.fileInput.files[0];\n    PDFViewerApplication.open({\n      url: URL.createObjectURL(file),\n      originalUrl: file.name\n    });\n  };\n  var webViewerOpenFile = function (evt) {\n    PDFViewerApplication._openFileInput?.click();\n  };\n}\nfunction webViewerPresentationMode() {\n  PDFViewerApplication.requestPresentationMode();\n}\nfunction webViewerSwitchAnnotationEditorMode(evt) {\n  PDFViewerApplication.pdfViewer.annotationEditorMode = evt;\n}\nfunction webViewerSwitchAnnotationEditorParams(evt) {\n  PDFViewerApplication.pdfViewer.annotationEditorParams = evt;\n}\nfunction webViewerPrint() {\n  PDFViewerApplication.triggerPrinting();\n}\nfunction webViewerDownload() {\n  PDFViewerApplication.downloadOrSave();\n}\nfunction webViewerFirstPage() {\n  PDFViewerApplication.page = 1;\n}\nfunction webViewerLastPage() {\n  PDFViewerApplication.page = PDFViewerApplication.pagesCount;\n}\nfunction webViewerNextPage() {\n  PDFViewerApplication.pdfViewer.nextPage();\n}\nfunction webViewerPreviousPage() {\n  PDFViewerApplication.pdfViewer.previousPage();\n}\nfunction webViewerZoomIn() {\n  PDFViewerApplication.zoomIn();\n}\nfunction webViewerZoomOut() {\n  PDFViewerApplication.zoomOut();\n}\nfunction webViewerZoomReset() {\n  PDFViewerApplication.zoomReset();\n}\nfunction webViewerPageNumberChanged(evt) {\n  const pdfViewer = PDFViewerApplication.pdfViewer;\n  if (evt.value !== \"\") {\n    PDFViewerApplication.pdfLinkService.goToPage(evt.value);\n  }\n  if (evt.value !== pdfViewer.currentPageNumber.toString() && evt.value !== pdfViewer.currentPageLabel) {\n    PDFViewerApplication.toolbar?.setPageNumber(pdfViewer.currentPageNumber, pdfViewer.currentPageLabel);\n  }\n}\nfunction webViewerScaleChanged(evt) {\n  PDFViewerApplication.pdfViewer.currentScaleValue = evt.value;\n}\nfunction webViewerRotateCw() {\n  PDFViewerApplication.rotatePages(90);\n}\nfunction webViewerRotateCcw() {\n  PDFViewerApplication.rotatePages(-90);\n}\nfunction webViewerOptionalContentConfig(evt) {\n  PDFViewerApplication.pdfViewer.optionalContentConfigPromise = evt.promise;\n}\nfunction webViewerSwitchScrollMode(evt) {\n  PDFViewerApplication.pdfViewer.scrollMode = evt.mode;\n}\nfunction webViewerSwitchSpreadMode(evt) {\n  PDFViewerApplication.pdfViewer.spreadMode = evt.mode;\n}\nfunction webViewerDocumentProperties() {\n  PDFViewerApplication.pdfDocumentProperties?.open();\n}\nfunction webViewerFindFromUrlHash(evt) {\n  PDFViewerApplication.eventBus.dispatch(\"find\", {\n    source: evt.source,\n    type: \"\",\n    query: evt.query,\n    caseSensitive: false,\n    entireWord: false,\n    highlightAll: true,\n    findPrevious: false,\n    matchDiacritics: true\n  });\n}\nfunction webViewerUpdateFindMatchesCount({\n  matchesCount\n}) {\n  if (PDFViewerApplication.supportsIntegratedFind) {\n    PDFViewerApplication.externalServices.updateFindMatchesCount(matchesCount);\n  } else {\n    PDFViewerApplication.findBar?.updateResultsCount(matchesCount);\n  }\n}\nfunction webViewerUpdateFindControlState({\n  state,\n  previous,\n  matchesCount,\n  rawQuery\n}) {\n  if (PDFViewerApplication.supportsIntegratedFind) {\n    PDFViewerApplication.externalServices.updateFindControlState({\n      result: state,\n      findPrevious: previous,\n      matchesCount,\n      rawQuery\n    });\n  } else {\n    PDFViewerApplication.findBar?.updateUIState(state, previous, matchesCount);\n  }\n}\nfunction webViewerScaleChanging(evt) {\n  PDFViewerApplication.toolbar?.setPageScale(evt.presetValue, evt.scale);\n  PDFViewerApplication.pdfViewer.update();\n}\nfunction webViewerRotationChanging(evt) {\n  if (PDFViewerApplication.pdfThumbnailViewer) {\n    PDFViewerApplication.pdfThumbnailViewer.pagesRotation = evt.pagesRotation;\n  }\n  PDFViewerApplication.forceRendering();\n  PDFViewerApplication.pdfViewer.currentPageNumber = evt.pageNumber;\n}\nfunction webViewerPageChanging({\n  pageNumber,\n  pageLabel\n}) {\n  PDFViewerApplication.toolbar?.setPageNumber(pageNumber, pageLabel);\n  PDFViewerApplication.secondaryToolbar?.setPageNumber(pageNumber);\n  if (PDFViewerApplication.pdfSidebar?.visibleView === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.THUMBS) {\n    PDFViewerApplication.pdfThumbnailViewer?.scrollThumbnailIntoView(pageNumber);\n  }\n  const currentPage = PDFViewerApplication.pdfViewer.getPageView(pageNumber - 1);\n  PDFViewerApplication.toolbar?.updateLoadingIndicatorState(currentPage?.renderingState === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.RUNNING);\n}\nfunction webViewerResolutionChange(evt) {\n  PDFViewerApplication.pdfViewer.refresh();\n}\nfunction webViewerVisibilityChange(evt) {\n  if (document.visibilityState === \"visible\") {\n    setZoomDisabledTimeout();\n  }\n}\nlet zoomDisabledTimeout = null;\nfunction setZoomDisabledTimeout() {\n  if (zoomDisabledTimeout) {\n    clearTimeout(zoomDisabledTimeout);\n  }\n  zoomDisabledTimeout = setTimeout(function () {\n    zoomDisabledTimeout = null;\n  }, WHEEL_ZOOM_DISABLED_TIMEOUT);\n}\nfunction webViewerWheel(evt) {\n  const {\n    pdfViewer,\n    supportsMouseWheelZoomCtrlKey,\n    supportsMouseWheelZoomMetaKey,\n    supportsPinchToZoom\n  } = PDFViewerApplication;\n  if (pdfViewer.isInPresentationMode) {\n    return;\n  }\n  const deltaMode = evt.deltaMode;\n  let scaleFactor = Math.exp(-evt.deltaY / 100);\n  const isBuiltInMac = false;\n  const isPinchToZoom = evt.ctrlKey && !PDFViewerApplication._isCtrlKeyDown && deltaMode === WheelEvent.DOM_DELTA_PIXEL && evt.deltaX === 0 && (Math.abs(scaleFactor - 1) < 0.05 || isBuiltInMac) && evt.deltaZ === 0;\n  if (isPinchToZoom || evt.ctrlKey && supportsMouseWheelZoomCtrlKey || evt.metaKey && supportsMouseWheelZoomMetaKey) {\n    evt.preventDefault();\n    if (PDFViewerApplication._isScrolling || zoomDisabledTimeout || document.visibilityState === \"hidden\" || PDFViewerApplication.overlayManager.active) {\n      return;\n    }\n    const previousScale = pdfViewer.currentScale;\n    if (isPinchToZoom && supportsPinchToZoom) {\n      scaleFactor = PDFViewerApplication._accumulateFactor(previousScale, scaleFactor, \"_wheelUnusedFactor\");\n      if (scaleFactor < 1) {\n        PDFViewerApplication.zoomOut(null, scaleFactor);\n      } else if (scaleFactor > 1) {\n        PDFViewerApplication.zoomIn(null, scaleFactor);\n      } else {\n        return;\n      }\n    } else {\n      const delta = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.normalizeWheelEventDirection)(evt);\n      let ticks = 0;\n      if (deltaMode === WheelEvent.DOM_DELTA_LINE || deltaMode === WheelEvent.DOM_DELTA_PAGE) {\n        if (Math.abs(delta) >= 1) {\n          ticks = Math.sign(delta);\n        } else {\n          ticks = PDFViewerApplication._accumulateTicks(delta, \"_wheelUnusedTicks\");\n        }\n      } else {\n        const PIXELS_PER_LINE_SCALE = 30;\n        ticks = PDFViewerApplication._accumulateTicks(delta / PIXELS_PER_LINE_SCALE, \"_wheelUnusedTicks\");\n      }\n      if (ticks < 0) {\n        PDFViewerApplication.zoomOut(-ticks);\n      } else if (ticks > 0) {\n        PDFViewerApplication.zoomIn(ticks);\n      } else {\n        return;\n      }\n    }\n    PDFViewerApplication._centerAtPos(previousScale, evt.clientX, evt.clientY);\n  }\n}\nfunction webViewerTouchStart(evt) {\n  if (PDFViewerApplication.pdfViewer.isInPresentationMode || evt.touches.length < 2) {\n    return;\n  }\n  evt.preventDefault();\n  if (evt.touches.length !== 2 || PDFViewerApplication.overlayManager.active) {\n    PDFViewerApplication._touchInfo = null;\n    return;\n  }\n  let [touch0, touch1] = evt.touches;\n  if (touch0.identifier > touch1.identifier) {\n    [touch0, touch1] = [touch1, touch0];\n  }\n  PDFViewerApplication._touchInfo = {\n    touch0X: touch0.pageX,\n    touch0Y: touch0.pageY,\n    touch1X: touch1.pageX,\n    touch1Y: touch1.pageY\n  };\n}\nfunction webViewerTouchMove(evt) {\n  if (!PDFViewerApplication._touchInfo || evt.touches.length !== 2) {\n    return;\n  }\n  const {\n    pdfViewer,\n    _touchInfo,\n    supportsPinchToZoom\n  } = PDFViewerApplication;\n  let [touch0, touch1] = evt.touches;\n  if (touch0.identifier > touch1.identifier) {\n    [touch0, touch1] = [touch1, touch0];\n  }\n  const {\n    pageX: page0X,\n    pageY: page0Y\n  } = touch0;\n  const {\n    pageX: page1X,\n    pageY: page1Y\n  } = touch1;\n  const {\n    touch0X: pTouch0X,\n    touch0Y: pTouch0Y,\n    touch1X: pTouch1X,\n    touch1Y: pTouch1Y\n  } = _touchInfo;\n  if (Math.abs(pTouch0X - page0X) <= 1 && Math.abs(pTouch0Y - page0Y) <= 1 && Math.abs(pTouch1X - page1X) <= 1 && Math.abs(pTouch1Y - page1Y) <= 1) {\n    return;\n  }\n  _touchInfo.touch0X = page0X;\n  _touchInfo.touch0Y = page0Y;\n  _touchInfo.touch1X = page1X;\n  _touchInfo.touch1Y = page1Y;\n  if (pTouch0X === page0X && pTouch0Y === page0Y) {\n    const v1X = pTouch1X - page0X;\n    const v1Y = pTouch1Y - page0Y;\n    const v2X = page1X - page0X;\n    const v2Y = page1Y - page0Y;\n    const det = v1X * v2Y - v1Y * v2X;\n    if (Math.abs(det) > 0.02 * Math.hypot(v1X, v1Y) * Math.hypot(v2X, v2Y)) {\n      return;\n    }\n  } else if (pTouch1X === page1X && pTouch1Y === page1Y) {\n    const v1X = pTouch0X - page1X;\n    const v1Y = pTouch0Y - page1Y;\n    const v2X = page0X - page1X;\n    const v2Y = page0Y - page1Y;\n    const det = v1X * v2Y - v1Y * v2X;\n    if (Math.abs(det) > 0.02 * Math.hypot(v1X, v1Y) * Math.hypot(v2X, v2Y)) {\n      return;\n    }\n  } else {\n    const diff0X = page0X - pTouch0X;\n    const diff1X = page1X - pTouch1X;\n    const diff0Y = page0Y - pTouch0Y;\n    const diff1Y = page1Y - pTouch1Y;\n    const dotProduct = diff0X * diff1X + diff0Y * diff1Y;\n    if (dotProduct >= 0) {\n      return;\n    }\n  }\n  evt.preventDefault();\n  const distance = Math.hypot(page0X - page1X, page0Y - page1Y) || 1;\n  const pDistance = Math.hypot(pTouch0X - pTouch1X, pTouch0Y - pTouch1Y) || 1;\n  const previousScale = pdfViewer.currentScale;\n  if (supportsPinchToZoom) {\n    const newScaleFactor = PDFViewerApplication._accumulateFactor(previousScale, distance / pDistance, \"_touchUnusedFactor\");\n    if (newScaleFactor < 1) {\n      PDFViewerApplication.zoomOut(null, newScaleFactor);\n    } else if (newScaleFactor > 1) {\n      PDFViewerApplication.zoomIn(null, newScaleFactor);\n    } else {\n      return;\n    }\n  } else {\n    const PIXELS_PER_LINE_SCALE = 30;\n    const ticks = PDFViewerApplication._accumulateTicks((distance - pDistance) / PIXELS_PER_LINE_SCALE, \"_touchUnusedTicks\");\n    if (ticks < 0) {\n      PDFViewerApplication.zoomOut(-ticks);\n    } else if (ticks > 0) {\n      PDFViewerApplication.zoomIn(ticks);\n    } else {\n      return;\n    }\n  }\n  PDFViewerApplication._centerAtPos(previousScale, (page0X + page1X) / 2, (page0Y + page1Y) / 2);\n}\nfunction webViewerTouchEnd(evt) {\n  if (!PDFViewerApplication._touchInfo) {\n    return;\n  }\n  evt.preventDefault();\n  PDFViewerApplication._touchInfo = null;\n  PDFViewerApplication._touchUnusedTicks = 0;\n  PDFViewerApplication._touchUnusedFactor = 1;\n}\nfunction webViewerClick(evt) {\n  if (!PDFViewerApplication.secondaryToolbar?.isOpen) {\n    return;\n  }\n  const appConfig = PDFViewerApplication.appConfig;\n  if (PDFViewerApplication.pdfViewer.containsElement(evt.target) || appConfig.toolbar?.container.contains(evt.target) && evt.target !== appConfig.secondaryToolbar?.toggleButton) {\n    PDFViewerApplication.secondaryToolbar.close();\n  }\n}\nfunction webViewerKeyUp(evt) {\n  if (evt.key === \"Control\") {\n    PDFViewerApplication._isCtrlKeyDown = false;\n  }\n}\nfunction webViewerKeyDown(evt) {\n  PDFViewerApplication._isCtrlKeyDown = evt.key === \"Control\";\n  if (PDFViewerApplication.overlayManager.active) {\n    return;\n  }\n  const {\n    eventBus,\n    pdfViewer\n  } = PDFViewerApplication;\n  const isViewerInPresentationMode = pdfViewer.isInPresentationMode;\n  let handled = false,\n    ensureViewerFocused = false;\n  const cmd = (evt.ctrlKey ? 1 : 0) | (evt.altKey ? 2 : 0) | (evt.shiftKey ? 4 : 0) | (evt.metaKey ? 8 : 0);\n  if (cmd === 1 || cmd === 8 || cmd === 5 || cmd === 12) {\n    switch (evt.keyCode) {\n      case 70:\n        if (!PDFViewerApplication.supportsIntegratedFind && !evt.shiftKey) {\n          PDFViewerApplication.findBar?.open();\n          handled = true;\n        }\n        break;\n      case 71:\n        if (!PDFViewerApplication.supportsIntegratedFind) {\n          const {\n            state\n          } = PDFViewerApplication.findController;\n          if (state) {\n            const newState = {\n              source: window,\n              type: \"again\",\n              findPrevious: cmd === 5 || cmd === 12\n            };\n            eventBus.dispatch(\"find\", {\n              ...state,\n              ...newState\n            });\n          }\n          handled = true;\n        }\n        break;\n      case 61:\n      case 107:\n      case 187:\n      case 171:\n        PDFViewerApplication.zoomIn();\n        handled = true;\n        break;\n      case 173:\n      case 109:\n      case 189:\n        PDFViewerApplication.zoomOut();\n        handled = true;\n        break;\n      case 48:\n      case 96:\n        if (!isViewerInPresentationMode) {\n          setTimeout(function () {\n            PDFViewerApplication.zoomReset();\n          });\n          handled = false;\n        }\n        break;\n      case 38:\n        if (isViewerInPresentationMode || PDFViewerApplication.page > 1) {\n          PDFViewerApplication.page = 1;\n          handled = true;\n          ensureViewerFocused = true;\n        }\n        break;\n      case 40:\n        if (isViewerInPresentationMode || PDFViewerApplication.page < PDFViewerApplication.pagesCount) {\n          PDFViewerApplication.page = PDFViewerApplication.pagesCount;\n          handled = true;\n          ensureViewerFocused = true;\n        }\n        break;\n    }\n  }\n  if (cmd === 1 || cmd === 8) {\n    switch (evt.keyCode) {\n      case 83:\n        eventBus.dispatch(\"download\", {\n          source: window\n        });\n        handled = true;\n        break;\n      case 79:\n        {\n          eventBus.dispatch(\"openfile\", {\n            source: window\n          });\n          handled = true;\n        }\n        break;\n    }\n  }\n  if (cmd === 3 || cmd === 10) {\n    switch (evt.keyCode) {\n      case 80:\n        PDFViewerApplication.requestPresentationMode();\n        handled = true;\n        PDFViewerApplication.externalServices.reportTelemetry({\n          type: \"buttons\",\n          data: {\n            id: \"presentationModeKeyboard\"\n          }\n        });\n        break;\n      case 71:\n        if (PDFViewerApplication.appConfig.toolbar) {\n          PDFViewerApplication.appConfig.toolbar.pageNumber.select();\n          handled = true;\n        }\n        break;\n    }\n  }\n  if (handled) {\n    if (ensureViewerFocused && !isViewerInPresentationMode) {\n      pdfViewer.focus();\n    }\n    evt.preventDefault();\n    return;\n  }\n  const curElement = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.getActiveOrFocusedElement)();\n  const curElementTagName = curElement?.tagName.toUpperCase();\n  if (curElementTagName === \"INPUT\" || curElementTagName === \"TEXTAREA\" || curElementTagName === \"SELECT\" || curElementTagName === \"BUTTON\" && (evt.keyCode === 13 || evt.keyCode === 32) || curElement?.isContentEditable) {\n    if (evt.keyCode !== 27) {\n      return;\n    }\n  }\n  if (cmd === 0) {\n    let turnPage = 0,\n      turnOnlyIfPageFit = false;\n    switch (evt.keyCode) {\n      case 38:\n        if (PDFViewerApplication.supportsCaretBrowsingMode) {\n          PDFViewerApplication.moveCaret(true, false);\n          handled = true;\n          break;\n        }\n      case 33:\n        if (pdfViewer.isVerticalScrollbarEnabled) {\n          turnOnlyIfPageFit = true;\n        }\n        turnPage = -1;\n        break;\n      case 8:\n        if (!isViewerInPresentationMode) {\n          turnOnlyIfPageFit = true;\n        }\n        turnPage = -1;\n        break;\n      case 37:\n        if (PDFViewerApplication.supportsCaretBrowsingMode) {\n          return;\n        }\n        if (pdfViewer.isHorizontalScrollbarEnabled) {\n          turnOnlyIfPageFit = true;\n        }\n      case 75:\n      case 80:\n        turnPage = -1;\n        break;\n      case 27:\n        if (PDFViewerApplication.secondaryToolbar?.isOpen) {\n          PDFViewerApplication.secondaryToolbar.close();\n          handled = true;\n        }\n        if (!PDFViewerApplication.supportsIntegratedFind && PDFViewerApplication.findBar?.opened) {\n          PDFViewerApplication.findBar.close();\n          handled = true;\n        }\n        break;\n      case 40:\n        if (PDFViewerApplication.supportsCaretBrowsingMode) {\n          PDFViewerApplication.moveCaret(false, false);\n          handled = true;\n          break;\n        }\n      case 34:\n        if (pdfViewer.isVerticalScrollbarEnabled) {\n          turnOnlyIfPageFit = true;\n        }\n        turnPage = 1;\n        break;\n      case 13:\n      case 32:\n        if (!isViewerInPresentationMode) {\n          turnOnlyIfPageFit = true;\n        }\n        turnPage = 1;\n        break;\n      case 39:\n        if (PDFViewerApplication.supportsCaretBrowsingMode) {\n          return;\n        }\n        if (pdfViewer.isHorizontalScrollbarEnabled) {\n          turnOnlyIfPageFit = true;\n        }\n      case 74:\n      case 78:\n        turnPage = 1;\n        break;\n      case 36:\n        if (isViewerInPresentationMode || PDFViewerApplication.page > 1) {\n          PDFViewerApplication.page = 1;\n          handled = true;\n          ensureViewerFocused = true;\n        }\n        break;\n      case 35:\n        if (isViewerInPresentationMode || PDFViewerApplication.page < PDFViewerApplication.pagesCount) {\n          PDFViewerApplication.page = PDFViewerApplication.pagesCount;\n          handled = true;\n          ensureViewerFocused = true;\n        }\n        break;\n      case 83:\n        PDFViewerApplication.pdfCursorTools?.switchTool(_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.CursorTool.SELECT);\n        break;\n      case 72:\n        PDFViewerApplication.pdfCursorTools?.switchTool(_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.CursorTool.HAND);\n        break;\n      case 82:\n        PDFViewerApplication.rotatePages(90);\n        break;\n      case 115:\n        PDFViewerApplication.pdfSidebar?.toggle();\n        break;\n    }\n    if (turnPage !== 0 && (!turnOnlyIfPageFit || pdfViewer.currentScaleValue === \"page-fit\")) {\n      if (turnPage > 0) {\n        pdfViewer.nextPage();\n      } else {\n        pdfViewer.previousPage();\n      }\n      handled = true;\n    }\n  }\n  if (cmd === 4) {\n    switch (evt.keyCode) {\n      case 13:\n      case 32:\n        if (!isViewerInPresentationMode && pdfViewer.currentScaleValue !== \"page-fit\") {\n          break;\n        }\n        pdfViewer.previousPage();\n        handled = true;\n        break;\n      case 38:\n        PDFViewerApplication.moveCaret(true, true);\n        handled = true;\n        break;\n      case 40:\n        PDFViewerApplication.moveCaret(false, true);\n        handled = true;\n        break;\n      case 82:\n        PDFViewerApplication.rotatePages(-90);\n        break;\n    }\n  }\n  if (!handled && !isViewerInPresentationMode) {\n    if (evt.keyCode >= 33 && evt.keyCode <= 40 || evt.keyCode === 32 && curElementTagName !== \"BUTTON\") {\n      ensureViewerFocused = true;\n    }\n  }\n  if (ensureViewerFocused && !pdfViewer.containsElement(curElement)) {\n    pdfViewer.focus();\n  }\n  if (handled) {\n    evt.preventDefault();\n  }\n}\nfunction beforeUnload(evt) {\n  evt.preventDefault();\n  evt.returnValue = \"\";\n  return false;\n}\nfunction webViewerAnnotationEditorStatesChanged(data) {\n  PDFViewerApplication.externalServices.updateEditorStates(data);\n}\nfunction webViewerReportTelemetry({\n  details\n}) {\n  PDFViewerApplication.externalServices.reportTelemetry(details);\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 9840:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   AppOptions: () => (/* binding */ AppOptions),\n/* harmony export */   OptionKind: () => (/* binding */ OptionKind)\n/* harmony export */ });\n{\n  var compatibilityParams = Object.create(null);\n  const userAgent = navigator.userAgent || \"\";\n  const platform = navigator.platform || \"\";\n  const maxTouchPoints = navigator.maxTouchPoints || 1;\n  const isAndroid = /Android/.test(userAgent);\n  const isIOS = /\\b(iPad|iPhone|iPod)(?=;)/.test(userAgent) || platform === \"MacIntel\" && maxTouchPoints > 1;\n  (function checkCanvasSizeLimitation() {\n    if (isIOS || isAndroid) {\n      compatibilityParams.maxCanvasPixels = 5242880;\n    }\n  })();\n}\nconst OptionKind = {\n  BROWSER: 0x01,\n  VIEWER: 0x02,\n  API: 0x04,\n  WORKER: 0x08,\n  PREFERENCE: 0x80\n};\nconst defaultOptions = {\n  canvasMaxAreaInBytes: {\n    value: -1,\n    kind: OptionKind.BROWSER + OptionKind.API\n  },\n  isInAutomation: {\n    value: false,\n    kind: OptionKind.BROWSER\n  },\n  supportsCaretBrowsingMode: {\n    value: false,\n    kind: OptionKind.BROWSER\n  },\n  supportsDocumentFonts: {\n    value: true,\n    kind: OptionKind.BROWSER\n  },\n  supportsIntegratedFind: {\n    value: false,\n    kind: OptionKind.BROWSER\n  },\n  supportsMouseWheelZoomCtrlKey: {\n    value: true,\n    kind: OptionKind.BROWSER\n  },\n  supportsMouseWheelZoomMetaKey: {\n    value: true,\n    kind: OptionKind.BROWSER\n  },\n  supportsPinchToZoom: {\n    value: true,\n    kind: OptionKind.BROWSER\n  },\n  annotationEditorMode: {\n    value: 0,\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  },\n  annotationMode: {\n    value: 2,\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  },\n  cursorToolOnLoad: {\n    value: 0,\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  },\n  debuggerSrc: {\n    value: \"./debugger.mjs\",\n    kind: OptionKind.VIEWER\n  },\n  defaultZoomDelay: {\n    value: 400,\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  },\n  defaultZoomValue: {\n    value: \"\",\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  },\n  disableHistory: {\n    value: false,\n    kind: OptionKind.VIEWER\n  },\n  disablePageLabels: {\n    value: false,\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  },\n  enableHighlightEditor: {\n    value: false,\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  },\n  enableHighlightFloatingButton: {\n    value: false,\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  },\n  enableML: {\n    value: false,\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  },\n  enablePermissions: {\n    value: false,\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  },\n  enablePrintAutoRotate: {\n    value: true,\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  },\n  enableScripting: {\n    value: true,\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  },\n  enableStampEditor: {\n    value: true,\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  },\n  externalLinkRel: {\n    value: \"noopener noreferrer nofollow\",\n    kind: OptionKind.VIEWER\n  },\n  externalLinkTarget: {\n    value: 0,\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  },\n  highlightEditorColors: {\n    value: \"yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F\",\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  },\n  historyUpdateUrl: {\n    value: false,\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  },\n  ignoreDestinationZoom: {\n    value: false,\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  },\n  imageResourcesPath: {\n    value: \"./images/\",\n    kind: OptionKind.VIEWER\n  },\n  maxCanvasPixels: {\n    value: 2 ** 25,\n    kind: OptionKind.VIEWER\n  },\n  forcePageColors: {\n    value: false,\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  },\n  pageColorsBackground: {\n    value: \"Canvas\",\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  },\n  pageColorsForeground: {\n    value: \"CanvasText\",\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  },\n  pdfBugEnabled: {\n    value: false,\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  },\n  printResolution: {\n    value: 150,\n    kind: OptionKind.VIEWER\n  },\n  sidebarViewOnLoad: {\n    value: -1,\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  },\n  scrollModeOnLoad: {\n    value: -1,\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  },\n  spreadModeOnLoad: {\n    value: -1,\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  },\n  textLayerMode: {\n    value: 1,\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  },\n  viewOnLoad: {\n    value: 0,\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  },\n  cMapPacked: {\n    value: true,\n    kind: OptionKind.API\n  },\n  cMapUrl: {\n    value: \"../web/cmaps/\",\n    kind: OptionKind.API\n  },\n  disableAutoFetch: {\n    value: false,\n    kind: OptionKind.API + OptionKind.PREFERENCE\n  },\n  disableFontFace: {\n    value: false,\n    kind: OptionKind.API + OptionKind.PREFERENCE\n  },\n  disableRange: {\n    value: false,\n    kind: OptionKind.API + OptionKind.PREFERENCE\n  },\n  disableStream: {\n    value: false,\n    kind: OptionKind.API + OptionKind.PREFERENCE\n  },\n  docBaseUrl: {\n    value: \"\",\n    kind: OptionKind.API\n  },\n  enableXfa: {\n    value: true,\n    kind: OptionKind.API + OptionKind.PREFERENCE\n  },\n  fontExtraProperties: {\n    value: false,\n    kind: OptionKind.API\n  },\n  isEvalSupported: {\n    value: true,\n    kind: OptionKind.API\n  },\n  isOffscreenCanvasSupported: {\n    value: true,\n    kind: OptionKind.API\n  },\n  maxImageSize: {\n    value: -1,\n    kind: OptionKind.API\n  },\n  pdfBug: {\n    value: false,\n    kind: OptionKind.API\n  },\n  standardFontDataUrl: {\n    value: \"../web/standard_fonts/\",\n    kind: OptionKind.API\n  },\n  verbosity: {\n    value: 1,\n    kind: OptionKind.API\n  },\n  workerPort: {\n    value: null,\n    kind: OptionKind.WORKER\n  },\n  workerSrc: {\n    value: \"../build/pdf.worker.mjs\",\n    kind: OptionKind.WORKER\n  }\n};\n{\n  defaultOptions.defaultUrl = {\n    value: \"compressed.tracemonkey-pldi-09.pdf\",\n    kind: OptionKind.VIEWER\n  };\n  defaultOptions.sandboxBundleSrc = {\n    value: \"../build/pdf.sandbox.mjs\",\n    kind: OptionKind.VIEWER\n  };\n  defaultOptions.viewerCssTheme = {\n    value: 0,\n    kind: OptionKind.VIEWER + OptionKind.PREFERENCE\n  };\n}\n{\n  defaultOptions.disablePreferences = {\n    value: false,\n    kind: OptionKind.VIEWER\n  };\n  defaultOptions.locale = {\n    value: navigator.language || \"en-US\",\n    kind: OptionKind.VIEWER\n  };\n}\nconst userOptions = Object.create(null);\n{\n  for (const name in compatibilityParams) {\n    userOptions[name] = compatibilityParams[name];\n  }\n}\nclass AppOptions {\n  constructor() {\n    throw new Error(\"Cannot initialize AppOptions.\");\n  }\n  static get(name) {\n    return userOptions[name] ?? defaultOptions[name]?.value ?? undefined;\n  }\n  static getAll(kind = null, defaultOnly = false) {\n    const options = Object.create(null);\n    for (const name in defaultOptions) {\n      const defaultOption = defaultOptions[name];\n      if (kind && !(kind & defaultOption.kind)) {\n        continue;\n      }\n      options[name] = defaultOnly ? defaultOption.value : userOptions[name] ?? defaultOption.value;\n    }\n    return options;\n  }\n  static set(name, value) {\n    userOptions[name] = value;\n  }\n  static setAll(options, init = false) {\n    if (init) {\n      if (this.get(\"disablePreferences\")) {\n        return;\n      }\n      for (const name in userOptions) {\n        if (compatibilityParams[name] !== undefined) {\n          continue;\n        }\n        console.warn(\"setAll: The Preferences may override manually set AppOptions; \" + 'please use the \"disablePreferences\"-option in order to prevent that.');\n        break;\n      }\n    }\n    for (const name in options) {\n      userOptions[name] = options[name];\n    }\n  }\n  static remove(name) {\n    delete userOptions[name];\n    const val = compatibilityParams[name];\n    if (val !== undefined) {\n      userOptions[name] = val;\n    }\n  }\n}\n\n\n/***/ }),\n\n/***/ 2961:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   BaseTreeViewer: () => (/* binding */ BaseTreeViewer)\n/* harmony export */ });\n/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256);\n\nconst TREEITEM_OFFSET_TOP = -100;\nconst TREEITEM_SELECTED_CLASS = \"selected\";\nclass BaseTreeViewer {\n  constructor(options) {\n    if (this.constructor === BaseTreeViewer) {\n      throw new Error(\"Cannot initialize BaseTreeViewer.\");\n    }\n    this.container = options.container;\n    this.eventBus = options.eventBus;\n    this._l10n = options.l10n;\n    this.reset();\n  }\n  reset() {\n    this._pdfDocument = null;\n    this._lastToggleIsShow = true;\n    this._currentTreeItem = null;\n    this.container.textContent = \"\";\n    this.container.classList.remove(\"treeWithDeepNesting\");\n  }\n  _dispatchEvent(count) {\n    throw new Error(\"Not implemented: _dispatchEvent\");\n  }\n  _bindLink(element, params) {\n    throw new Error(\"Not implemented: _bindLink\");\n  }\n  _normalizeTextContent(str) {\n    return (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.removeNullCharacters)(str, true) || \"\\u2013\";\n  }\n  _addToggleButton(div, hidden = false) {\n    const toggler = document.createElement(\"div\");\n    toggler.className = \"treeItemToggler\";\n    if (hidden) {\n      toggler.classList.add(\"treeItemsHidden\");\n    }\n    toggler.onclick = evt => {\n      evt.stopPropagation();\n      toggler.classList.toggle(\"treeItemsHidden\");\n      if (evt.shiftKey) {\n        const shouldShowAll = !toggler.classList.contains(\"treeItemsHidden\");\n        this._toggleTreeItem(div, shouldShowAll);\n      }\n    };\n    div.prepend(toggler);\n  }\n  _toggleTreeItem(root, show = false) {\n    this._l10n.pause();\n    this._lastToggleIsShow = show;\n    for (const toggler of root.querySelectorAll(\".treeItemToggler\")) {\n      toggler.classList.toggle(\"treeItemsHidden\", !show);\n    }\n    this._l10n.resume();\n  }\n  _toggleAllTreeItems() {\n    this._toggleTreeItem(this.container, !this._lastToggleIsShow);\n  }\n  _finishRendering(fragment, count, hasAnyNesting = false) {\n    if (hasAnyNesting) {\n      this.container.classList.add(\"treeWithDeepNesting\");\n      this._lastToggleIsShow = !fragment.querySelector(\".treeItemsHidden\");\n    }\n    this._l10n.pause();\n    this.container.append(fragment);\n    this._l10n.resume();\n    this._dispatchEvent(count);\n  }\n  render(params) {\n    throw new Error(\"Not implemented: render\");\n  }\n  _updateCurrentTreeItem(treeItem = null) {\n    if (this._currentTreeItem) {\n      this._currentTreeItem.classList.remove(TREEITEM_SELECTED_CLASS);\n      this._currentTreeItem = null;\n    }\n    if (treeItem) {\n      treeItem.classList.add(TREEITEM_SELECTED_CLASS);\n      this._currentTreeItem = treeItem;\n    }\n  }\n  _scrollToCurrentTreeItem(treeItem) {\n    if (!treeItem) {\n      return;\n    }\n    this._l10n.pause();\n    let currentNode = treeItem.parentNode;\n    while (currentNode && currentNode !== this.container) {\n      if (currentNode.classList.contains(\"treeItem\")) {\n        const toggler = currentNode.firstElementChild;\n        toggler?.classList.remove(\"treeItemsHidden\");\n      }\n      currentNode = currentNode.parentNode;\n    }\n    this._l10n.resume();\n    this._updateCurrentTreeItem(treeItem);\n    this.container.scrollTo(treeItem.offsetLeft, treeItem.offsetTop + TREEITEM_OFFSET_TOP);\n  }\n}\n\n\n/***/ }),\n\n/***/ 3973:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   CaretBrowsingMode: () => (/* binding */ CaretBrowsingMode)\n/* harmony export */ });\nconst PRECISION = 1e-1;\nclass CaretBrowsingMode {\n  #mainContainer;\n  #toolBarHeight;\n  #viewerContainer;\n  constructor(mainContainer, viewerContainer, toolbarContainer) {\n    this.#mainContainer = mainContainer;\n    this.#viewerContainer = viewerContainer;\n    this.#toolBarHeight = toolbarContainer?.getBoundingClientRect().height ?? 0;\n  }\n  #isOnSameLine(rect1, rect2) {\n    const top1 = rect1.y;\n    const bot1 = rect1.bottom;\n    const mid1 = rect1.y + rect1.height / 2;\n    const top2 = rect2.y;\n    const bot2 = rect2.bottom;\n    const mid2 = rect2.y + rect2.height / 2;\n    return top1 <= mid2 && mid2 <= bot1 || top2 <= mid1 && mid1 <= bot2;\n  }\n  #isUnderOver(rect, x, y, isUp) {\n    const midY = rect.y + rect.height / 2;\n    return (isUp ? y >= midY : y <= midY) && rect.x - PRECISION <= x && x <= rect.right + PRECISION;\n  }\n  #isVisible(rect) {\n    return rect.top >= this.#toolBarHeight && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth);\n  }\n  #getCaretPosition(selection, isUp) {\n    const {\n      focusNode,\n      focusOffset\n    } = selection;\n    const range = document.createRange();\n    range.setStart(focusNode, focusOffset);\n    range.setEnd(focusNode, focusOffset);\n    const rect = range.getBoundingClientRect();\n    return [rect.x, isUp ? rect.top : rect.bottom];\n  }\n  static #caretPositionFromPoint(x, y) {\n    if (!document.caretPositionFromPoint) {\n      const {\n        startContainer: offsetNode,\n        startOffset: offset\n      } = document.caretRangeFromPoint(x, y);\n      return {\n        offsetNode,\n        offset\n      };\n    }\n    return document.caretPositionFromPoint(x, y);\n  }\n  #setCaretPositionHelper(selection, caretX, select, element, rect) {\n    rect ||= element.getBoundingClientRect();\n    if (caretX <= rect.x + PRECISION) {\n      if (select) {\n        selection.extend(element.firstChild, 0);\n      } else {\n        selection.setPosition(element.firstChild, 0);\n      }\n      return;\n    }\n    if (rect.right - PRECISION <= caretX) {\n      const {\n        lastChild\n      } = element;\n      if (select) {\n        selection.extend(lastChild, lastChild.length);\n      } else {\n        selection.setPosition(lastChild, lastChild.length);\n      }\n      return;\n    }\n    const midY = rect.y + rect.height / 2;\n    let caretPosition = CaretBrowsingMode.#caretPositionFromPoint(caretX, midY);\n    let parentElement = caretPosition.offsetNode?.parentElement;\n    if (parentElement && parentElement !== element) {\n      const elementsAtPoint = document.elementsFromPoint(caretX, midY);\n      const savedVisibilities = [];\n      for (const el of elementsAtPoint) {\n        if (el === element) {\n          break;\n        }\n        const {\n          style\n        } = el;\n        savedVisibilities.push([el, style.visibility]);\n        style.visibility = \"hidden\";\n      }\n      caretPosition = CaretBrowsingMode.#caretPositionFromPoint(caretX, midY);\n      parentElement = caretPosition.offsetNode?.parentElement;\n      for (const [el, visibility] of savedVisibilities) {\n        el.style.visibility = visibility;\n      }\n    }\n    if (parentElement !== element) {\n      if (select) {\n        selection.extend(element.firstChild, 0);\n      } else {\n        selection.setPosition(element.firstChild, 0);\n      }\n      return;\n    }\n    if (select) {\n      selection.extend(caretPosition.offsetNode, caretPosition.offset);\n    } else {\n      selection.setPosition(caretPosition.offsetNode, caretPosition.offset);\n    }\n  }\n  #setCaretPosition(select, selection, newLineElement, newLineElementRect, caretX) {\n    if (this.#isVisible(newLineElementRect)) {\n      this.#setCaretPositionHelper(selection, caretX, select, newLineElement, newLineElementRect);\n      return;\n    }\n    this.#mainContainer.addEventListener(\"scrollend\", this.#setCaretPositionHelper.bind(this, selection, caretX, select, newLineElement, null), {\n      once: true\n    });\n    newLineElement.scrollIntoView();\n  }\n  #getNodeOnNextPage(textLayer, isUp) {\n    while (true) {\n      const page = textLayer.closest(\".page\");\n      const pageNumber = parseInt(page.getAttribute(\"data-page-number\"));\n      const nextPage = isUp ? pageNumber - 1 : pageNumber + 1;\n      textLayer = this.#viewerContainer.querySelector(`.page[data-page-number=\"${nextPage}\"] .textLayer`);\n      if (!textLayer) {\n        return null;\n      }\n      const walker = document.createTreeWalker(textLayer, NodeFilter.SHOW_TEXT);\n      const node = isUp ? walker.lastChild() : walker.firstChild();\n      if (node) {\n        return node;\n      }\n    }\n  }\n  moveCaret(isUp, select) {\n    const selection = document.getSelection();\n    if (selection.rangeCount === 0) {\n      return;\n    }\n    const {\n      focusNode\n    } = selection;\n    const focusElement = focusNode.nodeType !== Node.ELEMENT_NODE ? focusNode.parentElement : focusNode;\n    const root = focusElement.closest(\".textLayer\");\n    if (!root) {\n      return;\n    }\n    const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);\n    walker.currentNode = focusNode;\n    const focusRect = focusElement.getBoundingClientRect();\n    let newLineElement = null;\n    const nodeIterator = (isUp ? walker.previousSibling : walker.nextSibling).bind(walker);\n    while (nodeIterator()) {\n      const element = walker.currentNode.parentElement;\n      if (!this.#isOnSameLine(focusRect, element.getBoundingClientRect())) {\n        newLineElement = element;\n        break;\n      }\n    }\n    if (!newLineElement) {\n      const node = this.#getNodeOnNextPage(root, isUp);\n      if (!node) {\n        return;\n      }\n      if (select) {\n        const lastNode = (isUp ? walker.firstChild() : walker.lastChild()) || focusNode;\n        selection.extend(lastNode, isUp ? 0 : lastNode.length);\n        const range = document.createRange();\n        range.setStart(node, isUp ? node.length : 0);\n        range.setEnd(node, isUp ? node.length : 0);\n        selection.addRange(range);\n        return;\n      }\n      const [caretX] = this.#getCaretPosition(selection, isUp);\n      const {\n        parentElement\n      } = node;\n      this.#setCaretPosition(select, selection, parentElement, parentElement.getBoundingClientRect(), caretX);\n      return;\n    }\n    const [caretX, caretY] = this.#getCaretPosition(selection, isUp);\n    const newLineElementRect = newLineElement.getBoundingClientRect();\n    if (this.#isUnderOver(newLineElementRect, caretX, caretY, isUp)) {\n      this.#setCaretPosition(select, selection, newLineElement, newLineElementRect, caretX);\n      return;\n    }\n    while (nodeIterator()) {\n      const element = walker.currentNode.parentElement;\n      const elementRect = element.getBoundingClientRect();\n      if (!this.#isOnSameLine(newLineElementRect, elementRect)) {\n        break;\n      }\n      if (this.#isUnderOver(elementRect, caretX, caretY, isUp)) {\n        this.#setCaretPosition(select, selection, element, elementRect, caretX);\n        return;\n      }\n    }\n    this.#setCaretPosition(select, selection, newLineElement, newLineElementRect, caretX);\n  }\n}\n\n\n/***/ }),\n\n/***/ 1544:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   DownloadManager: () => (/* binding */ DownloadManager)\n/* harmony export */ });\n/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__]);\npdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];\n\nfunction download(blobUrl, filename) {\n  const a = document.createElement(\"a\");\n  if (!a.click) {\n    throw new Error('DownloadManager: \"a.click()\" is not supported.');\n  }\n  a.href = blobUrl;\n  a.target = \"_parent\";\n  if (\"download\" in a) {\n    a.download = filename;\n  }\n  (document.body || document.documentElement).append(a);\n  a.click();\n  a.remove();\n}\nclass DownloadManager {\n  #openBlobUrls = new WeakMap();\n  downloadUrl(url, filename, _options) {\n    if (!(0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.createValidAbsoluteUrl)(url, \"http://example.com\")) {\n      console.error(`downloadUrl - not a valid URL: ${url}`);\n      return;\n    }\n    download(url + \"#pdfjs.action=download\", filename);\n  }\n  downloadData(data, filename, contentType) {\n    const blobUrl = URL.createObjectURL(new Blob([data], {\n      type: contentType\n    }));\n    download(blobUrl, filename);\n  }\n  openOrDownloadData(data, filename, dest = null) {\n    const isPdfData = (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.isPdfFile)(filename);\n    const contentType = isPdfData ? \"application/pdf\" : \"\";\n    if (isPdfData) {\n      let blobUrl = this.#openBlobUrls.get(data);\n      if (!blobUrl) {\n        blobUrl = URL.createObjectURL(new Blob([data], {\n          type: contentType\n        }));\n        this.#openBlobUrls.set(data, blobUrl);\n      }\n      let viewerUrl;\n      viewerUrl = \"?file=\" + encodeURIComponent(blobUrl + \"#\" + filename);\n      if (dest) {\n        viewerUrl += `#${escape(dest)}`;\n      }\n      try {\n        window.open(viewerUrl);\n        return true;\n      } catch (ex) {\n        console.error(`openOrDownloadData: ${ex}`);\n        URL.revokeObjectURL(blobUrl);\n        this.#openBlobUrls.delete(data);\n      }\n    }\n    this.downloadData(data, filename, contentType);\n    return false;\n  }\n  download(blob, url, filename, _options) {\n    const blobUrl = URL.createObjectURL(blob);\n    download(blobUrl, filename);\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 3088:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   DrawLayerBuilder: () => (/* binding */ DrawLayerBuilder)\n/* harmony export */ });\n/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__]);\npdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];\n\nclass DrawLayerBuilder {\n  #drawLayer = null;\n  constructor(options) {\n    this.pageIndex = options.pageIndex;\n  }\n  async render(intent = \"display\") {\n    if (intent !== \"display\" || this.#drawLayer || this._cancelled) {\n      return;\n    }\n    this.#drawLayer = new pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.DrawLayer({\n      pageIndex: this.pageIndex\n    });\n  }\n  cancel() {\n    this._cancelled = true;\n    if (!this.#drawLayer) {\n      return;\n    }\n    this.#drawLayer.destroy();\n    this.#drawLayer = null;\n  }\n  setParent(parent) {\n    this.#drawLayer?.setParent(parent);\n  }\n  getDrawLayer() {\n    return this.#drawLayer;\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 5656:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   AutomationEventBus: () => (/* binding */ AutomationEventBus),\n/* harmony export */   EventBus: () => (/* binding */ EventBus),\n/* harmony export */   waitOnEventOrTimeout: () => (/* binding */ waitOnEventOrTimeout)\n/* harmony export */ });\n/* unused harmony export WaitOnType */\nconst WaitOnType = {\n  EVENT: \"event\",\n  TIMEOUT: \"timeout\"\n};\nasync function waitOnEventOrTimeout({\n  target,\n  name,\n  delay = 0\n}) {\n  if (typeof target !== \"object\" || !(name && typeof name === \"string\") || !(Number.isInteger(delay) && delay >= 0)) {\n    throw new Error(\"waitOnEventOrTimeout - invalid parameters.\");\n  }\n  const {\n    promise,\n    resolve\n  } = Promise.withResolvers();\n  const ac = new AbortController();\n  function handler(type) {\n    ac.abort();\n    clearTimeout(timeout);\n    resolve(type);\n  }\n  const evtMethod = target instanceof EventBus ? \"_on\" : \"addEventListener\";\n  target[evtMethod](name, handler.bind(null, WaitOnType.EVENT), {\n    signal: ac.signal\n  });\n  const timeout = setTimeout(handler.bind(null, WaitOnType.TIMEOUT), delay);\n  return promise;\n}\nclass EventBus {\n  #listeners = Object.create(null);\n  on(eventName, listener, options = null) {\n    this._on(eventName, listener, {\n      external: true,\n      once: options?.once,\n      signal: options?.signal\n    });\n  }\n  off(eventName, listener, options = null) {\n    this._off(eventName, listener);\n  }\n  dispatch(eventName, data) {\n    const eventListeners = this.#listeners[eventName];\n    if (!eventListeners || eventListeners.length === 0) {\n      return;\n    }\n    let externalListeners;\n    for (const {\n      listener,\n      external,\n      once\n    } of eventListeners.slice(0)) {\n      if (once) {\n        this._off(eventName, listener);\n      }\n      if (external) {\n        (externalListeners ||= []).push(listener);\n        continue;\n      }\n      listener(data);\n    }\n    if (externalListeners) {\n      for (const listener of externalListeners) {\n        listener(data);\n      }\n      externalListeners = null;\n    }\n  }\n  _on(eventName, listener, options = null) {\n    let rmAbort = null;\n    if (options?.signal instanceof AbortSignal) {\n      const {\n        signal\n      } = options;\n      if (signal.aborted) {\n        console.error(\"Cannot use an `aborted` signal.\");\n        return;\n      }\n      const onAbort = () => this._off(eventName, listener);\n      rmAbort = () => signal.removeEventListener(\"abort\", onAbort);\n      signal.addEventListener(\"abort\", onAbort);\n    }\n    const eventListeners = this.#listeners[eventName] ||= [];\n    eventListeners.push({\n      listener,\n      external: options?.external === true,\n      once: options?.once === true,\n      rmAbort\n    });\n  }\n  _off(eventName, listener, options = null) {\n    const eventListeners = this.#listeners[eventName];\n    if (!eventListeners) {\n      return;\n    }\n    for (let i = 0, ii = eventListeners.length; i < ii; i++) {\n      const evt = eventListeners[i];\n      if (evt.listener === listener) {\n        evt.rmAbort?.();\n        eventListeners.splice(i, 1);\n        return;\n      }\n    }\n  }\n}\nclass AutomationEventBus extends EventBus {\n  dispatch(eventName, data) {\n    throw new Error(\"Not implemented: AutomationEventBus.dispatch\");\n  }\n}\n\n\n/***/ }),\n\n/***/ 4290:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   BaseExternalServices: () => (/* binding */ BaseExternalServices)\n/* harmony export */ });\nclass BaseExternalServices {\n  constructor() {\n    if (this.constructor === BaseExternalServices) {\n      throw new Error(\"Cannot initialize BaseExternalServices.\");\n    }\n  }\n  updateFindControlState(data) {}\n  updateFindMatchesCount(data) {}\n  initPassiveLoading() {}\n  reportTelemetry(data) {}\n  async createL10n() {\n    throw new Error(\"Not implemented: createL10n\");\n  }\n  createScripting() {\n    throw new Error(\"Not implemented: createScripting\");\n  }\n  updateEditorStates(data) {\n    throw new Error(\"Not implemented: updateEditorStates\");\n  }\n  async getNimbusExperimentData() {}\n}\n\n\n/***/ }),\n\n/***/ 289:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   GenericScripting: () => (/* binding */ GenericScripting)\n/* harmony export */ });\n/* unused harmony export docProperties */\n/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__]);\npdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];\n\nasync function docProperties(pdfDocument) {\n  const url = \"\",\n    baseUrl = url.split(\"#\", 1)[0];\n  let {\n    info,\n    metadata,\n    contentDispositionFilename,\n    contentLength\n  } = await pdfDocument.getMetadata();\n  if (!contentLength) {\n    const {\n      length\n    } = await pdfDocument.getDownloadInfo();\n    contentLength = length;\n  }\n  return {\n    ...info,\n    baseURL: baseUrl,\n    filesize: contentLength,\n    filename: contentDispositionFilename || getPdfFilenameFromUrl(url),\n    metadata: metadata?.getRaw(),\n    authors: metadata?.get(\"dc:creator\"),\n    numPages: pdfDocument.numPages,\n    URL: url\n  };\n}\nclass GenericScripting {\n  constructor(sandboxBundleSrc) {\n    this._ready = new Promise((resolve, reject) => {\n      const sandbox = import( /*webpackIgnore: true*/sandboxBundleSrc);\n      sandbox.then(pdfjsSandbox => {\n        resolve(pdfjsSandbox.QuickJSSandbox());\n      }).catch(reject);\n    });\n  }\n  async createSandbox(data) {\n    const sandbox = await this._ready;\n    sandbox.create(data);\n  }\n  async dispatchEventInSandbox(event) {\n    const sandbox = await this._ready;\n    setTimeout(() => sandbox.dispatchEvent(event), 0);\n  }\n  async destroySandbox() {\n    const sandbox = await this._ready;\n    sandbox.nukeSandbox();\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 6750:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   ExternalServices: () => (/* binding */ ExternalServices),\n/* harmony export */   MLManager: () => (/* binding */ MLManager),\n/* harmony export */   Preferences: () => (/* binding */ Preferences),\n/* harmony export */   initCom: () => (/* binding */ initCom)\n/* harmony export */ });\n/* harmony import */ var _app_options_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9840);\n/* harmony import */ var _external_services_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(4290);\n/* harmony import */ var _preferences_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8224);\n/* harmony import */ var _genericl10n_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(410);\n/* harmony import */ var _generic_scripting_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(289);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([_genericl10n_js__WEBPACK_IMPORTED_MODULE_2__, _generic_scripting_js__WEBPACK_IMPORTED_MODULE_3__]);\n([_genericl10n_js__WEBPACK_IMPORTED_MODULE_2__, _generic_scripting_js__WEBPACK_IMPORTED_MODULE_3__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__);\n\n\n\n\n\nfunction initCom(app) {}\nclass Preferences extends _preferences_js__WEBPACK_IMPORTED_MODULE_1__.BasePreferences {\n  async _writeToStorage(prefObj) {\n    localStorage.setItem(\"pdfjs.preferences\", JSON.stringify(prefObj));\n  }\n  async _readFromStorage(prefObj) {\n    return {\n      prefs: JSON.parse(localStorage.getItem(\"pdfjs.preferences\"))\n    };\n  }\n}\nclass ExternalServices extends _external_services_js__WEBPACK_IMPORTED_MODULE_4__.BaseExternalServices {\n  async createL10n() {\n    return new _genericl10n_js__WEBPACK_IMPORTED_MODULE_2__.GenericL10n(_app_options_js__WEBPACK_IMPORTED_MODULE_0__.AppOptions.get(\"locale\"));\n  }\n  createScripting() {\n    return new _generic_scripting_js__WEBPACK_IMPORTED_MODULE_3__.GenericScripting(_app_options_js__WEBPACK_IMPORTED_MODULE_0__.AppOptions.get(\"sandboxBundleSrc\"));\n  }\n}\nclass MLManager {\n  async guess() {\n    return null;\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 410:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   GenericL10n: () => (/* binding */ GenericL10n)\n/* harmony export */ });\n/* harmony import */ var fluent_bundle__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(588);\n/* harmony import */ var fluent_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5273);\n/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2603);\n/* harmony import */ var _l10n_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4693);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_2__]);\npdfjs_lib__WEBPACK_IMPORTED_MODULE_2__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];\n\n\n\n\nfunction createBundle(lang, text) {\n  const resource = new fluent_bundle__WEBPACK_IMPORTED_MODULE_0__.FluentResource(text);\n  const bundle = new fluent_bundle__WEBPACK_IMPORTED_MODULE_0__.FluentBundle(lang);\n  const errors = bundle.addResource(resource);\n  if (errors.length) {\n    console.error(\"L10n errors\", errors);\n  }\n  return bundle;\n}\nclass GenericL10n extends _l10n_js__WEBPACK_IMPORTED_MODULE_3__.L10n {\n  constructor(lang) {\n    super({\n      lang\n    });\n    const generateBundles = !lang ? GenericL10n.#generateBundlesFallback.bind(GenericL10n, this.getLanguage()) : GenericL10n.#generateBundles.bind(GenericL10n, \"en-us\", this.getLanguage());\n    this._setL10n(new fluent_dom__WEBPACK_IMPORTED_MODULE_1__.DOMLocalization([], generateBundles));\n  }\n  static async *#generateBundles(defaultLang, baseLang) {\n    const {\n      baseURL,\n      paths\n    } = await this.#getPaths();\n    const langs = [baseLang];\n    if (defaultLang !== baseLang) {\n      const shortLang = baseLang.split(\"-\", 1)[0];\n      if (shortLang !== baseLang) {\n        langs.push(shortLang);\n      }\n      langs.push(defaultLang);\n    }\n    for (const lang of langs) {\n      const bundle = await this.#createBundle(lang, baseURL, paths);\n      if (bundle) {\n        yield bundle;\n      }\n      if (lang === \"en-us\") {\n        yield this.#createBundleFallback(lang);\n      }\n    }\n  }\n  static async #createBundle(lang, baseURL, paths) {\n    const path = paths[lang];\n    if (!path) {\n      return null;\n    }\n    const url = new URL(path, baseURL);\n    const text = await (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_2__.fetchData)(url, \"text\");\n    return createBundle(lang, text);\n  }\n  static async #getPaths() {\n    try {\n      const {\n        href\n      } = document.querySelector(`link[type=\"application/l10n\"]`);\n      const paths = await (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_2__.fetchData)(href, \"json\");\n      return {\n        baseURL: href.replace(/[^/]*$/, \"\") || \"./\",\n        paths\n      };\n    } catch {}\n    return {\n      baseURL: \"./\",\n      paths: Object.create(null)\n    };\n  }\n  static async *#generateBundlesFallback(lang) {\n    yield this.#createBundleFallback(lang);\n  }\n  static async #createBundleFallback(lang) {\n    const text = \"pdfjs-previous-button =\\n    .title = Previous Page\\npdfjs-previous-button-label = Previous\\npdfjs-next-button =\\n    .title = Next Page\\npdfjs-next-button-label = Next\\npdfjs-page-input =\\n    .title = Page\\npdfjs-of-pages = of { $pagesCount }\\npdfjs-page-of-pages = ({ $pageNumber } of { $pagesCount })\\npdfjs-zoom-out-button =\\n    .title = Zoom Out\\npdfjs-zoom-out-button-label = Zoom Out\\npdfjs-zoom-in-button =\\n    .title = Zoom In\\npdfjs-zoom-in-button-label = Zoom In\\npdfjs-zoom-select =\\n    .title = Zoom\\npdfjs-presentation-mode-button =\\n    .title = Switch to Presentation Mode\\npdfjs-presentation-mode-button-label = Presentation Mode\\npdfjs-open-file-button =\\n    .title = Open File\\npdfjs-open-file-button-label = Open\\npdfjs-print-button =\\n    .title = Print\\npdfjs-print-button-label = Print\\npdfjs-save-button =\\n    .title = Save\\npdfjs-save-button-label = Save\\npdfjs-download-button =\\n    .title = Download\\npdfjs-download-button-label = Download\\npdfjs-bookmark-button =\\n    .title = Current Page (View URL from Current Page)\\npdfjs-bookmark-button-label = Current Page\\npdfjs-tools-button =\\n    .title = Tools\\npdfjs-tools-button-label = Tools\\npdfjs-first-page-button =\\n    .title = Go to First Page\\npdfjs-first-page-button-label = Go to First Page\\npdfjs-last-page-button =\\n    .title = Go to Last Page\\npdfjs-last-page-button-label = Go to Last Page\\npdfjs-page-rotate-cw-button =\\n    .title = Rotate Clockwise\\npdfjs-page-rotate-cw-button-label = Rotate Clockwise\\npdfjs-page-rotate-ccw-button =\\n    .title = Rotate Counterclockwise\\npdfjs-page-rotate-ccw-button-label = Rotate Counterclockwise\\npdfjs-cursor-text-select-tool-button =\\n    .title = Enable Text Selection Tool\\npdfjs-cursor-text-select-tool-button-label = Text Selection Tool\\npdfjs-cursor-hand-tool-button =\\n    .title = Enable Hand Tool\\npdfjs-cursor-hand-tool-button-label = Hand Tool\\npdfjs-scroll-page-button =\\n    .title = Use Page Scrolling\\npdfjs-scroll-page-button-label = Page Scrolling\\npdfjs-scroll-vertical-button =\\n    .title = Use Vertical Scrolling\\npdfjs-scroll-vertical-button-label = Vertical Scrolling\\npdfjs-scroll-horizontal-button =\\n    .title = Use Horizontal Scrolling\\npdfjs-scroll-horizontal-button-label = Horizontal Scrolling\\npdfjs-scroll-wrapped-button =\\n    .title = Use Wrapped Scrolling\\npdfjs-scroll-wrapped-button-label = Wrapped Scrolling\\npdfjs-spread-none-button =\\n    .title = Do not join page spreads\\npdfjs-spread-none-button-label = No Spreads\\npdfjs-spread-odd-button =\\n    .title = Join page spreads starting with odd-numbered pages\\npdfjs-spread-odd-button-label = Odd Spreads\\npdfjs-spread-even-button =\\n    .title = Join page spreads starting with even-numbered pages\\npdfjs-spread-even-button-label = Even Spreads\\npdfjs-document-properties-button =\\n    .title = Document Properties\\u2026\\npdfjs-document-properties-button-label = Document Properties\\u2026\\npdfjs-document-properties-file-name = File name:\\npdfjs-document-properties-file-size = File size:\\npdfjs-document-properties-kb = { $size_kb } KB ({ $size_b } bytes)\\npdfjs-document-properties-mb = { $size_mb } MB ({ $size_b } bytes)\\npdfjs-document-properties-title = Title:\\npdfjs-document-properties-author = Author:\\npdfjs-document-properties-subject = Subject:\\npdfjs-document-properties-keywords = Keywords:\\npdfjs-document-properties-creation-date = Creation Date:\\npdfjs-document-properties-modification-date = Modification Date:\\npdfjs-document-properties-date-string = { $date }, { $time }\\npdfjs-document-properties-creator = Creator:\\npdfjs-document-properties-producer = PDF Producer:\\npdfjs-document-properties-version = PDF Version:\\npdfjs-document-properties-page-count = Page Count:\\npdfjs-document-properties-page-size = Page Size:\\npdfjs-document-properties-page-size-unit-inches = in\\npdfjs-document-properties-page-size-unit-millimeters = mm\\npdfjs-document-properties-page-size-orientation-portrait = portrait\\npdfjs-document-properties-page-size-orientation-landscape = landscape\\npdfjs-document-properties-page-size-name-a-three = A3\\npdfjs-document-properties-page-size-name-a-four = A4\\npdfjs-document-properties-page-size-name-letter = Letter\\npdfjs-document-properties-page-size-name-legal = Legal\\npdfjs-document-properties-page-size-dimension-string = { $width } \\xD7 { $height } { $unit } ({ $orientation })\\npdfjs-document-properties-page-size-dimension-name-string = { $width } \\xD7 { $height } { $unit } ({ $name }, { $orientation })\\npdfjs-document-properties-linearized = Fast Web View:\\npdfjs-document-properties-linearized-yes = Yes\\npdfjs-document-properties-linearized-no = No\\npdfjs-document-properties-close-button = Close\\npdfjs-print-progress-message = Preparing document for printing\\u2026\\npdfjs-print-progress-percent = { $progress }%\\npdfjs-print-progress-close-button = Cancel\\npdfjs-printing-not-supported = Warning: Printing is not fully supported by this browser.\\npdfjs-printing-not-ready = Warning: The PDF is not fully loaded for printing.\\npdfjs-toggle-sidebar-button =\\n    .title = Toggle Sidebar\\npdfjs-toggle-sidebar-notification-button =\\n    .title = Toggle Sidebar (document contains outline/attachments/layers)\\npdfjs-toggle-sidebar-button-label = Toggle Sidebar\\npdfjs-document-outline-button =\\n    .title = Show Document Outline (double-click to expand/collapse all items)\\npdfjs-document-outline-button-label = Document Outline\\npdfjs-attachments-button =\\n    .title = Show Attachments\\npdfjs-attachments-button-label = Attachments\\npdfjs-layers-button =\\n    .title = Show Layers (double-click to reset all layers to the default state)\\npdfjs-layers-button-label = Layers\\npdfjs-thumbs-button =\\n    .title = Show Thumbnails\\npdfjs-thumbs-button-label = Thumbnails\\npdfjs-current-outline-item-button =\\n    .title = Find Current Outline Item\\npdfjs-current-outline-item-button-label = Current Outline Item\\npdfjs-findbar-button =\\n    .title = Find in Document\\npdfjs-findbar-button-label = Find\\npdfjs-additional-layers = Additional Layers\\npdfjs-thumb-page-title =\\n    .title = Page { $page }\\npdfjs-thumb-page-canvas =\\n    .aria-label = Thumbnail of Page { $page }\\npdfjs-find-input =\\n    .title = Find\\n    .placeholder = Find in document\\u2026\\npdfjs-find-previous-button =\\n    .title = Find the previous occurrence of the phrase\\npdfjs-find-previous-button-label = Previous\\npdfjs-find-next-button =\\n    .title = Find the next occurrence of the phrase\\npdfjs-find-next-button-label = Next\\npdfjs-find-highlight-checkbox = Highlight All\\npdfjs-find-match-case-checkbox-label = Match Case\\npdfjs-find-match-diacritics-checkbox-label = Match Diacritics\\npdfjs-find-entire-word-checkbox-label = Whole Words\\npdfjs-find-reached-top = Reached top of document, continued from bottom\\npdfjs-find-reached-bottom = Reached end of document, continued from top\\npdfjs-find-match-count =\\n    { $total ->\\n        [one] { $current } of { $total } match\\n       *[other] { $current } of { $total } matches\\n    }\\npdfjs-find-match-count-limit =\\n    { $limit ->\\n        [one] More than { $limit } match\\n       *[other] More than { $limit } matches\\n    }\\npdfjs-find-not-found = Phrase not found\\npdfjs-page-scale-width = Page Width\\npdfjs-page-scale-fit = Page Fit\\npdfjs-page-scale-auto = Automatic Zoom\\npdfjs-page-scale-actual = Actual Size\\npdfjs-page-scale-percent = { $scale }%\\npdfjs-page-landmark =\\n    .aria-label = Page { $page }\\npdfjs-loading-error = An error occurred while loading the PDF.\\npdfjs-invalid-file-error = Invalid or corrupted PDF file.\\npdfjs-missing-file-error = Missing PDF file.\\npdfjs-unexpected-response-error = Unexpected server response.\\npdfjs-rendering-error = An error occurred while rendering the page.\\npdfjs-annotation-date-string = { $date }, { $time }\\npdfjs-text-annotation-type =\\n    .alt = [{ $type } Annotation]\\npdfjs-password-label = Enter the password to open this PDF file.\\npdfjs-password-invalid = Invalid password. Please try again.\\npdfjs-password-ok-button = OK\\npdfjs-password-cancel-button = Cancel\\npdfjs-web-fonts-disabled = Web fonts are disabled: unable to use embedded PDF fonts.\\npdfjs-editor-free-text-button =\\n    .title = Text\\npdfjs-editor-free-text-button-label = Text\\npdfjs-editor-ink-button =\\n    .title = Draw\\npdfjs-editor-ink-button-label = Draw\\npdfjs-editor-stamp-button =\\n    .title = Add or edit images\\npdfjs-editor-stamp-button-label = Add or edit images\\npdfjs-editor-highlight-button =\\n    .title = Highlight\\npdfjs-editor-highlight-button-label = Highlight\\npdfjs-highlight-floating-button1 =\\n    .title = Highlight\\n    .aria-label = Highlight\\npdfjs-highlight-floating-button-label = Highlight\\npdfjs-editor-remove-ink-button =\\n    .title = Remove drawing\\npdfjs-editor-remove-freetext-button =\\n    .title = Remove text\\npdfjs-editor-remove-stamp-button =\\n    .title = Remove image\\npdfjs-editor-remove-highlight-button =\\n    .title = Remove highlight\\npdfjs-editor-free-text-color-input = Color\\npdfjs-editor-free-text-size-input = Size\\npdfjs-editor-ink-color-input = Color\\npdfjs-editor-ink-thickness-input = Thickness\\npdfjs-editor-ink-opacity-input = Opacity\\npdfjs-editor-stamp-add-image-button =\\n    .title = Add image\\npdfjs-editor-stamp-add-image-button-label = Add image\\npdfjs-editor-free-highlight-thickness-input = Thickness\\npdfjs-editor-free-highlight-thickness-title =\\n    .title = Change thickness when highlighting items other than text\\npdfjs-free-text =\\n    .aria-label = Text Editor\\npdfjs-free-text-default-content = Start typing\\u2026\\npdfjs-ink =\\n    .aria-label = Draw Editor\\npdfjs-ink-canvas =\\n    .aria-label = User-created image\\npdfjs-editor-alt-text-button-label = Alt text\\npdfjs-editor-alt-text-edit-button-label = Edit alt text\\npdfjs-editor-alt-text-dialog-label = Choose an option\\npdfjs-editor-alt-text-dialog-description = Alt text (alternative text) helps when people can\\u2019t see the image or when it doesn\\u2019t load.\\npdfjs-editor-alt-text-add-description-label = Add a description\\npdfjs-editor-alt-text-add-description-description = Aim for 1-2 sentences that describe the subject, setting, or actions.\\npdfjs-editor-alt-text-mark-decorative-label = Mark as decorative\\npdfjs-editor-alt-text-mark-decorative-description = This is used for ornamental images, like borders or watermarks.\\npdfjs-editor-alt-text-cancel-button = Cancel\\npdfjs-editor-alt-text-save-button = Save\\npdfjs-editor-alt-text-decorative-tooltip = Marked as decorative\\npdfjs-editor-alt-text-textarea =\\n    .placeholder = For example, \\u201CA young man sits down at a table to eat a meal\\u201D\\npdfjs-editor-resizer-label-top-left = Top left corner \\u2014 resize\\npdfjs-editor-resizer-label-top-middle = Top middle \\u2014 resize\\npdfjs-editor-resizer-label-top-right = Top right corner \\u2014 resize\\npdfjs-editor-resizer-label-middle-right = Middle right \\u2014 resize\\npdfjs-editor-resizer-label-bottom-right = Bottom right corner \\u2014 resize\\npdfjs-editor-resizer-label-bottom-middle = Bottom middle \\u2014 resize\\npdfjs-editor-resizer-label-bottom-left = Bottom left corner \\u2014 resize\\npdfjs-editor-resizer-label-middle-left = Middle left \\u2014 resize\\npdfjs-editor-highlight-colorpicker-label = Highlight color\\npdfjs-editor-colorpicker-button =\\n    .title = Change color\\npdfjs-editor-colorpicker-dropdown =\\n    .aria-label = Color choices\\npdfjs-editor-colorpicker-yellow =\\n    .title = Yellow\\npdfjs-editor-colorpicker-green =\\n    .title = Green\\npdfjs-editor-colorpicker-blue =\\n    .title = Blue\\npdfjs-editor-colorpicker-pink =\\n    .title = Pink\\npdfjs-editor-colorpicker-red =\\n    .title = Red\\npdfjs-editor-highlight-show-all-button-label = Show all\\npdfjs-editor-highlight-show-all-button =\\n    .title = Show all\";\n    return createBundle(lang, text);\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 2640:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   GrabToPan: () => (/* binding */ GrabToPan)\n/* harmony export */ });\nconst CSS_CLASS_GRAB = \"grab-to-pan-grab\";\nclass GrabToPan {\n  constructor({\n    element\n  }) {\n    this.element = element;\n    this.document = element.ownerDocument;\n    this.activate = this.activate.bind(this);\n    this.deactivate = this.deactivate.bind(this);\n    this.toggle = this.toggle.bind(this);\n    this._onMouseDown = this.#onMouseDown.bind(this);\n    this._onMouseMove = this.#onMouseMove.bind(this);\n    this._endPan = this.#endPan.bind(this);\n    const overlay = this.overlay = document.createElement(\"div\");\n    overlay.className = \"grab-to-pan-grabbing\";\n  }\n  activate() {\n    if (!this.active) {\n      this.active = true;\n      this.element.addEventListener(\"mousedown\", this._onMouseDown, true);\n      this.element.classList.add(CSS_CLASS_GRAB);\n    }\n  }\n  deactivate() {\n    if (this.active) {\n      this.active = false;\n      this.element.removeEventListener(\"mousedown\", this._onMouseDown, true);\n      this._endPan();\n      this.element.classList.remove(CSS_CLASS_GRAB);\n    }\n  }\n  toggle() {\n    if (this.active) {\n      this.deactivate();\n    } else {\n      this.activate();\n    }\n  }\n  ignoreTarget(node) {\n    return node.matches(\"a[href], a[href] *, input, textarea, button, button *, select, option\");\n  }\n  #onMouseDown(event) {\n    if (event.button !== 0 || this.ignoreTarget(event.target)) {\n      return;\n    }\n    if (event.originalTarget) {\n      try {\n        event.originalTarget.tagName;\n      } catch {\n        return;\n      }\n    }\n    this.scrollLeftStart = this.element.scrollLeft;\n    this.scrollTopStart = this.element.scrollTop;\n    this.clientXStart = event.clientX;\n    this.clientYStart = event.clientY;\n    this.document.addEventListener(\"mousemove\", this._onMouseMove, true);\n    this.document.addEventListener(\"mouseup\", this._endPan, true);\n    this.element.addEventListener(\"scroll\", this._endPan, true);\n    event.preventDefault();\n    event.stopPropagation();\n    const focusedElement = document.activeElement;\n    if (focusedElement && !focusedElement.contains(event.target)) {\n      focusedElement.blur();\n    }\n  }\n  #onMouseMove(event) {\n    this.element.removeEventListener(\"scroll\", this._endPan, true);\n    if (!(event.buttons & 1)) {\n      this._endPan();\n      return;\n    }\n    const xDiff = event.clientX - this.clientXStart;\n    const yDiff = event.clientY - this.clientYStart;\n    this.element.scrollTo({\n      top: this.scrollTopStart - yDiff,\n      left: this.scrollLeftStart - xDiff,\n      behavior: \"instant\"\n    });\n    if (!this.overlay.parentNode) {\n      document.body.append(this.overlay);\n    }\n  }\n  #endPan() {\n    this.element.removeEventListener(\"scroll\", this._endPan, true);\n    this.document.removeEventListener(\"mousemove\", this._onMouseMove, true);\n    this.document.removeEventListener(\"mouseup\", this._endPan, true);\n    this.overlay.remove();\n  }\n}\n\n\n/***/ }),\n\n/***/ 4693:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   L10n: () => (/* binding */ L10n)\n/* harmony export */ });\n/* unused harmony export GenericL10n */\nclass L10n {\n  #dir;\n  #lang;\n  #l10n;\n  constructor({\n    lang,\n    isRTL\n  }, l10n = null) {\n    this.#lang = L10n.#fixupLangCode(lang);\n    this.#l10n = l10n;\n    this.#dir = isRTL ?? L10n.#isRTL(this.#lang) ? \"rtl\" : \"ltr\";\n  }\n  _setL10n(l10n) {\n    this.#l10n = l10n;\n  }\n  getLanguage() {\n    return this.#lang;\n  }\n  getDirection() {\n    return this.#dir;\n  }\n  async get(ids, args = null, fallback) {\n    if (Array.isArray(ids)) {\n      ids = ids.map(id => ({\n        id\n      }));\n      const messages = await this.#l10n.formatMessages(ids);\n      return messages.map(message => message.value);\n    }\n    const messages = await this.#l10n.formatMessages([{\n      id: ids,\n      args\n    }]);\n    return messages?.[0].value || fallback;\n  }\n  async translate(element) {\n    try {\n      this.#l10n.connectRoot(element);\n      await this.#l10n.translateRoots();\n    } catch {}\n  }\n  pause() {\n    this.#l10n.pauseObserving();\n  }\n  resume() {\n    this.#l10n.resumeObserving();\n  }\n  static #fixupLangCode(langCode) {\n    langCode = langCode?.toLowerCase() || \"en-us\";\n    const PARTIAL_LANG_CODES = {\n      en: \"en-us\",\n      es: \"es-es\",\n      fy: \"fy-nl\",\n      ga: \"ga-ie\",\n      gu: \"gu-in\",\n      hi: \"hi-in\",\n      hy: \"hy-am\",\n      nb: \"nb-no\",\n      ne: \"ne-np\",\n      nn: \"nn-no\",\n      pa: \"pa-in\",\n      pt: \"pt-pt\",\n      sv: \"sv-se\",\n      zh: \"zh-cn\"\n    };\n    return PARTIAL_LANG_CODES[langCode] || langCode;\n  }\n  static #isRTL(lang) {\n    const shortCode = lang.split(\"-\", 1)[0];\n    return [\"ar\", \"he\", \"fa\", \"ps\", \"ur\"].includes(shortCode);\n  }\n}\nconst GenericL10n = null;\n\n\n/***/ }),\n\n/***/ 6174:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   OverlayManager: () => (/* binding */ OverlayManager)\n/* harmony export */ });\nclass OverlayManager {\n  #overlays = new WeakMap();\n  #active = null;\n  get active() {\n    return this.#active;\n  }\n  async register(dialog, canForceClose = false) {\n    if (typeof dialog !== \"object\") {\n      throw new Error(\"Not enough parameters.\");\n    } else if (this.#overlays.has(dialog)) {\n      throw new Error(\"The overlay is already registered.\");\n    }\n    this.#overlays.set(dialog, {\n      canForceClose\n    });\n    dialog.addEventListener(\"cancel\", evt => {\n      this.#active = null;\n    });\n  }\n  async open(dialog) {\n    if (!this.#overlays.has(dialog)) {\n      throw new Error(\"The overlay does not exist.\");\n    } else if (this.#active) {\n      if (this.#active === dialog) {\n        throw new Error(\"The overlay is already active.\");\n      } else if (this.#overlays.get(dialog).canForceClose) {\n        await this.close();\n      } else {\n        throw new Error(\"Another overlay is currently active.\");\n      }\n    }\n    this.#active = dialog;\n    dialog.showModal();\n  }\n  async close(dialog = this.#active) {\n    if (!this.#overlays.has(dialog)) {\n      throw new Error(\"The overlay does not exist.\");\n    } else if (!this.#active) {\n      throw new Error(\"The overlay is currently not active.\");\n    } else if (this.#active !== dialog) {\n      throw new Error(\"Another overlay is currently active.\");\n    }\n    dialog.close();\n    this.#active = null;\n  }\n}\n\n\n/***/ }),\n\n/***/ 2690:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   PasswordPrompt: () => (/* binding */ PasswordPrompt)\n/* harmony export */ });\n/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__]);\npdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];\n\nclass PasswordPrompt {\n  #activeCapability = null;\n  #updateCallback = null;\n  #reason = null;\n  constructor(options, overlayManager, isViewerEmbedded = false) {\n    this.dialog = options.dialog;\n    this.label = options.label;\n    this.input = options.input;\n    this.submitButton = options.submitButton;\n    this.cancelButton = options.cancelButton;\n    this.overlayManager = overlayManager;\n    this._isViewerEmbedded = isViewerEmbedded;\n    this.submitButton.addEventListener(\"click\", this.#verify.bind(this));\n    this.cancelButton.addEventListener(\"click\", this.close.bind(this));\n    this.input.addEventListener(\"keydown\", e => {\n      if (e.keyCode === 13) {\n        this.#verify();\n      }\n    });\n    this.overlayManager.register(this.dialog, true);\n    this.dialog.addEventListener(\"close\", this.#cancel.bind(this));\n  }\n  async open() {\n    await this.#activeCapability?.promise;\n    this.#activeCapability = Promise.withResolvers();\n    try {\n      await this.overlayManager.open(this.dialog);\n    } catch (ex) {\n      this.#activeCapability.resolve();\n      throw ex;\n    }\n    const passwordIncorrect = this.#reason === pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PasswordResponses.INCORRECT_PASSWORD;\n    if (!this._isViewerEmbedded || passwordIncorrect) {\n      this.input.focus();\n    }\n    this.label.setAttribute(\"data-l10n-id\", `pdfjs-password-${passwordIncorrect ? \"invalid\" : \"label\"}`);\n  }\n  async close() {\n    if (this.overlayManager.active === this.dialog) {\n      this.overlayManager.close(this.dialog);\n    }\n  }\n  #verify() {\n    const password = this.input.value;\n    if (password?.length > 0) {\n      this.#invokeCallback(password);\n    }\n  }\n  #cancel() {\n    this.#invokeCallback(new Error(\"PasswordPrompt cancelled.\"));\n    this.#activeCapability.resolve();\n  }\n  #invokeCallback(password) {\n    if (!this.#updateCallback) {\n      return;\n    }\n    this.close();\n    this.input.value = \"\";\n    this.#updateCallback(password);\n    this.#updateCallback = null;\n  }\n  async setUpdateCallback(updateCallback, reason) {\n    if (this.#activeCapability) {\n      await this.#activeCapability.promise;\n    }\n    this.#updateCallback = updateCallback;\n    this.#reason = reason;\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 9251:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   PDFAttachmentViewer: () => (/* binding */ PDFAttachmentViewer)\n/* harmony export */ });\n/* harmony import */ var _base_tree_viewer_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2961);\n/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2603);\n/* harmony import */ var _event_utils_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5656);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__]);\npdfjs_lib__WEBPACK_IMPORTED_MODULE_1__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];\n\n\n\nclass PDFAttachmentViewer extends _base_tree_viewer_js__WEBPACK_IMPORTED_MODULE_0__.BaseTreeViewer {\n  constructor(options) {\n    super(options);\n    this.downloadManager = options.downloadManager;\n    this.eventBus._on(\"fileattachmentannotation\", this.#appendAttachment.bind(this));\n  }\n  reset(keepRenderedCapability = false) {\n    super.reset();\n    this._attachments = null;\n    if (!keepRenderedCapability) {\n      this._renderedCapability = Promise.withResolvers();\n    }\n    this._pendingDispatchEvent = false;\n  }\n  async _dispatchEvent(attachmentsCount) {\n    this._renderedCapability.resolve();\n    if (attachmentsCount === 0 && !this._pendingDispatchEvent) {\n      this._pendingDispatchEvent = true;\n      await (0,_event_utils_js__WEBPACK_IMPORTED_MODULE_2__.waitOnEventOrTimeout)({\n        target: this.eventBus,\n        name: \"annotationlayerrendered\",\n        delay: 1000\n      });\n      if (!this._pendingDispatchEvent) {\n        return;\n      }\n    }\n    this._pendingDispatchEvent = false;\n    this.eventBus.dispatch(\"attachmentsloaded\", {\n      source: this,\n      attachmentsCount\n    });\n  }\n  _bindLink(element, {\n    content,\n    filename\n  }) {\n    element.onclick = () => {\n      this.downloadManager.openOrDownloadData(content, filename);\n      return false;\n    };\n  }\n  render({\n    attachments,\n    keepRenderedCapability = false\n  }) {\n    if (this._attachments) {\n      this.reset(keepRenderedCapability);\n    }\n    this._attachments = attachments || null;\n    if (!attachments) {\n      this._dispatchEvent(0);\n      return;\n    }\n    const fragment = document.createDocumentFragment();\n    let attachmentsCount = 0;\n    for (const name in attachments) {\n      const item = attachments[name];\n      const content = item.content,\n        filename = (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.getFilenameFromUrl)(item.filename, true);\n      const div = document.createElement(\"div\");\n      div.className = \"treeItem\";\n      const element = document.createElement(\"a\");\n      this._bindLink(element, {\n        content,\n        filename\n      });\n      element.textContent = this._normalizeTextContent(filename);\n      div.append(element);\n      fragment.append(div);\n      attachmentsCount++;\n    }\n    this._finishRendering(fragment, attachmentsCount);\n  }\n  #appendAttachment({\n    filename,\n    content\n  }) {\n    const renderedPromise = this._renderedCapability.promise;\n    renderedPromise.then(() => {\n      if (renderedPromise !== this._renderedCapability.promise) {\n        return;\n      }\n      const attachments = this._attachments || Object.create(null);\n      for (const name in attachments) {\n        if (filename === name) {\n          return;\n        }\n      }\n      attachments[filename] = {\n        filename,\n        content\n      };\n      this.render({\n        attachments,\n        keepRenderedCapability: true\n      });\n    });\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 5993:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   PDFCursorTools: () => (/* binding */ PDFCursorTools)\n/* harmony export */ });\n/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603);\n/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7256);\n/* harmony import */ var _grab_to_pan_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2640);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__]);\npdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];\n\n\n\nclass PDFCursorTools {\n  #active = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.CursorTool.SELECT;\n  #prevActive = null;\n  constructor({\n    container,\n    eventBus,\n    cursorToolOnLoad = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.CursorTool.SELECT\n  }) {\n    this.container = container;\n    this.eventBus = eventBus;\n    this.#addEventListeners();\n    Promise.resolve().then(() => {\n      this.switchTool(cursorToolOnLoad);\n    });\n  }\n  get activeTool() {\n    return this.#active;\n  }\n  switchTool(tool) {\n    if (this.#prevActive !== null) {\n      return;\n    }\n    if (tool === this.#active) {\n      return;\n    }\n    const disableActiveTool = () => {\n      switch (this.#active) {\n        case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.CursorTool.SELECT:\n          break;\n        case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.CursorTool.HAND:\n          this._handTool.deactivate();\n          break;\n        case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.CursorTool.ZOOM:\n      }\n    };\n    switch (tool) {\n      case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.CursorTool.SELECT:\n        disableActiveTool();\n        break;\n      case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.CursorTool.HAND:\n        disableActiveTool();\n        this._handTool.activate();\n        break;\n      case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.CursorTool.ZOOM:\n      default:\n        console.error(`switchTool: \"${tool}\" is an unsupported value.`);\n        return;\n    }\n    this.#active = tool;\n    this.eventBus.dispatch(\"cursortoolchanged\", {\n      source: this,\n      tool\n    });\n  }\n  #addEventListeners() {\n    this.eventBus._on(\"switchcursortool\", evt => {\n      if (!evt.reset) {\n        this.switchTool(evt.tool);\n      } else if (this.#prevActive !== null) {\n        annotationEditorMode = pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE;\n        presentationModeState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.PresentationModeState.NORMAL;\n        enableActive();\n      }\n    });\n    let annotationEditorMode = pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE,\n      presentationModeState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.PresentationModeState.NORMAL;\n    const disableActive = () => {\n      const prevActive = this.#active;\n      this.switchTool(_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.CursorTool.SELECT);\n      this.#prevActive ??= prevActive;\n    };\n    const enableActive = () => {\n      const prevActive = this.#prevActive;\n      if (prevActive !== null && annotationEditorMode === pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE && presentationModeState === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.PresentationModeState.NORMAL) {\n        this.#prevActive = null;\n        this.switchTool(prevActive);\n      }\n    };\n    this.eventBus._on(\"annotationeditormodechanged\", ({\n      mode\n    }) => {\n      annotationEditorMode = mode;\n      if (mode === pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE) {\n        enableActive();\n      } else {\n        disableActive();\n      }\n    });\n    this.eventBus._on(\"presentationmodechanged\", ({\n      state\n    }) => {\n      presentationModeState = state;\n      if (state === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.PresentationModeState.NORMAL) {\n        enableActive();\n      } else if (state === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.PresentationModeState.FULLSCREEN) {\n        disableActive();\n      }\n    });\n  }\n  get _handTool() {\n    return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, \"_handTool\", new _grab_to_pan_js__WEBPACK_IMPORTED_MODULE_2__.GrabToPan({\n      element: this.container\n    }));\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 164:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   PDFDocumentProperties: () => (/* binding */ PDFDocumentProperties)\n/* harmony export */ });\n/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256);\n/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2603);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__]);\npdfjs_lib__WEBPACK_IMPORTED_MODULE_1__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];\n\n\nconst DEFAULT_FIELD_CONTENT = \"-\";\nconst NON_METRIC_LOCALES = [\"en-us\", \"en-lr\", \"my\"];\nconst US_PAGE_NAMES = {\n  \"8.5x11\": \"letter\",\n  \"8.5x14\": \"legal\"\n};\nconst METRIC_PAGE_NAMES = {\n  \"297x420\": \"a-three\",\n  \"210x297\": \"a-four\"\n};\nfunction getPageName(size, isPortrait, pageNames) {\n  const width = isPortrait ? size.width : size.height;\n  const height = isPortrait ? size.height : size.width;\n  return pageNames[`${width}x${height}`];\n}\nclass PDFDocumentProperties {\n  #fieldData = null;\n  constructor({\n    dialog,\n    fields,\n    closeButton\n  }, overlayManager, eventBus, l10n, fileNameLookup) {\n    this.dialog = dialog;\n    this.fields = fields;\n    this.overlayManager = overlayManager;\n    this.l10n = l10n;\n    this._fileNameLookup = fileNameLookup;\n    this.#reset();\n    closeButton.addEventListener(\"click\", this.close.bind(this));\n    this.overlayManager.register(this.dialog);\n    eventBus._on(\"pagechanging\", evt => {\n      this._currentPageNumber = evt.pageNumber;\n    });\n    eventBus._on(\"rotationchanging\", evt => {\n      this._pagesRotation = evt.pagesRotation;\n    });\n    this._isNonMetricLocale = NON_METRIC_LOCALES.includes(l10n.getLanguage());\n  }\n  async open() {\n    await Promise.all([this.overlayManager.open(this.dialog), this._dataAvailableCapability.promise]);\n    const currentPageNumber = this._currentPageNumber;\n    const pagesRotation = this._pagesRotation;\n    if (this.#fieldData && currentPageNumber === this.#fieldData._currentPageNumber && pagesRotation === this.#fieldData._pagesRotation) {\n      this.#updateUI();\n      return;\n    }\n    const {\n      info,\n      contentLength\n    } = await this.pdfDocument.getMetadata();\n    const [fileName, fileSize, creationDate, modificationDate, pageSize, isLinearized] = await Promise.all([this._fileNameLookup(), this.#parseFileSize(contentLength), this.#parseDate(info.CreationDate), this.#parseDate(info.ModDate), this.pdfDocument.getPage(currentPageNumber).then(pdfPage => {\n      return this.#parsePageSize((0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.getPageSizeInches)(pdfPage), pagesRotation);\n    }), this.#parseLinearization(info.IsLinearized)]);\n    this.#fieldData = Object.freeze({\n      fileName,\n      fileSize,\n      title: info.Title,\n      author: info.Author,\n      subject: info.Subject,\n      keywords: info.Keywords,\n      creationDate,\n      modificationDate,\n      creator: info.Creator,\n      producer: info.Producer,\n      version: info.PDFFormatVersion,\n      pageCount: this.pdfDocument.numPages,\n      pageSize,\n      linearized: isLinearized,\n      _currentPageNumber: currentPageNumber,\n      _pagesRotation: pagesRotation\n    });\n    this.#updateUI();\n    const {\n      length\n    } = await this.pdfDocument.getDownloadInfo();\n    if (contentLength === length) {\n      return;\n    }\n    const data = Object.assign(Object.create(null), this.#fieldData);\n    data.fileSize = await this.#parseFileSize(length);\n    this.#fieldData = Object.freeze(data);\n    this.#updateUI();\n  }\n  async close() {\n    this.overlayManager.close(this.dialog);\n  }\n  setDocument(pdfDocument) {\n    if (this.pdfDocument) {\n      this.#reset();\n      this.#updateUI(true);\n    }\n    if (!pdfDocument) {\n      return;\n    }\n    this.pdfDocument = pdfDocument;\n    this._dataAvailableCapability.resolve();\n  }\n  #reset() {\n    this.pdfDocument = null;\n    this.#fieldData = null;\n    this._dataAvailableCapability = Promise.withResolvers();\n    this._currentPageNumber = 1;\n    this._pagesRotation = 0;\n  }\n  #updateUI(reset = false) {\n    if (reset || !this.#fieldData) {\n      for (const id in this.fields) {\n        this.fields[id].textContent = DEFAULT_FIELD_CONTENT;\n      }\n      return;\n    }\n    if (this.overlayManager.active !== this.dialog) {\n      return;\n    }\n    for (const id in this.fields) {\n      const content = this.#fieldData[id];\n      this.fields[id].textContent = content || content === 0 ? content : DEFAULT_FIELD_CONTENT;\n    }\n  }\n  async #parseFileSize(fileSize = 0) {\n    const kb = fileSize / 1024,\n      mb = kb / 1024;\n    if (!kb) {\n      return undefined;\n    }\n    return this.l10n.get(`pdfjs-document-properties-${mb >= 1 ? \"mb\" : \"kb\"}`, {\n      size_mb: mb >= 1 && (+mb.toPrecision(3)).toLocaleString(),\n      size_kb: mb < 1 && (+kb.toPrecision(3)).toLocaleString(),\n      size_b: fileSize.toLocaleString()\n    });\n  }\n  async #parsePageSize(pageSizeInches, pagesRotation) {\n    if (!pageSizeInches) {\n      return undefined;\n    }\n    if (pagesRotation % 180 !== 0) {\n      pageSizeInches = {\n        width: pageSizeInches.height,\n        height: pageSizeInches.width\n      };\n    }\n    const isPortrait = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.isPortraitOrientation)(pageSizeInches);\n    let sizeInches = {\n      width: Math.round(pageSizeInches.width * 100) / 100,\n      height: Math.round(pageSizeInches.height * 100) / 100\n    };\n    let sizeMillimeters = {\n      width: Math.round(pageSizeInches.width * 25.4 * 10) / 10,\n      height: Math.round(pageSizeInches.height * 25.4 * 10) / 10\n    };\n    let rawName = getPageName(sizeInches, isPortrait, US_PAGE_NAMES) || getPageName(sizeMillimeters, isPortrait, METRIC_PAGE_NAMES);\n    if (!rawName && !(Number.isInteger(sizeMillimeters.width) && Number.isInteger(sizeMillimeters.height))) {\n      const exactMillimeters = {\n        width: pageSizeInches.width * 25.4,\n        height: pageSizeInches.height * 25.4\n      };\n      const intMillimeters = {\n        width: Math.round(sizeMillimeters.width),\n        height: Math.round(sizeMillimeters.height)\n      };\n      if (Math.abs(exactMillimeters.width - intMillimeters.width) < 0.1 && Math.abs(exactMillimeters.height - intMillimeters.height) < 0.1) {\n        rawName = getPageName(intMillimeters, isPortrait, METRIC_PAGE_NAMES);\n        if (rawName) {\n          sizeInches = {\n            width: Math.round(intMillimeters.width / 25.4 * 100) / 100,\n            height: Math.round(intMillimeters.height / 25.4 * 100) / 100\n          };\n          sizeMillimeters = intMillimeters;\n        }\n      }\n    }\n    const [{\n      width,\n      height\n    }, unit, name, orientation] = await Promise.all([this._isNonMetricLocale ? sizeInches : sizeMillimeters, this.l10n.get(`pdfjs-document-properties-page-size-unit-${this._isNonMetricLocale ? \"inches\" : \"millimeters\"}`), rawName && this.l10n.get(`pdfjs-document-properties-page-size-name-${rawName}`), this.l10n.get(`pdfjs-document-properties-page-size-orientation-${isPortrait ? \"portrait\" : \"landscape\"}`)]);\n    return this.l10n.get(`pdfjs-document-properties-page-size-dimension-${name ? \"name-\" : \"\"}string`, {\n      width: width.toLocaleString(),\n      height: height.toLocaleString(),\n      unit,\n      name,\n      orientation\n    });\n  }\n  async #parseDate(inputDate) {\n    const dateObject = pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.PDFDateString.toDateObject(inputDate);\n    if (!dateObject) {\n      return undefined;\n    }\n    return this.l10n.get(\"pdfjs-document-properties-date-string\", {\n      date: dateObject.toLocaleDateString(),\n      time: dateObject.toLocaleTimeString()\n    });\n  }\n  #parseLinearization(isLinearized) {\n    return this.l10n.get(`pdfjs-document-properties-linearized-${isLinearized ? \"yes\" : \"no\"}`);\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 2226:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   PDFFindBar: () => (/* binding */ PDFFindBar)\n/* harmony export */ });\n/* harmony import */ var _pdf_find_controller_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9814);\n/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7256);\n\n\nconst MATCHES_COUNT_LIMIT = 1000;\nclass PDFFindBar {\n  #resizeObserver = new ResizeObserver(this.#resizeObserverCallback.bind(this));\n  constructor(options, eventBus) {\n    this.opened = false;\n    this.bar = options.bar;\n    this.toggleButton = options.toggleButton;\n    this.findField = options.findField;\n    this.highlightAll = options.highlightAllCheckbox;\n    this.caseSensitive = options.caseSensitiveCheckbox;\n    this.matchDiacritics = options.matchDiacriticsCheckbox;\n    this.entireWord = options.entireWordCheckbox;\n    this.findMsg = options.findMsg;\n    this.findResultsCount = options.findResultsCount;\n    this.findPreviousButton = options.findPreviousButton;\n    this.findNextButton = options.findNextButton;\n    this.eventBus = eventBus;\n    this.toggleButton.addEventListener(\"click\", () => {\n      this.toggle();\n    });\n    this.findField.addEventListener(\"input\", () => {\n      this.dispatchEvent(\"\");\n    });\n    this.bar.addEventListener(\"keydown\", e => {\n      switch (e.keyCode) {\n        case 13:\n          if (e.target === this.findField) {\n            this.dispatchEvent(\"again\", e.shiftKey);\n          }\n          break;\n        case 27:\n          this.close();\n          break;\n      }\n    });\n    this.findPreviousButton.addEventListener(\"click\", () => {\n      this.dispatchEvent(\"again\", true);\n    });\n    this.findNextButton.addEventListener(\"click\", () => {\n      this.dispatchEvent(\"again\", false);\n    });\n    this.highlightAll.addEventListener(\"click\", () => {\n      this.dispatchEvent(\"highlightallchange\");\n    });\n    this.caseSensitive.addEventListener(\"click\", () => {\n      this.dispatchEvent(\"casesensitivitychange\");\n    });\n    this.entireWord.addEventListener(\"click\", () => {\n      this.dispatchEvent(\"entirewordchange\");\n    });\n    this.matchDiacritics.addEventListener(\"click\", () => {\n      this.dispatchEvent(\"diacriticmatchingchange\");\n    });\n  }\n  reset() {\n    this.updateUIState();\n  }\n  dispatchEvent(type, findPrev = false) {\n    this.eventBus.dispatch(\"find\", {\n      source: this,\n      type,\n      query: this.findField.value,\n      caseSensitive: this.caseSensitive.checked,\n      entireWord: this.entireWord.checked,\n      highlightAll: this.highlightAll.checked,\n      findPrevious: findPrev,\n      matchDiacritics: this.matchDiacritics.checked\n    });\n  }\n  updateUIState(state, previous, matchesCount) {\n    const {\n      findField,\n      findMsg\n    } = this;\n    let findMsgId = \"\",\n      status = \"\";\n    switch (state) {\n      case _pdf_find_controller_js__WEBPACK_IMPORTED_MODULE_0__.FindState.FOUND:\n        break;\n      case _pdf_find_controller_js__WEBPACK_IMPORTED_MODULE_0__.FindState.PENDING:\n        status = \"pending\";\n        break;\n      case _pdf_find_controller_js__WEBPACK_IMPORTED_MODULE_0__.FindState.NOT_FOUND:\n        findMsgId = \"pdfjs-find-not-found\";\n        status = \"notFound\";\n        break;\n      case _pdf_find_controller_js__WEBPACK_IMPORTED_MODULE_0__.FindState.WRAPPED:\n        findMsgId = `pdfjs-find-reached-${previous ? \"top\" : \"bottom\"}`;\n        break;\n    }\n    findField.setAttribute(\"data-status\", status);\n    findField.setAttribute(\"aria-invalid\", state === _pdf_find_controller_js__WEBPACK_IMPORTED_MODULE_0__.FindState.NOT_FOUND);\n    findMsg.setAttribute(\"data-status\", status);\n    if (findMsgId) {\n      findMsg.setAttribute(\"data-l10n-id\", findMsgId);\n    } else {\n      findMsg.removeAttribute(\"data-l10n-id\");\n      findMsg.textContent = \"\";\n    }\n    this.updateResultsCount(matchesCount);\n  }\n  updateResultsCount({\n    current = 0,\n    total = 0\n  } = {}) {\n    const {\n      findResultsCount\n    } = this;\n    if (total > 0) {\n      const limit = MATCHES_COUNT_LIMIT;\n      findResultsCount.setAttribute(\"data-l10n-id\", `pdfjs-find-match-count${total > limit ? \"-limit\" : \"\"}`);\n      findResultsCount.setAttribute(\"data-l10n-args\", JSON.stringify({\n        limit,\n        current,\n        total\n      }));\n    } else {\n      findResultsCount.removeAttribute(\"data-l10n-id\");\n      findResultsCount.textContent = \"\";\n    }\n  }\n  open() {\n    if (!this.opened) {\n      this.#resizeObserver.observe(this.bar.parentNode);\n      this.#resizeObserver.observe(this.bar);\n      this.opened = true;\n      (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.toggleExpandedBtn)(this.toggleButton, true, this.bar);\n    }\n    this.findField.select();\n    this.findField.focus();\n  }\n  close() {\n    if (!this.opened) {\n      return;\n    }\n    this.#resizeObserver.disconnect();\n    this.opened = false;\n    (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.toggleExpandedBtn)(this.toggleButton, false, this.bar);\n    this.eventBus.dispatch(\"findbarclose\", {\n      source: this\n    });\n  }\n  toggle() {\n    if (this.opened) {\n      this.close();\n    } else {\n      this.open();\n    }\n  }\n  #resizeObserverCallback(entries) {\n    const {\n      bar\n    } = this;\n    bar.classList.remove(\"wrapContainers\");\n    const findbarHeight = bar.clientHeight;\n    const inputContainerHeight = bar.firstElementChild.clientHeight;\n    if (findbarHeight > inputContainerHeight) {\n      bar.classList.add(\"wrapContainers\");\n    }\n  }\n}\n\n\n/***/ }),\n\n/***/ 9814:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, {\n  FindState: () => (/* binding */ FindState),\n  PDFFindController: () => (/* binding */ PDFFindController)\n});\n\n// EXTERNAL MODULE: ./web/ui_utils.js\nvar ui_utils = __webpack_require__(7256);\n;// CONCATENATED MODULE: ./web/pdf_find_utils.js\nconst CharacterType = {\n  SPACE: 0,\n  ALPHA_LETTER: 1,\n  PUNCT: 2,\n  HAN_LETTER: 3,\n  KATAKANA_LETTER: 4,\n  HIRAGANA_LETTER: 5,\n  HALFWIDTH_KATAKANA_LETTER: 6,\n  THAI_LETTER: 7\n};\nfunction isAlphabeticalScript(charCode) {\n  return charCode < 0x2e80;\n}\nfunction isAscii(charCode) {\n  return (charCode & 0xff80) === 0;\n}\nfunction isAsciiAlpha(charCode) {\n  return charCode >= 0x61 && charCode <= 0x7a || charCode >= 0x41 && charCode <= 0x5a;\n}\nfunction isAsciiDigit(charCode) {\n  return charCode >= 0x30 && charCode <= 0x39;\n}\nfunction isAsciiSpace(charCode) {\n  return charCode === 0x20 || charCode === 0x09 || charCode === 0x0d || charCode === 0x0a;\n}\nfunction isHan(charCode) {\n  return charCode >= 0x3400 && charCode <= 0x9fff || charCode >= 0xf900 && charCode <= 0xfaff;\n}\nfunction isKatakana(charCode) {\n  return charCode >= 0x30a0 && charCode <= 0x30ff;\n}\nfunction isHiragana(charCode) {\n  return charCode >= 0x3040 && charCode <= 0x309f;\n}\nfunction isHalfwidthKatakana(charCode) {\n  return charCode >= 0xff60 && charCode <= 0xff9f;\n}\nfunction isThai(charCode) {\n  return (charCode & 0xff80) === 0x0e00;\n}\nfunction getCharacterType(charCode) {\n  if (isAlphabeticalScript(charCode)) {\n    if (isAscii(charCode)) {\n      if (isAsciiSpace(charCode)) {\n        return CharacterType.SPACE;\n      } else if (isAsciiAlpha(charCode) || isAsciiDigit(charCode) || charCode === 0x5f) {\n        return CharacterType.ALPHA_LETTER;\n      }\n      return CharacterType.PUNCT;\n    } else if (isThai(charCode)) {\n      return CharacterType.THAI_LETTER;\n    } else if (charCode === 0xa0) {\n      return CharacterType.SPACE;\n    }\n    return CharacterType.ALPHA_LETTER;\n  }\n  if (isHan(charCode)) {\n    return CharacterType.HAN_LETTER;\n  } else if (isKatakana(charCode)) {\n    return CharacterType.KATAKANA_LETTER;\n  } else if (isHiragana(charCode)) {\n    return CharacterType.HIRAGANA_LETTER;\n  } else if (isHalfwidthKatakana(charCode)) {\n    return CharacterType.HALFWIDTH_KATAKANA_LETTER;\n  }\n  return CharacterType.ALPHA_LETTER;\n}\nlet NormalizeWithNFKC;\nfunction getNormalizeWithNFKC() {\n  NormalizeWithNFKC ||= ` ¨ª¯²-µ¸-º¼-¾Ĳ-ĳĿ-ŀŉſǄ-ǌǱ-ǳʰ-ʸ˘-˝ˠ-ˤʹͺ;΄-΅·ϐ-ϖϰ-ϲϴ-ϵϹևٵ-ٸक़-य़ড়-ঢ়য়ਲ਼ਸ਼ਖ਼-ਜ਼ਫ਼ଡ଼-ଢ଼ำຳໜ-ໝ༌གྷཌྷདྷབྷཛྷཀྵჼᴬ-ᴮᴰ-ᴺᴼ-ᵍᵏ-ᵪᵸᶛ-ᶿẚ-ẛάέήίόύώΆ᾽-῁ΈΉ῍-῏ΐΊ῝-῟ΰΎ῭-`ΌΏ´-῾ - ‑‗․-… ″-‴‶-‷‼‾⁇-⁉⁗ ⁰-ⁱ⁴-₎ₐ-ₜ₨℀-℃℅-ℇ℉-ℓℕ-№ℙ-ℝ℠-™ℤΩℨK-ℭℯ-ℱℳ-ℹ℻-⅀ⅅ-ⅉ⅐-ⅿ↉∬-∭∯-∰〈-〉①-⓪⨌⩴-⩶⫝̸ⱼ-ⱽⵯ⺟⻳⼀-⿕　〶〸-〺゛-゜ゟヿㄱ-ㆎ㆒-㆟㈀-㈞㈠-㉇㉐-㉾㊀-㏿ꚜ-ꚝꝰꟲ-ꟴꟸ-ꟹꭜ-ꭟꭩ豈-嗀塚晴凞-羽蘒諸逸-都飯-舘並-龎ﬀ-ﬆﬓ-ﬗיִײַ-זּטּ-לּמּנּ-סּףּ-פּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-﷼︐-︙︰-﹄﹇-﹒﹔-﹦﹨-﹫ﹰ-ﹲﹴﹶ-ﻼ！-ﾾￂ-ￇￊ-ￏￒ-ￗￚ-ￜ￠-￦`;\n  return NormalizeWithNFKC;\n}\n\n;// CONCATENATED MODULE: ./web/pdf_find_controller.js\n\n\nconst FindState = {\n  FOUND: 0,\n  NOT_FOUND: 1,\n  WRAPPED: 2,\n  PENDING: 3\n};\nconst FIND_TIMEOUT = 250;\nconst MATCH_SCROLL_OFFSET_TOP = -50;\nconst MATCH_SCROLL_OFFSET_LEFT = -400;\nconst CHARACTERS_TO_NORMALIZE = {\n  \"\\u2010\": \"-\",\n  \"\\u2018\": \"'\",\n  \"\\u2019\": \"'\",\n  \"\\u201A\": \"'\",\n  \"\\u201B\": \"'\",\n  \"\\u201C\": '\"',\n  \"\\u201D\": '\"',\n  \"\\u201E\": '\"',\n  \"\\u201F\": '\"',\n  \"\\u00BC\": \"1/4\",\n  \"\\u00BD\": \"1/2\",\n  \"\\u00BE\": \"3/4\"\n};\nconst DIACRITICS_EXCEPTION = new Set([0x3099, 0x309a, 0x094d, 0x09cd, 0x0a4d, 0x0acd, 0x0b4d, 0x0bcd, 0x0c4d, 0x0ccd, 0x0d3b, 0x0d3c, 0x0d4d, 0x0dca, 0x0e3a, 0x0eba, 0x0f84, 0x1039, 0x103a, 0x1714, 0x1734, 0x17d2, 0x1a60, 0x1b44, 0x1baa, 0x1bab, 0x1bf2, 0x1bf3, 0x2d7f, 0xa806, 0xa82c, 0xa8c4, 0xa953, 0xa9c0, 0xaaf6, 0xabed, 0x0c56, 0x0f71, 0x0f72, 0x0f7a, 0x0f7b, 0x0f7c, 0x0f7d, 0x0f80, 0x0f74]);\nlet DIACRITICS_EXCEPTION_STR;\nconst DIACRITICS_REG_EXP = /\\p{M}+/gu;\nconst SPECIAL_CHARS_REG_EXP = /([.*+?^${}()|[\\]\\\\])|(\\p{P})|(\\s+)|(\\p{M})|(\\p{L})/gu;\nconst NOT_DIACRITIC_FROM_END_REG_EXP = /([^\\p{M}])\\p{M}*$/u;\nconst NOT_DIACRITIC_FROM_START_REG_EXP = /^\\p{M}*([^\\p{M}])/u;\nconst SYLLABLES_REG_EXP = /[\\uAC00-\\uD7AF\\uFA6C\\uFACF-\\uFAD1\\uFAD5-\\uFAD7]+/g;\nconst SYLLABLES_LENGTHS = new Map();\nconst FIRST_CHAR_SYLLABLES_REG_EXP = \"[\\\\u1100-\\\\u1112\\\\ud7a4-\\\\ud7af\\\\ud84a\\\\ud84c\\\\ud850\\\\ud854\\\\ud857\\\\ud85f]\";\nconst NFKC_CHARS_TO_NORMALIZE = new Map();\nlet noSyllablesRegExp = null;\nlet withSyllablesRegExp = null;\nfunction normalize(text) {\n  const syllablePositions = [];\n  let m;\n  while ((m = SYLLABLES_REG_EXP.exec(text)) !== null) {\n    let {\n      index\n    } = m;\n    for (const char of m[0]) {\n      let len = SYLLABLES_LENGTHS.get(char);\n      if (!len) {\n        len = char.normalize(\"NFD\").length;\n        SYLLABLES_LENGTHS.set(char, len);\n      }\n      syllablePositions.push([len, index++]);\n    }\n  }\n  let normalizationRegex;\n  if (syllablePositions.length === 0 && noSyllablesRegExp) {\n    normalizationRegex = noSyllablesRegExp;\n  } else if (syllablePositions.length > 0 && withSyllablesRegExp) {\n    normalizationRegex = withSyllablesRegExp;\n  } else {\n    const replace = Object.keys(CHARACTERS_TO_NORMALIZE).join(\"\");\n    const toNormalizeWithNFKC = getNormalizeWithNFKC();\n    const CJK = \"(?:\\\\p{Ideographic}|[\\u3040-\\u30FF])\";\n    const HKDiacritics = \"(?:\\u3099|\\u309A)\";\n    const regexp = `([${replace}])|([${toNormalizeWithNFKC}])|(${HKDiacritics}\\\\n)|(\\\\p{M}+(?:-\\\\n)?)|(\\\\S-\\\\n)|(${CJK}\\\\n)|(\\\\n)`;\n    if (syllablePositions.length === 0) {\n      normalizationRegex = noSyllablesRegExp = new RegExp(regexp + \"|(\\\\u0000)\", \"gum\");\n    } else {\n      normalizationRegex = withSyllablesRegExp = new RegExp(regexp + `|(${FIRST_CHAR_SYLLABLES_REG_EXP})`, \"gum\");\n    }\n  }\n  const rawDiacriticsPositions = [];\n  while ((m = DIACRITICS_REG_EXP.exec(text)) !== null) {\n    rawDiacriticsPositions.push([m[0].length, m.index]);\n  }\n  let normalized = text.normalize(\"NFD\");\n  const positions = [[0, 0]];\n  let rawDiacriticsIndex = 0;\n  let syllableIndex = 0;\n  let shift = 0;\n  let shiftOrigin = 0;\n  let eol = 0;\n  let hasDiacritics = false;\n  normalized = normalized.replace(normalizationRegex, (match, p1, p2, p3, p4, p5, p6, p7, p8, i) => {\n    i -= shiftOrigin;\n    if (p1) {\n      const replacement = CHARACTERS_TO_NORMALIZE[p1];\n      const jj = replacement.length;\n      for (let j = 1; j < jj; j++) {\n        positions.push([i - shift + j, shift - j]);\n      }\n      shift -= jj - 1;\n      return replacement;\n    }\n    if (p2) {\n      let replacement = NFKC_CHARS_TO_NORMALIZE.get(p2);\n      if (!replacement) {\n        replacement = p2.normalize(\"NFKC\");\n        NFKC_CHARS_TO_NORMALIZE.set(p2, replacement);\n      }\n      const jj = replacement.length;\n      for (let j = 1; j < jj; j++) {\n        positions.push([i - shift + j, shift - j]);\n      }\n      shift -= jj - 1;\n      return replacement;\n    }\n    if (p3) {\n      hasDiacritics = true;\n      if (i + eol === rawDiacriticsPositions[rawDiacriticsIndex]?.[1]) {\n        ++rawDiacriticsIndex;\n      } else {\n        positions.push([i - 1 - shift + 1, shift - 1]);\n        shift -= 1;\n        shiftOrigin += 1;\n      }\n      positions.push([i - shift + 1, shift]);\n      shiftOrigin += 1;\n      eol += 1;\n      return p3.charAt(0);\n    }\n    if (p4) {\n      const hasTrailingDashEOL = p4.endsWith(\"\\n\");\n      const len = hasTrailingDashEOL ? p4.length - 2 : p4.length;\n      hasDiacritics = true;\n      let jj = len;\n      if (i + eol === rawDiacriticsPositions[rawDiacriticsIndex]?.[1]) {\n        jj -= rawDiacriticsPositions[rawDiacriticsIndex][0];\n        ++rawDiacriticsIndex;\n      }\n      for (let j = 1; j <= jj; j++) {\n        positions.push([i - 1 - shift + j, shift - j]);\n      }\n      shift -= jj;\n      shiftOrigin += jj;\n      if (hasTrailingDashEOL) {\n        i += len - 1;\n        positions.push([i - shift + 1, 1 + shift]);\n        shift += 1;\n        shiftOrigin += 1;\n        eol += 1;\n        return p4.slice(0, len);\n      }\n      return p4;\n    }\n    if (p5) {\n      const len = p5.length - 2;\n      positions.push([i - shift + len, 1 + shift]);\n      shift += 1;\n      shiftOrigin += 1;\n      eol += 1;\n      return p5.slice(0, -2);\n    }\n    if (p6) {\n      const len = p6.length - 1;\n      positions.push([i - shift + len, shift]);\n      shiftOrigin += 1;\n      eol += 1;\n      return p6.slice(0, -1);\n    }\n    if (p7) {\n      positions.push([i - shift + 1, shift - 1]);\n      shift -= 1;\n      shiftOrigin += 1;\n      eol += 1;\n      return \" \";\n    }\n    if (i + eol === syllablePositions[syllableIndex]?.[1]) {\n      const newCharLen = syllablePositions[syllableIndex][0] - 1;\n      ++syllableIndex;\n      for (let j = 1; j <= newCharLen; j++) {\n        positions.push([i - (shift - j), shift - j]);\n      }\n      shift -= newCharLen;\n      shiftOrigin += newCharLen;\n    }\n    return p8;\n  });\n  positions.push([normalized.length, shift]);\n  return [normalized, positions, hasDiacritics];\n}\nfunction getOriginalIndex(diffs, pos, len) {\n  if (!diffs) {\n    return [pos, len];\n  }\n  const start = pos;\n  const end = pos + len - 1;\n  let i = (0,ui_utils.binarySearchFirstItem)(diffs, x => x[0] >= start);\n  if (diffs[i][0] > start) {\n    --i;\n  }\n  let j = (0,ui_utils.binarySearchFirstItem)(diffs, x => x[0] >= end, i);\n  if (diffs[j][0] > end) {\n    --j;\n  }\n  const oldStart = start + diffs[i][1];\n  const oldEnd = end + diffs[j][1];\n  const oldLen = oldEnd + 1 - oldStart;\n  return [oldStart, oldLen];\n}\nclass PDFFindController {\n  #state = null;\n  #updateMatchesCountOnProgress = true;\n  #visitedPagesCount = 0;\n  constructor({\n    linkService,\n    eventBus,\n    updateMatchesCountOnProgress = true\n  }) {\n    this._linkService = linkService;\n    this._eventBus = eventBus;\n    this.#updateMatchesCountOnProgress = updateMatchesCountOnProgress;\n    this.onIsPageVisible = null;\n    this.#reset();\n    eventBus._on(\"find\", this.#onFind.bind(this));\n    eventBus._on(\"findbarclose\", this.#onFindBarClose.bind(this));\n  }\n  get highlightMatches() {\n    return this._highlightMatches;\n  }\n  get pageMatches() {\n    return this._pageMatches;\n  }\n  get pageMatchesLength() {\n    return this._pageMatchesLength;\n  }\n  get selected() {\n    return this._selected;\n  }\n  get state() {\n    return this.#state;\n  }\n  setDocument(pdfDocument) {\n    if (this._pdfDocument) {\n      this.#reset();\n    }\n    if (!pdfDocument) {\n      return;\n    }\n    this._pdfDocument = pdfDocument;\n    this._firstPageCapability.resolve();\n  }\n  #onFind(state) {\n    if (!state) {\n      return;\n    }\n    const pdfDocument = this._pdfDocument;\n    const {\n      type\n    } = state;\n    if (this.#state === null || this.#shouldDirtyMatch(state)) {\n      this._dirtyMatch = true;\n    }\n    this.#state = state;\n    if (type !== \"highlightallchange\") {\n      this.#updateUIState(FindState.PENDING);\n    }\n    this._firstPageCapability.promise.then(() => {\n      if (!this._pdfDocument || pdfDocument && this._pdfDocument !== pdfDocument) {\n        return;\n      }\n      this.#extractText();\n      const findbarClosed = !this._highlightMatches;\n      const pendingTimeout = !!this._findTimeout;\n      if (this._findTimeout) {\n        clearTimeout(this._findTimeout);\n        this._findTimeout = null;\n      }\n      if (!type) {\n        this._findTimeout = setTimeout(() => {\n          this.#nextMatch();\n          this._findTimeout = null;\n        }, FIND_TIMEOUT);\n      } else if (this._dirtyMatch) {\n        this.#nextMatch();\n      } else if (type === \"again\") {\n        this.#nextMatch();\n        if (findbarClosed && this.#state.highlightAll) {\n          this.#updateAllPages();\n        }\n      } else if (type === \"highlightallchange\") {\n        if (pendingTimeout) {\n          this.#nextMatch();\n        } else {\n          this._highlightMatches = true;\n        }\n        this.#updateAllPages();\n      } else {\n        this.#nextMatch();\n      }\n    });\n  }\n  scrollMatchIntoView({\n    element = null,\n    selectedLeft = 0,\n    pageIndex = -1,\n    matchIndex = -1\n  }) {\n    if (!this._scrollMatches || !element) {\n      return;\n    } else if (matchIndex === -1 || matchIndex !== this._selected.matchIdx) {\n      return;\n    } else if (pageIndex === -1 || pageIndex !== this._selected.pageIdx) {\n      return;\n    }\n    this._scrollMatches = false;\n    const spot = {\n      top: MATCH_SCROLL_OFFSET_TOP,\n      left: selectedLeft + MATCH_SCROLL_OFFSET_LEFT\n    };\n    (0,ui_utils.scrollIntoView)(element, spot, true);\n  }\n  #reset() {\n    this._highlightMatches = false;\n    this._scrollMatches = false;\n    this._pdfDocument = null;\n    this._pageMatches = [];\n    this._pageMatchesLength = [];\n    this.#visitedPagesCount = 0;\n    this.#state = null;\n    this._selected = {\n      pageIdx: -1,\n      matchIdx: -1\n    };\n    this._offset = {\n      pageIdx: null,\n      matchIdx: null,\n      wrapped: false\n    };\n    this._extractTextPromises = [];\n    this._pageContents = [];\n    this._pageDiffs = [];\n    this._hasDiacritics = [];\n    this._matchesCountTotal = 0;\n    this._pagesToSearch = null;\n    this._pendingFindMatches = new Set();\n    this._resumePageIdx = null;\n    this._dirtyMatch = false;\n    clearTimeout(this._findTimeout);\n    this._findTimeout = null;\n    this._firstPageCapability = Promise.withResolvers();\n  }\n  get #query() {\n    const {\n      query\n    } = this.#state;\n    if (typeof query === \"string\") {\n      if (query !== this._rawQuery) {\n        this._rawQuery = query;\n        [this._normalizedQuery] = normalize(query);\n      }\n      return this._normalizedQuery;\n    }\n    return (query || []).filter(q => !!q).map(q => normalize(q)[0]);\n  }\n  #shouldDirtyMatch(state) {\n    const newQuery = state.query,\n      prevQuery = this.#state.query;\n    const newType = typeof newQuery,\n      prevType = typeof prevQuery;\n    if (newType !== prevType) {\n      return true;\n    }\n    if (newType === \"string\") {\n      if (newQuery !== prevQuery) {\n        return true;\n      }\n    } else if (JSON.stringify(newQuery) !== JSON.stringify(prevQuery)) {\n      return true;\n    }\n    switch (state.type) {\n      case \"again\":\n        const pageNumber = this._selected.pageIdx + 1;\n        const linkService = this._linkService;\n        return pageNumber >= 1 && pageNumber <= linkService.pagesCount && pageNumber !== linkService.page && !(this.onIsPageVisible?.(pageNumber) ?? true);\n      case \"highlightallchange\":\n        return false;\n    }\n    return true;\n  }\n  #isEntireWord(content, startIdx, length) {\n    let match = content.slice(0, startIdx).match(NOT_DIACRITIC_FROM_END_REG_EXP);\n    if (match) {\n      const first = content.charCodeAt(startIdx);\n      const limit = match[1].charCodeAt(0);\n      if (getCharacterType(first) === getCharacterType(limit)) {\n        return false;\n      }\n    }\n    match = content.slice(startIdx + length).match(NOT_DIACRITIC_FROM_START_REG_EXP);\n    if (match) {\n      const last = content.charCodeAt(startIdx + length - 1);\n      const limit = match[1].charCodeAt(0);\n      if (getCharacterType(last) === getCharacterType(limit)) {\n        return false;\n      }\n    }\n    return true;\n  }\n  #calculateRegExpMatch(query, entireWord, pageIndex, pageContent) {\n    const matches = this._pageMatches[pageIndex] = [];\n    const matchesLength = this._pageMatchesLength[pageIndex] = [];\n    if (!query) {\n      return;\n    }\n    const diffs = this._pageDiffs[pageIndex];\n    let match;\n    while ((match = query.exec(pageContent)) !== null) {\n      if (entireWord && !this.#isEntireWord(pageContent, match.index, match[0].length)) {\n        continue;\n      }\n      const [matchPos, matchLen] = getOriginalIndex(diffs, match.index, match[0].length);\n      if (matchLen) {\n        matches.push(matchPos);\n        matchesLength.push(matchLen);\n      }\n    }\n  }\n  #convertToRegExpString(query, hasDiacritics) {\n    const {\n      matchDiacritics\n    } = this.#state;\n    let isUnicode = false;\n    query = query.replaceAll(SPECIAL_CHARS_REG_EXP, (match, p1, p2, p3, p4, p5) => {\n      if (p1) {\n        return `[ ]*\\\\${p1}[ ]*`;\n      }\n      if (p2) {\n        return `[ ]*${p2}[ ]*`;\n      }\n      if (p3) {\n        return \"[ ]+\";\n      }\n      if (matchDiacritics) {\n        return p4 || p5;\n      }\n      if (p4) {\n        return DIACRITICS_EXCEPTION.has(p4.charCodeAt(0)) ? p4 : \"\";\n      }\n      if (hasDiacritics) {\n        isUnicode = true;\n        return `${p5}\\\\p{M}*`;\n      }\n      return p5;\n    });\n    const trailingSpaces = \"[ ]*\";\n    if (query.endsWith(trailingSpaces)) {\n      query = query.slice(0, query.length - trailingSpaces.length);\n    }\n    if (matchDiacritics) {\n      if (hasDiacritics) {\n        DIACRITICS_EXCEPTION_STR ||= String.fromCharCode(...DIACRITICS_EXCEPTION);\n        isUnicode = true;\n        query = `${query}(?=[${DIACRITICS_EXCEPTION_STR}]|[^\\\\p{M}]|$)`;\n      }\n    }\n    return [isUnicode, query];\n  }\n  #calculateMatch(pageIndex) {\n    let query = this.#query;\n    if (query.length === 0) {\n      return;\n    }\n    const {\n      caseSensitive,\n      entireWord\n    } = this.#state;\n    const pageContent = this._pageContents[pageIndex];\n    const hasDiacritics = this._hasDiacritics[pageIndex];\n    let isUnicode = false;\n    if (typeof query === \"string\") {\n      [isUnicode, query] = this.#convertToRegExpString(query, hasDiacritics);\n    } else {\n      query = query.sort().reverse().map(q => {\n        const [isUnicodePart, queryPart] = this.#convertToRegExpString(q, hasDiacritics);\n        isUnicode ||= isUnicodePart;\n        return `(${queryPart})`;\n      }).join(\"|\");\n    }\n    const flags = `g${isUnicode ? \"u\" : \"\"}${caseSensitive ? \"\" : \"i\"}`;\n    query = query ? new RegExp(query, flags) : null;\n    this.#calculateRegExpMatch(query, entireWord, pageIndex, pageContent);\n    if (this.#state.highlightAll) {\n      this.#updatePage(pageIndex);\n    }\n    if (this._resumePageIdx === pageIndex) {\n      this._resumePageIdx = null;\n      this.#nextPageMatch();\n    }\n    const pageMatchesCount = this._pageMatches[pageIndex].length;\n    this._matchesCountTotal += pageMatchesCount;\n    if (this.#updateMatchesCountOnProgress) {\n      if (pageMatchesCount > 0) {\n        this.#updateUIResultsCount();\n      }\n    } else if (++this.#visitedPagesCount === this._linkService.pagesCount) {\n      this.#updateUIResultsCount();\n    }\n  }\n  #extractText() {\n    if (this._extractTextPromises.length > 0) {\n      return;\n    }\n    let deferred = Promise.resolve();\n    const textOptions = {\n      disableNormalization: true\n    };\n    for (let i = 0, ii = this._linkService.pagesCount; i < ii; i++) {\n      const {\n        promise,\n        resolve\n      } = Promise.withResolvers();\n      this._extractTextPromises[i] = promise;\n      deferred = deferred.then(() => {\n        return this._pdfDocument.getPage(i + 1).then(pdfPage => pdfPage.getTextContent(textOptions)).then(textContent => {\n          const strBuf = [];\n          for (const textItem of textContent.items) {\n            strBuf.push(textItem.str);\n            if (textItem.hasEOL) {\n              strBuf.push(\"\\n\");\n            }\n          }\n          [this._pageContents[i], this._pageDiffs[i], this._hasDiacritics[i]] = normalize(strBuf.join(\"\"));\n          resolve();\n        }, reason => {\n          console.error(`Unable to get text content for page ${i + 1}`, reason);\n          this._pageContents[i] = \"\";\n          this._pageDiffs[i] = null;\n          this._hasDiacritics[i] = false;\n          resolve();\n        });\n      });\n    }\n  }\n  #updatePage(index) {\n    if (this._scrollMatches && this._selected.pageIdx === index) {\n      this._linkService.page = index + 1;\n    }\n    this._eventBus.dispatch(\"updatetextlayermatches\", {\n      source: this,\n      pageIndex: index\n    });\n  }\n  #updateAllPages() {\n    this._eventBus.dispatch(\"updatetextlayermatches\", {\n      source: this,\n      pageIndex: -1\n    });\n  }\n  #nextMatch() {\n    const previous = this.#state.findPrevious;\n    const currentPageIndex = this._linkService.page - 1;\n    const numPages = this._linkService.pagesCount;\n    this._highlightMatches = true;\n    if (this._dirtyMatch) {\n      this._dirtyMatch = false;\n      this._selected.pageIdx = this._selected.matchIdx = -1;\n      this._offset.pageIdx = currentPageIndex;\n      this._offset.matchIdx = null;\n      this._offset.wrapped = false;\n      this._resumePageIdx = null;\n      this._pageMatches.length = 0;\n      this._pageMatchesLength.length = 0;\n      this.#visitedPagesCount = 0;\n      this._matchesCountTotal = 0;\n      this.#updateAllPages();\n      for (let i = 0; i < numPages; i++) {\n        if (this._pendingFindMatches.has(i)) {\n          continue;\n        }\n        this._pendingFindMatches.add(i);\n        this._extractTextPromises[i].then(() => {\n          this._pendingFindMatches.delete(i);\n          this.#calculateMatch(i);\n        });\n      }\n    }\n    const query = this.#query;\n    if (query.length === 0) {\n      this.#updateUIState(FindState.FOUND);\n      return;\n    }\n    if (this._resumePageIdx) {\n      return;\n    }\n    const offset = this._offset;\n    this._pagesToSearch = numPages;\n    if (offset.matchIdx !== null) {\n      const numPageMatches = this._pageMatches[offset.pageIdx].length;\n      if (!previous && offset.matchIdx + 1 < numPageMatches || previous && offset.matchIdx > 0) {\n        offset.matchIdx = previous ? offset.matchIdx - 1 : offset.matchIdx + 1;\n        this.#updateMatch(true);\n        return;\n      }\n      this.#advanceOffsetPage(previous);\n    }\n    this.#nextPageMatch();\n  }\n  #matchesReady(matches) {\n    const offset = this._offset;\n    const numMatches = matches.length;\n    const previous = this.#state.findPrevious;\n    if (numMatches) {\n      offset.matchIdx = previous ? numMatches - 1 : 0;\n      this.#updateMatch(true);\n      return true;\n    }\n    this.#advanceOffsetPage(previous);\n    if (offset.wrapped) {\n      offset.matchIdx = null;\n      if (this._pagesToSearch < 0) {\n        this.#updateMatch(false);\n        return true;\n      }\n    }\n    return false;\n  }\n  #nextPageMatch() {\n    if (this._resumePageIdx !== null) {\n      console.error(\"There can only be one pending page.\");\n    }\n    let matches = null;\n    do {\n      const pageIdx = this._offset.pageIdx;\n      matches = this._pageMatches[pageIdx];\n      if (!matches) {\n        this._resumePageIdx = pageIdx;\n        break;\n      }\n    } while (!this.#matchesReady(matches));\n  }\n  #advanceOffsetPage(previous) {\n    const offset = this._offset;\n    const numPages = this._linkService.pagesCount;\n    offset.pageIdx = previous ? offset.pageIdx - 1 : offset.pageIdx + 1;\n    offset.matchIdx = null;\n    this._pagesToSearch--;\n    if (offset.pageIdx >= numPages || offset.pageIdx < 0) {\n      offset.pageIdx = previous ? numPages - 1 : 0;\n      offset.wrapped = true;\n    }\n  }\n  #updateMatch(found = false) {\n    let state = FindState.NOT_FOUND;\n    const wrapped = this._offset.wrapped;\n    this._offset.wrapped = false;\n    if (found) {\n      const previousPage = this._selected.pageIdx;\n      this._selected.pageIdx = this._offset.pageIdx;\n      this._selected.matchIdx = this._offset.matchIdx;\n      state = wrapped ? FindState.WRAPPED : FindState.FOUND;\n      if (previousPage !== -1 && previousPage !== this._selected.pageIdx) {\n        this.#updatePage(previousPage);\n      }\n    }\n    this.#updateUIState(state, this.#state.findPrevious);\n    if (this._selected.pageIdx !== -1) {\n      this._scrollMatches = true;\n      this.#updatePage(this._selected.pageIdx);\n    }\n  }\n  #onFindBarClose(evt) {\n    const pdfDocument = this._pdfDocument;\n    this._firstPageCapability.promise.then(() => {\n      if (!this._pdfDocument || pdfDocument && this._pdfDocument !== pdfDocument) {\n        return;\n      }\n      if (this._findTimeout) {\n        clearTimeout(this._findTimeout);\n        this._findTimeout = null;\n      }\n      if (this._resumePageIdx) {\n        this._resumePageIdx = null;\n        this._dirtyMatch = true;\n      }\n      this.#updateUIState(FindState.FOUND);\n      this._highlightMatches = false;\n      this.#updateAllPages();\n    });\n  }\n  #requestMatchesCount() {\n    const {\n      pageIdx,\n      matchIdx\n    } = this._selected;\n    let current = 0,\n      total = this._matchesCountTotal;\n    if (matchIdx !== -1) {\n      for (let i = 0; i < pageIdx; i++) {\n        current += this._pageMatches[i]?.length || 0;\n      }\n      current += matchIdx + 1;\n    }\n    if (current < 1 || current > total) {\n      current = total = 0;\n    }\n    return {\n      current,\n      total\n    };\n  }\n  #updateUIResultsCount() {\n    this._eventBus.dispatch(\"updatefindmatchescount\", {\n      source: this,\n      matchesCount: this.#requestMatchesCount()\n    });\n  }\n  #updateUIState(state, previous = false) {\n    if (!this.#updateMatchesCountOnProgress && (this.#visitedPagesCount !== this._linkService.pagesCount || state === FindState.PENDING)) {\n      return;\n    }\n    this._eventBus.dispatch(\"updatefindcontrolstate\", {\n      source: this,\n      state,\n      previous,\n      matchesCount: this.#requestMatchesCount(),\n      rawQuery: this.#state?.query ?? null\n    });\n  }\n}\n\n\n/***/ }),\n\n/***/ 8543:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   PDFHistory: () => (/* binding */ PDFHistory)\n/* harmony export */ });\n/* unused harmony exports isDestArraysEqual, isDestHashesEqual */\n/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256);\n/* harmony import */ var _event_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5656);\n\n\nconst HASH_CHANGE_TIMEOUT = 1000;\nconst POSITION_UPDATED_THRESHOLD = 50;\nconst UPDATE_VIEWAREA_TIMEOUT = 1000;\nfunction getCurrentHash() {\n  return document.location.hash;\n}\nclass PDFHistory {\n  #eventAbortController = null;\n  constructor({\n    linkService,\n    eventBus\n  }) {\n    this.linkService = linkService;\n    this.eventBus = eventBus;\n    this._initialized = false;\n    this._fingerprint = \"\";\n    this.reset();\n    this.eventBus._on(\"pagesinit\", () => {\n      this._isPagesLoaded = false;\n      this.eventBus._on(\"pagesloaded\", evt => {\n        this._isPagesLoaded = !!evt.pagesCount;\n      }, {\n        once: true\n      });\n    });\n  }\n  initialize({\n    fingerprint,\n    resetHistory = false,\n    updateUrl = false\n  }) {\n    if (!fingerprint || typeof fingerprint !== \"string\") {\n      console.error('PDFHistory.initialize: The \"fingerprint\" must be a non-empty string.');\n      return;\n    }\n    if (this._initialized) {\n      this.reset();\n    }\n    const reInitialized = this._fingerprint !== \"\" && this._fingerprint !== fingerprint;\n    this._fingerprint = fingerprint;\n    this._updateUrl = updateUrl === true;\n    this._initialized = true;\n    this.#bindEvents();\n    const state = window.history.state;\n    this._popStateInProgress = false;\n    this._blockHashChange = 0;\n    this._currentHash = getCurrentHash();\n    this._numPositionUpdates = 0;\n    this._uid = this._maxUid = 0;\n    this._destination = null;\n    this._position = null;\n    if (!this.#isValidState(state, true) || resetHistory) {\n      const {\n        hash,\n        page,\n        rotation\n      } = this.#parseCurrentHash(true);\n      if (!hash || reInitialized || resetHistory) {\n        this.#pushOrReplaceState(null, true);\n        return;\n      }\n      this.#pushOrReplaceState({\n        hash,\n        page,\n        rotation\n      }, true);\n      return;\n    }\n    const destination = state.destination;\n    this.#updateInternalState(destination, state.uid, true);\n    if (destination.rotation !== undefined) {\n      this._initialRotation = destination.rotation;\n    }\n    if (destination.dest) {\n      this._initialBookmark = JSON.stringify(destination.dest);\n      this._destination.page = null;\n    } else if (destination.hash) {\n      this._initialBookmark = destination.hash;\n    } else if (destination.page) {\n      this._initialBookmark = `page=${destination.page}`;\n    }\n  }\n  reset() {\n    if (this._initialized) {\n      this.#pageHide();\n      this._initialized = false;\n      this.#unbindEvents();\n    }\n    if (this._updateViewareaTimeout) {\n      clearTimeout(this._updateViewareaTimeout);\n      this._updateViewareaTimeout = null;\n    }\n    this._initialBookmark = null;\n    this._initialRotation = null;\n  }\n  push({\n    namedDest = null,\n    explicitDest,\n    pageNumber\n  }) {\n    if (!this._initialized) {\n      return;\n    }\n    if (namedDest && typeof namedDest !== \"string\") {\n      console.error(\"PDFHistory.push: \" + `\"${namedDest}\" is not a valid namedDest parameter.`);\n      return;\n    } else if (!Array.isArray(explicitDest)) {\n      console.error(\"PDFHistory.push: \" + `\"${explicitDest}\" is not a valid explicitDest parameter.`);\n      return;\n    } else if (!this.#isValidPage(pageNumber)) {\n      if (pageNumber !== null || this._destination) {\n        console.error(\"PDFHistory.push: \" + `\"${pageNumber}\" is not a valid pageNumber parameter.`);\n        return;\n      }\n    }\n    const hash = namedDest || JSON.stringify(explicitDest);\n    if (!hash) {\n      return;\n    }\n    let forceReplace = false;\n    if (this._destination && (isDestHashesEqual(this._destination.hash, hash) || isDestArraysEqual(this._destination.dest, explicitDest))) {\n      if (this._destination.page) {\n        return;\n      }\n      forceReplace = true;\n    }\n    if (this._popStateInProgress && !forceReplace) {\n      return;\n    }\n    this.#pushOrReplaceState({\n      dest: explicitDest,\n      hash,\n      page: pageNumber,\n      rotation: this.linkService.rotation\n    }, forceReplace);\n    if (!this._popStateInProgress) {\n      this._popStateInProgress = true;\n      Promise.resolve().then(() => {\n        this._popStateInProgress = false;\n      });\n    }\n  }\n  pushPage(pageNumber) {\n    if (!this._initialized) {\n      return;\n    }\n    if (!this.#isValidPage(pageNumber)) {\n      console.error(`PDFHistory.pushPage: \"${pageNumber}\" is not a valid page number.`);\n      return;\n    }\n    if (this._destination?.page === pageNumber) {\n      return;\n    }\n    if (this._popStateInProgress) {\n      return;\n    }\n    this.#pushOrReplaceState({\n      dest: null,\n      hash: `page=${pageNumber}`,\n      page: pageNumber,\n      rotation: this.linkService.rotation\n    });\n    if (!this._popStateInProgress) {\n      this._popStateInProgress = true;\n      Promise.resolve().then(() => {\n        this._popStateInProgress = false;\n      });\n    }\n  }\n  pushCurrentPosition() {\n    if (!this._initialized || this._popStateInProgress) {\n      return;\n    }\n    this.#tryPushCurrentPosition();\n  }\n  back() {\n    if (!this._initialized || this._popStateInProgress) {\n      return;\n    }\n    const state = window.history.state;\n    if (this.#isValidState(state) && state.uid > 0) {\n      window.history.back();\n    }\n  }\n  forward() {\n    if (!this._initialized || this._popStateInProgress) {\n      return;\n    }\n    const state = window.history.state;\n    if (this.#isValidState(state) && state.uid < this._maxUid) {\n      window.history.forward();\n    }\n  }\n  get popStateInProgress() {\n    return this._initialized && (this._popStateInProgress || this._blockHashChange > 0);\n  }\n  get initialBookmark() {\n    return this._initialized ? this._initialBookmark : null;\n  }\n  get initialRotation() {\n    return this._initialized ? this._initialRotation : null;\n  }\n  #pushOrReplaceState(destination, forceReplace = false) {\n    const shouldReplace = forceReplace || !this._destination;\n    const newState = {\n      fingerprint: this._fingerprint,\n      uid: shouldReplace ? this._uid : this._uid + 1,\n      destination\n    };\n    this.#updateInternalState(destination, newState.uid);\n    let newUrl;\n    if (this._updateUrl && destination?.hash) {\n      const baseUrl = document.location.href.split(\"#\", 1)[0];\n      if (!baseUrl.startsWith(\"file://\")) {\n        newUrl = `${baseUrl}#${destination.hash}`;\n      }\n    }\n    if (shouldReplace) {\n      window.history.replaceState(newState, \"\", newUrl);\n    } else {\n      window.history.pushState(newState, \"\", newUrl);\n    }\n  }\n  #tryPushCurrentPosition(temporary = false) {\n    if (!this._position) {\n      return;\n    }\n    let position = this._position;\n    if (temporary) {\n      position = Object.assign(Object.create(null), this._position);\n      position.temporary = true;\n    }\n    if (!this._destination) {\n      this.#pushOrReplaceState(position);\n      return;\n    }\n    if (this._destination.temporary) {\n      this.#pushOrReplaceState(position, true);\n      return;\n    }\n    if (this._destination.hash === position.hash) {\n      return;\n    }\n    if (!this._destination.page && (POSITION_UPDATED_THRESHOLD <= 0 || this._numPositionUpdates <= POSITION_UPDATED_THRESHOLD)) {\n      return;\n    }\n    let forceReplace = false;\n    if (this._destination.page >= position.first && this._destination.page <= position.page) {\n      if (this._destination.dest !== undefined || !this._destination.first) {\n        return;\n      }\n      forceReplace = true;\n    }\n    this.#pushOrReplaceState(position, forceReplace);\n  }\n  #isValidPage(val) {\n    return Number.isInteger(val) && val > 0 && val <= this.linkService.pagesCount;\n  }\n  #isValidState(state, checkReload = false) {\n    if (!state) {\n      return false;\n    }\n    if (state.fingerprint !== this._fingerprint) {\n      if (checkReload) {\n        if (typeof state.fingerprint !== \"string\" || state.fingerprint.length !== this._fingerprint.length) {\n          return false;\n        }\n        const [perfEntry] = performance.getEntriesByType(\"navigation\");\n        if (perfEntry?.type !== \"reload\") {\n          return false;\n        }\n      } else {\n        return false;\n      }\n    }\n    if (!Number.isInteger(state.uid) || state.uid < 0) {\n      return false;\n    }\n    if (state.destination === null || typeof state.destination !== \"object\") {\n      return false;\n    }\n    return true;\n  }\n  #updateInternalState(destination, uid, removeTemporary = false) {\n    if (this._updateViewareaTimeout) {\n      clearTimeout(this._updateViewareaTimeout);\n      this._updateViewareaTimeout = null;\n    }\n    if (removeTemporary && destination?.temporary) {\n      delete destination.temporary;\n    }\n    this._destination = destination;\n    this._uid = uid;\n    this._maxUid = Math.max(this._maxUid, uid);\n    this._numPositionUpdates = 0;\n  }\n  #parseCurrentHash(checkNameddest = false) {\n    const hash = unescape(getCurrentHash()).substring(1);\n    const params = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.parseQueryString)(hash);\n    const nameddest = params.get(\"nameddest\") || \"\";\n    let page = params.get(\"page\") | 0;\n    if (!this.#isValidPage(page) || checkNameddest && nameddest.length > 0) {\n      page = null;\n    }\n    return {\n      hash,\n      page,\n      rotation: this.linkService.rotation\n    };\n  }\n  #updateViewarea({\n    location\n  }) {\n    if (this._updateViewareaTimeout) {\n      clearTimeout(this._updateViewareaTimeout);\n      this._updateViewareaTimeout = null;\n    }\n    this._position = {\n      hash: location.pdfOpenParams.substring(1),\n      page: this.linkService.page,\n      first: location.pageNumber,\n      rotation: location.rotation\n    };\n    if (this._popStateInProgress) {\n      return;\n    }\n    if (POSITION_UPDATED_THRESHOLD > 0 && this._isPagesLoaded && this._destination && !this._destination.page) {\n      this._numPositionUpdates++;\n    }\n    if (UPDATE_VIEWAREA_TIMEOUT > 0) {\n      this._updateViewareaTimeout = setTimeout(() => {\n        if (!this._popStateInProgress) {\n          this.#tryPushCurrentPosition(true);\n        }\n        this._updateViewareaTimeout = null;\n      }, UPDATE_VIEWAREA_TIMEOUT);\n    }\n  }\n  #popState({\n    state\n  }) {\n    const newHash = getCurrentHash(),\n      hashChanged = this._currentHash !== newHash;\n    this._currentHash = newHash;\n    if (!state) {\n      this._uid++;\n      const {\n        hash,\n        page,\n        rotation\n      } = this.#parseCurrentHash();\n      this.#pushOrReplaceState({\n        hash,\n        page,\n        rotation\n      }, true);\n      return;\n    }\n    if (!this.#isValidState(state)) {\n      return;\n    }\n    this._popStateInProgress = true;\n    if (hashChanged) {\n      this._blockHashChange++;\n      (0,_event_utils_js__WEBPACK_IMPORTED_MODULE_1__.waitOnEventOrTimeout)({\n        target: window,\n        name: \"hashchange\",\n        delay: HASH_CHANGE_TIMEOUT\n      }).then(() => {\n        this._blockHashChange--;\n      });\n    }\n    const destination = state.destination;\n    this.#updateInternalState(destination, state.uid, true);\n    if ((0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.isValidRotation)(destination.rotation)) {\n      this.linkService.rotation = destination.rotation;\n    }\n    if (destination.dest) {\n      this.linkService.goToDestination(destination.dest);\n    } else if (destination.hash) {\n      this.linkService.setHash(destination.hash);\n    } else if (destination.page) {\n      this.linkService.page = destination.page;\n    }\n    Promise.resolve().then(() => {\n      this._popStateInProgress = false;\n    });\n  }\n  #pageHide() {\n    if (!this._destination || this._destination.temporary) {\n      this.#tryPushCurrentPosition();\n    }\n  }\n  #bindEvents() {\n    if (this.#eventAbortController) {\n      return;\n    }\n    this.#eventAbortController = new AbortController();\n    const {\n      signal\n    } = this.#eventAbortController;\n    this.eventBus._on(\"updateviewarea\", this.#updateViewarea.bind(this), {\n      signal\n    });\n    window.addEventListener(\"popstate\", this.#popState.bind(this), {\n      signal\n    });\n    window.addEventListener(\"pagehide\", this.#pageHide.bind(this), {\n      signal\n    });\n  }\n  #unbindEvents() {\n    this.#eventAbortController?.abort();\n    this.#eventAbortController = null;\n  }\n}\nfunction isDestHashesEqual(destHash, pushHash) {\n  if (typeof destHash !== \"string\" || typeof pushHash !== \"string\") {\n    return false;\n  }\n  if (destHash === pushHash) {\n    return true;\n  }\n  const nameddest = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.parseQueryString)(destHash).get(\"nameddest\");\n  if (nameddest === pushHash) {\n    return true;\n  }\n  return false;\n}\nfunction isDestArraysEqual(firstDest, secondDest) {\n  function isEntryEqual(first, second) {\n    if (typeof first !== typeof second) {\n      return false;\n    }\n    if (Array.isArray(first) || Array.isArray(second)) {\n      return false;\n    }\n    if (first !== null && typeof first === \"object\" && second !== null) {\n      if (Object.keys(first).length !== Object.keys(second).length) {\n        return false;\n      }\n      for (const key in first) {\n        if (!isEntryEqual(first[key], second[key])) {\n          return false;\n        }\n      }\n      return true;\n    }\n    return first === second || Number.isNaN(first) && Number.isNaN(second);\n  }\n  if (!(Array.isArray(firstDest) && Array.isArray(secondDest))) {\n    return false;\n  }\n  if (firstDest.length !== secondDest.length) {\n    return false;\n  }\n  for (let i = 0, ii = firstDest.length; i < ii; i++) {\n    if (!isEntryEqual(firstDest[i], secondDest[i])) {\n      return false;\n    }\n  }\n  return true;\n}\n\n\n/***/ }),\n\n/***/ 4275:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   PDFLayerViewer: () => (/* binding */ PDFLayerViewer)\n/* harmony export */ });\n/* harmony import */ var _base_tree_viewer_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2961);\n\nclass PDFLayerViewer extends _base_tree_viewer_js__WEBPACK_IMPORTED_MODULE_0__.BaseTreeViewer {\n  constructor(options) {\n    super(options);\n    this.eventBus._on(\"optionalcontentconfigchanged\", evt => {\n      this.#updateLayers(evt.promise);\n    });\n    this.eventBus._on(\"resetlayers\", () => {\n      this.#updateLayers();\n    });\n    this.eventBus._on(\"togglelayerstree\", this._toggleAllTreeItems.bind(this));\n  }\n  reset() {\n    super.reset();\n    this._optionalContentConfig = null;\n    this._optionalContentHash = null;\n  }\n  _dispatchEvent(layersCount) {\n    this.eventBus.dispatch(\"layersloaded\", {\n      source: this,\n      layersCount\n    });\n  }\n  _bindLink(element, {\n    groupId,\n    input\n  }) {\n    const setVisibility = () => {\n      this._optionalContentConfig.setVisibility(groupId, input.checked);\n      this._optionalContentHash = this._optionalContentConfig.getHash();\n      this.eventBus.dispatch(\"optionalcontentconfig\", {\n        source: this,\n        promise: Promise.resolve(this._optionalContentConfig)\n      });\n    };\n    element.onclick = evt => {\n      if (evt.target === input) {\n        setVisibility();\n        return true;\n      } else if (evt.target !== element) {\n        return true;\n      }\n      input.checked = !input.checked;\n      setVisibility();\n      return false;\n    };\n  }\n  async _setNestedName(element, {\n    name = null\n  }) {\n    if (typeof name === \"string\") {\n      element.textContent = this._normalizeTextContent(name);\n      return;\n    }\n    element.textContent = await this._l10n.get(\"pdfjs-additional-layers\");\n    element.style.fontStyle = \"italic\";\n  }\n  _addToggleButton(div, {\n    name = null\n  }) {\n    super._addToggleButton(div, name === null);\n  }\n  _toggleAllTreeItems() {\n    if (!this._optionalContentConfig) {\n      return;\n    }\n    super._toggleAllTreeItems();\n  }\n  render({\n    optionalContentConfig,\n    pdfDocument\n  }) {\n    if (this._optionalContentConfig) {\n      this.reset();\n    }\n    this._optionalContentConfig = optionalContentConfig || null;\n    this._pdfDocument = pdfDocument || null;\n    const groups = optionalContentConfig?.getOrder();\n    if (!groups) {\n      this._dispatchEvent(0);\n      return;\n    }\n    this._optionalContentHash = optionalContentConfig.getHash();\n    const fragment = document.createDocumentFragment(),\n      queue = [{\n        parent: fragment,\n        groups\n      }];\n    let layersCount = 0,\n      hasAnyNesting = false;\n    while (queue.length > 0) {\n      const levelData = queue.shift();\n      for (const groupId of levelData.groups) {\n        const div = document.createElement(\"div\");\n        div.className = \"treeItem\";\n        const element = document.createElement(\"a\");\n        div.append(element);\n        if (typeof groupId === \"object\") {\n          hasAnyNesting = true;\n          this._addToggleButton(div, groupId);\n          this._setNestedName(element, groupId);\n          const itemsDiv = document.createElement(\"div\");\n          itemsDiv.className = \"treeItems\";\n          div.append(itemsDiv);\n          queue.push({\n            parent: itemsDiv,\n            groups: groupId.order\n          });\n        } else {\n          const group = optionalContentConfig.getGroup(groupId);\n          const input = document.createElement(\"input\");\n          this._bindLink(element, {\n            groupId,\n            input\n          });\n          input.type = \"checkbox\";\n          input.checked = group.visible;\n          const label = document.createElement(\"label\");\n          label.textContent = this._normalizeTextContent(group.name);\n          label.append(input);\n          element.append(label);\n          layersCount++;\n        }\n        levelData.parent.append(div);\n      }\n    }\n    this._finishRendering(fragment, layersCount, hasAnyNesting);\n  }\n  async #updateLayers(promise = null) {\n    if (!this._optionalContentConfig) {\n      return;\n    }\n    const pdfDocument = this._pdfDocument;\n    const optionalContentConfig = await (promise || pdfDocument.getOptionalContentConfig({\n      intent: \"display\"\n    }));\n    if (pdfDocument !== this._pdfDocument) {\n      return;\n    }\n    if (promise) {\n      if (optionalContentConfig.getHash() === this._optionalContentHash) {\n        return;\n      }\n    } else {\n      this.eventBus.dispatch(\"optionalcontentconfig\", {\n        source: this,\n        promise: Promise.resolve(optionalContentConfig)\n      });\n    }\n    this.render({\n      optionalContentConfig,\n      pdfDocument: this._pdfDocument\n    });\n  }\n}\n\n\n/***/ }),\n\n/***/ 787:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   LinkTarget: () => (/* binding */ LinkTarget),\n/* harmony export */   PDFLinkService: () => (/* binding */ PDFLinkService),\n/* harmony export */   SimpleLinkService: () => (/* binding */ SimpleLinkService)\n/* harmony export */ });\n/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256);\n\nconst DEFAULT_LINK_REL = \"noopener noreferrer nofollow\";\nconst LinkTarget = {\n  NONE: 0,\n  SELF: 1,\n  BLANK: 2,\n  PARENT: 3,\n  TOP: 4\n};\nclass PDFLinkService {\n  externalLinkEnabled = true;\n  constructor({\n    eventBus,\n    externalLinkTarget = null,\n    externalLinkRel = null,\n    ignoreDestinationZoom = false\n  } = {}) {\n    this.eventBus = eventBus;\n    this.externalLinkTarget = externalLinkTarget;\n    this.externalLinkRel = externalLinkRel;\n    this._ignoreDestinationZoom = ignoreDestinationZoom;\n    this.baseUrl = null;\n    this.pdfDocument = null;\n    this.pdfViewer = null;\n    this.pdfHistory = null;\n  }\n  setDocument(pdfDocument, baseUrl = null) {\n    this.baseUrl = baseUrl;\n    this.pdfDocument = pdfDocument;\n  }\n  setViewer(pdfViewer) {\n    this.pdfViewer = pdfViewer;\n  }\n  setHistory(pdfHistory) {\n    this.pdfHistory = pdfHistory;\n  }\n  get pagesCount() {\n    return this.pdfDocument ? this.pdfDocument.numPages : 0;\n  }\n  get page() {\n    return this.pdfDocument ? this.pdfViewer.currentPageNumber : 1;\n  }\n  set page(value) {\n    if (this.pdfDocument) {\n      this.pdfViewer.currentPageNumber = value;\n    }\n  }\n  get rotation() {\n    return this.pdfDocument ? this.pdfViewer.pagesRotation : 0;\n  }\n  set rotation(value) {\n    if (this.pdfDocument) {\n      this.pdfViewer.pagesRotation = value;\n    }\n  }\n  get isInPresentationMode() {\n    return this.pdfDocument ? this.pdfViewer.isInPresentationMode : false;\n  }\n  async goToDestination(dest) {\n    if (!this.pdfDocument) {\n      return;\n    }\n    let namedDest, explicitDest, pageNumber;\n    if (typeof dest === \"string\") {\n      namedDest = dest;\n      explicitDest = await this.pdfDocument.getDestination(dest);\n    } else {\n      namedDest = null;\n      explicitDest = await dest;\n    }\n    if (!Array.isArray(explicitDest)) {\n      console.error(`goToDestination: \"${explicitDest}\" is not a valid destination array, for dest=\"${dest}\".`);\n      return;\n    }\n    const [destRef] = explicitDest;\n    if (destRef && typeof destRef === \"object\") {\n      pageNumber = this.pdfDocument.cachedPageNumber(destRef);\n      if (!pageNumber) {\n        try {\n          pageNumber = (await this.pdfDocument.getPageIndex(destRef)) + 1;\n        } catch {\n          console.error(`goToDestination: \"${destRef}\" is not a valid page reference, for dest=\"${dest}\".`);\n          return;\n        }\n      }\n    } else if (Number.isInteger(destRef)) {\n      pageNumber = destRef + 1;\n    }\n    if (!pageNumber || pageNumber < 1 || pageNumber > this.pagesCount) {\n      console.error(`goToDestination: \"${pageNumber}\" is not a valid page number, for dest=\"${dest}\".`);\n      return;\n    }\n    if (this.pdfHistory) {\n      this.pdfHistory.pushCurrentPosition();\n      this.pdfHistory.push({\n        namedDest,\n        explicitDest,\n        pageNumber\n      });\n    }\n    this.pdfViewer.scrollPageIntoView({\n      pageNumber,\n      destArray: explicitDest,\n      ignoreDestinationZoom: this._ignoreDestinationZoom\n    });\n  }\n  goToPage(val) {\n    if (!this.pdfDocument) {\n      return;\n    }\n    const pageNumber = typeof val === \"string\" && this.pdfViewer.pageLabelToPageNumber(val) || val | 0;\n    if (!(Number.isInteger(pageNumber) && pageNumber > 0 && pageNumber <= this.pagesCount)) {\n      console.error(`PDFLinkService.goToPage: \"${val}\" is not a valid page.`);\n      return;\n    }\n    if (this.pdfHistory) {\n      this.pdfHistory.pushCurrentPosition();\n      this.pdfHistory.pushPage(pageNumber);\n    }\n    this.pdfViewer.scrollPageIntoView({\n      pageNumber\n    });\n  }\n  addLinkAttributes(link, url, newWindow = false) {\n    if (!url || typeof url !== \"string\") {\n      throw new Error('A valid \"url\" parameter must provided.');\n    }\n    const target = newWindow ? LinkTarget.BLANK : this.externalLinkTarget,\n      rel = this.externalLinkRel;\n    if (this.externalLinkEnabled) {\n      link.href = link.title = url;\n    } else {\n      link.href = \"\";\n      link.title = `Disabled: ${url}`;\n      link.onclick = () => false;\n    }\n    let targetStr = \"\";\n    switch (target) {\n      case LinkTarget.NONE:\n        break;\n      case LinkTarget.SELF:\n        targetStr = \"_self\";\n        break;\n      case LinkTarget.BLANK:\n        targetStr = \"_blank\";\n        break;\n      case LinkTarget.PARENT:\n        targetStr = \"_parent\";\n        break;\n      case LinkTarget.TOP:\n        targetStr = \"_top\";\n        break;\n    }\n    link.target = targetStr;\n    link.rel = typeof rel === \"string\" ? rel : DEFAULT_LINK_REL;\n  }\n  getDestinationHash(dest) {\n    if (typeof dest === \"string\") {\n      if (dest.length > 0) {\n        return this.getAnchorUrl(\"#\" + escape(dest));\n      }\n    } else if (Array.isArray(dest)) {\n      const str = JSON.stringify(dest);\n      if (str.length > 0) {\n        return this.getAnchorUrl(\"#\" + escape(str));\n      }\n    }\n    return this.getAnchorUrl(\"\");\n  }\n  getAnchorUrl(anchor) {\n    return this.baseUrl ? this.baseUrl + anchor : anchor;\n  }\n  setHash(hash) {\n    if (!this.pdfDocument) {\n      return;\n    }\n    let pageNumber, dest;\n    if (hash.includes(\"=\")) {\n      const params = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.parseQueryString)(hash);\n      if (params.has(\"search\")) {\n        const query = params.get(\"search\").replaceAll('\"', \"\"),\n          phrase = params.get(\"phrase\") === \"true\";\n        this.eventBus.dispatch(\"findfromurlhash\", {\n          source: this,\n          query: phrase ? query : query.match(/\\S+/g)\n        });\n      }\n      if (params.has(\"page\")) {\n        pageNumber = params.get(\"page\") | 0 || 1;\n      }\n      if (params.has(\"zoom\")) {\n        const zoomArgs = params.get(\"zoom\").split(\",\");\n        const zoomArg = zoomArgs[0];\n        const zoomArgNumber = parseFloat(zoomArg);\n        if (!zoomArg.includes(\"Fit\")) {\n          dest = [null, {\n            name: \"XYZ\"\n          }, zoomArgs.length > 1 ? zoomArgs[1] | 0 : null, zoomArgs.length > 2 ? zoomArgs[2] | 0 : null, zoomArgNumber ? zoomArgNumber / 100 : zoomArg];\n        } else if (zoomArg === \"Fit\" || zoomArg === \"FitB\") {\n          dest = [null, {\n            name: zoomArg\n          }];\n        } else if (zoomArg === \"FitH\" || zoomArg === \"FitBH\" || zoomArg === \"FitV\" || zoomArg === \"FitBV\") {\n          dest = [null, {\n            name: zoomArg\n          }, zoomArgs.length > 1 ? zoomArgs[1] | 0 : null];\n        } else if (zoomArg === \"FitR\") {\n          if (zoomArgs.length !== 5) {\n            console.error('PDFLinkService.setHash: Not enough parameters for \"FitR\".');\n          } else {\n            dest = [null, {\n              name: zoomArg\n            }, zoomArgs[1] | 0, zoomArgs[2] | 0, zoomArgs[3] | 0, zoomArgs[4] | 0];\n          }\n        } else {\n          console.error(`PDFLinkService.setHash: \"${zoomArg}\" is not a valid zoom value.`);\n        }\n      }\n      if (dest) {\n        this.pdfViewer.scrollPageIntoView({\n          pageNumber: pageNumber || this.page,\n          destArray: dest,\n          allowNegativeOffset: true\n        });\n      } else if (pageNumber) {\n        this.page = pageNumber;\n      }\n      if (params.has(\"pagemode\")) {\n        this.eventBus.dispatch(\"pagemode\", {\n          source: this,\n          mode: params.get(\"pagemode\")\n        });\n      }\n      if (params.has(\"nameddest\")) {\n        this.goToDestination(params.get(\"nameddest\"));\n      }\n      return;\n    }\n    dest = unescape(hash);\n    try {\n      dest = JSON.parse(dest);\n      if (!Array.isArray(dest)) {\n        dest = dest.toString();\n      }\n    } catch {}\n    if (typeof dest === \"string\" || PDFLinkService.#isValidExplicitDest(dest)) {\n      this.goToDestination(dest);\n      return;\n    }\n    console.error(`PDFLinkService.setHash: \"${unescape(hash)}\" is not a valid destination.`);\n  }\n  executeNamedAction(action) {\n    if (!this.pdfDocument) {\n      return;\n    }\n    switch (action) {\n      case \"GoBack\":\n        this.pdfHistory?.back();\n        break;\n      case \"GoForward\":\n        this.pdfHistory?.forward();\n        break;\n      case \"NextPage\":\n        this.pdfViewer.nextPage();\n        break;\n      case \"PrevPage\":\n        this.pdfViewer.previousPage();\n        break;\n      case \"LastPage\":\n        this.page = this.pagesCount;\n        break;\n      case \"FirstPage\":\n        this.page = 1;\n        break;\n      default:\n        break;\n    }\n    this.eventBus.dispatch(\"namedaction\", {\n      source: this,\n      action\n    });\n  }\n  async executeSetOCGState(action) {\n    if (!this.pdfDocument) {\n      return;\n    }\n    const pdfDocument = this.pdfDocument,\n      optionalContentConfig = await this.pdfViewer.optionalContentConfigPromise;\n    if (pdfDocument !== this.pdfDocument) {\n      return;\n    }\n    optionalContentConfig.setOCGState(action);\n    this.pdfViewer.optionalContentConfigPromise = Promise.resolve(optionalContentConfig);\n  }\n  static #isValidExplicitDest(dest) {\n    if (!Array.isArray(dest) || dest.length < 2) {\n      return false;\n    }\n    const [page, zoom, ...args] = dest;\n    if (!(typeof page === \"object\" && Number.isInteger(page?.num) && Number.isInteger(page?.gen)) && !Number.isInteger(page)) {\n      return false;\n    }\n    if (!(typeof zoom === \"object\" && typeof zoom?.name === \"string\")) {\n      return false;\n    }\n    let allowNull = true;\n    switch (zoom.name) {\n      case \"XYZ\":\n        if (args.length !== 3) {\n          return false;\n        }\n        break;\n      case \"Fit\":\n      case \"FitB\":\n        return args.length === 0;\n      case \"FitH\":\n      case \"FitBH\":\n      case \"FitV\":\n      case \"FitBV\":\n        if (args.length !== 1) {\n          return false;\n        }\n        break;\n      case \"FitR\":\n        if (args.length !== 4) {\n          return false;\n        }\n        allowNull = false;\n        break;\n      default:\n        return false;\n    }\n    for (const arg of args) {\n      if (!(typeof arg === \"number\" || allowNull && arg === null)) {\n        return false;\n      }\n    }\n    return true;\n  }\n}\nclass SimpleLinkService extends PDFLinkService {\n  setDocument(pdfDocument, baseUrl = null) {}\n}\n\n\n/***/ }),\n\n/***/ 5514:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   PDFOutlineViewer: () => (/* binding */ PDFOutlineViewer)\n/* harmony export */ });\n/* harmony import */ var _base_tree_viewer_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2961);\n/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7256);\n\n\nclass PDFOutlineViewer extends _base_tree_viewer_js__WEBPACK_IMPORTED_MODULE_0__.BaseTreeViewer {\n  constructor(options) {\n    super(options);\n    this.linkService = options.linkService;\n    this.downloadManager = options.downloadManager;\n    this.eventBus._on(\"toggleoutlinetree\", this._toggleAllTreeItems.bind(this));\n    this.eventBus._on(\"currentoutlineitem\", this._currentOutlineItem.bind(this));\n    this.eventBus._on(\"pagechanging\", evt => {\n      this._currentPageNumber = evt.pageNumber;\n    });\n    this.eventBus._on(\"pagesloaded\", evt => {\n      this._isPagesLoaded = !!evt.pagesCount;\n      this._currentOutlineItemCapability?.resolve(this._isPagesLoaded);\n    });\n    this.eventBus._on(\"sidebarviewchanged\", evt => {\n      this._sidebarView = evt.view;\n    });\n  }\n  reset() {\n    super.reset();\n    this._outline = null;\n    this._pageNumberToDestHashCapability = null;\n    this._currentPageNumber = 1;\n    this._isPagesLoaded = null;\n    this._currentOutlineItemCapability?.resolve(false);\n    this._currentOutlineItemCapability = null;\n  }\n  _dispatchEvent(outlineCount) {\n    this._currentOutlineItemCapability = Promise.withResolvers();\n    if (outlineCount === 0 || this._pdfDocument?.loadingParams.disableAutoFetch) {\n      this._currentOutlineItemCapability.resolve(false);\n    } else if (this._isPagesLoaded !== null) {\n      this._currentOutlineItemCapability.resolve(this._isPagesLoaded);\n    }\n    this.eventBus.dispatch(\"outlineloaded\", {\n      source: this,\n      outlineCount,\n      currentOutlineItemPromise: this._currentOutlineItemCapability.promise\n    });\n  }\n  _bindLink(element, {\n    url,\n    newWindow,\n    action,\n    attachment,\n    dest,\n    setOCGState\n  }) {\n    const {\n      linkService\n    } = this;\n    if (url) {\n      linkService.addLinkAttributes(element, url, newWindow);\n      return;\n    }\n    if (action) {\n      element.href = linkService.getAnchorUrl(\"\");\n      element.onclick = () => {\n        linkService.executeNamedAction(action);\n        return false;\n      };\n      return;\n    }\n    if (attachment) {\n      element.href = linkService.getAnchorUrl(\"\");\n      element.onclick = () => {\n        this.downloadManager.openOrDownloadData(attachment.content, attachment.filename);\n        return false;\n      };\n      return;\n    }\n    if (setOCGState) {\n      element.href = linkService.getAnchorUrl(\"\");\n      element.onclick = () => {\n        linkService.executeSetOCGState(setOCGState);\n        return false;\n      };\n      return;\n    }\n    element.href = linkService.getDestinationHash(dest);\n    element.onclick = evt => {\n      this._updateCurrentTreeItem(evt.target.parentNode);\n      if (dest) {\n        linkService.goToDestination(dest);\n      }\n      return false;\n    };\n  }\n  _setStyles(element, {\n    bold,\n    italic\n  }) {\n    if (bold) {\n      element.style.fontWeight = \"bold\";\n    }\n    if (italic) {\n      element.style.fontStyle = \"italic\";\n    }\n  }\n  _addToggleButton(div, {\n    count,\n    items\n  }) {\n    let hidden = false;\n    if (count < 0) {\n      let totalCount = items.length;\n      if (totalCount > 0) {\n        const queue = [...items];\n        while (queue.length > 0) {\n          const {\n            count: nestedCount,\n            items: nestedItems\n          } = queue.shift();\n          if (nestedCount > 0 && nestedItems.length > 0) {\n            totalCount += nestedItems.length;\n            queue.push(...nestedItems);\n          }\n        }\n      }\n      if (Math.abs(count) === totalCount) {\n        hidden = true;\n      }\n    }\n    super._addToggleButton(div, hidden);\n  }\n  _toggleAllTreeItems() {\n    if (!this._outline) {\n      return;\n    }\n    super._toggleAllTreeItems();\n  }\n  render({\n    outline,\n    pdfDocument\n  }) {\n    if (this._outline) {\n      this.reset();\n    }\n    this._outline = outline || null;\n    this._pdfDocument = pdfDocument || null;\n    if (!outline) {\n      this._dispatchEvent(0);\n      return;\n    }\n    const fragment = document.createDocumentFragment();\n    const queue = [{\n      parent: fragment,\n      items: outline\n    }];\n    let outlineCount = 0,\n      hasAnyNesting = false;\n    while (queue.length > 0) {\n      const levelData = queue.shift();\n      for (const item of levelData.items) {\n        const div = document.createElement(\"div\");\n        div.className = \"treeItem\";\n        const element = document.createElement(\"a\");\n        this._bindLink(element, item);\n        this._setStyles(element, item);\n        element.textContent = this._normalizeTextContent(item.title);\n        div.append(element);\n        if (item.items.length > 0) {\n          hasAnyNesting = true;\n          this._addToggleButton(div, item);\n          const itemsDiv = document.createElement(\"div\");\n          itemsDiv.className = \"treeItems\";\n          div.append(itemsDiv);\n          queue.push({\n            parent: itemsDiv,\n            items: item.items\n          });\n        }\n        levelData.parent.append(div);\n        outlineCount++;\n      }\n    }\n    this._finishRendering(fragment, outlineCount, hasAnyNesting);\n  }\n  async _currentOutlineItem() {\n    if (!this._isPagesLoaded) {\n      throw new Error(\"_currentOutlineItem: All pages have not been loaded.\");\n    }\n    if (!this._outline || !this._pdfDocument) {\n      return;\n    }\n    const pageNumberToDestHash = await this._getPageNumberToDestHash(this._pdfDocument);\n    if (!pageNumberToDestHash) {\n      return;\n    }\n    this._updateCurrentTreeItem(null);\n    if (this._sidebarView !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.SidebarView.OUTLINE) {\n      return;\n    }\n    for (let i = this._currentPageNumber; i > 0; i--) {\n      const destHash = pageNumberToDestHash.get(i);\n      if (!destHash) {\n        continue;\n      }\n      const linkElement = this.container.querySelector(`a[href=\"${destHash}\"]`);\n      if (!linkElement) {\n        continue;\n      }\n      this._scrollToCurrentTreeItem(linkElement.parentNode);\n      break;\n    }\n  }\n  async _getPageNumberToDestHash(pdfDocument) {\n    if (this._pageNumberToDestHashCapability) {\n      return this._pageNumberToDestHashCapability.promise;\n    }\n    this._pageNumberToDestHashCapability = Promise.withResolvers();\n    const pageNumberToDestHash = new Map(),\n      pageNumberNesting = new Map();\n    const queue = [{\n      nesting: 0,\n      items: this._outline\n    }];\n    while (queue.length > 0) {\n      const levelData = queue.shift(),\n        currentNesting = levelData.nesting;\n      for (const {\n        dest,\n        items\n      } of levelData.items) {\n        let explicitDest, pageNumber;\n        if (typeof dest === \"string\") {\n          explicitDest = await pdfDocument.getDestination(dest);\n          if (pdfDocument !== this._pdfDocument) {\n            return null;\n          }\n        } else {\n          explicitDest = dest;\n        }\n        if (Array.isArray(explicitDest)) {\n          const [destRef] = explicitDest;\n          if (destRef && typeof destRef === \"object\") {\n            pageNumber = pdfDocument.cachedPageNumber(destRef);\n          } else if (Number.isInteger(destRef)) {\n            pageNumber = destRef + 1;\n          }\n          if (Number.isInteger(pageNumber) && (!pageNumberToDestHash.has(pageNumber) || currentNesting > pageNumberNesting.get(pageNumber))) {\n            const destHash = this.linkService.getDestinationHash(dest);\n            pageNumberToDestHash.set(pageNumber, destHash);\n            pageNumberNesting.set(pageNumber, currentNesting);\n          }\n        }\n        if (items.length > 0) {\n          queue.push({\n            nesting: currentNesting + 1,\n            items\n          });\n        }\n      }\n    }\n    this._pageNumberToDestHashCapability.resolve(pageNumberToDestHash.size > 0 ? pageNumberToDestHash : null);\n    return this._pageNumberToDestHashCapability.promise;\n  }\n}\n\n\n/***/ }),\n\n/***/ 9966:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   PDFPageView: () => (/* binding */ PDFPageView)\n/* harmony export */ });\n/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603);\n/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7256);\n/* harmony import */ var _annotation_editor_layer_builder_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(283);\n/* harmony import */ var _annotation_layer_builder_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(2707);\n/* harmony import */ var _app_options_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(9840);\n/* harmony import */ var _draw_layer_builder_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(3088);\n/* harmony import */ var web_null_l10n__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(410);\n/* harmony import */ var _pdf_link_service_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(787);\n/* harmony import */ var _struct_tree_layer_builder_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(6698);\n/* harmony import */ var _text_accessibility_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(5860);\n/* harmony import */ var _text_highlighter_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(2027);\n/* harmony import */ var _text_layer_builder_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(7765);\n/* harmony import */ var _xfa_layer_builder_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(2973);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__, _annotation_editor_layer_builder_js__WEBPACK_IMPORTED_MODULE_2__, _annotation_layer_builder_js__WEBPACK_IMPORTED_MODULE_3__, _draw_layer_builder_js__WEBPACK_IMPORTED_MODULE_5__, web_null_l10n__WEBPACK_IMPORTED_MODULE_6__, _text_layer_builder_js__WEBPACK_IMPORTED_MODULE_10__, _xfa_layer_builder_js__WEBPACK_IMPORTED_MODULE_11__]);\n([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__, _annotation_editor_layer_builder_js__WEBPACK_IMPORTED_MODULE_2__, _annotation_layer_builder_js__WEBPACK_IMPORTED_MODULE_3__, _draw_layer_builder_js__WEBPACK_IMPORTED_MODULE_5__, web_null_l10n__WEBPACK_IMPORTED_MODULE_6__, _text_layer_builder_js__WEBPACK_IMPORTED_MODULE_10__, _xfa_layer_builder_js__WEBPACK_IMPORTED_MODULE_11__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__);\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst DEFAULT_LAYER_PROPERTIES = null;\nconst LAYERS_ORDER = new Map([[\"canvasWrapper\", 0], [\"textLayer\", 1], [\"annotationLayer\", 2], [\"annotationEditorLayer\", 3], [\"xfaLayer\", 3]]);\nclass PDFPageView {\n  #annotationMode = pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE_FORMS;\n  #hasRestrictedScaling = false;\n  #layerProperties = null;\n  #loadingId = null;\n  #previousRotation = null;\n  #renderError = null;\n  #renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.INITIAL;\n  #textLayerMode = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.TextLayerMode.ENABLE;\n  #useThumbnailCanvas = {\n    directDrawing: true,\n    initialOptionalContent: true,\n    regularAnnotations: true\n  };\n  #viewportMap = new WeakMap();\n  #layers = [null, null, null, null];\n  constructor(options) {\n    const container = options.container;\n    const defaultViewport = options.defaultViewport;\n    this.id = options.id;\n    this.renderingId = \"page\" + this.id;\n    this.#layerProperties = options.layerProperties || DEFAULT_LAYER_PROPERTIES;\n    this.pdfPage = null;\n    this.pageLabel = null;\n    this.rotation = 0;\n    this.scale = options.scale || _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.DEFAULT_SCALE;\n    this.viewport = defaultViewport;\n    this.pdfPageRotate = defaultViewport.rotation;\n    this._optionalContentConfigPromise = options.optionalContentConfigPromise || null;\n    this.#textLayerMode = options.textLayerMode ?? _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.TextLayerMode.ENABLE;\n    this.#annotationMode = options.annotationMode ?? pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE_FORMS;\n    this.imageResourcesPath = options.imageResourcesPath || \"\";\n    this.maxCanvasPixels = options.maxCanvasPixels ?? _app_options_js__WEBPACK_IMPORTED_MODULE_4__.AppOptions.get(\"maxCanvasPixels\");\n    this.pageColors = options.pageColors || null;\n    this.eventBus = options.eventBus;\n    this.renderingQueue = options.renderingQueue;\n    this.l10n = options.l10n;\n    this.l10n ||= new web_null_l10n__WEBPACK_IMPORTED_MODULE_6__.GenericL10n();\n    this.renderTask = null;\n    this.resume = null;\n    this._isStandalone = !this.renderingQueue?.hasViewer();\n    this._container = container;\n    this._annotationCanvasMap = null;\n    this.annotationLayer = null;\n    this.annotationEditorLayer = null;\n    this.textLayer = null;\n    this.zoomLayer = null;\n    this.xfaLayer = null;\n    this.structTreeLayer = null;\n    this.drawLayer = null;\n    const div = document.createElement(\"div\");\n    div.className = \"page\";\n    div.setAttribute(\"data-page-number\", this.id);\n    div.setAttribute(\"role\", \"region\");\n    div.setAttribute(\"data-l10n-id\", \"pdfjs-page-landmark\");\n    div.setAttribute(\"data-l10n-args\", JSON.stringify({\n      page: this.id\n    }));\n    this.div = div;\n    this.#setDimensions();\n    container?.append(div);\n    if (this._isStandalone) {\n      container?.style.setProperty(\"--scale-factor\", this.scale * pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PixelsPerInch.PDF_TO_CSS_UNITS);\n      const {\n        optionalContentConfigPromise\n      } = options;\n      if (optionalContentConfigPromise) {\n        optionalContentConfigPromise.then(optionalContentConfig => {\n          if (optionalContentConfigPromise !== this._optionalContentConfigPromise) {\n            return;\n          }\n          this.#useThumbnailCanvas.initialOptionalContent = optionalContentConfig.hasInitialVisibility;\n        });\n      }\n      if (!options.l10n) {\n        this.l10n.translate(this.div);\n      }\n    }\n  }\n  #addLayer(div, name) {\n    const pos = LAYERS_ORDER.get(name);\n    const oldDiv = this.#layers[pos];\n    this.#layers[pos] = div;\n    if (oldDiv) {\n      oldDiv.replaceWith(div);\n      return;\n    }\n    for (let i = pos - 1; i >= 0; i--) {\n      const layer = this.#layers[i];\n      if (layer) {\n        layer.after(div);\n        return;\n      }\n    }\n    this.div.prepend(div);\n  }\n  get renderingState() {\n    return this.#renderingState;\n  }\n  set renderingState(state) {\n    if (state === this.#renderingState) {\n      return;\n    }\n    this.#renderingState = state;\n    if (this.#loadingId) {\n      clearTimeout(this.#loadingId);\n      this.#loadingId = null;\n    }\n    switch (state) {\n      case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.PAUSED:\n        this.div.classList.remove(\"loading\");\n        break;\n      case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.RUNNING:\n        this.div.classList.add(\"loadingIcon\");\n        this.#loadingId = setTimeout(() => {\n          this.div.classList.add(\"loading\");\n          this.#loadingId = null;\n        }, 0);\n        break;\n      case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.INITIAL:\n      case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.FINISHED:\n        this.div.classList.remove(\"loadingIcon\", \"loading\");\n        break;\n    }\n  }\n  #setDimensions() {\n    const {\n      viewport\n    } = this;\n    if (this.pdfPage) {\n      if (this.#previousRotation === viewport.rotation) {\n        return;\n      }\n      this.#previousRotation = viewport.rotation;\n    }\n    (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.setLayerDimensions)(this.div, viewport, true, false);\n  }\n  setPdfPage(pdfPage) {\n    if (this._isStandalone && (this.pageColors?.foreground === \"CanvasText\" || this.pageColors?.background === \"Canvas\")) {\n      this._container?.style.setProperty(\"--hcm-highlight-filter\", pdfPage.filterFactory.addHighlightHCMFilter(\"highlight\", \"CanvasText\", \"Canvas\", \"HighlightText\", \"Highlight\"));\n      this._container?.style.setProperty(\"--hcm-highlight-selected-filter\", pdfPage.filterFactory.addHighlightHCMFilter(\"highlight_selected\", \"CanvasText\", \"Canvas\", \"HighlightText\", \"Highlight\"));\n    }\n    this.pdfPage = pdfPage;\n    this.pdfPageRotate = pdfPage.rotate;\n    const totalRotation = (this.rotation + this.pdfPageRotate) % 360;\n    this.viewport = pdfPage.getViewport({\n      scale: this.scale * pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PixelsPerInch.PDF_TO_CSS_UNITS,\n      rotation: totalRotation\n    });\n    this.#setDimensions();\n    this.reset();\n  }\n  destroy() {\n    this.reset();\n    this.pdfPage?.cleanup();\n  }\n  get _textHighlighter() {\n    return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, \"_textHighlighter\", new _text_highlighter_js__WEBPACK_IMPORTED_MODULE_12__.TextHighlighter({\n      pageIndex: this.id - 1,\n      eventBus: this.eventBus,\n      findController: this.#layerProperties.findController\n    }));\n  }\n  async #renderAnnotationLayer() {\n    let error = null;\n    try {\n      await this.annotationLayer.render(this.viewport, \"display\");\n    } catch (ex) {\n      console.error(`#renderAnnotationLayer: \"${ex}\".`);\n      error = ex;\n    } finally {\n      this.eventBus.dispatch(\"annotationlayerrendered\", {\n        source: this,\n        pageNumber: this.id,\n        error\n      });\n    }\n  }\n  async #renderAnnotationEditorLayer() {\n    let error = null;\n    try {\n      await this.annotationEditorLayer.render(this.viewport, \"display\");\n    } catch (ex) {\n      console.error(`#renderAnnotationEditorLayer: \"${ex}\".`);\n      error = ex;\n    } finally {\n      this.eventBus.dispatch(\"annotationeditorlayerrendered\", {\n        source: this,\n        pageNumber: this.id,\n        error\n      });\n    }\n  }\n  async #renderDrawLayer() {\n    try {\n      await this.drawLayer.render(\"display\");\n    } catch (ex) {\n      console.error(`#renderDrawLayer: \"${ex}\".`);\n    }\n  }\n  async #renderXfaLayer() {\n    let error = null;\n    try {\n      const result = await this.xfaLayer.render(this.viewport, \"display\");\n      if (result?.textDivs && this._textHighlighter) {\n        this.#buildXfaTextContentItems(result.textDivs);\n      }\n    } catch (ex) {\n      console.error(`#renderXfaLayer: \"${ex}\".`);\n      error = ex;\n    } finally {\n      if (this.xfaLayer?.div) {\n        this.l10n.pause();\n        this.#addLayer(this.xfaLayer.div, \"xfaLayer\");\n        this.l10n.resume();\n      }\n      this.eventBus.dispatch(\"xfalayerrendered\", {\n        source: this,\n        pageNumber: this.id,\n        error\n      });\n    }\n  }\n  async #renderTextLayer() {\n    const {\n      pdfPage,\n      textLayer,\n      viewport\n    } = this;\n    if (!textLayer) {\n      return;\n    }\n    let error = null;\n    try {\n      if (!textLayer.renderingDone) {\n        const readableStream = pdfPage.streamTextContent({\n          includeMarkedContent: true,\n          disableNormalization: true\n        });\n        textLayer.setTextContentSource(readableStream);\n      }\n      await textLayer.render(viewport);\n    } catch (ex) {\n      if (ex instanceof pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AbortException) {\n        return;\n      }\n      console.error(`#renderTextLayer: \"${ex}\".`);\n      error = ex;\n    }\n    this.eventBus.dispatch(\"textlayerrendered\", {\n      source: this,\n      pageNumber: this.id,\n      numTextDivs: textLayer.numTextDivs,\n      error\n    });\n    this.#renderStructTreeLayer();\n  }\n  async #renderStructTreeLayer() {\n    if (!this.textLayer) {\n      return;\n    }\n    this.structTreeLayer ||= new _struct_tree_layer_builder_js__WEBPACK_IMPORTED_MODULE_8__.StructTreeLayerBuilder();\n    const tree = await (!this.structTreeLayer.renderingDone ? this.pdfPage.getStructTree() : null);\n    const treeDom = this.structTreeLayer?.render(tree);\n    if (treeDom) {\n      this.l10n.pause();\n      this.canvas?.append(treeDom);\n      this.l10n.resume();\n    }\n    this.structTreeLayer?.show();\n  }\n  async #buildXfaTextContentItems(textDivs) {\n    const text = await this.pdfPage.getTextContent();\n    const items = [];\n    for (const item of text.items) {\n      items.push(item.str);\n    }\n    this._textHighlighter.setTextMapping(textDivs, items);\n    this._textHighlighter.enable();\n  }\n  _resetZoomLayer(removeFromDOM = false) {\n    if (!this.zoomLayer) {\n      return;\n    }\n    const zoomLayerCanvas = this.zoomLayer.firstChild;\n    this.#viewportMap.delete(zoomLayerCanvas);\n    zoomLayerCanvas.width = 0;\n    zoomLayerCanvas.height = 0;\n    if (removeFromDOM) {\n      this.zoomLayer.remove();\n    }\n    this.zoomLayer = null;\n  }\n  reset({\n    keepZoomLayer = false,\n    keepAnnotationLayer = false,\n    keepAnnotationEditorLayer = false,\n    keepXfaLayer = false,\n    keepTextLayer = false\n  } = {}) {\n    this.cancelRendering({\n      keepAnnotationLayer,\n      keepAnnotationEditorLayer,\n      keepXfaLayer,\n      keepTextLayer\n    });\n    this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.INITIAL;\n    const div = this.div;\n    const childNodes = div.childNodes,\n      zoomLayerNode = keepZoomLayer && this.zoomLayer || null,\n      annotationLayerNode = keepAnnotationLayer && this.annotationLayer?.div || null,\n      annotationEditorLayerNode = keepAnnotationEditorLayer && this.annotationEditorLayer?.div || null,\n      xfaLayerNode = keepXfaLayer && this.xfaLayer?.div || null,\n      textLayerNode = keepTextLayer && this.textLayer?.div || null;\n    for (let i = childNodes.length - 1; i >= 0; i--) {\n      const node = childNodes[i];\n      switch (node) {\n        case zoomLayerNode:\n        case annotationLayerNode:\n        case annotationEditorLayerNode:\n        case xfaLayerNode:\n        case textLayerNode:\n          continue;\n      }\n      node.remove();\n      const layerIndex = this.#layers.indexOf(node);\n      if (layerIndex >= 0) {\n        this.#layers[layerIndex] = null;\n      }\n    }\n    div.removeAttribute(\"data-loaded\");\n    if (annotationLayerNode) {\n      this.annotationLayer.hide();\n    }\n    if (annotationEditorLayerNode) {\n      this.annotationEditorLayer.hide();\n    }\n    if (xfaLayerNode) {\n      this.xfaLayer.hide();\n    }\n    if (textLayerNode) {\n      this.textLayer.hide();\n    }\n    this.structTreeLayer?.hide();\n    if (!zoomLayerNode) {\n      if (this.canvas) {\n        this.#viewportMap.delete(this.canvas);\n        this.canvas.width = 0;\n        this.canvas.height = 0;\n        delete this.canvas;\n      }\n      this._resetZoomLayer();\n    }\n  }\n  update({\n    scale = 0,\n    rotation = null,\n    optionalContentConfigPromise = null,\n    drawingDelay = -1\n  }) {\n    this.scale = scale || this.scale;\n    if (typeof rotation === \"number\") {\n      this.rotation = rotation;\n    }\n    if (optionalContentConfigPromise instanceof Promise) {\n      this._optionalContentConfigPromise = optionalContentConfigPromise;\n      optionalContentConfigPromise.then(optionalContentConfig => {\n        if (optionalContentConfigPromise !== this._optionalContentConfigPromise) {\n          return;\n        }\n        this.#useThumbnailCanvas.initialOptionalContent = optionalContentConfig.hasInitialVisibility;\n      });\n    }\n    this.#useThumbnailCanvas.directDrawing = true;\n    const totalRotation = (this.rotation + this.pdfPageRotate) % 360;\n    this.viewport = this.viewport.clone({\n      scale: this.scale * pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PixelsPerInch.PDF_TO_CSS_UNITS,\n      rotation: totalRotation\n    });\n    this.#setDimensions();\n    if (this._isStandalone) {\n      this._container?.style.setProperty(\"--scale-factor\", this.viewport.scale);\n    }\n    if (this.canvas) {\n      let onlyCssZoom = false;\n      if (this.#hasRestrictedScaling) {\n        if (this.maxCanvasPixels === 0) {\n          onlyCssZoom = true;\n        } else if (this.maxCanvasPixels > 0) {\n          const {\n            width,\n            height\n          } = this.viewport;\n          const {\n            sx,\n            sy\n          } = this.outputScale;\n          onlyCssZoom = (Math.floor(width) * sx | 0) * (Math.floor(height) * sy | 0) > this.maxCanvasPixels;\n        }\n      }\n      const postponeDrawing = !onlyCssZoom && drawingDelay >= 0 && drawingDelay < 1000;\n      if (postponeDrawing || onlyCssZoom) {\n        if (postponeDrawing && this.renderingState !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.FINISHED) {\n          this.cancelRendering({\n            keepZoomLayer: true,\n            keepAnnotationLayer: true,\n            keepAnnotationEditorLayer: true,\n            keepXfaLayer: true,\n            keepTextLayer: true,\n            cancelExtraDelay: drawingDelay\n          });\n          this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.FINISHED;\n          this.#useThumbnailCanvas.directDrawing = false;\n        }\n        this.cssTransform({\n          target: this.canvas,\n          redrawAnnotationLayer: true,\n          redrawAnnotationEditorLayer: true,\n          redrawXfaLayer: true,\n          redrawTextLayer: !postponeDrawing,\n          hideTextLayer: postponeDrawing\n        });\n        if (postponeDrawing) {\n          return;\n        }\n        this.eventBus.dispatch(\"pagerendered\", {\n          source: this,\n          pageNumber: this.id,\n          cssTransform: true,\n          timestamp: performance.now(),\n          error: this.#renderError\n        });\n        return;\n      }\n      if (!this.zoomLayer && !this.canvas.hidden) {\n        this.zoomLayer = this.canvas.parentNode;\n        this.zoomLayer.style.position = \"absolute\";\n      }\n    }\n    if (this.zoomLayer) {\n      this.cssTransform({\n        target: this.zoomLayer.firstChild\n      });\n    }\n    this.reset({\n      keepZoomLayer: true,\n      keepAnnotationLayer: true,\n      keepAnnotationEditorLayer: true,\n      keepXfaLayer: true,\n      keepTextLayer: true\n    });\n  }\n  cancelRendering({\n    keepAnnotationLayer = false,\n    keepAnnotationEditorLayer = false,\n    keepXfaLayer = false,\n    keepTextLayer = false,\n    cancelExtraDelay = 0\n  } = {}) {\n    if (this.renderTask) {\n      this.renderTask.cancel(cancelExtraDelay);\n      this.renderTask = null;\n    }\n    this.resume = null;\n    if (this.textLayer && (!keepTextLayer || !this.textLayer.div)) {\n      this.textLayer.cancel();\n      this.textLayer = null;\n    }\n    if (this.structTreeLayer && !this.textLayer) {\n      this.structTreeLayer = null;\n    }\n    if (this.annotationLayer && (!keepAnnotationLayer || !this.annotationLayer.div)) {\n      this.annotationLayer.cancel();\n      this.annotationLayer = null;\n      this._annotationCanvasMap = null;\n    }\n    if (this.annotationEditorLayer && (!keepAnnotationEditorLayer || !this.annotationEditorLayer.div)) {\n      if (this.drawLayer) {\n        this.drawLayer.cancel();\n        this.drawLayer = null;\n      }\n      this.annotationEditorLayer.cancel();\n      this.annotationEditorLayer = null;\n    }\n    if (this.xfaLayer && (!keepXfaLayer || !this.xfaLayer.div)) {\n      this.xfaLayer.cancel();\n      this.xfaLayer = null;\n      this._textHighlighter?.disable();\n    }\n  }\n  cssTransform({\n    target,\n    redrawAnnotationLayer = false,\n    redrawAnnotationEditorLayer = false,\n    redrawXfaLayer = false,\n    redrawTextLayer = false,\n    hideTextLayer = false\n  }) {\n    if (!target.hasAttribute(\"zooming\")) {\n      target.setAttribute(\"zooming\", true);\n      const {\n        style\n      } = target;\n      style.width = style.height = \"\";\n    }\n    const originalViewport = this.#viewportMap.get(target);\n    if (this.viewport !== originalViewport) {\n      const relativeRotation = this.viewport.rotation - originalViewport.rotation;\n      const absRotation = Math.abs(relativeRotation);\n      let scaleX = 1,\n        scaleY = 1;\n      if (absRotation === 90 || absRotation === 270) {\n        const {\n          width,\n          height\n        } = this.viewport;\n        scaleX = height / width;\n        scaleY = width / height;\n      }\n      target.style.transform = `rotate(${relativeRotation}deg) scale(${scaleX}, ${scaleY})`;\n    }\n    if (redrawAnnotationLayer && this.annotationLayer) {\n      this.#renderAnnotationLayer();\n    }\n    if (redrawAnnotationEditorLayer && this.annotationEditorLayer) {\n      if (this.drawLayer) {\n        this.#renderDrawLayer();\n      }\n      this.#renderAnnotationEditorLayer();\n    }\n    if (redrawXfaLayer && this.xfaLayer) {\n      this.#renderXfaLayer();\n    }\n    if (this.textLayer) {\n      if (hideTextLayer) {\n        this.textLayer.hide();\n        this.structTreeLayer?.hide();\n      } else if (redrawTextLayer) {\n        this.#renderTextLayer();\n      }\n    }\n  }\n  get width() {\n    return this.viewport.width;\n  }\n  get height() {\n    return this.viewport.height;\n  }\n  getPagePoint(x, y) {\n    return this.viewport.convertToPdfPoint(x, y);\n  }\n  async #finishRenderTask(renderTask, error = null) {\n    if (renderTask === this.renderTask) {\n      this.renderTask = null;\n    }\n    if (error instanceof pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.RenderingCancelledException) {\n      this.#renderError = null;\n      return;\n    }\n    this.#renderError = error;\n    this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.FINISHED;\n    this._resetZoomLayer(true);\n    this.#useThumbnailCanvas.regularAnnotations = !renderTask.separateAnnots;\n    this.eventBus.dispatch(\"pagerendered\", {\n      source: this,\n      pageNumber: this.id,\n      cssTransform: false,\n      timestamp: performance.now(),\n      error: this.#renderError\n    });\n    if (error) {\n      throw error;\n    }\n  }\n  async draw() {\n    if (this.renderingState !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.INITIAL) {\n      console.error(\"Must be in new state before drawing\");\n      this.reset();\n    }\n    const {\n      div,\n      l10n,\n      pageColors,\n      pdfPage,\n      viewport\n    } = this;\n    if (!pdfPage) {\n      this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.FINISHED;\n      throw new Error(\"pdfPage is not loaded\");\n    }\n    this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.RUNNING;\n    const canvasWrapper = document.createElement(\"div\");\n    canvasWrapper.classList.add(\"canvasWrapper\");\n    canvasWrapper.setAttribute(\"aria-hidden\", true);\n    this.#addLayer(canvasWrapper, \"canvasWrapper\");\n    if (!this.textLayer && this.#textLayerMode !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.TextLayerMode.DISABLE && !pdfPage.isPureXfa) {\n      this._accessibilityManager ||= new _text_accessibility_js__WEBPACK_IMPORTED_MODULE_9__.TextAccessibilityManager();\n      this.textLayer = new _text_layer_builder_js__WEBPACK_IMPORTED_MODULE_10__.TextLayerBuilder({\n        highlighter: this._textHighlighter,\n        accessibilityManager: this._accessibilityManager,\n        enablePermissions: this.#textLayerMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.TextLayerMode.ENABLE_PERMISSIONS,\n        onAppend: textLayerDiv => {\n          this.l10n.pause();\n          this.#addLayer(textLayerDiv, \"textLayer\");\n          this.l10n.resume();\n        }\n      });\n    }\n    if (!this.annotationLayer && this.#annotationMode !== pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.DISABLE) {\n      const {\n        annotationStorage,\n        annotationEditorUIManager,\n        downloadManager,\n        enableScripting,\n        fieldObjectsPromise,\n        hasJSActionsPromise,\n        linkService\n      } = this.#layerProperties;\n      this._annotationCanvasMap ||= new Map();\n      this.annotationLayer = new _annotation_layer_builder_js__WEBPACK_IMPORTED_MODULE_3__.AnnotationLayerBuilder({\n        pdfPage,\n        annotationStorage,\n        imageResourcesPath: this.imageResourcesPath,\n        renderForms: this.#annotationMode === pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE_FORMS,\n        linkService,\n        downloadManager,\n        enableScripting,\n        hasJSActionsPromise,\n        fieldObjectsPromise,\n        annotationCanvasMap: this._annotationCanvasMap,\n        accessibilityManager: this._accessibilityManager,\n        annotationEditorUIManager,\n        onAppend: annotationLayerDiv => {\n          this.#addLayer(annotationLayerDiv, \"annotationLayer\");\n        }\n      });\n    }\n    const renderContinueCallback = cont => {\n      showCanvas?.(false);\n      if (this.renderingQueue && !this.renderingQueue.isHighestPriority(this)) {\n        this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.PAUSED;\n        this.resume = () => {\n          this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.RUNNING;\n          cont();\n        };\n        return;\n      }\n      cont();\n    };\n    const {\n      width,\n      height\n    } = viewport;\n    const canvas = document.createElement(\"canvas\");\n    canvas.setAttribute(\"role\", \"presentation\");\n    canvas.hidden = true;\n    const hasHCM = !!(pageColors?.background && pageColors?.foreground);\n    let showCanvas = isLastShow => {\n      if (!hasHCM || isLastShow) {\n        canvas.hidden = false;\n        showCanvas = null;\n      }\n    };\n    canvasWrapper.append(canvas);\n    this.canvas = canvas;\n    const ctx = canvas.getContext(\"2d\", {\n      alpha: false\n    });\n    const outputScale = this.outputScale = new _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.OutputScale();\n    if (this.maxCanvasPixels === 0) {\n      const invScale = 1 / this.scale;\n      outputScale.sx *= invScale;\n      outputScale.sy *= invScale;\n      this.#hasRestrictedScaling = true;\n    } else if (this.maxCanvasPixels > 0) {\n      const pixelsInViewport = width * height;\n      const maxScale = Math.sqrt(this.maxCanvasPixels / pixelsInViewport);\n      if (outputScale.sx > maxScale || outputScale.sy > maxScale) {\n        outputScale.sx = maxScale;\n        outputScale.sy = maxScale;\n        this.#hasRestrictedScaling = true;\n      } else {\n        this.#hasRestrictedScaling = false;\n      }\n    }\n    const sfx = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.approximateFraction)(outputScale.sx);\n    const sfy = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.approximateFraction)(outputScale.sy);\n    canvas.width = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.roundToDivide)(width * outputScale.sx, sfx[0]);\n    canvas.height = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.roundToDivide)(height * outputScale.sy, sfy[0]);\n    const {\n      style\n    } = canvas;\n    style.width = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.roundToDivide)(width, sfx[1]) + \"px\";\n    style.height = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.roundToDivide)(height, sfy[1]) + \"px\";\n    this.#viewportMap.set(canvas, viewport);\n    const transform = outputScale.scaled ? [outputScale.sx, 0, 0, outputScale.sy, 0, 0] : null;\n    const renderContext = {\n      canvasContext: ctx,\n      transform,\n      viewport,\n      annotationMode: this.#annotationMode,\n      optionalContentConfigPromise: this._optionalContentConfigPromise,\n      annotationCanvasMap: this._annotationCanvasMap,\n      pageColors\n    };\n    const renderTask = this.renderTask = this.pdfPage.render(renderContext);\n    renderTask.onContinue = renderContinueCallback;\n    const resultPromise = renderTask.promise.then(async () => {\n      showCanvas?.(true);\n      await this.#finishRenderTask(renderTask);\n      this.#renderTextLayer();\n      if (this.annotationLayer) {\n        await this.#renderAnnotationLayer();\n      }\n      const {\n        annotationEditorUIManager\n      } = this.#layerProperties;\n      if (!annotationEditorUIManager) {\n        return;\n      }\n      this.drawLayer ||= new _draw_layer_builder_js__WEBPACK_IMPORTED_MODULE_5__.DrawLayerBuilder({\n        pageIndex: this.id\n      });\n      await this.#renderDrawLayer();\n      this.drawLayer.setParent(canvasWrapper);\n      if (!this.annotationEditorLayer) {\n        this.annotationEditorLayer = new _annotation_editor_layer_builder_js__WEBPACK_IMPORTED_MODULE_2__.AnnotationEditorLayerBuilder({\n          uiManager: annotationEditorUIManager,\n          pdfPage,\n          l10n,\n          accessibilityManager: this._accessibilityManager,\n          annotationLayer: this.annotationLayer?.annotationLayer,\n          textLayer: this.textLayer,\n          drawLayer: this.drawLayer.getDrawLayer(),\n          onAppend: annotationEditorLayerDiv => {\n            this.#addLayer(annotationEditorLayerDiv, \"annotationEditorLayer\");\n          }\n        });\n      }\n      this.#renderAnnotationEditorLayer();\n    }, error => {\n      if (!(error instanceof pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.RenderingCancelledException)) {\n        showCanvas?.(true);\n      }\n      return this.#finishRenderTask(renderTask, error);\n    });\n    if (pdfPage.isPureXfa) {\n      if (!this.xfaLayer) {\n        const {\n          annotationStorage,\n          linkService\n        } = this.#layerProperties;\n        this.xfaLayer = new _xfa_layer_builder_js__WEBPACK_IMPORTED_MODULE_11__.XfaLayerBuilder({\n          pdfPage,\n          annotationStorage,\n          linkService\n        });\n      }\n      this.#renderXfaLayer();\n    }\n    div.setAttribute(\"data-loaded\", true);\n    this.eventBus.dispatch(\"pagerender\", {\n      source: this,\n      pageNumber: this.id\n    });\n    return resultPromise;\n  }\n  setPageLabel(label) {\n    this.pageLabel = typeof label === \"string\" ? label : null;\n    this.div.setAttribute(\"data-l10n-args\", JSON.stringify({\n      page: this.pageLabel ?? this.id\n    }));\n    if (this.pageLabel !== null) {\n      this.div.setAttribute(\"data-page-label\", this.pageLabel);\n    } else {\n      this.div.removeAttribute(\"data-page-label\");\n    }\n  }\n  get thumbnailCanvas() {\n    const {\n      directDrawing,\n      initialOptionalContent,\n      regularAnnotations\n    } = this.#useThumbnailCanvas;\n    return directDrawing && initialOptionalContent && regularAnnotations ? this.canvas : null;\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 8917:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   PDFPresentationMode: () => (/* binding */ PDFPresentationMode)\n/* harmony export */ });\n/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256);\n/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2603);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__]);\npdfjs_lib__WEBPACK_IMPORTED_MODULE_1__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];\n\n\nconst DELAY_BEFORE_HIDING_CONTROLS = 3000;\nconst ACTIVE_SELECTOR = \"pdfPresentationMode\";\nconst CONTROLS_SELECTOR = \"pdfPresentationModeControls\";\nconst MOUSE_SCROLL_COOLDOWN_TIME = 50;\nconst PAGE_SWITCH_THRESHOLD = 0.1;\nconst SWIPE_MIN_DISTANCE_THRESHOLD = 50;\nconst SWIPE_ANGLE_THRESHOLD = Math.PI / 6;\nclass PDFPresentationMode {\n  #state = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.PresentationModeState.UNKNOWN;\n  #args = null;\n  #fullscreenChangeAbortController = null;\n  #windowAbortController = null;\n  constructor({\n    container,\n    pdfViewer,\n    eventBus\n  }) {\n    this.container = container;\n    this.pdfViewer = pdfViewer;\n    this.eventBus = eventBus;\n    this.contextMenuOpen = false;\n    this.mouseScrollTimeStamp = 0;\n    this.mouseScrollDelta = 0;\n    this.touchSwipeState = null;\n  }\n  async request() {\n    const {\n      container,\n      pdfViewer\n    } = this;\n    if (this.active || !pdfViewer.pagesCount || !container.requestFullscreen) {\n      return false;\n    }\n    this.#addFullscreenChangeListeners();\n    this.#notifyStateChange(_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.PresentationModeState.CHANGING);\n    const promise = container.requestFullscreen();\n    this.#args = {\n      pageNumber: pdfViewer.currentPageNumber,\n      scaleValue: pdfViewer.currentScaleValue,\n      scrollMode: pdfViewer.scrollMode,\n      spreadMode: null,\n      annotationEditorMode: null\n    };\n    if (pdfViewer.spreadMode !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SpreadMode.NONE && !(pdfViewer.pageViewsReady && pdfViewer.hasEqualPageSizes)) {\n      console.warn(\"Ignoring Spread modes when entering PresentationMode, \" + \"since the document may contain varying page sizes.\");\n      this.#args.spreadMode = pdfViewer.spreadMode;\n    }\n    if (pdfViewer.annotationEditorMode !== pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.AnnotationEditorType.DISABLE) {\n      this.#args.annotationEditorMode = pdfViewer.annotationEditorMode;\n    }\n    try {\n      await promise;\n      pdfViewer.focus();\n      return true;\n    } catch {\n      this.#removeFullscreenChangeListeners();\n      this.#notifyStateChange(_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.PresentationModeState.NORMAL);\n    }\n    return false;\n  }\n  get active() {\n    return this.#state === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.PresentationModeState.CHANGING || this.#state === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.PresentationModeState.FULLSCREEN;\n  }\n  #mouseWheel(evt) {\n    if (!this.active) {\n      return;\n    }\n    evt.preventDefault();\n    const delta = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.normalizeWheelEventDelta)(evt);\n    const currentTime = Date.now();\n    const storedTime = this.mouseScrollTimeStamp;\n    if (currentTime > storedTime && currentTime - storedTime < MOUSE_SCROLL_COOLDOWN_TIME) {\n      return;\n    }\n    if (this.mouseScrollDelta > 0 && delta < 0 || this.mouseScrollDelta < 0 && delta > 0) {\n      this.#resetMouseScrollState();\n    }\n    this.mouseScrollDelta += delta;\n    if (Math.abs(this.mouseScrollDelta) >= PAGE_SWITCH_THRESHOLD) {\n      const totalDelta = this.mouseScrollDelta;\n      this.#resetMouseScrollState();\n      const success = totalDelta > 0 ? this.pdfViewer.previousPage() : this.pdfViewer.nextPage();\n      if (success) {\n        this.mouseScrollTimeStamp = currentTime;\n      }\n    }\n  }\n  #notifyStateChange(state) {\n    this.#state = state;\n    this.eventBus.dispatch(\"presentationmodechanged\", {\n      source: this,\n      state\n    });\n  }\n  #enter() {\n    this.#notifyStateChange(_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.PresentationModeState.FULLSCREEN);\n    this.container.classList.add(ACTIVE_SELECTOR);\n    setTimeout(() => {\n      this.pdfViewer.scrollMode = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.PAGE;\n      if (this.#args.spreadMode !== null) {\n        this.pdfViewer.spreadMode = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SpreadMode.NONE;\n      }\n      this.pdfViewer.currentPageNumber = this.#args.pageNumber;\n      this.pdfViewer.currentScaleValue = \"page-fit\";\n      if (this.#args.annotationEditorMode !== null) {\n        this.pdfViewer.annotationEditorMode = {\n          mode: pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.AnnotationEditorType.NONE\n        };\n      }\n    }, 0);\n    this.#addWindowListeners();\n    this.#showControls();\n    this.contextMenuOpen = false;\n    document.getSelection().empty();\n  }\n  #exit() {\n    const pageNumber = this.pdfViewer.currentPageNumber;\n    this.container.classList.remove(ACTIVE_SELECTOR);\n    setTimeout(() => {\n      this.#removeFullscreenChangeListeners();\n      this.#notifyStateChange(_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.PresentationModeState.NORMAL);\n      this.pdfViewer.scrollMode = this.#args.scrollMode;\n      if (this.#args.spreadMode !== null) {\n        this.pdfViewer.spreadMode = this.#args.spreadMode;\n      }\n      this.pdfViewer.currentScaleValue = this.#args.scaleValue;\n      this.pdfViewer.currentPageNumber = pageNumber;\n      if (this.#args.annotationEditorMode !== null) {\n        this.pdfViewer.annotationEditorMode = {\n          mode: this.#args.annotationEditorMode\n        };\n      }\n      this.#args = null;\n    }, 0);\n    this.#removeWindowListeners();\n    this.#hideControls();\n    this.#resetMouseScrollState();\n    this.contextMenuOpen = false;\n  }\n  #mouseDown(evt) {\n    if (this.contextMenuOpen) {\n      this.contextMenuOpen = false;\n      evt.preventDefault();\n      return;\n    }\n    if (evt.button !== 0) {\n      return;\n    }\n    if (evt.target.href && evt.target.parentNode?.hasAttribute(\"data-internal-link\")) {\n      return;\n    }\n    evt.preventDefault();\n    if (evt.shiftKey) {\n      this.pdfViewer.previousPage();\n    } else {\n      this.pdfViewer.nextPage();\n    }\n  }\n  #contextMenu() {\n    this.contextMenuOpen = true;\n  }\n  #showControls() {\n    if (this.controlsTimeout) {\n      clearTimeout(this.controlsTimeout);\n    } else {\n      this.container.classList.add(CONTROLS_SELECTOR);\n    }\n    this.controlsTimeout = setTimeout(() => {\n      this.container.classList.remove(CONTROLS_SELECTOR);\n      delete this.controlsTimeout;\n    }, DELAY_BEFORE_HIDING_CONTROLS);\n  }\n  #hideControls() {\n    if (!this.controlsTimeout) {\n      return;\n    }\n    clearTimeout(this.controlsTimeout);\n    this.container.classList.remove(CONTROLS_SELECTOR);\n    delete this.controlsTimeout;\n  }\n  #resetMouseScrollState() {\n    this.mouseScrollTimeStamp = 0;\n    this.mouseScrollDelta = 0;\n  }\n  #touchSwipe(evt) {\n    if (!this.active) {\n      return;\n    }\n    if (evt.touches.length > 1) {\n      this.touchSwipeState = null;\n      return;\n    }\n    switch (evt.type) {\n      case \"touchstart\":\n        this.touchSwipeState = {\n          startX: evt.touches[0].pageX,\n          startY: evt.touches[0].pageY,\n          endX: evt.touches[0].pageX,\n          endY: evt.touches[0].pageY\n        };\n        break;\n      case \"touchmove\":\n        if (this.touchSwipeState === null) {\n          return;\n        }\n        this.touchSwipeState.endX = evt.touches[0].pageX;\n        this.touchSwipeState.endY = evt.touches[0].pageY;\n        evt.preventDefault();\n        break;\n      case \"touchend\":\n        if (this.touchSwipeState === null) {\n          return;\n        }\n        let delta = 0;\n        const dx = this.touchSwipeState.endX - this.touchSwipeState.startX;\n        const dy = this.touchSwipeState.endY - this.touchSwipeState.startY;\n        const absAngle = Math.abs(Math.atan2(dy, dx));\n        if (Math.abs(dx) > SWIPE_MIN_DISTANCE_THRESHOLD && (absAngle <= SWIPE_ANGLE_THRESHOLD || absAngle >= Math.PI - SWIPE_ANGLE_THRESHOLD)) {\n          delta = dx;\n        } else if (Math.abs(dy) > SWIPE_MIN_DISTANCE_THRESHOLD && Math.abs(absAngle - Math.PI / 2) <= SWIPE_ANGLE_THRESHOLD) {\n          delta = dy;\n        }\n        if (delta > 0) {\n          this.pdfViewer.previousPage();\n        } else if (delta < 0) {\n          this.pdfViewer.nextPage();\n        }\n        break;\n    }\n  }\n  #addWindowListeners() {\n    if (this.#windowAbortController) {\n      return;\n    }\n    this.#windowAbortController = new AbortController();\n    const {\n      signal\n    } = this.#windowAbortController;\n    const touchSwipeBind = this.#touchSwipe.bind(this);\n    window.addEventListener(\"mousemove\", this.#showControls.bind(this), {\n      signal\n    });\n    window.addEventListener(\"mousedown\", this.#mouseDown.bind(this), {\n      signal\n    });\n    window.addEventListener(\"wheel\", this.#mouseWheel.bind(this), {\n      passive: false,\n      signal\n    });\n    window.addEventListener(\"keydown\", this.#resetMouseScrollState.bind(this), {\n      signal\n    });\n    window.addEventListener(\"contextmenu\", this.#contextMenu.bind(this), {\n      signal\n    });\n    window.addEventListener(\"touchstart\", touchSwipeBind, {\n      signal\n    });\n    window.addEventListener(\"touchmove\", touchSwipeBind, {\n      signal\n    });\n    window.addEventListener(\"touchend\", touchSwipeBind, {\n      signal\n    });\n  }\n  #removeWindowListeners() {\n    this.#windowAbortController?.abort();\n    this.#windowAbortController = null;\n  }\n  #addFullscreenChangeListeners() {\n    if (this.#fullscreenChangeAbortController) {\n      return;\n    }\n    this.#fullscreenChangeAbortController = new AbortController();\n    window.addEventListener(\"fullscreenchange\", () => {\n      if (document.fullscreenElement) {\n        this.#enter();\n      } else {\n        this.#exit();\n      }\n    }, {\n      signal: this.#fullscreenChangeAbortController.signal\n    });\n  }\n  #removeFullscreenChangeListeners() {\n    this.#fullscreenChangeAbortController?.abort();\n    this.#fullscreenChangeAbortController = null;\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 1144:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   PDFPrintServiceFactory: () => (/* binding */ PDFPrintServiceFactory)\n/* harmony export */ });\n/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603);\n/* harmony import */ var _print_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(659);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__, _print_utils_js__WEBPACK_IMPORTED_MODULE_1__]);\n([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__, _print_utils_js__WEBPACK_IMPORTED_MODULE_1__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__);\n\n\nlet activeService = null;\nlet dialog = null;\nlet overlayManager = null;\nlet viewerApp = {\n  initialized: false\n};\nfunction renderPage(activeServiceOnEntry, pdfDocument, pageNumber, size, printResolution, optionalContentConfigPromise, printAnnotationStoragePromise) {\n  const scratchCanvas = activeService.scratchCanvas;\n  const PRINT_UNITS = printResolution / pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PixelsPerInch.PDF;\n  scratchCanvas.width = Math.floor(size.width * PRINT_UNITS);\n  scratchCanvas.height = Math.floor(size.height * PRINT_UNITS);\n  const ctx = scratchCanvas.getContext(\"2d\");\n  ctx.save();\n  ctx.fillStyle = \"rgb(255, 255, 255)\";\n  ctx.fillRect(0, 0, scratchCanvas.width, scratchCanvas.height);\n  ctx.restore();\n  return Promise.all([pdfDocument.getPage(pageNumber), printAnnotationStoragePromise]).then(function ([pdfPage, printAnnotationStorage]) {\n    const renderContext = {\n      canvasContext: ctx,\n      transform: [PRINT_UNITS, 0, 0, PRINT_UNITS, 0, 0],\n      viewport: pdfPage.getViewport({\n        scale: 1,\n        rotation: size.rotation\n      }),\n      intent: \"print\",\n      annotationMode: pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE_STORAGE,\n      optionalContentConfigPromise,\n      printAnnotationStorage\n    };\n    const renderTask = pdfPage.render(renderContext);\n    return renderTask.promise.catch(reason => {\n      if (!(reason instanceof pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.RenderingCancelledException)) {\n        console.error(reason);\n      }\n      throw reason;\n    });\n  });\n}\nclass PDFPrintService {\n  constructor({\n    pdfDocument,\n    pagesOverview,\n    printContainer,\n    printResolution,\n    printAnnotationStoragePromise = null\n  }) {\n    this.pdfDocument = pdfDocument;\n    this.pagesOverview = pagesOverview;\n    this.printContainer = printContainer;\n    this._printResolution = printResolution || 150;\n    this._optionalContentConfigPromise = pdfDocument.getOptionalContentConfig({\n      intent: \"print\"\n    });\n    this._printAnnotationStoragePromise = printAnnotationStoragePromise || Promise.resolve();\n    this.currentPage = -1;\n    this.scratchCanvas = document.createElement(\"canvas\");\n  }\n  layout() {\n    this.throwIfInactive();\n    const body = document.querySelector(\"body\");\n    body.setAttribute(\"data-pdfjsprinting\", true);\n    const {\n      width,\n      height\n    } = this.pagesOverview[0];\n    const hasEqualPageSizes = this.pagesOverview.every(size => size.width === width && size.height === height);\n    if (!hasEqualPageSizes) {\n      console.warn(\"Not all pages have the same size. The printed result may be incorrect!\");\n    }\n    this.pageStyleSheet = document.createElement(\"style\");\n    this.pageStyleSheet.textContent = `@page { size: ${width}pt ${height}pt;}`;\n    body.append(this.pageStyleSheet);\n  }\n  destroy() {\n    if (activeService !== this) {\n      return;\n    }\n    this.printContainer.textContent = \"\";\n    const body = document.querySelector(\"body\");\n    body.removeAttribute(\"data-pdfjsprinting\");\n    if (this.pageStyleSheet) {\n      this.pageStyleSheet.remove();\n      this.pageStyleSheet = null;\n    }\n    this.scratchCanvas.width = this.scratchCanvas.height = 0;\n    this.scratchCanvas = null;\n    activeService = null;\n    ensureOverlay().then(function () {\n      if (overlayManager.active === dialog) {\n        overlayManager.close(dialog);\n      }\n    });\n  }\n  renderPages() {\n    if (this.pdfDocument.isPureXfa) {\n      (0,_print_utils_js__WEBPACK_IMPORTED_MODULE_1__.getXfaHtmlForPrinting)(this.printContainer, this.pdfDocument);\n      return Promise.resolve();\n    }\n    const pageCount = this.pagesOverview.length;\n    const renderNextPage = (resolve, reject) => {\n      this.throwIfInactive();\n      if (++this.currentPage >= pageCount) {\n        renderProgress(pageCount, pageCount);\n        resolve();\n        return;\n      }\n      const index = this.currentPage;\n      renderProgress(index, pageCount);\n      renderPage(this, this.pdfDocument, index + 1, this.pagesOverview[index], this._printResolution, this._optionalContentConfigPromise, this._printAnnotationStoragePromise).then(this.useRenderedPage.bind(this)).then(function () {\n        renderNextPage(resolve, reject);\n      }, reject);\n    };\n    return new Promise(renderNextPage);\n  }\n  useRenderedPage() {\n    this.throwIfInactive();\n    const img = document.createElement(\"img\");\n    const scratchCanvas = this.scratchCanvas;\n    if (\"toBlob\" in scratchCanvas) {\n      scratchCanvas.toBlob(function (blob) {\n        img.src = URL.createObjectURL(blob);\n      });\n    } else {\n      img.src = scratchCanvas.toDataURL();\n    }\n    const wrapper = document.createElement(\"div\");\n    wrapper.className = \"printedPage\";\n    wrapper.append(img);\n    this.printContainer.append(wrapper);\n    return new Promise(function (resolve, reject) {\n      img.onload = resolve;\n      img.onerror = reject;\n    });\n  }\n  performPrint() {\n    this.throwIfInactive();\n    return new Promise(resolve => {\n      setTimeout(() => {\n        if (!this.active) {\n          resolve();\n          return;\n        }\n        print.call(window);\n        setTimeout(resolve, 20);\n      }, 0);\n    });\n  }\n  get active() {\n    return this === activeService;\n  }\n  throwIfInactive() {\n    if (!this.active) {\n      throw new Error(\"This print request was cancelled or completed.\");\n    }\n  }\n}\nconst print = window.print;\nwindow.print = function () {\n  if (activeService) {\n    console.warn(\"Ignored window.print() because of a pending print job.\");\n    return;\n  }\n  ensureOverlay().then(function () {\n    if (activeService) {\n      overlayManager.open(dialog);\n    }\n  });\n  try {\n    dispatchEvent(\"beforeprint\");\n  } finally {\n    if (!activeService) {\n      console.error(\"Expected print service to be initialized.\");\n      ensureOverlay().then(function () {\n        if (overlayManager.active === dialog) {\n          overlayManager.close(dialog);\n        }\n      });\n      return;\n    }\n    const activeServiceOnEntry = activeService;\n    activeService.renderPages().then(function () {\n      return activeServiceOnEntry.performPrint();\n    }).catch(function () {}).then(function () {\n      if (activeServiceOnEntry.active) {\n        abort();\n      }\n    });\n  }\n};\nfunction dispatchEvent(eventType) {\n  const event = new CustomEvent(eventType, {\n    bubbles: false,\n    cancelable: false,\n    detail: \"custom\"\n  });\n  window.dispatchEvent(event);\n}\nfunction abort() {\n  if (activeService) {\n    activeService.destroy();\n    dispatchEvent(\"afterprint\");\n  }\n}\nfunction renderProgress(index, total) {\n  dialog ||= document.getElementById(\"printServiceDialog\");\n  const progress = Math.round(100 * index / total);\n  const progressBar = dialog.querySelector(\"progress\");\n  const progressPerc = dialog.querySelector(\".relative-progress\");\n  progressBar.value = progress;\n  progressPerc.setAttribute(\"data-l10n-args\", JSON.stringify({\n    progress\n  }));\n}\nwindow.addEventListener(\"keydown\", function (event) {\n  if (event.keyCode === 80 && (event.ctrlKey || event.metaKey) && !event.altKey && (!event.shiftKey || window.chrome || window.opera)) {\n    window.print();\n    event.preventDefault();\n    event.stopImmediatePropagation();\n  }\n}, true);\nif (\"onbeforeprint\" in window) {\n  const stopPropagationIfNeeded = function (event) {\n    if (event.detail !== \"custom\") {\n      event.stopImmediatePropagation();\n    }\n  };\n  window.addEventListener(\"beforeprint\", stopPropagationIfNeeded);\n  window.addEventListener(\"afterprint\", stopPropagationIfNeeded);\n}\nlet overlayPromise;\nfunction ensureOverlay() {\n  if (!overlayPromise) {\n    overlayManager = viewerApp.overlayManager;\n    if (!overlayManager) {\n      throw new Error(\"The overlay manager has not yet been initialized.\");\n    }\n    dialog ||= document.getElementById(\"printServiceDialog\");\n    overlayPromise = overlayManager.register(dialog, true);\n    document.getElementById(\"printCancel\").onclick = abort;\n    dialog.addEventListener(\"close\", abort);\n  }\n  return overlayPromise;\n}\nclass PDFPrintServiceFactory {\n  static initGlobals(app) {\n    viewerApp = app;\n  }\n  static get supportsPrinting() {\n    return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, \"supportsPrinting\", true);\n  }\n  static createPrintService(params) {\n    if (activeService) {\n      throw new Error(\"The print service is created and active.\");\n    }\n    return activeService = new PDFPrintService(params);\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 6615:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   PDFRenderingQueue: () => (/* binding */ PDFRenderingQueue)\n/* harmony export */ });\n/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603);\n/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7256);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__]);\npdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];\n\n\nconst CLEANUP_TIMEOUT = 30000;\nclass PDFRenderingQueue {\n  constructor() {\n    this.pdfViewer = null;\n    this.pdfThumbnailViewer = null;\n    this.onIdle = null;\n    this.highestPriorityPage = null;\n    this.idleTimeout = null;\n    this.printing = false;\n    this.isThumbnailViewEnabled = false;\n    Object.defineProperty(this, \"hasViewer\", {\n      value: () => !!this.pdfViewer\n    });\n  }\n  setViewer(pdfViewer) {\n    this.pdfViewer = pdfViewer;\n  }\n  setThumbnailViewer(pdfThumbnailViewer) {\n    this.pdfThumbnailViewer = pdfThumbnailViewer;\n  }\n  isHighestPriority(view) {\n    return this.highestPriorityPage === view.renderingId;\n  }\n  renderHighestPriority(currentlyVisiblePages) {\n    if (this.idleTimeout) {\n      clearTimeout(this.idleTimeout);\n      this.idleTimeout = null;\n    }\n    if (this.pdfViewer.forceRendering(currentlyVisiblePages)) {\n      return;\n    }\n    if (this.isThumbnailViewEnabled && this.pdfThumbnailViewer?.forceRendering()) {\n      return;\n    }\n    if (this.printing) {\n      return;\n    }\n    if (this.onIdle) {\n      this.idleTimeout = setTimeout(this.onIdle.bind(this), CLEANUP_TIMEOUT);\n    }\n  }\n  getHighestPriority(visible, views, scrolledDown, preRenderExtra = false) {\n    const visibleViews = visible.views,\n      numVisible = visibleViews.length;\n    if (numVisible === 0) {\n      return null;\n    }\n    for (let i = 0; i < numVisible; i++) {\n      const view = visibleViews[i].view;\n      if (!this.isViewFinished(view)) {\n        return view;\n      }\n    }\n    const firstId = visible.first.id,\n      lastId = visible.last.id;\n    if (lastId - firstId + 1 > numVisible) {\n      const visibleIds = visible.ids;\n      for (let i = 1, ii = lastId - firstId; i < ii; i++) {\n        const holeId = scrolledDown ? firstId + i : lastId - i;\n        if (visibleIds.has(holeId)) {\n          continue;\n        }\n        const holeView = views[holeId - 1];\n        if (!this.isViewFinished(holeView)) {\n          return holeView;\n        }\n      }\n    }\n    let preRenderIndex = scrolledDown ? lastId : firstId - 2;\n    let preRenderView = views[preRenderIndex];\n    if (preRenderView && !this.isViewFinished(preRenderView)) {\n      return preRenderView;\n    }\n    if (preRenderExtra) {\n      preRenderIndex += scrolledDown ? 1 : -1;\n      preRenderView = views[preRenderIndex];\n      if (preRenderView && !this.isViewFinished(preRenderView)) {\n        return preRenderView;\n      }\n    }\n    return null;\n  }\n  isViewFinished(view) {\n    return view.renderingState === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.FINISHED;\n  }\n  renderView(view) {\n    switch (view.renderingState) {\n      case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.FINISHED:\n        return false;\n      case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.PAUSED:\n        this.highestPriorityPage = view.renderingId;\n        view.resume();\n        break;\n      case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.RUNNING:\n        this.highestPriorityPage = view.renderingId;\n        break;\n      case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.INITIAL:\n        this.highestPriorityPage = view.renderingId;\n        view.draw().finally(() => {\n          this.renderHighestPriority();\n        }).catch(reason => {\n          if (reason instanceof pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.RenderingCancelledException) {\n            return;\n          }\n          console.error(`renderView: \"${reason}\"`);\n        });\n        break;\n    }\n    return true;\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 5942:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   PDFScriptingManager: () => (/* binding */ PDFScriptingManager)\n/* harmony export */ });\n/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256);\n/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2603);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__]);\npdfjs_lib__WEBPACK_IMPORTED_MODULE_1__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];\n\n\nclass PDFScriptingManager {\n  #closeCapability = null;\n  #destroyCapability = null;\n  #docProperties = null;\n  #eventAbortController = null;\n  #eventBus = null;\n  #externalServices = null;\n  #pdfDocument = null;\n  #pdfViewer = null;\n  #ready = false;\n  #scripting = null;\n  #willPrintCapability = null;\n  constructor({\n    eventBus,\n    externalServices = null,\n    docProperties = null\n  }) {\n    this.#eventBus = eventBus;\n    this.#externalServices = externalServices;\n    this.#docProperties = docProperties;\n  }\n  setViewer(pdfViewer) {\n    this.#pdfViewer = pdfViewer;\n  }\n  async setDocument(pdfDocument) {\n    if (this.#pdfDocument) {\n      await this.#destroyScripting();\n    }\n    this.#pdfDocument = pdfDocument;\n    if (!pdfDocument) {\n      return;\n    }\n    const [objects, calculationOrder, docActions] = await Promise.all([pdfDocument.getFieldObjects(), pdfDocument.getCalculationOrderIds(), pdfDocument.getJSActions()]);\n    if (!objects && !docActions) {\n      await this.#destroyScripting();\n      return;\n    }\n    if (pdfDocument !== this.#pdfDocument) {\n      return;\n    }\n    try {\n      this.#scripting = this.#initScripting();\n    } catch (error) {\n      console.error(`setDocument: \"${error.message}\".`);\n      await this.#destroyScripting();\n      return;\n    }\n    const eventBus = this.#eventBus;\n    this.#eventAbortController = new AbortController();\n    const {\n      signal\n    } = this.#eventAbortController;\n    eventBus._on(\"updatefromsandbox\", event => {\n      if (event?.source === window) {\n        this.#updateFromSandbox(event.detail);\n      }\n    }, {\n      signal\n    });\n    eventBus._on(\"dispatcheventinsandbox\", event => {\n      this.#scripting?.dispatchEventInSandbox(event.detail);\n    }, {\n      signal\n    });\n    eventBus._on(\"pagechanging\", ({\n      pageNumber,\n      previous\n    }) => {\n      if (pageNumber === previous) {\n        return;\n      }\n      this.#dispatchPageClose(previous);\n      this.#dispatchPageOpen(pageNumber);\n    }, {\n      signal\n    });\n    eventBus._on(\"pagerendered\", ({\n      pageNumber\n    }) => {\n      if (!this._pageOpenPending.has(pageNumber)) {\n        return;\n      }\n      if (pageNumber !== this.#pdfViewer.currentPageNumber) {\n        return;\n      }\n      this.#dispatchPageOpen(pageNumber);\n    }, {\n      signal\n    });\n    eventBus._on(\"pagesdestroy\", async () => {\n      await this.#dispatchPageClose(this.#pdfViewer.currentPageNumber);\n      await this.#scripting?.dispatchEventInSandbox({\n        id: \"doc\",\n        name: \"WillClose\"\n      });\n      this.#closeCapability?.resolve();\n    }, {\n      signal\n    });\n    try {\n      const docProperties = await this.#docProperties(pdfDocument);\n      if (pdfDocument !== this.#pdfDocument) {\n        return;\n      }\n      await this.#scripting.createSandbox({\n        objects,\n        calculationOrder,\n        appInfo: {\n          platform: navigator.platform,\n          language: navigator.language\n        },\n        docInfo: {\n          ...docProperties,\n          actions: docActions\n        }\n      });\n      eventBus.dispatch(\"sandboxcreated\", {\n        source: this\n      });\n    } catch (error) {\n      console.error(`setDocument: \"${error.message}\".`);\n      await this.#destroyScripting();\n      return;\n    }\n    await this.#scripting?.dispatchEventInSandbox({\n      id: \"doc\",\n      name: \"Open\"\n    });\n    await this.#dispatchPageOpen(this.#pdfViewer.currentPageNumber, true);\n    Promise.resolve().then(() => {\n      if (pdfDocument === this.#pdfDocument) {\n        this.#ready = true;\n      }\n    });\n  }\n  async dispatchWillSave() {\n    return this.#scripting?.dispatchEventInSandbox({\n      id: \"doc\",\n      name: \"WillSave\"\n    });\n  }\n  async dispatchDidSave() {\n    return this.#scripting?.dispatchEventInSandbox({\n      id: \"doc\",\n      name: \"DidSave\"\n    });\n  }\n  async dispatchWillPrint() {\n    if (!this.#scripting) {\n      return;\n    }\n    await this.#willPrintCapability?.promise;\n    this.#willPrintCapability = Promise.withResolvers();\n    try {\n      await this.#scripting.dispatchEventInSandbox({\n        id: \"doc\",\n        name: \"WillPrint\"\n      });\n    } catch (ex) {\n      this.#willPrintCapability.resolve();\n      this.#willPrintCapability = null;\n      throw ex;\n    }\n    await this.#willPrintCapability.promise;\n  }\n  async dispatchDidPrint() {\n    return this.#scripting?.dispatchEventInSandbox({\n      id: \"doc\",\n      name: \"DidPrint\"\n    });\n  }\n  get destroyPromise() {\n    return this.#destroyCapability?.promise || null;\n  }\n  get ready() {\n    return this.#ready;\n  }\n  get _pageOpenPending() {\n    return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.shadow)(this, \"_pageOpenPending\", new Set());\n  }\n  get _visitedPages() {\n    return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.shadow)(this, \"_visitedPages\", new Map());\n  }\n  async #updateFromSandbox(detail) {\n    const pdfViewer = this.#pdfViewer;\n    const isInPresentationMode = pdfViewer.isInPresentationMode || pdfViewer.isChangingPresentationMode;\n    const {\n      id,\n      siblings,\n      command,\n      value\n    } = detail;\n    if (!id) {\n      switch (command) {\n        case \"clear\":\n          console.clear();\n          break;\n        case \"error\":\n          console.error(value);\n          break;\n        case \"layout\":\n          if (!isInPresentationMode) {\n            const modes = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.apiPageLayoutToViewerModes)(value);\n            pdfViewer.spreadMode = modes.spreadMode;\n          }\n          break;\n        case \"page-num\":\n          pdfViewer.currentPageNumber = value + 1;\n          break;\n        case \"print\":\n          await pdfViewer.pagesPromise;\n          this.#eventBus.dispatch(\"print\", {\n            source: this\n          });\n          break;\n        case \"println\":\n          console.log(value);\n          break;\n        case \"zoom\":\n          if (!isInPresentationMode) {\n            pdfViewer.currentScaleValue = value;\n          }\n          break;\n        case \"SaveAs\":\n          this.#eventBus.dispatch(\"download\", {\n            source: this\n          });\n          break;\n        case \"FirstPage\":\n          pdfViewer.currentPageNumber = 1;\n          break;\n        case \"LastPage\":\n          pdfViewer.currentPageNumber = pdfViewer.pagesCount;\n          break;\n        case \"NextPage\":\n          pdfViewer.nextPage();\n          break;\n        case \"PrevPage\":\n          pdfViewer.previousPage();\n          break;\n        case \"ZoomViewIn\":\n          if (!isInPresentationMode) {\n            pdfViewer.increaseScale();\n          }\n          break;\n        case \"ZoomViewOut\":\n          if (!isInPresentationMode) {\n            pdfViewer.decreaseScale();\n          }\n          break;\n        case \"WillPrintFinished\":\n          this.#willPrintCapability?.resolve();\n          this.#willPrintCapability = null;\n          break;\n      }\n      return;\n    }\n    if (isInPresentationMode && detail.focus) {\n      return;\n    }\n    delete detail.id;\n    delete detail.siblings;\n    const ids = siblings ? [id, ...siblings] : [id];\n    for (const elementId of ids) {\n      const element = document.querySelector(`[data-element-id=\"${elementId}\"]`);\n      if (element) {\n        element.dispatchEvent(new CustomEvent(\"updatefromsandbox\", {\n          detail\n        }));\n      } else {\n        this.#pdfDocument?.annotationStorage.setValue(elementId, detail);\n      }\n    }\n  }\n  async #dispatchPageOpen(pageNumber, initialize = false) {\n    const pdfDocument = this.#pdfDocument,\n      visitedPages = this._visitedPages;\n    if (initialize) {\n      this.#closeCapability = Promise.withResolvers();\n    }\n    if (!this.#closeCapability) {\n      return;\n    }\n    const pageView = this.#pdfViewer.getPageView(pageNumber - 1);\n    if (pageView?.renderingState !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.FINISHED) {\n      this._pageOpenPending.add(pageNumber);\n      return;\n    }\n    this._pageOpenPending.delete(pageNumber);\n    const actionsPromise = (async () => {\n      const actions = await (!visitedPages.has(pageNumber) ? pageView.pdfPage?.getJSActions() : null);\n      if (pdfDocument !== this.#pdfDocument) {\n        return;\n      }\n      await this.#scripting?.dispatchEventInSandbox({\n        id: \"page\",\n        name: \"PageOpen\",\n        pageNumber,\n        actions\n      });\n    })();\n    visitedPages.set(pageNumber, actionsPromise);\n  }\n  async #dispatchPageClose(pageNumber) {\n    const pdfDocument = this.#pdfDocument,\n      visitedPages = this._visitedPages;\n    if (!this.#closeCapability) {\n      return;\n    }\n    if (this._pageOpenPending.has(pageNumber)) {\n      return;\n    }\n    const actionsPromise = visitedPages.get(pageNumber);\n    if (!actionsPromise) {\n      return;\n    }\n    visitedPages.set(pageNumber, null);\n    await actionsPromise;\n    if (pdfDocument !== this.#pdfDocument) {\n      return;\n    }\n    await this.#scripting?.dispatchEventInSandbox({\n      id: \"page\",\n      name: \"PageClose\",\n      pageNumber\n    });\n  }\n  #initScripting() {\n    this.#destroyCapability = Promise.withResolvers();\n    if (this.#scripting) {\n      throw new Error(\"#initScripting: Scripting already exists.\");\n    }\n    return this.#externalServices.createScripting();\n  }\n  async #destroyScripting() {\n    if (!this.#scripting) {\n      this.#pdfDocument = null;\n      this.#destroyCapability?.resolve();\n      return;\n    }\n    if (this.#closeCapability) {\n      await Promise.race([this.#closeCapability.promise, new Promise(resolve => {\n        setTimeout(resolve, 1000);\n      })]).catch(() => {});\n      this.#closeCapability = null;\n    }\n    this.#pdfDocument = null;\n    try {\n      await this.#scripting.destroySandbox();\n    } catch {}\n    this.#willPrintCapability?.reject(new Error(\"Scripting destroyed.\"));\n    this.#willPrintCapability = null;\n    this.#eventAbortController?.abort();\n    this.#eventAbortController = null;\n    this._pageOpenPending.clear();\n    this._visitedPages.clear();\n    this.#scripting = null;\n    this.#ready = false;\n    this.#destroyCapability?.resolve();\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 2275:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   PDFSidebar: () => (/* binding */ PDFSidebar)\n/* harmony export */ });\n/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256);\n\nconst SIDEBAR_WIDTH_VAR = \"--sidebar-width\";\nconst SIDEBAR_MIN_WIDTH = 200;\nconst SIDEBAR_RESIZING_CLASS = \"sidebarResizing\";\nconst UI_NOTIFICATION_CLASS = \"pdfSidebarNotification\";\nclass PDFSidebar {\n  #isRTL = false;\n  #mouseMoveBound = this.#mouseMove.bind(this);\n  #mouseUpBound = this.#mouseUp.bind(this);\n  #outerContainerWidth = null;\n  #width = null;\n  constructor({\n    elements,\n    eventBus,\n    l10n\n  }) {\n    this.isOpen = false;\n    this.active = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.THUMBS;\n    this.isInitialViewSet = false;\n    this.isInitialEventDispatched = false;\n    this.onToggled = null;\n    this.onUpdateThumbnails = null;\n    this.outerContainer = elements.outerContainer;\n    this.sidebarContainer = elements.sidebarContainer;\n    this.toggleButton = elements.toggleButton;\n    this.resizer = elements.resizer;\n    this.thumbnailButton = elements.thumbnailButton;\n    this.outlineButton = elements.outlineButton;\n    this.attachmentsButton = elements.attachmentsButton;\n    this.layersButton = elements.layersButton;\n    this.thumbnailView = elements.thumbnailView;\n    this.outlineView = elements.outlineView;\n    this.attachmentsView = elements.attachmentsView;\n    this.layersView = elements.layersView;\n    this._currentOutlineItemButton = elements.currentOutlineItemButton;\n    this.eventBus = eventBus;\n    this.#isRTL = l10n.getDirection() === \"rtl\";\n    this.#addEventListeners();\n  }\n  reset() {\n    this.isInitialViewSet = false;\n    this.isInitialEventDispatched = false;\n    this.#hideUINotification(true);\n    this.switchView(_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.THUMBS);\n    this.outlineButton.disabled = false;\n    this.attachmentsButton.disabled = false;\n    this.layersButton.disabled = false;\n    this._currentOutlineItemButton.disabled = true;\n  }\n  get visibleView() {\n    return this.isOpen ? this.active : _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.NONE;\n  }\n  setInitialView(view = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.NONE) {\n    if (this.isInitialViewSet) {\n      return;\n    }\n    this.isInitialViewSet = true;\n    if (view === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.NONE || view === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.UNKNOWN) {\n      this.#dispatchEvent();\n      return;\n    }\n    this.switchView(view, true);\n    if (!this.isInitialEventDispatched) {\n      this.#dispatchEvent();\n    }\n  }\n  switchView(view, forceOpen = false) {\n    const isViewChanged = view !== this.active;\n    let forceRendering = false;\n    switch (view) {\n      case _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.NONE:\n        if (this.isOpen) {\n          this.close();\n        }\n        return;\n      case _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.THUMBS:\n        if (this.isOpen && isViewChanged) {\n          forceRendering = true;\n        }\n        break;\n      case _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.OUTLINE:\n        if (this.outlineButton.disabled) {\n          return;\n        }\n        break;\n      case _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.ATTACHMENTS:\n        if (this.attachmentsButton.disabled) {\n          return;\n        }\n        break;\n      case _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.LAYERS:\n        if (this.layersButton.disabled) {\n          return;\n        }\n        break;\n      default:\n        console.error(`PDFSidebar.switchView: \"${view}\" is not a valid view.`);\n        return;\n    }\n    this.active = view;\n    (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleCheckedBtn)(this.thumbnailButton, view === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.THUMBS, this.thumbnailView);\n    (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleCheckedBtn)(this.outlineButton, view === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.OUTLINE, this.outlineView);\n    (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleCheckedBtn)(this.attachmentsButton, view === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.ATTACHMENTS, this.attachmentsView);\n    (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleCheckedBtn)(this.layersButton, view === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.LAYERS, this.layersView);\n    if (forceOpen && !this.isOpen) {\n      this.open();\n      return;\n    }\n    if (forceRendering) {\n      this.onUpdateThumbnails();\n      this.onToggled();\n    }\n    if (isViewChanged) {\n      this.#dispatchEvent();\n    }\n  }\n  open() {\n    if (this.isOpen) {\n      return;\n    }\n    this.isOpen = true;\n    (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleExpandedBtn)(this.toggleButton, true);\n    this.outerContainer.classList.add(\"sidebarMoving\", \"sidebarOpen\");\n    if (this.active === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.THUMBS) {\n      this.onUpdateThumbnails();\n    }\n    this.onToggled();\n    this.#dispatchEvent();\n    this.#hideUINotification();\n  }\n  close(evt = null) {\n    if (!this.isOpen) {\n      return;\n    }\n    this.isOpen = false;\n    (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleExpandedBtn)(this.toggleButton, false);\n    this.outerContainer.classList.add(\"sidebarMoving\");\n    this.outerContainer.classList.remove(\"sidebarOpen\");\n    this.onToggled();\n    this.#dispatchEvent();\n    if (evt?.detail > 0) {\n      this.toggleButton.blur();\n    }\n  }\n  toggle(evt = null) {\n    if (this.isOpen) {\n      this.close(evt);\n    } else {\n      this.open();\n    }\n  }\n  #dispatchEvent() {\n    if (this.isInitialViewSet) {\n      this.isInitialEventDispatched ||= true;\n    }\n    this.eventBus.dispatch(\"sidebarviewchanged\", {\n      source: this,\n      view: this.visibleView\n    });\n  }\n  #showUINotification() {\n    this.toggleButton.setAttribute(\"data-l10n-id\", \"pdfjs-toggle-sidebar-notification-button\");\n    if (!this.isOpen) {\n      this.toggleButton.classList.add(UI_NOTIFICATION_CLASS);\n    }\n  }\n  #hideUINotification(reset = false) {\n    if (this.isOpen || reset) {\n      this.toggleButton.classList.remove(UI_NOTIFICATION_CLASS);\n    }\n    if (reset) {\n      this.toggleButton.setAttribute(\"data-l10n-id\", \"pdfjs-toggle-sidebar-button\");\n    }\n  }\n  #addEventListeners() {\n    this.sidebarContainer.addEventListener(\"transitionend\", evt => {\n      if (evt.target === this.sidebarContainer) {\n        this.outerContainer.classList.remove(\"sidebarMoving\");\n        this.eventBus.dispatch(\"resize\", {\n          source: this\n        });\n      }\n    });\n    this.toggleButton.addEventListener(\"click\", evt => {\n      this.toggle(evt);\n    });\n    this.thumbnailButton.addEventListener(\"click\", () => {\n      this.switchView(_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.THUMBS);\n    });\n    this.outlineButton.addEventListener(\"click\", () => {\n      this.switchView(_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.OUTLINE);\n    });\n    this.outlineButton.addEventListener(\"dblclick\", () => {\n      this.eventBus.dispatch(\"toggleoutlinetree\", {\n        source: this\n      });\n    });\n    this.attachmentsButton.addEventListener(\"click\", () => {\n      this.switchView(_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.ATTACHMENTS);\n    });\n    this.layersButton.addEventListener(\"click\", () => {\n      this.switchView(_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.LAYERS);\n    });\n    this.layersButton.addEventListener(\"dblclick\", () => {\n      this.eventBus.dispatch(\"resetlayers\", {\n        source: this\n      });\n    });\n    this._currentOutlineItemButton.addEventListener(\"click\", () => {\n      this.eventBus.dispatch(\"currentoutlineitem\", {\n        source: this\n      });\n    });\n    const onTreeLoaded = (count, button, view) => {\n      button.disabled = !count;\n      if (count) {\n        this.#showUINotification();\n      } else if (this.active === view) {\n        this.switchView(_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.THUMBS);\n      }\n    };\n    this.eventBus._on(\"outlineloaded\", evt => {\n      onTreeLoaded(evt.outlineCount, this.outlineButton, _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.OUTLINE);\n      evt.currentOutlineItemPromise.then(enabled => {\n        if (!this.isInitialViewSet) {\n          return;\n        }\n        this._currentOutlineItemButton.disabled = !enabled;\n      });\n    });\n    this.eventBus._on(\"attachmentsloaded\", evt => {\n      onTreeLoaded(evt.attachmentsCount, this.attachmentsButton, _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.ATTACHMENTS);\n    });\n    this.eventBus._on(\"layersloaded\", evt => {\n      onTreeLoaded(evt.layersCount, this.layersButton, _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.LAYERS);\n    });\n    this.eventBus._on(\"presentationmodechanged\", evt => {\n      if (evt.state === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.PresentationModeState.NORMAL && this.visibleView === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.THUMBS) {\n        this.onUpdateThumbnails();\n      }\n    });\n    this.resizer.addEventListener(\"mousedown\", evt => {\n      if (evt.button !== 0) {\n        return;\n      }\n      this.outerContainer.classList.add(SIDEBAR_RESIZING_CLASS);\n      window.addEventListener(\"mousemove\", this.#mouseMoveBound);\n      window.addEventListener(\"mouseup\", this.#mouseUpBound);\n    });\n    this.eventBus._on(\"resize\", evt => {\n      if (evt.source !== window) {\n        return;\n      }\n      this.#outerContainerWidth = null;\n      if (!this.#width) {\n        return;\n      }\n      if (!this.isOpen) {\n        this.#updateWidth(this.#width);\n        return;\n      }\n      this.outerContainer.classList.add(SIDEBAR_RESIZING_CLASS);\n      const updated = this.#updateWidth(this.#width);\n      Promise.resolve().then(() => {\n        this.outerContainer.classList.remove(SIDEBAR_RESIZING_CLASS);\n        if (updated) {\n          this.eventBus.dispatch(\"resize\", {\n            source: this\n          });\n        }\n      });\n    });\n  }\n  get outerContainerWidth() {\n    return this.#outerContainerWidth ||= this.outerContainer.clientWidth;\n  }\n  #updateWidth(width = 0) {\n    const maxWidth = Math.floor(this.outerContainerWidth / 2);\n    if (width > maxWidth) {\n      width = maxWidth;\n    }\n    if (width < SIDEBAR_MIN_WIDTH) {\n      width = SIDEBAR_MIN_WIDTH;\n    }\n    if (width === this.#width) {\n      return false;\n    }\n    this.#width = width;\n    _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.docStyle.setProperty(SIDEBAR_WIDTH_VAR, `${width}px`);\n    return true;\n  }\n  #mouseMove(evt) {\n    let width = evt.clientX;\n    if (this.#isRTL) {\n      width = this.outerContainerWidth - width;\n    }\n    this.#updateWidth(width);\n  }\n  #mouseUp(evt) {\n    this.outerContainer.classList.remove(SIDEBAR_RESIZING_CLASS);\n    this.eventBus.dispatch(\"resize\", {\n      source: this\n    });\n    window.removeEventListener(\"mousemove\", this.#mouseMoveBound);\n    window.removeEventListener(\"mouseup\", this.#mouseUpBound);\n  }\n}\n\n\n/***/ }),\n\n/***/ 1123:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   PDFThumbnailView: () => (/* binding */ PDFThumbnailView),\n/* harmony export */   TempImageFactory: () => (/* binding */ TempImageFactory)\n/* harmony export */ });\n/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256);\n/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2603);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__]);\npdfjs_lib__WEBPACK_IMPORTED_MODULE_1__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];\n\n\nconst DRAW_UPSCALE_FACTOR = 2;\nconst MAX_NUM_SCALING_STEPS = 3;\nconst THUMBNAIL_WIDTH = 98;\nclass TempImageFactory {\n  static #tempCanvas = null;\n  static getCanvas(width, height) {\n    const tempCanvas = this.#tempCanvas ||= document.createElement(\"canvas\");\n    tempCanvas.width = width;\n    tempCanvas.height = height;\n    const ctx = tempCanvas.getContext(\"2d\", {\n      alpha: false\n    });\n    ctx.save();\n    ctx.fillStyle = \"rgb(255, 255, 255)\";\n    ctx.fillRect(0, 0, width, height);\n    ctx.restore();\n    return [tempCanvas, tempCanvas.getContext(\"2d\")];\n  }\n  static destroyCanvas() {\n    const tempCanvas = this.#tempCanvas;\n    if (tempCanvas) {\n      tempCanvas.width = 0;\n      tempCanvas.height = 0;\n    }\n    this.#tempCanvas = null;\n  }\n}\nclass PDFThumbnailView {\n  constructor({\n    container,\n    eventBus,\n    id,\n    defaultViewport,\n    optionalContentConfigPromise,\n    linkService,\n    renderingQueue,\n    pageColors\n  }) {\n    this.id = id;\n    this.renderingId = \"thumbnail\" + id;\n    this.pageLabel = null;\n    this.pdfPage = null;\n    this.rotation = 0;\n    this.viewport = defaultViewport;\n    this.pdfPageRotate = defaultViewport.rotation;\n    this._optionalContentConfigPromise = optionalContentConfigPromise || null;\n    this.pageColors = pageColors || null;\n    this.eventBus = eventBus;\n    this.linkService = linkService;\n    this.renderingQueue = renderingQueue;\n    this.renderTask = null;\n    this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.INITIAL;\n    this.resume = null;\n    const anchor = document.createElement(\"a\");\n    anchor.href = linkService.getAnchorUrl(\"#page=\" + id);\n    anchor.setAttribute(\"data-l10n-id\", \"pdfjs-thumb-page-title\");\n    anchor.setAttribute(\"data-l10n-args\", this.#pageL10nArgs);\n    anchor.onclick = function () {\n      linkService.goToPage(id);\n      return false;\n    };\n    this.anchor = anchor;\n    const div = document.createElement(\"div\");\n    div.className = \"thumbnail\";\n    div.setAttribute(\"data-page-number\", this.id);\n    this.div = div;\n    this.#updateDims();\n    const img = document.createElement(\"div\");\n    img.className = \"thumbnailImage\";\n    this._placeholderImg = img;\n    div.append(img);\n    anchor.append(div);\n    container.append(anchor);\n  }\n  #updateDims() {\n    const {\n      width,\n      height\n    } = this.viewport;\n    const ratio = width / height;\n    this.canvasWidth = THUMBNAIL_WIDTH;\n    this.canvasHeight = this.canvasWidth / ratio | 0;\n    this.scale = this.canvasWidth / width;\n    const {\n      style\n    } = this.div;\n    style.setProperty(\"--thumbnail-width\", `${this.canvasWidth}px`);\n    style.setProperty(\"--thumbnail-height\", `${this.canvasHeight}px`);\n  }\n  setPdfPage(pdfPage) {\n    this.pdfPage = pdfPage;\n    this.pdfPageRotate = pdfPage.rotate;\n    const totalRotation = (this.rotation + this.pdfPageRotate) % 360;\n    this.viewport = pdfPage.getViewport({\n      scale: 1,\n      rotation: totalRotation\n    });\n    this.reset();\n  }\n  reset() {\n    this.cancelRendering();\n    this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.INITIAL;\n    this.div.removeAttribute(\"data-loaded\");\n    this.image?.replaceWith(this._placeholderImg);\n    this.#updateDims();\n    if (this.image) {\n      this.image.removeAttribute(\"src\");\n      delete this.image;\n    }\n  }\n  update({\n    rotation = null\n  }) {\n    if (typeof rotation === \"number\") {\n      this.rotation = rotation;\n    }\n    const totalRotation = (this.rotation + this.pdfPageRotate) % 360;\n    this.viewport = this.viewport.clone({\n      scale: 1,\n      rotation: totalRotation\n    });\n    this.reset();\n  }\n  cancelRendering() {\n    if (this.renderTask) {\n      this.renderTask.cancel();\n      this.renderTask = null;\n    }\n    this.resume = null;\n  }\n  #getPageDrawContext(upscaleFactor = 1) {\n    const canvas = document.createElement(\"canvas\");\n    const ctx = canvas.getContext(\"2d\", {\n      alpha: false\n    });\n    const outputScale = new _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.OutputScale();\n    canvas.width = upscaleFactor * this.canvasWidth * outputScale.sx | 0;\n    canvas.height = upscaleFactor * this.canvasHeight * outputScale.sy | 0;\n    const transform = outputScale.scaled ? [outputScale.sx, 0, 0, outputScale.sy, 0, 0] : null;\n    return {\n      ctx,\n      canvas,\n      transform\n    };\n  }\n  #convertCanvasToImage(canvas) {\n    if (this.renderingState !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.FINISHED) {\n      throw new Error(\"#convertCanvasToImage: Rendering has not finished.\");\n    }\n    const reducedCanvas = this.#reduceImage(canvas);\n    const image = document.createElement(\"img\");\n    image.className = \"thumbnailImage\";\n    image.setAttribute(\"data-l10n-id\", \"pdfjs-thumb-page-canvas\");\n    image.setAttribute(\"data-l10n-args\", this.#pageL10nArgs);\n    image.src = reducedCanvas.toDataURL();\n    this.image = image;\n    this.div.setAttribute(\"data-loaded\", true);\n    this._placeholderImg.replaceWith(image);\n    reducedCanvas.width = 0;\n    reducedCanvas.height = 0;\n  }\n  async #finishRenderTask(renderTask, canvas, error = null) {\n    if (renderTask === this.renderTask) {\n      this.renderTask = null;\n    }\n    if (error instanceof pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.RenderingCancelledException) {\n      return;\n    }\n    this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.FINISHED;\n    this.#convertCanvasToImage(canvas);\n    if (error) {\n      throw error;\n    }\n  }\n  async draw() {\n    if (this.renderingState !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.INITIAL) {\n      console.error(\"Must be in new state before drawing\");\n      return undefined;\n    }\n    const {\n      pdfPage\n    } = this;\n    if (!pdfPage) {\n      this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.FINISHED;\n      throw new Error(\"pdfPage is not loaded\");\n    }\n    this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.RUNNING;\n    const {\n      ctx,\n      canvas,\n      transform\n    } = this.#getPageDrawContext(DRAW_UPSCALE_FACTOR);\n    const drawViewport = this.viewport.clone({\n      scale: DRAW_UPSCALE_FACTOR * this.scale\n    });\n    const renderContinueCallback = cont => {\n      if (!this.renderingQueue.isHighestPriority(this)) {\n        this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.PAUSED;\n        this.resume = () => {\n          this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.RUNNING;\n          cont();\n        };\n        return;\n      }\n      cont();\n    };\n    const renderContext = {\n      canvasContext: ctx,\n      transform,\n      viewport: drawViewport,\n      optionalContentConfigPromise: this._optionalContentConfigPromise,\n      pageColors: this.pageColors\n    };\n    const renderTask = this.renderTask = pdfPage.render(renderContext);\n    renderTask.onContinue = renderContinueCallback;\n    const resultPromise = renderTask.promise.then(() => this.#finishRenderTask(renderTask, canvas), error => this.#finishRenderTask(renderTask, canvas, error));\n    resultPromise.finally(() => {\n      canvas.width = 0;\n      canvas.height = 0;\n      this.eventBus.dispatch(\"thumbnailrendered\", {\n        source: this,\n        pageNumber: this.id,\n        pdfPage: this.pdfPage\n      });\n    });\n    return resultPromise;\n  }\n  setImage(pageView) {\n    if (this.renderingState !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.INITIAL) {\n      return;\n    }\n    const {\n      thumbnailCanvas: canvas,\n      pdfPage,\n      scale\n    } = pageView;\n    if (!canvas) {\n      return;\n    }\n    if (!this.pdfPage) {\n      this.setPdfPage(pdfPage);\n    }\n    if (scale < this.scale) {\n      return;\n    }\n    this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.FINISHED;\n    this.#convertCanvasToImage(canvas);\n  }\n  #reduceImage(img) {\n    const {\n      ctx,\n      canvas\n    } = this.#getPageDrawContext();\n    if (img.width <= 2 * canvas.width) {\n      ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height);\n      return canvas;\n    }\n    let reducedWidth = canvas.width << MAX_NUM_SCALING_STEPS;\n    let reducedHeight = canvas.height << MAX_NUM_SCALING_STEPS;\n    const [reducedImage, reducedImageCtx] = TempImageFactory.getCanvas(reducedWidth, reducedHeight);\n    while (reducedWidth > img.width || reducedHeight > img.height) {\n      reducedWidth >>= 1;\n      reducedHeight >>= 1;\n    }\n    reducedImageCtx.drawImage(img, 0, 0, img.width, img.height, 0, 0, reducedWidth, reducedHeight);\n    while (reducedWidth > 2 * canvas.width) {\n      reducedImageCtx.drawImage(reducedImage, 0, 0, reducedWidth, reducedHeight, 0, 0, reducedWidth >> 1, reducedHeight >> 1);\n      reducedWidth >>= 1;\n      reducedHeight >>= 1;\n    }\n    ctx.drawImage(reducedImage, 0, 0, reducedWidth, reducedHeight, 0, 0, canvas.width, canvas.height);\n    return canvas;\n  }\n  get #pageL10nArgs() {\n    return JSON.stringify({\n      page: this.pageLabel ?? this.id\n    });\n  }\n  setPageLabel(label) {\n    this.pageLabel = typeof label === \"string\" ? label : null;\n    this.anchor.setAttribute(\"data-l10n-args\", this.#pageL10nArgs);\n    if (this.renderingState !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.FINISHED) {\n      return;\n    }\n    this.image?.setAttribute(\"data-l10n-args\", this.#pageL10nArgs);\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 8280:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   PDFThumbnailViewer: () => (/* binding */ PDFThumbnailViewer)\n/* harmony export */ });\n/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256);\n/* harmony import */ var _pdf_thumbnail_view_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(1123);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([_pdf_thumbnail_view_js__WEBPACK_IMPORTED_MODULE_1__]);\n_pdf_thumbnail_view_js__WEBPACK_IMPORTED_MODULE_1__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];\n\n\nconst THUMBNAIL_SCROLL_MARGIN = -19;\nconst THUMBNAIL_SELECTED_CLASS = \"selected\";\nclass PDFThumbnailViewer {\n  constructor({\n    container,\n    eventBus,\n    linkService,\n    renderingQueue,\n    pageColors\n  }) {\n    this.container = container;\n    this.eventBus = eventBus;\n    this.linkService = linkService;\n    this.renderingQueue = renderingQueue;\n    this.pageColors = pageColors || null;\n    this.scroll = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.watchScroll)(this.container, this.#scrollUpdated.bind(this));\n    this.#resetView();\n  }\n  #scrollUpdated() {\n    this.renderingQueue.renderHighestPriority();\n  }\n  getThumbnail(index) {\n    return this._thumbnails[index];\n  }\n  #getVisibleThumbs() {\n    return (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.getVisibleElements)({\n      scrollEl: this.container,\n      views: this._thumbnails\n    });\n  }\n  scrollThumbnailIntoView(pageNumber) {\n    if (!this.pdfDocument) {\n      return;\n    }\n    const thumbnailView = this._thumbnails[pageNumber - 1];\n    if (!thumbnailView) {\n      console.error('scrollThumbnailIntoView: Invalid \"pageNumber\" parameter.');\n      return;\n    }\n    if (pageNumber !== this._currentPageNumber) {\n      const prevThumbnailView = this._thumbnails[this._currentPageNumber - 1];\n      prevThumbnailView.div.classList.remove(THUMBNAIL_SELECTED_CLASS);\n      thumbnailView.div.classList.add(THUMBNAIL_SELECTED_CLASS);\n    }\n    const {\n      first,\n      last,\n      views\n    } = this.#getVisibleThumbs();\n    if (views.length > 0) {\n      let shouldScroll = false;\n      if (pageNumber <= first.id || pageNumber >= last.id) {\n        shouldScroll = true;\n      } else {\n        for (const {\n          id,\n          percent\n        } of views) {\n          if (id !== pageNumber) {\n            continue;\n          }\n          shouldScroll = percent < 100;\n          break;\n        }\n      }\n      if (shouldScroll) {\n        (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.scrollIntoView)(thumbnailView.div, {\n          top: THUMBNAIL_SCROLL_MARGIN\n        });\n      }\n    }\n    this._currentPageNumber = pageNumber;\n  }\n  get pagesRotation() {\n    return this._pagesRotation;\n  }\n  set pagesRotation(rotation) {\n    if (!(0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.isValidRotation)(rotation)) {\n      throw new Error(\"Invalid thumbnails rotation angle.\");\n    }\n    if (!this.pdfDocument) {\n      return;\n    }\n    if (this._pagesRotation === rotation) {\n      return;\n    }\n    this._pagesRotation = rotation;\n    const updateArgs = {\n      rotation\n    };\n    for (const thumbnail of this._thumbnails) {\n      thumbnail.update(updateArgs);\n    }\n  }\n  cleanup() {\n    for (const thumbnail of this._thumbnails) {\n      if (thumbnail.renderingState !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.FINISHED) {\n        thumbnail.reset();\n      }\n    }\n    _pdf_thumbnail_view_js__WEBPACK_IMPORTED_MODULE_1__.TempImageFactory.destroyCanvas();\n  }\n  #resetView() {\n    this._thumbnails = [];\n    this._currentPageNumber = 1;\n    this._pageLabels = null;\n    this._pagesRotation = 0;\n    this.container.textContent = \"\";\n  }\n  setDocument(pdfDocument) {\n    if (this.pdfDocument) {\n      this.#cancelRendering();\n      this.#resetView();\n    }\n    this.pdfDocument = pdfDocument;\n    if (!pdfDocument) {\n      return;\n    }\n    const firstPagePromise = pdfDocument.getPage(1);\n    const optionalContentConfigPromise = pdfDocument.getOptionalContentConfig({\n      intent: \"display\"\n    });\n    firstPagePromise.then(firstPdfPage => {\n      const pagesCount = pdfDocument.numPages;\n      const viewport = firstPdfPage.getViewport({\n        scale: 1\n      });\n      for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) {\n        const thumbnail = new _pdf_thumbnail_view_js__WEBPACK_IMPORTED_MODULE_1__.PDFThumbnailView({\n          container: this.container,\n          eventBus: this.eventBus,\n          id: pageNum,\n          defaultViewport: viewport.clone(),\n          optionalContentConfigPromise,\n          linkService: this.linkService,\n          renderingQueue: this.renderingQueue,\n          pageColors: this.pageColors\n        });\n        this._thumbnails.push(thumbnail);\n      }\n      this._thumbnails[0]?.setPdfPage(firstPdfPage);\n      const thumbnailView = this._thumbnails[this._currentPageNumber - 1];\n      thumbnailView.div.classList.add(THUMBNAIL_SELECTED_CLASS);\n    }).catch(reason => {\n      console.error(\"Unable to initialize thumbnail viewer\", reason);\n    });\n  }\n  #cancelRendering() {\n    for (const thumbnail of this._thumbnails) {\n      thumbnail.cancelRendering();\n    }\n  }\n  setPageLabels(labels) {\n    if (!this.pdfDocument) {\n      return;\n    }\n    if (!labels) {\n      this._pageLabels = null;\n    } else if (!(Array.isArray(labels) && this.pdfDocument.numPages === labels.length)) {\n      this._pageLabels = null;\n      console.error(\"PDFThumbnailViewer_setPageLabels: Invalid page labels.\");\n    } else {\n      this._pageLabels = labels;\n    }\n    for (let i = 0, ii = this._thumbnails.length; i < ii; i++) {\n      this._thumbnails[i].setPageLabel(this._pageLabels?.[i] ?? null);\n    }\n  }\n  async #ensurePdfPageLoaded(thumbView) {\n    if (thumbView.pdfPage) {\n      return thumbView.pdfPage;\n    }\n    try {\n      const pdfPage = await this.pdfDocument.getPage(thumbView.id);\n      if (!thumbView.pdfPage) {\n        thumbView.setPdfPage(pdfPage);\n      }\n      return pdfPage;\n    } catch (reason) {\n      console.error(\"Unable to get page for thumb view\", reason);\n      return null;\n    }\n  }\n  #getScrollAhead(visible) {\n    if (visible.first?.id === 1) {\n      return true;\n    } else if (visible.last?.id === this._thumbnails.length) {\n      return false;\n    }\n    return this.scroll.down;\n  }\n  forceRendering() {\n    const visibleThumbs = this.#getVisibleThumbs();\n    const scrollAhead = this.#getScrollAhead(visibleThumbs);\n    const thumbView = this.renderingQueue.getHighestPriority(visibleThumbs, this._thumbnails, scrollAhead);\n    if (thumbView) {\n      this.#ensurePdfPageLoaded(thumbView).then(() => {\n        this.renderingQueue.renderView(thumbView);\n      });\n      return true;\n    }\n    return false;\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 6285:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   PDFViewer: () => (/* binding */ PDFViewer),\n/* harmony export */   PagesCountLimit: () => (/* binding */ PagesCountLimit)\n/* harmony export */ });\n/* unused harmony export PDFPageViewBuffer */\n/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603);\n/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7256);\n/* harmony import */ var web_null_l10n__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(410);\n/* harmony import */ var _pdf_page_view_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(9966);\n/* harmony import */ var _pdf_rendering_queue_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(6615);\n/* harmony import */ var _pdf_link_service_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(787);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__, web_null_l10n__WEBPACK_IMPORTED_MODULE_2__, _pdf_page_view_js__WEBPACK_IMPORTED_MODULE_3__, _pdf_rendering_queue_js__WEBPACK_IMPORTED_MODULE_4__]);\n([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__, web_null_l10n__WEBPACK_IMPORTED_MODULE_2__, _pdf_page_view_js__WEBPACK_IMPORTED_MODULE_3__, _pdf_rendering_queue_js__WEBPACK_IMPORTED_MODULE_4__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__);\n\n\n\n\n\n\nconst DEFAULT_CACHE_SIZE = 10;\nconst PagesCountLimit = {\n  FORCE_SCROLL_MODE_PAGE: 15000,\n  FORCE_LAZY_PAGE_INIT: 7500,\n  PAUSE_EAGER_PAGE_INIT: 250\n};\nfunction isValidAnnotationEditorMode(mode) {\n  return Object.values(pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType).includes(mode) && mode !== pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.DISABLE;\n}\nclass PDFPageViewBuffer {\n  #buf = new Set();\n  #size = 0;\n  constructor(size) {\n    this.#size = size;\n  }\n  push(view) {\n    const buf = this.#buf;\n    if (buf.has(view)) {\n      buf.delete(view);\n    }\n    buf.add(view);\n    if (buf.size > this.#size) {\n      this.#destroyFirstView();\n    }\n  }\n  resize(newSize, idsToKeep = null) {\n    this.#size = newSize;\n    const buf = this.#buf;\n    if (idsToKeep) {\n      const ii = buf.size;\n      let i = 1;\n      for (const view of buf) {\n        if (idsToKeep.has(view.id)) {\n          buf.delete(view);\n          buf.add(view);\n        }\n        if (++i > ii) {\n          break;\n        }\n      }\n    }\n    while (buf.size > this.#size) {\n      this.#destroyFirstView();\n    }\n  }\n  has(view) {\n    return this.#buf.has(view);\n  }\n  [Symbol.iterator]() {\n    return this.#buf.keys();\n  }\n  #destroyFirstView() {\n    const firstView = this.#buf.keys().next().value;\n    firstView?.destroy();\n    this.#buf.delete(firstView);\n  }\n}\nclass PDFViewer {\n  #buffer = null;\n  #altTextManager = null;\n  #annotationEditorHighlightColors = null;\n  #annotationEditorMode = pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE;\n  #annotationEditorUIManager = null;\n  #annotationMode = pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE_FORMS;\n  #containerTopLeft = null;\n  #copyCallbackBound = null;\n  #enableHighlightFloatingButton = false;\n  #enablePermissions = false;\n  #mlManager = null;\n  #getAllTextInProgress = false;\n  #hiddenCopyElement = null;\n  #interruptCopyCondition = false;\n  #previousContainerHeight = 0;\n  #resizeObserver = new ResizeObserver(this.#resizeObserverCallback.bind(this));\n  #scrollModePageState = null;\n  #onVisibilityChange = null;\n  #scaleTimeoutId = null;\n  #textLayerMode = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.TextLayerMode.ENABLE;\n  constructor(options) {\n    const viewerVersion = \"4.2.67\";\n    if (pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.version !== viewerVersion) {\n      throw new Error(`The API version \"${pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.version}\" does not match the Viewer version \"${viewerVersion}\".`);\n    }\n    this.container = options.container;\n    this.viewer = options.viewer || options.container.firstElementChild;\n    if (this.container?.tagName !== \"DIV\" || this.viewer?.tagName !== \"DIV\") {\n      throw new Error(\"Invalid `container` and/or `viewer` option.\");\n    }\n    if (this.container.offsetParent && getComputedStyle(this.container).position !== \"absolute\") {\n      throw new Error(\"The `container` must be absolutely positioned.\");\n    }\n    this.#resizeObserver.observe(this.container);\n    this.eventBus = options.eventBus;\n    this.linkService = options.linkService || new _pdf_link_service_js__WEBPACK_IMPORTED_MODULE_5__.SimpleLinkService();\n    this.downloadManager = options.downloadManager || null;\n    this.findController = options.findController || null;\n    this.#altTextManager = options.altTextManager || null;\n    if (this.findController) {\n      this.findController.onIsPageVisible = pageNumber => this._getVisiblePages().ids.has(pageNumber);\n    }\n    this._scriptingManager = options.scriptingManager || null;\n    this.#textLayerMode = options.textLayerMode ?? _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.TextLayerMode.ENABLE;\n    this.#annotationMode = options.annotationMode ?? pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE_FORMS;\n    this.#annotationEditorMode = options.annotationEditorMode ?? pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE;\n    this.#annotationEditorHighlightColors = options.annotationEditorHighlightColors || null;\n    this.#enableHighlightFloatingButton = options.enableHighlightFloatingButton === true;\n    this.imageResourcesPath = options.imageResourcesPath || \"\";\n    this.enablePrintAutoRotate = options.enablePrintAutoRotate || false;\n    this.removePageBorders = options.removePageBorders || false;\n    this.maxCanvasPixels = options.maxCanvasPixels;\n    this.l10n = options.l10n;\n    this.l10n ||= new web_null_l10n__WEBPACK_IMPORTED_MODULE_2__.GenericL10n();\n    this.#enablePermissions = options.enablePermissions || false;\n    this.pageColors = options.pageColors || null;\n    this.#mlManager = options.mlManager || null;\n    this.defaultRenderingQueue = !options.renderingQueue;\n    if (this.defaultRenderingQueue) {\n      this.renderingQueue = new _pdf_rendering_queue_js__WEBPACK_IMPORTED_MODULE_4__.PDFRenderingQueue();\n      this.renderingQueue.setViewer(this);\n    } else {\n      this.renderingQueue = options.renderingQueue;\n    }\n    this.scroll = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.watchScroll)(this.container, this._scrollUpdate.bind(this));\n    this.presentationModeState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.PresentationModeState.UNKNOWN;\n    this._onBeforeDraw = this._onAfterDraw = null;\n    this._resetView();\n    if (this.removePageBorders) {\n      this.viewer.classList.add(\"removePageBorders\");\n    }\n    this.#updateContainerHeightCss();\n    this.eventBus._on(\"thumbnailrendered\", ({\n      pageNumber,\n      pdfPage\n    }) => {\n      const pageView = this._pages[pageNumber - 1];\n      if (!this.#buffer.has(pageView)) {\n        pdfPage?.cleanup();\n      }\n    });\n    if (!options.l10n) {\n      this.l10n.translate(this.container);\n    }\n  }\n  get pagesCount() {\n    return this._pages.length;\n  }\n  getPageView(index) {\n    return this._pages[index];\n  }\n  getCachedPageViews() {\n    return new Set(this.#buffer);\n  }\n  get pageViewsReady() {\n    return this._pages.every(pageView => pageView?.pdfPage);\n  }\n  get renderForms() {\n    return this.#annotationMode === pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE_FORMS;\n  }\n  get enableScripting() {\n    return !!this._scriptingManager;\n  }\n  get currentPageNumber() {\n    return this._currentPageNumber;\n  }\n  set currentPageNumber(val) {\n    if (!Number.isInteger(val)) {\n      throw new Error(\"Invalid page number.\");\n    }\n    if (!this.pdfDocument) {\n      return;\n    }\n    if (!this._setCurrentPageNumber(val, true)) {\n      console.error(`currentPageNumber: \"${val}\" is not a valid page.`);\n    }\n  }\n  _setCurrentPageNumber(val, resetCurrentPageView = false) {\n    if (this._currentPageNumber === val) {\n      if (resetCurrentPageView) {\n        this.#resetCurrentPageView();\n      }\n      return true;\n    }\n    if (!(0 < val && val <= this.pagesCount)) {\n      return false;\n    }\n    const previous = this._currentPageNumber;\n    this._currentPageNumber = val;\n    this.eventBus.dispatch(\"pagechanging\", {\n      source: this,\n      pageNumber: val,\n      pageLabel: this._pageLabels?.[val - 1] ?? null,\n      previous\n    });\n    if (resetCurrentPageView) {\n      this.#resetCurrentPageView();\n    }\n    return true;\n  }\n  get currentPageLabel() {\n    return this._pageLabels?.[this._currentPageNumber - 1] ?? null;\n  }\n  set currentPageLabel(val) {\n    if (!this.pdfDocument) {\n      return;\n    }\n    let page = val | 0;\n    if (this._pageLabels) {\n      const i = this._pageLabels.indexOf(val);\n      if (i >= 0) {\n        page = i + 1;\n      }\n    }\n    if (!this._setCurrentPageNumber(page, true)) {\n      console.error(`currentPageLabel: \"${val}\" is not a valid page.`);\n    }\n  }\n  get currentScale() {\n    return this._currentScale !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.UNKNOWN_SCALE ? this._currentScale : _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.DEFAULT_SCALE;\n  }\n  set currentScale(val) {\n    if (isNaN(val)) {\n      throw new Error(\"Invalid numeric scale.\");\n    }\n    if (!this.pdfDocument) {\n      return;\n    }\n    this.#setScale(val, {\n      noScroll: false\n    });\n  }\n  get currentScaleValue() {\n    return this._currentScaleValue;\n  }\n  set currentScaleValue(val) {\n    if (!this.pdfDocument) {\n      return;\n    }\n    this.#setScale(val, {\n      noScroll: false\n    });\n  }\n  get pagesRotation() {\n    return this._pagesRotation;\n  }\n  set pagesRotation(rotation) {\n    if (!(0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.isValidRotation)(rotation)) {\n      throw new Error(\"Invalid pages rotation angle.\");\n    }\n    if (!this.pdfDocument) {\n      return;\n    }\n    rotation %= 360;\n    if (rotation < 0) {\n      rotation += 360;\n    }\n    if (this._pagesRotation === rotation) {\n      return;\n    }\n    this._pagesRotation = rotation;\n    const pageNumber = this._currentPageNumber;\n    this.refresh(true, {\n      rotation\n    });\n    if (this._currentScaleValue) {\n      this.#setScale(this._currentScaleValue, {\n        noScroll: true\n      });\n    }\n    this.eventBus.dispatch(\"rotationchanging\", {\n      source: this,\n      pagesRotation: rotation,\n      pageNumber\n    });\n    if (this.defaultRenderingQueue) {\n      this.update();\n    }\n  }\n  get firstPagePromise() {\n    return this.pdfDocument ? this._firstPageCapability.promise : null;\n  }\n  get onePageRendered() {\n    return this.pdfDocument ? this._onePageRenderedCapability.promise : null;\n  }\n  get pagesPromise() {\n    return this.pdfDocument ? this._pagesCapability.promise : null;\n  }\n  get _layerProperties() {\n    const self = this;\n    return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, \"_layerProperties\", {\n      get annotationEditorUIManager() {\n        return self.#annotationEditorUIManager;\n      },\n      get annotationStorage() {\n        return self.pdfDocument?.annotationStorage;\n      },\n      get downloadManager() {\n        return self.downloadManager;\n      },\n      get enableScripting() {\n        return !!self._scriptingManager;\n      },\n      get fieldObjectsPromise() {\n        return self.pdfDocument?.getFieldObjects();\n      },\n      get findController() {\n        return self.findController;\n      },\n      get hasJSActionsPromise() {\n        return self.pdfDocument?.hasJSActions();\n      },\n      get linkService() {\n        return self.linkService;\n      }\n    });\n  }\n  #initializePermissions(permissions) {\n    const params = {\n      annotationEditorMode: this.#annotationEditorMode,\n      annotationMode: this.#annotationMode,\n      textLayerMode: this.#textLayerMode\n    };\n    if (!permissions) {\n      return params;\n    }\n    if (!permissions.includes(pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PermissionFlag.COPY) && this.#textLayerMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.TextLayerMode.ENABLE) {\n      params.textLayerMode = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.TextLayerMode.ENABLE_PERMISSIONS;\n    }\n    if (!permissions.includes(pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PermissionFlag.MODIFY_CONTENTS)) {\n      params.annotationEditorMode = pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.DISABLE;\n    }\n    if (!permissions.includes(pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PermissionFlag.MODIFY_ANNOTATIONS) && !permissions.includes(pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PermissionFlag.FILL_INTERACTIVE_FORMS) && this.#annotationMode === pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE_FORMS) {\n      params.annotationMode = pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE;\n    }\n    return params;\n  }\n  async #onePageRenderedOrForceFetch() {\n    if (document.visibilityState === \"hidden\" || !this.container.offsetParent || this._getVisiblePages().views.length === 0) {\n      return;\n    }\n    const visibilityChangePromise = new Promise(resolve => {\n      this.#onVisibilityChange = () => {\n        if (document.visibilityState !== \"hidden\") {\n          return;\n        }\n        resolve();\n      };\n      document.addEventListener(\"visibilitychange\", this.#onVisibilityChange);\n    });\n    await Promise.race([this._onePageRenderedCapability.promise, visibilityChangePromise]);\n    document.removeEventListener(\"visibilitychange\", this.#onVisibilityChange);\n    this.#onVisibilityChange = null;\n  }\n  async getAllText() {\n    const texts = [];\n    const buffer = [];\n    for (let pageNum = 1, pagesCount = this.pdfDocument.numPages; pageNum <= pagesCount; ++pageNum) {\n      if (this.#interruptCopyCondition) {\n        return null;\n      }\n      buffer.length = 0;\n      const page = await this.pdfDocument.getPage(pageNum);\n      const {\n        items\n      } = await page.getTextContent();\n      for (const item of items) {\n        if (item.str) {\n          buffer.push(item.str);\n        }\n        if (item.hasEOL) {\n          buffer.push(\"\\n\");\n        }\n      }\n      texts.push((0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.removeNullCharacters)(buffer.join(\"\")));\n    }\n    return texts.join(\"\\n\");\n  }\n  #copyCallback(textLayerMode, event) {\n    const selection = document.getSelection();\n    const {\n      focusNode,\n      anchorNode\n    } = selection;\n    if (anchorNode && focusNode && selection.containsNode(this.#hiddenCopyElement)) {\n      if (this.#getAllTextInProgress || textLayerMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.TextLayerMode.ENABLE_PERMISSIONS) {\n        event.preventDefault();\n        event.stopPropagation();\n        return;\n      }\n      this.#getAllTextInProgress = true;\n      const savedCursor = this.container.style.cursor;\n      this.container.style.cursor = \"wait\";\n      const interruptCopy = ev => this.#interruptCopyCondition = ev.key === \"Escape\";\n      window.addEventListener(\"keydown\", interruptCopy);\n      this.getAllText().then(async text => {\n        if (text !== null) {\n          await navigator.clipboard.writeText(text);\n        }\n      }).catch(reason => {\n        console.warn(`Something goes wrong when extracting the text: ${reason.message}`);\n      }).finally(() => {\n        this.#getAllTextInProgress = false;\n        this.#interruptCopyCondition = false;\n        window.removeEventListener(\"keydown\", interruptCopy);\n        this.container.style.cursor = savedCursor;\n      });\n      event.preventDefault();\n      event.stopPropagation();\n    }\n  }\n  setDocument(pdfDocument) {\n    if (this.pdfDocument) {\n      this.eventBus.dispatch(\"pagesdestroy\", {\n        source: this\n      });\n      this._cancelRendering();\n      this._resetView();\n      this.findController?.setDocument(null);\n      this._scriptingManager?.setDocument(null);\n      if (this.#annotationEditorUIManager) {\n        this.#annotationEditorUIManager.destroy();\n        this.#annotationEditorUIManager = null;\n      }\n    }\n    this.pdfDocument = pdfDocument;\n    if (!pdfDocument) {\n      return;\n    }\n    const pagesCount = pdfDocument.numPages;\n    const firstPagePromise = pdfDocument.getPage(1);\n    const optionalContentConfigPromise = pdfDocument.getOptionalContentConfig({\n      intent: \"display\"\n    });\n    const permissionsPromise = this.#enablePermissions ? pdfDocument.getPermissions() : Promise.resolve();\n    if (pagesCount > PagesCountLimit.FORCE_SCROLL_MODE_PAGE) {\n      console.warn(\"Forcing PAGE-scrolling for performance reasons, given the length of the document.\");\n      const mode = this._scrollMode = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.PAGE;\n      this.eventBus.dispatch(\"scrollmodechanged\", {\n        source: this,\n        mode\n      });\n    }\n    this._pagesCapability.promise.then(() => {\n      this.eventBus.dispatch(\"pagesloaded\", {\n        source: this,\n        pagesCount\n      });\n    }, () => {});\n    this._onBeforeDraw = evt => {\n      const pageView = this._pages[evt.pageNumber - 1];\n      if (!pageView) {\n        return;\n      }\n      this.#buffer.push(pageView);\n    };\n    this.eventBus._on(\"pagerender\", this._onBeforeDraw);\n    this._onAfterDraw = evt => {\n      if (evt.cssTransform) {\n        return;\n      }\n      this._onePageRenderedCapability.resolve({\n        timestamp: evt.timestamp\n      });\n      this.eventBus._off(\"pagerendered\", this._onAfterDraw);\n      this._onAfterDraw = null;\n    };\n    this.eventBus._on(\"pagerendered\", this._onAfterDraw);\n    Promise.all([firstPagePromise, permissionsPromise]).then(([firstPdfPage, permissions]) => {\n      if (pdfDocument !== this.pdfDocument) {\n        return;\n      }\n      this._firstPageCapability.resolve(firstPdfPage);\n      this._optionalContentConfigPromise = optionalContentConfigPromise;\n      const {\n        annotationEditorMode,\n        annotationMode,\n        textLayerMode\n      } = this.#initializePermissions(permissions);\n      if (textLayerMode !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.TextLayerMode.DISABLE) {\n        const element = this.#hiddenCopyElement = document.createElement(\"div\");\n        element.id = \"hiddenCopyElement\";\n        this.viewer.before(element);\n      }\n      if (annotationEditorMode !== pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.DISABLE) {\n        const mode = annotationEditorMode;\n        if (pdfDocument.isPureXfa) {\n          console.warn(\"Warning: XFA-editing is not implemented.\");\n        } else if (isValidAnnotationEditorMode(mode)) {\n          this.#annotationEditorUIManager = new pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorUIManager(this.container, this.viewer, this.#altTextManager, this.eventBus, pdfDocument, this.pageColors, this.#annotationEditorHighlightColors, this.#enableHighlightFloatingButton, this.#mlManager);\n          this.eventBus.dispatch(\"annotationeditoruimanager\", {\n            source: this,\n            uiManager: this.#annotationEditorUIManager\n          });\n          if (mode !== pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE) {\n            this.#annotationEditorUIManager.updateMode(mode);\n          }\n        } else {\n          console.error(`Invalid AnnotationEditor mode: ${mode}`);\n        }\n      }\n      const viewerElement = this._scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.PAGE ? null : this.viewer;\n      const scale = this.currentScale;\n      const viewport = firstPdfPage.getViewport({\n        scale: scale * pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PixelsPerInch.PDF_TO_CSS_UNITS\n      });\n      this.viewer.style.setProperty(\"--scale-factor\", viewport.scale);\n      if (this.pageColors?.foreground === \"CanvasText\" || this.pageColors?.background === \"Canvas\") {\n        this.viewer.style.setProperty(\"--hcm-highlight-filter\", pdfDocument.filterFactory.addHighlightHCMFilter(\"highlight\", \"CanvasText\", \"Canvas\", \"HighlightText\", \"Highlight\"));\n        this.viewer.style.setProperty(\"--hcm-highlight-selected-filter\", pdfDocument.filterFactory.addHighlightHCMFilter(\"highlight_selected\", \"CanvasText\", \"Canvas\", \"HighlightText\", \"ButtonText\"));\n      }\n      for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) {\n        const pageView = new _pdf_page_view_js__WEBPACK_IMPORTED_MODULE_3__.PDFPageView({\n          container: viewerElement,\n          eventBus: this.eventBus,\n          id: pageNum,\n          scale,\n          defaultViewport: viewport.clone(),\n          optionalContentConfigPromise,\n          renderingQueue: this.renderingQueue,\n          textLayerMode,\n          annotationMode,\n          imageResourcesPath: this.imageResourcesPath,\n          maxCanvasPixels: this.maxCanvasPixels,\n          pageColors: this.pageColors,\n          l10n: this.l10n,\n          layerProperties: this._layerProperties\n        });\n        this._pages.push(pageView);\n      }\n      this._pages[0]?.setPdfPage(firstPdfPage);\n      if (this._scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.PAGE) {\n        this.#ensurePageViewVisible();\n      } else if (this._spreadMode !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.SpreadMode.NONE) {\n        this._updateSpreadMode();\n      }\n      this.#onePageRenderedOrForceFetch().then(async () => {\n        this.findController?.setDocument(pdfDocument);\n        this._scriptingManager?.setDocument(pdfDocument);\n        if (this.#hiddenCopyElement) {\n          this.#copyCallbackBound = this.#copyCallback.bind(this, textLayerMode);\n          document.addEventListener(\"copy\", this.#copyCallbackBound);\n        }\n        if (this.#annotationEditorUIManager) {\n          this.eventBus.dispatch(\"annotationeditormodechanged\", {\n            source: this,\n            mode: this.#annotationEditorMode\n          });\n        }\n        if (pdfDocument.loadingParams.disableAutoFetch || pagesCount > PagesCountLimit.FORCE_LAZY_PAGE_INIT) {\n          this._pagesCapability.resolve();\n          return;\n        }\n        let getPagesLeft = pagesCount - 1;\n        if (getPagesLeft <= 0) {\n          this._pagesCapability.resolve();\n          return;\n        }\n        for (let pageNum = 2; pageNum <= pagesCount; ++pageNum) {\n          const promise = pdfDocument.getPage(pageNum).then(pdfPage => {\n            const pageView = this._pages[pageNum - 1];\n            if (!pageView.pdfPage) {\n              pageView.setPdfPage(pdfPage);\n            }\n            if (--getPagesLeft === 0) {\n              this._pagesCapability.resolve();\n            }\n          }, reason => {\n            console.error(`Unable to get page ${pageNum} to initialize viewer`, reason);\n            if (--getPagesLeft === 0) {\n              this._pagesCapability.resolve();\n            }\n          });\n          if (pageNum % PagesCountLimit.PAUSE_EAGER_PAGE_INIT === 0) {\n            await promise;\n          }\n        }\n      });\n      this.eventBus.dispatch(\"pagesinit\", {\n        source: this\n      });\n      pdfDocument.getMetadata().then(({\n        info\n      }) => {\n        if (pdfDocument !== this.pdfDocument) {\n          return;\n        }\n        if (info.Language) {\n          this.viewer.lang = info.Language;\n        }\n      });\n      if (this.defaultRenderingQueue) {\n        this.update();\n      }\n    }).catch(reason => {\n      console.error(\"Unable to initialize viewer\", reason);\n      this._pagesCapability.reject(reason);\n    });\n  }\n  setPageLabels(labels) {\n    if (!this.pdfDocument) {\n      return;\n    }\n    if (!labels) {\n      this._pageLabels = null;\n    } else if (!(Array.isArray(labels) && this.pdfDocument.numPages === labels.length)) {\n      this._pageLabels = null;\n      console.error(`setPageLabels: Invalid page labels.`);\n    } else {\n      this._pageLabels = labels;\n    }\n    for (let i = 0, ii = this._pages.length; i < ii; i++) {\n      this._pages[i].setPageLabel(this._pageLabels?.[i] ?? null);\n    }\n  }\n  _resetView() {\n    this._pages = [];\n    this._currentPageNumber = 1;\n    this._currentScale = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.UNKNOWN_SCALE;\n    this._currentScaleValue = null;\n    this._pageLabels = null;\n    this.#buffer = new PDFPageViewBuffer(DEFAULT_CACHE_SIZE);\n    this._location = null;\n    this._pagesRotation = 0;\n    this._optionalContentConfigPromise = null;\n    this._firstPageCapability = Promise.withResolvers();\n    this._onePageRenderedCapability = Promise.withResolvers();\n    this._pagesCapability = Promise.withResolvers();\n    this._scrollMode = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.VERTICAL;\n    this._previousScrollMode = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.UNKNOWN;\n    this._spreadMode = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.SpreadMode.NONE;\n    this.#scrollModePageState = {\n      previousPageNumber: 1,\n      scrollDown: true,\n      pages: []\n    };\n    if (this._onBeforeDraw) {\n      this.eventBus._off(\"pagerender\", this._onBeforeDraw);\n      this._onBeforeDraw = null;\n    }\n    if (this._onAfterDraw) {\n      this.eventBus._off(\"pagerendered\", this._onAfterDraw);\n      this._onAfterDraw = null;\n    }\n    if (this.#onVisibilityChange) {\n      document.removeEventListener(\"visibilitychange\", this.#onVisibilityChange);\n      this.#onVisibilityChange = null;\n    }\n    this.viewer.textContent = \"\";\n    this._updateScrollMode();\n    this.viewer.removeAttribute(\"lang\");\n    if (this.#hiddenCopyElement) {\n      document.removeEventListener(\"copy\", this.#copyCallbackBound);\n      this.#copyCallbackBound = null;\n      this.#hiddenCopyElement.remove();\n      this.#hiddenCopyElement = null;\n    }\n  }\n  #ensurePageViewVisible() {\n    if (this._scrollMode !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.PAGE) {\n      throw new Error(\"#ensurePageViewVisible: Invalid scrollMode value.\");\n    }\n    const pageNumber = this._currentPageNumber,\n      state = this.#scrollModePageState,\n      viewer = this.viewer;\n    viewer.textContent = \"\";\n    state.pages.length = 0;\n    if (this._spreadMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.SpreadMode.NONE && !this.isInPresentationMode) {\n      const pageView = this._pages[pageNumber - 1];\n      viewer.append(pageView.div);\n      state.pages.push(pageView);\n    } else {\n      const pageIndexSet = new Set(),\n        parity = this._spreadMode - 1;\n      if (parity === -1) {\n        pageIndexSet.add(pageNumber - 1);\n      } else if (pageNumber % 2 !== parity) {\n        pageIndexSet.add(pageNumber - 1);\n        pageIndexSet.add(pageNumber);\n      } else {\n        pageIndexSet.add(pageNumber - 2);\n        pageIndexSet.add(pageNumber - 1);\n      }\n      const spread = document.createElement(\"div\");\n      spread.className = \"spread\";\n      if (this.isInPresentationMode) {\n        const dummyPage = document.createElement(\"div\");\n        dummyPage.className = \"dummyPage\";\n        spread.append(dummyPage);\n      }\n      for (const i of pageIndexSet) {\n        const pageView = this._pages[i];\n        if (!pageView) {\n          continue;\n        }\n        spread.append(pageView.div);\n        state.pages.push(pageView);\n      }\n      viewer.append(spread);\n    }\n    state.scrollDown = pageNumber >= state.previousPageNumber;\n    state.previousPageNumber = pageNumber;\n  }\n  _scrollUpdate() {\n    if (this.pagesCount === 0) {\n      return;\n    }\n    this.update();\n  }\n  #scrollIntoView(pageView, pageSpot = null) {\n    const {\n      div,\n      id\n    } = pageView;\n    if (this._currentPageNumber !== id) {\n      this._setCurrentPageNumber(id);\n    }\n    if (this._scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.PAGE) {\n      this.#ensurePageViewVisible();\n      this.update();\n    }\n    if (!pageSpot && !this.isInPresentationMode) {\n      const left = div.offsetLeft + div.clientLeft,\n        right = left + div.clientWidth;\n      const {\n        scrollLeft,\n        clientWidth\n      } = this.container;\n      if (this._scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.HORIZONTAL || left < scrollLeft || right > scrollLeft + clientWidth) {\n        pageSpot = {\n          left: 0,\n          top: 0\n        };\n      }\n    }\n    (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.scrollIntoView)(div, pageSpot);\n    if (!this._currentScaleValue && this._location) {\n      this._location = null;\n    }\n  }\n  #isSameScale(newScale) {\n    return newScale === this._currentScale || Math.abs(newScale - this._currentScale) < 1e-15;\n  }\n  #setScaleUpdatePages(newScale, newValue, {\n    noScroll = false,\n    preset = false,\n    drawingDelay = -1\n  }) {\n    this._currentScaleValue = newValue.toString();\n    if (this.#isSameScale(newScale)) {\n      if (preset) {\n        this.eventBus.dispatch(\"scalechanging\", {\n          source: this,\n          scale: newScale,\n          presetValue: newValue\n        });\n      }\n      return;\n    }\n    this.viewer.style.setProperty(\"--scale-factor\", newScale * pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PixelsPerInch.PDF_TO_CSS_UNITS);\n    const postponeDrawing = drawingDelay >= 0 && drawingDelay < 1000;\n    this.refresh(true, {\n      scale: newScale,\n      drawingDelay: postponeDrawing ? drawingDelay : -1\n    });\n    if (postponeDrawing) {\n      this.#scaleTimeoutId = setTimeout(() => {\n        this.#scaleTimeoutId = null;\n        this.refresh();\n      }, drawingDelay);\n    }\n    this._currentScale = newScale;\n    if (!noScroll) {\n      let page = this._currentPageNumber,\n        dest;\n      if (this._location && !(this.isInPresentationMode || this.isChangingPresentationMode)) {\n        page = this._location.pageNumber;\n        dest = [null, {\n          name: \"XYZ\"\n        }, this._location.left, this._location.top, null];\n      }\n      this.scrollPageIntoView({\n        pageNumber: page,\n        destArray: dest,\n        allowNegativeOffset: true\n      });\n    }\n    this.eventBus.dispatch(\"scalechanging\", {\n      source: this,\n      scale: newScale,\n      presetValue: preset ? newValue : undefined\n    });\n    if (this.defaultRenderingQueue) {\n      this.update();\n    }\n  }\n  get #pageWidthScaleFactor() {\n    if (this._spreadMode !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.SpreadMode.NONE && this._scrollMode !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.HORIZONTAL) {\n      return 2;\n    }\n    return 1;\n  }\n  #setScale(value, options) {\n    let scale = parseFloat(value);\n    if (scale > 0) {\n      options.preset = false;\n      this.#setScaleUpdatePages(scale, value, options);\n    } else {\n      const currentPage = this._pages[this._currentPageNumber - 1];\n      if (!currentPage) {\n        return;\n      }\n      let hPadding = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.SCROLLBAR_PADDING,\n        vPadding = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.VERTICAL_PADDING;\n      if (this.isInPresentationMode) {\n        hPadding = vPadding = 4;\n        if (this._spreadMode !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.SpreadMode.NONE) {\n          hPadding *= 2;\n        }\n      } else if (this.removePageBorders) {\n        hPadding = vPadding = 0;\n      } else if (this._scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.HORIZONTAL) {\n        [hPadding, vPadding] = [vPadding, hPadding];\n      }\n      const pageWidthScale = (this.container.clientWidth - hPadding) / currentPage.width * currentPage.scale / this.#pageWidthScaleFactor;\n      const pageHeightScale = (this.container.clientHeight - vPadding) / currentPage.height * currentPage.scale;\n      switch (value) {\n        case \"page-actual\":\n          scale = 1;\n          break;\n        case \"page-width\":\n          scale = pageWidthScale;\n          break;\n        case \"page-height\":\n          scale = pageHeightScale;\n          break;\n        case \"page-fit\":\n          scale = Math.min(pageWidthScale, pageHeightScale);\n          break;\n        case \"auto\":\n          const horizontalScale = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.isPortraitOrientation)(currentPage) ? pageWidthScale : Math.min(pageHeightScale, pageWidthScale);\n          scale = Math.min(_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.MAX_AUTO_SCALE, horizontalScale);\n          break;\n        default:\n          console.error(`#setScale: \"${value}\" is an unknown zoom value.`);\n          return;\n      }\n      options.preset = true;\n      this.#setScaleUpdatePages(scale, value, options);\n    }\n  }\n  #resetCurrentPageView() {\n    const pageView = this._pages[this._currentPageNumber - 1];\n    if (this.isInPresentationMode) {\n      this.#setScale(this._currentScaleValue, {\n        noScroll: true\n      });\n    }\n    this.#scrollIntoView(pageView);\n  }\n  pageLabelToPageNumber(label) {\n    if (!this._pageLabels) {\n      return null;\n    }\n    const i = this._pageLabels.indexOf(label);\n    if (i < 0) {\n      return null;\n    }\n    return i + 1;\n  }\n  scrollPageIntoView({\n    pageNumber,\n    destArray = null,\n    allowNegativeOffset = false,\n    ignoreDestinationZoom = false\n  }) {\n    if (!this.pdfDocument) {\n      return;\n    }\n    const pageView = Number.isInteger(pageNumber) && this._pages[pageNumber - 1];\n    if (!pageView) {\n      console.error(`scrollPageIntoView: \"${pageNumber}\" is not a valid pageNumber parameter.`);\n      return;\n    }\n    if (this.isInPresentationMode || !destArray) {\n      this._setCurrentPageNumber(pageNumber, true);\n      return;\n    }\n    let x = 0,\n      y = 0;\n    let width = 0,\n      height = 0,\n      widthScale,\n      heightScale;\n    const changeOrientation = pageView.rotation % 180 !== 0;\n    const pageWidth = (changeOrientation ? pageView.height : pageView.width) / pageView.scale / pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PixelsPerInch.PDF_TO_CSS_UNITS;\n    const pageHeight = (changeOrientation ? pageView.width : pageView.height) / pageView.scale / pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PixelsPerInch.PDF_TO_CSS_UNITS;\n    let scale = 0;\n    switch (destArray[1].name) {\n      case \"XYZ\":\n        x = destArray[2];\n        y = destArray[3];\n        scale = destArray[4];\n        x = x !== null ? x : 0;\n        y = y !== null ? y : pageHeight;\n        break;\n      case \"Fit\":\n      case \"FitB\":\n        scale = \"page-fit\";\n        break;\n      case \"FitH\":\n      case \"FitBH\":\n        y = destArray[2];\n        scale = \"page-width\";\n        if (y === null && this._location) {\n          x = this._location.left;\n          y = this._location.top;\n        } else if (typeof y !== \"number\" || y < 0) {\n          y = pageHeight;\n        }\n        break;\n      case \"FitV\":\n      case \"FitBV\":\n        x = destArray[2];\n        width = pageWidth;\n        height = pageHeight;\n        scale = \"page-height\";\n        break;\n      case \"FitR\":\n        x = destArray[2];\n        y = destArray[3];\n        width = destArray[4] - x;\n        height = destArray[5] - y;\n        let hPadding = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.SCROLLBAR_PADDING,\n          vPadding = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.VERTICAL_PADDING;\n        if (this.removePageBorders) {\n          hPadding = vPadding = 0;\n        }\n        widthScale = (this.container.clientWidth - hPadding) / width / pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PixelsPerInch.PDF_TO_CSS_UNITS;\n        heightScale = (this.container.clientHeight - vPadding) / height / pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PixelsPerInch.PDF_TO_CSS_UNITS;\n        scale = Math.min(Math.abs(widthScale), Math.abs(heightScale));\n        break;\n      default:\n        console.error(`scrollPageIntoView: \"${destArray[1].name}\" is not a valid destination type.`);\n        return;\n    }\n    if (!ignoreDestinationZoom) {\n      if (scale && scale !== this._currentScale) {\n        this.currentScaleValue = scale;\n      } else if (this._currentScale === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.UNKNOWN_SCALE) {\n        this.currentScaleValue = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.DEFAULT_SCALE_VALUE;\n      }\n    }\n    if (scale === \"page-fit\" && !destArray[4]) {\n      this.#scrollIntoView(pageView);\n      return;\n    }\n    const boundingRect = [pageView.viewport.convertToViewportPoint(x, y), pageView.viewport.convertToViewportPoint(x + width, y + height)];\n    let left = Math.min(boundingRect[0][0], boundingRect[1][0]);\n    let top = Math.min(boundingRect[0][1], boundingRect[1][1]);\n    if (!allowNegativeOffset) {\n      left = Math.max(left, 0);\n      top = Math.max(top, 0);\n    }\n    this.#scrollIntoView(pageView, {\n      left,\n      top\n    });\n  }\n  _updateLocation(firstPage) {\n    const currentScale = this._currentScale;\n    const currentScaleValue = this._currentScaleValue;\n    const normalizedScaleValue = parseFloat(currentScaleValue) === currentScale ? Math.round(currentScale * 10000) / 100 : currentScaleValue;\n    const pageNumber = firstPage.id;\n    const currentPageView = this._pages[pageNumber - 1];\n    const container = this.container;\n    const topLeft = currentPageView.getPagePoint(container.scrollLeft - firstPage.x, container.scrollTop - firstPage.y);\n    const intLeft = Math.round(topLeft[0]);\n    const intTop = Math.round(topLeft[1]);\n    let pdfOpenParams = `#page=${pageNumber}`;\n    if (!this.isInPresentationMode) {\n      pdfOpenParams += `&zoom=${normalizedScaleValue},${intLeft},${intTop}`;\n    }\n    this._location = {\n      pageNumber,\n      scale: normalizedScaleValue,\n      top: intTop,\n      left: intLeft,\n      rotation: this._pagesRotation,\n      pdfOpenParams\n    };\n  }\n  update() {\n    const visible = this._getVisiblePages();\n    const visiblePages = visible.views,\n      numVisiblePages = visiblePages.length;\n    if (numVisiblePages === 0) {\n      return;\n    }\n    const newCacheSize = Math.max(DEFAULT_CACHE_SIZE, 2 * numVisiblePages + 1);\n    this.#buffer.resize(newCacheSize, visible.ids);\n    this.renderingQueue.renderHighestPriority(visible);\n    const isSimpleLayout = this._spreadMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.SpreadMode.NONE && (this._scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.PAGE || this._scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.VERTICAL);\n    const currentId = this._currentPageNumber;\n    let stillFullyVisible = false;\n    for (const page of visiblePages) {\n      if (page.percent < 100) {\n        break;\n      }\n      if (page.id === currentId && isSimpleLayout) {\n        stillFullyVisible = true;\n        break;\n      }\n    }\n    this._setCurrentPageNumber(stillFullyVisible ? currentId : visiblePages[0].id);\n    this._updateLocation(visible.first);\n    this.eventBus.dispatch(\"updateviewarea\", {\n      source: this,\n      location: this._location\n    });\n  }\n  containsElement(element) {\n    return this.container.contains(element);\n  }\n  focus() {\n    this.container.focus();\n  }\n  get _isContainerRtl() {\n    return getComputedStyle(this.container).direction === \"rtl\";\n  }\n  get isInPresentationMode() {\n    return this.presentationModeState === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.PresentationModeState.FULLSCREEN;\n  }\n  get isChangingPresentationMode() {\n    return this.presentationModeState === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.PresentationModeState.CHANGING;\n  }\n  get isHorizontalScrollbarEnabled() {\n    return this.isInPresentationMode ? false : this.container.scrollWidth > this.container.clientWidth;\n  }\n  get isVerticalScrollbarEnabled() {\n    return this.isInPresentationMode ? false : this.container.scrollHeight > this.container.clientHeight;\n  }\n  _getVisiblePages() {\n    const views = this._scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.PAGE ? this.#scrollModePageState.pages : this._pages,\n      horizontal = this._scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.HORIZONTAL,\n      rtl = horizontal && this._isContainerRtl;\n    return (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.getVisibleElements)({\n      scrollEl: this.container,\n      views,\n      sortByVisibility: true,\n      horizontal,\n      rtl\n    });\n  }\n  cleanup() {\n    for (const pageView of this._pages) {\n      if (pageView.renderingState !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.FINISHED) {\n        pageView.reset();\n      }\n    }\n  }\n  _cancelRendering() {\n    for (const pageView of this._pages) {\n      pageView.cancelRendering();\n    }\n  }\n  async #ensurePdfPageLoaded(pageView) {\n    if (pageView.pdfPage) {\n      return pageView.pdfPage;\n    }\n    try {\n      const pdfPage = await this.pdfDocument.getPage(pageView.id);\n      if (!pageView.pdfPage) {\n        pageView.setPdfPage(pdfPage);\n      }\n      return pdfPage;\n    } catch (reason) {\n      console.error(\"Unable to get page for page view\", reason);\n      return null;\n    }\n  }\n  #getScrollAhead(visible) {\n    if (visible.first?.id === 1) {\n      return true;\n    } else if (visible.last?.id === this.pagesCount) {\n      return false;\n    }\n    switch (this._scrollMode) {\n      case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.PAGE:\n        return this.#scrollModePageState.scrollDown;\n      case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.HORIZONTAL:\n        return this.scroll.right;\n    }\n    return this.scroll.down;\n  }\n  forceRendering(currentlyVisiblePages) {\n    const visiblePages = currentlyVisiblePages || this._getVisiblePages();\n    const scrollAhead = this.#getScrollAhead(visiblePages);\n    const preRenderExtra = this._spreadMode !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.SpreadMode.NONE && this._scrollMode !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.HORIZONTAL;\n    const pageView = this.renderingQueue.getHighestPriority(visiblePages, this._pages, scrollAhead, preRenderExtra);\n    if (pageView) {\n      this.#ensurePdfPageLoaded(pageView).then(() => {\n        this.renderingQueue.renderView(pageView);\n      });\n      return true;\n    }\n    return false;\n  }\n  get hasEqualPageSizes() {\n    const firstPageView = this._pages[0];\n    for (let i = 1, ii = this._pages.length; i < ii; ++i) {\n      const pageView = this._pages[i];\n      if (pageView.width !== firstPageView.width || pageView.height !== firstPageView.height) {\n        return false;\n      }\n    }\n    return true;\n  }\n  getPagesOverview() {\n    let initialOrientation;\n    return this._pages.map(pageView => {\n      const viewport = pageView.pdfPage.getViewport({\n        scale: 1\n      });\n      const orientation = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.isPortraitOrientation)(viewport);\n      if (initialOrientation === undefined) {\n        initialOrientation = orientation;\n      } else if (this.enablePrintAutoRotate && orientation !== initialOrientation) {\n        return {\n          width: viewport.height,\n          height: viewport.width,\n          rotation: (viewport.rotation - 90) % 360\n        };\n      }\n      return {\n        width: viewport.width,\n        height: viewport.height,\n        rotation: viewport.rotation\n      };\n    });\n  }\n  get optionalContentConfigPromise() {\n    if (!this.pdfDocument) {\n      return Promise.resolve(null);\n    }\n    if (!this._optionalContentConfigPromise) {\n      console.error(\"optionalContentConfigPromise: Not initialized yet.\");\n      return this.pdfDocument.getOptionalContentConfig({\n        intent: \"display\"\n      });\n    }\n    return this._optionalContentConfigPromise;\n  }\n  set optionalContentConfigPromise(promise) {\n    if (!(promise instanceof Promise)) {\n      throw new Error(`Invalid optionalContentConfigPromise: ${promise}`);\n    }\n    if (!this.pdfDocument) {\n      return;\n    }\n    if (!this._optionalContentConfigPromise) {\n      return;\n    }\n    this._optionalContentConfigPromise = promise;\n    this.refresh(false, {\n      optionalContentConfigPromise: promise\n    });\n    this.eventBus.dispatch(\"optionalcontentconfigchanged\", {\n      source: this,\n      promise\n    });\n  }\n  get scrollMode() {\n    return this._scrollMode;\n  }\n  set scrollMode(mode) {\n    if (this._scrollMode === mode) {\n      return;\n    }\n    if (!(0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.isValidScrollMode)(mode)) {\n      throw new Error(`Invalid scroll mode: ${mode}`);\n    }\n    if (this.pagesCount > PagesCountLimit.FORCE_SCROLL_MODE_PAGE) {\n      return;\n    }\n    this._previousScrollMode = this._scrollMode;\n    this._scrollMode = mode;\n    this.eventBus.dispatch(\"scrollmodechanged\", {\n      source: this,\n      mode\n    });\n    this._updateScrollMode(this._currentPageNumber);\n  }\n  _updateScrollMode(pageNumber = null) {\n    const scrollMode = this._scrollMode,\n      viewer = this.viewer;\n    viewer.classList.toggle(\"scrollHorizontal\", scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.HORIZONTAL);\n    viewer.classList.toggle(\"scrollWrapped\", scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.WRAPPED);\n    if (!this.pdfDocument || !pageNumber) {\n      return;\n    }\n    if (scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.PAGE) {\n      this.#ensurePageViewVisible();\n    } else if (this._previousScrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.PAGE) {\n      this._updateSpreadMode();\n    }\n    if (this._currentScaleValue && isNaN(this._currentScaleValue)) {\n      this.#setScale(this._currentScaleValue, {\n        noScroll: true\n      });\n    }\n    this._setCurrentPageNumber(pageNumber, true);\n    this.update();\n  }\n  get spreadMode() {\n    return this._spreadMode;\n  }\n  set spreadMode(mode) {\n    if (this._spreadMode === mode) {\n      return;\n    }\n    if (!(0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.isValidSpreadMode)(mode)) {\n      throw new Error(`Invalid spread mode: ${mode}`);\n    }\n    this._spreadMode = mode;\n    this.eventBus.dispatch(\"spreadmodechanged\", {\n      source: this,\n      mode\n    });\n    this._updateSpreadMode(this._currentPageNumber);\n  }\n  _updateSpreadMode(pageNumber = null) {\n    if (!this.pdfDocument) {\n      return;\n    }\n    const viewer = this.viewer,\n      pages = this._pages;\n    if (this._scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.PAGE) {\n      this.#ensurePageViewVisible();\n    } else {\n      viewer.textContent = \"\";\n      if (this._spreadMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.SpreadMode.NONE) {\n        for (const pageView of this._pages) {\n          viewer.append(pageView.div);\n        }\n      } else {\n        const parity = this._spreadMode - 1;\n        let spread = null;\n        for (let i = 0, ii = pages.length; i < ii; ++i) {\n          if (spread === null) {\n            spread = document.createElement(\"div\");\n            spread.className = \"spread\";\n            viewer.append(spread);\n          } else if (i % 2 === parity) {\n            spread = spread.cloneNode(false);\n            viewer.append(spread);\n          }\n          spread.append(pages[i].div);\n        }\n      }\n    }\n    if (!pageNumber) {\n      return;\n    }\n    if (this._currentScaleValue && isNaN(this._currentScaleValue)) {\n      this.#setScale(this._currentScaleValue, {\n        noScroll: true\n      });\n    }\n    this._setCurrentPageNumber(pageNumber, true);\n    this.update();\n  }\n  _getPageAdvance(currentPageNumber, previous = false) {\n    switch (this._scrollMode) {\n      case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.WRAPPED:\n        {\n          const {\n              views\n            } = this._getVisiblePages(),\n            pageLayout = new Map();\n          for (const {\n            id,\n            y,\n            percent,\n            widthPercent\n          } of views) {\n            if (percent === 0 || widthPercent < 100) {\n              continue;\n            }\n            let yArray = pageLayout.get(y);\n            if (!yArray) {\n              pageLayout.set(y, yArray ||= []);\n            }\n            yArray.push(id);\n          }\n          for (const yArray of pageLayout.values()) {\n            const currentIndex = yArray.indexOf(currentPageNumber);\n            if (currentIndex === -1) {\n              continue;\n            }\n            const numPages = yArray.length;\n            if (numPages === 1) {\n              break;\n            }\n            if (previous) {\n              for (let i = currentIndex - 1, ii = 0; i >= ii; i--) {\n                const currentId = yArray[i],\n                  expectedId = yArray[i + 1] - 1;\n                if (currentId < expectedId) {\n                  return currentPageNumber - expectedId;\n                }\n              }\n            } else {\n              for (let i = currentIndex + 1, ii = numPages; i < ii; i++) {\n                const currentId = yArray[i],\n                  expectedId = yArray[i - 1] + 1;\n                if (currentId > expectedId) {\n                  return expectedId - currentPageNumber;\n                }\n              }\n            }\n            if (previous) {\n              const firstId = yArray[0];\n              if (firstId < currentPageNumber) {\n                return currentPageNumber - firstId + 1;\n              }\n            } else {\n              const lastId = yArray[numPages - 1];\n              if (lastId > currentPageNumber) {\n                return lastId - currentPageNumber + 1;\n              }\n            }\n            break;\n          }\n          break;\n        }\n      case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.HORIZONTAL:\n        {\n          break;\n        }\n      case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.PAGE:\n      case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.VERTICAL:\n        {\n          if (this._spreadMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.SpreadMode.NONE) {\n            break;\n          }\n          const parity = this._spreadMode - 1;\n          if (previous && currentPageNumber % 2 !== parity) {\n            break;\n          } else if (!previous && currentPageNumber % 2 === parity) {\n            break;\n          }\n          const {\n              views\n            } = this._getVisiblePages(),\n            expectedId = previous ? currentPageNumber - 1 : currentPageNumber + 1;\n          for (const {\n            id,\n            percent,\n            widthPercent\n          } of views) {\n            if (id !== expectedId) {\n              continue;\n            }\n            if (percent > 0 && widthPercent === 100) {\n              return 2;\n            }\n            break;\n          }\n          break;\n        }\n    }\n    return 1;\n  }\n  nextPage() {\n    const currentPageNumber = this._currentPageNumber,\n      pagesCount = this.pagesCount;\n    if (currentPageNumber >= pagesCount) {\n      return false;\n    }\n    const advance = this._getPageAdvance(currentPageNumber, false) || 1;\n    this.currentPageNumber = Math.min(currentPageNumber + advance, pagesCount);\n    return true;\n  }\n  previousPage() {\n    const currentPageNumber = this._currentPageNumber;\n    if (currentPageNumber <= 1) {\n      return false;\n    }\n    const advance = this._getPageAdvance(currentPageNumber, true) || 1;\n    this.currentPageNumber = Math.max(currentPageNumber - advance, 1);\n    return true;\n  }\n  increaseScale({\n    drawingDelay,\n    scaleFactor,\n    steps\n  } = {}) {\n    if (!this.pdfDocument) {\n      return;\n    }\n    let newScale = this._currentScale;\n    if (scaleFactor > 1) {\n      newScale = Math.round(newScale * scaleFactor * 100) / 100;\n    } else {\n      steps ??= 1;\n      do {\n        newScale = Math.ceil((newScale * _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.DEFAULT_SCALE_DELTA).toFixed(2) * 10) / 10;\n      } while (--steps > 0 && newScale < _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.MAX_SCALE);\n    }\n    this.#setScale(Math.min(_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.MAX_SCALE, newScale), {\n      noScroll: false,\n      drawingDelay\n    });\n  }\n  decreaseScale({\n    drawingDelay,\n    scaleFactor,\n    steps\n  } = {}) {\n    if (!this.pdfDocument) {\n      return;\n    }\n    let newScale = this._currentScale;\n    if (scaleFactor > 0 && scaleFactor < 1) {\n      newScale = Math.round(newScale * scaleFactor * 100) / 100;\n    } else {\n      steps ??= 1;\n      do {\n        newScale = Math.floor((newScale / _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.DEFAULT_SCALE_DELTA).toFixed(2) * 10) / 10;\n      } while (--steps > 0 && newScale > _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.MIN_SCALE);\n    }\n    this.#setScale(Math.max(_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.MIN_SCALE, newScale), {\n      noScroll: false,\n      drawingDelay\n    });\n  }\n  #updateContainerHeightCss(height = this.container.clientHeight) {\n    if (height !== this.#previousContainerHeight) {\n      this.#previousContainerHeight = height;\n      _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.docStyle.setProperty(\"--viewer-container-height\", `${height}px`);\n    }\n  }\n  #resizeObserverCallback(entries) {\n    for (const entry of entries) {\n      if (entry.target === this.container) {\n        this.#updateContainerHeightCss(Math.floor(entry.borderBoxSize[0].blockSize));\n        this.#containerTopLeft = null;\n        break;\n      }\n    }\n  }\n  get containerTopLeft() {\n    return this.#containerTopLeft ||= [this.container.offsetTop, this.container.offsetLeft];\n  }\n  get annotationEditorMode() {\n    return this.#annotationEditorUIManager ? this.#annotationEditorMode : pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.DISABLE;\n  }\n  set annotationEditorMode({\n    mode,\n    editId = null,\n    isFromKeyboard = false\n  }) {\n    if (!this.#annotationEditorUIManager) {\n      throw new Error(`The AnnotationEditor is not enabled.`);\n    }\n    if (this.#annotationEditorMode === mode) {\n      return;\n    }\n    if (!isValidAnnotationEditorMode(mode)) {\n      throw new Error(`Invalid AnnotationEditor mode: ${mode}`);\n    }\n    if (!this.pdfDocument) {\n      return;\n    }\n    this.#annotationEditorMode = mode;\n    this.eventBus.dispatch(\"annotationeditormodechanged\", {\n      source: this,\n      mode\n    });\n    this.#annotationEditorUIManager.updateMode(mode, editId, isFromKeyboard);\n  }\n  set annotationEditorParams({\n    type,\n    value\n  }) {\n    if (!this.#annotationEditorUIManager) {\n      throw new Error(`The AnnotationEditor is not enabled.`);\n    }\n    this.#annotationEditorUIManager.updateParams(type, value);\n  }\n  refresh(noUpdate = false, updateArgs = Object.create(null)) {\n    if (!this.pdfDocument) {\n      return;\n    }\n    for (const pageView of this._pages) {\n      pageView.update(updateArgs);\n    }\n    if (this.#scaleTimeoutId !== null) {\n      clearTimeout(this.#scaleTimeoutId);\n      this.#scaleTimeoutId = null;\n    }\n    if (!noUpdate) {\n      this.update();\n    }\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 2603:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   AbortException: () => (/* binding */ AbortException),\n/* harmony export */   AnnotationEditorLayer: () => (/* binding */ AnnotationEditorLayer),\n/* harmony export */   AnnotationEditorParamsType: () => (/* binding */ AnnotationEditorParamsType),\n/* harmony export */   AnnotationEditorType: () => (/* binding */ AnnotationEditorType),\n/* harmony export */   AnnotationEditorUIManager: () => (/* binding */ AnnotationEditorUIManager),\n/* harmony export */   AnnotationLayer: () => (/* binding */ AnnotationLayer),\n/* harmony export */   AnnotationMode: () => (/* binding */ AnnotationMode),\n/* harmony export */   ColorPicker: () => (/* binding */ ColorPicker),\n/* harmony export */   DOMSVGFactory: () => (/* binding */ DOMSVGFactory),\n/* harmony export */   DrawLayer: () => (/* binding */ DrawLayer),\n/* harmony export */   GlobalWorkerOptions: () => (/* binding */ GlobalWorkerOptions),\n/* harmony export */   InvalidPDFException: () => (/* binding */ InvalidPDFException),\n/* harmony export */   MissingPDFException: () => (/* binding */ MissingPDFException),\n/* harmony export */   PDFDateString: () => (/* binding */ PDFDateString),\n/* harmony export */   PDFWorker: () => (/* binding */ PDFWorker),\n/* harmony export */   PasswordResponses: () => (/* binding */ PasswordResponses),\n/* harmony export */   PermissionFlag: () => (/* binding */ PermissionFlag),\n/* harmony export */   PixelsPerInch: () => (/* binding */ PixelsPerInch),\n/* harmony export */   RenderingCancelledException: () => (/* binding */ RenderingCancelledException),\n/* harmony export */   UnexpectedResponseException: () => (/* binding */ UnexpectedResponseException),\n/* harmony export */   XfaLayer: () => (/* binding */ XfaLayer),\n/* harmony export */   build: () => (/* binding */ build),\n/* harmony export */   createValidAbsoluteUrl: () => (/* binding */ createValidAbsoluteUrl),\n/* harmony export */   fetchData: () => (/* binding */ fetchData),\n/* harmony export */   getDocument: () => (/* binding */ getDocument),\n/* harmony export */   getFilenameFromUrl: () => (/* binding */ getFilenameFromUrl),\n/* harmony export */   getPdfFilenameFromUrl: () => (/* binding */ getPdfFilenameFromUrl),\n/* harmony export */   getXfaPageViewport: () => (/* binding */ getXfaPageViewport),\n/* harmony export */   isDataScheme: () => (/* binding */ isDataScheme),\n/* harmony export */   isPdfFile: () => (/* binding */ isPdfFile),\n/* harmony export */   noContextMenu: () => (/* binding */ noContextMenu),\n/* harmony export */   normalizeUnicode: () => (/* binding */ normalizeUnicode),\n/* harmony export */   renderTextLayer: () => (/* binding */ renderTextLayer),\n/* harmony export */   setLayerDimensions: () => (/* binding */ setLayerDimensions),\n/* harmony export */   shadow: () => (/* binding */ shadow),\n/* harmony export */   updateTextLayer: () => (/* binding */ updateTextLayer),\n/* harmony export */   version: () => (/* binding */ version)\n/* harmony export */ });\n/* unused harmony exports CMapCompressionType, FeatureTest, ImageKind, OPS, Outliner, PDFDataRangeTransport, Util, VerbosityLevel */\nif (!globalThis.pdfjsLib) {\n  await globalThis.pdfjsLibPromise;\n}\nconst {\n  AbortException,\n  AnnotationEditorLayer,\n  AnnotationEditorParamsType,\n  AnnotationEditorType,\n  AnnotationEditorUIManager,\n  AnnotationLayer,\n  AnnotationMode,\n  build,\n  CMapCompressionType,\n  ColorPicker,\n  createValidAbsoluteUrl,\n  DOMSVGFactory,\n  DrawLayer,\n  FeatureTest,\n  fetchData,\n  getDocument,\n  getFilenameFromUrl,\n  getPdfFilenameFromUrl,\n  getXfaPageViewport,\n  GlobalWorkerOptions,\n  ImageKind,\n  InvalidPDFException,\n  isDataScheme,\n  isPdfFile,\n  MissingPDFException,\n  noContextMenu,\n  normalizeUnicode,\n  OPS,\n  Outliner,\n  PasswordResponses,\n  PDFDataRangeTransport,\n  PDFDateString,\n  PDFWorker,\n  PermissionFlag,\n  PixelsPerInch,\n  RenderingCancelledException,\n  renderTextLayer,\n  setLayerDimensions,\n  shadow,\n  UnexpectedResponseException,\n  updateTextLayer,\n  Util,\n  VerbosityLevel,\n  version,\n  XfaLayer\n} = globalThis.pdfjsLib;\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } }, 1);\n\n/***/ }),\n\n/***/ 8224:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   BasePreferences: () => (/* binding */ BasePreferences)\n/* harmony export */ });\n/* harmony import */ var _app_options_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9840);\n\nclass BasePreferences {\n  #browserDefaults = Object.freeze({\n    canvasMaxAreaInBytes: -1,\n    isInAutomation: false,\n    supportsCaretBrowsingMode: false,\n    supportsDocumentFonts: true,\n    supportsIntegratedFind: false,\n    supportsMouseWheelZoomCtrlKey: true,\n    supportsMouseWheelZoomMetaKey: true,\n    supportsPinchToZoom: true\n  });\n  #defaults = Object.freeze({\n    annotationEditorMode: 0,\n    annotationMode: 2,\n    cursorToolOnLoad: 0,\n    defaultZoomDelay: 400,\n    defaultZoomValue: \"\",\n    disablePageLabels: false,\n    enableHighlightEditor: false,\n    enableHighlightFloatingButton: false,\n    enableML: false,\n    enablePermissions: false,\n    enablePrintAutoRotate: true,\n    enableScripting: true,\n    enableStampEditor: true,\n    externalLinkTarget: 0,\n    highlightEditorColors: \"yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F\",\n    historyUpdateUrl: false,\n    ignoreDestinationZoom: false,\n    forcePageColors: false,\n    pageColorsBackground: \"Canvas\",\n    pageColorsForeground: \"CanvasText\",\n    pdfBugEnabled: false,\n    sidebarViewOnLoad: -1,\n    scrollModeOnLoad: -1,\n    spreadModeOnLoad: -1,\n    textLayerMode: 1,\n    viewOnLoad: 0,\n    disableAutoFetch: false,\n    disableFontFace: false,\n    disableRange: false,\n    disableStream: false,\n    enableXfa: true,\n    viewerCssTheme: 0\n  });\n  #prefs = Object.create(null);\n  #initializedPromise = null;\n  constructor() {\n    if (this.constructor === BasePreferences) {\n      throw new Error(\"Cannot initialize BasePreferences.\");\n    }\n    this.#initializedPromise = this._readFromStorage(this.#defaults).then(({\n      browserPrefs,\n      prefs\n    }) => {\n      const options = Object.create(null);\n      for (const [name, val] of Object.entries(this.#browserDefaults)) {\n        const prefVal = browserPrefs?.[name];\n        options[name] = typeof prefVal === typeof val ? prefVal : val;\n      }\n      for (const [name, val] of Object.entries(this.#defaults)) {\n        const prefVal = prefs?.[name];\n        options[name] = this.#prefs[name] = typeof prefVal === typeof val ? prefVal : val;\n      }\n      _app_options_js__WEBPACK_IMPORTED_MODULE_0__.AppOptions.setAll(options, true);\n    });\n  }\n  async _writeToStorage(prefObj) {\n    throw new Error(\"Not implemented: _writeToStorage\");\n  }\n  async _readFromStorage(prefObj) {\n    throw new Error(\"Not implemented: _readFromStorage\");\n  }\n  #updatePref({\n    name,\n    value\n  }) {\n    throw new Error(\"Not implemented: #updatePref\");\n  }\n  async reset() {\n    await this.#initializedPromise;\n    const oldPrefs = structuredClone(this.#prefs);\n    this.#prefs = Object.create(null);\n    try {\n      await this._writeToStorage(this.#defaults);\n    } catch (reason) {\n      this.#prefs = oldPrefs;\n      throw reason;\n    }\n  }\n  async set(name, value) {\n    await this.#initializedPromise;\n    const defaultValue = this.#defaults[name],\n      oldPrefs = structuredClone(this.#prefs);\n    if (defaultValue === undefined) {\n      throw new Error(`Set preference: \"${name}\" is undefined.`);\n    } else if (value === undefined) {\n      throw new Error(\"Set preference: no value is specified.\");\n    }\n    const valueType = typeof value,\n      defaultType = typeof defaultValue;\n    if (valueType !== defaultType) {\n      if (valueType === \"number\" && defaultType === \"string\") {\n        value = value.toString();\n      } else {\n        throw new Error(`Set preference: \"${value}\" is a ${valueType}, expected a ${defaultType}.`);\n      }\n    } else if (valueType === \"number\" && !Number.isInteger(value)) {\n      throw new Error(`Set preference: \"${value}\" must be an integer.`);\n    }\n    this.#prefs[name] = value;\n    try {\n      await this._writeToStorage(this.#prefs);\n    } catch (reason) {\n      this.#prefs = oldPrefs;\n      throw reason;\n    }\n  }\n  async get(name) {\n    await this.#initializedPromise;\n    const defaultValue = this.#defaults[name];\n    if (defaultValue === undefined) {\n      throw new Error(`Get preference: \"${name}\" is undefined.`);\n    }\n    return this.#prefs[name] ?? defaultValue;\n  }\n  get initializedPromise() {\n    return this.#initializedPromise;\n  }\n}\n\n\n/***/ }),\n\n/***/ 659:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   getXfaHtmlForPrinting: () => (/* binding */ getXfaHtmlForPrinting)\n/* harmony export */ });\n/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603);\n/* harmony import */ var _pdf_link_service_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(787);\n/* harmony import */ var _xfa_layer_builder_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2973);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__, _xfa_layer_builder_js__WEBPACK_IMPORTED_MODULE_2__]);\n([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__, _xfa_layer_builder_js__WEBPACK_IMPORTED_MODULE_2__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__);\n\n\n\nfunction getXfaHtmlForPrinting(printContainer, pdfDocument) {\n  const xfaHtml = pdfDocument.allXfaHtml;\n  const linkService = new _pdf_link_service_js__WEBPACK_IMPORTED_MODULE_1__.SimpleLinkService();\n  const scale = Math.round(pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PixelsPerInch.PDF_TO_CSS_UNITS * 100) / 100;\n  for (const xfaPage of xfaHtml.children) {\n    const page = document.createElement(\"div\");\n    page.className = \"xfaPrintedPage\";\n    printContainer.append(page);\n    const builder = new _xfa_layer_builder_js__WEBPACK_IMPORTED_MODULE_2__.XfaLayerBuilder({\n      pdfPage: null,\n      annotationStorage: pdfDocument.annotationStorage,\n      linkService,\n      xfaHtml: xfaPage\n    });\n    const viewport = (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.getXfaPageViewport)(xfaPage, {\n      scale\n    });\n    builder.render(viewport, \"print\");\n    page.append(builder.div);\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 1900:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   SecondaryToolbar: () => (/* binding */ SecondaryToolbar)\n/* harmony export */ });\n/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256);\n/* harmony import */ var _pdf_viewer_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6285);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([_pdf_viewer_js__WEBPACK_IMPORTED_MODULE_1__]);\n_pdf_viewer_js__WEBPACK_IMPORTED_MODULE_1__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];\n\n\nclass SecondaryToolbar {\n  #opts;\n  constructor(options, eventBus) {\n    this.#opts = options;\n    const buttons = [{\n      element: options.presentationModeButton,\n      eventName: \"presentationmode\",\n      close: true\n    }, {\n      element: options.printButton,\n      eventName: \"print\",\n      close: true\n    }, {\n      element: options.downloadButton,\n      eventName: \"download\",\n      close: true\n    }, {\n      element: options.viewBookmarkButton,\n      eventName: null,\n      close: true\n    }, {\n      element: options.firstPageButton,\n      eventName: \"firstpage\",\n      close: true\n    }, {\n      element: options.lastPageButton,\n      eventName: \"lastpage\",\n      close: true\n    }, {\n      element: options.pageRotateCwButton,\n      eventName: \"rotatecw\",\n      close: false\n    }, {\n      element: options.pageRotateCcwButton,\n      eventName: \"rotateccw\",\n      close: false\n    }, {\n      element: options.cursorSelectToolButton,\n      eventName: \"switchcursortool\",\n      eventDetails: {\n        tool: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.CursorTool.SELECT\n      },\n      close: true\n    }, {\n      element: options.cursorHandToolButton,\n      eventName: \"switchcursortool\",\n      eventDetails: {\n        tool: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.CursorTool.HAND\n      },\n      close: true\n    }, {\n      element: options.scrollPageButton,\n      eventName: \"switchscrollmode\",\n      eventDetails: {\n        mode: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.PAGE\n      },\n      close: true\n    }, {\n      element: options.scrollVerticalButton,\n      eventName: \"switchscrollmode\",\n      eventDetails: {\n        mode: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.VERTICAL\n      },\n      close: true\n    }, {\n      element: options.scrollHorizontalButton,\n      eventName: \"switchscrollmode\",\n      eventDetails: {\n        mode: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.HORIZONTAL\n      },\n      close: true\n    }, {\n      element: options.scrollWrappedButton,\n      eventName: \"switchscrollmode\",\n      eventDetails: {\n        mode: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.WRAPPED\n      },\n      close: true\n    }, {\n      element: options.spreadNoneButton,\n      eventName: \"switchspreadmode\",\n      eventDetails: {\n        mode: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SpreadMode.NONE\n      },\n      close: true\n    }, {\n      element: options.spreadOddButton,\n      eventName: \"switchspreadmode\",\n      eventDetails: {\n        mode: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SpreadMode.ODD\n      },\n      close: true\n    }, {\n      element: options.spreadEvenButton,\n      eventName: \"switchspreadmode\",\n      eventDetails: {\n        mode: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SpreadMode.EVEN\n      },\n      close: true\n    }, {\n      element: options.documentPropertiesButton,\n      eventName: \"documentproperties\",\n      close: true\n    }];\n    buttons.push({\n      element: options.openFileButton,\n      eventName: \"openfile\",\n      close: true\n    });\n    this.eventBus = eventBus;\n    this.opened = false;\n    this.#bindListeners(buttons);\n    this.reset();\n  }\n  get isOpen() {\n    return this.opened;\n  }\n  setPageNumber(pageNumber) {\n    this.pageNumber = pageNumber;\n    this.#updateUIState();\n  }\n  setPagesCount(pagesCount) {\n    this.pagesCount = pagesCount;\n    this.#updateUIState();\n  }\n  reset() {\n    this.pageNumber = 0;\n    this.pagesCount = 0;\n    this.#updateUIState();\n    this.eventBus.dispatch(\"switchcursortool\", {\n      source: this,\n      reset: true\n    });\n    this.#scrollModeChanged({\n      mode: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.VERTICAL\n    });\n    this.#spreadModeChanged({\n      mode: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SpreadMode.NONE\n    });\n  }\n  #updateUIState() {\n    const {\n      firstPageButton,\n      lastPageButton,\n      pageRotateCwButton,\n      pageRotateCcwButton\n    } = this.#opts;\n    firstPageButton.disabled = this.pageNumber <= 1;\n    lastPageButton.disabled = this.pageNumber >= this.pagesCount;\n    pageRotateCwButton.disabled = this.pagesCount === 0;\n    pageRotateCcwButton.disabled = this.pagesCount === 0;\n  }\n  #bindListeners(buttons) {\n    const {\n      eventBus\n    } = this;\n    const {\n      toggleButton\n    } = this.#opts;\n    toggleButton.addEventListener(\"click\", this.toggle.bind(this));\n    for (const {\n      element,\n      eventName,\n      close,\n      eventDetails\n    } of buttons) {\n      element.addEventListener(\"click\", evt => {\n        if (eventName !== null) {\n          eventBus.dispatch(eventName, {\n            source: this,\n            ...eventDetails\n          });\n        }\n        if (close) {\n          this.close();\n        }\n        eventBus.dispatch(\"reporttelemetry\", {\n          source: this,\n          details: {\n            type: \"buttons\",\n            data: {\n              id: element.id\n            }\n          }\n        });\n      });\n    }\n    eventBus._on(\"cursortoolchanged\", this.#cursorToolChanged.bind(this));\n    eventBus._on(\"scrollmodechanged\", this.#scrollModeChanged.bind(this));\n    eventBus._on(\"spreadmodechanged\", this.#spreadModeChanged.bind(this));\n  }\n  #cursorToolChanged({\n    tool\n  }) {\n    const {\n      cursorSelectToolButton,\n      cursorHandToolButton\n    } = this.#opts;\n    (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleCheckedBtn)(cursorSelectToolButton, tool === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.CursorTool.SELECT);\n    (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleCheckedBtn)(cursorHandToolButton, tool === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.CursorTool.HAND);\n  }\n  #scrollModeChanged({\n    mode\n  }) {\n    const {\n      scrollPageButton,\n      scrollVerticalButton,\n      scrollHorizontalButton,\n      scrollWrappedButton,\n      spreadNoneButton,\n      spreadOddButton,\n      spreadEvenButton\n    } = this.#opts;\n    (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleCheckedBtn)(scrollPageButton, mode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.PAGE);\n    (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleCheckedBtn)(scrollVerticalButton, mode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.VERTICAL);\n    (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleCheckedBtn)(scrollHorizontalButton, mode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.HORIZONTAL);\n    (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleCheckedBtn)(scrollWrappedButton, mode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.WRAPPED);\n    const forceScrollModePage = this.pagesCount > _pdf_viewer_js__WEBPACK_IMPORTED_MODULE_1__.PagesCountLimit.FORCE_SCROLL_MODE_PAGE;\n    scrollPageButton.disabled = forceScrollModePage;\n    scrollVerticalButton.disabled = forceScrollModePage;\n    scrollHorizontalButton.disabled = forceScrollModePage;\n    scrollWrappedButton.disabled = forceScrollModePage;\n    const isHorizontal = mode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.HORIZONTAL;\n    spreadNoneButton.disabled = isHorizontal;\n    spreadOddButton.disabled = isHorizontal;\n    spreadEvenButton.disabled = isHorizontal;\n  }\n  #spreadModeChanged({\n    mode\n  }) {\n    const {\n      spreadNoneButton,\n      spreadOddButton,\n      spreadEvenButton\n    } = this.#opts;\n    (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleCheckedBtn)(spreadNoneButton, mode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SpreadMode.NONE);\n    (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleCheckedBtn)(spreadOddButton, mode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SpreadMode.ODD);\n    (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleCheckedBtn)(spreadEvenButton, mode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SpreadMode.EVEN);\n  }\n  open() {\n    if (this.opened) {\n      return;\n    }\n    this.opened = true;\n    const {\n      toggleButton,\n      toolbar\n    } = this.#opts;\n    (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleExpandedBtn)(toggleButton, true, toolbar);\n  }\n  close() {\n    if (!this.opened) {\n      return;\n    }\n    this.opened = false;\n    const {\n      toggleButton,\n      toolbar\n    } = this.#opts;\n    (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleExpandedBtn)(toggleButton, false, toolbar);\n  }\n  toggle() {\n    if (this.opened) {\n      this.close();\n    } else {\n      this.open();\n    }\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 6698:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   StructTreeLayerBuilder: () => (/* binding */ StructTreeLayerBuilder)\n/* harmony export */ });\n/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256);\n\nconst PDF_ROLE_TO_HTML_ROLE = {\n  Document: null,\n  DocumentFragment: null,\n  Part: \"group\",\n  Sect: \"group\",\n  Div: \"group\",\n  Aside: \"note\",\n  NonStruct: \"none\",\n  P: null,\n  H: \"heading\",\n  Title: null,\n  FENote: \"note\",\n  Sub: \"group\",\n  Lbl: null,\n  Span: null,\n  Em: null,\n  Strong: null,\n  Link: \"link\",\n  Annot: \"note\",\n  Form: \"form\",\n  Ruby: null,\n  RB: null,\n  RT: null,\n  RP: null,\n  Warichu: null,\n  WT: null,\n  WP: null,\n  L: \"list\",\n  LI: \"listitem\",\n  LBody: null,\n  Table: \"table\",\n  TR: \"row\",\n  TH: \"columnheader\",\n  TD: \"cell\",\n  THead: \"columnheader\",\n  TBody: null,\n  TFoot: null,\n  Caption: null,\n  Figure: \"figure\",\n  Formula: null,\n  Artifact: null\n};\nconst HEADING_PATTERN = /^H(\\d+)$/;\nclass StructTreeLayerBuilder {\n  #treeDom = undefined;\n  get renderingDone() {\n    return this.#treeDom !== undefined;\n  }\n  render(structTree) {\n    if (this.#treeDom !== undefined) {\n      return this.#treeDom;\n    }\n    const treeDom = this.#walk(structTree);\n    treeDom?.classList.add(\"structTree\");\n    return this.#treeDom = treeDom;\n  }\n  hide() {\n    if (this.#treeDom && !this.#treeDom.hidden) {\n      this.#treeDom.hidden = true;\n    }\n  }\n  show() {\n    if (this.#treeDom?.hidden) {\n      this.#treeDom.hidden = false;\n    }\n  }\n  #setAttributes(structElement, htmlElement) {\n    const {\n      alt,\n      id,\n      lang\n    } = structElement;\n    if (alt !== undefined) {\n      htmlElement.setAttribute(\"aria-label\", (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.removeNullCharacters)(alt));\n    }\n    if (id !== undefined) {\n      htmlElement.setAttribute(\"aria-owns\", id);\n    }\n    if (lang !== undefined) {\n      htmlElement.setAttribute(\"lang\", (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.removeNullCharacters)(lang, true));\n    }\n  }\n  #walk(node) {\n    if (!node) {\n      return null;\n    }\n    const element = document.createElement(\"span\");\n    if (\"role\" in node) {\n      const {\n        role\n      } = node;\n      const match = role.match(HEADING_PATTERN);\n      if (match) {\n        element.setAttribute(\"role\", \"heading\");\n        element.setAttribute(\"aria-level\", match[1]);\n      } else if (PDF_ROLE_TO_HTML_ROLE[role]) {\n        element.setAttribute(\"role\", PDF_ROLE_TO_HTML_ROLE[role]);\n      }\n    }\n    this.#setAttributes(node, element);\n    if (node.children) {\n      if (node.children.length === 1 && \"id\" in node.children[0]) {\n        this.#setAttributes(node.children[0], element);\n      } else {\n        for (const kid of node.children) {\n          element.append(this.#walk(kid));\n        }\n      }\n    }\n    return element;\n  }\n}\n\n\n/***/ }),\n\n/***/ 5860:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   TextAccessibilityManager: () => (/* binding */ TextAccessibilityManager)\n/* harmony export */ });\n/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256);\n\nclass TextAccessibilityManager {\n  #enabled = false;\n  #textChildren = null;\n  #textNodes = new Map();\n  #waitingElements = new Map();\n  setTextMapping(textDivs) {\n    this.#textChildren = textDivs;\n  }\n  static #compareElementPositions(e1, e2) {\n    const rect1 = e1.getBoundingClientRect();\n    const rect2 = e2.getBoundingClientRect();\n    if (rect1.width === 0 && rect1.height === 0) {\n      return +1;\n    }\n    if (rect2.width === 0 && rect2.height === 0) {\n      return -1;\n    }\n    const top1 = rect1.y;\n    const bot1 = rect1.y + rect1.height;\n    const mid1 = rect1.y + rect1.height / 2;\n    const top2 = rect2.y;\n    const bot2 = rect2.y + rect2.height;\n    const mid2 = rect2.y + rect2.height / 2;\n    if (mid1 <= top2 && mid2 >= bot1) {\n      return -1;\n    }\n    if (mid2 <= top1 && mid1 >= bot2) {\n      return +1;\n    }\n    const centerX1 = rect1.x + rect1.width / 2;\n    const centerX2 = rect2.x + rect2.width / 2;\n    return centerX1 - centerX2;\n  }\n  enable() {\n    if (this.#enabled) {\n      throw new Error(\"TextAccessibilityManager is already enabled.\");\n    }\n    if (!this.#textChildren) {\n      throw new Error(\"Text divs and strings have not been set.\");\n    }\n    this.#enabled = true;\n    this.#textChildren = this.#textChildren.slice();\n    this.#textChildren.sort(TextAccessibilityManager.#compareElementPositions);\n    if (this.#textNodes.size > 0) {\n      const textChildren = this.#textChildren;\n      for (const [id, nodeIndex] of this.#textNodes) {\n        const element = document.getElementById(id);\n        if (!element) {\n          this.#textNodes.delete(id);\n          continue;\n        }\n        this.#addIdToAriaOwns(id, textChildren[nodeIndex]);\n      }\n    }\n    for (const [element, isRemovable] of this.#waitingElements) {\n      this.addPointerInTextLayer(element, isRemovable);\n    }\n    this.#waitingElements.clear();\n  }\n  disable() {\n    if (!this.#enabled) {\n      return;\n    }\n    this.#waitingElements.clear();\n    this.#textChildren = null;\n    this.#enabled = false;\n  }\n  removePointerInTextLayer(element) {\n    if (!this.#enabled) {\n      this.#waitingElements.delete(element);\n      return;\n    }\n    const children = this.#textChildren;\n    if (!children || children.length === 0) {\n      return;\n    }\n    const {\n      id\n    } = element;\n    const nodeIndex = this.#textNodes.get(id);\n    if (nodeIndex === undefined) {\n      return;\n    }\n    const node = children[nodeIndex];\n    this.#textNodes.delete(id);\n    let owns = node.getAttribute(\"aria-owns\");\n    if (owns?.includes(id)) {\n      owns = owns.split(\" \").filter(x => x !== id).join(\" \");\n      if (owns) {\n        node.setAttribute(\"aria-owns\", owns);\n      } else {\n        node.removeAttribute(\"aria-owns\");\n        node.setAttribute(\"role\", \"presentation\");\n      }\n    }\n  }\n  #addIdToAriaOwns(id, node) {\n    const owns = node.getAttribute(\"aria-owns\");\n    if (!owns?.includes(id)) {\n      node.setAttribute(\"aria-owns\", owns ? `${owns} ${id}` : id);\n    }\n    node.removeAttribute(\"role\");\n  }\n  addPointerInTextLayer(element, isRemovable) {\n    const {\n      id\n    } = element;\n    if (!id) {\n      return null;\n    }\n    if (!this.#enabled) {\n      this.#waitingElements.set(element, isRemovable);\n      return null;\n    }\n    if (isRemovable) {\n      this.removePointerInTextLayer(element);\n    }\n    const children = this.#textChildren;\n    if (!children || children.length === 0) {\n      return null;\n    }\n    const index = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.binarySearchFirstItem)(children, node => TextAccessibilityManager.#compareElementPositions(element, node) < 0);\n    const nodeIndex = Math.max(0, index - 1);\n    const child = children[nodeIndex];\n    this.#addIdToAriaOwns(id, child);\n    this.#textNodes.set(id, nodeIndex);\n    const parent = child.parentNode;\n    return parent?.classList.contains(\"markedContent\") ? parent.id : null;\n  }\n  moveElementInDOM(container, element, contentElement, isRemovable) {\n    const id = this.addPointerInTextLayer(contentElement, isRemovable);\n    if (!container.hasChildNodes()) {\n      container.append(element);\n      return id;\n    }\n    const children = Array.from(container.childNodes).filter(node => node !== element);\n    if (children.length === 0) {\n      return id;\n    }\n    const elementToCompare = contentElement || element;\n    const index = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.binarySearchFirstItem)(children, node => TextAccessibilityManager.#compareElementPositions(elementToCompare, node) < 0);\n    if (index === 0) {\n      children[0].before(element);\n    } else {\n      children[index - 1].after(element);\n    }\n    return id;\n  }\n}\n\n\n/***/ }),\n\n/***/ 2027:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   TextHighlighter: () => (/* binding */ TextHighlighter)\n/* harmony export */ });\nclass TextHighlighter {\n  #eventAbortController = null;\n  constructor({\n    findController,\n    eventBus,\n    pageIndex\n  }) {\n    this.findController = findController;\n    this.matches = [];\n    this.eventBus = eventBus;\n    this.pageIdx = pageIndex;\n    this.textDivs = null;\n    this.textContentItemsStr = null;\n    this.enabled = false;\n  }\n  setTextMapping(divs, texts) {\n    this.textDivs = divs;\n    this.textContentItemsStr = texts;\n  }\n  enable() {\n    if (!this.textDivs || !this.textContentItemsStr) {\n      throw new Error(\"Text divs and strings have not been set.\");\n    }\n    if (this.enabled) {\n      throw new Error(\"TextHighlighter is already enabled.\");\n    }\n    this.enabled = true;\n    if (!this.#eventAbortController) {\n      this.#eventAbortController = new AbortController();\n      this.eventBus._on(\"updatetextlayermatches\", evt => {\n        if (evt.pageIndex === this.pageIdx || evt.pageIndex === -1) {\n          this._updateMatches();\n        }\n      }, {\n        signal: this.#eventAbortController.signal\n      });\n    }\n    this._updateMatches();\n  }\n  disable() {\n    if (!this.enabled) {\n      return;\n    }\n    this.enabled = false;\n    this.#eventAbortController?.abort();\n    this.#eventAbortController = null;\n    this._updateMatches(true);\n  }\n  _convertMatches(matches, matchesLength) {\n    if (!matches) {\n      return [];\n    }\n    const {\n      textContentItemsStr\n    } = this;\n    let i = 0,\n      iIndex = 0;\n    const end = textContentItemsStr.length - 1;\n    const result = [];\n    for (let m = 0, mm = matches.length; m < mm; m++) {\n      let matchIdx = matches[m];\n      while (i !== end && matchIdx >= iIndex + textContentItemsStr[i].length) {\n        iIndex += textContentItemsStr[i].length;\n        i++;\n      }\n      if (i === textContentItemsStr.length) {\n        console.error(\"Could not find a matching mapping\");\n      }\n      const match = {\n        begin: {\n          divIdx: i,\n          offset: matchIdx - iIndex\n        }\n      };\n      matchIdx += matchesLength[m];\n      while (i !== end && matchIdx > iIndex + textContentItemsStr[i].length) {\n        iIndex += textContentItemsStr[i].length;\n        i++;\n      }\n      match.end = {\n        divIdx: i,\n        offset: matchIdx - iIndex\n      };\n      result.push(match);\n    }\n    return result;\n  }\n  _renderMatches(matches) {\n    if (matches.length === 0) {\n      return;\n    }\n    const {\n      findController,\n      pageIdx\n    } = this;\n    const {\n      textContentItemsStr,\n      textDivs\n    } = this;\n    const isSelectedPage = pageIdx === findController.selected.pageIdx;\n    const selectedMatchIdx = findController.selected.matchIdx;\n    const highlightAll = findController.state.highlightAll;\n    let prevEnd = null;\n    const infinity = {\n      divIdx: -1,\n      offset: undefined\n    };\n    function beginText(begin, className) {\n      const divIdx = begin.divIdx;\n      textDivs[divIdx].textContent = \"\";\n      return appendTextToDiv(divIdx, 0, begin.offset, className);\n    }\n    function appendTextToDiv(divIdx, fromOffset, toOffset, className) {\n      let div = textDivs[divIdx];\n      if (div.nodeType === Node.TEXT_NODE) {\n        const span = document.createElement(\"span\");\n        div.before(span);\n        span.append(div);\n        textDivs[divIdx] = span;\n        div = span;\n      }\n      const content = textContentItemsStr[divIdx].substring(fromOffset, toOffset);\n      const node = document.createTextNode(content);\n      if (className) {\n        const span = document.createElement(\"span\");\n        span.className = `${className} appended`;\n        span.append(node);\n        div.append(span);\n        return className.includes(\"selected\") ? span.offsetLeft : 0;\n      }\n      div.append(node);\n      return 0;\n    }\n    let i0 = selectedMatchIdx,\n      i1 = i0 + 1;\n    if (highlightAll) {\n      i0 = 0;\n      i1 = matches.length;\n    } else if (!isSelectedPage) {\n      return;\n    }\n    let lastDivIdx = -1;\n    let lastOffset = -1;\n    for (let i = i0; i < i1; i++) {\n      const match = matches[i];\n      const begin = match.begin;\n      if (begin.divIdx === lastDivIdx && begin.offset === lastOffset) {\n        continue;\n      }\n      lastDivIdx = begin.divIdx;\n      lastOffset = begin.offset;\n      const end = match.end;\n      const isSelected = isSelectedPage && i === selectedMatchIdx;\n      const highlightSuffix = isSelected ? \" selected\" : \"\";\n      let selectedLeft = 0;\n      if (!prevEnd || begin.divIdx !== prevEnd.divIdx) {\n        if (prevEnd !== null) {\n          appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset);\n        }\n        beginText(begin);\n      } else {\n        appendTextToDiv(prevEnd.divIdx, prevEnd.offset, begin.offset);\n      }\n      if (begin.divIdx === end.divIdx) {\n        selectedLeft = appendTextToDiv(begin.divIdx, begin.offset, end.offset, \"highlight\" + highlightSuffix);\n      } else {\n        selectedLeft = appendTextToDiv(begin.divIdx, begin.offset, infinity.offset, \"highlight begin\" + highlightSuffix);\n        for (let n0 = begin.divIdx + 1, n1 = end.divIdx; n0 < n1; n0++) {\n          textDivs[n0].className = \"highlight middle\" + highlightSuffix;\n        }\n        beginText(end, \"highlight end\" + highlightSuffix);\n      }\n      prevEnd = end;\n      if (isSelected) {\n        findController.scrollMatchIntoView({\n          element: textDivs[begin.divIdx],\n          selectedLeft,\n          pageIndex: pageIdx,\n          matchIndex: selectedMatchIdx\n        });\n      }\n    }\n    if (prevEnd) {\n      appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset);\n    }\n  }\n  _updateMatches(reset = false) {\n    if (!this.enabled && !reset) {\n      return;\n    }\n    const {\n      findController,\n      matches,\n      pageIdx\n    } = this;\n    const {\n      textContentItemsStr,\n      textDivs\n    } = this;\n    let clearedUntilDivIdx = -1;\n    for (const match of matches) {\n      const begin = Math.max(clearedUntilDivIdx, match.begin.divIdx);\n      for (let n = begin, end = match.end.divIdx; n <= end; n++) {\n        const div = textDivs[n];\n        div.textContent = textContentItemsStr[n];\n        div.className = \"\";\n      }\n      clearedUntilDivIdx = match.end.divIdx + 1;\n    }\n    if (!findController?.highlightMatches || reset) {\n      return;\n    }\n    const pageMatches = findController.pageMatches[pageIdx] || null;\n    const pageMatchesLength = findController.pageMatchesLength[pageIdx] || null;\n    this.matches = this._convertMatches(pageMatches, pageMatchesLength);\n    this._renderMatches(this.matches);\n  }\n}\n\n\n/***/ }),\n\n/***/ 7765:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   TextLayerBuilder: () => (/* binding */ TextLayerBuilder)\n/* harmony export */ });\n/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603);\n/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7256);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__]);\npdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];\n\n\nclass TextLayerBuilder {\n  #enablePermissions = false;\n  #onAppend = null;\n  #rotation = 0;\n  #scale = 0;\n  #textContentSource = null;\n  constructor({\n    highlighter = null,\n    accessibilityManager = null,\n    enablePermissions = false,\n    onAppend = null\n  }) {\n    this.textContentItemsStr = [];\n    this.renderingDone = false;\n    this.textDivs = [];\n    this.textDivProperties = new WeakMap();\n    this.textLayerRenderTask = null;\n    this.highlighter = highlighter;\n    this.accessibilityManager = accessibilityManager;\n    this.#enablePermissions = enablePermissions === true;\n    this.#onAppend = onAppend;\n    this.div = document.createElement(\"div\");\n    this.div.tabIndex = 0;\n    this.div.className = \"textLayer\";\n  }\n  #finishRendering() {\n    this.renderingDone = true;\n    const endOfContent = document.createElement(\"div\");\n    endOfContent.className = \"endOfContent\";\n    this.div.append(endOfContent);\n    this.#bindMouse();\n  }\n  get numTextDivs() {\n    return this.textDivs.length;\n  }\n  async render(viewport) {\n    if (!this.#textContentSource) {\n      throw new Error('No \"textContentSource\" parameter specified.');\n    }\n    const scale = viewport.scale * (globalThis.devicePixelRatio || 1);\n    const {\n      rotation\n    } = viewport;\n    if (this.renderingDone) {\n      const mustRotate = rotation !== this.#rotation;\n      const mustRescale = scale !== this.#scale;\n      if (mustRotate || mustRescale) {\n        this.hide();\n        (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.updateTextLayer)({\n          container: this.div,\n          viewport,\n          textDivs: this.textDivs,\n          textDivProperties: this.textDivProperties,\n          mustRescale,\n          mustRotate\n        });\n        this.#scale = scale;\n        this.#rotation = rotation;\n      }\n      this.show();\n      return;\n    }\n    this.cancel();\n    this.highlighter?.setTextMapping(this.textDivs, this.textContentItemsStr);\n    this.accessibilityManager?.setTextMapping(this.textDivs);\n    this.textLayerRenderTask = (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.renderTextLayer)({\n      textContentSource: this.#textContentSource,\n      container: this.div,\n      viewport,\n      textDivs: this.textDivs,\n      textDivProperties: this.textDivProperties,\n      textContentItemsStr: this.textContentItemsStr\n    });\n    await this.textLayerRenderTask.promise;\n    this.#finishRendering();\n    this.#scale = scale;\n    this.#rotation = rotation;\n    this.#onAppend?.(this.div);\n    this.highlighter?.enable();\n    this.accessibilityManager?.enable();\n  }\n  hide() {\n    if (!this.div.hidden && this.renderingDone) {\n      this.highlighter?.disable();\n      this.div.hidden = true;\n    }\n  }\n  show() {\n    if (this.div.hidden && this.renderingDone) {\n      this.div.hidden = false;\n      this.highlighter?.enable();\n    }\n  }\n  cancel() {\n    if (this.textLayerRenderTask) {\n      this.textLayerRenderTask.cancel();\n      this.textLayerRenderTask = null;\n    }\n    this.highlighter?.disable();\n    this.accessibilityManager?.disable();\n    this.textContentItemsStr.length = 0;\n    this.textDivs.length = 0;\n    this.textDivProperties = new WeakMap();\n  }\n  setTextContentSource(source) {\n    this.cancel();\n    this.#textContentSource = source;\n  }\n  #bindMouse() {\n    const {\n      div\n    } = this;\n    div.addEventListener(\"mousedown\", evt => {\n      const end = div.querySelector(\".endOfContent\");\n      if (!end) {\n        return;\n      }\n      let adjustTop = evt.target !== div;\n      adjustTop &&= getComputedStyle(end).getPropertyValue(\"-moz-user-select\") !== \"none\";\n      if (adjustTop) {\n        const divBounds = div.getBoundingClientRect();\n        const r = Math.max(0, (evt.pageY - divBounds.top) / divBounds.height);\n        end.style.top = (r * 100).toFixed(2) + \"%\";\n      }\n      end.classList.add(\"active\");\n    });\n    div.addEventListener(\"mouseup\", () => {\n      const end = div.querySelector(\".endOfContent\");\n      if (!end) {\n        return;\n      }\n      end.style.top = \"\";\n      end.classList.remove(\"active\");\n    });\n    div.addEventListener(\"copy\", event => {\n      if (!this.#enablePermissions) {\n        const selection = document.getSelection();\n        event.clipboardData.setData(\"text/plain\", (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.removeNullCharacters)((0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.normalizeUnicode)(selection.toString())));\n      }\n      event.preventDefault();\n      event.stopPropagation();\n    });\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 6297:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   Toolbar: () => (/* binding */ Toolbar)\n/* harmony export */ });\n/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603);\n/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7256);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__]);\npdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];\n\n\nclass Toolbar {\n  #opts;\n  constructor(options, eventBus) {\n    this.#opts = options;\n    this.eventBus = eventBus;\n    const buttons = [{\n      element: options.previous,\n      eventName: \"previouspage\"\n    }, {\n      element: options.next,\n      eventName: \"nextpage\"\n    }, {\n      element: options.zoomIn,\n      eventName: \"zoomin\"\n    }, {\n      element: options.zoomOut,\n      eventName: \"zoomout\"\n    }, {\n      element: options.print,\n      eventName: \"print\"\n    }, {\n      element: options.download,\n      eventName: \"download\"\n    }, {\n      element: options.editorFreeTextButton,\n      eventName: \"switchannotationeditormode\",\n      eventDetails: {\n        get mode() {\n          const {\n            classList\n          } = options.editorFreeTextButton;\n          return classList.contains(\"toggled\") ? pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE : pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.FREETEXT;\n        }\n      }\n    }, {\n      element: options.editorHighlightButton,\n      eventName: \"switchannotationeditormode\",\n      eventDetails: {\n        get mode() {\n          const {\n            classList\n          } = options.editorHighlightButton;\n          return classList.contains(\"toggled\") ? pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE : pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.HIGHLIGHT;\n        }\n      }\n    }, {\n      element: options.editorInkButton,\n      eventName: \"switchannotationeditormode\",\n      eventDetails: {\n        get mode() {\n          const {\n            classList\n          } = options.editorInkButton;\n          return classList.contains(\"toggled\") ? pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE : pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.INK;\n        }\n      }\n    }, {\n      element: options.editorStampButton,\n      eventName: \"switchannotationeditormode\",\n      eventDetails: {\n        get mode() {\n          const {\n            classList\n          } = options.editorStampButton;\n          return classList.contains(\"toggled\") ? pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE : pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.STAMP;\n        }\n      }\n    }];\n    this.#bindListeners(buttons);\n    if (options.editorHighlightColorPicker) {\n      eventBus._on(\"annotationeditoruimanager\", ({\n        uiManager\n      }) => {\n        this.#setAnnotationEditorUIManager(uiManager, options.editorHighlightColorPicker);\n      }, {\n        once: true\n      });\n    }\n    eventBus._on(\"showannotationeditorui\", ({\n      mode\n    }) => {\n      switch (mode) {\n        case pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.HIGHLIGHT:\n          options.editorHighlightButton.click();\n          break;\n      }\n    });\n    this.reset();\n  }\n  #setAnnotationEditorUIManager(uiManager, parentContainer) {\n    const colorPicker = new pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.ColorPicker({\n      uiManager\n    });\n    uiManager.setMainHighlightColorPicker(colorPicker);\n    parentContainer.append(colorPicker.renderMainDropdown());\n  }\n  setPageNumber(pageNumber, pageLabel) {\n    this.pageNumber = pageNumber;\n    this.pageLabel = pageLabel;\n    this.#updateUIState(false);\n  }\n  setPagesCount(pagesCount, hasPageLabels) {\n    this.pagesCount = pagesCount;\n    this.hasPageLabels = hasPageLabels;\n    this.#updateUIState(true);\n  }\n  setPageScale(pageScaleValue, pageScale) {\n    this.pageScaleValue = (pageScaleValue || pageScale).toString();\n    this.pageScale = pageScale;\n    this.#updateUIState(false);\n  }\n  reset() {\n    this.pageNumber = 0;\n    this.pageLabel = null;\n    this.hasPageLabels = false;\n    this.pagesCount = 0;\n    this.pageScaleValue = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.DEFAULT_SCALE_VALUE;\n    this.pageScale = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.DEFAULT_SCALE;\n    this.#updateUIState(true);\n    this.updateLoadingIndicatorState();\n    this.#editorModeChanged({\n      mode: pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.DISABLE\n    });\n  }\n  #bindListeners(buttons) {\n    const {\n      eventBus\n    } = this;\n    const {\n      pageNumber,\n      scaleSelect\n    } = this.#opts;\n    const self = this;\n    for (const {\n      element,\n      eventName,\n      eventDetails\n    } of buttons) {\n      element.addEventListener(\"click\", evt => {\n        if (eventName !== null) {\n          eventBus.dispatch(eventName, {\n            source: this,\n            ...eventDetails,\n            isFromKeyboard: evt.detail === 0\n          });\n        }\n      });\n    }\n    pageNumber.addEventListener(\"click\", function () {\n      this.select();\n    });\n    pageNumber.addEventListener(\"change\", function () {\n      eventBus.dispatch(\"pagenumberchanged\", {\n        source: self,\n        value: this.value\n      });\n    });\n    scaleSelect.addEventListener(\"change\", function () {\n      if (this.value === \"custom\") {\n        return;\n      }\n      eventBus.dispatch(\"scalechanged\", {\n        source: self,\n        value: this.value\n      });\n    });\n    scaleSelect.addEventListener(\"click\", function ({\n      target\n    }) {\n      if (this.value === self.pageScaleValue && target.tagName.toUpperCase() === \"OPTION\") {\n        this.blur();\n      }\n    });\n    scaleSelect.oncontextmenu = pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.noContextMenu;\n    eventBus._on(\"annotationeditormodechanged\", this.#editorModeChanged.bind(this));\n  }\n  #editorModeChanged({\n    mode\n  }) {\n    const {\n      editorFreeTextButton,\n      editorFreeTextParamsToolbar,\n      editorHighlightButton,\n      editorHighlightParamsToolbar,\n      editorInkButton,\n      editorInkParamsToolbar,\n      editorStampButton,\n      editorStampParamsToolbar\n    } = this.#opts;\n    (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.toggleCheckedBtn)(editorFreeTextButton, mode === pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.FREETEXT, editorFreeTextParamsToolbar);\n    (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.toggleCheckedBtn)(editorHighlightButton, mode === pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.HIGHLIGHT, editorHighlightParamsToolbar);\n    (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.toggleCheckedBtn)(editorInkButton, mode === pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.INK, editorInkParamsToolbar);\n    (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.toggleCheckedBtn)(editorStampButton, mode === pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.STAMP, editorStampParamsToolbar);\n    const isDisable = mode === pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.DISABLE;\n    editorFreeTextButton.disabled = isDisable;\n    editorHighlightButton.disabled = isDisable;\n    editorInkButton.disabled = isDisable;\n    editorStampButton.disabled = isDisable;\n  }\n  #updateUIState(resetNumPages = false) {\n    const {\n      pageNumber,\n      pagesCount,\n      pageScaleValue,\n      pageScale\n    } = this;\n    const opts = this.#opts;\n    if (resetNumPages) {\n      if (this.hasPageLabels) {\n        opts.pageNumber.type = \"text\";\n        opts.numPages.setAttribute(\"data-l10n-id\", \"pdfjs-page-of-pages\");\n      } else {\n        opts.pageNumber.type = \"number\";\n        opts.numPages.setAttribute(\"data-l10n-id\", \"pdfjs-of-pages\");\n        opts.numPages.setAttribute(\"data-l10n-args\", JSON.stringify({\n          pagesCount\n        }));\n      }\n      opts.pageNumber.max = pagesCount;\n    }\n    if (this.hasPageLabels) {\n      opts.pageNumber.value = this.pageLabel;\n      opts.numPages.setAttribute(\"data-l10n-args\", JSON.stringify({\n        pageNumber,\n        pagesCount\n      }));\n    } else {\n      opts.pageNumber.value = pageNumber;\n    }\n    opts.previous.disabled = pageNumber <= 1;\n    opts.next.disabled = pageNumber >= pagesCount;\n    opts.zoomOut.disabled = pageScale <= _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.MIN_SCALE;\n    opts.zoomIn.disabled = pageScale >= _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.MAX_SCALE;\n    let predefinedValueFound = false;\n    for (const option of opts.scaleSelect.options) {\n      if (option.value !== pageScaleValue) {\n        option.selected = false;\n        continue;\n      }\n      option.selected = true;\n      predefinedValueFound = true;\n    }\n    if (!predefinedValueFound) {\n      opts.customScaleOption.selected = true;\n      opts.customScaleOption.setAttribute(\"data-l10n-args\", JSON.stringify({\n        scale: Math.round(pageScale * 10000) / 100\n      }));\n    }\n  }\n  updateLoadingIndicatorState(loading = false) {\n    const {\n      pageNumber\n    } = this.#opts;\n    pageNumber.classList.toggle(\"loading\", loading);\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 7256:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   AutoPrintRegExp: () => (/* binding */ AutoPrintRegExp),\n/* harmony export */   CursorTool: () => (/* binding */ CursorTool),\n/* harmony export */   DEFAULT_SCALE: () => (/* binding */ DEFAULT_SCALE),\n/* harmony export */   DEFAULT_SCALE_DELTA: () => (/* binding */ DEFAULT_SCALE_DELTA),\n/* harmony export */   DEFAULT_SCALE_VALUE: () => (/* binding */ DEFAULT_SCALE_VALUE),\n/* harmony export */   MAX_AUTO_SCALE: () => (/* binding */ MAX_AUTO_SCALE),\n/* harmony export */   MAX_SCALE: () => (/* binding */ MAX_SCALE),\n/* harmony export */   MIN_SCALE: () => (/* binding */ MIN_SCALE),\n/* harmony export */   OutputScale: () => (/* binding */ OutputScale),\n/* harmony export */   PresentationModeState: () => (/* binding */ PresentationModeState),\n/* harmony export */   ProgressBar: () => (/* binding */ ProgressBar),\n/* harmony export */   RenderingStates: () => (/* binding */ RenderingStates),\n/* harmony export */   SCROLLBAR_PADDING: () => (/* binding */ SCROLLBAR_PADDING),\n/* harmony export */   ScrollMode: () => (/* binding */ ScrollMode),\n/* harmony export */   SidebarView: () => (/* binding */ SidebarView),\n/* harmony export */   SpreadMode: () => (/* binding */ SpreadMode),\n/* harmony export */   TextLayerMode: () => (/* binding */ TextLayerMode),\n/* harmony export */   UNKNOWN_SCALE: () => (/* binding */ UNKNOWN_SCALE),\n/* harmony export */   VERTICAL_PADDING: () => (/* binding */ VERTICAL_PADDING),\n/* harmony export */   animationStarted: () => (/* binding */ animationStarted),\n/* harmony export */   apiPageLayoutToViewerModes: () => (/* binding */ apiPageLayoutToViewerModes),\n/* harmony export */   apiPageModeToSidebarView: () => (/* binding */ apiPageModeToSidebarView),\n/* harmony export */   approximateFraction: () => (/* binding */ approximateFraction),\n/* harmony export */   binarySearchFirstItem: () => (/* binding */ binarySearchFirstItem),\n/* harmony export */   docStyle: () => (/* binding */ docStyle),\n/* harmony export */   getActiveOrFocusedElement: () => (/* binding */ getActiveOrFocusedElement),\n/* harmony export */   getPageSizeInches: () => (/* binding */ getPageSizeInches),\n/* harmony export */   getVisibleElements: () => (/* binding */ getVisibleElements),\n/* harmony export */   isPortraitOrientation: () => (/* binding */ isPortraitOrientation),\n/* harmony export */   isValidRotation: () => (/* binding */ isValidRotation),\n/* harmony export */   isValidScrollMode: () => (/* binding */ isValidScrollMode),\n/* harmony export */   isValidSpreadMode: () => (/* binding */ isValidSpreadMode),\n/* harmony export */   normalizeWheelEventDelta: () => (/* binding */ normalizeWheelEventDelta),\n/* harmony export */   normalizeWheelEventDirection: () => (/* binding */ normalizeWheelEventDirection),\n/* harmony export */   parseQueryString: () => (/* binding */ parseQueryString),\n/* harmony export */   removeNullCharacters: () => (/* binding */ removeNullCharacters),\n/* harmony export */   roundToDivide: () => (/* binding */ roundToDivide),\n/* harmony export */   scrollIntoView: () => (/* binding */ scrollIntoView),\n/* harmony export */   toggleCheckedBtn: () => (/* binding */ toggleCheckedBtn),\n/* harmony export */   toggleExpandedBtn: () => (/* binding */ toggleExpandedBtn),\n/* harmony export */   watchScroll: () => (/* binding */ watchScroll)\n/* harmony export */ });\n/* unused harmony export backtrackBeforeAllVisibleElements */\nconst DEFAULT_SCALE_VALUE = \"auto\";\nconst DEFAULT_SCALE = 1.0;\nconst DEFAULT_SCALE_DELTA = 1.1;\nconst MIN_SCALE = 0.1;\nconst MAX_SCALE = 10.0;\nconst UNKNOWN_SCALE = 0;\nconst MAX_AUTO_SCALE = 1.25;\nconst SCROLLBAR_PADDING = 40;\nconst VERTICAL_PADDING = 5;\nconst RenderingStates = {\n  INITIAL: 0,\n  RUNNING: 1,\n  PAUSED: 2,\n  FINISHED: 3\n};\nconst PresentationModeState = {\n  UNKNOWN: 0,\n  NORMAL: 1,\n  CHANGING: 2,\n  FULLSCREEN: 3\n};\nconst SidebarView = {\n  UNKNOWN: -1,\n  NONE: 0,\n  THUMBS: 1,\n  OUTLINE: 2,\n  ATTACHMENTS: 3,\n  LAYERS: 4\n};\nconst TextLayerMode = {\n  DISABLE: 0,\n  ENABLE: 1,\n  ENABLE_PERMISSIONS: 2\n};\nconst ScrollMode = {\n  UNKNOWN: -1,\n  VERTICAL: 0,\n  HORIZONTAL: 1,\n  WRAPPED: 2,\n  PAGE: 3\n};\nconst SpreadMode = {\n  UNKNOWN: -1,\n  NONE: 0,\n  ODD: 1,\n  EVEN: 2\n};\nconst CursorTool = {\n  SELECT: 0,\n  HAND: 1,\n  ZOOM: 2\n};\nconst AutoPrintRegExp = /\\bprint\\s*\\(/;\nclass OutputScale {\n  constructor() {\n    const pixelRatio = window.devicePixelRatio || 1;\n    this.sx = pixelRatio;\n    this.sy = pixelRatio;\n  }\n  get scaled() {\n    return this.sx !== 1 || this.sy !== 1;\n  }\n}\nfunction scrollIntoView(element, spot, scrollMatches = false) {\n  let parent = element.offsetParent;\n  if (!parent) {\n    console.error(\"offsetParent is not set -- cannot scroll\");\n    return;\n  }\n  let offsetY = element.offsetTop + element.clientTop;\n  let offsetX = element.offsetLeft + element.clientLeft;\n  while (parent.clientHeight === parent.scrollHeight && parent.clientWidth === parent.scrollWidth || scrollMatches && (parent.classList.contains(\"markedContent\") || getComputedStyle(parent).overflow === \"hidden\")) {\n    offsetY += parent.offsetTop;\n    offsetX += parent.offsetLeft;\n    parent = parent.offsetParent;\n    if (!parent) {\n      return;\n    }\n  }\n  if (spot) {\n    if (spot.top !== undefined) {\n      offsetY += spot.top;\n    }\n    if (spot.left !== undefined) {\n      offsetX += spot.left;\n      parent.scrollLeft = offsetX;\n    }\n  }\n  parent.scrollTop = offsetY;\n}\nfunction watchScroll(viewAreaElement, callback) {\n  const debounceScroll = function (evt) {\n    if (rAF) {\n      return;\n    }\n    rAF = window.requestAnimationFrame(function viewAreaElementScrolled() {\n      rAF = null;\n      const currentX = viewAreaElement.scrollLeft;\n      const lastX = state.lastX;\n      if (currentX !== lastX) {\n        state.right = currentX > lastX;\n      }\n      state.lastX = currentX;\n      const currentY = viewAreaElement.scrollTop;\n      const lastY = state.lastY;\n      if (currentY !== lastY) {\n        state.down = currentY > lastY;\n      }\n      state.lastY = currentY;\n      callback(state);\n    });\n  };\n  const state = {\n    right: true,\n    down: true,\n    lastX: viewAreaElement.scrollLeft,\n    lastY: viewAreaElement.scrollTop,\n    _eventHandler: debounceScroll\n  };\n  let rAF = null;\n  viewAreaElement.addEventListener(\"scroll\", debounceScroll, true);\n  return state;\n}\nfunction parseQueryString(query) {\n  const params = new Map();\n  for (const [key, value] of new URLSearchParams(query)) {\n    params.set(key.toLowerCase(), value);\n  }\n  return params;\n}\nconst InvisibleCharsRegExp = /[\\x00-\\x1F]/g;\nfunction removeNullCharacters(str, replaceInvisible = false) {\n  if (!InvisibleCharsRegExp.test(str)) {\n    return str;\n  }\n  if (replaceInvisible) {\n    return str.replaceAll(InvisibleCharsRegExp, m => m === \"\\x00\" ? \"\" : \" \");\n  }\n  return str.replaceAll(\"\\x00\", \"\");\n}\nfunction binarySearchFirstItem(items, condition, start = 0) {\n  let minIndex = start;\n  let maxIndex = items.length - 1;\n  if (maxIndex < 0 || !condition(items[maxIndex])) {\n    return items.length;\n  }\n  if (condition(items[minIndex])) {\n    return minIndex;\n  }\n  while (minIndex < maxIndex) {\n    const currentIndex = minIndex + maxIndex >> 1;\n    const currentItem = items[currentIndex];\n    if (condition(currentItem)) {\n      maxIndex = currentIndex;\n    } else {\n      minIndex = currentIndex + 1;\n    }\n  }\n  return minIndex;\n}\nfunction approximateFraction(x) {\n  if (Math.floor(x) === x) {\n    return [x, 1];\n  }\n  const xinv = 1 / x;\n  const limit = 8;\n  if (xinv > limit) {\n    return [1, limit];\n  } else if (Math.floor(xinv) === xinv) {\n    return [1, xinv];\n  }\n  const x_ = x > 1 ? xinv : x;\n  let a = 0,\n    b = 1,\n    c = 1,\n    d = 1;\n  while (true) {\n    const p = a + c,\n      q = b + d;\n    if (q > limit) {\n      break;\n    }\n    if (x_ <= p / q) {\n      c = p;\n      d = q;\n    } else {\n      a = p;\n      b = q;\n    }\n  }\n  let result;\n  if (x_ - a / b < c / d - x_) {\n    result = x_ === x ? [a, b] : [b, a];\n  } else {\n    result = x_ === x ? [c, d] : [d, c];\n  }\n  return result;\n}\nfunction roundToDivide(x, div) {\n  const r = x % div;\n  return r === 0 ? x : Math.round(x - r + div);\n}\nfunction getPageSizeInches({\n  view,\n  userUnit,\n  rotate\n}) {\n  const [x1, y1, x2, y2] = view;\n  const changeOrientation = rotate % 180 !== 0;\n  const width = (x2 - x1) / 72 * userUnit;\n  const height = (y2 - y1) / 72 * userUnit;\n  return {\n    width: changeOrientation ? height : width,\n    height: changeOrientation ? width : height\n  };\n}\nfunction backtrackBeforeAllVisibleElements(index, views, top) {\n  if (index < 2) {\n    return index;\n  }\n  let elt = views[index].div;\n  let pageTop = elt.offsetTop + elt.clientTop;\n  if (pageTop >= top) {\n    elt = views[index - 1].div;\n    pageTop = elt.offsetTop + elt.clientTop;\n  }\n  for (let i = index - 2; i >= 0; --i) {\n    elt = views[i].div;\n    if (elt.offsetTop + elt.clientTop + elt.clientHeight <= pageTop) {\n      break;\n    }\n    index = i;\n  }\n  return index;\n}\nfunction getVisibleElements({\n  scrollEl,\n  views,\n  sortByVisibility = false,\n  horizontal = false,\n  rtl = false\n}) {\n  const top = scrollEl.scrollTop,\n    bottom = top + scrollEl.clientHeight;\n  const left = scrollEl.scrollLeft,\n    right = left + scrollEl.clientWidth;\n  function isElementBottomAfterViewTop(view) {\n    const element = view.div;\n    const elementBottom = element.offsetTop + element.clientTop + element.clientHeight;\n    return elementBottom > top;\n  }\n  function isElementNextAfterViewHorizontally(view) {\n    const element = view.div;\n    const elementLeft = element.offsetLeft + element.clientLeft;\n    const elementRight = elementLeft + element.clientWidth;\n    return rtl ? elementLeft < right : elementRight > left;\n  }\n  const visible = [],\n    ids = new Set(),\n    numViews = views.length;\n  let firstVisibleElementInd = binarySearchFirstItem(views, horizontal ? isElementNextAfterViewHorizontally : isElementBottomAfterViewTop);\n  if (firstVisibleElementInd > 0 && firstVisibleElementInd < numViews && !horizontal) {\n    firstVisibleElementInd = backtrackBeforeAllVisibleElements(firstVisibleElementInd, views, top);\n  }\n  let lastEdge = horizontal ? right : -1;\n  for (let i = firstVisibleElementInd; i < numViews; i++) {\n    const view = views[i],\n      element = view.div;\n    const currentWidth = element.offsetLeft + element.clientLeft;\n    const currentHeight = element.offsetTop + element.clientTop;\n    const viewWidth = element.clientWidth,\n      viewHeight = element.clientHeight;\n    const viewRight = currentWidth + viewWidth;\n    const viewBottom = currentHeight + viewHeight;\n    if (lastEdge === -1) {\n      if (viewBottom >= bottom) {\n        lastEdge = viewBottom;\n      }\n    } else if ((horizontal ? currentWidth : currentHeight) > lastEdge) {\n      break;\n    }\n    if (viewBottom <= top || currentHeight >= bottom || viewRight <= left || currentWidth >= right) {\n      continue;\n    }\n    const hiddenHeight = Math.max(0, top - currentHeight) + Math.max(0, viewBottom - bottom);\n    const hiddenWidth = Math.max(0, left - currentWidth) + Math.max(0, viewRight - right);\n    const fractionHeight = (viewHeight - hiddenHeight) / viewHeight,\n      fractionWidth = (viewWidth - hiddenWidth) / viewWidth;\n    const percent = fractionHeight * fractionWidth * 100 | 0;\n    visible.push({\n      id: view.id,\n      x: currentWidth,\n      y: currentHeight,\n      view,\n      percent,\n      widthPercent: fractionWidth * 100 | 0\n    });\n    ids.add(view.id);\n  }\n  const first = visible[0],\n    last = visible.at(-1);\n  if (sortByVisibility) {\n    visible.sort(function (a, b) {\n      const pc = a.percent - b.percent;\n      if (Math.abs(pc) > 0.001) {\n        return -pc;\n      }\n      return a.id - b.id;\n    });\n  }\n  return {\n    first,\n    last,\n    views: visible,\n    ids\n  };\n}\nfunction normalizeWheelEventDirection(evt) {\n  let delta = Math.hypot(evt.deltaX, evt.deltaY);\n  const angle = Math.atan2(evt.deltaY, evt.deltaX);\n  if (-0.25 * Math.PI < angle && angle < 0.75 * Math.PI) {\n    delta = -delta;\n  }\n  return delta;\n}\nfunction normalizeWheelEventDelta(evt) {\n  const deltaMode = evt.deltaMode;\n  let delta = normalizeWheelEventDirection(evt);\n  const MOUSE_PIXELS_PER_LINE = 30;\n  const MOUSE_LINES_PER_PAGE = 30;\n  if (deltaMode === WheelEvent.DOM_DELTA_PIXEL) {\n    delta /= MOUSE_PIXELS_PER_LINE * MOUSE_LINES_PER_PAGE;\n  } else if (deltaMode === WheelEvent.DOM_DELTA_LINE) {\n    delta /= MOUSE_LINES_PER_PAGE;\n  }\n  return delta;\n}\nfunction isValidRotation(angle) {\n  return Number.isInteger(angle) && angle % 90 === 0;\n}\nfunction isValidScrollMode(mode) {\n  return Number.isInteger(mode) && Object.values(ScrollMode).includes(mode) && mode !== ScrollMode.UNKNOWN;\n}\nfunction isValidSpreadMode(mode) {\n  return Number.isInteger(mode) && Object.values(SpreadMode).includes(mode) && mode !== SpreadMode.UNKNOWN;\n}\nfunction isPortraitOrientation(size) {\n  return size.width <= size.height;\n}\nconst animationStarted = new Promise(function (resolve) {\n  window.requestAnimationFrame(resolve);\n});\nconst docStyle = document.documentElement.style;\nfunction clamp(v, min, max) {\n  return Math.min(Math.max(v, min), max);\n}\nclass ProgressBar {\n  #classList = null;\n  #disableAutoFetchTimeout = null;\n  #percent = 0;\n  #style = null;\n  #visible = true;\n  constructor(bar) {\n    this.#classList = bar.classList;\n    this.#style = bar.style;\n  }\n  get percent() {\n    return this.#percent;\n  }\n  set percent(val) {\n    this.#percent = clamp(val, 0, 100);\n    if (isNaN(val)) {\n      this.#classList.add(\"indeterminate\");\n      return;\n    }\n    this.#classList.remove(\"indeterminate\");\n    this.#style.setProperty(\"--progressBar-percent\", `${this.#percent}%`);\n  }\n  setWidth(viewer) {\n    if (!viewer) {\n      return;\n    }\n    const container = viewer.parentNode;\n    const scrollbarWidth = container.offsetWidth - viewer.offsetWidth;\n    if (scrollbarWidth > 0) {\n      this.#style.setProperty(\"--progressBar-end-offset\", `${scrollbarWidth}px`);\n    }\n  }\n  setDisableAutoFetch(delay = 5000) {\n    if (isNaN(this.#percent)) {\n      return;\n    }\n    if (this.#disableAutoFetchTimeout) {\n      clearTimeout(this.#disableAutoFetchTimeout);\n    }\n    this.show();\n    this.#disableAutoFetchTimeout = setTimeout(() => {\n      this.#disableAutoFetchTimeout = null;\n      this.hide();\n    }, delay);\n  }\n  hide() {\n    if (!this.#visible) {\n      return;\n    }\n    this.#visible = false;\n    this.#classList.add(\"hidden\");\n  }\n  show() {\n    if (this.#visible) {\n      return;\n    }\n    this.#visible = true;\n    this.#classList.remove(\"hidden\");\n  }\n}\nfunction getActiveOrFocusedElement() {\n  let curRoot = document;\n  let curActiveOrFocused = curRoot.activeElement || curRoot.querySelector(\":focus\");\n  while (curActiveOrFocused?.shadowRoot) {\n    curRoot = curActiveOrFocused.shadowRoot;\n    curActiveOrFocused = curRoot.activeElement || curRoot.querySelector(\":focus\");\n  }\n  return curActiveOrFocused;\n}\nfunction apiPageLayoutToViewerModes(layout) {\n  let scrollMode = ScrollMode.VERTICAL,\n    spreadMode = SpreadMode.NONE;\n  switch (layout) {\n    case \"SinglePage\":\n      scrollMode = ScrollMode.PAGE;\n      break;\n    case \"OneColumn\":\n      break;\n    case \"TwoPageLeft\":\n      scrollMode = ScrollMode.PAGE;\n    case \"TwoColumnLeft\":\n      spreadMode = SpreadMode.ODD;\n      break;\n    case \"TwoPageRight\":\n      scrollMode = ScrollMode.PAGE;\n    case \"TwoColumnRight\":\n      spreadMode = SpreadMode.EVEN;\n      break;\n  }\n  return {\n    scrollMode,\n    spreadMode\n  };\n}\nfunction apiPageModeToSidebarView(mode) {\n  switch (mode) {\n    case \"UseNone\":\n      return SidebarView.NONE;\n    case \"UseThumbs\":\n      return SidebarView.THUMBS;\n    case \"UseOutlines\":\n      return SidebarView.OUTLINE;\n    case \"UseAttachments\":\n      return SidebarView.ATTACHMENTS;\n    case \"UseOC\":\n      return SidebarView.LAYERS;\n  }\n  return SidebarView.NONE;\n}\nfunction toggleCheckedBtn(button, toggle, view = null) {\n  button.classList.toggle(\"toggled\", toggle);\n  button.setAttribute(\"aria-checked\", toggle);\n  view?.classList.toggle(\"hidden\", !toggle);\n}\nfunction toggleExpandedBtn(button, toggle, view = null) {\n  button.classList.toggle(\"toggled\", toggle);\n  button.setAttribute(\"aria-expanded\", toggle);\n  view?.classList.toggle(\"hidden\", !toggle);\n}\n\n\n/***/ }),\n\n/***/ 9226:\n/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   ViewHistory: () => (/* binding */ ViewHistory)\n/* harmony export */ });\nconst DEFAULT_VIEW_HISTORY_CACHE_SIZE = 20;\nclass ViewHistory {\n  constructor(fingerprint, cacheSize = DEFAULT_VIEW_HISTORY_CACHE_SIZE) {\n    this.fingerprint = fingerprint;\n    this.cacheSize = cacheSize;\n    this._initializedPromise = this._readFromStorage().then(databaseStr => {\n      const database = JSON.parse(databaseStr || \"{}\");\n      let index = -1;\n      if (!Array.isArray(database.files)) {\n        database.files = [];\n      } else {\n        while (database.files.length >= this.cacheSize) {\n          database.files.shift();\n        }\n        for (let i = 0, ii = database.files.length; i < ii; i++) {\n          const branch = database.files[i];\n          if (branch.fingerprint === this.fingerprint) {\n            index = i;\n            break;\n          }\n        }\n      }\n      if (index === -1) {\n        index = database.files.push({\n          fingerprint: this.fingerprint\n        }) - 1;\n      }\n      this.file = database.files[index];\n      this.database = database;\n    });\n  }\n  async _writeToStorage() {\n    const databaseStr = JSON.stringify(this.database);\n    localStorage.setItem(\"pdfjs.history\", databaseStr);\n  }\n  async _readFromStorage() {\n    return localStorage.getItem(\"pdfjs.history\");\n  }\n  async set(name, val) {\n    await this._initializedPromise;\n    this.file[name] = val;\n    return this._writeToStorage();\n  }\n  async setMultiple(properties) {\n    await this._initializedPromise;\n    for (const name in properties) {\n      this.file[name] = properties[name];\n    }\n    return this._writeToStorage();\n  }\n  async get(name, defaultValue) {\n    await this._initializedPromise;\n    const val = this.file[name];\n    return val !== undefined ? val : defaultValue;\n  }\n  async getMultiple(properties) {\n    await this._initializedPromise;\n    const values = Object.create(null);\n    for (const name in properties) {\n      const val = this.file[name];\n      values[name] = val !== undefined ? val : properties[name];\n    }\n    return values;\n  }\n}\n\n\n/***/ }),\n\n/***/ 2030:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   PDFViewerApplication: () => (/* reexport safe */ _app_js__WEBPACK_IMPORTED_MODULE_3__.PDFViewerApplication),\n/* harmony export */   PDFViewerApplicationConstants: () => (/* binding */ AppConstants),\n/* harmony export */   PDFViewerApplicationOptions: () => (/* reexport safe */ _app_options_js__WEBPACK_IMPORTED_MODULE_1__.AppOptions)\n/* harmony export */ });\n/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256);\n/* harmony import */ var _app_options_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9840);\n/* harmony import */ var _pdf_link_service_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(787);\n/* harmony import */ var _app_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(1621);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([_app_js__WEBPACK_IMPORTED_MODULE_3__]);\n_app_js__WEBPACK_IMPORTED_MODULE_3__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];\n\n\n\n\nconst pdfjsVersion = \"4.2.67\";\nconst pdfjsBuild = \"49b388101\";\nconst AppConstants = {\n  LinkTarget: _pdf_link_service_js__WEBPACK_IMPORTED_MODULE_2__.LinkTarget,\n  RenderingStates: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates,\n  ScrollMode: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode,\n  SpreadMode: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SpreadMode\n};\nwindow.PDFViewerApplication = _app_js__WEBPACK_IMPORTED_MODULE_3__.PDFViewerApplication;\nwindow.PDFViewerApplicationConstants = AppConstants;\nwindow.PDFViewerApplicationOptions = _app_options_js__WEBPACK_IMPORTED_MODULE_1__.AppOptions;\nfunction getViewerConfiguration() {\n  return {\n    appContainer: document.body,\n    mainContainer: document.getElementById(\"viewerContainer\"),\n    viewerContainer: document.getElementById(\"viewer\"),\n    toolbar: {\n      container: document.getElementById(\"toolbarViewer\"),\n      numPages: document.getElementById(\"numPages\"),\n      pageNumber: document.getElementById(\"pageNumber\"),\n      scaleSelect: document.getElementById(\"scaleSelect\"),\n      customScaleOption: document.getElementById(\"customScaleOption\"),\n      previous: document.getElementById(\"previous\"),\n      next: document.getElementById(\"next\"),\n      zoomIn: document.getElementById(\"zoomIn\"),\n      zoomOut: document.getElementById(\"zoomOut\"),\n      viewFind: document.getElementById(\"viewFind\"),\n      print: document.getElementById(\"print\"),\n      editorFreeTextButton: document.getElementById(\"editorFreeText\"),\n      editorFreeTextParamsToolbar: document.getElementById(\"editorFreeTextParamsToolbar\"),\n      editorHighlightButton: document.getElementById(\"editorHighlight\"),\n      editorHighlightParamsToolbar: document.getElementById(\"editorHighlightParamsToolbar\"),\n      editorHighlightColorPicker: document.getElementById(\"editorHighlightColorPicker\"),\n      editorInkButton: document.getElementById(\"editorInk\"),\n      editorInkParamsToolbar: document.getElementById(\"editorInkParamsToolbar\"),\n      editorStampButton: document.getElementById(\"editorStamp\"),\n      editorStampParamsToolbar: document.getElementById(\"editorStampParamsToolbar\"),\n      download: document.getElementById(\"download\")\n    },\n    secondaryToolbar: {\n      toolbar: document.getElementById(\"secondaryToolbar\"),\n      toggleButton: document.getElementById(\"secondaryToolbarToggle\"),\n      presentationModeButton: document.getElementById(\"presentationMode\"),\n      openFileButton: document.getElementById(\"secondaryOpenFile\"),\n      printButton: document.getElementById(\"secondaryPrint\"),\n      downloadButton: document.getElementById(\"secondaryDownload\"),\n      viewBookmarkButton: document.getElementById(\"viewBookmark\"),\n      firstPageButton: document.getElementById(\"firstPage\"),\n      lastPageButton: document.getElementById(\"lastPage\"),\n      pageRotateCwButton: document.getElementById(\"pageRotateCw\"),\n      pageRotateCcwButton: document.getElementById(\"pageRotateCcw\"),\n      cursorSelectToolButton: document.getElementById(\"cursorSelectTool\"),\n      cursorHandToolButton: document.getElementById(\"cursorHandTool\"),\n      scrollPageButton: document.getElementById(\"scrollPage\"),\n      scrollVerticalButton: document.getElementById(\"scrollVertical\"),\n      scrollHorizontalButton: document.getElementById(\"scrollHorizontal\"),\n      scrollWrappedButton: document.getElementById(\"scrollWrapped\"),\n      spreadNoneButton: document.getElementById(\"spreadNone\"),\n      spreadOddButton: document.getElementById(\"spreadOdd\"),\n      spreadEvenButton: document.getElementById(\"spreadEven\"),\n      documentPropertiesButton: document.getElementById(\"documentProperties\")\n    },\n    sidebar: {\n      outerContainer: document.getElementById(\"outerContainer\"),\n      sidebarContainer: document.getElementById(\"sidebarContainer\"),\n      toggleButton: document.getElementById(\"sidebarToggle\"),\n      resizer: document.getElementById(\"sidebarResizer\"),\n      thumbnailButton: document.getElementById(\"viewThumbnail\"),\n      outlineButton: document.getElementById(\"viewOutline\"),\n      attachmentsButton: document.getElementById(\"viewAttachments\"),\n      layersButton: document.getElementById(\"viewLayers\"),\n      thumbnailView: document.getElementById(\"thumbnailView\"),\n      outlineView: document.getElementById(\"outlineView\"),\n      attachmentsView: document.getElementById(\"attachmentsView\"),\n      layersView: document.getElementById(\"layersView\"),\n      currentOutlineItemButton: document.getElementById(\"currentOutlineItem\")\n    },\n    findBar: {\n      bar: document.getElementById(\"findbar\"),\n      toggleButton: document.getElementById(\"viewFind\"),\n      findField: document.getElementById(\"findInput\"),\n      highlightAllCheckbox: document.getElementById(\"findHighlightAll\"),\n      caseSensitiveCheckbox: document.getElementById(\"findMatchCase\"),\n      matchDiacriticsCheckbox: document.getElementById(\"findMatchDiacritics\"),\n      entireWordCheckbox: document.getElementById(\"findEntireWord\"),\n      findMsg: document.getElementById(\"findMsg\"),\n      findResultsCount: document.getElementById(\"findResultsCount\"),\n      findPreviousButton: document.getElementById(\"findPrevious\"),\n      findNextButton: document.getElementById(\"findNext\")\n    },\n    passwordOverlay: {\n      dialog: document.getElementById(\"passwordDialog\"),\n      label: document.getElementById(\"passwordText\"),\n      input: document.getElementById(\"password\"),\n      submitButton: document.getElementById(\"passwordSubmit\"),\n      cancelButton: document.getElementById(\"passwordCancel\")\n    },\n    documentProperties: {\n      dialog: document.getElementById(\"documentPropertiesDialog\"),\n      closeButton: document.getElementById(\"documentPropertiesClose\"),\n      fields: {\n        fileName: document.getElementById(\"fileNameField\"),\n        fileSize: document.getElementById(\"fileSizeField\"),\n        title: document.getElementById(\"titleField\"),\n        author: document.getElementById(\"authorField\"),\n        subject: document.getElementById(\"subjectField\"),\n        keywords: document.getElementById(\"keywordsField\"),\n        creationDate: document.getElementById(\"creationDateField\"),\n        modificationDate: document.getElementById(\"modificationDateField\"),\n        creator: document.getElementById(\"creatorField\"),\n        producer: document.getElementById(\"producerField\"),\n        version: document.getElementById(\"versionField\"),\n        pageCount: document.getElementById(\"pageCountField\"),\n        pageSize: document.getElementById(\"pageSizeField\"),\n        linearized: document.getElementById(\"linearizedField\")\n      }\n    },\n    altTextDialog: {\n      dialog: document.getElementById(\"altTextDialog\"),\n      optionDescription: document.getElementById(\"descriptionButton\"),\n      optionDecorative: document.getElementById(\"decorativeButton\"),\n      textarea: document.getElementById(\"descriptionTextarea\"),\n      cancelButton: document.getElementById(\"altTextCancel\"),\n      saveButton: document.getElementById(\"altTextSave\")\n    },\n    annotationEditorParams: {\n      editorFreeTextFontSize: document.getElementById(\"editorFreeTextFontSize\"),\n      editorFreeTextColor: document.getElementById(\"editorFreeTextColor\"),\n      editorInkColor: document.getElementById(\"editorInkColor\"),\n      editorInkThickness: document.getElementById(\"editorInkThickness\"),\n      editorInkOpacity: document.getElementById(\"editorInkOpacity\"),\n      editorStampAddImage: document.getElementById(\"editorStampAddImage\"),\n      editorFreeHighlightThickness: document.getElementById(\"editorFreeHighlightThickness\"),\n      editorHighlightShowAll: document.getElementById(\"editorHighlightShowAll\")\n    },\n    printContainer: document.getElementById(\"printContainer\")\n  };\n}\nfunction webViewerLoad() {\n  const config = getViewerConfiguration();\n  const event = new CustomEvent(\"webviewerloaded\", {\n    bubbles: true,\n    cancelable: true,\n    detail: {\n      source: window\n    }\n  });\n  try {\n    parent.document.dispatchEvent(event);\n  } catch (ex) {\n    console.error(`webviewerloaded: ${ex}`);\n    document.dispatchEvent(event);\n  }\n  _app_js__WEBPACK_IMPORTED_MODULE_3__.PDFViewerApplication.run(config);\n}\ndocument.blockUnblockOnload?.(true);\nif (document.readyState === \"interactive\" || document.readyState === \"complete\") {\n  webViewerLoad();\n} else {\n  document.addEventListener(\"DOMContentLoaded\", webViewerLoad, true);\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ }),\n\n/***/ 2973:\n/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => {\n\n__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   XfaLayerBuilder: () => (/* binding */ XfaLayerBuilder)\n/* harmony export */ });\n/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603);\nvar __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__]);\npdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];\n\nclass XfaLayerBuilder {\n  constructor({\n    pdfPage,\n    annotationStorage = null,\n    linkService,\n    xfaHtml = null\n  }) {\n    this.pdfPage = pdfPage;\n    this.annotationStorage = annotationStorage;\n    this.linkService = linkService;\n    this.xfaHtml = xfaHtml;\n    this.div = null;\n    this._cancelled = false;\n  }\n  async render(viewport, intent = \"display\") {\n    if (intent === \"print\") {\n      const parameters = {\n        viewport: viewport.clone({\n          dontFlip: true\n        }),\n        div: this.div,\n        xfaHtml: this.xfaHtml,\n        annotationStorage: this.annotationStorage,\n        linkService: this.linkService,\n        intent\n      };\n      this.div = document.createElement(\"div\");\n      parameters.div = this.div;\n      return pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.XfaLayer.render(parameters);\n    }\n    const xfaHtml = await this.pdfPage.getXfa();\n    if (this._cancelled || !xfaHtml) {\n      return {\n        textDivs: []\n      };\n    }\n    const parameters = {\n      viewport: viewport.clone({\n        dontFlip: true\n      }),\n      div: this.div,\n      xfaHtml,\n      annotationStorage: this.annotationStorage,\n      linkService: this.linkService,\n      intent\n    };\n    if (this.div) {\n      return pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.XfaLayer.update(parameters);\n    }\n    this.div = document.createElement(\"div\");\n    parameters.div = this.div;\n    return pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.XfaLayer.render(parameters);\n  }\n  cancel() {\n    this._cancelled = true;\n  }\n  hide() {\n    if (!this.div) {\n      return;\n    }\n    this.div.hidden = true;\n  }\n}\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } });\n\n/***/ })\n\n/******/ });\n/************************************************************************/\n/******/ // The module cache\n/******/ var __webpack_module_cache__ = {};\n/******/ \n/******/ // The require function\n/******/ function __webpack_require__(moduleId) {\n/******/ \t// Check if module is in cache\n/******/ \tvar cachedModule = __webpack_module_cache__[moduleId];\n/******/ \tif (cachedModule !== undefined) {\n/******/ \t\treturn cachedModule.exports;\n/******/ \t}\n/******/ \t// Create a new module (and put it into the cache)\n/******/ \tvar module = __webpack_module_cache__[moduleId] = {\n/******/ \t\t// no module.id needed\n/******/ \t\t// no module.loaded needed\n/******/ \t\texports: {}\n/******/ \t};\n/******/ \n/******/ \t// Execute the module function\n/******/ \t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n/******/ \n/******/ \t// Return the exports of the module\n/******/ \treturn module.exports;\n/******/ }\n/******/ \n/************************************************************************/\n/******/ /* webpack/runtime/async module */\n/******/ (() => {\n/******/ \tvar webpackQueues = typeof Symbol === \"function\" ? Symbol(\"webpack queues\") : \"__webpack_queues__\";\n/******/ \tvar webpackExports = typeof Symbol === \"function\" ? Symbol(\"webpack exports\") : \"__webpack_exports__\";\n/******/ \tvar webpackError = typeof Symbol === \"function\" ? Symbol(\"webpack error\") : \"__webpack_error__\";\n/******/ \tvar resolveQueue = (queue) => {\n/******/ \t\tif(queue && queue.d < 1) {\n/******/ \t\t\tqueue.d = 1;\n/******/ \t\t\tqueue.forEach((fn) => (fn.r--));\n/******/ \t\t\tqueue.forEach((fn) => (fn.r-- ? fn.r++ : fn()));\n/******/ \t\t}\n/******/ \t}\n/******/ \tvar wrapDeps = (deps) => (deps.map((dep) => {\n/******/ \t\tif(dep !== null && typeof dep === \"object\") {\n/******/ \t\t\tif(dep[webpackQueues]) return dep;\n/******/ \t\t\tif(dep.then) {\n/******/ \t\t\t\tvar queue = [];\n/******/ \t\t\t\tqueue.d = 0;\n/******/ \t\t\t\tdep.then((r) => {\n/******/ \t\t\t\t\tobj[webpackExports] = r;\n/******/ \t\t\t\t\tresolveQueue(queue);\n/******/ \t\t\t\t}, (e) => {\n/******/ \t\t\t\t\tobj[webpackError] = e;\n/******/ \t\t\t\t\tresolveQueue(queue);\n/******/ \t\t\t\t});\n/******/ \t\t\t\tvar obj = {};\n/******/ \t\t\t\tobj[webpackQueues] = (fn) => (fn(queue));\n/******/ \t\t\t\treturn obj;\n/******/ \t\t\t}\n/******/ \t\t}\n/******/ \t\tvar ret = {};\n/******/ \t\tret[webpackQueues] = x => {};\n/******/ \t\tret[webpackExports] = dep;\n/******/ \t\treturn ret;\n/******/ \t}));\n/******/ \t__webpack_require__.a = (module, body, hasAwait) => {\n/******/ \t\tvar queue;\n/******/ \t\thasAwait && ((queue = []).d = -1);\n/******/ \t\tvar depQueues = new Set();\n/******/ \t\tvar exports = module.exports;\n/******/ \t\tvar currentDeps;\n/******/ \t\tvar outerResolve;\n/******/ \t\tvar reject;\n/******/ \t\tvar promise = new Promise((resolve, rej) => {\n/******/ \t\t\treject = rej;\n/******/ \t\t\touterResolve = resolve;\n/******/ \t\t});\n/******/ \t\tpromise[webpackExports] = exports;\n/******/ \t\tpromise[webpackQueues] = (fn) => (queue && fn(queue), depQueues.forEach(fn), promise[\"catch\"](x => {}));\n/******/ \t\tmodule.exports = promise;\n/******/ \t\tbody((deps) => {\n/******/ \t\t\tcurrentDeps = wrapDeps(deps);\n/******/ \t\t\tvar fn;\n/******/ \t\t\tvar getResult = () => (currentDeps.map((d) => {\n/******/ \t\t\t\tif(d[webpackError]) throw d[webpackError];\n/******/ \t\t\t\treturn d[webpackExports];\n/******/ \t\t\t}))\n/******/ \t\t\tvar promise = new Promise((resolve) => {\n/******/ \t\t\t\tfn = () => (resolve(getResult));\n/******/ \t\t\t\tfn.r = 0;\n/******/ \t\t\t\tvar fnQueue = (q) => (q !== queue && !depQueues.has(q) && (depQueues.add(q), q && !q.d && (fn.r++, q.push(fn))));\n/******/ \t\t\t\tcurrentDeps.map((dep) => (dep[webpackQueues](fnQueue)));\n/******/ \t\t\t});\n/******/ \t\t\treturn fn.r ? promise : getResult();\n/******/ \t\t}, (err) => ((err ? reject(promise[webpackError] = err) : outerResolve(exports)), resolveQueue(queue)));\n/******/ \t\tqueue && queue.d < 0 && (queue.d = 0);\n/******/ \t};\n/******/ })();\n/******/ \n/******/ /* webpack/runtime/define property getters */\n/******/ (() => {\n/******/ \t// define getter functions for harmony exports\n/******/ \t__webpack_require__.d = (exports, definition) => {\n/******/ \t\tfor(var key in definition) {\n/******/ \t\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n/******/ \t\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n/******/ \t\t\t}\n/******/ \t\t}\n/******/ \t};\n/******/ })();\n/******/ \n/******/ /* webpack/runtime/hasOwnProperty shorthand */\n/******/ (() => {\n/******/ \t__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))\n/******/ })();\n/******/ \n/************************************************************************/\n/******/ \n/******/ // startup\n/******/ // Load entry module and return exports\n/******/ // This entry module used 'module' so it can't be inlined\n/******/ var __webpack_exports__ = __webpack_require__(2030);\n/******/ __webpack_exports__ = await __webpack_exports__;\n/******/ var __webpack_exports__PDFViewerApplication = __webpack_exports__.PDFViewerApplication;\n/******/ var __webpack_exports__PDFViewerApplicationConstants = __webpack_exports__.PDFViewerApplicationConstants;\n/******/ var __webpack_exports__PDFViewerApplicationOptions = __webpack_exports__.PDFViewerApplicationOptions;\n/******/ export { __webpack_exports__PDFViewerApplication as PDFViewerApplication, __webpack_exports__PDFViewerApplicationConstants as PDFViewerApplicationConstants, __webpack_exports__PDFViewerApplicationOptions as PDFViewerApplicationOptions };\n/******/ \n\n//# sourceMappingURL=viewer.mjs.map"
  },
  {
    "path": "src/StaffWebUI/wwwroot/theme-info.js",
    "content": "﻿// This needs to be a custom element, because we need it to run during prerendering and immediately\n// after FluentUI's <loading-theme> custom element initializes. Otherwise there's a flash of wrong styling.\n// This also means it has to be a regular script file and not a module loaded via JS interop.\n\nclass LoadingThemeInfo extends HTMLElement {\n    static getEffectiveTheme() {\n        const explicitTheme = document.querySelector('fluent-design-theme').getAttribute('mode');\n        switch (explicitTheme) {\n            case 'dark':\n            case 'light':\n                return explicitTheme;\n            default:\n                // It's using system, or no theme is set so it defaults to system\n                return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n        }\n    }\n\n    static updateEffectiveThemeClass() {\n        document.documentElement.classList.toggle('dark-mode', LoadingThemeInfo.getEffectiveTheme() === 'dark');\n\n    }\n\n    connectedCallback() {\n        LoadingThemeInfo.updateEffectiveThemeClass();\n    }\n}\n\nwindow.customElements.define('loading-theme-info', LoadingThemeInfo);\nwindow.LoadingThemeInfo = LoadingThemeInfo;\n\nwindow.scrollToTop = function () {\n    window.scrollTo({ top: 0, left: 0, behavior: 'instant' });\n}"
  },
  {
    "path": "test/E2ETest/ChatCompletionCache/5AF0103EF2560BEC4FE94D21D18E3A1945C5202F7B452834A8FFC891322F321A.json",
    "content": "[{\"contents\":[],\"completionId\":\"\",\"createdAt\":\"1970-01-01T00:00:00+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG48030xtBzcYF1HrvS5lDsZIdiLG\",\"createdAt\":\"2024-10-08T13:01:20+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG48030xtBzcYF1HrvS5lDsZIdiLG\",\"createdAt\":\"2024-10-08T13:01:20+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG48030xtBzcYF1HrvS5lDsZIdiLG\",\"createdAt\":\"2024-10-08T13:01:20+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG48030xtBzcYF1HrvS5lDsZIdiLG\",\"createdAt\":\"2024-10-08T13:01:20+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG48030xtBzcYF1HrvS5lDsZIdiLG\",\"createdAt\":\"2024-10-08T13:01:20+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG48030xtBzcYF1HrvS5lDsZIdiLG\",\"createdAt\":\"2024-10-08T13:01:20+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG48030xtBzcYF1HrvS5lDsZIdiLG\",\"createdAt\":\"2024-10-08T13:01:20+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG48030xtBzcYF1HrvS5lDsZIdiLG\",\"createdAt\":\"2024-10-08T13:01:20+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG48030xtBzcYF1HrvS5lDsZIdiLG\",\"createdAt\":\"2024-10-08T13:01:20+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG48030xtBzcYF1HrvS5lDsZIdiLG\",\"createdAt\":\"2024-10-08T13:01:20+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG48030xtBzcYF1HrvS5lDsZIdiLG\",\"createdAt\":\"2024-10-08T13:01:20+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG48030xtBzcYF1HrvS5lDsZIdiLG\",\"createdAt\":\"2024-10-08T13:01:20+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG48030xtBzcYF1HrvS5lDsZIdiLG\",\"createdAt\":\"2024-10-08T13:01:20+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG48030xtBzcYF1HrvS5lDsZIdiLG\",\"createdAt\":\"2024-10-08T13:01:20+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG48030xtBzcYF1HrvS5lDsZIdiLG\",\"createdAt\":\"2024-10-08T13:01:20+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG48030xtBzcYF1HrvS5lDsZIdiLG\",\"createdAt\":\"2024-10-08T13:01:20+00:00\",\"choiceIndex\":0,\"finishReason\":\"tool_calls\"},{\"role\":\"assistant\",\"contents\":[{\"$type\":\"functionCall\",\"callId\":\"call_xhYpM2N6YVHEhEVDQXetIiJS\",\"name\":\"SearchManual\",\"arguments\":{\"searchPhrase\":\"LED safety light not working\",\"productId\":1},\"modelId\":\"\"}],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"\",\"createdAt\":\"1970-01-01T00:00:00+00:00\",\"choiceIndex\":0,\"finishReason\":\"tool_calls\"}]"
  },
  {
    "path": "test/E2ETest/ChatCompletionCache/6981B02D1211D89EAD2B18D2A00BC2CC55A0CAA06E294C0318ADBB35112EB9D7.json",
    "content": "[{\"contents\":[],\"completionId\":\"\",\"createdAt\":\"1970-01-01T00:00:00+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG488MmRLWzn9GhB6SNK7stdZ5mw4\",\"createdAt\":\"2024-10-08T13:01:28+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG488MmRLWzn9GhB6SNK7stdZ5mw4\",\"createdAt\":\"2024-10-08T13:01:28+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG488MmRLWzn9GhB6SNK7stdZ5mw4\",\"createdAt\":\"2024-10-08T13:01:28+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG488MmRLWzn9GhB6SNK7stdZ5mw4\",\"createdAt\":\"2024-10-08T13:01:28+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG488MmRLWzn9GhB6SNK7stdZ5mw4\",\"createdAt\":\"2024-10-08T13:01:28+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG488MmRLWzn9GhB6SNK7stdZ5mw4\",\"createdAt\":\"2024-10-08T13:01:28+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG488MmRLWzn9GhB6SNK7stdZ5mw4\",\"createdAt\":\"2024-10-08T13:01:28+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG488MmRLWzn9GhB6SNK7stdZ5mw4\",\"createdAt\":\"2024-10-08T13:01:28+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG488MmRLWzn9GhB6SNK7stdZ5mw4\",\"createdAt\":\"2024-10-08T13:01:28+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG488MmRLWzn9GhB6SNK7stdZ5mw4\",\"createdAt\":\"2024-10-08T13:01:28+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG488MmRLWzn9GhB6SNK7stdZ5mw4\",\"createdAt\":\"2024-10-08T13:01:28+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG488MmRLWzn9GhB6SNK7stdZ5mw4\",\"createdAt\":\"2024-10-08T13:01:28+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG488MmRLWzn9GhB6SNK7stdZ5mw4\",\"createdAt\":\"2024-10-08T13:01:28+00:00\",\"choiceIndex\":0,\"finishReason\":\"tool_calls\"},{\"role\":\"assistant\",\"contents\":[{\"$type\":\"functionCall\",\"callId\":\"call_zHanJB5ZgYy2u7M229bACKD5\",\"name\":\"SearchManual\",\"arguments\":{\"searchPhrase\":\"battery type\",\"productId\":1},\"modelId\":\"\"}],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"\",\"createdAt\":\"1970-01-01T00:00:00+00:00\",\"choiceIndex\":0,\"finishReason\":\"tool_calls\"}]"
  },
  {
    "path": "test/E2ETest/ChatCompletionCache/973247AA1FE93490986EF3435E4C6D88928EC469857A873D0899EB4389672BB0.json",
    "content": "[{\"contents\":[],\"completionId\":\"\",\"createdAt\":\"1970-01-01T00:00:00+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[{\"$type\":\"text\",\"text\":\"Trailblazer Bike Helmet\"}],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG481Y2gOxYJXXB9jLntCVDmtwdrb\",\"createdAt\":\"2024-10-08T13:01:21+00:00\",\"choiceIndex\":0,\"finishReason\":\"stop\"}]"
  },
  {
    "path": "test/E2ETest/ChatCompletionCache/C70A33FF52171DCD96D2BF8F41BC45DE1FA308FAF38030F5EFE5764FDA6F787A.json",
    "content": "{\"choices\":[{\"role\":\"assistant\",\"contents\":[{\"$type\":\"text\",\"text\":\"{\\n  \\u0022IsAddressedToCustomerByName\\u0022: false\\n}\",\"modelId\":\"gpt-35-turbo\"}]}],\"message\":{\"role\":\"assistant\",\"contents\":[{\"$type\":\"text\",\"text\":\"{\\n  \\u0022IsAddressedToCustomerByName\\u0022: false\\n}\",\"modelId\":\"gpt-35-turbo\"}]},\"completionId\":\"chatcmpl-AG489LfGYzvhuSqqGAE0XvKGUKW4S\",\"modelId\":\"gpt-35-turbo\",\"createdAt\":\"2024-10-08T13:01:29+00:00\",\"finishReason\":\"stop\",\"usage\":{\"inputTokenCount\":149,\"outputTokenCount\":13,\"totalTokenCount\":162},\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"}}"
  },
  {
    "path": "test/E2ETest/ChatCompletionCache/E55E8743B91B9650A9C60E7DF7627B0B5C39C8CD35093DF9D6F6EE4CF476FE87.json",
    "content": "[{\"contents\":[],\"completionId\":\"\",\"createdAt\":\"1970-01-01T00:00:00+00:00\",\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[{\"$type\":\"text\",\"text\":\"The Trailblazer Bike Helmet uses a CR2032 3V battery.\\n\\u003Ccite searchResultId=16\\u003E\\u0022Replace the battery if necessary with a CR2032 3V battery.\\u0022\\u003C/cite\\u003E\"}],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"choiceIndex\":0},{\"role\":\"assistant\",\"contents\":[],\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"},\"completionId\":\"chatcmpl-AG489AIps7y4omenzlnH3GE84MZX9\",\"createdAt\":\"2024-10-08T13:01:29+00:00\",\"choiceIndex\":0,\"finishReason\":\"stop\"}]"
  },
  {
    "path": "test/E2ETest/ChatCompletionCache/F7F43C2AD0BFAB1D1CEECA1454D8C1DD286336B9E097A32FA1A8FFEEA785937E.json",
    "content": "{\"choices\":[{\"role\":\"assistant\",\"contents\":[{\"$type\":\"text\",\"text\":\"{\\n  \\u0022IsAddressedToCustomerByName\\u0022: false\\n}\",\"modelId\":\"gpt-35-turbo\"}]}],\"message\":{\"role\":\"assistant\",\"contents\":[{\"$type\":\"text\",\"text\":\"{\\n  \\u0022IsAddressedToCustomerByName\\u0022: false\\n}\",\"modelId\":\"gpt-35-turbo\"}]},\"completionId\":\"chatcmpl-AG481PiFeEYrB0jmZcntxB49v9rHx\",\"modelId\":\"gpt-35-turbo\",\"createdAt\":\"2024-10-08T13:01:21+00:00\",\"finishReason\":\"stop\",\"usage\":{\"inputTokenCount\":113,\"outputTokenCount\":13,\"totalTokenCount\":126},\"additionalProperties\":{\"SystemFingerprint\":\"fp_808245b034\"}}"
  },
  {
    "path": "test/E2ETest/E2ETest.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n    <TargetFramework>net8.0</TargetFramework>\n    <ImplicitUsings>enable</ImplicitUsings>\n    <Nullable>enable</Nullable>\n\n    <IsPackable>false</IsPackable>\n    <IsTestProject>true</IsTestProject>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Aspire.Hosting.Testing\" />\n    <PackageReference Include=\"Microsoft.NET.Test.Sdk\" />\n    <PackageReference Include=\"Microsoft.Playwright\" />\n    <PackageReference Include=\"xunit\" />\n    <PackageReference Include=\"xunit.runner.visualstudio\">\n      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>\n      <PrivateAssets>all</PrivateAssets>\n    </PackageReference>\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\src\\AppHost\\AppHost.csproj\" />\n    <ProjectReference Include=\"..\\..\\src\\ServiceDefaults\\ServiceDefaults.csproj\" />\n  </ItemGroup>\n\n  <Target Name=\"InstallPlaywrightDeps\" BeforeTargets=\"CoreBuild\">\n    <PropertyGroup>\n      <_PowerShellExe>pwsh</_PowerShellExe>\n      <_PowerShellExe Condition=\"'$(OS)' == 'Windows_NT'\">powershell</_PowerShellExe>\n      <_PlaywrightScript>$([System.IO.Path]::GetFullPath($(OutDir)))playwright.ps1</_PlaywrightScript>\n    </PropertyGroup>\n    <Exec Command=\"$(_PowerShellExe) -NoProfile -NoLogo -NonInteractive -ExecutionPolicy Unrestricted -Command '$(_PlaywrightScript) install chromium --with-deps'\" />\n  </Target>\n\n</Project>\n"
  },
  {
    "path": "test/E2ETest/GlobalUsings.cs",
    "content": "﻿global using Xunit;\nglobal using E2ETest.Infrastructure;\nglobal using static Microsoft.Playwright.Assertions;\n"
  },
  {
    "path": "test/E2ETest/Infrastructure/AppHostFixture.cs",
    "content": "﻿using Aspire.Hosting.Testing;\nusing eShopSupport.ServiceDefaults.Clients.Backend;\nusing IdentityModel.Client;\n\nnamespace E2ETest.Infrastructure;\n\npublic class AppHostFixture : IAsyncDisposable\n{\n    private readonly Task<DistributedApplication> _appInitializer;\n\n    public Resource StaffWebUI { get; }\n\n    public AppHostFixture()\n    {\n        _appInitializer = InitializeAsync();\n        StaffWebUI = new Resource(\"staffwebui\", this);\n    }\n\n    private async Task<DistributedApplication> InitializeAsync()\n    {\n        Environment.CurrentDirectory = Projects.AppHost.ProjectPath;\n        Environment.SetEnvironmentVariable(\"E2E_TEST\", \"true\");\n        Environment.SetEnvironmentVariable(\"E2E_TEST_CHAT_COMPLETION_CACHE_DIR\",\n            Path.Combine(Projects.E2ETest.ProjectPath, \"ChatCompletionCache\"));\n        var builder = await DistributedApplicationTestingBuilder.CreateAsync<Projects.AppHost>();\n        var app = await builder.BuildAsync();\n        await app.StartAsync();\n\n        // Don't consider it initialized until we confirm it's finished data seeding\n        var backendClient = await DevToolBackendClient.GetDevToolStaffBackendClientAsync(\n            app.CreateHttpClient(\"identity-server\"),\n            app.CreateHttpClient(\"backend\"));\n        var tickets = await backendClient.ListTicketsAsync(new ListTicketsRequest(null, null, null, 0, 1, null, null));\n        Assert.NotEmpty(tickets.Items);\n\n        return app;\n    }\n\n    public async ValueTask DisposeAsync()\n    {\n        var app = await _appInitializer;\n        await app.StopAsync();\n    }\n\n    public class Resource(string name, AppHostFixture owner)\n    {\n        public async Task<HttpClient> CreateHttpClientAsync()\n            => (await owner._appInitializer).CreateHttpClient(name);\n\n        public async Task<string> ResolveUrlAsync(string relativeUrl)\n        {\n            var app = await owner._appInitializer;\n            var baseUri = app.GetEndpoint(name);\n            return new Uri(baseUri, relativeUrl).ToString();\n        }\n    }\n}\n"
  },
  {
    "path": "test/E2ETest/Infrastructure/AppTestCollection.cs",
    "content": "﻿\nnamespace E2ETest.Infrastructure;\n\n[CollectionDefinition(Name)]\npublic class AppTestCollection : ICollectionFixture<AppHostFixture>\n{\n    public const string Name = \"apptest collection\";\n}\n"
  },
  {
    "path": "test/E2ETest/Infrastructure/LoginExtensions.cs",
    "content": "﻿using Microsoft.Playwright;\n\nnamespace E2ETest;\n\npublic static class LoginExtensions\n{\n    public static async Task LoginAsTestUserAsync(this IPage page, AppHostFixture app)\n    {\n        var homeUrl = await app.StaffWebUI.ResolveUrlAsync(\"/\");\n        await page.GotoAsync(homeUrl);\n\n        var userNameInput = page.Locator(\"#Input_Username\");\n        var passwordInput = page.Locator(\"#Input_Password\");\n        await Expect(userNameInput).ToBeVisibleAsync();\n\n        await userNameInput.FillAsync(\"bob\");\n        await passwordInput.FillAsync(\"bob\");\n        await page.Locator(\"button[value='login']\").ClickAsync();\n\n        await Expect(page).ToHaveTitleAsync(\"eShopSupport: Tickets\");\n    }\n}\n"
  },
  {
    "path": "test/E2ETest/Infrastructure/PlaywrightTestBase.cs",
    "content": "﻿using System.Diagnostics;\nusing Microsoft.Playwright;\nnamespace E2ETest.Infrastructure;\n\npublic class PlaywrightTestBase : IAsyncLifetime\n{\n    protected IPlaywright Playwright { get; private set; } = default!;\n    protected IBrowser Browser { get; private set; } = default!;\n    protected IPage Page { get; private set; } = default!;\n\n    public virtual async Task InitializeAsync()\n    {\n        Playwright = await Microsoft.Playwright.Playwright.CreateAsync();\n        Browser = await Playwright.Chromium.LaunchAsync(new()\n        {\n            Headless = !Debugger.IsAttached,\n        });\n\n        if (Page is not null)\n        {\n            // Otherwise we have to deal with unsubscribing from Page.PageError\n            throw new InvalidOperationException(\"Cannot intialize a new page when one is already initialized\");\n        }\n\n        Page = await Browser.NewPageAsync();\n        Page.PageError += (_, message)\n            => throw new InvalidOperationException(\"Page error: \" + message);\n    }\n\n    public async Task DisposeAsync()\n    {\n        await Browser.DisposeAsync();\n        Playwright.Dispose();\n    }\n}\n"
  },
  {
    "path": "test/E2ETest/TicketAssistantTest.cs",
    "content": "﻿using Microsoft.Playwright;\n\nnamespace E2ETest;\n\n[Collection(AppTestCollection.Name)]\npublic class TicketAssistantTest(AppHostFixture app) : PlaywrightTestBase\n{\n    ILocator SuggestionLinks => Page.Locator(\".assistant .suggestions a\");\n    ILocator WriteMessageTextArea => Page.Locator(\".assistant .write-message textarea\");\n    ILocator NthReply(int n) => Page.Locator(\".assistant .message.assistant\").Nth(n);\n\n    public override async Task InitializeAsync()\n    {\n        await base.InitializeAsync();\n        await Page.LoginAsTestUserAsync(app);\n    }\n\n    [Fact]\n    public async Task OffersOptionsToCheckManualAndWriteReply()\n    {\n        var url = await app.StaffWebUI.ResolveUrlAsync(\"/ticket/1\");\n        await Page.GotoAsync(url);\n\n        await Expect(SuggestionLinks).ToHaveCountAsync(2);\n        await Expect(SuggestionLinks.Nth(0)).ToHaveTextAsync(\"What does the manual say about this?\");\n        await Expect(SuggestionLinks.Nth(1)).ToHaveTextAsync(\"Write a suggested reply to the customer.\");\n    }\n\n    [Fact]\n    public async Task CanAnswerQuestionAboutTicket()\n    {\n        var url = await app.StaffWebUI.ResolveUrlAsync(\"/ticket/1\");\n        await Page.GotoAsync(url);\n        await SendMessageAsync(\"What product is this about? Reply with the product name only and no other text.\");\n\n        var reply = await GetNthCompletedReply(0);\n        await Expect(reply.Locator(\".message-text\")).ToContainTextAsync(\"Trailblazer Bike Helmet\");\n    }\n\n    [Fact]\n    public async Task CanSearchManualToGetAnswer()\n    {\n        var url = await app.StaffWebUI.ResolveUrlAsync(\"/ticket/1\");\n        await Page.GotoAsync(url);\n\n        await SendMessageAsync(\"What type of battery does it have?\");\n\n        // See it does a search and gets info from the manual\n        var reply = await GetNthCompletedReply(0);\n        await Expect(reply.Locator(\".search-info\")).ToContainTextAsync(\"battery\");\n        await Expect(reply.Locator(\".message-text\")).ToContainTextAsync(\"CR2032\");\n\n        // Also check the link to the manual\n        var referenceLink = reply.Locator(\".reference-link\");\n        await Expect(referenceLink).ToContainTextAsync(\"battery\");\n        var referenceLinkUrl = await referenceLink.GetAttributeAsync(\"href\");\n        Assert.StartsWith(\"manual.html?file=1.pdf&page=7\", referenceLinkUrl);\n    }\n\n    private async Task SendMessageAsync(string text)\n    {\n        await WriteMessageTextArea.FillAsync(text);\n        await Task.Delay(500);\n        await WriteMessageTextArea.PressAsync(\"Enter\");\n    }\n\n    private async Task<ILocator> GetNthCompletedReply(int n)\n    {\n        // Wait for it to be added to the page, and the response to be completed\n        await Expect(NthReply(n)).ToBeAttachedAsync();\n        await Expect(Page.Locator(\".assistant .write-message.in-progress\"))\n            .ToHaveCountAsync(0, new() { Timeout = 30000 });\n\n        return NthReply(n);\n    }\n}\n"
  },
  {
    "path": "test/E2ETest/TicketsListTest.cs",
    "content": "﻿namespace E2ETest;\n\n[Collection(AppTestCollection.Name)]\npublic class TicketsListTest(AppHostFixture app) : PlaywrightTestBase\n{\n    public override async Task InitializeAsync()\n    {\n        await base.InitializeAsync();\n        await Page.LoginAsTestUserAsync(app);\n    }\n\n    [Fact]\n    public async Task HasPageTitle()\n    {\n        var url = await app.StaffWebUI.ResolveUrlAsync(\"/\");\n        await Page.GotoAsync(url);\n        await Expect(Page).ToHaveTitleAsync(\"eShopSupport: Tickets\");\n    }\n\n    [Fact]\n    public async Task ShowsOpenTicketsButNotClosedOnes()\n    {\n        var url = await app.StaffWebUI.ResolveUrlAsync(\"/\");\n        await Page.GotoAsync(url);\n\n        await Expect(Page.Locator(\"a[href='ticket/1']\").First).ToBeAttachedAsync();\n        await Expect(Page.Locator(\"a[href='ticket/2']\").First).Not.ToBeAttachedAsync();\n    }\n\n    [Fact]\n    public async Task CanSwitchToShowClosedTickets()\n    {\n        var url = await app.StaffWebUI.ResolveUrlAsync(\"/\");\n        await Page.GotoAsync(url);\n\n        await Page.ClickAsync(\"#filter-closed\");\n        await Expect(Page.Locator(\"a[href='ticket/2']\").First).ToBeAttachedAsync();\n        await Expect(Page.Locator(\"a[href='ticket/1']\").First).Not.ToBeAttachedAsync();\n    }\n}\n"
  },
  {
    "path": "test/EvaluationTests/AnswerScoringEvaluator.cs",
    "content": "﻿// --------------------------------------------------------------------------------------------\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// --------------------------------------------------------------------------------------------\n\nnamespace Microsoft.Extensions.AI.Evaluation.Quality;\n\npublic sealed class AnswerScoringEvaluator : IEvaluator\n{\n    public sealed class Context(string expectedAnswer) : EvaluationContext(ContextName, content: expectedAnswer)\n    {\n        private const string ContextName = \"Answer Score\";\n\n        public string ExpectedAnswer { get; } = expectedAnswer;\n    }\n\n    private const string MetricName = \"Answer Score\";\n\n    public IReadOnlyCollection<string> EvaluationMetricNames => [MetricName];\n\n    public async ValueTask<EvaluationResult> EvaluateAsync(\n        IEnumerable<ChatMessage> messages,\n        ChatResponse modelResponse,\n        ChatConfiguration? chatConfiguration = null,\n        IEnumerable<EvaluationContext>? additionalContext = null,\n        CancellationToken cancellationToken = default)\n    {\n        ArgumentNullException.ThrowIfNull(modelResponse);\n        ArgumentNullException.ThrowIfNull(chatConfiguration);\n\n        var numericMetric = new NumericMetric(MetricName);\n        var result = new EvaluationResult(numericMetric);\n\n        if (!messages.TryGetUserRequest(out ChatMessage? userRequest, out IReadOnlyList<ChatMessage> conversationHistory))\n        {\n            result.AddDiagnosticsToAllMetrics(\n                EvaluationDiagnostic.Error(\n                    $\"The ${messages} supplied for evaluation did not contain a user request as the last message.\"));\n            return result;\n        }\n\n        if (string.IsNullOrWhiteSpace(modelResponse.Text))\n        {\n            result.AddDiagnosticsToAllMetrics(\n                EvaluationDiagnostic.Error($\"The {nameof(modelResponse)} supplied for evaluation was null or empty.\"));\n            return result;\n        }\n\n        var evaluationInstructions = GetEvaluationInstructions(\n            userRequest,\n            modelResponse,\n            conversationHistory,\n            additionalContext);\n\n        var response = await chatConfiguration.ChatClient.GetResponseAsync<ScoringResponse>(\n            evaluationInstructions,\n            cancellationToken: cancellationToken);\n\n        if (!response.TryGetResult(out var scoringResponse))\n        {\n            result.AddDiagnosticsToAllMetrics(\n                EvaluationDiagnostic.Error(\"Scoring response was not provided in a valid format.\"));\n            return result;\n        }\n\n        if (scoringResponse.Scores is not [var score, ..])\n        {\n            result.AddDiagnosticsToAllMetrics(\n                EvaluationDiagnostic.Error(\"Scoring response contained no scores.\"));\n            return result;\n        }\n\n        numericMetric.Value = score.ScoreLabel;\n\n        if (!string.IsNullOrWhiteSpace(score.DescriptionOfQuality))\n        {\n            numericMetric.AddDiagnostics(EvaluationDiagnostic.Informational(score.DescriptionOfQuality));\n        }\n\n        numericMetric.Interpretation = Interpret(numericMetric);\n        return result;\n    }\n\n    private static List<ChatMessage> GetEvaluationInstructions(\n        ChatMessage? userRequest,\n        ChatResponse modelResponse,\n        IEnumerable<ChatMessage> includedHistory,\n        IEnumerable<EvaluationContext>? additionalContext)\n    {\n        string renderedModelResponse = modelResponse.RenderText();\n        string renderedUserRequest = userRequest?.RenderText() ?? string.Empty;\n        string answer;\n\n        if (additionalContext is not null &&\n            additionalContext.OfType<Context>().FirstOrDefault() is Context context)\n        {\n            answer = context.ExpectedAnswer;\n        }\n        else\n        {\n            throw new InvalidOperationException($\"The ExpectedAnswer must be provided in the additional context.\");\n        }\n\n        var prompt = $$\"\"\"\n        There is an AI assistant that answers questions about products sold by an online retailer. The questions\n        may be asked by customers or by customer support agents.\n\n        You are evaluating the quality of an AI assistant's response to several questions. Here are the\n        questions, the desired true answers, and the answers given by the AI system:\n\n        <questions>\n            <question index=\"0\">\n                <text>{{renderedUserRequest}}</text>\n                <truth>{{answer}}</truth>\n                <assistantAnswer>{{renderedModelResponse}}</assistantAnswer>\n            </question>\n        </questions>\n\n        Evaluate each of the assistant's answers separately by replying in this JSON format:\n\n        {\n            \"scores\": [\n                { \"index\": 0, \"descriptionOfQuality\": string, \"scoreLabel\": number },\n                { \"index\": 1, \"descriptionOfQuality\": string, \"scoreLabel\": number },\n                ... etc ...\n            ]\n        ]\n\n        Score only based on whether the assistant's answer is true and answers the question. As long as the\n        answer covers the question and is consistent with the truth, it should score as perfect. There is\n        no penalty for giving extra on-topic information or advice. Only penalize for missing necessary facts\n        or being misleading.\n\n        The descriptionOfQuality should be up to 5 words summarizing to what extent the assistant answer\n        is correct and sufficient.\n\n        Based on descriptionOfQuality, the scoreLabel must be a number between 1 and 5 inclusive, where 5 is best and 1 is worst.\n        Do not use any other words for scoreLabel. You may only pick one of those scores.\n        \n        \"\"\"\n        ;\n\n        return [new ChatMessage(ChatRole.User, prompt)];\n    }\n\n    internal static EvaluationMetricInterpretation Interpret(NumericMetric metric)\n    {\n        double score = metric?.Value ?? -1.0;\n        EvaluationRating rating = score switch {\n            1.0 => EvaluationRating.Unacceptable,\n            2.0 => EvaluationRating.Poor,\n            3.0 => EvaluationRating.Average,\n            4.0 => EvaluationRating.Good,\n            5.0 => EvaluationRating.Exceptional,\n            _ => EvaluationRating.Inconclusive,\n        };\n        return new EvaluationMetricInterpretation(rating, failed: rating == EvaluationRating.Inconclusive);\n    }\n}\n\nrecord ScoringResponse(AnswerScore[] Scores);\nrecord AnswerScore(int Index, int ScoreLabel, string DescriptionOfQuality);\n"
  },
  {
    "path": "test/EvaluationTests/EvalQuestion.cs",
    "content": "﻿namespace eShopSupport.EvaluationTests;\n\npublic class EvalQuestion\n{\n    public int QuestionId { get; set; }\n\n    public int? ProductId { get; set; }\n\n    public required string Question { get; set; }\n\n    public required string Answer { get; set; }\n}\n"
  },
  {
    "path": "test/EvaluationTests/EvaluationTests.cs",
    "content": "﻿using System.Reflection;\nusing System.Text;\nusing System.Text.Json;\nusing Azure.AI.OpenAI;\nusing Azure.Identity;\nusing eShopSupport.ServiceDefaults.Clients.Backend;\nusing EvaluationTests;\nusing Microsoft.Extensions.AI;\nusing Microsoft.Extensions.AI.Evaluation;\nusing Microsoft.Extensions.AI.Evaluation.Quality;\nusing Microsoft.Extensions.AI.Evaluation.Reporting;\nusing Microsoft.Extensions.AI.Evaluation.Reporting.Storage;\nusing Microsoft.ML.Tokenizers;\n\nnamespace eShopSupport.EvaluationTests\n{\n    public class EvaluationTests : IAsyncLifetime\n    {\n        public static IEnumerable<EvalQuestion> Questions => LoadEvaluationQuestions()\n            .OrderBy(a => a.QuestionId);\n\n        public static StaffBackendClient? backend = null;\n        public static IChatClient? chatCompletion = null;\n        private static readonly string ExecutionName = $\"{DateTime.UtcNow:yyyyMMddTHHmmss}\";\n\n        public async Task InitializeAsync()\n        {\n            backend = await DevToolBackendClient.GetDevToolStaffBackendClientAsync(\n                identityServerHttpClient: new HttpClient { BaseAddress = new Uri(\"https://localhost:7275/\") },\n                backendHttpClient: new HttpClient { BaseAddress = new Uri(\"https://localhost:7223/\") });\n            chatCompletion = new AzureOpenAIClient(new Uri(Settings.Current.Endpoint), new DefaultAzureCredential())\n                .GetChatClient(Settings.Current.DeploymentName).AsIChatClient();\n        }\n\n        public Task DisposeAsync() => Task.CompletedTask;\n\n        static EvalQuestion[] LoadEvaluationQuestions()\n        {\n            var questionDataPath = Assembly.GetExecutingAssembly()\n            .GetCustomAttributes<AssemblyMetadataAttribute>()\n            .Single(a => a.Key == \"EvalQuestionsJsonPath\").Value!;\n            if (!File.Exists(questionDataPath))\n            {\n                throw new FileNotFoundException(\"Questions not found. Ensure the data ingestor has run.\", questionDataPath);\n            }\n            var questionsJson = File.ReadAllText(questionDataPath);\n            return JsonSerializer.Deserialize<EvalQuestion[]>(questionsJson)!;\n        }\n\n        static ReportingConfiguration GetReportingConfiguration()\n        {\n            // Setup and configure the evaluators you would like to utilize for each AI chat\n#pragma warning disable AIEVAL001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.\n            IEvaluator rtcEvaluator = new RelevanceTruthAndCompletenessEvaluator();\n#pragma warning restore AIEVAL001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.\n            IEvaluator coherenceEvaluator = new CoherenceEvaluator();\n            IEvaluator fluencyEvaluator = new FluencyEvaluator();\n            IEvaluator groundednessEvaluator = new GroundednessEvaluator();\n            IEvaluator answerScoringEvaluator = new AnswerScoringEvaluator();\n\n            var endpoint = new Uri(Settings.Current.Endpoint);\n            var azureClient = new AzureOpenAIClient(endpoint, new DefaultAzureCredential());\n\n            IChatClient chatClient = azureClient.GetChatClient(Settings.Current.DeploymentName).AsIChatClient();\n            var chatConfig = new ChatConfiguration(chatClient);\n\n            return DiskBasedReportingConfiguration.Create(\n                    storageRootPath: Settings.Current.StorageRootPath,\n                    chatConfiguration: chatConfig,\n                    evaluators: [\n                        rtcEvaluator,\n                        coherenceEvaluator,\n                        fluencyEvaluator,\n                        groundednessEvaluator,\n                        answerScoringEvaluator],\n                    executionName: ExecutionName);\n        }\n\n        [Fact]\n        public async Task EvaluateQuestionsInALoop()\n        {\n\n            const int scoringParallelism = 4;\n            var reportingConfiguration = GetReportingConfiguration();\n\n            await Parallel.ForEachAsync(Questions.Take(5), new ParallelOptions { MaxDegreeOfParallelism = scoringParallelism }, (Func<EvalQuestion, CancellationToken, ValueTask>)(async (question, cancellationToken) =>\n            {\n\n                for (int i = 0; i < 3; i++)\n                {\n                    await EvaluateQuestion(question, reportingConfiguration, i, cancellationToken);\n                }\n            }));\n        }\n\n        public static TheoryData<EvalQuestion> EvalQuestions => [.. LoadEvaluationQuestions().OrderBy(a => a.QuestionId).Take(5)];\n\n        [Theory]\n        [MemberData(nameof(EvalQuestions))]\n        public async Task EvaluateQuestionsWithMemberData(EvalQuestion question)\n        {\n            var reportingConfiguration = GetReportingConfiguration();\n            for (int i = 0; i < 3; i++)\n            {\n                await EvaluateQuestion(question, reportingConfiguration, i, CancellationToken.None);\n            }\n        }\n\n        [Fact]\n        public async Task EvaluateQuestion_HowToAccessEssentials()\n        {\n            var reportingConfiguration = GetReportingConfiguration();\n            var question = new EvalQuestion\n            {\n                QuestionId = 1,\n                ProductId = 158,\n                Question = \"How to access essentials?\",\n                Answer = \"Unzip the main compartment\"\n            };\n            await EvaluateQuestion(question, reportingConfiguration, 0, CancellationToken.None);\n        }\n\n        [Fact]\n        public async Task EvaluateQuestion_WhatAreTheOverheatingPrecautions()\n        {\n            var reportingConfiguration = GetReportingConfiguration();\n            var question = new EvalQuestion\n            {\n                QuestionId = 2,\n                ProductId = 199,\n                Question = \"What are the overheating precautions?\",\n                Answer = \"Do not leave in direct sunlight for extended periods.\"\n            };\n\n            await EvaluateQuestion(question, reportingConfiguration, 0, CancellationToken.None);\n        }\n\n        [Fact]\n        public async Task EvaluateQuestion_Summit3000TrekkingBackpackStrapAdjustment()\n        {\n            var reportingConfiguration = GetReportingConfiguration();\n            var question = new EvalQuestion\n            {\n                QuestionId = 3,\n                ProductId = 99,\n                Question = \"Hi there, I recently purchased the Summit 3000 Trekking Backpack and I\\u0027m having issues with the strap adjustment. Can you provide me with the specified torque value for the strap adjustment bolts?\",\n                Answer = \"15-20 Nm\"\n            };\n            await EvaluateQuestion(question, reportingConfiguration, 0, CancellationToken.None);\n        }\n\n        private static async Task EvaluateQuestion(EvalQuestion question, ReportingConfiguration reportingConfiguration, int i, CancellationToken cancellationToken)\n        {\n            await using ScenarioRun scenario = await reportingConfiguration.CreateScenarioRunAsync($\"Question_{question.QuestionId}\", $\"Iteration {i + 1}\", cancellationToken: cancellationToken);\n\n            var responseItems = backend!.AssistantChatAsync(new AssistantChatRequest(\n                question.ProductId,\n                null,\n                null,\n                null,\n                [new() { IsAssistant = true, Text = question.Question }]),\n                cancellationToken);\n\n            var answerBuilder = new StringBuilder();\n            await foreach (var item in responseItems)\n            {\n                if (item.Type == AssistantChatReplyItemType.AnswerChunk)\n                {\n                    answerBuilder.Append(item.Text);\n                }\n            }\n\n            var finalAnswer = answerBuilder.ToString();\n\n            EvaluationResult evalResult = await scenario.EvaluateAsync(\n                [new ChatMessage(ChatRole.User, question.Question)],\n                new ChatResponse(new ChatMessage(ChatRole.Assistant, finalAnswer)),\n                additionalContext: [new AnswerScoringEvaluator.Context(question.Answer)],\n                cancellationToken);\n\n\n            Assert.False(evalResult.Metrics.Values.Any(m => m.Interpretation?.Rating == EvaluationRating.Inconclusive), \"Model response was inconclusive\");\n        }\n    }\n}\n"
  },
  {
    "path": "test/EvaluationTests/EvaluationTests.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>net8.0</TargetFramework>\n    <ImplicitUsings>enable</ImplicitUsings>\n    <Nullable>enable</Nullable>\n\n    <IsPackable>false</IsPackable>\n    <IsTestProject>true</IsTestProject>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\src\\Backend\\Backend.csproj\" />\n    <ProjectReference Include=\"..\\..\\src\\ServiceDefaults\\ServiceDefaults.csproj\" />\n\n    <AssemblyAttribute Include=\"System.Reflection.AssemblyMetadataAttribute\">\n      <_Parameter1>EvalQuestionsJsonPath</_Parameter1>\n      <_Parameter2>$(SolutionDir)seeddata\\test\\evalquestions.json</_Parameter2>\n    </AssemblyAttribute>\n  </ItemGroup>\n\n  <ItemGroup>\n    <None Update=\"appsettings.json\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </None>\n  </ItemGroup>\n  \n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.NET.Test.Sdk\"  />\n    <PackageReference Include=\"xunit\"  />\n    <PackageReference Include=\"xunit.runner.visualstudio\" />\n    <PackageReference Include=\"Microsoft.Extensions.AI.Evaluation\" />\n    <PackageReference Include=\"Microsoft.Extensions.AI.Evaluation.Quality\" />\n    <PackageReference Include=\"Microsoft.Extensions.AI.Evaluation.Reporting\" />\n    <PackageReference Include=\"Microsoft.ML.Tokenizers\" />\n    <PackageReference Include=\"Microsoft.ML.Tokenizers.Data.O200kBase\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <Using Include=\"Xunit\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "test/EvaluationTests/README.md",
    "content": "## Running the Evaluation Tests\n\n1. Make sure the eShopSupport application is configured and running on your local machine before running the tests. The tests will call into the eShopSupport APIs to collect AI responses, so this app must be up and running for evaluations to work.\n1. Create a local folder alongside the eShopSupport repo to contain the cached AI responses.\n1. Setup an [Azure OpenAI model deployment](https://azure.microsoft.com/en-us/products/ai-services/openai-service) to support the evaluation process. Take note of the model name, deployment name and endpoint during setup.\n1. Edit the [appsettings.json](./appsettings.json) file in this folder to reflect the correct Azure OpenAI deployment settings and the path to the cache folder.\n1. Run the tests from Visual Studio, VS Code, or `dotnet test`.\n\n## Generating the Evaluation report\n\n1. Update your dotnet tools by running\n    ```cmd\n    dotnet tool restore\n    ```\n1. Run the aieval report command to generate a report file.\n    ```cmd\n    dotnet aieval report --path /path/to/your/cache --output ./report.html\n    ```\n1. Open the `report.html` file in your web browser."
  },
  {
    "path": "test/EvaluationTests/Settings.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusing Microsoft.Extensions.Configuration;\n\nnamespace EvaluationTests;\n\npublic class Settings\n{\n\n    public readonly string DeploymentName;\n    public readonly string ModelName;\n    public readonly string Endpoint;\n    public readonly string StorageRootPath;\n\n    public Settings(IConfiguration config)\n    {\n        DeploymentName = config.GetValue<string>(\"DeploymentName\") ?? throw new ArgumentNullException(nameof(DeploymentName));\n        ModelName = config.GetValue<string>(\"ModelName\") ?? throw new ArgumentNullException(nameof(ModelName));\n        Endpoint = config.GetValue<string>(\"Endpoint\") ?? throw new ArgumentNullException(nameof(Endpoint));\n        StorageRootPath = config.GetValue<string>(\"StorageRootPath\") ?? throw new ArgumentNullException(nameof(StorageRootPath));\n    }\n\n    private static Settings? currentSettings = null;\n\n    public static Settings Current\n    {\n        get {\n            currentSettings ??= GetCurrentSettings();\n            return currentSettings;\n        }\n    }\n\n    private static Settings GetCurrentSettings()\n    {\n        var builder = new ConfigurationBuilder()\n            .SetBasePath(AppContext.BaseDirectory)\n            .AddJsonFile(\"appsettings.json\", optional: true, reloadOnChange: false)\n            .AddEnvironmentVariables();\n\n        IConfigurationRoot config = builder.Build();\n\n        return new Settings(config);\n    }\n}\n"
  },
  {
    "path": "test/EvaluationTests/appsettings.json",
    "content": "{\n  \"DeploymentName\": \"gpt-4o\",\n  \"ModelName\": \"gpt-4o\",\n  \"Endpoint\": \"https://your-ai-instance.openai.azure.com/\",\n  \"StorageRootPath\": \"/path/to/your/cache/folder\"\n}\n"
  }
]