/* ── Reset & Base ─────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* Visible keyboard focus everywhere — only shows for keyboard/switch nav,
   never on a mouse click, so it can't undo any component's existing hover polish. */
:focus-visible {
  outline: 2px solid var(--green-mid);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Respect the OS-level "reduce motion" preference before any animation or
   transition is defined below — this is the one rule that has to win over
   everything else, so it's declared once, globally, rather than repeated
   as an exception on each component. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* Skip-to-content link: invisible until a keyboard user tabs to it, so a
   screen-reader/keyboard visitor doesn't have to tab through the full nav
   on every single page just to reach the actual content. */
/* Clipped to 1px rather than pushed above the viewport with a negative
   `top` — that earlier approach put real box geometry above y=0 in the
   page, which Mac trackpad/mouse elastic overscroll (rubber-banding past
   the top of the page) could briefly reveal as visible text. Clipping
   keeps it truly invisible in normal document flow at all times, not just
   off-screen, so there's no negative-space geometry left for overscroll
   to expose. */
.skip-link {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.skip-link:focus {
  position: fixed;
  top: .5rem;
  left: .5rem;
  width: auto;
  height: auto;
  margin: 0;
  overflow: visible;
  clip: auto;
  white-space: normal;
  z-index: 100000;
  background: var(--header-bg);
  color: var(--white);
  padding: .6rem 1rem;
  border-radius: var(--radius);
  font-weight: 600;
  font-size: .9rem;
}

:root {
  /* Brand ramp — cobalt and silver (kept the historical green/gold token
     names since hundreds of rules reference them by name; only the hex
     values changed, so the whole app rebrands from this one block). */
  --green-dark:   #1e40af;
  --green-mid:    #1f4fc7; /* darkened from #2563eb (5.17:1) to 7:1+ (AAA) — primary buttons/links get read outdoors on the course */
  --green-light:  #60a5fa;
  /* Dedicated background for anything that puts white text on it
     (.btn-primary, .hole-pip.scored) — deliberately NOT var(--green-mid),
     because --green-mid also serves as the link/accent color and dark
     mode retunes that to a brighter blue for legibility against a dark
     page. A brighter background would then fail contrast with white
     text on top of it. Same literal value works for both themes (it's
     already the light-mode --green-mid value, already AAA-tested with
     white text at 7:1), so no dark-mode override is needed. */
  --btn-primary-bg: #1f4fc7;
  /* Same double-duty problem as --green-mid above, but for --green-dark:
     its dark-mode override (#3b82f6) is tuned to work as a badge/text
     color against the dark page, which breaks every place that instead
     uses it as a solid background behind white text (table headers, the
     active tab, score-entry banners, the nav bar). Dedicated token,
     reusing --green-dark's own light-mode value (already holds 8.7:1+
     with white). Same value works for both themes. */
  --header-bg: #1e40af;
  /* Same double-duty problem again, for --gray-400: its own comment says
     it was tuned as a TEXT color ("AAA 6.85:1 on white" / dark-mode's
     override "AAA 6.23:1 on surface") — correct for muted labels, but
     .rank-2 (2nd-place standings badge) and 2 hover states use it as a
     background behind white text instead, which the dark-mode override
     (a light gray, #93a2b3) breaks. Reuses the light-mode --gray-400
     value, already proven at 6.85:1 with white. */
  --gray-badge-bg: #4f5c69;
  /* Same double-duty problem again, for --red: its dark-mode override
     (a lighter salmon, #e57268) is tuned to read as TEXT against the
     dark page, not as a background behind white text — .btn-danger
     (every delete/reset/danger button app-wide) used it that way and
     measured 3.03:1. Reuses --red's light-mode value, already 5.45:1
     with white. */
  --btn-danger-bg: #c0392b;
  /* Same double-duty problem, discovered in a different shape: PHP/JS
     variables (not literal `background: var(--x)` strings, so the
     earlier stylesheet/file greps for that exact pattern missed
     these) that hold --indigo-text or --gray-500 and later feed a
     "T1"/"T2" team badge's background with white text on top. Both
     source tokens are tuned as TEXT against the dark page. Dedicated
     background token, reusing --indigo-text's light-mode value
     (already 7.3:1+ with white). --gray-500's equivalent case reuses
     the existing --gray-badge-bg from the --gray-400 fix above (the
     two grays are near-identical, no need for a second token). */
  --indigo-badge-bg: #3b4fa8;
  --green-pale:   #eaf1fc;
  --gold:         #64748b;
  --gold-light:   #e2e8f0;
  --gold-text:    #334155;
  --red:          #c0392b;
  --red-pale:        #fde8e8;
  --red-pale-border: #f5c6c6;
  /* A genuinely green pair, for trend/delta encoding only (sparklines, "+N
     this week" badges) — --green-dark/--green-pale above are the app's brand
     ramp and, per the rebrand note, are actually blue, not green. Reusing
     them for "improving" trend color made positive changes render in the
     same blue as ordinary brand chrome, indistinguishable at a glance and
     easy to lose entirely against a blue header. */
  --trend-good:      #15803d;
  --trend-good-pale: #dcfce7;
  /* Amber "highlighted row / needs attention" tint (sub-player rows, pending-
     invite badges, etc.) — a real token pair instead of the hardcoded
     literal #fffbeb scattered across admin.php, which stayed pale-on-pale
     in dark mode (unset text color inherits the page's light-on-dark
     default, landing on this same pale background = nearly invisible). */
  --amber-pale: #fffbeb;
  --amber-text: #92400e;
  /* Indigo "team 2 / opponent accent" tint (tournament team cards, roster
     pills, live score boxes) — a real token trio instead of the hardcoded
     literal #eef1ff, which stayed pale-on-pale in dark mode exactly like the
     amber case above (unset/gray text on a frozen-light indigo fill). The
     matching --green-pale is already dark-aware and covers "team 1". */
  --indigo-pale:        #eef1ff;
  --indigo-pale-border: #a5b4fc;
  --indigo-text:        #3b4fa8;
  --blue:         #2471a3;
  --blue-pale:        #e8f0f8;
  --blue-pale-border: #b8ceea;
  --gray-50:      #fafbfc;
  --gray-100:     #f4f6f8;
  --gray-200:     #e5e9ed;
  --gray-300:     #cbd2d9;
  --gray-400:     #4f5c69; /* WCAG AAA 6.85:1 on white (was 4.91:1, barely AA) — muted labels/captions read outdoors in direct sun */
  --gray-500:     #4c5764; /* WCAG AA 4.5:1+ on white — matches the old green-tinted gray-500's contrast, re-hued cool */
  --gray-700:     #37414c;
  --white:        #ffffff; /* always literal white — used where text sits on a colored fill (buttons, nav, headers), a role that doesn't change with theme. Card/panel backgrounds use --surface instead, which does. */
  --surface:      #ffffff; /* card/panel backgrounds — the token that actually swaps for dark mode */
  --shadow-sm:    0 1px 3px rgba(0,0,0,.10);
  --shadow-md:    0 4px 12px rgba(0,0,0,.12);
  --radius:       8px;
  --radius-lg:    12px;

  /* Back-compat aliases. These names are used across the app's inline styles
     (they pre-date the token cleanup) but were never actually defined, so
     every `var(--X)` below silently fell back to an inherited value — muted
     text rendered at full body strength, and "light panel" backgrounds /
     hairline borders vanished entirely (transparent). Each alias points at a
     real token, so they resolve lazily and adapt to dark mode for free. */
  --gray-600:     var(--gray-700);
  --gray-800:     var(--gray-700);
  --text-dark:    var(--gray-700);
  --text-muted:   var(--gray-500);
  --border:       var(--gray-200);
  --bg-light:     var(--gray-50);
  --bg-card:      var(--surface);
  --green:        var(--trend-good); /* a genuine green — used for "under par" / positive deltas; NOT the brand ramp (which is actually blue post-rebrand) */
  --color-danger: var(--red);

  /* Tell the UA to render native controls (select + its option popup, date
     pickers, checkboxes, scrollbars) in the current theme. Without this a
     <select> with a dark background but no explicit text color renders its
     text near-black on macOS/Chrome = unreadable in dark mode. */
  color-scheme: light;
}

/* Dark mode: follows the OS/browser preference automatically (no manual
   toggle in the nav, backed by assets/js/theme-init.js + app.js, storing an
   explicit choice in localStorage as `data-theme` on <html>). Every color
   below is the same token used throughout style.css and every page's inline
   styles, so these two blocks are what make the whole app dark-aware rather
   than needing per-page changes. Brand green is intentionally brighter here
   than in light mode — set against a dark canvas it needs the lift to stay
   legible as both text and fills, which is also just how dark-mode brand
   color usually reads (Slack, Linear, Discord all do the same "more
   saturated at night" thing).

   Structured for three states: no explicit choice follows the OS/browser
   preference (the media query, guarded so an explicit *light* choice can
   still override an OS dark preference); an explicit choice is stamped as
   data-theme on <html> and wins outright in either direction. The same dark
   palette is intentionally duplicated in both blocks rather than shared via
   a preprocessor — plain CSS custom properties can't compose across a media
   query and an attribute selector, and this app has no build step to add one. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --green-dark:   #3b82f6;
    --green-mid:    #60a5fa;
    --green-light:  #93c5fd;
    --green-pale:   #16213a;
    --gold-light:   #2a3441;
    --gold-text:    #cbd5e1;
    --red:          #e57268;
    --red-pale:        #3a1f1c;
    --red-pale-border: #5c3230;
    --trend-good:      #4ade80;
    --trend-good-pale: #14321f;
    --amber-pale: #3a2f14;
    --amber-text: #fbbf24;
    --indigo-pale:        #20264a;
    --indigo-pale-border: #3f4780;
    --indigo-text:        #a5b4fc;
    --blue:         #4a9fd8;
    --blue-pale:        #1c2a35;
    --blue-pale-border: #2f4a5c;
    --gray-50:      #202832;
    --gray-100:     #12171e;
    --gray-200:     #2f3b4a;
    --gray-300:     #3f4f60;
    --gray-400:     #93a2b3; /* WCAG AAA 6.23:1 on surface, was 4.59:1 */
    --gray-500:     #9dacba;
    --gray-700:     #e9edf2;
    --surface:      #1a2129;
    --shadow-sm:    0 1px 3px rgba(0,0,0,.35);
    --shadow-md:    0 4px 14px rgba(0,0,0,.45);
    color-scheme: dark;
  }
}
:root[data-theme="dark"] {
  --green-dark:   #3b82f6;
  --green-mid:    #60a5fa;
  --green-light:  #93c5fd;
  --green-pale:   #16213a;
  --gold-light:   #2a3441;
  --gold-text:    #cbd5e1;
  --red:          #e57268;
  --red-pale:        #3a1f1c;
  --red-pale-border: #5c3230;
  --trend-good:      #4ade80;
  --trend-good-pale: #14321f;
  --amber-pale: #3a2f14;
  --amber-text: #fbbf24;
  --indigo-pale:        #20264a;
  --indigo-pale-border: #3f4780;
  --indigo-text:        #a5b4fc;
  --blue:         #4a9fd8;
  --blue-pale:        #1c2a35;
  --blue-pale-border: #2f4a5c;
  --gray-50:      #202832;
  --gray-100:     #12171e;
  --gray-200:     #2f3b4a;
  --gray-300:     #3f4f60;
  --gray-400:     #93a2b3; /* WCAG AAA 6.23:1 on surface, was 4.59:1 */
  --gray-500:     #9dacba;
  --gray-700:     #e9edf2;
  --surface:      #1a2129;
  --shadow-sm:    0 1px 3px rgba(0,0,0,.35);
  --shadow-md:    0 4px 14px rgba(0,0,0,.45);
  color-scheme: dark;
}

html { font-size: 16px; }
body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  background: var(--gray-100);
  color: var(--gray-700);
  line-height: 1.5;
  /* Every digit takes the same width, so scores/dollar amounts/points stacked
     in a column actually line up instead of drifting with each row's number
     of "1"s vs "8"s. Applying it once here covers every numeric display in
     the app — scorecards, standings, payouts — with no per-component work. */
  font-variant-numeric: tabular-nums;
}

a { color: var(--green-mid); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ── Top Nav ──────────────────────────────────────────────────────────────── */
.topnav {
  /* 94% opacity + blur reads as "glass" once content scrolls underneath,
     without meaningfully changing the nav's own contrast — white nav text
     stays effectively as legible as it was on the fully solid fill.
     Plain solid fill first as a fallback for any browser that doesn't
     understand color-mix()/backdrop-filter — the later declaration only
     takes over once both are supported, so there's no state where the
     nav loses its background entirely. */
  background: var(--header-bg);
  background: color-mix(in srgb, var(--header-bg) 94%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  color: var(--white);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: .75rem 1.25rem;
  position: sticky;
  top: 0;
  z-index: 100;
  box-shadow: var(--shadow-md);
}
.nav-brand { font-size: 1.1rem; font-weight: 700; color: var(--white); letter-spacing: .01em; display:flex; align-items:center; gap:.5rem; }
.nav-logo  { height: 36px; width: auto; object-fit: contain; }
.nav-links  { display: flex; align-items: center; gap: 1.2rem; font-size: .9rem; }
.nav-links a { color: rgba(255,255,255,.85); font-weight: 500; }
.nav-links a:hover, .nav-links a.active { color: var(--white); text-decoration: none; border-bottom: 2px solid var(--gold); }
.nav-user      { color: rgba(255,255,255,.65); font-size: .85rem; }
.nav-logout    { color: rgba(255,255,255,.75) !important; font-size: .85rem; }
.nav-hamburger { display: none; }

/* Light/dark toggle — auto-inserted into any .topnav or .marketing-nav by
   assets/js/app.js (see initThemeToggle()), always visible (not folded into
   the mobile .nav-links collapse) since it's a quick global preference, not
   a navigation destination. */
.theme-toggle {
  background: transparent;
  border: 1.5px solid rgba(255,255,255,.35);
  border-radius: 6px;
  color: var(--white);
  width: 34px;
  height: 34px;
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.theme-toggle:hover { background: rgba(255,255,255,.12); }

/* ── Page ─────────────────────────────────────────────────────────────────── */
.page-content { max-width: 960px; margin: 0 auto; padding: 1.5rem 1rem 3rem; }
.page-title   { font-size: 1.5rem; font-weight: 700; color: var(--green-dark); margin-bottom: 1.25rem; }
.section-title { font-size: 1.1rem; font-weight: 600; color: var(--green-dark); margin: 1.5rem 0 .75rem; }

/* ── Auth Page ────────────────────────────────────────────────────────────── */
.auth-page {
  min-height: 100vh;
  background: linear-gradient(145deg, var(--green-dark) 0%, var(--green-mid) 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}
.auth-card {
  background: var(--surface);
  border-radius: var(--radius-lg);
  padding: 2.5rem 2rem;
  width: 100%;
  max-width: 380px;
  box-shadow: var(--shadow-md);
  text-align: center;
}
.auth-logo    { font-size: 3rem; margin-bottom: .5rem; }
.auth-title   { font-size: 1.4rem; font-weight: 700; color: var(--green-dark); }
.auth-subtitle { color: var(--gray-400); margin-bottom: 1.75rem; }

/* ── Forms ────────────────────────────────────────────────────────────────── */
/* Sizing floor: nothing below .78rem for body text, .8rem for interactive controls. */
.form-group  { text-align: left; margin-bottom: 1rem; }
.form-group label { display: block; font-size: .85rem; font-weight: 600; margin-bottom: .35rem; color: var(--gray-700); }
.form-group input,
.form-group select,
.form-group textarea {
  width: 100%;
  border: 1.5px solid var(--gray-200);
  border-radius: var(--radius);
  padding: .75rem .85rem;
  font-size: 1rem;
  color: var(--gray-700);
  background: var(--surface);
  transition: border-color .15s;
}
.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
  outline: none;
  border-color: var(--green-mid);
  box-shadow: 0 0 0 3px rgba(46,125,79,.12);
}
.form-row    { display: flex; gap: .75rem; }
.form-row .form-group { flex: 1; }

/* ── Buttons ──────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .4rem;
  padding: .6rem 1.2rem;
  min-height: 44px;
  border-radius: var(--radius);
  font-size: .9rem;
  font-weight: 600;
  cursor: pointer;
  border: none;
  text-decoration: none !important;
  transition: background .15s, transform .1s, box-shadow .15s;
  white-space: nowrap;
}
.btn:active { transform: scale(.97); }
.btn-primary   { background: var(--btn-primary-bg); color: var(--white); }
.btn-primary:hover, .btn-secondary:hover { transform: translateY(-1px); box-shadow: var(--shadow-sm); }
.btn-primary:hover { background: var(--header-bg); }
.btn-secondary { background: var(--gray-200); color: var(--gray-700); }
.btn-secondary:hover { background: var(--gray-badge-bg); color: var(--white); }
.btn-gold      { background: var(--gold); color: var(--white); }
.btn-gold:hover { background: #b8860f; }
.btn-danger    { background: var(--btn-danger-bg); color: var(--white); }
.btn-ghost     { background: transparent; color: var(--green-mid); border: 1.5px solid var(--green-mid); }
.btn-ghost:hover { background: var(--green-pale); }
.btn-block     { display: flex; width: 100%; }
.btn-sm        { padding: .45rem .9rem; font-size: .88rem; }

/* ── Cards ────────────────────────────────────────────────────────────────── */
.card {
  background: var(--surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: 1.25rem;
  margin-bottom: 1rem;
  transition: box-shadow .18s ease;
}
.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1rem;
  padding-bottom: .75rem;
  border-bottom: 1.5px solid var(--gray-200);
}
.card-title { font-size: 1rem; font-weight: 700; color: var(--green-dark); }

/* ── Dashboard ────────────────────────────────────────────────────────────── */
.dashboard-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.25rem; margin-top: 1rem; }
@media (max-width: 600px) { .dashboard-grid { grid-template-columns: 1fr; } }

.dash-card {
  background: var(--surface);
  border-radius: var(--radius-lg);
  padding: 1.75rem 1.5rem;
  box-shadow: var(--shadow-sm);
  border-top: 4px solid var(--green-mid);
  text-align: center;
}
.dash-card--tournament { border-top-color: var(--gold); }
.dash-card--scorecard  { border-top-color: var(--blue); }
/* Deliberately understated vs. a real league's solid card — a dashed border
   and no shadow read as "add something new" rather than competing visually
   with the leagues that already exist (choose_account.php's multi-league picker). */
.dash-card--add {
  background: transparent;
  border: 2px dashed var(--gray-300);
  border-top: 2px dashed var(--gray-300);
  box-shadow: none;
}
.dash-card__icon { font-size: 2.5rem; margin-bottom: .5rem; }
.dash-card h2    { font-size: 1.2rem; font-weight: 700; color: var(--green-dark); margin-bottom: .4rem; }
.dash-card--add h2 { color: var(--gray-500); }
.dash-meta       { font-size: .85rem; color: var(--gray-400); margin-bottom: .25rem; }
.dash-actions    { margin-top: 1.25rem; display: flex; gap: .6rem; flex-wrap: wrap; justify-content: center; }

/* ── Alerts ───────────────────────────────────────────────────────────────── */
.alert { padding: .75rem 1rem; border-radius: var(--radius); font-size: .9rem; margin-bottom: 1rem; }
.alert-error   { background: var(--red-pale); color: var(--red); border: 1px solid var(--red-pale-border); }
.alert-success { background: var(--green-pale); color: var(--green-dark); border: 1px solid #b8ddc7; }
.alert-info    { background: var(--blue-pale); color: var(--blue); border: 1px solid var(--blue-pale-border); }

/* ── Tables ───────────────────────────────────────────────────────────────── */
/* Scroll-shadow hint: fades in on either edge only while there's more table
   to see in that direction, so a horizontally-scrollable table doesn't read
   as "that's all the data" on a phone. Pure CSS — background-attachment:local
   scrolls the white cover with the content while the shadow layers stay fixed
   to the viewport edge. */
.table-wrap {
  overflow-x: auto;
  background:
    linear-gradient(to right, var(--surface) 30%, rgba(255,255,255,0)) left,
    linear-gradient(to left, var(--surface) 30%, rgba(255,255,255,0)) right,
    linear-gradient(to right, rgba(0,0,0,.12), rgba(0,0,0,0)) left,
    linear-gradient(to left, rgba(0,0,0,.12), rgba(0,0,0,0)) right;
  background-repeat: no-repeat;
  background-color: var(--surface);
  background-size: 32px 100%, 32px 100%, 12px 100%, 12px 100%;
  background-attachment: local, local, scroll, scroll;
}
table.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: .95rem;
}
.data-table th {
  background: var(--header-bg);
  color: var(--white);
  text-align: left;
  padding: .6rem .75rem;
  font-size: .85rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  white-space: nowrap;
}
.data-table td {
  padding: .6rem .75rem;
  border-bottom: 1px solid var(--gray-200);
  vertical-align: middle;
}
.data-table tr:hover td { background: var(--green-pale); }
.data-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.data-table .center { text-align: center; }

/* ── Handicap History Table ───────────────────────────────────────────────── */
.hcp-history-table thead th {
  vertical-align: bottom;
}
.hcp-history-table thead th .hcp-col-labels {
  display: flex;
  justify-content: space-between;
  font-size: .72rem;
  font-weight: 500;
  margin-top: .2rem;
  border-top: 1px solid rgba(255,255,255,.3);
  padding-top: .2rem;
  gap: .25rem;
}
.hcp-legend-in  { color: rgba(255,255,255,.55); flex: 1; text-align: left; }
.hcp-legend-op  { color: rgba(255,255,255,.9); flex: 1; text-align: center; }
.hcp-legend-out { color: rgba(255,255,255,.55); flex: 1; text-align: right; }
.hcp-history-table thead th.hcp-wk-col,
.hcp-week-cell { border-left: 1px solid var(--gray-200) !important; }
.hcp-week-cell { vertical-align: middle; padding: .35rem .5rem !important; }
.hcp-cell-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .2rem;
  font-size: .82rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.hcp-cell-row .hcp-in  { color: var(--gray-400); min-width: 1.4rem; text-align: left; }
.hcp-cell-row .hcp-op  { font-weight: 700; min-width: 2rem; text-align: center; }
.hcp-cell-row .hcp-op.positive { color: var(--red, #c0392b); }
.hcp-cell-row .hcp-op.negative { color: var(--green-dark); }
.hcp-cell-row .hcp-out { color: var(--green-dark); font-weight: 600; min-width: 1.4rem; text-align: right; }

/* ── Scorecard / Hole Grid ────────────────────────────────────────────────── */
.scorecard-wrap { overflow-x: auto; }
table.scorecard {
  width: 100%;
  border-collapse: collapse;
  font-size: .9rem;
}
.scorecard th, .scorecard td {
  border: 1px solid var(--gray-200);
  text-align: center;
  padding: .45rem .5rem;
  min-width: 36px;
}
.scorecard th { background: var(--header-bg); color: var(--white); font-size: .8rem; }
.scorecard .row-label { text-align: left; font-weight: 600; white-space: nowrap; padding-left: .75rem; min-width: 80px; }
.scorecard td.player-cell { white-space: normal; min-width: 72px; max-width: 80px; padding: .35rem .4rem; }
.scorecard .total-col { background: var(--green-pale); font-weight: 700; }
.scorecard thead th.total-col { background: var(--header-bg); color: var(--white); }
.scorecard .par-row td { background: var(--green-pale); color: var(--green-dark); font-weight: 600; }
.scorecard .hcp-row td { background: var(--gray-100); color: var(--gray-400); font-size: .8rem; }
.scorecard .score-cell { font-weight: 700; }
.scorecard .net-cell   { color: var(--green-mid); }
.scorecard .strokes-dot::after { content: '•'; color: var(--gold); font-size: .6rem; vertical-align: super; }

/* ── Score Entry (mobile) ─────────────────────────────────────────────────── */
.score-entry-page { max-width: 480px; margin: 0 auto; }
.match-banner {
  background: var(--header-bg);
  color: var(--white);
  border-radius: var(--radius-lg);
  padding: 1rem 1.25rem;
  margin-bottom: 1.25rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.match-banner .team-score { font-size: 1.8rem; font-weight: 800; }
.match-banner .vs { font-size: .85rem; opacity: .75; }
.match-banner .team-name { font-size: .82rem; opacity: .85; }

.hole-nav {
  display: flex;
  gap: .5rem;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}
.hole-pip {
  width: 44px; height: 44px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: .85rem; font-weight: 700;
  border: 2px solid var(--gray-200);
  cursor: pointer;
  background: var(--surface);
  color: var(--gray-700);
}
.hole-pip.scored  { background: var(--btn-primary-bg); color: var(--white); border-color: var(--btn-primary-bg); }
.hole-pip.current { border-color: var(--gold); background: var(--gold-light); }

.hole-card {
  background: var(--surface);
  border-radius: var(--radius-lg);
  padding: 1.25rem;
  box-shadow: var(--shadow-sm);
  margin-bottom: 1rem;
}
.hole-info {
  display: flex; gap: 1rem; margin-bottom: 1.25rem;
  justify-content: center; flex-wrap: wrap;
}
.hole-stat { text-align: center; }
.hole-stat .val  { font-size: 1.4rem; font-weight: 800; color: var(--green-dark); line-height: 1; }
.hole-stat .lbl  { font-size: .72rem; color: var(--gray-400); text-transform: uppercase; }

.player-score-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: .75rem 0;
  border-bottom: 1px solid var(--gray-200);
}
.player-score-row:last-child { border-bottom: none; }
.player-info { flex: 1; }
.player-info .name  { font-weight: 600; }
.player-info .strokes { font-size: .78rem; color: var(--gold); }
.score-controls { display: flex; align-items: center; gap: .6rem; }
.score-btn {
  width: 38px; height: 38px;
  border-radius: 50%;
  border: none;
  background: var(--gray-200);
  font-size: 1.3rem;
  font-weight: 700;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background .1s;
}
.score-btn:hover { background: var(--gray-badge-bg); color: var(--white); }
.score-display {
  width: 48px; height: 48px;
  border-radius: var(--radius);
  border: 2px solid var(--gray-200);
  font-size: 1.4rem; font-weight: 800;
  text-align: center;
  background: var(--surface);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
}
.score-display.is-birdie { border-color: var(--green-mid); color: var(--green-mid); }
.score-display.is-eagle  { border-color: var(--gold); color: var(--gold); }
.score-display.is-bogey  { border-color: var(--gray-400); }
.score-display.is-double { border-color: var(--red); color: var(--red); }

.hole-nav-btns { display: flex; gap: .75rem; margin-top: .75rem; }
.hole-nav-btns .btn { flex: 1; }

/* ── Standings ────────────────────────────────────────────────────────────── */
.standings-row td:first-child { font-weight: 700; }
.rank-badge {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; border-radius: 50%;
  font-size: .75rem; font-weight: 700;
}
.rank-1 { background: var(--gold); color: var(--white); }
.rank-2 { background: var(--gray-badge-bg); color: var(--white); }
.rank-3 { background: #cd7f32; color: var(--white); }

/* ── Tabs ─────────────────────────────────────────────────────────────────── */
.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: .35rem;
  border-bottom: 2px solid var(--gray-200);
  padding-bottom: .6rem;
  margin-bottom: 1.25rem;
}
.tab-btn {
  padding: .42rem .9rem;
  border: 1.5px solid var(--gray-200);
  border-radius: 99px;
  background: transparent;
  cursor: pointer;
  font-size: .83rem;
  font-weight: 600;
  color: var(--gray-500);
  white-space: nowrap;
  transition: background .15s, color .15s, border-color .15s;
}
.tab-btn:hover { background: var(--gray-100); color: var(--gray-700); border-color: var(--gray-400); }
.tab-btn.active { background: var(--header-bg); color: #fff; border-color: var(--header-bg); }
.tab-btn.tab-btn-hidden { display: none; }
.tab-pane { display: none; }
.tab-pane.active { display: block; animation: tabIn .15s ease; }
@keyframes tabIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: translateY(0); } }

/* ── Skeleton loading placeholders ───────────────────────────────────────────
   Shapes that mimic the content about to arrive, instead of a bare "Loading…"
   string — reads as faster and more deliberate, and the layout doesn't jump
   when real content swaps in since the skeleton already occupies the same
   space. Respects prefers-reduced-motion via the global rule above. */
.skeleton {
  background: linear-gradient(90deg, var(--gray-100) 25%, var(--gray-200) 37%, var(--gray-100) 63%);
  background-size: 400% 100%;
  animation: skeletonShimmer 1.4s ease infinite;
  border-radius: 6px;
}
@keyframes skeletonShimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
.skeleton-circle { border-radius: 50%; flex-shrink: 0; }
.skeleton-card { background: var(--surface); border-radius: var(--radius-lg); box-shadow: var(--shadow-sm); padding: 1rem 1.25rem; margin-bottom: .75rem; }
.skeleton-row { display: flex; align-items: center; gap: .6rem; margin-bottom: .85rem; }

/* Category row above .tabs — groups a long flat tab bar into fewer top-level
   choices. Purely additive: pages without .tab-groups are unaffected.
   Docked visually onto the .tabs row directly below it (one card, category
   row on top / items on bottom) instead of two separate floating pill bars —
   see the ".tab-groups + .tabs" override below for the item row's half. */
.tab-groups {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem;
  background: var(--gray-50);
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  padding: .75rem .75rem .5rem;
  margin-bottom: 0;
}
.tab-group-btn {
  padding: .5rem 1rem;
  border: 1.5px solid transparent;
  border-radius: 8px;
  background: transparent;
  cursor: pointer;
  font-size: .87rem;
  font-weight: 700;
  color: var(--gray-500);
  white-space: nowrap;
  transition: background .15s, color .15s, border-color .15s, box-shadow .15s;
}
.tab-group-btn:hover { background: var(--gray-200); color: var(--gray-700); }
.tab-group-btn.active { background: var(--surface); color: var(--green-dark); border-color: var(--gray-200); box-shadow: var(--shadow-sm); }

/* The item row directly under a category row: same card, bottom half —
   visually reads as "here are this category's tabs," not a second, separate
   navigation bar. */
.tab-groups + .tabs {
  background: var(--surface);
  border: 1px solid var(--gray-200);
  border-top: none;
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
  padding: .7rem .75rem;
}

/* ── Sub-nav ──────────────────────────────────────────────────────────────── */
/* Underline style (not a filled pill) is deliberate: this is the top-level
   "which page am I on" nav, and everything below it (tab-groups/.tabs) uses
   filled pills for its own active state — giving each level a different
   visual language is what makes it readable as two levels instead of one
   undifferentiated stack of green buttons. */
.subnav {
  display: flex; gap: .1rem; flex-wrap: wrap;
  background: var(--surface);
  border-radius: var(--radius);
  padding: .5rem .6rem 0;
  margin-bottom: 1.25rem;
  box-shadow: var(--shadow-sm);
  border-bottom: 1px solid var(--gray-200);
}
.subnav a {
  padding: .55rem .7rem .6rem;
  border-radius: calc(var(--radius) - 2px) calc(var(--radius) - 2px) 0 0;
  font-size: .88rem; font-weight: 500;
  color: var(--gray-600);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.subnav a:hover { background: var(--gray-100); color: var(--green-dark); text-decoration: none; }
.subnav a.active { color: var(--green-dark); font-weight: 700; border-bottom-color: var(--green-dark); }

/* ── Match Result ─────────────────────────────────────────────────────────── */
.result-grid { display: grid; grid-template-columns: 1fr auto 1fr; gap: .5rem; align-items: center; }
.result-team { text-align: center; }
.result-score { font-size: 2rem; font-weight: 900; text-align: center; }
.win-highlight { color: var(--green-mid); }
.loss-dim      { color: var(--gray-400); }
.pts-breakdown { display: flex; gap: .5rem; justify-content: center; flex-wrap: wrap; margin-top: .5rem; }
.pts-chip {
  padding: .25rem .6rem;
  border-radius: 99px;
  font-size: .78rem;
  font-weight: 600;
  background: var(--gray-200);
  color: var(--gray-700);
}
.pts-chip.win { background: var(--green-pale); color: var(--green-dark); }
.pts-chip.tie { background: var(--gold-light); color: var(--gold-text); }

/* ── Compact Matchup Row (standings recent results) ───────────────────────── */
.matchup-row {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: .25rem .75rem;
  align-items: center;
  padding: .55rem .9rem;
  border-bottom: 1px solid var(--gray-100);
}
.matchup-row:last-of-type { border-bottom: none; }
.mr-left  { text-align: right; }
.mr-right { text-align: left; }
.mr-name {
  font-weight: 700;
  font-size: .88rem;
  line-height: 1.2;
  display: block;
}
.mr-win  .mr-name { color: var(--green-dark); }
.mr-loss .mr-name { color: var(--gray-400); }
.mr-players {
  font-size: .72rem;
  color: var(--gray-400);
  display: block;
  margin-top: .05rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 18ch;
}
.mr-left  .mr-players { margin-left: auto; }
.mr-center { text-align: center; }
.mr-score-line {
  font-size: 1.15rem;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -.02em;
  white-space: nowrap;
}
.mr-s-win  { color: var(--green-mid); }
.mr-s-loss { color: var(--gray-400); }
.mr-dash   { color: var(--gray-300); margin: 0 .2rem; font-weight: 400; }
.mr-chips {
  display: flex;
  gap: .2rem;
  justify-content: center;
  margin-top: .25rem;
  flex-wrap: nowrap;
}
.mr-chip {
  font-size: .78rem;
  font-weight: 600;
  padding: .15rem .5rem;
  border-radius: 99px;
  background: var(--gray-100);
  color: var(--gray-500);
  white-space: nowrap;
}
.mr-chip.win { background: var(--green-pale); color: var(--green-dark); }
.mr-chip.tie { background: var(--gold-light); color: var(--gold-text); }

/* ── Payout Cards ─────────────────────────────────────────────────────────── */
.payout-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: .75rem; }
.payout-card {
  background: var(--surface);
  border-radius: var(--radius);
  padding: 1rem;
  box-shadow: var(--shadow-sm);
  border-left: 4px solid var(--gold);
}
.payout-card .category { font-size: .78rem; color: var(--gray-400); text-transform: uppercase; font-weight: 600; }
.payout-card .amount   { font-size: 1.5rem; font-weight: 800; color: var(--green-dark); }
.payout-card .winner   { font-size: .9rem; font-weight: 600; margin-top: .25rem; }

/* ── Admin ────────────────────────────────────────────────────────────────── */
.admin-panel { background: var(--surface); border-radius: var(--radius-lg); padding: 1.25rem; box-shadow: var(--shadow-sm); }
.admin-section { margin-bottom: 2rem; }
.admin-section h3 { font-size: 1rem; font-weight: 700; color: var(--green-dark); margin-bottom: .75rem; border-bottom: 2px solid var(--green-pale); padding-bottom: .4rem; }
.inline-form { display: flex; gap: .6rem; flex-wrap: wrap; align-items: flex-end; }
.inline-form .form-group { margin-bottom: 0; }

/* ── Utility ──────────────────────────────────────────────────────────────── */
.text-muted    { color: var(--gray-400); }
.text-green    { color: var(--green-mid); }
.text-gold     { color: var(--gold); }
.text-red      { color: var(--red); }
.text-center   { text-align: center; }
.text-right    { text-align: right; }
.fw-bold       { font-weight: 700; }
.mt-1 { margin-top: .5rem; }
.mt-2 { margin-top: 1rem; }
.mb-1 { margin-bottom: .5rem; }
.mb-2 { margin-bottom: 1rem; }
.flex-between  { display: flex; align-items: center; justify-content: space-between; }

/* ── Global course database search (league/admin.php, tournament/admin.php,
   tournament/admin_scorecard.php, scorecard/index.php) ── */
.course-import-panel { display: flex; flex-wrap: wrap; gap: .6rem; align-items: flex-start; margin-bottom: 1rem; }
.course-search-box { position: relative; flex: 1; min-width: 240px; }
.course-search-results {
  position: absolute; top: 100%; left: 0; right: 0; z-index: 20; background: var(--surface);
  border: 1px solid var(--gray-200); border-radius: 8px; box-shadow: var(--shadow-md);
  max-height: 260px; overflow-y: auto; margin-top: .25rem;
}
.course-result { padding: .5rem .75rem; cursor: pointer; border-bottom: 1px solid var(--gray-100); }
.course-result:last-child { border-bottom: none; }
.course-result:hover { background: var(--green-pale); }
.cr-name { font-weight: 600; font-size: .92rem; color: var(--gray-700); }
.cr-meta { font-size: .8rem; color: var(--gray-400); }
.import-error { color: var(--red); font-size: .85rem; margin-top: .35rem; }

.badge {
  display: inline-block;
  padding: .2rem .55rem;
  border-radius: 99px;
  font-size: .72rem;
  font-weight: 700;
}
.badge-green  { background: var(--green-pale); color: var(--green-dark); }
.badge-gold   { background: var(--gold-light); color: var(--gold-text); }
.badge-gray   { background: var(--gray-200); color: var(--gray-700); }
.badge-red    { background: var(--red-pale); color: var(--red); }

/* ── Sticky first column (for wide scorecards) ────────────────────────────── */
.scorecard-sticky thead th:first-child,
.scorecard-sticky tbody td:first-child {
    position: sticky;
    left: 0;
    z-index: 2;
    background: var(--surface);
    box-shadow: 2px 0 4px rgba(0,0,0,.07);
}
.scorecard-sticky thead th:first-child {
    background: var(--header-bg);
    z-index: 3;
}
.scorecard-sticky .par-row td:first-child { background: var(--green-pale); }
.scorecard-sticky .hcp-row td:first-child { background: var(--gray-100); }
.scorecard-sticky tr:hover td:first-child  { background: var(--green-pale); }

/* ── Responsive ───────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  .page-content  { padding: 1rem .6rem 2rem; }
  .topnav     { padding: .55rem .75rem; flex-wrap: wrap; gap: 0; }
  .nav-brand  { font-size: .97rem; flex: 1; }

  /* Hamburger button */
  .nav-hamburger {
    display: flex; align-items: center; justify-content: center;
    background: none;
    border: 1.5px solid rgba(255,255,255,.35);
    border-radius: 6px;
    color: #fff;
    font-size: 1.15rem;
    width: 36px; height: 36px;
    cursor: pointer;
    flex-shrink: 0;
  }

  /* Nav-links: hidden panel that drops below the brand row when open */
  .nav-links {
    display: none;
    flex-direction: column;
    width: 100%;
    order: 10;
    gap: 0;
    padding: .3rem 0 .1rem;
    border-top: 1px solid rgba(255,255,255,.15);
    margin-top: .4rem;
  }
  .nav-links.open { display: flex; }
  .nav-links a {
    display: block !important;
    padding: .65rem .25rem;
    font-size: .95rem;
    color: rgba(255,255,255,.9) !important;
    border-bottom: 1px solid rgba(255,255,255,.07);
    border-bottom-width: 1px !important; /* reset gold underline */
  }
  .nav-links a:last-child { border-bottom: none !important; }
  .nav-links a:hover, .nav-links a.active {
    color: #fff !important;
    background: rgba(255,255,255,.1);
    border-radius: 6px;
    text-decoration: none;
    border-bottom-color: transparent !important;
  }
  .nav-user { display: inline !important; color: rgba(255,255,255,.75); font-size: .9rem; }

  /* Subnav wraps into rows on mobile — no sideways scrolling */
  .subnav {
    flex-wrap: wrap;
    gap: .1rem;
    padding: .4rem .5rem 0;
  }
  .subnav a { padding: .4rem .55rem .45rem; font-size: .8rem; white-space: nowrap; }



  /* Page titles & layout */
  .page-title   { font-size: 1.2rem; }
  .section-title { font-size: 1rem; }
  .flex-between  { flex-wrap: wrap; gap: .5rem; }

  /* Cards */
  .card         { padding: .9rem .85rem; }
  .card-header  { flex-wrap: wrap; gap: .4rem; }

  /* Tables */
  .data-table th, .data-table td { padding: .5rem .45rem; font-size: .85rem; }

  /* Hole pips stay close to the 44px tap-target floor even on narrow screens —
     they'll wrap to two rows rather than shrink below a comfortable tap size. */
  .hole-pip  { width: 40px; height: 40px; font-size: .8rem; }
  .hole-nav  { gap: .35rem; }

  /* Admin inline forms stack */
  .inline-form { flex-direction: column; }
  .form-row    { flex-direction: column; }

  /* Round selector buttons wrap nicely. min-height keeps the tap target near
     the ~44px platforms recommend even though the label stays compact. */
  .btn-sm { padding: .4rem .75rem; font-size: .85rem; min-height: 42px; }
}

@media (max-width: 480px) {
  .page-content  { padding: .75rem .5rem 2rem; }
  .topnav        { padding: .55rem .6rem; }
  .nav-brand     { font-size: .92rem; }

  /* Dashboard */
  .payout-grid   { grid-template-columns: 1fr; }
  .dash-actions  { flex-direction: column; }
  .dash-actions .btn { width: 100%; justify-content: center; }

  /* Score entry card padding */
  .score-btn     { width: 42px; height: 42px; font-size: 1.4rem; }
  .score-display { width: 52px; height: 52px; font-size: 1.5rem; }
}

/* Round selector bar (shared across tournament pages) */
.round-sel-bar { display:flex; align-items:center; gap:.75rem; background:var(--surface);
                 border-radius:var(--radius-lg); box-shadow:var(--shadow-sm);
                 padding:.65rem 1rem; margin-bottom:1rem; flex-wrap:wrap; }
.round-sel-label { font-weight:600; font-size:.9rem; color:var(--gray-700); white-space:nowrap; }
.round-sel { flex:1; min-width:0; max-width:400px; padding:.4rem .75rem;
             border-radius:6px; border:1.5px solid var(--gray-200); font-size:.9rem;
             color:var(--gray-700); background:var(--surface); }

/* ── Player Profile ──────────────────────────────────────────────────────── */
.nav-avatar { width:30px; height:30px; border-radius:50%; object-fit:cover; border:2px solid rgba(255,255,255,.4); vertical-align:middle; }
.nav-user-link { display:flex; align-items:center; gap:.45rem; text-decoration:none; color:rgba(255,255,255,.65); font-size:.85rem; }
.nav-user-link:hover { color:#fff; text-decoration:none; }
.nav-user-link .nav-user { /* inherits existing nav-user styles */ }

/* ── Cowbell overlay ─────────────────────────────────────────────────────── */
@keyframes cowbell-fadein { from { opacity:0; transform:scale(.92); } to { opacity:1; transform:scale(1); } }
