From 7adaead6a03ea1d2722421df40f2329dbc1d1c00 Mon Sep 17 00:00:00 2001 From: Chris Sewell Date: Thu, 16 Jul 2026 14:36:17 +0000 Subject: [PATCH 1/3] =?UTF-8?q?=E2=9C=A8=20NEW:=20Add=20accordion=20compon?= =?UTF-8?q?ent=20(exclusive=20dropdown=20group)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An `accordion` directive groups `dropdown`s so that opening one item collapses the others, using the native, JavaScript-free `
` attribute. Only direct child dropdowns join the group (nested dropdowns stay independent), at most one item may start `:open:`, and a `:flush:` flag provides an edge-to-edge variant. `
` is Baseline Newly Available; it degrades gracefully (older browsers keep each item independently collapsible), as documented on the new accordions page. --- CHANGELOG.md | 6 + docs/accordions.md | 116 +++++++++++++ docs/index.md | 8 + docs/snippets/myst/accordion-basic.txt | 16 ++ docs/snippets/rst/accordion-basic.txt | 14 ++ sphinx_design/accordion.py | 122 ++++++++++++++ sphinx_design/dropdown.py | 13 +- sphinx_design/extension.py | 2 + sphinx_design/static/sphinx-design.min.css | 2 +- style/accordion.css | 24 +++ tests/test_misc.py | 159 ++++++++++++++++++ .../snippet_post_accordion-basic.xml | 35 ++++ .../snippet_pre_accordion-basic.xml | 20 +++ tools/generate_css.py | 1 + 14 files changed, 534 insertions(+), 4 deletions(-) create mode 100644 docs/accordions.md create mode 100644 docs/snippets/myst/accordion-basic.txt create mode 100644 docs/snippets/rst/accordion-basic.txt create mode 100644 sphinx_design/accordion.py create mode 100644 style/accordion.css create mode 100644 tests/test_snippets/snippet_post_accordion-basic.xml create mode 100644 tests/test_snippets/snippet_pre_accordion-basic.xml diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f31abd..f7b471a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ## Unreleased +- ✨ NEW: `accordion` directive groups `dropdown`s into an exclusive set — + opening one item automatically collapses the others, using the native, + JavaScript-free `
` attribute. It degrades gracefully on + browsers that predate the feature (each item stays independently + collapsible), and offers a `:flush:` edge-to-edge variant and a `class` + option ({pr}`PRNUM`) - ♻️ IMPROVE: Replace the Sass/Node build with a dependency-free Python CSS generator (`tools/generate_css.py` driven by `style/design.toml` and hand-authored `style/*.css`); `package.json` is gone. The compiled diff --git a/docs/accordions.md b/docs/accordions.md new file mode 100644 index 0000000..5838023 --- /dev/null +++ b/docs/accordions.md @@ -0,0 +1,116 @@ +(sd-accordions)= + +# Accordions + +An `accordion` groups a set of [dropdowns](sd-dropdowns) so that they behave as +one *exclusive* set: opening one item automatically closes the others. This is +useful for FAQ-style content, where only one answer should be visible at a time. + +The behaviour is native to HTML and requires **no JavaScript**: the directive +simply gives every item a shared `name`, and the browser does the rest. + +::::{accordion} + +:::{dropdown} What is an accordion? +A container of dropdowns where opening one collapses the others. +::: + +:::{dropdown} How do I add one? +Nest `dropdown` directives inside an `accordion` directive (see the syntax +below). +::: + +:::{dropdown} Does it need JavaScript? +No. It uses the native `name` attribute shared across `
` elements. +::: +:::: + +`````{dropdown-syntax} + +````{tab-set-code} +```{literalinclude} ./snippets/myst/accordion-basic.txt +:language: markdown +``` +```{literalinclude} ./snippets/rst/accordion-basic.txt +:language: rst +``` +```` +````` + +## The `:open:` interaction + +Because only one item in an exclusive group can be open at a time, you may mark +**at most one** child dropdown with the [`:open:`](sd-dropdowns) option, to have +the accordion start with that item expanded. If several items are marked +`:open:`, only the first is kept open (the rest are collapsed and a +`design.accordion` warning is emitted). + +## Flush variant + +Add the `:flush:` flag for an edge-to-edge look (like Bootstrap's +*accordion-flush*): the outer side borders and corner rounding are removed, so +the accordion blends into its parent container. + +::::{accordion} +:flush: + +:::{dropdown} First item +{{ loremipsum }} +::: + +:::{dropdown} Second item +{{ loremipsum }} +::: +:::: + +## Nested dropdowns + +Only the **direct** children of an accordion join the exclusive group. A +dropdown nested inside another item's *body* keeps its own independent +open/close behaviour, so you can freely nest expandable content within an +accordion item. + +:::::{accordion} + +::::{dropdown} Item with nested content +:open: + +This item stays open independently of the dropdown below it: + +:::{dropdown} A nested dropdown +:icon: quote + +Opening or closing me does not affect the sibling accordion items. +::: +:::: + +::::{dropdown} Another item +Opening me closes the first item, but the *nested* dropdown is unaffected. +:::: +::::: + +(sd-accordion-browser-support)= + +## Browser support + +The exclusive-open behaviour relies on the native `name` attribute on +`
` elements, which is +[Baseline *Newly* Available](https://web.dev/baseline) (Chrome/Edge 120+, +Firefox 130+ and Safari 17.2+, all shipped in 2024). This is a deliberate +exception to the project's [*Baseline Widely Available*](get_started.md) policy, +permitted because it **degrades gracefully**: browsers that predate the feature +simply ignore the shared `name` and render each item as an ordinary, +independently collapsible dropdown. Nothing breaks — you only lose the automatic +collapsing of sibling items, and no JavaScript fallback is involved. + +## `accordion` options + +flush +: Flag. Remove the outer side borders and corner rounding for an edge-to-edge + (Bootstrap *accordion-flush*) appearance. + +class +: Additional CSS classes for the accordion container element. + +The individual items are ordinary [dropdowns](sd-dropdowns) and accept all of +the `dropdown` options. diff --git a/docs/index.md b/docs/index.md index dd9c3d8..510c49b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -67,6 +67,7 @@ get_started grids cards dropdowns +accordions tabs badges_buttons additional @@ -126,6 +127,13 @@ Flexible and extensible content containers. Hide content in expandable containers. ::: +:::{grid-item-card} {octicon}`fold-down` Accordions +:link: accordions +:link-type: doc + +Group dropdowns into an exclusive set. +::: + :::{grid-item-card} {octicon}`duplicate` Tabs :link: tabs :link-type: doc diff --git a/docs/snippets/myst/accordion-basic.txt b/docs/snippets/myst/accordion-basic.txt new file mode 100644 index 0000000..6c4c5b0 --- /dev/null +++ b/docs/snippets/myst/accordion-basic.txt @@ -0,0 +1,16 @@ +::::{accordion} + +:::{dropdown} First item +Opening another item closes this one. +::: + +:::{dropdown} Second item +:open: + +Content of the second item. +::: + +:::{dropdown} Third item +Content of the third item. +::: +:::: diff --git a/docs/snippets/rst/accordion-basic.txt b/docs/snippets/rst/accordion-basic.txt new file mode 100644 index 0000000..0f97ccd --- /dev/null +++ b/docs/snippets/rst/accordion-basic.txt @@ -0,0 +1,14 @@ +.. accordion:: + + .. dropdown:: First item + + Opening another item closes this one. + + .. dropdown:: Second item + :open: + + Content of the second item. + + .. dropdown:: Third item + + Content of the third item. diff --git a/sphinx_design/accordion.py b/sphinx_design/accordion.py new file mode 100644 index 0000000..b38e1d0 --- /dev/null +++ b/sphinx_design/accordion.py @@ -0,0 +1,122 @@ +"""The ``accordion`` directive: a group of mutually-exclusive dropdowns. + +An accordion is a thin wrapper around a set of :mod:`~sphinx_design.dropdown` +directives. It assigns every *direct* child dropdown a shared, document-unique +``name``, which the HTML writer stamps onto the underlying ``
`` +elements. Browsers that support the native ``name`` attribute on ``
`` +then make the group mutually exclusive: opening one item automatically closes +the others -- with **no JavaScript**. + +This degrades gracefully: engines that predate ``
`` simply ignore +the attribute and render each item as an independent, individually collapsible +dropdown (see ``docs/accordions.md`` for the browser-support note). +""" + +from docutils import nodes +from docutils.parsers.rst import directives +from sphinx.application import Sphinx +from sphinx.util.logging import getLogger + +from .shared import ( + WARNING_TYPE, + SdDirective, + create_component, + is_component, + is_ignorable_child, +) + +LOGGER = getLogger(__name__) + + +def setup_accordion(app: Sphinx) -> None: + app.add_directive("accordion", AccordionDirective) + + +class AccordionDirective(SdDirective): + """A container of ``dropdown`` items behaving as one exclusive group. + + Opening one item collapses the others, via a shared native + ``
`` attribute (no JavaScript). The directive: + + - parses its content, which should be a sequence of ``dropdown`` directives; + - warns (subtype ``design.accordion``) about any non-dropdown child, while + silently keeping structurally inert nodes (comments, targets, ...); + - stamps every direct child dropdown with a shared ``details_name``, so the + HTML transform can emit the grouping ``name`` attribute; and + - enforces at most one initially-``open`` item (warning and keeping the + first, since an exclusive group can only have one member open at a time). + + Nested dropdowns (inside an item's *body*) are deliberately left untouched: + only *direct* children join the group. + """ + + has_content = True + option_spec = { + "flush": directives.flag, # edge-to-edge styling (no outer borders) + "class": directives.class_option, + } + + def _group_name(self) -> str: + """Build a document-unique, build-stable group name. + + The name is derived from the current docname (kept unique even in + single-page/concatenated builds, where accordions from different + source documents share one HTML page) plus a per-document serial + counter. It is fully deterministic -- no randomness -- so rebuilds of + unchanged content produce byte-identical output. + """ + slug = nodes.make_id(self.env.docname) or "doc" + serial = self.env.new_serialno("sd-accordion") + return f"sd-accordion-{slug}-{serial}" + + def run_with_defaults(self) -> list[nodes.Node]: + self.assert_has_content() + + classes = ["sd-accordion"] + if "flush" in self.options: + classes.append("sd-accordion-flush") + classes.extend(self.options.get("class", [])) + + accordion = create_component("accordion", classes=classes) + self.set_source_info(accordion) + self.state.nested_parse(self.content, self.content_offset, accordion) + + group_name = self._group_name() + valid_children: list[nodes.Node] = [] + has_open = False + for child in accordion.children: + if is_ignorable_child(child): + # comments and system messages can be dropped, but hyperlink + # targets must be kept so references to them still resolve + if isinstance(child, nodes.target): + valid_children.append(child) + continue + if not is_component(child, "dropdown"): + LOGGER.warning( + f"All children of an 'accordion' " + f"should be 'dropdown' [{WARNING_TYPE}.accordion]", + location=child, + type=WARNING_TYPE, + subtype="accordion", + ) + continue # skip invalid children rather than breaking + # only *direct* child dropdowns join the group; nested dropdowns + # keep their own independent open/close behaviour + child["details_name"] = group_name + if child.get("opened"): + if has_open: + # an exclusive group can only have one member open at a time + LOGGER.warning( + f"Multiple open 'dropdown' items in an 'accordion'; " + f"keeping only the first open [{WARNING_TYPE}.accordion]", + location=child, + type=WARNING_TYPE, + subtype="accordion", + ) + child["opened"] = False + else: + has_open = True + valid_children.append(child) + + accordion.children = valid_children + return [accordion] diff --git a/sphinx_design/dropdown.py b/sphinx_design/dropdown.py index ced4d81..f0e4f94 100644 --- a/sphinx_design/dropdown.py +++ b/sphinx_design/dropdown.py @@ -35,10 +35,14 @@ class dropdown_title(nodes.TextElement, nodes.General): # noqa: N801 def visit_dropdown_main(self, node): + attributes = {} + if node.get("details_name"): + # a shared name makes sibling
mutually exclusive (the + # native, JS-free basis of the ``accordion`` component) + attributes["name"] = node["details_name"] if node.get("opened"): - self.body.append(self.starttag(node, "details", open="open")) - else: - self.body.append(self.starttag(node, "details")) + attributes["open"] = "open" + self.body.append(self.starttag(node, "details", **attributes)) def depart_dropdown_main(self, node): @@ -176,6 +180,9 @@ def run(self, **kwargs: Any) -> None: + (["sd-card"] if use_card else ["sd-d-flex-column"]) + node["container_classes"], ) + if node.get("details_name"): + # propagate the accordion group name onto the
element + newnode["details_name"] = node["details_name"] if node["has_title"]: title_text_children = node[0].children diff --git a/sphinx_design/extension.py b/sphinx_design/extension.py index 370ddc7..0067eca 100644 --- a/sphinx_design/extension.py +++ b/sphinx_design/extension.py @@ -7,6 +7,7 @@ from sphinx.application import Sphinx from sphinx.transforms import SphinxTransform +from .accordion import setup_accordion from .article_info import setup_article_info from .badges_buttons import setup_badges_and_buttons from .cards import setup_cards @@ -49,6 +50,7 @@ def setup_extension(app: Sphinx) -> None: setup_cards(app) setup_grids(app) setup_dropdown(app) + setup_accordion(app) setup_icons(app) setup_tabs(app) setup_article_info(app) diff --git a/sphinx_design/static/sphinx-design.min.css b/sphinx_design/static/sphinx-design.min.css index 39fb201..bc924e4 100644 --- a/sphinx_design/static/sphinx-design.min.css +++ b/sphinx_design/static/sphinx-design.min.css @@ -1 +1 @@ -.sd-bg-primary{background-color:var(--sd-color-primary)!important}.sd-bg-text-primary{color:var(--sd-color-primary-text)!important}button.sd-bg-primary:focus,button.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight)!important}button.sd-bg-primary:focus-visible{outline-color:var(--sd-color-primary-highlight)!important}a.sd-bg-primary:focus,a.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight)!important}a.sd-bg-primary:focus-visible{outline-color:var(--sd-color-primary-highlight)!important}.sd-bg-secondary{background-color:var(--sd-color-secondary)!important}.sd-bg-text-secondary{color:var(--sd-color-secondary-text)!important}button.sd-bg-secondary:focus,button.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight)!important}button.sd-bg-secondary:focus-visible{outline-color:var(--sd-color-secondary-highlight)!important}a.sd-bg-secondary:focus,a.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight)!important}a.sd-bg-secondary:focus-visible{outline-color:var(--sd-color-secondary-highlight)!important}.sd-bg-success{background-color:var(--sd-color-success)!important}.sd-bg-text-success{color:var(--sd-color-success-text)!important}button.sd-bg-success:focus,button.sd-bg-success:hover{background-color:var(--sd-color-success-highlight)!important}button.sd-bg-success:focus-visible{outline-color:var(--sd-color-success-highlight)!important}a.sd-bg-success:focus,a.sd-bg-success:hover{background-color:var(--sd-color-success-highlight)!important}a.sd-bg-success:focus-visible{outline-color:var(--sd-color-success-highlight)!important}.sd-bg-info{background-color:var(--sd-color-info)!important}.sd-bg-text-info{color:var(--sd-color-info-text)!important}button.sd-bg-info:focus,button.sd-bg-info:hover{background-color:var(--sd-color-info-highlight)!important}button.sd-bg-info:focus-visible{outline-color:var(--sd-color-info-highlight)!important}a.sd-bg-info:focus,a.sd-bg-info:hover{background-color:var(--sd-color-info-highlight)!important}a.sd-bg-info:focus-visible{outline-color:var(--sd-color-info-highlight)!important}.sd-bg-warning{background-color:var(--sd-color-warning)!important}.sd-bg-text-warning{color:var(--sd-color-warning-text)!important}button.sd-bg-warning:focus,button.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight)!important}button.sd-bg-warning:focus-visible{outline-color:var(--sd-color-warning-highlight)!important}a.sd-bg-warning:focus,a.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight)!important}a.sd-bg-warning:focus-visible{outline-color:var(--sd-color-warning-highlight)!important}.sd-bg-danger{background-color:var(--sd-color-danger)!important}.sd-bg-text-danger{color:var(--sd-color-danger-text)!important}button.sd-bg-danger:focus,button.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight)!important}button.sd-bg-danger:focus-visible{outline-color:var(--sd-color-danger-highlight)!important}a.sd-bg-danger:focus,a.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight)!important}a.sd-bg-danger:focus-visible{outline-color:var(--sd-color-danger-highlight)!important}.sd-bg-light{background-color:var(--sd-color-light)!important}.sd-bg-text-light{color:var(--sd-color-light-text)!important}button.sd-bg-light:focus,button.sd-bg-light:hover{background-color:var(--sd-color-light-highlight)!important}button.sd-bg-light:focus-visible{outline-color:var(--sd-color-light-highlight)!important}a.sd-bg-light:focus,a.sd-bg-light:hover{background-color:var(--sd-color-light-highlight)!important}a.sd-bg-light:focus-visible{outline-color:var(--sd-color-light-highlight)!important}.sd-bg-muted{background-color:var(--sd-color-muted)!important}.sd-bg-text-muted{color:var(--sd-color-muted-text)!important}button.sd-bg-muted:focus,button.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight)!important}button.sd-bg-muted:focus-visible{outline-color:var(--sd-color-muted-highlight)!important}a.sd-bg-muted:focus,a.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight)!important}a.sd-bg-muted:focus-visible{outline-color:var(--sd-color-muted-highlight)!important}.sd-bg-dark{background-color:var(--sd-color-dark)!important}.sd-bg-text-dark{color:var(--sd-color-dark-text)!important}button.sd-bg-dark:focus,button.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight)!important}button.sd-bg-dark:focus-visible{outline-color:var(--sd-color-dark-highlight)!important}a.sd-bg-dark:focus,a.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight)!important}a.sd-bg-dark:focus-visible{outline-color:var(--sd-color-dark-highlight)!important}.sd-bg-black{background-color:var(--sd-color-black)!important}.sd-bg-text-black{color:var(--sd-color-black-text)!important}button.sd-bg-black:focus,button.sd-bg-black:hover{background-color:var(--sd-color-black-highlight)!important}button.sd-bg-black:focus-visible{outline-color:var(--sd-color-black-highlight)!important}a.sd-bg-black:focus,a.sd-bg-black:hover{background-color:var(--sd-color-black-highlight)!important}a.sd-bg-black:focus-visible{outline-color:var(--sd-color-black-highlight)!important}.sd-bg-white{background-color:var(--sd-color-white)!important}.sd-bg-text-white{color:var(--sd-color-white-text)!important}button.sd-bg-white:focus,button.sd-bg-white:hover{background-color:var(--sd-color-white-highlight)!important}button.sd-bg-white:focus-visible{outline-color:var(--sd-color-white-highlight)!important}a.sd-bg-white:focus,a.sd-bg-white:hover{background-color:var(--sd-color-white-highlight)!important}a.sd-bg-white:focus-visible{outline-color:var(--sd-color-white-highlight)!important}.sd-text-primary,.sd-text-primary>p{color:var(--sd-color-primary)!important}a.sd-text-primary:focus,a.sd-text-primary:hover{color:var(--sd-color-primary-highlight)!important}.sd-text-secondary,.sd-text-secondary>p{color:var(--sd-color-secondary)!important}a.sd-text-secondary:focus,a.sd-text-secondary:hover{color:var(--sd-color-secondary-highlight)!important}.sd-text-success,.sd-text-success>p{color:var(--sd-color-success)!important}a.sd-text-success:focus,a.sd-text-success:hover{color:var(--sd-color-success-highlight)!important}.sd-text-info,.sd-text-info>p{color:var(--sd-color-info)!important}a.sd-text-info:focus,a.sd-text-info:hover{color:var(--sd-color-info-highlight)!important}.sd-text-warning,.sd-text-warning>p{color:var(--sd-color-warning)!important}a.sd-text-warning:focus,a.sd-text-warning:hover{color:var(--sd-color-warning-highlight)!important}.sd-text-danger,.sd-text-danger>p{color:var(--sd-color-danger)!important}a.sd-text-danger:focus,a.sd-text-danger:hover{color:var(--sd-color-danger-highlight)!important}.sd-text-light,.sd-text-light>p{color:var(--sd-color-light)!important}a.sd-text-light:focus,a.sd-text-light:hover{color:var(--sd-color-light-highlight)!important}.sd-text-muted,.sd-text-muted>p{color:var(--sd-color-muted)!important}a.sd-text-muted:focus,a.sd-text-muted:hover{color:var(--sd-color-muted-highlight)!important}.sd-text-dark,.sd-text-dark>p{color:var(--sd-color-dark)!important}a.sd-text-dark:focus,a.sd-text-dark:hover{color:var(--sd-color-dark-highlight)!important}.sd-text-black,.sd-text-black>p{color:var(--sd-color-black)!important}a.sd-text-black:focus,a.sd-text-black:hover{color:var(--sd-color-black-highlight)!important}.sd-text-white,.sd-text-white>p{color:var(--sd-color-white)!important}a.sd-text-white:focus,a.sd-text-white:hover{color:var(--sd-color-white-highlight)!important}.sd-outline-primary{border-color:var(--sd-color-primary)!important;border-style:solid!important;border-width:1px!important}a.sd-outline-primary:focus,a.sd-outline-primary:hover{border-color:var(--sd-color-primary-highlight)!important}a.sd-outline-primary:focus-visible{outline-color:var(--sd-color-primary-highlight)!important}.sd-outline-secondary{border-color:var(--sd-color-secondary)!important;border-style:solid!important;border-width:1px!important}a.sd-outline-secondary:focus,a.sd-outline-secondary:hover{border-color:var(--sd-color-secondary-highlight)!important}a.sd-outline-secondary:focus-visible{outline-color:var(--sd-color-secondary-highlight)!important}.sd-outline-success{border-color:var(--sd-color-success)!important;border-style:solid!important;border-width:1px!important}a.sd-outline-success:focus,a.sd-outline-success:hover{border-color:var(--sd-color-success-highlight)!important}a.sd-outline-success:focus-visible{outline-color:var(--sd-color-success-highlight)!important}.sd-outline-info{border-color:var(--sd-color-info)!important;border-style:solid!important;border-width:1px!important}a.sd-outline-info:focus,a.sd-outline-info:hover{border-color:var(--sd-color-info-highlight)!important}a.sd-outline-info:focus-visible{outline-color:var(--sd-color-info-highlight)!important}.sd-outline-warning{border-color:var(--sd-color-warning)!important;border-style:solid!important;border-width:1px!important}a.sd-outline-warning:focus,a.sd-outline-warning:hover{border-color:var(--sd-color-warning-highlight)!important}a.sd-outline-warning:focus-visible{outline-color:var(--sd-color-warning-highlight)!important}.sd-outline-danger{border-color:var(--sd-color-danger)!important;border-style:solid!important;border-width:1px!important}a.sd-outline-danger:focus,a.sd-outline-danger:hover{border-color:var(--sd-color-danger-highlight)!important}a.sd-outline-danger:focus-visible{outline-color:var(--sd-color-danger-highlight)!important}.sd-outline-light{border-color:var(--sd-color-light)!important;border-style:solid!important;border-width:1px!important}a.sd-outline-light:focus,a.sd-outline-light:hover{border-color:var(--sd-color-light-highlight)!important}a.sd-outline-light:focus-visible{outline-color:var(--sd-color-light-highlight)!important}.sd-outline-muted{border-color:var(--sd-color-muted)!important;border-style:solid!important;border-width:1px!important}a.sd-outline-muted:focus,a.sd-outline-muted:hover{border-color:var(--sd-color-muted-highlight)!important}a.sd-outline-muted:focus-visible{outline-color:var(--sd-color-muted-highlight)!important}.sd-outline-dark{border-color:var(--sd-color-dark)!important;border-style:solid!important;border-width:1px!important}a.sd-outline-dark:focus,a.sd-outline-dark:hover{border-color:var(--sd-color-dark-highlight)!important}a.sd-outline-dark:focus-visible{outline-color:var(--sd-color-dark-highlight)!important}.sd-outline-black{border-color:var(--sd-color-black)!important;border-style:solid!important;border-width:1px!important}a.sd-outline-black:focus,a.sd-outline-black:hover{border-color:var(--sd-color-black-highlight)!important}a.sd-outline-black:focus-visible{outline-color:var(--sd-color-black-highlight)!important}.sd-outline-white{border-color:var(--sd-color-white)!important;border-style:solid!important;border-width:1px!important}a.sd-outline-white:focus,a.sd-outline-white:hover{border-color:var(--sd-color-white-highlight)!important}a.sd-outline-white:focus-visible{outline-color:var(--sd-color-white-highlight)!important}.sd-bg-transparent{background-color:transparent!important}.sd-outline-transparent{border-color:transparent!important}.sd-text-transparent{color:transparent!important}.sd-p-0{padding:0!important}.sd-pt-0,.sd-py-0{padding-top:0!important}.sd-pr-0,.sd-px-0{padding-right:0!important}.sd-pb-0,.sd-py-0{padding-bottom:0!important}.sd-pl-0,.sd-px-0{padding-left:0!important}.sd-p-1{padding:.25rem!important}.sd-pt-1,.sd-py-1{padding-top:.25rem!important}.sd-pr-1,.sd-px-1{padding-right:.25rem!important}.sd-pb-1,.sd-py-1{padding-bottom:.25rem!important}.sd-pl-1,.sd-px-1{padding-left:.25rem!important}.sd-p-2{padding:.5rem!important}.sd-pt-2,.sd-py-2{padding-top:.5rem!important}.sd-pr-2,.sd-px-2{padding-right:.5rem!important}.sd-pb-2,.sd-py-2{padding-bottom:.5rem!important}.sd-pl-2,.sd-px-2{padding-left:.5rem!important}.sd-p-3{padding:1rem!important}.sd-pt-3,.sd-py-3{padding-top:1rem!important}.sd-pr-3,.sd-px-3{padding-right:1rem!important}.sd-pb-3,.sd-py-3{padding-bottom:1rem!important}.sd-pl-3,.sd-px-3{padding-left:1rem!important}.sd-p-4{padding:1.5rem!important}.sd-pt-4,.sd-py-4{padding-top:1.5rem!important}.sd-pr-4,.sd-px-4{padding-right:1.5rem!important}.sd-pb-4,.sd-py-4{padding-bottom:1.5rem!important}.sd-pl-4,.sd-px-4{padding-left:1.5rem!important}.sd-p-5{padding:3rem!important}.sd-pt-5,.sd-py-5{padding-top:3rem!important}.sd-pr-5,.sd-px-5{padding-right:3rem!important}.sd-pb-5,.sd-py-5{padding-bottom:3rem!important}.sd-pl-5,.sd-px-5{padding-left:3rem!important}.sd-m-auto{margin:auto!important}.sd-mt-auto,.sd-my-auto{margin-top:auto!important}.sd-mr-auto,.sd-mx-auto{margin-right:auto!important}.sd-mb-auto,.sd-my-auto{margin-bottom:auto!important}.sd-ml-auto,.sd-mx-auto{margin-left:auto!important}.sd-m-0{margin:0!important}.sd-mt-0,.sd-my-0{margin-top:0!important}.sd-mr-0,.sd-mx-0{margin-right:0!important}.sd-mb-0,.sd-my-0{margin-bottom:0!important}.sd-ml-0,.sd-mx-0{margin-left:0!important}.sd-m-1{margin:.25rem!important}.sd-mt-1,.sd-my-1{margin-top:.25rem!important}.sd-mr-1,.sd-mx-1{margin-right:.25rem!important}.sd-mb-1,.sd-my-1{margin-bottom:.25rem!important}.sd-ml-1,.sd-mx-1{margin-left:.25rem!important}.sd-m-2{margin:.5rem!important}.sd-mt-2,.sd-my-2{margin-top:.5rem!important}.sd-mr-2,.sd-mx-2{margin-right:.5rem!important}.sd-mb-2,.sd-my-2{margin-bottom:.5rem!important}.sd-ml-2,.sd-mx-2{margin-left:.5rem!important}.sd-m-3{margin:1rem!important}.sd-mt-3,.sd-my-3{margin-top:1rem!important}.sd-mr-3,.sd-mx-3{margin-right:1rem!important}.sd-mb-3,.sd-my-3{margin-bottom:1rem!important}.sd-ml-3,.sd-mx-3{margin-left:1rem!important}.sd-m-4{margin:1.5rem!important}.sd-mt-4,.sd-my-4{margin-top:1.5rem!important}.sd-mr-4,.sd-mx-4{margin-right:1.5rem!important}.sd-mb-4,.sd-my-4{margin-bottom:1.5rem!important}.sd-ml-4,.sd-mx-4{margin-left:1.5rem!important}.sd-m-5{margin:3rem!important}.sd-mt-5,.sd-my-5{margin-top:3rem!important}.sd-mr-5,.sd-mx-5{margin-right:3rem!important}.sd-mb-5,.sd-my-5{margin-bottom:3rem!important}.sd-ml-5,.sd-mx-5{margin-left:3rem!important}.sd-w-25{width:25%!important}.sd-w-50{width:50%!important}.sd-w-75{width:75%!important}.sd-w-100{width:100%!important}.sd-w-auto{width:auto!important}.sd-h-25{height:25%!important}.sd-h-50{height:50%!important}.sd-h-75{height:75%!important}.sd-h-100{height:100%!important}.sd-h-auto{height:auto!important}.sd-d-none{display:none!important}.sd-d-inline{display:inline!important}.sd-d-inline-block{display:inline-block!important}.sd-d-block{display:block!important}.sd-d-grid{display:grid!important}.sd-d-flex-row{display:flex!important;flex-direction:row!important}.sd-d-flex-column{display:flex!important;flex-direction:column!important}.sd-d-inline-flex{display:inline-flex!important}.sd-align-major-start{justify-content:flex-start!important}.sd-align-major-end{justify-content:flex-end!important}.sd-align-major-center{justify-content:center!important}.sd-align-major-justify{justify-content:space-between!important}.sd-align-major-spaced{justify-content:space-evenly!important}.sd-align-minor-start{align-items:flex-start!important}.sd-align-minor-end{align-items:flex-end!important}.sd-align-minor-center{align-items:center!important}.sd-align-minor-stretch{align-items:stretch!important}@media (min-width:576px){.sd-d-sm-none{display:none!important}.sd-d-sm-inline{display:inline!important}.sd-d-sm-inline-block{display:inline-block!important}.sd-d-sm-block{display:block!important}.sd-d-sm-grid{display:grid!important}.sd-d-sm-flex{display:flex!important}.sd-d-sm-inline-flex{display:inline-flex!important}}@media (min-width:768px){.sd-d-md-none{display:none!important}.sd-d-md-inline{display:inline!important}.sd-d-md-inline-block{display:inline-block!important}.sd-d-md-block{display:block!important}.sd-d-md-grid{display:grid!important}.sd-d-md-flex{display:flex!important}.sd-d-md-inline-flex{display:inline-flex!important}}@media (min-width:992px){.sd-d-lg-none{display:none!important}.sd-d-lg-inline{display:inline!important}.sd-d-lg-inline-block{display:inline-block!important}.sd-d-lg-block{display:block!important}.sd-d-lg-grid{display:grid!important}.sd-d-lg-flex{display:flex!important}.sd-d-lg-inline-flex{display:inline-flex!important}}@media (min-width:1200px){.sd-d-xl-none{display:none!important}.sd-d-xl-inline{display:inline!important}.sd-d-xl-inline-block{display:inline-block!important}.sd-d-xl-block{display:block!important}.sd-d-xl-grid{display:grid!important}.sd-d-xl-flex{display:flex!important}.sd-d-xl-inline-flex{display:inline-flex!important}}.sd-text-justify{text-align:justify!important}.sd-text-left{text-align:left!important}.sd-text-right{text-align:right!important}.sd-text-center{text-align:center!important}.sd-font-weight-light{font-weight:300!important}.sd-font-weight-lighter{font-weight:lighter!important}.sd-font-weight-normal{font-weight:400!important}.sd-font-weight-bold{font-weight:700!important}.sd-font-weight-bolder{font-weight:bolder!important}.sd-font-italic{font-style:italic!important}.sd-text-decoration-none{text-decoration:none!important}.sd-text-lowercase{text-transform:lowercase!important}.sd-text-uppercase{text-transform:uppercase!important}.sd-text-capitalize{text-transform:capitalize!important}.sd-text-wrap{white-space:normal!important}.sd-text-nowrap{white-space:nowrap!important}.sd-text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sd-fs-1,.sd-fs-1>p{font-size:calc(1.375rem + 1.5vw)!important;line-height:unset!important}.sd-fs-2,.sd-fs-2>p{font-size:calc(1.325rem + 0.9vw)!important;line-height:unset!important}.sd-fs-3,.sd-fs-3>p{font-size:calc(1.3rem + 0.6vw)!important;line-height:unset!important}.sd-fs-4,.sd-fs-4>p{font-size:calc(1.275rem + 0.3vw)!important;line-height:unset!important}.sd-fs-5,.sd-fs-5>p{font-size:1.25rem!important;line-height:unset!important}.sd-fs-6,.sd-fs-6>p{font-size:1rem!important;line-height:unset!important}.sd-border-0{border:0 solid!important}.sd-border-top-0{border-top:0 solid!important}.sd-border-bottom-0{border-bottom:0 solid!important}.sd-border-right-0{border-right:0 solid!important}.sd-border-left-0{border-left:0 solid!important}.sd-border-1{border:1px solid!important}.sd-border-top-1{border-top:1px solid!important}.sd-border-bottom-1{border-bottom:1px solid!important}.sd-border-right-1{border-right:1px solid!important}.sd-border-left-1{border-left:1px solid!important}.sd-border-2{border:2px solid!important}.sd-border-top-2{border-top:2px solid!important}.sd-border-bottom-2{border-bottom:2px solid!important}.sd-border-right-2{border-right:2px solid!important}.sd-border-left-2{border-left:2px solid!important}.sd-border-3{border:3px solid!important}.sd-border-top-3{border-top:3px solid!important}.sd-border-bottom-3{border-bottom:3px solid!important}.sd-border-right-3{border-right:3px solid!important}.sd-border-left-3{border-left:3px solid!important}.sd-border-4{border:4px solid!important}.sd-border-top-4{border-top:4px solid!important}.sd-border-bottom-4{border-bottom:4px solid!important}.sd-border-right-4{border-right:4px solid!important}.sd-border-left-4{border-left:4px solid!important}.sd-border-5{border:5px solid!important}.sd-border-top-5{border-top:5px solid!important}.sd-border-bottom-5{border-bottom:5px solid!important}.sd-border-right-5{border-right:5px solid!important}.sd-border-left-5{border-left:5px solid!important}.sd-rounded-0{border-radius:0!important}.sd-rounded-1{border-radius:.2rem!important}.sd-rounded-2{border-radius:.3rem!important}.sd-rounded-3{border-radius:.5rem!important}.sd-rounded-pill{border-radius:50rem!important}.sd-rounded-circle{border-radius:50%!important}.shadow-none{box-shadow:none!important}.sd-shadow-sm{box-shadow:0 .125rem .25rem var(--sd-color-shadow)!important}.sd-shadow-md{box-shadow:0 .5rem 1rem var(--sd-color-shadow)!important}.sd-shadow-lg{box-shadow:0 1rem 3rem var(--sd-color-shadow)!important}@keyframes sd-slide-from-left{0%{transform:translateX(-100%)}100%{transform:translateX(0)}}@keyframes sd-slide-from-right{0%{transform:translateX(200%)}100%{transform:translateX(0)}}@keyframes sd-grow100{0%{transform:scale(0);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50{0%{transform:scale(0.5);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50-rot20{0%{transform:scale(0.5) rotateZ(-20deg);opacity:.5}75%{transform:scale(1) rotateZ(5deg);opacity:1}95%{transform:scale(1) rotateZ(-1deg);opacity:1}100%{transform:scale(1) rotateZ(0);opacity:1}}.sd-animate-slide-from-left{animation:1s ease-out 0s 1 normal none running sd-slide-from-left}.sd-animate-slide-from-right{animation:1s ease-out 0s 1 normal none running sd-slide-from-right}.sd-animate-grow100{animation:1s ease-out 0s 1 normal none running sd-grow100}.sd-animate-grow50{animation:1s ease-out 0s 1 normal none running sd-grow50}.sd-animate-grow50-rot20{animation:1s ease-out 0s 1 normal none running sd-grow50-rot20}.sd-badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.sd-badge:empty{display:none}a.sd-badge{text-decoration:none}.sd-btn .sd-badge{position:relative;top:-1px}.sd-btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;cursor:pointer;display:inline-block;font-weight:400;font-size:1rem;line-height:1.5;padding:.375rem .75rem;text-align:center;text-decoration: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;vertical-align:middle;user-select:none;outline-offset:.25rem}.sd-btn:hover{text-decoration:none}@media (prefers-reduced-motion:reduce){.sd-btn{transition:none}}.sd-stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.sd-hide-link-text{font-size:0}.sd-btn-primary,.sd-btn-outline-primary:hover,.sd-btn-outline-primary:focus{color:var(--sd-color-primary-text)!important;background-color:var(--sd-color-primary)!important;border-color:var(--sd-color-primary)!important;border-width:1px!important;border-style:solid!important}.sd-btn-primary:hover,.sd-btn-primary:focus{color:var(--sd-color-primary-text)!important;background-color:var(--sd-color-primary-highlight)!important;border-color:var(--sd-color-primary-highlight)!important;border-width:1px!important;border-style:solid!important}.sd-btn-outline-primary{color:var(--sd-color-primary)!important;border-color:var(--sd-color-primary)!important;border-width:1px!important;border-style:solid!important}.sd-btn-primary:focus-visible{outline-color:var(--sd-color-primary)!important}.sd-btn-primary:focus-visible::after{outline-color:var(--sd-color-primary)!important}.sd-btn-secondary,.sd-btn-outline-secondary:hover,.sd-btn-outline-secondary:focus{color:var(--sd-color-secondary-text)!important;background-color:var(--sd-color-secondary)!important;border-color:var(--sd-color-secondary)!important;border-width:1px!important;border-style:solid!important}.sd-btn-secondary:hover,.sd-btn-secondary:focus{color:var(--sd-color-secondary-text)!important;background-color:var(--sd-color-secondary-highlight)!important;border-color:var(--sd-color-secondary-highlight)!important;border-width:1px!important;border-style:solid!important}.sd-btn-outline-secondary{color:var(--sd-color-secondary)!important;border-color:var(--sd-color-secondary)!important;border-width:1px!important;border-style:solid!important}.sd-btn-secondary:focus-visible{outline-color:var(--sd-color-secondary)!important}.sd-btn-secondary:focus-visible::after{outline-color:var(--sd-color-secondary)!important}.sd-btn-success,.sd-btn-outline-success:hover,.sd-btn-outline-success:focus{color:var(--sd-color-success-text)!important;background-color:var(--sd-color-success)!important;border-color:var(--sd-color-success)!important;border-width:1px!important;border-style:solid!important}.sd-btn-success:hover,.sd-btn-success:focus{color:var(--sd-color-success-text)!important;background-color:var(--sd-color-success-highlight)!important;border-color:var(--sd-color-success-highlight)!important;border-width:1px!important;border-style:solid!important}.sd-btn-outline-success{color:var(--sd-color-success)!important;border-color:var(--sd-color-success)!important;border-width:1px!important;border-style:solid!important}.sd-btn-success:focus-visible{outline-color:var(--sd-color-success)!important}.sd-btn-success:focus-visible::after{outline-color:var(--sd-color-success)!important}.sd-btn-info,.sd-btn-outline-info:hover,.sd-btn-outline-info:focus{color:var(--sd-color-info-text)!important;background-color:var(--sd-color-info)!important;border-color:var(--sd-color-info)!important;border-width:1px!important;border-style:solid!important}.sd-btn-info:hover,.sd-btn-info:focus{color:var(--sd-color-info-text)!important;background-color:var(--sd-color-info-highlight)!important;border-color:var(--sd-color-info-highlight)!important;border-width:1px!important;border-style:solid!important}.sd-btn-outline-info{color:var(--sd-color-info)!important;border-color:var(--sd-color-info)!important;border-width:1px!important;border-style:solid!important}.sd-btn-info:focus-visible{outline-color:var(--sd-color-info)!important}.sd-btn-info:focus-visible::after{outline-color:var(--sd-color-info)!important}.sd-btn-warning,.sd-btn-outline-warning:hover,.sd-btn-outline-warning:focus{color:var(--sd-color-warning-text)!important;background-color:var(--sd-color-warning)!important;border-color:var(--sd-color-warning)!important;border-width:1px!important;border-style:solid!important}.sd-btn-warning:hover,.sd-btn-warning:focus{color:var(--sd-color-warning-text)!important;background-color:var(--sd-color-warning-highlight)!important;border-color:var(--sd-color-warning-highlight)!important;border-width:1px!important;border-style:solid!important}.sd-btn-outline-warning{color:var(--sd-color-warning)!important;border-color:var(--sd-color-warning)!important;border-width:1px!important;border-style:solid!important}.sd-btn-warning:focus-visible{outline-color:var(--sd-color-warning)!important}.sd-btn-warning:focus-visible::after{outline-color:var(--sd-color-warning)!important}.sd-btn-danger,.sd-btn-outline-danger:hover,.sd-btn-outline-danger:focus{color:var(--sd-color-danger-text)!important;background-color:var(--sd-color-danger)!important;border-color:var(--sd-color-danger)!important;border-width:1px!important;border-style:solid!important}.sd-btn-danger:hover,.sd-btn-danger:focus{color:var(--sd-color-danger-text)!important;background-color:var(--sd-color-danger-highlight)!important;border-color:var(--sd-color-danger-highlight)!important;border-width:1px!important;border-style:solid!important}.sd-btn-outline-danger{color:var(--sd-color-danger)!important;border-color:var(--sd-color-danger)!important;border-width:1px!important;border-style:solid!important}.sd-btn-danger:focus-visible{outline-color:var(--sd-color-danger)!important}.sd-btn-danger:focus-visible::after{outline-color:var(--sd-color-danger)!important}.sd-btn-light,.sd-btn-outline-light:hover,.sd-btn-outline-light:focus{color:var(--sd-color-light-text)!important;background-color:var(--sd-color-light)!important;border-color:var(--sd-color-light)!important;border-width:1px!important;border-style:solid!important}.sd-btn-light:hover,.sd-btn-light:focus{color:var(--sd-color-light-text)!important;background-color:var(--sd-color-light-highlight)!important;border-color:var(--sd-color-light-highlight)!important;border-width:1px!important;border-style:solid!important}.sd-btn-outline-light{color:var(--sd-color-light)!important;border-color:var(--sd-color-light)!important;border-width:1px!important;border-style:solid!important}.sd-btn-light:focus-visible{outline-color:var(--sd-color-light)!important}.sd-btn-light:focus-visible::after{outline-color:var(--sd-color-light)!important}.sd-btn-muted,.sd-btn-outline-muted:hover,.sd-btn-outline-muted:focus{color:var(--sd-color-muted-text)!important;background-color:var(--sd-color-muted)!important;border-color:var(--sd-color-muted)!important;border-width:1px!important;border-style:solid!important}.sd-btn-muted:hover,.sd-btn-muted:focus{color:var(--sd-color-muted-text)!important;background-color:var(--sd-color-muted-highlight)!important;border-color:var(--sd-color-muted-highlight)!important;border-width:1px!important;border-style:solid!important}.sd-btn-outline-muted{color:var(--sd-color-muted)!important;border-color:var(--sd-color-muted)!important;border-width:1px!important;border-style:solid!important}.sd-btn-muted:focus-visible{outline-color:var(--sd-color-muted)!important}.sd-btn-muted:focus-visible::after{outline-color:var(--sd-color-muted)!important}.sd-btn-dark,.sd-btn-outline-dark:hover,.sd-btn-outline-dark:focus{color:var(--sd-color-dark-text)!important;background-color:var(--sd-color-dark)!important;border-color:var(--sd-color-dark)!important;border-width:1px!important;border-style:solid!important}.sd-btn-dark:hover,.sd-btn-dark:focus{color:var(--sd-color-dark-text)!important;background-color:var(--sd-color-dark-highlight)!important;border-color:var(--sd-color-dark-highlight)!important;border-width:1px!important;border-style:solid!important}.sd-btn-outline-dark{color:var(--sd-color-dark)!important;border-color:var(--sd-color-dark)!important;border-width:1px!important;border-style:solid!important}.sd-btn-dark:focus-visible{outline-color:var(--sd-color-dark)!important}.sd-btn-dark:focus-visible::after{outline-color:var(--sd-color-dark)!important}.sd-btn-black,.sd-btn-outline-black:hover,.sd-btn-outline-black:focus{color:var(--sd-color-black-text)!important;background-color:var(--sd-color-black)!important;border-color:var(--sd-color-black)!important;border-width:1px!important;border-style:solid!important}.sd-btn-black:hover,.sd-btn-black:focus{color:var(--sd-color-black-text)!important;background-color:var(--sd-color-black-highlight)!important;border-color:var(--sd-color-black-highlight)!important;border-width:1px!important;border-style:solid!important}.sd-btn-outline-black{color:var(--sd-color-black)!important;border-color:var(--sd-color-black)!important;border-width:1px!important;border-style:solid!important}.sd-btn-black:focus-visible{outline-color:var(--sd-color-black)!important}.sd-btn-black:focus-visible::after{outline-color:var(--sd-color-black)!important}.sd-btn-white,.sd-btn-outline-white:hover,.sd-btn-outline-white:focus{color:var(--sd-color-white-text)!important;background-color:var(--sd-color-white)!important;border-color:var(--sd-color-white)!important;border-width:1px!important;border-style:solid!important}.sd-btn-white:hover,.sd-btn-white:focus{color:var(--sd-color-white-text)!important;background-color:var(--sd-color-white-highlight)!important;border-color:var(--sd-color-white-highlight)!important;border-width:1px!important;border-style:solid!important}.sd-btn-outline-white{color:var(--sd-color-white)!important;border-color:var(--sd-color-white)!important;border-width:1px!important;border-style:solid!important}.sd-btn-white:focus-visible{outline-color:var(--sd-color-white)!important}.sd-btn-white:focus-visible::after{outline-color:var(--sd-color-white)!important}.sd-octicon,.sd-material-icon{display:inline-block;fill:currentColor;vertical-align:middle}.sd-avatar-xs{border-radius:50%;object-fit:cover;object-position:center;width:1rem;height:1rem}.sd-avatar-sm{border-radius:50%;object-fit:cover;object-position:center;width:3rem;height:3rem}.sd-avatar-md{border-radius:50%;object-fit:cover;object-position:center;width:5rem;height:5rem}.sd-avatar-lg{border-radius:50%;object-fit:cover;object-position:center;width:7rem;height:7rem}.sd-avatar-xl{border-radius:50%;object-fit:cover;object-position:center;width:10rem;height:10rem}.sd-avatar-inherit{border-radius:50%;object-fit:cover;object-position:center;width:inherit;height:inherit}.sd-avatar-initial{border-radius:50%;object-fit:cover;object-position:center;width:initial;height:initial}.sd-card{background-clip:border-box;background-color:var(--sd-color-card-background);border:1px solid var(--sd-color-card-border);border-radius:.25rem;color:var(--sd-color-card-text);display:flex;flex-direction:column;min-width:0;position:relative;word-wrap:break-word}.sd-card>hr{margin-left:0;margin-right:0}.sd-card .sd-stretched-link:focus-visible{outline:none}.sd-card .sd-stretched-link:focus-visible::after{outline-style:auto;outline-color:var(--sd-color-primary)}.sd-card-hover:hover{border-color:var(--sd-color-card-border-hover);transform:scale(1.01)}.sd-card-body{flex:1 1 auto;padding:1rem 1rem}.sd-card-title{margin-bottom:.5rem}.sd-card-subtitle{margin-top:-0.25rem;margin-bottom:0}.sd-card-text:last-child{margin-bottom:0}.sd-card-link:hover{text-decoration:none}.sd-card-link + .card-link{margin-left:1rem}.sd-card-header{padding:.5rem 1rem;margin-bottom:0;background-color:var(--sd-color-card-header);border-bottom:1px solid var(--sd-color-card-border)}.sd-card-header:first-child{border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.sd-card-footer{padding:.5rem 1rem;background-color:var(--sd-color-card-footer);border-top:1px solid var(--sd-color-card-border)}.sd-card-footer:last-child{border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.sd-card-header-tabs{margin-right:-0.5rem;margin-bottom:-0.5rem;margin-left:-0.5rem;border-bottom:0}.sd-card-header-pills{margin-right:-0.5rem;margin-left:-0.5rem}.sd-card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom,.sd-card-img-top{width:100%}.sd-card-img,.sd-card-img-top{border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom{border-bottom-left-radius:calc(0.25rem - 1px);border-bottom-right-radius:calc(0.25rem - 1px)}.sd-cards-carousel{width:100%;display:flex;flex-wrap:nowrap;flex-direction:row;overflow-x:hidden;scroll-snap-type:x mandatory}.sd-cards-carousel.sd-show-scrollbar{overflow-x:auto}.sd-cards-carousel:hover,.sd-cards-carousel:focus{overflow-x:auto}.sd-cards-carousel>.sd-card{flex-shrink:0;scroll-snap-align:start}.sd-cards-carousel>.sd-card:not(:last-child){margin-right:3px}.sd-card-cols-1>.sd-card{width:90%}.sd-card-cols-2>.sd-card{width:45%}.sd-card-cols-3>.sd-card{width:30%}.sd-card-cols-4>.sd-card{width:22.5%}.sd-card-cols-5>.sd-card{width:18%}.sd-card-cols-6>.sd-card{width:15%}.sd-card-cols-7>.sd-card{width:12.8571428571%}.sd-card-cols-8>.sd-card{width:11.25%}.sd-card-cols-9>.sd-card{width:10%}.sd-card-cols-10>.sd-card{width:9%}.sd-card-cols-11>.sd-card{width:8.1818181818%}.sd-card-cols-12>.sd-card{width:7.5%}.sd-container,.sd-container-fluid,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container-xl{margin-left:auto;margin-right:auto;padding-left:var(--sd-gutter-x,0.75rem);padding-right:var(--sd-gutter-x,0.75rem);width:100%}@media (min-width:576px){.sd-container-sm,.sd-container{max-width:540px}}@media (min-width:768px){.sd-container-md,.sd-container-sm,.sd-container{max-width:720px}}@media (min-width:992px){.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:960px}}@media (min-width:1200px){.sd-container-xl,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:1140px}}.sd-row{--sd-gutter-x:1.5rem;--sd-gutter-y:0;display:flex;flex-wrap:wrap;margin-top:calc(var(--sd-gutter-y) * -1);margin-right:calc(var(--sd-gutter-x) * -0.5);margin-left:calc(var(--sd-gutter-x) * -0.5)}.sd-row>*{box-sizing:border-box;flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--sd-gutter-x) * 0.5);padding-left:calc(var(--sd-gutter-x) * 0.5);margin-top:var(--sd-gutter-y)}.sd-col{flex:1 0 0%}.sd-row-cols-auto>*{flex:0 0 auto;width:auto}.sd-flex-row-reverse{flex-direction:row-reverse!important}.sd-row-cols-1>*{flex:0 0 auto;width:100%}.sd-row-cols-2>*{flex:0 0 auto;width:50%}.sd-row-cols-3>*{flex:0 0 auto;width:33.3333333333%}.sd-row-cols-4>*{flex:0 0 auto;width:25%}.sd-row-cols-5>*{flex:0 0 auto;width:20%}.sd-row-cols-6>*{flex:0 0 auto;width:16.6666666667%}.sd-row-cols-7>*{flex:0 0 auto;width:14.2857142857%}.sd-row-cols-8>*{flex:0 0 auto;width:12.5%}.sd-row-cols-9>*{flex:0 0 auto;width:11.1111111111%}.sd-row-cols-10>*{flex:0 0 auto;width:10%}.sd-row-cols-11>*{flex:0 0 auto;width:9.0909090909%}.sd-row-cols-12>*{flex:0 0 auto;width:8.3333333333%}@media (min-width:576px){.sd-col-sm{flex:1 0 0%}.sd-row-cols-sm-auto{flex:1 0 auto;width:100%}.sd-row-cols-sm-1>*{flex:0 0 auto;width:100%}.sd-row-cols-sm-2>*{flex:0 0 auto;width:50%}.sd-row-cols-sm-3>*{flex:0 0 auto;width:33.3333333333%}.sd-row-cols-sm-4>*{flex:0 0 auto;width:25%}.sd-row-cols-sm-5>*{flex:0 0 auto;width:20%}.sd-row-cols-sm-6>*{flex:0 0 auto;width:16.6666666667%}.sd-row-cols-sm-7>*{flex:0 0 auto;width:14.2857142857%}.sd-row-cols-sm-8>*{flex:0 0 auto;width:12.5%}.sd-row-cols-sm-9>*{flex:0 0 auto;width:11.1111111111%}.sd-row-cols-sm-10>*{flex:0 0 auto;width:10%}.sd-row-cols-sm-11>*{flex:0 0 auto;width:9.0909090909%}.sd-row-cols-sm-12>*{flex:0 0 auto;width:8.3333333333%}}@media (min-width:768px){.sd-col-md{flex:1 0 0%}.sd-row-cols-md-auto{flex:1 0 auto;width:100%}.sd-row-cols-md-1>*{flex:0 0 auto;width:100%}.sd-row-cols-md-2>*{flex:0 0 auto;width:50%}.sd-row-cols-md-3>*{flex:0 0 auto;width:33.3333333333%}.sd-row-cols-md-4>*{flex:0 0 auto;width:25%}.sd-row-cols-md-5>*{flex:0 0 auto;width:20%}.sd-row-cols-md-6>*{flex:0 0 auto;width:16.6666666667%}.sd-row-cols-md-7>*{flex:0 0 auto;width:14.2857142857%}.sd-row-cols-md-8>*{flex:0 0 auto;width:12.5%}.sd-row-cols-md-9>*{flex:0 0 auto;width:11.1111111111%}.sd-row-cols-md-10>*{flex:0 0 auto;width:10%}.sd-row-cols-md-11>*{flex:0 0 auto;width:9.0909090909%}.sd-row-cols-md-12>*{flex:0 0 auto;width:8.3333333333%}}@media (min-width:992px){.sd-col-lg{flex:1 0 0%}.sd-row-cols-lg-auto{flex:1 0 auto;width:100%}.sd-row-cols-lg-1>*{flex:0 0 auto;width:100%}.sd-row-cols-lg-2>*{flex:0 0 auto;width:50%}.sd-row-cols-lg-3>*{flex:0 0 auto;width:33.3333333333%}.sd-row-cols-lg-4>*{flex:0 0 auto;width:25%}.sd-row-cols-lg-5>*{flex:0 0 auto;width:20%}.sd-row-cols-lg-6>*{flex:0 0 auto;width:16.6666666667%}.sd-row-cols-lg-7>*{flex:0 0 auto;width:14.2857142857%}.sd-row-cols-lg-8>*{flex:0 0 auto;width:12.5%}.sd-row-cols-lg-9>*{flex:0 0 auto;width:11.1111111111%}.sd-row-cols-lg-10>*{flex:0 0 auto;width:10%}.sd-row-cols-lg-11>*{flex:0 0 auto;width:9.0909090909%}.sd-row-cols-lg-12>*{flex:0 0 auto;width:8.3333333333%}}@media (min-width:1200px){.sd-col-xl{flex:1 0 0%}.sd-row-cols-xl-auto{flex:1 0 auto;width:100%}.sd-row-cols-xl-1>*{flex:0 0 auto;width:100%}.sd-row-cols-xl-2>*{flex:0 0 auto;width:50%}.sd-row-cols-xl-3>*{flex:0 0 auto;width:33.3333333333%}.sd-row-cols-xl-4>*{flex:0 0 auto;width:25%}.sd-row-cols-xl-5>*{flex:0 0 auto;width:20%}.sd-row-cols-xl-6>*{flex:0 0 auto;width:16.6666666667%}.sd-row-cols-xl-7>*{flex:0 0 auto;width:14.2857142857%}.sd-row-cols-xl-8>*{flex:0 0 auto;width:12.5%}.sd-row-cols-xl-9>*{flex:0 0 auto;width:11.1111111111%}.sd-row-cols-xl-10>*{flex:0 0 auto;width:10%}.sd-row-cols-xl-11>*{flex:0 0 auto;width:9.0909090909%}.sd-row-cols-xl-12>*{flex:0 0 auto;width:8.3333333333%}}.sd-col-auto{flex:0 0 auto;width:auto}.sd-col-1{flex:0 0 auto;width:8.3333333333%}.sd-col-2{flex:0 0 auto;width:16.6666666667%}.sd-col-3{flex:0 0 auto;width:25%}.sd-col-4{flex:0 0 auto;width:33.3333333333%}.sd-col-5{flex:0 0 auto;width:41.6666666667%}.sd-col-6{flex:0 0 auto;width:50%}.sd-col-7{flex:0 0 auto;width:58.3333333333%}.sd-col-8{flex:0 0 auto;width:66.6666666667%}.sd-col-9{flex:0 0 auto;width:75%}.sd-col-10{flex:0 0 auto;width:83.3333333333%}.sd-col-11{flex:0 0 auto;width:91.6666666667%}.sd-col-12{flex:0 0 auto;width:100%}.sd-g-0,.sd-gy-0{--sd-gutter-y:0}.sd-g-0,.sd-gx-0{--sd-gutter-x:0}.sd-g-1,.sd-gy-1{--sd-gutter-y:0.25rem}.sd-g-1,.sd-gx-1{--sd-gutter-x:0.25rem}.sd-g-2,.sd-gy-2{--sd-gutter-y:0.5rem}.sd-g-2,.sd-gx-2{--sd-gutter-x:0.5rem}.sd-g-3,.sd-gy-3{--sd-gutter-y:1rem}.sd-g-3,.sd-gx-3{--sd-gutter-x:1rem}.sd-g-4,.sd-gy-4{--sd-gutter-y:1.5rem}.sd-g-4,.sd-gx-4{--sd-gutter-x:1.5rem}.sd-g-5,.sd-gy-5{--sd-gutter-y:3rem}.sd-g-5,.sd-gx-5{--sd-gutter-x:3rem}@media (min-width:576px){.sd-col-sm-auto{flex:0 0 auto;width:auto}.sd-col-sm-1{flex:0 0 auto;width:8.3333333333%}.sd-col-sm-2{flex:0 0 auto;width:16.6666666667%}.sd-col-sm-3{flex:0 0 auto;width:25%}.sd-col-sm-4{flex:0 0 auto;width:33.3333333333%}.sd-col-sm-5{flex:0 0 auto;width:41.6666666667%}.sd-col-sm-6{flex:0 0 auto;width:50%}.sd-col-sm-7{flex:0 0 auto;width:58.3333333333%}.sd-col-sm-8{flex:0 0 auto;width:66.6666666667%}.sd-col-sm-9{flex:0 0 auto;width:75%}.sd-col-sm-10{flex:0 0 auto;width:83.3333333333%}.sd-col-sm-11{flex:0 0 auto;width:91.6666666667%}.sd-col-sm-12{flex:0 0 auto;width:100%}.sd-g-sm-0,.sd-gy-sm-0{--sd-gutter-y:0}.sd-g-sm-0,.sd-gx-sm-0{--sd-gutter-x:0}.sd-g-sm-1,.sd-gy-sm-1{--sd-gutter-y:0.25rem}.sd-g-sm-1,.sd-gx-sm-1{--sd-gutter-x:0.25rem}.sd-g-sm-2,.sd-gy-sm-2{--sd-gutter-y:0.5rem}.sd-g-sm-2,.sd-gx-sm-2{--sd-gutter-x:0.5rem}.sd-g-sm-3,.sd-gy-sm-3{--sd-gutter-y:1rem}.sd-g-sm-3,.sd-gx-sm-3{--sd-gutter-x:1rem}.sd-g-sm-4,.sd-gy-sm-4{--sd-gutter-y:1.5rem}.sd-g-sm-4,.sd-gx-sm-4{--sd-gutter-x:1.5rem}.sd-g-sm-5,.sd-gy-sm-5{--sd-gutter-y:3rem}.sd-g-sm-5,.sd-gx-sm-5{--sd-gutter-x:3rem}}@media (min-width:768px){.sd-col-md-auto{flex:0 0 auto;width:auto}.sd-col-md-1{flex:0 0 auto;width:8.3333333333%}.sd-col-md-2{flex:0 0 auto;width:16.6666666667%}.sd-col-md-3{flex:0 0 auto;width:25%}.sd-col-md-4{flex:0 0 auto;width:33.3333333333%}.sd-col-md-5{flex:0 0 auto;width:41.6666666667%}.sd-col-md-6{flex:0 0 auto;width:50%}.sd-col-md-7{flex:0 0 auto;width:58.3333333333%}.sd-col-md-8{flex:0 0 auto;width:66.6666666667%}.sd-col-md-9{flex:0 0 auto;width:75%}.sd-col-md-10{flex:0 0 auto;width:83.3333333333%}.sd-col-md-11{flex:0 0 auto;width:91.6666666667%}.sd-col-md-12{flex:0 0 auto;width:100%}.sd-g-md-0,.sd-gy-md-0{--sd-gutter-y:0}.sd-g-md-0,.sd-gx-md-0{--sd-gutter-x:0}.sd-g-md-1,.sd-gy-md-1{--sd-gutter-y:0.25rem}.sd-g-md-1,.sd-gx-md-1{--sd-gutter-x:0.25rem}.sd-g-md-2,.sd-gy-md-2{--sd-gutter-y:0.5rem}.sd-g-md-2,.sd-gx-md-2{--sd-gutter-x:0.5rem}.sd-g-md-3,.sd-gy-md-3{--sd-gutter-y:1rem}.sd-g-md-3,.sd-gx-md-3{--sd-gutter-x:1rem}.sd-g-md-4,.sd-gy-md-4{--sd-gutter-y:1.5rem}.sd-g-md-4,.sd-gx-md-4{--sd-gutter-x:1.5rem}.sd-g-md-5,.sd-gy-md-5{--sd-gutter-y:3rem}.sd-g-md-5,.sd-gx-md-5{--sd-gutter-x:3rem}}@media (min-width:992px){.sd-col-lg-auto{flex:0 0 auto;width:auto}.sd-col-lg-1{flex:0 0 auto;width:8.3333333333%}.sd-col-lg-2{flex:0 0 auto;width:16.6666666667%}.sd-col-lg-3{flex:0 0 auto;width:25%}.sd-col-lg-4{flex:0 0 auto;width:33.3333333333%}.sd-col-lg-5{flex:0 0 auto;width:41.6666666667%}.sd-col-lg-6{flex:0 0 auto;width:50%}.sd-col-lg-7{flex:0 0 auto;width:58.3333333333%}.sd-col-lg-8{flex:0 0 auto;width:66.6666666667%}.sd-col-lg-9{flex:0 0 auto;width:75%}.sd-col-lg-10{flex:0 0 auto;width:83.3333333333%}.sd-col-lg-11{flex:0 0 auto;width:91.6666666667%}.sd-col-lg-12{flex:0 0 auto;width:100%}.sd-g-lg-0,.sd-gy-lg-0{--sd-gutter-y:0}.sd-g-lg-0,.sd-gx-lg-0{--sd-gutter-x:0}.sd-g-lg-1,.sd-gy-lg-1{--sd-gutter-y:0.25rem}.sd-g-lg-1,.sd-gx-lg-1{--sd-gutter-x:0.25rem}.sd-g-lg-2,.sd-gy-lg-2{--sd-gutter-y:0.5rem}.sd-g-lg-2,.sd-gx-lg-2{--sd-gutter-x:0.5rem}.sd-g-lg-3,.sd-gy-lg-3{--sd-gutter-y:1rem}.sd-g-lg-3,.sd-gx-lg-3{--sd-gutter-x:1rem}.sd-g-lg-4,.sd-gy-lg-4{--sd-gutter-y:1.5rem}.sd-g-lg-4,.sd-gx-lg-4{--sd-gutter-x:1.5rem}.sd-g-lg-5,.sd-gy-lg-5{--sd-gutter-y:3rem}.sd-g-lg-5,.sd-gx-lg-5{--sd-gutter-x:3rem}}@media (min-width:1200px){.sd-col-xl-auto{flex:0 0 auto;width:auto}.sd-col-xl-1{flex:0 0 auto;width:8.3333333333%}.sd-col-xl-2{flex:0 0 auto;width:16.6666666667%}.sd-col-xl-3{flex:0 0 auto;width:25%}.sd-col-xl-4{flex:0 0 auto;width:33.3333333333%}.sd-col-xl-5{flex:0 0 auto;width:41.6666666667%}.sd-col-xl-6{flex:0 0 auto;width:50%}.sd-col-xl-7{flex:0 0 auto;width:58.3333333333%}.sd-col-xl-8{flex:0 0 auto;width:66.6666666667%}.sd-col-xl-9{flex:0 0 auto;width:75%}.sd-col-xl-10{flex:0 0 auto;width:83.3333333333%}.sd-col-xl-11{flex:0 0 auto;width:91.6666666667%}.sd-col-xl-12{flex:0 0 auto;width:100%}.sd-g-xl-0,.sd-gy-xl-0{--sd-gutter-y:0}.sd-g-xl-0,.sd-gx-xl-0{--sd-gutter-x:0}.sd-g-xl-1,.sd-gy-xl-1{--sd-gutter-y:0.25rem}.sd-g-xl-1,.sd-gx-xl-1{--sd-gutter-x:0.25rem}.sd-g-xl-2,.sd-gy-xl-2{--sd-gutter-y:0.5rem}.sd-g-xl-2,.sd-gx-xl-2{--sd-gutter-x:0.5rem}.sd-g-xl-3,.sd-gy-xl-3{--sd-gutter-y:1rem}.sd-g-xl-3,.sd-gx-xl-3{--sd-gutter-x:1rem}.sd-g-xl-4,.sd-gy-xl-4{--sd-gutter-y:1.5rem}.sd-g-xl-4,.sd-gx-xl-4{--sd-gutter-x:1.5rem}.sd-g-xl-5,.sd-gy-xl-5{--sd-gutter-y:3rem}.sd-g-xl-5,.sd-gx-xl-5{--sd-gutter-x:3rem}}details.sd-dropdown{position:relative;font-size:var(--sd-fontsize-dropdown)}details.sd-dropdown:hover{cursor:pointer}details.sd-dropdown .sd-summary-content{cursor:default}details.sd-dropdown summary.sd-summary-title{padding:.5em .6em .5em 1em;font-size:var(--sd-fontsize-dropdown-title);font-weight:var(--sd-fontweight-dropdown-title);user-select:none;list-style:none;display:inline-flex;justify-content:space-between;outline-offset:.25rem}details.sd-dropdown summary.sd-summary-title::-webkit-details-marker{display:none}details.sd-dropdown summary.sd-summary-title .sd-summary-icon{margin-right:.6em;display:inline-flex;align-items:center}details.sd-dropdown summary.sd-summary-title .sd-summary-icon svg{opacity:.8}details.sd-dropdown summary.sd-summary-title .sd-summary-text{flex-grow:1;line-height:1.5;padding-right:.5rem}details.sd-dropdown summary.sd-summary-title .sd-summary-state-marker{pointer-events:none;display:inline-flex;align-self:center}details.sd-dropdown summary.sd-summary-title .sd-summary-state-marker svg{opacity:.6}details.sd-dropdown summary.sd-summary-title:hover .sd-summary-state-marker svg{opacity:1;transform:scale(1.1)}details.sd-dropdown[open] summary .sd-octicon.no-title{visibility:hidden}details.sd-dropdown .sd-summary-chevron-right{transition:.25s}details.sd-dropdown[open]>.sd-summary-title .sd-summary-chevron-right{transform:rotate(90deg)}details.sd-dropdown[open]>.sd-summary-title .sd-summary-chevron-down{transform:rotate(180deg)}details.sd-dropdown:not([open]).sd-card{border:none}details.sd-dropdown:not([open])>.sd-card-header{border:1px solid var(--sd-color-card-border);border-radius:.25rem}details.sd-dropdown.sd-fade-in[open] summary ~ *{animation:sd-fade-in .5s ease-in-out}details.sd-dropdown.sd-fade-in-slide-down[open] summary ~ *{animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out}.sd-col>.sd-dropdown{width:100%}.sd-summary-content>.sd-tab-set:first-child{margin-top:0}@keyframes sd-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes sd-slide-down{0%{transform:translate(0,-10px)}100%{transform:translate(0,0)}}.sd-tab-set{border-radius:.125rem;display:flex;flex-wrap:wrap;margin:1em 0;position:relative}.sd-tab-set>input{opacity:0;position:absolute}.sd-tab-set>input:checked + label{border-color:var(--sd-color-tabs-underline-active);color:var(--sd-color-tabs-label-active)}.sd-tab-set>input:checked + label + .sd-tab-content{display:block}.sd-tab-set>input:not(:checked) + label:hover{color:var(--sd-color-tabs-label-hover);border-color:var(--sd-color-tabs-underline-hover)}.sd-tab-set>input:focus + label{outline-style:auto}.sd-tab-set>input:not(:focus-visible) + label{outline:none;-webkit-tap-highlight-color:transparent}.sd-tab-set>label{border-bottom:.125rem solid transparent;margin-bottom:0;color:var(--sd-color-tabs-label-inactive);border-color:var(--sd-color-tabs-underline-inactive);cursor:pointer;font-size:var(--sd-fontsize-tabs-label);font-weight:700;padding:.5em 1.25em;transition:color 250ms;width:auto;z-index:1}html .sd-tab-set>label:hover{color:var(--sd-color-tabs-label-active)}.sd-col>.sd-tab-set{width:100%}.sd-tab-content{box-shadow:0 -0.0625rem var(--sd-color-tabs-overline),0 .0625rem var(--sd-color-tabs-underline);display:none;order:99;padding-bottom:.75rem;padding-top:.75rem;width:100%}.sd-tab-content>:first-child{margin-top:0!important}.sd-tab-content>:last-child{margin-bottom:0!important}.sd-tab-content>.sd-tab-set{margin:0}.sd-sphinx-override,.sd-sphinx-override *{box-sizing:border-box}.sd-sphinx-override p{margin-top:0}.sd-sphinx-override:focus-visible{outline-offset:.25rem}:root{--sd-color-primary:#0071bc;--sd-color-secondary:#6c757d;--sd-color-success:#28a745;--sd-color-info:#17a2b8;--sd-color-warning:#f0b37e;--sd-color-danger:#dc3545;--sd-color-light:#f8f9fa;--sd-color-muted:#6c757d;--sd-color-dark:#212529;--sd-color-black:black;--sd-color-white:white;--sd-color-primary-highlight:#0060a0;--sd-color-primary-highlight:color-mix(in srgb,black 15%,var(--sd-color-primary));--sd-color-secondary-highlight:#5c636a;--sd-color-secondary-highlight:color-mix(in srgb,black 15%,var(--sd-color-secondary));--sd-color-success-highlight:#228e3b;--sd-color-success-highlight:color-mix(in srgb,black 15%,var(--sd-color-success));--sd-color-info-highlight:#148a9c;--sd-color-info-highlight:color-mix(in srgb,black 15%,var(--sd-color-info));--sd-color-warning-highlight:#cc986b;--sd-color-warning-highlight:color-mix(in srgb,black 15%,var(--sd-color-warning));--sd-color-danger-highlight:#bb2d3b;--sd-color-danger-highlight:color-mix(in srgb,black 15%,var(--sd-color-danger));--sd-color-light-highlight:#d3d4d5;--sd-color-light-highlight:color-mix(in srgb,black 15%,var(--sd-color-light));--sd-color-muted-highlight:#5c636a;--sd-color-muted-highlight:color-mix(in srgb,black 15%,var(--sd-color-muted));--sd-color-dark-highlight:#1c1f23;--sd-color-dark-highlight:color-mix(in srgb,black 15%,var(--sd-color-dark));--sd-color-black-highlight:black;--sd-color-black-highlight:color-mix(in srgb,black 15%,var(--sd-color-black));--sd-color-white-highlight:#d9d9d9;--sd-color-white-highlight:color-mix(in srgb,black 15%,var(--sd-color-white));--sd-color-primary-bg:rgba(0,113,188,0.2);--sd-color-secondary-bg:rgba(108,117,125,0.2);--sd-color-success-bg:rgba(40,167,69,0.2);--sd-color-info-bg:rgba(23,162,184,0.2);--sd-color-warning-bg:rgba(240,179,126,0.2);--sd-color-danger-bg:rgba(220,53,69,0.2);--sd-color-light-bg:rgba(248,249,250,0.2);--sd-color-muted-bg:rgba(108,117,125,0.2);--sd-color-dark-bg:rgba(33,37,41,0.2);--sd-color-black-bg:rgba(0,0,0,0.2);--sd-color-white-bg:rgba(255,255,255,0.2);--sd-color-primary-text:#fff;--sd-color-secondary-text:#fff;--sd-color-success-text:#fff;--sd-color-info-text:#fff;--sd-color-warning-text:#212529;--sd-color-danger-text:#fff;--sd-color-light-text:#212529;--sd-color-muted-text:#fff;--sd-color-dark-text:#fff;--sd-color-black-text:#fff;--sd-color-white-text:#212529;--sd-color-shadow:rgba(0,0,0,0.15);--sd-color-card-border:rgba(0,0,0,0.125);--sd-color-card-border-hover:hsla(231,99%,66%,1);--sd-color-card-background:transparent;--sd-color-card-text:inherit;--sd-color-card-header:transparent;--sd-color-card-footer:transparent;--sd-color-tabs-label-active:hsla(231,99%,66%,1);--sd-color-tabs-label-hover:hsla(231,99%,66%,1);--sd-color-tabs-label-inactive:hsl(0,0%,66%);--sd-color-tabs-underline-active:hsla(231,99%,66%,1);--sd-color-tabs-underline-hover:rgba(178,206,245,0.62);--sd-color-tabs-underline-inactive:transparent;--sd-color-tabs-overline:rgb(222,222,222);--sd-color-tabs-underline:rgb(222,222,222);--sd-fontsize-tabs-label:1rem;--sd-fontsize-dropdown:inherit;--sd-fontsize-dropdown-title:1rem;--sd-fontweight-dropdown-title:700} +.sd-bg-primary{background-color:var(--sd-color-primary)!important}.sd-bg-text-primary{color:var(--sd-color-primary-text)!important}button.sd-bg-primary:focus,button.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight)!important}button.sd-bg-primary:focus-visible{outline-color:var(--sd-color-primary-highlight)!important}a.sd-bg-primary:focus,a.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight)!important}a.sd-bg-primary:focus-visible{outline-color:var(--sd-color-primary-highlight)!important}.sd-bg-secondary{background-color:var(--sd-color-secondary)!important}.sd-bg-text-secondary{color:var(--sd-color-secondary-text)!important}button.sd-bg-secondary:focus,button.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight)!important}button.sd-bg-secondary:focus-visible{outline-color:var(--sd-color-secondary-highlight)!important}a.sd-bg-secondary:focus,a.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight)!important}a.sd-bg-secondary:focus-visible{outline-color:var(--sd-color-secondary-highlight)!important}.sd-bg-success{background-color:var(--sd-color-success)!important}.sd-bg-text-success{color:var(--sd-color-success-text)!important}button.sd-bg-success:focus,button.sd-bg-success:hover{background-color:var(--sd-color-success-highlight)!important}button.sd-bg-success:focus-visible{outline-color:var(--sd-color-success-highlight)!important}a.sd-bg-success:focus,a.sd-bg-success:hover{background-color:var(--sd-color-success-highlight)!important}a.sd-bg-success:focus-visible{outline-color:var(--sd-color-success-highlight)!important}.sd-bg-info{background-color:var(--sd-color-info)!important}.sd-bg-text-info{color:var(--sd-color-info-text)!important}button.sd-bg-info:focus,button.sd-bg-info:hover{background-color:var(--sd-color-info-highlight)!important}button.sd-bg-info:focus-visible{outline-color:var(--sd-color-info-highlight)!important}a.sd-bg-info:focus,a.sd-bg-info:hover{background-color:var(--sd-color-info-highlight)!important}a.sd-bg-info:focus-visible{outline-color:var(--sd-color-info-highlight)!important}.sd-bg-warning{background-color:var(--sd-color-warning)!important}.sd-bg-text-warning{color:var(--sd-color-warning-text)!important}button.sd-bg-warning:focus,button.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight)!important}button.sd-bg-warning:focus-visible{outline-color:var(--sd-color-warning-highlight)!important}a.sd-bg-warning:focus,a.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight)!important}a.sd-bg-warning:focus-visible{outline-color:var(--sd-color-warning-highlight)!important}.sd-bg-danger{background-color:var(--sd-color-danger)!important}.sd-bg-text-danger{color:var(--sd-color-danger-text)!important}button.sd-bg-danger:focus,button.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight)!important}button.sd-bg-danger:focus-visible{outline-color:var(--sd-color-danger-highlight)!important}a.sd-bg-danger:focus,a.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight)!important}a.sd-bg-danger:focus-visible{outline-color:var(--sd-color-danger-highlight)!important}.sd-bg-light{background-color:var(--sd-color-light)!important}.sd-bg-text-light{color:var(--sd-color-light-text)!important}button.sd-bg-light:focus,button.sd-bg-light:hover{background-color:var(--sd-color-light-highlight)!important}button.sd-bg-light:focus-visible{outline-color:var(--sd-color-light-highlight)!important}a.sd-bg-light:focus,a.sd-bg-light:hover{background-color:var(--sd-color-light-highlight)!important}a.sd-bg-light:focus-visible{outline-color:var(--sd-color-light-highlight)!important}.sd-bg-muted{background-color:var(--sd-color-muted)!important}.sd-bg-text-muted{color:var(--sd-color-muted-text)!important}button.sd-bg-muted:focus,button.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight)!important}button.sd-bg-muted:focus-visible{outline-color:var(--sd-color-muted-highlight)!important}a.sd-bg-muted:focus,a.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight)!important}a.sd-bg-muted:focus-visible{outline-color:var(--sd-color-muted-highlight)!important}.sd-bg-dark{background-color:var(--sd-color-dark)!important}.sd-bg-text-dark{color:var(--sd-color-dark-text)!important}button.sd-bg-dark:focus,button.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight)!important}button.sd-bg-dark:focus-visible{outline-color:var(--sd-color-dark-highlight)!important}a.sd-bg-dark:focus,a.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight)!important}a.sd-bg-dark:focus-visible{outline-color:var(--sd-color-dark-highlight)!important}.sd-bg-black{background-color:var(--sd-color-black)!important}.sd-bg-text-black{color:var(--sd-color-black-text)!important}button.sd-bg-black:focus,button.sd-bg-black:hover{background-color:var(--sd-color-black-highlight)!important}button.sd-bg-black:focus-visible{outline-color:var(--sd-color-black-highlight)!important}a.sd-bg-black:focus,a.sd-bg-black:hover{background-color:var(--sd-color-black-highlight)!important}a.sd-bg-black:focus-visible{outline-color:var(--sd-color-black-highlight)!important}.sd-bg-white{background-color:var(--sd-color-white)!important}.sd-bg-text-white{color:var(--sd-color-white-text)!important}button.sd-bg-white:focus,button.sd-bg-white:hover{background-color:var(--sd-color-white-highlight)!important}button.sd-bg-white:focus-visible{outline-color:var(--sd-color-white-highlight)!important}a.sd-bg-white:focus,a.sd-bg-white:hover{background-color:var(--sd-color-white-highlight)!important}a.sd-bg-white:focus-visible{outline-color:var(--sd-color-white-highlight)!important}.sd-text-primary,.sd-text-primary>p{color:var(--sd-color-primary)!important}a.sd-text-primary:focus,a.sd-text-primary:hover{color:var(--sd-color-primary-highlight)!important}.sd-text-secondary,.sd-text-secondary>p{color:var(--sd-color-secondary)!important}a.sd-text-secondary:focus,a.sd-text-secondary:hover{color:var(--sd-color-secondary-highlight)!important}.sd-text-success,.sd-text-success>p{color:var(--sd-color-success)!important}a.sd-text-success:focus,a.sd-text-success:hover{color:var(--sd-color-success-highlight)!important}.sd-text-info,.sd-text-info>p{color:var(--sd-color-info)!important}a.sd-text-info:focus,a.sd-text-info:hover{color:var(--sd-color-info-highlight)!important}.sd-text-warning,.sd-text-warning>p{color:var(--sd-color-warning)!important}a.sd-text-warning:focus,a.sd-text-warning:hover{color:var(--sd-color-warning-highlight)!important}.sd-text-danger,.sd-text-danger>p{color:var(--sd-color-danger)!important}a.sd-text-danger:focus,a.sd-text-danger:hover{color:var(--sd-color-danger-highlight)!important}.sd-text-light,.sd-text-light>p{color:var(--sd-color-light)!important}a.sd-text-light:focus,a.sd-text-light:hover{color:var(--sd-color-light-highlight)!important}.sd-text-muted,.sd-text-muted>p{color:var(--sd-color-muted)!important}a.sd-text-muted:focus,a.sd-text-muted:hover{color:var(--sd-color-muted-highlight)!important}.sd-text-dark,.sd-text-dark>p{color:var(--sd-color-dark)!important}a.sd-text-dark:focus,a.sd-text-dark:hover{color:var(--sd-color-dark-highlight)!important}.sd-text-black,.sd-text-black>p{color:var(--sd-color-black)!important}a.sd-text-black:focus,a.sd-text-black:hover{color:var(--sd-color-black-highlight)!important}.sd-text-white,.sd-text-white>p{color:var(--sd-color-white)!important}a.sd-text-white:focus,a.sd-text-white:hover{color:var(--sd-color-white-highlight)!important}.sd-outline-primary{border-color:var(--sd-color-primary)!important;border-style:solid!important;border-width:1px!important}a.sd-outline-primary:focus,a.sd-outline-primary:hover{border-color:var(--sd-color-primary-highlight)!important}a.sd-outline-primary:focus-visible{outline-color:var(--sd-color-primary-highlight)!important}.sd-outline-secondary{border-color:var(--sd-color-secondary)!important;border-style:solid!important;border-width:1px!important}a.sd-outline-secondary:focus,a.sd-outline-secondary:hover{border-color:var(--sd-color-secondary-highlight)!important}a.sd-outline-secondary:focus-visible{outline-color:var(--sd-color-secondary-highlight)!important}.sd-outline-success{border-color:var(--sd-color-success)!important;border-style:solid!important;border-width:1px!important}a.sd-outline-success:focus,a.sd-outline-success:hover{border-color:var(--sd-color-success-highlight)!important}a.sd-outline-success:focus-visible{outline-color:var(--sd-color-success-highlight)!important}.sd-outline-info{border-color:var(--sd-color-info)!important;border-style:solid!important;border-width:1px!important}a.sd-outline-info:focus,a.sd-outline-info:hover{border-color:var(--sd-color-info-highlight)!important}a.sd-outline-info:focus-visible{outline-color:var(--sd-color-info-highlight)!important}.sd-outline-warning{border-color:var(--sd-color-warning)!important;border-style:solid!important;border-width:1px!important}a.sd-outline-warning:focus,a.sd-outline-warning:hover{border-color:var(--sd-color-warning-highlight)!important}a.sd-outline-warning:focus-visible{outline-color:var(--sd-color-warning-highlight)!important}.sd-outline-danger{border-color:var(--sd-color-danger)!important;border-style:solid!important;border-width:1px!important}a.sd-outline-danger:focus,a.sd-outline-danger:hover{border-color:var(--sd-color-danger-highlight)!important}a.sd-outline-danger:focus-visible{outline-color:var(--sd-color-danger-highlight)!important}.sd-outline-light{border-color:var(--sd-color-light)!important;border-style:solid!important;border-width:1px!important}a.sd-outline-light:focus,a.sd-outline-light:hover{border-color:var(--sd-color-light-highlight)!important}a.sd-outline-light:focus-visible{outline-color:var(--sd-color-light-highlight)!important}.sd-outline-muted{border-color:var(--sd-color-muted)!important;border-style:solid!important;border-width:1px!important}a.sd-outline-muted:focus,a.sd-outline-muted:hover{border-color:var(--sd-color-muted-highlight)!important}a.sd-outline-muted:focus-visible{outline-color:var(--sd-color-muted-highlight)!important}.sd-outline-dark{border-color:var(--sd-color-dark)!important;border-style:solid!important;border-width:1px!important}a.sd-outline-dark:focus,a.sd-outline-dark:hover{border-color:var(--sd-color-dark-highlight)!important}a.sd-outline-dark:focus-visible{outline-color:var(--sd-color-dark-highlight)!important}.sd-outline-black{border-color:var(--sd-color-black)!important;border-style:solid!important;border-width:1px!important}a.sd-outline-black:focus,a.sd-outline-black:hover{border-color:var(--sd-color-black-highlight)!important}a.sd-outline-black:focus-visible{outline-color:var(--sd-color-black-highlight)!important}.sd-outline-white{border-color:var(--sd-color-white)!important;border-style:solid!important;border-width:1px!important}a.sd-outline-white:focus,a.sd-outline-white:hover{border-color:var(--sd-color-white-highlight)!important}a.sd-outline-white:focus-visible{outline-color:var(--sd-color-white-highlight)!important}.sd-bg-transparent{background-color:transparent!important}.sd-outline-transparent{border-color:transparent!important}.sd-text-transparent{color:transparent!important}.sd-p-0{padding:0!important}.sd-pt-0,.sd-py-0{padding-top:0!important}.sd-pr-0,.sd-px-0{padding-right:0!important}.sd-pb-0,.sd-py-0{padding-bottom:0!important}.sd-pl-0,.sd-px-0{padding-left:0!important}.sd-p-1{padding:.25rem!important}.sd-pt-1,.sd-py-1{padding-top:.25rem!important}.sd-pr-1,.sd-px-1{padding-right:.25rem!important}.sd-pb-1,.sd-py-1{padding-bottom:.25rem!important}.sd-pl-1,.sd-px-1{padding-left:.25rem!important}.sd-p-2{padding:.5rem!important}.sd-pt-2,.sd-py-2{padding-top:.5rem!important}.sd-pr-2,.sd-px-2{padding-right:.5rem!important}.sd-pb-2,.sd-py-2{padding-bottom:.5rem!important}.sd-pl-2,.sd-px-2{padding-left:.5rem!important}.sd-p-3{padding:1rem!important}.sd-pt-3,.sd-py-3{padding-top:1rem!important}.sd-pr-3,.sd-px-3{padding-right:1rem!important}.sd-pb-3,.sd-py-3{padding-bottom:1rem!important}.sd-pl-3,.sd-px-3{padding-left:1rem!important}.sd-p-4{padding:1.5rem!important}.sd-pt-4,.sd-py-4{padding-top:1.5rem!important}.sd-pr-4,.sd-px-4{padding-right:1.5rem!important}.sd-pb-4,.sd-py-4{padding-bottom:1.5rem!important}.sd-pl-4,.sd-px-4{padding-left:1.5rem!important}.sd-p-5{padding:3rem!important}.sd-pt-5,.sd-py-5{padding-top:3rem!important}.sd-pr-5,.sd-px-5{padding-right:3rem!important}.sd-pb-5,.sd-py-5{padding-bottom:3rem!important}.sd-pl-5,.sd-px-5{padding-left:3rem!important}.sd-m-auto{margin:auto!important}.sd-mt-auto,.sd-my-auto{margin-top:auto!important}.sd-mr-auto,.sd-mx-auto{margin-right:auto!important}.sd-mb-auto,.sd-my-auto{margin-bottom:auto!important}.sd-ml-auto,.sd-mx-auto{margin-left:auto!important}.sd-m-0{margin:0!important}.sd-mt-0,.sd-my-0{margin-top:0!important}.sd-mr-0,.sd-mx-0{margin-right:0!important}.sd-mb-0,.sd-my-0{margin-bottom:0!important}.sd-ml-0,.sd-mx-0{margin-left:0!important}.sd-m-1{margin:.25rem!important}.sd-mt-1,.sd-my-1{margin-top:.25rem!important}.sd-mr-1,.sd-mx-1{margin-right:.25rem!important}.sd-mb-1,.sd-my-1{margin-bottom:.25rem!important}.sd-ml-1,.sd-mx-1{margin-left:.25rem!important}.sd-m-2{margin:.5rem!important}.sd-mt-2,.sd-my-2{margin-top:.5rem!important}.sd-mr-2,.sd-mx-2{margin-right:.5rem!important}.sd-mb-2,.sd-my-2{margin-bottom:.5rem!important}.sd-ml-2,.sd-mx-2{margin-left:.5rem!important}.sd-m-3{margin:1rem!important}.sd-mt-3,.sd-my-3{margin-top:1rem!important}.sd-mr-3,.sd-mx-3{margin-right:1rem!important}.sd-mb-3,.sd-my-3{margin-bottom:1rem!important}.sd-ml-3,.sd-mx-3{margin-left:1rem!important}.sd-m-4{margin:1.5rem!important}.sd-mt-4,.sd-my-4{margin-top:1.5rem!important}.sd-mr-4,.sd-mx-4{margin-right:1.5rem!important}.sd-mb-4,.sd-my-4{margin-bottom:1.5rem!important}.sd-ml-4,.sd-mx-4{margin-left:1.5rem!important}.sd-m-5{margin:3rem!important}.sd-mt-5,.sd-my-5{margin-top:3rem!important}.sd-mr-5,.sd-mx-5{margin-right:3rem!important}.sd-mb-5,.sd-my-5{margin-bottom:3rem!important}.sd-ml-5,.sd-mx-5{margin-left:3rem!important}.sd-w-25{width:25%!important}.sd-w-50{width:50%!important}.sd-w-75{width:75%!important}.sd-w-100{width:100%!important}.sd-w-auto{width:auto!important}.sd-h-25{height:25%!important}.sd-h-50{height:50%!important}.sd-h-75{height:75%!important}.sd-h-100{height:100%!important}.sd-h-auto{height:auto!important}.sd-d-none{display:none!important}.sd-d-inline{display:inline!important}.sd-d-inline-block{display:inline-block!important}.sd-d-block{display:block!important}.sd-d-grid{display:grid!important}.sd-d-flex-row{display:flex!important;flex-direction:row!important}.sd-d-flex-column{display:flex!important;flex-direction:column!important}.sd-d-inline-flex{display:inline-flex!important}.sd-align-major-start{justify-content:flex-start!important}.sd-align-major-end{justify-content:flex-end!important}.sd-align-major-center{justify-content:center!important}.sd-align-major-justify{justify-content:space-between!important}.sd-align-major-spaced{justify-content:space-evenly!important}.sd-align-minor-start{align-items:flex-start!important}.sd-align-minor-end{align-items:flex-end!important}.sd-align-minor-center{align-items:center!important}.sd-align-minor-stretch{align-items:stretch!important}@media (min-width:576px){.sd-d-sm-none{display:none!important}.sd-d-sm-inline{display:inline!important}.sd-d-sm-inline-block{display:inline-block!important}.sd-d-sm-block{display:block!important}.sd-d-sm-grid{display:grid!important}.sd-d-sm-flex{display:flex!important}.sd-d-sm-inline-flex{display:inline-flex!important}}@media (min-width:768px){.sd-d-md-none{display:none!important}.sd-d-md-inline{display:inline!important}.sd-d-md-inline-block{display:inline-block!important}.sd-d-md-block{display:block!important}.sd-d-md-grid{display:grid!important}.sd-d-md-flex{display:flex!important}.sd-d-md-inline-flex{display:inline-flex!important}}@media (min-width:992px){.sd-d-lg-none{display:none!important}.sd-d-lg-inline{display:inline!important}.sd-d-lg-inline-block{display:inline-block!important}.sd-d-lg-block{display:block!important}.sd-d-lg-grid{display:grid!important}.sd-d-lg-flex{display:flex!important}.sd-d-lg-inline-flex{display:inline-flex!important}}@media (min-width:1200px){.sd-d-xl-none{display:none!important}.sd-d-xl-inline{display:inline!important}.sd-d-xl-inline-block{display:inline-block!important}.sd-d-xl-block{display:block!important}.sd-d-xl-grid{display:grid!important}.sd-d-xl-flex{display:flex!important}.sd-d-xl-inline-flex{display:inline-flex!important}}.sd-text-justify{text-align:justify!important}.sd-text-left{text-align:left!important}.sd-text-right{text-align:right!important}.sd-text-center{text-align:center!important}.sd-font-weight-light{font-weight:300!important}.sd-font-weight-lighter{font-weight:lighter!important}.sd-font-weight-normal{font-weight:400!important}.sd-font-weight-bold{font-weight:700!important}.sd-font-weight-bolder{font-weight:bolder!important}.sd-font-italic{font-style:italic!important}.sd-text-decoration-none{text-decoration:none!important}.sd-text-lowercase{text-transform:lowercase!important}.sd-text-uppercase{text-transform:uppercase!important}.sd-text-capitalize{text-transform:capitalize!important}.sd-text-wrap{white-space:normal!important}.sd-text-nowrap{white-space:nowrap!important}.sd-text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sd-fs-1,.sd-fs-1>p{font-size:calc(1.375rem + 1.5vw)!important;line-height:unset!important}.sd-fs-2,.sd-fs-2>p{font-size:calc(1.325rem + 0.9vw)!important;line-height:unset!important}.sd-fs-3,.sd-fs-3>p{font-size:calc(1.3rem + 0.6vw)!important;line-height:unset!important}.sd-fs-4,.sd-fs-4>p{font-size:calc(1.275rem + 0.3vw)!important;line-height:unset!important}.sd-fs-5,.sd-fs-5>p{font-size:1.25rem!important;line-height:unset!important}.sd-fs-6,.sd-fs-6>p{font-size:1rem!important;line-height:unset!important}.sd-border-0{border:0 solid!important}.sd-border-top-0{border-top:0 solid!important}.sd-border-bottom-0{border-bottom:0 solid!important}.sd-border-right-0{border-right:0 solid!important}.sd-border-left-0{border-left:0 solid!important}.sd-border-1{border:1px solid!important}.sd-border-top-1{border-top:1px solid!important}.sd-border-bottom-1{border-bottom:1px solid!important}.sd-border-right-1{border-right:1px solid!important}.sd-border-left-1{border-left:1px solid!important}.sd-border-2{border:2px solid!important}.sd-border-top-2{border-top:2px solid!important}.sd-border-bottom-2{border-bottom:2px solid!important}.sd-border-right-2{border-right:2px solid!important}.sd-border-left-2{border-left:2px solid!important}.sd-border-3{border:3px solid!important}.sd-border-top-3{border-top:3px solid!important}.sd-border-bottom-3{border-bottom:3px solid!important}.sd-border-right-3{border-right:3px solid!important}.sd-border-left-3{border-left:3px solid!important}.sd-border-4{border:4px solid!important}.sd-border-top-4{border-top:4px solid!important}.sd-border-bottom-4{border-bottom:4px solid!important}.sd-border-right-4{border-right:4px solid!important}.sd-border-left-4{border-left:4px solid!important}.sd-border-5{border:5px solid!important}.sd-border-top-5{border-top:5px solid!important}.sd-border-bottom-5{border-bottom:5px solid!important}.sd-border-right-5{border-right:5px solid!important}.sd-border-left-5{border-left:5px solid!important}.sd-rounded-0{border-radius:0!important}.sd-rounded-1{border-radius:.2rem!important}.sd-rounded-2{border-radius:.3rem!important}.sd-rounded-3{border-radius:.5rem!important}.sd-rounded-pill{border-radius:50rem!important}.sd-rounded-circle{border-radius:50%!important}.shadow-none{box-shadow:none!important}.sd-shadow-sm{box-shadow:0 .125rem .25rem var(--sd-color-shadow)!important}.sd-shadow-md{box-shadow:0 .5rem 1rem var(--sd-color-shadow)!important}.sd-shadow-lg{box-shadow:0 1rem 3rem var(--sd-color-shadow)!important}@keyframes sd-slide-from-left{0%{transform:translateX(-100%)}100%{transform:translateX(0)}}@keyframes sd-slide-from-right{0%{transform:translateX(200%)}100%{transform:translateX(0)}}@keyframes sd-grow100{0%{transform:scale(0);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50{0%{transform:scale(0.5);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50-rot20{0%{transform:scale(0.5) rotateZ(-20deg);opacity:.5}75%{transform:scale(1) rotateZ(5deg);opacity:1}95%{transform:scale(1) rotateZ(-1deg);opacity:1}100%{transform:scale(1) rotateZ(0);opacity:1}}.sd-animate-slide-from-left{animation:1s ease-out 0s 1 normal none running sd-slide-from-left}.sd-animate-slide-from-right{animation:1s ease-out 0s 1 normal none running sd-slide-from-right}.sd-animate-grow100{animation:1s ease-out 0s 1 normal none running sd-grow100}.sd-animate-grow50{animation:1s ease-out 0s 1 normal none running sd-grow50}.sd-animate-grow50-rot20{animation:1s ease-out 0s 1 normal none running sd-grow50-rot20}.sd-badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.sd-badge:empty{display:none}a.sd-badge{text-decoration:none}.sd-btn .sd-badge{position:relative;top:-1px}.sd-btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;cursor:pointer;display:inline-block;font-weight:400;font-size:1rem;line-height:1.5;padding:.375rem .75rem;text-align:center;text-decoration: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;vertical-align:middle;user-select:none;outline-offset:.25rem}.sd-btn:hover{text-decoration:none}@media (prefers-reduced-motion:reduce){.sd-btn{transition:none}}.sd-stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.sd-hide-link-text{font-size:0}.sd-btn-primary,.sd-btn-outline-primary:hover,.sd-btn-outline-primary:focus{color:var(--sd-color-primary-text)!important;background-color:var(--sd-color-primary)!important;border-color:var(--sd-color-primary)!important;border-width:1px!important;border-style:solid!important}.sd-btn-primary:hover,.sd-btn-primary:focus{color:var(--sd-color-primary-text)!important;background-color:var(--sd-color-primary-highlight)!important;border-color:var(--sd-color-primary-highlight)!important;border-width:1px!important;border-style:solid!important}.sd-btn-outline-primary{color:var(--sd-color-primary)!important;border-color:var(--sd-color-primary)!important;border-width:1px!important;border-style:solid!important}.sd-btn-primary:focus-visible{outline-color:var(--sd-color-primary)!important}.sd-btn-primary:focus-visible::after{outline-color:var(--sd-color-primary)!important}.sd-btn-secondary,.sd-btn-outline-secondary:hover,.sd-btn-outline-secondary:focus{color:var(--sd-color-secondary-text)!important;background-color:var(--sd-color-secondary)!important;border-color:var(--sd-color-secondary)!important;border-width:1px!important;border-style:solid!important}.sd-btn-secondary:hover,.sd-btn-secondary:focus{color:var(--sd-color-secondary-text)!important;background-color:var(--sd-color-secondary-highlight)!important;border-color:var(--sd-color-secondary-highlight)!important;border-width:1px!important;border-style:solid!important}.sd-btn-outline-secondary{color:var(--sd-color-secondary)!important;border-color:var(--sd-color-secondary)!important;border-width:1px!important;border-style:solid!important}.sd-btn-secondary:focus-visible{outline-color:var(--sd-color-secondary)!important}.sd-btn-secondary:focus-visible::after{outline-color:var(--sd-color-secondary)!important}.sd-btn-success,.sd-btn-outline-success:hover,.sd-btn-outline-success:focus{color:var(--sd-color-success-text)!important;background-color:var(--sd-color-success)!important;border-color:var(--sd-color-success)!important;border-width:1px!important;border-style:solid!important}.sd-btn-success:hover,.sd-btn-success:focus{color:var(--sd-color-success-text)!important;background-color:var(--sd-color-success-highlight)!important;border-color:var(--sd-color-success-highlight)!important;border-width:1px!important;border-style:solid!important}.sd-btn-outline-success{color:var(--sd-color-success)!important;border-color:var(--sd-color-success)!important;border-width:1px!important;border-style:solid!important}.sd-btn-success:focus-visible{outline-color:var(--sd-color-success)!important}.sd-btn-success:focus-visible::after{outline-color:var(--sd-color-success)!important}.sd-btn-info,.sd-btn-outline-info:hover,.sd-btn-outline-info:focus{color:var(--sd-color-info-text)!important;background-color:var(--sd-color-info)!important;border-color:var(--sd-color-info)!important;border-width:1px!important;border-style:solid!important}.sd-btn-info:hover,.sd-btn-info:focus{color:var(--sd-color-info-text)!important;background-color:var(--sd-color-info-highlight)!important;border-color:var(--sd-color-info-highlight)!important;border-width:1px!important;border-style:solid!important}.sd-btn-outline-info{color:var(--sd-color-info)!important;border-color:var(--sd-color-info)!important;border-width:1px!important;border-style:solid!important}.sd-btn-info:focus-visible{outline-color:var(--sd-color-info)!important}.sd-btn-info:focus-visible::after{outline-color:var(--sd-color-info)!important}.sd-btn-warning,.sd-btn-outline-warning:hover,.sd-btn-outline-warning:focus{color:var(--sd-color-warning-text)!important;background-color:var(--sd-color-warning)!important;border-color:var(--sd-color-warning)!important;border-width:1px!important;border-style:solid!important}.sd-btn-warning:hover,.sd-btn-warning:focus{color:var(--sd-color-warning-text)!important;background-color:var(--sd-color-warning-highlight)!important;border-color:var(--sd-color-warning-highlight)!important;border-width:1px!important;border-style:solid!important}.sd-btn-outline-warning{color:var(--sd-color-warning)!important;border-color:var(--sd-color-warning)!important;border-width:1px!important;border-style:solid!important}.sd-btn-warning:focus-visible{outline-color:var(--sd-color-warning)!important}.sd-btn-warning:focus-visible::after{outline-color:var(--sd-color-warning)!important}.sd-btn-danger,.sd-btn-outline-danger:hover,.sd-btn-outline-danger:focus{color:var(--sd-color-danger-text)!important;background-color:var(--sd-color-danger)!important;border-color:var(--sd-color-danger)!important;border-width:1px!important;border-style:solid!important}.sd-btn-danger:hover,.sd-btn-danger:focus{color:var(--sd-color-danger-text)!important;background-color:var(--sd-color-danger-highlight)!important;border-color:var(--sd-color-danger-highlight)!important;border-width:1px!important;border-style:solid!important}.sd-btn-outline-danger{color:var(--sd-color-danger)!important;border-color:var(--sd-color-danger)!important;border-width:1px!important;border-style:solid!important}.sd-btn-danger:focus-visible{outline-color:var(--sd-color-danger)!important}.sd-btn-danger:focus-visible::after{outline-color:var(--sd-color-danger)!important}.sd-btn-light,.sd-btn-outline-light:hover,.sd-btn-outline-light:focus{color:var(--sd-color-light-text)!important;background-color:var(--sd-color-light)!important;border-color:var(--sd-color-light)!important;border-width:1px!important;border-style:solid!important}.sd-btn-light:hover,.sd-btn-light:focus{color:var(--sd-color-light-text)!important;background-color:var(--sd-color-light-highlight)!important;border-color:var(--sd-color-light-highlight)!important;border-width:1px!important;border-style:solid!important}.sd-btn-outline-light{color:var(--sd-color-light)!important;border-color:var(--sd-color-light)!important;border-width:1px!important;border-style:solid!important}.sd-btn-light:focus-visible{outline-color:var(--sd-color-light)!important}.sd-btn-light:focus-visible::after{outline-color:var(--sd-color-light)!important}.sd-btn-muted,.sd-btn-outline-muted:hover,.sd-btn-outline-muted:focus{color:var(--sd-color-muted-text)!important;background-color:var(--sd-color-muted)!important;border-color:var(--sd-color-muted)!important;border-width:1px!important;border-style:solid!important}.sd-btn-muted:hover,.sd-btn-muted:focus{color:var(--sd-color-muted-text)!important;background-color:var(--sd-color-muted-highlight)!important;border-color:var(--sd-color-muted-highlight)!important;border-width:1px!important;border-style:solid!important}.sd-btn-outline-muted{color:var(--sd-color-muted)!important;border-color:var(--sd-color-muted)!important;border-width:1px!important;border-style:solid!important}.sd-btn-muted:focus-visible{outline-color:var(--sd-color-muted)!important}.sd-btn-muted:focus-visible::after{outline-color:var(--sd-color-muted)!important}.sd-btn-dark,.sd-btn-outline-dark:hover,.sd-btn-outline-dark:focus{color:var(--sd-color-dark-text)!important;background-color:var(--sd-color-dark)!important;border-color:var(--sd-color-dark)!important;border-width:1px!important;border-style:solid!important}.sd-btn-dark:hover,.sd-btn-dark:focus{color:var(--sd-color-dark-text)!important;background-color:var(--sd-color-dark-highlight)!important;border-color:var(--sd-color-dark-highlight)!important;border-width:1px!important;border-style:solid!important}.sd-btn-outline-dark{color:var(--sd-color-dark)!important;border-color:var(--sd-color-dark)!important;border-width:1px!important;border-style:solid!important}.sd-btn-dark:focus-visible{outline-color:var(--sd-color-dark)!important}.sd-btn-dark:focus-visible::after{outline-color:var(--sd-color-dark)!important}.sd-btn-black,.sd-btn-outline-black:hover,.sd-btn-outline-black:focus{color:var(--sd-color-black-text)!important;background-color:var(--sd-color-black)!important;border-color:var(--sd-color-black)!important;border-width:1px!important;border-style:solid!important}.sd-btn-black:hover,.sd-btn-black:focus{color:var(--sd-color-black-text)!important;background-color:var(--sd-color-black-highlight)!important;border-color:var(--sd-color-black-highlight)!important;border-width:1px!important;border-style:solid!important}.sd-btn-outline-black{color:var(--sd-color-black)!important;border-color:var(--sd-color-black)!important;border-width:1px!important;border-style:solid!important}.sd-btn-black:focus-visible{outline-color:var(--sd-color-black)!important}.sd-btn-black:focus-visible::after{outline-color:var(--sd-color-black)!important}.sd-btn-white,.sd-btn-outline-white:hover,.sd-btn-outline-white:focus{color:var(--sd-color-white-text)!important;background-color:var(--sd-color-white)!important;border-color:var(--sd-color-white)!important;border-width:1px!important;border-style:solid!important}.sd-btn-white:hover,.sd-btn-white:focus{color:var(--sd-color-white-text)!important;background-color:var(--sd-color-white-highlight)!important;border-color:var(--sd-color-white-highlight)!important;border-width:1px!important;border-style:solid!important}.sd-btn-outline-white{color:var(--sd-color-white)!important;border-color:var(--sd-color-white)!important;border-width:1px!important;border-style:solid!important}.sd-btn-white:focus-visible{outline-color:var(--sd-color-white)!important}.sd-btn-white:focus-visible::after{outline-color:var(--sd-color-white)!important}.sd-octicon,.sd-material-icon{display:inline-block;fill:currentColor;vertical-align:middle}.sd-avatar-xs{border-radius:50%;object-fit:cover;object-position:center;width:1rem;height:1rem}.sd-avatar-sm{border-radius:50%;object-fit:cover;object-position:center;width:3rem;height:3rem}.sd-avatar-md{border-radius:50%;object-fit:cover;object-position:center;width:5rem;height:5rem}.sd-avatar-lg{border-radius:50%;object-fit:cover;object-position:center;width:7rem;height:7rem}.sd-avatar-xl{border-radius:50%;object-fit:cover;object-position:center;width:10rem;height:10rem}.sd-avatar-inherit{border-radius:50%;object-fit:cover;object-position:center;width:inherit;height:inherit}.sd-avatar-initial{border-radius:50%;object-fit:cover;object-position:center;width:initial;height:initial}.sd-card{background-clip:border-box;background-color:var(--sd-color-card-background);border:1px solid var(--sd-color-card-border);border-radius:.25rem;color:var(--sd-color-card-text);display:flex;flex-direction:column;min-width:0;position:relative;word-wrap:break-word}.sd-card>hr{margin-left:0;margin-right:0}.sd-card .sd-stretched-link:focus-visible{outline:none}.sd-card .sd-stretched-link:focus-visible::after{outline-style:auto;outline-color:var(--sd-color-primary)}.sd-card-hover:hover{border-color:var(--sd-color-card-border-hover);transform:scale(1.01)}.sd-card-body{flex:1 1 auto;padding:1rem 1rem}.sd-card-title{margin-bottom:.5rem}.sd-card-subtitle{margin-top:-0.25rem;margin-bottom:0}.sd-card-text:last-child{margin-bottom:0}.sd-card-link:hover{text-decoration:none}.sd-card-link + .card-link{margin-left:1rem}.sd-card-header{padding:.5rem 1rem;margin-bottom:0;background-color:var(--sd-color-card-header);border-bottom:1px solid var(--sd-color-card-border)}.sd-card-header:first-child{border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.sd-card-footer{padding:.5rem 1rem;background-color:var(--sd-color-card-footer);border-top:1px solid var(--sd-color-card-border)}.sd-card-footer:last-child{border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.sd-card-header-tabs{margin-right:-0.5rem;margin-bottom:-0.5rem;margin-left:-0.5rem;border-bottom:0}.sd-card-header-pills{margin-right:-0.5rem;margin-left:-0.5rem}.sd-card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom,.sd-card-img-top{width:100%}.sd-card-img,.sd-card-img-top{border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom{border-bottom-left-radius:calc(0.25rem - 1px);border-bottom-right-radius:calc(0.25rem - 1px)}.sd-cards-carousel{width:100%;display:flex;flex-wrap:nowrap;flex-direction:row;overflow-x:hidden;scroll-snap-type:x mandatory}.sd-cards-carousel.sd-show-scrollbar{overflow-x:auto}.sd-cards-carousel:hover,.sd-cards-carousel:focus{overflow-x:auto}.sd-cards-carousel>.sd-card{flex-shrink:0;scroll-snap-align:start}.sd-cards-carousel>.sd-card:not(:last-child){margin-right:3px}.sd-card-cols-1>.sd-card{width:90%}.sd-card-cols-2>.sd-card{width:45%}.sd-card-cols-3>.sd-card{width:30%}.sd-card-cols-4>.sd-card{width:22.5%}.sd-card-cols-5>.sd-card{width:18%}.sd-card-cols-6>.sd-card{width:15%}.sd-card-cols-7>.sd-card{width:12.8571428571%}.sd-card-cols-8>.sd-card{width:11.25%}.sd-card-cols-9>.sd-card{width:10%}.sd-card-cols-10>.sd-card{width:9%}.sd-card-cols-11>.sd-card{width:8.1818181818%}.sd-card-cols-12>.sd-card{width:7.5%}.sd-container,.sd-container-fluid,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container-xl{margin-left:auto;margin-right:auto;padding-left:var(--sd-gutter-x,0.75rem);padding-right:var(--sd-gutter-x,0.75rem);width:100%}@media (min-width:576px){.sd-container-sm,.sd-container{max-width:540px}}@media (min-width:768px){.sd-container-md,.sd-container-sm,.sd-container{max-width:720px}}@media (min-width:992px){.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:960px}}@media (min-width:1200px){.sd-container-xl,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:1140px}}.sd-row{--sd-gutter-x:1.5rem;--sd-gutter-y:0;display:flex;flex-wrap:wrap;margin-top:calc(var(--sd-gutter-y) * -1);margin-right:calc(var(--sd-gutter-x) * -0.5);margin-left:calc(var(--sd-gutter-x) * -0.5)}.sd-row>*{box-sizing:border-box;flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--sd-gutter-x) * 0.5);padding-left:calc(var(--sd-gutter-x) * 0.5);margin-top:var(--sd-gutter-y)}.sd-col{flex:1 0 0%}.sd-row-cols-auto>*{flex:0 0 auto;width:auto}.sd-flex-row-reverse{flex-direction:row-reverse!important}.sd-row-cols-1>*{flex:0 0 auto;width:100%}.sd-row-cols-2>*{flex:0 0 auto;width:50%}.sd-row-cols-3>*{flex:0 0 auto;width:33.3333333333%}.sd-row-cols-4>*{flex:0 0 auto;width:25%}.sd-row-cols-5>*{flex:0 0 auto;width:20%}.sd-row-cols-6>*{flex:0 0 auto;width:16.6666666667%}.sd-row-cols-7>*{flex:0 0 auto;width:14.2857142857%}.sd-row-cols-8>*{flex:0 0 auto;width:12.5%}.sd-row-cols-9>*{flex:0 0 auto;width:11.1111111111%}.sd-row-cols-10>*{flex:0 0 auto;width:10%}.sd-row-cols-11>*{flex:0 0 auto;width:9.0909090909%}.sd-row-cols-12>*{flex:0 0 auto;width:8.3333333333%}@media (min-width:576px){.sd-col-sm{flex:1 0 0%}.sd-row-cols-sm-auto{flex:1 0 auto;width:100%}.sd-row-cols-sm-1>*{flex:0 0 auto;width:100%}.sd-row-cols-sm-2>*{flex:0 0 auto;width:50%}.sd-row-cols-sm-3>*{flex:0 0 auto;width:33.3333333333%}.sd-row-cols-sm-4>*{flex:0 0 auto;width:25%}.sd-row-cols-sm-5>*{flex:0 0 auto;width:20%}.sd-row-cols-sm-6>*{flex:0 0 auto;width:16.6666666667%}.sd-row-cols-sm-7>*{flex:0 0 auto;width:14.2857142857%}.sd-row-cols-sm-8>*{flex:0 0 auto;width:12.5%}.sd-row-cols-sm-9>*{flex:0 0 auto;width:11.1111111111%}.sd-row-cols-sm-10>*{flex:0 0 auto;width:10%}.sd-row-cols-sm-11>*{flex:0 0 auto;width:9.0909090909%}.sd-row-cols-sm-12>*{flex:0 0 auto;width:8.3333333333%}}@media (min-width:768px){.sd-col-md{flex:1 0 0%}.sd-row-cols-md-auto{flex:1 0 auto;width:100%}.sd-row-cols-md-1>*{flex:0 0 auto;width:100%}.sd-row-cols-md-2>*{flex:0 0 auto;width:50%}.sd-row-cols-md-3>*{flex:0 0 auto;width:33.3333333333%}.sd-row-cols-md-4>*{flex:0 0 auto;width:25%}.sd-row-cols-md-5>*{flex:0 0 auto;width:20%}.sd-row-cols-md-6>*{flex:0 0 auto;width:16.6666666667%}.sd-row-cols-md-7>*{flex:0 0 auto;width:14.2857142857%}.sd-row-cols-md-8>*{flex:0 0 auto;width:12.5%}.sd-row-cols-md-9>*{flex:0 0 auto;width:11.1111111111%}.sd-row-cols-md-10>*{flex:0 0 auto;width:10%}.sd-row-cols-md-11>*{flex:0 0 auto;width:9.0909090909%}.sd-row-cols-md-12>*{flex:0 0 auto;width:8.3333333333%}}@media (min-width:992px){.sd-col-lg{flex:1 0 0%}.sd-row-cols-lg-auto{flex:1 0 auto;width:100%}.sd-row-cols-lg-1>*{flex:0 0 auto;width:100%}.sd-row-cols-lg-2>*{flex:0 0 auto;width:50%}.sd-row-cols-lg-3>*{flex:0 0 auto;width:33.3333333333%}.sd-row-cols-lg-4>*{flex:0 0 auto;width:25%}.sd-row-cols-lg-5>*{flex:0 0 auto;width:20%}.sd-row-cols-lg-6>*{flex:0 0 auto;width:16.6666666667%}.sd-row-cols-lg-7>*{flex:0 0 auto;width:14.2857142857%}.sd-row-cols-lg-8>*{flex:0 0 auto;width:12.5%}.sd-row-cols-lg-9>*{flex:0 0 auto;width:11.1111111111%}.sd-row-cols-lg-10>*{flex:0 0 auto;width:10%}.sd-row-cols-lg-11>*{flex:0 0 auto;width:9.0909090909%}.sd-row-cols-lg-12>*{flex:0 0 auto;width:8.3333333333%}}@media (min-width:1200px){.sd-col-xl{flex:1 0 0%}.sd-row-cols-xl-auto{flex:1 0 auto;width:100%}.sd-row-cols-xl-1>*{flex:0 0 auto;width:100%}.sd-row-cols-xl-2>*{flex:0 0 auto;width:50%}.sd-row-cols-xl-3>*{flex:0 0 auto;width:33.3333333333%}.sd-row-cols-xl-4>*{flex:0 0 auto;width:25%}.sd-row-cols-xl-5>*{flex:0 0 auto;width:20%}.sd-row-cols-xl-6>*{flex:0 0 auto;width:16.6666666667%}.sd-row-cols-xl-7>*{flex:0 0 auto;width:14.2857142857%}.sd-row-cols-xl-8>*{flex:0 0 auto;width:12.5%}.sd-row-cols-xl-9>*{flex:0 0 auto;width:11.1111111111%}.sd-row-cols-xl-10>*{flex:0 0 auto;width:10%}.sd-row-cols-xl-11>*{flex:0 0 auto;width:9.0909090909%}.sd-row-cols-xl-12>*{flex:0 0 auto;width:8.3333333333%}}.sd-col-auto{flex:0 0 auto;width:auto}.sd-col-1{flex:0 0 auto;width:8.3333333333%}.sd-col-2{flex:0 0 auto;width:16.6666666667%}.sd-col-3{flex:0 0 auto;width:25%}.sd-col-4{flex:0 0 auto;width:33.3333333333%}.sd-col-5{flex:0 0 auto;width:41.6666666667%}.sd-col-6{flex:0 0 auto;width:50%}.sd-col-7{flex:0 0 auto;width:58.3333333333%}.sd-col-8{flex:0 0 auto;width:66.6666666667%}.sd-col-9{flex:0 0 auto;width:75%}.sd-col-10{flex:0 0 auto;width:83.3333333333%}.sd-col-11{flex:0 0 auto;width:91.6666666667%}.sd-col-12{flex:0 0 auto;width:100%}.sd-g-0,.sd-gy-0{--sd-gutter-y:0}.sd-g-0,.sd-gx-0{--sd-gutter-x:0}.sd-g-1,.sd-gy-1{--sd-gutter-y:0.25rem}.sd-g-1,.sd-gx-1{--sd-gutter-x:0.25rem}.sd-g-2,.sd-gy-2{--sd-gutter-y:0.5rem}.sd-g-2,.sd-gx-2{--sd-gutter-x:0.5rem}.sd-g-3,.sd-gy-3{--sd-gutter-y:1rem}.sd-g-3,.sd-gx-3{--sd-gutter-x:1rem}.sd-g-4,.sd-gy-4{--sd-gutter-y:1.5rem}.sd-g-4,.sd-gx-4{--sd-gutter-x:1.5rem}.sd-g-5,.sd-gy-5{--sd-gutter-y:3rem}.sd-g-5,.sd-gx-5{--sd-gutter-x:3rem}@media (min-width:576px){.sd-col-sm-auto{flex:0 0 auto;width:auto}.sd-col-sm-1{flex:0 0 auto;width:8.3333333333%}.sd-col-sm-2{flex:0 0 auto;width:16.6666666667%}.sd-col-sm-3{flex:0 0 auto;width:25%}.sd-col-sm-4{flex:0 0 auto;width:33.3333333333%}.sd-col-sm-5{flex:0 0 auto;width:41.6666666667%}.sd-col-sm-6{flex:0 0 auto;width:50%}.sd-col-sm-7{flex:0 0 auto;width:58.3333333333%}.sd-col-sm-8{flex:0 0 auto;width:66.6666666667%}.sd-col-sm-9{flex:0 0 auto;width:75%}.sd-col-sm-10{flex:0 0 auto;width:83.3333333333%}.sd-col-sm-11{flex:0 0 auto;width:91.6666666667%}.sd-col-sm-12{flex:0 0 auto;width:100%}.sd-g-sm-0,.sd-gy-sm-0{--sd-gutter-y:0}.sd-g-sm-0,.sd-gx-sm-0{--sd-gutter-x:0}.sd-g-sm-1,.sd-gy-sm-1{--sd-gutter-y:0.25rem}.sd-g-sm-1,.sd-gx-sm-1{--sd-gutter-x:0.25rem}.sd-g-sm-2,.sd-gy-sm-2{--sd-gutter-y:0.5rem}.sd-g-sm-2,.sd-gx-sm-2{--sd-gutter-x:0.5rem}.sd-g-sm-3,.sd-gy-sm-3{--sd-gutter-y:1rem}.sd-g-sm-3,.sd-gx-sm-3{--sd-gutter-x:1rem}.sd-g-sm-4,.sd-gy-sm-4{--sd-gutter-y:1.5rem}.sd-g-sm-4,.sd-gx-sm-4{--sd-gutter-x:1.5rem}.sd-g-sm-5,.sd-gy-sm-5{--sd-gutter-y:3rem}.sd-g-sm-5,.sd-gx-sm-5{--sd-gutter-x:3rem}}@media (min-width:768px){.sd-col-md-auto{flex:0 0 auto;width:auto}.sd-col-md-1{flex:0 0 auto;width:8.3333333333%}.sd-col-md-2{flex:0 0 auto;width:16.6666666667%}.sd-col-md-3{flex:0 0 auto;width:25%}.sd-col-md-4{flex:0 0 auto;width:33.3333333333%}.sd-col-md-5{flex:0 0 auto;width:41.6666666667%}.sd-col-md-6{flex:0 0 auto;width:50%}.sd-col-md-7{flex:0 0 auto;width:58.3333333333%}.sd-col-md-8{flex:0 0 auto;width:66.6666666667%}.sd-col-md-9{flex:0 0 auto;width:75%}.sd-col-md-10{flex:0 0 auto;width:83.3333333333%}.sd-col-md-11{flex:0 0 auto;width:91.6666666667%}.sd-col-md-12{flex:0 0 auto;width:100%}.sd-g-md-0,.sd-gy-md-0{--sd-gutter-y:0}.sd-g-md-0,.sd-gx-md-0{--sd-gutter-x:0}.sd-g-md-1,.sd-gy-md-1{--sd-gutter-y:0.25rem}.sd-g-md-1,.sd-gx-md-1{--sd-gutter-x:0.25rem}.sd-g-md-2,.sd-gy-md-2{--sd-gutter-y:0.5rem}.sd-g-md-2,.sd-gx-md-2{--sd-gutter-x:0.5rem}.sd-g-md-3,.sd-gy-md-3{--sd-gutter-y:1rem}.sd-g-md-3,.sd-gx-md-3{--sd-gutter-x:1rem}.sd-g-md-4,.sd-gy-md-4{--sd-gutter-y:1.5rem}.sd-g-md-4,.sd-gx-md-4{--sd-gutter-x:1.5rem}.sd-g-md-5,.sd-gy-md-5{--sd-gutter-y:3rem}.sd-g-md-5,.sd-gx-md-5{--sd-gutter-x:3rem}}@media (min-width:992px){.sd-col-lg-auto{flex:0 0 auto;width:auto}.sd-col-lg-1{flex:0 0 auto;width:8.3333333333%}.sd-col-lg-2{flex:0 0 auto;width:16.6666666667%}.sd-col-lg-3{flex:0 0 auto;width:25%}.sd-col-lg-4{flex:0 0 auto;width:33.3333333333%}.sd-col-lg-5{flex:0 0 auto;width:41.6666666667%}.sd-col-lg-6{flex:0 0 auto;width:50%}.sd-col-lg-7{flex:0 0 auto;width:58.3333333333%}.sd-col-lg-8{flex:0 0 auto;width:66.6666666667%}.sd-col-lg-9{flex:0 0 auto;width:75%}.sd-col-lg-10{flex:0 0 auto;width:83.3333333333%}.sd-col-lg-11{flex:0 0 auto;width:91.6666666667%}.sd-col-lg-12{flex:0 0 auto;width:100%}.sd-g-lg-0,.sd-gy-lg-0{--sd-gutter-y:0}.sd-g-lg-0,.sd-gx-lg-0{--sd-gutter-x:0}.sd-g-lg-1,.sd-gy-lg-1{--sd-gutter-y:0.25rem}.sd-g-lg-1,.sd-gx-lg-1{--sd-gutter-x:0.25rem}.sd-g-lg-2,.sd-gy-lg-2{--sd-gutter-y:0.5rem}.sd-g-lg-2,.sd-gx-lg-2{--sd-gutter-x:0.5rem}.sd-g-lg-3,.sd-gy-lg-3{--sd-gutter-y:1rem}.sd-g-lg-3,.sd-gx-lg-3{--sd-gutter-x:1rem}.sd-g-lg-4,.sd-gy-lg-4{--sd-gutter-y:1.5rem}.sd-g-lg-4,.sd-gx-lg-4{--sd-gutter-x:1.5rem}.sd-g-lg-5,.sd-gy-lg-5{--sd-gutter-y:3rem}.sd-g-lg-5,.sd-gx-lg-5{--sd-gutter-x:3rem}}@media (min-width:1200px){.sd-col-xl-auto{flex:0 0 auto;width:auto}.sd-col-xl-1{flex:0 0 auto;width:8.3333333333%}.sd-col-xl-2{flex:0 0 auto;width:16.6666666667%}.sd-col-xl-3{flex:0 0 auto;width:25%}.sd-col-xl-4{flex:0 0 auto;width:33.3333333333%}.sd-col-xl-5{flex:0 0 auto;width:41.6666666667%}.sd-col-xl-6{flex:0 0 auto;width:50%}.sd-col-xl-7{flex:0 0 auto;width:58.3333333333%}.sd-col-xl-8{flex:0 0 auto;width:66.6666666667%}.sd-col-xl-9{flex:0 0 auto;width:75%}.sd-col-xl-10{flex:0 0 auto;width:83.3333333333%}.sd-col-xl-11{flex:0 0 auto;width:91.6666666667%}.sd-col-xl-12{flex:0 0 auto;width:100%}.sd-g-xl-0,.sd-gy-xl-0{--sd-gutter-y:0}.sd-g-xl-0,.sd-gx-xl-0{--sd-gutter-x:0}.sd-g-xl-1,.sd-gy-xl-1{--sd-gutter-y:0.25rem}.sd-g-xl-1,.sd-gx-xl-1{--sd-gutter-x:0.25rem}.sd-g-xl-2,.sd-gy-xl-2{--sd-gutter-y:0.5rem}.sd-g-xl-2,.sd-gx-xl-2{--sd-gutter-x:0.5rem}.sd-g-xl-3,.sd-gy-xl-3{--sd-gutter-y:1rem}.sd-g-xl-3,.sd-gx-xl-3{--sd-gutter-x:1rem}.sd-g-xl-4,.sd-gy-xl-4{--sd-gutter-y:1.5rem}.sd-g-xl-4,.sd-gx-xl-4{--sd-gutter-x:1.5rem}.sd-g-xl-5,.sd-gy-xl-5{--sd-gutter-y:3rem}.sd-g-xl-5,.sd-gx-xl-5{--sd-gutter-x:3rem}}details.sd-dropdown{position:relative;font-size:var(--sd-fontsize-dropdown)}details.sd-dropdown:hover{cursor:pointer}details.sd-dropdown .sd-summary-content{cursor:default}details.sd-dropdown summary.sd-summary-title{padding:.5em .6em .5em 1em;font-size:var(--sd-fontsize-dropdown-title);font-weight:var(--sd-fontweight-dropdown-title);user-select:none;list-style:none;display:inline-flex;justify-content:space-between;outline-offset:.25rem}details.sd-dropdown summary.sd-summary-title::-webkit-details-marker{display:none}details.sd-dropdown summary.sd-summary-title .sd-summary-icon{margin-right:.6em;display:inline-flex;align-items:center}details.sd-dropdown summary.sd-summary-title .sd-summary-icon svg{opacity:.8}details.sd-dropdown summary.sd-summary-title .sd-summary-text{flex-grow:1;line-height:1.5;padding-right:.5rem}details.sd-dropdown summary.sd-summary-title .sd-summary-state-marker{pointer-events:none;display:inline-flex;align-self:center}details.sd-dropdown summary.sd-summary-title .sd-summary-state-marker svg{opacity:.6}details.sd-dropdown summary.sd-summary-title:hover .sd-summary-state-marker svg{opacity:1;transform:scale(1.1)}details.sd-dropdown[open] summary .sd-octicon.no-title{visibility:hidden}details.sd-dropdown .sd-summary-chevron-right{transition:.25s}details.sd-dropdown[open]>.sd-summary-title .sd-summary-chevron-right{transform:rotate(90deg)}details.sd-dropdown[open]>.sd-summary-title .sd-summary-chevron-down{transform:rotate(180deg)}details.sd-dropdown:not([open]).sd-card{border:none}details.sd-dropdown:not([open])>.sd-card-header{border:1px solid var(--sd-color-card-border);border-radius:.25rem}details.sd-dropdown.sd-fade-in[open] summary ~ *{animation:sd-fade-in .5s ease-in-out}details.sd-dropdown.sd-fade-in-slide-down[open] summary ~ *{animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out}.sd-col>.sd-dropdown{width:100%}.sd-summary-content>.sd-tab-set:first-child{margin-top:0}@keyframes sd-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes sd-slide-down{0%{transform:translate(0,-10px)}100%{transform:translate(0,0)}}.sd-accordion>.sd-dropdown:not(:last-child){margin-bottom:0!important}.sd-accordion-flush>.sd-dropdown,.sd-accordion-flush>.sd-dropdown>.sd-card-header{border-left:none!important;border-right:none!important;border-radius:0!important}.sd-tab-set{border-radius:.125rem;display:flex;flex-wrap:wrap;margin:1em 0;position:relative}.sd-tab-set>input{opacity:0;position:absolute}.sd-tab-set>input:checked + label{border-color:var(--sd-color-tabs-underline-active);color:var(--sd-color-tabs-label-active)}.sd-tab-set>input:checked + label + .sd-tab-content{display:block}.sd-tab-set>input:not(:checked) + label:hover{color:var(--sd-color-tabs-label-hover);border-color:var(--sd-color-tabs-underline-hover)}.sd-tab-set>input:focus + label{outline-style:auto}.sd-tab-set>input:not(:focus-visible) + label{outline:none;-webkit-tap-highlight-color:transparent}.sd-tab-set>label{border-bottom:.125rem solid transparent;margin-bottom:0;color:var(--sd-color-tabs-label-inactive);border-color:var(--sd-color-tabs-underline-inactive);cursor:pointer;font-size:var(--sd-fontsize-tabs-label);font-weight:700;padding:.5em 1.25em;transition:color 250ms;width:auto;z-index:1}html .sd-tab-set>label:hover{color:var(--sd-color-tabs-label-active)}.sd-col>.sd-tab-set{width:100%}.sd-tab-content{box-shadow:0 -0.0625rem var(--sd-color-tabs-overline),0 .0625rem var(--sd-color-tabs-underline);display:none;order:99;padding-bottom:.75rem;padding-top:.75rem;width:100%}.sd-tab-content>:first-child{margin-top:0!important}.sd-tab-content>:last-child{margin-bottom:0!important}.sd-tab-content>.sd-tab-set{margin:0}.sd-sphinx-override,.sd-sphinx-override *{box-sizing:border-box}.sd-sphinx-override p{margin-top:0}.sd-sphinx-override:focus-visible{outline-offset:.25rem}:root{--sd-color-primary:#0071bc;--sd-color-secondary:#6c757d;--sd-color-success:#28a745;--sd-color-info:#17a2b8;--sd-color-warning:#f0b37e;--sd-color-danger:#dc3545;--sd-color-light:#f8f9fa;--sd-color-muted:#6c757d;--sd-color-dark:#212529;--sd-color-black:black;--sd-color-white:white;--sd-color-primary-highlight:#0060a0;--sd-color-primary-highlight:color-mix(in srgb,black 15%,var(--sd-color-primary));--sd-color-secondary-highlight:#5c636a;--sd-color-secondary-highlight:color-mix(in srgb,black 15%,var(--sd-color-secondary));--sd-color-success-highlight:#228e3b;--sd-color-success-highlight:color-mix(in srgb,black 15%,var(--sd-color-success));--sd-color-info-highlight:#148a9c;--sd-color-info-highlight:color-mix(in srgb,black 15%,var(--sd-color-info));--sd-color-warning-highlight:#cc986b;--sd-color-warning-highlight:color-mix(in srgb,black 15%,var(--sd-color-warning));--sd-color-danger-highlight:#bb2d3b;--sd-color-danger-highlight:color-mix(in srgb,black 15%,var(--sd-color-danger));--sd-color-light-highlight:#d3d4d5;--sd-color-light-highlight:color-mix(in srgb,black 15%,var(--sd-color-light));--sd-color-muted-highlight:#5c636a;--sd-color-muted-highlight:color-mix(in srgb,black 15%,var(--sd-color-muted));--sd-color-dark-highlight:#1c1f23;--sd-color-dark-highlight:color-mix(in srgb,black 15%,var(--sd-color-dark));--sd-color-black-highlight:black;--sd-color-black-highlight:color-mix(in srgb,black 15%,var(--sd-color-black));--sd-color-white-highlight:#d9d9d9;--sd-color-white-highlight:color-mix(in srgb,black 15%,var(--sd-color-white));--sd-color-primary-bg:rgba(0,113,188,0.2);--sd-color-secondary-bg:rgba(108,117,125,0.2);--sd-color-success-bg:rgba(40,167,69,0.2);--sd-color-info-bg:rgba(23,162,184,0.2);--sd-color-warning-bg:rgba(240,179,126,0.2);--sd-color-danger-bg:rgba(220,53,69,0.2);--sd-color-light-bg:rgba(248,249,250,0.2);--sd-color-muted-bg:rgba(108,117,125,0.2);--sd-color-dark-bg:rgba(33,37,41,0.2);--sd-color-black-bg:rgba(0,0,0,0.2);--sd-color-white-bg:rgba(255,255,255,0.2);--sd-color-primary-text:#fff;--sd-color-secondary-text:#fff;--sd-color-success-text:#fff;--sd-color-info-text:#fff;--sd-color-warning-text:#212529;--sd-color-danger-text:#fff;--sd-color-light-text:#212529;--sd-color-muted-text:#fff;--sd-color-dark-text:#fff;--sd-color-black-text:#fff;--sd-color-white-text:#212529;--sd-color-shadow:rgba(0,0,0,0.15);--sd-color-card-border:rgba(0,0,0,0.125);--sd-color-card-border-hover:hsla(231,99%,66%,1);--sd-color-card-background:transparent;--sd-color-card-text:inherit;--sd-color-card-header:transparent;--sd-color-card-footer:transparent;--sd-color-tabs-label-active:hsla(231,99%,66%,1);--sd-color-tabs-label-hover:hsla(231,99%,66%,1);--sd-color-tabs-label-inactive:hsl(0,0%,66%);--sd-color-tabs-underline-active:hsla(231,99%,66%,1);--sd-color-tabs-underline-hover:rgba(178,206,245,0.62);--sd-color-tabs-underline-inactive:transparent;--sd-color-tabs-overline:rgb(222,222,222);--sd-color-tabs-underline:rgb(222,222,222);--sd-fontsize-tabs-label:1rem;--sd-fontsize-dropdown:inherit;--sd-fontsize-dropdown-title:1rem;--sd-fontweight-dropdown-title:700} diff --git a/style/accordion.css b/style/accordion.css new file mode 100644 index 0000000..3b610f7 --- /dev/null +++ b/style/accordion.css @@ -0,0 +1,24 @@ +/* Accordion: a group of dropdowns behaving as one exclusive set -- opening an + item collapses its siblings, via a shared native `
` attribute + and no JavaScript. Assembled directly after dropdown.css so these rules win + over the dropdown/card defaults at equal specificity. Browsers that ignore + `
` keep each item independently collapsible; see + docs/accordions.md for the graceful-degradation note. */ + +/* Collapse the margin *between* grouped items so they read as a single + connected stack. Each child dropdown carries a default sd-mb-3; the last + item keeps it, preserving the gap below the accordion as a whole. The + !important is required to override the sd-mb-3 utility (itself !important). */ +.sd-accordion > .sd-dropdown:not(:last-child) { + margin-bottom: 0 !important; +} + +/* Flush variant (cf. Bootstrap's accordion-flush): drop the outer side borders + and corner rounding so the accordion sits edge-to-edge within its container. + !important beats the higher-specificity closed-state dropdown header rule. */ +.sd-accordion-flush > .sd-dropdown, +.sd-accordion-flush > .sd-dropdown > .sd-card-header { + border-left: none !important; + border-right: none !important; + border-radius: 0 !important; +} diff --git a/tests/test_misc.py b/tests/test_misc.py index dc651e5..4922f17 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -648,3 +648,162 @@ def test_config_toml_round_trip(): "options": {"color": "primary", "icon": "code"}, } } + + +ACCORDION_NESTED = { + "rst": """ +Test +==== + +.. accordion:: + + .. dropdown:: A + + A content + + .. dropdown:: B + + .. dropdown:: Nested + + nested content + +.. accordion:: + + .. dropdown:: C + + C content +""", + "myst": """ +# Test + +:::::{accordion} + +:::{dropdown} A +A content +::: + +::::{dropdown} B +:::{dropdown} Nested +nested content +::: +:::: + +::::: + +:::::{accordion} + +:::{dropdown} C +C content +::: +::::: +""", +} + + +@pytest.mark.parametrize("fmt", ["rst", MYST_PARAM]) +def test_accordion_group_names(fmt, sphinx_builder): + """Direct child dropdowns of an accordion share a group name; nested + dropdowns do not join the group, and separate accordions get distinct + names -- so opening an item only ever closes its own group's siblings. + """ + if fmt == "rst": + builder = sphinx_builder(conf_kwargs={"extensions": ["sphinx_design"]}) + builder.src_path.joinpath("index.rst").write_text( + ACCORDION_NESTED["rst"], encoding="utf8" + ) + else: + builder = sphinx_builder() + builder.src_path.joinpath("index.md").write_text( + ACCORDION_NESTED["myst"], encoding="utf8" + ) + builder.build() # asserts no warnings + + doctree = builder.get_doctree("index") + dropdowns = list(doctree.findall(lambda node: is_component(node, "dropdown"))) + # A, B, Nested (inside B), C -- in document order + assert len(dropdowns) == 4 + name_a, name_b, name_nested, name_c = (d.get("details_name") for d in dropdowns) + # the two direct children of the first accordion share one group name + assert name_a is not None + assert name_a == name_b + # the dropdown nested inside an item's body must NOT inherit the group name + assert name_nested is None + # a second accordion on the same page gets a distinct group name + assert name_c is not None + assert name_c != name_a + # names are the deterministic, document-derived scheme + assert name_a == "sd-accordion-index-0" + assert name_c == "sd-accordion-index-1" + + # and the grouping reaches the rendered HTML
+ html = (builder.out_path / "index.html").read_text(encoding="utf8") + # three grouped
(A, B, C); the nested one carries no name + assert html.count('name="sd-accordion-index-0"') == 2 + assert html.count('name="sd-accordion-index-1"') == 1 + assert html.count('name="sd-accordion') == 3 + + +def test_accordion_invalid_child_warns(sphinx_builder): + """A non-dropdown child of an accordion warns (design.accordion) and is + skipped, while valid dropdown siblings are still grouped. + """ + builder = sphinx_builder(conf_kwargs={"extensions": ["sphinx_design"]}) + builder.src_path.joinpath("index.rst").write_text( + """ +Test +==== + +.. accordion:: + + .. dropdown:: A + + A content + + not a dropdown + + .. dropdown:: B + + B content +""", + encoding="utf8", + ) + builder.build(assert_pass=False) + assert "All children of an 'accordion' should be 'dropdown'" in builder.warnings + assert "[design.accordion]" in builder.warnings + # the two valid dropdowns are still grouped + doctree = builder.get_doctree("index") + dropdowns = list(doctree.findall(lambda node: is_component(node, "dropdown"))) + assert len(dropdowns) == 2 + assert dropdowns[0]["details_name"] == dropdowns[1]["details_name"] + + +def test_accordion_multiple_open_warns(sphinx_builder): + """More than one ``:open:`` item is invalid for an exclusive group: warn + and keep only the first open. + """ + builder = sphinx_builder(conf_kwargs={"extensions": ["sphinx_design"]}) + builder.src_path.joinpath("index.rst").write_text( + """ +Test +==== + +.. accordion:: + + .. dropdown:: A + :open: + + A content + + .. dropdown:: B + :open: + + B content +""", + encoding="utf8", + ) + builder.build(assert_pass=False) + assert "Multiple open 'dropdown' items in an 'accordion'" in builder.warnings + assert "[design.accordion]" in builder.warnings + doctree = builder.get_doctree("index") + dropdowns = list(doctree.findall(lambda node: is_component(node, "dropdown"))) + assert [d["opened"] for d in dropdowns] == [True, False] diff --git a/tests/test_snippets/snippet_post_accordion-basic.xml b/tests/test_snippets/snippet_post_accordion-basic.xml new file mode 100644 index 0000000..7726bf5 --- /dev/null +++ b/tests/test_snippets/snippet_post_accordion-basic.xml @@ -0,0 +1,35 @@ + +
+ + Heading + <container classes="sd-accordion" design_component="accordion" is_div="True"> + <dropdown_main classes="sd-sphinx-override sd-dropdown sd-card sd-mb-3" details_name="sd-accordion-index-0" opened="False"> + <dropdown_title classes="sd-summary-title sd-card-header"> + <inline classes="sd-summary-text"> + First item + <inline classes="sd-summary-state-marker sd-summary-chevron-right"> + <raw format="html" xml:space="preserve"> + <svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewBox="0 0 24 24" aria-hidden="true"><path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z"></path></svg> + <container classes="sd-summary-content sd-card-body" design_component="dropdown-body" is_div="True"> + <paragraph classes="sd-card-text"> + Opening another item closes this one. + <dropdown_main classes="sd-sphinx-override sd-dropdown sd-card sd-mb-3" details_name="sd-accordion-index-0" opened="True"> + <dropdown_title classes="sd-summary-title sd-card-header"> + <inline classes="sd-summary-text"> + Second item + <inline classes="sd-summary-state-marker sd-summary-chevron-right"> + <raw format="html" xml:space="preserve"> + <svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewBox="0 0 24 24" aria-hidden="true"><path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z"></path></svg> + <container classes="sd-summary-content sd-card-body" design_component="dropdown-body" is_div="True"> + <paragraph classes="sd-card-text"> + Content of the second item. + <dropdown_main classes="sd-sphinx-override sd-dropdown sd-card sd-mb-3" details_name="sd-accordion-index-0" opened="False"> + <dropdown_title classes="sd-summary-title sd-card-header"> + <inline classes="sd-summary-text"> + Third item + <inline classes="sd-summary-state-marker sd-summary-chevron-right"> + <raw format="html" xml:space="preserve"> + <svg version="1.1" width="1.5em" height="1.5em" class="sd-octicon sd-octicon-chevron-right" viewBox="0 0 24 24" aria-hidden="true"><path d="M8.72 18.78a.75.75 0 0 1 0-1.06L14.44 12 8.72 6.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018l6.25 6.25a.75.75 0 0 1 0 1.06l-6.25 6.25a.75.75 0 0 1-1.06 0Z"></path></svg> + <container classes="sd-summary-content sd-card-body" design_component="dropdown-body" is_div="True"> + <paragraph classes="sd-card-text"> + Content of the third item. diff --git a/tests/test_snippets/snippet_pre_accordion-basic.xml b/tests/test_snippets/snippet_pre_accordion-basic.xml new file mode 100644 index 0000000..0b6c793 --- /dev/null +++ b/tests/test_snippets/snippet_pre_accordion-basic.xml @@ -0,0 +1,20 @@ +<document source="index"> + <section ids="heading" names="heading"> + <title> + Heading + <container classes="sd-accordion" design_component="accordion" is_div="True"> + <container body_classes="" chevron="True" container_classes="sd-mb-3" design_component="dropdown" details_name="sd-accordion-index-0" has_title="True" icon="True" is_div="True" opened="False" title_classes="" type="dropdown"> + <rubric> + First item + <paragraph> + Opening another item closes this one. + <container body_classes="" chevron="True" container_classes="sd-mb-3" design_component="dropdown" details_name="sd-accordion-index-0" has_title="True" icon="True" is_div="True" opened="True" title_classes="" type="dropdown"> + <rubric> + Second item + <paragraph> + Content of the second item. + <container body_classes="" chevron="True" container_classes="sd-mb-3" design_component="dropdown" details_name="sd-accordion-index-0" has_title="True" icon="True" is_div="True" opened="False" title_classes="" type="dropdown"> + <rubric> + Third item + <paragraph> + Content of the third item. diff --git a/tools/generate_css.py b/tools/generate_css.py index c275fbd..0648417 100644 --- a/tools/generate_css.py +++ b/tools/generate_css.py @@ -82,6 +82,7 @@ "grids.css", ("gen", "grids"), "dropdown.css", + "accordion.css", "tabs.css", "overrides.css", ("gen", "root_variables"), From c86d260da9a138820c9457bda87596396ec99e66 Mon Sep 17 00:00:00 2001 From: Chris Sewell <chrisj_sewell@hotmail.com> Date: Thu, 16 Jul 2026 14:55:53 +0000 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=90=9B=20FIX:=20Prevent=20accordion?= =?UTF-8?q?=20group-name=20collisions=20across=20documents?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `nodes.make_id` is lossy (`a/b`, `a-b`, `a.b` all fold to `a-b`) and the serial counter is per-document, so accordions in docnames sharing a slug produced identical `<details name>` values. In a `singlehtml` build these land on one page and their exclusive-open groups coupled together. Append a short SHA-1 digest of the raw docname to the group name so colliding slugs stay distinct; add a singlehtml regression test and make the existing assertions structural rather than digest-hardcoded. --- sphinx_design/accordion.py | 38 ++++++++--- tests/test_misc.py | 66 +++++++++++++++++-- .../snippet_post_accordion-basic.xml | 6 +- .../snippet_pre_accordion-basic.xml | 6 +- 4 files changed, 95 insertions(+), 21 deletions(-) diff --git a/sphinx_design/accordion.py b/sphinx_design/accordion.py index b38e1d0..c41b5ca 100644 --- a/sphinx_design/accordion.py +++ b/sphinx_design/accordion.py @@ -1,7 +1,7 @@ """The ``accordion`` directive: a group of mutually-exclusive dropdowns. An accordion is a thin wrapper around a set of :mod:`~sphinx_design.dropdown` -directives. It assigns every *direct* child dropdown a shared, document-unique +directives. It assigns every *direct* child dropdown a shared, project-unique ``name``, which the HTML writer stamps onto the underlying ``<details>`` elements. Browsers that support the native ``name`` attribute on ``<details>`` then make the group mutually exclusive: opening one item automatically closes @@ -12,6 +12,8 @@ dropdown (see ``docs/accordions.md`` for the browser-support note). """ +import hashlib + from docutils import nodes from docutils.parsers.rst import directives from sphinx.application import Sphinx @@ -57,17 +59,33 @@ class AccordionDirective(SdDirective): } def _group_name(self) -> str: - """Build a document-unique, build-stable group name. - - The name is derived from the current docname (kept unique even in - single-page/concatenated builds, where accordions from different - source documents share one HTML page) plus a per-document serial - counter. It is fully deterministic -- no randomness -- so rebuilds of - unchanged content produce byte-identical output. + """Build a build-stable group name, unique across the whole project. + + The name combines three parts: + + - a readable slug of the docname (``nodes.make_id``), for legibility; + - a short digest of the *raw* docname. ``make_id`` is lossy (``a/b``, + ``a-b`` and ``a.b`` all fold to ``a-b``), so the slug alone is not + collision-free; the digest disambiguates docnames that share a slug. + This matters for single-page/concatenated builds (``singlehtml``), + where accordions from *different* source documents land on one HTML + page and must not accidentally share a ``<details name>`` group; and + - a per-document serial counter, distinguishing multiple accordions + within the same document. + + SHA-1 is used purely as a stable, deterministic fingerprint (not for + security), so rebuilds of unchanged content produce byte-identical + output -- there is no randomness anywhere in the name. """ - slug = nodes.make_id(self.env.docname) or "doc" + docname = self.env.docname + slug = nodes.make_id(docname) or "doc" + # SHA-1 here is only a stable, deterministic fingerprint of the raw + # docname (usedforsecurity=False), never a security primitive. + digest = hashlib.sha1( + docname.encode("utf-8"), usedforsecurity=False + ).hexdigest()[:8] serial = self.env.new_serialno("sd-accordion") - return f"sd-accordion-{slug}-{serial}" + return f"sd-accordion-{slug}-{digest}-{serial}" def run_with_defaults(self) -> list[nodes.Node]: self.assert_has_content() diff --git a/tests/test_misc.py b/tests/test_misc.py index 4922f17..1e0004b 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -731,18 +731,74 @@ def test_accordion_group_names(fmt, sphinx_builder): # a second accordion on the same page gets a distinct group name assert name_c is not None assert name_c != name_a - # names are the deterministic, document-derived scheme - assert name_a == "sd-accordion-index-0" - assert name_c == "sd-accordion-index-1" + # names follow the deterministic docname-derived scheme (readable slug + + # raw-docname digest + per-document serial); assert the structure rather + # than the exact digest, so the fixtures stay robust + assert name_a.startswith("sd-accordion-index-") + assert name_a.endswith("-0") + assert name_c.endswith("-1") # and the grouping reaches the rendered HTML <details name="..."> html = (builder.out_path / "index.html").read_text(encoding="utf8") # three grouped <details> (A, B, C); the nested one carries no name - assert html.count('name="sd-accordion-index-0"') == 2 - assert html.count('name="sd-accordion-index-1"') == 1 + assert html.count(f'name="{name_a}"') == 2 + assert html.count(f'name="{name_c}"') == 1 assert html.count('name="sd-accordion') == 3 +def test_accordion_group_names_singlehtml_no_collision(sphinx_builder): + """Docnames that fold to the same ``make_id`` slug must still get distinct + group names, so a ``singlehtml`` build -- which places every document on a + single page -- does not accidentally couple their exclusive groups. + + Regression test for the ``make_id`` lossiness collision: ``a/b`` and + ``a-b`` both slugify to ``a-b``, and the per-document serial counter + restarts at 0 for each, so without the raw-docname digest both accordions + would emit an identical ``<details name>``. + """ + # sanity: the two docnames really do collide under make_id + assert nodes.make_id("a/b") == nodes.make_id("a-b") + + accordion_rst = ( + ".. accordion::\n\n" + " .. dropdown:: one\n\n content\n\n" + " .. dropdown:: two\n\n content\n" + ) + builder = sphinx_builder( + "singlehtml", conf_kwargs={"extensions": ["sphinx_design"]} + ) + src = builder.src_path + (src / "a").mkdir() + (src / "a" / "b.rst").write_text( + f"Doc A slash B\n=============\n\n{accordion_rst}", encoding="utf8" + ) + (src / "a-b.rst").write_text( + f"Doc A dash B\n============\n\n{accordion_rst}", encoding="utf8" + ) + (src / "index.rst").write_text( + "Root\n====\n\n.. toctree::\n\n a/b\n a-b\n", encoding="utf8" + ) + builder.build() # asserts no warnings + + def group_name(docname: str) -> str: + doctree = builder.get_doctree(docname) + dropdowns = list(doctree.findall(lambda n: is_component(n, "dropdown"))) + names = {d["details_name"] for d in dropdowns} + assert len(names) == 1, names + return names.pop() + + name_slash = group_name("a/b") + name_dash = group_name("a-b") + # both share the same lossy slug, but the raw-docname digest keeps them apart + assert name_slash != name_dash, (name_slash, name_dash) + + # the assembled single page therefore carries two distinct <details name> + # groups (not one coupled group of four items) + html = (builder.out_path / "index.html").read_text(encoding="utf8") + assert html.count(f'name="{name_slash}"') == 2 + assert html.count(f'name="{name_dash}"') == 2 + + def test_accordion_invalid_child_warns(sphinx_builder): """A non-dropdown child of an accordion warns (design.accordion) and is skipped, while valid dropdown siblings are still grouped. diff --git a/tests/test_snippets/snippet_post_accordion-basic.xml b/tests/test_snippets/snippet_post_accordion-basic.xml index 7726bf5..e5abc57 100644 --- a/tests/test_snippets/snippet_post_accordion-basic.xml +++ b/tests/test_snippets/snippet_post_accordion-basic.xml @@ -3,7 +3,7 @@ <title> Heading <container classes="sd-accordion" design_component="accordion" is_div="True"> - <dropdown_main classes="sd-sphinx-override sd-dropdown sd-card sd-mb-3" details_name="sd-accordion-index-0" opened="False"> + <dropdown_main classes="sd-sphinx-override sd-dropdown sd-card sd-mb-3" details_name="sd-accordion-index-e540cdd1-0" opened="False"> <dropdown_title classes="sd-summary-title sd-card-header"> <inline classes="sd-summary-text"> First item @@ -13,7 +13,7 @@ <container classes="sd-summary-content sd-card-body" design_component="dropdown-body" is_div="True"> <paragraph classes="sd-card-text"> Opening another item closes this one. - <dropdown_main classes="sd-sphinx-override sd-dropdown sd-card sd-mb-3" details_name="sd-accordion-index-0" opened="True"> + <dropdown_main classes="sd-sphinx-override sd-dropdown sd-card sd-mb-3" details_name="sd-accordion-index-e540cdd1-0" opened="True"> <dropdown_title classes="sd-summary-title sd-card-header"> <inline classes="sd-summary-text"> Second item @@ -23,7 +23,7 @@ <container classes="sd-summary-content sd-card-body" design_component="dropdown-body" is_div="True"> <paragraph classes="sd-card-text"> Content of the second item. - <dropdown_main classes="sd-sphinx-override sd-dropdown sd-card sd-mb-3" details_name="sd-accordion-index-0" opened="False"> + <dropdown_main classes="sd-sphinx-override sd-dropdown sd-card sd-mb-3" details_name="sd-accordion-index-e540cdd1-0" opened="False"> <dropdown_title classes="sd-summary-title sd-card-header"> <inline classes="sd-summary-text"> Third item diff --git a/tests/test_snippets/snippet_pre_accordion-basic.xml b/tests/test_snippets/snippet_pre_accordion-basic.xml index 0b6c793..aabc82d 100644 --- a/tests/test_snippets/snippet_pre_accordion-basic.xml +++ b/tests/test_snippets/snippet_pre_accordion-basic.xml @@ -3,17 +3,17 @@ <title> Heading <container classes="sd-accordion" design_component="accordion" is_div="True"> - <container body_classes="" chevron="True" container_classes="sd-mb-3" design_component="dropdown" details_name="sd-accordion-index-0" has_title="True" icon="True" is_div="True" opened="False" title_classes="" type="dropdown"> + <container body_classes="" chevron="True" container_classes="sd-mb-3" design_component="dropdown" details_name="sd-accordion-index-e540cdd1-0" has_title="True" icon="True" is_div="True" opened="False" title_classes="" type="dropdown"> <rubric> First item <paragraph> Opening another item closes this one. - <container body_classes="" chevron="True" container_classes="sd-mb-3" design_component="dropdown" details_name="sd-accordion-index-0" has_title="True" icon="True" is_div="True" opened="True" title_classes="" type="dropdown"> + <container body_classes="" chevron="True" container_classes="sd-mb-3" design_component="dropdown" details_name="sd-accordion-index-e540cdd1-0" has_title="True" icon="True" is_div="True" opened="True" title_classes="" type="dropdown"> <rubric> Second item <paragraph> Content of the second item. - <container body_classes="" chevron="True" container_classes="sd-mb-3" design_component="dropdown" details_name="sd-accordion-index-0" has_title="True" icon="True" is_div="True" opened="False" title_classes="" type="dropdown"> + <container body_classes="" chevron="True" container_classes="sd-mb-3" design_component="dropdown" details_name="sd-accordion-index-e540cdd1-0" has_title="True" icon="True" is_div="True" opened="False" title_classes="" type="dropdown"> <rubric> Third item <paragraph> From b98b166a05cd04fcd0523d91bf6c50ee981c0647 Mon Sep 17 00:00:00 2001 From: Chris Sewell <chrisj_sewell@hotmail.com> Date: Thu, 16 Jul 2026 14:58:11 +0000 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=93=9A=20Fill=20changelog=20PR=20numb?= =?UTF-8?q?er?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7b471a..20a65a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ JavaScript-free `<details name>` attribute. It degrades gracefully on browsers that predate the feature (each item stays independently collapsible), and offers a `:flush:` edge-to-edge variant and a `class` - option ({pr}`PRNUM`) + option ({pr}`291`) - ♻️ IMPROVE: Replace the Sass/Node build with a dependency-free Python CSS generator (`tools/generate_css.py` driven by `style/design.toml` and hand-authored `style/*.css`); `package.json` is gone. The compiled