/* ==========================================================================
   DS Matrix — CoachOS Design System
   Editorial-style matrix primitive. Extension of components/tables.css —
   cells provide ALL borders directly (border-bottom on every cell, border-left
   on non-first columns, border-top on header, border-right on last column),
   and the 4 corner cells carry the border-radius. NO outer container border,
   NO overflow:hidden corner-clipping (unreliable per CLAUDE.md Lesson 8).
   Selected state = accent-subtle background + inset shadow (never border swap).

   Variants:
     • .ds-matrix             — interactive matrix (radio / checkbox cells).
                                Used by GRID_SINGLE_CHOICE, GRID_MULTIPLE_CHOICE,
                                CUSTOM_GRID_CHOICE answering.
     • .ds-matrix--rubric     — single-row rubric. Cells are level cards
                                (score + name + description). Used by RUBRIC.
     • .ds-matrix--readonly   — aggregation companion modifier. Cells render
                                pick counts; cells with picks adopt
                                .ds-matrix__cell--has-picks for emphasis.

   Mobile-first. Default layout is row-stacked cards (works at 360px+).
   The desktop true-matrix grid kicks in at @media (min-width: 768px).
   ========================================================================== */

/* ── Container ─────────────────────────────────────────────────────────── */

.ds-matrix {
  /* Mobile-first: row-stacked. No container chrome; rows are individual cards. */
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  --ds-matrix-row-label-width: 150px;
  --ds-matrix-cols: 4;
}

@media (min-width: 768px) {
  .ds-matrix {
    display: block;
    background-color: var(--surface-base);
    gap: 0;
    /* No outer border, no overflow:hidden. Corner cells carry the radius. */
  }
}

/* ── Header row (desktop only) ─────────────────────────────────────────── */

.ds-matrix__header {
  display: none;
}

@media (min-width: 768px) {
  .ds-matrix__header {
    display: grid;
    grid-template-columns: var(--ds-matrix-row-label-width) repeat(var(--ds-matrix-cols), 1fr);
  }
}

.ds-matrix__header-cell {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: var(--space-3);
  text-align: center;
  background-color: var(--surface-sunken);
}

.ds-matrix__header-cell:first-child {
  text-align: left;
}

@media (min-width: 768px) {
  /* Header cells: top + bottom + left borders. Last cell adds right border.
     This mirrors the table.css pattern (cells provide all borders). */
  .ds-matrix__header-cell {
    border-top: 1px solid var(--border-default);
    border-bottom: 1px solid var(--border-default);
    border-left: 1px solid var(--border-default);
  }
  .ds-matrix__header-cell:last-child {
    border-right: 1px solid var(--border-default);
  }
  /* Top corner radii on the header's first + last cells. */
  .ds-matrix__header-cell:first-child {
    border-top-left-radius: var(--radius-lg);
  }
  .ds-matrix__header-cell:last-child {
    border-top-right-radius: var(--radius-lg);
  }
}

/* ── Row ───────────────────────────────────────────────────────────────── */

.ds-matrix__row {
  /* Mobile: row is its own card */
  background-color: var(--surface-base);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  padding: var(--space-3);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

@media (min-width: 768px) {
  .ds-matrix__row {
    display: grid;
    grid-template-columns: var(--ds-matrix-row-label-width) repeat(var(--ds-matrix-cols), 1fr);
    background-color: transparent;
    border: 0;
    border-radius: 0;
    padding: 0;
    gap: 0;
  }
}

/* ── Row label ─────────────────────────────────────────────────────────── */

.ds-matrix__row-label {
  display: flex;
  align-items: center;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--text-primary);
}

@media (min-width: 768px) {
  .ds-matrix__row-label {
    padding: var(--space-3);
    border-bottom: 1px solid var(--border-default);
    border-left: 1px solid var(--border-default);
    background-color: var(--surface-base);
  }
  /* Bottom-left corner of the matrix: last row's row-label. */
  .ds-matrix__row:last-child .ds-matrix__row-label {
    border-bottom-left-radius: var(--radius-lg);
  }
  /* If there is no header row, the FIRST row's row-label carries top border + radius. */
  .ds-matrix:not(:has(.ds-matrix__header)) .ds-matrix__row:first-child .ds-matrix__row-label {
    border-top: 1px solid var(--border-default);
    border-top-left-radius: var(--radius-lg);
  }
}

/* ── Cells container (mobile only — flattens on desktop) ──────────────── */

.ds-matrix__cells {
  display: grid;
  grid-template-columns: repeat(var(--ds-matrix-cols), 1fr);
  gap: var(--space-1);
}

@media (min-width: 768px) {
  .ds-matrix__cells {
    display: contents;
  }
}

/* ── Cell ──────────────────────────────────────────────────────────────── */

.ds-matrix__cell {
  /* Mobile: labelled chip */
  /* position: relative is REQUIRED — anchors the visually-hidden
     .ds-matrix__input child (radio/checkbox) so label-click focus does
     not scroll the document root. See DS Conventions →
     "Visually-hidden form inputs" at /a/design-system/contribute. */
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  padding: var(--space-2);
  border-radius: var(--radius-sm);
  background-color: var(--surface-sunken);
  cursor: pointer;
  transition:
    background-color var(--duration-fast) var(--ease-out),
    box-shadow var(--duration-fast) var(--ease-out);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--text-secondary);
}

/* Hover bg rules across this file scope to non-picked cells via
   :not(:is(--has-picks, --on, :has(:checked))). The picked-state rule
   (lower in this file) is the single source of truth for picked
   appearance — hover never overrides it. */
.ds-matrix__cell:not(:is(.ds-matrix__cell--has-picks, .ds-matrix__cell--on, :has(.ds-matrix__input:checked))):hover {
  background-color: var(--surface-hover);
  color: var(--text-primary);
}

.ds-matrix__cell:has(.ds-matrix__input:focus-visible) {
  outline: 2px solid var(--border-focus, var(--accent-primary));
  outline-offset: 2px;
}

/* Picked state — single source of truth for all three picked markers:
     :has(.ds-matrix__input:checked) — interactive picked (Q-Web)
     .ds-matrix__cell--on            — interactive picked (manual modifier)
     .ds-matrix__cell--has-picks     — readonly picked (A-Web aggregation)
   Identical visual treatment across all three so coaches see exactly the
   same emphasis on a readonly aggregation that participants see while
   answering. Background fill + matching text color + inset accent ring. */
.ds-matrix__cell:has(.ds-matrix__input:checked),
.ds-matrix__cell--on,
.ds-matrix__cell--has-picks {
  background-color: var(--accent-subtle);
  color: var(--accent-primary);
  box-shadow: inset 0 0 0 1.5px var(--accent-primary);
}

@media (min-width: 768px) {
  .ds-matrix__cell {
    padding: var(--space-3);
    border-radius: 0;
    color: var(--text-secondary);
    font-size: var(--text-sm);
  }
  /* Bg scoped to non-picked cells so the canonical picked-state rule
     (--accent-subtle) survives. Without this exclusion, this desktop
     bg rule (specificity 0,1,0, source order later than picked) would
     beat .ds-matrix__cell--has-picks and .ds-matrix__cell--on by source
     order — picked cells in A-Web answer aggregation would render white
     on desktop. (Mobile is fine: the mobile base bg at the top of this
     file comes BEFORE the picked rule, so picked wins by source order.) */
  .ds-matrix__cell:not(:is(.ds-matrix__cell--has-picks, .ds-matrix__cell--on, :has(.ds-matrix__input:checked))) {
    background-color: var(--surface-base);
  }
  /* Cells provide their own borders, table-style. */
  .ds-matrix__cell {
    border-bottom: 1px solid var(--border-default);
    border-left: 1px solid var(--border-default);
  }
  .ds-matrix__cell:last-child {
    border-right: 1px solid var(--border-default);
  }
  /* When there is no header, the first row's cells need a top border. */
  .ds-matrix:not(:has(.ds-matrix__header)) .ds-matrix__row:first-child .ds-matrix__cell {
    border-top: 1px solid var(--border-default);
  }
  /* Bottom-right corner of the matrix: last row's last cell. */
  .ds-matrix__row:last-child .ds-matrix__cell:last-child {
    border-bottom-right-radius: var(--radius-lg);
  }
  /* If there is no header, the FIRST row's outer corners need radii too. */
  .ds-matrix:not(:has(.ds-matrix__header)) .ds-matrix__row:first-child .ds-matrix__cell:last-child {
    border-top-right-radius: var(--radius-lg);
  }
  .ds-matrix__cell:not(:is(.ds-matrix__cell--has-picks, .ds-matrix__cell--on, :has(.ds-matrix__input:checked))):hover {
    background-color: var(--surface-hover);
  }
  /* Picked-state rule lives once at the top of this file (mobile-first);
     it applies on desktop too — no redeclaration needed. */
}

/* Mobile-only column label inside the chip; hidden on desktop because the
   header row provides the column label. */
.ds-matrix__cell-label {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

@media (min-width: 768px) {
  .ds-matrix__cell-label {
    display: none;
  }
}

/* ── Hidden input ──────────────────────────────────────────────────────── */

.ds-matrix__input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  border: 0;
}

/* ── Mark (radio/checkbox indicator) ───────────────────────────────────── */

.ds-matrix__mark {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1.5px var(--border-strong);
  transition:
    box-shadow var(--duration-fast) var(--ease-out),
    background-color var(--duration-fast) var(--ease-out);
  flex-shrink: 0;
}

.ds-matrix__cell:has(.ds-matrix__input:checked) .ds-matrix__mark,
.ds-matrix__cell--on .ds-matrix__mark {
  box-shadow: inset 0 0 0 6px var(--accent-primary);
}

/* Square mark (checkbox variant) */
.ds-matrix__mark--square {
  border-radius: 4px;
  position: relative;
}

.ds-matrix__cell:has(.ds-matrix__input:checked) .ds-matrix__mark--square,
.ds-matrix__cell--on .ds-matrix__mark--square {
  box-shadow: inset 0 0 0 1.5px var(--accent-primary);
  background-color: var(--accent-primary);
}

.ds-matrix__cell:has(.ds-matrix__input:checked) .ds-matrix__mark--square::after,
.ds-matrix__cell--on .ds-matrix__mark--square::after {
  content: "✓";
  color: var(--text-on-accent);
  font-size: 13px;
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

/* ==========================================================================
   .ds-matrix--rubric — single-row rubric variant
   Each cell holds a level (score + name + description). Same outer chrome
   and selection treatment.
   ========================================================================== */

.ds-matrix--rubric .ds-matrix__cells {
  /* Mobile: rubric levels always stack 1-up regardless of desktop col count.
     Zero the inherited gap (var(--space-1) from base .ds-matrix__cells) so
     cells touch — otherwise the picked cell's accent treatment leaves a
     4px white strip above and below it, before the next cell's divider. */
  grid-template-columns: 1fr;
  gap: 0;
}

/* Mobile rubric: cells stack inside a single bordered card with 1px
   border-bottom hairline dividers between levels. White cell backgrounds
   contrast with picked cells' --accent-subtle. overflow: hidden on the
   row clips the selected cell's accent bg to the row's rounded corners. */
.ds-matrix--rubric .ds-matrix__row {
  padding: 0;
  gap: 0;
  overflow: hidden;
}
.ds-matrix--rubric .ds-matrix__cell {
  border-bottom: 1px solid var(--border-default);
  border-radius: 0;
}
.ds-matrix--rubric .ds-matrix__cells > .ds-matrix__cell:last-child {
  border-bottom: 0;
}
/* Background rules exclude every picked-state marker so the picked accent
   treatment survives:
     :has(.ds-matrix__input:checked) — interactive picked (Q-Web rubric)
     .ds-matrix__cell--on             — interactive picked (manual modifier)
     .ds-matrix__cell--has-picks      — readonly picked (A-Web rubric)
   Without the full exclusion, the rubric scope (specificity 0,2,0) beats
   the picked rules (0,2,0 same source order, but later picked rules win
   in source ONLY when this rubric rule doesn't outrank them) — so picked
   cells would render white instead of accent-subtle in either Q or A view. */
.ds-matrix--rubric .ds-matrix__cell:not(:is(.ds-matrix__cell--has-picks, .ds-matrix__cell--on, :has(.ds-matrix__input:checked))) {
  background-color: var(--surface-base);
}
.ds-matrix--rubric .ds-matrix__cell:not(:is(.ds-matrix__cell--has-picks, .ds-matrix__cell--on, :has(.ds-matrix__input:checked))):hover {
  background-color: var(--surface-hover);
}

@media (min-width: 768px) {
  /* Desktop: a single row with N columns (no row label, no header). */
  .ds-matrix--rubric .ds-matrix__row {
    grid-template-columns: repeat(var(--ds-matrix-cols, 3), 1fr);
  }
  /* No header + no row-label means the rubric row IS the entire matrix.
     Each cell needs full outer border treatment. */
  .ds-matrix--rubric .ds-matrix__cell {
    border-top: 1px solid var(--border-default);
  }
  .ds-matrix--rubric .ds-matrix__cell:first-child {
    border-top-left-radius: var(--radius-lg);
    border-bottom-left-radius: var(--radius-lg);
  }
  .ds-matrix--rubric .ds-matrix__cell:last-child {
    border-top-right-radius: var(--radius-lg);
    border-bottom-right-radius: var(--radius-lg);
  }
  /* Restore the bottom border on the rightmost cell — the mobile rule above
     strips it on the last child because mobile cells stack vertically.
     On desktop the cells are arranged horizontally, so the last cell's
     bottom border IS the matrix bottom. */
  .ds-matrix--rubric .ds-matrix__cells > .ds-matrix__cell:last-child {
    border-bottom: 1px solid var(--border-default);
  }
}

.ds-matrix--rubric .ds-matrix__cell {
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  gap: var(--space-2);
  padding: var(--space-4);
  text-align: left;
}

@media (min-width: 768px) {
  .ds-matrix--rubric .ds-matrix__cell {
    padding: var(--space-4);
  }
}

.ds-matrix__rubric-head {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
}

.ds-matrix__rubric-score {
  font-size: var(--text-xl);
  font-weight: var(--weight-bold);
  color: var(--accent-primary);
  line-height: var(--leading-none);
  font-variant-numeric: tabular-nums;
}

.ds-matrix__rubric-name {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--text-primary);
  line-height: var(--leading-snug);
}

.ds-matrix__rubric-desc {
  font-size: var(--text-xs);
  color: var(--text-secondary);
  line-height: var(--leading-snug);
}

/* Answer count pill — inline at the right edge of the rubric head. Renders
   only when the parent collection has more than one answer (per the
   "single-answer is obvious from style alone" rule). On --has-picks cells,
   adopts the saturated accent treatment. */
.ds-matrix__rubric-count {
  margin-left: auto;
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--text-secondary);
  padding: 2px var(--space-2);
  border-radius: var(--radius-full);
  background-color: var(--surface-sunken);
  font-variant-numeric: tabular-nums;
  line-height: 1.4;
}
.ds-matrix__cell--has-picks .ds-matrix__rubric-count {
  background-color: var(--accent-primary);
  color: var(--text-on-accent);
}

/* ==========================================================================
   .ds-matrix--readonly — aggregation companion modifier
   Reuses every structural rule above. Cells render pick counts via
   .ds-matrix__count; cells with picks adopt .ds-matrix__cell--has-picks
   (background-only accent-subtle, no inset ring).
   ========================================================================== */

/* Read-only is informative, not deactivated — the cell looks identical to
   the interactive resting state with two surgical changes: cursor signals
   non-interactivity, and hover collapses to resting (no color/background
   shift). The interactive variants' picked treatment (--has-picks +
   accent-subtle bg) carries through unchanged so coaches see exactly the
   same visual emphasis on selected cells that participants will see. */
.ds-matrix--readonly .ds-matrix__cell {
  cursor: not-allowed;
}

/* Mobile readonly: hover stays at resting state. Default mobile cell bg is
   --surface-sunken (per .ds-matrix__cell base); rubric overrides to white
   per the rubric mobile rules above — both are preserved here. */
.ds-matrix--readonly .ds-matrix__cell:not(:is(.ds-matrix__cell--has-picks, .ds-matrix__cell--on, :has(.ds-matrix__input:checked))):hover {
  background-color: var(--surface-sunken);
}
.ds-matrix--rubric.ds-matrix--readonly .ds-matrix__cell:not(:is(.ds-matrix__cell--has-picks, .ds-matrix__cell--on, :has(.ds-matrix__input:checked))):hover {
  background-color: var(--surface-base);
}

@media (min-width: 768px) {
  .ds-matrix--readonly .ds-matrix__cell:not(:is(.ds-matrix__cell--has-picks, .ds-matrix__cell--on, :has(.ds-matrix__input:checked))):hover {
    background-color: var(--surface-base);
  }
}

/* Picked readonly cells inherit the canonical picked-state rule near the
   top of this file (.ds-matrix__cell--has-picks is in that selector list).
   Hover behavior is locked because that rule has no :hover modifier and
   the readonly cell hover override below is scoped to non-picked cells. */

/* Pick count display inside readonly cells. */
.ds-matrix__count {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

.ds-matrix__cell--has-picks .ds-matrix__count {
  color: var(--accent-primary);
}
