/* The scroll table (components/scroll-table.js): a table wider than its column
   scrolls inside its own lane, never the page. The script sets can-left /
   can-right while more table sits off-screen that way: an edge fade on that
   side, and the "Scroll" chip under the table until the end is reached. */

.scroll-table { position: relative; }

/* contain: the lane takes its width from its container and never from the
   table inside it. Without it the unwrapping table sets the minimum width of
   every grid or flex ancestor, and the page scrolls sideways instead of the lane. */
.scroll-table-lane {
  overflow-x: auto;
  contain: inline-size;
  scrollbar-width: thin;
  scrollbar-color: var(--border) transparent;
}

.scroll-table-lane:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* site.css makes every table 100% wide and lets the body wrap anywhere, which
   would crush these columns to a letter each. In the lane a table is as wide
   as its content (the lane at least) and its cells never wrap, so it overflows
   and scrolls. Borders are separate: collapsed ones fall off a sticky cell as
   it slides. Columns get the air a full-width table has for free. */
.scroll-table table { width: max-content; min-width: 100%; border-collapse: separate; border-spacing: 0; }
.scroll-table th, .scroll-table td { white-space: nowrap; overflow-wrap: normal; padding-right: var(--md); }
.scroll-table th:last-child, .scroll-table td:last-child { padding-right: 0; }

/* The edge fades, in the page color so the table dissolves into it */
.scroll-table::before,
.scroll-table::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  z-index: 2;
  width: var(--xl);
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--fast);
}

.scroll-table::before { left: 0; background: linear-gradient(90deg, var(--bg), transparent); }
.scroll-table::after { right: 0; background: linear-gradient(270deg, var(--bg), transparent); }
.scroll-table.can-left::before, .scroll-table.can-right::after { opacity: 1; }

/* The hint: a chip under the table's right end, above the fade that runs the
   component's whole height. It keeps its line while hidden, so nothing below
   jumps when the end is reached. */
.scroll-hint {
  position: relative;
  z-index: 3;
  display: flex;
  width: fit-content;
  background: var(--bg);
  margin: var(--xs) 0 0 auto;
  visibility: hidden;
  opacity: 0;
  transition: opacity var(--fast);
}

.scroll-table.can-right .scroll-hint { visibility: visible; opacity: 1; }

/* The first column holds still, ruled off from what slides under it; the left
   fade would wash it out, so it stays off */
.scroll-table.sticky-first th:first-child,
.scroll-table.sticky-first td:first-child {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--bg);
  border-right: var(--hair);
}

.scroll-table.sticky-first th:nth-child(2), .scroll-table.sticky-first td:nth-child(2) { padding-left: var(--sm); }
.scroll-table.sticky-first::before { display: none; }

/* On a phone the fades are narrower (a full-width one would hide a whole
   cell), and a frozen column would cover too much of a small screen, so the
   whole table scrolls there (and its left fade comes back). left: auto lets go
   sideways only: a frozen header's first cell still holds to the top.
   .sticky-always keeps the column: a grid whose rows are nameless without it,
   which keeps it narrow. */
@media (max-width: 479px) {
  .scroll-table::before, .scroll-table::after { width: var(--md); }
  .scroll-table.sticky-first:not(.sticky-always) th:first-child,
  .scroll-table.sticky-first:not(.sticky-always) td:first-child { left: auto; border-right: 0; }
  .scroll-table.sticky-first:not(.sticky-always)::before { display: block; }
}

/* A long table holds its header row still: the lane scrolls both ways inside a
   height the screen can show (a header cannot stick to the page from inside a
   lane that scrolls sideways: the lane is its scroll container). A shorter
   table never reaches the cap and is unchanged. The corner cell rides above both. */
.scroll-table.sticky-head .scroll-table-lane { max-height: var(--scroll-table-max, calc(100dvh - var(--header-h) - var(--xl) - var(--safe-bottom))); overflow-y: auto; }
.scroll-table.sticky-head thead th { position: sticky; top: 0; z-index: 2; background: var(--bg); }
.scroll-table.sticky-head.sticky-first thead th:first-child { z-index: 3; }

/* On phones a bleeding lane runs to the screen's edges: the first and last
   cells carry the page inset, so the row hairlines cross the whole screen */
@media (max-width: 700px) {
  .scroll-table.bleed { margin-inline: calc(-1 * var(--page-inset)); }
  .scroll-table.bleed th:first-child, .scroll-table.bleed td:first-child { padding-left: var(--page-inset); }
  .scroll-table.bleed th:last-child, .scroll-table.bleed td:last-child { padding-right: var(--page-inset); }
  .scroll-table.bleed .scroll-hint { margin-right: var(--page-inset); }
}

/* wide: on a big screen a table wider than its column takes the room it needs
   before it scrolls: as wide as its content, never less than the column, never
   more than the screen less the page inset, centered on the column. The frame
   is a size container: the room around it is measured from the column (cqw),
   and the frame's own width never depends on the table, the containment the
   lane otherwise carries (what spills past the frame is paint, never the
   page's width). From 701px: below that a bleeding lane already runs edge to edge. */
.scroll-table-frame { container-type: inline-size; }

@media (min-width: 701px) {
  .scroll-table-room { display: flex; justify-content: center; margin-inline: calc(50cqw - min(50vw, var(--site-max) / 2) + var(--page-inset)); }
  .scroll-table-room > .scroll-table { flex: 0 1 auto; width: max-content; min-width: 100cqw; max-width: 100%; }
  .scroll-table-room .scroll-table-lane { contain: none; }
}
