/**
 * @file
 * Listing grids.
 *
 * The outgoing theme used Isotope + Packery (two 40KB+ scripts) to lay out the
 * event listing, which meant the grid was invisible until JS ran, reflowed on
 * every image load, and could not be keyboard-navigated in visual order.
 * CSS grid does the same job with zero JavaScript and correct source order.
 */

.card-grid {
  display: grid;
  gap: var(--space-m);
  /* 19rem, not 17.5rem: at the narrower value a 1400px page fitted five
     columns, and a 16:9 image in a 250px column is barely legible. */
  grid-template-columns: repeat(auto-fill, minmax(min(19rem, 100%), 1fr));
}

.card-grid--wide {
  grid-template-columns: repeat(auto-fill, minmax(min(22rem, 100%), 1fr));
}

.card-grid--two {
  grid-template-columns: repeat(auto-fit, minmax(min(24rem, 100%), 1fr));
}

/**
 * The event listing: a fixed three-up on a desktop, two-up on a tablet, one-up
 * on a phone.
 *
 * WHY NOT auto-fill
 * -----------------
 * `auto-fill` gives you as many tracks as fit, which on a 1320px content width
 * is four — and on a 1600px screen, five. The cards then shrink until an 825x465
 * image is 240px wide and the title wraps to four lines. A listing of event
 * cards reads better at three deliberate columns than at however many the
 * arithmetic allows, so the column counts are stated rather than derived.
 *
 * `minmax(0, 1fr)` rather than `1fr`: a grid track's default minimum is
 * `auto`, which is the widest unbreakable thing inside it. One long venue name
 * or URL in a card would then push the whole row wider than the page.
 */
.card-grid--listing {
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 40rem) {
  .card-grid--listing {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 64rem) {
  .card-grid--listing {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/**
 * Hub grid — TWO columns on anything but a phone.
 *
 * It was three on a desktop, matching the event listing. With two hubs
 * published that left the pair sitting in two of three tracks, ending two
 * thirds of the way across the page while the newsletter band above them ran to
 * the container's edge — the section read as broken rather than short. Two
 * columns fill the container whatever the count, and hub artwork is 16:9 with
 * type in it, so it wants the width.
 */
.card-grid--hubs {
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 44rem) {
  .card-grid--hubs {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/**
 * Two columns wherever hub cards are listed, whatever the container is called.
 *
 * `.card-grid--hubs` is the class the theme's own hubs template sets, and it is
 * the one to rely on. This is the backstop for the case that turned up on
 * /hubs: a listing rendered through a container this theme did not name — a
 * `.view__content` from the generic views template, or a row wrapper from a
 * style plugin — which then had no column rule at all and fell back to whatever
 * the generic `.card-grid` says, which is three.
 *
 * `:has()` asks the only question that matters — are there hub cards in here —
 * instead of trying to keep a list of every wrapper Views might produce.
 */
:is(.card-grid, .view__content, [data-me-reveal-items]):has(.hub-card) {
  display: grid;
  gap: var(--space-m);
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 44rem) {
  :is(.card-grid, .view__content, [data-me-reveal-items]):has(.hub-card) {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* A row wrapper between the grid and the card must not become a box of its
   own: it passes the track's width down and lets the card fill the height. */
:is(.card-grid, .view__content, [data-me-reveal-items]):has(.hub-card) > .views-row {
  display: flex;
  min-inline-size: 0;
}

:is(.card-grid, .view__content, [data-me-reveal-items]):has(.hub-card) > .views-row > .hub-card {
  flex: 1 1 100%;
  min-inline-size: 0;
}

/**
 * Search results — two ROW cards to a line.
 *
 * Not tiles. A result is read against a question rather than browsed, so the
 * words matter more than the artwork: the row card puts a small picture on the
 * left and the date, title, venue and tags beside it, and two of those fit on a
 * line where two tiles made the page enormously tall for what it said. Below
 * 62rem there is not enough width for two, so it is one.
 *
 * The card markup is identical either way — js/search-results.js adds
 * `.event-card--row` to each card as it places it, and event-card.css already
 * knows that layout.
 */
.card-grid--results {
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-m);
}

@media (min-width: 62rem) {
  .card-grid--results {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* A row card must be able to shrink to its column: a long title or a URL in
   the body would otherwise set the track's width. */
.card-grid--results > * {
  min-inline-size: 0;
}

/**
 * Editorial grid: the first card doubled in size. Kept for anywhere that wants
 * a focal point, but no longer used by the front listing — with a mixed result
 * set the promoted slot landed on whatever sorted first, which on the live site
 * was a dateless, imageless node blown up to four times the size of a real
 * event.
 */
@media (min-width: 64rem) {
  .card-grid--editorial > .card-grid__feature {
    grid-column: span 2;
    grid-row: span 2;
  }
}

/**
 * Row-based listing used on search results and taxonomy pages.
 *
 * Two columns from 62rem up. A row card is wide and short — image on the left,
 * title, date and tags beside it — so a single column of them on a desktop left
 * two thirds of the page empty and made a page of results feel much longer than
 * it is. Two columns fit the container and halve the scrolling; below 62rem
 * there is not enough width for a second row card, so it stays single.
 */
.card-rows {
  display: grid;
  gap: var(--space-s);
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 62rem) {
  .card-rows {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-m) var(--space-m);
  }
}

/* The row card must not be pushed wider than its column by a long title or a
   URL: a grid track's default minimum is the widest unbreakable thing in it. */
.card-rows > * {
  min-inline-size: 0;
}

/* Horizontal scroller for related events on narrow screens. */
.card-rail {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(15rem, 17rem);
  gap: var(--space-m);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding-block-end: var(--space-2xs);
  scrollbar-width: thin;
  scrollbar-color: var(--surface-3) transparent;
}

.card-rail > * {
  scroll-snap-align: start;
}

@media (min-width: 64rem) {
  .card-rail {
    grid-auto-flow: row;
    grid-template-columns: repeat(auto-fill, minmax(min(17rem, 100%), 1fr));
    overflow: visible;
  }
}

/* Hidden by the client-side filter without collapsing the grid. */
/*
 * Paged out: matched, but past the end of the current page.
 *
 * A separate class from `.is-filtered-out` so the two states can be told apart
 * — a card that did not match the filter and a card that simply has not been
 * revealed yet are different facts, and the empty-state rule in
 * empty-state.css depends on only the first of them. If both used one class,
 * a listing whose first twenty were shown would report itself as having
 * nothing to show the moment you pressed "See more" on an empty filter.
 */
.is-paged-out,
.is-filtered-out {
  display: none !important;
}
