/* Use https://www.audioeye.com/color-contrast-checker/ to ensure colour contrast */

/* A printed clip is a still frame, so the controls it carries are noise
   printed over it. Vendor pseudo-elements are the only handle CSS has on
   native controls; a browser that ignores them still prints the frame. */
@media print {
    video::-webkit-media-controls,
    video::-webkit-media-controls-enclosure,
    video::-webkit-media-controls-panel {
        display: none !important;
    }
}

/* Lexend, served from this site rather than from Google. A third-party
   font cannot start loading until this sheet has been parsed and a glyph
   of it laid out, and text reflows when it lands; the copy here is
   preloaded from the page head (see _templates/layout.html), so it
   arrives with the page and the text is drawn in it from the start.
   One file per unicode range covers every weight: Lexend is a variable
   font, and the site draws with 300, 500 and 800. */
@font-face {
    font-family: 'Lexend';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url("vendor/lexend/lexend-latin.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
        U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
        U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Lexend';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url("vendor/lexend/lexend-latin-ext.woff2") format("woff2");
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
        U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F,
        U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F,
        U+A720-A7FF;
}



/* The :icon: role's inline SVG. The nudge puts the glyph on the text
   baseline rather than the bottom of the line box, which is where an
   SVG sits by default. */
.icon svg {
    vertical-align: -0.125em;
}

/* Anchor links the API reference puts on section captions: invisible ink
until hovered, like the theme's own headerlinks */
.headerlink {
    --link-color: transparent;
}

.headerlink:hover {
    --link-color: var(--pst-color-link-hover);
}

.headerlink a.reference.internal {
    text-decoration: none;
    color: var(--link-color);
}

/* module captions in the API reference sidebar are links; keep them looking
like the other sidebar captions */
.caption-text>a {
    color: var(--pst-color-text-base);
    text-decoration: none;
}

:root {
    /* default muted-foreground doesn't work with light-blue background on sigs */
    --muted-foreground: #636d83;

    /* One container for the whole page: header, content and footer stay
       inside this width and centre together, so nothing spans a wide
       desktop screen edge to edge. The theme's own page width, which
       leaves the article column at the reading measure the site has
       always had; the footer follows it rather than the reverse. */
    --syside-page-width: 88rem;

    /* the header bar's full height: the 2.5rem row plus its paddings.
       Not derivable from --pst-header-height, which counts the row
       alone, so the drawer below needs it spelled out. */
    --syside-header-bar: 3.5rem;
}

.bd-page-width {
    max-width: var(--syside-page-width);
}

/* The theme centres the article column in whatever the sidebars leave,
   so a page whose page-toc comes out empty, and which therefore gets no
   secondary sidebar, would put its text 8.5rem to the right of where
   every other page puts it. Standing in for the missing sidebar keeps
   one column position, and one reading measure, from page to page.

   Two guards. Above 1200px only: below it the theme turns that sidebar
   into a drawer that takes no column, so the space is already the
   article's. And only where a primary sidebar holds its column, which
   `hide-on-wide` marks the pages without: a page with neither sidebar,
   the front page among them, is centred on the screen and has no column
   to line up with. */
@media (min-width: 1200px) {
    .bd-container__inner:has(.bd-sidebar-primary:not(.hide-on-wide)):not(:has(.bd-sidebar-secondary))
        .bd-content {
        padding-inline-end: var(--pst-sidebar-secondary);
    }
}

html[data-theme="light"] {
    --pst-color-primary: #0197cd;
    --pst-color-secondary: #0197cd;
    --pst-color-secondary-highlight: #6d6a73;
    --pst-color-primary-highlight: #6d6a73;

    --pst-color-surface: #f8f9fa;
    --pst-color-on-surface: #222832;

    /* signature blocks: API reference symbols and settings page keys */
    --sig-color: #19527b;
    --sig-border-top: #93bad4;
    --sig-background: #e7f2fa;
    --sig-border-left-color: #3e4446;
    --sig-border-left: #ccc;
}

html[data-theme="dark"] {
    --pst-color-surface: #29313d;
    --pst-color-on-surface: #f3f4f5;

    --sig-color: #fff;
    --sig-border-top: #4e5b64;
    --sig-background: #29313d;
    --sig-border-left-color: #3e4446;
    --sig-border-left: #666;
}

/* Hide the theme switch button */
button[aria-label="Color theme switcher"] {
    display: none !important;
}

/* keep the version dropdown discrete */
.version-switcher__button {
    font-size: 0.8em;
    padding: 0.25rem 0.5rem;
    color: var(--pst-color-text-muted);
    border-color: var(--pst-color-border);
}

.h-14 {
    height: 5rem;
}

img {
    width: 15rem;
    height: auto;
    filter: invert(0) !important;
}

img.shadowed-image,
video.shadowed-image {
    box-shadow: 0 4px 24px rgba(0, 0, 0, 0.07);
    margin: 30px auto;
}

/* A video is inline by default and the theme's rules for placing and
   fitting a picture name img, so a clip needs them stated for itself:
   without these it sits left, unshadowed, and free to overflow a narrow
   column. */
video {
    display: block;
    max-width: 100%;
    height: auto;
}

video.align-center {
    margin-left: auto;
    margin-right: auto;
}

video.align-right {
    margin-left: auto;
}

.top-banner p {
    margin: 0;
}

* {
    /* Disable ligatures */
    font-variant-ligatures: none;
}

.copy {
    display: none;
}

.dark,
.dark-mode,
header,
footer {
    background-color: var(--pst-color-surface) !important;
    color: var(--pst-color-on-surface) !important;
}

/* only the background: the text keeps the theme's inline-code accent,
so a code span stands out from the prose around it instead of sitting
grey on a grey chip */
code {
    background-color: var(--pst-color-surface) !important;
}

/* code chips inside cross-reference links: the rules above would paint
them like plain code, keep the link color and skip the underline instead,
the chip outline already marks them */
a.reference:has(> code) {
    text-decoration: none;
}

a.reference code {
    color: var(--pst-color-link) !important;
}

a.reference:hover code {
    color: var(--pst-color-link-hover) !important;
}

a.current.reference.internal,
kbd {
    background-color: var(--pst-color-surface) !important;
    color: var(--pst-color-on-surface) !important;
}

body {
    background-color: var(--pst-color-background) !important;
    color: var(--pst-color-on-surface) !important;
}

/* Updated font assignments */
h1 {
    font-family: 'Lexend', sans-serif !important;
    /* Extra Bold */
    font-weight: 800 !important;
}

h2,
h3,
h4,
h5,
h6,
p.caption {
    font-family: 'Lexend', sans-serif !important;
    /* Medium for subheadings */
    font-weight: 500 !important;
}

html,
body,
p {
    font-family: 'Lexend', sans-serif !important;
    /* Light */
    font-weight: 300 !important;
}

.sig-object {
    display: table;
    margin: 6px 0;
    color: var(--sig-color);
    border-top: 3px solid var(--sig-border-top);
    background: var(--sig-background);
    padding: 6px;
    position: relative;
}

:is(.class, .exception)>dd> :is(.attribute, .method, .property)>.sig-object {
    border-left-color: var(--sig-border-left-color);
    border: none;
    border-left: 3px solid var(--sig-border-left);
}

/* signature annotations (the class/property keywords, attribute types and
default values) render as span.property, which no theme styles; italics set
them off from the names, like the parameter lists' em.sig-param */
.sig .property {
    font-style: italic;
}

/* Ensure that inline image (mainly vscode extensions pane icon) stays inline */
#content img.inline {
    margin-top: -1.5ex;
}

/* Card hover effects */
.sd-card {
    transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
}

.sd-card:hover {
    transform: translateY(-4px);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
}

/* Clickable links above card stretched-link overlay */
.sd-card a:not(.sd-stretched-link),
.sd-card button {
    position: relative;
    z-index: 2;
}

html[data-theme="light"] .sd-badge.sd-bg-warning {
      color: #ffffff !important;
  }

/* The "New" pill (util/badges.py) is filled so that it catches the eye in
   the sidebar, and takes its green from the theme rather than from
   sphinx-design, whose lighter one leaves its text short of 4.5:1. */
.sd-badge.syside-badge-new {
    background-color: var(--pst-color-success);
    color: var(--pst-color-background);
}

.syside-download-btn {
    padding: 0.5em 1.2em;
    background: #06a6df;
    color: #fff;
    font-weight: bold;
    border: none;
    border-radius: 8px;
    font-size: 1em;
    cursor: pointer;
    box-shadow: 0 2px 0 #ccc;
    transition: background 0.2s;
    height: 2.5em;
    display: flex;
    align-items: center;
    margin-bottom: 0.75em;
}

.syside-download-btn:hover {
    background: #0594c7;
}

/* Footer Styles */
.footer-banner {
    background-color: var(--pst-color-surface);
    border-top: 1px solid #e9ecef;
    padding: 2rem 0;
    margin-top: 3rem;
}

.prev-next-footer {
    background-color: var(--pst-color-background) !important;
}

.footer-content {
    max-width: var(--syside-page-width);
    margin: 0 auto;
    padding: 0 1rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2rem;
}

.footer-copyright {
    text-align: center;
    padding-top: 1rem;
    border-top: 1px solid #e9ecef;
    width: 100%;
}

.footer-copyright p {
    margin: 0;
    color: #6c757d;
    font-size: 0.9rem;
}

.footer-sections {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 4rem;
    width: 100%;
    justify-content: center;
}

.footer-section {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    text-align: center;
}

.footer-section h4 {
    /* color: #2c3e50; */
    font-size: 1.1rem;
    font-weight: 600;
    margin: 0 0 0.5rem 0;
}

.footer-section p {
    margin: 0;
    color: #6c757d;
    font-size: 0.9rem;
    line-height: 1.5;
}

.footer-section a {
    color: #3498db;
    text-decoration: none;
    transition: color 0.2s ease;
}

.footer-section a:hover {
    color: #2980b9;
    text-decoration: underline;
}

.social-links {
    display: flex;
    gap: 1rem;
    flex-wrap: wrap;
}

.social-links a {
    color: #6c757d;
    font-size: 0.9rem;
}

.social-links a:hover {
    color: #3498db;
}

@media (max-width: 768px) {
    .footer-sections {
        grid-template-columns: 1fr;
        gap: 2rem;
    }

    .footer-section {
        text-align: center;
    }
}

.code-wrapped pre {
    white-space: pre-wrap !important;
    word-wrap: break-word !important;
    overflow-wrap: break-word !important;
}

/* --------------- START OF COMPARISON TABLE --------------- */
/* Internal vertical dividers in comparison table */
.comparison-table th + th,
.comparison-table td + td {
    border-left: var(--bs-border-width) solid var(--pst-color-primary);
    text-align: center;
}

.comparison-table thead tr:first-child th:nth-child(3) {
    border-right: none;
    text-align: right;
    padding-right: 0;
    overflow: visible;
}

.comparison-table thead tr:first-child th:nth-child(3) > * {
    display: inline-block;
    transform: translateX(50%);
}
 
/* Comparison table with section header rows */
.comparison-table thead tr:first-child th:nth-child(4) {
    border-left: none;
    padding: 0;
}

.comparison-table tbody tr:has(td:first-child strong) {
    background-color: var(--pst-color-primary) !important;
}

.comparison-table tbody tr:has(td:first-child strong) td {
    color: #ffffff;
    border-left: none;
    border-right: none;
}

/* Ignore first column as it should keep dotted underlines */
.comparison-table td:not(:first-child) abbr[title] {
    text-decoration: none;                                                                                                                   
}

/* --------------- END OF COMPARISON TABLE --------------- */

/* --------------- CAPTIONED PANEL (io-panel) --------------- */
.io-panel {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--pst-color-border);
    border-radius: 0.25rem;
}

/* .docutils.container qualifiers beat the theme's Bootstrap padding reset */
.io-panel-caption.docutils.container {
    border-bottom: 1px solid var(--pst-color-border);
    padding: 0.5rem;
    font-weight: var(--pst-font-weight-caption);
}

.io-panel-caption p {
    margin: 0;
}

/* Content padding matching the theme's pre padding */
.io-panel.docutils.container > :not(.io-panel-caption) {
    display: block;
    padding: 1rem;
    margin: 0;
}

/* Default size; override per image with :class: sd-w-25/50/75 */
.io-panel img {
    width: 100%;
    height: auto;
}

/* Equal-height columns: opt in with :class-container: match-heights on a grid */
.match-heights .literal-block-wrapper,
.match-heights .io-panel {
    flex: 1;
    display: flex;
    flex-direction: column;
    margin-top: 0;
    margin-bottom: 0;
}

.match-heights .literal-block-wrapper > div[class*="highlight"] {
    flex: 1;
    display: flex;
    flex-direction: column;
}

.match-heights .literal-block-wrapper div.highlight {
    flex: 1;
    display: flex;
    flex-direction: column;
}

.match-heights .literal-block-wrapper pre {
    flex: 1;
}

/* Thumbnails ignore :width: (the global img rule wins over the width attribute);
   size them with :class: sd-w-25/50/75/100 instead. The class lands on the anchor. */
a[class*="sd-w-"] {
    display: inline-block;
}

a[class*="sd-w-"] img {
    width: 100%;
    height: auto;
}

/* --------------- COVERAGE TABLE --------------- */

.coverage-table th + th,
.coverage-table td + td {
    border-left: var(--bs-border-width) solid var(--pst-color-primary);
}

.coverage-table th:nth-child(3),
.coverage-table td:nth-child(3) {
    text-align: center;
}

/* Box every rendered example into a uniform square. The thumbnail
   directive puts the class on the anchor around the img. */
.coverage-table a.coverage-diagram img {
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: contain;
}

/* Square LightBox2 popup, diagram fit inside (needs !important to beat inline styles) */
#lightbox .lb-image {
    width: min(1100px, 90vw, 85vh) !important;
    height: min(1100px, 90vw, 85vh) !important;
    object-fit: contain;
}

/* --------------- END OF COVERAGE TABLE --------------- */

/* Custom abbreviation tooltips */
abbr[title] {
    border-bottom: none;
    text-decoration-thickness: 0.1em;
    text-underline-offset: 0.2em;
}

.resizer,
.resizable-iframe-handle {
    height: 6px;
    background-color: var(--pst-color-border);
    cursor: ns-resize;
    user-select: none;
    position: relative;
    flex-shrink: 0;
}

.resizer:hover,
.resizable-iframe-handle:hover {
    background-color: var(--pst-color-primary);
}

/* Centered line indicator */
.resizer::before,
.resizable-iframe-handle::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 40px;
    height: 3px;
    background-color: var(--pst-color-text-base);
    opacity: 0.3;
    border-radius: 2px;
    pointer-events: none;
}

/* Markers keep their own column: no wrapping, and each takes the same
   width whether it is a letter, an icon or the blank standing in for a
   marker the rule does not carry. */
table.rules-table>tbody>tr>td>p:has(.icon),
table.rules-table>tbody>tr>td>p:has(abbr) {
    white-space: nowrap;
}

table.rules-table abbr[title] {
    display: inline-block;
    width: 1em;
    text-align: center;
    font-weight: 500;
    text-decoration: none;
    cursor: help;
}
/* The theme places the search container first in the navbar end
   regardless of configured order; the stable arrangement across site
   versions is search, the assembled-site version dropdown, and the
   theme toggle last: navigation actions first, the preference control
   at the edge, as the sysand-index navbar orders them. Archives get
   the same rules at assembly time. */
.navbar-header-items__end > .navbar-item:has(.search-button__button) {
  order: 2;
}
.navbar-header-items__end > .navbar-item:has(.version-switcher__button) {
  order: 3;
}
.navbar-header-items__end > .navbar-item:has(.theme-switch-button) {
  order: 4;
}

/* The theme renders the persistent search button twice, once for the
   wide navbar and once for the collapsed one. The wide navbar already
   carries the expanded search field, so only the collapsed copy is
   wanted; without this the header shows search twice.

   The .bd-header prefix is load-bearing rather than decorative: the
   theme lays these items out with `.bd-header .navbar-item{display:flex}`,
   and a single-class selector loses to it however late it is loaded. */
.bd-header .navbar-persistent--container {
  display: none;
}

/* The theme's `navbar_align: content` gives the logo column a rigid
   quarter of the header (Bootstrap col-lg-3). Left rigid, a tight
   navbar could only wrap the controls into a second row; left
   shrinkable, it gave way whenever anything else appeared, and the
   page-toc button appearing at 1200px dragged the nav links 57px
   sideways with it. So the column holds its width and never falls
   below the logo, and what appears or disappears in the header comes
   out of the gap before the controls: the nav links keep their place
   and only the controls move. */
.bd-header .navbar-header-items__start {
  flex-shrink: 0;
  min-width: fit-content;
}

/* One text axis for the page, at every width. Three things should
   start where the reader's eye already runs, the line the title and
   every paragraph begin on, and each of them is offset from it by a
   different amount that the theme decides:

   - the article's own inset, 2rem above 1200px and none below, which
     is what moves the axis when the window is resized;
   - the nav links, which `navbar_align: content` puts on the article
     column's box, half a rem of link padding aside;
   - the breadcrumb row, a sibling of the article rather than part of
     it, inset by its own 0.5rem plus the 0.1875rem margin on the first
     crumb's link.

   Naming the article's inset lets the other two be written as what
   they are, a correction towards that axis, so the three stay together
   when the breakpoint moves the axis rather than lining up on one side
   of it and scattering on the other. */
:root {
  --syside-article-inset: 0rem;
}

@media (min-width: 1200px) {
  :root {
    --syside-article-inset: 2rem;
  }
}

.bd-header .navbar-header-items__center {
  margin-left: calc(var(--syside-article-inset) - 0.5rem);
}

.bd-header-article {
  margin-left: calc(var(--syside-article-inset) - 0.6875rem);
}

/* The navbar dropdown is a button, so it inherits neither the body
   font weight nor the muted colour its sibling links carry, and read
   as the most important item in the row. Make it a peer of the links
   it sits among. */
.bd-header ul.navbar-nav > li.nav-item > .dropdown-toggle {
  font-weight: 300;
  color: var(--pst-color-text-muted);
}

/* The expanded search field is sized by its own text, so it grew when
   the body font arrived and nudged the controls beside it. A fixed
   width, the one the loaded font produces, keeps the header still
   while the glyphs settle. */
.bd-header .navbar-header-items__end .search-button-field {
  width: 12rem;
}

/* Font Awesome loads as a webfont with font-display:block, so every
   header icon is a glyph that arrives after first paint and, sized by
   its own advance, resized the row when it did. A fixed box per icon
   holds the space from the start; 1.25em is Font Awesome's own
   fixed-width measure. The theme-mode icons are excluded: the theme
   shows one of the three by switching their display, which a display
   of our own would defeat. */
.bd-header .fa-solid:not(.theme-switch),
.bd-header .fa-brands:not(.theme-switch) {
  display: inline-block;
  width: 1.25em;
  text-align: center;
}

/* The theme paints the sidebar toggles with --pst-color-muted but the
   theme switch and search icons with --pst-color-text-muted, and draws
   them a size up from those icons' fa-lg; one shade and one size for
   all four. */
.bd-header button.sidebar-toggle {
  color: var(--pst-color-text-muted);
  font-size: 1.25rem;
}

/* The header row takes the sysand-index navbar's proportions: a
   compact bar the 28px brand mark sits naturally in, rather than the
   theme's 4rem default that dwarfed it. Sticky sidebar offsets, the
   breadcrumb bar and scroll padding all derive from this variable and
   follow along. The expanded search field gives up some padding for
   the same reason; its height set the old bar's floor. */
html {
  --pst-header-height: 2.5rem;
}

.navbar-header-items__end .search-button-field {
  padding: 0.25rem 0.75rem;
}

.search-button-field .search-button__kbd-shortcut kbd {
  padding: 0.05rem 0.3rem;
}

/* The brand is a mark plus real text (conf.py logo.text), sized
   independently. The wordmark image drew its ball 1.34x the text
   height, which read as oversized, and one image allows no other
   ratio. The title inherits Lexend from the body rule; the weight
   needs !important because that body rule carries it too. */
/* Height only: a square contain box letterboxed the emblem 12%
   smaller, which pushed its thin outline crown under the visibility
   threshold on dense screens. */
.bd-header .navbar-brand img {
  height: 1.75rem;
  width: auto;
}

.bd-header .navbar-brand .logo__title {
  font-size: 1.15rem;
  font-weight: 800 !important;
  margin: 0;
}

/* the brand text is a home link; it must never pick up an underline */
.bd-header a.navbar-brand,
.bd-header a.navbar-brand:hover {
  text-decoration: none;
}

/* In the version picker menu the entry name says which line (or
   "latest"), and this muted subtext says which patch that resolves to
   right now. */
.version-switcher__menu a {
  display: flex;
  align-items: baseline;
  gap: 1.5rem;
  /* The menu is a shrink-to-fit box positioned inside the button's own
     narrow box, so its width falls back to the content's minimum. A
     pre-release number has a hyphen to break at, and would wrap onto a
     second line; holding the entries on one line makes the menu as wide
     as its longest one instead. */
  white-space: nowrap;
}

.version-switcher__patch {
  margin-left: auto;
  color: var(--pst-color-text-muted);
  font-size: 0.875rem;
}

/* The expanded search field collapses to its bare magnifier icon at
   the same width where the theme hides the secondary sidebar, so the
   header changes once, not twice a few pixels apart. */
@media (max-width: 1199.98px) {
  .navbar-header-items__end .search-button-field .search-button__default-text,
  .navbar-header-items__end .search-button-field .search-button__kbd-shortcut {
    display: none;
  }
  /* the .bd-header prefix matches the rule setting the field's width
     above, which a shorter selector would lose to */
  .bd-header .navbar-header-items__end .search-button-field {
    border: none;
    background: transparent;
    padding: 0.25rem;
    width: auto;
  }
  /* the field's inline icon stays 1rem when the field folds away; the
     bare icon matches the theme toggle's fa-lg size instead */
  .navbar-header-items__end .search-button-field .fa-magnifying-glass {
    font-size: 1.25rem;
  }
  /* the row must hold logo, nav links, controls and the toc toggle all
     the way down to the 960px hamburger point; tighter control spacing
     and toggle margin are what make it fit at the tightest widths */
  .bd-header .navbar-header-items__end {
    column-gap: 0.5rem;
  }

  .bd-header button.secondary-toggle {
    margin-left: 0.5rem;
  }

  /* The page-toc drawer opens over the header, from the top of the
     screen, as the nav drawer used to. Open it below the header too, so
     both drawers leave the header reachable. */
  .bd-sidebar-secondary {
    top: var(--syside-header-bar);
    height: calc(100dvh - var(--syside-header-bar));
    max-height: calc(100dvh - var(--syside-header-bar));
  }
}

/* Below 960px the theme folds the whole navbar end into the hamburger
   sidebar and leaves only its own bare search icon in the header. Keep
   the end controls (theme toggle, search icon, version dropdown) in the
   header instead, and drop both duplicates: the theme's mobile search
   icon and the sidebar's copy of the end controls. The nav links keep
   living in the hamburger sidebar, which stays the only thing the
   toggle opens. */
@media (max-width: 959.98px) {
  .bd-header .navbar-header-items {
    display: flex;
    flex-grow: 0;
    margin-left: auto;
  }
  .bd-header .navbar-header-items__center {
    display: none;
  }
  .bd-header .navbar-persistent--mobile {
    display: none;
  }
  /* the theme shows this with a three-class selector, so a shorter one
     loses regardless of load order */
  .bd-sidebar-primary .sidebar-header-items .sidebar-header-items__end {
    display: none;
  }
  /* The theme opens the nav drawer over the header, from the top of
     the screen, which puts its first entry against the very edge,
     under a phone browser's own chrome. Open it below the header, so
     the header stays reachable and nothing sits at the edge. */
  .bd-sidebar-primary {
    top: var(--syside-header-bar);
    height: calc(100dvh - var(--syside-header-bar));
    max-height: calc(100dvh - var(--syside-header-bar));
  }

  /* the toggles' full 1rem margins are what the row runs out of first
     just above the 540px floor; half keeps clear space there */
  .bd-header button.primary-toggle {
    margin-right: 0.5rem;
  }
  .bd-header button.secondary-toggle {
    margin-left: 0.5rem;
  }
  /* the theme styles the version dropdown for a sidebar placement here
     (larger font, 1em bottom margin), but it stays in the header; keep
     its wide-navbar size so it does not jump when the hamburger appears */
  .bd-header .navbar-header-items__end .version-switcher__button {
    font-size: 1rem;
    margin-bottom: 0;
  }
}

/* Phone-width header, on the theme's smallest breakpoint. Every
   control and the header itself keep their exact size; the brand drops
   its text and keeps the mark. If even the mark-only header runs out
   of room, the version label truncates with an ellipsis, number first,
   rather than letting anything overlap. */
@media (max-width: 539.98px) {
  .bd-header .navbar-brand .logo__title {
    display: none;
  }
  .bd-header .navbar-header-items__end > .navbar-item:has(.version-switcher__button) {
    flex-shrink: 1;
    min-width: 0;
  }
  .bd-header .navbar-header-items__end .version-switcher__button {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}

/* The search field the popup dialog and the search page share. The
   theme pins its magnifier at a fixed offset from the field's left
   edge, over the input's own padding: a rule that never applies to the
   icon a reader sees upstream, because Font Awesome's script rewrites
   the <i> the template writes into an <svg> carrying neither of the
   classes it names. The site drops that script (see
   src/util/fontawesome.py) and serves the glyph the <i> asks for, so
   the rule matches and the icon sits on the first characters typed.

   The field is a flex row with a gap, so the icon takes its place in
   that row instead, ahead of the input, as the header's search button
   carries its own. The input then needs no left padding: the row's gap
   is the space between icon and text. */
form.bd-search .fa-solid.fa-magnifying-glass {
  position: static;
}

form.bd-search input.form-control {
  padding-left: 0;
}

/* the dialog's input is a size up from the page's; the theme sizes the
   icon beside it through the same rule, naming the <svg> again, so the
   glyph is given that size here and the pair stays proportionate */
#pst-search-dialog[open] form.bd-search .fa-solid.fa-magnifying-glass {
  font-size: var(--pst-font-size-icon);
}

/* the shortcut hint keeps the compact chips the header's search button
   uses, rather than the theme's full-size ones */
form.bd-search .search-button__kbd-shortcut kbd {
  padding: 0.05rem 0.3rem;
}

/* Search results in the popup. The theme renders them into the search
   page's #search-results and, for the popup, moves that element into
   the dialog, where the .bd-search-container rules that style a result
   list no longer reach it: the popup showed a bulleted list under an
   article-sized heading while the page showed the same results laid
   out. These repeat that styling where the element now lives, so the
   two read alike. */
#pst-search-dialog #search-results > h2 {
  font-size: var(--pst-font-size-icon);
  margin-top: 0;
}

#pst-search-dialog #search-results p.search-summary {
  color: var(--pst-color-text-muted);
}

#pst-search-dialog #search-results ul.search {
  list-style: none;
  margin: 0;
  padding: 0;
}

#pst-search-dialog #search-results ul.search li {
  border-top: 1px solid var(--pst-color-text-muted);
  margin: 1rem 0;
  padding: 1rem 0;
}

#pst-search-dialog #search-results ul.search li > a {
  font-size: 1.2em;
}

#pst-search-dialog #search-results ul.search li .context {
  color: var(--pst-color-text-base);
  margin: 0.5em 0 0;
}

/* The theme marks whatever the URL fragment points at and keeps it marked
   for as long as the fragment stays, so a page reached through a link to
   one of its members stays painted long after the reader has found it.
   Flash the target and settle back to the page background instead.

   No specificity fight with the theme's own rules is needed: a running
   animation outranks any plain declaration, whatever its selector, and
   `forwards` holds the faded end state once it finishes. */
@keyframes syside-target-fade {
  0%,
  40% {
    background-color: var(--pst-color-target);
  }
  100% {
    background-color: transparent;
  }
}

.bd-article :target > :is(h1, h2, h3, h4, h5),
dt:target,
.viewcode-block:target,
aside.footnote:target {
  animation: syside-target-fade 2.5s ease-out forwards;
}

/* Base-class chain on API class pages. The generator emits it as a plain
   list so every entry stays a resolved cross-reference; the boxes and
   connectors are drawn here, from theme colors, so the diagram follows the
   light and dark palettes that a generated image could not. */
.inheritance-chain {
  margin-bottom: 1.5rem;
}

.inheritance-chain > p {
  text-align: center;
  margin-bottom: 0.75rem;
}

.inheritance-chain ul {
  list-style: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  margin: 0;
  padding: 0;
}

.inheritance-chain li {
  border: 1px solid var(--pst-color-border);
  border-radius: 0.25rem;
  padding: 0.1rem 0.6rem;
  background-color: var(--pst-color-surface);
}

.inheritance-chain li p {
  margin: 0;
}

/* the box is the frame, so the reference chip inside it drops its own */
.inheritance-chain li code {
  border: none;
  padding: 0;
}

/* the connector hangs above each box after the first, so the gap it needs
   is the box's own top margin */
.inheritance-chain li + li {
  position: relative;
  margin-top: 1.4rem;
}

.inheritance-chain li + li::before {
  content: "↓";
  position: absolute;
  top: -1.35rem;
  left: 50%;
  transform: translateX(-50%);
  line-height: 1;
  color: var(--pst-color-text-muted);
}

/* the search input under the Symbol reference caption in the generated
   API sidebar. The left inset is the padding the theme puts on a sidebar
   entry link, so the box lines up with the entries below it */
.api-sidebar-search {
    margin: 0.25rem 0.25rem 0.25rem 0.65rem;
}

/* the module a search result lives in, after its name: present because a
   flat result cannot say it by position the way a tree did. Dimmed by
   opacity rather than by colour: a sidebar link is already drawn in the
   muted colour, so naming that colour again separates nothing. */
.api-search-where {
    opacity: 0.75;
    font-size: 0.85em;
}

/* One line per result, cut off rather than wrapped. A wrapped result put
   the module on a second line at the left margin, where it read as an
   entry of its own; the name is the part being matched, so what a narrow
   sidebar drops is the tail of the module path. */
.api-search-result a {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* what the search box reports, for a reader who cannot see the list
   change under it */
.api-search-status {
    margin: 0.25rem 0 0 0.65rem;
    color: var(--pst-color-text-muted);
    font-size: var(--pst-sidebar-font-size, 0.9rem);
}

/* the count and no-match lines the search box shows in place of results */
.api-search-empty {
    padding: 0.25rem 0 0.25rem 0.65rem;
    color: var(--pst-color-text-muted);
    font-size: var(--pst-sidebar-font-size, 0.9rem);
}

.api-sidebar-search input {
    width: 100%;
    padding: 0.3rem 0.6rem;
    font-size: var(--pst-sidebar-font-size, 0.9rem);
    color: var(--pst-color-text-base);
    background-color: var(--pst-color-background);
    border: 1px solid var(--pst-color-border);
    border-radius: 0.25rem;
}

.api-sidebar-search input::placeholder {
    color: var(--pst-color-text-muted);
}

.api-sidebar-search input:focus {
    outline: none;
    border-color: var(--pst-color-primary);
}

/* !important: the theme styles sidebar items with higher specificity */
.bd-sidebar .api-search-hidden {
    display: none !important;
}
