/* Kickoff Grid — dark chrome around a navy SVG grid it doesn't try to match
   exactly; it just gets out of the way. The grid carries its own colors
   (inline in grid.js) so nothing here needs to agree with it pixel-for-pixel,
   only sit close enough in tone that the toolbar doesn't look like a
   different app bolted on top. */

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

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

[hidden] { display: none !important; }

/* Visually hidden but still reachable by screen readers — used for labels
   on controls (like the favorites search box) whose placeholder already
   carries the visible hint. */
.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;
}

:root {
  color-scheme: dark;
  --bg: #0a1420;
  --bg-panel: #0d1b2c;
  --bg-toolbar: #0b1728;
  --line: #22354f;
  --ink: #dbe6f5;
  --ink-soft: #7f95b3;
  --accent: #2f8fd6;
  --accent-tint: rgba(47, 143, 214, .18);
  /* A darker step of --accent for any surface that carries white text on
     top of it (the primary button fill, a selected calendar day) — the
     brighter --accent reads fine as an outline/tint but falls under 4.5:1
     with white text at these font sizes. */
  --accent-strong: #2570ad;
  --accent-strong-hover: #2876b3;
  --danger: #d9534f;
  --danger-tint: rgba(217, 83, 79, .12);
  --warn: #e0a63e;
  --warn-tint: rgba(224, 166, 62, .12);
  --r: 8px;
  --r-sm: 5px;
  --shadow-pop: 0 10px 28px rgba(0, 0, 0, .5);
}

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 14px/1.4 -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  /* #grid-wrap owns its own horizontal scrollbar for the (wide) SVG; this is
     just a backstop so a narrow-viewport toolbar can never drag the whole
     page sideways with it. */
  overflow-x: hidden;
}

button, select, input {
  font: inherit;
  color: inherit;
}

#shell {
  display: flex;
  flex-direction: column;
  height: 100vh;
}

/* ---------------------------------------------------------------- toolbar */

#toolbar {
  flex: none;
  padding: 10px 16px;
  background: var(--bg-toolbar);
  border-bottom: 1px solid var(--line);
}

#toolbar-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

#wordmark {
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-soft);
  margin-right: 4px;
}

/* Every toolbar control shares this base: 36px tall, same border/radius
   language as the rest of the chrome. .primary and [aria-pressed="true"]
   layer a fill on top for the one action that should read as "the" action
   and the one that reflects on/off state. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 36px;
  padding: 0 12px;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  color: var(--ink);
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: background-color .15s ease, border-color .15s ease;
}
.btn:hover { border-color: var(--accent); }

.btn.icon-btn {
  width: 36px;
  padding: 0;
  color: var(--ink-soft);
}
.btn.icon-btn:hover { color: var(--ink); }

.btn.primary {
  background: var(--accent-strong);
  border-color: var(--accent-strong);
  color: #fff;
  font-weight: 600;
}
.btn.primary:hover { background: var(--accent-strong-hover); border-color: var(--accent-strong-hover); }

.btn[aria-pressed="true"] {
  background: var(--accent-tint);
  border-color: var(--accent);
}

.label-short { display: none; }

/* -------------------------------------------------------------- date stepper */

#date-wrap {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: 12px;
  position: relative;
}

#btn-date { min-width: 122px; font-weight: 600; }

#btn-this-saturday { margin-left: 4px; }

#btn-refresh { margin-left: auto; }

/* Anchored under the date button; renderCalendar() in app.js fills this in
   fresh on every open and every month navigation, so there's nothing to
   style here beyond the shell — see .cal-* below. */
#calendar-pop {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 20;
  width: 264px;
  padding: 12px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--shadow-pop);
}

.cal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}

.cal-month {
  font-size: 13px;
  font-weight: 600;
}

.cal-nav {
  width: 28px;
  height: 28px;
}

.cal-weekdays, .cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
}

.cal-weekdays {
  margin-bottom: 4px;
  color: var(--ink-soft);
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  text-align: center;
}
.cal-weekdays span { padding: 2px 0; }

.cal-grid { gap: 2px; }

.cal-day {
  width: 100%;
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  border-radius: var(--r-sm);
  color: var(--ink-soft);
  font: inherit;
  font-size: 12.5px;
  cursor: pointer;
}
.cal-day:hover { background: rgba(219, 230, 245, .08); }

/* Saturdays are the whole point of this app, so they're the only day that
   reads as "full strength" by default — everything else stays dimmed but
   still clickable, because Thursday/Friday games exist too. */
.cal-day.is-sat {
  color: var(--ink);
  font-weight: 700;
  background: rgba(219, 230, 245, .07);
}

.cal-day.is-outside { opacity: .4; }

.cal-day.is-today { box-shadow: inset 0 0 0 1px var(--accent); }

.cal-day.is-selected {
  background: var(--accent-strong);
  color: #fff;
  font-weight: 700;
}

.cal-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--line);
}

.cal-foot button {
  background: transparent;
  border: none;
  color: var(--accent);
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  padding: 4px 2px;
}
.cal-foot button:last-child { color: var(--ink-soft); font-weight: 500; }
.cal-foot button:hover { text-decoration: underline; }

/* -------------------------------------------------------------- status */

#status-row {
  display: flex;
  align-items: baseline;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 4px;
}

#status-fresh {
  text-align: right;
  color: var(--ink-soft);
  font-size: 12px;
  /* The one place an ellipsis is acceptable — the alert strip below always
     wraps in full instead, because a clipped error is a hidden error. */
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Saving.../Saved/error — driven by store.js's onSaveState. Quiet like
   #status-fresh in the normal cases; the error state borrows --danger so a
   failed save doesn't read as just another quiet status line. */
#save-indicator {
  flex: none;
  color: var(--ink-soft);
  font-size: 12px;
  white-space: nowrap;
}
#save-indicator.is-error { color: var(--danger); }

.link-btn {
  background: none;
  border: none;
  padding: 0;
  color: inherit;
  text-decoration: underline;
  font: inherit;
  font-size: inherit;
  cursor: pointer;
}
#save-indicator.is-error .link-btn { color: var(--danger); font-weight: 600; }

#status-alert {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 8px 16px;
  background: var(--danger-tint);
  border-bottom: 1px solid rgba(217, 83, 79, .35);
  color: var(--danger);
  font-size: 13px;
  line-height: 1.4;
}
#status-alert.warn {
  background: var(--warn-tint);
  border-bottom-color: rgba(224, 166, 62, .35);
  color: var(--warn);
}

#status-alert .alert-icon { flex: none; margin-top: 1px; }

#status-alert-text { flex: 1; min-width: 0; }

#status-alert .icon-btn { flex: none; height: 24px; width: 24px; border: none; color: inherit; }
#status-alert .icon-btn:hover { color: inherit; opacity: .7; }

/* One-time offer to bring a browser's pre-account localStorage into the
   account — same full-width-strip language as #status-alert, but calmer
   (accent, not danger/warn) since nothing is wrong. */
#import-banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 8px 16px;
  background: var(--accent-tint);
  border-bottom: 1px solid rgba(47, 143, 214, .35);
  color: var(--ink);
  font-size: 13px;
}
#import-banner-text { flex: 1; min-width: 200px; }

/* Below this width the toolbar's controls alone are wider than the
   viewport, so they wrap into the two-row phone layout: row one is the
   date stepper plus refresh, row two is edit/export/print. #btn-edit-toggle
   forces the break — flex-basis:100% always starts a new line — and
   #btn-export-png's own auto margin pushes export+print to that new line's
   trailing edge, mirroring what #btn-refresh already does for row one. */
@media (max-width: 640px) {
  #wordmark { display: none; }

  .btn { min-height: 44px; }
  .btn.icon-btn { min-width: 44px; }

  #btn-edit-toggle { flex-basis: 100%; margin-left: 0; }
  #btn-export-png { margin-left: auto; }

  .label-full { display: none; }
  .label-short { display: inline; }

  #status-fresh { text-align: left; }

  #main {
    flex-direction: column;
  }

  #grid-wrap {
    flex: none;
    min-height: 60vh;
  }

  #panel {
    width: auto;
    max-height: 40vh;
    border-left: none;
    border-top: 1px solid var(--line);
  }

  /* Dense panel rows can't all grow to 44px without losing the list-density
     that's the whole point of this panel, but the two controls someone
     actually taps with a thumb — the favorite star and the hide checkbox —
     get a real target; the row itself grows a little to fit it. */
  .fav-star { min-width: 40px; min-height: 40px; font-size: 16px; }
  .hide-toggle input[type="checkbox"] { width: 20px; height: 20px; }
  .fav-chip-remove { min-width: 28px; min-height: 28px; }
}

/* Safari on iPhone has no useful print-to-PDF flow from a page's own Print
   button, so it doesn't get one — the OS share sheet's own "Print" already
   covers it for whoever wants a hard copy. */
@media (hover: none) {
  #btn-print { display: none; }
}

/* ---------------------------------------------------------------- main */

#main {
  flex: 1;
  display: flex;
  min-height: 0;
}

#grid-wrap {
  flex: 1;
  overflow: auto;
  /* No padding here on purpose: a sticky child pins to the scroll container's
     padding edge, so any padding on the scroll pane becomes a gap above the
     pinned header that rows scroll through. The 16px inset lives on the two
     grid pieces instead, and the header carries its own opaque background. */
  padding: 0;
}

/* The time-slot header stays put while #grid-body scrolls under it — both
   are clones of the one <svg> renderGrid() returned (see app.js), cropped
   to their own band via viewBox, so they scale in lockstep and their
   columns never drift apart. Sticky offsets resolve against the scroll
   container's padding edge, so top:0 already pins the header exactly where
   it rests at scrollTop 0; a negative top would double-count the padding
   and make the header jump by that much before it pins. */
/* #grid is sized to its content, not the pane: on a phone the SVG has a 720px
   floor and scrolls sideways, and a header div that only spanned the pane
   would stop covering the rows past its own right edge. max-content makes
   the sticky header exactly as wide as the grid it sits over. */
#grid {
  width: max-content;
  min-width: 100%;
}

#grid-head {
  position: sticky;
  top: 0;
  z-index: 2;
  padding: 16px 16px 0;
  background: var(--bg);
}

#grid-body {
  padding: 0 16px 16px;
}

#grid-head svg, #grid-body svg {
  width: 100%;
  height: auto;
  min-width: 720px; /* below this the slot labels stop being readable */
  display: block;
}

.grid-error {
  color: var(--danger);
  padding: 24px;
}

/* ---------------------------------------------------------------- panel */

#panel {
  flex: none;
  width: 340px;
  overflow-y: auto;
  padding: 16px;
  background: var(--bg-panel);
  border-left: 1px solid var(--line);
}

#panel h2 {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .5px;
  color: var(--ink-soft);
  margin: 20px 0 8px;
}

#panel section:first-of-type h2 { margin-top: 0; }

.group-head {
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: .4px;
  color: var(--ink-soft);
  margin: 14px 0 4px;
}

.net-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 3px 0;
  cursor: pointer;
}

.net-swatch {
  width: 10px;
  height: 10px;
  border-radius: 2px;
  flex: none;
}

.net-name { font-size: 13px; }

/* -------------------------------------------------------------- filters */

#filter-presets {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 8px 0 10px;
}

.preset-btn {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 4px 9px;
  font-size: 12px;
  cursor: pointer;
}
.preset-btn:hover { border-color: var(--accent); }

.conf-count {
  margin-left: auto;
  color: var(--ink-soft);
  font-size: 11.5px;
}

/* ------------------------------------------------------------- favorites */

#fav-picker {
  position: relative;
  margin: 8px 0 10px;
}

#fav-search {
  width: 100%;
  height: 36px;
  padding: 0 10px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  color: var(--ink);
  font: inherit;
  font-size: 12.5px;
}
#fav-search:focus { border-color: var(--accent); }

#fav-results {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  z-index: 15;
  max-height: 240px;
  overflow-y: auto;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--shadow-pop);
}

.fav-result {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 6px 10px;
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--line);
  color: var(--ink);
  font: inherit;
  font-size: 12.5px;
  text-align: left;
  cursor: pointer;
}
.fav-result:last-child { border-bottom: none; }
.fav-result:hover:not(:disabled) { background: rgba(219, 230, 245, .06); }
.fav-result:disabled, .fav-result.is-added { color: var(--ink-soft); cursor: default; }

.fav-result-logo { width: 20px; height: 20px; object-fit: contain; flex: none; }
.fav-result-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fav-result-conf { flex: none; color: var(--ink-soft); font-size: 11px; }

#fav-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
}

.fav-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 6px 3px 8px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 12px;
}

.fav-chip-logo { width: 16px; height: 16px; object-fit: contain; }

.fav-chip-remove {
  background: none;
  border: none;
  color: var(--ink-soft);
  font-size: 14px;
  line-height: 1;
  padding: 0 2px;
  cursor: pointer;
}
.fav-chip-remove:hover { color: var(--danger); }

/* Star toggle inline with a team's abbreviation in the side panel's game
   rows — small by default, sized up to a real tap target on phones below. */
.fav-star {
  flex: none;
  width: 18px;
  height: 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  background: none;
  border: none;
  color: var(--ink-soft);
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
}
.fav-star:hover { color: var(--accent); }
.fav-star.is-fav { color: #e8b93e; }

#panel-filters #btn-clear-filters {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 6px 10px;
  margin-top: 10px;
  cursor: pointer;
}
#panel-filters #btn-clear-filters:hover { border-color: var(--danger); }

.game-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 0;
  border-bottom: 1px solid var(--line);
  font-size: 12.5px;
}

.game-time {
  flex: none;
  width: 58px;
  color: var(--ink-soft);
}

.game-teams {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 3px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.game-odds {
  flex: none;
  color: var(--ink-soft);
  font-size: 12px;
  white-space: nowrap;
}

.game-network {
  flex: none;
  max-width: 108px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 2px 4px;
}

.hide-toggle {
  flex: none;
  display: flex;
  align-items: center;
  gap: 3px;
  color: var(--ink-soft);
  cursor: pointer;
}

.empty-note { color: var(--ink-soft); font-size: 12.5px; }

#panel-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 18px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}

#hidden-count { color: var(--ink-soft); font-size: 12.5px; }

#btn-reset {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 6px 10px;
  cursor: pointer;
}
#btn-reset:hover { border-color: var(--danger); }

/* -------------------------------------------------------------- prefs */

.field-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 4px 0;
}

.field-row-label { font-size: 13px; }

.field-row select {
  height: 30px;
  padding: 0 6px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  color: var(--ink);
}

#btn-use-shown-default {
  display: block;
  width: 100%;
  margin-top: 10px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 6px 10px;
  font-size: 12px;
  cursor: pointer;
}
#btn-use-shown-default:hover { border-color: var(--accent); }

/* Compact rows (prefs.compact): shrinks the side panel's row spacing and
   font only — the SVG grid itself is unaffected, per DESIGN §5. */
body.compact .game-row { padding: 2px 0; font-size: 11.5px; }
body.compact .net-row { padding: 1px 0; }
body.compact #panel h2 { margin: 14px 0 6px; }
body.compact .group-head { margin: 10px 0 3px; }

/* ---------------------------------------------------------------- print */

@media print {
  @page { size: landscape; margin: 8mm; }

  html, body { background: #fff; height: auto; }

  #toolbar, #status-alert, #import-banner, #panel { display: none; }

  #shell, #main { display: block; height: auto; }

  #grid-wrap { overflow: visible; padding: 0; }
  #grid-head, #grid-body { padding: 0; }

  /* Sticky positioning has no scroll container to stick inside once the
     page prints, so let it fall back to normal flow and keep the header
     and body clones glued together on the same page. */
  #grid-head { position: static; top: auto; }
  #grid { break-inside: avoid; }

  #grid-head svg, #grid-body svg { width: 100%; min-width: 0; }
}

/* ============================================================= auth pages
   login.html / signup.html / verify.html / reset.html / account.html share
   this section — same dark chrome/tokens as the app shell above, just a
   centered card instead of the toolbar+grid+panel layout. */

.auth-shell {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.auth-card {
  width: 100%;
  max-width: 380px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 28px 24px;
}

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

.auth-sub {
  color: var(--ink-soft);
  font-size: 13px;
  margin: 0 0 20px;
}

.field {
  margin-bottom: 14px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.field label {
  font-size: 12.5px;
  color: var(--ink-soft);
}

.field input, .field select {
  height: 40px;
  padding: 0 10px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  color: var(--ink);
  font: inherit;
}
.field input:focus, .field select:focus { border-color: var(--accent); }

.field-hint { font-size: 11.5px; color: var(--ink-soft); }

.field-error {
  color: var(--danger);
  font-size: 12px;
  min-height: 14px;
}

.form-error {
  color: var(--danger);
  background: var(--danger-tint);
  border: 1px solid rgba(217, 83, 79, .35);
  border-radius: var(--r-sm);
  padding: 8px 10px;
  font-size: 12.5px;
  margin: 0 0 14px;
}
.form-error[hidden] { display: none; }

.form-success {
  background: var(--accent-tint);
  border: 1px solid rgba(47, 143, 214, .35);
  border-radius: var(--r-sm);
  padding: 10px 12px;
  font-size: 13px;
  margin: 0 0 14px;
}

.auth-submit { width: 100%; height: 44px; margin-top: 4px; }

form.is-busy button[type="submit"] { opacity: .65; pointer-events: none; }

.auth-divider {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--ink-soft);
  font-size: 11.5px;
  margin: 18px 0;
}
.auth-divider::before, .auth-divider::after { content: ''; flex: 1; height: 1px; background: var(--line); }

.auth-providers {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.auth-provider-btn {
  width: 100%;
  height: 44px;
  text-decoration: none;
}

.auth-links {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin-top: 18px;
  font-size: 12.5px;
}
.auth-links a { color: var(--accent); text-decoration: none; }
.auth-links a:hover { text-decoration: underline; }

.auth-back {
  display: inline-block;
  margin-top: 18px;
  color: var(--accent);
  font-size: 12.5px;
  text-decoration: none;
}
.auth-back:hover { text-decoration: underline; }

.auth-danger-zone {
  margin-top: 28px;
  padding-top: 18px;
  border-top: 1px solid var(--line);
}
.auth-danger-zone h2 {
  font-size: 13px;
  color: var(--danger);
  margin: 0 0 4px;
}
.auth-danger-zone .auth-sub { margin-bottom: 12px; }
.auth-danger-zone .auth-submit { background: var(--danger); border-color: var(--danger); }
.auth-danger-zone .auth-submit:hover { background: #c24541; border-color: #c24541; }

.account-section {
  margin-top: 24px;
  padding-top: 18px;
  border-top: 1px solid var(--line);
}
.account-section:first-of-type { margin-top: 0; padding-top: 0; border-top: none; }
.account-section h2 { font-size: 13px; margin: 0 0 4px; }

#account-email { color: var(--ink-soft); }
