:root {
  --bg: #f5f6f8;
  --panel: #ffffff;
  --border: #d9dce1;
  --text: #1f2430;
  --muted: #667085;
  --accent: #2563eb;
  --accent-hover: #1d4ed8;
  --danger: #dc2626;
  --ok: #16a34a;
  --warn: #ca8a04;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-size: 14px;
}

a { color: var(--accent); }

/* ---------- Auth pages ---------- */
.auth-wrap {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.auth-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 32px;
  width: 100%;
  max-width: 380px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
}

.auth-card h1 {
  font-size: 20px;
  margin: 0 0 4px;
}

.auth-card p.sub {
  color: var(--muted);
  margin: 0 0 20px;
  font-size: 13px;
}

.field { margin-bottom: 14px; }
.field label { display: block; font-size: 13px; color: var(--muted); margin-bottom: 4px; }
.field input, .field select {
  width: 100%;
  padding: 9px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 14px;
  background: var(--panel);
}
.field input:focus, .field select:focus { outline: 2px solid var(--accent); outline-offset: -1px; }

button, .btn {
  cursor: pointer;
  border: 1px solid var(--border);
  background: var(--panel);
  border-radius: 6px;
  padding: 8px 14px;
  font-size: 13px;
  color: var(--text);
}
button.primary, .btn.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  width: 100%;
  padding: 10px;
  font-size: 14px;
}
button.primary:hover { background: var(--accent-hover); }
button.danger { color: var(--danger); border-color: var(--danger); }
button:disabled { opacity: 0.5; cursor: default; }

.error-msg {
  background: #fef2f2;
  border: 1px solid #fecaca;
  color: #991b1b;
  padding: 8px 10px;
  border-radius: 6px;
  font-size: 13px;
  margin-bottom: 14px;
}
.ok-msg {
  background: #f0fdf4;
  border: 1px solid #bbf7d0;
  color: #166534;
  padding: 8px 10px;
  border-radius: 6px;
  font-size: 13px;
  margin-bottom: 14px;
}

.auth-links { margin-top: 16px; font-size: 13px; text-align: center; color: var(--muted); }

/* ---------- App shell ---------- */
.app-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  padding: 10px 18px;
}
.app-header h1 { font-size: 16px; margin: 0; }
.app-header .who { color: var(--muted); font-size: 13px; }

.app-body {
  display: flex;
  height: calc(100vh - 49px);
}

.sidebar {
  width: 260px;
  border-right: 1px solid var(--border);
  background: var(--panel);
  overflow-y: auto;
  padding: 14px;
}
/* flex (not float) for the "RALLIES  + New" / "LEGS  + New" header rows —
   float:right left the button's own box (taller than the header's text
   line, thanks to its padding) hanging below the header's bottom edge
   with nothing clearing it, so it visually spilled down onto the first
   list item underneath instead of sitting inline with the label. */
.sidebar h2 {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-size: 12px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); margin: 18px 0 8px;
}
.sidebar h2:first-child { margin-top: 0; }
.sidebar h2 button { text-transform: none; letter-spacing: normal; font-size: 12px; padding: 5px 10px; flex: none; }

.list-item {
  padding: 7px 8px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 13px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.list-item:hover { background: var(--bg); }
.list-item.active { background: #eef2ff; color: var(--accent); font-weight: 600; }

/* A thin divider between rallies in the sidebar list, so a longer list
   doesn't run together into one solid block. Scoped to #rally-list (not
   .list-item generally) since the leg list below reuses the same class
   but didn't need this. */
#rally-list .list-item { border-bottom: 1px solid var(--border); }
#rally-list .list-item:last-child { border-bottom: none; }

.main {
  flex: 1;
  /* min-width: 0 overrides a flex item's default min-width:auto, which
     otherwise refuses to let this shrink below the intrinsic width of
     whatever's inside it (the bonus grid, with a dozen-plus columns).
     Without it, the grid pushes .main — and the whole page — wider than
     the viewport instead of scrolling within its own box, which is why
     there was no reachable horizontal scrollbar for the grid's right-hand
     columns (Address, Sym, Weather, Lookup).
     min-height: 0 is the same fix for the vertical axis: .app-body is a
     row flexbox with a fixed height (calc(100vh - 49px)), and .main is a
     flex item in it. Without min-height:0, a flex item's default
     min-height:auto lets it grow taller than its container to fit its
     content (all 247 grid rows, un-virtualized) instead of being capped
     at the container's height — which is why the grid just kept growing
     downward and you had to scroll the whole page to reach the bottom of
     the table, where Tabulator puts its own horizontal scrollbar. */
  min-width: 0;
  min-height: 0;
  overflow: auto;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.toolbar {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}
.toolbar .spacer { flex: 1; }

.save-indicator { font-size: 12px; color: var(--muted); }
.save-indicator.saving { color: var(--warn); }
.save-indicator.saved { color: var(--ok); }
.save-indicator.error { color: var(--danger); }

#bonus-grid { flex: 1; min-height: 300px; min-width: 0; }
#grid-area { min-width: 0; min-height: 0; }

.view-toggle { display: flex; border: 1px solid var(--border); border-radius: 6px; overflow: hidden; }
.view-toggle button {
  border: none;
  border-radius: 0;
  padding: 7px 14px;
}
.view-toggle button + button { border-left: 1px solid var(--border); }
.view-toggle button.active { background: var(--accent); color: #fff; }

#map-view { flex: 1; min-height: 300px; min-width: 0; }

.map-legend {
  background: rgba(255, 255, 255, 0.92);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 10px;
  font-size: 12px;
  line-height: 1.6;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
}
.map-legend .swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  margin-right: 6px;
  border: 1px solid rgba(0, 0, 0, 0.25);
}
.map-color-control {
  background: rgba(255, 255, 255, 0.95);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
}
.map-color-control button { font-size: 12px; padding: 6px 10px; }

/* Leaflet's default .leaflet-div-icon adds its own white box + border,
   which we don't want — the SVG shape inside (see buildMarkerIcon in
   app.js) already draws its own fill and outline. */
.bonus-marker-icon {
  background: transparent;
  border: none;
}

.bonus-popup h4 { margin: 0 0 6px; font-size: 14px; }
.bonus-popup .row { font-size: 12px; margin-bottom: 2px; }
.bonus-popup .row .lbl { color: var(--muted); margin-right: 4px; }

.empty-state {
  color: var(--muted);
  text-align: center;
  padding: 60px 20px;
}

.progress-bar {
  height: 6px;
  background: var(--border);
  border-radius: 3px;
  overflow: hidden;
  width: 200px;
}
.progress-bar > div { height: 100%; background: var(--accent); width: 0%; transition: width 0.2s; }

.modal-backdrop {
  position: fixed; inset: 0; background: rgba(0,0,0,0.35);
  display: flex; align-items: center; justify-content: center;
  /* Leaflet's own panes/controls use z-index values up to ~1000, and
     since #map-view and its ancestors (.main, #grid-area) don't establish
     their own stacking context, those layers compete directly against
     ours in the same global stacking order. z-index:50 lost that fight
     once a Leaflet map existed on the page — the map rendered on top of
     this backdrop, hiding every modal (rally/leg/import/point-ranges)
     behind it. 10000 is comfortably above anything Leaflet uses. */
  z-index: 10000;
}
.modal {
  background: var(--panel); border-radius: 10px; padding: 24px;
  width: 100%; max-width: 420px; box-shadow: 0 4px 24px rgba(0,0,0,0.15);
  max-height: 90vh; overflow-y: auto;
}
.modal h3 { margin-top: 0; }
.modal .actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 18px; }

.weather-panel {
  position: fixed; right: 16px; top: 60px; width: 320px; max-height: 80vh; overflow-y: auto;
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 4px 24px rgba(0,0,0,0.15); padding: 14px;
  z-index: 9000; /* same Leaflet reasoning as .modal-backdrop, just below it */
}
.weather-panel-header {
  display: flex; align-items: center; justify-content: space-between;
  margin: -2px -2px 10px; padding-bottom: 8px; border-bottom: 1px solid var(--border);
}
.weather-panel-title { font-weight: 600; font-size: 14px; }
.weather-panel-close {
  border: none; background: transparent; color: var(--muted);
  font-size: 15px; line-height: 1; padding: 2px 6px; cursor: pointer;
}
.weather-panel-close:hover { color: var(--text); }

.weather-day-list { display: flex; flex-direction: column; }
.weather-day {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 8px; padding: 8px 0; border-bottom: 1px solid var(--bg); font-size: 13px;
}
.weather-day:last-child { border-bottom: none; }
.weather-day-left { display: flex; align-items: flex-start; gap: 8px; min-width: 0; }
.weather-day-emoji { font-size: 18px; line-height: 1.3; }
.weather-day-date { font-size: 13px; font-weight: 600; }
.weather-day-cond { font-size: 11px; color: var(--muted); margin-top: 2px; }
.weather-day-temps { font-size: 13px; font-weight: 600; white-space: nowrap; flex: none; }

.popup-weather-btn {
  margin-top: 8px;
  width: 100%;
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  font-size: 12px;
  padding: 6px 8px;
}
.popup-weather-btn:hover { background: var(--accent-hover); }

select.avail-select, select.combo-select {
  width: 100%; padding: 4px; border: 1px solid var(--border); border-radius: 4px;
}

/* ---------- Hours & Miles Available planning view ---------- */
/* Checkpoints and legs render as real tables — one row per checkpoint/leg,
   one column per field — matching the row-per-leg, column-per-metric
   layout of the original spreadsheet tabs, instead of stacked
   label-then-input pairs. Reuses .admin-table's look (see Admin portal
   below) with a few overrides for editable cells. */
#hoursmiles-view { flex: 1; overflow-y: auto; padding: 4px 2px 24px; }
.hm-wrap { max-width: 100%; }
.hm-intro { color: var(--muted); font-size: 13px; max-width: 720px; margin: 0 0 14px; }

.hm-leg-count-controls { display: flex; align-items: center; gap: 8px; margin-bottom: 20px; }
.hm-leg-count-controls button { padding: 4px 10px; }
.hm-leg-count { font-weight: 600; min-width: 14px; text-align: center; }

.hm-table-heading { font-size: 13px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); margin: 0 0 8px; }
.hm-table-scroll { overflow-x: auto; margin-bottom: 24px; border: 1px solid var(--border); border-radius: 8px; }
/* table+class selectors (not just .hm-table) so these win over the later
   .admin-table rules below at equal specificity — otherwise the table's
   own border/radius/overflow would double up with .hm-table-scroll's. */
table.hm-table { border: none; border-radius: 0; font-size: 12.5px; }
table.hm-table th, table.hm-table td { white-space: nowrap; padding: 6px 8px; vertical-align: middle; }
table.hm-table thead th { font-size: 10.5px; }

.hm-row-label { font-weight: 600; background: var(--bg); }

.hm-cell-input {
  padding: 5px 7px; border: 1px solid var(--border); border-radius: 4px; font-size: 12.5px;
  width: 100%; min-width: 130px; box-sizing: border-box;
}
.hm-cell-input-num { min-width: 68px; }
.hm-cell-input:focus { outline: 2px solid var(--accent); outline-offset: -1px; }

.hm-checkpoint-address-cell { display: flex; align-items: center; gap: 6px; }
.hm-checkpoint-address-cell .hm-cell-input { min-width: 220px; }
.hm-checkpoint-address-cell button { flex: none; padding: 5px 10px; font-size: 12px; }
.hm-checkpoint-status { color: var(--muted); font-size: 12px; }

.hm-cell-output { text-align: right; background: var(--bg); font-weight: 600; }

.hm-totals-row td { font-weight: 700; background: #eef2ff; border-top: 2px solid var(--accent); }
.hm-totals-row td:first-child { color: var(--accent); }

/* ---------- Rally Bonus Point Planning view ---------- */
/* Same table markup/classes as Hours & Miles above (.hm-table, .hm-cell-input,
   .hm-cell-output, .hm-totals-row) — just a wider table (21 columns). Two
   columns get extra treatment matching the spreadsheet's own emphasis:
   "Points needed" is always bold red (same red text the sheet uses for
   that column), and "Diff vs target" turns pink when negative — the
   spreadsheet's own warning that the planned/actual points fall short
   of what's needed for that leg. */
#points-view { flex: 1; overflow-y: auto; padding: 4px 2px 24px; }
.pts-needed-cell { color: var(--danger); font-weight: 700; }
.pts-diff-negative { background: #fde2e2; color: var(--danger); }

/* ---------- Admin portal ---------- */
.admin-body { max-width: 1400px; margin: 0 auto; padding: 20px 24px 40px; }

/* Wraps a .admin-table to give it the rounded/bordered outer look (moved
   here from .admin-table itself) and a scrollable, bounded-height region —
   required for the header row's position:sticky below to actually have
   something to stick within, instead of scrolling off with the page. */
.admin-table-wrap {
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: auto;
}

.admin-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--panel);
  font-size: 13px;
}
.admin-table th, .admin-table td {
  padding: 9px 12px;
  text-align: left;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.admin-table th {
  background: var(--bg);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  position: sticky;
  top: 0;
  z-index: 1;
}
.admin-table tbody tr:last-child td { border-bottom: none; }
.admin-table tbody tr:hover { background: var(--bg); }

.online-dot {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--border);
}
.online-dot.online { background: var(--ok); box-shadow: 0 0 0 3px rgba(22, 163, 74, 0.15); }

.badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
}
.badge-ok { background: #f0fdf4; color: var(--ok); }
.badge-muted { background: var(--bg); color: var(--muted); }

/* Bonus grid "Name" column — matches the yellow-highlighted Name column
   from the spreadsheet version, so it stands out from the rest of the grid. */
.tabulator .tabulator-col.col-name,
.tabulator .tabulator-col.col-name .tabulator-col-content {
  background: #ffe066;
}
.tabulator-row .tabulator-cell.col-name {
  background: #fff3bf;
}
.tabulator-row.tabulator-selected .tabulator-cell.col-name,
.tabulator-row:hover .tabulator-cell.col-name {
  background: #ffe066;
}
.badge-accent { background: #eef2ff; color: var(--accent); }
