/* ============================================================
 * NextGen MIS — Data display
 * ------------------------------------------------------------
 * Tables, DataTables chrome (info, pagination, search filter),
 * code blocks. Atkinson Hyperlegible at 14px minimum for any
 * surface displaying identifiers / numerics.
 *
 * PR 3 will expand this with row density variants, sort
 * indicators, zebra rows, action-column patterns. For now this
 * file enforces the legibility floor.
 * ============================================================ */

/* ============================================================
 * TABLE CELLS — 14px minimum (Atkinson)
 * ------------------------------------------------------------
 * Overrides datatables.css and Metronic table defaults which
 * shipped at 13px. 14px is the WCAG-friendly minimum for
 * sustained scanning of tabular data.
 * ============================================================ */

.table,
.table > thead > tr > th,
.table > thead > tr > td,
.table > tbody > tr > th,
.table > tbody > tr > td,
.table > tfoot > tr > th,
.table > tfoot > tr > td {
  font-family: var(--font-family-data) !important;
  font-size: var(--font-size-sm) !important;   /* 14px minimum */
  font-variant-numeric: tabular-nums lining-nums;
  line-height: var(--line-height-snug);
}

/* Header row — clean, integrated (no grey bar): Figtree, transparent bg,
   readable label colour, defined by a single crisp bottom rule. */
.table > thead > tr > th {
  font-family: var(--font-family-display) !important; /* Figtree contrasts with Atkinson data rows */
  font-weight: var(--font-weight-semibold);
  font-size: var(--font-size-sm) !important;   /* 14px — respects table minimum */
  color: var(--color-text-strong);
  background-color: var(--color-bg-app) !important;  /* light grey band — semantic token so it flips in dark */
  border-top: none !important;
  border-bottom: 1px solid var(--color-border-default) !important;
  white-space: nowrap;
  vertical-align: middle;
}
/* No corner radius on the header band (it doubled up with the card corner on the
   full-bleed table). Also remove DataTables' dark bottom border on the table. */
.table > thead > tr > th:first-child,
.table > thead > tr > th:last-child {
  border-radius: 0 !important;
}
.table,
table.dataTable,
table.dataTable.no-footer,
.dataTables_wrapper {
  border-bottom: none !important;
}

/* Horizontal row separators on every row (including the last — see the COMPLETE
   TABLE BORDER CONTRACT block at the end of this file, which restores the outer
   frame + last-row rule that earlier "card-table look" passes kept dropping). */
.table > tbody > tr > td,
.table > tbody > tr > th {
  border-top: none !important;
  border-bottom: 1px solid var(--color-border-default) !important;  /* row separator — less faint */
}

/* ---------- DARK-SAFE TABLE SURFACES ----------
   Vendor DataTables / Bootstrap hardcode #fff on the table, wrappers and rows,
   which breaks dark mode. Inherit the card surface so they flip with the theme;
   the header band, striping (bg-raised) and hover (bg-app) still win (later + more
   specific). */
.table,
table.dataTable,
table.dataTable.no-footer,
.dataTables_wrapper,
.dataTables_scroll,
.dataTables_scrollHead,
.dataTables_scrollHeadInner,
.dataTables_scrollBody {
  background-color: transparent !important;
}
.table > tbody > tr,
table.dataTable > tbody > tr,
.table > tbody > tr > td,
table.dataTable > tbody > tr > td,
.table > tbody > tr > th,
table.dataTable > tbody > tr > th {
  background-color: transparent !important;
}
/* DataTables highlights the sorted column with a hardcoded light #fbfcfd via a
   high-specificity vendor `!important` rule (table.dataTable td.sorting_1), which
   the transparent rule above can't reach — so the sorted column reads as light
   bars in dark mode. Match the vendor selector's specificity to knock it back to
   transparent; the row hover/striping still win (more specific). */
table.dataTable td.sorting_1,
table.dataTable td.sorting_2,
table.dataTable td.sorting_3,
table.dataTable th.sorting_1,
table.dataTable th.sorting_2,
table.dataTable th.sorting_3 {
  background-color: transparent !important;
}

/* Metronic wraps every DataTable in `.table-scrollable` with a 1px #e7ecf1 frame —
   a strong light/white border around the table (very visible in dark) and redundant
   inside the card. Drop it so the card border is the table's only boundary. */
.table-scrollable {
  border: none !important;
}

/* ---------- SORT INDICATORS ----------
   The Phosphor caret is drawn INLINE via ::after, immediately after the column
   title, so the gap between title and chevron is a constant 8px on every
   sortable header regardless of column width or text alignment. (The old
   edge-positioned background-image left the gap varying per column.) */
table.dataTable thead th.sorting,
table.dataTable thead th.sorting_asc,
table.dataTable thead th.sorting_desc,
table.dataTable thead td.sorting,
table.dataTable thead td.sorting_asc,
table.dataTable thead td.sorting_desc {
  cursor: pointer;
  background-image: none !important;          /* drop the edge-positioned caret */
  position: relative !important;              /* anchor for the caret in its own reserved gutter */
  padding-right: 28px !important;             /* reserve room so the caret can NEVER collide with the title, even on squeezed columns */
  color: var(--color-text-strong) !important;
}
/* Keep the caret gutter on the LAST sortable header too — the full-bleed re-pad
   (below) sets the last cell's right padding for breathing room; out-specify it
   so a right-aligned last column (e.g. "Total Payment") still clears the caret. */
.portlet .dataTables_wrapper table.dataTable thead th.sorting:last-child,
.portlet .dataTables_wrapper table.dataTable thead th.sorting_asc:last-child,
.portlet .dataTables_wrapper table.dataTable thead th.sorting_desc:last-child {
  padding-right: 28px !important;
}
/* Drawn as a CSS mask, not a background-image, so the caret takes its colour
   from `currentColor` — the same technique the Phosphor remap uses in
   `_icons.css`.
   Previously the chevron was a data-URI with a near-black fill baked in
   (#181715), sized for "~12:1 on the light header". That made it invisible in
   dark mode: a black glyph on a dark header, on EVERY DataTable in the app.
   Masking keeps the light-theme contrast identical while letting the dark
   theme's header colour carry it, with no second set of data-URIs to keep in
   sync. */
table.dataTable thead th.sorting::after,
table.dataTable thead th.sorting_asc::after,
table.dataTable thead th.sorting_desc::after,
table.dataTable thead td.sorting::after,
table.dataTable thead td.sorting_asc::after,
table.dataTable thead td.sorting_desc::after {
  content: "";
  display: block !important;                   /* defeat the vendor `display:none` on the sort caret (was kept alive by the old inline-block) */
  position: absolute;                         /* sits in the reserved right gutter, out of the title's flow → can't overlap */
  right: 8px;
  top: 50%;
  transform: translateY(-50%);
  width: 14px;
  height: 14px;
  background-color: currentColor;      /* the caret IS this colour; the mask cuts its shape */
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
  opacity: 1;
}
table.dataTable thead th.sorting::after,
table.dataTable thead td.sorting::after {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='%23181715'%3E%3Cpath d='M181.66,170.34a8,8,0,0,1,0,11.32l-48,48a8,8,0,0,1-11.32,0l-48-48a8,8,0,0,1,11.32-11.32L128,212.69l42.34-42.35A8,8,0,0,1,181.66,170.34Zm-96-84.68L128,43.31l42.34,42.35a8,8,0,0,0,11.32-11.32l-48-48a8,8,0,0,0-11.32,0l-48,48A8,8,0,0,0,85.66,85.66Z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='%23181715'%3E%3Cpath d='M181.66,170.34a8,8,0,0,1,0,11.32l-48,48a8,8,0,0,1-11.32,0l-48-48a8,8,0,0,1,11.32-11.32L128,212.69l42.34-42.35A8,8,0,0,1,181.66,170.34Zm-96-84.68L128,43.31l42.34,42.35a8,8,0,0,0,11.32-11.32l-48-48a8,8,0,0,0-11.32,0l-48,48A8,8,0,0,0,85.66,85.66Z'/%3E%3C/svg%3E");
}
table.dataTable thead th.sorting_asc::after,
table.dataTable thead td.sorting_asc::after {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='%23181715'%3E%3Cpath d='M213.66,165.66a8,8,0,0,1-11.32,0L128,91.31,53.66,165.66a8,8,0,0,1-11.32-11.32l80-80a8,8,0,0,1,11.32,0l80,80A8,8,0,0,1,213.66,165.66Z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='%23181715'%3E%3Cpath d='M213.66,165.66a8,8,0,0,1-11.32,0L128,91.31,53.66,165.66a8,8,0,0,1-11.32-11.32l80-80a8,8,0,0,1,11.32,0l80,80A8,8,0,0,1,213.66,165.66Z'/%3E%3C/svg%3E");
}
table.dataTable thead th.sorting_desc::after,
table.dataTable thead td.sorting_desc::after {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='%23181715'%3E%3Cpath d='M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='%23181715'%3E%3Cpath d='M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z'/%3E%3C/svg%3E");
}

/* ---------- TABLE FULL WIDTH ----------
   Force the table + every DataTables wrapper to fill the card. !important beats
   DataTables' inline autoWidth pixel width; neutralise per-column inline widths. */
.dataTables_wrapper,
.dataTables_scroll,
.dataTables_scrollHead,
.dataTables_scrollHeadInner,
.dataTables_scrollBody,
.dataTables_scrollHeadInner > table,
table.dataTable,
.table {
  width: 100% !important;
  max-width: 100% !important;
}
table.dataTable { table-layout: auto !important; box-sizing: border-box; }
table.dataTable thead th[style*="width"],
table.dataTable tbody td[style*="width"] { width: auto !important; }

/* Fallback before refinements.js wraps the table (and if JS is unavailable):
   the wrapper itself scrolls so a wide table never spills out of the card and
   pushes a page-level scrollbar. Once wrapped, the wrapper's content fits so
   this is inert and only .ng-tablescroll scrolls. */
.portlet .dataTables_wrapper {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* ---------- WIDE TABLES — CONTAINED HORIZONTAL SCROLL + EDGE-FADE ----------
   The table fills the card; when it's wider than the card (many columns / narrow
   viewport) it scrolls horizontally INSIDE the card rather than spilling out and
   pushing a page-level scrollbar. refinements.js wraps each DataTable once in
   `.ng-tablefade > .ng-tablescroll` — the table scrolls in the inner div while
   the info + pagination stay put — and toggles `.is-overflow / .at-start /
   .at-end` on the shell from the LIVE scroll position (scroll, resize, every
   DataTables draw). The fade is an OVERLAY pinned to the shell's visible edges
   and painted ON TOP of the cells.
   (The previous fade used a background-attachment:local shadow on the scroller;
   it sat BEHIND the opaque header / zebra cells, so it was never visible — hence
   "the fade is missing". An overlay on a non-scrolling shell is the fix.) */
.ng-tablescroll {
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  max-width: 100%;
}
/* Keep columns readable; the table scrolls once the card is narrower than this.
   The floor is reduced at small viewports (see _responsive.css) so more columns
   fit before scrolling kicks in. */
.ng-tablescroll > .table,
.ng-tablescroll > table.dataTable {
  min-width: 720px;
  /* A bottom margin here lives INSIDE the overflow scroll (a BFC), so it inflates
     the scroll/shell past the table's bottom border — the edge-fade then overhangs
     the table. Zero it; the gap to the info/pagination moves to the shell below.
     !important defeats datatables.bootstrap.css `table.dataTable { margin-bottom: 6px !important }`. */
  margin-bottom: 0 !important;
}
/* The fade lives on a non-scrolling shell so it stays pinned to the edges the
   user sees (a pseudo-element on the scroller itself would scroll away). The
   shell carries the table's external bottom spacing so the fade hugs the table. */
.ng-tablefade { position: relative; margin-bottom: var(--space-2); }
.ng-tablefade::before,
.ng-tablefade::after {
  content: "";
  position: absolute;
  top: 0;
  /* Stop the fade at the table's bottom edge. When the OS shows a classic (space-
     taking) horizontal scrollbar, it sits in the scroller BELOW the table; the var
     (set live by refinements.js = scroller.offsetHeight - clientHeight) insets the
     fade by that height so it never paints over the scrollbar / past the table.
     0px with overlay scrollbars, so no visual change there. */
  bottom: var(--ng-tablefade-sbh, 0px);
  width: 44px;
  pointer-events: none;            /* clicks pass straight through to the cells/links beneath */
  z-index: 3;
  opacity: 0;                      /* hidden until JS confirms there's overflow at that edge */
  transition: opacity var(--motion-base) var(--ease-standard);
}
.ng-tablefade::before {
  left: 0;
  background: linear-gradient(to right, rgba(15, 19, 17, 0.13), rgba(15, 19, 17, 0));
}
.ng-tablefade::after {
  right: 0;
  background: linear-gradient(to left, rgba(15, 19, 17, 0.13), rgba(15, 19, 17, 0));
}
/* Show each side only while there's more table to reveal in that direction. */
.ng-tablefade.is-overflow:not(.at-start)::before { opacity: 1; }
.ng-tablefade.is-overflow:not(.at-end)::after { opacity: 1; }

/* Cell padding — slight refinement (per audit §4.2: 2-3px was too tight) */
.table > thead > tr > th,
.table > thead > tr > td,
.table > tbody > tr > th,
.table > tbody > tr > td,
.table > tfoot > tr > th,
.table > tfoot > tr > td {
  padding: var(--space-2) var(--space-3) !important;  /* 8px vertical, 12px horizontal */
  vertical-align: middle;
}

/* List tables — DataTables inside a portlet default to condensed body rows
   (operator scan pages). Same rhythm as .table-condensed without requiring
   the class on every list blade. Local overrides (e.g. cycle group spacers)
   can out-specify with their own padding. */
.portlet .dataTables_wrapper table.dataTable > tbody > tr:not(.child) > td,
.portlet .dataTables_wrapper table.dataTable > tbody > tr:not(.child) > th {
  padding-top: var(--space-1) !important;
  padding-bottom: var(--space-1) !important;
}

/* Action column — in-row .ng-actions-menu / .btn-xs shouldn't balloon row height */
.table.dataTable > tbody > tr > td:has(> .ng-actions-menu),
.table.dataTable > tbody > tr > td:has(> .btn.btn-xs:only-child) {
  width: 1%;
  white-space: nowrap;
  padding-top: var(--space-1) !important;
  padding-bottom: var(--space-1) !important;
  vertical-align: middle;
}

/* Compact tables — Bootstrap-3 .table-condensed stays denser for operator-heavy contexts */
.table.table-condensed > thead > tr > th,
.table.table-condensed > thead > tr > td,
.table.table-condensed > tbody > tr > th,
.table.table-condensed > tbody > tr > td {
  padding: var(--space-1) var(--space-3) !important;  /* 4px vertical, 12px horizontal */
}

/* Comfortable tables — new modifier for low-density contexts (PR 3 will use this more) */
.table.table-comfortable > thead > tr > th,
.table.table-comfortable > thead > tr > td,
.table.table-comfortable > tbody > tr > th,
.table.table-comfortable > tbody > tr > td {
  padding: var(--space-3) var(--space-4) !important;  /* 12px vertical, 16px horizontal */
}

/* Row hover — light warm grey, consistent with the global palette */
.table.table-hover > tbody > tr:hover,
.table.table-hover > tbody > tr:hover > td,
.table.table-hover > tbody > tr:hover > th {
  background-color: var(--color-bg-app) !important;
}

/* Archived rows — secondary in mixed registration lists (holders of rg:ls:arc).
   Dim cell content, but leave the trailing actions column full-strength so the
   view / unarchive entry point stays easy to hit. Opacity on the <tr> would
   bake into children and can't be undone on one cell. */
.table > tbody > tr.ng-table__row--archived > td:not(:last-child) {
  opacity: 0.58;
  color: var(--color-text-muted);
}
.table > tbody > tr.ng-table__row--archived > td:not(:last-child) a:not(.btn) {
  color: var(--color-text-muted);
}
.table.table-hover > tbody > tr.ng-table__row--archived:hover > td:not(:last-child) {
  opacity: 0.78;
}

/* Cell subtext — a muted second line under a cell's primary value, for context
   that would not earn its own column (e.g. the app version behind a last-login
   date). Render nothing rather than a placeholder when there is no value, so
   single-line cells stay single-line. */
.ng-table__subtext {
  display: block;
  margin-top: 2px;
  font-size: var(--font-size-xs);
  line-height: var(--line-height-tight);
  color: var(--color-text-muted);
}

/* Striped rows — opt-in via .table-striped */
.table.table-striped > tbody > tr:nth-of-type(odd) {
  background-color: var(--color-bg-raised) !important;
}

/* Borders — softer than Metronic default */
.table.table-bordered {
  border-color: var(--color-border-subtle);
}

.table.table-bordered > thead > tr > th,
.table.table-bordered > thead > tr > td,
.table.table-bordered > tbody > tr > th,
.table.table-bordered > tbody > tr > td {
  border-color: var(--color-border-subtle);
}

/* The existing .fit utility from layout-app.css for narrow action columns */
.table td.fit,
.table th.fit {
  white-space: nowrap;
  width: 1%;
}
/* Icon-only row actions — pair with .btn-xs.ng-btn-icon; right-aligned in
   .text-right.fit cells via justify-content. */
.ng-table__actions {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-1);
}

/* ---------- KILL STRAY VERTICAL GRID LINES ----------
   Vendor .table-light / .table-wh (beneficiary detail key/value tables) and
   the DataTables .order-column variant add dark VERTICAL grid lines between
   cells that clash with the soft card look. Drop only those vertical seams
   everywhere EXCEPT .table-bordered (which intentionally keeps its full subtle
   grid); the OUTER frame + horizontal row rules are (re)established by the
   COMPLETE TABLE BORDER CONTRACT block at the end of this file. */
.table:not(.table-bordered) > thead > tr > th,
.table:not(.table-bordered) > thead > tr > td,
.table:not(.table-bordered) > tbody > tr > th,
.table:not(.table-bordered) > tbody > tr > td,
.table:not(.table-bordered) > tfoot > tr > th,
.table:not(.table-bordered) > tfoot > tr > td {
  border-left: none !important;
  border-right: none !important;
}

/* ============================================================
 * COMPLETE TABLE BORDER CONTRACT
 * ------------------------------------------------------------
 * CONTRACT: every .table renders a COMPLETE 1px frame — a full
 * outer border (top/right/bottom/left) AND a bottom rule on every
 * row, including the last. This has regressed repeatedly because
 * three layers each strip part of the frame and the loss is only
 * visible on whichever table you didn't look at:
 *   • Vendor Metronic ships `.table { border: none }` on the table
 *     and `border-width: 0` on cells (its "borderless" default).
 *   • DataTables adds `border-bottom` on the wrapper/table that the
 *     dark-mode pass zeroed out (the `border-bottom: none` rule near
 *     the top of this file), which also took the OUTER bottom away.
 *   • Earlier "card-table look" passes dropped the last-row bottom
 *     rule and the outer left/right border for a frameless card.
 * This block is the single source of truth for the frame and sits
 * LAST in the table region so it wins the cascade over all three.
 * Lives outside :not(.table-bordered) deliberately — .table-bordered
 * already has its own full grid; this just guarantees the OUTER frame
 * is present and uses the same subtle token, so the two never diverge.
 * border-collapse:collapse (Bootstrap-3's default on .table) means the
 * shared outer+row edges merge into one 1px line — no 2px seams. */
.table,
.table-hover,
.dataTables_wrapper .table,
table.dataTable {
  border: 1px solid var(--color-border-default) !important;   /* defeat vendor `.table { border: none }` + the dark-mode `border-bottom: none` above */
  border-collapse: collapse !important;                       /* shared edges merge → no doubled 2px seams */
}
/* Last row keeps its bottom rule so it meets the outer bottom border as one
   crisp line (earlier passes set this to `none` for the frameless look). */
.table > tbody > tr:last-child > td,
.table > tbody > tr:last-child > th,
table.dataTable > tbody > tr:last-child > td,
table.dataTable > tbody > tr:last-child > th {
  border-bottom: 1px solid var(--color-border-default) !important;
}

/* ============================================================
 * DATATABLES CHROME (pagination, info, processing)
 * ============================================================ */

.dataTables_wrapper {
  font-family: var(--font-family-data);
  font-size: var(--font-size-sm) !important;   /* 14px */
}

/* "Showing X to Y of Z entries" */
.dataTables_wrapper .dataTables_info {
  font-family: var(--font-family-ui) !important;
  font-size: var(--font-size-sm) !important;   /* 14px — up from 13px Metronic default */
  color: var(--color-text-muted);
  padding-top: var(--space-2);
}

/* Pagination */
.dataTables_wrapper .dataTables_paginate {
  font-family: var(--font-family-ui) !important;
  font-size: var(--font-size-sm) !important;   /* 14px */
  padding-top: var(--space-2);
}

.dataTables_wrapper .dataTables_paginate .paginate_button {
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
  font-family: var(--font-family-ui) !important;
  font-size: var(--font-size-sm) !important;   /* 14px */
  font-weight: var(--font-weight-medium);
  min-height: 40px;                              /* match field height */
  padding: 0 var(--space-3) !important;
  margin: 0 var(--space-1) !important;
  color: var(--color-text-default) !important;
  background: transparent !important;
  border: 1px solid var(--color-border-default) !important;
  border-radius: var(--radius-md);
  min-width: 40px;
  text-align: center;
  cursor: pointer;
  transition: background var(--motion-fast) var(--ease-standard),
              border-color var(--motion-fast) var(--ease-standard);
}

.dataTables_wrapper .dataTables_paginate .paginate_button:hover {
  background: var(--color-bg-sunken) !important;   /* match the secondary/Reset outline hover */
  border-color: var(--color-border-strong) !important;
  color: var(--color-text-strong) !important;
}

.dataTables_wrapper .dataTables_paginate .paginate_button.current,
.dataTables_wrapper .dataTables_paginate .paginate_button.current:hover {
  background: var(--color-brand-primary) !important;
  border-color: var(--color-brand-primary) !important;
  color: var(--color-text-inverse) !important;
  font-weight: var(--font-weight-semibold);
}

.dataTables_wrapper .dataTables_paginate .paginate_button.disabled,
.dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover {
  color: var(--color-text-disabled) !important;
  background: transparent !important;
  border-color: var(--color-border-subtle) !important;
  cursor: not-allowed;
}

/* Custom pagination (createCustomPagination + pagination::ng) —
   first/prev/[input]/next/last. Make the page-number input the SAME height as
   the buttons (it's a .form-control, which the forms layer made 40px → taller
   than the buttons). */
.dataTables_paginate .form-horizontal.form-group,
.dataTables_paginate .form-group.row,
.ng-pagination .form-horizontal.form-group,
.ng-pagination .form-group.row {
  display: flex !important;
  align-items: center;
  gap: var(--space-1);
  margin: 0 !important;
}
.dataTables_paginate .form-group > [class*="col-"],
.ng-pagination .form-group > [class*="col-"] {
  width: auto !important;
  float: none !important;
  margin: 0 !important;
  padding: 0 2px !important;
  display: flex;
  align-items: center;
}
.dataTables_paginate .btn,
.ng-pagination .btn {
  height: 38px !important;
  min-height: 38px !important;
  padding: 0 var(--space-3) !important;
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-md);
}
.dataTables_paginate input.form-control,
.ng-pagination input.form-control {
  height: 38px !important;
  min-height: 0 !important;
  width: 56px !important;
  padding: 0 var(--space-2) !important;
  text-align: center;
}
.dataTables_paginate .control-label,
.ng-pagination .control-label {
  display: inline-block !important;   /* NOT flex — keep the spaces in "of N pages" */
  margin: 0 var(--space-2) !important;
  padding: 0 !important;
  white-space: nowrap;
  font-weight: var(--font-weight-regular);
  font-size: var(--font-size-xs) !important;   /* slightly smaller "of N pages" */
  color: var(--color-text-muted);
}
/* Keep a space around the page-count number even if the label is flexed elsewhere */
.dataTables_paginate .control-label > span,
.ng-pagination .control-label > span { margin: 0 0.25em; }

/* Laravel paginator shell — right-aligned below the list, same rhythm as DataTables. */
.ng-pagination {
  display: flex;
  justify-content: flex-end;
  padding-top: var(--space-2);
  font-family: var(--font-family-ui);
  font-size: var(--font-size-sm);
}

/* DataTables length / filter are unused (the custom #form-filter + pagination
   replace them). datatables.css hides them with visibility:hidden, which KEEPS
   their box → an empty white row above the table. display:none collapses it. */
.dataTables_wrapper .dataTables_length,
.dataTables_wrapper .dataTables_filter {
  display: none !important;
  font-family: var(--font-family-ui);
  font-size: var(--font-size-sm);
}
/* display:none on the controls alone left their Bootstrap .row/.col wrapper as a
   thin empty white strip above the table — collapse the whole top control row.
   (Metronic's dom wraps length+filter in `.dataTables_wrapper > .row:first-child`.) */
.dataTables_wrapper > .row:first-child {
  display: none !important;
}
/* Detail tables (.dt-accrdn) run paging:false + info:'' — their BOTTOM control
   row (info + paginate) renders empty but still leaves a dead ~18px white gap
   under the last row. Collapse it (scoped to .dt-accrdn so the main list's
   custom pagination row is untouched). */
.dataTables_wrapper:has(table.dt-accrdn) > .row:last-child {
  display: none !important;
}
/* Metronic wraps the table in .table-scrollable with a stray 10px top+bottom
   margin. On a short detail table that bottom 10px reads as uneven trailing
   space (the row looks pushed up, not centred). Zero it so the card's own
   symmetric 32px padding does the spacing. */
.dataTables_wrapper:has(table.dt-accrdn) .table-scrollable {
  margin: 0 !important;
  border: none !important;
}
/* The legacy detail-page stylesheet constrains wrapped tables to 99% and gives
   .dt-accrdn a half-pixel black frame. Restore the shared table contract here:
   the table fills its wrapper and owns the single semantic 1px frame. */
.dataTables_wrapper:has(table.dt-accrdn) table.dataTable {
  margin: 0 !important;
  width: 100% !important;
  border: 1px solid var(--color-border-default) !important;
}

/* Belt-and-braces: zero ALL top spacing across the table region so the grey
   header band sits flush at the top with no thin white strip above it. The
   table element itself KEEPS its 1px outer top border (the COMPLETE TABLE
   BORDER CONTRACT frame) — only the wrappers zero their top edge; stripping the
   table's own border-top here would punch a gap in the frame. */
.portlet .dataTables_wrapper,
.portlet .dataTables_wrapper .ng-tablefade,
.portlet .dataTables_wrapper .ng-tablescroll {
  margin-top: 0 !important;
  padding-top: 0 !important;
  border-top: none !important;
}
.portlet .dataTables_wrapper table.dataTable {
  margin-top: 0 !important;
  padding-top: 0 !important;
}
.portlet .dataTables_wrapper table.dataTable > thead > tr > th {
  border-top: none !important;   /* the header CELL has no top rule; the table's outer frame supplies the top edge */
}

.dataTables_wrapper .dataTables_length label,
.dataTables_wrapper .dataTables_filter label {
  color: var(--color-text-default);
  font-weight: var(--font-weight-regular);
}

.dataTables_wrapper .dataTables_filter input {
  font-family: var(--font-family-ui) !important;
  font-size: var(--font-size-sm);
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-sm);
  padding: var(--space-1) var(--space-3);
  margin-left: var(--space-2);
}

/* Empty state ("No data available in table") */
.dataTables_wrapper .dataTables_empty,
.dataTables_empty {
  font-family: var(--font-family-ui);
  font-size: var(--font-size-base);
  color: var(--color-text-muted);
  padding: var(--space-6) !important;
  text-align: center;
}

/* ============================================================
 * EMPTY STATE (.ng-empty-state) — a clean placeholder shown in
 * place of a table/list that has no records. Use via the
 * partials/empty-state.blade.php include.
 * ============================================================ */
.ng-empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-2);
  padding: var(--space-8) var(--space-4);
}
.ng-empty-state__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  margin-bottom: var(--space-1);
  border-radius: var(--radius-full);
  background: var(--color-bg-sunken);
  color: var(--color-text-faint);
  font-size: 22px;
}
.ng-empty-state__title {
  margin: 0;
  font-family: var(--font-family-display);
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-default);
}
.ng-empty-state__text {
  margin: 0;
  max-width: 380px;
  font-family: var(--font-family-ui);
  font-size: var(--font-size-sm);
  color: var(--color-text-faint);
  line-height: var(--line-height-snug);
}

/* ============================================================
 * ASYNC FORM PREVIEW (.ng-form-preview)
 * ------------------------------------------------------------
 * Compact candidate tally shown in the create-batch modal after a
 * district is selected. The shell comes from `.ng-form-modal` in
 * _forms.css; placeholder/loading/feedback states share one stable panel.
 * ============================================================ */
.ng-batch-create-modal__location .form-group {
  margin-bottom: 0;
}
.ng-form-preview {
  margin-top: var(--space-4);
  padding: var(--space-4);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-lg);
  background: var(--color-bg-raised);
}
.ng-form-preview__heading {
  margin: 0 0 var(--space-3);
  font-family: var(--font-family-display);
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-default);
}
.ng-form-preview__message {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 72px;
  padding: var(--space-3);
  border: 1px dashed var(--color-border-default);
  border-radius: var(--radius-md);
  background: var(--color-bg-surface);
}
.ng-form-preview__message-icon {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-full);
  background: var(--color-bg-sunken);
  color: var(--color-text-muted);
  font-size: var(--font-size-lg);
}
.ng-form-preview__message-title {
  margin: 0;
  font-family: var(--font-family-display);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-default);
}
.ng-form-preview__message-text {
  margin: var(--space-1) 0 0;
  font-family: var(--font-family-ui);
  font-size: var(--font-size-sm);
  line-height: var(--line-height-snug);
  color: var(--color-text-muted);
}
/* :not([hidden]) so author `display: flex` does not defeat the HTML hidden
   attribute (UA [hidden]{display:none} loses to any author display rule). */
.ng-form-preview__loading:not([hidden]) {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  min-height: 72px;
  padding: var(--space-3);
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
}
.ng-form-preview__alert.alert {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  margin: 0;
}
.ng-form-preview__alert > .fa {
  flex: 0 0 auto;
  margin-top: 2px;
  font-size: var(--font-size-md);
}
.ng-form-preview__alert strong,
.ng-form-preview__alert span {
  display: block;
}
.ng-form-preview__alert strong {
  margin-bottom: var(--space-1);
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-semibold);
}
.ng-form-preview__stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-2);
}
.ng-form-preview__stats--three {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.ng-form-preview__stat {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-3);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-md);
  background: var(--color-bg-surface);
}
.ng-form-preview__stat-value {
  font-family: var(--font-family-data);
  font-size: var(--font-size-2xl);
  font-weight: var(--font-weight-bold);
  line-height: 1.1;
  color: var(--color-text-strong);
  font-variant-numeric: tabular-nums;
}
.ng-form-preview__stat-label {
  font-family: var(--font-family-ui);
  font-size: var(--font-size-xs);
  line-height: var(--line-height-snug);
  color: var(--color-text-muted);
}
@media (max-width: 767px) {
  .ng-batch-create-modal__location .form-group {
    margin-bottom: var(--space-4);
  }
  .ng-batch-create-modal__location > [class*="col-"]:last-child .form-group {
    margin-bottom: 0;
  }
  .ng-form-preview__stats {
    grid-template-columns: 1fr 1fr;
  }
  .ng-form-preview__stats--three > :last-child {
    grid-column: 1 / -1;
  }
}

/* ============================================================
 * RESPONSIVE EXPAND CONTROL (DataTables Responsive, inline mode)
 * ------------------------------------------------------------
 * Vendor plugins.css renders a bare "+" via td:first-child::before
 * that sits ON TOP of the cell text. Re-skin it as a tidy circular
 * control in a reserved left gutter, with a Phosphor plus / minus
 * glyph (baked data-URI, like the sort carets). Selector matches
 * the vendor's `table.dataTable.dtr-inline.collapsed` specificity
 * so the later refinements rule wins.
 * ============================================================ */
table.dataTable.dtr-inline.collapsed > tbody > tr > td:first-child,
table.dataTable.dtr-inline.collapsed > tbody > tr > th:first-child {
  position: relative;
  padding-left: 42px !important;   /* gutter so the control never overlaps the value */
  cursor: pointer;
}
table.dataTable.dtr-inline.collapsed > tbody > tr > td:first-child::before,
table.dataTable.dtr-inline.collapsed > tbody > tr > th:first-child::before {
  content: "" !important;          /* drop the vendor "+" glyph */
  position: absolute;
  top: 50% !important;
  left: var(--space-3) !important;
  transform: translateY(-50%);
  width: 22px !important;
  height: 22px !important;
  margin: 0 !important;
  border: 1px solid var(--color-border-strong) !important;
  border-radius: var(--radius-full) !important;
  background-color: var(--color-bg-surface) !important;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='%2351504c'%3E%3Cpath d='M224,128a8,8,0,0,1-8,8H136v80a8,8,0,0,1-16,0V136H40a8,8,0,0,1,0-16h80V40a8,8,0,0,1,16,0v80h80A8,8,0,0,1,224,128Z'/%3E%3C/svg%3E") !important;
  background-repeat: no-repeat !important;
  background-position: center !important;
  background-size: 12px !important;
  box-shadow: none !important;
  color: transparent !important;
  transition: border-color var(--motion-fast) var(--ease-standard),
              background-color var(--motion-fast) var(--ease-standard);
}
table.dataTable.dtr-inline.collapsed > tbody > tr > td:first-child:hover::before {
  border-color: var(--color-input-border-hover) !important;
  background-color: var(--color-bg-raised) !important;
}
/* Expanded row → green minus control */
table.dataTable.dtr-inline.collapsed > tbody > tr.parent > td:first-child::before,
table.dataTable.dtr-inline.collapsed > tbody > tr.parent > th:first-child::before {
  border-color: var(--color-brand-secondary) !important;
  background-color: var(--color-brand-secondary-soft) !important;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='%234d6151'%3E%3Cpath d='M224,128a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,128Z'/%3E%3C/svg%3E") !important;
}
/* The expanded child row (hidden columns) — clean key/value list, not grid lines.
   DataTables renders it as <td.child> > <ul> (no class) > <li>(.dtr-title + .dtr-data). */
table.dataTable > tbody > tr.child td.child { padding: 0 !important; background: var(--color-bg-raised); }
table.dataTable > tbody > tr.child td.child > ul {
  width: 100%;
  margin: 0;
  padding: var(--space-2) var(--space-4) var(--space-2) 42px;   /* align under the control gutter */
  list-style: none;
}
table.dataTable > tbody > tr.child td.child > ul > li {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-1) 0;
  border-bottom: 1px solid var(--color-border-subtle);
  list-style: none;
}
table.dataTable > tbody > tr.child td.child > ul > li:last-child { border-bottom: 0; }
table.dataTable > tbody > tr.child .dtr-title {
  flex: 0 0 160px;
  font-family: var(--font-family-ui);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-muted);
}
table.dataTable > tbody > tr.child .dtr-data { color: var(--color-text-default); }

/* ============================================================
 * PII FIELD (preserve existing tooltip, refine type)
 * ============================================================ */

.pii-field {
  font-family: var(--font-family-data);
  font-size: inherit; /* table cell or wherever it sits */
}

/* ============================================================
 * MISC NUMERIC / ID VALUES
 * ============================================================ */

.numeric-value,
.id-value,
.beneficiary-id,
.registration-no,
[data-id],
[data-numeric] {
  font-family: var(--font-family-data);
  font-variant-numeric: tabular-nums lining-nums;
}

/* ============================================================
 * DEVICE AUDIT TRAIL — field-change diff table
 * ------------------------------------------------------------
 * Renders inside a `.portlet light` card on the applicant
 * profile (and the batch/archive detail popups), matching the
 * supporting-documents table. Reuses the base `.table` chrome
 * and layers diff-cell semantics over a fixed column grid.
 * Cursor-paginated via window.cursorList — not DataTables.
 * ============================================================ */
.ng-audit__subtitle {
  margin: 0 0 var(--space-3);
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
}

.ng-audit__table {
  table-layout: fixed;
}

.ng-audit__table > thead > tr > th,
.ng-audit__table > tbody > tr > td {
  word-break: break-word;
  overflow-wrap: anywhere;
}

.ng-audit__col--field  { width: 20%; }
.ng-audit__col--change { width: 37%; }
.ng-audit__col--by     { width: 25%; }
.ng-audit__col--time   { width: 18%; }

.ng-audit__field { color: var(--color-text-default); }

/* Non-field-change rows (submission attempts, corrections): muted line,
   bold action label, no diff cell. */
.ng-audit__row--action { color: var(--color-text-muted); }
.ng-audit__row--action .ng-audit__field { font-weight: var(--font-weight-semibold); }

.ng-audit__old {
  color: var(--color-feedback-danger);
  text-decoration: line-through;
}
.ng-audit__new   { color: var(--color-feedback-success); }
.ng-audit__arrow { color: var(--color-text-faint); }
.ng-audit__empty {
  color: var(--color-text-disabled);
  text-decoration: none;
}

.ng-audit__file {
  font-weight: var(--font-weight-medium);
  text-decoration: none;
}
.ng-audit__file--changed { color: var(--color-feedback-warning); }

.ng-audit__by {
  font-weight: var(--font-weight-medium);
  color: var(--color-text-default);
}
.ng-audit__time {
  color: var(--color-text-muted);
  font-size: var(--font-size-xs);
}

.ng-audit__loading {
  padding: var(--space-3);
  text-align: center;
  color: var(--color-text-faint);
}

/* ---------- SEGMENTED CONTROL (.ng-segmented) ----------
   iOS-style view switcher: a sunken track holding equal segments, the active
   one raised onto the surface. Used as the Graduation Forecast window switcher;
   generic enough for any "pick one view of the same list" control. */
.ng-segmented {
  display: inline-flex;
  gap: var(--space-1);
  padding: var(--space-1);
  margin-bottom: var(--space-4);
  background: var(--color-bg-sunken);
  border: var(--card-border);
  border-radius: var(--radius-xl);
}
.ng-segmented__option {
  appearance: none;
  border: 1px solid transparent;
  background: transparent;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-lg);
  color: var(--color-text-muted);
  font-weight: var(--font-weight-medium);
  line-height: var(--line-height-snug);
  cursor: pointer;
  transition: color var(--transition-fast), background-color var(--transition-fast),
    border-color var(--transition-fast), box-shadow var(--transition-fast);
}
.ng-segmented__option:hover {
  color: var(--color-text-default);
}
.ng-segmented__option:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}
.ng-segmented__option.is-active {
  background: var(--color-bg-surface);
  border-color: var(--color-border-default);
  box-shadow: var(--shadow-sm);
  color: var(--color-text-strong);
  font-weight: var(--font-weight-semibold);
}

/* Reminder admin — compact in-row actions (Edit / Enable / Disable) */
.reminder-admin-page .table > tbody > tr > td.ng-reminder__actions,
.reminder-admin-page .table > thead > tr > th:last-child {
  width: 1%;
  min-width: 132px;
  white-space: nowrap;
  vertical-align: middle;
  text-align: right;
}
.reminder-admin-page .ng-reminder__action-group {
  display: inline-flex;
  flex-wrap: nowrap;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-1);
}
.reminder-admin-page .ng-reminder__inline-form {
  display: inline-flex;
  margin: 0;
}
.reminder-admin-page .ng-reminder__action-group .btn {
  margin: 0;
  flex: 0 0 auto;
}
.reminder-admin-page .ng-reminder__test-section {
  margin-bottom: 0;
}
.reminder-admin-page .ng-reminder__test-section.ng-reminder-modal__row {
  margin-bottom: var(--space-4);
}
.ng-reminder-modal__label--empty {
  visibility: hidden;
}
.ng-reminder-modal .ng-reminder__test-toggle.ng-report-advanced-toggle {
  margin-left: 0; /* override _report-builder.css label offset — row grid handles alignment */
  margin-top: 0;
}
.ng-reminder__test-stack {
  display: inline-block;
  max-width: 100%;
  vertical-align: top;
}
.ng-reminder__test-stack .select2-container {
  width: 100% !important; /* defeat _forms.css full-width — match toggle, not modal field column */
}
.ng-reminder__test-stack .select2-hidden-accessible {
  width: 1px !important; /* clip off-screen select — avoid .form-control { width:100% } spill */
  min-width: 0 !important;
}
.reminder-admin-page .ng-reminder__test-toggle-row {
  margin-bottom: 0;
}
.reminder-admin-page .ng-reminder__test-toggle {
  margin-left: 0;
  margin-top: 0;
}
.reminder-admin-page .ng-reminder__test-panel {
  margin-top: var(--space-3);
  padding-top: 0;
  border-top: 0;
}
.reminder-admin-page .ng-reminder__test-form {
  margin-bottom: 0;
}
.reminder-admin-page .ng-reminder__test-form .form-group:last-child {
  margin-bottom: 0;
}

/* Reminder admin — toolbar + modal form (wireframe layout) */
.reminder-admin-page .reminder-toolbar {
  margin-bottom: var(--space-4);
}
.reminder-admin-page .ng-reminder__empty {
  margin: var(--space-4) 0 0;
  color: var(--color-text-muted);
}
.ng-reminder-modal__row {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  margin-bottom: var(--space-4);
}
.ng-reminder-modal__label {
  flex: 0 0 96px;
  margin: 8px 0 0;
  font-weight: var(--font-weight-medium);
  color: var(--color-text-default);
}
.ng-reminder-modal__field {
  flex: 1 1 auto;
  min-width: 0;
}
.ng-reminder-modal__cadence {
  display: grid;
  grid-template-columns: 110px 220px; /* 1/3 + 2/3 — matches DS 220px field cap */
  gap: var(--space-2);
  align-items: center;
  width: fit-content;
  max-width: 100%;
}
.ng-reminder-modal__cadence > #reminder-cadence.form-control,
.ng-reminder-modal__cadence > #reminder-slot.form-control,
.ng-reminder-modal__cadence > #reminder-time.form-control {
  width: 100%;
  min-width: 0;
}
.ng-reminder-modal__cadence-hint {
  grid-column: 1 / -1;
  margin-top: calc(-1 * var(--space-1));
}
[data-ng-reminder-slot][hidden],
[data-ng-reminder-time][hidden],
[data-ng-reminder-time-hint][hidden] {
  display: none !important; /* Bootstrap ignores [hidden] on form controls */
}
.ng-reminder-modal .help-block {
  margin-bottom: 0;
}
/* Audience multi-select — wrapped role chips need stable row gaps and vertical
   inset; vendor select2's 5px margin-top on each choice stacks unevenly when
   pills wrap (same pattern as .ng-report-field in _report-builder.css). */
.ng-reminder-modal .select2-selection--multiple .select2-selection__rendered {
  row-gap: var(--space-1);
  column-gap: var(--space-1);
  padding-top: var(--space-2) !important;    /* defeat global padding: 0 … !important */
  padding-bottom: var(--space-2) !important;
}
.ng-reminder-modal .select2-selection--multiple .select2-selection__choice {
  margin-top: 0 !important;    /* vendor default is 5px — stacks badly when wrapped */
  margin-bottom: 0 !important;
  margin-right: 0 !important; /* horizontal gap comes from column-gap on rendered */
}
@media (max-width: 480px) {
  .ng-reminder-modal__row {
    flex-direction: column;
    gap: var(--space-2);
  }
  .ng-reminder-modal__label {
    flex-basis: auto;
    margin-top: 0;
  }
  .ng-reminder-modal__cadence {
    width: 100%;
    grid-template-columns: 1fr;
  }
  .ng-reminder-modal__cadence > #reminder-cadence.form-control,
  .ng-reminder-modal__cadence > #reminder-slot.form-control,
  .ng-reminder-modal__cadence > #reminder-time.form-control {
    max-width: none;
  }
}

/* ============================================================
 * Fraud alert review — Epic C3 (#742), US-C3.1 (#77)
 * Cohort list on the alert detail page, plus the resolved
 * banner. Replaces the inline styles the first cut carried.
 * ============================================================ */
.ng-fraud-cohort {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.ng-fraud-cohort > li {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-sm);
  background: var(--color-bg-raised);
}
.ng-fraud-cohort > li > code {
  color: var(--color-text-muted);
}

/* Banner heading/body sit flush inside the vendor .alert box, which
   supplies its own padding. */
.ng-fraud-banner__title { margin-top: 0; }
.ng-fraud-banner__body  { margin-bottom: 0; }
.ng-fraud-banner__note  { margin: var(--space-2) 0 0; font-style: italic; }

/* ---------------------------------------------------------------------------
   Fast-lane criteria indicator (US-C2.1 #49 / US-C2.2 #85)
   --------------------------------------------------------------------------- */
.ng-criteria {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-full);
  line-height: 1;
  cursor: help;
}
.ng-criteria:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: 2px;
}
.ng-criteria__mark {
  display: inline-block;
  width: 14px;
  height: 14px;
  flex: 0 0 auto;
  background-color: currentColor;
  -webkit-mask: var(--ng-criteria-glyph) center / contain no-repeat;
          mask: var(--ng-criteria-glyph) center / contain no-repeat;
}
.ng-criteria__mark--pass {
  --ng-criteria-glyph: url(/img/icons/phosphor/check-circle.svg);
  color: var(--color-feedback-success);
}
.ng-criteria__mark--fail {
  --ng-criteria-glyph: url(/img/icons/phosphor/warning.svg);
  color: var(--color-feedback-danger);
}
.ng-criteria__mark--unknown {
  --ng-criteria-glyph: url(/img/icons/phosphor/minus.svg);
  color: var(--color-text-faint);
}

/* ---------------------------------------------------------------------------
   STATUS LEGEND (.ng-status-legend)
   --------------------------------------------------------------------------- */

/* Defines the status pills of the table it sits above, one row per tone. */
.ng-status-legend {
  list-style: none;
  margin: 0 0 var(--space-5);
  padding: 0;
}
.ng-status-legend__item {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  color: var(--color-text-muted);
}
.ng-status-legend__item + .ng-status-legend__item {
  margin-top: var(--space-2);
}
/* Keep the pill on one line so only the definition wraps. */
.ng-status-legend .ng-status-pill {
  flex: 0 0 auto;
}

/* ---------------------------------------------------------------------------
   Approval failed-checks confirmation (`.ng-approval-warning`)

   The body of the dialog shown before an approve is committed over
   applications whose automatic checks failed. Lives here, next to
   `.ng-criteria`, because it reuses that component's fail mark verbatim — the
   dialog must read as the same assessment the list column and the profile
   badges already showed, not a second opinion with its own iconography.

   Shell, alert and checkbox are the existing `.ng-form-modal`, `.alert-warning`
   and `.checkbox` components; only the application list is new.
   --------------------------------------------------------------------------- */
.ng-approval-warning__alert {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
}

.ng-approval-warning__list {
  list-style: none;
  margin: var(--space-4) 0 0;
  padding: 0;
  /* Capped rather than unbounded: the payload names at most 20 applications,
     and beyond ~6 rows the acknowledgement checkbox would be pushed below the
     fold — where an acknowledgement nobody scrolls to is not one. */
  max-height: 260px;
  overflow-y: auto;
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-md);
}

.ng-approval-warning__item {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-1) var(--space-3);
  padding: var(--space-3);
}

.ng-approval-warning__item + .ng-approval-warning__item {
  border-top: 1px solid var(--color-border-subtle);
}

.ng-approval-warning__identity {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  min-width: 0;
}

.ng-approval-warning__reg-no {
  font-family: var(--font-family-data);
  font-size: var(--font-size-sm);
  color: var(--color-text-default);
}

.ng-approval-warning__name {
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

.ng-approval-warning__checks {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1) var(--space-3);
  margin-left: auto;
}

.ng-approval-warning__check {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--font-size-xs);
  color: var(--color-feedback-warning);
}

.ng-approval-warning__more {
  margin: var(--space-2) 0 0;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

.ng-approval-warning__ack {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border-subtle);
}

/* On a narrow screen the checks wrap under the identity instead of being
   squeezed beside it — `margin-left: auto` would otherwise leave a single
   check hanging off the right edge of a two-line row. */
@media (max-width: 767px) {
  .ng-approval-warning__checks {
    margin-left: 0;
    width: 100%;
  }
}
