/*
 * Global utility classes that sit outside Bootstrap and the bundled theme.
 */
:root {
    --font-family-sans-serif: "Inter", "Avenir Next", "Segoe UI", "Helvetica Neue", Arial, sans-serif;
}

/*
 * Embed Inter locally so the app does not depend on a third-party font request.
 */
@font-face {
    font-family: "Inter";
    src: url("../fonts/inter/InterVariable.woff2") format("woff2");
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
}

@font-face {
    font-family: "Inter";
    src: url("../fonts/inter/InterVariable-Italic.woff2") format("woff2");
    font-style: italic;
    font-weight: 100 900;
    font-display: swap;
}

body {
    font-family: var(--font-family-sans-serif);
    /* font-size: 16px !important; */
    font-weight: 400;
}

[x-cloak] {
    display: none !important;
}

.font-size-base {
    font-size: 15px !important;
}

.font-weight-lighter {
    font-weight: 300 !important;
}

/*
 * Allow flex/grid children to shrink so nearby fixed-width content can stay visible.
 */
.min-width-0 {
    min-width: 0 !important;
}

/*
 * Let dropdown panels size to their content without borrowing Bootstrap grid
 * classes, so rows/columns can still be used inside the panel body.
 */
.dropdown-menu-natural {
    /* width: max-content; */
    min-width: 18rem;
    max-width: calc(100vw - 2rem);
}

.dropdown-menu-natural-lg {
    min-width: 36rem;
}

/* Informational tooltips must not steal hover from the control beneath their arrow. */
.tooltip { pointer-events: none; }

.tooltip-inner {
    font-size: 14px;
    line-height: 1.4;
    padding: .5rem .75rem;
}

.input-group > .btn {
  height: calc(1.5em + 1rem + 2px);
}

/* Keep the white button outline when Dashkit applies its disabled colour override. */
.btn-white:disabled,
.btn-white.disabled,
fieldset:disabled .btn-white {
    border-color: #e3ebf6;
}

/* State accents colour the left edge only; Bootstrap's border-[state] otherwise colours row dividers too.
 * Apply this to both cells and rows used by Adaptive Updates, Security Activity and suspended mailboxes.
 */
.table .border-left-2 {
    border-top-color: var(--light) !important;
    border-bottom-color: var(--light) !important;
}

/* Dashkit list checkboxes, backported for the bundled Bootstrap 4 theme. */
.form-check-input.list-checkbox {
    appearance: none;
    -webkit-appearance: none;
    position: static;
    width: 1rem;
    height: 1rem;
    margin: 0;
    vertical-align: middle;
    border: 1px solid #d2ddec;
    border-radius: .25rem;
    background: #fff no-repeat center / contain;
    cursor: pointer;
}

.form-check-input.list-checkbox:checked {
    background-color: var(--primary);
    border-color: var(--primary);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m4 8 3 3 5-6'/%3E%3C/svg%3E");
}

.form-check-input.list-checkbox:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

.form-check-input.list-checkbox:disabled {
    opacity: .65;
    cursor: default;
}

/*
 * Hide native number steppers when a field already has explicit +/- controls.
 */
.input-no-spinner {
    appearance: textfield;
    -moz-appearance: textfield;
}

.input-no-spinner::-webkit-inner-spin-button,
.input-no-spinner::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

/*
 * Bootstrap 5-style xxl grid helpers.
 * The bundled Bootstrap build does not include xxl classes.
 */
@media (min-width: 1900px) {
    .col-xxl-1 {
        flex: 0 0 8.333333%;
        max-width: 8.333333%;
    }

    .col-xxl-2 {
        flex: 0 0 16.666667%;
        max-width: 16.666667%;
    }

    .col-xxl-3 {
        flex: 0 0 25%;
        max-width: 25%;
    }

    .col-xxl-4 {
        flex: 0 0 33.333333%;
        max-width: 33.333333%;
    }

    .col-xxl-5 {
        flex: 0 0 41.666667%;
        max-width: 41.666667%;
    }

    .col-xxl-6 {
        flex: 0 0 50%;
        max-width: 50%;
    }

    .col-xxl-7 {
        flex: 0 0 58.333333%;
        max-width: 58.333333%;
    }

    .col-xxl-8 {
        flex: 0 0 66.666667%;
        max-width: 66.666667%;
    }

    .col-xxl-9 {
        flex: 0 0 75%;
        max-width: 75%;
    }

    .col-xxl-10 {
        flex: 0 0 83.333333%;
        max-width: 83.333333%;
    }

    .col-xxl-11 {
        flex: 0 0 91.666667%;
        max-width: 91.666667%;
    }

    .col-xxl-12 {
        flex: 0 0 100%;
        max-width: 100%;
    }
}

/*
 * Quill is one of the theme components that declares Cerebri Sans directly.
 */
.ql-container {
    font-family: var(--font-family-sans-serif);
}

/*
 * Keep small helper text readable across the bundled theme.
 */
.small,
small {
    font-size: 14px !important;
    font-weight: 300;
}

/*
 * Keep muted helper text readable while preserving existing markup.
 */
.text-muted {
    color: var(--secondary, #6e84a3) !important;
}

/*
 * Soft background utilities matching the bundled theme's badge-soft colours.
 */
.bg-soft-primary {
    background-color: #d5e5fa !important;
}

.bg-soft-secondary {
    background-color: #e2e6ed !important;
}

.bg-soft-success {
    background-color: #ccf7e5 !important;
}

.bg-soft-info {
    background-color: #d7eff6 !important;
}

.bg-soft-warning {
    background-color: #fdf3d9 !important;
}

.bg-soft-danger {
    background-color: #fad7dd !important;
}

.bg-soft-light {
    background-color: #fbfcfe !important;
}

.bg-soft-dark {
    background-color: #d0d4d9 !important;
}

/* Light hover feedback preserves the existing label and link colours. */
.hover-bg-light:hover,
.hover-bg-light:focus-visible {
    background-color: var(--light) !important;
}

/* Invert labels, counts and links together on hover or keyboard focus. */
.hover-bg-dark:hover,
.hover-bg-dark:focus-visible {
    background-color: var(--dark) !important;
}

.hover-bg-dark:hover,
.hover-bg-dark:hover *,
.hover-bg-dark:focus-visible,
.hover-bg-dark:focus-visible * {
    color: var(--light) !important;
}

.bg-soft-white {
    background-color: #fff !important;
}

/*
 * Soft button utilities matching the soft background/badge palette.
 */
.btn-soft-primary {
    color: #2c7be5;
    background-color: #d5e5fa;
    border-color: #d5e5fa;
}

.btn-soft-primary:hover,
.btn-soft-primary:focus {
    color: #2c7be5;
    background-color: #bdd6f6;
    border-color: #bdd6f6;
}

.btn-soft-secondary {
    color: #6e84a3;
    background-color: #e2e6ed;
    border-color: #e2e6ed;
}

.btn-soft-secondary:hover,
.btn-soft-secondary:focus {
    color: #12263f;
    background-color: #d2ddec;
    border-color: #d2ddec;
}

.btn-soft-success {
    color: #00a35f;
    background-color: #ccf7e5;
    border-color: #ccf7e5;
}

.btn-soft-success:hover,
.btn-soft-success:focus {
    color: #00a35f;
    background-color: #b3f2d8;
    border-color: #b3f2d8;
}

.btn-soft-info {
    color: #39afd1;
    background-color: #d7eff6;
    border-color: #d7eff6;
}

.btn-soft-info:hover,
.btn-soft-info:focus {
    color: #39afd1;
    background-color: #c0e6f1;
    border-color: #c0e6f1;
}

.btn-soft-warning {
    color: #f6c343;
    background-color: #fdf3d9;
    border-color: #fdf3d9;
}

.btn-soft-warning:hover,
.btn-soft-warning:focus {
    color: #12263f;
    background-color: #fbeabf;
    border-color: #fbeabf;
}

.btn-soft-danger {
    color: #e63757;
    background-color: #fad7dd;
    border-color: #fad7dd;
}

.btn-soft-danger:hover,
.btn-soft-danger:focus {
    color: #e63757;
    background-color: #f7c1cb;
    border-color: #f7c1cb;
}

.btn-soft-light {
    color: #6e84a3;
    background-color: #fbfcfe;
    border-color: #fbfcfe;
}

.btn-soft-light:hover,
.btn-soft-light:focus {
    color: #12263f;
    background-color: #edf2f9;
    border-color: #edf2f9;
}

.btn-soft-dark {
    color: #12263f;
    background-color: #d0d4d9;
    border-color: #d0d4d9;
}

.btn-soft-dark:hover,
.btn-soft-dark:focus {
    color: #12263f;
    background-color: #bec4cb;
    border-color: #bec4cb;
}

.btn-soft-white {
    color: #12263f;
    background-color: #fff;
    border-color: #fff;
}

.btn-soft-white:hover,
.btn-soft-white:focus {
    color: #12263f;
    background-color: #f9fbfd;
    border-color: #f9fbfd;
}

.btn-soft-primary.disabled,
.btn-soft-primary:disabled,
.btn-soft-secondary.disabled,
.btn-soft-secondary:disabled,
.btn-soft-success.disabled,
.btn-soft-success:disabled,
.btn-soft-info.disabled,
.btn-soft-info:disabled,
.btn-soft-warning.disabled,
.btn-soft-warning:disabled,
.btn-soft-danger.disabled,
.btn-soft-danger:disabled,
.btn-soft-light.disabled,
.btn-soft-light:disabled,
.btn-soft-dark.disabled,
.btn-soft-dark:disabled,
.btn-soft-white.disabled,
.btn-soft-white:disabled {
    color: #6e84a3;
    pointer-events: none;
    opacity: .65;
}

/*
 * Semi-collapsed content helper.
 *
 * Use this on informational sections where the first part should stay visible
 * and the lower content should fade out until the section is expanded.
 */
.collapse-fade {
    --collapse-fade-height: 12rem;
    --collapse-fade-expanded-height: 100rem;
    --collapse-fade-bg: #fff;
    --collapse-fade-mask-height: 4rem;

    max-height: var(--collapse-fade-height);
    overflow: hidden;
    position: relative;
    transition: max-height .2s ease-in-out;
}

/*
 * Bootstrap's .collapse class usually hides content completely; this helper
 * keeps the collapsed state partially visible while still using .show.
 */
.collapse-fade.collapse:not(.show) {
    display: block;
}

.collapse-fade.collapsing {
    height: auto !important;
    max-height: var(--collapse-fade-expanded-height);
}

/*
 * Keep the fade as a pseudo-element so the content can remain normal markup.
 * Override --collapse-fade-bg when the section sits on a tinted background.
 */
.collapse-fade::after {
    background: linear-gradient(to bottom, rgba(255, 255, 255, 0), var(--collapse-fade-bg));
    bottom: 0;
    content: "";
    height: var(--collapse-fade-mask-height);
    left: 0;
    pointer-events: none;
    position: absolute;
    right: 0;
    transition: opacity .2s ease-in-out;
}

/*
 * Bootstrap-style expanded state; this works well with a small click handler
 * that toggles .show on the same element.
 */
.collapse-fade.show {
    max-height: var(--collapse-fade-expanded-height);
}

.collapse-fade.show::after {
    opacity: 0;
}

/*
 * Preset collapsed heights. These are viewport-based approximations because
 * CSS cannot calculate a percentage of an element's natural content height.
 */
.collapse-fade-xs {
    --collapse-fade-height: 6rem;
}

.collapse-fade-sm {
    --collapse-fade-height: 10rem;
}

.collapse-fade-md {
    --collapse-fade-height: 12rem;
}

.collapse-fade-lg {
    --collapse-fade-height: 16rem;
}

/* Compact variant of the theme switch, retaining its focus and disabled states. */
.custom-switch.custom-switch-sm {
    padding-left: 2.5rem;
    min-height: 1.125rem;
}

.custom-switch-sm .custom-control-label::before {
    left: -2.5rem;
    width: 2rem;
    height: 1.125rem;
    border-radius: .5625rem;
}

.custom-switch-sm .custom-control-label::after {
    top: .125rem;
    left: -2.375rem;
    width: .875rem;
    height: .875rem;
    border-radius: 50%;
}

.custom-switch-sm .custom-control-input:checked ~ .custom-control-label::after {
    transform: translateX(.875rem);
}

/* Centre the switch on a small visible label's 21px line rather than its top edge. */
.custom-switch-sm .custom-control-label.small::before {
    top: .09375rem;
}

.custom-switch-sm .custom-control-label.small::after {
    top: .21875rem;
}

/* Keep security columns uniform; long request values must shrink within their cells. */
.security-activity-table-wrap {
    container-type: inline-size;
    container-name: security-activity;
    width: 100%;
    min-width: 0;
}

.security-activity-table {
    table-layout: fixed;
    width: 100%;
}

.security-activity-table .activity-time { width: 11rem; }
.security-activity-table .activity-protection { width: 15rem; }
.security-activity-table .activity-outcome { width: 10rem; }
.security-activity-table .activity-expand { width: 4rem; }
/* Reserve the remaining space explicitly, including the theme's outer cell padding. */
.security-activity-table .activity-request { width: calc(100% - 40rem); }

.security-activity-table > thead > tr > th,
.security-activity-table > tbody > tr > td {
    padding-left: 1rem;
    padding-right: 1rem;
}

.security-activity-table .activity-request-meta > span { min-width: 0; }
.security-activity-table .activity-request-meta { min-width: 0; overflow: hidden; }
.security-activity-table .security-activity-row > td:nth-child(3) { overflow: hidden; }
.security-activity-table .activity-uri { flex: 0 1 auto; }
.security-activity-table .activity-ip { flex-shrink: 0; }
.security-activity-table .activity-agent { flex: 0 1 auto; }
.security-activity-table .security-activity-details { overflow-wrap: anywhere; }
.security-activity-table .security-activity-details .text-break { word-break: normal !important; overflow-wrap: anywhere; }
/* Match the drawer preview while letting long evidence wrap on smaller screens. */
.activity-summary-icon { width: 3.5rem; height: 3.5rem; font-size: 1.5rem; position: relative; isolation: isolate; }
/* Lighten the existing soft colour without muting the status icon itself. */
.activity-summary-icon::before { content: ''; position: absolute; inset: 0; background: rgba(255, 255, 255, .55); border-radius: inherit; z-index: -1; }
.activity-summary-icon .fe { display: block; line-height: 1; }
.activity-check-copy { min-width: 0; }
.activity-request-details > div { min-width: 0; }
/* Separate the final context fields when they stack on smaller screens. */
@media (max-width: 767.98px) {
    .activity-detail-received { border-bottom: 1px solid var(--light); }
}
@media (min-width: 768px) {
    .activity-detail-half, .activity-detail-quarter { border-right: 1px solid var(--light); }
}

/* Reflow narrow cards instead of requiring horizontal scrolling or hiding outcomes. */
@container security-activity (max-width: 850px) {
    .security-activity-table,
    .security-activity-table tbody,
    .security-activity-table .security-activity-details,
    .security-activity-table .security-activity-details > td {
        display: block;
        width: 100%;
    }

    .security-activity-table colgroup { display: none; }
    .security-activity-table thead {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
    }

    .security-activity-table .security-activity-row {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        padding: .75rem 0;
        border-top: 1px solid var(--light);
    }

    .security-activity-table .security-activity-row > td { min-width: 0; border: 0; padding: .25rem 1rem; }
    .security-activity-table .security-activity-row > td:nth-child(1) { grid-column: 1; grid-row: 1; }
    .security-activity-table .security-activity-row > td:nth-child(2) { grid-column: 1; grid-row: 2; white-space: normal !important; }
    .security-activity-table .security-activity-row > td:nth-child(3) { grid-column: 1 / -1; grid-row: 3; }
    .security-activity-table .security-activity-row > td:nth-child(4) { grid-column: 2; grid-row: 1; text-align: right; }
    .security-activity-table .security-activity-row > td:nth-child(5) { grid-column: 2; grid-row: 2; text-align: right; }
    .security-activity-table .activity-ip { flex-shrink: 1; overflow: hidden; text-overflow: ellipsis; }
}

/* Plugin management follows the bordered sections and soft status colours of Security and Email. */
/* Overview card headings provide the first divider; avoid doubling it with the first list row. */
#wp-overview .list-group-item:first-child { border-top: 0; }
/* Fit the chart inside the overview's natural height; mobile cards retain their own content height. */
@media (min-width: 992px) {
    .wp-plugin-overview-card, .wp-advisories-card { height: var(--wordpress-overview-height, auto); }
    .wp-plugin-overview-chart { flex: 1; min-height: 0; }
    .wp-plugin-overview-chart .chart { height: 100%; }
    .wp-advisories-viewport { flex: 1; min-height: 0; }
}
.wp-plugin-manager { min-width: 0; }
.wp-plugin-manager, .wp-core-drawer { scroll-margin-top: 1.5rem; }
.wp-plugin-entry, .wp-plugin-columns, .wp-plugin-stats a { transition: background-color .15s ease; }
.wp-plugin-heading { gap: .35rem; }
.wp-plugin-heading h3 { margin-right: .25rem; }
.wp-plugin-columns { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 1.5rem; padding-top: 1.1rem; padding-bottom: 1.1rem; }
.wp-plugin-columns > * { min-width: 0; overflow-wrap: anywhere; }
.wp-plugin-entry + .wp-plugin-entry { border-top: 1px solid var(--light); }
/* The list clips rows to its rounded corners; let an open row menu (Adaptive Updates) show past it. */
.wp-plugin-list:has(.dropdown-menu.show) { overflow: visible !important; }
.wp-plugin-identity h3 { font-size: 1rem; }
.wp-plugin-title { font: inherit; }
.wp-plugin-clickable > .wp-plugin-columns { cursor: pointer; }
.wp-plugin-clickable > .wp-plugin-columns:hover { background-color: var(--light); }
.wp-plugin-meta { gap: .5rem .75rem; }
/* Keep password fields equal without stretching, and preserve copy-button width in both states. */
.wp-password-value { flex: 0 0 auto; max-width: 100%; }
.wp-password-copy-label { display: inline-grid; }
.wp-password-copy-label > span { grid-area: 1 / 1; }
/* Joined controls share a single border, with no gaps or Bootstrap's negative overlap. */
/* Alpine's template precedes the first filter button; reset its negative margin too so its border isn't clipped. */
.wp-plugin-actions > .btn + .btn, .btn-group.wp-plugin-filters > .btn { margin-left: 0; }
.wp-plugin-filter-scroll { max-width: 100%; overflow-x: auto; }
.wp-plugin-filters { white-space: nowrap; }
.wp-plugin-toolbar, .wp-plugin-update, .wp-plugin-pagination, .wp-plugin-finding-title { gap: 1rem; }
.wp-plugin-finding-title h4 { flex: 1 1 16rem; }
.wp-plugin-sources { gap: .75rem 1.5rem; overflow-wrap: anywhere; }
.wp-plugin-page-controls { gap: .75rem; }
.wp-plugin-drawer { overflow-wrap: anywhere; }
/* Drawer text fills the table without contributing to its automatic column widths. */
.wp-administrator-drawer { contain: inline-size; overflow-wrap: anywhere; }
/* Successful deletion briefly fades the whole account while preserving its space in the table. */
.wp-administrator-row { transition: opacity .2s ease; }
.wp-administrator-removing { opacity: 0; pointer-events: none; }
/* Reserve space for account actions so replacing the cog cannot resize the table. */
.wp-administrator-actions { display: inline-grid; width: 12rem; vertical-align: middle; }
.wp-administrator-actions > * { grid-area: 1 / 1; justify-self: end; }
/* Hover belongs to the button, including when the pointer crosses its icon. */
.wp-administrator-actions button > svg, .wp-administrator-actions button > .fe { pointer-events: none; }
.wp-plugin-drawer .wp-plugin-finding:last-of-type { margin-bottom: 0 !important; }
/* Reflow all row content on phones instead of forcing a horizontally scrolling table. */
@media (max-width: 575.98px) {
    .wp-plugin-columns { gap: 1rem; }
    .wp-plugin-pagination, .wp-plugin-page-controls { justify-content: center !important; width: 100%; }
}

/* Keep formatted technical names inside the same soft-bordered cards on mobile. */
.wp-plugin-drawer code, .wp-core-drawer code { white-space: normal; overflow-wrap: anywhere; }
/* Clamp visually so inline code remains intact and the preview follows the available width. */
.wp-vulnerability-description-clamped { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
.wp-core-drawer > summary { cursor: pointer; }
.wp-core-drawer > summary { list-style: none; }
.wp-core-drawer > summary::-webkit-details-marker { display: none; }
@media (prefers-reduced-motion: reduce) {
    .wp-plugin-manager *, .wp-core-drawer *, .wp-plugin-stats a { transition: none !important; }
}
.wp-core-drawer .wp-plugin-finding:last-child { margin-bottom: 0 !important; }

/* Use the brand colour by default; text-* utility classes override currentColor for the shimmer too. */
.thinking-text { color: var(--thinking-colour, var(--primary)); }
@supports ((background-clip: text) or (-webkit-background-clip: text)) {
    .thinking-text {
        background-image: linear-gradient(90deg, currentColor 35%, var(--gray-500, #95aac9) 50%, currentColor 65%);
        background-size: 300% 100%;
        background-repeat: no-repeat;
        background-clip: text;
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        animation: thinking-text-shimmer 2.5s linear infinite;
    }
}
@keyframes thinking-text-shimmer {
    /* Keep the highlight outside the text at both ends so the loop resets on the same solid colour. */
    from { background-position: 100% center; }
    to { background-position: 0% center; }
}
/* Keep the status readable when motion or custom colours are unwanted. */
@media (prefers-reduced-motion: reduce), (forced-colors: active) {
    .thinking-text { animation: none; background: none; -webkit-text-fill-color: currentColor; }
}

/* Stack the desktop sidebar as a column so the panel version sits at its foot. */
@media (min-width: 768px) {
    #sidebar { display: flex; flex-direction: column; align-items: stretch; }
    #sidebar > * { flex-shrink: 0; }
    #sidebar > .navbar-collapse { flex: 0 0 auto; }
    #sidebar > .sidebar-version { margin-top: auto; }
    /* The square Scout mark reads small at the theme's 3rem cap; brand logos keep it. */
    #sidebar .navbar-brand-img-scout { width: 64px; height: 64px; max-height: none; }
}

/*
 * Example text in an empty CodeJar editor (data-placeholder, newlines as &#10;).
 */
.code-editor[data-placeholder]:empty::before {
    content: attr(data-placeholder);
    color: rgba(255, 255, 255, 0.35);
    white-space: pre;
    pointer-events: none;
}

/*
 * Inline code on a light chip instead of the theme's blue text (paths, IDs, query strings).
 */
code.code-light {
    background-color: var(--light, #edf2f9);
    color: var(--dark, #12263f);
    padding: 0.125rem 0.375rem;
    border-radius: 0.25rem;
}

/*
 * Icon badge: a 30px tile with a 16px icon, used beside names in the Sites list. Pair it
 * with badge-soft-* text-dark (or bg-dark text-white, bg-white border text-secondary).
 */
.badge.badge-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    padding: 0;
    font-size: 1rem;
    line-height: 1;
    vertical-align: middle;
    flex-shrink: 0;
}
.badge.badge-icon svg { width: 16px; height: 16px; }
/* Small icon badge: a 20px tile with a 12px icon, for inline status beside small text. */
.badge.badge-icon.badge-icon-sm {
    width: 20px;
    height: 20px;
    font-size: .75rem;
}
.badge.badge-icon.badge-icon-sm svg { width: 12px; height: 12px; }
/* Adaptive Updates is running: the chevrons climb. */
@media (prefers-reduced-motion: no-preference) {
    .badge-icon-working .fe { animation: badge-icon-climb 1.5s ease-in-out infinite; }
}
@keyframes badge-icon-climb {
    0% { transform: translateY(2px); opacity: .45; }
    50% { transform: translateY(-1px); opacity: 1; }
    100% { transform: translateY(-2px); opacity: .45; }
}

/*
 * Sites list filter chips: rounded btn-sm buttons, btn-dark when pressed, split into a
 * label and a count segment with equal padding. An end-of-life PHP version keeps a
 * warning border in both states.
 */
.filter-chip { display: inline-flex; align-items: stretch; padding: 0; white-space: nowrap; overflow: hidden; }
.filter-chip .filter-label,
.filter-chip .filter-count { display: inline-flex; align-items: center; padding: .125rem .625rem; }
.filter-chip .filter-count { border-left: 1px solid #e3ebf6; color: #6e84a3; font-variant-numeric: tabular-nums; }
.filter-chip.btn-dark .filter-count { border-left-color: rgba(255, 255, 255, .25); color: rgba(255, 255, 255, .75); }
.filter-chip.border-warning .filter-count { border-left-color: #f6c343; }
/* Dashkit stretches every card-header child; the Filters and Export buttons size to their labels. */
.card-header > .site-filter-toggle, .card-header > .site-export { flex: 0 0 auto; }
