/* 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.

   dt-col-nowrap is the same opt-out for a value that is not a date: an exception type
   ("AmbiguousMatch" broke as "Ambiguous Match"), a host name, a count. Two names rather than one
   because dt-col-date also carries the date SORTER's meaning on the columns that use it, and a
   host name is not a date (issue #307). */
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,
table.dataTable.cp-table th.dt-col-nowrap,
table.dataTable.admin-table th.dt-col-nowrap,
table.dataTable.cp-table td.dt-col-nowrap,
table.dataTable.admin-table td.dt-col-nowrap {
    white-space: nowrap;
    overflow-wrap: normal;
    word-break: normal;
}

/* A cell holding one long free-text value — an exception message, a title — is clamped rather than
   allowed to set the row's height. Without it one 300-character message makes a 90px row beside
   40px neighbours, and the grid reads as ragged even though every column is correct. The full value
   stays in the cell's title attribute and on the detail screen, so nothing is lost, only deferred
   (issue #307).

   THE CLAMP ITSELF MOVED to admin-panels.css, where the number of lines is a custom property a
   column can raise (issue #323): how much height a cell may spend instead of width is a screen's
   decision, and it belongs beside the rule for how much width the panel has to spend. A copy here
   would not merely be duplication — it is MORE specific than the rule there, so it would win
   silently and the property would never take effect. */

/* A clamped cell has no intrinsic width left to ask for — the box it becomes is happy at any
   size — so under table-layout: auto the nowrap columns take everything and the clamped one
   collapses to a few characters ("The delegate…"). The floor is what keeps it readable; the
   column's own width percentage distributes whatever is left above it.

   Kept low deliberately. A floor generous enough to look right on its own puts two clamped columns
   past the panel's width between them, and the grid gains a horizontal scrollbar — which is worse
   than either column being a little narrow. */
table.dataTable.cp-table th.dt-col-clamp,
table.dataTable.admin-table th.dt-col-clamp,
table.dataTable.cp-table td.dt-col-clamp,
table.dataTable.admin-table td.dt-col-clamp {
    min-width: 10rem;
}

/* 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;
}

/* And the keyboard has to see what the mouse sees (issue #500). A row-link row is a tab stop, so
   the ring is the one the sortable headers already use — the same token, so the two read as one
   behaviour — and the hover fill comes with it, because a focused row IS the row about to open. */
table.dataTable.cp-table.cp-table--rowlink tbody tr:focus-visible,
table.dataTable.admin-table.admin-table--rowlink tbody tr:focus-visible {
    outline: 2px solid var(--surface-link);
    outline-offset: -2px;
    background: var(--surface-hover);
}

/* ── 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);
}

/* ── The primary filter row (issue #320) ──────────────────────────────────── */
/* The one or two questions a screen is really triaged by, lifted out of the row of selects and
   given segmented buttons. Same surface as the strip below it, separated only by the strip's own
   top border, so the two read as one control area rather than two panels. */

.admin-filter-primary {
    padding: 14px 20px 0;
    background: var(--surface-1);
    display: flex;
    flex-wrap: wrap;
    gap: .75rem 1.5rem;
    align-items: flex-end;
}

.admin-filter-primary .admin-filter-field--primary {
    display: flex;
    flex-direction: column;
    gap: .25rem;
    min-width: auto;
}

/* The buttons carry their own state through .btn-accent, which is the management screens' one
   primary vocabulary — never btn-primary here, they are the same fill and swapping them is not a
   contrast fix. */
.admin-filter-segmented .btn {
    font-size: .8rem;
}

/* ── A filter holding several values (issue #320) ─────────────────────────── */
/* A dropdown of checkboxes rather than a `select multiple`: what is chosen stays readable when the
   menu is shut, and choosing a second value does not need ctrl-click to discover. */

.admin-filter-multi {
    min-width: 180px;
}

/* Sized and coloured as the selects beside it so the row stays one vocabulary. The caret is
   form-select's own background image, which is why this is a .form-select rather than a .btn. */
.admin-filter-multi-toggle {
    width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.admin-filter-multi-menu {
    padding: .5rem .75rem;
    max-height: 16rem;
    overflow-y: auto;
    background: var(--surface-1);
    border-color: var(--surface-rule);
}

.admin-filter-multi-menu .form-check {
    margin-bottom: .25rem;
}

.admin-filter-multi-menu .form-check-label {
    font-size: .85rem;
    color: var(--surface-ink);
}

/* ── 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%;
    }
}
