/* ── Table column headers ────────────────────────────────── */

.capstone-grid thead th,
.datagrid-sticky-header th,
.datagrid-toolbar + .table-responsive th,
.datagrid-toolbar + div + .table-responsive th {
    white-space: nowrap;
}

/* ── Data cells (no-wrap — keeps columns at their declared width and enables horizontal scroll) ── */

.capstone-grid tbody td,
.datagrid-toolbar + .table-responsive td,
.datagrid-toolbar + div + .table-responsive td {
    white-space: nowrap;
    cursor: default;
}

/* Copyable cells — stamped with td-copyable at render time (capstone-grid) or
   via tbody.tbody-copyable for standalone enableClipboardCopy usage. */
.capstone-grid tbody td.td-copyable,
tbody.tbody-copyable td {
    cursor: pointer;
}

/* ── Column headers ──────────────────────────────────────── */

.capstone-grid thead th {
    cursor: default;
    user-select: none;
    /* ReSharper disable once CssNotResolved */
    background-color: var(--bs-secondary-bg);
}

.capstone-grid thead th.sortable {
    cursor: pointer;
}

/* Sortable header trigger — focusable button with no visible chrome.
   Lives inside the .d-flex; expands to fill so the filter button (when present) sits on the right. */
.capstone-grid-sort-btn {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    background: none;
    border: 0;
    padding: 0;
    color: inherit;
    font: inherit;
    text-align: inherit;
    cursor: pointer;
}

.capstone-grid-sort-btn > span {
    flex-grow: 1;
    overflow: hidden;
    text-overflow: ellipsis;
}

.capstone-grid-sort-btn:focus-visible,
button.filter-icon:focus-visible {
    /* ReSharper disable once CssNotResolved */
    outline: 2px solid var(--bs-primary);
    outline-offset: 2px;
    border-radius: 2px;
}

/* Filter trigger button reset — keep the bi pseudo-glyph rendering identical to the old <i>. */
button.filter-icon {
    background: none;
    border: 0;
    padding: 0;
    line-height: 1;
}

/* ── Sort icon in table headers ─────────────────────────── */

.sort-icon {
    flex-shrink: 0;
    margin-left: 0.35rem;
    font-size: 0.75em;
    /* ReSharper disable once CssNotResolved */
    color: var(--bs-secondary-color);
    /* No opacity dimming — secondary-color alone meets WCAG 1.4.11 (3:1 for UI components).
       Layering opacity on top dropped contrast under the bar; the active state is still
       distinct via the color-token swap (emphasis-color) and the icon glyph swap. */
}

    .sort-icon.sort-icon-active {
        /* ReSharper disable once CssNotResolved */
        color: var(--bs-emphasis-color);
    }

/* ── Filter icon in table headers ───────────────────────── */

.filter-icon {
    cursor: pointer;
    margin-left: 0.5rem;
    font-size: 0.75em;
    /* ReSharper disable once CssNotResolved */
    color: var(--bs-secondary-color);
    /* See .sort-icon — no opacity dimming so we stay above WCAG 1.4.11. */
}

    .filter-icon.active {
        /* ReSharper disable once CssNotResolved */
        color: var(--bs-emphasis-color);
    }

/* ── DataGrid toolbar (top) ─────────────────────────────── */

.datagrid-toolbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--bs-border-color);
    /* ReSharper disable CssNotResolved */
    border-radius: var(--bs-border-radius) var(--bs-border-radius) 0 0;
    /* ReSharper restore CssNotResolved */
    /* ReSharper disable once CssNotResolved */
    background-color: var(--bs-secondary-bg);
    min-height: 42px;
}

/* ── DataGrid footer (bottom) ───────────────────────────── */

/* Remove border-radius from tables between toolbar and footer */
.datagrid-toolbar + .table-responsive .table,
.datagrid-toolbar + div + .table-responsive .table {
    border-radius: 0;
}

/* Vertical side lines on the table wrapper so the toolbar and footer borders
   visually connect through the middle of the grid. */
.capstone-grid .table-responsive,
.datagrid-toolbar + .table-responsive,
.datagrid-toolbar + div + .table-responsive {
    border-left: 1px solid var(--bs-border-color);
    border-right: 1px solid var(--bs-border-color);
}

/* Top border and rounded top corners when the grid has no toolbar. */
.capstone-grid:not(:has(> .datagrid-toolbar)) .table-responsive {
    border-top: 1px solid var(--bs-border-color);
    /* ReSharper disable CssNotResolved */
    border-radius: var(--bs-border-radius) var(--bs-border-radius) 0 0;
    /* ReSharper restore CssNotResolved */
}

/* When the inner table uses Bootstrap's .table-bordered, the outer cell borders
   already form the side line — skip the wrapper borders to avoid doubling up. */
.capstone-grid .table-responsive:has(> .table-bordered),
.datagrid-toolbar + .table-responsive:has(> .table-bordered),
.datagrid-toolbar + div + .table-responsive:has(> .table-bordered) {
    border-left: none;
    border-right: none;
}

.datagrid-footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--bs-border-color);
    border-top: none;
    /* ReSharper disable CssNotResolved */
    border-radius: 0 0 var(--bs-border-radius) var(--bs-border-radius);
    background-color: var(--bs-secondary-bg);
    min-height: 42px;
}

.datagrid-footer .pagination {
    margin-bottom: 0;
}

.datagrid-footer .page-link {
    padding: 0.25rem 0.5rem;
    font-size: 0.85rem;
}

.datagrid-footer .page-link-jump {
    color: var(--bs-secondary-color);
    letter-spacing: 0.05em;
}

.datagrid-footer-right {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.85rem;
    color: var(--bs-primary);
    /* Always pin to the right, even when there's no left-side (pagination) sibling */
    margin-left: auto;
}

/* ── Scrollable grid with sticky header ────────────────── */

.datagrid-sticky-header thead th {
    position: sticky;
    top: 0;
    z-index: 2;
}

/* ── Sticky columns (sticky="left" / sticky="right" on <grid-column>) ─── */

.capstone-grid th.sticky-left,
.capstone-grid td.sticky-left,
.capstone-grid th.sticky-right,
.capstone-grid td.sticky-right {
    position: sticky;
    z-index: 1;
    background-color: var(--bs-body-bg);
}

.capstone-grid th.sticky-left,
.capstone-grid td.sticky-left {
    left: 0;
    /* ReSharper disable once CssNotResolved */
    box-shadow: 2px 0 6px color-mix(in srgb, var(--bs-body-color) 18%, transparent);
}

.capstone-grid th.sticky-right,
.capstone-grid td.sticky-right {
    right: 0;
    /* ReSharper disable once CssNotResolved */
    box-shadow: -2px 0 6px color-mix(in srgb, var(--bs-body-color) 18%, transparent);
}

/* Header cells need higher z-index so sticky headers (max-height mode) layer above sticky columns.
   Also restore secondary-bg — the sticky column base rule sets body-bg on all th/td. */
.capstone-grid thead th.sticky-left,
.capstone-grid thead th.sticky-right {
    z-index: 3;
    background-color: var(--bs-secondary-bg);
}

/* Preserve table-striped zebra pattern on sticky cells.
   Bootstrap's --bs-table-striped-bg is semi-transparent (e.g. rgba(0,0,0,0.05)), so setting it
   as background-color alone makes the cell see-through. Layer it over the opaque body bg instead. */
.capstone-grid .table-striped > tbody > tr:nth-of-type(odd) > td.sticky-left,
.capstone-grid .table-striped > tbody > tr:nth-of-type(odd) > td.sticky-right {
    background-color: var(--bs-body-bg);
    /* ReSharper disable once UnexpectedValue */
    background-image: linear-gradient(var(--bs-table-striped-bg), var(--bs-table-striped-bg));
}

/* Preserve hover highlight on sticky cells — same layering approach */
.capstone-grid .table-hover > tbody > tr:hover > td.sticky-left,
.capstone-grid .table-hover > tbody > tr:hover > td.sticky-right {
    background-color: var(--bs-body-bg);
    /* ReSharper disable once UnexpectedValue */
    background-image: linear-gradient(var(--bs-table-hover-bg), var(--bs-table-hover-bg));
}

/* ── Loading overlay (shown while read-url fetch / setLoading(true) is active) ── */

/* table-responsive needs to be the positioning ancestor for the overlay. */
.capstone-grid .table-responsive {
    position: relative;
}

.capstone-grid-loading-overlay {
    position: absolute;
    /* Top offset is set by JS (capstone-grid.js setLoading) to the thead's
       offsetHeight so the dots center against the tbody area only, not the
       whole table including the header. */
    top: var(--capstone-grid-thead-h, 0);
    right: 0;
    bottom: 0;
    left: 0;
    display: none;
    align-items: center;
    justify-content: center;
    /* ReSharper disable once InvalidValue */
    background-color: color-mix(in srgb, var(--bs-body-bg) 92%, transparent);
    z-index: 4;
    pointer-events: none;
}

/* Guarantee a visible data area while loading so the dots don't squash into
   a sliver when the tbody is empty (e.g. setData([]) was just called). */
.capstone-grid[data-loading="true"] .table-responsive {
    min-height: calc(var(--capstone-grid-thead-h, 0) + 6rem);
}

/* Hide tbody contents while loading. Covers the in-tbody "No Data Available."
   row that table-utilities renders for empty data, and stops existing rows
   from bleeding through the overlay. visibility (not display) keeps the
   tbody's intrinsic height so layout doesn't jump. */
.capstone-grid[data-loading="true"] tbody {
    visibility: hidden;
}

/* Container's data-loading attribute is set by CapstoneGrid.setLoading() —
   read() flips it around the fetch, consumers can flip it manually for setData() flows. */
.capstone-grid[data-loading="true"] .capstone-grid-loading-overlay {
    display: flex;
}

/* Suppress the empty-state message while loading — the dots already explain
   why the table is empty; showing both is contradictory. */
.capstone-grid[data-loading="true"] > [id$="-no-data"] {
    display: none !important;
}

/* Five-dot pulsating indicator inside the overlay. Each dot fades in opacity
   while its background-color cycles through btn-primary → btn-secondary →
   the SRU accent green (#6cc24a). With staggered animation delays, the five
   dots show different colors mid-cycle so the indicator looks like a wave. */
.capstone-grid-loading-dots {
    display: inline-flex;
    align-items: center;
    gap: 0.625rem;
}

.capstone-grid-loading-dots > span[aria-hidden="true"] {
    width: 1rem;
    height: 1rem;
    /* ReSharper disable once CssNotResolved */
    background-color: var(--bs-primary, #006633);
    border-radius: 50%;
    opacity: 0.25;
    animation: capstone-grid-loading-dot 1.7s ease-in-out infinite;
}

.capstone-grid-loading-dots > span[aria-hidden="true"]:nth-child(2) {
    animation-delay: 0.16s;
}

.capstone-grid-loading-dots > span[aria-hidden="true"]:nth-child(3) {
    animation-delay: 0.32s;
}

.capstone-grid-loading-dots > span[aria-hidden="true"]:nth-child(4) {
    animation-delay: 0.48s;
}

.capstone-grid-loading-dots > span[aria-hidden="true"]:nth-child(5) {
    animation-delay: 0.64s;
}

@keyframes capstone-grid-loading-dot {
    /* ReSharper disable CssNotResolved */
    0%   { opacity: 0.25; background-color: var(--bs-primary, #006633); }
    20%  { opacity: 1;    background-color: var(--bs-primary, #006633); }
    42%  { opacity: 1;    background-color: var(--bs-secondary, #6c757d); }
    63%  { opacity: 1;    background-color: #6cc24a; }
    85%  { opacity: 1;    background-color: #8BD3E6; }
    100% { opacity: 0.25; background-color: var(--bs-primary, #006633); }
    /* ReSharper restore CssNotResolved */
}

/* ── Clipboard toast countdown bar ──────────────────────── */

.toast-timer-bar {
    height: 4px;
    background: #ffffff;
    background: rgba(255, 255, 255, 0.7);
    width: 100%;
    animation: toast-timer 2s linear forwards;
}

@keyframes toast-timer {
    from { width: 0; }
    to { width: 100%; }
}

/* ── Responsive grid (small screens) ───────────────────── */

@media (max-width: 575.98px) {
    /* Give wrapped rows breathing room — column gap is already set, add row gap */
    .datagrid-toolbar,
    .datagrid-footer {
        row-gap: 0.5rem;
    }

    /* Let pagination page buttons wrap within the pagination <ul> instead of overflowing */
    .datagrid-footer .pagination {
        flex-wrap: wrap;
    }

    .datagrid-footer .page-link {
        padding: 0.375rem 0.625rem;
        font-size: 0.9rem;
    }
}
