/* A cross-tab of states: one scroll container with the axis and the row names sticky. A held cell is its
   state's wash with the state's `Status` mark on it, so cell and legend read one kind by one shape; a press
   is the datum's (`datum_toggle.css`), filling the cell. `data-axis` (named positions, else a wrapping
   field) and `data-mark` (glyph or intensity) key the rules. */
@layer theme, base, lotics, components, utilities;
@layer lotics.tokens, lotics.reset, lotics.components;

@layer lotics.components {
  .lotics-state-matrix {
    --lotics-state-matrix-hue: var(--lotics-tone-blue-solid);
    /* Read in more than one place. */
    --lotics-state-matrix-total-width: 64px;
    /* THE MATRIX'S RHYTHM. Its cells are items of one group, never one object (a strip's hairline): the
       group's rung between columns, and a row standing taller than its cells by a control interior above
       and below, so rows, the container, stand further apart than columns and each name reads as a list
       row. */
    --lotics-state-matrix-gap: var(--lotics-space-8);
    --lotics-state-matrix-air: var(--lotics-space-6);
    /* A column's floor: the band's square for a mark; wider for a cell that says its words. */
    --lotics-state-matrix-cell: var(--lotics-register-row);
    /* What a worded heading needs, measured by the matrix; a day's number needs none past the floor. */
    --lotics-state-matrix-heading: 0px;
    /* What the widest run of marks needs, measured by the matrix; one mark needs none past the floor. */
    --lotics-state-matrix-marks: 0px;
    /* What a worded cell's words need whole, measured by the matrix up to a cap; a mark's cell says none. */
    --lotics-state-matrix-words: 0px;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    min-width: 0;
    gap: var(--lotics-space-12);
    /* The pinned names are capped by the matrix's own width, which a row as wide as its days is not. */
    container-type: inline-size;
  }

  /* The one scroll port: a month beside a 220px label block cannot fit. A cell the arrows reach scrolls
     clear of the pinned names. */
  .lotics-state-matrix__body {
    display: flex;
    flex-direction: column;
    /* A row is as wide as its days, never the port's width, or its pinned name leaves with the row's
       right edge once the days scroll further than the port is wide. */
    align-items: flex-start;
    min-width: 0;
    overflow: auto;
    scroll-padding-inline-start: calc(
      var(--lotics-state-matrix-label-width) + var(--lotics-state-matrix-total-width)
    );
  }

  /* At least the port's width, so the days share its slack. */
  .lotics-state-matrix__head,
  .lotics-state-matrix__row {
    display: flex;
    flex-direction: row;
    align-items: stretch;
    flex-shrink: 0;
    min-width: 100%;
    gap: var(--lotics-state-matrix-gap);
  }

  /* The band and its air above and below a cell, which the name's column fills. */
  .lotics-state-matrix__row {
    min-height: calc(var(--lotics-register-row) + 2 * var(--lotics-state-matrix-air));
  }

  /* Sticky left over the head's rung, on the register ground so cells do not show through. The row
     anatomy inside it fills it. */
  .lotics-state-matrix__lead {
    display: flex;
    flex-direction: row;
    align-items: center;
    /* End-justified so the head's total heading lands over the figures. */
    justify-content: flex-end;
    flex: none;
    width: var(--lotics-state-matrix-label-width);
    /* Half at most: `rowLabelWidth` is a desk measure that cannot give way, so a proportion of the
       component's own box caps it. */
    max-width: 50cqi;
    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 added to the label width, with the cap raised to match, so it
     takes nothing from the name. */
  .lotics-state-matrix__lead[data-total] {
    width: calc(var(--lotics-state-matrix-label-width) + var(--lotics-state-matrix-total-width));
    max-width: calc(50cqi + var(--lotics-state-matrix-total-width));
  }

  /* Scoped to the lead so it outweighs the pressable surface's own `flex-shrink: 0`: a name wider than its
     capped column shrinks into it and wraps, never spilling out past the column's start. */
  .lotics-state-matrix__lead > .lotics-state-matrix__name {
    flex: 1 1 auto;
    min-width: 0;
  }

  /* The pinned column is the port's first box, so a press wash bleeding past its start stands outside the scroll
     area: the name's wash starts at the column's edge. */
  .lotics-state-matrix__row > .lotics-state-matrix__lead > .lotics-state-matrix__name {
    margin-inline-start: 0;
    padding-inline-start: 0;
  }

  /* The name fills its row, air and all, so it reads as a list row; a wrapped one keeps that air over and under
     it, its row growing with it — the cells centring in it — rather than crowding the next. */
  .lotics-state-matrix[data-axis="dated"] .lotics-state-matrix__lead > .lotics-state-matrix__name {
    padding-block: calc((var(--lotics-register-row) + 2 * var(--lotics-state-matrix-air) - var(--lotics-leading-sm)) / 2);
  }

  /* A cell's floor, or a worded heading's or a run of marks' measure where wider (the whole box is the
     target); grow takes the pane's slack. */
  .lotics-state-matrix__axis-cell,
  .lotics-state-matrix__cell {
    flex: 1 0 max(var(--lotics-state-matrix-cell), var(--lotics-state-matrix-heading), var(--lotics-state-matrix-marks), var(--lotics-state-matrix-words));
    min-width: max(var(--lotics-state-matrix-cell), var(--lotics-state-matrix-heading), var(--lotics-state-matrix-marks), var(--lotics-state-matrix-words));
    border-radius: calc(var(--lotics-radius-control) - var(--lotics-space-4));
  }

  /* A dated cell stands in its row's air. */
  .lotics-state-matrix[data-axis="dated"] .lotics-state-matrix__cell {
    margin-block: var(--lotics-state-matrix-air);
  }

  /* A week read for who does what where: each column seats a mark, a few words and one more fact. */
  .lotics-state-matrix[data-cells="words"] {
    --lotics-state-matrix-cell: 96px;
  }

  /* The calendar's day heading: the weekday over the date. */
  .lotics-state-matrix__axis-cell {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--lotics-space-2);
  }

  .lotics-state-matrix__day {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-width: var(--lotics-mark-sm);
    height: var(--lotics-mark-sm);
    border-radius: var(--lotics-radius-full);
  }

  /* TODAY IS A RING, NOT A FILL, as the calendar draws it: the accent disc is what a chosen day wears. */
  .lotics-state-matrix__day[data-current] {
    box-shadow: inset 0 0 0 1px var(--lotics-accent);
  }

  /* A worded heading is words across its column, two lines at most, never a disc. */
  .lotics-state-matrix__day[data-worded] {
    align-self: stretch;
    height: auto;
    padding-inline: var(--lotics-space-8);
    border-radius: 0;
  }

  .lotics-state-matrix__cell {
    position: relative;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    margin: 0;
    padding: 0;
  }

  /* A held cell's body is its state's strong wash, the step a tonal chip draws its edge in, so a grid of
     small marks still reads by colour at a glance; the state's mark stands on it. */
  .lotics-state-matrix__cell[data-held] {
    background-color: var(--lotics-state-matrix-ground);
  }

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

  /* THE PRESS, the datum's: the whole cell is the one target, taking the pointer, the hover and press
     washes laid as an image over the cell's own ground, and the ring. */
  .lotics-state-matrix__press {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    margin: 0;
    padding: 0;
    border: 0 solid transparent;
    border-radius: inherit;
    background-color: transparent;
    background-image: none;
    font: inherit;
    color: inherit;
    appearance: none;
    cursor: pointer;
    touch-action: manipulation;
    user-select: none;
  }

  .lotics-state-matrix__press:hover {
    background-image: linear-gradient(0deg, var(--lotics-wash-selected), var(--lotics-wash-selected));
  }

  .lotics-state-matrix__press:active {
    background-image: linear-gradient(0deg, var(--lotics-wash-press), var(--lotics-wash-press));
  }

  .lotics-state-matrix__press:focus-visible {
    outline: var(--lotics-ring-width) solid var(--ring);
    outline-offset: calc(var(--lotics-ring-width) * -1);
  }

  /* The open cell wears the accent an applied datum wears: on its words, and as its edge where it has
     none. */
  .lotics-state-matrix__cell[data-selected] {
    --lotics-ink-default: var(--lotics-accent);
    box-shadow: inset 0 0 0 var(--lotics-ring-width) var(--lotics-accent);
  }

  /* A cell saying its words reads from its start, as a line does. */
  .lotics-state-matrix[data-cells="words"] .lotics-state-matrix__cell,
  .lotics-state-matrix[data-cells="words"] .lotics-state-matrix__press {
    justify-content: flex-start;
    padding-inline: var(--lotics-space-6);
  }

  /* The state's mark and words over the one fact, each clipped past the column rather than widening it. */
  .lotics-state-matrix__words {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    min-width: 0;
    gap: var(--lotics-space-2);
    text-align: left;
  }

  .lotics-state-matrix__said {
    display: flex;
    flex-direction: row;
    align-items: center;
    min-width: 0;
    gap: var(--lotics-space-4);
  }

  /* A mark per entry, side by side at the pair rung, then "+N" — seated whole, the words giving way. */
  .lotics-state-matrix__marks {
    display: flex;
    flex-direction: row;
    align-items: center;
    flex-shrink: 0;
    gap: var(--lotics-space-4);
  }

  /* The list a cell of several opens: its entries' rows, one under the next. */
  .lotics-state-matrix__list {
    display: flex;
    flex-direction: column;
    align-items: stretch;
  }

  /* A blank the reader can fill: its + waits for the pointer or the keyboard. */
  .lotics-state-matrix__add {
    opacity: 0;
    transition: opacity var(--lotics-duration-fast) var(--lotics-ease-standard);
  }

  .lotics-state-matrix__press:hover > .lotics-state-matrix__add,
  .lotics-state-matrix__press:focus-visible > .lotics-state-matrix__add {
    opacity: 1;
  }

  /* ── the legend, a chart legend's rows: the mark, the name in the supporting ink, the figure ── */

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

  .lotics-state-matrix__legend-item {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--lotics-space-8);
  }

  /* A pressable entry's wash bleeds past its words, as a chart legend row's does, at a pressed row's
     content height. */
  .lotics-state-matrix__legend-item[data-pressable] {
    min-height: var(--lotics-control-content-height);
    padding-inline: var(--lotics-row-wash-bleed);
    margin-inline: calc(var(--lotics-row-wash-bleed) * -1);
  }

  /* ── THE WALLBOARD — `axis="none"` ── Units as textless chips scanned for red. A lane is its name and its
     own wrapping chips; lanes stand a group rung apart so lane edges read before wraps. */
  .lotics-state-matrix[data-axis="none"] .lotics-state-matrix__body {
    gap: var(--lotics-space-8);
  }

  .lotics-state-matrix[data-axis="none"] .lotics-state-matrix__row {
    align-items: flex-start;
    min-height: 0;
  }

  /* A named wallboard compares lengths, so every name keeps `rowLabelWidth`, centred on its first chip
     line. */
  .lotics-state-matrix[data-axis="none"] .lotics-state-matrix__lead {
    position: static;
    justify-content: flex-start;
    min-height: var(--lotics-mark-sm);
  }

  .lotics-state-matrix__cells {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: flex-start;
    flex: 1 1 0%;
    min-width: 0;
    /* The hairline rung, so a hundred cells read as one field. */
    gap: var(--lotics-space-2);
  }

  /* 24 is WCAG 2.5.8's floor; the corner scales the control corner. */
  .lotics-state-matrix[data-axis="none"] .lotics-state-matrix__cell {
    flex: none;
    width: var(--lotics-mark-sm);
    min-width: 0;
    height: var(--lotics-mark-sm);
    border-radius: calc(var(--lotics-radius-control) - var(--lotics-space-6));
  }

  /* ── DENSITY — `mark="intensity"` ── One hue on the root, intensity per cell; zero is neutral, not faint
     hue. */
  .lotics-state-matrix[data-mark="intensity"] .lotics-state-matrix__cell {
    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__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;
    /* Sized off the cell band, not 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
    );
  }
}
