From a8c5a3287e4321dfe07c6230595f7b03fc9534bc Mon Sep 17 00:00:00 2001 From: Zaid Date: Mon, 17 Aug 2020 02:01:03 +0200 Subject: [PATCH 1/9] Initial VS Support --- NpgsqlFSharpAnalyzer.sln | 30 + paket.dependencies | 2 +- src/AnalyzerVs/ContentTypeNames.cs | 7 + src/AnalyzerVs/FSharpLintVs.csproj | 534 ++++++++++++++++++ src/AnalyzerVs/FsLintVsPackage.cs | 77 +++ src/AnalyzerVs/LintChecker.cs | 314 ++++++++++ src/AnalyzerVs/LintCheckerProvider.cs | 181 ++++++ src/AnalyzerVs/LintError.cs | 76 +++ src/AnalyzerVs/LintProjectInfo.cs | 29 + src/AnalyzerVs/LintTagger.cs | 73 +++ src/AnalyzerVs/Options/FsLintOptionsPage.cs | 14 + src/AnalyzerVs/Properties/AssemblyInfo.cs | 33 ++ src/AnalyzerVs/Resources/License.txt | 8 + src/AnalyzerVs/Resources/ReleaseNotes.html | Bin 0 -> 1846 bytes src/AnalyzerVs/Resources/logo.png | Bin 0 -> 24590 bytes src/AnalyzerVs/SubscriptionManager.cs | 45 ++ src/AnalyzerVs/SuggestionPreview.xaml | 44 ++ src/AnalyzerVs/SuggestionPreview.xaml.cs | 33 ++ .../Suggestions/LintActionsSource.cs | 121 ++++ src/AnalyzerVs/Suggestions/LintFixAction.cs | 67 +++ .../Suggestions/LintSuggestionProvider.cs | 20 + .../Suggestions/LintSuppressAction.cs | 75 +++ src/AnalyzerVs/Suggestions/LintSuppressBy.cs | 140 +++++ .../Table/LintTableSnapshotFactory.cs | 40 ++ src/AnalyzerVs/Table/LintingErrorsSnapshot.cs | 177 ++++++ src/AnalyzerVs/paket.references | 2 + src/AnalyzerVs/source.extension.vsixmanifest | 27 + .../InformationSchema.fs | 112 ++-- .../NpgsqlFSharpAnalyzer.Core.fsproj | 20 + .../SqlAnalysis.fs | 7 +- src/NpgsqlFSharpAnalyzer.Core/SqlAnalyzer.fs | 31 + .../SyntacticAnalysis.fs | 9 +- src/NpgsqlFSharpAnalyzer.Core/Types.fs | 63 +++ .../NpgsqlFSharpAnalyzer.fsproj | 9 +- src/NpgsqlFSharpAnalyzer/SqlAnalyzer.fs | 70 ++- src/NpgsqlFSharpAnalyzer/Types.fs | 31 - src/NpgsqlFSharpAnalyzer/paket.references | 3 - .../NpgsqlFSharpAnalyzer.Tests.fsproj | 45 +- tests/NpgsqlFSharpAnalyzer.Tests/Tests.fs | 11 +- 39 files changed, 2419 insertions(+), 161 deletions(-) create mode 100644 src/AnalyzerVs/ContentTypeNames.cs create mode 100644 src/AnalyzerVs/FSharpLintVs.csproj create mode 100644 src/AnalyzerVs/FsLintVsPackage.cs create mode 100644 src/AnalyzerVs/LintChecker.cs create mode 100644 src/AnalyzerVs/LintCheckerProvider.cs create mode 100644 src/AnalyzerVs/LintError.cs create mode 100644 src/AnalyzerVs/LintProjectInfo.cs create mode 100644 src/AnalyzerVs/LintTagger.cs create mode 100644 src/AnalyzerVs/Options/FsLintOptionsPage.cs create mode 100644 src/AnalyzerVs/Properties/AssemblyInfo.cs create mode 100644 src/AnalyzerVs/Resources/License.txt create mode 100644 src/AnalyzerVs/Resources/ReleaseNotes.html create mode 100644 src/AnalyzerVs/Resources/logo.png create mode 100644 src/AnalyzerVs/SubscriptionManager.cs create mode 100644 src/AnalyzerVs/SuggestionPreview.xaml create mode 100644 src/AnalyzerVs/SuggestionPreview.xaml.cs create mode 100644 src/AnalyzerVs/Suggestions/LintActionsSource.cs create mode 100644 src/AnalyzerVs/Suggestions/LintFixAction.cs create mode 100644 src/AnalyzerVs/Suggestions/LintSuggestionProvider.cs create mode 100644 src/AnalyzerVs/Suggestions/LintSuppressAction.cs create mode 100644 src/AnalyzerVs/Suggestions/LintSuppressBy.cs create mode 100644 src/AnalyzerVs/Table/LintTableSnapshotFactory.cs create mode 100644 src/AnalyzerVs/Table/LintingErrorsSnapshot.cs create mode 100644 src/AnalyzerVs/paket.references create mode 100644 src/AnalyzerVs/source.extension.vsixmanifest rename src/{NpgsqlFSharpAnalyzer => NpgsqlFSharpAnalyzer.Core}/InformationSchema.fs (93%) create mode 100644 src/NpgsqlFSharpAnalyzer.Core/NpgsqlFSharpAnalyzer.Core.fsproj rename src/{NpgsqlFSharpAnalyzer => NpgsqlFSharpAnalyzer.Core}/SqlAnalysis.fs (99%) create mode 100644 src/NpgsqlFSharpAnalyzer.Core/SqlAnalyzer.fs rename src/{NpgsqlFSharpAnalyzer => NpgsqlFSharpAnalyzer.Core}/SyntacticAnalysis.fs (99%) create mode 100644 src/NpgsqlFSharpAnalyzer.Core/Types.fs delete mode 100644 src/NpgsqlFSharpAnalyzer/Types.fs diff --git a/NpgsqlFSharpAnalyzer.sln b/NpgsqlFSharpAnalyzer.sln index 0a6464f..b2622b0 100644 --- a/NpgsqlFSharpAnalyzer.sln +++ b/NpgsqlFSharpAnalyzer.sln @@ -29,6 +29,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution RELEASE_NOTES.md = RELEASE_NOTES.md EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FSharpLintVs", "src\AnalyzerVs\FSharpLintVs.csproj", "{37577282-1289-40DB-AD3D-24499BD09DAE}" +EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "NpgsqlFSharpAnalyzer.Core", "src\NpgsqlFSharpAnalyzer.Core\NpgsqlFSharpAnalyzer.Core.fsproj", "{5964BB56-97B8-4FAE-9933-8113DB11438D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -75,6 +79,30 @@ Global {8FC9B600-2A16-4E0C-89D7-F61F5F315F3E}.Release|x64.Build.0 = Release|Any CPU {8FC9B600-2A16-4E0C-89D7-F61F5F315F3E}.Release|x86.ActiveCfg = Release|Any CPU {8FC9B600-2A16-4E0C-89D7-F61F5F315F3E}.Release|x86.Build.0 = Release|Any CPU + {37577282-1289-40DB-AD3D-24499BD09DAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {37577282-1289-40DB-AD3D-24499BD09DAE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {37577282-1289-40DB-AD3D-24499BD09DAE}.Debug|x64.ActiveCfg = Debug|Any CPU + {37577282-1289-40DB-AD3D-24499BD09DAE}.Debug|x64.Build.0 = Debug|Any CPU + {37577282-1289-40DB-AD3D-24499BD09DAE}.Debug|x86.ActiveCfg = Debug|Any CPU + {37577282-1289-40DB-AD3D-24499BD09DAE}.Debug|x86.Build.0 = Debug|Any CPU + {37577282-1289-40DB-AD3D-24499BD09DAE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {37577282-1289-40DB-AD3D-24499BD09DAE}.Release|Any CPU.Build.0 = Release|Any CPU + {37577282-1289-40DB-AD3D-24499BD09DAE}.Release|x64.ActiveCfg = Release|Any CPU + {37577282-1289-40DB-AD3D-24499BD09DAE}.Release|x64.Build.0 = Release|Any CPU + {37577282-1289-40DB-AD3D-24499BD09DAE}.Release|x86.ActiveCfg = Release|Any CPU + {37577282-1289-40DB-AD3D-24499BD09DAE}.Release|x86.Build.0 = Release|Any CPU + {5964BB56-97B8-4FAE-9933-8113DB11438D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5964BB56-97B8-4FAE-9933-8113DB11438D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5964BB56-97B8-4FAE-9933-8113DB11438D}.Debug|x64.ActiveCfg = Debug|Any CPU + {5964BB56-97B8-4FAE-9933-8113DB11438D}.Debug|x64.Build.0 = Debug|Any CPU + {5964BB56-97B8-4FAE-9933-8113DB11438D}.Debug|x86.ActiveCfg = Debug|Any CPU + {5964BB56-97B8-4FAE-9933-8113DB11438D}.Debug|x86.Build.0 = Debug|Any CPU + {5964BB56-97B8-4FAE-9933-8113DB11438D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5964BB56-97B8-4FAE-9933-8113DB11438D}.Release|Any CPU.Build.0 = Release|Any CPU + {5964BB56-97B8-4FAE-9933-8113DB11438D}.Release|x64.ActiveCfg = Release|Any CPU + {5964BB56-97B8-4FAE-9933-8113DB11438D}.Release|x64.Build.0 = Release|Any CPU + {5964BB56-97B8-4FAE-9933-8113DB11438D}.Release|x86.ActiveCfg = Release|Any CPU + {5964BB56-97B8-4FAE-9933-8113DB11438D}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -84,6 +112,8 @@ Global {AAFC4496-746A-44AC-A4B1-CECC4ADED6CD} = {C397A34C-84F1-49E7-AEBC-2F9F2B196216} {4CA3F686-DFAB-4AAF-8004-4158E18EF24E} = {ACBEE43C-7A88-4FB1-9B06-DB064D22B29F} {8FC9B600-2A16-4E0C-89D7-F61F5F315F3E} = {4CA3F686-DFAB-4AAF-8004-4158E18EF24E} + {37577282-1289-40DB-AD3D-24499BD09DAE} = {C397A34C-84F1-49E7-AEBC-2F9F2B196216} + {5964BB56-97B8-4FAE-9933-8113DB11438D} = {C397A34C-84F1-49E7-AEBC-2F9F2B196216} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BC821061-2FB3-4ABD-9FA1-044D4C59C475} diff --git a/paket.dependencies b/paket.dependencies index 76ec5a5..f8ec8ee 100644 --- a/paket.dependencies +++ b/paket.dependencies @@ -49,4 +49,4 @@ group Docs nuget Microsoft.AspNetCore.Hosting nuget Microsoft.AspNetCore.Server.Kestrel nuget Microsoft.AspNetCore.WebSockets - nuget Dotnet.ProjInfo.Workspace.FCS + nuget Dotnet.ProjInfo.Workspace.FCS \ No newline at end of file diff --git a/src/AnalyzerVs/ContentTypeNames.cs b/src/AnalyzerVs/ContentTypeNames.cs new file mode 100644 index 0000000..e60ad0c --- /dev/null +++ b/src/AnalyzerVs/ContentTypeNames.cs @@ -0,0 +1,7 @@ +namespace FSharpLintVs +{ + public static class ContentTypeNames + { + public const string FSharpContentType = "F#"; + } +} diff --git a/src/AnalyzerVs/FSharpLintVs.csproj b/src/AnalyzerVs/FSharpLintVs.csproj new file mode 100644 index 0000000..b3263af --- /dev/null +++ b/src/AnalyzerVs/FSharpLintVs.csproj @@ -0,0 +1,534 @@ + + + + 16.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + Debug + AnyCPU + 2.0 + {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {37577282-1289-40DB-AD3D-24499BD09DAE} + Library + Properties + 8.0 + en + FSharpLintVs + FSharpLintVs + v4.8 + true + true + true + false + false + true + true + Program + $(DevEnvDir)devenv.exe + /rootsuffix Exp + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + Component + + + + + + + + + + + + + + + + SuggestionPreview.xaml + + + + + Always + true + + + Always + true + + + Designer + + + + + + + + + + + + + + + + + 0.43.0 + + + compile; build; native; contentfiles; analyzers; buildtransitive + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + 16.2.29116.78 + + + + + Always + true + + + + + Designer + MSBuild:Compile + + + + + {5964bb56-97b8-4fae-9933-8113db11438d} + NpgsqlFSharpAnalyzer.Core + + + + + + + + + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\fsharp.compiler.service\36.0.3\lib\netstandard2.0\FSharp.Compiler.Service.dll + True + True + + + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\fsharp.core\4.7.2\lib\net45\FSharp.Core.dll + True + True + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\fsharp.core\4.7.2\lib\netstandard2.0\FSharp.Core.dll + True + True + + + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.buffers\4.5.0\lib\netstandard2.0\System.Buffers.dll + True + True + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.buffers\4.5.0\ref\netstandard2.0\System.Buffers.dll + False + True + + + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.collections\4.3.0\ref\netcore50\System.Collections.dll + False + True + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.collections\4.3.0\ref\netstandard1.3\System.Collections.dll + False + True + + + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.collections.immutable\1.7.0\lib\netstandard2.0\System.Collections.Immutable.dll + True + True + + + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.diagnostics.contracts\4.3.0\lib\netcore50\System.Diagnostics.Contracts.dll + True + True + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.diagnostics.contracts\4.3.0\ref\netcore50\System.Diagnostics.Contracts.dll + False + True + + + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.diagnostics.debug\4.3.0\ref\netcore50\System.Diagnostics.Debug.dll + False + True + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.diagnostics.debug\4.3.0\ref\netstandard1.3\System.Diagnostics.Debug.dll + False + True + + + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.globalization\4.3.0\ref\netcore50\System.Globalization.dll + False + True + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.globalization\4.3.0\ref\netstandard1.3\System.Globalization.dll + False + True + + + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.io\4.3.0\ref\netcore50\System.IO.dll + False + True + + + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.linq\4.3.0\lib\netcore50\System.Linq.dll + True + True + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.linq\4.3.0\ref\netcore50\System.Linq.dll + False + True + + + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.memory\4.5.3\lib\netstandard2.0\System.Memory.dll + True + True + + + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.reflection\4.3.0\ref\netcore50\System.Reflection.dll + False + True + + + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.reflection.emit\4.7.0\lib\netcore50\System.Reflection.Emit.dll + True + True + + + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.reflection.emit.ilgeneration\4.7.0\lib\netcore50\System.Reflection.Emit.ILGeneration.dll + True + True + + + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.reflection.metadata\1.8.0\lib\netstandard2.0\System.Reflection.Metadata.dll + True + True + + + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.reflection.primitives\4.3.0\ref\netcore50\System.Reflection.Primitives.dll + False + True + + + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.reflection.typeextensions\4.7.0\lib\netcore50\System.Reflection.TypeExtensions.dll + True + True + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.reflection.typeextensions\4.7.0\lib\netstandard2.0\System.Reflection.TypeExtensions.dll + True + True + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.reflection.typeextensions\4.7.0\ref\netstandard2.0\System.Reflection.TypeExtensions.dll + False + True + + + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.resources.resourcemanager\4.3.0\ref\netcore50\System.Resources.ResourceManager.dll + False + True + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.resources.resourcemanager\4.3.0\ref\netstandard1.0\System.Resources.ResourceManager.dll + False + True + + + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.runtime\4.3.1\ref\netcore50\System.Runtime.dll + False + True + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.runtime\4.3.1\ref\netstandard1.5\System.Runtime.dll + False + True + + + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.runtime.compilerservices.unsafe\4.7.0\lib\netcoreapp2.0\System.Runtime.CompilerServices.Unsafe.dll + True + True + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.runtime.compilerservices.unsafe\4.7.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll + True + True + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.runtime.compilerservices.unsafe\4.7.0\ref\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll + False + True + + + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.runtime.extensions\4.3.1\ref\netcore50\System.Runtime.Extensions.dll + False + True + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.runtime.extensions\4.3.1\ref\netstandard1.5\System.Runtime.Extensions.dll + False + True + + + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.runtime.interopservices\4.3.0\ref\netcore50\System.Runtime.InteropServices.dll + False + True + + + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.runtime.loader\4.3.0\lib\netstandard1.5\System.Runtime.Loader.dll + True + True + + + + + + + ..\..\..\..\Users\zaidn\.nuget\packages\system.runtime.loader\4.3.0\ref\netstandard1.5\System.Runtime.Loader.dll + False + True + + + + + \ No newline at end of file diff --git a/src/AnalyzerVs/FsLintVsPackage.cs b/src/AnalyzerVs/FsLintVsPackage.cs new file mode 100644 index 0000000..1c37c87 --- /dev/null +++ b/src/AnalyzerVs/FsLintVsPackage.cs @@ -0,0 +1,77 @@ +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using EnvDTE80; +using Microsoft.VisualStudio.ComponentModelHost; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; +using Task = System.Threading.Tasks.Task; + +namespace FSharpLintVs +{ + // DO NOT REMOVE THIS MAGICAL INCANTATION NO MATTER HOW MUCH VS WARNS YOU OF DEPRECATION + // -------------------------------------------------------------------------------------- + [InstalledProductRegistration("F# Lint", "", "0.1", IconResourceID = 400)] + // -------------------------------------------------------------------------------------- + + // Package registration attributes + [PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)] + [Guid(FsLintVsPackage.PackageGuidString)] + + // Auto load only if a solution is open, this is important too + [ProvideAutoLoad(UIContextGuids80.SolutionExists, PackageAutoLoadFlags.BackgroundLoad)] + + // Options page + [ProvideOptionPage(typeof(FsLintOptionsPage), "F# Tools", "Linting", 0, 0, supportsAutomation: true)] + + public sealed partial class FsLintVsPackage : AsyncPackage + { + /// + /// FsLintVsPackage GUID string. + /// + public const string PackageGuidString = "74927147-72e8-4b47-a80d-5568807d6879"; + + private static readonly TaskCompletionSource _instance = new TaskCompletionSource(); + public static Task Instance => _instance.Task; + + public FsLintOptionsPage Options => GetDialogPage(typeof(FsLintOptionsPage)) as FsLintOptionsPage ?? new FsLintOptionsPage(); + + public IComponentModel MefHost { get; private set; } + + public IVsStatusbar Statusbar { get; private set; } + + public DTE2 Dte { get; private set; } + + public IVsSolution SolutionService { get; private set; } + + #region Package Members + + /// + /// Initialization of the package; this method is called right after the package is sited, so this is the place + /// where you can put all the initialization code that rely on services provided by VisualStudio. + /// + /// A cancellation token to monitor for initialization cancellation, which can occur when VS is shutting down. + /// A provider for progress updates. + /// A task representing the async work of package initialization, or an already completed task if there is none. Do not return null from this method. + protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress progress) + { + Trace.WriteLine("F# Lint Vs Package Loaded"); + + MefHost = await this.GetServiceAsync(); + Statusbar = await this.GetServiceAsync(); + Dte = await this.GetServiceAsync(); + SolutionService = await this.GetServiceAsync(); + + // When initialized asynchronously, the current thread may be a background thread at this point. + // Do any initialization that requires the UI thread after switching to the UI thread. + await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); + + // signal that package is ready + _instance.SetResult(this); + } + + #endregion + } +} diff --git a/src/AnalyzerVs/LintChecker.cs b/src/AnalyzerVs/LintChecker.cs new file mode 100644 index 0000000..8ac9464 --- /dev/null +++ b/src/AnalyzerVs/LintChecker.cs @@ -0,0 +1,314 @@ +using Dotnet.ProjInfo.Workspace; +using FSharp.Compiler; +using FSharp.Compiler.SourceCodeServices; +using FSharp.Compiler.Text; +using Npgsql.FSharp.Analyzers.Core; +using Microsoft.FSharp.Control; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Language.StandardClassification; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Classification; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Threading; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Controls; +using System.Windows.Threading; +using Microsoft.FSharp.Core; +using Microsoft.FSharp.Collections; + +namespace FSharpLintVs +{ + /// + /// Finds the linting errors in comments for a specific buffer. + /// + /// The lifespan of this object is tied to the lifespan of the taggers on the view. On creation of the first tagger, the LintChecker starts doing + /// work to find errors in the file. On the disposal of the last tagger, it shuts down. + /// + public class LintChecker : IDisposable + { + private readonly LintCheckerProvider _provider; + private readonly ITextBuffer _buffer; + + private ITextSnapshot _currentSnapshot; + private NormalizedSnapshotSpanCollection _dirtySpans; + + private readonly ITextDocument _document; + private readonly List _activeTaggers = new List(); + private CancellationTokenSource _cts; + + public Task Linting { get; private set; } + + public LintProjectInfo Project { get; private set; } + + public int RefCount => _activeTaggers.Count; + + public LintingErrorsSnapshot LastErrorsSnapshot { get; private set; } + + public bool HasSnapshot => LastErrorsSnapshot != null; + + public event EventHandler Updated; + + public bool IsDisposed { get; private set; } + + public LintTableSnapshotFactory Factory { get; } + + public LintChecker(LintCheckerProvider provider, ITextView textView, ITextBuffer buffer) + { + _provider = provider; + _buffer = buffer; + _currentSnapshot = buffer.CurrentSnapshot; + + // Get the name of the underlying document buffer + if (provider.TextDocumentFactoryService.TryGetTextDocument(textView.TextDataModel.DocumentBuffer, out ITextDocument document)) + { + this._document = document; + } + + this.Factory = new LintTableSnapshotFactory(new LintingErrorsSnapshot(document, version: 0)); + } + + public void AddTagger(LintTagger tagger) + { + if (RefCount == 0) + { + Initialize(); + RunLinter(); + } + + _activeTaggers.Add(tagger); + } + + public void Initialize() + { + _buffer.ChangedLowPriority += this.OnBufferChange; + + _dirtySpans = new NormalizedSnapshotSpanCollection(new SnapshotSpan(_currentSnapshot, 0, _currentSnapshot.Length)); + + _provider.AddLintChecker(this); + } + + public void RemoveTagger(LintTagger tagger) + { + _activeTaggers.Remove(tagger); + + if (RefCount== 0) + { + Dispose(); + } + } + + public void Dispose() + { + // Last tagger was disposed of. This is means there are no longer any open views on the buffer so we can safely shut down + // lint checking for that buffer. + _buffer.ChangedLowPriority -= this.OnBufferChange; + + _provider.RemoveLintChecker(this); + + IsDisposed = true; + + _buffer.Properties.RemoveProperty(typeof(LintChecker)); + } + + private void OnBufferChange(object sender, TextContentChangedEventArgs e) + { + _currentSnapshot = e.After; + + // Translate all of the old dirty spans to the new snapshot. + NormalizedSnapshotSpanCollection newDirtySpans = _dirtySpans.CloneAndTrackTo(e.After, SpanTrackingMode.EdgeInclusive); + + // Dirty all the spans that changed. + foreach (var change in e.Changes) + { + newDirtySpans = NormalizedSnapshotSpanCollection.Union(newDirtySpans, new NormalizedSnapshotSpanCollection(e.After, change.NewSpan)); + } + + // Translate all the linting errors to the new snapshot (and remove anything that is a dirty region since we will need to check that again). + var oldErrors = this.Factory.CurrentSnapshot; + var newErrors = new LintingErrorsSnapshot(oldErrors.Document, oldErrors.VersionNumber + 1); + + // Copy all of the old errors to the new errors unless the error was affected by the text change + foreach (var error in oldErrors.Errors) + { + Debug.Assert(error.NextIndex == -1); + + var newError = LintError.CloneAndTranslateTo(error, e.After); + + if (newError != null) + { + Debug.Assert(newError.Span.Length == error.Span.Length); + + error.NextIndex = newErrors.Errors.Count; + newErrors.Errors.Add(newError); + } + } + + this.UpdateLintingErrors(newErrors); + + _dirtySpans = newDirtySpans; + + // Start processing the dirty spans (which no-ops if we're already doing it). + if (_dirtySpans.Count != 0) + { + this.RunLinter(); + } + } + + private void RunLinter() + { + // We're assuming we will only be called from the UI thread so there should be no issues with race conditions. + _cts?.Cancel(); + _cts = new CancellationTokenSource(); + this.Linting = Task.Run(() => DoUpdateAsync()); + } + + public async Task DoUpdateAsync() + { + if (IsDisposed) + return; + + var buffer = _currentSnapshot; + var path = _document.FilePath; + + + // replace with user token + var token = _cts.Token; + var instance = await FsLintVsPackage.Instance.WithCancellation(token); + + // this acts as a throttle + await Task.Delay(200, token); + + if (Project == null) + { + await instance.JoinableTaskFactory.SwitchToMainThreadAsync(); + var project = instance.Dte.Solution.FindProjectItem(path)?.ContainingProject; + + if (project == null) + return; + + if (instance.SolutionService.GetProjectOfUniqueName(project.UniqueName, out var vsHierarchy) != VSConstants.S_OK) + return; + + if (instance.SolutionService.GetGuidOfProject(vsHierarchy, out var guid) != VSConstants.S_OK) + return; + + Project = new LintProjectInfo(project.Name, guid, vsHierarchy); + } + + await Task.Yield(); + + var defaults = FSharpParsingOptions.Default; + var parseOpts = new FSharpParsingOptions( + sourceFiles: new string[] { path }, + conditionalCompilationDefines: defaults.ConditionalCompilationDefines, + errorSeverityOptions: defaults.ErrorSeverityOptions, + isInteractive: defaults.IsInteractive, + lightSyntax: defaults.LightSyntax, + compilingFsLib: defaults.CompilingFsLib, + isExe: defaults.IsExe + ); + + var source = _currentSnapshot.GetText(); + var sourceText = SourceText.ofString(source); + var parseAsync = _provider.CheckerInstance.ParseFile(path, sourceText, parseOpts, null); + var parseResults = await FSharpAsync.StartAsTask(parseAsync, null, token); + if (parseResults.ParseHadErrors) + { + return; + } + + var connectionString = SqlAnalyzer.tryFindConnectionString(path); + + if (String.IsNullOrWhiteSpace(connectionString)) + { + return; + } + + var loadedSchema = SqlAnalysis.databaseSchema(connectionString); + + if (loadedSchema.IsError) + { + return; + } + + var context = new SpecializedContext( + fileName: path, + content: source.Split('\n'), + parseTree: parseResults.ParseTree.Value, + typedTree: null, + symbols: FSharpList.Empty, + getAllEntities: FSharpFunc>.FromConverter( + new Converter>(value => FSharpList.Empty) + ) + ); + + var operations = SyntacticAnalysis.findSqlOperations(context).ToList(); + var databaseSchema = loadedSchema.ResultValue; + + var foundErrors = + from operation in operations + from message in SqlAnalysis.analyzeOperation(operation, connectionString, databaseSchema) + select message; + + var oldLintingErrors = this.Factory.CurrentSnapshot; + var newLintErrors = new LintingErrorsSnapshot(_document, oldLintingErrors.VersionNumber + 1); + + foreach (var error in foundErrors) + { + var span = RangeToSpan(error.Range, buffer); + newLintErrors.Errors.Add(new LintError(span, error, Project)); + } + + await instance.JoinableTaskFactory.SwitchToMainThreadAsync(); + if (token.IsCancellationRequested) + return; + + UpdateLintingErrors(newLintErrors); + } + + public static SnapshotSpan RangeToSpan(Range.range fsrange, ITextSnapshot textSnapshot) + { + var from = fsrange.StartLine - 1; + ITextSnapshotLine anchor = textSnapshot.GetLineFromLineNumber(from); + var start = anchor.Start.Position + fsrange.StartColumn; + var to = fsrange.EndLine - 1; + var end = textSnapshot.GetLineFromLineNumber(to).Start.Position + fsrange.EndColumn; + return new SnapshotSpan(textSnapshot, new Span(start, end - start)); + } + + public static ITrackingSpan RangeToTrackingSpan(Range.range fsrange, ITextSnapshot textSnapshot) + { + var from = fsrange.StartLine - 1; + ITextSnapshotLine anchor = textSnapshot.GetLineFromLineNumber(from); + var start = anchor.Start.Position + fsrange.StartColumn; + var to = fsrange.EndLine - 1; + var end = textSnapshot.GetLineFromLineNumber(to).Start.Position + fsrange.EndColumn; + return textSnapshot.CreateTrackingSpan(start, end - start, SpanTrackingMode.EdgeExclusive); + } + + private void UpdateLintingErrors(LintingErrorsSnapshot lintSnapshot) + { + // Tell our factory to snap to a new snapshot. + this.Factory.UpdateErrors(lintSnapshot); + + // Tell the provider to mark all the sinks dirty (so, as a side-effect, they will start an update pass that will get the new snapshot + // from the factory). + _provider.NotifyAllSinks(); + + foreach (var tagger in _activeTaggers) + { + tagger.UpdateErrors(_currentSnapshot, lintSnapshot); + } + + this.LastErrorsSnapshot = lintSnapshot; + Updated?.Invoke(this, EventArgs.Empty); + } + + } +} diff --git a/src/AnalyzerVs/LintCheckerProvider.cs b/src/AnalyzerVs/LintCheckerProvider.cs new file mode 100644 index 0000000..e7f8a0e --- /dev/null +++ b/src/AnalyzerVs/LintCheckerProvider.cs @@ -0,0 +1,181 @@ +using FSharp.Compiler.SourceCodeServices; +using FSharpLintVs; +using Microsoft.VisualStudio.Shell.Interop; +using Microsoft.VisualStudio.Shell.TableControl; +using Microsoft.VisualStudio.Shell.TableManager; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Classification; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Text.Operations; +using Microsoft.VisualStudio.Text.Tagging; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Diagnostics; + +namespace FSharpLintVs +{ + /// + /// Factory for the and . + /// There will be only one instance of this class created. + /// + [Export(typeof(IViewTaggerProvider))] + [TagType(typeof(IErrorTag))] + [ContentType(ContentTypeNames.FSharpContentType)] + [TextViewRole(PredefinedTextViewRoles.Document)] + [TextViewRole(PredefinedTextViewRoles.Analyzable)] + public sealed class LintCheckerProvider : IViewTaggerProvider, ITableDataSource + { + public readonly ITableManager ErrorTableManager; + public readonly ITextDocumentFactoryService TextDocumentFactoryService; + + public const string LintCheckerDataSource = "LintChecker"; + + private readonly List _managers = new List(); // Also used for locks + private readonly List _lintCheckers = new List(); + + [ImportingConstructor] + public LintCheckerProvider + ( + [Import] ITableManagerProvider provider, + [Import] ITextDocumentFactoryService textDocumentFactoryService + ) + { + this.TextDocumentFactoryService = textDocumentFactoryService; + this.ErrorTableManager = provider.GetTableManager(StandardTables.ErrorsTable); + this.ErrorTableManager.AddSource(this, + StandardTableColumnDefinitions.DetailsExpander, + StandardTableColumnDefinitions.ErrorSeverity, + StandardTableColumnDefinitions.ErrorCode, + StandardTableColumnDefinitions.ErrorSource, + StandardTableColumnDefinitions.BuildTool, + StandardTableColumnDefinitions.ErrorSource, + StandardTableColumnDefinitions.ErrorCategory, + StandardTableColumnDefinitions.Text, + StandardTableColumnDefinitions.DocumentName, + StandardTableColumnDefinitions.Line, + StandardTableColumnDefinitions.Column, + StandardTableColumnDefinitions.ProjectName + ); + } + + /// + /// Create a tagger that does lint checking on the view/buffer combination. + /// + public ITagger CreateTagger(ITextView textView, ITextBuffer buffer) where T : ITag + { + ITagger tagger = null; + + // Only attempt to lint check on the view's edit buffer (and multiple views could have that buffer open simultaneously so + // only create one instance of the lint checker. + if ((buffer == textView.TextBuffer) && (typeof(T) == typeof(IErrorTag))) + { + var lintChecker = buffer.Properties.GetOrCreateSingletonProperty(typeof(LintChecker), () => new LintChecker(this, textView, buffer)); + + // This is a thin wrapper around the LintChecker that can be disposed of without shutting down the LintChecker + // (unless it was the last tagger on the lint checker). + tagger = new LintTagger(lintChecker) as ITagger; + } + + return tagger; + } + + #region ITableDataSource members + + // This string should, in general, be localized since it is what would be displayed in any UI that lets the end user pick + // which ITableDataSources should be subscribed to by an instance of the table control. It really isn't needed for the error + // list however because it autosubscribes to all the ITableDataSources. + public string DisplayName => "F# Lint"; + + public string Identifier => LintCheckerDataSource; + + public string SourceTypeIdentifier => StandardTableDataSources.ErrorTableDataSource; + + // This is the observer pattern + public IDisposable Subscribe(ITableDataSink sink) + { + // This method is called to each consumer interested in errors. In general, there will be only a single consumer (the error list tool window) + // but it is always possible for 3rd parties to write code that will want to subscribe. + return new SubscriptionManager(this, sink); + } + #endregion + + #region Checker + + private Lazy _checker = new Lazy(() => + FSharpChecker.Create(null, null, null, null, null, null, null, null) + ); + + public FSharpChecker CheckerInstance => _checker.Value; + + #endregion + + public void AddSinkManager(SubscriptionManager manager) + { + // This call can, in theory, happen from any thread so be appropriately thread safe. + // In practice, it will probably be called only once from the UI thread (by the error list tool window). + lock (_managers) + { + _managers.Add(manager); + + // Add the pre-existing lint checkers to the manager. + foreach (var checker in _lintCheckers) + { + manager.Add(checker); + } + } + } + + public void RemoveSinkManager(SubscriptionManager manager) + { + // This call can, in theory, happen from any thread so be appropriately thread safe. + // In practice, it will probably be called only once from the UI thread (by the error list tool window). + lock (_managers) + { + _managers.Remove(manager); + } + } + + public void AddLintChecker(LintChecker lintChecker) + { + // This call will always happen on the UI thread (it is a side-effect of adding or removing the 1st/last tagger). + lock (_managers) + { + _lintCheckers.Add(lintChecker); + + // Tell the preexisting managers about the new lint checker + foreach (var manager in _managers) + { + manager.Add(lintChecker); + } + } + } + + public void RemoveLintChecker(LintChecker lintChecker) + { + // This call will always happen on the UI thread (it is a side-effect of adding or removing the 1st/last tagger). + lock (_managers) + { + _lintCheckers.Remove(lintChecker); + + foreach (var manager in _managers) + { + manager.Remove(lintChecker); + } + } + } + + public void NotifyAllSinks() + { + lock (_managers) + { + foreach (var manager in _managers) + { + manager.Notify(); + } + } + } + + } +} diff --git a/src/AnalyzerVs/LintError.cs b/src/AnalyzerVs/LintError.cs new file mode 100644 index 0000000..70a285a --- /dev/null +++ b/src/AnalyzerVs/LintError.cs @@ -0,0 +1,76 @@ +using Npgsql.FSharp.Analyzers.Core; +using Microsoft.FSharp.Core; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Utilities; +using System.Collections.Generic; +using System.Text; +using System.Linq; + +namespace FSharpLintVs +{ + public class LintError + { + public readonly SnapshotSpan Span; + public readonly LintProjectInfo Project; + private readonly Message LintWarning; + + public int NextIndex = -1; + + public string Tooltip => $"{LintWarning.Code}: {LintWarning.Message}"; + + public string Identifier => LintWarning.Type; + + public string Name => LintWarning.Code; + + public string Message => LintWarning.Message; + + public string HelpUrl => $"https://fsprojects.github.io/FSharpLint/how-tos/rules/{Identifier}.html"; + + public bool HasSuggestedFix => LintWarning.Fixes.Any(); + + public Fix GetSuggestedFix() => LintWarning.Fixes.First(); + + public int Line => LintWarning.Range.StartLine - 1; + + public int Column => LintWarning.Range.StartColumn; + + public string ErrorText => LintWarning.Message; + + public string ReplacementText + { + get + { + var fix = GetSuggestedFix(); + if (fix == null) + return ""; + + var startColumn = fix.FromRange.StartColumn; + return ErrorText.Remove(startColumn, fix.FromRange.EndColumn - startColumn).Insert(startColumn, fix.ToText); + } + } + + public LintError(SnapshotSpan span, Message lintWarning, LintProjectInfo project) + { + this.Span = span; + this.LintWarning = lintWarning; + this.Project = project; + } + + public static LintError Clone(LintError error) + { + return new LintError(error.Span, error.LintWarning, error.Project); + } + + public static LintError CloneAndTranslateTo(LintError error, ITextSnapshot newSnapshot) + { + var newSpan = error.Span.TranslateTo(newSnapshot, SpanTrackingMode.EdgeExclusive); + + // We want to only translate the error if the length of the error span did not change (if it did change, it would imply that + // there was some text edit inside the error and, therefore, that the error is no longer valid). + return (newSpan.Length == error.Span.Length) + ? new LintError(newSpan, error.LintWarning, error.Project) + : null; + } + + } +} diff --git a/src/AnalyzerVs/LintProjectInfo.cs b/src/AnalyzerVs/LintProjectInfo.cs new file mode 100644 index 0000000..9e9c2ab --- /dev/null +++ b/src/AnalyzerVs/LintProjectInfo.cs @@ -0,0 +1,29 @@ +using Microsoft.VisualStudio.Shell.Interop; +using System; + +namespace FSharpLintVs +{ + public class LintProjectInfo + { + public string ProjectName { get; } + + + // Performance will be improved if you "prebox" your System.Guid by, + // in your Microsoft.VisualStudio.Shell.TableManager.ITableEntry + // or Microsoft.VisualStudio.Shell.TableManager.ITableEntriesSnapshot, having a + // member variable: + // private object boxedProjectGuid = projectGuid; + // and returning boxedProjectGuid instead of projectGuid. + public object ProjectGuid { get; } + + public IVsHierarchy Hierarchy { get; } + + public LintProjectInfo(string projectName, Guid projectGuid, IVsHierarchy hierarchy) + { + ProjectName = projectName; + ProjectGuid = projectGuid; + Hierarchy = hierarchy; + } + + } +} diff --git a/src/AnalyzerVs/LintTagger.cs b/src/AnalyzerVs/LintTagger.cs new file mode 100644 index 0000000..0fcd797 --- /dev/null +++ b/src/AnalyzerVs/LintTagger.cs @@ -0,0 +1,73 @@ +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Adornments; +using Microsoft.VisualStudio.Text.Tagging; +using System; +using System.Collections.Generic; + +namespace FSharpLintVs +{ + public class LintTagger : ITagger, IDisposable + { + private readonly LintChecker _lintChecker; + private LintingErrorsSnapshot _snapshot; + + public LintTagger(LintChecker lintChecker) + { + _lintChecker = lintChecker; + _snapshot = lintChecker.LastErrorsSnapshot; + + lintChecker.AddTagger(this); + } + + public event EventHandler TagsChanged; + + public void UpdateErrors(ITextSnapshot currentSnapshot, LintingErrorsSnapshot lintingErrors) + { + var oldLintingErrors = _snapshot; + _snapshot = lintingErrors; + + + // Raise a single tags changed event over the span that could have been affected by the change in the errors. + var start = int.MaxValue; + var end = int.MinValue; + + if (oldLintingErrors?.Errors.Count > 0) + { + start = oldLintingErrors.Errors[0].Span.Start.TranslateTo(currentSnapshot, PointTrackingMode.Negative); + end = oldLintingErrors.Errors[oldLintingErrors.Errors.Count - 1].Span.End.TranslateTo(currentSnapshot, PointTrackingMode.Positive); + } + + if (lintingErrors.Count > 0) + { + start = Math.Min(start, lintingErrors.Errors[0].Span.Start.Position); + end = Math.Max(end, lintingErrors.Errors[lintingErrors.Errors.Count - 1].Span.End.Position); + } + + if (start < end) + { + TagsChanged?.Invoke(this, new SnapshotSpanEventArgs(new SnapshotSpan(currentSnapshot, Span.FromBounds(start, end)))); + } + } + + public IEnumerable> GetTags(NormalizedSnapshotSpanCollection spans) + { + if (_snapshot != null) + { + foreach (var error in _snapshot.Errors) + { + if (spans.IntersectsWith(error.Span)) + { + yield return new TagSpan(error.Span, new ErrorTag(PredefinedErrorTypeNames.Warning, error.Tooltip) { }); + } + } + } + } + + public void Dispose() + { + // Called when the tagger is no longer needed (generally when the ITextView is closed). + _lintChecker.RemoveTagger(this); + } + + } +} diff --git a/src/AnalyzerVs/Options/FsLintOptionsPage.cs b/src/AnalyzerVs/Options/FsLintOptionsPage.cs new file mode 100644 index 0000000..714efeb --- /dev/null +++ b/src/AnalyzerVs/Options/FsLintOptionsPage.cs @@ -0,0 +1,14 @@ +using System; +using System.ComponentModel; +using Microsoft.VisualStudio.Shell; +using System.Runtime.InteropServices; + +namespace FSharpLintVs +{ + [Guid(GuidString)] + public class FsLintOptionsPage : DialogPage + { + public const string GuidString = "74927147-72e8-4b47-a70d-5568807d6879"; + + } +} diff --git a/src/AnalyzerVs/Properties/AssemblyInfo.cs b/src/AnalyzerVs/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..f0de40b --- /dev/null +++ b/src/AnalyzerVs/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("FsLintVs")] +[assembly: AssemblyDescription("F# Linter Extension for Visual Studio")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("asti")] +[assembly: AssemblyProduct("FsLintVs")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("0.2.0.0")] +[assembly: AssemblyFileVersion("0.2.0.0")] diff --git a/src/AnalyzerVs/Resources/License.txt b/src/AnalyzerVs/Resources/License.txt new file mode 100644 index 0000000..7844c89 --- /dev/null +++ b/src/AnalyzerVs/Resources/License.txt @@ -0,0 +1,8 @@ +Copyright 2020 Asti + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/src/AnalyzerVs/Resources/ReleaseNotes.html b/src/AnalyzerVs/Resources/ReleaseNotes.html new file mode 100644 index 0000000000000000000000000000000000000000..a6a87646d1577c5f3add3a87166e63b62beee89b GIT binary patch literal 1846 zcmcJQ-Afx$5XI-Y(Es7$lZ6`d1y!&CMFgSkLsNa%tcjs(5_UI2|M|ARbEoTW+@wj1 z687Wny>sTwoSDh5pC@*29Sb(K#6H@dWp-yN*Nx@e4{T<0D|pM<8`#&C-C$pyc2Ddu zA`R@Vy)mJ7Yp89I`dr7Av>vg6vjHe3$PjoCbDgOP(nl0-PpXQ#j>uEev6` z*}H{V!R`U8_8(+NaAbc!$667NIGfs!XjkEni6-OQEMoQT$lk}*ocpDHiqS9dF|zNG zc^&@{o)!1?(RWs&@4Q;{j$CKw?^m`UgBcMdL>TOmJSuaZfrR&h49tlm|Bv`oAFk|n zRZn3cf1k&tXbbAkYoTMk2HrNUdQUpJt<)^5vaYi8Dr3pX za&i! zj2ahlXU5(Xf2wMo+sr1!+!tV~!zQfMaq1S2Wy#lM1LuF&CfGi6=K~Rr@zSN&RF&@< z_}jFqCdx}rld6WqQ|zQ+pWiW=ZnAXc)L#j4XkM23Kg9LA+$zgbbjZD~p1Q~Jd~$8e zKs8l%nJAZdRV_~8r5akD=+AvSkH4wgtIgo`*5}mSh&p{BD>FO?yWmU4TA2zB#ogzS m)A}FMq*jG1SG(A)o^iV&o*u#4#83U94)Kn4UeC|gRrn1DrW9@f literal 0 HcmV?d00001 diff --git a/src/AnalyzerVs/Resources/logo.png b/src/AnalyzerVs/Resources/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..000b707cf49c5a510879a4d68fce4e67e377a8a8 GIT binary patch literal 24590 zcmbTe2|U#8_c#8TG0Kz>h3;r3ks{eDTbd~1%0pO4EVp zzTf^5@uK7YKzC2@Gz1;S1$x>$TygZpUUYPJ@z9oEt3&j5#2(y#NWnq*z(K5<#(w2Pss}VQ_F+|&l+_iL)D@Lg6_gKY9#GO$ zQNjNGpA>kT_a!IIv$`k#ei!(cw$x=`Ur$X%#ejf-{Q;``iQdkN${HFPib^VqDk=)# z2?d`Z4`2I01rMKH|IDE4=;Pq+;_2%`^uWS1+FvC4`D#mnm9A~U-SgjRJ$(Ka6A+kU zpuMM}@_r?FOaDA*Wc2_4sJr{WPy6_ub^PD!{Vyl>F$?l^R6OhGL-g}@a0HL<`sYr{`s&FVW{R z@xKwmzrX%h6rP$o-j4RZL~k=9(e0m8KK;)uSREbsR5h@BEL=P;5d(bo!h8CAjH9l- zucNk;c!U9@!;yZz<6DvgC8uxf5u+|hfB0W5_%<*Bz|`Kr zMSs6?Efa#yzt`72Y8Kct@dh1uZaAc1SwEP#bLWTm&F$^Ri9dH9D*rU9?S3=ZdnT#B z+r!7GM>ET&%f)p#DPy$K@4KmpgmdxdJ$SvQ==l5F_`B_P_u8q7?{e4IL+(T&QF@p0 zddFsJWWBn++HO}+D8Ch^okx5#71ZfaWz{G#QPwrJ!lmq;T$&q)Q7ZSi1pI{zKGt9h z;)B1#!k@_Sr&TQbfBzvCo`MX2`Y$IUHz9?@#6A!=V`+4U!K(Zf)61kClN8)zk|30( zyXS5I3Zj00i+TN{3{tbzS=shSbMwfyp%w^2L6DR<$A6;O#iC+=X^2%6{chldvwCR? z<4b7y($v+ml$$893qAz%Y+vhW%1 z3#Pvjyp-fSnUGi#nEhcm>kKDAQV+-!h_>OxAUB-mx1csvHASH;bt`fv9x7MRGdLKd z&w4ABQjk^*uKddLkernG+%Ssw%A;u;&d_7oVfN7W0PY{m2dy8+jlCu_OG?C6%pZ~E zjF4u}nNkQKIwT~NOygdm&H2f&xzlkX+!a!Pyt+qj4V%VX2f|#dO*t?!c1jNotO2EkGOyzB~NmB3;cp@w$|Y!T93;@5CRX5Z#(B_ zDUGm+JGGa=y@+L>GeZQbI!rb?j~ljYK%eV{$kj39M+cWmZkseORV+_cPBmsjuU-jz z7XLB}lS52QK0NzHO_prDCIsE$Y0^M`FeXLiPkM?RBSoB#lnk-MrJ$)uJhbC%e#FLS zPZtXWudQ$t*P*ajg!6t;Ok(^&Zk$42p4cN;pAgU;Jgb@z6#XbbwHCP9Xk3lh4{oa&m7d;+1QQ%h@dJ*#~B6~{HlTClM6 zQc(E7Is$#3`>b=`WP>PYrx4`FH=wvqgiJ=6nVBcWPo7G=&}Z&r0RLc?`3C_eR4Qg# zRQxm&UU6Q=<)7p5gpppN@b8}e5-K}bCS$5c>xVF_Y;lb(_ zz#F?NR@Ns?VC0cPQRMRXo$@r&Lfr87{Z5yKTd%J^<2lYW`6|b?f3W!B2E5f5S#SJZ zPmDeJu{0CDDmp04d@+YXYV_k2$w6}E%Ki-3QIDsw8dDvne$Gd>a-KtT)2lLpZtZ2i zP=F9<&x*EPE4!6e-Lxxqpc5a2zuGA$jP_&p&>j8!eZ5n`lXr3D7I4ffK93$qA!)l~b%1 zDN0ZLI8K|%+l2=vMs0sz8~>~m7wORRdK2s(|F&8#IE2=}F{LJtUD?-)#;?B3@HY3}^UKR0 zs-W*tWc4p4obGC$fTZ4PtICdyXb2OD2G)eV!ip3Lap!)>1ZMy4v^l3}KM=*8iVp<( z(~^TBSN=3_)kJ&lgwKuK&cNJF4|Uo~?&m&Lu`s+y2T>v6g6B-0J#-H3-p0)H40D~YifLR{K+7bRb06l@;U0}PB? zFkP(f+q_yHkOTJH&Lex(XZzD?Dl+5)@>f?4#ZZ1DQ=`c@WpTZgdq^FLwL1t3t4I5^ zY&!DeQ_2?jxA)u5V=^SI=Yu0#Oke2Z)m9&9@E*j(zFAS&1!tc2SGXZ!Mpm$;*_Jgf5a7(aHr$tW(xHiP0x=Rp{)O@y`!RYy zzIm2VR;{)Fig4@gRY`mi;D)+$FI#Ym(Re(vIrdrOvzW30iw8DFVt&bx;_5uQZ>9z3 z9@X;UN$A&Rwh6d{yZj7vEPe(JnrC*xCk;EUG>gTP7lR4%8^J6zx&0{#vGGd=HYY=r z*Jjwo{t&@8IS~o5iexo(&-r!4t37OvztHQIrx#5&mIihUR+AP(IW$yIz9Qlv!*&z} z4xqiW{TX-V%aczX?gx3pjPZhza;xYiEysN-K2z}+NPNI*qO4d=WvJ%tm$NZBXuPa2 zP!yni5zNS}a!L#;)dDFjnO0O=H2vU(kL}(o`&*8!Ex2woXQ`aj)HGjF44ZHI^UABh zd=(AhbK;je{BMU%|p3!X8?|JdlP zt_q*eRLh@m*#lYcTZC_hgr5tH=H(2`fN8~2eZ^3Oo zaTLaMRlaL7aOm*frO~9UUT|i6WPnHUZW)?NiGDK@&}ZAVb?x^}+cmE({~ zS0z57(^6kDPaDkNp!>eolGmkslEv0u1U7_sLcdlxnpEYvG;+#$=?VxDRQ{gi{G#>6 zCJcfvL^k#HtXp&Y{r0_gQ5VcS{9NKRC8+v0U;zo;jG;UUUfu>;PL7ceQ?N7adj{fy0t#|v5pxbuU6^ct~p#msf_}R>}zJGTR9y! zp$9Z#UOF|uJm2@KQ;)pk=fR*bW8nD75TyHJx}t6#_$hupe45UIPBrsWElCTs+wZ@+ zt?gI}!})pZ_Wb-w=%OLgYP(f-rdHc-c?zB12-$AKvrPbO27C4&Cxiwoek|PjrQKGm zKK@Aht9%wP_z_?=kkE5l3cMe=?)Tldt2@r&>f`5Kj~abJFfbcN+BFgIY9V`mQV)j@ zZx#Vev!b!>$>Yj_vYN3Qk;l1=)k7u=-J;Y^w77wJGBgp-j01YVH@%~Ls(ehb9!H|W zc&@R-AOs{H%IdvE%1ZG9AOkO`Qxl=RgYco|embQkx9QvSXh;xtc+`(_T(28I8SK`f z3wzteyt>#g8Z&n64e;nd;c*hw4X|H1A;d8Q#=ch*VbD}9=9ru0Rrq^mla*|0GOXK> zjv(phZruIFT~Nj->Xkj^d!!eKI&az;sEkq>s^Qy@YgdxC zpACq)Rs-X?{+eTg-pZ2>vd;ta{wRg$Qrpq1NwWTvKbU|j-31?!5Lm!(!HPBTmI+w? zVU$THqsEI^qBy^+s{6dLv}G4|)%Kw} zLgnO{Ixe~nJXI_bWhWABe640a??%AT-im}>>})>vpgr&V z-3j4ce`ud}t<%HlTK85>L?3)qb{({oiIB~Zp*|JZv$fdJn}eo7!?q$J^$2zv0s%Fi zK77DO)91>_R8+W&sFK9@#Fy`~q89?iP;Q)IG@31o>D}YQ}fIzdcEY7#Lh* zah&c6VmLlXZyV>QE}@tEXRiq1VjTu)cV41G=FaaQ-%W-uDK0(uFkE>9R;#b!IKveo zXk;AqD@E(id4tXyT~%-LH^8bJwU_;1ob3Y4&~5~kv`-@@OOKiZTQUQu`)bwKUCL(1 zGs7Xg5?aq#$a(+P;ijepTzY!-+~a(af#bk6K_%fh;Km`3od}sY#iXat;ty38<&4(k zi;&@$XP~)uz01X)1d)(V6#46PaouQhP&A0!?;S*(R$NuG(~CSvY~_E3>83CJkeVQ( zLPAd2>}>#u>`>j&5^3cb<(FKY#^kpuoa2QBEHoa2gI$P_99qx!PS}-Ajx^`R6xed> za9dIhR*e_$X3lY&z6s$+q*JqMvwnQOuTgNpwJIqu8k)N~%1}e`K@F!^szZ_B37OQq zqPe@%@to;v_3!v~WFa(+E_V!A3s;s+f&K~|L62N^El5sywB+iwvZ%AV2Gtnc$t5XB z$kxr_cU{NVKJ|mDeg$B2zdOX9Cn#9sca%ej|JB7&6qs>%{N0MZe@Ro zigWl;Brs^$Th`euuI^&X8XPP6yxX1<I z;;*b$9!5}ni%!bf(YeDSJN?%e4=G+|S*^y|IZpm8))aQ&Ll%{ax6e~agA zpmHtDEZEORw)50>s4AIP)@EN=knc(dQK!yI+aZOq*HOTaCY4mC>}jF> zos0m&#j<+ZIhY{wqI{*%ik34pxbIv&&LW4Mc!G5{5`#z9Zi|A#c$y-2X&g=3qY)J7 zKVL@(0HMmNxC%W60S?Ysa8!L`NG0HPTW=T`huBIapuVT;<0&AE#)hMk z6tv^C>*G1DJ^_s~Hh((|bUi6)&Bz{3%g z-W}~vJLU4tL~G-for|TOyi0(5rC={%$6-1rQ!d1i(mUq`JDze+KYM|i(5MQ!h)srE zq*Jr2vRQDVa^_i{lo8Z!II+h*5RAee9c;OUi%v_Nz=+Qjh;jTl&)t><=MQhvlqGi{ zy!G(zM(&@cA~R~v_L-Yvm;N>myC2NV2_lCnm^&kQizF@UHfpi{l`zxqd5Q?tlYBt< zw1u_BlGFR|pMayTOyhb&nEhZ^PqFL=?xaJD%6qSuQ#6M#@6n`Pqp0tPm7|Qw62eg< zLJ#I1#Eg03&-(<43X_2YG2;l`rg6OukH?hP6YQc>F5f08p_TlR?d~@*=^{Y-r3VfW z&S@dU{xXcbTdM)WBls;ZVQy%FVH=edw}-ihx00WXagKwrM%mY2*pmEt|r zQ&|s!@Aa?`B6kD-+)H@O>~dNjk6U`+8%)=OGYkEq2Spn#3iW(gs&^>Heqe{oBhv z+f`(7nfw0E-5vn4rwJD4;k3o4WC7w7=Sb* z3C`oPm2f%4Qp9z)?fV)HX`+g50*T$%e!r2KdiJfzGWr`Cr6fUysC()GMd(~k(MNk{ zr)=w73_pwPRz7`kHRUQ#5;U(hE%mG2T?RvlxIHV!)IGZ4GYDRq=`R@tlD{1?j6$V$ zB5#@$&q|4I8O9mvJ%47^0$u-sj{+y z?lxDieLh8qoJzS@7in;qt48XNE%^{J22?hA_k%1avi z6XbfF8*v?|9ux*MiKO>zBjc!Voa^bKu3LX?`m<5Vcw;A?YTIQ~^z>ULn#In=#*_#sC2f{~hXOco6my-NR%Yxiq!hwK_ z_Sgfqn)xdW7yYI?26A|SW4j4l_?9PIb{KrJWhMfu={7S((k@-UkPkwI1Oc)jvYfIg z&#lzBH&?P!U)J8jV!uLe!!hIqx!mGB|=bWgC4nS@EqOy zu${0THS1nxWV3GurE_v}Pn$GWLgylIe|A+&%1Ja=mXBm=!HF>##Hk`Pmv|GEu70Q| zTxGTpLVk-;s&@UE?2UG5iw@hv3=v(BAbLW(mTjhj3t#9n9^*!Va^2I0S7QM%l zQ4M3Kw*r&DCBuGDveH50@^&sJ9%9d(Tso09Ey%w;%Y6nX!A&QI4#&|s3n}y?LmPpO zodf_t%IBl5uOk^GHlir+-)h1ZbzV00*Ys@>nyO}HW%XbUNDER$03PPA;-N$Lui>YB zQ(2)r&D+k%amA*@eS!-PKP-}Yg=9VkMF?FwjYn0fdyL#4ah-qt$6bi@LC4Gtrwrr# zDL3_-;AGA7KwR(q1NKS=lussh$)wk@OS~JovZYLlmvpHdM09EjS#%5e`M2fEJXYU(m&ZbYkV;dlJj7dR7Awp0iB0dCD#|1x|Rnh6+Q=+Z{+ zcEzdnlT`~|gM*)M;Y7kox8~aOcD=t@S~dS2=V_qBa*`S4V{+;1pQy*+vPKy zn}Y|BIk=Pq`Qm}nnub%nl0iZP>@miw7bon%Ih2PqPr>*d`>yTU%k7Au1TyB83F4=B z$Ox0EQ#+3?@7SicF`=OWUn!kh_B{P+m8yI3^lzujNZ5Y9nt>Egb#K+p5GUQhWNwr^ zNuL+XT;@9@3pRk3NiE5GVf=_p5bfBC>0G5Fkak0B*xE&$+TMIK#3Ml|+lW=|$T9?6 z|4m7mCa0sq_S+rACe1BYaf$cf@%6qiyMs_V&RXBwA7>PLN-uSy;Njv)&pHBS*g5qZ zM^prIkfo|CpSF=ydfRIxix)*ReP1V@RS~OMr3vRl#^IgIk?vRyk}A`Wk+KOd?mP$M zwg6eTqNAP$h8qP|YrFfXig9-j8*n^qWT_9p=A2%E+)T}Dkoa^0quycCXRbEX!vWCU z?(np`TNkpUsXdGn?rMYl|DJUA>h!25@T?Q?5AS&{hUV$6U5&V zn_S8%?|7-*Xr+9Ckz^6-5yV-2axRUyk5_Y(r$R-Q{m_ft+4Y!V=cUCn-!Wy?3x~tJpea^;{oceNF~K z-0>c4nXk@Ue?OdNr z_J~$PvX?P*5^X4l(0Vv^z9`>w25E%s$=i+K!#|PxPXy1K#_eV&vUR<)2t;5HA431M zJ!%HbSC|4~-{vQ0kiu>kTOuO6YR@s74^L>h?FA7%)^AywI(8Gbv>wq=$aNs23(^&>_uWOt&Y%)xmx&w(u7opipQu<5;C=?YKqGH!D| z;PUKrg;Q|`;^-*;5AJBGYV`$?K`pK|K-lBss9QgmA3}Q4ki@7w2^3Vqaem1py+eyf zp<}xdE4$ZmKn5qPjr+3=#18)#b#or51|MPYy&FkHl?sgE75f1LGY@a@BHHd^>aS#S zv`nVTR&-!lU!T``RyfZ~P}0EqDo#=7bMG%23UjKALXn0m?MkzEnaN{ffuT}8-~>RP0~ zXa?yNo-tl!eo+KW&R7!{oPQqQyhe{11k>AT>3Jv7Q!OLgIatQ zh_^ipW+Eftt-7LLk3!GMs6ZRrIfX`|fiU`2ZuVhS1)u(3W912^DzL*yU{1OB3Ukh$ z<2<^&ykI>hHi{%4ZIDC<<{F zZUqxzGB+9e`40@sAdKdWwh}Kj#b4<0)#z!|WUrL2(%6x2 zfaCdibFId-9Rv!TY(Pwlfa1H*3>e3+%053P>&QA;HGzp{08`lVvjM*{1~m&roko6l z&yS6dAEjuX@fq7y0>rMwYV3X8oKjASsHfDF6}#Fte;qYo4Ijs{-K}_E9l?#=Dy(*} zPsSmI{w(O-nBSr7A$lMp;`+2cIkT-#Q_bfO(I@}clqlyp`DrZBf{_?F8K*&+OUJJT z(=GGao5_W>CO1B#?bPwdKuwzA6QuPuxiK{5OnixsEMn3UvBT)3 z;Vfz6iZtQVaQ#0J^e>nV_w-Y2vC<0Rrt2ggKwK8%Fdz(4$Qp?sR3r`-fLQ)JgVZ+T z5C(KrXe&BZ#14Tz%|kM34tvrkv)s7~h7GsC@!vFIIW*B<#*ofg`*kG!KK|Zx<${!o zJE`p)IGSJHNBL_U2Bf9&N6>dl-Yxbw_a{~T{NCR|%R2-j9&EM(CTAlQylg1WIn&ci zp9N>5n=V2<6^(Y6m*&0GvKW!3Zk;eD$MD*vzFGP9>%&W3mvXLA=CSuZa8aWv z0C_)$=jt%3(1fh}-ueFk5i$7+D?ec&z)YUwwJSuEZsB48vw%sQXWtjuZ9NtaHRPf| zssM79X?^?+qneb8EAN&}twk@>3tkzJxAI~y_r}r)RW! zBScc{)z|#~imZT#wg1HlemJ)p!6_?A3EOQ&h`R+7>gcynJsck&(Uw=^uOexWYMm|s zivQ^`bY!=raT8tPu zi;D*}8uDIgvdj(P0HlhsbI4PFw{KJ0M@$~%iwKQr8}5^ZB!2G-V4Zw1K^y~BRPv|{ zc=oXY9yAAq4!)VM_9z&?JCZ0O)M*U5w(z|K4l~lMmuvi`qJ1jZYEUs9;Gi-{*^{LJ zn(YULx*xiqKGlP+B2HC(-}#;F9G<#A9?`bYI#)pG0?a=@CiY2^)6S$=hrw@ik)ghJ z0L+lSOzOyw_@?vcX9(_oWic+oLJy-2)3-t^XBB?V*XGX1vcs3zvtbms5d)=RGU2R8@&&=o^Y$PPwF8IZ;4!unVV%Jz>Ui0Fa&9iCB7Z>k)X( zz}X-d4qONXcrXm=7kE7_gbEru38;$2lh?v=@-Q>q26(lI>$srVZ~84J*TNXkr$Skc zhQaLVI+ysY)tW*5PDC*u)h>~(G(`MLqkFz2HgqjE9)_zr$B<9OFJCvtJDzj=Gk(&U zlBP%93oOL09aGAWOr`e+B-u3)?lLWU{|3K0fto)iBdvF(}lu7%o4;q!(O)Fwp;*zE)p6c|gMM z1cFbL^G1*ZS6MwB&=x?H6cMEe4a78@XXM9DF2$c8Ef8(rA_^`RT( zE8qGp5}1*{vO=#jGpA2NmwuzfE!NK(^IuZO7Yly37kMTSF!MY2b^*+U<@zDQWDri9 zq0U9%rg#8pID8i81nM^CkIB@B*9GT2L>oNGPe8}eeCcPO{VPW1=O#Ts<+M?I3tH(W z#4idk?h0@OR*CFc|A%~FV=C>#eLHU`ZZ;DXy81+tXE2()BeEdmy3e~cHY}NJZGg|+ zh;NNs;0fsK)p9Z%G+{+zSLfVZG&iN{QvYH!uTigO5z|#ENI2?ctW-mCWDH;V>Cvi4ks+aQST50RfN^}XI^0a zscTL*DiV#!W|-G&mD7LwA76aGx$w5A$9lF;MO7HP-1#@ZO?$V9s&g zad63DVlgOTcs+uQK=a3E=^*H*^G|k+*J@Gzh|SchO;CD1X#N;Q>X|3WXy{%EX}?}B(*PXKR4HoAHI{Z*=Ud}(=Bn4G|K2B zrd$n(opv)DzwuJ`z9hM*XXZt1(+=~Ll;QVWX7B!#dtd?3&#qFU_&{Ti*23FAgry-7 z;x%X50&)AoZDs8p7>Z1UCrAfq*)*S$Vo`QlTKd?_*4;es??R~eo;-==uN=+_?v42# z$?;+fQf{N3f@<~eh`T6>p7IROXw4yCqgjQc=nqO{IcQAcu~!}L`fTVqb7?09t(-Uz0#u!Zb1hESCIk=NYW7@aRRkD`uLk8);EO5jLEfW=%n!eVCb$C z0(V-PyejWlD|rU@wJ=9fnByJB{r1&o81!poRQOhiM%0E_UX4S(|Ehxj+25gdCO-?${$^I^n0O>*>EnZ+O5;O9?`u8l%h9Jw1KtJ8CLTFA2R9hM$)c~s{KauVlRnjP z%TZ^18BH$f(rhehR#Dg z9@hG@)EeQ`?E+7??L@au1$N4>)lh#W&pZgBG*!Tlcy5A4w1l!#Bvd4ekYo5IEf5OPLIzZk;&4#*GWO51#A-SDJ6-K z;x}YjF3id5-!YZ`whkA|i+zd`@2xcR-W@|;Ne?f-EW)#^4{c`*Cwy)5ajNW_j2fMaOFcd zj0>VI0Yw_&Aie8nb?!ONSS;n{{x=W(5U*nZFQw!qi?7hcS_!A_-+b*B144lknMDA| zZvXD*)i>iz-{#id;7NfSGoDZH&ugutxbK-VRRs}*qL(!FmoVU?_(;`qUqyH@b}3+j zub^VxTDAfbe*K^Czs|=gu@`pG7Z`U%h>GVX&FiMBjfXrJL! z%;;BE+WQoBn9GdZQ8bM>27pe%FK+2>s%$y)NbvrY7_E7Kqe@;gJx_>XcITnVd_-Ibljc5>bwOJ z0_k_(CavZPo6PUoU$z=PdsHL)Sq{4C2h&bU)x9;zWJ^n_%kO|qDUnz??x2dXx1PI{ zojW%^Z_D~6IcT1|lYP=Rv?QJv&lMhqc7nXQ6)nUdNZLsVjD&D0k73_mnpM{zj7P`n9=%WLdj_Z7_-gPQe6J_A4*`xlV*scoFq)FURTVc<*)-|;u8_fv+#QiE$+1PgE+-tD{TWkX>*PpNm*q&`P-`S( zpg~ZCiRbcRJu=vf=Uuy7hc*`1fE+G^541@sld|BFA*kkQ9rXE>_FF!v+LuA!c9#Y^ zW%+g^)OsobLAF-Qu^XjvA1UHy8```{^`u({U#rb4AAOc;Zx$nY{bJ!WV7j_ z0^WrjJKC2)syH-cGN@?JQtMFbFljuM9P+$q_7$^YWsZR<7rXx(NI``+x$pB4#Ly&a zB#bAm+=L9%84YHGAj?NG=$?7c%@>=~pB#+S@?#W)P90|OlXCd*12RWi&(wj?i_AET zJ6iz1Ple4B1L*zuI^3t7u2)=hGMzFq%u3B1?*Zf1t)m+t?La6iyG})x`YRdg6MjoZ z6~eM|U@i3as};6K(g?N8g6#Zkv)U^qu07-4WlReSam;pk5D@EN5`VkOwV&f`7KA&2i$sKG_t;BQONCo|(RW&fkG?_a6@f+G zu^MdIjT7bL&N#{p0}7`Z+zU|ndYdBu7lY`CP^xWski*j+$3hV!#n4L6Q6ux{J11lZ z-a8$2dZLHIj>X`{*)p5BY4@D(I;ppv?dg+zS4W?ZbY)rFKsWRuALOr5R87t}O7|?% zEaDnI22vFO=5r={_jced}5f2U+O3_qM+mM^`guUw_ZC<#BLCX`B4+%K?CKA5@x^JQ~ zMTD{l(kH z2euqVVXYXTO9fp|2loX)zajgJHSg5EGm~bnF{DJM$&rVZOhB&7!r6x|vNYoQ^$x_D z-hF#SQ!ps3)T$~UxolliDAV1r98~RJfGcy1_a48ylO0mD6aWS;2zN~Z#+&+5I5k;H zJjVgy%rIY7vXVm0XW5{ z4>yal!Y4u;1xcX7@bO!*BWS)nN6Y(5f!*uy1|)#TW`s{7PwhvXIdWWSXdW<=#|Voe zoaxQPioHl7*-j_-?}an$ljEh}#?6Aest#z#y+65zq4@0rtyALNd+SQfySBgweYu_s zM^g=@Q?>I_?xe~(!eVJb0nLiyKXu#W(4LAhU*20T@G-wZDJh?RY>Y=)tZ$gzdxH;( z!F`uv$B+r}WgZ)xc<)e;l&Q%>&;szA9G#LUR>qT{Hk}!1)aEn`FD1UL5 zBstx`PL?x4bCV+F;trF2i&HyE}|$$z4nG0sOKvEc)eT z6Be!Bq~=fZUNg?)+Y~A9zR~lIVvgoRzrSXOwuOVWR>i5W=hNSf*nD9XDM66)73N^& z*&Qtt0yeu}GL{i|+EHFE2 zp*)wW32M7&Qqz3gUbeN3q-v7O%m&xH^Jwn()O8B%H%@|pt5!)S_siViU;oq`dA}ZU zebbS;kSB$qA3ojj1JSrpqS-T}MLt`eqq~uFA|9LyA3>J- zT5}+4_&rYh?ZgZgu{)Yf-FsuRgurWkq*SG@5JKD>jtmd5t+!hxWN5Vw$Sh3VT zi2}NlB{Pr_VFMOWDQ)IDithy;M%Qz@VGa+m#el{pLaM^)9Q90$ZEn z+pC9rywG5Oc1gAUY%=72F;!D`Ac1en6W`vvHvW1!X=*plVN&nqbes$ubdo;Le?B?) zqQsPDEvE|f9w)^4`lfU@wZ+A5*;R*QemArRJ(Q0^;`vJ(?u8&veMg^O zSPK{LG&>!&k2k#m@gHFT=*ovvsjK$jK1yy_{`=@UTz|ol85^ltpI{;A-iCkRlDw#e zIHRqFeNvAQ6(id*FqXq0P!Qz|HySj96OT*Tphm9cgfi@++FG7l8C|JG3?1 z6r~^sGMQ=Bm1>H4+|rpv!!4`%P6r$nJ!=E+3Ip$wT-U1{_4!5=`O9J4iz9b?ZXoTF zn3*`ZGvq*u_bM6$AHtE0=hHO$Y%L=8v+KVU>45&Ooqot0J7n&ou!vnzWYD(uRzEtF z&7?>HwghoUeU#lNr^gnvZF+&4q+lZKAU10v>8$u!PeZkGe-;trx|m7U6ATjznsC8%gG zq6yq(N|Qr~ZYHN1t~_PRIuDXknM`L;vox@%y*F4z!%6f8?t=KJcWh69{x`c1YD1`x z@(4!YD5}>vEx?bgDZymd!d3~EuRdptmzHb*Jg{#JW$-9;F$bo` z0e<=-L7gh<0<=!+YaE*N_%?Tv9eLzh&OovZEm@91T&}o1x*QJr>vqP0)=6**o){T7 z%qtNkGjxR`4A{F$9CBc13 z!b=Q}Ps`xXBKWKpfo&_XC0B3IEvRjA4>qhkr?9k}o#hYr-Yez7Az%?o*QIyB zUU0qM9#H(e@|;Nrty%$ea1ZB!_jtA_XCjR_xd{Z-aiA`LC`i`MoiVfxbjBZ$9*9kb zKB3@3#Qnv_>EhDfEr>fJ<0bSEXK>4hC|}_UXP8)a&>1Os@a}a6(umEP27%qlPz1^@ zmFXOf`2^79WkJEG{z8v{PqmwX-+^xqxCz^RhuaYKWw7hQc-oDrrgu@-8d+>TDd?!l zT=1_(LG4d&AiyRpHt!3_KVLSrdY1{H*%THqVc^zWGBgu_Oe@kHI03w$2^obeh4-|8*E&E~jZP+@-y33a_wG)hvm%)>sD8bF7x>qg^NQcPc zMaXem5#1ig5O&cR`5OM!OP7^xs&NWhR*&-Tx@rT6w$z7n$p{o`8?d=!YG;K#Dbs9r z8TiOrVt4Sz@1u$vqsxN2mCGqE4W%aKd3qVUP-n$uJtxa7M{ll%%dl3 zSK1OO_lOWO^qjIXK8)df;r^_iH02$jZ$X?U*b?^q4 z4hWiYY=O%!OhAdZ+;lF%&KTmQ0aFSH&=Z_5Aadm`e%z%oj9&oGe>qghRM>^%WyTO#HBCTEM(=r2lL2vI~#2G6| z&&=J(G12yZ(n>TbRC&tv?c3!rk{)9rQhH zchc%y*c-V5o{QfNTni`4wrL?Yf8V!9A9&P>XTkSF?spCP9lXM|AvSTUE-xEKYJb@Y zF7PDuH$BzL1eI2M1$H7}oFR3*p6i-RWhxRkRG`#L4Odb^(unj~%Ve{3;xgU-6&p>8 zsH3DmUrhLm16opXUAIYMK*ZF~$*?8@G#3}R)AsB+)z4;ue&=0u+kH5SSZJM(+xIsj zIf0_e@2?q+#yYHElE%WOD zeQP;s>2k7qgDv;?5#*zqi1!@`6KyrlDB2@sJz6OXrE8~-ohM21n6P%SW!^qY!scJ7 zJew6p^0PL|7v+E!E6{`(N2Y2LWBF)Z=)%V+{;E$c-CEHiZ~AuZ5Jk&z8_x|owy6$( z&IZ@3F0h=JKu5D0yth_Dtia}L5d+fZ>z|q;OJ#0Y`+)CeDlV>(jSy8=XNbd5a4JqfR!Mf35%;+wXKY9_UVj=Fv(dS^RqjWIPwmK|B{8y4Ru3Fd@MtN<$k=*B(Qd@ixFuzV321!pZYZx2?5CeD zbx#KXv6BtgA5hp6w(kL47VicC3tE9L7Ks3ClxC|9x%Cy71rEE~uqs5ri6e!olgW0y z>)K#LXc+LM+MQfdVVH!8Mf7Fx;gbTjf@i`chv)N6JvugkO#L8R8z?5|BiDhGNIm35 zyOLA{eDzG^gN)b90u-a*8m-I1F^^EOP$xSDvJw6moT4C54W;WS@nO)*0=SaaP3uo} z?aRE?r`bH2JNF4byA1J0p zw_2sJ>gdzJ!R`R(jE8^#s{_!1Hy*$=J-S85>`fSO!U$x*F) zi~`}pb`I!ET;_MSvI4gjKUj5O_(+PYtMN93o1mqs--U%}9f(qRG5<+BJy{jVxIS32 z%p>^lcf~+X%Z3kuGw%7zIxzz{jlH0S#d0He_m{4DX994@h{7m1{d;DNw^OGE-W@ny zk87RB$XX67I>Ic{!BdT=j4E3#mns1d20L&>VFqdh^f;W4`Xn?`l-l-r7Xx-fgX)N1EqPS$dl0zwykdN@NLfXmG;Ftade zOo}`E?W#=gY2cv1RNzlhB#N^JR0UTiUV?;a#Jhf|zD}}UcX5y@`PW}dnZeSR2<&h{y0bDZ$ZSD1=s1b|x zhv(q((d&>M(o_i~6Jxdhf3U!)`PaFq|HP$yW&$n?Wq{B7%hvabOG9FU~C@iQ$rY|{JW5iL+-*Cte@ zgbz{Vv*U_nW9LV||HI!jX76*~L2x%r5x8LPACHtiK4TD_3A+&_f`Jk|WHmC9o&)|77U1Wo=`wr@@9((7B4EzQ7Jc%RA5psjXaM$$M3+3Cs zsyRKuKX=`P>LN7RjLc*?NczsyEQ~BPXedOj{HFQ9-_a*cKq;PX$pC;8ibcsiNghncDm3DW{0uB5%IYpg)FdtVg+=#7aM}J^xg!P{F@!1 zI3T0rt#ot&I0)cQi-v~sAxQ5GY`G|L!ZhS*){5tAVhzTGLxvYHrXE7ZI4D2k-xTIN z1zs#rIcOMd6%acqMC_Z%%^9F#ircY~T@7Vpmc34AIH zKs20aUhh8;7Hi>pJ)LnmaC+u97_rJ(AqhgnC2z=cljl|lV{B`nhE22I^og73^A43e z0<`{Bc&Hf|i(>})+0F1dZmoi__jywKIM0BcNVOtcQoF_Fi#^4cZ)#UjYi;h#4m z9AAJ99#MrV?n0;{rZpwZxlEfe!M!#LW8Jlb_z`8bGzr=3?< zOz(e%Y(ol0Go@WdX)6!}XsJTldtY2>?dskUjZAGCRCy$;;dZ^y@E>$z94?Y>{wsE0 zn;bEdxc7u5QVkMDJIo{#DN!;Ji{evA4Yo!mS_=K?21v`TK;zZy!6!Cych1z+mAHmw zfGrk{Cg;YAMVn-5M9ff?@@#5|+^V$_ zTF8uOHQo!Dj(0ZBbki$KIzLn{m%HwSlY?!(@dbS-x5T&QtTN=7r+{PrqmUDV&K?Q7 zj>>XCDEDnt->Rysw7mjSGFDL&m&=lT^(An@dgeTDC#9xr-w!|1> z-`=?2-15vM>+bD0qbAUtFz*#Ykr!+p zCPo_}8_e6*W-NFOK*fBO&aY{0wTF9&fAz-OD9(^6tPKqlkZ=n%v=lu~2L)E`lWl$J zH-1^%x|mU_t@Ke%#WNEE3+2q*^%QYGa=e9Oaqp(jW@SK*aSQ$~W;FsL!Fsr`1k!r& zM5}jC7d?mSQ^$A8p31NAgrcpgcGD&TUC`-99>Wu7DF^l)KxDM-obd!u8y2otN5j+g zV77FAwGwlK+6)=MZes_Y3gVgryG;|09$-xn(PG^?2!f&zj95VeebkFzQWziN?c zyTO$3WU1OOBZ%PIr%HV_-dH1!=sYrd2HXS()qF=FY1CqgUmc#uRJtZo#ZL|6+~o(kYP+mhn#>N^kDJ;beO&3 zh@)6+XqqE(@t{%~*V#3E;Ak#YwWxaF zVi#g&_S&1UPZgP$b=1uVX@k^#$r$sAdhaK-@<1?=Aw^Z z(|Em|_-ZGCBx#M=cV&g;_pw+p$Quj+9He z^;zRV&x7iecdg`Lw4j+3(2B5TUmad42Bk65U0+#E>MxN;cVt#%urQnVEavbDRa{r9R+6M;)IBK#H~kC!(u?Aqx2%!?@@ z(Nd>=%T+=tn-nNzb3Y8&I6|e<=RSsMX^t4g7MP?3>S7h62}ytT#@Hd%-&6nv5MKm? zp1xaQcs$_eU6ABoOwc@|d{W2>t;Dh6UTJ`0R5c{pYMgO?$D9yIW*$?4gZ;t2vqb~c z5a1dthO%8WnHoO$hD7&|B?iAiI)fXd(O`ugkgZ|#4YTjI-R?XgzD&;vO}-}-t(1Gs z!loo)ku60`lEhQjAwh4^Wwu(h9Qz%j{ar7*jcS z`^UGtK~_ftV1Lg&oS}U#h4^eWHVN3lxycDs^l;5XZ@(dd>VN?c64>gJbHx}}iwUC7 zoq+*?rQ(R@-Fc9&v%$xf|1Dx%udrVdxr*SoMtOcsZl35_z6~3+A^(!DozRvS;g6xs z(K-jIO$(sIDe{C~YfEz(Q9=HvrA;5fao&heWwtl5?p|E^*CaS#D2n6*sLBJP7mDt0 z0k+4(L#RKr6gg?HDO+HfI;y?=bx!>_Lq-A@Ps_%ZFy6&HM&W zc$;--_d{W%Ca_)kTV|YJ;}c-9lCXS?^a#o)s?ywFdCV38f#- zorB{Or_F)y?~L%Gy!>;ed}Dc>GH`UP4Nf#{Q>YPH?yYmd40aT99P~C^yfI+q`$6Wi zHv}wi)PlugX8Y<~_?qz2T&b3xK@BbBJ9W4Bt!WQHK`7Ww<#&PmEa1e(T_@~GbIJWY2`?09{ImP~>$A{;Pc`hy)ZE+RUO08%i6p>~hz zB`ajQ4?U_vmXft_2x#vME~q&E`1IYCV}s_(d9bn?Xt3_f34d#vXRwV}XNkR^XCimq zI7J*dzZVqxLyUhGOVKzeM^#}bxD>^=y9~Te4-TlVfm9^_vZ@{LPar#* zELg1`c|XxrZ#&i^6m?1l3yZ1`|1EwZvo=JkavxwsP`-xp??UF)8PXXV_JE@);18+O zIPz{z*(BVCAJYo1U##d&_!-S6+yT<{K#XxHT6$GW(0Cp@WON#X;wX#<(%*xrd}Z;> zgIjZ$5PWgE;uL}iGR4&?@BH1MQVWjBG?Fut+Ru0S@KU5`g~?X1kxG z!#X|kGo{tG{F3&5-j#ZrC#>E$I^A}EtCHjMQLEw1r?HC_PdgKghPQdfCRadSB0fXq zxZz!>G!|S7x3}b}X}s4-&MfwxvKjfKcG;+CN)v2+yhZ=HW}=JF!nEP*W12nJmOVC< z(fcZ>PxmY1FZMb{z#fH(*{`Mf>6C$_i6Vplfv@bc<23Xg{{{aETEQ1==>N|j{~r%J b+oYT?>v}wz)41vg>X*kBpUq{PBGdj00re4) literal 0 HcmV?d00001 diff --git a/src/AnalyzerVs/SubscriptionManager.cs b/src/AnalyzerVs/SubscriptionManager.cs new file mode 100644 index 0000000..ec15fb8 --- /dev/null +++ b/src/AnalyzerVs/SubscriptionManager.cs @@ -0,0 +1,45 @@ +using Microsoft.VisualStudio.Shell.TableManager; +using System; + +namespace FSharpLintVs +{ + /// + /// Every consumer of data from an provides an to record the changes. We give the consumer + /// an IDisposable (this object) that they hang on to as long as they are interested in our data (and they Dispose() of it when they are done). + /// + public class SubscriptionManager : IDisposable + { + private readonly LintCheckerProvider _lintCheckerProvider; + private readonly ITableDataSink _sink; + + public SubscriptionManager(LintCheckerProvider lintCheckerProvider, ITableDataSink sink) + { + _lintCheckerProvider = lintCheckerProvider; + _sink = sink; + + lintCheckerProvider.AddSinkManager(this); + } + + public void Add(LintChecker lintChecker) + { + _sink.AddFactory(lintChecker.Factory); + } + + public void Remove(LintChecker lintChecker) + { + _sink.RemoveFactory(lintChecker.Factory); + } + + public void Notify() + { + _sink.FactorySnapshotChanged(null); + } + + public void Dispose() + { + // Called when the person who subscribed to the data source disposes of the cookie + // (== this object) they were given. + _lintCheckerProvider.RemoveSinkManager(this); + } + } +} diff --git a/src/AnalyzerVs/SuggestionPreview.xaml b/src/AnalyzerVs/SuggestionPreview.xaml new file mode 100644 index 0000000..100cd96 --- /dev/null +++ b/src/AnalyzerVs/SuggestionPreview.xaml @@ -0,0 +1,44 @@ + + + + + + + + + + + + . . . + + - + + + + + + + + + + + + + + . . . + + + + diff --git a/src/AnalyzerVs/SuggestionPreview.xaml.cs b/src/AnalyzerVs/SuggestionPreview.xaml.cs new file mode 100644 index 0000000..570c38f --- /dev/null +++ b/src/AnalyzerVs/SuggestionPreview.xaml.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace FSharpLintVs +{ + /// + /// Interaction logic for SuggestionPreview.xaml + /// + public partial class SuggestionPreview : UserControl + { + protected SuggestionPreview() + { + InitializeComponent(); + } + + public SuggestionPreview(LintError lintError) : this() + { + this.DataContext = lintError; + } + } +} diff --git a/src/AnalyzerVs/Suggestions/LintActionsSource.cs b/src/AnalyzerVs/Suggestions/LintActionsSource.cs new file mode 100644 index 0000000..46c88bf --- /dev/null +++ b/src/AnalyzerVs/Suggestions/LintActionsSource.cs @@ -0,0 +1,121 @@ +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Text.Operations; +using Microsoft.VisualStudio.Threading; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http.Headers; +using System.Threading; +using System.Threading.Tasks; + +namespace FSharpLintVs +{ + public class LintActionsSource : ISuggestedActionsSource + { + private readonly ITextBuffer _textBuffer; + private readonly ITextView _textView; + private LintChecker _lintChecker; + + public LintActionsSource(ITextView textView, ITextBuffer textBuffer) + { + _textBuffer = textBuffer; + _textView = textView; + } + +#pragma warning disable 0067 + public event EventHandler SuggestedActionsChanged; + protected void OnSuggestedActionsChanged(object sender, EventArgs e) + { + SuggestedActionsChanged?.Invoke(sender, e); + } +#pragma warning restore 0067 + + public void Dispose() + { + if (_lintChecker != null) + _lintChecker.Updated -= OnSuggestedActionsChanged; + } + + public IEnumerable GetSuggestedActions(ISuggestedActionCategorySet requestedActionCategories, SnapshotSpan range, CancellationToken cancellationToken) + { + yield return new SuggestedActionSet( + categoryName: PredefinedSuggestedActionCategoryNames.CodeFix, + actions: GetSuggestedActions(range), + title: "FsLint", + priority: SuggestedActionSetPriority.None, + applicableToSpan: null + ); + } + + public IEnumerable GetSuggestedActions(SnapshotSpan range) + { + if (!TryGetLintChecker(out var lintChecker)) + yield break; + + if (!lintChecker.HasSnapshot) + yield break; + + foreach (var error in lintChecker.LastErrorsSnapshot.Errors) + { + if (range.IntersectsWith(error.Span)) + { + if (error.HasSuggestedFix) + yield return new LintFixAction(error); + + yield return new LintSuppressAction(error); + } + } + } + + public Task HasSuggestedActionsAsync(ISuggestedActionCategorySet requestedActionCategories, SnapshotSpan range, CancellationToken cancellationToken) + { + return Task.Run(async () => + { + if (!TryGetLintChecker(out var lintChecker)) + return false; + + // wait for linting to complete + await lintChecker.Linting.WithCancellation(cancellationToken); + + if (!lintChecker.HasSnapshot) + return false; + + // we can't actually traverse the to see if the suggested action is a Some (fix) or None + // because we'd have to evaluate the lazy + return lintChecker.LastErrorsSnapshot.Count > 0; + + }, cancellationToken); + } + + private bool TryGetLintChecker(out LintChecker checker) + { + // return cached value + if (_lintChecker != null) + { + checker = _lintChecker; + return true; + } + + if (!_textBuffer.Properties.TryGetProperty(typeof(LintChecker), out checker)) + return false; + + if (checker.IsDisposed || checker.RefCount == 0 || checker.Linting == null) + return false; + + // cache value + _lintChecker = checker; + _lintChecker.Updated += OnSuggestedActionsChanged; + return true; + } + + + public bool TryGetTelemetryId(out Guid telemetryId) + { + telemetryId = Guid.Empty; + return false; + } + + } +} diff --git a/src/AnalyzerVs/Suggestions/LintFixAction.cs b/src/AnalyzerVs/Suggestions/LintFixAction.cs new file mode 100644 index 0000000..10b9c7b --- /dev/null +++ b/src/AnalyzerVs/Suggestions/LintFixAction.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using Microsoft.VisualStudio.Imaging; +using Microsoft.VisualStudio.Imaging.Interop; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Npgsql.FSharp.Analyzers.Core; + +namespace FSharpLintVs +{ + public class LintFixAction : ISuggestedAction + { + private readonly LintError _lintError; + private readonly Fix _fix; + + public LintFixAction(LintError lintError) + { + this._lintError = lintError; + this._fix = _lintError.GetSuggestedFix(); + } + + public string DisplayText => $"Replace with '{_fix.ToText}'"; + + public string IconAutomationText => null; + + ImageMoniker ISuggestedAction.IconMoniker => KnownMonikers.CodeWarningRule; + + public string InputGestureText => null; + + public bool HasActionSets => false; + +#pragma warning disable RCS1210 + public Task> GetActionSetsAsync(CancellationToken cancellationToken) => default; +#pragma warning restore RCS1210 + + public bool HasPreview => true; + + public Task GetPreviewAsync(CancellationToken cancellationToken) + { + var textBlock = new SuggestionPreview(this._lintError) { MaxWidth = 400, MinHeight = 100 }; + return Task.FromResult(textBlock); + } + + public void Invoke(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + return; + + var span = LintChecker.RangeToSpan(_fix.FromRange, _lintError.Span.Snapshot); + span.Snapshot.TextBuffer.Replace(span, _fix.ToText); + } + + public bool TryGetTelemetryId(out Guid telemetryId) + { + telemetryId = Guid.Empty; + return false; + } + + public void Dispose() + { + //nothing to do + } + } +} diff --git a/src/AnalyzerVs/Suggestions/LintSuggestionProvider.cs b/src/AnalyzerVs/Suggestions/LintSuggestionProvider.cs new file mode 100644 index 0000000..0dcb90d --- /dev/null +++ b/src/AnalyzerVs/Suggestions/LintSuggestionProvider.cs @@ -0,0 +1,20 @@ +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Utilities; +using System.ComponentModel.Composition; + +namespace FSharpLintVs +{ + [Export(typeof(ISuggestedActionsSourceProvider))] + [ContentType(ContentTypeNames.FSharpContentType)] + [Name("F# Lint Suggested Actions")] + public class LintSuggestionProvider : ISuggestedActionsSourceProvider + { + + public ISuggestedActionsSource CreateSuggestedActionsSource(ITextView textView, ITextBuffer textBuffer) + { + return new LintActionsSource(textView, textBuffer); + } + } +} diff --git a/src/AnalyzerVs/Suggestions/LintSuppressAction.cs b/src/AnalyzerVs/Suggestions/LintSuppressAction.cs new file mode 100644 index 0000000..78a807c --- /dev/null +++ b/src/AnalyzerVs/Suggestions/LintSuppressAction.cs @@ -0,0 +1,75 @@ +using Microsoft.VisualStudio.Imaging; +using Microsoft.VisualStudio.Imaging.Interop; +using Microsoft.VisualStudio.Language.Intellisense; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; + +namespace FSharpLintVs +{ + public class LintSuppressAction : ISuggestedAction + { + private readonly LintError error; + + public LintSuppressAction(LintError error) + { + this.error = error; + } + + public string DisplayText => $"Suppress {error.Identifier}"; + + public ImageMoniker IconMoniker => KnownMonikers.CodeSuppressedRule; + + public string IconAutomationText => default; + + public string InputGestureText => default; + + public bool HasPreview => false; + + public bool HasActionSets => true; + + public Task> GetActionSetsAsync(CancellationToken cancellationToken) + { + return Task.FromResult(new SuggestedActionSet[] + { + new SuggestedActionSet( + categoryName: PredefinedSuggestedActionCategoryNames.CodeFix, + actions: GetSuggestedActions(), + title: "FsLint", + priority: SuggestedActionSetPriority.None, + applicableToSpan: null + ) + }.AsEnumerable()); + } + + public IEnumerable GetSuggestedActions() + { + yield return new LintSuppressBy(error, LintSuppressBy.Method.Above); + yield return new LintSuppressBy(error, LintSuppressBy.Method.Inline); + yield return new LintSuppressBy(error, LintSuppressBy.Method.Section); + } + + public Task GetPreviewAsync(CancellationToken cancellationToken) => throw new NotImplementedException(); + + public void Invoke(CancellationToken cancellationToken) + { + GetSuggestedActions().First().Invoke(cancellationToken); + } + + public bool TryGetTelemetryId(out Guid telemetryId) + { + telemetryId = default; + return false; + } + + public void Dispose() + { + // nothing + } + } + + +} \ No newline at end of file diff --git a/src/AnalyzerVs/Suggestions/LintSuppressBy.cs b/src/AnalyzerVs/Suggestions/LintSuppressBy.cs new file mode 100644 index 0000000..95adc10 --- /dev/null +++ b/src/AnalyzerVs/Suggestions/LintSuppressBy.cs @@ -0,0 +1,140 @@ +using Microsoft.VisualStudio.Imaging; +using Microsoft.VisualStudio.Imaging.Interop; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; + +namespace FSharpLintVs +{ + public class LintSuppressBy : ISuggestedAction + { + public enum Method + { + Inline, + Above, + Section, + Global + } + + private readonly LintError _error; + private readonly Method _suppressionMethod; + + public LintSuppressBy(LintError error, Method suppressionMethod) + { + this._error = error; + this._suppressionMethod = suppressionMethod; + } + + public static string ToText(Method suppressionMethod) + { + switch (suppressionMethod) + { + case Method.Inline: + return "inline"; + case Method.Above: + return "above"; + case Method.Section: + return "section"; + default: + return "..."; + } + } + + public string DisplayText => $"Suppress {ToText(_suppressionMethod)}"; + + public ImageMoniker IconMoniker => _suppressionMethod switch + { + Method.Above => KnownMonikers.GlyphUp, + Method.Section => KnownMonikers.Inline, + Method.Inline => KnownMonikers.GoToCurrentLine, + _ => default + }; + + public string IconAutomationText => default; + + public string InputGestureText => default; + + public bool HasActionSets => false; + + public Task> GetActionSetsAsync(CancellationToken cancellationToken) + { + throw new NotSupportedException(); + } + + public bool HasPreview => false; + + public Task GetPreviewAsync(CancellationToken cancellationToken) => throw new NotImplementedException(); + + public void Invoke(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + return; + + var snapshot = _error.Span.Snapshot; + + switch (_suppressionMethod) + { + case Method.Inline: + { + var line = _error.Span.Start.GetContainingLine(); + if (line != null) + snapshot.TextBuffer.Insert(line.End.Position, $" // fsharplint:disable-line {_error.Name}"); + break; + } + case Method.Above: + { + var line = snapshot.GetLineFromLineNumber(_error.Line - 1); + var indent = snapshot.GetLineFromLineNumber(_error.Line).GetText().TakeWhile(Char.IsWhiteSpace).Count(); + if (line != null) + snapshot.TextBuffer.Insert(line.End.Position, $"{Environment.NewLine}{new String(' ', indent)}// fsharplint:disable-next-line {_error.Name}"); + break; + } + case Method.Section: + { + var containingLine = FindSection().FirstOrDefault(); + if (containingLine == null) + { + snapshot = _error.Span.Snapshot.TextBuffer.Insert(0, $"// fsharplint:disable{Environment.NewLine}"); + containingLine = snapshot.GetLineFromLineNumber(0); + } + + snapshot.TextBuffer.Insert(containingLine.End, $" {_error.Name}"); + break; + } + default: + break; + } + } + + public IEnumerable FindSection() + { + var cursor = _error.Line; + var snapshot = _error.Span.Snapshot; + + while (cursor-- >= 0) + { + var line = snapshot.GetLineFromLineNumber(cursor); + if (line.GetText().StartsWith("// fsharplint:disable ")) + yield return line; + } + } + + public bool TryGetTelemetryId(out Guid telemetryId) + { + telemetryId = default; + return false; + } + + public void Dispose() + { + // nothing + } + } + + +} \ No newline at end of file diff --git a/src/AnalyzerVs/Table/LintTableSnapshotFactory.cs b/src/AnalyzerVs/Table/LintTableSnapshotFactory.cs new file mode 100644 index 0000000..74f2891 --- /dev/null +++ b/src/AnalyzerVs/Table/LintTableSnapshotFactory.cs @@ -0,0 +1,40 @@ +using Microsoft.VisualStudio.Shell.TableManager; + +namespace FSharpLintVs +{ + public class LintTableSnapshotFactory : TableEntriesSnapshotFactoryBase + { + + public LintingErrorsSnapshot CurrentSnapshot { get; private set; } + + public LintTableSnapshotFactory(LintingErrorsSnapshot lintErrors) + { + this.CurrentSnapshot = lintErrors; + } + + public void UpdateErrors(LintingErrorsSnapshot lintingErrors) + { + this.CurrentSnapshot.NextSnapshot = lintingErrors; + this.CurrentSnapshot = lintingErrors; + } + + #region ITableEntriesSnapshotFactory members + + public override int CurrentVersionNumber => this.CurrentSnapshot.VersionNumber; + + public override ITableEntriesSnapshot GetCurrentSnapshot() => this.CurrentSnapshot; + + public override void Dispose() + { + } + + public override ITableEntriesSnapshot GetSnapshot(int versionNumber) + { + // In theory the snapshot could change in the middle of the return statement so snap the snapshot just to be safe. + var snapshot = this.CurrentSnapshot; + return (versionNumber == snapshot.VersionNumber) ? snapshot : null; + } + + #endregion + } +} diff --git a/src/AnalyzerVs/Table/LintingErrorsSnapshot.cs b/src/AnalyzerVs/Table/LintingErrorsSnapshot.cs new file mode 100644 index 0000000..e0f02ed --- /dev/null +++ b/src/AnalyzerVs/Table/LintingErrorsSnapshot.cs @@ -0,0 +1,177 @@ +using Microsoft.Internal.VisualStudio.Shell.TableControl; +using Microsoft.VisualStudio.Shell.Interop; +using Microsoft.VisualStudio.Shell.TableControl; +using Microsoft.VisualStudio.Shell.TableManager; +using Microsoft.VisualStudio.Text; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Windows; +using System.Windows.Documents; + +namespace FSharpLintVs +{ + public class LintingErrorsSnapshot : WpfTableEntriesSnapshotBase + { + public ITextDocument Document { get; } + + public override int VersionNumber { get; } + + public override int Count => this.Errors.Count; + + public const string ErrorCategory = "Lint"; + public const string ToolName = "FSharpLint"; + + // We're not using an immutable list here but we cannot modify the list in any way once we've published the snapshot. + public List Errors { get; } + + public LintingErrorsSnapshot NextSnapshot; + + public LintingErrorsSnapshot(ITextDocument document, int version) + { + Document = document; + VersionNumber = version; + Errors = new List(); + } + + public override int IndexOf(int currentIndex, ITableEntriesSnapshot newerSnapshot) + { + // This and TranslateTo() are used to map errors from one snapshot to a different one (that way the error list can do things like maintain the selection on an error + // even when the snapshot containing the error is replaced by a new one). + // + // You only need to implement Identity() or TranslateTo() and, of the two, TranslateTo() is more efficient for the error list to use. + + // Map currentIndex to the corresponding index in newerSnapshot (and keep doing it until either + // we run out of snapshots, we reach newerSnapshot, or the index can no longer be mapped forward). + var currentSnapshot = this; + do + { + Debug.Assert(currentIndex >= 0); + Debug.Assert(currentIndex < currentSnapshot.Count); + + currentIndex = currentSnapshot.Errors[currentIndex].NextIndex; + + currentSnapshot = currentSnapshot.NextSnapshot; + } + while ((currentSnapshot != null) && (currentSnapshot != newerSnapshot) && (currentIndex >= 0)); + + return currentIndex; + } + + public override bool TryGetValue(int index, string columnName, out object content) + { + if (index >= 0 && index < this.Errors.Count) + { + var err = this.Errors[index]; + + switch (columnName) + { + case StandardTableKeyNames.DocumentName: + { + // We return the full file path here. The UI handles displaying only the Path.GetFileName(). + content = Document.FilePath; + return true; + } + + case StandardTableKeyNames.ErrorCategory: + { + content = ErrorCategory; + return true; + } + + case StandardTableKeyNames.ErrorSource: + { + content = ErrorSource.Other; + return true; + } + + case StandardTableKeyNames.Line: + { + // Line and column numbers are 0-based (the UI that displays the line/column number will add one to the value returned here). + content = err.Line; + return true; + } + + case StandardTableKeyNames.Column: + { + content = err.Column; + return true; + } + + case StandardTableKeyNames.Text: + { + content = err.Message; + return true; + } + + case StandardTableKeyNames2.TextInlines: + { + //content = "?"; + // Do we have detailed inline text? + content = ""; + return false; + } + + case StandardTableKeyNames.ErrorSeverity: + { + content = __VSERRORCATEGORY.EC_WARNING; + return true; + } + + case StandardTableKeyNames.BuildTool: + { + content = ToolName; + return true; + } + + case StandardTableKeyNames.ErrorCode: + { + content = err.Identifier; + return true; + } + + case StandardTableKeyNames.ErrorCodeToolTip: + { + content = err.Name; + return true; + } + + case StandardTableKeyNames.HelpLink: + { + content = err.HelpUrl; + return true; + } + + case StandardTableKeyNames.ProjectName: + { + content = err.Project.ProjectName; + return true; + } + + case StandardTableKeyNames.ProjectGuid: + { + content = err.Project.ProjectGuid; + return true; + } + + // TODO: add support for case StandardTableKeyNames.ProjectGuid: + } + + } + + content = null; + return false; + } + + public override bool CanCreateDetailsContent(int index) + { + return false; + } + + public override bool TryCreateDetailsStringContent(int index, out string content) + { + content = this.Errors[index].Tooltip; + return content != null; + } + } +} diff --git a/src/AnalyzerVs/paket.references b/src/AnalyzerVs/paket.references new file mode 100644 index 0000000..0a1dca0 --- /dev/null +++ b/src/AnalyzerVs/paket.references @@ -0,0 +1,2 @@ +FSharp.Compiler.Service +FSharp.Core diff --git a/src/AnalyzerVs/source.extension.vsixmanifest b/src/AnalyzerVs/source.extension.vsixmanifest new file mode 100644 index 0000000..64772bc --- /dev/null +++ b/src/AnalyzerVs/source.extension.vsixmanifest @@ -0,0 +1,27 @@ + + + + + F# Lint + F# source code linting using FSharpLint. + https://github.com/deviousasti/fsharp-linting-for-vs + Resources\License.txt + Resources\ReleaseNotes.html + Resources\logo.png + Resources\logo.png + fsharp, linting + + + + + + + + + + + + + + + diff --git a/src/NpgsqlFSharpAnalyzer/InformationSchema.fs b/src/NpgsqlFSharpAnalyzer.Core/InformationSchema.fs similarity index 93% rename from src/NpgsqlFSharpAnalyzer/InformationSchema.fs rename to src/NpgsqlFSharpAnalyzer.Core/InformationSchema.fs index 3a018f0..c0b788a 100644 --- a/src/NpgsqlFSharpAnalyzer/InformationSchema.fs +++ b/src/NpgsqlFSharpAnalyzer.Core/InformationSchema.fs @@ -1,4 +1,4 @@ -namespace Npgsql.FSharp.Analyzers +namespace Npgsql.FSharp.Analyzers.Core open System open System.Data @@ -17,12 +17,12 @@ open System.Net module InformationSchema = type internal NpgsqlDataReader with - member cursor.GetValueOrDefault(name: string, defaultValue) = + member cursor.GetValueOrDefault(name: string, defaultValue) = let i = cursor.GetOrdinal(name) if cursor.IsDBNull( i) then defaultValue else cursor.GetFieldValue( i) type internal Type with - member this.PartiallyQualifiedName = + member this.PartiallyQualifiedName = sprintf "%s, %s" this.FullName (this.Assembly.GetName().Name) //https://www.postgresql.org/docs/current/static/datatype.html#DATATYPE-TABLE @@ -67,7 +67,7 @@ module InformationSchema = "date", typeof "interval", typeof - "timestamp without time zone", typeof; "timestamp", typeof + "timestamp without time zone", typeof; "timestamp", typeof "timestamp with time zone", typeof; "timestamptz", typeof "time without time zone", typeof; "time", typeof "time with time zone", typeof; "timetz", typeof @@ -82,43 +82,43 @@ module InformationSchema = //"range", typeof, NpgsqlDbType.Range) ] - let getTypeMapping = + let getTypeMapping = let allMappings = dict builtins - fun datatype -> + fun datatype -> let exists, value = allMappings.TryGetValue(datatype) - if exists then value else failwithf "Unsupported datatype %s." datatype + if exists then value else failwithf "Unsupported datatype %s." datatype - type PostgresType with - member this.ToClrType() = + type PostgresType with + member this.ToClrType() = match this with - | :? PostgresBaseType as x -> + | :? PostgresBaseType as x -> getTypeMapping x.Name | :? PostgresEnumType -> typeof - | :? PostgresDomainType as x -> + | :? PostgresDomainType as x -> x.BaseType.ToClrType() | :? PostgresTypes.PostgresArrayType as arr -> arr.Element.ToClrType().MakeArrayType() - | _ -> + | _ -> typeof - + type DataType = { Name: string Schema: string ClrType: Type - } with + } with member this.FullName = sprintf "%s.%s" this.Schema this.Name member this.IsUserDefinedType = this.Schema <> "pg_catalog" member this.IsFixedLength = this.ClrType.IsValueType - member this.UdtTypeName = - if this.ClrType.IsArray + member this.UdtTypeName = + if this.ClrType.IsArray then let withoutTrailingBrackets = this.Name.Substring(0, this.Name.Length - 2) // my_enum[] -> my_enum sprintf "%s.%s" this.Schema withoutTrailingBrackets else this.FullName - static member Create(x: PostgresTypes.PostgresType) = - { + static member Create(x: PostgresTypes.PostgresType) = + { Name = x.Name Schema = x.Namespace ClrType = x.ToClrType() @@ -127,12 +127,12 @@ module InformationSchema = type Schema = { OID : string Name : string } - + type Table = { OID : string Name : string Description : string option } - + type Column = { ColumnAttributeNumber : int16 Name: string @@ -151,7 +151,7 @@ module InformationSchema = member this.ClrType = this.DataType.ClrType - member this.ClrTypeConsideringNullability = + member this.ClrTypeConsideringNullability = if this.Nullable then typedefof<_ option>.MakeGenericType this.DataType.ClrType else this.DataType.ClrType @@ -167,46 +167,46 @@ module InformationSchema = { Schema : Schema Tables : Dictionary> Enums : Map } - + type ColumnLookupKey = { TableOID : string; ColumnAttributeNumber : int16 } - + type DbSchemaLookups = { Schemas : Dictionary Columns : Dictionary Enums : Map } - + type Parameter = { Name: string NpgsqlDbType: NpgsqlTypes.NpgsqlDbType - Direction: ParameterDirection + Direction: ParameterDirection MaxLength: int Precision: byte Scale : byte Optional: bool DataType: DataType } with - + member this.Size = this.MaxLength - let inline openConnection connectionString = + let inline openConnection connectionString = let conn = new NpgsqlConnection(connectionString) conn.Open() conn let extractParametersAndOutputColumns(connectionString, commandText, allParametersOptional, dbSchemaLookups : DbSchemaLookups) = use conn = openConnection(connectionString) - + use cmd = new NpgsqlCommand(commandText, conn) NpgsqlCommandBuilder.DeriveParameters(cmd) for p in cmd.Parameters do p.Value <- DBNull.Value - let cols = + let cols = use cursor = cmd.ExecuteReader(CommandBehavior.SchemaOnly) if cursor.FieldCount = 0 then [] else [ for c in cursor.GetColumnSchema() -> c ] - + let outputColumns = [ for column in cols -> let columnAttributeNumber = column.ColumnAttributeNumber.GetValueOrDefault(-1s) - + if column.TableOID <> 0u then let lookupKey = { TableOID = string column.TableOID ColumnAttributeNumber = columnAttributeNumber } @@ -231,13 +231,13 @@ module InformationSchema = } ] - let parameters = + let parameters = [ for p in cmd.Parameters -> assert (p.Direction = ParameterDirection.Input) { Name = p.ParameterName - NpgsqlDbType = + NpgsqlDbType = match p.PostgresType with - | :? PostgresArrayType as x when (x.Element :? PostgresEnumType) -> + | :? PostgresArrayType as x when (x.Element :? PostgresEnumType) -> //probably array of custom type (enum or composite) NpgsqlDbType.Array ||| NpgsqlDbType.Text | _ -> p.NpgsqlDbType @@ -245,20 +245,20 @@ module InformationSchema = MaxLength = p.Size Precision = p.Precision Scale = p.Scale - Optional = allParametersOptional + Optional = allParametersOptional DataType = DataType.Create(p.PostgresType) } ] - - let enums = - outputColumns + + let enums = + outputColumns |> Seq.choose (fun c -> if c.DataType.IsUserDefinedType && dbSchemaLookups.Enums.ContainsKey(c.DataType.UdtTypeName) then Some (c.DataType.UdtTypeName, dbSchemaLookups.Enums.[c.DataType.UdtTypeName]) else None) - |> Seq.append [ + |> Seq.append [ for p in parameters do if p.DataType.IsUserDefinedType && dbSchemaLookups.Enums.ContainsKey(p.DataType.UdtTypeName) - then + then yield p.DataType.UdtTypeName, dbSchemaLookups.Enums.[p.DataType.UdtTypeName] ] |> Seq.distinct @@ -268,7 +268,7 @@ module InformationSchema = let getDbSchemaLookups(connectionString) = use conn = openConnection(connectionString) - + use cmd = conn.CreateCommand() cmd.CommandText <- """ SELECT @@ -281,7 +281,7 @@ module InformationSchema = GROUP BY schema, name """ - + let enumsLookup = [ use cursor = cmd.ExecuteReader() @@ -297,7 +297,7 @@ module InformationSchema = schema, types |> Seq.map (fun (_, name, t) -> name, t) |> Map.ofSeq ) |> Map.ofSeq - + //https://stackoverflow.com/questions/12445608/psql-list-all-tables#12455382 use cmd = conn.CreateCommand() cmd.CommandText <- """ @@ -339,22 +339,22 @@ module InformationSchema = ns.nspname <> 'information_schema' ORDER BY nspname, relname; """ - + let schemas = Dictionary() let columns = Dictionary() - + use row = cmd.ExecuteReader() while row.Read() do let schema : Schema = { OID = string row.["schema_oid"] Name = string row.["schema_name"] } - + if not <| schemas.ContainsKey(schema.Name) then - + schemas.Add(schema.Name, { Schema = schema Tables = Dictionary(); Enums = enumsLookup.TryFind schema.Name |> Option.defaultValue Map.empty }) - + match row.["table_oid"] |> Option.ofObj with | None -> () | Some oid -> @@ -362,10 +362,10 @@ module InformationSchema = { OID = string oid Name = string row.["table_name"] Description = row.["table_description"] |> Option.ofObj |> Option.map string } - + if not <| schemas.[schema.Name].Tables.ContainsKey(table) then schemas.[schema.Name].Tables.Add(table, HashSet()) - + match row.GetValueOrDefault("col_number", -1s) with | -1s -> () | attnum -> @@ -374,17 +374,17 @@ module InformationSchema = schemas.[schema.Name].Enums |> Map.tryFind udtName |> Option.isSome - + let clrType = match string row.["col_data_type"] with | "ARRAY" -> - let elemType = getTypeMapping(udtName.TrimStart('_') ) + let elemType = getTypeMapping(udtName.TrimStart('_') ) elemType.MakeArrayType() | "USER-DEFINED" -> if isUdt then typeof else typeof - | dataType -> + | dataType -> getTypeMapping(dataType) - + let column = { ColumnAttributeNumber = attnum Name = string row.["col_name"] @@ -401,10 +401,10 @@ module InformationSchema = PartOfPrimaryKey = unbox row.["col_part_of_primary_key"] BaseSchemaName = schema.Name BaseTableName = string row.["table_name"] } - + if not <| schemas.[schema.Name].Tables.[table].Contains(column) then schemas.[schema.Name].Tables.[table].Add(column) |> ignore - + let lookupKey = { TableOID = table.OID ColumnAttributeNumber = column.ColumnAttributeNumber } if not <| columns.ContainsKey(lookupKey) then diff --git a/src/NpgsqlFSharpAnalyzer.Core/NpgsqlFSharpAnalyzer.Core.fsproj b/src/NpgsqlFSharpAnalyzer.Core/NpgsqlFSharpAnalyzer.Core.fsproj new file mode 100644 index 0000000..69fec35 --- /dev/null +++ b/src/NpgsqlFSharpAnalyzer.Core/NpgsqlFSharpAnalyzer.Core.fsproj @@ -0,0 +1,20 @@ + + + + netstandard2.0 + + + + + + + + + + + + + + + + diff --git a/src/NpgsqlFSharpAnalyzer/SqlAnalysis.fs b/src/NpgsqlFSharpAnalyzer.Core/SqlAnalysis.fs similarity index 99% rename from src/NpgsqlFSharpAnalyzer/SqlAnalysis.fs rename to src/NpgsqlFSharpAnalyzer.Core/SqlAnalysis.fs index d95dbde..b1a2728 100644 --- a/src/NpgsqlFSharpAnalyzer/SqlAnalysis.fs +++ b/src/NpgsqlFSharpAnalyzer.Core/SqlAnalysis.fs @@ -1,6 +1,5 @@ -namespace Npgsql.FSharp.Analyzers +namespace Npgsql.FSharp.Analyzers.Core -open FSharp.Analyzers.SDK open FSharp.Compiler.Range open F23.StringSimilarity @@ -180,7 +179,7 @@ module SqlAnalysis = then yield typeMismatch [ "Sql.jsonb"; "Sql.jsonbOrNone"; "Sql.dbnull" ] | ("text"|"json"|"xml") -> - if providedParam.paramFunc <> "Sql.text" && providedParam.paramFunc <> "Sql.textOrNone" && providedParam.paramFunc <> "Sql.string" && providedParam.paramFunc <> "Sql.textOrNone" && providedParam.paramFunc <> "Sql.dbnull" + if providedParam.paramFunc <> "Sql.text" && providedParam.paramFunc <> "Sql.textOrNone" && providedParam.paramFunc <> "Sql.string" && providedParam.paramFunc <> "Sql.textOrNone" && providedParam.paramFunc <> "Sql.dbnull" then yield typeMismatch [ "Sql.text"; "Sql.string"; "Sql.textOrNone"; "Sql.stringOrNone"; "Sql.dbnull" ] | _ -> () @@ -383,7 +382,7 @@ module SqlAnalysis = then yield typeMismatch [ replace "textOrNone"; replace "stringOrText" ] else yield typeMismatch [ replace "text"; replace "string" ] else () - + | "date" -> if column.Nullable && notUsing "dateOrNone" then yield typeMismatch [ replace "dateOrNone" ] diff --git a/src/NpgsqlFSharpAnalyzer.Core/SqlAnalyzer.fs b/src/NpgsqlFSharpAnalyzer.Core/SqlAnalyzer.fs new file mode 100644 index 0000000..e47dc8c --- /dev/null +++ b/src/NpgsqlFSharpAnalyzer.Core/SqlAnalyzer.fs @@ -0,0 +1,31 @@ +namespace Npgsql.FSharp.Analyzers.Core + +open System +open System.IO +open System.Linq + +module SqlAnalyzer = + + /// Recursively tries to find the parent of a file starting from a directory + let rec findParent (directory: string) (fileToFind: string) = + let path = if Directory.Exists(directory) then directory else Directory.GetParent(directory).FullName + let files = Directory.GetFiles(path) + if files.Any(fun file -> Path.GetFileName(file).ToLower() = fileToFind.ToLower()) + then path + else findParent (DirectoryInfo(path).Parent.FullName) fileToFind + + let tryFindConfig (file: string) = + try + let parent = (Directory.GetParent file).FullName + try Some (Path.Combine(findParent parent "NPGSQL_FSHARP", "NPGSQL_FSHARP")) + with error -> None + with error -> + None + + let tryFindConnectionString fileName = + match tryFindConfig fileName with + | Some config -> + try (File.ReadAllText config) + with error -> Environment.GetEnvironmentVariable "NPGSQL_FSHARP" + | None -> + Environment.GetEnvironmentVariable "NPGSQL_FSHARP" diff --git a/src/NpgsqlFSharpAnalyzer/SyntacticAnalysis.fs b/src/NpgsqlFSharpAnalyzer.Core/SyntacticAnalysis.fs similarity index 99% rename from src/NpgsqlFSharpAnalyzer/SyntacticAnalysis.fs rename to src/NpgsqlFSharpAnalyzer.Core/SyntacticAnalysis.fs index 536a8f0..2d80722 100644 --- a/src/NpgsqlFSharpAnalyzer/SyntacticAnalysis.fs +++ b/src/NpgsqlFSharpAnalyzer.Core/SyntacticAnalysis.fs @@ -1,6 +1,5 @@ -namespace Npgsql.FSharp.Analyzers +namespace Npgsql.FSharp.Analyzers.Core -open FSharp.Analyzers.SDK open FSharp.Compiler.SourceCodeServices open FSharp.Compiler.SyntaxTree open FSharp.Compiler.Range @@ -404,7 +403,7 @@ module SyntacticAnalysis = | SynBinding.Binding (access, kind, mustInline, isMutable, attrs, xmlDecl, valData, headPat, returnInfo, expr, range, seqPoint) -> visitSyntacticExpression expr range - let findLiterals (ctx: Context) = + let findLiterals (ctx: SpecializedContext) = let values = new ResizeArray() for symbol in ctx.Symbols |> Seq.collect (fun s -> s.TryGetMembersFunctionsAndValues) do match symbol.LiteralValue with @@ -428,7 +427,7 @@ module SyntacticAnalysis = { operation with blocks = modifiedBlocks } - let findSqlOperations (ctx: Context) = + let findSqlOperations (ctx: SpecializedContext) = let operations = ResizeArray() match ctx.ParseTree with | ParsedInput.ImplFile input -> @@ -478,7 +477,7 @@ module SyntacticAnalysis = | SynModuleDecl.NestedModule(moduleInfo, isRecursive, nestedDeclarations, _, _) -> iterDeclarations nestedDeclarations - | SynModuleDecl.Types(definitions, range) -> + | SynModuleDecl.Types(definitions, range) -> iterTypeDefs definitions | _ -> () diff --git a/src/NpgsqlFSharpAnalyzer.Core/Types.fs b/src/NpgsqlFSharpAnalyzer.Core/Types.fs new file mode 100644 index 0000000..33f9a20 --- /dev/null +++ b/src/NpgsqlFSharpAnalyzer.Core/Types.fs @@ -0,0 +1,63 @@ +namespace Npgsql.FSharp.Analyzers.Core + +open FSharp.Compiler.Range + +open System +open FSharp.Compiler +open FSharp.Compiler.SyntaxTree +open FSharp.Compiler.SourceCodeServices + +type SpecializedContext = + { FileName: string + Content: string[] + ParseTree: ParsedInput + TypedTree: FSharpImplementationFileContents + Symbols: FSharpEntity list + GetAllEntities: bool -> AssemblySymbol list} + +type Fix = + { FromRange : range + FromText : string + ToText : string } + +type Severity = + | Info + | Warning + | Error + +type Message = + { Type: string + Message: string + Code: string + Severity: Severity + Range: range + Fixes: Fix list } + + +type ColumnReadAttempt = { + funcName: string; + columnName: string; + columnNameRange : range + funcCallRange: range +} + +type UsedParameter = { + name : string + range : range + paramFunc : string + paramFuncRange : range + applicationRange : range option +} + +[] +type SqlAnalyzerBlock = + | Query of string * range + | LiteralQuery of ident:string * range + | StoredProcedure of string * range + | Parameters of UsedParameter list * range + | ReadingColumns of ColumnReadAttempt list + +type SqlOperation = { + blocks : SqlAnalyzerBlock list + range : range +} diff --git a/src/NpgsqlFSharpAnalyzer/NpgsqlFSharpAnalyzer.fsproj b/src/NpgsqlFSharpAnalyzer/NpgsqlFSharpAnalyzer.fsproj index f34cd3f..2e855e6 100644 --- a/src/NpgsqlFSharpAnalyzer/NpgsqlFSharpAnalyzer.fsproj +++ b/src/NpgsqlFSharpAnalyzer/NpgsqlFSharpAnalyzer.fsproj @@ -1,6 +1,7 @@ + NpgsqlFSharpAnalyzer netcoreapp2.0 true Advanced embedded static analysis and type-checking for SQL code from F# @@ -11,12 +12,10 @@ true - - - - - + + + diff --git a/src/NpgsqlFSharpAnalyzer/SqlAnalyzer.fs b/src/NpgsqlFSharpAnalyzer/SqlAnalyzer.fs index 2aed4fa..4574b69 100644 --- a/src/NpgsqlFSharpAnalyzer/SqlAnalyzer.fs +++ b/src/NpgsqlFSharpAnalyzer/SqlAnalyzer.fs @@ -7,52 +7,62 @@ open System.Linq module SqlAnalyzer = - /// Recursively tries to find the parent of a file starting from a directory - let rec findParent (directory: string) (fileToFind: string) = - let path = if Directory.Exists(directory) then directory else Directory.GetParent(directory).FullName - let files = Directory.GetFiles(path) - if files.Any(fun file -> Path.GetFileName(file).ToLower() = fileToFind.ToLower()) - then path - else findParent (DirectoryInfo(path).Parent.FullName) fileToFind - - let tryFindConfig (file: string) = - try - let parent = (Directory.GetParent file).FullName - try Some (Path.Combine(findParent parent "NPGSQL_FSHARP", "NPGSQL_FSHARP")) - with error -> None - with error -> - None - - let tryFindConnectionString (ctx: Context) = - match tryFindConfig ctx.FileName with - | Some config -> - try (File.ReadAllText config) - with error -> Environment.GetEnvironmentVariable "NPGSQL_FSHARP" - | None -> - Environment.GetEnvironmentVariable "NPGSQL_FSHARP" + let specializedSeverity = function + | Core.Severity.Error -> Severity.Error + | Core.Severity.Info -> Severity.Info + | Core.Severity.Warning -> Severity.Warning + + let specializedFix (fix: Core.Fix) : Fix = + { + FromRange = fix.FromRange + FromText = fix.FromText + ToText = fix.ToText + } + + let specializedMessage (message: Core.Message) : Message = + { + Code = message.Code + Fixes = message.Fixes |> List.map specializedFix + Message = message.Message + Range = message.Range + Severity = message.Severity |> specializedSeverity + Type = message.Type + } + + let specializedContext (ctx: Context) : Core.SpecializedContext = { + Content = ctx.Content + FileName = ctx.FileName + GetAllEntities = ctx.GetAllEntities + ParseTree = ctx.ParseTree + Symbols = ctx.Symbols + TypedTree = ctx.TypedTree + } [] let queryAnalyzer : Analyzer = fun (ctx: Context) -> - let syntacticBlocks = SyntacticAnalysis.findSqlOperations ctx + let syntacticBlocks = Core.SyntacticAnalysis.findSqlOperations (specializedContext ctx) if List.isEmpty syntacticBlocks then [ ] - else - let connectionString = tryFindConnectionString ctx + else + let connectionString = Core.SqlAnalyzer.tryFindConnectionString ctx.FileName if isNull connectionString || String.IsNullOrWhiteSpace connectionString then [ for block in syntacticBlocks -> - SqlAnalysis.createWarning "Missing environment variable 'NPGSQL_FSHARP'. Please set that variable to the connection string of your development database put the connection string in a file called 'NPGSQL_FSHARP' relative next your project or in your project root." block.range + Core.SqlAnalysis.createWarning "Missing environment variable 'NPGSQL_FSHARP'. Please set that variable to the connection string of your development database put the connection string in a file called 'NPGSQL_FSHARP' relative next your project or in your project root." block.range + |> specializedMessage ] else - match SqlAnalysis.databaseSchema connectionString with + match Core.SqlAnalysis.databaseSchema connectionString with | Result.Error connectionError -> [ for block in syntacticBlocks -> - SqlAnalysis.createWarning (sprintf "Error while connecting to the development database using the connection string from environment variable 'NPGSQL_FSHARP' or put the connection string in a file called 'NPGSQL_FSHARP' relative next your project or in your project root. Connection error: %s" connectionError) block.range + Core.SqlAnalysis.createWarning (sprintf "Error while connecting to the development database using the connection string from environment variable 'NPGSQL_FSHARP' or put the connection string in a file called 'NPGSQL_FSHARP' relative next your project or in your project root. Connection error: %s" connectionError) block.range + |> specializedMessage ] | Result.Ok schema -> syntacticBlocks - |> List.collect (fun block -> SqlAnalysis.analyzeOperation block connectionString schema) + |> List.collect (fun block -> Core.SqlAnalysis.analyzeOperation block connectionString schema) + |> List.map specializedMessage |> List.distinctBy (fun message -> message.Range) diff --git a/src/NpgsqlFSharpAnalyzer/Types.fs b/src/NpgsqlFSharpAnalyzer/Types.fs deleted file mode 100644 index 52e5b92..0000000 --- a/src/NpgsqlFSharpAnalyzer/Types.fs +++ /dev/null @@ -1,31 +0,0 @@ -namespace Npgsql.FSharp.Analyzers - -open FSharp.Compiler.Range - -type ColumnReadAttempt = { - funcName: string; - columnName: string; - columnNameRange : range - funcCallRange: range -} - -type UsedParameter = { - name : string - range : range - paramFunc : string - paramFuncRange : range - applicationRange : range option -} - -[] -type SqlAnalyzerBlock = - | Query of string * range - | LiteralQuery of ident:string * range - | StoredProcedure of string * range - | Parameters of UsedParameter list * range - | ReadingColumns of ColumnReadAttempt list - -type SqlOperation = { - blocks : SqlAnalyzerBlock list - range : range -} diff --git a/src/NpgsqlFSharpAnalyzer/paket.references b/src/NpgsqlFSharpAnalyzer/paket.references index 93db29e..0199b6f 100644 --- a/src/NpgsqlFSharpAnalyzer/paket.references +++ b/src/NpgsqlFSharpAnalyzer/paket.references @@ -1,6 +1,3 @@ Microsoft.SourceLink.GitHub Microsoft.NETFramework.ReferenceAssemblies FSharp.Analyzers.SDK -Npgsql -F23.StringSimilarity -FSharp.Core diff --git a/tests/NpgsqlFSharpAnalyzer.Tests/NpgsqlFSharpAnalyzer.Tests.fsproj b/tests/NpgsqlFSharpAnalyzer.Tests/NpgsqlFSharpAnalyzer.Tests.fsproj index ceba795..c3b04c5 100644 --- a/tests/NpgsqlFSharpAnalyzer.Tests/NpgsqlFSharpAnalyzer.Tests.fsproj +++ b/tests/NpgsqlFSharpAnalyzer.Tests/NpgsqlFSharpAnalyzer.Tests.fsproj @@ -1,24 +1,25 @@ - - Exe - netcoreapp2.0 - true - - - - - - - - - - - - - - - - - - \ No newline at end of file + + Exe + netcoreapp2.0 + true + + + + + + + + + + + + + + + + + + + diff --git a/tests/NpgsqlFSharpAnalyzer.Tests/Tests.fs b/tests/NpgsqlFSharpAnalyzer.Tests/Tests.fs index 788f1c7..020740a 100644 --- a/tests/NpgsqlFSharpAnalyzer.Tests/Tests.fs +++ b/tests/NpgsqlFSharpAnalyzer.Tests/Tests.fs @@ -3,6 +3,7 @@ module Tests open System open Expecto open Npgsql.FSharp.Analyzers +open Npgsql.FSharp.Analyzers.Core open Npgsql.FSharp open ThrowawayDb.Postgres open FSharp.Analyzers.SDK @@ -14,7 +15,9 @@ let analyzers = [ let inline find file = IO.Path.Combine(__SOURCE_DIRECTORY__ , file) let project = IO.Path.Combine(__SOURCE_DIRECTORY__, "../examples/hashing/examples.fsproj") -let inline context file = AnalyzerBootstrap.context file +let inline context file = + AnalyzerBootstrap.context file + |> Option.map SqlAnalyzer.specializedContext let createTestDatabase() = Sql.host "localhost" @@ -108,7 +111,7 @@ let tests = let messages = SqlAnalysis.analyzeOperation block db.ConnectionString schema match messages with | [ message ] -> - Expect.equal Severity.Warning message.Severity "The message is an warning" + Expect.equal Core.Severity.Warning message.Severity "The message is an warning" Expect.stringContains message.Message "Sql.int64" "Message should contain the missing column name" | _ -> failwith "Expected only one error message" @@ -241,7 +244,7 @@ let tests = let messages = SqlAnalysis.analyzeOperation block db.ConnectionString schema match messages with | [ message ] -> - Expect.equal Severity.Warning message.Severity "The message is an warning" + Expect.equal Core.Severity.Warning message.Severity "The message is an warning" Expect.stringContains message.Message "non_existent" "Message should contain the missing column name" | _ -> failwith "Expected only one error message" @@ -266,7 +269,7 @@ let tests = let messages = SqlAnalysis.analyzeOperation block db.ConnectionString schema match messages with | [ message ] -> - Expect.equal Severity.Warning message.Severity "The message is a warning" + Expect.equal Core.Severity.Warning message.Severity "The message is a warning" Expect.stringContains message.Message "Missing parameter 'active'" "Error should say which parameter is not provided" | _ -> failwith "Expected only one error message" From ee807ef64e645be94f42451378069891cd81b642 Mon Sep 17 00:00:00 2001 From: Zaid Date: Mon, 17 Aug 2020 03:20:48 +0200 Subject: [PATCH 2/9] Optimize user experience from VS --- src/AnalyzerVs/LintChecker.cs | 19 ++++++++----------- src/AnalyzerVs/LintError.cs | 4 +++- .../Suggestions/LintActionsSource.cs | 8 ++++---- src/AnalyzerVs/Suggestions/LintFixAction.cs | 6 +++--- src/NpgsqlFSharpAnalyzer.Core/Types.fs | 4 +--- src/NpgsqlFSharpAnalyzer/SqlAnalyzer.fs | 2 -- 6 files changed, 19 insertions(+), 24 deletions(-) diff --git a/src/AnalyzerVs/LintChecker.cs b/src/AnalyzerVs/LintChecker.cs index 8ac9464..d8b2667 100644 --- a/src/AnalyzerVs/LintChecker.cs +++ b/src/AnalyzerVs/LintChecker.cs @@ -203,6 +203,13 @@ public async Task DoUpdateAsync() await Task.Yield(); + var connectionString = SqlAnalyzer.tryFindConnectionString(path); + + if (string.IsNullOrWhiteSpace(connectionString)) + { + return; + } + var defaults = FSharpParsingOptions.Default; var parseOpts = new FSharpParsingOptions( sourceFiles: new string[] { path }, @@ -223,12 +230,6 @@ public async Task DoUpdateAsync() return; } - var connectionString = SqlAnalyzer.tryFindConnectionString(path); - - if (String.IsNullOrWhiteSpace(connectionString)) - { - return; - } var loadedSchema = SqlAnalysis.databaseSchema(connectionString); @@ -241,11 +242,7 @@ public async Task DoUpdateAsync() fileName: path, content: source.Split('\n'), parseTree: parseResults.ParseTree.Value, - typedTree: null, - symbols: FSharpList.Empty, - getAllEntities: FSharpFunc>.FromConverter( - new Converter>(value => FSharpList.Empty) - ) + symbols: FSharpList.Empty ); var operations = SyntacticAnalysis.findSqlOperations(context).ToList(); diff --git a/src/AnalyzerVs/LintError.cs b/src/AnalyzerVs/LintError.cs index 70a285a..71bdd7b 100644 --- a/src/AnalyzerVs/LintError.cs +++ b/src/AnalyzerVs/LintError.cs @@ -28,7 +28,9 @@ public class LintError public bool HasSuggestedFix => LintWarning.Fixes.Any(); - public Fix GetSuggestedFix() => LintWarning.Fixes.First(); + public Fix GetSuggestedFix() => LintWarning.Fixes.FirstOrDefault(); + + public IEnumerable Fixes => LintWarning.Fixes; public int Line => LintWarning.Range.StartLine - 1; diff --git a/src/AnalyzerVs/Suggestions/LintActionsSource.cs b/src/AnalyzerVs/Suggestions/LintActionsSource.cs index 46c88bf..efb633d 100644 --- a/src/AnalyzerVs/Suggestions/LintActionsSource.cs +++ b/src/AnalyzerVs/Suggestions/LintActionsSource.cs @@ -61,10 +61,10 @@ public IEnumerable GetSuggestedActions(SnapshotSpan range) { if (range.IntersectsWith(error.Span)) { - if (error.HasSuggestedFix) - yield return new LintFixAction(error); - - yield return new LintSuppressAction(error); + foreach(var fix in error.Fixes) + { + yield return new LintFixAction(error, fix); + } } } } diff --git a/src/AnalyzerVs/Suggestions/LintFixAction.cs b/src/AnalyzerVs/Suggestions/LintFixAction.cs index 10b9c7b..b21eae8 100644 --- a/src/AnalyzerVs/Suggestions/LintFixAction.cs +++ b/src/AnalyzerVs/Suggestions/LintFixAction.cs @@ -16,10 +16,10 @@ public class LintFixAction : ISuggestedAction private readonly LintError _lintError; private readonly Fix _fix; - public LintFixAction(LintError lintError) + public LintFixAction(LintError lintError, Fix fix) { this._lintError = lintError; - this._fix = _lintError.GetSuggestedFix(); + this._fix = fix; } public string DisplayText => $"Replace with '{_fix.ToText}'"; @@ -36,7 +36,7 @@ public LintFixAction(LintError lintError) public Task> GetActionSetsAsync(CancellationToken cancellationToken) => default; #pragma warning restore RCS1210 - public bool HasPreview => true; + public bool HasPreview => false; public Task GetPreviewAsync(CancellationToken cancellationToken) { diff --git a/src/NpgsqlFSharpAnalyzer.Core/Types.fs b/src/NpgsqlFSharpAnalyzer.Core/Types.fs index 33f9a20..76d4055 100644 --- a/src/NpgsqlFSharpAnalyzer.Core/Types.fs +++ b/src/NpgsqlFSharpAnalyzer.Core/Types.fs @@ -11,9 +11,7 @@ type SpecializedContext = { FileName: string Content: string[] ParseTree: ParsedInput - TypedTree: FSharpImplementationFileContents - Symbols: FSharpEntity list - GetAllEntities: bool -> AssemblySymbol list} + Symbols: FSharpEntity list } type Fix = { FromRange : range diff --git a/src/NpgsqlFSharpAnalyzer/SqlAnalyzer.fs b/src/NpgsqlFSharpAnalyzer/SqlAnalyzer.fs index 4574b69..ab50d6c 100644 --- a/src/NpgsqlFSharpAnalyzer/SqlAnalyzer.fs +++ b/src/NpgsqlFSharpAnalyzer/SqlAnalyzer.fs @@ -32,8 +32,6 @@ module SqlAnalyzer = let specializedContext (ctx: Context) : Core.SpecializedContext = { Content = ctx.Content FileName = ctx.FileName - GetAllEntities = ctx.GetAllEntities - ParseTree = ctx.ParseTree Symbols = ctx.Symbols TypedTree = ctx.TypedTree } From 48b015136ba211c56f2dc273abd06de0b2af4462 Mon Sep 17 00:00:00 2001 From: Zaid Date: Mon, 17 Aug 2020 03:24:48 +0200 Subject: [PATCH 3/9] Fix build --- src/NpgsqlFSharpAnalyzer/SqlAnalyzer.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NpgsqlFSharpAnalyzer/SqlAnalyzer.fs b/src/NpgsqlFSharpAnalyzer/SqlAnalyzer.fs index ab50d6c..5efdc54 100644 --- a/src/NpgsqlFSharpAnalyzer/SqlAnalyzer.fs +++ b/src/NpgsqlFSharpAnalyzer/SqlAnalyzer.fs @@ -33,7 +33,7 @@ module SqlAnalyzer = Content = ctx.Content FileName = ctx.FileName Symbols = ctx.Symbols - TypedTree = ctx.TypedTree + ParseTree = ctx.ParseTree } [] From b3e173952e4bbf07856576ac5a71eeed5fb90b0b Mon Sep 17 00:00:00 2001 From: Zaid Date: Mon, 17 Aug 2020 12:14:08 +0200 Subject: [PATCH 4/9] Proper file type checking for extracting symbols --- NpgsqlFSharpAnalyzer.sln | 4 +- src/AnalyzerVs/ContentTypeNames.cs | 2 +- src/AnalyzerVs/FsLintVsPackage.cs | 4 +- src/AnalyzerVs/LintChecker.cs | 81 +++++++++++-------- src/AnalyzerVs/LintCheckerProvider.cs | 4 +- src/AnalyzerVs/LintError.cs | 7 +- src/AnalyzerVs/LintProjectInfo.cs | 2 +- src/AnalyzerVs/LintTagger.cs | 2 +- ...arpLintVs.csproj => NpgsqlFSharpVs.csproj} | 0 src/AnalyzerVs/Options/FsLintOptionsPage.cs | 2 +- src/AnalyzerVs/SubscriptionManager.cs | 2 +- src/AnalyzerVs/SuggestionPreview.xaml | 4 +- src/AnalyzerVs/SuggestionPreview.xaml.cs | 2 +- .../Suggestions/LintActionsSource.cs | 2 +- src/AnalyzerVs/Suggestions/LintFixAction.cs | 2 +- .../Suggestions/LintSuggestionProvider.cs | 2 +- .../Suggestions/LintSuppressAction.cs | 2 +- src/AnalyzerVs/Suggestions/LintSuppressBy.cs | 2 +- .../Table/LintTableSnapshotFactory.cs | 2 +- src/AnalyzerVs/Table/LintingErrorsSnapshot.cs | 2 +- src/NpgsqlFSharpAnalyzer.Core/SqlAnalysis.fs | 44 +++------- src/NpgsqlFSharpAnalyzer.Core/SqlAnalyzer.fs | 10 +++ .../SyntacticAnalysis.fs | 4 +- src/NpgsqlFSharpAnalyzer.Core/Types.fs | 6 +- src/NpgsqlFSharpAnalyzer/SqlAnalyzer.fs | 4 +- tests/NpgsqlFSharpAnalyzer.Tests/Tests.fs | 7 +- 26 files changed, 101 insertions(+), 104 deletions(-) rename src/AnalyzerVs/{FSharpLintVs.csproj => NpgsqlFSharpVs.csproj} (100%) diff --git a/NpgsqlFSharpAnalyzer.sln b/NpgsqlFSharpAnalyzer.sln index b2622b0..b0a01c0 100644 --- a/NpgsqlFSharpAnalyzer.sln +++ b/NpgsqlFSharpAnalyzer.sln @@ -29,9 +29,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution RELEASE_NOTES.md = RELEASE_NOTES.md EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FSharpLintVs", "src\AnalyzerVs\FSharpLintVs.csproj", "{37577282-1289-40DB-AD3D-24499BD09DAE}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NpgsqlFSharpVs", "src\AnalyzerVs\NpgsqlFSharpVs.csproj", "{37577282-1289-40DB-AD3D-24499BD09DAE}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "NpgsqlFSharpAnalyzer.Core", "src\NpgsqlFSharpAnalyzer.Core\NpgsqlFSharpAnalyzer.Core.fsproj", "{5964BB56-97B8-4FAE-9933-8113DB11438D}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "NpgsqlFSharpAnalyzer.Core", "src\NpgsqlFSharpAnalyzer.Core\NpgsqlFSharpAnalyzer.Core.fsproj", "{5964BB56-97B8-4FAE-9933-8113DB11438D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/src/AnalyzerVs/ContentTypeNames.cs b/src/AnalyzerVs/ContentTypeNames.cs index e60ad0c..736f09b 100644 --- a/src/AnalyzerVs/ContentTypeNames.cs +++ b/src/AnalyzerVs/ContentTypeNames.cs @@ -1,4 +1,4 @@ -namespace FSharpLintVs +namespace NpgsqlFSharpVs { public static class ContentTypeNames { diff --git a/src/AnalyzerVs/FsLintVsPackage.cs b/src/AnalyzerVs/FsLintVsPackage.cs index 1c37c87..849653e 100644 --- a/src/AnalyzerVs/FsLintVsPackage.cs +++ b/src/AnalyzerVs/FsLintVsPackage.cs @@ -9,11 +9,11 @@ using Microsoft.VisualStudio.Shell.Interop; using Task = System.Threading.Tasks.Task; -namespace FSharpLintVs +namespace NpgsqlFSharpVs { // DO NOT REMOVE THIS MAGICAL INCANTATION NO MATTER HOW MUCH VS WARNS YOU OF DEPRECATION // -------------------------------------------------------------------------------------- - [InstalledProductRegistration("F# Lint", "", "0.1", IconResourceID = 400)] + [InstalledProductRegistration("F# Npgsql Analyzer", "Static SQL analyzer with Npgsql.FSharp", "0.1", IconResourceID = 400)] // -------------------------------------------------------------------------------------- // Package registration attributes diff --git a/src/AnalyzerVs/LintChecker.cs b/src/AnalyzerVs/LintChecker.cs index d8b2667..6e4e9fa 100644 --- a/src/AnalyzerVs/LintChecker.cs +++ b/src/AnalyzerVs/LintChecker.cs @@ -1,28 +1,20 @@ -using Dotnet.ProjInfo.Workspace; -using FSharp.Compiler; -using FSharp.Compiler.SourceCodeServices; +using FSharp.Compiler; using FSharp.Compiler.Text; using Npgsql.FSharp.Analyzers.Core; using Microsoft.FSharp.Control; using Microsoft.VisualStudio; -using Microsoft.VisualStudio.Language.StandardClassification; using Microsoft.VisualStudio.Text; -using Microsoft.VisualStudio.Text.Classification; using Microsoft.VisualStudio.Text.Editor; using Microsoft.VisualStudio.Threading; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; -using System.Windows.Controls; -using System.Windows.Threading; using Microsoft.FSharp.Core; -using Microsoft.FSharp.Collections; -namespace FSharpLintVs +namespace NpgsqlFSharpVs { /// /// Finds the linting errors in comments for a specific buffer. @@ -171,12 +163,13 @@ private void RunLinter() public async Task DoUpdateAsync() { if (IsDisposed) + { return; + } var buffer = _currentSnapshot; var path = _document.FilePath; - // replace with user token var token = _cts.Token; var instance = await FsLintVsPackage.Instance.WithCancellation(token); @@ -210,53 +203,73 @@ public async Task DoUpdateAsync() return; } - var defaults = FSharpParsingOptions.Default; - var parseOpts = new FSharpParsingOptions( - sourceFiles: new string[] { path }, - conditionalCompilationDefines: defaults.ConditionalCompilationDefines, - errorSeverityOptions: defaults.ErrorSeverityOptions, - isInteractive: defaults.IsInteractive, - lightSyntax: defaults.LightSyntax, - compilingFsLib: defaults.CompilingFsLib, - isExe: defaults.IsExe - ); + var loadedSchema = SqlAnalysis.databaseSchema(connectionString); + + if (loadedSchema.IsError) + { + return; + } var source = _currentSnapshot.GetText(); var sourceText = SourceText.ofString(source); - var parseAsync = _provider.CheckerInstance.ParseFile(path, sourceText, parseOpts, null); - var parseResults = await FSharpAsync.StartAsTask(parseAsync, null, token); - if (parseResults.ParseHadErrors) + + var getProjectOptions = _provider.CheckerInstance.GetProjectOptionsFromScript( + filename: path, + sourceText: sourceText, + assumeDotNetFramework: false, + useSdkRefs: true, + useFsiAuxLib: true, + previewEnabled: true, + otherFlags: new string[] { "--targetprofile:netstandard" }, + loadedTimeStamp: FSharpOption.None, + extraProjectInfo: FSharpOption.None, + optionsStamp: FSharpOption.None, + userOpName: FSharpOption.None + ); + + var (options, errors) = await FSharpAsync.StartAsTask(getProjectOptions, null, token); + + if (errors.Any()) { return; } + var performParseAndCheck = _provider.CheckerInstance.ParseAndCheckFileInProject( + filename: path, + fileversion: 1, + sourceText: sourceText, + options: options, + textSnapshotInfo: FSharpOption.None, + userOpName: FSharpOption.None + ); - var loadedSchema = SqlAnalysis.databaseSchema(connectionString); + var (parseResults, checkAnswer) = await FSharpAsync.StartAsTask(performParseAndCheck, null, token); - if (loadedSchema.IsError) + if (parseResults.ParseHadErrors || checkAnswer.IsAborted) { return; } - var context = new SpecializedContext( + var checkResults = SqlAnalyzer.checkAnswerResult(checkAnswer).Value; + + var context = new SqlAnalyzerContext( fileName: path, content: source.Split('\n'), parseTree: parseResults.ParseTree.Value, - symbols: FSharpList.Empty + symbols: SqlAnalyzer.getSymbols(checkResults) ); - var operations = SyntacticAnalysis.findSqlOperations(context).ToList(); var databaseSchema = loadedSchema.ResultValue; - var foundErrors = - from operation in operations - from message in SqlAnalysis.analyzeOperation(operation, connectionString, databaseSchema) - select message; + var errorMessages = + from operation in SyntacticAnalysis.findSqlOperations(context) + from analysisOutput in SqlAnalysis.analyzeOperation(operation, connectionString, databaseSchema) + select analysisOutput; var oldLintingErrors = this.Factory.CurrentSnapshot; var newLintErrors = new LintingErrorsSnapshot(_document, oldLintingErrors.VersionNumber + 1); - foreach (var error in foundErrors) + foreach (var error in errorMessages) { var span = RangeToSpan(error.Range, buffer); newLintErrors.Errors.Add(new LintError(span, error, Project)); diff --git a/src/AnalyzerVs/LintCheckerProvider.cs b/src/AnalyzerVs/LintCheckerProvider.cs index e7f8a0e..2f92f47 100644 --- a/src/AnalyzerVs/LintCheckerProvider.cs +++ b/src/AnalyzerVs/LintCheckerProvider.cs @@ -1,5 +1,5 @@ using FSharp.Compiler.SourceCodeServices; -using FSharpLintVs; +using NpgsqlFSharpVs; using Microsoft.VisualStudio.Shell.Interop; using Microsoft.VisualStudio.Shell.TableControl; using Microsoft.VisualStudio.Shell.TableManager; @@ -14,7 +14,7 @@ using System.ComponentModel.Composition; using System.Diagnostics; -namespace FSharpLintVs +namespace NpgsqlFSharpVs { /// /// Factory for the and . diff --git a/src/AnalyzerVs/LintError.cs b/src/AnalyzerVs/LintError.cs index 71bdd7b..990c2ee 100644 --- a/src/AnalyzerVs/LintError.cs +++ b/src/AnalyzerVs/LintError.cs @@ -1,12 +1,9 @@ using Npgsql.FSharp.Analyzers.Core; -using Microsoft.FSharp.Core; using Microsoft.VisualStudio.Text; -using Microsoft.VisualStudio.Utilities; using System.Collections.Generic; -using System.Text; using System.Linq; -namespace FSharpLintVs +namespace NpgsqlFSharpVs { public class LintError { @@ -16,7 +13,7 @@ public class LintError public int NextIndex = -1; - public string Tooltip => $"{LintWarning.Code}: {LintWarning.Message}"; + public string Tooltip => LintWarning.Message; public string Identifier => LintWarning.Type; diff --git a/src/AnalyzerVs/LintProjectInfo.cs b/src/AnalyzerVs/LintProjectInfo.cs index 9e9c2ab..c918218 100644 --- a/src/AnalyzerVs/LintProjectInfo.cs +++ b/src/AnalyzerVs/LintProjectInfo.cs @@ -1,7 +1,7 @@ using Microsoft.VisualStudio.Shell.Interop; using System; -namespace FSharpLintVs +namespace NpgsqlFSharpVs { public class LintProjectInfo { diff --git a/src/AnalyzerVs/LintTagger.cs b/src/AnalyzerVs/LintTagger.cs index 0fcd797..309baa6 100644 --- a/src/AnalyzerVs/LintTagger.cs +++ b/src/AnalyzerVs/LintTagger.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; -namespace FSharpLintVs +namespace NpgsqlFSharpVs { public class LintTagger : ITagger, IDisposable { diff --git a/src/AnalyzerVs/FSharpLintVs.csproj b/src/AnalyzerVs/NpgsqlFSharpVs.csproj similarity index 100% rename from src/AnalyzerVs/FSharpLintVs.csproj rename to src/AnalyzerVs/NpgsqlFSharpVs.csproj diff --git a/src/AnalyzerVs/Options/FsLintOptionsPage.cs b/src/AnalyzerVs/Options/FsLintOptionsPage.cs index 714efeb..38efe7b 100644 --- a/src/AnalyzerVs/Options/FsLintOptionsPage.cs +++ b/src/AnalyzerVs/Options/FsLintOptionsPage.cs @@ -3,7 +3,7 @@ using Microsoft.VisualStudio.Shell; using System.Runtime.InteropServices; -namespace FSharpLintVs +namespace NpgsqlFSharpVs { [Guid(GuidString)] public class FsLintOptionsPage : DialogPage diff --git a/src/AnalyzerVs/SubscriptionManager.cs b/src/AnalyzerVs/SubscriptionManager.cs index ec15fb8..3f413a4 100644 --- a/src/AnalyzerVs/SubscriptionManager.cs +++ b/src/AnalyzerVs/SubscriptionManager.cs @@ -1,7 +1,7 @@ using Microsoft.VisualStudio.Shell.TableManager; using System; -namespace FSharpLintVs +namespace NpgsqlFSharpVs { /// /// Every consumer of data from an provides an to record the changes. We give the consumer diff --git a/src/AnalyzerVs/SuggestionPreview.xaml b/src/AnalyzerVs/SuggestionPreview.xaml index 100cd96..fb818a4 100644 --- a/src/AnalyzerVs/SuggestionPreview.xaml +++ b/src/AnalyzerVs/SuggestionPreview.xaml @@ -1,10 +1,10 @@ - diff --git a/src/AnalyzerVs/SuggestionPreview.xaml.cs b/src/AnalyzerVs/SuggestionPreview.xaml.cs index 570c38f..f15c1ae 100644 --- a/src/AnalyzerVs/SuggestionPreview.xaml.cs +++ b/src/AnalyzerVs/SuggestionPreview.xaml.cs @@ -13,7 +13,7 @@ using System.Windows.Navigation; using System.Windows.Shapes; -namespace FSharpLintVs +namespace NpgsqlFSharpVs { /// /// Interaction logic for SuggestionPreview.xaml diff --git a/src/AnalyzerVs/Suggestions/LintActionsSource.cs b/src/AnalyzerVs/Suggestions/LintActionsSource.cs index efb633d..b7d3e59 100644 --- a/src/AnalyzerVs/Suggestions/LintActionsSource.cs +++ b/src/AnalyzerVs/Suggestions/LintActionsSource.cs @@ -10,7 +10,7 @@ using System.Threading; using System.Threading.Tasks; -namespace FSharpLintVs +namespace NpgsqlFSharpVs { public class LintActionsSource : ISuggestedActionsSource { diff --git a/src/AnalyzerVs/Suggestions/LintFixAction.cs b/src/AnalyzerVs/Suggestions/LintFixAction.cs index b21eae8..fc14c8f 100644 --- a/src/AnalyzerVs/Suggestions/LintFixAction.cs +++ b/src/AnalyzerVs/Suggestions/LintFixAction.cs @@ -9,7 +9,7 @@ using Microsoft.VisualStudio.Text; using Npgsql.FSharp.Analyzers.Core; -namespace FSharpLintVs +namespace NpgsqlFSharpVs { public class LintFixAction : ISuggestedAction { diff --git a/src/AnalyzerVs/Suggestions/LintSuggestionProvider.cs b/src/AnalyzerVs/Suggestions/LintSuggestionProvider.cs index 0dcb90d..29c6541 100644 --- a/src/AnalyzerVs/Suggestions/LintSuggestionProvider.cs +++ b/src/AnalyzerVs/Suggestions/LintSuggestionProvider.cs @@ -4,7 +4,7 @@ using Microsoft.VisualStudio.Utilities; using System.ComponentModel.Composition; -namespace FSharpLintVs +namespace NpgsqlFSharpVs { [Export(typeof(ISuggestedActionsSourceProvider))] [ContentType(ContentTypeNames.FSharpContentType)] diff --git a/src/AnalyzerVs/Suggestions/LintSuppressAction.cs b/src/AnalyzerVs/Suggestions/LintSuppressAction.cs index 78a807c..71e65e0 100644 --- a/src/AnalyzerVs/Suggestions/LintSuppressAction.cs +++ b/src/AnalyzerVs/Suggestions/LintSuppressAction.cs @@ -8,7 +8,7 @@ using System.Threading.Tasks; using System.Windows; -namespace FSharpLintVs +namespace NpgsqlFSharpVs { public class LintSuppressAction : ISuggestedAction { diff --git a/src/AnalyzerVs/Suggestions/LintSuppressBy.cs b/src/AnalyzerVs/Suggestions/LintSuppressBy.cs index 95adc10..9640e50 100644 --- a/src/AnalyzerVs/Suggestions/LintSuppressBy.cs +++ b/src/AnalyzerVs/Suggestions/LintSuppressBy.cs @@ -9,7 +9,7 @@ using System.Threading.Tasks; using System.Windows; -namespace FSharpLintVs +namespace NpgsqlFSharpVs { public class LintSuppressBy : ISuggestedAction { diff --git a/src/AnalyzerVs/Table/LintTableSnapshotFactory.cs b/src/AnalyzerVs/Table/LintTableSnapshotFactory.cs index 74f2891..94b4689 100644 --- a/src/AnalyzerVs/Table/LintTableSnapshotFactory.cs +++ b/src/AnalyzerVs/Table/LintTableSnapshotFactory.cs @@ -1,6 +1,6 @@ using Microsoft.VisualStudio.Shell.TableManager; -namespace FSharpLintVs +namespace NpgsqlFSharpVs { public class LintTableSnapshotFactory : TableEntriesSnapshotFactoryBase { diff --git a/src/AnalyzerVs/Table/LintingErrorsSnapshot.cs b/src/AnalyzerVs/Table/LintingErrorsSnapshot.cs index e0f02ed..ed385d5 100644 --- a/src/AnalyzerVs/Table/LintingErrorsSnapshot.cs +++ b/src/AnalyzerVs/Table/LintingErrorsSnapshot.cs @@ -9,7 +9,7 @@ using System.Windows; using System.Windows.Documents; -namespace FSharpLintVs +namespace NpgsqlFSharpVs { public class LintingErrorsSnapshot : WpfTableEntriesSnapshotBase { diff --git a/src/NpgsqlFSharpAnalyzer.Core/SqlAnalysis.fs b/src/NpgsqlFSharpAnalyzer.Core/SqlAnalysis.fs index b1a2728..923f2f2 100644 --- a/src/NpgsqlFSharpAnalyzer.Core/SqlAnalysis.fs +++ b/src/NpgsqlFSharpAnalyzer.Core/SqlAnalysis.fs @@ -1,5 +1,6 @@ namespace Npgsql.FSharp.Analyzers.Core +open System open FSharp.Compiler.Range open F23.StringSimilarity @@ -205,7 +206,12 @@ module SqlAnalysis = |> List.minBy (fun column -> levenshtein.Distance(attempt.columnName, column.Name)) |> fun column -> column.Name - let warningMsg = sprintf "Attempting to read column named '%s' that was not returned by the result set. Did you mean to read '%s'?\nAvailable columns from the result set are:\n%s" attempt.columnName closestAlternative (formatColumns availableColumns) + let warningMsg = + if String.IsNullOrWhiteSpace attempt.columnName then + sprintf "Attempting to read a column without specifying a name. Available columns returned from the result set are:\n%s" (formatColumns availableColumns) + else + sprintf "Attempting to read column named '%s' that was not returned by the result set. Did you mean to read '%s'?\nAvailable columns from the result set are:\n%s" attempt.columnName closestAlternative (formatColumns availableColumns) + let warning = createWarning warningMsg attempt.columnNameRange let codeFixes = availableColumns @@ -281,8 +287,6 @@ module SqlAnalysis = ("bit"|"bool"|"boolean") -> if column.Nullable && notUsing "boolOrNone" then yield typeMismatch [ replace "boolOrNone" ] - // else if not column.Nullable && using "boolOrNone" - // then yield typeMismatch [ replace "bool" ] else if notUsing "boolOrNone" && notUsing "bool" then if column.Nullable @@ -293,14 +297,6 @@ module SqlAnalysis = | ("int8" | "tinyint") -> if column.Nullable && List.forall notUsing [ "int8OrNone"; "int16OrNone"; "intOrNone"; "int64OrNone" ] then yield typeMismatch [ replace "int8OrNone"; replace "int16OrNone"; replace "intOrNone"; replace "int64OrNone" ] - // else if not column.Nullable && using "int8OrNone" - // then yield typeMismatch [ replace "int8"; replace "int16"; replace "int"; replace "int64" ] - // else if not column.Nullable && using "int16OrNone" - // then yield typeMismatch [ replace "int8"; replace "int16"; replace "int"; replace "int64" ] - // else if not column.Nullable && using "intdOrNone" - // then yield typeMismatch [ replace "int8"; replace "int16"; replace "int"; replace "int64" ] - // else if not column.Nullable && using "int64OrNone" - // then yield typeMismatch [ replace "int8"; replace "int16"; replace "int"; replace "int64" ] else if List.forall notUsing [ "int8OrNone"; "int16OrNone"; "intOrNone"; "int64OrNone"; "int8"; "int16"; "int"; "int64" ] then if column.Nullable @@ -310,25 +306,15 @@ module SqlAnalysis = | ("int16"| "smallint") -> if column.Nullable && List.forall notUsing [ "int16OrNone"; "intOrNone"; "int64OrNone" ] then yield typeMismatch [ replace "int16OrNone"; replace "intOrNone"; replace "int64OrNone" ] - //else if not column.Nullable && using "int16OrNone" - //then yield typeMismatch [ replace "int16"; replace "int"; replace "int64" ] - //else if not column.Nullable && using "intOrNone" - //then yield typeMismatch [ replace "int16"; replace "int"; replace "int64" ] - //else if not column.Nullable && using "int64OrNone" - //then yield typeMismatch [ replace "int16"; replace "int"; replace "int64" ] else if List.forall notUsing [ "int16OrNone"; "intOrNone"; "int64OrNone"; "int16"; "int"; "int64" ] then if column.Nullable then yield typeMismatch [ replace "int16OrNone"; replace "intOrNone"; replace "int64OrNone" ] else yield typeMismatch [ replace "int16"; replace "int"; replace "int64" ] - | ("int"|"integer"|"int32"|"serial"|"int4") -> + | ("int"|"integer"|"int32"|"serial"|"int4"|"int2") -> if column.Nullable && List.forall notUsing [ "intOrNone"; "int64OrNone" ] then yield typeMismatch [ replace "intOrNone"; replace "int64OrNone" ] - // else if not column.Nullable && using "intOrNone" - // then yield typeMismatch [ replace "int"; replace "int64" ] - // else if not column.Nullable && using "int64OrNone" - // then yield typeMismatch [ replace "int"; replace "int64" ] else if List.forall notUsing [ "intOrNone"; "int64OrNone"; "int"; "int64" ] then if column.Nullable @@ -338,8 +324,6 @@ module SqlAnalysis = | ("int64"|"bigint"|"bigserial") -> if column.Nullable && notUsing "int64OrNone" then yield typeMismatch [ replace "int64OrNone" ] - // else if not column.Nullable && using "int64OrNone" - // then yield typeMismatch [ replace "int64" ] else if notUsing "int64OrNone" && notUsing "int64" then if column.Nullable @@ -350,8 +334,6 @@ module SqlAnalysis = | ("numeric"|"decimal"|"money") -> if column.Nullable && notUsing "decimalOrNone" then yield typeMismatch [ replace "decimalOrNone" ] - // else if not column.Nullable && using "decimalOrNone" - // then yield typeMismatch [ replace "decimal" ] else if notUsing "decimalOrNone" && notUsing "decimal" then if column.Nullable @@ -362,8 +344,6 @@ module SqlAnalysis = | "double precision" -> if column.Nullable && notUsing "doubleOrNone" then yield typeMismatch [ replace "doubleOrNone" ] - // else if not column.Nullable && using "doubleOrNone" - // then yield typeMismatch [ replace "double" ] else if notUsing "doubleOrNone" && notUsing "double" then if column.Nullable @@ -371,11 +351,9 @@ module SqlAnalysis = else yield typeMismatch [ replace "double" ] else () - | ("text"|"json"|"xml"|"jsonb") -> + | ("text"|"json"|"xml"|"jsonb"|"varchar") -> if column.Nullable && notUsing "textOrNone" && notUsing "stringOrNone" then yield typeMismatch [ replace "textOrNone"; replace "stringOrNone" ] - //else if not column.Nullable && (using "textOrNone" || using "stringOrNone") - //then yield typeMismatch [ replace "text"; replace "string" ] else if notUsing "textOrNone" && notUsing "text" && notUsing "string" && notUsing "stringOrNone" then if column.Nullable @@ -386,8 +364,6 @@ module SqlAnalysis = | "date" -> if column.Nullable && notUsing "dateOrNone" then yield typeMismatch [ replace "dateOrNone" ] - //else if not column.Nullable && using "dateOrNone" - //then yield typeMismatch [ replace "date" ] else if notUsing "dateOrNone" && notUsing "date" then if column.Nullable @@ -398,8 +374,6 @@ module SqlAnalysis = | ("timestamp"|"timestamp without time zone") -> if column.Nullable && notUsing "timestampOrNone" && notUsing "dateTimeOrNone" then yield typeMismatch [ replace "dateTimeOrNone"; replace "timestampOrNone" ] - //else if not column.Nullable && (using "timestampOrNone" || using "dateTimeOrNone") - //then yield typeMismatch [ replace "dateTime"; replace "timestamp" ] else if notUsing "timestampOrNone" && notUsing "timestamp" && notUsing "dateTimeOrNone" && notUsing "dateTime" then if column.Nullable diff --git a/src/NpgsqlFSharpAnalyzer.Core/SqlAnalyzer.fs b/src/NpgsqlFSharpAnalyzer.Core/SqlAnalyzer.fs index e47dc8c..ae9cded 100644 --- a/src/NpgsqlFSharpAnalyzer.Core/SqlAnalyzer.fs +++ b/src/NpgsqlFSharpAnalyzer.Core/SqlAnalyzer.fs @@ -3,6 +3,7 @@ namespace Npgsql.FSharp.Analyzers.Core open System open System.IO open System.Linq +open FSharp.Compiler.SourceCodeServices module SqlAnalyzer = @@ -14,6 +15,15 @@ module SqlAnalyzer = then path else findParent (DirectoryInfo(path).Parent.FullName) fileToFind + let getSymbols (checkResults: FSharpCheckFileResults) = + checkResults.PartialAssemblySignature.Entities + |> Seq.toList + + let checkAnswerResult checkFileAnswer = + match checkFileAnswer with + | FSharpCheckFileAnswer.Aborted -> None + | FSharpCheckFileAnswer.Succeeded results -> Some results + let tryFindConfig (file: string) = try let parent = (Directory.GetParent file).FullName diff --git a/src/NpgsqlFSharpAnalyzer.Core/SyntacticAnalysis.fs b/src/NpgsqlFSharpAnalyzer.Core/SyntacticAnalysis.fs index 2d80722..21d7849 100644 --- a/src/NpgsqlFSharpAnalyzer.Core/SyntacticAnalysis.fs +++ b/src/NpgsqlFSharpAnalyzer.Core/SyntacticAnalysis.fs @@ -403,7 +403,7 @@ module SyntacticAnalysis = | SynBinding.Binding (access, kind, mustInline, isMutable, attrs, xmlDecl, valData, headPat, returnInfo, expr, range, seqPoint) -> visitSyntacticExpression expr range - let findLiterals (ctx: SpecializedContext) = + let findLiterals (ctx: SqlAnalyzerContext) = let values = new ResizeArray() for symbol in ctx.Symbols |> Seq.collect (fun s -> s.TryGetMembersFunctionsAndValues) do match symbol.LiteralValue with @@ -427,7 +427,7 @@ module SyntacticAnalysis = { operation with blocks = modifiedBlocks } - let findSqlOperations (ctx: SpecializedContext) = + let findSqlOperations (ctx: SqlAnalyzerContext) = let operations = ResizeArray() match ctx.ParseTree with | ParsedInput.ImplFile input -> diff --git a/src/NpgsqlFSharpAnalyzer.Core/Types.fs b/src/NpgsqlFSharpAnalyzer.Core/Types.fs index 76d4055..4903ace 100644 --- a/src/NpgsqlFSharpAnalyzer.Core/Types.fs +++ b/src/NpgsqlFSharpAnalyzer.Core/Types.fs @@ -7,7 +7,7 @@ open FSharp.Compiler open FSharp.Compiler.SyntaxTree open FSharp.Compiler.SourceCodeServices -type SpecializedContext = +type SqlAnalyzerContext = { FileName: string Content: string[] ParseTree: ParsedInput @@ -31,6 +31,10 @@ type Message = Range: range Fixes: Fix list } + with + member self.IsWarning() = self.Severity = Warning + member self.IsInfo() = self.Severity = Info + member self.IsError() = self.Severity = Error type ColumnReadAttempt = { funcName: string; diff --git a/src/NpgsqlFSharpAnalyzer/SqlAnalyzer.fs b/src/NpgsqlFSharpAnalyzer/SqlAnalyzer.fs index 5efdc54..5bcf1ae 100644 --- a/src/NpgsqlFSharpAnalyzer/SqlAnalyzer.fs +++ b/src/NpgsqlFSharpAnalyzer/SqlAnalyzer.fs @@ -29,7 +29,7 @@ module SqlAnalyzer = Type = message.Type } - let specializedContext (ctx: Context) : Core.SpecializedContext = { + let sqlAnalyzerContext (ctx: Context) : Core.SqlAnalyzerContext = { Content = ctx.Content FileName = ctx.FileName Symbols = ctx.Symbols @@ -39,7 +39,7 @@ module SqlAnalyzer = [] let queryAnalyzer : Analyzer = fun (ctx: Context) -> - let syntacticBlocks = Core.SyntacticAnalysis.findSqlOperations (specializedContext ctx) + let syntacticBlocks = Core.SyntacticAnalysis.findSqlOperations (sqlAnalyzerContext ctx) if List.isEmpty syntacticBlocks then [ ] else diff --git a/tests/NpgsqlFSharpAnalyzer.Tests/Tests.fs b/tests/NpgsqlFSharpAnalyzer.Tests/Tests.fs index 020740a..f3fdc8e 100644 --- a/tests/NpgsqlFSharpAnalyzer.Tests/Tests.fs +++ b/tests/NpgsqlFSharpAnalyzer.Tests/Tests.fs @@ -6,7 +6,6 @@ open Npgsql.FSharp.Analyzers open Npgsql.FSharp.Analyzers.Core open Npgsql.FSharp open ThrowawayDb.Postgres -open FSharp.Analyzers.SDK let analyzers = [ SqlAnalyzer.queryAnalyzer @@ -111,7 +110,7 @@ let tests = let messages = SqlAnalysis.analyzeOperation block db.ConnectionString schema match messages with | [ message ] -> - Expect.equal Core.Severity.Warning message.Severity "The message is an warning" + Expect.isTrue (message.IsWarning()) "The message is an warning" Expect.stringContains message.Message "Sql.int64" "Message should contain the missing column name" | _ -> failwith "Expected only one error message" @@ -244,7 +243,7 @@ let tests = let messages = SqlAnalysis.analyzeOperation block db.ConnectionString schema match messages with | [ message ] -> - Expect.equal Core.Severity.Warning message.Severity "The message is an warning" + Expect.isTrue (message.IsWarning()) "The message is an warning" Expect.stringContains message.Message "non_existent" "Message should contain the missing column name" | _ -> failwith "Expected only one error message" @@ -269,7 +268,7 @@ let tests = let messages = SqlAnalysis.analyzeOperation block db.ConnectionString schema match messages with | [ message ] -> - Expect.equal Core.Severity.Warning message.Severity "The message is a warning" + Expect.isTrue (message.IsWarning()) "The message is a warning" Expect.stringContains message.Message "Missing parameter 'active'" "Error should say which parameter is not provided" | _ -> failwith "Expected only one error message" From dd3e64ad4ec748002449b7afdd48988903bc67c5 Mon Sep 17 00:00:00 2001 From: Zaid Date: Mon, 17 Aug 2020 15:52:22 +0200 Subject: [PATCH 5/9] Rebrand the VSIX project to NpgsqlFSharpVs --- src/AnalyzerVs/NpgsqlFSharpVs.csproj | 8 ++++++-- src/AnalyzerVs/Resources/GettingStarted.html | 20 +++++++++++++++++++ src/AnalyzerVs/Resources/License.txt | 5 +++-- src/AnalyzerVs/Resources/ReleaseNotes.html | Bin 1846 -> 228 bytes src/AnalyzerVs/paket.references | 2 -- src/AnalyzerVs/source.extension.vsixmanifest | 11 +++++----- tests/NpgsqlFSharpAnalyzer.Tests/Tests.fs | 2 +- 7 files changed, 36 insertions(+), 12 deletions(-) create mode 100644 src/AnalyzerVs/Resources/GettingStarted.html delete mode 100644 src/AnalyzerVs/paket.references diff --git a/src/AnalyzerVs/NpgsqlFSharpVs.csproj b/src/AnalyzerVs/NpgsqlFSharpVs.csproj index b3263af..f28186e 100644 --- a/src/AnalyzerVs/NpgsqlFSharpVs.csproj +++ b/src/AnalyzerVs/NpgsqlFSharpVs.csproj @@ -16,8 +16,8 @@ Properties 8.0 en - FSharpLintVs - FSharpLintVs + NpgsqlFSharpVs + NpgsqlFSharpVs v4.8 true true @@ -72,6 +72,10 @@ + + true + Always + Always true diff --git a/src/AnalyzerVs/Resources/GettingStarted.html b/src/AnalyzerVs/Resources/GettingStarted.html new file mode 100644 index 0000000..c36c2f4 --- /dev/null +++ b/src/AnalyzerVs/Resources/GettingStarted.html @@ -0,0 +1,20 @@ +

Getting Started

+ +

+ Configure the connection string to your development database +

+ +

+ The analyzer requires a connection string that points to the database you are developing against. You can configure this connection string by either creating a file called NPGSQL_FSHARP (without extension) somewhere next to your F# project or preferably in the root of your workspace. This file should contain that connection string and nothing else. An example of the contents of such file: +

+
+Host=localhost; Username=postgres; Password=postgres; Database=databaseName
+
+

+ Remember to add an entry in your .gitingore file to make sure you don't commit the connection string to your source version control system +

+

+ Another way to configure the connection string is by setting the value of an environment variable named NPGSQL_FSHARP that contains the connection string. + + The analyzer will try to locate and read the file first, then falls back to using the environment variable. +

diff --git a/src/AnalyzerVs/Resources/License.txt b/src/AnalyzerVs/Resources/License.txt index 7844c89..011837c 100644 --- a/src/AnalyzerVs/Resources/License.txt +++ b/src/AnalyzerVs/Resources/License.txt @@ -1,8 +1,9 @@ -Copyright 2020 Asti +MIT LICENSE + +Copyright 2020 Zaid Ajaj Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - diff --git a/src/AnalyzerVs/Resources/ReleaseNotes.html b/src/AnalyzerVs/Resources/ReleaseNotes.html index a6a87646d1577c5f3add3a87166e63b62beee89b..221f5b448df29c2eced7a01bd457a20354df1ee4 100644 GIT binary patch delta 36 mcmdnS_k?jm8K)tG9)kf0PgZ1>W>;VU!^tmM%_n;?@&EvsPzRv^ literal 1846 zcmcJQ-Afx$5XI-Y(Es7$lZ6`d1y!&CMFgSkLsNa%tcjs(5_UI2|M|ARbEoTW+@wj1 z687Wny>sTwoSDh5pC@*29Sb(K#6H@dWp-yN*Nx@e4{T<0D|pM<8`#&C-C$pyc2Ddu zA`R@Vy)mJ7Yp89I`dr7Av>vg6vjHe3$PjoCbDgOP(nl0-PpXQ#j>uEev6` z*}H{V!R`U8_8(+NaAbc!$667NIGfs!XjkEni6-OQEMoQT$lk}*ocpDHiqS9dF|zNG zc^&@{o)!1?(RWs&@4Q;{j$CKw?^m`UgBcMdL>TOmJSuaZfrR&h49tlm|Bv`oAFk|n zRZn3cf1k&tXbbAkYoTMk2HrNUdQUpJt<)^5vaYi8Dr3pX za&i! zj2ahlXU5(Xf2wMo+sr1!+!tV~!zQfMaq1S2Wy#lM1LuF&CfGi6=K~Rr@zSN&RF&@< z_}jFqCdx}rld6WqQ|zQ+pWiW=ZnAXc)L#j4XkM23Kg9LA+$zgbbjZD~p1Q~Jd~$8e zKs8l%nJAZdRV_~8r5akD=+AvSkH4wgtIgo`*5}mSh&p{BD>FO?yWmU4TA2zB#ogzS m)A}FMq*jG1SG(A)o^iV&o*u#4#83U94)Kn4UeC|gRrn1DrW9@f diff --git a/src/AnalyzerVs/paket.references b/src/AnalyzerVs/paket.references deleted file mode 100644 index 0a1dca0..0000000 --- a/src/AnalyzerVs/paket.references +++ /dev/null @@ -1,2 +0,0 @@ -FSharp.Compiler.Service -FSharp.Core diff --git a/src/AnalyzerVs/source.extension.vsixmanifest b/src/AnalyzerVs/source.extension.vsixmanifest index 64772bc..2585756 100644 --- a/src/AnalyzerVs/source.extension.vsixmanifest +++ b/src/AnalyzerVs/source.extension.vsixmanifest @@ -1,15 +1,16 @@  - - F# Lint - F# source code linting using FSharpLint. - https://github.com/deviousasti/fsharp-linting-for-vs + + NpgsqlAnalyzerVs + F# analyzer that provides embedded SQL syntax analysis, type-checking for parameters and result sets and nullable column detection when writing queries using Npgsql.FSharp. + https://github.com/Zaid-Ajaj/Npgsql.FSharp.Analyzer Resources\License.txt + Resources\GettingStarted.html Resources\ReleaseNotes.html Resources\logo.png Resources\logo.png - fsharp, linting + fsharp, linting, sql, static-analysis diff --git a/tests/NpgsqlFSharpAnalyzer.Tests/Tests.fs b/tests/NpgsqlFSharpAnalyzer.Tests/Tests.fs index f3fdc8e..cc25bce 100644 --- a/tests/NpgsqlFSharpAnalyzer.Tests/Tests.fs +++ b/tests/NpgsqlFSharpAnalyzer.Tests/Tests.fs @@ -16,7 +16,7 @@ let project = IO.Path.Combine(__SOURCE_DIRECTORY__, "../examples/hashing/example let inline context file = AnalyzerBootstrap.context file - |> Option.map SqlAnalyzer.specializedContext + |> Option.map SqlAnalyzer.sqlAnalyzerContext let createTestDatabase() = Sql.host "localhost" From f09bdbac7dfb0715a15af6e66bf42eceaf01fb6c Mon Sep 17 00:00:00 2001 From: Zaid Date: Mon, 17 Aug 2020 20:22:53 +0200 Subject: [PATCH 6/9] Update README, Add build project --- README.md | 21 ++++++++++- src/Build/Build.fsproj | 23 ++++++++++++ src/Build/Files.fs | 13 +++++++ src/Build/Program.fs | 81 ++++++++++++++++++++++++++++++++++++++++++ src/Build/Swag.fs | 11 ++++++ src/Build/Tools.fs | 14 ++++++++ 6 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 src/Build/Build.fsproj create mode 100644 src/Build/Files.fs create mode 100644 src/Build/Program.fs create mode 100644 src/Build/Swag.fs create mode 100644 src/Build/Tools.fs diff --git a/README.md b/README.md index 71d3740..5afe711 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ Analyzer that provides embedded **SQL syntax analysis** when writing queries usi - Built-in code fixes for the above - Ability to write multi-line queries in `[]` text and referencing it - Free (MIT licensed) +- Supports VS Code with [Ionide](https://github.com/ionide/ionide-vscode-fsharp) via F# Analyzers SDK +- Supports Visual Studio ## NuGet @@ -21,7 +23,24 @@ Analyzer that provides embedded **SQL syntax analysis** when writing queries usi | NpgsqlFSharpAnalyzer | [![NuGet Badge](https://buildstats.info/nuget/NpgsqlFSharpAnalyzer)](https://www.nuget.org/packages/NpgsqlFSharpAnalyzer/) | [![NuGet Badge](https://buildstats.info/nuget/NpgsqlFSharpAnalyzer?includePreReleases=true)](https://www.nuget.org/packages/NpgsqlFSharpAnalyzer/) | -## Using The Analyzer +## Using The Analyzer (Visual Studio) + +### 1 - Configure the connection string to your development database +The analyzer requires a connection string that points to the database you are developing against. You can configure this connection string by either creating a file called `NPGSQL_FSHARP` (without extension) somewhere next to your F# project or preferably in the root of your workspace. This file should contain that connection string and nothing else. An example of the contents of such file: +``` +Host=localhost; Username=postgres; Password=postgres; Database=databaseName +``` +> Remember to add an entry in your .gitingore file to make sure you don't commit the connection string to your source version control system. + +Another way to configure the connection string is by setting the value of an environment variable named `NPGSQL_FSHARP` that contains the connection string. + +The analyzer will try to locate and read the file first, then falls back to using the environment variable. + +### 2 - Install the Visual Studio Extension + +Download the latest version of `NpgsqlFSharpVs.vsix` from the [Releases](https://github.com/Zaid-Ajaj/Npgsql.FSharp.Analyzer/releases) page and double click the extension to install in on your system. + +## Using The Analyzer (VS Code) ### 1 - Configure the connection string to your development database The analyzer requires a connection string that points to the database you are developing against. You can configure this connection string by either creating a file called `NPGSQL_FSHARP` (without extension) somewhere next to your F# project or preferably in the root of your workspace. This file should contain that connection string and nothing else. An example of the contents of such file: diff --git a/src/Build/Build.fsproj b/src/Build/Build.fsproj new file mode 100644 index 0000000..7812b39 --- /dev/null +++ b/src/Build/Build.fsproj @@ -0,0 +1,23 @@ + + + + Exe + netcoreapp3.1 + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Build/Files.fs b/src/Build/Files.fs new file mode 100644 index 0000000..670c882 --- /dev/null +++ b/src/Build/Files.fs @@ -0,0 +1,13 @@ +[] +module Files + +open System.IO +open System.Linq + +/// Recursively tries to find the parent of a file starting from a directory +let rec findParent (directory: string) (fileToFind: string) = + let path = if Directory.Exists(directory) then directory else Directory.GetParent(directory).FullName + let files = Directory.GetFiles(path) + if files.Any(fun file -> Path.GetFileName(file).ToLower() = fileToFind.ToLower()) + then path + else findParent (DirectoryInfo(path).Parent.FullName) fileToFind \ No newline at end of file diff --git a/src/Build/Program.fs b/src/Build/Program.fs new file mode 100644 index 0000000..ed2a7a7 --- /dev/null +++ b/src/Build/Program.fs @@ -0,0 +1,81 @@ +open System +open System.IO +open Fake.IO + +let targets = ResizeArray unit)>() + +let target name f = targets.Add(name, f) + +let rec retry n f = + if n = 0 then + ignore() + else + try f() + with ex -> + System.Threading.Thread.Sleep(1000) + retry (n - 1) f + +// Paths to different directories in the solution +let path xs = Path.Combine(Array.ofList xs) +let solutionRoot = Files.findParent __SOURCE_DIRECTORY__ "NpgsqlFSharpAnalyzer.sln"; +let analyzerCore = path [ solutionRoot; "src"; "NpgsqlFSharpAnalyzer" ] +let analyzer = path [ solutionRoot; "src"; "NpgsqlFSharpAnalyzer" ] +let analyzerVs = path [ solutionRoot; "src"; "NpgsqlFSharpVs" ] +let tests = path [ solutionRoot; "tests"; "NpgsqlFSharpAnalyzer.Tests" ] + +let clean() = + retry 5 <| fun _ -> List.iter Shell.deleteDir [ + path [ analyzerCore; "bin" ] + path [ analyzerCore; "obj" ] + path [ analyzer; "bin" ] + path [ analyzer; "obj" ] + path [ analyzerVs; "bin" ] + path [ analyzerVs; "obj" ] + path [ tests; "bin" ] + path [ tests; "obj" ] + ] + +let build() = Tools.dotnet "build -c Release" solutionRoot +let test() = Tools.dotnet "run" tests + +target "Clean" clean + +target "Test" (fun _ -> + clean() + test() +) + +target "Build" (fun _ -> + clean() + build() +) + +target "Default" test + +let run target = + targets + |> Seq.find (fun (t, f) -> t = target) + |> fun (target, execute) -> execute() + +[] +let main args = + Console.WriteLine(Swag.logo) + + try + match args with + | [| "RunDefaultOr" |] -> run "Default" + | [| "RunDefaultOr"; target |] -> run target + | _ -> + Console.WriteLine("[Interactive Mode] Available Targets: ") + for (addedTarget, execute) in targets do Console.WriteLine(sprintf " | -- %s" addedTarget); + Console.WriteLine() + Console.Write("[Interactive Mode] Run build target: ") + let target = Console.ReadLine() + if not (targets |> Seq.exists (fun (t, f) -> t = target)) then + Console.WriteLine(sprintf "Target %s was not recognized" target) + else + run target + 0 + with ex -> + printfn "%s" ex.Message + 1 diff --git a/src/Build/Swag.fs b/src/Build/Swag.fs new file mode 100644 index 0000000..1b2ed1a --- /dev/null +++ b/src/Build/Swag.fs @@ -0,0 +1,11 @@ +module Swag + +let logo = """ +________ _ ___ ____ ________ +|_ __ | / \ |_ ||_ _| |_ __ | + | |_ \_| / _ \ | |_/ / | |_ \_| + | _| / ___ \ | __'. | _| _ +_| |_ _/ / \ \_ _| | \ \_ _| |__/ | +|_____||____| |____||____||____||________| + +""" diff --git a/src/Build/Tools.fs b/src/Build/Tools.fs new file mode 100644 index 0000000..1687e43 --- /dev/null +++ b/src/Build/Tools.fs @@ -0,0 +1,14 @@ +[] +module Tools + +open Fake.IO +open Nuke.Common.Tooling +open Fake.Core + +let dotnetPath = ToolPathResolver.GetPathExecutable("dotnet") +let npm = ToolPathResolver.GetPathExecutable("npm") +let node = ToolPathResolver.GetPathExecutable("node") + +let dotnet argument workingDir = + if Shell.Exec(dotnetPath, argument, workingDir) <> 0 + then failwithf "FAILED %s> dotnet %s" workingDir argument From 345424ce57f88603bbd8d12186a0811faef59072 Mon Sep 17 00:00:00 2001 From: Zaid Date: Mon, 17 Aug 2020 21:12:09 +0200 Subject: [PATCH 7/9] De-paketize tests project --- .../NpgsqlFSharpAnalyzer.Tests.fsproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/NpgsqlFSharpAnalyzer.Tests/NpgsqlFSharpAnalyzer.Tests.fsproj b/tests/NpgsqlFSharpAnalyzer.Tests/NpgsqlFSharpAnalyzer.Tests.fsproj index c3b04c5..5348b79 100644 --- a/tests/NpgsqlFSharpAnalyzer.Tests/NpgsqlFSharpAnalyzer.Tests.fsproj +++ b/tests/NpgsqlFSharpAnalyzer.Tests/NpgsqlFSharpAnalyzer.Tests.fsproj @@ -18,8 +18,8 @@ - + + - From c2fe262c48cb74e1923ce5be6f286aaa4e02cc6d Mon Sep 17 00:00:00 2001 From: Zaid Date: Mon, 17 Aug 2020 21:37:46 +0200 Subject: [PATCH 8/9] Fix build script and remove docs project --- build.fsx | 85 +-- docsSrc/Explanations/Background.md | 3 - docsSrc/How_Tos/Doing_A_Thing.md | 2 - docsSrc/How_Tos/Doing_Another_Thing.md | 2 - docsSrc/Tutorials/Getting_Started.md | 13 - docsSrc/content/cleanups.js | 5 - docsSrc/content/hotload.js | 4 - docsSrc/content/style.css | 333 ---------- docsSrc/content/submenu.js | 21 - docsSrc/content/themes.js | 82 --- docsSrc/content/tips.js | 46 -- docsSrc/content/toggle-bootstrap-dark.min.css | 1 - docsSrc/content/toggle-bootstrap.min.css | 1 - docsSrc/files/placeholder.md | 1 - docsSrc/index.md | 60 -- docsTool/CLI.fs | 51 -- docsTool/Prelude.fs | 11 - docsTool/Program.fs | 586 ------------------ docsTool/README.md | 117 ---- docsTool/docsTool.fsproj | 25 - docsTool/paket.references | 12 - docsTool/templates/helpers.fs | 47 -- docsTool/templates/master.fs | 156 ----- docsTool/templates/modules.fs | 126 ---- docsTool/templates/namespaces.fs | 73 --- docsTool/templates/nav.fs | 189 ------ docsTool/templates/partMembers.fs | 135 ---- docsTool/templates/partNested.fs | 77 --- docsTool/templates/types.fs | 113 ---- src/AnalyzerVs/NpgsqlFSharpVs.csproj | 373 +---------- src/AnalyzerVs/paket.references | 1 + src/Build/Build.fsproj | 23 - src/Build/Files.fs | 13 - src/Build/Program.fs | 81 --- src/Build/Swag.fs | 11 - src/Build/Tools.fs | 14 - .../NpgsqlFSharpAnalyzer.Core.fsproj | 1 - src/NpgsqlFSharpAnalyzer.Core/Types.fs | 2 - .../paket.references | 5 - 39 files changed, 13 insertions(+), 2888 deletions(-) delete mode 100644 docsSrc/Explanations/Background.md delete mode 100644 docsSrc/How_Tos/Doing_A_Thing.md delete mode 100644 docsSrc/How_Tos/Doing_Another_Thing.md delete mode 100644 docsSrc/Tutorials/Getting_Started.md delete mode 100644 docsSrc/content/cleanups.js delete mode 100644 docsSrc/content/hotload.js delete mode 100644 docsSrc/content/style.css delete mode 100644 docsSrc/content/submenu.js delete mode 100644 docsSrc/content/themes.js delete mode 100644 docsSrc/content/tips.js delete mode 100644 docsSrc/content/toggle-bootstrap-dark.min.css delete mode 100644 docsSrc/content/toggle-bootstrap.min.css delete mode 100644 docsSrc/files/placeholder.md delete mode 100644 docsSrc/index.md delete mode 100644 docsTool/CLI.fs delete mode 100644 docsTool/Prelude.fs delete mode 100644 docsTool/Program.fs delete mode 100644 docsTool/README.md delete mode 100644 docsTool/docsTool.fsproj delete mode 100644 docsTool/paket.references delete mode 100644 docsTool/templates/helpers.fs delete mode 100644 docsTool/templates/master.fs delete mode 100644 docsTool/templates/modules.fs delete mode 100644 docsTool/templates/namespaces.fs delete mode 100644 docsTool/templates/nav.fs delete mode 100644 docsTool/templates/partMembers.fs delete mode 100644 docsTool/templates/partNested.fs delete mode 100644 docsTool/templates/types.fs create mode 100644 src/AnalyzerVs/paket.references delete mode 100644 src/Build/Build.fsproj delete mode 100644 src/Build/Files.fs delete mode 100644 src/Build/Program.fs delete mode 100644 src/Build/Swag.fs delete mode 100644 src/Build/Tools.fs delete mode 100644 tests/NpgsqlFSharpAnalyzer.Tests/paket.references diff --git a/build.fsx b/build.fsx index 186bc5e..a5aa115 100644 --- a/build.fsx +++ b/build.fsx @@ -1,5 +1,4 @@ #load ".fake/build.fsx/intellisense.fsx" -#load "docsTool/CLI.fs" #if !FAKE #r "Facades/netstandard" #r "netstandard" @@ -73,11 +72,6 @@ let distGlob = distDir @@ "*.nupkg" let coverageThresholdPercent = 1 let coverageReportDir = __SOURCE_DIRECTORY__ @@ "docs" @@ "coverage" - -let docsDir = __SOURCE_DIRECTORY__ @@ "docs" -let docsSrcDir = __SOURCE_DIRECTORY__ @@ "docsSrc" -let docsToolDir = __SOURCE_DIRECTORY__ @@ "docsTool" - let releaseNotes = Fake.Core.ReleaseNotes.load "RELEASE_NOTES.md" let publishUrl = "https://www.nuget.org" @@ -140,40 +134,6 @@ module dotnet = let fcswatch optionConfig args = tool optionConfig "fcswatch" args -open DocsTool.CLIArgs -module DocsTool = - open Argu - let buildparser = ArgumentParser.Create(programName = "docstool") - let buildCLI = - [ - BuildArgs.ProjectGlob srcGlob - BuildArgs.DocsOutputDirectory docsDir - BuildArgs.DocsSourceDirectory docsSrcDir - BuildArgs.ReleaseVersion releaseNotes.NugetVersion - ] - |> buildparser.PrintCommandLineArgumentsFlat - - let build () = - dotnet.run (fun args -> - { args with WorkingDirectory = docsToolDir } - ) (sprintf " -- build %s" (buildCLI)) - |> failOnBadExitAndPrint - - let watchparser = ArgumentParser.Create(programName = "docstool") - let watchCLI = - [ - WatchArgs.ProjectGlob srcGlob - WatchArgs.DocsSourceDirectory docsSrcDir - WatchArgs.ReleaseVersion releaseNotes.NugetVersion - ] - |> watchparser.PrintCommandLineArgumentsFlat - - let watch projectpath = - dotnet.watch (fun args -> - { args with WorkingDirectory = docsToolDir } - ) "run" (sprintf "-- watch %s" (watchCLI)) - |> failOnBadExitAndPrint - //----------------------------------------------------------------------------- // Target Implementations //----------------------------------------------------------------------------- @@ -195,14 +155,17 @@ let clean _ = |> Seq.iter Shell.rm let dotnetRestore _ = - let restoreExitCode = Shell.Exec("dotnet", "restore", __SOURCE_DIRECTORY__) - if restoreExitCode <> 0 - then failwith "Restore failed" + () -let dotnetBuild _ = - let buildResult = Shell.Exec("dotnet", "build", __SOURCE_DIRECTORY__) +let build dir = + let buildResult = Shell.Exec("dotnet", "build -c Release", dir) if buildResult <> 0 - then failwith "dotnet build failed" + then failwithf "FAILED %s> dotnet build -c Release" dir + +let dotnetBuild _ = + build (__SOURCE_DIRECTORY__ "src" "NpgsqlFSharpAnalyzer.Core") + build (__SOURCE_DIRECTORY__ "src" "NpgsqlFSharpAnalyzer") + build (__SOURCE_DIRECTORY__ "tests" "NpgsqlFSharpAnalyzer.Tests") let dotnetTest ctx = let testResult = Shell.Exec("dotnet", "run", "tests" "NpgsqlFSharpAnalyzer.Tests") @@ -340,24 +303,6 @@ let publishToNuget _ = if exitCode <> 0 then failwith "Could not publish package" -let buildDocs _ = - DocsTool.build () - -let watchDocs _ = - let watchBuild () = - !! srcGlob - |> Seq.map(fun proj -> fun () -> - dotnet.watch - (fun opt -> - opt |> DotNet.Options.withWorkingDirectory (IO.Path.GetDirectoryName proj)) - "build" - "" - |> ignore - ) - |> Seq.iter (invokeAsync >> Async.Catch >> Async.Ignore >> Async.Start) - watchBuild () - DocsTool.watch () - //----------------------------------------------------------------------------- // Target Declaration @@ -373,8 +318,6 @@ Target.create "GenerateAssemblyInfo" generateAssemblyInfo Target.create "DotnetPack" dotnetPack Target.create "PublishToNuGet" publishToNuget Target.create "Release" ignore -Target.create "BuildDocs" buildDocs -Target.create "WatchDocs" watchDocs //----------------------------------------------------------------------------- // Target Dependencies @@ -390,16 +333,8 @@ Target.create "WatchDocs" watchDocs "GenerateAssemblyInfo" ?=> "DotnetBuild" "GenerateAssemblyInfo" ==> "PublishToNuGet" -"DotnetBuild" ==> "BuildDocs" -"BuildDocs" ?=> "PublishToNuget" -"DotnetPack" ?=> "BuildDocs" - -"DotnetBuild" ==> "WatchDocs" - -"DotnetRestore" - ==> "DotnetBuild" +"DotnetBuild" ==> "DotnetTest" - =?> ("GenerateCoverageReport", not disableCodeCoverage) ==> "DotnetPack" ==> "PublishToNuGet" ==> "Release" diff --git a/docsSrc/Explanations/Background.md b/docsSrc/Explanations/Background.md deleted file mode 100644 index 43b3465..0000000 --- a/docsSrc/Explanations/Background.md +++ /dev/null @@ -1,3 +0,0 @@ -# Background - -Here's a core concept and reasons why this exists at a deeper level. diff --git a/docsSrc/How_Tos/Doing_A_Thing.md b/docsSrc/How_Tos/Doing_A_Thing.md deleted file mode 100644 index 032520a..0000000 --- a/docsSrc/How_Tos/Doing_A_Thing.md +++ /dev/null @@ -1,2 +0,0 @@ -# How To do this specific thing - diff --git a/docsSrc/How_Tos/Doing_Another_Thing.md b/docsSrc/How_Tos/Doing_Another_Thing.md deleted file mode 100644 index 032520a..0000000 --- a/docsSrc/How_Tos/Doing_Another_Thing.md +++ /dev/null @@ -1,2 +0,0 @@ -# How To do this specific thing - diff --git a/docsSrc/Tutorials/Getting_Started.md b/docsSrc/Tutorials/Getting_Started.md deleted file mode 100644 index c86e550..0000000 --- a/docsSrc/Tutorials/Getting_Started.md +++ /dev/null @@ -1,13 +0,0 @@ -# Getting Started - -```fsharp -let foo = () -let myAge = 21 -``` - -## Here is the path to downloading - - [lang=bash] - paket install BinaryDefense.FSharp.Analyzers - - diff --git a/docsSrc/content/cleanups.js b/docsSrc/content/cleanups.js deleted file mode 100644 index 79871b2..0000000 --- a/docsSrc/content/cleanups.js +++ /dev/null @@ -1,5 +0,0 @@ -$(function() { - // Makes code snippets responsive - $("table").addClass("table-responsive"); -}) - diff --git a/docsSrc/content/hotload.js b/docsSrc/content/hotload.js deleted file mode 100644 index c146f7f..0000000 --- a/docsSrc/content/hotload.js +++ /dev/null @@ -1,4 +0,0 @@ -var refreshSocket = new WebSocket('ws://' + window.location.host) - .onmessage = () => { - location.reload(); - } diff --git a/docsSrc/content/style.css b/docsSrc/content/style.css deleted file mode 100644 index b0ba005..0000000 --- a/docsSrc/content/style.css +++ /dev/null @@ -1,333 +0,0 @@ -@import url(https://fonts.googleapis.com/css?family=Droid+Sans|Droid+Sans+Mono|Open+Sans:400,600,700); - -/*-------------------------------------------------------------------------- - Formatting for F# code snippets -/*--------------------------------------------------------------------------*/ - -/* strings --- and styles for other string related formats */ -span.s { color:#E0E268; } -/* printf formatters */ -span.pf { color:#E0C57F; } -/* escaped chars */ -span.e { color:#EA8675; } - -/* identifiers --- and styles for more specific identifier types */ -span.i { color:#d1d1d1; } -/* type or module */ -span.t { color:#43AEC6; } -/* function */ -span.f { color:#e1e1e1; } -/* DU case or active pattern */ -span.p { color:#4ec9b0; } - -/* keywords */ -span.k { color:#FAB11D; } -/* comment */ -span.c { color:#808080; } -/* operators */ -span.o { color:#af75c1; } -/* numbers */ -span.n { color:#96C71D; } -/* line number */ -span.l { color:#80b0b0; } -/* mutable var or ref cell */ -span.v { color:#d1d1d1; font-weight: bold; } -/* inactive code */ -span.inactive { color:#808080; } -/* preprocessor */ -span.prep { color:#af75c1; } -/* fsi output */ -span.fsi { color:#808080; } - -/* omitted */ -span.omitted { - background:#3c4e52; - border-radius:5px; - color:#808080; - padding:0px 0px 1px 0px; -} -/* tool tip */ -div.tip { - background:#475b5f; - border-radius:4px; - font:11pt 'Droid Sans', arial, sans-serif; - padding:6px 8px 6px 8px; - display:none; - color:#d1d1d1; - pointer-events:none; -} -table.pre pre { - padding:0px; - margin:0px; - border:none; -} -table.pre, pre.fssnip, pre { - line-height:13pt; - /*border:1px solid #d8d8d8;*/ - border:1px solid #000; - /* border: none; */ - border-collapse:separate; - white-space:pre-wrap; - font: 9pt 'Droid Sans Mono',consolas,monospace; - width:90%; - margin:10px 20px 20px 20px; - background-color:#212d30; - padding:10px; - /*border-radius:5px;*/ - color:#d1d1d1; - max-width: none; -} -pre.fssnip code { - font: 9pt 'Droid Sans Mono',consolas,monospace; -} -table.pre pre { - padding:0px; - margin:0px; - border-radius:0px; - width: 100%; -} -table.pre td { - padding:0px; - white-space:normal; - margin:0px; -} -table.pre td.lines { - width:30px; -} - -.table thead td.fit, -.table th.fit { - white-space: nowrap; - width: 1%; -} -/*-------------------------------------------------------------------------- - Formatting for page & standard document content -/*--------------------------------------------------------------------------*/ - -body { - font-family: 'Open Sans', serif; -} - -pre { - word-wrap: inherit; -} - -/* Format the heading - nicer spacing etc. */ -.masthead { - overflow: hidden; -} -.masthead .muted a { - text-decoration:none; - color:#999999; -} -.masthead ul, .masthead li { - margin-bottom:0px; -} -.masthead .nav li { - margin-top: 15px; - font-size:110%; -} -.masthead h3 { - margin-bottom:5px; - font-size:170%; -} -hr { - margin:0px 0px 20px 0px; -} - -/* Make table headings and td.title bold */ -td.title, thead { - font-weight:bold; -} - -/* Format the right-side menu */ -#menu { - margin-top:50px; - font-size:11pt; - padding-left:20px; -} - -#menu .nav-header { - font-size:12pt; - color:#606060; - margin-top:20px; -} - -#menu li { - line-height:25px; -} - -.wrapper { - margin-top: -56px; - padding-top: 56px; -} - -/* Change font sizes for headings etc. */ -#main h1 { font-size: 26pt; margin:10px 0px 15px 0px; font-weight:400; } -#main h2 { font-size: 20pt; margin:20px 0px 0px 0px; font-weight:400; } -#main h3 { font-size: 14pt; margin:15px 0px 0px 0px; font-weight:600; } -#main p { font-size: 11pt; margin:5px 0px 15px 0px; } -#main ul { font-size: 11pt; margin-top:10px; } -#main li { font-size: 11pt; margin: 5px 0px 5px 0px; } -#main strong { font-weight:700; } - -/*-------------------------------------------------------------------------- - Formatting for API reference -/*--------------------------------------------------------------------------*/ - -.type-list .type-name, .module-list .module-name { - width:25%; - font-weight:bold; -} -.member-list .member-name { - width:35%; -} -#main .xmldoc h2 { - font-size:14pt; - margin:10px 0px 0px 0px; -} -#main .xmldoc h3 { - font-size:12pt; - margin:10px 0px 0px 0px; -} -.github-link { - float:right; - text-decoration:none; -} -.github-link img { - border-style:none; - margin-left:10px; -} -.github-link .hover { display:none; } -.github-link:hover .hover { display:block; } -.github-link .normal { display: block; } -.github-link:hover .normal { display: none; } - -/*-------------------------------------------------------------------------- - Links -/*--------------------------------------------------------------------------*/ - -.bootstrap h1 a, .bootstrap h1 a:hover, .bootstrap h1 a:focus, -.bootstrap h2 a, .bootstrap h2 a:hover, .bootstrap h2 a:focus, -.bootstrap h3 a, .bootstrap h3 a:hover, .bootstrap h3 a:focus, -.bootstrap h4 a, .bootstrap h4 a:hover, .bootstrap h4 a:focus, -.bootstrap h5 a, .bootstrap h5 a:hover, .bootstrap h5 a:focus, -.bootstrap h6 a, .bootstrap h6 a:hover, .bootstrap h6 a:focus { color : inherit; text-decoration : inherit; outline:none } - -/*-------------------------------------------------------------------------- - Additional formatting for the homepage -/*--------------------------------------------------------------------------*/ - -#nuget { - margin-top:20px; - font-size: 11pt; - padding:20px; -} - -#nuget pre { - font-size:11pt; - -moz-border-radius: 0px; - -webkit-border-radius: 0px; - border-radius: 0px; - background: #404040; - border-style:none; - color: #e0e0e0; - margin-top:15px; -} - -.date { - font-style: italic; - margin-bottom: 15px; -} - -h1.header { - color: green; -} - -h1.header:hover { - color: green; -} - -h1.header:visited { - color: green; -} - -.categories, .category, .recent-posts { - font-family: 'Droid Sans', arial, sans-serif; -} - -.categories ul, -.recent-posts ul { - margin-left: 0; -} -.categories li, -.category li, -.recent-posts li -{ - list-style-type: none; - white-space: nowrap; -} - -.links { - text-align: center; - margin-bottom: 8px; -} - -.copyright { - text-align: center; - color: lightslategray; - margin-bottom: 25px; -} - -.social { - margin-bottom: 30px; -} - -/* Fixes page anchors with bootstrap navbar */ -:target::before { - display: block; - height: 59px; - margin-top: -59px; - content: ""; -} - -/* Hides first br from FSharp.Literate xml-doc rendering */ -.comment-block > br:first-child, -.xmldoc > br:first-child { - display: none; -} - -.main h1 { - padding: .5em 0em -} - -.main h2 { - padding: .5em 0em -} - -.dropdown-submenu { - position: relative; -} - -.dropdown-submenu>a:after { - content: "\f0da"; - padding-left: 5px; - vertical-align: middle; - border: none; - font-weight: 900; - font-family: 'Font Awesome 5 Free'; -} - -.dropdown-submenu>.dropdown-menu { - top: 0; - left: 100%; - margin-top: 0px; - margin-left: 0px; -} - -.fsharp-footer-logo { - width: 20px; - margin-top: -2px; - -webkit-filter: grayscale(100%) brightness(0) invert(1); /* Safari 6.0 - 9.0 */ - filter: grayscale(100%) brightness(0) invert(1); -} diff --git a/docsSrc/content/submenu.js b/docsSrc/content/submenu.js deleted file mode 100644 index 9874084..0000000 --- a/docsSrc/content/submenu.js +++ /dev/null @@ -1,21 +0,0 @@ -$(function() { - // ------------------------------------------------------- // - // Multi Level dropdowns - // ------------------------------------------------------ // - $("ul.dropdown-menu [data-toggle='dropdown']").on("click", function(event) { - event.preventDefault(); - event.stopPropagation(); - - $(this).siblings().toggleClass("show"); - - - if (!$(this).next().hasClass('show')) { - $(this).parents('.dropdown-menu').first().find('.show').removeClass("show"); - } - $(this).parents('li.nav-item.dropdown.show').on('hidden.bs.dropdown', function(e) { - $('.dropdown-submenu .show').removeClass("show"); - }); - - }); - }); - \ No newline at end of file diff --git a/docsSrc/content/themes.js b/docsSrc/content/themes.js deleted file mode 100644 index 7bb300d..0000000 --- a/docsSrc/content/themes.js +++ /dev/null @@ -1,82 +0,0 @@ - -var themes = { - "light" : { - "button-text" : "Swap to Dark", - "button-classes" : "btn btn-dark border-light", - "next-theme" : "dark", - "body-class" : "bootstrap" - }, - "dark" : { - "button-text" : "Swap to Light", - "button-classes" : "btn btn-light", - "next-theme" : "light", - "body-class" : "bootstrap-dark" - } -}; - -var themeStorageKey = 'theme'; - -function swapThemeInDom(theme) { - var newTheme = themes[theme]; - var bootstrapCSS = document.getElementsByTagName('body')[0]; - bootstrapCSS.setAttribute('class', newTheme['body-class']) -} - -function persistNewTheme(theme) { - window.localStorage.setItem(themeStorageKey, theme); -} - -function setToggleButton(theme) { - var newTheme = themes[theme]; - var themeToggleButton = document.getElementById('theme-toggle'); - themeToggleButton.textContent = newTheme['button-text']; - themeToggleButton.className = newTheme['button-classes']; - themeToggleButton.onclick = function() { - setTheme(newTheme['next-theme']); - } -} - -function setTheme(theme) { - try { - swapThemeInDom(theme); - } - catch(e){ - } - try { - persistNewTheme(theme); - } - catch(e) { - } - try { - setToggleButton(theme); - } - catch (e) { - } -} - -function getThemeFromStorage() { - return window.localStorage.getItem(themeStorageKey); -} - -function getThemeFromScheme() { - try { - if (window.matchMedia("(prefers-color-scheme: dark)").matches){ - return 'dark'; - } - else { - return 'light'; - } - } - catch(e) { - return null; - } -} - -function loadTheme() { - var theme = getThemeFromStorage() || getThemeFromScheme() || 'light'; - setTheme(theme); -} - -document.addEventListener('readystatechange', (event) => { - loadTheme() -}); diff --git a/docsSrc/content/tips.js b/docsSrc/content/tips.js deleted file mode 100644 index e7ee730..0000000 --- a/docsSrc/content/tips.js +++ /dev/null @@ -1,46 +0,0 @@ -var currentTip = null; -var currentTipElement = null; - -function hideTip(evt, name, unique) { - var el = document.getElementById(name); - el.style.display = "none"; - currentTip = null; -} - -function findPos(obj) { - // no idea why, but it behaves differently in webbrowser component - if (window.location.search == "?inapp") - return [obj.offsetLeft + 10, obj.offsetTop + 30]; - - var curleft = 0; - var curtop = obj.offsetHeight; - while (obj) { - curleft += obj.offsetLeft; - curtop += obj.offsetTop; - obj = obj.offsetParent; - }; - return [curleft, curtop]; -} - -function hideUsingEsc(e) { - if (!e) { e = event; } - hideTip(e, currentTipElement, currentTip); -} - -function showTip(evt, name, unique, owner) { - document.onkeydown = hideUsingEsc; - if (currentTip == unique) return; - currentTip = unique; - currentTipElement = name; - - var pos = findPos(owner ? owner : (evt.srcElement ? evt.srcElement : evt.target)); - var posx = pos[0]; - var posy = pos[1]; - - var el = document.getElementById(name); - var parent = (document.documentElement == null) ? document.body : document.documentElement; - el.style.position = "absolute"; - el.style.left = posx + "px"; - el.style.top = posy + "px"; - el.style.display = "block"; -} diff --git a/docsSrc/content/toggle-bootstrap-dark.min.css b/docsSrc/content/toggle-bootstrap-dark.min.css deleted file mode 100644 index 348ff58..0000000 --- a/docsSrc/content/toggle-bootstrap-dark.min.css +++ /dev/null @@ -1 +0,0 @@ -html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}body.bootstrap-dark{margin:0;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";font-size:1rem;font-weight:400;line-height:1.5;color:#d3d3d3;text-align:left;background-color:#191d21}.bootstrap-dark :root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--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";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}.bootstrap-dark *,.bootstrap-dark ::after,.bootstrap-dark ::before{-webkit-box-sizing:border-box;box-sizing:border-box}.bootstrap-dark html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}.bootstrap-dark article,.bootstrap-dark aside,.bootstrap-dark figcaption,.bootstrap-dark figure,.bootstrap-dark footer,.bootstrap-dark header,.bootstrap-dark hgroup,.bootstrap-dark main,.bootstrap-dark nav,.bootstrap-dark section{display:block}.bootstrap-dark body{margin:0;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";font-size:1rem;font-weight:400;line-height:1.5;color:#d3d3d3;text-align:left;background-color:#191d21}.bootstrap-dark [tabindex="-1"]:focus:not(:focus-visible){outline:0!important}.bootstrap-dark hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}.bootstrap-dark h1,.bootstrap-dark h2,.bootstrap-dark h3,.bootstrap-dark h4,.bootstrap-dark h5,.bootstrap-dark h6{margin-top:0;margin-bottom:.5rem}.bootstrap-dark p{margin-top:0;margin-bottom:1rem}.bootstrap-dark abbr[data-original-title],.bootstrap-dark abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;text-decoration-skip-ink:none}.bootstrap-dark address{margin-bottom:1rem;font-style:normal;line-height:inherit}.bootstrap-dark dl,.bootstrap-dark ol,.bootstrap-dark ul{margin-top:0;margin-bottom:1rem}.bootstrap-dark ol ol,.bootstrap-dark ol ul,.bootstrap-dark ul ol,.bootstrap-dark ul ul{margin-bottom:0}.bootstrap-dark dt{font-weight:700}.bootstrap-dark dd{margin-bottom:.5rem;margin-left:0}.bootstrap-dark blockquote{margin:0 0 1rem}.bootstrap-dark b,.bootstrap-dark strong{font-weight:bolder}.bootstrap-dark small{font-size:80%}.bootstrap-dark sub,.bootstrap-dark sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}.bootstrap-dark sub{bottom:-.25em}.bootstrap-dark sup{top:-.5em}.bootstrap-dark a{color:#adadad;text-decoration:none;background-color:transparent}.bootstrap-dark a:hover{color:#878787;text-decoration:underline}.bootstrap-dark a:not([href]){color:inherit;text-decoration:none}.bootstrap-dark a:not([href]):hover{color:inherit;text-decoration:none}.bootstrap-dark code,.bootstrap-dark kbd,.bootstrap-dark pre,.bootstrap-dark samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}.bootstrap-dark pre{margin-top:0;margin-bottom:1rem;overflow:auto}.bootstrap-dark figure{margin:0 0 1rem}.bootstrap-dark img{vertical-align:middle;border-style:none}.bootstrap-dark svg{overflow:hidden;vertical-align:middle}.bootstrap-dark table{border-collapse:collapse}.bootstrap-dark caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}.bootstrap-dark th{text-align:inherit}.bootstrap-dark label{display:inline-block;margin-bottom:.5rem}.bootstrap-dark button{border-radius:0}.bootstrap-dark button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.bootstrap-dark button,.bootstrap-dark input,.bootstrap-dark optgroup,.bootstrap-dark select,.bootstrap-dark textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}.bootstrap-dark button,.bootstrap-dark input{overflow:visible}.bootstrap-dark button,.bootstrap-dark select{text-transform:none}.bootstrap-dark select{word-wrap:normal}.bootstrap-dark [type=button],.bootstrap-dark [type=reset],.bootstrap-dark [type=submit],.bootstrap-dark button{-webkit-appearance:button}.bootstrap-dark [type=button]:not(:disabled),.bootstrap-dark [type=reset]:not(:disabled),.bootstrap-dark [type=submit]:not(:disabled),.bootstrap-dark button:not(:disabled){cursor:pointer}.bootstrap-dark [type=button]::-moz-focus-inner,.bootstrap-dark [type=reset]::-moz-focus-inner,.bootstrap-dark [type=submit]::-moz-focus-inner,.bootstrap-dark button::-moz-focus-inner{padding:0;border-style:none}.bootstrap-dark input[type=checkbox],.bootstrap-dark input[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}.bootstrap-dark input[type=date],.bootstrap-dark input[type=datetime-local],.bootstrap-dark input[type=month],.bootstrap-dark input[type=time]{-webkit-appearance:listbox}.bootstrap-dark textarea{overflow:auto;resize:vertical}.bootstrap-dark fieldset{min-width:0;padding:0;margin:0;border:0}.bootstrap-dark legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}.bootstrap-dark progress{vertical-align:baseline}.bootstrap-dark [type=number]::-webkit-inner-spin-button,.bootstrap-dark [type=number]::-webkit-outer-spin-button{height:auto}.bootstrap-dark [type=search]{outline-offset:-2px;-webkit-appearance:none}.bootstrap-dark [type=search]::-webkit-search-decoration{-webkit-appearance:none}.bootstrap-dark ::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}.bootstrap-dark output{display:inline-block}.bootstrap-dark summary{display:list-item;cursor:pointer}.bootstrap-dark template{display:none}.bootstrap-dark [hidden]{display:none!important}.bootstrap-dark .h1,.bootstrap-dark .h2,.bootstrap-dark .h3,.bootstrap-dark .h4,.bootstrap-dark .h5,.bootstrap-dark .h6,.bootstrap-dark h1,.bootstrap-dark h2,.bootstrap-dark h3,.bootstrap-dark h4,.bootstrap-dark h5,.bootstrap-dark h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}.bootstrap-dark .h1,.bootstrap-dark h1{font-size:2.5rem}.bootstrap-dark .h2,.bootstrap-dark h2{font-size:2rem}.bootstrap-dark .h3,.bootstrap-dark h3{font-size:1.75rem}.bootstrap-dark .h4,.bootstrap-dark h4{font-size:1.5rem}.bootstrap-dark .h5,.bootstrap-dark h5{font-size:1.25rem}.bootstrap-dark .h6,.bootstrap-dark h6{font-size:1rem}.bootstrap-dark .lead{font-size:1.25rem;font-weight:300}.bootstrap-dark .display-1{font-size:6rem;font-weight:300;line-height:1.2}.bootstrap-dark .display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.bootstrap-dark .display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.bootstrap-dark .display-4{font-size:3.5rem;font-weight:300;line-height:1.2}.bootstrap-dark hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.bootstrap-dark .small,.bootstrap-dark small{font-size:80%;font-weight:400}.bootstrap-dark .mark,.bootstrap-dark mark{padding:.2em;background-color:#fcf8e3}.bootstrap-dark .list-unstyled{padding-left:0;list-style:none}.bootstrap-dark .list-inline{padding-left:0;list-style:none}.bootstrap-dark .list-inline-item{display:inline-block}.bootstrap-dark .list-inline-item:not(:last-child){margin-right:.5rem}.bootstrap-dark .initialism{font-size:90%;text-transform:uppercase}.bootstrap-dark .blockquote{margin-bottom:1rem;font-size:1.25rem}.bootstrap-dark .blockquote-footer{display:block;font-size:80%;color:#6c757d}.bootstrap-dark .blockquote-footer::before{content:"\2014\00A0"}.bootstrap-dark .img-fluid{max-width:100%;height:auto}.bootstrap-dark .img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.bootstrap-dark .figure{display:inline-block}.bootstrap-dark .figure-img{margin-bottom:.5rem;line-height:1}.bootstrap-dark .figure-caption{font-size:90%;color:#6c757d}.bootstrap-dark code{font-size:87.5%;color:#e83e8c;word-wrap:break-word}a>.bootstrap-dark code{color:inherit}.bootstrap-dark kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:.2rem}.bootstrap-dark kbd kbd{padding:0;font-size:100%;font-weight:700}.bootstrap-dark pre{display:block;font-size:87.5%;color:#212529}.bootstrap-dark pre code{font-size:inherit;color:inherit;word-break:normal}.bootstrap-dark .pre-scrollable{max-height:340px;overflow-y:scroll}.bootstrap-dark .container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.bootstrap-dark .container{max-width:540px}}@media (min-width:768px){.bootstrap-dark .container{max-width:720px}}@media (min-width:992px){.bootstrap-dark .container{max-width:960px}}@media (min-width:1200px){.bootstrap-dark .container{max-width:1140px}}.bootstrap-dark .container-fluid,.bootstrap-dark .container-lg,.bootstrap-dark .container-md,.bootstrap-dark .container-sm,.bootstrap-dark .container-xl{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.bootstrap-dark .container,.bootstrap-dark .container-sm{max-width:540px}}@media (min-width:768px){.bootstrap-dark .container,.bootstrap-dark .container-md,.bootstrap-dark .container-sm{max-width:720px}}@media (min-width:992px){.bootstrap-dark .container,.bootstrap-dark .container-lg,.bootstrap-dark .container-md,.bootstrap-dark .container-sm{max-width:960px}}@media (min-width:1200px){.bootstrap-dark .container,.bootstrap-dark .container-lg,.bootstrap-dark .container-md,.bootstrap-dark .container-sm,.bootstrap-dark .container-xl{max-width:1140px}}.bootstrap-dark .row{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.bootstrap-dark .no-gutters{margin-right:0;margin-left:0}.bootstrap-dark .no-gutters>.col,.bootstrap-dark .no-gutters>[class*=col-]{padding-right:0;padding-left:0}.bootstrap-dark .col,.bootstrap-dark .col-1,.bootstrap-dark .col-10,.bootstrap-dark .col-11,.bootstrap-dark .col-12,.bootstrap-dark .col-2,.bootstrap-dark .col-3,.bootstrap-dark .col-4,.bootstrap-dark .col-5,.bootstrap-dark .col-6,.bootstrap-dark .col-7,.bootstrap-dark .col-8,.bootstrap-dark .col-9,.bootstrap-dark .col-auto,.bootstrap-dark .col-lg,.bootstrap-dark .col-lg-1,.bootstrap-dark .col-lg-10,.bootstrap-dark .col-lg-11,.bootstrap-dark .col-lg-12,.bootstrap-dark .col-lg-2,.bootstrap-dark .col-lg-3,.bootstrap-dark .col-lg-4,.bootstrap-dark .col-lg-5,.bootstrap-dark .col-lg-6,.bootstrap-dark .col-lg-7,.bootstrap-dark .col-lg-8,.bootstrap-dark .col-lg-9,.bootstrap-dark .col-lg-auto,.bootstrap-dark .col-md,.bootstrap-dark .col-md-1,.bootstrap-dark .col-md-10,.bootstrap-dark .col-md-11,.bootstrap-dark .col-md-12,.bootstrap-dark .col-md-2,.bootstrap-dark .col-md-3,.bootstrap-dark .col-md-4,.bootstrap-dark .col-md-5,.bootstrap-dark .col-md-6,.bootstrap-dark .col-md-7,.bootstrap-dark .col-md-8,.bootstrap-dark .col-md-9,.bootstrap-dark .col-md-auto,.bootstrap-dark .col-sm,.bootstrap-dark .col-sm-1,.bootstrap-dark .col-sm-10,.bootstrap-dark .col-sm-11,.bootstrap-dark .col-sm-12,.bootstrap-dark .col-sm-2,.bootstrap-dark .col-sm-3,.bootstrap-dark .col-sm-4,.bootstrap-dark .col-sm-5,.bootstrap-dark .col-sm-6,.bootstrap-dark .col-sm-7,.bootstrap-dark .col-sm-8,.bootstrap-dark .col-sm-9,.bootstrap-dark .col-sm-auto,.bootstrap-dark .col-xl,.bootstrap-dark .col-xl-1,.bootstrap-dark .col-xl-10,.bootstrap-dark .col-xl-11,.bootstrap-dark .col-xl-12,.bootstrap-dark .col-xl-2,.bootstrap-dark .col-xl-3,.bootstrap-dark .col-xl-4,.bootstrap-dark .col-xl-5,.bootstrap-dark .col-xl-6,.bootstrap-dark .col-xl-7,.bootstrap-dark .col-xl-8,.bootstrap-dark .col-xl-9,.bootstrap-dark .col-xl-auto{position:relative;width:100%;padding-right:15px;padding-left:15px}.bootstrap-dark .col{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.bootstrap-dark .row-cols-1>*{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.bootstrap-dark .row-cols-2>*{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.bootstrap-dark .row-cols-3>*{-webkit-box-flex:0;-webkit-flex:0 0 33.33333%;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.bootstrap-dark .row-cols-4>*{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.bootstrap-dark .row-cols-5>*{-webkit-box-flex:0;-webkit-flex:0 0 20%;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.bootstrap-dark .row-cols-6>*{-webkit-box-flex:0;-webkit-flex:0 0 16.66667%;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.bootstrap-dark .col-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.bootstrap-dark .col-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333%;-ms-flex:0 0 8.33333%;flex:0 0 8.33333%;max-width:8.33333%}.bootstrap-dark .col-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66667%;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.bootstrap-dark .col-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.bootstrap-dark .col-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333%;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.bootstrap-dark .col-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66667%;-ms-flex:0 0 41.66667%;flex:0 0 41.66667%;max-width:41.66667%}.bootstrap-dark .col-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.bootstrap-dark .col-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333%;-ms-flex:0 0 58.33333%;flex:0 0 58.33333%;max-width:58.33333%}.bootstrap-dark .col-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66667%;-ms-flex:0 0 66.66667%;flex:0 0 66.66667%;max-width:66.66667%}.bootstrap-dark .col-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.bootstrap-dark .col-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333%;-ms-flex:0 0 83.33333%;flex:0 0 83.33333%;max-width:83.33333%}.bootstrap-dark .col-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66667%;-ms-flex:0 0 91.66667%;flex:0 0 91.66667%;max-width:91.66667%}.bootstrap-dark .col-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.bootstrap-dark .order-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.bootstrap-dark .order-last{-webkit-box-ordinal-group:14;-webkit-order:13;-ms-flex-order:13;order:13}.bootstrap-dark .order-0{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.bootstrap-dark .order-1{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.bootstrap-dark .order-2{-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2}.bootstrap-dark .order-3{-webkit-box-ordinal-group:4;-webkit-order:3;-ms-flex-order:3;order:3}.bootstrap-dark .order-4{-webkit-box-ordinal-group:5;-webkit-order:4;-ms-flex-order:4;order:4}.bootstrap-dark .order-5{-webkit-box-ordinal-group:6;-webkit-order:5;-ms-flex-order:5;order:5}.bootstrap-dark .order-6{-webkit-box-ordinal-group:7;-webkit-order:6;-ms-flex-order:6;order:6}.bootstrap-dark .order-7{-webkit-box-ordinal-group:8;-webkit-order:7;-ms-flex-order:7;order:7}.bootstrap-dark .order-8{-webkit-box-ordinal-group:9;-webkit-order:8;-ms-flex-order:8;order:8}.bootstrap-dark .order-9{-webkit-box-ordinal-group:10;-webkit-order:9;-ms-flex-order:9;order:9}.bootstrap-dark .order-10{-webkit-box-ordinal-group:11;-webkit-order:10;-ms-flex-order:10;order:10}.bootstrap-dark .order-11{-webkit-box-ordinal-group:12;-webkit-order:11;-ms-flex-order:11;order:11}.bootstrap-dark .order-12{-webkit-box-ordinal-group:13;-webkit-order:12;-ms-flex-order:12;order:12}.bootstrap-dark .offset-1{margin-left:8.33333%}.bootstrap-dark .offset-2{margin-left:16.66667%}.bootstrap-dark .offset-3{margin-left:25%}.bootstrap-dark .offset-4{margin-left:33.33333%}.bootstrap-dark .offset-5{margin-left:41.66667%}.bootstrap-dark .offset-6{margin-left:50%}.bootstrap-dark .offset-7{margin-left:58.33333%}.bootstrap-dark .offset-8{margin-left:66.66667%}.bootstrap-dark .offset-9{margin-left:75%}.bootstrap-dark .offset-10{margin-left:83.33333%}.bootstrap-dark .offset-11{margin-left:91.66667%}@media (min-width:576px){.bootstrap-dark .col-sm{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.bootstrap-dark .row-cols-sm-1>*{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.bootstrap-dark .row-cols-sm-2>*{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.bootstrap-dark .row-cols-sm-3>*{-webkit-box-flex:0;-webkit-flex:0 0 33.33333%;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.bootstrap-dark .row-cols-sm-4>*{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.bootstrap-dark .row-cols-sm-5>*{-webkit-box-flex:0;-webkit-flex:0 0 20%;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.bootstrap-dark .row-cols-sm-6>*{-webkit-box-flex:0;-webkit-flex:0 0 16.66667%;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.bootstrap-dark .col-sm-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.bootstrap-dark .col-sm-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333%;-ms-flex:0 0 8.33333%;flex:0 0 8.33333%;max-width:8.33333%}.bootstrap-dark .col-sm-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66667%;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.bootstrap-dark .col-sm-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.bootstrap-dark .col-sm-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333%;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.bootstrap-dark .col-sm-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66667%;-ms-flex:0 0 41.66667%;flex:0 0 41.66667%;max-width:41.66667%}.bootstrap-dark .col-sm-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.bootstrap-dark .col-sm-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333%;-ms-flex:0 0 58.33333%;flex:0 0 58.33333%;max-width:58.33333%}.bootstrap-dark .col-sm-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66667%;-ms-flex:0 0 66.66667%;flex:0 0 66.66667%;max-width:66.66667%}.bootstrap-dark .col-sm-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.bootstrap-dark .col-sm-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333%;-ms-flex:0 0 83.33333%;flex:0 0 83.33333%;max-width:83.33333%}.bootstrap-dark .col-sm-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66667%;-ms-flex:0 0 91.66667%;flex:0 0 91.66667%;max-width:91.66667%}.bootstrap-dark .col-sm-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.bootstrap-dark .order-sm-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.bootstrap-dark .order-sm-last{-webkit-box-ordinal-group:14;-webkit-order:13;-ms-flex-order:13;order:13}.bootstrap-dark .order-sm-0{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.bootstrap-dark .order-sm-1{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.bootstrap-dark .order-sm-2{-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2}.bootstrap-dark .order-sm-3{-webkit-box-ordinal-group:4;-webkit-order:3;-ms-flex-order:3;order:3}.bootstrap-dark .order-sm-4{-webkit-box-ordinal-group:5;-webkit-order:4;-ms-flex-order:4;order:4}.bootstrap-dark .order-sm-5{-webkit-box-ordinal-group:6;-webkit-order:5;-ms-flex-order:5;order:5}.bootstrap-dark .order-sm-6{-webkit-box-ordinal-group:7;-webkit-order:6;-ms-flex-order:6;order:6}.bootstrap-dark .order-sm-7{-webkit-box-ordinal-group:8;-webkit-order:7;-ms-flex-order:7;order:7}.bootstrap-dark .order-sm-8{-webkit-box-ordinal-group:9;-webkit-order:8;-ms-flex-order:8;order:8}.bootstrap-dark .order-sm-9{-webkit-box-ordinal-group:10;-webkit-order:9;-ms-flex-order:9;order:9}.bootstrap-dark .order-sm-10{-webkit-box-ordinal-group:11;-webkit-order:10;-ms-flex-order:10;order:10}.bootstrap-dark .order-sm-11{-webkit-box-ordinal-group:12;-webkit-order:11;-ms-flex-order:11;order:11}.bootstrap-dark .order-sm-12{-webkit-box-ordinal-group:13;-webkit-order:12;-ms-flex-order:12;order:12}.bootstrap-dark .offset-sm-0{margin-left:0}.bootstrap-dark .offset-sm-1{margin-left:8.33333%}.bootstrap-dark .offset-sm-2{margin-left:16.66667%}.bootstrap-dark .offset-sm-3{margin-left:25%}.bootstrap-dark .offset-sm-4{margin-left:33.33333%}.bootstrap-dark .offset-sm-5{margin-left:41.66667%}.bootstrap-dark .offset-sm-6{margin-left:50%}.bootstrap-dark .offset-sm-7{margin-left:58.33333%}.bootstrap-dark .offset-sm-8{margin-left:66.66667%}.bootstrap-dark .offset-sm-9{margin-left:75%}.bootstrap-dark .offset-sm-10{margin-left:83.33333%}.bootstrap-dark .offset-sm-11{margin-left:91.66667%}}@media (min-width:768px){.bootstrap-dark .col-md{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.bootstrap-dark .row-cols-md-1>*{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.bootstrap-dark .row-cols-md-2>*{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.bootstrap-dark .row-cols-md-3>*{-webkit-box-flex:0;-webkit-flex:0 0 33.33333%;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.bootstrap-dark .row-cols-md-4>*{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.bootstrap-dark .row-cols-md-5>*{-webkit-box-flex:0;-webkit-flex:0 0 20%;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.bootstrap-dark .row-cols-md-6>*{-webkit-box-flex:0;-webkit-flex:0 0 16.66667%;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.bootstrap-dark .col-md-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.bootstrap-dark .col-md-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333%;-ms-flex:0 0 8.33333%;flex:0 0 8.33333%;max-width:8.33333%}.bootstrap-dark .col-md-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66667%;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.bootstrap-dark .col-md-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.bootstrap-dark .col-md-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333%;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.bootstrap-dark .col-md-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66667%;-ms-flex:0 0 41.66667%;flex:0 0 41.66667%;max-width:41.66667%}.bootstrap-dark .col-md-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.bootstrap-dark .col-md-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333%;-ms-flex:0 0 58.33333%;flex:0 0 58.33333%;max-width:58.33333%}.bootstrap-dark .col-md-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66667%;-ms-flex:0 0 66.66667%;flex:0 0 66.66667%;max-width:66.66667%}.bootstrap-dark .col-md-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.bootstrap-dark .col-md-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333%;-ms-flex:0 0 83.33333%;flex:0 0 83.33333%;max-width:83.33333%}.bootstrap-dark .col-md-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66667%;-ms-flex:0 0 91.66667%;flex:0 0 91.66667%;max-width:91.66667%}.bootstrap-dark .col-md-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.bootstrap-dark .order-md-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.bootstrap-dark .order-md-last{-webkit-box-ordinal-group:14;-webkit-order:13;-ms-flex-order:13;order:13}.bootstrap-dark .order-md-0{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.bootstrap-dark .order-md-1{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.bootstrap-dark .order-md-2{-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2}.bootstrap-dark .order-md-3{-webkit-box-ordinal-group:4;-webkit-order:3;-ms-flex-order:3;order:3}.bootstrap-dark .order-md-4{-webkit-box-ordinal-group:5;-webkit-order:4;-ms-flex-order:4;order:4}.bootstrap-dark .order-md-5{-webkit-box-ordinal-group:6;-webkit-order:5;-ms-flex-order:5;order:5}.bootstrap-dark .order-md-6{-webkit-box-ordinal-group:7;-webkit-order:6;-ms-flex-order:6;order:6}.bootstrap-dark .order-md-7{-webkit-box-ordinal-group:8;-webkit-order:7;-ms-flex-order:7;order:7}.bootstrap-dark .order-md-8{-webkit-box-ordinal-group:9;-webkit-order:8;-ms-flex-order:8;order:8}.bootstrap-dark .order-md-9{-webkit-box-ordinal-group:10;-webkit-order:9;-ms-flex-order:9;order:9}.bootstrap-dark .order-md-10{-webkit-box-ordinal-group:11;-webkit-order:10;-ms-flex-order:10;order:10}.bootstrap-dark .order-md-11{-webkit-box-ordinal-group:12;-webkit-order:11;-ms-flex-order:11;order:11}.bootstrap-dark .order-md-12{-webkit-box-ordinal-group:13;-webkit-order:12;-ms-flex-order:12;order:12}.bootstrap-dark .offset-md-0{margin-left:0}.bootstrap-dark .offset-md-1{margin-left:8.33333%}.bootstrap-dark .offset-md-2{margin-left:16.66667%}.bootstrap-dark .offset-md-3{margin-left:25%}.bootstrap-dark .offset-md-4{margin-left:33.33333%}.bootstrap-dark .offset-md-5{margin-left:41.66667%}.bootstrap-dark .offset-md-6{margin-left:50%}.bootstrap-dark .offset-md-7{margin-left:58.33333%}.bootstrap-dark .offset-md-8{margin-left:66.66667%}.bootstrap-dark .offset-md-9{margin-left:75%}.bootstrap-dark .offset-md-10{margin-left:83.33333%}.bootstrap-dark .offset-md-11{margin-left:91.66667%}}@media (min-width:992px){.bootstrap-dark .col-lg{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.bootstrap-dark .row-cols-lg-1>*{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.bootstrap-dark .row-cols-lg-2>*{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.bootstrap-dark .row-cols-lg-3>*{-webkit-box-flex:0;-webkit-flex:0 0 33.33333%;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.bootstrap-dark .row-cols-lg-4>*{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.bootstrap-dark .row-cols-lg-5>*{-webkit-box-flex:0;-webkit-flex:0 0 20%;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.bootstrap-dark .row-cols-lg-6>*{-webkit-box-flex:0;-webkit-flex:0 0 16.66667%;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.bootstrap-dark .col-lg-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.bootstrap-dark .col-lg-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333%;-ms-flex:0 0 8.33333%;flex:0 0 8.33333%;max-width:8.33333%}.bootstrap-dark .col-lg-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66667%;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.bootstrap-dark .col-lg-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.bootstrap-dark .col-lg-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333%;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.bootstrap-dark .col-lg-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66667%;-ms-flex:0 0 41.66667%;flex:0 0 41.66667%;max-width:41.66667%}.bootstrap-dark .col-lg-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.bootstrap-dark .col-lg-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333%;-ms-flex:0 0 58.33333%;flex:0 0 58.33333%;max-width:58.33333%}.bootstrap-dark .col-lg-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66667%;-ms-flex:0 0 66.66667%;flex:0 0 66.66667%;max-width:66.66667%}.bootstrap-dark .col-lg-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.bootstrap-dark .col-lg-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333%;-ms-flex:0 0 83.33333%;flex:0 0 83.33333%;max-width:83.33333%}.bootstrap-dark .col-lg-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66667%;-ms-flex:0 0 91.66667%;flex:0 0 91.66667%;max-width:91.66667%}.bootstrap-dark .col-lg-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.bootstrap-dark .order-lg-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.bootstrap-dark .order-lg-last{-webkit-box-ordinal-group:14;-webkit-order:13;-ms-flex-order:13;order:13}.bootstrap-dark .order-lg-0{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.bootstrap-dark .order-lg-1{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.bootstrap-dark .order-lg-2{-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2}.bootstrap-dark .order-lg-3{-webkit-box-ordinal-group:4;-webkit-order:3;-ms-flex-order:3;order:3}.bootstrap-dark .order-lg-4{-webkit-box-ordinal-group:5;-webkit-order:4;-ms-flex-order:4;order:4}.bootstrap-dark .order-lg-5{-webkit-box-ordinal-group:6;-webkit-order:5;-ms-flex-order:5;order:5}.bootstrap-dark .order-lg-6{-webkit-box-ordinal-group:7;-webkit-order:6;-ms-flex-order:6;order:6}.bootstrap-dark .order-lg-7{-webkit-box-ordinal-group:8;-webkit-order:7;-ms-flex-order:7;order:7}.bootstrap-dark .order-lg-8{-webkit-box-ordinal-group:9;-webkit-order:8;-ms-flex-order:8;order:8}.bootstrap-dark .order-lg-9{-webkit-box-ordinal-group:10;-webkit-order:9;-ms-flex-order:9;order:9}.bootstrap-dark .order-lg-10{-webkit-box-ordinal-group:11;-webkit-order:10;-ms-flex-order:10;order:10}.bootstrap-dark .order-lg-11{-webkit-box-ordinal-group:12;-webkit-order:11;-ms-flex-order:11;order:11}.bootstrap-dark .order-lg-12{-webkit-box-ordinal-group:13;-webkit-order:12;-ms-flex-order:12;order:12}.bootstrap-dark .offset-lg-0{margin-left:0}.bootstrap-dark .offset-lg-1{margin-left:8.33333%}.bootstrap-dark .offset-lg-2{margin-left:16.66667%}.bootstrap-dark .offset-lg-3{margin-left:25%}.bootstrap-dark .offset-lg-4{margin-left:33.33333%}.bootstrap-dark .offset-lg-5{margin-left:41.66667%}.bootstrap-dark .offset-lg-6{margin-left:50%}.bootstrap-dark .offset-lg-7{margin-left:58.33333%}.bootstrap-dark .offset-lg-8{margin-left:66.66667%}.bootstrap-dark .offset-lg-9{margin-left:75%}.bootstrap-dark .offset-lg-10{margin-left:83.33333%}.bootstrap-dark .offset-lg-11{margin-left:91.66667%}}@media (min-width:1200px){.bootstrap-dark .col-xl{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.bootstrap-dark .row-cols-xl-1>*{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.bootstrap-dark .row-cols-xl-2>*{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.bootstrap-dark .row-cols-xl-3>*{-webkit-box-flex:0;-webkit-flex:0 0 33.33333%;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.bootstrap-dark .row-cols-xl-4>*{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.bootstrap-dark .row-cols-xl-5>*{-webkit-box-flex:0;-webkit-flex:0 0 20%;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.bootstrap-dark .row-cols-xl-6>*{-webkit-box-flex:0;-webkit-flex:0 0 16.66667%;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.bootstrap-dark .col-xl-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.bootstrap-dark .col-xl-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333%;-ms-flex:0 0 8.33333%;flex:0 0 8.33333%;max-width:8.33333%}.bootstrap-dark .col-xl-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66667%;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.bootstrap-dark .col-xl-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.bootstrap-dark .col-xl-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333%;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.bootstrap-dark .col-xl-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66667%;-ms-flex:0 0 41.66667%;flex:0 0 41.66667%;max-width:41.66667%}.bootstrap-dark .col-xl-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.bootstrap-dark .col-xl-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333%;-ms-flex:0 0 58.33333%;flex:0 0 58.33333%;max-width:58.33333%}.bootstrap-dark .col-xl-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66667%;-ms-flex:0 0 66.66667%;flex:0 0 66.66667%;max-width:66.66667%}.bootstrap-dark .col-xl-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.bootstrap-dark .col-xl-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333%;-ms-flex:0 0 83.33333%;flex:0 0 83.33333%;max-width:83.33333%}.bootstrap-dark .col-xl-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66667%;-ms-flex:0 0 91.66667%;flex:0 0 91.66667%;max-width:91.66667%}.bootstrap-dark .col-xl-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.bootstrap-dark .order-xl-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.bootstrap-dark .order-xl-last{-webkit-box-ordinal-group:14;-webkit-order:13;-ms-flex-order:13;order:13}.bootstrap-dark .order-xl-0{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.bootstrap-dark .order-xl-1{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.bootstrap-dark .order-xl-2{-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2}.bootstrap-dark .order-xl-3{-webkit-box-ordinal-group:4;-webkit-order:3;-ms-flex-order:3;order:3}.bootstrap-dark .order-xl-4{-webkit-box-ordinal-group:5;-webkit-order:4;-ms-flex-order:4;order:4}.bootstrap-dark .order-xl-5{-webkit-box-ordinal-group:6;-webkit-order:5;-ms-flex-order:5;order:5}.bootstrap-dark .order-xl-6{-webkit-box-ordinal-group:7;-webkit-order:6;-ms-flex-order:6;order:6}.bootstrap-dark .order-xl-7{-webkit-box-ordinal-group:8;-webkit-order:7;-ms-flex-order:7;order:7}.bootstrap-dark .order-xl-8{-webkit-box-ordinal-group:9;-webkit-order:8;-ms-flex-order:8;order:8}.bootstrap-dark .order-xl-9{-webkit-box-ordinal-group:10;-webkit-order:9;-ms-flex-order:9;order:9}.bootstrap-dark .order-xl-10{-webkit-box-ordinal-group:11;-webkit-order:10;-ms-flex-order:10;order:10}.bootstrap-dark .order-xl-11{-webkit-box-ordinal-group:12;-webkit-order:11;-ms-flex-order:11;order:11}.bootstrap-dark .order-xl-12{-webkit-box-ordinal-group:13;-webkit-order:12;-ms-flex-order:12;order:12}.bootstrap-dark .offset-xl-0{margin-left:0}.bootstrap-dark .offset-xl-1{margin-left:8.33333%}.bootstrap-dark .offset-xl-2{margin-left:16.66667%}.bootstrap-dark .offset-xl-3{margin-left:25%}.bootstrap-dark .offset-xl-4{margin-left:33.33333%}.bootstrap-dark .offset-xl-5{margin-left:41.66667%}.bootstrap-dark .offset-xl-6{margin-left:50%}.bootstrap-dark .offset-xl-7{margin-left:58.33333%}.bootstrap-dark .offset-xl-8{margin-left:66.66667%}.bootstrap-dark .offset-xl-9{margin-left:75%}.bootstrap-dark .offset-xl-10{margin-left:83.33333%}.bootstrap-dark .offset-xl-11{margin-left:91.66667%}}.bootstrap-dark .table{width:100%;margin-bottom:1rem;color:#d3d3d3}.bootstrap-dark .table td,.bootstrap-dark .table th{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.bootstrap-dark .table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.bootstrap-dark .table tbody+tbody{border-top:2px solid #dee2e6}.bootstrap-dark .table-sm td,.bootstrap-dark .table-sm th{padding:.3rem}.bootstrap-dark .table-bordered{border:1px solid #dee2e6}.bootstrap-dark .table-bordered td,.bootstrap-dark .table-bordered th{border:1px solid #dee2e6}.bootstrap-dark .table-bordered thead td,.bootstrap-dark .table-bordered thead th{border-bottom-width:2px}.bootstrap-dark .table-borderless tbody+tbody,.bootstrap-dark .table-borderless td,.bootstrap-dark .table-borderless th,.bootstrap-dark .table-borderless thead th{border:0}.bootstrap-dark .table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.bootstrap-dark .table-hover tbody tr:hover{color:#212529;background-color:rgba(0,0,0,.075)}.bootstrap-dark .table-primary,.bootstrap-dark .table-primary>td,.bootstrap-dark .table-primary>th{background-color:#b8daff}.bootstrap-dark .table-primary tbody+tbody,.bootstrap-dark .table-primary td,.bootstrap-dark .table-primary th,.bootstrap-dark .table-primary thead th{border-color:#7abaff}.bootstrap-dark .table-hover .table-primary:hover{background-color:#9fcdff}.bootstrap-dark .table-hover .table-primary:hover>td,.bootstrap-dark .table-hover .table-primary:hover>th{background-color:#9fcdff}.bootstrap-dark .table-secondary,.bootstrap-dark .table-secondary>td,.bootstrap-dark .table-secondary>th{background-color:#d6d8db}.bootstrap-dark .table-secondary tbody+tbody,.bootstrap-dark .table-secondary td,.bootstrap-dark .table-secondary th,.bootstrap-dark .table-secondary thead th{border-color:#b3b7bb}.bootstrap-dark .table-hover .table-secondary:hover{background-color:#c8cbcf}.bootstrap-dark .table-hover .table-secondary:hover>td,.bootstrap-dark .table-hover .table-secondary:hover>th{background-color:#c8cbcf}.bootstrap-dark .table-success,.bootstrap-dark .table-success>td,.bootstrap-dark .table-success>th{background-color:#c3e6cb}.bootstrap-dark .table-success tbody+tbody,.bootstrap-dark .table-success td,.bootstrap-dark .table-success th,.bootstrap-dark .table-success thead th{border-color:#8fd19e}.bootstrap-dark .table-hover .table-success:hover{background-color:#b1dfbb}.bootstrap-dark .table-hover .table-success:hover>td,.bootstrap-dark .table-hover .table-success:hover>th{background-color:#b1dfbb}.bootstrap-dark .table-info,.bootstrap-dark .table-info>td,.bootstrap-dark .table-info>th{background-color:#bee5eb}.bootstrap-dark .table-info tbody+tbody,.bootstrap-dark .table-info td,.bootstrap-dark .table-info th,.bootstrap-dark .table-info thead th{border-color:#86cfda}.bootstrap-dark .table-hover .table-info:hover{background-color:#abdde5}.bootstrap-dark .table-hover .table-info:hover>td,.bootstrap-dark .table-hover .table-info:hover>th{background-color:#abdde5}.bootstrap-dark .table-warning,.bootstrap-dark .table-warning>td,.bootstrap-dark .table-warning>th{background-color:#ffeeba}.bootstrap-dark .table-warning tbody+tbody,.bootstrap-dark .table-warning td,.bootstrap-dark .table-warning th,.bootstrap-dark .table-warning thead th{border-color:#ffdf7e}.bootstrap-dark .table-hover .table-warning:hover{background-color:#ffe8a1}.bootstrap-dark .table-hover .table-warning:hover>td,.bootstrap-dark .table-hover .table-warning:hover>th{background-color:#ffe8a1}.bootstrap-dark .table-danger,.bootstrap-dark .table-danger>td,.bootstrap-dark .table-danger>th{background-color:#f5c6cb}.bootstrap-dark .table-danger tbody+tbody,.bootstrap-dark .table-danger td,.bootstrap-dark .table-danger th,.bootstrap-dark .table-danger thead th{border-color:#ed969e}.bootstrap-dark .table-hover .table-danger:hover{background-color:#f1b0b7}.bootstrap-dark .table-hover .table-danger:hover>td,.bootstrap-dark .table-hover .table-danger:hover>th{background-color:#f1b0b7}.bootstrap-dark .table-light,.bootstrap-dark .table-light>td,.bootstrap-dark .table-light>th{background-color:#fdfdfe}.bootstrap-dark .table-light tbody+tbody,.bootstrap-dark .table-light td,.bootstrap-dark .table-light th,.bootstrap-dark .table-light thead th{border-color:#fbfcfc}.bootstrap-dark .table-hover .table-light:hover{background-color:#ececf6}.bootstrap-dark .table-hover .table-light:hover>td,.bootstrap-dark .table-hover .table-light:hover>th{background-color:#ececf6}.bootstrap-dark .table-dark,.bootstrap-dark .table-dark>td,.bootstrap-dark .table-dark>th{background-color:#c6c8ca}.bootstrap-dark .table-dark tbody+tbody,.bootstrap-dark .table-dark td,.bootstrap-dark .table-dark th,.bootstrap-dark .table-dark thead th{border-color:#95999c}.bootstrap-dark .table-hover .table-dark:hover{background-color:#b9bbbe}.bootstrap-dark .table-hover .table-dark:hover>td,.bootstrap-dark .table-hover .table-dark:hover>th{background-color:#b9bbbe}.bootstrap-dark .table-active,.bootstrap-dark .table-active>td,.bootstrap-dark .table-active>th{background-color:rgba(0,0,0,.075)}.bootstrap-dark .table-hover .table-active:hover{background-color:rgba(0,0,0,.075)}.bootstrap-dark .table-hover .table-active:hover>td,.bootstrap-dark .table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.bootstrap-dark .table .thead-dark th{color:#dee2e6;background-color:#343a40;border-color:#454d55}.bootstrap-dark .table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dee2e6}.bootstrap-dark .table-dark{color:#dee2e6;background-color:#343a40}.bootstrap-dark .table-dark td,.bootstrap-dark .table-dark th,.bootstrap-dark .table-dark thead th{border-color:#454d55}.bootstrap-dark .table-dark.table-bordered{border:0}.bootstrap-dark .table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,.05)}.bootstrap-dark .table-dark.table-hover tbody tr:hover{color:#fff;background-color:rgba(255,255,255,.075)}@media (max-width:575.98px){.bootstrap-dark .table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.bootstrap-dark .table-responsive-sm>.table-bordered{border:0}}@media (max-width:767.98px){.bootstrap-dark .table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.bootstrap-dark .table-responsive-md>.table-bordered{border:0}}@media (max-width:991.98px){.bootstrap-dark .table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.bootstrap-dark .table-responsive-lg>.table-bordered{border:0}}@media (max-width:1199.98px){.bootstrap-dark .table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.bootstrap-dark .table-responsive-xl>.table-bordered{border:0}}.bootstrap-dark .table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.bootstrap-dark .table-responsive>.table-bordered{border:0}.bootstrap-dark .table-primary,.bootstrap-dark .table-primary>td,.bootstrap-dark .table-primary>th{color:#212529}.bootstrap-dark .table-hover .table-primary:hover{color:#212529}.bootstrap-dark .table-hover .table-primary:hover>td,.bootstrap-dark .table-hover .table-primary:hover>th{color:#212529}.bootstrap-dark .table-secondary,.bootstrap-dark .table-secondary>td,.bootstrap-dark .table-secondary>th{color:#212529}.bootstrap-dark .table-hover .table-secondary:hover{color:#212529}.bootstrap-dark .table-hover .table-secondary:hover>td,.bootstrap-dark .table-hover .table-secondary:hover>th{color:#212529}.bootstrap-dark .table-success,.bootstrap-dark .table-success>td,.bootstrap-dark .table-success>th{color:#212529}.bootstrap-dark .table-hover .table-success:hover{color:#212529}.bootstrap-dark .table-hover .table-success:hover>td,.bootstrap-dark .table-hover .table-success:hover>th{color:#212529}.bootstrap-dark .table-info,.bootstrap-dark .table-info>td,.bootstrap-dark .table-info>th{color:#212529}.bootstrap-dark .table-hover .table-info:hover{color:#212529}.bootstrap-dark .table-hover .table-info:hover>td,.bootstrap-dark .table-hover .table-info:hover>th{color:#212529}.bootstrap-dark .table-warning,.bootstrap-dark .table-warning>td,.bootstrap-dark .table-warning>th{color:#212529}.bootstrap-dark .table-hover .table-warning:hover{color:#212529}.bootstrap-dark .table-hover .table-warning:hover>td,.bootstrap-dark .table-hover .table-warning:hover>th{color:#212529}.bootstrap-dark .table-danger,.bootstrap-dark .table-danger>td,.bootstrap-dark .table-danger>th{color:#212529}.bootstrap-dark .table-hover .table-danger:hover{color:#212529}.bootstrap-dark .table-hover .table-danger:hover>td,.bootstrap-dark .table-hover .table-danger:hover>th{color:#212529}.bootstrap-dark .table-light,.bootstrap-dark .table-light>td,.bootstrap-dark .table-light>th{color:#212529}.bootstrap-dark .table-hover .table-light:hover{color:#212529}.bootstrap-dark .table-hover .table-light:hover>td,.bootstrap-dark .table-hover .table-light:hover>th{color:#212529}.bootstrap-dark .table-dark,.bootstrap-dark .table-dark>td,.bootstrap-dark .table-dark>th{color:#212529}.bootstrap-dark .table-hover .table-dark:hover{color:#212529}.bootstrap-dark .table-hover .table-dark:hover>td,.bootstrap-dark .table-hover .table-dark:hover>th{color:#212529}.bootstrap-dark .table-active,.bootstrap-dark .table-active>td,.bootstrap-dark .table-active>th{color:#ced4da}.bootstrap-dark .table-hover .table-active:hover{color:#ced4da}.bootstrap-dark .table-hover .table-active:hover>td,.bootstrap-dark .table-hover .table-active:hover>th{color:#ced4da}.bootstrap-dark .table-dark{color:#dee2e6}.bootstrap-dark .form-control{display:block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#dee2e6;background-color:#000;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #6c757d;border-radius:.25rem;-webkit-transition:border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.bootstrap-dark .form-control{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap-dark .form-control::-ms-expand{background-color:transparent;border:0}.bootstrap-dark .form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #dee2e6}.bootstrap-dark .form-control:focus{color:#dee2e6;background-color:#191d21;border-color:#b3d7ff;outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(0,123,255,.25);box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.bootstrap-dark .form-control::-webkit-input-placeholder{color:#6c757d;opacity:1}.bootstrap-dark .form-control::-moz-placeholder{color:#6c757d;opacity:1}.bootstrap-dark .form-control::-ms-input-placeholder{color:#6c757d;opacity:1}.bootstrap-dark .form-control::placeholder{color:#6c757d;opacity:1}.bootstrap-dark .form-control:disabled,.bootstrap-dark .form-control[readonly]{background-color:#343a40;opacity:1}.bootstrap-dark select.form-control:focus::-ms-value{color:#dee2e6;background-color:#000}.bootstrap-dark .form-control-file,.bootstrap-dark .form-control-range{display:block;width:100%}.bootstrap-dark .col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.bootstrap-dark .col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.bootstrap-dark .col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.bootstrap-dark .form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;font-size:1rem;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.bootstrap-dark .form-control-plaintext.form-control-lg,.bootstrap-dark .form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.bootstrap-dark .form-control-sm{height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.bootstrap-dark .form-control-lg{height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.bootstrap-dark select.form-control[multiple],.bootstrap-dark select.form-control[size]{height:auto}.bootstrap-dark textarea.form-control{height:auto}.bootstrap-dark .form-group{margin-bottom:1rem}.bootstrap-dark .form-text{display:block;margin-top:.25rem}.bootstrap-dark .form-row{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.bootstrap-dark .form-row>.col,.bootstrap-dark .form-row>[class*=col-]{padding-right:5px;padding-left:5px}.bootstrap-dark .form-check{position:relative;display:block;padding-left:1.25rem}.bootstrap-dark .form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.bootstrap-dark .form-check-input:disabled~.form-check-label,.bootstrap-dark .form-check-input[disabled]~.form-check-label{color:#6c757d}.bootstrap-dark .form-check-label{margin-bottom:0}.bootstrap-dark .form-check-inline{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;padding-left:0;margin-right:.75rem}.bootstrap-dark .form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.bootstrap-dark .valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#28a745}.bootstrap-dark .valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#ced4da;background-color:rgba(40,167,69,.9);border-radius:.25rem}.bootstrap-dark.is-valid~.valid-feedback,.bootstrap-dark.is-valid~.valid-tooltip,.was-validated .bootstrap-dark:valid~.valid-feedback,.was-validated .bootstrap-dark:valid~.valid-tooltip{display:block}.bootstrap-dark .form-control.is-valid,.was-validated .bootstrap-dark .form-control:valid{border-color:#28a745;padding-right:calc(1.5em + .75rem);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");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;-webkit-background-size:calc(.75em + .375rem) calc(.75em + .375rem);background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.bootstrap-dark .form-control.is-valid:focus,.was-validated .bootstrap-dark .form-control:valid:focus{border-color:#28a745;-webkit-box-shadow:0 0 0 .2rem rgba(40,167,69,.25);box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.bootstrap-dark textarea.form-control.is-valid,.was-validated .bootstrap-dark textarea.form-control:valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.bootstrap-dark .custom-select.is-valid,.was-validated .bootstrap-dark .custom-select:valid{border-color:#28a745;padding-right:calc(.75em + 2.3125rem);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 .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(.75em + .375rem) calc(.75em + .375rem)}.bootstrap-dark .custom-select.is-valid:focus,.was-validated .bootstrap-dark .custom-select:valid:focus{border-color:#28a745;-webkit-box-shadow:0 0 0 .2rem rgba(40,167,69,.25);box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.bootstrap-dark .form-check-input.is-valid~.form-check-label,.was-validated .bootstrap-dark .form-check-input:valid~.form-check-label{color:#28a745}.bootstrap-dark .form-check-input.is-valid~.valid-feedback,.bootstrap-dark .form-check-input.is-valid~.valid-tooltip,.was-validated .bootstrap-dark .form-check-input:valid~.valid-feedback,.was-validated .bootstrap-dark .form-check-input:valid~.valid-tooltip{display:block}.bootstrap-dark .custom-control-input.is-valid~.custom-control-label,.was-validated .bootstrap-dark .custom-control-input:valid~.custom-control-label{color:#28a745}.bootstrap-dark .custom-control-input.is-valid~.custom-control-label::before,.was-validated .bootstrap-dark .custom-control-input:valid~.custom-control-label::before{border-color:#28a745}.bootstrap-dark .custom-control-input.is-valid:checked~.custom-control-label::before,.was-validated .bootstrap-dark .custom-control-input:valid:checked~.custom-control-label::before{border-color:#34ce57;background-color:#34ce57}.bootstrap-dark .custom-control-input.is-valid:focus~.custom-control-label::before,.was-validated .bootstrap-dark .custom-control-input:valid:focus~.custom-control-label::before{-webkit-box-shadow:0 0 0 .2rem rgba(40,167,69,.25);box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.bootstrap-dark .custom-control-input.is-valid:focus:not(:checked)~.custom-control-label::before,.was-validated .bootstrap-dark .custom-control-input:valid:focus:not(:checked)~.custom-control-label::before{border-color:#28a745}.bootstrap-dark .custom-file-input.is-valid~.custom-file-label,.was-validated .bootstrap-dark .custom-file-input:valid~.custom-file-label{border-color:#28a745}.bootstrap-dark .custom-file-input.is-valid:focus~.custom-file-label,.was-validated .bootstrap-dark .custom-file-input:valid:focus~.custom-file-label{border-color:#28a745;-webkit-box-shadow:0 0 0 .2rem rgba(40,167,69,.25);box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.bootstrap-dark .invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#dc3545}.bootstrap-dark .invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#ced4da;background-color:rgba(220,53,69,.9);border-radius:.25rem}.bootstrap-dark.is-invalid~.invalid-feedback,.bootstrap-dark.is-invalid~.invalid-tooltip,.was-validated .bootstrap-dark:invalid~.invalid-feedback,.was-validated .bootstrap-dark:invalid~.invalid-tooltip{display:block}.bootstrap-dark .form-control.is-invalid,.was-validated .bootstrap-dark .form-control:invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem);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");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;-webkit-background-size:calc(.75em + .375rem) calc(.75em + .375rem);background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.bootstrap-dark .form-control.is-invalid:focus,.was-validated .bootstrap-dark .form-control:invalid:focus{border-color:#dc3545;-webkit-box-shadow:0 0 0 .2rem rgba(220,53,69,.25);box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.bootstrap-dark textarea.form-control.is-invalid,.was-validated .bootstrap-dark textarea.form-control:invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.bootstrap-dark .custom-select.is-invalid,.was-validated .bootstrap-dark .custom-select:invalid{border-color:#dc3545;padding-right:calc(.75em + 2.3125rem);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 .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(.75em + .375rem) calc(.75em + .375rem)}.bootstrap-dark .custom-select.is-invalid:focus,.was-validated .bootstrap-dark .custom-select:invalid:focus{border-color:#dc3545;-webkit-box-shadow:0 0 0 .2rem rgba(220,53,69,.25);box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.bootstrap-dark .form-check-input.is-invalid~.form-check-label,.was-validated .bootstrap-dark .form-check-input:invalid~.form-check-label{color:#dc3545}.bootstrap-dark .form-check-input.is-invalid~.invalid-feedback,.bootstrap-dark .form-check-input.is-invalid~.invalid-tooltip,.was-validated .bootstrap-dark .form-check-input:invalid~.invalid-feedback,.was-validated .bootstrap-dark .form-check-input:invalid~.invalid-tooltip{display:block}.bootstrap-dark .custom-control-input.is-invalid~.custom-control-label,.was-validated .bootstrap-dark .custom-control-input:invalid~.custom-control-label{color:#dc3545}.bootstrap-dark .custom-control-input.is-invalid~.custom-control-label::before,.was-validated .bootstrap-dark .custom-control-input:invalid~.custom-control-label::before{border-color:#dc3545}.bootstrap-dark .custom-control-input.is-invalid:checked~.custom-control-label::before,.was-validated .bootstrap-dark .custom-control-input:invalid:checked~.custom-control-label::before{border-color:#e4606d;background-color:#e4606d}.bootstrap-dark .custom-control-input.is-invalid:focus~.custom-control-label::before,.was-validated .bootstrap-dark .custom-control-input:invalid:focus~.custom-control-label::before{-webkit-box-shadow:0 0 0 .2rem rgba(220,53,69,.25);box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.bootstrap-dark .custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label::before,.was-validated .bootstrap-dark .custom-control-input:invalid:focus:not(:checked)~.custom-control-label::before{border-color:#dc3545}.bootstrap-dark .custom-file-input.is-invalid~.custom-file-label,.was-validated .bootstrap-dark .custom-file-input:invalid~.custom-file-label{border-color:#dc3545}.bootstrap-dark .custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .bootstrap-dark .custom-file-input:invalid:focus~.custom-file-label{border-color:#dc3545;-webkit-box-shadow:0 0 0 .2rem rgba(220,53,69,.25);box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.bootstrap-dark .form-inline{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.bootstrap-dark .form-inline .form-check{width:100%}@media (min-width:576px){.bootstrap-dark .form-inline label{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.bootstrap-dark .form-inline .form-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;margin-bottom:0}.bootstrap-dark .form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.bootstrap-dark .form-inline .form-control-plaintext{display:inline-block}.bootstrap-dark .form-inline .custom-select,.bootstrap-dark .form-inline .input-group{width:auto}.bootstrap-dark .form-inline .form-check{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;width:auto;padding-left:0}.bootstrap-dark .form-inline .form-check-input{position:relative;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;margin-top:0;margin-right:.25rem;margin-left:0}.bootstrap-dark .form-inline .custom-control{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.bootstrap-dark .form-inline .custom-control-label{margin-bottom:0}}.bootstrap-dark .btn{display:inline-block;font-weight:400;color:#d3d3d3;text-align:center;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;-webkit-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.bootstrap-dark .btn{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap-dark .btn:hover{color:#d3d3d3;text-decoration:none}.bootstrap-dark .btn.focus,.bootstrap-dark .btn:focus{outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(0,123,255,.25);box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.bootstrap-dark .btn.disabled,.bootstrap-dark .btn:disabled{opacity:.65}.bootstrap-dark a.btn.disabled,.bootstrap-dark fieldset:disabled a.btn{pointer-events:none}.bootstrap-dark .btn-primary{color:#ced4da;background-color:#007bff;border-color:#007bff}.bootstrap-dark .btn-primary:hover{color:#ced4da;background-color:#0069d9;border-color:#0062cc}.bootstrap-dark .btn-primary.focus,.bootstrap-dark .btn-primary:focus{color:#ced4da;background-color:#0069d9;border-color:#0062cc;-webkit-box-shadow:0 0 0 .2rem rgba(31,136,249,.5);box-shadow:0 0 0 .2rem rgba(31,136,249,.5)}.bootstrap-dark .btn-primary.disabled,.bootstrap-dark .btn-primary:disabled{color:#ced4da;background-color:#007bff;border-color:#007bff}.bootstrap-dark .btn-primary:not(:disabled):not(.disabled).active,.bootstrap-dark .btn-primary:not(:disabled):not(.disabled):active,.show>.bootstrap-dark .btn-primary.dropdown-toggle{color:#ced4da;background-color:#0062cc;border-color:#005cbf}.bootstrap-dark .btn-primary:not(:disabled):not(.disabled).active:focus,.bootstrap-dark .btn-primary:not(:disabled):not(.disabled):active:focus,.show>.bootstrap-dark .btn-primary.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(31,136,249,.5);box-shadow:0 0 0 .2rem rgba(31,136,249,.5)}.bootstrap-dark .btn-secondary{color:#ced4da;background-color:#6c757d;border-color:#6c757d}.bootstrap-dark .btn-secondary:hover{color:#ced4da;background-color:#5a6268;border-color:#545b62}.bootstrap-dark .btn-secondary.focus,.bootstrap-dark .btn-secondary:focus{color:#ced4da;background-color:#5a6268;border-color:#545b62;-webkit-box-shadow:0 0 0 .2rem rgba(123,131,139,.5);box-shadow:0 0 0 .2rem rgba(123,131,139,.5)}.bootstrap-dark .btn-secondary.disabled,.bootstrap-dark .btn-secondary:disabled{color:#ced4da;background-color:#6c757d;border-color:#6c757d}.bootstrap-dark .btn-secondary:not(:disabled):not(.disabled).active,.bootstrap-dark .btn-secondary:not(:disabled):not(.disabled):active,.show>.bootstrap-dark .btn-secondary.dropdown-toggle{color:#ced4da;background-color:#545b62;border-color:#4e555b}.bootstrap-dark .btn-secondary:not(:disabled):not(.disabled).active:focus,.bootstrap-dark .btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.bootstrap-dark .btn-secondary.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(123,131,139,.5);box-shadow:0 0 0 .2rem rgba(123,131,139,.5)}.bootstrap-dark .btn-success{color:#ced4da;background-color:#28a745;border-color:#28a745}.bootstrap-dark .btn-success:hover{color:#ced4da;background-color:#218838;border-color:#1e7e34}.bootstrap-dark .btn-success.focus,.bootstrap-dark .btn-success:focus{color:#ced4da;background-color:#218838;border-color:#1e7e34;-webkit-box-shadow:0 0 0 .2rem rgba(65,174,91,.5);box-shadow:0 0 0 .2rem rgba(65,174,91,.5)}.bootstrap-dark .btn-success.disabled,.bootstrap-dark .btn-success:disabled{color:#ced4da;background-color:#28a745;border-color:#28a745}.bootstrap-dark .btn-success:not(:disabled):not(.disabled).active,.bootstrap-dark .btn-success:not(:disabled):not(.disabled):active,.show>.bootstrap-dark .btn-success.dropdown-toggle{color:#ced4da;background-color:#1e7e34;border-color:#1c7430}.bootstrap-dark .btn-success:not(:disabled):not(.disabled).active:focus,.bootstrap-dark .btn-success:not(:disabled):not(.disabled):active:focus,.show>.bootstrap-dark .btn-success.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(65,174,91,.5);box-shadow:0 0 0 .2rem rgba(65,174,91,.5)}.bootstrap-dark .btn-info{color:#ced4da;background-color:#17a2b8;border-color:#17a2b8}.bootstrap-dark .btn-info:hover{color:#ced4da;background-color:#138496;border-color:#117a8b}.bootstrap-dark .btn-info.focus,.bootstrap-dark .btn-info:focus{color:#ced4da;background-color:#138496;border-color:#117a8b;-webkit-box-shadow:0 0 0 .2rem rgba(50,170,189,.5);box-shadow:0 0 0 .2rem rgba(50,170,189,.5)}.bootstrap-dark .btn-info.disabled,.bootstrap-dark .btn-info:disabled{color:#ced4da;background-color:#17a2b8;border-color:#17a2b8}.bootstrap-dark .btn-info:not(:disabled):not(.disabled).active,.bootstrap-dark .btn-info:not(:disabled):not(.disabled):active,.show>.bootstrap-dark .btn-info.dropdown-toggle{color:#ced4da;background-color:#117a8b;border-color:#10707f}.bootstrap-dark .btn-info:not(:disabled):not(.disabled).active:focus,.bootstrap-dark .btn-info:not(:disabled):not(.disabled):active:focus,.show>.bootstrap-dark .btn-info.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(50,170,189,.5);box-shadow:0 0 0 .2rem rgba(50,170,189,.5)}.bootstrap-dark .btn-warning{color:#212529;background-color:#ffc107;border-color:#ffc107}.bootstrap-dark .btn-warning:hover{color:#212529;background-color:#e0a800;border-color:#d39e00}.bootstrap-dark .btn-warning.focus,.bootstrap-dark .btn-warning:focus{color:#212529;background-color:#e0a800;border-color:#d39e00;-webkit-box-shadow:0 0 0 .2rem rgba(222,170,12,.5);box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.bootstrap-dark .btn-warning.disabled,.bootstrap-dark .btn-warning:disabled{color:#212529;background-color:#ffc107;border-color:#ffc107}.bootstrap-dark .btn-warning:not(:disabled):not(.disabled).active,.bootstrap-dark .btn-warning:not(:disabled):not(.disabled):active,.show>.bootstrap-dark .btn-warning.dropdown-toggle{color:#212529;background-color:#d39e00;border-color:#c69500}.bootstrap-dark .btn-warning:not(:disabled):not(.disabled).active:focus,.bootstrap-dark .btn-warning:not(:disabled):not(.disabled):active:focus,.show>.bootstrap-dark .btn-warning.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(222,170,12,.5);box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.bootstrap-dark .btn-danger{color:#ced4da;background-color:#dc3545;border-color:#dc3545}.bootstrap-dark .btn-danger:hover{color:#ced4da;background-color:#c82333;border-color:#bd2130}.bootstrap-dark .btn-danger.focus,.bootstrap-dark .btn-danger:focus{color:#ced4da;background-color:#c82333;border-color:#bd2130;-webkit-box-shadow:0 0 0 .2rem rgba(218,77,91,.5);box-shadow:0 0 0 .2rem rgba(218,77,91,.5)}.bootstrap-dark .btn-danger.disabled,.bootstrap-dark .btn-danger:disabled{color:#ced4da;background-color:#dc3545;border-color:#dc3545}.bootstrap-dark .btn-danger:not(:disabled):not(.disabled).active,.bootstrap-dark .btn-danger:not(:disabled):not(.disabled):active,.show>.bootstrap-dark .btn-danger.dropdown-toggle{color:#ced4da;background-color:#bd2130;border-color:#b21f2d}.bootstrap-dark .btn-danger:not(:disabled):not(.disabled).active:focus,.bootstrap-dark .btn-danger:not(:disabled):not(.disabled):active:focus,.show>.bootstrap-dark .btn-danger.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(218,77,91,.5);box-shadow:0 0 0 .2rem rgba(218,77,91,.5)}.bootstrap-dark .btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.bootstrap-dark .btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.bootstrap-dark .btn-light.focus,.bootstrap-dark .btn-light:focus{color:#212529;background-color:#e2e6ea;border-color:#dae0e5;-webkit-box-shadow:0 0 0 .2rem rgba(216,217,219,.5);box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.bootstrap-dark .btn-light.disabled,.bootstrap-dark .btn-light:disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.bootstrap-dark .btn-light:not(:disabled):not(.disabled).active,.bootstrap-dark .btn-light:not(:disabled):not(.disabled):active,.show>.bootstrap-dark .btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.bootstrap-dark .btn-light:not(:disabled):not(.disabled).active:focus,.bootstrap-dark .btn-light:not(:disabled):not(.disabled):active:focus,.show>.bootstrap-dark .btn-light.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(216,217,219,.5);box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.bootstrap-dark .btn-dark{color:#ced4da;background-color:#343a40;border-color:#343a40}.bootstrap-dark .btn-dark:hover{color:#ced4da;background-color:#23272b;border-color:#1d2124}.bootstrap-dark .btn-dark.focus,.bootstrap-dark .btn-dark:focus{color:#ced4da;background-color:#23272b;border-color:#1d2124;-webkit-box-shadow:0 0 0 .2rem rgba(75,81,87,.5);box-shadow:0 0 0 .2rem rgba(75,81,87,.5)}.bootstrap-dark .btn-dark.disabled,.bootstrap-dark .btn-dark:disabled{color:#ced4da;background-color:#343a40;border-color:#343a40}.bootstrap-dark .btn-dark:not(:disabled):not(.disabled).active,.bootstrap-dark .btn-dark:not(:disabled):not(.disabled):active,.show>.bootstrap-dark .btn-dark.dropdown-toggle{color:#ced4da;background-color:#1d2124;border-color:#171a1d}.bootstrap-dark .btn-dark:not(:disabled):not(.disabled).active:focus,.bootstrap-dark .btn-dark:not(:disabled):not(.disabled):active:focus,.show>.bootstrap-dark .btn-dark.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(75,81,87,.5);box-shadow:0 0 0 .2rem rgba(75,81,87,.5)}.bootstrap-dark .btn-outline-primary{color:#007bff;border-color:#007bff}.bootstrap-dark .btn-outline-primary:hover{color:#ced4da;background-color:#007bff;border-color:#007bff}.bootstrap-dark .btn-outline-primary.focus,.bootstrap-dark .btn-outline-primary:focus{-webkit-box-shadow:0 0 0 .2rem rgba(0,123,255,.5);box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.bootstrap-dark .btn-outline-primary.disabled,.bootstrap-dark .btn-outline-primary:disabled{color:#007bff;background-color:transparent}.bootstrap-dark .btn-outline-primary:not(:disabled):not(.disabled).active,.bootstrap-dark .btn-outline-primary:not(:disabled):not(.disabled):active,.show>.bootstrap-dark .btn-outline-primary.dropdown-toggle{color:#ced4da;background-color:#007bff;border-color:#007bff}.bootstrap-dark .btn-outline-primary:not(:disabled):not(.disabled).active:focus,.bootstrap-dark .btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.bootstrap-dark .btn-outline-primary.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(0,123,255,.5);box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.bootstrap-dark .btn-outline-secondary{color:#6c757d;border-color:#6c757d}.bootstrap-dark .btn-outline-secondary:hover{color:#ced4da;background-color:#6c757d;border-color:#6c757d}.bootstrap-dark .btn-outline-secondary.focus,.bootstrap-dark .btn-outline-secondary:focus{-webkit-box-shadow:0 0 0 .2rem rgba(108,117,125,.5);box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.bootstrap-dark .btn-outline-secondary.disabled,.bootstrap-dark .btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.bootstrap-dark .btn-outline-secondary:not(:disabled):not(.disabled).active,.bootstrap-dark .btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.bootstrap-dark .btn-outline-secondary.dropdown-toggle{color:#ced4da;background-color:#6c757d;border-color:#6c757d}.bootstrap-dark .btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.bootstrap-dark .btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.bootstrap-dark .btn-outline-secondary.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(108,117,125,.5);box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.bootstrap-dark .btn-outline-success{color:#28a745;border-color:#28a745}.bootstrap-dark .btn-outline-success:hover{color:#ced4da;background-color:#28a745;border-color:#28a745}.bootstrap-dark .btn-outline-success.focus,.bootstrap-dark .btn-outline-success:focus{-webkit-box-shadow:0 0 0 .2rem rgba(40,167,69,.5);box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.bootstrap-dark .btn-outline-success.disabled,.bootstrap-dark .btn-outline-success:disabled{color:#28a745;background-color:transparent}.bootstrap-dark .btn-outline-success:not(:disabled):not(.disabled).active,.bootstrap-dark .btn-outline-success:not(:disabled):not(.disabled):active,.show>.bootstrap-dark .btn-outline-success.dropdown-toggle{color:#ced4da;background-color:#28a745;border-color:#28a745}.bootstrap-dark .btn-outline-success:not(:disabled):not(.disabled).active:focus,.bootstrap-dark .btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.bootstrap-dark .btn-outline-success.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(40,167,69,.5);box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.bootstrap-dark .btn-outline-info{color:#17a2b8;border-color:#17a2b8}.bootstrap-dark .btn-outline-info:hover{color:#ced4da;background-color:#17a2b8;border-color:#17a2b8}.bootstrap-dark .btn-outline-info.focus,.bootstrap-dark .btn-outline-info:focus{-webkit-box-shadow:0 0 0 .2rem rgba(23,162,184,.5);box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.bootstrap-dark .btn-outline-info.disabled,.bootstrap-dark .btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.bootstrap-dark .btn-outline-info:not(:disabled):not(.disabled).active,.bootstrap-dark .btn-outline-info:not(:disabled):not(.disabled):active,.show>.bootstrap-dark .btn-outline-info.dropdown-toggle{color:#ced4da;background-color:#17a2b8;border-color:#17a2b8}.bootstrap-dark .btn-outline-info:not(:disabled):not(.disabled).active:focus,.bootstrap-dark .btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.bootstrap-dark .btn-outline-info.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(23,162,184,.5);box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.bootstrap-dark .btn-outline-warning{color:#ffc107;border-color:#ffc107}.bootstrap-dark .btn-outline-warning:hover{color:#212529;background-color:#ffc107;border-color:#ffc107}.bootstrap-dark .btn-outline-warning.focus,.bootstrap-dark .btn-outline-warning:focus{-webkit-box-shadow:0 0 0 .2rem rgba(255,193,7,.5);box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.bootstrap-dark .btn-outline-warning.disabled,.bootstrap-dark .btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.bootstrap-dark .btn-outline-warning:not(:disabled):not(.disabled).active,.bootstrap-dark .btn-outline-warning:not(:disabled):not(.disabled):active,.show>.bootstrap-dark .btn-outline-warning.dropdown-toggle{color:#212529;background-color:#ffc107;border-color:#ffc107}.bootstrap-dark .btn-outline-warning:not(:disabled):not(.disabled).active:focus,.bootstrap-dark .btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.bootstrap-dark .btn-outline-warning.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(255,193,7,.5);box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.bootstrap-dark .btn-outline-danger{color:#dc3545;border-color:#dc3545}.bootstrap-dark .btn-outline-danger:hover{color:#ced4da;background-color:#dc3545;border-color:#dc3545}.bootstrap-dark .btn-outline-danger.focus,.bootstrap-dark .btn-outline-danger:focus{-webkit-box-shadow:0 0 0 .2rem rgba(220,53,69,.5);box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.bootstrap-dark .btn-outline-danger.disabled,.bootstrap-dark .btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.bootstrap-dark .btn-outline-danger:not(:disabled):not(.disabled).active,.bootstrap-dark .btn-outline-danger:not(:disabled):not(.disabled):active,.show>.bootstrap-dark .btn-outline-danger.dropdown-toggle{color:#ced4da;background-color:#dc3545;border-color:#dc3545}.bootstrap-dark .btn-outline-danger:not(:disabled):not(.disabled).active:focus,.bootstrap-dark .btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.bootstrap-dark .btn-outline-danger.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(220,53,69,.5);box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.bootstrap-dark .btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.bootstrap-dark .btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.bootstrap-dark .btn-outline-light.focus,.bootstrap-dark .btn-outline-light:focus{-webkit-box-shadow:0 0 0 .2rem rgba(248,249,250,.5);box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.bootstrap-dark .btn-outline-light.disabled,.bootstrap-dark .btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.bootstrap-dark .btn-outline-light:not(:disabled):not(.disabled).active,.bootstrap-dark .btn-outline-light:not(:disabled):not(.disabled):active,.show>.bootstrap-dark .btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.bootstrap-dark .btn-outline-light:not(:disabled):not(.disabled).active:focus,.bootstrap-dark .btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.bootstrap-dark .btn-outline-light.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(248,249,250,.5);box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.bootstrap-dark .btn-outline-dark{color:#343a40;border-color:#343a40}.bootstrap-dark .btn-outline-dark:hover{color:#ced4da;background-color:#343a40;border-color:#343a40}.bootstrap-dark .btn-outline-dark.focus,.bootstrap-dark .btn-outline-dark:focus{-webkit-box-shadow:0 0 0 .2rem rgba(52,58,64,.5);box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.bootstrap-dark .btn-outline-dark.disabled,.bootstrap-dark .btn-outline-dark:disabled{color:#343a40;background-color:transparent}.bootstrap-dark .btn-outline-dark:not(:disabled):not(.disabled).active,.bootstrap-dark .btn-outline-dark:not(:disabled):not(.disabled):active,.show>.bootstrap-dark .btn-outline-dark.dropdown-toggle{color:#ced4da;background-color:#343a40;border-color:#343a40}.bootstrap-dark .btn-outline-dark:not(:disabled):not(.disabled).active:focus,.bootstrap-dark .btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.bootstrap-dark .btn-outline-dark.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(52,58,64,.5);box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.bootstrap-dark .btn-link{font-weight:400;color:#adadad;text-decoration:none}.bootstrap-dark .btn-link:hover{color:#878787;text-decoration:underline}.bootstrap-dark .btn-link.focus,.bootstrap-dark .btn-link:focus{text-decoration:underline;-webkit-box-shadow:none;box-shadow:none}.bootstrap-dark .btn-link.disabled,.bootstrap-dark .btn-link:disabled{color:#6c757d;pointer-events:none}.bootstrap-dark .btn-group-lg>.btn,.bootstrap-dark .btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.bootstrap-dark .btn-group-sm>.btn,.bootstrap-dark .btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.bootstrap-dark .btn-block{display:block;width:100%}.bootstrap-dark .btn-block+.btn-block{margin-top:.5rem}.bootstrap-dark input[type=button].btn-block,.bootstrap-dark input[type=reset].btn-block,.bootstrap-dark input[type=submit].btn-block{width:100%}.bootstrap-dark .fade{-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.bootstrap-dark .fade{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap-dark .fade:not(.show){opacity:0}.bootstrap-dark .collapse:not(.show){display:none}.bootstrap-dark .collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.bootstrap-dark .collapsing{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap-dark .dropdown,.bootstrap-dark .dropleft,.bootstrap-dark .dropright,.bootstrap-dark .dropup{position:relative}.bootstrap-dark .dropdown-toggle{white-space:nowrap}.bootstrap-dark .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.bootstrap-dark .dropdown-toggle:empty::after{margin-left:0}.bootstrap-dark .dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.bootstrap-dark .dropdown-menu-left{right:auto;left:0}.bootstrap-dark .dropdown-menu-right{right:0;left:auto}@media (min-width:576px){.bootstrap-dark .dropdown-menu-sm-left{right:auto;left:0}.bootstrap-dark .dropdown-menu-sm-right{right:0;left:auto}}@media (min-width:768px){.bootstrap-dark .dropdown-menu-md-left{right:auto;left:0}.bootstrap-dark .dropdown-menu-md-right{right:0;left:auto}}@media (min-width:992px){.bootstrap-dark .dropdown-menu-lg-left{right:auto;left:0}.bootstrap-dark .dropdown-menu-lg-right{right:0;left:auto}}@media (min-width:1200px){.bootstrap-dark .dropdown-menu-xl-left{right:auto;left:0}.bootstrap-dark .dropdown-menu-xl-right{right:0;left:auto}}.bootstrap-dark .dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.bootstrap-dark .dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.bootstrap-dark .dropup .dropdown-toggle:empty::after{margin-left:0}.bootstrap-dark .dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.bootstrap-dark .dropright .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.bootstrap-dark .dropright .dropdown-toggle:empty::after{margin-left:0}.bootstrap-dark .dropright .dropdown-toggle::after{vertical-align:0}.bootstrap-dark .dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.bootstrap-dark .dropleft .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.bootstrap-dark .dropleft .dropdown-toggle::after{display:none}.bootstrap-dark .dropleft .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.bootstrap-dark .dropleft .dropdown-toggle:empty::after{margin-left:0}.bootstrap-dark .dropleft .dropdown-toggle::before{vertical-align:0}.bootstrap-dark .dropdown-menu[x-placement^=bottom],.bootstrap-dark .dropdown-menu[x-placement^=left],.bootstrap-dark .dropdown-menu[x-placement^=right],.bootstrap-dark .dropdown-menu[x-placement^=top]{right:auto;bottom:auto}.bootstrap-dark .dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.bootstrap-dark .dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#212529;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.bootstrap-dark .dropdown-item:focus,.bootstrap-dark .dropdown-item:hover{color:#16181b;text-decoration:none;background-color:#f8f9fa}.bootstrap-dark .dropdown-item.active,.bootstrap-dark .dropdown-item:active{color:#fff;text-decoration:none;background-color:#007bff}.bootstrap-dark .dropdown-item.disabled,.bootstrap-dark .dropdown-item:disabled{color:#6c757d;pointer-events:none;background-color:transparent}.bootstrap-dark .dropdown-menu.show{display:block}.bootstrap-dark .dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.bootstrap-dark .dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#212529}.bootstrap-dark .btn-group,.bootstrap-dark .btn-group-vertical{position:relative;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.bootstrap-dark .btn-group-vertical>.btn,.bootstrap-dark .btn-group>.btn{position:relative;-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.bootstrap-dark .btn-group-vertical>.btn:hover,.bootstrap-dark .btn-group>.btn:hover{z-index:1}.bootstrap-dark .btn-group-vertical>.btn.active,.bootstrap-dark .btn-group-vertical>.btn:active,.bootstrap-dark .btn-group-vertical>.btn:focus,.bootstrap-dark .btn-group>.btn.active,.bootstrap-dark .btn-group>.btn:active,.bootstrap-dark .btn-group>.btn:focus{z-index:1}.bootstrap-dark .btn-toolbar{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.bootstrap-dark .btn-toolbar .input-group{width:auto}.bootstrap-dark .btn-group>.btn-group:not(:first-child),.bootstrap-dark .btn-group>.btn:not(:first-child){margin-left:-1px}.bootstrap-dark .btn-group>.btn-group:not(:last-child)>.btn,.bootstrap-dark .btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.bootstrap-dark .btn-group>.btn-group:not(:first-child)>.btn,.bootstrap-dark .btn-group>.btn:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.bootstrap-dark .dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.bootstrap-dark .dropdown-toggle-split::after,.dropright .bootstrap-dark .dropdown-toggle-split::after,.dropup .bootstrap-dark .dropdown-toggle-split::after{margin-left:0}.dropleft .bootstrap-dark .dropdown-toggle-split::before{margin-right:0}.bootstrap-dark .btn-group-sm>.btn+.dropdown-toggle-split,.bootstrap-dark .btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.bootstrap-dark .btn-group-lg>.btn+.dropdown-toggle-split,.bootstrap-dark .btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.bootstrap-dark .btn-group-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.bootstrap-dark .btn-group-vertical>.btn,.bootstrap-dark .btn-group-vertical>.btn-group{width:100%}.bootstrap-dark .btn-group-vertical>.btn-group:not(:first-child),.bootstrap-dark .btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.bootstrap-dark .btn-group-vertical>.btn-group:not(:last-child)>.btn,.bootstrap-dark .btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.bootstrap-dark .btn-group-vertical>.btn-group:not(:first-child)>.btn,.bootstrap-dark .btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.bootstrap-dark .btn-group-toggle>.btn,.bootstrap-dark .btn-group-toggle>.btn-group>.btn{margin-bottom:0}.bootstrap-dark .btn-group-toggle>.btn input[type=checkbox],.bootstrap-dark .btn-group-toggle>.btn input[type=radio],.bootstrap-dark .btn-group-toggle>.btn-group>.btn input[type=checkbox],.bootstrap-dark .btn-group-toggle>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.bootstrap-dark .input-group{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch;width:100%}.bootstrap-dark .input-group>.custom-file,.bootstrap-dark .input-group>.custom-select,.bootstrap-dark .input-group>.form-control,.bootstrap-dark .input-group>.form-control-plaintext{position:relative;-webkit-box-flex:1;-webkit-flex:1 1 0%;-ms-flex:1 1 0%;flex:1 1 0%;min-width:0;margin-bottom:0}.bootstrap-dark .input-group>.custom-file+.custom-file,.bootstrap-dark .input-group>.custom-file+.custom-select,.bootstrap-dark .input-group>.custom-file+.form-control,.bootstrap-dark .input-group>.custom-select+.custom-file,.bootstrap-dark .input-group>.custom-select+.custom-select,.bootstrap-dark .input-group>.custom-select+.form-control,.bootstrap-dark .input-group>.form-control+.custom-file,.bootstrap-dark .input-group>.form-control+.custom-select,.bootstrap-dark .input-group>.form-control+.form-control,.bootstrap-dark .input-group>.form-control-plaintext+.custom-file,.bootstrap-dark .input-group>.form-control-plaintext+.custom-select,.bootstrap-dark .input-group>.form-control-plaintext+.form-control{margin-left:-1px}.bootstrap-dark .input-group>.custom-file .custom-file-input:focus~.custom-file-label,.bootstrap-dark .input-group>.custom-select:focus,.bootstrap-dark .input-group>.form-control:focus{z-index:3}.bootstrap-dark .input-group>.custom-file .custom-file-input:focus{z-index:4}.bootstrap-dark .input-group>.custom-select:not(:last-child),.bootstrap-dark .input-group>.form-control:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.bootstrap-dark .input-group>.custom-select:not(:first-child),.bootstrap-dark .input-group>.form-control:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.bootstrap-dark .input-group>.custom-file{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.bootstrap-dark .input-group>.custom-file:not(:last-child) .custom-file-label,.bootstrap-dark .input-group>.custom-file:not(:last-child) .custom-file-label::after{border-top-right-radius:0;border-bottom-right-radius:0}.bootstrap-dark .input-group>.custom-file:not(:first-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.bootstrap-dark .input-group-append,.bootstrap-dark .input-group-prepend{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.bootstrap-dark .input-group-append .btn,.bootstrap-dark .input-group-prepend .btn{position:relative;z-index:2}.bootstrap-dark .input-group-append .btn:focus,.bootstrap-dark .input-group-prepend .btn:focus{z-index:3}.bootstrap-dark .input-group-append .btn+.btn,.bootstrap-dark .input-group-append .btn+.input-group-text,.bootstrap-dark .input-group-append .input-group-text+.btn,.bootstrap-dark .input-group-append .input-group-text+.input-group-text,.bootstrap-dark .input-group-prepend .btn+.btn,.bootstrap-dark .input-group-prepend .btn+.input-group-text,.bootstrap-dark .input-group-prepend .input-group-text+.btn,.bootstrap-dark .input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.bootstrap-dark .input-group-prepend{margin-right:-1px}.bootstrap-dark .input-group-append{margin-left:-1px}.bootstrap-dark .input-group-text{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#dee2e6;text-align:center;white-space:nowrap;background-color:#343a40;border:1px solid #6c757d;border-radius:.25rem}.bootstrap-dark .input-group-text input[type=checkbox],.bootstrap-dark .input-group-text input[type=radio]{margin-top:0}.bootstrap-dark .input-group-lg>.custom-select,.bootstrap-dark .input-group-lg>.form-control:not(textarea){height:calc(1.5em + 1rem + 2px)}.bootstrap-dark .input-group-lg>.custom-select,.bootstrap-dark .input-group-lg>.form-control,.bootstrap-dark .input-group-lg>.input-group-append>.btn,.bootstrap-dark .input-group-lg>.input-group-append>.input-group-text,.bootstrap-dark .input-group-lg>.input-group-prepend>.btn,.bootstrap-dark .input-group-lg>.input-group-prepend>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.bootstrap-dark .input-group-sm>.custom-select,.bootstrap-dark .input-group-sm>.form-control:not(textarea){height:calc(1.5em + .5rem + 2px)}.bootstrap-dark .input-group-sm>.custom-select,.bootstrap-dark .input-group-sm>.form-control,.bootstrap-dark .input-group-sm>.input-group-append>.btn,.bootstrap-dark .input-group-sm>.input-group-append>.input-group-text,.bootstrap-dark .input-group-sm>.input-group-prepend>.btn,.bootstrap-dark .input-group-sm>.input-group-prepend>.input-group-text{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.bootstrap-dark .input-group-lg>.custom-select,.bootstrap-dark .input-group-sm>.custom-select{padding-right:1.75rem}.bootstrap-dark .input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.bootstrap-dark .input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.bootstrap-dark .input-group>.input-group-append:not(:last-child)>.btn,.bootstrap-dark .input-group>.input-group-append:not(:last-child)>.input-group-text,.bootstrap-dark .input-group>.input-group-prepend>.btn,.bootstrap-dark .input-group>.input-group-prepend>.input-group-text{border-top-right-radius:0;border-bottom-right-radius:0}.bootstrap-dark .input-group>.input-group-append>.btn,.bootstrap-dark .input-group>.input-group-append>.input-group-text,.bootstrap-dark .input-group>.input-group-prepend:first-child>.btn:not(:first-child),.bootstrap-dark .input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.bootstrap-dark .input-group>.input-group-prepend:not(:first-child)>.btn,.bootstrap-dark .input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-top-left-radius:0;border-bottom-left-radius:0}.bootstrap-dark .input-group>.input-group-append>.custom-select{border-top-left-radius:0;border-bottom-left-radius:0}.bootstrap-dark .input-group>.input-group-prepend>.custom-select{border-top-right-radius:0;border-bottom-right-radius:0}.bootstrap-dark .custom-control{position:relative;display:block;min-height:1.5rem;padding-left:1.5rem}.bootstrap-dark .custom-control-inline{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;margin-right:1rem}.bootstrap-dark .custom-control-input{position:absolute;left:0;z-index:-1;width:1rem;height:1.25rem;opacity:0}.bootstrap-dark .custom-control-input:checked~.custom-control-label::before{color:#fff;border-color:#007bff;background-color:#007bff}.bootstrap-dark .custom-control-input:focus~.custom-control-label::before{-webkit-box-shadow:0 0 0 .2rem rgba(0,123,255,.25);box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.bootstrap-dark .custom-control-input:focus:not(:checked)~.custom-control-label::before{border-color:#80bdff}.bootstrap-dark .custom-control-input:not(:disabled):active~.custom-control-label::before{color:#fff;background-color:#b3d7ff;border-color:#b3d7ff}.bootstrap-dark .custom-control-input:disabled~.custom-control-label,.bootstrap-dark .custom-control-input[disabled]~.custom-control-label{color:#6c757d}.bootstrap-dark .custom-control-input:disabled~.custom-control-label::before,.bootstrap-dark .custom-control-input[disabled]~.custom-control-label::before{background-color:#e9ecef}.bootstrap-dark .custom-control-label{position:relative;margin-bottom:0;vertical-align:top}.bootstrap-dark .custom-control-label::before{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;pointer-events:none;content:"";background-color:#fff;border:#adb5bd solid 1px}.bootstrap-dark .custom-control-label::after{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:"";background:no-repeat 50%/50% 50%}.bootstrap-dark .custom-checkbox .custom-control-label::before{border-radius:.25rem}.bootstrap-dark .custom-checkbox .custom-control-input:checked~.custom-control-label::after{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")}.bootstrap-dark .custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before{border-color:#007bff;background-color:#007bff}.bootstrap-dark .custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after{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")}.bootstrap-dark .custom-checkbox .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.bootstrap-dark .custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.bootstrap-dark .custom-radio .custom-control-label::before{border-radius:50%}.bootstrap-dark .custom-radio .custom-control-input:checked~.custom-control-label::after{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")}.bootstrap-dark .custom-radio .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.bootstrap-dark .custom-switch{padding-left:2.25rem}.bootstrap-dark .custom-switch .custom-control-label::before{left:-2.25rem;width:1.75rem;pointer-events:all;border-radius:.5rem}.bootstrap-dark .custom-switch .custom-control-label::after{top:calc(.25rem + 2px);left:calc(-2.25rem + 2px);width:calc(1rem - 4px);height:calc(1rem - 4px);background-color:#adb5bd;border-radius:.5rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-transform .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-transform .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-o-transform .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out,-o-transform .15s ease-in-out,-webkit-box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.bootstrap-dark .custom-switch .custom-control-label::after{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap-dark .custom-switch .custom-control-input:checked~.custom-control-label::after{background-color:#fff;-webkit-transform:translateX(.75rem);-o-transform:translateX(.75rem);transform:translateX(.75rem)}.bootstrap-dark .custom-switch .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.bootstrap-dark .custom-select{display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem 1.75rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;vertical-align:middle;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 .75rem center/8px 10px;border:1px solid #ced4da;border-radius:.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.bootstrap-dark .custom-select:focus{border-color:#80bdff;outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(0,123,255,.25);box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.bootstrap-dark .custom-select:focus::-ms-value{color:#dee2e6;background-color:#000}.bootstrap-dark .custom-select[multiple],.bootstrap-dark .custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.bootstrap-dark .custom-select:disabled{color:#ced4da;background-color:#343a40}.bootstrap-dark .custom-select::-ms-expand{display:none}.bootstrap-dark .custom-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.bootstrap-dark .custom-select-sm{height:calc(1.5em + .5rem + 2px);padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.bootstrap-dark .custom-select-lg{height:calc(1.5em + 1rem + 2px);padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.bootstrap-dark .custom-file{position:relative;display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);margin-bottom:0}.bootstrap-dark .custom-file-input{position:relative;z-index:2;width:100%;height:calc(1.5em + .75rem + 2px);margin:0;opacity:0}.bootstrap-dark .custom-file-input:focus~.custom-file-label{border-color:#80bdff;-webkit-box-shadow:0 0 0 .2rem rgba(0,123,255,.25);box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.bootstrap-dark .custom-file-input:disabled~.custom-file-label,.bootstrap-dark .custom-file-input[disabled]~.custom-file-label{background-color:#e9ecef}.bootstrap-dark .custom-file-input:lang(en)~.custom-file-label::after{content:"Browse"}.bootstrap-dark .custom-file-input~.custom-file-label[data-browse]::after{content:attr(data-browse)}.bootstrap-dark .custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.bootstrap-dark .custom-file-label::after{position:absolute;top:0;right:0;bottom:0;z-index:3;display:block;height:calc(1.5em + .75rem);padding:.375rem .75rem;line-height:1.5;color:#495057;content:"Browse";background-color:#e9ecef;border-left:inherit;border-radius:0 .25rem .25rem 0}.bootstrap-dark .custom-range{width:100%;height:1.4rem;padding:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.bootstrap-dark .custom-range:focus{outline:0}.bootstrap-dark .custom-range:focus::-webkit-slider-thumb{-webkit-box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25);box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.bootstrap-dark .custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.bootstrap-dark .custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.bootstrap-dark .custom-range::-moz-focus-outer{border:0}.bootstrap-dark .custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#007bff;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.bootstrap-dark .custom-range::-webkit-slider-thumb{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap-dark .custom-range::-webkit-slider-thumb:active{background-color:#b3d7ff}.bootstrap-dark .custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.bootstrap-dark .custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#007bff;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.bootstrap-dark .custom-range::-moz-range-thumb{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap-dark .custom-range::-moz-range-thumb:active{background-color:#b3d7ff}.bootstrap-dark .custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.bootstrap-dark .custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background-color:#007bff;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion:reduce){.bootstrap-dark .custom-range::-ms-thumb{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap-dark .custom-range::-ms-thumb:active{background-color:#b3d7ff}.bootstrap-dark .custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem}.bootstrap-dark .custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.bootstrap-dark .custom-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.bootstrap-dark .custom-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.bootstrap-dark .custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.bootstrap-dark .custom-range:disabled::-moz-range-thumb{background-color:#adb5bd}.bootstrap-dark .custom-range:disabled::-moz-range-track{cursor:default}.bootstrap-dark .custom-range:disabled::-ms-thumb{background-color:#adb5bd}.bootstrap-dark .custom-control-label::before,.bootstrap-dark .custom-file-label,.bootstrap-dark .custom-select{-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.bootstrap-dark .custom-control-label::before,.bootstrap-dark .custom-file-label,.bootstrap-dark .custom-select{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap-dark .nav{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.bootstrap-dark .nav-link{display:block;padding:.5rem 1rem}.bootstrap-dark .nav-link:focus,.bootstrap-dark .nav-link:hover{text-decoration:none}.bootstrap-dark .nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.bootstrap-dark .nav-tabs{border-bottom:1px solid rgba(255,255,255,.125)}.bootstrap-dark .nav-tabs .nav-item{margin-bottom:-1px}.bootstrap-dark .nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.bootstrap-dark .nav-tabs .nav-link:focus,.bootstrap-dark .nav-tabs .nav-link:hover{border-color:#495057 #495057 rgba(255,255,255,.125)}.bootstrap-dark .nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.bootstrap-dark .nav-tabs .nav-item.show .nav-link,.bootstrap-dark .nav-tabs .nav-link.active{color:#f8f9fa;background-color:#191d21;border-color:#495057 #495057 #191d21}.bootstrap-dark .nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.bootstrap-dark .nav-pills .nav-link{border-radius:.25rem}.bootstrap-dark .nav-pills .nav-link.active,.bootstrap-dark .nav-pills .show>.nav-link{color:#fff;background-color:#007bff}.bootstrap-dark .nav-fill .nav-item{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.bootstrap-dark .nav-justified .nav-item{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;text-align:center}.bootstrap-dark .tab-content>.tab-pane{display:none}.bootstrap-dark .tab-content>.active{display:block}.bootstrap-dark .navbar{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;padding:.5rem 1rem}.bootstrap-dark .navbar .container,.bootstrap-dark .navbar .container-fluid,.bootstrap-dark .navbar .container-lg,.bootstrap-dark .navbar .container-md,.bootstrap-dark .navbar .container-sm,.bootstrap-dark .navbar .container-xl{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.bootstrap-dark .navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.bootstrap-dark .navbar-brand:focus,.bootstrap-dark .navbar-brand:hover{text-decoration:none}.bootstrap-dark .navbar-nav{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.bootstrap-dark .navbar-nav .nav-link{padding-right:0;padding-left:0}.bootstrap-dark .navbar-nav .dropdown-menu{position:static;float:none}.bootstrap-dark .navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.bootstrap-dark .navbar-collapse{-webkit-flex-basis:100%;-ms-flex-preferred-size:100%;flex-basis:100%;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.bootstrap-dark .navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.bootstrap-dark .navbar-toggler:focus,.bootstrap-dark .navbar-toggler:hover{text-decoration:none}.bootstrap-dark .navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:no-repeat center center;-webkit-background-size:100% 100%;background-size:100% 100%}@media (max-width:575.98px){.bootstrap-dark .navbar-expand-sm>.container,.bootstrap-dark .navbar-expand-sm>.container-fluid,.bootstrap-dark .navbar-expand-sm>.container-lg,.bootstrap-dark .navbar-expand-sm>.container-md,.bootstrap-dark .navbar-expand-sm>.container-sm,.bootstrap-dark .navbar-expand-sm>.container-xl{padding-right:0;padding-left:0}}@media (min-width:576px){.bootstrap-dark .navbar-expand-sm{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.bootstrap-dark .navbar-expand-sm .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.bootstrap-dark .navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.bootstrap-dark .navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.bootstrap-dark .navbar-expand-sm>.container,.bootstrap-dark .navbar-expand-sm>.container-fluid,.bootstrap-dark .navbar-expand-sm>.container-lg,.bootstrap-dark .navbar-expand-sm>.container-md,.bootstrap-dark .navbar-expand-sm>.container-sm,.bootstrap-dark .navbar-expand-sm>.container-xl{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.bootstrap-dark .navbar-expand-sm .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;-webkit-flex-basis:auto;-ms-flex-preferred-size:auto;flex-basis:auto}.bootstrap-dark .navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:767.98px){.bootstrap-dark .navbar-expand-md>.container,.bootstrap-dark .navbar-expand-md>.container-fluid,.bootstrap-dark .navbar-expand-md>.container-lg,.bootstrap-dark .navbar-expand-md>.container-md,.bootstrap-dark .navbar-expand-md>.container-sm,.bootstrap-dark .navbar-expand-md>.container-xl{padding-right:0;padding-left:0}}@media (min-width:768px){.bootstrap-dark .navbar-expand-md{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.bootstrap-dark .navbar-expand-md .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.bootstrap-dark .navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.bootstrap-dark .navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.bootstrap-dark .navbar-expand-md>.container,.bootstrap-dark .navbar-expand-md>.container-fluid,.bootstrap-dark .navbar-expand-md>.container-lg,.bootstrap-dark .navbar-expand-md>.container-md,.bootstrap-dark .navbar-expand-md>.container-sm,.bootstrap-dark .navbar-expand-md>.container-xl{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.bootstrap-dark .navbar-expand-md .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;-webkit-flex-basis:auto;-ms-flex-preferred-size:auto;flex-basis:auto}.bootstrap-dark .navbar-expand-md .navbar-toggler{display:none}}@media (max-width:991.98px){.bootstrap-dark .navbar-expand-lg>.container,.bootstrap-dark .navbar-expand-lg>.container-fluid,.bootstrap-dark .navbar-expand-lg>.container-lg,.bootstrap-dark .navbar-expand-lg>.container-md,.bootstrap-dark .navbar-expand-lg>.container-sm,.bootstrap-dark .navbar-expand-lg>.container-xl{padding-right:0;padding-left:0}}@media (min-width:992px){.bootstrap-dark .navbar-expand-lg{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.bootstrap-dark .navbar-expand-lg .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.bootstrap-dark .navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.bootstrap-dark .navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.bootstrap-dark .navbar-expand-lg>.container,.bootstrap-dark .navbar-expand-lg>.container-fluid,.bootstrap-dark .navbar-expand-lg>.container-lg,.bootstrap-dark .navbar-expand-lg>.container-md,.bootstrap-dark .navbar-expand-lg>.container-sm,.bootstrap-dark .navbar-expand-lg>.container-xl{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.bootstrap-dark .navbar-expand-lg .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;-webkit-flex-basis:auto;-ms-flex-preferred-size:auto;flex-basis:auto}.bootstrap-dark .navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:1199.98px){.bootstrap-dark .navbar-expand-xl>.container,.bootstrap-dark .navbar-expand-xl>.container-fluid,.bootstrap-dark .navbar-expand-xl>.container-lg,.bootstrap-dark .navbar-expand-xl>.container-md,.bootstrap-dark .navbar-expand-xl>.container-sm,.bootstrap-dark .navbar-expand-xl>.container-xl{padding-right:0;padding-left:0}}@media (min-width:1200px){.bootstrap-dark .navbar-expand-xl{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.bootstrap-dark .navbar-expand-xl .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.bootstrap-dark .navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.bootstrap-dark .navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.bootstrap-dark .navbar-expand-xl>.container,.bootstrap-dark .navbar-expand-xl>.container-fluid,.bootstrap-dark .navbar-expand-xl>.container-lg,.bootstrap-dark .navbar-expand-xl>.container-md,.bootstrap-dark .navbar-expand-xl>.container-sm,.bootstrap-dark .navbar-expand-xl>.container-xl{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.bootstrap-dark .navbar-expand-xl .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;-webkit-flex-basis:auto;-ms-flex-preferred-size:auto;flex-basis:auto}.bootstrap-dark .navbar-expand-xl .navbar-toggler{display:none}}.bootstrap-dark .navbar-expand{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.bootstrap-dark .navbar-expand>.container,.bootstrap-dark .navbar-expand>.container-fluid,.bootstrap-dark .navbar-expand>.container-lg,.bootstrap-dark .navbar-expand>.container-md,.bootstrap-dark .navbar-expand>.container-sm,.bootstrap-dark .navbar-expand>.container-xl{padding-right:0;padding-left:0}.bootstrap-dark .navbar-expand .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.bootstrap-dark .navbar-expand .navbar-nav .dropdown-menu{position:absolute}.bootstrap-dark .navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.bootstrap-dark .navbar-expand>.container,.bootstrap-dark .navbar-expand>.container-fluid,.bootstrap-dark .navbar-expand>.container-lg,.bootstrap-dark .navbar-expand>.container-md,.bootstrap-dark .navbar-expand>.container-sm,.bootstrap-dark .navbar-expand>.container-xl{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.bootstrap-dark .navbar-expand .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;-webkit-flex-basis:auto;-ms-flex-preferred-size:auto;flex-basis:auto}.bootstrap-dark .navbar-expand .navbar-toggler{display:none}.bootstrap-dark .navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.bootstrap-dark .navbar-light .navbar-brand:focus,.bootstrap-dark .navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.bootstrap-dark .navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.bootstrap-dark .navbar-light .navbar-nav .nav-link:focus,.bootstrap-dark .navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.bootstrap-dark .navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.bootstrap-dark .navbar-light .navbar-nav .active>.nav-link,.bootstrap-dark .navbar-light .navbar-nav .nav-link.active,.bootstrap-dark .navbar-light .navbar-nav .nav-link.show,.bootstrap-dark .navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.bootstrap-dark .navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.bootstrap-dark .navbar-light .navbar-toggler-icon{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(0, 0, 0, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.bootstrap-dark .navbar-light .navbar-text{color:rgba(0,0,0,.5)}.bootstrap-dark .navbar-light .navbar-text a{color:rgba(0,0,0,.9)}.bootstrap-dark .navbar-light .navbar-text a:focus,.bootstrap-dark .navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.bootstrap-dark .navbar-dark .navbar-brand{color:#fff}.bootstrap-dark .navbar-dark .navbar-brand:focus,.bootstrap-dark .navbar-dark .navbar-brand:hover{color:#fff}.bootstrap-dark .navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.bootstrap-dark .navbar-dark .navbar-nav .nav-link:focus,.bootstrap-dark .navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.bootstrap-dark .navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.bootstrap-dark .navbar-dark .navbar-nav .active>.nav-link,.bootstrap-dark .navbar-dark .navbar-nav .nav-link.active,.bootstrap-dark .navbar-dark .navbar-nav .nav-link.show,.bootstrap-dark .navbar-dark .navbar-nav .show>.nav-link{color:#fff}.bootstrap-dark .navbar-dark .navbar-toggler{color:rgba(255,255,255,.5);border-color:rgba(255,255,255,.1)}.bootstrap-dark .navbar-dark .navbar-toggler-icon{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(255, 255, 255, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.bootstrap-dark .navbar-dark .navbar-text{color:rgba(255,255,255,.5)}.bootstrap-dark .navbar-dark .navbar-text a{color:#fff}.bootstrap-dark .navbar-dark .navbar-text a:focus,.bootstrap-dark .navbar-dark .navbar-text a:hover{color:#fff}.bootstrap-dark .card{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#212529;-webkit-background-clip:border-box;background-clip:border-box;border:1px solid rgba(255,255,255,.125);border-radius:.25rem}.bootstrap-dark .card>hr{margin-right:0;margin-left:0}.bootstrap-dark .card>.list-group:first-child .list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.bootstrap-dark .card>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.bootstrap-dark .card-body{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;min-height:1px;padding:1.25rem;color:#e9ecef}.bootstrap-dark .card-title{margin-bottom:.75rem}.bootstrap-dark .card-subtitle{margin-top:-.375rem;margin-bottom:0}.bootstrap-dark .card-text:last-child{margin-bottom:0}.bootstrap-dark .card-link:hover{text-decoration:none}.bootstrap-dark .card-link+.card-link{margin-left:1.25rem}.bootstrap-dark .card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(255,255,255,.03);border-bottom:1px solid rgba(255,255,255,.125)}.bootstrap-dark .card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.bootstrap-dark .card-header+.list-group .list-group-item:first-child{border-top:0}.bootstrap-dark .card-footer{padding:.75rem 1.25rem;background-color:rgba(255,255,255,.03);border-top:1px solid rgba(255,255,255,.125)}.bootstrap-dark .card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.bootstrap-dark .card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.bootstrap-dark .card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.bootstrap-dark .card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.bootstrap-dark .card-img,.bootstrap-dark .card-img-bottom,.bootstrap-dark .card-img-top{-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;width:100%}.bootstrap-dark .card-img,.bootstrap-dark .card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.bootstrap-dark .card-img,.bootstrap-dark .card-img-bottom{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.bootstrap-dark .card-deck .card{margin-bottom:15px}@media (min-width:576px){.bootstrap-dark .card-deck{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.bootstrap-dark .card-deck .card{-webkit-box-flex:1;-webkit-flex:1 0 0%;-ms-flex:1 0 0%;flex:1 0 0%;margin-right:15px;margin-bottom:0;margin-left:15px}}.bootstrap-dark .card-group>.card{margin-bottom:15px}@media (min-width:576px){.bootstrap-dark .card-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap}.bootstrap-dark .card-group>.card{-webkit-box-flex:1;-webkit-flex:1 0 0%;-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.bootstrap-dark .card-group>.card+.card{margin-left:0;border-left:0}.bootstrap-dark .card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.bootstrap-dark .card-group>.card:not(:last-child) .card-header,.bootstrap-dark .card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.bootstrap-dark .card-group>.card:not(:last-child) .card-footer,.bootstrap-dark .card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.bootstrap-dark .card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.bootstrap-dark .card-group>.card:not(:first-child) .card-header,.bootstrap-dark .card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.bootstrap-dark .card-group>.card:not(:first-child) .card-footer,.bootstrap-dark .card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.bootstrap-dark .card-columns .card{margin-bottom:.75rem}@media (min-width:576px){.bootstrap-dark .card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.bootstrap-dark .card-columns .card{display:inline-block;width:100%}}.bootstrap-dark .accordion>.card{overflow:hidden}.bootstrap-dark .accordion>.card:not(:last-of-type){border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.bootstrap-dark .accordion>.card:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.bootstrap-dark .accordion>.card>.card-header{border-radius:0;margin-bottom:-1px}.bootstrap-dark .breadcrumb{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#e9ecef;border-radius:.25rem}.bootstrap-dark .breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.bootstrap-dark .breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:.5rem;color:#6c757d;content:"/"}.bootstrap-dark .breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.bootstrap-dark .breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.bootstrap-dark .breadcrumb-item.active{color:#6c757d}.bootstrap-dark .pagination{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding-left:0;list-style:none;border-radius:.25rem}.bootstrap-dark .page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#007bff;background-color:#fff;border:1px solid #dee2e6}.bootstrap-dark .page-link:hover{z-index:2;color:#0056b3;text-decoration:none;background-color:#e9ecef;border-color:#dee2e6}.bootstrap-dark .page-link:focus{z-index:3;outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(0,123,255,.25);box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.bootstrap-dark .page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.bootstrap-dark .page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.bootstrap-dark .page-item.active .page-link{z-index:3;color:#fff;background-color:#007bff;border-color:#007bff}.bootstrap-dark .page-item.disabled .page-link{color:#6c757d;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.bootstrap-dark .pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.bootstrap-dark .pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.bootstrap-dark .pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.bootstrap-dark .pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.bootstrap-dark .pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.bootstrap-dark .pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.bootstrap-dark .badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem;-webkit-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.bootstrap-dark .badge{-webkit-transition:none;-o-transition:none;transition:none}}a.bootstrap-dark .badge:focus,a.bootstrap-dark .badge:hover{text-decoration:none}.bootstrap-dark .badge:empty{display:none}.bootstrap-dark .btn .badge{position:relative;top:-1px}.bootstrap-dark .badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.bootstrap-dark .badge-primary{color:#ced4da;background-color:#007bff}a.bootstrap-dark .badge-primary:focus,a.bootstrap-dark .badge-primary:hover{color:#ced4da;background-color:#0062cc}a.bootstrap-dark .badge-primary.focus,a.bootstrap-dark .badge-primary:focus{outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(0,123,255,.5);box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.bootstrap-dark .badge-secondary{color:#ced4da;background-color:#6c757d}a.bootstrap-dark .badge-secondary:focus,a.bootstrap-dark .badge-secondary:hover{color:#ced4da;background-color:#545b62}a.bootstrap-dark .badge-secondary.focus,a.bootstrap-dark .badge-secondary:focus{outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(108,117,125,.5);box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.bootstrap-dark .badge-success{color:#ced4da;background-color:#28a745}a.bootstrap-dark .badge-success:focus,a.bootstrap-dark .badge-success:hover{color:#ced4da;background-color:#1e7e34}a.bootstrap-dark .badge-success.focus,a.bootstrap-dark .badge-success:focus{outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(40,167,69,.5);box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.bootstrap-dark .badge-info{color:#ced4da;background-color:#17a2b8}a.bootstrap-dark .badge-info:focus,a.bootstrap-dark .badge-info:hover{color:#ced4da;background-color:#117a8b}a.bootstrap-dark .badge-info.focus,a.bootstrap-dark .badge-info:focus{outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(23,162,184,.5);box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.bootstrap-dark .badge-warning{color:#212529;background-color:#ffc107}a.bootstrap-dark .badge-warning:focus,a.bootstrap-dark .badge-warning:hover{color:#212529;background-color:#d39e00}a.bootstrap-dark .badge-warning.focus,a.bootstrap-dark .badge-warning:focus{outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(255,193,7,.5);box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.bootstrap-dark .badge-danger{color:#ced4da;background-color:#dc3545}a.bootstrap-dark .badge-danger:focus,a.bootstrap-dark .badge-danger:hover{color:#ced4da;background-color:#bd2130}a.bootstrap-dark .badge-danger.focus,a.bootstrap-dark .badge-danger:focus{outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(220,53,69,.5);box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.bootstrap-dark .badge-light{color:#212529;background-color:#f8f9fa}a.bootstrap-dark .badge-light:focus,a.bootstrap-dark .badge-light:hover{color:#212529;background-color:#dae0e5}a.bootstrap-dark .badge-light.focus,a.bootstrap-dark .badge-light:focus{outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(248,249,250,.5);box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.bootstrap-dark .badge-dark{color:#ced4da;background-color:#343a40}a.bootstrap-dark .badge-dark:focus,a.bootstrap-dark .badge-dark:hover{color:#ced4da;background-color:#1d2124}a.bootstrap-dark .badge-dark.focus,a.bootstrap-dark .badge-dark:focus{outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(52,58,64,.5);box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.bootstrap-dark .jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width:576px){.bootstrap-dark .jumbotron{padding:4rem 2rem}}.bootstrap-dark .jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.bootstrap-dark .alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.bootstrap-dark .alert-heading{color:inherit}.bootstrap-dark .alert-link{font-weight:700}.bootstrap-dark .alert-dismissible{padding-right:4rem}.bootstrap-dark .alert-dismissible .close{position:absolute;top:0;right:0;padding:.75rem 1.25rem;color:inherit}.bootstrap-dark .alert-primary{color:#004085;background-color:#cce5ff;border-color:#b8daff}.bootstrap-dark .alert-primary hr{border-top-color:#9fcdff}.bootstrap-dark .alert-primary .alert-link{color:#002752}.bootstrap-dark .alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.bootstrap-dark .alert-secondary hr{border-top-color:#c8cbcf}.bootstrap-dark .alert-secondary .alert-link{color:#202326}.bootstrap-dark .alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.bootstrap-dark .alert-success hr{border-top-color:#b1dfbb}.bootstrap-dark .alert-success .alert-link{color:#0b2e13}.bootstrap-dark .alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.bootstrap-dark .alert-info hr{border-top-color:#abdde5}.bootstrap-dark .alert-info .alert-link{color:#062c33}.bootstrap-dark .alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.bootstrap-dark .alert-warning hr{border-top-color:#ffe8a1}.bootstrap-dark .alert-warning .alert-link{color:#533f03}.bootstrap-dark .alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.bootstrap-dark .alert-danger hr{border-top-color:#f1b0b7}.bootstrap-dark .alert-danger .alert-link{color:#491217}.bootstrap-dark .alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.bootstrap-dark .alert-light hr{border-top-color:#ececf6}.bootstrap-dark .alert-light .alert-link{color:#686868}.bootstrap-dark .alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.bootstrap-dark .alert-dark hr{border-top-color:#b9bbbe}.bootstrap-dark .alert-dark .alert-link{color:#040505}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.bootstrap-dark .progress{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;height:1rem;overflow:hidden;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.bootstrap-dark .progress-bar{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;overflow:hidden;color:#fff;text-align:center;white-space:nowrap;background-color:#007bff;-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}@media (prefers-reduced-motion:reduce){.bootstrap-dark .progress-bar{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap-dark .progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:1rem 1rem;background-size:1rem 1rem}.bootstrap-dark .progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;-o-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}@media (prefers-reduced-motion:reduce){.bootstrap-dark .progress-bar-animated{-webkit-animation:none;-o-animation:none;animation:none}}.bootstrap-dark .media{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start}.bootstrap-dark .media-body{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.bootstrap-dark .list-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0}.bootstrap-dark .list-group-item-action{width:100%;color:#dee2e6;text-align:inherit}.bootstrap-dark .list-group-item-action:focus,.bootstrap-dark .list-group-item-action:hover{z-index:1;color:#dee2e6;text-decoration:none;background-color:#212529}.bootstrap-dark .list-group-item-action:active{color:#d3d3d3;background-color:#343a40}.bootstrap-dark .list-group-item{position:relative;display:block;padding:.75rem 1.25rem;background-color:rgba(25,29,33,.05);border:1px solid rgba(255,255,255,.125)}.bootstrap-dark .list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.bootstrap-dark .list-group-item:last-child{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.bootstrap-dark .list-group-item.disabled,.bootstrap-dark .list-group-item:disabled{color:#ced4da;pointer-events:none;background-color:rgba(25,29,33,.05)}.bootstrap-dark .list-group-item.active{z-index:2;color:#000;background-color:#3395ff;border-color:#3395ff}.bootstrap-dark .list-group-item+.bootstrap-dark .list-group-item{border-top-width:0}.bootstrap-dark .list-group-item+.bootstrap-dark .list-group-item.active{margin-top:-1px;border-top-width:1px}.bootstrap-dark .list-group-horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.bootstrap-dark .list-group-horizontal .list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.bootstrap-dark .list-group-horizontal .list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.bootstrap-dark .list-group-horizontal .list-group-item.active{margin-top:0}.bootstrap-dark .list-group-horizontal .list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.bootstrap-dark .list-group-horizontal .list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media (min-width:576px){.bootstrap-dark .list-group-horizontal-sm{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.bootstrap-dark .list-group-horizontal-sm .list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.bootstrap-dark .list-group-horizontal-sm .list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.bootstrap-dark .list-group-horizontal-sm .list-group-item.active{margin-top:0}.bootstrap-dark .list-group-horizontal-sm .list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.bootstrap-dark .list-group-horizontal-sm .list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:768px){.bootstrap-dark .list-group-horizontal-md{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.bootstrap-dark .list-group-horizontal-md .list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.bootstrap-dark .list-group-horizontal-md .list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.bootstrap-dark .list-group-horizontal-md .list-group-item.active{margin-top:0}.bootstrap-dark .list-group-horizontal-md .list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.bootstrap-dark .list-group-horizontal-md .list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:992px){.bootstrap-dark .list-group-horizontal-lg{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.bootstrap-dark .list-group-horizontal-lg .list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.bootstrap-dark .list-group-horizontal-lg .list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.bootstrap-dark .list-group-horizontal-lg .list-group-item.active{margin-top:0}.bootstrap-dark .list-group-horizontal-lg .list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.bootstrap-dark .list-group-horizontal-lg .list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:1200px){.bootstrap-dark .list-group-horizontal-xl{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.bootstrap-dark .list-group-horizontal-xl .list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.bootstrap-dark .list-group-horizontal-xl .list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.bootstrap-dark .list-group-horizontal-xl .list-group-item.active{margin-top:0}.bootstrap-dark .list-group-horizontal-xl .list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.bootstrap-dark .list-group-horizontal-xl .list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.bootstrap-dark .list-group-flush .list-group-item{border-right-width:0;border-left-width:0;border-radius:0}.bootstrap-dark .list-group-flush .list-group-item:first-child{border-top-width:0}.bootstrap-dark .list-group-flush:last-child .list-group-item:last-child{border-bottom-width:0}.bootstrap-dark .list-group-item-primary{color:#004085;background-color:#b8daff}.bootstrap-dark .list-group-item-primary.list-group-item-action:focus,.bootstrap-dark .list-group-item-primary.list-group-item-action:hover{color:#004085;background-color:#9fcdff}.bootstrap-dark .list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#004085;border-color:#004085}.bootstrap-dark .list-group-item-secondary{color:#383d41;background-color:#d6d8db}.bootstrap-dark .list-group-item-secondary.list-group-item-action:focus,.bootstrap-dark .list-group-item-secondary.list-group-item-action:hover{color:#383d41;background-color:#c8cbcf}.bootstrap-dark .list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#383d41;border-color:#383d41}.bootstrap-dark .list-group-item-success{color:#155724;background-color:#c3e6cb}.bootstrap-dark .list-group-item-success.list-group-item-action:focus,.bootstrap-dark .list-group-item-success.list-group-item-action:hover{color:#155724;background-color:#b1dfbb}.bootstrap-dark .list-group-item-success.list-group-item-action.active{color:#fff;background-color:#155724;border-color:#155724}.bootstrap-dark .list-group-item-info{color:#0c5460;background-color:#bee5eb}.bootstrap-dark .list-group-item-info.list-group-item-action:focus,.bootstrap-dark .list-group-item-info.list-group-item-action:hover{color:#0c5460;background-color:#abdde5}.bootstrap-dark .list-group-item-info.list-group-item-action.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.bootstrap-dark .list-group-item-warning{color:#856404;background-color:#ffeeba}.bootstrap-dark .list-group-item-warning.list-group-item-action:focus,.bootstrap-dark .list-group-item-warning.list-group-item-action:hover{color:#856404;background-color:#ffe8a1}.bootstrap-dark .list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#856404;border-color:#856404}.bootstrap-dark .list-group-item-danger{color:#721c24;background-color:#f5c6cb}.bootstrap-dark .list-group-item-danger.list-group-item-action:focus,.bootstrap-dark .list-group-item-danger.list-group-item-action:hover{color:#721c24;background-color:#f1b0b7}.bootstrap-dark .list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.bootstrap-dark .list-group-item-light{color:#818182;background-color:#fdfdfe}.bootstrap-dark .list-group-item-light.list-group-item-action:focus,.bootstrap-dark .list-group-item-light.list-group-item-action:hover{color:#818182;background-color:#ececf6}.bootstrap-dark .list-group-item-light.list-group-item-action.active{color:#fff;background-color:#818182;border-color:#818182}.bootstrap-dark .list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}.bootstrap-dark .list-group-item-dark.list-group-item-action:focus,.bootstrap-dark .list-group-item-dark.list-group-item-action:hover{color:#1b1e21;background-color:#b9bbbe}.bootstrap-dark .list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.bootstrap-dark .close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#fff;text-shadow:0 1px 0 #000;opacity:.5}.bootstrap-dark .close:hover{color:#fff;text-decoration:none}.bootstrap-dark .close:not(:disabled):not(.disabled):focus,.bootstrap-dark .close:not(:disabled):not(.disabled):hover{opacity:.75}.bootstrap-dark button.close{padding:0;background-color:transparent;border:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}.bootstrap-dark a.close.disabled{pointer-events:none}.bootstrap-dark .toast{max-width:350px;overflow:hidden;font-size:.875rem;background-color:rgba(255,255,255,.85);-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid rgba(0,0,0,.1);-webkit-box-shadow:0 .25rem .75rem rgba(0,0,0,.1);box-shadow:0 .25rem .75rem rgba(0,0,0,.1);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);opacity:0;border-radius:.25rem}.bootstrap-dark .toast:not(:last-child){margin-bottom:.75rem}.bootstrap-dark .toast.showing{opacity:1}.bootstrap-dark .toast.show{display:block;opacity:1}.bootstrap-dark .toast.hide{display:none}.bootstrap-dark .toast-header{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;padding:.25rem .75rem;color:#6c757d;background-color:rgba(255,255,255,.85);-webkit-background-clip:padding-box;background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05)}.bootstrap-dark .toast-body{padding:.75rem}.bootstrap-dark .modal-open{overflow:hidden}.bootstrap-dark .modal-open .modal{overflow-x:hidden;overflow-y:auto}.bootstrap-dark .modal{position:fixed;top:0;left:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.bootstrap-dark .modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .bootstrap-dark .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out,-o-transform .3s ease-out;-webkit-transform:translate(0,-50px);-o-transform:translate(0,-50px);transform:translate(0,-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .bootstrap-dark .modal-dialog{-webkit-transition:none;-o-transition:none;transition:none}}.modal.show .bootstrap-dark .modal-dialog{-webkit-transform:none;-o-transform:none;transform:none}.modal.modal-static .bootstrap-dark .modal-dialog{-webkit-transform:scale(1.02);-o-transform:scale(1.02);transform:scale(1.02)}.bootstrap-dark .modal-dialog-scrollable{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;max-height:calc(100% - 1rem)}.bootstrap-dark .modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.bootstrap-dark .modal-dialog-scrollable .modal-footer,.bootstrap-dark .modal-dialog-scrollable .modal-header{-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0}.bootstrap-dark .modal-dialog-scrollable .modal-body{overflow-y:auto}.bootstrap-dark .modal-dialog-centered{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;min-height:calc(100% - 1rem)}.bootstrap-dark .modal-dialog-centered::before{display:block;height:calc(100vh - 1rem);content:""}.bootstrap-dark .modal-dialog-centered.modal-dialog-scrollable{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;height:100%}.bootstrap-dark .modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.bootstrap-dark .modal-dialog-centered.modal-dialog-scrollable::before{content:none}.bootstrap-dark .modal-content{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#191d21;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid rgba(255,255,255,.2);border-radius:.3rem;outline:0}.bootstrap-dark .modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.bootstrap-dark .modal-backdrop.fade{opacity:0}.bootstrap-dark .modal-backdrop.show{opacity:.5}.bootstrap-dark .modal-header{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #343a40;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.bootstrap-dark .modal-header .close{padding:1rem 1rem;margin:-1rem -1rem -1rem auto}.bootstrap-dark .modal-title{margin-bottom:0;line-height:1.5}.bootstrap-dark .modal-body{position:relative;-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.bootstrap-dark .modal-footer{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end;padding:.75rem;border-top:1px solid #343a40;border-bottom-right-radius:calc(.3rem - 1px);border-bottom-left-radius:calc(.3rem - 1px)}.bootstrap-dark .modal-footer>*{margin:.25rem}.bootstrap-dark .modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.bootstrap-dark .modal-dialog{max-width:500px;margin:1.75rem auto}.bootstrap-dark .modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.bootstrap-dark .modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.bootstrap-dark .modal-dialog-centered{min-height:calc(100% - 3.5rem)}.bootstrap-dark .modal-dialog-centered::before{height:calc(100vh - 3.5rem)}.bootstrap-dark .modal-sm{max-width:300px}}@media (min-width:992px){.bootstrap-dark .modal-lg,.bootstrap-dark .modal-xl{max-width:800px}}@media (min-width:1200px){.bootstrap-dark .modal-xl{max-width:1140px}}.bootstrap-dark .tooltip{position:absolute;z-index:1070;display:block;margin:0;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";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.bootstrap-dark .tooltip.show{opacity:.9}.bootstrap-dark .tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.bootstrap-dark .tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bootstrap-dark .bs-tooltip-auto[x-placement^=top],.bootstrap-dark .bs-tooltip-top{padding:.4rem 0}.bootstrap-dark .bs-tooltip-auto[x-placement^=top] .arrow,.bootstrap-dark .bs-tooltip-top .arrow{bottom:0}.bootstrap-dark .bs-tooltip-auto[x-placement^=top] .arrow::before,.bootstrap-dark .bs-tooltip-top .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bootstrap-dark .bs-tooltip-auto[x-placement^=right],.bootstrap-dark .bs-tooltip-right{padding:0 .4rem}.bootstrap-dark .bs-tooltip-auto[x-placement^=right] .arrow,.bootstrap-dark .bs-tooltip-right .arrow{left:0;width:.4rem;height:.8rem}.bootstrap-dark .bs-tooltip-auto[x-placement^=right] .arrow::before,.bootstrap-dark .bs-tooltip-right .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bootstrap-dark .bs-tooltip-auto[x-placement^=bottom],.bootstrap-dark .bs-tooltip-bottom{padding:.4rem 0}.bootstrap-dark .bs-tooltip-auto[x-placement^=bottom] .arrow,.bootstrap-dark .bs-tooltip-bottom .arrow{top:0}.bootstrap-dark .bs-tooltip-auto[x-placement^=bottom] .arrow::before,.bootstrap-dark .bs-tooltip-bottom .arrow::before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bootstrap-dark .bs-tooltip-auto[x-placement^=left],.bootstrap-dark .bs-tooltip-left{padding:0 .4rem}.bootstrap-dark .bs-tooltip-auto[x-placement^=left] .arrow,.bootstrap-dark .bs-tooltip-left .arrow{right:0;width:.4rem;height:.8rem}.bootstrap-dark .bs-tooltip-auto[x-placement^=left] .arrow::before,.bootstrap-dark .bs-tooltip-left .arrow::before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.bootstrap-dark .tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.bootstrap-dark .popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;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";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.bootstrap-dark .popover .arrow{position:absolute;display:block;width:1rem;height:.5rem;margin:0 .3rem}.bootstrap-dark .popover .arrow::after,.bootstrap-dark .popover .arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bootstrap-dark .bs-popover-auto[x-placement^=top],.bootstrap-dark .bs-popover-top{margin-bottom:.5rem}.bootstrap-dark .bs-popover-auto[x-placement^=top]>.arrow,.bootstrap-dark .bs-popover-top>.arrow{bottom:calc(-.5rem - 1px)}.bootstrap-dark .bs-popover-auto[x-placement^=top]>.arrow::before,.bootstrap-dark .bs-popover-top>.arrow::before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,.25)}.bootstrap-dark .bs-popover-auto[x-placement^=top]>.arrow::after,.bootstrap-dark .bs-popover-top>.arrow::after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bootstrap-dark .bs-popover-auto[x-placement^=right],.bootstrap-dark .bs-popover-right{margin-left:.5rem}.bootstrap-dark .bs-popover-auto[x-placement^=right]>.arrow,.bootstrap-dark .bs-popover-right>.arrow{left:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bootstrap-dark .bs-popover-auto[x-placement^=right]>.arrow::before,.bootstrap-dark .bs-popover-right>.arrow::before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,.25)}.bootstrap-dark .bs-popover-auto[x-placement^=right]>.arrow::after,.bootstrap-dark .bs-popover-right>.arrow::after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bootstrap-dark .bs-popover-auto[x-placement^=bottom],.bootstrap-dark .bs-popover-bottom{margin-top:.5rem}.bootstrap-dark .bs-popover-auto[x-placement^=bottom]>.arrow,.bootstrap-dark .bs-popover-bottom>.arrow{top:calc(-.5rem - 1px)}.bootstrap-dark .bs-popover-auto[x-placement^=bottom]>.arrow::before,.bootstrap-dark .bs-popover-bottom>.arrow::before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(0,0,0,.25)}.bootstrap-dark .bs-popover-auto[x-placement^=bottom]>.arrow::after,.bootstrap-dark .bs-popover-bottom>.arrow::after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#fff}.bootstrap-dark .bs-popover-auto[x-placement^=bottom] .popover-header::before,.bootstrap-dark .bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.bootstrap-dark .bs-popover-auto[x-placement^=left],.bootstrap-dark .bs-popover-left{margin-right:.5rem}.bootstrap-dark .bs-popover-auto[x-placement^=left]>.arrow,.bootstrap-dark .bs-popover-left>.arrow{right:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bootstrap-dark .bs-popover-auto[x-placement^=left]>.arrow::before,.bootstrap-dark .bs-popover-left>.arrow::before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,.25)}.bootstrap-dark .bs-popover-auto[x-placement^=left]>.arrow::after,.bootstrap-dark .bs-popover-left>.arrow::after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.bootstrap-dark .popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.bootstrap-dark .popover-header:empty{display:none}.bootstrap-dark .popover-body{padding:.5rem .75rem;color:#212529}.bootstrap-dark .carousel{position:relative}.bootstrap-dark .carousel.pointer-event{-ms-touch-action:pan-y;touch-action:pan-y}.bootstrap-dark .carousel-inner{position:relative;width:100%;overflow:hidden}.bootstrap-dark .carousel-inner::after{display:block;clear:both;content:""}.bootstrap-dark .carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transition:-webkit-transform .6s ease-in-out;transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out,-o-transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.bootstrap-dark .carousel-item{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap-dark .carousel-item-next,.bootstrap-dark .carousel-item-prev,.bootstrap-dark .carousel-item.active{display:block}.bootstrap-dark .active.carousel-item-right,.bootstrap-dark .carousel-item-next:not(.carousel-item-left){-webkit-transform:translateX(100%);-o-transform:translateX(100%);transform:translateX(100%)}.bootstrap-dark .active.carousel-item-left,.bootstrap-dark .carousel-item-prev:not(.carousel-item-right){-webkit-transform:translateX(-100%);-o-transform:translateX(-100%);transform:translateX(-100%)}.bootstrap-dark .carousel-fade .carousel-item{opacity:0;-webkit-transition-property:opacity;-o-transition-property:opacity;transition-property:opacity;-webkit-transform:none;-o-transform:none;transform:none}.bootstrap-dark .carousel-fade .carousel-item-next.carousel-item-left,.bootstrap-dark .carousel-fade .carousel-item-prev.carousel-item-right,.bootstrap-dark .carousel-fade .carousel-item.active{z-index:1;opacity:1}.bootstrap-dark .carousel-fade .active.carousel-item-left,.bootstrap-dark .carousel-fade .active.carousel-item-right{z-index:0;opacity:0;-webkit-transition:opacity 0s .6s;-o-transition:opacity 0s .6s;transition:opacity 0s .6s}@media (prefers-reduced-motion:reduce){.bootstrap-dark .carousel-fade .active.carousel-item-left,.bootstrap-dark .carousel-fade .active.carousel-item-right{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap-dark .carousel-control-next,.bootstrap-dark .carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5;-webkit-transition:opacity .15s ease;-o-transition:opacity .15s ease;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.bootstrap-dark .carousel-control-next,.bootstrap-dark .carousel-control-prev{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap-dark .carousel-control-next:focus,.bootstrap-dark .carousel-control-next:hover,.bootstrap-dark .carousel-control-prev:focus,.bootstrap-dark .carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.bootstrap-dark .carousel-control-prev{left:0}.bootstrap-dark .carousel-control-next{right:0}.bootstrap-dark .carousel-control-next-icon,.bootstrap-dark .carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:no-repeat 50%/100% 100%}.bootstrap-dark .carousel-control-prev-icon{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")}.bootstrap-dark .carousel-control-next-icon{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")}.bootstrap-dark .carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:15;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.bootstrap-dark .carousel-indicators li{-webkit-box-sizing:content-box;box-sizing:content-box;-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;-webkit-transition:opacity .6s ease;-o-transition:opacity .6s ease;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.bootstrap-dark .carousel-indicators li{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap-dark .carousel-indicators .active{opacity:1}.bootstrap-dark .carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}@-webkit-keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-o-keyframes spinner-border{to{-o-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes spinner-border{to{-webkit-transform:rotate(360deg);-o-transform:rotate(360deg);transform:rotate(360deg)}}.bootstrap-dark .spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;border:.25em solid currentColor;border-right-color:transparent;border-radius:50%;-webkit-animation:spinner-border .75s linear infinite;-o-animation:spinner-border .75s linear infinite;animation:spinner-border .75s linear infinite}.bootstrap-dark .spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@-webkit-keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1}}@-o-keyframes spinner-grow{0%{-o-transform:scale(0);transform:scale(0)}50%{opacity:1}}@keyframes spinner-grow{0%{-webkit-transform:scale(0);-o-transform:scale(0);transform:scale(0)}50%{opacity:1}}.bootstrap-dark .spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;background-color:currentColor;border-radius:50%;opacity:0;-webkit-animation:spinner-grow .75s linear infinite;-o-animation:spinner-grow .75s linear infinite;animation:spinner-grow .75s linear infinite}.bootstrap-dark .spinner-grow-sm{width:1rem;height:1rem}.bootstrap-dark .align-baseline{vertical-align:baseline!important}.bootstrap-dark .align-top{vertical-align:top!important}.bootstrap-dark .align-middle{vertical-align:middle!important}.bootstrap-dark .align-bottom{vertical-align:bottom!important}.bootstrap-dark .align-text-bottom{vertical-align:text-bottom!important}.bootstrap-dark .align-text-top{vertical-align:text-top!important}.bootstrap-dark .bg-primary{background-color:#007bff!important}.bootstrap-dark a.bg-primary:focus,.bootstrap-dark a.bg-primary:hover,.bootstrap-dark button.bg-primary:focus,.bootstrap-dark button.bg-primary:hover{background-color:#0062cc!important}.bootstrap-dark .bg-secondary{background-color:#6c757d!important}.bootstrap-dark a.bg-secondary:focus,.bootstrap-dark a.bg-secondary:hover,.bootstrap-dark button.bg-secondary:focus,.bootstrap-dark button.bg-secondary:hover{background-color:#545b62!important}.bootstrap-dark .bg-success{background-color:#28a745!important}.bootstrap-dark a.bg-success:focus,.bootstrap-dark a.bg-success:hover,.bootstrap-dark button.bg-success:focus,.bootstrap-dark button.bg-success:hover{background-color:#1e7e34!important}.bootstrap-dark .bg-info{background-color:#17a2b8!important}.bootstrap-dark a.bg-info:focus,.bootstrap-dark a.bg-info:hover,.bootstrap-dark button.bg-info:focus,.bootstrap-dark button.bg-info:hover{background-color:#117a8b!important}.bootstrap-dark .bg-warning{background-color:#ffc107!important}.bootstrap-dark a.bg-warning:focus,.bootstrap-dark a.bg-warning:hover,.bootstrap-dark button.bg-warning:focus,.bootstrap-dark button.bg-warning:hover{background-color:#d39e00!important}.bootstrap-dark .bg-danger{background-color:#dc3545!important}.bootstrap-dark a.bg-danger:focus,.bootstrap-dark a.bg-danger:hover,.bootstrap-dark button.bg-danger:focus,.bootstrap-dark button.bg-danger:hover{background-color:#bd2130!important}.bootstrap-dark .bg-light{background-color:#f8f9fa!important}.bootstrap-dark a.bg-light:focus,.bootstrap-dark a.bg-light:hover,.bootstrap-dark button.bg-light:focus,.bootstrap-dark button.bg-light:hover{background-color:#dae0e5!important}.bootstrap-dark .bg-dark{background-color:#343a40!important}.bootstrap-dark a.bg-dark:focus,.bootstrap-dark a.bg-dark:hover,.bootstrap-dark button.bg-dark:focus,.bootstrap-dark button.bg-dark:hover{background-color:#1d2124!important}.bootstrap-dark .bg-white{background-color:#fff!important}.bootstrap-dark .bg-transparent{background-color:transparent!important}.bootstrap-dark .border{border:1px solid #dee2e6!important}.bootstrap-dark .border-top{border-top:1px solid #dee2e6!important}.bootstrap-dark .border-right{border-right:1px solid #dee2e6!important}.bootstrap-dark .border-bottom{border-bottom:1px solid #dee2e6!important}.bootstrap-dark .border-left{border-left:1px solid #dee2e6!important}.bootstrap-dark .border-0{border:0!important}.bootstrap-dark .border-top-0{border-top:0!important}.bootstrap-dark .border-right-0{border-right:0!important}.bootstrap-dark .border-bottom-0{border-bottom:0!important}.bootstrap-dark .border-left-0{border-left:0!important}.bootstrap-dark .border-primary{border-color:#007bff!important}.bootstrap-dark .border-secondary{border-color:#6c757d!important}.bootstrap-dark .border-success{border-color:#28a745!important}.bootstrap-dark .border-info{border-color:#17a2b8!important}.bootstrap-dark .border-warning{border-color:#ffc107!important}.bootstrap-dark .border-danger{border-color:#dc3545!important}.bootstrap-dark .border-light{border-color:#f8f9fa!important}.bootstrap-dark .border-dark{border-color:#343a40!important}.bootstrap-dark .border-white{border-color:#fff!important}.bootstrap-dark .rounded-sm{border-radius:.2rem!important}.bootstrap-dark .rounded{border-radius:.25rem!important}.bootstrap-dark .rounded-top{border-top-left-radius:.25rem!important;border-top-right-radius:.25rem!important}.bootstrap-dark .rounded-right{border-top-right-radius:.25rem!important;border-bottom-right-radius:.25rem!important}.bootstrap-dark .rounded-bottom{border-bottom-right-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.bootstrap-dark .rounded-left{border-top-left-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.bootstrap-dark .rounded-lg{border-radius:.3rem!important}.bootstrap-dark .rounded-circle{border-radius:50%!important}.bootstrap-dark .rounded-pill{border-radius:50rem!important}.bootstrap-dark .rounded-0{border-radius:0!important}.bootstrap-dark .clearfix::after{display:block;clear:both;content:""}.bootstrap-dark .d-none{display:none!important}.bootstrap-dark .d-inline{display:inline!important}.bootstrap-dark .d-inline-block{display:inline-block!important}.bootstrap-dark .d-block{display:block!important}.bootstrap-dark .d-table{display:table!important}.bootstrap-dark .d-table-row{display:table-row!important}.bootstrap-dark .d-table-cell{display:table-cell!important}.bootstrap-dark .d-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.bootstrap-dark .d-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.bootstrap-dark .d-sm-none{display:none!important}.bootstrap-dark .d-sm-inline{display:inline!important}.bootstrap-dark .d-sm-inline-block{display:inline-block!important}.bootstrap-dark .d-sm-block{display:block!important}.bootstrap-dark .d-sm-table{display:table!important}.bootstrap-dark .d-sm-table-row{display:table-row!important}.bootstrap-dark .d-sm-table-cell{display:table-cell!important}.bootstrap-dark .d-sm-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.bootstrap-dark .d-sm-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.bootstrap-dark .d-md-none{display:none!important}.bootstrap-dark .d-md-inline{display:inline!important}.bootstrap-dark .d-md-inline-block{display:inline-block!important}.bootstrap-dark .d-md-block{display:block!important}.bootstrap-dark .d-md-table{display:table!important}.bootstrap-dark .d-md-table-row{display:table-row!important}.bootstrap-dark .d-md-table-cell{display:table-cell!important}.bootstrap-dark .d-md-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.bootstrap-dark .d-md-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.bootstrap-dark .d-lg-none{display:none!important}.bootstrap-dark .d-lg-inline{display:inline!important}.bootstrap-dark .d-lg-inline-block{display:inline-block!important}.bootstrap-dark .d-lg-block{display:block!important}.bootstrap-dark .d-lg-table{display:table!important}.bootstrap-dark .d-lg-table-row{display:table-row!important}.bootstrap-dark .d-lg-table-cell{display:table-cell!important}.bootstrap-dark .d-lg-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.bootstrap-dark .d-lg-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.bootstrap-dark .d-xl-none{display:none!important}.bootstrap-dark .d-xl-inline{display:inline!important}.bootstrap-dark .d-xl-inline-block{display:inline-block!important}.bootstrap-dark .d-xl-block{display:block!important}.bootstrap-dark .d-xl-table{display:table!important}.bootstrap-dark .d-xl-table-row{display:table-row!important}.bootstrap-dark .d-xl-table-cell{display:table-cell!important}.bootstrap-dark .d-xl-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.bootstrap-dark .d-xl-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.bootstrap-dark .d-print-none{display:none!important}.bootstrap-dark .d-print-inline{display:inline!important}.bootstrap-dark .d-print-inline-block{display:inline-block!important}.bootstrap-dark .d-print-block{display:block!important}.bootstrap-dark .d-print-table{display:table!important}.bootstrap-dark .d-print-table-row{display:table-row!important}.bootstrap-dark .d-print-table-cell{display:table-cell!important}.bootstrap-dark .d-print-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.bootstrap-dark .d-print-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}.bootstrap-dark .embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.bootstrap-dark .embed-responsive::before{display:block;content:""}.bootstrap-dark .embed-responsive .embed-responsive-item,.bootstrap-dark .embed-responsive embed,.bootstrap-dark .embed-responsive iframe,.bootstrap-dark .embed-responsive object,.bootstrap-dark .embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.bootstrap-dark .embed-responsive-21by9::before{padding-top:42.85714%}.bootstrap-dark .embed-responsive-16by9::before{padding-top:56.25%}.bootstrap-dark .embed-responsive-4by3::before{padding-top:75%}.bootstrap-dark .embed-responsive-1by1::before{padding-top:100%}.bootstrap-dark .flex-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.bootstrap-dark .flex-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.bootstrap-dark .flex-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.bootstrap-dark .flex-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.bootstrap-dark .flex-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.bootstrap-dark .flex-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.bootstrap-dark .flex-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.bootstrap-dark .flex-fill{-webkit-box-flex:1!important;-webkit-flex:1 1 auto!important;-ms-flex:1 1 auto!important;flex:1 1 auto!important}.bootstrap-dark .flex-grow-0{-webkit-box-flex:0!important;-webkit-flex-grow:0!important;-ms-flex-positive:0!important;flex-grow:0!important}.bootstrap-dark .flex-grow-1{-webkit-box-flex:1!important;-webkit-flex-grow:1!important;-ms-flex-positive:1!important;flex-grow:1!important}.bootstrap-dark .flex-shrink-0{-webkit-flex-shrink:0!important;-ms-flex-negative:0!important;flex-shrink:0!important}.bootstrap-dark .flex-shrink-1{-webkit-flex-shrink:1!important;-ms-flex-negative:1!important;flex-shrink:1!important}.bootstrap-dark .justify-content-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.bootstrap-dark .justify-content-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.bootstrap-dark .justify-content-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.bootstrap-dark .justify-content-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.bootstrap-dark .justify-content-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.bootstrap-dark .align-items-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.bootstrap-dark .align-items-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.bootstrap-dark .align-items-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.bootstrap-dark .align-items-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.bootstrap-dark .align-items-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.bootstrap-dark .align-content-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.bootstrap-dark .align-content-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.bootstrap-dark .align-content-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.bootstrap-dark .align-content-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.bootstrap-dark .align-content-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.bootstrap-dark .align-content-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.bootstrap-dark .align-self-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;align-self:auto!important}.bootstrap-dark .align-self-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.bootstrap-dark .align-self-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.bootstrap-dark .align-self-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;align-self:center!important}.bootstrap-dark .align-self-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.bootstrap-dark .align-self-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.bootstrap-dark .flex-sm-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.bootstrap-dark .flex-sm-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.bootstrap-dark .flex-sm-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.bootstrap-dark .flex-sm-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.bootstrap-dark .flex-sm-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.bootstrap-dark .flex-sm-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.bootstrap-dark .flex-sm-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.bootstrap-dark .flex-sm-fill{-webkit-box-flex:1!important;-webkit-flex:1 1 auto!important;-ms-flex:1 1 auto!important;flex:1 1 auto!important}.bootstrap-dark .flex-sm-grow-0{-webkit-box-flex:0!important;-webkit-flex-grow:0!important;-ms-flex-positive:0!important;flex-grow:0!important}.bootstrap-dark .flex-sm-grow-1{-webkit-box-flex:1!important;-webkit-flex-grow:1!important;-ms-flex-positive:1!important;flex-grow:1!important}.bootstrap-dark .flex-sm-shrink-0{-webkit-flex-shrink:0!important;-ms-flex-negative:0!important;flex-shrink:0!important}.bootstrap-dark .flex-sm-shrink-1{-webkit-flex-shrink:1!important;-ms-flex-negative:1!important;flex-shrink:1!important}.bootstrap-dark .justify-content-sm-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.bootstrap-dark .justify-content-sm-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.bootstrap-dark .justify-content-sm-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.bootstrap-dark .justify-content-sm-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.bootstrap-dark .justify-content-sm-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.bootstrap-dark .align-items-sm-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.bootstrap-dark .align-items-sm-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.bootstrap-dark .align-items-sm-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.bootstrap-dark .align-items-sm-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.bootstrap-dark .align-items-sm-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.bootstrap-dark .align-content-sm-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.bootstrap-dark .align-content-sm-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.bootstrap-dark .align-content-sm-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.bootstrap-dark .align-content-sm-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.bootstrap-dark .align-content-sm-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.bootstrap-dark .align-content-sm-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.bootstrap-dark .align-self-sm-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;align-self:auto!important}.bootstrap-dark .align-self-sm-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.bootstrap-dark .align-self-sm-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.bootstrap-dark .align-self-sm-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;align-self:center!important}.bootstrap-dark .align-self-sm-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.bootstrap-dark .align-self-sm-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.bootstrap-dark .flex-md-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.bootstrap-dark .flex-md-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.bootstrap-dark .flex-md-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.bootstrap-dark .flex-md-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.bootstrap-dark .flex-md-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.bootstrap-dark .flex-md-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.bootstrap-dark .flex-md-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.bootstrap-dark .flex-md-fill{-webkit-box-flex:1!important;-webkit-flex:1 1 auto!important;-ms-flex:1 1 auto!important;flex:1 1 auto!important}.bootstrap-dark .flex-md-grow-0{-webkit-box-flex:0!important;-webkit-flex-grow:0!important;-ms-flex-positive:0!important;flex-grow:0!important}.bootstrap-dark .flex-md-grow-1{-webkit-box-flex:1!important;-webkit-flex-grow:1!important;-ms-flex-positive:1!important;flex-grow:1!important}.bootstrap-dark .flex-md-shrink-0{-webkit-flex-shrink:0!important;-ms-flex-negative:0!important;flex-shrink:0!important}.bootstrap-dark .flex-md-shrink-1{-webkit-flex-shrink:1!important;-ms-flex-negative:1!important;flex-shrink:1!important}.bootstrap-dark .justify-content-md-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.bootstrap-dark .justify-content-md-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.bootstrap-dark .justify-content-md-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.bootstrap-dark .justify-content-md-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.bootstrap-dark .justify-content-md-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.bootstrap-dark .align-items-md-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.bootstrap-dark .align-items-md-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.bootstrap-dark .align-items-md-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.bootstrap-dark .align-items-md-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.bootstrap-dark .align-items-md-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.bootstrap-dark .align-content-md-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.bootstrap-dark .align-content-md-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.bootstrap-dark .align-content-md-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.bootstrap-dark .align-content-md-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.bootstrap-dark .align-content-md-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.bootstrap-dark .align-content-md-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.bootstrap-dark .align-self-md-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;align-self:auto!important}.bootstrap-dark .align-self-md-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.bootstrap-dark .align-self-md-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.bootstrap-dark .align-self-md-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;align-self:center!important}.bootstrap-dark .align-self-md-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.bootstrap-dark .align-self-md-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.bootstrap-dark .flex-lg-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.bootstrap-dark .flex-lg-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.bootstrap-dark .flex-lg-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.bootstrap-dark .flex-lg-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.bootstrap-dark .flex-lg-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.bootstrap-dark .flex-lg-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.bootstrap-dark .flex-lg-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.bootstrap-dark .flex-lg-fill{-webkit-box-flex:1!important;-webkit-flex:1 1 auto!important;-ms-flex:1 1 auto!important;flex:1 1 auto!important}.bootstrap-dark .flex-lg-grow-0{-webkit-box-flex:0!important;-webkit-flex-grow:0!important;-ms-flex-positive:0!important;flex-grow:0!important}.bootstrap-dark .flex-lg-grow-1{-webkit-box-flex:1!important;-webkit-flex-grow:1!important;-ms-flex-positive:1!important;flex-grow:1!important}.bootstrap-dark .flex-lg-shrink-0{-webkit-flex-shrink:0!important;-ms-flex-negative:0!important;flex-shrink:0!important}.bootstrap-dark .flex-lg-shrink-1{-webkit-flex-shrink:1!important;-ms-flex-negative:1!important;flex-shrink:1!important}.bootstrap-dark .justify-content-lg-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.bootstrap-dark .justify-content-lg-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.bootstrap-dark .justify-content-lg-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.bootstrap-dark .justify-content-lg-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.bootstrap-dark .justify-content-lg-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.bootstrap-dark .align-items-lg-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.bootstrap-dark .align-items-lg-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.bootstrap-dark .align-items-lg-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.bootstrap-dark .align-items-lg-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.bootstrap-dark .align-items-lg-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.bootstrap-dark .align-content-lg-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.bootstrap-dark .align-content-lg-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.bootstrap-dark .align-content-lg-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.bootstrap-dark .align-content-lg-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.bootstrap-dark .align-content-lg-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.bootstrap-dark .align-content-lg-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.bootstrap-dark .align-self-lg-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;align-self:auto!important}.bootstrap-dark .align-self-lg-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.bootstrap-dark .align-self-lg-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.bootstrap-dark .align-self-lg-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;align-self:center!important}.bootstrap-dark .align-self-lg-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.bootstrap-dark .align-self-lg-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.bootstrap-dark .flex-xl-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.bootstrap-dark .flex-xl-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.bootstrap-dark .flex-xl-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.bootstrap-dark .flex-xl-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.bootstrap-dark .flex-xl-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.bootstrap-dark .flex-xl-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.bootstrap-dark .flex-xl-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.bootstrap-dark .flex-xl-fill{-webkit-box-flex:1!important;-webkit-flex:1 1 auto!important;-ms-flex:1 1 auto!important;flex:1 1 auto!important}.bootstrap-dark .flex-xl-grow-0{-webkit-box-flex:0!important;-webkit-flex-grow:0!important;-ms-flex-positive:0!important;flex-grow:0!important}.bootstrap-dark .flex-xl-grow-1{-webkit-box-flex:1!important;-webkit-flex-grow:1!important;-ms-flex-positive:1!important;flex-grow:1!important}.bootstrap-dark .flex-xl-shrink-0{-webkit-flex-shrink:0!important;-ms-flex-negative:0!important;flex-shrink:0!important}.bootstrap-dark .flex-xl-shrink-1{-webkit-flex-shrink:1!important;-ms-flex-negative:1!important;flex-shrink:1!important}.bootstrap-dark .justify-content-xl-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.bootstrap-dark .justify-content-xl-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.bootstrap-dark .justify-content-xl-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.bootstrap-dark .justify-content-xl-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.bootstrap-dark .justify-content-xl-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.bootstrap-dark .align-items-xl-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.bootstrap-dark .align-items-xl-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.bootstrap-dark .align-items-xl-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.bootstrap-dark .align-items-xl-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.bootstrap-dark .align-items-xl-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.bootstrap-dark .align-content-xl-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.bootstrap-dark .align-content-xl-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.bootstrap-dark .align-content-xl-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.bootstrap-dark .align-content-xl-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.bootstrap-dark .align-content-xl-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.bootstrap-dark .align-content-xl-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.bootstrap-dark .align-self-xl-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;align-self:auto!important}.bootstrap-dark .align-self-xl-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.bootstrap-dark .align-self-xl-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.bootstrap-dark .align-self-xl-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;align-self:center!important}.bootstrap-dark .align-self-xl-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.bootstrap-dark .align-self-xl-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;align-self:stretch!important}}.bootstrap-dark .float-left{float:left!important}.bootstrap-dark .float-right{float:right!important}.bootstrap-dark .float-none{float:none!important}@media (min-width:576px){.bootstrap-dark .float-sm-left{float:left!important}.bootstrap-dark .float-sm-right{float:right!important}.bootstrap-dark .float-sm-none{float:none!important}}@media (min-width:768px){.bootstrap-dark .float-md-left{float:left!important}.bootstrap-dark .float-md-right{float:right!important}.bootstrap-dark .float-md-none{float:none!important}}@media (min-width:992px){.bootstrap-dark .float-lg-left{float:left!important}.bootstrap-dark .float-lg-right{float:right!important}.bootstrap-dark .float-lg-none{float:none!important}}@media (min-width:1200px){.bootstrap-dark .float-xl-left{float:left!important}.bootstrap-dark .float-xl-right{float:right!important}.bootstrap-dark .float-xl-none{float:none!important}}.bootstrap-dark .overflow-auto{overflow:auto!important}.bootstrap-dark .overflow-hidden{overflow:hidden!important}.bootstrap-dark .position-static{position:static!important}.bootstrap-dark .position-relative{position:relative!important}.bootstrap-dark .position-absolute{position:absolute!important}.bootstrap-dark .position-fixed{position:fixed!important}.bootstrap-dark .position-sticky{position:-webkit-sticky!important;position:sticky!important}.bootstrap-dark .fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.bootstrap-dark .fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports ((position:-webkit-sticky) or (position:sticky)){.bootstrap-dark .sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.bootstrap-dark .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.bootstrap-dark .sr-only-focusable:active,.bootstrap-dark .sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.bootstrap-dark .shadow-sm{-webkit-box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important;box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.bootstrap-dark .shadow{-webkit-box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important;box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.bootstrap-dark .shadow-lg{-webkit-box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important;box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.bootstrap-dark .shadow-none{-webkit-box-shadow:none!important;box-shadow:none!important}.bootstrap-dark .w-25{width:25%!important}.bootstrap-dark .w-50{width:50%!important}.bootstrap-dark .w-75{width:75%!important}.bootstrap-dark .w-100{width:100%!important}.bootstrap-dark .w-auto{width:auto!important}.bootstrap-dark .h-25{height:25%!important}.bootstrap-dark .h-50{height:50%!important}.bootstrap-dark .h-75{height:75%!important}.bootstrap-dark .h-100{height:100%!important}.bootstrap-dark .h-auto{height:auto!important}.bootstrap-dark .mw-100{max-width:100%!important}.bootstrap-dark .mh-100{max-height:100%!important}.bootstrap-dark .min-vw-100{min-width:100vw!important}.bootstrap-dark .min-vh-100{min-height:100vh!important}.bootstrap-dark .vw-100{width:100vw!important}.bootstrap-dark .vh-100{height:100vh!important}.bootstrap-dark .stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;pointer-events:auto;content:"";background-color:rgba(0,0,0,0)}.bootstrap-dark .m-0{margin:0!important}.bootstrap-dark .mt-0,.bootstrap-dark .my-0{margin-top:0!important}.bootstrap-dark .mr-0,.bootstrap-dark .mx-0{margin-right:0!important}.bootstrap-dark .mb-0,.bootstrap-dark .my-0{margin-bottom:0!important}.bootstrap-dark .ml-0,.bootstrap-dark .mx-0{margin-left:0!important}.bootstrap-dark .m-1{margin:.25rem!important}.bootstrap-dark .mt-1,.bootstrap-dark .my-1{margin-top:.25rem!important}.bootstrap-dark .mr-1,.bootstrap-dark .mx-1{margin-right:.25rem!important}.bootstrap-dark .mb-1,.bootstrap-dark .my-1{margin-bottom:.25rem!important}.bootstrap-dark .ml-1,.bootstrap-dark .mx-1{margin-left:.25rem!important}.bootstrap-dark .m-2{margin:.5rem!important}.bootstrap-dark .mt-2,.bootstrap-dark .my-2{margin-top:.5rem!important}.bootstrap-dark .mr-2,.bootstrap-dark .mx-2{margin-right:.5rem!important}.bootstrap-dark .mb-2,.bootstrap-dark .my-2{margin-bottom:.5rem!important}.bootstrap-dark .ml-2,.bootstrap-dark .mx-2{margin-left:.5rem!important}.bootstrap-dark .m-3{margin:1rem!important}.bootstrap-dark .mt-3,.bootstrap-dark .my-3{margin-top:1rem!important}.bootstrap-dark .mr-3,.bootstrap-dark .mx-3{margin-right:1rem!important}.bootstrap-dark .mb-3,.bootstrap-dark .my-3{margin-bottom:1rem!important}.bootstrap-dark .ml-3,.bootstrap-dark .mx-3{margin-left:1rem!important}.bootstrap-dark .m-4{margin:1.5rem!important}.bootstrap-dark .mt-4,.bootstrap-dark .my-4{margin-top:1.5rem!important}.bootstrap-dark .mr-4,.bootstrap-dark .mx-4{margin-right:1.5rem!important}.bootstrap-dark .mb-4,.bootstrap-dark .my-4{margin-bottom:1.5rem!important}.bootstrap-dark .ml-4,.bootstrap-dark .mx-4{margin-left:1.5rem!important}.bootstrap-dark .m-5{margin:3rem!important}.bootstrap-dark .mt-5,.bootstrap-dark .my-5{margin-top:3rem!important}.bootstrap-dark .mr-5,.bootstrap-dark .mx-5{margin-right:3rem!important}.bootstrap-dark .mb-5,.bootstrap-dark .my-5{margin-bottom:3rem!important}.bootstrap-dark .ml-5,.bootstrap-dark .mx-5{margin-left:3rem!important}.bootstrap-dark .p-0{padding:0!important}.bootstrap-dark .pt-0,.bootstrap-dark .py-0{padding-top:0!important}.bootstrap-dark .pr-0,.bootstrap-dark .px-0{padding-right:0!important}.bootstrap-dark .pb-0,.bootstrap-dark .py-0{padding-bottom:0!important}.bootstrap-dark .pl-0,.bootstrap-dark .px-0{padding-left:0!important}.bootstrap-dark .p-1{padding:.25rem!important}.bootstrap-dark .pt-1,.bootstrap-dark .py-1{padding-top:.25rem!important}.bootstrap-dark .pr-1,.bootstrap-dark .px-1{padding-right:.25rem!important}.bootstrap-dark .pb-1,.bootstrap-dark .py-1{padding-bottom:.25rem!important}.bootstrap-dark .pl-1,.bootstrap-dark .px-1{padding-left:.25rem!important}.bootstrap-dark .p-2{padding:.5rem!important}.bootstrap-dark .pt-2,.bootstrap-dark .py-2{padding-top:.5rem!important}.bootstrap-dark .pr-2,.bootstrap-dark .px-2{padding-right:.5rem!important}.bootstrap-dark .pb-2,.bootstrap-dark .py-2{padding-bottom:.5rem!important}.bootstrap-dark .pl-2,.bootstrap-dark .px-2{padding-left:.5rem!important}.bootstrap-dark .p-3{padding:1rem!important}.bootstrap-dark .pt-3,.bootstrap-dark .py-3{padding-top:1rem!important}.bootstrap-dark .pr-3,.bootstrap-dark .px-3{padding-right:1rem!important}.bootstrap-dark .pb-3,.bootstrap-dark .py-3{padding-bottom:1rem!important}.bootstrap-dark .pl-3,.bootstrap-dark .px-3{padding-left:1rem!important}.bootstrap-dark .p-4{padding:1.5rem!important}.bootstrap-dark .pt-4,.bootstrap-dark .py-4{padding-top:1.5rem!important}.bootstrap-dark .pr-4,.bootstrap-dark .px-4{padding-right:1.5rem!important}.bootstrap-dark .pb-4,.bootstrap-dark .py-4{padding-bottom:1.5rem!important}.bootstrap-dark .pl-4,.bootstrap-dark .px-4{padding-left:1.5rem!important}.bootstrap-dark .p-5{padding:3rem!important}.bootstrap-dark .pt-5,.bootstrap-dark .py-5{padding-top:3rem!important}.bootstrap-dark .pr-5,.bootstrap-dark .px-5{padding-right:3rem!important}.bootstrap-dark .pb-5,.bootstrap-dark .py-5{padding-bottom:3rem!important}.bootstrap-dark .pl-5,.bootstrap-dark .px-5{padding-left:3rem!important}.bootstrap-dark .m-n1{margin:-.25rem!important}.bootstrap-dark .mt-n1,.bootstrap-dark .my-n1{margin-top:-.25rem!important}.bootstrap-dark .mr-n1,.bootstrap-dark .mx-n1{margin-right:-.25rem!important}.bootstrap-dark .mb-n1,.bootstrap-dark .my-n1{margin-bottom:-.25rem!important}.bootstrap-dark .ml-n1,.bootstrap-dark .mx-n1{margin-left:-.25rem!important}.bootstrap-dark .m-n2{margin:-.5rem!important}.bootstrap-dark .mt-n2,.bootstrap-dark .my-n2{margin-top:-.5rem!important}.bootstrap-dark .mr-n2,.bootstrap-dark .mx-n2{margin-right:-.5rem!important}.bootstrap-dark .mb-n2,.bootstrap-dark .my-n2{margin-bottom:-.5rem!important}.bootstrap-dark .ml-n2,.bootstrap-dark .mx-n2{margin-left:-.5rem!important}.bootstrap-dark .m-n3{margin:-1rem!important}.bootstrap-dark .mt-n3,.bootstrap-dark .my-n3{margin-top:-1rem!important}.bootstrap-dark .mr-n3,.bootstrap-dark .mx-n3{margin-right:-1rem!important}.bootstrap-dark .mb-n3,.bootstrap-dark .my-n3{margin-bottom:-1rem!important}.bootstrap-dark .ml-n3,.bootstrap-dark .mx-n3{margin-left:-1rem!important}.bootstrap-dark .m-n4{margin:-1.5rem!important}.bootstrap-dark .mt-n4,.bootstrap-dark .my-n4{margin-top:-1.5rem!important}.bootstrap-dark .mr-n4,.bootstrap-dark .mx-n4{margin-right:-1.5rem!important}.bootstrap-dark .mb-n4,.bootstrap-dark .my-n4{margin-bottom:-1.5rem!important}.bootstrap-dark .ml-n4,.bootstrap-dark .mx-n4{margin-left:-1.5rem!important}.bootstrap-dark .m-n5{margin:-3rem!important}.bootstrap-dark .mt-n5,.bootstrap-dark .my-n5{margin-top:-3rem!important}.bootstrap-dark .mr-n5,.bootstrap-dark .mx-n5{margin-right:-3rem!important}.bootstrap-dark .mb-n5,.bootstrap-dark .my-n5{margin-bottom:-3rem!important}.bootstrap-dark .ml-n5,.bootstrap-dark .mx-n5{margin-left:-3rem!important}.bootstrap-dark .m-auto{margin:auto!important}.bootstrap-dark .mt-auto,.bootstrap-dark .my-auto{margin-top:auto!important}.bootstrap-dark .mr-auto,.bootstrap-dark .mx-auto{margin-right:auto!important}.bootstrap-dark .mb-auto,.bootstrap-dark .my-auto{margin-bottom:auto!important}.bootstrap-dark .ml-auto,.bootstrap-dark .mx-auto{margin-left:auto!important}@media (min-width:576px){.bootstrap-dark .m-sm-0{margin:0!important}.bootstrap-dark .mt-sm-0,.bootstrap-dark .my-sm-0{margin-top:0!important}.bootstrap-dark .mr-sm-0,.bootstrap-dark .mx-sm-0{margin-right:0!important}.bootstrap-dark .mb-sm-0,.bootstrap-dark .my-sm-0{margin-bottom:0!important}.bootstrap-dark .ml-sm-0,.bootstrap-dark .mx-sm-0{margin-left:0!important}.bootstrap-dark .m-sm-1{margin:.25rem!important}.bootstrap-dark .mt-sm-1,.bootstrap-dark .my-sm-1{margin-top:.25rem!important}.bootstrap-dark .mr-sm-1,.bootstrap-dark .mx-sm-1{margin-right:.25rem!important}.bootstrap-dark .mb-sm-1,.bootstrap-dark .my-sm-1{margin-bottom:.25rem!important}.bootstrap-dark .ml-sm-1,.bootstrap-dark .mx-sm-1{margin-left:.25rem!important}.bootstrap-dark .m-sm-2{margin:.5rem!important}.bootstrap-dark .mt-sm-2,.bootstrap-dark .my-sm-2{margin-top:.5rem!important}.bootstrap-dark .mr-sm-2,.bootstrap-dark .mx-sm-2{margin-right:.5rem!important}.bootstrap-dark .mb-sm-2,.bootstrap-dark .my-sm-2{margin-bottom:.5rem!important}.bootstrap-dark .ml-sm-2,.bootstrap-dark .mx-sm-2{margin-left:.5rem!important}.bootstrap-dark .m-sm-3{margin:1rem!important}.bootstrap-dark .mt-sm-3,.bootstrap-dark .my-sm-3{margin-top:1rem!important}.bootstrap-dark .mr-sm-3,.bootstrap-dark .mx-sm-3{margin-right:1rem!important}.bootstrap-dark .mb-sm-3,.bootstrap-dark .my-sm-3{margin-bottom:1rem!important}.bootstrap-dark .ml-sm-3,.bootstrap-dark .mx-sm-3{margin-left:1rem!important}.bootstrap-dark .m-sm-4{margin:1.5rem!important}.bootstrap-dark .mt-sm-4,.bootstrap-dark .my-sm-4{margin-top:1.5rem!important}.bootstrap-dark .mr-sm-4,.bootstrap-dark .mx-sm-4{margin-right:1.5rem!important}.bootstrap-dark .mb-sm-4,.bootstrap-dark .my-sm-4{margin-bottom:1.5rem!important}.bootstrap-dark .ml-sm-4,.bootstrap-dark .mx-sm-4{margin-left:1.5rem!important}.bootstrap-dark .m-sm-5{margin:3rem!important}.bootstrap-dark .mt-sm-5,.bootstrap-dark .my-sm-5{margin-top:3rem!important}.bootstrap-dark .mr-sm-5,.bootstrap-dark .mx-sm-5{margin-right:3rem!important}.bootstrap-dark .mb-sm-5,.bootstrap-dark .my-sm-5{margin-bottom:3rem!important}.bootstrap-dark .ml-sm-5,.bootstrap-dark .mx-sm-5{margin-left:3rem!important}.bootstrap-dark .p-sm-0{padding:0!important}.bootstrap-dark .pt-sm-0,.bootstrap-dark .py-sm-0{padding-top:0!important}.bootstrap-dark .pr-sm-0,.bootstrap-dark .px-sm-0{padding-right:0!important}.bootstrap-dark .pb-sm-0,.bootstrap-dark .py-sm-0{padding-bottom:0!important}.bootstrap-dark .pl-sm-0,.bootstrap-dark .px-sm-0{padding-left:0!important}.bootstrap-dark .p-sm-1{padding:.25rem!important}.bootstrap-dark .pt-sm-1,.bootstrap-dark .py-sm-1{padding-top:.25rem!important}.bootstrap-dark .pr-sm-1,.bootstrap-dark .px-sm-1{padding-right:.25rem!important}.bootstrap-dark .pb-sm-1,.bootstrap-dark .py-sm-1{padding-bottom:.25rem!important}.bootstrap-dark .pl-sm-1,.bootstrap-dark .px-sm-1{padding-left:.25rem!important}.bootstrap-dark .p-sm-2{padding:.5rem!important}.bootstrap-dark .pt-sm-2,.bootstrap-dark .py-sm-2{padding-top:.5rem!important}.bootstrap-dark .pr-sm-2,.bootstrap-dark .px-sm-2{padding-right:.5rem!important}.bootstrap-dark .pb-sm-2,.bootstrap-dark .py-sm-2{padding-bottom:.5rem!important}.bootstrap-dark .pl-sm-2,.bootstrap-dark .px-sm-2{padding-left:.5rem!important}.bootstrap-dark .p-sm-3{padding:1rem!important}.bootstrap-dark .pt-sm-3,.bootstrap-dark .py-sm-3{padding-top:1rem!important}.bootstrap-dark .pr-sm-3,.bootstrap-dark .px-sm-3{padding-right:1rem!important}.bootstrap-dark .pb-sm-3,.bootstrap-dark .py-sm-3{padding-bottom:1rem!important}.bootstrap-dark .pl-sm-3,.bootstrap-dark .px-sm-3{padding-left:1rem!important}.bootstrap-dark .p-sm-4{padding:1.5rem!important}.bootstrap-dark .pt-sm-4,.bootstrap-dark .py-sm-4{padding-top:1.5rem!important}.bootstrap-dark .pr-sm-4,.bootstrap-dark .px-sm-4{padding-right:1.5rem!important}.bootstrap-dark .pb-sm-4,.bootstrap-dark .py-sm-4{padding-bottom:1.5rem!important}.bootstrap-dark .pl-sm-4,.bootstrap-dark .px-sm-4{padding-left:1.5rem!important}.bootstrap-dark .p-sm-5{padding:3rem!important}.bootstrap-dark .pt-sm-5,.bootstrap-dark .py-sm-5{padding-top:3rem!important}.bootstrap-dark .pr-sm-5,.bootstrap-dark .px-sm-5{padding-right:3rem!important}.bootstrap-dark .pb-sm-5,.bootstrap-dark .py-sm-5{padding-bottom:3rem!important}.bootstrap-dark .pl-sm-5,.bootstrap-dark .px-sm-5{padding-left:3rem!important}.bootstrap-dark .m-sm-n1{margin:-.25rem!important}.bootstrap-dark .mt-sm-n1,.bootstrap-dark .my-sm-n1{margin-top:-.25rem!important}.bootstrap-dark .mr-sm-n1,.bootstrap-dark .mx-sm-n1{margin-right:-.25rem!important}.bootstrap-dark .mb-sm-n1,.bootstrap-dark .my-sm-n1{margin-bottom:-.25rem!important}.bootstrap-dark .ml-sm-n1,.bootstrap-dark .mx-sm-n1{margin-left:-.25rem!important}.bootstrap-dark .m-sm-n2{margin:-.5rem!important}.bootstrap-dark .mt-sm-n2,.bootstrap-dark .my-sm-n2{margin-top:-.5rem!important}.bootstrap-dark .mr-sm-n2,.bootstrap-dark .mx-sm-n2{margin-right:-.5rem!important}.bootstrap-dark .mb-sm-n2,.bootstrap-dark .my-sm-n2{margin-bottom:-.5rem!important}.bootstrap-dark .ml-sm-n2,.bootstrap-dark .mx-sm-n2{margin-left:-.5rem!important}.bootstrap-dark .m-sm-n3{margin:-1rem!important}.bootstrap-dark .mt-sm-n3,.bootstrap-dark .my-sm-n3{margin-top:-1rem!important}.bootstrap-dark .mr-sm-n3,.bootstrap-dark .mx-sm-n3{margin-right:-1rem!important}.bootstrap-dark .mb-sm-n3,.bootstrap-dark .my-sm-n3{margin-bottom:-1rem!important}.bootstrap-dark .ml-sm-n3,.bootstrap-dark .mx-sm-n3{margin-left:-1rem!important}.bootstrap-dark .m-sm-n4{margin:-1.5rem!important}.bootstrap-dark .mt-sm-n4,.bootstrap-dark .my-sm-n4{margin-top:-1.5rem!important}.bootstrap-dark .mr-sm-n4,.bootstrap-dark .mx-sm-n4{margin-right:-1.5rem!important}.bootstrap-dark .mb-sm-n4,.bootstrap-dark .my-sm-n4{margin-bottom:-1.5rem!important}.bootstrap-dark .ml-sm-n4,.bootstrap-dark .mx-sm-n4{margin-left:-1.5rem!important}.bootstrap-dark .m-sm-n5{margin:-3rem!important}.bootstrap-dark .mt-sm-n5,.bootstrap-dark .my-sm-n5{margin-top:-3rem!important}.bootstrap-dark .mr-sm-n5,.bootstrap-dark .mx-sm-n5{margin-right:-3rem!important}.bootstrap-dark .mb-sm-n5,.bootstrap-dark .my-sm-n5{margin-bottom:-3rem!important}.bootstrap-dark .ml-sm-n5,.bootstrap-dark .mx-sm-n5{margin-left:-3rem!important}.bootstrap-dark .m-sm-auto{margin:auto!important}.bootstrap-dark .mt-sm-auto,.bootstrap-dark .my-sm-auto{margin-top:auto!important}.bootstrap-dark .mr-sm-auto,.bootstrap-dark .mx-sm-auto{margin-right:auto!important}.bootstrap-dark .mb-sm-auto,.bootstrap-dark .my-sm-auto{margin-bottom:auto!important}.bootstrap-dark .ml-sm-auto,.bootstrap-dark .mx-sm-auto{margin-left:auto!important}}@media (min-width:768px){.bootstrap-dark .m-md-0{margin:0!important}.bootstrap-dark .mt-md-0,.bootstrap-dark .my-md-0{margin-top:0!important}.bootstrap-dark .mr-md-0,.bootstrap-dark .mx-md-0{margin-right:0!important}.bootstrap-dark .mb-md-0,.bootstrap-dark .my-md-0{margin-bottom:0!important}.bootstrap-dark .ml-md-0,.bootstrap-dark .mx-md-0{margin-left:0!important}.bootstrap-dark .m-md-1{margin:.25rem!important}.bootstrap-dark .mt-md-1,.bootstrap-dark .my-md-1{margin-top:.25rem!important}.bootstrap-dark .mr-md-1,.bootstrap-dark .mx-md-1{margin-right:.25rem!important}.bootstrap-dark .mb-md-1,.bootstrap-dark .my-md-1{margin-bottom:.25rem!important}.bootstrap-dark .ml-md-1,.bootstrap-dark .mx-md-1{margin-left:.25rem!important}.bootstrap-dark .m-md-2{margin:.5rem!important}.bootstrap-dark .mt-md-2,.bootstrap-dark .my-md-2{margin-top:.5rem!important}.bootstrap-dark .mr-md-2,.bootstrap-dark .mx-md-2{margin-right:.5rem!important}.bootstrap-dark .mb-md-2,.bootstrap-dark .my-md-2{margin-bottom:.5rem!important}.bootstrap-dark .ml-md-2,.bootstrap-dark .mx-md-2{margin-left:.5rem!important}.bootstrap-dark .m-md-3{margin:1rem!important}.bootstrap-dark .mt-md-3,.bootstrap-dark .my-md-3{margin-top:1rem!important}.bootstrap-dark .mr-md-3,.bootstrap-dark .mx-md-3{margin-right:1rem!important}.bootstrap-dark .mb-md-3,.bootstrap-dark .my-md-3{margin-bottom:1rem!important}.bootstrap-dark .ml-md-3,.bootstrap-dark .mx-md-3{margin-left:1rem!important}.bootstrap-dark .m-md-4{margin:1.5rem!important}.bootstrap-dark .mt-md-4,.bootstrap-dark .my-md-4{margin-top:1.5rem!important}.bootstrap-dark .mr-md-4,.bootstrap-dark .mx-md-4{margin-right:1.5rem!important}.bootstrap-dark .mb-md-4,.bootstrap-dark .my-md-4{margin-bottom:1.5rem!important}.bootstrap-dark .ml-md-4,.bootstrap-dark .mx-md-4{margin-left:1.5rem!important}.bootstrap-dark .m-md-5{margin:3rem!important}.bootstrap-dark .mt-md-5,.bootstrap-dark .my-md-5{margin-top:3rem!important}.bootstrap-dark .mr-md-5,.bootstrap-dark .mx-md-5{margin-right:3rem!important}.bootstrap-dark .mb-md-5,.bootstrap-dark .my-md-5{margin-bottom:3rem!important}.bootstrap-dark .ml-md-5,.bootstrap-dark .mx-md-5{margin-left:3rem!important}.bootstrap-dark .p-md-0{padding:0!important}.bootstrap-dark .pt-md-0,.bootstrap-dark .py-md-0{padding-top:0!important}.bootstrap-dark .pr-md-0,.bootstrap-dark .px-md-0{padding-right:0!important}.bootstrap-dark .pb-md-0,.bootstrap-dark .py-md-0{padding-bottom:0!important}.bootstrap-dark .pl-md-0,.bootstrap-dark .px-md-0{padding-left:0!important}.bootstrap-dark .p-md-1{padding:.25rem!important}.bootstrap-dark .pt-md-1,.bootstrap-dark .py-md-1{padding-top:.25rem!important}.bootstrap-dark .pr-md-1,.bootstrap-dark .px-md-1{padding-right:.25rem!important}.bootstrap-dark .pb-md-1,.bootstrap-dark .py-md-1{padding-bottom:.25rem!important}.bootstrap-dark .pl-md-1,.bootstrap-dark .px-md-1{padding-left:.25rem!important}.bootstrap-dark .p-md-2{padding:.5rem!important}.bootstrap-dark .pt-md-2,.bootstrap-dark .py-md-2{padding-top:.5rem!important}.bootstrap-dark .pr-md-2,.bootstrap-dark .px-md-2{padding-right:.5rem!important}.bootstrap-dark .pb-md-2,.bootstrap-dark .py-md-2{padding-bottom:.5rem!important}.bootstrap-dark .pl-md-2,.bootstrap-dark .px-md-2{padding-left:.5rem!important}.bootstrap-dark .p-md-3{padding:1rem!important}.bootstrap-dark .pt-md-3,.bootstrap-dark .py-md-3{padding-top:1rem!important}.bootstrap-dark .pr-md-3,.bootstrap-dark .px-md-3{padding-right:1rem!important}.bootstrap-dark .pb-md-3,.bootstrap-dark .py-md-3{padding-bottom:1rem!important}.bootstrap-dark .pl-md-3,.bootstrap-dark .px-md-3{padding-left:1rem!important}.bootstrap-dark .p-md-4{padding:1.5rem!important}.bootstrap-dark .pt-md-4,.bootstrap-dark .py-md-4{padding-top:1.5rem!important}.bootstrap-dark .pr-md-4,.bootstrap-dark .px-md-4{padding-right:1.5rem!important}.bootstrap-dark .pb-md-4,.bootstrap-dark .py-md-4{padding-bottom:1.5rem!important}.bootstrap-dark .pl-md-4,.bootstrap-dark .px-md-4{padding-left:1.5rem!important}.bootstrap-dark .p-md-5{padding:3rem!important}.bootstrap-dark .pt-md-5,.bootstrap-dark .py-md-5{padding-top:3rem!important}.bootstrap-dark .pr-md-5,.bootstrap-dark .px-md-5{padding-right:3rem!important}.bootstrap-dark .pb-md-5,.bootstrap-dark .py-md-5{padding-bottom:3rem!important}.bootstrap-dark .pl-md-5,.bootstrap-dark .px-md-5{padding-left:3rem!important}.bootstrap-dark .m-md-n1{margin:-.25rem!important}.bootstrap-dark .mt-md-n1,.bootstrap-dark .my-md-n1{margin-top:-.25rem!important}.bootstrap-dark .mr-md-n1,.bootstrap-dark .mx-md-n1{margin-right:-.25rem!important}.bootstrap-dark .mb-md-n1,.bootstrap-dark .my-md-n1{margin-bottom:-.25rem!important}.bootstrap-dark .ml-md-n1,.bootstrap-dark .mx-md-n1{margin-left:-.25rem!important}.bootstrap-dark .m-md-n2{margin:-.5rem!important}.bootstrap-dark .mt-md-n2,.bootstrap-dark .my-md-n2{margin-top:-.5rem!important}.bootstrap-dark .mr-md-n2,.bootstrap-dark .mx-md-n2{margin-right:-.5rem!important}.bootstrap-dark .mb-md-n2,.bootstrap-dark .my-md-n2{margin-bottom:-.5rem!important}.bootstrap-dark .ml-md-n2,.bootstrap-dark .mx-md-n2{margin-left:-.5rem!important}.bootstrap-dark .m-md-n3{margin:-1rem!important}.bootstrap-dark .mt-md-n3,.bootstrap-dark .my-md-n3{margin-top:-1rem!important}.bootstrap-dark .mr-md-n3,.bootstrap-dark .mx-md-n3{margin-right:-1rem!important}.bootstrap-dark .mb-md-n3,.bootstrap-dark .my-md-n3{margin-bottom:-1rem!important}.bootstrap-dark .ml-md-n3,.bootstrap-dark .mx-md-n3{margin-left:-1rem!important}.bootstrap-dark .m-md-n4{margin:-1.5rem!important}.bootstrap-dark .mt-md-n4,.bootstrap-dark .my-md-n4{margin-top:-1.5rem!important}.bootstrap-dark .mr-md-n4,.bootstrap-dark .mx-md-n4{margin-right:-1.5rem!important}.bootstrap-dark .mb-md-n4,.bootstrap-dark .my-md-n4{margin-bottom:-1.5rem!important}.bootstrap-dark .ml-md-n4,.bootstrap-dark .mx-md-n4{margin-left:-1.5rem!important}.bootstrap-dark .m-md-n5{margin:-3rem!important}.bootstrap-dark .mt-md-n5,.bootstrap-dark .my-md-n5{margin-top:-3rem!important}.bootstrap-dark .mr-md-n5,.bootstrap-dark .mx-md-n5{margin-right:-3rem!important}.bootstrap-dark .mb-md-n5,.bootstrap-dark .my-md-n5{margin-bottom:-3rem!important}.bootstrap-dark .ml-md-n5,.bootstrap-dark .mx-md-n5{margin-left:-3rem!important}.bootstrap-dark .m-md-auto{margin:auto!important}.bootstrap-dark .mt-md-auto,.bootstrap-dark .my-md-auto{margin-top:auto!important}.bootstrap-dark .mr-md-auto,.bootstrap-dark .mx-md-auto{margin-right:auto!important}.bootstrap-dark .mb-md-auto,.bootstrap-dark .my-md-auto{margin-bottom:auto!important}.bootstrap-dark .ml-md-auto,.bootstrap-dark .mx-md-auto{margin-left:auto!important}}@media (min-width:992px){.bootstrap-dark .m-lg-0{margin:0!important}.bootstrap-dark .mt-lg-0,.bootstrap-dark .my-lg-0{margin-top:0!important}.bootstrap-dark .mr-lg-0,.bootstrap-dark .mx-lg-0{margin-right:0!important}.bootstrap-dark .mb-lg-0,.bootstrap-dark .my-lg-0{margin-bottom:0!important}.bootstrap-dark .ml-lg-0,.bootstrap-dark .mx-lg-0{margin-left:0!important}.bootstrap-dark .m-lg-1{margin:.25rem!important}.bootstrap-dark .mt-lg-1,.bootstrap-dark .my-lg-1{margin-top:.25rem!important}.bootstrap-dark .mr-lg-1,.bootstrap-dark .mx-lg-1{margin-right:.25rem!important}.bootstrap-dark .mb-lg-1,.bootstrap-dark .my-lg-1{margin-bottom:.25rem!important}.bootstrap-dark .ml-lg-1,.bootstrap-dark .mx-lg-1{margin-left:.25rem!important}.bootstrap-dark .m-lg-2{margin:.5rem!important}.bootstrap-dark .mt-lg-2,.bootstrap-dark .my-lg-2{margin-top:.5rem!important}.bootstrap-dark .mr-lg-2,.bootstrap-dark .mx-lg-2{margin-right:.5rem!important}.bootstrap-dark .mb-lg-2,.bootstrap-dark .my-lg-2{margin-bottom:.5rem!important}.bootstrap-dark .ml-lg-2,.bootstrap-dark .mx-lg-2{margin-left:.5rem!important}.bootstrap-dark .m-lg-3{margin:1rem!important}.bootstrap-dark .mt-lg-3,.bootstrap-dark .my-lg-3{margin-top:1rem!important}.bootstrap-dark .mr-lg-3,.bootstrap-dark .mx-lg-3{margin-right:1rem!important}.bootstrap-dark .mb-lg-3,.bootstrap-dark .my-lg-3{margin-bottom:1rem!important}.bootstrap-dark .ml-lg-3,.bootstrap-dark .mx-lg-3{margin-left:1rem!important}.bootstrap-dark .m-lg-4{margin:1.5rem!important}.bootstrap-dark .mt-lg-4,.bootstrap-dark .my-lg-4{margin-top:1.5rem!important}.bootstrap-dark .mr-lg-4,.bootstrap-dark .mx-lg-4{margin-right:1.5rem!important}.bootstrap-dark .mb-lg-4,.bootstrap-dark .my-lg-4{margin-bottom:1.5rem!important}.bootstrap-dark .ml-lg-4,.bootstrap-dark .mx-lg-4{margin-left:1.5rem!important}.bootstrap-dark .m-lg-5{margin:3rem!important}.bootstrap-dark .mt-lg-5,.bootstrap-dark .my-lg-5{margin-top:3rem!important}.bootstrap-dark .mr-lg-5,.bootstrap-dark .mx-lg-5{margin-right:3rem!important}.bootstrap-dark .mb-lg-5,.bootstrap-dark .my-lg-5{margin-bottom:3rem!important}.bootstrap-dark .ml-lg-5,.bootstrap-dark .mx-lg-5{margin-left:3rem!important}.bootstrap-dark .p-lg-0{padding:0!important}.bootstrap-dark .pt-lg-0,.bootstrap-dark .py-lg-0{padding-top:0!important}.bootstrap-dark .pr-lg-0,.bootstrap-dark .px-lg-0{padding-right:0!important}.bootstrap-dark .pb-lg-0,.bootstrap-dark .py-lg-0{padding-bottom:0!important}.bootstrap-dark .pl-lg-0,.bootstrap-dark .px-lg-0{padding-left:0!important}.bootstrap-dark .p-lg-1{padding:.25rem!important}.bootstrap-dark .pt-lg-1,.bootstrap-dark .py-lg-1{padding-top:.25rem!important}.bootstrap-dark .pr-lg-1,.bootstrap-dark .px-lg-1{padding-right:.25rem!important}.bootstrap-dark .pb-lg-1,.bootstrap-dark .py-lg-1{padding-bottom:.25rem!important}.bootstrap-dark .pl-lg-1,.bootstrap-dark .px-lg-1{padding-left:.25rem!important}.bootstrap-dark .p-lg-2{padding:.5rem!important}.bootstrap-dark .pt-lg-2,.bootstrap-dark .py-lg-2{padding-top:.5rem!important}.bootstrap-dark .pr-lg-2,.bootstrap-dark .px-lg-2{padding-right:.5rem!important}.bootstrap-dark .pb-lg-2,.bootstrap-dark .py-lg-2{padding-bottom:.5rem!important}.bootstrap-dark .pl-lg-2,.bootstrap-dark .px-lg-2{padding-left:.5rem!important}.bootstrap-dark .p-lg-3{padding:1rem!important}.bootstrap-dark .pt-lg-3,.bootstrap-dark .py-lg-3{padding-top:1rem!important}.bootstrap-dark .pr-lg-3,.bootstrap-dark .px-lg-3{padding-right:1rem!important}.bootstrap-dark .pb-lg-3,.bootstrap-dark .py-lg-3{padding-bottom:1rem!important}.bootstrap-dark .pl-lg-3,.bootstrap-dark .px-lg-3{padding-left:1rem!important}.bootstrap-dark .p-lg-4{padding:1.5rem!important}.bootstrap-dark .pt-lg-4,.bootstrap-dark .py-lg-4{padding-top:1.5rem!important}.bootstrap-dark .pr-lg-4,.bootstrap-dark .px-lg-4{padding-right:1.5rem!important}.bootstrap-dark .pb-lg-4,.bootstrap-dark .py-lg-4{padding-bottom:1.5rem!important}.bootstrap-dark .pl-lg-4,.bootstrap-dark .px-lg-4{padding-left:1.5rem!important}.bootstrap-dark .p-lg-5{padding:3rem!important}.bootstrap-dark .pt-lg-5,.bootstrap-dark .py-lg-5{padding-top:3rem!important}.bootstrap-dark .pr-lg-5,.bootstrap-dark .px-lg-5{padding-right:3rem!important}.bootstrap-dark .pb-lg-5,.bootstrap-dark .py-lg-5{padding-bottom:3rem!important}.bootstrap-dark .pl-lg-5,.bootstrap-dark .px-lg-5{padding-left:3rem!important}.bootstrap-dark .m-lg-n1{margin:-.25rem!important}.bootstrap-dark .mt-lg-n1,.bootstrap-dark .my-lg-n1{margin-top:-.25rem!important}.bootstrap-dark .mr-lg-n1,.bootstrap-dark .mx-lg-n1{margin-right:-.25rem!important}.bootstrap-dark .mb-lg-n1,.bootstrap-dark .my-lg-n1{margin-bottom:-.25rem!important}.bootstrap-dark .ml-lg-n1,.bootstrap-dark .mx-lg-n1{margin-left:-.25rem!important}.bootstrap-dark .m-lg-n2{margin:-.5rem!important}.bootstrap-dark .mt-lg-n2,.bootstrap-dark .my-lg-n2{margin-top:-.5rem!important}.bootstrap-dark .mr-lg-n2,.bootstrap-dark .mx-lg-n2{margin-right:-.5rem!important}.bootstrap-dark .mb-lg-n2,.bootstrap-dark .my-lg-n2{margin-bottom:-.5rem!important}.bootstrap-dark .ml-lg-n2,.bootstrap-dark .mx-lg-n2{margin-left:-.5rem!important}.bootstrap-dark .m-lg-n3{margin:-1rem!important}.bootstrap-dark .mt-lg-n3,.bootstrap-dark .my-lg-n3{margin-top:-1rem!important}.bootstrap-dark .mr-lg-n3,.bootstrap-dark .mx-lg-n3{margin-right:-1rem!important}.bootstrap-dark .mb-lg-n3,.bootstrap-dark .my-lg-n3{margin-bottom:-1rem!important}.bootstrap-dark .ml-lg-n3,.bootstrap-dark .mx-lg-n3{margin-left:-1rem!important}.bootstrap-dark .m-lg-n4{margin:-1.5rem!important}.bootstrap-dark .mt-lg-n4,.bootstrap-dark .my-lg-n4{margin-top:-1.5rem!important}.bootstrap-dark .mr-lg-n4,.bootstrap-dark .mx-lg-n4{margin-right:-1.5rem!important}.bootstrap-dark .mb-lg-n4,.bootstrap-dark .my-lg-n4{margin-bottom:-1.5rem!important}.bootstrap-dark .ml-lg-n4,.bootstrap-dark .mx-lg-n4{margin-left:-1.5rem!important}.bootstrap-dark .m-lg-n5{margin:-3rem!important}.bootstrap-dark .mt-lg-n5,.bootstrap-dark .my-lg-n5{margin-top:-3rem!important}.bootstrap-dark .mr-lg-n5,.bootstrap-dark .mx-lg-n5{margin-right:-3rem!important}.bootstrap-dark .mb-lg-n5,.bootstrap-dark .my-lg-n5{margin-bottom:-3rem!important}.bootstrap-dark .ml-lg-n5,.bootstrap-dark .mx-lg-n5{margin-left:-3rem!important}.bootstrap-dark .m-lg-auto{margin:auto!important}.bootstrap-dark .mt-lg-auto,.bootstrap-dark .my-lg-auto{margin-top:auto!important}.bootstrap-dark .mr-lg-auto,.bootstrap-dark .mx-lg-auto{margin-right:auto!important}.bootstrap-dark .mb-lg-auto,.bootstrap-dark .my-lg-auto{margin-bottom:auto!important}.bootstrap-dark .ml-lg-auto,.bootstrap-dark .mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.bootstrap-dark .m-xl-0{margin:0!important}.bootstrap-dark .mt-xl-0,.bootstrap-dark .my-xl-0{margin-top:0!important}.bootstrap-dark .mr-xl-0,.bootstrap-dark .mx-xl-0{margin-right:0!important}.bootstrap-dark .mb-xl-0,.bootstrap-dark .my-xl-0{margin-bottom:0!important}.bootstrap-dark .ml-xl-0,.bootstrap-dark .mx-xl-0{margin-left:0!important}.bootstrap-dark .m-xl-1{margin:.25rem!important}.bootstrap-dark .mt-xl-1,.bootstrap-dark .my-xl-1{margin-top:.25rem!important}.bootstrap-dark .mr-xl-1,.bootstrap-dark .mx-xl-1{margin-right:.25rem!important}.bootstrap-dark .mb-xl-1,.bootstrap-dark .my-xl-1{margin-bottom:.25rem!important}.bootstrap-dark .ml-xl-1,.bootstrap-dark .mx-xl-1{margin-left:.25rem!important}.bootstrap-dark .m-xl-2{margin:.5rem!important}.bootstrap-dark .mt-xl-2,.bootstrap-dark .my-xl-2{margin-top:.5rem!important}.bootstrap-dark .mr-xl-2,.bootstrap-dark .mx-xl-2{margin-right:.5rem!important}.bootstrap-dark .mb-xl-2,.bootstrap-dark .my-xl-2{margin-bottom:.5rem!important}.bootstrap-dark .ml-xl-2,.bootstrap-dark .mx-xl-2{margin-left:.5rem!important}.bootstrap-dark .m-xl-3{margin:1rem!important}.bootstrap-dark .mt-xl-3,.bootstrap-dark .my-xl-3{margin-top:1rem!important}.bootstrap-dark .mr-xl-3,.bootstrap-dark .mx-xl-3{margin-right:1rem!important}.bootstrap-dark .mb-xl-3,.bootstrap-dark .my-xl-3{margin-bottom:1rem!important}.bootstrap-dark .ml-xl-3,.bootstrap-dark .mx-xl-3{margin-left:1rem!important}.bootstrap-dark .m-xl-4{margin:1.5rem!important}.bootstrap-dark .mt-xl-4,.bootstrap-dark .my-xl-4{margin-top:1.5rem!important}.bootstrap-dark .mr-xl-4,.bootstrap-dark .mx-xl-4{margin-right:1.5rem!important}.bootstrap-dark .mb-xl-4,.bootstrap-dark .my-xl-4{margin-bottom:1.5rem!important}.bootstrap-dark .ml-xl-4,.bootstrap-dark .mx-xl-4{margin-left:1.5rem!important}.bootstrap-dark .m-xl-5{margin:3rem!important}.bootstrap-dark .mt-xl-5,.bootstrap-dark .my-xl-5{margin-top:3rem!important}.bootstrap-dark .mr-xl-5,.bootstrap-dark .mx-xl-5{margin-right:3rem!important}.bootstrap-dark .mb-xl-5,.bootstrap-dark .my-xl-5{margin-bottom:3rem!important}.bootstrap-dark .ml-xl-5,.bootstrap-dark .mx-xl-5{margin-left:3rem!important}.bootstrap-dark .p-xl-0{padding:0!important}.bootstrap-dark .pt-xl-0,.bootstrap-dark .py-xl-0{padding-top:0!important}.bootstrap-dark .pr-xl-0,.bootstrap-dark .px-xl-0{padding-right:0!important}.bootstrap-dark .pb-xl-0,.bootstrap-dark .py-xl-0{padding-bottom:0!important}.bootstrap-dark .pl-xl-0,.bootstrap-dark .px-xl-0{padding-left:0!important}.bootstrap-dark .p-xl-1{padding:.25rem!important}.bootstrap-dark .pt-xl-1,.bootstrap-dark .py-xl-1{padding-top:.25rem!important}.bootstrap-dark .pr-xl-1,.bootstrap-dark .px-xl-1{padding-right:.25rem!important}.bootstrap-dark .pb-xl-1,.bootstrap-dark .py-xl-1{padding-bottom:.25rem!important}.bootstrap-dark .pl-xl-1,.bootstrap-dark .px-xl-1{padding-left:.25rem!important}.bootstrap-dark .p-xl-2{padding:.5rem!important}.bootstrap-dark .pt-xl-2,.bootstrap-dark .py-xl-2{padding-top:.5rem!important}.bootstrap-dark .pr-xl-2,.bootstrap-dark .px-xl-2{padding-right:.5rem!important}.bootstrap-dark .pb-xl-2,.bootstrap-dark .py-xl-2{padding-bottom:.5rem!important}.bootstrap-dark .pl-xl-2,.bootstrap-dark .px-xl-2{padding-left:.5rem!important}.bootstrap-dark .p-xl-3{padding:1rem!important}.bootstrap-dark .pt-xl-3,.bootstrap-dark .py-xl-3{padding-top:1rem!important}.bootstrap-dark .pr-xl-3,.bootstrap-dark .px-xl-3{padding-right:1rem!important}.bootstrap-dark .pb-xl-3,.bootstrap-dark .py-xl-3{padding-bottom:1rem!important}.bootstrap-dark .pl-xl-3,.bootstrap-dark .px-xl-3{padding-left:1rem!important}.bootstrap-dark .p-xl-4{padding:1.5rem!important}.bootstrap-dark .pt-xl-4,.bootstrap-dark .py-xl-4{padding-top:1.5rem!important}.bootstrap-dark .pr-xl-4,.bootstrap-dark .px-xl-4{padding-right:1.5rem!important}.bootstrap-dark .pb-xl-4,.bootstrap-dark .py-xl-4{padding-bottom:1.5rem!important}.bootstrap-dark .pl-xl-4,.bootstrap-dark .px-xl-4{padding-left:1.5rem!important}.bootstrap-dark .p-xl-5{padding:3rem!important}.bootstrap-dark .pt-xl-5,.bootstrap-dark .py-xl-5{padding-top:3rem!important}.bootstrap-dark .pr-xl-5,.bootstrap-dark .px-xl-5{padding-right:3rem!important}.bootstrap-dark .pb-xl-5,.bootstrap-dark .py-xl-5{padding-bottom:3rem!important}.bootstrap-dark .pl-xl-5,.bootstrap-dark .px-xl-5{padding-left:3rem!important}.bootstrap-dark .m-xl-n1{margin:-.25rem!important}.bootstrap-dark .mt-xl-n1,.bootstrap-dark .my-xl-n1{margin-top:-.25rem!important}.bootstrap-dark .mr-xl-n1,.bootstrap-dark .mx-xl-n1{margin-right:-.25rem!important}.bootstrap-dark .mb-xl-n1,.bootstrap-dark .my-xl-n1{margin-bottom:-.25rem!important}.bootstrap-dark .ml-xl-n1,.bootstrap-dark .mx-xl-n1{margin-left:-.25rem!important}.bootstrap-dark .m-xl-n2{margin:-.5rem!important}.bootstrap-dark .mt-xl-n2,.bootstrap-dark .my-xl-n2{margin-top:-.5rem!important}.bootstrap-dark .mr-xl-n2,.bootstrap-dark .mx-xl-n2{margin-right:-.5rem!important}.bootstrap-dark .mb-xl-n2,.bootstrap-dark .my-xl-n2{margin-bottom:-.5rem!important}.bootstrap-dark .ml-xl-n2,.bootstrap-dark .mx-xl-n2{margin-left:-.5rem!important}.bootstrap-dark .m-xl-n3{margin:-1rem!important}.bootstrap-dark .mt-xl-n3,.bootstrap-dark .my-xl-n3{margin-top:-1rem!important}.bootstrap-dark .mr-xl-n3,.bootstrap-dark .mx-xl-n3{margin-right:-1rem!important}.bootstrap-dark .mb-xl-n3,.bootstrap-dark .my-xl-n3{margin-bottom:-1rem!important}.bootstrap-dark .ml-xl-n3,.bootstrap-dark .mx-xl-n3{margin-left:-1rem!important}.bootstrap-dark .m-xl-n4{margin:-1.5rem!important}.bootstrap-dark .mt-xl-n4,.bootstrap-dark .my-xl-n4{margin-top:-1.5rem!important}.bootstrap-dark .mr-xl-n4,.bootstrap-dark .mx-xl-n4{margin-right:-1.5rem!important}.bootstrap-dark .mb-xl-n4,.bootstrap-dark .my-xl-n4{margin-bottom:-1.5rem!important}.bootstrap-dark .ml-xl-n4,.bootstrap-dark .mx-xl-n4{margin-left:-1.5rem!important}.bootstrap-dark .m-xl-n5{margin:-3rem!important}.bootstrap-dark .mt-xl-n5,.bootstrap-dark .my-xl-n5{margin-top:-3rem!important}.bootstrap-dark .mr-xl-n5,.bootstrap-dark .mx-xl-n5{margin-right:-3rem!important}.bootstrap-dark .mb-xl-n5,.bootstrap-dark .my-xl-n5{margin-bottom:-3rem!important}.bootstrap-dark .ml-xl-n5,.bootstrap-dark .mx-xl-n5{margin-left:-3rem!important}.bootstrap-dark .m-xl-auto{margin:auto!important}.bootstrap-dark .mt-xl-auto,.bootstrap-dark .my-xl-auto{margin-top:auto!important}.bootstrap-dark .mr-xl-auto,.bootstrap-dark .mx-xl-auto{margin-right:auto!important}.bootstrap-dark .mb-xl-auto,.bootstrap-dark .my-xl-auto{margin-bottom:auto!important}.bootstrap-dark .ml-xl-auto,.bootstrap-dark .mx-xl-auto{margin-left:auto!important}}.bootstrap-dark .text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace!important}.bootstrap-dark .text-justify{text-align:justify!important}.bootstrap-dark .text-wrap{white-space:normal!important}.bootstrap-dark .text-nowrap{white-space:nowrap!important}.bootstrap-dark .text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.bootstrap-dark .text-left{text-align:left!important}.bootstrap-dark .text-right{text-align:right!important}.bootstrap-dark .text-center{text-align:center!important}@media (min-width:576px){.bootstrap-dark .text-sm-left{text-align:left!important}.bootstrap-dark .text-sm-right{text-align:right!important}.bootstrap-dark .text-sm-center{text-align:center!important}}@media (min-width:768px){.bootstrap-dark .text-md-left{text-align:left!important}.bootstrap-dark .text-md-right{text-align:right!important}.bootstrap-dark .text-md-center{text-align:center!important}}@media (min-width:992px){.bootstrap-dark .text-lg-left{text-align:left!important}.bootstrap-dark .text-lg-right{text-align:right!important}.bootstrap-dark .text-lg-center{text-align:center!important}}@media (min-width:1200px){.bootstrap-dark .text-xl-left{text-align:left!important}.bootstrap-dark .text-xl-right{text-align:right!important}.bootstrap-dark .text-xl-center{text-align:center!important}}.bootstrap-dark .text-lowercase{text-transform:lowercase!important}.bootstrap-dark .text-uppercase{text-transform:uppercase!important}.bootstrap-dark .text-capitalize{text-transform:capitalize!important}.bootstrap-dark .font-weight-light{font-weight:300!important}.bootstrap-dark .font-weight-lighter{font-weight:lighter!important}.bootstrap-dark .font-weight-normal{font-weight:400!important}.bootstrap-dark .font-weight-bold{font-weight:700!important}.bootstrap-dark .font-weight-bolder{font-weight:bolder!important}.bootstrap-dark .font-italic{font-style:italic!important}.bootstrap-dark .text-white{color:#fff!important}.bootstrap-dark .text-primary{color:#007bff!important}.bootstrap-dark a.text-primary:focus,.bootstrap-dark a.text-primary:hover{color:#0056b3!important}.bootstrap-dark .text-secondary{color:#6c757d!important}.bootstrap-dark a.text-secondary:focus,.bootstrap-dark a.text-secondary:hover{color:#494f54!important}.bootstrap-dark .text-success{color:#28a745!important}.bootstrap-dark a.text-success:focus,.bootstrap-dark a.text-success:hover{color:#19692c!important}.bootstrap-dark .text-info{color:#17a2b8!important}.bootstrap-dark a.text-info:focus,.bootstrap-dark a.text-info:hover{color:#0f6674!important}.bootstrap-dark .text-warning{color:#ffc107!important}.bootstrap-dark a.text-warning:focus,.bootstrap-dark a.text-warning:hover{color:#ba8b00!important}.bootstrap-dark .text-danger{color:#dc3545!important}.bootstrap-dark a.text-danger:focus,.bootstrap-dark a.text-danger:hover{color:#a71d2a!important}.bootstrap-dark .text-light{color:#f8f9fa!important}.bootstrap-dark a.text-light:focus,.bootstrap-dark a.text-light:hover{color:#cbd3da!important}.bootstrap-dark .text-dark{color:#343a40!important}.bootstrap-dark a.text-dark:focus,.bootstrap-dark a.text-dark:hover{color:#121416!important}.bootstrap-dark .text-body{color:#d3d3d3!important}.bootstrap-dark .text-muted{color:#6c757d!important}.bootstrap-dark .text-black-50{color:rgba(0,0,0,.5)!important}.bootstrap-dark .text-white-50{color:rgba(255,255,255,.5)!important}.bootstrap-dark .text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.bootstrap-dark .text-decoration-none{text-decoration:none!important}.bootstrap-dark .text-break{word-break:break-word!important;overflow-wrap:break-word!important}.bootstrap-dark .text-reset{color:inherit!important}.bootstrap-dark .visible{visibility:visible!important}.bootstrap-dark .invisible{visibility:hidden!important}.bootstrap-dark p a{text-decoration:underline}.bootstrap-dark hr{border-top:1px solid #495057} diff --git a/docsSrc/content/toggle-bootstrap.min.css b/docsSrc/content/toggle-bootstrap.min.css deleted file mode 100644 index 6ba4734..0000000 --- a/docsSrc/content/toggle-bootstrap.min.css +++ /dev/null @@ -1 +0,0 @@ -body.bootstrap{margin:0;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";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}.bootstrap :root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--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";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}.bootstrap *,.bootstrap ::after,.bootstrap ::before{-webkit-box-sizing:border-box;box-sizing:border-box}.bootstrap html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}.bootstrap article,.bootstrap aside,.bootstrap figcaption,.bootstrap figure,.bootstrap footer,.bootstrap header,.bootstrap hgroup,.bootstrap main,.bootstrap nav,.bootstrap section{display:block}.bootstrap body{margin:0;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";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}.bootstrap [tabindex="-1"]:focus:not(:focus-visible){outline:0!important}.bootstrap hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}.bootstrap h1,.bootstrap h2,.bootstrap h3,.bootstrap h4,.bootstrap h5,.bootstrap h6{margin-top:0;margin-bottom:.5rem}.bootstrap p{margin-top:0;margin-bottom:1rem}.bootstrap abbr[data-original-title],.bootstrap abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;text-decoration-skip-ink:none}.bootstrap address{margin-bottom:1rem;font-style:normal;line-height:inherit}.bootstrap dl,.bootstrap ol,.bootstrap ul{margin-top:0;margin-bottom:1rem}.bootstrap ol ol,.bootstrap ol ul,.bootstrap ul ol,.bootstrap ul ul{margin-bottom:0}.bootstrap dt{font-weight:700}.bootstrap dd{margin-bottom:.5rem;margin-left:0}.bootstrap blockquote{margin:0 0 1rem}.bootstrap b,.bootstrap strong{font-weight:bolder}.bootstrap small{font-size:80%}.bootstrap sub,.bootstrap sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}.bootstrap sub{bottom:-.25em}.bootstrap sup{top:-.5em}.bootstrap a{color:#007bff;text-decoration:none;background-color:transparent}.bootstrap a:hover{color:#0056b3;text-decoration:underline}.bootstrap a:not([href]){color:inherit;text-decoration:none}.bootstrap a:not([href]):hover{color:inherit;text-decoration:none}.bootstrap code,.bootstrap kbd,.bootstrap pre,.bootstrap samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}.bootstrap pre{margin-top:0;margin-bottom:1rem;overflow:auto}.bootstrap figure{margin:0 0 1rem}.bootstrap img{vertical-align:middle;border-style:none}.bootstrap svg{overflow:hidden;vertical-align:middle}.bootstrap table{border-collapse:collapse}.bootstrap caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}.bootstrap th{text-align:inherit}.bootstrap label{display:inline-block;margin-bottom:.5rem}.bootstrap button{border-radius:0}.bootstrap button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.bootstrap button,.bootstrap input,.bootstrap optgroup,.bootstrap select,.bootstrap textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}.bootstrap button,.bootstrap input{overflow:visible}.bootstrap button,.bootstrap select{text-transform:none}.bootstrap select{word-wrap:normal}.bootstrap [type=button],.bootstrap [type=reset],.bootstrap [type=submit],.bootstrap button{-webkit-appearance:button}.bootstrap [type=button]:not(:disabled),.bootstrap [type=reset]:not(:disabled),.bootstrap [type=submit]:not(:disabled),.bootstrap button:not(:disabled){cursor:pointer}.bootstrap [type=button]::-moz-focus-inner,.bootstrap [type=reset]::-moz-focus-inner,.bootstrap [type=submit]::-moz-focus-inner,.bootstrap button::-moz-focus-inner{padding:0;border-style:none}.bootstrap input[type=checkbox],.bootstrap input[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}.bootstrap input[type=date],.bootstrap input[type=datetime-local],.bootstrap input[type=month],.bootstrap input[type=time]{-webkit-appearance:listbox}.bootstrap textarea{overflow:auto;resize:vertical}.bootstrap fieldset{min-width:0;padding:0;margin:0;border:0}.bootstrap legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}.bootstrap progress{vertical-align:baseline}.bootstrap [type=number]::-webkit-inner-spin-button,.bootstrap [type=number]::-webkit-outer-spin-button{height:auto}.bootstrap [type=search]{outline-offset:-2px;-webkit-appearance:none}.bootstrap [type=search]::-webkit-search-decoration{-webkit-appearance:none}.bootstrap ::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}.bootstrap output{display:inline-block}.bootstrap summary{display:list-item;cursor:pointer}.bootstrap template{display:none}.bootstrap [hidden]{display:none!important}.bootstrap .h1,.bootstrap .h2,.bootstrap .h3,.bootstrap .h4,.bootstrap .h5,.bootstrap .h6,.bootstrap h1,.bootstrap h2,.bootstrap h3,.bootstrap h4,.bootstrap h5,.bootstrap h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}.bootstrap .h1,.bootstrap h1{font-size:2.5rem}.bootstrap .h2,.bootstrap h2{font-size:2rem}.bootstrap .h3,.bootstrap h3{font-size:1.75rem}.bootstrap .h4,.bootstrap h4{font-size:1.5rem}.bootstrap .h5,.bootstrap h5{font-size:1.25rem}.bootstrap .h6,.bootstrap h6{font-size:1rem}.bootstrap .lead{font-size:1.25rem;font-weight:300}.bootstrap .display-1{font-size:6rem;font-weight:300;line-height:1.2}.bootstrap .display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.bootstrap .display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.bootstrap .display-4{font-size:3.5rem;font-weight:300;line-height:1.2}.bootstrap hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.bootstrap .small,.bootstrap small{font-size:80%;font-weight:400}.bootstrap .mark,.bootstrap mark{padding:.2em;background-color:#fcf8e3}.bootstrap .list-unstyled{padding-left:0;list-style:none}.bootstrap .list-inline{padding-left:0;list-style:none}.bootstrap .list-inline-item{display:inline-block}.bootstrap .list-inline-item:not(:last-child){margin-right:.5rem}.bootstrap .initialism{font-size:90%;text-transform:uppercase}.bootstrap .blockquote{margin-bottom:1rem;font-size:1.25rem}.bootstrap .blockquote-footer{display:block;font-size:80%;color:#6c757d}.bootstrap .blockquote-footer::before{content:"\2014\00A0"}.bootstrap .img-fluid{max-width:100%;height:auto}.bootstrap .img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.bootstrap .figure{display:inline-block}.bootstrap .figure-img{margin-bottom:.5rem;line-height:1}.bootstrap .figure-caption{font-size:90%;color:#6c757d}.bootstrap code{font-size:87.5%;color:#e83e8c;word-wrap:break-word}a>.bootstrap code{color:inherit}.bootstrap kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:.2rem}.bootstrap kbd kbd{padding:0;font-size:100%;font-weight:700}.bootstrap pre{display:block;font-size:87.5%;color:#212529}.bootstrap pre code{font-size:inherit;color:inherit;word-break:normal}.bootstrap .pre-scrollable{max-height:340px;overflow-y:scroll}.bootstrap .container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.bootstrap .container{max-width:540px}}@media (min-width:768px){.bootstrap .container{max-width:720px}}@media (min-width:992px){.bootstrap .container{max-width:960px}}@media (min-width:1200px){.bootstrap .container{max-width:1140px}}.bootstrap .container-fluid,.bootstrap .container-lg,.bootstrap .container-md,.bootstrap .container-sm,.bootstrap .container-xl{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.bootstrap .container,.bootstrap .container-sm{max-width:540px}}@media (min-width:768px){.bootstrap .container,.bootstrap .container-md,.bootstrap .container-sm{max-width:720px}}@media (min-width:992px){.bootstrap .container,.bootstrap .container-lg,.bootstrap .container-md,.bootstrap .container-sm{max-width:960px}}@media (min-width:1200px){.bootstrap .container,.bootstrap .container-lg,.bootstrap .container-md,.bootstrap .container-sm,.bootstrap .container-xl{max-width:1140px}}.bootstrap .row{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.bootstrap .no-gutters{margin-right:0;margin-left:0}.bootstrap .no-gutters>.col,.bootstrap .no-gutters>[class*=col-]{padding-right:0;padding-left:0}.bootstrap .col,.bootstrap .col-1,.bootstrap .col-10,.bootstrap .col-11,.bootstrap .col-12,.bootstrap .col-2,.bootstrap .col-3,.bootstrap .col-4,.bootstrap .col-5,.bootstrap .col-6,.bootstrap .col-7,.bootstrap .col-8,.bootstrap .col-9,.bootstrap .col-auto,.bootstrap .col-lg,.bootstrap .col-lg-1,.bootstrap .col-lg-10,.bootstrap .col-lg-11,.bootstrap .col-lg-12,.bootstrap .col-lg-2,.bootstrap .col-lg-3,.bootstrap .col-lg-4,.bootstrap .col-lg-5,.bootstrap .col-lg-6,.bootstrap .col-lg-7,.bootstrap .col-lg-8,.bootstrap .col-lg-9,.bootstrap .col-lg-auto,.bootstrap .col-md,.bootstrap .col-md-1,.bootstrap .col-md-10,.bootstrap .col-md-11,.bootstrap .col-md-12,.bootstrap .col-md-2,.bootstrap .col-md-3,.bootstrap .col-md-4,.bootstrap .col-md-5,.bootstrap .col-md-6,.bootstrap .col-md-7,.bootstrap .col-md-8,.bootstrap .col-md-9,.bootstrap .col-md-auto,.bootstrap .col-sm,.bootstrap .col-sm-1,.bootstrap .col-sm-10,.bootstrap .col-sm-11,.bootstrap .col-sm-12,.bootstrap .col-sm-2,.bootstrap .col-sm-3,.bootstrap .col-sm-4,.bootstrap .col-sm-5,.bootstrap .col-sm-6,.bootstrap .col-sm-7,.bootstrap .col-sm-8,.bootstrap .col-sm-9,.bootstrap .col-sm-auto,.bootstrap .col-xl,.bootstrap .col-xl-1,.bootstrap .col-xl-10,.bootstrap .col-xl-11,.bootstrap .col-xl-12,.bootstrap .col-xl-2,.bootstrap .col-xl-3,.bootstrap .col-xl-4,.bootstrap .col-xl-5,.bootstrap .col-xl-6,.bootstrap .col-xl-7,.bootstrap .col-xl-8,.bootstrap .col-xl-9,.bootstrap .col-xl-auto{position:relative;width:100%;padding-right:15px;padding-left:15px}.bootstrap .col{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.bootstrap .row-cols-1>*{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.bootstrap .row-cols-2>*{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.bootstrap .row-cols-3>*{-webkit-box-flex:0;-webkit-flex:0 0 33.33333%;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.bootstrap .row-cols-4>*{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.bootstrap .row-cols-5>*{-webkit-box-flex:0;-webkit-flex:0 0 20%;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.bootstrap .row-cols-6>*{-webkit-box-flex:0;-webkit-flex:0 0 16.66667%;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.bootstrap .col-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.bootstrap .col-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333%;-ms-flex:0 0 8.33333%;flex:0 0 8.33333%;max-width:8.33333%}.bootstrap .col-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66667%;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.bootstrap .col-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.bootstrap .col-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333%;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.bootstrap .col-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66667%;-ms-flex:0 0 41.66667%;flex:0 0 41.66667%;max-width:41.66667%}.bootstrap .col-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.bootstrap .col-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333%;-ms-flex:0 0 58.33333%;flex:0 0 58.33333%;max-width:58.33333%}.bootstrap .col-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66667%;-ms-flex:0 0 66.66667%;flex:0 0 66.66667%;max-width:66.66667%}.bootstrap .col-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.bootstrap .col-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333%;-ms-flex:0 0 83.33333%;flex:0 0 83.33333%;max-width:83.33333%}.bootstrap .col-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66667%;-ms-flex:0 0 91.66667%;flex:0 0 91.66667%;max-width:91.66667%}.bootstrap .col-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.bootstrap .order-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.bootstrap .order-last{-webkit-box-ordinal-group:14;-webkit-order:13;-ms-flex-order:13;order:13}.bootstrap .order-0{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.bootstrap .order-1{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.bootstrap .order-2{-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2}.bootstrap .order-3{-webkit-box-ordinal-group:4;-webkit-order:3;-ms-flex-order:3;order:3}.bootstrap .order-4{-webkit-box-ordinal-group:5;-webkit-order:4;-ms-flex-order:4;order:4}.bootstrap .order-5{-webkit-box-ordinal-group:6;-webkit-order:5;-ms-flex-order:5;order:5}.bootstrap .order-6{-webkit-box-ordinal-group:7;-webkit-order:6;-ms-flex-order:6;order:6}.bootstrap .order-7{-webkit-box-ordinal-group:8;-webkit-order:7;-ms-flex-order:7;order:7}.bootstrap .order-8{-webkit-box-ordinal-group:9;-webkit-order:8;-ms-flex-order:8;order:8}.bootstrap .order-9{-webkit-box-ordinal-group:10;-webkit-order:9;-ms-flex-order:9;order:9}.bootstrap .order-10{-webkit-box-ordinal-group:11;-webkit-order:10;-ms-flex-order:10;order:10}.bootstrap .order-11{-webkit-box-ordinal-group:12;-webkit-order:11;-ms-flex-order:11;order:11}.bootstrap .order-12{-webkit-box-ordinal-group:13;-webkit-order:12;-ms-flex-order:12;order:12}.bootstrap .offset-1{margin-left:8.33333%}.bootstrap .offset-2{margin-left:16.66667%}.bootstrap .offset-3{margin-left:25%}.bootstrap .offset-4{margin-left:33.33333%}.bootstrap .offset-5{margin-left:41.66667%}.bootstrap .offset-6{margin-left:50%}.bootstrap .offset-7{margin-left:58.33333%}.bootstrap .offset-8{margin-left:66.66667%}.bootstrap .offset-9{margin-left:75%}.bootstrap .offset-10{margin-left:83.33333%}.bootstrap .offset-11{margin-left:91.66667%}@media (min-width:576px){.bootstrap .col-sm{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.bootstrap .row-cols-sm-1>*{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.bootstrap .row-cols-sm-2>*{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.bootstrap .row-cols-sm-3>*{-webkit-box-flex:0;-webkit-flex:0 0 33.33333%;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.bootstrap .row-cols-sm-4>*{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.bootstrap .row-cols-sm-5>*{-webkit-box-flex:0;-webkit-flex:0 0 20%;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.bootstrap .row-cols-sm-6>*{-webkit-box-flex:0;-webkit-flex:0 0 16.66667%;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.bootstrap .col-sm-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.bootstrap .col-sm-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333%;-ms-flex:0 0 8.33333%;flex:0 0 8.33333%;max-width:8.33333%}.bootstrap .col-sm-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66667%;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.bootstrap .col-sm-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.bootstrap .col-sm-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333%;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.bootstrap .col-sm-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66667%;-ms-flex:0 0 41.66667%;flex:0 0 41.66667%;max-width:41.66667%}.bootstrap .col-sm-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.bootstrap .col-sm-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333%;-ms-flex:0 0 58.33333%;flex:0 0 58.33333%;max-width:58.33333%}.bootstrap .col-sm-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66667%;-ms-flex:0 0 66.66667%;flex:0 0 66.66667%;max-width:66.66667%}.bootstrap .col-sm-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.bootstrap .col-sm-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333%;-ms-flex:0 0 83.33333%;flex:0 0 83.33333%;max-width:83.33333%}.bootstrap .col-sm-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66667%;-ms-flex:0 0 91.66667%;flex:0 0 91.66667%;max-width:91.66667%}.bootstrap .col-sm-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.bootstrap .order-sm-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.bootstrap .order-sm-last{-webkit-box-ordinal-group:14;-webkit-order:13;-ms-flex-order:13;order:13}.bootstrap .order-sm-0{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.bootstrap .order-sm-1{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.bootstrap .order-sm-2{-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2}.bootstrap .order-sm-3{-webkit-box-ordinal-group:4;-webkit-order:3;-ms-flex-order:3;order:3}.bootstrap .order-sm-4{-webkit-box-ordinal-group:5;-webkit-order:4;-ms-flex-order:4;order:4}.bootstrap .order-sm-5{-webkit-box-ordinal-group:6;-webkit-order:5;-ms-flex-order:5;order:5}.bootstrap .order-sm-6{-webkit-box-ordinal-group:7;-webkit-order:6;-ms-flex-order:6;order:6}.bootstrap .order-sm-7{-webkit-box-ordinal-group:8;-webkit-order:7;-ms-flex-order:7;order:7}.bootstrap .order-sm-8{-webkit-box-ordinal-group:9;-webkit-order:8;-ms-flex-order:8;order:8}.bootstrap .order-sm-9{-webkit-box-ordinal-group:10;-webkit-order:9;-ms-flex-order:9;order:9}.bootstrap .order-sm-10{-webkit-box-ordinal-group:11;-webkit-order:10;-ms-flex-order:10;order:10}.bootstrap .order-sm-11{-webkit-box-ordinal-group:12;-webkit-order:11;-ms-flex-order:11;order:11}.bootstrap .order-sm-12{-webkit-box-ordinal-group:13;-webkit-order:12;-ms-flex-order:12;order:12}.bootstrap .offset-sm-0{margin-left:0}.bootstrap .offset-sm-1{margin-left:8.33333%}.bootstrap .offset-sm-2{margin-left:16.66667%}.bootstrap .offset-sm-3{margin-left:25%}.bootstrap .offset-sm-4{margin-left:33.33333%}.bootstrap .offset-sm-5{margin-left:41.66667%}.bootstrap .offset-sm-6{margin-left:50%}.bootstrap .offset-sm-7{margin-left:58.33333%}.bootstrap .offset-sm-8{margin-left:66.66667%}.bootstrap .offset-sm-9{margin-left:75%}.bootstrap .offset-sm-10{margin-left:83.33333%}.bootstrap .offset-sm-11{margin-left:91.66667%}}@media (min-width:768px){.bootstrap .col-md{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.bootstrap .row-cols-md-1>*{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.bootstrap .row-cols-md-2>*{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.bootstrap .row-cols-md-3>*{-webkit-box-flex:0;-webkit-flex:0 0 33.33333%;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.bootstrap .row-cols-md-4>*{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.bootstrap .row-cols-md-5>*{-webkit-box-flex:0;-webkit-flex:0 0 20%;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.bootstrap .row-cols-md-6>*{-webkit-box-flex:0;-webkit-flex:0 0 16.66667%;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.bootstrap .col-md-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.bootstrap .col-md-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333%;-ms-flex:0 0 8.33333%;flex:0 0 8.33333%;max-width:8.33333%}.bootstrap .col-md-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66667%;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.bootstrap .col-md-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.bootstrap .col-md-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333%;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.bootstrap .col-md-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66667%;-ms-flex:0 0 41.66667%;flex:0 0 41.66667%;max-width:41.66667%}.bootstrap .col-md-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.bootstrap .col-md-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333%;-ms-flex:0 0 58.33333%;flex:0 0 58.33333%;max-width:58.33333%}.bootstrap .col-md-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66667%;-ms-flex:0 0 66.66667%;flex:0 0 66.66667%;max-width:66.66667%}.bootstrap .col-md-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.bootstrap .col-md-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333%;-ms-flex:0 0 83.33333%;flex:0 0 83.33333%;max-width:83.33333%}.bootstrap .col-md-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66667%;-ms-flex:0 0 91.66667%;flex:0 0 91.66667%;max-width:91.66667%}.bootstrap .col-md-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.bootstrap .order-md-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.bootstrap .order-md-last{-webkit-box-ordinal-group:14;-webkit-order:13;-ms-flex-order:13;order:13}.bootstrap .order-md-0{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.bootstrap .order-md-1{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.bootstrap .order-md-2{-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2}.bootstrap .order-md-3{-webkit-box-ordinal-group:4;-webkit-order:3;-ms-flex-order:3;order:3}.bootstrap .order-md-4{-webkit-box-ordinal-group:5;-webkit-order:4;-ms-flex-order:4;order:4}.bootstrap .order-md-5{-webkit-box-ordinal-group:6;-webkit-order:5;-ms-flex-order:5;order:5}.bootstrap .order-md-6{-webkit-box-ordinal-group:7;-webkit-order:6;-ms-flex-order:6;order:6}.bootstrap .order-md-7{-webkit-box-ordinal-group:8;-webkit-order:7;-ms-flex-order:7;order:7}.bootstrap .order-md-8{-webkit-box-ordinal-group:9;-webkit-order:8;-ms-flex-order:8;order:8}.bootstrap .order-md-9{-webkit-box-ordinal-group:10;-webkit-order:9;-ms-flex-order:9;order:9}.bootstrap .order-md-10{-webkit-box-ordinal-group:11;-webkit-order:10;-ms-flex-order:10;order:10}.bootstrap .order-md-11{-webkit-box-ordinal-group:12;-webkit-order:11;-ms-flex-order:11;order:11}.bootstrap .order-md-12{-webkit-box-ordinal-group:13;-webkit-order:12;-ms-flex-order:12;order:12}.bootstrap .offset-md-0{margin-left:0}.bootstrap .offset-md-1{margin-left:8.33333%}.bootstrap .offset-md-2{margin-left:16.66667%}.bootstrap .offset-md-3{margin-left:25%}.bootstrap .offset-md-4{margin-left:33.33333%}.bootstrap .offset-md-5{margin-left:41.66667%}.bootstrap .offset-md-6{margin-left:50%}.bootstrap .offset-md-7{margin-left:58.33333%}.bootstrap .offset-md-8{margin-left:66.66667%}.bootstrap .offset-md-9{margin-left:75%}.bootstrap .offset-md-10{margin-left:83.33333%}.bootstrap .offset-md-11{margin-left:91.66667%}}@media (min-width:992px){.bootstrap .col-lg{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.bootstrap .row-cols-lg-1>*{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.bootstrap .row-cols-lg-2>*{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.bootstrap .row-cols-lg-3>*{-webkit-box-flex:0;-webkit-flex:0 0 33.33333%;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.bootstrap .row-cols-lg-4>*{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.bootstrap .row-cols-lg-5>*{-webkit-box-flex:0;-webkit-flex:0 0 20%;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.bootstrap .row-cols-lg-6>*{-webkit-box-flex:0;-webkit-flex:0 0 16.66667%;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.bootstrap .col-lg-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.bootstrap .col-lg-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333%;-ms-flex:0 0 8.33333%;flex:0 0 8.33333%;max-width:8.33333%}.bootstrap .col-lg-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66667%;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.bootstrap .col-lg-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.bootstrap .col-lg-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333%;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.bootstrap .col-lg-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66667%;-ms-flex:0 0 41.66667%;flex:0 0 41.66667%;max-width:41.66667%}.bootstrap .col-lg-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.bootstrap .col-lg-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333%;-ms-flex:0 0 58.33333%;flex:0 0 58.33333%;max-width:58.33333%}.bootstrap .col-lg-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66667%;-ms-flex:0 0 66.66667%;flex:0 0 66.66667%;max-width:66.66667%}.bootstrap .col-lg-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.bootstrap .col-lg-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333%;-ms-flex:0 0 83.33333%;flex:0 0 83.33333%;max-width:83.33333%}.bootstrap .col-lg-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66667%;-ms-flex:0 0 91.66667%;flex:0 0 91.66667%;max-width:91.66667%}.bootstrap .col-lg-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.bootstrap .order-lg-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.bootstrap .order-lg-last{-webkit-box-ordinal-group:14;-webkit-order:13;-ms-flex-order:13;order:13}.bootstrap .order-lg-0{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.bootstrap .order-lg-1{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.bootstrap .order-lg-2{-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2}.bootstrap .order-lg-3{-webkit-box-ordinal-group:4;-webkit-order:3;-ms-flex-order:3;order:3}.bootstrap .order-lg-4{-webkit-box-ordinal-group:5;-webkit-order:4;-ms-flex-order:4;order:4}.bootstrap .order-lg-5{-webkit-box-ordinal-group:6;-webkit-order:5;-ms-flex-order:5;order:5}.bootstrap .order-lg-6{-webkit-box-ordinal-group:7;-webkit-order:6;-ms-flex-order:6;order:6}.bootstrap .order-lg-7{-webkit-box-ordinal-group:8;-webkit-order:7;-ms-flex-order:7;order:7}.bootstrap .order-lg-8{-webkit-box-ordinal-group:9;-webkit-order:8;-ms-flex-order:8;order:8}.bootstrap .order-lg-9{-webkit-box-ordinal-group:10;-webkit-order:9;-ms-flex-order:9;order:9}.bootstrap .order-lg-10{-webkit-box-ordinal-group:11;-webkit-order:10;-ms-flex-order:10;order:10}.bootstrap .order-lg-11{-webkit-box-ordinal-group:12;-webkit-order:11;-ms-flex-order:11;order:11}.bootstrap .order-lg-12{-webkit-box-ordinal-group:13;-webkit-order:12;-ms-flex-order:12;order:12}.bootstrap .offset-lg-0{margin-left:0}.bootstrap .offset-lg-1{margin-left:8.33333%}.bootstrap .offset-lg-2{margin-left:16.66667%}.bootstrap .offset-lg-3{margin-left:25%}.bootstrap .offset-lg-4{margin-left:33.33333%}.bootstrap .offset-lg-5{margin-left:41.66667%}.bootstrap .offset-lg-6{margin-left:50%}.bootstrap .offset-lg-7{margin-left:58.33333%}.bootstrap .offset-lg-8{margin-left:66.66667%}.bootstrap .offset-lg-9{margin-left:75%}.bootstrap .offset-lg-10{margin-left:83.33333%}.bootstrap .offset-lg-11{margin-left:91.66667%}}@media (min-width:1200px){.bootstrap .col-xl{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.bootstrap .row-cols-xl-1>*{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.bootstrap .row-cols-xl-2>*{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.bootstrap .row-cols-xl-3>*{-webkit-box-flex:0;-webkit-flex:0 0 33.33333%;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.bootstrap .row-cols-xl-4>*{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.bootstrap .row-cols-xl-5>*{-webkit-box-flex:0;-webkit-flex:0 0 20%;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.bootstrap .row-cols-xl-6>*{-webkit-box-flex:0;-webkit-flex:0 0 16.66667%;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.bootstrap .col-xl-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.bootstrap .col-xl-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333%;-ms-flex:0 0 8.33333%;flex:0 0 8.33333%;max-width:8.33333%}.bootstrap .col-xl-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66667%;-ms-flex:0 0 16.66667%;flex:0 0 16.66667%;max-width:16.66667%}.bootstrap .col-xl-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.bootstrap .col-xl-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333%;-ms-flex:0 0 33.33333%;flex:0 0 33.33333%;max-width:33.33333%}.bootstrap .col-xl-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66667%;-ms-flex:0 0 41.66667%;flex:0 0 41.66667%;max-width:41.66667%}.bootstrap .col-xl-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.bootstrap .col-xl-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333%;-ms-flex:0 0 58.33333%;flex:0 0 58.33333%;max-width:58.33333%}.bootstrap .col-xl-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66667%;-ms-flex:0 0 66.66667%;flex:0 0 66.66667%;max-width:66.66667%}.bootstrap .col-xl-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.bootstrap .col-xl-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333%;-ms-flex:0 0 83.33333%;flex:0 0 83.33333%;max-width:83.33333%}.bootstrap .col-xl-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66667%;-ms-flex:0 0 91.66667%;flex:0 0 91.66667%;max-width:91.66667%}.bootstrap .col-xl-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.bootstrap .order-xl-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.bootstrap .order-xl-last{-webkit-box-ordinal-group:14;-webkit-order:13;-ms-flex-order:13;order:13}.bootstrap .order-xl-0{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.bootstrap .order-xl-1{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.bootstrap .order-xl-2{-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2}.bootstrap .order-xl-3{-webkit-box-ordinal-group:4;-webkit-order:3;-ms-flex-order:3;order:3}.bootstrap .order-xl-4{-webkit-box-ordinal-group:5;-webkit-order:4;-ms-flex-order:4;order:4}.bootstrap .order-xl-5{-webkit-box-ordinal-group:6;-webkit-order:5;-ms-flex-order:5;order:5}.bootstrap .order-xl-6{-webkit-box-ordinal-group:7;-webkit-order:6;-ms-flex-order:6;order:6}.bootstrap .order-xl-7{-webkit-box-ordinal-group:8;-webkit-order:7;-ms-flex-order:7;order:7}.bootstrap .order-xl-8{-webkit-box-ordinal-group:9;-webkit-order:8;-ms-flex-order:8;order:8}.bootstrap .order-xl-9{-webkit-box-ordinal-group:10;-webkit-order:9;-ms-flex-order:9;order:9}.bootstrap .order-xl-10{-webkit-box-ordinal-group:11;-webkit-order:10;-ms-flex-order:10;order:10}.bootstrap .order-xl-11{-webkit-box-ordinal-group:12;-webkit-order:11;-ms-flex-order:11;order:11}.bootstrap .order-xl-12{-webkit-box-ordinal-group:13;-webkit-order:12;-ms-flex-order:12;order:12}.bootstrap .offset-xl-0{margin-left:0}.bootstrap .offset-xl-1{margin-left:8.33333%}.bootstrap .offset-xl-2{margin-left:16.66667%}.bootstrap .offset-xl-3{margin-left:25%}.bootstrap .offset-xl-4{margin-left:33.33333%}.bootstrap .offset-xl-5{margin-left:41.66667%}.bootstrap .offset-xl-6{margin-left:50%}.bootstrap .offset-xl-7{margin-left:58.33333%}.bootstrap .offset-xl-8{margin-left:66.66667%}.bootstrap .offset-xl-9{margin-left:75%}.bootstrap .offset-xl-10{margin-left:83.33333%}.bootstrap .offset-xl-11{margin-left:91.66667%}}.bootstrap .table{width:100%;margin-bottom:1rem;color:#212529}.bootstrap .table td,.bootstrap .table th{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.bootstrap .table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.bootstrap .table tbody+tbody{border-top:2px solid #dee2e6}.bootstrap .table-sm td,.bootstrap .table-sm th{padding:.3rem}.bootstrap .table-bordered{border:1px solid #dee2e6}.bootstrap .table-bordered td,.bootstrap .table-bordered th{border:1px solid #dee2e6}.bootstrap .table-bordered thead td,.bootstrap .table-bordered thead th{border-bottom-width:2px}.bootstrap .table-borderless tbody+tbody,.bootstrap .table-borderless td,.bootstrap .table-borderless th,.bootstrap .table-borderless thead th{border:0}.bootstrap .table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.bootstrap .table-hover tbody tr:hover{color:#212529;background-color:rgba(0,0,0,.075)}.bootstrap .table-primary,.bootstrap .table-primary>td,.bootstrap .table-primary>th{background-color:#b8daff}.bootstrap .table-primary tbody+tbody,.bootstrap .table-primary td,.bootstrap .table-primary th,.bootstrap .table-primary thead th{border-color:#7abaff}.bootstrap .table-hover .table-primary:hover{background-color:#9fcdff}.bootstrap .table-hover .table-primary:hover>td,.bootstrap .table-hover .table-primary:hover>th{background-color:#9fcdff}.bootstrap .table-secondary,.bootstrap .table-secondary>td,.bootstrap .table-secondary>th{background-color:#d6d8db}.bootstrap .table-secondary tbody+tbody,.bootstrap .table-secondary td,.bootstrap .table-secondary th,.bootstrap .table-secondary thead th{border-color:#b3b7bb}.bootstrap .table-hover .table-secondary:hover{background-color:#c8cbcf}.bootstrap .table-hover .table-secondary:hover>td,.bootstrap .table-hover .table-secondary:hover>th{background-color:#c8cbcf}.bootstrap .table-success,.bootstrap .table-success>td,.bootstrap .table-success>th{background-color:#c3e6cb}.bootstrap .table-success tbody+tbody,.bootstrap .table-success td,.bootstrap .table-success th,.bootstrap .table-success thead th{border-color:#8fd19e}.bootstrap .table-hover .table-success:hover{background-color:#b1dfbb}.bootstrap .table-hover .table-success:hover>td,.bootstrap .table-hover .table-success:hover>th{background-color:#b1dfbb}.bootstrap .table-info,.bootstrap .table-info>td,.bootstrap .table-info>th{background-color:#bee5eb}.bootstrap .table-info tbody+tbody,.bootstrap .table-info td,.bootstrap .table-info th,.bootstrap .table-info thead th{border-color:#86cfda}.bootstrap .table-hover .table-info:hover{background-color:#abdde5}.bootstrap .table-hover .table-info:hover>td,.bootstrap .table-hover .table-info:hover>th{background-color:#abdde5}.bootstrap .table-warning,.bootstrap .table-warning>td,.bootstrap .table-warning>th{background-color:#ffeeba}.bootstrap .table-warning tbody+tbody,.bootstrap .table-warning td,.bootstrap .table-warning th,.bootstrap .table-warning thead th{border-color:#ffdf7e}.bootstrap .table-hover .table-warning:hover{background-color:#ffe8a1}.bootstrap .table-hover .table-warning:hover>td,.bootstrap .table-hover .table-warning:hover>th{background-color:#ffe8a1}.bootstrap .table-danger,.bootstrap .table-danger>td,.bootstrap .table-danger>th{background-color:#f5c6cb}.bootstrap .table-danger tbody+tbody,.bootstrap .table-danger td,.bootstrap .table-danger th,.bootstrap .table-danger thead th{border-color:#ed969e}.bootstrap .table-hover .table-danger:hover{background-color:#f1b0b7}.bootstrap .table-hover .table-danger:hover>td,.bootstrap .table-hover .table-danger:hover>th{background-color:#f1b0b7}.bootstrap .table-light,.bootstrap .table-light>td,.bootstrap .table-light>th{background-color:#fdfdfe}.bootstrap .table-light tbody+tbody,.bootstrap .table-light td,.bootstrap .table-light th,.bootstrap .table-light thead th{border-color:#fbfcfc}.bootstrap .table-hover .table-light:hover{background-color:#ececf6}.bootstrap .table-hover .table-light:hover>td,.bootstrap .table-hover .table-light:hover>th{background-color:#ececf6}.bootstrap .table-dark,.bootstrap .table-dark>td,.bootstrap .table-dark>th{background-color:#c6c8ca}.bootstrap .table-dark tbody+tbody,.bootstrap .table-dark td,.bootstrap .table-dark th,.bootstrap .table-dark thead th{border-color:#95999c}.bootstrap .table-hover .table-dark:hover{background-color:#b9bbbe}.bootstrap .table-hover .table-dark:hover>td,.bootstrap .table-hover .table-dark:hover>th{background-color:#b9bbbe}.bootstrap .table-active,.bootstrap .table-active>td,.bootstrap .table-active>th{background-color:rgba(0,0,0,.075)}.bootstrap .table-hover .table-active:hover{background-color:rgba(0,0,0,.075)}.bootstrap .table-hover .table-active:hover>td,.bootstrap .table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.bootstrap .table .thead-dark th{color:#fff;background-color:#343a40;border-color:#454d55}.bootstrap .table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dee2e6}.bootstrap .table-dark{color:#fff;background-color:#343a40}.bootstrap .table-dark td,.bootstrap .table-dark th,.bootstrap .table-dark thead th{border-color:#454d55}.bootstrap .table-dark.table-bordered{border:0}.bootstrap .table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,.05)}.bootstrap .table-dark.table-hover tbody tr:hover{color:#fff;background-color:rgba(255,255,255,.075)}@media (max-width:575.98px){.bootstrap .table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.bootstrap .table-responsive-sm>.table-bordered{border:0}}@media (max-width:767.98px){.bootstrap .table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.bootstrap .table-responsive-md>.table-bordered{border:0}}@media (max-width:991.98px){.bootstrap .table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.bootstrap .table-responsive-lg>.table-bordered{border:0}}@media (max-width:1199.98px){.bootstrap .table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.bootstrap .table-responsive-xl>.table-bordered{border:0}}.bootstrap .table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.bootstrap .table-responsive>.table-bordered{border:0}.bootstrap .form-control{display:block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;-webkit-transition:border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.bootstrap .form-control{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap .form-control::-ms-expand{background-color:transparent;border:0}.bootstrap .form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.bootstrap .form-control:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(0,123,255,.25);box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.bootstrap .form-control::-webkit-input-placeholder{color:#6c757d;opacity:1}.bootstrap .form-control::-moz-placeholder{color:#6c757d;opacity:1}.bootstrap .form-control::-ms-input-placeholder{color:#6c757d;opacity:1}.bootstrap .form-control::placeholder{color:#6c757d;opacity:1}.bootstrap .form-control:disabled,.bootstrap .form-control[readonly]{background-color:#e9ecef;opacity:1}.bootstrap select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.bootstrap .form-control-file,.bootstrap .form-control-range{display:block;width:100%}.bootstrap .col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.bootstrap .col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.bootstrap .col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.bootstrap .form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;font-size:1rem;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.bootstrap .form-control-plaintext.form-control-lg,.bootstrap .form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.bootstrap .form-control-sm{height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.bootstrap .form-control-lg{height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.bootstrap select.form-control[multiple],.bootstrap select.form-control[size]{height:auto}.bootstrap textarea.form-control{height:auto}.bootstrap .form-group{margin-bottom:1rem}.bootstrap .form-text{display:block;margin-top:.25rem}.bootstrap .form-row{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.bootstrap .form-row>.col,.bootstrap .form-row>[class*=col-]{padding-right:5px;padding-left:5px}.bootstrap .form-check{position:relative;display:block;padding-left:1.25rem}.bootstrap .form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.bootstrap .form-check-input:disabled~.form-check-label,.bootstrap .form-check-input[disabled]~.form-check-label{color:#6c757d}.bootstrap .form-check-label{margin-bottom:0}.bootstrap .form-check-inline{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;padding-left:0;margin-right:.75rem}.bootstrap .form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.bootstrap .valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#28a745}.bootstrap .valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(40,167,69,.9);border-radius:.25rem}.bootstrap.is-valid~.valid-feedback,.bootstrap.is-valid~.valid-tooltip,.was-validated .bootstrap:valid~.valid-feedback,.was-validated .bootstrap:valid~.valid-tooltip{display:block}.bootstrap .form-control.is-valid,.was-validated .bootstrap .form-control:valid{border-color:#28a745;padding-right:calc(1.5em + .75rem);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");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;-webkit-background-size:calc(.75em + .375rem) calc(.75em + .375rem);background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.bootstrap .form-control.is-valid:focus,.was-validated .bootstrap .form-control:valid:focus{border-color:#28a745;-webkit-box-shadow:0 0 0 .2rem rgba(40,167,69,.25);box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.bootstrap textarea.form-control.is-valid,.was-validated .bootstrap textarea.form-control:valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.bootstrap .custom-select.is-valid,.was-validated .bootstrap .custom-select:valid{border-color:#28a745;padding-right:calc(.75em + 2.3125rem);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 .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(.75em + .375rem) calc(.75em + .375rem)}.bootstrap .custom-select.is-valid:focus,.was-validated .bootstrap .custom-select:valid:focus{border-color:#28a745;-webkit-box-shadow:0 0 0 .2rem rgba(40,167,69,.25);box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.bootstrap .form-check-input.is-valid~.form-check-label,.was-validated .bootstrap .form-check-input:valid~.form-check-label{color:#28a745}.bootstrap .form-check-input.is-valid~.valid-feedback,.bootstrap .form-check-input.is-valid~.valid-tooltip,.was-validated .bootstrap .form-check-input:valid~.valid-feedback,.was-validated .bootstrap .form-check-input:valid~.valid-tooltip{display:block}.bootstrap .custom-control-input.is-valid~.custom-control-label,.was-validated .bootstrap .custom-control-input:valid~.custom-control-label{color:#28a745}.bootstrap .custom-control-input.is-valid~.custom-control-label::before,.was-validated .bootstrap .custom-control-input:valid~.custom-control-label::before{border-color:#28a745}.bootstrap .custom-control-input.is-valid:checked~.custom-control-label::before,.was-validated .bootstrap .custom-control-input:valid:checked~.custom-control-label::before{border-color:#34ce57;background-color:#34ce57}.bootstrap .custom-control-input.is-valid:focus~.custom-control-label::before,.was-validated .bootstrap .custom-control-input:valid:focus~.custom-control-label::before{-webkit-box-shadow:0 0 0 .2rem rgba(40,167,69,.25);box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.bootstrap .custom-control-input.is-valid:focus:not(:checked)~.custom-control-label::before,.was-validated .bootstrap .custom-control-input:valid:focus:not(:checked)~.custom-control-label::before{border-color:#28a745}.bootstrap .custom-file-input.is-valid~.custom-file-label,.was-validated .bootstrap .custom-file-input:valid~.custom-file-label{border-color:#28a745}.bootstrap .custom-file-input.is-valid:focus~.custom-file-label,.was-validated .bootstrap .custom-file-input:valid:focus~.custom-file-label{border-color:#28a745;-webkit-box-shadow:0 0 0 .2rem rgba(40,167,69,.25);box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.bootstrap .invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#dc3545}.bootstrap .invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.25rem}.bootstrap.is-invalid~.invalid-feedback,.bootstrap.is-invalid~.invalid-tooltip,.was-validated .bootstrap:invalid~.invalid-feedback,.was-validated .bootstrap:invalid~.invalid-tooltip{display:block}.bootstrap .form-control.is-invalid,.was-validated .bootstrap .form-control:invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem);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");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;-webkit-background-size:calc(.75em + .375rem) calc(.75em + .375rem);background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.bootstrap .form-control.is-invalid:focus,.was-validated .bootstrap .form-control:invalid:focus{border-color:#dc3545;-webkit-box-shadow:0 0 0 .2rem rgba(220,53,69,.25);box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.bootstrap textarea.form-control.is-invalid,.was-validated .bootstrap textarea.form-control:invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.bootstrap .custom-select.is-invalid,.was-validated .bootstrap .custom-select:invalid{border-color:#dc3545;padding-right:calc(.75em + 2.3125rem);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 .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(.75em + .375rem) calc(.75em + .375rem)}.bootstrap .custom-select.is-invalid:focus,.was-validated .bootstrap .custom-select:invalid:focus{border-color:#dc3545;-webkit-box-shadow:0 0 0 .2rem rgba(220,53,69,.25);box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.bootstrap .form-check-input.is-invalid~.form-check-label,.was-validated .bootstrap .form-check-input:invalid~.form-check-label{color:#dc3545}.bootstrap .form-check-input.is-invalid~.invalid-feedback,.bootstrap .form-check-input.is-invalid~.invalid-tooltip,.was-validated .bootstrap .form-check-input:invalid~.invalid-feedback,.was-validated .bootstrap .form-check-input:invalid~.invalid-tooltip{display:block}.bootstrap .custom-control-input.is-invalid~.custom-control-label,.was-validated .bootstrap .custom-control-input:invalid~.custom-control-label{color:#dc3545}.bootstrap .custom-control-input.is-invalid~.custom-control-label::before,.was-validated .bootstrap .custom-control-input:invalid~.custom-control-label::before{border-color:#dc3545}.bootstrap .custom-control-input.is-invalid:checked~.custom-control-label::before,.was-validated .bootstrap .custom-control-input:invalid:checked~.custom-control-label::before{border-color:#e4606d;background-color:#e4606d}.bootstrap .custom-control-input.is-invalid:focus~.custom-control-label::before,.was-validated .bootstrap .custom-control-input:invalid:focus~.custom-control-label::before{-webkit-box-shadow:0 0 0 .2rem rgba(220,53,69,.25);box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.bootstrap .custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label::before,.was-validated .bootstrap .custom-control-input:invalid:focus:not(:checked)~.custom-control-label::before{border-color:#dc3545}.bootstrap .custom-file-input.is-invalid~.custom-file-label,.was-validated .bootstrap .custom-file-input:invalid~.custom-file-label{border-color:#dc3545}.bootstrap .custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .bootstrap .custom-file-input:invalid:focus~.custom-file-label{border-color:#dc3545;-webkit-box-shadow:0 0 0 .2rem rgba(220,53,69,.25);box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.bootstrap .form-inline{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.bootstrap .form-inline .form-check{width:100%}@media (min-width:576px){.bootstrap .form-inline label{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.bootstrap .form-inline .form-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;margin-bottom:0}.bootstrap .form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.bootstrap .form-inline .form-control-plaintext{display:inline-block}.bootstrap .form-inline .custom-select,.bootstrap .form-inline .input-group{width:auto}.bootstrap .form-inline .form-check{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;width:auto;padding-left:0}.bootstrap .form-inline .form-check-input{position:relative;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;margin-top:0;margin-right:.25rem;margin-left:0}.bootstrap .form-inline .custom-control{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.bootstrap .form-inline .custom-control-label{margin-bottom:0}}.bootstrap .btn{display:inline-block;font-weight:400;color:#212529;text-align:center;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;-webkit-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.bootstrap .btn{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap .btn:hover{color:#212529;text-decoration:none}.bootstrap .btn.focus,.bootstrap .btn:focus{outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(0,123,255,.25);box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.bootstrap .btn.disabled,.bootstrap .btn:disabled{opacity:.65}.bootstrap a.btn.disabled,.bootstrap fieldset:disabled a.btn{pointer-events:none}.bootstrap .btn-primary{color:#fff;background-color:#007bff;border-color:#007bff}.bootstrap .btn-primary:hover{color:#fff;background-color:#0069d9;border-color:#0062cc}.bootstrap .btn-primary.focus,.bootstrap .btn-primary:focus{color:#fff;background-color:#0069d9;border-color:#0062cc;-webkit-box-shadow:0 0 0 .2rem rgba(38,143,255,.5);box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.bootstrap .btn-primary.disabled,.bootstrap .btn-primary:disabled{color:#fff;background-color:#007bff;border-color:#007bff}.bootstrap .btn-primary:not(:disabled):not(.disabled).active,.bootstrap .btn-primary:not(:disabled):not(.disabled):active,.show>.bootstrap .btn-primary.dropdown-toggle{color:#fff;background-color:#0062cc;border-color:#005cbf}.bootstrap .btn-primary:not(:disabled):not(.disabled).active:focus,.bootstrap .btn-primary:not(:disabled):not(.disabled):active:focus,.show>.bootstrap .btn-primary.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(38,143,255,.5);box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.bootstrap .btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.bootstrap .btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.bootstrap .btn-secondary.focus,.bootstrap .btn-secondary:focus{color:#fff;background-color:#5a6268;border-color:#545b62;-webkit-box-shadow:0 0 0 .2rem rgba(130,138,145,.5);box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.bootstrap .btn-secondary.disabled,.bootstrap .btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.bootstrap .btn-secondary:not(:disabled):not(.disabled).active,.bootstrap .btn-secondary:not(:disabled):not(.disabled):active,.show>.bootstrap .btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.bootstrap .btn-secondary:not(:disabled):not(.disabled).active:focus,.bootstrap .btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.bootstrap .btn-secondary.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(130,138,145,.5);box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.bootstrap .btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.bootstrap .btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.bootstrap .btn-success.focus,.bootstrap .btn-success:focus{color:#fff;background-color:#218838;border-color:#1e7e34;-webkit-box-shadow:0 0 0 .2rem rgba(72,180,97,.5);box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.bootstrap .btn-success.disabled,.bootstrap .btn-success:disabled{color:#fff;background-color:#28a745;border-color:#28a745}.bootstrap .btn-success:not(:disabled):not(.disabled).active,.bootstrap .btn-success:not(:disabled):not(.disabled):active,.show>.bootstrap .btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430}.bootstrap .btn-success:not(:disabled):not(.disabled).active:focus,.bootstrap .btn-success:not(:disabled):not(.disabled):active:focus,.show>.bootstrap .btn-success.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(72,180,97,.5);box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.bootstrap .btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.bootstrap .btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.bootstrap .btn-info.focus,.bootstrap .btn-info:focus{color:#fff;background-color:#138496;border-color:#117a8b;-webkit-box-shadow:0 0 0 .2rem rgba(58,176,195,.5);box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.bootstrap .btn-info.disabled,.bootstrap .btn-info:disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.bootstrap .btn-info:not(:disabled):not(.disabled).active,.bootstrap .btn-info:not(:disabled):not(.disabled):active,.show>.bootstrap .btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.bootstrap .btn-info:not(:disabled):not(.disabled).active:focus,.bootstrap .btn-info:not(:disabled):not(.disabled):active:focus,.show>.bootstrap .btn-info.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(58,176,195,.5);box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.bootstrap .btn-warning{color:#212529;background-color:#ffc107;border-color:#ffc107}.bootstrap .btn-warning:hover{color:#212529;background-color:#e0a800;border-color:#d39e00}.bootstrap .btn-warning.focus,.bootstrap .btn-warning:focus{color:#212529;background-color:#e0a800;border-color:#d39e00;-webkit-box-shadow:0 0 0 .2rem rgba(222,170,12,.5);box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.bootstrap .btn-warning.disabled,.bootstrap .btn-warning:disabled{color:#212529;background-color:#ffc107;border-color:#ffc107}.bootstrap .btn-warning:not(:disabled):not(.disabled).active,.bootstrap .btn-warning:not(:disabled):not(.disabled):active,.show>.bootstrap .btn-warning.dropdown-toggle{color:#212529;background-color:#d39e00;border-color:#c69500}.bootstrap .btn-warning:not(:disabled):not(.disabled).active:focus,.bootstrap .btn-warning:not(:disabled):not(.disabled):active:focus,.show>.bootstrap .btn-warning.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(222,170,12,.5);box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.bootstrap .btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.bootstrap .btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.bootstrap .btn-danger.focus,.bootstrap .btn-danger:focus{color:#fff;background-color:#c82333;border-color:#bd2130;-webkit-box-shadow:0 0 0 .2rem rgba(225,83,97,.5);box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.bootstrap .btn-danger.disabled,.bootstrap .btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.bootstrap .btn-danger:not(:disabled):not(.disabled).active,.bootstrap .btn-danger:not(:disabled):not(.disabled):active,.show>.bootstrap .btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.bootstrap .btn-danger:not(:disabled):not(.disabled).active:focus,.bootstrap .btn-danger:not(:disabled):not(.disabled):active:focus,.show>.bootstrap .btn-danger.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(225,83,97,.5);box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.bootstrap .btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.bootstrap .btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.bootstrap .btn-light.focus,.bootstrap .btn-light:focus{color:#212529;background-color:#e2e6ea;border-color:#dae0e5;-webkit-box-shadow:0 0 0 .2rem rgba(216,217,219,.5);box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.bootstrap .btn-light.disabled,.bootstrap .btn-light:disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.bootstrap .btn-light:not(:disabled):not(.disabled).active,.bootstrap .btn-light:not(:disabled):not(.disabled):active,.show>.bootstrap .btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.bootstrap .btn-light:not(:disabled):not(.disabled).active:focus,.bootstrap .btn-light:not(:disabled):not(.disabled):active:focus,.show>.bootstrap .btn-light.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(216,217,219,.5);box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.bootstrap .btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.bootstrap .btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.bootstrap .btn-dark.focus,.bootstrap .btn-dark:focus{color:#fff;background-color:#23272b;border-color:#1d2124;-webkit-box-shadow:0 0 0 .2rem rgba(82,88,93,.5);box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.bootstrap .btn-dark.disabled,.bootstrap .btn-dark:disabled{color:#fff;background-color:#343a40;border-color:#343a40}.bootstrap .btn-dark:not(:disabled):not(.disabled).active,.bootstrap .btn-dark:not(:disabled):not(.disabled):active,.show>.bootstrap .btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.bootstrap .btn-dark:not(:disabled):not(.disabled).active:focus,.bootstrap .btn-dark:not(:disabled):not(.disabled):active:focus,.show>.bootstrap .btn-dark.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(82,88,93,.5);box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.bootstrap .btn-outline-primary{color:#007bff;border-color:#007bff}.bootstrap .btn-outline-primary:hover{color:#fff;background-color:#007bff;border-color:#007bff}.bootstrap .btn-outline-primary.focus,.bootstrap .btn-outline-primary:focus{-webkit-box-shadow:0 0 0 .2rem rgba(0,123,255,.5);box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.bootstrap .btn-outline-primary.disabled,.bootstrap .btn-outline-primary:disabled{color:#007bff;background-color:transparent}.bootstrap .btn-outline-primary:not(:disabled):not(.disabled).active,.bootstrap .btn-outline-primary:not(:disabled):not(.disabled):active,.show>.bootstrap .btn-outline-primary.dropdown-toggle{color:#fff;background-color:#007bff;border-color:#007bff}.bootstrap .btn-outline-primary:not(:disabled):not(.disabled).active:focus,.bootstrap .btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.bootstrap .btn-outline-primary.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(0,123,255,.5);box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.bootstrap .btn-outline-secondary{color:#6c757d;border-color:#6c757d}.bootstrap .btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.bootstrap .btn-outline-secondary.focus,.bootstrap .btn-outline-secondary:focus{-webkit-box-shadow:0 0 0 .2rem rgba(108,117,125,.5);box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.bootstrap .btn-outline-secondary.disabled,.bootstrap .btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.bootstrap .btn-outline-secondary:not(:disabled):not(.disabled).active,.bootstrap .btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.bootstrap .btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#6c757d}.bootstrap .btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.bootstrap .btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.bootstrap .btn-outline-secondary.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(108,117,125,.5);box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.bootstrap .btn-outline-success{color:#28a745;border-color:#28a745}.bootstrap .btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.bootstrap .btn-outline-success.focus,.bootstrap .btn-outline-success:focus{-webkit-box-shadow:0 0 0 .2rem rgba(40,167,69,.5);box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.bootstrap .btn-outline-success.disabled,.bootstrap .btn-outline-success:disabled{color:#28a745;background-color:transparent}.bootstrap .btn-outline-success:not(:disabled):not(.disabled).active,.bootstrap .btn-outline-success:not(:disabled):not(.disabled):active,.show>.bootstrap .btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.bootstrap .btn-outline-success:not(:disabled):not(.disabled).active:focus,.bootstrap .btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.bootstrap .btn-outline-success.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(40,167,69,.5);box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.bootstrap .btn-outline-info{color:#17a2b8;border-color:#17a2b8}.bootstrap .btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.bootstrap .btn-outline-info.focus,.bootstrap .btn-outline-info:focus{-webkit-box-shadow:0 0 0 .2rem rgba(23,162,184,.5);box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.bootstrap .btn-outline-info.disabled,.bootstrap .btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.bootstrap .btn-outline-info:not(:disabled):not(.disabled).active,.bootstrap .btn-outline-info:not(:disabled):not(.disabled):active,.show>.bootstrap .btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.bootstrap .btn-outline-info:not(:disabled):not(.disabled).active:focus,.bootstrap .btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.bootstrap .btn-outline-info.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(23,162,184,.5);box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.bootstrap .btn-outline-warning{color:#ffc107;border-color:#ffc107}.bootstrap .btn-outline-warning:hover{color:#212529;background-color:#ffc107;border-color:#ffc107}.bootstrap .btn-outline-warning.focus,.bootstrap .btn-outline-warning:focus{-webkit-box-shadow:0 0 0 .2rem rgba(255,193,7,.5);box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.bootstrap .btn-outline-warning.disabled,.bootstrap .btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.bootstrap .btn-outline-warning:not(:disabled):not(.disabled).active,.bootstrap .btn-outline-warning:not(:disabled):not(.disabled):active,.show>.bootstrap .btn-outline-warning.dropdown-toggle{color:#212529;background-color:#ffc107;border-color:#ffc107}.bootstrap .btn-outline-warning:not(:disabled):not(.disabled).active:focus,.bootstrap .btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.bootstrap .btn-outline-warning.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(255,193,7,.5);box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.bootstrap .btn-outline-danger{color:#dc3545;border-color:#dc3545}.bootstrap .btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.bootstrap .btn-outline-danger.focus,.bootstrap .btn-outline-danger:focus{-webkit-box-shadow:0 0 0 .2rem rgba(220,53,69,.5);box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.bootstrap .btn-outline-danger.disabled,.bootstrap .btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.bootstrap .btn-outline-danger:not(:disabled):not(.disabled).active,.bootstrap .btn-outline-danger:not(:disabled):not(.disabled):active,.show>.bootstrap .btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.bootstrap .btn-outline-danger:not(:disabled):not(.disabled).active:focus,.bootstrap .btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.bootstrap .btn-outline-danger.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(220,53,69,.5);box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.bootstrap .btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.bootstrap .btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.bootstrap .btn-outline-light.focus,.bootstrap .btn-outline-light:focus{-webkit-box-shadow:0 0 0 .2rem rgba(248,249,250,.5);box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.bootstrap .btn-outline-light.disabled,.bootstrap .btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.bootstrap .btn-outline-light:not(:disabled):not(.disabled).active,.bootstrap .btn-outline-light:not(:disabled):not(.disabled):active,.show>.bootstrap .btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.bootstrap .btn-outline-light:not(:disabled):not(.disabled).active:focus,.bootstrap .btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.bootstrap .btn-outline-light.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(248,249,250,.5);box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.bootstrap .btn-outline-dark{color:#343a40;border-color:#343a40}.bootstrap .btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.bootstrap .btn-outline-dark.focus,.bootstrap .btn-outline-dark:focus{-webkit-box-shadow:0 0 0 .2rem rgba(52,58,64,.5);box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.bootstrap .btn-outline-dark.disabled,.bootstrap .btn-outline-dark:disabled{color:#343a40;background-color:transparent}.bootstrap .btn-outline-dark:not(:disabled):not(.disabled).active,.bootstrap .btn-outline-dark:not(:disabled):not(.disabled):active,.show>.bootstrap .btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.bootstrap .btn-outline-dark:not(:disabled):not(.disabled).active:focus,.bootstrap .btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.bootstrap .btn-outline-dark.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 .2rem rgba(52,58,64,.5);box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.bootstrap .btn-link{font-weight:400;color:#007bff;text-decoration:none}.bootstrap .btn-link:hover{color:#0056b3;text-decoration:underline}.bootstrap .btn-link.focus,.bootstrap .btn-link:focus{text-decoration:underline;-webkit-box-shadow:none;box-shadow:none}.bootstrap .btn-link.disabled,.bootstrap .btn-link:disabled{color:#6c757d;pointer-events:none}.bootstrap .btn-group-lg>.btn,.bootstrap .btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.bootstrap .btn-group-sm>.btn,.bootstrap .btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.bootstrap .btn-block{display:block;width:100%}.bootstrap .btn-block+.btn-block{margin-top:.5rem}.bootstrap input[type=button].btn-block,.bootstrap input[type=reset].btn-block,.bootstrap input[type=submit].btn-block{width:100%}.bootstrap .fade{-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.bootstrap .fade{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap .fade:not(.show){opacity:0}.bootstrap .collapse:not(.show){display:none}.bootstrap .collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.bootstrap .collapsing{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap .dropdown,.bootstrap .dropleft,.bootstrap .dropright,.bootstrap .dropup{position:relative}.bootstrap .dropdown-toggle{white-space:nowrap}.bootstrap .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.bootstrap .dropdown-toggle:empty::after{margin-left:0}.bootstrap .dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.bootstrap .dropdown-menu-left{right:auto;left:0}.bootstrap .dropdown-menu-right{right:0;left:auto}@media (min-width:576px){.bootstrap .dropdown-menu-sm-left{right:auto;left:0}.bootstrap .dropdown-menu-sm-right{right:0;left:auto}}@media (min-width:768px){.bootstrap .dropdown-menu-md-left{right:auto;left:0}.bootstrap .dropdown-menu-md-right{right:0;left:auto}}@media (min-width:992px){.bootstrap .dropdown-menu-lg-left{right:auto;left:0}.bootstrap .dropdown-menu-lg-right{right:0;left:auto}}@media (min-width:1200px){.bootstrap .dropdown-menu-xl-left{right:auto;left:0}.bootstrap .dropdown-menu-xl-right{right:0;left:auto}}.bootstrap .dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.bootstrap .dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.bootstrap .dropup .dropdown-toggle:empty::after{margin-left:0}.bootstrap .dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.bootstrap .dropright .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.bootstrap .dropright .dropdown-toggle:empty::after{margin-left:0}.bootstrap .dropright .dropdown-toggle::after{vertical-align:0}.bootstrap .dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.bootstrap .dropleft .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.bootstrap .dropleft .dropdown-toggle::after{display:none}.bootstrap .dropleft .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.bootstrap .dropleft .dropdown-toggle:empty::after{margin-left:0}.bootstrap .dropleft .dropdown-toggle::before{vertical-align:0}.bootstrap .dropdown-menu[x-placement^=bottom],.bootstrap .dropdown-menu[x-placement^=left],.bootstrap .dropdown-menu[x-placement^=right],.bootstrap .dropdown-menu[x-placement^=top]{right:auto;bottom:auto}.bootstrap .dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.bootstrap .dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#212529;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.bootstrap .dropdown-item:focus,.bootstrap .dropdown-item:hover{color:#16181b;text-decoration:none;background-color:#f8f9fa}.bootstrap .dropdown-item.active,.bootstrap .dropdown-item:active{color:#fff;text-decoration:none;background-color:#007bff}.bootstrap .dropdown-item.disabled,.bootstrap .dropdown-item:disabled{color:#6c757d;pointer-events:none;background-color:transparent}.bootstrap .dropdown-menu.show{display:block}.bootstrap .dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.bootstrap .dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#212529}.bootstrap .btn-group,.bootstrap .btn-group-vertical{position:relative;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.bootstrap .btn-group-vertical>.btn,.bootstrap .btn-group>.btn{position:relative;-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.bootstrap .btn-group-vertical>.btn:hover,.bootstrap .btn-group>.btn:hover{z-index:1}.bootstrap .btn-group-vertical>.btn.active,.bootstrap .btn-group-vertical>.btn:active,.bootstrap .btn-group-vertical>.btn:focus,.bootstrap .btn-group>.btn.active,.bootstrap .btn-group>.btn:active,.bootstrap .btn-group>.btn:focus{z-index:1}.bootstrap .btn-toolbar{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.bootstrap .btn-toolbar .input-group{width:auto}.bootstrap .btn-group>.btn-group:not(:first-child),.bootstrap .btn-group>.btn:not(:first-child){margin-left:-1px}.bootstrap .btn-group>.btn-group:not(:last-child)>.btn,.bootstrap .btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.bootstrap .btn-group>.btn-group:not(:first-child)>.btn,.bootstrap .btn-group>.btn:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.bootstrap .dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.bootstrap .dropdown-toggle-split::after,.dropright .bootstrap .dropdown-toggle-split::after,.dropup .bootstrap .dropdown-toggle-split::after{margin-left:0}.dropleft .bootstrap .dropdown-toggle-split::before{margin-right:0}.bootstrap .btn-group-sm>.btn+.dropdown-toggle-split,.bootstrap .btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.bootstrap .btn-group-lg>.btn+.dropdown-toggle-split,.bootstrap .btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.bootstrap .btn-group-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.bootstrap .btn-group-vertical>.btn,.bootstrap .btn-group-vertical>.btn-group{width:100%}.bootstrap .btn-group-vertical>.btn-group:not(:first-child),.bootstrap .btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.bootstrap .btn-group-vertical>.btn-group:not(:last-child)>.btn,.bootstrap .btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.bootstrap .btn-group-vertical>.btn-group:not(:first-child)>.btn,.bootstrap .btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.bootstrap .btn-group-toggle>.btn,.bootstrap .btn-group-toggle>.btn-group>.btn{margin-bottom:0}.bootstrap .btn-group-toggle>.btn input[type=checkbox],.bootstrap .btn-group-toggle>.btn input[type=radio],.bootstrap .btn-group-toggle>.btn-group>.btn input[type=checkbox],.bootstrap .btn-group-toggle>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.bootstrap .input-group{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch;width:100%}.bootstrap .input-group>.custom-file,.bootstrap .input-group>.custom-select,.bootstrap .input-group>.form-control,.bootstrap .input-group>.form-control-plaintext{position:relative;-webkit-box-flex:1;-webkit-flex:1 1 0%;-ms-flex:1 1 0%;flex:1 1 0%;min-width:0;margin-bottom:0}.bootstrap .input-group>.custom-file+.custom-file,.bootstrap .input-group>.custom-file+.custom-select,.bootstrap .input-group>.custom-file+.form-control,.bootstrap .input-group>.custom-select+.custom-file,.bootstrap .input-group>.custom-select+.custom-select,.bootstrap .input-group>.custom-select+.form-control,.bootstrap .input-group>.form-control+.custom-file,.bootstrap .input-group>.form-control+.custom-select,.bootstrap .input-group>.form-control+.form-control,.bootstrap .input-group>.form-control-plaintext+.custom-file,.bootstrap .input-group>.form-control-plaintext+.custom-select,.bootstrap .input-group>.form-control-plaintext+.form-control{margin-left:-1px}.bootstrap .input-group>.custom-file .custom-file-input:focus~.custom-file-label,.bootstrap .input-group>.custom-select:focus,.bootstrap .input-group>.form-control:focus{z-index:3}.bootstrap .input-group>.custom-file .custom-file-input:focus{z-index:4}.bootstrap .input-group>.custom-select:not(:last-child),.bootstrap .input-group>.form-control:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.bootstrap .input-group>.custom-select:not(:first-child),.bootstrap .input-group>.form-control:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.bootstrap .input-group>.custom-file{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.bootstrap .input-group>.custom-file:not(:last-child) .custom-file-label,.bootstrap .input-group>.custom-file:not(:last-child) .custom-file-label::after{border-top-right-radius:0;border-bottom-right-radius:0}.bootstrap .input-group>.custom-file:not(:first-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.bootstrap .input-group-append,.bootstrap .input-group-prepend{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.bootstrap .input-group-append .btn,.bootstrap .input-group-prepend .btn{position:relative;z-index:2}.bootstrap .input-group-append .btn:focus,.bootstrap .input-group-prepend .btn:focus{z-index:3}.bootstrap .input-group-append .btn+.btn,.bootstrap .input-group-append .btn+.input-group-text,.bootstrap .input-group-append .input-group-text+.btn,.bootstrap .input-group-append .input-group-text+.input-group-text,.bootstrap .input-group-prepend .btn+.btn,.bootstrap .input-group-prepend .btn+.input-group-text,.bootstrap .input-group-prepend .input-group-text+.btn,.bootstrap .input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.bootstrap .input-group-prepend{margin-right:-1px}.bootstrap .input-group-append{margin-left:-1px}.bootstrap .input-group-text{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.bootstrap .input-group-text input[type=checkbox],.bootstrap .input-group-text input[type=radio]{margin-top:0}.bootstrap .input-group-lg>.custom-select,.bootstrap .input-group-lg>.form-control:not(textarea){height:calc(1.5em + 1rem + 2px)}.bootstrap .input-group-lg>.custom-select,.bootstrap .input-group-lg>.form-control,.bootstrap .input-group-lg>.input-group-append>.btn,.bootstrap .input-group-lg>.input-group-append>.input-group-text,.bootstrap .input-group-lg>.input-group-prepend>.btn,.bootstrap .input-group-lg>.input-group-prepend>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.bootstrap .input-group-sm>.custom-select,.bootstrap .input-group-sm>.form-control:not(textarea){height:calc(1.5em + .5rem + 2px)}.bootstrap .input-group-sm>.custom-select,.bootstrap .input-group-sm>.form-control,.bootstrap .input-group-sm>.input-group-append>.btn,.bootstrap .input-group-sm>.input-group-append>.input-group-text,.bootstrap .input-group-sm>.input-group-prepend>.btn,.bootstrap .input-group-sm>.input-group-prepend>.input-group-text{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.bootstrap .input-group-lg>.custom-select,.bootstrap .input-group-sm>.custom-select{padding-right:1.75rem}.bootstrap .input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.bootstrap .input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.bootstrap .input-group>.input-group-append:not(:last-child)>.btn,.bootstrap .input-group>.input-group-append:not(:last-child)>.input-group-text,.bootstrap .input-group>.input-group-prepend>.btn,.bootstrap .input-group>.input-group-prepend>.input-group-text{border-top-right-radius:0;border-bottom-right-radius:0}.bootstrap .input-group>.input-group-append>.btn,.bootstrap .input-group>.input-group-append>.input-group-text,.bootstrap .input-group>.input-group-prepend:first-child>.btn:not(:first-child),.bootstrap .input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.bootstrap .input-group>.input-group-prepend:not(:first-child)>.btn,.bootstrap .input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-top-left-radius:0;border-bottom-left-radius:0}.bootstrap .custom-control{position:relative;display:block;min-height:1.5rem;padding-left:1.5rem}.bootstrap .custom-control-inline{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;margin-right:1rem}.bootstrap .custom-control-input{position:absolute;left:0;z-index:-1;width:1rem;height:1.25rem;opacity:0}.bootstrap .custom-control-input:checked~.custom-control-label::before{color:#fff;border-color:#007bff;background-color:#007bff}.bootstrap .custom-control-input:focus~.custom-control-label::before{-webkit-box-shadow:0 0 0 .2rem rgba(0,123,255,.25);box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.bootstrap .custom-control-input:focus:not(:checked)~.custom-control-label::before{border-color:#80bdff}.bootstrap .custom-control-input:not(:disabled):active~.custom-control-label::before{color:#fff;background-color:#b3d7ff;border-color:#b3d7ff}.bootstrap .custom-control-input:disabled~.custom-control-label,.bootstrap .custom-control-input[disabled]~.custom-control-label{color:#6c757d}.bootstrap .custom-control-input:disabled~.custom-control-label::before,.bootstrap .custom-control-input[disabled]~.custom-control-label::before{background-color:#e9ecef}.bootstrap .custom-control-label{position:relative;margin-bottom:0;vertical-align:top}.bootstrap .custom-control-label::before{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;pointer-events:none;content:"";background-color:#fff;border:#adb5bd solid 1px}.bootstrap .custom-control-label::after{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:"";background:no-repeat 50%/50% 50%}.bootstrap .custom-checkbox .custom-control-label::before{border-radius:.25rem}.bootstrap .custom-checkbox .custom-control-input:checked~.custom-control-label::after{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")}.bootstrap .custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before{border-color:#007bff;background-color:#007bff}.bootstrap .custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after{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")}.bootstrap .custom-checkbox .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.bootstrap .custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.bootstrap .custom-radio .custom-control-label::before{border-radius:50%}.bootstrap .custom-radio .custom-control-input:checked~.custom-control-label::after{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")}.bootstrap .custom-radio .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.bootstrap .custom-switch{padding-left:2.25rem}.bootstrap .custom-switch .custom-control-label::before{left:-2.25rem;width:1.75rem;pointer-events:all;border-radius:.5rem}.bootstrap .custom-switch .custom-control-label::after{top:calc(.25rem + 2px);left:calc(-2.25rem + 2px);width:calc(1rem - 4px);height:calc(1rem - 4px);background-color:#adb5bd;border-radius:.5rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-transform .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-transform .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-o-transform .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out,-o-transform .15s ease-in-out,-webkit-box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.bootstrap .custom-switch .custom-control-label::after{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap .custom-switch .custom-control-input:checked~.custom-control-label::after{background-color:#fff;-webkit-transform:translateX(.75rem);-o-transform:translateX(.75rem);transform:translateX(.75rem)}.bootstrap .custom-switch .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.bootstrap .custom-select{display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem 1.75rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;vertical-align:middle;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 .75rem center/8px 10px;border:1px solid #ced4da;border-radius:.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.bootstrap .custom-select:focus{border-color:#80bdff;outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(0,123,255,.25);box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.bootstrap .custom-select:focus::-ms-value{color:#495057;background-color:#fff}.bootstrap .custom-select[multiple],.bootstrap .custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.bootstrap .custom-select:disabled{color:#6c757d;background-color:#e9ecef}.bootstrap .custom-select::-ms-expand{display:none}.bootstrap .custom-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.bootstrap .custom-select-sm{height:calc(1.5em + .5rem + 2px);padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.bootstrap .custom-select-lg{height:calc(1.5em + 1rem + 2px);padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.bootstrap .custom-file{position:relative;display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);margin-bottom:0}.bootstrap .custom-file-input{position:relative;z-index:2;width:100%;height:calc(1.5em + .75rem + 2px);margin:0;opacity:0}.bootstrap .custom-file-input:focus~.custom-file-label{border-color:#80bdff;-webkit-box-shadow:0 0 0 .2rem rgba(0,123,255,.25);box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.bootstrap .custom-file-input:disabled~.custom-file-label,.bootstrap .custom-file-input[disabled]~.custom-file-label{background-color:#e9ecef}.bootstrap .custom-file-input:lang(en)~.custom-file-label::after{content:"Browse"}.bootstrap .custom-file-input~.custom-file-label[data-browse]::after{content:attr(data-browse)}.bootstrap .custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.bootstrap .custom-file-label::after{position:absolute;top:0;right:0;bottom:0;z-index:3;display:block;height:calc(1.5em + .75rem);padding:.375rem .75rem;line-height:1.5;color:#495057;content:"Browse";background-color:#e9ecef;border-left:inherit;border-radius:0 .25rem .25rem 0}.bootstrap .custom-range{width:100%;height:1.4rem;padding:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.bootstrap .custom-range:focus{outline:0}.bootstrap .custom-range:focus::-webkit-slider-thumb{-webkit-box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25);box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.bootstrap .custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.bootstrap .custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.bootstrap .custom-range::-moz-focus-outer{border:0}.bootstrap .custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#007bff;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.bootstrap .custom-range::-webkit-slider-thumb{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap .custom-range::-webkit-slider-thumb:active{background-color:#b3d7ff}.bootstrap .custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.bootstrap .custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#007bff;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.bootstrap .custom-range::-moz-range-thumb{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap .custom-range::-moz-range-thumb:active{background-color:#b3d7ff}.bootstrap .custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.bootstrap .custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background-color:#007bff;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion:reduce){.bootstrap .custom-range::-ms-thumb{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap .custom-range::-ms-thumb:active{background-color:#b3d7ff}.bootstrap .custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem}.bootstrap .custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.bootstrap .custom-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.bootstrap .custom-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.bootstrap .custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.bootstrap .custom-range:disabled::-moz-range-thumb{background-color:#adb5bd}.bootstrap .custom-range:disabled::-moz-range-track{cursor:default}.bootstrap .custom-range:disabled::-ms-thumb{background-color:#adb5bd}.bootstrap .custom-control-label::before,.bootstrap .custom-file-label,.bootstrap .custom-select{-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.bootstrap .custom-control-label::before,.bootstrap .custom-file-label,.bootstrap .custom-select{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap .nav{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.bootstrap .nav-link{display:block;padding:.5rem 1rem}.bootstrap .nav-link:focus,.bootstrap .nav-link:hover{text-decoration:none}.bootstrap .nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.bootstrap .nav-tabs{border-bottom:1px solid #dee2e6}.bootstrap .nav-tabs .nav-item{margin-bottom:-1px}.bootstrap .nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.bootstrap .nav-tabs .nav-link:focus,.bootstrap .nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #dee2e6}.bootstrap .nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.bootstrap .nav-tabs .nav-item.show .nav-link,.bootstrap .nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.bootstrap .nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.bootstrap .nav-pills .nav-link{border-radius:.25rem}.bootstrap .nav-pills .nav-link.active,.bootstrap .nav-pills .show>.nav-link{color:#fff;background-color:#007bff}.bootstrap .nav-fill .nav-item{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.bootstrap .nav-justified .nav-item{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;text-align:center}.bootstrap .tab-content>.tab-pane{display:none}.bootstrap .tab-content>.active{display:block}.bootstrap .navbar{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;padding:.5rem 1rem}.bootstrap .navbar .container,.bootstrap .navbar .container-fluid,.bootstrap .navbar .container-lg,.bootstrap .navbar .container-md,.bootstrap .navbar .container-sm,.bootstrap .navbar .container-xl{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.bootstrap .navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.bootstrap .navbar-brand:focus,.bootstrap .navbar-brand:hover{text-decoration:none}.bootstrap .navbar-nav{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.bootstrap .navbar-nav .nav-link{padding-right:0;padding-left:0}.bootstrap .navbar-nav .dropdown-menu{position:static;float:none}.bootstrap .navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.bootstrap .navbar-collapse{-webkit-flex-basis:100%;-ms-flex-preferred-size:100%;flex-basis:100%;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.bootstrap .navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.bootstrap .navbar-toggler:focus,.bootstrap .navbar-toggler:hover{text-decoration:none}.bootstrap .navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:no-repeat center center;-webkit-background-size:100% 100%;background-size:100% 100%}@media (max-width:575.98px){.bootstrap .navbar-expand-sm>.container,.bootstrap .navbar-expand-sm>.container-fluid,.bootstrap .navbar-expand-sm>.container-lg,.bootstrap .navbar-expand-sm>.container-md,.bootstrap .navbar-expand-sm>.container-sm,.bootstrap .navbar-expand-sm>.container-xl{padding-right:0;padding-left:0}}@media (min-width:576px){.bootstrap .navbar-expand-sm{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.bootstrap .navbar-expand-sm .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.bootstrap .navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.bootstrap .navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.bootstrap .navbar-expand-sm>.container,.bootstrap .navbar-expand-sm>.container-fluid,.bootstrap .navbar-expand-sm>.container-lg,.bootstrap .navbar-expand-sm>.container-md,.bootstrap .navbar-expand-sm>.container-sm,.bootstrap .navbar-expand-sm>.container-xl{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.bootstrap .navbar-expand-sm .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;-webkit-flex-basis:auto;-ms-flex-preferred-size:auto;flex-basis:auto}.bootstrap .navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:767.98px){.bootstrap .navbar-expand-md>.container,.bootstrap .navbar-expand-md>.container-fluid,.bootstrap .navbar-expand-md>.container-lg,.bootstrap .navbar-expand-md>.container-md,.bootstrap .navbar-expand-md>.container-sm,.bootstrap .navbar-expand-md>.container-xl{padding-right:0;padding-left:0}}@media (min-width:768px){.bootstrap .navbar-expand-md{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.bootstrap .navbar-expand-md .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.bootstrap .navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.bootstrap .navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.bootstrap .navbar-expand-md>.container,.bootstrap .navbar-expand-md>.container-fluid,.bootstrap .navbar-expand-md>.container-lg,.bootstrap .navbar-expand-md>.container-md,.bootstrap .navbar-expand-md>.container-sm,.bootstrap .navbar-expand-md>.container-xl{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.bootstrap .navbar-expand-md .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;-webkit-flex-basis:auto;-ms-flex-preferred-size:auto;flex-basis:auto}.bootstrap .navbar-expand-md .navbar-toggler{display:none}}@media (max-width:991.98px){.bootstrap .navbar-expand-lg>.container,.bootstrap .navbar-expand-lg>.container-fluid,.bootstrap .navbar-expand-lg>.container-lg,.bootstrap .navbar-expand-lg>.container-md,.bootstrap .navbar-expand-lg>.container-sm,.bootstrap .navbar-expand-lg>.container-xl{padding-right:0;padding-left:0}}@media (min-width:992px){.bootstrap .navbar-expand-lg{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.bootstrap .navbar-expand-lg .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.bootstrap .navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.bootstrap .navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.bootstrap .navbar-expand-lg>.container,.bootstrap .navbar-expand-lg>.container-fluid,.bootstrap .navbar-expand-lg>.container-lg,.bootstrap .navbar-expand-lg>.container-md,.bootstrap .navbar-expand-lg>.container-sm,.bootstrap .navbar-expand-lg>.container-xl{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.bootstrap .navbar-expand-lg .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;-webkit-flex-basis:auto;-ms-flex-preferred-size:auto;flex-basis:auto}.bootstrap .navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:1199.98px){.bootstrap .navbar-expand-xl>.container,.bootstrap .navbar-expand-xl>.container-fluid,.bootstrap .navbar-expand-xl>.container-lg,.bootstrap .navbar-expand-xl>.container-md,.bootstrap .navbar-expand-xl>.container-sm,.bootstrap .navbar-expand-xl>.container-xl{padding-right:0;padding-left:0}}@media (min-width:1200px){.bootstrap .navbar-expand-xl{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.bootstrap .navbar-expand-xl .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.bootstrap .navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.bootstrap .navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.bootstrap .navbar-expand-xl>.container,.bootstrap .navbar-expand-xl>.container-fluid,.bootstrap .navbar-expand-xl>.container-lg,.bootstrap .navbar-expand-xl>.container-md,.bootstrap .navbar-expand-xl>.container-sm,.bootstrap .navbar-expand-xl>.container-xl{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.bootstrap .navbar-expand-xl .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;-webkit-flex-basis:auto;-ms-flex-preferred-size:auto;flex-basis:auto}.bootstrap .navbar-expand-xl .navbar-toggler{display:none}}.bootstrap .navbar-expand{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.bootstrap .navbar-expand>.container,.bootstrap .navbar-expand>.container-fluid,.bootstrap .navbar-expand>.container-lg,.bootstrap .navbar-expand>.container-md,.bootstrap .navbar-expand>.container-sm,.bootstrap .navbar-expand>.container-xl{padding-right:0;padding-left:0}.bootstrap .navbar-expand .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.bootstrap .navbar-expand .navbar-nav .dropdown-menu{position:absolute}.bootstrap .navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.bootstrap .navbar-expand>.container,.bootstrap .navbar-expand>.container-fluid,.bootstrap .navbar-expand>.container-lg,.bootstrap .navbar-expand>.container-md,.bootstrap .navbar-expand>.container-sm,.bootstrap .navbar-expand>.container-xl{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.bootstrap .navbar-expand .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;-webkit-flex-basis:auto;-ms-flex-preferred-size:auto;flex-basis:auto}.bootstrap .navbar-expand .navbar-toggler{display:none}.bootstrap .navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.bootstrap .navbar-light .navbar-brand:focus,.bootstrap .navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.bootstrap .navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.bootstrap .navbar-light .navbar-nav .nav-link:focus,.bootstrap .navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.bootstrap .navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.bootstrap .navbar-light .navbar-nav .active>.nav-link,.bootstrap .navbar-light .navbar-nav .nav-link.active,.bootstrap .navbar-light .navbar-nav .nav-link.show,.bootstrap .navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.bootstrap .navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.bootstrap .navbar-light .navbar-toggler-icon{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(0, 0, 0, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.bootstrap .navbar-light .navbar-text{color:rgba(0,0,0,.5)}.bootstrap .navbar-light .navbar-text a{color:rgba(0,0,0,.9)}.bootstrap .navbar-light .navbar-text a:focus,.bootstrap .navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.bootstrap .navbar-dark .navbar-brand{color:#fff}.bootstrap .navbar-dark .navbar-brand:focus,.bootstrap .navbar-dark .navbar-brand:hover{color:#fff}.bootstrap .navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.bootstrap .navbar-dark .navbar-nav .nav-link:focus,.bootstrap .navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.bootstrap .navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.bootstrap .navbar-dark .navbar-nav .active>.nav-link,.bootstrap .navbar-dark .navbar-nav .nav-link.active,.bootstrap .navbar-dark .navbar-nav .nav-link.show,.bootstrap .navbar-dark .navbar-nav .show>.nav-link{color:#fff}.bootstrap .navbar-dark .navbar-toggler{color:rgba(255,255,255,.5);border-color:rgba(255,255,255,.1)}.bootstrap .navbar-dark .navbar-toggler-icon{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(255, 255, 255, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.bootstrap .navbar-dark .navbar-text{color:rgba(255,255,255,.5)}.bootstrap .navbar-dark .navbar-text a{color:#fff}.bootstrap .navbar-dark .navbar-text a:focus,.bootstrap .navbar-dark .navbar-text a:hover{color:#fff}.bootstrap .card{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;-webkit-background-clip:border-box;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.bootstrap .card>hr{margin-right:0;margin-left:0}.bootstrap .card>.list-group:first-child .list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.bootstrap .card>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.bootstrap .card-body{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;min-height:1px;padding:1.25rem}.bootstrap .card-title{margin-bottom:.75rem}.bootstrap .card-subtitle{margin-top:-.375rem;margin-bottom:0}.bootstrap .card-text:last-child{margin-bottom:0}.bootstrap .card-link:hover{text-decoration:none}.bootstrap .card-link+.card-link{margin-left:1.25rem}.bootstrap .card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.bootstrap .card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.bootstrap .card-header+.list-group .list-group-item:first-child{border-top:0}.bootstrap .card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.bootstrap .card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.bootstrap .card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.bootstrap .card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.bootstrap .card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.bootstrap .card-img,.bootstrap .card-img-bottom,.bootstrap .card-img-top{-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;width:100%}.bootstrap .card-img,.bootstrap .card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.bootstrap .card-img,.bootstrap .card-img-bottom{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.bootstrap .card-deck .card{margin-bottom:15px}@media (min-width:576px){.bootstrap .card-deck{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.bootstrap .card-deck .card{-webkit-box-flex:1;-webkit-flex:1 0 0%;-ms-flex:1 0 0%;flex:1 0 0%;margin-right:15px;margin-bottom:0;margin-left:15px}}.bootstrap .card-group>.card{margin-bottom:15px}@media (min-width:576px){.bootstrap .card-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap}.bootstrap .card-group>.card{-webkit-box-flex:1;-webkit-flex:1 0 0%;-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.bootstrap .card-group>.card+.card{margin-left:0;border-left:0}.bootstrap .card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.bootstrap .card-group>.card:not(:last-child) .card-header,.bootstrap .card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.bootstrap .card-group>.card:not(:last-child) .card-footer,.bootstrap .card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.bootstrap .card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.bootstrap .card-group>.card:not(:first-child) .card-header,.bootstrap .card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.bootstrap .card-group>.card:not(:first-child) .card-footer,.bootstrap .card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.bootstrap .card-columns .card{margin-bottom:.75rem}@media (min-width:576px){.bootstrap .card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.bootstrap .card-columns .card{display:inline-block;width:100%}}.bootstrap .accordion>.card{overflow:hidden}.bootstrap .accordion>.card:not(:last-of-type){border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.bootstrap .accordion>.card:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.bootstrap .accordion>.card>.card-header{border-radius:0;margin-bottom:-1px}.bootstrap .breadcrumb{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#e9ecef;border-radius:.25rem}.bootstrap .breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.bootstrap .breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:.5rem;color:#6c757d;content:"/"}.bootstrap .breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.bootstrap .breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.bootstrap .breadcrumb-item.active{color:#6c757d}.bootstrap .pagination{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding-left:0;list-style:none;border-radius:.25rem}.bootstrap .page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#007bff;background-color:#fff;border:1px solid #dee2e6}.bootstrap .page-link:hover{z-index:2;color:#0056b3;text-decoration:none;background-color:#e9ecef;border-color:#dee2e6}.bootstrap .page-link:focus{z-index:3;outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(0,123,255,.25);box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.bootstrap .page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.bootstrap .page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.bootstrap .page-item.active .page-link{z-index:3;color:#fff;background-color:#007bff;border-color:#007bff}.bootstrap .page-item.disabled .page-link{color:#6c757d;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.bootstrap .pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.bootstrap .pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.bootstrap .pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.bootstrap .pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.bootstrap .pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.bootstrap .pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.bootstrap .badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem;-webkit-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.bootstrap .badge{-webkit-transition:none;-o-transition:none;transition:none}}a.bootstrap .badge:focus,a.bootstrap .badge:hover{text-decoration:none}.bootstrap .badge:empty{display:none}.bootstrap .btn .badge{position:relative;top:-1px}.bootstrap .badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.bootstrap .badge-primary{color:#fff;background-color:#007bff}a.bootstrap .badge-primary:focus,a.bootstrap .badge-primary:hover{color:#fff;background-color:#0062cc}a.bootstrap .badge-primary.focus,a.bootstrap .badge-primary:focus{outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(0,123,255,.5);box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.bootstrap .badge-secondary{color:#fff;background-color:#6c757d}a.bootstrap .badge-secondary:focus,a.bootstrap .badge-secondary:hover{color:#fff;background-color:#545b62}a.bootstrap .badge-secondary.focus,a.bootstrap .badge-secondary:focus{outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(108,117,125,.5);box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.bootstrap .badge-success{color:#fff;background-color:#28a745}a.bootstrap .badge-success:focus,a.bootstrap .badge-success:hover{color:#fff;background-color:#1e7e34}a.bootstrap .badge-success.focus,a.bootstrap .badge-success:focus{outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(40,167,69,.5);box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.bootstrap .badge-info{color:#fff;background-color:#17a2b8}a.bootstrap .badge-info:focus,a.bootstrap .badge-info:hover{color:#fff;background-color:#117a8b}a.bootstrap .badge-info.focus,a.bootstrap .badge-info:focus{outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(23,162,184,.5);box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.bootstrap .badge-warning{color:#212529;background-color:#ffc107}a.bootstrap .badge-warning:focus,a.bootstrap .badge-warning:hover{color:#212529;background-color:#d39e00}a.bootstrap .badge-warning.focus,a.bootstrap .badge-warning:focus{outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(255,193,7,.5);box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.bootstrap .badge-danger{color:#fff;background-color:#dc3545}a.bootstrap .badge-danger:focus,a.bootstrap .badge-danger:hover{color:#fff;background-color:#bd2130}a.bootstrap .badge-danger.focus,a.bootstrap .badge-danger:focus{outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(220,53,69,.5);box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.bootstrap .badge-light{color:#212529;background-color:#f8f9fa}a.bootstrap .badge-light:focus,a.bootstrap .badge-light:hover{color:#212529;background-color:#dae0e5}a.bootstrap .badge-light.focus,a.bootstrap .badge-light:focus{outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(248,249,250,.5);box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.bootstrap .badge-dark{color:#fff;background-color:#343a40}a.bootstrap .badge-dark:focus,a.bootstrap .badge-dark:hover{color:#fff;background-color:#1d2124}a.bootstrap .badge-dark.focus,a.bootstrap .badge-dark:focus{outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(52,58,64,.5);box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.bootstrap .jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width:576px){.bootstrap .jumbotron{padding:4rem 2rem}}.bootstrap .jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.bootstrap .alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.bootstrap .alert-heading{color:inherit}.bootstrap .alert-link{font-weight:700}.bootstrap .alert-dismissible{padding-right:4rem}.bootstrap .alert-dismissible .close{position:absolute;top:0;right:0;padding:.75rem 1.25rem;color:inherit}.bootstrap .alert-primary{color:#004085;background-color:#cce5ff;border-color:#b8daff}.bootstrap .alert-primary hr{border-top-color:#9fcdff}.bootstrap .alert-primary .alert-link{color:#002752}.bootstrap .alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.bootstrap .alert-secondary hr{border-top-color:#c8cbcf}.bootstrap .alert-secondary .alert-link{color:#202326}.bootstrap .alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.bootstrap .alert-success hr{border-top-color:#b1dfbb}.bootstrap .alert-success .alert-link{color:#0b2e13}.bootstrap .alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.bootstrap .alert-info hr{border-top-color:#abdde5}.bootstrap .alert-info .alert-link{color:#062c33}.bootstrap .alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.bootstrap .alert-warning hr{border-top-color:#ffe8a1}.bootstrap .alert-warning .alert-link{color:#533f03}.bootstrap .alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.bootstrap .alert-danger hr{border-top-color:#f1b0b7}.bootstrap .alert-danger .alert-link{color:#491217}.bootstrap .alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.bootstrap .alert-light hr{border-top-color:#ececf6}.bootstrap .alert-light .alert-link{color:#686868}.bootstrap .alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.bootstrap .alert-dark hr{border-top-color:#b9bbbe}.bootstrap .alert-dark .alert-link{color:#040505}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.bootstrap .progress{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;height:1rem;overflow:hidden;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.bootstrap .progress-bar{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;overflow:hidden;color:#fff;text-align:center;white-space:nowrap;background-color:#007bff;-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}@media (prefers-reduced-motion:reduce){.bootstrap .progress-bar{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap .progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:1rem 1rem;background-size:1rem 1rem}.bootstrap .progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;-o-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}@media (prefers-reduced-motion:reduce){.bootstrap .progress-bar-animated{-webkit-animation:none;-o-animation:none;animation:none}}.bootstrap .media{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start}.bootstrap .media-body{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.bootstrap .list-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0}.bootstrap .list-group-item-action{width:100%;color:#495057;text-align:inherit}.bootstrap .list-group-item-action:focus,.bootstrap .list-group-item-action:hover{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.bootstrap .list-group-item-action:active{color:#212529;background-color:#e9ecef}.bootstrap .list-group-item{position:relative;display:block;padding:.75rem 1.25rem;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.bootstrap .list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.bootstrap .list-group-item:last-child{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.bootstrap .list-group-item.disabled,.bootstrap .list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.bootstrap .list-group-item.active{z-index:2;color:#fff;background-color:#007bff;border-color:#007bff}.bootstrap .list-group-item+.bootstrap .list-group-item{border-top-width:0}.bootstrap .list-group-item+.bootstrap .list-group-item.active{margin-top:-1px;border-top-width:1px}.bootstrap .list-group-horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.bootstrap .list-group-horizontal .list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.bootstrap .list-group-horizontal .list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.bootstrap .list-group-horizontal .list-group-item.active{margin-top:0}.bootstrap .list-group-horizontal .list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.bootstrap .list-group-horizontal .list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media (min-width:576px){.bootstrap .list-group-horizontal-sm{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.bootstrap .list-group-horizontal-sm .list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.bootstrap .list-group-horizontal-sm .list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.bootstrap .list-group-horizontal-sm .list-group-item.active{margin-top:0}.bootstrap .list-group-horizontal-sm .list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.bootstrap .list-group-horizontal-sm .list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:768px){.bootstrap .list-group-horizontal-md{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.bootstrap .list-group-horizontal-md .list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.bootstrap .list-group-horizontal-md .list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.bootstrap .list-group-horizontal-md .list-group-item.active{margin-top:0}.bootstrap .list-group-horizontal-md .list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.bootstrap .list-group-horizontal-md .list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:992px){.bootstrap .list-group-horizontal-lg{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.bootstrap .list-group-horizontal-lg .list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.bootstrap .list-group-horizontal-lg .list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.bootstrap .list-group-horizontal-lg .list-group-item.active{margin-top:0}.bootstrap .list-group-horizontal-lg .list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.bootstrap .list-group-horizontal-lg .list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:1200px){.bootstrap .list-group-horizontal-xl{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.bootstrap .list-group-horizontal-xl .list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.bootstrap .list-group-horizontal-xl .list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.bootstrap .list-group-horizontal-xl .list-group-item.active{margin-top:0}.bootstrap .list-group-horizontal-xl .list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.bootstrap .list-group-horizontal-xl .list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.bootstrap .list-group-flush .list-group-item{border-right-width:0;border-left-width:0;border-radius:0}.bootstrap .list-group-flush .list-group-item:first-child{border-top-width:0}.bootstrap .list-group-flush:last-child .list-group-item:last-child{border-bottom-width:0}.bootstrap .list-group-item-primary{color:#004085;background-color:#b8daff}.bootstrap .list-group-item-primary.list-group-item-action:focus,.bootstrap .list-group-item-primary.list-group-item-action:hover{color:#004085;background-color:#9fcdff}.bootstrap .list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#004085;border-color:#004085}.bootstrap .list-group-item-secondary{color:#383d41;background-color:#d6d8db}.bootstrap .list-group-item-secondary.list-group-item-action:focus,.bootstrap .list-group-item-secondary.list-group-item-action:hover{color:#383d41;background-color:#c8cbcf}.bootstrap .list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#383d41;border-color:#383d41}.bootstrap .list-group-item-success{color:#155724;background-color:#c3e6cb}.bootstrap .list-group-item-success.list-group-item-action:focus,.bootstrap .list-group-item-success.list-group-item-action:hover{color:#155724;background-color:#b1dfbb}.bootstrap .list-group-item-success.list-group-item-action.active{color:#fff;background-color:#155724;border-color:#155724}.bootstrap .list-group-item-info{color:#0c5460;background-color:#bee5eb}.bootstrap .list-group-item-info.list-group-item-action:focus,.bootstrap .list-group-item-info.list-group-item-action:hover{color:#0c5460;background-color:#abdde5}.bootstrap .list-group-item-info.list-group-item-action.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.bootstrap .list-group-item-warning{color:#856404;background-color:#ffeeba}.bootstrap .list-group-item-warning.list-group-item-action:focus,.bootstrap .list-group-item-warning.list-group-item-action:hover{color:#856404;background-color:#ffe8a1}.bootstrap .list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#856404;border-color:#856404}.bootstrap .list-group-item-danger{color:#721c24;background-color:#f5c6cb}.bootstrap .list-group-item-danger.list-group-item-action:focus,.bootstrap .list-group-item-danger.list-group-item-action:hover{color:#721c24;background-color:#f1b0b7}.bootstrap .list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.bootstrap .list-group-item-light{color:#818182;background-color:#fdfdfe}.bootstrap .list-group-item-light.list-group-item-action:focus,.bootstrap .list-group-item-light.list-group-item-action:hover{color:#818182;background-color:#ececf6}.bootstrap .list-group-item-light.list-group-item-action.active{color:#fff;background-color:#818182;border-color:#818182}.bootstrap .list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}.bootstrap .list-group-item-dark.list-group-item-action:focus,.bootstrap .list-group-item-dark.list-group-item-action:hover{color:#1b1e21;background-color:#b9bbbe}.bootstrap .list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.bootstrap .close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.bootstrap .close:hover{color:#000;text-decoration:none}.bootstrap .close:not(:disabled):not(.disabled):focus,.bootstrap .close:not(:disabled):not(.disabled):hover{opacity:.75}.bootstrap button.close{padding:0;background-color:transparent;border:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}.bootstrap a.close.disabled{pointer-events:none}.bootstrap .toast{max-width:350px;overflow:hidden;font-size:.875rem;background-color:rgba(255,255,255,.85);-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid rgba(0,0,0,.1);-webkit-box-shadow:0 .25rem .75rem rgba(0,0,0,.1);box-shadow:0 .25rem .75rem rgba(0,0,0,.1);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);opacity:0;border-radius:.25rem}.bootstrap .toast:not(:last-child){margin-bottom:.75rem}.bootstrap .toast.showing{opacity:1}.bootstrap .toast.show{display:block;opacity:1}.bootstrap .toast.hide{display:none}.bootstrap .toast-header{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;padding:.25rem .75rem;color:#6c757d;background-color:rgba(255,255,255,.85);-webkit-background-clip:padding-box;background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05)}.bootstrap .toast-body{padding:.75rem}.bootstrap .modal-open{overflow:hidden}.bootstrap .modal-open .modal{overflow-x:hidden;overflow-y:auto}.bootstrap .modal{position:fixed;top:0;left:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.bootstrap .modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .bootstrap .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out,-o-transform .3s ease-out;-webkit-transform:translate(0,-50px);-o-transform:translate(0,-50px);transform:translate(0,-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .bootstrap .modal-dialog{-webkit-transition:none;-o-transition:none;transition:none}}.modal.show .bootstrap .modal-dialog{-webkit-transform:none;-o-transform:none;transform:none}.modal.modal-static .bootstrap .modal-dialog{-webkit-transform:scale(1.02);-o-transform:scale(1.02);transform:scale(1.02)}.bootstrap .modal-dialog-scrollable{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;max-height:calc(100% - 1rem)}.bootstrap .modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.bootstrap .modal-dialog-scrollable .modal-footer,.bootstrap .modal-dialog-scrollable .modal-header{-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0}.bootstrap .modal-dialog-scrollable .modal-body{overflow-y:auto}.bootstrap .modal-dialog-centered{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;min-height:calc(100% - 1rem)}.bootstrap .modal-dialog-centered::before{display:block;height:calc(100vh - 1rem);content:""}.bootstrap .modal-dialog-centered.modal-dialog-scrollable{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;height:100%}.bootstrap .modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.bootstrap .modal-dialog-centered.modal-dialog-scrollable::before{content:none}.bootstrap .modal-content{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.bootstrap .modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.bootstrap .modal-backdrop.fade{opacity:0}.bootstrap .modal-backdrop.show{opacity:.5}.bootstrap .modal-header{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #dee2e6;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.bootstrap .modal-header .close{padding:1rem 1rem;margin:-1rem -1rem -1rem auto}.bootstrap .modal-title{margin-bottom:0;line-height:1.5}.bootstrap .modal-body{position:relative;-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.bootstrap .modal-footer{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end;padding:.75rem;border-top:1px solid #dee2e6;border-bottom-right-radius:calc(.3rem - 1px);border-bottom-left-radius:calc(.3rem - 1px)}.bootstrap .modal-footer>*{margin:.25rem}.bootstrap .modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.bootstrap .modal-dialog{max-width:500px;margin:1.75rem auto}.bootstrap .modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.bootstrap .modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.bootstrap .modal-dialog-centered{min-height:calc(100% - 3.5rem)}.bootstrap .modal-dialog-centered::before{height:calc(100vh - 3.5rem)}.bootstrap .modal-sm{max-width:300px}}@media (min-width:992px){.bootstrap .modal-lg,.bootstrap .modal-xl{max-width:800px}}@media (min-width:1200px){.bootstrap .modal-xl{max-width:1140px}}.bootstrap .tooltip{position:absolute;z-index:1070;display:block;margin:0;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";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.bootstrap .tooltip.show{opacity:.9}.bootstrap .tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.bootstrap .tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bootstrap .bs-tooltip-auto[x-placement^=top],.bootstrap .bs-tooltip-top{padding:.4rem 0}.bootstrap .bs-tooltip-auto[x-placement^=top] .arrow,.bootstrap .bs-tooltip-top .arrow{bottom:0}.bootstrap .bs-tooltip-auto[x-placement^=top] .arrow::before,.bootstrap .bs-tooltip-top .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bootstrap .bs-tooltip-auto[x-placement^=right],.bootstrap .bs-tooltip-right{padding:0 .4rem}.bootstrap .bs-tooltip-auto[x-placement^=right] .arrow,.bootstrap .bs-tooltip-right .arrow{left:0;width:.4rem;height:.8rem}.bootstrap .bs-tooltip-auto[x-placement^=right] .arrow::before,.bootstrap .bs-tooltip-right .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bootstrap .bs-tooltip-auto[x-placement^=bottom],.bootstrap .bs-tooltip-bottom{padding:.4rem 0}.bootstrap .bs-tooltip-auto[x-placement^=bottom] .arrow,.bootstrap .bs-tooltip-bottom .arrow{top:0}.bootstrap .bs-tooltip-auto[x-placement^=bottom] .arrow::before,.bootstrap .bs-tooltip-bottom .arrow::before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bootstrap .bs-tooltip-auto[x-placement^=left],.bootstrap .bs-tooltip-left{padding:0 .4rem}.bootstrap .bs-tooltip-auto[x-placement^=left] .arrow,.bootstrap .bs-tooltip-left .arrow{right:0;width:.4rem;height:.8rem}.bootstrap .bs-tooltip-auto[x-placement^=left] .arrow::before,.bootstrap .bs-tooltip-left .arrow::before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.bootstrap .tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.bootstrap .popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;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";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.bootstrap .popover .arrow{position:absolute;display:block;width:1rem;height:.5rem;margin:0 .3rem}.bootstrap .popover .arrow::after,.bootstrap .popover .arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bootstrap .bs-popover-auto[x-placement^=top],.bootstrap .bs-popover-top{margin-bottom:.5rem}.bootstrap .bs-popover-auto[x-placement^=top]>.arrow,.bootstrap .bs-popover-top>.arrow{bottom:calc(-.5rem - 1px)}.bootstrap .bs-popover-auto[x-placement^=top]>.arrow::before,.bootstrap .bs-popover-top>.arrow::before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,.25)}.bootstrap .bs-popover-auto[x-placement^=top]>.arrow::after,.bootstrap .bs-popover-top>.arrow::after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bootstrap .bs-popover-auto[x-placement^=right],.bootstrap .bs-popover-right{margin-left:.5rem}.bootstrap .bs-popover-auto[x-placement^=right]>.arrow,.bootstrap .bs-popover-right>.arrow{left:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bootstrap .bs-popover-auto[x-placement^=right]>.arrow::before,.bootstrap .bs-popover-right>.arrow::before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,.25)}.bootstrap .bs-popover-auto[x-placement^=right]>.arrow::after,.bootstrap .bs-popover-right>.arrow::after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bootstrap .bs-popover-auto[x-placement^=bottom],.bootstrap .bs-popover-bottom{margin-top:.5rem}.bootstrap .bs-popover-auto[x-placement^=bottom]>.arrow,.bootstrap .bs-popover-bottom>.arrow{top:calc(-.5rem - 1px)}.bootstrap .bs-popover-auto[x-placement^=bottom]>.arrow::before,.bootstrap .bs-popover-bottom>.arrow::before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(0,0,0,.25)}.bootstrap .bs-popover-auto[x-placement^=bottom]>.arrow::after,.bootstrap .bs-popover-bottom>.arrow::after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#fff}.bootstrap .bs-popover-auto[x-placement^=bottom] .popover-header::before,.bootstrap .bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.bootstrap .bs-popover-auto[x-placement^=left],.bootstrap .bs-popover-left{margin-right:.5rem}.bootstrap .bs-popover-auto[x-placement^=left]>.arrow,.bootstrap .bs-popover-left>.arrow{right:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bootstrap .bs-popover-auto[x-placement^=left]>.arrow::before,.bootstrap .bs-popover-left>.arrow::before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,.25)}.bootstrap .bs-popover-auto[x-placement^=left]>.arrow::after,.bootstrap .bs-popover-left>.arrow::after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.bootstrap .popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.bootstrap .popover-header:empty{display:none}.bootstrap .popover-body{padding:.5rem .75rem;color:#212529}.bootstrap .carousel{position:relative}.bootstrap .carousel.pointer-event{-ms-touch-action:pan-y;touch-action:pan-y}.bootstrap .carousel-inner{position:relative;width:100%;overflow:hidden}.bootstrap .carousel-inner::after{display:block;clear:both;content:""}.bootstrap .carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transition:-webkit-transform .6s ease-in-out;transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out,-o-transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.bootstrap .carousel-item{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap .carousel-item-next,.bootstrap .carousel-item-prev,.bootstrap .carousel-item.active{display:block}.bootstrap .active.carousel-item-right,.bootstrap .carousel-item-next:not(.carousel-item-left){-webkit-transform:translateX(100%);-o-transform:translateX(100%);transform:translateX(100%)}.bootstrap .active.carousel-item-left,.bootstrap .carousel-item-prev:not(.carousel-item-right){-webkit-transform:translateX(-100%);-o-transform:translateX(-100%);transform:translateX(-100%)}.bootstrap .carousel-fade .carousel-item{opacity:0;-webkit-transition-property:opacity;-o-transition-property:opacity;transition-property:opacity;-webkit-transform:none;-o-transform:none;transform:none}.bootstrap .carousel-fade .carousel-item-next.carousel-item-left,.bootstrap .carousel-fade .carousel-item-prev.carousel-item-right,.bootstrap .carousel-fade .carousel-item.active{z-index:1;opacity:1}.bootstrap .carousel-fade .active.carousel-item-left,.bootstrap .carousel-fade .active.carousel-item-right{z-index:0;opacity:0;-webkit-transition:opacity 0s .6s;-o-transition:opacity 0s .6s;transition:opacity 0s .6s}@media (prefers-reduced-motion:reduce){.bootstrap .carousel-fade .active.carousel-item-left,.bootstrap .carousel-fade .active.carousel-item-right{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap .carousel-control-next,.bootstrap .carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5;-webkit-transition:opacity .15s ease;-o-transition:opacity .15s ease;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.bootstrap .carousel-control-next,.bootstrap .carousel-control-prev{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap .carousel-control-next:focus,.bootstrap .carousel-control-next:hover,.bootstrap .carousel-control-prev:focus,.bootstrap .carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.bootstrap .carousel-control-prev{left:0}.bootstrap .carousel-control-next{right:0}.bootstrap .carousel-control-next-icon,.bootstrap .carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:no-repeat 50%/100% 100%}.bootstrap .carousel-control-prev-icon{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")}.bootstrap .carousel-control-next-icon{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")}.bootstrap .carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:15;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.bootstrap .carousel-indicators li{-webkit-box-sizing:content-box;box-sizing:content-box;-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;-webkit-transition:opacity .6s ease;-o-transition:opacity .6s ease;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.bootstrap .carousel-indicators li{-webkit-transition:none;-o-transition:none;transition:none}}.bootstrap .carousel-indicators .active{opacity:1}.bootstrap .carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}@-webkit-keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-o-keyframes spinner-border{to{-o-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes spinner-border{to{-webkit-transform:rotate(360deg);-o-transform:rotate(360deg);transform:rotate(360deg)}}.bootstrap .spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;border:.25em solid currentColor;border-right-color:transparent;border-radius:50%;-webkit-animation:spinner-border .75s linear infinite;-o-animation:spinner-border .75s linear infinite;animation:spinner-border .75s linear infinite}.bootstrap .spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@-webkit-keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1}}@-o-keyframes spinner-grow{0%{-o-transform:scale(0);transform:scale(0)}50%{opacity:1}}@keyframes spinner-grow{0%{-webkit-transform:scale(0);-o-transform:scale(0);transform:scale(0)}50%{opacity:1}}.bootstrap .spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;background-color:currentColor;border-radius:50%;opacity:0;-webkit-animation:spinner-grow .75s linear infinite;-o-animation:spinner-grow .75s linear infinite;animation:spinner-grow .75s linear infinite}.bootstrap .spinner-grow-sm{width:1rem;height:1rem}.bootstrap .align-baseline{vertical-align:baseline!important}.bootstrap .align-top{vertical-align:top!important}.bootstrap .align-middle{vertical-align:middle!important}.bootstrap .align-bottom{vertical-align:bottom!important}.bootstrap .align-text-bottom{vertical-align:text-bottom!important}.bootstrap .align-text-top{vertical-align:text-top!important}.bootstrap .bg-primary{background-color:#007bff!important}.bootstrap a.bg-primary:focus,.bootstrap a.bg-primary:hover,.bootstrap button.bg-primary:focus,.bootstrap button.bg-primary:hover{background-color:#0062cc!important}.bootstrap .bg-secondary{background-color:#6c757d!important}.bootstrap a.bg-secondary:focus,.bootstrap a.bg-secondary:hover,.bootstrap button.bg-secondary:focus,.bootstrap button.bg-secondary:hover{background-color:#545b62!important}.bootstrap .bg-success{background-color:#28a745!important}.bootstrap a.bg-success:focus,.bootstrap a.bg-success:hover,.bootstrap button.bg-success:focus,.bootstrap button.bg-success:hover{background-color:#1e7e34!important}.bootstrap .bg-info{background-color:#17a2b8!important}.bootstrap a.bg-info:focus,.bootstrap a.bg-info:hover,.bootstrap button.bg-info:focus,.bootstrap button.bg-info:hover{background-color:#117a8b!important}.bootstrap .bg-warning{background-color:#ffc107!important}.bootstrap a.bg-warning:focus,.bootstrap a.bg-warning:hover,.bootstrap button.bg-warning:focus,.bootstrap button.bg-warning:hover{background-color:#d39e00!important}.bootstrap .bg-danger{background-color:#dc3545!important}.bootstrap a.bg-danger:focus,.bootstrap a.bg-danger:hover,.bootstrap button.bg-danger:focus,.bootstrap button.bg-danger:hover{background-color:#bd2130!important}.bootstrap .bg-light{background-color:#f8f9fa!important}.bootstrap a.bg-light:focus,.bootstrap a.bg-light:hover,.bootstrap button.bg-light:focus,.bootstrap button.bg-light:hover{background-color:#dae0e5!important}.bootstrap .bg-dark{background-color:#343a40!important}.bootstrap a.bg-dark:focus,.bootstrap a.bg-dark:hover,.bootstrap button.bg-dark:focus,.bootstrap button.bg-dark:hover{background-color:#1d2124!important}.bootstrap .bg-white{background-color:#fff!important}.bootstrap .bg-transparent{background-color:transparent!important}.bootstrap .border{border:1px solid #dee2e6!important}.bootstrap .border-top{border-top:1px solid #dee2e6!important}.bootstrap .border-right{border-right:1px solid #dee2e6!important}.bootstrap .border-bottom{border-bottom:1px solid #dee2e6!important}.bootstrap .border-left{border-left:1px solid #dee2e6!important}.bootstrap .border-0{border:0!important}.bootstrap .border-top-0{border-top:0!important}.bootstrap .border-right-0{border-right:0!important}.bootstrap .border-bottom-0{border-bottom:0!important}.bootstrap .border-left-0{border-left:0!important}.bootstrap .border-primary{border-color:#007bff!important}.bootstrap .border-secondary{border-color:#6c757d!important}.bootstrap .border-success{border-color:#28a745!important}.bootstrap .border-info{border-color:#17a2b8!important}.bootstrap .border-warning{border-color:#ffc107!important}.bootstrap .border-danger{border-color:#dc3545!important}.bootstrap .border-light{border-color:#f8f9fa!important}.bootstrap .border-dark{border-color:#343a40!important}.bootstrap .border-white{border-color:#fff!important}.bootstrap .rounded-sm{border-radius:.2rem!important}.bootstrap .rounded{border-radius:.25rem!important}.bootstrap .rounded-top{border-top-left-radius:.25rem!important;border-top-right-radius:.25rem!important}.bootstrap .rounded-right{border-top-right-radius:.25rem!important;border-bottom-right-radius:.25rem!important}.bootstrap .rounded-bottom{border-bottom-right-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.bootstrap .rounded-left{border-top-left-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.bootstrap .rounded-lg{border-radius:.3rem!important}.bootstrap .rounded-circle{border-radius:50%!important}.bootstrap .rounded-pill{border-radius:50rem!important}.bootstrap .rounded-0{border-radius:0!important}.bootstrap .clearfix::after{display:block;clear:both;content:""}.bootstrap .d-none{display:none!important}.bootstrap .d-inline{display:inline!important}.bootstrap .d-inline-block{display:inline-block!important}.bootstrap .d-block{display:block!important}.bootstrap .d-table{display:table!important}.bootstrap .d-table-row{display:table-row!important}.bootstrap .d-table-cell{display:table-cell!important}.bootstrap .d-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.bootstrap .d-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.bootstrap .d-sm-none{display:none!important}.bootstrap .d-sm-inline{display:inline!important}.bootstrap .d-sm-inline-block{display:inline-block!important}.bootstrap .d-sm-block{display:block!important}.bootstrap .d-sm-table{display:table!important}.bootstrap .d-sm-table-row{display:table-row!important}.bootstrap .d-sm-table-cell{display:table-cell!important}.bootstrap .d-sm-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.bootstrap .d-sm-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.bootstrap .d-md-none{display:none!important}.bootstrap .d-md-inline{display:inline!important}.bootstrap .d-md-inline-block{display:inline-block!important}.bootstrap .d-md-block{display:block!important}.bootstrap .d-md-table{display:table!important}.bootstrap .d-md-table-row{display:table-row!important}.bootstrap .d-md-table-cell{display:table-cell!important}.bootstrap .d-md-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.bootstrap .d-md-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.bootstrap .d-lg-none{display:none!important}.bootstrap .d-lg-inline{display:inline!important}.bootstrap .d-lg-inline-block{display:inline-block!important}.bootstrap .d-lg-block{display:block!important}.bootstrap .d-lg-table{display:table!important}.bootstrap .d-lg-table-row{display:table-row!important}.bootstrap .d-lg-table-cell{display:table-cell!important}.bootstrap .d-lg-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.bootstrap .d-lg-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.bootstrap .d-xl-none{display:none!important}.bootstrap .d-xl-inline{display:inline!important}.bootstrap .d-xl-inline-block{display:inline-block!important}.bootstrap .d-xl-block{display:block!important}.bootstrap .d-xl-table{display:table!important}.bootstrap .d-xl-table-row{display:table-row!important}.bootstrap .d-xl-table-cell{display:table-cell!important}.bootstrap .d-xl-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.bootstrap .d-xl-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.bootstrap .d-print-none{display:none!important}.bootstrap .d-print-inline{display:inline!important}.bootstrap .d-print-inline-block{display:inline-block!important}.bootstrap .d-print-block{display:block!important}.bootstrap .d-print-table{display:table!important}.bootstrap .d-print-table-row{display:table-row!important}.bootstrap .d-print-table-cell{display:table-cell!important}.bootstrap .d-print-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.bootstrap .d-print-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}.bootstrap .embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.bootstrap .embed-responsive::before{display:block;content:""}.bootstrap .embed-responsive .embed-responsive-item,.bootstrap .embed-responsive embed,.bootstrap .embed-responsive iframe,.bootstrap .embed-responsive object,.bootstrap .embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.bootstrap .embed-responsive-21by9::before{padding-top:42.85714%}.bootstrap .embed-responsive-16by9::before{padding-top:56.25%}.bootstrap .embed-responsive-4by3::before{padding-top:75%}.bootstrap .embed-responsive-1by1::before{padding-top:100%}.bootstrap .flex-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.bootstrap .flex-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.bootstrap .flex-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.bootstrap .flex-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.bootstrap .flex-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.bootstrap .flex-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.bootstrap .flex-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.bootstrap .flex-fill{-webkit-box-flex:1!important;-webkit-flex:1 1 auto!important;-ms-flex:1 1 auto!important;flex:1 1 auto!important}.bootstrap .flex-grow-0{-webkit-box-flex:0!important;-webkit-flex-grow:0!important;-ms-flex-positive:0!important;flex-grow:0!important}.bootstrap .flex-grow-1{-webkit-box-flex:1!important;-webkit-flex-grow:1!important;-ms-flex-positive:1!important;flex-grow:1!important}.bootstrap .flex-shrink-0{-webkit-flex-shrink:0!important;-ms-flex-negative:0!important;flex-shrink:0!important}.bootstrap .flex-shrink-1{-webkit-flex-shrink:1!important;-ms-flex-negative:1!important;flex-shrink:1!important}.bootstrap .justify-content-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.bootstrap .justify-content-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.bootstrap .justify-content-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.bootstrap .justify-content-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.bootstrap .justify-content-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.bootstrap .align-items-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.bootstrap .align-items-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.bootstrap .align-items-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.bootstrap .align-items-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.bootstrap .align-items-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.bootstrap .align-content-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.bootstrap .align-content-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.bootstrap .align-content-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.bootstrap .align-content-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.bootstrap .align-content-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.bootstrap .align-content-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.bootstrap .align-self-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;align-self:auto!important}.bootstrap .align-self-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.bootstrap .align-self-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.bootstrap .align-self-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;align-self:center!important}.bootstrap .align-self-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.bootstrap .align-self-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.bootstrap .flex-sm-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.bootstrap .flex-sm-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.bootstrap .flex-sm-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.bootstrap .flex-sm-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.bootstrap .flex-sm-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.bootstrap .flex-sm-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.bootstrap .flex-sm-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.bootstrap .flex-sm-fill{-webkit-box-flex:1!important;-webkit-flex:1 1 auto!important;-ms-flex:1 1 auto!important;flex:1 1 auto!important}.bootstrap .flex-sm-grow-0{-webkit-box-flex:0!important;-webkit-flex-grow:0!important;-ms-flex-positive:0!important;flex-grow:0!important}.bootstrap .flex-sm-grow-1{-webkit-box-flex:1!important;-webkit-flex-grow:1!important;-ms-flex-positive:1!important;flex-grow:1!important}.bootstrap .flex-sm-shrink-0{-webkit-flex-shrink:0!important;-ms-flex-negative:0!important;flex-shrink:0!important}.bootstrap .flex-sm-shrink-1{-webkit-flex-shrink:1!important;-ms-flex-negative:1!important;flex-shrink:1!important}.bootstrap .justify-content-sm-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.bootstrap .justify-content-sm-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.bootstrap .justify-content-sm-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.bootstrap .justify-content-sm-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.bootstrap .justify-content-sm-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.bootstrap .align-items-sm-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.bootstrap .align-items-sm-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.bootstrap .align-items-sm-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.bootstrap .align-items-sm-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.bootstrap .align-items-sm-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.bootstrap .align-content-sm-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.bootstrap .align-content-sm-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.bootstrap .align-content-sm-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.bootstrap .align-content-sm-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.bootstrap .align-content-sm-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.bootstrap .align-content-sm-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.bootstrap .align-self-sm-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;align-self:auto!important}.bootstrap .align-self-sm-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.bootstrap .align-self-sm-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.bootstrap .align-self-sm-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;align-self:center!important}.bootstrap .align-self-sm-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.bootstrap .align-self-sm-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.bootstrap .flex-md-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.bootstrap .flex-md-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.bootstrap .flex-md-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.bootstrap .flex-md-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.bootstrap .flex-md-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.bootstrap .flex-md-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.bootstrap .flex-md-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.bootstrap .flex-md-fill{-webkit-box-flex:1!important;-webkit-flex:1 1 auto!important;-ms-flex:1 1 auto!important;flex:1 1 auto!important}.bootstrap .flex-md-grow-0{-webkit-box-flex:0!important;-webkit-flex-grow:0!important;-ms-flex-positive:0!important;flex-grow:0!important}.bootstrap .flex-md-grow-1{-webkit-box-flex:1!important;-webkit-flex-grow:1!important;-ms-flex-positive:1!important;flex-grow:1!important}.bootstrap .flex-md-shrink-0{-webkit-flex-shrink:0!important;-ms-flex-negative:0!important;flex-shrink:0!important}.bootstrap .flex-md-shrink-1{-webkit-flex-shrink:1!important;-ms-flex-negative:1!important;flex-shrink:1!important}.bootstrap .justify-content-md-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.bootstrap .justify-content-md-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.bootstrap .justify-content-md-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.bootstrap .justify-content-md-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.bootstrap .justify-content-md-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.bootstrap .align-items-md-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.bootstrap .align-items-md-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.bootstrap .align-items-md-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.bootstrap .align-items-md-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.bootstrap .align-items-md-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.bootstrap .align-content-md-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.bootstrap .align-content-md-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.bootstrap .align-content-md-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.bootstrap .align-content-md-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.bootstrap .align-content-md-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.bootstrap .align-content-md-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.bootstrap .align-self-md-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;align-self:auto!important}.bootstrap .align-self-md-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.bootstrap .align-self-md-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.bootstrap .align-self-md-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;align-self:center!important}.bootstrap .align-self-md-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.bootstrap .align-self-md-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.bootstrap .flex-lg-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.bootstrap .flex-lg-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.bootstrap .flex-lg-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.bootstrap .flex-lg-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.bootstrap .flex-lg-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.bootstrap .flex-lg-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.bootstrap .flex-lg-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.bootstrap .flex-lg-fill{-webkit-box-flex:1!important;-webkit-flex:1 1 auto!important;-ms-flex:1 1 auto!important;flex:1 1 auto!important}.bootstrap .flex-lg-grow-0{-webkit-box-flex:0!important;-webkit-flex-grow:0!important;-ms-flex-positive:0!important;flex-grow:0!important}.bootstrap .flex-lg-grow-1{-webkit-box-flex:1!important;-webkit-flex-grow:1!important;-ms-flex-positive:1!important;flex-grow:1!important}.bootstrap .flex-lg-shrink-0{-webkit-flex-shrink:0!important;-ms-flex-negative:0!important;flex-shrink:0!important}.bootstrap .flex-lg-shrink-1{-webkit-flex-shrink:1!important;-ms-flex-negative:1!important;flex-shrink:1!important}.bootstrap .justify-content-lg-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.bootstrap .justify-content-lg-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.bootstrap .justify-content-lg-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.bootstrap .justify-content-lg-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.bootstrap .justify-content-lg-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.bootstrap .align-items-lg-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.bootstrap .align-items-lg-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.bootstrap .align-items-lg-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.bootstrap .align-items-lg-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.bootstrap .align-items-lg-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.bootstrap .align-content-lg-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.bootstrap .align-content-lg-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.bootstrap .align-content-lg-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.bootstrap .align-content-lg-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.bootstrap .align-content-lg-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.bootstrap .align-content-lg-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.bootstrap .align-self-lg-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;align-self:auto!important}.bootstrap .align-self-lg-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.bootstrap .align-self-lg-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.bootstrap .align-self-lg-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;align-self:center!important}.bootstrap .align-self-lg-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.bootstrap .align-self-lg-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.bootstrap .flex-xl-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.bootstrap .flex-xl-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.bootstrap .flex-xl-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.bootstrap .flex-xl-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.bootstrap .flex-xl-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.bootstrap .flex-xl-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.bootstrap .flex-xl-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.bootstrap .flex-xl-fill{-webkit-box-flex:1!important;-webkit-flex:1 1 auto!important;-ms-flex:1 1 auto!important;flex:1 1 auto!important}.bootstrap .flex-xl-grow-0{-webkit-box-flex:0!important;-webkit-flex-grow:0!important;-ms-flex-positive:0!important;flex-grow:0!important}.bootstrap .flex-xl-grow-1{-webkit-box-flex:1!important;-webkit-flex-grow:1!important;-ms-flex-positive:1!important;flex-grow:1!important}.bootstrap .flex-xl-shrink-0{-webkit-flex-shrink:0!important;-ms-flex-negative:0!important;flex-shrink:0!important}.bootstrap .flex-xl-shrink-1{-webkit-flex-shrink:1!important;-ms-flex-negative:1!important;flex-shrink:1!important}.bootstrap .justify-content-xl-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.bootstrap .justify-content-xl-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.bootstrap .justify-content-xl-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.bootstrap .justify-content-xl-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.bootstrap .justify-content-xl-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.bootstrap .align-items-xl-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.bootstrap .align-items-xl-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.bootstrap .align-items-xl-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.bootstrap .align-items-xl-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.bootstrap .align-items-xl-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.bootstrap .align-content-xl-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.bootstrap .align-content-xl-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.bootstrap .align-content-xl-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.bootstrap .align-content-xl-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.bootstrap .align-content-xl-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.bootstrap .align-content-xl-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.bootstrap .align-self-xl-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;align-self:auto!important}.bootstrap .align-self-xl-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.bootstrap .align-self-xl-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.bootstrap .align-self-xl-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;align-self:center!important}.bootstrap .align-self-xl-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.bootstrap .align-self-xl-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;align-self:stretch!important}}.bootstrap .float-left{float:left!important}.bootstrap .float-right{float:right!important}.bootstrap .float-none{float:none!important}@media (min-width:576px){.bootstrap .float-sm-left{float:left!important}.bootstrap .float-sm-right{float:right!important}.bootstrap .float-sm-none{float:none!important}}@media (min-width:768px){.bootstrap .float-md-left{float:left!important}.bootstrap .float-md-right{float:right!important}.bootstrap .float-md-none{float:none!important}}@media (min-width:992px){.bootstrap .float-lg-left{float:left!important}.bootstrap .float-lg-right{float:right!important}.bootstrap .float-lg-none{float:none!important}}@media (min-width:1200px){.bootstrap .float-xl-left{float:left!important}.bootstrap .float-xl-right{float:right!important}.bootstrap .float-xl-none{float:none!important}}.bootstrap .overflow-auto{overflow:auto!important}.bootstrap .overflow-hidden{overflow:hidden!important}.bootstrap .position-static{position:static!important}.bootstrap .position-relative{position:relative!important}.bootstrap .position-absolute{position:absolute!important}.bootstrap .position-fixed{position:fixed!important}.bootstrap .position-sticky{position:-webkit-sticky!important;position:sticky!important}.bootstrap .fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.bootstrap .fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports ((position:-webkit-sticky) or (position:sticky)){.bootstrap .sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.bootstrap .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.bootstrap .sr-only-focusable:active,.bootstrap .sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.bootstrap .shadow-sm{-webkit-box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important;box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.bootstrap .shadow{-webkit-box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important;box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.bootstrap .shadow-lg{-webkit-box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important;box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.bootstrap .shadow-none{-webkit-box-shadow:none!important;box-shadow:none!important}.bootstrap .w-25{width:25%!important}.bootstrap .w-50{width:50%!important}.bootstrap .w-75{width:75%!important}.bootstrap .w-100{width:100%!important}.bootstrap .w-auto{width:auto!important}.bootstrap .h-25{height:25%!important}.bootstrap .h-50{height:50%!important}.bootstrap .h-75{height:75%!important}.bootstrap .h-100{height:100%!important}.bootstrap .h-auto{height:auto!important}.bootstrap .mw-100{max-width:100%!important}.bootstrap .mh-100{max-height:100%!important}.bootstrap .min-vw-100{min-width:100vw!important}.bootstrap .min-vh-100{min-height:100vh!important}.bootstrap .vw-100{width:100vw!important}.bootstrap .vh-100{height:100vh!important}.bootstrap .stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;pointer-events:auto;content:"";background-color:rgba(0,0,0,0)}.bootstrap .m-0{margin:0!important}.bootstrap .mt-0,.bootstrap .my-0{margin-top:0!important}.bootstrap .mr-0,.bootstrap .mx-0{margin-right:0!important}.bootstrap .mb-0,.bootstrap .my-0{margin-bottom:0!important}.bootstrap .ml-0,.bootstrap .mx-0{margin-left:0!important}.bootstrap .m-1{margin:.25rem!important}.bootstrap .mt-1,.bootstrap .my-1{margin-top:.25rem!important}.bootstrap .mr-1,.bootstrap .mx-1{margin-right:.25rem!important}.bootstrap .mb-1,.bootstrap .my-1{margin-bottom:.25rem!important}.bootstrap .ml-1,.bootstrap .mx-1{margin-left:.25rem!important}.bootstrap .m-2{margin:.5rem!important}.bootstrap .mt-2,.bootstrap .my-2{margin-top:.5rem!important}.bootstrap .mr-2,.bootstrap .mx-2{margin-right:.5rem!important}.bootstrap .mb-2,.bootstrap .my-2{margin-bottom:.5rem!important}.bootstrap .ml-2,.bootstrap .mx-2{margin-left:.5rem!important}.bootstrap .m-3{margin:1rem!important}.bootstrap .mt-3,.bootstrap .my-3{margin-top:1rem!important}.bootstrap .mr-3,.bootstrap .mx-3{margin-right:1rem!important}.bootstrap .mb-3,.bootstrap .my-3{margin-bottom:1rem!important}.bootstrap .ml-3,.bootstrap .mx-3{margin-left:1rem!important}.bootstrap .m-4{margin:1.5rem!important}.bootstrap .mt-4,.bootstrap .my-4{margin-top:1.5rem!important}.bootstrap .mr-4,.bootstrap .mx-4{margin-right:1.5rem!important}.bootstrap .mb-4,.bootstrap .my-4{margin-bottom:1.5rem!important}.bootstrap .ml-4,.bootstrap .mx-4{margin-left:1.5rem!important}.bootstrap .m-5{margin:3rem!important}.bootstrap .mt-5,.bootstrap .my-5{margin-top:3rem!important}.bootstrap .mr-5,.bootstrap .mx-5{margin-right:3rem!important}.bootstrap .mb-5,.bootstrap .my-5{margin-bottom:3rem!important}.bootstrap .ml-5,.bootstrap .mx-5{margin-left:3rem!important}.bootstrap .p-0{padding:0!important}.bootstrap .pt-0,.bootstrap .py-0{padding-top:0!important}.bootstrap .pr-0,.bootstrap .px-0{padding-right:0!important}.bootstrap .pb-0,.bootstrap .py-0{padding-bottom:0!important}.bootstrap .pl-0,.bootstrap .px-0{padding-left:0!important}.bootstrap .p-1{padding:.25rem!important}.bootstrap .pt-1,.bootstrap .py-1{padding-top:.25rem!important}.bootstrap .pr-1,.bootstrap .px-1{padding-right:.25rem!important}.bootstrap .pb-1,.bootstrap .py-1{padding-bottom:.25rem!important}.bootstrap .pl-1,.bootstrap .px-1{padding-left:.25rem!important}.bootstrap .p-2{padding:.5rem!important}.bootstrap .pt-2,.bootstrap .py-2{padding-top:.5rem!important}.bootstrap .pr-2,.bootstrap .px-2{padding-right:.5rem!important}.bootstrap .pb-2,.bootstrap .py-2{padding-bottom:.5rem!important}.bootstrap .pl-2,.bootstrap .px-2{padding-left:.5rem!important}.bootstrap .p-3{padding:1rem!important}.bootstrap .pt-3,.bootstrap .py-3{padding-top:1rem!important}.bootstrap .pr-3,.bootstrap .px-3{padding-right:1rem!important}.bootstrap .pb-3,.bootstrap .py-3{padding-bottom:1rem!important}.bootstrap .pl-3,.bootstrap .px-3{padding-left:1rem!important}.bootstrap .p-4{padding:1.5rem!important}.bootstrap .pt-4,.bootstrap .py-4{padding-top:1.5rem!important}.bootstrap .pr-4,.bootstrap .px-4{padding-right:1.5rem!important}.bootstrap .pb-4,.bootstrap .py-4{padding-bottom:1.5rem!important}.bootstrap .pl-4,.bootstrap .px-4{padding-left:1.5rem!important}.bootstrap .p-5{padding:3rem!important}.bootstrap .pt-5,.bootstrap .py-5{padding-top:3rem!important}.bootstrap .pr-5,.bootstrap .px-5{padding-right:3rem!important}.bootstrap .pb-5,.bootstrap .py-5{padding-bottom:3rem!important}.bootstrap .pl-5,.bootstrap .px-5{padding-left:3rem!important}.bootstrap .m-n1{margin:-.25rem!important}.bootstrap .mt-n1,.bootstrap .my-n1{margin-top:-.25rem!important}.bootstrap .mr-n1,.bootstrap .mx-n1{margin-right:-.25rem!important}.bootstrap .mb-n1,.bootstrap .my-n1{margin-bottom:-.25rem!important}.bootstrap .ml-n1,.bootstrap .mx-n1{margin-left:-.25rem!important}.bootstrap .m-n2{margin:-.5rem!important}.bootstrap .mt-n2,.bootstrap .my-n2{margin-top:-.5rem!important}.bootstrap .mr-n2,.bootstrap .mx-n2{margin-right:-.5rem!important}.bootstrap .mb-n2,.bootstrap .my-n2{margin-bottom:-.5rem!important}.bootstrap .ml-n2,.bootstrap .mx-n2{margin-left:-.5rem!important}.bootstrap .m-n3{margin:-1rem!important}.bootstrap .mt-n3,.bootstrap .my-n3{margin-top:-1rem!important}.bootstrap .mr-n3,.bootstrap .mx-n3{margin-right:-1rem!important}.bootstrap .mb-n3,.bootstrap .my-n3{margin-bottom:-1rem!important}.bootstrap .ml-n3,.bootstrap .mx-n3{margin-left:-1rem!important}.bootstrap .m-n4{margin:-1.5rem!important}.bootstrap .mt-n4,.bootstrap .my-n4{margin-top:-1.5rem!important}.bootstrap .mr-n4,.bootstrap .mx-n4{margin-right:-1.5rem!important}.bootstrap .mb-n4,.bootstrap .my-n4{margin-bottom:-1.5rem!important}.bootstrap .ml-n4,.bootstrap .mx-n4{margin-left:-1.5rem!important}.bootstrap .m-n5{margin:-3rem!important}.bootstrap .mt-n5,.bootstrap .my-n5{margin-top:-3rem!important}.bootstrap .mr-n5,.bootstrap .mx-n5{margin-right:-3rem!important}.bootstrap .mb-n5,.bootstrap .my-n5{margin-bottom:-3rem!important}.bootstrap .ml-n5,.bootstrap .mx-n5{margin-left:-3rem!important}.bootstrap .m-auto{margin:auto!important}.bootstrap .mt-auto,.bootstrap .my-auto{margin-top:auto!important}.bootstrap .mr-auto,.bootstrap .mx-auto{margin-right:auto!important}.bootstrap .mb-auto,.bootstrap .my-auto{margin-bottom:auto!important}.bootstrap .ml-auto,.bootstrap .mx-auto{margin-left:auto!important}@media (min-width:576px){.bootstrap .m-sm-0{margin:0!important}.bootstrap .mt-sm-0,.bootstrap .my-sm-0{margin-top:0!important}.bootstrap .mr-sm-0,.bootstrap .mx-sm-0{margin-right:0!important}.bootstrap .mb-sm-0,.bootstrap .my-sm-0{margin-bottom:0!important}.bootstrap .ml-sm-0,.bootstrap .mx-sm-0{margin-left:0!important}.bootstrap .m-sm-1{margin:.25rem!important}.bootstrap .mt-sm-1,.bootstrap .my-sm-1{margin-top:.25rem!important}.bootstrap .mr-sm-1,.bootstrap .mx-sm-1{margin-right:.25rem!important}.bootstrap .mb-sm-1,.bootstrap .my-sm-1{margin-bottom:.25rem!important}.bootstrap .ml-sm-1,.bootstrap .mx-sm-1{margin-left:.25rem!important}.bootstrap .m-sm-2{margin:.5rem!important}.bootstrap .mt-sm-2,.bootstrap .my-sm-2{margin-top:.5rem!important}.bootstrap .mr-sm-2,.bootstrap .mx-sm-2{margin-right:.5rem!important}.bootstrap .mb-sm-2,.bootstrap .my-sm-2{margin-bottom:.5rem!important}.bootstrap .ml-sm-2,.bootstrap .mx-sm-2{margin-left:.5rem!important}.bootstrap .m-sm-3{margin:1rem!important}.bootstrap .mt-sm-3,.bootstrap .my-sm-3{margin-top:1rem!important}.bootstrap .mr-sm-3,.bootstrap .mx-sm-3{margin-right:1rem!important}.bootstrap .mb-sm-3,.bootstrap .my-sm-3{margin-bottom:1rem!important}.bootstrap .ml-sm-3,.bootstrap .mx-sm-3{margin-left:1rem!important}.bootstrap .m-sm-4{margin:1.5rem!important}.bootstrap .mt-sm-4,.bootstrap .my-sm-4{margin-top:1.5rem!important}.bootstrap .mr-sm-4,.bootstrap .mx-sm-4{margin-right:1.5rem!important}.bootstrap .mb-sm-4,.bootstrap .my-sm-4{margin-bottom:1.5rem!important}.bootstrap .ml-sm-4,.bootstrap .mx-sm-4{margin-left:1.5rem!important}.bootstrap .m-sm-5{margin:3rem!important}.bootstrap .mt-sm-5,.bootstrap .my-sm-5{margin-top:3rem!important}.bootstrap .mr-sm-5,.bootstrap .mx-sm-5{margin-right:3rem!important}.bootstrap .mb-sm-5,.bootstrap .my-sm-5{margin-bottom:3rem!important}.bootstrap .ml-sm-5,.bootstrap .mx-sm-5{margin-left:3rem!important}.bootstrap .p-sm-0{padding:0!important}.bootstrap .pt-sm-0,.bootstrap .py-sm-0{padding-top:0!important}.bootstrap .pr-sm-0,.bootstrap .px-sm-0{padding-right:0!important}.bootstrap .pb-sm-0,.bootstrap .py-sm-0{padding-bottom:0!important}.bootstrap .pl-sm-0,.bootstrap .px-sm-0{padding-left:0!important}.bootstrap .p-sm-1{padding:.25rem!important}.bootstrap .pt-sm-1,.bootstrap .py-sm-1{padding-top:.25rem!important}.bootstrap .pr-sm-1,.bootstrap .px-sm-1{padding-right:.25rem!important}.bootstrap .pb-sm-1,.bootstrap .py-sm-1{padding-bottom:.25rem!important}.bootstrap .pl-sm-1,.bootstrap .px-sm-1{padding-left:.25rem!important}.bootstrap .p-sm-2{padding:.5rem!important}.bootstrap .pt-sm-2,.bootstrap .py-sm-2{padding-top:.5rem!important}.bootstrap .pr-sm-2,.bootstrap .px-sm-2{padding-right:.5rem!important}.bootstrap .pb-sm-2,.bootstrap .py-sm-2{padding-bottom:.5rem!important}.bootstrap .pl-sm-2,.bootstrap .px-sm-2{padding-left:.5rem!important}.bootstrap .p-sm-3{padding:1rem!important}.bootstrap .pt-sm-3,.bootstrap .py-sm-3{padding-top:1rem!important}.bootstrap .pr-sm-3,.bootstrap .px-sm-3{padding-right:1rem!important}.bootstrap .pb-sm-3,.bootstrap .py-sm-3{padding-bottom:1rem!important}.bootstrap .pl-sm-3,.bootstrap .px-sm-3{padding-left:1rem!important}.bootstrap .p-sm-4{padding:1.5rem!important}.bootstrap .pt-sm-4,.bootstrap .py-sm-4{padding-top:1.5rem!important}.bootstrap .pr-sm-4,.bootstrap .px-sm-4{padding-right:1.5rem!important}.bootstrap .pb-sm-4,.bootstrap .py-sm-4{padding-bottom:1.5rem!important}.bootstrap .pl-sm-4,.bootstrap .px-sm-4{padding-left:1.5rem!important}.bootstrap .p-sm-5{padding:3rem!important}.bootstrap .pt-sm-5,.bootstrap .py-sm-5{padding-top:3rem!important}.bootstrap .pr-sm-5,.bootstrap .px-sm-5{padding-right:3rem!important}.bootstrap .pb-sm-5,.bootstrap .py-sm-5{padding-bottom:3rem!important}.bootstrap .pl-sm-5,.bootstrap .px-sm-5{padding-left:3rem!important}.bootstrap .m-sm-n1{margin:-.25rem!important}.bootstrap .mt-sm-n1,.bootstrap .my-sm-n1{margin-top:-.25rem!important}.bootstrap .mr-sm-n1,.bootstrap .mx-sm-n1{margin-right:-.25rem!important}.bootstrap .mb-sm-n1,.bootstrap .my-sm-n1{margin-bottom:-.25rem!important}.bootstrap .ml-sm-n1,.bootstrap .mx-sm-n1{margin-left:-.25rem!important}.bootstrap .m-sm-n2{margin:-.5rem!important}.bootstrap .mt-sm-n2,.bootstrap .my-sm-n2{margin-top:-.5rem!important}.bootstrap .mr-sm-n2,.bootstrap .mx-sm-n2{margin-right:-.5rem!important}.bootstrap .mb-sm-n2,.bootstrap .my-sm-n2{margin-bottom:-.5rem!important}.bootstrap .ml-sm-n2,.bootstrap .mx-sm-n2{margin-left:-.5rem!important}.bootstrap .m-sm-n3{margin:-1rem!important}.bootstrap .mt-sm-n3,.bootstrap .my-sm-n3{margin-top:-1rem!important}.bootstrap .mr-sm-n3,.bootstrap .mx-sm-n3{margin-right:-1rem!important}.bootstrap .mb-sm-n3,.bootstrap .my-sm-n3{margin-bottom:-1rem!important}.bootstrap .ml-sm-n3,.bootstrap .mx-sm-n3{margin-left:-1rem!important}.bootstrap .m-sm-n4{margin:-1.5rem!important}.bootstrap .mt-sm-n4,.bootstrap .my-sm-n4{margin-top:-1.5rem!important}.bootstrap .mr-sm-n4,.bootstrap .mx-sm-n4{margin-right:-1.5rem!important}.bootstrap .mb-sm-n4,.bootstrap .my-sm-n4{margin-bottom:-1.5rem!important}.bootstrap .ml-sm-n4,.bootstrap .mx-sm-n4{margin-left:-1.5rem!important}.bootstrap .m-sm-n5{margin:-3rem!important}.bootstrap .mt-sm-n5,.bootstrap .my-sm-n5{margin-top:-3rem!important}.bootstrap .mr-sm-n5,.bootstrap .mx-sm-n5{margin-right:-3rem!important}.bootstrap .mb-sm-n5,.bootstrap .my-sm-n5{margin-bottom:-3rem!important}.bootstrap .ml-sm-n5,.bootstrap .mx-sm-n5{margin-left:-3rem!important}.bootstrap .m-sm-auto{margin:auto!important}.bootstrap .mt-sm-auto,.bootstrap .my-sm-auto{margin-top:auto!important}.bootstrap .mr-sm-auto,.bootstrap .mx-sm-auto{margin-right:auto!important}.bootstrap .mb-sm-auto,.bootstrap .my-sm-auto{margin-bottom:auto!important}.bootstrap .ml-sm-auto,.bootstrap .mx-sm-auto{margin-left:auto!important}}@media (min-width:768px){.bootstrap .m-md-0{margin:0!important}.bootstrap .mt-md-0,.bootstrap .my-md-0{margin-top:0!important}.bootstrap .mr-md-0,.bootstrap .mx-md-0{margin-right:0!important}.bootstrap .mb-md-0,.bootstrap .my-md-0{margin-bottom:0!important}.bootstrap .ml-md-0,.bootstrap .mx-md-0{margin-left:0!important}.bootstrap .m-md-1{margin:.25rem!important}.bootstrap .mt-md-1,.bootstrap .my-md-1{margin-top:.25rem!important}.bootstrap .mr-md-1,.bootstrap .mx-md-1{margin-right:.25rem!important}.bootstrap .mb-md-1,.bootstrap .my-md-1{margin-bottom:.25rem!important}.bootstrap .ml-md-1,.bootstrap .mx-md-1{margin-left:.25rem!important}.bootstrap .m-md-2{margin:.5rem!important}.bootstrap .mt-md-2,.bootstrap .my-md-2{margin-top:.5rem!important}.bootstrap .mr-md-2,.bootstrap .mx-md-2{margin-right:.5rem!important}.bootstrap .mb-md-2,.bootstrap .my-md-2{margin-bottom:.5rem!important}.bootstrap .ml-md-2,.bootstrap .mx-md-2{margin-left:.5rem!important}.bootstrap .m-md-3{margin:1rem!important}.bootstrap .mt-md-3,.bootstrap .my-md-3{margin-top:1rem!important}.bootstrap .mr-md-3,.bootstrap .mx-md-3{margin-right:1rem!important}.bootstrap .mb-md-3,.bootstrap .my-md-3{margin-bottom:1rem!important}.bootstrap .ml-md-3,.bootstrap .mx-md-3{margin-left:1rem!important}.bootstrap .m-md-4{margin:1.5rem!important}.bootstrap .mt-md-4,.bootstrap .my-md-4{margin-top:1.5rem!important}.bootstrap .mr-md-4,.bootstrap .mx-md-4{margin-right:1.5rem!important}.bootstrap .mb-md-4,.bootstrap .my-md-4{margin-bottom:1.5rem!important}.bootstrap .ml-md-4,.bootstrap .mx-md-4{margin-left:1.5rem!important}.bootstrap .m-md-5{margin:3rem!important}.bootstrap .mt-md-5,.bootstrap .my-md-5{margin-top:3rem!important}.bootstrap .mr-md-5,.bootstrap .mx-md-5{margin-right:3rem!important}.bootstrap .mb-md-5,.bootstrap .my-md-5{margin-bottom:3rem!important}.bootstrap .ml-md-5,.bootstrap .mx-md-5{margin-left:3rem!important}.bootstrap .p-md-0{padding:0!important}.bootstrap .pt-md-0,.bootstrap .py-md-0{padding-top:0!important}.bootstrap .pr-md-0,.bootstrap .px-md-0{padding-right:0!important}.bootstrap .pb-md-0,.bootstrap .py-md-0{padding-bottom:0!important}.bootstrap .pl-md-0,.bootstrap .px-md-0{padding-left:0!important}.bootstrap .p-md-1{padding:.25rem!important}.bootstrap .pt-md-1,.bootstrap .py-md-1{padding-top:.25rem!important}.bootstrap .pr-md-1,.bootstrap .px-md-1{padding-right:.25rem!important}.bootstrap .pb-md-1,.bootstrap .py-md-1{padding-bottom:.25rem!important}.bootstrap .pl-md-1,.bootstrap .px-md-1{padding-left:.25rem!important}.bootstrap .p-md-2{padding:.5rem!important}.bootstrap .pt-md-2,.bootstrap .py-md-2{padding-top:.5rem!important}.bootstrap .pr-md-2,.bootstrap .px-md-2{padding-right:.5rem!important}.bootstrap .pb-md-2,.bootstrap .py-md-2{padding-bottom:.5rem!important}.bootstrap .pl-md-2,.bootstrap .px-md-2{padding-left:.5rem!important}.bootstrap .p-md-3{padding:1rem!important}.bootstrap .pt-md-3,.bootstrap .py-md-3{padding-top:1rem!important}.bootstrap .pr-md-3,.bootstrap .px-md-3{padding-right:1rem!important}.bootstrap .pb-md-3,.bootstrap .py-md-3{padding-bottom:1rem!important}.bootstrap .pl-md-3,.bootstrap .px-md-3{padding-left:1rem!important}.bootstrap .p-md-4{padding:1.5rem!important}.bootstrap .pt-md-4,.bootstrap .py-md-4{padding-top:1.5rem!important}.bootstrap .pr-md-4,.bootstrap .px-md-4{padding-right:1.5rem!important}.bootstrap .pb-md-4,.bootstrap .py-md-4{padding-bottom:1.5rem!important}.bootstrap .pl-md-4,.bootstrap .px-md-4{padding-left:1.5rem!important}.bootstrap .p-md-5{padding:3rem!important}.bootstrap .pt-md-5,.bootstrap .py-md-5{padding-top:3rem!important}.bootstrap .pr-md-5,.bootstrap .px-md-5{padding-right:3rem!important}.bootstrap .pb-md-5,.bootstrap .py-md-5{padding-bottom:3rem!important}.bootstrap .pl-md-5,.bootstrap .px-md-5{padding-left:3rem!important}.bootstrap .m-md-n1{margin:-.25rem!important}.bootstrap .mt-md-n1,.bootstrap .my-md-n1{margin-top:-.25rem!important}.bootstrap .mr-md-n1,.bootstrap .mx-md-n1{margin-right:-.25rem!important}.bootstrap .mb-md-n1,.bootstrap .my-md-n1{margin-bottom:-.25rem!important}.bootstrap .ml-md-n1,.bootstrap .mx-md-n1{margin-left:-.25rem!important}.bootstrap .m-md-n2{margin:-.5rem!important}.bootstrap .mt-md-n2,.bootstrap .my-md-n2{margin-top:-.5rem!important}.bootstrap .mr-md-n2,.bootstrap .mx-md-n2{margin-right:-.5rem!important}.bootstrap .mb-md-n2,.bootstrap .my-md-n2{margin-bottom:-.5rem!important}.bootstrap .ml-md-n2,.bootstrap .mx-md-n2{margin-left:-.5rem!important}.bootstrap .m-md-n3{margin:-1rem!important}.bootstrap .mt-md-n3,.bootstrap .my-md-n3{margin-top:-1rem!important}.bootstrap .mr-md-n3,.bootstrap .mx-md-n3{margin-right:-1rem!important}.bootstrap .mb-md-n3,.bootstrap .my-md-n3{margin-bottom:-1rem!important}.bootstrap .ml-md-n3,.bootstrap .mx-md-n3{margin-left:-1rem!important}.bootstrap .m-md-n4{margin:-1.5rem!important}.bootstrap .mt-md-n4,.bootstrap .my-md-n4{margin-top:-1.5rem!important}.bootstrap .mr-md-n4,.bootstrap .mx-md-n4{margin-right:-1.5rem!important}.bootstrap .mb-md-n4,.bootstrap .my-md-n4{margin-bottom:-1.5rem!important}.bootstrap .ml-md-n4,.bootstrap .mx-md-n4{margin-left:-1.5rem!important}.bootstrap .m-md-n5{margin:-3rem!important}.bootstrap .mt-md-n5,.bootstrap .my-md-n5{margin-top:-3rem!important}.bootstrap .mr-md-n5,.bootstrap .mx-md-n5{margin-right:-3rem!important}.bootstrap .mb-md-n5,.bootstrap .my-md-n5{margin-bottom:-3rem!important}.bootstrap .ml-md-n5,.bootstrap .mx-md-n5{margin-left:-3rem!important}.bootstrap .m-md-auto{margin:auto!important}.bootstrap .mt-md-auto,.bootstrap .my-md-auto{margin-top:auto!important}.bootstrap .mr-md-auto,.bootstrap .mx-md-auto{margin-right:auto!important}.bootstrap .mb-md-auto,.bootstrap .my-md-auto{margin-bottom:auto!important}.bootstrap .ml-md-auto,.bootstrap .mx-md-auto{margin-left:auto!important}}@media (min-width:992px){.bootstrap .m-lg-0{margin:0!important}.bootstrap .mt-lg-0,.bootstrap .my-lg-0{margin-top:0!important}.bootstrap .mr-lg-0,.bootstrap .mx-lg-0{margin-right:0!important}.bootstrap .mb-lg-0,.bootstrap .my-lg-0{margin-bottom:0!important}.bootstrap .ml-lg-0,.bootstrap .mx-lg-0{margin-left:0!important}.bootstrap .m-lg-1{margin:.25rem!important}.bootstrap .mt-lg-1,.bootstrap .my-lg-1{margin-top:.25rem!important}.bootstrap .mr-lg-1,.bootstrap .mx-lg-1{margin-right:.25rem!important}.bootstrap .mb-lg-1,.bootstrap .my-lg-1{margin-bottom:.25rem!important}.bootstrap .ml-lg-1,.bootstrap .mx-lg-1{margin-left:.25rem!important}.bootstrap .m-lg-2{margin:.5rem!important}.bootstrap .mt-lg-2,.bootstrap .my-lg-2{margin-top:.5rem!important}.bootstrap .mr-lg-2,.bootstrap .mx-lg-2{margin-right:.5rem!important}.bootstrap .mb-lg-2,.bootstrap .my-lg-2{margin-bottom:.5rem!important}.bootstrap .ml-lg-2,.bootstrap .mx-lg-2{margin-left:.5rem!important}.bootstrap .m-lg-3{margin:1rem!important}.bootstrap .mt-lg-3,.bootstrap .my-lg-3{margin-top:1rem!important}.bootstrap .mr-lg-3,.bootstrap .mx-lg-3{margin-right:1rem!important}.bootstrap .mb-lg-3,.bootstrap .my-lg-3{margin-bottom:1rem!important}.bootstrap .ml-lg-3,.bootstrap .mx-lg-3{margin-left:1rem!important}.bootstrap .m-lg-4{margin:1.5rem!important}.bootstrap .mt-lg-4,.bootstrap .my-lg-4{margin-top:1.5rem!important}.bootstrap .mr-lg-4,.bootstrap .mx-lg-4{margin-right:1.5rem!important}.bootstrap .mb-lg-4,.bootstrap .my-lg-4{margin-bottom:1.5rem!important}.bootstrap .ml-lg-4,.bootstrap .mx-lg-4{margin-left:1.5rem!important}.bootstrap .m-lg-5{margin:3rem!important}.bootstrap .mt-lg-5,.bootstrap .my-lg-5{margin-top:3rem!important}.bootstrap .mr-lg-5,.bootstrap .mx-lg-5{margin-right:3rem!important}.bootstrap .mb-lg-5,.bootstrap .my-lg-5{margin-bottom:3rem!important}.bootstrap .ml-lg-5,.bootstrap .mx-lg-5{margin-left:3rem!important}.bootstrap .p-lg-0{padding:0!important}.bootstrap .pt-lg-0,.bootstrap .py-lg-0{padding-top:0!important}.bootstrap .pr-lg-0,.bootstrap .px-lg-0{padding-right:0!important}.bootstrap .pb-lg-0,.bootstrap .py-lg-0{padding-bottom:0!important}.bootstrap .pl-lg-0,.bootstrap .px-lg-0{padding-left:0!important}.bootstrap .p-lg-1{padding:.25rem!important}.bootstrap .pt-lg-1,.bootstrap .py-lg-1{padding-top:.25rem!important}.bootstrap .pr-lg-1,.bootstrap .px-lg-1{padding-right:.25rem!important}.bootstrap .pb-lg-1,.bootstrap .py-lg-1{padding-bottom:.25rem!important}.bootstrap .pl-lg-1,.bootstrap .px-lg-1{padding-left:.25rem!important}.bootstrap .p-lg-2{padding:.5rem!important}.bootstrap .pt-lg-2,.bootstrap .py-lg-2{padding-top:.5rem!important}.bootstrap .pr-lg-2,.bootstrap .px-lg-2{padding-right:.5rem!important}.bootstrap .pb-lg-2,.bootstrap .py-lg-2{padding-bottom:.5rem!important}.bootstrap .pl-lg-2,.bootstrap .px-lg-2{padding-left:.5rem!important}.bootstrap .p-lg-3{padding:1rem!important}.bootstrap .pt-lg-3,.bootstrap .py-lg-3{padding-top:1rem!important}.bootstrap .pr-lg-3,.bootstrap .px-lg-3{padding-right:1rem!important}.bootstrap .pb-lg-3,.bootstrap .py-lg-3{padding-bottom:1rem!important}.bootstrap .pl-lg-3,.bootstrap .px-lg-3{padding-left:1rem!important}.bootstrap .p-lg-4{padding:1.5rem!important}.bootstrap .pt-lg-4,.bootstrap .py-lg-4{padding-top:1.5rem!important}.bootstrap .pr-lg-4,.bootstrap .px-lg-4{padding-right:1.5rem!important}.bootstrap .pb-lg-4,.bootstrap .py-lg-4{padding-bottom:1.5rem!important}.bootstrap .pl-lg-4,.bootstrap .px-lg-4{padding-left:1.5rem!important}.bootstrap .p-lg-5{padding:3rem!important}.bootstrap .pt-lg-5,.bootstrap .py-lg-5{padding-top:3rem!important}.bootstrap .pr-lg-5,.bootstrap .px-lg-5{padding-right:3rem!important}.bootstrap .pb-lg-5,.bootstrap .py-lg-5{padding-bottom:3rem!important}.bootstrap .pl-lg-5,.bootstrap .px-lg-5{padding-left:3rem!important}.bootstrap .m-lg-n1{margin:-.25rem!important}.bootstrap .mt-lg-n1,.bootstrap .my-lg-n1{margin-top:-.25rem!important}.bootstrap .mr-lg-n1,.bootstrap .mx-lg-n1{margin-right:-.25rem!important}.bootstrap .mb-lg-n1,.bootstrap .my-lg-n1{margin-bottom:-.25rem!important}.bootstrap .ml-lg-n1,.bootstrap .mx-lg-n1{margin-left:-.25rem!important}.bootstrap .m-lg-n2{margin:-.5rem!important}.bootstrap .mt-lg-n2,.bootstrap .my-lg-n2{margin-top:-.5rem!important}.bootstrap .mr-lg-n2,.bootstrap .mx-lg-n2{margin-right:-.5rem!important}.bootstrap .mb-lg-n2,.bootstrap .my-lg-n2{margin-bottom:-.5rem!important}.bootstrap .ml-lg-n2,.bootstrap .mx-lg-n2{margin-left:-.5rem!important}.bootstrap .m-lg-n3{margin:-1rem!important}.bootstrap .mt-lg-n3,.bootstrap .my-lg-n3{margin-top:-1rem!important}.bootstrap .mr-lg-n3,.bootstrap .mx-lg-n3{margin-right:-1rem!important}.bootstrap .mb-lg-n3,.bootstrap .my-lg-n3{margin-bottom:-1rem!important}.bootstrap .ml-lg-n3,.bootstrap .mx-lg-n3{margin-left:-1rem!important}.bootstrap .m-lg-n4{margin:-1.5rem!important}.bootstrap .mt-lg-n4,.bootstrap .my-lg-n4{margin-top:-1.5rem!important}.bootstrap .mr-lg-n4,.bootstrap .mx-lg-n4{margin-right:-1.5rem!important}.bootstrap .mb-lg-n4,.bootstrap .my-lg-n4{margin-bottom:-1.5rem!important}.bootstrap .ml-lg-n4,.bootstrap .mx-lg-n4{margin-left:-1.5rem!important}.bootstrap .m-lg-n5{margin:-3rem!important}.bootstrap .mt-lg-n5,.bootstrap .my-lg-n5{margin-top:-3rem!important}.bootstrap .mr-lg-n5,.bootstrap .mx-lg-n5{margin-right:-3rem!important}.bootstrap .mb-lg-n5,.bootstrap .my-lg-n5{margin-bottom:-3rem!important}.bootstrap .ml-lg-n5,.bootstrap .mx-lg-n5{margin-left:-3rem!important}.bootstrap .m-lg-auto{margin:auto!important}.bootstrap .mt-lg-auto,.bootstrap .my-lg-auto{margin-top:auto!important}.bootstrap .mr-lg-auto,.bootstrap .mx-lg-auto{margin-right:auto!important}.bootstrap .mb-lg-auto,.bootstrap .my-lg-auto{margin-bottom:auto!important}.bootstrap .ml-lg-auto,.bootstrap .mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.bootstrap .m-xl-0{margin:0!important}.bootstrap .mt-xl-0,.bootstrap .my-xl-0{margin-top:0!important}.bootstrap .mr-xl-0,.bootstrap .mx-xl-0{margin-right:0!important}.bootstrap .mb-xl-0,.bootstrap .my-xl-0{margin-bottom:0!important}.bootstrap .ml-xl-0,.bootstrap .mx-xl-0{margin-left:0!important}.bootstrap .m-xl-1{margin:.25rem!important}.bootstrap .mt-xl-1,.bootstrap .my-xl-1{margin-top:.25rem!important}.bootstrap .mr-xl-1,.bootstrap .mx-xl-1{margin-right:.25rem!important}.bootstrap .mb-xl-1,.bootstrap .my-xl-1{margin-bottom:.25rem!important}.bootstrap .ml-xl-1,.bootstrap .mx-xl-1{margin-left:.25rem!important}.bootstrap .m-xl-2{margin:.5rem!important}.bootstrap .mt-xl-2,.bootstrap .my-xl-2{margin-top:.5rem!important}.bootstrap .mr-xl-2,.bootstrap .mx-xl-2{margin-right:.5rem!important}.bootstrap .mb-xl-2,.bootstrap .my-xl-2{margin-bottom:.5rem!important}.bootstrap .ml-xl-2,.bootstrap .mx-xl-2{margin-left:.5rem!important}.bootstrap .m-xl-3{margin:1rem!important}.bootstrap .mt-xl-3,.bootstrap .my-xl-3{margin-top:1rem!important}.bootstrap .mr-xl-3,.bootstrap .mx-xl-3{margin-right:1rem!important}.bootstrap .mb-xl-3,.bootstrap .my-xl-3{margin-bottom:1rem!important}.bootstrap .ml-xl-3,.bootstrap .mx-xl-3{margin-left:1rem!important}.bootstrap .m-xl-4{margin:1.5rem!important}.bootstrap .mt-xl-4,.bootstrap .my-xl-4{margin-top:1.5rem!important}.bootstrap .mr-xl-4,.bootstrap .mx-xl-4{margin-right:1.5rem!important}.bootstrap .mb-xl-4,.bootstrap .my-xl-4{margin-bottom:1.5rem!important}.bootstrap .ml-xl-4,.bootstrap .mx-xl-4{margin-left:1.5rem!important}.bootstrap .m-xl-5{margin:3rem!important}.bootstrap .mt-xl-5,.bootstrap .my-xl-5{margin-top:3rem!important}.bootstrap .mr-xl-5,.bootstrap .mx-xl-5{margin-right:3rem!important}.bootstrap .mb-xl-5,.bootstrap .my-xl-5{margin-bottom:3rem!important}.bootstrap .ml-xl-5,.bootstrap .mx-xl-5{margin-left:3rem!important}.bootstrap .p-xl-0{padding:0!important}.bootstrap .pt-xl-0,.bootstrap .py-xl-0{padding-top:0!important}.bootstrap .pr-xl-0,.bootstrap .px-xl-0{padding-right:0!important}.bootstrap .pb-xl-0,.bootstrap .py-xl-0{padding-bottom:0!important}.bootstrap .pl-xl-0,.bootstrap .px-xl-0{padding-left:0!important}.bootstrap .p-xl-1{padding:.25rem!important}.bootstrap .pt-xl-1,.bootstrap .py-xl-1{padding-top:.25rem!important}.bootstrap .pr-xl-1,.bootstrap .px-xl-1{padding-right:.25rem!important}.bootstrap .pb-xl-1,.bootstrap .py-xl-1{padding-bottom:.25rem!important}.bootstrap .pl-xl-1,.bootstrap .px-xl-1{padding-left:.25rem!important}.bootstrap .p-xl-2{padding:.5rem!important}.bootstrap .pt-xl-2,.bootstrap .py-xl-2{padding-top:.5rem!important}.bootstrap .pr-xl-2,.bootstrap .px-xl-2{padding-right:.5rem!important}.bootstrap .pb-xl-2,.bootstrap .py-xl-2{padding-bottom:.5rem!important}.bootstrap .pl-xl-2,.bootstrap .px-xl-2{padding-left:.5rem!important}.bootstrap .p-xl-3{padding:1rem!important}.bootstrap .pt-xl-3,.bootstrap .py-xl-3{padding-top:1rem!important}.bootstrap .pr-xl-3,.bootstrap .px-xl-3{padding-right:1rem!important}.bootstrap .pb-xl-3,.bootstrap .py-xl-3{padding-bottom:1rem!important}.bootstrap .pl-xl-3,.bootstrap .px-xl-3{padding-left:1rem!important}.bootstrap .p-xl-4{padding:1.5rem!important}.bootstrap .pt-xl-4,.bootstrap .py-xl-4{padding-top:1.5rem!important}.bootstrap .pr-xl-4,.bootstrap .px-xl-4{padding-right:1.5rem!important}.bootstrap .pb-xl-4,.bootstrap .py-xl-4{padding-bottom:1.5rem!important}.bootstrap .pl-xl-4,.bootstrap .px-xl-4{padding-left:1.5rem!important}.bootstrap .p-xl-5{padding:3rem!important}.bootstrap .pt-xl-5,.bootstrap .py-xl-5{padding-top:3rem!important}.bootstrap .pr-xl-5,.bootstrap .px-xl-5{padding-right:3rem!important}.bootstrap .pb-xl-5,.bootstrap .py-xl-5{padding-bottom:3rem!important}.bootstrap .pl-xl-5,.bootstrap .px-xl-5{padding-left:3rem!important}.bootstrap .m-xl-n1{margin:-.25rem!important}.bootstrap .mt-xl-n1,.bootstrap .my-xl-n1{margin-top:-.25rem!important}.bootstrap .mr-xl-n1,.bootstrap .mx-xl-n1{margin-right:-.25rem!important}.bootstrap .mb-xl-n1,.bootstrap .my-xl-n1{margin-bottom:-.25rem!important}.bootstrap .ml-xl-n1,.bootstrap .mx-xl-n1{margin-left:-.25rem!important}.bootstrap .m-xl-n2{margin:-.5rem!important}.bootstrap .mt-xl-n2,.bootstrap .my-xl-n2{margin-top:-.5rem!important}.bootstrap .mr-xl-n2,.bootstrap .mx-xl-n2{margin-right:-.5rem!important}.bootstrap .mb-xl-n2,.bootstrap .my-xl-n2{margin-bottom:-.5rem!important}.bootstrap .ml-xl-n2,.bootstrap .mx-xl-n2{margin-left:-.5rem!important}.bootstrap .m-xl-n3{margin:-1rem!important}.bootstrap .mt-xl-n3,.bootstrap .my-xl-n3{margin-top:-1rem!important}.bootstrap .mr-xl-n3,.bootstrap .mx-xl-n3{margin-right:-1rem!important}.bootstrap .mb-xl-n3,.bootstrap .my-xl-n3{margin-bottom:-1rem!important}.bootstrap .ml-xl-n3,.bootstrap .mx-xl-n3{margin-left:-1rem!important}.bootstrap .m-xl-n4{margin:-1.5rem!important}.bootstrap .mt-xl-n4,.bootstrap .my-xl-n4{margin-top:-1.5rem!important}.bootstrap .mr-xl-n4,.bootstrap .mx-xl-n4{margin-right:-1.5rem!important}.bootstrap .mb-xl-n4,.bootstrap .my-xl-n4{margin-bottom:-1.5rem!important}.bootstrap .ml-xl-n4,.bootstrap .mx-xl-n4{margin-left:-1.5rem!important}.bootstrap .m-xl-n5{margin:-3rem!important}.bootstrap .mt-xl-n5,.bootstrap .my-xl-n5{margin-top:-3rem!important}.bootstrap .mr-xl-n5,.bootstrap .mx-xl-n5{margin-right:-3rem!important}.bootstrap .mb-xl-n5,.bootstrap .my-xl-n5{margin-bottom:-3rem!important}.bootstrap .ml-xl-n5,.bootstrap .mx-xl-n5{margin-left:-3rem!important}.bootstrap .m-xl-auto{margin:auto!important}.bootstrap .mt-xl-auto,.bootstrap .my-xl-auto{margin-top:auto!important}.bootstrap .mr-xl-auto,.bootstrap .mx-xl-auto{margin-right:auto!important}.bootstrap .mb-xl-auto,.bootstrap .my-xl-auto{margin-bottom:auto!important}.bootstrap .ml-xl-auto,.bootstrap .mx-xl-auto{margin-left:auto!important}}.bootstrap .text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace!important}.bootstrap .text-justify{text-align:justify!important}.bootstrap .text-wrap{white-space:normal!important}.bootstrap .text-nowrap{white-space:nowrap!important}.bootstrap .text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.bootstrap .text-left{text-align:left!important}.bootstrap .text-right{text-align:right!important}.bootstrap .text-center{text-align:center!important}@media (min-width:576px){.bootstrap .text-sm-left{text-align:left!important}.bootstrap .text-sm-right{text-align:right!important}.bootstrap .text-sm-center{text-align:center!important}}@media (min-width:768px){.bootstrap .text-md-left{text-align:left!important}.bootstrap .text-md-right{text-align:right!important}.bootstrap .text-md-center{text-align:center!important}}@media (min-width:992px){.bootstrap .text-lg-left{text-align:left!important}.bootstrap .text-lg-right{text-align:right!important}.bootstrap .text-lg-center{text-align:center!important}}@media (min-width:1200px){.bootstrap .text-xl-left{text-align:left!important}.bootstrap .text-xl-right{text-align:right!important}.bootstrap .text-xl-center{text-align:center!important}}.bootstrap .text-lowercase{text-transform:lowercase!important}.bootstrap .text-uppercase{text-transform:uppercase!important}.bootstrap .text-capitalize{text-transform:capitalize!important}.bootstrap .font-weight-light{font-weight:300!important}.bootstrap .font-weight-lighter{font-weight:lighter!important}.bootstrap .font-weight-normal{font-weight:400!important}.bootstrap .font-weight-bold{font-weight:700!important}.bootstrap .font-weight-bolder{font-weight:bolder!important}.bootstrap .font-italic{font-style:italic!important}.bootstrap .text-white{color:#fff!important}.bootstrap .text-primary{color:#007bff!important}.bootstrap a.text-primary:focus,.bootstrap a.text-primary:hover{color:#0056b3!important}.bootstrap .text-secondary{color:#6c757d!important}.bootstrap a.text-secondary:focus,.bootstrap a.text-secondary:hover{color:#494f54!important}.bootstrap .text-success{color:#28a745!important}.bootstrap a.text-success:focus,.bootstrap a.text-success:hover{color:#19692c!important}.bootstrap .text-info{color:#17a2b8!important}.bootstrap a.text-info:focus,.bootstrap a.text-info:hover{color:#0f6674!important}.bootstrap .text-warning{color:#ffc107!important}.bootstrap a.text-warning:focus,.bootstrap a.text-warning:hover{color:#ba8b00!important}.bootstrap .text-danger{color:#dc3545!important}.bootstrap a.text-danger:focus,.bootstrap a.text-danger:hover{color:#a71d2a!important}.bootstrap .text-light{color:#f8f9fa!important}.bootstrap a.text-light:focus,.bootstrap a.text-light:hover{color:#cbd3da!important}.bootstrap .text-dark{color:#343a40!important}.bootstrap a.text-dark:focus,.bootstrap a.text-dark:hover{color:#121416!important}.bootstrap .text-body{color:#212529!important}.bootstrap .text-muted{color:#6c757d!important}.bootstrap .text-black-50{color:rgba(0,0,0,.5)!important}.bootstrap .text-white-50{color:rgba(255,255,255,.5)!important}.bootstrap .text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.bootstrap .text-decoration-none{text-decoration:none!important}.bootstrap .text-break{word-break:break-word!important;overflow-wrap:break-word!important}.bootstrap .text-reset{color:inherit!important}.bootstrap .visible{visibility:visible!important}.bootstrap .invisible{visibility:hidden!important} diff --git a/docsSrc/files/placeholder.md b/docsSrc/files/placeholder.md deleted file mode 100644 index 21d4034..0000000 --- a/docsSrc/files/placeholder.md +++ /dev/null @@ -1 +0,0 @@ -place images or other files here diff --git a/docsSrc/index.md b/docsSrc/index.md deleted file mode 100644 index e08f3ba..0000000 --- a/docsSrc/index.md +++ /dev/null @@ -1,60 +0,0 @@ -# BinaryDefense.FSharp.Analyzers - ---- - -## What is BinaryDefense.FSharp.Analyzers? - -BinaryDefense.FSharp.Analyzers is a library that does this specific thing. - -## Why use BinaryDefense.FSharp.Analyzers? - -I created it because I had to solve an issue with this other thing. - ---- - -
-
-
-
-
Tutorials
-

Takes you by the hand through a series of steps to create your first thing.

-
- -
-
-
-
-
-
How-To Guides
-

Guides you through the steps involved in addressing key problems and use-cases.

-
- -
-
-
-
-
-
Explanations
-

Discusses key topics and concepts at a fairly high level and provide useful background information and explanation..

-
- -
-
-
-
-
-
Api Reference
-

Contain technical reference for APIs.

-
- -
-
-
diff --git a/docsTool/CLI.fs b/docsTool/CLI.fs deleted file mode 100644 index 61e65a4..0000000 --- a/docsTool/CLI.fs +++ /dev/null @@ -1,51 +0,0 @@ -namespace DocsTool - -module CLIArgs = - open Argu - open Fake.IO.Globbing.Operators - - type WatchArgs = - | ProjectGlob of string - | DocsSourceDirectory of string - | GitHubRepoUrl of string - | ProjectName of string - | ReleaseVersion of string - with - interface IArgParserTemplate with - member this.Usage = - match this with - | ProjectGlob _ -> "The glob for the dlls to generate API documentation." - | DocsSourceDirectory _ -> "The docs source directory." - | GitHubRepoUrl _ -> "The GitHub repository url." - | ProjectName _ -> "The project name." - | ReleaseVersion _ -> "The project's Release Version name." - - type BuildArgs = - | SiteBaseUrl of string - | ProjectGlob of string - | DocsOutputDirectory of string - | DocsSourceDirectory of string - | GitHubRepoUrl of string - | ProjectName of string - | ReleaseVersion of string - with - interface IArgParserTemplate with - member this.Usage = - match this with - | SiteBaseUrl _ -> "The public site's base url." - | ProjectGlob _ -> "The glob for the dlls to generate API documentation" - | DocsOutputDirectory _ -> "The docs output directory." - | DocsSourceDirectory _ -> "The docs source directory." - | GitHubRepoUrl _ -> "The GitHub repository url." - | ProjectName _ -> "The project name." - | ReleaseVersion _ -> "The project's Release Version name." - - type CLIArguments = - | [] Watch of ParseResults - | [] Build of ParseResults - with - interface IArgParserTemplate with - member this.Usage = - match this with - | Watch _ -> "Builds the docs, serves the content, and watches for changes to the content." - | Build _ -> "Builds the docs" diff --git a/docsTool/Prelude.fs b/docsTool/Prelude.fs deleted file mode 100644 index fc2c743..0000000 --- a/docsTool/Prelude.fs +++ /dev/null @@ -1,11 +0,0 @@ -namespace DocsTool - -module Uri = - open System - let simpleCombine (slug : string) (baseUri : Uri) = - sprintf "%s/%s" (baseUri.AbsoluteUri.TrimEnd('/')) (slug.TrimStart('/')) - - let create (url : string) = - match Uri.TryCreate(url, UriKind.Absolute) with - | (true, v) -> v - | _ -> failwithf "Bad url %s" url diff --git a/docsTool/Program.fs b/docsTool/Program.fs deleted file mode 100644 index 3c6fe9a..0000000 --- a/docsTool/Program.fs +++ /dev/null @@ -1,586 +0,0 @@ -// Learn more about F# at http://fsharp.org - - -open System -open Fake.IO.FileSystemOperators -open Fake.IO -open Fake.Core - -let dispose (d : #IDisposable) = d.Dispose() -type DisposableDirectory (directory : string) = - do - Trace.tracefn "Created disposable directory %s" directory - static member Create() = - let tempPath = IO.Path.Combine(IO.Path.GetTempPath(), Guid.NewGuid().ToString("n")) - IO.Directory.CreateDirectory tempPath |> ignore - - new DisposableDirectory(tempPath) - member x.Directory = directory - member x.DirectoryInfo = IO.DirectoryInfo(directory) - - interface IDisposable with - member x.Dispose() = - Trace.tracefn "Deleting directory %s" directory - IO.Directory.Delete(x.Directory,true) - - -let refreshWebpageEvent = new Event() - -type Configuration = { - SiteBaseUrl : Uri - GitHubRepoUrl : Uri - RepositoryRoot : IO.DirectoryInfo - DocsOutputDirectory : IO.DirectoryInfo - DocsSourceDirectory : IO.DirectoryInfo - ProjectName : string - ProjectFilesGlob : IGlobbingPattern - ReleaseVersion : string -} - -let docsApiDir docsDir = docsDir @@ "Api_Reference" - -type DisposableList = - { - disposables : IDisposable list - } interface IDisposable with - member x.Dispose () = - x.disposables |> List.iter(fun s -> s.Dispose()) - - -module ProjInfo = - open System.IO - - type References = FileInfo [] - type TargetPath = FileInfo - - type ProjInfo = { - References : References - TargetPath : TargetPath - } - - open Dotnet.ProjInfo.Workspace - open Dotnet.ProjInfo.Workspace.FCS - let createFCS () = - let checker = - FCS_Checker.Create( - projectCacheSize = 200, - keepAllBackgroundResolutions = true, - keepAssemblyContents = true) - checker.ImplicitlyStartBackgroundWork <- true - checker - - let createLoader () = - let msbuildLocator = MSBuildLocator() - let config = LoaderConfig.Default msbuildLocator - let loader = Loader.Create(config) - let netFwconfig = NetFWInfoConfig.Default msbuildLocator - let netFwInfo = NetFWInfo.Create(netFwconfig) - - loader, netFwInfo - - let [] RefPrefix = "-r:" - - let findTargetPath targetPath = - if File.exists targetPath then - FileInfo targetPath - else - //HACK: Need to get dotnet-proj-info to handle configurations when extracting data - let debugFolder = sprintf "%cDebug%c" Path.DirectorySeparatorChar Path.DirectorySeparatorChar - let releaseFolder = sprintf "%cRelease%c" Path.DirectorySeparatorChar Path.DirectorySeparatorChar - let debugFolderAlt = sprintf "%cDebug%c" Path.DirectorySeparatorChar Path.AltDirectorySeparatorChar - let releaseFolderAlt = sprintf "%cRelease%c" Path.DirectorySeparatorChar Path.AltDirectorySeparatorChar - - let releasePath = targetPath.Replace(debugFolder, releaseFolder).Replace(debugFolderAlt, releaseFolderAlt) - if releasePath |> File.exists then - releasePath |> FileInfo - else - failwithf "Couldn't find a dll to generate documentationfrom %s or %s" targetPath releasePath - - let findReferences projPath : ProjInfo= - let fcs = createFCS () - let loader, netFwInfo = createLoader () - loader.LoadProjects [ projPath ] - let fcsBinder = FCSBinder(netFwInfo, loader, fcs) - match fcsBinder.GetProjectOptions(projPath) with - | Some options -> - let references = - options.OtherOptions - |> Array.filter(fun s -> - s.StartsWith(RefPrefix) - ) - |> Array.map(fun s -> - // removes "-r:" from beginning of reference path - s.Remove(0,RefPrefix.Length) - |> FileInfo - ) - - let dpwPo = - match options.ExtraProjectInfo with - | Some (:? ProjectOptions as dpwPo) -> dpwPo - | x -> failwithf "invalid project info %A" x - let targetPath = findTargetPath dpwPo.ExtraProjectInfo.TargetPath - { References = references ; TargetPath = targetPath} - - | None -> - failwithf "Couldn't read project %s" projPath - - -module GenerateDocs = - open DocsTool - open Fake.Core - open Fake.IO.Globbing.Operators - open Fake.IO - open Fable.React - open Fable.React.Helpers - open FSharp.Literate - open System.IO - open FSharp.MetadataFormat - - - type GeneratedDoc = { - SourcePath : FileInfo option - OutputPath : FileInfo - Content : ReactElement list - Title : string - } - - - let docsFileGlob docsSrcDir = - !! (docsSrcDir @@ "**/*.fsx") - ++ (docsSrcDir @@ "**/*.md") - - let render html = - fragment [] [ - RawText "" - RawText "\n" - html ] - |> Fable.ReactServer.renderToString - - let renderWithMasterTemplate masterCfg navBar titletext bodytext pageSource = - Master.masterTemplate masterCfg navBar titletext bodytext pageSource - |> render - - let renderWithMasterAndWrite masterCfg (outPath : FileInfo) navBar titletext bodytext pageSource = - let contents = renderWithMasterTemplate masterCfg navBar titletext bodytext pageSource - IO.Directory.CreateDirectory(outPath.DirectoryName) |> ignore - - IO.File.WriteAllText(outPath.FullName, contents) - Fake.Core.Trace.tracefn "Rendered to %s" outPath.FullName - - let generateNav (cfg : Configuration) (generatedDocs : GeneratedDoc list) = - let docsDir = cfg.DocsOutputDirectory.FullName - let pages = - generatedDocs - |> List.map(fun gd -> gd.OutputPath) - |> List.filter(fun f -> f.FullName.StartsWith(docsDir "content") |> not) - |> List.filter(fun f -> f.FullName.StartsWith(docsDir "files") |> not) - |> List.filter(fun f -> f.FullName.StartsWith(docsDir "index.html") |> not) - - let topLevelNavs : Nav.TopLevelNav = { - DocsRoot = IO.DirectoryInfo docsDir - DocsPages = pages - } - - let navCfg : Nav.NavConfig = { - SiteBaseUrl = cfg.SiteBaseUrl - GitHubRepoUrl = cfg.GitHubRepoUrl - ProjectName = cfg.ProjectName - TopLevelNav = topLevelNavs - } - - Nav.generateNav navCfg - - let renderGeneratedDocs isWatchMode (cfg : Configuration) (generatedDocs : GeneratedDoc list) = - let nav = generateNav cfg generatedDocs - let masterCfg : Master.MasterTemplateConfig = { - SiteBaseUrl = cfg.SiteBaseUrl - GitHubRepoUrl = cfg.GitHubRepoUrl - ProjectName = cfg.ProjectName - ReleaseVersion = cfg.ReleaseVersion - ReleaseDate = DateTimeOffset.Now - RepositoryRoot = cfg.RepositoryRoot - IsWatchMode = isWatchMode - } - generatedDocs - |> Seq.iter(fun gd -> - let pageSource = - gd.SourcePath - |> Option.map(fun sp -> - sp.FullName.Replace(cfg.RepositoryRoot.FullName, "").Replace("\\", "/") - ) - renderWithMasterAndWrite masterCfg gd.OutputPath nav gd.Title gd.Content pageSource - ) - - - let copyAssets (cfg : Configuration) = - Shell.copyDir (cfg.DocsOutputDirectory.FullName "content") ( cfg.DocsSourceDirectory.FullName "content") (fun _ -> true) - Shell.copyDir (cfg.DocsOutputDirectory.FullName "files") ( cfg.DocsSourceDirectory.FullName "files") (fun _ -> true) - - - let regexReplace (cfg : Configuration) source = - let replacements = - [ - "{{siteBaseUrl}}", (cfg.SiteBaseUrl.ToString().TrimEnd('/')) - ] - (source, replacements) - ||> List.fold(fun state (pattern, replacement) -> - Text.RegularExpressions.Regex.Replace(state, pattern, replacement) - ) - - let generateDocs (libDirs : ProjInfo.References) (docSourcePaths : IGlobbingPattern) (cfg : Configuration) = - let parse (fileName : string) source = - let doc = - let references = - libDirs - |> Array.map(fun fi -> fi.DirectoryName) - |> Array.distinct - |> Array.map(sprintf "-I:%s") - let runtimeDeps = - [| - "-r:System.Runtime" - "-r:System.Net.WebClient" - |] - let compilerOptions = String.Join(' ', Array.concat [runtimeDeps; references]) - let fsiEvaluator = FSharp.Literate.FsiEvaluator(references) - match Path.GetExtension fileName with - | ".fsx" -> - Literate.ParseScriptString( - source, - path = fileName, - compilerOptions = compilerOptions, - fsiEvaluator = fsiEvaluator) - | ".md" -> - let source = regexReplace cfg source - Literate.ParseMarkdownString( - source, - path = fileName, - compilerOptions = compilerOptions, - fsiEvaluator = fsiEvaluator - ) - | others -> failwithf "FSharp.Literal does not support %s file extensions" others - FSharp.Literate.Literate.FormatLiterateNodes(doc, OutputKind.Html, "", true, true) - - let format (doc: LiterateDocument) = - if not <| Seq.isEmpty doc.Errors - then - failwithf "error while formatting file %s. Errors are:\n%A" doc.SourceFile doc.Errors - else - Formatting.format doc.MarkdownDocument true OutputKind.Html - + doc.FormattedTips - - - - docSourcePaths - |> Array.ofSeq - |> Seq.map(fun filePath -> - - Fake.Core.Trace.tracefn "Rendering %s" filePath - let file = IO.File.ReadAllText filePath - let outPath = - let changeExtension ext path = IO.Path.ChangeExtension(path,ext) - filePath.Replace(cfg.DocsSourceDirectory.FullName, cfg.DocsOutputDirectory.FullName) - |> changeExtension ".html" - |> FileInfo - let fs = - file - |> parse filePath - |> format - let contents = - [div [] [ - fs - |> RawText - ]] - - { - SourcePath = FileInfo filePath |> Some - OutputPath = outPath - Content = contents - Title = sprintf "%s-%s" outPath.Name cfg.ProjectName - } - ) - |> Seq.toList - - - let generateAPI (projInfos : ProjInfo.ProjInfo array) (cfg : Configuration) = - let generate (projInfo : ProjInfo.ProjInfo) = - Trace.tracefn "Generating API Docs for %s" projInfo.TargetPath.FullName - let mscorlibDir = - (Uri(typedefof.GetType().Assembly.CodeBase)) //Find runtime dll - .AbsolutePath // removes file protocol from path - |> Path.GetDirectoryName - let references = - projInfo.References - |> Array.toList - |> List.map(fun fi -> fi.DirectoryName) - |> List.distinct - let libDirs = mscorlibDir :: references - let targetApiDir = docsApiDir cfg.DocsOutputDirectory.FullName @@ IO.Path.GetFileNameWithoutExtension(projInfo.TargetPath.Name) - - let generatorOutput = - MetadataFormat.Generate( - projInfo.TargetPath.FullName, - libDirs = libDirs, - sourceFolder = cfg.RepositoryRoot.FullName, - sourceRepo = (cfg.GitHubRepoUrl |> Uri.simpleCombine "tree/master" |> string), - markDownComments = false - ) - - let fi = FileInfo <| targetApiDir @@ (sprintf "%s.html" generatorOutput.AssemblyGroup.Name) - let indexDoc = { - SourcePath = None - OutputPath = fi - Content = [Namespaces.generateNamespaceDocs generatorOutput.AssemblyGroup generatorOutput.Properties] - Title = sprintf "%s-%s" fi.Name cfg.ProjectName - } - - let moduleDocs = - generatorOutput.ModuleInfos - |> List.map (fun m -> - let fi = FileInfo <| targetApiDir @@ (sprintf "%s.html" m.Module.UrlName) - let content = Modules.generateModuleDocs m generatorOutput.Properties - { - SourcePath = None - OutputPath = fi - Content = content - Title = sprintf "%s-%s" m.Module.Name cfg.ProjectName - } - ) - let typeDocs = - generatorOutput.TypesInfos - |> List.map (fun m -> - let fi = FileInfo <| targetApiDir @@ (sprintf "%s.html" m.Type.UrlName) - let content = Types.generateTypeDocs m generatorOutput.Properties - { - SourcePath = None - OutputPath = fi - Content = content - Title = sprintf "%s-%s" m.Type.Name cfg.ProjectName - } - ) - [ indexDoc ] @ moduleDocs @ typeDocs - projInfos - |> Seq.collect(generate) - |> Seq.toList - - let buildDocs (projInfos : ProjInfo.ProjInfo array) (cfg : Configuration) = - let refs = projInfos |> Seq.collect (fun p -> p.References) |> Seq.distinct |> Seq.toArray - copyAssets cfg - let generateDocs = - async { - return generateDocs refs (docsFileGlob cfg.DocsSourceDirectory.FullName) cfg - } - let generateAPI = - async { - return (generateAPI projInfos cfg) - } - Async.Parallel [generateDocs; generateAPI] - |> Async.RunSynchronously - |> Array.toList - |> List.collect id - - let renderDocs (cfg : Configuration) = - let projInfos = cfg.ProjectFilesGlob |> Seq.map(ProjInfo.findReferences) |> Seq.toArray - buildDocs projInfos cfg - |> renderGeneratedDocs false cfg - - let watchDocs (cfg : Configuration) = - let projInfos = cfg.ProjectFilesGlob |> Seq.map(ProjInfo.findReferences) |> Seq.toArray - let initialDocs = buildDocs projInfos cfg - let renderGeneratedDocs = renderGeneratedDocs true - initialDocs |> renderGeneratedDocs cfg - - let refs = projInfos |> Seq.collect (fun p -> p.References) |> Seq.distinct |> Seq.toArray - let d1 = - docsFileGlob cfg.DocsSourceDirectory.FullName - |> ChangeWatcher.run (fun changes -> - printfn "changes %A" changes - changes - |> Seq.iter (fun m -> - printfn "watching %s" m.FullPath - let generated = generateDocs refs (!! m.FullPath) cfg - initialDocs - |> List.filter(fun x -> generated |> List.exists(fun y -> y.OutputPath = x.OutputPath) |> not ) - |> List.append generated - |> List.distinctBy(fun gd -> gd.OutputPath.FullName) - |> renderGeneratedDocs cfg - ) - refreshWebpageEvent.Trigger "m.FullPath" - ) - let d2 = - !! (cfg.DocsSourceDirectory.FullName "content" "**/*") - ++ (cfg.DocsSourceDirectory.FullName "files" "**/*") - |> ChangeWatcher.run(fun changes -> - printfn "changes %A" changes - copyAssets cfg - refreshWebpageEvent.Trigger "Assets" - ) - - - let d3 = - projInfos - |> Seq.map(fun p -> p.TargetPath.FullName) - |> Seq.fold ((++)) (!! "") - - |> ChangeWatcher.run(fun changes -> - changes - |> Seq.iter(fun c -> Trace.logf "Regenerating API docs due to %s" c.FullPath ) - let generated = generateAPI projInfos cfg - initialDocs - |> List.filter(fun x -> generated |> List.exists(fun y -> y.OutputPath = x.OutputPath) |> not ) - |> List.append generated - |> List.distinctBy(fun gd -> gd.OutputPath.FullName) - |> renderGeneratedDocs cfg - refreshWebpageEvent.Trigger "Api" - ) - { disposables = [d1; d2; d3] } :> IDisposable - - -module WebServer = - open Microsoft.AspNetCore.Hosting - open Microsoft.AspNetCore.Builder - open Microsoft.Extensions.FileProviders - open Microsoft.AspNetCore.Http - open System.Net.WebSockets - open System.Diagnostics - - let hostname = "localhost" - let port = 5000 - - /// Helper to determine if port is in use - let waitForPortInUse (hostname : string) port = - let mutable portInUse = false - while not portInUse do - Async.Sleep(10) |> Async.RunSynchronously - use client = new Net.Sockets.TcpClient() - try - client.Connect(hostname,port) - portInUse <- client.Connected - client.Close() - with e -> - client.Close() - - /// Async version of IApplicationBuilder.Use - let useAsync (middlware : HttpContext -> (unit -> Async) -> Async) (app:IApplicationBuilder) = - app.Use(fun env next -> - middlware env (next.Invoke >> Async.AwaitTask) - |> Async.StartAsTask - :> System.Threading.Tasks.Task - ) - - let createWebsocketForLiveReload (httpContext : HttpContext) (next : unit -> Async) = async { - if httpContext.WebSockets.IsWebSocketRequest then - let! websocket = httpContext.WebSockets.AcceptWebSocketAsync() |> Async.AwaitTask - use d = - refreshWebpageEvent.Publish - |> Observable.subscribe (fun m -> - let segment = ArraySegment(m |> Text.Encoding.UTF8.GetBytes) - websocket.SendAsync(segment, WebSocketMessageType.Text, true, httpContext.RequestAborted) - |> Async.AwaitTask - |> Async.Start - - ) - while websocket.State <> WebSocketState.Closed do - do! Async.Sleep(1000) - else - do! next () - } - - let configureWebsocket (appBuilder : IApplicationBuilder) = - appBuilder.UseWebSockets() - |> useAsync (createWebsocketForLiveReload) - |> ignore - - let startWebserver docsDir (url : string) = - WebHostBuilder() - .UseKestrel() - .UseUrls(url) - .Configure(fun app -> - let opts = - StaticFileOptions( - FileProvider = new PhysicalFileProvider(docsDir) - ) - app.UseStaticFiles(opts) |> ignore - configureWebsocket app - ) - .Build() - .Run() - - let openBrowser url = - //https://github.com/dotnet/corefx/issues/10361 - let psi = ProcessStartInfo(FileName = url, UseShellExecute = true) - let proc = Process.Start psi - proc.WaitForExit() - if proc.ExitCode <> 0 then failwithf "opening browser failed" - - let serveDocs docsDir = - async { - waitForPortInUse hostname port - sprintf "http://%s:%d/index.html" hostname port |> openBrowser - } |> Async.Start - startWebserver docsDir (sprintf "http://%s:%d" hostname port) - - -open Argu -open Fake.IO.Globbing.Operators -open DocsTool.CLIArgs -[] -let main argv = - use tempDocsOutDir = DisposableDirectory.Create() - use __ = AppDomain.CurrentDomain.ProcessExit.Subscribe(fun _ -> - dispose tempDocsOutDir - ) - use __ = Console.CancelKeyPress.Subscribe(fun _ -> - dispose tempDocsOutDir - ) - let defaultConfig = { - SiteBaseUrl = Uri(sprintf "http://%s:%d/" WebServer.hostname WebServer.port ) - GitHubRepoUrl = Uri "https://github.com" - RepositoryRoot = IO.DirectoryInfo (__SOURCE_DIRECTORY__ @@ "..") - DocsOutputDirectory = tempDocsOutDir.DirectoryInfo - DocsSourceDirectory = IO.DirectoryInfo "docsSrc" - ProjectName = "" - ProjectFilesGlob = !! "" - ReleaseVersion = "0.1.0" - } - - let errorHandler = ProcessExiter(colorizer = function ErrorCode.HelpText -> None | _ -> Some ConsoleColor.Red) - let programName = - let name = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name - if Fake.Core.Environment.isWindows then - sprintf "%s.exe" name - else - name - - - - let parser = ArgumentParser.Create(programName = programName, errorHandler = errorHandler) - let parsedArgs = parser.Parse argv - match parsedArgs.GetSubCommand() with - | Build args -> - let config = - (defaultConfig, args.GetAllResults()) - ||> List.fold(fun state next -> - match next with - | BuildArgs.SiteBaseUrl url -> { state with SiteBaseUrl = Uri url } - | BuildArgs.ProjectGlob glob -> { state with ProjectFilesGlob = !! glob} - | BuildArgs.DocsOutputDirectory outdir -> { state with DocsOutputDirectory = IO.DirectoryInfo outdir} - | BuildArgs.DocsSourceDirectory srcdir -> { state with DocsSourceDirectory = IO.DirectoryInfo srcdir} - | BuildArgs.GitHubRepoUrl url -> { state with GitHubRepoUrl = Uri url} - | BuildArgs.ProjectName repo -> { state with ProjectName = repo} - | BuildArgs.ReleaseVersion version -> { state with ReleaseVersion = version} - ) - GenerateDocs.renderDocs config - | Watch args -> - let config = - (defaultConfig, args.GetAllResults()) - ||> List.fold(fun state next -> - match next with - | WatchArgs.ProjectGlob glob -> {state with ProjectFilesGlob = !! glob} - | WatchArgs.DocsSourceDirectory srcdir -> { state with DocsSourceDirectory = IO.DirectoryInfo srcdir} - | WatchArgs.GitHubRepoUrl url -> { state with GitHubRepoUrl = Uri url} - | WatchArgs.ProjectName repo -> { state with ProjectName = repo} - | WatchArgs.ReleaseVersion version -> { state with ReleaseVersion = version} - ) - use ds = GenerateDocs.watchDocs config - WebServer.serveDocs config.DocsOutputDirectory.FullName - 0 // return an integer exit code diff --git a/docsTool/README.md b/docsTool/README.md deleted file mode 100644 index 064e868..0000000 --- a/docsTool/README.md +++ /dev/null @@ -1,117 +0,0 @@ -# Docs Tool - -## Example -[MiniScaffold docs example](https://www.jimmybyrd.me/miniscaffold-docs-test/) - -## Docs High Level Design - -This template is based heavily on [What nobody tells you about documentation](https://www.divio.com/blog/documentation/). In `docsSrc` folder you'll see a similar structure to what is described below: - -- **Tutorials** - - is learning-oriented - - allows the newcomer to get started - - is a lesson - - Analogy: teaching a small child how to cook -- **How-To Guides** - - is goal-oriented - - shows how to solve a specific problem - - is a series of steps - - Analogy: a recipe in a cookery book -- **Explanation** - - is understanding-oriented - - explains - - provides background and context - - Analogy: an article on culinary social history -- **Reference** - - is information-oriented - - describes the machinery - - is accurate and complete - - Analogy: a reference encyclopedia article - - -The folders in `docsSrc` are: - -- `content` - custom css, javascript, and similar go here. -- `Explanations` - A content section as defined above. -- `files` - extra files like screenshots, images, videos. -- `How_Tos` - A content section as defined above. -- `Tutorials` - A content section as defined above. -- `index.md` - The entry page to your documentation - -The navbar is generated by the folders in docsSrc, excluding `content` and `files` folders. Looking at the [example](https://www.jimmybyrd.me/miniscaffold-docs-test/) we can the navbar containing: - -- `Api References` -- `Explanations` -- `How Tos` -- `Tutorials` - -The odd one not generated from the convention of your folders in docsSrc is Api References. This is generated by the [XML Doc Comments](https://docs.microsoft.com/en-us/dotnet/csharp/codedoc) in your libraries under the `src` folder. - - -## Running docs tool - -``` -USAGE: docsTool [--help] [ []] - -SUBCOMMANDS: - - watch Builds the docs, serves the content, and watches for changes to the content. - build Builds the docs - - Use 'docsTool --help' for additional information. -``` - -### build - -Builds the docs - -``` -USAGE: docsTool build [--help] [--sitebaseurl ] [--projectglob ] [--docsoutputdirectory ] [--docssourcedirectory ] [--githubrepourl ] [--projectname ] - [--releaseversion ] - -OPTIONS: - - --sitebaseurl - The public site's base url. - --projectglob - The glob for the dlls to generate API documentation - --docsoutputdirectory - The docs output directory. - --docssourcedirectory - The docs source directory. - --githubrepourl - The GitHub repository url. - --projectname - The project name. - --releaseversion - The project's Release Version name. - --help display this list of options. - -``` - - -### watch - -Builds the docs, serves the content, and watches for changes to the content. - -``` - -USAGE: docsTool watch [--help] [--projectglob ] [--docsoutputdirectory ] [--docssourcedirectory ] [--githubrepourl ] [--projectname ] [--releaseversion ] - -OPTIONS: - - --projectglob - The glob for the dlls to generate API documentation. - --docsoutputdirectory - The docs output directory. - --docssourcedirectory - The docs source directory. - --githubrepourl - The GitHub repository url. - --projectname - The project name. - --releaseversion - The project's Release Version name. - --help display this list of options. -``` - diff --git a/docsTool/docsTool.fsproj b/docsTool/docsTool.fsproj deleted file mode 100644 index 4c02724..0000000 --- a/docsTool/docsTool.fsproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - Exe - netcoreapp2.2 - false - - - - - - - - - - - - - - - - - - - diff --git a/docsTool/paket.references b/docsTool/paket.references deleted file mode 100644 index 296f963..0000000 --- a/docsTool/paket.references +++ /dev/null @@ -1,12 +0,0 @@ -group Docs -Argu -FSharp.Core -Fake.IO.FileSystem -Fake.DotNet.Cli -FSharp.Literate -Fable.React -Microsoft.AspNetCore.StaticFiles -Microsoft.AspNetCore.Hosting -Microsoft.AspNetCore.Server.Kestrel -Microsoft.AspNetCore.WebSockets -Dotnet.ProjInfo.Workspace.FCS diff --git a/docsTool/templates/helpers.fs b/docsTool/templates/helpers.fs deleted file mode 100644 index 0a27bf8..0000000 --- a/docsTool/templates/helpers.fs +++ /dev/null @@ -1,47 +0,0 @@ -module Helpers -open System -open Fable.React -open Fable.React.Props -open FSharp.MetadataFormat - - -let createAnchorIcon name = - let normalized = name - let href = sprintf "#%s" normalized - a [Href href; Id normalized] [ - str "#" - ] - -let createAnchor fullName name = - let fullNameNormalize = fullName - a [ - Name fullNameNormalize - Href (sprintf "#%s" fullNameNormalize) - Class "anchor" - ] [ - str name - ] - -let renderNamespace (ns: Namespace) = [ - h3 [] [ str "Namespace" ] - str ns.Name -] - -let inline isObsolete< ^t when ^t : (member IsObsolete: bool)> t = - (^t : (member IsObsolete: bool) (t)) - -let inline obsoleteMessage< ^t when ^t : (member ObsoleteMessage: string)> t = - (^t : (member ObsoleteMessage:string) (t)) - -let inline renderObsoleteMessage item = - if isObsolete item - then - let text = match obsoleteMessage item with | "" | null -> "This member is obsolete" | s -> s - [ - div [Class "alert alert-warning"] [ - strong [] [ str "OBSOLETE: "] - str text - ] - ] - else - [] diff --git a/docsTool/templates/master.fs b/docsTool/templates/master.fs deleted file mode 100644 index 00fdfcb..0000000 --- a/docsTool/templates/master.fs +++ /dev/null @@ -1,156 +0,0 @@ -module Master - -open System -open Fable.React -open Fable.React.Props -open DocsTool - -type MasterTemplateConfig = { - SiteBaseUrl : Uri - GitHubRepoUrl : Uri - ProjectName : string - ReleaseVersion : string - ReleaseDate : DateTimeOffset - RepositoryRoot: IO.DirectoryInfo - IsWatchMode : bool -} - -type FAIcon = -| Solid of name: string -| Brand of name: string - -let footerLink uri image linkText = - let faClass, img = - match image with - | Solid name -> "fas", name - | Brand name -> "fab", name - a [Href uri; Class "text-white"] [ - i [Class (sprintf "%s fa-%s fa-fw mr-2" faClass img)] [] - str linkText - ] - -let repoFileLink repoUrl filePathFromRepoRoot = - let link = repoUrl |> Uri.simpleCombine (sprintf "blob/master/%s" filePathFromRepoRoot) - footerLink link - -let linkColumn headerTitle items = - div [Class "col-12 col-md-4 mb-4 mb-md-0"] [ - div [Class "text-light"] [ - h2 [Class "h5"] [ str headerTitle ] - ul [Class "list-group list-group-flush"] - (items |> List.choose (function | [] -> None - | items -> Some(li [Class "list-group-item bg-dark ml-0 pl-0"] items))) - ] - ] - -let renderFooter (cfg : MasterTemplateConfig) (pageSource : string option) = - let hasFile relPath = - match cfg.RepositoryRoot.GetFiles(relPath) with - | [||] -> false - | [|file|] -> true - | files -> false - - let repoFileLink relPath image title = - if hasFile relPath - then [ repoFileLink cfg.GitHubRepoUrl relPath image title ] - else [] - - footer [Class "footer font-small m-0 py-4 bg-dark"] [ - div [Class "container"] [ - div [Class "row"] [ - linkColumn "Project Resources" [ - repoFileLink "README.md" (Solid "book-reader") "README" - repoFileLink "RELEASE_NOTES.md" (Solid "sticky-note") "Release Notes / Changelog" - repoFileLink "LICENSE.md" (Solid "id-card") "License" - repoFileLink "CONTRIBUTING.md" (Solid "directions") "Contributing" - repoFileLink "CODE_OF_CONDUCT.md" (Solid "users") "Code of Conduct" - ] - linkColumn "Other Links" [ - [footerLink "https://docs.microsoft.com/en-us/dotnet/fsharp/" (Brand "microsoft") "F# Documentation"] - [footerLink "https://fsharp.org/guides/slack/" (Brand "slack") "F# Slack"] - [a [Href "http://foundation.fsharp.org/"; Class "text-white"] [ - img [Class "fsharp-footer-logo mr-2"; Src "https://fsharp.org/img/logo/fsharp.svg"; Alt "FSharp Logo"] - str "F# Software Foundation" - ]] - ] - linkColumn "Metadata" [ - [str "Generated for version " - a [Class "text-white"; Href (cfg.GitHubRepoUrl |> Uri.simpleCombine (sprintf "releases/tag/%s" cfg.ReleaseVersion))] [str cfg.ReleaseVersion] - str (sprintf " on %s" (cfg.ReleaseDate.ToString("yyyy/MM/dd")))] - match pageSource with - | Some p -> - let page = cfg.GitHubRepoUrl |> Uri.simpleCombine "edit/master" |> Uri |> Uri.simpleCombine p - [ str "Found an issue? " - a [Class "text-white"; Href (page |> string)] [ str "Edit this page." ] ] - | None -> - () - ] - ] - div [Class "row"] [ - div [Class "col text-center"] [ - small [Class "text-light"] [ - i [Class "fas fa-copyright mr-1"] [] - str (sprintf "%s BinaryDefense.FSharp.Analyzers, All rights reserved" (DateTimeOffset.UtcNow.ToString("yyyy"))) - ] - ] - ] - ] - ] - -let masterTemplate (cfg : MasterTemplateConfig) navBar titletext bodyText pageSource = - html [Lang "en"] [ - head [] [ - title [] [ str (sprintf "%s docs / %s" cfg.ProjectName titletext) ] - meta [Name "viewport"; HTMLAttr.Content "width=device-width, initial-scale=1" ] - link [ - Href (cfg.SiteBaseUrl |> Uri.simpleCombine (sprintf "/content/toggle-bootstrap.min.css?version=%i" cfg.ReleaseDate.Ticks) ) - Type "text/css" - Rel "stylesheet" - ] - link [ - Href (cfg.SiteBaseUrl |> Uri.simpleCombine (sprintf "/content/toggle-bootstrap-dark.min.css?version=%i" cfg.ReleaseDate.Ticks) ) - Type "text/css" - Rel "stylesheet" - ] - link [ - Href "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css" - Rel "stylesheet" - Integrity "sha384-KA6wR/X5RY4zFAHpv/CnoG2UW1uogYfdnP67Uv7eULvTveboZJg0qUpmJZb5VqzN" - CrossOrigin "anonymous" - ] - link [ - Href (cfg.SiteBaseUrl |> Uri.simpleCombine (sprintf "/content/style.css?version=%i" cfg.ReleaseDate.Ticks) ) - Type "text/css" - Rel "stylesheet" - ] - - ] - body [] [ - yield navBar - yield div [Class "wrapper d-flex flex-column justify-content-between min-vh-100"] [ - main [Class "container main mb-4"] bodyText - renderFooter cfg pageSource - ] - yield script [Src (cfg.SiteBaseUrl |> Uri.simpleCombine (sprintf "/content/themes.js?version=%i" cfg.ReleaseDate.Ticks)) ] [] - yield script [ - Src "https://code.jquery.com/jquery-3.4.1.slim.min.js" - Integrity "sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" - CrossOrigin "anonymous" - ] [] - yield script [ - Src "https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" - Integrity "sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" - CrossOrigin "anonymous" - ] [] - yield script [ - Src "https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" - Integrity "sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" - CrossOrigin "anonymous" - ] [] - yield script [Src (cfg.SiteBaseUrl |> Uri.simpleCombine (sprintf "/content/tips.js?version=%i" cfg.ReleaseDate.Ticks)) ] [] - if cfg.IsWatchMode then - yield script [Src (cfg.SiteBaseUrl |> Uri.simpleCombine (sprintf "/content/hotload.js?version=%i" cfg.ReleaseDate.Ticks)) ] [] - yield script [Src (cfg.SiteBaseUrl |> Uri.simpleCombine (sprintf "/content/submenu.js?version=%i" cfg.ReleaseDate.Ticks)) ] [] - yield script [Src (cfg.SiteBaseUrl |> Uri.simpleCombine (sprintf "/content/cleanups.js?version=%i" cfg.ReleaseDate.Ticks)) ] [] - ] - ] diff --git a/docsTool/templates/modules.fs b/docsTool/templates/modules.fs deleted file mode 100644 index 4ab8941..0000000 --- a/docsTool/templates/modules.fs +++ /dev/null @@ -1,126 +0,0 @@ -module Modules -open System -open Fable.React -open Fable.React.Props -open FSharp.MetadataFormat -open PartNested -open PartMembers -open Helpers - - -let generateModuleDocs (moduleInfo : ModuleInfo) (props) = - let members = moduleInfo.Module.AllMembers - let comment = moduleInfo.Module.Comment - - let byCategory = - members - |> List.groupBy(fun m -> m.Category) - |> List.sortBy(fun (g,v) -> if String.IsNullOrEmpty g then "ZZZ" else g) - |> List.mapi(fun i (key, value) -> { - Index = i - GroupKey = key - Members = value |> List.sortBy(fun m -> m.Name) - Name = if String.IsNullOrEmpty key then "Other module members" else key - }) - let nestModules = moduleInfo.Module.NestedModules - let nestTypes = moduleInfo.Module.NestedTypes - [ - yield div [ Class "container-fluid py-3" ] [ - yield div [ Class "row" ] [ - yield div [ Class "col-12" ] [ - yield h1 [] [ - str moduleInfo.Module.Name - ] - yield! renderObsoleteMessage moduleInfo.Module - yield! renderNamespace moduleInfo.Namespace - yield dl [] [ - if moduleInfo.ParentModule.IsSome then - yield dt [] [ - str "Parent Module" - ] - yield dd [] [ - a [ - Href (sprintf "%s.html" moduleInfo.ParentModule.Value.UrlName) - ] [ - str moduleInfo.ParentModule.Value.Name - ] - ] - if moduleInfo.Module.Attributes |> Seq.isEmpty |> not then - yield dt [] [ - str "Attributes" - ] - yield dd [] [ - for attr in moduleInfo.Module.Attributes do - yield str (attr.Format()) - yield br [] - ] - ] - - yield div [ - Class "xmldoc" - ] [ - for sec in comment.Sections do - if byCategory |> Seq.exists (fun g -> g.GroupKey = sec.Key) |> not then - if sec.Key <> "" then - yield h2 [] [ - RawText sec.Key - ] - yield RawText sec.Value - ] - - - if byCategory |> Seq.length > 1 then - yield h2 [] [ - str "Table of contents" - ] - - yield ul [] [ - for g in byCategory do - yield li [] [ - a [ - Href (g.Index.ToString() |> sprintf "#section%s") - ] [ - str g.Name - ] - ] - ] - - if (nestTypes |> Seq.length) + (nestModules |> Seq.length) > 0 then - yield h2 [] [ - str "Nested types and modules" - ] - - yield! (partNested (nestTypes |> Seq.toArray) (nestModules |> Seq.toArray)) - - for g in byCategory do - if byCategory |> Seq.length > 1 then - yield h2 [] [ - str g.Name - a [ - Name (sprintf "section%d" g.Index) - ] [ - str " " - ] - ] - - let info = comment.Sections |> Seq.tryFind(fun kvp -> kvp.Key = g.GroupKey) - - match info with - | Some info -> - yield div [ - Class "xmldoc" - ] [ - str info.Value - ] - | None -> - yield nothing - - yield! partMembers "Functions and values" "Function or value" (g.Members |> Seq.filter(fun m -> m.Kind = MemberKind.ValueOrFunction)) - - yield! partMembers "Type extensions" "Type extension" (g.Members |> Seq.filter(fun m -> m.Kind = MemberKind.TypeExtension)) - - yield! partMembers "Active patterns" "Active pattern" (g.Members |> Seq.filter(fun m -> m.Kind = MemberKind.ActivePattern)) - ] - ] - ] - ] diff --git a/docsTool/templates/namespaces.fs b/docsTool/templates/namespaces.fs deleted file mode 100644 index 42de5ef..0000000 --- a/docsTool/templates/namespaces.fs +++ /dev/null @@ -1,73 +0,0 @@ -module Namespaces - -open System -open Fable.React -open Fable.React.Props -open FSharp.MetadataFormat - - -type ByCategory = { - Name : string - Index : string - Types : Type array - Modules : Module array -} - -let generateNamespaceDocs (asm : AssemblyGroup) (props) = - let parts = - asm.Namespaces - |> Seq.mapi(fun nsi ns -> - let allByCategories = - ns.Types - |> Seq.map(fun t -> t.Category) - |> Seq.append (ns.Modules |> Seq.map(fun m -> m.Category)) - |> Seq.distinct - |> Seq.sortBy(fun s -> - if String.IsNullOrEmpty(s) then "ZZZ" - else s) - |> Seq.mapi(fun ci c -> - { - Name = if String.IsNullOrEmpty(c) then "Other namespace members" else c - Index = sprintf "%d_%d" nsi ci - Types = ns.Types |> Seq.filter(fun t -> t.Category = c) |> Seq.toArray - Modules = ns.Modules |> Seq.filter(fun m -> m.Category = c) |> Seq.toArray - }) - |> Seq.filter(fun c -> c.Types.Length + c.Modules.Length > 0) - |> Seq.toArray - [ - yield h2 [] [ - Helpers.createAnchor ns.Name ns.Name - ] - if allByCategories.Length > 1 then - yield ul [] [ - for c in allByCategories do - yield - li [] [ - a [Href (sprintf "#section%s" c.Index)] [ - str c.Name - ] - ] - ] - - - for c in allByCategories do - if allByCategories.Length > 1 then - yield h3 [] [ - a [Class "anchor"; Name (sprintf "section%s" c.Index); Href (sprintf "#section%s" c.Index)] [ - str c.Name - ] - ] - yield! PartNested.partNested c.Types c.Modules - ] - ) - |> Seq.collect id - div [ Class "container-fluid py-3" ] [ - div [ Class "row" ] [ - div [ Class "col-12" ] [ - yield h1 [] [ - Helpers.createAnchor asm.Name asm.Name - ] - yield! parts - ] - ] - ] diff --git a/docsTool/templates/nav.fs b/docsTool/templates/nav.fs deleted file mode 100644 index 33d3ba6..0000000 --- a/docsTool/templates/nav.fs +++ /dev/null @@ -1,189 +0,0 @@ -module Nav - -open System -open DocsTool -open Fable.React -open Fable.React.Props - -type NameOfArticle = string -type UrlPath = string - -type TopLevelNav = { - DocsRoot : IO.DirectoryInfo - DocsPages : IO.FileInfo list -} - -type NavConfig = { - SiteBaseUrl : Uri - GitHubRepoUrl : Uri - ProjectName : string - TopLevelNav : TopLevelNav -} - -let normalizeText text = - System.Text.RegularExpressions.Regex.Replace(text, @"[^0-9a-zA-Z\.]+", " ") - -let normalizeStr = normalizeText >> str - -let navItem link inner = - li [ - Class "nav-item" - ] [ - a [ - Class "nav-link" - Href link - ] inner - ] - -let navItemText text link = - navItem link [ normalizeStr text ] - -let navItemIconOnly link ariaLabel inner = - li [Class "nav-item"] [ - a [ - Class "nav-link" - HTMLAttr.Custom("aria-label", ariaLabel) - Href link - ] inner - ] - -let dropDownNavMenu text items = - li [ Class "nav-item dropdown" ][ - a [ - Id (sprintf "navbarDropdown-%s" text) - Href "#" - DataToggle "dropdown" - AriaHasPopup true - AriaExpanded false - Class "nav-link dropdown-toggle" ] - [ normalizeStr text ] - ul [ HTMLAttr.Custom ("aria-labelledby", "dropdownMenu1") - Class "dropdown-menu border-0 shadow" ] items ] - -let dropDownNavItem text link = - li [ - Class "nav-item" - ] [ - a [ - Class "dropdown-item" - Href link - ] [ - normalizeStr text - ] - ] -let dropdownSubMenu text items = - li [ Class "dropdown-submenu" ] [ - a [ Id (sprintf "navbarDropdown-%s" text) - Href "#" - Role "button" - DataToggle "dropdown" - AriaHasPopup true - AriaExpanded false - Class "dropdown-item dropdown-toggle" ] [ - normalizeStr text ] - ul [ - HTMLAttr.Custom ("aria-labelledby", "dropdownMenu2") - Class "dropdown-menu border-0 shadow" ] items - ] - -type NavTree = -| File of title:string * link:string -| Folder of title: string * NavTree list - -let rec sortNavTree (navtree : NavTree list) = - navtree - |> List.map(fun navTree -> - match navTree with - | File (t,l) -> File (t,l) - | Folder(title, nodes) -> Folder(title, sortNavTree nodes) - ) - |> List.sortBy(fun navtree -> - match navtree with - | File(title,_) -> title - | Folder(title, _) -> title - ) - -let navTreeFromPaths (rootPath : IO.DirectoryInfo) (files : IO.FileInfo list) = - let rec addPath subFilePath parts nodes = - match parts with - | [] -> nodes - | hp :: tp -> - addHeadPath subFilePath hp tp nodes - and addHeadPath subFilePath (part : string) remainingParts (nodes : NavTree list)= - match nodes with - | [] -> - if part.EndsWith("html") then - File(IO.Path.GetFileNameWithoutExtension part, subFilePath) - else - Folder(part, addPath subFilePath remainingParts []) - |> List.singleton - | Folder(title, subnodes) :: nodes when title = part -> Folder(title, addPath subFilePath remainingParts subnodes ) :: nodes - | hn :: tn -> hn :: addHeadPath subFilePath part remainingParts tn - - ([], files) - ||> List.fold(fun state file -> - let subFilePath = file.FullName.Replace(rootPath.FullName, "") - let pathParts = subFilePath.Split(IO.Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries) |> Array.toList - addPath subFilePath pathParts state - ) - - - -let generateNavMenus siteBaseUrl (navTree : NavTree list) = - let rec innerDo depth (navTree : NavTree list) = - navTree - |> List.map(fun nav -> - match nav with - | File (title, link) when depth = 0 -> navItemText title (siteBaseUrl |> Uri.simpleCombine link) - | File (title, link) -> dropDownNavItem title (siteBaseUrl |> Uri.simpleCombine link) - | Folder (title, subtree) when depth = 0 -> - innerDo (depth + 1) subtree - |> dropDownNavMenu title - | Folder (title, subtree) -> - innerDo (depth + 1) subtree - |> dropdownSubMenu title - ) - innerDo 0 navTree - - - -let generateNav (navCfg : NavConfig) = - nav [ - Class "navbar navbar-expand-md sticky-top navbar-dark bg-dark" - ] [ - a [ - Class "navbar-brand" - Href (navCfg.SiteBaseUrl |> Uri.simpleCombine "/index.html") - ] [ - i [ Class "fa fa-car text-white mr-2"] [] - str (navCfg.ProjectName) - ] - button [ - Class "navbar-toggler" - Type "button" - DataToggle "collapse" - HTMLAttr.Custom("data-target","#navbarNav" ) - HTMLAttr.Custom("aria-controls","navbarNav" ) - HTMLAttr.Custom("aria-expanded","false" ) - HTMLAttr.Custom("aria-label","Toggle navigation" ) - ] [ - span [Class "navbar-toggler-icon"] [] - ] - div [ Class "collapse navbar-collapse" - Id "navbarNav" ] [ - ul [ Class "navbar-nav mr-auto" ] [ - yield! navTreeFromPaths navCfg.TopLevelNav.DocsRoot navCfg.TopLevelNav.DocsPages |> sortNavTree |> generateNavMenus navCfg.SiteBaseUrl - ] - ul [ Class "navbar-nav"] [ - button [Id "theme-toggle"; Class ""] [ - str "" - ] - navItemIconOnly (string navCfg.GitHubRepoUrl) (sprintf "%s Repository on Github" navCfg.ProjectName) [ - i [ Class "fab fa-github fa-lg fa-fw text-light"] [] - ] - ] - ] - ] - - - diff --git a/docsTool/templates/partMembers.fs b/docsTool/templates/partMembers.fs deleted file mode 100644 index fc5d770..0000000 --- a/docsTool/templates/partMembers.fs +++ /dev/null @@ -1,135 +0,0 @@ -module PartMembers - -open System -open Fable.React -open Fable.React.Props -open FSharp.MetadataFormat -open System.Collections.Generic -open Helpers - -type ModuleByCategory = { - Index : int - GroupKey : string - Members : list - Name : string -} - - -let signature (m : Member) = seq { - if m.Details.Signature |> String.IsNullOrEmpty |> not then - yield - code [ Class "function-or-value"] [ - str m.Details.Signature - ] -} - -let repoSourceLink (m: Member) = seq { - if m.Details.FormatSourceLocation |> String.IsNullOrEmpty |> not then - yield a [ - Href m.Details.FormatSourceLocation - Class "float-right" - HTMLAttr.Custom("aria-label", "View source on GitHub") - ] [ - yield i [ - Class "fab fa-github text-dark" - ] [] - ] -} - -let replaceh2withh5 (content : string) = - content.Replace("

", "

") - - -let normalize (content : string) = - content - |> replaceh2withh5 - - - -let commentBlock (c: Comment) = - let (|EmptyDefaultBlock|NonEmptyDefaultBlock|Section|) (KeyValue(section, content)) = - match section, content with - | "", c when String.IsNullOrEmpty c -> EmptyDefaultBlock - | "", c -> NonEmptyDefaultBlock c - | section, content -> Section (section, content) - - let renderSection (s : KeyValuePair): Fable.React.ReactElement list = - match s with - | EmptyDefaultBlock -> [] - | NonEmptyDefaultBlock content -> [ div [ Class "comment-block" ] [ RawText (normalize content) ] ] - | Section(name, content) -> [ h5 [] [ str name ] // h2 is obnoxiously large for this context, go with the smaller h5 - RawText (normalize content) ] - c.Sections - |> List.collect renderSection - -let compiledName (m: Member) = seq { - if m.Details.FormatCompiledName |> String.IsNullOrEmpty |> not then - yield p [] [ - strong [] [ str "CompiledName:" ] - code [] [ str m.Details.FormatCompiledName ] - ] -} - -let partMembers (header : string) (tableHeader : string) (members : #seq) = [ - if members |> Seq.length > 0 then - yield h3 [] [ - str header - ] - - yield table [ - Class "table" - ] [ - thead [] [ - - tr [] [ - th [Class "fit"] [ - - ] - th [] [ - str tableHeader - ] - - th [] [ - str "Signature" - ] - - th [] [ - str "Description" - ] - ] - ] - tbody [] [ - for it in members do - let id = Guid.NewGuid().ToString() - yield tr [] [ - td [] [ - Helpers.createAnchorIcon (it.Details.FormatUsage(40)) - ] - td [ - Class "member-name" - ] [ - code [ - Class "function-or-value" - HTMLAttr.Custom("data-guid", id) - ] [ - str (it.Details.FormatUsage(40)) - ] - ] - td [ - Class "member-name" - ] [ - yield! signature it - ] - - td [ - Class "xmldoc" - ] [ - yield! renderObsoleteMessage it - yield! repoSourceLink it - yield! commentBlock it.Comment - yield! compiledName it - ] - ] - ] - ] -] diff --git a/docsTool/templates/partNested.fs b/docsTool/templates/partNested.fs deleted file mode 100644 index e8c9c24..0000000 --- a/docsTool/templates/partNested.fs +++ /dev/null @@ -1,77 +0,0 @@ -module PartNested - -open System -open Fable.React -open Fable.React.Props -open FSharp.MetadataFormat -open Helpers - -let partNested (types : Type array) (modules : Module array) = - [ - if types.Length > 0 then - yield table [ Class "table" ] [ - thead [] [ - tr [] [ - th [Class "fit"] [ - - ] - th [] [ - str "Type" - ] - th [] [ - str "Description" - ] - ] - ] - tbody [] [ - for t in types do - yield tr [] [ - td [] [ - Helpers.createAnchorIcon t.Name - ] - td [Class "type-name"] [ - a [Href (sprintf "%s.html" t.UrlName)] [ - str t.Name - ] - ] - td [Class "xmldoc"] [ - yield! renderObsoleteMessage t - yield RawText t.Comment.Blurb - ] - ] - ] - ] - if modules.Length > 0 then - yield table [ Class "table" ] [ - thead [] [ - tr [] [ - th [Class "fit"] [ - - ] - th [] [ - str "Module" - ] - th [] [ - str "Description" - ] - ] - ] - tbody [] [ - for t in modules do - yield tr [] [ - td [] [ - Helpers.createAnchorIcon t.Name - ] - td [Class "Modules-name"] [ - a [Href (sprintf "%s.html" t.UrlName)] [ - str t.Name - ] - ] - td [Class "xmldoc"] [ - yield! renderObsoleteMessage t - yield RawText t.Comment.Blurb - ] - ] - ] - ] - ] diff --git a/docsTool/templates/types.fs b/docsTool/templates/types.fs deleted file mode 100644 index 20d3091..0000000 --- a/docsTool/templates/types.fs +++ /dev/null @@ -1,113 +0,0 @@ -module Types - -open System -open Fable.React -open Fable.React.Props -open FSharp.MetadataFormat -open PartMembers -open Helpers - -let generateTypeDocs (model : TypeInfo) (props) = - let members = model.Type.AllMembers - let comment = model.Type.Comment - let ``type`` = model.Type - let byCategory = - members - |> List.groupBy (fun m -> m.Category) - |> List.sortBy (fun (k,v) -> if String.IsNullOrEmpty(k) then "ZZZ" else k ) - |> List.mapi (fun i (k,v) -> { - Index = i - GroupKey = k - Members = v |> List.sortBy (fun m -> if m.Kind = MemberKind.StaticParameter then "" else m.Name) - Name = if String.IsNullOrEmpty(k) then "Other type members" else k - }) - [ - yield h1 [] [ - str model.Type.Name - ] - - yield p [] [ - yield! renderObsoleteMessage model.Type - yield! renderNamespace model.Namespace - if model.HasParentModule then - yield br [] - yield span [] [ - str "Parent Module: " - - a [ - Href (sprintf "%s.html" model.ParentModule.Value.UrlName) - ] [ - str model.ParentModule.Value.Name - ] - ] - - - if ``type``.Attributes |> Seq.isEmpty |> not then - yield br [] - yield span [] [ - yield str "Attributes: " - - yield br [] - - for attr in ``type``.Attributes do - yield str (attr.Format()) - yield br [] - ] - ] - - yield div [ - Class "xmldoc" - ] [ - for sec in comment.Sections do - if byCategory |> Seq.exists (fun m -> m.GroupKey = sec.Key) |> not then - if sec.Key <> "" then - yield h2 [] [ - str sec.Key - ] - yield RawText sec.Value - ] - - if byCategory |> Seq.length > 1 then - yield h2 [] [ - str "Table of contents" - ] - - yield ul [] [ - for g in byCategory do - yield li [] [ - a [ - Href (sprintf "#section%d" g.Index) - ] [ - str g.Name - ] - ] - ] - - for g in byCategory do - if byCategory |> Seq.length > 1 then - yield h2 [] [ - str g.Name - - a [ - Name (sprintf "section%d" g.Index) - ] [ - str " " - ] - ] - - match comment.Sections |> Seq.tryFind (fun kvp -> kvp.Key = g.GroupKey) with - | Some info -> - yield div [ - Class "xmldoc" - ] [ - str info.Value - ] - | None -> yield nothing - - yield! partMembers "Union Cases" "Union Case" (g.Members |> Seq.filter(fun m -> m.Kind = MemberKind.UnionCase)) - yield! partMembers "Record Fields" "Record Field" (g.Members |> Seq.filter(fun m -> m.Kind = MemberKind.RecordField)) - yield! partMembers "Static parameters" "Static parameters" (g.Members |> Seq.filter(fun m -> m.Kind = MemberKind.StaticParameter)) - yield! partMembers "Contructors" "Constructor" (g.Members |> Seq.filter(fun m -> m.Kind = MemberKind.Constructor)) - yield! partMembers "Instance members" "Instance member" (g.Members |> Seq.filter(fun m -> m.Kind = MemberKind.InstanceMember)) - yield! partMembers "Static members" "Static member" (g.Members |> Seq.filter(fun m -> m.Kind = MemberKind.StaticMember)) - ] diff --git a/src/AnalyzerVs/NpgsqlFSharpVs.csproj b/src/AnalyzerVs/NpgsqlFSharpVs.csproj index f28186e..c42ced1 100644 --- a/src/AnalyzerVs/NpgsqlFSharpVs.csproj +++ b/src/AnalyzerVs/NpgsqlFSharpVs.csproj @@ -51,9 +51,7 @@ - - Component - + @@ -84,6 +82,7 @@ Always true + Designer @@ -147,17 +146,6 @@ --> - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\fsharp.compiler.service\36.0.3\lib\netstandard2.0\FSharp.Compiler.Service.dll - True - True - - - - @@ -178,361 +166,4 @@ - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.buffers\4.5.0\lib\netstandard2.0\System.Buffers.dll - True - True - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.buffers\4.5.0\ref\netstandard2.0\System.Buffers.dll - False - True - - - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.collections\4.3.0\ref\netcore50\System.Collections.dll - False - True - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.collections\4.3.0\ref\netstandard1.3\System.Collections.dll - False - True - - - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.collections.immutable\1.7.0\lib\netstandard2.0\System.Collections.Immutable.dll - True - True - - - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.diagnostics.contracts\4.3.0\lib\netcore50\System.Diagnostics.Contracts.dll - True - True - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.diagnostics.contracts\4.3.0\ref\netcore50\System.Diagnostics.Contracts.dll - False - True - - - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.diagnostics.debug\4.3.0\ref\netcore50\System.Diagnostics.Debug.dll - False - True - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.diagnostics.debug\4.3.0\ref\netstandard1.3\System.Diagnostics.Debug.dll - False - True - - - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.globalization\4.3.0\ref\netcore50\System.Globalization.dll - False - True - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.globalization\4.3.0\ref\netstandard1.3\System.Globalization.dll - False - True - - - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.io\4.3.0\ref\netcore50\System.IO.dll - False - True - - - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.linq\4.3.0\lib\netcore50\System.Linq.dll - True - True - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.linq\4.3.0\ref\netcore50\System.Linq.dll - False - True - - - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.memory\4.5.3\lib\netstandard2.0\System.Memory.dll - True - True - - - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.reflection\4.3.0\ref\netcore50\System.Reflection.dll - False - True - - - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.reflection.emit\4.7.0\lib\netcore50\System.Reflection.Emit.dll - True - True - - - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.reflection.emit.ilgeneration\4.7.0\lib\netcore50\System.Reflection.Emit.ILGeneration.dll - True - True - - - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.reflection.metadata\1.8.0\lib\netstandard2.0\System.Reflection.Metadata.dll - True - True - - - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.reflection.primitives\4.3.0\ref\netcore50\System.Reflection.Primitives.dll - False - True - - - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.reflection.typeextensions\4.7.0\lib\netcore50\System.Reflection.TypeExtensions.dll - True - True - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.reflection.typeextensions\4.7.0\lib\netstandard2.0\System.Reflection.TypeExtensions.dll - True - True - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.reflection.typeextensions\4.7.0\ref\netstandard2.0\System.Reflection.TypeExtensions.dll - False - True - - - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.resources.resourcemanager\4.3.0\ref\netcore50\System.Resources.ResourceManager.dll - False - True - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.resources.resourcemanager\4.3.0\ref\netstandard1.0\System.Resources.ResourceManager.dll - False - True - - - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.runtime\4.3.1\ref\netcore50\System.Runtime.dll - False - True - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.runtime\4.3.1\ref\netstandard1.5\System.Runtime.dll - False - True - - - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.runtime.compilerservices.unsafe\4.7.0\lib\netcoreapp2.0\System.Runtime.CompilerServices.Unsafe.dll - True - True - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.runtime.compilerservices.unsafe\4.7.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll - True - True - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.runtime.compilerservices.unsafe\4.7.0\ref\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll - False - True - - - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.runtime.extensions\4.3.1\ref\netcore50\System.Runtime.Extensions.dll - False - True - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.runtime.extensions\4.3.1\ref\netstandard1.5\System.Runtime.Extensions.dll - False - True - - - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.runtime.interopservices\4.3.0\ref\netcore50\System.Runtime.InteropServices.dll - False - True - - - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.runtime.loader\4.3.0\lib\netstandard1.5\System.Runtime.Loader.dll - True - True - - - - - - - ..\..\..\..\Users\zaidn\.nuget\packages\system.runtime.loader\4.3.0\ref\netstandard1.5\System.Runtime.Loader.dll - False - True - - - - \ No newline at end of file diff --git a/src/AnalyzerVs/paket.references b/src/AnalyzerVs/paket.references new file mode 100644 index 0000000..6f627f4 --- /dev/null +++ b/src/AnalyzerVs/paket.references @@ -0,0 +1 @@ +FSharp.Core diff --git a/src/Build/Build.fsproj b/src/Build/Build.fsproj deleted file mode 100644 index 7812b39..0000000 --- a/src/Build/Build.fsproj +++ /dev/null @@ -1,23 +0,0 @@ - - - - Exe - netcoreapp3.1 - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Build/Files.fs b/src/Build/Files.fs deleted file mode 100644 index 670c882..0000000 --- a/src/Build/Files.fs +++ /dev/null @@ -1,13 +0,0 @@ -[] -module Files - -open System.IO -open System.Linq - -/// Recursively tries to find the parent of a file starting from a directory -let rec findParent (directory: string) (fileToFind: string) = - let path = if Directory.Exists(directory) then directory else Directory.GetParent(directory).FullName - let files = Directory.GetFiles(path) - if files.Any(fun file -> Path.GetFileName(file).ToLower() = fileToFind.ToLower()) - then path - else findParent (DirectoryInfo(path).Parent.FullName) fileToFind \ No newline at end of file diff --git a/src/Build/Program.fs b/src/Build/Program.fs deleted file mode 100644 index ed2a7a7..0000000 --- a/src/Build/Program.fs +++ /dev/null @@ -1,81 +0,0 @@ -open System -open System.IO -open Fake.IO - -let targets = ResizeArray unit)>() - -let target name f = targets.Add(name, f) - -let rec retry n f = - if n = 0 then - ignore() - else - try f() - with ex -> - System.Threading.Thread.Sleep(1000) - retry (n - 1) f - -// Paths to different directories in the solution -let path xs = Path.Combine(Array.ofList xs) -let solutionRoot = Files.findParent __SOURCE_DIRECTORY__ "NpgsqlFSharpAnalyzer.sln"; -let analyzerCore = path [ solutionRoot; "src"; "NpgsqlFSharpAnalyzer" ] -let analyzer = path [ solutionRoot; "src"; "NpgsqlFSharpAnalyzer" ] -let analyzerVs = path [ solutionRoot; "src"; "NpgsqlFSharpVs" ] -let tests = path [ solutionRoot; "tests"; "NpgsqlFSharpAnalyzer.Tests" ] - -let clean() = - retry 5 <| fun _ -> List.iter Shell.deleteDir [ - path [ analyzerCore; "bin" ] - path [ analyzerCore; "obj" ] - path [ analyzer; "bin" ] - path [ analyzer; "obj" ] - path [ analyzerVs; "bin" ] - path [ analyzerVs; "obj" ] - path [ tests; "bin" ] - path [ tests; "obj" ] - ] - -let build() = Tools.dotnet "build -c Release" solutionRoot -let test() = Tools.dotnet "run" tests - -target "Clean" clean - -target "Test" (fun _ -> - clean() - test() -) - -target "Build" (fun _ -> - clean() - build() -) - -target "Default" test - -let run target = - targets - |> Seq.find (fun (t, f) -> t = target) - |> fun (target, execute) -> execute() - -[] -let main args = - Console.WriteLine(Swag.logo) - - try - match args with - | [| "RunDefaultOr" |] -> run "Default" - | [| "RunDefaultOr"; target |] -> run target - | _ -> - Console.WriteLine("[Interactive Mode] Available Targets: ") - for (addedTarget, execute) in targets do Console.WriteLine(sprintf " | -- %s" addedTarget); - Console.WriteLine() - Console.Write("[Interactive Mode] Run build target: ") - let target = Console.ReadLine() - if not (targets |> Seq.exists (fun (t, f) -> t = target)) then - Console.WriteLine(sprintf "Target %s was not recognized" target) - else - run target - 0 - with ex -> - printfn "%s" ex.Message - 1 diff --git a/src/Build/Swag.fs b/src/Build/Swag.fs deleted file mode 100644 index 1b2ed1a..0000000 --- a/src/Build/Swag.fs +++ /dev/null @@ -1,11 +0,0 @@ -module Swag - -let logo = """ -________ _ ___ ____ ________ -|_ __ | / \ |_ ||_ _| |_ __ | - | |_ \_| / _ \ | |_/ / | |_ \_| - | _| / ___ \ | __'. | _| _ -_| |_ _/ / \ \_ _| | \ \_ _| |__/ | -|_____||____| |____||____||____||________| - -""" diff --git a/src/Build/Tools.fs b/src/Build/Tools.fs deleted file mode 100644 index 1687e43..0000000 --- a/src/Build/Tools.fs +++ /dev/null @@ -1,14 +0,0 @@ -[] -module Tools - -open Fake.IO -open Nuke.Common.Tooling -open Fake.Core - -let dotnetPath = ToolPathResolver.GetPathExecutable("dotnet") -let npm = ToolPathResolver.GetPathExecutable("npm") -let node = ToolPathResolver.GetPathExecutable("node") - -let dotnet argument workingDir = - if Shell.Exec(dotnetPath, argument, workingDir) <> 0 - then failwithf "FAILED %s> dotnet %s" workingDir argument diff --git a/src/NpgsqlFSharpAnalyzer.Core/NpgsqlFSharpAnalyzer.Core.fsproj b/src/NpgsqlFSharpAnalyzer.Core/NpgsqlFSharpAnalyzer.Core.fsproj index 69fec35..207ccee 100644 --- a/src/NpgsqlFSharpAnalyzer.Core/NpgsqlFSharpAnalyzer.Core.fsproj +++ b/src/NpgsqlFSharpAnalyzer.Core/NpgsqlFSharpAnalyzer.Core.fsproj @@ -14,7 +14,6 @@ - diff --git a/src/NpgsqlFSharpAnalyzer.Core/Types.fs b/src/NpgsqlFSharpAnalyzer.Core/Types.fs index 4903ace..587fcdc 100644 --- a/src/NpgsqlFSharpAnalyzer.Core/Types.fs +++ b/src/NpgsqlFSharpAnalyzer.Core/Types.fs @@ -2,8 +2,6 @@ namespace Npgsql.FSharp.Analyzers.Core open FSharp.Compiler.Range -open System -open FSharp.Compiler open FSharp.Compiler.SyntaxTree open FSharp.Compiler.SourceCodeServices diff --git a/tests/NpgsqlFSharpAnalyzer.Tests/paket.references b/tests/NpgsqlFSharpAnalyzer.Tests/paket.references deleted file mode 100644 index 4320365..0000000 --- a/tests/NpgsqlFSharpAnalyzer.Tests/paket.references +++ /dev/null @@ -1,5 +0,0 @@ -Expecto -dotnet-mono -altcover -ThrowawayDb.Postgres -Npgsql.FSharp From efd7856d0da5457b62943ad21d08c4145c7d394b Mon Sep 17 00:00:00 2001 From: Zaid Date: Mon, 17 Aug 2020 21:51:44 +0200 Subject: [PATCH 9/9] Rename VS extension directory --- NpgsqlFSharpAnalyzer.sln | 2 +- .../ContentTypeNames.cs | 0 .../FsLintVsPackage.cs | 0 src/{AnalyzerVs => NpgsqlFSharpVs}/LintChecker.cs | 0 .../LintCheckerProvider.cs | 0 src/{AnalyzerVs => NpgsqlFSharpVs}/LintError.cs | 0 .../LintProjectInfo.cs | 0 src/{AnalyzerVs => NpgsqlFSharpVs}/LintTagger.cs | 0 .../NpgsqlFSharpVs.csproj | 4 +++- .../Options/FsLintOptionsPage.cs | 0 .../Properties/AssemblyInfo.cs | 0 .../Resources/GettingStarted.html | 0 .../Resources/License.txt | 0 .../Resources/ReleaseNotes.html | Bin .../Resources/logo.png | Bin .../SubscriptionManager.cs | 0 .../SuggestionPreview.xaml | 0 .../SuggestionPreview.xaml.cs | 0 .../Suggestions/LintActionsSource.cs | 0 .../Suggestions/LintFixAction.cs | 0 .../Suggestions/LintSuggestionProvider.cs | 0 .../Suggestions/LintSuppressAction.cs | 0 .../Suggestions/LintSuppressBy.cs | 0 .../Table/LintTableSnapshotFactory.cs | 0 .../Table/LintingErrorsSnapshot.cs | 0 src/{AnalyzerVs => NpgsqlFSharpVs}/paket.references | 0 .../source.extension.vsixmanifest | 8 +++++--- 27 files changed, 9 insertions(+), 5 deletions(-) rename src/{AnalyzerVs => NpgsqlFSharpVs}/ContentTypeNames.cs (100%) rename src/{AnalyzerVs => NpgsqlFSharpVs}/FsLintVsPackage.cs (100%) rename src/{AnalyzerVs => NpgsqlFSharpVs}/LintChecker.cs (100%) rename src/{AnalyzerVs => NpgsqlFSharpVs}/LintCheckerProvider.cs (100%) rename src/{AnalyzerVs => NpgsqlFSharpVs}/LintError.cs (100%) rename src/{AnalyzerVs => NpgsqlFSharpVs}/LintProjectInfo.cs (100%) rename src/{AnalyzerVs => NpgsqlFSharpVs}/LintTagger.cs (100%) rename src/{AnalyzerVs => NpgsqlFSharpVs}/NpgsqlFSharpVs.csproj (98%) rename src/{AnalyzerVs => NpgsqlFSharpVs}/Options/FsLintOptionsPage.cs (100%) rename src/{AnalyzerVs => NpgsqlFSharpVs}/Properties/AssemblyInfo.cs (100%) rename src/{AnalyzerVs => NpgsqlFSharpVs}/Resources/GettingStarted.html (100%) rename src/{AnalyzerVs => NpgsqlFSharpVs}/Resources/License.txt (100%) rename src/{AnalyzerVs => NpgsqlFSharpVs}/Resources/ReleaseNotes.html (100%) rename src/{AnalyzerVs => NpgsqlFSharpVs}/Resources/logo.png (100%) rename src/{AnalyzerVs => NpgsqlFSharpVs}/SubscriptionManager.cs (100%) rename src/{AnalyzerVs => NpgsqlFSharpVs}/SuggestionPreview.xaml (100%) rename src/{AnalyzerVs => NpgsqlFSharpVs}/SuggestionPreview.xaml.cs (100%) rename src/{AnalyzerVs => NpgsqlFSharpVs}/Suggestions/LintActionsSource.cs (100%) rename src/{AnalyzerVs => NpgsqlFSharpVs}/Suggestions/LintFixAction.cs (100%) rename src/{AnalyzerVs => NpgsqlFSharpVs}/Suggestions/LintSuggestionProvider.cs (100%) rename src/{AnalyzerVs => NpgsqlFSharpVs}/Suggestions/LintSuppressAction.cs (100%) rename src/{AnalyzerVs => NpgsqlFSharpVs}/Suggestions/LintSuppressBy.cs (100%) rename src/{AnalyzerVs => NpgsqlFSharpVs}/Table/LintTableSnapshotFactory.cs (100%) rename src/{AnalyzerVs => NpgsqlFSharpVs}/Table/LintingErrorsSnapshot.cs (100%) rename src/{AnalyzerVs => NpgsqlFSharpVs}/paket.references (100%) rename src/{AnalyzerVs => NpgsqlFSharpVs}/source.extension.vsixmanifest (76%) diff --git a/NpgsqlFSharpAnalyzer.sln b/NpgsqlFSharpAnalyzer.sln index b0a01c0..a912a26 100644 --- a/NpgsqlFSharpAnalyzer.sln +++ b/NpgsqlFSharpAnalyzer.sln @@ -29,7 +29,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution RELEASE_NOTES.md = RELEASE_NOTES.md EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NpgsqlFSharpVs", "src\AnalyzerVs\NpgsqlFSharpVs.csproj", "{37577282-1289-40DB-AD3D-24499BD09DAE}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NpgsqlFSharpVs", "src\NpgsqlFSharpVs\NpgsqlFSharpVs.csproj", "{37577282-1289-40DB-AD3D-24499BD09DAE}" EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "NpgsqlFSharpAnalyzer.Core", "src\NpgsqlFSharpAnalyzer.Core\NpgsqlFSharpAnalyzer.Core.fsproj", "{5964BB56-97B8-4FAE-9933-8113DB11438D}" EndProject diff --git a/src/AnalyzerVs/ContentTypeNames.cs b/src/NpgsqlFSharpVs/ContentTypeNames.cs similarity index 100% rename from src/AnalyzerVs/ContentTypeNames.cs rename to src/NpgsqlFSharpVs/ContentTypeNames.cs diff --git a/src/AnalyzerVs/FsLintVsPackage.cs b/src/NpgsqlFSharpVs/FsLintVsPackage.cs similarity index 100% rename from src/AnalyzerVs/FsLintVsPackage.cs rename to src/NpgsqlFSharpVs/FsLintVsPackage.cs diff --git a/src/AnalyzerVs/LintChecker.cs b/src/NpgsqlFSharpVs/LintChecker.cs similarity index 100% rename from src/AnalyzerVs/LintChecker.cs rename to src/NpgsqlFSharpVs/LintChecker.cs diff --git a/src/AnalyzerVs/LintCheckerProvider.cs b/src/NpgsqlFSharpVs/LintCheckerProvider.cs similarity index 100% rename from src/AnalyzerVs/LintCheckerProvider.cs rename to src/NpgsqlFSharpVs/LintCheckerProvider.cs diff --git a/src/AnalyzerVs/LintError.cs b/src/NpgsqlFSharpVs/LintError.cs similarity index 100% rename from src/AnalyzerVs/LintError.cs rename to src/NpgsqlFSharpVs/LintError.cs diff --git a/src/AnalyzerVs/LintProjectInfo.cs b/src/NpgsqlFSharpVs/LintProjectInfo.cs similarity index 100% rename from src/AnalyzerVs/LintProjectInfo.cs rename to src/NpgsqlFSharpVs/LintProjectInfo.cs diff --git a/src/AnalyzerVs/LintTagger.cs b/src/NpgsqlFSharpVs/LintTagger.cs similarity index 100% rename from src/AnalyzerVs/LintTagger.cs rename to src/NpgsqlFSharpVs/LintTagger.cs diff --git a/src/AnalyzerVs/NpgsqlFSharpVs.csproj b/src/NpgsqlFSharpVs/NpgsqlFSharpVs.csproj similarity index 98% rename from src/AnalyzerVs/NpgsqlFSharpVs.csproj rename to src/NpgsqlFSharpVs/NpgsqlFSharpVs.csproj index c42ced1..ff5563e 100644 --- a/src/AnalyzerVs/NpgsqlFSharpVs.csproj +++ b/src/NpgsqlFSharpVs/NpgsqlFSharpVs.csproj @@ -51,7 +51,9 @@ - + + Component + diff --git a/src/AnalyzerVs/Options/FsLintOptionsPage.cs b/src/NpgsqlFSharpVs/Options/FsLintOptionsPage.cs similarity index 100% rename from src/AnalyzerVs/Options/FsLintOptionsPage.cs rename to src/NpgsqlFSharpVs/Options/FsLintOptionsPage.cs diff --git a/src/AnalyzerVs/Properties/AssemblyInfo.cs b/src/NpgsqlFSharpVs/Properties/AssemblyInfo.cs similarity index 100% rename from src/AnalyzerVs/Properties/AssemblyInfo.cs rename to src/NpgsqlFSharpVs/Properties/AssemblyInfo.cs diff --git a/src/AnalyzerVs/Resources/GettingStarted.html b/src/NpgsqlFSharpVs/Resources/GettingStarted.html similarity index 100% rename from src/AnalyzerVs/Resources/GettingStarted.html rename to src/NpgsqlFSharpVs/Resources/GettingStarted.html diff --git a/src/AnalyzerVs/Resources/License.txt b/src/NpgsqlFSharpVs/Resources/License.txt similarity index 100% rename from src/AnalyzerVs/Resources/License.txt rename to src/NpgsqlFSharpVs/Resources/License.txt diff --git a/src/AnalyzerVs/Resources/ReleaseNotes.html b/src/NpgsqlFSharpVs/Resources/ReleaseNotes.html similarity index 100% rename from src/AnalyzerVs/Resources/ReleaseNotes.html rename to src/NpgsqlFSharpVs/Resources/ReleaseNotes.html diff --git a/src/AnalyzerVs/Resources/logo.png b/src/NpgsqlFSharpVs/Resources/logo.png similarity index 100% rename from src/AnalyzerVs/Resources/logo.png rename to src/NpgsqlFSharpVs/Resources/logo.png diff --git a/src/AnalyzerVs/SubscriptionManager.cs b/src/NpgsqlFSharpVs/SubscriptionManager.cs similarity index 100% rename from src/AnalyzerVs/SubscriptionManager.cs rename to src/NpgsqlFSharpVs/SubscriptionManager.cs diff --git a/src/AnalyzerVs/SuggestionPreview.xaml b/src/NpgsqlFSharpVs/SuggestionPreview.xaml similarity index 100% rename from src/AnalyzerVs/SuggestionPreview.xaml rename to src/NpgsqlFSharpVs/SuggestionPreview.xaml diff --git a/src/AnalyzerVs/SuggestionPreview.xaml.cs b/src/NpgsqlFSharpVs/SuggestionPreview.xaml.cs similarity index 100% rename from src/AnalyzerVs/SuggestionPreview.xaml.cs rename to src/NpgsqlFSharpVs/SuggestionPreview.xaml.cs diff --git a/src/AnalyzerVs/Suggestions/LintActionsSource.cs b/src/NpgsqlFSharpVs/Suggestions/LintActionsSource.cs similarity index 100% rename from src/AnalyzerVs/Suggestions/LintActionsSource.cs rename to src/NpgsqlFSharpVs/Suggestions/LintActionsSource.cs diff --git a/src/AnalyzerVs/Suggestions/LintFixAction.cs b/src/NpgsqlFSharpVs/Suggestions/LintFixAction.cs similarity index 100% rename from src/AnalyzerVs/Suggestions/LintFixAction.cs rename to src/NpgsqlFSharpVs/Suggestions/LintFixAction.cs diff --git a/src/AnalyzerVs/Suggestions/LintSuggestionProvider.cs b/src/NpgsqlFSharpVs/Suggestions/LintSuggestionProvider.cs similarity index 100% rename from src/AnalyzerVs/Suggestions/LintSuggestionProvider.cs rename to src/NpgsqlFSharpVs/Suggestions/LintSuggestionProvider.cs diff --git a/src/AnalyzerVs/Suggestions/LintSuppressAction.cs b/src/NpgsqlFSharpVs/Suggestions/LintSuppressAction.cs similarity index 100% rename from src/AnalyzerVs/Suggestions/LintSuppressAction.cs rename to src/NpgsqlFSharpVs/Suggestions/LintSuppressAction.cs diff --git a/src/AnalyzerVs/Suggestions/LintSuppressBy.cs b/src/NpgsqlFSharpVs/Suggestions/LintSuppressBy.cs similarity index 100% rename from src/AnalyzerVs/Suggestions/LintSuppressBy.cs rename to src/NpgsqlFSharpVs/Suggestions/LintSuppressBy.cs diff --git a/src/AnalyzerVs/Table/LintTableSnapshotFactory.cs b/src/NpgsqlFSharpVs/Table/LintTableSnapshotFactory.cs similarity index 100% rename from src/AnalyzerVs/Table/LintTableSnapshotFactory.cs rename to src/NpgsqlFSharpVs/Table/LintTableSnapshotFactory.cs diff --git a/src/AnalyzerVs/Table/LintingErrorsSnapshot.cs b/src/NpgsqlFSharpVs/Table/LintingErrorsSnapshot.cs similarity index 100% rename from src/AnalyzerVs/Table/LintingErrorsSnapshot.cs rename to src/NpgsqlFSharpVs/Table/LintingErrorsSnapshot.cs diff --git a/src/AnalyzerVs/paket.references b/src/NpgsqlFSharpVs/paket.references similarity index 100% rename from src/AnalyzerVs/paket.references rename to src/NpgsqlFSharpVs/paket.references diff --git a/src/AnalyzerVs/source.extension.vsixmanifest b/src/NpgsqlFSharpVs/source.extension.vsixmanifest similarity index 76% rename from src/AnalyzerVs/source.extension.vsixmanifest rename to src/NpgsqlFSharpVs/source.extension.vsixmanifest index 2585756..e717388 100644 --- a/src/AnalyzerVs/source.extension.vsixmanifest +++ b/src/NpgsqlFSharpVs/source.extension.vsixmanifest @@ -1,9 +1,11 @@  - + - NpgsqlAnalyzerVs - F# analyzer that provides embedded SQL syntax analysis, type-checking for parameters and result sets and nullable column detection when writing queries using Npgsql.FSharp. + NpgsqlFSharpVs + F# Analyzer for embedded SQL syntax analysis, type-checking for parameters and result sets and nullable column detection when writing queries using Npgsql.FSharp. https://github.com/Zaid-Ajaj/Npgsql.FSharp.Analyzer Resources\License.txt Resources\GettingStarted.html