/* Single hand-written stylesheet -- no build tooling, per the project's tech decisions. */

:root {
  --ink: #1b1f24;
  --muted: #6b7480;
  --line: #e3e6ea;
  --bg: #f7f8fa;
  --card: #ffffff;
  --accent: #1f5f3f;
  --accent-soft: #eaf3ee;

  /* Hairline for the board grid: present enough to align by, quiet enough
     that names read as floating on it rather than boxed in. */
  --hair: #edeff2;

  /* Tint behind a ticked sandbox row. Deliberately neutral: on this board,
     hue is reserved for position and nothing else. */
  --picked-row: #eef1f4;

  /* Position palette, defined once. Each position has a solid colour for
     resolved cells and a desaturated one for projections, so "fact" and
     "guess" differ by saturation rather than by hue. */
  --qb:  #d94f6e;  --qb-soft:  #7c4553;
  --rb:  #2e9e8f;  --rb-soft:  #35635d;
  --wr:  #3d7fc1;  --wr-soft:  #3c5570;
  --te:  #e08640;  --te-soft:  #7a5636;
  --k:   #9a7bc8;  --k-soft:   #56496b;
  --def: #6b7a88;  --def-soft: #464f57;

  /* The board's own dark ground, distinct from the light page around it. */
  --board-bg: #1e242b;
  --board-line: #2b333c;
  --board-cell: #232a32;
  --board-ink: #8b97a4;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.5 -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

main {
  max-width: 900px;
  margin: 0 auto;
  padding: 2rem 1rem 3rem;
}

/* Header ------------------------------------------------------------------ */

.site-header {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  flex-wrap: wrap;
  padding: 0.85rem 1.25rem;
  background: var(--accent);
  color: #fff;
}

.site-header a { color: #fff; text-decoration: none; }
.site-header a:hover { text-decoration: underline; }
.brand { font-weight: 700; letter-spacing: 0.02em; }

.site-header nav {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-left: auto;
}

.site-header nav form { margin: 0; }
.who { opacity: 0.75; font-size: 0.9rem; }

.linkish {
  background: none;
  border: 0;
  color: #fff;
  font: inherit;
  cursor: pointer;
  padding: 0;
  text-decoration: underline;
}

/* The hamburger menu ------------------------------------------------------
   Eight links plus a username and a logout form had outgrown one row, so all
   of it except the Draft Board now hangs off a <details>. Same disclosure
   element as the board's cell popovers, for the same reason: the browser owns
   the open/close state, so this works with no JavaScript at all. */

.nav-menu {
  /* The panel is positioned against this, not against the header, so it lands
     under the button however the header has wrapped. */
  position: relative;
}

.nav-menu > summary {
  display: flex;
  align-items: center;
  cursor: pointer;
  padding: 0.3rem 0.35rem;
  border-radius: 5px;
  /* Both lines kill the default disclosure triangle: `list-style` covers
     Firefox and modern Chrome, the ::-webkit- pseudo-element older Safari. */
  list-style: none;
}

.nav-menu > summary::-webkit-details-marker { display: none; }
.nav-menu[open] > summary,
.nav-menu > summary:hover { background: rgba(255, 255, 255, 0.15); }

/* Focus ring drawn by hand: the summary is the menu's keyboard entry point, so
   it has to be obviously focused, and the header's green ground swallows the
   browser default. */
.nav-menu > summary:focus-visible { outline: 2px solid #fff; outline-offset: 1px; }

/* The glyph. Three spans, drawn in CSS -- no image file, no icon font. */
.nav-burger {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  width: 1.15rem;
  height: 0.85rem;
}

.nav-burger span {
  display: block;
  height: 2px;
  background: #fff;
  border-radius: 1px;
}

.nav-panel {
  position: absolute;
  top: calc(100% + 0.45rem);
  /* Right-aligned so it opens inward from the corner rather than off-screen. */
  right: 0;
  /* Must clearly beat the board: an open prediction popover lifts its cell to
     z-index 20 (see .cell:has(.cell-pop[open])), and this panel overlaps the
     board's top-right corner exactly where those cells are. */
  z-index: 100;
  display: flex;
  flex-direction: column;
  min-width: 12rem;
  padding: 0.35rem;
  background: var(--accent);
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 7px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
}

.nav-panel a,
.nav-panel .who,
.nav-panel .linkish {
  padding: 0.45rem 0.6rem;
  border-radius: 4px;
  text-align: left;
  white-space: nowrap;
}

.nav-panel a:hover { background: rgba(255, 255, 255, 0.12); text-decoration: none; }

/* "You are here", drawn from the same attribute that announces it to a screen
   reader -- one source of truth, so the tick cannot drift from the semantics.
   The links no longer sit in the header where you could see which was
   highlighted, so the menu has to answer it from the inside.

   The tick is written as the CSS escape \2713 rather than a literal check mark.
   That keeps this file pure ASCII, which is not fussiness: the literal glyph was
   here and had already been corrupted into a stray superscript-one by an
   encoding round trip somewhere between a Windows checkout and this file. An
   escape cannot be mangled that way. */
.nav-panel [aria-current="page"] { background: rgba(255, 255, 255, 0.18); font-weight: 600; }
.nav-panel [aria-current="page"]::after { content: " \2713"; }

/* The logout form is still a form -- Django 5+ refuses a GET logout, so this
   cannot become a link. It only has to sit in the column looking like one. */
.nav-panel form { width: 100%; }
.nav-panel .linkish { display: block; width: 100%; text-decoration: none; }
.nav-panel .linkish:hover { background: rgba(255, 255, 255, 0.12); text-decoration: underline; }

/* Divider above the account block, so "who am I / log out" reads as its own
   group rather than as two more destinations. */
.nav-panel .who {
  margin-top: 0.25rem;
  padding-top: 0.5rem;
  border-top: 1px solid rgba(255, 255, 255, 0.2);
}

/* Typography -------------------------------------------------------------- */

h1 { margin: 0 0 0.25rem; font-size: 1.6rem; }
.subtle { color: var(--muted); }
.note { color: var(--muted); font-size: 0.9rem; max-width: 60ch; }
.error { color: #a12a2a; }
code { background: #eef0f3; padding: 0.1em 0.35em; border-radius: 3px; font-size: 0.9em; }

/* Flash messages (django.contrib.messages) --------------------------------- */

/* Rendered in base.html, so any view can leave one behind on a redirect.
   Classed by the message's own tags -- `success`, `error` -- which is what
   Django puts there. */
.messages {
  list-style: none;
  margin: 0 0 1.2rem;
  padding: 0;
}

.messages li {
  padding: 0.7rem 1rem;
  border-radius: 6px;
  border-left: 4px solid var(--accent);
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 600;
}

.messages li.error {
  border-left-color: #a12a2a;
  background: #fbeeee;
  color: #a12a2a;
}


/* Site feedback ------------------------------------------------------------ */

.feedback-form {
  max-width: 46rem;
  margin: 1.4rem 0 2rem;
  padding: 1.1rem 1.2rem;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 8px;
}

.feedback-form .field label {
  padding: 0;
  font-size: 0.9rem;
  font-weight: 700;
}

.feedback-form .field { margin: 0 0 1rem; }

.feedback-form textarea {
  display: block;
  width: 100%;
  margin-top: 0.4rem;
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 6px;
  font: inherit;
  font-size: 0.95rem;
  /* Vertical only: a textarea dragged wider than its container is the one
     resize direction that breaks the layout. */
  resize: vertical;
}

/* Django's field.errors renders as <ul class="errorlist">. */
.feedback-form .errorlist {
  margin: 0.4rem 0 0;
  padding: 0;
  list-style: none;
  color: #a12a2a;
  font-size: 0.85rem;
}

.feedback-mine-head { margin-top: 2rem; font-size: 1.1rem; }

.feedback-list {
  max-width: 46rem;
  margin: 0.8rem 0 0;
  padding: 0;
  list-style: none;
}

.feedback-item {
  padding: 0.8rem 1rem;
  margin-bottom: 0.7rem;
  background: var(--card);
  border: 1px solid var(--line);
  border-left: 4px solid var(--line);
  border-radius: 6px;
}

/* Handled notes keep their place in the list but stop asking for attention. */
.feedback-item.done { border-left-color: var(--accent); }

.feedback-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  margin: 0;
  font-size: 0.8rem;
}

.feedback-done-tag { color: var(--accent); font-weight: 700; }

.feedback-body { font-size: 0.95rem; }
.feedback-body p { margin: 0.4rem 0 0; }


/* Tables ------------------------------------------------------------------ */

table.data {
  width: 100%;
  border-collapse: collapse;
  margin: 1.25rem 0;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 6px;
  overflow: hidden;
}

table.data th,
table.data td {
  text-align: left;
  padding: 0.55rem 0.8rem;
  border-bottom: 1px solid var(--line);
}

table.data th {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  background: #fbfcfd;
}

table.data tr:last-child td { border-bottom: 0; }
table.data td.num, table.data th.num { text-align: right; }
table.data tr.mine { background: var(--accent-soft); }
table.data tr.undrafted td { color: var(--muted); }
table.data tr.undrafted td strong { color: var(--ink); }
table.data a { color: var(--accent); font-weight: 600; }

/* Finishing position: narrow, bold, and quiet enough not to shout over the
   team names, which are what people actually scan for. */
table.data td.rank {
  width: 3.5rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}

table.data tr:first-child td.rank { color: var(--accent); }

/* Position chips ---------------------------------------------------------- */

.pos {
  display: inline-block;
  min-width: 2.6em;
  text-align: center;
  padding: 0.1em 0.4em;
  border-radius: 3px;
  font-size: 0.75rem;
  font-weight: 700;
  background: #eef0f3;
  color: #46505c;
}

.pos-QB  { background: #e7e0f7; color: #4b3b7a; }
.pos-RB  { background: #dcefe2; color: #23603c; }
.pos-WR  { background: #dde8f7; color: #23486e; }
.pos-TE  { background: #f9e6d5; color: #7a4a1e; }
.pos-K   { background: #f3e2e6; color: #7a2f42; }
.pos-DEF { background: #e2e5e8; color: #414a54; }

/* Status pills ------------------------------------------------------------ */

.pill {
  display: inline-block;
  padding: 0.1em 0.5em;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 700;
}

.pill-yes     { background: #dcefe2; color: #23603c; }
.pill-no      { background: #f7dcdc; color: #802626; }
.pill-pending { background: #f4ecd6; color: #6d5716; }

/* Callout ----------------------------------------------------------------- */

.callout {
  background: var(--accent-soft);
  border-left: 4px solid var(--accent);
  border-radius: 4px;
  padding: 0.8rem 1rem;
  margin: 1.25rem 0;
  font-size: 0.94rem;
}

/* The one line above the board. A .callout, but tighter: it sits between the
   title and the grid, and the standard callout margin pushes the board a
   screen-inch further down on a phone for one sentence. */
.board-note { margin: 0.9rem 0 0; }


/* Rendered markdown (the rules page) -------------------------------------- */

.prose {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 1.5rem 1.75rem;
}

.prose h1 { font-size: 1.7rem; margin-top: 0; }
.prose h2 { font-size: 1.25rem; margin-top: 2rem; border-bottom: 1px solid var(--line); padding-bottom: 0.3rem; }
.prose h3 { font-size: 1.05rem; margin-top: 1.5rem; }
.prose li { margin-bottom: 0.3rem; }
.prose hr { border: 0; border-top: 1px solid var(--line); margin: 2rem 0; }
.prose em { color: var(--muted); }
.prose table { border-collapse: collapse; margin: 1rem 0; width: 100%; }
.prose th, .prose td { border: 1px solid var(--line); padding: 0.4rem 0.6rem; text-align: left; font-size: 0.92rem; }
.prose th { background: #fbfcfd; }
.prose blockquote { margin: 1rem 0; padding-left: 1rem; border-left: 3px solid var(--line); color: var(--muted); }

/* Draft board ------------------------------------------------------------- */

main.wide { max-width: 1500px; }

.board-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

/* The settled draft time, under the board title. Sized up from .subtle beside
   it on purpose: with the draft weeks out it is the most useful line here. */
.draft-when {
  margin: 0.35rem 0 0;
  font-size: 0.95rem;
}

.draft-when strong { color: var(--accent); }

.round-toggle {
  flex: 0 0 auto;
  align-self: center;
  padding: 0.35rem 0.8rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--card);
  color: var(--accent);
  font-size: 0.82rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}

.round-toggle:hover { border-color: var(--accent); }

/* Board controls: simulate, clear, round toggle -- one row, right of the title. */
.board-controls {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.board-btn {
  padding: 0.35rem 0.9rem;
  border: 1px solid transparent;
  border-radius: 999px;
  background: var(--accent);
  color: #fff;
  font: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
}

.board-btn:hover:not(:disabled) { filter: brightness(1.15); }
.board-btn:disabled { opacity: 0.55; cursor: default; }

/* The secondary action reads as an outline, so "simulate" stays the one filled
   button on the page. */
.board-btn.ghost {
  background: var(--card);
  border-color: var(--line);
  color: var(--accent);
}

.board-btn.ghost:hover { border-color: var(--accent); }

/* Destructive, so it reads warm rather than green -- but still an outline, not
   a filled button. It clears your own private notes, not the league's data. */
.board-btn.ghost.danger { color: #a8442c; }
.board-btn.ghost.danger:hover { border-color: #a8442c; }

.board-btn.staff-btn {
  background: #344a69;
}

/* The reset form is a flex item alongside the buttons; without this it would
   introduce its own block box and break the row. */
.board-controls form { display: inline-flex; margin: 0; }

/* Team picker on the roster page. Shares .board-head's layout, so it sits on
   the right of the title the same way the board's controls do. */
.team-picker {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex: 0 0 auto;
  font-size: 0.82rem;
}

.team-picker label { color: var(--muted); font-weight: 600; }

.team-picker select {
  padding: 0.3rem 0.4rem;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--card);
  font: inherit;
  font-size: 0.82rem;
  max-width: 16rem;
}

.sim-error,
.sim-done {
  margin: 0.6rem 0 0;
  padding: 0.5rem 0.7rem;
  border-left: 3px solid #b4462f;
  background: #fdf1ee;
  color: #7d2f1e;
  font-size: 0.85rem;
}

/* Staff probability analysis --------------------------------------------- */

.probability-panel {
  margin: 0.75rem 0;
  padding: 0.9rem 1rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--card);
  box-shadow: 0 8px 24px rgba(16, 20, 25, 0.08);
}

.probability-panel[hidden] { display: none; }

.probability-head,
.probability-result-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
}

.probability-head h2 { margin: 0; font-size: 1.05rem; }
.probability-head p { margin: 0.15rem 0 0; }

.probability-controls {
  display: grid;
  grid-template-columns: max-content minmax(15rem, 1fr) max-content;
  align-items: end;
  gap: 0.75rem;
  margin-top: 0.8rem;
}

.probability-controls label,
.probability-result-head label {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  color: var(--muted);
  font-size: 0.76rem;
  font-weight: 600;
}

.probability-controls select,
.probability-controls input,
.probability-result-head select {
  padding: 0.38rem 0.5rem;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--card);
  color: var(--ink);
  font: inherit;
}

.probability-targets { grid-row: span 2; }
.probability-targets select { min-width: 15rem; }

.probability-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.55rem;
  grid-column: 1 / 2;
}

.probability-result-head {
  align-items: end;
  justify-content: flex-end;
  margin: 0.8rem 0 0.5rem;
}

.probability-result-head p { flex: 1 1 auto; margin: 0; }

.likely-lists {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 0.5rem;
  margin-bottom: 0.7rem;
}

.likely-lists section {
  padding: 0.55rem 0.65rem;
  border-radius: 7px;
  background: var(--accent-soft);
}

.likely-lists h3 { margin: 0 0 0.25rem; font-size: 0.78rem; }
.likely-lists ul { margin: 0; padding-left: 1rem; font-size: 0.72rem; }

.probability-table-wrap { max-height: 31rem; overflow: auto; }

.probability-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
}

.probability-table th,
.probability-table td {
  padding: 0.38rem 0.45rem;
  border-bottom: 1px solid var(--line);
  text-align: left;
  white-space: nowrap;
}

.probability-table th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--card);
  color: var(--muted);
}

/* Same box, good news. "Your mock draft is finished" is not a failure. */
.sim-done {
  border-left-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent);
}


/* Pick modal (mock draft) -------------------------------------------------- */

/* Anchored under the cell being drafted, not centred over the board.
   Absolute (page coordinates), not fixed, so it travels with the cell it
   belongs to when the page scrolls. board.js sets top/left; everything about
   where it lands is computed there, since only JS knows where the cell is. */
.pick-panel {
  position: absolute;
  z-index: 100;
  width: min(30rem, calc(100vw - 2rem));
}

.pick-panel[hidden] { display: none; }

.modal {
  display: flex;
  flex-direction: column;
  /* Bounded so the panel cannot swallow the board below it. The list inside
     scrolls; the panel itself stays a readable size. */
  max-height: min(26rem, 52vh);
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: 0 14px 38px rgba(16, 20, 25, 0.28);
  overflow: hidden;
}

.modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.6rem 1rem;
  border-bottom: 1px solid var(--line);
  background: var(--accent-soft);
  cursor: grab;                 /* the header is the drag handle */
  user-select: none;
}

.pick-panel.dragging .modal-head { cursor: grabbing; }

/* While a drag is in progress, stop the pointer selecting text across the page
   -- otherwise a quick drag highlights half the board. */
body.dragging-panel { user-select: none; }

/* A small pointer up at the cell the panel belongs to, so the association is
   visible rather than inferred from proximity. Hidden when the panel has been
   dragged away or flipped above its cell. */
.pick-panel::before {
  content: '';
  position: absolute;
  top: -6px;
  left: var(--tail-x, 1.5rem);
  width: 10px;
  height: 10px;
  background: var(--accent-soft);
  border-left: 1px solid var(--line);
  border-top: 1px solid var(--line);
  transform: rotate(45deg);
}

.pick-panel.detached::before { display: none; }

/* The cell whose pick is being made. Same green as the own-column marker, so
   "this is yours, right now" reads as an intensification of "this is yours". */
.cell.on-the-clock {
  box-shadow: inset 0 0 0 2px #7ac8a0, 0 0 0 3px rgba(122, 200, 160, 0.35);
}

.modal-head h2 { margin: 0; font-size: 1rem; }

.modal-close {
  border: 0;
  background: none;
  font-size: 1.4rem;
  line-height: 1;
  color: var(--muted);
  cursor: pointer;
}

.modal-close:hover { color: var(--ink); }

.modal-tools { padding: 0.7rem 1rem 0.4rem; }

.modal-tools input[type="search"] {
  width: 100%;
  padding: 0.4rem 0.6rem;
  border: 1px solid var(--line);
  border-radius: 6px;
  font: inherit;
  font-size: 0.9rem;
}

.pick-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin-top: 0.5rem;
}

.chip {
  padding: 0.15rem 0.55rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--card);
  font: inherit;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--muted);
  cursor: pointer;
}

/* The active chip is outlined, not filled: the position chips already carry
   their own hue, and filling them would put two colour languages in one row. */
.chip.active { border-color: var(--accent); color: var(--accent); }

.modal-hint {
  margin: 0;
  padding: 0.2rem 1rem 0.5rem;
  font-size: 0.76rem;
  color: var(--muted);
}

.pick-list {
  flex: 1 1 auto;
  overflow-y: auto;
  /* A swipe that runs off the end of this list stops there instead of handing
     the rest of the gesture to the page behind it. Without it a scroll started
     over the list moved the list, then the board, then stopped -- one gesture,
     two different things moving. */
  overscroll-behavior: contain;
  margin: 0;
  padding: 0 0.5rem;
  list-style: none;
}

.pick-row {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  width: 100%;
  padding: 0.45rem 0.5rem;
  border: 0;
  border-radius: 6px;
  background: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.pick-row:hover { background: var(--accent-soft); }

.pick-name { flex: 1 1 auto; font-weight: 600; }

.pick-team {
  flex: 0 0 auto;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--muted);
}

.pick-adp {
  flex: 0 0 auto;
  min-width: 5rem;
  text-align: right;
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}

.pick-none { padding: 0.8rem 0.5rem; color: var(--muted); font-size: 0.85rem; }

.modal-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  padding: 0.7rem 1rem;
  border-top: 1px solid var(--line);
}

.board-layout {
  display: flex;
  align-items: flex-start;
  gap: 1.1rem;
  margin: 1.1rem 0 1.5rem;
}

/* At the default eight rounds the grid fits without scrolling. The overflow
   rule only bites once "all rounds" is on, or on a narrow screen. */
.board-scroll {
  flex: 1 1 auto;
  min-width: 0;
  overflow: auto;
  background: var(--board-bg);
  border: 1px solid var(--board-line);
  border-radius: 8px;
  padding: 2px;
}

table.board {
  border-collapse: separate;
  border-spacing: 2px;
  width: 100%;
  table-layout: fixed;      /* ten equal columns, no content-driven widths */
  font-size: 0.75rem;
}

table.board thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--board-bg);
  padding: 0.4rem 0.35rem;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--board-ink);
}

.slot-num {
  display: block;
  font-size: 0.62rem;
  color: #5d6874;
  font-weight: 700;
}

th.round-head {
  position: sticky;
  left: 0;
  z-index: 3;
  width: 2.4rem;
  background: var(--board-bg);
  color: var(--board-ink);
  font-size: 0.78rem;
  font-weight: 700;
  text-align: center;
  vertical-align: middle;
}

/* The corner cell is sticky in BOTH directions, so it has to outrank the column
   headers sliding underneath it as well as the round numbers below it.
   Qualified with `table.board` on purpose: `thead th.round-head` alone is less
   specific than the `table.board thead th` rule above, which would pin it back
   to z-index 2 and let the scrolling headers paint straight over "Rd". */
table.board thead th.round-head { z-index: 4; }

.arrow {
  display: block;
  font-size: 0.62rem;
  line-height: 1;
  color: #4d5762;
  font-weight: 400;
}

/* Cells ------------------------------------------------------------------- */

.cell {
  position: relative;
  /* Taller than the names strictly need, because a cell also has to hold three
     candidate rows and the "+N more" line under them at the new size. */
  height: 5.1rem;
  /* Locking a prediction reloads the page and comes back to #pick-N. Without
     this the anchored cell lands hard against the top edge (and under the
     header); the margin gives it somewhere to sit with its neighbours in view.
     Honoured on the horizontal scroll of .board-scroll too, which is what stops
     the cell arriving flush against the pinned round column. */
  scroll-margin: 5rem 0 0 4rem;
  padding: 0.9rem 0.35rem 0.25rem;
  border-radius: 5px;
  background: var(--board-cell);
  vertical-align: top;
  overflow: hidden;
}

.own-col { box-shadow: inset 0 0 0 1px rgba(122, 200, 160, 0.35); }
thead th.own-col { color: #7ac8a0; box-shadow: none; }

/* Pick number, quiet in the corner. */
.pick-label {
  position: absolute;
  top: 0.2rem;
  left: 0.4rem;
  font-size: 0.62rem;
  font-weight: 700;
  color: #5a646f;
  letter-spacing: 0.02em;
}

/* Resolved cells: solid position colour, name first. --------------------- */

.cell.filled { color: #fff; }
.cell.filled .pick-label { color: rgba(255, 255, 255, 0.72); }

/* The name is the thing you read across a board of a hundred cells, so it gets
   the size. It can afford it because the grid prints "J. Chase" rather than
   "Ja'Marr Chase" -- see league/names.py. */
.filled-name {
  display: block;
  margin-top: 0.15rem;
  font-size: 0.95rem;
  font-weight: 700;
  line-height: 1.15;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Position and NFL team stay deliberately small and quiet: they are how you
   confirm a name you have already read, not what you scan for. */
.filled-sub {
  display: block;
  font-size: 0.63rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  opacity: 0.78;
}

/* Solid = fact (declared or locked). Desaturated = projection. */
.pos-bg-QB  { background: var(--qb); }
.pos-bg-RB  { background: var(--rb); }
.pos-bg-WR  { background: var(--wr); }
.pos-bg-TE  { background: var(--te); }
.pos-bg-K   { background: var(--k); }
.pos-bg-DEF { background: var(--def); }

.cell.projected.pos-bg-QB  { background: var(--qb-soft); }
.cell.projected.pos-bg-RB  { background: var(--rb-soft); }
.cell.projected.pos-bg-WR  { background: var(--wr-soft); }
.cell.projected.pos-bg-TE  { background: var(--te-soft); }
.cell.projected.pos-bg-K   { background: var(--k-soft); }
.cell.projected.pos-bg-DEF { background: var(--def-soft); }
.cell.projected { color: #cfd6dd; }
.cell.projected .filled-name { font-weight: 600; }

/* A projected cell has a player in it, so the "who could be kept here" list
   underneath it would be noise. Clearing the simulation brings it back --
   nothing is removed from the DOM, only hidden. */
.cell.projected .cands,
.cell.projected .more,
.cell.projected .more-count { display: none; }

/* The fill is appended after the cell's <details>, which carries the padding
   on its summary, so it pays for its own. */
.sim-fill { display: block; padding: 0 0.35rem 0.3rem; }

/* A pick I made myself in a mock draft. Full position colour, and the same
   solid ring a lock wears: on this board hue means position and the ring means
   certainty, and an explicit choice of mine is certain in a way an ADP guess
   never is. */
.cell.mine-pick {
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.9);
  color: #fff;
}

.cell.mine-pick .cands,
.cell.mine-pick .more,
.cell.mine-pick .more-count { display: none; }

/* A locked/declared call is louder than a projection: full-strength colour
   plus a ring, so the two never read the same at a glance. */
.cell.locked {
  box-shadow: inset 0 0 0 2px #fff, 0 0 0 1px rgba(0, 0, 0, 0.3);
}

.cell.own-col.locked { box-shadow: inset 0 0 0 2px #fff; }

/* "You called it" -- a small tick on a revealed keeper this user predicted.
   Deliberately quiet: it is a private footnote on a public board, not a score. */
.called-tick {
  position: absolute;
  bottom: 0.15rem;
  right: 0.3rem;         /* bottom corner: the top-right one is the trade badge */
  font-size: 0.7rem;
  color: rgba(255, 255, 255, 0.85);
}

/* Candidate names --------------------------------------------------------- */

.cell .cands { margin: 0; padding: 0; list-style: none; }

.cell .cand {
  display: flex;
  align-items: center;
  gap: 0.2rem;
  margin-bottom: 1px;
  padding: 0 0.25rem;
  border-radius: 2px;
  line-height: 1.35;
  font-size: 0.78rem;
  color: #fff;
  white-space: nowrap;
  overflow: hidden;
}

.cand-name { overflow: hidden; text-overflow: ellipsis; }
.cand-team { opacity: 0.7; font-size: 0.6rem; font-weight: 700; }
.cell .cand.pending { opacity: 0.5; }

.pending-tag {
  flex: 0 0 auto;
  font-weight: 700;
  cursor: help;
  opacity: 0.85;
}

.shift-mark {
  flex: 0 0 auto;
  font-size: 0.56rem;
  font-weight: 700;
  opacity: 0.85;
  cursor: help;
}

.cell .more { margin-top: 1px; }

.cell .more summary {
  cursor: pointer;
  font-size: 0.6rem;
  color: #6d7883;
  list-style: none;
  padding-left: 0.25rem;
}

.cell .more summary::-webkit-details-marker { display: none; }
.cell .more summary:hover { color: #a9b4bf; }

/* Traded ------------------------------------------------------------------ */

.cell .badge {
  position: absolute;
  top: 0.18rem;
  right: 0.3rem;
  padding: 0 0.25em;
  border-radius: 2px;
  background: rgba(224, 134, 64, 0.22);
  color: #e6a86b;
  font-size: 0.58rem;
  font-weight: 700;
}

.cell.filled .badge { background: rgba(0, 0, 0, 0.25); color: #fff; }

/* Sandbox burn highlight -- classes added and removed by board.js.
   The background comes from the same .pos-bg-* class every other filled cell
   uses, so a kept RB is RB-teal here exactly as it is anywhere else. What
   marks a burn as provisional is the RING, not the hue: dashed means "you are
   trying this, nothing is saved", against the solid ring of a locked call and
   the ringless desaturation of a projection. */
.cell.burned {
  color: #fff;
  outline: 2px dashed rgba(255, 255, 255, 0.92);
  outline-offset: -3px;
}
.cell.burned .pick-label { color: rgba(255, 255, 255, 0.8); }

/* Matched to .filled-name, near enough: a burned cell is a name in the grid
   like any other, and it reads at the same distance. */
.burn-tag {
  display: block;
  margin-top: 0.15rem;
  font-size: 0.9rem;
  font-weight: 700;
  line-height: 1.2;
  color: #fff;
  white-space: normal;
}

.burn-tag em {
  display: block;
  font-weight: 400;
  font-style: normal;
  font-size: 0.62rem;
  opacity: 0.85;
}

/* Prediction popover ------------------------------------------------------ */

.cell-pop { position: static; }

.cell-pop > summary {
  display: block;
  cursor: pointer;
  list-style: none;
  height: 100%;
}

.cell-pop > summary::-webkit-details-marker { display: none; }
.cell:has(.cell-pop) { padding: 0; }
.cell-pop > summary { padding: 0.9rem 0.35rem 0.25rem; }
.cell-pop[open] > summary { outline: 2px solid #7ac8a0; outline-offset: -2px; border-radius: 5px; }

/* The menu escapes the cell, which is why the cell does not clip it. */
.cell:has(.cell-pop[open]) { overflow: visible; z-index: 20; }

.pop-menu {
  position: absolute;
  top: calc(100% - 0.2rem);
  left: 0;
  z-index: 30;
  min-width: 13rem;
  padding: 0.4rem;
  border-radius: 6px;
  background: #12171c;
  border: 1px solid #39434e;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.45);
  text-align: left;
}

/* The menu hangs below its cell, and .board-scroll clips anything outside it.
   Absolutely-positioned content does not extend a scroll area, so on the last
   row the menu is not merely off-screen -- it cannot be scrolled to at all,
   which reads as "Round 8 cells don't respond to clicks". Flip it upward on the
   bottom two rows, and inward on the last two columns for the same reason. */
.board tbody tr:nth-last-child(-n + 2) .pop-menu {
  top: auto;
  bottom: calc(100% - 0.2rem);
}

.board tbody td:nth-last-child(-n + 2) .pop-menu {
  left: auto;
  right: 0;
}

.pop-head {
  margin: 0 0 0.3rem;
  padding: 0 0.2rem;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #74808d;
}

.pop-item {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  width: 100%;
  padding: 0.28rem 0.3rem;
  border: 0;
  border-radius: 4px;
  background: none;
  color: #dfe5ec;
  font: inherit;
  font-size: 0.72rem;
  text-align: left;
  cursor: pointer;
}

.pop-item:hover { background: #232c35; }

.pop-pos {
  flex: 0 0 auto;
  min-width: 2.1em;
  padding: 0 0.25em;
  border-radius: 2px;
  font-size: 0.6rem;
  font-weight: 700;
  text-align: center;
  color: #fff;
}

.pop-name { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pop-team { flex: 0 0 auto; font-size: 0.62rem; color: #8b97a4; font-weight: 700; }
.pop-cost { flex: 0 0 auto; font-size: 0.66rem; font-weight: 700; color: #a9b4bf; }

.pop-item.unlock { justify-content: center; color: #e08a8a; font-weight: 600; }
.pop-item.unlock:hover { background: #32222a; }

.more-count {
  display: block;
  padding-left: 0.25rem;
  font-size: 0.66rem;
  color: #6d7883;
}

/* A predicted cell is a call, not a fact: same colour, dashed ring. */
.cell.predicted.locked {
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.85);
}

.col-warn {
  display: inline-block;
  margin-left: 0.2rem;
  width: 1rem;
  height: 1rem;
  line-height: 1rem;
  border-radius: 50%;
  background: #b4462f;
  color: #fff;
  font-size: 0.68rem;
  font-weight: 700;
  text-align: center;
  cursor: help;
}

/* Legend ------------------------------------------------------------------ */

.board-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 0.9rem;
  align-items: center;
  margin: 0.6rem 0 0;
  font-size: 0.74rem;
  color: var(--muted);
}

.legend-key {
  display: inline-block;
  width: 0.8rem;
  height: 0.8rem;
  border-radius: 2px;
  vertical-align: -1px;
  margin-right: 0.25rem;
}

.legend-projected { background: var(--rb-soft); }

/* Same teal as a real RB cell, wearing the sandbox's dashed ring -- the key
   has to show the ring, since the ring is the whole distinction. */
.legend-trying {
  background: var(--rb);
  outline: 1.5px dashed #fff;
  outline-offset: -2px;
}

/* The simulator's assumptions, folded away until asked for. */
.sim-legend {
  margin: 0.5rem 0 0;
  font-size: 0.78rem;
  color: var(--muted);
}

.sim-legend summary { cursor: pointer; color: var(--accent); font-weight: 600; }
.sim-legend ul { margin: 0.4rem 0 0; padding-left: 1.1rem; }
.sim-legend li { margin: 0.15rem 0; }


/* Sandbox sidebar --------------------------------------------------------- */

.sandbox {
  flex: 0 0 18rem;
  position: sticky;
  top: 1rem;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 0.9rem 1rem 0.8rem;
}

.sandbox h2 { font-size: 0.95rem; margin: 0 0 0.1rem; }
.sandbox-list { list-style: none; margin: 0.7rem 0 0.6rem; padding: 0; }

.sandbox-list li {
  border-radius: 4px;
  margin-bottom: 0.1rem;
  font-size: 0.8rem;
}

.sandbox-list li.disabled { opacity: 0.4; }

.sandbox-list label {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.2rem 0.3rem;
  cursor: pointer;
}

.sandbox-list li.disabled label { cursor: default; }
.sandbox-list li:not(.disabled):hover { background: #f5f7f8; }

/* The swatch is invisible until picked, then takes that player's POSITION
   colour -- the same one his burned cell wears on the board. board.js adds the
   .pos-bg-* class; there is no separate sidebar palette to keep in sync. */
.swatch {
  flex: 0 0 auto;
  width: 0.55rem;
  height: 1.1rem;
  border-radius: 2px;
  background: transparent;
}

.sandbox-list li.picked { font-weight: 600; background: var(--picked-row); }

.sandbox-name {
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sandbox-cost {
  flex: 0 0 auto;
  font-weight: 700;
  font-size: 0.74rem;
  color: #4a535e;
}

.sandbox-cost.shifted { color: #8a6a2f; cursor: help; }

.kept-count {
  flex: 0 0 auto;
  font-size: 0.65rem;
  font-weight: 700;
  color: #7a5bbf;
  cursor: help;
}

.sandbox-result {
  border-top: 1px solid var(--line);
  padding-top: 0.55rem;
  font-size: 0.8rem;
}

.sandbox-result ul { margin: 0.25rem 0 0; padding-left: 1.05rem; }
.sandbox-result li { margin-bottom: 0.15rem; }
.sandbox-good { color: var(--accent); font-weight: 600; margin: 0; }
.sandbox-bad { color: #a12a2a; font-weight: 600; margin: 0; }
.sandbox-warn { color: #7a5b12; }

.sandbox .note { font-size: 0.72rem; margin: 0.6rem 0 0; }

/* Narrow screens that are still made to fit ten columns ------------------- */

/* The full-size type above assumes a column of about 100px, which is what a
   1400px-plus window gives (and what the phone rules below buy back by
   scrolling). In between, ten columns are still squeezed into whatever is
   left after the sandbox, and a column can fall to ~60px -- there, a bigger
   font would only move the ellipsis further left. So the type scales back to
   just above its old size: the abbreviation still buys real characters at
   every width, but only a wide board spends them on size as well.

   Deliberately type-only. The layout here is untouched: ten columns, no
   scrolling, exactly as before. */
@media (min-width: 701px) and (max-width: 1400px) {
  .filled-name { font-size: 0.85rem; }
  .burn-tag { font-size: 0.8rem; }
  .cell .cand { font-size: 0.7rem; }
  .cell { height: 4.7rem; }
}

/* Only shown on a phone, where the board no longer fits and swiping it
   sideways is not obvious from a grid whose left column never moves.
   Same for the fit toggle: above 700px all ten columns are there already. */
.board-hint { display: none; }
#fit-btn { display: none; }

@media (max-width: 860px) {
  .board-layout { flex-direction: column; }
  .board-scroll { max-height: none; width: 100%; }

  /* Board first, keeper list under it. Beside the board the list is a sidebar;
     stacked above it, it is sixteen rows of checkboxes between you and the
     thing you opened the page to look at.
     `order` rather than moving it in the template: the DOM keeps the order the
     desktop layout wants, and one flex property flips the stacked view.
     Applied at the stacking breakpoint, not the phone one, because a phone held
     sideways is ~844px wide -- still stacked, and just as annoying there.

     The sandbox's own verdict ("Legal set. Burns Round 3, 5") sits inside the
     list, so ticking a player still confirms itself without scrolling; the
     burned CELLS are what you scroll up for. */
  .board-scroll { order: 1; }
  .sandbox { flex: 1 1 auto; width: 100%; position: static; order: 2; }
}

/* Phones ------------------------------------------------------------------ */

/* Ten columns cannot fit across a phone at any size worth reading, so stop
   trying: give the columns a real minimum width and let the board scroll
   sideways under a pinned round column. Desktop is untouched -- all ten columns
   still fit there, with no scrolling. */
@media (max-width: 700px) {
  main.wide { padding-left: 0.6rem; padding-right: 0.6rem; }

  #fit-btn { display: inline-block; }

  .board-hint {
    display: block;
    margin: 0.8rem 0 -0.4rem;
    font-size: 0.78rem;
    color: var(--muted);
  }

  /* min-width, not width: the table still fills a wider phone. The ten is the
     league's ten teams, which the whole app treats as fixed.

     7.6rem a column is set by the widest thing a cell has to hold: a candidate
     row is name + NFL team side by side, and anything narrower truncates
     "A. St. Brown" to "A. St. Br...". Three-and-a-bit phone screens of board is
     the price, and scrolling a board you can read beats seeing all of one you
     cannot. */
  table.board {
    min-width: calc(2.6rem + 10 * 7.6rem);
    font-size: 0.8rem;
  }

  /* Which round you are looking at has to survive the sideways scroll -- with
     it gone, a cell in the middle of the board means nothing. The shadow is
     what shows the rest of the grid passing underneath. */
  th.round-head {
    width: 2.6rem;
    font-size: 0.85rem;
    box-shadow: 3px 0 6px rgba(0, 0, 0, 0.35);
  }

  /* Room for a bigger name and a comfortable tap. */
  .cell { height: 5.8rem; }
  .filled-name { font-size: 1rem; }
  .burn-tag { font-size: 0.95rem; }
  .cell .cand { font-size: 0.82rem; line-height: 1.45; }

  /* Every one of these is a finger target on this screen, and the desktop
     sizes are all well under the ~44px a thumb needs. */
  .pop-menu { min-width: 15rem; padding: 0.3rem; }

  .pop-item {
    min-height: 2.75rem;
    padding: 0.5rem 0.45rem;
    font-size: 0.85rem;
  }

  .pop-pos { font-size: 0.7rem; }
  .pop-name { font-size: 0.85rem; }

  .pick-row { min-height: 2.75rem; padding: 0.6rem 0.5rem; }
  .pick-name { font-size: 0.92rem; }

  .chip { min-height: 2.1rem; padding: 0.35rem 0.7rem; font-size: 0.78rem; }
  .board-btn { min-height: 2.75rem; padding: 0.5rem 1rem; font-size: 0.88rem; }
  .modal-close { min-width: 2.75rem; min-height: 2.75rem; }

  .probability-controls { grid-template-columns: 1fr; align-items: stretch; }
  .probability-targets,
  .probability-actions { grid-column: auto; grid-row: auto; }
  .probability-targets select { min-width: 0; width: 100%; }
  .probability-result-head { flex-wrap: wrap; }
  .probability-result-head p { flex-basis: 100%; }
  .probability-table-wrap { max-height: 70vh; }

  /* The sandbox tick is the smallest target on the page by some way. */
  .sandbox-list label { padding: 0.55rem 0.3rem; }
  .sandbox-list input[type="checkbox"] { width: 1.15rem; height: 1.15rem; }

  /* "Fit all 10 teams" -- the overview mode, toggled by board.js.
     Everything the scrolling view spends on legibility is handed back here:
     the minimum width, the type, the cell height, and the NFL team code beside
     each candidate. At ~32px a column no name survives anyway, and what this
     mode is actually for is shape -- which slots are spoken for, and by which
     position. Colour still carries that at any size. */
  .board-scroll.fit table.board { min-width: 0; width: 100%; }
  .board-scroll.fit .cell { height: 4rem; }
  .board-scroll.fit .filled-name { font-size: 0.62rem; }
  .board-scroll.fit .filled-sub { font-size: 0.5rem; }
  .board-scroll.fit .burn-tag { font-size: 0.58rem; }
  .board-scroll.fit .burn-tag em { font-size: 0.5rem; }
  .board-scroll.fit .cell .cand { font-size: 0.52rem; line-height: 1.3; }
  .board-scroll.fit .cand-team { display: none; }
  .board-scroll.fit .more-count { font-size: 0.5rem; }
  .board-scroll.fit .pick-label { font-size: 0.48rem; }
  .board-scroll.fit thead th { font-size: 0.52rem; padding: 0.3rem 0.15rem; }
  .board-scroll.fit .slot-num { font-size: 0.48rem; }

  /* Nothing scrolls sideways in this mode, so the pinned column has nothing to
     cast a shadow over. */
  .board-scroll.fit th.round-head {
    width: 1.7rem;
    font-size: 0.62rem;
    box-shadow: none;
  }

  /* "Swipe the board sideways" is a lie once it all fits. */
  body:has(.board-scroll.fit) .board-hint { display: none; }

  /* The mock-draft pick panel, as a sheet ---------------------------------- */

  /* On a wide screen the panel hangs off the cell being drafted, in absolute
     page coordinates. On a phone that was actively hostile: the panel sat over
     whatever you had scrolled to, and board.js re-placed it on every `resize`
     -- which a phone fires continuously while you scroll, as the URL bar slides
     in and out. The page could only come to rest where the panel wanted it.

     Pinned to the bottom of the viewport instead, there is nothing to place and
     nothing to fight: the board scrolls freely behind it, which is what the
     panel being non-modal was always for. board.js clears the inline top/left
     at this width (see isSheet) so this geometry is the only one in play. */
  .pick-panel {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    width: auto;
  }

  /* The tail points at a cell the sheet is no longer attached to. */
  .pick-panel::before { display: none; }

  .modal {
    /* Roughly half the screen: enough list to choose from, enough board above
       it to choose WITH. vh rather than dvh so the box does not resize as the
       URL bar comes and goes -- a sheet that changes height under your thumb
       is the same complaint in a smaller form. */
    max-height: 52vh;
    border-radius: 12px 12px 0 0;
    border-bottom: 0;
    box-shadow: 0 -12px 34px rgba(16, 20, 25, 0.32);
  }

  /* Dragging is off at this width (board.js), so stop advertising it. */
  .modal-head { cursor: default; }

  /* Room to scroll the last rounds out from behind the sheet. Only while a
     pick is open -- board.js puts this class on the body and takes it off. */
  body.picking { padding-bottom: 56vh; }
}


/* Printing / Save as PDF --------------------------------------------------- */

/* The rules page's "Save as PDF" button is just window.print(), so everything
   that makes the saved file worth keeping is here. Top level rather than inside
   the @media print block below: @page only ever applies to paper anyway, and
   nesting it is the less well-supported spelling. */
@page {
  margin: 18mm 16mm;
}

/* Right-aligned toolbar above a document. Its own rule rather than reusing
   .board-head, which is a two-column title/controls layout this has no title
   for. The button itself is the shared pill from the board. */
.doc-controls {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 0.6rem;
}

/* Draft-time poll --------------------------------------------------------- */

/* Text for screen readers only. Every answer in the grid is drawn as a glyph
   and a colour; this is the same fact in words, for anyone who is getting
   neither. Clipped rather than `display: none`, which would take it out of the
   accessibility tree along with everything else. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.poll-intro {
  max-width: 62ch;
  padding: 0.1rem 0.9rem;
  border-left: 3px solid var(--accent);
  background: var(--accent-soft);
  border-radius: 0 5px 5px 0;
}

.poll-closed {
  padding: 0.6rem 0.9rem;
  background: #fdf3e3;
  border: 1px solid #e6c88a;
  border-radius: 6px;
}

.poll-error {
  padding: 0.6rem 0.9rem;
  color: #7d1f1f;
  background: #fbeaea;
  border: 1px solid #e0a3a3;
  border-radius: 6px;
}

/* The grid scrolls sideways in its own box rather than widening the page:
   eight candidate times on a phone is wider than any screen. */
.poll-scroll {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--card);
}

.poll-table {
  border-collapse: collapse;
  width: 100%;
}

.poll-table th,
.poll-table td {
  padding: 0.45rem 0.55rem;
  border-bottom: 1px solid var(--line);
  text-align: center;
}

.poll-head {
  font-size: 0.8rem;
  font-weight: 600;
  line-height: 1.25;
  vertical-align: bottom;
  white-space: nowrap;
}

.poll-when { display: block; }
.poll-note { display: block; font-weight: 400; color: var(--muted); font-size: 0.75rem; }

/* The manager column is pinned, so a row still says whose it is once the grid
   has been scrolled sideways past its first few columns. */
.poll-corner,
.poll-owner {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--card);
  text-align: left;
  white-space: nowrap;
}

.poll-you {
  margin-left: 0.35rem;
  padding: 0.05rem 0.3rem;
  border-radius: 3px;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* Your own row, marked the same way the board marks your own column. */
.poll-row.own-row { background: var(--accent-soft); }
.poll-row.own-row .poll-owner { background: var(--accent-soft); }

/* The answers. Colour AND a glyph, never colour alone -- the glyphs are in the
   markup (see league.poll.GLYPHS), these only tint them. */
.poll-mark {
  display: inline-block;
  min-width: 1.6rem;
  padding: 0.1rem 0.3rem;
  border-radius: 4px;
  font-weight: 700;
}

.poll-mark.ans-yes   { background: #e2f3e8; color: #1c6b3d; }
.poll-mark.ans-maybe { background: #fbf0da; color: #8a6209; }
.poll-mark.ans-no    { background: #fbe6e6; color: #94272b; }
.poll-mark.ans-none  { color: var(--line); }

/* Your own cells: three buttons, one click each. */
.poll-choice {
  display: inline-flex;
  gap: 2px;
}

.poll-btn {
  min-width: 1.7rem;
  padding: 0.2rem 0.35rem;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--card);
  color: var(--muted);
  font: inherit;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
}

.poll-btn:hover { border-color: var(--muted); }
.poll-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.poll-btn.ans-yes.on   { background: #1c6b3d; border-color: #1c6b3d; color: #fff; }
.poll-btn.ans-maybe.on { background: #b07d10; border-color: #b07d10; color: #fff; }
.poll-btn.ans-no.on    { background: #94272b; border-color: #94272b; color: #fff; }

/* Totals. The best column(s) are highlighted, and every tie is highlighted --
   telling the commissioner there is one clear winner when there are three
   would be a lie in the one direction that matters. */
.poll-total th,
.poll-total td {
  border-top: 2px solid var(--line);
  border-bottom: 0;
  font-weight: 700;
}

.poll-total th { text-align: left; font-weight: 600; }
.poll-total.soft th,
.poll-total.soft td { border-top: 0; color: var(--muted); font-weight: 600; }

.poll-count.best { background: var(--accent-soft); color: var(--accent); }
.poll-head.best { background: var(--accent-soft); }

/* Bigger and darker than the usual .note it shares a class with: it is the
   only thing on the page that explains what clicking a cell does, and at the
   muted 0.9rem the rest of the site uses for asides it read as fine print. */
.poll-live {
  margin-top: 0.6rem;
  font-size: 1.05rem;
  color: var(--ink);
}

.poll-alt { margin-top: 2rem; }
.poll-alt h2 { font-size: 1.15rem; }


/* Rules vote -------------------------------------------------------------- */

/* On the rules page: there is a live ballot on the rules you are reading. */
.rules-vote-callout {
  margin: 0 0 1rem;
  padding: 0.6rem 0.9rem;
  border: 1px solid #e6c88a;
  border-radius: 6px;
  background: #fdf3e3;
}

/* .ballot-secrecy lived here, styling a hardcoded "secret now, public later"
   banner on the rules vote. The banner was removed -- the same wording is in the
   poll's editable intro -- so the rule went with it rather than sitting here
   matching nothing. rules_vote.html says why at the point it was removed. */

.proposal {
  margin: 1.6rem 0;
  padding: 1rem 1.1rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--card);
}

.proposal h2 { font-size: 1.2rem; margin: 0; }
.proposal h3 { font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); margin: 0 0 0.2rem; }
.proposal p { margin: 0.4rem 0; }
.proposal-ref { color: var(--muted); font-size: 0.9rem; margin-top: 0.15rem; }

/* Two columns where there is room, one where there is not. auto-fit with a
   minimum column width does that without a media query and without a breakpoint
   to keep in step with the board's -- the columns stack when they no longer
   fit, which is the actual condition. */
.proposal-texts,
.proposal-cases {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 0.9rem;
  margin: 0.9rem 0;
}

.proposal-text {
  padding: 0.6rem 0.8rem;
  border-radius: 6px;
  background: var(--accent-soft);
}

/* The proposed wording is the change, so it gets the outline. Same size type as
   the current wording -- this marks which is which, not which is better. */
.proposal-text.proposed { background: none; border: 1px dashed var(--accent); }

/* The two cases are visually identical on purpose. The commissioner wrote both
   and votes on the result; giving "for" the larger type would be a thumb on the
   scale nobody agreed to. */
.proposal-case { font-size: 0.95rem; }

.proposal-note {
  margin: 0.9rem 0;
  padding: 0.5rem 0.8rem;
  border-left: 3px solid var(--line);
  color: var(--muted);
  font-size: 0.92rem;
}

.ballot-choice {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
  margin: 1rem 0 0.4rem;
  padding: 0.5rem 0.8rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 6px;
}

.ballot-choice legend { padding: 0 0.3rem; font-weight: 600; font-size: 0.9rem; }

/* A real radio inside a clickable label, not a styled div: the browser gives us
   arrow-key movement within the group, and the label makes the whole pill a hit
   target. The checked state is drawn on the label AND left on the radio, so it
   survives with CSS off. */
.ballot-option {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.3rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  cursor: pointer;
}

.ballot-option:hover { border-color: var(--muted); }
.ballot-option.on { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); font-weight: 600; }
.ballot-option:focus-within { outline: 2px solid var(--accent); outline-offset: 1px; }

.ballot-turnout { color: var(--muted); font-size: 0.9rem; }

.ballot-results {
  margin-top: 1rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--line);
}

.ballot-tally { list-style: none; padding: 0; margin: 0.3rem 0; }
.ballot-tally li { margin-bottom: 0.2rem; }
.ballot-tally .subtle { margin-left: 0.4rem; font-size: 0.9rem; }
.ballot-outcome { margin-top: 0.5rem; }

.ballot-closing {
  margin: 1.6rem 0;
  padding: 0.7rem 1rem;
  border-left: 3px solid var(--accent);
  background: var(--accent-soft);
  border-radius: 0 5px 5px 0;
}

.ballot-note { margin-top: 2rem; }
.ballot-note h2 { font-size: 1.15rem; }
.ballot-note textarea { width: 100%; max-width: 46rem; font: inherit; padding: 0.5rem; border: 1px solid #c8cdd4; border-radius: 4px; }

.ballot-submit { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: center; margin-top: 1.2rem; }

@media print {
  /* Site furniture is navigation; on paper there is nowhere to navigate to.
     The button would print as an empty pill, which is worse than most.

     .messages is here because a flash message is a reply to something you just
     did -- "your ballot is saved" baked into a printed rulebook is a sentence
     that was true for one second in 2026.

     .rules-vote-callout for the same reason and a sharper one: a saved rulebook
     should not carry a link to a vote that closed months before whoever is
     holding it read it. */
  .site-header,
  footer,
  .messages,
  .rules-vote-callout,
  .doc-controls { display: none; }

  body {
    background: #fff;
    color: #000;
  }

  /* The page's own margins come from @page now, and the card's frame is screen
     decoration -- on paper the paper is the card. */
  main,
  main.wide {
    max-width: none;
    margin: 0;
    padding: 0;
  }

  .prose {
    background: none;
    border: 0;
    border-radius: 0;
    padding: 0;
  }

  /* Points, not rems: print is the one place a physical unit is the honest one,
     and 10.5pt body is what a rules doc should read at in the hand. */
  .prose { font-size: 10.5pt; line-height: 1.45; }
  .prose h1 { font-size: 19pt; margin-bottom: 0.4em; }
  .prose h2 { font-size: 13pt; margin-top: 16pt; }
  .prose h3 { font-size: 11.5pt; margin-top: 12pt; }
  .prose th, .prose td { font-size: 9.5pt; }

  /* A heading stranded at the foot of a page is the classic print bug: the
     rule it introduces is overleaf, so the page ends on a promise. */
  .prose h1,
  .prose h2,
  .prose h3 { break-after: avoid; page-break-after: avoid; }

  /* And these should not be split down the middle across a page break. */
  .prose li,
  .prose tr,
  .prose blockquote { break-inside: avoid; page-break-inside: avoid; }

  /* Section 6's draft order runs long enough to cross a page; repeat its header
     row there rather than leaving a column of bare numbers. */
  .prose thead { display: table-header-group; }

  /* Grey-on-white is a screen luxury: it prints weak, and these carry rules
     text. Ink is cheap and the emphasis is already in the markup. */
  .prose em,
  .prose blockquote { color: #000; }

  .prose blockquote { border-left-color: #666; }
  .prose th { background: none; border-bottom: 1px solid #000; }

  /* Underlined and black: a link's colour means nothing once it is printed. */
  a { color: #000; text-decoration: underline; }

  code {
    background: none;
    border: 1px solid #ccc;
  }
}

/* Login ------------------------------------------------------------------- */

.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 1.25rem;
}

.login-form { max-width: 22rem; margin-top: 1rem; }
.login-form p { margin: 0 0 0.9rem; }
.login-form label { display: block; font-weight: 600; font-size: 0.9rem; margin-bottom: 0.2rem; }

.login-form input {
  width: 100%;
  padding: 0.45rem 0.55rem;
  border: 1px solid #c8cdd4;
  border-radius: 4px;
  font: inherit;
}

button[type="submit"] {
  background: var(--accent);
  color: #fff;
  border: 0;
  border-radius: 4px;
  padding: 0.5rem 1.1rem;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

.helptext, .login-form ul { color: var(--muted); font-size: 0.85rem; }

footer {
  max-width: 900px;
  margin: 0 auto;
  padding: 0 1rem 2rem;
  color: var(--muted);
  font-size: 0.85rem;
}
