/* Catalogue faceting (BL-022) + side-by-side comparison (BL-023).
 *
 * A page-scoped sheet rather than an addition to portal.css: these two features
 * load on /catalogue and /compare only, and portal.css is the shared surface
 * every other session edits. Everything below is expressed in the design tokens
 * portal.css already publishes, so both visual registers (Classic / Modern) and
 * both themes (light / dark) are inherited rather than re-specified — no
 * hard-coded colour appears in this file.
 */

/* A filtered-out card must disappear in BOTH registers. The grid rules in
 * portal.css set `display` on these elements, which outranks the UA stylesheet's
 * [hidden] rule, so the intent is restated where it can win. This is also what
 * makes the server-rendered no-JS filter work with scripting off. */
.cat-card[hidden],
.cat-bootcamp[hidden],
.cat-level[hidden] {
  display: none !important;
}

/* ---------------------------------------------------------------- *
 * Filter / sort panel
 * ---------------------------------------------------------------- */

.cat-filters {
  margin: 1.25rem 0 2rem;
  padding: 1rem 1.15rem 1.15rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-elev);
}

.cat-filters-head {
  margin: 0 0 0.2rem;
  font-size: 1.05rem;
}

.cat-filters-intro {
  margin: 0 0 0.85rem;
  font-size: 0.9rem;
}

/* auto-fit rather than a fixed column count: seven controls have to sit on one
 * row on a desktop and stack cleanly on a phone without a media query. */
.cat-filters-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 0.6rem 0.9rem;
}

.cat-filter {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  margin: 0;
}

.cat-filter-label {
  font-size: 0.8rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  opacity: 0.85;
}

.cat-filter-select {
  width: 100%;
  min-height: 2.2rem;
  max-width: 100%;
}

.cat-filters-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  margin: 0.9rem 0 0;
}

.cat-filters-count {
  font-size: 0.9rem;
  opacity: 0.85;
}

.cat-filters-empty {
  margin: 0.7rem 0 0;
  font-weight: 600;
}

/* ---------------------------------------------------------------- *
 * Compare selection
 * ---------------------------------------------------------------- */

.cat-compare-pick {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0 0 0.35rem;
  font-size: 0.85rem;
}

.cat-compare-input {
  /* A 16px target is the minimum that stays comfortably clickable beside the
   * status chips at the top of a card. */
  width: 1rem;
  height: 1rem;
  margin: 0;
}

.cat-compare-label {
  cursor: pointer;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  opacity: 0.85;
}

/* Sticky, not fixed: it comes to rest at the foot of the catalogue instead of
 * covering a card while you read it, and `position: sticky` degrades to a plain
 * block in anything that does not support it. */
.cat-compare-bar {
  position: sticky;
  bottom: 0;
  z-index: 2;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-top: 2rem;
  padding: 0.75rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-elev);
}

.cat-compare-note {
  margin: 0;
  font-size: 0.9rem;
}

/* ---------------------------------------------------------------- *
 * /compare — the table
 * ---------------------------------------------------------------- */

.cmp-note,
.cmp-empty {
  margin: 0.5rem 0 1rem;
}

/* The table is wider than a phone. It scrolls inside its own container so the
 * PAGE never scrolls sideways; the tabindex makes that scroller reachable from
 * the keyboard, which a scrollable region needs to be. */
.cmp-scroll {
  overflow-x: auto;
  max-width: 100%;
}

.cmp-table {
  width: 100%;
  border-collapse: collapse;
}

.cmp-table th,
.cmp-table td {
  padding: 0.55rem 0.75rem;
  border: 1px solid var(--border);
  text-align: left;
  vertical-align: top;
}

.cmp-table thead th {
  font-size: 1rem;
}

/* The row label column is the reading spine of the table: it stays put while
 * the programme columns scroll under it. */
.cmp-table tbody th {
  position: sticky;
  left: 0;
  min-width: 9rem;
  background: var(--bg-elev);
  font-weight: 600;
}

.cmp-table tbody tr:nth-child(odd) td {
  background: var(--bg-elev);
}

.cmp-col-link {
  font-weight: 700;
}

.cmp-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.cmp-apply {
  display: block;
  margin-top: 0.45rem;
}
