/* THE CROSS-TAB, every number a door. Heading, cell and total share one sizing law (a flex share over a
   floor), and the heading adds back what a cell's border and inset push its figure in by, so columns
   match. One heat hue: the sheet mixes it and a cell supplies only intensity, so `heatColor` picks a
   themeable token. */
@layer theme, base, lotics, components, utilities;
@layer lotics.tokens, lotics.reset, lotics.components;

@layer lotics.components {
  .lotics-matrix {
    /* Air either side of a figure in a filled cell, or a right-aligned number reads as cut against the
       ground. */
    --lotics-matrix-cell-pad: var(--lotics-space-6);
    --lotics-matrix-col-gap: var(--lotics-space-2);
    /* Named because the heading adds it back to match a cell's figure edge to the pixel. */
    --lotics-matrix-cell-edge: 2px;
    /* Both floors are declared here and read back by the frame's minimum, so a grid never believes it fits
       a frame its cells were squeezed out of. */
    --lotics-matrix-cell-min: max(
      calc(52px + var(--lotics-matrix-cell-pad) * 2),
      calc(var(--lotics-matrix-head-ink, 0px) + var(--lotics-matrix-cell-pad) * 2 + var(--lotics-matrix-cell-edge) * 2)
    );
    --lotics-matrix-total-min: 64px;
    display: flex;
    flex-direction: row;
    align-items: stretch;
    min-width: 0;
    /* Past its floor the matrix scrolls; a squeezed thirty-column pivot says nothing. */
    overflow-x: auto;
  }

  .lotics-matrix__frame {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    /* Grows into a wider frame, or a row-laid scroller leaves a third of the card empty while figures
       wrap. */
    flex: 1 0 auto;
    min-width: calc(
      var(--lotics-matrix-label-width) + var(--lotics-matrix-cols) *
        (var(--lotics-matrix-cell-min) + var(--lotics-matrix-col-gap)) +
        var(--lotics-matrix-total-slots) *
        (var(--lotics-matrix-total-min) + var(--lotics-matrix-col-gap))
    );
    gap: var(--lotics-matrix-col-gap);
  }

  .lotics-matrix__header,
  .lotics-matrix__row,
  .lotics-matrix__totals {
    display: flex;
    flex-direction: row;
    align-items: center;
    min-width: 0;
    gap: var(--lotics-matrix-col-gap);
  }

  .lotics-matrix__header {
    padding-bottom: var(--lotics-space-2);
  }

  .lotics-matrix__grid {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    min-width: 0;
    gap: var(--lotics-matrix-col-gap);
  }

  /* The leading column (corner, row name, totals label) holds its width, so the bands end on one edge and
     data columns take the squeeze. The totals label is text, taking `display` from
     `.lotics-text[data-clamped]` (two classes). */
  .lotics-matrix__label {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    flex-shrink: 0;
    min-width: 0;
    width: var(--lotics-matrix-label-width);
    padding-right: var(--lotics-space-8);
  }

  /* Mark and name on one line in one column, so marked and unmarked matrices align. */
  .lotics-matrix__label[data-subject] {
    flex-direction: row;
    align-items: center;
    gap: var(--lotics-lead-gap);
  }

  /* `min-width: 0` so the name truncates rather than pushing the mark out. */
  .lotics-matrix__label-text {
    flex: 1;
    min-width: 0;
  }

  /* A box, not the text, since the floor is the column's (a clamped `Text` has `min-width: 0`); a cell's
     floor, so both resolve alike. */
  .lotics-matrix__column {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    flex: 1;
    min-width: var(--lotics-matrix-cell-min);
    /* Matches what a cell pushes its figure in by — 2px border plus inline pad — or heading and figures
       end on different x. */
    padding-right: calc(var(--lotics-matrix-cell-edge) + var(--lotics-matrix-cell-pad));
  }

  /* A head whose column is someone: the mark before the name, both at the column's right edge. */
  .lotics-matrix__column[data-led] {
    flex-direction: row;
    align-items: center;
    justify-content: flex-end;
    gap: var(--lotics-space-6);
  }

  .lotics-matrix__cell {
    /* Stretch: centred text shrink-wraps, leaving the right-aligned figure nothing to align to. */
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: center;
    flex: 1;
    min-width: var(--lotics-matrix-cell-min);
    height: 36px;
    margin: 0;
    padding-inline: var(--lotics-matrix-cell-pad);
    padding-block: 0;
    border: var(--lotics-matrix-cell-edge) solid transparent;
    border-radius: calc(var(--lotics-radius-control) - var(--lotics-space-6));
    background: color-mix(in srgb, var(--lotics-matrix-heat) var(--lotics-matrix-alpha), transparent);
    font: inherit;
    color: inherit;
    text-align: start;
    appearance: none;
    transition: border-color var(--lotics-duration-fast) var(--lotics-ease-standard);
  }

  /* Nothing is no fill: the ramp starts at the surface, so an empty cell never reads heavier than a small one. */
  .lotics-matrix__cell[data-zero] {
    background: transparent;
  }

  /* A number-only grid has no wash. */
  .lotics-matrix__cell[data-display="number"] {
    background: var(--card);
  }

  /* A tile marks the condition it holds on its edge, beside its press's accent ink. */
  .lotics-matrix__cell[data-selected],
  .lotics-matrix__cell[data-selected]:hover {
    border-color: var(--foreground);
  }

  .lotics-matrix__cell:focus-visible {
    outline: var(--lotics-ring-width) solid var(--ring);
    outline-offset: 0;
  }

  /* Sized like a data column: a total is its row's longest figure, so a clamp hits it first. Floored at
     the old fixed width. */
  .lotics-matrix__total-column {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    flex: 1;
    min-width: var(--lotics-matrix-total-min);
    padding-left: var(--lotics-space-4);
  }

  .lotics-matrix__totals {
    margin-top: var(--lotics-space-2);
    padding-top: var(--lotics-space-8);
    border-top: 1px solid var(--border);
  }

  /* WIDER THAN ITS BOX: the names and the totals hold their place on the card's opaque ground, each behind a
     hairline edge, and the cells scroll UNDER them — never through a fade, where a half-hidden cell reads as a
     ghost of a figure. */
  /* A pinned column takes its row's whole height, so no strip of a cell shows above or below it. */
  .lotics-matrix[data-overflow] .lotics-matrix__label {
    position: sticky;
    left: 0;
    z-index: var(--lotics-z-sticky-column);
    align-self: stretch;
    justify-content: center;
    background: var(--card);
    box-shadow: inset -1px 0 0 var(--border);
  }

  .lotics-matrix[data-overflow] .lotics-matrix__total-column {
    position: sticky;
    right: 0;
    z-index: var(--lotics-z-sticky-column);
    flex: 0 0 auto;
    align-self: stretch;
    justify-content: center;
    background: var(--card);
    box-shadow: inset 1px 0 0 var(--border);
  }

  .lotics-matrix__legend {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: flex-end;
    min-width: 0;
    gap: var(--lotics-space-4);
    padding-top: var(--lotics-space-8);
  }

  .lotics-matrix__swatch {
    display: block;
    flex-shrink: 0;
    width: 14px;
    height: 10px;
    border-radius: calc(var(--lotics-radius-control) - var(--lotics-space-8));
    background: color-mix(in srgb, var(--lotics-matrix-heat) var(--lotics-matrix-alpha), transparent);
  }

  /* In a register's readings band, whose line is one low height: a row is a line of text high, each name on
     one line. */
  @container lotics-reading-band (width >= 0px) {
    .lotics-matrix__cell {
      height: 20px;
    }

    .lotics-matrix__header {
      padding-bottom: 0;
    }

    .lotics-matrix__row .lotics-matrix__label-text[data-clamped] {
      -webkit-line-clamp: 1;
      line-clamp: 1;
    }
  }
}
