/* ==========================================================================
   Fantasy Draft Board — "DRAFT NIGHT" theme
   Stadium scoreboard + Friday-night lights + sticker draft board.

   Performance contract for the weak TV box (unchanged from the old theme):
     - no backdrop-filter, no filter: blur()/drop-shadow()
     - no CSS animations, no transitions at all (hover = plain colour swap)
     - no box-shadows anywhere; depth comes from 1-3px solid borders and, on a
       filled board cell, one static linear-gradient (same class of paint as
       the turf stripes on #windowBody — no blur, no compositing layer)
     - no background-attachment: fixed, no rAF/setInterval
     - exactly three static images (one photo, two flat SVGs) + 5 woff2 faces
   ========================================================================== */

/* ---------- tokens ---------- */
:root {
  /* POSITION COLOURS — hard client requirement.
     QB red / RB blue / WR green / TE orange / K pink / DST purple.
     Shades tuned so white bold text clears 4.5:1 (TE clears the 3:1
     large-text floor; a 4.5:1 orange stops reading as orange). */
  --pos-QB:  #CE3A2C;   /* red    4.9:1 on white text */
  --pos-RB:  #2F76B4;   /* blue   4.8:1 */
  --pos-WR:  #1E8449;   /* green  4.7:1 */
  --pos-TE:  #C1720F;   /* orange 3.7:1 — large bold text only */
  --pos-K:   #B84A80;   /* pink   4.9:1 */
  --pos-DST: #7A57B5;   /* purple 5.4:1 */

  /* stadium chrome */
  --navy-950: #08111d;
  --navy-900: #0e1b2e;
  --navy-800: #142a45;
  --navy-700: #1d3a5c;
  --navy-600: #2a5079;
  --navy-500: #37628f;
  --navy-line:#24405f;

  /* stadium lights */
  --gold:    #ffc42e;
  --gold-hi: #ffd75f;
  --gold-dk: #a8760a;

  --turf:    #1E8449;

  /* light surfaces */
  --card:       #ffffff;
  --card-alt:   #eef3f8;
  --ink:        #14202e;
  --ink-soft:   #566e88;
  --ink-onnavy: #a9c0da;

  --cell-line:  #c2ccd8;   /* 1px row line inside a lane */
  --cell-rule:  #a3b3c6;   /* 2px rule BETWEEN team columns */
  --cell-empty: #f1f5f9;
  --cell-lane:  #dfe8f2;   /* every other team column, so a stack reads as a lane */
  --current:    #ffc42e;
  --current-fill: #ffeeba; /* pale gold behind the pick that is on the clock */

  /* type */
  --disp: 'Bebas Neue', 'Arial Narrow', sans-serif;
  --text: 'Rubik', 'Segoe UI', sans-serif;
}

/* ---------- reset-ish ---------- */
* { box-sizing: border-box; }

[hidden] { display: none !important; }
.hidden  { display: none !important; }

html, body { height: 100%; }

body {
  margin: 0;
  padding: 8px;
  height: 100vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  font-family: var(--text);
  font-size: 13px;
  color: var(--ink);
  background-color: var(--navy-950);
}

/* Keyboard focus is visible everywhere — one gold ring, no glow. */
:focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 2px;
}

/* ---------- touch behaviour (people draft from iPads) ----------
   touch-action: manipulation drops the 300ms double-tap-zoom wait Safari
   otherwise sits through before it will admit a tap was a tap — which is half
   of why the app felt slow on a touchscreen. The transparent tap highlight
   stops iOS painting a grey slab over a position sticker, and user-select
   keeps a slightly long press from selecting the words "RESET DRAFT" instead
   of pressing the button. Text inputs keep selection: you have to be able to
   fix a typo in a team name. None of these paint anything — no shadow, no
   filter, no transition. */
.btn, .ptab, .prow, .pick-close, .exit-board, .pick-fab, .rlabel, .bcell, .ins-x {
  touch-action: manipulation;
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
  -webkit-user-select: none;
  user-select: none;
}
input, textarea {
  -webkit-user-select: text;
  user-select: text;
}

/* Shared display-type helper */
.disp { font-family: var(--disp); letter-spacing: 0.045em; text-transform: uppercase; }

/* football glyph used as the section marker */
.ficon {
  width: 1.15em;
  height: 1.15em;
  flex: 0 0 auto;
  fill: var(--gold);
}

/* ==========================================================================
   APP SHELL
   ========================================================================== */
#app {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  border: 2px solid var(--navy-line);
  border-radius: 12px;
  background: var(--navy-900);
  overflow: hidden;
}

/* --- scoreboard bar: dimmed stadium strip, gold rail underneath --- */
#titlebar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border-bottom: 3px solid var(--gold);
  color: #fff;
  background-color: var(--navy-900);
  background-image:
    linear-gradient(180deg, rgba(8,17,29,0.80) 0%, rgba(8,17,29,0.92) 100%),
    url('img/stadium-night.jpg');
  background-size: auto, cover;
  background-position: 0 0, center 42%;
  background-repeat: repeat, no-repeat;
}

/* white line-art helmet flanking the title */
#tbIcon {
  width: 30px;
  height: 30px;
  flex: 0 0 auto;
  background-image: url('img/helmet-white.svg');
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
}

#tbTitle {
  font-family: var(--disp);
  font-weight: 400;
  font-size: 27px;
  line-height: 1;
  letter-spacing: 0.045em;
  text-transform: uppercase;
  color: #fff;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 42%;
}

/* gold slanted rule between the league name and the date */
.tb-wedge {
  flex: 0 0 auto;
  width: 10px;
  height: 22px;
  background: var(--gold);
  transform: skewX(-16deg);
}

#tbDate {
  flex: 1 1 auto;
  min-width: 0;
  font-family: var(--text);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-onnavy);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

#tbButtons { flex: 0 0 auto; display: flex; gap: 6px; }

body.mode-setup .tb-draft-only { display: none; }

/* ---------- LAN sync light (server mode only — hidden on file://) ----------
   Two static states, no animation and no shadow: a green dot means the last
   poll or post reached the server, a red one means it did not and the app is
   running on its own copy until the link comes back. */
.sync-badge {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 9px 3px;
  font-family: var(--disp);
  font-size: 14px;
  line-height: 1;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--ink-onnavy);
  background: var(--navy-800);
  border: 1px solid var(--navy-line);
  border-radius: 6px;
}
.sync-badge .sync-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #7f8f9f;              /* not known yet */
}
.sync-badge.sync-live { color: #d2ecdb; }
.sync-badge.sync-live .sync-dot { background: #35c46a; }
.sync-badge.sync-down { color: #ffd0c8; background: #4a1a15; border-color: #8e2b1f; }
.sync-badge.sync-down .sync-dot { background: #e0483a; }

/* Display Mode hides the title bar, so app.js moves the badge to <body> and it
   becomes a corner tab. pointer-events:none — it is a light, not a control. */
body.display-mode .sync-badge {
  position: fixed;
  top: 0;
  right: 0;
  z-index: 60;
  font-size: 12px;
  padding: 3px 8px 2px;
  border-width: 0 0 1px 1px;
  border-radius: 0 0 0 6px;
  pointer-events: none;
}
/* the pick overlay owns that corner (its Close button lives there) */
body.display-mode.pick-open .sync-badge { display: none; }

/* ---------- DRAFT PIN light ----------
   Every change to the board needs the PIN now, so a device is either a screen
   that can draft or a screen that can only watch — and which one it is has to
   be visible before somebody discovers it mid-pick. Two static states, no
   animation, no shadow: grey padlock + LOCKED until this device has had a write
   accepted, gold + UNLOCKED afterwards. It is a light, not a control, so it
   takes no pointer events and never appears on the TV (Display Mode hides the
   whole title bar, and the big screen has nothing to say about it). */
.auth-lock {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 9px 3px;
  font-family: var(--disp);
  font-size: 14px;
  line-height: 1;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  white-space: nowrap;
  color: #8ba0b6;
  background: var(--navy-800);
  border: 1px solid var(--navy-line);
  border-radius: 6px;
  pointer-events: none;
}
.auth-lock .lockicon {
  width: 11px;
  height: 13px;
  flex: 0 0 auto;
  fill: #8ba0b6;
}
.auth-lock.auth-ok { color: var(--gold); border-color: var(--gold-dk); }
.auth-lock.auth-ok .lockicon { fill: var(--gold); }

/* ==========================================================================
   CHUNKY ARCADE BUTTONS
   ========================================================================== */
.btn {
  font-family: var(--disp);
  font-weight: 400;
  font-size: 17px;
  line-height: 1;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 8px 15px 7px;
  color: #fff;
  background: var(--navy-600);
  border: 0;
  border-bottom: 3px solid var(--navy-800);
  border-radius: 8px;
  cursor: pointer;
}
.btn:hover  { background: var(--navy-500); }
.btn:active { transform: translateY(1px); }

.btn:disabled,
.btn:disabled:hover,
.btn:disabled:active {
  color: #6d829b;
  background: #1a2c42;
  border-bottom-color: #122133;
  cursor: default;
  transform: none;
}

/* the one gold action in the scoreboard bar */
#btnDisplay {
  color: var(--navy-950);
  background: var(--gold);
  border-bottom-color: var(--gold-dk);
}
#btnDisplay:hover { background: var(--gold-hi); }

/* gold confirm button inside the PIN dialog */
.btn-gold {
  color: var(--navy-950);
  background: var(--gold);
  border-bottom-color: var(--gold-dk);
}
.btn-gold:hover { background: var(--gold-hi); }

/* big primary action (START DRAFT) */
.btn-default {
  font-size: 30px;
  padding: 12px 42px 10px;
  letter-spacing: 0.06em;
  color: var(--navy-950);
  background: var(--gold);
  border-bottom: 5px solid var(--gold-dk);
  border-radius: 10px;
}
.btn-default:hover { background: var(--gold-hi); }

/* ==========================================================================
   WINDOW BODY — the "field" behind every panel
   ========================================================================== */
#windowBody {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  padding: 10px;
  /* draft view: static turf stripes behind the panels */
  background-color: #0c2318;
  background-image: repeating-linear-gradient(
    90deg,
    rgba(30,132,73,0.22) 0 74px,
    rgba(8,17,29,0.55)  74px 148px
  );
}

/* setup view: the whole body area becomes the night-game stadium */
body.mode-setup #windowBody {
  background-color: var(--navy-950);
  background-image:
    linear-gradient(180deg, rgba(9,20,36,0.70) 0%, rgba(9,20,36,0.90) 100%),
    url('img/stadium-night.jpg');
  background-size: auto, cover;
  background-position: 0 0, center top;
  background-repeat: repeat, no-repeat;
}

/* ---------- light cards ---------- */
.panel {
  border: 2px solid var(--navy-line);
  border-radius: 10px;
  background: var(--card);
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}
.panel-head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px 6px;
  font-family: var(--disp);
  font-weight: 400;
  font-size: 19px;
  line-height: 1;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: #fff;
  background: var(--navy-800);
  border-bottom: 3px solid var(--gold);
}
.panel-body { flex: 1 1 auto; min-height: 0; padding: 14px; }

/* ---------- inputs ---------- */
.txt {
  font-family: var(--text);
  font-size: 14px;
  font-weight: 500;
  padding: 8px 10px;
  color: var(--ink);
  background: #fff;
  border: 2px solid #b8c6d4;
  border-bottom-width: 3px;
  border-radius: 6px;
  width: 100%;
}
.txt::placeholder { color: var(--ink-soft); }
.txt:focus {
  border-color: var(--gold-dk);
  background: #fffdf4;
  outline: none;
}
.txt.num { width: 92px; }

input[type="radio"] { accent-color: var(--gold-dk); width: 16px; height: 16px; }

/* ==========================================================================
   SETUP SCREEN — stadium hero + clean light cards
   ========================================================================== */
/* transparent: the stadium photo lives on #windowBody so it never repaints
   while this container scrolls */
#setupScreen {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
}

.setup-wrap {
  max-width: 920px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding-bottom: 8px;
}

/* --- hero --- */
.hero {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 22px;
  padding: 26px 10px 22px;
  text-align: center;
}
.hero-helmet {
  width: 88px;
  height: 88px;
  flex: 0 0 auto;
  opacity: 0.85;
}
.hero-helmet-r { transform: scaleX(-1); }

.hero-text { min-width: 0; }

.hero-title {
  margin: 0;
  font-family: var(--disp);
  font-weight: 400;
  font-size: clamp(46px, 6.2vw, 92px);
  line-height: 0.94;
  letter-spacing: 0.055em;
  text-transform: uppercase;
  color: #fff;
}
.hero-rule {
  display: block;
  width: 128px;
  height: 6px;
  margin: 12px auto 10px;
  background: var(--gold);
  transform: skewX(-16deg);
}
.hero-sub {
  margin: 0;
  font-family: var(--text);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: #d3e0ee;
}

/* --- form grid --- */
.setup-grid {
  display: grid;
  grid-template-columns: 190px 1fr;
  gap: 12px 16px;
  align-items: center;
}
.setup-grid > label {
  font-family: var(--text);
  font-weight: 700;
  font-size: 11.5px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--navy-700);
}
.hint { font-size: 11.5px; color: var(--ink-soft); }

.radio-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.rlabel {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 14px 5px;
  font-family: var(--disp);
  font-size: 17px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--navy-800);
  background: var(--card-alt);
  border: 2px solid #c7d4e1;
  border-bottom-width: 3px;
  border-radius: 8px;
  cursor: pointer;
}
.rlabel:hover { background: #e2eaf3; }

/* --- team names --- */
.team-name-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(224px, 1fr));
  gap: 9px 14px;
}
.team-name-row { display: flex; align-items: center; gap: 8px; }
.team-name-row .tn-num {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--disp);
  font-size: 16px;
  letter-spacing: 0.02em;
  color: var(--gold);
  background: var(--navy-800);
  border-radius: 6px;
}

.setup-actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding: 6px 0 18px;
}
.setup-note {
  font-family: var(--text);
  font-size: 13px;
  font-weight: 600;
  color: #ffd0c8;
  background: #8e2b1f;
  border-radius: 6px;
  padding: 6px 10px;
}
.setup-note:empty { display: none; }

/* ==========================================================================
   DRAFT SCREEN
   ========================================================================== */
#draftScreen {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* ---------- ON THE CLOCK — broadcast lower third ---------- */
#clockBanner {
  position: relative;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 9px 16px 8px 34px;
  overflow: hidden;
  color: #fff;
  background: var(--navy-800);
  border: 2px solid var(--navy-line);
  border-bottom: 4px solid var(--gold);
  border-radius: 10px;
}
/* static gold wedge — the lower-third slash */
#clockBanner::before {
  content: '';
  position: absolute;
  left: -12px;
  top: -4px;
  bottom: -4px;
  width: 26px;
  background: var(--gold);
  transform: skewX(-14deg);
  z-index: 0;
}

.clock-block { position: relative; z-index: 1; min-width: 0; }
.clock-team-block { flex: 1 1 46%; }
.clock-pick-block {
  flex: 0 0 auto;
  text-align: center;
  padding: 2px 18px;
  border-left: 2px solid var(--navy-600);
  border-right: 2px solid var(--navy-600);
}
.clock-last-block { flex: 1 1 34%; }

.clock-label {
  font-family: var(--disp);
  font-size: 14px;
  line-height: 1;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold);
}
.clock-team {
  font-family: var(--disp);
  font-weight: 400;
  font-size: 34px;
  line-height: 1.02;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #fff;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.clock-pick {
  font-family: var(--disp);
  font-size: 30px;
  line-height: 1.02;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #fff;
  white-space: nowrap;
}
.clock-sub {
  font-family: var(--text);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-onnavy);
  white-space: nowrap;
}
.clock-last {
  font-family: var(--text);
  font-size: 14px;
  font-weight: 500;
  color: #e4edf6;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.display-hint { display: none; }

/* ---------- draft complete ---------- */
#completeBanner {
  position: relative;
  flex: 0 0 auto;
  padding: 12px 18px 11px;
  overflow: hidden;
  color: var(--navy-950);
  background: var(--gold);
  border: 2px solid var(--gold-dk);
  border-bottom: 4px solid var(--navy-800);
  border-radius: 10px;
}
/* helmet watermark in the empty right corner */
#completeBanner::after {
  content: '';
  position: absolute;
  right: 14px;
  top: -8px;
  width: 92px;
  height: 92px;
  opacity: 0.16;
  background-image: url('img/helmet.svg');
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
  z-index: 0;
}
.cb-title {
  position: relative;
  z-index: 1;
  font-family: var(--disp);
  font-size: 34px;
  line-height: 1.02;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.cb-sub {
  position: relative;
  z-index: 1;
  font-family: var(--text);
  font-size: 13px;
  font-weight: 500;
  color: #4a3806;
}

/* ---------- main split ---------- */
#draftMain {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  gap: 10px;
}

/* ==========================================================================
   THE BOARD — physical sticker board
   ========================================================================== */
#boardWrap {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
  overflow: auto;
  border: 2px solid var(--navy-line);
  border-radius: 10px;
  background: var(--cell-empty);
}

#boardGrid {
  display: grid;
  height: 100%;
  /* grid-template-columns / grid-template-rows are set inline by app.js.
     Row 1 is the team-name header; every later (implicit) row is a round.
     minmax(min, 1fr) makes rounds share the height evenly but never squash
     below a legible minimum — past that the wrapper simply scrolls. */
  grid-auto-rows: minmax(2.9em, 1fr);
  font-size: clamp(10px, 0.72vw, 15px);

  /* THE TWO NUMBERS THAT DECIDE WHETHER A FULL NAME FITS.
     Both are fractions of the board font size, so they scale with every
     .cols-N step and with the --fit height cap below.

     Display mode overrides them (see BOARD TYPE SCALE). The normal-mode
     values are larger because that board is only ~half the window wide —
     the commissioner's cells are narrower in px, so the em share is bigger
     to keep the working view readable; the longest names ellipsize there
     and the cell tooltip carries the full text. */
  --name-size: 0.80em;
  --meta-size: 0.62em;
}

.bcell {
  min-width: 0;
  overflow: hidden;
  border-right: 2px solid var(--cell-rule);   /* the lane divider */
  border-bottom: 1px solid var(--cell-line);
  /* Horizontal padding is width the name cannot use, so it is as small as a
     sticker can look with: 0.2em is ~4px at the 12-team display size. */
  padding: 0.16em 0.2em;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* header row (team names) — the lane's nameplate: taller than a round row,
   alternating navy so each header sits over its own column tint, one gold
   rail across the whole board underneath */
.bhead {
  position: sticky;
  top: 0;
  z-index: 2;
  text-align: center;
  font-family: var(--disp);
  font-weight: 400;
  font-size: 1.08em;
  /* 1.1 is the most two lines can take and still clear the 2.9em row:
     2 x 1.1 x 1.08em = 2.38em, plus 0.32em padding and the gold rail. */
  line-height: 1.1;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: #fff;
  background: var(--navy-800);
  border-right: 2px solid var(--navy-600);
  border-bottom: 3px solid var(--gold);
}
.bhead[data-lane="1"] { background: var(--navy-700); }
/* Team names are typed by hand and run long ("Gridiron Gladiators"), and the
   header row is 2.9em tall — so it takes two lines before it gives up and
   ellipsizes, which fits nearly every real one whole. */
.bhead-t {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  overflow-wrap: break-word;
}
/* the RD corner is the scoreboard's own tab */
.bcorner {
  z-index: 3;
  font-size: 1.0em;
  color: var(--navy-950);
  background: var(--gold);
  border-right-color: var(--gold-dk);
}

/* round label column — just the numeral, set big enough to read from the far
   side of the room (the corner tab above it says what the column is) */
.rdlabel {
  text-align: center;
  font-family: var(--disp);
  font-weight: 400;
  font-size: 1.55em;
  line-height: 1;
  letter-spacing: 0.02em;
  color: var(--gold);
  background: var(--navy-800);
  border-right: 2px solid var(--gold-dk);
  border-bottom-color: var(--navy-700);
  white-space: nowrap;
}

/* empty pick cell — light, gridded, waiting for a sticker. Alternate columns
   carry a slightly deeper tint so every team's picks read as one vertical
   lane even before a single sticker lands in it. */
.pick { position: relative; background: var(--cell-empty); cursor: pointer; }
.pick:not(.filled)[data-lane="1"] { background: var(--cell-lane); }

/* ---------- every cell is a tap target ----------
   An empty cell opens the picker aimed at THAT slot; a filled one offers to
   take the player back off. The empty cell has to say so without shouting on
   a 75" screen, so the affordance is one small "+" in the corner — a
   pseudo-element, so it costs the board no extra nodes and clearCell() does
   not have to build one — and it only exists where it means something:

     coarse pointer   always (an iPad has no hover to discover it with)
     fine pointer     on hover only

   The slot number is untouched: it is the wayfinding mark and it stays put in
   the middle of the cell either way. position: relative on the cell is what
   the corner is measured from; it paints nothing. */
.pick:not(.filled)::after {
  content: '+';
  display: none;
  position: absolute;
  top: 0;
  right: 0.14em;
  font-family: var(--disp);
  font-size: 0.9em;
  line-height: 1;
  color: #9fb0c2;              /* one step lighter than .slotnum: a hint, not a label */
}
@media (pointer: coarse) {
  .pick:not(.filled)::after { display: block; }
}
@media (hover: hover) and (pointer: fine) {
  .pick:not(.filled):hover::after { display: block; }
  /* warm, but deliberately NOT --current-fill: the on-the-clock cell is the
     only thing on this board allowed to be that colour */
  .pick:not(.filled):hover { background: #fff8e3; }
}

.slotnum {
  text-align: center;
  font-family: var(--disp);
  font-size: 0.95em;
  letter-spacing: 0.05em;
  /* 2.73:1 on --cell-empty (#f1f5f9), 2.57:1 on the lane tint: subdued enough
     to stay background, dark enough to read across a room. Deliberately below
     the 4.5:1 text floor — these are wayfinding marks on an empty cell, not
     content. */
  color: #8697a9;
}

/* filled pick cell — chunky sticker: solid position colour, white bold text,
   2px darker border of the same hue (rgba black over the fill) with a darker
   bottom edge for thickness, slight radius */
.pick.filled {
  color: #fff;
  border: 2px solid rgba(0,0,0,0.30);
  border-bottom-color: rgba(0,0,0,0.45);
  border-radius: 4px;
  /* One flat gradient — not a shadow, not a filter — so a sticker reads as a
     physical chip rather than a painted rectangle. It is weighted DOWN
     (transparent to 55%, then a touch of black) so it can only raise the white
     text's contrast, never lower it: the name line sits in the clear half and
     the meta line lands on the darker end. The .pos-* fills below therefore
     set background-COLOR, so this image survives them. */
  background-image: linear-gradient(180deg,
      rgba(255,255,255,0.05) 0%,
      rgba(255,255,255,0)   32%,
      rgba(0,0,0,0)         55%,
      rgba(0,0,0,0.12)     100%);
}
.pname {
  font-family: var(--text);
  /* 600, not 700: it measures ~2% narrower for the same colour on screen at
     TV distance, and 2% of a cell is most of a character. */
  font-weight: 600;
  font-size: var(--name-size);
  line-height: 1.12;
  letter-spacing: -0.025em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;      /* backstop only — app.js shortens first */
}
.pmeta {
  font-family: var(--text);
  font-weight: 600;
  font-size: var(--meta-size);
  line-height: 1.18;
  letter-spacing: 0.04em;
  color: rgba(255,255,255,0.92);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* current pick — thick gold outline plus a pale gold fill, inset so nothing
   clips (no glow, no animation). The :not(.filled) keeps it ahead of the lane
   tint, which is also a two-class selector. */
.pick.current {
  outline: 3px solid var(--current);
  outline-offset: -3px;
}
.pick.current:not(.filled) { background: var(--current-fill); }
.pick.current .slotnum {
  font-size: 1.15em;
  color: var(--gold-dk);
}

/* the cell an armed insert is aimed at — gold DASHED, so it cannot be mistaken
   for the solid gold on-the-clock outline even when it is the same cell.
   Declared after .pick.current on purpose: same specificity, later wins. */
.pick.insert-target {
  outline: 3px dashed var(--gold);
  outline-offset: -3px;
}
/* three classes, so it beats the lane tint (.pick:not(.filled)[data-lane="1"]) */
.pick.insert-target:not(.filled) { background: #fff8e3; }
.pick.insert-target .slotnum { color: var(--gold-dk); }
body.display-mode .pick.insert-target { outline-width: 4px; outline-offset: -4px; }

/* position fills — board cells AND pool badges.
   background-COLOR, not the shorthand: a filled board cell layers its sticker
   gradient on top of whichever of these it wears. */
.pos-QB  { background-color: var(--pos-QB); }
.pos-RB  { background-color: var(--pos-RB); }
.pos-WR  { background-color: var(--pos-WR); }
.pos-TE  { background-color: var(--pos-TE); }
.pos-K   { background-color: var(--pos-K); }
.pos-DST { background-color: var(--pos-DST); }

/* ==========================================================================
   PLAYER POOL SIDEBAR
   ========================================================================== */
#sidebar {
  flex: 0 0 348px;
  min-width: 0;
  min-height: 0;
  display: flex;
}
.side-panel { flex: 1 1 auto; min-height: 0; }
.side-body {
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-height: 0;
  background: var(--card-alt);
}

/* live count reads as a scoreboard chip */
#poolCount {
  margin-left: auto;
  padding: 3px 9px 1px;
  font-family: var(--disp);
  font-size: 17px;
  line-height: 1;
  letter-spacing: 0.04em;
  color: var(--navy-950);
  background: var(--gold);
  border-radius: 5px;
}

.search { flex: 0 0 auto; }

/* ---------- INSERT MODE strip ----------
   While a board cell is armed, the pool stops meaning "the next pick" and
   starts meaning "that cell". That is a big enough change of meaning that it
   gets a gold bar of its own directly above the search box, in the docked
   sidebar and in the overlay alike, with the way out on the right. Flat gold
   on navy — no shadow, no animation, nothing that moves. */
.insert-strip {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 6px 5px 10px;
  color: var(--navy-950);
  background: var(--gold);
  border-bottom: 3px solid var(--gold-dk);
  border-radius: 7px;
}
.ins-text {
  flex: 1 1 auto;
  min-width: 0;
  font-family: var(--disp);
  font-size: 16px;
  line-height: 1.05;
  letter-spacing: 0.045em;
  text-transform: uppercase;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ins-x {
  flex: 0 0 auto;
  min-width: 30px;
  font-family: var(--text);
  font-size: 15px;
  font-weight: 700;
  line-height: 1;
  padding: 7px 9px;
  color: var(--gold);
  background: var(--navy-900);
  border: 0;
  border-bottom: 3px solid var(--navy-950);
  border-radius: 6px;
  cursor: pointer;
}
.ins-x:hover { background: var(--navy-700); }
body.display-mode.pick-open .ins-text { font-size: 19px; }

/* --- position tabs: each one wears its own position colour when active --- */
.pos-tabs { flex: 0 0 auto; display: flex; gap: 3px; }
.ptab {
  flex: 1 1 auto;
  font-family: var(--disp);
  font-weight: 400;
  font-size: 15px;
  line-height: 1;
  letter-spacing: 0.05em;
  padding: 7px 0 5px;
  color: var(--navy-800);
  background: #dfe7f0;
  border: 0;
  border-bottom: 3px solid #bccadb;
  border-radius: 6px;
  cursor: pointer;
}
.ptab:hover { background: #cfdbe8; }
.ptab.active { color: #fff; border-bottom-color: rgba(0,0,0,0.32); }
.ptab.active:hover { color: #fff; }

.ptab[data-pos="ALL"].active     { color: var(--navy-950); background: var(--gold);   border-bottom-color: var(--gold-dk); }
.ptab[data-pos="ALL"].active:hover { color: var(--navy-950); background: var(--gold-hi); }
.ptab[data-pos="QB"].active,  .ptab[data-pos="QB"].active:hover  { background: var(--pos-QB); }
.ptab[data-pos="RB"].active,  .ptab[data-pos="RB"].active:hover  { background: var(--pos-RB); }
.ptab[data-pos="WR"].active,  .ptab[data-pos="WR"].active:hover  { background: var(--pos-WR); }
.ptab[data-pos="TE"].active,  .ptab[data-pos="TE"].active:hover  { background: var(--pos-TE); }
.ptab[data-pos="K"].active,   .ptab[data-pos="K"].active:hover   { background: var(--pos-K); }
.ptab[data-pos="DST"].active, .ptab[data-pos="DST"].active:hover { background: var(--pos-DST); }

/* --- column headings --- */
.pool-head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 8px 4px;
  font-family: var(--text);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.11em;
  color: var(--ink-onnavy);
  background: var(--navy-700);
  border-radius: 5px 5px 0 0;
}
.pool-head .c-rk { flex: 0 0 30px; }
.pool-head .c-bd { flex: 0 0 34px; }
.pool-head .c-nm { flex: 1 1 auto; }
.pool-head .c-pj { flex: 0 0 38px; text-align: right; }
.pool-head .c-ad { flex: 0 0 34px; text-align: right; }

#playerListWrap {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  border: 2px solid var(--navy-700);
  border-top: 0;
  border-radius: 0 0 6px 6px;
  background: #fff;
}
#playerList { display: block; }

#noResults {
  padding: 22px 10px;
  text-align: center;
  font-family: var(--text);
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-soft);
}

.prow {
  display: flex;
  align-items: center;
  gap: 6px;
  height: 36px;
  padding: 0 6px;
  border-bottom: 1px solid #e4eaf1;
  cursor: pointer;
  /* keeps 350 rows cheap to lay out on a weak GPU; ignored by older engines */
  content-visibility: auto;
  contain-intrinsic-size: 0 36px;
}
.prow:hover { background-color: #fff2cf; }

.p-rk {
  flex: 0 0 30px;
  text-align: right;
  font-family: var(--disp);
  font-size: 16px;
  line-height: 1;
  letter-spacing: 0.02em;
  color: var(--ink-soft);
}
/* chunky position chip — same six colours as the board */
.p-bd {
  flex: 0 0 34px;
  text-align: center;
  font-family: var(--disp);
  font-size: 14px;
  line-height: 1;
  letter-spacing: 0.05em;
  color: #fff;
  padding: 5px 0 3px;
  border-radius: 5px;
  border-bottom: 2px solid rgba(0,0,0,0.28);
}
.p-info { flex: 1 1 auto; min-width: 0; }
.p-nm {
  font-family: var(--text);
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.2;
}
.p-sub {
  font-family: var(--text);
  font-size: 10.5px;
  font-weight: 400;
  color: var(--ink-soft);
  line-height: 1.25;
}
.p-inj {
  display: inline-block;
  margin-left: 5px;
  padding: 0 4px;
  font-size: 9.5px;
  font-weight: 700;
  color: #fff;
  background: var(--pos-QB);
  border-radius: 3px;
  vertical-align: 1px;
}
.p-pj {
  flex: 0 0 38px;
  text-align: right;
  font-family: var(--text);
  font-size: 12px;
  font-weight: 700;
  color: var(--navy-700);
}
.p-ad {
  flex: 0 0 34px;
  text-align: right;
  font-family: var(--text);
  font-size: 11px;
  color: var(--ink-soft);
}

.pool-foot {
  flex: 0 0 auto;
  font-family: var(--text);
  font-size: 10.5px;
  font-weight: 500;
  color: var(--navy-700);
  text-align: center;
}

/* ==========================================================================
   DISPLAY MODE (TV) — board + clock only, sized to read across the room
   ========================================================================== */
body.display-mode { padding: 0; }
body.display-mode #app { border: 0; border-radius: 0; }
body.display-mode #titlebar { display: none; }
body.display-mode #windowBody { padding: 7px; }
body.display-mode #sidebar { display: none; }
body.display-mode #boardWrap { border-radius: 0; border-width: 3px; }
body.display-mode #draftScreen { gap: 7px; }
body.display-mode #clockBanner,
body.display-mode #completeBanner { border-radius: 0; }

body.display-mode #clockBanner { padding: 12px 20px 10px 46px; }
body.display-mode #clockBanner::before { left: -16px; width: 34px; }

body.display-mode .clock-label { font-size: clamp(13px, 1.05vw, 24px); }
body.display-mode .clock-team  { font-size: clamp(30px, 4.0vw, 92px); }
body.display-mode .clock-pick  { font-size: clamp(24px, 2.7vw, 60px); }
body.display-mode .clock-sub   { font-size: clamp(11px, 0.85vw, 20px); }
body.display-mode .clock-last  { font-size: clamp(14px, 1.35vw, 30px); }
body.display-mode .cb-title    { font-size: clamp(34px, 4.0vw, 88px); }
body.display-mode .cb-sub      { font-size: clamp(13px, 1.2vw, 26px); }
body.display-mode #completeBanner::after { width: 150px; height: 150px; top: -14px; right: 24px; }

body.display-mode .display-hint {
  display: block;
  position: absolute;
  right: 12px;
  bottom: 4px;
  font-family: var(--text);
  font-size: 11px;
  font-weight: 500;
  color: #7794b4;
}
body.display-mode #completeBanner .display-hint { color: #5c4805; }

/* ---------------------------------------------------------------------------
   BOARD TYPE SCALE — width AND height, both have to be satisfied

   NAMES FIRST. The client watches this from across a 75" room and asked for
   whole names, not "C. McCaffrey", so the name line is sized from the widest
   string the pool can produce rather than from what looks comfortable in a
   screenshot. Measured in Chrome with the shipped Rubik 600 face, the widest
   board texts in players.js are:

       Anthony Richardson Sr.  11.55em    Rhamondre Stevenson  11.13em
       Jacory Croskey-Merritt  11.52em    TreVeyon Henderson   10.10em

   at -0.025em tracking that worst case is 11.55 - 22 x 0.025 = 11.0em of name
   line. A display-mode cell gives the name

       (1901px board - 2.3em round column) / teams - 4px sticker border
                                                   - 0.4em cell padding

   so at 1920x1080 the name line can be 0.645em of the board font and still
   clear the worst name by 4-8% at every team count from 8 to 14:

       teams   board font   name px   text px   widest name   margin
         8       27.8px      17.96     214.5      196.9        8.2%
         9       25.3px      16.35     190.6      179.3        6.3%
        10       23.0px      14.86     171.6      163.0        5.3%
        11       21.1px      13.62     156.0      149.4        4.4%
        12       19.2px      12.38     143.0      135.8        5.3%
        13       17.9px      11.52     131.9      122.7        7.5%   (a)
        14       16.5px      10.65     122.5      113.4        8.0%   (a)

   (a) 13-14 teams shorten the two 22-character names — see NAME_LIMITS in
       app.js — so their widest is "Rhamondre Stevenson" at 10.65em.

   Everything else on the sticker gives way to that: the meta line drops to
   0.56em (it is "RB · DET", a label the colour already half-tells you), the
   cell padding drops to 0.16em/0.2em, and the round column is a numeral in
   2.3em rather than "RD 12" in 4.8em.

   WIDTH   the .cols-N steps below: an 8-team board would look stretched at a
           14-team size, a 14-team board would clip its columns at an 8-team
           size. These are the numbers the theme was tuned with, unchanged —
           the name fit above is what moved.

   HEIGHT  a board is (rounds + 1 header) rows tall. The width rule alone made
           the font *bigger* when there were fewer teams, which made rows
           taller, which pushed the bottom rounds off the screen: at 1920x1080
           8 teams x 15 rounds hid 167px (rounds 13-15), 8 x 20 hid 514px and
           12 x 20 hid 61px. Team count was never the whole story.

   --fit is the height answer. app.js writes --fit-rows (= rounds + 1, the
   header included) onto #boardGrid, and:

     usable height = 100vh - 176px of display-mode chrome, made of
        14px   #windowBody padding (7px top + 7px bottom)
       135px   the taller of the two banners — draft-complete is
               78px title + 27px sub + 23px padding + 6px border
               (on-the-clock measures ~127px, so this is the safe one)
         7px   #draftScreen gap
         6px   #boardWrap borders (3px top + 3px bottom)
        14px   slack, so a rounding error can't produce a scrollbar

     row height = usable height / --fit-rows

     font-size  = row height / 2.25, because a filled cell now stacks
        0.645em x 1.12 line-height (name)  = 0.722em
      + 0.560em x 1.18 line-height (meta)  = 0.661em
      + 0.160em x 2 (cell padding)         = 0.320em
                                    total  = 1.703em + 4px border.

     The divisor moved 2.75 -> 2.25 because that stack shrank from 2.346em:
     shrinking the type must not COST vertical room, and holding 2.75 would
     have thrown the reclaimed height away (a 20-round board would have run
     11px names when 15px fit). The check is that a round row still ends up
     taller than its own contents, header included:

       row  = (904 - 2.9em header x F) / rounds        F = 904/(rounds+1)/2.25
       need = 1.703em x F + 4px

       rounds   F        row      need     headroom
         20    19.1px   42.4px   36.6px     16%
         15    24.6px   53.9px   45.9px     17%
         10    27.8px*  82.3px   51.4px     60%     * width rule wins here
     versus 6% headroom on the old 2.75/2.346 pair at 20 rounds. Both the type
     and the fit got safer.

   Worst cases at 1920x1080, font-size = min(width rule, --fit):
      8 x 20  --fit 19.1px vs width 27.8px -> 19.1px, 21 rows            fits
     14 x 20  --fit 19.1px vs width 16.5px -> 16.5px (width)             fits
      8 x 15  --fit 24.6px vs width 27.8px -> 24.6px                     fits
      8 x 10  --fit 36.5px vs width 27.8px -> width wins                 fits
     12 x 15  --fit 24.6px vs width 19.2px -> width wins                 fits
   i.e. the height cap still only engages on the combinations that would
   otherwise overflow; every board that already fitted keeps its width size.

   grid-auto-rows: minmax(0, 1fr) is the backstop. Rounds divide whatever
   height actually exists rather than demanding a 2.5em minimum, so the board
   cannot overflow even if the 176px chrome estimate is off on some panel —
   the worst case is slightly tighter cells, never a hidden round.

   There is deliberately no lower bound on the font size here (the old
   clamp() floor was itself a cause of the overflow). Normal, non-display mode
   is untouched and may still scroll.
   ------------------------------------------------------------------------- */
body.display-mode #boardGrid {
  --fit: calc((100vh - 176px) / var(--fit-rows, 21) / 2.25);
  grid-auto-rows: minmax(0, 1fr);
  /* the TV's share of the board font: names win, the meta line gives way */
  --name-size: 0.645em;
  --meta-size: 0.56em;
}
/* a little more weight on the gold rail and the on-the-clock outline at TV size */
body.display-mode .bhead { border-bottom-width: 4px; }
body.display-mode .pick.current { outline-width: 4px; outline-offset: -4px; }
body.display-mode #boardGrid.cols-8  { font-size: min(1.45vw, 32px, var(--fit)); }
body.display-mode #boardGrid.cols-9  { font-size: min(1.32vw, 30px, var(--fit)); }
body.display-mode #boardGrid.cols-10 { font-size: min(1.20vw, 28px, var(--fit)); }
body.display-mode #boardGrid.cols-11 { font-size: min(1.10vw, 26px, var(--fit)); }
body.display-mode #boardGrid.cols-12 { font-size: min(1.00vw, 24px, var(--fit)); }
body.display-mode #boardGrid.cols-13 { font-size: min(0.93vw, 22px, var(--fit)); }
body.display-mode #boardGrid.cols-14 { font-size: min(0.86vw, 21px, var(--fit)); }

/* ---------------------------------------------------------------------------
   DISPLAY-MODE PICK OVERLAY — the sidebar, promoted to a fixed panel

   position: fixed takes it out of #draftMain's flex flow, so opening it does
   NOT resize #boardWrap and the grid is never re-laid-out. Solid background,
   no transition, no blur: it is there or it is not.
   ------------------------------------------------------------------------- */
/* Two doors into the same overlay, and never both at once: .pick-btn rides in
   the clock banner in Display Mode, .pick-fab is the fixed tablet button that
   the NARROW SCREENS block below switches on under 1100px. */
.pick-btn { display: none; }
.pick-fab { display: none; }

body.display-mode .pick-btn {
  display: block;
  position: relative;
  z-index: 1;
  flex: 0 0 auto;
  align-self: center;
  font-size: clamp(17px, 1.25vw, 28px);
  padding: 11px 22px 9px;
  color: var(--navy-950);
  background: var(--gold);
  border-bottom: 4px solid var(--gold-dk);
}
body.display-mode .pick-btn:hover { background: var(--gold-hi); }

body.display-mode.pick-open #sidebar {
  display: flex;
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: 400px;
  max-width: 42vw;
  z-index: 40;
  padding: 8px;
  background: var(--navy-900);
  border-left: 5px solid var(--gold);
}
/* the panel head and search grow a little for TV distance; the 350 rows are
   left exactly as they are so showing the overlay costs no restyle */
body.display-mode.pick-open #sidebar .panel-head { font-size: 22px; }
body.display-mode.pick-open #sidebar .search { font-size: 17px; }
body.display-mode.pick-open #sidebar .pool-foot { font-size: 12px; }

/* A full-height right panel sits over the right end of the clock banner, which
   is where the "Pick a Player" toggle lives — so the way out has to be inside
   the overlay too, not just Esc / "/" / drafting someone.

   The look is defined once here and only the display switch is scoped, because
   the same overlay is now also how a tablet picks (see NARROW SCREENS). */
.pick-close {
  display: none;
  margin-left: 10px;
  font-family: var(--disp);
  font-size: 17px;
  line-height: 1;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 6px 13px 4px;
  color: var(--navy-950);
  background: var(--card-alt);
  border: 0;
  border-bottom: 3px solid #9fb1c4;
  border-radius: 6px;
  cursor: pointer;
}
.pick-close:hover { background: #fff; }
body.display-mode.pick-open .pick-close { display: block; }

/* ==========================================================================
   EXIT BOARD — the way out of Display Mode for someone who has never heard
   of the D key.

   Display Mode hides the entire title bar, which is the whole point of it, and
   that left the room with no visible way back: the field report was a person
   standing in front of the TV with no idea how to leave. One small fixed tab,
   bottom-left, where it clears both banners and the pick overlay. It is fixed,
   so it costs the board no height and the 8-14 x 10-20 fit contract is
   untouched. D and Esc still work.
   ========================================================================== */
.exit-board { display: none; }
body.display-mode .exit-board {
  display: block;
  position: fixed;
  left: calc(8px + env(safe-area-inset-left, 0px));
  bottom: calc(8px + env(safe-area-inset-bottom, 0px));
  z-index: 55;
  font-family: var(--disp);
  font-weight: 400;
  font-size: 16px;
  line-height: 1;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 8px 14px 6px;
  color: var(--gold);
  background: var(--navy-900);
  border: 2px solid var(--gold);
  border-radius: 7px;
  cursor: pointer;
}
body.display-mode .exit-board:hover {
  color: var(--navy-950);
  background: var(--gold);
}

/* ==========================================================================
   PIN DIALOG — every write, server-enforced
   Plain solid scrim: no blur, no transition, no shadow. It is up or it is not.
   ========================================================================== */
.modal-back {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 90;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 18px;
  background: rgba(6, 13, 22, 0.86);
}
.modal {
  width: 100%;
  max-width: 400px;
  border: 2px solid var(--navy-line);
  border-radius: 10px;
  background: var(--card);
  overflow: hidden;
}
.modal-head {
  padding: 9px 14px 7px;
  font-family: var(--disp);
  font-weight: 400;
  font-size: 21px;
  line-height: 1;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: #fff;
  background: var(--navy-800);
  border-bottom: 3px solid var(--gold);
}
.modal-body { padding: 14px; }
.modal-msg {
  margin: 0 0 11px;
  font-family: var(--text);
  font-size: 13.5px;
  font-weight: 500;
  line-height: 1.38;
  color: var(--ink);
}
.modal-msg:empty { display: none; }
.pin-input {
  font-family: var(--disp);
  font-size: 30px;
  line-height: 1;
  letter-spacing: 0.3em;
  text-indent: 0.3em;          /* re-centres text that letter-spacing pushed left */
  text-align: center;
  padding: 10px 10px 8px;
}
.modal-err {
  margin: 10px 0 0;
  font-family: var(--text);
  font-size: 12.5px;
  font-weight: 700;
  color: #8e2b1f;
}
.modal-err:empty { display: none; }
.modal-foot {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 0 14px 14px;
}

/* ==========================================================================
   NARROW SCREENS — iPads and half-width windows, under 1100px

   Adding the device-width viewport meta is what made this necessary: before it
   an iPad laid the page out at 980 CSS px and scaled it down, and now it lays
   out at its real 810 (portrait) or 1024 (landscape). At those widths the
   348px docked sidebar leaves the board about 430px, which is not a board.

   So under 1100px the sidebar undocks and the SAME #sidebar node becomes a
   full-screen overlay — exactly the mechanism Display Mode already used, which
   is why this costs no second player list and no second code path. The board
   gets the whole width, and a fixed gold PICK A PLAYER button is the way in.

   Nothing here may overflow horizontally: the board's columns are
   minmax(0, 1fr) so they divide whatever width exists, the title bar wraps to
   two rows rather than pushing New Draft off the edge, and every long string
   in the banner already ellipsizes. Vertical scrolling in normal mode is
   unchanged and still allowed. Display Mode is untouched at every width — its
   own rules come later in the file and win.
   ========================================================================== */
@media (max-width: 1099px) {
  /* two rows beats a clipped row: five controls in Bebas do not fit beside a
     league name at 810px, and the date is the one thing here that is decoration */
  #titlebar { flex-wrap: wrap; row-gap: 6px; padding: 7px 9px; }
  #tbTitle { font-size: 22px; max-width: calc(100% - 130px); }
  #tbDate { display: none; }
  #tbButtons { flex: 1 1 100%; justify-content: flex-end; flex-wrap: wrap; }

  /* --- the board takes the width --- */
  body:not(.display-mode) #sidebar { display: none; }
  body:not(.display-mode) #boardGrid {
    /* a floor of 10px and 1.5vw: 12.2px at 810, 15px from 1000 up. Long names
       ellipsize at these widths — the position colour and the POS · TEAM line
       still read, and the picking happens in the overlay, not on the board. */
    font-size: clamp(10px, 1.5vw, 15px);
    grid-auto-rows: minmax(2.5em, 1fr);
    --name-size: 0.74em;
    --meta-size: 0.58em;
  }
  body:not(.display-mode) #clockBanner { gap: 10px; padding: 8px 12px 7px 26px; }
  body:not(.display-mode) #clockBanner::before { left: -10px; width: 20px; }
  body:not(.display-mode) .clock-team { font-size: 26px; }
  body:not(.display-mode) .clock-pick { font-size: 22px; }
  body:not(.display-mode) .clock-sub  { font-size: 10.5px; }
  body:not(.display-mode) .clock-last { font-size: 12.5px; }
  body:not(.display-mode) .clock-pick-block { padding: 2px 10px; }
  body:not(.display-mode) .cb-title { font-size: 26px; }

  /* --- the pool, as a full-screen overlay --- */
  body:not(.display-mode).pick-open #sidebar {
    display: flex;
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 40;
    flex: 1 1 auto;
    width: auto;
    max-width: none;
    padding: calc(6px + env(safe-area-inset-top, 0px))
             calc(6px + env(safe-area-inset-right, 0px))
             calc(6px + env(safe-area-inset-bottom, 0px))
             calc(6px + env(safe-area-inset-left, 0px));
    background: var(--navy-900);
  }
  body:not(.display-mode).pick-open .pick-close { display: block; }
  body:not(.display-mode).pick-open #sidebar .panel-head { font-size: 21px; }

  /* the way IN: fixed, thumb-sized, and the only gold thing on the screen */
  body:not(.display-mode):not(.mode-setup) .pick-fab {
    display: block;
    position: fixed;
    right: calc(14px + env(safe-area-inset-right, 0px));
    bottom: calc(14px + env(safe-area-inset-bottom, 0px));
    z-index: 45;
    font-size: 23px;
    min-height: 58px;
    padding: 15px 24px 13px;
    color: var(--navy-950);
    background: var(--gold);
    border-bottom: 4px solid var(--gold-dk);
    border-radius: 10px;
  }
  body:not(.display-mode):not(.mode-setup) .pick-fab:hover { background: var(--gold-hi); }
  /* while the overlay is up its own Close button is the control that matters
     (the selector has to out-specify the one above, hence the repeated :not) */
  body:not(.display-mode):not(.mode-setup).pick-open .pick-fab { display: none; }
}

/* narrow windows: drop the second helmet before it crowds the title */
@media (max-width: 760px) {
  .hero { gap: 14px; }
  .hero-helmet-r { display: none; }
  .hero-helmet { width: 62px; height: 62px; }
  .setup-grid { grid-template-columns: 1fr; gap: 6px; }
}

/* ==========================================================================
   COARSE POINTERS — finger targets

   A 36px row and a 30px button are fine under a mouse and a coin toss under a
   thumb. Anything that gets pressed goes to at least 44px here. Desktop is
   untouched: this whole block only matches a touchscreen.
   ========================================================================== */
@media (pointer: coarse) {
  .btn { min-height: 44px; padding: 11px 16px 9px; }
  .btn-default { min-height: 64px; }
  .ptab { min-height: 44px; font-size: 17px; }
  .pick-close { min-height: 44px; }
  .exit-board, .pick-fab { min-height: 48px; }
  /* the insert bar's ✕ is the one way out of insert mode on a tablet */
  .ins-x { min-height: 44px; min-width: 44px; font-size: 17px; }
  .ins-text { font-size: 18px; }

  /* Board cells are the newest tap target and the biggest: a 14x20 board at
     810px still gives ~55x40px per cell, and the round rows divide whatever
     height is going, so this floor only ever bites on a short board — where
     there is room for it. Display Mode is exempt: its whole contract is that
     every round fits without scrolling, and a min-height would break that. */
  body:not(.display-mode) #boardGrid { grid-auto-rows: minmax(44px, 1fr); }

  /* content-visibility needs contain-intrinsic-size to match the real row
     height, or the scrollbar jumps as rows come into view */
  .prow { height: 52px; contain-intrinsic-size: 0 52px; }
  .p-nm { font-size: 15px; }
  .p-sub { font-size: 12px; }
  .p-rk { font-size: 18px; }
  .p-bd { padding: 7px 0 5px; font-size: 15px; }

  /* 16px is the threshold under which iOS Safari zooms the page in when a
     field takes focus — which would blow the layout apart mid-draft */
  .txt { font-size: 16px; padding: 10px 12px; }
  .txt.num { width: 104px; }
  .team-name-row .tn-num { width: 34px; height: 34px; font-size: 17px; }
  .rlabel { min-height: 44px; }
}

/* ==========================================================================
   SCROLLBARS
   ========================================================================== */
::-webkit-scrollbar { width: 14px; height: 14px; }
::-webkit-scrollbar-track { background: var(--navy-900); }
::-webkit-scrollbar-thumb {
  background: var(--navy-600);
  border: 3px solid var(--navy-900);
  border-radius: 7px;
}
::-webkit-scrollbar-thumb:hover { background: var(--gold); }
::-webkit-scrollbar-corner { background: var(--navy-900); }

/* light panels get a light-on-light bar so it does not punch a hole */
#boardWrap::-webkit-scrollbar-track,
#playerListWrap::-webkit-scrollbar-track { background: #dde5ee; }
#boardWrap::-webkit-scrollbar-thumb,
#playerListWrap::-webkit-scrollbar-thumb { background: #8298b1; border-color: #dde5ee; }
#boardWrap::-webkit-scrollbar-thumb:hover,
#playerListWrap::-webkit-scrollbar-thumb:hover { background: var(--gold-dk); }
#boardWrap::-webkit-scrollbar-corner,
#playerListWrap::-webkit-scrollbar-corner { background: #dde5ee; }
