@layer components {
  /* Base
  /* -------------------------------------------------------------------------- */

  /* Wrapper owns the horizontal scroll so a wide table never gets clipped by
     the `overflow-x: clip` safety net on the document. */
  .table-scroller {
    inline-size: 100%;
    overflow-x: auto;
    overscroll-behavior-x: contain;
  }

  /* `separate` rather than `collapse`: collapsed borders ignore border-radius,
     which square off the corners of the card the table sits in. */
  .table {
    border-collapse: separate;
    border-spacing: 0;
    inline-size: 100%;
    min-inline-size: var(--table-min-inline-size, 28rem);
  }

  /* Elements
  /* -------------------------------------------------------------------------- */

  .table__head {
    background-color: var(--color-surface-subtle);
  }

  .table__row {
    @media (any-hover: hover) {
      .table__body &:hover {
        background-color: var(--color-surface-subtle);
      }
    }
  }

  .table__header,
  .table__cell {
    border-block-end: var(--border);
    color: var(--color-ink);
    font-size: var(--text-small);
    padding: var(--table-cell-padding, var(--block-space));
    text-align: start;
  }

  /* Headers never wrap: a label broken mid-phrase is a layout failure. The
     table scrolls inside .table-scroller instead, and the column chosen to
     flex (see .table__cell--truncate) absorbs any squeeze. */
  .table__header {
    font-weight: 600;
    white-space: nowrap;
  }

  .table__body .table__row:last-child .table__cell {
    border-block-end: 0;
  }

  /* Variants
  /* -------------------------------------------------------------------------- */

  .table__cell--label {
    font-weight: 500;
    inline-size: var(--table-label-size, 8rem);
    white-space: nowrap;
  }

  /* Figures line up by place value so they compare down the column. Put it
     on the header too so the label sits over the numbers. */
  .table__header--numeric,
  .table__cell--numeric {
    font-variant-numeric: tabular-nums;
    text-align: end;
    white-space: nowrap;
  }

  /* The one flexible column: it takes whatever width the others leave and
     cuts its text off with an ellipsis, so every row stays one line tall.
     max-inline-size: 0 stops the text's own width from sizing the column.
     Give the cell a title attribute with the full text. */
  .table__cell--truncate {
    inline-size: 100%;
    max-inline-size: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* The column hugs its widest content, leaving free table width to other
     columns. Used so per-row content (e.g. the genre meter) sizes to the
     longest label rather than the stretched column. */
  .table__cell--fit {
    inline-size: 1%;
    white-space: nowrap;
  }

  /* A row that is one link: the .table__link's ::after stretches over the row
     so a click anywhere follows it. Other links and buttons in the row sit
     above it to stay clickable. */
  .table__row--linked {
    position: relative;

    :is(a, button):not(.table__link) {
      position: relative;
      z-index: var(--z-above-stretched-link);
    }
  }

  .table__link {
    color: var(--color-ink);
    font-weight: 500;

    &::after {
      content: "";
      inset: 0;
      position: absolute;
      z-index: var(--z-stretched-link);
    }

    @media (any-hover: hover) {
      .table__row--linked:hover & {
        color: var(--color-link);
      }
    }
  }

  /* A row whose cells hold form controls. Until the row is in edit mode the
     controls lose their chrome and read as plain cell text; the owning
     controller makes the cells inert so they can't be focused or changed. */
  .table__row--editable {
    .input {
      --input-font-size: var(--text-small);
    }

    &:not(.table__row--editing) {
      .input {
        --input-background: transparent;
        --input-border-color: transparent;
        --input-padding: 0.5em 0;
      }

      .select__chevron,
      ::-webkit-calendar-picker-indicator {
        display: none;
      }
    }
  }

  /* Buttons pinned to the end of the row. The cell takes no more width than
     its contents, and text-align: end works because buttons are inline-flex. */
  .table__cell--actions,
  .table__header--actions {
    inline-size: 1%;
    padding-block: var(--block-space-half);
    text-align: end;
    white-space: nowrap;

    /* Reveal on hover or keyboard focus, pointer devices only. On touch the
       buttons stay visible because there is no hover to reveal them. */
    @media (any-hover: hover) {
      .btn {
        opacity: 0;
        transition: opacity var(--duration-fast) var(--ease-out-expo);
      }

      .table__row:hover & .btn,
      .table__row:focus-within & .btn {
        opacity: 1;
      }
    }
  }
}
