/* admin.css — layers on shop.css, the same way login.css does. Only the roster
   table is new; the shell, toast and .loading state are all shop.css's.

   No custom properties here: shop.css hard-codes its palette and player.css's
   :root is a per-player theme written at runtime by player.js. /admin has no
   player theme, so it stays on the shop palette. */

/* The Players/Memories switch. Both sections stay behind the same
   /bot/admin/players access gate (see admin.html), so this only ever toggles
   which of the two already-rendered sections is visible — it makes no
   request of its own. */
.admin-tabs {
  display: flex;
  gap: 8px;
  margin-bottom: 18px;
}

/* Two-class selector, not shop.css's bare `.hidden` — `.admin-tabs` above
   already sets its own `display`, so a single-class `.hidden` would tie with
   it on specificity and could lose depending on stylesheet order (the bug
   player.css documents at `.nav-link.hidden`). The compound selector always
   wins regardless of load order. */
.admin-tabs.hidden { display: none; }

.admin-tab {
  font: inherit;
  font-weight: 600;
  color: rgba(234, 246, 255, 0.65);
  cursor: pointer;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 10px;
  padding: 9px 18px;
  transition: background 0.2s ease, color 0.2s ease;
}

.admin-tab:hover { background: rgba(255, 255, 255, 0.12); }

.admin-tab.is-active {
  color: #0f2027;
  background: linear-gradient(90deg, #74ebd5, #9face6);
  border-color: transparent;
}

.admin-toolbar {
  display: flex;
  gap: 12px;
  margin-bottom: 18px;
}

.admin-search {
  flex: 1;
  min-width: 0;
  font: inherit;
  color: #eaf6ff;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 10px;
  padding: 11px 14px;
}

.admin-search::placeholder { color: rgba(234, 246, 255, 0.45); }

.admin-search:focus {
  outline: none;
  border-color: rgba(116, 235, 213, 0.6);
  background: rgba(255, 255, 255, 0.12);
}

.admin-refresh {
  font: inherit;
  font-weight: 600;
  color: #eaf6ff;
  cursor: pointer;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 10px;
  padding: 11px 20px;
  transition: background 0.2s ease;
}

.admin-refresh:hover:not(:disabled) { background: rgba(255, 255, 255, 0.18); }
.admin-refresh:disabled { opacity: 0.55; cursor: default; }

/* A grid rather than a <table>, so the row can collapse to two lines on a phone
   without the usual table-reflow tricks. */
.admin-table {
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 14px;
  overflow: hidden;
}

.admin-row {
  display: grid;
  grid-template-columns: 1fr 150px 92px 74px;
  align-items: center;
  gap: 14px;
  padding: 13px 18px;
  border-top: 1px solid rgba(255, 255, 255, 0.09);
}

/* Super Admin only — see isSuperAdmin in module/adminData.js. A fifth
   column, added only when the row set actually carries it (state.isSuperAdmin
   in admin.js), rather than always reserving the space for a column a plain
   Admin's table never has. */
.admin-row.has-password {
  grid-template-columns: 1fr 150px 150px 92px 74px;
}

.admin-row:first-child { border-top: none; }
.admin-row:hover { background: rgba(255, 255, 255, 0.04); }

.admin-head {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(234, 246, 255, 0.55);
  background: rgba(255, 255, 255, 0.05);
}

.admin-head:hover { background: rgba(255, 255, 255, 0.05); }

/* min-width: 0 so a long nickname ellipsises instead of widening the column. */
.admin-who { min-width: 0; }

.admin-name {
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.admin-name a { color: inherit; text-decoration: none; }
.admin-name a:hover { text-decoration: underline; }

.admin-handle {
  font-size: 0.82rem;
  color: rgba(234, 246, 255, 0.5);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.admin-role {
  display: inline-block;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  border-radius: 999px;
  padding: 4px 11px;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.18);
}

.admin-role-admin {
  color: #0f2027;
  background: linear-gradient(90deg, #74ebd5, #9face6);
  border-color: transparent;
}

/* A warmer gradient than plain Admin's cool one — Super Admin is the same
   badge shape, just visibly a step up rather than indistinguishable from it. */
.admin-role-super {
  color: #2a1400;
  background: linear-gradient(90deg, #ffb347, #ff7a7a);
  border-color: transparent;
}

/* Plaintext, monospace so similar-looking characters (l/1, O/0) are actually
   distinguishable — see module/auth.js for why the column holds plaintext
   at all. Only ever rendered for a Super Admin (admin.js checks
   state.isSuperAdmin before adding .has-password to the table), which is also
   the only case the server includes this field in the response at all — see
   includePasswords in module/adminData.js's listPlayers. */
.admin-password {
  font-family: ui-monospace, 'SFMono-Regular', Consolas, monospace;
  font-size: 0.82rem;
  color: rgba(234, 246, 255, 0.75);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.admin-toggle {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  cursor: pointer;
  user-select: none;
  font-size: 0.85rem;
  color: rgba(234, 246, 255, 0.6);
}

.admin-toggle input {
  width: 18px;
  height: 18px;
  cursor: pointer;
  accent-color: #74ebd5;
  flex: none;
}

/* The in-flight state. Pointer events stay on the row so a second click can't
   race the first; the checkbox itself is disabled in JS. */
.admin-row.saving { opacity: 0.55; }
.admin-toggle input:disabled { cursor: default; }

/* Rename — the Edit button, and the form that replaces .admin-name in place.

   .admin-edit declares no `display`, deliberately. admin.js hides it with
   shop.css's `.hidden` while the editor is open, and a single-class `display`
   here would tie that rule on specificity and win on load order (admin.css
   comes second), leaving a "hidden" button on screen — the bug player.css
   documents. A button is inline-block anyway. */
.admin-edit {
  font: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  color: #eaf6ff;
  cursor: pointer;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 8px;
  padding: 6px 13px;
  transition: background 0.2s ease;
}

.admin-edit:hover:not(:disabled) { background: rgba(255, 255, 255, 0.18); }
.admin-edit:disabled { opacity: 0.55; cursor: default; }

/* Wraps, because the .admin-who column is 1fr and gets narrow well before the
   620px breakpoint — the buttons drop under the field rather than squeezing it
   to nothing. */
.admin-rename {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 7px;
  margin-bottom: 4px;
}

.admin-rename-input {
  flex: 1;
  /* 8em, not 0: below about that the field can't show a nickname while it is
     being typed, and there is a whole row of width to wrap into instead. */
  min-width: 8em;
  font: inherit;
  font-size: 0.92rem;
  font-weight: 600;
  color: #eaf6ff;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(116, 235, 213, 0.5);
  border-radius: 8px;
  padding: 6px 10px;
}

.admin-rename-input::placeholder { color: rgba(234, 246, 255, 0.4); font-weight: 400; }

.admin-rename-input:focus {
  outline: none;
  border-color: rgba(116, 235, 213, 0.85);
  background: rgba(255, 255, 255, 0.14);
}

.admin-rename button {
  font: inherit;
  font-size: 0.8rem;
  font-weight: 700;
  cursor: pointer;
  border-radius: 8px;
  padding: 6px 12px;
  flex: none;
  transition: filter 0.2s ease, background 0.2s ease;
}

.admin-rename button:disabled { opacity: 0.55; cursor: default; }

.admin-rename-save {
  color: #0f2027;
  background: linear-gradient(90deg, #74ebd5, #9face6);
  border: 1px solid transparent;
}

.admin-rename-save:hover:not(:disabled) { filter: brightness(1.08); }

.admin-rename-cancel {
  color: #eaf6ff;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.2);
}

.admin-rename-cancel:hover:not(:disabled) { background: rgba(255, 255, 255, 0.16); }

@media (max-width: 620px) {
  .admin-row {
    grid-template-columns: 1fr 92px;
    gap: 8px 14px;
  }

  /* .admin-row.has-password otherwise keeps winning here — same specificity
     (two classes) as the desktop rule above it, so the cascade alone
     wouldn't collapse a Super Admin's table back to two columns on a phone
     without this override. */
  .admin-row.has-password {
    grid-template-columns: 1fr 92px;
  }

  /* Role drops under the name rather than out of the layout — it is the only
     way to see who else is an admin. */
  .admin-role-cell {
    grid-column: 1;
    grid-row: 2;
  }

  /* Password gets its own third row rather than crowding onto the role's —
     a monospace password beside a role badge would either truncate one of
     them or blow out the row's height fighting for the same line. */
  .admin-password-cell {
    grid-column: 1;
    grid-row: 3;
  }

  /* Active and Edit stack in the right-hand column instead of the toggle
     spanning both rows, which is what makes room for the button without taking
     a third column off the name. */
  .admin-toggle-cell {
    grid-column: 2;
    grid-row: 1;
  }

  .admin-edit-cell {
    grid-column: 2;
    grid-row: 2;
  }

  /* Both head labels go rather than moving: with the cells they name stacked
     into one column there is no row left to head. */
  .admin-head .admin-role-cell,
  .admin-head .admin-password-cell,
  .admin-head .admin-edit-cell { display: none; }
}

/* Memories tab — upload form and the grid of what's already on disk. */

.memory-upload {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 10px;
}

.memory-file-label {
  display: inline-flex;
  align-items: center;
  min-width: 0;
  max-width: 220px;
  font: inherit;
  font-weight: 600;
  color: #eaf6ff;
  cursor: pointer;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 10px;
  padding: 11px 16px;
  transition: background 0.2s ease;
}

.memory-file-label:hover { background: rgba(255, 255, 255, 0.18); }

.memory-file-label span {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.memory-upload .admin-search { flex: 1; min-width: 200px; }

.memory-upload .admin-refresh { flex: none; }

/* .admin-table has fixed vertical padding, but a file input's chosen-name text
   still shows through the label's own padding, so no extra state is needed
   here beyond swapping the span's textContent (see admin.js). */

.memory-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 14px;
}

.memory-card {
  position: relative;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 14px;
  overflow: hidden;
}

.memory-thumb {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  background: rgba(255, 255, 255, 0.04);
}

.memory-caption {
  padding: 8px 10px;
  font-size: 0.8rem;
  color: rgba(234, 246, 255, 0.75);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.memory-delete {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.95rem;
  line-height: 1;
  color: #ffd7d7;
  cursor: pointer;
  background: rgba(20, 8, 8, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 50%;
  transition: background 0.2s ease;
}

.memory-delete:hover:not(:disabled) { background: rgba(255, 90, 90, 0.4); }
.memory-delete:disabled { opacity: 0.55; cursor: default; }

.memory-card.saving { opacity: 0.55; pointer-events: none; }

@media (max-width: 480px) {
  .memory-file-label { max-width: none; }
}

/* Posts tab — browse Gameplay/Captures and flag one as a WOW Kill. Reuses
   .admin-tab (the type switch) and .memory-grid (the card layout) rather
   than redeclaring either — see admin.html. */

.admin-post-types {
  display: flex;
  gap: 8px;
  margin-bottom: 16px;
}

.admin-post-card {
  position: relative;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 14px;
  overflow: hidden;
}

.admin-post-thumb {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  background: rgba(255, 255, 255, 0.04);
}

/* Super Admin only — see includeViews in module/postsData.js's
   getAdminPostsPage; admin.js only ever builds this node when the field is
   present on the post at all. Pinned opposite .memory-delete's own
   top-right circle (used here too — see postCard in admin.js) so the two
   never overlap. */
.admin-post-views {
  position: absolute;
  top: 8px;
  left: 8px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 9px;
  font-size: 0.72rem;
  font-weight: 700;
  color: #eaf6ff;
  background: rgba(20, 8, 8, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 999px;
  pointer-events: none;
}

.admin-post-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 8px 10px;
}

.admin-post-name {
  min-width: 0;
  font-size: 0.8rem;
  color: rgba(234, 246, 255, 0.75);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Reuses .admin-toggle's checkbox+label look (the roster's Active switch),
   just without that class's own gap/font sizing tuned for a table row —
   this sits in a narrow card footer instead. */
.admin-post-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: none;
  cursor: pointer;
  user-select: none;
  font-size: 0.74rem;
  font-weight: 700;
  color: rgba(234, 246, 255, 0.6);
}

.admin-post-toggle input {
  width: 16px;
  height: 16px;
  cursor: pointer;
  accent-color: #ff9a3c;
}

.admin-post-card.saving { opacity: 0.55; pointer-events: none; }

/* No `display` of its own, deliberately — admin.js toggles shop.css's bare
   `.hidden` on this button, and a single-class `display` here would tie with
   it on specificity and could win on load order (admin.css loads after
   shop.css), leaving a "hidden" button on screen — the bug player.css
   documents at `.nav-link.hidden`. `margin-top` alone is enough; a button
   needs no help left-aligning under the grid like the other admin buttons. */
.admin-load-more { margin-top: 18px; }
