/*
 * This is a manifest file that'll be compiled into application.css.
 *
 * With Propshaft, assets are served efficiently without preprocessing steps. You can still include
 * application-wide styles in this file, but keep in mind that CSS precedence will follow the standard
 * cascading order, meaning styles declared later in the document or manifest will override earlier ones,
 * depending on specificity.
 *
 * Consider organizing styles into separate files for maintainability.
 */

:root {
  color-scheme: dark light;
  --bg: #111418;
  --surface: #1a1e24;
  --text: #e8eaed;
  --text-dim: #9aa4b2;
  --accent: #22b573;
  --border: #2a2f37;
  --danger: #ff6b6b;
  --warning: #ffd23f;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  padding-bottom: 4.5rem; /* room for the fixed bottom nav */
}

.app-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 1rem;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
}

.app-header__brand {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-weight: 700;
}

.app-header__crown {
  width: 1.1rem;
  height: 1.1rem;
}

.app-header__account {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.9rem;
  color: var(--text-dim);
  text-decoration: none;
}

.app-header__account strong {
  color: var(--text);
}

.role-badge {
  text-transform: uppercase;
  font-size: 0.7rem;
  letter-spacing: 0.05em;
  padding: 0.15rem 0.4rem;
  border-radius: 0.25rem;
  background: var(--border);
  color: var(--text);
}

.role-badge--admin {
  background: var(--accent);
  color: #fff;
}

.app-main {
  max-width: 40rem;
  margin: 0 auto;
  padding: 1rem;
}

.flash {
  padding: 0.6rem 0.9rem;
  border-radius: 0.4rem;
  margin: 0 0 1rem;
  background: var(--surface);
  border: 1px solid var(--border);
}

.flash--alert {
  border-color: var(--danger);
  color: var(--danger);
}

.flash--warning {
  border-color: var(--warning);
  color: var(--warning);
}

/* Generic transient message (push_notifications_controller's toast()) --
   centered above the fixed bottom nav, fades/rises in and back out. */
.toast {
  position: fixed;
  left: 50%;
  bottom: 5.5rem;
  z-index: 30;
  max-width: calc(100% - 2rem);
  padding: 0.6rem 0.9rem;
  border-radius: 0.4rem;
  background: var(--surface);
  border: 1px solid var(--border);
  font-size: 0.85rem;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
  opacity: 0;
  pointer-events: none;
  transform: translate(-50%, 0.4rem);
  transition: opacity 0.2s ease, transform 0.2s ease;
}

.toast--danger {
  border-color: var(--danger);
  color: var(--danger);
}

.toast--visible {
  opacity: 1;
  transform: translate(-50%, 0);
}

.button,
.link-button {
  display: inline-block;
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: 0.4rem;
  padding: 0.6rem 1rem;
  font-size: 1rem;
  text-decoration: none;
  cursor: pointer;
}

.link-button {
  background: transparent;
  color: var(--text-dim);
  padding: 0;
  font-size: 0.85rem;
  text-decoration: underline;
}

.sign-in {
  min-height: 80vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 1.25rem;
  text-align: center;
}

/* Shared by the sign-in screen and the landing page -- same brand
   lockup (crown + wordmark), each page just sets its own bottom margin. */
.brand-title {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  font-size: 2.25rem;
  font-weight: 700;
  color: var(--accent);
  letter-spacing: -0.02em;
}

/* Sized under the title's own line-height so the crown rides alongside
   the text instead of stretching the header row to fit it. */
.brand-crown {
  width: 2.1rem;
  height: 2.1rem;
  flex-shrink: 0;
}

.sign-in__title {
  margin: 0 0 3rem;
}

/* The one button on the page that's deliberately not .button's solid-accent
   fill (2025 app's card-button treatment) -- a dark bordered pill that
   lifts and picks up the accent color on hover, carrying the real Google
   "G" instead of a plain label. */
.button--google {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  min-width: 12.5rem;
  padding: 0.875rem 1.5rem;
  border: 2px solid var(--border);
  border-radius: 0.75rem;
  background: var(--surface);
  color: var(--text);
  font-size: 1rem;
  font-weight: 500;
  text-decoration: none;
  transition: background-color 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
}

.button--google:hover {
  background: color-mix(in srgb, var(--surface) 100%, white 8%);
  border-color: var(--accent);
  transform: translateY(-1px);
}

.button--google:active {
  transform: translateY(0);
}

.button--google__icon {
  flex-shrink: 0;
}

.marketing {
  margin: 0 auto;
  padding: 3rem 0;
}

.marketing__hero {
  text-align: center;
  margin-bottom: 2.5rem;
}

.marketing__title {
  margin: 0 0 0.5rem;
}

.marketing__tagline {
  color: var(--text-dim);
  font-size: 1.1rem;
  margin: 0;
}

.marketing__section {
  margin-bottom: 2rem;
}

.marketing__section h2 {
  font-size: 1rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-dim);
  margin: 0 0 0.5rem;
}

.marketing__section p {
  line-height: 1.6;
  margin: 0;
}

/* Opening paragraph reads better with more room between lines than the
   rest of the page's tighter copy. Qualified with p -- a bare class here
   would lose the specificity tiebreak to .marketing__section p above,
   regardless of source order (same trap the comment below this warns about). */
.marketing__section p.marketing__lede {
  line-height: 2;
}

/* Landing page's What/How/Why: even vertical rhythm between whatever mix
   of paragraph, diagram, and example board a section holds. */
.marketing__section--intro {
  margin-bottom: 2.75rem;
}

/* Beats .marketing__section p's margin: 0 (same specificity would lose
   the tiebreak to source order otherwise). */
.marketing__section.marketing__section--intro > * + * {
  margin-top: 1.25rem;
}

.marketing__cta {
  text-align: center;
  margin-top: 2.5rem;
}

.marketing__cta .button {
  padding: 0.875rem 2rem;
  font-size: 1.05rem;
  border-radius: 0.75rem;
}

/* The top-of-page CTA -- same green .button, just louder than the
   closing one so it reads as the primary action, not a repeat of it. */
.marketing__cta--top {
  margin-top: 0;
  margin-bottom: 2.75rem;
}

.marketing__cta--top .button {
  padding: 1.1rem 2.75rem;
  font-size: 1.25rem;
  border-radius: 0.85rem;
}

/* Season archives' entry point on the landing page -- a bordered card
   (same language as .marketing__season-card) instead of a small dim
   link, kept last on the page since it's the secondary path. */
.marketing__archive-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 1.5rem;
  padding: 1rem 1.25rem;
  border: 1px solid var(--border);
  border-radius: 0.75rem;
  background: var(--surface);
  color: var(--text);
  text-decoration: none;
  transition: border-color 0.2s ease;
}

.marketing__archive-link:hover {
  border-color: var(--accent);
}

.marketing__archive-link-body {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.marketing__archive-link-title {
  font-weight: 600;
}

.marketing__archive-link-sub {
  color: var(--text-dim);
  font-size: 0.85rem;
}

.marketing__archive-link-arrow {
  color: var(--text-dim);
  font-size: 1.2rem;
  flex-shrink: 0;
}

.marketing--wide {
  max-width: 42rem;
}

.marketing__eyebrow {
  margin: 0 0 1rem;
}

.marketing__eyebrow a {
  color: var(--text-dim);
  font-size: 0.9rem;
  text-decoration: none;
}

.marketing__season-disclaimer {
  color: var(--text-dim);
  font-size: 0.9rem;
  line-height: 1.6;
  margin: 0 0 2rem;
}

.marketing__table-wrap {
  overflow-x: auto;
}

.marketing__table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}

.marketing__table th,
.marketing__table td {
  padding: 0.6rem 0.75rem;
  text-align: left;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

.marketing__table th {
  color: var(--text-dim);
  font-weight: 500;
  text-transform: uppercase;
  font-size: 0.75rem;
  letter-spacing: 0.04em;
}

.marketing__table--standings tr:first-child td {
  color: var(--accent);
  font-weight: 600;
}

/* Truncates the name with an ellipsis instead of forcing the whole
   standings table wider than a phone screen -- Score stays on-screen
   without side-scrolling. */
.marketing__table td.marketing__table-player {
  max-width: 6.5rem;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Rk only ever holds a single digit -- give Player the room instead. */
.marketing__table-rank {
  width: 1.4rem;
  padding-right: 0.35rem;
}

.marketing__net {
  font-variant-numeric: tabular-nums;
}

.marketing__net--top {
  color: var(--accent);
  font-weight: 600;
}

@media (max-width: 30rem) {
  .marketing__table--weekly .marketing__net {
    font-size: 0.8rem;
  }
}

.marketing__swatch {
  display: inline-block;
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 50%;
  margin-right: 0.5rem;
}

/* Season archives index */
.marketing__season-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.marketing__season-card {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 1rem 1.25rem;
  border: 1px solid var(--border);
  border-radius: 0.75rem;
  background: var(--surface);
  text-decoration: none;
  transition: border-color 0.2s ease;
}

.marketing__season-card:hover {
  border-color: var(--accent);
}

.marketing__season-card-year {
  color: var(--text);
  font-weight: 600;
  font-size: 1.1rem;
}

/* Charts (season recap) */
.marketing__section--charts {
  display: flex;
  flex-direction: column;
  gap: 2.5rem;
}

.marketing__figure {
  margin: 0;
}

.marketing__figure-caption {
  color: var(--text-dim);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 0.75rem;
}

.marketing__chart {
  width: 100%;
  height: auto;
  overflow: visible;
}

.marketing__chart-value,
.marketing__chart-tick {
  fill: var(--text-dim);
  font-size: 12px;
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
}

.marketing__chart-value {
  fill: var(--text);
}

.marketing__chart-gridline {
  stroke: var(--border);
  stroke-width: 1;
}

.marketing__chart-leader {
  stroke: var(--text-dim);
  stroke-width: 1;
}

.marketing__table-toggle {
  margin-top: 1rem;
}

.marketing__table-toggle summary {
  color: var(--text-dim);
  font-size: 0.85rem;
  cursor: pointer;
}

.marketing__table-toggle .marketing__table-wrap {
  margin-top: 0.75rem;
}

/* How It Works figures */
.hiw__weight-diagram {
  display: flex;
  gap: 1rem;
  margin-top: 1.25rem;
}

/* Stay side by side even on narrow phones -- a 12rem flex-basis was forcing
   these to wrap to their own rows below ~26rem. Shrinking together instead
   (flex: 1 1 0, min-width: 0) keeps them on one row; max-width caps how
   wide (not tall/narrow) either card can grow to relative to its own
   content height (~8rem), so the pair reads as a rectangle, not a square. */
.hiw__weight-card {
  flex: 1 1 0;
  min-width: 0;
  max-width: 24rem;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  padding: 1rem;
  border: 1px solid var(--border);
  border-radius: 0.75rem;
  background: var(--surface);
}

.hiw__weight-card-title {
  font-weight: 600;
}

.hiw__weight-card-sub {
  color: var(--text-dim);
  font-size: 0.8rem;
}

.hiw__weight-bar {
  display: flex;
  gap: 2px;
  height: 2.5rem;
}

/* Same fill/border/shadow recipe as shared/_chip's tiers (--chip-color /
   --chip-shadow), just stretched into a proportional bar instead of a
   fixed badge -- the weight diagram should read as the same idea as the
   real slot chip, not its own color scheme. */
.hiw__weight-slot {
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid var(--chip-shadow);
  border-radius: 0.25rem;
  background: var(--chip-color);
  color: #14171c;
  font-family: "Courier New", monospace;
  font-weight: 800;
  font-size: 0.9rem;
  letter-spacing: -0.03em;
  box-shadow: 2px 2px 0 var(--chip-shadow), inset 0 -3px 0 rgb(0 0 0 / 0.2);
}

.hiw__weight-slot--full {
  flex: 3;
  --chip-color: #ff2e88;
  --chip-shadow: #c41e68;
}

.hiw__weight-slot--major {
  flex: 2;
  --chip-color: #00d9ff;
  --chip-shadow: #0099b8;
}

.hiw__weight-slot--minor {
  flex: 1;
  --chip-color: #ffb800;
  --chip-shadow: #cc8e00;
}

.hiw__timeline {
  list-style: none;
  margin: 1.5rem 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.75rem;
}

.hiw__timeline-step {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  padding-top: 1.5rem;
  border-top: 2px solid var(--border);
}

.hiw__timeline-dot {
  position: absolute;
  top: -5px;
  left: 0;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
}

.hiw__timeline-label {
  font-weight: 600;
  font-size: 0.9rem;
}

.hiw__timeline-detail {
  color: var(--text-dim);
  font-size: 0.8rem;
  line-height: 1.4;
}

/* The scoring walkthrough's equation -- the "3×" is shared/_chip, the same
   slot badge the real app uses, not a marketing-only lookalike. */
.hiw__equation {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  flex-wrap: wrap;
  padding: 0.65rem;
  border: 1px solid var(--border);
  border-radius: 0.75rem;
  font-size: 1.15rem;
  font-weight: 600;
}

.hiw__equation-op {
  color: var(--text-dim);
  font-weight: 400;
}

.hiw__equation-result {
  color: var(--accent);
}

/* A major + minor pick's equations sharing one frame -- one grid across
   both rows (each .hiw__equation drops to display: contents and donates
   its five cells to it) so chip/×/value/=/result line up column by
   column instead of each row centering on its own. */
.hiw__equation-group {
  display: grid;
  grid-template-columns: repeat(5, auto);
  justify-content: center;
  justify-items: center;
  align-items: center;
  column-gap: 0.75rem;
  row-gap: 0.5rem;
  padding: 0.65rem;
  border: 1px solid var(--border);
  border-radius: 0.75rem;
}

.hiw__equation-group .hiw__equation {
  display: contents;
}

@media (max-width: 30rem) {
  .hiw__timeline {
    grid-template-columns: 1fr 1fr;
  }
}

.bottom-nav {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  background: var(--surface);
  border-top: 1px solid var(--border);
}

/* Installed-to-home-screen only: standalone has no browser chrome to clear
   the home-indicator swipe bar for us, so the nav needs its own bottom
   padding here. Gated to display-mode: standalone so a normal browser tab
   (Safari already keeps content clear of the indicator) is untouched. */
@media (display-mode: standalone) {
  .bottom-nav {
    padding-bottom: env(safe-area-inset-bottom);
  }
}

.bottom-nav__tab {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
  text-align: center;
  padding: 0.6rem 0.25rem;
  color: var(--text-dim);
  text-decoration: none;
}

.bottom-nav__icon {
  width: 1.4rem;
  height: 1.4rem;
}

.bottom-nav__label {
  font-size: 0.65rem;
}

.bottom-nav__tab--active {
  color: var(--accent);
  font-weight: 600;
}

.week-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}

.week-header h1 {
  font-size: 1.25rem;
  margin: 0;
}

.week-header__nav {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  color: var(--accent);
  text-decoration: none;
  font-size: 1.75rem;
  line-height: 1;
}

.week-header__nav--disabled {
  color: var(--text-dim);
  opacity: 0.5;
}

.week-header__window {
  color: var(--text-dim);
  font-size: 0.85rem;
  margin: 0.25rem 0 1.5rem;
  text-align: center;
}

.empty-state {
  color: var(--text-dim);
}

.game-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 0.5rem;
  padding: 0.5rem;
  margin-bottom: 0.75rem;
}

.game-card--voided {
  opacity: 0.6;
}

.game-card__header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}

/* Shared matchup block (shared/_matchup): away team dim over home team
   bright, kickoff stacked icon+day over time on the right. */
.matchup__teams {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.matchup__away,
.matchup__home {
  font-weight: 600;
  font-size: 0.85rem;
}

.matchup__away {
  color: var(--text-dim);
}

.matchup__home {
  color: var(--text);
}

/* Completed-game score prefix (shared/_matchup) -- fixed to 2 digits'
   width regardless of the actual score, so both team names still start
   at the same x position whether it's "7" or "17". */
.matchup__score {
  display: inline-block;
  min-width: 2ch;
  margin-right: 0.5rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* Game card only -- team names sized to match the bet description on a
   pick card (.slot-card__selection). */
.game-card__header .matchup__away,
.game-card__header .matchup__home {
  font-size: 1.05rem;
}

/* Pick cards -- both team names read as the same dim byline, no
   home/away emphasis (that distinction is the game card's job). */
.slot-card__meta .matchup__away,
.slot-card__meta .matchup__home {
  color: var(--text-dim);
}

/* Dim, lightly tracked, but sized to match a pick card's team names
   (.matchup__away/__home's base size) -- same row, same two-line stack,
   no reason for the kickoff half to read smaller. One size everywhere,
   including the game card, rather than scaling up with that header's
   bigger team names. */
.matchup__when {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.1rem;
  color: var(--text-dim);
  font-size: 0.85rem;
  letter-spacing: 0.03em;
  white-space: nowrap;
}

.matchup__day {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
}

/* The icon reads heavier than text at the same size, so it sits a step
   below the day/time text next to it rather than matching it exactly. */
.matchup__day .sport-icon {
  font-size: 0.75rem;
}

.game-card__voided-note {
  color: var(--danger);
  margin: 0;
}

.game-card__grid {
  display: grid;
  grid-template-columns: 1fr repeat(3, minmax(3rem, 1fr));
  align-items: center;
  gap: 0.1rem;
}

.game-card__col-label {
  font-size: 0.65rem;
  letter-spacing: 0.03em;
  color: var(--text-dim);
  text-align: center;
}

.game-card__team {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text-dim);
}

.market-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.1rem;
  width: 100%;
  min-height: 3rem;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 0.4rem;
  padding: 0.3rem 0.2rem;
  color: var(--text);
  font-family: inherit;
  cursor: pointer;
}

.market-btn__price {
  font-size: 0.95rem;
  font-weight: 700;
}

.market-btn__point {
  display: block;
  min-height: 1.1em;
  font-size: 0.75rem;
  color: var(--text-dim);
}

.market-btn--locked {
  opacity: 0.5;
  cursor: default;
}

.market-btn--empty {
  color: var(--text-dim);
}

/* Marks a market as the walkthrough's pick (home/_game's selected_market) --
   full opacity even when also --locked, so it reads as chosen, not dimmed. */
.market-btn.market-btn--selected {
  opacity: 1;
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 18%, var(--bg));
}

.home-header {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 0.75rem;
}

.home-header h1 {
  font-size: 1.25rem;
  margin: 0;
}

/* M10 #9 -- small, out of the way of the board above it. */
.home-footnote {
  margin-top: 1.75rem;
  padding-top: 1rem;
  border-top: 1px solid var(--border);
  color: var(--text-dim);
  font-size: 0.8rem;
  text-align: center;
}

.home-footnote a {
  color: var(--text-dim);
}

/* Vendored Font Awesome glyphs (IconHelper) -- sized/colored like the icon
   font they replaced: a 1em box that fills with the surrounding text color. */
.icon {
  width: 1em;
  height: 1em;
  fill: currentColor;
  flex: none;
  vertical-align: -0.125em;
}

/* Shield (NFL) / football (NCAAF) glyph, sitting in every matchup block's
   kickoff corner and the home sport filter where nothing's picked yet. */
.sport-icon {
  margin-right: 0.3em;
  color: var(--text-dim);
}

/* No text follows it (the sport filter's icon-only NFL/NCAAF buttons) --
   the default right margin above assumes text follows and otherwise pushes
   the glyph off-center in its button. */
.sport-icon--standalone {
  margin-right: 0;
}

/* The pick-config modal -- centered on the page (a bottom sheet was tried
   first; feedback was it should sit in the middle), via a native <dialog>'s
   own inset:0 + margin:auto centering rather than fighting it. */
.sheet {
  position: fixed;
  inset: 0;
  margin: auto;
  width: min(92vw, 26rem);
  max-height: 85vh;
  border: none;
  border-radius: 0.75rem;
  padding: 0;
  background: var(--surface);
  color: var(--text);
}

.sheet::backdrop {
  background: rgb(0 0 0 / 0.5);
}

.sheet__content {
  padding: 1.25rem;
  overflow-y: auto;
}

.sheet__label {
  font-weight: 600;
  margin: 0 0 0.75rem;
}

.sheet fieldset {
  border: none;
  padding: 0;
  margin: 0.75rem 0;
}

.sheet legend {
  font-size: 0.75rem;
  color: var(--text-dim);
  padding: 0;
  margin-bottom: 0.4rem;
}

.sheet__actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 1rem;
  margin-top: 0.75rem;
}

.filter-bar {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 1rem;
  flex-wrap: wrap;
}

.filter-bar__team {
  flex: 1 1 10rem;
  min-width: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 0.4rem;
  padding: 0.5rem 0.6rem;
  color: var(--text);
  /* iOS Safari auto-zooms on focus for any input under 16px, and never
     zooms back out -- keep this at 1rem to avoid that trap. */
  font-size: 1rem;
}

/* A button-group radio: the label itself is the aesthetic control, a plain
   radio sits underneath (opacity: 0, but real size/position) for native
   form semantics and keyboard/Capybara interaction. Shared by the sport
   filter and the pick dialog's reveal choice, so this pattern lives once. */
.toggle-group {
  display: flex;
  gap: 0.4rem;
}

.toggle-btn {
  position: relative;
}

.toggle-btn__input {
  position: absolute;
  opacity: 0;
  inset: 0;
  margin: 0;
  cursor: pointer;
}

.toggle-btn__label {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.3rem;
  padding: 0.4rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: 0.4rem;
  font-size: 0.8rem;
  color: var(--text-dim);
  white-space: nowrap;
}

/* Sport filter only -- its NFL/NCAAF buttons are icon-only, and the icon
   glyph's own line-height doesn't match plain text's, so "All" and the two
   icon buttons came out different heights at the shared padding-driven size
   above. A fixed height fixes that, but it doesn't belong on every
   toggle-group (it made the board's Player/Kickoff sort toggle needlessly
   huge), so it's scoped here instead of on .toggle-btn__label itself. */
.toggle-group--filter .toggle-btn__label {
  height: 2.6rem;
  padding: 0 0.9rem;
  font-size: 0.85rem;
}

/* Outline + text only, no tinted fill -- keeps green meaning one thing in
   the pick dialog (the "Place pick" button, the one solid-green surface)
   instead of also filling every selected pill. */
.toggle-btn__input:checked + .toggle-btn__label {
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
}

/* Reveal choice icons (lock/eye, RevealIconHelper) -- currentColor so they
   pick up the label's own color, dim when unselected and green when
   checked, same as the text beside them. */
.toggle-btn__icon {
  width: 1rem;
  height: 1rem;
  flex: none;
}

.slot-picker {
  display: flex;
  gap: 0.75rem;
  justify-content: center;
}

.slot-picker__option {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
  padding: 0.5rem;
  border-radius: 0.5rem;
  cursor: pointer;
}

/* Hidden but real (opacity, not display:none) -- the chip is the aesthetic
   control; this just keeps native radio semantics/keyboard behavior. */
.slot-picker__input {
  position: absolute;
  opacity: 0;
  inset: 0;
  margin: 0;
  cursor: pointer;
}

/* Selected state: bigger + a deeper drop shadow, same offset-sprite style as
   the resting chip, rather than a ring around it -- a ring sat outside the
   chip's own offset shadow and read as misaligned with it. */
.slot-picker__input:checked ~ .chip {
  transform: translateY(-2px) scale(1.15);
  box-shadow: 5px 7px 0 var(--chip-shadow), inset 0 -4px 0 rgb(0 0 0 / 0.2);
}

.slot-picker__label {
  font-size: 0.8rem;
  /* Room for the checked chip's scale-up above (:checked ~ .chip) to grow
     into without covering the label. */
  padding-top: 0.35rem;
}

/* All-in/major/minor badge (ui.md) -- the multiplier itself is the sprite,
   bold and color-coded per tier, everywhere the slot choice shows up: the
   pick dialog's slot picker, My Picks' slot cards, the board. */
.chip {
  --chip-color: var(--text-dim);
  --chip-shadow: #14171c;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.2rem;
  height: 2.2rem;
  padding: 0 0.35rem;
  background: var(--chip-color);
  color: #14171c;
  font-family: "Courier New", monospace;
  font-weight: 800;
  font-size: 1rem;
  letter-spacing: -0.03em;
  border: 2px solid var(--chip-shadow);
  border-radius: 0.25rem;
  box-shadow: 2px 2px 0 var(--chip-shadow), inset 0 -3px 0 rgb(0 0 0 / 0.2);
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}

/* Fill + a matching darker shadow per tier -- hot pink/cyan/gold reads more
   distinctly at a glance than the previous gold/violet/green, and each
   tier's shadow is a shade of its own fill rather than the flat near-black
   every chip used before. */
.chip--all_in {
  --chip-color: #ff2e88;
  --chip-shadow: #c41e68;
}

.chip--major {
  --chip-color: #00d9ff;
  --chip-shadow: #0099b8;
}

.chip--minor {
  --chip-color: #ffb800;
  --chip-shadow: #cc8e00;
}

/* Leaderboard standings' rank 1-3, full size -- same chip shape as the
   tiers above, medal tones instead. */
.chip--gold {
  --chip-color: #f1c542;
  --chip-shadow: #b3861a;
}

.chip--silver {
  --chip-color: #c7ccd6;
  --chip-shadow: #868c99;
}

.chip--bronze {
  --chip-color: #cd8c52;
  --chip-shadow: #8f5d2e;
}

/* The pick row's compact chip (shared/_chip size: "sm") -- the row already
   has a name/description doing most of the talking, so the slot badge
   shrinks to match instead of anchoring the row's height. */
.chip--sm {
  min-width: 1.5rem;
  height: 1.5rem;
  font-size: 0.65rem;
  border-width: 1px;
  box-shadow: 1px 1px 0 var(--chip-shadow), inset 0 -2px 0 rgb(0 0 0 / 0.2);
}

.chip--lg {
  min-width: 3.4rem;
  height: 3.4rem;
  font-size: 1.4rem;
  box-shadow: 3px 3px 0 var(--chip-shadow), inset 0 -4px 0 rgb(0 0 0 / 0.2);
}

/* Leaderboard rank badge: same fill/border as the square pick-slot chip,
   but flatter -- the square's inset bevel highlight is built for straight
   edges and reads as a stray band once clipped to a circle, so this drops
   it for a plain offset shadow. Bigger than the square's own sm size so it
   still reads as a badge, not a dot. */
.chip--circle {
  min-width: 2rem;
  height: 2rem;
  border-radius: 50%;
  box-shadow: 2px 2px 0 var(--chip-shadow);
}

.my-slots,
.board {
  margin-bottom: 1.5rem;
}

.my-slots h2,
.board h2 {
  font-size: 1rem;
  margin-bottom: 0.5rem;
}

.slot-card {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 0.5rem;
  padding: 0.5rem;
  margin-bottom: 1rem;
}

/* Dashed placeholder for a slot you haven't filled yet (shared/
   _empty_slot_card) -- same corner radius and roughly the same height as a
   real .slot-card, so My Picks doesn't reflow once a pick lands here. */
.empty-slot-card {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 5.5rem;
  margin-bottom: 0.5rem;
  background: none;
  border: 1px dashed var(--border);
  border-radius: 0.5rem;
  color: var(--text-dim);
  font-size: 1.3rem;
  cursor: pointer;
}

/* "Look below" nudge (empty_slot_controller): hidden until the empty slot
   is tapped, gone again two seconds later. Fixed to the viewport, not the
   page, so it never shifts the home stack while it toggles in and out --
   top/left are set inline by the controller, top-aligned to the pressed
   button and centered over it (transform below only handles the
   horizontal half). Accent green throughout so it reads as a call to
   action, not a neutral tooltip. */
.empty-slot-hint {
  position: fixed;
  transform: translateX(-50%);
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
  padding: 0.5rem 0.9rem;
  background: var(--surface);
  border: 1px solid var(--accent);
  border-radius: 0.75rem;
  color: var(--accent);
  font-size: 0.8rem;
  text-align: center;
  white-space: nowrap;
}

/* display: flex above beats the browser's own [hidden] default (author
   CSS always wins over the user-agent stylesheet, specificity aside) --
   spell it out again here, higher specificity, so toggling the attribute
   actually hides it. */
.empty-slot-hint[hidden] {
  display: none;
}

@keyframes empty-slot-hint-bounce {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(0.3rem); }
}

.empty-slot-hint__arrow {
  font-size: 1.1rem;
  animation: empty-slot-hint-bounce 0.6s ease-in-out infinite;
}

.slot-card__header {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* Board-only (picks/_card show_name): whose card this is, its own row
   above the selection -- Kickoff sort only, Player sort's own group
   divider already says who (see the data-sort-mode rule below). */
.slot-card__player-tag {
  display: inline-flex;
  margin-bottom: 0.5rem;
}

/* Plain text while pending; once settled it also carries the chip as a
   prefix ("2× Lions -3.5"), so this is a flex row throughout. One line
   only -- a long team name ellipses in .slot-card__selection-head rather
   than wrapping, so the row never grows past its single-line height. */
.slot-card__selection {
  display: flex;
  gap: 0.25rem;
  flex: 1 1 auto;
  min-width: 0;
  color: var(--text);
  font-weight: 700;
  font-size: 1.05rem;
  align-items: center;
}

/* The team name (or "Over"/"Under") -- shrinks and ellipses first so the
   tail beside it never gets pushed off. */
.slot-card__selection-head {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  min-width: 0;
}

/* "ML" or the spread/total number -- never shrinks or wraps away from
   the team name it qualifies. */
.slot-card__selection-tail {
  flex: none;
  white-space: nowrap;
}

/* Someone else's unrevealed pick, face-down on the board -- dimmed and
   de-emphasized next to real selections. */
.slot-card__selection--hidden {
  color: var(--text-dim);
  font-weight: 500;
}

/* Chip × base points, sized to sit side by side. */
.slot-card__points {
  flex: none;
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.slot-card__base {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: center;
  line-height: 1.1;
}

.slot-card__base-value {
  font-weight: 700;
  font-size: 1.3rem;
}

/* Settled state: just the final points (the chip moved in front of the
   selection instead), no "WIN"/"LOSS" label under it either -- the color
   alone carries the result. */
.slot-card__points--settled {
  display: flex;
  align-items: center;
}

.slot-card__points--settled .slot-card__base-value {
  color: var(--result-color);
}

.slot-card__points--win {
  --result-color: #4caf7d;
}

.slot-card__points--loss {
  --result-color: var(--danger);
}

.slot-card__points--push,
.slot-card__points--void {
  --result-color: var(--warning);
}

/* Dashed, not solid -- distinct from the meta row's own solid separator
   above it (game info vs. pick editor/metadata are a lighter split than
   header vs. game info) -- and the extra margin/padding around the line
   is what actually pulls the footer away from the matchup above it. */
.slot-card__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 0.75rem;
  padding-top: 0.5rem;
  border-top: 1px dashed var(--border);
}

.slot-card__actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* Icon-only outline squares -- Edit (dim) and Remove (danger); aria-label/
   title carry the text. */
.slot-card__action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  background: none;
  border: 1px solid var(--border);
  border-radius: 0.4rem;
  color: var(--text-dim);
  font-size: 0.8rem;
  cursor: pointer;
}

.slot-card__action--danger {
  color: var(--danger);
}

.slot-card__reveal {
  color: var(--text-dim);
  font-size: 0.85rem;
}

.slot-card__meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
  margin: 0.75rem 0 0;
  padding-top: 0.5rem;
  border-top: 1px solid var(--border);
}

/* Compact mode (compact_controller): hides a card's own team/kickoff row.
   data-compact lives on the card itself, not an ancestor -- the toggle sets
   it on every card in its section, but a tap can then flip just one, so
   Home's own slot cards (never a compact_controller target) are untouched
   either way. */
.slot-card[data-compact="true"] .slot-card__meta {
  display: none;
}

/* Only cards a tap can actually flip (Week board, Profile history) hint at
   it -- Home's slot cards have their own Edit/Remove footer instead. */
.board .slot-card,
.profile-history .slot-card {
  cursor: pointer;
}

/* Compact toggle (shared/_compact_toggle): a small switch, not a checkbox,
   so it reads as a mode change rather than a form field -- pinned to the
   end of its board-sort row via margin-left: auto, small enough to never
   force that row to wrap on mobile. */
.compact-toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-left: auto;
  cursor: pointer;
}

.compact-toggle__label {
  font-size: 0.8rem;
}

/* Hidden but real, same recipe as .slot-picker__input -- native checkbox
   semantics drive the sibling track/thumb below. */
.compact-toggle__input {
  position: absolute;
  opacity: 0;
  inset: 0;
  margin: 0;
  cursor: pointer;
}

.compact-toggle__track {
  position: relative;
  flex: none;
  width: 2rem;
  height: 1.1rem;
  background: var(--border);
  border-radius: 999px;
  transition: background 0.15s ease;
}

.compact-toggle__thumb {
  position: absolute;
  top: 0.1rem;
  left: 0.1rem;
  width: 0.9rem;
  height: 0.9rem;
  background: var(--surface);
  border-radius: 50%;
  transition: transform 0.15s ease;
}

.compact-toggle__input:checked + .compact-toggle__track {
  background: var(--accent);
}

.compact-toggle__input:checked + .compact-toggle__track .compact-toggle__thumb {
  transform: translateX(0.9rem);
}

.compact-toggle__input:focus-visible + .compact-toggle__track {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Settings' Notifications switch (push_notifications_controller) -- same
   hidden-checkbox-plus-track-thumb recipe as .compact-toggle, its own
   block since it lives in a setting-card__row rather than a sort row. */
.notify-toggle {
  position: relative;
  display: inline-flex;
  flex: none;
  cursor: pointer;
}

.notify-toggle__input {
  position: absolute;
  opacity: 0;
  inset: 0;
  margin: 0;
  cursor: pointer;
}

.notify-toggle__track {
  position: relative;
  flex: none;
  width: 2rem;
  height: 1.1rem;
  background: var(--border);
  border-radius: 999px;
  transition: background 0.15s ease;
}

.notify-toggle__thumb {
  position: absolute;
  top: 0.1rem;
  left: 0.1rem;
  width: 0.9rem;
  height: 0.9rem;
  background: var(--surface);
  border-radius: 50%;
  transition: transform 0.15s ease;
}

.notify-toggle__input:checked + .notify-toggle__track {
  background: var(--accent);
}

.notify-toggle__input:checked + .notify-toggle__track .notify-toggle__thumb {
  transform: translateX(0.9rem);
}

.notify-toggle__input:focus-visible + .notify-toggle__track {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Sort toggle -- underline tabs, not buttons (docs/specs/ui.md): the
   selected one gets an accent underline + text, plain text/no border the
   rest of the time, since this is a lightweight in-page control next to
   the board, not a primary decision point. */
.board-sort {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 0.75rem;
  font-size: 0.85rem;
  color: var(--text-dim);
}

/* Same padding-bottom + transparent border as .board-sort__text below --
   the label has no underline of its own, but it needs the identical box
   model so align-items: center lines its text up with the tabs' baseline
   instead of centering a shorter box against their taller (bordered) one. */
.board-sort__label {
  display: inline-block;
  padding-bottom: 0.2rem;
  border-bottom: 2px solid transparent;
}

.board-sort__tab {
  position: relative;
}

.board-sort__input {
  position: absolute;
  opacity: 0;
  inset: 0;
  margin: 0;
  cursor: pointer;
}

/* Also used as a plain link (Profile's sort, no radio/JS behind it -- a
   real navigation instead, since Team grouping's tie-break is server-side
   logic, not something worth re-deriving in JS) -- color/no-underline reset
   so it reads the same as the Week board's <span> version. */
.board-sort__text {
  display: inline-block;
  padding-bottom: 0.2rem;
  border-bottom: 2px solid transparent;
  color: inherit;
  text-decoration: none;
  cursor: pointer;
}

.board-sort__input:checked + .board-sort__text,
.board-sort__text--active {
  color: var(--accent);
  font-weight: 600;
  border-bottom-color: var(--accent);
}

/* Group divider (shared/_group_divider): a centered pill on a full-width
   rule, marking a group boundary wherever the app groups things -- the
   board's Kickoff (day) and Player (name) sort, Profile's week grouping.
   One shared form so grouping looks and behaves the same everywhere. */
.group-divider {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 1.25rem 0 0.75rem;
}

.group-divider__rule {
  flex: 1;
  height: 1px;
  background: var(--border);
}

/* pill: false's plain alternative to .value-pill below -- same size/weight,
   no background/padding, for a value (a day, a week number) that isn't a
   name anywhere else on the card. */
.group-divider__label {
  color: var(--text-dim);
  font-size: 0.75rem;
  font-weight: 600;
  white-space: nowrap;
}

/* The small, rounded label used by .group-divider's pill, a board card's
   own player tag (.slot-card__player-tag), and a leaderboard row's name
   (.standings-card__name) -- one shape for "whose name this is", sized to
   match the team names it sits beside (.matchup__away/__home). */
.value-pill {
  display: inline-flex;
  align-items: center;
  padding: 0.2rem 0.6rem;
  border-radius: 0.25rem;
  background: var(--border);
  color: var(--text);
  font-size: 0.85rem;
  font-weight: 600;
  white-space: nowrap;
  text-decoration: none;
}

/* The board's two sort tabs share one fully-rendered set of cards
   (sort_controller only reorders/regroups, never re-renders) -- .board's
   own data-sort-mode (kickoff by default, matching the checked radio;
   sort_controller updates it on switch) hides each card's player tag once
   Player sort's own group divider says who instead; the card's matchup
   block carries kickoff under either sort. */
.board[data-sort-mode="player"] .slot-card__player-tag {
  display: none;
}

.table-scroll {
  overflow-x: auto;
}

/* Recent syncs' OK column, condensed to a dot so it fits before "When" on mobile. */
.sync-status {
  display: inline-block;
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 50%;
}

.sync-status--ok {
  background: var(--accent);
}

.sync-status--error {
  background: var(--danger);
}

/* Tighter cell padding on mobile so the status dot column doesn't eat
   width that the timestamp/counts need. */
@media (max-width: 480px) {
  .sync-table th,
  .sync-table td {
    padding: 0.5rem 0.4rem;
  }

  .sync-table th:first-child,
  .sync-table td:first-child {
    padding-right: 0.25rem;
  }
}

/* Admin dashboard (admin/dashboard/show): top-level links as tappable
   cards instead of bare " · "-joined text, and the two sync buttons in a
   wrapping row -- both hold up on a phone-width screen. */
.admin-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 1rem;
}

.admin-nav__link {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 0.5rem;
  padding: 0.5rem 0.9rem;
  color: var(--text);
  font-size: 0.9rem;
  font-weight: 600;
  text-decoration: none;
}

.admin-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 1.5rem;
}

/* button_to wraps each button in its own <form>; that's the actual flex
   item, so the sizing rule targets the form, not .button. */
.admin-actions form {
  flex: 1 1 auto;
  margin: 0;
}

.admin-actions .button {
  display: block;
  width: 100%;
  text-align: center;
}

.admin-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.admin-list__item {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 0.5rem;
  padding: 0.5rem 0.75rem;
  font-size: 0.9rem;
}

.admin-tabs {
  display: flex;
  gap: 0.25rem;
  overflow-x: auto;
  margin-bottom: 1rem;
  border-bottom: 1px solid var(--border);
}

.admin-tabs__tab {
  padding: 0.5rem 0.75rem;
  color: var(--text-dim);
  text-decoration: none;
  font-size: 0.85rem;
  white-space: nowrap;
  border-bottom: 2px solid transparent;
}

.admin-tabs__tab--active {
  color: var(--accent);
  border-bottom-color: var(--accent);
  font-weight: 600;
}

table {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: 1.5rem;
  font-size: 0.9rem;
}

th,
td {
  text-align: left;
  padding: 0.5rem 0.75rem;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

th {
  color: var(--text-dim);
  font-weight: 600;
  font-size: 0.8rem;
}

/* Admin games (admin/games#index): one card per game instead of a wide
   table -- the old table's score/completed/voided form needed horizontal
   scrolling to reach on a phone. */
.game-list {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.game-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 0.5rem;
  padding: 0.75rem 1rem;
}

.game-card__matchup {
  font-weight: 600;
}

.game-card__kickoff {
  color: var(--text-dim);
  font-size: 0.85rem;
  margin-bottom: 0.75rem;
}

.game-card__scores {
  display: flex;
  gap: 0.75rem;
  margin-bottom: 0.6rem;
}

.game-card__field {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  font-size: 0.8rem;
  color: var(--text-dim);
}

.game-card__flags {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.game-card__flags .button--compact {
  margin-left: auto;
}

.game-card__form .button--compact {
  width: auto;
  padding: 0.35rem 0.75rem;
  font-size: 0.8rem;
}

/* Admin users (admin/users#index): same one-card-per-row treatment as
   .game-card, but the role form is one field so it fits on one line. */
.user-list {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.user-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 0.5rem;
  padding: 0.75rem 1rem;
}

.user-card__identity {
  margin-bottom: 0.6rem;
}

.user-card__name {
  font-weight: 600;
  color: var(--text);
}

.user-card__email {
  color: var(--text-dim);
  font-size: 0.85rem;
}

.profile-auto-pick {
  margin: -0.25rem 0 1rem;
  color: var(--text-dim);
}

.profile-stats {
  margin-bottom: 1.5rem;
  color: var(--text-dim);
}

.profile-history h2 {
  color: var(--text-dim);
}

/* Purely structural -- list semantics only. Its shared/_group_divider
   child owns all the spacing between one period's picks and the next's. */

.profile-history__list {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* The .slot-card inside each <li> already owns padding/margin -- the <li>
   itself is just list semantics. */

/* Settings -- a stack of small cards (2025 app's pattern), one setting (or
   group of related settings) per card, instead of one long bare form. */
.settings-list {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.setting-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 0.5rem;
  padding: 0.6rem 0.75rem;
}

.setting-card__label {
  display: block;
  font-size: 0.75rem;
  letter-spacing: 0.03em;
  color: var(--text-dim);
  margin-bottom: 0.25rem;
}

.setting-card__value {
  font-size: 1rem;
}

/* Shared by the Account row (email + Log out) and the Role row (badge +
   Admin link) -- label/value on the left, an action on the right. */
.setting-card__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}

.setting-card__hint {
  font-size: 0.8rem;
  color: var(--text-dim);
  margin: 0.15rem 0 0.6rem;
}

/* Notifications card: hint text doubling as a row's left side (next to the
   toggle) instead of sitting on its own block above/below -- no bottom
   margin needed there. */
.setting-card__row .setting-card__hint {
  margin: 0;
}

/* Nickname/auto-pick: field + its own Save button, one row, never wrapping
   to a second line even on a narrow phone -- the field shrinks (min-width:
   0 overrides its own flex-basis auto, which would otherwise refuse to
   shrink below its content) rather than pushing Save down or off-screen. */
.setting-card__inline-form {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 0.5rem;
}

.setting-card__inline-form .text-input {
  flex: 1 1 auto;
  min-width: 0;
}

.setting-card__inline-form .button--compact {
  flex: 0 0 auto;
  width: auto;
  padding: 0.35rem 0.75rem;
  font-size: 0.8rem;
}

.text-input {
  display: block;
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 0.4rem;
  padding: 0.55rem 0.7rem;
  color: var(--text);
  /* iOS Safari auto-zooms on focus for any input under 16px, and never
     zooms back out -- keep this at 1rem to avoid that trap. */
  font-size: 1rem;
}

.text-input:focus {
  outline: none;
  border-color: var(--accent);
}

/* Every button on Settings is one of these inline, sits-next-to-its-field
   ones (Log out next to the account email, Save next to each card's own
   field) -- same colors as .button, just a smaller footprint than the
   solid full-width default. */
.settings-list .button--compact {
  width: auto;
  padding: 0.35rem 0.75rem;
  font-size: 0.8rem;
}

.button--danger {
  background: var(--danger);
}

@media (prefers-color-scheme: light) {
  :root {
    --bg: #f5f6f8;
    --surface: #ffffff;
    --text: #1a1e24;
    --text-dim: #5b6472;
    --border: #dde1e6;
  }
}


/* ---------------------------------------------------------------------
   Leaderboard: one card per player, three columns -- rank | name + record/
   streak | trend + points -- so the rank badge and the trend/points group
   can center vertically against the two-line name column instead of
   pinning to its top line. Rank 1-3 use the same chip badge the pick slots
   use (gold/silver/bronze here).
   ------------------------------------------------------------------ */

.standings-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-bottom: 1.5rem;
}

.standings-card {
  display: grid;
  /* Rank column is a fixed width, not auto -- each card is its own grid
     (standings-list is a flex column of separate <a>s), so an auto track
     sizes to that row's own rank content alone: rank 1-3's chip badge vs.
     4+'s bare number would otherwise size the column differently per row,
     knocking the info column out of alignment underneath it. */
  grid-template-columns: 2.25rem 1fr auto;
  align-items: center;
  column-gap: 0.75rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 0.5rem;
  padding: 0.5rem;
  text-decoration: none;
}

.standings-card__rank-col {
  display: flex;
  align-items: center;
  justify-content: center;
}

.standings-card__rank {
  font-weight: 700;
  font-size: 1.2rem;
  color: var(--text-dim);
}

.standings-card__info {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

/* .value-pill (application.css) carries the look now, matching the same
   tag used on the Week board's cards -- this just keeps it from
   stretching full-width in the flex column and truncates a long name. */
.standings-card__name {
  align-self: flex-start;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.standings-card__meta {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.85rem;
  color: var(--text-dim);
}

.standings-card__dot {
  opacity: 0.6;
}

.standings-card__totals {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* White for the podium (rank 1-3); everyone else's total is the same
   neutral gray as their record/streak line -- no green/red anywhere on
   this card, the numbers speak for themselves. Same bold sans-serif
   treatment as a pick card's own point value (.slot-card__base-value) --
   monospace here read as a mismatched, unrelated number style. */
.standings-card__points {
  font-weight: 700;
  font-size: 1.2rem;
  color: var(--text);
  white-space: nowrap;
}

.standings-card__points--muted {
  color: var(--text-dim);
}

.standings-trend {
  flex: none;
  display: block;
  width: 3.25rem;
  height: 1.15rem;
}

.standings-trend polyline {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  opacity: 0.85;
}
