/* ==========================================================================
   Table — Data display component for structured tabular data.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Table Root — Outer container for table + optional footer.
   Primary variant: gray background with the table body as a white card inside.
   -------------------------------------------------------------------------- */
.table-root {
  @apply relative grid w-full overflow-clip;
  grid-template-columns: minmax(0, 1fr);
}

/* --------------------------------------------------------------------------
   Scroll Container — Allows the table to scroll horizontally while the
   wrapper and footer remain at full width. The parent grid with
   minmax(0, 1fr) creates a hard width boundary that table layout
   cannot push beyond.
   -------------------------------------------------------------------------- */
.table__scroll-container {
  @apply scrollbar overflow-x-auto;
  scrollbar-gutter: auto;
}

.table-root--primary {
  @apply bg-surface-secondary px-1 pb-1;
  border-radius: min(32px, calc(var(--radius) * 2.5));
}

.table-root--secondary {
  /* No background, padding, or rounding on the root */
}

/* Secondary: header is a standalone rounded card.
   Background is on cells (not <thead>) because Firefox does not support */
.table-root--secondary .table__header {
  @apply border-b-0 bg-transparent;
}

.table-root--secondary .table__column {
  @apply bg-surface-secondary;
}

/* Round only the truly first/last column header.
   Non-virtualized: column is a <th> child of <tr>.
   Virtualized: column is wrapped in a `VirtualizerItem` (role="presentation") so
   `:first-child` / `:last-child` on `.table__column` would match every column
   (each is the only child of its wrapper). Walk up to the row instead. */
.table-root--secondary
  :is(
    th.table__column:first-child,
    [role="row"] > [role="presentation"]:first-of-type > .table__column
  ) {
  border-start-start-radius: min(32px, var(--radius-2xl));
  border-end-start-radius: min(32px, var(--radius-2xl));
}

.table-root--secondary
  :is(
    th.table__column:last-child,
    [role="row"] > [role="presentation"]:last-of-type > .table__column
  ) {
  border-start-end-radius: min(32px, var(--radius-2xl));
  border-end-end-radius: min(32px, var(--radius-2xl));
}

/* Secondary: body has no shadow or rounded corners */
.table-root--secondary .table__body {
  @apply shadow-none;

  /* Non-virtualized */
  & tr:first-child td:first-child,
  & tr:first-child td:last-child,
  & tr:last-child td:first-child,
  & tr:last-child td:last-child {
    @apply rounded-none;
  }

  /* Virtualized: undo the rounding applied by .table__body:not(tbody) */
  &:not(tbody) {
    @apply overflow-visible rounded-none;
  }
}

/* Secondary: rows are transparent and keep bottom border on every row */
.table-root--secondary .table__row {
  .table__cell {
    @apply border-b border-separator-tertiary/50 bg-transparent;
  }

  @media (hover: hover) {
    &:hover .table__cell,
    &[data-hovered="true"] .table__cell {
      @apply bg-default/50;
    }
  }
}

/* --------------------------------------------------------------------------
   Table Content (<table> element) — the white card inside the root
   -------------------------------------------------------------------------- */
.table__content {
  @apply w-full border-separate border-spacing-0 text-sm;
}

/* Primary variant: table gets the white surface card look */
.table-root--primary .table__content {
  @apply overflow-clip;
}

/* --------------------------------------------------------------------------
   Table Header (<thead>)
   -------------------------------------------------------------------------- */
.table__header {
  @apply border-b border-separator/50 bg-surface-secondary;
}

/* --------------------------------------------------------------------------
   Table Column (<th>)
   -------------------------------------------------------------------------- */
.table__column {
  @apply relative px-4 py-2.5 text-start text-xs font-medium text-muted;

  /* Separator between columns — a short vertical line on the right edge */
  &::after {
    content: "";
    @apply pointer-events-none absolute end-0 top-1/2 h-4 w-px -translate-y-1/2 rounded-sm bg-separator;
  }

  &:last-child:not(:only-child)::after {
    content: none;
  }

  /* Sortable columns */
  &[data-allows-sorting="true"] {
    cursor: var(--cursor-interactive);
  }

  @media (hover: hover) {
    &[data-allows-sorting="true"]:hover,
    &[data-allows-sorting="true"][data-hovered="true"] {
      @apply text-foreground;
    }
  }

  /* Focus visible — inset shadow for consistent table focus styling */
  &:focus-visible,
  &[data-focus-visible="true"] {
    @apply rounded-lg outline-none;
    box-shadow: inset 0 0 0 2px var(--focus);
  }
}

/* Virtualized: each column is wrapped in a `VirtualizerItem` (role="presentation"),
   so `.table__column:last-child:not(:only-child)::after` above never matches.
   Hide the trailing separator on the rightmost wrapper instead. */
[role="row"] > [role="presentation"]:last-of-type:not(:only-of-type) > .table__column::after {
  content: none;
}

/* --------------------------------------------------------------------------
   Sortable Column Header — wraps the column label and an optional indicator
   icon. Rendered inside a sortable `Table.Column`'s render prop callback.
   -------------------------------------------------------------------------- */
.table__sortable-column-header {
  @apply flex items-center justify-between;
}

/* --------------------------------------------------------------------------
   Sortable Column Indicator — chevron that flips based on `data-direction`.
   Defaults to pointing up (ascending) and rotates 180° for descending.
   -------------------------------------------------------------------------- */
.table__sortable-column-indicator {
  @apply inline-grid size-3 transform place-content-center transition-transform duration-100 ease-out;

  &[data-direction="descending"] {
    @apply rotate-180;
  }
}

/* --------------------------------------------------------------------------
   Table Body (<tbody>)
   -------------------------------------------------------------------------- */
.table__body {
  /* Non-virtualized: round corners via first/last cells
     (border-radius on <tbody> itself has no effect).
     Logical properties so corners follow `dir` in RTL. */
  & tr:first-child td:first-child {
    border-start-start-radius: min(32px, var(--radius-2xl));
  }
  & tr:first-child td:last-child {
    border-start-end-radius: min(32px, var(--radius-2xl));
  }
  & tr:last-child td:first-child {
    border-end-start-radius: min(32px, var(--radius-2xl));
  }
  & tr:last-child td:last-child {
    border-end-end-radius: min(32px, var(--radius-2xl));
  }

  /* Virtualized: elements are divs, not tr/td. VirtualizerItem wrappers
     break :first-child/:last-child on rows and cells, so round the body
     itself and clip overflow instead. */
  &:not(tbody) {
    @apply relative h-full overflow-clip;
    border-radius: min(32px, var(--radius-2xl));
  }
}

/* --------------------------------------------------------------------------
   Table Row (<tr>)
   -------------------------------------------------------------------------- */
.table__row {
  @apply relative h-full;

  /* Bottom separator */
  @apply border-b border-separator/50;

  /* Last row in body has no bottom border */
  &:last-child {
    @apply border-b-0;
  }

  /* Hover state — applied to cells so Firefox clips bg to border-radius */
  @media (hover: hover) {
    &:hover .table__cell,
    &[data-hovered="true"] .table__cell {
      @apply bg-surface/40;
    }
  }

  /* Selected state */
  &[data-selected="true"] .table__cell {
    @apply bg-surface/10;
  }

  /* Disabled state */
  &[aria-disabled="true"],
  &[data-disabled="true"] {
    @apply status-disabled;
  }

  /* Row focus ring: see “Table row focus ring” block below (after `.table__cell`). */
  &:focus-visible,
  &[data-focus-visible="true"] {
    @apply outline-none;
  }

  /* Dragging state */
  &[data-dragging="true"] {
    @apply opacity-50;
  }

  /* Drop target state */
  &[data-drop-target="true"] .table__cell {
    @apply bg-accent-soft;
  }
}

/* --------------------------------------------------------------------------
   Table Cell (<td>)
   -------------------------------------------------------------------------- */
.table__cell {
  @apply h-full bg-surface px-4 py-3 align-middle text-sm text-foreground;

  @apply border-b border-separator-tertiary/50;

  /* Focus visible — inset shadow so focus stays within the cell boundaries */
  &:focus-visible,
  &[data-focus-visible="true"] {
    @apply rounded-lg outline-none;
    box-shadow: inset 0 0 0 2px var(--focus);
  }
}

/* --------------------------------------------------------------------------
   Table row focus ring — must follow `.table__cell` (cascade). One continuous
   inset ring split across cells; `:is(.table__cell, .table__column)` + direct vs
   `> *:…` covers virtualized wrappers. `:is(:focus-visible, [data-focus-visible])`
   matches row keyboard focus from RAC.
   -------------------------------------------------------------------------- */
.table__row:is(:focus-visible, [data-focus-visible="true"]) :is(.table__cell, .table__column) {
  @apply shadow-none;
}

.table__row:is(:focus-visible, [data-focus-visible="true"])
  > :is(.table__cell, .table__column):only-child,
.table__row:is(:focus-visible, [data-focus-visible="true"])
  > *:only-child
  :is(.table__cell, .table__column) {
  @apply rounded-lg shadow-[inset_0_0_0_2px_var(--focus)] outline-none;
}

.table__row:is(:focus-visible, [data-focus-visible="true"])
  > :is(.table__cell, .table__column):first-child:not(:only-child),
.table__row:is(:focus-visible, [data-focus-visible="true"])
  > *:first-child:not(:only-child)
  :is(.table__cell, .table__column) {
  @apply rounded-s-lg shadow-[inset_2px_0_0_0_var(--focus),inset_0_2px_0_0_var(--focus),inset_0_-2px_0_0_var(--focus)] outline-none;
}

.table__row:is(:focus-visible, [data-focus-visible="true"])
  > :is(.table__cell, .table__column):last-child:not(:only-child),
.table__row:is(:focus-visible, [data-focus-visible="true"])
  > *:last-child:not(:only-child)
  :is(.table__cell, .table__column) {
  @apply rounded-e-lg shadow-[inset_-2px_0_0_0_var(--focus),inset_0_2px_0_0_var(--focus),inset_0_-2px_0_0_var(--focus)] outline-none;
}

.table__row:is(:focus-visible, [data-focus-visible="true"])
  > :is(.table__cell, .table__column):not(:first-child):not(:last-child):not(:only-child),
.table__row:is(:focus-visible, [data-focus-visible="true"])
  > *:not(:first-child):not(:last-child):not(:only-child)
  :is(.table__cell, .table__column) {
  @apply shadow-[inset_0_2px_0_0_var(--focus),inset_0_-2px_0_0_var(--focus)] outline-none;
}

/* --------------------------------------------------------------------------
   Tree / expandable rows — indent the tree column by depth (any level).
   React Aria sets `--table-row-level` (1-based) on each body row and
   `data-level` on cells; tree column cells expose `[data-tree-column]`.
   The row custom property inherits onto cells (1rem per level).
   -------------------------------------------------------------------------- */
.table__cell[data-tree-column] {
  padding-inline-start: calc(1rem * var(--table-row-level, 1));
}

/* --------------------------------------------------------------------------
   Table Footer (div outside <table>, sits on gray bg)
   -------------------------------------------------------------------------- */
.table__footer {
  @apply flex items-center px-4 py-2.5;
}

/* --------------------------------------------------------------------------
   Resizable Container — wraps table to enable column resizing via React Aria.
   -------------------------------------------------------------------------- */
.table__resizable-container {
  @apply relative scrollbar overflow-auto;
  scrollbar-gutter: auto;
}

/* --------------------------------------------------------------------------
   Column Resizer — drag handle between resizable columns.
   Replaces the ::after separator when present.
   -------------------------------------------------------------------------- */
.table__column-resizer {
  /* Match the ::after separator: absolute, right edge, short vertical line */
  @apply absolute end-0 top-1/2 h-4 w-px -translate-y-1/2 rounded-sm bg-separator;
  /* Make it interactive — wider hit area with transparent padding */
  @apply box-content translate-x-1/2 cursor-col-resize touch-none px-2;
  /* Reset appearance */
  @apply border-none bg-clip-content outline-none;

  &[data-hovered="true"],
  &:hover {
    @apply h-full w-0.5 bg-accent;
  }

  &[data-resizing="true"] {
    @apply h-full w-0.5 bg-accent;
  }

  &[data-focus-visible="true"],
  &:focus-visible {
    @apply h-full w-0.5 bg-focus;
  }
}

/* Hide the ::after separator when a resizer is present in the column */
.table__column:has(.table__column-resizer)::after {
  content: none;
}

/* --------------------------------------------------------------------------
   Load More Item — sentinel row for infinite scrolling.
   Non-virtualized: <tr> with <td colSpan=N> inside.
   Virtualized: <div> with <div role="rowheader"> inside.
   -------------------------------------------------------------------------- */
.table__load-more {
  & td,
  & [role="rowheader"] {
    @apply py-3 text-center;
    & > * {
      @apply mx-auto;
    }
  }
}

/* --------------------------------------------------------------------------
   Load More Content — styled container for the loading indicator inside
   the load-more sentinel row.
   -------------------------------------------------------------------------- */
.table__load-more-content {
  @apply flex items-center justify-center gap-2 py-2;
}
