/* DataTables in Industrial Precision (issue #164).
   ════════════════════════════════════════════════
   DataTables 1.13 arrives from cdn.datatables.net with its own complete look: grey sort sprites,
   blue #0d6efd-ish pagination pills, a bordered box, its own type scale. Six screens already use
   it, so the portal has been showing two different table designs — `.admin-table` everywhere else
   and DataTables' factory styling on /users/list, /admin/images and /content/contents.

   This file makes a DataTables grid read as the SAME component as `.admin-table`, so an async grid
   and a server-rendered table can sit on the same screen without looking like two products.

   Written entirely against the --surface-* semantic tokens from theme-surfaces.css, which is why
   there is not one [data-bs-theme="dark"] rule below: a component written against those names is
   correct on either surface and in dark mode with no second rule (Styles/README.md §2). It also
   keeps theme-dark.css the last stylesheet loaded, which DarkModeTests pins.

   SPECIFICITY. DataTables' own selectors are things like `table.dataTable thead th` (0,1,3) and
   `.dataTables_wrapper .dataTables_paginate .paginate_button` (0,3,0), and its stylesheet loads
   from the CDN at the top of <head> — before this file. Load order alone would settle ties, but
   these rules use a doubled class (`table.dataTable.admin-table`) so they win outright rather than
   by a hair, because a future reordering of _Layout must not silently revert the theme. The wrapper
   rules are NOT scoped to `.admin-panel`: the ticket lists are customer-facing and sit in
   `.cp-table-wrap` rather than a panel, and a grid should look the same wherever it is.

   Plain CSS, not SCSS, for the reason the whole wwwroot/css directory exists: the Dart Sass step
   runs under ContinueOnError and Node is not installed, so a rule added to Styles/**.scss may
   never reach a browser. Do not name this file in Main.scss — tests assert its absence there by
   substring. */

/* ── The table itself ───────────────────────────────────────────────────────── */
/* Mirrors .admin-table. Doubled class beats DataTables' `table.dataTable` at (0,2,1). */

table.dataTable.cp-table,
table.dataTable.admin-table {
    /* !important beats the inline width DataTables writes onto the table when it measures columns.
       Without it the grid keeps whatever pixel width its content wanted and overflows the panel. */
    width: 100% !important;
    max-width: 100%;
    table-layout: auto;
    border-collapse: collapse;
    font-size: .9rem;
    margin: 0 !important; /* DataTables sets margin on the table; the panel owns spacing here. */
    color: var(--surface-ink);
    border: none;
}

/* Long unbroken strings — an email address, a role name, a file name — must break rather than set
   a floor under the table's width. This is what lets table-layout: auto actually fit the panel. */
table.dataTable.cp-table tbody td,
table.dataTable.admin-table tbody td {
    overflow-wrap: anywhere;
    word-break: break-word;
}

/* …but a date is not a long string, it is one value, and breaking it renders "10/10/2 024".
   Short atomic values opt out of the break above. */
table.dataTable.cp-table th.dt-col-date,
table.dataTable.admin-table th.dt-col-date,
table.dataTable.cp-table td.dt-col-date,
table.dataTable.admin-table td.dt-col-date {
    white-space: nowrap;
    overflow-wrap: normal;
    word-break: normal;
}

/* DataTables draws its own row borders and a wrapper border. The Industrial look is a single
   hairline per row and nothing around the outside. */
table.dataTable.cp-table,
table.dataTable.admin-table,
table.dataTable.cp-table tbody,
table.dataTable.admin-table tbody,
table.dataTable.cp-table thead,
table.dataTable.admin-table thead {
    border: none;
}

table.dataTable.cp-table thead th,
table.dataTable.admin-table thead th,
table.dataTable.cp-table thead td,
table.dataTable.admin-table thead td {
    background: var(--surface-2);
    color: var(--surface-muted);
    font-size: .78rem;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    padding: 10px 14px;
    border-bottom: 1px solid var(--surface-rule);
    border-top: none;
    text-align: left;

    /* Headers WRAP. They were `nowrap`, which — with seven columns, an email address and a date —
       forced the table wider than its panel, so the page scrolled sideways and the last column's
       buttons ended up unreachable off-screen. A grid must fit the screen it is on. */
    white-space: normal;
}

table.dataTable.cp-table tbody tr,
table.dataTable.admin-table tbody tr {
    background: transparent;
    border-bottom: 1px solid var(--surface-rule);
    transition: background .15s;
}

table.dataTable.cp-table tbody tr:last-child,
table.dataTable.admin-table tbody tr:last-child {
    border-bottom: none;
}

table.dataTable.cp-table tbody tr:hover,
table.dataTable.admin-table tbody tr:hover {
    background: var(--surface-hover);
}

table.dataTable.cp-table tbody td,
table.dataTable.admin-table tbody td {
    padding: 12px 20px;
    color: var(--surface-ink);
    vertical-align: middle;
    background: transparent;
    border-top: none;
}


/* Row-click navigation is the house behaviour on these grids (TicketListModule, Users/Index), so
   the cursor has to say the row is a target. */
table.dataTable.cp-table.cp-table--rowlink tbody tr,
table.dataTable.admin-table.admin-table--rowlink tbody tr {
    cursor: pointer;
}

/* ── Sort indicators ───────────────────────────────────────────────────────── */
/* DataTables 1.13 paints these as background-image sprites in a fixed grey, which is invisible on
   the navy-tinted header band in dark mode. Replaced with text carets in currentColor, so they
   follow --surface-muted on both surfaces. */

table.dataTable.cp-table thead th.sorting,
table.dataTable.admin-table thead th.sorting,
table.dataTable.cp-table thead th.sorting_asc,
table.dataTable.admin-table thead th.sorting_asc,
table.dataTable.cp-table thead th.sorting_desc,
table.dataTable.admin-table thead th.sorting_desc,
table.dataTable.cp-table thead th.sorting_asc_disabled,
table.dataTable.admin-table thead th.sorting_asc_disabled,
table.dataTable.cp-table thead th.sorting_desc_disabled,
table.dataTable.admin-table thead th.sorting_desc_disabled {
    background-image: none !important;
    padding-right: 30px;
    position: relative;
    cursor: pointer;
}

table.dataTable.cp-table thead th.sorting::after,
table.dataTable.admin-table thead th.sorting::after,
table.dataTable.cp-table thead th.sorting_asc::after,
table.dataTable.admin-table thead th.sorting_asc::after,
table.dataTable.cp-table thead th.sorting_desc::after,
table.dataTable.admin-table thead th.sorting_desc::after {
    position: absolute;
    right: 12px;
    top: 50%;
    transform: translateY(-50%);
    font-size: .7rem;
    line-height: 1;
    opacity: .45;
    color: currentColor;
}

table.dataTable.cp-table thead th.sorting::after,
table.dataTable.admin-table thead th.sorting::after       { content: "\2195"; } /* up-down arrow */
table.dataTable.cp-table thead th.sorting_asc::after,
table.dataTable.admin-table thead th.sorting_asc::after   { content: "\2191"; opacity: 1; }
table.dataTable.cp-table thead th.sorting_desc::after,
table.dataTable.admin-table thead th.sorting_desc::after  { content: "\2193"; opacity: 1; }

/* The sorted column's header reads as active rather than merely arrowed. */
table.dataTable.cp-table thead th.sorting_asc,
table.dataTable.admin-table thead th.sorting_asc,
table.dataTable.cp-table thead th.sorting_desc,
table.dataTable.admin-table thead th.sorting_desc {
    color: var(--surface-ink);
}

table.dataTable.cp-table thead th.sorting:hover,
table.dataTable.admin-table thead th.sorting:hover {
    color: var(--surface-ink);
}

/* Keyboard focus must be visible: these headers are interactive. */
table.dataTable.cp-table thead th:focus-visible,
table.dataTable.admin-table thead th:focus-visible {
    outline: 2px solid var(--surface-link);
    outline-offset: -2px;
}

/* ── The Select extension ──────────────────────────────────────────────────── */
/* Its own CSS fills a selected row with a blue that is neither of our accents. */

table.dataTable.cp-table tbody tr.selected,
table.dataTable.admin-table tbody tr.selected,
table.dataTable.cp-table tbody tr.selected td,
table.dataTable.admin-table tbody tr.selected td,
table.dataTable.cp-table tbody > tr.selected > *,
table.dataTable.admin-table tbody > tr.selected > * {
    background: var(--surface-hover) !important;
    color: var(--surface-ink) !important;
    box-shadow: none !important;
}

/* Left edge marker, so selection is not carried by a faint tint alone — it is the same accent the
   rest of the app uses for "this one". */
table.dataTable.cp-table tbody tr.selected td:first-child,
table.dataTable.admin-table tbody tr.selected td:first-child {
    box-shadow: inset 3px 0 0 0 var(--accent) !important;
}

/* ── The wrapper controls ──────────────────────────────────────────────────── */
/* Length menu, search box, info line and pagination. Applies to every DataTables grid, panel or
   not: /tickets and /cx-tickets are customer-facing and sit in .cp-table-wrap, and the whole point
   of this file is that there is ONE table design rather than two. */

.admin-panel .dataTables_wrapper,
.cp-table-wrap .dataTables_wrapper {
    padding: 0;
    color: var(--surface-ink);

    /* A wide grid scrolls INSIDE the panel, never by pushing the page sideways.
       `.admin-panel` is `overflow-x: hidden`, so without this a table wider than the panel is
       clipped at the panel edge AND the document scrolls horizontally to reach it — the last
       columns end up unreachable without scrolling the whole page, which is how the /my-team
       actions column lost its Reset and Archive buttons off-screen. Measured: an 1094px table in
       a 912px panel took the document to 1427px against a 1052px viewport. */
    overflow-x: auto;
}

/* The control rows get panel padding; the TABLE stays flush to the panel edge, which is the
   Industrial rule that a header strip and a table both run edge to edge while prose is inset. */
.admin-panel .dataTables_wrapper .dataTables_length,
.cp-table-wrap .dataTables_wrapper .dataTables_length,
.admin-panel .dataTables_wrapper .dataTables_filter,
.cp-table-wrap .dataTables_wrapper .dataTables_filter,
.admin-panel .dataTables_wrapper .dataTables_info,
.cp-table-wrap .dataTables_wrapper .dataTables_info,
.admin-panel .dataTables_wrapper .dataTables_paginate,
.cp-table-wrap .dataTables_wrapper .dataTables_paginate {
    padding: 12px 20px;
    color: var(--surface-muted);
    font-size: .85rem;
}

.admin-panel .dataTables_wrapper .dataTables_length,
.cp-table-wrap .dataTables_wrapper .dataTables_length,
.admin-panel .dataTables_wrapper .dataTables_filter,
.cp-table-wrap .dataTables_wrapper .dataTables_filter {
    border-bottom: 1px solid var(--surface-rule);
}

.admin-panel .dataTables_wrapper .dataTables_info,
.cp-table-wrap .dataTables_wrapper .dataTables_info,
.admin-panel .dataTables_wrapper .dataTables_paginate,
.cp-table-wrap .dataTables_wrapper .dataTables_paginate {
    border-top: 1px solid var(--surface-rule);
}

/* Its inputs and selects, given the Bootstrap form control shape the rest of the panel uses.
   Inside a panel body Bootstrap is correct as authored (Styles/README.md §4) -- but DataTables
   injects these elements itself with no Bootstrap classes on them, so the shape has to be
   restated here rather than added to the markup. */
.admin-panel .dataTables_wrapper .dataTables_filter input,
.cp-table-wrap .dataTables_wrapper .dataTables_filter input,
.admin-panel .dataTables_wrapper .dataTables_length select,
.cp-table-wrap .dataTables_wrapper .dataTables_length select {
    background-color: var(--surface-1);
    color: var(--surface-ink);
    border: 1px solid var(--surface-rule);
    border-radius: .375rem;
    padding: .25rem .5rem;
    font-size: .85rem;
    margin-left: .5rem;
    min-height: 31px;
}

.admin-panel .dataTables_wrapper .dataTables_filter input::placeholder,
.cp-table-wrap .dataTables_wrapper .dataTables_filter input::placeholder {
    color: var(--surface-muted);
    opacity: .8;
}

.admin-panel .dataTables_wrapper .dataTables_filter input:focus,
.cp-table-wrap .dataTables_wrapper .dataTables_filter input:focus,
.admin-panel .dataTables_wrapper .dataTables_length select:focus,
.cp-table-wrap .dataTables_wrapper .dataTables_length select:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 .2rem rgba(61, 184, 245, 0.25);
}

/* ── Pagination ────────────────────────────────────────────────────────────── */
/* DataTables' buttons carry inline-ish gradients and a blue active fill. The active page uses
   --accent as a FILL with navy text, which is the one correct use of that token: it is 2.24:1 as
   text on white and must never be text on a light surface. */

.admin-panel .dataTables_wrapper .dataTables_paginate .paginate_button,
.cp-table-wrap .dataTables_wrapper .dataTables_paginate .paginate_button {
    background: transparent !important;
    border: 1px solid var(--surface-rule) !important;
    border-radius: .375rem;
    color: var(--surface-link) !important;
    padding: .2rem .55rem;
    margin: 0 2px;
    font-size: .85rem;
    box-shadow: none !important;
}

.admin-panel .dataTables_wrapper .dataTables_paginate .paginate_button:hover,
.cp-table-wrap .dataTables_wrapper .dataTables_paginate .paginate_button:hover,
.admin-panel .dataTables_wrapper .dataTables_paginate .paginate_button:focus,
.cp-table-wrap .dataTables_wrapper .dataTables_paginate .paginate_button:focus {
    background: var(--surface-hover) !important;
    border-color: var(--accent) !important;
    color: var(--surface-link-hover) !important;
}

.admin-panel .dataTables_wrapper .dataTables_paginate .paginate_button.current,
.cp-table-wrap .dataTables_wrapper .dataTables_paginate .paginate_button.current,
.admin-panel .dataTables_wrapper .dataTables_paginate .paginate_button.current:hover,
.cp-table-wrap .dataTables_wrapper .dataTables_paginate .paginate_button.current:hover {
    background: var(--accent) !important;
    border-color: var(--accent) !important;
    color: var(--navy) !important;
    font-weight: 600;
}

.admin-panel .dataTables_wrapper .dataTables_paginate .paginate_button.disabled,
.cp-table-wrap .dataTables_wrapper .dataTables_paginate .paginate_button.disabled,
.admin-panel .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover,
.cp-table-wrap .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover {
    background: transparent !important;
    border-color: var(--surface-rule) !important;
    color: var(--surface-muted) !important;
    opacity: .5;
    cursor: default;
}

/* ── Empty and loading states ──────────────────────────────────────────────── */

table.dataTable.cp-table td.dataTables_empty,
table.dataTable.admin-table td.dataTables_empty {
    padding: 28px 20px;
    text-align: center;
    color: var(--surface-muted);
    font-size: .9rem;
}

/* The processing overlay: DataTables centres a translucent white band, which disappears on a
   navy canvas. */
.admin-panel .dataTables_wrapper .dataTables_processing,
.cp-table-wrap .dataTables_wrapper .dataTables_processing {
    background: var(--surface-1);
    color: var(--surface-ink);
    border: 1px solid var(--surface-rule);
    border-radius: .375rem;
    box-shadow: 0 2px 10px rgba(0, 20, 40, 0.15);
    padding: .5rem 1rem;
}

/* ── The filter strip above a grid ─────────────────────────────────────────── */
/* Where the role/permission/customer selects live. On the panel BODY, not on the navy header
   strip: admin-industrial.css styles `.admin-panel-header .form-control` but not `.form-select`,
   so a select on the strip renders unthemed -- which is exactly what the old /users/list did with
   its customer filter. On the light body, Bootstrap's own form-select is correct as authored. */

.admin-filter-strip {
    padding: 14px 20px;
    border-bottom: 1px solid var(--surface-rule);
    background: var(--surface-1);
    display: flex;
    flex-wrap: wrap;
    gap: .75rem 1rem;
    align-items: flex-end;
}

.admin-filter-strip .admin-filter-field {
    display: flex;
    flex-direction: column;
    gap: .25rem;
    min-width: 180px;
}

.admin-filter-strip .admin-filter-label {
    font-size: .7rem;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--surface-muted);
}

/* Pushes the reset control to the far end without a spacer element. */
.admin-filter-strip .admin-filter-actions {
    margin-left: auto;
    display: flex;
    gap: .5rem;
    align-items: flex-end;
}

/* A live count of what the filters matched, so an empty grid is explained rather than blank. */
.admin-filter-summary {
    font-size: .8rem;
    color: var(--surface-muted);
}

/* ── Role and permission chips inside a grid cell ──────────────────────────── */
/* .admin-badge is the badge family for these screens; these two modifiers cover states the
   family did not have a meaning for. Both say "this grants nothing", so both are struck
   through, and neither invents a colour. */

.admin-badge--stale {
    text-decoration: line-through;
    opacity: .65;
}

/* Wraps a cell full of chips without stretching the row. */
/* An action group in a grid cell: every control on ONE line, never wrapped into a ragged stack.
   Role chips still wrap (.admin-chip-cell below) because a user may hold many and stacking them is
   correct; a fixed set of two or three buttons is a single control group and reads as unrelated
   controls the moment it breaks across lines. The cell sizes to content, so the column widens
   rather than the buttons stacking. */
.admin-action-cell {
    display: flex;
    flex-wrap: nowrap;
    gap: .25rem;
    align-items: center;
    white-space: nowrap;
}

/* ── Responsive column priority ─────────────────────────────────────────────── */
/* Seven columns cannot fit a phone by wrapping alone — measured at 375px, the /my-team grid wanted
   580px inside a 327px panel. So the lower-priority columns come out as the viewport narrows,
   rather than the grid overflowing or the page scrolling sideways.

   Priority is by class, not by nth-child, because the two grids have different column ORDERS
   (/users/list has a Customer column and no Actions; /my-team the reverse) and position-based rules
   would silently hide the wrong thing the first time a column is inserted.

   What always survives: who the row is, what they can do, and the controls to act on them. */

@media (max-width: 991.98px) {
    table.dataTable.admin-table th.dt-col-lo,
    table.dataTable.admin-table td.dt-col-lo {
        display: none;
    }
}

@media (max-width: 767.98px) {
    table.dataTable.admin-table th.dt-col-mid,
    table.dataTable.admin-table td.dt-col-mid {
        display: none;
    }
}

/* The label beside each action icon. Present by default, dropped on a narrow viewport so the column
   shrinks to three icon buttons instead of forcing the table wider than the screen — the grid fits
   the screen it is on, rather than making the page scroll sideways to reach its last column.
   Dropping the label is safe ONLY because each icon is a glyph that actually renders and each
   control keeps its title attribute; an icon-only button with a missing glyph is the empty box this
   whole area started as. */
@media (max-width: 1199.98px) {
    .admin-action-label {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip: rect(0 0 0 0);
        white-space: nowrap;
    }
}

.admin-chip-cell {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem;
    align-items: center;
}

/* A chip in a grid cell wraps as a WHOLE chip or not at all (issue #167).
   .admin-badge is white-space:normal, which is right for a badge in a hero or a panel header where
   there is room. In a squeezed grid cell it broke labels mid-word — the review queue at 670px
   rendered "Sugg estio n" and "Pendi ng" inside their outlines, which reads as a rendering fault
   rather than a narrow column. Chips still wrap onto further lines, because .admin-chip-cell is a
   flex container and each chip is one flex item.

   Scoped to a grid cell so the shared .admin-badge keeps its own behaviour everywhere else: made
   global, a long badge would overflow its container instead of wrapping, on screens that are fine
   as they are. */
table.dataTable.cp-table td .admin-badge,
table.dataTable.admin-table td .admin-badge {
    white-space: nowrap;
}

@media (max-width: 767.98px) {
    .admin-filter-strip .admin-filter-field {
        min-width: 100%;
    }

    .admin-filter-strip .admin-filter-actions {
        margin-left: 0;
        width: 100%;
    }
}
