/* ---------------------------------------------------------------------------
   Daleen shared controls: action button, controlled table, filter popover.
   ---------------------------------------------------------------------------
   Genesis's geometry, Daleen's palette.

   The geometry is copied on purpose and measured from
   AS-AR-PROJECT/public/admin/app.css: the 3:1 button with a 24px icon column, the
   34px label row over the 26px tool row, the 8px resize strip hanging 3px past
   the column edge, the 22x21 tool button. Those numbers are why the Genesis
   grids feel dense but not cramped, and re-deriving them by eye would have
   produced something almost right.

   The palette is not copied. Genesis's table header is #DFE5ED on navy #344456
   and its action tones are #0072ce / #2f9e26 / #c8343c / #111827. Those are
   Genesis's brand, and Daleen's standard 149 already ruled on this once for
   gridlines: keep the rule, drop the borrowed value. So every color here is a
   token from brand-tokens.css, which means the contrast gate covers it and a
   palette change reaches these controls without anyone remembering they exist.
   --------------------------------------------------------------------------- */

/* ---- action button ---- */

.ui-action {
  --ui-action-color: var(--navy);
  --ui-action-hover: var(--soft-2);
  --ui-action-width: 108px;
  --ui-action-height: 36px;
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr);
  align-items: center;
  gap: 6px;
  width: var(--ui-action-width);
  max-width: 100%;
  min-width: 0;
  height: var(--ui-action-height);
  min-height: var(--ui-action-height);
  padding: 3px 7px 3px 4px;
  border: 1.5px solid var(--ui-action-color);
  border-radius: 7px;
  background: var(--white);
  color: var(--ui-action-color);
  font-family: var(--font-stack);
  font-size: 9.5px;
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: 0.02em;
  text-align: left;
  text-transform: uppercase;
  white-space: normal;
  cursor: pointer;
}

.ui-action:hover { background: var(--ui-action-hover); }
.ui-action:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.ui-action:disabled { cursor: not-allowed; opacity: 0.55; }

/* Tones, per the standard: black is the default, blue is create/save/open/
   download/send, green is refresh/apply/verify/success, red is destructive,
   cancel and close. */
.ui-action-black { --ui-action-color: var(--navy); --ui-action-hover: var(--soft-2); }
.ui-action-blue { --ui-action-color: var(--blue-dark); --ui-action-hover: var(--soft-2); }
.ui-action-green { --ui-action-color: var(--green); --ui-action-hover: var(--green-tint); }
.ui-action-red { --ui-action-color: var(--red); --ui-action-hover: var(--red-tint); }
.ui-action-amber { --ui-action-color: var(--amber); --ui-action-hover: var(--amber-tint); }

.ui-action-toolbar { --ui-action-width: 90px; --ui-action-height: 30px; grid-template-columns: 22px minmax(0, 1fr); gap: 5px; }
.ui-action-wide { --ui-action-width: 132px; }

.ui-action-icon {
  display: grid;
  place-items: center;
  justify-self: center;
  width: 23px;
  height: 23px;
  color: var(--ui-action-color);
}

.ui-action-icon svg {
  display: block;
  width: 86%;
  height: 86%;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.75;
  stroke-linecap: round;
  stroke-linejoin: round;
  overflow: visible;
}

.ui-action-label {
  display: grid;
  align-items: center;
  justify-items: center;
  justify-self: stretch;
  min-width: 0;
  line-height: 1.02;
  text-align: center;
}

/* One span per word, so a two-word label stacks and stays centred instead of
   being clipped at the button edge. */
.ui-action-label span { display: block; }

.ui-link {
  border: 0;
  padding: 0;
  background: none;
  color: var(--blue-dark);
  font: inherit;
  text-decoration: underline;
  cursor: pointer;
}

/* ---- controlled table ---- */

.ui-table-meta {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 6px;
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 11px;
}

/* Horizontal scrolling without layout collapse, which is the standard's phrasing
   and the reason the wrapper exists at all. */
.ui-table-wrap {
  overflow: auto;
  max-width: 100%;
  border: 1.5px solid var(--grid);
  border-radius: 8px;
  background: var(--white);
}

.ui-table {
  border-collapse: separate;
  border-spacing: 0;
  /* Fixed, so the colgroup widths are honoured and a long cell cannot silently
     widen its column past what the operator dragged it to. */
  table-layout: fixed;
  width: max-content;
  min-width: 100%;
  font-size: 13px;
}

.ui-table th, .ui-table td {
  border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.ui-table th:last-child, .ui-table td:last-child { border-right: 0; }

/* Label row: the strongest header, sticky, with the resize strip. */
.ui-table thead tr.ui-label-row th {
  position: sticky;
  top: 0;
  z-index: 8;
  height: 34px;
  padding: 2px 8px;
  background: var(--soft-2);
  border-bottom: 1.5px solid var(--grid);
  color: var(--navy);
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-align: center;
  text-transform: uppercase;
  vertical-align: middle;
}

.ui-label-text {
  display: inline-block;
  max-width: calc(100% - 10px);
  line-height: 1.1;
  white-space: normal;
  vertical-align: middle;
}

/*
   One header row, carrying both controls.

   The cell is the sort button: click it, or tab to it and press Enter. The
   direction is an arrow after the label at 8px, and the filter funnel sits in the
   bottom-right corner -- 14x14, no chrome, 7px in and 3px up, which is Genesis's
   placement measured from its stylesheet. Genesis builds a second row of tool
   buttons and then folds it into this cell at runtime; this renders the folded
   form, so there is no intermediate state and no DOM to move after paint.
*/
.ui-table thead th.ui-sortable { cursor: pointer; padding-right: 24px; }
.ui-table thead th.ui-sortable:hover { background: var(--line); }
.ui-table thead th.ui-sortable:focus-visible { outline: 2px solid var(--blue); outline-offset: -2px; }

.ui-table thead th.ui-sortable .ui-label-text::after { content: " \2195"; font-size: 8px; opacity: 0.45; }
.ui-table thead th.ui-sort-asc .ui-label-text::after { content: " \25B2"; font-size: 8px; opacity: 1; }
.ui-table thead th.ui-sort-desc .ui-label-text::after { content: " \25BC"; font-size: 8px; opacity: 1; }

.ui-filter-btn {
  position: absolute;
  right: 7px;
  bottom: 3px;
  width: 14px;
  height: 14px;
  min-height: 14px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--green);
  cursor: pointer;
}

.ui-filter-btn svg {
  width: 11px;
  height: 11px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.ui-filter-btn:hover { color: var(--navy); }
.ui-filter-btn.active { color: var(--blue-dark); }
.ui-filter-btn.active svg { fill: currentColor; }

/* The grab strip. Hangs 3px past the column edge so the target is the boundary
   rather than the header's inside edge. */
/*
   The grab strip straddles the column boundary, 3px of it outside the cell, so
   the cursor changes slightly before the border rather than exactly on it.

   On the last column there is no boundary to straddle and those 3px hang off the
   table, which is enough to make the wrap scroll horizontally by 3px -- a
   scrollbar under a table that fits, on every screen in the console. Measured
   2026-08-31 while fitting nine columns into one page width: 1226 scroll against
   1223 client, and the difference was this.
*/
.ui-table th:last-child .ui-resize { right: 0; }

.ui-resize {
  position: absolute;
  top: 0;
  right: -3px;
  width: 8px;
  height: 100%;
  cursor: col-resize;
  z-index: 3;
  touch-action: none;
}

/* Both header rows are sticky, which also makes each th a containing block --
   that is what the absolutely positioned resize strip is measured against. */

body.ui-resizing { cursor: col-resize; user-select: none; }

.ui-table tbody td {
  padding: 6px 8px;
  color: var(--ink);
  /* Truncate rather than widen: the standard forbids a memo column forcing the
     page to scroll, and the title attribute carries the rest. */
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  vertical-align: middle;
}

.ui-table tbody tr:hover td { background: var(--soft); }

.ui-num { text-align: right; font-variant-numeric: tabular-nums; }
.ui-mono { font-family: var(--font-mono); font-size: 12px; color: var(--navy); }
.ui-none { color: var(--muted); }

.ui-empty-row td { color: var(--muted); text-align: center; padding: 14px 8px; }

/* Total row: bold, header-family shading, and a 2px rule above it only. */
.ui-table tfoot tr.ui-total-row td {
  padding: 7px 8px;
  background: var(--soft-2);
  border-top: 2px solid var(--navy);
  color: var(--navy);
  font-weight: 800;
}

.ui-pill {
  display: inline-block;
  padding: 1px 7px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--soft-2);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 700;
  white-space: nowrap;
}

.ui-pill.ok { border-color: var(--green-line); background: var(--green-tint); color: var(--green); }
.ui-pill.warn { border-color: var(--amber-line); background: var(--amber-tint); color: var(--amber); }
.ui-pill.bad { border-color: var(--red-line); background: var(--red-tint); color: var(--red); }

/* ---- filter popover ---- */

.ui-filter-popover {
  position: fixed;
  z-index: 60;
  display: grid;
  gap: 8px;
  width: 320px;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--white);
  box-shadow: var(--shadow);
}

.ui-filter-title { color: var(--navy); font-size: 13px; font-weight: 800; }

.ui-filter-search {
  width: 100%;
  padding: 6px 8px;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: var(--white);
  color: var(--ink);
  font: inherit;
  font-size: 12.5px;
}

.ui-filter-actions, .ui-filter-footer { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ui-filter-footer { justify-content: flex-end; }
.ui-filter-count { color: var(--muted); font-size: 11.5px; font-family: var(--font-mono); }

.ui-filter-list {
  overflow: auto;
  min-height: 120px;
  max-height: 240px;
  padding: 5px;
  border: 1px solid var(--line);
  border-radius: 8px;
}

.ui-filter-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 5px;
  border-radius: 5px;
  color: var(--ink);
  font-size: 12.5px;
  cursor: pointer;
}

.ui-filter-item:hover { background: var(--soft); }
.ui-filter-item input { margin: 0; accent-color: var(--blue); }
.ui-filter-item span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

@media print {
  /* Controls are not content: they have no meaning on paper, and printed output
     must match the screen's rows and columns rather than its buttons. */
  .ui-table-meta, .ui-resize, .ui-filter-btn { display: none; }
  .ui-table thead th.ui-sortable { padding-right: 8px; }
  .ui-table thead th.ui-sortable .ui-label-text::after { content: ""; }
  .ui-table-wrap { overflow: visible; border-color: var(--navy); }
}

/* ---------------------------------------------------------------------------
   Genesis table skin, and the compact density
   ---------------------------------------------------------------------------

   Opt-in, per table, with .ui-table--genesis. The console keeps its indigo
   palette everywhere else; a dense operational grid gets Genesis's, because an
   operator scans it by column and needs the header band and the gridlines to
   carry structure that flat grey does not.

   Every value is a token. A hex here is what the standard forbids and what the
   archaeology report exists to find.
*/
.ui-table--genesis thead tr.ui-label-row th {
  background: var(--g-table-header-bg);
  color: var(--g-table-header-text);
  border-bottom: 1.5px solid var(--g-table-header-rule);
}

.ui-table--genesis thead th.ui-sortable:hover { background: var(--g-table-row-selected); }

.ui-table--genesis th,
.ui-table--genesis td { border-right: 1px solid var(--g-table-grid); border-bottom: 1px solid var(--g-table-grid); }
.ui-table--genesis th:last-child,
.ui-table--genesis td:last-child { border-right: 0; }

.ui-table--genesis tbody td { color: var(--g-table-body-text); }

/* Zebra before hover, so hover still reads as a change on every row. */
.ui-table--genesis tbody tr:nth-child(even) td { background: var(--g-table-row-alt); }
.ui-table--genesis tbody tr:hover td { background: var(--g-table-row-hover); }

/*
   The key column.

   Tinted so the eye can find its place after scrolling sideways. Applied to the
   cell rather than to a column element, because a colgroup background paints
   under the sticky header on Safari and the header stops being opaque.
*/
.ui-table--genesis td.ui-key-col,
.ui-table--genesis th.ui-key-col { background: var(--g-table-key-col); }
.ui-table--genesis tbody tr:hover td.ui-key-col { background: var(--g-table-row-hover); }

/* Selection persists, so it has to beat both zebra and hover. */
.ui-table--genesis tbody tr.ui-row-selected td,
.ui-table--genesis tbody tr.ui-row-selected:hover td,
.ui-table--genesis tbody tr.ui-row-selected td.ui-key-col {
  background: var(--g-table-row-selected);
  color: var(--g-table-header-text);
}

/* A selectable table says so on hover, before the operator commits to a click. */
.ui-table--selectable tbody tr { cursor: pointer; }
.ui-table--selectable tbody tr:focus-visible { outline: 2px solid var(--blue); outline-offset: -2px; }

/*
   Compact density.

   Ten rows and nine columns inside one page width, which is what an operator
   asked for and what the standard's density section requires: a toggle or a
   short select must not stretch to full width. Row height drops from 30px to
   24px and the type from 13px to 12px -- below that, tabular figures stop being
   comfortably scannable, which is the floor the deck's type pass found too.
*/
/*
   Reserve the vertical scrollbar's width, always.

   Measured, not guessed: with ten rows capped and an eleventh account present,
   the scrollbar appears, takes ~15px off the client width, and pushes a table
   that fitted at 1238px in 1240px into horizontal scroll. The columns had not
   changed -- the room had. Reserving the gutter means a list crossing ten rows
   does not suddenly start scrolling sideways, which is the exact "horizontal
   overflow" the Genesis table standard forbids.
*/
.ui-table-wrap { scrollbar-gutter: stable; }

.ui-table--compact { font-size: 12px; }
.ui-table--compact thead tr.ui-label-row th { height: 26px; padding: 1px 6px; font-size: 9.5px; }
.ui-table--compact tbody td { padding: 3px 6px; line-height: 1.35; }
.ui-table--compact .ui-mono { font-size: 11px; }
.ui-table--compact tfoot tr.ui-total-row td { padding: 4px 6px; }

/*
   The row switch.

   A real checkbox under a painted track, not a div pretending to be one: it
   tabs, it takes a space bar, a screen reader calls it a checkbox, and the
   label travels with it. The painted part is the ::before/::after on the label.

   Sized to the compact row -- 30x16 inside a 24px row -- because the standard is
   explicit that a toggle must not stretch, and because a control taller than its
   row is what makes a table's row heights go uneven.
*/
.ui-act-cell { text-align: center; padding: 0 4px; }

.ui-switch { position: relative; display: inline-block; width: 30px; height: 16px; vertical-align: middle; }
.ui-switch input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}
.ui-switch .ui-switch-track {
  position: absolute;
  inset: 0;
  border-radius: 999px;
  background: var(--g-table-header-rule);
  transition: background 120ms ease;
  pointer-events: none;
}
.ui-switch .ui-switch-track::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--white);
  transition: transform 120ms ease;
}
.ui-switch input:checked + .ui-switch-track { background: var(--green); }
.ui-switch input:checked + .ui-switch-track::after { transform: translateX(14px); }
.ui-switch input:focus-visible + .ui-switch-track { outline: 2px solid var(--blue); outline-offset: 2px; }
.ui-switch input:disabled + .ui-switch-track { opacity: 0.5; cursor: progress; }
