/*
 * Admin component layer — token-driven building blocks for internal pages.
 *
 * Use these classes in admin views instead of inline <style> blocks so the
 * design language stays consistent. Never apply to public/donor-facing
 * surfaces (donation form, checkout, web elements, campaign pages, donor
 * portal, receipts).
 */

/* -- Bootstrap tooltip background ---------------------------------------- */
/*
 * Bootstrap 5.3 defaults --bs-tooltip-bg to var(--bs-emphasis-color), which
 * is not defined by this app's CSS layer — leaving tooltips with a visible
 * arrow but a transparent body. Pin the dark scheme explicitly.
 */
.tooltip {
    --bs-tooltip-bg: var(--color-bg-tooltip) !important;
    --bs-tooltip-color: var(--color-text-on-dark);
}

.tooltip .tooltip-arrow::before,
.bs-tooltip-top .tooltip-arrow::before,
.bs-tooltip-auto[data-popper-placement^="top"] .tooltip-arrow::before {
    border-top-color: var(--color-bg-tooltip);
}
.bs-tooltip-bottom .tooltip-arrow::before,
.bs-tooltip-auto[data-popper-placement^="bottom"] .tooltip-arrow::before {
    border-bottom-color: var(--color-bg-tooltip);
}
.bs-tooltip-start .tooltip-arrow::before,
.bs-tooltip-auto[data-popper-placement^="left"] .tooltip-arrow::before {
    border-left-color: var(--color-bg-tooltip);
}
.bs-tooltip-end .tooltip-arrow::before,
.bs-tooltip-auto[data-popper-placement^="right"] .tooltip-arrow::before {
    border-right-color: var(--color-bg-tooltip);
}

/* -- Page header ---------------------------------------------------------- */

.page-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--space-4);
    margin-bottom: var(--space-4);
}

.page-header .page-title {
    margin: 0;
    font-size: 1.75rem;
    font-weight: 500;
    color: var(--color-text-strong);
}

.page-header__actions {
    display: flex;
    gap: var(--space-2);
    align-items: center;
}

.page-header__actions .btn,
.page-header__actions .btn-sm {
    padding: 6px 12px;
    font-size: 1rem;
    border-radius: var(--radius-md);
    white-space: nowrap;
}

/* -- Toolbar -------------------------------------------------------------- */

.toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-4);
    align-items: flex-end;
    margin-bottom: var(--space-2);
}

.toolbar__field {
    flex: 0 0 auto;
    min-width: 160px;
}

.toolbar__field--grow {
    flex: 1 1 200px;
}

.toolbar__actions {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-left: auto;
}

/* -- Card ----------------------------------------------------------------- */

.surface-card {
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-lg);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
    padding: var(--space-6);
}

/*
 * Use only on cards that are actually clickable (dashboard tiles, link tiles).
 * Do NOT apply to filter cards — they're not clickable and the hover-lift
 * implies the wrong affordance.
 */
.surface-card--interactive {
    transition: box-shadow 0.15s ease-in-out;
    cursor: pointer;
}

.surface-card--interactive:hover {
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
}

/* -- Filter controls ------------------------------------------------------ */

.filter-label {
    display: block;
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--color-text-default);
    margin-bottom: var(--space-1);
}

.filter-input {
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}

.filter-input:focus {
    border-color: var(--color-border);
    box-shadow: 0 0 0 0.1rem rgba(21, 43, 75, 0.15);
    outline: 0;
}

/* -- Row actions menu ----------------------------------------------------- */

.actions-dropdown {
    position: relative;
    display: flex;
    justify-content: center;
    align-items: center;
}

.actions-dropdown .btn-actions {
    background: none;
    border: none;
    padding: 6px 12px;
    color: var(--color-text-muted);
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
    border-radius: var(--radius-sm);
    transition: background-color 0.15s ease-in-out;
    display: flex;
    align-items: center;
    justify-content: center;
}

.actions-dropdown .btn-actions:hover {
    background-color: var(--color-bg-row-hover);
    color: var(--color-bg-sidebar);
}

.actions-dropdown .btn-actions:focus {
    outline: none;
    box-shadow: none;
}

/* -- DataTables shared overrides ----------------------------------------- */

.dataTable.table {
    box-shadow: none;
}

.data-table-wrapper {
    width: 100%;
    -webkit-overflow-scrolling: touch;
}

/* Connected Apps: the scope list is the one free-text cell wide enough to push the
   trailing Status and Revoke columns off screen. Cap it and let it wrap. */
.connection-scopes {
    max-width: 320px;
    white-space: normal;
}

.data-table-wrapper .dataTables_length,
.data-table-wrapper .dataTables_filter,
.data-table-wrapper .dataTables_info {
    display: none !important;
}

.data-table-wrapper .dataTables_paginate {
    margin-top: var(--space-5) !important;
}

.data-table-wrapper .page-link {
    color: var(--color-bg-sidebar);
    background-color: var(--color-bg-faint);
    border-color: var(--color-border-subtle);
    box-shadow: none;
}

.data-table-wrapper .page-link:hover {
    color: var(--color-bg-sidebar);
    background-color: var(--color-bg-light);
    border-color: var(--color-border-subtle);
}

.data-table-wrapper .page-link.active,
.data-table-wrapper .active > .page-link {
    background-color: var(--color-bg-sidebar);
    border-color: var(--color-bg-sidebar);
    color: var(--color-text-on-dark);
}

.data-table-wrapper .page-link:focus {
    box-shadow: none !important;
}

.data-table-wrapper .page-item.disabled .page-link {
    color: var(--color-text-muted);
    background-color: var(--color-bg-faint);
    border-color: var(--color-border-subtle);
}

.data-table-wrapper table.dataTable thead > tr > th.sorting,
.data-table-wrapper table.dataTable thead > tr > th.sorting_asc,
.data-table-wrapper table.dataTable thead > tr > th.sorting_desc {
    background-image: none !important;
    padding-right: var(--space-3);
    position: relative;
    cursor: pointer;
}

.data-table-wrapper table.dataTable thead > tr > th.sorting:after,
.data-table-wrapper table.dataTable thead > tr > th.sorting:before {
    content: '';
}

.data-table-wrapper table.dataTable thead > tr > th.sorting_asc:after {
    content: '↑';
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 14px;
    color: var(--color-bg-sidebar);
    font-weight: bold;
    opacity: 1;
}

.data-table-wrapper table.dataTable thead > tr > th.sorting_desc:after {
    content: '↓';
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 14px;
    color: var(--color-bg-sidebar);
    font-weight: bold;
    opacity: 1;
}

@media (max-width: 768px) {
    .page-header {
        flex-direction: column;
        align-items: stretch;
        gap: var(--space-3);
    }
    .page-header__actions {
        flex-wrap: wrap;
    }
    .toolbar {
        flex-direction: column;
        align-items: stretch;
        gap: var(--space-3);
    }
    .toolbar__field,
    .toolbar__field--grow {
        flex: 0 0 auto;
        min-width: 100%;
    }
    .toolbar__actions {
        margin-left: 0;
        justify-content: flex-start;
    }
}

/* -- Data table skin ------------------------------------------------------ */
/*
 * Generic styling for admin list tables (donors, donations, campaigns,
 * reports). Apply by wrapping a <table class="table"> in
 * <div class="data-table-wrapper">. View-specific column alignment and
 * column widths still live in the view.
 */

.data-table-wrapper .table {
    box-shadow: none;
    border-collapse: collapse;
    margin: 0 !important;
}

.data-table-wrapper .table thead tr { background: transparent; }

.data-table-wrapper .table th,
.data-table-wrapper .table td {
    text-align: left;
    vertical-align: middle;
    border: none;
    border-bottom: 1px solid var(--color-border-light);
    padding: var(--space-3);
}

.data-table-wrapper .table thead th {
    background-color: var(--color-bg-faint);
    color: var(--color-text-default);
    border-bottom: 1px solid var(--color-border-subtle);
}

.data-table-wrapper .table tbody tr {
    background-color: var(--color-bg-surface);
    cursor: pointer;
}

.data-table-wrapper .table tbody tr:hover {
    background-color: var(--color-bg-table-hover);
}

.data-table-wrapper .table tbody tr td > a {
    text-decoration: none;
    color: inherit;
    padding: var(--space-4) var(--space-3);
    display: flex;
    align-items: center;
    height: 100%;
}

.data-table-wrapper .table tr td:first-child > a { padding-left: var(--space-5); }
.data-table-wrapper .table tr td:last-child > a { padding-right: var(--space-5); }

/*
 * Two-line cell: a primary value with a smaller secondary line beneath it —
 * a donor's name over the address that was actually suppressed.
 *
 * The wrapper is load-bearing, not decoration. The rule above turns a direct
 * `td > a` into a padded flex box so that the whole cell becomes a click
 * target; a link that is only the FIRST line of a cell picks that padding up
 * too, and indents itself relative to the line underneath. Nesting the link
 * inside .cell-stack takes it out of `td > a` and both lines start at the
 * same edge — including on rows that have no link at all, which is what makes
 * the column read as a column.
 */
.data-table-wrapper .table td .cell-stack {
    display: flex;
    flex-direction: column;
}

.data-table-wrapper .table td .cell-subtext {
    font-size: 12px;
    color: var(--color-text-muted);
}

/* DataTables processing overlay + spinner */
.data-table-wrapper .dataTables_empty {
    text-align: center !important;
    padding: 2rem !important;
    color: var(--color-text-muted) !important;
    height: 84px;
}

.data-table-wrapper .dataTables_scrollBody {
    border: 1px solid var(--color-border-subtle);
}

.data-table-wrapper .dataTables_scrollHead,
.data-table-wrapper .dataTables_scrollBody {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

.data-table-wrapper .dataTables_wrapper {
    width: 100%;
    position: relative;
}

.data-table-wrapper .dataTables_processing {
    position: absolute;
    top: 50px !important;
    left: calc(var(--bs-gutter-x) * 0.5) !important;
    width: calc(100% - var(--bs-gutter-x)) !important;
    height: calc(100% - 50px) !important;
    min-height: 150px;
    display: block;
    background-color: rgba(255, 255, 255, 0.9) !important;
    margin: 0 !important;
    z-index: 10;
    border-top-right-radius: 0;
    border-top-left-radius: 0;
    border: 1px solid var(--color-border-subtle);
}

.data-table-wrapper .dataTables_processing.card {
    background-color: unset;
    border-top: 0;
}

.data-table-wrapper .dataTables_processing div { display: none; }

@keyframes dataTableSpin { to { transform: rotate(360deg); } }

.data-table-wrapper .dataTables_processing::before {
    display: block;
    content: '';
    width: 50px;
    height: 50px;
    border: 4px solid rgba(21, 43, 75, 0.3);
    border-radius: 50%;
    border-top-color: var(--color-bg-sidebar);
    animation: dataTableSpin 1s ease-in-out infinite;
    position: absolute;
    top: calc(50% - 40px);
    left: calc(50% - 25px);
}

.data-table-wrapper .dataTables_processing::after {
    display: block;
    content: 'Loading...';
    font-family: avenirnext-medium, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    color: var(--color-bg-sidebar);
    font-size: 16px;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, calc(-50% + 35px));
    white-space: nowrap;
}

/* DataTables Responsive plugin (dtr-*) child rows */
.data-table-wrapper table.dataTable.dtr-inline.collapsed > tbody > tr > td.dtr-control:before,
.data-table-wrapper table.dataTable.dtr-inline.collapsed > tbody > tr > th.dtr-control:before {
    background-color: transparent;
    position: absolute;
    right: 18px;
    margin-top: 18px;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    text-align: right;
}

.data-table-wrapper table.dataTable.dtr-inline.collapsed > tbody > tr > td.dtr-control,
.data-table-wrapper table.dataTable.dtr-inline.collapsed > tbody > tr > th.dtr-control {
    padding-left: 30px;
    min-width: 40px;
}

.data-table-wrapper table.dataTable > tbody > tr.child ul.dtr-details {
    width: 100%;
    padding-left: 0;
}

.data-table-wrapper table.dataTable > tbody > tr.child ul.dtr-details > li {
    border-bottom: 1px solid var(--color-border-light);
    padding: var(--space-3) 0;
}

.data-table-wrapper table.dataTable > tbody > tr.child ul.dtr-details > li:last-child {
    border-bottom: none;
}

.data-table-wrapper table.dataTable > tbody > tr.child span.dtr-title {
    font-weight: 600;
    color: var(--color-text-default);
    min-width: 120px;
    display: inline-block;
}

.data-table-wrapper table.dataTable > tbody > tr.child span.dtr-data {
    color: var(--color-text-strong);
}

/* Filter helpers shared by list pages */
.advanced-filters-toggle {
    color: var(--color-text-muted);
    background: none;
    border: none;
    padding: 0;
    text-decoration: none;
    font-size: 0.875rem;
    font-weight: 500;
    cursor: pointer;
    transition: color 0.15s ease-in-out;
}

.advanced-filters-toggle:hover {
    color: var(--color-bg-sidebar);
    text-decoration: none;
}

#advancedFiltersContainer { overflow: hidden; }

.input-group-text {
    background-color: var(--color-bg-light);
    border-color: var(--color-border);
    color: var(--color-text-default);
}

/* -- Detail page components ----------------------------------------------- */
/*
 * Shared building blocks for single-record detail pages (donations/detail.php,
 * donors/detail.php, pledges/detail.php, recurring/detail.php, task/view.php,
 * etc.). View-specific layout (timeline content, fee breakdown rows, etc.)
 * still lives in the view, but the surface and typographic system is shared.
 */

.info-card {
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-lg);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
    overflow: hidden;
}

.card-header-custom {
    background: var(--color-bg-surface);
    border-bottom: 1px solid var(--color-border-light);
    padding: 1.25rem 1.5rem;
}

.card-header-custom h5 {
    font-size: 1.2rem;
    color: var(--color-text-strong);
}

.card-body-custom {
    padding: 1.5rem;
}

.detail-label {
    font-size: 0.875rem;
    color: var(--color-text-secondary);
    margin-bottom: 0.25rem;
    display: block;
}

.detail-value {
    font-size: 0.9375rem;
    color: var(--color-text-strong);
    font-weight: 500;
}

.amount-value {
    font-family: avenirnext-medium;
    font-size: 1.75rem;
    color: var(--color-text-strong);
}

.amount-currency {
    color: var(--color-text-secondary);
    font-size: 0.875rem;
}

.amount-icon {
    width: 60px;
    height: 60px;
    background: var(--color-green);
    border-radius: 0.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
}

.amount-icon i {
    font-size: 1.75rem;
    color: var(--color-text-on-dark);
}

/* Status badges */
.status-badge {
    padding: 0.5rem 1rem;
    border-radius: 0.375rem;
    font-size: 0.875rem;
    font-weight: 500;
    display: inline-flex;
    align-items: center;
}

.badge-success { background-color: var(--color-green); color: var(--color-text-on-dark); }
.badge-danger { background-color: var(--color-red); color: var(--color-text-on-dark); }
.badge-warning { background-color: var(--color-amber); color: var(--color-text-on-dark); }
.badge-secondary { background-color: var(--color-text-secondary); color: var(--color-text-on-dark); }

/* Action buttons */
.action-btn {
    padding: 0.75rem 1.25rem;
    border-radius: 0.5rem;
    border: none;
    font-size: 0.9375rem;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s;
    display: flex;
    align-items: center;
    justify-content: start;
    text-decoration: none;
}

.action-btn-primary { background: var(--color-blue); color: var(--color-text-on-dark); }
.action-btn-primary:hover { background: var(--color-blue-hover); color: var(--color-text-on-dark); }

.action-btn-purple { background: var(--color-purple); color: var(--color-text-on-dark); }
.action-btn-purple:hover { background: var(--color-purple-hover); color: var(--color-text-on-dark); }

.action-btn-green,
.action-btn-success { background: var(--color-green); color: var(--color-text-on-dark); }
.action-btn-green:hover,
.action-btn-success:hover { background: var(--color-green-hover); color: var(--color-text-on-dark); }

.action-btn-primary i, .action-btn-primary span,
.action-btn-purple i, .action-btn-purple span,
.action-btn-green i, .action-btn-green span,
.action-btn-success i, .action-btn-success span { color: var(--color-text-on-dark); }

.action-btn-outline {
    background: var(--color-bg-surface);
    color: var(--color-text-secondary);
    border: 1px solid var(--color-border-mid);
}

.action-btn-outline:hover {
    background: var(--color-bg-light);
    color: var(--color-text-strong);
}

.action-btn-outline-primary {
    background: var(--color-bg-surface);
    color: var(--color-blue);
    border: 1px solid var(--color-blue-border);
}

.action-btn-outline-primary i,
.action-btn-outline-primary span { color: var(--color-blue); }

.action-btn-outline-primary:hover {
    background: var(--color-blue-tint);
    color: var(--color-blue-hover);
}

.action-btn-outline-danger {
    background: var(--color-bg-surface);
    color: var(--color-red);
    border: 1px solid var(--color-red-border);
}

.action-btn-outline-danger i,
.action-btn-outline-danger span { color: var(--color-red); }

.action-btn-outline-danger:hover {
    background: var(--color-red-tint);
    color: var(--color-red-hover);
}

.btn-text-shift-down {
    position: relative;
    top: 3px;
}

/* Timeline (donations/detail and similar) */
.timeline {
    position: relative;
    padding-left: 30px;
}

.timeline::before {
    content: '';
    position: absolute;
    left: 13px;
    top: 3px;
    bottom: 25px;
    width: 2px;
    background: var(--color-border-light);
}

.timeline-item {
    position: relative;
    margin-bottom: 1.5rem;
}

.timeline-item:last-child { margin-bottom: 0; }

.timeline-marker {
    position: absolute;
    left: -22px;
    top: 5px;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    border: 2px solid var(--color-bg-surface);
    box-shadow: 0 0 0 2px var(--color-border-light);
}

.timeline-title {
    font-size: 0.9375rem;
    font-weight: 500;
    margin-bottom: 0.25rem;
    color: var(--color-text-strong);
}

.timeline-text { color: var(--color-text-secondary); }

/* Detail page container */
.detail-container {
    max-width: 1400px;
    margin: 0 auto;
}

/* Fee breakdown (donations/detail, event-registrations/detail, attendees/view) */
.fee-breakdown {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.fee-breakdown-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.fee-breakdown-label {
    font-size: 0.875rem;
    color: var(--color-text-strong);
}

.fee-breakdown-value {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--color-text-strong);
}

.fee-breakdown-item .text-muted {
    color: var(--color-text-secondary) !important;
    font-weight: 400;
}

.fee-breakdown-divider {
    height: 1px;
    background: var(--color-border-light);
    margin: 0.5rem 0;
}

.fee-breakdown-total .fee-breakdown-label {
    font-weight: 600;
    font-size: 0.875rem;
}

.fee-breakdown-total .fee-breakdown-value {
    font-size: 0.875rem;
    font-weight: 700;
}

.action-btn-outline i,
.action-btn-outline span { color: var(--color-text-secondary); }

/* -- Dashboard components ------------------------------------------------- */
/*
 * Shared building blocks for dashboard pages (campaign/dashboard.php,
 * event/dashboard.php, sponsorship/dashboard.php, donors/dashboard.php).
 * Surface aesthetic matches .surface-card / .info-card: hairline border,
 * subtle shadow, 8px radius.
 */

.dashboard-container {
    display: flex;
    flex-wrap: wrap;
    column-gap: 30px;
}

.dashboard-header {
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-lg);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
    flex-basis: 100%;
}

.header-title {
    margin: 0;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.header-subtitle {
    font-size: 0.875rem;
    color: var(--color-text-muted);
    margin-top: 0.5rem;
    margin-bottom: 0;
}

.header-actions {
    display: flex;
    gap: 0.5rem;
}

/* Tab button bar */
.tab-button-group {
    margin: 1rem 0;
    background: var(--color-bg-faint);
    padding: 1rem;
    border-radius: var(--radius-lg);
    border: 1px solid var(--color-border-subtle);
    flex-basis: 100%;
}

.tab-buttons-container {
    display: flex;
    flex-wrap: wrap;
    padding: 0;
    margin: 0;
}

.tab-button {
    border: none;
    background: transparent;
    padding: var(--space-3) var(--space-5);
    font-weight: 500;
    color: var(--color-text-default);
    cursor: pointer;
    border-radius: var(--radius-md);
    transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out;
}

.tab-button:hover {
    background-color: var(--color-bg-row-hover);
}

.tab-button.active,
.tab-button[aria-selected="true"] {
    background-color: var(--color-bg-sidebar);
    color: var(--color-text-on-dark);
}

/* Dense variant: for dashboards with many sections (campaign has nine). One
   row, never wrapping; tighter tabs, a divider between groups, and the last
   group pushed right. When the column is still too narrow it scrolls
   sideways, with no visible scrollbar. */
.tab-button-group--dense { padding: var(--space-2); min-width: 0; max-width: 100%; container-type: inline-size; }
.tab-button-group--dense .tab-buttons-container {
    flex-wrap: nowrap;
    align-items: center;
    gap: var(--space-1);
    overflow-x: auto;
    scrollbar-width: none;
    overscroll-behavior-x: contain;
}
.tab-button-group--dense .tab-buttons-container::-webkit-scrollbar { display: none; }
.tab-button-group--dense .tab-button {
    flex: none;
    white-space: nowrap;
    padding: var(--space-2) 10px;
    font-size: var(--font-size-sm);
}
.tab-button-group--dense .tab-button i { margin-right: 6px; font-size: 13px; }
.tab-button-group--dense .tab-button--end { margin-left: auto; }
/* Too narrow for icons and labels (a 1280px laptop): keep the labels, which
   are what people read, and drop the icons so every section stays visible. */
@container (max-width: 1140px) {
    .tab-button-group--dense .tab-button i { display: none; }
}
.tab-button-group--dense .tab-divider {
    flex: none;
    width: 1px;
    height: 20px;
    margin: 0 var(--space-2);
    background: var(--color-border-subtle);
}

/* Content area / section panels */
.content-area {
    flex: 1;
    display: none;
}

.content-area.active {
    display: block;
}

.content-area form {
    height: 100%;
}

.content-section {
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-lg);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
    padding: 2rem;
    display: none;
    height: 100%;
}

.content-section.active {
    display: block;
}

.content-section-title {
    font-size: 1.5rem;
    margin-bottom: 1.5rem;
    color: var(--color-text-strong);
}

/* Sidebar menu (left rail in dashboard tabs) */
.sidebar-menu {
    width: 280px;
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-lg);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
    padding: 2rem 0;
    display: none;
    align-self: start;
}

.sidebar-menu.active {
    display: block;
}

.sidebar-section-title {
    padding: 0 1.5rem;
    margin-bottom: 1rem;
    font-size: 0.75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-text-muted);
}

.sidebar-menu-item {
    padding: 0.75rem 1.5rem;
    margin: 0.25rem 0.75rem;
    color: var(--color-text-default);
    text-decoration: none;
    display: flex;
    align-items: center;
    cursor: pointer;
    border-radius: var(--radius-md);
    border: 1px solid transparent;
    transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.sidebar-menu-item:hover,
.sidebar-menu-item.active {
    color: var(--color-text-strong);
    background: var(--color-bg-row-alt);
    border-color: var(--color-border-subtle);
}

.sidebar-menu-item i {
    margin-right: 0.75rem;
    width: 20px;
    text-align: center;
}

/* Metric cards (KPIs) */
.metric-card {
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-lg);
    padding: 1.25rem;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
    flex: 1 1 280px;
    min-width: 280px;
}

.metric-card--interactive {
    transition: transform 0.2s ease, box-shadow 0.2s ease;
    cursor: pointer;
}

.metric-card--interactive:hover {
    transform: translateY(-2px);
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
}

.metric-label {
    font-size: 0.875rem;
    color: var(--color-text-muted);
    margin-bottom: 0.5rem;
    font-weight: 500;
}

.metric-value {
    font-size: 2rem;
    font-family: avenirnext-medium;
    color: var(--color-text-strong);
    margin-bottom: 0.25rem;
}

.metric-subtitle {
    color: var(--color-text-muted);
    font-size: 0.85rem;
}

/* Stat card (highlighted KPI tile with accent stripe) */
.stat-card {
    background: var(--color-bg-surface);
    padding: 1.75rem;
    border-radius: var(--radius-lg);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
    border: 1px solid var(--color-border-subtle);
    border-left: 4px solid var(--color-accent-navy);
    transition: all 0.2s ease;
}

@media (max-width: 768px) {
    .metric-card {
        flex: 1 1 100%;
        min-width: 100%;
        padding: 1rem;
    }
    .metric-value {
        font-size: 1.5rem;
    }
    .stat-card {
        padding: 1.25rem;
    }
}

@media (max-width: 480px) {
    .metric-value {
        font-size: 1.25rem;
    }
    .stat-card {
        padding: 1rem;
    }
}

/* -- Status icon ---------------------------------------------------------- */
/*
 * Shared status icon base and unified color modifiers for all donation,
 * recurring, campaign, and event status indicators.
 */
.status-icon {
    text-align: center;
    display: flex;
    justify-content: center;
    align-items: center;
    font-weight: bold;
    font-size: 16px;
}

/* Status color modifiers - used across donations, recurring, campaigns, events */
.status-complete {
    color: var(--color-success);
}

.status-refunded {
    color: var(--color-danger);
}

.status-refunded i {
    font-size: 14px;
}

.status-pending {
    color: var(--color-warning);
}

.status-failed {
    color: var(--color-danger);
}

.status-active {
    color: var(--color-success);
}

.status-canceled,
.status-cancelled {
    color: var(--color-text-secondary);
}

.status-incomplete {
    color: var(--color-warning);
}

.status-pastdue {
    color: var(--color-danger);
}

.status-completed {
    color: var(--color-text-secondary);
}

.status-paused {
    color: var(--color-danger);
}

.status-retrying {
    color: var(--color-orange);
}

.status-archived {
    color: var(--color-text-secondary);
}

/* Donation type icons - recurring, offline, one-time */
.recurring-icon {
    color: var(--color-text-muted);
    font-size: 14px;
}

/* Recurring rows carry which payment of the plan they are, as a #N beside the
   mark. Set next to the glyph rather than pinned over it, so a three-digit
   count on a long-running plan cannot swallow the mark it belongs to. */
.recurring-icon-numbered {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    color: var(--color-text-muted);
    line-height: 1;
    cursor: help;
}

/* Both children sit on the flex cross-axis centre only if neither carries its
   own leading — the icon's line box would otherwise push the number down. */
.recurring-icon-numbered > i {
    display: block;
    line-height: 1;
}

.recurring-installment {
    display: block;
    font-size: 11.5px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.2px;
    line-height: 1;
    color: var(--color-text-secondary);
}

.offline-icon,
.onetime-icon {
    color: var(--color-text-muted);
    font-size: 18px;
}

/* Payment method icons - used across donations, events, registrations */
.payment-method-icon {
    color: var(--color-text-default);
    font-size: 16px;
    flex-shrink: 0;
}

/* Image-based method marks (tap to pay, Stripe Link) need an explicit box —
   they are <img>, so font-size does not size them. */
.payment-method-icon-img {
    width: 24px;
    height: 24px;
}

/* Inline brand SVGs (Zelle, Venmo) — Font Awesome carries no mark for either.
   Third-party brand colors, same exception as .fa-apple-pay / .fa-google-pay
   below; sourced from venmo.com/about/brand and zellepay.com.
   Two selectors per rule because the PHP renderer wraps the mark in a <span>
   while the React one puts the class on the <svg> itself. */
.payment-method-icon--zelle,
.payment-method-icon--venmo {
    display: inline-flex;
    align-items: center;
}

.payment-method-icon--zelle {
    color: #6d1ed4;
}

.payment-method-icon--venmo {
    color: #008cff;
}

/* Venmo ships as a wordmark occupying a 24x4.55 band, so it needs a wide box —
   a square one renders it as an illegible sliver. */
.payment-method-icon--venmo svg,
svg.payment-method-icon--venmo {
    width: 2.5em;
    height: 0.474em;
}

.fa-apple-pay {
    color: #000000;
}

.fa-google-pay {
    color: #4285f4;
}

.fa-credit-card {
    color: var(--color-text-muted);
}

.fa-mobile-alt {
    color: var(--color-success);
}

.fa-university {
    color: #007bff;
}

/* Add item button - reusable for "Add Amount", "Add Designation", "Add Mapping", etc. */
.btn-add-item {
    background-color: var(--color-bg-light);
    border: 1px solid var(--color-border-mid);
    color: var(--color-text-secondary);
    transition: all 0.2s ease;
    padding: 6px 12px;
    border-radius: 6px;
    cursor: pointer;
}

.btn-add-item:hover {
    background-color: var(--color-border-light);
    border-color: var(--color-border-hover);
    color: var(--color-text-emphasis);
    /* box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); */
}

.btn-add-item:active {
    /* box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); */
}

@media screen and (max-width: 768px) {
    .data-table-wrapper .dataTables_processing {
        top: 32.5px !important;
        height: calc(100% - 32.5px) !important;
        left: 0 !important;
        width: 100% !important;
    }
    .data-table-wrapper .dataTables_wrapper .dataTables_paginate {
        margin-top: 15px !important;
    }
    .data-table-wrapper .dataTables_wrapper .dataTables_paginate .pagination {
        flex-wrap: wrap;
        gap: var(--space-1);
    }
    .data-table-wrapper .page-item { margin: 0; }
    .data-table-wrapper .page-link {
        padding: 0.375rem 0.65rem;
        font-size: 0.875rem;
    }
    .data-table-wrapper table.dataTable > tbody > tr.child ul.dtr-details {
        display: block;
        width: 100%;
        padding: 10px 15px;
        background-color: var(--color-bg-light);
        margin: 0;
    }
    .data-table-wrapper table.dataTable > tbody > tr.child ul.dtr-details > li {
        display: flex;
        flex-direction: column;
        padding: var(--space-2) 0;
        border-bottom: 1px solid var(--color-border-subtle);
    }
    .data-table-wrapper table.dataTable > tbody > tr.child span.dtr-title {
        margin-bottom: var(--space-1);
        font-size: 0.875rem;
    }
    .data-table-wrapper table.dataTable > tbody > tr.child span.dtr-data {
        font-size: 0.875rem;
        word-break: break-word;
    }
    .data-table-wrapper table.dataTable.dtr-inline.collapsed > tbody > tr > td.dtr-control:before,
    .data-table-wrapper table.dataTable.dtr-inline.collapsed > tbody > tr > th.dtr-control:before {
        border-radius: 4px;
        width: 24px;
        height: 24px;
        line-height: 24px;
        font-size: 14px;
        margin-right: 0;
    }
    .export-button-text { display: none !important; }
}

@media screen and (max-width: 576px) {
    .data-table-wrapper .page-link {
        padding: 0.25rem 0.5rem;
        font-size: 0.8125rem;
    }
    .data-table-wrapper table.dataTable > tbody > tr.child ul.dtr-details {
        padding: var(--space-2) var(--space-3);
    }
    .data-table-wrapper table.dataTable > tbody > tr.child span.dtr-title,
    .data-table-wrapper table.dataTable > tbody > tr.child span.dtr-data {
        font-size: 0.8125rem;
    }
    .data-table-wrapper table.dataTable.dtr-inline.collapsed > tbody > tr > td.dtr-control:before,
    .data-table-wrapper table.dataTable.dtr-inline.collapsed > tbody > tr > th.dtr-control:before {
        width: 20px;
        height: 20px;
        line-height: 20px;
        font-size: 12px;
    }
}

@media screen and (max-width: 480px) {
    .data-table-wrapper .dataTables_wrapper {
        width: 100%;
        overflow-x: auto;
    }
}

/* -- Admin index page chrome --------------------------------------------- */
/*
 * Shared helpers used by index views (campaign, donations, donors). Keep
 * view-specific column-hiding / nth-child rules in the views themselves;
 * everything below is mechanically identical across those pages.
 */
.admin-index input { margin-bottom: 0 !important; }
.admin-index select { padding: 7px 7px 3px 7px; }

.admin-index .modal-body { padding: 0; }

.admin-index__table-wrap { margin-top: var(--space-5); }
.admin-index__table {
    width: 100%;
    display: table;
    height: 1px;
    border-collapse: collapse;
}

.admin-index__filter-toggle {
    color: var(--color-text-muted);
    transition: transform 0.2s ease;
    cursor: pointer;
}
.admin-index__filter-divider {
    border-color: var(--color-border-subtle);
    margin: 1rem 0;
}
.btn-clear-all {
    white-space: nowrap;
    padding: 6px 12px;
}

@media screen and (max-width: 768px) {
    .admin-index-table { font-size: 0.875rem; }
    .admin-index-table th,
    .admin-index-table td { padding: 8px 6px; }
    .admin-index-table tr td:last-child a { padding-right: var(--space-3); }
}
@media screen and (max-width: 576px) {
    .admin-index-table { font-size: 0.8125rem; }
    .admin-index-table th,
    .admin-index-table td { padding: 6px 4px; }
    .data-table-wrapper .dataTables_wrapper .row,
    .data-table-wrapper .dataTables_wrapper .col-sm-12 { margin: 0; padding: 0; }
}
@media screen and (max-width: 480px) {
    .admin-index-table { min-width: 100%; }
}

/* -- Integration Modal Common Styles -------------------------------------- */
/*
 * Shared styles for all integration configuration modals
 * (Mailchimp, Meta Pixel, Bloomerang, Double the Donation, Meta Business)
 */

/* Message alerts */
.message-container {
    margin-bottom: var(--space-5);
    display: none;
}

.message-alert {
    padding: var(--space-3) var(--space-4);
    border-radius: 6px;
    margin-bottom: var(--space-3);
    position: relative;
    border: 1px solid;
}

.message-alert.success {
    background-color: var(--color-alert-success-bg);
    border-color: var(--color-alert-success-border);
    color: var(--color-alert-success-text);
}

.message-alert.error {
    background-color: var(--color-alert-danger-bg);
    border-color: var(--color-alert-danger-border);
    color: var(--color-alert-danger-text);
}

.message-alert.info {
    background-color: var(--color-alert-info-bg);
    border-color: var(--color-alert-info-border);
    color: var(--color-alert-info-text);
}

.message-alert .close-btn {
    position: absolute;
    top: 8px;
    right: 12px;
    background: none;
    border: none;
    font-size: 18px;
    cursor: pointer;
    color: inherit;
    opacity: 0.7;
}

.message-alert .close-btn:hover {
    opacity: 1;
}

/* Welcome/no-config state containers */
.no-api-key-container,
.no-pixel-id-container,
.no-keys-container {
    text-align: center;
    padding: var(--space-10) var(--space-5);
    min-height: 300px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
}

.welcome-section {
    margin-bottom: 30px;
}

.welcome-section h3 {
    color: var(--color-text-strong);
    font-size: 20px;
    font-weight: 600;
    margin-bottom: 10px;
}

.welcome-section p {
    color: var(--color-text-secondary);
    margin-bottom: 0;
    font-size: 14px;
}

/* Form containers */
.api-key-form-centered,
.pixel-id-form-centered,
.keys-form {
    width: 100%;
    max-width: 400px;
}

.api-key-form-centered .form-group,
.pixel-id-form-centered .form-group,
.keys-form .form-group {
    margin-bottom: var(--space-5);
}

.api-key-form-centered input[type="text"],
.api-key-form-centered input[type="password"],
.pixel-id-form-centered input[type="text"],
.pixel-id-form-centered input[type="password"],
.keys-form input[type="text"],
.keys-form input[type="password"] {
    width: 100%;
    padding: var(--space-3) var(--space-4);
    border: 2px solid var(--color-border-light);
    border-radius: 6px;
    font-size: 14px;
    transition: border-color 0.15s ease-in-out;
}

.api-key-form-centered input:focus,
.pixel-id-form-centered input:focus,
.keys-form input:focus {
    outline: 0;
}

.help-text {
    color: var(--color-text-secondary);
    font-size: 12px;
    margin-top: var(--space-2);
    text-align: left;
}

/* Connected state */
.connected-container {
    padding: var(--space-5);
}

.account-info-section {
    background: var(--color-bg-light);
    border-radius: 8px;
    padding: var(--space-5);
    margin-bottom: var(--space-5);
    border: 1px solid var(--color-border-light);
}

/* Info items */
.info-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: var(--space-2) 0;
    border-bottom: 1px solid var(--color-border-light);
}

.info-item:last-child {
    border-bottom: none;
}

.info-label {
    font-weight: 500;
    color: var(--color-text-emphasis);
    font-size: 14px;
}

.info-value {
    color: var(--color-text-secondary);
    font-size: 14px;
}

/* Status badges */
.status-badge {
    display: inline-block;
    padding: var(--space-1) var(--space-3);
    border-radius: 4px;
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.status-connected {
    background-color: var(--color-alert-success-bg);
    color: var(--color-alert-success-text);
}

.status-disconnected {
    background-color: var(--color-alert-danger-bg);
    color: var(--color-alert-danger-text);
}

/* Disconnect section */
.disconnect-section {
    border-top: 1px solid var(--color-border-light);
    padding-top: var(--space-5);
    margin-top: var(--space-5);
    text-align: center;
}

.btn-disconnect {
    background: var(--color-danger);
    border: none;
    color: var(--color-text-on-dark);
    padding: 10px 20px;
    border-radius: 6px;
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    transition: background-color 0.2s;
}

.btn-disconnect:hover {
    background: var(--color-danger-hover);
}

.btn-disconnect:disabled {
    background-color: var(--color-gray-disabled);
    cursor: not-allowed;
}

/* Section titles with icons */
.section-title-with-icon {
    margin-top: 0;
    margin-bottom: var(--space-4);
    color: var(--color-text-emphasis);
    display: flex;
    align-items: center;
    font-size: 16px;
    font-weight: 600;
}

.section-title-with-icon i {
    margin-right: var(--space-2);
    font-size: 18px;
}

/* Section titles without icons */
.section-title {
    margin-top: 0;
    margin-bottom: var(--space-3);
    color: var(--color-text-emphasis);
    font-size: 16px;
    font-weight: 600;
}


/* ------------------------------------------------------------------
   Salesforce connect: authentication-method chooser + JWT setup
   Two flows share one modal (OAuth browser consent, JWT server-to-server),
   so the chooser has to make the trade-off legible before anything is typed.
   ------------------------------------------------------------------ */
.auth-method-tabs {
    display: flex;
    gap: var(--space-2);
    margin-bottom: var(--space-5);
    border-bottom: 1px solid var(--color-border-light);
}

.auth-method-tab {
    appearance: none;
    background: none;
    border: 0;
    border-bottom: 2px solid transparent;
    padding: var(--space-3) var(--space-4);
    font-size: 14px;
    font-weight: 500;
    color: var(--color-text-secondary);
    cursor: pointer;
}

.auth-method-tab:hover {
    color: var(--color-text-emphasis);
}

.auth-method-tab.is-active {
    color: var(--color-link);
    border-bottom-color: var(--color-link);
}

.auth-method-panel[hidden] {
    display: none;
}

/* Inline notices inside integration modals. Sized down from .message-alert:
   these are static explanatory copy, not dismissible feedback. */
.setup-notice {
    border: 1px solid var(--color-border-light);
    border-left: 3px solid var(--color-border-hover);
    border-radius: 4px;
    padding: var(--space-3) var(--space-4);
    font-size: 13px;
    line-height: 1.5;
    color: var(--color-text-emphasis);
    background: var(--color-bg-light);
    margin-bottom: var(--space-4);
}

.setup-notice--info {
    background: var(--color-blue-tint);
    border-color: var(--color-blue-border);
    border-left-color: var(--color-blue);
    color: var(--color-alert-info-text);
}

.setup-notice--warning {
    background: var(--color-bg-faint);
    border-color: var(--color-border-mid);
    border-left-color: var(--color-amber);
    color: var(--color-text-emphasis);
}

.setup-notice--error {
    background: var(--color-alert-danger-bg);
    border-color: var(--color-alert-danger-border);
    border-left-color: var(--color-danger);
    color: var(--color-alert-danger-text);
}

.setup-notice strong {
    display: block;
    margin-bottom: var(--space-1);
}

/* Ordered setup instructions handed to a Salesforce admin. */
.setup-steps {
    margin: var(--space-3) 0 var(--space-5);
    padding-left: var(--space-5);
    font-size: 13px;
    line-height: 1.6;
    color: var(--color-text-emphasis);
}

.setup-steps li {
    margin-bottom: var(--space-2);
}

.setup-steps code {
    background: var(--color-bg-light);
    border: 1px solid var(--color-border-light);
    border-radius: 3px;
    padding: 1px 4px;
    font-size: 12px;
}

/* Monospace echo of an opaque identifier (consumer key, username). */
.info-value--mono {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 12px;
    word-break: break-all;
}

/* ------------------------------------------------------------------
   Integration-modal building blocks.

   These replace inline styles that had been re-typing token values by
   hand — `color: #6c757d` is exactly --color-text-secondary and
   `color: #495057` is --color-text-emphasis — which is how the modal
   drifted from the rest of the admin UI in the first place.
   ------------------------------------------------------------------ */

/* Modal heading with the integration's logo beside the title. */
.modal-title--with-logo {
    display: flex;
    align-items: center;
    gap: var(--space-3);
}

.integration-logo {
    height: 28px;
    width: auto;
}

/* Explanatory paragraph under a section title. */
.section-lede {
    color: var(--color-text-secondary);
    font-size: 13px;
    margin-bottom: var(--space-3);
}

/* Last element of a section, so the section's own padding does the spacing. */
.section-lede--flush {
    margin-bottom: 0;
}

/* One radio/checkbox choice in a settings list. */
.radio-option {
    margin-bottom: var(--space-2);
}

.radio-option .form-check-label {
    font-size: 14px;
    color: var(--color-text-emphasis);
}

/* A labelled control standing on its own inside a modal section. The
   .form-group rule above only applies inside .keys-form / .api-key-form-centered,
   so a bare .form-group out here silently falls through to the older
   definition in main.css and lands at the wrong size. */
.setting-group {
    margin-bottom: var(--space-4);
}

.setting-group > label {
    display: block;
    margin-bottom: var(--space-2);
    font-size: 14px;
    font-weight: 500;
    color: var(--color-text-emphasis);
}

/* Row of buttons, optionally trailed by an aria-live status line. */
.form-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-top: var(--space-4);
}

/* Icon to the left of button text. 6px is deliberately off the 4px scale:
   it is what every button in these modals already used inline, and rounding
   to 8px would nudge a dozen buttons for no reason. */
.btn-icon-left {
    margin-right: 6px;
}

/* Primary connect button for integration modals. Previously inline-styled in
   views/salesforce/configure-modal.php; folded here so the two connect flows
   and the retry action share one definition. */
.btn-connect {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    width: 100%;
    background: var(--color-brand-salesforce);
    border: none;
    color: var(--color-text-on-dark);
    padding: var(--space-3) var(--space-6);
    border-radius: 6px;
    font-size: 14px;
    font-weight: 500;
    text-decoration: none;
    cursor: pointer;
    transition: background-color 0.15s ease-in-out;
}

.btn-connect:hover {
    background: var(--color-brand-salesforce-hover);
    color: var(--color-text-on-dark);
    text-decoration: none;
}

.btn-connect:disabled {
    background: var(--color-gray-disabled);
    cursor: not-allowed;
}

.btn-connect-secondary {
    display: block;
    text-align: center;
    margin-top: var(--space-3);
    color: var(--color-text-secondary);
    font-size: 13px;
    text-decoration: underline;
}

.keys-form label {
    display: block;
    margin-bottom: var(--space-2);
    font-size: 13px;
    font-weight: 500;
    color: var(--color-text-emphasis);
}

.keys-form .form-select {
    width: 100%;
    padding: var(--space-3) var(--space-4);
    border: 2px solid var(--color-border-light);
    border-radius: 6px;
    font-size: 14px;
}


.welcome-lede {
    color: var(--color-text-secondary);
    font-size: 14px;
    line-height: 1.55;
}

.icon-brand-salesforce {
    color: var(--color-brand-salesforce);
}

/* Empty-state container, form variant.
   The base .no-api-key-container centres its text and shrink-wraps its children
   (align-items: center) — right for a blurb plus one button, wrong for a setup
   flow with instructions, labelled fields and a tab bar. Those need a common
   left edge and a single full-bleed content width, or the numbered steps detach
   from their markers and each block finds its own width.
   Applied per-view; the six other integrations keep the centred base. */
.no-api-key-container--form {
    text-align: left;
    align-items: stretch;
    justify-content: flex-start;
    min-height: 0;
    padding: var(--space-6) var(--space-5);
}

.no-api-key-container--form .welcome-section {
    margin-bottom: var(--space-5);
}

/* Full-bleed so the tab bar's underline spans the panel rather than floating
   under just the two labels. */
.no-api-key-container--form .auth-method-tabs,
.no-api-key-container--form .auth-method-panel {
    width: 100%;
}

/* The base .keys-form caps at 400px for a single centred API-key field. Here it
   sits under full-width notices and steps, so that cap would leave a ragged
   right edge halfway across the modal. */
.no-api-key-container--form .keys-form {
    max-width: none;
}

/* Shrink to its label and stay on the left edge, under the steps it follows. */
.sf-cert-download {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    align-self: flex-start;
    margin-bottom: var(--space-5);
}

/* Toggle row with the label on the left and the switch pushed to the right
   edge, so a column of switches lines up regardless of label length. */
.switch-wrapper--between {
    justify-content: space-between;
}

/* -- OAuth consent / error pages ------------------------------------------ */

/*
 * loginLayout centres its content with a flex parent, so a plain .container
 * shrink-wraps to its text: the short error page collapsed to a ~150px column
 * while the long consent page happened to look fine. Pin the width here so both
 * pages render at the same size regardless of how much copy they hold.
 */
.oauth-page {
    width: min(640px, calc(100vw - var(--space-8)));
    margin: var(--space-8) auto;
}

/* .info-value--mono sets word-break, but <pre>'s white-space: pre overrides it,
   so a long redirect_uri or a sentence-length note runs off the card edge. The
   detail is copy-pasteable config text, so keep its line breaks — just wrap. */
.oauth-page pre.info-value--mono {
    white-space: pre-wrap;
    /* break-all would split ordinary words mid-letter; overflow-wrap only kicks
       in for tokens that genuinely cannot fit, like a long redirect_uri. */
    word-break: normal;
    overflow-wrap: anywhere;
    margin-bottom: 0;
}

/* ---------------------------------------------------------------------------
   Outbound webhooks — health pills, signing secret, delivery log
   ------------------------------------------------------------------------ */

.webhook-health {
    display: inline-block;
    padding: var(--space-1) var(--space-3);
    border-radius: var(--radius-sm);
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    white-space: nowrap;
}

.webhook-health--healthy {
    background-color: var(--color-alert-success-bg);
    color: var(--color-alert-success-text);
}
.webhook-health--failing {
    background-color: var(--color-alert-warning-bg);
    color: var(--color-alert-warning-text);
}
.webhook-health--disabled {
    background-color: var(--color-alert-danger-bg);
    color: var(--color-alert-danger-text);
}
.webhook-health--inactive {
    background-color: var(--color-bg-light);
    color: var(--color-text-secondary);
}
.webhook-health--new {
    background-color: var(--color-alert-info-bg);
    color: var(--color-alert-info-text);
}

/* Read-only credential with a copy button beside it. */
.secret-field {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}
.secret-field input {
    font-family: var(--font-family-mono);
    font-size: var(--font-size-xs);
    background-color: var(--color-bg-light);
}

/* JSON bodies and response snippets. Scrolls in its own box — a 4KB payload
   must not widen the page. */
.payload-view {
    font-family: var(--font-family-mono);
    font-size: var(--font-size-xs);
    background-color: var(--color-bg-light);
    border: 1px solid var(--color-border-light);
    border-radius: var(--radius-sm);
    padding: var(--space-3);
    max-height: 320px;
    overflow: auto;
    white-space: pre-wrap;
    word-break: break-word;
    margin: 0;
}

.webhook-meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-6);
    font-size: var(--font-size-sm);
    color: var(--color-text-secondary);
}

/* Response code in the delivery table: legible at a glance without a pill. */
.delivery-code {
    font-family: var(--font-family-mono);
    font-size: var(--font-size-xs);
}
.delivery-code--ok { color: var(--color-alert-success-text); }
.delivery-code--bad { color: var(--color-alert-danger-text); }

/* ---------------------------------------------------------------------------
   Email preview surface
   ---------------------------------------------------------------------------
   Renders an email body the way the recipient will actually see it, NOT the way
   the admin page would style it. Deliberately not on the design tokens: it has
   to mirror mail/layouts/html-wide.php, which sets Helvetica Neue / 14px / 1.6
   and is what the mail client receives.

   Two rules keep it honest:
   - Bootstrap sizes h2/h3 for a page, which made the same heading render large
     in the preview and small in the editor. The heading and margin values below
     are the browser defaults an email client applies, expressed against the
     14px base so both panes agree.
   - The TinyMCE `content_style` on the event template editors is kept in sync
     with this block by hand. Change one, change the other, or the editor and
     the preview drift apart again.
   ------------------------------------------------------------------------- */
.email-surface {
    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
    font-size: 14px;
    line-height: 1.6;
    color: #333;
}
/* Admin CSS sets font-family on h2/h3/p directly, which beats inheriting from
   the container -- so the panes matched on size but not typeface until this.
   The caption is excluded because it is admin chrome, not email content. */
.email-surface *:not(.email-locked-note) {
    font-family: inherit;
}
.email-surface h1 { font-size: 2em;    font-weight: bold; margin: 0.67em 0; line-height: 1.3; }
.email-surface h2 { font-size: 1.5em;  font-weight: bold; margin: 0.83em 0; line-height: 1.3; }
.email-surface h3 { font-size: 1.17em; font-weight: bold; margin: 1em 0;    line-height: 1.3; }
.email-surface h4 { font-size: 1em;    font-weight: bold; margin: 1.33em 0; line-height: 1.3; }
.email-surface p  { margin: 0 0 10px; }
.email-surface ul,
.email-surface ol { margin: 0 0 10px; padding-left: 40px; }
.email-surface table { border-collapse: collapse; }

/* The "added automatically" caption sits inside .email-surface but is admin
   chrome, not part of the email — keep it on the admin type scale. */
.email-locked-note {
    font-family: var(--font-family-base);
    font-size: var(--font-size-xs);
    color: var(--color-text-secondary);
    margin-bottom: var(--space-2);
}

/* -- Page tabs (module sub-navigation) ------------------------------------ */

.page-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1);
    border-bottom: 1px solid var(--color-border-subtle);
    margin-bottom: var(--space-4);
}

.page-tabs__link {
    padding: var(--space-2) var(--space-3);
    font-size: var(--font-size-sm);
    color: var(--color-text-secondary);
    text-decoration: none;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    white-space: nowrap;
}

.page-tabs__link:hover {
    color: var(--color-text-strong);
    background: var(--color-bg-light);
}

.page-tabs__link--active {
    color: var(--color-accent-navy);
    border-bottom-color: var(--color-accent-navy);
    font-weight: 500;
}

/* ── Donation form preview modal (campaign dashboard) ────────────────────────
   A left rail of screens beside a replica of the donor's form card.

   Every class here is prefixed `sg-preview-` and used by exactly one view.
   That is deliberate: the generic names this file grew up on (.metrics-grid,
   .chart-card) are each redefined by a dozen views, so anything added here
   under a short name silently reskins pages nobody is looking at.

   The card deliberately does NOT use the admin type scale. It is a picture of
   the donor-facing form, which is not on the token system, so admin tokens
   inside the card would make the preview a confident lie. Tokens are used for
   the rail and the frame — the parts that really are admin UI. Keep the card in
   step with views/donations/donation_modal.php. */

.sg-preview {
    /* donation_modal.php :root — #3a6b4a / #ffffff when the campaign sets none. */
    --sg-preview-accent: #3a6b4a;
    --sg-preview-halo: #3a6b4a1a;
    --sg-preview-on-accent: #ffffff;
    display: flex;
    align-items: stretch;
    min-height: 520px;
}

/* ---- left rail (admin UI) ---- */

/* The rail reuses .sidebar-section-title / .sidebar-menu-item from the campaign
   dashboard's own settings nav, so it stays in step with that automatically.
   Only the container and the per-screen "off" flag are local. */
.sg-preview-side {
    flex: 0 0 280px;
    padding: var(--space-4) 0;
    border-right: 1px solid var(--color-border);
    /* --color-bg-sidebar is the app's dark navy rail; the settings nav this
       borrows from sits on the light panel background. */
    background: var(--color-bg-light);
}

/* Styles copied from .sidebar-section-title / .sidebar-menu-item rather than
   those classes reused: dashboard.php has a document-level click handler on
   `.tab-button, .sidebar-menu-item` (around line 6963), so wearing that class
   would make a rail click also switch the settings section behind the modal. */
.sg-preview-rail-title {
    padding: 0 1.5rem;
    margin-bottom: 1rem;
    font-size: 0.75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-text-muted);
}

.sg-preview-nav {
    padding: 0.75rem 1.5rem;
    margin: 0.25rem 0.75rem;
    width: calc(100% - 1.5rem);
    color: var(--color-text-default);
    background: transparent;
    display: flex;
    align-items: center;
    cursor: pointer;
    font-size: var(--font-size-sm);
    text-align: left;
    border-radius: var(--radius-md);
    border: 1px solid transparent;
    transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.sg-preview-nav:hover,
.sg-preview-nav.is-active {
    color: var(--color-text-strong);
    background: var(--color-bg-row-alt);
    border-color: var(--color-border-subtle);
}

.sg-preview-nav i {
    margin-right: 0.75rem;
    width: 20px;
    text-align: center;
}

/* Keeps 'Monthly upgrade' + its off badge on one line. */
.sg-preview-nav span { white-space: nowrap; }

.sg-preview-group { margin-bottom: 0; }












/* Marks a screen a donor cannot currently reach. It stays clickable — an admin
   deciding whether to switch it on wants to see it first. */
/* Marks a screen a donor cannot currently reach. It stays clickable — an admin
   deciding whether to switch it on wants to see it first. */
.sg-preview-flag {
    margin-left: auto;
    padding-left: var(--space-3);
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.6875rem;
    font-style: normal;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--color-text-muted);
    white-space: nowrap;
}

/* A hollow dot reads as "not live" without the badge outline crowding the label. */
.sg-preview-flag::before {
    content: '';
    width: 6px;
    height: 6px;
    border-radius: 50%;
    border: 1.5px solid currentColor;
}











/* ---- the replica card (donor UI) ----------------------------------------
   Values below are COPIED from the donor form, not eyeballed. Sources:
     checkout.css              button{}, .myFields .amountInput{}
     donation_form_styles.css  .Input/.p-FauxInput{}, :root tokens
     donation_modal.php        * { font-family: avenirnext }, .inputSelected{},
                               #customAmount{}, .checkmark*, .powered-by-section
   If you change one of those, change this. The admin already loads
   css/fonts.css, so avenirnext and avenirnext-medium resolve here exactly as
   they do on the form.

   The !important flags are not stubbornness — this card sits inside the admin
   layout, whose own type and colour rules would otherwise win on the generic
   elements (h4, p, span) the card is built from. */

.sg-preview-stage {
    flex: 1 1 auto;
    display: flex;
    justify-content: center;
    /* Centred with margin:auto on the card rather than align-items:center, so a
       card taller than the pane scrolls from its top instead of being clipped. */
    align-items: flex-start;
    padding: var(--space-5) var(--space-4);
    background: var(--color-bg-app);
    overflow-y: auto;
}

/* The form's own page padding is 40px; 26px here keeps the card readable at
   modal width without changing the proportions of what sits inside it. */
.sg-preview-card {
    width: 100%;
    /* `form { width: 400px }` — set identically in donation_modal.php and
       donation_form.php, so it is the width on both surfaces. .middle's 500px
       is the modal shell around the form (hero image included), not the form. */
    max-width: 400px;
    background: #fff;
    border-radius: 8px;        /* .middle border-radius */
    /* 40px top and sides as .page1; 20px at the bottom, measured on the live
       form as the space between the Powered by block and the card edge. The
       card sizes to its content — it is not stretched to the pane. */
    padding: 40px 40px 20px;
    margin: auto 0;
    box-shadow: 0px 0px 0px 0.5px rgba(50, 50, 93, 0.1),
                0px 2px 5px 0px rgba(50, 50, 93, 0.1),
                0px 1px 1.5px 0px rgba(0, 0, 0, 0.07);
}

/* The form sets `* { font-family: avenirnext }` inside itself, so everything
   inherits it rather than only the places that name it. */
.sg-preview-card,
.sg-preview-card * {
    font-family: avenirnext, -apple-system, system-ui, sans-serif;
    box-sizing: border-box;
    color: #30313d;
}

/* [hidden] is display:none from the UA sheet, which a class setting display
   loses to. Without this every pane with its own display value stayed on
   screen underneath the one being previewed. */
.sg-preview-pane[hidden],
.sg-preview-upsell[hidden],
.sg-preview-skip[hidden] { display: none !important; }

.sg-preview-pane--center {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    min-height: 250px;
}

/* #customAmount: deemphasize10 background, no border, 25px, 80px tall. */
.sg-preview-custom {
    background: #e6e6e6;
    border: 0;
    border-radius: 8px;
    height: 80px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 25px;
    color: #757680 !important;
    margin-bottom: 20px;
}

/* #amounts-element: flex wrap, centred, 10px gaps. */
/* Pinned to three per row. The form itself flex-wraps on a 90px basis, so the
   count follows the container width — 2 in the modal, 3 on the campaign page,
   4 in a preview card this wide. A preview that reflows differently from the
   surface being previewed is worse than one that picks the common case, so
   this is a deliberate departure from the form rather than a copy of it. */
.sg-preview-amounts {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px;
    padding-bottom: 20px;
}

/* .Input / .p-FauxInput */
/* .Input / .p-FauxInput — the form's own controls (5px), distinct from the
   Stripe elements below which are 8px. */
.sg-preview-amount,
.sg-preview-interval,
.sg-preview-input {
    background-color: #fff;
    border: 1px solid #e6e6e6;
    /* donation_modal.php overrides .Input/.p-FauxInput to 8px; the 5px in
       donation_form_styles.css :root never reaches these controls. */
    border-radius: 8px;
    box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.03), 0px 3px 6px rgba(0, 0, 0, 0.02);
}

/* .myFields .amountInput — flex-grow:10 is why these stretch to fill the row
   rather than sitting at their 90px basis. */
.sg-preview-amount {
    height: 65px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 17px;
}

.sg-preview-intervals {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 10px;
    padding-bottom: 20px;
}

.sg-preview-interval {
    width: 90px;
    padding: 12px 0;
    text-align: center;
    font-size: 13px;
}

/* .inputSelected */
.sg-preview-interval.is-active,
.sg-preview-amount.is-active {
    background-color: var(--sg-preview-accent);
    color: var(--sg-preview-on-accent) !important;
    box-shadow: none;
    border: 1px solid #e6e6e6;
}

.sg-preview-fees {
    display: block;
    pointer-events: none;
    font-size: 14px;
    margin-bottom: 14px;
}

.sg-preview-input {
    padding: 12px;
    font-size: 15px;
    color: #757680 !important;
    margin-bottom: 14px;
    min-height: 46px;
}

.sg-preview-label {
    font-size: 0.93rem;
    margin-bottom: 4px;
}

.sg-preview-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }

.sg-preview-cardbox {
    padding: 12px;
    margin-bottom: 16px;
}



/* checkout.css button{} — avenirnext-medium, 8px radius, no border, 12px/16px
   padding, 16px/600, full width. Rendered as a block, not a <button>: a preview
   that looks clickable invites a click there is nothing behind. */
.sg-preview-cta {
    background: var(--sg-preview-accent);
    color: var(--sg-preview-on-accent) !important;
    font-family: avenirnext-medium, avenirnext, sans-serif !important;
    border-radius: 8px;
    border: 0;
    padding: 12px 16px;
    font-size: 16px;
    font-weight: 600;
    text-align: center;
    width: 100%;
}



/* The form's back button: transparent, #666, 14px, 5px gap, 16px icon. */
.sg-preview-back {
    display: flex;
    align-items: center;
    gap: 5px;
    color: #666 !important;
    font-size: 14px;
    padding: 5px 0;
    margin-bottom: 10px;
}

.sg-preview-back svg { flex-shrink: 0; }











/* Matches views/donations/_recurring_upsell.php exactly. */
.sg-preview-upsell {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 10px 0 20px;
    min-height: 260px;
    justify-content: center;
}

.sg-preview-upsell-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 52px;
    height: 52px;
    border-radius: 50%;
    margin-bottom: 16px;
    background: var(--sg-preview-halo);
    color: var(--sg-preview-accent);
}

.sg-preview-upsell-headline {
    font-size: 22px;
    line-height: 1.25;
    margin: 0 0 10px;
    font-family: avenirnext-medium, avenirnext, sans-serif !important;
}

.sg-preview-upsell-message {
    font-size: 14px;
    line-height: 1.5;
    color: #4b5563 !important;
    margin: 0 0 22px;
    max-width: 320px;
}

.sg-preview-upsell-accept { margin-bottom: 10px; }

.sg-preview-upsell-decline {
    color: #6b7280 !important;
    font-size: 13px;
    text-decoration: underline;
    padding: 6px 0;
}

.sg-preview-skip {
    min-height: 260px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    text-align: center;
    font-size: 13px;
    line-height: 1.5;
    color: #6b7280 !important;
}

.sg-preview-skip strong { display: block; margin-bottom: 4px; color: #374151 !important; }

/* .checkmark is 80px and animates to a FILLED green circle with a white tick. */
.sg-preview-tick { margin-bottom: 20px; line-height: 0; }   /* .checkmark-container */

.sg-preview-success-title {
    /* No rule styles this heading on the form: it is a browser <h1> in the
       form's inherited avenirnext. Measured: 24px, weight 400, normal line
       height, 0.67em margins. Not the medium weight used for buttons. */
    font-family: avenirnext, sans-serif !important;
    font-size: 24px;
    font-weight: 400;
    line-height: normal;
    margin: 16.08px 0;
    color: rgb(20, 24, 31) !important;
}





/* .powered-by-section: 12px text beside the 40px logo, avenirnext-medium. */
.sg-preview-poweredby {
    margin-top: 10px;          /* measured: CTA bottom to Powered by block */
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 10px;
    font-size: 12px;
    font-family: avenirnext-medium, avenirnext, sans-serif !important;
}

.sg-preview-poweredby span { padding-top: 5px; margin-right: 10px; }
.sg-preview-poweredby img { height: 40px; }

/* ---- payment screen ------------------------------------------------------
   Stripe is created with `appearance: { variables: { borderRadius: '8px' } }`
   and its default theme otherwise, so its controls are 8px and use Stripe's
   own greys — NOT the 5px the form's .Input uses. Mixing the two is what made
   this screen read wrong. */

.sg-preview-wallet {
    background: #000;
    color: #fff !important;
    border-radius: 8px;
    height: 48px;                 /* expressCheckout buttonHeight: 48 */
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    font-size: 15px;
    font-weight: 600;
    margin-bottom: 0;
}

/* Stripe stacks the express buttons with a small gap of their own. */
.sg-preview-wallet + .sg-preview-wallet { margin-top: 10px; }

/* #express-checkout-element padding-bottom:12px, applied once below the
   stack rather than per button. */
.sg-preview-wallets { padding-bottom: 12px; }

.sg-preview-wallet * { color: #fff !important; }
/* Apple's own mark sits tight against "Pay" at roughly the cap height. */
.sg-preview-applepay { font-size: 21px; font-weight: 500; letter-spacing: -0.01em; }
.sg-preview-gpay-label { font-size: 16px; font-weight: 600; }
.sg-preview-gpay b { color: #4285F4 !important; }

/* #express-checkout-divider: two 1px #ddd rules either side, #888, 0.85em. */
.sg-preview-divider {
    display: flex;
    align-items: center;
    gap: 10px;
    color: #888 !important;
    font-size: 0.85em;
    padding-bottom: 14px;
}

.sg-preview-divider span { color: #888 !important; }
.sg-preview-divider-line { flex: 1; height: 1px; background: #ddd; }

/* #address-element padding-bottom:20px */
.sg-preview-stripe { padding-bottom: 20px; }

/* Stripe's own input: 8px radius, its greys, its shadow. */
.sg-preview-sinput {
    display: flex;
    align-items: center;
    gap: 8px;
    background: #fff;
    border: 1px solid #e6e6e6;
    border-radius: 8px;
    box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.03), 0px 3px 6px rgba(0, 0, 0, 0.02);
    padding: 12px;
    min-height: 44px;
    font-size: 16px;
    margin-bottom: 12px;
}

.sg-preview-placeholder { color: #757680 !important; }
.sg-preview-sinput svg { margin-left: auto; flex-shrink: 0; }
.sg-preview-select { justify-content: space-between; }

/* layout: accordion, radios true, spacedAccordionItems false — one bordered
   box, rows divided by a hairline rather than separated. */
.sg-preview-accordion {
    border: 1px solid #e6e6e6;
    border-radius: 8px;
    overflow: hidden;
    margin-bottom: 12px;
}

.sg-preview-acc-row + .sg-preview-acc-row { border-top: 1px solid #e6e6e6; }

.sg-preview-acc-head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 12px;
}

.sg-preview-acc-icon { color: #30313d; flex-shrink: 0; }

.sg-preview-acc-title { font-size: 15px; }

/* Stripe marks the open accordion item with its primary colour. */
.sg-preview-acc-row:first-child .sg-preview-acc-title,
.sg-preview-acc-row:first-child .sg-preview-acc-icon { color: #0570de !important; }

.sg-preview-radio {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    border: 1px solid #cccccc;
    flex-shrink: 0;
}

.sg-preview-radio.is-on {
    border: 5px solid #0570de;
}

.sg-preview-acc-body { padding: 0 12px 12px; }
.sg-preview-acc-body .sg-preview-sinput:last-of-type { margin-bottom: 0; }

.sg-preview-mandate {
    font-size: 0.8125rem;
    line-height: 1.45;
    color: #6d6e78 !important;
    margin: 12px 0 0;
}

/* ---- abandoned cart ------------------------------------------------------
   page4: a 400px block with 20px padding, and buttons that are taller than the
   form's ordinary CTA (15px/30px, stacked with a 15px gap). */

/* .page4 { display:flex; flex-direction:column; justify-content:center;
   align-items:center; text-align:center } — the copy is centred, not left. */
.sg-preview-abandoned {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    max-width: 400px;
    margin: 0 auto;
    padding: 20px 0;
}

.sg-preview-abandoned-actions { width: 100%; }

.sg-preview-abandoned-title {
    font-size: 24px;
    font-weight: normal;
    margin: 0 0 20px;
}

.sg-preview-abandoned-copy {
    font-size: 16px;
    line-height: 1.6;
    margin: 0 0 20px;
}

/* align-items:center on the flex column shrinks children to their content;
   the real input fills the 400px block. */
.sg-preview-abandoned-email { width: 100%; font-size: 16px; margin-bottom: 20px; text-align: left; }

.sg-preview-abandoned-actions { display: flex; flex-direction: column; gap: 15px; }

.sg-preview-cta--tall { padding: 15px 30px; }

/* "I'll come back later": transparent, #666, 1px #ddd — not the card greys. */
.sg-preview-cta--ghost {
    background: transparent;
    color: #666 !important;
    border: 1px solid #ddd;
    font-weight: normal;
}

/* ---------------------------------------------------------------------------
   Task linked-item search (views/task/_linked_item_search.php): one box that
   searches donors, donations, recurring plans, pledges and campaigns at once.
   The results panel sits in normal flow rather than floating, so the task
   modal's overflow:hidden never clips it.
   ------------------------------------------------------------------------- */
.link-search-box {
    position: relative;
}

.link-search-icon {
    position: absolute;
    left: var(--space-3);
    top: 50%;
    transform: translateY(-50%);
    color: var(--color-text-secondary);
    pointer-events: none;
}

.link-search .link-search-input.form-control {
    padding-left: var(--space-10);
    background: var(--color-bg-surface);
}

.link-search-results {
    margin-top: var(--space-1);
    max-height: 320px;
    overflow-y: auto;
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    padding: var(--space-1) 0;
}

.link-search-group,
.link-search-hint {
    padding: var(--space-2) var(--space-3) var(--space-1);
    font-size: var(--font-size-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--color-text-secondary);
}

.link-search-hint {
    padding-bottom: 0;
}

.link-search-option {
    display: flex;
    align-items: baseline;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    cursor: pointer;
}

.link-search-option.is-active {
    background: var(--color-blue-tint);
}

.link-search-title {
    color: var(--color-text-strong);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.link-search-meta {
    margin-left: auto;
    flex-shrink: 0;
    font-size: var(--font-size-xs);
    color: var(--color-text-secondary);
    white-space: nowrap;
}

.link-search-empty {
    padding: var(--space-3);
    color: var(--color-text-secondary);
    font-size: var(--font-size-sm);
}

.link-search-selected {
    list-style: none;
    margin: var(--space-3) 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.link-search-selected:empty {
    display: none;
}

.link-search-chosen {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    background: var(--color-bg-light);
    border: 1px solid var(--color-border-mid);
    border-radius: var(--radius-md);
}

.link-search-badge {
    flex-shrink: 0;
    padding: 2px var(--space-2);
    font-size: var(--font-size-xs);
    color: var(--color-blue-hover);
    background: var(--color-blue-tint);
    border: 1px solid var(--color-blue-border);
    border-radius: var(--radius-sm);
}

.link-search-chosen .link-search-meta {
    margin-left: auto;
}

.link-search-remove {
    flex-shrink: 0;
    background: none;
    border: none;
    padding: var(--space-1);
    color: var(--color-text-secondary);
    cursor: pointer;
    line-height: 1;
}

.link-search-remove:hover {
    color: var(--color-danger);
}

/* ── Campaign Settings > Bulk Import (views/campaign/_bulk_import.php) ── */
/* The section sits after #campaign-settings-form (never inside it); that form
   is height:100%, so hide it while this section is showing. */
.content-area:has(> .bulk-import.active) > form { display: none; }
/* The grid is wider than the column; let it scroll inside its wrapper
   instead of stretching the flex item and wrapping it under the sidebar. */
.content-area:has(> .bulk-import) { min-width: 0; }

.bulk-import__modes {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-5);
}

.bulk-import__mode {
    border: 1px solid var(--color-border-subtle);
    background: var(--color-bg-surface);
    color: var(--color-text-default);
    padding: var(--space-2) var(--space-4);
    border-radius: var(--radius-md);
    font-weight: 500;
    font-size: var(--font-size-sm);
    cursor: pointer;
    transition: background-color 0.15s, color 0.15s, border-color 0.15s;
}

.bulk-import__mode i { margin-right: 6px; }
.bulk-import__mode:hover { background: var(--color-bg-row-alt); }

.bulk-import__mode.is-active {
    background: var(--color-bg-sidebar);
    border-color: var(--color-bg-sidebar);
    color: var(--color-text-on-dark);
}

.bulk-import__link {
    border: none;
    background: none;
    padding: var(--space-1) var(--space-2);
    color: var(--color-link);
    font-size: var(--font-size-xs);
    font-weight: 500;
    cursor: pointer;
    border-radius: var(--radius-sm);
}

.bulk-import__link:hover { background: var(--color-blue-tint); }
.bulk-import__link i { margin-right: 4px; }
.bulk-import__modes .bulk-import__link { margin-left: auto; }
.bulk-import__link--danger { color: var(--color-danger); }
.bulk-import__link--danger:hover { background: var(--color-red-tint); }

.bulk-import__drop {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-10) var(--space-6);
    border: 2px dashed var(--color-border);
    border-radius: var(--radius-lg);
    background: var(--color-bg-faint);
    text-align: center;
    cursor: pointer;
    transition: border-color 0.15s, background-color 0.15s;
}

.bulk-import__drop:hover,
.bulk-import__drop.is-dragover {
    border-color: var(--color-blue);
    background: var(--color-blue-tint);
}

.bulk-import__drop[hidden] { display: none; }
.bulk-import__drop .help-text { text-align: center; margin-top: 0; }
.bulk-import__file { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.bulk-import__drop-icon { font-size: 2rem; color: var(--color-border-hover); }
.bulk-import__drop-title { font-weight: 600; color: var(--color-text-default); }

.bulk-import__mapping-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: var(--space-2);
}

.bulk-import__mapping-head .help-text { display: inline; }

.bulk-import__mapping-grid {
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-md);
    margin-bottom: var(--space-4);
    max-height: 420px;
    overflow-y: auto;
}

.bulk-import__mapping-row {
    display: grid;
    grid-template-columns: minmax(140px, 1fr) minmax(140px, 1.2fr) minmax(200px, 1fr);
    gap: var(--space-4);
    align-items: center;
    padding: var(--space-2) var(--space-4);
    border-bottom: 1px solid var(--color-border-light);
    font-size: var(--font-size-sm);
}

.bulk-import__mapping-row:last-child { border-bottom: none; }

.bulk-import__mapping-row--head {
    position: sticky;
    top: 0;
    background: var(--color-bg-light);
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--color-text-secondary);
}

.bulk-import__mapping-name { font-weight: 600; color: var(--color-text-strong); }

.bulk-import__mapping-sample {
    color: var(--color-text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bulk-import__toolbar {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-2);
}

.bulk-import__hint { margin-top: 0; }
.bulk-import__hint i { color: var(--color-amber); margin-right: 4px; }
.bulk-import__toolbar-actions { display: flex; gap: var(--space-1); }

.bulk-import__table-wrap {
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    overflow: auto;
    max-height: 560px;
    background: var(--color-bg-surface);
}

.bulk-import__table {
    border-collapse: separate;
    border-spacing: 0;
    width: max-content;
    min-width: 100%;
    font-size: var(--font-size-xs);
}

.bulk-import__table th {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--color-bg-light);
    color: var(--color-text-emphasis);
    font-weight: 600;
    text-align: left;
    padding: var(--space-2) var(--space-2);
    border-bottom: 1px solid var(--color-border);
    border-right: 1px solid var(--color-border-light);
    white-space: nowrap;
    min-width: 120px;
}

.bulk-import__table th.bulk-import__col--wide { min-width: 200px; }
.bulk-import__table th.bulk-import__col--narrow { min-width: 96px; }
.bulk-import__req { color: var(--color-danger); }

.bulk-import__table td {
    padding: 0;
    border-bottom: 1px solid var(--color-border-light);
    border-right: 1px solid var(--color-border-light);
    background: var(--color-bg-surface);
}

.bulk-import__table th.bulk-import__col-status,
.bulk-import__table td.bulk-import__col-status {
    position: sticky;
    left: 0;
    z-index: 1;
    min-width: 0;
    width: 56px;
    text-align: right;
    padding: 0 var(--space-2);
    background: var(--color-bg-light);
    color: var(--color-text-muted);
    white-space: nowrap;
}

.bulk-import__table th.bulk-import__col-status { z-index: 3; }

.bulk-import__table th.bulk-import__col-remove,
.bulk-import__table td.bulk-import__col-remove {
    min-width: 0;
    width: 36px;
    text-align: center;
    border-right: none;
}

.bulk-import__status { display: inline-block; width: 18px; text-align: center; margin-right: 4px; }
.bulk-import__status a { color: inherit; }

/* Doubled class to outrank main.css's global input[type="text"] box. */
.bulk-import__table .bulk-import__input {
    display: block;
    width: 100%;
    height: auto;
    border: none;
    border-radius: 0;
    box-shadow: none;
    background: transparent;
    padding: 7px var(--space-2);
    font-size: var(--font-size-xs);
    color: var(--color-text-strong);
    outline: none;
}

.bulk-import__input::placeholder { color: var(--color-text-muted); }

.bulk-import__cell:focus-within {
    box-shadow: inset 0 0 0 2px var(--color-blue);
}

.bulk-import__check { margin: 0 auto; display: block; }
.bulk-import__cell[data-cell="anonymous"] { text-align: center; }

.bulk-import__cell.is-invalid {
    background: var(--color-red-tint);
    box-shadow: inset 0 0 0 1px var(--color-red);
}

.bulk-import__row.has-error .bulk-import__status { color: var(--color-danger); }
.bulk-import__row.has-warning .bulk-import__status { color: var(--color-amber); }
.bulk-import__row.is-valid .bulk-import__status { color: var(--color-green); }
.bulk-import__row.is-imported .bulk-import__status { color: var(--color-green); }
.bulk-import__row.is-skipped .bulk-import__status { color: var(--color-text-secondary); }
.bulk-import__row.has-warning td.bulk-import__col-status { box-shadow: inset 3px 0 0 var(--color-amber); }
.bulk-import__row.has-error td.bulk-import__col-status { box-shadow: inset 3px 0 0 var(--color-danger); }
.bulk-import__row.is-valid td.bulk-import__col-status { box-shadow: inset 3px 0 0 var(--color-green); }

.bulk-import__row.is-imported td,
.bulk-import__row.is-skipped td { background: var(--color-bg-faint); }
.bulk-import__row.is-imported .bulk-import__input,
.bulk-import__row.is-skipped .bulk-import__input { color: var(--color-text-secondary); }

.bulk-import__remove {
    border: none;
    background: none;
    color: var(--color-text-muted);
    padding: var(--space-1) var(--space-2);
    border-radius: var(--radius-sm);
    cursor: pointer;
}

.bulk-import__remove:hover:not(:disabled) { color: var(--color-danger); background: var(--color-red-tint); }
.bulk-import__remove:disabled { visibility: hidden; }

.bulk-import__summary {
    padding: var(--space-3) 0;
    font-size: var(--font-size-sm);
    color: var(--color-text-emphasis);
}

.bulk-import__count--error { color: var(--color-danger); font-weight: 600; }
.bulk-import__count--ok { color: var(--color-green-hover); font-weight: 600; }

.bulk-import__options {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding: var(--space-4);
    margin-bottom: var(--space-4);
    background: var(--color-bg-faint);
    border: 1px solid var(--color-border-light);
    border-radius: var(--radius-md);
    font-size: var(--font-size-sm);
}

.bulk-import__options .help-text { margin-top: var(--space-1); }

.bulk-import__progress { margin-bottom: var(--space-4); }
.bulk-import__progress[hidden] { display: none; }

.bulk-import__progress-bar {
    height: 6px;
    background: var(--color-border-light);
    border-radius: 3px;
    overflow: hidden;
}

.bulk-import__progress-bar span {
    display: block;
    height: 100%;
    width: 0;
    background: var(--color-blue);
    transition: width 0.25s;
}

.bulk-import__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
}

.bulk-import__actions .action-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.bulk-import.is-busy .bulk-import__table-wrap { opacity: 0.85; }

/* ==========================================================================
   Site setup on Web Elements (views/web-elements/_site-setup.php, index.php,
   configure.php). The code a website needs once, before any element shows.
   Every class is ss- prefixed and used only by those views.
   ========================================================================== */
.ss-muted { color: var(--color-text-secondary); font-size: 12px; }
.ss-badge {
    display: inline-flex; align-items: center; gap: var(--space-1);
    padding: 2px var(--space-2); border-radius: var(--radius-sm);
    font-size: 12px; font-weight: 500; white-space: nowrap; border: 1px solid transparent;
}
.ss-badge i { font-size: 11px; }
.ss-badge--success { background: var(--color-alert-success-bg); color: var(--color-alert-success-text); border-color: var(--color-alert-success-border); }
.ss-badge--warning { background: var(--color-alert-warning-bg); color: var(--color-alert-warning-text); border-color: var(--color-alert-warning-border); }
.ss-badge--danger { background: var(--color-alert-danger-bg); color: var(--color-alert-danger-text); border-color: var(--color-alert-danger-border); }
.ss-badge--neutral { background: var(--color-bg-light); color: var(--color-text-emphasis); border-color: var(--color-border-light); }

/* Table cells */
.ss-element-icon {
    width: 36px; height: 36px; border-radius: var(--radius-md);
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--color-blue); color: var(--color-text-on-dark);
}
.ss-element-icon--off { background: var(--color-border-light); color: var(--color-text-secondary); }
.ss-name { display: block; font-weight: 500; color: var(--color-text-strong); }
.ss-name__type { display: block; font-size: 12px; color: var(--color-text-secondary); }
.ss-click { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--color-text-secondary); white-space: nowrap; }
.ss-click--popup { color: var(--color-text-default); }
.ss-click i { font-size: 12px; }

/* Banner above the list */
.ss-banner {
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3);
    background: var(--color-bg-surface); border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-lg); padding: var(--space-3) var(--space-4); margin-bottom: var(--space-4);
}
.ss-banner__text { flex: 1; min-width: 220px; margin: 0; font-size: 14px; }
.ss-banner__title { display: block; font-weight: 600; color: var(--color-text-strong); }
.ss-banner__sub { display: block; font-size: 13px; color: var(--color-text-secondary); }
.ss-banner--warn { background: var(--color-alert-warning-bg); border-color: var(--color-alert-warning-border); }
.ss-banner--warn > i { color: var(--color-alert-warning-text); font-size: 16px; }
.ss-banner__form { display: flex; gap: var(--space-2); }
.ss-banner__form .form-control { min-width: 240px; }
.ss-banner__form .btn { white-space: nowrap; }
/* On the list page it sits between the filter card and the table. */
.admin-index > .ss-banner, .admin-index > .ss-invite { margin-top: var(--space-5); margin-bottom: 0; }
.ss-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--color-success); box-shadow: 0 0 0 4px var(--color-alert-success-bg); flex: none; }
.ss-icon-box {
    width: 32px; height: 32px; border-radius: var(--radius-md); flex: none;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--color-blue-tint); color: var(--color-blue);
}

/* One-time invitation */
.ss-invite {
    display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
    background: var(--color-bg-surface); border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-lg); overflow: hidden; margin-bottom: var(--space-4);
}
.ss-invite__main { padding: var(--space-6); display: flex; flex-direction: column; gap: var(--space-4); }
.ss-invite__code { padding: var(--space-6); background: var(--color-bg-light); border-left: 1px solid var(--color-border-light); display: flex; flex-direction: column; gap: var(--space-3); }
.ss-invite__title { margin: 0; font-size: 18px; font-weight: 600; color: var(--color-text-strong); line-height: 1.3; }
.ss-eyebrow { margin: 0; font-size: 12px; font-weight: 600; color: var(--color-blue); }
.ss-steps { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }
.ss-step { display: flex; gap: 10px; font-size: 13px; }
.ss-step strong { display: block; color: var(--color-text-strong); font-weight: 600; }
.ss-step span { color: var(--color-text-secondary); font-size: 12px; }
.ss-num {
    width: 24px; height: 24px; border-radius: 50%; flex: none;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--color-border-mid); background: var(--color-bg-surface);
    font-size: 12px; font-weight: 600; color: var(--color-text-secondary);
}
.ss-num--current { border-color: var(--color-blue); color: var(--color-blue); }
.ss-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }

/* Code boxes */
.ss-code-wrap { position: relative; }
.ss-code {
    display: block; width: 100%; resize: vertical; border: 0; border-radius: var(--radius-md);
    background: var(--color-bg-light); color: var(--color-text-strong);
    font-family: SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px; line-height: 1.6;
    padding: var(--space-3);
    white-space: pre; overflow-x: auto; /* one tag per line, never broken mid-URL */
}
.ss-invite__code .ss-code { background: var(--color-bg-surface); }
.ss-code-wrap { display: flex; flex-direction: column; align-items: flex-end; gap: var(--space-2); }
.ss-code-wrap .ss-copy { white-space: nowrap; }

/* Setup panel (offcanvas) */
.ss-panel.offcanvas { width: 560px; max-width: 100%; }
.ss-panel .offcanvas-header { align-items: flex-start; gap: var(--space-3); border-bottom: 1px solid var(--color-border-light); }
.ss-panel .offcanvas-body { display: flex; flex-direction: column; gap: var(--space-6); }
.ss-section__title { margin: 0; font-size: 14px; font-weight: 600; color: var(--color-text-strong); }
.ss-section__sub { margin: 2px 0 0; font-size: 13px; color: var(--color-text-secondary); }
.ss-part { display: flex; gap: 10px; align-items: flex-start; border: 1px solid var(--color-border-light); border-radius: var(--radius-md); padding: var(--space-3); margin-top: var(--space-2); }
.ss-part > i { color: var(--color-text-secondary); margin-top: 3px; }
.ss-part__body { flex: 1; min-width: 0; font-size: 13px; }
.ss-part__body strong { display: block; color: var(--color-text-strong); font-weight: 500; }
.ss-part__body span { display: block; font-size: 12px; color: var(--color-text-secondary); }
.ss-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.ss-tabs { display: inline-flex; flex-wrap: wrap; gap: 2px; background: var(--color-bg-light); padding: 3px; border-radius: var(--radius-lg); margin-top: var(--space-2); }
.ss-tab { border: 0; background: transparent; font-size: 13px; font-weight: 500; padding: var(--space-1) var(--space-3); border-radius: var(--radius-md); color: var(--color-text-secondary); }
.ss-tab.is-active { background: var(--color-bg-surface); color: var(--color-text-strong); box-shadow: var(--shadow-card-strong); }
.ss-guide ol { margin: var(--space-3) 0 0; padding-left: var(--space-5); font-size: 13px; }
.ss-guide ol li { margin-bottom: 6px; }
.ss-guide__body { margin: var(--space-3) 0 0; font-size: 13px; }
.ss-guide__notes { margin: var(--space-3) 0 0; padding-left: var(--space-4); font-size: 12px; color: var(--color-text-secondary); }
.ss-check-form { display: flex; gap: var(--space-2); margin-top: 10px; }
.ss-result { border: 1px solid var(--color-border-light); border-radius: var(--radius-md); margin-top: var(--space-3); }
.ss-result__row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding: var(--space-2) var(--space-3); font-size: 13px; }
.ss-result__row + .ss-result__row { border-top: 1px solid var(--color-border-light); }
.ss-result__error { margin: var(--space-3) 0 0; font-size: 13px; color: var(--color-danger); }
.ss-mailbox { display: flex; align-items: center; gap: var(--space-3); background: var(--color-bg-light); border-radius: var(--radius-md); padding: var(--space-3); font-size: 13px; }
.ss-mailbox span { flex: 1; }
.ss-callout { display: flex; gap: 10px; align-items: flex-start; border: 1px solid var(--color-border-light); border-radius: var(--radius-md); padding: var(--space-3); font-size: 13px; }
.ss-callout--ok { background: var(--color-alert-success-bg); border-color: var(--color-alert-success-border); }

/* "Also uses your site setup" */
.ss-also { margin-top: var(--space-8); }
.ss-also__title { margin: 0; font-size: 16px; font-weight: 600; color: var(--color-text-strong); }
.ss-also__grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); margin-top: var(--space-3); }
.ss-also__card { display: flex; gap: var(--space-3); align-items: flex-start; background: var(--color-bg-surface); border: 1px solid var(--color-border-subtle); border-radius: var(--radius-lg); padding: var(--space-4); }
.ss-also__card div { flex: 1; min-width: 0; font-size: 13px; color: var(--color-text-secondary); }
.ss-also__card strong { display: block; font-size: 14px; color: var(--color-text-strong); }

/* Configure: "Put it on your site" */
.ss-code-steps { list-style: none; margin: 0; padding: 0; }
.ss-code-step { display: grid; grid-template-columns: 24px minmax(0, 1fr); gap: var(--space-3); padding: var(--space-4) 0; }
.ss-code-step + .ss-code-step { border-top: 1px dashed var(--color-border-mid); }
.ss-code-head { display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-1); }
.ss-code-head h5 { flex: 1; margin: 0; }

@media (max-width: 991px) {
    .ss-invite { grid-template-columns: 1fr; }
    .ss-invite__code { border-left: 0; border-top: 1px solid var(--color-border-light); }
    .ss-also__grid, .ss-steps { grid-template-columns: 1fr; }
    .ss-banner__form { width: 100%; }
    .ss-banner__form .form-control { min-width: 0; flex: 1; }
}

/* ── Report builder modal (views/reports/_builder-modal.php, js/report-builder.js) ── */

/* A workspace-sized dialog with a fixed height, so the settings and the
   preview each scroll on their own instead of the whole modal scrolling. */
.sg-modal.report-builder-modal .report-builder-modal__dialog {
    max-width: min(1280px, calc(100vw - var(--space-8)));
}
.sg-modal.report-builder-modal .report-builder-modal__content {
    height: min(880px, calc(100vh - var(--space-8)));
}
.sg-modal.report-builder-modal .report-builder-modal__body {
    display: flex;
    flex-direction: column;
    min-height: 0;
    padding: 0;
    overflow: hidden;
}
.sg-modal.report-builder-modal .report-builder-modal__body > *:first-child { margin-top: 0; }
.report-builder-modal__footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--space-3);
}
.report-builder-modal__actions {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-left: auto;
}
.report-builder-modal__actions[hidden] { display: none; }
.report-builder-modal__discard { font-weight: 500; color: var(--color-text-strong); }

.report-builder__workspace {
    flex: 1 1 auto;
    min-height: 0;
    display: grid;
    grid-template-columns: minmax(300px, 360px) minmax(0, 1fr);
}
.report-builder__settings {
    min-height: 0;
    overflow-y: auto;
    border-right: 1px solid var(--color-border-light);
    background: var(--color-bg-faint);
}
.report-builder__preview {
    min-width: 0;
    min-height: 0;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    transition: opacity 0.15s;
}
.report-builder__preview.is-busy > :not(.report-builder__preview-head) { opacity: 0.55; }

.report-builder__tabs { display: none; }

.report-builder__loading {
    margin: auto;
    padding: var(--space-10);
    display: flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--color-text-secondary);
}

.report-builder__section {
    padding: var(--space-4) var(--space-5);
    border-bottom: 1px solid var(--color-border-light);
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}
.report-builder__section:last-child { border-bottom: none; }
.report-builder__step {
    margin: 0;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--color-text-emphasis);
}
.report-builder__field .form-label { margin-bottom: var(--space-1); font-size: var(--font-size-sm); font-weight: 500; }
.report-builder__hint { margin: 0; font-size: var(--font-size-xs); color: var(--color-text-secondary); }
.report-builder__choices { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.report-builder__choice {
    padding: 6px var(--space-3);
    border: 1px solid var(--color-border);
    border-radius: 999px;
    background: var(--color-bg-surface);
    color: var(--color-text-default);
    font-size: var(--font-size-sm);
    cursor: pointer;
}
.report-builder__choice:hover { border-color: var(--color-border-hover); }
.report-builder__choice[aria-pressed="true"] {
    background: var(--color-goal-accent-tint);
    border-color: var(--color-goal-accent);
    color: var(--color-goal-accent);
    font-weight: 600;
}
.report-builder__checks,
.report-builder__values {
    margin: 0;
    padding: 0;
    border: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.report-builder__checks .form-label { margin-bottom: var(--space-1); font-size: var(--font-size-sm); font-weight: 500; }
.report-builder__values {
    max-height: 168px;
    overflow-y: auto;
    padding: var(--space-1) var(--space-2);
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
}
.report-builder__check {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0;
    padding: 3px 0;
    font-size: var(--font-size-sm);
    font-weight: 400;
    cursor: pointer;
}
.report-builder__check .form-check-input { margin: 0; flex: none; }
.report-builder__filter {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: var(--space-2);
    padding: var(--space-2);
    background: var(--color-bg-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
}
.report-builder__filter-fields { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.report-builder__filter-remove {
    align-self: start;
    border: none;
    background: none;
    color: var(--color-text-secondary);
    font-size: 18px;
    line-height: 1;
    padding: 2px 6px;
    border-radius: var(--radius-sm);
    cursor: pointer;
}
.report-builder__filter-remove:hover { color: var(--color-danger); background: var(--color-bg-light); }
.report-builder__add {
    align-self: flex-start;
    border: 1px dashed var(--color-border-hover);
    background: var(--color-bg-surface);
    color: var(--color-link);
    border-radius: var(--radius-md);
    padding: 6px var(--space-3);
    font-size: var(--font-size-sm);
    cursor: pointer;
}
.report-builder__row { display: flex; gap: var(--space-2); }
.report-builder__row > * { flex: 1 1 0; min-width: 0; }

.report-builder__preview-head {
    position: sticky;
    top: 0;
    z-index: 2;
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-5);
    background: var(--color-bg-surface);
    border-bottom: 1px solid var(--color-border-light);
}
.report-builder__preview-title { margin: 0; font-size: var(--font-size-base); font-weight: 600; color: var(--color-text-strong); }
.report-builder__status { font-size: var(--font-size-xs); color: var(--color-text-secondary); }
.report-builder__status--error { color: var(--color-error-text); }
.report-builder__message {
    margin: var(--space-4) var(--space-5) 0;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-md);
    background: var(--color-bg-light);
    font-size: var(--font-size-sm);
    color: var(--color-text-emphasis);
}
.report-builder__message--error {
    background: var(--color-error-bg);
    border: 1px solid var(--color-error-border);
    color: var(--color-error-text);
}
.report-builder__stats {
    margin: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    border-bottom: 1px solid var(--color-border-light);
}
.report-builder__stat { padding: var(--space-4) var(--space-5); border-right: 1px solid var(--color-border-light); }
.report-builder__stat:last-child { border-right: none; }
.report-builder__stat-label { font-size: var(--font-size-xs); font-weight: 400; color: var(--color-text-secondary); }
.report-builder__stat-value { margin: var(--space-1) 0 0; font-size: 22px; font-weight: 600; color: var(--color-text-strong); }
.report-builder__chart { position: relative; flex: none; height: 300px; padding: var(--space-4) var(--space-5); }
.report-builder__table-wrap { flex: none; overflow-x: auto; }
.report-builder__table { width: 100%; border-collapse: collapse; font-size: var(--font-size-sm); }
.report-builder__table th {
    position: sticky;
    top: 0;
    background: var(--color-bg-faint);
    color: var(--color-text-emphasis);
    font-weight: 600;
    text-align: left;
    padding: var(--space-2) var(--space-4);
    border-bottom: 1px solid var(--color-border);
    white-space: nowrap;
}
.report-builder__table td { padding: var(--space-2) var(--space-4); border-bottom: 1px solid var(--color-border-light); }
.report-builder__table tfoot td {
    font-weight: 600;
    color: var(--color-text-strong);
    background: var(--color-bg-faint);
    border-top: 2px solid var(--color-border);
    border-bottom: none;
}
.report-builder__table .is-num { text-align: right; font-variant-numeric: tabular-nums; }
/* A row that opens a record is a link in every cell, so the whole row clicks. */
.report-builder__table tbody tr.is-linked { cursor: pointer; }
.report-builder__table tbody tr.is-linked:hover td { background: var(--color-bg-faint); }
.report-builder__table tbody tr.is-linked td { padding: 0; }
.report-builder__row-link { display: block; padding: var(--space-2) var(--space-4); color: inherit; text-decoration: none; }
.report-builder__row-link:hover { color: inherit; text-decoration: none; }
.report-builder__sort {
    border: none;
    background: none;
    color: inherit;
    font: inherit;
    padding: 0;
    cursor: pointer;
    white-space: nowrap;
}
.report-builder__table-note { margin: 0; padding: var(--space-3) var(--space-5); font-size: var(--font-size-xs); color: var(--color-text-secondary); }
.report-builder__empty { padding: var(--space-10) var(--space-5); text-align: center; color: var(--color-text-secondary); }

/* Phone width: full-screen dialog, one pane at a time behind tabs. */
@media (max-width: 767.98px) {
    .sg-modal.report-builder-modal .report-builder-modal__dialog { max-width: none; margin: 0; }
    .sg-modal.report-builder-modal .report-builder-modal__content { height: 100dvh; border-radius: 0; }
    .report-builder__tabs {
        display: flex;
        flex: none;
        border-bottom: 1px solid var(--color-border-light);
    }
    .report-builder__tab {
        flex: 1 1 0;
        padding: var(--space-3);
        border: none;
        border-bottom: 2px solid transparent;
        background: none;
        font-weight: 500;
        color: var(--color-text-secondary);
    }
    .report-builder__tab[aria-selected="true"] { color: var(--color-text-strong); border-bottom-color: var(--color-goal-accent); }
    .report-builder__workspace { grid-template-columns: minmax(0, 1fr); }
    .report-builder__settings { border-right: none; }
    [data-pane="settings"] .report-builder__preview,
    [data-pane="preview"] .report-builder__settings { display: none; }
    .report-builder-modal__footer .report-builder__status { display: none; }
}

/* ── A saved builder report's table (views/reports/custom-report.php) ───── */

/* main.css makes every .table display:block (a sideways-scroll hack) and
   paints every .table th navy; the fixed reports undo the first inline. */
.table.report-table { display: table; width: 100%; }
.report-table tbody tr[data-href] { cursor: pointer; }
.report-table tfoot tr {
    /* main.css forces every .table td to `background: inherit !important`,
       so the total row's tint goes on the row. */
    background: var(--color-bg-faint);
}
.report-table tfoot td {
    /* Bootstrap paints cells with an inset box-shadow of --bs-table-bg, and
       DataTables' separate borders drop a cell's border-top: draw the rule
       above the total as an inset shadow instead. */
    --bs-table-bg: transparent;
    box-shadow: inset 0 2px 0 var(--color-border);
    font-weight: 600;
    color: var(--color-text-strong);
    border-bottom: none;
}
.report-builder__chart-card { padding: var(--space-4) var(--space-5); }
.report-builder__chart-card .report-builder__chart { padding: 0; }
