/*
 * COMPONENTS -- one stylesheet for the whole product.
 *
 * Replaces global-styles.css, nfl-theme.css, table-styles.css and auth.css, plus the four
 * per-view <style> blocks that used to live inside account/sheet/leaderboard/import-week.
 * Those were four token systems fighting each other: nfl-theme and global-styles both
 * defined --primary-color with different values, and every view then patched the result
 * with `body.dark-mode ... !important`.
 *
 * Rules here:
 *   - No raw colour values. Everything comes from tokens.css.
 *   - Phone first. Every media query is min-width; the unqualified rule is the phone rule.
 *   - Figures carry `tabular-nums` so columns of money line up.
 *
 * Section order:
 *   1  base            8  badges + pills
 *   2  layout shell    9  alerts
 *   3  nav            10  tables
 *   4  type           11  the sheet
 *   5  cards          12  leaderboard + account
 *   6  buttons        13  admin + import
 *   7  forms          14  auth pages
 *                     15  utilities
 */

/* ============================================================ 1. base */

*,
*::before,
*::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  padding: 0;
  min-height: 100vh;
  font-family: var(--font-sans);
  font-size: var(--fs-400);
  line-height: var(--lh-body);
  color: var(--fg);
  background: var(--ground);
}

/* Every figure in this product is money or a count. Proportional digits make a column of
   them jitter, which is exactly the thing you scan down. */
table, .stat-value, .balance-amount, .payout, .stake-amount, .spread,
.transaction-amount, .final-score, .current-score, .bet-size, .figure {
  font-variant-numeric: tabular-nums;
}

a {
  color: var(--brand-text);
  text-decoration-color: color-mix(in srgb, var(--brand-text) 40%, transparent);
  text-underline-offset: 2px;
}

a:hover { color: var(--brand); }

img, svg { max-width: 100%; }

hr {
  border: 0;
  border-top: 1px solid var(--line);
  margin: var(--sp-5) 0;
}

code, pre { font-family: var(--font-mono); }

::selection {
  background: var(--brand-soft);
  color: var(--fg);
}

:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--r-sm);
}

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--ground-2); }
::-webkit-scrollbar-thumb {
  background: var(--line-2);
  border-radius: var(--r-pill);
  border: 2px solid var(--ground-2);
}
::-webkit-scrollbar-thumb:hover { background: var(--fg-3); }

/* ============================================================ 2. layout shell */

.container {
  width: 100%;
  max-width: var(--page-max);
  margin: 0 auto;
  padding: var(--sp-4) var(--sp-4) var(--sp-7);
}

@media (min-width: 820px) {
  .container { padding: var(--sp-6) var(--sp-5) var(--sp-7); }
}

.page-header {
  margin: 0 0 var(--sp-4);
}

.page-header h1 {
  margin: 0;
  font-size: var(--fs-700);
  line-height: var(--lh-tight);
  letter-spacing: -0.015em;
}

.page-header p { margin: var(--sp-2) 0 0; color: var(--fg-2); }

.section-title {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin: var(--sp-6) 0 var(--sp-3);
  font-size: var(--fs-600);
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--fg);
}

.section-title::before {
  content: '';
  width: 3px;
  height: 1.1em;
  border-radius: var(--r-pill);
  background: var(--brand);
}

/* ============================================================ 3. nav */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--ground-2);
  border-bottom: 1px solid var(--line);
  box-shadow: var(--shadow-sm);
}

/* The gold hairline is the brand mark. There is no logo and no webfont, so this and the
   weight contrast are what make the product recognisable. */
.site-header::after {
  content: '';
  display: block;
  height: 2px;
  background: linear-gradient(90deg, var(--brand) 0%, var(--brand-2) 45%, transparent 100%);
}

/* Named areas rather than auto-placement, so the DOM order of the three groups is free to
   stay readable while the phone layout drops the links onto their own row. */
.nav {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: var(--sp-3) var(--sp-4);
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas:
    "brand right"
    "links links";
  align-items: center;
  gap: var(--sp-3);
}

.nav-brand { grid-area: brand; }
.nav-links { grid-area: links; }
.nav-right { grid-area: right; }

.nav-brand {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  /* Phone first. "Centorbi Football Pool" at 17px overflows a narrow header and gets
     ellipsised to "Centorbi Footb..."; it goes back up to --fs-500 at 900px. */
  font-size: var(--fs-400);
  font-weight: 800;
  letter-spacing: -0.015em;
  color: var(--fg);
  min-width: 0;
  text-decoration: none;
}

.nav-brand:hover .pool-name { text-decoration: underline; }
.nav-brand:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; border-radius: var(--r-sm); }

.nav-brand .pool-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.football-icon { font-size: 1.25em; line-height: 1; }

/* Phone: the links become a full-width strip that scrolls sideways rather than wrapping
   into three ragged rows. 19 people pick on phones; the nav must not eat the screen. */
.nav-links {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  overflow-x: auto;
  scrollbar-width: none;
  margin: 0 calc(var(--sp-4) * -1);
  padding: 0 var(--sp-4);
}

.nav-links::-webkit-scrollbar { display: none; }

.nav-links a {
  flex: 0 0 auto;
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-pill);
  font-size: var(--fs-300);
  font-weight: 600;
  color: var(--fg-2);
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--t-fast), color var(--t-fast);
}

.nav-links a:hover {
  background: var(--surface-2);
  color: var(--fg);
}

.nav-links a.super-admin-link {
  color: var(--brand-text);
  box-shadow: inset 0 0 0 1px var(--line-2);
}

.nav-right {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  justify-self: end;
}

.nav-welcome {
  display: none;
  font-size: var(--fs-300);
  color: var(--fg-2);
}

.pool-switcher,
.league-switcher,
.league-selector-wrapper {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}

.pool-label,
.league-label {
  display: none;
  font-size: var(--fs-100);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--fg-3);
}

/* The switcher shrinks before the wordmark does. On a 390px screen there is not room for
   both at full size, and losing the product's name is worse than truncating a pool name. */
.nav select {
  max-width: 7rem;
  padding: var(--sp-1) var(--sp-2);
  font-size: var(--fs-300);
  font-weight: 600;
}

@media (min-width: 560px) {
  .nav select { max-width: 10rem; }
}

.pool-badge,
.league-badge {
  padding: var(--sp-1) var(--sp-2);
  border-radius: var(--r-pill);
  background: var(--surface-2);
  border: 1px solid var(--line);
  font-size: var(--fs-100);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--fg-2);
  white-space: nowrap;
}




@media (min-width: 900px) {
  .nav {
    grid-template-columns: auto 1fr auto;
    grid-template-areas: "brand links right";
    padding: var(--sp-3) var(--sp-5);
  }

  .nav-links {
    overflow: visible;
    margin: 0;
    padding: 0;
    gap: var(--sp-1);
  }

  .nav-welcome { display: inline; }
  .pool-label, .league-label { display: inline; }
  .nav-brand { font-size: var(--fs-500); }
}

/* ============================================================ 4. type */

h1, h2, h3, h4 {
  margin: 0 0 var(--sp-3);
  line-height: var(--lh-tight);
  letter-spacing: -0.012em;
  color: var(--fg);
}

h1 { font-size: var(--fs-700); font-weight: 800; }
h2 { font-size: var(--fs-600); font-weight: 700; }
h3 { font-size: var(--fs-500); font-weight: 700; }
h4 { font-size: var(--fs-400); font-weight: 700; }

p { margin: 0 0 var(--sp-3); }

/* The uppercase micro-label. Used for every "what is this number" caption. */
.label,
.stat-label,
.balance-label,
.countdown-label,
.form-group-label {
  font-size: var(--fs-100);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--fg-3);
}

.muted,
.text-muted,
.hint,
.quota-info,
.footer-text {
  color: var(--fg-2);
}

.hint,
.quota-info {
  font-size: var(--fs-200);
  margin-top: var(--sp-1);
}

/* ============================================================ 5. cards */

.card,
.nfl-card,
.config-section,
.games-preview {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--sp-4);
  margin: 0 0 var(--sp-4);
}

@media (min-width: 560px) {
  .card,
  .nfl-card,
  .config-section,
  .games-preview { padding: var(--sp-5); }
}

.card > :last-child,
.config-section > :last-child { margin-bottom: 0; }

.card h2,
.card h3 { margin-top: 0; }

.card-header,
.admin-header,
.import-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
}

.card-header h3,
.admin-header h1 { margin: 0; }

.admin-header-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
}

.stat-card,
.stat-mini,
.strategy-card,
.league-card,
.league-card-mini,
.week-card,
.user-row,
.team-row,
.game-card,
.balance-card {
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: var(--sp-3);
}

.stat-card { text-align: center; }

.stat-value {
  display: block;
  font-size: var(--fs-700);
  font-weight: 800;
  line-height: var(--lh-tight);
  letter-spacing: -0.02em;
  color: var(--fg);
}

.stat-name {
  display: block;
  margin-top: var(--sp-1);
  font-size: var(--fs-300);
  color: var(--fg-2);
}

.stat-card-good { border-color: color-mix(in srgb, var(--win) 45%, var(--line)); }
.stat-card-good .stat-value { color: var(--win); }
.stat-card-bad { border-color: color-mix(in srgb, var(--lose) 45%, var(--line)); }
.stat-card-bad .stat-value { color: var(--lose); }

.stats-heading-good { color: var(--win); }
.stats-heading-bad { color: var(--lose); }

.stats-grid,
.stats-container,
.settings-grid,
.leagues-grid,
.teams-list,
.grid-auto {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-3);
}

@media (min-width: 560px) {
  .stats-grid,
  .stats-container,
  .settings-grid,
  .leagues-grid,
  .teams-list,
  .grid-auto {
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  }
}

.grid-2,
.grid-3,
.config-grid,
.account-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-4);
}

@media (min-width: 720px) {
  .grid-2, .config-grid, .account-grid { grid-template-columns: repeat(2, 1fr); }
  .grid-3 { grid-template-columns: repeat(3, 1fr); }
}

.weeks-games-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-4);
  align-items: start;
}

@media (min-width: 900px) {
  .weeks-games-grid { grid-template-columns: 19rem 1fr; }
}

.week-card,
.user-row,
.team-row { margin-bottom: var(--sp-2); }

.week-card-header,
.user-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
}

.week-card-actions,
.user-actions,
.team-actions,
.user-status,
.modal-actions,
.pick-buttons {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
}

.users-list,
.weeks-list,
.enrolled-leagues {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.user-info { flex: 1 1 12rem; min-width: 0; }

/*
 * The auto-pick fallback on the admin user list. It used to read just "Default:", which said
 * nothing about what it defaults FOR -- so it now carries a full label and a note that a
 * per-pool choice overrides it. Stacked rather than inline because the label is a sentence,
 * and a sentence beside a <select> wraps badly on a phone.
 */
.default-pick-select {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  margin-top: var(--sp-2);
}

.default-pick-select label {
  font-size: var(--fs-200);
  color: var(--fg-2);
}

.default-pick-select select { align-self: flex-start; }

.hint-inline {
  font-size: var(--fs-100, var(--fs-200));
  color: var(--fg-2);
}

/* ============================================================ 6. buttons */

.btn,
button,
input[type="submit"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  min-height: 2.75rem;      /* a thumb target, not a mouse target */
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  background: var(--brand);
  color: var(--fg-on-fill);
  font: inherit;
  font-size: var(--fs-300);
  font-weight: 700;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast);
}

.btn:hover,
button:hover { background: var(--brand-2); color: var(--fg-on-fill); }

.btn:disabled,
button:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.btn-primary,
.btn-nfl,
.btn-confirm { background: var(--brand); color: var(--fg-on-fill); }

.btn.secondary,
.btn-cancel,
.modal-close {
  background: var(--surface-2);
  border-color: var(--line-2);
  color: var(--fg);
}

.btn.secondary:hover,
.btn-cancel:hover,
.modal-close:hover { background: var(--surface-3); color: var(--fg); }

/* Deliberately NOT green. Green means "you are up" and nothing else -- a green Create User
   button spends the one colour the sheet needs. These are primary actions, so they get the
   brand. Red is kept for destructive actions: it never lands next to a figure, so it cannot
   be misread as a loss. */
.btn.success,
.btn-fetch {
  background: var(--brand);
  color: var(--fg-on-fill);
}

.btn.success:hover,
.btn-fetch:hover { background: var(--brand-2); }

.btn.danger,
.btn-danger {
  background: var(--lose);
  color: var(--fg-on-fill);
}

.btn.danger:hover,
.btn-danger:hover { background: color-mix(in srgb, var(--lose) 82%, black); }

/* Logging out is not a call to action. Defined here rather than with the nav so it lands
   after the .btn rule it has to beat. */
.btn-logout {
  min-height: 2rem;
  padding: var(--sp-1) var(--sp-3);
  background: transparent;
  border-color: var(--line-2);
  color: var(--fg-2);
  font-size: var(--fs-200);
  font-weight: 600;
}

.btn-logout:hover {
  background: var(--surface-2);
  border-color: var(--fg-3);
  color: var(--fg);
}

.btn-sm,
.btn-small {
  min-height: 2rem;
  padding: var(--sp-1) var(--sp-3);
  font-size: var(--fs-200);
}

.modal-close {
  width: 2rem;
  min-height: 2rem;
  padding: 0;
  border-radius: var(--r-pill);
  font-size: var(--fs-500);
}

/* ============================================================ 7. forms */

label {
  display: block;
  margin-bottom: var(--sp-1);
  font-size: var(--fs-300);
  font-weight: 600;
  color: var(--fg);
}

input:not([type="submit"], [type="button"], [type="reset"], [type="checkbox"], [type="radio"]),
select,
textarea {
  font: inherit;
  font-size: max(var(--fs-400), 16px);   /* under 16px iOS zooms the whole page on focus */
  width: 100%;
  padding: var(--sp-3);
  color: var(--fg);
  background: var(--surface-2);
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}

textarea { min-height: 6rem; }

/* Checkboxes and radios are excluded from the rule above rather than overridden by it:
   `input:not(...)` carries three attribute selectors and would out-specify a plain
   `input[type=checkbox]`, which is how the sheet's "view my column only" checkbox ended up
   stretched to the full width of its label. */
input[type="checkbox"],
input[type="radio"] {
  width: auto;
  min-height: 0;
  accent-color: var(--brand);
  cursor: pointer;
}

input:focus,
select:focus,
textarea:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: var(--focus-ring);
}

input::placeholder { color: var(--fg-3); }

.form-group { margin-bottom: var(--sp-4); }

.form-group label { margin-bottom: var(--sp-2); }

.form-control { width: 100%; }

/* Toggle switch */
.switch {
  position: relative;
  display: inline-block;
  flex: 0 0 auto;
  width: 2.5rem;
  height: 1.5rem;
}

.switch input { opacity: 0; width: 0; height: 0; }

.slider {
  position: absolute;
  inset: 0;
  cursor: pointer;
  background: var(--line-2);
  border-radius: var(--r-pill);
  transition: background var(--t-base);
}

.slider::before {
  content: '';
  position: absolute;
  left: 3px;
  bottom: 3px;
  width: 1.125rem;
  height: 1.125rem;
  border-radius: 50%;
  background: var(--fg);
  transition: transform var(--t-base);
}

input:checked + .slider { background: var(--win); }
input:checked + .slider::before { transform: translateX(1rem); }
input:focus + .slider { box-shadow: var(--focus-ring); }

/* ============================================================ 8. badges + pills */

.status-badge,
.pill,
.transaction-type,
.auto-poll-badge,
.invite-code,
.team-abbrev,
.league-status,
.save-indicator {
  display: inline-block;
  padding: var(--sp-1) var(--sp-2);
  border-radius: var(--r-pill);
  background: var(--neutral-soft);
  color: var(--fg-2);
  font-size: var(--fs-100);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  white-space: nowrap;
}

.invite-code {
  font-family: var(--font-mono);
  font-size: var(--fs-400);
  letter-spacing: 0.14em;
  text-transform: none;
  color: var(--brand-text);
  background: var(--brand-soft);
}

.status-open,
.pill-win,
.transaction-type.payout,
.save-indicator { background: var(--win-soft); color: var(--win); }

.status-closed,
.pill-lose { background: var(--lose-soft); color: var(--lose); }

.transaction-type.adjustment { background: var(--warn-soft); color: var(--warn); }
.transaction-type.bet { background: var(--brand-soft); color: var(--brand-text); }

.live-indicator {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  color: var(--lose);
  font-size: var(--fs-100);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
}

.live-indicator::before {
  content: '';
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--lose);
  animation: pulse 1.6s infinite;
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}

/* ============================================================ 9. alerts */

.alert,
.warning-box,
.error-box,
.success-box,
.polling-info-box,
.league-polling-status,
.closed-notice,
.picks-open-notice,
.notice {
  padding: var(--sp-3) var(--sp-4);
  margin-bottom: var(--sp-4);
  border: 1px solid var(--line);
  border-left: 3px solid var(--fg-3);
  border-radius: var(--r-sm);
  background: var(--neutral-soft);
  color: var(--fg);
  font-size: var(--fs-300);
}

.alert-success,
.success-box,
.notice,
.picks-open-notice,
.league-polling-status.enabled {
  background: var(--win-soft);
  border-color: color-mix(in srgb, var(--win) 40%, transparent);
  border-left-color: var(--win);
  color: var(--fg);
}

.alert-danger,
.alert-error,
.error-box,
.closed-notice,
.league-polling-status.disabled {
  background: var(--lose-soft);
  border-color: color-mix(in srgb, var(--lose) 40%, transparent);
  border-left-color: var(--lose);
  color: var(--fg);
}

.alert-warning,
.warning-box {
  background: var(--warn-soft);
  border-color: color-mix(in srgb, var(--warn) 40%, transparent);
  border-left-color: var(--warn);
  color: var(--fg);
}

.alert-info,
.polling-info-box {
  background: var(--info-soft);
  border-color: color-mix(in srgb, var(--info) 40%, transparent);
  border-left-color: var(--info);
  color: var(--fg);
}

.league-polling-status,
.auto-poll-status {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3);
}

/* ============================================================ 10. tables */

/* Wide tables scroll inside their own box. The page body never scrolls sideways --
   on a phone that is how you lose your own column. */
.table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  margin: 0 0 var(--sp-4);
}

.data-table,
.transaction-table,
table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-300);
}

.data-table thead th,
.transaction-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  padding: var(--sp-2) var(--sp-2);
  background: var(--surface-3);
  border-bottom: 2px solid var(--brand);
  color: var(--fg-2);
  font-size: var(--fs-100);
  font-weight: 700;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  white-space: nowrap;
}

.data-table thead th:first-child,
.transaction-table thead th { text-align: left; }

.data-table thead th:first-child {
  left: 0;
  z-index: 3;
  min-width: 6.5rem;
}

.data-table tbody td,
.transaction-table tbody td {
  padding: var(--sp-2);
  border-bottom: 1px solid var(--line);
  text-align: center;
  vertical-align: middle;
}

.transaction-table tbody td { text-align: left; }

.data-table tbody td:first-child {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--surface-2);
  text-align: left;
  font-weight: 600;
  white-space: nowrap;
}

.data-table tbody tr:hover td,
.transaction-table tbody tr:hover td { background: var(--surface-2); }

.data-table tbody tr.total-row td,
.weekly-total-row td {
  border-top: 2px solid var(--line-2);
  background: var(--surface-2);
  font-size: var(--fs-400);
  font-weight: 700;
}

.data-table tbody tr.bottom-names-row th {
  position: sticky;
  bottom: 0;
  z-index: 2;
  padding: var(--sp-2);
  background: var(--surface-3);
  border-top: 2px solid var(--brand);
  color: var(--fg-2);
  font-size: var(--fs-100);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  white-space: nowrap;
}

.data-table tbody tr.bottom-names-row th:first-child { left: 0; z-index: 3; text-align: left; }

.projected-row td { background: var(--warn-soft); }

/* Meaning colours. Green is winning, red is losing -- nothing else in the product is
   allowed to use them. */
.positive-value, .text-success, .payout.positive, .transaction-amount.positive,
.amount-positive { color: var(--win); font-weight: 700; }

.negative-value, .text-danger, .payout.negative, .transaction-amount.negative,
.amount-negative { color: var(--lose); font-weight: 700; }

.neutral-value { color: var(--fg-2); }

.week-winner { background: var(--win-soft) !important; color: var(--win) !important; font-weight: 700; }
.week-loser { background: var(--lose-soft) !important; color: var(--lose) !important; font-weight: 700; }
.leader-cell { background: var(--brand-soft) !important; }
.leader-badge { margin-left: var(--sp-1); }

/* ============================================================ 11. the sheet */

.game-info {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  text-align: left;
}

.matchup { font-size: var(--fs-300); font-weight: 700; color: var(--fg); }
.spread { font-size: var(--fs-200); color: var(--fg-2); }
.final-score { font-size: var(--fs-100); color: var(--fg-2); font-weight: 600; }
.current-score { font-size: var(--fs-100); color: var(--fg); font-weight: 700; margin-left: var(--sp-1); }
.bet-size { font-size: var(--fs-200); color: var(--brand-text); font-weight: 700; }
.game-time { font-size: var(--fs-200); color: var(--fg-2); }
.game-teams { font-size: var(--fs-400); font-weight: 700; }
.game-spread { text-align: center; }

.pick-cell { min-height: 3rem; }

.pick-display {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-1);
}

.team-pick { font-size: var(--fs-300); font-weight: 700; color: var(--brand-text); }
.stake-amount { font-size: var(--fs-200); color: var(--fg-2); }

.pick-result {
  padding: 1px var(--sp-2);
  border-radius: var(--r-pill);
  font-size: var(--fs-100);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
}

.pick-result.win { background: var(--win-soft); color: var(--win); }
.pick-result.loss { background: var(--lose-soft); color: var(--lose); }
.pick-result.push { background: var(--warn-soft); color: var(--warn); }

.pick-result.projected {
  background: transparent;
  border: 1px dashed currentColor;
  font-style: italic;
}

.payout { font-size: var(--fs-200); font-weight: 700; }

.pick-buttons { flex-direction: column; }

/* The two opposing targets. Big enough to hit with a thumb without looking. */
.pick-team-btn {
  width: 100%;
  min-width: 4.5rem;
  min-height: 2.5rem;
  padding: var(--sp-2);
  background: var(--surface-2);
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  color: var(--fg);
  font-size: var(--fs-200);
  font-weight: 700;
}

.pick-team-btn:hover {
  background: var(--surface-3);
  border-color: var(--brand);
  color: var(--fg);
}

.pick-team-btn.selected {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--fg-on-fill);
}

.pick-btn.selected { background: var(--brand); color: var(--fg-on-fill); }
.pick-btn.winner { background: var(--win-soft); color: var(--win); border-color: var(--win); }
.pick-btn.loser { background: var(--lose-soft); color: var(--lose); border-color: var(--lose); }

.save-indicator { text-transform: none; letter-spacing: 0; }

.view-toggle-label {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  background: var(--surface-2) !important;
  border: 1px solid var(--line-2) !important;
  border-radius: var(--r-sm);
  color: var(--fg) !important;
  font-size: var(--fs-300);
  cursor: pointer;
}

.view-toggle-label:hover { background: var(--surface-3) !important; }

.countdown-card,
.waiting-card,
.success-card {
  border-radius: var(--r-lg);
  padding: var(--sp-4);
  text-align: center;
}

.countdown-card {
  background: var(--info-soft) !important;
  border: 1px solid color-mix(in srgb, var(--info) 40%, transparent) !important;
}

.countdown-card h3,
.countdown-card p,
#countdown { color: var(--info) !important; }

.countdown-time { font-size: var(--fs-600); font-weight: 800; color: var(--fg) !important; }

.waiting-card {
  background: var(--warn-soft) !important;
  border: 1px solid color-mix(in srgb, var(--warn) 40%, transparent) !important;
}

.waiting-card h3, .waiting-card p { color: var(--warn) !important; }
.waiting-card li { border-color: var(--line) !important; color: var(--fg) !important; }

.success-card {
  background: var(--win-soft) !important;
  border: 1px solid color-mix(in srgb, var(--win) 40%, transparent) !important;
}

.success-card p { color: var(--win) !important; }

/* ============================================================ 12. leaderboard + account */

.account-header {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-5) var(--sp-4);
  margin-bottom: var(--sp-5);
  text-align: center;
  background: var(--surface);
  border: 1px solid var(--line);
  border-top: 3px solid var(--brand);
  border-radius: var(--r-lg);
}

@media (min-width: 640px) {
  .account-header { flex-direction: row; text-align: left; }
}

.profile-avatar,
.avatar {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 4rem;
  height: 4rem;
  border-radius: 50%;
  background: var(--brand-soft);
  border: 2px solid var(--brand);
  color: var(--brand-text);
  font-size: var(--fs-700);
  font-weight: 800;
}

.profile-info { flex-grow: 1; min-width: 0; }
.profile-info h1 { margin: 0 0 var(--sp-1); font-size: var(--fs-700); }
.profile-info .username { margin-bottom: var(--sp-3); color: var(--fg-2); font-size: var(--fs-300); }

.pool-standings {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  justify-content: center;
}

@media (min-width: 640px) { .pool-standings { justify-content: flex-start; } }

.balance-card { text-align: left; }
.balance-amount { display: block; font-size: var(--fs-700); font-weight: 800; color: var(--fg); }
.balance-amount.positive, .balance-display.positive { color: var(--win); }
.balance-amount.negative, .balance-display.negative { color: var(--lose); }
.balance-display { font-size: var(--fs-800); font-weight: 800; }
.balance-display.zero { color: var(--fg-2); }

.transaction-amount { font-size: var(--fs-400); font-weight: 700; }

.pagination {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  margin-top: var(--sp-4);
}

/* ============================================================ 13. admin + import */

.tabs-container {
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--sp-5);
  overflow-x: auto;
  scrollbar-width: none;
}

.tabs-container::-webkit-scrollbar { display: none; }

.tabs-nav { display: flex; gap: var(--sp-1); }

.tab-btn {
  flex: 0 0 auto;
  min-height: 2.5rem;
  padding: var(--sp-2) var(--sp-3);
  background: transparent;
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  color: var(--fg-3);
  font-size: var(--fs-300);
  font-weight: 700;
  white-space: nowrap;
}

.tab-btn:hover { background: var(--surface-2); color: var(--fg); }
.tab-btn.active { border-bottom-color: var(--brand); color: var(--brand-text); background: transparent; }

.tab-content { display: none; }
.tab-content.active { display: block; }

.modal-overlay {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 100;
  align-items: center;
  justify-content: center;
  padding: var(--sp-4);
  background: rgba(0, 0, 0, 0.65);
}

.modal-overlay.active { display: flex; }

.modal-content {
  width: 100%;
  max-width: 32rem;
  max-height: 88vh;
  overflow-y: auto;
  padding: var(--sp-5);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
}

.modal-header h3 { margin: 0; }

.import-header {
  display: block;
  padding: var(--sp-5);
  margin-bottom: var(--sp-5);
  background: var(--surface);
  border: 1px solid var(--line);
  border-top: 3px solid var(--brand);
  border-radius: var(--r-lg);
}

.import-header h1 { margin: 0 0 var(--sp-2); }
.import-header p { margin: 0; color: var(--fg-2); }

.import-container {
  max-width: var(--page-max);
  margin: 0 auto;
}

.games-preview { display: none; }
.games-preview.show { display: block; }

.game-card {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-3);
  margin-bottom: var(--sp-3);
}

@media (min-width: 720px) {
  .game-card { grid-template-columns: 2fr 1fr 1fr; align-items: center; }
}

.team-mapping { margin-top: var(--sp-2); }

.loading { text-align: center; padding: var(--sp-7) var(--sp-4); }

.spinner {
  width: 2.5rem;
  height: 2.5rem;
  margin: 0 auto var(--sp-4);
  border: 3px solid var(--line);
  border-top-color: var(--brand);
  border-radius: 50%;
  animation: spin 0.9s linear infinite;
}

@keyframes spin { to { transform: rotate(360deg); } }

.import-week-link .btn,
.week-value-form { display: inline-flex; }

.week-value-form input[type="number"] { width: 5.5rem; }

.week-value-form,
.add-user-form,
.add-team-form,
.league-strategy-form,
.edit-modal-form,
.week-selector,
.user-selector,
.favorite-selector {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
}

.week-value-form input,
.add-user-form input,
.add-team-form input,
.week-selector select,
.user-selector select,
.favorite-selector select { width: auto; flex: 1 1 8rem; }

/* ============================================================ 14. auth pages */

/*
 * The way in. Same ground as everywhere else -- signing in must not change the look of the app,
 * which is the mistake the old UI made (auth.css was its own dark world, then you landed on a
 * light dashboard). The only thing the entrance does differently is let the brand wash the
 * whole screen, faintly, from above.
 */
body.auth {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-5) var(--sp-4);
  background:
    radial-gradient(120% 80% at 50% -10%, rgba(232, 179, 60, 0.10) 0%, transparent 60%),
    var(--ground);
}

.login-container {
  width: 100%;
  max-width: 24rem;
}

.login-form {
  padding: var(--sp-6) var(--sp-5);
  background: var(--surface);
  border: 1px solid var(--line);
  border-top: 3px solid var(--brand);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
}

.login-header {
  margin-bottom: var(--sp-5);
  text-align: center;
}

.login-header .football-icon {
  display: block;
  margin-bottom: var(--sp-2);
  font-size: 2.5rem;
}

.login-header h2 {
  margin: 0;
  font-size: var(--fs-600);
  font-weight: 800;
}

.login-header p {
  margin: var(--sp-2) 0 0;
  color: var(--fg-2);
  font-size: var(--fs-300);
}

.btn-login {
  width: 100%;
  margin-top: var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  background: var(--brand);
  color: var(--fg-on-fill);
  font-size: var(--fs-400);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
}

.btn-login:hover { background: var(--brand-2); }

.error {
  margin-top: var(--sp-4);
  padding: var(--sp-3);
  border-radius: var(--r-sm);
  background: var(--lose-soft);
  border: 1px solid color-mix(in srgb, var(--lose) 40%, transparent);
  color: var(--fg);
  font-size: var(--fs-300);
}

.auth-body {
  text-align: center;
  color: var(--fg-2);
  font-size: var(--fs-400);
}

.auth-body strong { color: var(--fg); word-break: break-all; }

.auth-links {
  margin-top: var(--sp-4);
  text-align: center;
  font-size: var(--fs-300);
}

.auth-links .sep { color: var(--fg-3); margin: 0 var(--sp-2); }

.footer-text {
  margin-top: var(--sp-4);
  text-align: center;
  font-size: var(--fs-200);
  color: var(--fg-3);
}

/* ============================================================ 15. home screen */

/*
 * Your pools. One card per pool, and the card IS the door -- the whole card is the link, so
 * on a phone there is no small target to aim at.
 *
 * Explicit grid tracks, not `auto`. An earlier pass let each card size its own columns, so
 * the standing sat in a different place on every row depending on how long the pool's name
 * was, and the column of figures -- the thing you actually scan down -- was ragged.
 */

.pool-list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}

.pool-card {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--sp-1) var(--sp-4);
  align-items: center;
  padding: var(--sp-4);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  color: var(--fg);
  text-decoration: none;
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}

.pool-card:hover,
.pool-card:focus-visible {
  border-color: var(--brand-2);
  box-shadow: var(--shadow-sm);
  outline: none;
  color: var(--fg);
}

.pool-card-name {
  grid-column: 1;
  font-size: var(--fs-500);
  font-weight: 700;
  letter-spacing: -0.01em;
}

.pool-card-figure {
  grid-column: 2;
  grid-row: 1 / span 2;
  align-self: center;
  font-size: var(--fs-700);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

.pool-card-figure.up { color: var(--win); }
.pool-card-figure.down { color: var(--lose); }
.pool-card-figure.flat { color: var(--fg-3); }

.pool-card-meta {
  grid-column: 1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-200);
  color: var(--fg-2);
}

/* Picks outstanding. Spans both columns so it reads as a line about the card, not a caption
   under the name. */
.pool-card-owed {
  grid-column: 1 / -1;
  margin-top: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-sm);
  background: var(--brand-soft);
  color: var(--brand-text);
  font-size: var(--fs-200);
  font-weight: 700;
}

.tag {
  padding: 2px var(--sp-2);
  border: 1px solid var(--line-2);
  border-radius: var(--r-pill);
  font-size: var(--fs-100);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--fg-3);
  white-space: nowrap;
}

.tag-live { color: var(--brand-text); border-color: var(--brand-2); background: var(--brand-soft); }

.past-pools {
  margin-top: var(--sp-5);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line);
}

.past-pools > summary {
  display: flex;
  justify-content: space-between;
  align-items: center;
  cursor: pointer;
  list-style: none;
  font-size: var(--fs-100);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--fg-3);
}

.past-pools > summary::-webkit-details-marker { display: none; }
.past-pools .pool-list { margin-top: var(--sp-3); }

/* A chevron drawn from borders rather than a glyph. \25BE renders as a hyphen-width stub in
   the Windows system stack, which is exactly what it did here first time out. */
.past-pools > summary::after {
  content: '';
  width: 0.45em;
  height: 0.45em;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: translateY(-0.15em) rotate(45deg);
  transition: transform var(--t-fast);
}

.past-pools[open] > summary::after { transform: translateY(0.1em) rotate(-135deg); }

@media (min-width: 720px) {
  /* Two up on a wider screen. One card per row at 1120px puts the standing an inch and a half
     from the name it belongs to, and the column of figures stops reading as a column. */
  .pool-list {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    align-items: start;
  }
}

.empty-state {
  padding: var(--sp-6) var(--sp-4);
  text-align: center;
  background: var(--surface);
  border: 1px dashed var(--line-2);
  border-radius: var(--r-lg);
  color: var(--fg-2);
}

.empty-state .empty-title {
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-500);
  font-weight: 700;
  color: var(--fg);
}

/*
 * The docked actions. Fixed rather than sticky: the list above scrolls and these two must not
 * move as it grows, which is the whole reason they are not inline in the list.
 *
 * `.container.has-dock` pays for the space so the last card is never hidden underneath, and
 * the safe-area inset keeps it clear of the iPhone home indicator.
 */
.container.has-dock { padding-bottom: calc(var(--sp-7) + 3.5rem); }

.dock {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 20;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4) calc(var(--sp-3) + env(safe-area-inset-bottom));
  background: var(--surface);
  border-top: 1px solid var(--line);
  box-shadow: 0 -4px 16px rgba(16, 24, 20, 0.06);
}

@media (min-width: 820px) {
  /* On a desktop there is no thumb and no scroll to fight, so the bar stops spanning the
     window and sits with the content. */
  .dock {
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    width: min(var(--page-max), 100%);
    border-radius: var(--r-lg) var(--r-lg) 0 0;
    border: 1px solid var(--line);
    border-bottom: none;
    grid-template-columns: auto auto;
    justify-content: end;
  }
}

/* <dialog> gives us focus trapping, Escape and the top layer for free. */
.sheet-dialog {
  width: min(26rem, calc(100vw - 2rem));
  padding: var(--sp-5);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  color: var(--fg);
  box-shadow: var(--shadow-lg);
}

.sheet-dialog::backdrop { background: rgba(15, 23, 19, 0.45); }
.sheet-dialog h2 { margin: 0 0 var(--sp-2); font-size: var(--fs-600); }
.sheet-dialog p { margin: 0 0 var(--sp-4); color: var(--fg-2); font-size: var(--fs-300); }

.field { display: block; margin-bottom: var(--sp-4); }

.field > span {
  display: block;
  margin-bottom: var(--sp-1);
  font-size: var(--fs-100);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--fg-3);
}

.dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--sp-2);
}

/* ============================================================ 16. per-pool settings */

.settings-card { display: flex; flex-direction: column; gap: var(--sp-5); }
.settings-card .field { margin-bottom: 0; }

/* A handle is four characters that people compare down a column, so it gets the treatment
   the sheet gives them: monospaced, spaced out, and unmistakably not a name field. */
.input-handle {
  max-width: 8rem;
  font-family: var(--font-mono);
  font-size: var(--fs-500);
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

/* `small` is inline, so a hint after a narrow input wraps AROUND it -- the handle field ended
   up with a paragraph curled into the space beside an 8rem box. */
.field .hint { display: block; }

fieldset.field { border: 0; padding: 0; margin: 0; }

.field-legend {
  display: block;
  margin-bottom: var(--sp-2);
  font-size: var(--fs-100);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--fg-3);
}

/* Radios as rows you can hit with a thumb, not 13px dots with a label beside them. */
.choice {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  margin-bottom: var(--sp-2);
  padding: var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
  font-weight: 400;
  cursor: pointer;
  transition: border-color var(--t-fast), background var(--t-fast);
}

.choice:hover { border-color: var(--line-2); }
.choice:has(input:checked) { border-color: var(--brand-2); background: var(--brand-soft); }
.choice input { margin-top: 0.2em; flex: none; }
.choice-body { display: flex; flex-direction: column; gap: 2px; }
.choice-title { font-weight: 700; font-size: var(--fs-400); }
.choice-note { font-size: var(--fs-200); color: var(--fg-2); }

.form-actions { display: flex; justify-content: flex-end; gap: var(--sp-2); }

/* Leaving a pool is not undoable, so it does not sit in the same box as a name field. */
.danger-card {
  margin-top: var(--sp-5);
  border-color: color-mix(in srgb, var(--lose) 35%, var(--line));
}

.danger-card h2 { font-size: var(--fs-500); color: var(--lose); }
.danger-card p { color: var(--fg-2); font-size: var(--fs-300); }

/* ============================================================ 17. the pool sheet */

/*
 * The page everyone actually looks at, and the one that has to survive 18 players x 16 games
 * on a phone. Everything here is sized so a column of eighteen 4-character handles wraps into
 * three rows rather than scrolling sideways -- scrolling sideways to find your own column is
 * the thing the old week-by-player grid made you do.
 */

.sheet-head { margin-bottom: var(--sp-4); }
.sheet-head .page-header { margin-bottom: var(--sp-3); }

.week-strip {
  display: flex;
  gap: var(--sp-2);
  overflow-x: auto;
  padding-bottom: var(--sp-2);
  scrollbar-width: none;
}

.week-strip::-webkit-scrollbar { display: none; }

.week-chip {
  flex: none;
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--fg-2);
  font-size: var(--fs-200);
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
}

.week-chip[aria-current="page"] {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--fg-on-fill);
}

@media (min-width: 820px) {
  /* Wide enough to show the whole season at once, so it wraps instead of scrolling. */
  .week-strip { flex-wrap: wrap; overflow-x: visible; }
}

/*
 * Your week, in separate columns. They are not summed into one headline on purpose -- see the
 * note in views/pools/sheet.ejs. Explicit equal tracks so the figures line up as a row of
 * numbers rather than sizing themselves to their own labels.
 */
.week-summary {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
  padding: var(--sp-3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
}

.ws-cell { display: flex; flex-direction: column; gap: 2px; min-width: 0; }

.ws-label {
  font-size: var(--fs-100);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--fg-3);
}

.ws-figure {
  font-size: var(--fs-600);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

.ws-figure.up { color: var(--win); }
.ws-figure.down { color: var(--lose); }
.ws-figure.flat { color: var(--fg-2); }
.ws-figure.soft { opacity: 0.72; }

.ws-note { font-size: var(--fs-200); color: var(--fg-3); }

/* The one that answers "so where am I this week" gets the edge. */
.ws-total { border-left: 2px solid var(--line); padding-left: var(--sp-3); }

.sec-label {
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-100);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--fg-3);
}

.sheet-open-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--sp-3);
  flex-wrap: wrap;
}

.closes { margin: 0 0 var(--sp-2); display: flex; align-items: baseline; gap: var(--sp-2); }

.closes-label {
  font-size: var(--fs-100);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--fg-3);
}

.closes-value {
  font-size: var(--fs-400);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--brand-text);
}

.games { display: flex; flex-direction: column; gap: var(--sp-3); }

.game {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
}

.game-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--line);
}

.game-head .kick { font-size: var(--fs-200); color: var(--fg-3); }
.game-head .kick b { color: var(--fg-2); font-variant-numeric: tabular-nums; }

.game-head .risk {
  font-size: var(--fs-200);
  font-weight: 700;
  color: var(--brand-text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ---------- open: two targets, tap to save ---------- */

.sides { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: var(--line); }

.side {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-1);
  min-height: 3.75rem;      /* a thumb, and two of them side by side on the narrowest phone */
  padding: var(--sp-3) var(--sp-2);
  border: 0;
  border-radius: 0;
  background: var(--surface);
  color: var(--fg);
}

.side:hover { background: var(--surface-2); color: var(--fg); }
.side .abbr { font-size: var(--fs-500); font-weight: 800; letter-spacing: -0.01em; }
.side .spread { font-size: var(--fs-200); color: var(--fg-3); font-variant-numeric: tabular-nums; }

.side[aria-pressed="true"],
.side[aria-pressed="true"]:hover { background: var(--brand); color: var(--fg-on-fill); }
.side[aria-pressed="true"] .spread { color: var(--fg-on-fill); opacity: 0.75; }

/* ---------- locked: the split, the handles, the money ---------- */

.split { display: flex; height: 6px; background: var(--line); }
.split i { display: block; }
.split .split-a { background: var(--brand); }
.split .split-b { background: var(--fg-3); }

.split-nums {
  display: flex;
  justify-content: space-between;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3) 0;
  font-size: var(--fs-200);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--fg-3);
}

.cols { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: var(--line); }

.col {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-3);
  background: var(--surface);
}

.col.won { background: var(--win-soft); }
/* Your side of a game you lost. Replaces the winner's green on that game (views/pools/sheet.ejs).
   Stronger than --lose-soft: at 10% the red sits on the warm ground as tan, not as a loss. */
.col.you-lost { background: color-mix(in srgb, var(--lose) 17%, var(--surface)); }

.col-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-2); }
.col-head .col-team { font-size: var(--fs-400); font-weight: 800; }
.col-head .col-spread { font-size: var(--fs-200); color: var(--fg-3); font-variant-numeric: tabular-nums; }

.outcome {
  font-size: var(--fs-100);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
}

.outcome.up { color: var(--win); }
.outcome.down { color: var(--lose); }
.outcome.flat { color: var(--fg-3); }

/*
 * A PROJECTION IS NOT A RESULT. "Leading" while a game is being played must not look like
 * "Covered" after it has paid out, or a page refresh reads as money moving. Same hue so the
 * meaning carries, hollowed out so the certainty does not.
 */
.outcome.soft { font-weight: 700; opacity: 0.72; }
.per b.soft { font-weight: 700; opacity: 0.72; }

.live-dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-right: 5px;
  border-radius: 50%;
  background: var(--lose);
  vertical-align: middle;
}

@media (prefers-reduced-motion: no-preference) {
  .live-dot { animation: live-pulse 2s ease-in-out infinite; }
}

@keyframes live-pulse { 50% { opacity: 0.3; } }

/* A game being played is the one you look at first. */
.game:has(.live-dot) { border-color: var(--lose-soft); box-shadow: var(--shadow-sm); }

.who-grid { display: flex; flex-wrap: wrap; gap: 3px; }

.ini {
  padding: 2px 5px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  font-family: var(--font-mono);
  font-size: var(--fs-100);
  font-weight: 700;
  line-height: 1.4;
  color: var(--fg-2);
}

.ini.me { background: var(--brand); border-color: var(--brand); color: var(--fg-on-fill); }
.ini.none { border-style: dashed; color: var(--fg-3); }
.col.won .ini { border-color: var(--win); }
.col.you-lost .ini { border-color: var(--lose); }

.per { margin: 0; font-size: var(--fs-200); color: var(--fg-3); font-variant-numeric: tabular-nums; }
.per b { font-size: var(--fs-400); font-weight: 800; }
.per b.up { color: var(--win); }
.per b.down { color: var(--lose); }
.per b.flat { color: var(--fg-3); }
.per .muted { font-style: italic; }

details.who-all > summary {
  padding: var(--sp-2) var(--sp-3) var(--sp-3);
  cursor: pointer;
  list-style: none;
  font-size: var(--fs-200);
  font-weight: 700;
  color: var(--brand-text);
}

details.who-all > summary::-webkit-details-marker { display: none; }
details.who-all[open] > summary { color: var(--fg-3); }

.who-names { padding: 0 var(--sp-3) var(--sp-3); }
.who-names p { margin: 0 0 var(--sp-1); font-size: var(--fs-200); color: var(--fg-2); }

@media (min-width: 820px) {
  /* Two games abreast on a desktop: 16 games is a long scroll otherwise, and there is room. */
  .games { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; }
}

/* ============================================================ 18. the board */

/*
 * Explicit grid tracks, not `auto`. Each row used to size its own columns, so the rank, the
 * name and the figure landed in a different place on every line depending on how long the
 * name was -- the column of money you scan down was ragged. Alex flagged exactly this on the
 * prototype.
 */

.board { display: flex; flex-direction: column; gap: var(--sp-2); }
.board-entry { border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }

.board-row {
  display: grid;
  grid-template-columns: 2rem minmax(0, 1fr) 5.5rem;
  gap: var(--sp-3);
  align-items: center;
  width: 100%;
  padding: var(--sp-3);
  border: 0;
  border-radius: 0;
  background: var(--surface);
  color: var(--fg);
  text-align: left;
}

.board-row:hover { background: var(--surface-2); color: var(--fg); }
/* The week's board on the sheet does not expand, so it must not look clickable. */
.board-row.static:hover { background: var(--surface); }
.board-row.me { background: var(--brand-soft); }
.board-row.me:hover { background: var(--brand-soft); }

.board-row .rank {
  font-size: var(--fs-400);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--fg-3);
  text-align: right;
}

.board-row .who { display: flex; flex-direction: column; gap: 1px; min-width: 0; }

.board-row .who-name {
  font-size: var(--fs-400);
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.board-row .rec { font-size: var(--fs-200); color: var(--fg-3); font-variant-numeric: tabular-nums; }

.board-row .amt {
  font-size: var(--fs-500);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.amt.up { color: var(--win); }
.amt.down { color: var(--lose); }
.amt.flat { color: var(--fg-3); }

.board-row[aria-expanded="true"] { border-bottom: 1px solid var(--line); }

.weeks { padding: var(--sp-2) var(--sp-3) var(--sp-3); background: var(--surface-2); }

.wk {
  display: flex;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-1) 0;
  font-size: var(--fs-300);
  font-variant-numeric: tabular-nums;
  color: var(--fg-2);
}

.wk .up { color: var(--win); font-weight: 700; }
.wk .down { color: var(--lose); font-weight: 700; }
.wk .flat { color: var(--fg-3); }

/* ---------- season notes: the fun stats, moved off the old leaderboard ---------- */

.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: var(--sp-3);
  margin-bottom: var(--sp-5);
}

.stat {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--sp-3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  min-width: 0;
}

.stat-label {
  font-size: var(--fs-100);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--fg-3);
}

.stat-figure {
  font-size: var(--fs-600);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

/* A tie lists everybody, so this has to wrap rather than clip. */
.stat-who { font-size: var(--fs-200); color: var(--fg-2); overflow-wrap: anywhere; }

/* ============================================================ 19. pool admin */

/*
 * THE POOL'S OWN NAVIGATION, under the page title on all four pages inside a pool.
 *
 * Wraps on a narrow screen rather than scrolling sideways -- four destinations plus the pool
 * name does not fit one phone line, and a nav you have to scroll to see is a nav people miss.
 * The current page is marked rather than removed, so the row is the same shape everywhere and
 * you can see where you are without reading the URL.
 */
.pool-nav {
  margin-top: var(--sp-3);
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}

/*
 * BUTTONS, NOT A BYLINE.
 *
 * These were 13px text links joined by interpuncts -- "Pool name . The sheet . Standings . Your
 * settings". That reads as a caption, and the four things people navigate a pool with did not
 * look like controls at all. Pills with a real border and a 44px minimum height do: 44px is the
 * smallest target a thumb hits reliably, and most of this pool picks on a phone.
 */
.pool-nav a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 var(--sp-4);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--fg);
  font-size: var(--fs-400);
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
}

.pool-nav a:hover {
  background: var(--surface-2);
  border-color: var(--line-2);
  text-decoration: none;
}

/* The pool's name is the way back up, so it reads as the parent rather than a sibling. */
.pool-nav .pool-nav-home { font-weight: 700; }

/*
 * Where you are. Not a colour change alone -- colour by itself is not something everyone can
 * see, so the current page is a filled pill: it differs in fill, contrast AND cursor.
 */
.pool-nav a.is-current {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--fg-on-fill);
  cursor: default;
}
.pool-nav a.is-current:hover {
  background: var(--brand);
  border-color: var(--brand);
  text-decoration: none;
}

/* Facts about the WEEK, below the pool's navigation on the sheet. */
.week-facts { margin: var(--sp-1) 0 0; color: var(--fg-2); font-size: var(--fs-300); }
.week-print { margin: var(--sp-2) 0 0; }


/*
 * WEEK VALUES. Rows, not a table. A four-column table of 22 weeks needs sideways scrolling on
 * a phone, and the thing being edited ends up off-screen from the week it belongs to.
 *
 * The game count is spelled out rather than sitting under a "Games" heading. Alex read "155
 * games" on the old table and took it for a season total; "16 games this week" cannot be read
 * that way.
 */
.week-values { display: flex; flex-direction: column; }

.wv-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--sp-3);
  align-items: center;
  padding: var(--sp-3) 0;
  border-bottom: 1px solid var(--line);
}

.wv-row:last-child { border-bottom: 0; }
.wv-week { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.wv-name { font-size: var(--fs-400); font-weight: 700; }
.wv-meta { font-size: var(--fs-200); color: var(--fg-3); }

.wv-value { display: flex; align-items: center; gap: var(--sp-2); }
.wv-figure { font-size: var(--fs-500); font-weight: 800; font-variant-numeric: tabular-nums; }

.week-value-form { display: flex; align-items: center; gap: var(--sp-1); flex-wrap: wrap; }
.wv-currency { color: var(--fg-3); font-weight: 700; }
.week-value-form input { width: 5.5rem; text-align: right; font-variant-numeric: tabular-nums; }
.wv-error { flex-basis: 100%; font-size: var(--fs-200); color: var(--lose); text-align: right; }

/*
 * THE ROSTER at eighteen people. The old table put two buttons in a third column and pushed
 * the names into a narrow strip; this gives each person a row, the handle they appear under on
 * the sheet, and the controls underneath on a phone rather than beside.
 */
.roster { display: flex; flex-direction: column; }

.roster-row {
  display: grid;
  grid-template-columns: 3rem minmax(0, 1fr);
  gap: var(--sp-2) var(--sp-3);
  align-items: center;
  padding: var(--sp-2) var(--sp-2);
  border-bottom: 1px solid var(--line);
}

.roster-row:last-child { border-bottom: 0; }
.roster-row.me { background: var(--brand-soft); border-radius: var(--r-sm); }

.roster-who { display: flex; align-items: center; gap: var(--sp-2); min-width: 0; }

.roster-name {
  font-size: var(--fs-400);
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.roster-actions { grid-column: 2; display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.roster-actions form { margin: 0; }

@media (min-width: 620px) {
  /* Room for the controls beside the name instead of under it. */
  .roster-row { grid-template-columns: 3rem minmax(0, 1fr) auto; }
  .roster-actions { grid-column: 3; }
}

/* ---------- invites: one record, a link and a code ---------- */

.invite-form {
  display: flex;
  align-items: flex-end;
  gap: var(--sp-3);
  flex-wrap: wrap;
  margin-bottom: var(--sp-4);
}

.invite-form .field { margin-bottom: 0; }
.invite-form input { width: 9rem; }

.invites { display: flex; flex-direction: column; gap: var(--sp-3); }

.invite {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-3);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
}

.invite.dead { opacity: 0.55; }
.invite-main { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
.invite-state { font-size: var(--fs-200); color: var(--fg-3); }

.invite-link { display: flex; gap: var(--sp-2); align-items: center; }
.invite-link input {
  flex: 1 1 auto;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-200);
}

.invite form { margin: 0; align-self: flex-start; }

/* ============================================================ 20. utilities */

/* Present for a screen reader, absent on screen. Used where a visible label would just repeat
   the row it sits in -- the week-value inputs. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.text-center { text-align: center; }
.text-right { text-align: right; }
.text-accent { color: var(--brand-text); }
.text-warning { color: var(--warn); }

.mb-0 { margin-bottom: 0; }
.mb-1 { margin-bottom: var(--sp-2); }
.mb-2 { margin-bottom: var(--sp-4); }
.mb-3 { margin-bottom: var(--sp-5); }
.mt-0 { margin-top: 0; }
.mt-1 { margin-top: var(--sp-2); }
.mt-2 { margin-top: var(--sp-4); }
.mt-3 { margin-top: var(--sp-5); }
.m-0 { margin: 0; }

.p-0 { padding: 0; }
.p-1 { padding: var(--sp-2); }
.p-2 { padding: var(--sp-4); }
.p-3 { padding: var(--sp-5); }

.flex { display: flex; }
.flex-column { flex-direction: column; }
.flex-wrap { flex-wrap: wrap; }
.align-center { align-items: center; }
.justify-center { justify-content: center; }
.justify-between { justify-content: space-between; }
.gap-1 { gap: var(--sp-2); }
.gap-2 { gap: var(--sp-4); }
.gap-3 { gap: var(--sp-5); }

.bg-card { background: var(--surface); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
