.player-list,
.match-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.player-item,
.match-item {
  display: flex;
  align-items: center;
  gap: var(--spacing-md);
  padding: 0.75rem var(--spacing-sm);
  border-bottom: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  transition: background var(--transition);
}

.player-item:hover,
.match-item:hover {
  background: var(--color-surface-alt);
}

.player-item:last-child,
.match-item:last-child {
  border-bottom: none;
}

.player-item__name,
.match-item__players {
  font-weight: 550;
  flex: 1;
  min-width: 0;
}

.player-item__avatar {
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
  border: 1px solid var(--color-border);
}

a.player-item__name {
  color: var(--color-text);
  text-decoration: none;
}

a.player-item__name:hover {
  text-decoration: underline;
}

.player-item__meta,
.match-item__meta {
  color: var(--color-muted);
  font-size: var(--font-size-sm);
}

/* The winner keeps the row's full-weight black; the loser drops to a light
   grey so the outcome reads at a glance. */
.match-item__winner {
  color: var(--color-text);
}

.match-item__loser {
  color: var(--color-muted);
  font-weight: 400;
}

/* The scoreline is the one place a monospaced figure helps: 6-4, 3-6, 7-5
   should line up between rows. Chipped so the result stands out from the
   row's metadata. */
.match-item__score {
  color: var(--color-text);
  font-weight: 600;
  font-size: var(--font-size-sm);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  background: var(--color-surface-alt);
  padding: 0.125rem 0.5rem;
  border-radius: var(--radius-sm);
}

/* An account carries more than a row of inline pieces can hold — name, email,
   role, status, sign-up date, who approved it, and up to three buttons — and the
   roster sits in a half-width column. So it is a grid, not a flex line:

     identity ............ badges
     signed up · approved  buttons

   The two text columns are minmax(0, …) so their children can truncate; without
   that they would refuse to shrink and push the badges and buttons out of the
   row, which is what made the name collide with everything else. */
.user-item {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    'identity tags'
    'facts actions';
  align-items: center;
  gap: var(--spacing-xs) var(--spacing-md);
  padding: 0.75rem var(--spacing-sm);
  border-bottom: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  transition: background var(--transition);
}

.user-item:hover {
  background: var(--color-surface-alt);
}

.user-item:last-child {
  border-bottom: none;
}

.user-item__identity {
  grid-area: identity;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.user-item__name,
.user-item__email,
.user-item__facts {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.user-item__name {
  font-weight: 550;
}

.user-item__email,
.user-item__facts {
  color: var(--color-muted);
  font-size: var(--font-size-sm);
}

.user-item__facts {
  grid-area: facts;
}

/* The signed-in admin's own row, so they don't demote themselves by accident. */
.user-item__you {
  margin-left: var(--spacing-xs);
  padding: 0.0625rem 0.375rem;
  border-radius: 999px;
  background: var(--color-surface-alt);
  border: 1px solid var(--color-border);
  color: var(--color-muted);
  font-size: var(--font-size-xs);
  font-weight: 600;
}

.user-item__tags {
  grid-area: tags;
  display: flex;
  justify-content: flex-end;
  gap: var(--spacing-xs);
}

.user-item__actions {
  grid-area: actions;
  display: flex;
  justify-content: flex-end;
  gap: var(--spacing-xs);
}

.empty {
  color: var(--color-muted);
  padding: var(--spacing-lg) 0;
  text-align: center;
  font-size: var(--font-size-sm);
}

.badge {
  font-size: var(--font-size-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 0.1875rem 0.5rem;
  border-radius: 999px;
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface-alt);
  color: var(--color-muted);
  white-space: nowrap;
}

.badge--approved {
  color: var(--color-success);
  border-color: color-mix(in srgb, var(--color-success) 25%, transparent);
  background: color-mix(in srgb, var(--color-success) 6%, white);
}

.badge--submitted {
  color: var(--color-warning);
  border-color: color-mix(in srgb, var(--color-warning) 25%, transparent);
  background: color-mix(in srgb, var(--color-warning) 7%, white);
}

.badge--cancelled {
  color: var(--color-muted);
  text-decoration: line-through;
}

/* The approvals queue. A result, its buttons, and its whole audit trail will not
   sit on one line: a long pair of names wraps mid-row and shoves everything else
   into a block nobody can read. So it is two lines, not one —

     Ana Silva def. Ben Nguyen   6-4, 6-3      [Approve]
     SUBMITTED  5 Jun 2026 · Court 1 · submitted by Ada on 2 Jun 2026

   The headline column is minmax(0, …) so the names can wrap inside their own
   half of the row without pushing the buttons off the end of it. */
.match-item--queue {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    'headline actions'
    'details details';
  align-items: center;
  gap: var(--spacing-xs) var(--spacing-md);
}

.match-item__headline {
  grid-area: headline;
  display: flex;
  align-items: center;
  gap: var(--spacing-sm);
  min-width: 0;
}

/* The score keeps its own width; the names take the rest and wrap if they must. */
.match-item--queue .match-item__players {
  flex: 1;
  min-width: 0;
}

.match-item__actions {
  grid-area: actions;
  display: flex;
  gap: var(--spacing-xs);
  flex-shrink: 0;
}

.match-item__details {
  grid-area: details;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--spacing-xs) var(--spacing-sm);
  min-width: 0;
}

/* In a narrow column — the ranking page's sidebar — the pieces of a match
   squeeze the names down to one word per line. Stack them instead. */
.match-list--stacked .match-item {
  flex-wrap: wrap;
  gap: var(--spacing-xs) var(--spacing-sm);
}

.match-list--stacked .match-item__players {
  flex-basis: 100%;
}

.match-list--stacked .match-item__meta {
  margin-left: auto;
}

@media (max-width: 768px) {
  /* A row of five inline pieces doesn't fit at 360px — stack them, with the
     buttons on their own line. */
  .player-item,
  .match-item {
    flex-wrap: wrap;
    gap: var(--spacing-xs) var(--spacing-sm);
    padding: var(--spacing-md) var(--spacing-sm);
  }

  .player-item__name,
  .match-item__players {
    flex-basis: 100%;
  }

  /* The queue row is already a grid; at this width its three parts each get a
     line of their own, and the score stays beside the names rather than being
     bumped onto its own row by the flex-basis rule above. */
  .match-item--queue {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      'headline'
      'details'
      'actions';
  }

  .match-item--queue .match-item__players {
    flex-basis: auto;
  }

  .match-item__actions {
    flex-wrap: wrap;
  }

  /* One column: the buttons need the full width to themselves at this size. */
  .user-item {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      'identity'
      'tags'
      'facts'
      'actions';
    padding: var(--spacing-md) var(--spacing-sm);
  }

  .user-item__tags,
  .user-item__actions {
    justify-content: flex-start;
    flex-wrap: wrap;
  }
}
