/* Card header gradient — used on dashboard / schedules / archive detail.
   In DARK mode this is the signature deep-navy hero header; in LIGHT mode
   it intentionally collapses to the same neutral surface as the standard
   .card-header so the page palette stays cohesive — no jarring dark
   block sitting in an otherwise light layout. */
.card-head-gradient {
    background-color: #f1f3f5;
    color: var(--bs-body-color);
    border-bottom: 1px solid rgba(0, 0, 0, 0.08);
}
.card-head-gradient i { color: var(--bs-primary); }
[data-bs-theme="dark"] .card-head-gradient {
    /* Flat — same #202b3f used by .card-header in dark mode so every
       header on every page is visually identical. */
    background: #202b3f;
    color: #fff;
    border-bottom: 1px solid rgb(24 24 25);
}
[data-bs-theme="dark"] .card-head-gradient .text-muted { color: rgba(255, 255, 255, 0.7) !important; }
[data-bs-theme="dark"] .card-head-gradient i { color: #9ec5fe; }

/* The previous .metric-tile / .v2 .metric-tile rule set was retired in
   2.53.x — all stat blocks now use the icon-on-left card pattern (see
   .metric-card-* and .stat-icon below). */

/* Global dropdown + tooltip escape fix. Issue #161 and several predecessors:
   Bootstrap cards and other containers use overflow:hidden (for rounded
   corners), which clips dropdown menus that pop out of them. The
   companion JS in layouts/app.php sets data-bs-strategy="fixed" on every
   dropdown so Popper uses position:fixed and the menu renders in the
   top-level stacking context. This rule guarantees the menu sits above
   everything else once it's shown. */
.dropdown-menu.show,
.tooltip.show,
.popover.show {
    z-index: 2147483647 !important;
}

/* Font & nav color variables */
:root {
    --bs-body-font-family: 'Inter', system-ui, -apple-system, sans-serif;
    --bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.375);
    --bbs-nav-bg: #2c3e50;
    --bbs-nav-color: rgba(255, 255, 255, 0.7);
    --bbs-nav-hover-bg: rgba(255, 255, 255, 0.1);
    --bbs-nav-hover-color: #fff;
    --bbs-nav-active-bg: #e67e22;
    --bbs-nav-active-color: #fff;
    --bbs-topbar-bg: #2c3e50;
}

/* Muted Bootstrap color overrides — buttons and badges only */
.btn-primary {
    --bs-btn-bg: #4a6fa5;
    --bs-btn-border-color: #4a6fa5;
    --bs-btn-hover-bg: #3d5f8f;
    --bs-btn-hover-border-color: #3d5f8f;
    --bs-btn-active-bg: #345280;
    --bs-btn-active-border-color: #345280;
    --bs-btn-disabled-bg: #4a6fa5;
    --bs-btn-disabled-border-color: #4a6fa5;
}

.btn-outline-primary {
    --bs-btn-color: #4a6fa5;
    --bs-btn-border-color: #4a6fa5;
    --bs-btn-hover-bg: #4a6fa5;
    --bs-btn-hover-border-color: #4a6fa5;
    --bs-btn-active-bg: #3d5f8f;
    --bs-btn-active-border-color: #3d5f8f;
}

.btn-success {
    --bs-btn-bg: #4a9e6e;
    --bs-btn-border-color: #4a9e6e;
    --bs-btn-hover-bg: #3d8a5e;
    --bs-btn-hover-border-color: #3d8a5e;
    --bs-btn-active-bg: #347a52;
    --bs-btn-active-border-color: #347a52;
    --bs-btn-disabled-bg: #4a9e6e;
    --bs-btn-disabled-border-color: #4a9e6e;
}

.btn-outline-success {
    --bs-btn-color: #4a9e6e;
    --bs-btn-border-color: #4a9e6e;
    --bs-btn-hover-bg: #4a9e6e;
    --bs-btn-hover-border-color: #4a9e6e;
    --bs-btn-active-bg: #3d8a5e;
    --bs-btn-active-border-color: #3d8a5e;
}

.btn-danger {
    --bs-btn-bg: #c25b5b;
    --bs-btn-border-color: #c25b5b;
    --bs-btn-hover-bg: #aa4e4e;
    --bs-btn-hover-border-color: #aa4e4e;
    --bs-btn-active-bg: #964444;
    --bs-btn-active-border-color: #964444;
    --bs-btn-disabled-bg: #c25b5b;
    --bs-btn-disabled-border-color: #c25b5b;
}

.btn-outline-danger {
    --bs-btn-color: #c25b5b;
    --bs-btn-border-color: #c25b5b;
    --bs-btn-hover-bg: #c25b5b;
    --bs-btn-hover-border-color: #c25b5b;
    --bs-btn-active-bg: #aa4e4e;
    --bs-btn-active-border-color: #aa4e4e;
}

.btn-warning {
    --bs-btn-bg: #d4a843;
    --bs-btn-border-color: #d4a843;
    --bs-btn-hover-bg: #be9638;
    --bs-btn-hover-border-color: #be9638;
    --bs-btn-active-bg: #a8852f;
    --bs-btn-active-border-color: #a8852f;
    --bs-btn-color: #fff;
    --bs-btn-hover-color: #fff;
    --bs-btn-active-color: #fff;
}

.btn-outline-warning {
    --bs-btn-color: #d4a843;
    --bs-btn-border-color: #d4a843;
    --bs-btn-hover-bg: #d4a843;
    --bs-btn-hover-border-color: #d4a843;
    --bs-btn-hover-color: #fff;
    --bs-btn-active-bg: #be9638;
    --bs-btn-active-border-color: #be9638;
}

.btn-info {
    --bs-btn-bg: #4a9fb5;
    --bs-btn-border-color: #4a9fb5;
    --bs-btn-hover-bg: #3d8da1;
    --bs-btn-hover-border-color: #3d8da1;
    --bs-btn-active-bg: #347d8f;
    --bs-btn-active-border-color: #347d8f;
    --bs-btn-color: #fff;
    --bs-btn-hover-color: #fff;
    --bs-btn-active-color: #fff;
}

/* Confirm modal backdrop blur */
.modal-backdrop.show {
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    background-color: rgba(0, 0, 0, 0.4);
}

/* Prevent horizontal scroll */
html, body {
    overflow-x: hidden;
    max-width: 100vw;
}

/* Placeholder text - lighter so it's clearly not entered data */
::placeholder {
    color: rgba(0, 0, 0, 0.4) !important;
    opacity: 1 !important;
}
::-webkit-input-placeholder {
    color: rgba(0, 0, 0, 0.4) !important;
}
::-moz-placeholder {
    color: rgba(0, 0, 0, 0.4) !important;
}
:-ms-input-placeholder {
    color: rgba(0, 0, 0, 0.4) !important;
}

[data-bs-theme="dark"] ::placeholder {
    color: rgba(255, 255, 255, 0.4) !important;
}
[data-bs-theme="dark"] ::-webkit-input-placeholder {
    color: rgba(255, 255, 255, 0.4) !important;
}
[data-bs-theme="dark"] ::-moz-placeholder {
    color: rgba(255, 255, 255, 0.4) !important;
}
[data-bs-theme="dark"] :-ms-input-placeholder {
    color: rgba(255, 255, 255, 0.4) !important;
}

/* Sidebar */
.sidebar {
    width: 192px;
    height: calc(100vh - 64px);
    background-color: var(--bbs-nav-bg);
    position: fixed;
    top: 64px;
    left: 0;
    overflow-y: auto;
    z-index: 1020;
}

/* Version pill at the bottom of the sidebar. The sidebar background is
   always dark navy regardless of theme (--bbs-nav-bg = #2c3e50 light /
   #16191d dark), so the pill uses light-on-dark colors hardcoded. The
   previous Bootstrap text-body-secondary token resolved to a midtone
   gray in light mode, which read as illegible against the dark navy. */
.sidebar-version-pill {
    color: rgba(255, 255, 255, 0.78);
    background-color: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.2);
    font-weight: 500;
    font-size: 0.65rem;
    padding: 3px 9px;
    letter-spacing: 0.02em;
}

.sidebar-link {
    color: var(--bbs-nav-color) !important;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 7px 14px !important;
    margin-bottom: 1px;
    border-radius: 0 !important;
    transition: background-color 0.15s, color 0.15s;
    line-height: 1.2;
    font-size: 0.875rem;
    white-space: nowrap;
}

/* Fixed-width icon column so every label starts on the same vertical line,
   whatever glyph precedes it. */
.sidebar-link > i:first-child {
    font-size: 0.95rem;
    width: 18px;
    text-align: center;
    flex-shrink: 0;
}

.sidebar-link .sidebar-label {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Group headings — quiet, since they are labels rather than destinations. */
.sidebar-section {
    color: rgba(255, 255, 255, 0.38);
    font-size: 0.63rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    padding: 13px 14px 5px;
    margin: 0;
}

/* Settings is a destination-sized row like Users, not a section label — it
   just happens to expand. Width and background reset because it is a <button>
   wearing a link's clothes. */
.sidebar-group-toggle {
    width: 100%;
    background: none;
    border: 0;
    cursor: pointer;
    text-align: left;
}

.sidebar-group-caret {
    margin-left: auto;
    font-size: 0.7rem;
    opacity: 0.6;
    transition: transform 0.15s;
}

.sidebar-group-toggle[aria-expanded="false"] .sidebar-group-caret {
    transform: rotate(-90deg);
}

/* Children hang off a rail so the nesting reads without indentation alone. */
.sidebar-sub {
    list-style: none;
    margin: 0 0 0 27px;
    padding: 0;
    border-left: 1px solid rgba(255, 255, 255, 0.12);
}

.sidebar-sub .sidebar-link {
    padding: 5px 10px 5px 14px !important;
    font-size: 0.8125rem;
    margin-bottom: 0;
    position: relative;
}

/* The short tick joining a child to the rail. */
.sidebar-sub .sidebar-link::before {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    width: 8px;
    border-top: 1px solid rgba(255, 255, 255, 0.12);
}

.sidebar-sub .sidebar-link.active::before {
    border-top-color: var(--bbs-nav-active-color);
}

.sidebar-link:hover {
    color: var(--bbs-nav-hover-color) !important;
    background-color: var(--bbs-nav-hover-bg) !important;
}

.sidebar-link.active {
    color: var(--bbs-nav-active-color) !important;
    background-color: var(--bbs-nav-active-bg) !important;
    box-shadow: inset 3px 0 0 var(--bbs-nav-active-color);
}

.sidebar-sub .sidebar-link.active {
    box-shadow: none;
    background-color: transparent !important;
    font-weight: 600;
}

/* Topbar */
.topbar {
    height: 64px;
    background-color: var(--bbs-topbar-bg);
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 1030;
    padding-left: 0 !important;
    /* Allow the mascot logo to hang below the topbar so the robot's
       hands appear to grab the edge of the page header. */
    overflow: visible;
}

.main-content {
    margin-top: 64px;
    /* Without min-width:0 a flex child default-sizes to its content's
       intrinsic width, so a single long unbreakable string (a borg file
       path, a sidebar progress message) anywhere on the page can blow
       the column past the viewport and trigger horizontal scroll
       (#108, #209, #233). min-width:0 lets the column shrink and lets
       descendants like .text-truncate / overflow-wrap actually do their
       jobs. */
    min-width: 0;
}

.topbar .navbar-text {
    color: #fff !important;
}

.topbar .btn-link,
.topbar .dropdown-toggle {
    color: rgba(255, 255, 255, 0.85) !important;
}

.topbar .btn-link:hover,
.topbar .dropdown-toggle:hover {
    color: #fff !important;
}

.topbar .navbar-brand {
    background-color: transparent;
    height: 64px;
    flex-shrink: 0;
    position: relative;
    overflow: visible;
}

.topbar-logo {
    /* Matches the sidebar so the logo sits over its column rather than
       floating short of it. */
    width: 192px;
    overflow: visible;
}

@media (max-width: 767.98px) {
    /* No sidebar to align to on mobile — keep the old narrow box so the page
       title still has room beside it. */
    .topbar-logo {
        width: 98px;
    }
}

/* Mascot logo. Contained inside the topbar and centred in the logo column,
   which is the width of the sidebar. */
.topbar-mascot {
    /* The artwork is a full lockup — wordmark and mascot — sized for the wider
       sidebar column, so it is contained within the topbar rather than
       overhanging it the way the old mascot-only image deliberately did. A
       wordmark hanging below the bar reads as a mistake, not as character. */
    /* Fills the bar: full 64px height, no padding. At 650x266 that lands it
       about 156px wide in the 192px column, so it is height-bound — the
       remaining slack is horizontal and the lockup stays undistorted. */
    height: 64px;
    width: auto;
    max-width: 192px;
    object-fit: contain;
    pointer-events: none;
}

/* Custom brand logos uploaded via Settings → Branding don't share the
   default mascot's "peek over the edge of the topbar" geometry. They get
   constrained to the navbar height and contained without distortion (#261). */
.topbar-brand-logo {
    /* Matches the slot the branding page now advertises: the full 64px bar
       height and the width of the logo column. The previous 92px cap was
       sized for the old 98px column and left a custom logo marooned in the
       middle of the new one. */
    max-height: 64px;
    max-width: 192px;
    height: auto;
    width: auto;
    object-fit: contain;
    z-index: 1031;
    pointer-events: none;
}

/* Offset main content for fixed sidebar on desktop */
@media (min-width: 768px) {
    .main-content {
        margin-left: 192px;
    }
}

@media (max-width: 767.98px) {
    .main-content {
        /* No bottom bar to clear any more — the drawer overlays instead. */
        min-width: 0;
        overflow-x: hidden;
    }
    /* Logo stays hidden on a phone: the hamburger and the page title need the
       width more than a mark that only repeats what the tab already says. */
    .topbar .navbar-brand,
    .topbar-logo {
        display: none !important;
    }
    .topbar .navbar-text {
        margin-left: 0.25rem !important;
    }
}

/* Stat cards. Hover effect uses box-shadow only — NOT transform.
   A `transform` on a parent creates a new stacking context, which traps
   `position: fixed` dropdown menus inside the card and defeats the
   global dropdown escape fix (issue #161). */
.stat-card {
    transition: box-shadow 0.15s;
}

.stat-card:hover {
    box-shadow: 0 .35rem 1rem rgba(0,0,0,.18) !important;
}

a .stat-card {
    cursor: pointer;
}

/* Tables. Headers AND body cells both use 0.775rem site-wide; cell padding
   tightened from Bootstrap's default 0.5rem to 0.3rem so rows pack denser
   without changing the row layout. Headers are mixed case (not ALL CAPS). */
.table {
    font-size: 0.775rem;
}
.table > :not(caption) > * > * {
    padding: 0.3rem 0.3rem;
}
.table th {
    font-weight: 600;
    font-size: 0.775rem;
    text-transform: none;
    letter-spacing: 0;
    color: #6c757d;
}

/* Dashboard bottom tables */
.dash-table .table {
    font-size: 0.85rem;
}
.dash-table .table th {
    font-size: 0.8rem;
}
.dash-table .table .badge {
    font-size: 0.7rem;
}

/* Badge / pill overrides — site-wide consistency.
   - font-weight 500 (not bold) so badges read as labels, not emphasis.
   - text-transform: capitalize gives every pill Title Case without having
     to touch each rendering site (CSS leaves acronyms and already-cap
     characters alone, so "API" stays "API" and "S3 sync" becomes "S3 Sync").
   Per-page .text-uppercase overrides still win if a view needs the caps
   look (e.g. the dashboard section labels). */
.badge {
    font-weight: 500;
    text-transform: capitalize;
}

/* Login page */
body.bg-body-secondary {
    background-color: #ecf0f1 !important;
}

/* Cards */
.card {
    border-radius: 8px;
    border: 1px solid rgba(0, 0, 0, 0.08) !important;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06), 0 0 12px rgba(0, 0, 0, 0.03);
}

/* Standard card-header — subtle neutral surface in both themes so every
   card on every page has the same visual treatment unless it's an
   explicit "hero" card (.card-head-gradient) or a status alert
   (.bg-warning / .bg-danger). Was previously inconsistent: settings used
   bg-primary bg-opacity-10 (light blue), clients used bg-body
   (transparent), dashboard used card-head-gradient (dark navy). */
.card-header {
    background-color: #f1f3f5;
    color: var(--bs-body-color);
    border-bottom: 1px solid rgba(0, 0, 0, 0.08);
    /* Shrunk from Bootstrap's default 1rem to ~14px (0.875rem) site-wide
       per UX feedback — the previous size felt too heavy for headers
       that mostly carry a title + an icon. Applies to all pages
       (dashboard, schedules, settings, etc.); wins over Bootstrap's
       default without per-card overrides. */
    font-size: 0.875rem;
}

.card.card-no-outline {
    border: none !important;
}

/* Client detail tabs */
.client-tabs {
    gap: 4px;
    flex-wrap: wrap;
}

.client-tabs .nav-link {
    color: var(--bs-secondary-color);
    background-color: transparent;
    border-radius: 6px 6px 0 0 !important;
    padding: 8px 16px;
    font-weight: 500;
    font-size: 0.9rem;
    border: 1px solid transparent;
    border-bottom: none;
    margin-bottom: -1px;
    white-space: nowrap;
    text-align: center;
}

.client-tabs .nav-link:hover {
    background-color: var(--bs-tertiary-bg);
    color: var(--bs-body-color);
    border-color: var(--bs-border-color);
    border-bottom-color: transparent;
}

.client-tabs .nav-link.active {
    background-color: var(--bs-tertiary-bg);
    color: var(--bs-body-color);
    border-color: var(--bs-border-color);
    border-bottom-color: var(--bs-tertiary-bg);
    position: relative;
    z-index: 1;
}

.client-tabs .nav-link.text-danger {
    color: #dc3545 !important;
}

.client-tabs .nav-link.text-danger.active {
    color: #dc3545 !important;
    background-color: var(--bs-tertiary-bg);
}

.client-tab-content {
    border-radius: 0 0 8px 8px;
    overflow: visible;
    background-color: var(--bs-tertiary-bg) !important;
}

/* Mobile: icon-focused tabs */
@media (max-width: 767.98px) {
    .client-tabs {
        gap: 2px;
    }
    .client-tabs .nav-link {
        padding: 6px 6px;
        font-size: 0.8rem;
        min-width: 46px;
    }
    .client-tabs .nav-link i {
        display: block;
        font-size: 1.1rem;
        margin-bottom: 2px;
        margin-right: 0 !important;
    }
    .client-tabs .tab-label {
        display: block;
        font-size: 0.6rem;
    }
    .client-tab-content {
        padding: 0.75rem !important;
    }
}

/* Storage sub-navigation */
.storage-subnav {
    gap: 2px;
    border-bottom: 2px solid var(--bs-border-color);
    padding-bottom: 0;
    flex-wrap: nowrap;
    /* No overflow clipping: setting overflow-x makes the browser compute
       overflow-y to 'auto', and the nav-links' -2px margin-bottom then
       triggers a stray vertical scrollbar on the sub-nav bar (#323). */
}
.storage-subnav .nav-link {
    color: var(--bs-secondary-color);
    font-size: 0.82rem;
    font-weight: 500;
    padding: 6px 14px;
    border-radius: 4px 4px 0 0;
    border: none;
    margin-bottom: -2px;
    background: transparent;
    white-space: nowrap;
}
.storage-subnav .nav-link:hover {
    color: var(--bs-body-color);
    background-color: rgba(var(--bs-primary-rgb), 0.05);
}
.storage-subnav .nav-link.active {
    color: var(--bs-primary);
    background: transparent;
    border-bottom: 2px solid var(--bs-primary);
    font-weight: 600;
}
@media (max-width: 767.98px) {
    .storage-subnav .nav-link {
        font-size: 0.75rem;
        padding: 5px 10px;
    }
    .storage-subnav .nav-link i {
        display: none;
    }
}

/* Header stat icon cards */
.stat-icon-sm {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    flex-shrink: 0;
}

/* Repo cards - dark header style. Hover uses box-shadow only — NOT
   transform. A `transform` creates a stacking context that traps
   `position: fixed` dropdown menus inside the card, defeating the
   global dropdown escape fix (issue #161). */
.repo-card {
    transition: box-shadow 0.15s;
    overflow: visible !important;
}

.repo-card:hover {
    box-shadow: 0 .25rem .75rem rgba(0,0,0,.14) !important;
}

.repo-card .dropdown-menu {
    z-index: 2147483647 !important;
    font-size: 0.8rem;
    min-width: 140px;
    padding: 0.25rem 0;
}

.repo-card-header {
    background: linear-gradient(135deg, #4a90d9 0%, #357abd 100%);
    border-radius: 8px 8px 0 0;
}

.repo-icon-wrap {
    background: linear-gradient(135deg, #4a90d9 0%, #357abd 100%);
    color: #fff;
}

.repo-icon-remote {
    background: linear-gradient(135deg, #6f42c1 0%, #5a32a3 100%);
    color: #fff;
}

.repo-status-bar {
    text-align: center;
    font-size: 0.8rem;
    font-weight: 600;
    padding: 6px 12px;
    color: #fff;
    border-radius: 0 0 8px 8px;
    background: linear-gradient(135deg, #4a6a8a 0%, #3a5570 100%);
}

/* Schedule cards. Hover uses box-shadow only (see repo-card note). */
.schedule-card {
    overflow: visible !important;
    transition: box-shadow 0.15s;
}

.schedule-card:hover {
    box-shadow: 0 .25rem .75rem rgba(0,0,0,.14) !important;
}

.schedule-card .dropdown-menu {
    z-index: 2147483647 !important;
    font-size: 0.8rem;
    min-width: 140px;
    padding: 0.25rem 0;
}

.schedule-card .dropdown-item {
    padding: 0.3rem 0.75rem;
}

.schedule-card .dropdown-divider {
    margin: 0.2rem 0;
}

.schedule-icon-wrap {
    width: 56px;
    height: 56px;
    border-radius: 10px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    position: relative;
}

.schedule-icon-wrap i {
    font-size: 1.4rem;
}

.schedule-icon-wrap .schedule-id {
    font-size: 0.55rem;
    font-weight: 700;
    margin-top: 1px;
}

.schedule-active {
    background: linear-gradient(135deg, #86c540 0%, #5da832 100%);
    color: #fff;
}

.schedule-manual {
    background: linear-gradient(135deg, #4a90d9 0%, #357abd 100%);
    color: #fff;
}

.schedule-paused {
    background: linear-gradient(135deg, #9ca3af 0%, #6b7280 100%);
    color: #fff;
}

.schedule-status-bar {
    text-align: center;
    font-size: 0.8rem;
    font-weight: 600;
    padding: 6px 12px;
    color: #fff;
    border-radius: 0 0 8px 8px;
}

/* Delete warning box */
.delete-warning-box {
    background-color: #fef2f2;
    border: 2px solid #fecaca;
    border-radius: 8px;
    padding: 1.25rem;
}

/* Topbar mobile improvements */
@media (max-width: 767.98px) {
    .topbar {
        height: 48px;
    }
    .main-content {
        margin-top: 48px;
    }
    .topbar .navbar-brand {
        height: 48px;
    }
}

/* Hour picker - wrap on mobile */
.hour-picker-row .btn-group {
    flex-wrap: wrap;
    gap: 2px;
}
@media (max-width: 767.98px) {
    .hour-picker-row {
        flex-direction: column !important;
        align-items: flex-start !important;
    }
    .hour-picker-row .btn-group {
        display: flex;
        flex-wrap: wrap;
        gap: 3px;
    }
    .hour-picker-row .btn-group .btn {
        flex: 0 0 auto;
        padding: 4px 8px;
        font-size: 0.75rem;
    }
}

/* Mobile table improvements */
@media (max-width: 767.98px) {
    /* Hide less important table columns on mobile */
    .d-table-cell-md {
        display: none !important;
    }
    .d-th-md {
        display: none !important;
    }
    /* Compact tables on mobile */
    .table td, .table th {
        padding: 0.4rem 0.5rem;
        font-size: 0.8rem;
    }
    .table .text-nowrap {
        white-space: normal !important;
    }
    /* Smaller stat cards on mobile */
    .stat-icon {
        padding: 0.5rem !important;
    }
    .stat-icon i {
        font-size: 1.25rem !important;
    }
    /* Stack client header info vertically */
    .client-header-info {
        flex-direction: column;
        gap: 0.25rem;
    }
    /* Dashboard stat cards smaller text */
    .stat-card .fs-2 {
        font-size: 1.5rem !important;
    }
    /* Truncate long text in tables */
    .table .text-truncate-mobile {
        max-width: 120px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
}

@media (min-width: 768px) {
    .d-table-cell-md {
        display: table-cell !important;
    }
    .d-th-md {
        display: table-cell !important;
    }
}

/* Restore panels */
.restore-panel-header {
    background: linear-gradient(135deg, #48bb78 0%, #38a169 100%);
    color: #fff;
    padding: 10px 16px;
    font-weight: 600;
    font-size: 0.9rem;
    border-radius: 8px 8px 0 0;
}

.restore-panel-body {
    height: 450px;
    overflow-y: auto;
    border: 1px solid rgba(0,0,0,0.08);
    border-top: none;
    border-radius: 0 0 8px 8px;
}

.restore-control-bar {
    padding: 0;
}

.tree-item {
    padding: 4px 8px;
    cursor: pointer;
    white-space: nowrap;
    border-left: 3px solid transparent;
    transition: background 0.1s, border-color 0.1s;
    display: flex;
    align-items: center;
}
.tree-item:nth-child(even) {
    background: #f8f9fa;
}
.tree-item:hover {
    background: #f0fdf4;
    border-left-color: #48bb78;
}
.tree-dir > .tree-label { font-weight: 600; }
.tree-children { display: none; }
.tree-children.open { display: block; }
.tree-toggle { display: inline-block; width: 16px; text-align: center; color: #6c757d; flex-shrink: 0; }
.tree-cb { margin-right: 4px; flex-shrink: 0; }
.tree-icon { margin-right: 4px; flex-shrink: 0; }
.tree-label { overflow: hidden; text-overflow: ellipsis; }
.tree-meta { margin-left: auto; display: flex; align-items: center; gap: 12px; padding-left: 12px; flex-shrink: 0; }
.tree-size { color: #6c757d; white-space: nowrap; min-width: 60px; text-align: right; font-size: 0.85em; }
.tree-mtime { color: #6c757d; font-size: 0.8em; white-space: nowrap; min-width: 130px; text-align: right; }
.tree-count { color: #6c757d; font-size: 0.8em; margin-left: 6px; }

.restore-selection-item {
    padding: 6px 12px;
    border-bottom: 1px solid rgba(0,0,0,0.05);
    display: flex;
    justify-content: space-between;
    align-items: center;
}
.restore-selection-item:last-child { border-bottom: none; }
.restore-selection-item .btn-remove {
    opacity: 0.3;
    transition: opacity 0.15s;
}
.restore-selection-item:hover .btn-remove { opacity: 1; }

.restore-actions {
    border-top: 1px solid rgba(0,0,0,0.08);
    padding: 12px 16px;
    background: #f8f9fa;
    border-radius: 0 0 8px 8px;
}

.version-group {
    border-bottom: 1px solid rgba(0,0,0,0.06);
}
.version-group-header {
    position: sticky;
    top: 0;
    background: #f8f9fa;
    padding: 6px 12px;
    font-weight: 600;
    font-size: 0.85rem;
    border-bottom: 1px solid rgba(0,0,0,0.08);
    z-index: 1;
}
.version-row {
    padding: 4px 12px 4px 28px;
    font-size: 0.85rem;
    display: flex;
    align-items: center;
    gap: 8px;
}
.version-row:hover { background: #f0fdf4; }

.restore-back-btn {
    border: none;
    background: none;
    color: #48bb78;
    font-weight: 600;
    cursor: pointer;
    padding: 4px 8px;
}
.restore-back-btn:hover { color: #2f855a; }

/* Mobile: stack restore panels */
@media (max-width: 991.98px) {
    .restore-panel-body {
        height: 300px;
    }
}

/* Responsive border utilities */
@media (max-width: 767.98px) {
    .border-md-start { border-left: none !important; }
    .border-top-0-md { border-top: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; }
}
@media (min-width: 768px) {
    .border-md-start { border-left: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; }
    .border-top-0-md { border-top: none !important; }
}
@media (max-width: 991.98px) {
    .border-lg-0 { border: none !important; }
}
@media (min-width: 992px) {
    .border-top.border-lg-0 { border-top: none !important; }
}

/* Dark mode — low-contrast palette */
[data-bs-theme="dark"] {
    /* Three surfaces, deliberately separated: topbar, sidebar, canvas. They
       used to sit within a couple of points of each other, which read as one
       flat plane with lines drawn on it. */
    --bs-body-bg: #1a1f25;
    --bs-body-color: #b0b8c1;
    --bs-secondary-color: #8b929a;
    --bs-secondary-bg: #23272b;
    --bs-tertiary-bg: #23272b;
    --bs-border-color: rgba(255, 255, 255, 0.08);
    --bbs-nav-bg: #151a1f;
    --bbs-nav-color: rgba(255, 255, 255, 0.5);
    --bbs-nav-hover-bg: rgba(255, 255, 255, 0.06);
    --bbs-nav-hover-color: rgba(255, 255, 255, 0.9);
    --bbs-topbar-bg: #101417;
}

[data-bs-theme="dark"] .card {
    border: 1px solid rgba(255, 255, 255, 0.05) !important;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
    background-color: #111214;
}

[data-bs-theme="dark"] .card-header {
    /* Universal dark-mode header color — also applied to
       .card-head-gradient below, plus .table th, so every header on
       every page is visually identical. */
    background-color: #202b3f;
    color: #fff;
    border-bottom: 1px solid rgb(24 24 25);
}

[data-bs-theme="dark"] .table th {
    /* Match the card header color so a table on a page reads as a
       continuation of the header above it. */
    background-color: #202b3f;
    color: #d6dbe1;
    border-bottom-color: rgb(24 24 25);
}

[data-bs-theme="dark"] .table-light {
    --bs-table-bg: #23272b;
    --bs-table-border-color: rgba(255, 255, 255, 0.06);
    color: var(--bs-body-color);
}

[data-bs-theme="dark"] .tree-item:nth-child(even) {
    background: rgba(255, 255, 255, 0.02);
}

[data-bs-theme="dark"] .tree-item:hover {
    background: rgba(72, 187, 120, 0.08);
}

[data-bs-theme="dark"] .version-group-header {
    background: #23272b;
}

[data-bs-theme="dark"] .version-row:hover {
    background: rgba(72, 187, 120, 0.08);
}

[data-bs-theme="dark"] .restore-actions {
    background: #23272b;
}

[data-bs-theme="dark"] .restore-panel-body {
    border-color: rgba(255, 255, 255, 0.05);
}

[data-bs-theme="dark"] .delete-warning-box {
    background-color: #2a1515;
    border-color: #4a2020;
}

[data-bs-theme="dark"] .stat-card:hover {
    box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .3) !important;
}

/* Dashboard: SVG gauge styles */
.gauge-track { stroke: #e9ecef; }
.gauge-pct { fill: #212529; }
.gauge-detail { fill: #6c757d; }

[data-bs-theme="dark"] .gauge-track { stroke: #343a40; }
[data-bs-theme="dark"] .gauge-pct { fill: #b0b8c1; }
[data-bs-theme="dark"] .gauge-detail { fill: #8b929a; }

/* Dashboard: Storage pool donut */
.donut-track { stroke: #e9ecef; }
.donut-free-dot { background: #e9ecef; }

[data-bs-theme="dark"] .donut-track { stroke: #343a40; }
[data-bs-theme="dark"] .donut-free-dot { background: #343a40; }

/* Dashboard: MySQL partition bar */
.mysql-partition-bar { background: #e9ecef; }
.mysql-bar-db { background: #0d6efd; color: #fff; }
.mysql-bar-other { background: #6c757d; color: #fff; }
.mysql-bar-free { background: #e9ecef; color: #6c757d; }

[data-bs-theme="dark"] .mysql-partition-bar { background: #343a40; }
[data-bs-theme="dark"] .mysql-bar-free { background: #343a40; color: #8b929a; }

/* Dashboard: Progress bar track (partitions) */
[data-bs-theme="dark"] .progress { --bs-progress-bg: #343a40; }

/* Client detail: metric card tint backgrounds */
.metric-card-blue { background-color: rgba(13,110,253,0.05); }
.metric-card-cyan { background-color: rgba(13,202,240,0.05); }
.metric-card-success { background-color: rgba(25,135,84,0.05); }
.metric-card-warning { background-color: rgba(255,193,7,0.05); }
.metric-card-danger { background-color: rgba(220,53,69,0.05); }

[data-bs-theme="dark"] .metric-card-blue { background-color: rgba(13,110,253,0.08); }
[data-bs-theme="dark"] .metric-card-cyan { background-color: rgba(13,202,240,0.08); }
[data-bs-theme="dark"] .metric-card-success { background-color: rgba(25,135,84,0.08); }
[data-bs-theme="dark"] .metric-card-warning { background-color: rgba(255,193,7,0.08); }
[data-bs-theme="dark"] .metric-card-danger { background-color: rgba(220,53,69,0.08); }

/* Anchor wrapper for clickable metric cards (e.g. dashboard hero tiles).
   Lifts the inner card on hover so it still feels interactive even though
   the card markup is the same as the non-clickable /clients tiles. */
.metric-card-link .card { transition: transform 0.15s ease, filter 0.15s ease; }
.metric-card-link:hover .card { transform: translateY(-1px); filter: brightness(1.05); }

/* Dashed placeholder / "add" cards */
.card-dashed {
    border: 2px dashed var(--bs-border-color) !important;
    background-color: var(--bs-tertiary-bg) !important;
    cursor: pointer;
}

/* Release notes markdown */
.release-notes-md h1, .release-notes-md h2, .release-notes-md h3 { font-size: 0.95rem; font-weight: 600; margin-top: 1rem; margin-bottom: 0.5rem; }
.release-notes-md h1:first-child, .release-notes-md h2:first-child, .release-notes-md h3:first-child { margin-top: 0; }
.release-notes-md p { margin-bottom: 0.5rem; }
.release-notes-md ul, .release-notes-md ol { padding-left: 1.25rem; margin-bottom: 0.5rem; }
.release-notes-md li { margin-bottom: 0.15rem; }
.release-notes-md code { font-size: 0.85em; padding: 1px 4px; background: rgba(0,0,0,0.05); border-radius: 3px; }
.release-notes-md pre { background: var(--bs-tertiary-bg); padding: 0.75rem; border-radius: 6px; font-size: 0.8rem; overflow-x: auto; }
.release-notes-md pre code { background: none; padding: 0; }
.release-notes-md *:last-child { margin-bottom: 0; }

[data-bs-theme="dark"] .release-notes-md code { background: rgba(255,255,255,0.08); }

[data-bs-theme="dark"] body.bg-body-secondary {
    background-color: #1a1d21 !important;
}


/* ── Settings rows ────────────────────────────────────────────────────────
   A settings page is a list of decisions, not a stack of boxes. Each row is
   label + explanation, the control, and the default.

   The typography carries the hierarchy: page title, section, setting name,
   description, metadata — five weights of emphasis rather than five shades of
   the same grey. Tokens so light mode isn't a hardcoded dark palette. */

:root {
    --bbs-set-title:   #1f2429;   /* page + section headings */
    --bbs-set-label:   #2c333b;   /* the setting's name */
    --bbs-set-desc:    #6b7581;   /* what it does */
    --bbs-set-meta:    #7f8895;   /* the default */
    --bbs-set-rule:    rgba(0, 0, 0, 0.07);
    --bbs-set-control-bg: #fff;
    --bbs-set-control-border: #ced4da;
    --bbs-set-control-hover-bg: #fff;
    --bbs-set-control-hover-border: #adb5bd;
    --bbs-set-control-color: #212529;
}

[data-bs-theme="dark"] {
    --bbs-set-title:   #e5e9ef;
    --bbs-set-label:   #d8dde5;
    --bbs-set-desc:    #88919d;
    --bbs-set-meta:    #7f8895;
    /* Faint on purpose: rows are separated by air, and the rule only
       reinforces it. A full-strength line per row reads as a spreadsheet. */
    --bbs-set-rule:    rgba(255, 255, 255, 0.055);
    --bbs-set-control-bg: #1d2228;
    --bbs-set-control-border: #343b45;
    --bbs-set-control-hover-bg: #20262d;
    --bbs-set-control-hover-border: #46505c;
    --bbs-set-control-color: #dce2ea;
}

/* Page heading — the level above the sections, so a page reads
   page → section → setting → description rather than starting mid-hierarchy. */
.settings-page-title {
    font-size: 1.4rem;
    font-weight: 650;
    color: var(--bbs-set-title);
    margin: 0 0 4px;
}

.settings-page-lede {
    color: var(--bbs-set-desc);
    font-size: 0.875rem;
    margin: 0 0 26px;
    /* No measure cap: the lede sits inside a full-width band now, and text
       wrapping at 45% of a wide panel reads as a mistake rather than as
       considered line length. */
}

.settings-group {
    font-size: 17px;
    font-weight: 650;
    color: var(--bbs-set-title);
    margin: 30px 0 8px;
}

.settings-group:first-of-type {
    margin-top: 4px;
}

/* Section copy that explains a group rather than one setting. */
.settings-group-note {
    color: var(--bbs-set-desc);
    font-size: 13px;
    line-height: 1.45;
    max-width: 70ch;
    margin: -2px 0 10px;
}

.settings-row {
    display: grid;
    /* Proportional, not fixed minimums. Hard minima (480 + 300 + 140 plus the
       gaps) came to 992px, which a 1280px window cannot give once the sidebar
       and the canvas padding are taken out — so the grid overflowed and ate the
       right-hand padding. minmax(0, …) lets every column shrink instead. */
    grid-template-columns: minmax(0, 1.9fr) minmax(0, 1fr) minmax(0, 0.62fr);
    column-gap: 36px;
    align-items: center;
    min-height: 82px;
    padding: 17px 0;
    border-bottom: 1px solid var(--bbs-set-rule);
}

.settings-row:last-child {
    border-bottom: 0;
}

.settings-row-label {
    font-size: 15px;
    font-weight: 600;
    color: var(--bbs-set-label);
    margin-bottom: 3px;
}

.settings-row-help {
    color: var(--bbs-set-desc);
    font-size: 13px;
    font-weight: 400;
    line-height: 1.45;
    margin: 0;
}

.settings-row-control {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

/* Controls sit on a slightly raised surface so they read as things you can
   act on, rather than dissolving into the page. */
.settings-row-control .form-control,
.settings-row-control .form-select {
    max-width: 190px;
    background-color: var(--bbs-set-control-bg);
    border: 1px solid var(--bbs-set-control-border);
    border-radius: 6px;
    color: var(--bbs-set-control-color);
}

.settings-row-control .form-control:hover,
.settings-row-control .form-select:hover {
    background-color: var(--bbs-set-control-hover-bg);
    border-color: var(--bbs-set-control-hover-border);
}

.settings-row-control .form-control:focus,
.settings-row-control .form-select:focus {
    border-color: #2684ff;
    box-shadow: 0 0 0 2px rgba(38, 132, 255, 0.12);
}

.settings-row-control .form-control-narrow {
    max-width: 110px;
}

.settings-row-unit {
    color: var(--bbs-set-desc);
    font-size: 13px;
}

.settings-row-default {
    color: var(--bbs-set-meta);
    font-size: 13px;
    text-align: left;
}

.settings-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 10px;
    padding-top: 26px;
    margin-top: 10px;
    border-top: 1px solid var(--bbs-set-rule);
}

/* Below the grid's natural width the three columns stack, and the default
   sits under the control it describes rather than stranded on its own line. */
@media (max-width: 991.98px) {
    .settings-row {
        grid-template-columns: 1fr;
        gap: 10px;
        min-height: 0;
        padding: 18px 0;
    }
}


/* Page canvas — the padding around every page's content.
   Horizontal is deliberately larger than vertical: content that runs to the
   window edge reads as unfinished, and the settings rows in particular need
   the label column to start somewhere other than hard against the sidebar. */
.page-canvas {
    padding: 20px 14px;
}

@media (min-width: 768px) {
    .page-canvas {
        padding: 26px 24px;
    }
}

@media (min-width: 1400px) {
    .page-canvas {
        padding: 30px 28px;
    }
}


/* ── Apprise URL examples ─────────────────────────────────────────────────
   Reference material, so it reads as a lookup table: the service name in a
   fixed column with its URL beside it, rather than "Label: value" run
   together on one line where the eye has to find each label again. */
.url-example-panel {
    border: 1px solid var(--bbs-set-rule);
    border-radius: 8px;
    padding: 18px 22px;
    background-color: var(--bs-tertiary-bg);
}

.url-example {
    display: flex;
    align-items: baseline;
    gap: 14px;
    padding: 6px 0;
    font-family: var(--bs-font-monospace, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 0.82rem;
}

.url-example-label {
    flex: 0 0 92px;
    font-weight: 600;
    color: #6ea8fe;
}

[data-bs-theme="light"] .url-example-label {
    color: #0d6efd;
}

.url-example-value {
    color: var(--bbs-set-desc);
    background: none;
    padding: 0;
    word-break: break-all;
}

/* Table headers on the settings pages: quiet column labels rather than a
   filled bar competing with the section heading above them. */
.settings-table thead th {
    background: none;
    border-bottom: 1px solid var(--bbs-set-rule);
    color: var(--bbs-set-meta);
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    padding-bottom: 10px;
}

.settings-table tbody td {
    border-bottom: 1px solid var(--bbs-set-rule);
    padding-top: 14px;
    padding-bottom: 14px;
}


/* Mobile navigation drawer — replaces the bottom bar, which could only ever
   show four destinations and pushed the rest behind "More". */
.mobile-nav-drawer {
    width: 270px;
}

.mobile-nav-drawer .list-group-item {
    border: 0;
    padding: 9px 18px;
    font-size: 0.9rem;
}

.mobile-nav-drawer .mobile-nav-heading {
    padding: 13px 18px 5px;
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--bs-secondary-color);
}

.topbar-burger:focus {
    box-shadow: none;
}


/* A long unbroken value — an Apprise URL, a token, a repo path — must wrap
   rather than widen its column and shove the page out from under its own
   right-hand padding. */
.settings-row,
.settings-row-control,
.settings-row-label,
.settings-row-help {
    min-width: 0;
}

.settings-row-control .form-control,
.settings-row-control .form-select {
    max-width: 100%;
}


/* Settings page headline band.
   A faint blue cast so the top of the page has somewhere to start, rather than
   a title floating on the same flat surface as everything under it. Kept very
   low contrast — this is a backdrop, not a callout, and it must not compete
   with the warning and info alerts that appear directly below it on some
   pages. */
.settings-page-head {
    background: linear-gradient(180deg,
        rgba(38, 132, 255, 0.055) 0%,
        rgba(38, 132, 255, 0.02) 100%);
    border-bottom: 1px solid rgba(38, 132, 255, 0.10);
    margin-bottom: 26px;

    /* Full bleed: pulled out to the edges of the content area by exactly the
       canvas padding, then given that padding back on the inside — so the band
       reaches the edges while its text stays on the same line as everything
       below it. The values track .page-canvas at each breakpoint; change one
       and change the other. */
    margin-top: -20px;
    margin-left: -14px;
    margin-right: -14px;
    padding: 20px 14px;
}

@media (min-width: 768px) {
    .settings-page-head {
        margin-top: -26px;
        margin-left: -24px;
        margin-right: -24px;
        padding: 26px 24px;
    }
}

@media (min-width: 1400px) {
    .settings-page-head {
        margin-top: -30px;
        margin-left: -28px;
        margin-right: -28px;
        padding: 30px 28px;
    }
}

[data-bs-theme="light"] .settings-page-head {
    background: linear-gradient(180deg,
        rgba(13, 110, 253, 0.045) 0%,
        rgba(13, 110, 253, 0.015) 100%);
    border-bottom-color: rgba(13, 110, 253, 0.11);
}

.settings-page-head .settings-page-title,
.settings-page-head .settings-page-lede {
    margin-bottom: 0;
}

.settings-page-head .settings-page-title {
    margin-bottom: 4px;
}

/* The first section heading sits closer to the band than it would to a bare
   title, since the band already provides the separation. */
.settings-page-head + .settings-group,
.settings-page-head + div > .settings-group:first-of-type {
    margin-top: 0;
}
