/* The published replays: the browsable index (replays/index) and a run's own page (replays/show).
   Two things here are not the components': the index rows, which a Stimulus controller reorders
   and a second one arms and unloads the screencasts of, and the two-column walkthrough on the show
   page, whose columns are a reading of one run against another and whose source order is the
   collapsed layout's. */
.p-replays {
  display: flex;
  flex-direction: column;
  gap: var(--space-xl);
}

.p-replays__frontmatter {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  margin-block-start: var(--space-xl);
  padding-block: var(--space-lg);
  border-block: var(--bw) dashed var(--line-strong);
}

.p-replays__title {
  color: var(--text-bright);
  font-size: var(--text-3xl);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  letter-spacing: 0;
}

/* The negative top margin takes back the frontmatter's gap, so the stored title reads as a second
   line of the run's title rather than as the first line of the block under it, which is the step
   the index card makes too. */
.p-replays__subtitle {
  margin-block-start: calc(var(--space-sm) * -1 + var(--space-2xs));
  max-width: var(--measure-wide);
  color: var(--text-muted);
  font-size: var(--text-lg);
  line-height: var(--lh-tight);
}

.p-replays__lede,
.p-replays__tagline,
.p-replays__meta,
.p-replays__backlink {
  color: var(--text-muted);
  font-size: var(--text-sm);
}

.p-replays__tagline {
  max-width: var(--measure-wide);
  color: var(--text);
  font-size: var(--text-lg);
  line-height: var(--lh-copy);
}

.p-replays__backlink { width: fit-content; }
.p-replays__backlink::before { content: "◂ "; color: var(--accent); }

.p-replays__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-xs);
}

/* The bar and the list are one block because replay_sort_controller.js is mounted on it and needs
   both inside its scope. */
.p-replays__browser {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

/* One button per measure a card already shows. The controller toggles is-active on the pressed key
   and writes the arrow's glyph into the span below, which is why that span holds a width open
   while it is empty: without it every button shifts as the arrow moves between them. */
.p-replays__sortbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2xs) var(--space-xs);
}

.p-replays__sort-label {
  margin-inline-end: var(--space-2xs);
  color: var(--text-dim);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
}

.p-replays__sort-button {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3xs);
  padding: var(--space-2xs) var(--space-sm);
  border: var(--bw) solid var(--line);
  background: var(--surface-raised);
  color: var(--text-muted);
  font: inherit;
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  cursor: pointer;
  transition: border-color 0.2s ease, color 0.2s ease;
}

.p-replays__sort-button:hover,
.p-replays__sort-button:focus-visible {
  border-color: var(--accent);
  color: var(--text-bright);
}

.p-replays__sort-button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.p-replays__sort-button.is-active {
  border-color: var(--accent);
  color: var(--accent);
}

.p-replays__sort-arrow {
  min-width: 0.75em;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

/* A single-column grid rather than a flex column, which would leave each row's own grid collapsed
   to its content width instead of filling the body. The controller reorders these <li> rows in
   place on every sort, so nothing here may key off a row's position: a rule counting rows would
   restripe the list under the reader. */
.p-replays__list {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-lg);
  width: 100%;
  max-width: none; /* 04-elements caps a list at the reading measure; this one is the page */
  margin: 0;
  padding: 0;
  list-style: none;
}

/* A row is the run's card beside its screencast, two thirds to one. */
.p-replays__item {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-lg);
  width: 100%;
  min-width: 0;
}

.p-replays__card {
  border: var(--bw) solid var(--line);
  background: var(--surface-raised);
  overflow: hidden;
  transition: border-color 0.2s ease;
}

.p-replays__card:hover,
.p-replays__card:focus-within {
  border-color: var(--accent);
}

/* The chrome strip is in normal flow above the clip, so the 16/9 belongs to the video alone and
   the media block stands that much taller than the ratio. align-self keeps it that height instead
   of stretching to the card beside it. */
.p-replays__card-media {
  position: relative;
  display: flex;
  flex-direction: column;
  align-self: start;
  border: var(--bw) solid var(--line);
  background: var(--surface-sunken);
  overflow: hidden;
  cursor: zoom-in;
  text-decoration: none;
  transition: border-color 0.2s ease;
}

.p-replays__card-media:hover {
  border-color: var(--accent);
}

/* The card is first in the source and stays the reading order; only the visual order changes, so
   the screencast leads a stacked row and gives the card back the left column once there are two.
   A row that reordered its markup instead would announce the clip before the run it belongs to. */
.p-replays__card { order: 2; }
.p-replays__card-media { order: 1; }

@media (min-width: 52rem) {
  .p-replays__item { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
  .p-replays__card { order: 1; }
  .p-replays__card-media { order: 2; }
}

.p-replays__card-media:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.p-replays__card-chrome {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  padding: var(--space-2xs) var(--space-md);
  background: color-mix(in oklab, var(--panel) 82%, transparent);
  border-block-end: var(--bw) solid var(--line);
  color: var(--text-muted);
  font-size: var(--text-sm);
}

.p-replays__card-mark { color: var(--accent); }

.p-replays__card-chrome-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.p-replays__card-expand { color: var(--text-dim); }

.p-replays__card-video {
  display: block;
  inline-size: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  background: var(--surface-sunken);
}

.p-replays__card-pending {
  aspect-ratio: 16 / 9;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2xs);
  color: var(--text-dim);
}

.p-replays__card-pending-glyph { font-size: var(--text-2xl); }

.p-replays__card-pending-label {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
}

.p-replays__card-body {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--space-sm);
  padding: var(--space-lg);
}

.p-replays__card-title {
  margin: 0;
  font-size: var(--text-2xl);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
}

.p-replays__card-title-link {
  color: var(--text-bright);
  text-decoration: none;
}

.p-replays__card-title-link:hover,
.p-replays__card-title-link:focus-visible {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-color: var(--accent);
}

/* The stored title, under the run name it no longer supplies. Its negative top margin takes back
   the card's gap so it reads as a second line of the heading rather than the start of the tagline
   below, the same step the show page's own subtitle makes. */
.p-replays__card-subtitle {
  margin: 0;
  margin-block-start: calc(var(--space-sm) * -1 + var(--space-2xs));
  color: var(--text-muted);
  line-height: var(--lh-tight);
}

.p-replays__card-tagline {
  margin: 0;
  margin-block-end: auto;
  color: var(--text);
  font-size: var(--text-lg);
  line-height: var(--lh-copy);
}

/* The authored feature and build summaries, in a label column beside their prose. Whichever block
   is last before the meta line carries the auto end margin that pushes that line to the foot of
   the card, which is why the summaries take it over from the tagline and the tagline gives it up
   in the rule below. */
.p-replays__card-summaries {
  display: grid;
  grid-template-columns: max-content 1fr;
  column-gap: var(--space-sm);
  row-gap: var(--space-xs);
  margin: 0;
  margin-block-end: auto;
}

.p-replays__card-summary-label {
  color: var(--text);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  line-height: var(--lh-copy);
  text-transform: uppercase;
}

.p-replays__card-summary {
  margin: 0;
  color: var(--text-dim);
  line-height: var(--lh-copy);
}

.p-replays__card-tagline:has(+ .p-replays__card-summaries) {
  margin-block-end: var(--space-xs);
}

.p-replays__card-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-sm);
  margin: 0;
  margin-block-start: var(--space-sm);
  color: var(--text);
  font-size: var(--text-sm);
}

/* The published-corpus totals under the index's lede: one wrapping row of measures, separated by
   space rather than punctuation so a wrapped line does not start on a stray comma. */
.p-replays__intro-stats {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs) var(--space-lg);
  margin: 0;
  max-width: var(--measure-wide);
  color: var(--text-dim);
  line-height: var(--lh-copy);
}

.p-replays__intro-figure {
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}


/* The run's measured shape on one line above the card title. ReplaysHelper marks a peak context
   under its light-run threshold is-good, so the accent below is the tone a figure starts from
   rather than the one every figure takes. */
.p-replays__card-eyebrow {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs) var(--space-md);
  margin: 0;
  color: var(--text-dim);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
}

.p-replays__card-eyebrow-value {
  color: var(--accent);
  font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
}

.p-replays__card-eyebrow-stat.is-good .p-replays__card-eyebrow-value { color: var(--good); }

/* The duration keeps its lowercase h/m/s units against the eyebrow's uppercasing. */
.p-replays__card-eyebrow-stat--exact { text-transform: none; }

.p-replays__media,
.p-replays__description,
.p-replays__prose {
  max-width: var(--measure-wide);
}

/* The intro above the walkthrough is read at the size a milestone's feature paragraph takes, so
   the page opens at the size its largest task is written at. */
.p-replays__description {
  max-width: var(--measure);
  font-size: var(--text-xl);
}

.p-replays__prose-summary {
  color: var(--text-bright);
  font-weight: var(--fw-bold);
}

/* Two parallel readings of one run, a row per task of its decomposition. replays/_prose_grid emits
   a row's feature and build cells together for this: collapsed to one column the reader gets each
   task as a pair rather than the whole feature article followed by the whole build one. */
.p-replays__prose--grid {
  max-width: none; /* two columns are wider than the single-column reading measure */
}

.p-replays__grid {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xl);
}

/* The column headings live in the run-level row and are emitted interleaved with their cells —
   feature head, feature cell, build head, build cell — so the collapsed column keeps each heading
   next to what it heads. Restoring the two columns therefore means placing all four by hand,
   which the wide breakpoint below does. */
.p-replays__grid-colhead {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: var(--space-2xs);
  padding-bottom: var(--space-xs);
  border-bottom: var(--bw) solid var(--line);
}

.p-replays__grid-note {
  margin: 0;
  color: var(--text-dim);
  font-size: var(--text-sm);
}

.p-replays__grid-col {
  margin: 0;
  color: var(--text-dim);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
}

/* A column head is an h2 inside c-prose, so this is scoped to beat that component's heading margin
   and keep the head against the pre-header above it. */
.c-prose .p-replays__grid-col {
  margin-top: 0;
}

.p-replays__grid-row {
  display: grid;
  grid-template-columns: 1fr;
  /* The row gap is what separates label, feature and build once the row is one column; the wider
     column gap only bites in the two-column layout. */
  gap: var(--space-lg) var(--space-xl);
  align-items: start;
}

.p-replays__grid-label {
  margin: 0;
  color: var(--text-bright);
}

.p-replays__grid-header {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: var(--space-xs);
}

/* The label over a section: the "Milestone N" counter over each milestone heading, and the
   walkthrough's own pre-header over the run-level row. */
.p-replays__grid-eyebrow {
  margin: 0;
  color: var(--accent);
  font-size: var(--text-xs);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
}

/* Its top margin adds to the page-section gap so the space above the pre-header matches the space
   between the overview cells and the first milestone's rule, which is a grid gap plus a
   milestone's own top margin. */
.p-replays__grid-eyebrow--replay {
  margin-block-start: var(--space-xl);
}

/* Scoped under .c-prose to beat that component's h3 margin, a task heading being spaced by its row
   rather than by itself. Milestone and task headings both read bright, one size apart, so the
   hierarchy is carried by scale rather than by colour. */
.c-prose .p-replays__grid-label--milestone {
  margin-top: 0;
  color: var(--text-bright);
  font-size: var(--text-2xl);
  line-height: var(--lh-tight);
}

.p-replays__grid-label--sprint {
  color: var(--text-bright);
  font-size: var(--text-xl);
  line-height: var(--lh-tight);
}

/* A milestone is told from the tasks under it by a rule and the space above it rather than by
   indentation, so every task of the walkthrough starts on the same left edge however deep the
   decomposition runs. */
.p-replays__grid-row--milestone {
  margin-top: var(--space-lg);
  padding-top: var(--space-xl);
  border-top: var(--bw) solid var(--line-strong);
}

.p-replays__grid-cell {
  min-width: 0;
}

/* c-prose spaces its own direct children, and a cell's paragraphs are three levels below it, so
   the rhythm between them is set here or they run together. */
.p-replays__grid-cell > p {
  margin: 0;
}

.p-replays__grid-cell > p + p {
  margin-top: var(--space-md);
}

/* The two readings are unequal at every width: feature is the body, a step larger than base, and
   build is an aside to it, a step smaller and dimmer behind a rule feature never carries. Side by
   side the type is what says which is which; stacked, it is all that does. */
.p-replays__grid-cell--feature {
  font-size: var(--text-lg);
}

.p-replays__grid-cell--build {
  border-inline-start: var(--bw) solid var(--line-strong);
  padding-inline-start: var(--space-md);
  color: var(--text-muted);
  font-size: var(--text-sm);
}

/* A milestone opts out of the columns, which are for tasks and the run-level row: its feature
   paragraph runs as one lede a step larger again, capped to the reading measure since nothing
   sits beside it, with the build note stacked under it. */
.p-replays__grid-row--milestone .p-replays__grid-cell--feature {
  max-width: var(--measure);
  font-size: var(--text-xl);
}

.p-replays__grid-row--milestone .p-replays__grid-cell--build {
  max-width: var(--measure);
}

@media (min-width: 52rem) {
  /* The feature column is the wider of the two, so the layout says which reading leads as well as
     the type does. */
  .p-replays__grid-row {
    grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
  }

  /* The run-level row's four children are interleaved head-then-cell in the source, so each is
     placed by hand to put both heads on the top row with their own cell beneath. */
  .p-replays__grid-row--replay .p-replays__grid-colhead--feature { grid-area: 1 / 1; }
  .p-replays__grid-row--replay .p-replays__grid-cell--feature { grid-area: 2 / 1; }
  .p-replays__grid-row--replay .p-replays__grid-colhead--build { grid-area: 1 / 2; }
  .p-replays__grid-row--replay .p-replays__grid-cell--build { grid-area: 2 / 2; }

  /* A milestone row keeps its single column here, and its label and header span whatever the
     task rows are divided into. */
  .p-replays__grid-row--milestone {
    grid-template-columns: 1fr;
  }

  .p-replays__grid-label {
    grid-column: 1 / -1;
  }

  .p-replays__grid-header {
    grid-column: 1 / -1;
  }
}
