/* ==========================================================================
   QZONE OMS — TABLES
   Dense, ruled, tabular figures. Header is a small-caps rule, not a colored
   band. Rows are separated by hairlines only.

   Two responsive strategies, pick per table:
     .qz-table-wrap        horizontal scroll with a sticky first column
     .qz-table--stack      collapses to label/value cards under 768px
   ========================================================================== */

.qz-table-wrap {
  position: relative;
  width: 100%;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
  border-radius: var(--qz-r-lg);
  background: var(--qz-surface-2);
  box-shadow: var(--qz-ring);
}
/* When a table sits directly inside a surface, don't double the chrome. */
.qz-surface .qz-table-wrap,
.qz-surface__body--flush .qz-table-wrap { border-radius: 0; box-shadow: none; background: transparent; }

.qz-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--qz-fs-sm);
  font-variant-numeric: tabular-nums;
}

/* The vertical padding matters as much as the row height. `height` on a cell
   is a MINIMUM, so single-line rows still land on exactly --qz-row-h; the
   padding only does work once a cell holds something taller (a stacked name +
   sub-label, a wrapped note, a badge row), which is where the old zero-padding
   rule crushed content against the row rules. */
.qz-table th,
.qz-table td {
  padding: var(--qz-s-2) var(--qz-s-4);
  height: var(--qz-row-h);
  text-align: left;
  vertical-align: middle;
  white-space: nowrap;
}

.qz-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  height: 34px;
  padding-top: 0;
  padding-bottom: 0;
  background: var(--qz-surface-inset);
  border-bottom: 1px solid var(--qz-line);
  color: var(--qz-text-mute);
  font-size: var(--qz-fs-2xs);
  font-weight: 600;
  letter-spacing: var(--qz-track-label);
  text-transform: uppercase;
  white-space: nowrap;
}

.qz-table tbody td {
  border-bottom: 1px solid var(--qz-line-soft);
  color: var(--qz-text-dim);
}
.qz-table tbody tr:last-child td { border-bottom: 0; }

.qz-table tbody tr { transition: background-color var(--qz-dur-fast) var(--qz-ease); }
.qz-table tbody tr:hover td { background: var(--qz-surface-3); color: var(--qz-text); }

/* The first cell carries the row's identity, so it gets full-strength text. */
.qz-table tbody td:first-child { color: var(--qz-text); font-weight: 500; }

.qz-table tr.is-clickable { cursor: pointer; }
.qz-table tr.is-selected td { background: var(--qz-accent-weaker); }

/* Alignment + width helpers */
.qz-table .qz-num,
.qz-table .qz-t-right { text-align: right; font-family: var(--qz-font-mono); }
.qz-table .qz-t-center { text-align: center; }
.qz-table .qz-t-wrap { white-space: normal; min-width: 220px; }
.qz-table .qz-t-fit { width: 1%; }

/* Row actions — revealed on hover on pointer devices, always shown on touch */
.qz-table__actions { display: flex; align-items: center; gap: 4px; justify-content: flex-end; }
@media (hover: hover) and (pointer: fine) {
  .qz-table__actions { opacity: 0; transition: opacity var(--qz-dur-fast) var(--qz-ease); }
  .qz-table tbody tr:hover .qz-table__actions,
  .qz-table tbody tr:focus-within .qz-table__actions { opacity: 1; }
}

/* Sticky identity column for wide tables */
.qz-table--sticky thead th:first-child,
.qz-table--sticky tbody td:first-child {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--qz-surface-2);
}
.qz-table--sticky thead th:first-child { z-index: 3; background: var(--qz-surface-inset); }
.qz-table--sticky tbody tr:hover td:first-child { background: var(--qz-surface-3); }
/* A hairline marks where the frozen column ends */
.qz-table--sticky thead th:first-child::after,
.qz-table--sticky tbody td:first-child::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 1px;
  background: var(--qz-line);
}

/* Compact / roomy variants. Both restate the vertical padding so they stay in
   proportion to the new default rather than inheriting it and drifting. */
.qz-table--compact th, .qz-table--compact td { height: 32px; padding: var(--qz-s-1) var(--qz-s-3); font-size: var(--qz-fs-xs); }
.qz-table--roomy th,   .qz-table--roomy td   { height: 52px; padding: var(--qz-s-3) var(--qz-s-4); }

/* Cell composites */
.qz-cell-id { font-family: var(--qz-font-mono); font-size: var(--qz-fs-xs); color: var(--qz-text-mute); }
.qz-cell-person { display: flex; align-items: center; gap: var(--qz-s-2); }
.qz-cell-person__name { font-weight: 500; color: var(--qz-text); }
.qz-cell-person__sub { font-size: var(--qz-fs-2xs); color: var(--qz-text-mute); }
/* The cell itself now carries the vertical padding, so the stack no longer
   adds its own — otherwise the two compound and stacked rows sit too tall. */
.qz-cell-stack { display: flex; flex-direction: column; line-height: 1.3; }
.qz-cell-stack__sub { font-size: var(--qz-fs-2xs); color: var(--qz-text-mute); }

/* Table footer / summary row */
.qz-table tfoot td {
  height: 34px;
  background: var(--qz-surface-inset);
  border-top: 1px solid var(--qz-line);
  color: var(--qz-text);
  font-weight: 600;
  font-family: var(--qz-font-mono);
}

/* Empty row */
.qz-table__empty td { height: auto; padding: 0; }

/* ==========================================================================
   STACKED TABLES — under 768px, rows become label/value cards.
   Requires each <td> to carry data-label="Column name".
   ========================================================================== */

@media (max-width: 767.98px) {
  .qz-table--stack { display: block; }
  .qz-table--stack thead { display: none; }
  .qz-table--stack tbody,
  .qz-table--stack tfoot { display: block; }

  .qz-table--stack tbody tr {
    display: block;
    margin-bottom: var(--qz-s-2);
    padding: var(--qz-s-1) 0;
    border-radius: var(--qz-r-lg);
    background: var(--qz-surface-2);
    box-shadow: var(--qz-ring);
  }
  .qz-table--stack tbody tr:hover td { background: transparent; }

  .qz-table--stack tbody td {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--qz-s-4);
    height: auto;
    min-height: 34px;
    padding: 7px var(--qz-s-3);
    border-bottom: 1px solid var(--qz-line-soft);
    white-space: normal;
    text-align: right;
  }
  .qz-table--stack tbody tr td:last-child { border-bottom: 0; }

  /* The column name comes from the cell's own data-label */
  .qz-table--stack tbody td::before {
    content: attr(data-label);
    flex: 0 0 auto;
    font-size: var(--qz-fs-2xs);
    font-weight: 600;
    letter-spacing: var(--qz-track-label);
    text-transform: uppercase;
    color: var(--qz-text-mute);
    text-align: left;
  }
  /* Cells with no label span the full width (action rows, etc.) */
  .qz-table--stack tbody td:not([data-label])::before { content: none; }
  .qz-table--stack tbody td:not([data-label]) { justify-content: flex-end; }

  /* The identity cell becomes the card's header */
  .qz-table--stack tbody td:first-child {
    background: var(--qz-surface-inset);
    border-radius: var(--qz-r-md) var(--qz-r-md) 0 0;
    font-weight: 600;
    font-size: var(--qz-fs-base);
  }

  .qz-table--stack .qz-table__actions { opacity: 1; width: 100%; justify-content: stretch; }
  .qz-table--stack .qz-table__actions > * { flex: 1 1 auto; }

  /* Stacked tables never need to scroll sideways */
  .qz-table-wrap:has(.qz-table--stack) { overflow-x: visible; background: transparent; box-shadow: none; border-radius: 0; }
}

/* ==========================================================================
   PAGINATION
   ========================================================================== */

.qz-pagination {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--qz-s-3);
  flex-wrap: wrap;
  padding: var(--qz-s-3) var(--qz-s-4);
  border-top: 1px solid var(--qz-line-soft);
}
.qz-pagination__info { font-size: var(--qz-fs-xs); color: var(--qz-text-mute); font-variant-numeric: tabular-nums; }
.qz-pagination__pages { display: flex; align-items: center; gap: 3px; }
.qz-pagination__page {
  display: grid;
  place-items: center;
  min-width: 28px;
  height: 28px;
  padding: 0 6px;
  border-radius: var(--qz-r-pill);
  background: transparent;
  border: 0;
  color: var(--qz-text-dim);
  font-family: var(--qz-font-mono);
  font-size: var(--qz-fs-xs);
  cursor: pointer;
  transition: background-color var(--qz-dur-fast) var(--qz-ease), color var(--qz-dur-fast) var(--qz-ease);
}
/* The server-side pager draws these as real links so it survives with
   JavaScript off; the client-side one builds <button>s. Both must land on the
   same pixels, so the anchor's underline and inherited link colour go — the
   colour is restated to hold off base.css's `a:hover`, which at (0,1,1)
   outranks the class rule below on its own. */
a.qz-pagination__page { text-decoration: none; color: var(--qz-text-dim); }

.qz-pagination__page:hover { background: var(--qz-surface-3); color: var(--qz-text); }
a.qz-pagination__page:hover { text-decoration: none; color: var(--qz-text); }
.qz-pagination__page.is-active { background: var(--qz-accent); color: var(--qz-on-accent); font-weight: 700; }
a.qz-pagination__page.is-active,
a.qz-pagination__page.is-active:hover { color: var(--qz-on-accent); }
.qz-pagination__page.is-disabled { color: var(--qz-text-faint); pointer-events: none; }

/* Says out loud that "All" stopped short of all. Only the server-side pager can
   need this — the client-side one never has more rows than it was given. */
.qz-pagination__note { color: var(--qz-warn); font-weight: 600; }

/* A jump in the run of page numbers (1 … 6 7 8 … 20). Sized to a page button so
   the row of them keeps an even rhythm across the gap. */
.qz-pagination__gap {
  display: grid;
  place-items: center;
  min-width: 20px;
  height: 28px;
  color: var(--qz-text-faint);
  font-size: var(--qz-fs-xs);
  user-select: none;
}

/* Rows-per-page. A label wrapping its select, so the words either side of it
   are part of the hit target rather than decoration next to one. */
.qz-pagination__size {
  display: flex;
  align-items: center;
  gap: var(--qz-s-2);
  margin: 0;
  font-size: var(--qz-fs-xs);
  color: var(--qz-text-mute);
  white-space: nowrap;
  cursor: pointer;
}

/* The form select is a block that fills its field; here it is one word in a
   sentence, and sits at the height of the page buttons beside it. */
.qz-pagination__size .qz-select {
  width: auto;
  min-height: var(--qz-control-h-sm);
  padding: 0 var(--qz-s-6) 0 var(--qz-s-2);
  line-height: var(--qz-control-h-sm);
  background-position: right var(--qz-s-2) center;
  background-size: 13px;
  font-family: var(--qz-font-mono);
  font-size: var(--qz-fs-xs);
  font-variant-numeric: tabular-nums;
}

/* Dropped into a container that already pads its own edges — a card body, say.
   Only the sides go: the rule above the pager still wants air under the table.
   Without this the footer sits indented from the table it belongs to. */
.qz-pagination--flush { padding-inline: 0; }

/* The pager is display:flex, which a bare `hidden` attribute cannot outrank —
   and it ships hidden, for the stretch before its controller is up. */
.qz-pagination[hidden] { display: none; }

@media (max-width: 575.98px) {
  .qz-pagination { justify-content: center; }
  .qz-pagination__info { width: 100%; text-align: center; }
}

/* ==========================================================================
   ROW ACTIONS — .qz-rowactions / .qz-rowact
   Ported from QZONE Scheduler so the two consoles read as one product.

   Icon-only controls that repeat once per table row. Square, so a wide glyph
   (the PDF page) and a narrow one (the eye) sit on the same grid instead of
   the ragged widths `btn-sm px-3` gave them.

   Each one carries its meaning colour at rest — a tinted face, an accent
   hairline and an accent glyph — because in a long table these are the only
   controls there are, and an operator scanning for Delete should find it by
   colour, not by counting positions. Hover fills the face solid with the same
   accent, so the target you are about to commit to is unmistakable. Nothing
   lifts or moves: clickable things react, and they react with colour.

   Variants set --ra (accent), --ra-tint (rest face) and --ra-ink (glyph once
   filled); the base rule does the rest.
   ========================================================================== */

.qz-rowactions {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.qz-rowactions--center { justify-content: center; }
.qz-rowactions--end   { justify-content: flex-end; }

/* button_to — and the hand-rolled form_with wrappers around a toggle or a
   delete — put a form between the cluster and its button. Let the button
   itself be the flex item so it keeps the 8px rhythm with its link siblings. */
.qz-rowactions > form { display: contents; }
.qz-rowactions form   { margin: 0; }

.qz-rowact {
  --ra: var(--qz-text-mute);
  --ra-tint: var(--qz-surface-3);
  --ra-ink: #fff;

  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 1px solid var(--ra);
  border-radius: var(--qz-r-xl);
  background: var(--ra-tint);
  color: var(--ra);
  font-size: 0.85rem;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--qz-dur-fast) var(--qz-ease),
              border-color var(--qz-dur-fast) var(--qz-ease),
              color var(--qz-dur-fast) var(--qz-ease);
}

.qz-rowact i { font-size: 0.875rem; line-height: 1; }

.qz-rowact:hover,
.qz-rowact:focus-visible {
  background: var(--ra);
  border-color: var(--ra);
  color: var(--ra-ink);
}

.qz-rowact:focus-visible { outline: none; box-shadow: var(--qz-focus); }

.qz-rowact:disabled,
.qz-rowact.disabled {
  opacity: 0.45;
  pointer-events: none;
}

.qz-rowact--view    { --ra: var(--qz-info);   --ra-tint: var(--qz-info-weak); }
.qz-rowact--doc     { --ra: var(--qz-accent); --ra-tint: var(--qz-accent-weak); }
.qz-rowact--primary { --ra: var(--qz-accent); --ra-tint: var(--qz-accent-weak); }
.qz-rowact--edit    { --ra: var(--qz-warn);   --ra-tint: var(--qz-warn-weak); }
.qz-rowact--lock    { --ra: var(--qz-warn);   --ra-tint: var(--qz-warn-weak); }
.qz-rowact--unlock  { --ra: var(--qz-ok);     --ra-tint: var(--qz-ok-weak); }
.qz-rowact--renew   { --ra: var(--qz-ok);     --ra-tint: var(--qz-ok-weak); }
.qz-rowact--ok      { --ra: var(--qz-ok);     --ra-tint: var(--qz-ok-weak); }
.qz-rowact--danger  { --ra: var(--qz-crit);   --ra-tint: var(--qz-crit-weak); }
.qz-rowact--muted   { --ra: var(--qz-idle);   --ra-tint: var(--qz-idle-weak); }

/* Dark is the default scheme here, and its cyan, amber, mint and accent are
   light enough that a white glyph on the filled face would sit under 3:1 —
   ink those instead. Amber stays inked in light too: white on #c28a00 is
   under 3:1 either way. */
.qz-rowact--view,
.qz-rowact--doc,
.qz-rowact--primary,
.qz-rowact--edit,
.qz-rowact--lock,
.qz-rowact--unlock,
.qz-rowact--renew,
.qz-rowact--ok { --ra-ink: #05141d; }

[data-theme="light"] .qz-rowact--view,
[data-theme="light"] .qz-rowact--doc,
[data-theme="light"] .qz-rowact--primary,
[data-theme="light"] .qz-rowact--unlock,
[data-theme="light"] .qz-rowact--renew,
[data-theme="light"] .qz-rowact--ok { --ra-ink: #fff; }
