/* ============================================================================
   THE PROGRAM x STAGE MATRIX — the signature visual
   Ledger P2-1 · base audit §5.1, re-grounded by Addendum C Part F
   ----------------------------------------------------------------------------
   A real <table> styled as a star-chart plate. The table is the substrate, not a
   fallback: base audit §5.1 requires it be selectable and screen-readable, and
   Addendum A Part E's "build the table first, then the visual on top of it" makes
   the mobile behaviour free.

   INTERACTION IS PURE CSS — :hover and :focus-within. No script, so it works
   under script-src 'self', for keyboard users, and with JS off. Each cell is
   tabindex=0 so the detail is reachable by Tab, not only by pointer.

   RESPONSIVE, per Addendum A Part E's per-diagram table:
     >=1024  full 5x5 grid
     768-1024 5x5, condensed cells
     <768    stepper — one program at a time, five stages stacked, swipe between
             programs. Implemented as CSS scroll-snap, so the swipe is native and
             needs no script.
   ========================================================================= */

/* ⛔ CONTAINER NAMING IS A SITE-WIDE CONVENTION, NOT A PER-DIAGRAM CHOICE.
   This file used to set `container-name: matrix` here — on the SAME element that
   layout.css names `plate`. Cascade order decided the winner, so every generic
   `@container plate (...)` rule silently stopped matching on a matrix plate. With
   thirteen diagrams each naming its own container on the shared .plate element,
   that fragments on contact.
   THE RULE: layout.css's .plate owns `container-type` and `container-name: plate`.
   Every diagram queries `@container plate (...)`. No diagram declares its own. */
.matrix-plate { position: relative; }

.matrix-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

table.matrix {
  border-collapse: separate;
  border-spacing: 0;
  width: 100%;
  table-layout: fixed;
}

/* ── HEADERS ─────────────────────────────────────────────────────────────── */
.matrix-corner { width: 12rem; padding: 0 0.75rem 0.6rem 0; vertical-align: bottom; }
.matrix-corner .tick { color: var(--star-dim); opacity: 0.7; }

th.matrix-stage {
  text-align: left;
  font-weight: 400;
  padding: 0 0.75rem 0.6rem;
  vertical-align: bottom;
  border-bottom: var(--hair) solid color-mix(in srgb, var(--star) 30%, transparent);
}
th.matrix-stage .tick { display: block; color: var(--star-dim); opacity: 0.65; }
.matrix-stage-l {
  display: block;
  font-family: var(--f-display);
  font-size: var(--d5);
  letter-spacing: -0.01em;
  color: var(--star);
}

/* ── ROW HEADER — the "star" ─────────────────────────────────────────────
   Uniform markers. Size encodes nothing because nothing honest is available to
   encode; the legend says so rather than leaving the reader to assume. */
th.matrix-prog {
  text-align: left;
  font-weight: 400;
  padding: 0.9rem 0.75rem 0.9rem 0;
  vertical-align: top;
  border-bottom: var(--hair) solid color-mix(in srgb, var(--star) 12%, transparent);
}
.matrix-star {
  display: inline-block; width: 0.5rem; height: 0.5rem; margin-right: 0.5rem;
  border-radius: 50%;
  background: var(--star-dim);
  vertical-align: 0.15em;
  transition: background-color var(--t-hover) var(--e-out), box-shadow var(--t-hover) var(--e-out);
}
.matrix-prog-l { font-family: var(--f-display); font-size: var(--d5); color: var(--star); }
.matrix-prog-f { display: block; margin-top: 0.15rem; color: var(--star-dim); opacity: 0.75; }

/* Hover/focus anywhere in a row brightens that row's star — the asterism
   responding to the cell (Addendum C Part F). */
.matrix-row:hover .matrix-star,
.matrix-row:focus-within .matrix-star {
  background: var(--waterline);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--waterline) 22%, transparent);
}

/* ── CELLS ───────────────────────────────────────────────────────────────── */
td.matrix-cell {
  padding: 0.9rem 0.75rem;
  vertical-align: top;
  border-bottom: var(--hair) solid color-mix(in srgb, var(--star) 12%, transparent);
  border-left: var(--hair) solid color-mix(in srgb, var(--star) 9%, transparent);
  cursor: default;
  transition: background-color var(--t-hover) var(--e-out);
}
td.matrix-cell:hover,
td.matrix-cell:focus-visible,
td.matrix-cell:focus-within { background: color-mix(in srgb, var(--star) 5%, transparent); }
td.matrix-cell:focus-visible { outline: 2px solid var(--waterline); outline-offset: -2px; }

.matrix-label {
  display: block;
  font-size: var(--t-small);
  line-height: 1.35;
  color: var(--star);
}

/* THE DETAIL. Collapsed by grid-template-rows so it animates without animating
   height, and so its content stays in the accessibility tree at all times —
   opacity-hiding a live region is the failure mode Addendum A Part D names.

   🪤 THE 0fr COLLAPSE REQUIRES EXACTLY ONE GRID CHILD, and this shipped with
   three. `grid-template-rows: 0fr` defines ONE EXPLICIT ROW; children 2..n land
   in AUTO-SIZED IMPLICIT rows and do not collapse at all. Measured 2026-08-13
   across nine viewports in both reduced-motion arms: the detail was open at
   every width, 125–240px tall, so the progressive disclosure that makes a 5x5
   matrix readable had never once worked. The screenshot looked dense because
   every cell was fully expanded.
   The fix is structural, not a tweak: ONE child, .matrix-detail-inner, and the
   selector below enforces it by only ever sizing that single row. */
.matrix-detail {
  display: grid;
  grid-template-rows: 0fr;
  overflow: hidden;
  transition: grid-template-rows var(--t-accordion) var(--e-inout);
}
.matrix-detail > .matrix-detail-inner { min-height: 0; overflow: hidden; }
td.matrix-cell:hover .matrix-detail,
td.matrix-cell:focus-within .matrix-detail,
td.matrix-cell:focus-visible .matrix-detail { grid-template-rows: 1fr; }

.matrix-work,
.matrix-artifact { display: block; font-size: var(--m-tick); line-height: 1.5; color: var(--star-dim); }
.matrix-work { margin-top: 0.6rem; }
.matrix-artifact { margin-top: 0.45rem; }
.matrix-artifact .tick { color: color-mix(in srgb, var(--star-dim) 70%, transparent); text-transform: uppercase; letter-spacing: 0.06em; }
.matrix-detail .badge { margin-top: 0.5rem; font-size: var(--m-tick); white-space: normal; }
.matrix-detail .badge .cite { display: block; margin-top: 0.15rem; }

/* Reduced motion: no collapse animation, and the detail is simply always open.
   A reader who asked for no motion gets the information, not a stub. */
@media (prefers-reduced-motion: reduce) {
  .matrix-detail { grid-template-rows: 1fr; transition: none; }
}

/* ── THE SPINE / ASTERISM ────────────────────────────────────────────────
   A continuous hairline beneath all five rows. Base audit §5.1: this visually
   proves the claim the copy currently has to assert. It is drawn in --current
   because what runs along it is the student record. */
.matrix-spine { margin-top: 0.85rem; }
.matrix-spine-rule {
  display: block; height: 0; width: 100%;
  border-top: var(--hair-strong) solid var(--current);
  transform-origin: left center;
}
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .matrix-spine-rule { animation: draw-x linear both; animation-timeline: view(); animation-range: entry 25% entry 75%; }
  }
}
.matrix-spine-note { margin: 0.5rem 0 0; color: var(--star-dim); }

.matrix-legend { margin-top: 1.5rem; }
.matrix-prov { margin: 0.75rem 0 0; color: var(--star-dim); }

/* ── 768-1024: condensed ─────────────────────────────────────────────────── */
/* ── THRESHOLDS ARE MEASURED, NOT INHERITED ─────────────────────────────
   These were Addendum A Part E's table (>=1024 / 768-1024 / <768) applied
   verbatim. That table is VIEWPORT widths; these are CONTAINER widths, and
   they are not the same measurement. Measured 2026-08-13, the plate's content
   box ran 200px at a 360px viewport and capped at 952px at 3440px -- so the
   full 5x5 grid, the signature visual, NEVER RENDERED AT ANY VIEWPORT, and a
   1024px laptop got the phone stepper.
   Re-derived from the measured series (200/581/573/799/882/952+, and ~1430
   once the plate breaks out of the main column via .bleed in layout.css). */
@container plate (max-width: 1099px) {
  .matrix-corner { width: 9rem; }
  td.matrix-cell, th.matrix-prog { padding: 0.7rem 0.5rem; }
  .matrix-prog-f { display: none; }
}

/* ── <768: THE STEPPER ───────────────────────────────────────────────────
   One program at a time, five stages stacked, native swipe via scroll-snap.
   Addendum A Part E: "The matrix at 360px cannot be a tappable 5x5 grid."
   The table becomes a set of blocks; each row is a snap point. Semantics are
   preserved — it is still the same table to a screen reader. */
@container plate (max-width: 639px) {
  .matrix-scroll {
    display: flex; overflow-x: auto;
    scroll-snap-type: x mandatory;
    gap: 1rem;
  }
  table.matrix, table.matrix thead, table.matrix tbody { display: block; width: 100%; }
  table.matrix thead { display: none; }
  table.matrix tbody { display: flex; gap: 1rem; }
  .matrix-row {
    display: block;
    flex: 0 0 min(85vw, 22rem);
    scroll-snap-align: start;
    border: var(--hair) solid color-mix(in srgb, var(--star) 15%, transparent);
    padding: 0.9rem;
  }
  th.matrix-prog { display: block; padding: 0 0 0.6rem; border-bottom-color: color-mix(in srgb, var(--star) 25%, transparent); }
  .matrix-prog-f { display: block; }
  td.matrix-cell { display: block; border-left: 0; padding: 0.7rem 0; min-height: 44px; }
  /* Stages are unlabelled once the column header is gone — restore the label. */
  td.matrix-cell::before {
    content: attr(data-stage);
    display: block;
    font-family: var(--f-data); font-size: var(--m-tick);
    color: var(--star-dim); letter-spacing: 0.06em; text-transform: uppercase;
    margin-bottom: 0.2rem;
  }
  /* On touch there is no hover: show every detail rather than hiding content
     behind an interaction the device cannot perform. */
  .matrix-detail { grid-template-rows: 1fr; }
}

/* ── PRINT ───────────────────────────────────────────────────────────────── */
@media print {
  .matrix-plate { background: #fff; color: #000; }
  .matrix-detail { grid-template-rows: 1fr; }
  td.matrix-cell, th.matrix-prog, th.matrix-stage { border-color: #999; }
  .matrix-label, .matrix-prog-l, .matrix-stage-l { color: #000; }
  .matrix-work, .matrix-artifact, .matrix-prog-f { color: #333; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   THE STAR-CHART TREATMENT (Addendum C Part F)
   ---------------------------------------------------------------------------
   "A constellation is literally lines drawn between fixed points. Five programs
   are five stars; the record is the asterism joining them." The claim the copy
   used to have to assert — one record across five programmes — becomes the
   picture: a continuous chain that cannot be broken without breaking the figure.
   ═════════════════════════════════════════════════════════════════════════ */

/* The row marker becomes a real star: a bright core with a faint halo, on the
   chain. ⛔ UNIFORM SIZE — see the generator header. */
.matrix-star {
  position: relative; z-index: 2;
  width: .5rem; height: .5rem; border-radius: 50%;
  background: var(--star);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--star) 18%, transparent),
              0 0 7px 1px color-mix(in srgb, var(--star) 30%, transparent);
}

/* THE CHAIN. Each row header draws the segment rising to the row above it, so
   the five markers are joined top to bottom by one continuous line. Drawn on the
   header rather than as an overlay, so it tracks real row heights at any
   viewport instead of needing measured coordinates. */
th.matrix-prog { position: relative; }
/* 🪤 EVERY ROW DRAWS A FULL-HEIGHT SEGMENT, not a half-segment reaching up.
   The first version used top:-50% with a half-height span, which assumes rows
   are the same height. They are not — an expanded cell can double a row — so the
   chain rendered as disconnected dashes. A full-height line in every row header
   makes adjacent rows TOUCH BY CONSTRUCTION, at any row height, with no
   measurement. The first row starts at its star so the chain does not float
   above the figure. */
.matrix-row th.matrix-prog::before {
  content: ''; position: absolute; z-index: 1;
  left: calc(.25rem - 0.5px); width: 1px;
  top: 0; bottom: 0;
  background: color-mix(in srgb, var(--current) 42%, transparent);
  transition: background var(--t-hover) var(--e-out);
}
.matrix-row:first-child th.matrix-prog::before { top: 1.05rem; }
.matrix-row:last-child  th.matrix-prog::before { bottom: auto; height: 1.05rem; }
/* Hovering a row brightens ITS star and the segments it touches — the segment
   above it, and the one below it, which belongs to the next row. */
/* Hovering a row lights its own segment and the one below it — the two segments
   that meet at its star. */
.matrix-row:hover th.matrix-prog::before,
.matrix-row:focus-within th.matrix-prog::before,
.matrix-row:hover + .matrix-row th.matrix-prog::before,
.matrix-row:focus-within + .matrix-row th.matrix-prog::before {
  background: var(--waterline);
}
.matrix-row:hover .matrix-star,
.matrix-row:focus-within .matrix-star {
  background: var(--waterline);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--waterline) 26%, transparent),
              0 0 14px 2px color-mix(in srgb, var(--waterline) 45%, transparent);
}

/* ── MARGIN TICKS — real, per Addendum C Part G ─────────────────────────── */
.matrix-dens {
  display: block; margin-top: .3rem;
  color: color-mix(in srgb, var(--mira) 78%, var(--star-dim));
  letter-spacing: .04em;
}
th.matrix-stage .matrix-dens { margin-top: .35rem; }

/* ── CHART-PLATE FRAME ──────────────────────────────────────────────────
   Coordinate ticks along the plate edge, in the chart-plate convention: short
   rules at the column boundaries rather than a box. A chart is a measured
   field, not a card. */
.matrix-plate { --tick-c: color-mix(in srgb, var(--star) 26%, transparent); }
table.matrix { position: relative; }
th.matrix-stage { position: relative; }
th.matrix-stage::before {
  content: ''; position: absolute; left: 0; top: 0; width: 1px; height: .5rem;
  background: var(--tick-c);
}
td.matrix-cell:first-of-type { border-left-color: var(--tick-c); }

/* Legend keys mirror the plate exactly so the legend cannot drift from it. */
.matrix-key-star {
  display: inline-block; width: .5rem; height: .5rem; border-radius: 50%;
  background: var(--star); vertical-align: .05rem;
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--star) 18%, transparent);
}
.matrix-key-line {
  display: inline-block; width: 1.6rem; height: 0; vertical-align: .28rem;
  border-top: var(--hair-strong) solid color-mix(in srgb, var(--current) 55%, transparent);
}

/* On the stepper the chain is meaningless — the rows are side-by-side panels,
   not a vertical figure — so it is removed rather than drawn wrong. */
@container plate (max-width: 639px) {
  .matrix-row th.matrix-prog::before { display: none; }
  .matrix-dens { color: var(--star-dim); }
}

/* ══ THE TWO-PART MATRIX (restructure 2026-08-15) ═══════════════════
   The grid summarises; the notes below carry the prose at full column width.
   ⛔ THE ACCORDION RULES ABOVE ARE NOW INERT — .matrix-detail is no longer
   emitted. They are left in place deliberately: they document the 0fr/implicit-
   row trap in the position where the next person will hit it, and they cost
   nothing because their selectors match nothing. The build guard that used to
   count .matrix-detail-inner has been REPLACED, not deleted, by a set-equality
   check between the grid's links and the notes' ids. */

.matrix-ref {
  display: flex; align-items: baseline; gap: .4rem;
  color: inherit; text-decoration: none;
}
.matrix-ref:hover .matrix-label,
.matrix-ref:focus-visible .matrix-label { text-decoration: underline; text-underline-offset: 2px; }
.matrix-ref:focus-visible { outline: 2px solid var(--waterline); outline-offset: 3px; border-radius: 2px; }
.matrix-refn {
  margin-left: auto; flex: none;
  color: var(--star-dim); opacity: .6;
  font-variant-numeric: tabular-nums;
}
/* The visually-hidden pointer: a screen reader hears “Refer + consent — see
   note 2.2”, which is the same navigation the sighted reader gets from the
   number. Without it the link text is the label alone and the reference is
   unreachable by sound. */
.vh {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

td.matrix-cell { vertical-align: top; }

.matrix-notes { margin-top: clamp(1.6rem, 3.5vh, 2.6rem); }
/* ⛔ A REAL HEADING, NOT A CAPTION. This shipped as <h3 class="sec-n"> and
   failed WCAG AA at 3.32:1 — .sec-n is the dim tick style for figure captions,
   which is legible as a label beside a plate and is not legible as the only
   heading of a 25-entry reference list. It also jumped h1 -> h3. */
.matrix-notes-h {
  margin: 0 0 1rem;
  font-size: var(--m-h3, 1.05rem); font-weight: 500;
  /* ⛔ --text-ink DOES NOT RESOLVE HERE and the fallback did not save it:
     measured 1.10:1, effectively invisible. .g-chart REMAPS --star to the ink
     colour for its own surface, so --star is the correct token on this plate
     and --text-ink is a token from the light-surface set. A fallback chain is
     not a substitute for using the surface's own variable. */
  color: var(--star);
  letter-spacing: .01em;
}
/* ⛔ A MULTI-COLUMN LIST WOULD RE-CREATE THE DEFECT. The whole point is that
   these entries get a readable measure, so the columns are wide and only
   appear when there is genuinely room for two of them. */
/* ⛔ COLUMNS, NOT GRID. As a grid the entries share row tracks, so a tall
   entry left a matching hole beside every short one — visible in the first
   capture as a gap under 1.5 the height of 2.1. Multi-column FLOWS instead of
   aligning, which is what a reference list wants; break-inside keeps an entry
   whole. The column width is a measure, not a count: two columns appear only
   when there is room for two readable ones. */
.matrix-dl {
  margin: 0;
  columns: 30rem 2;
  column-gap: 2.6rem;
}
.matrix-entry { break-inside: avoid; -webkit-column-break-inside: avoid; page-break-inside: avoid; }
/* the first entry must not start with a top margin the column edge exposes */
.matrix-entry:first-child .matrix-dt { margin-top: 0; }
.matrix-dt {
  display: flex; align-items: baseline; gap: .5rem;
  margin-top: 1.05rem; padding-top: .55rem;
  border-top: var(--hair) solid color-mix(in srgb, var(--star) 16%, transparent);
}
.matrix-dtn { color: var(--star-dim); opacity: .75; font-variant-numeric: tabular-nums; flex: none; }
.matrix-dtp { color: var(--star-dim); font-size: var(--m-tick); }
.matrix-dts { font-weight: 500; }
.matrix-dd { margin: .3rem 0 0; }
.matrix-dd .matrix-work { margin: 0; max-width: 62ch; }
.matrix-dd .matrix-artifact { margin: .35rem 0 0; }
.matrix-dd .badge { margin-top: .45rem; }

/* Print: the notes are the content, so they must not be split mid-entry. */
@media print {
  .matrix-dt { break-after: avoid; }
  .matrix-dd { break-inside: avoid; }
  .matrix-refn { display: none; }
}
