/*
 * A CROSS-TAB OF STATES. ONE scroll container, and both edges stick to it — the
 * axis at the top, the row's name at the left.
 *
 * The glyph is ONE box drawn four ways off `data-shape`, and the state's colour
 * arrives as its palette TOKEN, so a cell and its legend entry cannot disagree.
 *
 * TWO AXES key the rules below. `data-axis` says whether the positions are
 * named: without an axis the cells wrap as a dense field and the band gives way
 * to a chip. `data-mark` says what a cell holds: a glyph, or one hue at the
 * value's intensity.
 */
@layer theme, base, lotics, components, utilities;
@layer lotics.tokens, lotics.reset, lotics.components;

@layer lotics.components {
  .lotics-state-matrix {
    /* The hue every intensity cell is a density of. */
    --lotics-state-matrix-hue: var(--lotics-tone-blue-solid);
    /* The pinned figure's column, read in more than one place. */
    --lotics-state-matrix-total-width: 64px;
    /* A NAME, NOT TWO CHARACTERS: 96 is a given name and the start of a family
       name at the `sm` rung. */
    --lotics-state-matrix-name-width: 96px;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    min-width: 0;
    gap: var(--lotics-space-12);
  }

  /* The ONE scroll port: a month of columns beside a 220px label block cannot
     fit a pane. */
  .lotics-state-matrix__body {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    min-width: 0;
    overflow: auto;
  }

  .lotics-state-matrix__head,
  .lotics-state-matrix__row {
    display: flex;
    flex-direction: row;
    align-items: stretch;
    flex-shrink: 0;
    min-width: 0;
    gap: var(--lotics-register-cell-gap);
  }

  .lotics-state-matrix__row {
    min-height: var(--lotics-register-row);
  }

  /* STICKY LEFT, and over the head's own rung inside it. It paints the
     register's ground, or the cells it is pinned over draw through it. */
  .lotics-state-matrix__lead {
    display: flex;
    flex-direction: row;
    align-items: center;
    /* END-justified for the HEAD's sake — its only child is the total's heading,
       which has to land over the figures. */
    justify-content: flex-end;
    flex: none;
    width: var(--lotics-state-matrix-label-width);
    /* HALF THE MATRIX AT MOST: `rowLabelWidth` is a desk measurement, and pinned
       to the left edge it is the one thing that cannot give way. A proportion of
       the component's own box, so there is no width to query. */
    max-width: 50%;
    gap: var(--lotics-lead-gap);
    padding-right: var(--lotics-space-8);
    position: sticky;
    left: 0;
    z-index: var(--lotics-z-sticky-column);
    background-color: var(--lotics-register-ground);
  }

  /* The pinned figure is a SECOND column inside the block, added to the caller's
     label width rather than taken out of it, and the cap is raised by the same
     column so the figure is not taken out of the NAME's half either. */
  .lotics-state-matrix__lead[data-total] {
    width: calc(
      var(--lotics-state-matrix-label-width) + var(--lotics-state-matrix-total-width)
    );
    max-width: calc(50% + var(--lotics-state-matrix-total-width));
  }

  .lotics-state-matrix__label {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    /* The name ASKS for its own width and gives way only when the cap above
       leaves nothing else to give — a min instead would spill the block out of
       its own left edge. */
    flex: 1 1 var(--lotics-state-matrix-name-width);
    min-width: 0;
  }

  .lotics-state-matrix__total {
    flex-shrink: 0;
    width: var(--lotics-state-matrix-total-width);
  }

  /* THE COLUMNS SHARE THE SLACK. The register band is the FLOOR — a cell's whole
     box is the press target — and grow takes whatever the pane has left. */
  .lotics-state-matrix__axis-cell,
  .lotics-state-matrix__cell {
    flex: 1 0 var(--lotics-register-row);
    min-width: var(--lotics-register-row);
    border-radius: calc(var(--lotics-radius-control) - var(--lotics-space-4));
  }

  .lotics-state-matrix__axis-cell {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
  }

  .lotics-state-matrix__cell {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    font: inherit;
    color: inherit;
    appearance: none;
    cursor: auto;
  }

  /* The column the reader is standing in, tinted down its whole height so the
     eye can run a finger along it. */
  .lotics-state-matrix__axis-cell[data-current],
  .lotics-state-matrix__cell[data-current] {
    background: var(--lotics-wash-selected);
  }

  .lotics-state-matrix__cell[data-pressable] {
    cursor: pointer;
  }

  .lotics-state-matrix__cell[data-pressable]:hover {
    background: var(--lotics-wash-press);
  }

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

  /* ── the glyph ────────────────────────────────────────────────────────── */

  /* HALF THE CELL, which is 20 — the lone-affordance rung of §9, reached as a
     fraction of the box the component owns rather than as a number. */
  .lotics-state-matrix__mark {
    display: block;
    flex-shrink: 0;
    width: calc(var(--lotics-register-row) / 2);
    height: calc(var(--lotics-register-row) / 2);
    border-radius: calc(var(--lotics-radius-control) - var(--lotics-space-6));
    background: var(--lotics-state-matrix-mark);
  }

  /* NOTHING WAS DUE, which is not a state worth a glyph — the box stays, so the
     column keeps its rhythm and the blank reads as an answer. */
  .lotics-state-matrix__mark[data-shape="none"] {
    background: transparent;
  }

  .lotics-state-matrix__mark[data-shape="hollow"] {
    background: var(--card);
    border: 1.5px solid var(--lotics-state-matrix-mark);
  }

  .lotics-state-matrix__mark[data-shape="dot"] {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    background: transparent;
  }

  .lotics-state-matrix__mark[data-shape="dot"]::before {
    content: "";
    width: calc(var(--lotics-register-row) / 4);
    height: calc(var(--lotics-register-row) / 4);
    border-radius: var(--lotics-radius-full);
    background: var(--lotics-state-matrix-mark);
  }

  /* ── the legend ───────────────────────────────────────────────────────── */

  .lotics-state-matrix__legend {
    display: flex;
    flex-direction: row;
    align-items: center;
    flex-wrap: wrap;
    column-gap: var(--lotics-space-12);
    row-gap: var(--lotics-space-4);
  }

  .lotics-state-matrix__legend-item {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--lotics-space-6);
    min-height: var(--lotics-avatar-sm);
  }

  /* A LEGEND THAT FILTERS IS A CONTROL, and the kit's controls are one height —
     a `Chip`, a `FilterChip`, a register's own cell. */
  .lotics-state-matrix__legend-item[data-pressable] {
    min-height: var(--lotics-register-row);
  }

  /* A cell outside the drilled slice goes quiet and stops being a target — one
     treatment everywhere: opacity down, never a second colour. */
  .lotics-state-matrix__cell[data-dimmed] {
    opacity: 0.25;
  }

  /* ── THE WALLBOARD — `axis="none"` ────────────────────────────────────────
     Hundreds of units as coloured chips, read by scanning for the one that is
     red, so a cell carries no text. The cells WRAP as one field rather than
     sharing an axis's slack, and a row's name sits beside them at its own
     width. */
  .lotics-state-matrix[data-axis="none"] .lotics-state-matrix__row {
    flex-wrap: wrap;
    align-items: flex-start;
    min-height: 0;
    /* Three quarters of the smallest rung — tight enough that a hundred cells
       read as one field rather than as a hundred objects. */
    gap: var(--lotics-space-2);
  }

  .lotics-state-matrix[data-axis="none"] .lotics-state-matrix__lead {
    position: static;
    width: auto;
    max-width: none;
    justify-content: flex-start;
  }

  /* A NAMED WALLBOARD IS A COMPARISON of LENGTHS, which a ragged left edge
     destroys, so its names take one column. */
  .lotics-state-matrix[data-axis="none"][data-labelled] .lotics-state-matrix__lead {
    width: var(--lotics-state-matrix-label-width);
    flex: none;
  }

  .lotics-state-matrix[data-axis="none"] .lotics-state-matrix__cell {
    /* A chip that is PRESSED, and 24 is the floor WCAG 2.5.8 asks. The corner is
       the control corner scaled down so it moves with the ladder; the 2px edge is
       always there and usually transparent, since one appearing on hover would
       move every cell after it. */
    flex: none;
    width: var(--lotics-avatar-sm);
    min-width: 0;
    height: var(--lotics-avatar-sm);
    border: 2px solid transparent;
    border-radius: calc(var(--lotics-radius-control) - var(--lotics-space-6));
  }

  /* The chip IS the glyph here, so the mark fills the cell. THE CELL'S OWN mark,
     named as such: the legend draws the same glyph outside any cell, and a rule
     that fills its parent may only name a parent with a size. */
  .lotics-state-matrix[data-axis="none"] .lotics-state-matrix__cell > .lotics-state-matrix__mark {
    width: 100%;
    height: 100%;
  }

  /* A light edge INSIDE the colour: a neutral one would read as a different
     state on a saturated cell. */
  .lotics-state-matrix[data-axis="none"] .lotics-state-matrix__cell[data-pressable]:hover {
    border-color: color-mix(in srgb, var(--lotics-white) 75%, transparent);
    background: transparent;
  }

  /* The open unit. It outranks hover, because "this is the one in the drawer"
     survives the pointer moving on. */
  .lotics-state-matrix[data-axis="none"] .lotics-state-matrix__cell[data-selected],
  .lotics-state-matrix[data-axis="none"] .lotics-state-matrix__cell[data-selected]:hover {
    border-color: var(--foreground);
  }

  /* ── DENSITY — `mark="intensity"` ─────────────────────────────────────────
     ONE hue carries every cell and a cell's value is only its INTENSITY within
     it, so the hue is a property on the root and the intensity one on the cell.
     A zero cell is neutral, not a faint version of the hue. */
  .lotics-state-matrix[data-mark="intensity"] .lotics-state-matrix__cell {
    border: 2px solid transparent;
    background-color: color-mix(
      in srgb,
      var(--lotics-state-matrix-hue) var(--lotics-state-matrix-intensity),
      transparent
    );
  }

  .lotics-state-matrix[data-mark="intensity"] .lotics-state-matrix__cell[data-empty] {
    background-color: var(--lotics-wash-selected);
  }

  .lotics-state-matrix[data-mark="intensity"] .lotics-state-matrix__cell[data-pressable]:hover {
    border-color: var(--lotics-border-hover);
  }

  .lotics-state-matrix[data-mark="intensity"] .lotics-state-matrix__cell[data-selected] {
    border-color: var(--primary);
  }

  .lotics-state-matrix__scale {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: flex-end;
    gap: var(--lotics-space-4);
  }

  .lotics-state-matrix__swatch {
    flex-shrink: 0;
    /* A stop on the scale, sized off the band the cells take rather than off a
       pair of numbers. */
    width: calc(var(--lotics-register-row) / 2 - var(--lotics-space-6));
    height: calc(var(--lotics-register-row) / 4);
    border-radius: calc(var(--lotics-radius-control) - var(--lotics-space-8));
    background-color: color-mix(
      in srgb,
      var(--lotics-state-matrix-hue) var(--lotics-state-matrix-intensity),
      transparent
    );
  }

  /* Only a pressable legend entry gets the band and the ground — the wash has to
     have somewhere to sit, and a legend nobody can press must not look
     pressable. */
  .lotics-state-matrix__legend-item[data-pressable] {
    padding-inline: var(--lotics-space-8);
    margin: 0;
    border: 0 solid var(--border);
    border-radius: calc(var(--lotics-radius-control) - var(--lotics-space-4));
    background-color: transparent;
    color: inherit;
    font: inherit;
    text-align: start;
    appearance: none;
    cursor: pointer;
    transition: background-color var(--lotics-duration-fast) var(--lotics-ease-standard);
  }

  /* Two rungs, because both states exist here: the filter you picked has to
     stay legible while the pointer travels over its neighbours. */
  .lotics-state-matrix__legend-item[data-pressable]:not([data-selected]):hover {
    background-color: var(--lotics-wash-hover);
  }

  .lotics-state-matrix__legend-item[data-pressable][data-selected] {
    background-color: var(--lotics-wash-selected);
  }

  .lotics-state-matrix__legend-item[data-pressable]:active {
    background-color: var(--lotics-wash-press);
  }

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