/* ==========================================================================
   LIVE RANKINGS
   Self-contained page styles — tokens.css variables only, no new colors.
   Some rules (.tool-header, .pool-table, .pos-filter-btn, .pos-chip,
   .panel) intentionally mirror draft-simulator.css's component look so
   this tool-type page feels consistent with the rest of the site, but
   each page's CSS file stays independent per the project's convention.
   ========================================================================== */

.tool-header {
  padding: var(--space-12) 0 var(--space-8);
  border-bottom: var(--border-hair);
}
.tool-header h1 { font-size: var(--text-3xl); margin-top: var(--space-3); }
.tool-header p { color: var(--text-400); max-width: 60ch; margin-top: var(--space-3); }

/* ---- View tabs: Overall Rankings vs. This Week's Ratings ----
   Sits above the position tabs -- a bigger, more prominent segmented
   control since it's the bigger decision (which sort/question), with
   the position tabs underneath narrowing within whichever is picked. */
.ranking-view-tabs {
  display: inline-flex;
  gap: var(--space-1);
  padding: var(--space-1);
  margin-top: var(--space-8);
  background: var(--ink-900);
  border: var(--border-hair);
  border-radius: var(--radius-md);
}
.view-tab-btn {
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: 600;
  padding: 0.6rem 1.1rem;
  border-radius: calc(var(--radius-md) - 4px);
  border: none;
  background: transparent;
  color: var(--text-400);
  cursor: pointer;
  transition: background var(--dur-fast), color var(--dur-fast);
}
.view-tab-btn:hover { color: var(--text-100); }
.view-tab-btn.active { background: var(--lime-500); color: var(--ink-950); }
@media (max-width: 480px) {
  .ranking-view-tabs { display: flex; }
  .view-tab-btn { flex: 1; text-align: center; padding: 0.6rem 0.5rem; }
}

/* ---- Toolbar: position tabs + live meta ---- */
.rankings-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-4);
  padding: var(--space-8) 0 var(--space-4);
}
.rankings-tabs { display: flex; gap: var(--space-2); flex-wrap: wrap; }

.pos-filter-btn {
  font-family: var(--font-data);
  font-size: var(--text-xs);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 0.5rem 1rem;
  border-radius: 999px;
  border: 1px solid var(--ink-600);
  background: transparent;
  color: var(--text-400);
  cursor: pointer;
  transition: border-color var(--dur-fast), color var(--dur-fast), background var(--dur-fast);
}
.pos-filter-btn:hover { border-color: var(--lime-500); color: var(--text-100); }
.pos-filter-btn.active { background: var(--lime-500); border-color: var(--lime-500); color: var(--ink-950); }

.rankings-meta { display: flex; align-items: center; gap: var(--space-3); }
.rankings-timestamp {
  font-family: var(--font-data);
  font-size: var(--text-xs);
  color: var(--text-600);
  letter-spacing: 0.04em;
}

/* ---- Panel + status states (loading / error / empty) ---- */
.panel {
  background: var(--ink-900);
  border: var(--border-hair);
  border-radius: var(--radius-lg);
  overflow: hidden;
  margin-bottom: var(--space-16);
}
.rankings-status { padding: var(--space-16) var(--space-6); text-align: center; }
.rankings-status .eyebrow { display: block; margin-bottom: var(--space-3); }
.rankings-status p { color: var(--text-300); max-width: 50ch; margin: 0 auto; }
.rankings-error .btn { margin-top: var(--space-6); }
.empty-cell { padding: var(--space-6); color: var(--text-600); text-align: center; }

.rankings-partial-warning {
  margin: var(--space-4) var(--space-5) 0;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--grade-d);
  border-radius: var(--radius-sm);
  background: var(--ink-800);
  color: var(--text-300);
  font-size: var(--text-sm);
}

/* General informational banner on the weekly tab -- currently used for
   the "these players have no posted Vegas line yet" note (see
   noLineNotice in renderBody(), live-rankings.js). Same shape as
   .rankings-partial-warning but neutral (ink border, not the
   yellow/orange grade-d) since this isn't a data failure, just an honest
   "here's a detail worth knowing" note. */
.rankings-info-notice {
  margin: var(--space-4) var(--space-5) 0;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--ink-600);
  border-radius: var(--radius-sm);
  background: var(--ink-800);
  color: var(--text-400);
  font-size: var(--text-sm);
}

/* ---- Results table ----
   No vertical max-height/scroll here on purpose — this section is meant
   to show every player returned (60+ for a full position, 100s for
   "All"), not a scrollable slice of them. Only horizontal scroll stays,
   as a safety net for narrow viewports.
   NOT sticky on purpose: `position: sticky` on these `th`s was tried
   (stuck at top:72px, just below the site nav) but turned out to be a
   real, reproducible broken render in this exact setup — confirmed live
   that the header would visually paint above the first data row instead
   of above the whole table, consistently, once the real (80+ row) data
   loaded — not just a one-off loading glitch. Disabling `position:
   sticky` alone (nothing else changed) fixed it instantly and every
   time, so it's staying off rather than chasing a flaky rendering bug
   for a nice-to-have. If a sticky header comes back later, re-test
   against the FULL real dataset (not just a handful of rows), since
   that's what exposed the bug. */
.pool-table-wrap { overflow-x: auto; }
table.pool-table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
table.pool-table thead th {
  background: var(--ink-900);
  text-align: left;
  font-family: var(--font-data);
  font-size: var(--text-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-600);
  padding: var(--space-3) var(--space-5);
  border-bottom: var(--border-hair);
}
table.pool-table td {
  padding: var(--space-3) var(--space-5);
  border-bottom: 1px solid var(--ink-800);
  white-space: nowrap;
}
table.pool-table tbody tr:hover { background: var(--ink-800); }
.cell-adp { font-family: var(--font-data); color: var(--text-400); }
.cell-name { font-weight: 600; white-space: normal; display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2); }
.cell-team { font-family: var(--font-data); color: var(--text-400); }

/* ---- Player headshot ----
   Initials circle renders first and always stays in the DOM; the real
   Sleeper photo (see renderAvatar()/headshotUrl() in live-rankings.js) is
   layered on top and removes itself on a 404, so a missing photo (team
   DEF, deep-roster names) just quietly falls back to initials instead of
   a broken-image icon. object-position: top crops in tight on the face
   instead of showing the flat gray studio backdrop Sleeper's photos sit
   on -- closest a plain <img> crop gets to a real cutout without an
   image-processing step. */
.player-avatar {
  position: relative;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  overflow: hidden;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--ink-700);
}
.player-avatar-initials {
  font-family: var(--font-data);
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--text-400);
}
.player-avatar-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
}

/* ---- Player rating chip ----
   Weekly tab only (see renderRow() in live-rankings.js). Used to show
   Sleeper's own independent season-long VORP rating here -- dropped
   because that number could (and did) disagree with the Vegas/
   projection points driving this tab's actual order, e.g. ranking
   higher on points while showing a LOWER rating chip right next to it.
   Now a straight 0-10 min-max rescaling of that SAME points value (see
   renderRow()'s ratingOutOf10 math), so it's guaranteed to always move
   with the sort order, never against it -- still labeled "Rating N/10"
   rather than a bare points number since it's still just a friendlier
   read on the same thing, not a second competing ranking. */
.player-name { margin-right: var(--space-2); }
.player-rating-chip {
  display: inline-flex;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  background: var(--lime-500-10);
  border: 1px solid var(--lime-500-35);
  font-family: var(--font-data);
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--lime-500);
  white-space: nowrap;
  margin-right: var(--space-2);
}
/* Opponent -- weekly tab only (see renderRow() in live-rankings.js).
   Plain small text rather than a bordered chip like the rating, so it
   reads as a quiet detail next to the name, not a second badge
   competing with it. */
.player-matchup {
  font-family: var(--font-data);
  font-size: var(--text-xs);
  letter-spacing: 0.03em;
  color: var(--text-600);
  white-space: nowrap;
}

/* Vegas-line-based projection (see vegas-projections.js) -- weekly tab
   only, next to the opponent tag. This IS what the tab sorts by (see
   weeklyPointsFor()/currentRows() in live-rankings.js). Kept teal rather
   than lime: tokens.css reserves teal for a "secondary signal" role, and
   this number comes from a genuinely different source (real sportsbook
   lines) than the site's own 0-10 rating chip above, so it's worth it
   visibly reading as a different KIND of number. */
.player-vegas-chip {
  display: inline-flex;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  background: var(--teal-500-15);
  border: 1px solid var(--teal-500-35);
  font-family: var(--font-data);
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--teal-500);
  white-space: nowrap;
  margin-right: var(--space-2);
}
/* Fallback for when a player has no posted Vegas line yet (see
   weeklyPointsFor() in live-rankings.js) -- WINNR's own real weekly
   projection standing in for Vegas's number, on the same point scale,
   so the sort still makes sense. Deliberately gray/neutral rather than
   teal: same chip POSITION and role as .player-vegas-chip (it's what's
   driving this row's spot in the order), but visibly a different,
   less-certain source -- a viewer should be able to tell at a glance
   which rows are real sportsbook numbers and which are estimates. */
.player-projection-chip {
  display: inline-flex;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  background: var(--ink-800);
  border: 1px dashed var(--ink-600);
  font-family: var(--font-data);
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--text-400);
  white-space: nowrap;
  margin-right: var(--space-2);
}

.pos-chip {
  font-family: var(--font-data);
  font-size: 0.68rem;
  letter-spacing: 0.03em;
  padding: 0.2rem 0.5rem;
  border-radius: 4px;
  background: var(--ink-700);
  color: var(--text-300);
}

/* Injury badges — reuse the site's existing 5-color grade spectrum
   (tokens.css --grade-a..--grade-f) instead of inventing new colors.
   That scale already runs green -> yellow -> orange -> red for letter
   grades elsewhere in WINNR, which maps directly onto Healthy -> Out. */
.injury-badge {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-data);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.04em;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  color: var(--ink-950);
}
.injury-healthy { background: var(--grade-a); }      /* green */
.injury-questionable { background: var(--grade-c); } /* yellow */
.injury-doubtful { background: var(--grade-d); }     /* orange */
.injury-out { background: var(--grade-f); }          /* red */
.injury-unknown { background: var(--ink-700); color: var(--text-300); }

@media (max-width: 720px) {
  .rankings-toolbar { flex-direction: column; align-items: flex-start; }
}
