/*
 * Muhdo.Common.Blazor controls.
 *
 * Link once in index.html, after Bootstrap and the theme CSS and before the app's own overrides:
 * <link href="_content/Muhdo.Common.Blazor/css/muhdo-controls.css?v=<package version>" rel="stylesheet" />
 *
 * The host also loads Bootstrap 5 (btn, spinner-border, d-flex, text-start and the other utilities the markup uses) and
 * Material Design Icons (the mdi classes).
 *
 * Theming: every token is read as var(--token, <literal>) under the portals' own token names, and none is declared on
 * :root here, so an app's :root block, or a per-organisation style block injected at runtime, always wins whatever the link
 * order. The literals are the Muhdo defaults.
 *
 * Tokens: --brand-50, --brand-100, --brand-600, --brand-700, --brand-rgb (as "22, 148, 200"), --ink-500, --line-100,
 * --line-200, --surface-2, --r-sm, --r-md, and per status (ok, warn, bad, grape) the colour --<status> with its
 * --<status>-tint background and --<status>-line border.
 *
 * The sheet is global rather than scoped .razor.css: apps also put the pill classes on plain spans, and the index.html
 * boot loader draws its helix with the .dna-* classes before Blazor starts. The boot loader's placement
 * (.dna-loader-boot, .loading-progress-text) stays in the app.
 */

/* Confirm bubble: ConfirmButtonComponent and DeleteButtonComponent. The bubble is hidden until the component adds show
   to it on the first press. */
.popup-container {
    position: relative;
}

.popup-container .popup-contents-above,
.popup-container .popup-contents-below,
.popup-container .popup-contents-left,
.popup-container .popup-contents-right {
    visibility: hidden;
    width: 80px;
    background-color: #555;
    color: #fff;
    text-align: center;
    border-radius: 6px;
    padding: 8px 0;
    position: absolute;
    z-index: 1;
}

.popup-container .popup-contents-above,
.popup-container .popup-contents-below {
    left: 50%;
    margin-left: -40px;
}

/* Beside the button rather than over or under it, so the bubble stays within its own row. A row inside an overflow
   container clips anything crossing the container's top or bottom edge, which is what above and below do on the first
   and last rows of a scrolling list. */
.popup-container .popup-contents-left,
.popup-container .popup-contents-right {
    top: 50%;
    transform: translateY(-50%);
}

.popup-container .popup-contents-above {
    bottom: 125%;
}

.popup-container .popup-contents-below {
    top: 125%;
}

.popup-container .popup-contents-left {
    right: 125%;
}

.popup-container .popup-contents-right {
    left: 125%;
}

.popup-container .popup-contents-above::after,
.popup-container .popup-contents-below::after,
.popup-container .popup-contents-left::after,
.popup-container .popup-contents-right::after {
    content: "";
    position: absolute;
    border: 5px solid transparent;
}

.popup-container .popup-contents-above::after {
    top: 100%;
    left: calc(50% - 5px);
    border-top-color: #555;
}

.popup-container .popup-contents-below::after {
    bottom: 100%;
    left: calc(50% - 5px);
    border-bottom-color: #555;
}

.popup-container .popup-contents-left::after {
    left: 100%;
    top: calc(50% - 5px);
    border-left-color: #555;
}

.popup-container .popup-contents-right::after {
    right: 100%;
    top: calc(50% - 5px);
    border-right-color: #555;
}

.popup-container .show {
    visibility: visible;
    animation: muhdo-popup-fade-in 1s;
}

@keyframes muhdo-popup-fade-in {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

/* DNA loader: LoadingComponent and the index.html boot loader. */
.dna-loader {
    display: inline-block;
    line-height: 0;
}

.dna-loader-md .dna-loader-svg {
    width: 60px;
    height: 60px;
}

.dna-loader-sm .dna-loader-svg {
    width: 30px;
    height: 30px;
}

.dna-strand {
    fill: none;
    stroke-width: 3;
    stroke-linecap: round;
    stroke: rgb(var(--brand-rgb, 22, 148, 200));
    animation: dna-helix-pulse 1.2s ease-in-out infinite;
}

.dna-strand-b {
    opacity: 0.5;
    animation-delay: -0.6s;
}

.dna-rungs line {
    stroke: rgb(var(--brand-rgb, 22, 148, 200));
    stroke-width: 2;
    stroke-linecap: round;
    opacity: 0.6;
    transform-box: fill-box;
    transform-origin: center;
    animation: dna-rung-spin 1.2s linear infinite;
}

.dna-rungs line:nth-child(2) {
    animation-delay: -0.15s;
}

.dna-rungs line:nth-child(3) {
    animation-delay: -0.30s;
}

.dna-rungs line:nth-child(4) {
    animation-delay: -0.45s;
}

.dna-rungs line:nth-child(5) {
    animation-delay: -0.60s;
}

.dna-rungs line:nth-child(6) {
    animation-delay: -0.75s;
}

.dna-rungs line:nth-child(7) {
    animation-delay: -0.90s;
}

.dna-rungs line:nth-child(8) {
    animation-delay: -1.05s;
}

@keyframes dna-helix-pulse {
    0%, 100% {
        opacity: 0.4;
    }

    50% {
        opacity: 1;
    }
}

@keyframes dna-rung-spin {
    0% {
        transform: scaleY(1);
        opacity: 0.7;
    }

    50% {
        transform: scaleY(0.15);
        opacity: 0.2;
    }

    100% {
        transform: scaleY(1);
        opacity: 0.7;
    }
}

/* MessageComponent. No font-size, so the panel takes the size of its context or of a size class in BackgroundCss. */
.message-component-background {
    margin: 5px;
    padding: 10px;
    border-radius: var(--r-sm, 8px);
}

/* Filter bar: FilterBarComponent and FilterChipComponent. */
.filter-bar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
    padding: 10px 14px;
    margin-bottom: 14px;
    background: var(--surface-2, #FAFCFD);
    border: 1px solid var(--line-200, #E4EAEF);
    border-radius: var(--r-md, 12px);
}

.filter-bar-icon {
    color: var(--brand-600, #0E7CAB);
    font-size: 18px;
    flex-shrink: 0;
}

.filter-bar-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    flex: 1 1 auto;
    min-width: 0;
}

/* The edit and clear buttons wrap as one group. */
.filter-bar-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    flex-shrink: 0;
}

.filter-chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 12.5px;
    line-height: 1.4;
    padding: 4px 11px;
    border-radius: 999px;
    background: var(--brand-50, #ECF7FC);
    color: var(--brand-700, #0C6488);
    border: 1px solid var(--brand-100, #D2ECF7);
    white-space: nowrap;
}

.filter-chip .mdi {
    font-size: 13px;
}

.filter-chip-label {
    font-weight: 600;
}

.filter-chip-value {
    font-weight: 500;
}

.filter-chip .filter-chip-remove {
    padding: 0;
    border: 0;
    line-height: 1;
    font-size: 13px;
    color: inherit;
    opacity: 0.65;
    text-decoration: none;
}

.filter-chip .filter-chip-remove:hover,
.filter-chip .filter-chip-remove:focus-visible {
    opacity: 1;
    color: var(--bad, #D6455B);
}

/* Cancels the Bootstrap mx-1 that LoadingIconComponent puts on the remove button's icon. */
.filter-chip .filter-chip-remove i {
    margin: 0 !important;
}

/* Pills: PillComponent, one variant per PillStyleEnum value. */
.pill {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 11.5px;
    font-weight: 600;
    padding: 3px 9px;
    border-radius: 999px;
    white-space: nowrap;
    line-height: 1.4;
}

.pill .mdi {
    font-size: 13px;
}

.pill.ok {
    background: var(--ok-tint, #E6F6EF);
    color: var(--ok, #1F9D6B);
    border: 1px solid var(--ok-line, #BDE6D3);
}

.pill.warn {
    background: var(--warn-tint, #FBF1DD);
    color: var(--warn, #C77A12);
    border: 1px solid var(--warn-line, #F0DBAE);
}

.pill.bad {
    background: var(--bad-tint, #FBE7EB);
    color: var(--bad, #D6455B);
    border: 1px solid var(--bad-line, #F2C3CC);
}

.pill.info {
    background: var(--brand-50, #ECF7FC);
    color: var(--brand-700, #0C6488);
    border: 1px solid var(--brand-100, #D2ECF7);
}

.pill.grape {
    background: var(--grape-tint, #ECECFB);
    color: var(--grape, #5B5BD6);
    border: 1px solid var(--grape-line, #CFCFF4);
}

.pill.neut {
    background: var(--line-100, #EEF2F5);
    color: var(--ink-500, #5B6B76);
    border: 1px solid var(--line-200, #E4EAEF);
}

/* A pill that truncates its label (keeps the leading icon, ellipsises the text) rather than overflowing. */
.pill.pill-truncate {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: middle;
}

/* Drawer: DrawerComponent. A right-side tray over a backdrop. z-index 1045/1046 puts it over Bootstrap's sticky and
   fixed bars and under its modals. No ancestor may carry a transform, because the tray is position:fixed. */
.drawer-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, .32);
    opacity: 0;
    visibility: hidden;
    transition: opacity .2s ease;
    z-index: 1045;
}

.drawer-backdrop.show {
    opacity: 1;
    visibility: visible;
}

.drawer {
    position: fixed;
    top: 0;
    right: 0;
    height: 100%;
    width: min(720px, 96vw);
    background: var(--surface, #FFFFFF);
    transform: translateX(100%);
    transition: transform .25s ease;
    z-index: 1046;
    display: flex;
    flex-direction: column;
}

.drawer.open {
    transform: translateX(0);
    box-shadow: var(--shadow-lg, 0 24px 60px rgba(13, 30, 40, .16), 0 8px 20px rgba(13, 30, 40, .08));
}

.drawer.drawer-wide {
    width: min(960px, 96vw);
}

.drawer-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 15px 18px;
    border-bottom: 1px solid var(--line-200, #E4EAEF);
}

.drawer-body {
    padding: 14px 16px;
    overflow-y: auto;
    flex: 1;
}

.drawer-footer {
    padding: 13px 16px;
    border-top: 1px solid var(--line-200, #E4EAEF);
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    flex-wrap: wrap;
}

.drawer-subheader {
    padding: 12px 18px;
    border-bottom: 1px solid var(--line-200, #E4EAEF);
    background: var(--surface-2, #FAFCFD);
}

.drawer-form {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}

/* Tab strip: TabsComponent and TabItemComponent. The strip scrolls sideways rather than wrapping. */
.ptabs {
    display: flex;
    flex-wrap: nowrap;
    gap: 4px;
    padding: 4px;
    background: var(--surface-2, #FAFCFD);
    border: 1px solid var(--line-200, #E4EAEF);
    border-radius: var(--r-md, 12px);
    overflow-x: auto;
    scrollbar-width: none;
}

/* Hidden when no tab occupies the strip, without depending on Bootstrap's [hidden] rule. */
.ptabs[hidden] {
    display: none;
}

.ptabs::-webkit-scrollbar {
    display: none;
}

.ptab {
    appearance: none;
    background: none;
    border: 1px solid transparent;
    border-radius: calc(var(--r-md, 12px) - 4px);
    padding: 8px 14px;
    font-size: 13.5px;
    font-weight: 600;
    color: var(--ink-500, #5B6B76);
    display: inline-flex;
    align-items: center;
    gap: 7px;
    flex: 0 0 auto;
    white-space: nowrap;
    transition: background-color 0.12s ease, color 0.12s ease;
}

.ptab:hover {
    color: var(--ink-800, #16242E);
    background: var(--line-100, #EEF2F5);
}

.ptab.on {
    color: var(--brand-700, #0C6488);
    background: var(--surface, #FFFFFF);
    border-color: var(--line-200, #E4EAEF);
    box-shadow: var(--shadow-sm, 0 1px 2px rgba(13, 30, 40, 0.06), 0 1px 1px rgba(13, 30, 40, 0.04));
}

.ptab .mdi {
    font-size: 16px;
}

/* The placeholder for a tab whose visibility is still loading. It stretches to the height of the tabs beside it, and the
   min-height keeps it visible in a strip that holds only placeholders. */
.ptab-skeleton {
    flex: 0 0 auto;
    width: 130px;
    min-height: 36px;
    border-radius: calc(var(--r-md, 12px) - 4px);
    background: var(--line-100, #EEF2F5);
    animation: muhdo-skeleton-pulse 1.2s ease-in-out infinite;
}

@keyframes muhdo-skeleton-pulse {
    0%, 100% {
        opacity: 1;
    }

    50% {
        opacity: 0.55;
    }
}

@media (min-width: 768px) {
    .ptabs {
        scrollbar-width: thin;
        scrollbar-color: var(--line-200, #E4EAEF) transparent;
        padding-bottom: 8px;
    }

    .ptabs::-webkit-scrollbar {
        display: block;
        height: 8px;
    }

    .ptabs::-webkit-scrollbar-track {
        background: transparent;
    }

    .ptabs::-webkit-scrollbar-thumb {
        background: var(--line-200, #E4EAEF);
        border-radius: 999px;
    }

    .ptabs::-webkit-scrollbar-thumb:hover {
        background: var(--ink-500, #5B6B76);
    }
}

/* Sticky strips (CssClass "ptabs-sticky ptabs-sticky-N") pin to the top of a scrolling .drawer-body, full-bleed over its
   14px top and 16px side padding. Every level pins at the same offset and a deeper level stacks above a shallower one.
   Must follow the .ptabs rules. */
.ptabs-sticky {
    position: sticky;
    top: -14px;
    margin-left: -16px;
    margin-right: -16px;
    padding-left: 16px;
    padding-right: 16px;
    border-radius: 0;
    border-left: 0;
    border-right: 0;
}

.ptabs-sticky-1 {
    z-index: 4;
}

.ptabs-sticky-2 {
    z-index: 5;
}

.ptabs-sticky-3 {
    z-index: 6;
}

/* The container (TabsComponent ShowContainer, on by default) frames the strip and its panels as one card: the strip
   becomes the card's header band and each panel is padded. It must not clip (no overflow), or a sticky strip inside it
   stops pinning. Must follow the .ptabs and .ptabs-sticky rules. */
.ptabs-group {
    background: var(--surface, #FFFFFF);
    border: 1px solid var(--line-200, #E4EAEF);
    border-radius: var(--r-md, 12px);
}

.ptabs-group > .ptabs {
    border-width: 0 0 1px 0;
    border-radius: var(--r-md, 12px) var(--r-md, 12px) 0 0;
}

.ptabs-group > .ptabs-sticky {
    margin-left: 0;
    margin-right: 0;
    padding-left: 4px;
    padding-right: 4px;
}

.ptabs-group > .ptab-panel {
    padding: 16px;
}

/* Without the container the wrapper drops out of layout, so the strip and panels sit exactly as they did before it. */
.ptabs-bare {
    display: contents;
}

/* Accordion: AccordionComponent and AccordionItemComponent. Org themes set the --acc-head-bg, --acc-head-fg,
   --acc-body-bg and --acc-body-fg tokens at runtime, so those names must stay. */
.acc {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.acc-item {
    border: 1px solid var(--line-200, #E4EAEF);
    border-radius: var(--r-md, 12px);
    background: var(--surface, #FFFFFF);
    overflow: hidden;
    transition: border-color .15s ease, box-shadow .15s ease;
}

.acc-item.is-open {
    border-color: rgba(var(--brand-rgb, 22, 148, 200), .35);
    box-shadow: var(--shadow-sm, 0 1px 2px rgba(13, 30, 40, .06), 0 1px 1px rgba(13, 30, 40, .04));
}

.acc-head {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 13px 18px;
    background-color: var(--acc-head-bg, var(--surface-2, #FAFCFD));
    background-image: linear-gradient(90deg, rgba(var(--brand-rgb, 22, 148, 200), .10), transparent 60%);
    color: var(--acc-head-fg, var(--ink-800, #16242E));
    font-weight: 600;
    cursor: pointer;
    transition: background .15s ease, color .15s ease;
}

.acc-head:hover {
    background: var(--brand-50, #ECF7FC);
}

.acc-item.is-open > .acc-head {
    background: var(--brand-50, #ECF7FC);
    color: var(--brand-700, #0C6488);
}

/* The head's top corners follow the item's radius less its 1px border. */
.acc-item > .acc-head {
    border-top-left-radius: calc(var(--r-md, 12px) - 1px);
    border-top-right-radius: calc(var(--r-md, 12px) - 1px);
}

.acc-heading {
    flex: 1;
    min-width: 0;
}

.acc-heading h5 {
    margin: 0;
    font-size: 14px;
    font-weight: 600;
    line-height: 1.3;
}

.acc-chevron {
    flex-shrink: 0;
    font-size: 22px;
    color: var(--ink-400, #8595A0);
    transition: transform .2s ease, color .2s ease;
}

.acc-item.is-open > .acc-head .acc-chevron {
    transform: rotate(180deg);
    color: var(--brand-600, #0E7CAB);
}

.acc-collapse {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows .25s ease;
}

.acc-collapse.show {
    grid-template-rows: 1fr;
}

.acc-collapse-inner {
    min-height: 0;
    overflow: hidden;
}

/* While a searchable select's panel is open inside an item (the panel renders only when open), the item stops
   clipping so the panel can drop below it. */
.acc-item:has(.user-search-panel),
.acc-item:has(.user-search-panel) .acc-collapse-inner {
    overflow: visible;
}

.acc-panel {
    background: var(--acc-body-bg, var(--surface, #FFFFFF));
    color: var(--acc-body-fg, var(--ink-700, #243441));
    border-top: 1px solid var(--line-200, #E4EAEF);
}

.acc-body {
    padding-top: 12px;
    padding-bottom: 12px;
}

@media (prefers-reduced-motion: reduce) {
    .acc-collapse {
        transition: none;
    }
}

/* Switch: SwitchComponent. The checkbox stays in the page but is invisible, and the label straight after it draws the
   track and the knob, with data-off-label or data-on-label inside the track. Scoped to .switch-control so these rules
   also beat the Hyper theme's input[data-switch] rules, which hide the checkbox and draw their own track. */
.switch-control {
    position: relative;
}

.switch-control input[data-switch] {
    display: block;
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
    margin: 0;
}

.switch-control input[data-switch] + label {
    position: relative;
    display: inline-block;
    vertical-align: middle;
    margin: 0;
    cursor: pointer;
    width: 56px;
    height: 24px;
    border-radius: 30px;
    background: var(--line-300, #D7DEE4);
    text-align: inherit;
    transition: background .15s;
}

.switch-control input[data-switch] + label::before {
    content: attr(data-off-label);
    position: absolute;
    right: 7px;
    top: 0;
    margin: 0;
    min-width: 0;
    line-height: 24px;
    font-size: 10.5px;
    font-weight: 600;
    color: var(--ink-500, #5B6B76);
    text-align: inherit;
    overflow: visible;
    transition: none;
}

.switch-control input[data-switch] + label::after {
    content: '';
    position: absolute;
    left: 3px;
    top: 3px;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 1px 2px rgba(0, 0, 0, .25);
    transition: left .15s;
}

.switch-control input[data-switch]:checked + label {
    background: var(--ok, #1F9D6B);
}

.switch-control input[data-switch]:checked + label::before {
    content: attr(data-on-label);
    left: 9px;
    right: auto;
    color: #fff;
}

.switch-control input[data-switch]:checked + label::after {
    left: 35px;
    background: #fff;
}

.switch-control input[data-switch]:disabled + label {
    opacity: .5;
    cursor: not-allowed;
}

.switch-control input[data-switch]:focus-visible + label {
    box-shadow: 0 0 0 .2rem rgba(var(--brand-rgb, 22, 148, 200), .25);
}

/* The side texts are labels for the checkbox, so clicking them flips the switch. The inherited weight undoes the Hyper
   theme's label { font-weight: 600 }; Bootstrap's me-2 and ms-2 still set the gap. */
.switch-control .switch-side-label {
    cursor: pointer;
    margin: 0;
    font-weight: inherit;
}

.switch-control:has(input[data-switch]:disabled) .switch-side-label {
    cursor: not-allowed;
}

/* Page header: PageHeaderComponent. The title colour follows --page-title, which organisation themes set. Only the
   heading's own icon takes the brand colour, so icons inside TitleFragment keep theirs. */
.page-title-box .header-title {
    color: var(--page-title, var(--ink-900, #0E1A22));
    font-size: 21px;
    font-weight: 800;
    letter-spacing: -.01em;
    display: flex;
    align-items: center;
    gap: 9px;
    margin: 0;
}

.page-title-box .header-title > i {
    color: var(--brand-600, #0E7CAB);
}

/* The title takes the free width and wraps inside it, so a kebab menu stays beside it on any phone. The box wraps on
   each item's full width, so the 12rem basis means only a menu wider than the rest of the row moves to its own line. */
.page-title-main {
    flex: 1 1 12rem;
    min-width: 0;
}

.page-title-main > .header-title + .text-muted {
    margin-top: .25rem;
}

/* A free-form menu that wraps onto its own line stays on the right. */
.page-title-menu {
    margin-left: auto;
}

/* Below md, a free-form menu takes its own full-width line under the title. */
@media (max-width: 767.98px) {
    .page-title-menu {
        flex-basis: 100%;
    }
}

/* Ribbon: RibbonComponent. The host element carries ribbon-box. Every RibbonStyleEnum variant draws in the warning
   colours, which organisation themes set through --c-warning-bg and --c-warning-border. */
.ribbon-box {
    position: relative;
}

.ribbon {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 600;
    padding: 4px 12px;
    border-radius: 6px;
    background: var(--c-warning-bg, var(--warn-tint, #FBF1DD));
    border: var(--c-warning-border, 1px solid var(--warn-line, #F0DBAE));
    color: var(--bs-warning-text-emphasis, #664d03);
}

/* Below lg, a row that follows a floated ribbon starts under it rather than beside it. */
@media (max-width: 991.98px) {
    .ribbon-box .ribbon + .row {
        clear: both;
    }
}

/* Pager: PaginationComponent. The toggle rule carries --ct-btn-* twins of each --bs-btn-* for Magellan's Hyper theme, and
   :not(.dropdown-toggle-split) lifts it above the portals' select-toggle rules (Helix theme.css, Magellan helix-align.css).
   The 150px minimum width and square right corners belong to the go-to toggle only, so the page-size picker keeps its
   own shape and the refresh, previous and next buttons sit at their natural width after it. Phones drop the minimum so
   the joined group fits a 320px screen. The right column sizes to its content, so the page-size picker and counts wrap
   below the buttons as a whole rather than squeezing beside them, and the row gap spaces them when they do. Previous and
   next share a light divider on both sides of the join, so it stays visible whichever button is raised on hover or
   focus. */
.pager-bar {
    --bs-gutter-x: 0;
    --ct-gutter-x: 0;
    background: var(--surface-2, #FAFCFD);
    border: 1px solid var(--line-200, #E4EAEF);
    border-radius: var(--r-lg, 16px);
    padding: 9px 14px;
    margin-bottom: 14px;
    row-gap: 8px;
}

.pager-bar > .col {
    flex: 1 0 auto;
    width: auto;
}

.pager-bar .btn-primary.dropdown-toggle:not(.dropdown-toggle-split) {
    --bs-btn-bg: var(--surface, #FFFFFF);
    --bs-btn-border-color: var(--line-300, #D7DEE4);
    --bs-btn-hover-bg: var(--surface, #FFFFFF);
    --bs-btn-hover-border-color: var(--brand, #1694C8);
    --bs-btn-active-bg: var(--surface, #FFFFFF);
    --bs-btn-active-border-color: var(--brand, #1694C8);
    --ct-btn-bg: var(--surface, #FFFFFF);
    --ct-btn-border-color: var(--line-300, #D7DEE4);
    --ct-btn-hover-bg: var(--surface, #FFFFFF);
    --ct-btn-hover-border-color: var(--brand, #1694C8);
    --ct-btn-active-bg: var(--surface, #FFFFFF);
    --ct-btn-active-border-color: var(--brand, #1694C8);
    box-shadow: var(--shadow-sm, 0 1px 2px rgba(13, 30, 40, .06), 0 1px 1px rgba(13, 30, 40, .04));
}

.pager-bar .pager-goto > .dropdown-toggle {
    min-width: 150px;
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}

@media (max-width: 575.98px) {
    .pager-bar .pager-goto > .dropdown-toggle {
        min-width: 0;
    }
}

.pager-bar .pager-goto > .pager-previous {
    border-right-color: rgba(255, 255, 255, .45);
}

.pager-bar .pager-goto > .pager-next {
    border-left-color: rgba(255, 255, 255, .45);
}

.pager-bar .pager-size .dropdown-toggle {
    min-width: 80px;
}

.pager-bar .dropdown-item {
    cursor: pointer;
}

/* Searchable pickers: SearchSelectComponent and MultiSearchSelectComponent (SelectListComponent also uses
   .org-search-logo). The class names are the ones HelixPortal's own user picker and hand-rolled drawers already use, so
   those keep their look off this sheet. The panel is pinned to both sides of the root, so the list is always exactly as
   wide as its toggle, with no script. */
.user-search {
    position: relative;
}

.user-search-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1040;
}

.user-search-panel {
    position: absolute;
    z-index: 1050;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    max-height: 380px;
    overflow-y: auto;
    background: var(--surface, #FFFFFF);
    border: 1px solid var(--line-300, #D7DEE4);
    border-radius: var(--r-md, 12px);
    box-shadow: var(--shadow-lg, 0 24px 60px rgba(13, 30, 40, .16), 0 8px 20px rgba(13, 30, 40, .08));
    padding: 8px;
}

.user-search-result {
    display: flex;
    align-items: center;
    gap: 11px;
    width: 100%;
    text-align: left;
    border: 0;
    background: transparent;
    border-radius: var(--r-sm, 8px);
    padding: 8px 10px;
}

.user-search-result:hover {
    background: var(--brand-50, #ECF7FC);
}

.user-search-result.is-selected {
    background: var(--brand-50, #ECF7FC);
    color: var(--brand-700, #0C6488);
}

/* Lets a truncating name shrink inside the flex toggle and rows, so it ellipsises instead of overflowing. */
.user-search-text {
    min-width: 0;
}

/* MultiSearchSelectComponent's tick, in the brand colour once chosen. */
.user-search-tick {
    flex: 0 0 auto;
    font-size: 18px;
    line-height: 1;
    color: var(--ink-400, #8595A0);
}

.user-search-result.is-selected .user-search-tick {
    color: var(--brand-600, #0E7CAB);
}

/* The logo or icon circle before a picker's text. */
.org-search-logo {
    width: 24px;
    height: 24px;
    flex: 0 0 auto;
    display: inline-grid;
    place-items: center;
    background-color: var(--brand-50, #ECF7FC);
    background-position: center;
    background-repeat: no-repeat;
    background-size: contain;
    color: var(--brand-600, #0E7CAB);
}

/* Select list: SelectListComponent. The search box (and the select-all row above it) sticks to the top of the
   scrolling drawer or panel, above Bootstrap's .list-group-item.active (z-index 2). The logo spans reuse
   .org-search-logo from the picker block, which is not repeated here. */
.clinic-list-search {
    position: sticky;
    top: 0;
    z-index: 3;
    background: var(--surface, #FFFFFF);
    padding: 4px 4px 8px;
}

/* The selected / total counter follows the unselect-all button inside the input group, so Bootstrap squares the
   button's right corners; round them again. */
.clinic-list-search .input-group > .btn:has(+ .input-control) {
    border-top-right-radius: var(--bs-btn-border-radius, var(--ct-btn-border-radius, 9px)) !important;
    border-bottom-right-radius: var(--bs-btn-border-radius, var(--ct-btn-border-radius, 9px)) !important;
}

.select-list-row {
    cursor: pointer;
}

.select-list-text {
    min-width: 0;
}

.select-list-count {
    font-size: 12px;
    color: var(--ink-400, #8595A0);
}

/* Password box: the eye that shows or hides the password, PasswordTextBoxComponent. It does nothing while the box is
   disabled. */
.password-toggle {
    cursor: pointer;
}

.input-group:has(> input:disabled) > .password-toggle {
    cursor: not-allowed;
}
