diff --git a/.keepme b/.keepme new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000000..e69de29bb2 diff --git a/404.html b/404.html new file mode 100644 index 0000000000..aed553dbd1 --- /dev/null +++ b/404.html @@ -0,0 +1,215 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +404 Page not found | FTL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+
+
+
+
+

Page not found :(

+

The page you are looking for doesn't exist or has been moved.

+
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/_headers b/_headers new file mode 100644 index 0000000000..c269214ab2 --- /dev/null +++ b/_headers @@ -0,0 +1,2 @@ +/* + Access-Control-Allow-Origin: * \ No newline at end of file diff --git a/android-chrome-192x192.png b/android-chrome-192x192.png new file mode 100644 index 0000000000..f8d56c0047 Binary files /dev/null and b/android-chrome-192x192.png differ diff --git a/android-chrome-512x512.png b/android-chrome-512x512.png new file mode 100644 index 0000000000..3ece19d2c6 Binary files /dev/null and b/android-chrome-512x512.png differ diff --git a/apple-touch-icon.png b/apple-touch-icon.png new file mode 100644 index 0000000000..30e0b54e13 Binary files /dev/null and b/apple-touch-icon.png differ diff --git a/atom.xml b/atom.xml new file mode 100644 index 0000000000..eb00b65793 --- /dev/null +++ b/atom.xml @@ -0,0 +1,1720 @@ + + + FTL + FTL - Towards a 𝝺-calculus for large-scale systems + + + Zola + 2024-07-12T18:00:00+00:00 + https://block.github.io/ftl/atom.xml + + External Types + 2024-07-12T18:00:00+00:00 + 2024-07-12T18:00:00+00:00 + + + + + Unknown + + + + + + https://block.github.io/ftl/docs/reference/externaltypes/ + + <h2 id="using-external-types">Using external types</h2> +<p>FTL supports the use of external types in your FTL modules. External types are types defined in other packages or modules that are not part of the FTL module.</p> +<p>The primary difference is that external types are not defined in the FTL schema, and therefore serialization and deserialization of these types is not handled +by FTL. Instead, FTL relies on the runtime to handle serialization and deserialization of these types.</p> +<p>In some cases this feature can also be used to provide custom serialization and deserialization logic for types that are not directly supported by FTL, even +if they are defined in the same package as the FTL module.</p> +<p>To use an external type in your FTL module schema, declare a type alias over the external type:</p> +<div class="code-selector"> +<ul class="nav nav-tabs mb-2"> +</ul> +<!-- go --> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#65737e;">//ftl:typealias +</span><span style="color:#b48ead;">type </span><span>FtlType </span><span style="color:#bf616a;">external</span><span>.</span><span style="color:#b48ead;">OtherType +</span><span> +</span><span style="color:#65737e;">//ftl:typealias +</span><span style="color:#b48ead;">type </span><span>FtlType2 = </span><span style="color:#bf616a;">external</span><span>.</span><span style="color:#b48ead;">OtherType +</span></code></pre> +<p>The external type is widened to <code>Any</code> in the FTL schema, and the corresponding type alias will include metadata +for the runtime-specific type mapping:</p> +<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>typealias FtlType Any +</span><span> +typemap go &quot;github.com/external.OtherType&quot; +</span></code></pre> +<!-- kotlin --> +<pre data-lang="kotlin" style="background-color:#2b303b;color:#c0c5ce;" class="language-kotlin "><code class="language-kotlin" data-lang="kotlin"><span>@TypeAlias(name = &quot;</span><span style="color:#a3be8c;">OtherType</span><span>&quot;) +</span><span style="color:#b48ead;">class </span><span style="color:#ebcb8b;">OtherTypeTypeMapper </span><span>: </span><span style="color:#a3be8c;">TypeAliasMapper</span><span>&lt;</span><span style="color:#a3be8c;">OtherType</span><span>, </span><span style="color:#a3be8c;">JsonNode</span><span>&gt; { +</span><span> </span><span style="color:#b48ead;">override fun </span><span style="color:#8fa1b3;">encode</span><span>(`object`: OtherType): JsonNode { +</span><span> </span><span style="color:#b48ead;">return</span><span> TextNode.valueOf(`</span><span style="color:#a3be8c;">object</span><span>`.value) +</span><span> } +</span><span> +</span><span> </span><span style="color:#b48ead;">override fun </span><span style="color:#8fa1b3;">decode</span><span>(serialized: JsonNode): OtherType { +</span><span> </span><span style="color:#b48ead;">if</span><span> (serialized.isTextual) { +</span><span> </span><span style="color:#b48ead;">return</span><span> OtherType(serialized.textValue()) +</span><span> } +</span><span> </span><span style="color:#b48ead;">throw</span><span> RuntimeException(&quot;</span><span style="color:#a3be8c;">Expected a textual value</span><span>&quot;) +</span><span> } +</span><span>} +</span></code></pre> +<p>In the example above the external type is widened to <code>Any</code> in the FTL schema, and the corresponding type alias will include metadata +for the runtime-specific type mapping:</p> +<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>typealias FtlType Any +</span><span> +typemap java &quot;foo.bar.OtherType&quot; +</span></code></pre> +<p>Note that for JVM languages <code>java</code> is always used as the runtime name, regardless of the actual language used.</p> +<p>It is also possible to map to any other valid FTL type (e.g. <code>String</code>) by use this as the second type parameter:</p> +<p>Users can achieve functionally equivalent behavior to using the external type directly by using the declared +alias (<code>FtlType</code>) in place of the external type in any other schema declarations (e.g. as the type of a Verb request). Direct usage of the external type in schema declarations is not supported; +instead, the type alias must be used.</p> +<pre data-lang="kotlin" style="background-color:#2b303b;color:#c0c5ce;" class="language-kotlin "><code class="language-kotlin" data-lang="kotlin"><span>@TypeAlias(name = &quot;</span><span style="color:#a3be8c;">OtherType</span><span>&quot;) +</span><span style="color:#b48ead;">class </span><span style="color:#ebcb8b;">OtherTypeTypeMapper </span><span>: </span><span style="color:#a3be8c;">TypeAliasMapper</span><span>&lt;</span><span style="color:#a3be8c;">OtherType</span><span>, </span><span style="color:#a3be8c;">String</span><span>&gt; { +</span><span> </span><span style="color:#b48ead;">override fun </span><span style="color:#8fa1b3;">encode</span><span>(other: OtherType): JsonNode { +</span><span> </span><span style="color:#b48ead;">return</span><span> other.value +</span><span> } +</span><span> +</span><span> </span><span style="color:#b48ead;">override fun </span><span style="color:#8fa1b3;">decode</span><span>(serialized: </span><span style="color:#b48ead;">String</span><span>): OtherType { +</span><span> </span><span style="color:#b48ead;">return</span><span> OtherType(serialized.textValue()) +</span><span> } +</span><span>} +</span></code></pre> +<p>The corresponding type alias will be to a <code>String</code>, which makes the schema more useful:</p> +<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>typealias FtlType String +</span><span> +typemap kotlin &quot;foo.bar.OtherType&quot; +</span></code></pre> +<!-- java --> +<pre data-lang="java" style="background-color:#2b303b;color:#c0c5ce;" class="language-java "><code class="language-java" data-lang="java"><span>@</span><span style="color:#bf616a;">TypeAlias</span><span>(</span><span style="color:#bf616a;">name </span><span>= &quot;</span><span style="color:#a3be8c;">OtherType</span><span>&quot;) +</span><span style="color:#b48ead;">public class </span><span style="color:#ebcb8b;">OtherTypeTypeMapper </span><span style="color:#b48ead;">implements </span><span style="color:#a3be8c;">TypeAliasMapper</span><span style="color:#eff1f5;">&lt;</span><span style="color:#ebcb8b;">OtherType</span><span style="color:#eff1f5;">, </span><span style="color:#ebcb8b;">JsonNode</span><span style="color:#eff1f5;">&gt; { +</span><span style="color:#eff1f5;"> @</span><span style="color:#bf616a;">Override +</span><span style="color:#eff1f5;"> </span><span style="color:#b48ead;">public </span><span style="color:#ebcb8b;">JsonNode </span><span style="color:#8fa1b3;">encode</span><span style="color:#eff1f5;">(</span><span style="color:#ebcb8b;">OtherType </span><span style="color:#bf616a;">object</span><span style="color:#eff1f5;">) { +</span><span style="color:#eff1f5;"> </span><span style="color:#b48ead;">return </span><span style="color:#ebcb8b;">TextNode</span><span style="color:#eff1f5;">.</span><span style="color:#bf616a;">valueOf</span><span style="color:#eff1f5;">(object.</span><span style="color:#bf616a;">getValue</span><span style="color:#eff1f5;">()); +</span><span style="color:#eff1f5;"> } +</span><span style="color:#eff1f5;"> +</span><span style="color:#eff1f5;"> @</span><span style="color:#bf616a;">Override +</span><span style="color:#eff1f5;"> </span><span style="color:#b48ead;">public </span><span style="color:#ebcb8b;">AnySerializedType </span><span style="color:#8fa1b3;">decode</span><span style="color:#eff1f5;">(</span><span style="color:#ebcb8b;">OtherType </span><span style="color:#bf616a;">serialized</span><span style="color:#eff1f5;">) { +</span><span style="color:#eff1f5;"> </span><span style="color:#b48ead;">if </span><span style="color:#eff1f5;">(serialized.</span><span style="color:#bf616a;">isTextual</span><span style="color:#eff1f5;">()) { +</span><span style="color:#eff1f5;"> </span><span style="color:#b48ead;">return new </span><span style="color:#ebcb8b;">OtherType</span><span style="color:#eff1f5;">(serialized.</span><span style="color:#bf616a;">textValue</span><span style="color:#eff1f5;">()); +</span><span style="color:#eff1f5;"> } +</span><span style="color:#eff1f5;"> </span><span style="color:#b48ead;">throw new </span><span style="color:#ebcb8b;">RuntimeException</span><span style="color:#eff1f5;">(</span><span>&quot;</span><span style="color:#a3be8c;">Expected a textual value</span><span>&quot;</span><span style="color:#eff1f5;">); +</span><span style="color:#eff1f5;"> } +</span><span style="color:#eff1f5;">} +</span></code></pre> +<p>In the example above the external type is widened to <code>Any</code> in the FTL schema, and the corresponding type alias will include metadata +for the runtime-specific type mapping:</p> +<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>typealias FtlType Any +</span><span> +typemap java &quot;foo.bar.OtherType&quot; +</span></code></pre> +<p>It is also possible to map to any other valid FTL type (e.g. <code>String</code>) by use this as the second type parameter:</p> +<pre data-lang="java" style="background-color:#2b303b;color:#c0c5ce;" class="language-java "><code class="language-java" data-lang="java"><span>@</span><span style="color:#bf616a;">TypeAlias</span><span>(</span><span style="color:#bf616a;">name </span><span>= &quot;</span><span style="color:#a3be8c;">OtherType</span><span>&quot;) +</span><span style="color:#b48ead;">public class </span><span style="color:#ebcb8b;">OtherTypeTypeMapper </span><span style="color:#b48ead;">implements </span><span style="color:#a3be8c;">TypeAliasMapper</span><span style="color:#eff1f5;">&lt;</span><span style="color:#ebcb8b;">OtherType</span><span style="color:#eff1f5;">, </span><span style="color:#ebcb8b;">String</span><span style="color:#eff1f5;">&gt; { +</span><span style="color:#eff1f5;"> @</span><span style="color:#bf616a;">Override +</span><span style="color:#eff1f5;"> </span><span style="color:#b48ead;">public </span><span style="color:#ebcb8b;">String </span><span style="color:#8fa1b3;">encode</span><span style="color:#eff1f5;">(</span><span style="color:#ebcb8b;">OtherType </span><span style="color:#bf616a;">object</span><span style="color:#eff1f5;">) { +</span><span style="color:#eff1f5;"> </span><span style="color:#b48ead;">return</span><span style="color:#eff1f5;"> object.</span><span style="color:#bf616a;">getValue</span><span style="color:#eff1f5;">(); +</span><span style="color:#eff1f5;"> } +</span><span style="color:#eff1f5;"> +</span><span style="color:#eff1f5;"> @</span><span style="color:#bf616a;">Override +</span><span style="color:#eff1f5;"> </span><span style="color:#b48ead;">public </span><span style="color:#ebcb8b;">String </span><span style="color:#8fa1b3;">decode</span><span style="color:#eff1f5;">(</span><span style="color:#ebcb8b;">OtherType </span><span style="color:#bf616a;">serialized</span><span style="color:#eff1f5;">) { +</span><span style="color:#eff1f5;"> </span><span style="color:#b48ead;">return new </span><span style="color:#ebcb8b;">OtherType</span><span style="color:#eff1f5;">(serialized.</span><span style="color:#bf616a;">textValue</span><span style="color:#eff1f5;">()); +</span><span style="color:#eff1f5;"> } +</span><span style="color:#eff1f5;">} +</span></code></pre> +<p>The corresponding type alias will be to a <code>String</code>, which makes the schema more useful:</p> +<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>typealias FtlType String +</span><span> +typemap java &quot;com.external.other.OtherType&quot; +</span></code></pre> +</div> +<p>FTL will automatically serialize and deserialize the external type to the strong type indicated by the mapping.</p> +<h2 id="cross-runtime-type-mappings">Cross-Runtime Type Mappings</h2> +<p>FTL also provides the capability to declare type mappings for other runtimes. For instance, to include a type mapping for another language, you can +annotate your type alias declaration as follows:</p> +<div class="code-selector"> +<ul class="nav nav-tabs mb-2"> +</ul> +<!-- go --> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#65737e;">//ftl:typealias +</span><span style="color:#65737e;">//ftl:typemap java &quot;com.external.other.OtherType&quot; +</span><span style="color:#b48ead;">type </span><span>FtlType </span><span style="color:#bf616a;">external</span><span>.</span><span style="color:#b48ead;">OtherType +</span></code></pre> +<!-- kotlin --> +<pre data-lang="kotlin" style="background-color:#2b303b;color:#c0c5ce;" class="language-kotlin "><code class="language-kotlin" data-lang="kotlin"><span>@TypeAlias( +</span><span> name = &quot;</span><span style="color:#a3be8c;">OtherType</span><span>&quot;, +</span><span> languageTypeMappings = [LanguageTypeMapping(language = &quot;</span><span style="color:#a3be8c;">go</span><span>&quot;, type = &quot;</span><span style="color:#a3be8c;">github.com/external.OtherType</span><span>&quot;)] +</span><span>) +</span></code></pre> +<!-- java --> +<pre data-lang="java" style="background-color:#2b303b;color:#c0c5ce;" class="language-java "><code class="language-java" data-lang="java"><span>@</span><span style="color:#bf616a;">TypeAlias</span><span>(</span><span style="color:#bf616a;">name </span><span>= &quot;</span><span style="color:#a3be8c;">OtherType</span><span>&quot;, </span><span style="color:#bf616a;">languageTypeMappings </span><span>= { +</span><span> @</span><span style="color:#bf616a;">LanguageTypeMapping</span><span>(</span><span style="color:#bf616a;">language </span><span>= &quot;</span><span style="color:#a3be8c;">go</span><span>&quot;, </span><span style="color:#bf616a;">type </span><span>= &quot;</span><span style="color:#a3be8c;">github.com/external.OtherType</span><span>&quot;), +</span><span>}) +</span><span>... +</span></code></pre> +</div> +<p>In the FTL schema, this will appear as:</p> +<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>typealias FtlType Any +</span><span> +typemap go &quot;github.com/external.OtherType&quot; +</span><span> +typemap java &quot;com.external.other.OtherType&quot; +</span></code></pre> +<p>This allows FTL to decode the type properly in other languages, for seamless +interoperability across different runtimes.</p> + + + + + Unit Tests + 2024-06-13T08:20:00+00:00 + 2024-06-13T08:20:00+00:00 + + + + + Unknown + + + + + + https://block.github.io/ftl/docs/reference/unittests/ + + <h2 id="create-a-context">Create a context</h2> +<p>When writing a unit test, first create a context:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#b48ead;">func </span><span style="color:#8fa1b3;">ExampleTest</span><span>(</span><span style="color:#bf616a;">t </span><span>*</span><span style="color:#bf616a;">testing</span><span>.</span><span style="color:#b48ead;">Test</span><span>) { +</span><span> </span><span style="color:#bf616a;">ctx </span><span>:= </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">Context</span><span>( +</span><span> </span><span style="color:#65737e;">// options go here +</span><span> ) +</span><span>} +</span></code></pre> +<p>FTL will help isolate what you want to test by restricting access to FTL features by default. You can expand what is available to test by adding options to <code>ftltest.Context(...)</code>.</p> +<p>In this default set up, FTL does the following:</p> +<ul> +<li>prevents access to <code>ftl.ConfigValue</code> and <code>ftl.SecretValue</code> (<a href="https://block.github.io/ftl/docs/reference/unittests/#project-files-configs-and-secrets">See options</a>)</li> +<li>prevents access to <code>ftl.Database</code> (<a href="https://block.github.io/ftl/docs/reference/unittests/#databases">See options</a>)</li> +<li>prevents access to <code>ftl.MapHandle</code> (<a href="https://block.github.io/ftl/docs/reference/unittests/#maps">See options</a>)</li> +<li>disables all subscribers (<a href="https://block.github.io/ftl/docs/reference/unittests/#pubsub">See options</a>)</li> +</ul> +<h2 id="customization">Customization</h2> +<h3 id="project-files-configs-and-secrets">Project files, configs and secrets</h3> +<p>To enable configs and secrets from the default project file:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#bf616a;">ctx </span><span>:= </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">Context</span><span>( +</span><span> </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">WithDefaultProjectFile</span><span>(), +</span><span>) +</span></code></pre> +<p>Or you can specify a specific project file:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#bf616a;">ctx </span><span>:= </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">Context</span><span>( +</span><span> </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">WithProjectFile</span><span>(</span><span style="color:#bf616a;">path</span><span>), +</span><span>) +</span></code></pre> +<p>You can also override specific config and secret values:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#bf616a;">ctx </span><span>:= </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">Context</span><span>( +</span><span> </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">WithDefaultProjectFile</span><span>(), +</span><span> +</span><span> </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">WithConfig</span><span>(</span><span style="color:#bf616a;">endpoint</span><span>, &quot;</span><span style="color:#a3be8c;">test</span><span>&quot;), +</span><span> </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">WithSecret</span><span>(</span><span style="color:#bf616a;">secret</span><span>, &quot;</span><span style="color:#a3be8c;">...</span><span>&quot;), +</span><span>) +</span></code></pre> +<h3 id="databases">Databases</h3> +<p>To enable database access in a test, you must first <a href="https://block.github.io/ftl/docs/reference/unittests/#project-files-configs-and-secrets">provide a DSN via a project file</a>. You can then set up a test database:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#bf616a;">ctx </span><span>:= </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">Context</span><span>( +</span><span> </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">WithDefaultProjectFile</span><span>(), +</span><span> </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">WithDatabase</span><span>[</span><span style="color:#bf616a;">MyDBConfig</span><span>](), +</span><span>) +</span></code></pre> +<p>This will:</p> +<ul> +<li>Take the provided DSN and appends <code>_test</code> to the database name. Eg: <code>accounts</code> becomes <code>accounts_test</code></li> +<li>Wipe all tables in the database so each test run happens on a clean database</li> +</ul> +<p>You can access the database in your test using its handle:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#bf616a;">db</span><span>, </span><span style="color:#bf616a;">err </span><span>:= </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">GetDatabaseHandle</span><span>[</span><span style="color:#bf616a;">MyDBConfig</span><span>]() +</span><span style="color:#bf616a;">db</span><span>.</span><span style="color:#bf616a;">Get</span><span>(</span><span style="color:#bf616a;">ctx</span><span>).</span><span style="color:#bf616a;">Exec</span><span>(...) +</span></code></pre> +<h3 id="maps">Maps</h3> +<p>By default, calling <code>Get(ctx)</code> on a map handle will panic.</p> +<p>You can inject a fake via a map:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#bf616a;">ctx </span><span>:= </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">Context</span><span>( +</span><span> </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">WhenMap</span><span>(</span><span style="color:#bf616a;">exampleMap</span><span>, </span><span style="color:#b48ead;">func</span><span>(</span><span style="color:#bf616a;">ctx context</span><span>.</span><span style="color:#b48ead;">Context</span><span>) (</span><span style="color:#b48ead;">string</span><span>, </span><span style="color:#b48ead;">error</span><span>) { +</span><span> </span><span style="color:#b48ead;">return </span><span>&quot;</span><span style="color:#a3be8c;">Test Value</span><span>&quot; +</span><span> }), +</span><span>) +</span></code></pre> +<p>You can also allow the use of all maps:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#bf616a;">ctx </span><span>:= </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">Context</span><span>( +</span><span> </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">WithMapsAllowed</span><span>(), +</span><span>) +</span></code></pre> +<h3 id="calls">Calls</h3> +<p>Use <code>ftltest.Call[Client](...)</code> (or <code>ftltest.CallSource[Client](...)</code>, <code>ftltest.CallSink[Client](...)</code>, <code>ftltest.CallEmpty[Client](...)</code>) to invoke your +verb. At runtime, FTL automatically provides these +resources to your verb, and using <code>ftltest.Call(...)</code> rather than direct invocations simulates this behavior.</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#65737e;">// Call a verb +</span><span style="color:#bf616a;">resp</span><span>, </span><span style="color:#bf616a;">err </span><span>:= </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">Call</span><span>[</span><span style="color:#bf616a;">ExampleVerbClient</span><span>, </span><span style="color:#bf616a;">Request</span><span>, </span><span style="color:#bf616a;">Response</span><span>](</span><span style="color:#bf616a;">ctx</span><span>, </span><span style="color:#bf616a;">Request</span><span>{</span><span style="color:#bf616a;">Param</span><span>: &quot;</span><span style="color:#a3be8c;">Test</span><span>&quot;}) +</span></code></pre> +<p>You can inject fakes for verbs:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#bf616a;">ctx </span><span>:= </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">Context</span><span>( +</span><span> </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">WhenVerb</span><span>[</span><span style="color:#bf616a;">ExampleVerbClient</span><span>](</span><span style="color:#b48ead;">func</span><span>(</span><span style="color:#bf616a;">ctx context</span><span>.</span><span style="color:#b48ead;">Context</span><span>, </span><span style="color:#bf616a;">req </span><span style="color:#b48ead;">Request</span><span>) (</span><span style="color:#b48ead;">Response</span><span>, </span><span style="color:#b48ead;">error</span><span>) { +</span><span> </span><span style="color:#b48ead;">return </span><span style="color:#bf616a;">Response</span><span>{</span><span style="color:#bf616a;">Result</span><span>: &quot;</span><span style="color:#a3be8c;">Lorem Ipsum</span><span>&quot;}, </span><span style="color:#d08770;">nil +</span><span> }), +</span><span>) +</span></code></pre> +<p>If there is no request or response parameters, you can use <code>WhenSource(...)</code>, <code>WhenSink(...)</code>, or <code>WhenEmpty(...)</code>.</p> +<p>To enable all calls within a module:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#bf616a;">ctx </span><span>:= </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">Context</span><span>( +</span><span> </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">WithCallsAllowedWithinModule</span><span>(), +</span><span>) +</span></code></pre> +<h3 id="pubsub">PubSub</h3> +<p>By default, all subscribers are disabled. +To enable a subscriber:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#bf616a;">ctx </span><span>:= </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">Context</span><span>( +</span><span> </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">WithSubscriber</span><span>(</span><span style="color:#bf616a;">paymentsSubscription</span><span>, </span><span style="color:#bf616a;">ProcessPayment</span><span>), +</span><span>) +</span></code></pre> +<p>Or you can inject a fake subscriber:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#bf616a;">ctx </span><span>:= </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">Context</span><span>( +</span><span> </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">WithSubscriber</span><span>(</span><span style="color:#bf616a;">paymentsSubscription</span><span>, </span><span style="color:#b48ead;">func </span><span>(</span><span style="color:#bf616a;">ctx context</span><span>.</span><span style="color:#b48ead;">Context</span><span>, </span><span style="color:#bf616a;">in </span><span style="color:#b48ead;">PaymentEvent</span><span>) </span><span style="color:#b48ead;">error </span><span>{ +</span><span> </span><span style="color:#b48ead;">return </span><span style="color:#bf616a;">fmt</span><span>.</span><span style="color:#bf616a;">Errorf</span><span>(&quot;</span><span style="color:#a3be8c;">failed payment: </span><span style="color:#d08770;">%v</span><span>&quot;, </span><span style="color:#bf616a;">in</span><span>) +</span><span> }), +</span><span>) +</span></code></pre> +<p>Due to the asynchronous nature of pubsub, your test should wait for subscriptions to consume the published events:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#bf616a;">topic</span><span>.</span><span style="color:#bf616a;">Publish</span><span>(</span><span style="color:#bf616a;">ctx</span><span>, </span><span style="color:#bf616a;">Event</span><span>{</span><span style="color:#bf616a;">Name</span><span>: &quot;</span><span style="color:#a3be8c;">Test</span><span>&quot;}) +</span><span> +</span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">WaitForSubscriptionsToComplete</span><span>(</span><span style="color:#bf616a;">ctx</span><span>) +</span><span style="color:#65737e;">// Event will have been consumed by now +</span></code></pre> +<p>You can check what events were published to a topic:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#bf616a;">events </span><span>:= </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">EventsForTopic</span><span>(</span><span style="color:#bf616a;">ctx</span><span>, </span><span style="color:#bf616a;">topic</span><span>) +</span></code></pre> +<p>You can check what events were consumed by a subscription, and whether a subscriber returned an error:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#bf616a;">results </span><span>:= </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">ResultsForSubscription</span><span>(</span><span style="color:#bf616a;">ctx</span><span>, </span><span style="color:#bf616a;">subscription</span><span>) +</span></code></pre> +<p>If all you wanted to check was whether a subscriber returned an error, this function is simpler:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#bf616a;">errs </span><span>:= </span><span style="color:#bf616a;">ftltest</span><span>.</span><span style="color:#bf616a;">ErrorsForSubscription</span><span>(</span><span style="color:#bf616a;">ctx</span><span>, </span><span style="color:#bf616a;">subscription</span><span>) +</span></code></pre> +<p>PubSub also has these different behaviours while testing:</p> +<ul> +<li>Publishing to topics in other modules is allowed</li> +<li>If a subscriber returns an error, no retries will occur regardless of retry policy.</li> +</ul> + + + + + FAQ + 2021-05-01T19:30:00+00:00 + 2021-05-01T19:30:00+00:00 + + + + + Unknown + + + + + + https://block.github.io/ftl/docs/help/faq/ + + <h2 id="why-does-ftl-not-allow-external-types-directly">Why does FTL not allow external types directly?</h2> +<p>Because of the nature of writing FTL verbs and data types, it's easy to think of it as just writing standard native code. Through that lens it is then somewhat surprising when FTL disallows the use of arbitrary external data types.</p> +<p>However, FTL types are not <em>just</em> native types. FTL types are a more convenient method of writing an IDL such as <a href="https://protobuf.dev/">Protobufs</a>, <a href="https://www.openapis.org/">OpenAPI</a> or <a href="https://thrift.apache.org/">Thrift</a>. With this in mind the constraint makes more sense. An IDL by its very nature must support a multitude of languages, so including an arbitrary type from a third party native library in one language may not be translatable to another language.</p> +<p>There are also secondary reasons, such as:</p> +<ul> +<li>Unclear ownership - in FTL a type must be owned by a single module. When importing a common third party type from multiple modules, which module owns that type?</li> +<li>An external type must be representable in the FTL schema. The schema is then used to generate types for other modules, including those in other languages. For an external type, FTL could track the external library it belongs to to generate the "correct" code, but this would only be representable in a single language.</li> +<li>External types often perform custom marshalling to/from JSON. This is not representable cross-language.</li> +<li>Cleaner separation of abstraction layers - the ability to mix in abitrary external types is convenient, but can easily lead to mixing of concerns between internal and external data representations.</li> +</ul> +<p>So what to do? See the <a href="https://block.github.io/ftl/docs/reference/externaltypes/">external types</a> documentation +for how to work around this limitation.</p> +<h2 id="what-is-a-module">What is a "module"?</h2> +<p>In its least abstract form, a module is a collection of verbs, and the resources (databases, queues, cron jobs, secrets, config, etc.) that those verbs rely on to operate. All resources are private to their owning module.</p> +<p>More abstractly, the separation of concerns between modules is largely subjective. You <em>can</em> think of each module as largely analogous to a traditional service, so when asking where the division between modules is that could inform your decision. That said, the ease of deploying modules in FTL is designed to give you more flexibility in how you structure your code.</p> +<h2 id="how-do-i-represent-optional-nullable-values">How do I represent optional/nullable values?</h2> +<p>FTL's type system includes support for optionals. In Go this is represented as <code>ftl.Option[T]</code>, in languages with first-class support for optionals such as Kotlin, FTL will leverage the native type system.</p> +<p>When FTL is mapping to JSON, optional values will be represented as <code>null</code>.</p> +<p>In Go specifically, pointers to values are not supported because pointers are semantically ambiguous and error prone. They can mean, variously: "this value may or may not be present", or "this value just happens to be a pointer", or "this value is a pointer because it's mutable"</p> +<p>Additionally pointers to builtin types are painful to use in Go because you can't obtain a reference to a literal.</p> +<h2 id="why-must-requests-responses-be-data-structures-can-t-they-be-arrays-etc">Why must requests/responses be data structures, can't they be arrays, etc.?</h2> +<p>This is currently due to FTL relying on traditional <a href="https://softwaremill.com/schema-evolution-protobuf-scalapb-fs2grpc/">schema evolution</a> for forwards/backwards compatibility - eg. changing a slice to a struct in a backward compatible way is not possible, as an existing deployed peer consuming the slice will fail if it suddenly changes to a data structure.</p> +<p>Eventually FTL will allow multiple versions of a verb to be simultaneously deployed, such that a version returning a slice can coexist temporarily with a version returning a struct. Once all peers have been updated to support the new type signature, the old version will be dropped.</p> +<h2 id="i-can-t-export-a-verb-from-a-nested-package-inside-a-subdirectory-of-the-module-root-what-do-i-do">I can't export a Verb from a nested package inside a subdirectory of the module root. What do I do?</h2> +<p>Verbs and types can only be exported from the top level of each module. You are welcome to put any helper code you'd like in a nested package/directory.</p> +<h2 id="what-types-are-supported-by-ftl">What types are supported by FTL?</h2> +<p>FTL supports the following types: <code>Int</code> (64-bit), <code>Float</code> (64-bit), <code>String</code>, <code>Bytes</code> (a byte array), <code>Bool</code>, <code>Time</code>, <code>Any</code> (a dynamic type), <code>Unit</code> (similar to "void"), arrays, maps, data structures, and constant enumerations. Each FTL type is mapped to a corresponding language-specific type. For example in Go <code>Float</code> is represented as <code>float64</code>, <code>Time</code> is represented by <code>time.Time</code>, and so on.</p> +<p>Note that currently (until <a href="https://github.com/block/ftl/issues/1296">type widening</a> is implemented), external types are not supported.</p> +<h2 id="sql-errors-on-startup">SQL errors on startup?</h2> +<p>For example:</p> +<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#65737e;"># ftl dev ~/src/ftl +</span><span style="color:#bf616a;">info:</span><span> Starting FTL with 1 controller(s) +</span><span style="color:#bf616a;">ftl:</span><span> error: ERROR: relation &quot;</span><span style="color:#a3be8c;">fsm_executions</span><span>&quot; does not exist (SQLSTATE 42P01) +</span></code></pre> +<p>Run again with <code>ftl dev</code>. This usually indicates that your DB has an old schema.</p> +<p>This can occur when FTL has been upgraded with schema changes, making the database out of date. While in alpha we do not use schema migrations, so this won't occur once we hit a stable release.</p> + + + + + Glossary + 2021-05-01T19:30:00+00:00 + 2021-05-01T19:30:00+00:00 + + + + + Unknown + + + + + + https://block.github.io/ftl/docs/help/glossary/ + + <h5 id="verb">Verb</h5> +<p>A Verb is a remotely callable function that takes an input and returns an output.</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#b48ead;">func</span><span>(</span><span style="color:#bf616a;">context</span><span>.</span><span style="color:#b48ead;">Context</span><span>, </span><span style="color:#b48ead;">In</span><span>) (</span><span style="color:#b48ead;">Out</span><span>, </span><span style="color:#b48ead;">error</span><span>) +</span></code></pre> +<h5 id="sink">Sink</h5> +<p>A Sink is a function that takes an input and returns nothing.</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#b48ead;">func</span><span>(</span><span style="color:#bf616a;">context</span><span>.</span><span style="color:#b48ead;">Context</span><span>, </span><span style="color:#b48ead;">In</span><span>) </span><span style="color:#b48ead;">error +</span></code></pre> +<h5 id="source">Source</h5> +<p>A Source is a function that takes no input and returns an output.</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#b48ead;">func</span><span>(</span><span style="color:#bf616a;">context</span><span>.</span><span style="color:#b48ead;">Context</span><span>) (</span><span style="color:#b48ead;">Out</span><span>, </span><span style="color:#b48ead;">error</span><span>) +</span></code></pre> +<h5 id="empty">Empty</h5> +<p>An Empty function is one that takes neither input or output.</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#b48ead;">func</span><span>(</span><span style="color:#bf616a;">context</span><span>.</span><span style="color:#b48ead;">Context</span><span>) </span><span style="color:#b48ead;">error +</span></code></pre> + + + + + Quick Start + 2021-05-01T08:20:00+00:00 + 2021-05-01T08:20:00+00:00 + + + + + Unknown + + + + + + https://block.github.io/ftl/docs/getting-started/quick-start/ + + <h2 id="requirements">Requirements</h2> +<h3 id="install-the-ftl-cli">Install the FTL CLI</h3> +<p>Install the FTL CLI via <a href="https://cashapp.github.io/hermit">Hermit</a>, <a href="https://brew.sh/">Homebrew</a>, or manually.</p> +<div class="code-selector"> +<ul class="nav nav-tabs mb-2"> +</ul> +<!-- hermit --> +<h4 id="hermit-mac-or-linux">Hermit (Mac or Linux)</h4> +<p>FTL can be installed from the main Hermit package repository by simply:</p> +<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>hermit install ftl +</span></code></pre> +<p>Alternatively you can add <a href="https://github.com/block/hermit-ftl">hermit-ftl</a> to your sources by adding the following to your Hermit environment's <code>bin/hermit.hcl</code> file:</p> +<pre data-lang="hcl" style="background-color:#2b303b;color:#c0c5ce;" class="language-hcl "><code class="language-hcl" data-lang="hcl"><span>sources = [&quot;https://github.com/block/hermit-ftl.git&quot;, &quot;https://github.com/cashapp/hermit-packages.git&quot;] +</span></code></pre> +<!-- homebrew --> +<h4 id="homebrew-mac-or-linux">Homebrew (Mac or Linux)</h4> +<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>brew tap block/ftl &amp;&amp; brew install ftl +</span></code></pre> +<!-- manual --> +<h4 id="manually-mac-or-linux">Manually (Mac or Linux)</h4> +<p>Download binaries from the <a href="https://github.com/block/ftl/releases/latest">latest release page</a> and place them in your <code>$PATH</code>.</p> +</div> +<hr /> +<h3 id="install-the-vscode-extension">Install the VSCode extension</h3> +<p>The <a href="https://marketplace.visualstudio.com/items?itemName=FTL.ftl">FTL VSCode extension</a> will run FTL within VSCode, and provide LSP support for FTL, displaying errors within the editor.</p> +<h2 id="development">Development</h2> +<h3 id="intitialize-an-ftl-project">Intitialize an FTL project</h3> +<p>Once FTL is installed, initialize an FTL project:</p> +<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>mkdir myproject +</span><span>cd myproject +</span><span>ftl init myproject . --hermit +</span></code></pre> +<p>This will create an <code>ftl-project.toml</code> file, a git repository, and a <code>bin/</code> directory with Hermit tooling.</p> +<h3 id="create-a-new-module">Create a new module</h3> +<p>Now that you have an FTL project, create a new module:</p> +<div class="code-selector"> +<ul class="nav nav-tabs mb-2"> +</ul> +<!-- go --> +<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>ftl new go alice +</span></code></pre> +<p>This will place the code for the new module <code>alice</code> in <code>myproject/alice/alice.go</code>:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#b48ead;">package </span><span style="color:#bf616a;">alice +</span><span> +</span><span style="color:#b48ead;">import </span><span>( +</span><span> &quot;</span><span style="color:#a3be8c;">context</span><span>&quot; +</span><span> &quot;</span><span style="color:#a3be8c;">fmt</span><span>&quot; +</span><span> +</span><span> &quot;</span><span style="color:#a3be8c;">github.com/block/ftl/go-runtime/ftl</span><span>&quot; </span><span style="color:#65737e;">// Import the FTL SDK. +</span><span>) +</span><span> +</span><span style="color:#b48ead;">type </span><span>EchoRequest </span><span style="color:#b48ead;">struct </span><span>{ +</span><span> </span><span style="color:#bf616a;">Name ftl</span><span>.</span><span style="color:#b48ead;">Option</span><span>[</span><span style="color:#bf616a;">string</span><span>] `</span><span style="color:#a3be8c;">json:&quot;name&quot;</span><span>` +</span><span>} +</span><span> +</span><span style="color:#b48ead;">type </span><span>EchoResponse </span><span style="color:#b48ead;">struct </span><span>{ +</span><span> </span><span style="color:#bf616a;">Message </span><span style="color:#b48ead;">string </span><span>`</span><span style="color:#a3be8c;">json:&quot;message&quot;</span><span>` +</span><span>} +</span><span> +</span><span style="color:#65737e;">//ftl:verb +</span><span style="color:#b48ead;">func </span><span style="color:#8fa1b3;">Echo</span><span>(</span><span style="color:#bf616a;">ctx context</span><span>.</span><span style="color:#b48ead;">Context</span><span>, </span><span style="color:#bf616a;">req </span><span style="color:#b48ead;">EchoRequest</span><span>) (</span><span style="color:#b48ead;">EchoResponse</span><span>, </span><span style="color:#b48ead;">error</span><span>) { +</span><span> </span><span style="color:#b48ead;">return </span><span style="color:#bf616a;">EchoResponse</span><span>{</span><span style="color:#bf616a;">Message</span><span>: </span><span style="color:#bf616a;">fmt</span><span>.</span><span style="color:#bf616a;">Sprintf</span><span>(&quot;</span><span style="color:#a3be8c;">Hello, </span><span style="color:#d08770;">%s</span><span style="color:#a3be8c;">!</span><span>&quot;, </span><span style="color:#bf616a;">req</span><span>.</span><span style="color:#bf616a;">Name</span><span>.</span><span style="color:#bf616a;">Default</span><span>(&quot;</span><span style="color:#a3be8c;">anonymous</span><span>&quot;))}, </span><span style="color:#d08770;">nil +</span><span>} +</span></code></pre> +<p>Each module is its own Go module.</p> +<!-- kotlin --> +<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>ftl new kotlin alice +</span></code></pre> +<p>This will create a new Maven <code>pom.xml</code> based project in the directory <code>alice</code> and create new example code in <code>alice/src/main/kotlin/com/example/EchoVerb.kt</code>:</p> +<pre data-lang="kotlin" style="background-color:#2b303b;color:#c0c5ce;" class="language-kotlin "><code class="language-kotlin" data-lang="kotlin"><span style="color:#b48ead;">package </span><span>com.example +</span><span> +</span><span style="color:#b48ead;">import</span><span> xyz.block.ftl.Export +</span><span style="color:#b48ead;">import</span><span> xyz.block.ftl.Verb +</span><span> +</span><span> +</span><span>@Export +</span><span>@Verb +</span><span style="color:#b48ead;">fun </span><span style="color:#8fa1b3;">echo</span><span>(req: </span><span style="color:#b48ead;">String</span><span>): </span><span style="color:#b48ead;">String </span><span>= &quot;</span><span style="color:#a3be8c;">Hello, </span><span style="color:#bf616a;">$req</span><span style="color:#a3be8c;">!</span><span>&quot; +</span></code></pre> +<!-- java --> +<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>ftl new java alice +</span></code></pre> +<p>This will create a new Maven <code>pom.xml</code> based project in the directory <code>alice</code> and create new example code in <code>alice/src/main/java/com/example/EchoVerb.java</code>:</p> +<pre data-lang="java" style="background-color:#2b303b;color:#c0c5ce;" class="language-java "><code class="language-java" data-lang="java"><span style="color:#b48ead;">package </span><span>com.example; +</span><span> +</span><span style="color:#b48ead;">import </span><span>xyz.block.ftl.</span><span style="color:#ebcb8b;">Export</span><span>; +</span><span style="color:#b48ead;">import </span><span>xyz.block.ftl.</span><span style="color:#ebcb8b;">Verb</span><span>; +</span><span> +</span><span style="color:#b48ead;">public class </span><span style="color:#ebcb8b;">EchoVerb </span><span style="color:#eff1f5;">{ +</span><span style="color:#eff1f5;"> +</span><span style="color:#eff1f5;"> @</span><span style="color:#bf616a;">Export +</span><span style="color:#eff1f5;"> @</span><span style="color:#bf616a;">Verb +</span><span style="color:#eff1f5;"> </span><span style="color:#b48ead;">public </span><span style="color:#ebcb8b;">String </span><span style="color:#8fa1b3;">echo</span><span style="color:#eff1f5;">(</span><span style="color:#ebcb8b;">String </span><span style="color:#bf616a;">request</span><span style="color:#eff1f5;">) { +</span><span style="color:#eff1f5;"> </span><span style="color:#b48ead;">return </span><span>&quot;</span><span style="color:#a3be8c;">Hello, </span><span>&quot; +</span><span style="color:#eff1f5;"> request </span><span>+ &quot;</span><span style="color:#a3be8c;">!</span><span>&quot;</span><span style="color:#eff1f5;">; +</span><span style="color:#eff1f5;"> } +</span><span style="color:#eff1f5;">} +</span></code></pre> +</div> +<p>Any number of modules can be added to your project, adjacent to each other.</p> +<h3 id="start-the-ftl-cluster">Start the FTL cluster</h3> +<h4 id="vscode">VSCode</h4> +<p>If using VSCode, opening the directory will prompt you to start FTL:</p> +<p><a href="https://block.github.io/ftl/docs/getting-started/quick-start/vscode.png"><img src="https://block.github.io/ftl/docs/getting-started/quick-start/vscode.png" alt="VSCode" /></a></p> +<h4 id="manually">Manually</h4> +<p>Alternatively start the local FTL development cluster from the command-line:</p> +<p><a href="https://block.github.io/ftl/docs/getting-started/quick-start/ftldev.png"><img src="https://block.github.io/ftl/docs/getting-started/quick-start/ftldev.png" alt="ftl dev" /></a></p> +<p>This will build and deploy all local modules. Modifying the code will cause <code>ftl dev</code> to rebuild and redeploy the module.</p> +<h3 id="open-the-console">Open the console</h3> +<p>FTL has a console that allows interaction with the cluster topology, logs, traces, +and more. Open a browser window at <a href="https://localhost:8899">https://localhost:8899</a> to view it:</p> +<p><a href="https://block.github.io/ftl/docs/getting-started/quick-start/console.png"><img src="https://block.github.io/ftl/docs/getting-started/quick-start/console.png" alt="FTL Console" /></a></p> +<h3 id="call-your-verb">Call your verb</h3> +<p>You can call verbs from the console:</p> +<p><img src="https://block.github.io/ftl/docs/getting-started/quick-start/consolecall.png" alt="console call" /></p> +<p>Or from a terminal use <code>ftl call</code> to call your verb:</p> +<p><a href="https://block.github.io/ftl/docs/getting-started/quick-start/ftlcall.png"><img src="https://block.github.io/ftl/docs/getting-started/quick-start/ftlcall.png" alt="ftl call" /></a></p> +<h3 id="create-another-module">Create another module</h3> +<p>Create another module and call <code>alice.echo</code> from it with by importing the <code>alice</code> module and adding the verb client, +<code>alice.EchoClient</code>, to the signature of the calling verb. It can be invoked as a function:</p> +<div class="code-selector"> +<ul class="nav nav-tabs mb-2"> +</ul> +<!-- go --> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#65737e;">//ftl:verb +</span><span style="color:#b48ead;">import </span><span>&quot;</span><span style="color:#a3be8c;">ftl/alice</span><span>&quot; +</span><span> +</span><span style="color:#65737e;">//ftl:verb +</span><span style="color:#b48ead;">func </span><span style="color:#8fa1b3;">Other</span><span>(</span><span style="color:#bf616a;">ctx context</span><span>.</span><span style="color:#b48ead;">Context</span><span>, </span><span style="color:#bf616a;">in </span><span style="color:#b48ead;">Request</span><span>, </span><span style="color:#bf616a;">ec alice</span><span>.</span><span style="color:#b48ead;">EchoClient</span><span>) (</span><span style="color:#b48ead;">Response</span><span>, </span><span style="color:#b48ead;">error</span><span>) { +</span><span> </span><span style="color:#bf616a;">out</span><span>, </span><span style="color:#bf616a;">err </span><span>:= </span><span style="color:#bf616a;">ec</span><span>(</span><span style="color:#bf616a;">ctx</span><span>, </span><span style="color:#bf616a;">alice</span><span>.</span><span style="color:#bf616a;">EchoRequest</span><span>{...}) +</span><span> ... +</span><span>} +</span></code></pre> +<!-- kotlin --> +<pre data-lang="kotlin" style="background-color:#2b303b;color:#c0c5ce;" class="language-kotlin "><code class="language-kotlin" data-lang="kotlin"><span style="color:#b48ead;">package </span><span>com.example +</span><span> +</span><span style="color:#b48ead;">import</span><span> xyz.block.ftl.Export +</span><span style="color:#b48ead;">import</span><span> xyz.block.ftl.Verb +</span><span style="color:#b48ead;">import</span><span> ftl.alice.EchoClient +</span><span> +</span><span> +</span><span>@Export +</span><span>@Verb +</span><span style="color:#b48ead;">fun </span><span style="color:#8fa1b3;">other</span><span>(req: </span><span style="color:#b48ead;">String</span><span>, echo: EchoClient): </span><span style="color:#b48ead;">String </span><span>= &quot;</span><span style="color:#a3be8c;">Hello from Other , </span><span style="color:#bf616a;">${echo.call(req)}</span><span style="color:#a3be8c;">!</span><span>&quot; +</span></code></pre> +<p>Note that the <code>EchoClient</code> is generated by FTL and must be imported. Unfortunately at the moment JVM based languages have +a bit of a chicken-and-egg problem with the generated clients. To force a dependency between the modules you need to add +an import on a class that does not exist yet, and then FTL will generate the client for you. This will be fixed in the future.</p> +<!-- java --> +<pre data-lang="java" style="background-color:#2b303b;color:#c0c5ce;" class="language-java "><code class="language-java" data-lang="java"><span style="color:#b48ead;">package </span><span>com.example.client; +</span><span> +</span><span style="color:#b48ead;">import </span><span>xyz.block.ftl.</span><span style="color:#ebcb8b;">Export</span><span>; +</span><span style="color:#b48ead;">import </span><span>xyz.block.ftl.</span><span style="color:#ebcb8b;">Verb</span><span>; +</span><span style="color:#b48ead;">import </span><span>ftl.alice.</span><span style="color:#ebcb8b;">EchoClient</span><span>; +</span><span> +</span><span style="color:#b48ead;">public class </span><span style="color:#ebcb8b;">OtherVerb </span><span style="color:#eff1f5;">{ +</span><span style="color:#eff1f5;"> +</span><span style="color:#eff1f5;"> @</span><span style="color:#bf616a;">Export +</span><span style="color:#eff1f5;"> @</span><span style="color:#bf616a;">Verb +</span><span style="color:#eff1f5;"> </span><span style="color:#b48ead;">public </span><span style="color:#ebcb8b;">String </span><span style="color:#8fa1b3;">other</span><span style="color:#eff1f5;">(</span><span style="color:#ebcb8b;">String </span><span style="color:#bf616a;">request</span><span style="color:#eff1f5;">, </span><span style="color:#ebcb8b;">EchoClient </span><span style="color:#bf616a;">echoClient</span><span style="color:#eff1f5;">) { +</span><span style="color:#eff1f5;"> </span><span style="color:#b48ead;">return </span><span>&quot;</span><span style="color:#a3be8c;">Hello, </span><span>&quot; +</span><span style="color:#eff1f5;"> echoClient.</span><span style="color:#bf616a;">call</span><span style="color:#eff1f5;">(request) </span><span>+ &quot;</span><span style="color:#a3be8c;">!</span><span>&quot;</span><span style="color:#eff1f5;">; +</span><span style="color:#eff1f5;"> } +</span><span style="color:#eff1f5;">} +</span></code></pre> +<p>Note that the <code>EchoClient</code> is generated by FTL and must be imported. Unfortunately at the moment JVM based languages have +a bit of a chicken-and-egg problem with the generated clients. To force a dependency between the modules you need to add +an import on a class that does not exist yet, and then FTL will generate the client for you. This will be fixed in the future.</p> +<!-- java --> +</div> +<h3 id="what-next">What next?</h3> +<p>Explore the <a href="../../reference/start/">reference documentation</a>.</p> + + + + + Cron + 2021-05-01T08:20:00+00:00 + 2021-05-01T08:20:00+00:00 + + + + + Unknown + + + + + + https://block.github.io/ftl/docs/reference/cron/ + + <p>A cron job is an Empty verb that will be called on a schedule. The syntax is described <a href="https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/utilities/crontab.html">here</a>.</p> +<p>You can also use a shorthand syntax for the cron job, supporting seconds (<code>s</code>), minutes (<code>m</code>), hours (<code>h</code>), and specific days of the week (e.g. <code>Mon</code>).</p> +<h3 id="examples">Examples</h3> +<p>The following function will be called hourly:</p> +<div class="code-selector"> +<ul class="nav nav-tabs mb-2"> +</ul> +<!-- go --> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#65737e;">//ftl:cron 0 * * * * +</span><span style="color:#b48ead;">func </span><span style="color:#8fa1b3;">Hourly</span><span>(</span><span style="color:#bf616a;">ctx context</span><span>.</span><span style="color:#b48ead;">Context</span><span>) </span><span style="color:#b48ead;">error </span><span>{ +</span><span> </span><span style="color:#65737e;">// ... +</span><span>} +</span></code></pre> +<!-- kotlin --> +<pre data-lang="kotlin" style="background-color:#2b303b;color:#c0c5ce;" class="language-kotlin "><code class="language-kotlin" data-lang="kotlin"><span style="color:#b48ead;">import</span><span> xyz.block.ftl.Cron +</span><span>@Cron(&quot;</span><span style="color:#a3be8c;">0 * * * *</span><span>&quot;) +</span><span style="color:#b48ead;">fun </span><span style="color:#8fa1b3;">hourly</span><span>() { +</span><span> +</span><span>} +</span></code></pre> +<!-- java --> +<pre data-lang="java" style="background-color:#2b303b;color:#c0c5ce;" class="language-java "><code class="language-java" data-lang="java"><span style="color:#b48ead;">import </span><span>xyz.block.ftl.</span><span style="color:#ebcb8b;">Cron</span><span>; +</span><span> +</span><span style="color:#b48ead;">class </span><span style="color:#ebcb8b;">MyCron </span><span style="color:#eff1f5;">{ +</span><span style="color:#eff1f5;"> @</span><span style="color:#bf616a;">Cron</span><span style="color:#eff1f5;">(</span><span>&quot;</span><span style="color:#a3be8c;">0 * * * *</span><span>&quot;</span><span style="color:#eff1f5;">) +</span><span style="color:#eff1f5;"> </span><span style="color:#b48ead;">void </span><span style="color:#8fa1b3;">hourly</span><span style="color:#eff1f5;">() { +</span><span style="color:#eff1f5;"> +</span><span style="color:#eff1f5;"> } +</span><span style="color:#eff1f5;">} +</span></code></pre> +</div> +<p>Every 12 hours, starting at UTC midnight:</p> +<div class="code-selector"> +<ul class="nav nav-tabs mb-2"> +</ul> +<!-- go --> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#65737e;">//ftl:cron 12h +</span><span style="color:#b48ead;">func </span><span style="color:#8fa1b3;">TwiceADay</span><span>(</span><span style="color:#bf616a;">ctx context</span><span>.</span><span style="color:#b48ead;">Context</span><span>) </span><span style="color:#b48ead;">error </span><span>{ +</span><span> </span><span style="color:#65737e;">// ... +</span><span>} +</span></code></pre> +<!-- kotlin --> +<pre data-lang="kotlin" style="background-color:#2b303b;color:#c0c5ce;" class="language-kotlin "><code class="language-kotlin" data-lang="kotlin"><span style="color:#b48ead;">import</span><span> xyz.block.ftl.Cron +</span><span>@Cron(&quot;</span><span style="color:#a3be8c;">12h</span><span>&quot;) +</span><span style="color:#b48ead;">fun </span><span style="color:#8fa1b3;">twiceADay</span><span>() { +</span><span> +</span><span>} +</span></code></pre> +<!-- java --> +<pre data-lang="java" style="background-color:#2b303b;color:#c0c5ce;" class="language-java "><code class="language-java" data-lang="java"><span style="color:#b48ead;">import </span><span>xyz.block.ftl.</span><span style="color:#ebcb8b;">Cron</span><span>; +</span><span> +</span><span style="color:#b48ead;">class </span><span style="color:#ebcb8b;">MyCron </span><span style="color:#eff1f5;">{ +</span><span style="color:#eff1f5;"> @</span><span style="color:#bf616a;">Cron</span><span style="color:#eff1f5;">(</span><span>&quot;</span><span style="color:#a3be8c;">12h</span><span>&quot;</span><span style="color:#eff1f5;">) +</span><span style="color:#eff1f5;"> </span><span style="color:#b48ead;">void </span><span style="color:#8fa1b3;">twiceADay</span><span style="color:#eff1f5;">() { +</span><span style="color:#eff1f5;"> +</span><span style="color:#eff1f5;"> } +</span><span style="color:#eff1f5;">} +</span></code></pre> +</div> +<p>Every Monday at UTC midnight:</p> +<div class="code-selector"> +<ul class="nav nav-tabs mb-2"> +</ul> +<!-- go --> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#65737e;">//ftl:cron Mon +</span><span style="color:#b48ead;">func </span><span style="color:#8fa1b3;">Mondays</span><span>(</span><span style="color:#bf616a;">ctx context</span><span>.</span><span style="color:#b48ead;">Context</span><span>) </span><span style="color:#b48ead;">error </span><span>{ +</span><span> </span><span style="color:#65737e;">// ... +</span><span>} +</span></code></pre> +<!-- kotlin --> +<pre data-lang="kotlin" style="background-color:#2b303b;color:#c0c5ce;" class="language-kotlin "><code class="language-kotlin" data-lang="kotlin"><span style="color:#b48ead;">import</span><span> xyz.block.ftl.Cron +</span><span>@Cron(&quot;</span><span style="color:#a3be8c;">Mon</span><span>&quot;) +</span><span style="color:#b48ead;">fun </span><span style="color:#8fa1b3;">mondays</span><span>() { +</span><span> +</span><span>} +</span></code></pre> +<!-- java --> +<pre data-lang="java" style="background-color:#2b303b;color:#c0c5ce;" class="language-java "><code class="language-java" data-lang="java"><span style="color:#b48ead;">import </span><span>xyz.block.ftl.</span><span style="color:#ebcb8b;">Cron</span><span>; +</span><span> +</span><span style="color:#b48ead;">class </span><span style="color:#ebcb8b;">MyCron </span><span style="color:#eff1f5;">{ +</span><span style="color:#eff1f5;"> @</span><span style="color:#bf616a;">Cron</span><span style="color:#eff1f5;">(</span><span>&quot;</span><span style="color:#a3be8c;">Mon</span><span>&quot;</span><span style="color:#eff1f5;">) +</span><span style="color:#eff1f5;"> </span><span style="color:#b48ead;">void </span><span style="color:#8fa1b3;">mondays</span><span style="color:#eff1f5;">() { +</span><span style="color:#eff1f5;"> +</span><span style="color:#eff1f5;"> } +</span><span style="color:#eff1f5;">} +</span></code></pre> +</div> + + + + + HTTP Ingress + 2021-05-01T08:20:00+00:00 + 2021-05-01T08:20:00+00:00 + + + + + Unknown + + + + + + https://block.github.io/ftl/docs/reference/ingress/ + + <p>Verbs annotated with <code>ftl:ingress</code> will be exposed via HTTP (<code>http</code> is the default ingress type). These endpoints will then be available on one of our default <code>ingress</code> ports (local development defaults to <code>http://localhost:8891</code>).</p> +<p>The following will be available at <code>http://localhost:8891/http/users/123/posts?postId=456</code>.</p> +<div class="code-selector"> +<ul class="nav nav-tabs mb-2"> +</ul> +<!-- go --> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#b48ead;">type </span><span>GetRequestPathParams </span><span style="color:#b48ead;">struct </span><span>{ +</span><span> </span><span style="color:#bf616a;">UserID </span><span style="color:#b48ead;">string </span><span>`</span><span style="color:#a3be8c;">json:&quot;userId&quot;</span><span>` +</span><span>} +</span><span> +</span><span style="color:#b48ead;">type </span><span>GetRequestQueryParams </span><span style="color:#b48ead;">struct </span><span>{ +</span><span> </span><span style="color:#bf616a;">PostID </span><span style="color:#b48ead;">string </span><span>`</span><span style="color:#a3be8c;">json:&quot;postId&quot;</span><span>` +</span><span>} +</span><span> +</span><span style="color:#b48ead;">type </span><span>GetResponse </span><span style="color:#b48ead;">struct </span><span>{ +</span><span> </span><span style="color:#bf616a;">Message </span><span style="color:#b48ead;">string </span><span>`</span><span style="color:#a3be8c;">json:&quot;msg&quot;</span><span>` +</span><span>} +</span><span> +</span><span style="color:#65737e;">//ftl:ingress GET /http/users/{userId}/posts +</span><span style="color:#b48ead;">func </span><span style="color:#8fa1b3;">Get</span><span>(</span><span style="color:#bf616a;">ctx context</span><span>.</span><span style="color:#b48ead;">Context</span><span>, </span><span style="color:#bf616a;">req builtin</span><span>.</span><span style="color:#b48ead;">HttpRequest</span><span>[</span><span style="color:#bf616a;">ftl</span><span>.</span><span style="color:#bf616a;">Unit</span><span>, </span><span style="color:#bf616a;">GetRequestPathParams</span><span>, </span><span style="color:#bf616a;">GetRequestQueryParams</span><span>]) (</span><span style="color:#bf616a;">builtin</span><span>.</span><span style="color:#b48ead;">HttpResponse</span><span>[</span><span style="color:#bf616a;">GetResponse</span><span>, </span><span style="color:#bf616a;">ErrorResponse</span><span>], </span><span style="color:#b48ead;">error</span><span>) { +</span><span> </span><span style="color:#65737e;">// ... +</span><span>} +</span></code></pre> +<p>Because the example above only has a single path parameter it can be simplified by just using a scalar such as <code>string</code> or <code>int64</code> as the path parameter type:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span> +</span><span style="color:#65737e;">//ftl:ingress GET /http/users/{userId}/posts +</span><span style="color:#b48ead;">func </span><span style="color:#8fa1b3;">Get</span><span>(</span><span style="color:#bf616a;">ctx context</span><span>.</span><span style="color:#b48ead;">Context</span><span>, </span><span style="color:#bf616a;">req builtin</span><span>.</span><span style="color:#b48ead;">HttpRequest</span><span>[</span><span style="color:#bf616a;">ftl</span><span>.</span><span style="color:#bf616a;">Unit</span><span>, </span><span style="color:#bf616a;">int64</span><span>, </span><span style="color:#bf616a;">GetRequestQueryParams</span><span>]) (</span><span style="color:#bf616a;">builtin</span><span>.</span><span style="color:#b48ead;">HttpResponse</span><span>[</span><span style="color:#bf616a;">GetResponse</span><span>, </span><span style="color:#bf616a;">ErrorResponse</span><span>], </span><span style="color:#b48ead;">error</span><span>) { +</span><span> </span><span style="color:#65737e;">// ... +</span><span>} +</span></code></pre> +<blockquote> +<p><strong>NOTE!</strong> +The <code>req</code> and <code>resp</code> types of HTTP <code>ingress</code> <a href="../verbs">verbs</a> must be <code>builtin.HttpRequest</code> and <code>builtin.HttpResponse</code> respectively. These types provide the necessary fields for HTTP <code>ingress</code> (<code>headers</code>, <code>statusCode</code>, etc.)</p> +<p>You will need to import <code>ftl/builtin</code>.</p> +</blockquote> +<p>Key points:</p> +<ul> +<li><code>ingress</code> verbs will be automatically exported by default.</li> +</ul> +<h2 id="field-mapping">Field mapping</h2> +<p>The <code>HttpRequest</code> request object takes 3 type parameters, the body, the path parameters and the query parameters.</p> +<p>Given the following request verb:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span> +</span><span style="color:#b48ead;">type </span><span>PostBody </span><span style="color:#b48ead;">struct</span><span>{ +</span><span> </span><span style="color:#bf616a;">Title </span><span style="color:#b48ead;">string </span><span>`</span><span style="color:#a3be8c;">json:&quot;title&quot;</span><span>` +</span><span> </span><span style="color:#bf616a;">Content </span><span style="color:#b48ead;">string </span><span>`</span><span style="color:#a3be8c;">json:&quot;content&quot;</span><span>` +</span><span> </span><span style="color:#bf616a;">Tag ftl</span><span>.</span><span style="color:#b48ead;">Option</span><span>[</span><span style="color:#bf616a;">string</span><span>] `</span><span style="color:#a3be8c;">json:&quot;tag&quot;</span><span>` +</span><span>} +</span><span style="color:#b48ead;">type </span><span>PostPathParams </span><span style="color:#b48ead;">struct </span><span>{ +</span><span> </span><span style="color:#bf616a;">UserID </span><span style="color:#b48ead;">string </span><span>`</span><span style="color:#a3be8c;">json:&quot;userId&quot;</span><span>` +</span><span> </span><span style="color:#bf616a;">PostID </span><span style="color:#b48ead;">string </span><span>`</span><span style="color:#a3be8c;">json:&quot;postId&quot;</span><span>` +</span><span>} +</span><span> +</span><span style="color:#b48ead;">type </span><span>PostQueryParams </span><span style="color:#b48ead;">struct </span><span>{ +</span><span> </span><span style="color:#bf616a;">Publish </span><span style="color:#b48ead;">boolean </span><span>`</span><span style="color:#a3be8c;">json:&quot;publish&quot;</span><span>` +</span><span>} +</span><span> +</span><span style="color:#65737e;">//ftl:ingress http PUT /users/{userId}/posts/{postId} +</span><span style="color:#b48ead;">func </span><span style="color:#8fa1b3;">Get</span><span>(</span><span style="color:#bf616a;">ctx context</span><span>.</span><span style="color:#b48ead;">Context</span><span>, </span><span style="color:#bf616a;">req builtin</span><span>.</span><span style="color:#b48ead;">HttpRequest</span><span>[</span><span style="color:#bf616a;">PostBody</span><span>, </span><span style="color:#bf616a;">PostPathParams</span><span>, </span><span style="color:#bf616a;">PostQueryParams</span><span>]) (</span><span style="color:#bf616a;">builtin</span><span>.</span><span style="color:#b48ead;">HttpResponse</span><span>[</span><span style="color:#bf616a;">GetResponse</span><span>, </span><span style="color:#bf616a;">string</span><span>], </span><span style="color:#b48ead;">error</span><span>) { +</span><span> </span><span style="color:#b48ead;">return </span><span style="color:#bf616a;">builtin</span><span>.</span><span style="color:#bf616a;">HttpResponse</span><span>[</span><span style="color:#bf616a;">GetResponse</span><span>, </span><span style="color:#bf616a;">string</span><span>]{ +</span><span> </span><span style="color:#bf616a;">Headers</span><span>: </span><span style="color:#b48ead;">map</span><span>[</span><span style="color:#b48ead;">string</span><span>][]</span><span style="color:#b48ead;">string</span><span>{&quot;</span><span style="color:#a3be8c;">Get</span><span>&quot;: {&quot;</span><span style="color:#a3be8c;">Header from FTL</span><span>&quot;}}, +</span><span> </span><span style="color:#bf616a;">Body</span><span>: </span><span style="color:#bf616a;">ftl</span><span>.</span><span style="color:#bf616a;">Some</span><span>(</span><span style="color:#bf616a;">GetResponse</span><span>{ +</span><span> </span><span style="color:#bf616a;">Message</span><span>: </span><span style="color:#bf616a;">fmt</span><span>.</span><span style="color:#bf616a;">Sprintf</span><span>(&quot;</span><span style="color:#a3be8c;">UserID: </span><span style="color:#d08770;">%s</span><span style="color:#a3be8c;">, PostID: </span><span style="color:#d08770;">%s</span><span style="color:#a3be8c;">, Tag: </span><span style="color:#d08770;">%s</span><span>&quot;, </span><span style="color:#bf616a;">req</span><span>.</span><span style="color:#bf616a;">pathParameters</span><span>.</span><span style="color:#bf616a;">UserID</span><span>, </span><span style="color:#bf616a;">req</span><span>.</span><span style="color:#bf616a;">pathParameters</span><span>.</span><span style="color:#bf616a;">PostID</span><span>, </span><span style="color:#bf616a;">req</span><span>.</span><span style="color:#bf616a;">Body</span><span>.</span><span style="color:#bf616a;">Tag</span><span>.</span><span style="color:#bf616a;">Default</span><span>(&quot;</span><span style="color:#a3be8c;">none</span><span>&quot;)), +</span><span> }), +</span><span> }, </span><span style="color:#d08770;">nil +</span><span>} +</span></code></pre> +<p>The rules for how each element is mapped are slightly different, as they have a different structure:</p> +<ul> +<li>The body is mapped directly to the body of the request, generally as a JSON object. Scalars are also supported, as well as []byte to get the raw body. If they type is <code>any</code> then it will be assumed to be JSON and mapped to the appropriate types based on the JSON structure.</li> +<li>The path parameters can be mapped directly to an object with field names corresponding to the name of the path parameter. If there is only a single path parameter it can be injected directly as a scalar. They can also be injected as a <code>map[string]string</code>.</li> +<li>The path parameters can also be mapped directly to an object with field names corresponding to the name of the path parameter. They can also be injected directly as a <code>map[string]string</code>, or <code>map[string][]string</code> for multiple values.</li> +</ul> +<h4 id="optional-fields">Optional fields</h4> +<p>Optional fields are represented by the <code>ftl.Option</code> type. The <code>Option</code> type is a wrapper around the actual type and can be <code>Some</code> or <code>None</code>. In the example above, the <code>Tag</code> field is optional.</p> +<pre data-lang="sh" style="background-color:#2b303b;color:#c0c5ce;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#bf616a;">curl -i</span><span> http://localhost:8891/users/123/posts/456 +</span></code></pre> +<p>Because the <code>tag</code> query parameter is not provided, the response will be:</p> +<pre data-lang="json" style="background-color:#2b303b;color:#c0c5ce;" class="language-json "><code class="language-json" data-lang="json"><span>{ +</span><span> &quot;</span><span style="color:#a3be8c;">msg</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">UserID: 123, PostID: 456, Tag: none</span><span>&quot; +</span><span>} +</span></code></pre> +<h4 id="casing">Casing</h4> +<p>Field names use lowerCamelCase by default. You can override this by using the <code>json</code> tag.</p> +<h2 id="sumtypes">SumTypes</h2> +<p>Given the following request verb:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#65737e;">//ftl:enum export +</span><span style="color:#b48ead;">type </span><span>SumType </span><span style="color:#b48ead;">interface </span><span>{ +</span><span> </span><span style="color:#8fa1b3;">tag</span><span>() +</span><span>} +</span><span> +</span><span style="color:#b48ead;">type </span><span>A </span><span style="color:#b48ead;">string +</span><span> +</span><span style="color:#b48ead;">func </span><span>(</span><span style="color:#b48ead;">A</span><span>) </span><span style="color:#8fa1b3;">tag</span><span>() {} +</span><span> +</span><span style="color:#b48ead;">type </span><span>B []</span><span style="color:#b48ead;">string +</span><span> +</span><span style="color:#b48ead;">func </span><span>(</span><span style="color:#b48ead;">B</span><span>) </span><span style="color:#8fa1b3;">tag</span><span>() {} +</span><span> +</span><span style="color:#65737e;">//ftl:ingress http POST /typeenum +</span><span style="color:#b48ead;">func </span><span style="color:#8fa1b3;">TypeEnum</span><span>(</span><span style="color:#bf616a;">ctx context</span><span>.</span><span style="color:#b48ead;">Context</span><span>, </span><span style="color:#bf616a;">req builtin</span><span>.</span><span style="color:#b48ead;">HttpRequest</span><span>[</span><span style="color:#bf616a;">SumType</span><span>, </span><span style="color:#bf616a;">ftl</span><span>.</span><span style="color:#bf616a;">Unit</span><span>, </span><span style="color:#bf616a;">ftl</span><span>.</span><span style="color:#bf616a;">Unit</span><span>]) (</span><span style="color:#bf616a;">builtin</span><span>.</span><span style="color:#b48ead;">HttpResponse</span><span>[</span><span style="color:#bf616a;">SumType</span><span>, </span><span style="color:#bf616a;">string</span><span>], </span><span style="color:#b48ead;">error</span><span>) { +</span><span> </span><span style="color:#b48ead;">return </span><span style="color:#bf616a;">builtin</span><span>.</span><span style="color:#bf616a;">HttpResponse</span><span>[</span><span style="color:#bf616a;">SumType</span><span>, </span><span style="color:#bf616a;">string</span><span>]{</span><span style="color:#bf616a;">Body</span><span>: </span><span style="color:#bf616a;">ftl</span><span>.</span><span style="color:#bf616a;">Some</span><span>(</span><span style="color:#bf616a;">req</span><span>.</span><span style="color:#bf616a;">Body</span><span>)}, </span><span style="color:#d08770;">nil +</span><span>} +</span></code></pre> +<p>The following curl request will map the <code>SumType</code> name and value to the <code>req.Body</code>:</p> +<pre data-lang="sh" style="background-color:#2b303b;color:#c0c5ce;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#bf616a;">curl -X</span><span> POST &quot;</span><span style="color:#a3be8c;">http://localhost:8891/typeenum</span><span>&quot; \ +</span><span style="color:#bf616a;"> -H </span><span>&quot;</span><span style="color:#a3be8c;">Content-Type: application/json</span><span>&quot; \ +</span><span style="color:#bf616a;"> --data </span><span>&#39;</span><span style="color:#a3be8c;">{&quot;name&quot;: &quot;A&quot;, &quot;value&quot;: &quot;sample&quot;}</span><span>&#39; +</span></code></pre> +<p>The response will be:</p> +<pre data-lang="json" style="background-color:#2b303b;color:#c0c5ce;" class="language-json "><code class="language-json" data-lang="json"><span>{ +</span><span> &quot;</span><span style="color:#a3be8c;">name</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">A</span><span>&quot;, +</span><span> &quot;</span><span style="color:#a3be8c;">value</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">sample</span><span>&quot; +</span><span>} +</span></code></pre> +<h2 id="encoding-query-params-as-json">Encoding query params as JSON</h2> +<p>Complex query params can also be encoded as JSON using the <code>@json</code> query parameter. For example:</p> +<blockquote> +<p><code>{"tag":"ftl"}</code> url-encoded is <code>%7B%22tag%22%3A%22ftl%22%7D</code></p> +</blockquote> +<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#bf616a;">curl -i</span><span> http://localhost:8891/users/123/posts/456?@json=%</span><span style="color:#d08770;">7</span><span>B%</span><span style="color:#d08770;">22</span><span>tag%</span><span style="color:#d08770;">22</span><span>%</span><span style="color:#d08770;">3</span><span>A%</span><span style="color:#d08770;">22</span><span>ftl%</span><span style="color:#d08770;">22</span><span>%</span><span style="color:#d08770;">7</span><span>D +</span></code></pre> +<!-- java --> +<p>JVM Languages use the <code>JAX-RS</code> annotations to define HTTP endpoints. The following example shows how to define an HTTP endpoint in Java. As the underling implementation is based on <a href="https://quarkus.io">Quarkus</a> +it is also possible to use the <a href="https://quarkus.io/guides/rest#accessing-request-parameters">Quarkus extensions to the JAX-RS annotations</a>:</p> +<p>In general the difference between the Quarkus annotation and the standard JAX-RS ones is that the Quarkus parameters infer the parameter name from the method parameter name, while the JAX-RS ones require the parameter name to be explicitly defined.</p> +<pre data-lang="java" style="background-color:#2b303b;color:#c0c5ce;" class="language-java "><code class="language-java" data-lang="java"><span> +</span><span style="color:#b48ead;">import </span><span>java.util.</span><span style="color:#ebcb8b;">List</span><span>; +</span><span> +</span><span style="color:#b48ead;">import </span><span>jakarta.ws.rs.</span><span style="color:#ebcb8b;">DELETE</span><span>; +</span><span style="color:#b48ead;">import </span><span>jakarta.ws.rs.</span><span style="color:#ebcb8b;">GET</span><span>; +</span><span style="color:#b48ead;">import </span><span>jakarta.ws.rs.</span><span style="color:#ebcb8b;">POST</span><span>; +</span><span style="color:#b48ead;">import </span><span>jakarta.ws.rs.</span><span style="color:#ebcb8b;">PUT</span><span>; +</span><span style="color:#b48ead;">import </span><span>jakarta.ws.rs.</span><span style="color:#ebcb8b;">Path</span><span>; +</span><span> +</span><span style="color:#b48ead;">import </span><span>jakarta.ws.rs.</span><span style="color:#ebcb8b;">QueryParam</span><span>; </span><span style="color:#65737e;">// JAX-RS annotation to get the query parameter +</span><span style="color:#b48ead;">import </span><span>org.jboss.resteasy.reactive.</span><span style="color:#ebcb8b;">RestPath</span><span>; </span><span style="color:#65737e;">// Quarkus annotation to get the path parameter +</span><span> +</span><span>@</span><span style="color:#bf616a;">Path</span><span>(&quot;</span><span style="color:#a3be8c;">/</span><span>&quot;) +</span><span style="color:#b48ead;">public class </span><span style="color:#ebcb8b;">TestHTTP </span><span style="color:#eff1f5;">{ +</span><span style="color:#eff1f5;"> +</span><span style="color:#eff1f5;"> @</span><span style="color:#bf616a;">GET +</span><span style="color:#eff1f5;"> @</span><span style="color:#bf616a;">Path</span><span style="color:#eff1f5;">(</span><span>&quot;</span><span style="color:#a3be8c;">/http/users/{userId}/posts</span><span>&quot;</span><span style="color:#eff1f5;">) +</span><span style="color:#eff1f5;"> </span><span style="color:#b48ead;">public </span><span style="color:#ebcb8b;">String </span><span style="color:#8fa1b3;">get</span><span style="color:#eff1f5;">(@</span><span style="color:#bf616a;">RestPath </span><span style="color:#ebcb8b;">String </span><span style="color:#bf616a;">userId</span><span style="color:#eff1f5;">, @</span><span style="color:#bf616a;">QueryParam</span><span style="color:#eff1f5;">(</span><span>&quot;</span><span style="color:#a3be8c;">postId</span><span>&quot;</span><span style="color:#eff1f5;">) </span><span style="color:#ebcb8b;">String </span><span style="color:#bf616a;">post</span><span style="color:#eff1f5;">) { +</span><span style="color:#eff1f5;"> </span><span style="color:#65737e;">//... +</span><span style="color:#eff1f5;"> } +</span><span style="color:#eff1f5;"> +</span><span style="color:#eff1f5;">} +</span></code></pre> +<p>Under the hood these HTTP invocations are being mapped to verbs that take a <code>builtin.HttpRequest</code> and return a <code>builtin.HttpResponse</code>. This is not exposed directly to the user, but is instead mapped directly to <code>JAX-RS</code> annotations.</p> +</div> + + + + + Feature Matrix + 2021-05-01T08:20:00+00:00 + 2021-05-01T08:20:00+00:00 + + + + + Unknown + + + + + + https://block.github.io/ftl/docs/reference/matrix/ + + <table><thead><tr><th style="text-align: left">System</th><th style="text-align: left">Feature</th><th style="text-align: left">Go</th><th style="text-align: left">JVM</th><th style="text-align: left">Rust</th></tr></thead><tbody> +<tr><td style="text-align: left"><strong>Types</strong></td><td style="text-align: left">Basic Types</td><td style="text-align: left">✔️</td><td style="text-align: left">✔️</td><td style="text-align: left">️ ✔️</td></tr> +<tr><td style="text-align: left"></td><td style="text-align: left">Optional Type</td><td style="text-align: left">✔️</td><td style="text-align: left">✔️</td><td style="text-align: left"></td></tr> +<tr><td style="text-align: left"></td><td style="text-align: left">Unit Type</td><td style="text-align: left">✔️</td><td style="text-align: left">✔️</td><td style="text-align: left"></td></tr> +<tr><td style="text-align: left"></td><td style="text-align: left">Empty Type</td><td style="text-align: left">✔️</td><td style="text-align: left">✔️</td><td style="text-align: left"></td></tr> +<tr><td style="text-align: left"></td><td style="text-align: left">Generic Types</td><td style="text-align: left">✔️</td><td style="text-align: left">✔️</td><td style="text-align: left"></td></tr> +<tr><td style="text-align: left"></td><td style="text-align: left">Type Aliases</td><td style="text-align: left">✔️</td><td style="text-align: left">️</td><td style="text-align: left"></td></tr> +<tr><td style="text-align: left"></td><td style="text-align: left">Value Enums</td><td style="text-align: left">✔️</td><td style="text-align: left">️</td><td style="text-align: left"></td></tr> +<tr><td style="text-align: left"></td><td style="text-align: left">Type Enums</td><td style="text-align: left">✔️</td><td style="text-align: left">️</td><td style="text-align: left"></td></tr> +<tr><td style="text-align: left"></td><td style="text-align: left">Visibility</td><td style="text-align: left">✔️</td><td style="text-align: left">✔️</td><td style="text-align: left"></td></tr> +<tr><td style="text-align: left"><strong>Verbs</strong></td><td style="text-align: left">Verb</td><td style="text-align: left">✔️</td><td style="text-align: left">✔️</td><td style="text-align: left">️✔️</td></tr> +<tr><td style="text-align: left"></td><td style="text-align: left">Sink</td><td style="text-align: left">✔️</td><td style="text-align: left">✔️</td><td style="text-align: left"></td></tr> +<tr><td style="text-align: left"></td><td style="text-align: left">Source</td><td style="text-align: left">✔️</td><td style="text-align: left">✔️</td><td style="text-align: left"></td></tr> +<tr><td style="text-align: left"></td><td style="text-align: left">Empty</td><td style="text-align: left">✔️</td><td style="text-align: left">✔️</td><td style="text-align: left"></td></tr> +<tr><td style="text-align: left"></td><td style="text-align: left">Visibility</td><td style="text-align: left">✔️</td><td style="text-align: left">✔️</td><td style="text-align: left"></td></tr> +<tr><td style="text-align: left"><strong>Core</strong></td><td style="text-align: left">Leases</td><td style="text-align: left">✔️</td><td style="text-align: left">✔️</td><td style="text-align: left"></td></tr> +<tr><td style="text-align: left"></td><td style="text-align: left">Cron</td><td style="text-align: left">✔️</td><td style="text-align: left">✔️</td><td style="text-align: left"></td></tr> +<tr><td style="text-align: left"></td><td style="text-align: left">Config</td><td style="text-align: left">✔️</td><td style="text-align: left">✔️</td><td style="text-align: left"></td></tr> +<tr><td style="text-align: left"></td><td style="text-align: left">Secrets</td><td style="text-align: left">✔️</td><td style="text-align: left">✔️</td><td style="text-align: left"></td></tr> +<tr><td style="text-align: left"></td><td style="text-align: left">HTTP Ingress</td><td style="text-align: left">✔️</td><td style="text-align: left">✔️</td><td style="text-align: left"></td></tr> +<tr><td style="text-align: left"><strong>Resources</strong></td><td style="text-align: left">PostgreSQL</td><td style="text-align: left">✔️</td><td style="text-align: left">✔️</td><td style="text-align: left"></td></tr> +<tr><td style="text-align: left"></td><td style="text-align: left">MySQL</td><td style="text-align: left"></td><td style="text-align: left"></td><td style="text-align: left"></td></tr> +<tr><td style="text-align: left"></td><td style="text-align: left">Kafka</td><td style="text-align: left"></td><td style="text-align: left"></td><td style="text-align: left"></td></tr> +<tr><td style="text-align: left"><strong>PubSub</strong></td><td style="text-align: left">Declaring Topic</td><td style="text-align: left">✔️</td><td style="text-align: left">✔️</td><td style="text-align: left"></td></tr> +<tr><td style="text-align: left"></td><td style="text-align: left">Subscribing</td><td style="text-align: left">✔️</td><td style="text-align: left">✔️</td><td style="text-align: left"></td></tr> +<tr><td style="text-align: left"></td><td style="text-align: left">Publishing</td><td style="text-align: left">✔️</td><td style="text-align: left">✔️</td><td style="text-align: left"></td></tr> +</tbody></table> + + + + + PubSub + 2021-05-01T08:20:00+00:00 + 2021-05-01T08:20:00+00:00 + + + + + Unknown + + + + + + https://block.github.io/ftl/docs/reference/pubsub/ + + <p>FTL has first-class support for PubSub, modelled on the concepts of topics (where events are sent) and subscribers (a verb which consumes events). Subscribers are, as you would expect, sinks. Each subscriber is a cursor over the topic it is associated with. Each topic may have multiple subscriptions. Each published event has an at least once delivery guarantee for each subscription.</p> +<div class="code-selector"> +<ul class="nav nav-tabs mb-2"> +</ul> +<!-- go --> +<p>First, declare a new topic:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#b48ead;">package </span><span style="color:#bf616a;">payments +</span><span> +</span><span style="color:#b48ead;">type </span><span>Invoices = </span><span style="color:#bf616a;">ftl</span><span>.</span><span style="color:#b48ead;">TopicHandle</span><span>[</span><span style="color:#bf616a;">Invoice</span><span>, </span><span style="color:#bf616a;">ftl</span><span>.</span><span style="color:#bf616a;">SinglePartitionMap</span><span>[</span><span style="color:#bf616a;">Invoice</span><span>]] +</span></code></pre> +<p>Note that the name of the topic as represented in the FTL schema is the lower camel case version of the type name.</p> +<p>The <code>Invoices</code> type is a handle to the topic. It is a generic type that takes two arguments: the event type and the partition map type. The partition map type is used to map events to partitions. In this case, we are using a single partition map, which means that all events are sent to the same partition.</p> +<p>Then define a Sink to consume from the topic:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#65737e;">//ftl:subscribe payments.invoices from=beginning +</span><span style="color:#b48ead;">func </span><span style="color:#8fa1b3;">SendInvoiceEmail</span><span>(</span><span style="color:#bf616a;">ctx context</span><span>.</span><span style="color:#b48ead;">Context</span><span>, </span><span style="color:#bf616a;">in </span><span style="color:#b48ead;">Invoice</span><span>) </span><span style="color:#b48ead;">error </span><span>{ +</span><span> </span><span style="color:#65737e;">// ... +</span><span>} +</span></code></pre> +<p>Events can be published to a topic by injecting the topic type into a verb:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#b48ead;">func </span><span style="color:#8fa1b3;">PublishInvoice</span><span>(</span><span style="color:#bf616a;">ctx context</span><span>.</span><span style="color:#b48ead;">Context</span><span>, </span><span style="color:#bf616a;">topic </span><span style="color:#b48ead;">Invoices</span><span>) </span><span style="color:#b48ead;">error </span><span>{ +</span><span> </span><span style="color:#bf616a;">topic</span><span>.</span><span style="color:#bf616a;">Publish</span><span>(</span><span style="color:#bf616a;">ctx</span><span>, </span><span style="color:#bf616a;">Invoice</span><span>{...}) +</span><span> </span><span style="color:#65737e;">// ... +</span><span>} +</span></code></pre> +<!-- kotlin --> +<p>First, declare a new topic :</p> +<pre data-lang="kotlin" style="background-color:#2b303b;color:#c0c5ce;" class="language-kotlin "><code class="language-kotlin" data-lang="kotlin"><span>@Export +</span><span>@Topic(&quot;</span><span style="color:#a3be8c;">invoices</span><span>&quot;) +</span><span style="color:#b48ead;">internal interface </span><span style="color:#ebcb8b;">InvoiceTopic </span><span>: </span><span style="color:#a3be8c;">WriteableTopic</span><span>&lt;</span><span style="color:#a3be8c;">Invoice</span><span>&gt; +</span></code></pre> +<p>Events can be published to a topic by injecting it into an <code>@Verb</code> method:</p> +<pre data-lang="kotlin" style="background-color:#2b303b;color:#c0c5ce;" class="language-kotlin "><code class="language-kotlin" data-lang="kotlin"><span>@Verb +</span><span style="color:#b48ead;">fun </span><span style="color:#8fa1b3;">publishInvoice</span><span>(request: InvoiceRequest, topic: InvoiceTopic) { +</span><span> topic.publish(Invoice(request.getInvoiceNo())) +</span><span>} +</span></code></pre> +<p>To subscribe to a topic use the <code>@Subscription</code> annotation, referencing the topic class and providing a method to consume the event:</p> +<pre data-lang="kotlin" style="background-color:#2b303b;color:#c0c5ce;" class="language-kotlin "><code class="language-kotlin" data-lang="kotlin"><span>@Subscription(topic = InvoiceTopic::class, from = FromOffset.</span><span style="color:#d08770;">LATEST</span><span>) +</span><span style="color:#b48ead;">fun </span><span style="color:#8fa1b3;">consumeInvoice</span><span>(event: Invoice) { +</span><span> </span><span style="color:#65737e;">// ... +</span><span>} +</span></code></pre> +<p>If you are subscribing to a topic from another module, FTL will generate a topic class for you so you can subscribe to it. This generated +topic cannot be published to, only subscribed to:</p> +<pre data-lang="kotlin" style="background-color:#2b303b;color:#c0c5ce;" class="language-kotlin "><code class="language-kotlin" data-lang="kotlin"><span>@Topic(name=&quot;</span><span style="color:#a3be8c;">invoices</span><span>&quot;, module=&quot;</span><span style="color:#a3be8c;">publisher</span><span>&quot;) +</span><span style="color:#b48ead;">internal interface </span><span style="color:#ebcb8b;">InvoiceTopic </span><span>: </span><span style="color:#a3be8c;">ConsumableTopic</span><span>&lt;</span><span style="color:#a3be8c;">Invoice</span><span>&gt; +</span></code></pre> +<!-- java --> +<p>First, declare a new topic:</p> +<pre data-lang="java" style="background-color:#2b303b;color:#c0c5ce;" class="language-java "><code class="language-java" data-lang="java"><span>@</span><span style="color:#bf616a;">Export +</span><span>@</span><span style="color:#bf616a;">Topic</span><span>(&quot;</span><span style="color:#a3be8c;">invoices</span><span>&quot;) +</span><span style="color:#b48ead;">interface </span><span style="color:#ebcb8b;">InvoiceTopic </span><span style="color:#b48ead;">extends </span><span style="color:#a3be8c;">WriteableTopic</span><span style="color:#eff1f5;">&lt;</span><span style="color:#ebcb8b;">Invoice</span><span style="color:#eff1f5;">&gt; {} +</span></code></pre> +<p>Events can be published to a topic by injecting it into an <code>@Verb</code> method:</p> +<pre data-lang="java" style="background-color:#2b303b;color:#c0c5ce;" class="language-java "><code class="language-java" data-lang="java"><span>@</span><span style="color:#bf616a;">Verb +</span><span>void </span><span style="color:#bf616a;">publishInvoice</span><span>(</span><span style="color:#ebcb8b;">InvoiceRequest</span><span> request, </span><span style="color:#ebcb8b;">InvoiceTopic</span><span> topic) throws </span><span style="color:#ebcb8b;">Exception </span><span>{ +</span><span> topic.</span><span style="color:#bf616a;">publish</span><span>(</span><span style="color:#b48ead;">new </span><span style="color:#ebcb8b;">Invoice</span><span>(request.</span><span style="color:#bf616a;">getInvoiceNo</span><span>())); +</span><span>} +</span></code></pre> +<p>To subscribe to a topic use the <code>@Subscription</code> annotation, referencing the topic class and providing a method to consume the event:</p> +<pre data-lang="java" style="background-color:#2b303b;color:#c0c5ce;" class="language-java "><code class="language-java" data-lang="java"><span>@</span><span style="color:#bf616a;">Subscription</span><span>(</span><span style="color:#bf616a;">topic </span><span>= </span><span style="color:#ebcb8b;">InvoiceTopic</span><span>.</span><span style="color:#bf616a;">class</span><span>, </span><span style="color:#bf616a;">from </span><span>= </span><span style="color:#ebcb8b;">FromOffset</span><span>.</span><span style="color:#d08770;">LATEST</span><span>) +</span><span style="color:#b48ead;">public</span><span> void </span><span style="color:#bf616a;">consumeInvoice</span><span>(</span><span style="color:#ebcb8b;">Invoice</span><span> event) { +</span><span> </span><span style="color:#65737e;">// ... +</span><span>} +</span></code></pre> +<p>If you are subscribing to a topic from another module, FTL will generate a topic class for you so you can subscribe to it. This generated +topic cannot be published to, only subscribed to:</p> +<pre data-lang="java" style="background-color:#2b303b;color:#c0c5ce;" class="language-java "><code class="language-java" data-lang="java"><span>@</span><span style="color:#bf616a;">Topic</span><span>(</span><span style="color:#bf616a;">name</span><span>=&quot;</span><span style="color:#a3be8c;">invoices</span><span>&quot;, </span><span style="color:#bf616a;">module</span><span>=&quot;</span><span style="color:#a3be8c;">publisher</span><span>&quot;) +</span><span> </span><span style="color:#b48ead;">interface </span><span style="color:#ebcb8b;">InvoiceTopic </span><span style="color:#b48ead;">extends </span><span style="color:#a3be8c;">ConsumableTopic</span><span style="color:#eff1f5;">&lt;</span><span style="color:#ebcb8b;">Invoice</span><span style="color:#eff1f5;">&gt; {} +</span></code></pre> +</div> +<blockquote> +<p><strong>NOTE!</strong> +PubSub topics cannot be published to from outside the module that declared them, they can only be subscribed to. That is, if a topic is declared in module <code>A</code>, module <code>B</code> cannot publish to it.</p> +</blockquote> + + + + + Retries + 2021-05-01T08:20:00+00:00 + 2021-05-01T08:20:00+00:00 + + + + + Unknown + + + + + + https://block.github.io/ftl/docs/reference/retries/ + + <p>Some FTL features allow specifying a retry policy via a Go comment directive. Retries back off exponentially until the maximum is reached.</p> +<p>The directive has the following syntax:</p> +<div class="code-selector"> +<ul class="nav nav-tabs mb-2"> +</ul> +<!-- go --> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#65737e;">//ftl:retry [&lt;attempts=10&gt;] &lt;min-backoff&gt; [&lt;max-backoff=1hr&gt;] [catch &lt;catchVerb&gt;] +</span></code></pre> +<!-- kotlin --> +<pre data-lang="kotlin" style="background-color:#2b303b;color:#c0c5ce;" class="language-kotlin "><code class="language-kotlin" data-lang="kotlin"><span>@Retry(attempts = </span><span style="color:#d08770;">10</span><span>, minBackoff = &quot;</span><span style="color:#a3be8c;">5s</span><span>&quot;, maxBackoff = &quot;</span><span style="color:#a3be8c;">1h</span><span>&quot;, catchVerb = &quot;</span><span style="color:#a3be8c;">&lt;catchVerb&gt;</span><span>&quot;, catchModule = &quot;</span><span style="color:#a3be8c;">&lt;catchModule&gt;</span><span>&quot;) +</span></code></pre> +<!-- java --> +<pre data-lang="java" style="background-color:#2b303b;color:#c0c5ce;" class="language-java "><code class="language-java" data-lang="java"><span>@</span><span style="color:#bf616a;">Retry</span><span>(</span><span style="color:#bf616a;">attempts </span><span>= </span><span style="color:#d08770;">10</span><span>, </span><span style="color:#bf616a;">minBackoff </span><span>= &quot;</span><span style="color:#a3be8c;">5s</span><span>&quot;, </span><span style="color:#bf616a;">maxBackoff </span><span>= &quot;</span><span style="color:#a3be8c;">1h</span><span>&quot;, </span><span style="color:#bf616a;">catchVerb </span><span>= &quot;</span><span style="color:#a3be8c;">&lt;catchVerb&gt;</span><span>&quot;, </span><span style="color:#bf616a;">catchModule </span><span>= &quot;</span><span style="color:#a3be8c;">&lt;catchModule&gt;</span><span>&quot;) +</span></code></pre> +</div> +<p>For example, the following function will retry up to 10 times, with a delay of 5s, 10s, 20s, 40s, 60s, 60s, etc.</p> +<div class="code-selector"> +<ul class="nav nav-tabs mb-2"> +</ul> +<!-- go --> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#65737e;">//ftl:retry 10 5s 1m +</span><span style="color:#b48ead;">func </span><span style="color:#8fa1b3;">Process</span><span>(</span><span style="color:#bf616a;">ctx context</span><span>.</span><span style="color:#b48ead;">Context</span><span>, </span><span style="color:#bf616a;">in </span><span style="color:#b48ead;">Invoice</span><span>) </span><span style="color:#b48ead;">error </span><span>{ +</span><span> </span><span style="color:#65737e;">// ... +</span><span>} +</span></code></pre> +<!-- kotlin --> +<pre data-lang="kotlin" style="background-color:#2b303b;color:#c0c5ce;" class="language-kotlin "><code class="language-kotlin" data-lang="kotlin"><span>@Retry(count = </span><span style="color:#d08770;">10</span><span>, minBackoff = &quot;</span><span style="color:#a3be8c;">5s</span><span>&quot;, maxBackoff = &quot;</span><span style="color:#a3be8c;">1m</span><span>&quot;) +</span><span style="color:#b48ead;">fun </span><span style="color:#8fa1b3;">process</span><span>(inv: Invoice) { +</span><span> </span><span style="color:#65737e;">// ... +</span><span>} +</span></code></pre> +<!-- java --> +<pre data-lang="java" style="background-color:#2b303b;color:#c0c5ce;" class="language-java "><code class="language-java" data-lang="java"><span>@</span><span style="color:#bf616a;">Retry</span><span>(</span><span style="color:#bf616a;">count </span><span>= </span><span style="color:#d08770;">10</span><span>, </span><span style="color:#bf616a;">minBackoff </span><span>= &quot;</span><span style="color:#a3be8c;">5s</span><span>&quot;, </span><span style="color:#bf616a;">maxBackoff </span><span>= &quot;</span><span style="color:#a3be8c;">1m</span><span>&quot;) +</span><span style="color:#b48ead;">public</span><span> void </span><span style="color:#bf616a;">process</span><span>(</span><span style="color:#ebcb8b;">Invoice</span><span> in) { +</span><span> </span><span style="color:#65737e;">// ... +</span><span>} +</span></code></pre> +</div> +<h3 id="pubsub">PubSub</h3> +<p>Subscribers can have a retry policy. For example:</p> +<div class="code-selector"> +<ul class="nav nav-tabs mb-2"> +</ul> +<!-- go --> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#65737e;">//ftl:retry 5 1s catch recoverPaymentProcessing +</span><span style="color:#b48ead;">func </span><span style="color:#8fa1b3;">ProcessPayment</span><span>(</span><span style="color:#bf616a;">ctx context</span><span>.</span><span style="color:#b48ead;">Context</span><span>, </span><span style="color:#bf616a;">payment </span><span style="color:#b48ead;">Payment</span><span>) </span><span style="color:#b48ead;">error </span><span>{ +</span><span>... +</span><span>} +</span></code></pre> +<!-- kotlin --> +<pre data-lang="kotlin" style="background-color:#2b303b;color:#c0c5ce;" class="language-kotlin "><code class="language-kotlin" data-lang="kotlin"><span>@Subscription(topic = &quot;</span><span style="color:#a3be8c;">example</span><span>&quot;, name = &quot;</span><span style="color:#a3be8c;">exampleSubscription</span><span>&quot;) +</span><span>@SubscriptionOptions(from = FromOffset.</span><span style="color:#d08770;">LATEST</span><span>) +</span><span>@Retry(count = </span><span style="color:#d08770;">5</span><span>, minBackoff = &quot;</span><span style="color:#a3be8c;">1s</span><span>&quot;, catchVerb = &quot;</span><span style="color:#a3be8c;">recoverPaymentProcessing</span><span>&quot;) +</span><span style="color:#b48ead;">fun </span><span style="color:#8fa1b3;">processPayment</span><span>(payment: Payment) { +</span><span> </span><span style="color:#65737e;">// ... +</span><span>} +</span></code></pre> +<!-- java --> +<pre data-lang="java" style="background-color:#2b303b;color:#c0c5ce;" class="language-java "><code class="language-java" data-lang="java"><span>@</span><span style="color:#bf616a;">Subscription</span><span>(</span><span style="color:#bf616a;">topic </span><span>= &quot;</span><span style="color:#a3be8c;">example</span><span>&quot;, </span><span style="color:#bf616a;">name </span><span>= &quot;</span><span style="color:#a3be8c;">exampleSubscription</span><span>&quot;) +</span><span>@</span><span style="color:#bf616a;">SubscriptionOptions</span><span>(</span><span style="color:#bf616a;">from </span><span>= </span><span style="color:#ebcb8b;">FromOffset</span><span>.</span><span style="color:#d08770;">LATEST</span><span>) +</span><span>@</span><span style="color:#bf616a;">Retry</span><span>(</span><span style="color:#bf616a;">count </span><span>= </span><span style="color:#d08770;">5</span><span>, </span><span style="color:#bf616a;">minBackoff </span><span>= &quot;</span><span style="color:#a3be8c;">1s</span><span>&quot;, </span><span style="color:#bf616a;">catchVerb </span><span>= &quot;</span><span style="color:#a3be8c;">recoverPaymentProcessing</span><span>&quot;) +</span><span style="color:#b48ead;">public</span><span> void </span><span style="color:#bf616a;">processPayment</span><span>(</span><span style="color:#ebcb8b;">Payment</span><span> payment) { +</span><span> </span><span style="color:#65737e;">// ... +</span><span>} +</span></code></pre> +</div> +<h2 id="catching">Catching</h2> +<p>After all retries have failed, a catch verb can be used to safely recover.</p> +<p>These catch verbs have a request type of <code>builtin.CatchRequest&lt;Req&gt;</code> and no response type. If a catch verb returns an error, it will be retried until it succeeds so it is important to handle errors carefully.</p> +<div class="code-selector"> +<ul class="nav nav-tabs mb-2"> +</ul> +<!-- go --> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#65737e;">//ftl:retry 5 1s catch recoverPaymentProcessing +</span><span style="color:#b48ead;">func </span><span style="color:#8fa1b3;">ProcessPayment</span><span>(</span><span style="color:#bf616a;">ctx context</span><span>.</span><span style="color:#b48ead;">Context</span><span>, </span><span style="color:#bf616a;">payment </span><span style="color:#b48ead;">Payment</span><span>) </span><span style="color:#b48ead;">error </span><span>{ +</span><span>... +</span><span>} +</span><span> +</span><span style="color:#65737e;">//ftl:verb +</span><span style="color:#b48ead;">func </span><span style="color:#8fa1b3;">RecoverPaymentProcessing</span><span>(</span><span style="color:#bf616a;">ctx context</span><span>.</span><span style="color:#b48ead;">Context</span><span>, </span><span style="color:#bf616a;">request builtin</span><span>.</span><span style="color:#b48ead;">CatchRequest</span><span>[</span><span style="color:#bf616a;">Payment</span><span>]) </span><span style="color:#b48ead;">error </span><span>{ +</span><span style="color:#65737e;">// safely handle final failure of the payment +</span><span>} +</span></code></pre> +<!-- kotlin --> +<pre data-lang="kotlin" style="background-color:#2b303b;color:#c0c5ce;" class="language-kotlin "><code class="language-kotlin" data-lang="kotlin"><span> +</span><span>@Retry(count = </span><span style="color:#d08770;">5</span><span>, minBackoff = &quot;</span><span style="color:#a3be8c;">1s</span><span>&quot;, catchVerb = &quot;</span><span style="color:#a3be8c;">recoverPaymentProcessing</span><span>&quot;) +</span><span style="color:#b48ead;">fun </span><span style="color:#8fa1b3;">processPayment</span><span>(payment: Payment) { +</span><span> </span><span style="color:#65737e;">// ... +</span><span>} +</span><span> +</span><span>@Verb +</span><span style="color:#b48ead;">fun </span><span style="color:#8fa1b3;">recoverPaymentProcessing</span><span>(req: CatchRequest&lt;Payment&gt;) { +</span><span> </span><span style="color:#65737e;">// safely handle final failure of the payment +</span><span>} +</span></code></pre> +<!-- java --> +<pre data-lang="java" style="background-color:#2b303b;color:#c0c5ce;" class="language-java "><code class="language-java" data-lang="java"><span>@</span><span style="color:#bf616a;">Retry</span><span>(</span><span style="color:#bf616a;">count </span><span>= </span><span style="color:#d08770;">5</span><span>, </span><span style="color:#bf616a;">minBackoff </span><span>= &quot;</span><span style="color:#a3be8c;">1s</span><span>&quot;, </span><span style="color:#bf616a;">catchVerb </span><span>= &quot;</span><span style="color:#a3be8c;">recoverPaymentProcessing</span><span>&quot;) +</span><span style="color:#b48ead;">public</span><span> void </span><span style="color:#bf616a;">processPayment</span><span>(</span><span style="color:#ebcb8b;">Payment</span><span> payment) { +</span><span> </span><span style="color:#65737e;">// ... +</span><span>} +</span><span> +</span><span>@</span><span style="color:#bf616a;">Verb +</span><span style="color:#b48ead;">public</span><span> void </span><span style="color:#bf616a;">recoverPaymentProcessing</span><span>(</span><span style="color:#ebcb8b;">CatchRequest</span><span>&lt;</span><span style="color:#ebcb8b;">Payment</span><span>&gt; req) { +</span><span> </span><span style="color:#65737e;">// safely handle final failure of the payment +</span><span>} +</span></code></pre> +</div> + + + + + Secrets/Config + 2021-05-01T08:20:00+00:00 + 2021-05-01T08:20:00+00:00 + + + + + Unknown + + + + + + https://block.github.io/ftl/docs/reference/secretsconfig/ + + <h3 id="configuration">Configuration</h3> +<p>Configuration values are named, typed values. They are managed by the <code>ftl config</code> command-line.</p> +<div class="code-selector"> +<ul class="nav nav-tabs mb-2"> +</ul> +<!-- go --> +<p>To declare a configuration value use the following syntax:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#b48ead;">type </span><span>DefaultUser = </span><span style="color:#bf616a;">ftl</span><span>.</span><span style="color:#b48ead;">Config</span><span>[</span><span style="color:#bf616a;">Username</span><span>] +</span></code></pre> +<p>Note that the name of the configuration value as represented in the FTL schema is the lower camel case version of the type name.</p> +<p>Configuration values can be injected into FTL methods, such as <code>@Verb</code>, HTTP ingress, Cron etc. To inject a configuration value, use the following syntax:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#65737e;">//ftl:verb +</span><span style="color:#b48ead;">func </span><span style="color:#8fa1b3;">Hello</span><span>(</span><span style="color:#bf616a;">ctx context</span><span>.</span><span style="color:#b48ead;">Context</span><span>, </span><span style="color:#bf616a;">req </span><span style="color:#b48ead;">Request</span><span>, </span><span style="color:#bf616a;">defaultUser </span><span style="color:#b48ead;">DefaultUser</span><span>) </span><span style="color:#b48ead;">error </span><span>{ +</span><span> </span><span style="color:#bf616a;">username </span><span>:= </span><span style="color:#bf616a;">defaultUser</span><span>.</span><span style="color:#bf616a;">Get</span><span>(</span><span style="color:#bf616a;">ctx</span><span>) +</span><span> </span><span style="color:#65737e;">// ... +</span><span>} +</span></code></pre> +<!-- kotlin --> +<p>Configuration values can be injected into FTL methods, such as <code>@Verb</code>, HTTP ingress, Cron etc. To inject a configuration value, use the following syntax:</p> +<pre data-lang="kotlin" style="background-color:#2b303b;color:#c0c5ce;" class="language-kotlin "><code class="language-kotlin" data-lang="kotlin"><span>@Export +</span><span>@Verb +</span><span style="color:#b48ead;">fun </span><span style="color:#8fa1b3;">hello</span><span>(helloRequest: HelloRequest, @Config(&quot;defaultUser&quot;) defaultUser: </span><span style="color:#b48ead;">String</span><span>): HelloResponse { +</span><span> </span><span style="color:#b48ead;">return</span><span> HelloResponse(&quot;</span><span style="color:#a3be8c;">Hello, </span><span style="color:#bf616a;">$defaultUser</span><span>&quot;) +</span><span>} +</span></code></pre> +<!-- java --> +<p>Configuration values can be injected into FTL methods, such as <code>@Verb</code>, HTTP ingress, Cron etc. To inject a configuration value, use the following syntax:</p> +<pre data-lang="java" style="background-color:#2b303b;color:#c0c5ce;" class="language-java "><code class="language-java" data-lang="java"><span>@</span><span style="color:#bf616a;">Export +</span><span>@</span><span style="color:#bf616a;">Verb +</span><span style="color:#ebcb8b;">HelloResponse </span><span style="color:#bf616a;">hello</span><span>(</span><span style="color:#ebcb8b;">HelloRequest</span><span> helloRequest, @</span><span style="color:#bf616a;">Config</span><span>(&quot;</span><span style="color:#a3be8c;">defaultUser</span><span>&quot;) </span><span style="color:#ebcb8b;">String</span><span> defaultUser) { +</span><span> </span><span style="color:#b48ead;">return new </span><span style="color:#ebcb8b;">HelloResponse</span><span>(&quot;</span><span style="color:#a3be8c;">Hello, </span><span>&quot; + defaultUser); +</span><span>} +</span></code></pre> +</div> +<h3 id="secrets">Secrets</h3> +<p>Secrets are encrypted, named, typed values. They are managed by the <code>ftl secret</code> command-line.</p> +<div class="code-selector"> +<ul class="nav nav-tabs mb-2"> +</ul> +<!-- go --> +<p>Declare a secret with the following:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#b48ead;">type </span><span>ApiKey = </span><span style="color:#bf616a;">ftl</span><span>.</span><span style="color:#b48ead;">Secret</span><span>[</span><span style="color:#bf616a;">Credentials</span><span>] +</span></code></pre> +<p>Like configuration values, the name of the secret as represented in the FTL schema is the lower camel case version of the type name.</p> +<p>Configuration values can be injected into FTL methods, such as <code>@Verb</code>, HTTP ingress, Cron etc. To inject a configuration value, use the following syntax:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#65737e;">//ftl:verb +</span><span style="color:#b48ead;">func </span><span style="color:#8fa1b3;">CallApi</span><span>(</span><span style="color:#bf616a;">ctx context</span><span>.</span><span style="color:#b48ead;">Context</span><span>, </span><span style="color:#bf616a;">req </span><span style="color:#b48ead;">Request</span><span>, </span><span style="color:#bf616a;">apiKey </span><span style="color:#b48ead;">ApiKey</span><span>) </span><span style="color:#b48ead;">error </span><span>{ +</span><span> </span><span style="color:#bf616a;">credentials </span><span>:= </span><span style="color:#bf616a;">apiKey</span><span>.</span><span style="color:#bf616a;">Get</span><span>(</span><span style="color:#bf616a;">ctx</span><span>) +</span><span> </span><span style="color:#65737e;">// ... +</span><span>} +</span></code></pre> +<!-- kotlin --> +<p>Configuration values can be injected into FTL methods, such as <code>@Verb</code>, HTTP ingress, Cron etc. To inject a configuration value, use the following syntax:</p> +<pre data-lang="kotlin" style="background-color:#2b303b;color:#c0c5ce;" class="language-kotlin "><code class="language-kotlin" data-lang="kotlin"><span>@Export +</span><span>@Verb +</span><span style="color:#b48ead;">fun </span><span style="color:#8fa1b3;">hello</span><span>(helloRequest: HelloRequest, @Secret(&quot;apiKey&quot;) apiKey: </span><span style="color:#b48ead;">String</span><span>): HelloResponse { +</span><span> </span><span style="color:#b48ead;">return</span><span> HelloResponse(&quot;</span><span style="color:#a3be8c;">Hello, </span><span style="color:#bf616a;">${api.call(apiKey)}</span><span>&quot;) +</span><span>} +</span></code></pre> +<!-- java --> +<p>Configuration values can be injected into FTL methods, such as <code>@Verb</code>, HTTP ingress, Cron etc. To inject a configuration value, use the following syntax:</p> +<pre data-lang="java" style="background-color:#2b303b;color:#c0c5ce;" class="language-java "><code class="language-java" data-lang="java"><span>@</span><span style="color:#bf616a;">Export +</span><span>@</span><span style="color:#bf616a;">Verb +</span><span style="color:#ebcb8b;">HelloResponse </span><span style="color:#bf616a;">hello</span><span>(</span><span style="color:#ebcb8b;">HelloRequest</span><span> helloRequest, @</span><span style="color:#bf616a;">Secret</span><span>(&quot;</span><span style="color:#a3be8c;">apiKey</span><span>&quot;) </span><span style="color:#ebcb8b;">String</span><span> apiKey) { +</span><span> </span><span style="color:#b48ead;">return new </span><span style="color:#ebcb8b;">HelloResponse</span><span>(&quot;</span><span style="color:#a3be8c;">Hello, </span><span>&quot; + api.</span><span style="color:#bf616a;">call</span><span>(apiKey)); +</span><span>} +</span></code></pre> +</div> +<h3 id="transforming-secrets-configuration">Transforming secrets/configuration</h3> +<p>Often, raw secret/configuration values aren't directly useful. For example, raw credentials might be used to create an API client. For those situations <code>ftl.Map()</code> can be used to transform a configuration or secret value into another type:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#b48ead;">var </span><span style="color:#bf616a;">client </span><span>= </span><span style="color:#bf616a;">ftl</span><span>.</span><span style="color:#bf616a;">Map</span><span>(</span><span style="color:#bf616a;">ftl</span><span>.</span><span style="color:#bf616a;">Secret</span><span>[</span><span style="color:#bf616a;">Credentials</span><span>](&quot;</span><span style="color:#a3be8c;">credentials</span><span>&quot;), +</span><span> </span><span style="color:#b48ead;">func</span><span>(</span><span style="color:#bf616a;">ctx context</span><span>.</span><span style="color:#b48ead;">Context</span><span>, </span><span style="color:#bf616a;">creds </span><span style="color:#b48ead;">Credentials</span><span>) (*</span><span style="color:#bf616a;">api</span><span>.</span><span style="color:#b48ead;">Client</span><span>, </span><span style="color:#b48ead;">error</span><span>) { +</span><span> </span><span style="color:#b48ead;">return </span><span style="color:#bf616a;">api</span><span>.</span><span style="color:#bf616a;">NewClient</span><span>(</span><span style="color:#bf616a;">creds</span><span>) +</span><span>}) +</span></code></pre> +<p>This is not currently supported in Kotlin or Java.</p> + + + + + Start + 2021-05-01T08:20:00+00:00 + 2021-05-01T08:20:00+00:00 + + + + + Unknown + + + + + + https://block.github.io/ftl/docs/reference/start/ + + <h2 id="import-the-runtime">Import the runtime</h2> +<div class="code-selector"> +<ul class="nav nav-tabs mb-2"> +</ul> +<!-- go --> +<p>Some aspects of FTL rely on a runtime which must be imported with:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#b48ead;">import </span><span>&quot;</span><span style="color:#a3be8c;">github.com/block/ftl/go-runtime/ftl</span><span>&quot; +</span></code></pre> +<!-- kotlin --> +<p>The easiest way to get started with Kotlin is to use the <code>ftl-build-parent-kotlin</code> parent POM. This will automatically include the FTL runtime as a dependency, and setup all required plugins:</p> +<pre data-lang="xml" style="background-color:#2b303b;color:#c0c5ce;" class="language-xml "><code class="language-xml" data-lang="xml"><span>&lt;?</span><span style="color:#bf616a;">xml </span><span style="color:#d08770;">version</span><span>=&quot;</span><span style="color:#a3be8c;">1.0</span><span>&quot; </span><span style="color:#d08770;">encoding</span><span>=&quot;</span><span style="color:#a3be8c;">UTF-8</span><span>&quot;?&gt; +</span><span>&lt;</span><span style="color:#bf616a;">project </span><span style="color:#d08770;">xmlns</span><span>=&quot;</span><span style="color:#a3be8c;">http://maven.apache.org/POM/4.0.0</span><span>&quot; </span><span style="color:#d08770;">xmlns:xsi</span><span>=&quot;</span><span style="color:#a3be8c;">http://www.w3.org/2001/XMLSchema-instance</span><span>&quot; </span><span style="color:#d08770;">xsi:schemaLocation</span><span>=&quot;</span><span style="color:#a3be8c;">http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd</span><span>&quot;&gt; +</span><span> &lt;</span><span style="color:#bf616a;">modelVersion</span><span>&gt;4.0.0&lt;/</span><span style="color:#bf616a;">modelVersion</span><span>&gt; +</span><span> &lt;</span><span style="color:#bf616a;">groupId</span><span>&gt;com.myproject&lt;/</span><span style="color:#bf616a;">groupId</span><span>&gt; +</span><span> &lt;</span><span style="color:#bf616a;">artifactId</span><span>&gt;myproject&lt;/</span><span style="color:#bf616a;">artifactId</span><span>&gt; +</span><span> &lt;</span><span style="color:#bf616a;">version</span><span>&gt;1.0-SNAPSHOT&lt;/</span><span style="color:#bf616a;">version</span><span>&gt; +</span><span> +</span><span> &lt;</span><span style="color:#bf616a;">parent</span><span>&gt; +</span><span> &lt;</span><span style="color:#bf616a;">groupId</span><span>&gt;xyz.block.ftl&lt;/</span><span style="color:#bf616a;">groupId</span><span>&gt; +</span><span> &lt;</span><span style="color:#bf616a;">artifactId</span><span>&gt;ftl-build-parent-kotlin&lt;/</span><span style="color:#bf616a;">artifactId</span><span>&gt; +</span><span> &lt;</span><span style="color:#bf616a;">version</span><span>&gt;${ftl.version}&lt;/</span><span style="color:#bf616a;">version</span><span>&gt; +</span><span> &lt;/</span><span style="color:#bf616a;">parent</span><span>&gt; +</span><span> +</span><span>&lt;/</span><span style="color:#bf616a;">project</span><span>&gt; +</span></code></pre> +<p>If you do not want to use a parent pom then you can copy the plugins and dependencies from the parent pom into your own pom.</p> +<!-- java --> +<p>The easiest way to get started with Java is to use the <code>ftl-build-parent-java</code> parent POM. This will automatically include the FTL runtime as a dependency, and setup all required plugins:</p> +<pre data-lang="xml" style="background-color:#2b303b;color:#c0c5ce;" class="language-xml "><code class="language-xml" data-lang="xml"><span>&lt;?</span><span style="color:#bf616a;">xml </span><span style="color:#d08770;">version</span><span>=&quot;</span><span style="color:#a3be8c;">1.0</span><span>&quot; </span><span style="color:#d08770;">encoding</span><span>=&quot;</span><span style="color:#a3be8c;">UTF-8</span><span>&quot;?&gt; +</span><span>&lt;</span><span style="color:#bf616a;">project </span><span style="color:#d08770;">xmlns</span><span>=&quot;</span><span style="color:#a3be8c;">http://maven.apache.org/POM/4.0.0</span><span>&quot; </span><span style="color:#d08770;">xmlns:xsi</span><span>=&quot;</span><span style="color:#a3be8c;">http://www.w3.org/2001/XMLSchema-instance</span><span>&quot; </span><span style="color:#d08770;">xsi:schemaLocation</span><span>=&quot;</span><span style="color:#a3be8c;">http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd</span><span>&quot;&gt; +</span><span> &lt;</span><span style="color:#bf616a;">modelVersion</span><span>&gt;4.0.0&lt;/</span><span style="color:#bf616a;">modelVersion</span><span>&gt; +</span><span> &lt;</span><span style="color:#bf616a;">groupId</span><span>&gt;com.myproject&lt;/</span><span style="color:#bf616a;">groupId</span><span>&gt; +</span><span> &lt;</span><span style="color:#bf616a;">artifactId</span><span>&gt;myproject&lt;/</span><span style="color:#bf616a;">artifactId</span><span>&gt; +</span><span> &lt;</span><span style="color:#bf616a;">version</span><span>&gt;1.0-SNAPSHOT&lt;/</span><span style="color:#bf616a;">version</span><span>&gt; +</span><span> +</span><span> &lt;</span><span style="color:#bf616a;">parent</span><span>&gt; +</span><span> &lt;</span><span style="color:#bf616a;">groupId</span><span>&gt;xyz.block.ftl&lt;/</span><span style="color:#bf616a;">groupId</span><span>&gt; +</span><span> &lt;</span><span style="color:#bf616a;">artifactId</span><span>&gt;ftl-build-parent-java&lt;/</span><span style="color:#bf616a;">artifactId</span><span>&gt; +</span><span> &lt;</span><span style="color:#bf616a;">version</span><span>&gt;${ftl.version}&lt;/</span><span style="color:#bf616a;">version</span><span>&gt; +</span><span> &lt;/</span><span style="color:#bf616a;">parent</span><span>&gt; +</span><span> +</span><span>&lt;/</span><span style="color:#bf616a;">project</span><span>&gt; +</span></code></pre> +<p>If you do not want to use a parent pom then you can copy the plugins and dependencies from the parent pom into your own pom.</p> +</div> + + + + + Types + 2021-05-01T08:20:00+00:00 + 2021-05-01T08:20:00+00:00 + + + + + Unknown + + + + + + https://block.github.io/ftl/docs/reference/types/ + + <p>FTL supports the following types: <code>Int</code> (64-bit), <code>Float</code> (64-bit), <code>String</code>, <code>Bytes</code> (a byte array), <code>Bool</code>, <code>Time</code>, <code>Any</code> (a dynamic type), <code>Unit</code> (similar to "void"), arrays, maps, data structures, and constant enumerations. Each FTL type is mapped to a corresponding language-specific type. For example in Go <code>Float</code> is represented as <code>float64</code>, <code>Time</code> is represented by <code>time.Time</code>, and so on. [^1]</p> +<p>Any Go type supported by FTL and referenced by an FTL declaration will be automatically exposed to an FTL type.</p> +<p>For example, the following verb declaration will result in <code>Request</code> and <code>Response</code> being automatically translated to FTL types.</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#b48ead;">type </span><span>Request </span><span style="color:#b48ead;">struct </span><span>{} +</span><span style="color:#b48ead;">type </span><span>Response </span><span style="color:#b48ead;">struct </span><span>{} +</span><span> +</span><span style="color:#65737e;">//ftl:verb +</span><span style="color:#b48ead;">func </span><span style="color:#8fa1b3;">Hello</span><span>(</span><span style="color:#bf616a;">ctx context</span><span>.</span><span style="color:#b48ead;">Context</span><span>, </span><span style="color:#bf616a;">in </span><span style="color:#b48ead;">Request</span><span>) (</span><span style="color:#b48ead;">Response</span><span>, </span><span style="color:#b48ead;">error</span><span>) { +</span><span> </span><span style="color:#65737e;">// ... +</span><span>} +</span></code></pre> +<h2 id="type-enums-sum-types">Type enums (sum types)</h2> +<p><a href="https://en.wikipedia.org/wiki/Tagged_union">Sum types</a> are supported by FTL's type system, but aren't directly supported by Go. However they can be approximated with the use of <a href="https://blog.chewxy.com/2018/03/18/golang-interfaces/">sealed interfaces</a>. To declare a sum type in FTL use the comment directive <code>//ftl:enum</code>:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#65737e;">//ftl:enum +</span><span style="color:#b48ead;">type </span><span>Animal </span><span style="color:#b48ead;">interface </span><span>{ </span><span style="color:#8fa1b3;">animal</span><span>() } +</span><span> +</span><span style="color:#b48ead;">type </span><span>Cat </span><span style="color:#b48ead;">struct </span><span>{} +</span><span style="color:#b48ead;">func </span><span>(</span><span style="color:#b48ead;">Cat</span><span>) </span><span style="color:#8fa1b3;">animal</span><span>() {} +</span><span> +</span><span style="color:#b48ead;">type </span><span>Dog </span><span style="color:#b48ead;">struct </span><span>{} +</span><span style="color:#b48ead;">func </span><span>(</span><span style="color:#b48ead;">Dog</span><span>) </span><span style="color:#8fa1b3;">animal</span><span>() {} +</span></code></pre> +<h2 id="value-enums">Value enums</h2> +<p>A value enum is an enumerated set of string or integer values.</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#65737e;">//ftl:enum +</span><span style="color:#b48ead;">type </span><span>Colour </span><span style="color:#b48ead;">string +</span><span> +</span><span style="color:#b48ead;">const </span><span>( +</span><span> </span><span style="color:#bf616a;">Red </span><span style="color:#b48ead;">Colour </span><span>= &quot;</span><span style="color:#a3be8c;">red</span><span>&quot; +</span><span> </span><span style="color:#bf616a;">Green </span><span style="color:#b48ead;">Colour </span><span>= &quot;</span><span style="color:#a3be8c;">green</span><span>&quot; +</span><span> </span><span style="color:#bf616a;">Blue </span><span style="color:#b48ead;">Colour </span><span>= &quot;</span><span style="color:#a3be8c;">blue</span><span>&quot; +</span><span>) +</span></code></pre> +<h2 id="type-aliases">Type aliases</h2> +<p>A type alias is an alternate name for an existing type. It can be declared like so:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#65737e;">//ftl:typealias +</span><span style="color:#b48ead;">type </span><span>Alias </span><span style="color:#b48ead;">Target +</span></code></pre> +<p>or</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#65737e;">//ftl:typealias +</span><span style="color:#b48ead;">type </span><span>Alias = </span><span style="color:#b48ead;">Target +</span></code></pre> +<p>eg.</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#65737e;">//ftl:typealias +</span><span style="color:#b48ead;">type </span><span>UserID </span><span style="color:#b48ead;">string +</span><span> +</span><span style="color:#65737e;">//ftl:typealias +</span><span style="color:#b48ead;">type </span><span>UserToken = </span><span style="color:#b48ead;">string +</span></code></pre> +<hr /> +<h2 id="optional-types">Optional types</h2> +<p>FTL supports optional types, which are types that can be <code>None</code> or <code>Some</code> and can be declared via <code>ftl.Option[T]</code>. These types are provided by the <code>ftl</code> runtimes. For example, the following FTL type declaration in go, will provide an optional string type "Name":</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#b48ead;">type </span><span>EchoResponse </span><span style="color:#b48ead;">struct </span><span>{ +</span><span> </span><span style="color:#bf616a;">Name ftl</span><span>.</span><span style="color:#b48ead;">Option</span><span>[</span><span style="color:#bf616a;">string</span><span>] `</span><span style="color:#a3be8c;">json:&quot;name&quot;</span><span>` +</span><span>} +</span></code></pre> +<p>The value of this type can be set to <code>Some</code> or <code>None</code>:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#bf616a;">resp </span><span>:= </span><span style="color:#bf616a;">EchoResponse</span><span>{ +</span><span> </span><span style="color:#bf616a;">Name</span><span>: </span><span style="color:#bf616a;">ftl</span><span>.</span><span style="color:#bf616a;">Some</span><span>(&quot;</span><span style="color:#a3be8c;">John</span><span>&quot;), +</span><span>} +</span><span> +</span><span style="color:#bf616a;">resp </span><span>:= </span><span style="color:#bf616a;">EchoResponse</span><span>{ +</span><span> </span><span style="color:#bf616a;">Name</span><span>: </span><span style="color:#bf616a;">ftl</span><span>.</span><span style="color:#bf616a;">None</span><span>(), +</span><span>} +</span></code></pre> +<p>The value of the optional type can be accessed using <code>Get</code>, <code>MustGet</code>, or <code>Default</code> methods:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#65737e;">// Get returns the value and a boolean indicating if the Option contains a value. +</span><span style="color:#b48ead;">if </span><span style="color:#bf616a;">value</span><span>, </span><span style="color:#bf616a;">ok </span><span>:= </span><span style="color:#bf616a;">resp</span><span>.</span><span style="color:#bf616a;">Name</span><span>.</span><span style="color:#bf616a;">Get</span><span>(); </span><span style="color:#bf616a;">ok </span><span>{ +</span><span> </span><span style="color:#bf616a;">resp</span><span>.</span><span style="color:#bf616a;">Name </span><span>= </span><span style="color:#bf616a;">ftl</span><span>.</span><span style="color:#bf616a;">Some</span><span>(</span><span style="color:#bf616a;">value</span><span>) +</span><span>} +</span><span> +</span><span style="color:#65737e;">// MustGet returns the value or panics if the Option is None. +</span><span style="color:#bf616a;">value </span><span>:= </span><span style="color:#bf616a;">resp</span><span>.</span><span style="color:#bf616a;">Name</span><span>.</span><span style="color:#bf616a;">MustGet</span><span>() +</span><span> +</span><span style="color:#65737e;">// Default returns the value or a default value if the Option is None. +</span><span style="color:#bf616a;">value </span><span>:= </span><span style="color:#bf616a;">resp</span><span>.</span><span style="color:#bf616a;">Name</span><span>.</span><span style="color:#bf616a;">Default</span><span>(&quot;</span><span style="color:#a3be8c;">default</span><span>&quot;) +</span></code></pre> +<h2 id="unit-void-type">Unit "void" type</h2> +<p>The <code>Unit</code> type is similar to the <code>void</code> type in other languages. It is used to indicate that a function does not return a value. For example:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#65737e;">//ftl:ingress GET /unit +</span><span style="color:#b48ead;">func </span><span style="color:#8fa1b3;">Unit</span><span>(</span><span style="color:#bf616a;">ctx context</span><span>.</span><span style="color:#b48ead;">Context</span><span>, </span><span style="color:#bf616a;">req builtin</span><span>.</span><span style="color:#b48ead;">HttpRequest</span><span>[</span><span style="color:#bf616a;">ftl</span><span>.</span><span style="color:#bf616a;">Unit</span><span>, </span><span style="color:#bf616a;">ftl</span><span>.</span><span style="color:#bf616a;">Unit</span><span>, </span><span style="color:#bf616a;">TimeRequest</span><span>]) (</span><span style="color:#bf616a;">builtin</span><span>.</span><span style="color:#b48ead;">HttpResponse</span><span>[</span><span style="color:#bf616a;">ftl</span><span>.</span><span style="color:#bf616a;">Unit</span><span>, </span><span style="color:#bf616a;">string</span><span>], </span><span style="color:#b48ead;">error</span><span>) { +</span><span> </span><span style="color:#b48ead;">return </span><span style="color:#bf616a;">builtin</span><span>.</span><span style="color:#bf616a;">HttpResponse</span><span>[</span><span style="color:#bf616a;">ftl</span><span>.</span><span style="color:#bf616a;">Unit</span><span>, </span><span style="color:#bf616a;">string</span><span>]{</span><span style="color:#bf616a;">Body</span><span>: </span><span style="color:#bf616a;">ftl</span><span>.</span><span style="color:#bf616a;">Some</span><span>(</span><span style="color:#bf616a;">ftl</span><span>.</span><span style="color:#bf616a;">Unit</span><span>{})}, </span><span style="color:#d08770;">nil +</span><span>} +</span></code></pre> +<p>This request will return an empty body with a status code of 200:</p> +<pre data-lang="sh" style="background-color:#2b303b;color:#c0c5ce;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#bf616a;">curl</span><span> http://localhost:8891/unit</span><span style="color:#bf616a;"> -i +</span></code></pre> +<pre data-lang="http" style="background-color:#2b303b;color:#c0c5ce;" class="language-http "><code class="language-http" data-lang="http"><span>HTTP/1.1 200 OK +</span><span>Date: Mon, 12 Aug 2024 17:58:22 GMT +</span><span>Content-Length: 0 +</span></code></pre> +<h2 id="builtin-types">Builtin types</h2> +<p>FTL provides a set of builtin types that are automatically available in all FTL runtimes. These types are:</p> +<ul> +<li><code>builtin.HttpRequest[Body, PathParams, QueryParams]</code> - Represents an HTTP request with a body of type <code>Body</code>, path parameter type of <code>PathParams</code> and a query parameter type of <code>QueryParams</code>.</li> +<li><code>builtin.HttpResponse[Body, Error]</code> - Represents an HTTP response with a body of type <code>Body</code> and an error of type <code>Error</code>.</li> +<li><code>builtin.Empty</code> - Represents an empty type. This equates to an empty structure <code>{}</code>.</li> +<li><code>builtin.CatchRequest</code> - Represents a request structure for catch verbs.</li> +</ul> + + + + + Verbs + 2021-05-01T08:20:00+00:00 + 2021-05-01T08:20:00+00:00 + + + + + Unknown + + + + + + https://block.github.io/ftl/docs/reference/verbs/ + + <h2 id="defining-verbs">Defining Verbs</h2> +<div class="code-selector"> +<ul class="nav nav-tabs mb-2"> +</ul> +<!-- go --> +<p>To declare a Verb, write a normal Go function with the following signature, annotated with the Go <a href="https://tip.golang.org/doc/comment#syntax">comment directive</a> <code>//ftl:verb</code>:</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#65737e;">//ftl:verb +</span><span style="color:#b48ead;">func </span><span style="color:#8fa1b3;">F</span><span>(</span><span style="color:#bf616a;">context</span><span>.</span><span style="color:#b48ead;">Context</span><span>, </span><span style="color:#b48ead;">In</span><span>) (</span><span style="color:#b48ead;">Out</span><span>, </span><span style="color:#b48ead;">error</span><span>) { } +</span></code></pre> +<p>eg.</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#b48ead;">type </span><span>EchoRequest </span><span style="color:#b48ead;">struct </span><span>{} +</span><span> +</span><span style="color:#b48ead;">type </span><span>EchoResponse </span><span style="color:#b48ead;">struct </span><span>{} +</span><span> +</span><span style="color:#65737e;">//ftl:verb +</span><span style="color:#b48ead;">func </span><span style="color:#8fa1b3;">Echo</span><span>(</span><span style="color:#bf616a;">ctx context</span><span>.</span><span style="color:#b48ead;">Context</span><span>, </span><span style="color:#bf616a;">in </span><span style="color:#b48ead;">EchoRequest</span><span>) (</span><span style="color:#b48ead;">EchoResponse</span><span>, </span><span style="color:#b48ead;">error</span><span>) { +</span><span> </span><span style="color:#65737e;">// ... +</span><span>} +</span></code></pre> +<!-- kotlin --> +<p>To declare a Verb, write a normal Kotlin function with the following signature, annotated with the Kotlin <a href="https://kotlinlang.org/docs/annotations.html">annotation</a> <code>@Verb</code>:</p> +<pre data-lang="kotlin" style="background-color:#2b303b;color:#c0c5ce;" class="language-kotlin "><code class="language-kotlin" data-lang="kotlin"><span>@Verb +</span><span style="color:#b48ead;">fun </span><span style="color:#8fa1b3;">F</span><span>(In): Out { } +</span></code></pre> +<p>eg.</p> +<pre data-lang="kotlin" style="background-color:#2b303b;color:#c0c5ce;" class="language-kotlin "><code class="language-kotlin" data-lang="kotlin"><span style="color:#b48ead;">data class </span><span style="color:#ebcb8b;">EchoRequest +</span><span style="color:#b48ead;">data class </span><span style="color:#ebcb8b;">EchoResponse +</span><span> +</span><span>@Verb +</span><span style="color:#b48ead;">fun </span><span style="color:#8fa1b3;">echo</span><span>(request: EchoRequest): EchoResponse { +</span><span> </span><span style="color:#65737e;">// ... +</span><span>} +</span></code></pre> +</div> +<p>By default verbs are only <a href="../visibility">visible</a> to other verbs in the same module.</p> +<h2 id="calling-verbs">Calling Verbs</h2> +<div class="code-selector"> +<ul class="nav nav-tabs mb-2"> +</ul> +<!-- go --> +<p>To call a verb, import the module's verb client (<code>{ModuleName}.{VerbName}Client</code>), add it to your verb's signature, then invoke it as a function. eg.</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#65737e;">//ftl:verb +</span><span style="color:#b48ead;">func </span><span style="color:#8fa1b3;">Echo</span><span>(</span><span style="color:#bf616a;">ctx context</span><span>.</span><span style="color:#b48ead;">Context</span><span>, </span><span style="color:#bf616a;">in </span><span style="color:#b48ead;">EchoRequest</span><span>, </span><span style="color:#bf616a;">tc time</span><span>.</span><span style="color:#b48ead;">TimeClient</span><span>) (</span><span style="color:#b48ead;">EchoResponse</span><span>, </span><span style="color:#b48ead;">error</span><span>) { +</span><span> </span><span style="color:#bf616a;">out</span><span>, </span><span style="color:#bf616a;">err </span><span>:= </span><span style="color:#bf616a;">tc</span><span>(</span><span style="color:#bf616a;">ctx</span><span>, </span><span style="color:#bf616a;">TimeRequest</span><span>{...}) +</span><span>} +</span></code></pre> +<p>Verb clients are generated by FTL. If the callee verb belongs to the same module as the caller, you must build the +module first (with callee verb defined) in order to generate its client for use by the caller. Local verb clients are +available in the generated <code>types.ftl.go</code> file as <code>{VerbName}Client</code>.</p> +<!-- kotlin --> +<p>To call a verb, import the module's verb client, add it to your verb's signature, then <code>call()</code> it. eg.</p> +<pre data-lang="kotlin" style="background-color:#2b303b;color:#c0c5ce;" class="language-kotlin "><code class="language-kotlin" data-lang="kotlin"><span style="color:#b48ead;">import</span><span> ftl.time.TimeClient +</span><span> +</span><span>@Verb +</span><span style="color:#b48ead;">fun </span><span style="color:#8fa1b3;">echo</span><span>(req: EchoRequest, time: TimeClient): EchoResponse { +</span><span> </span><span style="color:#b48ead;">val </span><span>response = time.call() +</span><span> </span><span style="color:#65737e;">// ... +</span><span>} +</span><span> +</span><span style="color:#b48ead;">val </span><span>response = time.call() +</span></code></pre> +<p>Verb clients are generated by FTL. If the callee verb belongs to the same module as the caller, you must manually define your +own client:</p> +<pre data-lang="kotlin" style="background-color:#2b303b;color:#c0c5ce;" class="language-kotlin "><code class="language-kotlin" data-lang="kotlin"><span>@VerbClient(name=&quot;</span><span style="color:#a3be8c;">time</span><span>&quot;) +</span><span style="color:#b48ead;">interface </span><span style="color:#ebcb8b;">TimeClient</span><span> { +</span><span> </span><span style="color:#b48ead;">fun </span><span style="color:#8fa1b3;">call</span><span>(): TimeResponse +</span><span>} +</span></code></pre> +</div> + + + + + Visibility + 2021-05-01T08:20:00+00:00 + 2021-05-01T08:20:00+00:00 + + + + + Unknown + + + + + + https://block.github.io/ftl/docs/reference/visibility/ + + <p>By default all declarations in FTL are visible only to the module they're declared in. The implicit visibility of types is that of the first verb or other declaration that references it.</p> +<h2 id="exporting-declarations">Exporting declarations</h2> +<p>Exporting a declaration makes it accessible to other modules. Some declarations that are entirely local to a module, such as secrets/config, cannot be exported.</p> +<p>Types that are transitively referenced by an exported declaration will be automatically exported unless they were already defined but unexported. In this case, an error will be raised and the type must be explicitly exported.</p> +<div class="code-selector"> +<ul class="nav nav-tabs mb-2"> +</ul> +<!-- go --> +<p>The following table describes the go directives used to export the corresponding declaration:</p> +<table><thead><tr><th>Symbol</th><th>Export syntax</th></tr></thead><tbody> +<tr><td>Verb</td><td><code>//ftl:verb export</code></td></tr> +<tr><td>Data</td><td><code>//ftl:data export</code></td></tr> +<tr><td>Enum/Sum type</td><td><code>//ftl:enum export</code></td></tr> +<tr><td>Typealias</td><td><code>//ftl:typealias export</code></td></tr> +<tr><td>Topic</td><td><code>//ftl:export</code> <sup class="footnote-reference"><a href="#1">1</a></sup></td></tr> +</tbody></table> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#65737e;">//ftl:verb export +</span><span style="color:#b48ead;">func </span><span style="color:#8fa1b3;">Verb</span><span>(</span><span style="color:#bf616a;">ctx context</span><span>.</span><span style="color:#b48ead;">Context</span><span>, </span><span style="color:#bf616a;">in </span><span style="color:#b48ead;">In</span><span>) (</span><span style="color:#b48ead;">Out</span><span>, </span><span style="color:#b48ead;">error</span><span>) +</span><span> +</span><span style="color:#65737e;">//ftl:typealias export +</span><span style="color:#b48ead;">type </span><span>UserID </span><span style="color:#b48ead;">string +</span></code></pre> +<div class="footnote-definition" id="1"><sup class="footnote-definition-label">1</sup> +<p>By default, topics do not require any annotations as the declaration itself is sufficient.</p> +</div> +<!-- kotlin --> +<p>For Kotlin the <code>@Export</code> annotation can be used to export a declaration:</p> +<pre data-lang="kotlin" style="background-color:#2b303b;color:#c0c5ce;" class="language-kotlin "><code class="language-kotlin" data-lang="kotlin"><span>@Verb +</span><span>@Export +</span><span style="color:#b48ead;">fun </span><span style="color:#8fa1b3;">time</span><span>(): TimeResponse { +</span><span> </span><span style="color:#65737e;">// ... +</span><span>} +</span></code></pre> +<!-- java --> +<p>For Java the <code>@Export</code> annotation can be used to export a declaration:</p> +<pre data-lang="java" style="background-color:#2b303b;color:#c0c5ce;" class="language-java "><code class="language-java" data-lang="java"><span>@</span><span style="color:#bf616a;">Verb +</span><span>@</span><span style="color:#bf616a;">Export +</span><span style="color:#ebcb8b;">TimeResponse </span><span style="color:#bf616a;">time</span><span>() { +</span><span> </span><span style="color:#65737e;">// ... +</span><span>} +</span></code></pre> +</div> + + + + + Introduction + 2021-05-01T08:00:00+00:00 + 2021-05-01T08:00:00+00:00 + + + + + Unknown + + + + + + https://block.github.io/ftl/docs/getting-started/introduction/ + + <p>FTL is tooling, runtimes, and frameworks for simplifying the creation of distributed systems.</p> + + + + + Metrics + 2021-05-01T08:00:00+00:00 + 2021-05-01T08:00:00+00:00 + + + + + Unknown + + + + + + https://block.github.io/ftl/docs/observability/metrics/ + + <p>FTL collects and exports a variety of metrics to help you monitor and understand the behavior of your FTL deployment using OTEL. This allows cluster operators to consume metrics in their preferred monitoring system e.g. Prometheus, Grafana, Datadog etc.</p> +<p><strong>Note on Metric Types:</strong></p> +<ul> +<li><strong>Counters</strong> typically have a <code>_total</code> suffix in Prometheus, which is omitted here for brevity.</li> +<li><strong>Histograms</strong> typically have <code>_bucket</code>, <code>_sum</code>, and <code>_count</code> variants, with <code>_bucket</code> including multiple entries for different bucket boundaries.</li> +<li><strong>Gauges</strong> represent a single numerical value that can go up and down.</li> +</ul> +<p><em>Note: this documentation is incomplete</em></p> +<h2 id="ftl-metrics">FTL Metrics</h2> +<h3 id="metrics-table">Metrics Table</h3> +<table><thead><tr><th>Metric Name</th><th>Type</th><th>Description</th></tr></thead><tbody> +<tr><td><code>ftl.async_call.acquired</code></td><td>Counter</td><td>Number of times an async call was acquired</td></tr> +<tr><td><code>ftl.async_call.completed</code></td><td>Counter</td><td>Number of completed async calls</td></tr> +<tr><td><code>ftl.async_call.created</code></td><td>Counter</td><td>Number of created async calls</td></tr> +<tr><td><code>ftl.async_call.executed</code></td><td>Counter</td><td>Number of executed async calls</td></tr> +<tr><td><code>ftl.async_call.ms_to_complete</code></td><td>Histogram</td><td>Time taken to complete async calls in milliseconds</td></tr> +<tr><td><code>ftl.async_call.queue_depth_ratio</code></td><td>Gauge</td><td>Ratio of queued async calls</td></tr> +<tr><td><code>ftl.call.ms_to_complete</code></td><td>Histogram</td><td>Time taken to complete calls in milliseconds</td></tr> +<tr><td><code>ftl.call.requests</code></td><td>Counter</td><td>Total number of call requests</td></tr> +<tr><td><code>ftl.deployments.runner.active</code></td><td>Gauge</td><td>Number of active deployment runners</td></tr> +<tr><td><code>ftl.runner.registration.heartbeats</code></td><td>Counter</td><td>Total number of runner registration heartbeats</td></tr> +<tr><td><code>ftl.timeline.inserted</code></td><td>Counter</td><td>Total number of timeline insertions</td></tr> +</tbody></table> +<h3 id="attributes">Attributes</h3> +<p>Attributes provide additional context and dimensions for metrics and are often used for analysis and filtering. Each section below represents an attribute key that is collected for a specific set of metrics.</p> +<h4 id="ftl-async-call-catching">ftl.async_call.catching</h4> +<ul> +<li><code>ftl.async_call.acquired</code></li> +<li><code>ftl.async_call.completed</code></li> +<li><code>ftl.async_call.created</code></li> +<li><code>ftl.async_call.executed</code></li> +<li><code>ftl.async_call.ms_to_complete</code></li> +</ul> +<h4 id="ftl-async-call-origin">ftl.async_call.origin</h4> +<ul> +<li><code>ftl.async_call.acquired</code></li> +<li><code>ftl.async_call.completed</code></li> +<li><code>ftl.async_call.created</code></li> +<li><code>ftl.async_call.executed</code></li> +<li><code>ftl.async_call.ms_to_complete</code></li> +</ul> +<h4 id="ftl-async-call-time-since-scheduled-at-ms-bucket">ftl.async_call.time_since_scheduled_at_ms.bucket</h4> +<ul> +<li><code>ftl.async_call.acquired</code></li> +<li><code>ftl.async_call.completed</code></li> +<li><code>ftl.async_call.executed</code></li> +</ul> +<h4 id="ftl-async-call-verb-ref">ftl.async_call.verb.ref</h4> +<ul> +<li><code>ftl.async_call.acquired</code></li> +<li><code>ftl.async_call.completed</code></li> +<li><code>ftl.async_call.created</code></li> +<li><code>ftl.async_call.executed</code></li> +<li><code>ftl.async_call.ms_to_complete</code></li> +</ul> +<h4 id="ftl-module-name">ftl.module.name</h4> +<ul> +<li><code>ftl.async_call.acquired</code></li> +<li><code>ftl.async_call.completed</code></li> +<li><code>ftl.async_call.created</code></li> +<li><code>ftl.async_call.executed</code></li> +<li><code>ftl.async_call.ms_to_complete</code></li> +<li><code>ftl.call.ms_to_complete</code></li> +<li><code>ftl.call.requests</code></li> +</ul> +<h4 id="ftl-outcome-status">ftl.outcome.status</h4> +<ul> +<li><code>ftl.async_call.acquired</code></li> +<li><code>ftl.async_call.completed</code></li> +<li><code>ftl.async_call.created</code></li> +<li><code>ftl.async_call.executed</code></li> +<li><code>ftl.async_call.ms_to_complete</code></li> +<li><code>ftl.call.ms_to_complete</code></li> +<li><code>ftl.call.requests</code></li> +</ul> +<h4 id="ftl-async-call-remaining-attempts">ftl.async_call.remaining_attempts</h4> +<ul> +<li><code>ftl.async_call.created</code></li> +</ul> +<h4 id="ftl-call-verb-ref">ftl.call.verb.ref</h4> +<ul> +<li><code>ftl.call.ms_to_complete</code></li> +<li><code>ftl.call.requests</code></li> +</ul> +<h4 id="ftl-call-run-time-ms-bucket">ftl.call.run_time_ms.bucket</h4> +<ul> +<li><code>ftl.call.requests</code></li> +</ul> +<h4 id="ftl-deployment-key">ftl.deployment.key</h4> +<ul> +<li><code>ftl.deployments.runner.active</code></li> +<li><code>ftl.runner.registration.heartbeats</code></li> +</ul> +<h2 id="db-metrics">DB Metrics</h2> +<p>DB Metrics are collected from the SQL database used by FTL. These metrics provide insights into the database connection pool, query latency etc.</p> +<h3 id="metrics-table-1">Metrics Table</h3> +<table><thead><tr><th>Metric Name</th><th>Type</th><th>Description</th></tr></thead><tbody> +<tr><td><code>db.sql.connection.closed_max_idle_time</code></td><td>Counter</td><td>Total number of connections closed due to max idle time</td></tr> +<tr><td><code>db.sql.connection.closed_max_idle</code></td><td>Counter</td><td>Total number of connections closed due to max idle connections</td></tr> +<tr><td><code>db.sql.connection.closed_max_lifetime</code></td><td>Counter</td><td>Total number of connections closed due to max lifetime</td></tr> +<tr><td><code>db.sql.connection.max_open</code></td><td>Gauge</td><td>Maximum number of open connections</td></tr> +<tr><td><code>db.sql.connection.open</code></td><td>Gauge</td><td>Number of open connections</td></tr> +<tr><td><code>db.sql.connection.wait_duration_milliseconds</code></td><td>Histogram</td><td>Duration of connection wait times in milliseconds</td></tr> +<tr><td><code>db.sql.connection.wait</code></td><td>Counter</td><td>Total number of connection waits</td></tr> +<tr><td><code>db.sql.latency_milliseconds</code></td><td>Histogram</td><td>SQL query latency in milliseconds</td></tr> +</tbody></table> +<h3 id="attributes-1">Attributes</h3> +<h4 id="db-system">db.system</h4> +<ul> +<li><code>db.sql.connection.closed_max_idle_time</code></li> +<li><code>db.sql.connection.closed_max_idle</code></li> +<li><code>db.sql.connection.closed_max_lifetime</code></li> +<li><code>db.sql.connection.max_open</code></li> +<li><code>db.sql.connection.open</code></li> +<li><code>db.sql.connection.wait_duration_milliseconds</code></li> +<li><code>db.sql.connection.wait</code></li> +</ul> +<h4 id="status">status</h4> +<ul> +<li><code>db.sql.connection.open</code></li> +<li><code>db.sql.latency_milliseconds</code></li> +</ul> +<h4 id="method">method</h4> +<ul> +<li><code>db.sql.latency_milliseconds</code></li> +</ul> +<h4 id="le-less-than-or-equal-to">le (less than or equal to)</h4> +<ul> +<li><code>db.sql.latency_milliseconds_bucket</code></li> +</ul> +<p>Note: The <code>job</code> attribute with value "ftl-serve" is common to all metrics and has been omitted from the individual listings for brevity.</p> + + + + diff --git a/bootstrap/scss/bootstrap-grid.css b/bootstrap/scss/bootstrap-grid.css new file mode 100644 index 0000000000..88b068ed73 --- /dev/null +++ b/bootstrap/scss/bootstrap-grid.css @@ -0,0 +1,6 @@ +/*! + * Bootstrap Grid v5.0.0-beta3 (https://getbootstrap.com/) + * Copyright 2011-2021 The Bootstrap Authors + * Copyright 2011-2021 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */.container,.container-fluid,.container-xxl,.container-xl,.container-lg,.container-md,.container-sm{width:100%;padding-right:var(--bs-gutter-x, .75rem);padding-left:var(--bs-gutter-x, .75rem);margin-right:auto;margin-left:auto}@media (min-width: 576px){.container-sm,.container{max-width:540px}}@media (min-width: 768px){.container-md,.container-sm,.container{max-width:720px}}@media (min-width: 992px){.container-lg,.container-md,.container-sm,.container{max-width:960px}}@media (min-width: 1200px){.container-xl,.container-lg,.container-md,.container-sm,.container{max-width:1140px}}@media (min-width: 1400px){.container-xxl,.container-xl,.container-lg,.container-md,.container-sm,.container{max-width:1320px}}.row{--bs-gutter-x: 1.5rem;--bs-gutter-y: 0;display:flex;flex-wrap:wrap;margin-top:calc(var(--bs-gutter-y)*-1);margin-right:calc(var(--bs-gutter-x)/-2);margin-left:calc(var(--bs-gutter-x)/-2)}.row>*{box-sizing:border-box;flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--bs-gutter-x)/2);padding-left:calc(var(--bs-gutter-x)/2);margin-top:var(--bs-gutter-y)}.col{flex:1 0 0%}.row-cols-auto>*{flex:0 0 auto;width:auto}.row-cols-1>*{flex:0 0 auto;width:100%}.row-cols-2>*{flex:0 0 auto;width:50%}.row-cols-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-4>*{flex:0 0 auto;width:25%}.row-cols-5>*{flex:0 0 auto;width:20%}.row-cols-6>*{flex:0 0 auto;width:16.6666666667%}.col-auto{flex:0 0 auto;width:auto}.col-1{flex:0 0 auto;width:8.3333333333%}.col-2{flex:0 0 auto;width:16.6666666667%}.col-3{flex:0 0 auto;width:25%}.col-4{flex:0 0 auto;width:33.3333333333%}.col-5{flex:0 0 auto;width:41.6666666667%}.col-6{flex:0 0 auto;width:50%}.col-7{flex:0 0 auto;width:58.3333333333%}.col-8{flex:0 0 auto;width:66.6666666667%}.col-9{flex:0 0 auto;width:75%}.col-10{flex:0 0 auto;width:83.3333333333%}.col-11{flex:0 0 auto;width:91.6666666667%}.col-12{flex:0 0 auto;width:100%}.offset-1{margin-left:8.3333333333%}.offset-2{margin-left:16.6666666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.3333333333%}.offset-5{margin-left:41.6666666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.3333333333%}.offset-8{margin-left:66.6666666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.3333333333%}.offset-11{margin-left:91.6666666667%}.g-0,.gx-0{--bs-gutter-x: 0}.g-0,.gy-0{--bs-gutter-y: 0}.g-1,.gx-1{--bs-gutter-x: .25rem}.g-1,.gy-1{--bs-gutter-y: .25rem}.g-2,.gx-2{--bs-gutter-x: .5rem}.g-2,.gy-2{--bs-gutter-y: .5rem}.g-3,.gx-3{--bs-gutter-x: 1rem}.g-3,.gy-3{--bs-gutter-y: 1rem}.g-4,.gx-4{--bs-gutter-x: 1.5rem}.g-4,.gy-4{--bs-gutter-y: 1.5rem}.g-5,.gx-5{--bs-gutter-x: 3rem}.g-5,.gy-5{--bs-gutter-y: 3rem}@media (min-width: 576px){.col-sm{flex:1 0 0%}.row-cols-sm-auto>*{flex:0 0 auto;width:auto}.row-cols-sm-1>*{flex:0 0 auto;width:100%}.row-cols-sm-2>*{flex:0 0 auto;width:50%}.row-cols-sm-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-sm-4>*{flex:0 0 auto;width:25%}.row-cols-sm-5>*{flex:0 0 auto;width:20%}.row-cols-sm-6>*{flex:0 0 auto;width:16.6666666667%}.col-sm-auto{flex:0 0 auto;width:auto}.col-sm-1{flex:0 0 auto;width:8.3333333333%}.col-sm-2{flex:0 0 auto;width:16.6666666667%}.col-sm-3{flex:0 0 auto;width:25%}.col-sm-4{flex:0 0 auto;width:33.3333333333%}.col-sm-5{flex:0 0 auto;width:41.6666666667%}.col-sm-6{flex:0 0 auto;width:50%}.col-sm-7{flex:0 0 auto;width:58.3333333333%}.col-sm-8{flex:0 0 auto;width:66.6666666667%}.col-sm-9{flex:0 0 auto;width:75%}.col-sm-10{flex:0 0 auto;width:83.3333333333%}.col-sm-11{flex:0 0 auto;width:91.6666666667%}.col-sm-12{flex:0 0 auto;width:100%}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.3333333333%}.offset-sm-2{margin-left:16.6666666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.3333333333%}.offset-sm-5{margin-left:41.6666666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.3333333333%}.offset-sm-8{margin-left:66.6666666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.3333333333%}.offset-sm-11{margin-left:91.6666666667%}.g-sm-0,.gx-sm-0{--bs-gutter-x: 0}.g-sm-0,.gy-sm-0{--bs-gutter-y: 0}.g-sm-1,.gx-sm-1{--bs-gutter-x: .25rem}.g-sm-1,.gy-sm-1{--bs-gutter-y: .25rem}.g-sm-2,.gx-sm-2{--bs-gutter-x: .5rem}.g-sm-2,.gy-sm-2{--bs-gutter-y: .5rem}.g-sm-3,.gx-sm-3{--bs-gutter-x: 1rem}.g-sm-3,.gy-sm-3{--bs-gutter-y: 1rem}.g-sm-4,.gx-sm-4{--bs-gutter-x: 1.5rem}.g-sm-4,.gy-sm-4{--bs-gutter-y: 1.5rem}.g-sm-5,.gx-sm-5{--bs-gutter-x: 3rem}.g-sm-5,.gy-sm-5{--bs-gutter-y: 3rem}}@media (min-width: 768px){.col-md{flex:1 0 0%}.row-cols-md-auto>*{flex:0 0 auto;width:auto}.row-cols-md-1>*{flex:0 0 auto;width:100%}.row-cols-md-2>*{flex:0 0 auto;width:50%}.row-cols-md-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-md-4>*{flex:0 0 auto;width:25%}.row-cols-md-5>*{flex:0 0 auto;width:20%}.row-cols-md-6>*{flex:0 0 auto;width:16.6666666667%}.col-md-auto{flex:0 0 auto;width:auto}.col-md-1{flex:0 0 auto;width:8.3333333333%}.col-md-2{flex:0 0 auto;width:16.6666666667%}.col-md-3{flex:0 0 auto;width:25%}.col-md-4{flex:0 0 auto;width:33.3333333333%}.col-md-5{flex:0 0 auto;width:41.6666666667%}.col-md-6{flex:0 0 auto;width:50%}.col-md-7{flex:0 0 auto;width:58.3333333333%}.col-md-8{flex:0 0 auto;width:66.6666666667%}.col-md-9{flex:0 0 auto;width:75%}.col-md-10{flex:0 0 auto;width:83.3333333333%}.col-md-11{flex:0 0 auto;width:91.6666666667%}.col-md-12{flex:0 0 auto;width:100%}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.3333333333%}.offset-md-2{margin-left:16.6666666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.3333333333%}.offset-md-5{margin-left:41.6666666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.3333333333%}.offset-md-8{margin-left:66.6666666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.3333333333%}.offset-md-11{margin-left:91.6666666667%}.g-md-0,.gx-md-0{--bs-gutter-x: 0}.g-md-0,.gy-md-0{--bs-gutter-y: 0}.g-md-1,.gx-md-1{--bs-gutter-x: .25rem}.g-md-1,.gy-md-1{--bs-gutter-y: .25rem}.g-md-2,.gx-md-2{--bs-gutter-x: .5rem}.g-md-2,.gy-md-2{--bs-gutter-y: .5rem}.g-md-3,.gx-md-3{--bs-gutter-x: 1rem}.g-md-3,.gy-md-3{--bs-gutter-y: 1rem}.g-md-4,.gx-md-4{--bs-gutter-x: 1.5rem}.g-md-4,.gy-md-4{--bs-gutter-y: 1.5rem}.g-md-5,.gx-md-5{--bs-gutter-x: 3rem}.g-md-5,.gy-md-5{--bs-gutter-y: 3rem}}@media (min-width: 992px){.col-lg{flex:1 0 0%}.row-cols-lg-auto>*{flex:0 0 auto;width:auto}.row-cols-lg-1>*{flex:0 0 auto;width:100%}.row-cols-lg-2>*{flex:0 0 auto;width:50%}.row-cols-lg-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-lg-4>*{flex:0 0 auto;width:25%}.row-cols-lg-5>*{flex:0 0 auto;width:20%}.row-cols-lg-6>*{flex:0 0 auto;width:16.6666666667%}.col-lg-auto{flex:0 0 auto;width:auto}.col-lg-1{flex:0 0 auto;width:8.3333333333%}.col-lg-2{flex:0 0 auto;width:16.6666666667%}.col-lg-3{flex:0 0 auto;width:25%}.col-lg-4{flex:0 0 auto;width:33.3333333333%}.col-lg-5{flex:0 0 auto;width:41.6666666667%}.col-lg-6{flex:0 0 auto;width:50%}.col-lg-7{flex:0 0 auto;width:58.3333333333%}.col-lg-8{flex:0 0 auto;width:66.6666666667%}.col-lg-9{flex:0 0 auto;width:75%}.col-lg-10{flex:0 0 auto;width:83.3333333333%}.col-lg-11{flex:0 0 auto;width:91.6666666667%}.col-lg-12{flex:0 0 auto;width:100%}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.3333333333%}.offset-lg-2{margin-left:16.6666666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.3333333333%}.offset-lg-5{margin-left:41.6666666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.3333333333%}.offset-lg-8{margin-left:66.6666666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.3333333333%}.offset-lg-11{margin-left:91.6666666667%}.g-lg-0,.gx-lg-0{--bs-gutter-x: 0}.g-lg-0,.gy-lg-0{--bs-gutter-y: 0}.g-lg-1,.gx-lg-1{--bs-gutter-x: .25rem}.g-lg-1,.gy-lg-1{--bs-gutter-y: .25rem}.g-lg-2,.gx-lg-2{--bs-gutter-x: .5rem}.g-lg-2,.gy-lg-2{--bs-gutter-y: .5rem}.g-lg-3,.gx-lg-3{--bs-gutter-x: 1rem}.g-lg-3,.gy-lg-3{--bs-gutter-y: 1rem}.g-lg-4,.gx-lg-4{--bs-gutter-x: 1.5rem}.g-lg-4,.gy-lg-4{--bs-gutter-y: 1.5rem}.g-lg-5,.gx-lg-5{--bs-gutter-x: 3rem}.g-lg-5,.gy-lg-5{--bs-gutter-y: 3rem}}@media (min-width: 1200px){.col-xl{flex:1 0 0%}.row-cols-xl-auto>*{flex:0 0 auto;width:auto}.row-cols-xl-1>*{flex:0 0 auto;width:100%}.row-cols-xl-2>*{flex:0 0 auto;width:50%}.row-cols-xl-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-xl-4>*{flex:0 0 auto;width:25%}.row-cols-xl-5>*{flex:0 0 auto;width:20%}.row-cols-xl-6>*{flex:0 0 auto;width:16.6666666667%}.col-xl-auto{flex:0 0 auto;width:auto}.col-xl-1{flex:0 0 auto;width:8.3333333333%}.col-xl-2{flex:0 0 auto;width:16.6666666667%}.col-xl-3{flex:0 0 auto;width:25%}.col-xl-4{flex:0 0 auto;width:33.3333333333%}.col-xl-5{flex:0 0 auto;width:41.6666666667%}.col-xl-6{flex:0 0 auto;width:50%}.col-xl-7{flex:0 0 auto;width:58.3333333333%}.col-xl-8{flex:0 0 auto;width:66.6666666667%}.col-xl-9{flex:0 0 auto;width:75%}.col-xl-10{flex:0 0 auto;width:83.3333333333%}.col-xl-11{flex:0 0 auto;width:91.6666666667%}.col-xl-12{flex:0 0 auto;width:100%}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.3333333333%}.offset-xl-2{margin-left:16.6666666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.3333333333%}.offset-xl-5{margin-left:41.6666666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.3333333333%}.offset-xl-8{margin-left:66.6666666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.3333333333%}.offset-xl-11{margin-left:91.6666666667%}.g-xl-0,.gx-xl-0{--bs-gutter-x: 0}.g-xl-0,.gy-xl-0{--bs-gutter-y: 0}.g-xl-1,.gx-xl-1{--bs-gutter-x: .25rem}.g-xl-1,.gy-xl-1{--bs-gutter-y: .25rem}.g-xl-2,.gx-xl-2{--bs-gutter-x: .5rem}.g-xl-2,.gy-xl-2{--bs-gutter-y: .5rem}.g-xl-3,.gx-xl-3{--bs-gutter-x: 1rem}.g-xl-3,.gy-xl-3{--bs-gutter-y: 1rem}.g-xl-4,.gx-xl-4{--bs-gutter-x: 1.5rem}.g-xl-4,.gy-xl-4{--bs-gutter-y: 1.5rem}.g-xl-5,.gx-xl-5{--bs-gutter-x: 3rem}.g-xl-5,.gy-xl-5{--bs-gutter-y: 3rem}}@media (min-width: 1400px){.col-xxl{flex:1 0 0%}.row-cols-xxl-auto>*{flex:0 0 auto;width:auto}.row-cols-xxl-1>*{flex:0 0 auto;width:100%}.row-cols-xxl-2>*{flex:0 0 auto;width:50%}.row-cols-xxl-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-xxl-4>*{flex:0 0 auto;width:25%}.row-cols-xxl-5>*{flex:0 0 auto;width:20%}.row-cols-xxl-6>*{flex:0 0 auto;width:16.6666666667%}.col-xxl-auto{flex:0 0 auto;width:auto}.col-xxl-1{flex:0 0 auto;width:8.3333333333%}.col-xxl-2{flex:0 0 auto;width:16.6666666667%}.col-xxl-3{flex:0 0 auto;width:25%}.col-xxl-4{flex:0 0 auto;width:33.3333333333%}.col-xxl-5{flex:0 0 auto;width:41.6666666667%}.col-xxl-6{flex:0 0 auto;width:50%}.col-xxl-7{flex:0 0 auto;width:58.3333333333%}.col-xxl-8{flex:0 0 auto;width:66.6666666667%}.col-xxl-9{flex:0 0 auto;width:75%}.col-xxl-10{flex:0 0 auto;width:83.3333333333%}.col-xxl-11{flex:0 0 auto;width:91.6666666667%}.col-xxl-12{flex:0 0 auto;width:100%}.offset-xxl-0{margin-left:0}.offset-xxl-1{margin-left:8.3333333333%}.offset-xxl-2{margin-left:16.6666666667%}.offset-xxl-3{margin-left:25%}.offset-xxl-4{margin-left:33.3333333333%}.offset-xxl-5{margin-left:41.6666666667%}.offset-xxl-6{margin-left:50%}.offset-xxl-7{margin-left:58.3333333333%}.offset-xxl-8{margin-left:66.6666666667%}.offset-xxl-9{margin-left:75%}.offset-xxl-10{margin-left:83.3333333333%}.offset-xxl-11{margin-left:91.6666666667%}.g-xxl-0,.gx-xxl-0{--bs-gutter-x: 0}.g-xxl-0,.gy-xxl-0{--bs-gutter-y: 0}.g-xxl-1,.gx-xxl-1{--bs-gutter-x: .25rem}.g-xxl-1,.gy-xxl-1{--bs-gutter-y: .25rem}.g-xxl-2,.gx-xxl-2{--bs-gutter-x: .5rem}.g-xxl-2,.gy-xxl-2{--bs-gutter-y: .5rem}.g-xxl-3,.gx-xxl-3{--bs-gutter-x: 1rem}.g-xxl-3,.gy-xxl-3{--bs-gutter-y: 1rem}.g-xxl-4,.gx-xxl-4{--bs-gutter-x: 1.5rem}.g-xxl-4,.gy-xxl-4{--bs-gutter-y: 1.5rem}.g-xxl-5,.gx-xxl-5{--bs-gutter-x: 3rem}.g-xxl-5,.gy-xxl-5{--bs-gutter-y: 3rem}}.d-inline{display:inline !important}.d-inline-block{display:inline-block !important}.d-block{display:block !important}.d-grid{display:grid !important}.d-table{display:table !important}.d-table-row{display:table-row !important}.d-table-cell{display:table-cell !important}.d-flex{display:flex !important}.d-inline-flex{display:inline-flex !important}.d-none{display:none !important}.flex-fill{flex:1 1 auto !important}.flex-row{flex-direction:row !important}.flex-column{flex-direction:column !important}.flex-row-reverse{flex-direction:row-reverse !important}.flex-column-reverse{flex-direction:column-reverse !important}.flex-grow-0{flex-grow:0 !important}.flex-grow-1{flex-grow:1 !important}.flex-shrink-0{flex-shrink:0 !important}.flex-shrink-1{flex-shrink:1 !important}.flex-wrap{flex-wrap:wrap !important}.flex-nowrap{flex-wrap:nowrap !important}.flex-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-start{justify-content:flex-start !important}.justify-content-end{justify-content:flex-end !important}.justify-content-center{justify-content:center !important}.justify-content-between{justify-content:space-between !important}.justify-content-around{justify-content:space-around !important}.justify-content-evenly{justify-content:space-evenly !important}.align-items-start{align-items:flex-start !important}.align-items-end{align-items:flex-end !important}.align-items-center{align-items:center !important}.align-items-baseline{align-items:baseline !important}.align-items-stretch{align-items:stretch !important}.align-content-start{align-content:flex-start !important}.align-content-end{align-content:flex-end !important}.align-content-center{align-content:center !important}.align-content-between{align-content:space-between !important}.align-content-around{align-content:space-around !important}.align-content-stretch{align-content:stretch !important}.align-self-auto{align-self:auto !important}.align-self-start{align-self:flex-start !important}.align-self-end{align-self:flex-end !important}.align-self-center{align-self:center !important}.align-self-baseline{align-self:baseline !important}.align-self-stretch{align-self:stretch !important}.order-first{order:-1 !important}.order-0{order:0 !important}.order-1{order:1 !important}.order-2{order:2 !important}.order-3{order:3 !important}.order-4{order:4 !important}.order-5{order:5 !important}.order-last{order:6 !important}.m-0{margin:0 !important}.m-1{margin:.25rem !important}.m-2{margin:.5rem !important}.m-3{margin:1rem !important}.m-4{margin:1.5rem !important}.m-5{margin:3rem !important}.m-auto{margin:auto !important}.mx-0{margin-right:0 !important;margin-left:0 !important}.mx-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-3{margin-right:1rem !important;margin-left:1rem !important}.mx-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-5{margin-right:3rem !important;margin-left:3rem !important}.mx-auto{margin-right:auto !important;margin-left:auto !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.my-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-0{margin-top:0 !important}.mt-1{margin-top:.25rem !important}.mt-2{margin-top:.5rem !important}.mt-3{margin-top:1rem !important}.mt-4{margin-top:1.5rem !important}.mt-5{margin-top:3rem !important}.mt-auto{margin-top:auto !important}.me-0{margin-right:0 !important}.me-1{margin-right:.25rem !important}.me-2{margin-right:.5rem !important}.me-3{margin-right:1rem !important}.me-4{margin-right:1.5rem !important}.me-5{margin-right:3rem !important}.me-auto{margin-right:auto !important}.mb-0{margin-bottom:0 !important}.mb-1{margin-bottom:.25rem !important}.mb-2{margin-bottom:.5rem !important}.mb-3{margin-bottom:1rem !important}.mb-4{margin-bottom:1.5rem !important}.mb-5{margin-bottom:3rem !important}.mb-auto{margin-bottom:auto !important}.ms-0{margin-left:0 !important}.ms-1{margin-left:.25rem !important}.ms-2{margin-left:.5rem !important}.ms-3{margin-left:1rem !important}.ms-4{margin-left:1.5rem !important}.ms-5{margin-left:3rem !important}.ms-auto{margin-left:auto !important}.p-0{padding:0 !important}.p-1{padding:.25rem !important}.p-2{padding:.5rem !important}.p-3{padding:1rem !important}.p-4{padding:1.5rem !important}.p-5{padding:3rem !important}.px-0{padding-right:0 !important;padding-left:0 !important}.px-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-3{padding-right:1rem !important;padding-left:1rem !important}.px-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-5{padding-right:3rem !important;padding-left:3rem !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.py-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-0{padding-top:0 !important}.pt-1{padding-top:.25rem !important}.pt-2{padding-top:.5rem !important}.pt-3{padding-top:1rem !important}.pt-4{padding-top:1.5rem !important}.pt-5{padding-top:3rem !important}.pe-0{padding-right:0 !important}.pe-1{padding-right:.25rem !important}.pe-2{padding-right:.5rem !important}.pe-3{padding-right:1rem !important}.pe-4{padding-right:1.5rem !important}.pe-5{padding-right:3rem !important}.pb-0{padding-bottom:0 !important}.pb-1{padding-bottom:.25rem !important}.pb-2{padding-bottom:.5rem !important}.pb-3{padding-bottom:1rem !important}.pb-4{padding-bottom:1.5rem !important}.pb-5{padding-bottom:3rem !important}.ps-0{padding-left:0 !important}.ps-1{padding-left:.25rem !important}.ps-2{padding-left:.5rem !important}.ps-3{padding-left:1rem !important}.ps-4{padding-left:1.5rem !important}.ps-5{padding-left:3rem !important}@media (min-width: 576px){.d-sm-inline{display:inline !important}.d-sm-inline-block{display:inline-block !important}.d-sm-block{display:block !important}.d-sm-grid{display:grid !important}.d-sm-table{display:table !important}.d-sm-table-row{display:table-row !important}.d-sm-table-cell{display:table-cell !important}.d-sm-flex{display:flex !important}.d-sm-inline-flex{display:inline-flex !important}.d-sm-none{display:none !important}.flex-sm-fill{flex:1 1 auto !important}.flex-sm-row{flex-direction:row !important}.flex-sm-column{flex-direction:column !important}.flex-sm-row-reverse{flex-direction:row-reverse !important}.flex-sm-column-reverse{flex-direction:column-reverse !important}.flex-sm-grow-0{flex-grow:0 !important}.flex-sm-grow-1{flex-grow:1 !important}.flex-sm-shrink-0{flex-shrink:0 !important}.flex-sm-shrink-1{flex-shrink:1 !important}.flex-sm-wrap{flex-wrap:wrap !important}.flex-sm-nowrap{flex-wrap:nowrap !important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-sm-start{justify-content:flex-start !important}.justify-content-sm-end{justify-content:flex-end !important}.justify-content-sm-center{justify-content:center !important}.justify-content-sm-between{justify-content:space-between !important}.justify-content-sm-around{justify-content:space-around !important}.justify-content-sm-evenly{justify-content:space-evenly !important}.align-items-sm-start{align-items:flex-start !important}.align-items-sm-end{align-items:flex-end !important}.align-items-sm-center{align-items:center !important}.align-items-sm-baseline{align-items:baseline !important}.align-items-sm-stretch{align-items:stretch !important}.align-content-sm-start{align-content:flex-start !important}.align-content-sm-end{align-content:flex-end !important}.align-content-sm-center{align-content:center !important}.align-content-sm-between{align-content:space-between !important}.align-content-sm-around{align-content:space-around !important}.align-content-sm-stretch{align-content:stretch !important}.align-self-sm-auto{align-self:auto !important}.align-self-sm-start{align-self:flex-start !important}.align-self-sm-end{align-self:flex-end !important}.align-self-sm-center{align-self:center !important}.align-self-sm-baseline{align-self:baseline !important}.align-self-sm-stretch{align-self:stretch !important}.order-sm-first{order:-1 !important}.order-sm-0{order:0 !important}.order-sm-1{order:1 !important}.order-sm-2{order:2 !important}.order-sm-3{order:3 !important}.order-sm-4{order:4 !important}.order-sm-5{order:5 !important}.order-sm-last{order:6 !important}.m-sm-0{margin:0 !important}.m-sm-1{margin:.25rem !important}.m-sm-2{margin:.5rem !important}.m-sm-3{margin:1rem !important}.m-sm-4{margin:1.5rem !important}.m-sm-5{margin:3rem !important}.m-sm-auto{margin:auto !important}.mx-sm-0{margin-right:0 !important;margin-left:0 !important}.mx-sm-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-sm-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-sm-3{margin-right:1rem !important;margin-left:1rem !important}.mx-sm-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-sm-5{margin-right:3rem !important;margin-left:3rem !important}.mx-sm-auto{margin-right:auto !important;margin-left:auto !important}.my-sm-0{margin-top:0 !important;margin-bottom:0 !important}.my-sm-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-sm-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-sm-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-sm-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-sm-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-sm-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-sm-0{margin-top:0 !important}.mt-sm-1{margin-top:.25rem !important}.mt-sm-2{margin-top:.5rem !important}.mt-sm-3{margin-top:1rem !important}.mt-sm-4{margin-top:1.5rem !important}.mt-sm-5{margin-top:3rem !important}.mt-sm-auto{margin-top:auto !important}.me-sm-0{margin-right:0 !important}.me-sm-1{margin-right:.25rem !important}.me-sm-2{margin-right:.5rem !important}.me-sm-3{margin-right:1rem !important}.me-sm-4{margin-right:1.5rem !important}.me-sm-5{margin-right:3rem !important}.me-sm-auto{margin-right:auto !important}.mb-sm-0{margin-bottom:0 !important}.mb-sm-1{margin-bottom:.25rem !important}.mb-sm-2{margin-bottom:.5rem !important}.mb-sm-3{margin-bottom:1rem !important}.mb-sm-4{margin-bottom:1.5rem !important}.mb-sm-5{margin-bottom:3rem !important}.mb-sm-auto{margin-bottom:auto !important}.ms-sm-0{margin-left:0 !important}.ms-sm-1{margin-left:.25rem !important}.ms-sm-2{margin-left:.5rem !important}.ms-sm-3{margin-left:1rem !important}.ms-sm-4{margin-left:1.5rem !important}.ms-sm-5{margin-left:3rem !important}.ms-sm-auto{margin-left:auto !important}.p-sm-0{padding:0 !important}.p-sm-1{padding:.25rem !important}.p-sm-2{padding:.5rem !important}.p-sm-3{padding:1rem !important}.p-sm-4{padding:1.5rem !important}.p-sm-5{padding:3rem !important}.px-sm-0{padding-right:0 !important;padding-left:0 !important}.px-sm-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-sm-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-sm-3{padding-right:1rem !important;padding-left:1rem !important}.px-sm-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-sm-5{padding-right:3rem !important;padding-left:3rem !important}.py-sm-0{padding-top:0 !important;padding-bottom:0 !important}.py-sm-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-sm-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-sm-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-sm-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-sm-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-sm-0{padding-top:0 !important}.pt-sm-1{padding-top:.25rem !important}.pt-sm-2{padding-top:.5rem !important}.pt-sm-3{padding-top:1rem !important}.pt-sm-4{padding-top:1.5rem !important}.pt-sm-5{padding-top:3rem !important}.pe-sm-0{padding-right:0 !important}.pe-sm-1{padding-right:.25rem !important}.pe-sm-2{padding-right:.5rem !important}.pe-sm-3{padding-right:1rem !important}.pe-sm-4{padding-right:1.5rem !important}.pe-sm-5{padding-right:3rem !important}.pb-sm-0{padding-bottom:0 !important}.pb-sm-1{padding-bottom:.25rem !important}.pb-sm-2{padding-bottom:.5rem !important}.pb-sm-3{padding-bottom:1rem !important}.pb-sm-4{padding-bottom:1.5rem !important}.pb-sm-5{padding-bottom:3rem !important}.ps-sm-0{padding-left:0 !important}.ps-sm-1{padding-left:.25rem !important}.ps-sm-2{padding-left:.5rem !important}.ps-sm-3{padding-left:1rem !important}.ps-sm-4{padding-left:1.5rem !important}.ps-sm-5{padding-left:3rem !important}}@media (min-width: 768px){.d-md-inline{display:inline !important}.d-md-inline-block{display:inline-block !important}.d-md-block{display:block !important}.d-md-grid{display:grid !important}.d-md-table{display:table !important}.d-md-table-row{display:table-row !important}.d-md-table-cell{display:table-cell !important}.d-md-flex{display:flex !important}.d-md-inline-flex{display:inline-flex !important}.d-md-none{display:none !important}.flex-md-fill{flex:1 1 auto !important}.flex-md-row{flex-direction:row !important}.flex-md-column{flex-direction:column !important}.flex-md-row-reverse{flex-direction:row-reverse !important}.flex-md-column-reverse{flex-direction:column-reverse !important}.flex-md-grow-0{flex-grow:0 !important}.flex-md-grow-1{flex-grow:1 !important}.flex-md-shrink-0{flex-shrink:0 !important}.flex-md-shrink-1{flex-shrink:1 !important}.flex-md-wrap{flex-wrap:wrap !important}.flex-md-nowrap{flex-wrap:nowrap !important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-md-start{justify-content:flex-start !important}.justify-content-md-end{justify-content:flex-end !important}.justify-content-md-center{justify-content:center !important}.justify-content-md-between{justify-content:space-between !important}.justify-content-md-around{justify-content:space-around !important}.justify-content-md-evenly{justify-content:space-evenly !important}.align-items-md-start{align-items:flex-start !important}.align-items-md-end{align-items:flex-end !important}.align-items-md-center{align-items:center !important}.align-items-md-baseline{align-items:baseline !important}.align-items-md-stretch{align-items:stretch !important}.align-content-md-start{align-content:flex-start !important}.align-content-md-end{align-content:flex-end !important}.align-content-md-center{align-content:center !important}.align-content-md-between{align-content:space-between !important}.align-content-md-around{align-content:space-around !important}.align-content-md-stretch{align-content:stretch !important}.align-self-md-auto{align-self:auto !important}.align-self-md-start{align-self:flex-start !important}.align-self-md-end{align-self:flex-end !important}.align-self-md-center{align-self:center !important}.align-self-md-baseline{align-self:baseline !important}.align-self-md-stretch{align-self:stretch !important}.order-md-first{order:-1 !important}.order-md-0{order:0 !important}.order-md-1{order:1 !important}.order-md-2{order:2 !important}.order-md-3{order:3 !important}.order-md-4{order:4 !important}.order-md-5{order:5 !important}.order-md-last{order:6 !important}.m-md-0{margin:0 !important}.m-md-1{margin:.25rem !important}.m-md-2{margin:.5rem !important}.m-md-3{margin:1rem !important}.m-md-4{margin:1.5rem !important}.m-md-5{margin:3rem !important}.m-md-auto{margin:auto !important}.mx-md-0{margin-right:0 !important;margin-left:0 !important}.mx-md-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-md-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-md-3{margin-right:1rem !important;margin-left:1rem !important}.mx-md-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-md-5{margin-right:3rem !important;margin-left:3rem !important}.mx-md-auto{margin-right:auto !important;margin-left:auto !important}.my-md-0{margin-top:0 !important;margin-bottom:0 !important}.my-md-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-md-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-md-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-md-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-md-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-md-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-md-0{margin-top:0 !important}.mt-md-1{margin-top:.25rem !important}.mt-md-2{margin-top:.5rem !important}.mt-md-3{margin-top:1rem !important}.mt-md-4{margin-top:1.5rem !important}.mt-md-5{margin-top:3rem !important}.mt-md-auto{margin-top:auto !important}.me-md-0{margin-right:0 !important}.me-md-1{margin-right:.25rem !important}.me-md-2{margin-right:.5rem !important}.me-md-3{margin-right:1rem !important}.me-md-4{margin-right:1.5rem !important}.me-md-5{margin-right:3rem !important}.me-md-auto{margin-right:auto !important}.mb-md-0{margin-bottom:0 !important}.mb-md-1{margin-bottom:.25rem !important}.mb-md-2{margin-bottom:.5rem !important}.mb-md-3{margin-bottom:1rem !important}.mb-md-4{margin-bottom:1.5rem !important}.mb-md-5{margin-bottom:3rem !important}.mb-md-auto{margin-bottom:auto !important}.ms-md-0{margin-left:0 !important}.ms-md-1{margin-left:.25rem !important}.ms-md-2{margin-left:.5rem !important}.ms-md-3{margin-left:1rem !important}.ms-md-4{margin-left:1.5rem !important}.ms-md-5{margin-left:3rem !important}.ms-md-auto{margin-left:auto !important}.p-md-0{padding:0 !important}.p-md-1{padding:.25rem !important}.p-md-2{padding:.5rem !important}.p-md-3{padding:1rem !important}.p-md-4{padding:1.5rem !important}.p-md-5{padding:3rem !important}.px-md-0{padding-right:0 !important;padding-left:0 !important}.px-md-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-md-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-md-3{padding-right:1rem !important;padding-left:1rem !important}.px-md-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-md-5{padding-right:3rem !important;padding-left:3rem !important}.py-md-0{padding-top:0 !important;padding-bottom:0 !important}.py-md-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-md-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-md-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-md-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-md-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-md-0{padding-top:0 !important}.pt-md-1{padding-top:.25rem !important}.pt-md-2{padding-top:.5rem !important}.pt-md-3{padding-top:1rem !important}.pt-md-4{padding-top:1.5rem !important}.pt-md-5{padding-top:3rem !important}.pe-md-0{padding-right:0 !important}.pe-md-1{padding-right:.25rem !important}.pe-md-2{padding-right:.5rem !important}.pe-md-3{padding-right:1rem !important}.pe-md-4{padding-right:1.5rem !important}.pe-md-5{padding-right:3rem !important}.pb-md-0{padding-bottom:0 !important}.pb-md-1{padding-bottom:.25rem !important}.pb-md-2{padding-bottom:.5rem !important}.pb-md-3{padding-bottom:1rem !important}.pb-md-4{padding-bottom:1.5rem !important}.pb-md-5{padding-bottom:3rem !important}.ps-md-0{padding-left:0 !important}.ps-md-1{padding-left:.25rem !important}.ps-md-2{padding-left:.5rem !important}.ps-md-3{padding-left:1rem !important}.ps-md-4{padding-left:1.5rem !important}.ps-md-5{padding-left:3rem !important}}@media (min-width: 992px){.d-lg-inline{display:inline !important}.d-lg-inline-block{display:inline-block !important}.d-lg-block{display:block !important}.d-lg-grid{display:grid !important}.d-lg-table{display:table !important}.d-lg-table-row{display:table-row !important}.d-lg-table-cell{display:table-cell !important}.d-lg-flex{display:flex !important}.d-lg-inline-flex{display:inline-flex !important}.d-lg-none{display:none !important}.flex-lg-fill{flex:1 1 auto !important}.flex-lg-row{flex-direction:row !important}.flex-lg-column{flex-direction:column !important}.flex-lg-row-reverse{flex-direction:row-reverse !important}.flex-lg-column-reverse{flex-direction:column-reverse !important}.flex-lg-grow-0{flex-grow:0 !important}.flex-lg-grow-1{flex-grow:1 !important}.flex-lg-shrink-0{flex-shrink:0 !important}.flex-lg-shrink-1{flex-shrink:1 !important}.flex-lg-wrap{flex-wrap:wrap !important}.flex-lg-nowrap{flex-wrap:nowrap !important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-lg-start{justify-content:flex-start !important}.justify-content-lg-end{justify-content:flex-end !important}.justify-content-lg-center{justify-content:center !important}.justify-content-lg-between{justify-content:space-between !important}.justify-content-lg-around{justify-content:space-around !important}.justify-content-lg-evenly{justify-content:space-evenly !important}.align-items-lg-start{align-items:flex-start !important}.align-items-lg-end{align-items:flex-end !important}.align-items-lg-center{align-items:center !important}.align-items-lg-baseline{align-items:baseline !important}.align-items-lg-stretch{align-items:stretch !important}.align-content-lg-start{align-content:flex-start !important}.align-content-lg-end{align-content:flex-end !important}.align-content-lg-center{align-content:center !important}.align-content-lg-between{align-content:space-between !important}.align-content-lg-around{align-content:space-around !important}.align-content-lg-stretch{align-content:stretch !important}.align-self-lg-auto{align-self:auto !important}.align-self-lg-start{align-self:flex-start !important}.align-self-lg-end{align-self:flex-end !important}.align-self-lg-center{align-self:center !important}.align-self-lg-baseline{align-self:baseline !important}.align-self-lg-stretch{align-self:stretch !important}.order-lg-first{order:-1 !important}.order-lg-0{order:0 !important}.order-lg-1{order:1 !important}.order-lg-2{order:2 !important}.order-lg-3{order:3 !important}.order-lg-4{order:4 !important}.order-lg-5{order:5 !important}.order-lg-last{order:6 !important}.m-lg-0{margin:0 !important}.m-lg-1{margin:.25rem !important}.m-lg-2{margin:.5rem !important}.m-lg-3{margin:1rem !important}.m-lg-4{margin:1.5rem !important}.m-lg-5{margin:3rem !important}.m-lg-auto{margin:auto !important}.mx-lg-0{margin-right:0 !important;margin-left:0 !important}.mx-lg-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-lg-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-lg-3{margin-right:1rem !important;margin-left:1rem !important}.mx-lg-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-lg-5{margin-right:3rem !important;margin-left:3rem !important}.mx-lg-auto{margin-right:auto !important;margin-left:auto !important}.my-lg-0{margin-top:0 !important;margin-bottom:0 !important}.my-lg-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-lg-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-lg-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-lg-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-lg-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-lg-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-lg-0{margin-top:0 !important}.mt-lg-1{margin-top:.25rem !important}.mt-lg-2{margin-top:.5rem !important}.mt-lg-3{margin-top:1rem !important}.mt-lg-4{margin-top:1.5rem !important}.mt-lg-5{margin-top:3rem !important}.mt-lg-auto{margin-top:auto !important}.me-lg-0{margin-right:0 !important}.me-lg-1{margin-right:.25rem !important}.me-lg-2{margin-right:.5rem !important}.me-lg-3{margin-right:1rem !important}.me-lg-4{margin-right:1.5rem !important}.me-lg-5{margin-right:3rem !important}.me-lg-auto{margin-right:auto !important}.mb-lg-0{margin-bottom:0 !important}.mb-lg-1{margin-bottom:.25rem !important}.mb-lg-2{margin-bottom:.5rem !important}.mb-lg-3{margin-bottom:1rem !important}.mb-lg-4{margin-bottom:1.5rem !important}.mb-lg-5{margin-bottom:3rem !important}.mb-lg-auto{margin-bottom:auto !important}.ms-lg-0{margin-left:0 !important}.ms-lg-1{margin-left:.25rem !important}.ms-lg-2{margin-left:.5rem !important}.ms-lg-3{margin-left:1rem !important}.ms-lg-4{margin-left:1.5rem !important}.ms-lg-5{margin-left:3rem !important}.ms-lg-auto{margin-left:auto !important}.p-lg-0{padding:0 !important}.p-lg-1{padding:.25rem !important}.p-lg-2{padding:.5rem !important}.p-lg-3{padding:1rem !important}.p-lg-4{padding:1.5rem !important}.p-lg-5{padding:3rem !important}.px-lg-0{padding-right:0 !important;padding-left:0 !important}.px-lg-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-lg-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-lg-3{padding-right:1rem !important;padding-left:1rem !important}.px-lg-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-lg-5{padding-right:3rem !important;padding-left:3rem !important}.py-lg-0{padding-top:0 !important;padding-bottom:0 !important}.py-lg-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-lg-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-lg-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-lg-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-lg-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-lg-0{padding-top:0 !important}.pt-lg-1{padding-top:.25rem !important}.pt-lg-2{padding-top:.5rem !important}.pt-lg-3{padding-top:1rem !important}.pt-lg-4{padding-top:1.5rem !important}.pt-lg-5{padding-top:3rem !important}.pe-lg-0{padding-right:0 !important}.pe-lg-1{padding-right:.25rem !important}.pe-lg-2{padding-right:.5rem !important}.pe-lg-3{padding-right:1rem !important}.pe-lg-4{padding-right:1.5rem !important}.pe-lg-5{padding-right:3rem !important}.pb-lg-0{padding-bottom:0 !important}.pb-lg-1{padding-bottom:.25rem !important}.pb-lg-2{padding-bottom:.5rem !important}.pb-lg-3{padding-bottom:1rem !important}.pb-lg-4{padding-bottom:1.5rem !important}.pb-lg-5{padding-bottom:3rem !important}.ps-lg-0{padding-left:0 !important}.ps-lg-1{padding-left:.25rem !important}.ps-lg-2{padding-left:.5rem !important}.ps-lg-3{padding-left:1rem !important}.ps-lg-4{padding-left:1.5rem !important}.ps-lg-5{padding-left:3rem !important}}@media (min-width: 1200px){.d-xl-inline{display:inline !important}.d-xl-inline-block{display:inline-block !important}.d-xl-block{display:block !important}.d-xl-grid{display:grid !important}.d-xl-table{display:table !important}.d-xl-table-row{display:table-row !important}.d-xl-table-cell{display:table-cell !important}.d-xl-flex{display:flex !important}.d-xl-inline-flex{display:inline-flex !important}.d-xl-none{display:none !important}.flex-xl-fill{flex:1 1 auto !important}.flex-xl-row{flex-direction:row !important}.flex-xl-column{flex-direction:column !important}.flex-xl-row-reverse{flex-direction:row-reverse !important}.flex-xl-column-reverse{flex-direction:column-reverse !important}.flex-xl-grow-0{flex-grow:0 !important}.flex-xl-grow-1{flex-grow:1 !important}.flex-xl-shrink-0{flex-shrink:0 !important}.flex-xl-shrink-1{flex-shrink:1 !important}.flex-xl-wrap{flex-wrap:wrap !important}.flex-xl-nowrap{flex-wrap:nowrap !important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-xl-start{justify-content:flex-start !important}.justify-content-xl-end{justify-content:flex-end !important}.justify-content-xl-center{justify-content:center !important}.justify-content-xl-between{justify-content:space-between !important}.justify-content-xl-around{justify-content:space-around !important}.justify-content-xl-evenly{justify-content:space-evenly !important}.align-items-xl-start{align-items:flex-start !important}.align-items-xl-end{align-items:flex-end !important}.align-items-xl-center{align-items:center !important}.align-items-xl-baseline{align-items:baseline !important}.align-items-xl-stretch{align-items:stretch !important}.align-content-xl-start{align-content:flex-start !important}.align-content-xl-end{align-content:flex-end !important}.align-content-xl-center{align-content:center !important}.align-content-xl-between{align-content:space-between !important}.align-content-xl-around{align-content:space-around !important}.align-content-xl-stretch{align-content:stretch !important}.align-self-xl-auto{align-self:auto !important}.align-self-xl-start{align-self:flex-start !important}.align-self-xl-end{align-self:flex-end !important}.align-self-xl-center{align-self:center !important}.align-self-xl-baseline{align-self:baseline !important}.align-self-xl-stretch{align-self:stretch !important}.order-xl-first{order:-1 !important}.order-xl-0{order:0 !important}.order-xl-1{order:1 !important}.order-xl-2{order:2 !important}.order-xl-3{order:3 !important}.order-xl-4{order:4 !important}.order-xl-5{order:5 !important}.order-xl-last{order:6 !important}.m-xl-0{margin:0 !important}.m-xl-1{margin:.25rem !important}.m-xl-2{margin:.5rem !important}.m-xl-3{margin:1rem !important}.m-xl-4{margin:1.5rem !important}.m-xl-5{margin:3rem !important}.m-xl-auto{margin:auto !important}.mx-xl-0{margin-right:0 !important;margin-left:0 !important}.mx-xl-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-xl-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-xl-3{margin-right:1rem !important;margin-left:1rem !important}.mx-xl-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-xl-5{margin-right:3rem !important;margin-left:3rem !important}.mx-xl-auto{margin-right:auto !important;margin-left:auto !important}.my-xl-0{margin-top:0 !important;margin-bottom:0 !important}.my-xl-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-xl-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-xl-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-xl-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-xl-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-xl-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-xl-0{margin-top:0 !important}.mt-xl-1{margin-top:.25rem !important}.mt-xl-2{margin-top:.5rem !important}.mt-xl-3{margin-top:1rem !important}.mt-xl-4{margin-top:1.5rem !important}.mt-xl-5{margin-top:3rem !important}.mt-xl-auto{margin-top:auto !important}.me-xl-0{margin-right:0 !important}.me-xl-1{margin-right:.25rem !important}.me-xl-2{margin-right:.5rem !important}.me-xl-3{margin-right:1rem !important}.me-xl-4{margin-right:1.5rem !important}.me-xl-5{margin-right:3rem !important}.me-xl-auto{margin-right:auto !important}.mb-xl-0{margin-bottom:0 !important}.mb-xl-1{margin-bottom:.25rem !important}.mb-xl-2{margin-bottom:.5rem !important}.mb-xl-3{margin-bottom:1rem !important}.mb-xl-4{margin-bottom:1.5rem !important}.mb-xl-5{margin-bottom:3rem !important}.mb-xl-auto{margin-bottom:auto !important}.ms-xl-0{margin-left:0 !important}.ms-xl-1{margin-left:.25rem !important}.ms-xl-2{margin-left:.5rem !important}.ms-xl-3{margin-left:1rem !important}.ms-xl-4{margin-left:1.5rem !important}.ms-xl-5{margin-left:3rem !important}.ms-xl-auto{margin-left:auto !important}.p-xl-0{padding:0 !important}.p-xl-1{padding:.25rem !important}.p-xl-2{padding:.5rem !important}.p-xl-3{padding:1rem !important}.p-xl-4{padding:1.5rem !important}.p-xl-5{padding:3rem !important}.px-xl-0{padding-right:0 !important;padding-left:0 !important}.px-xl-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-xl-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-xl-3{padding-right:1rem !important;padding-left:1rem !important}.px-xl-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-xl-5{padding-right:3rem !important;padding-left:3rem !important}.py-xl-0{padding-top:0 !important;padding-bottom:0 !important}.py-xl-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-xl-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-xl-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-xl-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-xl-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-xl-0{padding-top:0 !important}.pt-xl-1{padding-top:.25rem !important}.pt-xl-2{padding-top:.5rem !important}.pt-xl-3{padding-top:1rem !important}.pt-xl-4{padding-top:1.5rem !important}.pt-xl-5{padding-top:3rem !important}.pe-xl-0{padding-right:0 !important}.pe-xl-1{padding-right:.25rem !important}.pe-xl-2{padding-right:.5rem !important}.pe-xl-3{padding-right:1rem !important}.pe-xl-4{padding-right:1.5rem !important}.pe-xl-5{padding-right:3rem !important}.pb-xl-0{padding-bottom:0 !important}.pb-xl-1{padding-bottom:.25rem !important}.pb-xl-2{padding-bottom:.5rem !important}.pb-xl-3{padding-bottom:1rem !important}.pb-xl-4{padding-bottom:1.5rem !important}.pb-xl-5{padding-bottom:3rem !important}.ps-xl-0{padding-left:0 !important}.ps-xl-1{padding-left:.25rem !important}.ps-xl-2{padding-left:.5rem !important}.ps-xl-3{padding-left:1rem !important}.ps-xl-4{padding-left:1.5rem !important}.ps-xl-5{padding-left:3rem !important}}@media (min-width: 1400px){.d-xxl-inline{display:inline !important}.d-xxl-inline-block{display:inline-block !important}.d-xxl-block{display:block !important}.d-xxl-grid{display:grid !important}.d-xxl-table{display:table !important}.d-xxl-table-row{display:table-row !important}.d-xxl-table-cell{display:table-cell !important}.d-xxl-flex{display:flex !important}.d-xxl-inline-flex{display:inline-flex !important}.d-xxl-none{display:none !important}.flex-xxl-fill{flex:1 1 auto !important}.flex-xxl-row{flex-direction:row !important}.flex-xxl-column{flex-direction:column !important}.flex-xxl-row-reverse{flex-direction:row-reverse !important}.flex-xxl-column-reverse{flex-direction:column-reverse !important}.flex-xxl-grow-0{flex-grow:0 !important}.flex-xxl-grow-1{flex-grow:1 !important}.flex-xxl-shrink-0{flex-shrink:0 !important}.flex-xxl-shrink-1{flex-shrink:1 !important}.flex-xxl-wrap{flex-wrap:wrap !important}.flex-xxl-nowrap{flex-wrap:nowrap !important}.flex-xxl-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-xxl-start{justify-content:flex-start !important}.justify-content-xxl-end{justify-content:flex-end !important}.justify-content-xxl-center{justify-content:center !important}.justify-content-xxl-between{justify-content:space-between !important}.justify-content-xxl-around{justify-content:space-around !important}.justify-content-xxl-evenly{justify-content:space-evenly !important}.align-items-xxl-start{align-items:flex-start !important}.align-items-xxl-end{align-items:flex-end !important}.align-items-xxl-center{align-items:center !important}.align-items-xxl-baseline{align-items:baseline !important}.align-items-xxl-stretch{align-items:stretch !important}.align-content-xxl-start{align-content:flex-start !important}.align-content-xxl-end{align-content:flex-end !important}.align-content-xxl-center{align-content:center !important}.align-content-xxl-between{align-content:space-between !important}.align-content-xxl-around{align-content:space-around !important}.align-content-xxl-stretch{align-content:stretch !important}.align-self-xxl-auto{align-self:auto !important}.align-self-xxl-start{align-self:flex-start !important}.align-self-xxl-end{align-self:flex-end !important}.align-self-xxl-center{align-self:center !important}.align-self-xxl-baseline{align-self:baseline !important}.align-self-xxl-stretch{align-self:stretch !important}.order-xxl-first{order:-1 !important}.order-xxl-0{order:0 !important}.order-xxl-1{order:1 !important}.order-xxl-2{order:2 !important}.order-xxl-3{order:3 !important}.order-xxl-4{order:4 !important}.order-xxl-5{order:5 !important}.order-xxl-last{order:6 !important}.m-xxl-0{margin:0 !important}.m-xxl-1{margin:.25rem !important}.m-xxl-2{margin:.5rem !important}.m-xxl-3{margin:1rem !important}.m-xxl-4{margin:1.5rem !important}.m-xxl-5{margin:3rem !important}.m-xxl-auto{margin:auto !important}.mx-xxl-0{margin-right:0 !important;margin-left:0 !important}.mx-xxl-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-xxl-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-xxl-3{margin-right:1rem !important;margin-left:1rem !important}.mx-xxl-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-xxl-5{margin-right:3rem !important;margin-left:3rem !important}.mx-xxl-auto{margin-right:auto !important;margin-left:auto !important}.my-xxl-0{margin-top:0 !important;margin-bottom:0 !important}.my-xxl-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-xxl-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-xxl-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-xxl-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-xxl-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-xxl-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-xxl-0{margin-top:0 !important}.mt-xxl-1{margin-top:.25rem !important}.mt-xxl-2{margin-top:.5rem !important}.mt-xxl-3{margin-top:1rem !important}.mt-xxl-4{margin-top:1.5rem !important}.mt-xxl-5{margin-top:3rem !important}.mt-xxl-auto{margin-top:auto !important}.me-xxl-0{margin-right:0 !important}.me-xxl-1{margin-right:.25rem !important}.me-xxl-2{margin-right:.5rem !important}.me-xxl-3{margin-right:1rem !important}.me-xxl-4{margin-right:1.5rem !important}.me-xxl-5{margin-right:3rem !important}.me-xxl-auto{margin-right:auto !important}.mb-xxl-0{margin-bottom:0 !important}.mb-xxl-1{margin-bottom:.25rem !important}.mb-xxl-2{margin-bottom:.5rem !important}.mb-xxl-3{margin-bottom:1rem !important}.mb-xxl-4{margin-bottom:1.5rem !important}.mb-xxl-5{margin-bottom:3rem !important}.mb-xxl-auto{margin-bottom:auto !important}.ms-xxl-0{margin-left:0 !important}.ms-xxl-1{margin-left:.25rem !important}.ms-xxl-2{margin-left:.5rem !important}.ms-xxl-3{margin-left:1rem !important}.ms-xxl-4{margin-left:1.5rem !important}.ms-xxl-5{margin-left:3rem !important}.ms-xxl-auto{margin-left:auto !important}.p-xxl-0{padding:0 !important}.p-xxl-1{padding:.25rem !important}.p-xxl-2{padding:.5rem !important}.p-xxl-3{padding:1rem !important}.p-xxl-4{padding:1.5rem !important}.p-xxl-5{padding:3rem !important}.px-xxl-0{padding-right:0 !important;padding-left:0 !important}.px-xxl-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-xxl-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-xxl-3{padding-right:1rem !important;padding-left:1rem !important}.px-xxl-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-xxl-5{padding-right:3rem !important;padding-left:3rem !important}.py-xxl-0{padding-top:0 !important;padding-bottom:0 !important}.py-xxl-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-xxl-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-xxl-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-xxl-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-xxl-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-xxl-0{padding-top:0 !important}.pt-xxl-1{padding-top:.25rem !important}.pt-xxl-2{padding-top:.5rem !important}.pt-xxl-3{padding-top:1rem !important}.pt-xxl-4{padding-top:1.5rem !important}.pt-xxl-5{padding-top:3rem !important}.pe-xxl-0{padding-right:0 !important}.pe-xxl-1{padding-right:.25rem !important}.pe-xxl-2{padding-right:.5rem !important}.pe-xxl-3{padding-right:1rem !important}.pe-xxl-4{padding-right:1.5rem !important}.pe-xxl-5{padding-right:3rem !important}.pb-xxl-0{padding-bottom:0 !important}.pb-xxl-1{padding-bottom:.25rem !important}.pb-xxl-2{padding-bottom:.5rem !important}.pb-xxl-3{padding-bottom:1rem !important}.pb-xxl-4{padding-bottom:1.5rem !important}.pb-xxl-5{padding-bottom:3rem !important}.ps-xxl-0{padding-left:0 !important}.ps-xxl-1{padding-left:.25rem !important}.ps-xxl-2{padding-left:.5rem !important}.ps-xxl-3{padding-left:1rem !important}.ps-xxl-4{padding-left:1.5rem !important}.ps-xxl-5{padding-left:3rem !important}}@media print{.d-print-inline{display:inline !important}.d-print-inline-block{display:inline-block !important}.d-print-block{display:block !important}.d-print-grid{display:grid !important}.d-print-table{display:table !important}.d-print-table-row{display:table-row !important}.d-print-table-cell{display:table-cell !important}.d-print-flex{display:flex !important}.d-print-inline-flex{display:inline-flex !important}.d-print-none{display:none !important}} \ No newline at end of file diff --git a/bootstrap/scss/bootstrap-reboot.css b/bootstrap/scss/bootstrap-reboot.css new file mode 100644 index 0000000000..106dbab1c9 --- /dev/null +++ b/bootstrap/scss/bootstrap-reboot.css @@ -0,0 +1,7 @@ +/*! + * Bootstrap Reboot v5.0.0-beta3 (https://getbootstrap.com/) + * Copyright 2011-2021 The Bootstrap Authors + * Copyright 2011-2021 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) + */*,*::before,*::after{box-sizing:border-box}@media (prefers-reduced-motion: no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation 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;background-color:#fff;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h6,h5,h4,h3,h2,h1{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width: 1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width: 1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width: 1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width: 1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[title],abbr[data-bs-original-title]{text-decoration:underline dotted;cursor:help;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}ol,ul,dl{margin-top:0;margin-bottom:1rem}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}pre,code,kbd,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em;direction:ltr /* rtl:ignore */;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}thead,tbody,tfoot,tr,td,th{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}input,button,select,optgroup,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button:not(:disabled),[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width: 1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-text,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none !important} \ No newline at end of file diff --git a/bootstrap/scss/bootstrap-utilities.css b/bootstrap/scss/bootstrap-utilities.css new file mode 100644 index 0000000000..2647b49dd4 --- /dev/null +++ b/bootstrap/scss/bootstrap-utilities.css @@ -0,0 +1,6 @@ +/*! + * Bootstrap Utilities v5.0.0-beta3 (https://getbootstrap.com/) + * Copyright 2011-2021 The Bootstrap Authors + * Copyright 2011-2021 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */.clearfix::after{display:block;clear:both;content:""}.link-primary{color:#0d6efd}.link-primary:hover,.link-primary:focus{color:#0a58ca}.link-secondary{color:#6c757d}.link-secondary:hover,.link-secondary:focus{color:#565e64}.link-success{color:#198754}.link-success:hover,.link-success:focus{color:#146c43}.link-info{color:#0dcaf0}.link-info:hover,.link-info:focus{color:#3dd5f3}.link-warning{color:#ffc107}.link-warning:hover,.link-warning:focus{color:#ffcd39}.link-danger{color:#dc3545}.link-danger:hover,.link-danger:focus{color:#b02a37}.link-light{color:#f8f9fa}.link-light:hover,.link-light:focus{color:#f9fafb}.link-dark{color:#212529}.link-dark:hover,.link-dark:focus{color:#1a1e21}.ratio{position:relative;width:100%}.ratio::before{display:block;padding-top:var(--bs-aspect-ratio);content:""}.ratio>*{position:absolute;top:0;left:0;width:100%;height:100%}.ratio-1x1{--bs-aspect-ratio: 100%}.ratio-4x3{--bs-aspect-ratio: 75%}.ratio-16x9{--bs-aspect-ratio: 56.25%}.ratio-21x9{--bs-aspect-ratio: 42.8571428571%}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top{position:sticky;top:0;z-index:1020}@media (min-width: 576px){.sticky-sm-top{position:sticky;top:0;z-index:1020}}@media (min-width: 768px){.sticky-md-top{position:sticky;top:0;z-index:1020}}@media (min-width: 992px){.sticky-lg-top{position:sticky;top:0;z-index:1020}}@media (min-width: 1200px){.sticky-xl-top{position:sticky;top:0;z-index:1020}}@media (min-width: 1400px){.sticky-xxl-top{position:sticky;top:0;z-index:1020}}.visually-hidden,.visually-hidden-focusable:not(:focus):not(:focus-within){position:absolute !important;width:1px !important;height:1px !important;padding:0 !important;margin:-1px !important;overflow:hidden !important;clip:rect(0, 0, 0, 0) !important;white-space:nowrap !important;border:0 !important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.align-baseline{vertical-align:baseline !important}.align-top{vertical-align:top !important}.align-middle{vertical-align:middle !important}.align-bottom{vertical-align:bottom !important}.align-text-bottom{vertical-align:text-bottom !important}.align-text-top{vertical-align:text-top !important}.float-start{float:left !important}.float-end{float:right !important}.float-none{float:none !important}.overflow-auto{overflow:auto !important}.overflow-hidden{overflow:hidden !important}.overflow-visible{overflow:visible !important}.overflow-scroll{overflow:scroll !important}.d-inline{display:inline !important}.d-inline-block{display:inline-block !important}.d-block{display:block !important}.d-grid{display:grid !important}.d-table{display:table !important}.d-table-row{display:table-row !important}.d-table-cell{display:table-cell !important}.d-flex{display:flex !important}.d-inline-flex{display:inline-flex !important}.d-none{display:none !important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15) !important}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075) !important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175) !important}.shadow-none{box-shadow:none !important}.position-static{position:static !important}.position-relative{position:relative !important}.position-absolute{position:absolute !important}.position-fixed{position:fixed !important}.position-sticky{position:sticky !important}.top-0{top:0 !important}.top-50{top:50% !important}.top-100{top:100% !important}.bottom-0{bottom:0 !important}.bottom-50{bottom:50% !important}.bottom-100{bottom:100% !important}.start-0{left:0 !important}.start-50{left:50% !important}.start-100{left:100% !important}.end-0{right:0 !important}.end-50{right:50% !important}.end-100{right:100% !important}.translate-middle{transform:translate(-50%, -50%) !important}.translate-middle-x{transform:translateX(-50%) !important}.translate-middle-y{transform:translateY(-50%) !important}.border{border:1px solid #dee2e6 !important}.border-0{border:0 !important}.border-top{border-top:1px solid #dee2e6 !important}.border-top-0{border-top:0 !important}.border-end{border-right:1px solid #dee2e6 !important}.border-end-0{border-right:0 !important}.border-bottom{border-bottom:1px solid #dee2e6 !important}.border-bottom-0{border-bottom:0 !important}.border-start{border-left:1px solid #dee2e6 !important}.border-start-0{border-left:0 !important}.border-primary{border-color:#0d6efd !important}.border-secondary{border-color:#6c757d !important}.border-success{border-color:#198754 !important}.border-info{border-color:#0dcaf0 !important}.border-warning{border-color:#ffc107 !important}.border-danger{border-color:#dc3545 !important}.border-light{border-color:#f8f9fa !important}.border-dark{border-color:#212529 !important}.border-white{border-color:#fff !important}.border-1{border-width:1px !important}.border-2{border-width:2px !important}.border-3{border-width:3px !important}.border-4{border-width:4px !important}.border-5{border-width:5px !important}.w-25{width:25% !important}.w-50{width:50% !important}.w-75{width:75% !important}.w-100{width:100% !important}.w-auto{width:auto !important}.mw-100{max-width:100% !important}.vw-100{width:100vw !important}.min-vw-100{min-width:100vw !important}.h-25{height:25% !important}.h-50{height:50% !important}.h-75{height:75% !important}.h-100{height:100% !important}.h-auto{height:auto !important}.mh-100{max-height:100% !important}.vh-100{height:100vh !important}.min-vh-100{min-height:100vh !important}.flex-fill{flex:1 1 auto !important}.flex-row{flex-direction:row !important}.flex-column{flex-direction:column !important}.flex-row-reverse{flex-direction:row-reverse !important}.flex-column-reverse{flex-direction:column-reverse !important}.flex-grow-0{flex-grow:0 !important}.flex-grow-1{flex-grow:1 !important}.flex-shrink-0{flex-shrink:0 !important}.flex-shrink-1{flex-shrink:1 !important}.flex-wrap{flex-wrap:wrap !important}.flex-nowrap{flex-wrap:nowrap !important}.flex-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-0{gap:0 !important}.gap-1{gap:.25rem !important}.gap-2{gap:.5rem !important}.gap-3{gap:1rem !important}.gap-4{gap:1.5rem !important}.gap-5{gap:3rem !important}.justify-content-start{justify-content:flex-start !important}.justify-content-end{justify-content:flex-end !important}.justify-content-center{justify-content:center !important}.justify-content-between{justify-content:space-between !important}.justify-content-around{justify-content:space-around !important}.justify-content-evenly{justify-content:space-evenly !important}.align-items-start{align-items:flex-start !important}.align-items-end{align-items:flex-end !important}.align-items-center{align-items:center !important}.align-items-baseline{align-items:baseline !important}.align-items-stretch{align-items:stretch !important}.align-content-start{align-content:flex-start !important}.align-content-end{align-content:flex-end !important}.align-content-center{align-content:center !important}.align-content-between{align-content:space-between !important}.align-content-around{align-content:space-around !important}.align-content-stretch{align-content:stretch !important}.align-self-auto{align-self:auto !important}.align-self-start{align-self:flex-start !important}.align-self-end{align-self:flex-end !important}.align-self-center{align-self:center !important}.align-self-baseline{align-self:baseline !important}.align-self-stretch{align-self:stretch !important}.order-first{order:-1 !important}.order-0{order:0 !important}.order-1{order:1 !important}.order-2{order:2 !important}.order-3{order:3 !important}.order-4{order:4 !important}.order-5{order:5 !important}.order-last{order:6 !important}.m-0{margin:0 !important}.m-1{margin:.25rem !important}.m-2{margin:.5rem !important}.m-3{margin:1rem !important}.m-4{margin:1.5rem !important}.m-5{margin:3rem !important}.m-auto{margin:auto !important}.mx-0{margin-right:0 !important;margin-left:0 !important}.mx-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-3{margin-right:1rem !important;margin-left:1rem !important}.mx-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-5{margin-right:3rem !important;margin-left:3rem !important}.mx-auto{margin-right:auto !important;margin-left:auto !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.my-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-0{margin-top:0 !important}.mt-1{margin-top:.25rem !important}.mt-2{margin-top:.5rem !important}.mt-3{margin-top:1rem !important}.mt-4{margin-top:1.5rem !important}.mt-5{margin-top:3rem !important}.mt-auto{margin-top:auto !important}.me-0{margin-right:0 !important}.me-1{margin-right:.25rem !important}.me-2{margin-right:.5rem !important}.me-3{margin-right:1rem !important}.me-4{margin-right:1.5rem !important}.me-5{margin-right:3rem !important}.me-auto{margin-right:auto !important}.mb-0{margin-bottom:0 !important}.mb-1{margin-bottom:.25rem !important}.mb-2{margin-bottom:.5rem !important}.mb-3{margin-bottom:1rem !important}.mb-4{margin-bottom:1.5rem !important}.mb-5{margin-bottom:3rem !important}.mb-auto{margin-bottom:auto !important}.ms-0{margin-left:0 !important}.ms-1{margin-left:.25rem !important}.ms-2{margin-left:.5rem !important}.ms-3{margin-left:1rem !important}.ms-4{margin-left:1.5rem !important}.ms-5{margin-left:3rem !important}.ms-auto{margin-left:auto !important}.p-0{padding:0 !important}.p-1{padding:.25rem !important}.p-2{padding:.5rem !important}.p-3{padding:1rem !important}.p-4{padding:1.5rem !important}.p-5{padding:3rem !important}.px-0{padding-right:0 !important;padding-left:0 !important}.px-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-3{padding-right:1rem !important;padding-left:1rem !important}.px-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-5{padding-right:3rem !important;padding-left:3rem !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.py-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-0{padding-top:0 !important}.pt-1{padding-top:.25rem !important}.pt-2{padding-top:.5rem !important}.pt-3{padding-top:1rem !important}.pt-4{padding-top:1.5rem !important}.pt-5{padding-top:3rem !important}.pe-0{padding-right:0 !important}.pe-1{padding-right:.25rem !important}.pe-2{padding-right:.5rem !important}.pe-3{padding-right:1rem !important}.pe-4{padding-right:1.5rem !important}.pe-5{padding-right:3rem !important}.pb-0{padding-bottom:0 !important}.pb-1{padding-bottom:.25rem !important}.pb-2{padding-bottom:.5rem !important}.pb-3{padding-bottom:1rem !important}.pb-4{padding-bottom:1.5rem !important}.pb-5{padding-bottom:3rem !important}.ps-0{padding-left:0 !important}.ps-1{padding-left:.25rem !important}.ps-2{padding-left:.5rem !important}.ps-3{padding-left:1rem !important}.ps-4{padding-left:1.5rem !important}.ps-5{padding-left:3rem !important}.font-monospace{font-family:var(--bs-font-monospace) !important}.fs-1{font-size:calc(1.375rem + 1.5vw) !important}.fs-2{font-size:calc(1.325rem + .9vw) !important}.fs-3{font-size:calc(1.3rem + .6vw) !important}.fs-4{font-size:calc(1.275rem + .3vw) !important}.fs-5{font-size:1.25rem !important}.fs-6{font-size:1rem !important}.fst-italic{font-style:italic !important}.fst-normal{font-style:normal !important}.fw-light{font-weight:300 !important}.fw-lighter{font-weight:lighter !important}.fw-normal{font-weight:400 !important}.fw-bold{font-weight:700 !important}.fw-bolder{font-weight:bolder !important}.lh-1{line-height:1 !important}.lh-sm{line-height:1.25 !important}.lh-base{line-height:1.5 !important}.lh-lg{line-height:2 !important}.text-start{text-align:left !important}.text-end{text-align:right !important}.text-center{text-align:center !important}.text-decoration-none{text-decoration:none !important}.text-decoration-underline{text-decoration:underline !important}.text-decoration-line-through{text-decoration:line-through !important}.text-lowercase{text-transform:lowercase !important}.text-uppercase{text-transform:uppercase !important}.text-capitalize{text-transform:capitalize !important}.text-wrap{white-space:normal !important}.text-nowrap{white-space:nowrap !important}.text-break{word-wrap:break-word !important;word-break:break-word !important}.text-primary{color:#0d6efd !important}.text-secondary{color:#6c757d !important}.text-success{color:#198754 !important}.text-info{color:#0dcaf0 !important}.text-warning{color:#ffc107 !important}.text-danger{color:#dc3545 !important}.text-light{color:#f8f9fa !important}.text-dark{color:#212529 !important}.text-white{color:#fff !important}.text-body{color:#212529 !important}.text-muted{color:#6c757d !important}.text-black-50{color:rgba(0,0,0,.5) !important}.text-white-50{color:rgba(255,255,255,.5) !important}.text-reset{color:inherit !important}.bg-primary{background-color:#0d6efd !important}.bg-secondary{background-color:#6c757d !important}.bg-success{background-color:#198754 !important}.bg-info{background-color:#0dcaf0 !important}.bg-warning{background-color:#ffc107 !important}.bg-danger{background-color:#dc3545 !important}.bg-light{background-color:#f8f9fa !important}.bg-dark{background-color:#212529 !important}.bg-body{background-color:#fff !important}.bg-white{background-color:#fff !important}.bg-transparent{background-color:rgba(0,0,0,0) !important}.bg-gradient{background-image:var(--bs-gradient) !important}.user-select-all{user-select:all !important}.user-select-auto{user-select:auto !important}.user-select-none{user-select:none !important}.pe-none{pointer-events:none !important}.pe-auto{pointer-events:auto !important}.rounded{border-radius:.25rem !important}.rounded-0{border-radius:0 !important}.rounded-1{border-radius:.2rem !important}.rounded-2{border-radius:.25rem !important}.rounded-3{border-radius:.3rem !important}.rounded-circle{border-radius:50% !important}.rounded-pill{border-radius:50rem !important}.rounded-top{border-top-left-radius:.25rem !important;border-top-right-radius:.25rem !important}.rounded-end{border-top-right-radius:.25rem !important;border-bottom-right-radius:.25rem !important}.rounded-bottom{border-bottom-right-radius:.25rem !important;border-bottom-left-radius:.25rem !important}.rounded-start{border-bottom-left-radius:.25rem !important;border-top-left-radius:.25rem !important}.visible{visibility:visible !important}.invisible{visibility:hidden !important}@media (min-width: 576px){.float-sm-start{float:left !important}.float-sm-end{float:right !important}.float-sm-none{float:none !important}.d-sm-inline{display:inline !important}.d-sm-inline-block{display:inline-block !important}.d-sm-block{display:block !important}.d-sm-grid{display:grid !important}.d-sm-table{display:table !important}.d-sm-table-row{display:table-row !important}.d-sm-table-cell{display:table-cell !important}.d-sm-flex{display:flex !important}.d-sm-inline-flex{display:inline-flex !important}.d-sm-none{display:none !important}.flex-sm-fill{flex:1 1 auto !important}.flex-sm-row{flex-direction:row !important}.flex-sm-column{flex-direction:column !important}.flex-sm-row-reverse{flex-direction:row-reverse !important}.flex-sm-column-reverse{flex-direction:column-reverse !important}.flex-sm-grow-0{flex-grow:0 !important}.flex-sm-grow-1{flex-grow:1 !important}.flex-sm-shrink-0{flex-shrink:0 !important}.flex-sm-shrink-1{flex-shrink:1 !important}.flex-sm-wrap{flex-wrap:wrap !important}.flex-sm-nowrap{flex-wrap:nowrap !important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-sm-0{gap:0 !important}.gap-sm-1{gap:.25rem !important}.gap-sm-2{gap:.5rem !important}.gap-sm-3{gap:1rem !important}.gap-sm-4{gap:1.5rem !important}.gap-sm-5{gap:3rem !important}.justify-content-sm-start{justify-content:flex-start !important}.justify-content-sm-end{justify-content:flex-end !important}.justify-content-sm-center{justify-content:center !important}.justify-content-sm-between{justify-content:space-between !important}.justify-content-sm-around{justify-content:space-around !important}.justify-content-sm-evenly{justify-content:space-evenly !important}.align-items-sm-start{align-items:flex-start !important}.align-items-sm-end{align-items:flex-end !important}.align-items-sm-center{align-items:center !important}.align-items-sm-baseline{align-items:baseline !important}.align-items-sm-stretch{align-items:stretch !important}.align-content-sm-start{align-content:flex-start !important}.align-content-sm-end{align-content:flex-end !important}.align-content-sm-center{align-content:center !important}.align-content-sm-between{align-content:space-between !important}.align-content-sm-around{align-content:space-around !important}.align-content-sm-stretch{align-content:stretch !important}.align-self-sm-auto{align-self:auto !important}.align-self-sm-start{align-self:flex-start !important}.align-self-sm-end{align-self:flex-end !important}.align-self-sm-center{align-self:center !important}.align-self-sm-baseline{align-self:baseline !important}.align-self-sm-stretch{align-self:stretch !important}.order-sm-first{order:-1 !important}.order-sm-0{order:0 !important}.order-sm-1{order:1 !important}.order-sm-2{order:2 !important}.order-sm-3{order:3 !important}.order-sm-4{order:4 !important}.order-sm-5{order:5 !important}.order-sm-last{order:6 !important}.m-sm-0{margin:0 !important}.m-sm-1{margin:.25rem !important}.m-sm-2{margin:.5rem !important}.m-sm-3{margin:1rem !important}.m-sm-4{margin:1.5rem !important}.m-sm-5{margin:3rem !important}.m-sm-auto{margin:auto !important}.mx-sm-0{margin-right:0 !important;margin-left:0 !important}.mx-sm-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-sm-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-sm-3{margin-right:1rem !important;margin-left:1rem !important}.mx-sm-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-sm-5{margin-right:3rem !important;margin-left:3rem !important}.mx-sm-auto{margin-right:auto !important;margin-left:auto !important}.my-sm-0{margin-top:0 !important;margin-bottom:0 !important}.my-sm-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-sm-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-sm-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-sm-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-sm-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-sm-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-sm-0{margin-top:0 !important}.mt-sm-1{margin-top:.25rem !important}.mt-sm-2{margin-top:.5rem !important}.mt-sm-3{margin-top:1rem !important}.mt-sm-4{margin-top:1.5rem !important}.mt-sm-5{margin-top:3rem !important}.mt-sm-auto{margin-top:auto !important}.me-sm-0{margin-right:0 !important}.me-sm-1{margin-right:.25rem !important}.me-sm-2{margin-right:.5rem !important}.me-sm-3{margin-right:1rem !important}.me-sm-4{margin-right:1.5rem !important}.me-sm-5{margin-right:3rem !important}.me-sm-auto{margin-right:auto !important}.mb-sm-0{margin-bottom:0 !important}.mb-sm-1{margin-bottom:.25rem !important}.mb-sm-2{margin-bottom:.5rem !important}.mb-sm-3{margin-bottom:1rem !important}.mb-sm-4{margin-bottom:1.5rem !important}.mb-sm-5{margin-bottom:3rem !important}.mb-sm-auto{margin-bottom:auto !important}.ms-sm-0{margin-left:0 !important}.ms-sm-1{margin-left:.25rem !important}.ms-sm-2{margin-left:.5rem !important}.ms-sm-3{margin-left:1rem !important}.ms-sm-4{margin-left:1.5rem !important}.ms-sm-5{margin-left:3rem !important}.ms-sm-auto{margin-left:auto !important}.p-sm-0{padding:0 !important}.p-sm-1{padding:.25rem !important}.p-sm-2{padding:.5rem !important}.p-sm-3{padding:1rem !important}.p-sm-4{padding:1.5rem !important}.p-sm-5{padding:3rem !important}.px-sm-0{padding-right:0 !important;padding-left:0 !important}.px-sm-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-sm-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-sm-3{padding-right:1rem !important;padding-left:1rem !important}.px-sm-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-sm-5{padding-right:3rem !important;padding-left:3rem !important}.py-sm-0{padding-top:0 !important;padding-bottom:0 !important}.py-sm-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-sm-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-sm-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-sm-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-sm-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-sm-0{padding-top:0 !important}.pt-sm-1{padding-top:.25rem !important}.pt-sm-2{padding-top:.5rem !important}.pt-sm-3{padding-top:1rem !important}.pt-sm-4{padding-top:1.5rem !important}.pt-sm-5{padding-top:3rem !important}.pe-sm-0{padding-right:0 !important}.pe-sm-1{padding-right:.25rem !important}.pe-sm-2{padding-right:.5rem !important}.pe-sm-3{padding-right:1rem !important}.pe-sm-4{padding-right:1.5rem !important}.pe-sm-5{padding-right:3rem !important}.pb-sm-0{padding-bottom:0 !important}.pb-sm-1{padding-bottom:.25rem !important}.pb-sm-2{padding-bottom:.5rem !important}.pb-sm-3{padding-bottom:1rem !important}.pb-sm-4{padding-bottom:1.5rem !important}.pb-sm-5{padding-bottom:3rem !important}.ps-sm-0{padding-left:0 !important}.ps-sm-1{padding-left:.25rem !important}.ps-sm-2{padding-left:.5rem !important}.ps-sm-3{padding-left:1rem !important}.ps-sm-4{padding-left:1.5rem !important}.ps-sm-5{padding-left:3rem !important}.text-sm-start{text-align:left !important}.text-sm-end{text-align:right !important}.text-sm-center{text-align:center !important}}@media (min-width: 768px){.float-md-start{float:left !important}.float-md-end{float:right !important}.float-md-none{float:none !important}.d-md-inline{display:inline !important}.d-md-inline-block{display:inline-block !important}.d-md-block{display:block !important}.d-md-grid{display:grid !important}.d-md-table{display:table !important}.d-md-table-row{display:table-row !important}.d-md-table-cell{display:table-cell !important}.d-md-flex{display:flex !important}.d-md-inline-flex{display:inline-flex !important}.d-md-none{display:none !important}.flex-md-fill{flex:1 1 auto !important}.flex-md-row{flex-direction:row !important}.flex-md-column{flex-direction:column !important}.flex-md-row-reverse{flex-direction:row-reverse !important}.flex-md-column-reverse{flex-direction:column-reverse !important}.flex-md-grow-0{flex-grow:0 !important}.flex-md-grow-1{flex-grow:1 !important}.flex-md-shrink-0{flex-shrink:0 !important}.flex-md-shrink-1{flex-shrink:1 !important}.flex-md-wrap{flex-wrap:wrap !important}.flex-md-nowrap{flex-wrap:nowrap !important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-md-0{gap:0 !important}.gap-md-1{gap:.25rem !important}.gap-md-2{gap:.5rem !important}.gap-md-3{gap:1rem !important}.gap-md-4{gap:1.5rem !important}.gap-md-5{gap:3rem !important}.justify-content-md-start{justify-content:flex-start !important}.justify-content-md-end{justify-content:flex-end !important}.justify-content-md-center{justify-content:center !important}.justify-content-md-between{justify-content:space-between !important}.justify-content-md-around{justify-content:space-around !important}.justify-content-md-evenly{justify-content:space-evenly !important}.align-items-md-start{align-items:flex-start !important}.align-items-md-end{align-items:flex-end !important}.align-items-md-center{align-items:center !important}.align-items-md-baseline{align-items:baseline !important}.align-items-md-stretch{align-items:stretch !important}.align-content-md-start{align-content:flex-start !important}.align-content-md-end{align-content:flex-end !important}.align-content-md-center{align-content:center !important}.align-content-md-between{align-content:space-between !important}.align-content-md-around{align-content:space-around !important}.align-content-md-stretch{align-content:stretch !important}.align-self-md-auto{align-self:auto !important}.align-self-md-start{align-self:flex-start !important}.align-self-md-end{align-self:flex-end !important}.align-self-md-center{align-self:center !important}.align-self-md-baseline{align-self:baseline !important}.align-self-md-stretch{align-self:stretch !important}.order-md-first{order:-1 !important}.order-md-0{order:0 !important}.order-md-1{order:1 !important}.order-md-2{order:2 !important}.order-md-3{order:3 !important}.order-md-4{order:4 !important}.order-md-5{order:5 !important}.order-md-last{order:6 !important}.m-md-0{margin:0 !important}.m-md-1{margin:.25rem !important}.m-md-2{margin:.5rem !important}.m-md-3{margin:1rem !important}.m-md-4{margin:1.5rem !important}.m-md-5{margin:3rem !important}.m-md-auto{margin:auto !important}.mx-md-0{margin-right:0 !important;margin-left:0 !important}.mx-md-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-md-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-md-3{margin-right:1rem !important;margin-left:1rem !important}.mx-md-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-md-5{margin-right:3rem !important;margin-left:3rem !important}.mx-md-auto{margin-right:auto !important;margin-left:auto !important}.my-md-0{margin-top:0 !important;margin-bottom:0 !important}.my-md-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-md-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-md-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-md-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-md-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-md-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-md-0{margin-top:0 !important}.mt-md-1{margin-top:.25rem !important}.mt-md-2{margin-top:.5rem !important}.mt-md-3{margin-top:1rem !important}.mt-md-4{margin-top:1.5rem !important}.mt-md-5{margin-top:3rem !important}.mt-md-auto{margin-top:auto !important}.me-md-0{margin-right:0 !important}.me-md-1{margin-right:.25rem !important}.me-md-2{margin-right:.5rem !important}.me-md-3{margin-right:1rem !important}.me-md-4{margin-right:1.5rem !important}.me-md-5{margin-right:3rem !important}.me-md-auto{margin-right:auto !important}.mb-md-0{margin-bottom:0 !important}.mb-md-1{margin-bottom:.25rem !important}.mb-md-2{margin-bottom:.5rem !important}.mb-md-3{margin-bottom:1rem !important}.mb-md-4{margin-bottom:1.5rem !important}.mb-md-5{margin-bottom:3rem !important}.mb-md-auto{margin-bottom:auto !important}.ms-md-0{margin-left:0 !important}.ms-md-1{margin-left:.25rem !important}.ms-md-2{margin-left:.5rem !important}.ms-md-3{margin-left:1rem !important}.ms-md-4{margin-left:1.5rem !important}.ms-md-5{margin-left:3rem !important}.ms-md-auto{margin-left:auto !important}.p-md-0{padding:0 !important}.p-md-1{padding:.25rem !important}.p-md-2{padding:.5rem !important}.p-md-3{padding:1rem !important}.p-md-4{padding:1.5rem !important}.p-md-5{padding:3rem !important}.px-md-0{padding-right:0 !important;padding-left:0 !important}.px-md-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-md-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-md-3{padding-right:1rem !important;padding-left:1rem !important}.px-md-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-md-5{padding-right:3rem !important;padding-left:3rem !important}.py-md-0{padding-top:0 !important;padding-bottom:0 !important}.py-md-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-md-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-md-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-md-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-md-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-md-0{padding-top:0 !important}.pt-md-1{padding-top:.25rem !important}.pt-md-2{padding-top:.5rem !important}.pt-md-3{padding-top:1rem !important}.pt-md-4{padding-top:1.5rem !important}.pt-md-5{padding-top:3rem !important}.pe-md-0{padding-right:0 !important}.pe-md-1{padding-right:.25rem !important}.pe-md-2{padding-right:.5rem !important}.pe-md-3{padding-right:1rem !important}.pe-md-4{padding-right:1.5rem !important}.pe-md-5{padding-right:3rem !important}.pb-md-0{padding-bottom:0 !important}.pb-md-1{padding-bottom:.25rem !important}.pb-md-2{padding-bottom:.5rem !important}.pb-md-3{padding-bottom:1rem !important}.pb-md-4{padding-bottom:1.5rem !important}.pb-md-5{padding-bottom:3rem !important}.ps-md-0{padding-left:0 !important}.ps-md-1{padding-left:.25rem !important}.ps-md-2{padding-left:.5rem !important}.ps-md-3{padding-left:1rem !important}.ps-md-4{padding-left:1.5rem !important}.ps-md-5{padding-left:3rem !important}.text-md-start{text-align:left !important}.text-md-end{text-align:right !important}.text-md-center{text-align:center !important}}@media (min-width: 992px){.float-lg-start{float:left !important}.float-lg-end{float:right !important}.float-lg-none{float:none !important}.d-lg-inline{display:inline !important}.d-lg-inline-block{display:inline-block !important}.d-lg-block{display:block !important}.d-lg-grid{display:grid !important}.d-lg-table{display:table !important}.d-lg-table-row{display:table-row !important}.d-lg-table-cell{display:table-cell !important}.d-lg-flex{display:flex !important}.d-lg-inline-flex{display:inline-flex !important}.d-lg-none{display:none !important}.flex-lg-fill{flex:1 1 auto !important}.flex-lg-row{flex-direction:row !important}.flex-lg-column{flex-direction:column !important}.flex-lg-row-reverse{flex-direction:row-reverse !important}.flex-lg-column-reverse{flex-direction:column-reverse !important}.flex-lg-grow-0{flex-grow:0 !important}.flex-lg-grow-1{flex-grow:1 !important}.flex-lg-shrink-0{flex-shrink:0 !important}.flex-lg-shrink-1{flex-shrink:1 !important}.flex-lg-wrap{flex-wrap:wrap !important}.flex-lg-nowrap{flex-wrap:nowrap !important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-lg-0{gap:0 !important}.gap-lg-1{gap:.25rem !important}.gap-lg-2{gap:.5rem !important}.gap-lg-3{gap:1rem !important}.gap-lg-4{gap:1.5rem !important}.gap-lg-5{gap:3rem !important}.justify-content-lg-start{justify-content:flex-start !important}.justify-content-lg-end{justify-content:flex-end !important}.justify-content-lg-center{justify-content:center !important}.justify-content-lg-between{justify-content:space-between !important}.justify-content-lg-around{justify-content:space-around !important}.justify-content-lg-evenly{justify-content:space-evenly !important}.align-items-lg-start{align-items:flex-start !important}.align-items-lg-end{align-items:flex-end !important}.align-items-lg-center{align-items:center !important}.align-items-lg-baseline{align-items:baseline !important}.align-items-lg-stretch{align-items:stretch !important}.align-content-lg-start{align-content:flex-start !important}.align-content-lg-end{align-content:flex-end !important}.align-content-lg-center{align-content:center !important}.align-content-lg-between{align-content:space-between !important}.align-content-lg-around{align-content:space-around !important}.align-content-lg-stretch{align-content:stretch !important}.align-self-lg-auto{align-self:auto !important}.align-self-lg-start{align-self:flex-start !important}.align-self-lg-end{align-self:flex-end !important}.align-self-lg-center{align-self:center !important}.align-self-lg-baseline{align-self:baseline !important}.align-self-lg-stretch{align-self:stretch !important}.order-lg-first{order:-1 !important}.order-lg-0{order:0 !important}.order-lg-1{order:1 !important}.order-lg-2{order:2 !important}.order-lg-3{order:3 !important}.order-lg-4{order:4 !important}.order-lg-5{order:5 !important}.order-lg-last{order:6 !important}.m-lg-0{margin:0 !important}.m-lg-1{margin:.25rem !important}.m-lg-2{margin:.5rem !important}.m-lg-3{margin:1rem !important}.m-lg-4{margin:1.5rem !important}.m-lg-5{margin:3rem !important}.m-lg-auto{margin:auto !important}.mx-lg-0{margin-right:0 !important;margin-left:0 !important}.mx-lg-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-lg-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-lg-3{margin-right:1rem !important;margin-left:1rem !important}.mx-lg-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-lg-5{margin-right:3rem !important;margin-left:3rem !important}.mx-lg-auto{margin-right:auto !important;margin-left:auto !important}.my-lg-0{margin-top:0 !important;margin-bottom:0 !important}.my-lg-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-lg-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-lg-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-lg-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-lg-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-lg-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-lg-0{margin-top:0 !important}.mt-lg-1{margin-top:.25rem !important}.mt-lg-2{margin-top:.5rem !important}.mt-lg-3{margin-top:1rem !important}.mt-lg-4{margin-top:1.5rem !important}.mt-lg-5{margin-top:3rem !important}.mt-lg-auto{margin-top:auto !important}.me-lg-0{margin-right:0 !important}.me-lg-1{margin-right:.25rem !important}.me-lg-2{margin-right:.5rem !important}.me-lg-3{margin-right:1rem !important}.me-lg-4{margin-right:1.5rem !important}.me-lg-5{margin-right:3rem !important}.me-lg-auto{margin-right:auto !important}.mb-lg-0{margin-bottom:0 !important}.mb-lg-1{margin-bottom:.25rem !important}.mb-lg-2{margin-bottom:.5rem !important}.mb-lg-3{margin-bottom:1rem !important}.mb-lg-4{margin-bottom:1.5rem !important}.mb-lg-5{margin-bottom:3rem !important}.mb-lg-auto{margin-bottom:auto !important}.ms-lg-0{margin-left:0 !important}.ms-lg-1{margin-left:.25rem !important}.ms-lg-2{margin-left:.5rem !important}.ms-lg-3{margin-left:1rem !important}.ms-lg-4{margin-left:1.5rem !important}.ms-lg-5{margin-left:3rem !important}.ms-lg-auto{margin-left:auto !important}.p-lg-0{padding:0 !important}.p-lg-1{padding:.25rem !important}.p-lg-2{padding:.5rem !important}.p-lg-3{padding:1rem !important}.p-lg-4{padding:1.5rem !important}.p-lg-5{padding:3rem !important}.px-lg-0{padding-right:0 !important;padding-left:0 !important}.px-lg-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-lg-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-lg-3{padding-right:1rem !important;padding-left:1rem !important}.px-lg-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-lg-5{padding-right:3rem !important;padding-left:3rem !important}.py-lg-0{padding-top:0 !important;padding-bottom:0 !important}.py-lg-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-lg-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-lg-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-lg-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-lg-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-lg-0{padding-top:0 !important}.pt-lg-1{padding-top:.25rem !important}.pt-lg-2{padding-top:.5rem !important}.pt-lg-3{padding-top:1rem !important}.pt-lg-4{padding-top:1.5rem !important}.pt-lg-5{padding-top:3rem !important}.pe-lg-0{padding-right:0 !important}.pe-lg-1{padding-right:.25rem !important}.pe-lg-2{padding-right:.5rem !important}.pe-lg-3{padding-right:1rem !important}.pe-lg-4{padding-right:1.5rem !important}.pe-lg-5{padding-right:3rem !important}.pb-lg-0{padding-bottom:0 !important}.pb-lg-1{padding-bottom:.25rem !important}.pb-lg-2{padding-bottom:.5rem !important}.pb-lg-3{padding-bottom:1rem !important}.pb-lg-4{padding-bottom:1.5rem !important}.pb-lg-5{padding-bottom:3rem !important}.ps-lg-0{padding-left:0 !important}.ps-lg-1{padding-left:.25rem !important}.ps-lg-2{padding-left:.5rem !important}.ps-lg-3{padding-left:1rem !important}.ps-lg-4{padding-left:1.5rem !important}.ps-lg-5{padding-left:3rem !important}.text-lg-start{text-align:left !important}.text-lg-end{text-align:right !important}.text-lg-center{text-align:center !important}}@media (min-width: 1200px){.float-xl-start{float:left !important}.float-xl-end{float:right !important}.float-xl-none{float:none !important}.d-xl-inline{display:inline !important}.d-xl-inline-block{display:inline-block !important}.d-xl-block{display:block !important}.d-xl-grid{display:grid !important}.d-xl-table{display:table !important}.d-xl-table-row{display:table-row !important}.d-xl-table-cell{display:table-cell !important}.d-xl-flex{display:flex !important}.d-xl-inline-flex{display:inline-flex !important}.d-xl-none{display:none !important}.flex-xl-fill{flex:1 1 auto !important}.flex-xl-row{flex-direction:row !important}.flex-xl-column{flex-direction:column !important}.flex-xl-row-reverse{flex-direction:row-reverse !important}.flex-xl-column-reverse{flex-direction:column-reverse !important}.flex-xl-grow-0{flex-grow:0 !important}.flex-xl-grow-1{flex-grow:1 !important}.flex-xl-shrink-0{flex-shrink:0 !important}.flex-xl-shrink-1{flex-shrink:1 !important}.flex-xl-wrap{flex-wrap:wrap !important}.flex-xl-nowrap{flex-wrap:nowrap !important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-xl-0{gap:0 !important}.gap-xl-1{gap:.25rem !important}.gap-xl-2{gap:.5rem !important}.gap-xl-3{gap:1rem !important}.gap-xl-4{gap:1.5rem !important}.gap-xl-5{gap:3rem !important}.justify-content-xl-start{justify-content:flex-start !important}.justify-content-xl-end{justify-content:flex-end !important}.justify-content-xl-center{justify-content:center !important}.justify-content-xl-between{justify-content:space-between !important}.justify-content-xl-around{justify-content:space-around !important}.justify-content-xl-evenly{justify-content:space-evenly !important}.align-items-xl-start{align-items:flex-start !important}.align-items-xl-end{align-items:flex-end !important}.align-items-xl-center{align-items:center !important}.align-items-xl-baseline{align-items:baseline !important}.align-items-xl-stretch{align-items:stretch !important}.align-content-xl-start{align-content:flex-start !important}.align-content-xl-end{align-content:flex-end !important}.align-content-xl-center{align-content:center !important}.align-content-xl-between{align-content:space-between !important}.align-content-xl-around{align-content:space-around !important}.align-content-xl-stretch{align-content:stretch !important}.align-self-xl-auto{align-self:auto !important}.align-self-xl-start{align-self:flex-start !important}.align-self-xl-end{align-self:flex-end !important}.align-self-xl-center{align-self:center !important}.align-self-xl-baseline{align-self:baseline !important}.align-self-xl-stretch{align-self:stretch !important}.order-xl-first{order:-1 !important}.order-xl-0{order:0 !important}.order-xl-1{order:1 !important}.order-xl-2{order:2 !important}.order-xl-3{order:3 !important}.order-xl-4{order:4 !important}.order-xl-5{order:5 !important}.order-xl-last{order:6 !important}.m-xl-0{margin:0 !important}.m-xl-1{margin:.25rem !important}.m-xl-2{margin:.5rem !important}.m-xl-3{margin:1rem !important}.m-xl-4{margin:1.5rem !important}.m-xl-5{margin:3rem !important}.m-xl-auto{margin:auto !important}.mx-xl-0{margin-right:0 !important;margin-left:0 !important}.mx-xl-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-xl-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-xl-3{margin-right:1rem !important;margin-left:1rem !important}.mx-xl-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-xl-5{margin-right:3rem !important;margin-left:3rem !important}.mx-xl-auto{margin-right:auto !important;margin-left:auto !important}.my-xl-0{margin-top:0 !important;margin-bottom:0 !important}.my-xl-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-xl-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-xl-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-xl-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-xl-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-xl-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-xl-0{margin-top:0 !important}.mt-xl-1{margin-top:.25rem !important}.mt-xl-2{margin-top:.5rem !important}.mt-xl-3{margin-top:1rem !important}.mt-xl-4{margin-top:1.5rem !important}.mt-xl-5{margin-top:3rem !important}.mt-xl-auto{margin-top:auto !important}.me-xl-0{margin-right:0 !important}.me-xl-1{margin-right:.25rem !important}.me-xl-2{margin-right:.5rem !important}.me-xl-3{margin-right:1rem !important}.me-xl-4{margin-right:1.5rem !important}.me-xl-5{margin-right:3rem !important}.me-xl-auto{margin-right:auto !important}.mb-xl-0{margin-bottom:0 !important}.mb-xl-1{margin-bottom:.25rem !important}.mb-xl-2{margin-bottom:.5rem !important}.mb-xl-3{margin-bottom:1rem !important}.mb-xl-4{margin-bottom:1.5rem !important}.mb-xl-5{margin-bottom:3rem !important}.mb-xl-auto{margin-bottom:auto !important}.ms-xl-0{margin-left:0 !important}.ms-xl-1{margin-left:.25rem !important}.ms-xl-2{margin-left:.5rem !important}.ms-xl-3{margin-left:1rem !important}.ms-xl-4{margin-left:1.5rem !important}.ms-xl-5{margin-left:3rem !important}.ms-xl-auto{margin-left:auto !important}.p-xl-0{padding:0 !important}.p-xl-1{padding:.25rem !important}.p-xl-2{padding:.5rem !important}.p-xl-3{padding:1rem !important}.p-xl-4{padding:1.5rem !important}.p-xl-5{padding:3rem !important}.px-xl-0{padding-right:0 !important;padding-left:0 !important}.px-xl-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-xl-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-xl-3{padding-right:1rem !important;padding-left:1rem !important}.px-xl-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-xl-5{padding-right:3rem !important;padding-left:3rem !important}.py-xl-0{padding-top:0 !important;padding-bottom:0 !important}.py-xl-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-xl-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-xl-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-xl-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-xl-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-xl-0{padding-top:0 !important}.pt-xl-1{padding-top:.25rem !important}.pt-xl-2{padding-top:.5rem !important}.pt-xl-3{padding-top:1rem !important}.pt-xl-4{padding-top:1.5rem !important}.pt-xl-5{padding-top:3rem !important}.pe-xl-0{padding-right:0 !important}.pe-xl-1{padding-right:.25rem !important}.pe-xl-2{padding-right:.5rem !important}.pe-xl-3{padding-right:1rem !important}.pe-xl-4{padding-right:1.5rem !important}.pe-xl-5{padding-right:3rem !important}.pb-xl-0{padding-bottom:0 !important}.pb-xl-1{padding-bottom:.25rem !important}.pb-xl-2{padding-bottom:.5rem !important}.pb-xl-3{padding-bottom:1rem !important}.pb-xl-4{padding-bottom:1.5rem !important}.pb-xl-5{padding-bottom:3rem !important}.ps-xl-0{padding-left:0 !important}.ps-xl-1{padding-left:.25rem !important}.ps-xl-2{padding-left:.5rem !important}.ps-xl-3{padding-left:1rem !important}.ps-xl-4{padding-left:1.5rem !important}.ps-xl-5{padding-left:3rem !important}.text-xl-start{text-align:left !important}.text-xl-end{text-align:right !important}.text-xl-center{text-align:center !important}}@media (min-width: 1400px){.float-xxl-start{float:left !important}.float-xxl-end{float:right !important}.float-xxl-none{float:none !important}.d-xxl-inline{display:inline !important}.d-xxl-inline-block{display:inline-block !important}.d-xxl-block{display:block !important}.d-xxl-grid{display:grid !important}.d-xxl-table{display:table !important}.d-xxl-table-row{display:table-row !important}.d-xxl-table-cell{display:table-cell !important}.d-xxl-flex{display:flex !important}.d-xxl-inline-flex{display:inline-flex !important}.d-xxl-none{display:none !important}.flex-xxl-fill{flex:1 1 auto !important}.flex-xxl-row{flex-direction:row !important}.flex-xxl-column{flex-direction:column !important}.flex-xxl-row-reverse{flex-direction:row-reverse !important}.flex-xxl-column-reverse{flex-direction:column-reverse !important}.flex-xxl-grow-0{flex-grow:0 !important}.flex-xxl-grow-1{flex-grow:1 !important}.flex-xxl-shrink-0{flex-shrink:0 !important}.flex-xxl-shrink-1{flex-shrink:1 !important}.flex-xxl-wrap{flex-wrap:wrap !important}.flex-xxl-nowrap{flex-wrap:nowrap !important}.flex-xxl-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-xxl-0{gap:0 !important}.gap-xxl-1{gap:.25rem !important}.gap-xxl-2{gap:.5rem !important}.gap-xxl-3{gap:1rem !important}.gap-xxl-4{gap:1.5rem !important}.gap-xxl-5{gap:3rem !important}.justify-content-xxl-start{justify-content:flex-start !important}.justify-content-xxl-end{justify-content:flex-end !important}.justify-content-xxl-center{justify-content:center !important}.justify-content-xxl-between{justify-content:space-between !important}.justify-content-xxl-around{justify-content:space-around !important}.justify-content-xxl-evenly{justify-content:space-evenly !important}.align-items-xxl-start{align-items:flex-start !important}.align-items-xxl-end{align-items:flex-end !important}.align-items-xxl-center{align-items:center !important}.align-items-xxl-baseline{align-items:baseline !important}.align-items-xxl-stretch{align-items:stretch !important}.align-content-xxl-start{align-content:flex-start !important}.align-content-xxl-end{align-content:flex-end !important}.align-content-xxl-center{align-content:center !important}.align-content-xxl-between{align-content:space-between !important}.align-content-xxl-around{align-content:space-around !important}.align-content-xxl-stretch{align-content:stretch !important}.align-self-xxl-auto{align-self:auto !important}.align-self-xxl-start{align-self:flex-start !important}.align-self-xxl-end{align-self:flex-end !important}.align-self-xxl-center{align-self:center !important}.align-self-xxl-baseline{align-self:baseline !important}.align-self-xxl-stretch{align-self:stretch !important}.order-xxl-first{order:-1 !important}.order-xxl-0{order:0 !important}.order-xxl-1{order:1 !important}.order-xxl-2{order:2 !important}.order-xxl-3{order:3 !important}.order-xxl-4{order:4 !important}.order-xxl-5{order:5 !important}.order-xxl-last{order:6 !important}.m-xxl-0{margin:0 !important}.m-xxl-1{margin:.25rem !important}.m-xxl-2{margin:.5rem !important}.m-xxl-3{margin:1rem !important}.m-xxl-4{margin:1.5rem !important}.m-xxl-5{margin:3rem !important}.m-xxl-auto{margin:auto !important}.mx-xxl-0{margin-right:0 !important;margin-left:0 !important}.mx-xxl-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-xxl-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-xxl-3{margin-right:1rem !important;margin-left:1rem !important}.mx-xxl-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-xxl-5{margin-right:3rem !important;margin-left:3rem !important}.mx-xxl-auto{margin-right:auto !important;margin-left:auto !important}.my-xxl-0{margin-top:0 !important;margin-bottom:0 !important}.my-xxl-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-xxl-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-xxl-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-xxl-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-xxl-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-xxl-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-xxl-0{margin-top:0 !important}.mt-xxl-1{margin-top:.25rem !important}.mt-xxl-2{margin-top:.5rem !important}.mt-xxl-3{margin-top:1rem !important}.mt-xxl-4{margin-top:1.5rem !important}.mt-xxl-5{margin-top:3rem !important}.mt-xxl-auto{margin-top:auto !important}.me-xxl-0{margin-right:0 !important}.me-xxl-1{margin-right:.25rem !important}.me-xxl-2{margin-right:.5rem !important}.me-xxl-3{margin-right:1rem !important}.me-xxl-4{margin-right:1.5rem !important}.me-xxl-5{margin-right:3rem !important}.me-xxl-auto{margin-right:auto !important}.mb-xxl-0{margin-bottom:0 !important}.mb-xxl-1{margin-bottom:.25rem !important}.mb-xxl-2{margin-bottom:.5rem !important}.mb-xxl-3{margin-bottom:1rem !important}.mb-xxl-4{margin-bottom:1.5rem !important}.mb-xxl-5{margin-bottom:3rem !important}.mb-xxl-auto{margin-bottom:auto !important}.ms-xxl-0{margin-left:0 !important}.ms-xxl-1{margin-left:.25rem !important}.ms-xxl-2{margin-left:.5rem !important}.ms-xxl-3{margin-left:1rem !important}.ms-xxl-4{margin-left:1.5rem !important}.ms-xxl-5{margin-left:3rem !important}.ms-xxl-auto{margin-left:auto !important}.p-xxl-0{padding:0 !important}.p-xxl-1{padding:.25rem !important}.p-xxl-2{padding:.5rem !important}.p-xxl-3{padding:1rem !important}.p-xxl-4{padding:1.5rem !important}.p-xxl-5{padding:3rem !important}.px-xxl-0{padding-right:0 !important;padding-left:0 !important}.px-xxl-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-xxl-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-xxl-3{padding-right:1rem !important;padding-left:1rem !important}.px-xxl-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-xxl-5{padding-right:3rem !important;padding-left:3rem !important}.py-xxl-0{padding-top:0 !important;padding-bottom:0 !important}.py-xxl-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-xxl-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-xxl-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-xxl-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-xxl-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-xxl-0{padding-top:0 !important}.pt-xxl-1{padding-top:.25rem !important}.pt-xxl-2{padding-top:.5rem !important}.pt-xxl-3{padding-top:1rem !important}.pt-xxl-4{padding-top:1.5rem !important}.pt-xxl-5{padding-top:3rem !important}.pe-xxl-0{padding-right:0 !important}.pe-xxl-1{padding-right:.25rem !important}.pe-xxl-2{padding-right:.5rem !important}.pe-xxl-3{padding-right:1rem !important}.pe-xxl-4{padding-right:1.5rem !important}.pe-xxl-5{padding-right:3rem !important}.pb-xxl-0{padding-bottom:0 !important}.pb-xxl-1{padding-bottom:.25rem !important}.pb-xxl-2{padding-bottom:.5rem !important}.pb-xxl-3{padding-bottom:1rem !important}.pb-xxl-4{padding-bottom:1.5rem !important}.pb-xxl-5{padding-bottom:3rem !important}.ps-xxl-0{padding-left:0 !important}.ps-xxl-1{padding-left:.25rem !important}.ps-xxl-2{padding-left:.5rem !important}.ps-xxl-3{padding-left:1rem !important}.ps-xxl-4{padding-left:1.5rem !important}.ps-xxl-5{padding-left:3rem !important}.text-xxl-start{text-align:left !important}.text-xxl-end{text-align:right !important}.text-xxl-center{text-align:center !important}}@media (min-width: 1200px){.fs-1{font-size:2.5rem !important}.fs-2{font-size:2rem !important}.fs-3{font-size:1.75rem !important}.fs-4{font-size:1.5rem !important}}@media print{.d-print-inline{display:inline !important}.d-print-inline-block{display:inline-block !important}.d-print-block{display:block !important}.d-print-grid{display:grid !important}.d-print-table{display:table !important}.d-print-table-row{display:table-row !important}.d-print-table-cell{display:table-cell !important}.d-print-flex{display:flex !important}.d-print-inline-flex{display:inline-flex !important}.d-print-none{display:none !important}} \ No newline at end of file diff --git a/bootstrap/scss/bootstrap.css b/bootstrap/scss/bootstrap.css new file mode 100644 index 0000000000..824c460095 --- /dev/null +++ b/bootstrap/scss/bootstrap.css @@ -0,0 +1,6 @@ +/*! + * Bootstrap v5.0.0-beta3 (https://getbootstrap.com/) + * Copyright 2011-2021 The Bootstrap Authors + * Copyright 2011-2021 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */:root{--bs-blue: #0d6efd;--bs-indigo: #6610f2;--bs-purple: #6f42c1;--bs-pink: #d63384;--bs-red: #dc3545;--bs-orange: #fd7e14;--bs-yellow: #ffc107;--bs-green: #198754;--bs-teal: #20c997;--bs-cyan: #0dcaf0;--bs-white: #fff;--bs-gray: #6c757d;--bs-gray-dark: #343a40;--bs-primary: #0d6efd;--bs-secondary: #6c757d;--bs-success: #198754;--bs-info: #0dcaf0;--bs-warning: #ffc107;--bs-danger: #dc3545;--bs-light: #f8f9fa;--bs-dark: #212529;--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--bs-gradient: linear-gradient(180deg, rgba(255,255,255,.15), rgba(255,255,255,0))}*,*::before,*::after{box-sizing:border-box}@media (prefers-reduced-motion: no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-font-sans-serif);font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h6,.h6,h5,.h5,h4,.h4,h3,.h3,h2,.h2,h1,.h1{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1,.h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width: 1200px){h1,.h1{font-size:2.5rem}}h2,.h2{font-size:calc(1.325rem + .9vw)}@media (min-width: 1200px){h2,.h2{font-size:2rem}}h3,.h3{font-size:calc(1.3rem + .6vw)}@media (min-width: 1200px){h3,.h3{font-size:1.75rem}}h4,.h4{font-size:calc(1.275rem + .3vw)}@media (min-width: 1200px){h4,.h4{font-size:1.5rem}}h5,.h5{font-size:1.25rem}h6,.h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[title],abbr[data-bs-original-title]{text-decoration:underline dotted;cursor:help;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}ol,ul,dl{margin-top:0;margin-bottom:1rem}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small,.small{font-size:.875em}mark,.mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}pre,code,kbd,samp{font-family:var(--bs-font-monospace);font-size:1em;direction:ltr /* rtl:ignore */;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}thead,tbody,tfoot,tr,td,th{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}input,button,select,optgroup,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button:not(:disabled),[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width: 1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-text,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none !important}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:calc(1.625rem + 4.5vw);font-weight:300;line-height:1.2}@media (min-width: 1200px){.display-1{font-size:5rem}}.display-2{font-size:calc(1.575rem + 3.9vw);font-weight:300;line-height:1.2}@media (min-width: 1200px){.display-2{font-size:4.5rem}}.display-3{font-size:calc(1.525rem + 3.3vw);font-weight:300;line-height:1.2}@media (min-width: 1200px){.display-3{font-size:4rem}}.display-4{font-size:calc(1.475rem + 2.7vw);font-weight:300;line-height:1.2}@media (min-width: 1200px){.display-4{font-size:3.5rem}}.display-5{font-size:calc(1.425rem + 2.1vw);font-weight:300;line-height:1.2}@media (min-width: 1200px){.display-5{font-size:3rem}}.display-6{font-size:calc(1.375rem + 1.5vw);font-weight:300;line-height:1.2}@media (min-width: 1200px){.display-6{font-size:2.5rem}}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:.875em;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote>:last-child{margin-bottom:0}.blockquote-footer{margin-top:-1rem;margin-bottom:1rem;font-size:.875em;color:#6c757d}.blockquote-footer::before{content:"— "}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:.875em;color:#6c757d}.container,.container-fluid,.container-xxl,.container-xl,.container-lg,.container-md,.container-sm{width:100%;padding-right:var(--bs-gutter-x, .75rem);padding-left:var(--bs-gutter-x, .75rem);margin-right:auto;margin-left:auto}@media (min-width: 576px){.container-sm,.container{max-width:540px}}@media (min-width: 768px){.container-md,.container-sm,.container{max-width:720px}}@media (min-width: 992px){.container-lg,.container-md,.container-sm,.container{max-width:960px}}@media (min-width: 1200px){.container-xl,.container-lg,.container-md,.container-sm,.container{max-width:1140px}}@media (min-width: 1400px){.container-xxl,.container-xl,.container-lg,.container-md,.container-sm,.container{max-width:1320px}}.row{--bs-gutter-x: 1.5rem;--bs-gutter-y: 0;display:flex;flex-wrap:wrap;margin-top:calc(var(--bs-gutter-y)*-1);margin-right:calc(var(--bs-gutter-x)/-2);margin-left:calc(var(--bs-gutter-x)/-2)}.row>*{flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--bs-gutter-x)/2);padding-left:calc(var(--bs-gutter-x)/2);margin-top:var(--bs-gutter-y)}.col{flex:1 0 0%}.row-cols-auto>*{flex:0 0 auto;width:auto}.row-cols-1>*{flex:0 0 auto;width:100%}.row-cols-2>*{flex:0 0 auto;width:50%}.row-cols-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-4>*{flex:0 0 auto;width:25%}.row-cols-5>*{flex:0 0 auto;width:20%}.row-cols-6>*{flex:0 0 auto;width:16.6666666667%}.col-auto{flex:0 0 auto;width:auto}.col-1{flex:0 0 auto;width:8.3333333333%}.col-2{flex:0 0 auto;width:16.6666666667%}.col-3{flex:0 0 auto;width:25%}.col-4{flex:0 0 auto;width:33.3333333333%}.col-5{flex:0 0 auto;width:41.6666666667%}.col-6{flex:0 0 auto;width:50%}.col-7{flex:0 0 auto;width:58.3333333333%}.col-8{flex:0 0 auto;width:66.6666666667%}.col-9{flex:0 0 auto;width:75%}.col-10{flex:0 0 auto;width:83.3333333333%}.col-11{flex:0 0 auto;width:91.6666666667%}.col-12{flex:0 0 auto;width:100%}.offset-1{margin-left:8.3333333333%}.offset-2{margin-left:16.6666666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.3333333333%}.offset-5{margin-left:41.6666666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.3333333333%}.offset-8{margin-left:66.6666666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.3333333333%}.offset-11{margin-left:91.6666666667%}.g-0,.gx-0{--bs-gutter-x: 0}.g-0,.gy-0{--bs-gutter-y: 0}.g-1,.gx-1{--bs-gutter-x: .25rem}.g-1,.gy-1{--bs-gutter-y: .25rem}.g-2,.gx-2{--bs-gutter-x: .5rem}.g-2,.gy-2{--bs-gutter-y: .5rem}.g-3,.gx-3{--bs-gutter-x: 1rem}.g-3,.gy-3{--bs-gutter-y: 1rem}.g-4,.gx-4{--bs-gutter-x: 1.5rem}.g-4,.gy-4{--bs-gutter-y: 1.5rem}.g-5,.gx-5{--bs-gutter-x: 3rem}.g-5,.gy-5{--bs-gutter-y: 3rem}@media (min-width: 576px){.col-sm{flex:1 0 0%}.row-cols-sm-auto>*{flex:0 0 auto;width:auto}.row-cols-sm-1>*{flex:0 0 auto;width:100%}.row-cols-sm-2>*{flex:0 0 auto;width:50%}.row-cols-sm-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-sm-4>*{flex:0 0 auto;width:25%}.row-cols-sm-5>*{flex:0 0 auto;width:20%}.row-cols-sm-6>*{flex:0 0 auto;width:16.6666666667%}.col-sm-auto{flex:0 0 auto;width:auto}.col-sm-1{flex:0 0 auto;width:8.3333333333%}.col-sm-2{flex:0 0 auto;width:16.6666666667%}.col-sm-3{flex:0 0 auto;width:25%}.col-sm-4{flex:0 0 auto;width:33.3333333333%}.col-sm-5{flex:0 0 auto;width:41.6666666667%}.col-sm-6{flex:0 0 auto;width:50%}.col-sm-7{flex:0 0 auto;width:58.3333333333%}.col-sm-8{flex:0 0 auto;width:66.6666666667%}.col-sm-9{flex:0 0 auto;width:75%}.col-sm-10{flex:0 0 auto;width:83.3333333333%}.col-sm-11{flex:0 0 auto;width:91.6666666667%}.col-sm-12{flex:0 0 auto;width:100%}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.3333333333%}.offset-sm-2{margin-left:16.6666666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.3333333333%}.offset-sm-5{margin-left:41.6666666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.3333333333%}.offset-sm-8{margin-left:66.6666666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.3333333333%}.offset-sm-11{margin-left:91.6666666667%}.g-sm-0,.gx-sm-0{--bs-gutter-x: 0}.g-sm-0,.gy-sm-0{--bs-gutter-y: 0}.g-sm-1,.gx-sm-1{--bs-gutter-x: .25rem}.g-sm-1,.gy-sm-1{--bs-gutter-y: .25rem}.g-sm-2,.gx-sm-2{--bs-gutter-x: .5rem}.g-sm-2,.gy-sm-2{--bs-gutter-y: .5rem}.g-sm-3,.gx-sm-3{--bs-gutter-x: 1rem}.g-sm-3,.gy-sm-3{--bs-gutter-y: 1rem}.g-sm-4,.gx-sm-4{--bs-gutter-x: 1.5rem}.g-sm-4,.gy-sm-4{--bs-gutter-y: 1.5rem}.g-sm-5,.gx-sm-5{--bs-gutter-x: 3rem}.g-sm-5,.gy-sm-5{--bs-gutter-y: 3rem}}@media (min-width: 768px){.col-md{flex:1 0 0%}.row-cols-md-auto>*{flex:0 0 auto;width:auto}.row-cols-md-1>*{flex:0 0 auto;width:100%}.row-cols-md-2>*{flex:0 0 auto;width:50%}.row-cols-md-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-md-4>*{flex:0 0 auto;width:25%}.row-cols-md-5>*{flex:0 0 auto;width:20%}.row-cols-md-6>*{flex:0 0 auto;width:16.6666666667%}.col-md-auto{flex:0 0 auto;width:auto}.col-md-1{flex:0 0 auto;width:8.3333333333%}.col-md-2{flex:0 0 auto;width:16.6666666667%}.col-md-3{flex:0 0 auto;width:25%}.col-md-4{flex:0 0 auto;width:33.3333333333%}.col-md-5{flex:0 0 auto;width:41.6666666667%}.col-md-6{flex:0 0 auto;width:50%}.col-md-7{flex:0 0 auto;width:58.3333333333%}.col-md-8{flex:0 0 auto;width:66.6666666667%}.col-md-9{flex:0 0 auto;width:75%}.col-md-10{flex:0 0 auto;width:83.3333333333%}.col-md-11{flex:0 0 auto;width:91.6666666667%}.col-md-12{flex:0 0 auto;width:100%}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.3333333333%}.offset-md-2{margin-left:16.6666666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.3333333333%}.offset-md-5{margin-left:41.6666666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.3333333333%}.offset-md-8{margin-left:66.6666666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.3333333333%}.offset-md-11{margin-left:91.6666666667%}.g-md-0,.gx-md-0{--bs-gutter-x: 0}.g-md-0,.gy-md-0{--bs-gutter-y: 0}.g-md-1,.gx-md-1{--bs-gutter-x: .25rem}.g-md-1,.gy-md-1{--bs-gutter-y: .25rem}.g-md-2,.gx-md-2{--bs-gutter-x: .5rem}.g-md-2,.gy-md-2{--bs-gutter-y: .5rem}.g-md-3,.gx-md-3{--bs-gutter-x: 1rem}.g-md-3,.gy-md-3{--bs-gutter-y: 1rem}.g-md-4,.gx-md-4{--bs-gutter-x: 1.5rem}.g-md-4,.gy-md-4{--bs-gutter-y: 1.5rem}.g-md-5,.gx-md-5{--bs-gutter-x: 3rem}.g-md-5,.gy-md-5{--bs-gutter-y: 3rem}}@media (min-width: 992px){.col-lg{flex:1 0 0%}.row-cols-lg-auto>*{flex:0 0 auto;width:auto}.row-cols-lg-1>*{flex:0 0 auto;width:100%}.row-cols-lg-2>*{flex:0 0 auto;width:50%}.row-cols-lg-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-lg-4>*{flex:0 0 auto;width:25%}.row-cols-lg-5>*{flex:0 0 auto;width:20%}.row-cols-lg-6>*{flex:0 0 auto;width:16.6666666667%}.col-lg-auto{flex:0 0 auto;width:auto}.col-lg-1{flex:0 0 auto;width:8.3333333333%}.col-lg-2{flex:0 0 auto;width:16.6666666667%}.col-lg-3{flex:0 0 auto;width:25%}.col-lg-4{flex:0 0 auto;width:33.3333333333%}.col-lg-5{flex:0 0 auto;width:41.6666666667%}.col-lg-6{flex:0 0 auto;width:50%}.col-lg-7{flex:0 0 auto;width:58.3333333333%}.col-lg-8{flex:0 0 auto;width:66.6666666667%}.col-lg-9{flex:0 0 auto;width:75%}.col-lg-10{flex:0 0 auto;width:83.3333333333%}.col-lg-11{flex:0 0 auto;width:91.6666666667%}.col-lg-12{flex:0 0 auto;width:100%}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.3333333333%}.offset-lg-2{margin-left:16.6666666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.3333333333%}.offset-lg-5{margin-left:41.6666666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.3333333333%}.offset-lg-8{margin-left:66.6666666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.3333333333%}.offset-lg-11{margin-left:91.6666666667%}.g-lg-0,.gx-lg-0{--bs-gutter-x: 0}.g-lg-0,.gy-lg-0{--bs-gutter-y: 0}.g-lg-1,.gx-lg-1{--bs-gutter-x: .25rem}.g-lg-1,.gy-lg-1{--bs-gutter-y: .25rem}.g-lg-2,.gx-lg-2{--bs-gutter-x: .5rem}.g-lg-2,.gy-lg-2{--bs-gutter-y: .5rem}.g-lg-3,.gx-lg-3{--bs-gutter-x: 1rem}.g-lg-3,.gy-lg-3{--bs-gutter-y: 1rem}.g-lg-4,.gx-lg-4{--bs-gutter-x: 1.5rem}.g-lg-4,.gy-lg-4{--bs-gutter-y: 1.5rem}.g-lg-5,.gx-lg-5{--bs-gutter-x: 3rem}.g-lg-5,.gy-lg-5{--bs-gutter-y: 3rem}}@media (min-width: 1200px){.col-xl{flex:1 0 0%}.row-cols-xl-auto>*{flex:0 0 auto;width:auto}.row-cols-xl-1>*{flex:0 0 auto;width:100%}.row-cols-xl-2>*{flex:0 0 auto;width:50%}.row-cols-xl-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-xl-4>*{flex:0 0 auto;width:25%}.row-cols-xl-5>*{flex:0 0 auto;width:20%}.row-cols-xl-6>*{flex:0 0 auto;width:16.6666666667%}.col-xl-auto{flex:0 0 auto;width:auto}.col-xl-1{flex:0 0 auto;width:8.3333333333%}.col-xl-2{flex:0 0 auto;width:16.6666666667%}.col-xl-3{flex:0 0 auto;width:25%}.col-xl-4{flex:0 0 auto;width:33.3333333333%}.col-xl-5{flex:0 0 auto;width:41.6666666667%}.col-xl-6{flex:0 0 auto;width:50%}.col-xl-7{flex:0 0 auto;width:58.3333333333%}.col-xl-8{flex:0 0 auto;width:66.6666666667%}.col-xl-9{flex:0 0 auto;width:75%}.col-xl-10{flex:0 0 auto;width:83.3333333333%}.col-xl-11{flex:0 0 auto;width:91.6666666667%}.col-xl-12{flex:0 0 auto;width:100%}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.3333333333%}.offset-xl-2{margin-left:16.6666666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.3333333333%}.offset-xl-5{margin-left:41.6666666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.3333333333%}.offset-xl-8{margin-left:66.6666666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.3333333333%}.offset-xl-11{margin-left:91.6666666667%}.g-xl-0,.gx-xl-0{--bs-gutter-x: 0}.g-xl-0,.gy-xl-0{--bs-gutter-y: 0}.g-xl-1,.gx-xl-1{--bs-gutter-x: .25rem}.g-xl-1,.gy-xl-1{--bs-gutter-y: .25rem}.g-xl-2,.gx-xl-2{--bs-gutter-x: .5rem}.g-xl-2,.gy-xl-2{--bs-gutter-y: .5rem}.g-xl-3,.gx-xl-3{--bs-gutter-x: 1rem}.g-xl-3,.gy-xl-3{--bs-gutter-y: 1rem}.g-xl-4,.gx-xl-4{--bs-gutter-x: 1.5rem}.g-xl-4,.gy-xl-4{--bs-gutter-y: 1.5rem}.g-xl-5,.gx-xl-5{--bs-gutter-x: 3rem}.g-xl-5,.gy-xl-5{--bs-gutter-y: 3rem}}@media (min-width: 1400px){.col-xxl{flex:1 0 0%}.row-cols-xxl-auto>*{flex:0 0 auto;width:auto}.row-cols-xxl-1>*{flex:0 0 auto;width:100%}.row-cols-xxl-2>*{flex:0 0 auto;width:50%}.row-cols-xxl-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-xxl-4>*{flex:0 0 auto;width:25%}.row-cols-xxl-5>*{flex:0 0 auto;width:20%}.row-cols-xxl-6>*{flex:0 0 auto;width:16.6666666667%}.col-xxl-auto{flex:0 0 auto;width:auto}.col-xxl-1{flex:0 0 auto;width:8.3333333333%}.col-xxl-2{flex:0 0 auto;width:16.6666666667%}.col-xxl-3{flex:0 0 auto;width:25%}.col-xxl-4{flex:0 0 auto;width:33.3333333333%}.col-xxl-5{flex:0 0 auto;width:41.6666666667%}.col-xxl-6{flex:0 0 auto;width:50%}.col-xxl-7{flex:0 0 auto;width:58.3333333333%}.col-xxl-8{flex:0 0 auto;width:66.6666666667%}.col-xxl-9{flex:0 0 auto;width:75%}.col-xxl-10{flex:0 0 auto;width:83.3333333333%}.col-xxl-11{flex:0 0 auto;width:91.6666666667%}.col-xxl-12{flex:0 0 auto;width:100%}.offset-xxl-0{margin-left:0}.offset-xxl-1{margin-left:8.3333333333%}.offset-xxl-2{margin-left:16.6666666667%}.offset-xxl-3{margin-left:25%}.offset-xxl-4{margin-left:33.3333333333%}.offset-xxl-5{margin-left:41.6666666667%}.offset-xxl-6{margin-left:50%}.offset-xxl-7{margin-left:58.3333333333%}.offset-xxl-8{margin-left:66.6666666667%}.offset-xxl-9{margin-left:75%}.offset-xxl-10{margin-left:83.3333333333%}.offset-xxl-11{margin-left:91.6666666667%}.g-xxl-0,.gx-xxl-0{--bs-gutter-x: 0}.g-xxl-0,.gy-xxl-0{--bs-gutter-y: 0}.g-xxl-1,.gx-xxl-1{--bs-gutter-x: .25rem}.g-xxl-1,.gy-xxl-1{--bs-gutter-y: .25rem}.g-xxl-2,.gx-xxl-2{--bs-gutter-x: .5rem}.g-xxl-2,.gy-xxl-2{--bs-gutter-y: .5rem}.g-xxl-3,.gx-xxl-3{--bs-gutter-x: 1rem}.g-xxl-3,.gy-xxl-3{--bs-gutter-y: 1rem}.g-xxl-4,.gx-xxl-4{--bs-gutter-x: 1.5rem}.g-xxl-4,.gy-xxl-4{--bs-gutter-y: 1.5rem}.g-xxl-5,.gx-xxl-5{--bs-gutter-x: 3rem}.g-xxl-5,.gy-xxl-5{--bs-gutter-y: 3rem}}.table{--bs-table-bg: rgba(0,0,0,0);--bs-table-striped-color: #212529;--bs-table-striped-bg: rgba(0,0,0,.05);--bs-table-active-color: #212529;--bs-table-active-bg: rgba(0,0,0,.1);--bs-table-hover-color: #212529;--bs-table-hover-bg: rgba(0,0,0,.075);width:100%;margin-bottom:1rem;color:#212529;vertical-align:top;border-color:#dee2e6}.table>:not(caption)>*>*{padding:.5rem .5rem;background-color:var(--bs-table-bg);border-bottom-width:1px;box-shadow:inset 0 0 0 9999px var(--bs-table-accent-bg)}.table>tbody{vertical-align:inherit}.table>thead{vertical-align:bottom}.table>:not(:last-child)>:last-child>*{border-bottom-color:currentColor}.caption-top{caption-side:top}.table-sm>:not(caption)>*>*{padding:.25rem .25rem}.table-bordered>:not(caption)>*{border-width:1px 0}.table-bordered>:not(caption)>*>*{border-width:0 1px}.table-borderless>:not(caption)>*>*{border-bottom-width:0}.table-striped>tbody>tr:nth-of-type(odd){--bs-table-accent-bg: var(--bs-table-striped-bg);color:var(--bs-table-striped-color)}.table-active{--bs-table-accent-bg: var(--bs-table-active-bg);color:var(--bs-table-active-color)}.table-hover>tbody>tr:hover{--bs-table-accent-bg: var(--bs-table-hover-bg);color:var(--bs-table-hover-color)}.table-primary{--bs-table-bg: #cfe2ff;--bs-table-striped-bg: #c5d7f2;--bs-table-striped-color: #000;--bs-table-active-bg: #bacbe6;--bs-table-active-color: #000;--bs-table-hover-bg: #bfd1ec;--bs-table-hover-color: #000;color:#000;border-color:#bacbe6}.table-secondary{--bs-table-bg: #e2e3e5;--bs-table-striped-bg: #d7d8da;--bs-table-striped-color: #000;--bs-table-active-bg: #cbccce;--bs-table-active-color: #000;--bs-table-hover-bg: #d1d2d4;--bs-table-hover-color: #000;color:#000;border-color:#cbccce}.table-success{--bs-table-bg: #d1e7dd;--bs-table-striped-bg: #c7dbd2;--bs-table-striped-color: #000;--bs-table-active-bg: #bcd0c7;--bs-table-active-color: #000;--bs-table-hover-bg: #c1d6cc;--bs-table-hover-color: #000;color:#000;border-color:#bcd0c7}.table-info{--bs-table-bg: #cff4fc;--bs-table-striped-bg: #c5e8ef;--bs-table-striped-color: #000;--bs-table-active-bg: #badce3;--bs-table-active-color: #000;--bs-table-hover-bg: #bfe2e9;--bs-table-hover-color: #000;color:#000;border-color:#badce3}.table-warning{--bs-table-bg: #fff3cd;--bs-table-striped-bg: #f2e7c3;--bs-table-striped-color: #000;--bs-table-active-bg: #e6dbb9;--bs-table-active-color: #000;--bs-table-hover-bg: #ece1be;--bs-table-hover-color: #000;color:#000;border-color:#e6dbb9}.table-danger{--bs-table-bg: #f8d7da;--bs-table-striped-bg: #eccccf;--bs-table-striped-color: #000;--bs-table-active-bg: #dfc2c4;--bs-table-active-color: #000;--bs-table-hover-bg: #e5c7ca;--bs-table-hover-color: #000;color:#000;border-color:#dfc2c4}.table-light{--bs-table-bg: #f8f9fa;--bs-table-striped-bg: #ecedee;--bs-table-striped-color: #000;--bs-table-active-bg: #dfe0e1;--bs-table-active-color: #000;--bs-table-hover-bg: #e5e6e7;--bs-table-hover-color: #000;color:#000;border-color:#dfe0e1}.table-dark{--bs-table-bg: #212529;--bs-table-striped-bg: #2c3034;--bs-table-striped-color: #fff;--bs-table-active-bg: #373b3e;--bs-table-active-color: #fff;--bs-table-hover-bg: #323539;--bs-table-hover-color: #fff;color:#fff;border-color:#373b3e}.table-responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media (max-width: 575.98px){.table-responsive-sm{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width: 767.98px){.table-responsive-md{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width: 991.98px){.table-responsive-lg{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width: 1199.98px){.table-responsive-xl{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width: 1399.98px){.table-responsive-xxl{overflow-x:auto;-webkit-overflow-scrolling:touch}}.form-label{margin-bottom:.5rem}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem}.form-text{margin-top:.25rem;font-size:.875em;color:#6c757d}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;appearance:none;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion: reduce){.form-control{transition:none}}.form-control[type=file]{overflow:hidden}.form-control[type=file]:not(:disabled):not([readonly]){cursor:pointer}.form-control:focus{color:#212529;background-color:#fff;border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-control::-webkit-date-and-time-value{height:1.5em}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}.form-control::file-selector-button{padding:.375rem .75rem;margin:-.375rem -.75rem;margin-inline-end:.75rem;color:#212529;background-color:#e9ecef;pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:1px;border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion: reduce){.form-control::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:#dde0e3}.form-control::-webkit-file-upload-button{padding:.375rem .75rem;margin:-.375rem -.75rem;margin-inline-end:.75rem;color:#212529;background-color:#e9ecef;pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:1px;border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion: reduce){.form-control::-webkit-file-upload-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button{background-color:#dde0e3}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;line-height:1.5;color:#212529;background-color:rgba(0,0,0,0);border:solid rgba(0,0,0,0);border-width:1px 0}.form-control-plaintext.form-control-sm,.form-control-plaintext.form-control-lg{padding-right:0;padding-left:0}.form-control-sm{min-height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.form-control-sm::file-selector-button{padding:.25rem .5rem;margin:-.25rem -.5rem;margin-inline-end:.5rem}.form-control-sm::-webkit-file-upload-button{padding:.25rem .5rem;margin:-.25rem -.5rem;margin-inline-end:.5rem}.form-control-lg{min-height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;border-radius:.3rem}.form-control-lg::file-selector-button{padding:.5rem 1rem;margin:-.5rem -1rem;margin-inline-end:1rem}.form-control-lg::-webkit-file-upload-button{padding:.5rem 1rem;margin:-.5rem -1rem;margin-inline-end:1rem}textarea.form-control{min-height:calc(1.5em + .75rem + 2px)}textarea.form-control-sm{min-height:calc(1.5em + .5rem + 2px)}textarea.form-control-lg{min-height:calc(1.5em + 1rem + 2px)}.form-control-color{max-width:3rem;height:auto;padding:.375rem}.form-control-color:not(:disabled):not([readonly]){cursor:pointer}.form-control-color::-moz-color-swatch{height:1.5em;border-radius:.25rem}.form-control-color::-webkit-color-swatch{height:1.5em;border-radius:.25rem}.form-select{display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:1px solid #ced4da;border-radius:.25rem;appearance:none}.form-select:focus{border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-select[multiple],.form-select[size]:not([size="1"]){padding-right:.75rem;background-image:none}.form-select:disabled{background-color:#e9ecef}.form-select:-moz-focusring{color:rgba(0,0,0,0);text-shadow:0 0 0 #212529}.form-select-sm{padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.form-select-lg{padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.form-check{display:block;min-height:1.5rem;padding-left:1.5em;margin-bottom:.125rem}.form-check .form-check-input{float:left;margin-left:-1.5em}.form-check-input{width:1em;height:1em;margin-top:.25em;vertical-align:top;background-color:#fff;background-repeat:no-repeat;background-position:center;background-size:contain;border:1px solid rgba(0,0,0,.25);appearance:none;color-adjust:exact}.form-check-input[type=checkbox]{border-radius:.25em}.form-check-input[type=radio]{border-radius:50%}.form-check-input:active{filter:brightness(90%)}.form-check-input:focus{border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-check-input:checked{background-color:#0d6efd;border-color:#0d6efd}.form-check-input:checked[type=checkbox]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10l3 3l6-6'/%3e%3c/svg%3e")}.form-check-input:checked[type=radio]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e")}.form-check-input[type=checkbox]:indeterminate{background-color:#0d6efd;border-color:#0d6efd;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e")}.form-check-input:disabled{pointer-events:none;filter:none;opacity:.5}.form-check-input[disabled]~.form-check-label,.form-check-input:disabled~.form-check-label{opacity:.5}.form-switch{padding-left:2.5em}.form-switch .form-check-input{width:2em;margin-left:-2.5em;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280,0,0,.25%29'/%3e%3c/svg%3e");background-position:left center;border-radius:2em;transition:background-position .15s ease-in-out}@media (prefers-reduced-motion: reduce){.form-switch .form-check-input{transition:none}}.form-switch .form-check-input:focus{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2386b7fe'/%3e%3c/svg%3e")}.form-switch .form-check-input:checked{background-position:right center;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.form-check-inline{display:inline-block;margin-right:1rem}.btn-check{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.btn-check[disabled]+.btn,.btn-check:disabled+.btn{pointer-events:none;filter:none;opacity:.65}.form-range{width:100%;height:1.5rem;padding:0;background-color:rgba(0,0,0,0);appearance:none}.form-range:focus{outline:0}.form-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(13,110,253,.25)}.form-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(13,110,253,.25)}.form-range::-moz-focus-outer{border:0}.form-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#0d6efd;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion: reduce){.form-range::-webkit-slider-thumb{transition:none}}.form-range::-webkit-slider-thumb:active{background-color:#b6d4fe}.form-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:rgba(0,0,0,0);cursor:pointer;background-color:#dee2e6;border-color:rgba(0,0,0,0);border-radius:1rem}.form-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#0d6efd;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion: reduce){.form-range::-moz-range-thumb{transition:none}}.form-range::-moz-range-thumb:active{background-color:#b6d4fe}.form-range::-moz-range-track{width:100%;height:.5rem;color:rgba(0,0,0,0);cursor:pointer;background-color:#dee2e6;border-color:rgba(0,0,0,0);border-radius:1rem}.form-range:disabled{pointer-events:none}.form-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.form-range:disabled::-moz-range-thumb{background-color:#adb5bd}.form-floating{position:relative}.form-floating>.form-control,.form-floating>.form-select{height:calc(3.5rem + 2px);padding:1rem .75rem}.form-floating>label{position:absolute;top:0;left:0;height:100%;padding:1rem .75rem;pointer-events:none;border:1px solid rgba(0,0,0,0);transform-origin:0 0;transition:opacity .1s ease-in-out,transform .1s ease-in-out}@media (prefers-reduced-motion: reduce){.form-floating>label{transition:none}}.form-floating>.form-control::placeholder{color:rgba(0,0,0,0)}.form-floating>.form-control:focus,.form-floating>.form-control:not(:placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:-webkit-autofill{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-select{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:focus~label,.form-floating>.form-control:not(:placeholder-shown)~label,.form-floating>.form-select~label{opacity:.65;transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>.form-control:-webkit-autofill~label{opacity:.65;transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.input-group{position:relative;display:flex;flex-wrap:wrap;align-items:stretch;width:100%}.input-group>.form-control,.input-group>.form-select{position:relative;flex:1 1 auto;width:1%;min-width:0}.input-group>.form-control:focus,.input-group>.form-select:focus{z-index:3}.input-group .btn{position:relative;z-index:2}.input-group .btn:focus{z-index:3}.input-group-text{display:flex;align-items:center;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-lg>.form-control,.input-group-lg>.form-select,.input-group-lg>.input-group-text,.input-group-lg>.btn{padding:.5rem 1rem;font-size:1.25rem;border-radius:.3rem}.input-group-sm>.form-control,.input-group-sm>.form-select,.input-group-sm>.input-group-text,.input-group-sm>.btn{padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.input-group-lg>.form-select,.input-group-sm>.form-select{padding-right:3rem}.input-group:not(.has-validation)>:not(:last-child):not(.dropdown-toggle):not(.dropdown-menu),.input-group:not(.has-validation)>.dropdown-toggle:nth-last-child(n+3){border-top-right-radius:0;border-bottom-right-radius:0}.input-group.has-validation>:nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu),.input-group.has-validation>.dropdown-toggle:nth-last-child(n+4){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>:not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback){margin-left:-1px;border-top-left-radius:0;border-bottom-left-radius:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#198754}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:rgba(25,135,84,.9);border-radius:.25rem}.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip,.is-valid~.valid-feedback,.is-valid~.valid-tooltip{display:block}.was-validated .form-control:valid,.form-control.is-valid{border-color:#198754;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' 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;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.was-validated .form-control:valid:focus,.form-control.is-valid:focus{border-color:#198754;box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.was-validated .form-select:valid,.form-select.is-valid{border-color:#198754;padding-right:4.125rem;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' 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-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.was-validated .form-select:valid:focus,.form-select.is-valid:focus{border-color:#198754;box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.was-validated .form-check-input:valid,.form-check-input.is-valid{border-color:#198754}.was-validated .form-check-input:valid:checked,.form-check-input.is-valid:checked{background-color:#198754}.was-validated .form-check-input:valid:focus,.form-check-input.is-valid:focus{box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.was-validated .form-check-input:valid~.form-check-label,.form-check-input.is-valid~.form-check-label{color:#198754}.form-check-inline .form-check-input~.valid-feedback{margin-left:.5em}.was-validated .input-group .form-control:valid,.input-group .form-control.is-valid,.was-validated .input-group .form-select:valid,.input-group .form-select.is-valid{z-index:3}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.25rem}.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip,.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip{display:block}.was-validated .form-control:invalid,.form-control.is-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' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%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;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.was-validated .form-control:invalid:focus,.form-control.is-invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.was-validated .form-select:invalid,.form-select.is-invalid{border-color:#dc3545;padding-right:4.125rem;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%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-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.was-validated .form-select:invalid:focus,.form-select.is-invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.was-validated .form-check-input:invalid,.form-check-input.is-invalid{border-color:#dc3545}.was-validated .form-check-input:invalid:checked,.form-check-input.is-invalid:checked{background-color:#dc3545}.was-validated .form-check-input:invalid:focus,.form-check-input.is-invalid:focus{box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.was-validated .form-check-input:invalid~.form-check-label,.form-check-input.is-invalid~.form-check-label{color:#dc3545}.form-check-inline .form-check-input~.invalid-feedback{margin-left:.5em}.was-validated .input-group .form-control:invalid,.input-group .form-control.is-invalid,.was-validated .input-group .form-select:invalid,.input-group .form-select.is-invalid{z-index:3}.btn{display:inline-block;font-weight:400;line-height:1.5;color:#212529;text-align:center;text-decoration:none;vertical-align:middle;cursor:pointer;user-select:none;background-color:rgba(0,0,0,0);border:1px solid rgba(0,0,0,0);padding:.375rem .75rem;font-size:1rem;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion: reduce){.btn{transition:none}}.btn:hover{color:#212529}.btn-check:focus+.btn,.btn:focus{outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.btn:disabled,.btn.disabled,fieldset:disabled .btn{pointer-events:none;opacity:.65}.btn-primary{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.btn-primary:hover{color:#fff;background-color:#0b5ed7;border-color:#0a58ca}.btn-check:focus+.btn-primary,.btn-primary:focus{color:#fff;background-color:#0b5ed7;border-color:#0a58ca;box-shadow:0 0 0 .25rem rgba(49,132,253,.5)}.btn-check:checked+.btn-primary,.btn-check:active+.btn-primary,.btn-primary:active,.btn-primary.active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0a58ca;border-color:#0a53be}.btn-check:checked+.btn-primary:focus,.btn-check:active+.btn-primary:focus,.btn-primary:active:focus,.btn-primary.active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(49,132,253,.5)}.btn-primary:disabled,.btn-primary.disabled{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover{color:#fff;background-color:#5c636a;border-color:#565e64}.btn-check:focus+.btn-secondary,.btn-secondary:focus{color:#fff;background-color:#5c636a;border-color:#565e64;box-shadow:0 0 0 .25rem rgba(130,138,145,.5)}.btn-check:checked+.btn-secondary,.btn-check:active+.btn-secondary,.btn-secondary:active,.btn-secondary.active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#565e64;border-color:#51585e}.btn-check:checked+.btn-secondary:focus,.btn-check:active+.btn-secondary:focus,.btn-secondary:active:focus,.btn-secondary.active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(130,138,145,.5)}.btn-secondary:disabled,.btn-secondary.disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-success{color:#fff;background-color:#198754;border-color:#198754}.btn-success:hover{color:#fff;background-color:#157347;border-color:#146c43}.btn-check:focus+.btn-success,.btn-success:focus{color:#fff;background-color:#157347;border-color:#146c43;box-shadow:0 0 0 .25rem rgba(60,153,110,.5)}.btn-check:checked+.btn-success,.btn-check:active+.btn-success,.btn-success:active,.btn-success.active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#146c43;border-color:#13653f}.btn-check:checked+.btn-success:focus,.btn-check:active+.btn-success:focus,.btn-success:active:focus,.btn-success.active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(60,153,110,.5)}.btn-success:disabled,.btn-success.disabled{color:#fff;background-color:#198754;border-color:#198754}.btn-info{color:#000;background-color:#0dcaf0;border-color:#0dcaf0}.btn-info:hover{color:#000;background-color:#31d2f2;border-color:#25cff2}.btn-check:focus+.btn-info,.btn-info:focus{color:#000;background-color:#31d2f2;border-color:#25cff2;box-shadow:0 0 0 .25rem rgba(11,172,204,.5)}.btn-check:checked+.btn-info,.btn-check:active+.btn-info,.btn-info:active,.btn-info.active,.show>.btn-info.dropdown-toggle{color:#000;background-color:#3dd5f3;border-color:#25cff2}.btn-check:checked+.btn-info:focus,.btn-check:active+.btn-info:focus,.btn-info:active:focus,.btn-info.active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(11,172,204,.5)}.btn-info:disabled,.btn-info.disabled{color:#000;background-color:#0dcaf0;border-color:#0dcaf0}.btn-warning{color:#000;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#000;background-color:#ffca2c;border-color:#ffc720}.btn-check:focus+.btn-warning,.btn-warning:focus{color:#000;background-color:#ffca2c;border-color:#ffc720;box-shadow:0 0 0 .25rem rgba(217,164,6,.5)}.btn-check:checked+.btn-warning,.btn-check:active+.btn-warning,.btn-warning:active,.btn-warning.active,.show>.btn-warning.dropdown-toggle{color:#000;background-color:#ffcd39;border-color:#ffc720}.btn-check:checked+.btn-warning:focus,.btn-check:active+.btn-warning:focus,.btn-warning:active:focus,.btn-warning.active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(217,164,6,.5)}.btn-warning:disabled,.btn-warning.disabled{color:#000;background-color:#ffc107;border-color:#ffc107}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#bb2d3b;border-color:#b02a37}.btn-check:focus+.btn-danger,.btn-danger:focus{color:#fff;background-color:#bb2d3b;border-color:#b02a37;box-shadow:0 0 0 .25rem rgba(225,83,97,.5)}.btn-check:checked+.btn-danger,.btn-check:active+.btn-danger,.btn-danger:active,.btn-danger.active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#b02a37;border-color:#a52834}.btn-check:checked+.btn-danger:focus,.btn-check:active+.btn-danger:focus,.btn-danger:active:focus,.btn-danger.active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(225,83,97,.5)}.btn-danger:disabled,.btn-danger.disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-light{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#000;background-color:#f9fafb;border-color:#f9fafb}.btn-check:focus+.btn-light,.btn-light:focus{color:#000;background-color:#f9fafb;border-color:#f9fafb;box-shadow:0 0 0 .25rem rgba(211,212,213,.5)}.btn-check:checked+.btn-light,.btn-check:active+.btn-light,.btn-light:active,.btn-light.active,.show>.btn-light.dropdown-toggle{color:#000;background-color:#f9fafb;border-color:#f9fafb}.btn-check:checked+.btn-light:focus,.btn-check:active+.btn-light:focus,.btn-light:active:focus,.btn-light.active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(211,212,213,.5)}.btn-light:disabled,.btn-light.disabled{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-dark{color:#fff;background-color:#212529;border-color:#212529}.btn-dark:hover{color:#fff;background-color:#1c1f23;border-color:#1a1e21}.btn-check:focus+.btn-dark,.btn-dark:focus{color:#fff;background-color:#1c1f23;border-color:#1a1e21;box-shadow:0 0 0 .25rem rgba(66,70,73,.5)}.btn-check:checked+.btn-dark,.btn-check:active+.btn-dark,.btn-dark:active,.btn-dark.active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1a1e21;border-color:#191c1f}.btn-check:checked+.btn-dark:focus,.btn-check:active+.btn-dark:focus,.btn-dark:active:focus,.btn-dark.active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(66,70,73,.5)}.btn-dark:disabled,.btn-dark.disabled{color:#fff;background-color:#212529;border-color:#212529}.btn-outline-primary{color:#0d6efd;border-color:#0d6efd}.btn-outline-primary:hover{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.btn-check:focus+.btn-outline-primary,.btn-outline-primary:focus{box-shadow:0 0 0 .25rem rgba(13,110,253,.5)}.btn-check:checked+.btn-outline-primary,.btn-check:active+.btn-outline-primary,.btn-outline-primary:active,.btn-outline-primary.active,.btn-outline-primary.dropdown-toggle.show{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.btn-check:checked+.btn-outline-primary:focus,.btn-check:active+.btn-outline-primary:focus,.btn-outline-primary:active:focus,.btn-outline-primary.active:focus,.btn-outline-primary.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(13,110,253,.5)}.btn-outline-primary:disabled,.btn-outline-primary.disabled{color:#0d6efd;background-color:rgba(0,0,0,0)}.btn-outline-secondary{color:#6c757d;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-check:focus+.btn-outline-secondary,.btn-outline-secondary:focus{box-shadow:0 0 0 .25rem rgba(108,117,125,.5)}.btn-check:checked+.btn-outline-secondary,.btn-check:active+.btn-outline-secondary,.btn-outline-secondary:active,.btn-outline-secondary.active,.btn-outline-secondary.dropdown-toggle.show{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-check:checked+.btn-outline-secondary:focus,.btn-check:active+.btn-outline-secondary:focus,.btn-outline-secondary:active:focus,.btn-outline-secondary.active:focus,.btn-outline-secondary.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(108,117,125,.5)}.btn-outline-secondary:disabled,.btn-outline-secondary.disabled{color:#6c757d;background-color:rgba(0,0,0,0)}.btn-outline-success{color:#198754;border-color:#198754}.btn-outline-success:hover{color:#fff;background-color:#198754;border-color:#198754}.btn-check:focus+.btn-outline-success,.btn-outline-success:focus{box-shadow:0 0 0 .25rem rgba(25,135,84,.5)}.btn-check:checked+.btn-outline-success,.btn-check:active+.btn-outline-success,.btn-outline-success:active,.btn-outline-success.active,.btn-outline-success.dropdown-toggle.show{color:#fff;background-color:#198754;border-color:#198754}.btn-check:checked+.btn-outline-success:focus,.btn-check:active+.btn-outline-success:focus,.btn-outline-success:active:focus,.btn-outline-success.active:focus,.btn-outline-success.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(25,135,84,.5)}.btn-outline-success:disabled,.btn-outline-success.disabled{color:#198754;background-color:rgba(0,0,0,0)}.btn-outline-info{color:#0dcaf0;border-color:#0dcaf0}.btn-outline-info:hover{color:#000;background-color:#0dcaf0;border-color:#0dcaf0}.btn-check:focus+.btn-outline-info,.btn-outline-info:focus{box-shadow:0 0 0 .25rem rgba(13,202,240,.5)}.btn-check:checked+.btn-outline-info,.btn-check:active+.btn-outline-info,.btn-outline-info:active,.btn-outline-info.active,.btn-outline-info.dropdown-toggle.show{color:#000;background-color:#0dcaf0;border-color:#0dcaf0}.btn-check:checked+.btn-outline-info:focus,.btn-check:active+.btn-outline-info:focus,.btn-outline-info:active:focus,.btn-outline-info.active:focus,.btn-outline-info.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(13,202,240,.5)}.btn-outline-info:disabled,.btn-outline-info.disabled{color:#0dcaf0;background-color:rgba(0,0,0,0)}.btn-outline-warning{color:#ffc107;border-color:#ffc107}.btn-outline-warning:hover{color:#000;background-color:#ffc107;border-color:#ffc107}.btn-check:focus+.btn-outline-warning,.btn-outline-warning:focus{box-shadow:0 0 0 .25rem rgba(255,193,7,.5)}.btn-check:checked+.btn-outline-warning,.btn-check:active+.btn-outline-warning,.btn-outline-warning:active,.btn-outline-warning.active,.btn-outline-warning.dropdown-toggle.show{color:#000;background-color:#ffc107;border-color:#ffc107}.btn-check:checked+.btn-outline-warning:focus,.btn-check:active+.btn-outline-warning:focus,.btn-outline-warning:active:focus,.btn-outline-warning.active:focus,.btn-outline-warning.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(255,193,7,.5)}.btn-outline-warning:disabled,.btn-outline-warning.disabled{color:#ffc107;background-color:rgba(0,0,0,0)}.btn-outline-danger{color:#dc3545;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-check:focus+.btn-outline-danger,.btn-outline-danger:focus{box-shadow:0 0 0 .25rem rgba(220,53,69,.5)}.btn-check:checked+.btn-outline-danger,.btn-check:active+.btn-outline-danger,.btn-outline-danger:active,.btn-outline-danger.active,.btn-outline-danger.dropdown-toggle.show{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-check:checked+.btn-outline-danger:focus,.btn-check:active+.btn-outline-danger:focus,.btn-outline-danger:active:focus,.btn-outline-danger.active:focus,.btn-outline-danger.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(220,53,69,.5)}.btn-outline-danger:disabled,.btn-outline-danger.disabled{color:#dc3545;background-color:rgba(0,0,0,0)}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:hover{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-check:focus+.btn-outline-light,.btn-outline-light:focus{box-shadow:0 0 0 .25rem rgba(248,249,250,.5)}.btn-check:checked+.btn-outline-light,.btn-check:active+.btn-outline-light,.btn-outline-light:active,.btn-outline-light.active,.btn-outline-light.dropdown-toggle.show{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-check:checked+.btn-outline-light:focus,.btn-check:active+.btn-outline-light:focus,.btn-outline-light:active:focus,.btn-outline-light.active:focus,.btn-outline-light.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(248,249,250,.5)}.btn-outline-light:disabled,.btn-outline-light.disabled{color:#f8f9fa;background-color:rgba(0,0,0,0)}.btn-outline-dark{color:#212529;border-color:#212529}.btn-outline-dark:hover{color:#fff;background-color:#212529;border-color:#212529}.btn-check:focus+.btn-outline-dark,.btn-outline-dark:focus{box-shadow:0 0 0 .25rem rgba(33,37,41,.5)}.btn-check:checked+.btn-outline-dark,.btn-check:active+.btn-outline-dark,.btn-outline-dark:active,.btn-outline-dark.active,.btn-outline-dark.dropdown-toggle.show{color:#fff;background-color:#212529;border-color:#212529}.btn-check:checked+.btn-outline-dark:focus,.btn-check:active+.btn-outline-dark:focus,.btn-outline-dark:active:focus,.btn-outline-dark.active:focus,.btn-outline-dark.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(33,37,41,.5)}.btn-outline-dark:disabled,.btn-outline-dark.disabled{color:#212529;background-color:rgba(0,0,0,0)}.btn-link{font-weight:400;color:#0d6efd;text-decoration:underline}.btn-link:hover{color:#0a58ca}.btn-link:disabled,.btn-link.disabled{color:#6c757d}.btn-lg,.btn-group-lg>.btn{padding:.5rem 1rem;font-size:1.25rem;border-radius:.3rem}.btn-sm,.btn-group-sm>.btn{padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion: reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion: reduce){.collapsing{transition:none}}.dropup,.dropend,.dropdown,.dropstart{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid rgba(0,0,0,0);border-bottom:0;border-left:.3em solid rgba(0,0,0,0)}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;z-index:1000;display:none;min-width:10rem;padding:.5rem 0;margin:0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-menu[data-bs-popper]{left:0;margin-top:.125rem}.dropdown-menu-start{--bs-position: start}.dropdown-menu-start[data-bs-popper]{right:auto /* rtl:ignore */;left:0 /* rtl:ignore */}.dropdown-menu-end{--bs-position: end}.dropdown-menu-end[data-bs-popper]{right:0 /* rtl:ignore */;left:auto /* rtl:ignore */}@media (min-width: 576px){.dropdown-menu-sm-start{--bs-position: start}.dropdown-menu-sm-start[data-bs-popper]{right:auto /* rtl:ignore */;left:0 /* rtl:ignore */}.dropdown-menu-sm-end{--bs-position: end}.dropdown-menu-sm-end[data-bs-popper]{right:0 /* rtl:ignore */;left:auto /* rtl:ignore */}}@media (min-width: 768px){.dropdown-menu-md-start{--bs-position: start}.dropdown-menu-md-start[data-bs-popper]{right:auto /* rtl:ignore */;left:0 /* rtl:ignore */}.dropdown-menu-md-end{--bs-position: end}.dropdown-menu-md-end[data-bs-popper]{right:0 /* rtl:ignore */;left:auto /* rtl:ignore */}}@media (min-width: 992px){.dropdown-menu-lg-start{--bs-position: start}.dropdown-menu-lg-start[data-bs-popper]{right:auto /* rtl:ignore */;left:0 /* rtl:ignore */}.dropdown-menu-lg-end{--bs-position: end}.dropdown-menu-lg-end[data-bs-popper]{right:0 /* rtl:ignore */;left:auto /* rtl:ignore */}}@media (min-width: 1200px){.dropdown-menu-xl-start{--bs-position: start}.dropdown-menu-xl-start[data-bs-popper]{right:auto /* rtl:ignore */;left:0 /* rtl:ignore */}.dropdown-menu-xl-end{--bs-position: end}.dropdown-menu-xl-end[data-bs-popper]{right:0 /* rtl:ignore */;left:auto /* rtl:ignore */}}@media (min-width: 1400px){.dropdown-menu-xxl-start{--bs-position: start}.dropdown-menu-xxl-start[data-bs-popper]{right:auto /* rtl:ignore */;left:0 /* rtl:ignore */}.dropdown-menu-xxl-end{--bs-position: end}.dropdown-menu-xxl-end[data-bs-popper]{right:0 /* rtl:ignore */;left:auto /* rtl:ignore */}}.dropup .dropdown-menu[data-bs-popper]{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid rgba(0,0,0,0);border-bottom:.3em solid;border-left:.3em solid rgba(0,0,0,0)}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-menu{top:0;right:auto;left:100%}.dropend .dropdown-menu[data-bs-popper]{margin-top:0;margin-left:.125rem}.dropend .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid rgba(0,0,0,0);border-right:0;border-bottom:.3em solid rgba(0,0,0,0);border-left:.3em solid}.dropend .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-toggle::after{vertical-align:0}.dropstart .dropdown-menu{top:0;right:100%;left:auto}.dropstart .dropdown-menu[data-bs-popper]{margin-top:0;margin-right:.125rem}.dropstart .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropstart .dropdown-toggle::after{display:none}.dropstart .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid rgba(0,0,0,0);border-right:.3em solid;border-bottom:.3em solid rgba(0,0,0,0)}.dropstart .dropdown-toggle:empty::after{margin-left:0}.dropstart .dropdown-toggle::before{vertical-align:0}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid rgba(0,0,0,.15)}.dropdown-item{display:block;width:100%;padding:.25rem 1rem;clear:both;font-weight:400;color:#212529;text-align:inherit;text-decoration:none;white-space:nowrap;background-color:rgba(0,0,0,0);border:0}.dropdown-item:hover,.dropdown-item:focus{color:#1e2125;background-color:#e9ecef}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#0d6efd}.dropdown-item.disabled,.dropdown-item:disabled{color:#adb5bd;pointer-events:none;background-color:rgba(0,0,0,0)}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1rem;color:#212529}.dropdown-menu-dark{color:#dee2e6;background-color:#343a40;border-color:rgba(0,0,0,.15)}.dropdown-menu-dark .dropdown-item{color:#dee2e6}.dropdown-menu-dark .dropdown-item:hover,.dropdown-menu-dark .dropdown-item:focus{color:#fff;background-color:rgba(255,255,255,.15)}.dropdown-menu-dark .dropdown-item.active,.dropdown-menu-dark .dropdown-item:active{color:#fff;background-color:#0d6efd}.dropdown-menu-dark .dropdown-item.disabled,.dropdown-menu-dark .dropdown-item:disabled{color:#adb5bd}.dropdown-menu-dark .dropdown-divider{border-color:rgba(0,0,0,.15)}.dropdown-menu-dark .dropdown-item-text{color:#dee2e6}.dropdown-menu-dark .dropdown-header{color:#adb5bd}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;flex:1 1 auto}.btn-group>.btn-check:checked+.btn,.btn-group>.btn-check:focus+.btn,.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn-check:checked+.btn,.btn-group-vertical>.btn-check:focus+.btn,.btn-group-vertical>.btn:hover,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn.active{z-index:1}.btn-toolbar{display:flex;flex-wrap:wrap;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn:not(:first-child),.btn-group>.btn-group:not(:first-child){margin-left:-1px}.btn-group>.btn:not(:last-child):not(.dropdown-toggle),.btn-group>.btn-group:not(:last-child)>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:nth-child(n+3),.btn-group>:not(.btn-check)+.btn,.btn-group>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after,.dropend .dropdown-toggle-split::after{margin-left:0}.dropstart .dropdown-toggle-split::before{margin-right:0}.btn-sm+.dropdown-toggle-split,.btn-group-sm>.btn+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-lg+.dropdown-toggle-split,.btn-group-lg>.btn+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{flex-direction:column;align-items:flex-start;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn:not(:first-child),.btn-group-vertical>.btn-group:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle),.btn-group-vertical>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn~.btn,.btn-group-vertical>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-top-right-radius:0}.nav{display:flex;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out}@media (prefers-reduced-motion: reduce){.nav-link{transition:none}}.nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-link{margin-bottom:-1px;background:none;border:1px solid rgba(0,0,0,0);border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:hover,.nav-tabs .nav-link:focus{border-color:#e9ecef #e9ecef #dee2e6;isolation:isolate}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:rgba(0,0,0,0);border-color:rgba(0,0,0,0)}.nav-tabs .nav-link.active,.nav-tabs .nav-item.show .nav-link{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{background:none;border:0;border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#0d6efd}.nav-fill>.nav-link,.nav-fill .nav-item{flex:1 1 auto;text-align:center}.nav-justified>.nav-link,.nav-justified .nav-item{flex-basis:0;flex-grow:1;text-align:center}.nav-fill .nav-item .nav-link,.nav-justified .nav-item .nav-link{width:100%}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;padding-top:.5rem;padding-bottom:.5rem}.navbar>.container,.navbar>.container-fluid,.navbar>.container-sm,.navbar>.container-md,.navbar>.container-lg,.navbar>.container-xl,.navbar>.container-xxl{display:flex;flex-wrap:inherit;align-items:center;justify-content:space-between}.navbar-brand{padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;text-decoration:none;white-space:nowrap}.navbar-nav{display:flex;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static}.navbar-text{padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{flex-basis:100%;flex-grow:1;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:rgba(0,0,0,0);border:1px solid rgba(0,0,0,0);border-radius:.25rem;transition:box-shadow .15s ease-in-out}@media (prefers-reduced-motion: reduce){.navbar-toggler{transition:none}}.navbar-toggler:hover{text-decoration:none}.navbar-toggler:focus{text-decoration:none;outline:0;box-shadow:0 0 0 .25rem}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;background-repeat:no-repeat;background-position:center;background-size:100%}.navbar-nav-scroll{max-height:var(--bs-scroll-height, 75vh);overflow-y:auto}@media (min-width: 576px){.navbar-expand-sm{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex !important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (min-width: 768px){.navbar-expand-md{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex !important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (min-width: 992px){.navbar-expand-lg{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex !important;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (min-width: 1200px){.navbar-expand-xl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex !important;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}@media (min-width: 1400px){.navbar-expand-xxl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xxl .navbar-nav{flex-direction:row}.navbar-expand-xxl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xxl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xxl .navbar-nav-scroll{overflow:visible}.navbar-expand-xxl .navbar-collapse{display:flex !important;flex-basis:auto}.navbar-expand-xxl .navbar-toggler{display:none}}.navbar-expand{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex !important;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:hover,.navbar-light .navbar-brand:focus{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.55)}.navbar-light .navbar-nav .nav-link:hover,.navbar-light .navbar-nav .nav-link:focus{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .show>.nav-link,.navbar-light .navbar-nav .nav-link.active{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.55);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280,0,0,.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text{color:rgba(0,0,0,.55)}.navbar-light .navbar-text a,.navbar-light .navbar-text a:hover,.navbar-light .navbar-text a:focus{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:hover,.navbar-dark .navbar-brand:focus{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.55)}.navbar-dark .navbar-nav .nav-link:hover,.navbar-dark .navbar-nav .nav-link:focus{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .show>.nav-link,.navbar-dark .navbar-nav .nav-link.active{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.55);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255,255,255,.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text{color:rgba(255,255,255,.55)}.navbar-dark .navbar-text a,.navbar-dark .navbar-text a:hover,.navbar-dark .navbar-text a:focus{color:#fff}.card{position:relative;display:flex;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;padding:1rem 1rem}.card-title{margin-bottom:.5rem}.card-subtitle{margin-top:-.25rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1rem}.card-header{padding:.5rem 1rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-footer{padding:.5rem 1rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.5rem;margin-bottom:-.5rem;margin-left:-.5rem;border-bottom:0}.card-header-pills{margin-right:-.5rem;margin-left:-.5rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(.25rem - 1px)}.card-img,.card-img-top,.card-img-bottom{width:100%}.card-img,.card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-group>.card{margin-bottom:.75rem}@media (min-width: 576px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card{flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-img-top,.card-group>.card:not(:last-child) .card-header{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-img-bottom,.card-group>.card:not(:last-child) .card-footer{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-img-top,.card-group>.card:not(:first-child) .card-header{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-img-bottom,.card-group>.card:not(:first-child) .card-footer{border-bottom-left-radius:0}}.accordion-button{position:relative;display:flex;align-items:center;width:100%;padding:1rem 1.25rem;font-size:1rem;color:#212529;text-align:left;background-color:#fff;border:0;border-radius:0;overflow-anchor:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,border-radius .15s ease}@media (prefers-reduced-motion: reduce){.accordion-button{transition:none}}.accordion-button:not(.collapsed){color:#0c63e4;background-color:#e7f1ff;box-shadow:inset 0 -1px 0 rgba(0,0,0,.125)}.accordion-button:not(.collapsed)::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%230c63e4'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");transform:rotate(180deg)}.accordion-button::after{flex-shrink:0;width:1.25rem;height:1.25rem;margin-left:auto;content:"";background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23212529'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-size:1.25rem;transition:transform .2s ease-in-out}@media (prefers-reduced-motion: reduce){.accordion-button::after{transition:none}}.accordion-button:hover{z-index:2}.accordion-button:focus{z-index:3;border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.accordion-header{margin-bottom:0}.accordion-item{margin-bottom:-1px;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.accordion-item:first-of-type{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.accordion-item:first-of-type .accordion-button{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.accordion-item:last-of-type{margin-bottom:0;border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.accordion-item:last-of-type .accordion-button.collapsed{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.accordion-item:last-of-type .accordion-collapse{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.accordion-body{padding:1rem 1.25rem}.accordion-flush .accordion-collapse{border-width:0}.accordion-flush .accordion-item{border-right:0;border-left:0;border-radius:0}.accordion-flush .accordion-item:first-child{border-top:0}.accordion-flush .accordion-item:last-child{border-bottom:0}.accordion-flush .accordion-item .accordion-button{border-radius:0}.breadcrumb{display:flex;flex-wrap:wrap;padding:0 0;margin-bottom:1rem;list-style:none}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{float:left;padding-right:.5rem;color:#6c757d;content:var(--bs-breadcrumb-divider, "/") /* rtl: var(--bs-breadcrumb-divider, "/") */}.breadcrumb-item.active{color:#6c757d}.pagination{display:flex;padding-left:0;list-style:none}.page-link{position:relative;display:block;color:#0d6efd;text-decoration:none;background-color:#fff;border:1px solid #dee2e6;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion: reduce){.page-link{transition:none}}.page-link:hover{z-index:2;color:#0a58ca;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:3;color:#0a58ca;background-color:#e9ecef;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.page-item:not(:first-child) .page-link{margin-left:-1px}.page-item.active .page-link{z-index:3;color:#fff;background-color:#0d6efd;border-color:#0d6efd}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;background-color:#fff;border-color:#dee2e6}.page-link{padding:.375rem .75rem}.page-item:first-child .page-link{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.alert{position:relative;padding:1rem 1rem;margin-bottom:1rem;border:1px solid rgba(0,0,0,0);border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:3rem}.alert-dismissible .btn-close{position:absolute;top:0;right:0;z-index:2;padding:1.25rem 1rem}.alert-primary{color:#084298;background-color:#cfe2ff;border-color:#b6d4fe}.alert-primary .alert-link{color:#06357a}.alert-secondary{color:#41464b;background-color:#e2e3e5;border-color:#d3d6d8}.alert-secondary .alert-link{color:#34383c}.alert-success{color:#0f5132;background-color:#d1e7dd;border-color:#badbcc}.alert-success .alert-link{color:#0c4128}.alert-info{color:#055160;background-color:#cff4fc;border-color:#b6effb}.alert-info .alert-link{color:#04414d}.alert-warning{color:#664d03;background-color:#fff3cd;border-color:#ffecb5}.alert-warning .alert-link{color:#523e02}.alert-danger{color:#842029;background-color:#f8d7da;border-color:#f5c2c7}.alert-danger .alert-link{color:#6a1a21}.alert-light{color:#636464;background-color:#fefefe;border-color:#fdfdfe}.alert-light .alert-link{color:#4f5050}.alert-dark{color:#141619;background-color:#d3d3d4;border-color:#bcbebf}.alert-dark .alert-link{color:#101214}@keyframes progress-bar-stripes{0%{background-position-x:1rem}}.progress{display:flex;height:1rem;overflow:hidden;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress-bar{display:flex;flex-direction:column;justify-content:center;overflow:hidden;color:#fff;text-align:center;white-space:nowrap;background-color:#0d6efd;transition:width .6s ease}@media (prefers-reduced-motion: reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg, rgba(255,255,255,.15) 25%, rgba(0,0,0,0) 25%, rgba(0,0,0,0) 50%, rgba(255,255,255,.15) 50%, rgba(255,255,255,.15) 75%, rgba(0,0,0,0) 75%, rgba(0,0,0,0));background-size:1rem 1rem}.progress-bar-animated{animation:1s linear infinite progress-bar-stripes}@media (prefers-reduced-motion: reduce){.progress-bar-animated{animation:none}}.list-group{display:flex;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:.25rem}.list-group-numbered{list-style-type:none;counter-reset:section}.list-group-numbered>li::before{content:counters(section, ".") ". ";counter-increment:section}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:hover,.list-group-item-action:focus{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.5rem 1rem;color:#212529;text-decoration:none;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#0d6efd;border-color:#0d6efd}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:-1px;border-top-width:1px}.list-group-horizontal{flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media (min-width: 576px){.list-group-horizontal-sm{flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width: 768px){.list-group-horizontal-md{flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width: 992px){.list-group-horizontal-lg{flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width: 1200px){.list-group-horizontal-xl{flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width: 1400px){.list-group-horizontal-xxl{flex-direction:row}.list-group-horizontal-xxl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xxl>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-xxl>.list-group-item.active{margin-top:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{color:#084298;background-color:#cfe2ff}.list-group-item-primary.list-group-item-action:hover,.list-group-item-primary.list-group-item-action:focus{color:#084298;background-color:#bacbe6}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#084298;border-color:#084298}.list-group-item-secondary{color:#41464b;background-color:#e2e3e5}.list-group-item-secondary.list-group-item-action:hover,.list-group-item-secondary.list-group-item-action:focus{color:#41464b;background-color:#cbccce}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#41464b;border-color:#41464b}.list-group-item-success{color:#0f5132;background-color:#d1e7dd}.list-group-item-success.list-group-item-action:hover,.list-group-item-success.list-group-item-action:focus{color:#0f5132;background-color:#bcd0c7}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#0f5132;border-color:#0f5132}.list-group-item-info{color:#055160;background-color:#cff4fc}.list-group-item-info.list-group-item-action:hover,.list-group-item-info.list-group-item-action:focus{color:#055160;background-color:#badce3}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#055160;border-color:#055160}.list-group-item-warning{color:#664d03;background-color:#fff3cd}.list-group-item-warning.list-group-item-action:hover,.list-group-item-warning.list-group-item-action:focus{color:#664d03;background-color:#e6dbb9}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#664d03;border-color:#664d03}.list-group-item-danger{color:#842029;background-color:#f8d7da}.list-group-item-danger.list-group-item-action:hover,.list-group-item-danger.list-group-item-action:focus{color:#842029;background-color:#dfc2c4}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#842029;border-color:#842029}.list-group-item-light{color:#636464;background-color:#fefefe}.list-group-item-light.list-group-item-action:hover,.list-group-item-light.list-group-item-action:focus{color:#636464;background-color:#e5e5e5}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#636464;border-color:#636464}.list-group-item-dark{color:#141619;background-color:#d3d3d4}.list-group-item-dark.list-group-item-action:hover,.list-group-item-dark.list-group-item-action:focus{color:#141619;background-color:#bebebf}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#141619;border-color:#141619}.btn-close{box-sizing:content-box;width:1em;height:1em;padding:.25em .25em;color:#000;background:rgba(0,0,0,0) url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z'/%3e%3c/svg%3e") center/1em auto no-repeat;border:0;border-radius:.25rem;opacity:.5}.btn-close:hover{color:#000;text-decoration:none;opacity:.75}.btn-close:focus{outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25);opacity:1}.btn-close:disabled,.btn-close.disabled{pointer-events:none;user-select:none;opacity:.25}.btn-close-white{filter:invert(1) grayscale(100%) brightness(200%)}.toast{width:350px;max-width:100%;font-size:.875rem;pointer-events:auto;background-color:rgba(255,255,255,.85);background-clip:padding-box;border:1px solid rgba(0,0,0,.1);box-shadow:0 .5rem 1rem rgba(0,0,0,.15);border-radius:.25rem}.toast:not(.showing):not(.show){opacity:0}.toast.hide{display:none}.toast-container{width:max-content;max-width:100%;pointer-events:none}.toast-container>:not(:last-child){margin-bottom:.75rem}.toast-header{display:flex;align-items:center;padding:.5rem .75rem;color:#6c757d;background-color:rgba(255,255,255,.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05);border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.toast-header .btn-close{margin-right:-.375rem;margin-left:.75rem}.toast-body{padding:.75rem;word-wrap:break-word}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;left:0;z-index:1060;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:transform .3s ease-out;transform:translate(0, -50px)}@media (prefers-reduced-motion: reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:100%;overflow:hidden}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;align-items:center;min-height:calc(100% - 1rem)}.modal-content{position:relative;display:flex;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1050;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:flex;flex-shrink:0;align-items:center;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)}.modal-header .btn-close{padding:.5rem .5rem;margin:-.5rem -.5rem -.5rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;flex:1 1 auto;padding:1rem}.modal-footer{display:flex;flex-wrap:wrap;flex-shrink:0;align-items:center;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)}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width: 576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{height:calc(100% - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-sm{max-width:300px}}@media (min-width: 992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width: 1200px){.modal-xl{max-width:1140px}}.modal-fullscreen{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen .modal-header{border-radius:0}.modal-fullscreen .modal-body{overflow-y:auto}.modal-fullscreen .modal-footer{border-radius:0}@media (max-width: 575.98px){.modal-fullscreen-sm-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-sm-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-sm-down .modal-header{border-radius:0}.modal-fullscreen-sm-down .modal-body{overflow-y:auto}.modal-fullscreen-sm-down .modal-footer{border-radius:0}}@media (max-width: 767.98px){.modal-fullscreen-md-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-md-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-md-down .modal-header{border-radius:0}.modal-fullscreen-md-down .modal-body{overflow-y:auto}.modal-fullscreen-md-down .modal-footer{border-radius:0}}@media (max-width: 991.98px){.modal-fullscreen-lg-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-lg-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-lg-down .modal-header{border-radius:0}.modal-fullscreen-lg-down .modal-body{overflow-y:auto}.modal-fullscreen-lg-down .modal-footer{border-radius:0}}@media (max-width: 1199.98px){.modal-fullscreen-xl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xl-down .modal-header{border-radius:0}.modal-fullscreen-xl-down .modal-body{overflow-y:auto}.modal-fullscreen-xl-down .modal-footer{border-radius:0}}@media (max-width: 1399.98px){.modal-fullscreen-xxl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xxl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xxl-down .modal-header{border-radius:0}.modal-fullscreen-xxl-down .modal-body{overflow-y:auto}.modal-fullscreen-xxl-down .modal-footer{border-radius:0}}.tooltip{position:absolute;z-index:1080;display:block;margin:0;font-family:var(--bs-font-sans-serif);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}.tooltip.show{opacity:.9}.tooltip .tooltip-arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .tooltip-arrow::before{position:absolute;content:"";border-color:rgba(0,0,0,0);border-style:solid}.bs-tooltip-top,.bs-tooltip-auto[data-popper-placement^=top]{padding:.4rem 0}.bs-tooltip-top .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow{bottom:0}.bs-tooltip-top .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before{top:-1px;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-end,.bs-tooltip-auto[data-popper-placement^=right]{padding:0 .4rem}.bs-tooltip-end .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-end .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before{right:-1px;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-bottom,.bs-tooltip-auto[data-popper-placement^=bottom]{padding:.4rem 0}.bs-tooltip-bottom .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow{top:0}.bs-tooltip-bottom .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before{bottom:-1px;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-start,.bs-tooltip-auto[data-popper-placement^=left]{padding:0 .4rem}.bs-tooltip-start .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-start .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before{left:-1px;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{position:absolute;top:0;left:0 /* rtl:ignore */;z-index:1070;display:block;max-width:276px;font-family:var(--bs-font-sans-serif);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;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover .popover-arrow{position:absolute;display:block;width:1rem;height:.5rem}.popover .popover-arrow::before,.popover .popover-arrow::after{position:absolute;display:block;content:"";border-color:rgba(0,0,0,0);border-style:solid}.bs-popover-top>.popover-arrow,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow{bottom:calc(-.5rem - 1px)}.bs-popover-top>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,.25)}.bs-popover-top>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bs-popover-end>.popover-arrow,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow{left:calc(-.5rem - 1px);width:.5rem;height:1rem}.bs-popover-end>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,.25)}.bs-popover-end>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bs-popover-bottom>.popover-arrow,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow{top:calc(-.5rem - 1px)}.bs-popover-bottom>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-bottom>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#fff}.bs-popover-bottom .popover-header::before,.bs-popover-auto[data-popper-placement^=bottom] .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f0f0f0}.bs-popover-start>.popover-arrow,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow{right:calc(-.5rem - 1px);width:.5rem;height:1rem}.bs-popover-start>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,.25)}.bs-popover-start>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.popover-header{padding:.5rem 1rem;margin-bottom:0;font-size:1rem;background-color:#f0f0f0;border-bottom:1px solid #d8d8d8;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:1rem 1rem;color:#212529}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;backface-visibility:hidden;transition:transform .6s ease-in-out}@media (prefers-reduced-motion: reduce){.carousel-item{transition:none}}.carousel-item.active,.carousel-item-next,.carousel-item-prev{display:block}.carousel-item-next:not(.carousel-item-start),.active.carousel-item-end{transform:translateX(100%)}.carousel-item-prev:not(.carousel-item-end),.active.carousel-item-start{transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;transform:none}.carousel-fade .carousel-item.active,.carousel-fade .carousel-item-next.carousel-item-start,.carousel-fade .carousel-item-prev.carousel-item-end{z-index:1;opacity:1}.carousel-fade .active.carousel-item-start,.carousel-fade .active.carousel-item-end{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion: reduce){.carousel-fade .active.carousel-item-start,.carousel-fade .active.carousel-item-end{transition:none}}.carousel-control-prev,.carousel-control-next{position:absolute;top:0;bottom:0;z-index:1;display:flex;align-items:center;justify-content:center;width:15%;padding:0;color:#fff;text-align:center;background:none;border:0;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion: reduce){.carousel-control-prev,.carousel-control-next{transition:none}}.carousel-control-prev:hover,.carousel-control-prev:focus,.carousel-control-next:hover,.carousel-control-next:focus{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-prev-icon,.carousel-control-next-icon{display:inline-block;width:2rem;height:2rem;background-repeat:no-repeat;background-position:50%;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:2;display:flex;justify-content:center;padding:0;margin-right:15%;margin-bottom:1rem;margin-left:15%;list-style:none}.carousel-indicators [data-bs-target]{box-sizing:content-box;flex:0 1 auto;width:30px;height:3px;padding:0;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border:0;border-top:10px solid rgba(0,0,0,0);border-bottom:10px solid rgba(0,0,0,0);opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion: reduce){.carousel-indicators [data-bs-target]{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:1.25rem;left:15%;padding-top:1.25rem;padding-bottom:1.25rem;color:#fff;text-align:center}.carousel-dark .carousel-control-prev-icon,.carousel-dark .carousel-control-next-icon{filter:invert(1) grayscale(100)}.carousel-dark .carousel-indicators [data-bs-target]{background-color:#000}.carousel-dark .carousel-caption{color:#000}@keyframes spinner-border{to{transform:rotate(360deg) /* rtl:ignore */}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;border:.25em solid currentColor;border-right-color:rgba(0,0,0,0);border-radius:50%;animation:.75s linear infinite spinner-border}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;background-color:currentColor;border-radius:50%;opacity:0;animation:.75s linear infinite spinner-grow}.spinner-grow-sm{width:1rem;height:1rem}@media (prefers-reduced-motion: reduce){.spinner-border,.spinner-grow{animation-duration:1.5s}}.offcanvas{position:fixed;bottom:0;z-index:1040;display:flex;flex-direction:column;max-width:100%;visibility:hidden;background-color:#fff;background-clip:padding-box;outline:0;transition:transform .3s ease-in-out}@media (prefers-reduced-motion: reduce){.offcanvas{transition:none}}.offcanvas-header{display:flex;justify-content:space-between;padding:1rem 1rem}.offcanvas-header .btn-close{padding:.5rem .5rem;margin:-.5rem -.5rem -.5rem auto}.offcanvas-title{margin-bottom:0;line-height:1.5}.offcanvas-body{flex-grow:1;padding:1rem 1rem;overflow-y:auto}.offcanvas-start{top:0;left:0;width:400px;border-right:1px solid rgba(0,0,0,.2);transform:translateX(-100%)}.offcanvas-end{top:0;right:0;width:400px;border-left:1px solid rgba(0,0,0,.2);transform:translateX(100%)}.offcanvas-bottom{right:0;left:0;height:30vh;max-height:100%;border-top:1px solid rgba(0,0,0,.2);transform:translateY(100%)}.offcanvas.show{transform:none}.offcanvas-backdrop::before{position:fixed;top:0;left:0;z-index:1039;width:100vw;height:100vh;content:"";background-color:rgba(0,0,0,.5)}.clearfix::after{display:block;clear:both;content:""}.link-primary{color:#0d6efd}.link-primary:hover,.link-primary:focus{color:#0a58ca}.link-secondary{color:#6c757d}.link-secondary:hover,.link-secondary:focus{color:#565e64}.link-success{color:#198754}.link-success:hover,.link-success:focus{color:#146c43}.link-info{color:#0dcaf0}.link-info:hover,.link-info:focus{color:#3dd5f3}.link-warning{color:#ffc107}.link-warning:hover,.link-warning:focus{color:#ffcd39}.link-danger{color:#dc3545}.link-danger:hover,.link-danger:focus{color:#b02a37}.link-light{color:#f8f9fa}.link-light:hover,.link-light:focus{color:#f9fafb}.link-dark{color:#212529}.link-dark:hover,.link-dark:focus{color:#1a1e21}.ratio{position:relative;width:100%}.ratio::before{display:block;padding-top:var(--bs-aspect-ratio);content:""}.ratio>*{position:absolute;top:0;left:0;width:100%;height:100%}.ratio-1x1{--bs-aspect-ratio: 100%}.ratio-4x3{--bs-aspect-ratio: 75%}.ratio-16x9{--bs-aspect-ratio: 56.25%}.ratio-21x9{--bs-aspect-ratio: 42.8571428571%}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top{position:sticky;top:0;z-index:1020}@media (min-width: 576px){.sticky-sm-top{position:sticky;top:0;z-index:1020}}@media (min-width: 768px){.sticky-md-top{position:sticky;top:0;z-index:1020}}@media (min-width: 992px){.sticky-lg-top{position:sticky;top:0;z-index:1020}}@media (min-width: 1200px){.sticky-xl-top{position:sticky;top:0;z-index:1020}}@media (min-width: 1400px){.sticky-xxl-top{position:sticky;top:0;z-index:1020}}.visually-hidden,.visually-hidden-focusable:not(:focus):not(:focus-within){position:absolute !important;width:1px !important;height:1px !important;padding:0 !important;margin:-1px !important;overflow:hidden !important;clip:rect(0, 0, 0, 0) !important;white-space:nowrap !important;border:0 !important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.align-baseline{vertical-align:baseline !important}.align-top{vertical-align:top !important}.align-middle{vertical-align:middle !important}.align-bottom{vertical-align:bottom !important}.align-text-bottom{vertical-align:text-bottom !important}.align-text-top{vertical-align:text-top !important}.float-start{float:left !important}.float-end{float:right !important}.float-none{float:none !important}.overflow-auto{overflow:auto !important}.overflow-hidden{overflow:hidden !important}.overflow-visible{overflow:visible !important}.overflow-scroll{overflow:scroll !important}.d-inline{display:inline !important}.d-inline-block{display:inline-block !important}.d-block{display:block !important}.d-grid{display:grid !important}.d-table{display:table !important}.d-table-row{display:table-row !important}.d-table-cell{display:table-cell !important}.d-flex{display:flex !important}.d-inline-flex{display:inline-flex !important}.d-none{display:none !important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15) !important}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075) !important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175) !important}.shadow-none{box-shadow:none !important}.position-static{position:static !important}.position-relative{position:relative !important}.position-absolute{position:absolute !important}.position-fixed{position:fixed !important}.position-sticky{position:sticky !important}.top-0{top:0 !important}.top-50{top:50% !important}.top-100{top:100% !important}.bottom-0{bottom:0 !important}.bottom-50{bottom:50% !important}.bottom-100{bottom:100% !important}.start-0{left:0 !important}.start-50{left:50% !important}.start-100{left:100% !important}.end-0{right:0 !important}.end-50{right:50% !important}.end-100{right:100% !important}.translate-middle{transform:translate(-50%, -50%) !important}.translate-middle-x{transform:translateX(-50%) !important}.translate-middle-y{transform:translateY(-50%) !important}.border{border:1px solid #dee2e6 !important}.border-0{border:0 !important}.border-top{border-top:1px solid #dee2e6 !important}.border-top-0{border-top:0 !important}.border-end{border-right:1px solid #dee2e6 !important}.border-end-0{border-right:0 !important}.border-bottom{border-bottom:1px solid #dee2e6 !important}.border-bottom-0{border-bottom:0 !important}.border-start{border-left:1px solid #dee2e6 !important}.border-start-0{border-left:0 !important}.border-primary{border-color:#0d6efd !important}.border-secondary{border-color:#6c757d !important}.border-success{border-color:#198754 !important}.border-info{border-color:#0dcaf0 !important}.border-warning{border-color:#ffc107 !important}.border-danger{border-color:#dc3545 !important}.border-light{border-color:#f8f9fa !important}.border-dark{border-color:#212529 !important}.border-white{border-color:#fff !important}.border-1{border-width:1px !important}.border-2{border-width:2px !important}.border-3{border-width:3px !important}.border-4{border-width:4px !important}.border-5{border-width:5px !important}.w-25{width:25% !important}.w-50{width:50% !important}.w-75{width:75% !important}.w-100{width:100% !important}.w-auto{width:auto !important}.mw-100{max-width:100% !important}.vw-100{width:100vw !important}.min-vw-100{min-width:100vw !important}.h-25{height:25% !important}.h-50{height:50% !important}.h-75{height:75% !important}.h-100{height:100% !important}.h-auto{height:auto !important}.mh-100{max-height:100% !important}.vh-100{height:100vh !important}.min-vh-100{min-height:100vh !important}.flex-fill{flex:1 1 auto !important}.flex-row{flex-direction:row !important}.flex-column{flex-direction:column !important}.flex-row-reverse{flex-direction:row-reverse !important}.flex-column-reverse{flex-direction:column-reverse !important}.flex-grow-0{flex-grow:0 !important}.flex-grow-1{flex-grow:1 !important}.flex-shrink-0{flex-shrink:0 !important}.flex-shrink-1{flex-shrink:1 !important}.flex-wrap{flex-wrap:wrap !important}.flex-nowrap{flex-wrap:nowrap !important}.flex-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-0{gap:0 !important}.gap-1{gap:.25rem !important}.gap-2{gap:.5rem !important}.gap-3{gap:1rem !important}.gap-4{gap:1.5rem !important}.gap-5{gap:3rem !important}.justify-content-start{justify-content:flex-start !important}.justify-content-end{justify-content:flex-end !important}.justify-content-center{justify-content:center !important}.justify-content-between{justify-content:space-between !important}.justify-content-around{justify-content:space-around !important}.justify-content-evenly{justify-content:space-evenly !important}.align-items-start{align-items:flex-start !important}.align-items-end{align-items:flex-end !important}.align-items-center{align-items:center !important}.align-items-baseline{align-items:baseline !important}.align-items-stretch{align-items:stretch !important}.align-content-start{align-content:flex-start !important}.align-content-end{align-content:flex-end !important}.align-content-center{align-content:center !important}.align-content-between{align-content:space-between !important}.align-content-around{align-content:space-around !important}.align-content-stretch{align-content:stretch !important}.align-self-auto{align-self:auto !important}.align-self-start{align-self:flex-start !important}.align-self-end{align-self:flex-end !important}.align-self-center{align-self:center !important}.align-self-baseline{align-self:baseline !important}.align-self-stretch{align-self:stretch !important}.order-first{order:-1 !important}.order-0{order:0 !important}.order-1{order:1 !important}.order-2{order:2 !important}.order-3{order:3 !important}.order-4{order:4 !important}.order-5{order:5 !important}.order-last{order:6 !important}.m-0{margin:0 !important}.m-1{margin:.25rem !important}.m-2{margin:.5rem !important}.m-3{margin:1rem !important}.m-4{margin:1.5rem !important}.m-5{margin:3rem !important}.m-auto{margin:auto !important}.mx-0{margin-right:0 !important;margin-left:0 !important}.mx-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-3{margin-right:1rem !important;margin-left:1rem !important}.mx-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-5{margin-right:3rem !important;margin-left:3rem !important}.mx-auto{margin-right:auto !important;margin-left:auto !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.my-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-0{margin-top:0 !important}.mt-1{margin-top:.25rem !important}.mt-2{margin-top:.5rem !important}.mt-3{margin-top:1rem !important}.mt-4{margin-top:1.5rem !important}.mt-5{margin-top:3rem !important}.mt-auto{margin-top:auto !important}.me-0{margin-right:0 !important}.me-1{margin-right:.25rem !important}.me-2{margin-right:.5rem !important}.me-3{margin-right:1rem !important}.me-4{margin-right:1.5rem !important}.me-5{margin-right:3rem !important}.me-auto{margin-right:auto !important}.mb-0{margin-bottom:0 !important}.mb-1{margin-bottom:.25rem !important}.mb-2{margin-bottom:.5rem !important}.mb-3{margin-bottom:1rem !important}.mb-4{margin-bottom:1.5rem !important}.mb-5{margin-bottom:3rem !important}.mb-auto{margin-bottom:auto !important}.ms-0{margin-left:0 !important}.ms-1{margin-left:.25rem !important}.ms-2{margin-left:.5rem !important}.ms-3{margin-left:1rem !important}.ms-4{margin-left:1.5rem !important}.ms-5{margin-left:3rem !important}.ms-auto{margin-left:auto !important}.p-0{padding:0 !important}.p-1{padding:.25rem !important}.p-2{padding:.5rem !important}.p-3{padding:1rem !important}.p-4{padding:1.5rem !important}.p-5{padding:3rem !important}.px-0{padding-right:0 !important;padding-left:0 !important}.px-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-3{padding-right:1rem !important;padding-left:1rem !important}.px-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-5{padding-right:3rem !important;padding-left:3rem !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.py-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-0{padding-top:0 !important}.pt-1{padding-top:.25rem !important}.pt-2{padding-top:.5rem !important}.pt-3{padding-top:1rem !important}.pt-4{padding-top:1.5rem !important}.pt-5{padding-top:3rem !important}.pe-0{padding-right:0 !important}.pe-1{padding-right:.25rem !important}.pe-2{padding-right:.5rem !important}.pe-3{padding-right:1rem !important}.pe-4{padding-right:1.5rem !important}.pe-5{padding-right:3rem !important}.pb-0{padding-bottom:0 !important}.pb-1{padding-bottom:.25rem !important}.pb-2{padding-bottom:.5rem !important}.pb-3{padding-bottom:1rem !important}.pb-4{padding-bottom:1.5rem !important}.pb-5{padding-bottom:3rem !important}.ps-0{padding-left:0 !important}.ps-1{padding-left:.25rem !important}.ps-2{padding-left:.5rem !important}.ps-3{padding-left:1rem !important}.ps-4{padding-left:1.5rem !important}.ps-5{padding-left:3rem !important}.font-monospace{font-family:var(--bs-font-monospace) !important}.fs-1{font-size:calc(1.375rem + 1.5vw) !important}.fs-2{font-size:calc(1.325rem + .9vw) !important}.fs-3{font-size:calc(1.3rem + .6vw) !important}.fs-4{font-size:calc(1.275rem + .3vw) !important}.fs-5{font-size:1.25rem !important}.fs-6{font-size:1rem !important}.fst-italic{font-style:italic !important}.fst-normal{font-style:normal !important}.fw-light{font-weight:300 !important}.fw-lighter{font-weight:lighter !important}.fw-normal{font-weight:400 !important}.fw-bold{font-weight:700 !important}.fw-bolder{font-weight:bolder !important}.lh-1{line-height:1 !important}.lh-sm{line-height:1.25 !important}.lh-base{line-height:1.5 !important}.lh-lg{line-height:2 !important}.text-start{text-align:left !important}.text-end{text-align:right !important}.text-center{text-align:center !important}.text-decoration-none{text-decoration:none !important}.text-decoration-underline{text-decoration:underline !important}.text-decoration-line-through{text-decoration:line-through !important}.text-lowercase{text-transform:lowercase !important}.text-uppercase{text-transform:uppercase !important}.text-capitalize{text-transform:capitalize !important}.text-wrap{white-space:normal !important}.text-nowrap{white-space:nowrap !important}.text-break{word-wrap:break-word !important;word-break:break-word !important}.text-primary{color:#0d6efd !important}.text-secondary{color:#6c757d !important}.text-success{color:#198754 !important}.text-info{color:#0dcaf0 !important}.text-warning{color:#ffc107 !important}.text-danger{color:#dc3545 !important}.text-light{color:#f8f9fa !important}.text-dark{color:#212529 !important}.text-white{color:#fff !important}.text-body{color:#212529 !important}.text-muted{color:#6c757d !important}.text-black-50{color:rgba(0,0,0,.5) !important}.text-white-50{color:rgba(255,255,255,.5) !important}.text-reset{color:inherit !important}.bg-primary{background-color:#0d6efd !important}.bg-secondary{background-color:#6c757d !important}.bg-success{background-color:#198754 !important}.bg-info{background-color:#0dcaf0 !important}.bg-warning{background-color:#ffc107 !important}.bg-danger{background-color:#dc3545 !important}.bg-light{background-color:#f8f9fa !important}.bg-dark{background-color:#212529 !important}.bg-body{background-color:#fff !important}.bg-white{background-color:#fff !important}.bg-transparent{background-color:rgba(0,0,0,0) !important}.bg-gradient{background-image:var(--bs-gradient) !important}.user-select-all{user-select:all !important}.user-select-auto{user-select:auto !important}.user-select-none{user-select:none !important}.pe-none{pointer-events:none !important}.pe-auto{pointer-events:auto !important}.rounded{border-radius:.25rem !important}.rounded-0{border-radius:0 !important}.rounded-1{border-radius:.2rem !important}.rounded-2{border-radius:.25rem !important}.rounded-3{border-radius:.3rem !important}.rounded-circle{border-radius:50% !important}.rounded-pill{border-radius:50rem !important}.rounded-top{border-top-left-radius:.25rem !important;border-top-right-radius:.25rem !important}.rounded-end{border-top-right-radius:.25rem !important;border-bottom-right-radius:.25rem !important}.rounded-bottom{border-bottom-right-radius:.25rem !important;border-bottom-left-radius:.25rem !important}.rounded-start{border-bottom-left-radius:.25rem !important;border-top-left-radius:.25rem !important}.visible{visibility:visible !important}.invisible{visibility:hidden !important}@media (min-width: 576px){.float-sm-start{float:left !important}.float-sm-end{float:right !important}.float-sm-none{float:none !important}.d-sm-inline{display:inline !important}.d-sm-inline-block{display:inline-block !important}.d-sm-block{display:block !important}.d-sm-grid{display:grid !important}.d-sm-table{display:table !important}.d-sm-table-row{display:table-row !important}.d-sm-table-cell{display:table-cell !important}.d-sm-flex{display:flex !important}.d-sm-inline-flex{display:inline-flex !important}.d-sm-none{display:none !important}.flex-sm-fill{flex:1 1 auto !important}.flex-sm-row{flex-direction:row !important}.flex-sm-column{flex-direction:column !important}.flex-sm-row-reverse{flex-direction:row-reverse !important}.flex-sm-column-reverse{flex-direction:column-reverse !important}.flex-sm-grow-0{flex-grow:0 !important}.flex-sm-grow-1{flex-grow:1 !important}.flex-sm-shrink-0{flex-shrink:0 !important}.flex-sm-shrink-1{flex-shrink:1 !important}.flex-sm-wrap{flex-wrap:wrap !important}.flex-sm-nowrap{flex-wrap:nowrap !important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-sm-0{gap:0 !important}.gap-sm-1{gap:.25rem !important}.gap-sm-2{gap:.5rem !important}.gap-sm-3{gap:1rem !important}.gap-sm-4{gap:1.5rem !important}.gap-sm-5{gap:3rem !important}.justify-content-sm-start{justify-content:flex-start !important}.justify-content-sm-end{justify-content:flex-end !important}.justify-content-sm-center{justify-content:center !important}.justify-content-sm-between{justify-content:space-between !important}.justify-content-sm-around{justify-content:space-around !important}.justify-content-sm-evenly{justify-content:space-evenly !important}.align-items-sm-start{align-items:flex-start !important}.align-items-sm-end{align-items:flex-end !important}.align-items-sm-center{align-items:center !important}.align-items-sm-baseline{align-items:baseline !important}.align-items-sm-stretch{align-items:stretch !important}.align-content-sm-start{align-content:flex-start !important}.align-content-sm-end{align-content:flex-end !important}.align-content-sm-center{align-content:center !important}.align-content-sm-between{align-content:space-between !important}.align-content-sm-around{align-content:space-around !important}.align-content-sm-stretch{align-content:stretch !important}.align-self-sm-auto{align-self:auto !important}.align-self-sm-start{align-self:flex-start !important}.align-self-sm-end{align-self:flex-end !important}.align-self-sm-center{align-self:center !important}.align-self-sm-baseline{align-self:baseline !important}.align-self-sm-stretch{align-self:stretch !important}.order-sm-first{order:-1 !important}.order-sm-0{order:0 !important}.order-sm-1{order:1 !important}.order-sm-2{order:2 !important}.order-sm-3{order:3 !important}.order-sm-4{order:4 !important}.order-sm-5{order:5 !important}.order-sm-last{order:6 !important}.m-sm-0{margin:0 !important}.m-sm-1{margin:.25rem !important}.m-sm-2{margin:.5rem !important}.m-sm-3{margin:1rem !important}.m-sm-4{margin:1.5rem !important}.m-sm-5{margin:3rem !important}.m-sm-auto{margin:auto !important}.mx-sm-0{margin-right:0 !important;margin-left:0 !important}.mx-sm-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-sm-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-sm-3{margin-right:1rem !important;margin-left:1rem !important}.mx-sm-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-sm-5{margin-right:3rem !important;margin-left:3rem !important}.mx-sm-auto{margin-right:auto !important;margin-left:auto !important}.my-sm-0{margin-top:0 !important;margin-bottom:0 !important}.my-sm-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-sm-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-sm-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-sm-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-sm-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-sm-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-sm-0{margin-top:0 !important}.mt-sm-1{margin-top:.25rem !important}.mt-sm-2{margin-top:.5rem !important}.mt-sm-3{margin-top:1rem !important}.mt-sm-4{margin-top:1.5rem !important}.mt-sm-5{margin-top:3rem !important}.mt-sm-auto{margin-top:auto !important}.me-sm-0{margin-right:0 !important}.me-sm-1{margin-right:.25rem !important}.me-sm-2{margin-right:.5rem !important}.me-sm-3{margin-right:1rem !important}.me-sm-4{margin-right:1.5rem !important}.me-sm-5{margin-right:3rem !important}.me-sm-auto{margin-right:auto !important}.mb-sm-0{margin-bottom:0 !important}.mb-sm-1{margin-bottom:.25rem !important}.mb-sm-2{margin-bottom:.5rem !important}.mb-sm-3{margin-bottom:1rem !important}.mb-sm-4{margin-bottom:1.5rem !important}.mb-sm-5{margin-bottom:3rem !important}.mb-sm-auto{margin-bottom:auto !important}.ms-sm-0{margin-left:0 !important}.ms-sm-1{margin-left:.25rem !important}.ms-sm-2{margin-left:.5rem !important}.ms-sm-3{margin-left:1rem !important}.ms-sm-4{margin-left:1.5rem !important}.ms-sm-5{margin-left:3rem !important}.ms-sm-auto{margin-left:auto !important}.p-sm-0{padding:0 !important}.p-sm-1{padding:.25rem !important}.p-sm-2{padding:.5rem !important}.p-sm-3{padding:1rem !important}.p-sm-4{padding:1.5rem !important}.p-sm-5{padding:3rem !important}.px-sm-0{padding-right:0 !important;padding-left:0 !important}.px-sm-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-sm-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-sm-3{padding-right:1rem !important;padding-left:1rem !important}.px-sm-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-sm-5{padding-right:3rem !important;padding-left:3rem !important}.py-sm-0{padding-top:0 !important;padding-bottom:0 !important}.py-sm-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-sm-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-sm-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-sm-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-sm-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-sm-0{padding-top:0 !important}.pt-sm-1{padding-top:.25rem !important}.pt-sm-2{padding-top:.5rem !important}.pt-sm-3{padding-top:1rem !important}.pt-sm-4{padding-top:1.5rem !important}.pt-sm-5{padding-top:3rem !important}.pe-sm-0{padding-right:0 !important}.pe-sm-1{padding-right:.25rem !important}.pe-sm-2{padding-right:.5rem !important}.pe-sm-3{padding-right:1rem !important}.pe-sm-4{padding-right:1.5rem !important}.pe-sm-5{padding-right:3rem !important}.pb-sm-0{padding-bottom:0 !important}.pb-sm-1{padding-bottom:.25rem !important}.pb-sm-2{padding-bottom:.5rem !important}.pb-sm-3{padding-bottom:1rem !important}.pb-sm-4{padding-bottom:1.5rem !important}.pb-sm-5{padding-bottom:3rem !important}.ps-sm-0{padding-left:0 !important}.ps-sm-1{padding-left:.25rem !important}.ps-sm-2{padding-left:.5rem !important}.ps-sm-3{padding-left:1rem !important}.ps-sm-4{padding-left:1.5rem !important}.ps-sm-5{padding-left:3rem !important}.text-sm-start{text-align:left !important}.text-sm-end{text-align:right !important}.text-sm-center{text-align:center !important}}@media (min-width: 768px){.float-md-start{float:left !important}.float-md-end{float:right !important}.float-md-none{float:none !important}.d-md-inline{display:inline !important}.d-md-inline-block{display:inline-block !important}.d-md-block{display:block !important}.d-md-grid{display:grid !important}.d-md-table{display:table !important}.d-md-table-row{display:table-row !important}.d-md-table-cell{display:table-cell !important}.d-md-flex{display:flex !important}.d-md-inline-flex{display:inline-flex !important}.d-md-none{display:none !important}.flex-md-fill{flex:1 1 auto !important}.flex-md-row{flex-direction:row !important}.flex-md-column{flex-direction:column !important}.flex-md-row-reverse{flex-direction:row-reverse !important}.flex-md-column-reverse{flex-direction:column-reverse !important}.flex-md-grow-0{flex-grow:0 !important}.flex-md-grow-1{flex-grow:1 !important}.flex-md-shrink-0{flex-shrink:0 !important}.flex-md-shrink-1{flex-shrink:1 !important}.flex-md-wrap{flex-wrap:wrap !important}.flex-md-nowrap{flex-wrap:nowrap !important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-md-0{gap:0 !important}.gap-md-1{gap:.25rem !important}.gap-md-2{gap:.5rem !important}.gap-md-3{gap:1rem !important}.gap-md-4{gap:1.5rem !important}.gap-md-5{gap:3rem !important}.justify-content-md-start{justify-content:flex-start !important}.justify-content-md-end{justify-content:flex-end !important}.justify-content-md-center{justify-content:center !important}.justify-content-md-between{justify-content:space-between !important}.justify-content-md-around{justify-content:space-around !important}.justify-content-md-evenly{justify-content:space-evenly !important}.align-items-md-start{align-items:flex-start !important}.align-items-md-end{align-items:flex-end !important}.align-items-md-center{align-items:center !important}.align-items-md-baseline{align-items:baseline !important}.align-items-md-stretch{align-items:stretch !important}.align-content-md-start{align-content:flex-start !important}.align-content-md-end{align-content:flex-end !important}.align-content-md-center{align-content:center !important}.align-content-md-between{align-content:space-between !important}.align-content-md-around{align-content:space-around !important}.align-content-md-stretch{align-content:stretch !important}.align-self-md-auto{align-self:auto !important}.align-self-md-start{align-self:flex-start !important}.align-self-md-end{align-self:flex-end !important}.align-self-md-center{align-self:center !important}.align-self-md-baseline{align-self:baseline !important}.align-self-md-stretch{align-self:stretch !important}.order-md-first{order:-1 !important}.order-md-0{order:0 !important}.order-md-1{order:1 !important}.order-md-2{order:2 !important}.order-md-3{order:3 !important}.order-md-4{order:4 !important}.order-md-5{order:5 !important}.order-md-last{order:6 !important}.m-md-0{margin:0 !important}.m-md-1{margin:.25rem !important}.m-md-2{margin:.5rem !important}.m-md-3{margin:1rem !important}.m-md-4{margin:1.5rem !important}.m-md-5{margin:3rem !important}.m-md-auto{margin:auto !important}.mx-md-0{margin-right:0 !important;margin-left:0 !important}.mx-md-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-md-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-md-3{margin-right:1rem !important;margin-left:1rem !important}.mx-md-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-md-5{margin-right:3rem !important;margin-left:3rem !important}.mx-md-auto{margin-right:auto !important;margin-left:auto !important}.my-md-0{margin-top:0 !important;margin-bottom:0 !important}.my-md-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-md-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-md-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-md-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-md-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-md-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-md-0{margin-top:0 !important}.mt-md-1{margin-top:.25rem !important}.mt-md-2{margin-top:.5rem !important}.mt-md-3{margin-top:1rem !important}.mt-md-4{margin-top:1.5rem !important}.mt-md-5{margin-top:3rem !important}.mt-md-auto{margin-top:auto !important}.me-md-0{margin-right:0 !important}.me-md-1{margin-right:.25rem !important}.me-md-2{margin-right:.5rem !important}.me-md-3{margin-right:1rem !important}.me-md-4{margin-right:1.5rem !important}.me-md-5{margin-right:3rem !important}.me-md-auto{margin-right:auto !important}.mb-md-0{margin-bottom:0 !important}.mb-md-1{margin-bottom:.25rem !important}.mb-md-2{margin-bottom:.5rem !important}.mb-md-3{margin-bottom:1rem !important}.mb-md-4{margin-bottom:1.5rem !important}.mb-md-5{margin-bottom:3rem !important}.mb-md-auto{margin-bottom:auto !important}.ms-md-0{margin-left:0 !important}.ms-md-1{margin-left:.25rem !important}.ms-md-2{margin-left:.5rem !important}.ms-md-3{margin-left:1rem !important}.ms-md-4{margin-left:1.5rem !important}.ms-md-5{margin-left:3rem !important}.ms-md-auto{margin-left:auto !important}.p-md-0{padding:0 !important}.p-md-1{padding:.25rem !important}.p-md-2{padding:.5rem !important}.p-md-3{padding:1rem !important}.p-md-4{padding:1.5rem !important}.p-md-5{padding:3rem !important}.px-md-0{padding-right:0 !important;padding-left:0 !important}.px-md-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-md-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-md-3{padding-right:1rem !important;padding-left:1rem !important}.px-md-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-md-5{padding-right:3rem !important;padding-left:3rem !important}.py-md-0{padding-top:0 !important;padding-bottom:0 !important}.py-md-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-md-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-md-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-md-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-md-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-md-0{padding-top:0 !important}.pt-md-1{padding-top:.25rem !important}.pt-md-2{padding-top:.5rem !important}.pt-md-3{padding-top:1rem !important}.pt-md-4{padding-top:1.5rem !important}.pt-md-5{padding-top:3rem !important}.pe-md-0{padding-right:0 !important}.pe-md-1{padding-right:.25rem !important}.pe-md-2{padding-right:.5rem !important}.pe-md-3{padding-right:1rem !important}.pe-md-4{padding-right:1.5rem !important}.pe-md-5{padding-right:3rem !important}.pb-md-0{padding-bottom:0 !important}.pb-md-1{padding-bottom:.25rem !important}.pb-md-2{padding-bottom:.5rem !important}.pb-md-3{padding-bottom:1rem !important}.pb-md-4{padding-bottom:1.5rem !important}.pb-md-5{padding-bottom:3rem !important}.ps-md-0{padding-left:0 !important}.ps-md-1{padding-left:.25rem !important}.ps-md-2{padding-left:.5rem !important}.ps-md-3{padding-left:1rem !important}.ps-md-4{padding-left:1.5rem !important}.ps-md-5{padding-left:3rem !important}.text-md-start{text-align:left !important}.text-md-end{text-align:right !important}.text-md-center{text-align:center !important}}@media (min-width: 992px){.float-lg-start{float:left !important}.float-lg-end{float:right !important}.float-lg-none{float:none !important}.d-lg-inline{display:inline !important}.d-lg-inline-block{display:inline-block !important}.d-lg-block{display:block !important}.d-lg-grid{display:grid !important}.d-lg-table{display:table !important}.d-lg-table-row{display:table-row !important}.d-lg-table-cell{display:table-cell !important}.d-lg-flex{display:flex !important}.d-lg-inline-flex{display:inline-flex !important}.d-lg-none{display:none !important}.flex-lg-fill{flex:1 1 auto !important}.flex-lg-row{flex-direction:row !important}.flex-lg-column{flex-direction:column !important}.flex-lg-row-reverse{flex-direction:row-reverse !important}.flex-lg-column-reverse{flex-direction:column-reverse !important}.flex-lg-grow-0{flex-grow:0 !important}.flex-lg-grow-1{flex-grow:1 !important}.flex-lg-shrink-0{flex-shrink:0 !important}.flex-lg-shrink-1{flex-shrink:1 !important}.flex-lg-wrap{flex-wrap:wrap !important}.flex-lg-nowrap{flex-wrap:nowrap !important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-lg-0{gap:0 !important}.gap-lg-1{gap:.25rem !important}.gap-lg-2{gap:.5rem !important}.gap-lg-3{gap:1rem !important}.gap-lg-4{gap:1.5rem !important}.gap-lg-5{gap:3rem !important}.justify-content-lg-start{justify-content:flex-start !important}.justify-content-lg-end{justify-content:flex-end !important}.justify-content-lg-center{justify-content:center !important}.justify-content-lg-between{justify-content:space-between !important}.justify-content-lg-around{justify-content:space-around !important}.justify-content-lg-evenly{justify-content:space-evenly !important}.align-items-lg-start{align-items:flex-start !important}.align-items-lg-end{align-items:flex-end !important}.align-items-lg-center{align-items:center !important}.align-items-lg-baseline{align-items:baseline !important}.align-items-lg-stretch{align-items:stretch !important}.align-content-lg-start{align-content:flex-start !important}.align-content-lg-end{align-content:flex-end !important}.align-content-lg-center{align-content:center !important}.align-content-lg-between{align-content:space-between !important}.align-content-lg-around{align-content:space-around !important}.align-content-lg-stretch{align-content:stretch !important}.align-self-lg-auto{align-self:auto !important}.align-self-lg-start{align-self:flex-start !important}.align-self-lg-end{align-self:flex-end !important}.align-self-lg-center{align-self:center !important}.align-self-lg-baseline{align-self:baseline !important}.align-self-lg-stretch{align-self:stretch !important}.order-lg-first{order:-1 !important}.order-lg-0{order:0 !important}.order-lg-1{order:1 !important}.order-lg-2{order:2 !important}.order-lg-3{order:3 !important}.order-lg-4{order:4 !important}.order-lg-5{order:5 !important}.order-lg-last{order:6 !important}.m-lg-0{margin:0 !important}.m-lg-1{margin:.25rem !important}.m-lg-2{margin:.5rem !important}.m-lg-3{margin:1rem !important}.m-lg-4{margin:1.5rem !important}.m-lg-5{margin:3rem !important}.m-lg-auto{margin:auto !important}.mx-lg-0{margin-right:0 !important;margin-left:0 !important}.mx-lg-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-lg-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-lg-3{margin-right:1rem !important;margin-left:1rem !important}.mx-lg-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-lg-5{margin-right:3rem !important;margin-left:3rem !important}.mx-lg-auto{margin-right:auto !important;margin-left:auto !important}.my-lg-0{margin-top:0 !important;margin-bottom:0 !important}.my-lg-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-lg-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-lg-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-lg-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-lg-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-lg-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-lg-0{margin-top:0 !important}.mt-lg-1{margin-top:.25rem !important}.mt-lg-2{margin-top:.5rem !important}.mt-lg-3{margin-top:1rem !important}.mt-lg-4{margin-top:1.5rem !important}.mt-lg-5{margin-top:3rem !important}.mt-lg-auto{margin-top:auto !important}.me-lg-0{margin-right:0 !important}.me-lg-1{margin-right:.25rem !important}.me-lg-2{margin-right:.5rem !important}.me-lg-3{margin-right:1rem !important}.me-lg-4{margin-right:1.5rem !important}.me-lg-5{margin-right:3rem !important}.me-lg-auto{margin-right:auto !important}.mb-lg-0{margin-bottom:0 !important}.mb-lg-1{margin-bottom:.25rem !important}.mb-lg-2{margin-bottom:.5rem !important}.mb-lg-3{margin-bottom:1rem !important}.mb-lg-4{margin-bottom:1.5rem !important}.mb-lg-5{margin-bottom:3rem !important}.mb-lg-auto{margin-bottom:auto !important}.ms-lg-0{margin-left:0 !important}.ms-lg-1{margin-left:.25rem !important}.ms-lg-2{margin-left:.5rem !important}.ms-lg-3{margin-left:1rem !important}.ms-lg-4{margin-left:1.5rem !important}.ms-lg-5{margin-left:3rem !important}.ms-lg-auto{margin-left:auto !important}.p-lg-0{padding:0 !important}.p-lg-1{padding:.25rem !important}.p-lg-2{padding:.5rem !important}.p-lg-3{padding:1rem !important}.p-lg-4{padding:1.5rem !important}.p-lg-5{padding:3rem !important}.px-lg-0{padding-right:0 !important;padding-left:0 !important}.px-lg-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-lg-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-lg-3{padding-right:1rem !important;padding-left:1rem !important}.px-lg-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-lg-5{padding-right:3rem !important;padding-left:3rem !important}.py-lg-0{padding-top:0 !important;padding-bottom:0 !important}.py-lg-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-lg-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-lg-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-lg-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-lg-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-lg-0{padding-top:0 !important}.pt-lg-1{padding-top:.25rem !important}.pt-lg-2{padding-top:.5rem !important}.pt-lg-3{padding-top:1rem !important}.pt-lg-4{padding-top:1.5rem !important}.pt-lg-5{padding-top:3rem !important}.pe-lg-0{padding-right:0 !important}.pe-lg-1{padding-right:.25rem !important}.pe-lg-2{padding-right:.5rem !important}.pe-lg-3{padding-right:1rem !important}.pe-lg-4{padding-right:1.5rem !important}.pe-lg-5{padding-right:3rem !important}.pb-lg-0{padding-bottom:0 !important}.pb-lg-1{padding-bottom:.25rem !important}.pb-lg-2{padding-bottom:.5rem !important}.pb-lg-3{padding-bottom:1rem !important}.pb-lg-4{padding-bottom:1.5rem !important}.pb-lg-5{padding-bottom:3rem !important}.ps-lg-0{padding-left:0 !important}.ps-lg-1{padding-left:.25rem !important}.ps-lg-2{padding-left:.5rem !important}.ps-lg-3{padding-left:1rem !important}.ps-lg-4{padding-left:1.5rem !important}.ps-lg-5{padding-left:3rem !important}.text-lg-start{text-align:left !important}.text-lg-end{text-align:right !important}.text-lg-center{text-align:center !important}}@media (min-width: 1200px){.float-xl-start{float:left !important}.float-xl-end{float:right !important}.float-xl-none{float:none !important}.d-xl-inline{display:inline !important}.d-xl-inline-block{display:inline-block !important}.d-xl-block{display:block !important}.d-xl-grid{display:grid !important}.d-xl-table{display:table !important}.d-xl-table-row{display:table-row !important}.d-xl-table-cell{display:table-cell !important}.d-xl-flex{display:flex !important}.d-xl-inline-flex{display:inline-flex !important}.d-xl-none{display:none !important}.flex-xl-fill{flex:1 1 auto !important}.flex-xl-row{flex-direction:row !important}.flex-xl-column{flex-direction:column !important}.flex-xl-row-reverse{flex-direction:row-reverse !important}.flex-xl-column-reverse{flex-direction:column-reverse !important}.flex-xl-grow-0{flex-grow:0 !important}.flex-xl-grow-1{flex-grow:1 !important}.flex-xl-shrink-0{flex-shrink:0 !important}.flex-xl-shrink-1{flex-shrink:1 !important}.flex-xl-wrap{flex-wrap:wrap !important}.flex-xl-nowrap{flex-wrap:nowrap !important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-xl-0{gap:0 !important}.gap-xl-1{gap:.25rem !important}.gap-xl-2{gap:.5rem !important}.gap-xl-3{gap:1rem !important}.gap-xl-4{gap:1.5rem !important}.gap-xl-5{gap:3rem !important}.justify-content-xl-start{justify-content:flex-start !important}.justify-content-xl-end{justify-content:flex-end !important}.justify-content-xl-center{justify-content:center !important}.justify-content-xl-between{justify-content:space-between !important}.justify-content-xl-around{justify-content:space-around !important}.justify-content-xl-evenly{justify-content:space-evenly !important}.align-items-xl-start{align-items:flex-start !important}.align-items-xl-end{align-items:flex-end !important}.align-items-xl-center{align-items:center !important}.align-items-xl-baseline{align-items:baseline !important}.align-items-xl-stretch{align-items:stretch !important}.align-content-xl-start{align-content:flex-start !important}.align-content-xl-end{align-content:flex-end !important}.align-content-xl-center{align-content:center !important}.align-content-xl-between{align-content:space-between !important}.align-content-xl-around{align-content:space-around !important}.align-content-xl-stretch{align-content:stretch !important}.align-self-xl-auto{align-self:auto !important}.align-self-xl-start{align-self:flex-start !important}.align-self-xl-end{align-self:flex-end !important}.align-self-xl-center{align-self:center !important}.align-self-xl-baseline{align-self:baseline !important}.align-self-xl-stretch{align-self:stretch !important}.order-xl-first{order:-1 !important}.order-xl-0{order:0 !important}.order-xl-1{order:1 !important}.order-xl-2{order:2 !important}.order-xl-3{order:3 !important}.order-xl-4{order:4 !important}.order-xl-5{order:5 !important}.order-xl-last{order:6 !important}.m-xl-0{margin:0 !important}.m-xl-1{margin:.25rem !important}.m-xl-2{margin:.5rem !important}.m-xl-3{margin:1rem !important}.m-xl-4{margin:1.5rem !important}.m-xl-5{margin:3rem !important}.m-xl-auto{margin:auto !important}.mx-xl-0{margin-right:0 !important;margin-left:0 !important}.mx-xl-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-xl-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-xl-3{margin-right:1rem !important;margin-left:1rem !important}.mx-xl-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-xl-5{margin-right:3rem !important;margin-left:3rem !important}.mx-xl-auto{margin-right:auto !important;margin-left:auto !important}.my-xl-0{margin-top:0 !important;margin-bottom:0 !important}.my-xl-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-xl-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-xl-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-xl-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-xl-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-xl-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-xl-0{margin-top:0 !important}.mt-xl-1{margin-top:.25rem !important}.mt-xl-2{margin-top:.5rem !important}.mt-xl-3{margin-top:1rem !important}.mt-xl-4{margin-top:1.5rem !important}.mt-xl-5{margin-top:3rem !important}.mt-xl-auto{margin-top:auto !important}.me-xl-0{margin-right:0 !important}.me-xl-1{margin-right:.25rem !important}.me-xl-2{margin-right:.5rem !important}.me-xl-3{margin-right:1rem !important}.me-xl-4{margin-right:1.5rem !important}.me-xl-5{margin-right:3rem !important}.me-xl-auto{margin-right:auto !important}.mb-xl-0{margin-bottom:0 !important}.mb-xl-1{margin-bottom:.25rem !important}.mb-xl-2{margin-bottom:.5rem !important}.mb-xl-3{margin-bottom:1rem !important}.mb-xl-4{margin-bottom:1.5rem !important}.mb-xl-5{margin-bottom:3rem !important}.mb-xl-auto{margin-bottom:auto !important}.ms-xl-0{margin-left:0 !important}.ms-xl-1{margin-left:.25rem !important}.ms-xl-2{margin-left:.5rem !important}.ms-xl-3{margin-left:1rem !important}.ms-xl-4{margin-left:1.5rem !important}.ms-xl-5{margin-left:3rem !important}.ms-xl-auto{margin-left:auto !important}.p-xl-0{padding:0 !important}.p-xl-1{padding:.25rem !important}.p-xl-2{padding:.5rem !important}.p-xl-3{padding:1rem !important}.p-xl-4{padding:1.5rem !important}.p-xl-5{padding:3rem !important}.px-xl-0{padding-right:0 !important;padding-left:0 !important}.px-xl-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-xl-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-xl-3{padding-right:1rem !important;padding-left:1rem !important}.px-xl-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-xl-5{padding-right:3rem !important;padding-left:3rem !important}.py-xl-0{padding-top:0 !important;padding-bottom:0 !important}.py-xl-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-xl-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-xl-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-xl-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-xl-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-xl-0{padding-top:0 !important}.pt-xl-1{padding-top:.25rem !important}.pt-xl-2{padding-top:.5rem !important}.pt-xl-3{padding-top:1rem !important}.pt-xl-4{padding-top:1.5rem !important}.pt-xl-5{padding-top:3rem !important}.pe-xl-0{padding-right:0 !important}.pe-xl-1{padding-right:.25rem !important}.pe-xl-2{padding-right:.5rem !important}.pe-xl-3{padding-right:1rem !important}.pe-xl-4{padding-right:1.5rem !important}.pe-xl-5{padding-right:3rem !important}.pb-xl-0{padding-bottom:0 !important}.pb-xl-1{padding-bottom:.25rem !important}.pb-xl-2{padding-bottom:.5rem !important}.pb-xl-3{padding-bottom:1rem !important}.pb-xl-4{padding-bottom:1.5rem !important}.pb-xl-5{padding-bottom:3rem !important}.ps-xl-0{padding-left:0 !important}.ps-xl-1{padding-left:.25rem !important}.ps-xl-2{padding-left:.5rem !important}.ps-xl-3{padding-left:1rem !important}.ps-xl-4{padding-left:1.5rem !important}.ps-xl-5{padding-left:3rem !important}.text-xl-start{text-align:left !important}.text-xl-end{text-align:right !important}.text-xl-center{text-align:center !important}}@media (min-width: 1400px){.float-xxl-start{float:left !important}.float-xxl-end{float:right !important}.float-xxl-none{float:none !important}.d-xxl-inline{display:inline !important}.d-xxl-inline-block{display:inline-block !important}.d-xxl-block{display:block !important}.d-xxl-grid{display:grid !important}.d-xxl-table{display:table !important}.d-xxl-table-row{display:table-row !important}.d-xxl-table-cell{display:table-cell !important}.d-xxl-flex{display:flex !important}.d-xxl-inline-flex{display:inline-flex !important}.d-xxl-none{display:none !important}.flex-xxl-fill{flex:1 1 auto !important}.flex-xxl-row{flex-direction:row !important}.flex-xxl-column{flex-direction:column !important}.flex-xxl-row-reverse{flex-direction:row-reverse !important}.flex-xxl-column-reverse{flex-direction:column-reverse !important}.flex-xxl-grow-0{flex-grow:0 !important}.flex-xxl-grow-1{flex-grow:1 !important}.flex-xxl-shrink-0{flex-shrink:0 !important}.flex-xxl-shrink-1{flex-shrink:1 !important}.flex-xxl-wrap{flex-wrap:wrap !important}.flex-xxl-nowrap{flex-wrap:nowrap !important}.flex-xxl-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-xxl-0{gap:0 !important}.gap-xxl-1{gap:.25rem !important}.gap-xxl-2{gap:.5rem !important}.gap-xxl-3{gap:1rem !important}.gap-xxl-4{gap:1.5rem !important}.gap-xxl-5{gap:3rem !important}.justify-content-xxl-start{justify-content:flex-start !important}.justify-content-xxl-end{justify-content:flex-end !important}.justify-content-xxl-center{justify-content:center !important}.justify-content-xxl-between{justify-content:space-between !important}.justify-content-xxl-around{justify-content:space-around !important}.justify-content-xxl-evenly{justify-content:space-evenly !important}.align-items-xxl-start{align-items:flex-start !important}.align-items-xxl-end{align-items:flex-end !important}.align-items-xxl-center{align-items:center !important}.align-items-xxl-baseline{align-items:baseline !important}.align-items-xxl-stretch{align-items:stretch !important}.align-content-xxl-start{align-content:flex-start !important}.align-content-xxl-end{align-content:flex-end !important}.align-content-xxl-center{align-content:center !important}.align-content-xxl-between{align-content:space-between !important}.align-content-xxl-around{align-content:space-around !important}.align-content-xxl-stretch{align-content:stretch !important}.align-self-xxl-auto{align-self:auto !important}.align-self-xxl-start{align-self:flex-start !important}.align-self-xxl-end{align-self:flex-end !important}.align-self-xxl-center{align-self:center !important}.align-self-xxl-baseline{align-self:baseline !important}.align-self-xxl-stretch{align-self:stretch !important}.order-xxl-first{order:-1 !important}.order-xxl-0{order:0 !important}.order-xxl-1{order:1 !important}.order-xxl-2{order:2 !important}.order-xxl-3{order:3 !important}.order-xxl-4{order:4 !important}.order-xxl-5{order:5 !important}.order-xxl-last{order:6 !important}.m-xxl-0{margin:0 !important}.m-xxl-1{margin:.25rem !important}.m-xxl-2{margin:.5rem !important}.m-xxl-3{margin:1rem !important}.m-xxl-4{margin:1.5rem !important}.m-xxl-5{margin:3rem !important}.m-xxl-auto{margin:auto !important}.mx-xxl-0{margin-right:0 !important;margin-left:0 !important}.mx-xxl-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-xxl-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-xxl-3{margin-right:1rem !important;margin-left:1rem !important}.mx-xxl-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-xxl-5{margin-right:3rem !important;margin-left:3rem !important}.mx-xxl-auto{margin-right:auto !important;margin-left:auto !important}.my-xxl-0{margin-top:0 !important;margin-bottom:0 !important}.my-xxl-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-xxl-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-xxl-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-xxl-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-xxl-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-xxl-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-xxl-0{margin-top:0 !important}.mt-xxl-1{margin-top:.25rem !important}.mt-xxl-2{margin-top:.5rem !important}.mt-xxl-3{margin-top:1rem !important}.mt-xxl-4{margin-top:1.5rem !important}.mt-xxl-5{margin-top:3rem !important}.mt-xxl-auto{margin-top:auto !important}.me-xxl-0{margin-right:0 !important}.me-xxl-1{margin-right:.25rem !important}.me-xxl-2{margin-right:.5rem !important}.me-xxl-3{margin-right:1rem !important}.me-xxl-4{margin-right:1.5rem !important}.me-xxl-5{margin-right:3rem !important}.me-xxl-auto{margin-right:auto !important}.mb-xxl-0{margin-bottom:0 !important}.mb-xxl-1{margin-bottom:.25rem !important}.mb-xxl-2{margin-bottom:.5rem !important}.mb-xxl-3{margin-bottom:1rem !important}.mb-xxl-4{margin-bottom:1.5rem !important}.mb-xxl-5{margin-bottom:3rem !important}.mb-xxl-auto{margin-bottom:auto !important}.ms-xxl-0{margin-left:0 !important}.ms-xxl-1{margin-left:.25rem !important}.ms-xxl-2{margin-left:.5rem !important}.ms-xxl-3{margin-left:1rem !important}.ms-xxl-4{margin-left:1.5rem !important}.ms-xxl-5{margin-left:3rem !important}.ms-xxl-auto{margin-left:auto !important}.p-xxl-0{padding:0 !important}.p-xxl-1{padding:.25rem !important}.p-xxl-2{padding:.5rem !important}.p-xxl-3{padding:1rem !important}.p-xxl-4{padding:1.5rem !important}.p-xxl-5{padding:3rem !important}.px-xxl-0{padding-right:0 !important;padding-left:0 !important}.px-xxl-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-xxl-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-xxl-3{padding-right:1rem !important;padding-left:1rem !important}.px-xxl-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-xxl-5{padding-right:3rem !important;padding-left:3rem !important}.py-xxl-0{padding-top:0 !important;padding-bottom:0 !important}.py-xxl-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-xxl-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-xxl-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-xxl-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-xxl-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-xxl-0{padding-top:0 !important}.pt-xxl-1{padding-top:.25rem !important}.pt-xxl-2{padding-top:.5rem !important}.pt-xxl-3{padding-top:1rem !important}.pt-xxl-4{padding-top:1.5rem !important}.pt-xxl-5{padding-top:3rem !important}.pe-xxl-0{padding-right:0 !important}.pe-xxl-1{padding-right:.25rem !important}.pe-xxl-2{padding-right:.5rem !important}.pe-xxl-3{padding-right:1rem !important}.pe-xxl-4{padding-right:1.5rem !important}.pe-xxl-5{padding-right:3rem !important}.pb-xxl-0{padding-bottom:0 !important}.pb-xxl-1{padding-bottom:.25rem !important}.pb-xxl-2{padding-bottom:.5rem !important}.pb-xxl-3{padding-bottom:1rem !important}.pb-xxl-4{padding-bottom:1.5rem !important}.pb-xxl-5{padding-bottom:3rem !important}.ps-xxl-0{padding-left:0 !important}.ps-xxl-1{padding-left:.25rem !important}.ps-xxl-2{padding-left:.5rem !important}.ps-xxl-3{padding-left:1rem !important}.ps-xxl-4{padding-left:1.5rem !important}.ps-xxl-5{padding-left:3rem !important}.text-xxl-start{text-align:left !important}.text-xxl-end{text-align:right !important}.text-xxl-center{text-align:center !important}}@media (min-width: 1200px){.fs-1{font-size:2.5rem !important}.fs-2{font-size:2rem !important}.fs-3{font-size:1.75rem !important}.fs-4{font-size:1.5rem !important}}@media print{.d-print-inline{display:inline !important}.d-print-inline-block{display:inline-block !important}.d-print-block{display:block !important}.d-print-grid{display:grid !important}.d-print-table{display:table !important}.d-print-table-row{display:table-row !important}.d-print-table-cell{display:table-cell !important}.d-print-flex{display:flex !important}.d-print-inline-flex{display:inline-flex !important}.d-print-none{display:none !important}} \ No newline at end of file diff --git a/docs/getting-started/index.html b/docs/getting-started/index.html new file mode 100644 index 0000000000..0b7e9623d8 --- /dev/null +++ b/docs/getting-started/index.html @@ -0,0 +1,259 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Getting Started | FTL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/getting-started/introduction/index.html b/docs/getting-started/introduction/index.html new file mode 100644 index 0000000000..427db89d10 --- /dev/null +++ b/docs/getting-started/introduction/index.html @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Introduction | FTL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+ +
+ +
+ + + + + + +
+

Introduction

+ +

FTL is tooling, runtimes, and frameworks for simplifying the creation of distributed systems.

+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ Start → +
+
+
+ + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/getting-started/quick-start/console.png b/docs/getting-started/quick-start/console.png new file mode 100644 index 0000000000..04616f0631 Binary files /dev/null and b/docs/getting-started/quick-start/console.png differ diff --git a/docs/getting-started/quick-start/consolecall.png b/docs/getting-started/quick-start/consolecall.png new file mode 100644 index 0000000000..2503cd4af8 Binary files /dev/null and b/docs/getting-started/quick-start/consolecall.png differ diff --git a/docs/getting-started/quick-start/ftlcall.png b/docs/getting-started/quick-start/ftlcall.png new file mode 100644 index 0000000000..959db03836 Binary files /dev/null and b/docs/getting-started/quick-start/ftlcall.png differ diff --git a/docs/getting-started/quick-start/ftldev.png b/docs/getting-started/quick-start/ftldev.png new file mode 100644 index 0000000000..6830091e2b Binary files /dev/null and b/docs/getting-started/quick-start/ftldev.png differ diff --git a/docs/getting-started/quick-start/index.html b/docs/getting-started/quick-start/index.html new file mode 100644 index 0000000000..73ba2be6af --- /dev/null +++ b/docs/getting-started/quick-start/index.html @@ -0,0 +1,619 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Quick Start | FTL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+ +
+ +
+ + + + + + +
+

Quick Start

+

One page summary of how to start a new FTL project.

+

Requirements

+

Install the FTL CLI

+

Install the FTL CLI via Hermit, Homebrew, or manually.

+
+ + +

Hermit (Mac or Linux)

+

FTL can be installed from the main Hermit package repository by simply:

+
hermit install ftl
+
+

Alternatively you can add hermit-ftl to your sources by adding the following to your Hermit environment's bin/hermit.hcl file:

+
sources = ["https://github.com/block/hermit-ftl.git", "https://github.com/cashapp/hermit-packages.git"]
+
+ +

Homebrew (Mac or Linux)

+
brew tap block/ftl && brew install ftl
+
+ +

Manually (Mac or Linux)

+

Download binaries from the latest release page and place them in your $PATH.

+
+
+

Install the VSCode extension

+

The FTL VSCode extension will run FTL within VSCode, and provide LSP support for FTL, displaying errors within the editor.

+

Development

+

Intitialize an FTL project

+

Once FTL is installed, initialize an FTL project:

+
mkdir myproject
+cd myproject
+ftl init myproject . --hermit
+
+

This will create an ftl-project.toml file, a git repository, and a bin/ directory with Hermit tooling.

+

Create a new module

+

Now that you have an FTL project, create a new module:

+
+ + +
ftl new go alice
+
+

This will place the code for the new module alice in myproject/alice/alice.go:

+
package alice
+
+import (
+	"context"
+	"fmt"
+
+	"github.com/block/ftl/go-runtime/ftl" // Import the FTL SDK.
+)
+
+type EchoRequest struct {
+	Name ftl.Option[string] `json:"name"`
+}
+
+type EchoResponse struct {
+	Message string `json:"message"`
+}
+
+//ftl:verb
+func Echo(ctx context.Context, req EchoRequest) (EchoResponse, error) {
+	return EchoResponse{Message: fmt.Sprintf("Hello, %s!", req.Name.Default("anonymous"))}, nil
+}
+
+

Each module is its own Go module.

+ +
ftl new kotlin alice
+
+

This will create a new Maven pom.xml based project in the directory alice and create new example code in alice/src/main/kotlin/com/example/EchoVerb.kt:

+
package com.example
+
+import xyz.block.ftl.Export
+import xyz.block.ftl.Verb
+
+
+@Export
+@Verb
+fun echo(req: String): String = "Hello, $req!"
+
+ +
ftl new java alice
+
+

This will create a new Maven pom.xml based project in the directory alice and create new example code in alice/src/main/java/com/example/EchoVerb.java:

+
package com.example;
+
+import xyz.block.ftl.Export;
+import xyz.block.ftl.Verb;
+
+public class EchoVerb {
+
+    @Export
+    @Verb
+    public String echo(String request) {
+        return "Hello, " + request + "!";
+    }
+}
+
+
+

Any number of modules can be added to your project, adjacent to each other.

+

Start the FTL cluster

+

VSCode

+

If using VSCode, opening the directory will prompt you to start FTL:

+

VSCode

+

Manually

+

Alternatively start the local FTL development cluster from the command-line:

+

ftl dev

+

This will build and deploy all local modules. Modifying the code will cause ftl dev to rebuild and redeploy the module.

+

Open the console

+

FTL has a console that allows interaction with the cluster topology, logs, traces, +and more. Open a browser window at https://localhost:8899 to view it:

+

FTL Console

+

Call your verb

+

You can call verbs from the console:

+

console call

+

Or from a terminal use ftl call to call your verb:

+

ftl call

+

Create another module

+

Create another module and call alice.echo from it with by importing the alice module and adding the verb client, +alice.EchoClient, to the signature of the calling verb. It can be invoked as a function:

+
+ + +
//ftl:verb
+import "ftl/alice"
+
+//ftl:verb
+func Other(ctx context.Context, in Request, ec alice.EchoClient) (Response, error) {
+    out, err := ec(ctx, alice.EchoRequest{...})
+	...
+}
+
+ +
package com.example
+
+import xyz.block.ftl.Export
+import xyz.block.ftl.Verb
+import ftl.alice.EchoClient
+
+
+@Export
+@Verb
+fun other(req: String, echo: EchoClient): String = "Hello from Other , ${echo.call(req)}!"
+
+

Note that the EchoClient is generated by FTL and must be imported. Unfortunately at the moment JVM based languages have +a bit of a chicken-and-egg problem with the generated clients. To force a dependency between the modules you need to add +an import on a class that does not exist yet, and then FTL will generate the client for you. This will be fixed in the future.

+ +
package com.example.client;
+
+import xyz.block.ftl.Export;
+import xyz.block.ftl.Verb;
+import ftl.alice.EchoClient;
+
+public class OtherVerb {
+
+    @Export
+    @Verb
+    public String other(String request, EchoClient echoClient) {
+        return "Hello, " + echoClient.call(request) + "!";
+    }
+}
+
+

Note that the EchoClient is generated by FTL and must be imported. Unfortunately at the moment JVM based languages have +a bit of a chicken-and-egg problem with the generated clients. To force a dependency between the modules you need to add +an import on a class that does not exist yet, and then FTL will generate the client for you. This will be fixed in the future.

+ +
+

What next?

+

Explore the reference documentation.

+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ Start → +
+
+
+ + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/getting-started/quick-start/vscode.png b/docs/getting-started/quick-start/vscode.png new file mode 100644 index 0000000000..d1a5111c17 Binary files /dev/null and b/docs/getting-started/quick-start/vscode.png differ diff --git a/docs/help/faq/index.html b/docs/help/faq/index.html new file mode 100644 index 0000000000..2d1400a63d --- /dev/null +++ b/docs/help/faq/index.html @@ -0,0 +1,488 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +FAQ | FTL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+ +
+ +
+ + + + + + +
+

FAQ

+

Answers to frequently asked questions.

+

Why does FTL not allow external types directly?

+

Because of the nature of writing FTL verbs and data types, it's easy to think of it as just writing standard native code. Through that lens it is then somewhat surprising when FTL disallows the use of arbitrary external data types.

+

However, FTL types are not just native types. FTL types are a more convenient method of writing an IDL such as Protobufs, OpenAPI or Thrift. With this in mind the constraint makes more sense. An IDL by its very nature must support a multitude of languages, so including an arbitrary type from a third party native library in one language may not be translatable to another language.

+

There are also secondary reasons, such as:

+
    +
  • Unclear ownership - in FTL a type must be owned by a single module. When importing a common third party type from multiple modules, which module owns that type?
  • +
  • An external type must be representable in the FTL schema. The schema is then used to generate types for other modules, including those in other languages. For an external type, FTL could track the external library it belongs to to generate the "correct" code, but this would only be representable in a single language.
  • +
  • External types often perform custom marshalling to/from JSON. This is not representable cross-language.
  • +
  • Cleaner separation of abstraction layers - the ability to mix in abitrary external types is convenient, but can easily lead to mixing of concerns between internal and external data representations.
  • +
+

So what to do? See the external types documentation +for how to work around this limitation.

+

What is a "module"?

+

In its least abstract form, a module is a collection of verbs, and the resources (databases, queues, cron jobs, secrets, config, etc.) that those verbs rely on to operate. All resources are private to their owning module.

+

More abstractly, the separation of concerns between modules is largely subjective. You can think of each module as largely analogous to a traditional service, so when asking where the division between modules is that could inform your decision. That said, the ease of deploying modules in FTL is designed to give you more flexibility in how you structure your code.

+

How do I represent optional/nullable values?

+

FTL's type system includes support for optionals. In Go this is represented as ftl.Option[T], in languages with first-class support for optionals such as Kotlin, FTL will leverage the native type system.

+

When FTL is mapping to JSON, optional values will be represented as null.

+

In Go specifically, pointers to values are not supported because pointers are semantically ambiguous and error prone. They can mean, variously: "this value may or may not be present", or "this value just happens to be a pointer", or "this value is a pointer because it's mutable"

+

Additionally pointers to builtin types are painful to use in Go because you can't obtain a reference to a literal.

+

Why must requests/responses be data structures, can't they be arrays, etc.?

+

This is currently due to FTL relying on traditional schema evolution for forwards/backwards compatibility - eg. changing a slice to a struct in a backward compatible way is not possible, as an existing deployed peer consuming the slice will fail if it suddenly changes to a data structure.

+

Eventually FTL will allow multiple versions of a verb to be simultaneously deployed, such that a version returning a slice can coexist temporarily with a version returning a struct. Once all peers have been updated to support the new type signature, the old version will be dropped.

+

I can't export a Verb from a nested package inside a subdirectory of the module root. What do I do?

+

Verbs and types can only be exported from the top level of each module. You are welcome to put any helper code you'd like in a nested package/directory.

+

What types are supported by FTL?

+

FTL supports the following types: Int (64-bit), Float (64-bit), String, Bytes (a byte array), Bool, Time, Any (a dynamic type), Unit (similar to "void"), arrays, maps, data structures, and constant enumerations. Each FTL type is mapped to a corresponding language-specific type. For example in Go Float is represented as float64, Time is represented by time.Time, and so on.

+

Note that currently (until type widening is implemented), external types are not supported.

+

SQL errors on startup?

+

For example:

+
# ftl dev                                                                                            ~/src/ftl
+info: Starting FTL with 1 controller(s)
+ftl: error: ERROR: relation "fsm_executions" does not exist (SQLSTATE 42P01)
+
+

Run again with ftl dev. This usually indicates that your DB has an old schema.

+

This can occur when FTL has been upgraded with schema changes, making the database out of date. While in alpha we do not use schema migrations, so this won't occur once we hit a stable release.

+ + + +
+ + + + + + + + + + + + + + + + + + + + + +
+
+ ← Metrics +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/help/glossary/index.html b/docs/help/glossary/index.html new file mode 100644 index 0000000000..913498fe38 --- /dev/null +++ b/docs/help/glossary/index.html @@ -0,0 +1,459 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Glossary | FTL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+ +
+ +
+ + + + + + +
+

Glossary

+

Glossary of terms and definitions in FTL.

+
Verb
+

A Verb is a remotely callable function that takes an input and returns an output.

+
func(context.Context, In) (Out, error)
+
+
Sink
+

A Sink is a function that takes an input and returns nothing.

+
func(context.Context, In) error
+
+
Source
+

A Source is a function that takes no input and returns an output.

+
func(context.Context) (Out, error)
+
+
Empty
+

An Empty function is one that takes neither input or output.

+
func(context.Context) error
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + +
+
+ ← Metrics +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/help/index.html b/docs/help/index.html new file mode 100644 index 0000000000..d2cd3c24d3 --- /dev/null +++ b/docs/help/index.html @@ -0,0 +1,256 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Help | FTL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000000..6012b191c1 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,348 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Docs | FTL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/observability/index.html b/docs/observability/index.html new file mode 100644 index 0000000000..c363b1846c --- /dev/null +++ b/docs/observability/index.html @@ -0,0 +1,250 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Observability | FTL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+
+
+

Observability

+
+
+ + + +
+ +
+ + +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/observability/metrics/index.html b/docs/observability/metrics/index.html new file mode 100644 index 0000000000..1b3beee737 --- /dev/null +++ b/docs/observability/metrics/index.html @@ -0,0 +1,597 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Metrics | FTL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+ +
+ +
+ + + + + + +
+

Metrics

+ +

FTL collects and exports a variety of metrics to help you monitor and understand the behavior of your FTL deployment using OTEL. This allows cluster operators to consume metrics in their preferred monitoring system e.g. Prometheus, Grafana, Datadog etc.

+

Note on Metric Types:

+
    +
  • Counters typically have a _total suffix in Prometheus, which is omitted here for brevity.
  • +
  • Histograms typically have _bucket, _sum, and _count variants, with _bucket including multiple entries for different bucket boundaries.
  • +
  • Gauges represent a single numerical value that can go up and down.
  • +
+

Note: this documentation is incomplete

+

FTL Metrics

+

Metrics Table

+ + + + + + + + + + + + +
Metric NameTypeDescription
ftl.async_call.acquiredCounterNumber of times an async call was acquired
ftl.async_call.completedCounterNumber of completed async calls
ftl.async_call.createdCounterNumber of created async calls
ftl.async_call.executedCounterNumber of executed async calls
ftl.async_call.ms_to_completeHistogramTime taken to complete async calls in milliseconds
ftl.async_call.queue_depth_ratioGaugeRatio of queued async calls
ftl.call.ms_to_completeHistogramTime taken to complete calls in milliseconds
ftl.call.requestsCounterTotal number of call requests
ftl.deployments.runner.activeGaugeNumber of active deployment runners
ftl.runner.registration.heartbeatsCounterTotal number of runner registration heartbeats
ftl.timeline.insertedCounterTotal number of timeline insertions
+

Attributes

+

Attributes provide additional context and dimensions for metrics and are often used for analysis and filtering. Each section below represents an attribute key that is collected for a specific set of metrics.

+

ftl.async_call.catching

+
    +
  • ftl.async_call.acquired
  • +
  • ftl.async_call.completed
  • +
  • ftl.async_call.created
  • +
  • ftl.async_call.executed
  • +
  • ftl.async_call.ms_to_complete
  • +
+

ftl.async_call.origin

+
    +
  • ftl.async_call.acquired
  • +
  • ftl.async_call.completed
  • +
  • ftl.async_call.created
  • +
  • ftl.async_call.executed
  • +
  • ftl.async_call.ms_to_complete
  • +
+

ftl.async_call.time_since_scheduled_at_ms.bucket

+
    +
  • ftl.async_call.acquired
  • +
  • ftl.async_call.completed
  • +
  • ftl.async_call.executed
  • +
+

ftl.async_call.verb.ref

+
    +
  • ftl.async_call.acquired
  • +
  • ftl.async_call.completed
  • +
  • ftl.async_call.created
  • +
  • ftl.async_call.executed
  • +
  • ftl.async_call.ms_to_complete
  • +
+

ftl.module.name

+
    +
  • ftl.async_call.acquired
  • +
  • ftl.async_call.completed
  • +
  • ftl.async_call.created
  • +
  • ftl.async_call.executed
  • +
  • ftl.async_call.ms_to_complete
  • +
  • ftl.call.ms_to_complete
  • +
  • ftl.call.requests
  • +
+

ftl.outcome.status

+
    +
  • ftl.async_call.acquired
  • +
  • ftl.async_call.completed
  • +
  • ftl.async_call.created
  • +
  • ftl.async_call.executed
  • +
  • ftl.async_call.ms_to_complete
  • +
  • ftl.call.ms_to_complete
  • +
  • ftl.call.requests
  • +
+

ftl.async_call.remaining_attempts

+
    +
  • ftl.async_call.created
  • +
+

ftl.call.verb.ref

+
    +
  • ftl.call.ms_to_complete
  • +
  • ftl.call.requests
  • +
+

ftl.call.run_time_ms.bucket

+
    +
  • ftl.call.requests
  • +
+

ftl.deployment.key

+
    +
  • ftl.deployments.runner.active
  • +
  • ftl.runner.registration.heartbeats
  • +
+

DB Metrics

+

DB Metrics are collected from the SQL database used by FTL. These metrics provide insights into the database connection pool, query latency etc.

+

Metrics Table

+ + + + + + + + + +
Metric NameTypeDescription
db.sql.connection.closed_max_idle_timeCounterTotal number of connections closed due to max idle time
db.sql.connection.closed_max_idleCounterTotal number of connections closed due to max idle connections
db.sql.connection.closed_max_lifetimeCounterTotal number of connections closed due to max lifetime
db.sql.connection.max_openGaugeMaximum number of open connections
db.sql.connection.openGaugeNumber of open connections
db.sql.connection.wait_duration_millisecondsHistogramDuration of connection wait times in milliseconds
db.sql.connection.waitCounterTotal number of connection waits
db.sql.latency_millisecondsHistogramSQL query latency in milliseconds
+

Attributes

+

db.system

+
    +
  • db.sql.connection.closed_max_idle_time
  • +
  • db.sql.connection.closed_max_idle
  • +
  • db.sql.connection.closed_max_lifetime
  • +
  • db.sql.connection.max_open
  • +
  • db.sql.connection.open
  • +
  • db.sql.connection.wait_duration_milliseconds
  • +
  • db.sql.connection.wait
  • +
+

status

+
    +
  • db.sql.connection.open
  • +
  • db.sql.latency_milliseconds
  • +
+

method

+
    +
  • db.sql.latency_milliseconds
  • +
+

le (less than or equal to)

+
    +
  • db.sql.latency_milliseconds_bucket
  • +
+

Note: The job attribute with value "ftl-serve" is common to all metrics and has been omitted from the individual listings for brevity.

+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ ← Feature Matrix +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ FAQ → +
+
+
+ + + + + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/reference/cron/index.html b/docs/reference/cron/index.html new file mode 100644 index 0000000000..6b42674a7b --- /dev/null +++ b/docs/reference/cron/index.html @@ -0,0 +1,534 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Cron | FTL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+ +
+ +
+ + + + + + +
+

Cron

+ +

A cron job is an Empty verb that will be called on a schedule. The syntax is described here.

+

You can also use a shorthand syntax for the cron job, supporting seconds (s), minutes (m), hours (h), and specific days of the week (e.g. Mon).

+

Examples

+

The following function will be called hourly:

+
+ + +
//ftl:cron 0 * * * *
+func Hourly(ctx context.Context) error {
+  // ...
+}
+
+ +
import xyz.block.ftl.Cron
+@Cron("0 * * * *")
+fun hourly() {
+    
+}
+
+ +
import xyz.block.ftl.Cron;
+
+class MyCron {
+    @Cron("0 * * * *")
+    void hourly() {
+        
+    }
+}
+
+
+

Every 12 hours, starting at UTC midnight:

+
+ + +
//ftl:cron 12h
+func TwiceADay(ctx context.Context) error {
+  // ...
+}
+
+ +
import xyz.block.ftl.Cron
+@Cron("12h")
+fun twiceADay() {
+    
+}
+
+ +
import xyz.block.ftl.Cron;
+
+class MyCron {
+    @Cron("12h")
+    void twiceADay() {
+        
+    }
+}
+
+
+

Every Monday at UTC midnight:

+
+ + +
//ftl:cron Mon
+func Mondays(ctx context.Context) error {
+  // ...
+}
+
+ +
import xyz.block.ftl.Cron
+@Cron("Mon")
+fun mondays() {
+    
+}
+
+ +
import xyz.block.ftl.Cron;
+
+class MyCron {
+    @Cron("Mon")
+    void mondays() {
+        
+    }
+}
+
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ ← Quick Start +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ Metrics → +
+
+
+ + + + + + + + + + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/reference/externaltypes/index.html b/docs/reference/externaltypes/index.html new file mode 100644 index 0000000000..610ab5fdc3 --- /dev/null +++ b/docs/reference/externaltypes/index.html @@ -0,0 +1,585 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +External Types | FTL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+ +
+ +
+ + + + + + +
+

External Types

+ +

Using external types

+

FTL supports the use of external types in your FTL modules. External types are types defined in other packages or modules that are not part of the FTL module.

+

The primary difference is that external types are not defined in the FTL schema, and therefore serialization and deserialization of these types is not handled +by FTL. Instead, FTL relies on the runtime to handle serialization and deserialization of these types.

+

In some cases this feature can also be used to provide custom serialization and deserialization logic for types that are not directly supported by FTL, even +if they are defined in the same package as the FTL module.

+

To use an external type in your FTL module schema, declare a type alias over the external type:

+
+ + +
//ftl:typealias
+type FtlType external.OtherType
+
+//ftl:typealias
+type FtlType2 = external.OtherType
+
+

The external type is widened to Any in the FTL schema, and the corresponding type alias will include metadata +for the runtime-specific type mapping:

+
typealias FtlType Any
+  +typemap go "github.com/external.OtherType"
+
+ +
@TypeAlias(name = "OtherType")
+class OtherTypeTypeMapper : TypeAliasMapper<OtherType, JsonNode> {
+    override fun encode(`object`: OtherType): JsonNode {
+        return TextNode.valueOf(`object`.value)
+    }
+
+    override fun decode(serialized: JsonNode): OtherType {
+        if (serialized.isTextual) {
+            return OtherType(serialized.textValue())
+        }
+        throw RuntimeException("Expected a textual value")
+    }
+}
+
+

In the example above the external type is widened to Any in the FTL schema, and the corresponding type alias will include metadata +for the runtime-specific type mapping:

+
typealias FtlType Any
+  +typemap java "foo.bar.OtherType"
+
+

Note that for JVM languages java is always used as the runtime name, regardless of the actual language used.

+

It is also possible to map to any other valid FTL type (e.g. String) by use this as the second type parameter:

+

Users can achieve functionally equivalent behavior to using the external type directly by using the declared +alias (FtlType) in place of the external type in any other schema declarations (e.g. as the type of a Verb request). Direct usage of the external type in schema declarations is not supported; +instead, the type alias must be used.

+
@TypeAlias(name = "OtherType")
+class OtherTypeTypeMapper : TypeAliasMapper<OtherType, String> {
+    override fun encode(other: OtherType): JsonNode {
+        return other.value
+    }
+
+    override fun decode(serialized: String): OtherType {
+        return OtherType(serialized.textValue())
+    }
+}
+
+

The corresponding type alias will be to a String, which makes the schema more useful:

+
typealias FtlType String
+  +typemap kotlin "foo.bar.OtherType"
+
+ +
@TypeAlias(name = "OtherType")
+public class OtherTypeTypeMapper implements TypeAliasMapper<OtherType, JsonNode> {
+    @Override
+    public JsonNode encode(OtherType object) {
+        return TextNode.valueOf(object.getValue());
+    }
+
+    @Override
+    public AnySerializedType decode(OtherType serialized) {
+        if (serialized.isTextual()) {
+            return new OtherType(serialized.textValue());
+        }
+        throw new RuntimeException("Expected a textual value");
+    }
+}
+
+

In the example above the external type is widened to Any in the FTL schema, and the corresponding type alias will include metadata +for the runtime-specific type mapping:

+
typealias FtlType Any
+  +typemap java "foo.bar.OtherType"
+
+

It is also possible to map to any other valid FTL type (e.g. String) by use this as the second type parameter:

+
@TypeAlias(name = "OtherType")
+public class OtherTypeTypeMapper implements TypeAliasMapper<OtherType, String> {
+    @Override
+    public String encode(OtherType object) {
+        return object.getValue();
+    }
+
+    @Override
+    public String decode(OtherType serialized) {
+        return new OtherType(serialized.textValue());
+    }
+}
+
+

The corresponding type alias will be to a String, which makes the schema more useful:

+
typealias FtlType String
+  +typemap java "com.external.other.OtherType"
+
+
+

FTL will automatically serialize and deserialize the external type to the strong type indicated by the mapping.

+

Cross-Runtime Type Mappings

+

FTL also provides the capability to declare type mappings for other runtimes. For instance, to include a type mapping for another language, you can +annotate your type alias declaration as follows:

+
+ + +
//ftl:typealias
+//ftl:typemap java "com.external.other.OtherType"
+type FtlType external.OtherType
+
+ +
@TypeAlias(
+  name = "OtherType",
+  languageTypeMappings = [LanguageTypeMapping(language = "go", type = "github.com/external.OtherType")]
+)
+
+ +
@TypeAlias(name = "OtherType", languageTypeMappings = {
+        @LanguageTypeMapping(language = "go", type = "github.com/external.OtherType"),
+})
+...
+
+
+

In the FTL schema, this will appear as:

+
typealias FtlType Any
+  +typemap go "github.com/external.OtherType"
+  +typemap java "com.external.other.OtherType"
+
+

This allows FTL to decode the type properly in other languages, for seamless +interoperability across different runtimes.

+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ ← Quick Start +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ Metrics → +
+
+
+ + + + + + + + + + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/reference/index.html b/docs/reference/index.html new file mode 100644 index 0000000000..0bf096ae5e --- /dev/null +++ b/docs/reference/index.html @@ -0,0 +1,316 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Reference | FTL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/reference/ingress/index.html b/docs/reference/ingress/index.html new file mode 100644 index 0000000000..6cc6141dce --- /dev/null +++ b/docs/reference/ingress/index.html @@ -0,0 +1,612 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +HTTP Ingress | FTL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+ +
+ +
+ + + + + + +
+

HTTP Ingress

+ +

Verbs annotated with ftl:ingress will be exposed via HTTP (http is the default ingress type). These endpoints will then be available on one of our default ingress ports (local development defaults to http://localhost:8891).

+

The following will be available at http://localhost:8891/http/users/123/posts?postId=456.

+
+ + +
type GetRequestPathParams struct {
+	UserID string `json:"userId"`
+}
+
+type GetRequestQueryParams struct {
+	PostID string `json:"postId"`
+}
+
+type GetResponse struct {
+	Message string `json:"msg"`
+}
+
+//ftl:ingress GET /http/users/{userId}/posts
+func Get(ctx context.Context, req builtin.HttpRequest[ftl.Unit, GetRequestPathParams, GetRequestQueryParams]) (builtin.HttpResponse[GetResponse, ErrorResponse], error) {
+  // ...
+}
+
+

Because the example above only has a single path parameter it can be simplified by just using a scalar such as string or int64 as the path parameter type:

+

+//ftl:ingress GET /http/users/{userId}/posts
+func Get(ctx context.Context, req builtin.HttpRequest[ftl.Unit, int64, GetRequestQueryParams]) (builtin.HttpResponse[GetResponse, ErrorResponse], error) {
+  // ...
+}
+
+
+

NOTE! +The req and resp types of HTTP ingress verbs must be builtin.HttpRequest and builtin.HttpResponse respectively. These types provide the necessary fields for HTTP ingress (headers, statusCode, etc.)

+

You will need to import ftl/builtin.

+
+

Key points:

+
    +
  • ingress verbs will be automatically exported by default.
  • +
+

Field mapping

+

The HttpRequest request object takes 3 type parameters, the body, the path parameters and the query parameters.

+

Given the following request verb:

+

+type PostBody struct{
+	Title string               `json:"title"`
+	Content string             `json:"content"`
+	Tag ftl.Option[string]     `json:"tag"`
+}
+type PostPathParams struct {
+	UserID string             `json:"userId"`
+	PostID string             `json:"postId"`
+}
+
+type PostQueryParams struct {
+	Publish boolean `json:"publish"`
+}
+
+//ftl:ingress http PUT /users/{userId}/posts/{postId}
+func Get(ctx context.Context, req builtin.HttpRequest[PostBody, PostPathParams, PostQueryParams]) (builtin.HttpResponse[GetResponse, string], error) {
+	return builtin.HttpResponse[GetResponse, string]{
+		Headers: map[string][]string{"Get": {"Header from FTL"}},
+		Body: ftl.Some(GetResponse{
+			Message: fmt.Sprintf("UserID: %s, PostID: %s, Tag: %s", req.pathParameters.UserID, req.pathParameters.PostID, req.Body.Tag.Default("none")),
+		}),
+	}, nil
+}
+
+

The rules for how each element is mapped are slightly different, as they have a different structure:

+
    +
  • The body is mapped directly to the body of the request, generally as a JSON object. Scalars are also supported, as well as []byte to get the raw body. If they type is any then it will be assumed to be JSON and mapped to the appropriate types based on the JSON structure.
  • +
  • The path parameters can be mapped directly to an object with field names corresponding to the name of the path parameter. If there is only a single path parameter it can be injected directly as a scalar. They can also be injected as a map[string]string.
  • +
  • The path parameters can also be mapped directly to an object with field names corresponding to the name of the path parameter. They can also be injected directly as a map[string]string, or map[string][]string for multiple values.
  • +
+

Optional fields

+

Optional fields are represented by the ftl.Option type. The Option type is a wrapper around the actual type and can be Some or None. In the example above, the Tag field is optional.

+
curl -i http://localhost:8891/users/123/posts/456
+
+

Because the tag query parameter is not provided, the response will be:

+
{
+  "msg": "UserID: 123, PostID: 456, Tag: none"
+}
+
+

Casing

+

Field names use lowerCamelCase by default. You can override this by using the json tag.

+

SumTypes

+

Given the following request verb:

+
//ftl:enum export
+type SumType interface {
+	tag()
+}
+
+type A string
+
+func (A) tag() {}
+
+type B []string
+
+func (B) tag() {}
+
+//ftl:ingress http POST /typeenum
+func TypeEnum(ctx context.Context, req builtin.HttpRequest[SumType, ftl.Unit, ftl.Unit]) (builtin.HttpResponse[SumType, string], error) {
+	return builtin.HttpResponse[SumType, string]{Body: ftl.Some(req.Body)}, nil
+}
+
+

The following curl request will map the SumType name and value to the req.Body:

+
curl -X POST "http://localhost:8891/typeenum" \
+     -H "Content-Type: application/json" \
+     --data '{"name": "A", "value": "sample"}'
+
+

The response will be:

+
{
+  "name": "A",
+  "value": "sample"
+}
+
+

Encoding query params as JSON

+

Complex query params can also be encoded as JSON using the @json query parameter. For example:

+
+

{"tag":"ftl"} url-encoded is %7B%22tag%22%3A%22ftl%22%7D

+
+
curl -i http://localhost:8891/users/123/posts/456?@json=%7B%22tag%22%3A%22ftl%22%7D
+
+ +

JVM Languages use the JAX-RS annotations to define HTTP endpoints. The following example shows how to define an HTTP endpoint in Java. As the underling implementation is based on Quarkus +it is also possible to use the Quarkus extensions to the JAX-RS annotations:

+

In general the difference between the Quarkus annotation and the standard JAX-RS ones is that the Quarkus parameters infer the parameter name from the method parameter name, while the JAX-RS ones require the parameter name to be explicitly defined.

+

+import java.util.List;
+
+import jakarta.ws.rs.DELETE;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.PUT;
+import jakarta.ws.rs.Path;
+
+import jakarta.ws.rs.QueryParam; // JAX-RS annotation to get the query parameter
+import org.jboss.resteasy.reactive.RestPath; // Quarkus annotation to get the path parameter
+
+@Path("/")
+public class TestHTTP {
+
+    @GET
+    @Path("/http/users/{userId}/posts")
+    public String get(@RestPath String userId, @QueryParam("postId") String post) {
+        //...
+    }
+
+}
+
+

Under the hood these HTTP invocations are being mapped to verbs that take a builtin.HttpRequest and return a builtin.HttpResponse. This is not exposed directly to the user, but is instead mapped directly to JAX-RS annotations.

+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ ← Quick Start +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ Metrics → +
+
+
+ + + + + + + + + + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/reference/matrix/index.html b/docs/reference/matrix/index.html new file mode 100644 index 0000000000..a6b4cdd80c --- /dev/null +++ b/docs/reference/matrix/index.html @@ -0,0 +1,471 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Feature Matrix | FTL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+ +
+ +
+ + + + + + +
+

Feature Matrix

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
SystemFeatureGoJVMRust
TypesBasic Types✔️✔️️ ✔️
Optional Type✔️✔️
Unit Type✔️✔️
Empty Type✔️✔️
Generic Types✔️✔️
Type Aliases✔️
Value Enums✔️
Type Enums✔️
Visibility✔️✔️
VerbsVerb✔️✔️️✔️
Sink✔️✔️
Source✔️✔️
Empty✔️✔️
Visibility✔️✔️
CoreLeases✔️✔️
Cron✔️✔️
Config✔️✔️
Secrets✔️✔️
HTTP Ingress✔️✔️
ResourcesPostgreSQL✔️✔️
MySQL
Kafka
PubSubDeclaring Topic✔️✔️
Subscribing✔️✔️
Publishing✔️✔️
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ ← Quick Start +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ Metrics → +
+
+
+ + + + + + + + + + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/reference/pubsub/index.html b/docs/reference/pubsub/index.html new file mode 100644 index 0000000000..00e8624944 --- /dev/null +++ b/docs/reference/pubsub/index.html @@ -0,0 +1,519 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +PubSub | FTL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+ +
+ +
+ + + + + + +
+

PubSub

+ +

FTL has first-class support for PubSub, modelled on the concepts of topics (where events are sent) and subscribers (a verb which consumes events). Subscribers are, as you would expect, sinks. Each subscriber is a cursor over the topic it is associated with. Each topic may have multiple subscriptions. Each published event has an at least once delivery guarantee for each subscription.

+
+ + +

First, declare a new topic:

+
package payments
+
+type Invoices = ftl.TopicHandle[Invoice, ftl.SinglePartitionMap[Invoice]]
+
+

Note that the name of the topic as represented in the FTL schema is the lower camel case version of the type name.

+

The Invoices type is a handle to the topic. It is a generic type that takes two arguments: the event type and the partition map type. The partition map type is used to map events to partitions. In this case, we are using a single partition map, which means that all events are sent to the same partition.

+

Then define a Sink to consume from the topic:

+
//ftl:subscribe payments.invoices from=beginning
+func SendInvoiceEmail(ctx context.Context, in Invoice) error {
+  // ...
+}
+
+

Events can be published to a topic by injecting the topic type into a verb:

+
func PublishInvoice(ctx context.Context, topic Invoices) error {
+   topic.Publish(ctx, Invoice{...})
+   // ...
+}
+
+ +

First, declare a new topic :

+
@Export
+@Topic("invoices")
+internal interface InvoiceTopic : WriteableTopic<Invoice>
+
+

Events can be published to a topic by injecting it into an @Verb method:

+
@Verb
+fun publishInvoice(request: InvoiceRequest, topic: InvoiceTopic) {
+    topic.publish(Invoice(request.getInvoiceNo()))
+}
+
+

To subscribe to a topic use the @Subscription annotation, referencing the topic class and providing a method to consume the event:

+
@Subscription(topic = InvoiceTopic::class, from = FromOffset.LATEST)
+fun consumeInvoice(event: Invoice) {
+    // ...
+}
+
+

If you are subscribing to a topic from another module, FTL will generate a topic class for you so you can subscribe to it. This generated +topic cannot be published to, only subscribed to:

+
@Topic(name="invoices", module="publisher")
+internal interface InvoiceTopic : ConsumableTopic<Invoice>
+
+ +

First, declare a new topic:

+
@Export
+@Topic("invoices")
+interface InvoiceTopic extends WriteableTopic<Invoice> {}
+
+

Events can be published to a topic by injecting it into an @Verb method:

+
@Verb
+void publishInvoice(InvoiceRequest request, InvoiceTopic topic) throws Exception {
+    topic.publish(new Invoice(request.getInvoiceNo()));
+}
+
+

To subscribe to a topic use the @Subscription annotation, referencing the topic class and providing a method to consume the event:

+
@Subscription(topic = InvoiceTopic.class, from = FromOffset.LATEST)
+public void consumeInvoice(Invoice event) {
+    // ...
+}
+
+

If you are subscribing to a topic from another module, FTL will generate a topic class for you so you can subscribe to it. This generated +topic cannot be published to, only subscribed to:

+
@Topic(name="invoices", module="publisher")
+ interface InvoiceTopic extends ConsumableTopic<Invoice> {}
+
+
+
+

NOTE! +PubSub topics cannot be published to from outside the module that declared them, they can only be subscribed to. That is, if a topic is declared in module A, module B cannot publish to it.

+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ ← Quick Start +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ Metrics → +
+
+
+ + + + + + + + + + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/reference/retries/index.html b/docs/reference/retries/index.html new file mode 100644 index 0000000000..32f277540a --- /dev/null +++ b/docs/reference/retries/index.html @@ -0,0 +1,557 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Retries | FTL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+ +
+ +
+ + + + + + +
+

Retries

+ +

Some FTL features allow specifying a retry policy via a Go comment directive. Retries back off exponentially until the maximum is reached.

+

The directive has the following syntax:

+
+ + +
//ftl:retry [<attempts=10>] <min-backoff> [<max-backoff=1hr>] [catch <catchVerb>]
+
+ +
@Retry(attempts = 10, minBackoff = "5s", maxBackoff = "1h", catchVerb = "<catchVerb>", catchModule = "<catchModule>")
+
+ +
@Retry(attempts = 10, minBackoff = "5s", maxBackoff = "1h", catchVerb = "<catchVerb>", catchModule = "<catchModule>")
+
+
+

For example, the following function will retry up to 10 times, with a delay of 5s, 10s, 20s, 40s, 60s, 60s, etc.

+
+ + +
//ftl:retry 10 5s 1m
+func Process(ctx context.Context, in Invoice) error {
+  // ...
+}
+
+ +
@Retry(count = 10, minBackoff = "5s", maxBackoff = "1m")
+fun process(inv: Invoice) {
+    // ... 
+}
+
+ +
@Retry(count = 10, minBackoff = "5s", maxBackoff = "1m")
+public void process(Invoice in) {
+    // ... 
+}
+
+
+

PubSub

+

Subscribers can have a retry policy. For example:

+
+ + +
//ftl:retry 5 1s catch recoverPaymentProcessing
+func ProcessPayment(ctx context.Context, payment Payment) error {
+...
+}
+
+ +
@Subscription(topic = "example", name = "exampleSubscription")
+@SubscriptionOptions(from = FromOffset.LATEST)
+@Retry(count = 5, minBackoff = "1s", catchVerb = "recoverPaymentProcessing")
+fun processPayment(payment: Payment) {
+    // ... 
+}
+
+ +
@Subscription(topic = "example", name = "exampleSubscription")
+@SubscriptionOptions(from = FromOffset.LATEST)
+@Retry(count = 5, minBackoff = "1s", catchVerb = "recoverPaymentProcessing")
+public void processPayment(Payment payment) {
+    // ... 
+}
+
+
+

Catching

+

After all retries have failed, a catch verb can be used to safely recover.

+

These catch verbs have a request type of builtin.CatchRequest<Req> and no response type. If a catch verb returns an error, it will be retried until it succeeds so it is important to handle errors carefully.

+
+ + +
//ftl:retry 5 1s catch recoverPaymentProcessing
+func ProcessPayment(ctx context.Context, payment Payment) error {
+...
+}
+
+//ftl:verb
+func RecoverPaymentProcessing(ctx context.Context, request builtin.CatchRequest[Payment]) error {
+// safely handle final failure of the payment
+}
+
+ +

+@Retry(count = 5, minBackoff = "1s", catchVerb = "recoverPaymentProcessing")
+fun processPayment(payment: Payment) {
+    // ... 
+}
+
+@Verb
+fun recoverPaymentProcessing(req: CatchRequest<Payment>) {
+    // safely handle final failure of the payment
+}
+
+ +
@Retry(count = 5, minBackoff = "1s", catchVerb = "recoverPaymentProcessing")
+public void processPayment(Payment payment) {
+    // ... 
+}
+
+@Verb
+public void recoverPaymentProcessing(CatchRequest<Payment> req) {
+    // safely handle final failure of the payment
+}
+
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ ← Quick Start +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ Metrics → +
+
+
+ + + + + + + + + + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/reference/secretsconfig/index.html b/docs/reference/secretsconfig/index.html new file mode 100644 index 0000000000..3a69ab0e33 --- /dev/null +++ b/docs/reference/secretsconfig/index.html @@ -0,0 +1,529 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Secrets/Config | FTL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+ +
+ +
+ + + + + + +
+

Secrets/Config

+ +

Configuration

+

Configuration values are named, typed values. They are managed by the ftl config command-line.

+
+ + +

To declare a configuration value use the following syntax:

+
type DefaultUser = ftl.Config[Username]
+
+

Note that the name of the configuration value as represented in the FTL schema is the lower camel case version of the type name.

+

Configuration values can be injected into FTL methods, such as @Verb, HTTP ingress, Cron etc. To inject a configuration value, use the following syntax:

+
//ftl:verb
+func Hello(ctx context.Context, req Request, defaultUser DefaultUser) error {
+    username := defaultUser.Get(ctx)
+    // ...
+}
+
+ +

Configuration values can be injected into FTL methods, such as @Verb, HTTP ingress, Cron etc. To inject a configuration value, use the following syntax:

+
@Export
+@Verb
+fun hello(helloRequest: HelloRequest, @Config("defaultUser") defaultUser: String): HelloResponse {
+    return HelloResponse("Hello, $defaultUser")
+}
+
+ +

Configuration values can be injected into FTL methods, such as @Verb, HTTP ingress, Cron etc. To inject a configuration value, use the following syntax:

+
@Export
+@Verb
+HelloResponse hello(HelloRequest helloRequest, @Config("defaultUser") String defaultUser)  {
+    return new HelloResponse("Hello, " + defaultUser);
+}
+
+
+

Secrets

+

Secrets are encrypted, named, typed values. They are managed by the ftl secret command-line.

+
+ + +

Declare a secret with the following:

+
type ApiKey = ftl.Secret[Credentials]
+
+

Like configuration values, the name of the secret as represented in the FTL schema is the lower camel case version of the type name.

+

Configuration values can be injected into FTL methods, such as @Verb, HTTP ingress, Cron etc. To inject a configuration value, use the following syntax:

+
//ftl:verb
+func CallApi(ctx context.Context, req Request, apiKey ApiKey) error {
+    credentials := apiKey.Get(ctx)
+    // ...
+}
+
+ +

Configuration values can be injected into FTL methods, such as @Verb, HTTP ingress, Cron etc. To inject a configuration value, use the following syntax:

+
@Export
+@Verb
+fun hello(helloRequest: HelloRequest, @Secret("apiKey") apiKey: String): HelloResponse {
+    return HelloResponse("Hello, ${api.call(apiKey)}")
+}
+
+ +

Configuration values can be injected into FTL methods, such as @Verb, HTTP ingress, Cron etc. To inject a configuration value, use the following syntax:

+
@Export
+@Verb
+HelloResponse hello(HelloRequest helloRequest, @Secret("apiKey") String apiKey)  {
+    return new HelloResponse("Hello, " + api.call(apiKey));
+}
+
+
+

Transforming secrets/configuration

+

Often, raw secret/configuration values aren't directly useful. For example, raw credentials might be used to create an API client. For those situations ftl.Map() can be used to transform a configuration or secret value into another type:

+
var client = ftl.Map(ftl.Secret[Credentials]("credentials"),
+                     func(ctx context.Context, creds Credentials) (*api.Client, error) {
+    return api.NewClient(creds)
+})
+
+

This is not currently supported in Kotlin or Java.

+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ ← Quick Start +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ Metrics → +
+
+
+ + + + + + + + + + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/reference/start/index.html b/docs/reference/start/index.html new file mode 100644 index 0000000000..707b93be23 --- /dev/null +++ b/docs/reference/start/index.html @@ -0,0 +1,492 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Start | FTL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+ +
+ +
+ + + + + + +
+

Start

+ +

Import the runtime

+
+ + +

Some aspects of FTL rely on a runtime which must be imported with:

+
import "github.com/block/ftl/go-runtime/ftl"
+
+ +

The easiest way to get started with Kotlin is to use the ftl-build-parent-kotlin parent POM. This will automatically include the FTL runtime as a dependency, and setup all required plugins:

+
<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.myproject</groupId>
+    <artifactId>myproject</artifactId>
+    <version>1.0-SNAPSHOT</version>
+
+    <parent>
+        <groupId>xyz.block.ftl</groupId>
+        <artifactId>ftl-build-parent-kotlin</artifactId>
+        <version>${ftl.version}</version>
+    </parent>
+
+</project>
+
+

If you do not want to use a parent pom then you can copy the plugins and dependencies from the parent pom into your own pom.

+ +

The easiest way to get started with Java is to use the ftl-build-parent-java parent POM. This will automatically include the FTL runtime as a dependency, and setup all required plugins:

+
<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.myproject</groupId>
+    <artifactId>myproject</artifactId>
+    <version>1.0-SNAPSHOT</version>
+
+    <parent>
+        <groupId>xyz.block.ftl</groupId>
+        <artifactId>ftl-build-parent-java</artifactId>
+        <version>${ftl.version}</version>
+    </parent>
+
+</project>
+
+

If you do not want to use a parent pom then you can copy the plugins and dependencies from the parent pom into your own pom.

+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ ← Quick Start +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ Metrics → +
+
+
+ + + + + + + + + + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/reference/types/index.html b/docs/reference/types/index.html new file mode 100644 index 0000000000..25dbaf7f21 --- /dev/null +++ b/docs/reference/types/index.html @@ -0,0 +1,561 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Types | FTL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+ +
+ +
+ + + + + + +
+

Types

+ +

FTL supports the following types: Int (64-bit), Float (64-bit), String, Bytes (a byte array), Bool, Time, Any (a dynamic type), Unit (similar to "void"), arrays, maps, data structures, and constant enumerations. Each FTL type is mapped to a corresponding language-specific type. For example in Go Float is represented as float64, Time is represented by time.Time, and so on. [^1]

+

Any Go type supported by FTL and referenced by an FTL declaration will be automatically exposed to an FTL type.

+

For example, the following verb declaration will result in Request and Response being automatically translated to FTL types.

+
type Request struct {}
+type Response struct {}
+
+//ftl:verb
+func Hello(ctx context.Context, in Request) (Response, error) {
+  // ...
+}
+
+

Type enums (sum types)

+

Sum types are supported by FTL's type system, but aren't directly supported by Go. However they can be approximated with the use of sealed interfaces. To declare a sum type in FTL use the comment directive //ftl:enum:

+
//ftl:enum
+type Animal interface { animal() }
+
+type Cat struct {}
+func (Cat) animal() {}
+
+type Dog struct {}
+func (Dog) animal() {}
+
+

Value enums

+

A value enum is an enumerated set of string or integer values.

+
//ftl:enum
+type Colour string
+
+const (
+  Red   Colour = "red"
+  Green Colour = "green"
+  Blue  Colour = "blue"
+)
+
+

Type aliases

+

A type alias is an alternate name for an existing type. It can be declared like so:

+
//ftl:typealias
+type Alias Target
+
+

or

+
//ftl:typealias
+type Alias = Target
+
+

eg.

+
//ftl:typealias
+type UserID string
+
+//ftl:typealias
+type UserToken = string
+
+
+

Optional types

+

FTL supports optional types, which are types that can be None or Some and can be declared via ftl.Option[T]. These types are provided by the ftl runtimes. For example, the following FTL type declaration in go, will provide an optional string type "Name":

+
type EchoResponse struct {
+	Name ftl.Option[string] `json:"name"`
+}
+
+

The value of this type can be set to Some or None:

+
resp := EchoResponse{
+  Name: ftl.Some("John"),
+}
+
+resp := EchoResponse{
+  Name: ftl.None(),
+}
+
+

The value of the optional type can be accessed using Get, MustGet, or Default methods:

+
// Get returns the value and a boolean indicating if the Option contains a value.
+if value, ok := resp.Name.Get(); ok {
+  resp.Name = ftl.Some(value)
+}
+
+// MustGet returns the value or panics if the Option is None.
+value := resp.Name.MustGet()
+
+// Default returns the value or a default value if the Option is None.
+value := resp.Name.Default("default")
+
+

Unit "void" type

+

The Unit type is similar to the void type in other languages. It is used to indicate that a function does not return a value. For example:

+
//ftl:ingress GET /unit
+func Unit(ctx context.Context, req builtin.HttpRequest[ftl.Unit, ftl.Unit, TimeRequest]) (builtin.HttpResponse[ftl.Unit, string], error) {
+	return builtin.HttpResponse[ftl.Unit, string]{Body: ftl.Some(ftl.Unit{})}, nil
+}
+
+

This request will return an empty body with a status code of 200:

+
curl http://localhost:8891/unit -i
+
+
HTTP/1.1 200 OK
+Date: Mon, 12 Aug 2024 17:58:22 GMT
+Content-Length: 0
+
+

Builtin types

+

FTL provides a set of builtin types that are automatically available in all FTL runtimes. These types are:

+
    +
  • builtin.HttpRequest[Body, PathParams, QueryParams] - Represents an HTTP request with a body of type Body, path parameter type of PathParams and a query parameter type of QueryParams.
  • +
  • builtin.HttpResponse[Body, Error] - Represents an HTTP response with a body of type Body and an error of type Error.
  • +
  • builtin.Empty - Represents an empty type. This equates to an empty structure {}.
  • +
  • builtin.CatchRequest - Represents a request structure for catch verbs.
  • +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ ← Quick Start +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ Metrics → +
+
+
+ + + + + + + + + + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/reference/unittests/index.html b/docs/reference/unittests/index.html new file mode 100644 index 0000000000..1720a25f65 --- /dev/null +++ b/docs/reference/unittests/index.html @@ -0,0 +1,584 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Unit Tests | FTL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+ +
+ +
+ + + + + + +
+

Unit Tests

+ +

Create a context

+

When writing a unit test, first create a context:

+
func ExampleTest(t *testing.Test) {
+    ctx := ftltest.Context(
+        // options go here
+    )
+}
+
+

FTL will help isolate what you want to test by restricting access to FTL features by default. You can expand what is available to test by adding options to ftltest.Context(...).

+

In this default set up, FTL does the following:

+ +

Customization

+

Project files, configs and secrets

+

To enable configs and secrets from the default project file:

+
ctx := ftltest.Context(
+    ftltest.WithDefaultProjectFile(),
+)
+
+

Or you can specify a specific project file:

+
ctx := ftltest.Context(
+    ftltest.WithProjectFile(path),
+)
+
+

You can also override specific config and secret values:

+
ctx := ftltest.Context(
+    ftltest.WithDefaultProjectFile(),
+    
+    ftltest.WithConfig(endpoint, "test"),
+    ftltest.WithSecret(secret, "..."),
+)
+
+

Databases

+

To enable database access in a test, you must first provide a DSN via a project file. You can then set up a test database:

+
ctx := ftltest.Context(
+    ftltest.WithDefaultProjectFile(),
+    ftltest.WithDatabase[MyDBConfig](),
+)
+
+

This will:

+
    +
  • Take the provided DSN and appends _test to the database name. Eg: accounts becomes accounts_test
  • +
  • Wipe all tables in the database so each test run happens on a clean database
  • +
+

You can access the database in your test using its handle:

+
db, err := ftltest.GetDatabaseHandle[MyDBConfig]()
+db.Get(ctx).Exec(...)
+
+

Maps

+

By default, calling Get(ctx) on a map handle will panic.

+

You can inject a fake via a map:

+
ctx := ftltest.Context(
+    ftltest.WhenMap(exampleMap, func(ctx context.Context) (string, error) {
+       return "Test Value"
+    }),
+)
+
+

You can also allow the use of all maps:

+
ctx := ftltest.Context(
+    ftltest.WithMapsAllowed(),
+)
+
+

Calls

+

Use ftltest.Call[Client](...) (or ftltest.CallSource[Client](...), ftltest.CallSink[Client](...), ftltest.CallEmpty[Client](...)) to invoke your +verb. At runtime, FTL automatically provides these +resources to your verb, and using ftltest.Call(...) rather than direct invocations simulates this behavior.

+
// Call a verb
+resp, err := ftltest.Call[ExampleVerbClient, Request, Response](ctx, Request{Param: "Test"})
+
+

You can inject fakes for verbs:

+
ctx := ftltest.Context(
+    ftltest.WhenVerb[ExampleVerbClient](func(ctx context.Context, req Request) (Response, error) {
+       return Response{Result: "Lorem Ipsum"}, nil
+    }),
+)
+
+

If there is no request or response parameters, you can use WhenSource(...), WhenSink(...), or WhenEmpty(...).

+

To enable all calls within a module:

+
ctx := ftltest.Context(
+    ftltest.WithCallsAllowedWithinModule(),
+)
+
+

PubSub

+

By default, all subscribers are disabled. +To enable a subscriber:

+
ctx := ftltest.Context(
+    ftltest.WithSubscriber(paymentsSubscription, ProcessPayment),
+)
+
+

Or you can inject a fake subscriber:

+
ctx := ftltest.Context(
+    ftltest.WithSubscriber(paymentsSubscription, func (ctx context.Context, in PaymentEvent) error {
+       return fmt.Errorf("failed payment: %v", in)
+    }),
+)
+
+

Due to the asynchronous nature of pubsub, your test should wait for subscriptions to consume the published events:

+
topic.Publish(ctx, Event{Name: "Test"})
+
+ftltest.WaitForSubscriptionsToComplete(ctx)
+// Event will have been consumed by now
+
+

You can check what events were published to a topic:

+
events := ftltest.EventsForTopic(ctx, topic)
+
+

You can check what events were consumed by a subscription, and whether a subscriber returned an error:

+
results := ftltest.ResultsForSubscription(ctx, subscription)
+
+

If all you wanted to check was whether a subscriber returned an error, this function is simpler:

+
errs := ftltest.ErrorsForSubscription(ctx, subscription)
+
+

PubSub also has these different behaviours while testing:

+
    +
  • Publishing to topics in other modules is allowed
  • +
  • If a subscriber returns an error, no retries will occur regardless of retry policy.
  • +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ ← Quick Start +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ Metrics → +
+
+
+ + + + + + + + + + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/reference/verbs/index.html b/docs/reference/verbs/index.html new file mode 100644 index 0000000000..2cd5ca9b19 --- /dev/null +++ b/docs/reference/verbs/index.html @@ -0,0 +1,519 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Verbs | FTL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+ +
+ +
+ + + + + + +
+

Verbs

+ +

Defining Verbs

+
+ + +

To declare a Verb, write a normal Go function with the following signature, annotated with the Go comment directive //ftl:verb:

+
//ftl:verb
+func F(context.Context, In) (Out, error) { }
+
+

eg.

+
type EchoRequest struct {}
+
+type EchoResponse struct {}
+
+//ftl:verb
+func Echo(ctx context.Context, in EchoRequest) (EchoResponse, error) {
+  // ...
+}
+
+ +

To declare a Verb, write a normal Kotlin function with the following signature, annotated with the Kotlin annotation @Verb:

+
@Verb
+fun F(In): Out { }
+
+

eg.

+
data class EchoRequest
+data class EchoResponse
+
+@Verb
+fun echo(request: EchoRequest): EchoResponse {
+  // ...
+}
+
+
+

By default verbs are only visible to other verbs in the same module.

+

Calling Verbs

+
+ + +

To call a verb, import the module's verb client ({ModuleName}.{VerbName}Client), add it to your verb's signature, then invoke it as a function. eg.

+
//ftl:verb
+func Echo(ctx context.Context, in EchoRequest, tc time.TimeClient) (EchoResponse, error) {
+	out, err := tc(ctx, TimeRequest{...})
+}
+
+

Verb clients are generated by FTL. If the callee verb belongs to the same module as the caller, you must build the +module first (with callee verb defined) in order to generate its client for use by the caller. Local verb clients are +available in the generated types.ftl.go file as {VerbName}Client.

+ +

To call a verb, import the module's verb client, add it to your verb's signature, then call() it. eg.

+
import ftl.time.TimeClient
+
+@Verb
+fun echo(req: EchoRequest, time: TimeClient): EchoResponse {
+  val response = time.call()
+  // ...
+}
+
+val response = time.call()
+
+

Verb clients are generated by FTL. If the callee verb belongs to the same module as the caller, you must manually define your +own client:

+
@VerbClient(name="time")
+interface TimeClient {
+    fun call(): TimeResponse
+}
+
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ ← Quick Start +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ Metrics → +
+
+
+ + + + + + + + + + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/reference/visibility/index.html b/docs/reference/visibility/index.html new file mode 100644 index 0000000000..44bca27a88 --- /dev/null +++ b/docs/reference/visibility/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Visibility | FTL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+ +
+ +
+ + + + + + +
+

Visibility

+ +

By default all declarations in FTL are visible only to the module they're declared in. The implicit visibility of types is that of the first verb or other declaration that references it.

+

Exporting declarations

+

Exporting a declaration makes it accessible to other modules. Some declarations that are entirely local to a module, such as secrets/config, cannot be exported.

+

Types that are transitively referenced by an exported declaration will be automatically exported unless they were already defined but unexported. In this case, an error will be raised and the type must be explicitly exported.

+
+ + +

The following table describes the go directives used to export the corresponding declaration:

+ + + + + + +
SymbolExport syntax
Verb//ftl:verb export
Data//ftl:data export
Enum/Sum type//ftl:enum export
Typealias//ftl:typealias export
Topic//ftl:export 1
+
//ftl:verb export
+func Verb(ctx context.Context, in In) (Out, error)
+
+//ftl:typealias export
+type UserID string
+
+
1 +

By default, topics do not require any annotations as the declaration itself is sufficient.

+
+ +

For Kotlin the @Export annotation can be used to export a declaration:

+
@Verb
+@Export
+fun time(): TimeResponse {
+    // ...
+}
+
+ +

For Java the @Export annotation can be used to export a declaration:

+
@Verb
+@Export
+TimeResponse time()  {
+    // ...
+}
+
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ ← Quick Start +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ Metrics → +
+
+
+ + + + + + + + + + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/doks.png b/doks.png new file mode 100644 index 0000000000..70d8c78611 Binary files /dev/null and b/doks.png differ diff --git a/doks.svg b/doks.svg new file mode 100644 index 0000000000..4631bc5350 --- /dev/null +++ b/doks.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/elasticlunr.min.js b/elasticlunr.min.js new file mode 100644 index 0000000000..79dad65f52 --- /dev/null +++ b/elasticlunr.min.js @@ -0,0 +1,10 @@ +/** + * elasticlunr - http://weixsong.github.io + * Lightweight full-text search engine in Javascript for browser search and offline search. - 0.9.6 + * + * Copyright (C) 2017 Oliver Nightingale + * Copyright (C) 2017 Wei Song + * MIT Licensed + * @license + */ +!function(){function e(e){if(null===e||"object"!=typeof e)return e;var t=e.constructor();for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.9.5",lunr=t,t.utils={},t.utils.warn=function(e){return function(t){e.console&&console.warn&&console.warn(t)}}(this),t.utils.toString=function(e){return void 0===e||null===e?"":e.toString()},t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var e=Array.prototype.slice.call(arguments),t=e.pop(),n=e;if("function"!=typeof t)throw new TypeError("last argument must be a function");n.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},t.EventEmitter.prototype.removeListener=function(e,t){if(this.hasHandler(e)){var n=this.events[e].indexOf(t);-1!==n&&(this.events[e].splice(n,1),0==this.events[e].length&&delete this.events[e])}},t.EventEmitter.prototype.emit=function(e){if(this.hasHandler(e)){var t=Array.prototype.slice.call(arguments,1);this.events[e].forEach(function(e){e.apply(void 0,t)},this)}},t.EventEmitter.prototype.hasHandler=function(e){return e in this.events},t.tokenizer=function(e){if(!arguments.length||null===e||void 0===e)return[];if(Array.isArray(e)){var n=e.filter(function(e){return null===e||void 0===e?!1:!0});n=n.map(function(e){return t.utils.toString(e).toLowerCase()});var i=[];return n.forEach(function(e){var n=e.split(t.tokenizer.seperator);i=i.concat(n)},this),i}return e.toString().trim().toLowerCase().split(t.tokenizer.seperator)},t.tokenizer.defaultSeperator=/[\s\-]+/,t.tokenizer.seperator=t.tokenizer.defaultSeperator,t.tokenizer.setSeperator=function(e){null!==e&&void 0!==e&&"object"==typeof e&&(t.tokenizer.seperator=e)},t.tokenizer.resetSeperator=function(){t.tokenizer.seperator=t.tokenizer.defaultSeperator},t.tokenizer.getSeperator=function(){return t.tokenizer.seperator},t.Pipeline=function(){this._queue=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in t.Pipeline.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[n]=e},t.Pipeline.getRegisteredFunction=function(e){return e in t.Pipeline.registeredFunctions!=!0?null:t.Pipeline.registeredFunctions[e]},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.getRegisteredFunction(e);if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i+1,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i,0,n)},t.Pipeline.prototype.remove=function(e){var t=this._queue.indexOf(e);-1!==t&&this._queue.splice(t,1)},t.Pipeline.prototype.run=function(e){for(var t=[],n=e.length,i=this._queue.length,o=0;n>o;o++){for(var r=e[o],s=0;i>s&&(r=this._queue[s](r,o,e),void 0!==r&&null!==r);s++);void 0!==r&&null!==r&&t.push(r)}return t},t.Pipeline.prototype.reset=function(){this._queue=[]},t.Pipeline.prototype.get=function(){return this._queue},t.Pipeline.prototype.toJSON=function(){return this._queue.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.DocumentStore,this.index={},this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var e=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,e)},t.Index.prototype.off=function(e,t){return this.eventEmitter.removeListener(e,t)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;n._fields=e.fields,n._ref=e.ref,n.documentStore=t.DocumentStore.load(e.documentStore),n.pipeline=t.Pipeline.load(e.pipeline),n.index={};for(var i in e.index)n.index[i]=t.InvertedIndex.load(e.index[i]);return n},t.Index.prototype.addField=function(e){return this._fields.push(e),this.index[e]=new t.InvertedIndex,this},t.Index.prototype.setRef=function(e){return this._ref=e,this},t.Index.prototype.saveDocument=function(e){return this.documentStore=new t.DocumentStore(e),this},t.Index.prototype.addDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.addDoc(i,e),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));this.documentStore.addFieldLength(i,n,o.length);var r={};o.forEach(function(e){e in r?r[e]+=1:r[e]=1},this);for(var s in r){var u=r[s];u=Math.sqrt(u),this.index[n].addToken(s,{ref:i,tf:u})}},this),n&&this.eventEmitter.emit("add",e,this)}},t.Index.prototype.removeDocByRef=function(e){if(e&&this.documentStore.isDocStored()!==!1&&this.documentStore.hasDoc(e)){var t=this.documentStore.getDoc(e);this.removeDoc(t,!1)}},t.Index.prototype.removeDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.hasDoc(i)&&(this.documentStore.removeDoc(i),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));o.forEach(function(e){this.index[n].removeToken(e,i)},this)},this),n&&this.eventEmitter.emit("remove",e,this))}},t.Index.prototype.updateDoc=function(e,t){var t=void 0===t?!0:t;this.removeDocByRef(e[this._ref],!1),this.addDoc(e,!1),t&&this.eventEmitter.emit("update",e,this)},t.Index.prototype.idf=function(e,t){var n="@"+t+"/"+e;if(Object.prototype.hasOwnProperty.call(this._idfCache,n))return this._idfCache[n];var i=this.index[t].getDocFreq(e),o=1+Math.log(this.documentStore.length/(i+1));return this._idfCache[n]=o,o},t.Index.prototype.getFields=function(){return this._fields.slice()},t.Index.prototype.search=function(e,n){if(!e)return[];e="string"==typeof e?{any:e}:JSON.parse(JSON.stringify(e));var i=null;null!=n&&(i=JSON.stringify(n));for(var o=new t.Configuration(i,this.getFields()).get(),r={},s=Object.keys(e),u=0;u0&&t.push(e);for(var i in n)"docs"!==i&&"df"!==i&&this.expandToken(e+i,t,n[i]);return t},t.InvertedIndex.prototype.toJSON=function(){return{root:this.root}},t.Configuration=function(e,n){var e=e||"";if(void 0==n||null==n)throw new Error("fields should not be null");this.config={};var i;try{i=JSON.parse(e),this.buildUserConfig(i,n)}catch(o){t.utils.warn("user configuration parse failed, will use default configuration"),this.buildDefaultConfig(n)}},t.Configuration.prototype.buildDefaultConfig=function(e){this.reset(),e.forEach(function(e){this.config[e]={boost:1,bool:"OR",expand:!1}},this)},t.Configuration.prototype.buildUserConfig=function(e,n){var i="OR",o=!1;if(this.reset(),"bool"in e&&(i=e.bool||i),"expand"in e&&(o=e.expand||o),"fields"in e)for(var r in e.fields)if(n.indexOf(r)>-1){var s=e.fields[r],u=o;void 0!=s.expand&&(u=s.expand),this.config[r]={boost:s.boost||0===s.boost?s.boost:1,bool:s.bool||i,expand:u}}else t.utils.warn("field name in user configuration not found in index instance fields");else this.addAllFields2UserConfig(i,o,n)},t.Configuration.prototype.addAllFields2UserConfig=function(e,t,n){n.forEach(function(n){this.config[n]={boost:1,bool:e,expand:t}},this)},t.Configuration.prototype.get=function(){return this.config},t.Configuration.prototype.reset=function(){this.config={}},lunr.SortedSet=function(){this.length=0,this.elements=[]},lunr.SortedSet.load=function(e){var t=new this;return t.elements=e,t.length=e.length,t},lunr.SortedSet.prototype.add=function(){var e,t;for(e=0;e1;){if(r===e)return o;e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o]}return r===e?o:-1},lunr.SortedSet.prototype.locationFor=function(e){for(var t=0,n=this.elements.length,i=n-t,o=t+Math.floor(i/2),r=this.elements[o];i>1;)e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o];return r>e?o:e>r?o+1:void 0},lunr.SortedSet.prototype.intersect=function(e){for(var t=new lunr.SortedSet,n=0,i=0,o=this.length,r=e.length,s=this.elements,u=e.elements;;){if(n>o-1||i>r-1)break;s[n]!==u[i]?s[n]u[i]&&i++:(t.add(s[n]),n++,i++)}return t},lunr.SortedSet.prototype.clone=function(){var e=new lunr.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},lunr.SortedSet.prototype.union=function(e){var t,n,i;this.length>=e.length?(t=this,n=e):(t=e,n=this),i=t.clone();for(var o=0,r=n.toArray();o + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +FTL | Towards a 𝝺-calculus for large-scale systems + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+
+
+

FTL

+
+
+

Towards a 𝝺-calculus for large-scale systems

+ Get started +

Open-source Apache License. 0.248.0

+
+
+
+
+
+ +
+
+
+ + +
+

Infrastructure as code

+

Not YAML. Declare your infrastructure in the same language you're writing in as type-safe values, rather than in separate configuration files disassociated from their point of use.

+
+ +
+

Language agnostic

+

FTL makes it possible to write backend code in your language of choice. You write normal code, and FTL extracts a service interface from your code directly, making your functions and types automatically available to all supported languages.

+
+ +
+

Fearless development against production

+

There is no substitute for production data. FTL plans to support forking of production infrastructure _and_ code during development.

+
+ +
+

Fearlessly modify types

+

Multiple versions of a single verb with different signatures can be live concurrently. See Unison for inspiration. We can statically detect changes that would violate runtime and persistent data constraints.

+
+ +
+

AI from the ground up

+

We plan to integrate AI sensibly and deeply into the FTL platform. Automated AI-driven tuning suggestions, automated third-party API integration, and so on.

+
+ + +
+
+
+ +
+
+
+
+
+ + + + + +
+
+
+
+ +
+
+
    + +
+
+
+
+
+ + + + + + + + + + + + + + + diff --git a/index.js b/index.js new file mode 100644 index 0000000000..8c87d5fb75 --- /dev/null +++ b/index.js @@ -0,0 +1,146 @@ +var suggestions = document.getElementById('suggestions'); +var userinput = document.getElementById('userinput'); + +document.addEventListener('keydown', inputFocus); + +function inputFocus(e) { + + if (e.keyCode === 191 ) { + e.preventDefault(); + userinput.focus(); + } + + if (e.keyCode === 27 ) { + userinput.blur(); + suggestions.classList.add('d-none'); + } + +} + +document.addEventListener('click', function(event) { + + var isClickInsideElement = suggestions.contains(event.target); + + if (!isClickInsideElement) { + suggestions.classList.add('d-none'); + } + +}); + +/* +Source: + - https://dev.to/shubhamprakash/trap-focus-using-javascript-6a3 +*/ + +document.addEventListener('keydown',suggestionFocus); + +function suggestionFocus(e){ + + const focusableSuggestions= suggestions.querySelectorAll('a'); + const focusable= [...focusableSuggestions]; + const index = focusable.indexOf(document.activeElement); + + let nextIndex = 0; + + if (e.keyCode === 38) { + e.preventDefault(); + nextIndex= index > 0 ? index-1 : 0; + focusableSuggestions[nextIndex].focus(); + } + else if (e.keyCode === 40) { + e.preventDefault(); + nextIndex= index+1 < focusable.length ? index+1 : index; + focusableSuggestions[nextIndex].focus(); + } + +} + + +/* +Source: + - https://github.com/nextapps-de/flexsearch#index-documents-field-search + - https://raw.githack.com/nextapps-de/flexsearch/master/demo/autocomplete.html +*/ + +(function(){ + + var index = new FlexSearch({ + preset: 'score', + cache: true, + doc: { + id: 'id', + field: [ + 'title', + 'description', + 'content', + ], + store: [ + 'href', + 'title', + 'description', + ], + }, + }); + + var docs = [ + {{ range $index, $page := (where .Site.Pages "Section" "docs") -}} + { + id: {{ $index }}, + href: "{{ .RelPermalink | relURL }}", + title: {{ .Title | jsonify }}, + description: {{ .Params.description | jsonify }}, + content: {{ .Content | jsonify }} + }, + {{ end -}} + ]; + + index.add(docs); + + userinput.addEventListener('input', show_results, true); + suggestions.addEventListener('click', accept_suggestion, true); + + function show_results(){ + + var value = this.value; + var results = index.search(value, 5); + var entry, childs = suggestions.childNodes; + var i = 0, len = results.length; + + suggestions.classList.remove('d-none'); + + results.forEach(function(page) { + + entry = document.createElement('div'); + + entry.innerHTML = ''; + + a = entry.querySelector('a'), + t = entry.querySelector('span:first-child'), + d = entry.querySelector('span:nth-child(2)'); + + a.href = page.href; + t.textContent = page.title; + d.textContent = page.description; + + suggestions.appendChild(entry); + + }); + + while(childs.length > len){ + + suggestions.removeChild(childs[i]) + } + + } + + function accept_suggestion(){ + + while(suggestions.lastChild){ + + suggestions.removeChild(suggestions.lastChild); + } + + return false; + } + +}()); diff --git a/js/code-selector.js b/js/code-selector.js new file mode 100644 index 0000000000..3142d93cf0 --- /dev/null +++ b/js/code-selector.js @@ -0,0 +1,127 @@ +document.addEventListener("DOMContentLoaded", inject); + +function inject() { + document.querySelectorAll(".code-selector").forEach(injectTabs); +} + +function injectTabs(codeSelector) { + const nav = codeSelector.querySelector("ul.nav"); + + const langs = []; + const tabs = []; + let currentLang = null; + codeSelector.childNodes.forEach((element) => { + let toAdd = null; + + if (element.nodeType === Node.COMMENT_NODE) { + // if it's a comment like , then set the currentLang to go and add it to langs + // end will cancel the currentLang, so you can continue to write common documentation. + const lang = element.data.trim(); + if (lang === "end") { + currentLang = null; + } else { + currentLang = lang; + toAdd = { lang, element }; + } + } else if (currentLang) { + // if we are in a currentLang, then add the element to it. + toAdd = { lang: currentLang, element }; + } + + if (!toAdd) { + return; + } + + langs.push(toAdd); + if (!tabs.includes(toAdd.lang)) { + tabs.push(toAdd.lang); + } + }); + + // Let us put this in the codeSelector element, so that we later check if the new selected language is in the list first. + codeSelector.langs = langs; + + let saved = localStorage.getItem("code-lang"); + let selected = tabs[0]; + if (saved) { + // Only select the saved language if it's in the list. + const found = tabs.find((lang) => lang === saved); + if (found) { + selected = found; + } + } + + for (const lang of tabs) { + const li = document.createElement("li"); + li.classList.add("nav-item"); + + const a = document.createElement("a"); + a.classList.add("nav-link"); + if (selected === lang) { + a.classList.add("active"); + a.setAttribute("aria-current", "page"); + } + + a.href = "#"; + a.textContent = capitalize(lang); + a.lang = lang; + + a.addEventListener("click", (e) => { + e.preventDefault(); + changeLanguage(lang); + }); + + li.appendChild(a); + nav.appendChild(li); + } + + for (const { lang, element } of langs) { + if (element.classList && selected !== lang) { + element.classList.add("d-none"); + } + } +} + +function capitalize(str) { + return str[0].toUpperCase() + str.slice(1); +} + +function changeLanguage(lang) { + localStorage.setItem("code-lang", lang); + + document.querySelectorAll(".code-selector").forEach((codeSelector) => { + const langs = codeSelector.langs; + if (!langs) { + console.error("Missing langs property on codeSelector", codeSelector); + return; + } + + const selected = langs.find((l) => l.lang === lang); + if (!selected) { + // This tab group doesn't have the selected language--all good. + return; + } + + // Show/hide each element within the codeSelector + langs.forEach((l) => { + if (!l.element.classList) { + return; + } + if (l.lang === selected.lang) { + l.element.classList.remove("d-none"); + } else { + l.element.classList.add("d-none"); + } + }); + + // Update the active tab + codeSelector.querySelectorAll("a.nav-link").forEach((a) => { + a.classList.remove("active"); + a.removeAttribute("aria-current"); + if (a.lang === lang) { + a.classList.add("active"); + a.setAttribute("aria-current", "page"); + } + }); + }); +} diff --git a/js/main.js b/js/main.js new file mode 100644 index 0000000000..2fbc2285bf --- /dev/null +++ b/js/main.js @@ -0,0 +1,14 @@ +// Set darkmode +document.getElementById('mode').addEventListener('click', () => { + + document.body.classList.toggle('dark'); + localStorage.setItem('theme', document.body.classList.contains('dark') ? 'dark' : 'light'); + +}); + +// enforce local storage setting but also fallback to user-agent preferences +if (localStorage.getItem('theme') === 'dark' || (!localStorage.getItem('theme') && window.matchMedia("(prefers-color-scheme: dark)").matches)) { + + document.body.classList.add('dark'); + +} diff --git a/js/search.js b/js/search.js new file mode 100644 index 0000000000..7c5c745831 --- /dev/null +++ b/js/search.js @@ -0,0 +1,317 @@ +var suggestions = document.getElementById('suggestions'); +var userinput = document.getElementById('userinput'); + +document.addEventListener('keydown', inputFocus); + +function inputFocus(e) { + + if (e.keyCode === 191 + && document.activeElement.tagName !== "INPUT" + && document.activeElement.tagName !== "TEXTAREA") { + e.preventDefault(); + userinput.focus(); + } + + if (e.keyCode === 27 ) { + userinput.blur(); + suggestions.classList.add('d-none'); + } + +} + +document.addEventListener('click', function(event) { + + var isClickInsideElement = suggestions.contains(event.target); + + if (!isClickInsideElement) { + suggestions.classList.add('d-none'); + } + +}); + +/* +Source: + - https://dev.to/shubhamprakash/trap-focus-using-javascript-6a3 +*/ + +document.addEventListener('keydown',suggestionFocus); + +function suggestionFocus(e){ + const focusableSuggestions= suggestions.querySelectorAll('a'); + if (suggestions.classList.contains('d-none') + || focusableSuggestions.length === 0) { + return; + } + const focusable= [...focusableSuggestions]; + const index = focusable.indexOf(document.activeElement); + + let nextIndex = 0; + + if (e.keyCode === 38) { + e.preventDefault(); + nextIndex= index > 0 ? index-1 : 0; + focusableSuggestions[nextIndex].focus(); + } + else if (e.keyCode === 40) { + e.preventDefault(); + nextIndex= index+1 < focusable.length ? index+1 : index; + focusableSuggestions[nextIndex].focus(); + } + +} + +/* +Source: + - https://github.com/nextapps-de/flexsearch#index-documents-field-search + - https://raw.githack.com/nextapps-de/flexsearch/master/demo/autocomplete.html + - http://elasticlunr.com/ + - https://github.com/getzola/zola/blob/master/docs/static/search.js +*/ +(function(){ + var index = elasticlunr.Index.load(window.searchIndex); + userinput.addEventListener('input', show_results, true); + suggestions.addEventListener('click', accept_suggestion, true); + + function show_results(){ + var value = this.value.trim(); + var options = { + bool: "OR", + fields: { + title: {boost: 2}, + body: {boost: 1}, + } + }; + var results = index.search(value, options); + + var entry, childs = suggestions.childNodes; + var i = 0, len = results.length; + var items = value.split(/\s+/); + suggestions.classList.remove('d-none'); + + results.forEach(function(page) { + if (page.doc.body !== '') { + entry = document.createElement('div'); + + entry.innerHTML = ''; + + a = entry.querySelector('a'), + t = entry.querySelector('span:first-child'), + d = entry.querySelector('span:nth-child(2)'); + a.href = page.ref; + t.textContent = page.doc.title; + d.innerHTML = makeTeaser(page.doc.body, items); + + suggestions.appendChild(entry); + } + }); + + while(childs.length > len){ + suggestions.removeChild(childs[i]) + } + + } + + function accept_suggestion(){ + + while(suggestions.lastChild){ + + suggestions.removeChild(suggestions.lastChild); + } + + return false; + } + + // Taken from mdbook + // The strategy is as follows: + // First, assign a value to each word in the document: + // Words that correspond to search terms (stemmer aware): 40 + // Normal words: 2 + // First word in a sentence: 8 + // Then use a sliding window with a constant number of words and count the + // sum of the values of the words within the window. Then use the window that got the + // maximum sum. If there are multiple maximas, then get the last one. + // Enclose the terms in . + function makeTeaser(body, terms) { + var TERM_WEIGHT = 40; + var NORMAL_WORD_WEIGHT = 2; + var FIRST_WORD_WEIGHT = 8; + var TEASER_MAX_WORDS = 30; + + var stemmedTerms = terms.map(function (w) { + return elasticlunr.stemmer(w.toLowerCase()); + }); + var termFound = false; + var index = 0; + var weighted = []; // contains elements of ["word", weight, index_in_document] + + // split in sentences, then words + var sentences = body.toLowerCase().split(". "); + for (var i in sentences) { + var words = sentences[i].split(/[\s\n]/); + var value = FIRST_WORD_WEIGHT; + for (var j in words) { + + var word = words[j]; + + if (word.length > 0) { + for (var k in stemmedTerms) { + if (elasticlunr.stemmer(word).startsWith(stemmedTerms[k])) { + value = TERM_WEIGHT; + termFound = true; + } + } + weighted.push([word, value, index]); + value = NORMAL_WORD_WEIGHT; + } + + index += word.length; + index += 1; // ' ' or '.' if last word in sentence + } + + index += 1; // because we split at a two-char boundary '. ' + } + + if (weighted.length === 0) { + if (body.length !== undefined && body.length > TEASER_MAX_WORDS * 10) { + return body.substring(0, TEASER_MAX_WORDS * 10) + '...'; + } else { + return body; + } + } + + var windowWeights = []; + var windowSize = Math.min(weighted.length, TEASER_MAX_WORDS); + // We add a window with all the weights first + var curSum = 0; + for (var i = 0; i < windowSize; i++) { + curSum += weighted[i][1]; + } + windowWeights.push(curSum); + + for (var i = 0; i < weighted.length - windowSize; i++) { + curSum -= weighted[i][1]; + curSum += weighted[i + windowSize][1]; + windowWeights.push(curSum); + } + + // If we didn't find the term, just pick the first window + var maxSumIndex = 0; + if (termFound) { + var maxFound = 0; + // backwards + for (var i = windowWeights.length - 1; i >= 0; i--) { + if (windowWeights[i] > maxFound) { + maxFound = windowWeights[i]; + maxSumIndex = i; + } + } + } + + var teaser = []; + var startIndex = weighted[maxSumIndex][2]; + for (var i = maxSumIndex; i < maxSumIndex + windowSize; i++) { + var word = weighted[i]; + if (startIndex < word[2]) { + // missing text from index to start of `word` + teaser.push(body.substring(startIndex, word[2])); + startIndex = word[2]; + } + + // add around search terms + if (word[1] === TERM_WEIGHT) { + teaser.push(""); + } + + startIndex = word[2] + word[0].length; + // Check the string is ascii characters or not + var re = /^[\x00-\xff]+$/ + if (word[1] !== TERM_WEIGHT && word[0].length >= 12 && !re.test(word[0])) { + // If the string's length is too long, it maybe a Chinese/Japance/Korean article + // if using substring method directly, it may occur error codes on emoji chars + var strBefor = body.substring(word[2], startIndex); + var strAfter = substringByByte(strBefor, 12); + teaser.push(strAfter); + } else { + teaser.push(body.substring(word[2], startIndex)); + } + + if (word[1] === TERM_WEIGHT) { + teaser.push(""); + } + } + teaser.push("…"); + return teaser.join(""); + } +}()); + + +// Get substring by bytes +// If using JavaScript inline substring method, it will return error codes +// Source: https://www.52pojie.cn/thread-1059814-1-1.html +function substringByByte(str, maxLength) { + var result = ""; + var flag = false; + var len = 0; + var length = 0; + var length2 = 0; + for (var i = 0; i < str.length; i++) { + var code = str.codePointAt(i).toString(16); + if (code.length > 4) { + i++; + if ((i + 1) < str.length) { + flag = str.codePointAt(i + 1).toString(16) == "200d"; + } + } + if (flag) { + len += getByteByHex(code); + if (i == str.length - 1) { + length += len; + if (length <= maxLength) { + result += str.substr(length2, i - length2 + 1); + } else { + break + } + } + } else { + if (len != 0) { + length += len; + length += getByteByHex(code); + if (length <= maxLength) { + result += str.substr(length2, i - length2 + 1); + length2 = i + 1; + } else { + break + } + len = 0; + continue; + } + length += getByteByHex(code); + if (length <= maxLength) { + if (code.length <= 4) { + result += str[i] + } else { + result += str[i - 1] + str[i] + } + length2 = i + 1; + } else { + break + } + } + } + return result; +} + +// Get the string bytes from binary +function getByteByBinary(binaryCode) { + // Binary system, starts with `0b` in ES6 + // Octal number system, starts with `0` in ES5 and starts with `0o` in ES6 + // Hexadecimal, starts with `0x` in both ES5 and ES6 + var byteLengthDatas = [0, 1, 2, 3, 4]; + var len = byteLengthDatas[Math.ceil(binaryCode.length / 8)]; + return len; +} + +// Get the string bytes from hexadecimal +function getByteByHex(hexCode) { + return getByteByBinary(parseInt(hexCode, 16).toString(2)); +} diff --git a/logo-doks.png b/logo-doks.png new file mode 100644 index 0000000000..74bdfb9da9 Binary files /dev/null and b/logo-doks.png differ diff --git a/main.css b/main.css new file mode 100644 index 0000000000..1dcc1a294c --- /dev/null +++ b/main.css @@ -0,0 +1,6 @@ +/*! + * Bootstrap v5.0.0-beta3 (https://getbootstrap.com/) + * Copyright 2011-2021 The Bootstrap Authors + * Copyright 2011-2021 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */:root{--bs-blue: #0d6efd;--bs-indigo: #6610f2;--bs-purple: #5d2f86;--bs-pink: #d63384;--bs-red: #dc3545;--bs-orange: #fd7e14;--bs-yellow: #ffe000;--bs-green: #198754;--bs-teal: #20c997;--bs-cyan: #0dcaf0;--bs-white: #fff;--bs-gray: #6c757d;--bs-gray-dark: #343a40;--bs-primary: #5d2f86;--bs-secondary: #6c757d;--bs-success: #198754;--bs-info: #0dcaf0;--bs-warning: #ffe000;--bs-danger: #dc3545;--bs-light: #f8f9fa;--bs-dark: #212529;--bs-font-sans-serif: "Jost", -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";--bs-font-monospace: sfmono-regular, menlo, monaco, consolas, "Liberation Mono", "Courier New", monospace;--bs-gradient: linear-gradient(180deg, rgba(255,255,255,.15), rgba(255,255,255,0))}*,*::before,*::after{box-sizing:border-box}@media (prefers-reduced-motion: no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:"Jost",-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:#1d2d35;background-color:#fff;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(29,45,53,0)}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h6,.h6,h5,.h5,h4,.h4,h3,.h3,h2,.h2,h1,.h1{margin-top:0;margin-bottom:.5rem;font-weight:700;line-height:1.2}h1,.h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width: 1200px){h1,.h1{font-size:2.5rem}}h2,.h2{font-size:calc(1.325rem + .9vw)}@media (min-width: 1200px){h2,.h2{font-size:2rem}}h3,.h3{font-size:calc(1.3rem + .6vw)}@media (min-width: 1200px){h3,.h3{font-size:1.75rem}}h4,.h4{font-size:calc(1.275rem + .3vw)}@media (min-width: 1200px){h4,.h4{font-size:1.5rem}}h5,.h5{font-size:1.25rem}h6,.h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[title],abbr[data-bs-original-title]{text-decoration:underline dotted;cursor:help;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}ol,ul,dl{margin-top:0;margin-bottom:1rem}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small,.small{font-size:.875em}mark,.mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#5d2f86;text-decoration:none}a:hover{color:#4a266b}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}pre,code,kbd,samp{font-family:var(--bs-font-monospace);font-size:1em;direction:ltr /* rtl:ignore */;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}thead,tbody,tfoot,tr,td,th{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}input,button,select,optgroup,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button:not(:disabled),[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width: 1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-text,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none !important}.lead{font-size:1.25rem;font-weight:400}.display-1{font-size:calc(1.625rem + 4.5vw);font-weight:300;line-height:1.2}@media (min-width: 1200px){.display-1{font-size:5rem}}.display-2{font-size:calc(1.575rem + 3.9vw);font-weight:300;line-height:1.2}@media (min-width: 1200px){.display-2{font-size:4.5rem}}.display-3{font-size:calc(1.525rem + 3.3vw);font-weight:300;line-height:1.2}@media (min-width: 1200px){.display-3{font-size:4rem}}.display-4{font-size:calc(1.475rem + 2.7vw);font-weight:300;line-height:1.2}@media (min-width: 1200px){.display-4{font-size:3.5rem}}.display-5{font-size:calc(1.425rem + 2.1vw);font-weight:300;line-height:1.2}@media (min-width: 1200px){.display-5{font-size:3rem}}.display-6{font-size:calc(1.375rem + 1.5vw);font-weight:300;line-height:1.2}@media (min-width: 1200px){.display-6{font-size:2.5rem}}.list-unstyled,.comment-list{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:.875em;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote>:last-child{margin-bottom:0}.blockquote-footer{margin-top:-1rem;margin-bottom:1rem;font-size:.875em;color:#6c757d}.blockquote-footer::before{content:"— "}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:.875em;color:#6c757d}.container,.container-fluid,.container-xxl,.container-xl,.container-lg,.container-md,.container-sm{width:100%;padding-right:var(--bs-gutter-x, 24px);padding-left:var(--bs-gutter-x, 24px);margin-right:auto;margin-left:auto}@media (min-width: 576px){.container-sm,.container{max-width:540px}}@media (min-width: 768px){.container-md,.container-sm,.container{max-width:720px}}@media (min-width: 992px){.container-lg,.container-md,.container-sm,.container{max-width:960px}}@media (min-width: 1200px){.container-xl,.container-lg,.container-md,.container-sm,.container{max-width:1240px}}@media (min-width: 1400px){.container-xxl,.container-xl,.container-lg,.container-md,.container-sm,.container{max-width:1320px}}.row{--bs-gutter-x: 48px;--bs-gutter-y: 0;display:flex;flex-wrap:wrap;margin-top:calc(var(--bs-gutter-y)*-1);margin-right:calc(var(--bs-gutter-x)/-2);margin-left:calc(var(--bs-gutter-x)/-2)}.row>*{flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--bs-gutter-x)/2);padding-left:calc(var(--bs-gutter-x)/2);margin-top:var(--bs-gutter-y)}.col{flex:1 0 0%}.row-cols-auto>*{flex:0 0 auto;width:auto}.row-cols-1>*{flex:0 0 auto;width:100%}.row-cols-2>*{flex:0 0 auto;width:50%}.row-cols-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-4>*{flex:0 0 auto;width:25%}.row-cols-5>*{flex:0 0 auto;width:20%}.row-cols-6>*{flex:0 0 auto;width:16.6666666667%}.col-auto{flex:0 0 auto;width:auto}.col-1{flex:0 0 auto;width:6.25%}.col-2{flex:0 0 auto;width:12.5%}.col-3{flex:0 0 auto;width:18.75%}.col-4{flex:0 0 auto;width:25%}.col-5{flex:0 0 auto;width:31.25%}.col-6{flex:0 0 auto;width:37.5%}.col-7{flex:0 0 auto;width:43.75%}.col-8{flex:0 0 auto;width:50%}.col-9{flex:0 0 auto;width:56.25%}.col-10{flex:0 0 auto;width:62.5%}.col-11{flex:0 0 auto;width:68.75%}.col-12{flex:0 0 auto;width:75%}.col-13{flex:0 0 auto;width:81.25%}.col-14{flex:0 0 auto;width:87.5%}.col-15{flex:0 0 auto;width:93.75%}.col-16{flex:0 0 auto;width:100%}.offset-1{margin-left:6.25%}.offset-2{margin-left:12.5%}.offset-3{margin-left:18.75%}.offset-4{margin-left:25%}.offset-5{margin-left:31.25%}.offset-6{margin-left:37.5%}.offset-7{margin-left:43.75%}.offset-8{margin-left:50%}.offset-9{margin-left:56.25%}.offset-10{margin-left:62.5%}.offset-11{margin-left:68.75%}.offset-12{margin-left:75%}.offset-13{margin-left:81.25%}.offset-14{margin-left:87.5%}.offset-15{margin-left:93.75%}.g-0,.gx-0{--bs-gutter-x: 0}.g-0,.gy-0{--bs-gutter-y: 0}.g-1,.gx-1{--bs-gutter-x: .25rem}.g-1,.gy-1{--bs-gutter-y: .25rem}.g-2,.gx-2{--bs-gutter-x: .5rem}.g-2,.gy-2{--bs-gutter-y: .5rem}.g-3,.gx-3{--bs-gutter-x: 1rem}.g-3,.gy-3{--bs-gutter-y: 1rem}.g-4,.gx-4{--bs-gutter-x: 1.5rem}.g-4,.gy-4{--bs-gutter-y: 1.5rem}.g-5,.gx-5{--bs-gutter-x: 3rem}.g-5,.gy-5{--bs-gutter-y: 3rem}@media (min-width: 576px){.col-sm{flex:1 0 0%}.row-cols-sm-auto>*{flex:0 0 auto;width:auto}.row-cols-sm-1>*{flex:0 0 auto;width:100%}.row-cols-sm-2>*{flex:0 0 auto;width:50%}.row-cols-sm-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-sm-4>*{flex:0 0 auto;width:25%}.row-cols-sm-5>*{flex:0 0 auto;width:20%}.row-cols-sm-6>*{flex:0 0 auto;width:16.6666666667%}.col-sm-auto{flex:0 0 auto;width:auto}.col-sm-1{flex:0 0 auto;width:6.25%}.col-sm-2{flex:0 0 auto;width:12.5%}.col-sm-3{flex:0 0 auto;width:18.75%}.col-sm-4{flex:0 0 auto;width:25%}.col-sm-5{flex:0 0 auto;width:31.25%}.col-sm-6{flex:0 0 auto;width:37.5%}.col-sm-7{flex:0 0 auto;width:43.75%}.col-sm-8{flex:0 0 auto;width:50%}.col-sm-9{flex:0 0 auto;width:56.25%}.col-sm-10{flex:0 0 auto;width:62.5%}.col-sm-11{flex:0 0 auto;width:68.75%}.col-sm-12{flex:0 0 auto;width:75%}.col-sm-13{flex:0 0 auto;width:81.25%}.col-sm-14{flex:0 0 auto;width:87.5%}.col-sm-15{flex:0 0 auto;width:93.75%}.col-sm-16{flex:0 0 auto;width:100%}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:6.25%}.offset-sm-2{margin-left:12.5%}.offset-sm-3{margin-left:18.75%}.offset-sm-4{margin-left:25%}.offset-sm-5{margin-left:31.25%}.offset-sm-6{margin-left:37.5%}.offset-sm-7{margin-left:43.75%}.offset-sm-8{margin-left:50%}.offset-sm-9{margin-left:56.25%}.offset-sm-10{margin-left:62.5%}.offset-sm-11{margin-left:68.75%}.offset-sm-12{margin-left:75%}.offset-sm-13{margin-left:81.25%}.offset-sm-14{margin-left:87.5%}.offset-sm-15{margin-left:93.75%}.g-sm-0,.gx-sm-0{--bs-gutter-x: 0}.g-sm-0,.gy-sm-0{--bs-gutter-y: 0}.g-sm-1,.gx-sm-1{--bs-gutter-x: .25rem}.g-sm-1,.gy-sm-1{--bs-gutter-y: .25rem}.g-sm-2,.gx-sm-2{--bs-gutter-x: .5rem}.g-sm-2,.gy-sm-2{--bs-gutter-y: .5rem}.g-sm-3,.gx-sm-3{--bs-gutter-x: 1rem}.g-sm-3,.gy-sm-3{--bs-gutter-y: 1rem}.g-sm-4,.gx-sm-4{--bs-gutter-x: 1.5rem}.g-sm-4,.gy-sm-4{--bs-gutter-y: 1.5rem}.g-sm-5,.gx-sm-5{--bs-gutter-x: 3rem}.g-sm-5,.gy-sm-5{--bs-gutter-y: 3rem}}@media (min-width: 768px){.col-md{flex:1 0 0%}.row-cols-md-auto>*{flex:0 0 auto;width:auto}.row-cols-md-1>*{flex:0 0 auto;width:100%}.row-cols-md-2>*{flex:0 0 auto;width:50%}.row-cols-md-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-md-4>*{flex:0 0 auto;width:25%}.row-cols-md-5>*{flex:0 0 auto;width:20%}.row-cols-md-6>*{flex:0 0 auto;width:16.6666666667%}.col-md-auto{flex:0 0 auto;width:auto}.col-md-1{flex:0 0 auto;width:6.25%}.col-md-2{flex:0 0 auto;width:12.5%}.col-md-3{flex:0 0 auto;width:18.75%}.col-md-4{flex:0 0 auto;width:25%}.col-md-5{flex:0 0 auto;width:31.25%}.col-md-6{flex:0 0 auto;width:37.5%}.col-md-7{flex:0 0 auto;width:43.75%}.col-md-8{flex:0 0 auto;width:50%}.col-md-9{flex:0 0 auto;width:56.25%}.col-md-10{flex:0 0 auto;width:62.5%}.col-md-11{flex:0 0 auto;width:68.75%}.col-md-12{flex:0 0 auto;width:75%}.col-md-13{flex:0 0 auto;width:81.25%}.col-md-14{flex:0 0 auto;width:87.5%}.col-md-15{flex:0 0 auto;width:93.75%}.col-md-16{flex:0 0 auto;width:100%}.offset-md-0{margin-left:0}.offset-md-1{margin-left:6.25%}.offset-md-2{margin-left:12.5%}.offset-md-3{margin-left:18.75%}.offset-md-4{margin-left:25%}.offset-md-5{margin-left:31.25%}.offset-md-6{margin-left:37.5%}.offset-md-7{margin-left:43.75%}.offset-md-8{margin-left:50%}.offset-md-9{margin-left:56.25%}.offset-md-10{margin-left:62.5%}.offset-md-11{margin-left:68.75%}.offset-md-12{margin-left:75%}.offset-md-13{margin-left:81.25%}.offset-md-14{margin-left:87.5%}.offset-md-15{margin-left:93.75%}.g-md-0,.gx-md-0{--bs-gutter-x: 0}.g-md-0,.gy-md-0{--bs-gutter-y: 0}.g-md-1,.gx-md-1{--bs-gutter-x: .25rem}.g-md-1,.gy-md-1{--bs-gutter-y: .25rem}.g-md-2,.gx-md-2{--bs-gutter-x: .5rem}.g-md-2,.gy-md-2{--bs-gutter-y: .5rem}.g-md-3,.gx-md-3{--bs-gutter-x: 1rem}.g-md-3,.gy-md-3{--bs-gutter-y: 1rem}.g-md-4,.gx-md-4{--bs-gutter-x: 1.5rem}.g-md-4,.gy-md-4{--bs-gutter-y: 1.5rem}.g-md-5,.gx-md-5{--bs-gutter-x: 3rem}.g-md-5,.gy-md-5{--bs-gutter-y: 3rem}}@media (min-width: 992px){.col-lg{flex:1 0 0%}.row-cols-lg-auto>*{flex:0 0 auto;width:auto}.row-cols-lg-1>*{flex:0 0 auto;width:100%}.row-cols-lg-2>*{flex:0 0 auto;width:50%}.row-cols-lg-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-lg-4>*{flex:0 0 auto;width:25%}.row-cols-lg-5>*{flex:0 0 auto;width:20%}.row-cols-lg-6>*{flex:0 0 auto;width:16.6666666667%}.col-lg-auto{flex:0 0 auto;width:auto}.col-lg-1{flex:0 0 auto;width:6.25%}.col-lg-2{flex:0 0 auto;width:12.5%}.col-lg-3{flex:0 0 auto;width:18.75%}.col-lg-4{flex:0 0 auto;width:25%}.col-lg-5{flex:0 0 auto;width:31.25%}.col-lg-6{flex:0 0 auto;width:37.5%}.col-lg-7{flex:0 0 auto;width:43.75%}.col-lg-8{flex:0 0 auto;width:50%}.col-lg-9{flex:0 0 auto;width:56.25%}.col-lg-10{flex:0 0 auto;width:62.5%}.col-lg-11{flex:0 0 auto;width:68.75%}.col-lg-12{flex:0 0 auto;width:75%}.col-lg-13{flex:0 0 auto;width:81.25%}.col-lg-14{flex:0 0 auto;width:87.5%}.col-lg-15{flex:0 0 auto;width:93.75%}.col-lg-16{flex:0 0 auto;width:100%}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:6.25%}.offset-lg-2{margin-left:12.5%}.offset-lg-3{margin-left:18.75%}.offset-lg-4{margin-left:25%}.offset-lg-5{margin-left:31.25%}.offset-lg-6{margin-left:37.5%}.offset-lg-7{margin-left:43.75%}.offset-lg-8{margin-left:50%}.offset-lg-9{margin-left:56.25%}.offset-lg-10{margin-left:62.5%}.offset-lg-11{margin-left:68.75%}.offset-lg-12{margin-left:75%}.offset-lg-13{margin-left:81.25%}.offset-lg-14{margin-left:87.5%}.offset-lg-15{margin-left:93.75%}.g-lg-0,.gx-lg-0{--bs-gutter-x: 0}.g-lg-0,.gy-lg-0{--bs-gutter-y: 0}.g-lg-1,.gx-lg-1{--bs-gutter-x: .25rem}.g-lg-1,.gy-lg-1{--bs-gutter-y: .25rem}.g-lg-2,.gx-lg-2{--bs-gutter-x: .5rem}.g-lg-2,.gy-lg-2{--bs-gutter-y: .5rem}.g-lg-3,.gx-lg-3{--bs-gutter-x: 1rem}.g-lg-3,.gy-lg-3{--bs-gutter-y: 1rem}.g-lg-4,.gx-lg-4{--bs-gutter-x: 1.5rem}.g-lg-4,.gy-lg-4{--bs-gutter-y: 1.5rem}.g-lg-5,.gx-lg-5{--bs-gutter-x: 3rem}.g-lg-5,.gy-lg-5{--bs-gutter-y: 3rem}}@media (min-width: 1200px){.col-xl{flex:1 0 0%}.row-cols-xl-auto>*{flex:0 0 auto;width:auto}.row-cols-xl-1>*{flex:0 0 auto;width:100%}.row-cols-xl-2>*{flex:0 0 auto;width:50%}.row-cols-xl-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-xl-4>*{flex:0 0 auto;width:25%}.row-cols-xl-5>*{flex:0 0 auto;width:20%}.row-cols-xl-6>*{flex:0 0 auto;width:16.6666666667%}.col-xl-auto{flex:0 0 auto;width:auto}.col-xl-1{flex:0 0 auto;width:6.25%}.col-xl-2{flex:0 0 auto;width:12.5%}.col-xl-3{flex:0 0 auto;width:18.75%}.col-xl-4{flex:0 0 auto;width:25%}.col-xl-5{flex:0 0 auto;width:31.25%}.col-xl-6{flex:0 0 auto;width:37.5%}.col-xl-7{flex:0 0 auto;width:43.75%}.col-xl-8{flex:0 0 auto;width:50%}.col-xl-9{flex:0 0 auto;width:56.25%}.col-xl-10{flex:0 0 auto;width:62.5%}.col-xl-11{flex:0 0 auto;width:68.75%}.col-xl-12{flex:0 0 auto;width:75%}.col-xl-13{flex:0 0 auto;width:81.25%}.col-xl-14{flex:0 0 auto;width:87.5%}.col-xl-15{flex:0 0 auto;width:93.75%}.col-xl-16{flex:0 0 auto;width:100%}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:6.25%}.offset-xl-2{margin-left:12.5%}.offset-xl-3{margin-left:18.75%}.offset-xl-4{margin-left:25%}.offset-xl-5{margin-left:31.25%}.offset-xl-6{margin-left:37.5%}.offset-xl-7{margin-left:43.75%}.offset-xl-8{margin-left:50%}.offset-xl-9{margin-left:56.25%}.offset-xl-10{margin-left:62.5%}.offset-xl-11{margin-left:68.75%}.offset-xl-12{margin-left:75%}.offset-xl-13{margin-left:81.25%}.offset-xl-14{margin-left:87.5%}.offset-xl-15{margin-left:93.75%}.g-xl-0,.gx-xl-0{--bs-gutter-x: 0}.g-xl-0,.gy-xl-0{--bs-gutter-y: 0}.g-xl-1,.gx-xl-1{--bs-gutter-x: .25rem}.g-xl-1,.gy-xl-1{--bs-gutter-y: .25rem}.g-xl-2,.gx-xl-2{--bs-gutter-x: .5rem}.g-xl-2,.gy-xl-2{--bs-gutter-y: .5rem}.g-xl-3,.gx-xl-3{--bs-gutter-x: 1rem}.g-xl-3,.gy-xl-3{--bs-gutter-y: 1rem}.g-xl-4,.gx-xl-4{--bs-gutter-x: 1.5rem}.g-xl-4,.gy-xl-4{--bs-gutter-y: 1.5rem}.g-xl-5,.gx-xl-5{--bs-gutter-x: 3rem}.g-xl-5,.gy-xl-5{--bs-gutter-y: 3rem}}@media (min-width: 1400px){.col-xxl{flex:1 0 0%}.row-cols-xxl-auto>*{flex:0 0 auto;width:auto}.row-cols-xxl-1>*{flex:0 0 auto;width:100%}.row-cols-xxl-2>*{flex:0 0 auto;width:50%}.row-cols-xxl-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-xxl-4>*{flex:0 0 auto;width:25%}.row-cols-xxl-5>*{flex:0 0 auto;width:20%}.row-cols-xxl-6>*{flex:0 0 auto;width:16.6666666667%}.col-xxl-auto{flex:0 0 auto;width:auto}.col-xxl-1{flex:0 0 auto;width:6.25%}.col-xxl-2{flex:0 0 auto;width:12.5%}.col-xxl-3{flex:0 0 auto;width:18.75%}.col-xxl-4{flex:0 0 auto;width:25%}.col-xxl-5{flex:0 0 auto;width:31.25%}.col-xxl-6{flex:0 0 auto;width:37.5%}.col-xxl-7{flex:0 0 auto;width:43.75%}.col-xxl-8{flex:0 0 auto;width:50%}.col-xxl-9{flex:0 0 auto;width:56.25%}.col-xxl-10{flex:0 0 auto;width:62.5%}.col-xxl-11{flex:0 0 auto;width:68.75%}.col-xxl-12{flex:0 0 auto;width:75%}.col-xxl-13{flex:0 0 auto;width:81.25%}.col-xxl-14{flex:0 0 auto;width:87.5%}.col-xxl-15{flex:0 0 auto;width:93.75%}.col-xxl-16{flex:0 0 auto;width:100%}.offset-xxl-0{margin-left:0}.offset-xxl-1{margin-left:6.25%}.offset-xxl-2{margin-left:12.5%}.offset-xxl-3{margin-left:18.75%}.offset-xxl-4{margin-left:25%}.offset-xxl-5{margin-left:31.25%}.offset-xxl-6{margin-left:37.5%}.offset-xxl-7{margin-left:43.75%}.offset-xxl-8{margin-left:50%}.offset-xxl-9{margin-left:56.25%}.offset-xxl-10{margin-left:62.5%}.offset-xxl-11{margin-left:68.75%}.offset-xxl-12{margin-left:75%}.offset-xxl-13{margin-left:81.25%}.offset-xxl-14{margin-left:87.5%}.offset-xxl-15{margin-left:93.75%}.g-xxl-0,.gx-xxl-0{--bs-gutter-x: 0}.g-xxl-0,.gy-xxl-0{--bs-gutter-y: 0}.g-xxl-1,.gx-xxl-1{--bs-gutter-x: .25rem}.g-xxl-1,.gy-xxl-1{--bs-gutter-y: .25rem}.g-xxl-2,.gx-xxl-2{--bs-gutter-x: .5rem}.g-xxl-2,.gy-xxl-2{--bs-gutter-y: .5rem}.g-xxl-3,.gx-xxl-3{--bs-gutter-x: 1rem}.g-xxl-3,.gy-xxl-3{--bs-gutter-y: 1rem}.g-xxl-4,.gx-xxl-4{--bs-gutter-x: 1.5rem}.g-xxl-4,.gy-xxl-4{--bs-gutter-y: 1.5rem}.g-xxl-5,.gx-xxl-5{--bs-gutter-x: 3rem}.g-xxl-5,.gy-xxl-5{--bs-gutter-y: 3rem}}.table,table{--bs-table-bg: rgba(0,0,0,0);--bs-table-striped-color: #1d2d35;--bs-table-striped-bg: rgba(29,45,53,.05);--bs-table-active-color: #1d2d35;--bs-table-active-bg: rgba(29,45,53,.1);--bs-table-hover-color: #1d2d35;--bs-table-hover-bg: rgba(29,45,53,.075);width:100%;margin-bottom:1rem;color:#1d2d35;vertical-align:top;border-color:#e9ecef}.table>:not(caption)>*>*,table>:not(caption)>*>*{padding:.5rem .5rem;background-color:var(--bs-table-bg);border-bottom-width:1px;box-shadow:inset 0 0 0 9999px var(--bs-table-accent-bg)}.table>tbody,table>tbody{vertical-align:inherit}.table>thead,table>thead{vertical-align:bottom}.table>:not(:last-child)>:last-child>*,table>:not(:last-child)>:last-child>*{border-bottom-color:currentColor}.caption-top{caption-side:top}.table-sm>:not(caption)>*>*{padding:.25rem .25rem}.table-bordered>:not(caption)>*{border-width:1px 0}.table-bordered>:not(caption)>*>*{border-width:0 1px}.table-borderless>:not(caption)>*>*{border-bottom-width:0}.table-striped>tbody>tr:nth-of-type(odd){--bs-table-accent-bg: var(--bs-table-striped-bg);color:var(--bs-table-striped-color)}.table-active{--bs-table-accent-bg: var(--bs-table-active-bg);color:var(--bs-table-active-color)}.table-hover>tbody>tr:hover{--bs-table-accent-bg: var(--bs-table-hover-bg);color:var(--bs-table-hover-color)}.table-primary{--bs-table-bg: #dfd5e7;--bs-table-striped-bg: #d5cdde;--bs-table-striped-color: #1d2d35;--bs-table-active-bg: #ccc4d5;--bs-table-active-color: #1d2d35;--bs-table-hover-bg: #d0c8da;--bs-table-hover-color: #1d2d35;color:#1d2d35;border-color:#ccc4d5}.table-secondary{--bs-table-bg: #e2e3e5;--bs-table-striped-bg: #d8dadc;--bs-table-striped-color: #1d2d35;--bs-table-active-bg: #ced1d3;--bs-table-active-color: #1d2d35;--bs-table-hover-bg: #d3d5d8;--bs-table-hover-color: #1d2d35;color:#1d2d35;border-color:#ced1d3}.table-success{--bs-table-bg: #d1e7dd;--bs-table-striped-bg: #c8ded5;--bs-table-striped-color: #1d2d35;--bs-table-active-bg: #bfd4cc;--bs-table-active-color: #1d2d35;--bs-table-hover-bg: #c4d9d0;--bs-table-hover-color: #1d2d35;color:#1d2d35;border-color:#bfd4cc}.table-info{--bs-table-bg: #cff4fc;--bs-table-striped-bg: #c6eaf2;--bs-table-striped-color: #1d2d35;--bs-table-active-bg: #bde0e8;--bs-table-active-color: #1d2d35;--bs-table-hover-bg: #c2e5ed;--bs-table-hover-color: #1d2d35;color:#1d2d35;border-color:#bde0e8}.table-warning{--bs-table-bg: #fff9cc;--bs-table-striped-bg: #f4efc4;--bs-table-striped-color: #1d2d35;--bs-table-active-bg: #e8e5bd;--bs-table-active-color: #1d2d35;--bs-table-hover-bg: #eeeac1;--bs-table-hover-color: #1d2d35;color:#1d2d35;border-color:#e8e5bd}.table-danger{--bs-table-bg: #f8d7da;--bs-table-striped-bg: #edcfd2;--bs-table-striped-color: #1d2d35;--bs-table-active-bg: #e2c6ca;--bs-table-active-color: #1d2d35;--bs-table-hover-bg: #e8cace;--bs-table-hover-color: #1d2d35;color:#1d2d35;border-color:#e2c6ca}.table-light{--bs-table-bg: #f8f9fa;--bs-table-striped-bg: #edeff0;--bs-table-striped-color: #1d2d35;--bs-table-active-bg: #e2e5e6;--bs-table-active-color: #1d2d35;--bs-table-hover-bg: #e8eaeb;--bs-table-hover-color: #1d2d35;color:#1d2d35;border-color:#e2e5e6}.table-dark,body.dark table{--bs-table-bg: #212529;--bs-table-striped-bg: #2c3034;--bs-table-striped-color: #fff;--bs-table-active-bg: #373b3e;--bs-table-active-color: #fff;--bs-table-hover-bg: #323539;--bs-table-hover-color: #fff;color:#fff;border-color:#373b3e}.table-responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media (max-width: 575.98px){.table-responsive-sm{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width: 767.98px){.table-responsive-md{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width: 991.98px){.table-responsive-lg{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width: 1199.98px){.table-responsive-xl{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width: 1399.98px){.table-responsive-xxl{overflow-x:auto;-webkit-overflow-scrolling:touch}}.form-label{margin-bottom:.5rem}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem}.form-text{margin-top:.25rem;font-size:.875em;color:#6c757d}.form-control,.search-form .search-field,.comment-form input[type=text],.comment-form input[type=email],.comment-form input[type=url],.comment-form textarea{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#1d2d35;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;appearance:none;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion: reduce){.form-control,.search-form .search-field,.comment-form input[type=text],.comment-form input[type=email],.comment-form input[type=url],.comment-form textarea{transition:none}}.form-control[type=file],.search-form [type=file].search-field,.comment-form input[type=file][type=text],.comment-form input[type=file][type=email],.comment-form input[type=file][type=url],.comment-form textarea[type=file]{overflow:hidden}.form-control[type=file]:not(:disabled):not([readonly]),.search-form [type=file].search-field:not(:disabled):not([readonly]),.comment-form input[type=file][type=text]:not(:disabled):not([readonly]),.comment-form input[type=file][type=email]:not(:disabled):not([readonly]),.comment-form input[type=file][type=url]:not(:disabled):not([readonly]),.comment-form textarea[type=file]:not(:disabled):not([readonly]){cursor:pointer}.form-control:focus,.search-form .search-field:focus,.comment-form input[type=text]:focus,.comment-form input[type=email]:focus,.comment-form input[type=url]:focus,.comment-form textarea:focus{color:#1d2d35;background-color:#fff;border-color:#ae97c3;outline:0;box-shadow:0 0 0 .25rem rgba(93,47,134,.25)}.form-control::-webkit-date-and-time-value,.search-form .search-field::-webkit-date-and-time-value,.comment-form input[type=text]::-webkit-date-and-time-value,.comment-form input[type=email]::-webkit-date-and-time-value,.comment-form input[type=url]::-webkit-date-and-time-value,.comment-form textarea::-webkit-date-and-time-value{height:1.5em}.form-control::placeholder,.search-form .search-field::placeholder,.comment-form input[type=text]::placeholder,.comment-form input[type=email]::placeholder,.comment-form input[type=url]::placeholder,.comment-form textarea::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.search-form .search-field:disabled,.comment-form input[type=text]:disabled,.comment-form input[type=email]:disabled,.comment-form input[type=url]:disabled,.comment-form textarea:disabled,.form-control[readonly],.search-form [readonly].search-field,.comment-form input[readonly][type=text],.comment-form input[readonly][type=email],.comment-form input[readonly][type=url],.comment-form textarea[readonly]{background-color:#e9ecef;opacity:1}.form-control::file-selector-button,.search-form .search-field::file-selector-button,.comment-form input[type=text]::file-selector-button,.comment-form input[type=email]::file-selector-button,.comment-form input[type=url]::file-selector-button,.comment-form textarea::file-selector-button{padding:.375rem .75rem;margin:-.375rem -.75rem;margin-inline-end:.75rem;color:#1d2d35;background-color:#e9ecef;pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:1px;border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion: reduce){.form-control::file-selector-button,.search-form .search-field::file-selector-button,.comment-form input[type=text]::file-selector-button,.comment-form input[type=email]::file-selector-button,.comment-form input[type=url]::file-selector-button,.comment-form textarea::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::file-selector-button,.search-form .search-field:hover:not(:disabled):not([readonly])::file-selector-button,.comment-form input[type=text]:hover:not(:disabled):not([readonly])::file-selector-button,.comment-form input[type=email]:hover:not(:disabled):not([readonly])::file-selector-button,.comment-form input[type=url]:hover:not(:disabled):not([readonly])::file-selector-button,.comment-form textarea:hover:not(:disabled):not([readonly])::file-selector-button{background-color:#dde0e3}.form-control::-webkit-file-upload-button,.search-form .search-field::-webkit-file-upload-button,.comment-form input[type=text]::-webkit-file-upload-button,.comment-form input[type=email]::-webkit-file-upload-button,.comment-form input[type=url]::-webkit-file-upload-button,.comment-form textarea::-webkit-file-upload-button{padding:.375rem .75rem;margin:-.375rem -.75rem;margin-inline-end:.75rem;color:#1d2d35;background-color:#e9ecef;pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:1px;border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion: reduce){.form-control::-webkit-file-upload-button,.search-form .search-field::-webkit-file-upload-button,.comment-form input[type=text]::-webkit-file-upload-button,.comment-form input[type=email]::-webkit-file-upload-button,.comment-form input[type=url]::-webkit-file-upload-button,.comment-form textarea::-webkit-file-upload-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button,.search-form .search-field:hover:not(:disabled):not([readonly])::-webkit-file-upload-button,.comment-form input[type=text]:hover:not(:disabled):not([readonly])::-webkit-file-upload-button,.comment-form input[type=email]:hover:not(:disabled):not([readonly])::-webkit-file-upload-button,.comment-form input[type=url]:hover:not(:disabled):not([readonly])::-webkit-file-upload-button,.comment-form textarea:hover:not(:disabled):not([readonly])::-webkit-file-upload-button{background-color:#dde0e3}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;line-height:1.5;color:#1d2d35;background-color:rgba(0,0,0,0);border:solid rgba(0,0,0,0);border-width:1px 0}.form-control-plaintext.form-control-sm,.form-control-plaintext.form-control-lg{padding-right:0;padding-left:0}.form-control-sm{min-height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.form-control-sm::file-selector-button{padding:.25rem .5rem;margin:-.25rem -.5rem;margin-inline-end:.5rem}.form-control-sm::-webkit-file-upload-button{padding:.25rem .5rem;margin:-.25rem -.5rem;margin-inline-end:.5rem}.form-control-lg{min-height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;border-radius:.3rem}.form-control-lg::file-selector-button{padding:.5rem 1rem;margin:-.5rem -1rem;margin-inline-end:1rem}.form-control-lg::-webkit-file-upload-button{padding:.5rem 1rem;margin:-.5rem -1rem;margin-inline-end:1rem}textarea.form-control,.search-form textarea.search-field,.comment-form textarea{min-height:calc(1.5em + .75rem + 2px)}textarea.form-control-sm{min-height:calc(1.5em + .5rem + 2px)}textarea.form-control-lg{min-height:calc(1.5em + 1rem + 2px)}.form-control-color{max-width:3rem;height:auto;padding:.375rem}.form-control-color:not(:disabled):not([readonly]){cursor:pointer}.form-control-color::-moz-color-swatch{height:1.5em;border-radius:.25rem}.form-control-color::-webkit-color-swatch{height:1.5em;border-radius:.25rem}.form-select{display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#1d2d35;background-color:#fff;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:1px solid #ced4da;border-radius:.25rem;appearance:none}.form-select:focus{border-color:#ae97c3;outline:0;box-shadow:0 0 0 .25rem rgba(93,47,134,.25)}.form-select[multiple],.form-select[size]:not([size="1"]){padding-right:.75rem;background-image:none}.form-select:disabled{background-color:#e9ecef}.form-select:-moz-focusring{color:rgba(0,0,0,0);text-shadow:0 0 0 #1d2d35}.form-select-sm{padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.form-select-lg{padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.form-check{display:block;min-height:1.5rem;padding-left:1.5em;margin-bottom:.125rem}.form-check .form-check-input{float:left;margin-left:-1.5em}.form-check-input{width:1em;height:1em;margin-top:.25em;vertical-align:top;background-color:#fff;background-repeat:no-repeat;background-position:center;background-size:contain;border:1px solid rgba(0,0,0,.25);appearance:none;color-adjust:exact}.form-check-input[type=checkbox]{border-radius:.25em}.form-check-input[type=radio]{border-radius:50%}.form-check-input:active{filter:brightness(90%)}.form-check-input:focus{border-color:#ae97c3;outline:0;box-shadow:0 0 0 .25rem rgba(93,47,134,.25)}.form-check-input:checked{background-color:#5d2f86;border-color:#5d2f86}.form-check-input:checked[type=checkbox]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10l3 3l6-6'/%3e%3c/svg%3e")}.form-check-input:checked[type=radio]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e")}.form-check-input[type=checkbox]:indeterminate{background-color:#5d2f86;border-color:#5d2f86;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e")}.form-check-input:disabled{pointer-events:none;filter:none;opacity:.5}.form-check-input[disabled]~.form-check-label,.form-check-input:disabled~.form-check-label{opacity:.5}.form-switch{padding-left:2.5em}.form-switch .form-check-input{width:2em;margin-left:-2.5em;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280,0,0,.25%29'/%3e%3c/svg%3e");background-position:left center;border-radius:2em;transition:background-position .15s ease-in-out}@media (prefers-reduced-motion: reduce){.form-switch .form-check-input{transition:none}}.form-switch .form-check-input:focus{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23ae97c3'/%3e%3c/svg%3e")}.form-switch .form-check-input:checked{background-position:right center;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.form-check-inline{display:inline-block;margin-right:1rem}.btn-check{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.btn-check[disabled]+.btn,.search-form .btn-check[disabled]+.search-submit,.comment-form .btn-check[disabled]+input[type=submit],.btn-check:disabled+.btn,.search-form .btn-check:disabled+.search-submit,.comment-form .btn-check:disabled+input[type=submit]{pointer-events:none;filter:none;opacity:.65}.form-range{width:100%;height:1.5rem;padding:0;background-color:rgba(0,0,0,0);appearance:none}.form-range:focus{outline:0}.form-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(93,47,134,.25)}.form-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(93,47,134,.25)}.form-range::-moz-focus-outer{border:0}.form-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#5d2f86;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion: reduce){.form-range::-webkit-slider-thumb{transition:none}}.form-range::-webkit-slider-thumb:active{background-color:#cec1db}.form-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:rgba(0,0,0,0);cursor:pointer;background-color:#dee2e6;border-color:rgba(0,0,0,0);border-radius:1rem}.form-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#5d2f86;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion: reduce){.form-range::-moz-range-thumb{transition:none}}.form-range::-moz-range-thumb:active{background-color:#cec1db}.form-range::-moz-range-track{width:100%;height:.5rem;color:rgba(0,0,0,0);cursor:pointer;background-color:#dee2e6;border-color:rgba(0,0,0,0);border-radius:1rem}.form-range:disabled{pointer-events:none}.form-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.form-range:disabled::-moz-range-thumb{background-color:#adb5bd}.form-floating{position:relative}.form-floating>.form-control,.search-form .form-floating>.search-field,.comment-form .form-floating>input[type=text],.comment-form .form-floating>input[type=email],.comment-form .form-floating>input[type=url],.comment-form .form-floating>textarea,.form-floating>.form-select{height:calc(3.5rem + 2px);padding:1rem .75rem}.form-floating>label{position:absolute;top:0;left:0;height:100%;padding:1rem .75rem;pointer-events:none;border:1px solid rgba(0,0,0,0);transform-origin:0 0;transition:opacity .1s ease-in-out,transform .1s ease-in-out}@media (prefers-reduced-motion: reduce){.form-floating>label{transition:none}}.form-floating>.form-control::placeholder,.search-form .form-floating>.search-field::placeholder,.comment-form .form-floating>input[type=text]::placeholder,.comment-form .form-floating>input[type=email]::placeholder,.comment-form .form-floating>input[type=url]::placeholder,.comment-form .form-floating>textarea::placeholder{color:rgba(0,0,0,0)}.form-floating>.form-control:focus,.search-form .form-floating>.search-field:focus,.comment-form .form-floating>input[type=text]:focus,.comment-form .form-floating>input[type=email]:focus,.comment-form .form-floating>input[type=url]:focus,.comment-form .form-floating>textarea:focus,.form-floating>.form-control:not(:placeholder-shown),.search-form .form-floating>.search-field:not(:placeholder-shown),.comment-form .form-floating>input[type=text]:not(:placeholder-shown),.comment-form .form-floating>input[type=email]:not(:placeholder-shown),.comment-form .form-floating>input[type=url]:not(:placeholder-shown),.comment-form .form-floating>textarea:not(:placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:-webkit-autofill,.search-form .form-floating>.search-field:-webkit-autofill,.comment-form .form-floating>input[type=text]:-webkit-autofill,.comment-form .form-floating>input[type=email]:-webkit-autofill,.comment-form .form-floating>input[type=url]:-webkit-autofill,.comment-form .form-floating>textarea:-webkit-autofill{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-select{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:focus~label,.search-form .form-floating>.search-field:focus~label,.comment-form .form-floating>input[type=text]:focus~label,.comment-form .form-floating>input[type=email]:focus~label,.comment-form .form-floating>input[type=url]:focus~label,.comment-form .form-floating>textarea:focus~label,.form-floating>.form-control:not(:placeholder-shown)~label,.search-form .form-floating>.search-field:not(:placeholder-shown)~label,.comment-form .form-floating>input[type=text]:not(:placeholder-shown)~label,.comment-form .form-floating>input[type=email]:not(:placeholder-shown)~label,.comment-form .form-floating>input[type=url]:not(:placeholder-shown)~label,.comment-form .form-floating>textarea:not(:placeholder-shown)~label,.form-floating>.form-select~label{opacity:.65;transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>.form-control:-webkit-autofill~label,.search-form .form-floating>.search-field:-webkit-autofill~label,.comment-form .form-floating>input[type=text]:-webkit-autofill~label,.comment-form .form-floating>input[type=email]:-webkit-autofill~label,.comment-form .form-floating>input[type=url]:-webkit-autofill~label,.comment-form .form-floating>textarea:-webkit-autofill~label{opacity:.65;transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.input-group{position:relative;display:flex;flex-wrap:wrap;align-items:stretch;width:100%}.input-group>.form-control,.search-form .input-group>.search-field,.comment-form .input-group>input[type=text],.comment-form .input-group>input[type=email],.comment-form .input-group>input[type=url],.comment-form .input-group>textarea,.input-group>.form-select{position:relative;flex:1 1 auto;width:1%;min-width:0}.input-group>.form-control:focus,.search-form .input-group>.search-field:focus,.comment-form .input-group>input[type=text]:focus,.comment-form .input-group>input[type=email]:focus,.comment-form .input-group>input[type=url]:focus,.comment-form .input-group>textarea:focus,.input-group>.form-select:focus{z-index:3}.input-group .btn,.input-group .search-form .search-submit,.search-form .input-group .search-submit,.input-group .comment-form input[type=submit],.comment-form .input-group input[type=submit]{position:relative;z-index:2}.input-group .btn:focus,.input-group .search-form .search-submit:focus,.search-form .input-group .search-submit:focus,.input-group .comment-form input[type=submit]:focus,.comment-form .input-group input[type=submit]:focus{z-index:3}.input-group-text{display:flex;align-items:center;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#1d2d35;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-lg>.form-control,.search-form .input-group-lg>.search-field,.comment-form .input-group-lg>input[type=text],.comment-form .input-group-lg>input[type=email],.comment-form .input-group-lg>input[type=url],.comment-form .input-group-lg>textarea,.input-group-lg>.form-select,.input-group-lg>.input-group-text,.input-group-lg>.btn,.search-form .input-group-lg>.search-submit,.comment-form .input-group-lg>input[type=submit]{padding:.5rem 1rem;font-size:1.25rem;border-radius:.3rem}.input-group-sm>.form-control,.search-form .input-group-sm>.search-field,.comment-form .input-group-sm>input[type=text],.comment-form .input-group-sm>input[type=email],.comment-form .input-group-sm>input[type=url],.comment-form .input-group-sm>textarea,.input-group-sm>.form-select,.input-group-sm>.input-group-text,.input-group-sm>.btn,.search-form .input-group-sm>.search-submit,.comment-form .input-group-sm>input[type=submit]{padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.input-group-lg>.form-select,.input-group-sm>.form-select{padding-right:3rem}.input-group:not(.has-validation)>:not(:last-child):not(.dropdown-toggle):not(.dropdown-menu),.input-group:not(.has-validation)>.dropdown-toggle:nth-last-child(n+3){border-top-right-radius:0;border-bottom-right-radius:0}.input-group.has-validation>:nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu),.input-group.has-validation>.dropdown-toggle:nth-last-child(n+4){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>:not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback){margin-left:-1px;border-top-left-radius:0;border-bottom-left-radius:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#198754}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:rgba(25,135,84,.9);border-radius:.25rem}.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip,.is-valid~.valid-feedback,.is-valid~.valid-tooltip{display:block}.was-validated .form-control:valid,.was-validated .search-form .search-field:valid,.search-form .was-validated .search-field:valid,.was-validated .comment-form input[type=text]:valid,.comment-form .was-validated input[type=text]:valid,.was-validated .comment-form input[type=email]:valid,.comment-form .was-validated input[type=email]:valid,.was-validated .comment-form input[type=url]:valid,.comment-form .was-validated input[type=url]:valid,.was-validated .comment-form textarea:valid,.comment-form .was-validated textarea:valid,.form-control.is-valid,.search-form .is-valid.search-field,.comment-form input.is-valid[type=text],.comment-form input.is-valid[type=email],.comment-form input.is-valid[type=url],.comment-form textarea.is-valid{border-color:#198754;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' 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;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.was-validated .form-control:valid:focus,.was-validated .search-form .search-field:valid:focus,.search-form .was-validated .search-field:valid:focus,.was-validated .comment-form input[type=text]:valid:focus,.comment-form .was-validated input[type=text]:valid:focus,.was-validated .comment-form input[type=email]:valid:focus,.comment-form .was-validated input[type=email]:valid:focus,.was-validated .comment-form input[type=url]:valid:focus,.comment-form .was-validated input[type=url]:valid:focus,.was-validated .comment-form textarea:valid:focus,.comment-form .was-validated textarea:valid:focus,.form-control.is-valid:focus,.search-form .is-valid.search-field:focus,.comment-form input.is-valid[type=text]:focus,.comment-form input.is-valid[type=email]:focus,.comment-form input.is-valid[type=url]:focus,.comment-form textarea.is-valid:focus{border-color:#198754;box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.was-validated textarea.form-control:valid,.was-validated .search-form textarea.search-field:valid,.search-form .was-validated textarea.search-field:valid,.was-validated .comment-form textarea:valid,.comment-form .was-validated textarea:valid,textarea.form-control.is-valid,.search-form textarea.is-valid.search-field,.comment-form textarea.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.was-validated .form-select:valid,.form-select.is-valid{border-color:#198754;padding-right:4.125rem;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' 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-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.was-validated .form-select:valid:focus,.form-select.is-valid:focus{border-color:#198754;box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.was-validated .form-check-input:valid,.form-check-input.is-valid{border-color:#198754}.was-validated .form-check-input:valid:checked,.form-check-input.is-valid:checked{background-color:#198754}.was-validated .form-check-input:valid:focus,.form-check-input.is-valid:focus{box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.was-validated .form-check-input:valid~.form-check-label,.form-check-input.is-valid~.form-check-label{color:#198754}.form-check-inline .form-check-input~.valid-feedback{margin-left:.5em}.was-validated .input-group .form-control:valid,.was-validated .input-group .search-form .search-field:valid,.search-form .was-validated .input-group .search-field:valid,.was-validated .input-group .comment-form input[type=text]:valid,.comment-form .was-validated .input-group input[type=text]:valid,.was-validated .input-group .comment-form input[type=email]:valid,.comment-form .was-validated .input-group input[type=email]:valid,.was-validated .input-group .comment-form input[type=url]:valid,.comment-form .was-validated .input-group input[type=url]:valid,.was-validated .input-group .comment-form textarea:valid,.comment-form .was-validated .input-group textarea:valid,.input-group .form-control.is-valid,.input-group .search-form .is-valid.search-field,.search-form .input-group .is-valid.search-field,.input-group .comment-form input.is-valid[type=text],.comment-form .input-group input.is-valid[type=text],.input-group .comment-form input.is-valid[type=email],.comment-form .input-group input.is-valid[type=email],.input-group .comment-form input.is-valid[type=url],.comment-form .input-group input.is-valid[type=url],.input-group .comment-form textarea.is-valid,.comment-form .input-group textarea.is-valid,.was-validated .input-group .form-select:valid,.input-group .form-select.is-valid{z-index:3}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.25rem}.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip,.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip{display:block}.was-validated .form-control:invalid,.was-validated .search-form .search-field:invalid,.search-form .was-validated .search-field:invalid,.was-validated .comment-form input[type=text]:invalid,.comment-form .was-validated input[type=text]:invalid,.was-validated .comment-form input[type=email]:invalid,.comment-form .was-validated input[type=email]:invalid,.was-validated .comment-form input[type=url]:invalid,.comment-form .was-validated input[type=url]:invalid,.was-validated .comment-form textarea:invalid,.comment-form .was-validated textarea:invalid,.form-control.is-invalid,.search-form .is-invalid.search-field,.comment-form input.is-invalid[type=text],.comment-form input.is-invalid[type=email],.comment-form input.is-invalid[type=url],.comment-form textarea.is-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' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%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;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.was-validated .form-control:invalid:focus,.was-validated .search-form .search-field:invalid:focus,.search-form .was-validated .search-field:invalid:focus,.was-validated .comment-form input[type=text]:invalid:focus,.comment-form .was-validated input[type=text]:invalid:focus,.was-validated .comment-form input[type=email]:invalid:focus,.comment-form .was-validated input[type=email]:invalid:focus,.was-validated .comment-form input[type=url]:invalid:focus,.comment-form .was-validated input[type=url]:invalid:focus,.was-validated .comment-form textarea:invalid:focus,.comment-form .was-validated textarea:invalid:focus,.form-control.is-invalid:focus,.search-form .is-invalid.search-field:focus,.comment-form input.is-invalid[type=text]:focus,.comment-form input.is-invalid[type=email]:focus,.comment-form input.is-invalid[type=url]:focus,.comment-form textarea.is-invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.was-validated textarea.form-control:invalid,.was-validated .search-form textarea.search-field:invalid,.search-form .was-validated textarea.search-field:invalid,.was-validated .comment-form textarea:invalid,.comment-form .was-validated textarea:invalid,textarea.form-control.is-invalid,.search-form textarea.is-invalid.search-field,.comment-form textarea.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.was-validated .form-select:invalid,.form-select.is-invalid{border-color:#dc3545;padding-right:4.125rem;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%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-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.was-validated .form-select:invalid:focus,.form-select.is-invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.was-validated .form-check-input:invalid,.form-check-input.is-invalid{border-color:#dc3545}.was-validated .form-check-input:invalid:checked,.form-check-input.is-invalid:checked{background-color:#dc3545}.was-validated .form-check-input:invalid:focus,.form-check-input.is-invalid:focus{box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.was-validated .form-check-input:invalid~.form-check-label,.form-check-input.is-invalid~.form-check-label{color:#dc3545}.form-check-inline .form-check-input~.invalid-feedback{margin-left:.5em}.was-validated .input-group .form-control:invalid,.was-validated .input-group .search-form .search-field:invalid,.search-form .was-validated .input-group .search-field:invalid,.was-validated .input-group .comment-form input[type=text]:invalid,.comment-form .was-validated .input-group input[type=text]:invalid,.was-validated .input-group .comment-form input[type=email]:invalid,.comment-form .was-validated .input-group input[type=email]:invalid,.was-validated .input-group .comment-form input[type=url]:invalid,.comment-form .was-validated .input-group input[type=url]:invalid,.was-validated .input-group .comment-form textarea:invalid,.comment-form .was-validated .input-group textarea:invalid,.input-group .form-control.is-invalid,.input-group .search-form .is-invalid.search-field,.search-form .input-group .is-invalid.search-field,.input-group .comment-form input.is-invalid[type=text],.comment-form .input-group input.is-invalid[type=text],.input-group .comment-form input.is-invalid[type=email],.comment-form .input-group input.is-invalid[type=email],.input-group .comment-form input.is-invalid[type=url],.comment-form .input-group input.is-invalid[type=url],.input-group .comment-form textarea.is-invalid,.comment-form .input-group textarea.is-invalid,.was-validated .input-group .form-select:invalid,.input-group .form-select.is-invalid{z-index:3}.btn,.search-form .search-submit,.comment-form input[type=submit]{display:inline-block;font-weight:400;line-height:1.5;color:#1d2d35;text-align:center;vertical-align:middle;cursor:pointer;user-select:none;background-color:rgba(0,0,0,0);border:1px solid rgba(0,0,0,0);padding:.375rem .75rem;font-size:1rem;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion: reduce){.btn,.search-form .search-submit,.comment-form input[type=submit]{transition:none}}.btn:hover,.search-form .search-submit:hover,.comment-form input[type=submit]:hover{color:#1d2d35}.btn-check:focus+.btn,.search-form .btn-check:focus+.search-submit,.comment-form .btn-check:focus+input[type=submit],.btn:focus,.search-form .search-submit:focus,.comment-form input[type=submit]:focus{outline:0;box-shadow:0 0 0 .25rem rgba(93,47,134,.25)}.btn:disabled,.search-form .search-submit:disabled,.comment-form input[type=submit]:disabled,.btn.disabled,.search-form .disabled.search-submit,.comment-form input.disabled[type=submit],fieldset:disabled .btn,fieldset:disabled .search-form .search-submit,.search-form fieldset:disabled .search-submit,fieldset:disabled .comment-form input[type=submit],.comment-form fieldset:disabled input[type=submit]{pointer-events:none;opacity:.65}.btn-primary{color:#fff;background-color:#5d2f86;border-color:#5d2f86}.btn-primary:hover{color:#fff;background-color:#4f2872;border-color:#4a266b}.btn-check:focus+.btn-primary,.btn-primary:focus{color:#fff;background-color:#4f2872;border-color:#4a266b;box-shadow:0 0 0 .25rem rgba(117,78,152,.5)}.btn-check:checked+.btn-primary,.btn-check:active+.btn-primary,.btn-primary:active,.btn-primary.active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#4a266b;border-color:#462365}.btn-check:checked+.btn-primary:focus,.btn-check:active+.btn-primary:focus,.btn-primary:active:focus,.btn-primary.active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(117,78,152,.5)}.btn-primary:disabled,.btn-primary.disabled{color:#fff;background-color:#5d2f86;border-color:#5d2f86}.btn-secondary,.search-form .search-submit,.comment-form input[type=submit]{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover,.search-form .search-submit:hover,.comment-form input[type=submit]:hover{color:#fff;background-color:#5c636a;border-color:#565e64}.btn-check:focus+.btn-secondary,.search-form .btn-check:focus+.search-submit,.comment-form .btn-check:focus+input[type=submit],.btn-secondary:focus,.search-form .search-submit:focus,.comment-form input[type=submit]:focus{color:#fff;background-color:#5c636a;border-color:#565e64;box-shadow:0 0 0 .25rem rgba(130,138,145,.5)}.btn-check:checked+.btn-secondary,.search-form .btn-check:checked+.search-submit,.comment-form .btn-check:checked+input[type=submit],.btn-check:active+.btn-secondary,.search-form .btn-check:active+.search-submit,.comment-form .btn-check:active+input[type=submit],.btn-secondary:active,.search-form .search-submit:active,.comment-form input[type=submit]:active,.btn-secondary.active,.search-form .active.search-submit,.comment-form input.active[type=submit],.show>.btn-secondary.dropdown-toggle,.search-form .show>.dropdown-toggle.search-submit,.comment-form .show>input.dropdown-toggle[type=submit]{color:#fff;background-color:#565e64;border-color:#51585e}.btn-check:checked+.btn-secondary:focus,.search-form .btn-check:checked+.search-submit:focus,.comment-form .btn-check:checked+input[type=submit]:focus,.btn-check:active+.btn-secondary:focus,.search-form .btn-check:active+.search-submit:focus,.comment-form .btn-check:active+input[type=submit]:focus,.btn-secondary:active:focus,.search-form .search-submit:active:focus,.comment-form input[type=submit]:active:focus,.btn-secondary.active:focus,.search-form .active.search-submit:focus,.comment-form input.active[type=submit]:focus,.show>.btn-secondary.dropdown-toggle:focus,.search-form .show>.dropdown-toggle.search-submit:focus,.comment-form .show>input.dropdown-toggle[type=submit]:focus{box-shadow:0 0 0 .25rem rgba(130,138,145,.5)}.btn-secondary:disabled,.search-form .search-submit:disabled,.comment-form input[type=submit]:disabled,.btn-secondary.disabled,.search-form .disabled.search-submit,.comment-form input.disabled[type=submit]{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-success{color:#fff;background-color:#198754;border-color:#198754}.btn-success:hover{color:#fff;background-color:#157347;border-color:#146c43}.btn-check:focus+.btn-success,.btn-success:focus{color:#fff;background-color:#157347;border-color:#146c43;box-shadow:0 0 0 .25rem rgba(60,153,110,.5)}.btn-check:checked+.btn-success,.btn-check:active+.btn-success,.btn-success:active,.btn-success.active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#146c43;border-color:#13653f}.btn-check:checked+.btn-success:focus,.btn-check:active+.btn-success:focus,.btn-success:active:focus,.btn-success.active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(60,153,110,.5)}.btn-success:disabled,.btn-success.disabled{color:#fff;background-color:#198754;border-color:#198754}.btn-info{color:#1d2d35;background-color:#0dcaf0;border-color:#0dcaf0}.btn-info:hover{color:#1d2d35;background-color:#31d2f2;border-color:#25cff2}.btn-check:focus+.btn-info,.btn-info:focus{color:#1d2d35;background-color:#31d2f2;border-color:#25cff2;box-shadow:0 0 0 .25rem rgba(15,178,212,.5)}.btn-check:checked+.btn-info,.btn-check:active+.btn-info,.btn-info:active,.btn-info.active,.show>.btn-info.dropdown-toggle{color:#1d2d35;background-color:#3dd5f3;border-color:#25cff2}.btn-check:checked+.btn-info:focus,.btn-check:active+.btn-info:focus,.btn-info:active:focus,.btn-info.active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(15,178,212,.5)}.btn-info:disabled,.btn-info.disabled{color:#1d2d35;background-color:#0dcaf0;border-color:#0dcaf0}.btn-warning{color:#1d2d35;background-color:#ffe000;border-color:#ffe000}.btn-warning:hover{color:#1d2d35;background-color:#ffe526;border-color:#ffe319}.btn-check:focus+.btn-warning,.btn-warning:focus{color:#1d2d35;background-color:#ffe526;border-color:#ffe319;box-shadow:0 0 0 .25rem rgba(221,197,8,.5)}.btn-check:checked+.btn-warning,.btn-check:active+.btn-warning,.btn-warning:active,.btn-warning.active,.show>.btn-warning.dropdown-toggle{color:#1d2d35;background-color:#ffe633;border-color:#ffe319}.btn-check:checked+.btn-warning:focus,.btn-check:active+.btn-warning:focus,.btn-warning:active:focus,.btn-warning.active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(221,197,8,.5)}.btn-warning:disabled,.btn-warning.disabled{color:#1d2d35;background-color:#ffe000;border-color:#ffe000}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#bb2d3b;border-color:#b02a37}.btn-check:focus+.btn-danger,.btn-danger:focus{color:#fff;background-color:#bb2d3b;border-color:#b02a37;box-shadow:0 0 0 .25rem rgba(225,83,97,.5)}.btn-check:checked+.btn-danger,.btn-check:active+.btn-danger,.btn-danger:active,.btn-danger.active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#b02a37;border-color:#a52834}.btn-check:checked+.btn-danger:focus,.btn-check:active+.btn-danger:focus,.btn-danger:active:focus,.btn-danger.active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(225,83,97,.5)}.btn-danger:disabled,.btn-danger.disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-light{color:#1d2d35;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#1d2d35;background-color:#f9fafb;border-color:#f9fafb}.btn-check:focus+.btn-light,.btn-light:focus{color:#1d2d35;background-color:#f9fafb;border-color:#f9fafb;box-shadow:0 0 0 .25rem rgba(215,218,220,.5)}.btn-check:checked+.btn-light,.btn-check:active+.btn-light,.btn-light:active,.btn-light.active,.show>.btn-light.dropdown-toggle{color:#1d2d35;background-color:#f9fafb;border-color:#f9fafb}.btn-check:checked+.btn-light:focus,.btn-check:active+.btn-light:focus,.btn-light:active:focus,.btn-light.active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(215,218,220,.5)}.btn-light:disabled,.btn-light.disabled{color:#1d2d35;background-color:#f8f9fa;border-color:#f8f9fa}.btn-dark{color:#fff;background-color:#212529;border-color:#212529}.btn-dark:hover{color:#fff;background-color:#1c1f23;border-color:#1a1e21}.btn-check:focus+.btn-dark,.btn-dark:focus{color:#fff;background-color:#1c1f23;border-color:#1a1e21;box-shadow:0 0 0 .25rem rgba(66,70,73,.5)}.btn-check:checked+.btn-dark,.btn-check:active+.btn-dark,.btn-dark:active,.btn-dark.active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1a1e21;border-color:#191c1f}.btn-check:checked+.btn-dark:focus,.btn-check:active+.btn-dark:focus,.btn-dark:active:focus,.btn-dark.active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(66,70,73,.5)}.btn-dark:disabled,.btn-dark.disabled{color:#fff;background-color:#212529;border-color:#212529}.btn-outline-primary{color:#5d2f86;border-color:#5d2f86}.btn-outline-primary:hover{color:#fff;background-color:#5d2f86;border-color:#5d2f86}.btn-check:focus+.btn-outline-primary,.btn-outline-primary:focus{box-shadow:0 0 0 .25rem rgba(93,47,134,.5)}.btn-check:checked+.btn-outline-primary,.btn-check:active+.btn-outline-primary,.btn-outline-primary:active,.btn-outline-primary.active,.btn-outline-primary.dropdown-toggle.show{color:#fff;background-color:#5d2f86;border-color:#5d2f86}.btn-check:checked+.btn-outline-primary:focus,.btn-check:active+.btn-outline-primary:focus,.btn-outline-primary:active:focus,.btn-outline-primary.active:focus,.btn-outline-primary.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(93,47,134,.5)}.btn-outline-primary:disabled,.btn-outline-primary.disabled{color:#5d2f86;background-color:rgba(0,0,0,0)}.btn-outline-secondary{color:#6c757d;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-check:focus+.btn-outline-secondary,.btn-outline-secondary:focus{box-shadow:0 0 0 .25rem rgba(108,117,125,.5)}.btn-check:checked+.btn-outline-secondary,.btn-check:active+.btn-outline-secondary,.btn-outline-secondary:active,.btn-outline-secondary.active,.btn-outline-secondary.dropdown-toggle.show{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-check:checked+.btn-outline-secondary:focus,.btn-check:active+.btn-outline-secondary:focus,.btn-outline-secondary:active:focus,.btn-outline-secondary.active:focus,.btn-outline-secondary.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(108,117,125,.5)}.btn-outline-secondary:disabled,.btn-outline-secondary.disabled{color:#6c757d;background-color:rgba(0,0,0,0)}.btn-outline-success{color:#198754;border-color:#198754}.btn-outline-success:hover{color:#fff;background-color:#198754;border-color:#198754}.btn-check:focus+.btn-outline-success,.btn-outline-success:focus{box-shadow:0 0 0 .25rem rgba(25,135,84,.5)}.btn-check:checked+.btn-outline-success,.btn-check:active+.btn-outline-success,.btn-outline-success:active,.btn-outline-success.active,.btn-outline-success.dropdown-toggle.show{color:#fff;background-color:#198754;border-color:#198754}.btn-check:checked+.btn-outline-success:focus,.btn-check:active+.btn-outline-success:focus,.btn-outline-success:active:focus,.btn-outline-success.active:focus,.btn-outline-success.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(25,135,84,.5)}.btn-outline-success:disabled,.btn-outline-success.disabled{color:#198754;background-color:rgba(0,0,0,0)}.btn-outline-info{color:#0dcaf0;border-color:#0dcaf0}.btn-outline-info:hover{color:#1d2d35;background-color:#0dcaf0;border-color:#0dcaf0}.btn-check:focus+.btn-outline-info,.btn-outline-info:focus{box-shadow:0 0 0 .25rem rgba(13,202,240,.5)}.btn-check:checked+.btn-outline-info,.btn-check:active+.btn-outline-info,.btn-outline-info:active,.btn-outline-info.active,.btn-outline-info.dropdown-toggle.show{color:#1d2d35;background-color:#0dcaf0;border-color:#0dcaf0}.btn-check:checked+.btn-outline-info:focus,.btn-check:active+.btn-outline-info:focus,.btn-outline-info:active:focus,.btn-outline-info.active:focus,.btn-outline-info.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(13,202,240,.5)}.btn-outline-info:disabled,.btn-outline-info.disabled{color:#0dcaf0;background-color:rgba(0,0,0,0)}.btn-outline-warning{color:#ffe000;border-color:#ffe000}.btn-outline-warning:hover{color:#1d2d35;background-color:#ffe000;border-color:#ffe000}.btn-check:focus+.btn-outline-warning,.btn-outline-warning:focus{box-shadow:0 0 0 .25rem rgba(255,224,0,.5)}.btn-check:checked+.btn-outline-warning,.btn-check:active+.btn-outline-warning,.btn-outline-warning:active,.btn-outline-warning.active,.btn-outline-warning.dropdown-toggle.show{color:#1d2d35;background-color:#ffe000;border-color:#ffe000}.btn-check:checked+.btn-outline-warning:focus,.btn-check:active+.btn-outline-warning:focus,.btn-outline-warning:active:focus,.btn-outline-warning.active:focus,.btn-outline-warning.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(255,224,0,.5)}.btn-outline-warning:disabled,.btn-outline-warning.disabled{color:#ffe000;background-color:rgba(0,0,0,0)}.btn-outline-danger{color:#dc3545;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-check:focus+.btn-outline-danger,.btn-outline-danger:focus{box-shadow:0 0 0 .25rem rgba(220,53,69,.5)}.btn-check:checked+.btn-outline-danger,.btn-check:active+.btn-outline-danger,.btn-outline-danger:active,.btn-outline-danger.active,.btn-outline-danger.dropdown-toggle.show{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-check:checked+.btn-outline-danger:focus,.btn-check:active+.btn-outline-danger:focus,.btn-outline-danger:active:focus,.btn-outline-danger.active:focus,.btn-outline-danger.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(220,53,69,.5)}.btn-outline-danger:disabled,.btn-outline-danger.disabled{color:#dc3545;background-color:rgba(0,0,0,0)}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:hover{color:#1d2d35;background-color:#f8f9fa;border-color:#f8f9fa}.btn-check:focus+.btn-outline-light,.btn-outline-light:focus{box-shadow:0 0 0 .25rem rgba(248,249,250,.5)}.btn-check:checked+.btn-outline-light,.btn-check:active+.btn-outline-light,.btn-outline-light:active,.btn-outline-light.active,.btn-outline-light.dropdown-toggle.show{color:#1d2d35;background-color:#f8f9fa;border-color:#f8f9fa}.btn-check:checked+.btn-outline-light:focus,.btn-check:active+.btn-outline-light:focus,.btn-outline-light:active:focus,.btn-outline-light.active:focus,.btn-outline-light.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(248,249,250,.5)}.btn-outline-light:disabled,.btn-outline-light.disabled{color:#f8f9fa;background-color:rgba(0,0,0,0)}.btn-outline-dark{color:#212529;border-color:#212529}.btn-outline-dark:hover{color:#fff;background-color:#212529;border-color:#212529}.btn-check:focus+.btn-outline-dark,.btn-outline-dark:focus{box-shadow:0 0 0 .25rem rgba(33,37,41,.5)}.btn-check:checked+.btn-outline-dark,.btn-check:active+.btn-outline-dark,.btn-outline-dark:active,.btn-outline-dark.active,.btn-outline-dark.dropdown-toggle.show{color:#fff;background-color:#212529;border-color:#212529}.btn-check:checked+.btn-outline-dark:focus,.btn-check:active+.btn-outline-dark:focus,.btn-outline-dark:active:focus,.btn-outline-dark.active:focus,.btn-outline-dark.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(33,37,41,.5)}.btn-outline-dark:disabled,.btn-outline-dark.disabled{color:#212529;background-color:rgba(0,0,0,0)}.btn-link{font-weight:400;color:#5d2f86;text-decoration:none}.btn-link:hover{color:#4a266b}.btn-link:disabled,.btn-link.disabled{color:#6c757d}.btn-lg,.btn-group-lg>.btn,.search-form .btn-group-lg>.search-submit,.comment-form .btn-group-lg>input[type=submit]{padding:.5rem 1rem;font-size:1.25rem;border-radius:.3rem}.btn-sm,.btn-group-sm>.btn,.search-form .btn-group-sm>.search-submit,.comment-form .btn-group-sm>input[type=submit]{padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion: reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion: reduce){.collapsing{transition:none}}.dropup,.dropend,.dropdown,.dropstart{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid rgba(0,0,0,0);border-bottom:0;border-left:.3em solid rgba(0,0,0,0)}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;z-index:1000;display:none;min-width:10rem;padding:.5rem 0;margin:0;font-size:1rem;color:#1d2d35;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(29,45,53,.15);border-radius:.25rem}.dropdown-menu[data-bs-popper]{left:0;margin-top:.125rem}.dropdown-menu-start{--bs-position: start}.dropdown-menu-start[data-bs-popper]{right:auto /* rtl:ignore */;left:0 /* rtl:ignore */}.dropdown-menu-end{--bs-position: end}.dropdown-menu-end[data-bs-popper]{right:0 /* rtl:ignore */;left:auto /* rtl:ignore */}@media (min-width: 576px){.dropdown-menu-sm-start{--bs-position: start}.dropdown-menu-sm-start[data-bs-popper]{right:auto /* rtl:ignore */;left:0 /* rtl:ignore */}.dropdown-menu-sm-end{--bs-position: end}.dropdown-menu-sm-end[data-bs-popper]{right:0 /* rtl:ignore */;left:auto /* rtl:ignore */}}@media (min-width: 768px){.dropdown-menu-md-start{--bs-position: start}.dropdown-menu-md-start[data-bs-popper]{right:auto /* rtl:ignore */;left:0 /* rtl:ignore */}.dropdown-menu-md-end{--bs-position: end}.dropdown-menu-md-end[data-bs-popper]{right:0 /* rtl:ignore */;left:auto /* rtl:ignore */}}@media (min-width: 992px){.dropdown-menu-lg-start{--bs-position: start}.dropdown-menu-lg-start[data-bs-popper]{right:auto /* rtl:ignore */;left:0 /* rtl:ignore */}.dropdown-menu-lg-end{--bs-position: end}.dropdown-menu-lg-end[data-bs-popper]{right:0 /* rtl:ignore */;left:auto /* rtl:ignore */}}@media (min-width: 1200px){.dropdown-menu-xl-start{--bs-position: start}.dropdown-menu-xl-start[data-bs-popper]{right:auto /* rtl:ignore */;left:0 /* rtl:ignore */}.dropdown-menu-xl-end{--bs-position: end}.dropdown-menu-xl-end[data-bs-popper]{right:0 /* rtl:ignore */;left:auto /* rtl:ignore */}}@media (min-width: 1400px){.dropdown-menu-xxl-start{--bs-position: start}.dropdown-menu-xxl-start[data-bs-popper]{right:auto /* rtl:ignore */;left:0 /* rtl:ignore */}.dropdown-menu-xxl-end{--bs-position: end}.dropdown-menu-xxl-end[data-bs-popper]{right:0 /* rtl:ignore */;left:auto /* rtl:ignore */}}.dropup .dropdown-menu[data-bs-popper]{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid rgba(0,0,0,0);border-bottom:.3em solid;border-left:.3em solid rgba(0,0,0,0)}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-menu{top:0;right:auto;left:100%}.dropend .dropdown-menu[data-bs-popper]{margin-top:0;margin-left:.125rem}.dropend .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid rgba(0,0,0,0);border-right:0;border-bottom:.3em solid rgba(0,0,0,0);border-left:.3em solid}.dropend .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-toggle::after{vertical-align:0}.dropstart .dropdown-menu{top:0;right:100%;left:auto}.dropstart .dropdown-menu[data-bs-popper]{margin-top:0;margin-right:.125rem}.dropstart .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropstart .dropdown-toggle::after{display:none}.dropstart .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid rgba(0,0,0,0);border-right:.3em solid;border-bottom:.3em solid rgba(0,0,0,0)}.dropstart .dropdown-toggle:empty::after{margin-left:0}.dropstart .dropdown-toggle::before{vertical-align:0}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid rgba(29,45,53,.15)}.dropdown-item{display:block;width:100%;padding:.25rem 1rem;clear:both;font-weight:400;color:#212529;text-align:inherit;white-space:nowrap;background-color:rgba(0,0,0,0);border:0}.dropdown-item:hover,.dropdown-item:focus{color:#1e2125;background-color:#e9ecef}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#5d2f86}.dropdown-item.disabled,.dropdown-item:disabled{color:#adb5bd;pointer-events:none;background-color:rgba(0,0,0,0)}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1rem;color:#212529}.dropdown-menu-dark{color:#dee2e6;background-color:#343a40;border-color:rgba(29,45,53,.15)}.dropdown-menu-dark .dropdown-item{color:#dee2e6}.dropdown-menu-dark .dropdown-item:hover,.dropdown-menu-dark .dropdown-item:focus{color:#fff;background-color:rgba(255,255,255,.15)}.dropdown-menu-dark .dropdown-item.active,.dropdown-menu-dark .dropdown-item:active{color:#fff;background-color:#5d2f86}.dropdown-menu-dark .dropdown-item.disabled,.dropdown-menu-dark .dropdown-item:disabled{color:#adb5bd}.dropdown-menu-dark .dropdown-divider{border-color:rgba(29,45,53,.15)}.dropdown-menu-dark .dropdown-item-text{color:#dee2e6}.dropdown-menu-dark .dropdown-header{color:#adb5bd}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group>.btn,.search-form .btn-group>.search-submit,.comment-form .btn-group>input[type=submit],.btn-group-vertical>.btn,.search-form .btn-group-vertical>.search-submit,.comment-form .btn-group-vertical>input[type=submit]{position:relative;flex:1 1 auto}.btn-group>.btn-check:checked+.btn,.search-form .btn-group>.btn-check:checked+.search-submit,.comment-form .btn-group>.btn-check:checked+input[type=submit],.btn-group>.btn-check:focus+.btn,.search-form .btn-group>.btn-check:focus+.search-submit,.comment-form .btn-group>.btn-check:focus+input[type=submit],.btn-group>.btn:hover,.search-form .btn-group>.search-submit:hover,.comment-form .btn-group>input[type=submit]:hover,.btn-group>.btn:focus,.search-form .btn-group>.search-submit:focus,.comment-form .btn-group>input[type=submit]:focus,.btn-group>.btn:active,.search-form .btn-group>.search-submit:active,.comment-form .btn-group>input[type=submit]:active,.btn-group>.btn.active,.search-form .btn-group>.active.search-submit,.comment-form .btn-group>input.active[type=submit],.btn-group-vertical>.btn-check:checked+.btn,.search-form .btn-group-vertical>.btn-check:checked+.search-submit,.comment-form .btn-group-vertical>.btn-check:checked+input[type=submit],.btn-group-vertical>.btn-check:focus+.btn,.search-form .btn-group-vertical>.btn-check:focus+.search-submit,.comment-form .btn-group-vertical>.btn-check:focus+input[type=submit],.btn-group-vertical>.btn:hover,.search-form .btn-group-vertical>.search-submit:hover,.comment-form .btn-group-vertical>input[type=submit]:hover,.btn-group-vertical>.btn:focus,.search-form .btn-group-vertical>.search-submit:focus,.comment-form .btn-group-vertical>input[type=submit]:focus,.btn-group-vertical>.btn:active,.search-form .btn-group-vertical>.search-submit:active,.comment-form .btn-group-vertical>input[type=submit]:active,.btn-group-vertical>.btn.active,.search-form .btn-group-vertical>.active.search-submit,.comment-form .btn-group-vertical>input.active[type=submit]{z-index:1}.btn-toolbar{display:flex;flex-wrap:wrap;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn:not(:first-child),.search-form .btn-group>.search-submit:not(:first-child),.comment-form .btn-group>input[type=submit]:not(:first-child),.btn-group>.btn-group:not(:first-child){margin-left:-1px}.btn-group>.btn:not(:last-child):not(.dropdown-toggle),.search-form .btn-group>.search-submit:not(:last-child):not(.dropdown-toggle),.comment-form .btn-group>input[type=submit]:not(:last-child):not(.dropdown-toggle),.btn-group>.btn-group:not(:last-child)>.btn,.search-form .btn-group>.btn-group:not(:last-child)>.search-submit,.comment-form .btn-group>.btn-group:not(:last-child)>input[type=submit]{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:nth-child(n+3),.search-form .btn-group>.search-submit:nth-child(n+3),.comment-form .btn-group>input[type=submit]:nth-child(n+3),.btn-group>:not(.btn-check)+.btn,.search-form .btn-group>:not(.btn-check)+.search-submit,.comment-form .btn-group>:not(.btn-check)+input[type=submit],.btn-group>.btn-group:not(:first-child)>.btn,.search-form .btn-group>.btn-group:not(:first-child)>.search-submit,.comment-form .btn-group>.btn-group:not(:first-child)>input[type=submit]{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after,.dropend .dropdown-toggle-split::after{margin-left:0}.dropstart .dropdown-toggle-split::before{margin-right:0}.btn-sm+.dropdown-toggle-split,.btn-group-sm>.btn+.dropdown-toggle-split,.search-form .btn-group-sm>.search-submit+.dropdown-toggle-split,.comment-form .btn-group-sm>input[type=submit]+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-lg+.dropdown-toggle-split,.btn-group-lg>.btn+.dropdown-toggle-split,.search-form .btn-group-lg>.search-submit+.dropdown-toggle-split,.comment-form .btn-group-lg>input[type=submit]+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{flex-direction:column;align-items:flex-start;justify-content:center}.btn-group-vertical>.btn,.search-form .btn-group-vertical>.search-submit,.comment-form .btn-group-vertical>input[type=submit],.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn:not(:first-child),.search-form .btn-group-vertical>.search-submit:not(:first-child),.comment-form .btn-group-vertical>input[type=submit]:not(:first-child),.btn-group-vertical>.btn-group:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle),.search-form .btn-group-vertical>.search-submit:not(:last-child):not(.dropdown-toggle),.comment-form .btn-group-vertical>input[type=submit]:not(:last-child):not(.dropdown-toggle),.btn-group-vertical>.btn-group:not(:last-child)>.btn,.search-form .btn-group-vertical>.btn-group:not(:last-child)>.search-submit,.comment-form .btn-group-vertical>.btn-group:not(:last-child)>input[type=submit]{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn~.btn,.search-form .btn-group-vertical>.search-submit~.btn,.search-form .btn-group-vertical>.btn~.search-submit,.search-form .btn-group-vertical>.search-submit~.search-submit,.comment-form .btn-group-vertical>input[type=submit]~.btn,.comment-form .search-form .btn-group-vertical>input[type=submit]~.search-submit,.search-form .comment-form .btn-group-vertical>input[type=submit]~.search-submit,.comment-form .btn-group-vertical>.btn~input[type=submit],.comment-form .search-form .btn-group-vertical>.search-submit~input[type=submit],.search-form .comment-form .btn-group-vertical>.search-submit~input[type=submit],.comment-form .btn-group-vertical>input[type=submit]~input[type=submit],.btn-group-vertical>.btn-group:not(:first-child)>.btn,.search-form .btn-group-vertical>.btn-group:not(:first-child)>.search-submit,.comment-form .btn-group-vertical>.btn-group:not(:first-child)>input[type=submit]{border-top-left-radius:0;border-top-right-radius:0}.nav{display:flex;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link,.banner .nav a{display:block;padding:.5rem 1rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out}@media (prefers-reduced-motion: reduce){.nav-link,.banner .nav a{transition:none}}.nav-link.disabled,.banner .nav a.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-link,.nav-tabs .banner .nav a,.banner .nav .nav-tabs a{margin-bottom:-1px;background:none;border:1px solid rgba(0,0,0,0);border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:hover,.nav-tabs .banner .nav a:hover,.banner .nav .nav-tabs a:hover,.nav-tabs .nav-link:focus,.nav-tabs .banner .nav a:focus,.banner .nav .nav-tabs a:focus{border-color:#e9ecef #e9ecef #dee2e6;isolation:isolate}.nav-tabs .nav-link.disabled,.nav-tabs .banner .nav a.disabled,.banner .nav .nav-tabs a.disabled{color:#6c757d;background-color:rgba(0,0,0,0);border-color:rgba(0,0,0,0)}.nav-tabs .nav-link.active,.nav-tabs .banner .nav a.active,.banner .nav .nav-tabs a.active,.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-item.show .banner .nav a,.banner .nav .nav-tabs .nav-item.show a,.nav-tabs .banner .nav li.show .nav-link,.nav-tabs .banner .nav li.show a,.banner .nav .nav-tabs li.show .nav-link,.banner .nav .nav-tabs li.show a{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link,.nav-pills .banner .nav a,.banner .nav .nav-pills a{background:none;border:0;border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .banner .nav a.active,.banner .nav .nav-pills a.active,.nav-pills .show>.nav-link,.nav-pills .banner .nav .show>a,.banner .nav .nav-pills .show>a{color:#fff;background-color:#5d2f86}.nav-fill>.nav-link,.banner .nav .nav-fill>a,.nav-fill .nav-item,.nav-fill .banner .nav li,.banner .nav .nav-fill li{flex:1 1 auto;text-align:center}.nav-justified>.nav-link,.banner .nav .nav-justified>a,.nav-justified .nav-item,.nav-justified .banner .nav li,.banner .nav .nav-justified li{flex-basis:0;flex-grow:1;text-align:center}.nav-fill .nav-item .nav-link,.nav-fill .nav-item .banner .nav a,.banner .nav .nav-fill .nav-item a,.nav-fill .banner .nav li .nav-link,.nav-fill .banner .nav li a,.banner .nav .nav-fill li .nav-link,.banner .nav .nav-fill li a,.nav-justified .nav-item .nav-link,.nav-justified .nav-item .banner .nav a,.banner .nav .nav-justified .nav-item a,.nav-justified .banner .nav li .nav-link,.nav-justified .banner .nav li a,.banner .nav .nav-justified li .nav-link,.banner .nav .nav-justified li a{width:100%}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;padding-top:.5rem;padding-bottom:.5rem}.navbar>.container,.navbar>.container-fluid,.navbar>.container-sm,.navbar>.container-md,.navbar>.container-lg,.navbar>.container-xl,.navbar>.container-xxl{display:flex;flex-wrap:inherit;align-items:center;justify-content:space-between}.navbar-brand{padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;white-space:nowrap}.navbar-nav{display:flex;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link,.navbar-nav .banner .nav a,.banner .nav .navbar-nav a{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static}.navbar-text{padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{flex-basis:100%;flex-grow:1;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:rgba(0,0,0,0);border:1px solid rgba(0,0,0,0);border-radius:.25rem;transition:box-shadow .15s ease-in-out}@media (prefers-reduced-motion: reduce){.navbar-toggler{transition:none}}.navbar-toggler:hover{text-decoration:none}.navbar-toggler:focus{text-decoration:none;outline:0;box-shadow:0 0 0 .25rem}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;background-repeat:no-repeat;background-position:center;background-size:100%}.navbar-nav-scroll{max-height:var(--bs-scroll-height, 75vh);overflow-y:auto}@media (min-width: 576px){.navbar-expand-sm{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link,.navbar-expand-sm .navbar-nav .banner .nav a,.banner .nav .navbar-expand-sm .navbar-nav a{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex !important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (min-width: 768px){.navbar-expand-md{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link,.navbar-expand-md .navbar-nav .banner .nav a,.banner .nav .navbar-expand-md .navbar-nav a{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex !important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (min-width: 992px){.navbar-expand-lg{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link,.navbar-expand-lg .navbar-nav .banner .nav a,.banner .nav .navbar-expand-lg .navbar-nav a{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex !important;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (min-width: 1200px){.navbar-expand-xl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link,.navbar-expand-xl .navbar-nav .banner .nav a,.banner .nav .navbar-expand-xl .navbar-nav a{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex !important;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}@media (min-width: 1400px){.navbar-expand-xxl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xxl .navbar-nav{flex-direction:row}.navbar-expand-xxl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xxl .navbar-nav .nav-link,.navbar-expand-xxl .navbar-nav .banner .nav a,.banner .nav .navbar-expand-xxl .navbar-nav a{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xxl .navbar-nav-scroll{overflow:visible}.navbar-expand-xxl .navbar-collapse{display:flex !important;flex-basis:auto}.navbar-expand-xxl .navbar-toggler{display:none}}.navbar-expand{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link,.navbar-expand .navbar-nav .banner .nav a,.banner .nav .navbar-expand .navbar-nav a{padding-right:.5rem;padding-left:.5rem}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex !important;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:#5d2f86}.navbar-light .navbar-brand:hover,.navbar-light .navbar-brand:focus{color:#5d2f86}.navbar-light .navbar-nav .nav-link,.navbar-light .navbar-nav .banner .nav a,.banner .nav .navbar-light .navbar-nav a{color:#1d2d35}.navbar-light .navbar-nav .nav-link:hover,.navbar-light .navbar-nav .banner .nav a:hover,.banner .nav .navbar-light .navbar-nav a:hover,.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .banner .nav a:focus,.banner .nav .navbar-light .navbar-nav a:focus{color:#5d2f86}.navbar-light .navbar-nav .nav-link.disabled,.navbar-light .navbar-nav .banner .nav a.disabled,.banner .nav .navbar-light .navbar-nav a.disabled{color:rgba(29,45,53,.3)}.navbar-light .navbar-nav .show>.nav-link,.navbar-light .navbar-nav .banner .nav .show>a,.banner .nav .navbar-light .navbar-nav .show>a,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .banner .nav a.active,.banner .nav .navbar-light .navbar-nav a.active{color:#5d2f86}.navbar-light .navbar-toggler{color:#1d2d35;border-color:rgba(29,45,53,.1)}.navbar-light .navbar-toggler-icon{background-image:none}.navbar-light .navbar-text{color:#1d2d35}.navbar-light .navbar-text a,.navbar-light .navbar-text a:hover,.navbar-light .navbar-text a:focus{color:#5d2f86}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:hover,.navbar-dark .navbar-brand:focus{color:#fff}.navbar-dark .navbar-nav .nav-link,.navbar-dark .navbar-nav .banner .nav a,.banner .nav .navbar-dark .navbar-nav a{color:rgba(255,255,255,.55)}.navbar-dark .navbar-nav .nav-link:hover,.navbar-dark .navbar-nav .banner .nav a:hover,.banner .nav .navbar-dark .navbar-nav a:hover,.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .banner .nav a:focus,.banner .nav .navbar-dark .navbar-nav a:focus{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled,.navbar-dark .navbar-nav .banner .nav a.disabled,.banner .nav .navbar-dark .navbar-nav a.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .show>.nav-link,.navbar-dark .navbar-nav .banner .nav .show>a,.banner .nav .navbar-dark .navbar-nav .show>a,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .banner .nav a.active,.banner .nav .navbar-dark .navbar-nav a.active{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.55);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:none}.navbar-dark .navbar-text{color:rgba(255,255,255,.55)}.navbar-dark .navbar-text a,.navbar-dark .navbar-text a:hover,.navbar-dark .navbar-text a:focus{color:#fff}.card{position:relative;display:flex;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid #e9ecef;border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;padding:1rem 1rem}.card-title{margin-bottom:.5rem}.card-subtitle{margin-top:-.25rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1rem}.card-header{padding:.5rem 1rem;margin-bottom:0;background-color:rgba(29,45,53,.03);border-bottom:1px solid #e9ecef}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-footer{padding:.5rem 1rem;background-color:rgba(29,45,53,.03);border-top:1px solid #e9ecef}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.5rem;margin-bottom:-.5rem;margin-left:-.5rem;border-bottom:0}.card-header-pills{margin-right:-.5rem;margin-left:-.5rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(.25rem - 1px)}.card-img,.card-img-top,.card-img-bottom{width:100%}.card-img,.card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-group>.card{margin-bottom:24px}@media (min-width: 576px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card{flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-img-top,.card-group>.card:not(:last-child) .card-header{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-img-bottom,.card-group>.card:not(:last-child) .card-footer{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-img-top,.card-group>.card:not(:first-child) .card-header{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-img-bottom,.card-group>.card:not(:first-child) .card-footer{border-bottom-left-radius:0}}.accordion-button{position:relative;display:flex;align-items:center;width:100%;padding:1rem 1.25rem;font-size:1rem;color:#1d2d35;text-align:left;background-color:#fff;border:0;border-radius:0;overflow-anchor:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,border-radius .15s ease}@media (prefers-reduced-motion: reduce){.accordion-button{transition:none}}.accordion-button:not(.collapsed){color:#542a79;background-color:#efeaf3;box-shadow:inset 0 -1px 0 rgba(29,45,53,.125)}.accordion-button:not(.collapsed)::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23542a79'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");transform:rotate(180deg)}.accordion-button::after{flex-shrink:0;width:1.25rem;height:1.25rem;margin-left:auto;content:"";background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%231d2d35'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-size:1.25rem;transition:transform .2s ease-in-out}@media (prefers-reduced-motion: reduce){.accordion-button::after{transition:none}}.accordion-button:hover{z-index:2}.accordion-button:focus{z-index:3;border-color:#ae97c3;outline:0;box-shadow:0 0 0 .25rem rgba(93,47,134,.25)}.accordion-header{margin-bottom:0}.accordion-item{margin-bottom:-1px;background-color:#fff;border:1px solid rgba(29,45,53,.125)}.accordion-item:first-of-type{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.accordion-item:first-of-type .accordion-button{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.accordion-item:last-of-type{margin-bottom:0;border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.accordion-item:last-of-type .accordion-button.collapsed{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.accordion-item:last-of-type .accordion-collapse{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.accordion-body{padding:1rem 1.25rem}.accordion-flush .accordion-collapse{border-width:0}.accordion-flush .accordion-item{border-right:0;border-left:0;border-radius:0}.accordion-flush .accordion-item:first-child{border-top:0}.accordion-flush .accordion-item:last-child{border-bottom:0}.accordion-flush .accordion-item .accordion-button{border-radius:0}.breadcrumb{display:flex;flex-wrap:wrap;padding:0 0;margin-bottom:1rem;list-style:none}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{float:left;padding-right:.5rem;color:#6c757d;content:var(--bs-breadcrumb-divider, "/") /* rtl: var(--bs-breadcrumb-divider, "/") */}.breadcrumb-item.active{color:#6c757d}.pagination{display:flex;padding-left:0;list-style:none}.page-link{position:relative;display:block;color:#5d2f86;background-color:#fff;border:1px solid #dee2e6;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion: reduce){.page-link{transition:none}}.page-link:hover{z-index:2;color:#4a266b;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:3;color:#4a266b;background-color:#e9ecef;outline:0;box-shadow:0 0 0 .25rem rgba(93,47,134,.25)}.page-item:not(:first-child) .page-link{margin-left:-1px}.page-item.active .page-link{z-index:3;color:#fff;background-color:#5d2f86;border-color:#5d2f86}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;background-color:#fff;border-color:#dee2e6}.page-link{padding:.375rem .75rem}.page-item:first-child .page-link{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.badge:empty{display:none}.btn .badge,.search-form .search-submit .badge,.comment-form input[type=submit] .badge{position:relative;top:-1px}.alert{position:relative;padding:1rem 1.5rem;margin-bottom:0;border:0 solid rgba(0,0,0,0);border-radius:0}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4.5rem}.alert-dismissible .btn-close{position:absolute;top:0;right:0;z-index:2;padding:1.25rem 1.5rem}.alert-primary{color:#fff;background-color:#5d2f86;border-color:#5d2f86}.alert-primary .alert-link{color:#ccc}.alert-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.alert-secondary .alert-link{color:#ccc}.alert-success{color:#fff;background-color:#198754;border-color:#198754}.alert-success .alert-link{color:#ccc}.alert-info{color:#1d2d35;background-color:#0dcaf0;border-color:#0dcaf0}.alert-info .alert-link{color:#17242a}.alert-warning{color:#1d2d35;background-color:#ffe000;border-color:#ffe000}.alert-warning .alert-link{color:#17242a}.alert-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.alert-danger .alert-link{color:#ccc}.alert-light{color:#1d2d35;background-color:#f8f9fa;border-color:#f8f9fa}.alert-light .alert-link{color:#17242a}.alert-dark{color:#fff;background-color:#212529;border-color:#212529}.alert-dark .alert-link{color:#ccc}@keyframes progress-bar-stripes{0%{background-position-x:1rem}}.progress{display:flex;height:1rem;overflow:hidden;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress-bar{display:flex;flex-direction:column;justify-content:center;overflow:hidden;color:#fff;text-align:center;white-space:nowrap;background-color:#5d2f86;transition:width .6s ease}@media (prefers-reduced-motion: reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg, rgba(255,255,255,.15) 25%, rgba(0,0,0,0) 25%, rgba(0,0,0,0) 50%, rgba(255,255,255,.15) 50%, rgba(255,255,255,.15) 75%, rgba(0,0,0,0) 75%, rgba(0,0,0,0));background-size:1rem 1rem}.progress-bar-animated{animation:1s linear infinite progress-bar-stripes}@media (prefers-reduced-motion: reduce){.progress-bar-animated{animation:none}}.list-group{display:flex;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:.25rem}.list-group-numbered{list-style-type:none;counter-reset:section}.list-group-numbered>li::before{content:counters(section, ".") ". ";counter-increment:section}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:hover,.list-group-item-action:focus{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#1d2d35;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.5rem 1rem;color:#212529;background-color:#fff;border:1px solid rgba(29,45,53,.125)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#5d2f86;border-color:#5d2f86}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:-1px;border-top-width:1px}.list-group-horizontal{flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media (min-width: 576px){.list-group-horizontal-sm{flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width: 768px){.list-group-horizontal-md{flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width: 992px){.list-group-horizontal-lg{flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width: 1200px){.list-group-horizontal-xl{flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width: 1400px){.list-group-horizontal-xxl{flex-direction:row}.list-group-horizontal-xxl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xxl>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-xxl>.list-group-item.active{margin-top:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{color:#381c50;background-color:#dfd5e7}.list-group-item-primary.list-group-item-action:hover,.list-group-item-primary.list-group-item-action:focus{color:#381c50;background-color:#c9c0d0}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#381c50;border-color:#381c50}.list-group-item-secondary{color:#41464b;background-color:#e2e3e5}.list-group-item-secondary.list-group-item-action:hover,.list-group-item-secondary.list-group-item-action:focus{color:#41464b;background-color:#cbccce}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#41464b;border-color:#41464b}.list-group-item-success{color:#0f5132;background-color:#d1e7dd}.list-group-item-success.list-group-item-action:hover,.list-group-item-success.list-group-item-action:focus{color:#0f5132;background-color:#bcd0c7}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#0f5132;border-color:#0f5132}.list-group-item-info{color:#1d2d35;background-color:#cff4fc}.list-group-item-info.list-group-item-action:hover,.list-group-item-info.list-group-item-action:focus{color:#1d2d35;background-color:#badce3}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#1d2d35;border-color:#1d2d35}.list-group-item-warning{color:#1d2d35;background-color:#fff9cc}.list-group-item-warning.list-group-item-action:hover,.list-group-item-warning.list-group-item-action:focus{color:#1d2d35;background-color:#e6e0b8}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#1d2d35;border-color:#1d2d35}.list-group-item-danger{color:#842029;background-color:#f8d7da}.list-group-item-danger.list-group-item-action:hover,.list-group-item-danger.list-group-item-action:focus{color:#842029;background-color:#dfc2c4}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#842029;border-color:#842029}.list-group-item-light{color:#1d2d35;background-color:#fefefe}.list-group-item-light.list-group-item-action:hover,.list-group-item-light.list-group-item-action:focus{color:#1d2d35;background-color:#e5e5e5}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#1d2d35;border-color:#1d2d35}.list-group-item-dark{color:#141619;background-color:#d3d3d4}.list-group-item-dark.list-group-item-action:hover,.list-group-item-dark.list-group-item-action:focus{color:#141619;background-color:#bebebf}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#141619;border-color:#141619}.btn-close{box-sizing:content-box;width:1em;height:1em;padding:.25em .25em;color:#1d2d35;background:rgba(0,0,0,0) url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%231d2d35'%3e%3cpath d='M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z'/%3e%3c/svg%3e") center/1em auto no-repeat;border:0;border-radius:.25rem;opacity:.5}.btn-close:hover{color:#1d2d35;text-decoration:none;opacity:.75}.btn-close:focus{outline:0;box-shadow:0 0 0 .25rem rgba(93,47,134,.25);opacity:1}.btn-close:disabled,.btn-close.disabled{pointer-events:none;user-select:none;opacity:.25}.btn-close-white{filter:invert(1) grayscale(100%) brightness(200%)}.toast{width:350px;max-width:100%;font-size:.875rem;pointer-events:auto;background-color:rgba(255,255,255,.85);background-clip:padding-box;border:1px solid rgba(0,0,0,.1);box-shadow:0 .5rem 1rem rgba(29,45,53,.15);border-radius:.25rem}.toast:not(.showing):not(.show){opacity:0}.toast.hide{display:none}.toast-container{width:max-content;max-width:100%;pointer-events:none}.toast-container>:not(:last-child){margin-bottom:24px}.toast-header{display:flex;align-items:center;padding:.5rem .75rem;color:#6c757d;background-color:rgba(255,255,255,.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05);border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.toast-header .btn-close{margin-right:-.375rem;margin-left:.75rem}.toast-body{padding:.75rem;word-wrap:break-word}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;left:0;z-index:1060;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:transform .3s ease-out;transform:translate(0, -50px)}@media (prefers-reduced-motion: reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:100%;overflow:hidden}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;align-items:center;min-height:calc(100% - 1rem)}.modal-content{position:relative;display:flex;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(29,45,53,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1050;width:100vw;height:100vh;background-color:#1d2d35}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:flex;flex-shrink:0;align-items:center;justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #e9ecef;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.modal-header .btn-close{padding:.5rem .5rem;margin:-.5rem -.5rem -.5rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;flex:1 1 auto;padding:1rem}.modal-footer{display:flex;flex-wrap:wrap;flex-shrink:0;align-items:center;justify-content:flex-end;padding:.75rem;border-top:1px solid #e9ecef;border-bottom-right-radius:calc(.3rem - 1px);border-bottom-left-radius:calc(.3rem - 1px)}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width: 576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{height:calc(100% - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-sm{max-width:300px}}@media (min-width: 992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width: 1200px){.modal-xl{max-width:1140px}}.modal-fullscreen{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen .modal-header{border-radius:0}.modal-fullscreen .modal-body{overflow-y:auto}.modal-fullscreen .modal-footer{border-radius:0}@media (max-width: 575.98px){.modal-fullscreen-sm-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-sm-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-sm-down .modal-header{border-radius:0}.modal-fullscreen-sm-down .modal-body{overflow-y:auto}.modal-fullscreen-sm-down .modal-footer{border-radius:0}}@media (max-width: 767.98px){.modal-fullscreen-md-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-md-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-md-down .modal-header{border-radius:0}.modal-fullscreen-md-down .modal-body{overflow-y:auto}.modal-fullscreen-md-down .modal-footer{border-radius:0}}@media (max-width: 991.98px){.modal-fullscreen-lg-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-lg-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-lg-down .modal-header{border-radius:0}.modal-fullscreen-lg-down .modal-body{overflow-y:auto}.modal-fullscreen-lg-down .modal-footer{border-radius:0}}@media (max-width: 1199.98px){.modal-fullscreen-xl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xl-down .modal-header{border-radius:0}.modal-fullscreen-xl-down .modal-body{overflow-y:auto}.modal-fullscreen-xl-down .modal-footer{border-radius:0}}@media (max-width: 1399.98px){.modal-fullscreen-xxl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xxl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xxl-down .modal-header{border-radius:0}.modal-fullscreen-xxl-down .modal-body{overflow-y:auto}.modal-fullscreen-xxl-down .modal-footer{border-radius:0}}.tooltip{position:absolute;z-index:1080;display:block;margin:0;font-family:"Jost",-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}.tooltip.show{opacity:.9}.tooltip .tooltip-arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .tooltip-arrow::before{position:absolute;content:"";border-color:rgba(0,0,0,0);border-style:solid}.bs-tooltip-top,.bs-tooltip-auto[data-popper-placement^=top]{padding:.4rem 0}.bs-tooltip-top .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow{bottom:0}.bs-tooltip-top .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before{top:-1px;border-width:.4rem .4rem 0;border-top-color:#1d2d35}.bs-tooltip-end,.bs-tooltip-auto[data-popper-placement^=right]{padding:0 .4rem}.bs-tooltip-end .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-end .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before{right:-1px;border-width:.4rem .4rem .4rem 0;border-right-color:#1d2d35}.bs-tooltip-bottom,.bs-tooltip-auto[data-popper-placement^=bottom]{padding:.4rem 0}.bs-tooltip-bottom .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow{top:0}.bs-tooltip-bottom .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before{bottom:-1px;border-width:0 .4rem .4rem;border-bottom-color:#1d2d35}.bs-tooltip-start,.bs-tooltip-auto[data-popper-placement^=left]{padding:0 .4rem}.bs-tooltip-start .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-start .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before{left:-1px;border-width:.4rem 0 .4rem .4rem;border-left-color:#1d2d35}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#1d2d35;border-radius:.25rem}.popover{position:absolute;top:0;left:0 /* rtl:ignore */;z-index:1070;display:block;max-width:276px;font-family:"Jost",-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;background-clip:padding-box;border:1px solid rgba(29,45,53,.2);border-radius:.3rem}.popover .popover-arrow{position:absolute;display:block;width:1rem;height:.5rem}.popover .popover-arrow::before,.popover .popover-arrow::after{position:absolute;display:block;content:"";border-color:rgba(0,0,0,0);border-style:solid}.bs-popover-top>.popover-arrow,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow{bottom:calc(-.5rem - 1px)}.bs-popover-top>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(29,45,53,.25)}.bs-popover-top>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bs-popover-end>.popover-arrow,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow{left:calc(-.5rem - 1px);width:.5rem;height:1rem}.bs-popover-end>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(29,45,53,.25)}.bs-popover-end>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bs-popover-bottom>.popover-arrow,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow{top:calc(-.5rem - 1px)}.bs-popover-bottom>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(29,45,53,.25)}.bs-popover-bottom>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#fff}.bs-popover-bottom .popover-header::before,.bs-popover-auto[data-popper-placement^=bottom] .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f0f0f0}.bs-popover-start>.popover-arrow,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow{right:calc(-.5rem - 1px);width:.5rem;height:1rem}.bs-popover-start>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(29,45,53,.25)}.bs-popover-start>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.popover-header{padding:.5rem 1rem;margin-bottom:0;font-size:1rem;background-color:#f0f0f0;border-bottom:1px solid #d8d8d8;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:1rem 1rem;color:#1d2d35}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;backface-visibility:hidden;transition:transform .6s ease-in-out}@media (prefers-reduced-motion: reduce){.carousel-item{transition:none}}.carousel-item.active,.carousel-item-next,.carousel-item-prev{display:block}.carousel-item-next:not(.carousel-item-start),.active.carousel-item-end{transform:translateX(100%)}.carousel-item-prev:not(.carousel-item-end),.active.carousel-item-start{transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;transform:none}.carousel-fade .carousel-item.active,.carousel-fade .carousel-item-next.carousel-item-start,.carousel-fade .carousel-item-prev.carousel-item-end{z-index:1;opacity:1}.carousel-fade .active.carousel-item-start,.carousel-fade .active.carousel-item-end{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion: reduce){.carousel-fade .active.carousel-item-start,.carousel-fade .active.carousel-item-end{transition:none}}.carousel-control-prev,.carousel-control-next{position:absolute;top:0;bottom:0;z-index:1;display:flex;align-items:center;justify-content:center;width:15%;padding:0;color:#fff;text-align:center;background:none;border:0;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion: reduce){.carousel-control-prev,.carousel-control-next{transition:none}}.carousel-control-prev:hover,.carousel-control-prev:focus,.carousel-control-next:hover,.carousel-control-next:focus{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-prev-icon,.carousel-control-next-icon{display:inline-block;width:2rem;height:2rem;background-repeat:no-repeat;background-position:50%;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:2;display:flex;justify-content:center;padding:0;margin-right:15%;margin-bottom:1rem;margin-left:15%;list-style:none}.carousel-indicators [data-bs-target]{box-sizing:content-box;flex:0 1 auto;width:30px;height:3px;padding:0;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border:0;border-top:10px solid rgba(0,0,0,0);border-bottom:10px solid rgba(0,0,0,0);opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion: reduce){.carousel-indicators [data-bs-target]{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:1.25rem;left:15%;padding-top:1.25rem;padding-bottom:1.25rem;color:#fff;text-align:center}.carousel-dark .carousel-control-prev-icon,.carousel-dark .carousel-control-next-icon{filter:invert(1) grayscale(100)}.carousel-dark .carousel-indicators [data-bs-target]{background-color:#1d2d35}.carousel-dark .carousel-caption{color:#1d2d35}@keyframes spinner-border{to{transform:rotate(360deg) /* rtl:ignore */}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;border:.25em solid currentColor;border-right-color:rgba(0,0,0,0);border-radius:50%;animation:.75s linear infinite spinner-border}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;background-color:currentColor;border-radius:50%;opacity:0;animation:.75s linear infinite spinner-grow}.spinner-grow-sm{width:1rem;height:1rem}@media (prefers-reduced-motion: reduce){.spinner-border,.spinner-grow{animation-duration:1.5s}}.offcanvas{position:fixed;bottom:0;z-index:1040;display:flex;flex-direction:column;max-width:100%;visibility:hidden;background-color:#fff;background-clip:padding-box;outline:0;transition:transform .3s ease-in-out}@media (prefers-reduced-motion: reduce){.offcanvas{transition:none}}.offcanvas-header{display:flex;justify-content:space-between;padding:1rem 1rem}.offcanvas-header .btn-close{padding:.5rem .5rem;margin:-.5rem -.5rem -.5rem auto}.offcanvas-title{margin-bottom:0;line-height:1.5}.offcanvas-body{flex-grow:1;padding:1rem 1rem;overflow-y:auto}.offcanvas-start{top:0;left:0;width:400px;border-right:1px solid rgba(29,45,53,.2);transform:translateX(-100%)}.offcanvas-end{top:0;right:0;width:400px;border-left:1px solid rgba(29,45,53,.2);transform:translateX(100%)}.offcanvas-bottom{right:0;left:0;height:30vh;max-height:100%;border-top:1px solid rgba(29,45,53,.2);transform:translateY(100%)}.offcanvas.show{transform:none}.offcanvas-backdrop::before{position:fixed;top:0;left:0;z-index:1039;width:100vw;height:100vh;content:"";background-color:rgba(29,45,53,.5)}.clearfix::after{display:block;clear:both;content:""}.link-primary{color:#5d2f86}.link-primary:hover,.link-primary:focus{color:#4a266b}.link-secondary{color:#6c757d}.link-secondary:hover,.link-secondary:focus{color:#565e64}.link-success{color:#198754}.link-success:hover,.link-success:focus{color:#146c43}.link-info{color:#0dcaf0}.link-info:hover,.link-info:focus{color:#3dd5f3}.link-warning{color:#ffe000}.link-warning:hover,.link-warning:focus{color:#ffe633}.link-danger{color:#dc3545}.link-danger:hover,.link-danger:focus{color:#b02a37}.link-light{color:#f8f9fa}.link-light:hover,.link-light:focus{color:#f9fafb}.link-dark{color:#212529}.link-dark:hover,.link-dark:focus{color:#1a1e21}.ratio{position:relative;width:100%}.ratio::before{display:block;padding-top:var(--bs-aspect-ratio);content:""}.ratio>*{position:absolute;top:0;left:0;width:100%;height:100%}.ratio-1x1{--bs-aspect-ratio: 100%}.ratio-4x3{--bs-aspect-ratio: 75%}.ratio-16x9{--bs-aspect-ratio: 56.25%}.ratio-21x9{--bs-aspect-ratio: 42.8571428571%}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top{position:sticky;top:0;z-index:1020}@media (min-width: 576px){.sticky-sm-top{position:sticky;top:0;z-index:1020}}@media (min-width: 768px){.sticky-md-top{position:sticky;top:0;z-index:1020}}@media (min-width: 992px){.sticky-lg-top{position:sticky;top:0;z-index:1020}}@media (min-width: 1200px){.sticky-xl-top{position:sticky;top:0;z-index:1020}}@media (min-width: 1400px){.sticky-xxl-top{position:sticky;top:0;z-index:1020}}.visually-hidden,.visually-hidden-focusable:not(:focus):not(:focus-within){position:absolute !important;width:1px !important;height:1px !important;padding:0 !important;margin:-1px !important;overflow:hidden !important;clip:rect(0, 0, 0, 0) !important;white-space:nowrap !important;border:0 !important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.align-baseline{vertical-align:baseline !important}.align-top{vertical-align:top !important}.align-middle{vertical-align:middle !important}.align-bottom{vertical-align:bottom !important}.align-text-bottom{vertical-align:text-bottom !important}.align-text-top{vertical-align:text-top !important}.float-start{float:left !important}.float-end{float:right !important}.float-none{float:none !important}.overflow-auto{overflow:auto !important}.overflow-hidden{overflow:hidden !important}.overflow-visible{overflow:visible !important}.overflow-scroll{overflow:scroll !important}.d-inline{display:inline !important}.d-inline-block{display:inline-block !important}.d-block{display:block !important}.d-grid{display:grid !important}.d-table{display:table !important}.d-table-row{display:table-row !important}.d-table-cell{display:table-cell !important}.d-flex{display:flex !important}.d-inline-flex{display:inline-flex !important}.d-none{display:none !important}.shadow{box-shadow:0 .5rem 1rem rgba(29,45,53,.15) !important}.shadow-sm{box-shadow:0 .125rem .25rem rgba(29,45,53,.075) !important}.shadow-lg{box-shadow:0 1rem 3rem rgba(29,45,53,.175) !important}.shadow-none{box-shadow:none !important}.position-static{position:static !important}.position-relative{position:relative !important}.position-absolute{position:absolute !important}.position-fixed{position:fixed !important}.position-sticky{position:sticky !important}.top-0{top:0 !important}.top-50{top:50% !important}.top-100{top:100% !important}.bottom-0{bottom:0 !important}.bottom-50{bottom:50% !important}.bottom-100{bottom:100% !important}.start-0{left:0 !important}.start-50{left:50% !important}.start-100{left:100% !important}.end-0{right:0 !important}.end-50{right:50% !important}.end-100{right:100% !important}.translate-middle{transform:translate(-50%, -50%) !important}.translate-middle-x{transform:translateX(-50%) !important}.translate-middle-y{transform:translateY(-50%) !important}.border{border:1px solid #e9ecef !important}.border-0{border:0 !important}.border-top{border-top:1px solid #e9ecef !important}.border-top-0{border-top:0 !important}.border-end{border-right:1px solid #e9ecef !important}.border-end-0{border-right:0 !important}.border-bottom{border-bottom:1px solid #e9ecef !important}.border-bottom-0{border-bottom:0 !important}.border-start{border-left:1px solid #e9ecef !important}.border-start-0{border-left:0 !important}.border-primary{border-color:#5d2f86 !important}.border-secondary{border-color:#6c757d !important}.border-success{border-color:#198754 !important}.border-info{border-color:#0dcaf0 !important}.border-warning{border-color:#ffe000 !important}.border-danger{border-color:#dc3545 !important}.border-light{border-color:#f8f9fa !important}.border-dark{border-color:#212529 !important}.border-white{border-color:#fff !important}.border-1{border-width:1px !important}.border-2{border-width:2px !important}.border-3{border-width:3px !important}.border-4{border-width:4px !important}.border-5{border-width:5px !important}.w-25{width:25% !important}.w-50{width:50% !important}.w-75{width:75% !important}.w-100{width:100% !important}.w-auto{width:auto !important}.mw-100{max-width:100% !important}.vw-100{width:100vw !important}.min-vw-100{min-width:100vw !important}.h-25{height:25% !important}.h-50{height:50% !important}.h-75{height:75% !important}.h-100{height:100% !important}.h-auto{height:auto !important}.mh-100{max-height:100% !important}.vh-100{height:100vh !important}.min-vh-100{min-height:100vh !important}.flex-fill{flex:1 1 auto !important}.flex-row{flex-direction:row !important}.flex-column{flex-direction:column !important}.flex-row-reverse{flex-direction:row-reverse !important}.flex-column-reverse{flex-direction:column-reverse !important}.flex-grow-0{flex-grow:0 !important}.flex-grow-1{flex-grow:1 !important}.flex-shrink-0{flex-shrink:0 !important}.flex-shrink-1{flex-shrink:1 !important}.flex-wrap{flex-wrap:wrap !important}.flex-nowrap{flex-wrap:nowrap !important}.flex-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-0{gap:0 !important}.gap-1{gap:.25rem !important}.gap-2{gap:.5rem !important}.gap-3{gap:1rem !important}.gap-4{gap:1.5rem !important}.gap-5{gap:3rem !important}.justify-content-start{justify-content:flex-start !important}.justify-content-end{justify-content:flex-end !important}.justify-content-center{justify-content:center !important}.justify-content-between{justify-content:space-between !important}.justify-content-around{justify-content:space-around !important}.justify-content-evenly{justify-content:space-evenly !important}.align-items-start{align-items:flex-start !important}.align-items-end{align-items:flex-end !important}.align-items-center{align-items:center !important}.align-items-baseline{align-items:baseline !important}.align-items-stretch{align-items:stretch !important}.align-content-start{align-content:flex-start !important}.align-content-end{align-content:flex-end !important}.align-content-center{align-content:center !important}.align-content-between{align-content:space-between !important}.align-content-around{align-content:space-around !important}.align-content-stretch{align-content:stretch !important}.align-self-auto{align-self:auto !important}.align-self-start{align-self:flex-start !important}.align-self-end{align-self:flex-end !important}.align-self-center{align-self:center !important}.align-self-baseline{align-self:baseline !important}.align-self-stretch{align-self:stretch !important}.order-first{order:-1 !important}.order-0{order:0 !important}.order-1{order:1 !important}.order-2{order:2 !important}.order-3{order:3 !important}.order-4{order:4 !important}.order-5{order:5 !important}.order-last{order:6 !important}.m-0{margin:0 !important}.m-1{margin:.25rem !important}.m-2{margin:.5rem !important}.m-3{margin:1rem !important}.m-4{margin:1.5rem !important}.m-5{margin:3rem !important}.m-auto{margin:auto !important}.mx-0{margin-right:0 !important;margin-left:0 !important}.mx-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-3{margin-right:1rem !important;margin-left:1rem !important}.mx-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-5{margin-right:3rem !important;margin-left:3rem !important}.mx-auto{margin-right:auto !important;margin-left:auto !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.my-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-0{margin-top:0 !important}.mt-1{margin-top:.25rem !important}.mt-2{margin-top:.5rem !important}.mt-3{margin-top:1rem !important}.mt-4{margin-top:1.5rem !important}.mt-5{margin-top:3rem !important}.mt-auto{margin-top:auto !important}.me-0{margin-right:0 !important}.me-1{margin-right:.25rem !important}.me-2{margin-right:.5rem !important}.me-3{margin-right:1rem !important}.me-4{margin-right:1.5rem !important}.me-5{margin-right:3rem !important}.me-auto{margin-right:auto !important}.mb-0{margin-bottom:0 !important}.mb-1{margin-bottom:.25rem !important}.mb-2{margin-bottom:.5rem !important}.mb-3{margin-bottom:1rem !important}.mb-4{margin-bottom:1.5rem !important}.mb-5{margin-bottom:3rem !important}.mb-auto{margin-bottom:auto !important}.ms-0{margin-left:0 !important}.ms-1{margin-left:.25rem !important}.ms-2{margin-left:.5rem !important}.ms-3{margin-left:1rem !important}.ms-4{margin-left:1.5rem !important}.ms-5{margin-left:3rem !important}.ms-auto{margin-left:auto !important}.m-n1{margin:-.25rem !important}.m-n2{margin:-.5rem !important}.m-n3{margin:-1rem !important}.m-n4{margin:-1.5rem !important}.m-n5{margin:-3rem !important}.mx-n1{margin-right:-.25rem !important;margin-left:-.25rem !important}.mx-n2{margin-right:-.5rem !important;margin-left:-.5rem !important}.mx-n3{margin-right:-1rem !important;margin-left:-1rem !important}.mx-n4{margin-right:-1.5rem !important;margin-left:-1.5rem !important}.mx-n5{margin-right:-3rem !important;margin-left:-3rem !important}.my-n1{margin-top:-.25rem !important;margin-bottom:-.25rem !important}.my-n2{margin-top:-.5rem !important;margin-bottom:-.5rem !important}.my-n3{margin-top:-1rem !important;margin-bottom:-1rem !important}.my-n4{margin-top:-1.5rem !important;margin-bottom:-1.5rem !important}.my-n5{margin-top:-3rem !important;margin-bottom:-3rem !important}.mt-n1{margin-top:-.25rem !important}.mt-n2{margin-top:-.5rem !important}.mt-n3{margin-top:-1rem !important}.mt-n4{margin-top:-1.5rem !important}.mt-n5{margin-top:-3rem !important}.me-n1{margin-right:-.25rem !important}.me-n2{margin-right:-.5rem !important}.me-n3{margin-right:-1rem !important}.me-n4{margin-right:-1.5rem !important}.me-n5{margin-right:-3rem !important}.mb-n1{margin-bottom:-.25rem !important}.mb-n2{margin-bottom:-.5rem !important}.mb-n3{margin-bottom:-1rem !important}.mb-n4{margin-bottom:-1.5rem !important}.mb-n5{margin-bottom:-3rem !important}.ms-n1{margin-left:-.25rem !important}.ms-n2{margin-left:-.5rem !important}.ms-n3{margin-left:-1rem !important}.ms-n4{margin-left:-1.5rem !important}.ms-n5{margin-left:-3rem !important}.p-0{padding:0 !important}.p-1{padding:.25rem !important}.p-2{padding:.5rem !important}.p-3{padding:1rem !important}.p-4{padding:1.5rem !important}.p-5{padding:3rem !important}.px-0{padding-right:0 !important;padding-left:0 !important}.px-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-3{padding-right:1rem !important;padding-left:1rem !important}.px-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-5{padding-right:3rem !important;padding-left:3rem !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.py-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-0{padding-top:0 !important}.pt-1{padding-top:.25rem !important}.pt-2{padding-top:.5rem !important}.pt-3{padding-top:1rem !important}.pt-4{padding-top:1.5rem !important}.pt-5{padding-top:3rem !important}.pe-0{padding-right:0 !important}.pe-1{padding-right:.25rem !important}.pe-2{padding-right:.5rem !important}.pe-3{padding-right:1rem !important}.pe-4{padding-right:1.5rem !important}.pe-5{padding-right:3rem !important}.pb-0{padding-bottom:0 !important}.pb-1{padding-bottom:.25rem !important}.pb-2{padding-bottom:.5rem !important}.pb-3{padding-bottom:1rem !important}.pb-4{padding-bottom:1.5rem !important}.pb-5{padding-bottom:3rem !important}.ps-0{padding-left:0 !important}.ps-1{padding-left:.25rem !important}.ps-2{padding-left:.5rem !important}.ps-3{padding-left:1rem !important}.ps-4{padding-left:1.5rem !important}.ps-5{padding-left:3rem !important}.font-monospace{font-family:var(--bs-font-monospace) !important}.fs-1{font-size:calc(1.375rem + 1.5vw) !important}.fs-2{font-size:calc(1.325rem + .9vw) !important}.fs-3{font-size:calc(1.3rem + .6vw) !important}.fs-4{font-size:calc(1.275rem + .3vw) !important}.fs-5{font-size:1.25rem !important}.fs-6{font-size:1rem !important}.fst-italic{font-style:italic !important}.fst-normal{font-style:normal !important}.fw-light{font-weight:300 !important}.fw-lighter{font-weight:lighter !important}.fw-normal{font-weight:400 !important}.fw-bold{font-weight:700 !important}.fw-bolder{font-weight:bolder !important}.lh-1{line-height:1 !important}.lh-sm{line-height:1.25 !important}.lh-base{line-height:1.5 !important}.lh-lg{line-height:2 !important}.text-start{text-align:left !important}.text-end{text-align:right !important}.text-center{text-align:center !important}.text-decoration-none{text-decoration:none !important}.text-decoration-underline{text-decoration:underline !important}.text-decoration-line-through{text-decoration:line-through !important}.text-lowercase{text-transform:lowercase !important}.text-uppercase{text-transform:uppercase !important}.text-capitalize{text-transform:capitalize !important}.text-wrap{white-space:normal !important}.text-nowrap{white-space:nowrap !important}.text-break{word-wrap:break-word !important;word-break:break-word !important}.text-primary{color:#5d2f86 !important}.text-secondary{color:#6c757d !important}.text-success{color:#198754 !important}.text-info{color:#0dcaf0 !important}.text-warning{color:#ffe000 !important}.text-danger{color:#dc3545 !important}.text-light{color:#f8f9fa !important}.text-dark{color:#212529 !important}.text-white{color:#fff !important}.text-body{color:#1d2d35 !important}.text-muted{color:#6c757d !important}.text-black-50{color:rgba(29,45,53,.5) !important}.text-white-50{color:rgba(255,255,255,.5) !important}.text-reset{color:inherit !important}.bg-primary{background-color:#5d2f86 !important}.bg-secondary{background-color:#6c757d !important}.bg-success{background-color:#198754 !important}.bg-info{background-color:#0dcaf0 !important}.bg-warning{background-color:#ffe000 !important}.bg-danger{background-color:#dc3545 !important}.bg-light{background-color:#f8f9fa !important}.bg-dark{background-color:#212529 !important}.bg-body{background-color:#fff !important}.bg-white{background-color:#fff !important}.bg-transparent{background-color:rgba(0,0,0,0) !important}.bg-gradient{background-image:var(--bs-gradient) !important}.user-select-all{user-select:all !important}.user-select-auto{user-select:auto !important}.user-select-none{user-select:none !important}.pe-none{pointer-events:none !important}.pe-auto{pointer-events:auto !important}.rounded{border-radius:.25rem !important}.rounded-0{border-radius:0 !important}.rounded-1{border-radius:.2rem !important}.rounded-2{border-radius:.25rem !important}.rounded-3{border-radius:.3rem !important}.rounded-circle{border-radius:50% !important}.rounded-pill{border-radius:50rem !important}.rounded-top{border-top-left-radius:.25rem !important;border-top-right-radius:.25rem !important}.rounded-end{border-top-right-radius:.25rem !important;border-bottom-right-radius:.25rem !important}.rounded-bottom{border-bottom-right-radius:.25rem !important;border-bottom-left-radius:.25rem !important}.rounded-start{border-bottom-left-radius:.25rem !important;border-top-left-radius:.25rem !important}.visible{visibility:visible !important}.invisible{visibility:hidden !important}@media (min-width: 576px){.float-sm-start{float:left !important}.float-sm-end{float:right !important}.float-sm-none{float:none !important}.d-sm-inline{display:inline !important}.d-sm-inline-block{display:inline-block !important}.d-sm-block{display:block !important}.d-sm-grid{display:grid !important}.d-sm-table{display:table !important}.d-sm-table-row{display:table-row !important}.d-sm-table-cell{display:table-cell !important}.d-sm-flex{display:flex !important}.d-sm-inline-flex{display:inline-flex !important}.d-sm-none{display:none !important}.flex-sm-fill{flex:1 1 auto !important}.flex-sm-row{flex-direction:row !important}.flex-sm-column{flex-direction:column !important}.flex-sm-row-reverse{flex-direction:row-reverse !important}.flex-sm-column-reverse{flex-direction:column-reverse !important}.flex-sm-grow-0{flex-grow:0 !important}.flex-sm-grow-1{flex-grow:1 !important}.flex-sm-shrink-0{flex-shrink:0 !important}.flex-sm-shrink-1{flex-shrink:1 !important}.flex-sm-wrap{flex-wrap:wrap !important}.flex-sm-nowrap{flex-wrap:nowrap !important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-sm-0{gap:0 !important}.gap-sm-1{gap:.25rem !important}.gap-sm-2{gap:.5rem !important}.gap-sm-3{gap:1rem !important}.gap-sm-4{gap:1.5rem !important}.gap-sm-5{gap:3rem !important}.justify-content-sm-start{justify-content:flex-start !important}.justify-content-sm-end{justify-content:flex-end !important}.justify-content-sm-center{justify-content:center !important}.justify-content-sm-between{justify-content:space-between !important}.justify-content-sm-around{justify-content:space-around !important}.justify-content-sm-evenly{justify-content:space-evenly !important}.align-items-sm-start{align-items:flex-start !important}.align-items-sm-end{align-items:flex-end !important}.align-items-sm-center{align-items:center !important}.align-items-sm-baseline{align-items:baseline !important}.align-items-sm-stretch{align-items:stretch !important}.align-content-sm-start{align-content:flex-start !important}.align-content-sm-end{align-content:flex-end !important}.align-content-sm-center{align-content:center !important}.align-content-sm-between{align-content:space-between !important}.align-content-sm-around{align-content:space-around !important}.align-content-sm-stretch{align-content:stretch !important}.align-self-sm-auto{align-self:auto !important}.align-self-sm-start{align-self:flex-start !important}.align-self-sm-end{align-self:flex-end !important}.align-self-sm-center{align-self:center !important}.align-self-sm-baseline{align-self:baseline !important}.align-self-sm-stretch{align-self:stretch !important}.order-sm-first{order:-1 !important}.order-sm-0{order:0 !important}.order-sm-1{order:1 !important}.order-sm-2{order:2 !important}.order-sm-3{order:3 !important}.order-sm-4{order:4 !important}.order-sm-5{order:5 !important}.order-sm-last{order:6 !important}.m-sm-0{margin:0 !important}.m-sm-1{margin:.25rem !important}.m-sm-2{margin:.5rem !important}.m-sm-3{margin:1rem !important}.m-sm-4{margin:1.5rem !important}.m-sm-5{margin:3rem !important}.m-sm-auto{margin:auto !important}.mx-sm-0{margin-right:0 !important;margin-left:0 !important}.mx-sm-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-sm-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-sm-3{margin-right:1rem !important;margin-left:1rem !important}.mx-sm-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-sm-5{margin-right:3rem !important;margin-left:3rem !important}.mx-sm-auto{margin-right:auto !important;margin-left:auto !important}.my-sm-0{margin-top:0 !important;margin-bottom:0 !important}.my-sm-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-sm-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-sm-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-sm-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-sm-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-sm-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-sm-0{margin-top:0 !important}.mt-sm-1{margin-top:.25rem !important}.mt-sm-2{margin-top:.5rem !important}.mt-sm-3{margin-top:1rem !important}.mt-sm-4{margin-top:1.5rem !important}.mt-sm-5{margin-top:3rem !important}.mt-sm-auto{margin-top:auto !important}.me-sm-0{margin-right:0 !important}.me-sm-1{margin-right:.25rem !important}.me-sm-2{margin-right:.5rem !important}.me-sm-3{margin-right:1rem !important}.me-sm-4{margin-right:1.5rem !important}.me-sm-5{margin-right:3rem !important}.me-sm-auto{margin-right:auto !important}.mb-sm-0{margin-bottom:0 !important}.mb-sm-1{margin-bottom:.25rem !important}.mb-sm-2{margin-bottom:.5rem !important}.mb-sm-3{margin-bottom:1rem !important}.mb-sm-4{margin-bottom:1.5rem !important}.mb-sm-5{margin-bottom:3rem !important}.mb-sm-auto{margin-bottom:auto !important}.ms-sm-0{margin-left:0 !important}.ms-sm-1{margin-left:.25rem !important}.ms-sm-2{margin-left:.5rem !important}.ms-sm-3{margin-left:1rem !important}.ms-sm-4{margin-left:1.5rem !important}.ms-sm-5{margin-left:3rem !important}.ms-sm-auto{margin-left:auto !important}.m-sm-n1{margin:-.25rem !important}.m-sm-n2{margin:-.5rem !important}.m-sm-n3{margin:-1rem !important}.m-sm-n4{margin:-1.5rem !important}.m-sm-n5{margin:-3rem !important}.mx-sm-n1{margin-right:-.25rem !important;margin-left:-.25rem !important}.mx-sm-n2{margin-right:-.5rem !important;margin-left:-.5rem !important}.mx-sm-n3{margin-right:-1rem !important;margin-left:-1rem !important}.mx-sm-n4{margin-right:-1.5rem !important;margin-left:-1.5rem !important}.mx-sm-n5{margin-right:-3rem !important;margin-left:-3rem !important}.my-sm-n1{margin-top:-.25rem !important;margin-bottom:-.25rem !important}.my-sm-n2{margin-top:-.5rem !important;margin-bottom:-.5rem !important}.my-sm-n3{margin-top:-1rem !important;margin-bottom:-1rem !important}.my-sm-n4{margin-top:-1.5rem !important;margin-bottom:-1.5rem !important}.my-sm-n5{margin-top:-3rem !important;margin-bottom:-3rem !important}.mt-sm-n1{margin-top:-.25rem !important}.mt-sm-n2{margin-top:-.5rem !important}.mt-sm-n3{margin-top:-1rem !important}.mt-sm-n4{margin-top:-1.5rem !important}.mt-sm-n5{margin-top:-3rem !important}.me-sm-n1{margin-right:-.25rem !important}.me-sm-n2{margin-right:-.5rem !important}.me-sm-n3{margin-right:-1rem !important}.me-sm-n4{margin-right:-1.5rem !important}.me-sm-n5{margin-right:-3rem !important}.mb-sm-n1{margin-bottom:-.25rem !important}.mb-sm-n2{margin-bottom:-.5rem !important}.mb-sm-n3{margin-bottom:-1rem !important}.mb-sm-n4{margin-bottom:-1.5rem !important}.mb-sm-n5{margin-bottom:-3rem !important}.ms-sm-n1{margin-left:-.25rem !important}.ms-sm-n2{margin-left:-.5rem !important}.ms-sm-n3{margin-left:-1rem !important}.ms-sm-n4{margin-left:-1.5rem !important}.ms-sm-n5{margin-left:-3rem !important}.p-sm-0{padding:0 !important}.p-sm-1{padding:.25rem !important}.p-sm-2{padding:.5rem !important}.p-sm-3{padding:1rem !important}.p-sm-4{padding:1.5rem !important}.p-sm-5{padding:3rem !important}.px-sm-0{padding-right:0 !important;padding-left:0 !important}.px-sm-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-sm-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-sm-3{padding-right:1rem !important;padding-left:1rem !important}.px-sm-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-sm-5{padding-right:3rem !important;padding-left:3rem !important}.py-sm-0{padding-top:0 !important;padding-bottom:0 !important}.py-sm-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-sm-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-sm-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-sm-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-sm-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-sm-0{padding-top:0 !important}.pt-sm-1{padding-top:.25rem !important}.pt-sm-2{padding-top:.5rem !important}.pt-sm-3{padding-top:1rem !important}.pt-sm-4{padding-top:1.5rem !important}.pt-sm-5{padding-top:3rem !important}.pe-sm-0{padding-right:0 !important}.pe-sm-1{padding-right:.25rem !important}.pe-sm-2{padding-right:.5rem !important}.pe-sm-3{padding-right:1rem !important}.pe-sm-4{padding-right:1.5rem !important}.pe-sm-5{padding-right:3rem !important}.pb-sm-0{padding-bottom:0 !important}.pb-sm-1{padding-bottom:.25rem !important}.pb-sm-2{padding-bottom:.5rem !important}.pb-sm-3{padding-bottom:1rem !important}.pb-sm-4{padding-bottom:1.5rem !important}.pb-sm-5{padding-bottom:3rem !important}.ps-sm-0{padding-left:0 !important}.ps-sm-1{padding-left:.25rem !important}.ps-sm-2{padding-left:.5rem !important}.ps-sm-3{padding-left:1rem !important}.ps-sm-4{padding-left:1.5rem !important}.ps-sm-5{padding-left:3rem !important}.text-sm-start{text-align:left !important}.text-sm-end{text-align:right !important}.text-sm-center{text-align:center !important}}@media (min-width: 768px){.float-md-start{float:left !important}.float-md-end{float:right !important}.float-md-none{float:none !important}.d-md-inline{display:inline !important}.d-md-inline-block{display:inline-block !important}.d-md-block{display:block !important}.d-md-grid{display:grid !important}.d-md-table{display:table !important}.d-md-table-row{display:table-row !important}.d-md-table-cell{display:table-cell !important}.d-md-flex{display:flex !important}.d-md-inline-flex{display:inline-flex !important}.d-md-none{display:none !important}.flex-md-fill{flex:1 1 auto !important}.flex-md-row{flex-direction:row !important}.flex-md-column{flex-direction:column !important}.flex-md-row-reverse{flex-direction:row-reverse !important}.flex-md-column-reverse{flex-direction:column-reverse !important}.flex-md-grow-0{flex-grow:0 !important}.flex-md-grow-1{flex-grow:1 !important}.flex-md-shrink-0{flex-shrink:0 !important}.flex-md-shrink-1{flex-shrink:1 !important}.flex-md-wrap{flex-wrap:wrap !important}.flex-md-nowrap{flex-wrap:nowrap !important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-md-0{gap:0 !important}.gap-md-1{gap:.25rem !important}.gap-md-2{gap:.5rem !important}.gap-md-3{gap:1rem !important}.gap-md-4{gap:1.5rem !important}.gap-md-5{gap:3rem !important}.justify-content-md-start{justify-content:flex-start !important}.justify-content-md-end{justify-content:flex-end !important}.justify-content-md-center{justify-content:center !important}.justify-content-md-between{justify-content:space-between !important}.justify-content-md-around{justify-content:space-around !important}.justify-content-md-evenly{justify-content:space-evenly !important}.align-items-md-start{align-items:flex-start !important}.align-items-md-end{align-items:flex-end !important}.align-items-md-center{align-items:center !important}.align-items-md-baseline{align-items:baseline !important}.align-items-md-stretch{align-items:stretch !important}.align-content-md-start{align-content:flex-start !important}.align-content-md-end{align-content:flex-end !important}.align-content-md-center{align-content:center !important}.align-content-md-between{align-content:space-between !important}.align-content-md-around{align-content:space-around !important}.align-content-md-stretch{align-content:stretch !important}.align-self-md-auto{align-self:auto !important}.align-self-md-start{align-self:flex-start !important}.align-self-md-end{align-self:flex-end !important}.align-self-md-center{align-self:center !important}.align-self-md-baseline{align-self:baseline !important}.align-self-md-stretch{align-self:stretch !important}.order-md-first{order:-1 !important}.order-md-0{order:0 !important}.order-md-1{order:1 !important}.order-md-2{order:2 !important}.order-md-3{order:3 !important}.order-md-4{order:4 !important}.order-md-5{order:5 !important}.order-md-last{order:6 !important}.m-md-0{margin:0 !important}.m-md-1{margin:.25rem !important}.m-md-2{margin:.5rem !important}.m-md-3{margin:1rem !important}.m-md-4{margin:1.5rem !important}.m-md-5{margin:3rem !important}.m-md-auto{margin:auto !important}.mx-md-0{margin-right:0 !important;margin-left:0 !important}.mx-md-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-md-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-md-3{margin-right:1rem !important;margin-left:1rem !important}.mx-md-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-md-5{margin-right:3rem !important;margin-left:3rem !important}.mx-md-auto{margin-right:auto !important;margin-left:auto !important}.my-md-0{margin-top:0 !important;margin-bottom:0 !important}.my-md-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-md-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-md-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-md-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-md-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-md-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-md-0{margin-top:0 !important}.mt-md-1{margin-top:.25rem !important}.mt-md-2{margin-top:.5rem !important}.mt-md-3{margin-top:1rem !important}.mt-md-4{margin-top:1.5rem !important}.mt-md-5{margin-top:3rem !important}.mt-md-auto{margin-top:auto !important}.me-md-0{margin-right:0 !important}.me-md-1{margin-right:.25rem !important}.me-md-2{margin-right:.5rem !important}.me-md-3{margin-right:1rem !important}.me-md-4{margin-right:1.5rem !important}.me-md-5{margin-right:3rem !important}.me-md-auto{margin-right:auto !important}.mb-md-0{margin-bottom:0 !important}.mb-md-1{margin-bottom:.25rem !important}.mb-md-2{margin-bottom:.5rem !important}.mb-md-3{margin-bottom:1rem !important}.mb-md-4{margin-bottom:1.5rem !important}.mb-md-5{margin-bottom:3rem !important}.mb-md-auto{margin-bottom:auto !important}.ms-md-0{margin-left:0 !important}.ms-md-1{margin-left:.25rem !important}.ms-md-2{margin-left:.5rem !important}.ms-md-3{margin-left:1rem !important}.ms-md-4{margin-left:1.5rem !important}.ms-md-5{margin-left:3rem !important}.ms-md-auto{margin-left:auto !important}.m-md-n1{margin:-.25rem !important}.m-md-n2{margin:-.5rem !important}.m-md-n3{margin:-1rem !important}.m-md-n4{margin:-1.5rem !important}.m-md-n5{margin:-3rem !important}.mx-md-n1{margin-right:-.25rem !important;margin-left:-.25rem !important}.mx-md-n2{margin-right:-.5rem !important;margin-left:-.5rem !important}.mx-md-n3{margin-right:-1rem !important;margin-left:-1rem !important}.mx-md-n4{margin-right:-1.5rem !important;margin-left:-1.5rem !important}.mx-md-n5{margin-right:-3rem !important;margin-left:-3rem !important}.my-md-n1{margin-top:-.25rem !important;margin-bottom:-.25rem !important}.my-md-n2{margin-top:-.5rem !important;margin-bottom:-.5rem !important}.my-md-n3{margin-top:-1rem !important;margin-bottom:-1rem !important}.my-md-n4{margin-top:-1.5rem !important;margin-bottom:-1.5rem !important}.my-md-n5{margin-top:-3rem !important;margin-bottom:-3rem !important}.mt-md-n1{margin-top:-.25rem !important}.mt-md-n2{margin-top:-.5rem !important}.mt-md-n3{margin-top:-1rem !important}.mt-md-n4{margin-top:-1.5rem !important}.mt-md-n5{margin-top:-3rem !important}.me-md-n1{margin-right:-.25rem !important}.me-md-n2{margin-right:-.5rem !important}.me-md-n3{margin-right:-1rem !important}.me-md-n4{margin-right:-1.5rem !important}.me-md-n5{margin-right:-3rem !important}.mb-md-n1{margin-bottom:-.25rem !important}.mb-md-n2{margin-bottom:-.5rem !important}.mb-md-n3{margin-bottom:-1rem !important}.mb-md-n4{margin-bottom:-1.5rem !important}.mb-md-n5{margin-bottom:-3rem !important}.ms-md-n1{margin-left:-.25rem !important}.ms-md-n2{margin-left:-.5rem !important}.ms-md-n3{margin-left:-1rem !important}.ms-md-n4{margin-left:-1.5rem !important}.ms-md-n5{margin-left:-3rem !important}.p-md-0{padding:0 !important}.p-md-1{padding:.25rem !important}.p-md-2{padding:.5rem !important}.p-md-3{padding:1rem !important}.p-md-4{padding:1.5rem !important}.p-md-5{padding:3rem !important}.px-md-0{padding-right:0 !important;padding-left:0 !important}.px-md-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-md-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-md-3{padding-right:1rem !important;padding-left:1rem !important}.px-md-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-md-5{padding-right:3rem !important;padding-left:3rem !important}.py-md-0{padding-top:0 !important;padding-bottom:0 !important}.py-md-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-md-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-md-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-md-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-md-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-md-0{padding-top:0 !important}.pt-md-1{padding-top:.25rem !important}.pt-md-2{padding-top:.5rem !important}.pt-md-3{padding-top:1rem !important}.pt-md-4{padding-top:1.5rem !important}.pt-md-5{padding-top:3rem !important}.pe-md-0{padding-right:0 !important}.pe-md-1{padding-right:.25rem !important}.pe-md-2{padding-right:.5rem !important}.pe-md-3{padding-right:1rem !important}.pe-md-4{padding-right:1.5rem !important}.pe-md-5{padding-right:3rem !important}.pb-md-0{padding-bottom:0 !important}.pb-md-1{padding-bottom:.25rem !important}.pb-md-2{padding-bottom:.5rem !important}.pb-md-3{padding-bottom:1rem !important}.pb-md-4{padding-bottom:1.5rem !important}.pb-md-5{padding-bottom:3rem !important}.ps-md-0{padding-left:0 !important}.ps-md-1{padding-left:.25rem !important}.ps-md-2{padding-left:.5rem !important}.ps-md-3{padding-left:1rem !important}.ps-md-4{padding-left:1.5rem !important}.ps-md-5{padding-left:3rem !important}.text-md-start{text-align:left !important}.text-md-end{text-align:right !important}.text-md-center{text-align:center !important}}@media (min-width: 992px){.float-lg-start{float:left !important}.float-lg-end{float:right !important}.float-lg-none{float:none !important}.d-lg-inline{display:inline !important}.d-lg-inline-block{display:inline-block !important}.d-lg-block{display:block !important}.d-lg-grid{display:grid !important}.d-lg-table{display:table !important}.d-lg-table-row{display:table-row !important}.d-lg-table-cell{display:table-cell !important}.d-lg-flex{display:flex !important}.d-lg-inline-flex{display:inline-flex !important}.d-lg-none{display:none !important}.flex-lg-fill{flex:1 1 auto !important}.flex-lg-row{flex-direction:row !important}.flex-lg-column{flex-direction:column !important}.flex-lg-row-reverse{flex-direction:row-reverse !important}.flex-lg-column-reverse{flex-direction:column-reverse !important}.flex-lg-grow-0{flex-grow:0 !important}.flex-lg-grow-1{flex-grow:1 !important}.flex-lg-shrink-0{flex-shrink:0 !important}.flex-lg-shrink-1{flex-shrink:1 !important}.flex-lg-wrap{flex-wrap:wrap !important}.flex-lg-nowrap{flex-wrap:nowrap !important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-lg-0{gap:0 !important}.gap-lg-1{gap:.25rem !important}.gap-lg-2{gap:.5rem !important}.gap-lg-3{gap:1rem !important}.gap-lg-4{gap:1.5rem !important}.gap-lg-5{gap:3rem !important}.justify-content-lg-start{justify-content:flex-start !important}.justify-content-lg-end{justify-content:flex-end !important}.justify-content-lg-center{justify-content:center !important}.justify-content-lg-between{justify-content:space-between !important}.justify-content-lg-around{justify-content:space-around !important}.justify-content-lg-evenly{justify-content:space-evenly !important}.align-items-lg-start{align-items:flex-start !important}.align-items-lg-end{align-items:flex-end !important}.align-items-lg-center{align-items:center !important}.align-items-lg-baseline{align-items:baseline !important}.align-items-lg-stretch{align-items:stretch !important}.align-content-lg-start{align-content:flex-start !important}.align-content-lg-end{align-content:flex-end !important}.align-content-lg-center{align-content:center !important}.align-content-lg-between{align-content:space-between !important}.align-content-lg-around{align-content:space-around !important}.align-content-lg-stretch{align-content:stretch !important}.align-self-lg-auto{align-self:auto !important}.align-self-lg-start{align-self:flex-start !important}.align-self-lg-end{align-self:flex-end !important}.align-self-lg-center{align-self:center !important}.align-self-lg-baseline{align-self:baseline !important}.align-self-lg-stretch{align-self:stretch !important}.order-lg-first{order:-1 !important}.order-lg-0{order:0 !important}.order-lg-1{order:1 !important}.order-lg-2{order:2 !important}.order-lg-3{order:3 !important}.order-lg-4{order:4 !important}.order-lg-5{order:5 !important}.order-lg-last{order:6 !important}.m-lg-0{margin:0 !important}.m-lg-1{margin:.25rem !important}.m-lg-2{margin:.5rem !important}.m-lg-3{margin:1rem !important}.m-lg-4{margin:1.5rem !important}.m-lg-5{margin:3rem !important}.m-lg-auto{margin:auto !important}.mx-lg-0{margin-right:0 !important;margin-left:0 !important}.mx-lg-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-lg-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-lg-3{margin-right:1rem !important;margin-left:1rem !important}.mx-lg-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-lg-5{margin-right:3rem !important;margin-left:3rem !important}.mx-lg-auto{margin-right:auto !important;margin-left:auto !important}.my-lg-0{margin-top:0 !important;margin-bottom:0 !important}.my-lg-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-lg-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-lg-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-lg-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-lg-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-lg-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-lg-0{margin-top:0 !important}.mt-lg-1{margin-top:.25rem !important}.mt-lg-2{margin-top:.5rem !important}.mt-lg-3{margin-top:1rem !important}.mt-lg-4{margin-top:1.5rem !important}.mt-lg-5{margin-top:3rem !important}.mt-lg-auto{margin-top:auto !important}.me-lg-0{margin-right:0 !important}.me-lg-1{margin-right:.25rem !important}.me-lg-2{margin-right:.5rem !important}.me-lg-3{margin-right:1rem !important}.me-lg-4{margin-right:1.5rem !important}.me-lg-5{margin-right:3rem !important}.me-lg-auto{margin-right:auto !important}.mb-lg-0{margin-bottom:0 !important}.mb-lg-1{margin-bottom:.25rem !important}.mb-lg-2{margin-bottom:.5rem !important}.mb-lg-3{margin-bottom:1rem !important}.mb-lg-4{margin-bottom:1.5rem !important}.mb-lg-5{margin-bottom:3rem !important}.mb-lg-auto{margin-bottom:auto !important}.ms-lg-0{margin-left:0 !important}.ms-lg-1{margin-left:.25rem !important}.ms-lg-2{margin-left:.5rem !important}.ms-lg-3{margin-left:1rem !important}.ms-lg-4{margin-left:1.5rem !important}.ms-lg-5{margin-left:3rem !important}.ms-lg-auto{margin-left:auto !important}.m-lg-n1{margin:-.25rem !important}.m-lg-n2{margin:-.5rem !important}.m-lg-n3{margin:-1rem !important}.m-lg-n4{margin:-1.5rem !important}.m-lg-n5{margin:-3rem !important}.mx-lg-n1{margin-right:-.25rem !important;margin-left:-.25rem !important}.mx-lg-n2{margin-right:-.5rem !important;margin-left:-.5rem !important}.mx-lg-n3{margin-right:-1rem !important;margin-left:-1rem !important}.mx-lg-n4{margin-right:-1.5rem !important;margin-left:-1.5rem !important}.mx-lg-n5{margin-right:-3rem !important;margin-left:-3rem !important}.my-lg-n1{margin-top:-.25rem !important;margin-bottom:-.25rem !important}.my-lg-n2{margin-top:-.5rem !important;margin-bottom:-.5rem !important}.my-lg-n3{margin-top:-1rem !important;margin-bottom:-1rem !important}.my-lg-n4{margin-top:-1.5rem !important;margin-bottom:-1.5rem !important}.my-lg-n5{margin-top:-3rem !important;margin-bottom:-3rem !important}.mt-lg-n1{margin-top:-.25rem !important}.mt-lg-n2{margin-top:-.5rem !important}.mt-lg-n3{margin-top:-1rem !important}.mt-lg-n4{margin-top:-1.5rem !important}.mt-lg-n5{margin-top:-3rem !important}.me-lg-n1{margin-right:-.25rem !important}.me-lg-n2{margin-right:-.5rem !important}.me-lg-n3{margin-right:-1rem !important}.me-lg-n4{margin-right:-1.5rem !important}.me-lg-n5{margin-right:-3rem !important}.mb-lg-n1{margin-bottom:-.25rem !important}.mb-lg-n2{margin-bottom:-.5rem !important}.mb-lg-n3{margin-bottom:-1rem !important}.mb-lg-n4{margin-bottom:-1.5rem !important}.mb-lg-n5{margin-bottom:-3rem !important}.ms-lg-n1{margin-left:-.25rem !important}.ms-lg-n2{margin-left:-.5rem !important}.ms-lg-n3{margin-left:-1rem !important}.ms-lg-n4{margin-left:-1.5rem !important}.ms-lg-n5{margin-left:-3rem !important}.p-lg-0{padding:0 !important}.p-lg-1{padding:.25rem !important}.p-lg-2{padding:.5rem !important}.p-lg-3{padding:1rem !important}.p-lg-4{padding:1.5rem !important}.p-lg-5{padding:3rem !important}.px-lg-0{padding-right:0 !important;padding-left:0 !important}.px-lg-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-lg-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-lg-3{padding-right:1rem !important;padding-left:1rem !important}.px-lg-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-lg-5{padding-right:3rem !important;padding-left:3rem !important}.py-lg-0{padding-top:0 !important;padding-bottom:0 !important}.py-lg-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-lg-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-lg-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-lg-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-lg-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-lg-0{padding-top:0 !important}.pt-lg-1{padding-top:.25rem !important}.pt-lg-2{padding-top:.5rem !important}.pt-lg-3{padding-top:1rem !important}.pt-lg-4{padding-top:1.5rem !important}.pt-lg-5{padding-top:3rem !important}.pe-lg-0{padding-right:0 !important}.pe-lg-1{padding-right:.25rem !important}.pe-lg-2{padding-right:.5rem !important}.pe-lg-3{padding-right:1rem !important}.pe-lg-4{padding-right:1.5rem !important}.pe-lg-5{padding-right:3rem !important}.pb-lg-0{padding-bottom:0 !important}.pb-lg-1{padding-bottom:.25rem !important}.pb-lg-2{padding-bottom:.5rem !important}.pb-lg-3{padding-bottom:1rem !important}.pb-lg-4{padding-bottom:1.5rem !important}.pb-lg-5{padding-bottom:3rem !important}.ps-lg-0{padding-left:0 !important}.ps-lg-1{padding-left:.25rem !important}.ps-lg-2{padding-left:.5rem !important}.ps-lg-3{padding-left:1rem !important}.ps-lg-4{padding-left:1.5rem !important}.ps-lg-5{padding-left:3rem !important}.text-lg-start{text-align:left !important}.text-lg-end{text-align:right !important}.text-lg-center{text-align:center !important}}@media (min-width: 1200px){.float-xl-start{float:left !important}.float-xl-end{float:right !important}.float-xl-none{float:none !important}.d-xl-inline{display:inline !important}.d-xl-inline-block{display:inline-block !important}.d-xl-block{display:block !important}.d-xl-grid{display:grid !important}.d-xl-table{display:table !important}.d-xl-table-row{display:table-row !important}.d-xl-table-cell{display:table-cell !important}.d-xl-flex{display:flex !important}.d-xl-inline-flex{display:inline-flex !important}.d-xl-none{display:none !important}.flex-xl-fill{flex:1 1 auto !important}.flex-xl-row{flex-direction:row !important}.flex-xl-column{flex-direction:column !important}.flex-xl-row-reverse{flex-direction:row-reverse !important}.flex-xl-column-reverse{flex-direction:column-reverse !important}.flex-xl-grow-0{flex-grow:0 !important}.flex-xl-grow-1{flex-grow:1 !important}.flex-xl-shrink-0{flex-shrink:0 !important}.flex-xl-shrink-1{flex-shrink:1 !important}.flex-xl-wrap{flex-wrap:wrap !important}.flex-xl-nowrap{flex-wrap:nowrap !important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-xl-0{gap:0 !important}.gap-xl-1{gap:.25rem !important}.gap-xl-2{gap:.5rem !important}.gap-xl-3{gap:1rem !important}.gap-xl-4{gap:1.5rem !important}.gap-xl-5{gap:3rem !important}.justify-content-xl-start{justify-content:flex-start !important}.justify-content-xl-end{justify-content:flex-end !important}.justify-content-xl-center{justify-content:center !important}.justify-content-xl-between{justify-content:space-between !important}.justify-content-xl-around{justify-content:space-around !important}.justify-content-xl-evenly{justify-content:space-evenly !important}.align-items-xl-start{align-items:flex-start !important}.align-items-xl-end{align-items:flex-end !important}.align-items-xl-center{align-items:center !important}.align-items-xl-baseline{align-items:baseline !important}.align-items-xl-stretch{align-items:stretch !important}.align-content-xl-start{align-content:flex-start !important}.align-content-xl-end{align-content:flex-end !important}.align-content-xl-center{align-content:center !important}.align-content-xl-between{align-content:space-between !important}.align-content-xl-around{align-content:space-around !important}.align-content-xl-stretch{align-content:stretch !important}.align-self-xl-auto{align-self:auto !important}.align-self-xl-start{align-self:flex-start !important}.align-self-xl-end{align-self:flex-end !important}.align-self-xl-center{align-self:center !important}.align-self-xl-baseline{align-self:baseline !important}.align-self-xl-stretch{align-self:stretch !important}.order-xl-first{order:-1 !important}.order-xl-0{order:0 !important}.order-xl-1{order:1 !important}.order-xl-2{order:2 !important}.order-xl-3{order:3 !important}.order-xl-4{order:4 !important}.order-xl-5{order:5 !important}.order-xl-last{order:6 !important}.m-xl-0{margin:0 !important}.m-xl-1{margin:.25rem !important}.m-xl-2{margin:.5rem !important}.m-xl-3{margin:1rem !important}.m-xl-4{margin:1.5rem !important}.m-xl-5{margin:3rem !important}.m-xl-auto{margin:auto !important}.mx-xl-0{margin-right:0 !important;margin-left:0 !important}.mx-xl-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-xl-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-xl-3{margin-right:1rem !important;margin-left:1rem !important}.mx-xl-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-xl-5{margin-right:3rem !important;margin-left:3rem !important}.mx-xl-auto{margin-right:auto !important;margin-left:auto !important}.my-xl-0{margin-top:0 !important;margin-bottom:0 !important}.my-xl-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-xl-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-xl-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-xl-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-xl-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-xl-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-xl-0{margin-top:0 !important}.mt-xl-1{margin-top:.25rem !important}.mt-xl-2{margin-top:.5rem !important}.mt-xl-3{margin-top:1rem !important}.mt-xl-4{margin-top:1.5rem !important}.mt-xl-5{margin-top:3rem !important}.mt-xl-auto{margin-top:auto !important}.me-xl-0{margin-right:0 !important}.me-xl-1{margin-right:.25rem !important}.me-xl-2{margin-right:.5rem !important}.me-xl-3{margin-right:1rem !important}.me-xl-4{margin-right:1.5rem !important}.me-xl-5{margin-right:3rem !important}.me-xl-auto{margin-right:auto !important}.mb-xl-0{margin-bottom:0 !important}.mb-xl-1{margin-bottom:.25rem !important}.mb-xl-2{margin-bottom:.5rem !important}.mb-xl-3{margin-bottom:1rem !important}.mb-xl-4{margin-bottom:1.5rem !important}.mb-xl-5{margin-bottom:3rem !important}.mb-xl-auto{margin-bottom:auto !important}.ms-xl-0{margin-left:0 !important}.ms-xl-1{margin-left:.25rem !important}.ms-xl-2{margin-left:.5rem !important}.ms-xl-3{margin-left:1rem !important}.ms-xl-4{margin-left:1.5rem !important}.ms-xl-5{margin-left:3rem !important}.ms-xl-auto{margin-left:auto !important}.m-xl-n1{margin:-.25rem !important}.m-xl-n2{margin:-.5rem !important}.m-xl-n3{margin:-1rem !important}.m-xl-n4{margin:-1.5rem !important}.m-xl-n5{margin:-3rem !important}.mx-xl-n1{margin-right:-.25rem !important;margin-left:-.25rem !important}.mx-xl-n2{margin-right:-.5rem !important;margin-left:-.5rem !important}.mx-xl-n3{margin-right:-1rem !important;margin-left:-1rem !important}.mx-xl-n4{margin-right:-1.5rem !important;margin-left:-1.5rem !important}.mx-xl-n5{margin-right:-3rem !important;margin-left:-3rem !important}.my-xl-n1{margin-top:-.25rem !important;margin-bottom:-.25rem !important}.my-xl-n2{margin-top:-.5rem !important;margin-bottom:-.5rem !important}.my-xl-n3{margin-top:-1rem !important;margin-bottom:-1rem !important}.my-xl-n4{margin-top:-1.5rem !important;margin-bottom:-1.5rem !important}.my-xl-n5{margin-top:-3rem !important;margin-bottom:-3rem !important}.mt-xl-n1{margin-top:-.25rem !important}.mt-xl-n2{margin-top:-.5rem !important}.mt-xl-n3{margin-top:-1rem !important}.mt-xl-n4{margin-top:-1.5rem !important}.mt-xl-n5{margin-top:-3rem !important}.me-xl-n1{margin-right:-.25rem !important}.me-xl-n2{margin-right:-.5rem !important}.me-xl-n3{margin-right:-1rem !important}.me-xl-n4{margin-right:-1.5rem !important}.me-xl-n5{margin-right:-3rem !important}.mb-xl-n1{margin-bottom:-.25rem !important}.mb-xl-n2{margin-bottom:-.5rem !important}.mb-xl-n3{margin-bottom:-1rem !important}.mb-xl-n4{margin-bottom:-1.5rem !important}.mb-xl-n5{margin-bottom:-3rem !important}.ms-xl-n1{margin-left:-.25rem !important}.ms-xl-n2{margin-left:-.5rem !important}.ms-xl-n3{margin-left:-1rem !important}.ms-xl-n4{margin-left:-1.5rem !important}.ms-xl-n5{margin-left:-3rem !important}.p-xl-0{padding:0 !important}.p-xl-1{padding:.25rem !important}.p-xl-2{padding:.5rem !important}.p-xl-3{padding:1rem !important}.p-xl-4{padding:1.5rem !important}.p-xl-5{padding:3rem !important}.px-xl-0{padding-right:0 !important;padding-left:0 !important}.px-xl-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-xl-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-xl-3{padding-right:1rem !important;padding-left:1rem !important}.px-xl-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-xl-5{padding-right:3rem !important;padding-left:3rem !important}.py-xl-0{padding-top:0 !important;padding-bottom:0 !important}.py-xl-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-xl-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-xl-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-xl-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-xl-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-xl-0{padding-top:0 !important}.pt-xl-1{padding-top:.25rem !important}.pt-xl-2{padding-top:.5rem !important}.pt-xl-3{padding-top:1rem !important}.pt-xl-4{padding-top:1.5rem !important}.pt-xl-5{padding-top:3rem !important}.pe-xl-0{padding-right:0 !important}.pe-xl-1{padding-right:.25rem !important}.pe-xl-2{padding-right:.5rem !important}.pe-xl-3{padding-right:1rem !important}.pe-xl-4{padding-right:1.5rem !important}.pe-xl-5{padding-right:3rem !important}.pb-xl-0{padding-bottom:0 !important}.pb-xl-1{padding-bottom:.25rem !important}.pb-xl-2{padding-bottom:.5rem !important}.pb-xl-3{padding-bottom:1rem !important}.pb-xl-4{padding-bottom:1.5rem !important}.pb-xl-5{padding-bottom:3rem !important}.ps-xl-0{padding-left:0 !important}.ps-xl-1{padding-left:.25rem !important}.ps-xl-2{padding-left:.5rem !important}.ps-xl-3{padding-left:1rem !important}.ps-xl-4{padding-left:1.5rem !important}.ps-xl-5{padding-left:3rem !important}.text-xl-start{text-align:left !important}.text-xl-end{text-align:right !important}.text-xl-center{text-align:center !important}}@media (min-width: 1400px){.float-xxl-start{float:left !important}.float-xxl-end{float:right !important}.float-xxl-none{float:none !important}.d-xxl-inline{display:inline !important}.d-xxl-inline-block{display:inline-block !important}.d-xxl-block{display:block !important}.d-xxl-grid{display:grid !important}.d-xxl-table{display:table !important}.d-xxl-table-row{display:table-row !important}.d-xxl-table-cell{display:table-cell !important}.d-xxl-flex{display:flex !important}.d-xxl-inline-flex{display:inline-flex !important}.d-xxl-none{display:none !important}.flex-xxl-fill{flex:1 1 auto !important}.flex-xxl-row{flex-direction:row !important}.flex-xxl-column{flex-direction:column !important}.flex-xxl-row-reverse{flex-direction:row-reverse !important}.flex-xxl-column-reverse{flex-direction:column-reverse !important}.flex-xxl-grow-0{flex-grow:0 !important}.flex-xxl-grow-1{flex-grow:1 !important}.flex-xxl-shrink-0{flex-shrink:0 !important}.flex-xxl-shrink-1{flex-shrink:1 !important}.flex-xxl-wrap{flex-wrap:wrap !important}.flex-xxl-nowrap{flex-wrap:nowrap !important}.flex-xxl-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-xxl-0{gap:0 !important}.gap-xxl-1{gap:.25rem !important}.gap-xxl-2{gap:.5rem !important}.gap-xxl-3{gap:1rem !important}.gap-xxl-4{gap:1.5rem !important}.gap-xxl-5{gap:3rem !important}.justify-content-xxl-start{justify-content:flex-start !important}.justify-content-xxl-end{justify-content:flex-end !important}.justify-content-xxl-center{justify-content:center !important}.justify-content-xxl-between{justify-content:space-between !important}.justify-content-xxl-around{justify-content:space-around !important}.justify-content-xxl-evenly{justify-content:space-evenly !important}.align-items-xxl-start{align-items:flex-start !important}.align-items-xxl-end{align-items:flex-end !important}.align-items-xxl-center{align-items:center !important}.align-items-xxl-baseline{align-items:baseline !important}.align-items-xxl-stretch{align-items:stretch !important}.align-content-xxl-start{align-content:flex-start !important}.align-content-xxl-end{align-content:flex-end !important}.align-content-xxl-center{align-content:center !important}.align-content-xxl-between{align-content:space-between !important}.align-content-xxl-around{align-content:space-around !important}.align-content-xxl-stretch{align-content:stretch !important}.align-self-xxl-auto{align-self:auto !important}.align-self-xxl-start{align-self:flex-start !important}.align-self-xxl-end{align-self:flex-end !important}.align-self-xxl-center{align-self:center !important}.align-self-xxl-baseline{align-self:baseline !important}.align-self-xxl-stretch{align-self:stretch !important}.order-xxl-first{order:-1 !important}.order-xxl-0{order:0 !important}.order-xxl-1{order:1 !important}.order-xxl-2{order:2 !important}.order-xxl-3{order:3 !important}.order-xxl-4{order:4 !important}.order-xxl-5{order:5 !important}.order-xxl-last{order:6 !important}.m-xxl-0{margin:0 !important}.m-xxl-1{margin:.25rem !important}.m-xxl-2{margin:.5rem !important}.m-xxl-3{margin:1rem !important}.m-xxl-4{margin:1.5rem !important}.m-xxl-5{margin:3rem !important}.m-xxl-auto{margin:auto !important}.mx-xxl-0{margin-right:0 !important;margin-left:0 !important}.mx-xxl-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-xxl-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-xxl-3{margin-right:1rem !important;margin-left:1rem !important}.mx-xxl-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-xxl-5{margin-right:3rem !important;margin-left:3rem !important}.mx-xxl-auto{margin-right:auto !important;margin-left:auto !important}.my-xxl-0{margin-top:0 !important;margin-bottom:0 !important}.my-xxl-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-xxl-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-xxl-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-xxl-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-xxl-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-xxl-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-xxl-0{margin-top:0 !important}.mt-xxl-1{margin-top:.25rem !important}.mt-xxl-2{margin-top:.5rem !important}.mt-xxl-3{margin-top:1rem !important}.mt-xxl-4{margin-top:1.5rem !important}.mt-xxl-5{margin-top:3rem !important}.mt-xxl-auto{margin-top:auto !important}.me-xxl-0{margin-right:0 !important}.me-xxl-1{margin-right:.25rem !important}.me-xxl-2{margin-right:.5rem !important}.me-xxl-3{margin-right:1rem !important}.me-xxl-4{margin-right:1.5rem !important}.me-xxl-5{margin-right:3rem !important}.me-xxl-auto{margin-right:auto !important}.mb-xxl-0{margin-bottom:0 !important}.mb-xxl-1{margin-bottom:.25rem !important}.mb-xxl-2{margin-bottom:.5rem !important}.mb-xxl-3{margin-bottom:1rem !important}.mb-xxl-4{margin-bottom:1.5rem !important}.mb-xxl-5{margin-bottom:3rem !important}.mb-xxl-auto{margin-bottom:auto !important}.ms-xxl-0{margin-left:0 !important}.ms-xxl-1{margin-left:.25rem !important}.ms-xxl-2{margin-left:.5rem !important}.ms-xxl-3{margin-left:1rem !important}.ms-xxl-4{margin-left:1.5rem !important}.ms-xxl-5{margin-left:3rem !important}.ms-xxl-auto{margin-left:auto !important}.m-xxl-n1{margin:-.25rem !important}.m-xxl-n2{margin:-.5rem !important}.m-xxl-n3{margin:-1rem !important}.m-xxl-n4{margin:-1.5rem !important}.m-xxl-n5{margin:-3rem !important}.mx-xxl-n1{margin-right:-.25rem !important;margin-left:-.25rem !important}.mx-xxl-n2{margin-right:-.5rem !important;margin-left:-.5rem !important}.mx-xxl-n3{margin-right:-1rem !important;margin-left:-1rem !important}.mx-xxl-n4{margin-right:-1.5rem !important;margin-left:-1.5rem !important}.mx-xxl-n5{margin-right:-3rem !important;margin-left:-3rem !important}.my-xxl-n1{margin-top:-.25rem !important;margin-bottom:-.25rem !important}.my-xxl-n2{margin-top:-.5rem !important;margin-bottom:-.5rem !important}.my-xxl-n3{margin-top:-1rem !important;margin-bottom:-1rem !important}.my-xxl-n4{margin-top:-1.5rem !important;margin-bottom:-1.5rem !important}.my-xxl-n5{margin-top:-3rem !important;margin-bottom:-3rem !important}.mt-xxl-n1{margin-top:-.25rem !important}.mt-xxl-n2{margin-top:-.5rem !important}.mt-xxl-n3{margin-top:-1rem !important}.mt-xxl-n4{margin-top:-1.5rem !important}.mt-xxl-n5{margin-top:-3rem !important}.me-xxl-n1{margin-right:-.25rem !important}.me-xxl-n2{margin-right:-.5rem !important}.me-xxl-n3{margin-right:-1rem !important}.me-xxl-n4{margin-right:-1.5rem !important}.me-xxl-n5{margin-right:-3rem !important}.mb-xxl-n1{margin-bottom:-.25rem !important}.mb-xxl-n2{margin-bottom:-.5rem !important}.mb-xxl-n3{margin-bottom:-1rem !important}.mb-xxl-n4{margin-bottom:-1.5rem !important}.mb-xxl-n5{margin-bottom:-3rem !important}.ms-xxl-n1{margin-left:-.25rem !important}.ms-xxl-n2{margin-left:-.5rem !important}.ms-xxl-n3{margin-left:-1rem !important}.ms-xxl-n4{margin-left:-1.5rem !important}.ms-xxl-n5{margin-left:-3rem !important}.p-xxl-0{padding:0 !important}.p-xxl-1{padding:.25rem !important}.p-xxl-2{padding:.5rem !important}.p-xxl-3{padding:1rem !important}.p-xxl-4{padding:1.5rem !important}.p-xxl-5{padding:3rem !important}.px-xxl-0{padding-right:0 !important;padding-left:0 !important}.px-xxl-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-xxl-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-xxl-3{padding-right:1rem !important;padding-left:1rem !important}.px-xxl-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-xxl-5{padding-right:3rem !important;padding-left:3rem !important}.py-xxl-0{padding-top:0 !important;padding-bottom:0 !important}.py-xxl-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-xxl-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-xxl-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-xxl-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-xxl-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-xxl-0{padding-top:0 !important}.pt-xxl-1{padding-top:.25rem !important}.pt-xxl-2{padding-top:.5rem !important}.pt-xxl-3{padding-top:1rem !important}.pt-xxl-4{padding-top:1.5rem !important}.pt-xxl-5{padding-top:3rem !important}.pe-xxl-0{padding-right:0 !important}.pe-xxl-1{padding-right:.25rem !important}.pe-xxl-2{padding-right:.5rem !important}.pe-xxl-3{padding-right:1rem !important}.pe-xxl-4{padding-right:1.5rem !important}.pe-xxl-5{padding-right:3rem !important}.pb-xxl-0{padding-bottom:0 !important}.pb-xxl-1{padding-bottom:.25rem !important}.pb-xxl-2{padding-bottom:.5rem !important}.pb-xxl-3{padding-bottom:1rem !important}.pb-xxl-4{padding-bottom:1.5rem !important}.pb-xxl-5{padding-bottom:3rem !important}.ps-xxl-0{padding-left:0 !important}.ps-xxl-1{padding-left:.25rem !important}.ps-xxl-2{padding-left:.5rem !important}.ps-xxl-3{padding-left:1rem !important}.ps-xxl-4{padding-left:1.5rem !important}.ps-xxl-5{padding-left:3rem !important}.text-xxl-start{text-align:left !important}.text-xxl-end{text-align:right !important}.text-xxl-center{text-align:center !important}}@media (min-width: 1200px){.fs-1{font-size:2.5rem !important}.fs-2{font-size:2rem !important}.fs-3{font-size:1.75rem !important}.fs-4{font-size:1.5rem !important}}@media print{.d-print-inline{display:inline !important}.d-print-inline-block{display:inline-block !important}.d-print-block{display:block !important}.d-print-grid{display:grid !important}.d-print-table{display:table !important}.d-print-table-row{display:table-row !important}.d-print-table-cell{display:table-cell !important}.d-print-flex{display:flex !important}.d-print-inline-flex{display:inline-flex !important}.d-print-none{display:none !important}}@font-face{font-family:"Jost";font-style:normal;font-weight:400;font-display:swap;src:local("Jost"),url("fonts/vendor/jost/jost-v4-latin-regular.woff2") format("woff2"),url("fonts/vendor/jost/jost-v4-latin-regular.woff") format("woff");}@font-face{font-family:"Jost";font-style:normal;font-weight:500;font-display:swap;src:local("Jost"),url("fonts/vendor/jost/jost-v4-latin-500.woff2") format("woff2"),url("fonts/vendor/jost/jost-v4-latin-500.woff") format("woff");}@font-face{font-family:"Jost";font-style:normal;font-weight:700;font-display:swap;src:local("Jost"),url("fonts/vendor/jost/jost-v4-latin-700.woff2") format("woff2"),url("fonts/vendor/jost/jost-v4-latin-700.woff") format("woff");}@font-face{font-family:"Jost";font-style:italic;font-weight:400;font-display:swap;src:local("Jost"),url("fonts/vendor/jost/jost-v4-latin-italic.woff2") format("woff2"),url("fonts/vendor/jost/jost-v4-latin-italic.woff") format("woff");}@font-face{font-family:"Jost";font-style:italic;font-weight:500;font-display:swap;src:local("Jost"),url("fonts/vendor/jost/jost-v4-latin-500italic.woff2") format("woff2"),url("fonts/vendor/jost/jost-v4-latin-500italic.woff") format("woff");}@font-face{font-family:"Jost";font-style:italic;font-weight:700;font-display:swap;src:local("Jost"),url("fonts/vendor/jost/jost-v4-latin-700italic.woff2") format("woff2"),url("fonts/vendor/jost/jost-v4-latin-700italic.woff") format("woff");}.contributors .content,.blog .content,.page .content,.error404 .content,.docs.list .content,.tutorial.list .content,.showcase.list .content{padding-top:1rem;padding-bottom:3rem}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{margin:2rem 0 1rem}@media (min-width: 768px){body{font-size:1.125rem;padding-top:4rem !important}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{margin-bottom:1.125rem}}.home h1,.home .h1{font-size:calc(1.875rem + 1.5vw)}a:hover,a:focus{text-decoration:underline}a.btn:hover,.search-form a.search-submit:hover,a.btn:focus,.search-form a.search-submit:focus{text-decoration:none}.section{padding-top:5rem;padding-bottom:5rem}.section-md{padding-top:3rem;padding-bottom:3rem}.section-sm{padding-top:1rem;padding-bottom:1rem}body{padding-top:3.5625rem}.docs-sidebar{order:2}@media (min-width: 992px){.docs-sidebar{order:0;border-right:1px solid #e9ecef}@supports (position: -webkit-sticky) or (position: sticky){.docs-sidebar{position:-webkit-sticky;position:sticky;top:4rem;z-index:1000;height:calc(100vh - 4rem)}}}@media (min-width: 1200px){.docs-sidebar{flex:0 1 320px}}.docs-links{padding-bottom:5rem}@media (min-width: 992px){@supports (position: -webkit-sticky) or (position: sticky){.docs-links{max-height:calc(100vh - 4rem);overflow-y:scroll}}}@media (min-width: 992px){.docs-links{display:block;width:auto;margin-right:-1.5rem;padding-bottom:4rem}}.docs-toc{order:2}@supports (position: -webkit-sticky) or (position: sticky){.docs-toc{position:-webkit-sticky;position:sticky;top:4rem;height:calc(100vh - 4rem);overflow-y:auto}}.docs-content{padding-bottom:3rem;order:1}.docs-navigation,.blog-navigation{margin-top:2rem;margin-bottom:0;padding-top:2rem}.docs-navigation a,.blog-navigation a{font-size:.9rem}.docs-navigation{border-top:1px solid #e9ecef}@media (min-width: 992px){.docs-navigation,.blog-navigation{margin-bottom:-1rem}.docs-navigation a,.blog-navigation a{font-size:1rem}}.navbar a:hover,.navbar a:focus{text-decoration:none}#TableOfContents ul{padding-left:0;list-style:none}::selection{background:rgba(212,53,159,.2)}.bg-dots{background-image:radial-gradient(#dee2e6 15%, rgba(0,0,0,0) 15%);background-position:0 0;background-size:1rem 1rem;-webkit-mask:linear-gradient(to top, #fff, rgba(0,0,0,0));mask:linear-gradient(to top, #fff, rgba(0,0,0,0));width:100%;height:9rem;margin-top:-10rem;z-index:-1}.bg-dots-md{margin-top:-11rem}.bg-dots-lg{margin-top:-12rem}.gradient-text{background-color:#5d2f86;background-image:linear-gradient(90deg, #5d2f86, #8ed6fb 50%, #d32e9d);background-size:100%;background-repeat:repeat;-webkit-background-clip:text;-moz-background-clip:text;-webkit-text-fill-color:rgba(0,0,0,0);-moz-text-fill-color:rgba(0,0,0,0)}.katex{font-size:1.125rem}article hr{margin:3rem 0}body.dark{background:#212529;color:#dee2e6}body.dark a{color:#8ed6fb}body.dark a.text-body{color:#dee2e6 !important}body.dark .btn-primary{color:#1d2d35;background-color:#8ed6fb;border-color:#8ed6fb;color:#212529 !important}body.dark .btn-primary:hover{color:#1d2d35;background-color:#9fdcfc;border-color:#99dafb}.btn-check:focus+body.dark .btn-primary,body.dark .btn-primary:focus{color:#1d2d35;background-color:#9fdcfc;border-color:#99dafb;box-shadow:0 0 0 .25rem rgba(125,189,221,.5)}.btn-check:checked+body.dark .btn-primary,.btn-check:active+body.dark .btn-primary,body.dark .btn-primary:active,body.dark .btn-primary.active,.show>body.dark .btn-primary.dropdown-toggle{color:#1d2d35;background-color:#a5defc;border-color:#99dafb}.btn-check:checked+body.dark .btn-primary:focus,.btn-check:active+body.dark .btn-primary:focus,body.dark .btn-primary:active:focus,body.dark .btn-primary.active:focus,.show>body.dark .btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(125,189,221,.5)}body.dark .btn-primary:disabled,body.dark .btn-primary.disabled{color:#1d2d35;background-color:#8ed6fb;border-color:#8ed6fb}body.dark .btn-outline-primary{color:#8ed6fb;border-color:#8ed6fb;color:#8ed6fb}body.dark .btn-outline-primary:hover{color:#8ed6fb;background-color:#8ed6fb;border-color:#8ed6fb}.btn-check:focus+body.dark .btn-outline-primary,body.dark .btn-outline-primary:focus{box-shadow:0 0 0 .25rem rgba(142,214,251,.5)}.btn-check:checked+body.dark .btn-outline-primary,.btn-check:active+body.dark .btn-outline-primary,body.dark .btn-outline-primary:active,body.dark .btn-outline-primary.active,body.dark .btn-outline-primary.dropdown-toggle.show{color:#1d2d35;background-color:#8ed6fb;border-color:#8ed6fb}.btn-check:checked+body.dark .btn-outline-primary:focus,.btn-check:active+body.dark .btn-outline-primary:focus,body.dark .btn-outline-primary:active:focus,body.dark .btn-outline-primary.active:focus,body.dark .btn-outline-primary.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(142,214,251,.5)}body.dark .btn-outline-primary:disabled,body.dark .btn-outline-primary.disabled{color:#8ed6fb;background-color:rgba(0,0,0,0)}body.dark .btn-outline-primary:hover{color:#212529}body.dark .navbar{background:#212529;opacity:.975;border-bottom:1px solid #1b1f22}body.dark.home .navbar{border-bottom:0}body.dark .navbar-light .navbar-brand{color:#dee2e6 !important}body.dark .navbar-light .navbar-nav .nav-link,body.dark .navbar-light .navbar-nav .banner .nav a,.banner .nav body.dark .navbar-light .navbar-nav a{color:#dee2e6}body.dark .navbar-light .navbar-nav .nav-link:hover,body.dark .navbar-light .navbar-nav .banner .nav a:hover,.banner .nav body.dark .navbar-light .navbar-nav a:hover,body.dark .navbar-light .navbar-nav .nav-link:focus,body.dark .navbar-light .navbar-nav .banner .nav a:focus,.banner .nav body.dark .navbar-light .navbar-nav a:focus{color:#8ed6fb}body.dark .navbar-light .navbar-nav .nav-link.disabled,body.dark .navbar-light .navbar-nav .banner .nav a.disabled,.banner .nav body.dark .navbar-light .navbar-nav a.disabled{color:rgba(255,255,255,.25)}body.dark .navbar-light .navbar-nav .show>.nav-link,body.dark .navbar-light .navbar-nav .banner .nav .show>a,.banner .nav body.dark .navbar-light .navbar-nav .show>a,body.dark .navbar-light .navbar-nav .active>.nav-link,body.dark .navbar-light .navbar-nav .banner .nav .active>a,.banner .nav body.dark .navbar-light .navbar-nav .active>a,body.dark .navbar-light .navbar-nav .nav-link.show,body.dark .navbar-light .navbar-nav .banner .nav a.show,.banner .nav body.dark .navbar-light .navbar-nav a.show,body.dark .navbar-light .navbar-nav .nav-link.active,body.dark .navbar-light .navbar-nav .banner .nav a.active,.banner .nav body.dark .navbar-light .navbar-nav a.active{color:#8ed6fb}body.dark .navbar-light .navbar-text{color:#dee2e6}body.dark .alert-primary a{color:#212529}body.dark .alert-warning{background:#1b1f22;color:#dee2e6}body.dark .page-links a{color:#dee2e6}body.dark .showcase-meta a{color:#dee2e6}body.dark .showcase-meta a:hover,body.dark .showcase-meta a:focus{color:#8ed6fb}body.dark .docs-link:hover,body.dark .docs-link.active,body.dark .page-links a:hover{text-decoration:none;color:#8ed6fb}body.dark .navbar-light .navbar-text a{color:#8ed6fb}body.dark .docs-links h3.sidebar-link a,body.dark .docs-links .sidebar-link.h3 a,body.dark .page-links h3.sidebar-link a,body.dark .page-links .sidebar-link.h3 a{color:#dee2e6}body.dark .navbar-light .navbar-text a:hover,body.dark .navbar-light .navbar-text a:focus{color:#8ed6fb}body.dark .navbar .btn-link{color:#dee2e6}body.dark .content .btn-link{color:#8ed6fb}body.dark .content .btn-link:hover{color:#8ed6fb}body.dark .navbar .btn-link:hover{color:#8ed6fb}body.dark .navbar .btn-link:active{color:#8ed6fb}body.dark .form-control.is-search,body.dark .search-form .is-search.search-field,.search-form body.dark .is-search.search-field,body.dark .comment-form input.is-search[type=text],.comment-form body.dark input.is-search[type=text],body.dark .comment-form input.is-search[type=email],.comment-form body.dark input.is-search[type=email],body.dark .comment-form input.is-search[type=url],.comment-form body.dark input.is-search[type=url],body.dark .comment-form textarea.is-search,.comment-form body.dark textarea.is-search{background:#1b1f22;}body.dark .navbar-form::after{color:#6c757d;border:1px solid #343a40}body.dark .form-control,body.dark .search-form .search-field,.search-form body.dark .search-field,body.dark .comment-form input[type=text],.comment-form body.dark input[type=text],body.dark .comment-form input[type=email],.comment-form body.dark input[type=email],body.dark .comment-form input[type=url],.comment-form body.dark input[type=url],body.dark .comment-form textarea,.comment-form body.dark textarea{color:#adb5bd}body.dark .form-control:focus,body.dark .search-form .search-field:focus,.search-form body.dark .search-field:focus,body.dark .comment-form input[type=text]:focus,.comment-form body.dark input[type=text]:focus,body.dark .comment-form input[type=email]:focus,.comment-form body.dark input[type=email]:focus,body.dark .comment-form input[type=url]:focus,.comment-form body.dark input[type=url]:focus,body.dark .comment-form textarea:focus,.comment-form body.dark textarea:focus{box-shadow:0 0 0 .2rem #9adafb}body.dark .border-top{border-top:1px solid #1b1f22 !important}@media (min-width: 992px){body.dark .docs-sidebar{order:0;border-right:1px solid #1b1f22}}body.dark .docs-navigation{border-top:1px solid #1b1f22}body.dark pre code::-webkit-scrollbar-thumb{background:#1b1f22}body.dark pre:not(.hljs){background:#1b1f22;color:#dee2e6}body.dark pre code:hover{scrollbar-width:thin;scrollbar-color:#1b1f22 rgba(0,0,0,0)}body.dark pre code::-webkit-scrollbar-thumb:hover{background:#1b1f22}body.dark blockquote{border-left:3px solid #1b1f22}body.dark .footer{border-top:1px solid #1b1f22}body.dark .docs-links,body.dark .docs-toc{scrollbar-width:thin;scrollbar-color:#212529 #212529}body.dark .docs-links::-webkit-scrollbar,body.dark .docs-toc::-webkit-scrollbar{width:5px}body.dark .docs-links::-webkit-scrollbar-track,body.dark .docs-toc::-webkit-scrollbar-track{background:#212529}body.dark .docs-links::-webkit-scrollbar-thumb,body.dark .docs-toc::-webkit-scrollbar-thumb{background:#212529}body.dark .docs-links:hover,body.dark .docs-toc:hover{scrollbar-width:thin;scrollbar-color:#1b1f22 #212529}body.dark .docs-links:hover::-webkit-scrollbar-thumb,body.dark .docs-toc:hover::-webkit-scrollbar-thumb{background:#1b1f22}body.dark .docs-links::-webkit-scrollbar-thumb:hover,body.dark .docs-toc::-webkit-scrollbar-thumb:hover{background:#1b1f22}body.dark .docs-links h3:not(:first-child),body.dark .docs-links .h3:not(:first-child){border-top:1px solid #1b1f22}body.dark a.docs-link{color:#dee2e6}body.dark .page-links li:not(:first-child){border-top:1px dashed #1b1f22}body.dark .card{background:#212529;border:1px solid #1b1f22}body.dark .card.bg-light{background:#1b1f22 !important}body.dark .navbar .menu-icon .navicon{background:#dee2e6}body.dark .navbar .menu-icon .navicon::before,body.dark .navbar .menu-icon .navicon::after{background:#dee2e6}body.dark .logo-light{display:none !important}body.dark .logo-dark{display:inline-block !important}body.dark .bg-light{background:#1e2125 !important}body.dark .bg-dots{background-image:radial-gradient(#556370 15%, rgba(0,0,0,0) 15%)}body.dark .text-muted{color:#c8cfd6 !important}body.dark .alert-primary{background:#8ed6fb;color:#212529}body.dark .figure-caption{color:#dee2e6}body.dark .copy-status::after{content:"Copy";display:block;color:#dee2e6}body.dark .copy-status:hover::after{content:"Copy";display:block;color:#8ed6fb}body.dark .copy-status:focus::after,body.dark .copy-status:active::after{content:"Copied";display:block;color:#8ed6fb}.hljs{display:block;overflow-x:auto;padding:.5em;background:#fbf7f0;color:#1d2d35}.hljs-string,.hljs-variable,.hljs-template-variable,.hljs-symbol,.hljs-bullet,.hljs-section,.hljs-addition,.hljs-attribute,.hljs-link{color:#d32e9d}.hljs-comment,.hljs-quote,.hljs-meta,.hljs-deletion{color:#888}.hljs-keyword,.hljs-selector-tag,.hljs-section,.hljs-name,.hljs-type,.hljs-strong{font-weight:bold}.hljs-emphasis{font-style:italic}body.dark .hljs{background:#1b1f22;color:#dee2e6}body.dark .hljs-string,body.dark .hljs-variable,body.dark .hljs-template-variable,body.dark .hljs-symbol,body.dark .hljs-bullet,body.dark .hljs-section,body.dark .hljs-addition,body.dark .hljs-attribute,body.dark .hljs-link{color:#8ed6fb}pre,code,kbd,samp{font-family:sfmono-regular,menlo,monaco,consolas,"Liberation Mono","Courier New",monospace;font-size:.875rem;border-radius:.25rem}code{padding:.25rem .5rem}pre{background:#fbf7f0;color:#1d2d35;margin:2rem 0}pre code{display:block;overflow-x:auto;line-height:1.5;padding:1.25rem 1.5rem;tab-size:4;scrollbar-width:thin;scrollbar-color:rgba(0,0,0,0) rgba(0,0,0,0)}.hljs{padding:1.25rem 1.5rem}@media (max-width: 575.98px){pre,code,kbd,samp{border-radius:0}pre{margin:2rem -1.5rem}}pre code::-webkit-scrollbar{height:5px}pre code::-webkit-scrollbar-thumb{background:#e9ecef}pre code:hover{scrollbar-width:thin;scrollbar-color:#e9ecef rgba(0,0,0,0)}pre code::-webkit-scrollbar-thumb:hover{background:#e9ecef}.alert{font-family:sfmono-regular,menlo,monaco,consolas,"Liberation Mono","Courier New",monospace;font-size:.875rem}.alert-icon{margin-right:.75rem}.docs .alert{margin:2rem -1.5rem}.alert .alert-link{text-decoration:underline}.alert-dark{color:#fff;background-color:#1d2d35}.alert-dark .alert-link{color:#fff}.alert-light{color:#1d2d35}.alert-warning{background:#fbf7f0;color:#1d2d35}.alert-white{background-color:rgba(255,255,255,.95)}.alert-primary{color:#fff;background-color:#5d2f86}.alert-primary .alert-link{color:#fff}.alert .alert-link:hover,.alert .alert-link:focus{text-decoration:none}.navbar .btn-link{color:#1d2d35;padding:.4375rem 0}#mode{margin-right:1.25rem}.btn-link:focus{outline:0;box-shadow:none}#navigation{margin-left:1.25rem}@media (min-width: 768px){#mode{margin-right:.5rem}.navbar .btn-link{padding:.5625em .25rem .5rem .125rem}}.navbar .btn-link:hover{color:#5d2f86}.navbar .btn-link:active{color:#5d2f86}body .toggle-dark{display:block}body .toggle-light{display:none}body.dark .toggle-light{display:block}body.dark .toggle-dark{display:none}.btn-clipboard{display:none}@media (min-width: 768px){.doks-clipboard{position:relative;float:right}.btn-clipboard{position:absolute;top:1rem;right:.25rem;z-index:10;display:block;padding:.25rem .5rem;font-size:.875rem}}.copy-status::after{content:"Copy";display:block;color:#1d2d35}.copy-status:hover::after{content:"Copy";display:block;color:#d32e9d}.copy-status:focus::after,.copy-status:active::after{content:"Copied";display:block;color:#d32e9d}.comment-list ol{list-style:none}blockquote{margin-bottom:1rem;font-size:1.25rem;border-left:3px solid #dee2e6;padding-left:1rem}.footnote-definition sup{top:-.2 .5em;font-size:.75em;display:inline}.footnote-definition p{display:inline}.search-form label{font-weight:normal}figure{margin:2rem 0}.figure-caption{margin:.25rem 0 .75rem}figure.wide{margin:2rem -1.5rem}figure.wide .figure-caption{margin:.25rem 1.5rem .75rem}@media (min-width: 768px){figure.wide{margin:2rem -2.5rem}figure.wide .figure-caption{margin:.25rem 2.5rem .75rem}}@media (min-width: 992px){figure.wide{margin:2rem -5rem}figure.wide .figure-caption{margin:.25rem 5rem .75rem}}.blur-up{filter:blur(5px)}.blur-up.lazyloaded{filter:unset}.img-simple{margin-top:.375rem;margin-bottom:1.25rem}.navbar-form{position:relative}#suggestions{position:absolute;right:0;margin-top:.5rem;width:calc(100vw - 3rem);max-height:500px;overflow:auto}#suggestions a{display:block;text-decoration:none;padding:.75rem;margin:0 .5rem}#suggestions a:focus{background:#f8f9fa;outline:0}#suggestions div:not(:first-child){border-top:1px dashed #e9ecef}#suggestions div:first-child{margin-top:.5rem}#suggestions div:last-child{margin-bottom:.5rem}#suggestions a:hover{background:#f8f9fa}#suggestions span{font-size:1rem}#suggestions span:first-child{font-weight:700;color:#1d2d35}#suggestions span:nth-child(2){color:#495057}@media (min-width: 576px){#suggestions{width:30rem}#suggestions a{display:flex}#suggestions span:first-child{width:9rem;padding-right:1rem;border-right:1px solid #e9ecef;display:inline-block;text-align:right}#suggestions span:nth-child(2){width:19rem;padding-left:1rem}}table{margin:3rem 0}.footer{border-top:1px solid #e9ecef;padding-top:1.125rem;padding-bottom:1.125rem}.footer ul{margin-bottom:0}.footer li{font-size:.875rem;margin-bottom:0}@media (min-width: 768px){.footer li{font-size:1rem}}.navbar-text{margin-left:1rem}.navbar-brand{font-weight:700}.navbar-light .navbar-brand,.navbar-light .navbar-brand:hover,.navbar-light .navbar-brand:active{color:#1d2d35}.navbar-light .navbar-nav .active .nav-link,.navbar-light .navbar-nav .active .banner .nav a,.banner .nav .navbar-light .navbar-nav .active a{color:#5d2f86}@media (min-width: 768px){.navbar-brand{font-size:1.375rem}.navbar-text{margin-left:1.25rem}}.navbar-nav{flex-direction:row}.nav-item,.banner .nav li{margin-left:1.25rem}@media (min-width: 768px){.nav-item,.banner .nav li{margin-left:.5rem}}@media (max-width: 575.98px){.nav-item:first-child,.banner .nav li:first-child{margin-left:0}}@media (max-width: 767.98px){.navbar .container{padding-left:1.5rem;padding-right:1.5rem}}.break{flex-basis:100%;height:0}.navbar{background-color:rgba(255,255,255,.95);border-bottom:1px solid #e9ecef;margin-top:4px}.header-bar{border-top:4px solid;border-image-source:linear-gradient(90deg, #5d2f86, #8ed6fb 50%, #d32e9d);border-image-slice:1}.home .navbar{border-bottom:0}.navbar-form{position:relative;margin-top:.25rem}@media (min-width: 768px){.navbar-brand{margin-right:1rem !important}.main-nav .nav-item:first-child .nav-link,.main-nav .banner .nav li:first-child .nav-link,.banner .nav .main-nav li:first-child .nav-link,.main-nav .nav-item:first-child .banner .nav a,.banner .nav .main-nav .nav-item:first-child a,.main-nav .banner .nav li:first-child a,.banner .nav .main-nav li:first-child a,.fork-me .nav-item:first-child .nav-link,.fork-me .banner .nav li:first-child .nav-link,.banner .nav .fork-me li:first-child .nav-link,.fork-me .nav-item:first-child .banner .nav a,.banner .nav .fork-me .nav-item:first-child a,.fork-me .banner .nav li:first-child a,.banner .nav .fork-me li:first-child a{padding-left:0}.main-nav .nav-item:last-child .nav-link,.main-nav .banner .nav li:last-child .nav-link,.banner .nav .main-nav li:last-child .nav-link,.main-nav .nav-item:last-child .banner .nav a,.banner .nav .main-nav .nav-item:last-child a,.main-nav .banner .nav li:last-child a,.banner .nav .main-nav li:last-child a,.fork-me .nav-item:last-child .nav-link,.fork-me .banner .nav li:last-child .nav-link,.banner .nav .fork-me li:last-child .nav-link,.fork-me .nav-item:last-child .banner .nav a,.banner .nav .fork-me .nav-item:last-child a,.fork-me .banner .nav li:last-child a,.banner .nav .fork-me li:last-child a{padding-right:0}.navbar-form{margin-top:0;margin-left:6rem;margin-right:1.5rem}}@media (min-width: 992px){.navbar-form{margin-left:15rem}}@media (min-width: 1200px){.navbar-form{margin-left:30rem}}.form-control.is-search,.comment-form input.is-search[type=text],.comment-form input.is-search[type=email],.comment-form input.is-search[type=url],.comment-form textarea.is-search,.search-form .is-search.search-field{padding-right:2.5rem;background:#f8f9fa;border:0;}.navbar-form::after{position:absolute;top:.4625rem;right:.5375rem;display:flex;align-items:center;justify-content:center;height:1.5rem;padding-right:.4375rem;padding-left:.4375rem;font-size:.75rem;color:#495057;content:"/";border:1px solid #dee2e6;border-radius:.25rem}/*! purgecss start ignore */.algolia-autocomplete{display:flex !important}.algolia-autocomplete .ds-dropdown-menu{box-shadow:0 .5rem 1rem rgba(0,0,0,.15) !important}@media (max-width: 575.98px){.algolia-autocomplete .ds-dropdown-menu{max-width:512px !important;min-width:312px !important;width:auto !important}.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column::after{content:"|";margin-right:.25rem}}.algolia-autocomplete .algolia-docsearch-suggestion--title{margin-bottom:0}.algolia-autocomplete .algolia-docsearch-suggestion--highlight{padding:0 .05em}.algolia-autocomplete .algolia-docsearch-footer{margin-top:1rem;margin-right:.5rem;margin-bottom:.5rem}/*! purgecss end ignore */.navbar .menu-icon{cursor:pointer;padding:1.125rem .625rem;margin:0 0 0 -.625rem;user-select:none}.navbar .menu-icon .navicon{background:#1d2d35;display:block;height:2px;position:relative;transition:background .2s ease-out;width:18px}.navbar .menu-icon .navicon::before,.navbar .menu-icon .navicon::after{background:#1d2d35;content:"";display:block;height:100%;position:absolute;transition:all .2s ease-out;width:100%}.navbar .menu-icon .navicon::before{top:5px}.navbar .menu-icon .navicon::after{top:-5px}.navbar .menu-btn{display:none}.navbar .menu-btn:checked~.navbar-collapse{display:block;max-height:100vh}.navbar .menu-btn:checked~.menu-icon .navicon{background:rgba(0,0,0,0)}.navbar .menu-btn:checked~.menu-icon .navicon::before{transform:rotate(-45deg)}.navbar .menu-btn:checked~.menu-icon .navicon::after{transform:rotate(45deg)}.navbar .menu-btn:checked~.menu-icon:not(.steps) .navicon::before,.navbar .menu-btn:checked~.menu-icon:not(.steps) .navicon::after{top:0}.docs-content>h2[id]::before,.docs-content>[id].h2::before,.docs-content>h3[id]::before,.docs-content>[id].h3::before,.docs-content>h4[id]::before,.docs-content>[id].h4::before{display:block;height:6rem;margin-top:-6rem;content:""}.anchor{visibility:hidden;padding-left:.5rem}h1:hover a,.h1:hover a,h2:hover a,.h2:hover a,h3:hover a,.h3:hover a,h4:hover a,.h4:hover a{visibility:visible;text-decoration:none}.card-list{margin-top:2.25rem}.edit-page{margin-top:3rem;font-size:1rem}.edit-page svg{margin-right:.5rem;margin-bottom:.25rem}p.meta{margin-top:.5rem;font-size:1rem}.breadcrumb{margin-top:2.25rem;font-size:1rem}.page-header{text-align:center;margin-bottom:2rem}.home .card,.contributors.list .card,.blog.list .card{margin-top:2rem;margin-bottom:2rem;transition:transform .3s}.home .card:hover,.contributors.list .card:hover,.blog.list .card:hover{transform:scale(1.025)}.home .card-body,.contributors.list .card-body,.blog.list .card-body{padding:0 2rem 1rem}.blog-header{text-align:center;margin-bottom:2rem}.blog-footer{text-align:center}.docs-links,.docs-toc{scrollbar-width:thin;scrollbar-color:#fff #fff}.docs-links::-webkit-scrollbar,.docs-toc::-webkit-scrollbar{width:5px}.docs-links::-webkit-scrollbar-track,.docs-toc::-webkit-scrollbar-track{background:#fff}.docs-links::-webkit-scrollbar-thumb,.docs-toc::-webkit-scrollbar-thumb{background:#fff}.docs-links:hover,.docs-toc:hover{scrollbar-width:thin;scrollbar-color:#e9ecef #fff}.docs-links:hover::-webkit-scrollbar-thumb,.docs-toc:hover::-webkit-scrollbar-thumb{background:#e9ecef}.docs-links::-webkit-scrollbar-thumb:hover,.docs-toc::-webkit-scrollbar-thumb:hover{background:#e9ecef}.docs-links h3,.docs-links .h3,.page-links h3,.page-links .h3{text-transform:uppercase;font-size:1rem;margin:1.25rem 0 .5rem 0;padding:1.5rem 0 0 0}@media (min-width: 992px){.docs-links h3,.docs-links .h3,.page-links h3,.page-links .h3{margin:1.125rem 1.5rem .75rem 0;padding:1.375rem 0 0 0}}.docs-links h3:not(:first-child),.docs-links .h3:not(:first-child){border-top:1px solid #e9ecef}a.docs-link{color:#1d2d35;display:block;padding:.125rem 0;font-size:1rem}.page-links li{margin-top:.375rem;padding-top:.375rem}.page-links ul ul li{border-top:none;padding-left:1rem;margin-top:.125rem;padding-top:.125rem}.page-links li:not(:first-child){border-top:1px dashed #e9ecef}.page-links a{color:#1d2d35;display:block;padding:.125rem 0;font-size:.9375rem}.docs-link:hover,.docs-link.active,.page-links a:hover{text-decoration:none;color:#5d2f86}.docs-links h3.sidebar-link,.docs-links .sidebar-link.h3,.page-links h3.sidebar-link,.page-links .sidebar-link.h3{text-transform:none;font-size:1.125rem;font-weight:normal}.docs-links h3.sidebar-link a,.docs-links .sidebar-link.h3 a,.page-links h3.sidebar-link a,.page-links .sidebar-link.h3 a{color:#1d2d35}.docs-links h3.sidebar-link a:hover,.docs-links .sidebar-link.h3 a:hover,.page-links h3.sidebar-link a:hover,.page-links .sidebar-link.h3 a:hover{text-decoration:underline}main img{max-width:100%;height:auto} \ No newline at end of file diff --git a/plugins/elasticlunr.min.js b/plugins/elasticlunr.min.js new file mode 100644 index 0000000000..94b20dd2ef --- /dev/null +++ b/plugins/elasticlunr.min.js @@ -0,0 +1,10 @@ +/** + * elasticlunr - http://weixsong.github.io + * Lightweight full-text search engine in Javascript for browser search and offline search. - 0.9.5 + * + * Copyright (C) 2017 Oliver Nightingale + * Copyright (C) 2017 Wei Song + * MIT Licensed + * @license + */ +!function(){function e(e){if(null===e||"object"!=typeof e)return e;var t=e.constructor();for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.9.5",lunr=t,t.utils={},t.utils.warn=function(e){return function(t){e.console&&console.warn&&console.warn(t)}}(this),t.utils.toString=function(e){return void 0===e||null===e?"":e.toString()},t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var e=Array.prototype.slice.call(arguments),t=e.pop(),n=e;if("function"!=typeof t)throw new TypeError("last argument must be a function");n.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},t.EventEmitter.prototype.removeListener=function(e,t){if(this.hasHandler(e)){var n=this.events[e].indexOf(t);-1!==n&&(this.events[e].splice(n,1),0==this.events[e].length&&delete this.events[e])}},t.EventEmitter.prototype.emit=function(e){if(this.hasHandler(e)){var t=Array.prototype.slice.call(arguments,1);this.events[e].forEach(function(e){e.apply(void 0,t)},this)}},t.EventEmitter.prototype.hasHandler=function(e){return e in this.events},t.tokenizer=function(e){if(!arguments.length||null===e||void 0===e)return[];if(Array.isArray(e)){var n=e.filter(function(e){return null===e||void 0===e?!1:!0});n=n.map(function(e){return t.utils.toString(e).toLowerCase()});var i=[];return n.forEach(function(e){var n=e.split(t.tokenizer.seperator);i=i.concat(n)},this),i}return e.toString().trim().toLowerCase().split(t.tokenizer.seperator)},t.tokenizer.defaultSeperator=/[\s\-]+/,t.tokenizer.seperator=t.tokenizer.defaultSeperator,t.tokenizer.setSeperator=function(e){null!==e&&void 0!==e&&"object"==typeof e&&(t.tokenizer.seperator=e)},t.tokenizer.resetSeperator=function(){t.tokenizer.seperator=t.tokenizer.defaultSeperator},t.tokenizer.getSeperator=function(){return t.tokenizer.seperator},t.Pipeline=function(){this._queue=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in t.Pipeline.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[n]=e},t.Pipeline.getRegisteredFunction=function(e){return e in t.Pipeline.registeredFunctions!=!0?null:t.Pipeline.registeredFunctions[e]},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.getRegisteredFunction(e);if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i+1,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i,0,n)},t.Pipeline.prototype.remove=function(e){var t=this._queue.indexOf(e);-1!==t&&this._queue.splice(t,1)},t.Pipeline.prototype.run=function(e){for(var t=[],n=e.length,i=this._queue.length,o=0;n>o;o++){for(var r=e[o],s=0;i>s&&(r=this._queue[s](r,o,e),void 0!==r&&null!==r);s++);void 0!==r&&null!==r&&t.push(r)}return t},t.Pipeline.prototype.reset=function(){this._queue=[]},t.Pipeline.prototype.get=function(){return this._queue},t.Pipeline.prototype.toJSON=function(){return this._queue.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.DocumentStore,this.index={},this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var e=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,e)},t.Index.prototype.off=function(e,t){return this.eventEmitter.removeListener(e,t)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;n._fields=e.fields,n._ref=e.ref,n.documentStore=t.DocumentStore.load(e.documentStore),n.pipeline=t.Pipeline.load(e.pipeline),n.index={};for(var i in e.index)n.index[i]=t.InvertedIndex.load(e.index[i]);return n},t.Index.prototype.addField=function(e){return this._fields.push(e),this.index[e]=new t.InvertedIndex,this},t.Index.prototype.setRef=function(e){return this._ref=e,this},t.Index.prototype.saveDocument=function(e){return this.documentStore=new t.DocumentStore(e),this},t.Index.prototype.addDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.addDoc(i,e),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));this.documentStore.addFieldLength(i,n,o.length);var r={};o.forEach(function(e){e in r?r[e]+=1:r[e]=1},this);for(var s in r){var u=r[s];u=Math.sqrt(u),this.index[n].addToken(s,{ref:i,tf:u})}},this),n&&this.eventEmitter.emit("add",e,this)}},t.Index.prototype.removeDocByRef=function(e){if(e&&this.documentStore.isDocStored()!==!1&&this.documentStore.hasDoc(e)){var t=this.documentStore.getDoc(e);this.removeDoc(t,!1)}},t.Index.prototype.removeDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.hasDoc(i)&&(this.documentStore.removeDoc(i),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));o.forEach(function(e){this.index[n].removeToken(e,i)},this)},this),n&&this.eventEmitter.emit("remove",e,this))}},t.Index.prototype.updateDoc=function(e,t){var t=void 0===t?!0:t;this.removeDocByRef(e[this._ref],!1),this.addDoc(e,!1),t&&this.eventEmitter.emit("update",e,this)},t.Index.prototype.idf=function(e,t){var n="@"+t+"/"+e;if(Object.prototype.hasOwnProperty.call(this._idfCache,n))return this._idfCache[n];var i=this.index[t].getDocFreq(e),o=1+Math.log(this.documentStore.length/(i+1));return this._idfCache[n]=o,o},t.Index.prototype.getFields=function(){return this._fields.slice()},t.Index.prototype.search=function(e,n){if(!e)return[];e="string"==typeof e?{any:e}:JSON.parse(JSON.stringify(e));var i=null;null!=n&&(i=JSON.stringify(n));for(var o=new t.Configuration(i,this.getFields()).get(),r={},s=Object.keys(e),u=0;u0&&t.push(e);for(var i in n)"docs"!==i&&"df"!==i&&this.expandToken(e+i,t,n[i]);return t},t.InvertedIndex.prototype.toJSON=function(){return{root:this.root}},t.Configuration=function(e,n){var e=e||"";if(void 0==n||null==n)throw new Error("fields should not be null");this.config={};var i;try{i=JSON.parse(e),this.buildUserConfig(i,n)}catch(o){t.utils.warn("user configuration parse failed, will use default configuration"),this.buildDefaultConfig(n)}},t.Configuration.prototype.buildDefaultConfig=function(e){this.reset(),e.forEach(function(e){this.config[e]={boost:1,bool:"OR",expand:!1}},this)},t.Configuration.prototype.buildUserConfig=function(e,n){var i="OR",o=!1;if(this.reset(),"bool"in e&&(i=e.bool||i),"expand"in e&&(o=e.expand||o),"fields"in e)for(var r in e.fields)if(n.indexOf(r)>-1){var s=e.fields[r],u=o;void 0!=s.expand&&(u=s.expand),this.config[r]={boost:s.boost||0===s.boost?s.boost:1,bool:s.bool||i,expand:u}}else t.utils.warn("field name in user configuration not found in index instance fields");else this.addAllFields2UserConfig(i,o,n)},t.Configuration.prototype.addAllFields2UserConfig=function(e,t,n){n.forEach(function(n){this.config[n]={boost:1,bool:e,expand:t}},this)},t.Configuration.prototype.get=function(){return this.config},t.Configuration.prototype.reset=function(){this.config={}},lunr.SortedSet=function(){this.length=0,this.elements=[]},lunr.SortedSet.load=function(e){var t=new this;return t.elements=e,t.length=e.length,t},lunr.SortedSet.prototype.add=function(){var e,t;for(e=0;e1;){if(r===e)return o;e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o]}return r===e?o:-1},lunr.SortedSet.prototype.locationFor=function(e){for(var t=0,n=this.elements.length,i=n-t,o=t+Math.floor(i/2),r=this.elements[o];i>1;)e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o];return r>e?o:e>r?o+1:void 0},lunr.SortedSet.prototype.intersect=function(e){for(var t=new lunr.SortedSet,n=0,i=0,o=this.length,r=e.length,s=this.elements,u=e.elements;;){if(n>o-1||i>r-1)break;s[n]!==u[i]?s[n]u[i]&&i++:(t.add(s[n]),n++,i++)}return t},lunr.SortedSet.prototype.clone=function(){var e=new lunr.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},lunr.SortedSet.prototype.union=function(e){var t,n,i;this.length>=e.length?(t=this,n=e):(t=e,n=this),i=t.clone();for(var o=0,r=n.toArray();o + + + https://block.github.io/ftl/ + + + https://block.github.io/ftl/authors/ + + + https://block.github.io/ftl/docs/ + + + https://block.github.io/ftl/docs/getting-started/ + + + https://block.github.io/ftl/docs/getting-started/introduction/ + 2021-05-01T08:00:00+00:00 + + + https://block.github.io/ftl/docs/getting-started/quick-start/ + 2021-05-01T08:20:00+00:00 + + + https://block.github.io/ftl/docs/help/ + + + https://block.github.io/ftl/docs/help/faq/ + 2021-05-01T19:30:00+00:00 + + + https://block.github.io/ftl/docs/help/glossary/ + 2021-05-01T19:30:00+00:00 + + + https://block.github.io/ftl/docs/observability/ + + + https://block.github.io/ftl/docs/observability/metrics/ + 2021-05-01T08:00:00+00:00 + + + https://block.github.io/ftl/docs/reference/ + + + https://block.github.io/ftl/docs/reference/cron/ + 2021-05-01T08:20:00+00:00 + + + https://block.github.io/ftl/docs/reference/externaltypes/ + 2024-07-12T18:00:00+00:00 + + + https://block.github.io/ftl/docs/reference/ingress/ + 2021-05-01T08:20:00+00:00 + + + https://block.github.io/ftl/docs/reference/matrix/ + 2021-05-01T08:20:00+00:00 + + + https://block.github.io/ftl/docs/reference/pubsub/ + 2021-05-01T08:20:00+00:00 + + + https://block.github.io/ftl/docs/reference/retries/ + 2021-05-01T08:20:00+00:00 + + + https://block.github.io/ftl/docs/reference/secretsconfig/ + 2021-05-01T08:20:00+00:00 + + + https://block.github.io/ftl/docs/reference/start/ + 2021-05-01T08:20:00+00:00 + + + https://block.github.io/ftl/docs/reference/types/ + 2021-05-01T08:20:00+00:00 + + + https://block.github.io/ftl/docs/reference/unittests/ + 2024-06-13T08:20:00+00:00 + + + https://block.github.io/ftl/docs/reference/verbs/ + 2021-05-01T08:20:00+00:00 + + + https://block.github.io/ftl/docs/reference/visibility/ + 2021-05-01T08:20:00+00:00 + +