/*
 * THE CROSS-TAB. One dimension against another, every number a door.
 *
 * The columns all resolve to the same width because a heading, a cell and a
 * column total share ONE sizing law — a flex share of the leftover over a floor
 * — and the heading adds back exactly what a cell's border and inset push its
 * figure in by.
 *
 * The heat ramp is ONE hue: the sheet mixes it, and the CELL supplies only its
 * intensity, so a caller picking `heatColor="emerald"` picks a palette token
 * rather than a resolved colour and a theme can still repaint the family.
 */
@layer theme, base, lotics, components, utilities;
@layer lotics.tokens, lotics.reset, lotics.components;

@layer lotics.components {
  .lotics-matrix {
    /* Chỗ thở hai bên con số bên trong một ô: ô có NỀN, nên con số căn phải cần
       một khoảng với mép nền; dán sát thì nó đọc như bị cắt. */
    --lotics-matrix-cell-pad: var(--lotics-space-6);
    --lotics-matrix-col-gap: var(--lotics-space-2);
    /* The cell's edge, named because the column HEADING has to add it back:
       the heading's right padding is what a cell's border plus its inset push
       the figure in by, and the two must agree to the pixel. */
    --lotics-matrix-cell-edge: 2px;
    /* The two FLOORS, declared where the cells that carry them are styled, and
       read back by the frame's own minimum: one number each, so a grid can never
       believe it fits a frame its cells have already been squeezed out of. */
    --lotics-matrix-cell-min: calc(52px + var(--lotics-matrix-cell-pad) * 2);
    --lotics-matrix-total-min: 64px;
    display: flex;
    flex-direction: row;
    align-items: stretch;
    min-width: 0;
    /* Past the frame's own floor the matrix SCROLLS rather than shrinking: a
       thirty-column pivot squeezed to fit states nothing at all. */
    overflow-x: auto;
  }

  .lotics-matrix__frame {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    /* Grows into a frame WIDER than the floor: a scroller lays its content out in
       a row, so a box that kept its content width would leave a third of the card
       empty while its cells wrapped their figures onto two lines. */
    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: the corner, a row's name, the totals band's label. All
     three HOLD their width, so the three bands end on one edge by construction.
     The squeeze comes out of the data columns, which carry a floor, and past
     that the matrix overflows.

     One class, two shapes: the HEADER's corner and a GRID row's subject are both
     boxes around what the caller passed, and that is what this `display`
     governs; the totals band's label is the run of text itself and takes its
     `display` from `.lotics-text[data-clamped]`, two classes, which wins here. */
  .lotics-matrix__label {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    flex-shrink: 0;
    min-width: 0;
    width: var(--lotics-matrix-label-width);
    /* The air between a row label and the first cell. */
    padding-right: var(--lotics-space-8);
  }

  /* A row is a SUBJECT: its mark and its name sit on one line, inside the same
     column, so a marked matrix lines up with an unmarked one. */
  .lotics-matrix__label[data-subject] {
    flex-direction: row;
    align-items: center;
    gap: var(--lotics-lead-gap);
  }

  /* The name takes what is left after the mark; `min-width: 0` so it truncates
     rather than pushing the mark out past the column's edge. */
  .lotics-matrix__label-text {
    flex: 1;
    min-width: 0;
  }

  /* A DATA column — a heading or a column total. A BOX rather than the run of
     text inside it, because the floor belongs to the column: a clamped `Text`
     states `min-width: 0`. Same floor as a cell, so the two resolve to one
     width. */
  .lotics-matrix__column {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    flex: 1;
    min-width: var(--lotics-matrix-cell-min);
    /* Khớp với tổng phần ô đẩy con số vào: 2px viền cộng cái đệm ngang. Lệch
       một pixel ở đây là tiêu đề cột và dãy số dưới nó kết thúc ở hai đường x
       khác nhau. */
    padding-right: calc(var(--lotics-matrix-cell-edge) + var(--lotics-matrix-cell-pad));
  }

  .lotics-matrix__cell {
    /* STRETCH, not centre: a run of text centred by its parent SHRINK-WRAPS, so
       the right-aligned figure inside has nothing to align against. */
    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;
    cursor: auto;
    transition: border-color var(--lotics-duration-fast) var(--lotics-ease-standard);
  }

  /* Nothing at this intersection: neutral, so the ramp reads as a ramp of
     SOMETHING rather than bottoming out in a pale hue. */
  .lotics-matrix__cell[data-zero] {
    background: var(--lotics-wash-selected);
  }

  /* A number-only grid has no wash at all — the ground is the page's. */
  .lotics-matrix__cell[data-display="number"] {
    background: var(--card);
  }

  .lotics-matrix__cell[data-pressable]:hover {
    border-color: var(--lotics-border-hover);
  }

  .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;
  }

  /*
   * THE TRAILING TOTAL, SIZED LIKE A DATA COLUMN rather than to a fixed number:
   * a total is by construction the LONGEST figure in its row, so a clamp hits it
   * first. The floor is the old fixed width, so a matrix with many columns in a
   * narrow frame never loses ground.
   */
  .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);
  }

  .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);
  }
}
