/* ==================================================================
   th-grid — Threshold cross-destination tabular canon
   ------------------------------------------------------------------
   One shared chrome substrate for every Threshold tabular destination
   (Submissions, Users, Roles, Invitations, Audit, Prospects, …).

   Namespace: .th-grid-*  (sibling to the .cc-* chrome family, but a
   distinct, newer canon atom with its own ownership boundary).

   Domain affordances (status pills, completion bars, audit KindPill,
   per-destination filter rails) live DOWNSTREAM of this — they layer
   on top of the cell, they are not defined here. The canon owns the
   table; the destination owns what goes in the cells.

   Recreated from the design handoff (design_handoff_tabular_canon/
   th-grid.css). The handoff's unprefixed tokens (--paper, --ink-2,
   --advant, --t-14, --r-5, …) are remapped to Threshold's canonical
   --th-* token layer (--th-paper, --th-ink-2, --th-advant, --th-size-14,
   --th-radius-5, …) so the one-home token rule holds and a theme swap
   flows through untouched.

   Axes are driven by data-attributes on a root container so the host
   can flip the whole surface at once:
     [data-density]  comfortable | compact
     [data-sep]      hairline | zebra
     [data-select]   always | hover
     [data-sticky]   on | off
     [data-accent]   advant            (default; selection = action role)

   The handoff's [data-accent="marigold"] (editorial/authoring accent)
   is intentionally deferred until an authoring surface becomes tabular
   — every current tabular destination is a viewing/operations surface,
   so selection is advant by role. Keeps the ADR-0035 locked-accent
   inventory untouched.
   ================================================================== */

:root {
  /* Canon-local tokens. They reference the base Threshold ramp so a
     theme swap (light/dark) flows through untouched. Density values
     are overridden by [data-density] below. */
  --grid-cell-px:   14px;
  --grid-cell-py:   11px;
  --grid-row-min:   46px;
  --grid-lead:      var(--th-size-14);
  --grid-meta:      11.5px;

  --grid-sel:       var(--th-advant);
  --grid-sel-soft:  var(--th-advant-soft);
  --grid-sel-ink:   var(--th-advant-deep);
}

/* ---- Density --------------------------------------------------- */
[data-density="compact"] {
  --grid-cell-px: 12px;
  --grid-cell-py: 6px;
  --grid-row-min: 33px;
  --grid-lead:    var(--th-size-13);
}

/* ==================================================================
   Surface scaffold — head, toolbar, meta, wrap
   ================================================================== */
.th-grid-surface {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.th-grid-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  padding: 0 0 14px;
}
.th-grid-head h2 {
  margin: 0;
  font-size: var(--th-size-20);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--th-ink);
}
.th-grid-head .sub {
  margin-top: 3px;
  font-size: var(--grid-meta);
  color: var(--th-ink-3);
}
.th-grid-head-actions { display: flex; gap: 8px; flex: 0 0 auto; }

/* Toolbar — search + filter chips left, view controls right */
.th-grid-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  background: var(--th-paper-sunk);
  border: 1px solid var(--th-line);
  border-bottom: none;
  border-radius: var(--th-radius-5) var(--th-radius-5) 0 0;
  flex-wrap: wrap;
}
.th-grid-toolbar .spacer { flex: 1; }
.th-grid-search {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 10px;
  min-width: 220px;
  background: var(--th-paper);
  border: 1px solid var(--th-line-2);
  border-radius: var(--th-radius-5);
  color: var(--th-ink-4);
  font-size: var(--th-size-13);
}
.th-grid-search input {
  border: none; outline: none; background: transparent;
  font: inherit; color: var(--th-ink); flex: 1; min-width: 0;
  font-size: var(--th-size-13);
}
.th-grid-search kbd {
  font-family: var(--th-f-mono); font-size: 10px;
  color: var(--th-ink-4);
  background: var(--th-paper-2);
  border: 1px solid var(--th-line);
  border-radius: var(--th-radius-3);
  padding: 0 4px;
}

/* Result meta strip */
.th-grid-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 14px;
  font-family: var(--th-f-mono);
  font-size: var(--grid-meta);
  color: var(--th-ink-3);
  background: var(--th-paper-sunk);
  border: 1px solid var(--th-line);
  border-bottom: none;
}
.th-grid-meta b { color: var(--th-ink); font-weight: 600; }
.th-grid-meta .dim { color: var(--th-ink-4); }
.th-grid-toolbar + .th-grid-meta { border-top: 1px solid var(--th-line-soft); }

/* The scroll wrap holds the border + radius + sticky context */
.th-grid-wrap {
  border: 1px solid var(--th-line);
  border-radius: var(--th-radius-5);
  background: var(--th-paper-sunk);
  overflow: hidden;
}
/* When stacked under a toolbar/meta the top corners square up */
.th-grid-toolbar + .th-grid-wrap,
.th-grid-meta + .th-grid-wrap { border-radius: 0 0 var(--th-radius-5) var(--th-radius-5); }

[data-sticky="on"] .th-grid-wrap.is-scroll {
  max-height: 360px;
  overflow: auto;
}

/* ==================================================================
   The grid itself
   ================================================================== */
.th-grid {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--grid-lead);
}

/* ---- Header ---------------------------------------------------- */
.th-grid thead th {
  text-align: left;
  padding: 8px var(--grid-cell-px);
  font-weight: 600;
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--th-ink-3);
  background: var(--th-paper-2);
  border-bottom: 1px solid var(--th-line);
  white-space: nowrap;
  vertical-align: middle;
}
[data-sticky="on"] .th-grid-wrap.is-scroll thead th {
  position: sticky; top: 0; z-index: 2;
}
.th-grid thead th.is-num { text-align: right; }
.th-grid thead th.is-center { text-align: center; }

/* Sortable header — opt-in. Renders as a button so it's keyboard- and
   AT-reachable. Sort glyph is faint until hover; solid on the active
   sort column. */
.th-grid-sort {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: inherit;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}
.is-num .th-grid-sort { flex-direction: row-reverse; }
.th-grid-sort .arw {
  font-family: var(--th-f-mono);
  font-size: 10px;
  line-height: 1;
  color: var(--th-ink-4);
  opacity: 0;
  transition: opacity 90ms ease;
}
.th-grid-sort:hover { color: var(--th-ink); }
.th-grid-sort:hover .arw { opacity: 0.6; }
.th-grid th.is-sorted .th-grid-sort { color: var(--th-ink); }
.th-grid th.is-sorted .th-grid-sort .arw { opacity: 1; color: var(--grid-sel-ink); }
.th-grid-sort:focus-visible { outline: 2px solid var(--grid-sel); outline-offset: 2px; border-radius: var(--th-radius-2); }

/* ---- Body cells ------------------------------------------------ */
.th-grid tbody td {
  padding: var(--grid-cell-py) var(--grid-cell-px);
  border-bottom: 1px solid var(--th-line-soft);
  color: var(--th-ink);
  vertical-align: middle;
  height: var(--grid-row-min);
}
.th-grid tbody tr:last-child td { border-bottom: none; }

.th-grid td.is-num   { font-family: var(--th-f-mono); font-variant-numeric: tabular-nums; text-align: right; color: var(--th-ink-2); white-space: nowrap; }
.th-grid td.is-key   { font-family: var(--th-f-mono); font-size: var(--th-size-13); color: var(--th-ink-2); white-space: nowrap; }
.th-grid td.is-center{ text-align: center; }

/* Lead cell — primary + secondary stacked. The primary line is the
   link target when the destination is navigable. */
.th-grid-lead { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.th-grid-lead .pri {
  font-weight: 500; color: var(--th-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.th-grid-lead .sec {
  font-size: 11.5px; color: var(--th-ink-3);
}
.th-grid-lead .sec.mono { font-family: var(--th-f-mono); }
a.th-grid-link {
  color: var(--th-ink); text-decoration: none; font-weight: 500;
  border-bottom: 1px solid transparent;
}
a.th-grid-link:hover { color: var(--grid-sel-ink); border-bottom-color: var(--grid-sel); }
[data-density="compact"] .th-grid-lead .sec { display: none; }
[data-density="compact"] .th-grid-lead.keep-sec .sec { display: block; }

/* ---- Row states ------------------------------------------------ */
.th-grid tbody tr.th-grid-row { transition: background 80ms ease; }
.th-grid tbody tr.th-grid-row:hover { background: var(--th-paper-2); }
.th-grid tbody tr.is-navigable { cursor: pointer; }

/* Zebra — opt-in via [data-sep="zebra"]; hover always wins. */
[data-sep="zebra"] .th-grid tbody tr.th-grid-row:nth-child(even) { background: var(--th-paper-2); }
[data-sep="zebra"] .th-grid tbody tr.th-grid-row:nth-child(even):hover { background: var(--th-paper-3); }
[data-sep="zebra"] .th-grid tbody td { border-bottom-color: transparent; }

/* Selected — soft accent fill + a 2px accent edge marker. */
.th-grid tbody tr.is-selected,
[data-sep="zebra"] .th-grid tbody tr.is-selected:nth-child(even) {
  background: var(--grid-sel-soft);
}
.th-grid tbody tr.is-selected td:first-child { box-shadow: inset 2px 0 0 var(--grid-sel); }
.th-grid tbody tr.is-selected:hover { background: var(--grid-sel-soft); filter: brightness(0.985); }

/* ---- Select column -------------------------------------------- */
.th-grid-cb {
  appearance: none;
  width: 14px; height: 14px;
  border: 1px solid var(--th-line-2);
  border-radius: 3px;
  background: var(--th-paper);
  cursor: pointer;
  vertical-align: middle;
  flex: 0 0 auto;
}
.th-grid-cb:checked {
  background: var(--grid-sel);
  border-color: var(--grid-sel);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'><path d='M3 7l3 3 5-6' stroke='white' stroke-width='2' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-size: contain;
}
/* The indeterminate dash. Native :indeterminate is a JS-only IDL property;
   .is-indeterminate is a Blazor-settable class mirror so the partial-select
   glyph works without interop (and stays bUnit-testable). The native IDL
   property (for AT "mixed" announcement) is wired by the first select-primary
   destination that needs it; this class covers the visual until then. */
.th-grid-cb:indeterminate,
.th-grid-cb.is-indeterminate {
  background: var(--grid-sel); border-color: var(--grid-sel);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'><path d='M3.5 7h7' stroke='white' stroke-width='2' fill='none' stroke-linecap='round'/></svg>");
  background-size: contain;
}
.th-grid-cb:focus-visible { outline: 2px solid var(--grid-sel); outline-offset: 2px; }
.th-grid td.is-select, .th-grid th.is-select { width: 36px; padding-right: 0; }

/* Reveal-on-hover selection: checkbox column is reserved (layout
   stable) but the box only appears on row hover / focus / selected.
   Header box stays visible so the affordance is discoverable. */
[data-select="hover"] .th-grid td.is-select .th-grid-cb {
  opacity: 0; transition: opacity 80ms ease;
}
[data-select="hover"] .th-grid tr:hover .is-select .th-grid-cb,
[data-select="hover"] .th-grid tr:focus-within .is-select .th-grid-cb,
[data-select="hover"] .th-grid tr.is-selected .is-select .th-grid-cb { opacity: 1; }

/* ---- Expand column (audit-style) ------------------------------- */
.th-grid-expand {
  width: 22px; height: 22px;
  display: inline-flex; align-items: center; justify-content: center;
  border: none; background: none; cursor: pointer;
  color: var(--th-ink-4); border-radius: var(--th-radius-3);
}
.th-grid-expand:hover { background: var(--th-paper-3); color: var(--th-ink-2); }
.th-grid-expand svg { transition: transform 110ms ease; }
.th-grid tr.is-expanded .th-grid-expand svg { transform: rotate(90deg); }
.th-grid td.is-expand, .th-grid th.is-expand { width: 34px; }

.th-grid tr.th-grid-detail-row > td {
  padding: 0;
  background: var(--th-paper-2);
  border-bottom: 1px solid var(--th-line-soft);
}
.th-grid-detail {
  padding: 12px 16px 14px;
  font-size: var(--th-size-13);
  color: var(--th-ink-2);
}

/* ---- Row actions ---------------------------------------------- */
.th-grid-rowactions {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  justify-content: flex-end;
}
.th-grid-rowactions .reveal {
  opacity: 0; transition: opacity 80ms ease;
}
.th-grid tr:hover .th-grid-rowactions .reveal,
.th-grid tr:focus-within .th-grid-rowactions .reveal { opacity: 1; }
.th-grid-action {
  font-size: 11.5px;
  padding: 2px 8px;
  border: 1px solid var(--th-line-2);
  border-radius: var(--th-radius-3);
  background: var(--th-paper);
  color: var(--th-ink-2);
  cursor: pointer;
  white-space: nowrap;
}
.th-grid-action:hover { border-color: var(--th-ink-4); color: var(--th-ink); }
.th-grid-action.is-danger:hover { border-color: var(--th-risk); color: var(--th-risk); background: var(--th-risk-soft); }
.th-grid-kebab {
  width: 24px; height: 24px;
  display: inline-flex; align-items: center; justify-content: center;
  border: none; background: none; cursor: pointer;
  color: var(--th-ink-4); border-radius: var(--th-radius-3); flex: 0 0 auto;
}
.th-grid-kebab:hover { background: var(--th-paper-3); color: var(--th-ink); }
.th-grid td.is-actions, .th-grid th.is-actions { text-align: right; white-space: nowrap; width: 1%; }

/* ==================================================================
   Bulk-action bar — replaces the meta strip when ≥1 row selected
   ================================================================== */
.th-grid-bulkbar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 12px;
  background: var(--grid-sel-soft);
  border: 1px solid var(--grid-sel);
  border-bottom: none;
  color: var(--grid-sel-ink);
  font-size: var(--th-size-13);
}
.th-grid-bulkbar .count { font-weight: 600; font-variant-numeric: tabular-nums; }
.th-grid-bulkbar .spacer { flex: 1; }
.th-grid-bulkbar .bulk-act {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12px;
  padding: 3px 9px;
  border: 1px solid color-mix(in oklab, var(--grid-sel) 40%, transparent);
  border-radius: var(--th-radius-3);
  background: var(--th-paper-sunk);
  color: var(--grid-sel-ink);
  cursor: pointer;
}
.th-grid-bulkbar .bulk-act:hover { background: var(--th-paper); border-color: var(--grid-sel); }
.th-grid-bulkbar .bulk-act.is-danger { color: var(--th-risk); border-color: color-mix(in oklab, var(--th-risk) 40%, transparent); }
.th-grid-bulkbar .bulk-act.is-danger:hover { background: var(--th-risk-soft); border-color: var(--th-risk); }
.th-grid-bulkbar .clear {
  background: none; border: none; cursor: pointer;
  color: var(--grid-sel-ink); font-size: 11.5px; text-decoration: underline;
  text-underline-offset: 2px;
}

/* ==================================================================
   Pager — two readings that share a shell
   .is-paged   page-number controls (bounded, cheap-count cardinality)
   .is-cursor  range + prev/next (server cursor, large cardinality)
   ================================================================== */
.th-grid-pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 4px 4px;
  font-size: var(--grid-meta);
  color: var(--th-ink-3);
  font-family: var(--th-f-mono);
}
.th-grid-pager .controls { display: flex; align-items: center; gap: 4px; }
.th-grid-pagebtn {
  min-width: 26px; height: 26px;
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0 8px;
  border: 1px solid var(--th-line-2);
  border-radius: var(--th-radius-3);
  background: var(--th-paper-sunk);
  color: var(--th-ink-2);
  font: inherit; cursor: pointer;
}
.th-grid-pagebtn:hover:not(:disabled) { border-color: var(--th-ink-4); color: var(--th-ink); }
.th-grid-pagebtn.is-current { background: var(--grid-sel-soft); border-color: var(--grid-sel); color: var(--grid-sel-ink); font-weight: 600; }
.th-grid-pagebtn:disabled { opacity: 0.4; cursor: default; }
.th-grid-pager .ellip { color: var(--th-ink-4); padding: 0 2px; }

/* ==================================================================
   States — empty / no-match / loading / error
   ================================================================== */
.th-grid-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  text-align: center;
  padding: 48px 24px;
  color: var(--th-ink-3);
}
.th-grid-state .glyph {
  width: 40px; height: 40px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--th-paper-2);
  border: 1px solid var(--th-line);
  color: var(--th-ink-4);
  margin-bottom: 2px;
}
.th-grid-state .title { font-size: var(--th-size-15); font-weight: 600; color: var(--th-ink); }
.th-grid-state .body { font-size: var(--th-size-13); max-width: 380px; color: var(--th-ink-3); }
.th-grid-state code {
  font-family: var(--th-f-mono); font-size: 12px;
  background: var(--th-paper-2); border: 1px solid var(--th-line);
  padding: 0 5px; border-radius: var(--th-radius-2); color: var(--th-ink-2);
}
.th-grid-state.is-error .glyph { background: var(--th-risk-soft); border-color: color-mix(in oklab, var(--th-risk) 30%, transparent); color: var(--th-risk); }

/* Skeleton loading rows — preserve column rhythm, no spinner */
.th-grid-skel-cell { padding: var(--grid-cell-py) var(--grid-cell-px); }
.th-grid-skel {
  height: 11px; border-radius: var(--th-radius-2);
  background: linear-gradient(90deg, var(--th-paper-2) 0%, var(--th-paper-3) 40%, var(--th-paper-2) 80%);
  background-size: 200% 100%;
  animation: th-grid-shimmer 1.25s ease-in-out infinite;
}
@keyframes th-grid-shimmer {
  0% { background-position: 160% 0; }
  100% { background-position: -60% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .th-grid-skel { animation: none; }
}

/* ==================================================================
   Focus visibility — every interactive control gets one consistent
   ring. Sort headers + checkboxes define their own above; this covers
   the rest so keyboard focus is never lost against the browser default.
   ================================================================== */
.th-grid-link:focus-visible,
.th-grid-expand:focus-visible,
.th-grid-kebab:focus-visible,
.th-grid-action:focus-visible,
.th-grid-pagebtn:focus-visible,
.th-grid-bulkbar .bulk-act:focus-visible,
.th-grid-bulkbar .clear:focus-visible,
.th-grid-search:focus-within {
  outline: 2px solid var(--grid-sel);
  outline-offset: 2px;
  border-radius: var(--th-radius-2);
}
